@jsenv/navi 0.12.8 → 0.12.10
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/dist/jsenv_navi.js +1505 -1809
- package/dist/jsenv_navi.js.map +118 -89
- package/dist/jsenv_navi_side_effects.js +2 -0
- package/dist/jsenv_navi_side_effects.js.map +2 -2
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { installImportMetaCss } from "./jsenv_navi_side_effects.js";
|
|
2
|
-
import { createIterableWeakSet, createPubSub, createValueEffect, createStyleController, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, resolveCSSColor, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, activeElementSignal, canInterceptKeys, createGroupTransitionController,
|
|
2
|
+
import { createIterableWeakSet, createPubSub, createValueEffect, createStyleController, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, resolveCSSColor, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, activeElementSignal, canInterceptKeys, createGroupTransitionController, getElementSignature, getBorderRadius, getBackground, preventIntermediateScrollbar, createOpacityTransition, stringifyStyle, mergeOneStyle, mergeTwoStyles, appendStyles, normalizeStyles, resolveCSSSize, findBefore, findAfter, initFocusGroup, elementIsFocusable, pickLightOrDark, resolveColorLuminance, dragAfterThreshold, getScrollContainer, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
|
|
3
3
|
import { prefixFirstAndIndentRemainingLines } from "@jsenv/humanize";
|
|
4
4
|
import { effect, signal, computed, batch, useSignal } from "@preact/signals";
|
|
5
5
|
import { useEffect, useRef, useCallback, useContext, useState, useLayoutEffect, useMemo, useErrorBoundary, useImperativeHandle, useId } from "preact/hooks";
|
|
6
6
|
import { createContext, toChildArray, createRef, cloneElement } from "preact";
|
|
7
|
-
import {
|
|
7
|
+
import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
|
|
8
8
|
import { createPortal, forwardRef } from "preact/compat";
|
|
9
9
|
|
|
10
10
|
const actionPrivatePropertiesWeakMap = new WeakMap();
|
|
@@ -614,9 +614,9 @@ const weakEffect = (values, callback) => {
|
|
|
614
614
|
return dispose;
|
|
615
615
|
};
|
|
616
616
|
|
|
617
|
-
let DEBUG$
|
|
617
|
+
let DEBUG$2 = false;
|
|
618
618
|
const enableDebugActions = () => {
|
|
619
|
-
DEBUG$
|
|
619
|
+
DEBUG$2 = true;
|
|
620
620
|
};
|
|
621
621
|
|
|
622
622
|
let dispatchActions = (params) => {
|
|
@@ -680,7 +680,7 @@ const prerunProtectionRegistry = (() => {
|
|
|
680
680
|
if (protection) {
|
|
681
681
|
clearTimeout(protection.timeoutId);
|
|
682
682
|
protectedActionMap.delete(action);
|
|
683
|
-
if (DEBUG$
|
|
683
|
+
if (DEBUG$2) {
|
|
684
684
|
const elapsed = Date.now() - protection.timestamp;
|
|
685
685
|
console.debug(`"${action}": GC protection removed after ${elapsed}ms`);
|
|
686
686
|
}
|
|
@@ -698,7 +698,7 @@ const prerunProtectionRegistry = (() => {
|
|
|
698
698
|
const timestamp = Date.now();
|
|
699
699
|
const timeoutId = setTimeout(() => {
|
|
700
700
|
unprotect(action);
|
|
701
|
-
if (DEBUG$
|
|
701
|
+
if (DEBUG$2) {
|
|
702
702
|
console.debug(
|
|
703
703
|
`"${action}": prerun protection expired after ${PROTECTION_DURATION}ms`,
|
|
704
704
|
);
|
|
@@ -707,7 +707,7 @@ const prerunProtectionRegistry = (() => {
|
|
|
707
707
|
|
|
708
708
|
protectedActionMap.set(action, { timeoutId, timestamp });
|
|
709
709
|
|
|
710
|
-
if (DEBUG$
|
|
710
|
+
if (DEBUG$2) {
|
|
711
711
|
console.debug(
|
|
712
712
|
`"${action}": protected from GC for ${PROTECTION_DURATION}ms`,
|
|
713
713
|
);
|
|
@@ -818,7 +818,7 @@ const updateActions = ({
|
|
|
818
818
|
|
|
819
819
|
const { runningSet, settledSet } = getActivationInfo();
|
|
820
820
|
|
|
821
|
-
if (DEBUG$
|
|
821
|
+
if (DEBUG$2) {
|
|
822
822
|
let argSource = `reason: \`${reason}\``;
|
|
823
823
|
if (isReplace) {
|
|
824
824
|
argSource += `, isReplace: true`;
|
|
@@ -942,7 +942,7 @@ ${lines.join("\n")}`,
|
|
|
942
942
|
}
|
|
943
943
|
}
|
|
944
944
|
}
|
|
945
|
-
if (DEBUG$
|
|
945
|
+
if (DEBUG$2) {
|
|
946
946
|
const lines = [
|
|
947
947
|
...(willResetSet.size
|
|
948
948
|
? [formatActionSet(willResetSet, "- will reset:")]
|
|
@@ -1038,7 +1038,7 @@ ${lines.join("\n")}`);
|
|
|
1038
1038
|
actionToPromotePrivateProperties.isPrerunSignal.value = false;
|
|
1039
1039
|
}
|
|
1040
1040
|
}
|
|
1041
|
-
if (DEBUG$
|
|
1041
|
+
if (DEBUG$2) {
|
|
1042
1042
|
console.groupEnd();
|
|
1043
1043
|
}
|
|
1044
1044
|
|
|
@@ -1149,7 +1149,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
1149
1149
|
if (!actionAbort) {
|
|
1150
1150
|
return false;
|
|
1151
1151
|
}
|
|
1152
|
-
if (DEBUG$
|
|
1152
|
+
if (DEBUG$2) {
|
|
1153
1153
|
console.log(`"${action}": aborting (reason: ${reason})`);
|
|
1154
1154
|
}
|
|
1155
1155
|
actionAbort(reason);
|
|
@@ -1421,7 +1421,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
1421
1421
|
if (isPrerun && (globalAbortSignal.aborted || abortSignal.aborted)) {
|
|
1422
1422
|
prerunProtectionRegistry.unprotect(action);
|
|
1423
1423
|
}
|
|
1424
|
-
if (DEBUG$
|
|
1424
|
+
if (DEBUG$2) {
|
|
1425
1425
|
console.log(`"${action}": aborted (reason: ${abortReason})`);
|
|
1426
1426
|
}
|
|
1427
1427
|
};
|
|
@@ -1494,7 +1494,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
1494
1494
|
onComplete?.(computedDataSignal.peek(), action);
|
|
1495
1495
|
completeSideEffect?.(action);
|
|
1496
1496
|
});
|
|
1497
|
-
if (DEBUG$
|
|
1497
|
+
if (DEBUG$2) {
|
|
1498
1498
|
console.log(`"${action}": completed`);
|
|
1499
1499
|
}
|
|
1500
1500
|
return computedDataSignal.peek();
|
|
@@ -1521,7 +1521,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
1521
1521
|
"never supposed to happen, abort error should be handled by the abort signal",
|
|
1522
1522
|
);
|
|
1523
1523
|
}
|
|
1524
|
-
if (DEBUG$
|
|
1524
|
+
if (DEBUG$2) {
|
|
1525
1525
|
console.log(
|
|
1526
1526
|
`"${action}": failed (error: ${e}, handled by ui: ${ui.hasRenderers})`,
|
|
1527
1527
|
);
|
|
@@ -1591,7 +1591,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
1591
1591
|
|
|
1592
1592
|
const performStop = ({ reason }) => {
|
|
1593
1593
|
abort(reason);
|
|
1594
|
-
if (DEBUG$
|
|
1594
|
+
if (DEBUG$2) {
|
|
1595
1595
|
console.log(`"${action}": stopping (reason: ${reason})`);
|
|
1596
1596
|
}
|
|
1597
1597
|
|
|
@@ -5212,11 +5212,11 @@ const useExternalValueSync = (
|
|
|
5212
5212
|
}
|
|
5213
5213
|
};
|
|
5214
5214
|
|
|
5215
|
-
const UNSET = {};
|
|
5215
|
+
const UNSET$1 = {};
|
|
5216
5216
|
const useInitialValue = (compute) => {
|
|
5217
|
-
const initialValueRef = useRef(UNSET);
|
|
5217
|
+
const initialValueRef = useRef(UNSET$1);
|
|
5218
5218
|
let initialValue = initialValueRef.current;
|
|
5219
|
-
if (initialValue !== UNSET) {
|
|
5219
|
+
if (initialValue !== UNSET$1) {
|
|
5220
5220
|
return initialValue;
|
|
5221
5221
|
}
|
|
5222
5222
|
|
|
@@ -8013,9 +8013,9 @@ const executeWithCleanup = (fn, cleanup) => {
|
|
|
8013
8013
|
}
|
|
8014
8014
|
};
|
|
8015
8015
|
|
|
8016
|
-
let DEBUG$
|
|
8016
|
+
let DEBUG$1 = false;
|
|
8017
8017
|
const enableDebugOnDocumentLoading = () => {
|
|
8018
|
-
DEBUG$
|
|
8018
|
+
DEBUG$1 = true;
|
|
8019
8019
|
};
|
|
8020
8020
|
|
|
8021
8021
|
const windowIsLoadingSignal = signal(true);
|
|
@@ -8035,13 +8035,13 @@ const [
|
|
|
8035
8035
|
removeFromDocumentLoadingRouteArraySignal,
|
|
8036
8036
|
] = arraySignal([]);
|
|
8037
8037
|
const routingWhile = (fn, routeNames = []) => {
|
|
8038
|
-
if (DEBUG$
|
|
8038
|
+
if (DEBUG$1 && routeNames.length > 0) {
|
|
8039
8039
|
console.debug(`routingWhile: Adding routes to loading state:`, routeNames);
|
|
8040
8040
|
}
|
|
8041
8041
|
addToDocumentLoadingRouteArraySignal(...routeNames);
|
|
8042
8042
|
return executeWithCleanup(fn, () => {
|
|
8043
8043
|
removeFromDocumentLoadingRouteArraySignal(...routeNames);
|
|
8044
|
-
if (DEBUG$
|
|
8044
|
+
if (DEBUG$1 && routeNames.length > 0) {
|
|
8045
8045
|
console.debug(
|
|
8046
8046
|
`routingWhile: Removed routes from loading state:`,
|
|
8047
8047
|
routeNames,
|
|
@@ -8058,7 +8058,7 @@ const [
|
|
|
8058
8058
|
removeFromDocumentLoadingActionArraySignal,
|
|
8059
8059
|
] = arraySignal([]);
|
|
8060
8060
|
const workingWhile = (fn, actionNames = []) => {
|
|
8061
|
-
if (DEBUG$
|
|
8061
|
+
if (DEBUG$1 && actionNames.length > 0) {
|
|
8062
8062
|
console.debug(
|
|
8063
8063
|
`workingWhile: Adding actions to loading state:`,
|
|
8064
8064
|
actionNames,
|
|
@@ -8067,7 +8067,7 @@ const workingWhile = (fn, actionNames = []) => {
|
|
|
8067
8067
|
addToDocumentLoadingActionArraySignal(...actionNames);
|
|
8068
8068
|
return executeWithCleanup(fn, () => {
|
|
8069
8069
|
removeFromDocumentLoadingActionArraySignal(...actionNames);
|
|
8070
|
-
if (DEBUG$
|
|
8070
|
+
if (DEBUG$1 && actionNames.length > 0) {
|
|
8071
8071
|
console.debug(
|
|
8072
8072
|
`routingWhile: Removed action from loading state:`,
|
|
8073
8073
|
actionNames,
|
|
@@ -8585,1104 +8585,807 @@ const useUrlSearchParam = (paramName) => {
|
|
|
8585
8585
|
return [value, setSearchParamValue];
|
|
8586
8586
|
};
|
|
8587
8587
|
|
|
8588
|
+
/**
|
|
8589
|
+
* Fix alignment behavior for flex/grid containers that use `height: 100%`.
|
|
8590
|
+
*
|
|
8591
|
+
* Context:
|
|
8592
|
+
* - When a flex/grid container has `height: 100%`, it is "height-locked".
|
|
8593
|
+
* - If its content becomes taller than the container, alignment rules like
|
|
8594
|
+
* `align-items: center` will cause content to be partially clipped.
|
|
8595
|
+
*
|
|
8596
|
+
* Goal:
|
|
8597
|
+
* - Center content only when it fits.
|
|
8598
|
+
* - Align content at start when it overflows.
|
|
8599
|
+
*
|
|
8600
|
+
* How:
|
|
8601
|
+
* - Temporarily remove height-constraint (`height:auto`) to measure natural height.
|
|
8602
|
+
* - Compare natural height to container height.
|
|
8603
|
+
* - Add/remove an attribute so CSS can adapt alignment.
|
|
8604
|
+
*
|
|
8605
|
+
* Usage:
|
|
8606
|
+
* monitorItemsOverflow(containerElement);
|
|
8607
|
+
*
|
|
8608
|
+
* CSS example:
|
|
8609
|
+
* .container { align-items: center; }
|
|
8610
|
+
* .container[data-items-height-overflow] { align-items: flex-start; }
|
|
8611
|
+
*/
|
|
8612
|
+
|
|
8613
|
+
|
|
8614
|
+
const WIDTH_ATTRIBUTE_NAME = "data-items-width-overflow";
|
|
8615
|
+
const HEIGHT_ATTRIBUTE_NAME = "data-items-height-overflow";
|
|
8616
|
+
const monitorItemsOverflow = (container) => {
|
|
8617
|
+
let widthIsOverflowing;
|
|
8618
|
+
let heightIsOverflowing;
|
|
8619
|
+
const onItemsWidthOverflowChange = () => {
|
|
8620
|
+
if (widthIsOverflowing) {
|
|
8621
|
+
container.setAttribute(WIDTH_ATTRIBUTE_NAME, "");
|
|
8622
|
+
} else {
|
|
8623
|
+
container.removeAttribute(WIDTH_ATTRIBUTE_NAME);
|
|
8624
|
+
}
|
|
8625
|
+
};
|
|
8626
|
+
const onItemsHeightOverflowChange = () => {
|
|
8627
|
+
if (heightIsOverflowing) {
|
|
8628
|
+
container.setAttribute(HEIGHT_ATTRIBUTE_NAME, "");
|
|
8629
|
+
} else {
|
|
8630
|
+
container.removeAttribute(HEIGHT_ATTRIBUTE_NAME);
|
|
8631
|
+
}
|
|
8632
|
+
};
|
|
8633
|
+
|
|
8634
|
+
const update = () => {
|
|
8635
|
+
// Save current manual height constraint
|
|
8636
|
+
const prevWidth = container.style.width;
|
|
8637
|
+
const prevHeight = container.style.height;
|
|
8638
|
+
// Remove constraint → get true content dimension
|
|
8639
|
+
container.style.width = "auto";
|
|
8640
|
+
container.style.height = "auto";
|
|
8641
|
+
const naturalWidth = container.scrollWidth;
|
|
8642
|
+
const naturalHeight = container.scrollHeight;
|
|
8643
|
+
if (prevWidth) {
|
|
8644
|
+
container.style.width = prevWidth;
|
|
8645
|
+
} else {
|
|
8646
|
+
container.style.removeProperty("width");
|
|
8647
|
+
}
|
|
8648
|
+
if (prevHeight) {
|
|
8649
|
+
container.style.height = prevHeight;
|
|
8650
|
+
} else {
|
|
8651
|
+
container.style.removeProperty("height");
|
|
8652
|
+
}
|
|
8653
|
+
|
|
8654
|
+
const lockedWidth = container.clientWidth;
|
|
8655
|
+
const lockedHeight = container.clientHeight;
|
|
8656
|
+
const currentWidthIsOverflowing = naturalWidth > lockedWidth;
|
|
8657
|
+
const currentHeightIsOverflowing = naturalHeight > lockedHeight;
|
|
8658
|
+
if (currentWidthIsOverflowing !== widthIsOverflowing) {
|
|
8659
|
+
widthIsOverflowing = currentWidthIsOverflowing;
|
|
8660
|
+
onItemsWidthOverflowChange();
|
|
8661
|
+
}
|
|
8662
|
+
if (currentHeightIsOverflowing !== heightIsOverflowing) {
|
|
8663
|
+
heightIsOverflowing = currentHeightIsOverflowing;
|
|
8664
|
+
onItemsHeightOverflowChange();
|
|
8665
|
+
}
|
|
8666
|
+
};
|
|
8667
|
+
|
|
8668
|
+
const [teardown, addTeardown] = createPubSub();
|
|
8669
|
+
|
|
8670
|
+
update();
|
|
8671
|
+
|
|
8672
|
+
// mutation observer
|
|
8673
|
+
const mutationObserver = new MutationObserver(() => {
|
|
8674
|
+
update();
|
|
8675
|
+
});
|
|
8676
|
+
mutationObserver.observe(container, {
|
|
8677
|
+
childList: true,
|
|
8678
|
+
characterData: true,
|
|
8679
|
+
});
|
|
8680
|
+
addTeardown(() => {
|
|
8681
|
+
mutationObserver.disconnect();
|
|
8682
|
+
});
|
|
8683
|
+
|
|
8684
|
+
// resize observer
|
|
8685
|
+
const resizeObserver = new ResizeObserver(update);
|
|
8686
|
+
resizeObserver.observe(container);
|
|
8687
|
+
addTeardown(() => {
|
|
8688
|
+
resizeObserver.disconnect();
|
|
8689
|
+
});
|
|
8690
|
+
|
|
8691
|
+
const destroy = () => {
|
|
8692
|
+
teardown();
|
|
8693
|
+
container.removeAttribute(WIDTH_ATTRIBUTE_NAME);
|
|
8694
|
+
container.removeAttribute(HEIGHT_ATTRIBUTE_NAME);
|
|
8695
|
+
};
|
|
8696
|
+
return destroy;
|
|
8697
|
+
};
|
|
8698
|
+
|
|
8588
8699
|
installImportMetaCss(import.meta);
|
|
8589
8700
|
import.meta.css = /* css */ `
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
/* Either because the transition slides */
|
|
8593
|
-
/* Or when size transition are disabled because we need to immediatly crop old content when it's bigger than new content */
|
|
8594
|
-
overflow: hidden;
|
|
8701
|
+
* {
|
|
8702
|
+
box-sizing: border-box;
|
|
8595
8703
|
}
|
|
8596
8704
|
|
|
8597
|
-
.
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8705
|
+
.ui_transition {
|
|
8706
|
+
--transition-duration: 300ms;
|
|
8707
|
+
--justify-content: center;
|
|
8708
|
+
--align-items: center;
|
|
8709
|
+
|
|
8710
|
+
--x-transition-duration: var(--transition-duration);
|
|
8711
|
+
--x-justify-content: var(--justify-content);
|
|
8712
|
+
--x-align-items: var(--align-items);
|
|
8713
|
+
|
|
8714
|
+
position: relative;
|
|
8715
|
+
}
|
|
8716
|
+
/* Alignment controls */
|
|
8717
|
+
.ui_transition[data-align-x="start"] {
|
|
8718
|
+
--x-justify-content: flex-start;
|
|
8719
|
+
}
|
|
8720
|
+
.ui_transition[data-align-x="center"] {
|
|
8721
|
+
--x-justify-content: center;
|
|
8722
|
+
}
|
|
8723
|
+
.ui_transition[data-align-x="end"] {
|
|
8724
|
+
--x-justify-content: flex-end;
|
|
8725
|
+
}
|
|
8726
|
+
.ui_transition[data-align-y="start"] {
|
|
8727
|
+
--x-align-items: flex-start;
|
|
8728
|
+
}
|
|
8729
|
+
.ui_transition[data-align-y="center"] {
|
|
8730
|
+
--x-align-items: center;
|
|
8731
|
+
}
|
|
8732
|
+
.ui_transition[data-align-y="end"] {
|
|
8733
|
+
--x-align-items: flex-end;
|
|
8612
8734
|
}
|
|
8613
8735
|
|
|
8614
|
-
.
|
|
8736
|
+
.ui_transition,
|
|
8737
|
+
.ui_transition_active_group,
|
|
8738
|
+
.ui_transition_previous_group,
|
|
8739
|
+
.ui_transition_target_slot,
|
|
8740
|
+
.ui_transition_previous_target_slot,
|
|
8741
|
+
.ui_transition_outgoing_slot,
|
|
8742
|
+
.ui_transition_previous_outgoing_slot {
|
|
8615
8743
|
width: 100%;
|
|
8616
|
-
min-width: fit-content;
|
|
8617
8744
|
height: 100%;
|
|
8618
|
-
min-height: fit-content;
|
|
8619
|
-
flex-direction: column;
|
|
8620
8745
|
}
|
|
8621
8746
|
|
|
8622
|
-
.
|
|
8623
|
-
.
|
|
8624
|
-
|
|
8747
|
+
.ui_transition_target_slot,
|
|
8748
|
+
.ui_transition_outgoing_slot,
|
|
8749
|
+
.ui_transition_previous_target_slot,
|
|
8750
|
+
.ui_transition_previous_outgoing_slot {
|
|
8751
|
+
display: flex;
|
|
8752
|
+
align-items: var(--x-align-items);
|
|
8753
|
+
justify-content: var(--x-justify-content);
|
|
8754
|
+
}
|
|
8755
|
+
.ui_transition_target_slot[data-items-width-overflow],
|
|
8756
|
+
.ui_transition_previous_target_slot[data-items-width-overflow],
|
|
8757
|
+
.ui_transition_previous_target_slot[data-items-width-overflow],
|
|
8758
|
+
.ui_transition_previous_outgoing_slot[data-items-width-overflow] {
|
|
8759
|
+
--x-justify-content: flex-start;
|
|
8760
|
+
}
|
|
8761
|
+
.ui_transition_target_slot[data-items-height-overflow],
|
|
8762
|
+
.ui_transition_previous_slot[data-items-height-overflow],
|
|
8763
|
+
.ui_transition_previous_target_slot[data-items-height-overflow],
|
|
8764
|
+
.ui_transition_previous_outgoing_slot[data-items-height-overflow] {
|
|
8765
|
+
--x-align-items: flex-start;
|
|
8625
8766
|
}
|
|
8626
8767
|
|
|
8627
|
-
.
|
|
8628
|
-
|
|
8768
|
+
.ui_transition_active_group {
|
|
8769
|
+
position: relative;
|
|
8770
|
+
}
|
|
8771
|
+
.ui_transition_target_slot {
|
|
8772
|
+
position: relative;
|
|
8773
|
+
}
|
|
8774
|
+
.ui_transition_outgoing_slot,
|
|
8775
|
+
.ui_transition_previous_outgoing_slot {
|
|
8776
|
+
position: absolute;
|
|
8777
|
+
top: 0;
|
|
8778
|
+
left: 0;
|
|
8779
|
+
}
|
|
8780
|
+
.ui_transition_previous_group {
|
|
8629
8781
|
position: absolute;
|
|
8630
8782
|
inset: 0;
|
|
8783
|
+
}
|
|
8784
|
+
.ui_transition[data-only-previous-group] .ui_transition_previous_group {
|
|
8785
|
+
position: relative;
|
|
8786
|
+
}
|
|
8787
|
+
|
|
8788
|
+
.ui_transition_target_slot_background {
|
|
8789
|
+
position: absolute;
|
|
8790
|
+
top: 0;
|
|
8791
|
+
left: 0;
|
|
8792
|
+
z-index: -1;
|
|
8793
|
+
display: none;
|
|
8794
|
+
width: var(--target-slot-width, 100%);
|
|
8795
|
+
height: var(--target-slot-height, 100%);
|
|
8796
|
+
background: var(--target-slot-background, transparent);
|
|
8631
8797
|
pointer-events: none;
|
|
8632
8798
|
}
|
|
8799
|
+
.ui_transition[data-transitioning] .ui_transition_target_slot_background {
|
|
8800
|
+
display: block;
|
|
8801
|
+
}
|
|
8633
8802
|
`;
|
|
8634
8803
|
|
|
8635
|
-
const
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
8804
|
+
const CONTENT_ID_ATTRIBUTE = "data-content-id";
|
|
8805
|
+
const CONTENT_PHASE_ATTRIBUTE = "data-content-phase";
|
|
8806
|
+
const UNSET = {
|
|
8807
|
+
domNodes: [],
|
|
8808
|
+
domNodesClone: [],
|
|
8809
|
+
isEmpty: true,
|
|
8641
8810
|
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8811
|
+
type: "unset",
|
|
8812
|
+
contentId: "unset",
|
|
8813
|
+
contentPhase: undefined,
|
|
8814
|
+
isContentPhase: false,
|
|
8815
|
+
isContent: false,
|
|
8816
|
+
toString: () => "unset",
|
|
8817
|
+
};
|
|
8648
8818
|
|
|
8649
|
-
const
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
return { cleanup: () => {} };
|
|
8653
|
-
}
|
|
8819
|
+
const isSameConfiguration = (configA, configB) => {
|
|
8820
|
+
return configA.toString() === configB.toString();
|
|
8821
|
+
};
|
|
8654
8822
|
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8823
|
+
const createUITransitionController = (
|
|
8824
|
+
root,
|
|
8825
|
+
{
|
|
8826
|
+
duration = 300,
|
|
8827
|
+
alignX = "center",
|
|
8828
|
+
alignY = "center",
|
|
8829
|
+
onStateChange = () => {},
|
|
8830
|
+
pauseBreakpoints = [],
|
|
8831
|
+
} = {},
|
|
8832
|
+
) => {
|
|
8833
|
+
const debugConfig = {
|
|
8834
|
+
detection: root.hasAttribute("data-debug-detection"),
|
|
8835
|
+
size: root.hasAttribute("data-debug-size"),
|
|
8660
8836
|
};
|
|
8661
|
-
const
|
|
8662
|
-
|
|
8663
|
-
|
|
8664
|
-
|
|
8665
|
-
|
|
8666
|
-
)
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
console.debug(`[${type}]`, ...args);
|
|
8670
|
-
}
|
|
8837
|
+
const hasDebugLogs = debugConfig.size;
|
|
8838
|
+
const debugDetection = (message) => {
|
|
8839
|
+
if (!debugConfig.detection) return;
|
|
8840
|
+
console.debug(`[detection]`, message);
|
|
8841
|
+
};
|
|
8842
|
+
const debugSize = (message) => {
|
|
8843
|
+
if (!debugConfig.size) return;
|
|
8844
|
+
console.debug(`[size]`, message);
|
|
8671
8845
|
};
|
|
8672
8846
|
|
|
8673
|
-
const
|
|
8674
|
-
const
|
|
8675
|
-
const
|
|
8676
|
-
|
|
8847
|
+
const activeGroup = root.querySelector(".ui_transition_active_group");
|
|
8848
|
+
const targetSlot = root.querySelector(".ui_transition_target_slot");
|
|
8849
|
+
const outgoingSlot = root.querySelector(".ui_transition_outgoing_slot");
|
|
8850
|
+
const previousGroup = root.querySelector(".ui_transition_previous_group");
|
|
8851
|
+
const previousTargetSlot = previousGroup?.querySelector(
|
|
8852
|
+
".ui_transition_previous_target_slot",
|
|
8677
8853
|
);
|
|
8678
|
-
const
|
|
8679
|
-
".
|
|
8854
|
+
const previousOutgoingSlot = previousGroup?.querySelector(
|
|
8855
|
+
".ui_transition_previous_outgoing_slot",
|
|
8680
8856
|
);
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8857
|
+
|
|
8858
|
+
if (
|
|
8859
|
+
!root ||
|
|
8860
|
+
!activeGroup ||
|
|
8861
|
+
!targetSlot ||
|
|
8862
|
+
!outgoingSlot ||
|
|
8863
|
+
!previousGroup ||
|
|
8864
|
+
!previousTargetSlot ||
|
|
8865
|
+
!previousOutgoingSlot
|
|
8866
|
+
) {
|
|
8867
|
+
throw new Error(
|
|
8868
|
+
"createUITransitionController requires element with .active_group, .target_slot, .outgoing_slot, .previous_group, .previous_target_slot, and .previous_outgoing_slot elements",
|
|
8869
|
+
);
|
|
8684
8870
|
}
|
|
8685
8871
|
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
);
|
|
8692
|
-
const transitionController = createGroupTransitionController();
|
|
8693
|
-
const setupTransition = ({
|
|
8694
|
-
isPhaseTransition = false,
|
|
8695
|
-
overlay,
|
|
8696
|
-
needsOldChildNodesClone,
|
|
8697
|
-
previousChildNodes,
|
|
8698
|
-
childNodes,
|
|
8699
|
-
slotInfo,
|
|
8700
|
-
attributeToRemove = [],
|
|
8701
|
-
}) => {
|
|
8702
|
-
let cleanup = () => {};
|
|
8703
|
-
let elementToImpact;
|
|
8872
|
+
// we maintain a background copy behind target slot to avoid showing
|
|
8873
|
+
// the body flashing during the fade-in
|
|
8874
|
+
const targetSlotBackground = document.createElement("div");
|
|
8875
|
+
targetSlotBackground.className = "ui_transition_target_slot_background";
|
|
8876
|
+
activeGroup.insertBefore(targetSlotBackground, targetSlot);
|
|
8704
8877
|
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
if (!debugClones) {
|
|
8709
|
-
overlay.innerHTML = "";
|
|
8710
|
-
}
|
|
8711
|
-
};
|
|
8712
|
-
debug(
|
|
8713
|
-
"content",
|
|
8714
|
-
`Continuing from current ${isPhaseTransition ? "phase" : "content"} transition element`,
|
|
8715
|
-
);
|
|
8716
|
-
} else if (needsOldChildNodesClone) {
|
|
8717
|
-
overlay.innerHTML = "";
|
|
8718
|
-
for (const previousChildNode of previousChildNodes) {
|
|
8719
|
-
const previousChildClone = previousChildNode.cloneNode(true);
|
|
8720
|
-
if (previousChildClone.nodeType !== Node.TEXT_NODE) {
|
|
8721
|
-
for (const attrToRemove of attributeToRemove) {
|
|
8722
|
-
previousChildClone.removeAttribute(attrToRemove);
|
|
8723
|
-
}
|
|
8724
|
-
previousChildClone.setAttribute("data-ui-transition-clone", "");
|
|
8725
|
-
}
|
|
8726
|
-
overlay.appendChild(previousChildClone);
|
|
8727
|
-
}
|
|
8728
|
-
elementToImpact = overlay;
|
|
8729
|
-
cleanup = () => {
|
|
8730
|
-
if (!debugClones) {
|
|
8731
|
-
overlay.innerHTML = "";
|
|
8732
|
-
}
|
|
8733
|
-
};
|
|
8734
|
-
debug(
|
|
8735
|
-
"content",
|
|
8736
|
-
`Cloned previous child for ${isPhaseTransition ? "phase" : "content"} transition:`,
|
|
8737
|
-
getElementSignature(previousChildNodes),
|
|
8738
|
-
);
|
|
8739
|
-
if (debugBreakAfterClone === slotInfo.contentKey) {
|
|
8740
|
-
debugger;
|
|
8741
|
-
}
|
|
8742
|
-
} else {
|
|
8743
|
-
overlay.innerHTML = "";
|
|
8744
|
-
debug(
|
|
8745
|
-
"content",
|
|
8746
|
-
`No old child to clone for ${isPhaseTransition ? "phase" : "content"} transition`,
|
|
8747
|
-
);
|
|
8748
|
-
}
|
|
8878
|
+
root.style.setProperty("--x-transition-duration", `${duration}ms`);
|
|
8879
|
+
outgoingSlot.setAttribute("inert", "");
|
|
8880
|
+
previousGroup.setAttribute("inert", "");
|
|
8749
8881
|
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
let newElement;
|
|
8755
|
-
if (isPhaseTransition) {
|
|
8756
|
-
// Phase transitions work on individual elements
|
|
8757
|
-
oldElement = elementToImpact;
|
|
8758
|
-
newElement = slot;
|
|
8759
|
-
} else {
|
|
8760
|
-
// Content transitions work at container level and can outlive content phase changes
|
|
8761
|
-
oldElement = previousChildNodes.length ? elementToImpact : null;
|
|
8762
|
-
newElement = childNodes.length ? slot : null;
|
|
8882
|
+
const detectConfiguration = (slot, { contentId, contentPhase } = {}) => {
|
|
8883
|
+
const domNodes = Array.from(slot.childNodes);
|
|
8884
|
+
if (!domNodes) {
|
|
8885
|
+
return UNSET;
|
|
8763
8886
|
}
|
|
8764
8887
|
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
const [publishResume, addResumeCallback] = createPubSub();
|
|
8774
|
-
|
|
8775
|
-
const [publishChange, subscribeChange] = createPubSub();
|
|
8776
|
-
let triggerChildSlotMutation;
|
|
8777
|
-
let previousSlotInfo;
|
|
8778
|
-
let slotInfo;
|
|
8779
|
-
let changeInfo;
|
|
8780
|
-
{
|
|
8781
|
-
const createSlotInfo = (childNodes, { contentKey, contentPhase }) => {
|
|
8782
|
-
const hasChild = childNodes.length > 0;
|
|
8783
|
-
let contentKeyFormatted;
|
|
8784
|
-
let contentName;
|
|
8785
|
-
if (hasChild) {
|
|
8786
|
-
if (contentKey) {
|
|
8787
|
-
contentKeyFormatted = `[data-content-key="${contentKey}"]`;
|
|
8788
|
-
} else {
|
|
8789
|
-
let onlyTextNodes = true;
|
|
8790
|
-
for (const child of childNodes) {
|
|
8791
|
-
if (child.nodeType !== Node.TEXT_NODE) {
|
|
8792
|
-
onlyTextNodes = false;
|
|
8793
|
-
break;
|
|
8794
|
-
}
|
|
8795
|
-
}
|
|
8796
|
-
contentKeyFormatted = onlyTextNodes ? "[text]" : "[unkeyed]";
|
|
8797
|
-
}
|
|
8798
|
-
contentName = contentPhase ? "content-phase" : "content";
|
|
8799
|
-
} else {
|
|
8800
|
-
contentKeyFormatted = "[empty]";
|
|
8801
|
-
contentName = "null";
|
|
8802
|
-
}
|
|
8803
|
-
|
|
8804
|
-
return {
|
|
8805
|
-
childNodes,
|
|
8806
|
-
contentKey,
|
|
8807
|
-
contentPhase,
|
|
8808
|
-
|
|
8809
|
-
hasChild: childNodes.length > 0,
|
|
8810
|
-
contentKeyFormatted,
|
|
8811
|
-
isContentPhase: Boolean(contentPhase),
|
|
8812
|
-
contentName,
|
|
8813
|
-
};
|
|
8814
|
-
};
|
|
8815
|
-
previousSlotInfo = createSlotInfo([], {
|
|
8816
|
-
contentKey: undefined,
|
|
8817
|
-
contentPhase: undefined,
|
|
8818
|
-
});
|
|
8819
|
-
slotInfo = previousSlotInfo;
|
|
8820
|
-
let isUpdating = false;
|
|
8821
|
-
triggerChildSlotMutation = (reason) => {
|
|
8822
|
-
if (isUpdating) {
|
|
8823
|
-
debug("detection", "Preventing recursive update");
|
|
8824
|
-
return;
|
|
8888
|
+
const isEmpty = domNodes.length === 0;
|
|
8889
|
+
let textNodeCount = 0;
|
|
8890
|
+
let elementNodeCount = 0;
|
|
8891
|
+
let firstElementNode;
|
|
8892
|
+
const domNodesClone = [];
|
|
8893
|
+
if (isEmpty) {
|
|
8894
|
+
if (contentPhase === undefined) {
|
|
8895
|
+
contentPhase = "empty";
|
|
8825
8896
|
}
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
: childNodes.length === 1
|
|
8833
|
-
? getElementSignature(childNodes[0])
|
|
8834
|
-
: getElementSignature(slot);
|
|
8835
|
-
console.group(`UI Update: ${updateLabel} (reason: ${reason})`);
|
|
8836
|
-
}
|
|
8837
|
-
updateSlotChangeInfo(childNodes, reason);
|
|
8838
|
-
if (changeInfo.isStateChangeOnly) {
|
|
8897
|
+
} else {
|
|
8898
|
+
const contentIdSlotAttr = slot.getAttribute(CONTENT_ID_ATTRIBUTE);
|
|
8899
|
+
let contentIdChildAttr;
|
|
8900
|
+
for (const domNode of domNodes) {
|
|
8901
|
+
if (domNode.nodeType === Node.TEXT_NODE) {
|
|
8902
|
+
textNodeCount++;
|
|
8839
8903
|
} else {
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
if (
|
|
8843
|
-
changeInfo.isInitialPopulationWithoutTransition ||
|
|
8844
|
-
changeInfo.becomesPopulated
|
|
8845
|
-
) {
|
|
8846
|
-
hasPopulatedOnce = true;
|
|
8904
|
+
if (!firstElementNode) {
|
|
8905
|
+
firstElementNode = domNode;
|
|
8847
8906
|
}
|
|
8848
|
-
|
|
8849
|
-
} finally {
|
|
8850
|
-
isUpdating = false;
|
|
8851
|
-
if (hasSomeDebugLogs) {
|
|
8852
|
-
console.groupEnd();
|
|
8853
|
-
}
|
|
8854
|
-
}
|
|
8855
|
-
};
|
|
8907
|
+
elementNodeCount++;
|
|
8856
8908
|
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
let contentPhase;
|
|
8861
|
-
if (currentChildNodes.length === 0) {
|
|
8862
|
-
contentPhase = true; // empty treated as phase
|
|
8863
|
-
} else {
|
|
8864
|
-
for (const childNode of currentChildNodes) {
|
|
8865
|
-
if (childNode.nodeType === Node.TEXT_NODE) {
|
|
8866
|
-
continue;
|
|
8867
|
-
}
|
|
8868
|
-
if (childNode.hasAttribute("data-content-phase")) {
|
|
8869
|
-
const contentPhaseAttr =
|
|
8870
|
-
childNode.getAttribute("data-content-phase");
|
|
8871
|
-
contentPhase = contentPhaseAttr || true;
|
|
8909
|
+
if (domNode.hasAttribute("data-content-phase")) {
|
|
8910
|
+
const contentPhaseAttr = domNode.getAttribute("data-content-phase");
|
|
8911
|
+
contentPhase = contentPhaseAttr || "attr";
|
|
8872
8912
|
}
|
|
8873
|
-
if (
|
|
8874
|
-
|
|
8913
|
+
if (domNode.hasAttribute("data-content-key")) {
|
|
8914
|
+
contentIdChildAttr = domNode.getAttribute("data-content-key");
|
|
8875
8915
|
}
|
|
8876
8916
|
}
|
|
8917
|
+
const domNodeClone = domNode.cloneNode(true);
|
|
8918
|
+
domNodesClone.push(domNodeClone);
|
|
8877
8919
|
}
|
|
8878
|
-
|
|
8879
|
-
if (
|
|
8920
|
+
|
|
8921
|
+
if (contentIdSlotAttr && contentIdChildAttr) {
|
|
8880
8922
|
console.warn(
|
|
8881
|
-
`Slot and slot child both have a [
|
|
8923
|
+
`Slot and slot child both have a [${CONTENT_ID_ATTRIBUTE}]. Slot is ${contentIdSlotAttr} and child is ${contentIdChildAttr}, using the child.`,
|
|
8882
8924
|
);
|
|
8883
8925
|
}
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8926
|
+
if (contentId === undefined) {
|
|
8927
|
+
contentId = contentIdChildAttr || contentIdSlotAttr || undefined;
|
|
8928
|
+
}
|
|
8929
|
+
}
|
|
8930
|
+
const isOnlyTextNodes = elementNodeCount === 0 && textNodeCount > 1;
|
|
8931
|
+
const singleElementNode = elementNodeCount === 1 ? firstElementNode : null;
|
|
8932
|
+
|
|
8933
|
+
contentId = contentId || getElementSignature(domNodes[0]);
|
|
8934
|
+
if (!contentPhase && isEmpty) {
|
|
8935
|
+
// Imagine code rendering null while switching to a new content
|
|
8936
|
+
// or even while staying on the same content.
|
|
8937
|
+
// In the UI we want to consider this as an "empty" phase.
|
|
8938
|
+
// meaning the ui will keep the same size until something else happens
|
|
8939
|
+
// This prevent layout shifts of code not properly handling
|
|
8940
|
+
// intermediate states.
|
|
8941
|
+
contentPhase = "empty";
|
|
8942
|
+
}
|
|
8943
|
+
|
|
8944
|
+
let width;
|
|
8945
|
+
let height;
|
|
8946
|
+
let borderRadius;
|
|
8947
|
+
let border;
|
|
8948
|
+
let background;
|
|
8949
|
+
|
|
8950
|
+
if (isEmpty) {
|
|
8951
|
+
debugSize(`measureSlot(".${slot.className}") -> it is empty`);
|
|
8952
|
+
} else if (singleElementNode) {
|
|
8953
|
+
const rect = singleElementNode.getBoundingClientRect();
|
|
8954
|
+
width = rect.width;
|
|
8955
|
+
height = rect.height;
|
|
8956
|
+
debugSize(`measureSlot(".${slot.className}") -> [${width}x${height}]`);
|
|
8957
|
+
borderRadius = getBorderRadius(singleElementNode);
|
|
8958
|
+
border = getComputedStyle(singleElementNode).border;
|
|
8959
|
+
background = getBackground(singleElementNode);
|
|
8960
|
+
} else {
|
|
8961
|
+
// text, multiple elements
|
|
8962
|
+
const rect = slot.getBoundingClientRect();
|
|
8963
|
+
width = rect.width;
|
|
8964
|
+
height = rect.height;
|
|
8965
|
+
debugSize(`measureSlot(".${slot.className}") -> [${width}x${height}]`);
|
|
8966
|
+
}
|
|
8889
8967
|
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
|
|
8893
|
-
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
!shouldDoPhaseTransition &&
|
|
8915
|
-
!becomesPopulated &&
|
|
8916
|
-
!becomesEmpty;
|
|
8917
|
-
const shouldDoContentTransitionIncludingPopulation =
|
|
8918
|
-
shouldDoContentTransition ||
|
|
8919
|
-
(becomesPopulated && !shouldDoPhaseTransition);
|
|
8920
|
-
// nothing to transition if no previous and no current child
|
|
8921
|
-
// (Either it's the initial call or just content-key changes but there is no child yet)
|
|
8922
|
-
const isStateChangeOnly = !hadChild && !hasChild;
|
|
8923
|
-
if (isStateChangeOnly) {
|
|
8924
|
-
const prevKey = previousSlotInfo.contentKey;
|
|
8925
|
-
const keyIsTheSame = prevKey === contentKey;
|
|
8926
|
-
if (keyIsTheSame) {
|
|
8927
|
-
debug(
|
|
8928
|
-
"detection",
|
|
8929
|
-
`Childless change: no changes found -> do nothing and skip transitions`,
|
|
8930
|
-
);
|
|
8931
|
-
} else if (!prevKey && contentKey) {
|
|
8932
|
-
debug(
|
|
8933
|
-
"detection",
|
|
8934
|
-
`Childless change: ${contentKey} added -> registering it and skip transitions`,
|
|
8935
|
-
);
|
|
8936
|
-
} else if (prevKey && !contentKey) {
|
|
8937
|
-
debug(
|
|
8938
|
-
"detection",
|
|
8939
|
-
`Childless change: ${contentKey} removed -> registering it and skip transitions`,
|
|
8940
|
-
);
|
|
8941
|
-
} else {
|
|
8942
|
-
debug(
|
|
8943
|
-
"detection",
|
|
8944
|
-
`Childless change: content key updated from ${prevKey} to ${contentKey} -> registering it and skip transitions`,
|
|
8945
|
-
);
|
|
8946
|
-
}
|
|
8947
|
-
} else if (isInitialPopulationWithoutTransition) {
|
|
8948
|
-
debug(
|
|
8949
|
-
"detection",
|
|
8950
|
-
"Initial population detected -> skipping transitions (opt-in with [data-initial-transition])",
|
|
8951
|
-
);
|
|
8952
|
-
} else if (previousSlotInfo.contentKey !== slotInfo.contentKey) {
|
|
8953
|
-
let contentKeysSentence = `Content key: ${previousSlotInfo.contentKeyFormatted} → ${slotInfo.contentKeyFormatted}`;
|
|
8954
|
-
debug("detection", contentKeysSentence);
|
|
8955
|
-
} else if (previousSlotInfo.contentPhase !== slotInfo.contentPhase) {
|
|
8956
|
-
let contentPhasesSentence =
|
|
8957
|
-
slotInfo.contentPhase && previousSlotInfo.contentPhase
|
|
8958
|
-
? `Content phase: ${previousSlotInfo.contentPhase} → ${slotInfo.contentPhase}`
|
|
8959
|
-
: previousSlotInfo.contentPhase
|
|
8960
|
-
? `becomes content (content phase becomes undefined)`
|
|
8961
|
-
: `content phase becomes ${slotInfo.contentPhase}`;
|
|
8962
|
-
debug("detection", contentPhasesSentence);
|
|
8963
|
-
}
|
|
8964
|
-
|
|
8965
|
-
changeInfo = {
|
|
8966
|
-
reason,
|
|
8967
|
-
previousSlotInfo,
|
|
8968
|
-
becomesEmpty,
|
|
8969
|
-
becomesPopulated,
|
|
8970
|
-
isInitialPopulationWithoutTransition,
|
|
8971
|
-
shouldDoContentTransition,
|
|
8972
|
-
shouldDoPhaseTransition,
|
|
8973
|
-
contentChange,
|
|
8974
|
-
phaseChange,
|
|
8975
|
-
isTransitionLess,
|
|
8976
|
-
shouldDoContentTransitionIncludingPopulation,
|
|
8977
|
-
isStateChangeOnly,
|
|
8968
|
+
const commonProperties = {
|
|
8969
|
+
domNodes,
|
|
8970
|
+
domNodesClone,
|
|
8971
|
+
isEmpty,
|
|
8972
|
+
isOnlyTextNodes,
|
|
8973
|
+
singleElementNode,
|
|
8974
|
+
|
|
8975
|
+
width,
|
|
8976
|
+
height,
|
|
8977
|
+
borderRadius,
|
|
8978
|
+
border,
|
|
8979
|
+
background,
|
|
8980
|
+
|
|
8981
|
+
contentId,
|
|
8982
|
+
};
|
|
8983
|
+
|
|
8984
|
+
if (contentPhase) {
|
|
8985
|
+
return {
|
|
8986
|
+
...commonProperties,
|
|
8987
|
+
type: "content_phase",
|
|
8988
|
+
contentPhase,
|
|
8989
|
+
isContentPhase: true,
|
|
8990
|
+
isContent: false,
|
|
8991
|
+
toString: () => `content(${contentId}).phase(${contentPhase})`,
|
|
8978
8992
|
};
|
|
8993
|
+
}
|
|
8994
|
+
return {
|
|
8995
|
+
...commonProperties,
|
|
8996
|
+
type: "content",
|
|
8997
|
+
contentPhase: undefined,
|
|
8998
|
+
isContentPhase: false,
|
|
8999
|
+
isContent: true,
|
|
9000
|
+
toString: () => `content(${contentId})`,
|
|
8979
9001
|
};
|
|
8980
|
-
}
|
|
9002
|
+
};
|
|
8981
9003
|
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
let sizeTransition = null;
|
|
9004
|
+
const targetSlotInitialConfiguration = detectConfiguration(targetSlot);
|
|
9005
|
+
const outgoingSlotInitialConfiguration = detectConfiguration(outgoingSlot, {
|
|
9006
|
+
contentPhase: "true",
|
|
9007
|
+
});
|
|
9008
|
+
let targetSlotConfiguration = targetSlotInitialConfiguration;
|
|
9009
|
+
let outgoingSlotConfiguration = outgoingSlotInitialConfiguration;
|
|
9010
|
+
let previousTargetSlotConfiguration = UNSET;
|
|
8990
9011
|
|
|
8991
|
-
|
|
8992
|
-
{
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9012
|
+
const updateSlotAttributes = () => {
|
|
9013
|
+
if (targetSlotConfiguration.isEmpty && outgoingSlotConfiguration.isEmpty) {
|
|
9014
|
+
root.setAttribute("data-only-previous-group", "");
|
|
9015
|
+
} else {
|
|
9016
|
+
root.removeAttribute("data-only-previous-group");
|
|
9017
|
+
}
|
|
9018
|
+
};
|
|
9019
|
+
const updateAlignment = () => {
|
|
9020
|
+
// Set data attributes for CSS-based alignment
|
|
9021
|
+
root.setAttribute("data-align-x", alignX);
|
|
9022
|
+
root.setAttribute("data-align-y", alignY);
|
|
9023
|
+
};
|
|
9024
|
+
|
|
9025
|
+
const moveConfigurationIntoSlot = (configuration, slot) => {
|
|
9026
|
+
slot.innerHTML = "";
|
|
9027
|
+
for (const domNode of configuration.domNodesClone) {
|
|
9028
|
+
slot.appendChild(domNode);
|
|
9029
|
+
}
|
|
9030
|
+
// in case border or stuff like that have changed we re-detect the config
|
|
9031
|
+
const updatedConfig = detectConfiguration(slot);
|
|
9032
|
+
if (slot === targetSlot) {
|
|
9033
|
+
targetSlotConfiguration = updatedConfig;
|
|
9034
|
+
} else if (slot === outgoingSlot) {
|
|
9035
|
+
outgoingSlotConfiguration = updatedConfig;
|
|
9036
|
+
} else if (slot === previousTargetSlot) {
|
|
9037
|
+
previousTargetSlotConfiguration = updatedConfig;
|
|
9038
|
+
} else if (slot === previousOutgoingSlot) ; else {
|
|
9039
|
+
throw new Error("Unknown slot for applyConfiguration");
|
|
9040
|
+
}
|
|
9041
|
+
};
|
|
9042
|
+
|
|
9043
|
+
updateAlignment();
|
|
9044
|
+
|
|
9045
|
+
let transitionType = "none";
|
|
9046
|
+
const groupTransitionOptions = {
|
|
9047
|
+
// debugBreakpoints: [0.25],
|
|
9048
|
+
pauseBreakpoints,
|
|
9049
|
+
lifecycle: {
|
|
9050
|
+
setup: () => {
|
|
9051
|
+
updateSlotAttributes();
|
|
9052
|
+
root.setAttribute("data-transitioning", "");
|
|
9053
|
+
onStateChange({ isTransitioning: true });
|
|
9054
|
+
return {
|
|
9055
|
+
teardown: () => {
|
|
9056
|
+
root.removeAttribute("data-transitioning");
|
|
9057
|
+
updateSlotAttributes(); // Update positioning after transition
|
|
9058
|
+
onStateChange({ isTransitioning: false });
|
|
9059
|
+
},
|
|
9037
9060
|
};
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9061
|
+
},
|
|
9062
|
+
},
|
|
9063
|
+
};
|
|
9064
|
+
const transitionController = createGroupTransitionController(
|
|
9065
|
+
groupTransitionOptions,
|
|
9066
|
+
);
|
|
9067
|
+
|
|
9068
|
+
const elementToClip = root;
|
|
9069
|
+
const morphContainerIntoTarget = () => {
|
|
9070
|
+
const morphTransitions = [];
|
|
9071
|
+
{
|
|
9072
|
+
// TODO: ideally when scrollContainer is document AND we transition
|
|
9073
|
+
// from a layout with scrollbar to a layout without
|
|
9074
|
+
// we have clip path detecting we go from a given width/height to a new width/height
|
|
9075
|
+
// that might just be the result of scrollbar appearing/disappearing
|
|
9076
|
+
// we should detect when this happens to avoid clipping what correspond to the scrollbar presence toggling
|
|
9077
|
+
const fromWidth = previousTargetSlotConfiguration.width || 0;
|
|
9078
|
+
const fromHeight = previousTargetSlotConfiguration.height || 0;
|
|
9079
|
+
const toWidth = targetSlotConfiguration.width || 0;
|
|
9080
|
+
const toHeight = targetSlotConfiguration.height || 0;
|
|
9081
|
+
debugSize(
|
|
9082
|
+
`transition from [${fromWidth}x${fromHeight}] to [${toWidth}x${toHeight}]`,
|
|
9083
|
+
);
|
|
9084
|
+
const restoreOverflow = preventIntermediateScrollbar(root, {
|
|
9085
|
+
fromWidth,
|
|
9086
|
+
fromHeight,
|
|
9087
|
+
toWidth,
|
|
9088
|
+
toHeight,
|
|
9089
|
+
onPrevent: ({ x, y, scrollContainer }) => {
|
|
9090
|
+
if (x) {
|
|
9091
|
+
debugSize(
|
|
9092
|
+
`Temporarily hiding horizontal overflow during transition on ${getElementSignature(scrollContainer)}`,
|
|
9056
9093
|
);
|
|
9057
|
-
return;
|
|
9058
9094
|
}
|
|
9059
|
-
if (
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
Array.from(pauseReasonSet).join(", ") ||
|
|
9063
|
-
"wait next frame to resume";
|
|
9064
|
-
debug(
|
|
9065
|
-
"size",
|
|
9066
|
-
`[resize observer] size change ignore (${pauseReason})`,
|
|
9095
|
+
if (y) {
|
|
9096
|
+
debugSize(
|
|
9097
|
+
`Temporarily hiding vertical overflow during transition on ${getElementSignature(scrollContainer)}`,
|
|
9067
9098
|
);
|
|
9068
|
-
return;
|
|
9069
|
-
}
|
|
9070
|
-
if (localDebug.size) {
|
|
9071
|
-
console.group("[resize observer] size change detected");
|
|
9072
9099
|
}
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
}
|
|
9078
|
-
requestAnimationFrame(() => {
|
|
9079
|
-
isWithinResizeObserverTick = false;
|
|
9080
|
-
});
|
|
9081
|
-
});
|
|
9082
|
-
resizeObserver.observe(slot);
|
|
9083
|
-
};
|
|
9084
|
-
startResizeObserver();
|
|
9085
|
-
addTeardown(() => {
|
|
9086
|
-
stopResizeObserver();
|
|
9100
|
+
},
|
|
9101
|
+
onRestore: () => {
|
|
9102
|
+
debugSize(`Restored overflow after transition`);
|
|
9103
|
+
},
|
|
9087
9104
|
});
|
|
9088
|
-
}
|
|
9089
9105
|
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
getHeightWithoutTransition(slot),
|
|
9094
|
-
];
|
|
9095
|
-
};
|
|
9096
|
-
const syncContentDimensions = () => {
|
|
9097
|
-
// check content dimensions to see if they changed and sync them
|
|
9098
|
-
const [currentWidth, currentHeight] = measureSlotSize();
|
|
9099
|
-
if (!slotInfo.isContentPhase) {
|
|
9100
|
-
updateNaturalContentSize(currentWidth, currentHeight);
|
|
9101
|
-
}
|
|
9102
|
-
if (sizeTransition) {
|
|
9103
|
-
updateToSize(currentWidth, currentHeight);
|
|
9104
|
-
} else {
|
|
9105
|
-
constrainedWidth = currentWidth;
|
|
9106
|
-
constrainedHeight = currentHeight;
|
|
9107
|
-
}
|
|
9108
|
-
};
|
|
9109
|
-
const applySizeConstraintsUntil = (width, height, reason) => {
|
|
9110
|
-
// we want to pause either because we have a diff and don't want to trigger the resize observer
|
|
9111
|
-
// or if we have no diff because we're about to do something that would trigger it (transition)
|
|
9112
|
-
const resumeResizeObserver = pauseResizeObserver(reason);
|
|
9113
|
-
debug("size", `Applying size constraints (${reason})`, {
|
|
9114
|
-
width: `${constrainedWidth} → ${width}`,
|
|
9115
|
-
height: `${constrainedHeight} → ${height}`,
|
|
9116
|
-
});
|
|
9117
|
-
outerWrapper.style.width = `${width}px`;
|
|
9118
|
-
outerWrapper.style.height = `${height}px`;
|
|
9119
|
-
constrainedWidth = width;
|
|
9120
|
-
constrainedHeight = height;
|
|
9121
|
-
// force content overlay to take the right size
|
|
9122
|
-
// (this way the content clone is not distorted by the new content size)
|
|
9123
|
-
contentOverlay.style.width = `${width}px`;
|
|
9124
|
-
contentOverlay.style.height = `${height}px`;
|
|
9125
|
-
const release = (reason) => {
|
|
9126
|
-
releaseSizeConstraints(reason);
|
|
9127
|
-
resumeResizeObserver(reason);
|
|
9106
|
+
const onSizeTransitionFinished = () => {
|
|
9107
|
+
// Restore overflow when transition is complete
|
|
9108
|
+
restoreOverflow();
|
|
9128
9109
|
};
|
|
9129
|
-
|
|
9130
|
-
|
|
9110
|
+
|
|
9111
|
+
// https://emilkowal.ski/ui/the-magic-of-clip-path
|
|
9112
|
+
const elementToClipRect = elementToClip.getBoundingClientRect();
|
|
9113
|
+
const elementToClipWidth = elementToClipRect.width;
|
|
9114
|
+
const elementToClipHeight = elementToClipRect.height;
|
|
9115
|
+
// Calculate where content is positioned within the large container
|
|
9116
|
+
const getAlignedPosition = (containerSize, contentSize, align) => {
|
|
9117
|
+
switch (align) {
|
|
9118
|
+
case "start":
|
|
9119
|
+
return 0;
|
|
9120
|
+
case "end":
|
|
9121
|
+
return containerSize - contentSize;
|
|
9122
|
+
case "center":
|
|
9123
|
+
default:
|
|
9124
|
+
return (containerSize - contentSize) / 2;
|
|
9125
|
+
}
|
|
9131
9126
|
};
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
const releaseSizeConstraints = (reason) => {
|
|
9138
|
-
if (slotInfo.isContentPhase) {
|
|
9139
|
-
return;
|
|
9140
|
-
}
|
|
9141
|
-
debug("size", `Releasing constraints (${reason})`);
|
|
9142
|
-
const [beforeWidth, beforeHeight] = measureSlotSize();
|
|
9143
|
-
outerWrapper.style.width = "";
|
|
9144
|
-
outerWrapper.style.height = "";
|
|
9145
|
-
const [afterWidth, afterHeight] = measureSlotSize();
|
|
9146
|
-
debug("size", "Size after release:", {
|
|
9147
|
-
width: `${beforeWidth} → ${afterWidth}`,
|
|
9148
|
-
height: `${beforeHeight} → ${afterHeight}`,
|
|
9149
|
-
});
|
|
9150
|
-
updateNaturalContentSize(afterWidth, afterHeight);
|
|
9151
|
-
constrainedWidth = afterWidth;
|
|
9152
|
-
constrainedHeight = afterHeight;
|
|
9153
|
-
contentOverlay.style.width = ``;
|
|
9154
|
-
contentOverlay.style.height = ``;
|
|
9155
|
-
};
|
|
9156
|
-
const updateToSize = (targetWidth, targetHeight) => {
|
|
9157
|
-
if (
|
|
9158
|
-
constrainedWidth === targetWidth &&
|
|
9159
|
-
constrainedHeight === targetHeight
|
|
9160
|
-
) {
|
|
9161
|
-
return;
|
|
9162
|
-
}
|
|
9163
|
-
if (!hasSizeTransitions) {
|
|
9164
|
-
applySizeConstraints(
|
|
9165
|
-
targetWidth,
|
|
9166
|
-
targetHeight,
|
|
9167
|
-
"size update without transition",
|
|
9168
|
-
);
|
|
9169
|
-
return;
|
|
9170
|
-
}
|
|
9171
|
-
const widthDiff = Math.abs(targetWidth - constrainedWidth);
|
|
9172
|
-
const heightDiff = Math.abs(targetHeight - constrainedHeight);
|
|
9173
|
-
if (widthDiff <= SIZE_DIFF_EPSILON && heightDiff <= SIZE_DIFF_EPSILON) {
|
|
9174
|
-
applySizeConstraints(
|
|
9175
|
-
targetWidth,
|
|
9176
|
-
targetHeight,
|
|
9177
|
-
"skip transition (negligible diff)",
|
|
9178
|
-
);
|
|
9179
|
-
return;
|
|
9180
|
-
}
|
|
9181
|
-
const duration = parseInt(
|
|
9182
|
-
container.getAttribute("data-size-transition-duration") ||
|
|
9183
|
-
SIZE_TRANSITION_DURATION,
|
|
9127
|
+
// Position of "from" content within large container
|
|
9128
|
+
const fromLeft = getAlignedPosition(
|
|
9129
|
+
elementToClipWidth,
|
|
9130
|
+
fromWidth,
|
|
9131
|
+
alignX,
|
|
9184
9132
|
);
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
});
|
|
9190
|
-
|
|
9191
|
-
const transitions = [];
|
|
9192
|
-
if (widthDiff === 0) ; else if (widthDiff <= SIZE_DIFF_EPSILON) {
|
|
9193
|
-
debug(
|
|
9194
|
-
"size",
|
|
9195
|
-
`Skip width transition (negligible diff ${widthDiff.toFixed(4)}px)`,
|
|
9196
|
-
);
|
|
9197
|
-
} else {
|
|
9198
|
-
transitions.push(
|
|
9199
|
-
createWidthTransition(outerWrapper, targetWidth, {
|
|
9200
|
-
setup: () =>
|
|
9201
|
-
notifyTransition(outerWrapper, {
|
|
9202
|
-
modelId: "ui_transition_width",
|
|
9203
|
-
canOverflow: true,
|
|
9204
|
-
id:
|
|
9205
|
-
targetWidth > constrainedWidth
|
|
9206
|
-
? "grow_to_new_width"
|
|
9207
|
-
: "shrink_to_new_width",
|
|
9208
|
-
}),
|
|
9209
|
-
duration,
|
|
9210
|
-
onUpdate: ({ value }) => {
|
|
9211
|
-
constrainedWidth = value;
|
|
9212
|
-
},
|
|
9213
|
-
}),
|
|
9214
|
-
);
|
|
9215
|
-
}
|
|
9216
|
-
if (heightDiff === 0) ; else if (heightDiff <= SIZE_DIFF_EPSILON) {
|
|
9217
|
-
debug(
|
|
9218
|
-
"size",
|
|
9219
|
-
`Skip height transition (negligible diff ${heightDiff.toFixed(4)}px)`,
|
|
9220
|
-
);
|
|
9221
|
-
} else {
|
|
9222
|
-
transitions.push(
|
|
9223
|
-
createHeightTransition(outerWrapper, targetHeight, {
|
|
9224
|
-
setup: () =>
|
|
9225
|
-
notifyTransition(outerWrapper, {
|
|
9226
|
-
modelId: "ui_transition_height",
|
|
9227
|
-
canOverflow: true,
|
|
9228
|
-
id:
|
|
9229
|
-
targetHeight > constrainedHeight
|
|
9230
|
-
? "grow_to_new_height"
|
|
9231
|
-
: "shrink_to_new_height",
|
|
9232
|
-
}),
|
|
9233
|
-
duration,
|
|
9234
|
-
onUpdate: ({ value }) => {
|
|
9235
|
-
constrainedHeight = value;
|
|
9236
|
-
},
|
|
9237
|
-
}),
|
|
9238
|
-
);
|
|
9239
|
-
}
|
|
9240
|
-
const release = applySizeConstraintsUntil(
|
|
9241
|
-
constrainedWidth,
|
|
9242
|
-
constrainedHeight,
|
|
9243
|
-
"size transitioning",
|
|
9133
|
+
const fromTop = getAlignedPosition(
|
|
9134
|
+
elementToClipHeight,
|
|
9135
|
+
fromHeight,
|
|
9136
|
+
alignY,
|
|
9244
9137
|
);
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9138
|
+
// Position of target content within large container
|
|
9139
|
+
const targetLeft = getAlignedPosition(
|
|
9140
|
+
elementToClipWidth,
|
|
9141
|
+
toWidth,
|
|
9142
|
+
alignX,
|
|
9143
|
+
);
|
|
9144
|
+
const targetTop = getAlignedPosition(
|
|
9145
|
+
elementToClipHeight,
|
|
9146
|
+
toHeight,
|
|
9147
|
+
alignY,
|
|
9148
|
+
);
|
|
9149
|
+
debugSize(
|
|
9150
|
+
`Positions in container: from [${fromLeft},${fromTop}] ${fromWidth}x${fromHeight} to [${targetLeft},${targetTop}] ${toWidth}x${toHeight}`,
|
|
9151
|
+
);
|
|
9152
|
+
// Get border-radius values
|
|
9153
|
+
const fromBorderRadius =
|
|
9154
|
+
previousTargetSlotConfiguration.borderRadius || 0;
|
|
9155
|
+
const toBorderRadius = targetSlotConfiguration.borderRadius || 0;
|
|
9156
|
+
const startInsetTop = fromTop;
|
|
9157
|
+
const startInsetRight = elementToClipWidth - (fromLeft + fromWidth);
|
|
9158
|
+
const startInsetBottom = elementToClipHeight - (fromTop + fromHeight);
|
|
9159
|
+
const startInsetLeft = fromLeft;
|
|
9160
|
+
|
|
9161
|
+
const endInsetTop = targetTop;
|
|
9162
|
+
const endInsetRight = elementToClipWidth - (targetLeft + toWidth);
|
|
9163
|
+
const endInsetBottom = elementToClipHeight - (targetTop + toHeight);
|
|
9164
|
+
const endInsetLeft = targetLeft;
|
|
9165
|
+
|
|
9166
|
+
const startClipPath = `inset(${startInsetTop}px ${startInsetRight}px ${startInsetBottom}px ${startInsetLeft}px round ${fromBorderRadius}px)`;
|
|
9167
|
+
const endClipPath = `inset(${endInsetTop}px ${endInsetRight}px ${endInsetBottom}px ${endInsetLeft}px round ${toBorderRadius}px)`;
|
|
9168
|
+
// Create clip-path animation using Web Animations API
|
|
9169
|
+
const clipAnimation = elementToClip.animate(
|
|
9170
|
+
[{ clipPath: startClipPath }, { clipPath: endClipPath }],
|
|
9171
|
+
{
|
|
9172
|
+
duration,
|
|
9173
|
+
easing: "ease",
|
|
9174
|
+
fill: "forwards",
|
|
9251
9175
|
},
|
|
9252
|
-
});
|
|
9253
|
-
sizeTransition.play();
|
|
9254
|
-
};
|
|
9255
|
-
const updateNaturalContentSize = (width, height) => {
|
|
9256
|
-
if (width === naturalContentWidth && height === naturalContentHeight) {
|
|
9257
|
-
return;
|
|
9258
|
-
}
|
|
9259
|
-
debug("size", "Updating natural content size:", {
|
|
9260
|
-
width: `${naturalContentWidth} → ${width}`,
|
|
9261
|
-
height: `${naturalContentHeight} → ${height}`,
|
|
9262
|
-
});
|
|
9263
|
-
naturalContentWidth = width;
|
|
9264
|
-
naturalContentHeight = height;
|
|
9265
|
-
};
|
|
9266
|
-
|
|
9267
|
-
// Initialize with current size
|
|
9268
|
-
[constrainedWidth, constrainedHeight] = measureSlotSize();
|
|
9269
|
-
|
|
9270
|
-
const updateSizeTransition = () => {
|
|
9271
|
-
hasSizeTransitions = container.hasAttribute("data-size-transition");
|
|
9272
|
-
const { isContentPhase } = slotInfo;
|
|
9273
|
-
const { isInitialPopulationWithoutTransition } = changeInfo;
|
|
9274
|
-
debug(
|
|
9275
|
-
"size",
|
|
9276
|
-
`updateSizeTransition(), current constrained size: ${constrainedWidth.toFixed(2)}x${constrainedHeight.toFixed(2)}`,
|
|
9277
9176
|
);
|
|
9278
|
-
sizeTransition?.cancel();
|
|
9279
|
-
|
|
9280
|
-
// Initial population skip (first null → something): no content or size animations
|
|
9281
|
-
if (isInitialPopulationWithoutTransition) {
|
|
9282
|
-
const [newWidth, newHeight] = measureSlotSize();
|
|
9283
|
-
debug("size", `content size measured to: ${newWidth}x${newHeight}`);
|
|
9284
|
-
if (isContentPhase) {
|
|
9285
|
-
applySizeConstraints(
|
|
9286
|
-
newWidth,
|
|
9287
|
-
newHeight,
|
|
9288
|
-
"content phase initial population",
|
|
9289
|
-
);
|
|
9290
|
-
} else {
|
|
9291
|
-
updateNaturalContentSize(newWidth, newHeight);
|
|
9292
|
-
releaseSizeConstraints("initial population - skip transitions");
|
|
9293
|
-
}
|
|
9294
|
-
return;
|
|
9295
|
-
}
|
|
9296
|
-
|
|
9297
|
-
let targetWidth;
|
|
9298
|
-
let targetHeight;
|
|
9299
|
-
if (isContentPhase) {
|
|
9300
|
-
const shouldUseNewDimensions =
|
|
9301
|
-
naturalContentWidth === 0 && naturalContentHeight === 0;
|
|
9302
|
-
if (shouldUseNewDimensions) {
|
|
9303
|
-
// we don't have any natural content dimensions yet, we can use the content phase dimensions for now
|
|
9304
|
-
[targetWidth, targetHeight] = measureSlotSize();
|
|
9305
|
-
debug(
|
|
9306
|
-
"size",
|
|
9307
|
-
`content phase dimension measured to: ${targetWidth}x${targetHeight}`,
|
|
9308
|
-
);
|
|
9309
|
-
} else {
|
|
9310
|
-
// we don't care about the content phase dimension.
|
|
9311
|
-
// the content dimensions prevails
|
|
9312
|
-
targetWidth = naturalContentWidth;
|
|
9313
|
-
targetHeight = naturalContentHeight;
|
|
9314
|
-
debug(
|
|
9315
|
-
"size",
|
|
9316
|
-
`content phase using natural content size: ${naturalContentWidth}x${naturalContentHeight}`,
|
|
9317
|
-
);
|
|
9318
|
-
}
|
|
9319
|
-
} else {
|
|
9320
|
-
outerWrapper.style.width = "";
|
|
9321
|
-
outerWrapper.style.height = "";
|
|
9322
|
-
const [slotNaturalWidth, slotNaturalHeight] = measureSlotSize();
|
|
9323
|
-
outerWrapper.style.width = `${constrainedWidth}px`;
|
|
9324
|
-
outerWrapper.style.height = `${constrainedHeight}px`;
|
|
9325
|
-
updateNaturalContentSize(slotNaturalWidth, slotNaturalHeight);
|
|
9326
|
-
targetWidth = slotNaturalWidth;
|
|
9327
|
-
targetHeight = slotNaturalHeight;
|
|
9328
|
-
debug(
|
|
9329
|
-
"size",
|
|
9330
|
-
`content size measured to: ${slotNaturalWidth}x${slotNaturalHeight}`,
|
|
9331
|
-
);
|
|
9332
|
-
}
|
|
9333
|
-
|
|
9334
|
-
// If size transitions are disabled hold the previous size to avoid cropping during the content transition.
|
|
9335
|
-
if (!hasSizeTransitions) {
|
|
9336
|
-
debug(
|
|
9337
|
-
"size",
|
|
9338
|
-
`Holding previous size during content transition: ${constrainedWidth}x${constrainedHeight}`,
|
|
9339
|
-
);
|
|
9340
|
-
applySizeConstraints(
|
|
9341
|
-
constrainedWidth,
|
|
9342
|
-
constrainedHeight,
|
|
9343
|
-
"hold size for content transition",
|
|
9344
|
-
);
|
|
9345
|
-
sizeTransition?.cancel();
|
|
9346
|
-
onContentTransitionComplete = () => {
|
|
9347
|
-
onContentTransitionComplete = null;
|
|
9348
|
-
releaseSizeConstraints(
|
|
9349
|
-
"content transition completed - release size hold",
|
|
9350
|
-
);
|
|
9351
|
-
};
|
|
9352
|
-
return;
|
|
9353
|
-
}
|
|
9354
9177
|
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
updateToSize(targetWidth, targetHeight);
|
|
9369
|
-
};
|
|
9370
|
-
subscribeChange(updateSizeTransition);
|
|
9178
|
+
// Handle finish
|
|
9179
|
+
clipAnimation.finished
|
|
9180
|
+
.then(() => {
|
|
9181
|
+
// Clear clip-path to restore normal behavior
|
|
9182
|
+
elementToClip.style.clipPath = "";
|
|
9183
|
+
clipAnimation.cancel();
|
|
9184
|
+
onSizeTransitionFinished();
|
|
9185
|
+
})
|
|
9186
|
+
.catch(() => {
|
|
9187
|
+
// Animation was cancelled
|
|
9188
|
+
});
|
|
9189
|
+
clipAnimation.play();
|
|
9190
|
+
}
|
|
9371
9191
|
|
|
9372
|
-
|
|
9373
|
-
|
|
9192
|
+
return morphTransitions;
|
|
9193
|
+
};
|
|
9194
|
+
const fadeInTargetSlot = () => {
|
|
9195
|
+
targetSlotBackground.style.setProperty(
|
|
9196
|
+
"--target-slot-background",
|
|
9197
|
+
stringifyStyle(targetSlotConfiguration.background, "background"),
|
|
9198
|
+
);
|
|
9199
|
+
targetSlotBackground.style.setProperty(
|
|
9200
|
+
"--target-slot-width",
|
|
9201
|
+
`${targetSlotConfiguration.width || 0}px`,
|
|
9202
|
+
);
|
|
9203
|
+
targetSlotBackground.style.setProperty(
|
|
9204
|
+
"--target-slot-height",
|
|
9205
|
+
`${targetSlotConfiguration.height || 0}px`,
|
|
9206
|
+
);
|
|
9207
|
+
return createOpacityTransition(targetSlot, 1, {
|
|
9208
|
+
from: 0,
|
|
9209
|
+
duration,
|
|
9210
|
+
styleSynchronizer: "inline_style",
|
|
9211
|
+
onFinish: (targetSlotOpacityTransition) => {
|
|
9212
|
+
targetSlotOpacityTransition.cancel();
|
|
9213
|
+
},
|
|
9374
9214
|
});
|
|
9375
|
-
|
|
9376
|
-
|
|
9215
|
+
};
|
|
9216
|
+
const fadeOutPreviousGroup = () => {
|
|
9217
|
+
return createOpacityTransition(previousGroup, 0, {
|
|
9218
|
+
from: 1,
|
|
9219
|
+
duration,
|
|
9220
|
+
styleSynchronizer: "inline_style",
|
|
9221
|
+
onFinish: (previousGroupOpacityTransition) => {
|
|
9222
|
+
previousGroupOpacityTransition.cancel();
|
|
9223
|
+
previousGroup.style.opacity = "0"; // keep previous group visually hidden
|
|
9224
|
+
},
|
|
9377
9225
|
});
|
|
9378
|
-
|
|
9379
|
-
|
|
9226
|
+
};
|
|
9227
|
+
const fadeOutOutgoingSlot = () => {
|
|
9228
|
+
return createOpacityTransition(outgoingSlot, 0, {
|
|
9229
|
+
duration,
|
|
9230
|
+
from: 1,
|
|
9231
|
+
styleSynchronizer: "inline_style",
|
|
9232
|
+
onFinish: (outgoingSlotOpacityTransition) => {
|
|
9233
|
+
outgoingSlotOpacityTransition.cancel();
|
|
9234
|
+
outgoingSlot.style.opacity = "0"; // keep outgoing slot visually hidden
|
|
9235
|
+
},
|
|
9380
9236
|
});
|
|
9381
|
-
}
|
|
9382
|
-
|
|
9383
|
-
{
|
|
9384
|
-
let activeContentTransition = null;
|
|
9385
|
-
let activeContentTransitionType = null;
|
|
9386
|
-
let activePhaseTransition = null;
|
|
9387
|
-
let activePhaseTransitionType = null;
|
|
9388
|
-
|
|
9389
|
-
const updateContentTransitions = () => {
|
|
9390
|
-
const { childNodes, contentName: fromContentName } = slotInfo;
|
|
9391
|
-
const {
|
|
9392
|
-
previousSlotInfo,
|
|
9393
|
-
becomesEmpty,
|
|
9394
|
-
becomesPopulated,
|
|
9395
|
-
shouldDoContentTransition,
|
|
9396
|
-
shouldDoPhaseTransition,
|
|
9397
|
-
contentChange,
|
|
9398
|
-
phaseChange,
|
|
9399
|
-
isTransitionLess,
|
|
9400
|
-
shouldDoContentTransitionIncludingPopulation,
|
|
9401
|
-
} = changeInfo;
|
|
9402
|
-
const { hasChild: hadChild, contentName: toContentName } =
|
|
9403
|
-
previousSlotInfo;
|
|
9404
|
-
|
|
9405
|
-
const preserveOnlyContentTransition =
|
|
9406
|
-
isTransitionLess && activeContentTransition !== null;
|
|
9407
|
-
const previousChildNodes = previousSlotInfo.childNodes;
|
|
9408
|
-
|
|
9409
|
-
// Determine transition scenarios (hadChild/hasChild already computed above for logging)
|
|
9410
|
-
|
|
9411
|
-
/**
|
|
9412
|
-
* Content Phase Logic: Why empty slots are treated as content phases
|
|
9413
|
-
*
|
|
9414
|
-
* When there is no child element (React component returns null), it is considered
|
|
9415
|
-
* that the component does not render anything temporarily. This might be because:
|
|
9416
|
-
* - The component is loading but does not have a loading state
|
|
9417
|
-
* - The component has an error but does not have an error state
|
|
9418
|
-
* - The component is conceptually unloaded (underlying content was deleted/is not accessible)
|
|
9419
|
-
*
|
|
9420
|
-
* This represents a phase of the given content: having nothing to display.
|
|
9421
|
-
*
|
|
9422
|
-
* We support transitions between different contents via the ability to set
|
|
9423
|
-
* [data-content-key] on the ".ui_transition_slot". This is also useful when you want
|
|
9424
|
-
* all children of a React component to inherit the same data-content-key without
|
|
9425
|
-
* explicitly setting the attribute on each child element.
|
|
9426
|
-
*/
|
|
9427
|
-
|
|
9428
|
-
// Content key change when either slot or child has data-content-key and it changed
|
|
9429
|
-
// Content key change detection already computed in getSlotChangeInfo.
|
|
9430
|
-
// We rely on the shouldDoContentTransition value coming from changeInfo.
|
|
9431
|
-
|
|
9432
|
-
const decisions = [];
|
|
9433
|
-
if (shouldDoContentTransition) {
|
|
9434
|
-
decisions.push("CONTENT TRANSITION");
|
|
9435
|
-
}
|
|
9436
|
-
if (shouldDoPhaseTransition) {
|
|
9437
|
-
decisions.push("PHASE TRANSITION");
|
|
9438
|
-
}
|
|
9439
|
-
if (preserveOnlyContentTransition) {
|
|
9440
|
-
decisions.push("PRESERVE CONTENT TRANSITION");
|
|
9441
|
-
}
|
|
9442
|
-
if (decisions.length === 0) {
|
|
9443
|
-
decisions.push("NO TRANSITION");
|
|
9444
|
-
}
|
|
9445
|
-
|
|
9446
|
-
debug("content", `Decision: ${decisions.join(" + ")}`);
|
|
9447
|
-
if (preserveOnlyContentTransition) {
|
|
9448
|
-
const progress = (activeContentTransition.progress * 100).toFixed(1);
|
|
9449
|
-
debug(
|
|
9450
|
-
"content",
|
|
9451
|
-
`Preserving existing content transition (progress ${progress}%)`,
|
|
9452
|
-
);
|
|
9453
|
-
}
|
|
9454
|
-
|
|
9455
|
-
if (changeInfo.isInitialPopulationWithoutTransition) {
|
|
9456
|
-
return;
|
|
9457
|
-
}
|
|
9458
|
-
|
|
9459
|
-
// Handle content transitions (slide-left, cross-fade for content key changes)
|
|
9460
|
-
if (
|
|
9461
|
-
decisions.length === 1 &&
|
|
9462
|
-
decisions[0] === "NO TRANSITION" &&
|
|
9463
|
-
activeContentTransition === null &&
|
|
9464
|
-
activePhaseTransition === null
|
|
9465
|
-
) {
|
|
9466
|
-
// Skip creating any new transitions entirely
|
|
9467
|
-
onContentTransitionComplete?.();
|
|
9468
|
-
} else if (
|
|
9469
|
-
shouldDoContentTransitionIncludingPopulation &&
|
|
9470
|
-
!preserveOnlyContentTransition
|
|
9471
|
-
) {
|
|
9472
|
-
const animationProgress = activeContentTransition?.progress || 0;
|
|
9473
|
-
if (animationProgress > 0) {
|
|
9474
|
-
debug(
|
|
9475
|
-
"content",
|
|
9476
|
-
`Preserving content transition progress: ${(animationProgress * 100).toFixed(1)}%`,
|
|
9477
|
-
);
|
|
9478
|
-
}
|
|
9479
|
-
|
|
9480
|
-
const newTransitionType =
|
|
9481
|
-
container.getAttribute("data-content-transition") ||
|
|
9482
|
-
CONTENT_TRANSITION;
|
|
9483
|
-
const canContinueSmoothly =
|
|
9484
|
-
activeContentTransitionType === newTransitionType &&
|
|
9485
|
-
activeContentTransition;
|
|
9486
|
-
if (canContinueSmoothly) {
|
|
9487
|
-
debug(
|
|
9488
|
-
"content",
|
|
9489
|
-
"Continuing with same content transition type (restarting due to actual change)",
|
|
9490
|
-
);
|
|
9491
|
-
activeContentTransition.cancel();
|
|
9492
|
-
} else if (
|
|
9493
|
-
activeContentTransition &&
|
|
9494
|
-
activeContentTransitionType !== newTransitionType
|
|
9495
|
-
) {
|
|
9496
|
-
debug(
|
|
9497
|
-
"content",
|
|
9498
|
-
"Different content transition type, keeping both",
|
|
9499
|
-
`${activeContentTransitionType} → ${newTransitionType}`,
|
|
9500
|
-
);
|
|
9501
|
-
} else if (activeContentTransition) {
|
|
9502
|
-
debug("content", "Cancelling current content transition");
|
|
9503
|
-
activeContentTransition.cancel();
|
|
9504
|
-
}
|
|
9505
|
-
|
|
9506
|
-
const needsOldChildNodesClone =
|
|
9507
|
-
(contentChange || becomesEmpty) && hadChild;
|
|
9508
|
-
const duration = parseInt(
|
|
9509
|
-
container.getAttribute("data-content-transition-duration") ||
|
|
9510
|
-
CONTENT_TRANSITION_DURATION,
|
|
9511
|
-
);
|
|
9512
|
-
const type =
|
|
9513
|
-
container.getAttribute("data-content-transition") ||
|
|
9514
|
-
CONTENT_TRANSITION;
|
|
9515
|
-
|
|
9516
|
-
const setupContentTransition = () =>
|
|
9517
|
-
setupTransition({
|
|
9518
|
-
isPhaseTransition: false,
|
|
9519
|
-
overlay: contentOverlay,
|
|
9520
|
-
needsOldChildNodesClone,
|
|
9521
|
-
previousChildNodes,
|
|
9522
|
-
childNodes,
|
|
9523
|
-
slotInfo,
|
|
9524
|
-
attributeToRemove: ["data-content-key"],
|
|
9525
|
-
});
|
|
9526
|
-
|
|
9527
|
-
activeContentTransition = applyTransition(
|
|
9528
|
-
transitionController,
|
|
9529
|
-
setupContentTransition,
|
|
9530
|
-
{
|
|
9531
|
-
duration,
|
|
9532
|
-
type,
|
|
9533
|
-
animationProgress,
|
|
9534
|
-
isPhaseTransition: false,
|
|
9535
|
-
previousSlotInfo,
|
|
9536
|
-
slotInfo,
|
|
9537
|
-
onComplete: () => {
|
|
9538
|
-
activeContentTransition = null;
|
|
9539
|
-
activeContentTransitionType = null;
|
|
9540
|
-
onContentTransitionComplete?.();
|
|
9541
|
-
},
|
|
9542
|
-
debug,
|
|
9543
|
-
},
|
|
9544
|
-
);
|
|
9545
|
-
|
|
9546
|
-
if (activeContentTransition) {
|
|
9547
|
-
activeContentTransition.play();
|
|
9548
|
-
}
|
|
9549
|
-
activeContentTransitionType = type;
|
|
9550
|
-
} else if (!shouldDoContentTransition && !preserveOnlyContentTransition) {
|
|
9551
|
-
// Clean up content overlay if no content transition needed and nothing to preserve
|
|
9552
|
-
contentOverlay.innerHTML = "";
|
|
9553
|
-
activeContentTransition = null;
|
|
9554
|
-
activeContentTransitionType = null;
|
|
9555
|
-
}
|
|
9556
|
-
|
|
9557
|
-
// Handle phase transitions (cross-fade for content phase changes)
|
|
9558
|
-
if (shouldDoPhaseTransition) {
|
|
9559
|
-
const phaseTransitionType =
|
|
9560
|
-
container.getAttribute("data-phase-transition") || PHASE_TRANSITION;
|
|
9561
|
-
const phaseAnimationProgress = activePhaseTransition?.progress || 0;
|
|
9562
|
-
if (phaseAnimationProgress > 0) {
|
|
9563
|
-
debug(
|
|
9564
|
-
"content",
|
|
9565
|
-
`Preserving phase transition progress: ${(phaseAnimationProgress * 100).toFixed(1)}%`,
|
|
9566
|
-
);
|
|
9567
|
-
}
|
|
9568
|
-
|
|
9569
|
-
const canContinueSmoothly =
|
|
9570
|
-
activePhaseTransitionType === phaseTransitionType &&
|
|
9571
|
-
activePhaseTransition;
|
|
9237
|
+
};
|
|
9572
9238
|
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9239
|
+
// content_to_content transition (uses previous_group)
|
|
9240
|
+
const applyContentToContentTransition = (toConfiguration) => {
|
|
9241
|
+
// 1. move target slot to previous
|
|
9242
|
+
moveConfigurationIntoSlot(targetSlotConfiguration, previousTargetSlot);
|
|
9243
|
+
targetSlotConfiguration = toConfiguration;
|
|
9244
|
+
// 2. move outgoing slot to previous
|
|
9245
|
+
moveConfigurationIntoSlot(outgoingSlotConfiguration, previousOutgoingSlot);
|
|
9246
|
+
moveConfigurationIntoSlot(UNSET, outgoingSlot);
|
|
9247
|
+
|
|
9248
|
+
const transitions = [
|
|
9249
|
+
...morphContainerIntoTarget(),
|
|
9250
|
+
fadeInTargetSlot(),
|
|
9251
|
+
fadeOutPreviousGroup(),
|
|
9252
|
+
];
|
|
9253
|
+
const transition = transitionController.update(transitions, {
|
|
9254
|
+
onFinish: () => {
|
|
9255
|
+
moveConfigurationIntoSlot(UNSET, previousTargetSlot);
|
|
9256
|
+
moveConfigurationIntoSlot(UNSET, previousOutgoingSlot);
|
|
9257
|
+
if (hasDebugLogs) {
|
|
9258
|
+
console.groupEnd();
|
|
9588
9259
|
}
|
|
9260
|
+
},
|
|
9261
|
+
});
|
|
9262
|
+
transition.play();
|
|
9263
|
+
};
|
|
9264
|
+
// content_phase_to_content_phase transition (uses outgoing_slot)
|
|
9265
|
+
const applyContentPhaseToContentPhaseTransition = (toConfiguration) => {
|
|
9266
|
+
// 1. Move target slot to outgoing
|
|
9267
|
+
moveConfigurationIntoSlot(targetSlotConfiguration, outgoingSlot);
|
|
9268
|
+
targetSlotConfiguration = toConfiguration;
|
|
9269
|
+
|
|
9270
|
+
const transitions = [
|
|
9271
|
+
...morphContainerIntoTarget(),
|
|
9272
|
+
fadeInTargetSlot(),
|
|
9273
|
+
fadeOutOutgoingSlot(),
|
|
9274
|
+
];
|
|
9275
|
+
const transition = transitionController.update(transitions, {
|
|
9276
|
+
onFinish: () => {
|
|
9277
|
+
moveConfigurationIntoSlot(UNSET, outgoingSlot);
|
|
9589
9278
|
|
|
9590
|
-
|
|
9591
|
-
(
|
|
9592
|
-
const phaseDuration = parseInt(
|
|
9593
|
-
container.getAttribute("data-phase-transition-duration") ||
|
|
9594
|
-
PHASE_TRANSITION_DURATION,
|
|
9595
|
-
);
|
|
9596
|
-
|
|
9597
|
-
const setupPhaseTransition = () =>
|
|
9598
|
-
setupTransition({
|
|
9599
|
-
isPhaseTransition: true,
|
|
9600
|
-
overlay: phaseOverlay,
|
|
9601
|
-
needsOldChildNodesClone: needsOldPhaseClone,
|
|
9602
|
-
previousChildNodes,
|
|
9603
|
-
childNodes,
|
|
9604
|
-
slotInfo,
|
|
9605
|
-
attributeToRemove: ["data-content-key", "data-content-phase"],
|
|
9606
|
-
});
|
|
9607
|
-
|
|
9608
|
-
debug(
|
|
9609
|
-
"content",
|
|
9610
|
-
`Starting transition: ${fromContentName} → ${toContentName}`,
|
|
9611
|
-
);
|
|
9612
|
-
|
|
9613
|
-
activePhaseTransition = applyTransition(
|
|
9614
|
-
transitionController,
|
|
9615
|
-
setupPhaseTransition,
|
|
9616
|
-
{
|
|
9617
|
-
duration: phaseDuration,
|
|
9618
|
-
type: phaseTransitionType,
|
|
9619
|
-
animationProgress: phaseAnimationProgress,
|
|
9620
|
-
isPhaseTransition: true,
|
|
9621
|
-
previousSlotInfo,
|
|
9622
|
-
slotInfo,
|
|
9623
|
-
onComplete: () => {
|
|
9624
|
-
activePhaseTransition = null;
|
|
9625
|
-
activePhaseTransitionType = null;
|
|
9626
|
-
onContentTransitionComplete?.();
|
|
9627
|
-
debug("content", "Phase transition complete");
|
|
9628
|
-
},
|
|
9629
|
-
debug,
|
|
9630
|
-
},
|
|
9631
|
-
);
|
|
9632
|
-
|
|
9633
|
-
if (activePhaseTransition) {
|
|
9634
|
-
activePhaseTransition.play();
|
|
9279
|
+
if (hasDebugLogs) {
|
|
9280
|
+
console.groupEnd();
|
|
9635
9281
|
}
|
|
9636
|
-
|
|
9637
|
-
}
|
|
9638
|
-
};
|
|
9639
|
-
subscribeChange(updateContentTransitions);
|
|
9640
|
-
|
|
9641
|
-
addPauseCallback(() => {
|
|
9642
|
-
activeContentTransition?.pause();
|
|
9643
|
-
activePhaseTransition?.pause();
|
|
9644
|
-
});
|
|
9645
|
-
addResumeCallback(() => {
|
|
9646
|
-
activeContentTransition?.play();
|
|
9647
|
-
activePhaseTransition?.play();
|
|
9282
|
+
},
|
|
9648
9283
|
});
|
|
9649
|
-
|
|
9650
|
-
|
|
9651
|
-
|
|
9284
|
+
transition.play();
|
|
9285
|
+
};
|
|
9286
|
+
// any_to_empty transition
|
|
9287
|
+
const applyToEmptyTransition = () => {
|
|
9288
|
+
// 1. move target slot to previous
|
|
9289
|
+
moveConfigurationIntoSlot(targetSlotConfiguration, previousTargetSlot);
|
|
9290
|
+
targetSlotConfiguration = UNSET;
|
|
9291
|
+
// 2. move outgoing slot to previous
|
|
9292
|
+
moveConfigurationIntoSlot(outgoingSlotConfiguration, previousOutgoingSlot);
|
|
9293
|
+
outgoingSlotConfiguration = UNSET;
|
|
9294
|
+
|
|
9295
|
+
const transitions = [...morphContainerIntoTarget(), fadeOutPreviousGroup()];
|
|
9296
|
+
const transition = transitionController.update(transitions, {
|
|
9297
|
+
onFinish: () => {
|
|
9298
|
+
moveConfigurationIntoSlot(UNSET, previousTargetSlot);
|
|
9299
|
+
moveConfigurationIntoSlot(UNSET, previousOutgoingSlot);
|
|
9300
|
+
if (hasDebugLogs) {
|
|
9301
|
+
console.groupEnd();
|
|
9302
|
+
}
|
|
9303
|
+
},
|
|
9652
9304
|
});
|
|
9653
|
-
|
|
9305
|
+
transition.play();
|
|
9306
|
+
};
|
|
9307
|
+
// Main transition method
|
|
9308
|
+
const transitionTo = (
|
|
9309
|
+
newContentElement,
|
|
9310
|
+
{ contentPhase, contentId } = {},
|
|
9311
|
+
) => {
|
|
9312
|
+
if (contentId) {
|
|
9313
|
+
targetSlot.setAttribute(CONTENT_ID_ATTRIBUTE, contentId);
|
|
9314
|
+
} else {
|
|
9315
|
+
targetSlot.removeAttribute(CONTENT_ID_ATTRIBUTE);
|
|
9316
|
+
}
|
|
9317
|
+
if (contentPhase) {
|
|
9318
|
+
targetSlot.setAttribute(CONTENT_PHASE_ATTRIBUTE, contentPhase);
|
|
9319
|
+
} else {
|
|
9320
|
+
targetSlot.removeAttribute(CONTENT_PHASE_ATTRIBUTE);
|
|
9321
|
+
}
|
|
9322
|
+
if (newContentElement) {
|
|
9323
|
+
targetSlot.innerHTML = "";
|
|
9324
|
+
targetSlot.appendChild(newContentElement);
|
|
9325
|
+
} else {
|
|
9326
|
+
targetSlot.innerHTML = "";
|
|
9327
|
+
}
|
|
9328
|
+
};
|
|
9329
|
+
// Reset to initial content
|
|
9330
|
+
const resetContent = () => {
|
|
9331
|
+
transitionController.cancel();
|
|
9332
|
+
moveConfigurationIntoSlot(targetSlotInitialConfiguration, targetSlot);
|
|
9333
|
+
moveConfigurationIntoSlot(outgoingSlotInitialConfiguration, outgoingSlot);
|
|
9334
|
+
moveConfigurationIntoSlot(UNSET, previousTargetSlot);
|
|
9335
|
+
moveConfigurationIntoSlot(UNSET, previousOutgoingSlot);
|
|
9336
|
+
};
|
|
9654
9337
|
|
|
9655
|
-
{
|
|
9656
|
-
const
|
|
9657
|
-
const
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
|
|
9338
|
+
const targetSlotEffect = (reasons) => {
|
|
9339
|
+
const fromConfiguration = targetSlotConfiguration;
|
|
9340
|
+
const toConfiguration = detectConfiguration(targetSlot);
|
|
9341
|
+
if (hasDebugLogs) {
|
|
9342
|
+
console.group(`targetSlotEffect()`);
|
|
9343
|
+
console.debug(`reasons:`);
|
|
9344
|
+
console.debug(`- ${reasons.join("\n- ")}`);
|
|
9345
|
+
}
|
|
9346
|
+
if (isSameConfiguration(fromConfiguration, toConfiguration)) {
|
|
9347
|
+
debugDetection(
|
|
9348
|
+
`already in desired state (${toConfiguration}) -> early return`,
|
|
9349
|
+
);
|
|
9350
|
+
if (hasDebugLogs) {
|
|
9351
|
+
console.groupEnd();
|
|
9662
9352
|
}
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
}
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9353
|
+
return;
|
|
9354
|
+
}
|
|
9355
|
+
const fromConfigType = fromConfiguration.type;
|
|
9356
|
+
const toConfigType = toConfiguration.type;
|
|
9357
|
+
transitionType = `${fromConfigType}_to_${toConfigType}`;
|
|
9358
|
+
debugDetection(
|
|
9359
|
+
`Prepare "${transitionType}" transition (${fromConfiguration} -> ${toConfiguration})`,
|
|
9360
|
+
);
|
|
9361
|
+
// content_to_empty / content_phase_to_empty
|
|
9362
|
+
if (toConfiguration.isEmpty) {
|
|
9363
|
+
applyToEmptyTransition();
|
|
9364
|
+
return;
|
|
9365
|
+
}
|
|
9366
|
+
// content_phase_to_content_phase
|
|
9367
|
+
if (fromConfiguration.isContentPhase && toConfiguration.isContentPhase) {
|
|
9368
|
+
applyContentPhaseToContentPhaseTransition(toConfiguration);
|
|
9369
|
+
return;
|
|
9370
|
+
}
|
|
9371
|
+
// content_phase_to_content
|
|
9372
|
+
if (fromConfiguration.isContentPhase && toConfiguration.isContent) {
|
|
9373
|
+
applyContentPhaseToContentPhaseTransition(toConfiguration);
|
|
9374
|
+
return;
|
|
9375
|
+
}
|
|
9376
|
+
// content_to_content_phase
|
|
9377
|
+
if (fromConfiguration.isContent && toConfiguration.isContentPhase) {
|
|
9378
|
+
applyContentPhaseToContentPhaseTransition(toConfiguration);
|
|
9379
|
+
return;
|
|
9380
|
+
}
|
|
9381
|
+
// content_to_content (default case)
|
|
9382
|
+
applyContentToContentTransition(toConfiguration);
|
|
9383
|
+
};
|
|
9679
9384
|
|
|
9680
|
-
|
|
9681
|
-
triggerChildSlotMutation("init");
|
|
9385
|
+
const [teardown, addTeardown] = createPubSub();
|
|
9682
9386
|
{
|
|
9683
9387
|
const mutationObserver = new MutationObserver((mutations) => {
|
|
9684
9388
|
const reasonParts = [];
|
|
9685
|
-
|
|
9686
9389
|
for (const mutation of mutations) {
|
|
9687
9390
|
if (mutation.type === "childList") {
|
|
9688
9391
|
const added = mutation.addedNodes.length;
|
|
@@ -9699,10 +9402,27 @@ const initUITransition = (container) => {
|
|
|
9699
9402
|
if (mutation.type === "attributes") {
|
|
9700
9403
|
const { attributeName } = mutation;
|
|
9701
9404
|
if (
|
|
9702
|
-
attributeName ===
|
|
9703
|
-
attributeName ===
|
|
9405
|
+
attributeName === CONTENT_ID_ATTRIBUTE ||
|
|
9406
|
+
attributeName === CONTENT_PHASE_ATTRIBUTE
|
|
9704
9407
|
) {
|
|
9705
|
-
|
|
9408
|
+
const { oldValue } = mutation;
|
|
9409
|
+
if (oldValue === null) {
|
|
9410
|
+
const value = targetSlot.getAttribute(attributeName);
|
|
9411
|
+
reasonParts.push(
|
|
9412
|
+
value
|
|
9413
|
+
? `added [${attributeName}=${value}]`
|
|
9414
|
+
: `added [${attributeName}]`,
|
|
9415
|
+
);
|
|
9416
|
+
} else if (targetSlot.hasAttribute(attributeName)) {
|
|
9417
|
+
const value = targetSlot.getAttribute(attributeName);
|
|
9418
|
+
reasonParts.push(`[${attributeName}] ${oldValue} -> ${value}`);
|
|
9419
|
+
} else {
|
|
9420
|
+
reasonParts.push(
|
|
9421
|
+
oldValue
|
|
9422
|
+
? `removed [${attributeName}=${oldValue}]`
|
|
9423
|
+
: `removed [${attributeName}]`,
|
|
9424
|
+
);
|
|
9425
|
+
}
|
|
9706
9426
|
}
|
|
9707
9427
|
}
|
|
9708
9428
|
}
|
|
@@ -9710,410 +9430,63 @@ const initUITransition = (container) => {
|
|
|
9710
9430
|
if (reasonParts.length === 0) {
|
|
9711
9431
|
return;
|
|
9712
9432
|
}
|
|
9713
|
-
|
|
9714
|
-
triggerChildSlotMutation(reason);
|
|
9433
|
+
targetSlotEffect(reasonParts);
|
|
9715
9434
|
});
|
|
9716
|
-
mutationObserver.observe(
|
|
9435
|
+
mutationObserver.observe(targetSlot, {
|
|
9717
9436
|
childList: true,
|
|
9718
9437
|
attributes: true,
|
|
9719
|
-
attributeFilter: [
|
|
9438
|
+
attributeFilter: [CONTENT_ID_ATTRIBUTE, CONTENT_PHASE_ATTRIBUTE],
|
|
9720
9439
|
characterData: false,
|
|
9721
9440
|
});
|
|
9722
9441
|
addTeardown(() => {
|
|
9723
9442
|
mutationObserver.disconnect();
|
|
9724
9443
|
});
|
|
9725
9444
|
}
|
|
9726
|
-
|
|
9727
|
-
return {
|
|
9728
|
-
slot,
|
|
9729
|
-
|
|
9730
|
-
cleanup: () => {
|
|
9731
|
-
teardown();
|
|
9732
|
-
},
|
|
9733
|
-
pause: () => {
|
|
9734
|
-
if (state.isPaused) {
|
|
9735
|
-
return;
|
|
9736
|
-
}
|
|
9737
|
-
publishPause();
|
|
9738
|
-
state.isPaused = true;
|
|
9739
|
-
},
|
|
9740
|
-
resume: () => {
|
|
9741
|
-
if (!state.isPaused) {
|
|
9742
|
-
return;
|
|
9743
|
-
}
|
|
9744
|
-
state.isPaused = false;
|
|
9745
|
-
publishResume();
|
|
9746
|
-
},
|
|
9747
|
-
getState: () => state,
|
|
9748
|
-
};
|
|
9749
|
-
};
|
|
9750
|
-
|
|
9751
|
-
const applyTransition = (
|
|
9752
|
-
transitionController,
|
|
9753
|
-
setupTransition,
|
|
9754
9445
|
{
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
) => {
|
|
9765
|
-
let transitionType;
|
|
9766
|
-
if (type === "cross-fade") {
|
|
9767
|
-
transitionType = crossFade;
|
|
9768
|
-
} else if (type === "slide-left") {
|
|
9769
|
-
transitionType = slideLeft;
|
|
9770
|
-
} else {
|
|
9771
|
-
return null;
|
|
9446
|
+
const slots = [
|
|
9447
|
+
targetSlot,
|
|
9448
|
+
outgoingSlot,
|
|
9449
|
+
previousTargetSlot,
|
|
9450
|
+
previousOutgoingSlot,
|
|
9451
|
+
];
|
|
9452
|
+
for (const slot of slots) {
|
|
9453
|
+
addTeardown(monitorItemsOverflow(slot));
|
|
9454
|
+
}
|
|
9772
9455
|
}
|
|
9773
9456
|
|
|
9774
|
-
const
|
|
9775
|
-
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
});
|
|
9785
|
-
|
|
9786
|
-
const remainingDuration = Math.max(100, duration * (1 - animationProgress));
|
|
9787
|
-
debug("content", `Animation duration: ${remainingDuration}ms`);
|
|
9788
|
-
|
|
9789
|
-
const transitions = transitionType.apply(oldElement, newElement, {
|
|
9790
|
-
duration: remainingDuration,
|
|
9791
|
-
startProgress: animationProgress,
|
|
9792
|
-
isPhaseTransition,
|
|
9793
|
-
debug,
|
|
9794
|
-
});
|
|
9795
|
-
|
|
9796
|
-
debug("content", `Created ${transitions.length} transition(s) for animation`);
|
|
9797
|
-
|
|
9798
|
-
if (transitions.length === 0) {
|
|
9799
|
-
debug("content", "No transitions to animate, cleaning up immediately");
|
|
9800
|
-
cleanup();
|
|
9801
|
-
onTeardown?.();
|
|
9802
|
-
onComplete?.();
|
|
9803
|
-
return null;
|
|
9804
|
-
}
|
|
9457
|
+
const setDuration = (newDuration) => {
|
|
9458
|
+
duration = newDuration;
|
|
9459
|
+
// Update CSS variable immediately
|
|
9460
|
+
root.style.setProperty("--x-transition-duration", `${duration}ms`);
|
|
9461
|
+
};
|
|
9462
|
+
const setAlignment = (newAlignX, newAlignY) => {
|
|
9463
|
+
alignX = newAlignX;
|
|
9464
|
+
alignY = newAlignY;
|
|
9465
|
+
updateAlignment();
|
|
9466
|
+
};
|
|
9805
9467
|
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9468
|
+
return {
|
|
9469
|
+
updateContentId: (value) => {
|
|
9470
|
+
if (value) {
|
|
9471
|
+
targetSlot.setAttribute(CONTENT_ID_ATTRIBUTE, value);
|
|
9472
|
+
} else {
|
|
9473
|
+
targetSlot.removeAttribute(CONTENT_ID_ATTRIBUTE);
|
|
9474
|
+
}
|
|
9812
9475
|
},
|
|
9813
|
-
});
|
|
9814
|
-
|
|
9815
|
-
return groupTransition;
|
|
9816
|
-
};
|
|
9817
|
-
|
|
9818
|
-
const slideLeft = {
|
|
9819
|
-
id: "ui_transition_slide_left",
|
|
9820
|
-
name: "slide-left",
|
|
9821
|
-
apply: (
|
|
9822
|
-
oldElement,
|
|
9823
|
-
newElement,
|
|
9824
|
-
{ duration, startProgress = 0, isPhaseTransition = false, debug },
|
|
9825
|
-
) => {
|
|
9826
|
-
if (!oldElement && !newElement) {
|
|
9827
|
-
return [];
|
|
9828
|
-
}
|
|
9829
|
-
|
|
9830
|
-
if (!newElement) {
|
|
9831
|
-
// Content -> Empty (slide out left only)
|
|
9832
|
-
const currentPosition = getTranslateX(oldElement);
|
|
9833
|
-
const containerWidth = getInnerWidth(oldElement.parentElement);
|
|
9834
|
-
const from = currentPosition;
|
|
9835
|
-
const to = -containerWidth;
|
|
9836
|
-
debug("content", "Slide out to empty:", { from, to });
|
|
9837
|
-
|
|
9838
|
-
return [
|
|
9839
|
-
createTranslateXTransition(oldElement, to, {
|
|
9840
|
-
setup: () =>
|
|
9841
|
-
notifyTransition(newElement, {
|
|
9842
|
-
modelId: slideLeft.id,
|
|
9843
|
-
canOverflow: true,
|
|
9844
|
-
id: "slide_out_old_content",
|
|
9845
|
-
}),
|
|
9846
|
-
from,
|
|
9847
|
-
duration,
|
|
9848
|
-
startProgress,
|
|
9849
|
-
onUpdate: ({ value, timing }) => {
|
|
9850
|
-
debug("transition_updates", "Slide out progress:", value);
|
|
9851
|
-
if (timing === "end") {
|
|
9852
|
-
debug("content", "Slide out complete");
|
|
9853
|
-
}
|
|
9854
|
-
},
|
|
9855
|
-
}),
|
|
9856
|
-
];
|
|
9857
|
-
}
|
|
9858
|
-
|
|
9859
|
-
if (!oldElement) {
|
|
9860
|
-
// Empty -> Content (slide in from right)
|
|
9861
|
-
const containerWidth = getInnerWidth(newElement.parentElement);
|
|
9862
|
-
const from = containerWidth; // Start from right edge for slide-in effect
|
|
9863
|
-
const to = getTranslateXWithoutTransition(newElement);
|
|
9864
|
-
debug("content", "Slide in from empty:", { from, to });
|
|
9865
|
-
return [
|
|
9866
|
-
createTranslateXTransition(newElement, to, {
|
|
9867
|
-
setup: () =>
|
|
9868
|
-
notifyTransition(newElement, {
|
|
9869
|
-
modelId: slideLeft.id,
|
|
9870
|
-
canOverflow: true,
|
|
9871
|
-
id: "slide_in_new_content",
|
|
9872
|
-
}),
|
|
9873
|
-
from,
|
|
9874
|
-
duration,
|
|
9875
|
-
startProgress,
|
|
9876
|
-
onUpdate: ({ value, timing }) => {
|
|
9877
|
-
debug("transition_updates", "Slide in progress:", value);
|
|
9878
|
-
if (timing === "end") {
|
|
9879
|
-
debug("content", "Slide in complete");
|
|
9880
|
-
}
|
|
9881
|
-
},
|
|
9882
|
-
}),
|
|
9883
|
-
];
|
|
9884
|
-
}
|
|
9885
|
-
|
|
9886
|
-
// Content -> Content (slide left)
|
|
9887
|
-
// The old content (oldElement) slides OUT to the left
|
|
9888
|
-
// The new content (newElement) slides IN from the right
|
|
9889
|
-
|
|
9890
|
-
// Get positions for the slide animation
|
|
9891
|
-
const containerWidth = getInnerWidth(newElement.parentElement);
|
|
9892
|
-
const oldContentPosition = getTranslateX(oldElement);
|
|
9893
|
-
const currentNewPosition = getTranslateX(newElement);
|
|
9894
|
-
const naturalNewPosition = getTranslateXWithoutTransition(newElement);
|
|
9895
|
-
|
|
9896
|
-
// For smooth continuation: if newElement is mid-transition,
|
|
9897
|
-
// calculate new position to maintain seamless sliding
|
|
9898
|
-
let startNewPosition;
|
|
9899
|
-
if (currentNewPosition !== 0 && naturalNewPosition === 0) {
|
|
9900
|
-
startNewPosition = currentNewPosition + containerWidth;
|
|
9901
|
-
debug(
|
|
9902
|
-
"content",
|
|
9903
|
-
"Calculated seamless position:",
|
|
9904
|
-
`${currentNewPosition} + ${containerWidth} = ${startNewPosition}`,
|
|
9905
|
-
);
|
|
9906
|
-
} else {
|
|
9907
|
-
startNewPosition = naturalNewPosition || containerWidth;
|
|
9908
|
-
}
|
|
9909
|
-
|
|
9910
|
-
// For phase transitions, force new content to start from right edge for proper slide-in
|
|
9911
|
-
const effectiveFromPosition = isPhaseTransition
|
|
9912
|
-
? containerWidth
|
|
9913
|
-
: startNewPosition;
|
|
9914
|
-
|
|
9915
|
-
debug("content", "Slide transition:", {
|
|
9916
|
-
oldContent: `${oldContentPosition} → ${-containerWidth}`,
|
|
9917
|
-
newContent: `${effectiveFromPosition} → ${naturalNewPosition}`,
|
|
9918
|
-
});
|
|
9919
|
-
|
|
9920
|
-
const transitions = [];
|
|
9921
|
-
|
|
9922
|
-
// Slide old content out
|
|
9923
|
-
transitions.push(
|
|
9924
|
-
createTranslateXTransition(oldElement, -containerWidth, {
|
|
9925
|
-
setup: () =>
|
|
9926
|
-
notifyTransition(newElement, {
|
|
9927
|
-
modelId: slideLeft.id,
|
|
9928
|
-
canOverflow: true,
|
|
9929
|
-
id: "slide_out_old_content",
|
|
9930
|
-
}),
|
|
9931
|
-
from: oldContentPosition,
|
|
9932
|
-
duration,
|
|
9933
|
-
startProgress,
|
|
9934
|
-
onUpdate: ({ value }) => {
|
|
9935
|
-
debug("transition_updates", "Old content slide out:", value);
|
|
9936
|
-
},
|
|
9937
|
-
}),
|
|
9938
|
-
);
|
|
9939
|
-
|
|
9940
|
-
// Slide new content in
|
|
9941
|
-
transitions.push(
|
|
9942
|
-
createTranslateXTransition(newElement, naturalNewPosition, {
|
|
9943
|
-
setup: () =>
|
|
9944
|
-
notifyTransition(newElement, {
|
|
9945
|
-
modelId: slideLeft.id,
|
|
9946
|
-
canOverflow: true,
|
|
9947
|
-
id: "slide_in_new_content",
|
|
9948
|
-
}),
|
|
9949
|
-
from: effectiveFromPosition,
|
|
9950
|
-
duration,
|
|
9951
|
-
startProgress,
|
|
9952
|
-
onUpdate: ({ value, timing }) => {
|
|
9953
|
-
debug("transition_updates", "New content slide in:", value);
|
|
9954
|
-
if (timing === "end") {
|
|
9955
|
-
debug("content", "Slide complete");
|
|
9956
|
-
}
|
|
9957
|
-
},
|
|
9958
|
-
}),
|
|
9959
|
-
);
|
|
9960
|
-
|
|
9961
|
-
return transitions;
|
|
9962
|
-
},
|
|
9963
|
-
};
|
|
9964
|
-
|
|
9965
|
-
const crossFade = {
|
|
9966
|
-
id: "ui_transition_cross_fade",
|
|
9967
|
-
name: "cross-fade",
|
|
9968
|
-
apply: (
|
|
9969
|
-
oldElement,
|
|
9970
|
-
newElement,
|
|
9971
|
-
{ duration, startProgress = 0, isPhaseTransition = false, debug },
|
|
9972
|
-
) => {
|
|
9973
|
-
if (!oldElement && !newElement) {
|
|
9974
|
-
return [];
|
|
9975
|
-
}
|
|
9976
|
-
|
|
9977
|
-
if (!newElement) {
|
|
9978
|
-
// Content -> Empty (fade out only)
|
|
9979
|
-
const from = getOpacity(oldElement);
|
|
9980
|
-
const to = 0;
|
|
9981
|
-
debug("content", "Fade out to empty:", { from, to });
|
|
9982
|
-
return [
|
|
9983
|
-
createOpacityTransition(oldElement, to, {
|
|
9984
|
-
setup: () =>
|
|
9985
|
-
notifyTransition(newElement, {
|
|
9986
|
-
modelId: crossFade.id,
|
|
9987
|
-
canOverflow: true,
|
|
9988
|
-
id: "fade_out_old_content",
|
|
9989
|
-
}),
|
|
9990
|
-
from,
|
|
9991
|
-
duration,
|
|
9992
|
-
startProgress,
|
|
9993
|
-
onUpdate: ({ value, timing }) => {
|
|
9994
|
-
debug("transition_updates", "Content fade out:", value.toFixed(3));
|
|
9995
|
-
if (timing === "end") {
|
|
9996
|
-
debug("content", "Fade out complete");
|
|
9997
|
-
}
|
|
9998
|
-
},
|
|
9999
|
-
}),
|
|
10000
|
-
];
|
|
10001
|
-
}
|
|
10002
|
-
|
|
10003
|
-
if (!oldElement) {
|
|
10004
|
-
// Empty -> Content (fade in only)
|
|
10005
|
-
const from = 0;
|
|
10006
|
-
const to = getOpacityWithoutTransition(newElement);
|
|
10007
|
-
debug("content", "Fade in from empty:", { from, to });
|
|
10008
|
-
return [
|
|
10009
|
-
createOpacityTransition(newElement, to, {
|
|
10010
|
-
setup: () =>
|
|
10011
|
-
notifyTransition(newElement, {
|
|
10012
|
-
modelId: crossFade.id,
|
|
10013
|
-
canOverflow: true,
|
|
10014
|
-
id: "fade_in_new_content",
|
|
10015
|
-
}),
|
|
10016
|
-
from,
|
|
10017
|
-
duration,
|
|
10018
|
-
startProgress,
|
|
10019
|
-
onUpdate: ({ value, timing }) => {
|
|
10020
|
-
debug("transition_updates", "Fade in progress:", value.toFixed(3));
|
|
10021
|
-
if (timing === "end") {
|
|
10022
|
-
debug("content", "Fade in complete");
|
|
10023
|
-
}
|
|
10024
|
-
},
|
|
10025
|
-
}),
|
|
10026
|
-
];
|
|
10027
|
-
}
|
|
10028
|
-
|
|
10029
|
-
// Content -> Content (cross-fade)
|
|
10030
|
-
// Get current opacity for both elements
|
|
10031
|
-
const oldOpacity = getOpacity(oldElement);
|
|
10032
|
-
const newOpacity = getOpacity(newElement);
|
|
10033
|
-
const newNaturalOpacity = getOpacityWithoutTransition(newElement);
|
|
10034
|
-
|
|
10035
|
-
// For phase transitions, always start new content from 0 for clean visual transition
|
|
10036
|
-
// For content transitions, check for ongoing transitions to continue smoothly
|
|
10037
|
-
let effectiveFromOpacity;
|
|
10038
|
-
if (isPhaseTransition) {
|
|
10039
|
-
effectiveFromOpacity = 0; // Always start fresh for phase transitions (loading → content, etc.)
|
|
10040
|
-
} else {
|
|
10041
|
-
// For content transitions: if new element has ongoing opacity transition
|
|
10042
|
-
// (indicated by non-zero opacity when natural opacity is different),
|
|
10043
|
-
// start from current opacity to continue smoothly, otherwise start from 0
|
|
10044
|
-
const hasOngoingTransition =
|
|
10045
|
-
newOpacity !== newNaturalOpacity && newOpacity > 0;
|
|
10046
|
-
effectiveFromOpacity = hasOngoingTransition ? newOpacity : 0;
|
|
10047
|
-
}
|
|
10048
|
-
|
|
10049
|
-
debug("content", "Cross-fade transition:", {
|
|
10050
|
-
oldOpacity: `${oldOpacity} → 0`,
|
|
10051
|
-
newOpacity: `${effectiveFromOpacity} → ${newNaturalOpacity}`,
|
|
10052
|
-
isPhaseTransition,
|
|
10053
|
-
});
|
|
10054
|
-
|
|
10055
|
-
return [
|
|
10056
|
-
createOpacityTransition(oldElement, 0, {
|
|
10057
|
-
setup: () =>
|
|
10058
|
-
notifyTransition(newElement, {
|
|
10059
|
-
modelId: crossFade.id,
|
|
10060
|
-
canOverflow: true,
|
|
10061
|
-
id: "fade_out_old_content",
|
|
10062
|
-
}),
|
|
10063
|
-
from: oldOpacity,
|
|
10064
|
-
duration,
|
|
10065
|
-
startProgress,
|
|
10066
|
-
onUpdate: ({ value }) => {
|
|
10067
|
-
if (value > 0) {
|
|
10068
|
-
debug(
|
|
10069
|
-
"transition_updates",
|
|
10070
|
-
"Old content fade out:",
|
|
10071
|
-
value.toFixed(3),
|
|
10072
|
-
);
|
|
10073
|
-
}
|
|
10074
|
-
},
|
|
10075
|
-
}),
|
|
10076
|
-
createOpacityTransition(newElement, newNaturalOpacity, {
|
|
10077
|
-
setup: () =>
|
|
10078
|
-
notifyTransition(newElement, {
|
|
10079
|
-
modelId: crossFade.id,
|
|
10080
|
-
canOverflow: true,
|
|
10081
|
-
id: "fade_in_new_content",
|
|
10082
|
-
}),
|
|
10083
|
-
from: effectiveFromOpacity,
|
|
10084
|
-
duration,
|
|
10085
|
-
startProgress: isPhaseTransition ? 0 : startProgress, // Phase transitions: new content always starts fresh
|
|
10086
|
-
onUpdate: ({ value, timing }) => {
|
|
10087
|
-
debug("transition_updates", "New content fade in:", value.toFixed(3));
|
|
10088
|
-
if (timing === "end") {
|
|
10089
|
-
debug("content", "Cross-fade complete");
|
|
10090
|
-
}
|
|
10091
|
-
},
|
|
10092
|
-
}),
|
|
10093
|
-
];
|
|
10094
|
-
},
|
|
10095
|
-
};
|
|
10096
9476
|
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
9477
|
+
transitionTo,
|
|
9478
|
+
resetContent,
|
|
9479
|
+
setDuration,
|
|
9480
|
+
setAlignment,
|
|
9481
|
+
updateAlignment,
|
|
9482
|
+
setPauseBreakpoints: (value) => {
|
|
9483
|
+
groupTransitionOptions.pauseBreakpoints = value;
|
|
9484
|
+
},
|
|
9485
|
+
cleanup: () => {
|
|
9486
|
+
teardown();
|
|
9487
|
+
},
|
|
10101
9488
|
};
|
|
10102
9489
|
};
|
|
10103
|
-
const dispatchUITransitionStartCustomEvent = (element, detail) => {
|
|
10104
|
-
const customEvent = new CustomEvent("ui_transition_start", {
|
|
10105
|
-
bubbles: true,
|
|
10106
|
-
detail,
|
|
10107
|
-
});
|
|
10108
|
-
element.dispatchEvent(customEvent);
|
|
10109
|
-
};
|
|
10110
|
-
const dispatchUITransitionEndCustomEvent = (element, detail) => {
|
|
10111
|
-
const customEvent = new CustomEvent("ui_transition_end", {
|
|
10112
|
-
bubbles: true,
|
|
10113
|
-
detail,
|
|
10114
|
-
});
|
|
10115
|
-
element.dispatchEvent(customEvent);
|
|
10116
|
-
};
|
|
10117
9490
|
|
|
10118
9491
|
/**
|
|
10119
9492
|
* UITransition
|
|
@@ -10130,76 +9503,81 @@ const dispatchUITransitionEndCustomEvent = (element, detail) => {
|
|
|
10130
9503
|
*
|
|
10131
9504
|
* Usage:
|
|
10132
9505
|
* - Wrap dynamic content in <UITransition> to animate between states
|
|
10133
|
-
* - Set a unique `data-content-
|
|
9506
|
+
* - Set a unique `data-content-id` on your rendered content to identify each content variant
|
|
10134
9507
|
* - Use `data-content-phase` to mark loading/error states for phase transitions
|
|
10135
9508
|
* - Configure transition types and durations for both content and phase changes
|
|
10136
9509
|
*
|
|
10137
9510
|
* Example:
|
|
10138
9511
|
*
|
|
10139
|
-
* <UITransition
|
|
10140
|
-
* transitionType="slide-left"
|
|
10141
|
-
* transitionDuration={400}
|
|
10142
|
-
* phaseTransitionType="cross-fade"
|
|
10143
|
-
* phaseTransitionDuration={300}
|
|
10144
|
-
* >
|
|
9512
|
+
* <UITransition>
|
|
10145
9513
|
* {isLoading
|
|
10146
9514
|
* ? <Spinner data-content-key={userId} data-content-phase />
|
|
10147
9515
|
* : <UserProfile user={user} data-content-key={userId} />}
|
|
10148
9516
|
* </UITransition>
|
|
10149
9517
|
*
|
|
10150
|
-
* When `data-content-
|
|
9518
|
+
* When `data-content-id` changes, UITransition animates content transitions.
|
|
10151
9519
|
* When `data-content-phase` changes for the same key, it animates phase transitions.
|
|
10152
9520
|
*/
|
|
10153
9521
|
|
|
10154
|
-
const
|
|
9522
|
+
const UITransitionContentIdContext = createContext();
|
|
10155
9523
|
const UITransition = ({
|
|
10156
9524
|
children,
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
transitionType,
|
|
10161
|
-
transitionDuration,
|
|
10162
|
-
phaseTransitionType,
|
|
10163
|
-
phaseTransitionDuration,
|
|
9525
|
+
contentId,
|
|
9526
|
+
type,
|
|
9527
|
+
duration,
|
|
10164
9528
|
debugDetection,
|
|
9529
|
+
debugContent,
|
|
10165
9530
|
debugSize,
|
|
10166
|
-
|
|
9531
|
+
disabled,
|
|
9532
|
+
uiTransitionRef,
|
|
9533
|
+
alignX,
|
|
9534
|
+
alignY,
|
|
10167
9535
|
...props
|
|
10168
9536
|
}) => {
|
|
10169
|
-
const
|
|
10170
|
-
const
|
|
10171
|
-
const
|
|
10172
|
-
|
|
10173
|
-
|
|
9537
|
+
const contentIdRef = useRef(contentId);
|
|
9538
|
+
const updateContentId = () => {
|
|
9539
|
+
const uiTransition = uiTransitionRef.current;
|
|
9540
|
+
if (!uiTransition) {
|
|
9541
|
+
return;
|
|
9542
|
+
}
|
|
9543
|
+
const value = contentIdRef.current;
|
|
9544
|
+
uiTransition.updateContentId(value);
|
|
9545
|
+
};
|
|
9546
|
+
const uiTransitionContentIdContextValue = useMemo(() => {
|
|
9547
|
+
const set = new Set();
|
|
9548
|
+
const onSetChange = () => {
|
|
9549
|
+
const value = Array.from(set).join("|");
|
|
9550
|
+
contentIdRef.current = value;
|
|
9551
|
+
updateContentId();
|
|
10174
9552
|
};
|
|
10175
|
-
const update = (
|
|
10176
|
-
if (!
|
|
10177
|
-
console.warn(`UITransition: trying to update
|
|
9553
|
+
const update = (part, newPart) => {
|
|
9554
|
+
if (!set.has(part)) {
|
|
9555
|
+
console.warn(`UITransition: trying to update an id that does not exist: ${part}`);
|
|
10178
9556
|
return;
|
|
10179
9557
|
}
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
|
|
9558
|
+
set.delete(part);
|
|
9559
|
+
set.add(newPart);
|
|
9560
|
+
onSetChange();
|
|
10183
9561
|
};
|
|
10184
|
-
const add =
|
|
10185
|
-
if (!
|
|
9562
|
+
const add = part => {
|
|
9563
|
+
if (!part) {
|
|
10186
9564
|
return;
|
|
10187
9565
|
}
|
|
10188
|
-
if (
|
|
9566
|
+
if (set.has(part)) {
|
|
10189
9567
|
return;
|
|
10190
9568
|
}
|
|
10191
|
-
|
|
10192
|
-
|
|
9569
|
+
set.add(part);
|
|
9570
|
+
onSetChange();
|
|
10193
9571
|
};
|
|
10194
|
-
const remove =
|
|
10195
|
-
if (!
|
|
9572
|
+
const remove = part => {
|
|
9573
|
+
if (!part) {
|
|
10196
9574
|
return;
|
|
10197
9575
|
}
|
|
10198
|
-
if (!
|
|
9576
|
+
if (!set.has(part)) {
|
|
10199
9577
|
return;
|
|
10200
9578
|
}
|
|
10201
|
-
|
|
10202
|
-
|
|
9579
|
+
set.delete(part);
|
|
9580
|
+
onSetChange();
|
|
10203
9581
|
};
|
|
10204
9582
|
return {
|
|
10205
9583
|
add,
|
|
@@ -10207,42 +9585,54 @@ const UITransition = ({
|
|
|
10207
9585
|
remove
|
|
10208
9586
|
};
|
|
10209
9587
|
}, []);
|
|
10210
|
-
const effectiveContentKey = contentKey || contentKeyFromContext;
|
|
10211
9588
|
const ref = useRef();
|
|
9589
|
+
const uiTransitionRefDefault = useRef();
|
|
9590
|
+
uiTransitionRef = uiTransitionRef || uiTransitionRefDefault;
|
|
10212
9591
|
useLayoutEffect(() => {
|
|
10213
|
-
|
|
9592
|
+
if (disabled) {
|
|
9593
|
+
return null;
|
|
9594
|
+
}
|
|
9595
|
+
const uiTransition = createUITransitionController(ref.current, {
|
|
9596
|
+
alignX,
|
|
9597
|
+
alignY
|
|
9598
|
+
});
|
|
9599
|
+
uiTransitionRef.current = uiTransition;
|
|
10214
9600
|
return () => {
|
|
10215
9601
|
uiTransition.cleanup();
|
|
10216
9602
|
};
|
|
10217
|
-
}, []);
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
"
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
children:
|
|
10236
|
-
|
|
10237
|
-
"data-content-key": effectiveContentKey ? effectiveContentKey : undefined,
|
|
9603
|
+
}, [disabled, alignX, alignY]);
|
|
9604
|
+
if (disabled) {
|
|
9605
|
+
return children;
|
|
9606
|
+
}
|
|
9607
|
+
return jsxs("div", {
|
|
9608
|
+
ref: ref,
|
|
9609
|
+
...props,
|
|
9610
|
+
className: "ui_transition",
|
|
9611
|
+
"data-transition-type": type,
|
|
9612
|
+
"data-transition-duration": duration,
|
|
9613
|
+
"data-debug-detection": debugDetection ? "" : undefined,
|
|
9614
|
+
"data-debug-size": debugSize ? "" : undefined,
|
|
9615
|
+
"data-debug-content": debugContent ? "" : undefined,
|
|
9616
|
+
children: [jsxs("div", {
|
|
9617
|
+
className: "ui_transition_active_group",
|
|
9618
|
+
children: [jsx("div", {
|
|
9619
|
+
className: "ui_transition_target_slot",
|
|
9620
|
+
"data-content-id": contentIdRef.current ? contentIdRef.current : undefined,
|
|
9621
|
+
children: jsx(UITransitionContentIdContext.Provider, {
|
|
9622
|
+
value: uiTransitionContentIdContextValue,
|
|
10238
9623
|
children: children
|
|
10239
|
-
})
|
|
10240
|
-
className: "ui_transition_phase_overlay"
|
|
10241
|
-
})]
|
|
9624
|
+
})
|
|
10242
9625
|
}), jsx("div", {
|
|
10243
|
-
className: "
|
|
9626
|
+
className: "ui_transition_outgoing_slot"
|
|
10244
9627
|
})]
|
|
10245
|
-
})
|
|
9628
|
+
}), jsxs("div", {
|
|
9629
|
+
className: "ui_transition_previous_group",
|
|
9630
|
+
children: [jsx("div", {
|
|
9631
|
+
className: "ui_transition_previous_target_slot"
|
|
9632
|
+
}), jsx("div", {
|
|
9633
|
+
className: "ui_transition_previous_outgoing_slot"
|
|
9634
|
+
})]
|
|
9635
|
+
})]
|
|
10246
9636
|
});
|
|
10247
9637
|
};
|
|
10248
9638
|
|
|
@@ -10254,28 +9644,28 @@ const UITransition = ({
|
|
|
10254
9644
|
* as changed even if the component is still the same
|
|
10255
9645
|
*
|
|
10256
9646
|
* This is used by <Route> to set the content key to the route path
|
|
10257
|
-
* When the route becomes inactive it will call
|
|
10258
|
-
* And if a sibling route becones active it will call
|
|
9647
|
+
* When the route becomes inactive it will call useUITransitionContentId(undefined)
|
|
9648
|
+
* And if a sibling route becones active it will call useUITransitionContentId with its own path
|
|
10259
9649
|
*
|
|
10260
9650
|
*/
|
|
10261
|
-
const
|
|
10262
|
-
const
|
|
10263
|
-
const
|
|
10264
|
-
if (
|
|
10265
|
-
const
|
|
10266
|
-
|
|
10267
|
-
if (
|
|
10268
|
-
|
|
9651
|
+
const useUITransitionContentId = value => {
|
|
9652
|
+
const contentId = useContext(UITransitionContentIdContext);
|
|
9653
|
+
const valueRef = useRef();
|
|
9654
|
+
if (contentId !== undefined && valueRef.current !== value) {
|
|
9655
|
+
const previousValue = valueRef.current;
|
|
9656
|
+
valueRef.current = value;
|
|
9657
|
+
if (previousValue === undefined) {
|
|
9658
|
+
contentId.add(value);
|
|
10269
9659
|
} else {
|
|
10270
|
-
|
|
9660
|
+
contentId.update(previousValue, value);
|
|
10271
9661
|
}
|
|
10272
9662
|
}
|
|
10273
9663
|
useLayoutEffect(() => {
|
|
10274
|
-
if (
|
|
9664
|
+
if (contentId === undefined) {
|
|
10275
9665
|
return null;
|
|
10276
9666
|
}
|
|
10277
9667
|
return () => {
|
|
10278
|
-
|
|
9668
|
+
contentId.remove(valueRef.current);
|
|
10279
9669
|
};
|
|
10280
9670
|
}, []);
|
|
10281
9671
|
};
|
|
@@ -10331,10 +9721,13 @@ const Routes = ({
|
|
|
10331
9721
|
});
|
|
10332
9722
|
};
|
|
10333
9723
|
const SlotContext = createContext(null);
|
|
9724
|
+
const RouteInfoContext = createContext(null);
|
|
9725
|
+
const useActiveRouteInfo = () => useContext(RouteInfoContext);
|
|
10334
9726
|
const Route = ({
|
|
10335
9727
|
element,
|
|
10336
9728
|
route,
|
|
10337
9729
|
fallback,
|
|
9730
|
+
meta,
|
|
10338
9731
|
children
|
|
10339
9732
|
}) => {
|
|
10340
9733
|
const forceRender = useForceRender();
|
|
@@ -10345,6 +9738,7 @@ const Route = ({
|
|
|
10345
9738
|
element: element,
|
|
10346
9739
|
route: route,
|
|
10347
9740
|
fallback: fallback,
|
|
9741
|
+
meta: meta,
|
|
10348
9742
|
onActiveInfoChange: activeInfo => {
|
|
10349
9743
|
hasDiscoveredRef.current = true;
|
|
10350
9744
|
activeInfoRef.current = activeInfo;
|
|
@@ -10371,18 +9765,23 @@ const ActiveRouteManager = ({
|
|
|
10371
9765
|
element,
|
|
10372
9766
|
route,
|
|
10373
9767
|
fallback,
|
|
9768
|
+
meta,
|
|
10374
9769
|
onActiveInfoChange,
|
|
10375
9770
|
children
|
|
10376
9771
|
}) => {
|
|
9772
|
+
if (route && fallback) {
|
|
9773
|
+
throw new Error("Route cannot have both route and fallback props");
|
|
9774
|
+
}
|
|
10377
9775
|
const registerChildRouteFromContext = useContext(RegisterChildRouteContext);
|
|
10378
9776
|
getElementSignature(element);
|
|
10379
9777
|
const candidateSet = new Set();
|
|
10380
|
-
const registerChildRoute = (ChildActiveElement, childRoute, childFallback) => {
|
|
9778
|
+
const registerChildRoute = (ChildActiveElement, childRoute, childFallback, childMeta) => {
|
|
10381
9779
|
getElementSignature(ChildActiveElement);
|
|
10382
9780
|
candidateSet.add({
|
|
10383
9781
|
ActiveElement: ChildActiveElement,
|
|
10384
9782
|
route: childRoute,
|
|
10385
|
-
fallback: childFallback
|
|
9783
|
+
fallback: childFallback,
|
|
9784
|
+
meta: childMeta
|
|
10386
9785
|
});
|
|
10387
9786
|
};
|
|
10388
9787
|
useLayoutEffect(() => {
|
|
@@ -10390,6 +9789,7 @@ const ActiveRouteManager = ({
|
|
|
10390
9789
|
element,
|
|
10391
9790
|
route,
|
|
10392
9791
|
fallback,
|
|
9792
|
+
meta,
|
|
10393
9793
|
candidateSet,
|
|
10394
9794
|
onActiveInfoChange,
|
|
10395
9795
|
registerChildRouteFromContext
|
|
@@ -10404,6 +9804,7 @@ const initRouteObserver = ({
|
|
|
10404
9804
|
element,
|
|
10405
9805
|
route,
|
|
10406
9806
|
fallback,
|
|
9807
|
+
meta,
|
|
10407
9808
|
candidateSet,
|
|
10408
9809
|
onActiveInfoChange,
|
|
10409
9810
|
registerChildRouteFromContext
|
|
@@ -10424,19 +9825,13 @@ const initRouteObserver = ({
|
|
|
10424
9825
|
let fallbackInfo = null;
|
|
10425
9826
|
for (const candidate of candidateSet) {
|
|
10426
9827
|
if (candidate.route?.active) {
|
|
10427
|
-
return
|
|
10428
|
-
ChildActiveElement: candidate.ActiveElement,
|
|
10429
|
-
route: candidate.route
|
|
10430
|
-
};
|
|
9828
|
+
return candidate;
|
|
10431
9829
|
}
|
|
10432
9830
|
// fallback without route can match when no other route matches.
|
|
10433
9831
|
// This is useful solely for "catch all" fallback used on the <Routes>
|
|
10434
9832
|
// otherwise a fallback would always match and make the parent route always active
|
|
10435
9833
|
if (candidate.fallback && !candidate.route.routeFromProps) {
|
|
10436
|
-
fallbackInfo =
|
|
10437
|
-
ChildActiveElement: candidate.ActiveElement,
|
|
10438
|
-
route: candidate.route
|
|
10439
|
-
};
|
|
9834
|
+
fallbackInfo = candidate;
|
|
10440
9835
|
}
|
|
10441
9836
|
}
|
|
10442
9837
|
return fallbackInfo;
|
|
@@ -10453,8 +9848,9 @@ const initRouteObserver = ({
|
|
|
10453
9848
|
return activeChildInfo;
|
|
10454
9849
|
}
|
|
10455
9850
|
return {
|
|
10456
|
-
|
|
10457
|
-
route
|
|
9851
|
+
ActiveElement: null,
|
|
9852
|
+
route,
|
|
9853
|
+
meta
|
|
10458
9854
|
};
|
|
10459
9855
|
} : () => {
|
|
10460
9856
|
// we don't have a route, do we have an active child?
|
|
@@ -10464,22 +9860,22 @@ const initRouteObserver = ({
|
|
|
10464
9860
|
}
|
|
10465
9861
|
return null;
|
|
10466
9862
|
};
|
|
10467
|
-
const
|
|
9863
|
+
const activeRouteInfoSignal = signal();
|
|
10468
9864
|
const SlotActiveElementSignal = signal();
|
|
10469
9865
|
const ActiveElement = () => {
|
|
10470
|
-
const
|
|
10471
|
-
|
|
9866
|
+
const activeRouteInfo = activeRouteInfoSignal.value;
|
|
9867
|
+
useUITransitionContentId(activeRouteInfo ? activeRouteInfo.route.urlPattern : fallback ? "fallback" : undefined);
|
|
10472
9868
|
const SlotActiveElement = SlotActiveElementSignal.value;
|
|
10473
9869
|
if (typeof element === "function") {
|
|
10474
9870
|
const Element = element;
|
|
10475
|
-
|
|
10476
|
-
value: SlotActiveElement,
|
|
10477
|
-
children: jsx(Element, {})
|
|
10478
|
-
});
|
|
9871
|
+
element = jsx(Element, {});
|
|
10479
9872
|
}
|
|
10480
|
-
return jsx(
|
|
10481
|
-
value:
|
|
10482
|
-
children:
|
|
9873
|
+
return jsx(RouteInfoContext.Provider, {
|
|
9874
|
+
value: activeRouteInfo,
|
|
9875
|
+
children: jsx(SlotContext.Provider, {
|
|
9876
|
+
value: SlotActiveElement,
|
|
9877
|
+
children: element
|
|
9878
|
+
})
|
|
10483
9879
|
});
|
|
10484
9880
|
};
|
|
10485
9881
|
ActiveElement.underlyingElementId = candidateSet.size === 0 ? `${getElementSignature(element)} without slot` : `[${getElementSignature(element)} with slot one of ${candidateElementIds}]`;
|
|
@@ -10487,20 +9883,17 @@ const initRouteObserver = ({
|
|
|
10487
9883
|
const newActiveInfo = getActiveInfo();
|
|
10488
9884
|
if (newActiveInfo) {
|
|
10489
9885
|
compositeRoute.active = true;
|
|
10490
|
-
|
|
10491
|
-
|
|
10492
|
-
ChildActiveElement
|
|
10493
|
-
} = newActiveInfo;
|
|
10494
|
-
activeRouteSignal.value = route;
|
|
10495
|
-
SlotActiveElementSignal.value = ChildActiveElement;
|
|
9886
|
+
activeRouteInfoSignal.value = newActiveInfo;
|
|
9887
|
+
SlotActiveElementSignal.value = newActiveInfo.ActiveElement;
|
|
10496
9888
|
onActiveInfoChange({
|
|
10497
|
-
route: newActiveInfo.route,
|
|
10498
9889
|
ActiveElement,
|
|
10499
|
-
SlotActiveElement:
|
|
9890
|
+
SlotActiveElement: newActiveInfo.ActiveElement,
|
|
9891
|
+
route: newActiveInfo.route,
|
|
9892
|
+
meta: newActiveInfo.meta
|
|
10500
9893
|
});
|
|
10501
9894
|
} else {
|
|
10502
9895
|
compositeRoute.active = false;
|
|
10503
|
-
|
|
9896
|
+
activeRouteInfoSignal.value = null;
|
|
10504
9897
|
SlotActiveElementSignal.value = null;
|
|
10505
9898
|
onActiveInfoChange(null);
|
|
10506
9899
|
}
|
|
@@ -10516,7 +9909,7 @@ const initRouteObserver = ({
|
|
|
10516
9909
|
candidate.route.subscribeStatus(onChange);
|
|
10517
9910
|
}
|
|
10518
9911
|
if (registerChildRouteFromContext) {
|
|
10519
|
-
registerChildRouteFromContext(ActiveElement, compositeRoute, fallback);
|
|
9912
|
+
registerChildRouteFromContext(ActiveElement, compositeRoute, fallback, meta);
|
|
10520
9913
|
}
|
|
10521
9914
|
updateActiveInfo();
|
|
10522
9915
|
};
|
|
@@ -10718,14 +10111,11 @@ const renderActionableComponent = (props, {
|
|
|
10718
10111
|
|
|
10719
10112
|
const normalizeSpacingStyle = (value, property = "padding") => {
|
|
10720
10113
|
const cssSize = sizeSpacingScale[value];
|
|
10721
|
-
return cssSize ||
|
|
10114
|
+
return cssSize || stringifyStyle(value, property);
|
|
10722
10115
|
};
|
|
10723
10116
|
const normalizeTypoStyle = (value, property = "fontSize") => {
|
|
10724
10117
|
const cssSize = sizeTypoScale[value];
|
|
10725
|
-
return cssSize ||
|
|
10726
|
-
};
|
|
10727
|
-
const normalizeCssStyle = (value, property) => {
|
|
10728
|
-
return normalizeStyle(value, property, "css");
|
|
10118
|
+
return cssSize || stringifyStyle(value, property);
|
|
10729
10119
|
};
|
|
10730
10120
|
|
|
10731
10121
|
const PASS_THROUGH = { name: "pass_through" };
|
|
@@ -10776,6 +10166,13 @@ const applyOnTwoProps = (propA, propB) => {
|
|
|
10776
10166
|
};
|
|
10777
10167
|
};
|
|
10778
10168
|
|
|
10169
|
+
const LAYOUT_PROPS = {
|
|
10170
|
+
// all are handled by data-attributes
|
|
10171
|
+
inline: () => {},
|
|
10172
|
+
box: () => {},
|
|
10173
|
+
row: () => {},
|
|
10174
|
+
column: () => {},
|
|
10175
|
+
};
|
|
10779
10176
|
const OUTER_SPACING_PROPS = {
|
|
10780
10177
|
margin: PASS_THROUGH,
|
|
10781
10178
|
marginLeft: PASS_THROUGH,
|
|
@@ -10812,21 +10209,21 @@ const DIMENSION_PROPS = {
|
|
|
10812
10209
|
return { flexGrow: 1 }; // Grow horizontally in row
|
|
10813
10210
|
}
|
|
10814
10211
|
if (parentLayout === "row") {
|
|
10815
|
-
return { minWidth: "100%" }; // Take full width in column
|
|
10212
|
+
return { minWidth: "100%", width: "auto" }; // Take full width in column
|
|
10816
10213
|
}
|
|
10817
|
-
return { minWidth: "100%" }; // Take full width outside flex
|
|
10214
|
+
return { minWidth: "100%", width: "auto" }; // Take full width outside flex
|
|
10818
10215
|
},
|
|
10819
10216
|
expandY: (value, { parentLayout }) => {
|
|
10820
10217
|
if (!value) {
|
|
10821
10218
|
return null;
|
|
10822
10219
|
}
|
|
10823
10220
|
if (parentLayout === "column") {
|
|
10824
|
-
return { minHeight: "100%" }; // Make column full height
|
|
10221
|
+
return { minHeight: "100%", height: "auto" }; // Make column full height
|
|
10825
10222
|
}
|
|
10826
10223
|
if (parentLayout === "row" || parentLayout === "inline-row") {
|
|
10827
10224
|
return { flexGrow: 1 }; // Make row full height
|
|
10828
10225
|
}
|
|
10829
|
-
return { minHeight: "100%" }; // Take full height outside flex
|
|
10226
|
+
return { minHeight: "100%", height: "auto" }; // Take full height outside flex
|
|
10830
10227
|
},
|
|
10831
10228
|
shrinkX: (value, { parentLayout }) => {
|
|
10832
10229
|
if (!value) {
|
|
@@ -10846,6 +10243,23 @@ const DIMENSION_PROPS = {
|
|
|
10846
10243
|
}
|
|
10847
10244
|
return { maxHeight: "100%" };
|
|
10848
10245
|
},
|
|
10246
|
+
|
|
10247
|
+
scaleX: (value) => {
|
|
10248
|
+
return { transform: `scaleX(${stringifyStyle(value, "scaleX")})` };
|
|
10249
|
+
},
|
|
10250
|
+
scaleY: (value) => {
|
|
10251
|
+
return { transform: `scaleY(${value})` };
|
|
10252
|
+
},
|
|
10253
|
+
scale: (value) => {
|
|
10254
|
+
if (Array.isArray(value)) {
|
|
10255
|
+
const [x, y] = value;
|
|
10256
|
+
return { transform: `scale(${x}, ${y})` };
|
|
10257
|
+
}
|
|
10258
|
+
return { transform: `scale(${value})` };
|
|
10259
|
+
},
|
|
10260
|
+
scaleZ: (value) => {
|
|
10261
|
+
return { transform: `scaleZ(${value})` };
|
|
10262
|
+
},
|
|
10849
10263
|
};
|
|
10850
10264
|
const POSITION_PROPS = {
|
|
10851
10265
|
// For row, alignX uses auto margins for positioning
|
|
@@ -10886,7 +10300,7 @@ const POSITION_PROPS = {
|
|
|
10886
10300
|
|
|
10887
10301
|
if (value === "start") {
|
|
10888
10302
|
if (inlineColumnLayout) {
|
|
10889
|
-
return
|
|
10303
|
+
return { alignSelf: "start" };
|
|
10890
10304
|
}
|
|
10891
10305
|
return { marginBottom: "auto" };
|
|
10892
10306
|
}
|
|
@@ -10906,8 +10320,49 @@ const POSITION_PROPS = {
|
|
|
10906
10320
|
},
|
|
10907
10321
|
left: PASS_THROUGH,
|
|
10908
10322
|
top: PASS_THROUGH,
|
|
10323
|
+
|
|
10324
|
+
translateX: (value) => {
|
|
10325
|
+
return { transform: `translateX(${value})` };
|
|
10326
|
+
},
|
|
10327
|
+
translateY: (value) => {
|
|
10328
|
+
return { transform: `translateY(${value})` };
|
|
10329
|
+
},
|
|
10330
|
+
translate: (value) => {
|
|
10331
|
+
if (Array.isArray(value)) {
|
|
10332
|
+
const [x, y] = value;
|
|
10333
|
+
return { transform: `translate(${x}, ${y})` };
|
|
10334
|
+
}
|
|
10335
|
+
return { transform: `translate(${stringifyStyle(value, "translateX")})` };
|
|
10336
|
+
},
|
|
10337
|
+
rotateX: (value) => {
|
|
10338
|
+
return { transform: `rotateX(${value})` };
|
|
10339
|
+
},
|
|
10340
|
+
rotateY: (value) => {
|
|
10341
|
+
return { transform: `rotateY(${value})` };
|
|
10342
|
+
},
|
|
10343
|
+
rotateZ: (value) => {
|
|
10344
|
+
return { transform: `rotateZ(${value})` };
|
|
10345
|
+
},
|
|
10346
|
+
rotate: (value) => {
|
|
10347
|
+
return { transform: `rotate(${value})` };
|
|
10348
|
+
},
|
|
10349
|
+
skewX: (value) => {
|
|
10350
|
+
return { transform: `skewX(${value})` };
|
|
10351
|
+
},
|
|
10352
|
+
skewY: (value) => {
|
|
10353
|
+
return { transform: `skewY(${value})` };
|
|
10354
|
+
},
|
|
10355
|
+
skew: (value) => {
|
|
10356
|
+
if (Array.isArray(value)) {
|
|
10357
|
+
const [x, y] = value;
|
|
10358
|
+
return { transform: `skew(${x}, ${y})` };
|
|
10359
|
+
}
|
|
10360
|
+
return { transform: `skew(${value})` };
|
|
10361
|
+
},
|
|
10909
10362
|
};
|
|
10910
10363
|
const TYPO_PROPS = {
|
|
10364
|
+
font: PASS_THROUGH,
|
|
10365
|
+
fontFamily: PASS_THROUGH,
|
|
10911
10366
|
size: applyOnCSSProp("fontSize"),
|
|
10912
10367
|
fontSize: PASS_THROUGH,
|
|
10913
10368
|
bold: applyToCssPropWhenTruthy("fontWeight", "bold", "normal"),
|
|
@@ -10924,6 +10379,11 @@ const TYPO_PROPS = {
|
|
|
10924
10379
|
preWrap: applyToCssPropWhenTruthy("whiteSpace", "pre-wrap", "normal"),
|
|
10925
10380
|
};
|
|
10926
10381
|
const VISUAL_PROPS = {
|
|
10382
|
+
outline: PASS_THROUGH,
|
|
10383
|
+
outlineStyle: PASS_THROUGH,
|
|
10384
|
+
outlineColor: PASS_THROUGH,
|
|
10385
|
+
outlineWidth: PASS_THROUGH,
|
|
10386
|
+
boxDecorationBreak: PASS_THROUGH,
|
|
10927
10387
|
boxShadow: PASS_THROUGH,
|
|
10928
10388
|
background: PASS_THROUGH,
|
|
10929
10389
|
backgroundColor: PASS_THROUGH,
|
|
@@ -11003,6 +10463,7 @@ const CONTENT_PROPS = {
|
|
|
11003
10463
|
},
|
|
11004
10464
|
};
|
|
11005
10465
|
const All_PROPS = {
|
|
10466
|
+
...LAYOUT_PROPS,
|
|
11006
10467
|
...OUTER_SPACING_PROPS,
|
|
11007
10468
|
...INNER_SPACING_PROPS,
|
|
11008
10469
|
...DIMENSION_PROPS,
|
|
@@ -11011,6 +10472,7 @@ const All_PROPS = {
|
|
|
11011
10472
|
...VISUAL_PROPS,
|
|
11012
10473
|
...CONTENT_PROPS,
|
|
11013
10474
|
};
|
|
10475
|
+
const LAYOUT_PROP_NAME_SET = new Set(Object.keys(LAYOUT_PROPS));
|
|
11014
10476
|
const OUTER_SPACING_PROP_NAME_SET = new Set(Object.keys(OUTER_SPACING_PROPS));
|
|
11015
10477
|
const INNER_SPACING_PROP_NAME_SET = new Set(Object.keys(INNER_SPACING_PROPS));
|
|
11016
10478
|
const DIMENSION_PROP_NAME_SET = new Set(Object.keys(DIMENSION_PROPS));
|
|
@@ -11026,6 +10488,7 @@ const HANDLED_BY_VISUAL_CHILD_PROP_SET = new Set([
|
|
|
11026
10488
|
...CONTENT_PROP_NAME_SET,
|
|
11027
10489
|
]);
|
|
11028
10490
|
const COPIED_ON_VISUAL_CHILD_PROP_SET = new Set([
|
|
10491
|
+
...LAYOUT_PROP_NAME_SET,
|
|
11029
10492
|
"expand",
|
|
11030
10493
|
"shrink",
|
|
11031
10494
|
"expandX",
|
|
@@ -11037,6 +10500,9 @@ const COPIED_ON_VISUAL_CHILD_PROP_SET = new Set([
|
|
|
11037
10500
|
const isStyleProp = (name) => STYLE_PROP_NAME_SET.has(name);
|
|
11038
10501
|
|
|
11039
10502
|
const getStylePropGroup = (name) => {
|
|
10503
|
+
if (LAYOUT_PROP_NAME_SET.has(name)) {
|
|
10504
|
+
return "layout";
|
|
10505
|
+
}
|
|
11040
10506
|
if (OUTER_SPACING_PROP_NAME_SET.has(name)) {
|
|
11041
10507
|
return "margin";
|
|
11042
10508
|
}
|
|
@@ -11068,7 +10534,7 @@ const getNormalizer = (key) => {
|
|
|
11068
10534
|
if (group === "typo") {
|
|
11069
10535
|
return normalizeTypoStyle;
|
|
11070
10536
|
}
|
|
11071
|
-
return
|
|
10537
|
+
return stringifyStyle;
|
|
11072
10538
|
};
|
|
11073
10539
|
|
|
11074
10540
|
const assignStyle = (
|
|
@@ -11076,7 +10542,7 @@ const assignStyle = (
|
|
|
11076
10542
|
propValue,
|
|
11077
10543
|
propName,
|
|
11078
10544
|
styleContext,
|
|
11079
|
-
|
|
10545
|
+
context = "js",
|
|
11080
10546
|
) => {
|
|
11081
10547
|
if (propValue === undefined) {
|
|
11082
10548
|
return;
|
|
@@ -11085,6 +10551,7 @@ const assignStyle = (
|
|
|
11085
10551
|
if (!managedByCSSVars) {
|
|
11086
10552
|
throw new Error("managedByCSSVars is required in styleContext");
|
|
11087
10553
|
}
|
|
10554
|
+
const normalizer = getNormalizer(propName);
|
|
11088
10555
|
const getStyle = All_PROPS[propName];
|
|
11089
10556
|
if (
|
|
11090
10557
|
getStyle === PASS_THROUGH ||
|
|
@@ -11093,10 +10560,16 @@ const assignStyle = (
|
|
|
11093
10560
|
) {
|
|
11094
10561
|
const cssValue = normalizer(propValue, propName);
|
|
11095
10562
|
const cssVar = managedByCSSVars[propName];
|
|
10563
|
+
const mergedValue = mergeOneStyle(
|
|
10564
|
+
styleObject[propName],
|
|
10565
|
+
cssValue,
|
|
10566
|
+
propName,
|
|
10567
|
+
context,
|
|
10568
|
+
);
|
|
11096
10569
|
if (cssVar) {
|
|
11097
|
-
styleObject[cssVar] =
|
|
10570
|
+
styleObject[cssVar] = mergedValue;
|
|
11098
10571
|
} else {
|
|
11099
|
-
styleObject[propName] =
|
|
10572
|
+
styleObject[propName] = mergedValue;
|
|
11100
10573
|
}
|
|
11101
10574
|
return;
|
|
11102
10575
|
}
|
|
@@ -11108,10 +10581,11 @@ const assignStyle = (
|
|
|
11108
10581
|
const value = values[key];
|
|
11109
10582
|
const cssValue = normalizer(value, key);
|
|
11110
10583
|
const cssVar = managedByCSSVars[key];
|
|
10584
|
+
const mergedValue = mergeOneStyle(styleObject[key], cssValue, key, context);
|
|
11111
10585
|
if (cssVar) {
|
|
11112
|
-
styleObject[cssVar] =
|
|
10586
|
+
styleObject[cssVar] = mergedValue;
|
|
11113
10587
|
} else {
|
|
11114
|
-
styleObject[key] =
|
|
10588
|
+
styleObject[key] = mergedValue;
|
|
11115
10589
|
}
|
|
11116
10590
|
}
|
|
11117
10591
|
};
|
|
@@ -11128,12 +10602,8 @@ const sizeSpacingScale = {
|
|
|
11128
10602
|
xl: "2em", // 2 = 32px at 16px base
|
|
11129
10603
|
xxl: "3em", // 3 = 48px at 16px base
|
|
11130
10604
|
};
|
|
11131
|
-
const resolveSpacingSize = (
|
|
11132
|
-
size,
|
|
11133
|
-
property = "padding",
|
|
11134
|
-
context = "css",
|
|
11135
|
-
) => {
|
|
11136
|
-
return normalizeStyle(sizeSpacingScale[size] || size, property, context);
|
|
10605
|
+
const resolveSpacingSize = (size, property = "padding") => {
|
|
10606
|
+
return stringifyStyle(sizeSpacingScale[size] || size, property);
|
|
11137
10607
|
};
|
|
11138
10608
|
|
|
11139
10609
|
const sizeTypoScale = {
|
|
@@ -11511,7 +10981,7 @@ const initPseudoStyles = (
|
|
|
11511
10981
|
}
|
|
11512
10982
|
currentState[pseudoClass] = currentValue;
|
|
11513
10983
|
const oldValue = state ? state[pseudoClass] : undefined;
|
|
11514
|
-
if (oldValue !== currentValue) {
|
|
10984
|
+
if (oldValue !== currentValue || !state) {
|
|
11515
10985
|
someChange = true;
|
|
11516
10986
|
const { attribute, add, remove } = pseudoClassDefinition;
|
|
11517
10987
|
if (currentValue) {
|
|
@@ -11566,8 +11036,15 @@ const applyStyle = (element, style, pseudoState, pseudoNamedStyles) => {
|
|
|
11566
11036
|
updateStyle(element, getStyleToApply(style, pseudoState, pseudoNamedStyles));
|
|
11567
11037
|
};
|
|
11568
11038
|
|
|
11039
|
+
const PSEUDO_STATE_DEFAULT = {};
|
|
11040
|
+
const PSEUDO_NAMED_STYLES_DEFAULT = {};
|
|
11569
11041
|
const getStyleToApply = (styles, pseudoState, pseudoNamedStyles) => {
|
|
11570
|
-
if (
|
|
11042
|
+
if (
|
|
11043
|
+
!pseudoState ||
|
|
11044
|
+
pseudoState === PSEUDO_STATE_DEFAULT ||
|
|
11045
|
+
!pseudoNamedStyles ||
|
|
11046
|
+
pseudoNamedStyles === PSEUDO_NAMED_STYLES_DEFAULT
|
|
11047
|
+
) {
|
|
11571
11048
|
return styles;
|
|
11572
11049
|
}
|
|
11573
11050
|
|
|
@@ -11634,7 +11111,13 @@ const updateStyle = (element, style) => {
|
|
|
11634
11111
|
}
|
|
11635
11112
|
}
|
|
11636
11113
|
for (const toDeleteKey of toDeleteKeySet) {
|
|
11637
|
-
|
|
11114
|
+
if (toDeleteKey.startsWith("--")) {
|
|
11115
|
+
element.style.removeProperty(toDeleteKey);
|
|
11116
|
+
} else {
|
|
11117
|
+
// we can't use removeProperty because "toDeleteKey" is in camelCase
|
|
11118
|
+
// e.g., backgroundColor (and it's safer to just let the browser do the conversion)
|
|
11119
|
+
element.style[toDeleteKey] = "";
|
|
11120
|
+
}
|
|
11638
11121
|
}
|
|
11639
11122
|
styleKeySetWeakMap.set(element, styleKeySet);
|
|
11640
11123
|
return;
|
|
@@ -11693,8 +11176,10 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
11693
11176
|
flex-direction: row;
|
|
11694
11177
|
}
|
|
11695
11178
|
|
|
11696
|
-
[data-layout-row] >
|
|
11697
|
-
[data-layout-
|
|
11179
|
+
[data-layout-row] > [data-layout-row],
|
|
11180
|
+
[data-layout-row] > [data-layout-column],
|
|
11181
|
+
[data-layout-column] > [data-layout-column],
|
|
11182
|
+
[data-layout-column] > [data-layout-row] {
|
|
11698
11183
|
flex-shrink: 0;
|
|
11699
11184
|
}
|
|
11700
11185
|
|
|
@@ -11709,9 +11194,6 @@ const MANAGED_BY_CSS_VARS_DEFAULT = {};
|
|
|
11709
11194
|
const Box = props => {
|
|
11710
11195
|
const {
|
|
11711
11196
|
as = "div",
|
|
11712
|
-
layoutRow,
|
|
11713
|
-
layoutColumn,
|
|
11714
|
-
layoutInline,
|
|
11715
11197
|
baseClassName,
|
|
11716
11198
|
className,
|
|
11717
11199
|
baseStyle,
|
|
@@ -11741,30 +11223,78 @@ const Box = props => {
|
|
|
11741
11223
|
const defaultRef = useRef();
|
|
11742
11224
|
const ref = props.ref || defaultRef;
|
|
11743
11225
|
const TagName = as;
|
|
11226
|
+
const {
|
|
11227
|
+
box,
|
|
11228
|
+
inline = box,
|
|
11229
|
+
row,
|
|
11230
|
+
column = box
|
|
11231
|
+
} = rest;
|
|
11744
11232
|
let layout;
|
|
11745
|
-
if (
|
|
11746
|
-
if (
|
|
11233
|
+
if (inline) {
|
|
11234
|
+
if (row) {
|
|
11747
11235
|
layout = "inline-row";
|
|
11748
|
-
} else if (
|
|
11236
|
+
} else if (column) {
|
|
11749
11237
|
layout = "inline-column";
|
|
11750
11238
|
} else {
|
|
11751
11239
|
layout = "inline";
|
|
11752
11240
|
}
|
|
11753
|
-
} else if (
|
|
11241
|
+
} else if (row) {
|
|
11754
11242
|
layout = "row";
|
|
11755
|
-
} else if (
|
|
11243
|
+
} else if (column) {
|
|
11756
11244
|
layout = "column";
|
|
11757
11245
|
} else {
|
|
11758
11246
|
layout = getDefaultDisplay(TagName);
|
|
11759
11247
|
}
|
|
11760
11248
|
const innerClassName = withPropsClassName(baseClassName, className);
|
|
11761
11249
|
const remainingProps = {};
|
|
11250
|
+
const propsToForward = {};
|
|
11251
|
+
const shouldForwardAllToChild = visualSelector && pseudoStateSelector;
|
|
11762
11252
|
{
|
|
11763
11253
|
const parentLayout = useContext(BoxLayoutContext);
|
|
11764
|
-
const
|
|
11765
|
-
|
|
11766
|
-
|
|
11767
|
-
|
|
11254
|
+
const styleDeps = [
|
|
11255
|
+
// Layout and alignment props
|
|
11256
|
+
parentLayout, layout,
|
|
11257
|
+
// Style context dependencies
|
|
11258
|
+
managedByCSSVars, pseudoClasses, pseudoElements,
|
|
11259
|
+
// Selectors
|
|
11260
|
+
visualSelector, pseudoStateSelector];
|
|
11261
|
+
let innerPseudoState;
|
|
11262
|
+
if (basePseudoState && pseudoState) {
|
|
11263
|
+
innerPseudoState = {};
|
|
11264
|
+
const baseStateKeys = Object.keys(basePseudoState);
|
|
11265
|
+
const pseudoStateKeySet = new Set(Object.keys(pseudoState));
|
|
11266
|
+
for (const key of baseStateKeys) {
|
|
11267
|
+
if (pseudoStateKeySet.has(key)) {
|
|
11268
|
+
pseudoStateKeySet.delete(key);
|
|
11269
|
+
const value = pseudoState[key];
|
|
11270
|
+
styleDeps.push(value);
|
|
11271
|
+
innerPseudoState[key] = value;
|
|
11272
|
+
} else {
|
|
11273
|
+
const value = basePseudoState[key];
|
|
11274
|
+
styleDeps.push(value);
|
|
11275
|
+
innerPseudoState[key] = value;
|
|
11276
|
+
}
|
|
11277
|
+
}
|
|
11278
|
+
for (const key of pseudoStateKeySet) {
|
|
11279
|
+
const value = pseudoState[key];
|
|
11280
|
+
styleDeps.push(value);
|
|
11281
|
+
innerPseudoState[key] = value;
|
|
11282
|
+
}
|
|
11283
|
+
} else if (basePseudoState) {
|
|
11284
|
+
innerPseudoState = basePseudoState;
|
|
11285
|
+
for (const key of Object.keys(basePseudoState)) {
|
|
11286
|
+
const value = basePseudoState[key];
|
|
11287
|
+
styleDeps.push(value);
|
|
11288
|
+
}
|
|
11289
|
+
} else if (pseudoState) {
|
|
11290
|
+
innerPseudoState = pseudoState;
|
|
11291
|
+
for (const key of Object.keys(pseudoState)) {
|
|
11292
|
+
const value = pseudoState[key];
|
|
11293
|
+
styleDeps.push(value);
|
|
11294
|
+
}
|
|
11295
|
+
} else {
|
|
11296
|
+
innerPseudoState = PSEUDO_STATE_DEFAULT;
|
|
11297
|
+
}
|
|
11768
11298
|
const styleContext = {
|
|
11769
11299
|
parentLayout,
|
|
11770
11300
|
layout,
|
|
@@ -11773,13 +11303,6 @@ const Box = props => {
|
|
|
11773
11303
|
pseudoClasses,
|
|
11774
11304
|
pseudoElements
|
|
11775
11305
|
};
|
|
11776
|
-
const styleDeps = [
|
|
11777
|
-
// Layout and alignment props
|
|
11778
|
-
parentLayout, layout,
|
|
11779
|
-
// Style context dependencies
|
|
11780
|
-
managedByCSSVars, pseudoClasses, pseudoElements,
|
|
11781
|
-
// Selectors
|
|
11782
|
-
visualSelector, pseudoStateSelector];
|
|
11783
11306
|
const boxStyles = {};
|
|
11784
11307
|
if (baseStyle) {
|
|
11785
11308
|
for (const key of baseStyle) {
|
|
@@ -11789,22 +11312,6 @@ const Box = props => {
|
|
|
11789
11312
|
}
|
|
11790
11313
|
}
|
|
11791
11314
|
const stylingKeyCandidateArray = Object.keys(rest);
|
|
11792
|
-
const assignStyleFromProp = (propValue, propName, stylesTarget, context) => {
|
|
11793
|
-
const propEffect = getPropEffect(propName);
|
|
11794
|
-
if (propEffect === "ignore") {
|
|
11795
|
-
return;
|
|
11796
|
-
}
|
|
11797
|
-
if (propEffect === "forward" || propEffect === "style_and_forward") {
|
|
11798
|
-
if (stylesTarget === boxStyles) {
|
|
11799
|
-
remainingProps[propName] = propValue;
|
|
11800
|
-
}
|
|
11801
|
-
if (propEffect === "forward") {
|
|
11802
|
-
return;
|
|
11803
|
-
}
|
|
11804
|
-
}
|
|
11805
|
-
styleDeps.push(propValue);
|
|
11806
|
-
assignStyle(stylesTarget, propValue, propName, context);
|
|
11807
|
-
};
|
|
11808
11315
|
const getPropEffect = propName => {
|
|
11809
11316
|
if (visualSelector) {
|
|
11810
11317
|
if (HANDLED_BY_VISUAL_CHILD_PROP_SET.has(propName)) {
|
|
@@ -11814,7 +11321,34 @@ const Box = props => {
|
|
|
11814
11321
|
return "style_and_forward";
|
|
11815
11322
|
}
|
|
11816
11323
|
}
|
|
11817
|
-
|
|
11324
|
+
if (isStyleProp(propName)) {
|
|
11325
|
+
return "style";
|
|
11326
|
+
}
|
|
11327
|
+
if (propName.startsWith("data-")) {
|
|
11328
|
+
return "use";
|
|
11329
|
+
}
|
|
11330
|
+
return "forward";
|
|
11331
|
+
};
|
|
11332
|
+
const assignStyleFromProp = (propValue, propName, stylesTarget, styleContext) => {
|
|
11333
|
+
const propEffect = getPropEffect(propName);
|
|
11334
|
+
if (propEffect === "ignore") {
|
|
11335
|
+
return;
|
|
11336
|
+
}
|
|
11337
|
+
const useToStyle = propEffect === "style" || propEffect === "style_and_forward";
|
|
11338
|
+
const shouldForward = propEffect === "forward" || propEffect === "style_and_forward";
|
|
11339
|
+
if (useToStyle) {
|
|
11340
|
+
styleDeps.push(propValue);
|
|
11341
|
+
assignStyle(stylesTarget, propValue, propName, styleContext, "css");
|
|
11342
|
+
}
|
|
11343
|
+
if (stylesTarget === boxStyles) {
|
|
11344
|
+
if (!shouldForwardAllToChild && !useToStyle) {
|
|
11345
|
+
// we'll put these props on ourselves
|
|
11346
|
+
remainingProps[propName] = propValue;
|
|
11347
|
+
}
|
|
11348
|
+
if (shouldForward) {
|
|
11349
|
+
propsToForward[propName] = propValue;
|
|
11350
|
+
}
|
|
11351
|
+
}
|
|
11818
11352
|
};
|
|
11819
11353
|
for (const key of stylingKeyCandidateArray) {
|
|
11820
11354
|
if (key === "ref") {
|
|
@@ -11825,46 +11359,49 @@ const Box = props => {
|
|
|
11825
11359
|
const value = rest[key];
|
|
11826
11360
|
assignStyleFromProp(value, key, boxStyles, styleContext);
|
|
11827
11361
|
}
|
|
11828
|
-
|
|
11362
|
+
let pseudoNamedStyles = PSEUDO_NAMED_STYLES_DEFAULT;
|
|
11829
11363
|
if (pseudoStyle) {
|
|
11830
|
-
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
...
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11364
|
+
const pseudoStyleKeys = Object.keys(pseudoStyle);
|
|
11365
|
+
if (pseudoStyleKeys.length) {
|
|
11366
|
+
pseudoNamedStyles = {};
|
|
11367
|
+
for (const key of pseudoStyleKeys) {
|
|
11368
|
+
const pseudoStyleContext = {
|
|
11369
|
+
...styleContext,
|
|
11370
|
+
managedByCSSVars: {
|
|
11371
|
+
...managedByCSSVars,
|
|
11372
|
+
...managedByCSSVars[key]
|
|
11373
|
+
},
|
|
11374
|
+
pseudoName: key
|
|
11375
|
+
};
|
|
11839
11376
|
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11377
|
+
// pseudo class
|
|
11378
|
+
if (key.startsWith(":")) {
|
|
11379
|
+
styleDeps.push(key);
|
|
11380
|
+
const pseudoClassStyles = {};
|
|
11381
|
+
const pseudoClassStyle = pseudoStyle[key];
|
|
11382
|
+
for (const pseudoClassStyleKey of Object.keys(pseudoClassStyle)) {
|
|
11383
|
+
const pseudoClassStyleValue = pseudoClassStyle[pseudoClassStyleKey];
|
|
11384
|
+
assignStyleFromProp(pseudoClassStyleValue, pseudoClassStyleKey, pseudoClassStyles, pseudoStyleContext);
|
|
11385
|
+
}
|
|
11386
|
+
pseudoNamedStyles[key] = pseudoClassStyles;
|
|
11387
|
+
continue;
|
|
11848
11388
|
}
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
|
|
11853
|
-
|
|
11854
|
-
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11389
|
+
// pseudo element
|
|
11390
|
+
if (key.startsWith("::")) {
|
|
11391
|
+
styleDeps.push(key);
|
|
11392
|
+
const pseudoElementStyles = {};
|
|
11393
|
+
const pseudoElementStyle = pseudoStyle[key];
|
|
11394
|
+
for (const pseudoElementStyleKey of Object.keys(pseudoElementStyle)) {
|
|
11395
|
+
const pseudoElementStyleValue = pseudoElementStyle[pseudoElementStyleKey];
|
|
11396
|
+
assignStyleFromProp(pseudoElementStyleValue, pseudoElementStyleKey, pseudoElementStyles, pseudoStyleContext);
|
|
11397
|
+
}
|
|
11398
|
+
pseudoNamedStyles[key] = pseudoElementStyles;
|
|
11399
|
+
continue;
|
|
11860
11400
|
}
|
|
11861
|
-
|
|
11862
|
-
continue;
|
|
11401
|
+
console.warn(`unsupported pseudo style key "${key}"`);
|
|
11863
11402
|
}
|
|
11864
|
-
console.warn(`unsupported pseudo style key "${key}"`);
|
|
11865
11403
|
}
|
|
11866
11404
|
remainingProps.pseudoStyle = pseudoStyle;
|
|
11867
|
-
// TODO: we should also pass pseudoState right?
|
|
11868
11405
|
}
|
|
11869
11406
|
if (typeof style === "string") {
|
|
11870
11407
|
appendStyles(boxStyles, normalizeStyles(style, "css"), "css");
|
|
@@ -11872,7 +11409,7 @@ const Box = props => {
|
|
|
11872
11409
|
} else if (style && typeof style === "object") {
|
|
11873
11410
|
for (const key of Object.keys(style)) {
|
|
11874
11411
|
const stylePropValue = style[key];
|
|
11875
|
-
assignStyle(boxStyles, stylePropValue, key, styleContext);
|
|
11412
|
+
assignStyle(boxStyles, stylePropValue, key, styleContext, "css");
|
|
11876
11413
|
styleDeps.push(stylePropValue); // impact box style -> add to deps
|
|
11877
11414
|
}
|
|
11878
11415
|
}
|
|
@@ -11924,49 +11461,31 @@ const Box = props => {
|
|
|
11924
11461
|
let innerChildren;
|
|
11925
11462
|
if (hasChildFunction) {
|
|
11926
11463
|
if (Array.isArray(children)) {
|
|
11927
|
-
innerChildren = children.map(child => typeof child === "function" ? child(
|
|
11464
|
+
innerChildren = children.map(child => typeof child === "function" ? child(propsToForward) : child);
|
|
11928
11465
|
} else if (typeof children === "function") {
|
|
11929
|
-
innerChildren = children(
|
|
11466
|
+
innerChildren = children(propsToForward);
|
|
11930
11467
|
} else {
|
|
11931
11468
|
innerChildren = children;
|
|
11932
11469
|
}
|
|
11933
11470
|
} else {
|
|
11934
11471
|
innerChildren = children;
|
|
11935
11472
|
}
|
|
11936
|
-
const shouldForwardAllToChild = visualSelector && pseudoStateSelector;
|
|
11937
11473
|
return jsx(TagName, {
|
|
11938
11474
|
ref: ref,
|
|
11939
11475
|
className: innerClassName,
|
|
11940
|
-
"data-layout-inline":
|
|
11941
|
-
"data-layout-row":
|
|
11942
|
-
"data-layout-column":
|
|
11943
|
-
...
|
|
11476
|
+
"data-layout-inline": inline ? "" : undefined,
|
|
11477
|
+
"data-layout-row": row ? "" : undefined,
|
|
11478
|
+
"data-layout-column": column ? "" : undefined,
|
|
11479
|
+
...remainingProps,
|
|
11944
11480
|
children: jsx(BoxLayoutContext.Provider, {
|
|
11945
11481
|
value: layout,
|
|
11946
11482
|
children: innerChildren
|
|
11947
11483
|
})
|
|
11948
11484
|
});
|
|
11949
11485
|
};
|
|
11950
|
-
const Layout = props => {
|
|
11951
|
-
const {
|
|
11952
|
-
row,
|
|
11953
|
-
column,
|
|
11954
|
-
...rest
|
|
11955
|
-
} = props;
|
|
11956
|
-
if (row) {
|
|
11957
|
-
return jsx(Box, {
|
|
11958
|
-
layoutRow: true,
|
|
11959
|
-
...rest
|
|
11960
|
-
});
|
|
11961
|
-
}
|
|
11962
|
-
if (column) {
|
|
11963
|
-
return jsx(Box, {
|
|
11964
|
-
layoutColumn: true,
|
|
11965
|
-
...rest
|
|
11966
|
-
});
|
|
11967
|
-
}
|
|
11486
|
+
const Layout = props => {
|
|
11968
11487
|
return jsx(Box, {
|
|
11969
|
-
...
|
|
11488
|
+
...props
|
|
11970
11489
|
});
|
|
11971
11490
|
};
|
|
11972
11491
|
|
|
@@ -13907,31 +13426,6 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
13907
13426
|
color: inherit;
|
|
13908
13427
|
}
|
|
13909
13428
|
|
|
13910
|
-
.navi_char_slot_invisible {
|
|
13911
|
-
opacity: 0;
|
|
13912
|
-
}
|
|
13913
|
-
|
|
13914
|
-
.navi_icon {
|
|
13915
|
-
display: flex;
|
|
13916
|
-
aspect-ratio: 1 / 1;
|
|
13917
|
-
height: 100%;
|
|
13918
|
-
max-height: 1em;
|
|
13919
|
-
align-items: center;
|
|
13920
|
-
justify-content: center;
|
|
13921
|
-
}
|
|
13922
|
-
|
|
13923
|
-
.navi_text[data-has-foreground] {
|
|
13924
|
-
display: inline-block;
|
|
13925
|
-
}
|
|
13926
|
-
|
|
13927
|
-
.navi_text_foreground {
|
|
13928
|
-
position: absolute;
|
|
13929
|
-
inset: 0;
|
|
13930
|
-
display: inline-flex;
|
|
13931
|
-
align-items: center;
|
|
13932
|
-
justify-content: center;
|
|
13933
|
-
}
|
|
13934
|
-
|
|
13935
13429
|
.navi_text_overflow_wrapper {
|
|
13936
13430
|
display: flex;
|
|
13937
13431
|
width: 0;
|
|
@@ -14016,91 +13510,18 @@ const TextOverflowPinned = ({
|
|
|
14016
13510
|
};
|
|
14017
13511
|
const TextBasic = ({
|
|
14018
13512
|
as = "span",
|
|
14019
|
-
foregroundColor,
|
|
14020
|
-
foregroundElement,
|
|
14021
13513
|
contentSpacing = " ",
|
|
14022
|
-
box,
|
|
14023
13514
|
children,
|
|
14024
13515
|
...rest
|
|
14025
13516
|
}) => {
|
|
14026
|
-
const
|
|
14027
|
-
const text = jsxs(Box, {
|
|
13517
|
+
const text = jsx(Box, {
|
|
14028
13518
|
...rest,
|
|
14029
13519
|
baseClassName: "navi_text",
|
|
14030
13520
|
as: as,
|
|
14031
|
-
|
|
14032
|
-
layoutColumn: box ? true : undefined,
|
|
14033
|
-
"data-has-foreground": hasForeground ? "" : undefined,
|
|
14034
|
-
children: [applyContentSpacingOnTextChildren(children, contentSpacing), hasForeground && jsx("span", {
|
|
14035
|
-
className: "navi_text_foreground",
|
|
14036
|
-
style: {
|
|
14037
|
-
backgroundColor: foregroundColor
|
|
14038
|
-
},
|
|
14039
|
-
children: foregroundElement
|
|
14040
|
-
})]
|
|
13521
|
+
children: applyContentSpacingOnTextChildren(children, contentSpacing)
|
|
14041
13522
|
});
|
|
14042
13523
|
return text;
|
|
14043
13524
|
};
|
|
14044
|
-
const CharSlot = ({
|
|
14045
|
-
charWidth = 1,
|
|
14046
|
-
// 0 (zéro) is the real char width
|
|
14047
|
-
// but 2 zéros gives too big icons
|
|
14048
|
-
// while 1 "W" gives a nice result
|
|
14049
|
-
baseChar = "W",
|
|
14050
|
-
"aria-label": ariaLabel,
|
|
14051
|
-
role,
|
|
14052
|
-
decorative = false,
|
|
14053
|
-
children,
|
|
14054
|
-
...rest
|
|
14055
|
-
}) => {
|
|
14056
|
-
const invisibleText = baseChar.repeat(charWidth);
|
|
14057
|
-
const ariaProps = decorative ? {
|
|
14058
|
-
"aria-hidden": "true"
|
|
14059
|
-
} : {
|
|
14060
|
-
role,
|
|
14061
|
-
"aria-label": ariaLabel
|
|
14062
|
-
};
|
|
14063
|
-
return jsx(Text, {
|
|
14064
|
-
...rest,
|
|
14065
|
-
...ariaProps,
|
|
14066
|
-
foregroundElement: children,
|
|
14067
|
-
children: jsx("span", {
|
|
14068
|
-
className: "navi_char_slot_invisible",
|
|
14069
|
-
"aria-hidden": "true",
|
|
14070
|
-
children: invisibleText
|
|
14071
|
-
})
|
|
14072
|
-
});
|
|
14073
|
-
};
|
|
14074
|
-
const Icon = ({
|
|
14075
|
-
box,
|
|
14076
|
-
href,
|
|
14077
|
-
children,
|
|
14078
|
-
...props
|
|
14079
|
-
}) => {
|
|
14080
|
-
const innerChildren = href ? jsx("svg", {
|
|
14081
|
-
width: "100%",
|
|
14082
|
-
height: "100%",
|
|
14083
|
-
children: jsx("use", {
|
|
14084
|
-
href: href
|
|
14085
|
-
})
|
|
14086
|
-
}) : children;
|
|
14087
|
-
if (box) {
|
|
14088
|
-
return jsx(Box, {
|
|
14089
|
-
layoutInline: true,
|
|
14090
|
-
layoutColumn: true,
|
|
14091
|
-
...props,
|
|
14092
|
-
children: innerChildren
|
|
14093
|
-
});
|
|
14094
|
-
}
|
|
14095
|
-
return jsx(CharSlot, {
|
|
14096
|
-
decorative: true,
|
|
14097
|
-
...props,
|
|
14098
|
-
children: jsx("span", {
|
|
14099
|
-
className: "navi_icon",
|
|
14100
|
-
children: innerChildren
|
|
14101
|
-
})
|
|
14102
|
-
});
|
|
14103
|
-
};
|
|
14104
13525
|
const Paragraph = ({
|
|
14105
13526
|
contentSpacing = " ",
|
|
14106
13527
|
marginTop = "md",
|
|
@@ -14163,6 +13584,114 @@ const applyContentSpacingOnTextChildren = (children, contentSpacing) => {
|
|
|
14163
13584
|
return childrenWithGap;
|
|
14164
13585
|
};
|
|
14165
13586
|
|
|
13587
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
13588
|
+
.navi_icon {
|
|
13589
|
+
display: inline-block;
|
|
13590
|
+
box-sizing: border-box;
|
|
13591
|
+
}
|
|
13592
|
+
|
|
13593
|
+
.navi_icon_char_slot {
|
|
13594
|
+
opacity: 0;
|
|
13595
|
+
}
|
|
13596
|
+
.navi_icon_foreground {
|
|
13597
|
+
position: absolute;
|
|
13598
|
+
inset: 0;
|
|
13599
|
+
display: inline-flex;
|
|
13600
|
+
box-sizing: border-box;
|
|
13601
|
+
align-items: center;
|
|
13602
|
+
justify-content: start;
|
|
13603
|
+
}
|
|
13604
|
+
.navi_icon_foreground > .navi_text {
|
|
13605
|
+
display: flex;
|
|
13606
|
+
aspect-ratio: 1 / 1;
|
|
13607
|
+
height: 100%;
|
|
13608
|
+
max-height: 1em;
|
|
13609
|
+
align-items: center;
|
|
13610
|
+
justify-content: center;
|
|
13611
|
+
}
|
|
13612
|
+
|
|
13613
|
+
.navi_icon > svg,
|
|
13614
|
+
.navi_icon > img {
|
|
13615
|
+
width: 100%;
|
|
13616
|
+
height: 100%;
|
|
13617
|
+
}
|
|
13618
|
+
.navi_icon[data-width] > svg,
|
|
13619
|
+
.navi_icon[data-width] > img {
|
|
13620
|
+
width: 100%;
|
|
13621
|
+
height: auto;
|
|
13622
|
+
}
|
|
13623
|
+
.navi_icon[data-height] > svg,
|
|
13624
|
+
.navi_icon[data-height] > img {
|
|
13625
|
+
width: auto;
|
|
13626
|
+
height: 100%;
|
|
13627
|
+
}
|
|
13628
|
+
`;
|
|
13629
|
+
const Icon = ({
|
|
13630
|
+
href,
|
|
13631
|
+
children,
|
|
13632
|
+
className,
|
|
13633
|
+
charWidth = 1,
|
|
13634
|
+
// 0 (zéro) is the real char width
|
|
13635
|
+
// but 2 zéros gives too big icons
|
|
13636
|
+
// while 1 "W" gives a nice result
|
|
13637
|
+
baseChar = "W",
|
|
13638
|
+
"aria-label": ariaLabel,
|
|
13639
|
+
role,
|
|
13640
|
+
decorative = false,
|
|
13641
|
+
...props
|
|
13642
|
+
}) => {
|
|
13643
|
+
const innerChildren = href ? jsx("svg", {
|
|
13644
|
+
width: "100%",
|
|
13645
|
+
height: "100%",
|
|
13646
|
+
children: jsx("use", {
|
|
13647
|
+
href: href
|
|
13648
|
+
})
|
|
13649
|
+
}) : children;
|
|
13650
|
+
let {
|
|
13651
|
+
box,
|
|
13652
|
+
width,
|
|
13653
|
+
height
|
|
13654
|
+
} = props;
|
|
13655
|
+
if (width !== undefined || height !== undefined) {
|
|
13656
|
+
box = true;
|
|
13657
|
+
}
|
|
13658
|
+
if (box) {
|
|
13659
|
+
return jsx(Box, {
|
|
13660
|
+
...props,
|
|
13661
|
+
baseClassName: "navi_icon",
|
|
13662
|
+
"data-width": width,
|
|
13663
|
+
"data-height": height,
|
|
13664
|
+
children: innerChildren
|
|
13665
|
+
});
|
|
13666
|
+
}
|
|
13667
|
+
const invisibleText = baseChar.repeat(charWidth);
|
|
13668
|
+
const ariaProps = decorative ? {
|
|
13669
|
+
"aria-hidden": "true"
|
|
13670
|
+
} : {
|
|
13671
|
+
role,
|
|
13672
|
+
"aria-label": ariaLabel
|
|
13673
|
+
};
|
|
13674
|
+
return jsxs(Text, {
|
|
13675
|
+
...props,
|
|
13676
|
+
...ariaProps,
|
|
13677
|
+
box: box,
|
|
13678
|
+
className: withPropsClassName("navi_icon", className),
|
|
13679
|
+
"data-icon-char": "",
|
|
13680
|
+
"data-width": width,
|
|
13681
|
+
"data-height": height,
|
|
13682
|
+
children: [jsx("span", {
|
|
13683
|
+
className: "navi_icon_char_slot",
|
|
13684
|
+
"aria-hidden": "true",
|
|
13685
|
+
children: invisibleText
|
|
13686
|
+
}), jsx("span", {
|
|
13687
|
+
className: "navi_icon_foreground",
|
|
13688
|
+
children: jsx(Text, {
|
|
13689
|
+
children: innerChildren
|
|
13690
|
+
})
|
|
13691
|
+
})]
|
|
13692
|
+
});
|
|
13693
|
+
};
|
|
13694
|
+
|
|
14166
13695
|
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
14167
13696
|
@layer navi {
|
|
14168
13697
|
.navi_link {
|
|
@@ -14172,7 +13701,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
14172
13701
|
--color-visited: light-dark(#6a1b9a, #ab47bc);
|
|
14173
13702
|
--color-active: red;
|
|
14174
13703
|
--text-decoration: underline;
|
|
14175
|
-
--text-decoration-hover:
|
|
13704
|
+
--text-decoration-hover: var(--text-decoration);
|
|
14176
13705
|
--cursor: pointer;
|
|
14177
13706
|
}
|
|
14178
13707
|
}
|
|
@@ -14183,7 +13712,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
14183
13712
|
--x-color-visited: var(--color-visited);
|
|
14184
13713
|
--x-color-active: var(--color-active);
|
|
14185
13714
|
--x-text-decoration: var(--text-decoration);
|
|
14186
|
-
--x-text-decoration-hover: var(--text-decoration-hover
|
|
13715
|
+
--x-text-decoration-hover: var(--text-decoration-hover);
|
|
14187
13716
|
--x-cursor: var(--cursor);
|
|
14188
13717
|
|
|
14189
13718
|
position: relative;
|
|
@@ -14301,7 +13830,6 @@ const LinkPlain = props => {
|
|
|
14301
13830
|
rel,
|
|
14302
13831
|
preventDefault,
|
|
14303
13832
|
// visual
|
|
14304
|
-
box,
|
|
14305
13833
|
blankTargetIcon,
|
|
14306
13834
|
anchorIcon,
|
|
14307
13835
|
icon,
|
|
@@ -14361,8 +13889,6 @@ const LinkPlain = props => {
|
|
|
14361
13889
|
// Visual
|
|
14362
13890
|
,
|
|
14363
13891
|
baseClassName: "navi_link",
|
|
14364
|
-
layoutInline: true,
|
|
14365
|
-
layoutColumn: box ? true : undefined,
|
|
14366
13892
|
managedByCSSVars: LinkManagedByCSSVars,
|
|
14367
13893
|
pseudoClasses: LinkPseudoClasses,
|
|
14368
13894
|
pseudoElements: LinkPseudoElements,
|
|
@@ -14408,8 +13934,6 @@ const LinkPlain = props => {
|
|
|
14408
13934
|
const BlankTargetLinkSvg = () => {
|
|
14409
13935
|
return jsx("svg", {
|
|
14410
13936
|
viewBox: "0 0 24 24",
|
|
14411
|
-
width: "100%",
|
|
14412
|
-
height: "100%",
|
|
14413
13937
|
xmlns: "http://www.w3.org/2000/svg",
|
|
14414
13938
|
children: jsx("path", {
|
|
14415
13939
|
d: "M10.0002 5H8.2002C7.08009 5 6.51962 5 6.0918 5.21799C5.71547 5.40973 5.40973 5.71547 5.21799 6.0918C5 6.51962 5 7.08009 5 8.2002V15.8002C5 16.9203 5 17.4801 5.21799 17.9079C5.40973 18.2842 5.71547 18.5905 6.0918 18.7822C6.5192 19 7.07899 19 8.19691 19H15.8031C16.921 19 17.48 19 17.9074 18.7822C18.2837 18.5905 18.5905 18.2839 18.7822 17.9076C19 17.4802 19 16.921 19 15.8031V14M20 9V4M20 4H15M20 4L13 11",
|
|
@@ -14424,8 +13948,6 @@ const BlankTargetLinkSvg = () => {
|
|
|
14424
13948
|
const AnchorLinkSvg = () => {
|
|
14425
13949
|
return jsxs("svg", {
|
|
14426
13950
|
viewBox: "0 0 24 24",
|
|
14427
|
-
width: "100%",
|
|
14428
|
-
height: "100%",
|
|
14429
13951
|
xmlns: "http://www.w3.org/2000/svg",
|
|
14430
13952
|
children: [jsx("path", {
|
|
14431
13953
|
d: "M13.2218 3.32234C15.3697 1.17445 18.8521 1.17445 21 3.32234C23.1479 5.47022 23.1479 8.95263 21 11.1005L17.4645 14.636C15.3166 16.7839 11.8342 16.7839 9.6863 14.636C9.48752 14.4373 9.30713 14.2271 9.14514 14.0075C8.90318 13.6796 8.97098 13.2301 9.25914 12.9419C9.73221 12.4688 10.5662 12.6561 11.0245 13.1435C11.0494 13.1699 11.0747 13.196 11.1005 13.2218C12.4673 14.5887 14.6834 14.5887 16.0503 13.2218L19.5858 9.6863C20.9526 8.31947 20.9526 6.10339 19.5858 4.73655C18.219 3.36972 16.0029 3.36972 14.636 4.73655L13.5754 5.79721C13.1849 6.18774 12.5517 6.18774 12.1612 5.79721C11.7706 5.40669 11.7706 4.77352 12.1612 4.383L13.2218 3.32234Z",
|
|
@@ -14439,8 +13961,6 @@ const AnchorLinkSvg = () => {
|
|
|
14439
13961
|
const PhoneSvg = () => {
|
|
14440
13962
|
return jsx("svg", {
|
|
14441
13963
|
viewBox: "0 0 24 24",
|
|
14442
|
-
width: "100%",
|
|
14443
|
-
height: "100%",
|
|
14444
13964
|
xmlns: "http://www.w3.org/2000/svg",
|
|
14445
13965
|
children: jsx("path", {
|
|
14446
13966
|
d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z",
|
|
@@ -14451,8 +13971,6 @@ const PhoneSvg = () => {
|
|
|
14451
13971
|
const SmsSvg = () => {
|
|
14452
13972
|
return jsx("svg", {
|
|
14453
13973
|
viewBox: "0 0 24 24",
|
|
14454
|
-
width: "100%",
|
|
14455
|
-
height: "100%",
|
|
14456
13974
|
xmlns: "http://www.w3.org/2000/svg",
|
|
14457
13975
|
children: jsx("path", {
|
|
14458
13976
|
d: "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM18 14H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z",
|
|
@@ -14463,8 +13981,6 @@ const SmsSvg = () => {
|
|
|
14463
13981
|
const EmailSvg = () => {
|
|
14464
13982
|
return jsxs("svg", {
|
|
14465
13983
|
viewBox: "0 0 24 24",
|
|
14466
|
-
width: "100%",
|
|
14467
|
-
height: "100%",
|
|
14468
13984
|
xmlns: "http://www.w3.org/2000/svg",
|
|
14469
13985
|
children: [jsx("path", {
|
|
14470
13986
|
d: "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z",
|
|
@@ -14484,8 +14000,6 @@ const EmailSvg = () => {
|
|
|
14484
14000
|
const GithubSvg = () => {
|
|
14485
14001
|
return jsx("svg", {
|
|
14486
14002
|
viewBox: "0 0 24 24",
|
|
14487
|
-
width: "100%",
|
|
14488
|
-
height: "100%",
|
|
14489
14003
|
xmlns: "http://www.w3.org/2000/svg",
|
|
14490
14004
|
children: jsx("path", {
|
|
14491
14005
|
d: "M12 2C6.48 2 2 6.48 2 12c0 4.42 2.87 8.17 6.84 9.5.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34-.46-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.87 1.52 2.34 1.07 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.92 0-1.11.38-2 1.03-2.71-.1-.25-.45-1.29.1-2.64 0 0 .84-.27 2.75 1.02.79-.22 1.65-.33 2.5-.33.85 0 1.71.11 2.5.33 1.91-1.29 2.75-1.02 2.75-1.02.55 1.35.2 2.39.1 2.64.65.71 1.03 1.6 1.03 2.71 0 3.82-2.34 4.66-4.57 4.91.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0012 2z",
|
|
@@ -17056,13 +16570,10 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
17056
16570
|
--x-color: var(--color);
|
|
17057
16571
|
|
|
17058
16572
|
position: relative;
|
|
16573
|
+
display: inline-flex;
|
|
17059
16574
|
box-sizing: border-box;
|
|
17060
|
-
width: fit-content;
|
|
17061
|
-
height: fit-content;
|
|
17062
16575
|
padding: 0;
|
|
17063
16576
|
flex-direction: inherit;
|
|
17064
|
-
align-items: inherit;
|
|
17065
|
-
justify-content: inherit;
|
|
17066
16577
|
background: none;
|
|
17067
16578
|
border: none;
|
|
17068
16579
|
border-radius: inherit;
|
|
@@ -17071,6 +16582,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
17071
16582
|
}
|
|
17072
16583
|
.navi_button_content {
|
|
17073
16584
|
position: relative;
|
|
16585
|
+
box-sizing: border-box;
|
|
17074
16586
|
padding-top: var(--padding-top, var(--padding-y, var(--padding, 1px)));
|
|
17075
16587
|
padding-right: var(--padding-right, var(--padding-x, var(--padding, 6px)));
|
|
17076
16588
|
padding-bottom: var(
|
|
@@ -17241,7 +16753,6 @@ const ButtonBasic = props => {
|
|
|
17241
16753
|
...buttonProps,
|
|
17242
16754
|
as: "span",
|
|
17243
16755
|
baseClassName: "navi_button_content",
|
|
17244
|
-
layoutInline: true,
|
|
17245
16756
|
children: [innerChildren, jsx("span", {
|
|
17246
16757
|
className: "navi_button_shadow"
|
|
17247
16758
|
})]
|
|
@@ -17259,8 +16770,6 @@ const ButtonBasic = props => {
|
|
|
17259
16770
|
// style management
|
|
17260
16771
|
,
|
|
17261
16772
|
baseClassName: "navi_button",
|
|
17262
|
-
layoutInline: true,
|
|
17263
|
-
layoutColumn: true,
|
|
17264
16773
|
managedByCSSVars: ButtonManagedByCSSVars,
|
|
17265
16774
|
pseudoClasses: ButtonPseudoClasses,
|
|
17266
16775
|
pseudoElements: ButtonPseudoElements,
|
|
@@ -21811,29 +21320,97 @@ const SVGMaskOverlay = ({
|
|
|
21811
21320
|
});
|
|
21812
21321
|
};
|
|
21813
21322
|
|
|
21323
|
+
const CSS_VAR_NAME = "--color-contrasting";
|
|
21324
|
+
|
|
21325
|
+
const useContrastingColor = (ref) => {
|
|
21326
|
+
useLayoutEffect(() => {
|
|
21327
|
+
const el = ref.current;
|
|
21328
|
+
if (!el) {
|
|
21329
|
+
return;
|
|
21330
|
+
}
|
|
21331
|
+
const lightColor = "var(--navi-color-light)";
|
|
21332
|
+
const darkColor = "var(--navi-color-dark)";
|
|
21333
|
+
const backgroundColor = getComputedStyle(el).backgroundColor;
|
|
21334
|
+
if (!backgroundColor) {
|
|
21335
|
+
el.style.removeProperty(CSS_VAR_NAME);
|
|
21336
|
+
return;
|
|
21337
|
+
}
|
|
21338
|
+
const colorPicked = pickLightOrDark(
|
|
21339
|
+
backgroundColor,
|
|
21340
|
+
lightColor,
|
|
21341
|
+
darkColor,
|
|
21342
|
+
el,
|
|
21343
|
+
);
|
|
21344
|
+
el.style.setProperty(CSS_VAR_NAME, colorPicked);
|
|
21345
|
+
}, []);
|
|
21346
|
+
};
|
|
21347
|
+
|
|
21814
21348
|
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
21815
|
-
|
|
21816
|
-
|
|
21817
|
-
|
|
21818
|
-
|
|
21349
|
+
@layer navi {
|
|
21350
|
+
.navi_badge {
|
|
21351
|
+
--border-radius: 1em;
|
|
21352
|
+
}
|
|
21353
|
+
}
|
|
21354
|
+
.navi_badge {
|
|
21355
|
+
display: inline-block;
|
|
21356
|
+
box-sizing: border-box;
|
|
21357
|
+
min-width: 1.5em;
|
|
21358
|
+
height: 1.5em;
|
|
21359
|
+
max-height: 1.5em;
|
|
21360
|
+
padding-right: var(
|
|
21361
|
+
--padding-right,
|
|
21362
|
+
var(--padding-x, var(--padding, 0.4em))
|
|
21363
|
+
);
|
|
21364
|
+
padding-left: var(--padding-left, var(--padding-x, var(--padding, 0.4em)));
|
|
21365
|
+
color: var(--color, var(--color-contrasting));
|
|
21366
|
+
text-align: center;
|
|
21367
|
+
line-height: 1.5em;
|
|
21368
|
+
vertical-align: middle;
|
|
21369
|
+
border-radius: var(--border-radius, 1em);
|
|
21819
21370
|
}
|
|
21820
21371
|
`;
|
|
21821
|
-
const
|
|
21372
|
+
const BadgeManagedByCSSVars = {
|
|
21373
|
+
borderWidth: "--border-width",
|
|
21374
|
+
borderRadius: "--border-radius",
|
|
21375
|
+
paddingRight: "--padding-right",
|
|
21376
|
+
paddingLeft: "--padding-left",
|
|
21377
|
+
backgroundColor: "--background-color",
|
|
21378
|
+
borderColor: "--border-color",
|
|
21379
|
+
color: "--color"
|
|
21380
|
+
};
|
|
21381
|
+
const BadgeCount = ({
|
|
21822
21382
|
children,
|
|
21823
|
-
|
|
21383
|
+
bold = true,
|
|
21384
|
+
max,
|
|
21385
|
+
...props
|
|
21824
21386
|
}) => {
|
|
21825
|
-
|
|
21826
|
-
|
|
21827
|
-
baseClassName: ".navi_count",
|
|
21828
|
-
...rest,
|
|
21829
|
-
children: ["(", children, ")"]
|
|
21830
|
-
});
|
|
21831
|
-
};
|
|
21387
|
+
const defaultRef = useRef();
|
|
21388
|
+
const ref = props.ref || defaultRef;
|
|
21832
21389
|
|
|
21833
|
-
|
|
21834
|
-
|
|
21390
|
+
// Calculer la valeur à afficher en fonction du paramètre max
|
|
21391
|
+
const getDisplayValue = () => {
|
|
21392
|
+
if (max === undefined) {
|
|
21393
|
+
return children;
|
|
21394
|
+
}
|
|
21395
|
+
const numericValue = typeof children === "string" ? parseInt(children, 10) : children;
|
|
21396
|
+
const numericMax = typeof max === "string" ? parseInt(max, 10) : max;
|
|
21397
|
+
if (isNaN(numericValue) || isNaN(numericMax)) {
|
|
21398
|
+
return children;
|
|
21399
|
+
}
|
|
21400
|
+
if (numericValue > numericMax) {
|
|
21401
|
+
return `${numericMax}+`;
|
|
21402
|
+
}
|
|
21403
|
+
return children;
|
|
21404
|
+
};
|
|
21405
|
+
const displayValue = getDisplayValue();
|
|
21406
|
+
useContrastingColor(ref);
|
|
21407
|
+
return jsx(Text, {
|
|
21835
21408
|
...props,
|
|
21836
|
-
|
|
21409
|
+
ref: ref,
|
|
21410
|
+
className: "navi_badge",
|
|
21411
|
+
bold: bold,
|
|
21412
|
+
managedByCSSVars: BadgeManagedByCSSVars,
|
|
21413
|
+
children: displayValue
|
|
21837
21414
|
});
|
|
21838
21415
|
};
|
|
21839
21416
|
|
|
@@ -21849,6 +21426,13 @@ const Code = ({
|
|
|
21849
21426
|
});
|
|
21850
21427
|
};
|
|
21851
21428
|
|
|
21429
|
+
const Image = props => {
|
|
21430
|
+
return jsx(Box, {
|
|
21431
|
+
...props,
|
|
21432
|
+
as: "img"
|
|
21433
|
+
});
|
|
21434
|
+
};
|
|
21435
|
+
|
|
21852
21436
|
const LinkWithIcon = () => {};
|
|
21853
21437
|
|
|
21854
21438
|
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
@@ -22009,6 +21593,118 @@ const Title = ({
|
|
|
22009
21593
|
});
|
|
22010
21594
|
};
|
|
22011
21595
|
|
|
21596
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
21597
|
+
@layer navi {
|
|
21598
|
+
.navi_dialog_layout {
|
|
21599
|
+
--margin: 30px;
|
|
21600
|
+
--padding: 20px;
|
|
21601
|
+
--background: white;
|
|
21602
|
+
--border-width: 2px;
|
|
21603
|
+
--border-color: lightgrey;
|
|
21604
|
+
--border-radius: 10px;
|
|
21605
|
+
--min-width: 300px;
|
|
21606
|
+
--min-height: auto;
|
|
21607
|
+
}
|
|
21608
|
+
}
|
|
21609
|
+
.navi_dialog_layout {
|
|
21610
|
+
padding-top: var(--margin-top, var(--margin-y, var(--margin)));
|
|
21611
|
+
padding-right: var(--margin-right, var(--margin-x, var(--margin)));
|
|
21612
|
+
padding-bottom: var(--margin-bottom, var(--margin-y, var(--margin)));
|
|
21613
|
+
padding-left: var(--margin-left, var(--margin-x, var(--margin)));
|
|
21614
|
+
}
|
|
21615
|
+
|
|
21616
|
+
.navi_dialog_content {
|
|
21617
|
+
min-width: var(--min-width);
|
|
21618
|
+
min-height: var(--min-height);
|
|
21619
|
+
padding-top: var(--padding-top, var(--padding-y, var(--padding)));
|
|
21620
|
+
padding-right: var(--padding-right, var(--padding-x, var(--padding)));
|
|
21621
|
+
padding-bottom: var(--padding-bottom, var(--padding-y, var(--padding)));
|
|
21622
|
+
padding-left: var(--padding-left, var(--padding-x, var(--padding)));
|
|
21623
|
+
background: var(--background);
|
|
21624
|
+
background-color: var(--background-color, var(--background));
|
|
21625
|
+
border-width: var(--border-width);
|
|
21626
|
+
border-style: solid;
|
|
21627
|
+
border-color: var(--border-color);
|
|
21628
|
+
border-radius: var(--border-radius);
|
|
21629
|
+
}
|
|
21630
|
+
`;
|
|
21631
|
+
const DialogManagedByCSSVars = {
|
|
21632
|
+
margin: "--margin",
|
|
21633
|
+
marginTop: "--margin-top",
|
|
21634
|
+
marginBottom: "--margin-bottom",
|
|
21635
|
+
marginLeft: "--margin-left",
|
|
21636
|
+
marginRight: "--margin-right",
|
|
21637
|
+
borderRadius: "--border-radius",
|
|
21638
|
+
borderWidth: "--border-width",
|
|
21639
|
+
borderColor: "--border-color",
|
|
21640
|
+
background: "--background",
|
|
21641
|
+
backgroundColor: "--background-color",
|
|
21642
|
+
padding: "--padding",
|
|
21643
|
+
paddingTop: "--padding-top",
|
|
21644
|
+
paddingBottom: "--padding-bottom",
|
|
21645
|
+
paddingLeft: "--padding-left",
|
|
21646
|
+
paddingRight: "--padding-right",
|
|
21647
|
+
minWidth: "--min-width",
|
|
21648
|
+
minHeight: "--min-height"
|
|
21649
|
+
};
|
|
21650
|
+
const DialogLayout = ({
|
|
21651
|
+
children,
|
|
21652
|
+
contentAlignX = "center",
|
|
21653
|
+
contentAlignY = "center",
|
|
21654
|
+
...props
|
|
21655
|
+
}) => {
|
|
21656
|
+
return jsx(Box, {
|
|
21657
|
+
className: "navi_dialog_layout",
|
|
21658
|
+
managedByCSSVars: DialogManagedByCSSVars,
|
|
21659
|
+
visualSelector: ".navi_dialog_content",
|
|
21660
|
+
...props,
|
|
21661
|
+
contentAlignX: contentAlignX,
|
|
21662
|
+
contentAlignY: contentAlignY,
|
|
21663
|
+
children: jsx(Box, {
|
|
21664
|
+
className: "navi_dialog_content",
|
|
21665
|
+
row: true,
|
|
21666
|
+
children: children
|
|
21667
|
+
})
|
|
21668
|
+
});
|
|
21669
|
+
};
|
|
21670
|
+
|
|
21671
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
21672
|
+
@layer navi {
|
|
21673
|
+
.navi_viewport_layout {
|
|
21674
|
+
--padding: 40px;
|
|
21675
|
+
--background: white;
|
|
21676
|
+
}
|
|
21677
|
+
}
|
|
21678
|
+
|
|
21679
|
+
.navi_viewport_layout {
|
|
21680
|
+
padding-top: var(--padding-top, var(--padding-y, var(--padding)));
|
|
21681
|
+
padding-right: var(--padding-right, var(--padding-x, var(--padding)));
|
|
21682
|
+
padding-bottom: var(--padding-bottom, var(--padding-y, var(--padding)));
|
|
21683
|
+
padding-left: var(--padding-left, var(--padding-x, var(--padding)));
|
|
21684
|
+
background: var(--background);
|
|
21685
|
+
}
|
|
21686
|
+
`;
|
|
21687
|
+
const ViewportManagedByCSSVars = {
|
|
21688
|
+
padding: "--padding",
|
|
21689
|
+
paddingTop: "--padding-top",
|
|
21690
|
+
paddingBottom: "--padding-bottom",
|
|
21691
|
+
paddingLeft: "--padding-left",
|
|
21692
|
+
paddingRight: "--padding-right",
|
|
21693
|
+
background: "--background"
|
|
21694
|
+
};
|
|
21695
|
+
const ViewportLayout = props => {
|
|
21696
|
+
return jsx(Box, {
|
|
21697
|
+
row: true,
|
|
21698
|
+
...props,
|
|
21699
|
+
className: "navi_viewport_layout",
|
|
21700
|
+
managedByCSSVars: ViewportManagedByCSSVars,
|
|
21701
|
+
minWidth: "max-content",
|
|
21702
|
+
minHeight: "max-content",
|
|
21703
|
+
width: "100%",
|
|
21704
|
+
height: "100%"
|
|
21705
|
+
});
|
|
21706
|
+
};
|
|
21707
|
+
|
|
22012
21708
|
const createUniqueValueConstraint = (
|
|
22013
21709
|
// the set might be incomplete (the front usually don't have the full copy of all the items from the backend)
|
|
22014
21710
|
// but this is already nice to help user with what we know
|
|
@@ -22086,5 +21782,5 @@ const useDependenciesDiff = (inputs) => {
|
|
|
22086
21782
|
return diffRef.current;
|
|
22087
21783
|
};
|
|
22088
21784
|
|
|
22089
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Box, Button,
|
|
21785
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, BadgeCount, Box, Button, Checkbox, CheckboxList, Code, Col, Colgroup, Details, DialogLayout, Editable, ErrorBoundaryContext, FontSizedSvg, Form, Icon, IconAndText, Image, Input, Label, Layout, Link, LinkWithIcon, MessageBox, Paragraph, Radio, RadioList, Route, RouteLink, Routes, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, Select, SelectionContext, SummaryMarker, Svg, Tab, TabList, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, ViewportLayout, actionIntegratedVia, addCustomMessage, createAction, createSelectionKeyboardShortcuts, createUniqueValueConstraint, enableDebugActions, enableDebugOnDocumentLoading, forwardActionRequested, goBack, goForward, goTo, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, setBaseUrl, setupRoutes, stopLoad, stringifyTableSelectionValue, updateActions, useActionData, useActionStatus, useActiveRouteInfo, useCellsAndColumns, useDependenciesDiff, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSignalSync, useStateArray, useUrlSearchParam, valueInLocalStorage };
|
|
22090
21786
|
//# sourceMappingURL=jsenv_navi.js.map
|