@proyecto-viviana/solidaria-components 0.3.2 → 0.4.1
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/ActionBar.d.ts.map +1 -1
- package/dist/ActionBar.js +175 -0
- package/dist/ActionBar.js.map +1 -0
- package/dist/ActionBar.jsx +119 -0
- package/dist/ActionBar.jsx.map +1 -0
- package/dist/ActionGroup.d.ts.map +1 -1
- package/dist/ActionGroup.js +179 -0
- package/dist/ActionGroup.js.map +1 -0
- package/dist/ActionGroup.jsx +129 -0
- package/dist/ActionGroup.jsx.map +1 -0
- package/dist/Alert.js +111 -0
- package/dist/Alert.js.map +1 -0
- package/dist/Alert.jsx +82 -0
- package/dist/Alert.jsx.map +1 -0
- package/dist/Autocomplete.d.ts +2 -2
- package/dist/Autocomplete.d.ts.map +1 -1
- package/dist/Autocomplete.js +130 -0
- package/dist/Autocomplete.js.map +1 -0
- package/dist/Autocomplete.jsx +116 -0
- package/dist/Autocomplete.jsx.map +1 -0
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs.js +333 -0
- package/dist/Breadcrumbs.js.map +1 -0
- package/dist/Breadcrumbs.jsx +261 -0
- package/dist/Breadcrumbs.jsx.map +1 -0
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +348 -0
- package/dist/Button.js.map +1 -0
- package/dist/Button.jsx +314 -0
- package/dist/Button.jsx.map +1 -0
- package/dist/Calendar.d.ts +4 -4
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Calendar.js +573 -0
- package/dist/Calendar.js.map +1 -0
- package/dist/Calendar.jsx +342 -0
- package/dist/Calendar.jsx.map +1 -0
- package/dist/CalendarPicker.d.ts +33 -0
- package/dist/CalendarPicker.d.ts.map +1 -0
- package/dist/CalendarPicker.js +44 -0
- package/dist/CalendarPicker.js.map +1 -0
- package/dist/CalendarPicker.jsx +44 -0
- package/dist/CalendarPicker.jsx.map +1 -0
- package/dist/Checkbox.d.ts +83 -4
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +923 -0
- package/dist/Checkbox.js.map +1 -0
- package/dist/Checkbox.jsx +707 -0
- package/dist/Checkbox.jsx.map +1 -0
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +202 -0
- package/dist/Collection.js.map +1 -0
- package/dist/Collection.jsx +152 -0
- package/dist/Collection.jsx.map +1 -0
- package/dist/Color.d.ts.map +1 -1
- package/dist/Color.js +1717 -0
- package/dist/Color.js.map +1 -0
- package/dist/Color.jsx +1340 -0
- package/dist/Color.jsx.map +1 -0
- package/dist/ColorEditor.js +208 -0
- package/dist/ColorEditor.js.map +1 -0
- package/dist/ColorEditor.jsx +120 -0
- package/dist/ColorEditor.jsx.map +1 -0
- package/dist/ComboBox.d.ts +8 -4
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ComboBox.js +1000 -0
- package/dist/ComboBox.js.map +1 -0
- package/dist/ComboBox.jsx +724 -0
- package/dist/ComboBox.jsx.map +1 -0
- package/dist/ContextualHelpTrigger.js +146 -0
- package/dist/ContextualHelpTrigger.js.map +1 -0
- package/dist/ContextualHelpTrigger.jsx +109 -0
- package/dist/ContextualHelpTrigger.jsx.map +1 -0
- package/dist/DateField.d.ts +14 -5
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DateField.js +4 -0
- package/dist/DateField.jsx +4 -0
- package/dist/DateField2.js +502 -0
- package/dist/DateField2.js.map +1 -0
- package/dist/DateField2.jsx +354 -0
- package/dist/DateField2.jsx.map +1 -0
- package/dist/DatePicker.d.ts +46 -7
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DatePicker.js +7 -0
- package/dist/DatePicker.jsx +7 -0
- package/dist/DatePicker2.js +1171 -0
- package/dist/DatePicker2.js.map +1 -0
- package/dist/DatePicker2.jsx +820 -0
- package/dist/DatePicker2.jsx.map +1 -0
- package/dist/DateRangePickerContext.d.ts +2 -0
- package/dist/DateRangePickerContext.d.ts.map +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +337 -0
- package/dist/Dialog.js.map +1 -0
- package/dist/Dialog.jsx +192 -0
- package/dist/Dialog.jsx.map +1 -0
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/Disclosure.js +331 -0
- package/dist/Disclosure.js.map +1 -0
- package/dist/Disclosure.jsx +230 -0
- package/dist/Disclosure.jsx.map +1 -0
- package/dist/DragAndDrop.d.ts.map +1 -1
- package/dist/DragAndDrop.js +176 -0
- package/dist/DragAndDrop.js.map +1 -0
- package/dist/DragAndDrop.jsx +160 -0
- package/dist/DragAndDrop.jsx.map +1 -0
- package/dist/DropZone.d.ts.map +1 -1
- package/dist/DropZone.js +189 -0
- package/dist/DropZone.js.map +1 -0
- package/dist/DropZone.jsx +144 -0
- package/dist/DropZone.jsx.map +1 -0
- package/dist/FieldError.js +66 -0
- package/dist/FieldError.js.map +1 -0
- package/dist/FieldError.jsx +47 -0
- package/dist/FieldError.jsx.map +1 -0
- package/dist/FileTrigger.js +79 -0
- package/dist/FileTrigger.js.map +1 -0
- package/dist/FileTrigger.jsx +49 -0
- package/dist/FileTrigger.jsx.map +1 -0
- package/dist/Focusable.js +70 -0
- package/dist/Focusable.js.map +1 -0
- package/dist/Focusable.jsx +69 -0
- package/dist/Focusable.jsx.map +1 -0
- package/dist/Form.js +99 -0
- package/dist/Form.js.map +1 -0
- package/dist/Form.jsx +73 -0
- package/dist/Form.jsx.map +1 -0
- package/dist/GridList.d.ts +34 -2
- package/dist/GridList.d.ts.map +1 -1
- package/dist/GridList.js +723 -0
- package/dist/GridList.js.map +1 -0
- package/dist/GridList.jsx +552 -0
- package/dist/GridList.jsx.map +1 -0
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Icon.js +127 -0
- package/dist/Icon.js.map +1 -0
- package/dist/Icon.jsx +72 -0
- package/dist/Icon.jsx.map +1 -0
- package/dist/Keyboard.js +30 -0
- package/dist/Keyboard.js.map +1 -0
- package/dist/Keyboard.jsx +24 -0
- package/dist/Keyboard.jsx.map +1 -0
- package/dist/Landmark.js +134 -0
- package/dist/Landmark.js.map +1 -0
- package/dist/Landmark.jsx +118 -0
- package/dist/Landmark.jsx.map +1 -0
- package/dist/Link.d.ts.map +1 -1
- package/dist/Link.js +219 -0
- package/dist/Link.js.map +1 -0
- package/dist/Link.jsx +189 -0
- package/dist/Link.jsx.map +1 -0
- package/dist/ListBox.d.ts +2 -2
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListBox.js +831 -0
- package/dist/ListBox.js.map +1 -0
- package/dist/ListBox.jsx +644 -0
- package/dist/ListBox.jsx.map +1 -0
- package/dist/Menu.d.ts +27 -9
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Menu.js +1254 -0
- package/dist/Menu.js.map +1 -0
- package/dist/Menu.jsx +1042 -0
- package/dist/Menu.jsx.map +1 -0
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Meter.js +123 -0
- package/dist/Meter.js.map +1 -0
- package/dist/Meter.jsx +107 -0
- package/dist/Meter.jsx.map +1 -0
- package/dist/Modal.d.ts.map +1 -1
- package/dist/Modal.js +382 -0
- package/dist/Modal.js.map +1 -0
- package/dist/Modal.jsx +314 -0
- package/dist/Modal.jsx.map +1 -0
- package/dist/NumberField.d.ts +3 -3
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/NumberField.js +573 -0
- package/dist/NumberField.js.map +1 -0
- package/dist/NumberField.jsx +443 -0
- package/dist/NumberField.jsx.map +1 -0
- package/dist/Popover.d.ts +10 -2
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Popover.js +471 -0
- package/dist/Popover.js.map +1 -0
- package/dist/Popover.jsx +354 -0
- package/dist/Popover.jsx.map +1 -0
- package/dist/Pressable.js +69 -0
- package/dist/Pressable.js.map +1 -0
- package/dist/Pressable.jsx +68 -0
- package/dist/Pressable.jsx.map +1 -0
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar.js +130 -0
- package/dist/ProgressBar.js.map +1 -0
- package/dist/ProgressBar.jsx +114 -0
- package/dist/ProgressBar.jsx.map +1 -0
- package/dist/RadioGroup.d.ts +82 -4
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +931 -0
- package/dist/RadioGroup.js.map +1 -0
- package/dist/RadioGroup.jsx +681 -0
- package/dist/RadioGroup.jsx.map +1 -0
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RangeCalendar.js +546 -0
- package/dist/RangeCalendar.js.map +1 -0
- package/dist/RangeCalendar.jsx +323 -0
- package/dist/RangeCalendar.jsx.map +1 -0
- package/dist/RouterProvider.js +118 -0
- package/dist/RouterProvider.js.map +1 -0
- package/dist/RouterProvider.jsx +112 -0
- package/dist/RouterProvider.jsx.map +1 -0
- package/dist/SearchField.d.ts +2 -2
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/SearchField.js +667 -0
- package/dist/SearchField.js.map +1 -0
- package/dist/SearchField.jsx +550 -0
- package/dist/SearchField.jsx.map +1 -0
- package/dist/Select.d.ts +7 -0
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +1044 -0
- package/dist/Select.js.map +1 -0
- package/dist/Select.jsx +759 -0
- package/dist/Select.jsx.map +1 -0
- package/dist/SelectionIndicator.d.ts.map +1 -1
- package/dist/SelectionIndicator.js +86 -0
- package/dist/SelectionIndicator.js.map +1 -0
- package/dist/SelectionIndicator.jsx +50 -0
- package/dist/SelectionIndicator.jsx.map +1 -0
- package/dist/Separator.js +97 -0
- package/dist/Separator.js.map +1 -0
- package/dist/Separator.jsx +85 -0
- package/dist/Separator.jsx.map +1 -0
- package/dist/SharedElementTransition.d.ts.map +1 -1
- package/dist/SharedElementTransition.js +167 -0
- package/dist/SharedElementTransition.js.map +1 -0
- package/dist/SharedElementTransition.jsx +140 -0
- package/dist/SharedElementTransition.jsx.map +1 -0
- package/dist/Slider.d.ts +33 -1
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Slider.js +515 -0
- package/dist/Slider.js.map +1 -0
- package/dist/Slider.jsx +403 -0
- package/dist/Slider.jsx.map +1 -0
- package/dist/StepList.d.ts.map +1 -1
- package/dist/StepList.js +191 -0
- package/dist/StepList.js.map +1 -0
- package/dist/StepList.jsx +136 -0
- package/dist/StepList.jsx.map +1 -0
- package/dist/Switch.d.ts +65 -2
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Switch.js +534 -0
- package/dist/Switch.js.map +1 -0
- package/dist/Switch.jsx +393 -0
- package/dist/Switch.jsx.map +1 -0
- package/dist/Table.d.ts +50 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +1766 -0
- package/dist/Table.js.map +1 -0
- package/dist/Table.jsx +1355 -0
- package/dist/Table.jsx.map +1 -0
- package/dist/Tabs.d.ts +0 -4
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/Tabs.js +598 -0
- package/dist/Tabs.js.map +1 -0
- package/dist/Tabs.jsx +367 -0
- package/dist/Tabs.jsx.map +1 -0
- package/dist/TagGroup.d.ts +3 -1
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/TagGroup.js +382 -0
- package/dist/TagGroup.js.map +1 -0
- package/dist/TagGroup.jsx +273 -0
- package/dist/TagGroup.jsx.map +1 -0
- package/dist/Text.d.ts +18 -6
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +42 -0
- package/dist/Text.js.map +1 -0
- package/dist/Text.jsx +35 -0
- package/dist/Text.jsx.map +1 -0
- package/dist/TextField.d.ts +6 -6
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TextField.js +439 -0
- package/dist/TextField.js.map +1 -0
- package/dist/TextField.jsx +406 -0
- package/dist/TextField.jsx.map +1 -0
- package/dist/TimeField.d.ts +17 -53
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/TimeField.js +278 -0
- package/dist/TimeField.js.map +1 -0
- package/dist/TimeField.jsx +218 -0
- package/dist/TimeField.jsx.map +1 -0
- package/dist/Toast.d.ts +14 -0
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toast.js +551 -0
- package/dist/Toast.js.map +1 -0
- package/dist/Toast.jsx +361 -0
- package/dist/Toast.jsx.map +1 -0
- package/dist/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton.js +123 -0
- package/dist/ToggleButton.js.map +1 -0
- package/dist/ToggleButton.jsx +88 -0
- package/dist/ToggleButton.jsx.map +1 -0
- package/dist/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButtonGroup.js +114 -0
- package/dist/ToggleButtonGroup.js.map +1 -0
- package/dist/ToggleButtonGroup.jsx +85 -0
- package/dist/ToggleButtonGroup.jsx.map +1 -0
- package/dist/Toolbar.js +112 -0
- package/dist/Toolbar.js.map +1 -0
- package/dist/Toolbar.jsx +92 -0
- package/dist/Toolbar.jsx.map +1 -0
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip.js +539 -0
- package/dist/Tooltip.js.map +1 -0
- package/dist/Tooltip.jsx +465 -0
- package/dist/Tooltip.jsx.map +1 -0
- package/dist/Tree.d.ts +14 -2
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Tree.js +1424 -0
- package/dist/Tree.js.map +1 -0
- package/dist/Tree.jsx +1172 -0
- package/dist/Tree.jsx.map +1 -0
- package/dist/Virtualizer.d.ts +16 -2
- package/dist/Virtualizer.d.ts.map +1 -1
- package/dist/Virtualizer.js +2 -0
- package/dist/Virtualizer.jsx +2 -0
- package/dist/Virtualizer2.js +751 -0
- package/dist/Virtualizer2.js.map +1 -0
- package/dist/Virtualizer2.jsx +730 -0
- package/dist/Virtualizer2.jsx.map +1 -0
- package/dist/VirtualizerLayouts.d.ts +18 -0
- package/dist/VirtualizerLayouts.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +42 -0
- package/dist/VisuallyHidden.js.map +1 -0
- package/dist/VisuallyHidden.jsx +35 -0
- package/dist/VisuallyHidden.jsx.map +1 -0
- package/dist/contexts.js +33 -0
- package/dist/contexts.js.map +1 -0
- package/dist/contexts.jsx +33 -0
- package/dist/contexts.jsx.map +1 -0
- package/dist/index.d.ts +9 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +69 -23932
- package/dist/index.jsx +69 -18337
- package/dist/useDragAndDrop.d.ts +0 -8
- package/dist/useDragAndDrop.d.ts.map +1 -1
- package/dist/useDragAndDrop.js +2 -0
- package/dist/useDragAndDrop.jsx +2 -0
- package/dist/useDragAndDrop2.js +399 -0
- package/dist/useDragAndDrop2.js.map +1 -0
- package/dist/useDragAndDrop2.jsx +399 -0
- package/dist/useDragAndDrop2.jsx.map +1 -0
- package/dist/utils.d.ts +84 -11
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +285 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.jsx +277 -0
- package/dist/utils.jsx.map +1 -0
- package/dist/virtualizer/Layout.js +144 -0
- package/dist/virtualizer/Layout.js.map +1 -0
- package/dist/virtualizer/Layout.jsx +144 -0
- package/dist/virtualizer/Layout.jsx.map +1 -0
- package/package.json +395 -4
- package/src/ActionBar.tsx +10 -12
- package/src/ActionGroup.tsx +5 -3
- package/src/Autocomplete.tsx +14 -9
- package/src/Breadcrumbs.tsx +58 -39
- package/src/Button.tsx +22 -2
- package/src/Calendar.tsx +57 -11
- package/src/CalendarPicker.tsx +73 -0
- package/src/Checkbox.tsx +539 -3
- package/src/Collection.tsx +9 -3
- package/src/Color.tsx +84 -41
- package/src/ComboBox.tsx +97 -21
- package/src/DateField.tsx +304 -53
- package/src/DatePicker.tsx +402 -62
- package/src/DateRangePickerContext.tsx +2 -0
- package/src/Dialog.tsx +13 -5
- package/src/Disclosure.tsx +7 -1
- package/src/DragAndDrop.tsx +3 -1
- package/src/DropZone.tsx +3 -1
- package/src/GridList.tsx +133 -26
- package/src/Icon.tsx +3 -1
- package/src/Link.tsx +3 -1
- package/src/ListBox.tsx +354 -25
- package/src/Menu.tsx +252 -128
- package/src/Meter.tsx +3 -1
- package/src/Modal.tsx +120 -56
- package/src/NumberField.tsx +51 -8
- package/src/Popover.tsx +68 -17
- package/src/ProgressBar.tsx +3 -1
- package/src/RadioGroup.tsx +468 -4
- package/src/RangeCalendar.tsx +123 -2
- package/src/SearchField.tsx +80 -4
- package/src/Select.tsx +122 -26
- package/src/SelectionIndicator.tsx +3 -1
- package/src/SharedElementTransition.tsx +95 -37
- package/src/Slider.tsx +159 -13
- package/src/StepList.tsx +0 -7
- package/src/Switch.tsx +395 -2
- package/src/Table.tsx +428 -99
- package/src/Tabs.tsx +17 -45
- package/src/TagGroup.tsx +29 -7
- package/src/Text.tsx +31 -10
- package/src/TextField.tsx +44 -6
- package/src/TimeField.tsx +127 -192
- package/src/Toast.tsx +79 -14
- package/src/ToggleButton.tsx +3 -1
- package/src/ToggleButtonGroup.tsx +3 -1
- package/src/Tooltip.tsx +3 -1
- package/src/Tree.tsx +91 -13
- package/src/Virtualizer.tsx +180 -31
- package/src/VirtualizerLayouts.ts +45 -10
- package/src/index.ts +51 -8
- package/src/useDragAndDrop.ts +8 -10
- package/src/utils.tsx +246 -30
- package/dist/HiddenTimeInput.d.ts +0 -25
- package/dist/HiddenTimeInput.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.jsx.map +0 -1
- package/src/HiddenTimeInput.tsx +0 -133
package/src/Meter.tsx
CHANGED
|
@@ -119,7 +119,9 @@ export function Meter(props: MeterProps): JSX.Element {
|
|
|
119
119
|
|
|
120
120
|
const renderProps = useRenderProps(
|
|
121
121
|
{
|
|
122
|
-
children
|
|
122
|
+
get children() {
|
|
123
|
+
return props.children;
|
|
124
|
+
},
|
|
123
125
|
class: local.class,
|
|
124
126
|
style: local.style,
|
|
125
127
|
defaultClassName: "solidaria-Meter",
|
package/src/Modal.tsx
CHANGED
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
ariaHideOutside,
|
|
23
23
|
FocusScope,
|
|
24
24
|
useUNSAFE_PortalContext,
|
|
25
|
+
createEnterAnimation,
|
|
26
|
+
createExitAnimation,
|
|
25
27
|
} from "@proyecto-viviana/solidaria";
|
|
26
28
|
import {
|
|
27
29
|
type RenderChildren,
|
|
@@ -37,6 +39,7 @@ import {
|
|
|
37
39
|
OverlayTriggerStateContext,
|
|
38
40
|
type OverlayTriggerState,
|
|
39
41
|
} from "./contexts";
|
|
42
|
+
import { VisuallyHidden } from "./VisuallyHidden";
|
|
40
43
|
|
|
41
44
|
/**
|
|
42
45
|
* Internal context to signal that Modal is wrapped in ModalOverlay.
|
|
@@ -45,6 +48,13 @@ import {
|
|
|
45
48
|
interface InternalModalContextValue {
|
|
46
49
|
isDismissable?: boolean;
|
|
47
50
|
isKeyboardDismissDisabled?: boolean;
|
|
51
|
+
// Upstream's ModalOverlay owns the modal element's ref so it can watch the
|
|
52
|
+
// modal surface's exit animation alongside the overlay's (both must finish
|
|
53
|
+
// before the overlay unmounts). ModalContent registers its element here.
|
|
54
|
+
setModalRef?: (element: HTMLElement | null) => void;
|
|
55
|
+
// Combined exit flag (overlay OR modal still exiting). Both the overlay and
|
|
56
|
+
// the modal surface carry `data-exiting` off this so they fade out together.
|
|
57
|
+
isExiting?: () => boolean;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
const InternalModalContext = createContext<InternalModalContextValue | null>(null);
|
|
@@ -177,9 +187,34 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
|
|
|
177
187
|
toggle,
|
|
178
188
|
};
|
|
179
189
|
|
|
190
|
+
// Enter/exit animation state (mirrors upstream's ModalOverlayWithForwardRef +
|
|
191
|
+
// ModalOverlayInner). The overlay stays mounted here even while closed, so the
|
|
192
|
+
// enter animation is gated on `isOpen` (isReady) — otherwise it would resolve
|
|
193
|
+
// to "done entering" before the element ever mounts. Exit is watched for BOTH
|
|
194
|
+
// the overlay and the modal surface; the modal registers its element via
|
|
195
|
+
// InternalModalContext (setModalRef) so we can await its exit too.
|
|
196
|
+
let overlayRef!: HTMLDivElement;
|
|
197
|
+
// Signal-backed so the enter/exit effects re-run once the element mounts — a
|
|
198
|
+
// plain closure over `overlayRef` would read `null` if the effect fired first
|
|
199
|
+
// and, with no reactive dep on the ref, never recover (stuck `data-entering`).
|
|
200
|
+
const [overlayEl, setOverlayEl] = createSignal<HTMLElement | null>(null);
|
|
201
|
+
const overlayRefAccessor = () => overlayEl();
|
|
202
|
+
const registerOverlayRef = (element: HTMLDivElement) => {
|
|
203
|
+
overlayRef = element;
|
|
204
|
+
setOverlayEl(element);
|
|
205
|
+
};
|
|
206
|
+
const [modalEl, setModalEl] = createSignal<HTMLElement | null>(null);
|
|
207
|
+
|
|
208
|
+
const isOverlayEntering = createEnterAnimation(overlayRefAccessor, isOpen);
|
|
209
|
+
const isOverlayExiting = createExitAnimation(overlayRefAccessor, isOpen);
|
|
210
|
+
const isModalExiting = createExitAnimation(() => modalEl(), isOpen);
|
|
211
|
+
const overlayEntering = () => isOverlayEntering() || (local.isEntering ?? false);
|
|
212
|
+
const combinedExiting = () =>
|
|
213
|
+
isOverlayExiting() || isModalExiting() || (local.isExiting ?? false);
|
|
214
|
+
|
|
180
215
|
const renderValues = createMemo<ModalRenderProps>(() => ({
|
|
181
|
-
isEntering:
|
|
182
|
-
isExiting:
|
|
216
|
+
isEntering: overlayEntering(),
|
|
217
|
+
isExiting: combinedExiting(),
|
|
183
218
|
}));
|
|
184
219
|
|
|
185
220
|
// Resolve render props - don't pass children, we'll render props.children directly
|
|
@@ -200,10 +235,11 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
|
|
|
200
235
|
const internalModalContext: InternalModalContextValue = {
|
|
201
236
|
isDismissable: local.isDismissable,
|
|
202
237
|
isKeyboardDismissDisabled: local.isKeyboardDismissDisabled,
|
|
238
|
+
setModalRef: setModalEl,
|
|
239
|
+
isExiting: combinedExiting,
|
|
203
240
|
};
|
|
204
241
|
const portalContext = useUNSAFE_PortalContext();
|
|
205
242
|
const portalContainer = () => portalContext.getContainer?.() ?? undefined;
|
|
206
|
-
let overlayRef!: HTMLDivElement;
|
|
207
243
|
|
|
208
244
|
const isTopMostModalInOverlay = () => {
|
|
209
245
|
pruneDisconnectedModals();
|
|
@@ -228,9 +264,14 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
|
|
|
228
264
|
}
|
|
229
265
|
};
|
|
230
266
|
|
|
231
|
-
|
|
267
|
+
// Bubble phase, mirroring react-aria's `useOverlay` (its `onKeyDown` is an
|
|
268
|
+
// overlay-element prop, handled on bubble). Capture would preempt inner
|
|
269
|
+
// widgets that dismiss on Escape (a combobox/menu inside the dialog must
|
|
270
|
+
// consume Escape first) and would also fire before the event is recorded by
|
|
271
|
+
// capture-phase listeners, inverting the keydown/onOpenChange order.
|
|
272
|
+
document.addEventListener("keydown", handleKeyDown, false);
|
|
232
273
|
onCleanup(() => {
|
|
233
|
-
document.removeEventListener("keydown", handleKeyDown,
|
|
274
|
+
document.removeEventListener("keydown", handleKeyDown, false);
|
|
234
275
|
});
|
|
235
276
|
});
|
|
236
277
|
|
|
@@ -246,17 +287,17 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
|
|
|
246
287
|
};
|
|
247
288
|
|
|
248
289
|
return (
|
|
249
|
-
<Show when={isHydrated() && (isOpen() ||
|
|
290
|
+
<Show when={isHydrated() && (isOpen() || combinedExiting())}>
|
|
250
291
|
<Portal mount={portalContainer()}>
|
|
251
292
|
<OverlayTriggerStateContext.Provider value={state}>
|
|
252
293
|
<InternalModalContext.Provider value={internalModalContext}>
|
|
253
294
|
<div
|
|
254
295
|
{...domProps()}
|
|
255
|
-
ref={
|
|
296
|
+
ref={registerOverlayRef}
|
|
256
297
|
class={renderProps.class()}
|
|
257
298
|
style={renderProps.style()}
|
|
258
|
-
data-entering={dataAttr(
|
|
259
|
-
data-exiting={dataAttr(
|
|
299
|
+
data-entering={dataAttr(overlayEntering())}
|
|
300
|
+
data-exiting={dataAttr(combinedExiting())}
|
|
260
301
|
onPointerDown={handleOverlayPointerDown}
|
|
261
302
|
>
|
|
262
303
|
{resolveChildren()}
|
|
@@ -305,26 +346,17 @@ function ModalContentWithAutoOverlay(props: ModalProps): JSX.Element {
|
|
|
305
346
|
// Check for InternalModalContext - if present, we're inside a ModalOverlay
|
|
306
347
|
const internalContext = useContext(InternalModalContext);
|
|
307
348
|
|
|
308
|
-
// If wrapped in ModalOverlay, just render the content
|
|
349
|
+
// If wrapped in ModalOverlay, just render the content. ModalContent reads the
|
|
350
|
+
// overlay's InternalModalContext itself (via useContext), so nothing needs
|
|
351
|
+
// threading — in both branches ModalContent renders inside a provider.
|
|
309
352
|
if (internalContext) {
|
|
310
|
-
return
|
|
311
|
-
<ModalContent {...modalProps} internalContext={internalContext}>
|
|
312
|
-
{props.children}
|
|
313
|
-
</ModalContent>
|
|
314
|
-
);
|
|
353
|
+
return <ModalContent {...modalProps}>{props.children}</ModalContent>;
|
|
315
354
|
}
|
|
316
355
|
|
|
317
|
-
// For standalone usage, wrap in ModalOverlay
|
|
318
|
-
const standaloneContext: InternalModalContextValue = {
|
|
319
|
-
isDismissable: overlayProps.isDismissable,
|
|
320
|
-
isKeyboardDismissDisabled: overlayProps.isKeyboardDismissDisabled,
|
|
321
|
-
};
|
|
322
|
-
|
|
356
|
+
// For standalone usage, wrap in ModalOverlay.
|
|
323
357
|
return (
|
|
324
358
|
<ModalOverlay {...overlayProps}>
|
|
325
|
-
<ModalContent {...modalProps}
|
|
326
|
-
{props.children}
|
|
327
|
-
</ModalContent>
|
|
359
|
+
<ModalContent {...modalProps}>{props.children}</ModalContent>
|
|
328
360
|
</ModalOverlay>
|
|
329
361
|
);
|
|
330
362
|
}
|
|
@@ -333,9 +365,7 @@ function ModalContentWithAutoOverlay(props: ModalProps): JSX.Element {
|
|
|
333
365
|
* Internal component that renders the actual modal content.
|
|
334
366
|
* Used by both standalone Modal and Modal wrapped in ModalOverlay.
|
|
335
367
|
*/
|
|
336
|
-
function ModalContent(
|
|
337
|
-
props: ModalProps & { internalContext: InternalModalContextValue },
|
|
338
|
-
): JSX.Element {
|
|
368
|
+
function ModalContent(props: ModalProps): JSX.Element {
|
|
339
369
|
if (isServer) {
|
|
340
370
|
return <>{props.children}</>;
|
|
341
371
|
}
|
|
@@ -351,19 +381,27 @@ function ModalContent(
|
|
|
351
381
|
"isKeyboardDismissDisabled",
|
|
352
382
|
"isEntering",
|
|
353
383
|
"isExiting",
|
|
354
|
-
"internalContext",
|
|
355
384
|
]);
|
|
356
385
|
|
|
357
386
|
let modalRef!: HTMLDivElement;
|
|
358
387
|
const modalRefAccessor = () => modalRef ?? null;
|
|
388
|
+
// Signal-backed element for the enter animation, so the effect re-runs when
|
|
389
|
+
// the surface mounts (see the overlay's note); the plain `modalRef` var still
|
|
390
|
+
// backs the synchronous consumers (focus stack, interact-outside, aria-hide).
|
|
391
|
+
const [modalEl, setModalEl] = createSignal<HTMLElement | null>(null);
|
|
359
392
|
|
|
360
393
|
// Get state from parent OverlayTriggerStateContext (provided by ModalOverlay)
|
|
361
394
|
const parentState = useContext(OverlayTriggerStateContext);
|
|
362
395
|
|
|
396
|
+
// The overlay (auto or user-provided) always wraps this content, so it owns
|
|
397
|
+
// the InternalModalContext: dismissal settings, the modal-ref registration
|
|
398
|
+
// sink, and the combined exit flag.
|
|
399
|
+
const internalContext = useContext(InternalModalContext);
|
|
400
|
+
|
|
363
401
|
// Get dismissable settings from internal context (set by ModalOverlay)
|
|
364
|
-
const isDismissable = () =>
|
|
402
|
+
const isDismissable = () => internalContext?.isDismissable ?? local.isDismissable;
|
|
365
403
|
const isKeyboardDismissDisabled = () =>
|
|
366
|
-
|
|
404
|
+
internalContext?.isKeyboardDismissDisabled ?? local.isKeyboardDismissDisabled;
|
|
367
405
|
|
|
368
406
|
// Determine if open from parent state
|
|
369
407
|
const isOpen = (): boolean => {
|
|
@@ -371,6 +409,19 @@ function ModalContent(
|
|
|
371
409
|
return parentState?.isOpen ?? false;
|
|
372
410
|
};
|
|
373
411
|
|
|
412
|
+
// Register this element with the overlay so it can await the modal surface's
|
|
413
|
+
// exit animation (upstream threads modalRef down the same way). The overlay's
|
|
414
|
+
// combined exit flag drives this surface's `data-exiting`. The enter animation
|
|
415
|
+
// is local — the modal fades/slides in on its own timeline (delay 160 vs the
|
|
416
|
+
// overlay's 0).
|
|
417
|
+
const registerModalRef = (element: HTMLDivElement) => {
|
|
418
|
+
modalRef = element;
|
|
419
|
+
setModalEl(element);
|
|
420
|
+
internalContext?.setModalRef?.(element);
|
|
421
|
+
};
|
|
422
|
+
const isModalEntering = createEnterAnimation(() => modalEl(), isOpen);
|
|
423
|
+
const isModalExiting = () => internalContext?.isExiting?.() ?? local.isExiting ?? false;
|
|
424
|
+
|
|
374
425
|
// Keep this modal in a global stack so nested modals dismiss in top-down order.
|
|
375
426
|
createEffect(() => {
|
|
376
427
|
if (!isOpen()) return;
|
|
@@ -441,9 +492,11 @@ function ModalContent(
|
|
|
441
492
|
}
|
|
442
493
|
};
|
|
443
494
|
|
|
444
|
-
|
|
495
|
+
// Bubble phase — see the ModalOverlay handler above for why (react-aria
|
|
496
|
+
// `useOverlay` parity; inner-widget Escape precedence; event-order fidelity).
|
|
497
|
+
document.addEventListener("keydown", handleKeyDown, false);
|
|
445
498
|
onCleanup(() => {
|
|
446
|
-
document.removeEventListener("keydown", handleKeyDown,
|
|
499
|
+
document.removeEventListener("keydown", handleKeyDown, false);
|
|
447
500
|
});
|
|
448
501
|
});
|
|
449
502
|
|
|
@@ -457,7 +510,7 @@ function ModalContent(
|
|
|
457
510
|
|
|
458
511
|
const hideOutside = () => {
|
|
459
512
|
if (cancelled || !modalRef?.isConnected) return;
|
|
460
|
-
cleanup = ariaHideOutside([modalRef]);
|
|
513
|
+
cleanup = ariaHideOutside([modalRef], { shouldUseInert: true });
|
|
461
514
|
};
|
|
462
515
|
|
|
463
516
|
if (modalRef.isConnected) {
|
|
@@ -473,8 +526,8 @@ function ModalContent(
|
|
|
473
526
|
});
|
|
474
527
|
|
|
475
528
|
const renderValues = createMemo<ModalRenderProps>(() => ({
|
|
476
|
-
isEntering:
|
|
477
|
-
isExiting:
|
|
529
|
+
isEntering: isModalEntering(),
|
|
530
|
+
isExiting: isModalExiting(),
|
|
478
531
|
}));
|
|
479
532
|
|
|
480
533
|
const renderProps = useRenderProps(
|
|
@@ -499,33 +552,44 @@ function ModalContent(
|
|
|
499
552
|
);
|
|
500
553
|
|
|
501
554
|
return (
|
|
502
|
-
|
|
555
|
+
// No autoFocus: react-aria's Overlay renders FocusScope with restoreFocus +
|
|
556
|
+
// contain only — initial focus is useDialog's job (it focuses the dialog
|
|
557
|
+
// element itself when nothing inside holds focus).
|
|
558
|
+
//
|
|
559
|
+
// `contain` is gated on `!isExiting`, mirroring react-aria's Overlay
|
|
560
|
+
// (react-aria/src/overlays/Overlay.tsx: `contain={... && !isExiting}`). The
|
|
561
|
+
// overlay stays mounted through its exit transition (isOpen || isExiting), so
|
|
562
|
+
// without this gate containment would remain active during the exit and yank
|
|
563
|
+
// focus back into the dialog as restoreFocus moves it to the trigger —
|
|
564
|
+
// producing a focus bounce (focusout→focusin→focusout) that React never
|
|
565
|
+
// shows. Releasing containment the instant the exit begins lets focus settle
|
|
566
|
+
// on the trigger in a single move, matching upstream's event sequence.
|
|
567
|
+
<FocusScope contain={!isModalExiting()} restoreFocus>
|
|
503
568
|
<div
|
|
504
569
|
{...domProps()}
|
|
505
|
-
ref={
|
|
570
|
+
ref={registerModalRef}
|
|
506
571
|
class={renderProps.class()}
|
|
507
572
|
style={renderProps.style()}
|
|
508
|
-
data-entering={dataAttr(
|
|
509
|
-
data-exiting={dataAttr(
|
|
573
|
+
data-entering={dataAttr(isModalEntering())}
|
|
574
|
+
data-exiting={dataAttr(isModalExiting())}
|
|
510
575
|
>
|
|
511
576
|
<Show when={isDismissable()}>
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
"
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
/>
|
|
577
|
+
{/* Faithful to react-aria's DismissButton: a bare button carrying
|
|
578
|
+
only `width/height: 1px` inside a VisuallyHidden `div` wrapper —
|
|
579
|
+
NOT the hidden styles inlined onto the button. The wrapper clips
|
|
580
|
+
it out of sight while the button keeps its intrinsic UA border-box,
|
|
581
|
+
which is exactly what upstream renders (and what D8 target-size
|
|
582
|
+
measures against the pair oracle). Inlining the reset onto the
|
|
583
|
+
button instead collapsed it to a 1x1 box, diverging from
|
|
584
|
+
upstream's ~16x6 sentinel. */}
|
|
585
|
+
<VisuallyHidden elementType="div">
|
|
586
|
+
<button
|
|
587
|
+
aria-label="Dismiss"
|
|
588
|
+
tabIndex={-1}
|
|
589
|
+
onClick={close}
|
|
590
|
+
style={{ width: "1px", height: "1px" }}
|
|
591
|
+
/>
|
|
592
|
+
</VisuallyHidden>
|
|
529
593
|
</Show>
|
|
530
594
|
{renderProps.renderChildren()}
|
|
531
595
|
</div>
|
package/src/NumberField.tsx
CHANGED
|
@@ -5,7 +5,14 @@
|
|
|
5
5
|
* Port of react-aria-components/src/NumberField.tsx
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
type JSX,
|
|
10
|
+
type Context,
|
|
11
|
+
createContext,
|
|
12
|
+
createMemo,
|
|
13
|
+
splitProps,
|
|
14
|
+
useContext,
|
|
15
|
+
} from "solid-js";
|
|
9
16
|
import {
|
|
10
17
|
createNumberField,
|
|
11
18
|
createButton,
|
|
@@ -22,7 +29,9 @@ import {
|
|
|
22
29
|
type SlotProps,
|
|
23
30
|
useRenderProps,
|
|
24
31
|
filterDOMProps,
|
|
32
|
+
Provider,
|
|
25
33
|
} from "./utils";
|
|
34
|
+
import { TextContext } from "./Text";
|
|
26
35
|
|
|
27
36
|
export interface NumberFieldRenderProps {
|
|
28
37
|
/** Whether the number field is disabled. */
|
|
@@ -294,7 +303,9 @@ export function NumberField(props: NumberFieldProps): JSX.Element {
|
|
|
294
303
|
|
|
295
304
|
const renderProps = useRenderProps(
|
|
296
305
|
{
|
|
297
|
-
children
|
|
306
|
+
get children() {
|
|
307
|
+
return props.children;
|
|
308
|
+
},
|
|
298
309
|
class: local.class,
|
|
299
310
|
style: local.style,
|
|
300
311
|
defaultClassName: "solidaria-NumberField",
|
|
@@ -366,6 +377,21 @@ export function NumberField(props: NumberFieldProps): JSX.Element {
|
|
|
366
377
|
},
|
|
367
378
|
setInputRef,
|
|
368
379
|
};
|
|
380
|
+
// Provide the description / errorMessage props as `TextContext` slots (mirrors
|
|
381
|
+
// react-aria-components' NumberField), so a `<Text slot="description">` /
|
|
382
|
+
// `<Text slot="errorMessage">` child picks up the `id` its `aria-describedby`
|
|
383
|
+
// references. Additive: existing consumers reading these off
|
|
384
|
+
// `NumberFieldContext` are unaffected.
|
|
385
|
+
const textSlots = {
|
|
386
|
+
slots: {
|
|
387
|
+
get description() {
|
|
388
|
+
return numberFieldAria.descriptionProps;
|
|
389
|
+
},
|
|
390
|
+
get errorMessage() {
|
|
391
|
+
return numberFieldAria.errorMessageProps;
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
};
|
|
369
395
|
|
|
370
396
|
return (
|
|
371
397
|
<NumberFieldStateContext.Provider value={state}>
|
|
@@ -379,7 +405,9 @@ export function NumberField(props: NumberFieldProps): JSX.Element {
|
|
|
379
405
|
data-required={ariaProps.isRequired || undefined}
|
|
380
406
|
data-readonly={ariaProps.isReadOnly || undefined}
|
|
381
407
|
>
|
|
382
|
-
{
|
|
408
|
+
<Provider values={[[TextContext, textSlots]] as Array<[Context<unknown>, unknown]>}>
|
|
409
|
+
{fieldChildren()}
|
|
410
|
+
</Provider>
|
|
383
411
|
</div>
|
|
384
412
|
</NumberFieldContext.Provider>
|
|
385
413
|
</NumberFieldStateContext.Provider>
|
|
@@ -399,14 +427,25 @@ export function NumberFieldLabel(props: {
|
|
|
399
427
|
throw new Error("NumberFieldLabel must be used within a NumberField");
|
|
400
428
|
}
|
|
401
429
|
|
|
430
|
+
// Upstream RAC/S2 renders the NumberField label as a native `<label>` (the field's
|
|
431
|
+
// `labelElementType` is the default `'label'`), so `labelProps` carries `for=inputId`.
|
|
432
|
+
// This was a `<span>` — a self-inflicted divergence dropping the native for/label
|
|
433
|
+
// semantics; reverted to `<label>` to match the shipped React DOM byte-for-byte.
|
|
434
|
+
// (Mirror SearchFieldLabel: `labelProps` is typed for a generic element, so strip the
|
|
435
|
+
// `ref` and spread the rest onto the `<label>` intrinsic.)
|
|
436
|
+
const cleanLabelProps = () => {
|
|
437
|
+
const { ref: _ref, ...rest } = context.labelProps as Record<string, unknown>;
|
|
438
|
+
return rest;
|
|
439
|
+
};
|
|
440
|
+
|
|
402
441
|
return (
|
|
403
|
-
<
|
|
404
|
-
{...
|
|
442
|
+
<label
|
|
443
|
+
{...cleanLabelProps()}
|
|
405
444
|
class={props.class ?? "solidaria-NumberField-label"}
|
|
406
445
|
style={props.style}
|
|
407
446
|
>
|
|
408
447
|
{props.children}
|
|
409
|
-
</
|
|
448
|
+
</label>
|
|
410
449
|
);
|
|
411
450
|
}
|
|
412
451
|
|
|
@@ -558,7 +597,9 @@ export function NumberFieldIncrementButton(props: NumberFieldIncrementButtonProp
|
|
|
558
597
|
|
|
559
598
|
const renderProps = useRenderProps(
|
|
560
599
|
{
|
|
561
|
-
children
|
|
600
|
+
get children() {
|
|
601
|
+
return props.children;
|
|
602
|
+
},
|
|
562
603
|
class: local.class,
|
|
563
604
|
style: local.style,
|
|
564
605
|
defaultClassName: "solidaria-NumberField-increment",
|
|
@@ -637,7 +678,9 @@ export function NumberFieldDecrementButton(props: NumberFieldDecrementButtonProp
|
|
|
637
678
|
|
|
638
679
|
const renderProps = useRenderProps(
|
|
639
680
|
{
|
|
640
|
-
children
|
|
681
|
+
get children() {
|
|
682
|
+
return props.children;
|
|
683
|
+
},
|
|
641
684
|
class: local.class,
|
|
642
685
|
style: local.style,
|
|
643
686
|
defaultClassName: "solidaria-NumberField-decrement",
|
package/src/Popover.tsx
CHANGED
|
@@ -22,8 +22,10 @@ import {
|
|
|
22
22
|
createOverlayTrigger,
|
|
23
23
|
createPopover,
|
|
24
24
|
FocusScope,
|
|
25
|
+
useLocale,
|
|
25
26
|
useUNSAFE_PortalContext,
|
|
26
27
|
visuallyHiddenStyles,
|
|
28
|
+
type AriaLabelingProps,
|
|
27
29
|
type Placement,
|
|
28
30
|
type PlacementAxis,
|
|
29
31
|
} from "@proyecto-viviana/solidaria";
|
|
@@ -59,7 +61,7 @@ export interface PopoverRenderProps {
|
|
|
59
61
|
isExiting: boolean;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
export interface PopoverProps extends SlotProps {
|
|
64
|
+
export interface PopoverProps extends SlotProps, AriaLabelingProps {
|
|
63
65
|
/** The children of the component - can be JSX or render function. */
|
|
64
66
|
children?: RenderChildren<PopoverRenderProps>;
|
|
65
67
|
/** The CSS className for the element. */
|
|
@@ -111,6 +113,14 @@ export interface PopoverProps extends SlotProps {
|
|
|
111
113
|
* A boundary element for placement calculations.
|
|
112
114
|
*/
|
|
113
115
|
boundaryElement?: Element;
|
|
116
|
+
/**
|
|
117
|
+
* Overrides the target element's bounding rectangle. Useful for positioning relative to
|
|
118
|
+
* a specific point such as the mouse cursor (e.g. context menus) or text selection.
|
|
119
|
+
*
|
|
120
|
+
* @default target.getBoundingClientRect()
|
|
121
|
+
* @param target - The target element.
|
|
122
|
+
*/
|
|
123
|
+
getTargetRect?: (target: Element) => DOMRect | null | undefined;
|
|
114
124
|
/**
|
|
115
125
|
* A ref for the popover arrow element.
|
|
116
126
|
*/
|
|
@@ -257,6 +267,7 @@ export function Popover(props: PopoverProps): JSX.Element {
|
|
|
257
267
|
"shouldFlip",
|
|
258
268
|
"maxHeight",
|
|
259
269
|
"boundaryElement",
|
|
270
|
+
"getTargetRect",
|
|
260
271
|
"arrowRef",
|
|
261
272
|
"scrollRef",
|
|
262
273
|
"isNonModal",
|
|
@@ -270,12 +281,29 @@ export function Popover(props: PopoverProps): JSX.Element {
|
|
|
270
281
|
"isExiting",
|
|
271
282
|
]);
|
|
272
283
|
|
|
273
|
-
let
|
|
284
|
+
// A reactive ref (not a plain `let`) so the overlay-position effect in
|
|
285
|
+
// createOverlayPosition — which tracks `overlayRef()` as a dependency —
|
|
286
|
+
// re-runs once the portal node actually mounts. React gets this timing for
|
|
287
|
+
// free from useLayoutEffect (the ref is populated before the position effect
|
|
288
|
+
// fires); in Solid the portal node is created lazily on open, AFTER the
|
|
289
|
+
// position effect first ran with a null ref, so a non-reactive ref left the
|
|
290
|
+
// popover stranded at the createOverlayPosition fallback (position:fixed;
|
|
291
|
+
// top:0; left:0) whenever no other dependency happened to re-fire the effect
|
|
292
|
+
// after mount. Mirrors the sibling groupRef signal below.
|
|
293
|
+
const [popoverRef, setPopoverRef] = createSignal<HTMLDivElement | null>(null);
|
|
274
294
|
const [groupRef, setGroupRef] = createSignal<HTMLDivElement | null>(null);
|
|
275
295
|
// False on the server and during hydration; true after onMount. Gates the Portal
|
|
276
296
|
// so overlay content only ever renders client-side, post-hydration.
|
|
277
297
|
const isHydrated = useIsHydrated();
|
|
278
298
|
|
|
299
|
+
// Mirrors upstream S2 Popover (Popover.mjs: `el.lang = locale; el.dir =
|
|
300
|
+
// direction`): the overlay portals out of the app root, so it must carry both
|
|
301
|
+
// the locale `lang` AND writing `direction` — otherwise the portaled
|
|
302
|
+
// listbox/dialog stays LTR and keeps the Latin font under an RTL Provider (the
|
|
303
|
+
// `:lang(ar)` font swap needs a `lang` ancestor the portal would otherwise
|
|
304
|
+
// escape). RAC's own Popover only threads `dir`; S2 adds `lang` on top.
|
|
305
|
+
const locale = useLocale();
|
|
306
|
+
|
|
279
307
|
const triggerContext = useContext(PopoverTriggerContext);
|
|
280
308
|
const dialogTriggerContext = useContext(DialogTriggerContext);
|
|
281
309
|
const popoverGroupContext = useContext(PopoverGroupContext);
|
|
@@ -323,7 +351,7 @@ export function Popover(props: PopoverProps): JSX.Element {
|
|
|
323
351
|
const popoverAria = createPopover(
|
|
324
352
|
{
|
|
325
353
|
triggerRef: getTriggerRef,
|
|
326
|
-
popoverRef: () => popoverRef
|
|
354
|
+
popoverRef: () => popoverRef(),
|
|
327
355
|
groupRef: () => (isSubPopover() ? (popoverGroupContext?.() ?? null) : groupRef()),
|
|
328
356
|
get placement() {
|
|
329
357
|
return local.placement;
|
|
@@ -346,6 +374,9 @@ export function Popover(props: PopoverProps): JSX.Element {
|
|
|
346
374
|
get boundaryElement() {
|
|
347
375
|
return local.boundaryElement;
|
|
348
376
|
},
|
|
377
|
+
get getTargetRect() {
|
|
378
|
+
return local.getTargetRect;
|
|
379
|
+
},
|
|
349
380
|
get arrowRef() {
|
|
350
381
|
return local.arrowRef;
|
|
351
382
|
},
|
|
@@ -501,7 +532,7 @@ export function Popover(props: PopoverProps): JSX.Element {
|
|
|
501
532
|
createEffect(() => {
|
|
502
533
|
if (!isOpen() || !shouldBeDialog()) return;
|
|
503
534
|
if ((local.autoFocus ?? true) === false) return;
|
|
504
|
-
if (!popoverRef) return;
|
|
535
|
+
if (!popoverRef()) return;
|
|
505
536
|
if (resolvedTrigger() === "SubmenuTrigger") return;
|
|
506
537
|
|
|
507
538
|
let timeout: number | undefined;
|
|
@@ -509,11 +540,12 @@ export function Popover(props: PopoverProps): JSX.Element {
|
|
|
509
540
|
|
|
510
541
|
const focusIfNeeded = () => {
|
|
511
542
|
if (!isOpen() || !shouldBeDialog()) return;
|
|
512
|
-
|
|
513
|
-
if (
|
|
543
|
+
const node = popoverRef();
|
|
544
|
+
if (!node || resolvedTrigger() === "SubmenuTrigger") return;
|
|
545
|
+
if (document.activeElement === node || node.contains(document.activeElement)) {
|
|
514
546
|
return;
|
|
515
547
|
}
|
|
516
|
-
|
|
548
|
+
node.focus();
|
|
517
549
|
};
|
|
518
550
|
|
|
519
551
|
const scheduleFocus = () => {
|
|
@@ -559,12 +591,14 @@ export function Popover(props: PopoverProps): JSX.Element {
|
|
|
559
591
|
<div
|
|
560
592
|
{...domProps()}
|
|
561
593
|
{...cleanPopoverProps()}
|
|
562
|
-
ref={
|
|
594
|
+
ref={setPopoverRef}
|
|
563
595
|
id={overlayId()}
|
|
564
596
|
role={shouldBeDialog() ? "dialog" : undefined}
|
|
565
597
|
tabIndex={shouldBeDialog() ? -1 : undefined}
|
|
566
598
|
class={renderProps.class()}
|
|
567
599
|
style={mergedStyle()}
|
|
600
|
+
lang={locale().locale}
|
|
601
|
+
dir={locale().direction}
|
|
568
602
|
data-trigger={resolvedTrigger()}
|
|
569
603
|
data-placement={popoverAria.placement()}
|
|
570
604
|
data-entering={dataAttr(local.isEntering)}
|
|
@@ -627,10 +661,33 @@ export function OverlayArrow(props: OverlayArrowProps): JSX.Element {
|
|
|
627
661
|
const popoverContext = useContext(PopoverContext);
|
|
628
662
|
const placement = () => popoverContext?.placement() ?? null;
|
|
629
663
|
|
|
630
|
-
|
|
664
|
+
// Mirror react-aria-components' OverlayArrow: the wrapper positions itself
|
|
665
|
+
// absolutely against the popover edge (`[placement]: '100%'`) and takes the
|
|
666
|
+
// cross-axis offset (`left`/`top`) from the overlay's computed `arrowProps`.
|
|
667
|
+
// No `aria-hidden`/`role="presentation"` — upstream leaves the arrow in the
|
|
668
|
+
// accessibility tree (the arrow SVG surfaces as an unlabeled `img`), matching
|
|
669
|
+
// S2's `<OverlayArrow className="">`. The styled layer therefore passes no
|
|
670
|
+
// positioning class of its own.
|
|
671
|
+
const mergedStyle = (): JSX.CSSProperties => {
|
|
672
|
+
const currentPlacement = placement();
|
|
673
|
+
// Mirror react-aria-components' OverlayArrow: the reported `arrowProps`
|
|
674
|
+
// offset (`left`/`top`) points at the arrow's CENTER, so the wrapper must be
|
|
675
|
+
// pulled back by half its size to center on that point — horizontally for
|
|
676
|
+
// top/bottom placements, vertically for left/right. Omitting this shifts the
|
|
677
|
+
// arrow off by half its width/height (a self-inflicted divergence).
|
|
678
|
+
const style: JSX.CSSProperties = {
|
|
679
|
+
position: "absolute",
|
|
680
|
+
transform:
|
|
681
|
+
currentPlacement === "top" || currentPlacement === "bottom"
|
|
682
|
+
? "translateX(-50%)"
|
|
683
|
+
: "translateY(-50%)",
|
|
684
|
+
};
|
|
685
|
+
if (currentPlacement != null) {
|
|
686
|
+
(style as Record<string, string>)[currentPlacement] = "100%";
|
|
687
|
+
}
|
|
688
|
+
|
|
631
689
|
const contextStyle = (popoverContext?.arrowProps() as Record<string, unknown> | undefined)
|
|
632
690
|
?.style as (JSX.CSSProperties & Record<string, unknown>) | undefined;
|
|
633
|
-
const style: JSX.CSSProperties = {};
|
|
634
691
|
if (typeof contextStyle?.left === "string") {
|
|
635
692
|
style.left = contextStyle.left;
|
|
636
693
|
}
|
|
@@ -651,13 +708,7 @@ export function OverlayArrow(props: OverlayArrowProps): JSX.Element {
|
|
|
651
708
|
};
|
|
652
709
|
|
|
653
710
|
return (
|
|
654
|
-
<div
|
|
655
|
-
class={props.class}
|
|
656
|
-
style={mergedStyle()}
|
|
657
|
-
data-placement={placement()}
|
|
658
|
-
aria-hidden="true"
|
|
659
|
-
role="presentation"
|
|
660
|
-
>
|
|
711
|
+
<div class={props.class} style={mergedStyle()} data-placement={placement()}>
|
|
661
712
|
{props.render ? props.render() : props.children}
|
|
662
713
|
</div>
|
|
663
714
|
);
|
package/src/ProgressBar.tsx
CHANGED
|
@@ -133,7 +133,9 @@ export function ProgressBar(props: ProgressBarProps): JSX.Element {
|
|
|
133
133
|
|
|
134
134
|
const renderProps = useRenderProps(
|
|
135
135
|
{
|
|
136
|
-
children
|
|
136
|
+
get children() {
|
|
137
|
+
return props.children;
|
|
138
|
+
},
|
|
137
139
|
class: local.class,
|
|
138
140
|
style: local.style,
|
|
139
141
|
defaultClassName: "solidaria-ProgressBar",
|