@astryxdesign/core 0.4.1 → 0.4.2-canary.01592f7
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/Chat/ChatTokenizedText.js +1 -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/ComplexSelector/ComplexSelector.d.ts +38 -4
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +96 -35
- package/dist/ComplexSelector/index.d.ts +2 -2
- package/dist/ComplexSelector/index.d.ts.map +1 -1
- package/dist/ComplexSelector/index.js +1 -1
- 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/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +55 -12
- 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/Chat/ChatTokenizedText.tsx +1 -1
- package/src/CheckboxInput/CheckboxInput.tsx +20 -0
- package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
- package/src/CommandPalette/CommandPaletteFooter.tsx +6 -3
- package/src/ComplexSelector/ComplexSelector.doc.mjs +55 -6
- package/src/ComplexSelector/ComplexSelector.test.tsx +197 -6
- package/src/ComplexSelector/ComplexSelector.tsx +153 -32
- package/src/ComplexSelector/index.ts +3 -1
- 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/Markdown/parser.test.ts +53 -0
- package/src/Markdown/parser.ts +53 -12
- 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,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file ComplexSelector.tsx
|
|
7
|
-
* @input Uses React, StyleX, Field, usePopover
|
|
8
|
-
* @output Exports
|
|
7
|
+
* @input Uses React, StyleX, Field, Icon slots, Layer positioning, and usePopover
|
|
8
|
+
* @output Exports a rich-selector shell with exact token-sized input and ghost triggers, plus an imperative open/close handle
|
|
9
9
|
* @position Core implementation; consumed by index.ts
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update:
|
|
@@ -13,17 +13,18 @@
|
|
|
13
13
|
* - /packages/core/src/ComplexSelector/ComplexSelector.test.tsx
|
|
14
14
|
* - /packages/core/src/ComplexSelector/index.ts
|
|
15
15
|
* - /apps/storybook/stories/ComplexSelector.stories.tsx
|
|
16
|
+
* - /packages/cli/assets/templates/blocks/components/ComplexSelector/ (showcase blocks)
|
|
16
17
|
*/
|
|
17
|
-
import React, { useCallback, useId, useOptimistic, useTransition } from 'react';
|
|
18
|
+
import React, { useCallback, useId, useImperativeHandle, useOptimistic, useRef, useTransition } from 'react';
|
|
18
19
|
import * as stylex from '@stylexjs/stylex';
|
|
19
20
|
import { Field, inputWrapperStyles } from "../Field/index.js";
|
|
20
|
-
import { Icon } from "../Icon/index.js";
|
|
21
|
+
import { Icon, renderIconSlot } from "../Icon/index.js";
|
|
21
22
|
import { Spinner } from "../Spinner/index.js";
|
|
22
23
|
import { useTranslator } from "../i18n/index.js";
|
|
23
24
|
import { layerAnimations } from "../Layer/layerAnimations.stylex.js";
|
|
24
25
|
import { usePopover } from "../Popover/usePopover.js";
|
|
25
26
|
import "../theme/tokens.stylex.js";
|
|
26
|
-
import { colorVars, durationVars, easeVars, radiusVars, sizeVars, spacingVars, typographyVars, typeScaleVars } from "../theme/tokens.stylex.js";
|
|
27
|
+
import { colorVars, durationVars, easeVars, fontWeightVars, radiusVars, sizeVars, spacingVars, typographyVars, typeScaleVars } from "../theme/tokens.stylex.js";
|
|
27
28
|
import { mergeProps } from "../utils/index.js";
|
|
28
29
|
import { composeEventHandlers } from "../utils/composeEventHandlers.js";
|
|
29
30
|
import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
|
|
@@ -82,6 +83,22 @@ const styles = {
|
|
|
82
83
|
kMwMTN: "xv1l7n4",
|
|
83
84
|
$$css: true
|
|
84
85
|
},
|
|
86
|
+
triggerGhost: {
|
|
87
|
+
kzqmXN: "x14atkfc",
|
|
88
|
+
kMzoRj: "xc342km",
|
|
89
|
+
kWkggS: "xjbqb8w",
|
|
90
|
+
kKwaWg: "x1ilzqfv xq8i9tn",
|
|
91
|
+
kGVxlE: "x1gnnqk1 x1irk71m x15ysqaf",
|
|
92
|
+
k63SB2: "x1e4wzip",
|
|
93
|
+
k1ekBW: "xrafxwg",
|
|
94
|
+
k3aq6I: "x3oybdh xk4oym4",
|
|
95
|
+
$$css: true
|
|
96
|
+
},
|
|
97
|
+
triggerGhostDisabled: {
|
|
98
|
+
kKwaWg: "x18o3ruo",
|
|
99
|
+
k3aq6I: "x1c071of x1pdlv7q",
|
|
100
|
+
$$css: true
|
|
101
|
+
},
|
|
85
102
|
triggerIcon: {
|
|
86
103
|
kmuXW: "x2lah0s",
|
|
87
104
|
$$css: true
|
|
@@ -109,15 +126,15 @@ const styles = {
|
|
|
109
126
|
$$css: true
|
|
110
127
|
},
|
|
111
128
|
sm: {
|
|
112
|
-
|
|
129
|
+
kZKoxP: "x6k0iem",
|
|
113
130
|
$$css: true
|
|
114
131
|
},
|
|
115
132
|
md: {
|
|
116
|
-
|
|
133
|
+
kZKoxP: "x1ueg155",
|
|
117
134
|
$$css: true
|
|
118
135
|
},
|
|
119
136
|
lg: {
|
|
120
|
-
|
|
137
|
+
kZKoxP: "xssyfek",
|
|
121
138
|
$$css: true
|
|
122
139
|
},
|
|
123
140
|
disabled: {
|
|
@@ -125,6 +142,16 @@ const styles = {
|
|
|
125
142
|
$$css: true
|
|
126
143
|
}
|
|
127
144
|
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Imperative control surface for ComplexSelector, accessed via the `handleRef`
|
|
148
|
+
* prop. Methods drive the same popover machinery as the built-in trigger, so
|
|
149
|
+
* they respect focus restoration, light dismiss, and Escape. Prefer these
|
|
150
|
+
* callbacks over mirroring open state in the parent — the selector owns its
|
|
151
|
+
* visibility, and imperative calls avoid the focus-management pitfalls of
|
|
152
|
+
* syncing an external `isOpen` prop.
|
|
153
|
+
*/
|
|
154
|
+
|
|
128
155
|
/**
|
|
129
156
|
* A selector shell for rich, custom selection surfaces.
|
|
130
157
|
*
|
|
@@ -170,8 +197,12 @@ export function ComplexSelector({
|
|
|
170
197
|
statusVariant = 'attached',
|
|
171
198
|
labelTooltip,
|
|
172
199
|
size = 'md',
|
|
200
|
+
variant = 'input',
|
|
201
|
+
startIcon,
|
|
173
202
|
width,
|
|
174
203
|
placement = 'below',
|
|
204
|
+
alignment = 'start',
|
|
205
|
+
handleRef,
|
|
175
206
|
contentXstyle,
|
|
176
207
|
xstyle,
|
|
177
208
|
className,
|
|
@@ -182,28 +213,62 @@ export function ComplexSelector({
|
|
|
182
213
|
}) {
|
|
183
214
|
const t = useTranslator();
|
|
184
215
|
const placeholder = placeholderFromProps ?? t('@astryx.selector.placeholder');
|
|
216
|
+
const effectiveStatusVariant = variant === 'ghost' && statusVariant === 'attached' ? 'detached' : statusVariant;
|
|
185
217
|
const triggerId = useId();
|
|
186
218
|
const labelId = useId();
|
|
187
219
|
const contentId = useId();
|
|
188
220
|
const descriptionId = useId();
|
|
189
221
|
const statusMessageId = useId();
|
|
190
222
|
const ariaDescribedBy = [description ? descriptionId : null, status?.message ? statusMessageId : null].filter(id => id != null).join(' ') || undefined;
|
|
223
|
+
const triggerRef = useRef(null);
|
|
224
|
+
const lastHideTimeRef = useRef(0);
|
|
191
225
|
const [isPending, startTransition] = useTransition();
|
|
192
226
|
const [optimisticValue, setOptimisticValue] = useOptimistic(value);
|
|
193
227
|
const isBusy = isLoading || isPending;
|
|
228
|
+
const handlePopoverHide = useCallback(() => {
|
|
229
|
+
lastHideTimeRef.current = Date.now();
|
|
230
|
+
triggerRef.current?.focus();
|
|
231
|
+
}, []);
|
|
194
232
|
const popover = usePopover({
|
|
195
233
|
dialogLabel: label,
|
|
196
234
|
hasCloseButton: false,
|
|
197
235
|
hasAutoFocus: true,
|
|
198
|
-
// The popup's theme target belongs on the SURFACE — the element painting
|
|
199
|
-
// background, radius and elevation — which `usePopover` owns. Rendered on
|
|
200
|
-
// the content box below it, a theme's background or radius rule paints the
|
|
201
|
-
// wrong box.
|
|
202
236
|
surfaceTarget: 'complex-selector-popup',
|
|
203
|
-
onHide:
|
|
204
|
-
document.getElementById(triggerId)?.focus();
|
|
205
|
-
}
|
|
237
|
+
onHide: handlePopoverHide
|
|
206
238
|
});
|
|
239
|
+
const isOpen = popover.isOpen;
|
|
240
|
+
const handleTriggerClick = useCallback(() => {
|
|
241
|
+
if (isDisabled || Date.now() - lastHideTimeRef.current < 50) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (popover.isOpen) {
|
|
245
|
+
popover.hide();
|
|
246
|
+
} else {
|
|
247
|
+
popover.show();
|
|
248
|
+
}
|
|
249
|
+
}, [isDisabled, popover]);
|
|
250
|
+
const close = useCallback(() => {
|
|
251
|
+
popover.hide();
|
|
252
|
+
}, [popover]);
|
|
253
|
+
useImperativeHandle(handleRef, () => ({
|
|
254
|
+
open: () => {
|
|
255
|
+
if (!isDisabled) {
|
|
256
|
+
popover.show();
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
close: () => popover.hide(),
|
|
260
|
+
toggle: () => {
|
|
261
|
+
if (isDisabled) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (popover.isOpen) {
|
|
265
|
+
popover.hide();
|
|
266
|
+
} else {
|
|
267
|
+
popover.show();
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
isOpen: () => popover.isOpen
|
|
271
|
+
}), [isDisabled, popover]);
|
|
207
272
|
const commitValue = useCallback(nextValue => {
|
|
208
273
|
onChange?.(nextValue);
|
|
209
274
|
if (changeAction) {
|
|
@@ -217,8 +282,8 @@ export function ComplexSelector({
|
|
|
217
282
|
const content = /*#__PURE__*/_jsx("div", {
|
|
218
283
|
id: contentId,
|
|
219
284
|
...stylex.props(styles.content, contentXstyle),
|
|
220
|
-
children: children(optimisticValue, commitValue,
|
|
221
|
-
isOpen
|
|
285
|
+
children: children(optimisticValue, commitValue, close, {
|
|
286
|
+
isOpen,
|
|
222
287
|
isBusy,
|
|
223
288
|
triggerId,
|
|
224
289
|
contentId
|
|
@@ -229,25 +294,21 @@ export function ComplexSelector({
|
|
|
229
294
|
ref: popover.triggerRef,
|
|
230
295
|
"data-testid": testId,
|
|
231
296
|
...props,
|
|
232
|
-
onClick: composeEventHandlers(onClickProp,
|
|
233
|
-
if (!isDisabled) {
|
|
234
|
-
popover.toggle();
|
|
235
|
-
}
|
|
236
|
-
}),
|
|
297
|
+
onClick: composeEventHandlers(onClickProp, handleTriggerClick),
|
|
237
298
|
...mergeProps(themeProps('complex-selector', {
|
|
299
|
+
variant,
|
|
238
300
|
size,
|
|
239
301
|
status: status?.type ?? null
|
|
240
|
-
}), stylex.props(inputWrapperStyles.base, styles.triggerContainer, styles[size],
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
children: [/*#__PURE__*/_jsx("button", {
|
|
302
|
+
}), stylex.props(inputWrapperStyles.base, styles.triggerContainer, styles[size], variant === 'input' && focusOutlineStyles.focusWithin, variant === 'ghost' && styles.triggerGhost, variant === 'ghost' && focusOutlineStyles.focusWithin, isDisabled && inputWrapperStyles.disabled, variant === 'ghost' && isDisabled && styles.triggerGhostDisabled, isDisabled && styles.disabled, triggerLabel == null && styles.placeholder, xstyle), className, style),
|
|
303
|
+
children: [startIcon && renderIconSlot(startIcon, {
|
|
304
|
+
size: 'sm',
|
|
305
|
+
color: 'secondary'
|
|
306
|
+
}), /*#__PURE__*/_jsx("button", {
|
|
307
|
+
ref: triggerRef,
|
|
247
308
|
id: triggerId,
|
|
248
309
|
type: "button",
|
|
249
310
|
"aria-haspopup": "dialog",
|
|
250
|
-
"aria-expanded":
|
|
311
|
+
"aria-expanded": isOpen,
|
|
251
312
|
"aria-controls": contentId,
|
|
252
313
|
"aria-describedby": ariaDescribedBy,
|
|
253
314
|
"aria-labelledby": labelId,
|
|
@@ -256,7 +317,7 @@ export function ComplexSelector({
|
|
|
256
317
|
"aria-busy": isBusy || undefined,
|
|
257
318
|
disabled: isDisabled,
|
|
258
319
|
onKeyDown: event => {
|
|
259
|
-
if (event.key === 'ArrowDown' && !
|
|
320
|
+
if (event.key === 'ArrowDown' && !isOpen && !isDisabled) {
|
|
260
321
|
event.preventDefault();
|
|
261
322
|
popover.show();
|
|
262
323
|
}
|
|
@@ -281,14 +342,14 @@ export function ComplexSelector({
|
|
|
281
342
|
// IS the trigger's icon element — one node carrying the box, the
|
|
282
343
|
// color, the rotation, and the theme target.
|
|
283
344
|
,
|
|
284
|
-
xstyle: [styles.triggerIcon, styles.triggerIconRotation,
|
|
345
|
+
xstyle: [styles.triggerIcon, styles.triggerIconRotation, isOpen && styles.triggerIconOpen],
|
|
285
346
|
...themeProps('complex-selector-indicator-icon', {
|
|
286
|
-
state:
|
|
347
|
+
state: isOpen ? 'expanded' : 'collapsed'
|
|
287
348
|
})
|
|
288
349
|
})]
|
|
289
350
|
}), popover.render(content, {
|
|
290
351
|
placement,
|
|
291
|
-
alignment
|
|
352
|
+
alignment,
|
|
292
353
|
offset: spacingVars['--spacing-1'],
|
|
293
354
|
xstyle: [styles.popover, layerAnimations[placement]]
|
|
294
355
|
})]
|
|
@@ -308,7 +369,7 @@ export function ComplexSelector({
|
|
|
308
369
|
message: status.message,
|
|
309
370
|
messageID: status.message ? statusMessageId : undefined
|
|
310
371
|
} : undefined,
|
|
311
|
-
statusVariant:
|
|
372
|
+
statusVariant: effectiveStatusVariant,
|
|
312
373
|
labelTooltip: labelTooltip,
|
|
313
374
|
width: width,
|
|
314
375
|
children: selectorContent
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file index.ts
|
|
3
|
-
* @output Exports ComplexSelector and types
|
|
3
|
+
* @output Exports ComplexSelector and its trigger-size contract types
|
|
4
4
|
* @position Public API entry point
|
|
5
5
|
*/
|
|
6
|
-
export { ComplexSelector, type ComplexSelectorProps, type ComplexSelectorRenderState, type ComplexSelectorSize, type ComplexSelectorStatus, } from './ComplexSelector';
|
|
6
|
+
export { ComplexSelector, type ComplexSelectorHandle, type ComplexSelectorProps, type ComplexSelectorRenderState, type ComplexSelectorSize, type ComplexSelectorStatus, type ComplexSelectorVariant, } from './ComplexSelector';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ComplexSelector/index.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ComplexSelector/index.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimeInput.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/DateTimeInput.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"DateTimeInput.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/DateTimeInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -287,10 +287,10 @@ export function DateTimeInput({
|
|
|
287
287
|
}, [timePendingInput, hasSeconds, timeMin, timeMax]);
|
|
288
288
|
const resolvedTimePlaceholder = useMemo(() => {
|
|
289
289
|
if (isTimeFocused && !timeDisplayValue) {
|
|
290
|
-
return hourFormat === '12h' ? '
|
|
290
|
+
return hourFormat === '12h' ? t('@astryx.dateTimeInput.timeHint12h') : t('@astryx.dateTimeInput.timeHint24h');
|
|
291
291
|
}
|
|
292
292
|
return timePlaceholder;
|
|
293
|
-
}, [isTimeFocused, timeDisplayValue, hourFormat, timePlaceholder]);
|
|
293
|
+
}, [isTimeFocused, timeDisplayValue, hourFormat, timePlaceholder, t]);
|
|
294
294
|
|
|
295
295
|
// --- Unified change handler ---
|
|
296
296
|
const fireChange = useCallback(newValue => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMenuSubMenu.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenuSubMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAc,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAoB5D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAqF5C,UAAU,4BAA6B,SAAQ,IAAI,CACjD,SAAS,EACT,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC,2DAA2D;IAC3D,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,8CAA8C;IAC9C,KAAK,EAAE,SAAS,CAAC;IACjB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,8CAA8C;IAC9C,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,wBAAyB,SAAQ,4BAA4B;IAC5E;;;;;;;;OAQG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,SAAS,
|
|
1
|
+
{"version":3,"file":"DropdownMenuSubMenu.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenuSubMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAc,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAoB5D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAqF5C,UAAU,4BAA6B,SAAQ,IAAI,CACjD,SAAS,EACT,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC,2DAA2D;IAC3D,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,8CAA8C;IAC9C,KAAK,EAAE,SAAS,CAAC;IACjB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,8CAA8C;IAC9C,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,wBAAyB,SAAQ,4BAA4B;IAC5E;;;;;;;;OAQG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,SAAS,CAwVX;yBA1Ve,mBAAmB"}
|
|
@@ -198,9 +198,13 @@ export function DropdownMenuSubMenu(props) {
|
|
|
198
198
|
|
|
199
199
|
// Hover-intent: entering the trigger opens after a short delay; leaving
|
|
200
200
|
// either surface closes after a delay. Hover-open does not steal focus.
|
|
201
|
+
// Hover intent and the shared hover→click guard only: this level owns its own
|
|
202
|
+
// click handling, roving focus and typeahead. popover="manual", so the
|
|
203
|
+
// invoker wiring other consumers need does not apply.
|
|
201
204
|
const {
|
|
202
205
|
triggerProps,
|
|
203
|
-
contentProps
|
|
206
|
+
contentProps,
|
|
207
|
+
confirmHoverOpen
|
|
204
208
|
} = useMenuHover({
|
|
205
209
|
show: showLayer,
|
|
206
210
|
hide: hideLayer,
|
|
@@ -213,18 +217,12 @@ export function DropdownMenuSubMenu(props) {
|
|
|
213
217
|
}
|
|
214
218
|
layer.show();
|
|
215
219
|
if (options?.focusFirst) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
// arrow keys rove the parent while the empty flyout stays open.
|
|
223
|
-
const focusedItem = focusFirst();
|
|
224
|
-
if (!focusedItem) {
|
|
225
|
-
menuRef.current?.focus();
|
|
226
|
-
}
|
|
227
|
-
});
|
|
220
|
+
// Synchronous by design — see the focus note in useMenuHover. A
|
|
221
|
+
// still-loading flyout has no focusable item, so fall back to the
|
|
222
|
+
// container: keyboard ownership must leave the parent list either way.
|
|
223
|
+
if (!focusFirst()) {
|
|
224
|
+
menuRef.current?.focus();
|
|
225
|
+
}
|
|
228
226
|
}
|
|
229
227
|
}, [canOpen, layer, focusFirst, menuRef]);
|
|
230
228
|
const close = useCallback(options => {
|
|
@@ -244,8 +242,14 @@ export function DropdownMenuSubMenu(props) {
|
|
|
244
242
|
if (isDisabled) {
|
|
245
243
|
return;
|
|
246
244
|
}
|
|
247
|
-
//
|
|
245
|
+
// Toggles, except for the click that follows a hover-open (#3121).
|
|
248
246
|
if (isOpen) {
|
|
247
|
+
if (confirmHoverOpen()) {
|
|
248
|
+
if (!focusFirst()) {
|
|
249
|
+
menuRef.current?.focus();
|
|
250
|
+
}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
249
253
|
close({
|
|
250
254
|
focusTrigger: true
|
|
251
255
|
});
|
|
@@ -254,7 +258,7 @@ export function DropdownMenuSubMenu(props) {
|
|
|
254
258
|
focusFirst: true
|
|
255
259
|
});
|
|
256
260
|
}
|
|
257
|
-
}, [isDisabled, isOpen, open, close]);
|
|
261
|
+
}, [isDisabled, isOpen, open, close, confirmHoverOpen, focusFirst, menuRef]);
|
|
258
262
|
const handleTriggerKeyDown = useCallback(e => {
|
|
259
263
|
if (isDisabled) {
|
|
260
264
|
return;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @file HoverCard.tsx
|
|
3
3
|
* @input Uses React, useHoverCard hook
|
|
4
4
|
* @output Exports HoverCard component for hover/focus triggered layers
|
|
5
|
-
* @position Layer component;
|
|
5
|
+
* @position Layer component; inline-safe trigger wrapper, floating layer hosted by useLayer
|
|
6
6
|
*
|
|
7
7
|
* SYNC: When modified, update these files to stay in sync:
|
|
8
8
|
* - /packages/core/src/HoverCard/HoverCard.test.tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HoverCard.d.ts","sourceRoot":"","sources":["../../src/HoverCard/HoverCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAsB,KAAK,YAAY,EAAE,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG7E,OAAO,EAAe,KAAK,qBAAqB,EAAC,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAC,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,YAAY,EAAC,qBAAqB,EAAC,MAAM,gBAAgB,CAAC;AAiB1D,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,EACT,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IAErC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAEtC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAiBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,OAAO,EACP,SAAmB,EACnB,SAAoB,EACpB,KAAW,EACX,SAAe,EACf,YAAqB,EACrB,SAAgB,EAChB,KAAK,EACL,YAAY,EACZ,kBAA2B,EAC3B,MAAM,EACN,aAAa,EACb,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,cAAc,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"HoverCard.d.ts","sourceRoot":"","sources":["../../src/HoverCard/HoverCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAsB,KAAK,YAAY,EAAE,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG7E,OAAO,EAAe,KAAK,qBAAqB,EAAC,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAC,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,YAAY,EAAC,qBAAqB,EAAC,MAAM,gBAAgB,CAAC;AAiB1D,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,EACT,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IAErC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAEtC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAiBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,OAAO,EACP,SAAmB,EACnB,SAAoB,EACpB,KAAW,EACX,SAAe,EACf,YAAqB,EACrB,SAAgB,EAChB,KAAK,EACL,YAAY,EACZ,kBAA2B,EAC3B,MAAM,EACN,aAAa,EACb,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,cAAc,GAAG,YAAY,CAyG/B;yBA1He,SAAS"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @file HoverCard.tsx
|
|
7
7
|
* @input Uses React, useHoverCard hook
|
|
8
8
|
* @output Exports HoverCard component for hover/focus triggered layers
|
|
9
|
-
* @position Layer component;
|
|
9
|
+
* @position Layer component; inline-safe trigger wrapper, floating layer hosted by useLayer
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update these files to stay in sync:
|
|
12
12
|
* - /packages/core/src/HoverCard/HoverCard.test.tsx
|
|
@@ -127,18 +127,10 @@ export function HoverCard({
|
|
|
127
127
|
};
|
|
128
128
|
}, [textOnly, hoverCard.ref, hoverCard.describedBy]);
|
|
129
129
|
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
// anchor positioning resolves the trigger reference regardless of where the
|
|
135
|
-
// element sits in the DOM, so no portal is needed to "escape" layout.
|
|
136
|
-
//
|
|
137
|
-
// The layer renders as inline-safe phrasing markup (a `<span>`, see
|
|
138
|
-
// useHoverCard), which stays put inside a `<p>` instead of being reparented
|
|
139
|
-
// by the HTML parser. That keeps the server markup and the first client
|
|
140
|
-
// render identical, so there is no hydration mismatch — and it preserves the
|
|
141
|
-
// inline-safety guarantee (no block elements injected into a paragraph).
|
|
130
|
+
// While closed, useLayer leaves only an inert <template> marker at this JSX
|
|
131
|
+
// position. When the card needs to open, it uses that marker to keep the
|
|
132
|
+
// final layer inline when the parent is safe or portal it outside a <p>,
|
|
133
|
+
// link, or other ancestor that cannot contain it safely.
|
|
142
134
|
const renderedHoverCard = hoverCard.renderHoverCard(content, {
|
|
143
135
|
xstyle,
|
|
144
136
|
className,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHoverCard.d.ts","sourceRoot":"","sources":["../../src/HoverCard/useHoverCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,OAAO,CAAC;AAEf,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"useHoverCard.d.ts","sourceRoot":"","sources":["../../src/HoverCard/useHoverCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,OAAO,CAAC;AAEf,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AA4B3B;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IAErC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,GAAG,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAE9B;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAEtC;;;;OAIG;IACH,cAAc,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAEzC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;;;;OAOG;IACH,eAAe,EAAE,CACf,QAAQ,EAAE,SAAS,EACnB,KAAK,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,KAC5C,SAAS,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAyBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAkT5E"}
|
|
@@ -88,6 +88,7 @@ export function useHoverCard(options = {}) {
|
|
|
88
88
|
} = options;
|
|
89
89
|
const layer = useLayer({
|
|
90
90
|
mode: 'context',
|
|
91
|
+
lazyMount: true,
|
|
91
92
|
onShow,
|
|
92
93
|
onHide
|
|
93
94
|
});
|
|
@@ -254,15 +255,15 @@ export function useHoverCard(options = {}) {
|
|
|
254
255
|
// Consumer surface style props land on the layer container — the
|
|
255
256
|
// themed surface (bg/radius/shadow) where the theme class lives — so
|
|
256
257
|
// customizing the card targets the same element as the theme. The inner
|
|
257
|
-
//
|
|
258
|
+
// div keeps `styles.content` for padding.
|
|
258
259
|
xstyle: [popoverXstyle, layerAnimations[renderPlacement], props?.xstyle],
|
|
259
260
|
className: props?.className ? `${themeClassName} ${props.className}` : themeClassName,
|
|
260
261
|
style: props?.style,
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
as: '
|
|
262
|
+
// useLayer mounts only after it has verified or corrected the parent,
|
|
263
|
+
// so rich HoverCard content can use block-safe markup.
|
|
264
|
+
as: 'div'
|
|
264
265
|
};
|
|
265
|
-
return layer.render(/*#__PURE__*/_jsx("
|
|
266
|
+
return layer.render(/*#__PURE__*/_jsx("div", {
|
|
266
267
|
...{
|
|
267
268
|
className: "x1lliihq x1vlblms xvmdzux x126nfab x1t818jl"
|
|
268
269
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groupStyles.d.ts","sourceRoot":"","sources":["../../src/InputGroup/groupStyles.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"groupStyles.d.ts","sourceRoot":"","sources":["../../src/InputGroup/groupStyles.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAQ3C,eAAO,MAAM,WAAW;;;;;;;;;;;;;;EA6BtB,CAAC"}
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
import * as stylex from '@stylexjs/stylex';
|
|
11
11
|
import "../theme/tokens.stylex.js";
|
|
12
12
|
import { radiusVars, borderVars } from "../theme/tokens.stylex.js";
|
|
13
|
+
|
|
14
|
+
// A grouped control may be followed by context-layer infrastructure rather
|
|
15
|
+
// than another control. Neither the inert marker nor the popover is a visual
|
|
16
|
+
// group member, so skip both when finding the trailing edge.
|
|
17
|
+
const IS_LAST_ITEM = ':not(:has(~ *:not([popover]):not(template)))';
|
|
13
18
|
export const groupStyles = {
|
|
14
19
|
inGroup: {
|
|
15
20
|
kUk6DE: "x98rzlu",
|
|
@@ -18,8 +23,8 @@ export const groupStyles = {
|
|
|
18
23
|
keTefX: "xd10s4z x1pwwqoy",
|
|
19
24
|
krdFHd: "x15mokao x8eehn2",
|
|
20
25
|
kVL7Gh: "xbiv7yw x1xrp5p4",
|
|
21
|
-
kfmiAY: "x1ga7v0g
|
|
22
|
-
kT0f0o: "x16uus16
|
|
26
|
+
kfmiAY: "x1ga7v0g x1tzxhge",
|
|
27
|
+
kT0f0o: "x16uus16 x1rmb4wm",
|
|
23
28
|
kXnDq0: "x1rm9qnc",
|
|
24
29
|
$$css: true
|
|
25
30
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return the corrective portal target for a layer's intended inline parent.
|
|
3
|
+
*
|
|
4
|
+
* A null result means the inline parent and all of its ancestors are safe, so
|
|
5
|
+
* the layer should stay at its JSX position. Otherwise the result is the
|
|
6
|
+
* nearest element outside every unsafe ancestor around that position.
|
|
7
|
+
*
|
|
8
|
+
* Walking up from the actual render position (rather than the trigger, or
|
|
9
|
+
* portaling to `document.body`) keeps the two things a layer inherits there:
|
|
10
|
+
*
|
|
11
|
+
* - **Theme.** Theme scopes live on DOM ancestors. Staying as close as
|
|
12
|
+
* possible to the intended render position preserves their component rules
|
|
13
|
+
* and custom properties; `document.body` may sit outside a nested scope.
|
|
14
|
+
* - **Tab order.** Sequential focus follows DOM order, so a host near the
|
|
15
|
+
* trigger keeps the layer's focusables next to it. (`show()` also passes
|
|
16
|
+
* the trigger as the popover's invoker `source`, which pins focus order to
|
|
17
|
+
* the invoker in browsers that support it.)
|
|
18
|
+
*
|
|
19
|
+
* The outermost unsafe ancestor matters. A safe div may itself sit inside an
|
|
20
|
+
* anchor; stopping at that div would still put the layer's buttons inside the
|
|
21
|
+
* link. Walking the whole chain ensures the target is outside both.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveLayerPortalTarget(inlineParent: HTMLElement | null): HTMLElement | null;
|
|
24
|
+
//# sourceMappingURL=layerHost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layerHost.d.ts","sourceRoot":"","sources":["../../src/Layer/layerHost.ts"],"names":[],"mappings":"AAqGA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,WAAW,GAAG,IAAI,GAC/B,WAAW,GAAG,IAAI,CAepB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file layerHost.ts
|
|
5
|
+
* @input Uses the layer's intended inline parent element
|
|
6
|
+
* @output Exports resolveLayerPortalTarget, the corrective portal target
|
|
7
|
+
* @position Layer utility; used by useLayer to place the popover in the DOM
|
|
8
|
+
*
|
|
9
|
+
* SYNC: When modified, update:
|
|
10
|
+
* - /packages/core/src/Layer/layerHost.test.ts
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Ancestors a layer must not be hosted inside.
|
|
15
|
+
*
|
|
16
|
+
* Two overlapping reasons, both verified in Chrome:
|
|
17
|
+
*
|
|
18
|
+
* 1. The HTML parser owns server markup. `<p>` and the heading-ish elements
|
|
19
|
+
* take phrasing content only, so a block element inside one makes the
|
|
20
|
+
* parser close the paragraph and reparent the rest — the layer's content
|
|
21
|
+
* ends up in the page instead of the popover. A nested `<a>` triggers the
|
|
22
|
+
* same tearing through the adoption agency algorithm.
|
|
23
|
+
* 2. Interactive ancestors capture the layer's own interactions. A card
|
|
24
|
+
* hosted inside an `<a>` or `<button>` puts its links and buttons inside
|
|
25
|
+
* that control: clicking one navigates the wrapping link, and every
|
|
26
|
+
* focusable in the card joins the control's own tab stop.
|
|
27
|
+
*
|
|
28
|
+
* Inline formatting elements are on the list for a third, milder reason: a
|
|
29
|
+
* layer hosted in one inherits its typography (font-size, text-align), so a
|
|
30
|
+
* card in a 13px centered paragraph renders 13px and centered.
|
|
31
|
+
*/
|
|
32
|
+
const UNSAFE_HOSTS = new Set([
|
|
33
|
+
// Phrasing-content-only containers
|
|
34
|
+
'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'dt', 'pre', 'legend', 'data', 'dfn', 'meter', 'output', 'progress', 'option', 'optgroup',
|
|
35
|
+
// Structural containers whose direct children are restricted. An inert
|
|
36
|
+
// <template> marker is valid script-supporting content in these positions,
|
|
37
|
+
// but the eventual div/span layer is not.
|
|
38
|
+
'table', 'thead', 'tbody', 'tfoot', 'tr', 'colgroup', 'ul', 'ol', 'menu', 'dl', 'select', 'datalist', 'picture', 'hgroup', 'ruby', 'rt', 'rp',
|
|
39
|
+
// Interactive containers
|
|
40
|
+
'a', 'button', 'label', 'summary',
|
|
41
|
+
// Inline formatting context
|
|
42
|
+
'span', 'em', 'strong', 'b', 'i', 'u', 's', 'small', 'mark', 'code', 'kbd', 'samp', 'var', 'sub', 'sup', 'abbr', 'cite', 'q', 'time', 'bdi', 'bdo', 'ins', 'del']);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Return the corrective portal target for a layer's intended inline parent.
|
|
46
|
+
*
|
|
47
|
+
* A null result means the inline parent and all of its ancestors are safe, so
|
|
48
|
+
* the layer should stay at its JSX position. Otherwise the result is the
|
|
49
|
+
* nearest element outside every unsafe ancestor around that position.
|
|
50
|
+
*
|
|
51
|
+
* Walking up from the actual render position (rather than the trigger, or
|
|
52
|
+
* portaling to `document.body`) keeps the two things a layer inherits there:
|
|
53
|
+
*
|
|
54
|
+
* - **Theme.** Theme scopes live on DOM ancestors. Staying as close as
|
|
55
|
+
* possible to the intended render position preserves their component rules
|
|
56
|
+
* and custom properties; `document.body` may sit outside a nested scope.
|
|
57
|
+
* - **Tab order.** Sequential focus follows DOM order, so a host near the
|
|
58
|
+
* trigger keeps the layer's focusables next to it. (`show()` also passes
|
|
59
|
+
* the trigger as the popover's invoker `source`, which pins focus order to
|
|
60
|
+
* the invoker in browsers that support it.)
|
|
61
|
+
*
|
|
62
|
+
* The outermost unsafe ancestor matters. A safe div may itself sit inside an
|
|
63
|
+
* anchor; stopping at that div would still put the layer's buttons inside the
|
|
64
|
+
* link. Walking the whole chain ensures the target is outside both.
|
|
65
|
+
*/
|
|
66
|
+
export function resolveLayerPortalTarget(inlineParent) {
|
|
67
|
+
if (!inlineParent) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
let outermostUnsafe = null;
|
|
71
|
+
let node = inlineParent;
|
|
72
|
+
while (node) {
|
|
73
|
+
if (UNSAFE_HOSTS.has(node.tagName.toLowerCase())) {
|
|
74
|
+
outermostUnsafe = node;
|
|
75
|
+
}
|
|
76
|
+
node = node.parentElement;
|
|
77
|
+
}
|
|
78
|
+
return outermostUnsafe?.parentElement ?? null;
|
|
79
|
+
}
|