ember-nav-stack 6.1.2 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -21
- package/addon-main.cjs +4 -0
- package/dist/_app_/components/nav-stack-inner-wrapper.js +1 -0
- package/dist/_app_/components/nav-stack.js +1 -0
- package/dist/_app_/components/to-nav-stack.js +1 -0
- package/dist/_app_/helpers/nav-layer-indices.js +1 -0
- package/dist/_app_/modifiers/back-swipe.js +1 -0
- package/dist/_app_/services/gesture.js +1 -0
- package/dist/_app_/services/nav-stacks.js +1 -0
- package/dist/_app_/templates/stackable.js +1 -0
- package/dist/back-swipe-gesture.js +261 -0
- package/dist/back-swipe-gesture.js.map +1 -0
- package/dist/components/nav-stack-inner-wrapper.js +10 -0
- package/dist/components/nav-stack-inner-wrapper.js.map +1 -0
- package/dist/components/nav-stack.js +700 -0
- package/dist/components/nav-stack.js.map +1 -0
- package/dist/components/to-nav-stack.js +22 -0
- package/dist/components/to-nav-stack.js.map +1 -0
- package/dist/helpers/nav-layer-indices.js +21 -0
- package/dist/helpers/nav-layer-indices.js.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/modifiers/back-swipe.js +40 -0
- package/dist/modifiers/back-swipe.js.map +1 -0
- package/dist/routes/stackable-route.js +99 -0
- package/dist/routes/stackable-route.js.map +1 -0
- package/{addon → dist}/services/gesture.js +7 -9
- package/dist/services/gesture.js.map +1 -0
- package/dist/services/nav-stacks.js +137 -0
- package/dist/services/nav-stacks.js.map +1 -0
- package/dist/styles/nav-stack.css +399 -0
- package/dist/templates/stackable.js +8 -0
- package/dist/templates/stackable.js.map +1 -0
- package/{addon-test-support → dist/test-support}/in-viewport.js +7 -10
- package/dist/test-support/in-viewport.js.map +1 -0
- package/dist/test-support/index.js +2 -0
- package/dist/test-support/index.js.map +1 -0
- package/{addon → dist}/utils/animation.js +17 -40
- package/dist/utils/animation.js.map +1 -0
- package/{addon → dist}/utils/back-swipe-recognizer.js +29 -49
- package/dist/utils/back-swipe-recognizer.js.map +1 -0
- package/dist/utils/clone-store.js +88 -0
- package/dist/utils/clone-store.js.map +1 -0
- package/dist/utils/component.js +121 -0
- package/dist/utils/component.js.map +1 -0
- package/dist/utils/header-style.js +46 -0
- package/dist/utils/header-style.js.map +1 -0
- package/dist/utils/transition-decision.js +71 -0
- package/dist/utils/transition-decision.js.map +1 -0
- package/dist/utils/waiter-state.js +130 -0
- package/dist/utils/waiter-state.js.map +1 -0
- package/package.json +79 -91
- package/.vscode/settings.json +0 -2
- package/CHANGELOG.md +0 -208
- package/MODULE_REPORT.md +0 -27
- package/RELEASE.md +0 -54
- package/addon/components/nav-stack/component.js +0 -690
- package/addon/components/nav-stack/template.hbs +0 -37
- package/addon/components/to-nav-stack.js +0 -32
- package/addon/helpers/nav-layer-indices.js +0 -29
- package/addon/routes/stackable-route.js +0 -61
- package/addon/services/nav-stacks.js +0 -157
- package/addon/utils/component.js +0 -40
- package/app/components/nav-stack/component.js +0 -1
- package/app/components/nav-stack/template.js +0 -1
- package/app/components/to-nav-stack.js +0 -1
- package/app/helpers/nav-layer-indices.js +0 -1
- package/app/services/gesture.js +0 -1
- package/app/services/nav-stacks.js +0 -1
- package/app/styles/nav-stack.scss +0 -117
- package/app/templates/stackable.hbs +0 -8
- package/app/utils/animation.js +0 -1
- package/config/deploy.js +0 -29
- package/config/environment.js +0 -5
- package/config/release.js +0 -21
- package/docs/ember-nav-stack-waiters-plan.md +0 -125
- package/index.js +0 -15
- package/tsconfig.json +0 -6
- package/vendor/wobble-shim.js +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"back-swipe-recognizer.js","sources":["../../src/utils/back-swipe-recognizer.js"],"sourcesContent":["import Hammer from 'hammerjs';\nimport { macroCondition, isTesting } from '@embroider/macros';\nconst { DIRECTION_RIGHT } = Hammer;\nconst FIELD_REGEXP = /input|textarea|select/i;\n\n/* This recognizer subclasses the Pan recognizer and adds the constraint that the initial touch\n * must be in the validLeftAreaPercent portion of the screen.\n */\nexport default class BackSwipeRecognizer extends Hammer.Pan {\n constructor(options) {\n super(options);\n this.options = Object.assign({}, this.defaults, options || {});\n this.captureClick = (ev) => {\n ev.stopPropagation(); // Stop the click from being propagated.\n this.manager.element.removeEventListener(\n 'click',\n this.captureClick,\n true,\n );\n };\n }\n\n defaults = {\n enable: true,\n event: 'pan',\n threshold: 10,\n pointers: 1,\n direction: DIRECTION_RIGHT,\n validLeftAreaPercent: 33,\n };\n\n recognize(inputData) {\n if (inputData.isFirst) {\n this.isInitialTouchInValidArea =\n this.checkInitialTouchInValidArea(inputData);\n }\n let isOverElementThatPreventsScrollingInteraction =\n this.shouldPreventScrollingInteraction(inputData);\n if (isOverElementThatPreventsScrollingInteraction) {\n this.manager.stop();\n return;\n }\n this.captureGhostClickIfNeeded(inputData);\n super.recognize(inputData);\n if (inputData.isFinal) {\n setTimeout(() => {\n this.state = Hammer.STATE_POSSIBLE;\n }, 0);\n }\n }\n\n shouldPreventScrollingInteraction(inputData) {\n let { target } = inputData;\n return (\n inputData.isFirst &&\n ((target && target.tagName.match(FIELD_REGEXP)) ||\n (target && target.hasAttribute('data-prevent-scrolling')))\n );\n }\n\n captureGhostClickIfNeeded(inputData) {\n if (\n inputData.srcEvent.type === 'mouseup' &&\n this.state & Hammer.STATE_BEGAN\n ) {\n this.manager.element.addEventListener('click', this.captureClick, true);\n setTimeout(() => {\n this.manager.element.removeEventListener(\n 'click',\n this.captureClick,\n true,\n );\n }, 0);\n }\n }\n\n reset() {\n this.isInitialTouchInValidArea = undefined;\n }\n\n checkInitialTouchInValidArea(inputData) {\n if (macroCondition(isTesting())) {\n let testingEl = document.querySelector('#ember-testing');\n if (testingEl) {\n let testingRect = testingEl.getBoundingClientRect();\n let minValidX = testingRect.left;\n let maxValidX =\n minValidX +\n testingEl.clientWidth * (this.options.validLeftAreaPercent / 100);\n return (\n inputData.center.x >= minValidX && inputData.center.x <= maxValidX\n );\n }\n }\n let maxValidX =\n window.innerWidth * (this.options.validLeftAreaPercent / 100);\n return inputData.center.x <= maxValidX;\n }\n\n attrTest(input) {\n return this.isInitialTouchInValidArea && super.attrTest(input);\n }\n}\n"],"names":["DIRECTION_RIGHT","Hammer","FIELD_REGEXP","BackSwipeRecognizer","Pan","constructor","options","Object","assign","defaults","captureClick","ev","stopPropagation","manager","element","removeEventListener","enable","event","threshold","pointers","direction","validLeftAreaPercent","recognize","inputData","isFirst","isInitialTouchInValidArea","checkInitialTouchInValidArea","isOverElementThatPreventsScrollingInteraction","shouldPreventScrollingInteraction","stop","captureGhostClickIfNeeded","isFinal","setTimeout","state","STATE_POSSIBLE","target","tagName","match","hasAttribute","srcEvent","type","STATE_BEGAN","addEventListener","reset","undefined","macroCondition","isTesting","testingEl","document","querySelector","testingRect","getBoundingClientRect","minValidX","left","maxValidX","clientWidth","center","x","window","innerWidth","attrTest","input"],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Tracks groups of cloned DOM nodes so they can be removed from the document
|
|
2
|
+
// as a unit. NavStack creates four groups during its animations:
|
|
3
|
+
//
|
|
4
|
+
// - 'stackItems' — the last item cloned for a slideBack
|
|
5
|
+
// - 'headers' — the leaving header cloned for slide animations
|
|
6
|
+
// - 'elements' — the whole NavStack cloned for slideDown
|
|
7
|
+
// - 'gestureBackOverlays' — target-header snapshot during a back-swipe
|
|
8
|
+
// (lifecycle described in PR #79's commit body)
|
|
9
|
+
//
|
|
10
|
+
// The store doesn't know how to CREATE the clones — callers do the
|
|
11
|
+
// `.cloneNode(true)` + attach themselves and pass the result to `track()`.
|
|
12
|
+
// What the store provides is uniform cleanup (`remove()`, `clear()`,
|
|
13
|
+
// `clearAll()`) with a `parentNode?.removeChild` guard so a clone whose
|
|
14
|
+
// parent has already been removed from the DOM is dropped silently rather
|
|
15
|
+
// than throwing.
|
|
16
|
+
class CloneStore {
|
|
17
|
+
#groups = new Map();
|
|
18
|
+
|
|
19
|
+
// Records `clone` under `groupName`. Tracking the same clone twice in the
|
|
20
|
+
// same group is a no-op. (Tracking the same clone in MULTIPLE groups is
|
|
21
|
+
// not prevented — but no caller does that today; each clone has one
|
|
22
|
+
// logical owner group based on which slide animation created it.)
|
|
23
|
+
track(groupName, clone) {
|
|
24
|
+
if (!clone) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
let group = this.#groups.get(groupName);
|
|
28
|
+
if (!group) {
|
|
29
|
+
group = [];
|
|
30
|
+
this.#groups.set(groupName, group);
|
|
31
|
+
}
|
|
32
|
+
if (group.indexOf(clone) === -1) {
|
|
33
|
+
group.push(clone);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Removes a specific clone from a group AND from the DOM. Safe to call
|
|
38
|
+
// when the clone has already been detached.
|
|
39
|
+
remove(groupName, clone) {
|
|
40
|
+
if (!clone) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
let group = this.#groups.get(groupName);
|
|
44
|
+
if (group) {
|
|
45
|
+
let idx = group.indexOf(clone);
|
|
46
|
+
if (idx !== -1) {
|
|
47
|
+
group.splice(idx, 1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (clone.parentNode) {
|
|
51
|
+
clone.parentNode.removeChild(clone);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Removes every clone in a group from the DOM and empties the group.
|
|
56
|
+
// Safe to call when the group doesn't exist yet.
|
|
57
|
+
clear(groupName) {
|
|
58
|
+
let group = this.#groups.get(groupName);
|
|
59
|
+
if (!group) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
let clone;
|
|
63
|
+
while (clone = group.pop()) {
|
|
64
|
+
if (clone.parentNode) {
|
|
65
|
+
clone.parentNode.removeChild(clone);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Clears every group. Used in NavStack's willDestroy to sweep anything
|
|
71
|
+
// left over from abandoned transitions.
|
|
72
|
+
clearAll() {
|
|
73
|
+
for (let groupName of this.#groups.keys()) {
|
|
74
|
+
this.clear(groupName);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Convenience for reading "the most recently tracked clone in this group"
|
|
79
|
+
// — used by NavStack's slideDown which needs the cloned-NavStack element
|
|
80
|
+
// it just produced. Returns undefined for empty/missing groups.
|
|
81
|
+
last(groupName) {
|
|
82
|
+
let group = this.#groups.get(groupName);
|
|
83
|
+
return group?.[group.length - 1];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export { CloneStore as default };
|
|
88
|
+
//# sourceMappingURL=clone-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone-store.js","sources":["../../src/utils/clone-store.js"],"sourcesContent":["// Tracks groups of cloned DOM nodes so they can be removed from the document\n// as a unit. NavStack creates four groups during its animations:\n//\n// - 'stackItems' — the last item cloned for a slideBack\n// - 'headers' — the leaving header cloned for slide animations\n// - 'elements' — the whole NavStack cloned for slideDown\n// - 'gestureBackOverlays' — target-header snapshot during a back-swipe\n// (lifecycle described in PR #79's commit body)\n//\n// The store doesn't know how to CREATE the clones — callers do the\n// `.cloneNode(true)` + attach themselves and pass the result to `track()`.\n// What the store provides is uniform cleanup (`remove()`, `clear()`,\n// `clearAll()`) with a `parentNode?.removeChild` guard so a clone whose\n// parent has already been removed from the DOM is dropped silently rather\n// than throwing.\nexport default class CloneStore {\n #groups = new Map();\n\n // Records `clone` under `groupName`. Tracking the same clone twice in the\n // same group is a no-op. (Tracking the same clone in MULTIPLE groups is\n // not prevented — but no caller does that today; each clone has one\n // logical owner group based on which slide animation created it.)\n track(groupName, clone) {\n if (!clone) {\n return;\n }\n let group = this.#groups.get(groupName);\n if (!group) {\n group = [];\n this.#groups.set(groupName, group);\n }\n if (group.indexOf(clone) === -1) {\n group.push(clone);\n }\n }\n\n // Removes a specific clone from a group AND from the DOM. Safe to call\n // when the clone has already been detached.\n remove(groupName, clone) {\n if (!clone) {\n return;\n }\n let group = this.#groups.get(groupName);\n if (group) {\n let idx = group.indexOf(clone);\n if (idx !== -1) {\n group.splice(idx, 1);\n }\n }\n if (clone.parentNode) {\n clone.parentNode.removeChild(clone);\n }\n }\n\n // Removes every clone in a group from the DOM and empties the group.\n // Safe to call when the group doesn't exist yet.\n clear(groupName) {\n let group = this.#groups.get(groupName);\n if (!group) {\n return;\n }\n let clone;\n while ((clone = group.pop())) {\n if (clone.parentNode) {\n clone.parentNode.removeChild(clone);\n }\n }\n }\n\n // Clears every group. Used in NavStack's willDestroy to sweep anything\n // left over from abandoned transitions.\n clearAll() {\n for (let groupName of this.#groups.keys()) {\n this.clear(groupName);\n }\n }\n\n // Convenience for reading \"the most recently tracked clone in this group\"\n // — used by NavStack's slideDown which needs the cloned-NavStack element\n // it just produced. Returns undefined for empty/missing groups.\n last(groupName) {\n let group = this.#groups.get(groupName);\n return group?.[group.length - 1];\n }\n}\n"],"names":["CloneStore","Map","track","groupName","clone","group","get","set","indexOf","push","remove","idx","splice","parentNode","removeChild","clear","pop","clearAll","keys","last","length"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,MAAMA,UAAU,CAAC;AAC9B,EAAA,OAAO,GAAG,IAAIC,GAAG,EAAE;;AAEnB;AACA;AACA;AACA;AACAC,EAAAA,KAAKA,CAACC,SAAS,EAAEC,KAAK,EAAE;IACtB,IAAI,CAACA,KAAK,EAAE;AACV,MAAA;AACF,IAAA;IACA,IAAIC,KAAK,GAAG,IAAI,CAAC,OAAO,CAACC,GAAG,CAACH,SAAS,CAAC;IACvC,IAAI,CAACE,KAAK,EAAE;AACVA,MAAAA,KAAK,GAAG,EAAE;MACV,IAAI,CAAC,OAAO,CAACE,GAAG,CAACJ,SAAS,EAAEE,KAAK,CAAC;AACpC,IAAA;IACA,IAAIA,KAAK,CAACG,OAAO,CAACJ,KAAK,CAAC,KAAK,EAAE,EAAE;AAC/BC,MAAAA,KAAK,CAACI,IAAI,CAACL,KAAK,CAAC;AACnB,IAAA;AACF,EAAA;;AAEA;AACA;AACAM,EAAAA,MAAMA,CAACP,SAAS,EAAEC,KAAK,EAAE;IACvB,IAAI,CAACA,KAAK,EAAE;AACV,MAAA;AACF,IAAA;IACA,IAAIC,KAAK,GAAG,IAAI,CAAC,OAAO,CAACC,GAAG,CAACH,SAAS,CAAC;AACvC,IAAA,IAAIE,KAAK,EAAE;AACT,MAAA,IAAIM,GAAG,GAAGN,KAAK,CAACG,OAAO,CAACJ,KAAK,CAAC;AAC9B,MAAA,IAAIO,GAAG,KAAK,EAAE,EAAE;AACdN,QAAAA,KAAK,CAACO,MAAM,CAACD,GAAG,EAAE,CAAC,CAAC;AACtB,MAAA;AACF,IAAA;IACA,IAAIP,KAAK,CAACS,UAAU,EAAE;AACpBT,MAAAA,KAAK,CAACS,UAAU,CAACC,WAAW,CAACV,KAAK,CAAC;AACrC,IAAA;AACF,EAAA;;AAEA;AACA;EACAW,KAAKA,CAACZ,SAAS,EAAE;IACf,IAAIE,KAAK,GAAG,IAAI,CAAC,OAAO,CAACC,GAAG,CAACH,SAAS,CAAC;IACvC,IAAI,CAACE,KAAK,EAAE;AACV,MAAA;AACF,IAAA;AACA,IAAA,IAAID,KAAK;AACT,IAAA,OAAQA,KAAK,GAAGC,KAAK,CAACW,GAAG,EAAE,EAAG;MAC5B,IAAIZ,KAAK,CAACS,UAAU,EAAE;AACpBT,QAAAA,KAAK,CAACS,UAAU,CAACC,WAAW,CAACV,KAAK,CAAC;AACrC,MAAA;AACF,IAAA;AACF,EAAA;;AAEA;AACA;AACAa,EAAAA,QAAQA,GAAG;IACT,KAAK,IAAId,SAAS,IAAI,IAAI,CAAC,OAAO,CAACe,IAAI,EAAE,EAAE;AACzC,MAAA,IAAI,CAACH,KAAK,CAACZ,SAAS,CAAC;AACvB,IAAA;AACF,EAAA;;AAEA;AACA;AACA;EACAgB,IAAIA,CAAChB,SAAS,EAAE;IACd,IAAIE,KAAK,GAAG,IAAI,CAAC,OAAO,CAACC,GAAG,CAACH,SAAS,CAAC;AACvC,IAAA,OAAOE,KAAK,GAAGA,KAAK,CAACe,MAAM,GAAG,CAAC,CAAC;AAClC,EAAA;AACF;;;;"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { macroCondition, isDevelopingApp } from '@embroider/macros';
|
|
2
|
+
|
|
3
|
+
function extractComponentKey(componentRef) {
|
|
4
|
+
if (!componentRef) {
|
|
5
|
+
return 'none';
|
|
6
|
+
}
|
|
7
|
+
let result = getComponentRefName(componentRef);
|
|
8
|
+
// Dev-only safeguard: if every access path failed to produce a name, the
|
|
9
|
+
// Glimmer reference's shape has likely changed (it has before — see the
|
|
10
|
+
// INNER-slot-as-string vs. -as-object update further down) and we'd
|
|
11
|
+
// otherwise return `undefined` silently. That makes
|
|
12
|
+
// `rootComponentKey !== this._rootComponentKey` always compare
|
|
13
|
+
// `'undefined' === 'undefined'`, so root-change cuts (e.g. tab switches)
|
|
14
|
+
// would never fire and the addon would silently fall through to a slide
|
|
15
|
+
// animation. Failing loud here surfaces the breakage at the source.
|
|
16
|
+
//
|
|
17
|
+
// Gated on `@embroider/macros`'s `isDevelopingApp()` so the entire check
|
|
18
|
+
// (including the message string) is stripped from production builds by
|
|
19
|
+
// the consumer's babel pipeline — both Embroider and classic ember-cli
|
|
20
|
+
// run the macros transform on v2 addon code, unlike
|
|
21
|
+
// `babel-plugin-debug-macros` (which only applies to app + v1 addon
|
|
22
|
+
// code in classic builds and would leave the string in the bundle).
|
|
23
|
+
if (macroCondition(isDevelopingApp())) {
|
|
24
|
+
if (result === undefined) {
|
|
25
|
+
throw new Error('[ember-nav-stack] extractComponentKey could not derive a name from the component reference. The Glimmer reference shape has likely changed; see src/utils/component.js.');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
let modelId = getComponentRefModelId(componentRef);
|
|
29
|
+
if (modelId) {
|
|
30
|
+
result += `:${modelId}`;
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Component-name-only key for a curried component reference. Skips the
|
|
36
|
+
// `model.id` appendage that `extractComponentKey` adds because, unlike the
|
|
37
|
+
// component name (which is set at curry time), the model ref's `lastValue`
|
|
38
|
+
// resolves lazily — the active-item-change path needs a key that's stable
|
|
39
|
+
// the moment the curry exists, otherwise a single push fires twice as the
|
|
40
|
+
// model id transitions from undefined to its concrete value across two
|
|
41
|
+
// render ticks.
|
|
42
|
+
function extractComponentName(componentRef) {
|
|
43
|
+
if (!componentRef) {
|
|
44
|
+
return 'none';
|
|
45
|
+
}
|
|
46
|
+
return getComponentRefName(componentRef);
|
|
47
|
+
}
|
|
48
|
+
function getComponentRefName(componentRef) {
|
|
49
|
+
if (componentRef.name) {
|
|
50
|
+
return componentRef.name;
|
|
51
|
+
}
|
|
52
|
+
let innerSym = Object.getOwnPropertySymbols(componentRef).find(s => s.description === 'INNER');
|
|
53
|
+
let inner = componentRef.inner || innerSym && componentRef[innerSym];
|
|
54
|
+
// In modern Glimmer, a curried component's INNER slot holds the resolved
|
|
55
|
+
// component name as a string. Older builds wrapped it in an object with
|
|
56
|
+
// a `.name` property.
|
|
57
|
+
if (typeof inner === 'string') {
|
|
58
|
+
return inner;
|
|
59
|
+
}
|
|
60
|
+
return inner?.name;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Resolve a Glimmer reference to its current value without importing from
|
|
64
|
+
// `@glimmer/reference` (which would couple this addon to a specific
|
|
65
|
+
// Glimmer release line and cause dedupe headaches under strict resolvers).
|
|
66
|
+
// Three paths:
|
|
67
|
+
// 1. `ref.value()` — classic Glimmer (pre-2020-ish).
|
|
68
|
+
// 2. `ref.compute()` — modern Glimmer. Calls the underlying compute
|
|
69
|
+
// function, which both recomputes the live value AND consumes the
|
|
70
|
+
// ref's tag so we participate in autotracking. This is critical for
|
|
71
|
+
// the `stackItemsFingerprint` getter: without it, we'd be reading
|
|
72
|
+
// `lastValue` (a snapshot from the last render that consumed this
|
|
73
|
+
// ref) and miss in-place arg changes — e.g. a parent route swapping
|
|
74
|
+
// its `model` while keeping the same curried component instance
|
|
75
|
+
// alive. The fingerprint would then stay stale and the NavStack
|
|
76
|
+
// would miss the root-key change entirely (next stack mutation
|
|
77
|
+
// would lump the root change with the depth change and degenerate
|
|
78
|
+
// to a cut, suppressing the expected slide).
|
|
79
|
+
// 3. `ref.lastValue` — last-resort fallback.
|
|
80
|
+
// `extractComponentKey` is
|
|
81
|
+
// invoked from `<NavStack>`'s reactive `stackItemsFingerprint` getter
|
|
82
|
+
// whose own re-evaluation is what propagated the change in the first place.
|
|
83
|
+
function valueForRef(ref) {
|
|
84
|
+
if (!ref) {
|
|
85
|
+
return ref;
|
|
86
|
+
}
|
|
87
|
+
if (typeof ref.value === 'function') {
|
|
88
|
+
return ref.value();
|
|
89
|
+
}
|
|
90
|
+
if (typeof ref.compute === 'function') {
|
|
91
|
+
return ref.compute();
|
|
92
|
+
}
|
|
93
|
+
return ref.lastValue;
|
|
94
|
+
}
|
|
95
|
+
function getComponentRefModelId(componentRef) {
|
|
96
|
+
let argsSym = Object.getOwnPropertySymbols(componentRef).find(s => s.description === 'ARGS');
|
|
97
|
+
let args = componentRef.args || argsSym && componentRef[argsSym];
|
|
98
|
+
if (!args || !args.named) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let named = args.named;
|
|
102
|
+
let modelRef;
|
|
103
|
+
if (typeof named.has === 'function' && named.has('model')) {
|
|
104
|
+
// Older Glimmer exposed named args as a Map-like with has/get.
|
|
105
|
+
modelRef = named.get('model');
|
|
106
|
+
} else if (named.model) {
|
|
107
|
+
// Modern Glimmer: args.named is a POJO of references keyed by arg name.
|
|
108
|
+
modelRef = named.model;
|
|
109
|
+
}
|
|
110
|
+
if (!modelRef) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
let model = valueForRef(modelRef);
|
|
114
|
+
if (model) {
|
|
115
|
+
return model.id;
|
|
116
|
+
}
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { extractComponentKey, extractComponentName };
|
|
121
|
+
//# sourceMappingURL=component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.js","sources":["../../src/utils/component.js"],"sourcesContent":["import { macroCondition, isDevelopingApp } from '@embroider/macros';\n\nexport function extractComponentKey(componentRef) {\n if (!componentRef) {\n return 'none';\n }\n let result = getComponentRefName(componentRef);\n // Dev-only safeguard: if every access path failed to produce a name, the\n // Glimmer reference's shape has likely changed (it has before — see the\n // INNER-slot-as-string vs. -as-object update further down) and we'd\n // otherwise return `undefined` silently. That makes\n // `rootComponentKey !== this._rootComponentKey` always compare\n // `'undefined' === 'undefined'`, so root-change cuts (e.g. tab switches)\n // would never fire and the addon would silently fall through to a slide\n // animation. Failing loud here surfaces the breakage at the source.\n //\n // Gated on `@embroider/macros`'s `isDevelopingApp()` so the entire check\n // (including the message string) is stripped from production builds by\n // the consumer's babel pipeline — both Embroider and classic ember-cli\n // run the macros transform on v2 addon code, unlike\n // `babel-plugin-debug-macros` (which only applies to app + v1 addon\n // code in classic builds and would leave the string in the bundle).\n if (macroCondition(isDevelopingApp())) {\n if (result === undefined) {\n throw new Error(\n '[ember-nav-stack] extractComponentKey could not derive a name from the component reference. The Glimmer reference shape has likely changed; see src/utils/component.js.',\n );\n }\n }\n let modelId = getComponentRefModelId(componentRef);\n if (modelId) {\n result += `:${modelId}`;\n }\n return result;\n}\n\n// Component-name-only key for a curried component reference. Skips the\n// `model.id` appendage that `extractComponentKey` adds because, unlike the\n// component name (which is set at curry time), the model ref's `lastValue`\n// resolves lazily — the active-item-change path needs a key that's stable\n// the moment the curry exists, otherwise a single push fires twice as the\n// model id transitions from undefined to its concrete value across two\n// render ticks.\nexport function extractComponentName(componentRef) {\n if (!componentRef) {\n return 'none';\n }\n return getComponentRefName(componentRef);\n}\n\nfunction getComponentRefName(componentRef) {\n if (componentRef.name) {\n return componentRef.name;\n }\n let innerSym = Object.getOwnPropertySymbols(componentRef).find(\n (s) => s.description === 'INNER',\n );\n let inner = componentRef.inner || (innerSym && componentRef[innerSym]);\n // In modern Glimmer, a curried component's INNER slot holds the resolved\n // component name as a string. Older builds wrapped it in an object with\n // a `.name` property.\n if (typeof inner === 'string') {\n return inner;\n }\n return inner?.name;\n}\n\n// Resolve a Glimmer reference to its current value without importing from\n// `@glimmer/reference` (which would couple this addon to a specific\n// Glimmer release line and cause dedupe headaches under strict resolvers).\n// Three paths:\n// 1. `ref.value()` — classic Glimmer (pre-2020-ish).\n// 2. `ref.compute()` — modern Glimmer. Calls the underlying compute\n// function, which both recomputes the live value AND consumes the\n// ref's tag so we participate in autotracking. This is critical for\n// the `stackItemsFingerprint` getter: without it, we'd be reading\n// `lastValue` (a snapshot from the last render that consumed this\n// ref) and miss in-place arg changes — e.g. a parent route swapping\n// its `model` while keeping the same curried component instance\n// alive. The fingerprint would then stay stale and the NavStack\n// would miss the root-key change entirely (next stack mutation\n// would lump the root change with the depth change and degenerate\n// to a cut, suppressing the expected slide).\n// 3. `ref.lastValue` — last-resort fallback.\n// `extractComponentKey` is\n// invoked from `<NavStack>`'s reactive `stackItemsFingerprint` getter\n// whose own re-evaluation is what propagated the change in the first place.\nfunction valueForRef(ref) {\n if (!ref) {\n return ref;\n }\n if (typeof ref.value === 'function') {\n return ref.value();\n }\n if (typeof ref.compute === 'function') {\n return ref.compute();\n }\n return ref.lastValue;\n}\n\nfunction getComponentRefModelId(componentRef) {\n let argsSym = Object.getOwnPropertySymbols(componentRef).find(\n (s) => s.description === 'ARGS',\n );\n let args = componentRef.args || (argsSym && componentRef[argsSym]);\n if (!args || !args.named) {\n return;\n }\n let named = args.named;\n let modelRef;\n if (typeof named.has === 'function' && named.has('model')) {\n // Older Glimmer exposed named args as a Map-like with has/get.\n modelRef = named.get('model');\n } else if (named.model) {\n // Modern Glimmer: args.named is a POJO of references keyed by arg name.\n modelRef = named.model;\n }\n if (!modelRef) {\n return;\n }\n let model = valueForRef(modelRef);\n if (model) {\n return model.id;\n }\n return;\n}\n"],"names":["extractComponentKey","componentRef","result","getComponentRefName","macroCondition","isDevelopingApp","undefined","Error","modelId","getComponentRefModelId","extractComponentName","name","innerSym","Object","getOwnPropertySymbols","find","s","description","inner","valueForRef","ref","value","compute","lastValue","argsSym","args","named","modelRef","has","get","model","id"],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { setTransform } from './animation.js';
|
|
2
|
+
|
|
3
|
+
// Pixels of parallax applied to the header elements during a horizontal
|
|
4
|
+
// transition. The currentHeaderContainer slides this far while the parent
|
|
5
|
+
// (target page) header slides in from the opposite direction.
|
|
6
|
+
const HEADER_PARALLAX_OFFSET = 60;
|
|
7
|
+
|
|
8
|
+
// Maps an animation's current value (e.g. translateX in CSS px) to a 0..1
|
|
9
|
+
// ratio representing how far the transition has progressed from fromValue
|
|
10
|
+
// to toValue. Returns 1 when fromValue is unset or equal to toValue (used by
|
|
11
|
+
// the no-op case in horizontalTransition).
|
|
12
|
+
function currentTransitionPercentage(fromValue, toValue, currentValue) {
|
|
13
|
+
if (fromValue === undefined || fromValue === toValue) {
|
|
14
|
+
return 1;
|
|
15
|
+
}
|
|
16
|
+
let percentage = Math.abs((currentValue - fromValue) / (toValue - fromValue));
|
|
17
|
+
if (toValue > fromValue) {
|
|
18
|
+
return 1 - percentage;
|
|
19
|
+
}
|
|
20
|
+
return percentage;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Cross-fades and translates two header elements as a horizontal transition
|
|
24
|
+
// progresses. `isForward` controls which direction the offset goes (forward
|
|
25
|
+
// transitions push the leaving header rightward; back transitions leftward).
|
|
26
|
+
// Either element argument may be null — both are conditionally available
|
|
27
|
+
// during slideBack/slideForward and the swipe-driven path.
|
|
28
|
+
function styleHeaderElements(transitionRatio, isForward, currentHeaderElement, otherHeaderElement) {
|
|
29
|
+
let startingOffset = HEADER_PARALLAX_OFFSET;
|
|
30
|
+
if (!isForward) {
|
|
31
|
+
transitionRatio = 1 - transitionRatio;
|
|
32
|
+
startingOffset = -1 * startingOffset;
|
|
33
|
+
}
|
|
34
|
+
let xOffset = transitionRatio * -1 * startingOffset;
|
|
35
|
+
if (currentHeaderElement) {
|
|
36
|
+
currentHeaderElement.style.opacity = transitionRatio;
|
|
37
|
+
setTransform(currentHeaderElement, `translateX(${startingOffset + xOffset}px)`);
|
|
38
|
+
}
|
|
39
|
+
if (otherHeaderElement) {
|
|
40
|
+
otherHeaderElement.style.opacity = 1 - transitionRatio;
|
|
41
|
+
setTransform(otherHeaderElement, `translateX(${xOffset}px)`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { HEADER_PARALLAX_OFFSET, currentTransitionPercentage, styleHeaderElements };
|
|
46
|
+
//# sourceMappingURL=header-style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header-style.js","sources":["../../src/utils/header-style.js"],"sourcesContent":["import { setTransform } from './animation.js';\n\n// Pixels of parallax applied to the header elements during a horizontal\n// transition. The currentHeaderContainer slides this far while the parent\n// (target page) header slides in from the opposite direction.\nexport const HEADER_PARALLAX_OFFSET = 60;\n\n// Maps an animation's current value (e.g. translateX in CSS px) to a 0..1\n// ratio representing how far the transition has progressed from fromValue\n// to toValue. Returns 1 when fromValue is unset or equal to toValue (used by\n// the no-op case in horizontalTransition).\nexport function currentTransitionPercentage(fromValue, toValue, currentValue) {\n if (fromValue === undefined || fromValue === toValue) {\n return 1;\n }\n let percentage = Math.abs((currentValue - fromValue) / (toValue - fromValue));\n if (toValue > fromValue) {\n return 1 - percentage;\n }\n return percentage;\n}\n\n// Cross-fades and translates two header elements as a horizontal transition\n// progresses. `isForward` controls which direction the offset goes (forward\n// transitions push the leaving header rightward; back transitions leftward).\n// Either element argument may be null — both are conditionally available\n// during slideBack/slideForward and the swipe-driven path.\nexport function styleHeaderElements(\n transitionRatio,\n isForward,\n currentHeaderElement,\n otherHeaderElement,\n) {\n let startingOffset = HEADER_PARALLAX_OFFSET;\n if (!isForward) {\n transitionRatio = 1 - transitionRatio;\n startingOffset = -1 * startingOffset;\n }\n let xOffset = transitionRatio * -1 * startingOffset;\n if (currentHeaderElement) {\n currentHeaderElement.style.opacity = transitionRatio;\n setTransform(\n currentHeaderElement,\n `translateX(${startingOffset + xOffset}px)`,\n );\n }\n if (otherHeaderElement) {\n otherHeaderElement.style.opacity = 1 - transitionRatio;\n setTransform(otherHeaderElement, `translateX(${xOffset}px)`);\n }\n}\n"],"names":["HEADER_PARALLAX_OFFSET","currentTransitionPercentage","fromValue","toValue","currentValue","undefined","percentage","Math","abs","styleHeaderElements","transitionRatio","isForward","currentHeaderElement","otherHeaderElement","startingOffset","xOffset","style","opacity","setTransform"],"mappings":";;AAEA;AACA;AACA;AACO,MAAMA,sBAAsB,GAAG;;AAEtC;AACA;AACA;AACA;AACO,SAASC,2BAA2BA,CAACC,SAAS,EAAEC,OAAO,EAAEC,YAAY,EAAE;AAC5E,EAAA,IAAIF,SAAS,KAAKG,SAAS,IAAIH,SAAS,KAAKC,OAAO,EAAE;AACpD,IAAA,OAAO,CAAC;AACV,EAAA;AACA,EAAA,IAAIG,UAAU,GAAGC,IAAI,CAACC,GAAG,CAAC,CAACJ,YAAY,GAAGF,SAAS,KAAKC,OAAO,GAAGD,SAAS,CAAC,CAAC;EAC7E,IAAIC,OAAO,GAAGD,SAAS,EAAE;IACvB,OAAO,CAAC,GAAGI,UAAU;AACvB,EAAA;AACA,EAAA,OAAOA,UAAU;AACnB;;AAEA;AACA;AACA;AACA;AACA;AACO,SAASG,mBAAmBA,CACjCC,eAAe,EACfC,SAAS,EACTC,oBAAoB,EACpBC,kBAAkB,EAClB;EACA,IAAIC,cAAc,GAAGd,sBAAsB;EAC3C,IAAI,CAACW,SAAS,EAAE;IACdD,eAAe,GAAG,CAAC,GAAGA,eAAe;AACrCI,IAAAA,cAAc,GAAG,EAAE,GAAGA,cAAc;AACtC,EAAA;AACA,EAAA,IAAIC,OAAO,GAAGL,eAAe,GAAG,EAAE,GAAGI,cAAc;AACnD,EAAA,IAAIF,oBAAoB,EAAE;AACxBA,IAAAA,oBAAoB,CAACI,KAAK,CAACC,OAAO,GAAGP,eAAe;IACpDQ,YAAY,CACVN,oBAAoB,EACpB,CAAA,WAAA,EAAcE,cAAc,GAAGC,OAAO,KACxC,CAAC;AACH,EAAA;AACA,EAAA,IAAIF,kBAAkB,EAAE;AACtBA,IAAAA,kBAAkB,CAACG,KAAK,CAACC,OAAO,GAAG,CAAC,GAAGP,eAAe;AACtDQ,IAAAA,YAAY,CAACL,kBAAkB,EAAE,CAAA,WAAA,EAAcE,OAAO,KAAK,CAAC;AAC9D,EAAA;AACF;;;;"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Pure function mapping an observed stack-state change to a transition intent.
|
|
2
|
+
//
|
|
3
|
+
// The full truth table is exercised by
|
|
4
|
+
// test-app/tests/unit/utils/transition-decision-test.js. Summary:
|
|
5
|
+
//
|
|
6
|
+
// isInitialRender → cut
|
|
7
|
+
// layer>0, prev=0, next>0 → slideUp (underlay appears)
|
|
8
|
+
// prev=undefined (first observation) → slideUp
|
|
9
|
+
// layer>0, prev>0, next=0 → slideDown (underlay disappears)
|
|
10
|
+
// newRootKey ≠ previousRootKey → cut, startsRootChange=true
|
|
11
|
+
// next<prev, !rootJustChanged → slideBack
|
|
12
|
+
// next<prev, rootJustChanged → cut (depth change rides on root change)
|
|
13
|
+
// next>prev, !rootJustChanged → slideForward
|
|
14
|
+
// next>prev, rootJustChanged → cut
|
|
15
|
+
// next===prev, same root, !initial → none
|
|
16
|
+
//
|
|
17
|
+
// `rootJustChanged` is set by the caller when a previous call in the same
|
|
18
|
+
// runloop tick produced a root-change intent. It exists because multiple
|
|
19
|
+
// service flushes can land in the same tick (e.g. parent-route swap +
|
|
20
|
+
// drilled-child exit during a tab switch); without coalescing, the second
|
|
21
|
+
// flush would animate over the cut from the first.
|
|
22
|
+
|
|
23
|
+
function decideTransition({
|
|
24
|
+
isInitialRender,
|
|
25
|
+
previousDepth,
|
|
26
|
+
newDepth,
|
|
27
|
+
previousRootKey,
|
|
28
|
+
newRootKey,
|
|
29
|
+
layer,
|
|
30
|
+
rootJustChanged
|
|
31
|
+
}) {
|
|
32
|
+
if (isInitialRender) {
|
|
33
|
+
return {
|
|
34
|
+
kind: 'cut'
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
let appearsAsUnderlay = layer > 0 && newDepth > 0 && previousDepth === 0;
|
|
38
|
+
if (appearsAsUnderlay || previousDepth === undefined) {
|
|
39
|
+
return {
|
|
40
|
+
kind: 'slideUp'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
let disappearsAsUnderlay = layer > 0 && newDepth === 0 && previousDepth > 0;
|
|
44
|
+
if (disappearsAsUnderlay) {
|
|
45
|
+
return {
|
|
46
|
+
kind: 'slideDown'
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (newRootKey !== previousRootKey) {
|
|
50
|
+
return {
|
|
51
|
+
kind: 'cut',
|
|
52
|
+
startsRootChange: true
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (newDepth < previousDepth) {
|
|
56
|
+
return {
|
|
57
|
+
kind: rootJustChanged ? 'cut' : 'slideBack'
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (newDepth > previousDepth) {
|
|
61
|
+
return {
|
|
62
|
+
kind: rootJustChanged ? 'cut' : 'slideForward'
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
kind: 'none'
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { decideTransition };
|
|
71
|
+
//# sourceMappingURL=transition-decision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transition-decision.js","sources":["../../src/utils/transition-decision.js"],"sourcesContent":["// Pure function mapping an observed stack-state change to a transition intent.\n//\n// The full truth table is exercised by\n// test-app/tests/unit/utils/transition-decision-test.js. Summary:\n//\n// isInitialRender → cut\n// layer>0, prev=0, next>0 → slideUp (underlay appears)\n// prev=undefined (first observation) → slideUp\n// layer>0, prev>0, next=0 → slideDown (underlay disappears)\n// newRootKey ≠ previousRootKey → cut, startsRootChange=true\n// next<prev, !rootJustChanged → slideBack\n// next<prev, rootJustChanged → cut (depth change rides on root change)\n// next>prev, !rootJustChanged → slideForward\n// next>prev, rootJustChanged → cut\n// next===prev, same root, !initial → none\n//\n// `rootJustChanged` is set by the caller when a previous call in the same\n// runloop tick produced a root-change intent. It exists because multiple\n// service flushes can land in the same tick (e.g. parent-route swap +\n// drilled-child exit during a tab switch); without coalescing, the second\n// flush would animate over the cut from the first.\n\nexport function decideTransition({\n isInitialRender,\n previousDepth,\n newDepth,\n previousRootKey,\n newRootKey,\n layer,\n rootJustChanged,\n}) {\n if (isInitialRender) {\n return { kind: 'cut' };\n }\n\n let appearsAsUnderlay = layer > 0 && newDepth > 0 && previousDepth === 0;\n if (appearsAsUnderlay || previousDepth === undefined) {\n return { kind: 'slideUp' };\n }\n\n let disappearsAsUnderlay = layer > 0 && newDepth === 0 && previousDepth > 0;\n if (disappearsAsUnderlay) {\n return { kind: 'slideDown' };\n }\n\n if (newRootKey !== previousRootKey) {\n return { kind: 'cut', startsRootChange: true };\n }\n\n if (newDepth < previousDepth) {\n return { kind: rootJustChanged ? 'cut' : 'slideBack' };\n }\n if (newDepth > previousDepth) {\n return { kind: rootJustChanged ? 'cut' : 'slideForward' };\n }\n\n return { kind: 'none' };\n}\n"],"names":["decideTransition","isInitialRender","previousDepth","newDepth","previousRootKey","newRootKey","layer","rootJustChanged","kind","appearsAsUnderlay","undefined","disappearsAsUnderlay","startsRootChange"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEO,SAASA,gBAAgBA,CAAC;EAC/BC,eAAe;EACfC,aAAa;EACbC,QAAQ;EACRC,eAAe;EACfC,UAAU;EACVC,KAAK;AACLC,EAAAA;AACF,CAAC,EAAE;AACD,EAAA,IAAIN,eAAe,EAAE;IACnB,OAAO;AAAEO,MAAAA,IAAI,EAAE;KAAO;AACxB,EAAA;AAEA,EAAA,IAAIC,iBAAiB,GAAGH,KAAK,GAAG,CAAC,IAAIH,QAAQ,GAAG,CAAC,IAAID,aAAa,KAAK,CAAC;AACxE,EAAA,IAAIO,iBAAiB,IAAIP,aAAa,KAAKQ,SAAS,EAAE;IACpD,OAAO;AAAEF,MAAAA,IAAI,EAAE;KAAW;AAC5B,EAAA;AAEA,EAAA,IAAIG,oBAAoB,GAAGL,KAAK,GAAG,CAAC,IAAIH,QAAQ,KAAK,CAAC,IAAID,aAAa,GAAG,CAAC;AAC3E,EAAA,IAAIS,oBAAoB,EAAE;IACxB,OAAO;AAAEH,MAAAA,IAAI,EAAE;KAAa;AAC9B,EAAA;EAEA,IAAIH,UAAU,KAAKD,eAAe,EAAE;IAClC,OAAO;AAAEI,MAAAA,IAAI,EAAE,KAAK;AAAEI,MAAAA,gBAAgB,EAAE;KAAM;AAChD,EAAA;EAEA,IAAIT,QAAQ,GAAGD,aAAa,EAAE;IAC5B,OAAO;AAAEM,MAAAA,IAAI,EAAED,eAAe,GAAG,KAAK,GAAG;KAAa;AACxD,EAAA;EACA,IAAIJ,QAAQ,GAAGD,aAAa,EAAE;IAC5B,OAAO;AAAEM,MAAAA,IAAI,EAAED,eAAe,GAAG,KAAK,GAAG;KAAgB;AAC3D,EAAA;EAEA,OAAO;AAAEC,IAAAA,IAAI,EAAE;GAAQ;AACzB;;;;"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { buildWaiter } from '@ember/test-waiters';
|
|
2
|
+
|
|
3
|
+
// `buildWaiter` registers a named waiter globally in `@ember/test-waiters`.
|
|
4
|
+
// Hoist these to module scope so every WaiterState instance shares the same
|
|
5
|
+
// two waiters — without this, each `new WaiterState()` (notably in unit
|
|
6
|
+
// tests) would register a fresh duplicate, accumulating noise in the global
|
|
7
|
+
// waiter registry over a test run.
|
|
8
|
+
const TRANSITION_WAITER = buildWaiter('ember-nav-stack:transition');
|
|
9
|
+
const STACK_WAITER = buildWaiter('ember-nav-stack:stack-update');
|
|
10
|
+
|
|
11
|
+
// Encapsulates the three test-waiter tokens NavStacks needs to manage
|
|
12
|
+
// (transition, stack-update, initial-render), a counter for currently
|
|
13
|
+
// running transitions, and a single-resolver "wait until idle" promise.
|
|
14
|
+
//
|
|
15
|
+
// State diagram:
|
|
16
|
+
//
|
|
17
|
+
// Tokens (each independently OPEN or CLOSED):
|
|
18
|
+
// - transition opens when runningTransitions goes 0 → 1,
|
|
19
|
+
// closes when runningTransitions returns to 0
|
|
20
|
+
// - stackUpdate opens on beginStackUpdate (idempotent),
|
|
21
|
+
// closes on endStackUpdate
|
|
22
|
+
// - initialRender opens once at construction, closes once on
|
|
23
|
+
// markInitialRenderComplete (subsequent calls
|
|
24
|
+
// are no-ops)
|
|
25
|
+
//
|
|
26
|
+
// isIdle === all three tokens CLOSED && runningTransitions === 0
|
|
27
|
+
//
|
|
28
|
+
// whenIdle() returns a Promise that resolves the next time isIdle()
|
|
29
|
+
// becomes true and maybeResolveIdle() is invoked. Repeat callers
|
|
30
|
+
// while waiting share one promise.
|
|
31
|
+
//
|
|
32
|
+
// `maybeResolveIdle()` is an explicit method (not auto-called from
|
|
33
|
+
// end*/markX) so the caller can wrap it in `next()` (or any other
|
|
34
|
+
// scheduler) — that defers resolution past the current runloop tick,
|
|
35
|
+
// giving other code in the same tick a chance to start another
|
|
36
|
+
// transition before "idle" is declared.
|
|
37
|
+
class WaiterState {
|
|
38
|
+
constructor() {
|
|
39
|
+
this._transitionToken = null;
|
|
40
|
+
this._stackUpdateToken = null;
|
|
41
|
+
this._initialRenderToken = STACK_WAITER.beginAsync();
|
|
42
|
+
this._runningTransitions = 0;
|
|
43
|
+
this._whenIdlePromise = null;
|
|
44
|
+
this._whenIdleResolve = null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Transition counter
|
|
48
|
+
|
|
49
|
+
beginTransition() {
|
|
50
|
+
this._runningTransitions++;
|
|
51
|
+
if (this._runningTransitions === 1) {
|
|
52
|
+
this._transitionToken = TRANSITION_WAITER.beginAsync();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
endTransition() {
|
|
56
|
+
this._runningTransitions--;
|
|
57
|
+
if (this._runningTransitions < 0) {
|
|
58
|
+
this._runningTransitions = 0;
|
|
59
|
+
}
|
|
60
|
+
if (this._runningTransitions === 0 && this._transitionToken) {
|
|
61
|
+
TRANSITION_WAITER.endAsync(this._transitionToken);
|
|
62
|
+
this._transitionToken = null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
runningTransitions() {
|
|
66
|
+
return this._runningTransitions;
|
|
67
|
+
}
|
|
68
|
+
isRunningTransitions() {
|
|
69
|
+
return this._runningTransitions > 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Stack-update token (coalesced across pushItem/removeItem in one flush)
|
|
73
|
+
|
|
74
|
+
beginStackUpdate() {
|
|
75
|
+
if (!this._stackUpdateToken) {
|
|
76
|
+
this._stackUpdateToken = STACK_WAITER.beginAsync();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
endStackUpdate() {
|
|
80
|
+
if (this._stackUpdateToken) {
|
|
81
|
+
STACK_WAITER.endAsync(this._stackUpdateToken);
|
|
82
|
+
this._stackUpdateToken = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
hasPendingStackUpdate() {
|
|
86
|
+
return !!this._stackUpdateToken;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Initial-render token (open from construction, closed at most once)
|
|
90
|
+
|
|
91
|
+
markInitialRenderComplete() {
|
|
92
|
+
if (this._initialRenderToken) {
|
|
93
|
+
STACK_WAITER.endAsync(this._initialRenderToken);
|
|
94
|
+
this._initialRenderToken = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
hasPendingInitialRender() {
|
|
98
|
+
return !!this._initialRenderToken;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Idle queries + promise
|
|
102
|
+
|
|
103
|
+
isIdle() {
|
|
104
|
+
return this._runningTransitions === 0 && !this._stackUpdateToken && !this._initialRenderToken;
|
|
105
|
+
}
|
|
106
|
+
whenIdle() {
|
|
107
|
+
if (this._whenIdlePromise) {
|
|
108
|
+
return this._whenIdlePromise;
|
|
109
|
+
}
|
|
110
|
+
this._whenIdlePromise = new Promise(resolve => {
|
|
111
|
+
this._whenIdleResolve = resolve;
|
|
112
|
+
});
|
|
113
|
+
return this._whenIdlePromise;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Resolves any outstanding whenIdle() promise if all tokens are closed
|
|
117
|
+
// and no transitions are running. No-op otherwise. Callers schedule this
|
|
118
|
+
// via `next()` (or similar) to defer resolution past the current tick.
|
|
119
|
+
maybeResolveIdle() {
|
|
120
|
+
if (this.isIdle() && this._whenIdleResolve) {
|
|
121
|
+
let resolve = this._whenIdleResolve;
|
|
122
|
+
this._whenIdleResolve = null;
|
|
123
|
+
this._whenIdlePromise = null;
|
|
124
|
+
resolve();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { WaiterState as default };
|
|
130
|
+
//# sourceMappingURL=waiter-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waiter-state.js","sources":["../../src/utils/waiter-state.js"],"sourcesContent":["import { buildWaiter } from '@ember/test-waiters';\n\n// `buildWaiter` registers a named waiter globally in `@ember/test-waiters`.\n// Hoist these to module scope so every WaiterState instance shares the same\n// two waiters — without this, each `new WaiterState()` (notably in unit\n// tests) would register a fresh duplicate, accumulating noise in the global\n// waiter registry over a test run.\nconst TRANSITION_WAITER = buildWaiter('ember-nav-stack:transition');\nconst STACK_WAITER = buildWaiter('ember-nav-stack:stack-update');\n\n// Encapsulates the three test-waiter tokens NavStacks needs to manage\n// (transition, stack-update, initial-render), a counter for currently\n// running transitions, and a single-resolver \"wait until idle\" promise.\n//\n// State diagram:\n//\n// Tokens (each independently OPEN or CLOSED):\n// - transition opens when runningTransitions goes 0 → 1,\n// closes when runningTransitions returns to 0\n// - stackUpdate opens on beginStackUpdate (idempotent),\n// closes on endStackUpdate\n// - initialRender opens once at construction, closes once on\n// markInitialRenderComplete (subsequent calls\n// are no-ops)\n//\n// isIdle === all three tokens CLOSED && runningTransitions === 0\n//\n// whenIdle() returns a Promise that resolves the next time isIdle()\n// becomes true and maybeResolveIdle() is invoked. Repeat callers\n// while waiting share one promise.\n//\n// `maybeResolveIdle()` is an explicit method (not auto-called from\n// end*/markX) so the caller can wrap it in `next()` (or any other\n// scheduler) — that defers resolution past the current runloop tick,\n// giving other code in the same tick a chance to start another\n// transition before \"idle\" is declared.\nexport default class WaiterState {\n constructor() {\n this._transitionToken = null;\n this._stackUpdateToken = null;\n this._initialRenderToken = STACK_WAITER.beginAsync();\n this._runningTransitions = 0;\n this._whenIdlePromise = null;\n this._whenIdleResolve = null;\n }\n\n // Transition counter\n\n beginTransition() {\n this._runningTransitions++;\n if (this._runningTransitions === 1) {\n this._transitionToken = TRANSITION_WAITER.beginAsync();\n }\n }\n\n endTransition() {\n this._runningTransitions--;\n if (this._runningTransitions < 0) {\n this._runningTransitions = 0;\n }\n if (this._runningTransitions === 0 && this._transitionToken) {\n TRANSITION_WAITER.endAsync(this._transitionToken);\n this._transitionToken = null;\n }\n }\n\n runningTransitions() {\n return this._runningTransitions;\n }\n\n isRunningTransitions() {\n return this._runningTransitions > 0;\n }\n\n // Stack-update token (coalesced across pushItem/removeItem in one flush)\n\n beginStackUpdate() {\n if (!this._stackUpdateToken) {\n this._stackUpdateToken = STACK_WAITER.beginAsync();\n }\n }\n\n endStackUpdate() {\n if (this._stackUpdateToken) {\n STACK_WAITER.endAsync(this._stackUpdateToken);\n this._stackUpdateToken = null;\n }\n }\n\n hasPendingStackUpdate() {\n return !!this._stackUpdateToken;\n }\n\n // Initial-render token (open from construction, closed at most once)\n\n markInitialRenderComplete() {\n if (this._initialRenderToken) {\n STACK_WAITER.endAsync(this._initialRenderToken);\n this._initialRenderToken = null;\n }\n }\n\n hasPendingInitialRender() {\n return !!this._initialRenderToken;\n }\n\n // Idle queries + promise\n\n isIdle() {\n return (\n this._runningTransitions === 0 &&\n !this._stackUpdateToken &&\n !this._initialRenderToken\n );\n }\n\n whenIdle() {\n if (this._whenIdlePromise) {\n return this._whenIdlePromise;\n }\n this._whenIdlePromise = new Promise((resolve) => {\n this._whenIdleResolve = resolve;\n });\n return this._whenIdlePromise;\n }\n\n // Resolves any outstanding whenIdle() promise if all tokens are closed\n // and no transitions are running. No-op otherwise. Callers schedule this\n // via `next()` (or similar) to defer resolution past the current tick.\n maybeResolveIdle() {\n if (this.isIdle() && this._whenIdleResolve) {\n let resolve = this._whenIdleResolve;\n this._whenIdleResolve = null;\n this._whenIdlePromise = null;\n resolve();\n }\n }\n}\n"],"names":["TRANSITION_WAITER","buildWaiter","STACK_WAITER","WaiterState","constructor","_transitionToken","_stackUpdateToken","_initialRenderToken","beginAsync","_runningTransitions","_whenIdlePromise","_whenIdleResolve","beginTransition","endTransition","endAsync","runningTransitions","isRunningTransitions","beginStackUpdate","endStackUpdate","hasPendingStackUpdate","markInitialRenderComplete","hasPendingInitialRender","isIdle","whenIdle","Promise","resolve","maybeResolveIdle"],"mappings":"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"}
|