@proyecto-viviana/solidaria-components 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -272
- package/dist/ActionBar.d.ts +21 -13
- package/dist/ActionBar.d.ts.map +1 -1
- package/dist/ActionGroup.d.ts +8 -8
- package/dist/ActionGroup.d.ts.map +1 -1
- package/dist/Alert.d.ts +5 -5
- package/dist/Alert.d.ts.map +1 -1
- package/dist/Autocomplete.d.ts +5 -5
- package/dist/Autocomplete.d.ts.map +1 -1
- package/dist/Breadcrumbs.d.ts +18 -7
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Button.d.ts +24 -5
- package/dist/Button.d.ts.map +1 -1
- package/dist/Calendar.d.ts +38 -7
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Checkbox.d.ts +32 -7
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Collection.d.ts +19 -14
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Color.d.ts +103 -14
- package/dist/Color.d.ts.map +1 -1
- package/dist/ColorEditor.d.ts +6 -6
- package/dist/ColorEditor.d.ts.map +1 -1
- package/dist/ComboBox.d.ts +85 -19
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ContextualHelpTrigger.d.ts +2 -2
- package/dist/ContextualHelpTrigger.d.ts.map +1 -1
- package/dist/DateField.d.ts +8 -6
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DatePicker.d.ts +53 -22
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DateRangePickerContext.d.ts +30 -0
- package/dist/DateRangePickerContext.d.ts.map +1 -0
- package/dist/Dialog.d.ts +5 -5
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Disclosure.d.ts +23 -5
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/DragAndDrop.d.ts +6 -6
- package/dist/DragAndDrop.d.ts.map +1 -1
- package/dist/DragPreview.d.ts +2 -2
- package/dist/DragPreview.d.ts.map +1 -1
- package/dist/DropZone.d.ts +4 -4
- package/dist/DropZone.d.ts.map +1 -1
- package/dist/FieldError.d.ts +9 -5
- package/dist/FieldError.d.ts.map +1 -1
- package/dist/FileTrigger.d.ts +3 -3
- package/dist/FileTrigger.d.ts.map +1 -1
- package/dist/Focusable.d.ts +2 -2
- package/dist/Focusable.d.ts.map +1 -1
- package/dist/Form.d.ts +18 -4
- package/dist/Form.d.ts.map +1 -1
- package/dist/GridList.d.ts +32 -12
- package/dist/GridList.d.ts.map +1 -1
- package/dist/HiddenDateInput.d.ts +26 -0
- package/dist/HiddenDateInput.d.ts.map +1 -0
- package/dist/HiddenTimeInput.d.ts +25 -0
- package/dist/HiddenTimeInput.d.ts.map +1 -0
- package/dist/Icon.d.ts +5 -5
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Keyboard.d.ts +1 -1
- package/dist/Landmark.d.ts +3 -3
- package/dist/Landmark.d.ts.map +1 -1
- package/dist/Link.d.ts +10 -4
- package/dist/Link.d.ts.map +1 -1
- package/dist/ListBox.d.ts +32 -12
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListDropTargetDelegate.d.ts +6 -6
- package/dist/ListDropTargetDelegate.d.ts.map +1 -1
- package/dist/Menu.d.ts +65 -14
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Meter.d.ts +3 -3
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Modal.d.ts +5 -5
- package/dist/Modal.d.ts.map +1 -1
- package/dist/NumberField.d.ts +8 -12
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/Popover.d.ts +28 -5
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Pressable.d.ts +2 -2
- package/dist/Pressable.d.ts.map +1 -1
- package/dist/ProgressBar.d.ts +5 -3
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/RadioGroup.d.ts +43 -9
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RangeCalendar.d.ts +34 -7
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RouterProvider.d.ts +2 -2
- package/dist/RouterProvider.d.ts.map +1 -1
- package/dist/SearchField.d.ts +23 -20
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/Select.d.ts +41 -11
- package/dist/Select.d.ts.map +1 -1
- package/dist/SelectionIndicator.d.ts +3 -3
- package/dist/SelectionIndicator.d.ts.map +1 -1
- package/dist/Separator.d.ts +9 -3
- package/dist/Separator.d.ts.map +1 -1
- package/dist/SharedElementTransition.d.ts +6 -4
- package/dist/SharedElementTransition.d.ts.map +1 -1
- package/dist/Slider.d.ts +12 -8
- package/dist/Slider.d.ts.map +1 -1
- package/dist/StepList.d.ts +90 -0
- package/dist/StepList.d.ts.map +1 -0
- package/dist/Switch.d.ts +11 -5
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Table.d.ts +187 -23
- package/dist/Table.d.ts.map +1 -1
- package/dist/Tabs.d.ts +45 -9
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/TagGroup.d.ts +12 -10
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/Text.d.ts +2 -2
- package/dist/TextField.d.ts +15 -11
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TimeField.d.ts +6 -6
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/Toast.d.ts +29 -14
- package/dist/Toast.d.ts.map +1 -1
- package/dist/ToggleButton.d.ts +11 -5
- package/dist/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButtonGroup.d.ts +7 -7
- package/dist/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/Toolbar.d.ts +7 -3
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Tooltip.d.ts +50 -8
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tree.d.ts +66 -17
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Virtualizer.d.ts +12 -12
- package/dist/Virtualizer.d.ts.map +1 -1
- package/dist/VirtualizerLayouts.d.ts +2 -2
- package/dist/VirtualizerLayouts.d.ts.map +1 -1
- package/dist/VisuallyHidden.d.ts +1 -1
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/contexts.d.ts +5 -1
- package/dist/contexts.d.ts.map +1 -1
- package/dist/index.d.ts +73 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23247 -18564
- package/dist/index.js.map +1 -1
- package/dist/index.jsx +18110 -0
- package/dist/index.jsx.map +1 -0
- package/dist/useDragAndDrop.d.ts +13 -13
- package/dist/useDragAndDrop.d.ts.map +1 -1
- package/dist/utils.d.ts +2 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/virtualizer/Layout.d.ts +1 -1
- package/dist/virtualizer/Layout.d.ts.map +1 -1
- package/package.json +31 -32
- package/src/ActionBar.tsx +75 -72
- package/src/ActionGroup.tsx +53 -61
- package/src/Alert.tsx +17 -42
- package/src/Autocomplete.tsx +39 -44
- package/src/Breadcrumbs.tsx +149 -80
- package/src/Button.tsx +267 -70
- package/src/Calendar.tsx +218 -138
- package/src/Checkbox.tsx +413 -121
- package/src/Collection.tsx +67 -58
- package/src/Color.tsx +803 -380
- package/src/ColorEditor.tsx +131 -149
- package/src/ComboBox.tsx +414 -249
- package/src/ContextualHelpTrigger.tsx +86 -74
- package/src/DateField.tsx +185 -91
- package/src/DatePicker.tsx +524 -213
- package/src/DateRangePickerContext.tsx +44 -0
- package/src/Dialog.tsx +156 -118
- package/src/Disclosure.tsx +127 -80
- package/src/DragAndDrop.tsx +60 -54
- package/src/DragPreview.tsx +13 -11
- package/src/DropZone.tsx +42 -22
- package/src/FieldError.tsx +45 -23
- package/src/FileTrigger.tsx +19 -19
- package/src/Focusable.tsx +21 -24
- package/src/Form.tsx +71 -16
- package/src/GridList.tsx +273 -197
- package/src/HiddenDateInput.tsx +153 -0
- package/src/HiddenTimeInput.tsx +133 -0
- package/src/Icon.tsx +22 -43
- package/src/Keyboard.tsx +3 -3
- package/src/Landmark.tsx +37 -63
- package/src/Link.tsx +125 -75
- package/src/ListBox.tsx +332 -233
- package/src/ListDropTargetDelegate.ts +81 -80
- package/src/Menu.tsx +1023 -274
- package/src/Meter.tsx +38 -56
- package/src/Modal.tsx +243 -175
- package/src/NumberField.tsx +139 -143
- package/src/Popover.tsx +386 -233
- package/src/Pressable.tsx +21 -21
- package/src/ProgressBar.tsx +48 -57
- package/src/RadioGroup.tsx +524 -122
- package/src/RangeCalendar.tsx +157 -90
- package/src/RouterProvider.tsx +30 -47
- package/src/SearchField.tsx +362 -143
- package/src/Select.tsx +656 -233
- package/src/SelectionIndicator.tsx +18 -15
- package/src/Separator.tsx +47 -49
- package/src/SharedElementTransition.tsx +103 -97
- package/src/Slider.tsx +138 -98
- package/src/StepList.tsx +272 -0
- package/src/Switch.tsx +93 -46
- package/src/Table.tsx +1308 -342
- package/src/Tabs.tsx +324 -103
- package/src/TagGroup.tsx +139 -126
- package/src/Text.tsx +3 -3
- package/src/TextField.tsx +389 -79
- package/src/TimeField.tsx +136 -76
- package/src/Toast.tsx +209 -157
- package/src/ToggleButton.tsx +47 -37
- package/src/ToggleButtonGroup.tsx +39 -34
- package/src/Toolbar.tsx +54 -69
- package/src/Tooltip.tsx +387 -119
- package/src/Tree.tsx +651 -368
- package/src/Virtualizer.tsx +208 -180
- package/src/VirtualizerLayouts.ts +45 -30
- package/src/VisuallyHidden.tsx +19 -19
- package/src/contexts.ts +29 -37
- package/src/index.ts +110 -195
- package/src/useDragAndDrop.ts +87 -71
- package/src/utils.tsx +40 -55
- package/src/virtualizer/Layout.ts +14 -22
- package/dist/index.ssr.js +0 -16996
- package/dist/index.ssr.js.map +0 -1
package/src/Popover.tsx
CHANGED
|
@@ -16,17 +16,18 @@ import {
|
|
|
16
16
|
splitProps,
|
|
17
17
|
useContext,
|
|
18
18
|
Show,
|
|
19
|
-
} from
|
|
20
|
-
import { Portal
|
|
19
|
+
} from "solid-js";
|
|
20
|
+
import { Portal } from "solid-js/web";
|
|
21
21
|
import {
|
|
22
22
|
createOverlayTrigger,
|
|
23
23
|
createPopover,
|
|
24
24
|
FocusScope,
|
|
25
25
|
useUNSAFE_PortalContext,
|
|
26
|
+
visuallyHiddenStyles,
|
|
26
27
|
type Placement,
|
|
27
28
|
type PlacementAxis,
|
|
28
|
-
} from
|
|
29
|
-
import { createOverlayTriggerState } from
|
|
29
|
+
} from "@proyecto-viviana/solidaria";
|
|
30
|
+
import { createOverlayTriggerState } from "@proyecto-viviana/solid-stately";
|
|
30
31
|
import {
|
|
31
32
|
type RenderChildren,
|
|
32
33
|
type ClassNameOrFunction,
|
|
@@ -35,160 +36,177 @@ import {
|
|
|
35
36
|
useRenderProps,
|
|
36
37
|
filterDOMProps,
|
|
37
38
|
dataAttr,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// ============================================
|
|
42
|
-
// TYPES
|
|
43
|
-
// ============================================
|
|
39
|
+
useIsHydrated,
|
|
40
|
+
} from "./utils";
|
|
41
|
+
import { DialogTriggerContext, PopoverTriggerContext } from "./contexts";
|
|
44
42
|
|
|
45
43
|
export interface PopoverRenderProps {
|
|
46
44
|
/**
|
|
47
45
|
* The name of the component that triggered the popover.
|
|
48
46
|
*/
|
|
49
|
-
trigger: string | null
|
|
47
|
+
trigger: string | null;
|
|
50
48
|
/**
|
|
51
49
|
* The placement of the popover relative to the trigger.
|
|
52
50
|
*/
|
|
53
|
-
placement: PlacementAxis | null
|
|
51
|
+
placement: PlacementAxis | null;
|
|
54
52
|
/**
|
|
55
53
|
* Whether the popover is currently entering (for animations).
|
|
56
54
|
*/
|
|
57
|
-
isEntering: boolean
|
|
55
|
+
isEntering: boolean;
|
|
58
56
|
/**
|
|
59
57
|
* Whether the popover is currently exiting (for animations).
|
|
60
58
|
*/
|
|
61
|
-
isExiting: boolean
|
|
59
|
+
isExiting: boolean;
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
export interface PopoverProps extends SlotProps {
|
|
65
63
|
/** The children of the component - can be JSX or render function. */
|
|
66
|
-
children?: RenderChildren<PopoverRenderProps
|
|
64
|
+
children?: RenderChildren<PopoverRenderProps>;
|
|
67
65
|
/** The CSS className for the element. */
|
|
68
|
-
class?: ClassNameOrFunction<PopoverRenderProps
|
|
66
|
+
class?: ClassNameOrFunction<PopoverRenderProps>;
|
|
69
67
|
/** The inline style for the element. */
|
|
70
|
-
style?: StyleOrFunction<PopoverRenderProps
|
|
68
|
+
style?: StyleOrFunction<PopoverRenderProps>;
|
|
71
69
|
/**
|
|
72
70
|
* The name of the component that triggered the popover.
|
|
73
71
|
*/
|
|
74
|
-
trigger?: string
|
|
72
|
+
trigger?: string;
|
|
75
73
|
/**
|
|
76
74
|
* The ref for the element which the popover positions itself with respect to.
|
|
77
75
|
* Required when used standalone (not within a trigger component).
|
|
78
76
|
*/
|
|
79
|
-
triggerRef?: () => Element | null
|
|
77
|
+
triggerRef?: () => Element | null;
|
|
80
78
|
/**
|
|
81
79
|
* The placement of the element with respect to its anchor element.
|
|
82
80
|
* @default 'bottom'
|
|
83
81
|
*/
|
|
84
|
-
placement?: Placement
|
|
82
|
+
placement?: Placement;
|
|
85
83
|
/**
|
|
86
84
|
* The placement padding that should be applied between the element and its
|
|
87
85
|
* surrounding container.
|
|
88
86
|
* @default 12
|
|
89
87
|
*/
|
|
90
|
-
containerPadding?: number
|
|
88
|
+
containerPadding?: number;
|
|
91
89
|
/**
|
|
92
90
|
* The additional offset applied along the main axis between the element and its
|
|
93
91
|
* anchor element.
|
|
94
92
|
* @default 8
|
|
95
93
|
*/
|
|
96
|
-
offset?: number
|
|
94
|
+
offset?: number;
|
|
97
95
|
/**
|
|
98
96
|
* The additional offset applied along the cross axis between the element and its
|
|
99
97
|
* anchor element.
|
|
100
98
|
* @default 0
|
|
101
99
|
*/
|
|
102
|
-
crossOffset?: number
|
|
100
|
+
crossOffset?: number;
|
|
103
101
|
/**
|
|
104
102
|
* Whether the element should flip its orientation when there is insufficient room.
|
|
105
103
|
* @default true
|
|
106
104
|
*/
|
|
107
|
-
shouldFlip?: boolean
|
|
105
|
+
shouldFlip?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* The max height of the popover.
|
|
108
|
+
*/
|
|
109
|
+
maxHeight?: number;
|
|
110
|
+
/**
|
|
111
|
+
* A boundary element for placement calculations.
|
|
112
|
+
*/
|
|
113
|
+
boundaryElement?: Element;
|
|
114
|
+
/**
|
|
115
|
+
* A ref for the popover arrow element.
|
|
116
|
+
*/
|
|
117
|
+
arrowRef?: () => Element | null;
|
|
118
|
+
/**
|
|
119
|
+
* A ref for the scrollable popover element.
|
|
120
|
+
*/
|
|
121
|
+
scrollRef?: () => Element | null;
|
|
108
122
|
/**
|
|
109
123
|
* Whether the popover is non-modal (allows interaction outside).
|
|
110
124
|
*/
|
|
111
|
-
isNonModal?: boolean
|
|
125
|
+
isNonModal?: boolean;
|
|
112
126
|
/**
|
|
113
127
|
* Whether pressing Escape to close should be disabled.
|
|
114
128
|
*/
|
|
115
|
-
isKeyboardDismissDisabled?: boolean
|
|
129
|
+
isKeyboardDismissDisabled?: boolean;
|
|
116
130
|
/**
|
|
117
131
|
* Filter for which outside interactions should close the popover.
|
|
118
132
|
*/
|
|
119
|
-
shouldCloseOnInteractOutside?: (element: Element) => boolean
|
|
133
|
+
shouldCloseOnInteractOutside?: (element: Element) => boolean;
|
|
120
134
|
/** Whether the popover is open (controlled). */
|
|
121
|
-
isOpen?: boolean
|
|
135
|
+
isOpen?: boolean;
|
|
122
136
|
/** Whether the popover opens by default (uncontrolled). */
|
|
123
|
-
defaultOpen?: boolean
|
|
137
|
+
defaultOpen?: boolean;
|
|
124
138
|
/** Handler called when the popover's open state changes. */
|
|
125
|
-
onOpenChange?: (isOpen: boolean) => void
|
|
139
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
140
|
+
/**
|
|
141
|
+
* Whether focus should move to the popover container on open.
|
|
142
|
+
* @default true
|
|
143
|
+
*/
|
|
144
|
+
autoFocus?: boolean;
|
|
126
145
|
/** Whether the popover is entering (for animations). */
|
|
127
|
-
isEntering?: boolean
|
|
146
|
+
isEntering?: boolean;
|
|
128
147
|
/** Whether the popover is exiting (for animations). */
|
|
129
|
-
isExiting?: boolean
|
|
148
|
+
isExiting?: boolean;
|
|
130
149
|
}
|
|
131
150
|
|
|
132
151
|
export interface PopoverTriggerProps {
|
|
133
152
|
/** The children - should include a trigger and popover content. */
|
|
134
|
-
children: JSX.Element
|
|
153
|
+
children: JSX.Element;
|
|
135
154
|
/** Whether the popover is open (controlled). */
|
|
136
|
-
isOpen?: boolean
|
|
155
|
+
isOpen?: boolean;
|
|
137
156
|
/** Whether the popover is open by default (uncontrolled). */
|
|
138
|
-
defaultOpen?: boolean
|
|
157
|
+
defaultOpen?: boolean;
|
|
139
158
|
/** Callback when open state changes. */
|
|
140
|
-
onOpenChange?: (isOpen: boolean) => void
|
|
159
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
141
160
|
}
|
|
142
161
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
export { PopoverTriggerContext, usePopoverTrigger, type PopoverTriggerContextValue } from './contexts'
|
|
162
|
+
export {
|
|
163
|
+
PopoverTriggerContext,
|
|
164
|
+
usePopoverTrigger,
|
|
165
|
+
type PopoverTriggerContextValue,
|
|
166
|
+
} from "./contexts";
|
|
149
167
|
|
|
150
168
|
interface PopoverContextValue {
|
|
151
|
-
placement: () => PlacementAxis | null
|
|
152
|
-
arrowProps: () => JSX.HTMLAttributes<HTMLElement
|
|
169
|
+
placement: () => PlacementAxis | null;
|
|
170
|
+
arrowProps: () => JSX.HTMLAttributes<HTMLElement>;
|
|
153
171
|
}
|
|
154
172
|
|
|
155
|
-
|
|
156
|
-
|
|
173
|
+
export const PopoverContext = createContext<PopoverContextValue | null>(null);
|
|
174
|
+
const PopoverGroupContext = createContext<(() => HTMLElement | null) | null>(null);
|
|
157
175
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
176
|
+
function PopoverDismissButton(props: { onDismiss: () => void }): JSX.Element {
|
|
177
|
+
return (
|
|
178
|
+
<button
|
|
179
|
+
type="button"
|
|
180
|
+
aria-label="Dismiss"
|
|
181
|
+
tabIndex={-1}
|
|
182
|
+
onClick={props.onDismiss}
|
|
183
|
+
style={visuallyHiddenStyles}
|
|
184
|
+
/>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
161
187
|
|
|
162
188
|
/**
|
|
163
189
|
* A PopoverTrigger opens a popover when a trigger element is pressed.
|
|
164
190
|
* Children should include a trigger element (e.g. Button) and the Popover.
|
|
165
191
|
*/
|
|
166
192
|
export function PopoverTrigger(props: PopoverTriggerProps): JSX.Element {
|
|
167
|
-
const [local] = splitProps(props, [
|
|
193
|
+
const [local] = splitProps(props, ["isOpen", "defaultOpen", "onOpenChange"]);
|
|
168
194
|
|
|
169
|
-
// Create overlay trigger state
|
|
170
195
|
const state = createOverlayTriggerState({
|
|
171
196
|
get isOpen() {
|
|
172
|
-
return local.isOpen
|
|
197
|
+
return local.isOpen;
|
|
173
198
|
},
|
|
174
199
|
get defaultOpen() {
|
|
175
|
-
return local.defaultOpen
|
|
200
|
+
return local.defaultOpen;
|
|
176
201
|
},
|
|
177
202
|
onOpenChange: local.onOpenChange,
|
|
178
|
-
})
|
|
203
|
+
});
|
|
179
204
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const triggerId = createUniqueId()
|
|
205
|
+
let triggerRef: HTMLElement | null = null;
|
|
206
|
+
const triggerId = createUniqueId();
|
|
183
207
|
|
|
184
|
-
|
|
185
|
-
createOverlayTrigger(
|
|
186
|
-
{ type: 'dialog' },
|
|
187
|
-
state,
|
|
188
|
-
() => triggerRef
|
|
189
|
-
)
|
|
208
|
+
const triggerAria = createOverlayTrigger({ type: "dialog" }, state, () => triggerRef);
|
|
190
209
|
|
|
191
|
-
// Context value
|
|
192
210
|
const contextValue = createMemo(() => ({
|
|
193
211
|
state: {
|
|
194
212
|
isOpen: () => state.isOpen(),
|
|
@@ -198,299 +216,434 @@ export function PopoverTrigger(props: PopoverTriggerProps): JSX.Element {
|
|
|
198
216
|
},
|
|
199
217
|
triggerRef: () => triggerRef,
|
|
200
218
|
setTriggerRef: (el: HTMLElement | null) => {
|
|
201
|
-
if (!el) return
|
|
219
|
+
if (!el) return;
|
|
202
220
|
if (!triggerRef || !triggerRef.isConnected) {
|
|
203
|
-
triggerRef = el
|
|
221
|
+
triggerRef = el;
|
|
204
222
|
}
|
|
205
223
|
},
|
|
206
224
|
triggerId,
|
|
207
|
-
|
|
208
|
-
|
|
225
|
+
triggerProps: triggerAria.triggerProps,
|
|
226
|
+
overlayProps: triggerAria.overlayProps,
|
|
227
|
+
trigger: "PopoverTrigger",
|
|
228
|
+
}));
|
|
209
229
|
|
|
210
230
|
return (
|
|
211
231
|
<PopoverTriggerContext.Provider value={contextValue()}>
|
|
212
232
|
{props.children}
|
|
213
233
|
</PopoverTriggerContext.Provider>
|
|
214
|
-
)
|
|
234
|
+
);
|
|
215
235
|
}
|
|
216
236
|
|
|
217
|
-
// ============================================
|
|
218
|
-
// POPOVER COMPONENT
|
|
219
|
-
// ============================================
|
|
220
|
-
|
|
221
237
|
/**
|
|
222
238
|
* A popover is an overlay element positioned relative to a trigger.
|
|
223
239
|
*/
|
|
224
240
|
export function Popover(props: PopoverProps): JSX.Element {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
241
|
+
// Note: do NOT early-return on the server. Returning `null` on the server and a
|
|
242
|
+
// full <Show>/<Portal> tree on the client desyncs Solid's hydration walk (the
|
|
243
|
+
// server emits no marker for the <Show>), which surfaces as "Hydration Mismatch /
|
|
244
|
+
// getNextElement" in the parent (e.g. Picker). Instead, run the same structure on
|
|
245
|
+
// both and gate the Portal on `useIsHydrated()` so the overlay only mounts on the
|
|
246
|
+
// client after hydration — the server + first client render both produce an empty
|
|
247
|
+
// <Show> marker, so hydration aligns.
|
|
230
248
|
const [local, rest] = splitProps(props, [
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const [
|
|
257
|
-
|
|
258
|
-
//
|
|
249
|
+
"class",
|
|
250
|
+
"style",
|
|
251
|
+
"trigger",
|
|
252
|
+
"triggerRef",
|
|
253
|
+
"placement",
|
|
254
|
+
"containerPadding",
|
|
255
|
+
"offset",
|
|
256
|
+
"crossOffset",
|
|
257
|
+
"shouldFlip",
|
|
258
|
+
"maxHeight",
|
|
259
|
+
"boundaryElement",
|
|
260
|
+
"arrowRef",
|
|
261
|
+
"scrollRef",
|
|
262
|
+
"isNonModal",
|
|
263
|
+
"isKeyboardDismissDisabled",
|
|
264
|
+
"shouldCloseOnInteractOutside",
|
|
265
|
+
"isOpen",
|
|
266
|
+
"defaultOpen",
|
|
267
|
+
"onOpenChange",
|
|
268
|
+
"autoFocus",
|
|
269
|
+
"isEntering",
|
|
270
|
+
"isExiting",
|
|
271
|
+
]);
|
|
272
|
+
|
|
273
|
+
let popoverRef!: HTMLDivElement;
|
|
274
|
+
const [groupRef, setGroupRef] = createSignal<HTMLDivElement | null>(null);
|
|
275
|
+
// False on the server and during hydration; true after onMount. Gates the Portal
|
|
276
|
+
// so overlay content only ever renders client-side, post-hydration.
|
|
277
|
+
const isHydrated = useIsHydrated();
|
|
278
|
+
|
|
279
|
+
const triggerContext = useContext(PopoverTriggerContext);
|
|
280
|
+
const dialogTriggerContext = useContext(DialogTriggerContext);
|
|
281
|
+
const popoverGroupContext = useContext(PopoverGroupContext);
|
|
282
|
+
const resolvedTrigger = () =>
|
|
283
|
+
local.trigger ??
|
|
284
|
+
triggerContext?.trigger ??
|
|
285
|
+
(dialogTriggerContext ? "DialogTrigger" : undefined);
|
|
286
|
+
const isSubPopover = () => resolvedTrigger() === "SubmenuTrigger" && popoverGroupContext != null;
|
|
287
|
+
|
|
288
|
+
const [internalOpen, setInternalOpen] = createSignal(local.defaultOpen ?? false);
|
|
289
|
+
|
|
259
290
|
const isOpen = (): boolean => {
|
|
260
|
-
if (local.isOpen !== undefined) return local.isOpen
|
|
291
|
+
if (local.isOpen !== undefined) return local.isOpen;
|
|
261
292
|
if (triggerContext) {
|
|
262
|
-
return triggerContext.state.isOpen()
|
|
293
|
+
return triggerContext.state.isOpen();
|
|
263
294
|
}
|
|
264
|
-
|
|
265
|
-
|
|
295
|
+
if (dialogTriggerContext) {
|
|
296
|
+
return dialogTriggerContext.state.isOpen();
|
|
297
|
+
}
|
|
298
|
+
return internalOpen();
|
|
299
|
+
};
|
|
266
300
|
|
|
267
301
|
const close = () => {
|
|
268
302
|
if (local.isOpen !== undefined) {
|
|
269
|
-
local.onOpenChange?.(false)
|
|
303
|
+
local.onOpenChange?.(false);
|
|
270
304
|
} else if (triggerContext) {
|
|
271
|
-
triggerContext.state.close()
|
|
272
|
-
local.onOpenChange?.(false)
|
|
305
|
+
triggerContext.state.close();
|
|
306
|
+
local.onOpenChange?.(false);
|
|
307
|
+
} else if (dialogTriggerContext) {
|
|
308
|
+
dialogTriggerContext.state.close();
|
|
309
|
+
local.onOpenChange?.(false);
|
|
273
310
|
} else {
|
|
274
|
-
setInternalOpen(false)
|
|
275
|
-
local.onOpenChange?.(false)
|
|
311
|
+
setInternalOpen(false);
|
|
312
|
+
local.onOpenChange?.(false);
|
|
276
313
|
}
|
|
277
|
-
}
|
|
314
|
+
};
|
|
278
315
|
|
|
279
|
-
// Get trigger ref
|
|
280
316
|
const getTriggerRef = () => {
|
|
281
|
-
if (local.triggerRef) return local.triggerRef()
|
|
282
|
-
if (triggerContext) return triggerContext.triggerRef()
|
|
283
|
-
return
|
|
284
|
-
|
|
317
|
+
if (local.triggerRef) return local.triggerRef();
|
|
318
|
+
if (triggerContext) return triggerContext.triggerRef();
|
|
319
|
+
if (dialogTriggerContext) return dialogTriggerContext.triggerRef();
|
|
320
|
+
return null;
|
|
321
|
+
};
|
|
285
322
|
|
|
286
323
|
const popoverAria = createPopover(
|
|
287
324
|
{
|
|
288
325
|
triggerRef: getTriggerRef,
|
|
289
326
|
popoverRef: () => popoverRef ?? null,
|
|
327
|
+
groupRef: () => (isSubPopover() ? (popoverGroupContext?.() ?? null) : groupRef()),
|
|
290
328
|
get placement() {
|
|
291
|
-
return local.placement
|
|
329
|
+
return local.placement;
|
|
292
330
|
},
|
|
293
331
|
get containerPadding() {
|
|
294
|
-
return local.containerPadding
|
|
332
|
+
return local.containerPadding;
|
|
295
333
|
},
|
|
296
334
|
get offset() {
|
|
297
|
-
return local.offset ?? 8
|
|
335
|
+
return local.offset ?? 8;
|
|
298
336
|
},
|
|
299
337
|
get crossOffset() {
|
|
300
|
-
return local.crossOffset
|
|
338
|
+
return local.crossOffset;
|
|
301
339
|
},
|
|
302
340
|
get shouldFlip() {
|
|
303
|
-
return local.shouldFlip
|
|
341
|
+
return local.shouldFlip;
|
|
342
|
+
},
|
|
343
|
+
get maxHeight() {
|
|
344
|
+
return local.maxHeight;
|
|
345
|
+
},
|
|
346
|
+
get boundaryElement() {
|
|
347
|
+
return local.boundaryElement;
|
|
348
|
+
},
|
|
349
|
+
get arrowRef() {
|
|
350
|
+
return local.arrowRef;
|
|
351
|
+
},
|
|
352
|
+
get scrollRef() {
|
|
353
|
+
return local.scrollRef;
|
|
304
354
|
},
|
|
305
355
|
get isNonModal() {
|
|
306
|
-
return local.isNonModal
|
|
356
|
+
return local.isNonModal;
|
|
307
357
|
},
|
|
308
358
|
get isKeyboardDismissDisabled() {
|
|
309
|
-
return local.isKeyboardDismissDisabled
|
|
359
|
+
return local.isKeyboardDismissDisabled;
|
|
310
360
|
},
|
|
311
361
|
get shouldCloseOnInteractOutside() {
|
|
312
|
-
return local.shouldCloseOnInteractOutside
|
|
362
|
+
return local.shouldCloseOnInteractOutside;
|
|
313
363
|
},
|
|
314
364
|
get trigger() {
|
|
315
|
-
return
|
|
365
|
+
return resolvedTrigger();
|
|
316
366
|
},
|
|
317
367
|
},
|
|
318
368
|
{
|
|
319
369
|
isOpen,
|
|
320
370
|
open: () => {
|
|
321
371
|
if (local.isOpen !== undefined) {
|
|
322
|
-
local.onOpenChange?.(true)
|
|
372
|
+
local.onOpenChange?.(true);
|
|
323
373
|
} else if (triggerContext) {
|
|
324
|
-
triggerContext.state.open()
|
|
325
|
-
local.onOpenChange?.(true)
|
|
374
|
+
triggerContext.state.open();
|
|
375
|
+
local.onOpenChange?.(true);
|
|
376
|
+
} else if (dialogTriggerContext) {
|
|
377
|
+
dialogTriggerContext.state.open();
|
|
378
|
+
local.onOpenChange?.(true);
|
|
326
379
|
} else {
|
|
327
|
-
setInternalOpen(true)
|
|
328
|
-
local.onOpenChange?.(true)
|
|
380
|
+
setInternalOpen(true);
|
|
381
|
+
local.onOpenChange?.(true);
|
|
329
382
|
}
|
|
330
383
|
},
|
|
331
384
|
close,
|
|
332
385
|
toggle: () => {
|
|
333
|
-
if (isOpen()) close()
|
|
386
|
+
if (isOpen()) close();
|
|
334
387
|
else if (local.isOpen !== undefined) {
|
|
335
|
-
local.onOpenChange?.(true)
|
|
388
|
+
local.onOpenChange?.(true);
|
|
336
389
|
} else if (triggerContext) {
|
|
337
|
-
triggerContext.state.toggle()
|
|
390
|
+
triggerContext.state.toggle();
|
|
391
|
+
} else if (dialogTriggerContext) {
|
|
392
|
+
dialogTriggerContext.state.toggle();
|
|
338
393
|
} else {
|
|
339
|
-
setInternalOpen(true)
|
|
340
|
-
local.onOpenChange?.(true)
|
|
394
|
+
setInternalOpen(true);
|
|
395
|
+
local.onOpenChange?.(true);
|
|
341
396
|
}
|
|
342
397
|
},
|
|
343
|
-
}
|
|
344
|
-
)
|
|
398
|
+
},
|
|
399
|
+
);
|
|
345
400
|
|
|
346
|
-
// Render props values
|
|
347
401
|
const renderValues = createMemo<PopoverRenderProps>(() => ({
|
|
348
|
-
trigger:
|
|
402
|
+
trigger: resolvedTrigger() ?? null,
|
|
349
403
|
placement: popoverAria.placement(),
|
|
350
404
|
isEntering: local.isEntering ?? false,
|
|
351
405
|
isExiting: local.isExiting ?? false,
|
|
352
|
-
}))
|
|
406
|
+
}));
|
|
353
407
|
|
|
354
|
-
// Resolve render props
|
|
355
408
|
const renderProps = useRenderProps(
|
|
356
409
|
{
|
|
357
410
|
children: props.children,
|
|
358
411
|
class: local.class,
|
|
359
412
|
style: local.style,
|
|
360
|
-
defaultClassName:
|
|
413
|
+
defaultClassName: "solidaria-Popover",
|
|
361
414
|
},
|
|
362
|
-
renderValues
|
|
363
|
-
)
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const
|
|
415
|
+
renderValues,
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
const [triggerWidth, setTriggerWidth] = createSignal<string | undefined>();
|
|
419
|
+
const hasExplicitTriggerWidth = () => {
|
|
420
|
+
const style = renderProps.style() as (JSX.CSSProperties & Record<string, unknown>) | undefined;
|
|
421
|
+
return style?.["--trigger-width"] != null;
|
|
422
|
+
};
|
|
423
|
+
const updateTriggerWidth = () => {
|
|
424
|
+
const trigger = getTriggerRef();
|
|
425
|
+
if (!trigger || hasExplicitTriggerWidth()) return;
|
|
426
|
+
setTriggerWidth(`${trigger.getBoundingClientRect().width}px`);
|
|
427
|
+
};
|
|
428
|
+
createEffect(() => {
|
|
429
|
+
if (!isOpen()) return;
|
|
430
|
+
updateTriggerWidth();
|
|
431
|
+
|
|
432
|
+
const trigger = getTriggerRef();
|
|
433
|
+
if (!trigger || hasExplicitTriggerWidth() || typeof ResizeObserver === "undefined") return;
|
|
434
|
+
|
|
435
|
+
const observer = new ResizeObserver(updateTriggerWidth);
|
|
436
|
+
observer.observe(trigger);
|
|
437
|
+
onCleanup(() => observer.disconnect());
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const domProps = createMemo(() =>
|
|
441
|
+
filterDOMProps(rest as Record<string, unknown>, { global: true }),
|
|
442
|
+
);
|
|
443
|
+
const overlayId = () => {
|
|
444
|
+
const restId = (rest as Record<string, unknown>).id as string | undefined;
|
|
445
|
+
return (
|
|
446
|
+
restId ??
|
|
447
|
+
(triggerContext?.overlayProps?.id as string | undefined) ??
|
|
448
|
+
(dialogTriggerContext?.overlayProps?.id as string | undefined)
|
|
449
|
+
);
|
|
450
|
+
};
|
|
367
451
|
|
|
368
|
-
// Remove style/ref from spread props to avoid collisions
|
|
369
452
|
const cleanPopoverProps = () => {
|
|
370
|
-
const {
|
|
371
|
-
|
|
372
|
-
|
|
453
|
+
const {
|
|
454
|
+
style: _style,
|
|
455
|
+
ref: _ref,
|
|
456
|
+
...remaining
|
|
457
|
+
} = popoverAria.popoverProps as Record<string, unknown>;
|
|
458
|
+
return remaining;
|
|
459
|
+
};
|
|
373
460
|
|
|
374
461
|
const mergedStyle = (): JSX.CSSProperties => {
|
|
375
|
-
const ariaStyle = (popoverAria.popoverProps as Record<string, unknown>).style as
|
|
376
|
-
|
|
462
|
+
const ariaStyle = (popoverAria.popoverProps as Record<string, unknown>).style as
|
|
463
|
+
| JSX.CSSProperties
|
|
464
|
+
| undefined;
|
|
465
|
+
const renderStyle = (renderProps.style() || {}) as JSX.CSSProperties & Record<string, unknown>;
|
|
377
466
|
return {
|
|
378
|
-
...
|
|
467
|
+
...ariaStyle,
|
|
379
468
|
...renderStyle,
|
|
469
|
+
"--trigger-width": renderStyle["--trigger-width"] ?? triggerWidth(),
|
|
470
|
+
};
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const shouldBeDialog = () => !local.isNonModal || resolvedTrigger() === "SubmenuTrigger";
|
|
474
|
+
const portalContext = useUNSAFE_PortalContext();
|
|
475
|
+
const portalContainer = () => {
|
|
476
|
+
if (isSubPopover()) {
|
|
477
|
+
return popoverGroupContext?.() ?? portalContext.getContainer?.() ?? undefined;
|
|
380
478
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
// Check if we should render with dialog role
|
|
384
|
-
const shouldBeDialog = () => !local.isNonModal
|
|
385
|
-
const portalContext = useUNSAFE_PortalContext()
|
|
386
|
-
const portalContainer = () => portalContext.getContainer?.() ?? undefined
|
|
479
|
+
return portalContext.getContainer?.() ?? undefined;
|
|
480
|
+
};
|
|
387
481
|
|
|
388
|
-
//
|
|
482
|
+
// Match React Aria Components: focus the popover container only when no
|
|
483
|
+
// descendant has already moved focus during mount.
|
|
389
484
|
createEffect(() => {
|
|
390
|
-
if (!isOpen() || !shouldBeDialog()) return
|
|
391
|
-
if (
|
|
392
|
-
if (
|
|
393
|
-
|
|
485
|
+
if (!isOpen() || !shouldBeDialog()) return;
|
|
486
|
+
if ((local.autoFocus ?? true) === false) return;
|
|
487
|
+
if (!popoverRef) return;
|
|
488
|
+
if (resolvedTrigger() === "SubmenuTrigger") return;
|
|
489
|
+
|
|
490
|
+
let timeout: number | undefined;
|
|
491
|
+
let frame: number | undefined;
|
|
492
|
+
|
|
493
|
+
const focusIfNeeded = () => {
|
|
494
|
+
if (!isOpen() || !shouldBeDialog()) return;
|
|
495
|
+
if (!popoverRef || resolvedTrigger() === "SubmenuTrigger") return;
|
|
496
|
+
if (document.activeElement === popoverRef || popoverRef.contains(document.activeElement)) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
popoverRef.focus();
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
const scheduleFocus = () => {
|
|
503
|
+
timeout = window.setTimeout(focusIfNeeded, 0);
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
if (typeof window.requestAnimationFrame === "function") {
|
|
507
|
+
frame = window.requestAnimationFrame(scheduleFocus);
|
|
508
|
+
} else {
|
|
509
|
+
scheduleFocus();
|
|
394
510
|
}
|
|
395
|
-
|
|
511
|
+
|
|
512
|
+
onCleanup(() => {
|
|
513
|
+
if (frame !== undefined) {
|
|
514
|
+
window.cancelAnimationFrame(frame);
|
|
515
|
+
}
|
|
516
|
+
if (timeout !== undefined) {
|
|
517
|
+
window.clearTimeout(timeout);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
});
|
|
396
521
|
|
|
397
522
|
// Fallback Escape handling for environments where focus is not moved into the popover.
|
|
398
523
|
createEffect(() => {
|
|
399
|
-
if (!isOpen()) return
|
|
400
|
-
if (local.isKeyboardDismissDisabled) return
|
|
524
|
+
if (!isOpen()) return;
|
|
525
|
+
if (local.isKeyboardDismissDisabled) return;
|
|
401
526
|
|
|
402
527
|
const onKeyDown = (event: KeyboardEvent) => {
|
|
403
|
-
if (event.key !==
|
|
404
|
-
if (event.defaultPrevented) return
|
|
405
|
-
close()
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
document.addEventListener(
|
|
409
|
-
onCleanup(() => document.removeEventListener(
|
|
410
|
-
})
|
|
528
|
+
if (event.key !== "Escape") return;
|
|
529
|
+
if (event.defaultPrevented) return;
|
|
530
|
+
close();
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
document.addEventListener("keydown", onKeyDown);
|
|
534
|
+
onCleanup(() => document.removeEventListener("keydown", onKeyDown));
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
const overlay = () => (
|
|
538
|
+
<PopoverContext.Provider
|
|
539
|
+
value={{ placement: popoverAria.placement, arrowProps: () => popoverAria.arrowProps }}
|
|
540
|
+
>
|
|
541
|
+
<FocusScope contain={shouldBeDialog()} restoreFocus>
|
|
542
|
+
<div
|
|
543
|
+
{...domProps()}
|
|
544
|
+
{...cleanPopoverProps()}
|
|
545
|
+
ref={popoverRef}
|
|
546
|
+
id={overlayId()}
|
|
547
|
+
role={shouldBeDialog() ? "dialog" : undefined}
|
|
548
|
+
tabIndex={shouldBeDialog() ? -1 : undefined}
|
|
549
|
+
class={renderProps.class()}
|
|
550
|
+
style={mergedStyle()}
|
|
551
|
+
data-trigger={resolvedTrigger()}
|
|
552
|
+
data-placement={popoverAria.placement()}
|
|
553
|
+
data-entering={dataAttr(local.isEntering)}
|
|
554
|
+
data-exiting={dataAttr(local.isExiting)}
|
|
555
|
+
>
|
|
556
|
+
<Show when={!local.isNonModal}>
|
|
557
|
+
<PopoverDismissButton onDismiss={close} />
|
|
558
|
+
</Show>
|
|
559
|
+
{renderProps.renderChildren()}
|
|
560
|
+
<PopoverDismissButton onDismiss={close} />
|
|
561
|
+
</div>
|
|
562
|
+
</FocusScope>
|
|
563
|
+
</PopoverContext.Provider>
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
const underlay = () => (
|
|
567
|
+
<div
|
|
568
|
+
data-testid="underlay"
|
|
569
|
+
{...(popoverAria.underlayProps as unknown as JSX.HTMLAttributes<HTMLDivElement>)}
|
|
570
|
+
style={{ position: "fixed", inset: 0 }}
|
|
571
|
+
/>
|
|
572
|
+
);
|
|
411
573
|
|
|
412
574
|
return (
|
|
413
|
-
<Show when={isOpen() || local.isExiting}>
|
|
575
|
+
<Show when={isHydrated() && (isOpen() || local.isExiting)}>
|
|
414
576
|
<Portal mount={portalContainer()}>
|
|
415
|
-
<
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
class={renderProps.class()}
|
|
424
|
-
style={mergedStyle()}
|
|
425
|
-
data-trigger={local.trigger ?? triggerContext?.trigger}
|
|
426
|
-
data-placement={popoverAria.placement()}
|
|
427
|
-
data-entering={dataAttr(local.isEntering)}
|
|
428
|
-
data-exiting={dataAttr(local.isExiting)}
|
|
429
|
-
>
|
|
430
|
-
{renderProps.renderChildren()}
|
|
577
|
+
<Show when={!local.isNonModal && !isSubPopover() && isOpen()}>{underlay()}</Show>
|
|
578
|
+
<Show
|
|
579
|
+
when={isSubPopover()}
|
|
580
|
+
fallback={
|
|
581
|
+
<div ref={setGroupRef} style={{ display: "contents" }}>
|
|
582
|
+
<PopoverGroupContext.Provider value={() => groupRef()}>
|
|
583
|
+
{overlay()}
|
|
584
|
+
</PopoverGroupContext.Provider>
|
|
431
585
|
</div>
|
|
432
|
-
|
|
433
|
-
|
|
586
|
+
}
|
|
587
|
+
>
|
|
588
|
+
{overlay()}
|
|
589
|
+
</Show>
|
|
434
590
|
</Portal>
|
|
435
591
|
</Show>
|
|
436
|
-
)
|
|
592
|
+
);
|
|
437
593
|
}
|
|
438
594
|
|
|
439
|
-
// ============================================
|
|
440
|
-
// OVERLAY ARROW COMPONENT
|
|
441
|
-
// ============================================
|
|
442
|
-
|
|
443
595
|
export interface OverlayArrowProps {
|
|
444
596
|
/** The children - should be an SVG or element for the arrow. */
|
|
445
|
-
children?: JSX.Element
|
|
597
|
+
children?: JSX.Element;
|
|
598
|
+
/** Render function used when Solid children accessors would be ambiguous. */
|
|
599
|
+
render?: () => JSX.Element;
|
|
446
600
|
/** The CSS className. */
|
|
447
|
-
class?: string
|
|
601
|
+
class?: string;
|
|
448
602
|
/** The inline style. */
|
|
449
|
-
style?: JSX.CSSProperties
|
|
603
|
+
style?: JSX.CSSProperties;
|
|
450
604
|
}
|
|
451
605
|
|
|
452
606
|
/**
|
|
453
607
|
* An arrow element that points towards the trigger.
|
|
454
608
|
*/
|
|
455
609
|
export function OverlayArrow(props: OverlayArrowProps): JSX.Element {
|
|
456
|
-
const popoverContext = useContext(PopoverContext)
|
|
457
|
-
const placement = () => popoverContext?.placement() ?? null
|
|
458
|
-
|
|
459
|
-
const cleanArrowProps = () => {
|
|
460
|
-
const contextArrowProps = popoverContext?.arrowProps() as Record<string, unknown> | undefined
|
|
461
|
-
if (!contextArrowProps) return {}
|
|
462
|
-
const { style: _style, ref: _ref, ...rest } = contextArrowProps
|
|
463
|
-
return rest
|
|
464
|
-
}
|
|
610
|
+
const popoverContext = useContext(PopoverContext);
|
|
611
|
+
const placement = () => popoverContext?.placement() ?? null;
|
|
465
612
|
|
|
466
613
|
const mergedStyle = () => {
|
|
467
|
-
const contextStyle = (popoverContext?.arrowProps() as Record<string, unknown> | undefined)
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
614
|
+
const contextStyle = (popoverContext?.arrowProps() as Record<string, unknown> | undefined)
|
|
615
|
+
?.style as (JSX.CSSProperties & Record<string, unknown>) | undefined;
|
|
616
|
+
const style: JSX.CSSProperties = {};
|
|
617
|
+
if (typeof contextStyle?.left === "string") {
|
|
618
|
+
style.left = contextStyle.left;
|
|
471
619
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
const resolveChildren = () => {
|
|
475
|
-
const children = props.children
|
|
476
|
-
if (typeof children === 'function') {
|
|
477
|
-
return children(placement())
|
|
620
|
+
if (typeof contextStyle?.top === "string") {
|
|
621
|
+
style.top = contextStyle.top;
|
|
478
622
|
}
|
|
479
|
-
|
|
480
|
-
|
|
623
|
+
|
|
624
|
+
const localStyle =
|
|
625
|
+
props.style &&
|
|
626
|
+
!(typeof CSSStyleDeclaration !== "undefined" && props.style instanceof CSSStyleDeclaration)
|
|
627
|
+
? props.style
|
|
628
|
+
: undefined;
|
|
629
|
+
|
|
630
|
+
return {
|
|
631
|
+
...style,
|
|
632
|
+
...localStyle,
|
|
633
|
+
};
|
|
634
|
+
};
|
|
481
635
|
|
|
482
636
|
return (
|
|
483
637
|
<div
|
|
484
|
-
{...cleanArrowProps()}
|
|
485
638
|
class={props.class}
|
|
486
639
|
style={mergedStyle()}
|
|
487
640
|
data-placement={placement()}
|
|
488
641
|
aria-hidden="true"
|
|
489
642
|
role="presentation"
|
|
490
643
|
>
|
|
491
|
-
{
|
|
644
|
+
{props.render ? props.render() : props.children}
|
|
492
645
|
</div>
|
|
493
|
-
)
|
|
646
|
+
);
|
|
494
647
|
}
|
|
495
648
|
|
|
496
|
-
export default Popover
|
|
649
|
+
export default Popover;
|