diff --git a/ghost/admin/app/modifiers/autofocus.js b/ghost/admin/app/modifiers/autofocus.js index 2309202b09..2d5c8d55a0 100644 --- a/ghost/admin/app/modifiers/autofocus.js +++ b/ghost/admin/app/modifiers/autofocus.js @@ -1,3 +1,3 @@ import {modifier} from 'ember-modifier'; -export default modifier(element => element.focus()); +export default modifier(element => element.focus(), {eager: false}); diff --git a/ghost/admin/app/modifiers/movable.js b/ghost/admin/app/modifiers/movable.js index af6d2cf2bb..cc503be35e 100644 --- a/ghost/admin/app/modifiers/movable.js +++ b/ghost/admin/app/modifiers/movable.js @@ -1,6 +1,7 @@ import Modifier from 'ember-modifier'; import {action} from '@ember/object'; import {guidFor} from '@ember/object/internals'; +import {registerDestructor} from '@ember/destroyable'; import {inject as service} from '@ember/service'; export default class MovableModifier extends Modifier { @@ -16,53 +17,63 @@ export default class MovableModifier extends Modifier { xOffset = 0; yOffset = 0; + constructor(owner, args) { + super(owner, args); + registerDestructor(this, this.cleanup); + } + // Lifecycle hooks --------------------------------------------------------- - didInstall() { - this.addStartEventListeners(); + modify(element, positional, named) { + if (!this.didSetup) { + this.elem = element; + this.addStartEventListeners(); - if (this.args.named.adjustOnResize) { - this._resizeObserver = new ResizeObserver(() => { - if (this.currentX === undefined || this.currentY === undefined) { - return; - } + if (named.adjustOnResize) { + this._resizeObserver = new ResizeObserver(() => { + if (this.currentX === undefined || this.currentY === undefined) { + return; + } - const {x, y} = this.args.named.adjustOnResize(this.element, {x: this.currentX, y: this.currentY}); + const {x, y} = named.adjustOnResize(element, {x: this.currentX, y: this.currentY}); - if (x === this.currentX && y === this.currentY) { - return; - } + if (x === this.currentX && y === this.currentY) { + return; + } - this.currentX = x; - this.initialX = x; - this.xOffset = x; + this.currentX = x; + this.initialX = x; + this.xOffset = x; - this.currentY = y; - this.initialY = y; - this.yOffset = y; + this.currentY = y; + this.initialY = y; + this.yOffset = y; - this.setTranslate(x, y); - }); - this._resizeObserver.observe(this.element); + this.setTranslate(x, y); + }); + this._resizeObserver.observe(element); + } + + this.didSetup = true; } } - willDestroy() { + cleanup = () => { this.removeEventListeners(); this.removeResizeObserver(); this.enableSelection(); - } + }; // Custom methods ----------------------------------------------------------- addStartEventListeners() { - this.element.addEventListener('touchstart', this.dragStart, false); - this.element.addEventListener('mousedown', this.dragStart, false); + this.elem.addEventListener('touchstart', this.dragStart, false); + this.elem.addEventListener('mousedown', this.dragStart, false); } removeStartEventListeners() { - this.element.removeEventListener('touchstart', this.dragStart, false); - this.element.removeEventListener('mousedown', this.dragStart, false); + this.elem.removeEventListener('touchstart', this.dragStart, false); + this.elem.removeEventListener('mousedown', this.dragStart, false); } addActiveEventListeners() { @@ -111,7 +122,7 @@ export default class MovableModifier extends Modifier { break; } - if (elem === this.element) { + if (elem === this.elem) { this.addActiveEventListeners(); break; } @@ -183,16 +194,16 @@ export default class MovableModifier extends Modifier { } setTranslate(xPos, yPos) { - this.element.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`; + this.elem.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`; } disableScroll() { - this.originalOverflow = this.element.style.overflow; - this.element.style.overflow = 'hidden'; + this.originalOverflow = this.elem.style.overflow; + this.elem.style.overflow = 'hidden'; } enableScroll() { - this.element.style.overflow = this.originalOverflow; + this.elem.style.overflow = this.originalOverflow; } disableSelection() { @@ -215,12 +226,12 @@ export default class MovableModifier extends Modifier { // preventing clicks stops any event handlers that may otherwise result in the // movable element being closed when the drag finishes disablePointerEvents() { - this.element.style.pointerEvents = 'none'; + this.elem.style.pointerEvents = 'none'; window.addEventListener('click', this.cancelClick, {capture: true, passive: false}); } enablePointerEvents() { - this.element.style.pointerEvents = ''; + this.elem.style.pointerEvents = ''; window.removeEventListener('click', this.cancelClick, {capture: true, passive: false}); } } diff --git a/ghost/admin/app/modifiers/on-resize.js b/ghost/admin/app/modifiers/on-resize.js index 6f3cdbe0f0..0cd333179c 100644 --- a/ghost/admin/app/modifiers/on-resize.js +++ b/ghost/admin/app/modifiers/on-resize.js @@ -1,14 +1,27 @@ import Modifier from 'ember-modifier'; +import {registerDestructor} from '@ember/destroyable'; import {inject as service} from '@ember/service'; export default class MovableModifier extends Modifier { @service resizeDetector; - didInstall() { - this.resizeDetector.setup(this.element, this.args.positional[0]); + constructor(owner, args) { + super(owner, args); + registerDestructor(this, this.cleanup); } - willDestroy() { - this.resizeDetector.teardown(this.element, this.args.positional[0]); + modify(element, [callback]) { + if (!this.didSetup) { + this.elem = element; + this.callback = callback; + + this.resizeDetector.setup(element, callback); + + this.didSetup = true; + } } + + cleanup = () => { + this.resizeDetector.teardown(this.elem, this.callback); + }; } diff --git a/ghost/admin/app/modifiers/on-scroll.js b/ghost/admin/app/modifiers/on-scroll.js index 99e6bbe870..4a9efbe459 100644 --- a/ghost/admin/app/modifiers/on-scroll.js +++ b/ghost/admin/app/modifiers/on-scroll.js @@ -1,23 +1,31 @@ import Modifier from 'ember-modifier'; import {action} from '@ember/object'; +import {registerDestructor} from '@ember/destroyable'; export default class OnScrollModifier extends Modifier { - @action - onScroll(event) { - this.args.positional[0](this.element, this.scrollContainer, event); + constructor(owner, args) { + super(owner, args); + registerDestructor(this, this.cleanup); } - didInstall() { - this.scrollContainer = this.element; + modify(element, [callback], named) { + this.elem = element; + this.callback = callback; + this.scrollContainer = element; - if (this.args.named.scrollContainer) { - this.scrollContainer = this.element.closest(this.args.named.scrollContainer); + if (named.scrollContainer) { + this.scrollContainer = element.closest(named.scrollContainer); } this.scrollContainer?.addEventListener('scroll', this.onScroll, {passive: true}); } - willDestroy() { + cleanup = () => { this.scrollContainer?.removeEventListener('scroll', this.onScroll, {passive: true}); + }; + + @action + onScroll(event) { + this.callback(this.elem, this.scrollContainer, event); } } diff --git a/ghost/admin/app/modifiers/ratio-zoom.js b/ghost/admin/app/modifiers/ratio-zoom.js index 712df7e4ef..92dd1639da 100644 --- a/ghost/admin/app/modifiers/ratio-zoom.js +++ b/ghost/admin/app/modifiers/ratio-zoom.js @@ -1,28 +1,30 @@ import Modifier from 'ember-modifier'; import {bind, throttle} from '@ember/runloop'; +import {registerDestructor} from '@ember/destroyable'; export default class RatioZoom extends Modifier { resizeHandler = null; - didReceiveArguments() { - const {zoomed} = this.args.named; + constructor(owner, args) { + super(owner, args); + registerDestructor(this, this.cleanup); + } + modify(element, positional, {zoomed, ratio}) { if (zoomed) { - this.setZoomedSize(); + this.setZoomedSize(element, {ratio}); } } - willDestroy() { + cleanup = () => { this.removeResizeEventListener(); - } + }; - setZoomedSize() { - const {ratio} = this.args.named; + setZoomedSize(element, {ratio}) { + element.style.width = '100%'; + element.style.height = '100%'; - this.element.style.width = '100%'; - this.element.style.height = '100%'; - - const offsets = this.element.getBoundingClientRect(); + const offsets = element.getBoundingClientRect(); let maxHeight = { width: offsets.height / ratio, @@ -42,8 +44,8 @@ export default class RatioZoom extends Modifier { usableSize = maxHeight.width > offsets.width ? maxWidth : maxHeight; } - this.element.style.width = `${usableSize.width}px`; - this.element.style.height = `${usableSize.height}px`; + element.style.width = `${usableSize.width}px`; + element.style.height = `${usableSize.height}px`; this.addResizeEventListener(); } diff --git a/ghost/admin/app/modifiers/react-render.js b/ghost/admin/app/modifiers/react-render.js index e13809f8c1..1d0911627b 100644 --- a/ghost/admin/app/modifiers/react-render.js +++ b/ghost/admin/app/modifiers/react-render.js @@ -2,6 +2,7 @@ import Modifier from 'ember-modifier'; import React from 'react'; import ReactDOM from 'react-dom'; import {createRoot} from 'react-dom/client'; +import {registerDestructor} from '@ember/destroyable'; // make globals available for any pulled in UMD components // - avoids external components needing to bundle React and running into multiple version errors @@ -9,21 +10,28 @@ window.React = React; window.ReactDOM = ReactDOM; export default class ReactRenderModifier extends Modifier { - didInstall() { - const [reactComponent] = this.args.positional; - const props = this.args.named; - - if (!this.root) { - this.root = createRoot(this.element); - } - this.root.render(React.createElement(reactComponent, {...props})); + constructor(owner, args) { + super(owner, args); + registerDestructor(this, this.cleanup); } - willDestroy() { + modify(element, [reactComponent], {props}) { + if (!this.didSetup) { + if (!this.root) { + this.root = createRoot(element); + } + + this.root.render(React.createElement(reactComponent, {...props})); + + this.didSetup = true; + } + } + + cleanup = () => { if (!this.root) { return; } this.root.unmount(); - } + }; } diff --git a/ghost/admin/app/modifiers/scroll-into-view.js b/ghost/admin/app/modifiers/scroll-into-view.js index 7ca3fbbeba..81f88795c1 100644 --- a/ghost/admin/app/modifiers/scroll-into-view.js +++ b/ghost/admin/app/modifiers/scroll-into-view.js @@ -51,4 +51,4 @@ export default modifier((element, [shouldScroll = true], {offset = 0, useViewpor } } } -}); +}, {eager: false}); diff --git a/ghost/admin/app/modifiers/scroll-to.js b/ghost/admin/app/modifiers/scroll-to.js index 8e30bbd445..9d16af8147 100644 --- a/ghost/admin/app/modifiers/scroll-to.js +++ b/ghost/admin/app/modifiers/scroll-to.js @@ -10,4 +10,4 @@ export default modifier((element, positional, {shouldScroll = true}) => { scrollParent.scrollTo({top: y, behavior: 'smooth'}); }, 200); } -}); +}, {eager: false}); diff --git a/ghost/admin/app/modifiers/scroll-top.js b/ghost/admin/app/modifiers/scroll-top.js index 00f5e9f24f..809d9f9872 100644 --- a/ghost/admin/app/modifiers/scroll-top.js +++ b/ghost/admin/app/modifiers/scroll-top.js @@ -3,4 +3,4 @@ import {modifier} from 'ember-modifier'; export default modifier((element) => { getScrollParent(element).scrollTop = 0; -}); +}, {eager: false}); diff --git a/ghost/admin/package.json b/ghost/admin/package.json index 39eaa67a29..df637124a3 100644 --- a/ghost/admin/package.json +++ b/ghost/admin/package.json @@ -169,7 +169,8 @@ ] }, "resolutions": { - "ember-basic-dropdown": "4.0.5" + "ember-basic-dropdown": "4.0.5", + "ember-in-viewport": "4.0.2" }, "ember": { "edition": "octane" diff --git a/ghost/admin/yarn.lock b/ghost/admin/yarn.lock index 14f1e444dd..9a228d9227 100644 --- a/ghost/admin/yarn.lock +++ b/ghost/admin/yarn.lock @@ -6454,7 +6454,7 @@ ember-auto-import@2.4.2, ember-auto-import@^2.2.3: typescript-memoize "^1.0.0-alpha.3" walk-sync "^3.0.0" -ember-auto-import@^1.11.2, ember-auto-import@^1.11.3, ember-auto-import@^1.12.0: +ember-auto-import@^1.11.3, ember-auto-import@^1.12.0: version "1.12.2" resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-1.12.2.tgz#cc7298ee5c0654b0249267de68fb27a2861c3579" integrity sha512-gLqML2k77AuUiXxWNon1FSzuG1DV7PEPpCLCU5aJvf6fdL6rmFfElsZRh+8ELEB/qP9dT+LHjNEunVzd2dYc8A== @@ -7165,7 +7165,7 @@ ember-cli@3.24.0: workerpool "^6.0.3" yam "^1.0.0" -ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-compatibility-helpers@^1.2.1, ember-compatibility-helpers@^1.2.4, ember-compatibility-helpers@^1.2.5: +ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-compatibility-helpers@^1.2.1, ember-compatibility-helpers@^1.2.5: version "1.2.6" resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.6.tgz#603579ab2fb14be567ef944da3fc2d355f779cd8" integrity sha512-2UBUa5SAuPg8/kRVaiOfTwlXdeVweal1zdNPibwItrhR0IvPrXpaqwJDlEZnWKEoB+h33V0JIfiWleSG6hGkkA== @@ -7405,7 +7405,7 @@ ember-in-element-polyfill@^1.0.1: ember-cli-htmlbars "^5.3.1" ember-cli-version-checker "^5.1.2" -ember-in-viewport@4.0.2: +ember-in-viewport@4.0.2, ember-in-viewport@~3.10.2: version "4.0.2" resolved "https://registry.yarnpkg.com/ember-in-viewport/-/ember-in-viewport-4.0.2.tgz#09243f6921cc0b62d7ea0d399e349466a45b26f3" integrity sha512-Uor/fSk53/wASJDpnXEP6RQFeEIjC5uGt64I7tjtr6aPT/jLRg0SKKRuImqUbbsHHoBDWUbkxzryexTda6LhCA== @@ -7417,18 +7417,6 @@ ember-in-viewport@4.0.2: intersection-observer-admin "~0.3.2" raf-pool "~0.1.4" -ember-in-viewport@~3.10.2: - version "3.10.3" - resolved "https://registry.yarnpkg.com/ember-in-viewport/-/ember-in-viewport-3.10.3.tgz#317472bb82bed11f7895821b799349c6a7406e81" - integrity sha512-hSX7p+G6hJjZaY2BAqzyuiMP7QIHzQ4g0+ZBnEwAa8GMbILFAtzPx5A4XEX8wY6dSzhHB9n9jkcWZdmaML6q8A== - dependencies: - ember-auto-import "^1.11.2" - ember-cli-babel "^7.26.3" - ember-modifier "^2.1.0" - fast-deep-equal "^2.0.1" - intersection-observer-admin "~0.3.2" - raf-pool "~0.1.4" - ember-infinity@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/ember-infinity/-/ember-infinity-2.3.0.tgz#73fe13883c212147bfba4f0b2fe8c8d2a96887d9" @@ -7533,19 +7521,6 @@ ember-modifier@3.2.7, "ember-modifier@^2.1.2 || ^3.0.0", "ember-modifier@^2.1.2 ember-cli-typescript "^5.0.0" ember-compatibility-helpers "^1.2.5" -ember-modifier@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ember-modifier/-/ember-modifier-2.1.2.tgz#62d18faedf972dcd9d34f90d5321fbc943d139b1" - integrity sha512-3Lsu1fV1sIGa66HOW07RZc6EHISwKt5VA5AUnFss2HX6OTfpxTJ2qvPctt2Yt0XPQXJ4G6BQasr/F35CX7UGJA== - dependencies: - ember-cli-babel "^7.22.1" - ember-cli-normalize-entity-name "^1.0.0" - ember-cli-string-utils "^1.1.0" - ember-cli-typescript "^3.1.3" - ember-compatibility-helpers "^1.2.4" - ember-destroyable-polyfill "^2.0.2" - ember-modifier-manager-polyfill "^1.2.0" - ember-moment@10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/ember-moment/-/ember-moment-10.0.0.tgz#db2affde4574b7d679ad1a34e8a5675fda0b72fe"