@astryxdesign/core 0.4.1 → 0.4.2-canary.356d2f9
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/CHANGELOG.md +55 -0
- package/dist/Avatar/Avatar.d.ts +4 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +19 -23
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +9 -7
- package/dist/Chat/ChatMessage.d.ts +7 -0
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.d.ts +13 -1
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +19 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +5 -0
- package/dist/CommandPalette/CommandPaletteFooter.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteFooter.js +5 -3
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +2 -2
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +19 -15
- package/dist/HoverCard/HoverCard.d.ts +1 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +5 -13
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +6 -5
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +7 -2
- package/dist/Layer/layerHost.d.ts +24 -0
- package/dist/Layer/layerHost.d.ts.map +1 -0
- package/dist/Layer/layerHost.js +79 -0
- package/dist/Layer/useLayer.d.ts +14 -6
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +158 -30
- package/dist/NavItem/navItemStyles.stylex.d.ts +17 -5
- package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
- package/dist/NavItem/navItemStyles.stylex.js +11 -5
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +5 -0
- package/dist/SideNav/SideNav.d.ts +7 -9
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +32 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts +25 -9
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +39 -15
- package/dist/SideNav/SideNavCollapseContext.d.ts +21 -0
- package/dist/SideNav/SideNavCollapseContext.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseContext.js +16 -2
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +89 -32
- package/dist/SideNav/SideNavItem.d.ts +7 -2
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +119 -75
- package/dist/SideNav/SideNavSection.d.ts.map +1 -1
- package/dist/SideNav/SideNavSection.js +7 -16
- package/dist/SideNav/index.d.ts +1 -1
- package/dist/SideNav/index.d.ts.map +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +56 -15
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +5 -0
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +5 -0
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +14 -6
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +25 -93
- package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +10 -5
- package/dist/astryx.css +40 -8
- package/dist/astryx.umd.js +50 -50
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/containerReveal.stylex.d.ts +71 -4
- package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
- package/dist/hooks/containerReveal.stylex.js +57 -5
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useContainerReveal.d.ts +60 -3
- package/dist/hooks/useContainerReveal.d.ts.map +1 -1
- package/dist/hooks/useContainerReveal.js +27 -5
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +16 -2
- package/dist/hooks/useMenuHover.d.ts +50 -5
- package/dist/hooks/useMenuHover.d.ts.map +1 -1
- package/dist/hooks/useMenuHover.js +171 -51
- package/dist/theme/defineTheme.d.ts +16 -5
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +44 -48
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +7 -0
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +1 -0
- package/dist/theme/expandMotionScale.d.ts +1 -0
- package/dist/theme/expandMotionScale.d.ts.map +1 -1
- package/dist/theme/expandMotionScale.js +1 -0
- package/dist/theme/expandRadiusScale.d.ts +1 -0
- package/dist/theme/expandRadiusScale.d.ts.map +1 -1
- package/dist/theme/expandRadiusScale.js +1 -0
- package/dist/theme/expandTypeScale.d.ts +1 -0
- package/dist/theme/expandTypeScale.d.ts.map +1 -1
- package/dist/theme/expandTypeScale.js +1 -0
- package/dist/theme/mergeComponents.d.ts +20 -0
- package/dist/theme/mergeComponents.d.ts.map +1 -0
- package/dist/theme/mergeComponents.js +56 -0
- package/dist/theme/onMediaTokens.d.ts +6 -1
- package/dist/theme/onMediaTokens.d.ts.map +1 -1
- package/dist/theme/onMediaTokens.js +11 -3
- package/dist/theme/tokens.stylex.d.ts +3 -1
- package/dist/theme/tokens.stylex.d.ts.map +1 -1
- package/dist/theme/tokens.stylex.js +3 -1
- package/locales/en.json +84 -0
- package/locales/pseudo.json +63 -0
- package/package.json +3 -3
- package/src/Avatar/Avatar.doc.mjs +5 -2
- package/src/Avatar/Avatar.test.tsx +51 -0
- package/src/Avatar/Avatar.tsx +30 -20
- package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -1
- package/src/AvatarGroup/AvatarGroup.test.tsx +14 -0
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -2
- package/src/Button/Button.tsx +5 -3
- package/src/ButtonGroup/ButtonGroup.test.tsx +7 -4
- package/src/Card/Card.doc.mjs +2 -0
- package/src/Chat/Chat.doc.mjs +4 -1
- package/src/Chat/ChatMessage.doc.mjs +3 -3
- package/src/Chat/ChatMessage.tsx +7 -0
- package/src/Chat/ChatMessageBubble.doc.mjs +7 -0
- package/src/Chat/ChatMessageBubble.test.tsx +95 -6
- package/src/Chat/ChatMessageBubble.tsx +25 -0
- package/src/CheckboxInput/CheckboxInput.tsx +20 -0
- package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
- package/src/CommandPalette/CommandPaletteFooter.tsx +6 -3
- package/src/DateTimeInput/DateTimeInput.tsx +4 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +72 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +24 -20
- package/src/HoverCard/HoverCard.doc.mjs +3 -3
- package/src/HoverCard/HoverCard.test.tsx +283 -55
- package/src/HoverCard/HoverCard.tsx +5 -13
- package/src/HoverCard/useHoverCard.tsx +8 -11
- package/src/InputGroup/groupStyles.ts +7 -8
- package/src/Item/Item.doc.mjs +4 -0
- package/src/Layer/layerHost.test.ts +99 -0
- package/src/Layer/layerHost.ts +141 -0
- package/src/Layer/useLayer.doc.mjs +14 -4
- package/src/Layer/useLayer.test.tsx +332 -7
- package/src/Layer/useLayer.tsx +235 -36
- package/src/MobileNav/MobileNav.doc.mjs +7 -0
- package/src/NavItem/navItemStyles.stylex.ts +31 -5
- package/src/RadioList/RadioListItem.tsx +20 -0
- package/src/SideNav/SideNav.doc.mjs +13 -4
- package/src/SideNav/SideNav.test.tsx +858 -2
- package/src/SideNav/SideNav.tsx +37 -16
- package/src/SideNav/SideNavCollapseButton.doc.mjs +28 -6
- package/src/SideNav/SideNavCollapseButton.tsx +67 -15
- package/src/SideNav/SideNavCollapseContext.ts +29 -9
- package/src/SideNav/SideNavHeading.tsx +53 -25
- package/src/SideNav/SideNavItem.doc.mjs +13 -0
- package/src/SideNav/SideNavItem.tsx +97 -84
- package/src/SideNav/SideNavSection.tsx +6 -20
- package/src/SideNav/index.ts +2 -0
- package/src/Slider/Slider.test.tsx +69 -33
- package/src/Slider/Slider.tsx +65 -13
- package/src/Switch/Switch.tsx +20 -0
- package/src/TabList/TabList.doc.mjs +3 -0
- package/src/Text/Text.doc.mjs +1 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +3 -0
- package/src/Thumbnail/Thumbnail.tsx +10 -0
- package/src/Timestamp/Timestamp.test.tsx +40 -22
- package/src/Toolbar/Toolbar.test.tsx +14 -14
- package/src/TopNav/TopNav.test.tsx +86 -1
- package/src/TopNav/TopNavHeading.tsx +21 -14
- package/src/TopNav/TopNavMegaMenu.test.tsx +43 -0
- package/src/TopNav/TopNavMegaMenu.tsx +29 -105
- package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
- package/src/TopNav/TopNavMenu.test.tsx +41 -0
- package/src/TopNav/TopNavMenu.tsx +14 -4
- package/src/TreeList/TreeList.doc.mjs +1 -0
- package/src/hooks/containerReveal.stylex.ts +140 -9
- package/src/hooks/index.ts +6 -1
- package/src/hooks/useContainerReveal.doc.mjs +11 -5
- package/src/hooks/useContainerReveal.test.tsx +70 -3
- package/src/hooks/useContainerReveal.ts +86 -7
- package/src/hooks/useFocusTrap.test.tsx +16 -0
- package/src/hooks/useFocusTrap.ts +20 -2
- package/src/hooks/useMenuHover.test.tsx +364 -0
- package/src/hooks/useMenuHover.ts +243 -47
- package/src/theme/defineTheme.test.ts +127 -0
- package/src/theme/defineTheme.ts +57 -51
- package/src/theme/derivedVarRegistry.test.ts +78 -12
- package/src/theme/derivedVarRegistry.ts +4 -0
- package/src/theme/expandColorScale.ts +1 -0
- package/src/theme/expandMotionScale.ts +1 -0
- package/src/theme/expandRadiusScale.ts +1 -0
- package/src/theme/expandTypeScale.ts +1 -0
- package/src/theme/mergeComponents.ts +59 -0
- package/src/theme/onMediaTokens.ts +9 -2
- package/src/theme/themingTargets.test.ts +152 -26
- package/src/theme/tokens.stylex.ts +3 -1
- package/src/theme/tokens.test.ts +12 -0
- package/src/theme/useTheme.test.tsx +18 -0
|
@@ -4,26 +4,53 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useMenuHover.ts
|
|
7
|
-
* @input Uses React hooks, useListFocus
|
|
7
|
+
* @input Uses React hooks, useListFocus, useMediaQuery
|
|
8
8
|
* @output Exports useMenuHover hook
|
|
9
|
-
* @position Internal hook; used by nav heading components
|
|
9
|
+
* @position Internal hook; used by nav heading components, TopNavMenu,
|
|
10
|
+
* TopNavMegaMenu and DropdownMenuSubMenu
|
|
10
11
|
*
|
|
11
|
-
* Hover as a progressive enhancement
|
|
12
|
+
* Hover as a progressive enhancement over standard popover behavior: click
|
|
13
|
+
* toggles, Escape and outside-click close, arrows navigate; on top of that,
|
|
14
|
+
* mouseenter opens after a delay and mouseleave closes one that hover opened.
|
|
12
15
|
*
|
|
13
|
-
*
|
|
14
|
-
* arrow keys navigate menu items.
|
|
16
|
+
* Three behaviors here are not obvious and are load-bearing:
|
|
15
17
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* - Click-to-close additionally skips the next mouseenter
|
|
18
|
+
* 1. Hover→click guard (#3121). A hover-opened menu is already open under the
|
|
19
|
+
* cursor when the pointer arrives, so the click that naturally follows would
|
|
20
|
+
* toggle it shut. Within `clickGuardMs` a click instead confirms it: the menu
|
|
21
|
+
* pins and behaves like a click-open from then on.
|
|
21
22
|
*
|
|
22
|
-
*
|
|
23
|
+
* 2. Focus moves synchronously. `useLayer.show()` calls `showPopover()` in the
|
|
24
|
+
* same tick and the layer's children are always mounted, so items are
|
|
25
|
+
* focusable the moment `show()` returns — a `requestAnimationFrame` here
|
|
26
|
+
* lands after paint and races anything else moving focus. Hover-opens are the
|
|
27
|
+
* exception: the pointer is driving, so focus stays on the trigger. The hook
|
|
28
|
+
* always passes `skipAutoFocus` and owns focus itself, because the popover's
|
|
29
|
+
* auto-focus targets the first *tabbable* node while a menu wants its first
|
|
30
|
+
* item — under roving tabindex those are different elements.
|
|
31
|
+
*
|
|
32
|
+
* 3. Native light dismiss. A `popover="auto"` is dismissed by the browser on
|
|
33
|
+
* pointer interaction outside the panel, and a trigger outside the panel
|
|
34
|
+
* counts — before React's click handler runs. `popoverId` makes the trigger
|
|
35
|
+
* the panel's invoker, which exempts it. jsdom implements neither light
|
|
36
|
+
* dismiss nor invokers, so that wiring is only verifiable in a browser.
|
|
23
37
|
*/
|
|
24
38
|
import { useCallback, useEffect, useRef } from 'react';
|
|
39
|
+
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
25
40
|
import { useListFocus } from "./useListFocus.js";
|
|
26
41
|
import { useMediaQuery } from "./useMediaQuery.js";
|
|
42
|
+
const DEFAULT_CLICK_GUARD_MS = 500;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* How long after a close a mouseenter on the trigger is ignored.
|
|
46
|
+
*
|
|
47
|
+
* A panel positioned over its own trigger puts that trigger back under a
|
|
48
|
+
* stationary pointer when it closes, and the browser fires a fresh mouseenter —
|
|
49
|
+
* which reopened the menu the user had just dismissed. Time-bounded rather than
|
|
50
|
+
* a one-shot flag, so a deliberate re-hover seconds later still opens; a real
|
|
51
|
+
* mouseleave clears it early.
|
|
52
|
+
*/
|
|
53
|
+
const REOPEN_SUPPRESS_MS = 300;
|
|
27
54
|
export function useMenuHover(options) {
|
|
28
55
|
const {
|
|
29
56
|
show,
|
|
@@ -31,23 +58,35 @@ export function useMenuHover(options) {
|
|
|
31
58
|
isOpen,
|
|
32
59
|
isEnabled,
|
|
33
60
|
showDelay = 150,
|
|
34
|
-
hideDelay = 200
|
|
61
|
+
hideDelay = 200,
|
|
62
|
+
clickGuardMs = DEFAULT_CLICK_GUARD_MS,
|
|
63
|
+
itemSelector,
|
|
64
|
+
popoverId,
|
|
65
|
+
ownsFocus = true
|
|
35
66
|
} = options;
|
|
36
67
|
const hasHover = useMediaQuery('(hover: hover)');
|
|
37
68
|
const showTimerRef = useRef(null);
|
|
38
69
|
const hideTimerRef = useRef(null);
|
|
39
70
|
const triggerElRef = useRef(null);
|
|
40
|
-
|
|
71
|
+
/** Menu was hover-opened, so mouseleave may close it. */
|
|
41
72
|
const hoverModeRef = useRef(false);
|
|
42
|
-
|
|
43
|
-
|
|
73
|
+
const closedAtRef = useRef(0);
|
|
74
|
+
/** When the current open began as a hover-open; 0 once confirmed or closed. */
|
|
75
|
+
const hoverOpenedAtRef = useRef(0);
|
|
44
76
|
const prevIsOpenRef = useRef(isOpen);
|
|
45
77
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
78
|
+
// Catches every close, whatever caused it. A layout effect, not render: it
|
|
79
|
+
// must land before the browser hit-tests the vanished panel and fires the
|
|
80
|
+
// mouseenter REOPEN_SUPPRESS_MS exists to swallow.
|
|
81
|
+
useIsomorphicLayoutEffect(() => {
|
|
82
|
+
const wasOpen = prevIsOpenRef.current;
|
|
83
|
+
prevIsOpenRef.current = isOpen;
|
|
84
|
+
if (wasOpen && !isOpen) {
|
|
85
|
+
hoverModeRef.current = false;
|
|
86
|
+
hoverOpenedAtRef.current = 0;
|
|
87
|
+
closedAtRef.current = Date.now();
|
|
88
|
+
}
|
|
89
|
+
}, [isOpen]);
|
|
51
90
|
const clearTimeouts = useCallback(() => {
|
|
52
91
|
if (showTimerRef.current) {
|
|
53
92
|
clearTimeout(showTimerRef.current);
|
|
@@ -58,59 +97,133 @@ export function useMenuHover(options) {
|
|
|
58
97
|
hideTimerRef.current = null;
|
|
59
98
|
}
|
|
60
99
|
}, []);
|
|
100
|
+
|
|
101
|
+
// useListFocus needs an onEscape that is defined in terms of its own listRef;
|
|
102
|
+
// the indirection avoids the use-before-declare.
|
|
103
|
+
const escapeHandlerRef = useRef(() => {});
|
|
61
104
|
const {
|
|
62
105
|
listRef: menuRef,
|
|
63
106
|
handleKeyDown: handleListKeyDown,
|
|
64
107
|
focusFirst
|
|
65
108
|
} = useListFocus({
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
hide();
|
|
69
|
-
}
|
|
109
|
+
itemSelector,
|
|
110
|
+
onEscape: () => escapeHandlerRef.current()
|
|
70
111
|
});
|
|
112
|
+
const hideAndRestoreFocus = useCallback(() => {
|
|
113
|
+
// Read before hiding: closing the layer moves focus itself.
|
|
114
|
+
const menuHadFocus = menuRef.current?.contains(document.activeElement) ?? false;
|
|
115
|
+
hide();
|
|
116
|
+
if (menuHadFocus) {
|
|
117
|
+
triggerElRef.current?.focus();
|
|
118
|
+
}
|
|
119
|
+
}, [hide, menuRef]);
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
escapeHandlerRef.current = () => {
|
|
122
|
+
clearTimeouts();
|
|
123
|
+
hideAndRestoreFocus();
|
|
124
|
+
};
|
|
125
|
+
}, [clearTimeouts, hideAndRestoreFocus]);
|
|
71
126
|
useEffect(() => {
|
|
72
127
|
return () => clearTimeouts();
|
|
73
128
|
}, [clearTimeouts]);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
129
|
+
const focusMenu = useCallback(() => {
|
|
130
|
+
// An empty or still-loading menu has no focusable item; focus the container
|
|
131
|
+
// so keyboard ownership still transfers off the trigger's list.
|
|
132
|
+
if (!focusFirst()) {
|
|
133
|
+
menuRef.current?.focus();
|
|
134
|
+
}
|
|
135
|
+
}, [focusFirst, menuRef]);
|
|
136
|
+
const openAndFocus = useCallback(() => {
|
|
137
|
+
if (!ownsFocus) {
|
|
83
138
|
show();
|
|
84
|
-
|
|
139
|
+
return;
|
|
85
140
|
}
|
|
86
|
-
|
|
141
|
+
show({
|
|
142
|
+
skipAutoFocus: true
|
|
143
|
+
});
|
|
144
|
+
focusMenu();
|
|
145
|
+
}, [ownsFocus, show, focusMenu]);
|
|
146
|
+
const confirmHoverOpen = useCallback(() => {
|
|
147
|
+
const isConfirming = clickGuardMs > 0 && hoverOpenedAtRef.current > 0 && Date.now() - hoverOpenedAtRef.current < clickGuardMs;
|
|
148
|
+
if (!isConfirming) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
hoverModeRef.current = false;
|
|
152
|
+
hoverOpenedAtRef.current = 0;
|
|
153
|
+
return true;
|
|
154
|
+
}, [clickGuardMs]);
|
|
155
|
+
const handleClick = useCallback(event => {
|
|
156
|
+
// Cancel the invoker's default toggle so this handler stays the single
|
|
157
|
+
// source of truth; popoverTarget still exempts the trigger from dismissal.
|
|
158
|
+
if (popoverId) {
|
|
159
|
+
event?.preventDefault();
|
|
160
|
+
}
|
|
161
|
+
clearTimeouts();
|
|
87
162
|
|
|
88
|
-
|
|
163
|
+
// Enter/Space arrive as a click with detail 0, and always open. A keyboard
|
|
164
|
+
// user reaches the trigger of an open menu only because a hover-open left
|
|
165
|
+
// focus behind; closing there would stranded them outside a visible menu.
|
|
166
|
+
const isKeyboardActivation = event != null && event.detail === 0;
|
|
167
|
+
if (isKeyboardActivation) {
|
|
168
|
+
closedAtRef.current = 0;
|
|
169
|
+
hoverModeRef.current = false;
|
|
170
|
+
hoverOpenedAtRef.current = 0;
|
|
171
|
+
if (isOpen) {
|
|
172
|
+
if (ownsFocus) {
|
|
173
|
+
focusMenu();
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
openAndFocus();
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (!isOpen) {
|
|
181
|
+
closedAtRef.current = 0;
|
|
182
|
+
hoverModeRef.current = false;
|
|
183
|
+
hoverOpenedAtRef.current = 0;
|
|
184
|
+
openAndFocus();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (confirmHoverOpen()) {
|
|
188
|
+
if (ownsFocus) {
|
|
189
|
+
focusMenu();
|
|
190
|
+
}
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
hideAndRestoreFocus();
|
|
194
|
+
}, [popoverId, clearTimeouts, isOpen, ownsFocus, confirmHoverOpen, openAndFocus, focusMenu, hideAndRestoreFocus]);
|
|
89
195
|
const handleMouseEnter = useCallback(() => {
|
|
90
196
|
if (!hasHover) {
|
|
91
197
|
return;
|
|
92
198
|
}
|
|
93
|
-
if (
|
|
94
|
-
|
|
199
|
+
if (closedAtRef.current > 0 && Date.now() - closedAtRef.current < REOPEN_SUPPRESS_MS) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// Re-entering an open menu's trigger must not un-pin it or re-arm the
|
|
203
|
+
// guard, which would make the next deliberate click another "confirm" and
|
|
204
|
+
// leave the menu undismissable.
|
|
205
|
+
if (isOpen) {
|
|
206
|
+
clearTimeouts();
|
|
95
207
|
return;
|
|
96
208
|
}
|
|
97
209
|
hoverModeRef.current = true;
|
|
98
210
|
clearTimeouts();
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
show({
|
|
102
|
-
skipAutoFocus: true
|
|
103
|
-
});
|
|
104
|
-
}, showDelay);
|
|
105
|
-
} else {
|
|
211
|
+
const openByHover = () => {
|
|
212
|
+
hoverOpenedAtRef.current = Date.now();
|
|
106
213
|
show({
|
|
107
214
|
skipAutoFocus: true
|
|
108
215
|
});
|
|
216
|
+
};
|
|
217
|
+
if (showDelay > 0) {
|
|
218
|
+
showTimerRef.current = setTimeout(openByHover, showDelay);
|
|
219
|
+
} else {
|
|
220
|
+
openByHover();
|
|
109
221
|
}
|
|
110
|
-
}, [hasHover, clearTimeouts, show, showDelay]);
|
|
111
|
-
|
|
112
|
-
// Hover: mouseleave only closes if in hover mode
|
|
222
|
+
}, [hasHover, isOpen, clearTimeouts, show, showDelay]);
|
|
113
223
|
const handleMouseLeave = useCallback(() => {
|
|
224
|
+
// A real leave ends the stationary-pointer case the suppression window
|
|
225
|
+
// exists for, so the next enter is deliberate whenever it arrives.
|
|
226
|
+
closedAtRef.current = 0;
|
|
114
227
|
if (!hoverModeRef.current) {
|
|
115
228
|
return;
|
|
116
229
|
}
|
|
@@ -119,8 +232,6 @@ export function useMenuHover(options) {
|
|
|
119
232
|
hide();
|
|
120
233
|
}, hideDelay);
|
|
121
234
|
}, [clearTimeouts, hide, hideDelay]);
|
|
122
|
-
|
|
123
|
-
// Content: mouseenter cancels pending hide
|
|
124
235
|
const handleContentMouseEnter = useCallback(() => {
|
|
125
236
|
clearTimeouts();
|
|
126
237
|
}, [clearTimeouts]);
|
|
@@ -144,6 +255,9 @@ export function useMenuHover(options) {
|
|
|
144
255
|
},
|
|
145
256
|
menuRef,
|
|
146
257
|
focusFirst,
|
|
258
|
+
focusMenu,
|
|
259
|
+
confirmHoverOpen,
|
|
260
|
+
close: hideAndRestoreFocus,
|
|
147
261
|
setTriggerEl: noopRef
|
|
148
262
|
};
|
|
149
263
|
}
|
|
@@ -151,7 +265,10 @@ export function useMenuHover(options) {
|
|
|
151
265
|
triggerProps: {
|
|
152
266
|
onClick: handleClick,
|
|
153
267
|
onMouseEnter: handleMouseEnter,
|
|
154
|
-
onMouseLeave: handleMouseLeave
|
|
268
|
+
onMouseLeave: handleMouseLeave,
|
|
269
|
+
...(popoverId ? {
|
|
270
|
+
popoverTarget: popoverId
|
|
271
|
+
} : null)
|
|
155
272
|
},
|
|
156
273
|
contentProps: {
|
|
157
274
|
onMouseEnter: handleContentMouseEnter,
|
|
@@ -160,6 +277,9 @@ export function useMenuHover(options) {
|
|
|
160
277
|
},
|
|
161
278
|
menuRef,
|
|
162
279
|
focusFirst,
|
|
280
|
+
focusMenu,
|
|
281
|
+
confirmHoverOpen,
|
|
282
|
+
close: hideAndRestoreFocus,
|
|
163
283
|
setTriggerEl: setTriggerRef
|
|
164
284
|
};
|
|
165
285
|
}
|
|
@@ -26,19 +26,25 @@
|
|
|
26
26
|
* <App />
|
|
27
27
|
* </Theme>
|
|
28
28
|
* ```
|
|
29
|
+
*
|
|
30
|
+
* SYNC: `DefineThemeInput` is the theme surface. Adding, removing, or renaming
|
|
31
|
+
* a field means updating:
|
|
32
|
+
* - /packages/cli/assets/theme.template.ts (documents every field; the
|
|
33
|
+
* drift guard is scripts/check-theme-template.test.mjs)
|
|
34
|
+
* - /packages/cli/assets/docs/theme.doc.mjs (`astryx docs theme`)
|
|
29
35
|
*/
|
|
30
36
|
import type { IconRegistry } from '../Icon/globalIconRegistry';
|
|
31
37
|
import type { IndicatorRegistry } from '../Indicator/types';
|
|
32
38
|
import type { TypographyConfig } from './types';
|
|
33
39
|
import { type OnMediaOverrides, type ResolvedOnMedia } from './onMediaTokens';
|
|
34
|
-
import { colorDefaults, spacingDefaults, sizeDefaults, focusDefaults, radiusDefaults, shadowDefaults, durationDefaults, easeDefaults, typographyDefaults, textSizeDefaults, fontWeightDefaults, typeScaleDefaults } from './tokens.stylex';
|
|
40
|
+
import { colorDefaults, spacingDefaults, sizeDefaults, borderDefaults, focusDefaults, radiusDefaults, shadowDefaults, durationDefaults, easeDefaults, typographyDefaults, textSizeDefaults, fontWeightDefaults, typeScaleDefaults } from './tokens.stylex';
|
|
35
41
|
import { type MotionScaleConfig } from './expandMotionScale';
|
|
36
42
|
import { type RadiusScaleConfig } from './expandRadiusScale';
|
|
37
43
|
import { type ColorScaleConfig } from './expandColorScale';
|
|
38
44
|
import type { DomainTokenName } from './domainTokens';
|
|
39
45
|
import type { SyntaxThemeDefinition } from './syntax';
|
|
40
46
|
/** All valid Astryx core token names */
|
|
41
|
-
export type CoreTokenName = keyof typeof colorDefaults | keyof typeof spacingDefaults | keyof typeof sizeDefaults | keyof typeof focusDefaults | keyof typeof radiusDefaults | keyof typeof shadowDefaults | keyof typeof durationDefaults | keyof typeof easeDefaults | keyof typeof typographyDefaults | keyof typeof textSizeDefaults | keyof typeof fontWeightDefaults | keyof typeof typeScaleDefaults;
|
|
47
|
+
export type CoreTokenName = keyof typeof colorDefaults | keyof typeof spacingDefaults | keyof typeof sizeDefaults | keyof typeof borderDefaults | keyof typeof focusDefaults | keyof typeof radiusDefaults | keyof typeof shadowDefaults | keyof typeof durationDefaults | keyof typeof easeDefaults | keyof typeof typographyDefaults | keyof typeof textSizeDefaults | keyof typeof fontWeightDefaults | keyof typeof typeScaleDefaults;
|
|
42
48
|
/** All valid Astryx token names — core + domain tokens */
|
|
43
49
|
export type TokenName = CoreTokenName | DomainTokenName;
|
|
44
50
|
/**
|
|
@@ -106,9 +112,14 @@ export interface DefineThemeInput {
|
|
|
106
112
|
/** Theme name — used for data-astryx-theme attribute and identification */
|
|
107
113
|
name: string;
|
|
108
114
|
/**
|
|
109
|
-
* Base theme to extend. When provided, the new theme starts with
|
|
110
|
-
* base
|
|
111
|
-
*
|
|
115
|
+
* Base theme to extend. When provided, the new theme starts with everything
|
|
116
|
+
* the base resolved to — tokens, component overrides, icons, indicators, and
|
|
117
|
+
* its `onDark`/`onLight` surfaces — then applies this input on top. The base
|
|
118
|
+
* theme's values have lowest precedence.
|
|
119
|
+
*
|
|
120
|
+
* The result is flat: an extended theme carries its inheritance in its own
|
|
121
|
+
* resolved output, so `astryx theme build` emits one self-contained
|
|
122
|
+
* stylesheet and the base's CSS does not need to be loaded alongside it.
|
|
112
123
|
*
|
|
113
124
|
* Use this to create variant themes that customize only a few aspects
|
|
114
125
|
* (e.g. icons, accent color) without re-specifying the full theme.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defineTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defineTheme.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"defineTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defineTheme.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,16 +28,23 @@
|
|
|
28
28
|
* <App />
|
|
29
29
|
* </Theme>
|
|
30
30
|
* ```
|
|
31
|
+
*
|
|
32
|
+
* SYNC: `DefineThemeInput` is the theme surface. Adding, removing, or renaming
|
|
33
|
+
* a field means updating:
|
|
34
|
+
* - /packages/cli/assets/theme.template.ts (documents every field; the
|
|
35
|
+
* drift guard is scripts/check-theme-template.test.mjs)
|
|
36
|
+
* - /packages/cli/assets/docs/theme.doc.mjs (`astryx docs theme`)
|
|
31
37
|
*/
|
|
32
38
|
|
|
33
39
|
import { resolveOnMedia } from "./onMediaTokens.js";
|
|
34
|
-
import { colorDefaults, spacingDefaults, sizeDefaults, focusDefaults, radiusDefaults, shadowDefaults, durationDefaults, easeDefaults, typographyDefaults, textSizeDefaults, fontWeightDefaults, typeScaleDefaults } from "./tokens.stylex.js";
|
|
40
|
+
import { colorDefaults, spacingDefaults, sizeDefaults, borderDefaults, focusDefaults, radiusDefaults, shadowDefaults, durationDefaults, easeDefaults, typographyDefaults, textSizeDefaults, fontWeightDefaults, typeScaleDefaults } from "./tokens.stylex.js";
|
|
35
41
|
import { expandTypeScale, generateTypeScaleComponents } from "./expandTypeScale.js";
|
|
36
42
|
import { expandMotionScale } from "./expandMotionScale.js";
|
|
37
43
|
import { expandRadiusScale } from "./expandRadiusScale.js";
|
|
38
44
|
import { expandColorScale } from "./expandColorScale.js";
|
|
39
45
|
import { domainTokenDefaults } from "./domainTokens/index.js";
|
|
40
46
|
import { registerTheme } from "./themeRegistry.js";
|
|
47
|
+
import { deepMergeComponents } from "./mergeComponents.js";
|
|
41
48
|
|
|
42
49
|
// =============================================================================
|
|
43
50
|
// Types
|
|
@@ -120,6 +127,7 @@ export const tokenDefaults = {
|
|
|
120
127
|
...colorDefaults,
|
|
121
128
|
...spacingDefaults,
|
|
122
129
|
...sizeDefaults,
|
|
130
|
+
...borderDefaults,
|
|
123
131
|
...focusDefaults,
|
|
124
132
|
...radiusDefaults,
|
|
125
133
|
...shadowDefaults,
|
|
@@ -148,48 +156,6 @@ function resolveTokenValue(value) {
|
|
|
148
156
|
return value;
|
|
149
157
|
}
|
|
150
158
|
|
|
151
|
-
/**
|
|
152
|
-
* Deep-merge two component style maps.
|
|
153
|
-
* Properties in `overrides` take precedence over `base`.
|
|
154
|
-
* This allows typeScale-generated rules to be overridden by explicit components.
|
|
155
|
-
*/
|
|
156
|
-
function deepMergeComponents(base, overrides) {
|
|
157
|
-
if (!base && !overrides) {
|
|
158
|
-
return undefined;
|
|
159
|
-
}
|
|
160
|
-
if (!base) {
|
|
161
|
-
return overrides;
|
|
162
|
-
}
|
|
163
|
-
if (!overrides) {
|
|
164
|
-
return base;
|
|
165
|
-
}
|
|
166
|
-
const result = {};
|
|
167
|
-
|
|
168
|
-
// Start with all base entries
|
|
169
|
-
for (const [component, rules] of Object.entries(base)) {
|
|
170
|
-
result[component] = {
|
|
171
|
-
...rules
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Merge overrides on top
|
|
176
|
-
for (const [component, rules] of Object.entries(overrides)) {
|
|
177
|
-
if (!result[component]) {
|
|
178
|
-
result[component] = {
|
|
179
|
-
...rules
|
|
180
|
-
};
|
|
181
|
-
} else {
|
|
182
|
-
for (const [key, styles] of Object.entries(rules)) {
|
|
183
|
-
result[component][key] = {
|
|
184
|
-
...result[component][key],
|
|
185
|
-
...styles
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
159
|
/**
|
|
194
160
|
* Resolve a FontWeight name to a var() reference.
|
|
195
161
|
* Named weights map to var(--font-weight-*); raw values pass through.
|
|
@@ -219,6 +185,24 @@ function buildFontFamily(family, fallbacks) {
|
|
|
219
185
|
return quoted;
|
|
220
186
|
}
|
|
221
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Describe a rejected `extends` value for the error message — enough to tell a
|
|
190
|
+
* missed import (`undefined`) from a module namespace or a plain object.
|
|
191
|
+
*/
|
|
192
|
+
function describeBadBase(value) {
|
|
193
|
+
if (value === undefined) {
|
|
194
|
+
return 'undefined';
|
|
195
|
+
}
|
|
196
|
+
if (value === null) {
|
|
197
|
+
return 'null';
|
|
198
|
+
}
|
|
199
|
+
if (typeof value !== 'object') {
|
|
200
|
+
return typeof value;
|
|
201
|
+
}
|
|
202
|
+
const keys = Object.keys(value);
|
|
203
|
+
return `an object with keys [${keys.slice(0, 4).join(', ')}${keys.length > 4 ? ', …' : ''}]`;
|
|
204
|
+
}
|
|
205
|
+
|
|
222
206
|
/**
|
|
223
207
|
* Create an Astryx theme.
|
|
224
208
|
*
|
|
@@ -232,7 +216,15 @@ function buildFontFamily(family, fallbacks) {
|
|
|
232
216
|
export function defineTheme(input) {
|
|
233
217
|
const tokens = {};
|
|
234
218
|
|
|
235
|
-
// 0. Pre-seed from base theme when `extends` is provided (lowest precedence)
|
|
219
|
+
// 0. Pre-seed from base theme when `extends` is provided (lowest precedence).
|
|
220
|
+
// A base that is not a theme is refused rather than ignored: `extends` used
|
|
221
|
+
// to inherit nothing when its value was undefined, which is what a named
|
|
222
|
+
// import silently resolving to the wrong module hands over, and the theme
|
|
223
|
+
// then built into a plausible-looking stylesheet missing everything it was
|
|
224
|
+
// supposed to inherit.
|
|
225
|
+
if ('extends' in input && !isDefinedTheme(input.extends)) {
|
|
226
|
+
throw new Error(`defineTheme("${input.name}"): \`extends\` must be a theme from defineTheme(), got ${describeBadBase(input.extends)}. ` + `Check that the import naming your base theme resolves to its source and exports that name — ` + `a generated \`<theme>.js\` artifact sitting next to the source exports \`<name>Theme\`, not the source's own export.`);
|
|
227
|
+
}
|
|
236
228
|
const base = input.extends;
|
|
237
229
|
if (base) {
|
|
238
230
|
for (const [key, value] of Object.entries(base.tokens)) {
|
|
@@ -363,9 +355,10 @@ export function defineTheme(input) {
|
|
|
363
355
|
components = deepMergeComponents(base.components, components);
|
|
364
356
|
}
|
|
365
357
|
|
|
366
|
-
// 4. Resolve on-media token overrides (
|
|
367
|
-
|
|
368
|
-
const
|
|
358
|
+
// 4. Resolve on-media token overrides (base's resolved surface, then
|
|
359
|
+
// defaults, then this theme's own overrides)
|
|
360
|
+
const __onDark = resolveOnMedia('dark', input.onDark, base?.__onDark);
|
|
361
|
+
const __onLight = resolveOnMedia('light', input.onLight, base?.__onLight);
|
|
369
362
|
|
|
370
363
|
// 5. Merge icons — input icons override base icons
|
|
371
364
|
const icons = input.icons && base?.icons ? {
|
|
@@ -385,7 +378,10 @@ export function defineTheme(input) {
|
|
|
385
378
|
components,
|
|
386
379
|
icons,
|
|
387
380
|
indicators,
|
|
388
|
-
__inputTokens: input.tokens
|
|
381
|
+
__inputTokens: base?.__inputTokens || input.tokens ? {
|
|
382
|
+
...base?.__inputTokens,
|
|
383
|
+
...input.tokens
|
|
384
|
+
} : undefined,
|
|
389
385
|
__onDark,
|
|
390
386
|
__onLight
|
|
391
387
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derivedVarRegistry.d.ts","sourceRoot":"","sources":["../../src/theme/derivedVarRegistry.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,iFAAiF;IACjF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"derivedVarRegistry.d.ts","sourceRoot":"","sources":["../../src/theme/derivedVarRegistry.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,iFAAiF;IACjF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CA0ChE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,eAAe,EAAE,CAMnB"}
|
|
@@ -55,6 +55,13 @@ export const derivedVarRegistry = {
|
|
|
55
55
|
property: 'padding',
|
|
56
56
|
expand: 'container'
|
|
57
57
|
}],
|
|
58
|
+
'context-menu': [{
|
|
59
|
+
property: 'borderRadius',
|
|
60
|
+
vars: ['--_dropdown-menu-radius']
|
|
61
|
+
}, {
|
|
62
|
+
property: 'padding',
|
|
63
|
+
vars: ['--_dropdown-menu-padding']
|
|
64
|
+
}],
|
|
58
65
|
'dropdown-menu': [{
|
|
59
66
|
property: 'borderRadius',
|
|
60
67
|
vars: ['--_dropdown-menu-radius']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expandColorScale.d.ts","sourceRoot":"","sources":["../../src/theme/expandColorScale.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"expandColorScale.d.ts","sourceRoot":"","sources":["../../src/theme/expandColorScale.ts"],"names":[],"mappings":"AAwCA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAE3C;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAyCtD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,EACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,MAAM,CAYR;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAoI3E"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* SYNC: When modified, update:
|
|
17
17
|
* - /packages/core/src/theme/expandMotionScale.test.ts
|
|
18
18
|
* - /packages/core/src/theme/defineTheme.ts
|
|
19
|
+
* - /packages/cli/assets/theme.template.ts (the annotated field reference)
|
|
19
20
|
*/
|
|
20
21
|
/**
|
|
21
22
|
* Motion scale configuration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expandMotionScale.d.ts","sourceRoot":"","sources":["../../src/theme/expandMotionScale.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"expandMotionScale.d.ts","sourceRoot":"","sources":["../../src/theme/expandMotionScale.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qDAAqD;AACrD,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAavD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,iBAAiB,GACxB,iBAAiB,CA0BnB"}
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* SYNC: When modified, update:
|
|
19
19
|
* - /packages/core/src/theme/expandMotionScale.test.ts
|
|
20
20
|
* - /packages/core/src/theme/defineTheme.ts
|
|
21
|
+
* - /packages/cli/assets/theme.template.ts (the annotated field reference)
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
24
|
// =============================================================================
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* SYNC: When modified, update:
|
|
21
21
|
* - /packages/core/src/theme/expandRadiusScale.test.ts
|
|
22
22
|
* - /packages/core/src/theme/defineTheme.ts
|
|
23
|
+
* - /packages/cli/assets/theme.template.ts (the annotated field reference)
|
|
23
24
|
*/
|
|
24
25
|
/**
|
|
25
26
|
* Radius scale configuration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expandRadiusScale.d.ts","sourceRoot":"","sources":["../../src/theme/expandRadiusScale.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"expandRadiusScale.d.ts","sourceRoot":"","sources":["../../src/theme/expandRadiusScale.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAMvD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,iBAAiB,GACxB,iBAAiB,CAanB"}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* SYNC: When modified, update:
|
|
23
23
|
* - /packages/core/src/theme/expandRadiusScale.test.ts
|
|
24
24
|
* - /packages/core/src/theme/defineTheme.ts
|
|
25
|
+
* - /packages/cli/assets/theme.template.ts (the annotated field reference)
|
|
25
26
|
*/
|
|
26
27
|
|
|
27
28
|
// =============================================================================
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
* SYNC: When modified, update:
|
|
43
43
|
* - /packages/core/src/theme/expandTypeScale.test.ts
|
|
44
44
|
* - /packages/core/src/theme/defineTheme.ts
|
|
45
|
+
* - /packages/cli/assets/theme.template.ts (the annotated field reference)
|
|
45
46
|
*/
|
|
46
47
|
/** Font weight value — either a CSS string or a var() reference. */
|
|
47
48
|
export type FontWeightValue = string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expandTypeScale.d.ts","sourceRoot":"","sources":["../../src/theme/expandTypeScale.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"expandTypeScale.d.ts","sourceRoot":"","sources":["../../src/theme/expandTypeScale.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAMH,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC1C,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,CAC/C,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CACvC,MAAM,CACF,MAAM,GACN,OAAO,GACP,OAAO,GACP,MAAM,GACN,YAAY,GACZ,WAAW,GACX,WAAW,GACX,WAAW,GACX,CAAC,MAAM,GAAG,EAAE,CAAC,EACf,eAAe,CAChB,CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,OAAO,CAAC,EAAE;QACR,yEAAyE;QACzE,OAAO,CAAC,EAAE,sBAAsB,CAAC;QACjC,oEAAoE;QACpE,IAAI,CAAC,EAAE,mBAAmB,CAAC;KAC5B,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAwIrD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CA+CxE;AAiBD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAmDxD"}
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
* SYNC: When modified, update:
|
|
45
45
|
* - /packages/core/src/theme/expandTypeScale.test.ts
|
|
46
46
|
* - /packages/core/src/theme/defineTheme.ts
|
|
47
|
+
* - /packages/cli/assets/theme.template.ts (the annotated field reference)
|
|
47
48
|
*/
|
|
48
49
|
|
|
49
50
|
// =============================================================================
|