@proyecto-viviana/solidaria-components 0.2.9 → 0.3.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/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 +23253 -18564
- package/dist/index.js.map +1 -1
- package/dist/index.jsx +18116 -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 +251 -176
- package/src/NumberField.tsx +139 -143
- package/src/Popover.tsx +396 -234
- 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 +216 -158
- 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 +49 -60
- package/src/virtualizer/Layout.ts +14 -22
- package/dist/index.ssr.js +0 -16996
- package/dist/index.ssr.js.map +0 -1
package/src/GridList.tsx
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
-
type Accessor,
|
|
13
12
|
type JSX,
|
|
14
13
|
createContext,
|
|
15
14
|
createEffect,
|
|
@@ -19,7 +18,8 @@ import {
|
|
|
19
18
|
splitProps,
|
|
20
19
|
useContext,
|
|
21
20
|
For,
|
|
22
|
-
|
|
21
|
+
Show,
|
|
22
|
+
} from "solid-js";
|
|
23
23
|
import {
|
|
24
24
|
createGridList,
|
|
25
25
|
createGridListItem,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
createHover,
|
|
29
29
|
mergeProps,
|
|
30
30
|
type AriaGridListProps,
|
|
31
|
-
} from
|
|
31
|
+
} from "@proyecto-viviana/solidaria";
|
|
32
32
|
import {
|
|
33
33
|
createGridState,
|
|
34
34
|
type GridState,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
type GridNode,
|
|
37
37
|
type Key,
|
|
38
38
|
type DropTarget,
|
|
39
|
-
} from
|
|
39
|
+
} from "@proyecto-viviana/solid-stately";
|
|
40
40
|
import {
|
|
41
41
|
type RenderChildren,
|
|
42
42
|
type ClassNameOrFunction,
|
|
@@ -44,27 +44,34 @@ import {
|
|
|
44
44
|
type SlotProps,
|
|
45
45
|
useRenderProps,
|
|
46
46
|
filterDOMProps,
|
|
47
|
-
} from
|
|
48
|
-
import { SharedElementTransition } from
|
|
49
|
-
import { type DragAndDropHooks } from
|
|
47
|
+
} from "./utils";
|
|
48
|
+
import { SharedElementTransition } from "./SharedElementTransition";
|
|
49
|
+
import { type DragAndDropHooks } from "./useDragAndDrop";
|
|
50
50
|
import {
|
|
51
51
|
CollectionRendererContext,
|
|
52
52
|
type CollectionRendererContextValue,
|
|
53
53
|
Section,
|
|
54
54
|
type SectionProps,
|
|
55
55
|
useCollectionRenderer,
|
|
56
|
-
} from
|
|
57
|
-
import { useVirtualizerContext } from
|
|
56
|
+
} from "./Collection";
|
|
57
|
+
import { useVirtualizerContext } from "./Virtualizer";
|
|
58
58
|
import {
|
|
59
59
|
getNormalizedDropTargetKey,
|
|
60
60
|
mergePersistedKeysIntoVirtualRange,
|
|
61
61
|
useDndPersistedKeys,
|
|
62
62
|
useRenderDropIndicator,
|
|
63
|
-
} from
|
|
63
|
+
} from "./DragAndDrop";
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
type RefLike<T> = ((el: T) => void) | { current?: T | null } | undefined;
|
|
66
|
+
|
|
67
|
+
function assignRef<T>(ref: RefLike<T>, el: T): void {
|
|
68
|
+
if (!ref) return;
|
|
69
|
+
if (typeof ref === "function") {
|
|
70
|
+
ref(el);
|
|
71
|
+
} else {
|
|
72
|
+
ref.current = el;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
68
75
|
|
|
69
76
|
export interface GridListRenderProps {
|
|
70
77
|
/** Whether the grid list has focus. */
|
|
@@ -77,7 +84,8 @@ export interface GridListRenderProps {
|
|
|
77
84
|
isEmpty: boolean;
|
|
78
85
|
}
|
|
79
86
|
|
|
80
|
-
export interface GridListProps<T extends object>
|
|
87
|
+
export interface GridListProps<T extends object>
|
|
88
|
+
extends Omit<AriaGridListProps, "children">, SlotProps {
|
|
81
89
|
/** The items to render in the grid list. */
|
|
82
90
|
items: T[];
|
|
83
91
|
/** Function to get the key from an item. */
|
|
@@ -87,21 +95,25 @@ export interface GridListProps<T extends object> extends Omit<AriaGridListProps,
|
|
|
87
95
|
/** Function to check if an item is disabled. */
|
|
88
96
|
getDisabled?: (item: T) => boolean;
|
|
89
97
|
/** The selection mode. */
|
|
90
|
-
selectionMode?:
|
|
98
|
+
selectionMode?: "none" | "single" | "multiple";
|
|
99
|
+
/** How selection should behave when pressing an item. */
|
|
100
|
+
selectionBehavior?: "replace" | "toggle";
|
|
91
101
|
/** Keys of disabled items. */
|
|
92
102
|
disabledKeys?: Iterable<Key>;
|
|
93
103
|
/** Currently selected keys (controlled). */
|
|
94
|
-
selectedKeys?:
|
|
104
|
+
selectedKeys?: "all" | Iterable<Key>;
|
|
95
105
|
/** Default selected keys (uncontrolled). */
|
|
96
|
-
defaultSelectedKeys?:
|
|
106
|
+
defaultSelectedKeys?: "all" | Iterable<Key>;
|
|
97
107
|
/** Handler called when selection changes. */
|
|
98
|
-
onSelectionChange?: (keys:
|
|
108
|
+
onSelectionChange?: (keys: "all" | Set<Key>) => void;
|
|
99
109
|
/** The children of the component. A function may be provided to render each item. */
|
|
100
110
|
children: (item: T) => JSX.Element;
|
|
101
111
|
/** The CSS className for the element. */
|
|
102
112
|
class?: ClassNameOrFunction<GridListRenderProps>;
|
|
103
113
|
/** The inline style for the element. */
|
|
104
114
|
style?: StyleOrFunction<GridListRenderProps>;
|
|
115
|
+
/** Ref for the grid list root element. */
|
|
116
|
+
ref?: RefLike<HTMLDivElement>;
|
|
105
117
|
/** A function to render when the grid list is empty. */
|
|
106
118
|
renderEmptyState?: () => JSX.Element;
|
|
107
119
|
/** Whether there are more items to load. */
|
|
@@ -127,9 +139,16 @@ export interface GridListItemRenderProps {
|
|
|
127
139
|
isHovered: boolean;
|
|
128
140
|
/** Whether the item is disabled. */
|
|
129
141
|
isDisabled: boolean;
|
|
142
|
+
/** The grid list selection mode. */
|
|
143
|
+
selectionMode: "none" | "single" | "multiple";
|
|
144
|
+
/** How selection behaves when pressing an item. */
|
|
145
|
+
selectionBehavior: "replace" | "toggle";
|
|
130
146
|
}
|
|
131
147
|
|
|
132
|
-
export interface GridListItemProps<T extends object>
|
|
148
|
+
export interface GridListItemProps<T extends object>
|
|
149
|
+
extends
|
|
150
|
+
SlotProps,
|
|
151
|
+
Omit<JSX.HTMLAttributes<HTMLDivElement>, "class" | "style" | "children" | "id" | "ref"> {
|
|
133
152
|
/** The unique key for the item. */
|
|
134
153
|
id: Key;
|
|
135
154
|
/** The item value. */
|
|
@@ -144,11 +163,15 @@ export interface GridListItemProps<T extends object> extends SlotProps, Omit<JSX
|
|
|
144
163
|
textValue?: string;
|
|
145
164
|
/** Handler called when the item is activated. */
|
|
146
165
|
onAction?: () => void;
|
|
166
|
+
/** Ref for the rendered row element. */
|
|
167
|
+
ref?: RefLike<HTMLDivElement>;
|
|
147
168
|
}
|
|
148
169
|
|
|
149
170
|
export interface GridListLoadMoreItemProps extends SlotProps {
|
|
150
171
|
onLoadMore: () => void | Promise<void>;
|
|
151
172
|
isLoading?: boolean;
|
|
173
|
+
/** Scroll offset multiplier for early loading trigger (default: 1 = 100% of viewport height). */
|
|
174
|
+
scrollOffset?: number;
|
|
152
175
|
children?: JSX.Element;
|
|
153
176
|
class?: ClassNameOrFunction<{ isLoading: boolean }>;
|
|
154
177
|
style?: StyleOrFunction<{ isLoading: boolean }>;
|
|
@@ -161,37 +184,32 @@ export interface GridListHeaderProps extends SlotProps {
|
|
|
161
184
|
style?: JSX.CSSProperties;
|
|
162
185
|
}
|
|
163
186
|
|
|
164
|
-
// ============================================
|
|
165
|
-
// CONTEXT
|
|
166
|
-
// ============================================
|
|
167
|
-
|
|
168
187
|
interface GridListContextValue<T extends object> {
|
|
169
188
|
state: GridState<T, GridCollection<T>>;
|
|
170
189
|
collection: GridCollection<T>;
|
|
171
190
|
isDisabled: boolean;
|
|
191
|
+
selectionBehavior: "replace" | "toggle";
|
|
172
192
|
dragAndDropHooks?: DragAndDropHooks<T>;
|
|
173
193
|
dragState?: unknown;
|
|
174
194
|
dropState?: unknown;
|
|
175
195
|
}
|
|
176
196
|
|
|
177
197
|
export const GridListContext = createContext<GridListContextValue<object> | null>(null);
|
|
178
|
-
export const GridListStateContext = createContext<GridState<object, GridCollection<object>> | null>(
|
|
198
|
+
export const GridListStateContext = createContext<GridState<object, GridCollection<object>> | null>(
|
|
199
|
+
null,
|
|
200
|
+
);
|
|
179
201
|
export const GridListHeaderContext = createContext<null>(null);
|
|
180
202
|
|
|
181
|
-
// ============================================
|
|
182
|
-
// HELPER: Build GridCollection from items
|
|
183
|
-
// ============================================
|
|
184
|
-
|
|
185
203
|
function buildGridCollection<T extends object>(
|
|
186
204
|
items: T[],
|
|
187
205
|
getKey?: (item: T) => Key,
|
|
188
206
|
getTextValue?: (item: T) => string,
|
|
189
|
-
getDisabled?: (item: T) => boolean
|
|
207
|
+
getDisabled?: (item: T) => boolean,
|
|
190
208
|
): GridCollection<T> {
|
|
191
209
|
const nodes: GridNode<T>[] = items.map((item, index) => {
|
|
192
210
|
const key = getKey?.(item) ?? index;
|
|
193
211
|
return {
|
|
194
|
-
type:
|
|
212
|
+
type: "item" as const,
|
|
195
213
|
key,
|
|
196
214
|
value: item,
|
|
197
215
|
textValue: getTextValue?.(item) ?? String(key),
|
|
@@ -248,7 +266,7 @@ function buildGridCollection<T extends object>(
|
|
|
248
266
|
return [];
|
|
249
267
|
},
|
|
250
268
|
getTextValue(key: Key) {
|
|
251
|
-
return keyMap.get(key)?.textValue ??
|
|
269
|
+
return keyMap.get(key)?.textValue ?? "";
|
|
252
270
|
},
|
|
253
271
|
getCell(_rowKey: Key, _columnKey: Key) {
|
|
254
272
|
return null;
|
|
@@ -259,10 +277,6 @@ function buildGridCollection<T extends object>(
|
|
|
259
277
|
};
|
|
260
278
|
}
|
|
261
279
|
|
|
262
|
-
// ============================================
|
|
263
|
-
// COMPONENTS
|
|
264
|
-
// ============================================
|
|
265
|
-
|
|
266
280
|
/**
|
|
267
281
|
* A grid list displays a list of interactive items, with support for
|
|
268
282
|
* keyboard navigation, single or multiple selection, and row actions.
|
|
@@ -270,45 +284,52 @@ function buildGridCollection<T extends object>(
|
|
|
270
284
|
export function GridList<T extends object>(props: GridListProps<T>): JSX.Element {
|
|
271
285
|
const [local, stateProps, ariaProps] = splitProps(
|
|
272
286
|
props,
|
|
273
|
-
['children', 'class', 'style', 'slot', 'renderEmptyState', 'hasMore', 'isLoading', 'onLoadMore', 'dragAndDropHooks'],
|
|
274
287
|
[
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
288
|
+
"children",
|
|
289
|
+
"class",
|
|
290
|
+
"style",
|
|
291
|
+
"ref",
|
|
292
|
+
"slot",
|
|
293
|
+
"renderEmptyState",
|
|
294
|
+
"hasMore",
|
|
295
|
+
"isLoading",
|
|
296
|
+
"onLoadMore",
|
|
297
|
+
"dragAndDropHooks",
|
|
298
|
+
],
|
|
299
|
+
[
|
|
300
|
+
"items",
|
|
301
|
+
"getKey",
|
|
302
|
+
"getTextValue",
|
|
303
|
+
"getDisabled",
|
|
304
|
+
"disabledKeys",
|
|
305
|
+
"selectionMode",
|
|
306
|
+
"selectedKeys",
|
|
307
|
+
"defaultSelectedKeys",
|
|
308
|
+
"onSelectionChange",
|
|
309
|
+
"selectionBehavior",
|
|
310
|
+
],
|
|
285
311
|
);
|
|
286
312
|
|
|
287
|
-
|
|
288
|
-
const [ref, setRef] = createSignal<HTMLUListElement | null>(null);
|
|
313
|
+
const [ref, setRef] = createSignal<HTMLDivElement | null>(null);
|
|
289
314
|
|
|
290
|
-
// Build collection
|
|
291
315
|
const collection = createMemo(() =>
|
|
292
316
|
buildGridCollection(
|
|
293
317
|
stateProps.items,
|
|
294
318
|
stateProps.getKey,
|
|
295
319
|
stateProps.getTextValue,
|
|
296
|
-
stateProps.getDisabled
|
|
297
|
-
)
|
|
320
|
+
stateProps.getDisabled,
|
|
321
|
+
),
|
|
298
322
|
);
|
|
299
323
|
|
|
300
|
-
// Get disabled keys from items + explicit disabledKeys
|
|
301
324
|
const allDisabledKeys = createMemo(() => {
|
|
302
325
|
const keys = new Set<Key>();
|
|
303
326
|
|
|
304
|
-
// Add explicitly disabled keys
|
|
305
327
|
if (stateProps.disabledKeys) {
|
|
306
328
|
for (const key of stateProps.disabledKeys) {
|
|
307
329
|
keys.add(key);
|
|
308
330
|
}
|
|
309
331
|
}
|
|
310
332
|
|
|
311
|
-
// Add keys from items marked as disabled
|
|
312
333
|
for (const node of collection().rows) {
|
|
313
334
|
if (node.isDisabled) {
|
|
314
335
|
keys.add(node.key);
|
|
@@ -318,35 +339,33 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
318
339
|
return keys;
|
|
319
340
|
});
|
|
320
341
|
|
|
321
|
-
// Create grid state
|
|
322
342
|
const state = createGridState<T, GridCollection<T>>(() => ({
|
|
323
343
|
collection: collection(),
|
|
324
344
|
disabledKeys: allDisabledKeys(),
|
|
325
345
|
selectionMode: stateProps.selectionMode,
|
|
346
|
+
selectionBehavior: stateProps.selectionBehavior,
|
|
326
347
|
selectedKeys: stateProps.selectedKeys,
|
|
327
348
|
defaultSelectedKeys: stateProps.defaultSelectedKeys,
|
|
328
349
|
onSelectionChange: stateProps.onSelectionChange,
|
|
329
350
|
}));
|
|
330
351
|
|
|
331
|
-
// Create grid list aria props
|
|
332
352
|
const { gridProps } = createGridList<T, GridCollection<T>>(
|
|
333
353
|
() => ({
|
|
334
354
|
id: ariaProps.id,
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
355
|
+
"aria-label": ariaProps["aria-label"],
|
|
356
|
+
"aria-labelledby": ariaProps["aria-labelledby"],
|
|
357
|
+
"aria-describedby": ariaProps["aria-describedby"],
|
|
338
358
|
isVirtualized: ariaProps.isVirtualized,
|
|
339
359
|
onAction: ariaProps.onAction,
|
|
340
360
|
isDisabled: ariaProps.isDisabled,
|
|
361
|
+
selectionBehavior: stateProps.selectionBehavior,
|
|
341
362
|
}),
|
|
342
363
|
() => state,
|
|
343
|
-
ref
|
|
364
|
+
ref,
|
|
344
365
|
);
|
|
345
366
|
|
|
346
|
-
// Create focus ring
|
|
347
367
|
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
348
368
|
|
|
349
|
-
// Render props values
|
|
350
369
|
const renderValues = createMemo<GridListRenderProps>(() => ({
|
|
351
370
|
isFocused: state.isFocused || isFocused(),
|
|
352
371
|
isFocusVisible: isFocusVisible(),
|
|
@@ -354,23 +373,20 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
354
373
|
isEmpty: stateProps.items.length === 0,
|
|
355
374
|
}));
|
|
356
375
|
|
|
357
|
-
// Resolve render props
|
|
358
376
|
const renderProps = useRenderProps(
|
|
359
377
|
{
|
|
360
378
|
class: local.class,
|
|
361
379
|
style: local.style,
|
|
362
|
-
defaultClassName:
|
|
380
|
+
defaultClassName: "solidaria-GridList",
|
|
363
381
|
},
|
|
364
|
-
renderValues
|
|
382
|
+
renderValues,
|
|
365
383
|
);
|
|
366
384
|
|
|
367
|
-
// Filter DOM props
|
|
368
385
|
const domProps = createMemo(() => {
|
|
369
386
|
const filtered = filterDOMProps(ariaProps as Record<string, unknown>, { global: true });
|
|
370
387
|
return filtered;
|
|
371
388
|
});
|
|
372
389
|
|
|
373
|
-
// Remove ref from spread props
|
|
374
390
|
const cleanGridProps = () => {
|
|
375
391
|
const { ref: _ref1, ...rest } = gridProps as Record<string, unknown>;
|
|
376
392
|
return rest;
|
|
@@ -383,18 +399,25 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
383
399
|
const isEmpty = () => stateProps.items.length === 0;
|
|
384
400
|
const virtualizer = useVirtualizerContext();
|
|
385
401
|
const parentCollectionRenderer = useCollectionRenderer<T>();
|
|
386
|
-
const getItemNodes = createMemo(() =>
|
|
387
|
-
|
|
402
|
+
const getItemNodes = createMemo(() =>
|
|
403
|
+
Array.from(state.collection).filter((node) => node.type === "item"),
|
|
404
|
+
);
|
|
405
|
+
const getDropTargetByIndex = (
|
|
406
|
+
index: number,
|
|
407
|
+
position: "before" | "after" | "on",
|
|
408
|
+
): DropTarget | null => {
|
|
388
409
|
const node = getItemNodes()[index];
|
|
389
410
|
if (!node) return null;
|
|
390
|
-
return { type:
|
|
411
|
+
return { type: "item", key: node.key, dropPosition: position };
|
|
391
412
|
};
|
|
392
413
|
const hasDroppableDnd = createMemo(() => {
|
|
393
414
|
const hooks = local.dragAndDropHooks;
|
|
394
415
|
return Boolean(
|
|
395
416
|
hooks?.useDroppableCollectionState &&
|
|
396
417
|
hooks.useDroppableCollection &&
|
|
397
|
-
(hooks.dropTargetDelegate ||
|
|
418
|
+
(hooks.dropTargetDelegate ||
|
|
419
|
+
parentCollectionRenderer?.dropTargetDelegate ||
|
|
420
|
+
hooks.ListDropTargetDelegate),
|
|
398
421
|
);
|
|
399
422
|
});
|
|
400
423
|
const hasDraggableDnd = createMemo(() => {
|
|
@@ -423,22 +446,23 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
423
446
|
const hooks = local.dragAndDropHooks;
|
|
424
447
|
const activeDropState = dropState();
|
|
425
448
|
if (!hooks?.useDroppableCollection || !activeDropState) return undefined;
|
|
426
|
-
const resolveDirection = ():
|
|
449
|
+
const resolveDirection = (): "ltr" | "rtl" => {
|
|
427
450
|
const el = ref();
|
|
428
|
-
if (el && typeof window !==
|
|
451
|
+
if (el && typeof window !== "undefined" && typeof window.getComputedStyle === "function") {
|
|
429
452
|
const dir = window.getComputedStyle(el).direction;
|
|
430
|
-
if (dir ===
|
|
453
|
+
if (dir === "rtl") return "rtl";
|
|
431
454
|
}
|
|
432
|
-
return typeof document !==
|
|
455
|
+
return typeof document !== "undefined" && document.dir === "rtl" ? "rtl" : "ltr";
|
|
433
456
|
};
|
|
434
|
-
const dropTargetDelegate =
|
|
435
|
-
??
|
|
436
|
-
??
|
|
457
|
+
const dropTargetDelegate =
|
|
458
|
+
hooks.dropTargetDelegate ??
|
|
459
|
+
parentCollectionRenderer?.dropTargetDelegate ??
|
|
460
|
+
(hooks.ListDropTargetDelegate
|
|
437
461
|
? new hooks.ListDropTargetDelegate(
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
462
|
+
() => state.collection,
|
|
463
|
+
() => ref(),
|
|
464
|
+
{ layout: "grid", orientation: "vertical", direction: resolveDirection() },
|
|
465
|
+
)
|
|
442
466
|
: undefined);
|
|
443
467
|
if (!dropTargetDelegate) return undefined;
|
|
444
468
|
return hooks.useDroppableCollection(
|
|
@@ -450,35 +474,37 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
450
474
|
getKeyBelow: (key) => state.collection.getKeyAfter?.(key) ?? null,
|
|
451
475
|
getKeyAbove: (key) => state.collection.getKeyBefore?.(key) ?? null,
|
|
452
476
|
getKeyLeftOf: (key) =>
|
|
453
|
-
resolveDirection() ===
|
|
454
|
-
? state.collection.getKeyAfter?.(key) ?? null
|
|
455
|
-
: state.collection.getKeyBefore?.(key) ?? null,
|
|
477
|
+
resolveDirection() === "rtl"
|
|
478
|
+
? (state.collection.getKeyAfter?.(key) ?? null)
|
|
479
|
+
: (state.collection.getKeyBefore?.(key) ?? null),
|
|
456
480
|
getKeyRightOf: (key) =>
|
|
457
|
-
resolveDirection() ===
|
|
458
|
-
? state.collection.getKeyBefore?.(key) ?? null
|
|
459
|
-
: state.collection.getKeyAfter?.(key) ?? null,
|
|
481
|
+
resolveDirection() === "rtl"
|
|
482
|
+
? (state.collection.getKeyBefore?.(key) ?? null)
|
|
483
|
+
: (state.collection.getKeyAfter?.(key) ?? null),
|
|
460
484
|
getKeyPageBelow: (key) => state.collection.getKeyAfter?.(key) ?? null,
|
|
461
485
|
getKeyPageAbove: (key) => state.collection.getKeyBefore?.(key) ?? null,
|
|
462
486
|
},
|
|
463
487
|
},
|
|
464
488
|
activeDropState,
|
|
465
|
-
() => ref()
|
|
489
|
+
() => ref(),
|
|
466
490
|
);
|
|
467
491
|
});
|
|
468
492
|
const isRootDropTarget = createMemo(() => {
|
|
469
|
-
return Boolean(dropState()?.target?.type ===
|
|
493
|
+
return Boolean(dropState()?.target?.type === "root");
|
|
470
494
|
});
|
|
471
|
-
const dndRenderDropIndicator = createMemo(() =>
|
|
472
|
-
|
|
495
|
+
const dndRenderDropIndicator = createMemo(() =>
|
|
496
|
+
useRenderDropIndicator(local.dragAndDropHooks, dropState()),
|
|
497
|
+
);
|
|
498
|
+
const dndDropIndicator = (index: number, position: "before" | "after" | "on") => {
|
|
473
499
|
const target = getDropTargetByIndex(index, position);
|
|
474
|
-
if (!target || target.type !==
|
|
500
|
+
if (!target || target.type !== "item") return undefined;
|
|
475
501
|
return dndRenderDropIndicator()?.(target);
|
|
476
502
|
};
|
|
477
503
|
const persistedKeys = useDndPersistedKeys(
|
|
478
504
|
{ focusedKey: () => state.focusedKey },
|
|
479
505
|
local.dragAndDropHooks,
|
|
480
506
|
dropState(),
|
|
481
|
-
state.collection
|
|
507
|
+
state.collection,
|
|
482
508
|
);
|
|
483
509
|
const virtualRange = createMemo(() => {
|
|
484
510
|
if (!virtualizer || !parentCollectionRenderer?.isVirtualized) return null;
|
|
@@ -490,16 +516,26 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
490
516
|
const dropTarget = dropState()?.target;
|
|
491
517
|
const normalizedDropKey = getNormalizedDropTargetKey(dropTarget, state.collection);
|
|
492
518
|
const focusedKey = state.focusedKey;
|
|
493
|
-
const focusedIndex =
|
|
519
|
+
const focusedIndex =
|
|
520
|
+
focusedKey != null ? itemNodes.findIndex((node) => node.key === focusedKey) : -1;
|
|
494
521
|
const forceIncludeIndexes = [
|
|
495
|
-
dropTarget?.type ===
|
|
496
|
-
normalizedDropKey != null
|
|
497
|
-
|
|
522
|
+
dropTarget?.type === "item" ? itemNodes.findIndex((node) => node.key === dropTarget.key) : -1,
|
|
523
|
+
normalizedDropKey != null
|
|
524
|
+
? itemNodes.findIndex((node) => node.key === normalizedDropKey)
|
|
525
|
+
: -1,
|
|
526
|
+
dropTarget?.type === "item" ? -1 : focusedIndex,
|
|
498
527
|
].filter((index) => index >= 0);
|
|
499
|
-
return mergePersistedKeysIntoVirtualRange(
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
528
|
+
return mergePersistedKeysIntoVirtualRange(
|
|
529
|
+
baseRange,
|
|
530
|
+
persistedIndexes,
|
|
531
|
+
stateProps.items.length,
|
|
532
|
+
virtualizer,
|
|
533
|
+
80,
|
|
534
|
+
{
|
|
535
|
+
forceIncludeIndexes,
|
|
536
|
+
forceIncludeMaxSpan: 320,
|
|
537
|
+
},
|
|
538
|
+
);
|
|
503
539
|
});
|
|
504
540
|
createEffect(() => {
|
|
505
541
|
if (!virtualizer || !parentCollectionRenderer?.isVirtualized) return;
|
|
@@ -514,7 +550,7 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
514
550
|
if (!node) return target;
|
|
515
551
|
return {
|
|
516
552
|
...target,
|
|
517
|
-
key: typeof node.key ===
|
|
553
|
+
key: typeof node.key === "string" || typeof node.key === "number" ? node.key : undefined,
|
|
518
554
|
};
|
|
519
555
|
});
|
|
520
556
|
onCleanup(() => {
|
|
@@ -533,6 +569,7 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
533
569
|
state,
|
|
534
570
|
collection: collection(),
|
|
535
571
|
isDisabled: ariaProps.isDisabled ?? false,
|
|
572
|
+
selectionBehavior: stateProps.selectionBehavior ?? "replace",
|
|
536
573
|
dragAndDropHooks: local.dragAndDropHooks,
|
|
537
574
|
dragState: dragState(),
|
|
538
575
|
dropState: dropState(),
|
|
@@ -540,21 +577,27 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
540
577
|
const collectionRenderer = createMemo<CollectionRendererContextValue<unknown>>(() => ({
|
|
541
578
|
...parentCollectionRenderer,
|
|
542
579
|
renderItem: (item) => props.children(item as T),
|
|
543
|
-
renderDropIndicator: (index: number, position:
|
|
544
|
-
dndDropIndicator(index, position) ??
|
|
580
|
+
renderDropIndicator: (index: number, position: "before" | "after" | "on") =>
|
|
581
|
+
dndDropIndicator(index, position) ??
|
|
582
|
+
parentCollectionRenderer?.renderDropIndicator?.(index, position),
|
|
545
583
|
}));
|
|
546
584
|
|
|
547
585
|
return (
|
|
548
586
|
<GridListContext.Provider value={contextValue() as unknown as GridListContextValue<object>}>
|
|
549
|
-
<GridListStateContext.Provider
|
|
587
|
+
<GridListStateContext.Provider
|
|
588
|
+
value={state as unknown as GridState<object, GridCollection<object>>}
|
|
589
|
+
>
|
|
550
590
|
<CollectionRendererContext.Provider value={collectionRenderer()}>
|
|
551
591
|
<div
|
|
552
|
-
ref={
|
|
592
|
+
ref={(element) => {
|
|
593
|
+
setRef(element);
|
|
594
|
+
assignRef(local.ref, element);
|
|
595
|
+
}}
|
|
553
596
|
{...mergeProps(
|
|
554
597
|
domProps(),
|
|
555
598
|
cleanGridProps(),
|
|
556
599
|
cleanFocusProps(),
|
|
557
|
-
(droppableCollection()?.collectionProps as Record<string, unknown> | undefined) ?? {}
|
|
600
|
+
(droppableCollection()?.collectionProps as Record<string, unknown> | undefined) ?? {},
|
|
558
601
|
)}
|
|
559
602
|
class={renderProps.class()}
|
|
560
603
|
style={renderProps.style()}
|
|
@@ -565,34 +608,47 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
565
608
|
data-drop-target={isRootDropTarget() || undefined}
|
|
566
609
|
>
|
|
567
610
|
<SharedElementTransition>
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
611
|
+
{isEmpty() && local.renderEmptyState ? (
|
|
612
|
+
local.renderEmptyState()
|
|
613
|
+
) : (
|
|
614
|
+
<>
|
|
615
|
+
{virtualRange()?.offsetTop ? (
|
|
616
|
+
<div
|
|
617
|
+
role="presentation"
|
|
618
|
+
aria-hidden="true"
|
|
619
|
+
style={{ height: `${virtualRange()!.offsetTop}px` }}
|
|
620
|
+
data-virtualizer-spacer="top"
|
|
621
|
+
/>
|
|
622
|
+
) : null}
|
|
623
|
+
<For each={visibleItems()}>
|
|
624
|
+
{(item, index) => {
|
|
625
|
+
const itemIndex = () => (virtualRange()?.start ?? 0) + index();
|
|
626
|
+
const beforeIndicator = () =>
|
|
627
|
+
collectionRenderer().renderDropIndicator?.(itemIndex(), "before");
|
|
628
|
+
const onIndicator = () =>
|
|
629
|
+
collectionRenderer().renderDropIndicator?.(itemIndex(), "on");
|
|
630
|
+
const afterIndicator = () =>
|
|
631
|
+
collectionRenderer().renderDropIndicator?.(itemIndex(), "after");
|
|
632
|
+
return (
|
|
633
|
+
<>
|
|
634
|
+
{beforeIndicator()}
|
|
635
|
+
{onIndicator()}
|
|
636
|
+
{props.children(item)}
|
|
637
|
+
{afterIndicator()}
|
|
638
|
+
</>
|
|
639
|
+
);
|
|
640
|
+
}}
|
|
641
|
+
</For>
|
|
642
|
+
{virtualRange()?.offsetBottom ? (
|
|
643
|
+
<div
|
|
644
|
+
role="presentation"
|
|
645
|
+
aria-hidden="true"
|
|
646
|
+
style={{ height: `${virtualRange()!.offsetBottom}px` }}
|
|
647
|
+
data-virtualizer-spacer="bottom"
|
|
648
|
+
/>
|
|
649
|
+
) : null}
|
|
650
|
+
</>
|
|
651
|
+
)}
|
|
596
652
|
</SharedElementTransition>
|
|
597
653
|
{local.hasMore && local.onLoadMore && (
|
|
598
654
|
<GridListLoadMoreItem onLoadMore={local.onLoadMore} isLoading={local.isLoading} />
|
|
@@ -609,34 +665,31 @@ export function GridList<T extends object>(props: GridListProps<T>): JSX.Element
|
|
|
609
665
|
*/
|
|
610
666
|
export function GridListItem<T extends object>(props: GridListItemProps<T>): JSX.Element {
|
|
611
667
|
const [local, domProps] = splitProps(props, [
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
668
|
+
"class",
|
|
669
|
+
"style",
|
|
670
|
+
"slot",
|
|
671
|
+
"id",
|
|
672
|
+
"item",
|
|
673
|
+
"textValue",
|
|
674
|
+
"onAction",
|
|
675
|
+
"children",
|
|
676
|
+
"ref",
|
|
620
677
|
]);
|
|
621
678
|
|
|
622
|
-
// Get state from context
|
|
623
679
|
const context = useContext(GridListStateContext);
|
|
624
680
|
if (!context) {
|
|
625
|
-
throw new Error(
|
|
681
|
+
throw new Error("GridListItem must be used within a GridList");
|
|
626
682
|
}
|
|
627
683
|
const state = context as GridState<T, GridCollection<T>>;
|
|
628
684
|
const listContext = useContext(GridListContext) as GridListContextValue<T> | null;
|
|
629
685
|
|
|
630
|
-
// Create ref signal
|
|
631
686
|
const [ref, setRef] = createSignal<HTMLDivElement | null>(null);
|
|
632
687
|
|
|
633
|
-
// Find or create the item node
|
|
634
688
|
const itemNode = createMemo(() => {
|
|
635
689
|
const node = state.collection.getItem(local.id);
|
|
636
690
|
if (!node) {
|
|
637
|
-
// Create a simple node for the item
|
|
638
691
|
return {
|
|
639
|
-
type:
|
|
692
|
+
type: "item" as const,
|
|
640
693
|
key: local.id,
|
|
641
694
|
value: local.item ?? null,
|
|
642
695
|
textValue: local.textValue ?? String(local.id),
|
|
@@ -649,52 +702,50 @@ export function GridListItem<T extends object>(props: GridListItemProps<T>): JSX
|
|
|
649
702
|
return node as GridNode<T>;
|
|
650
703
|
});
|
|
651
704
|
|
|
652
|
-
// Create item aria props
|
|
653
705
|
const itemAria = createGridListItem<T, GridCollection<T>>(
|
|
654
706
|
() => ({
|
|
655
707
|
node: itemNode(),
|
|
656
708
|
onAction: local.onAction,
|
|
709
|
+
selectionBehavior: listContext?.selectionBehavior ?? "replace",
|
|
657
710
|
}),
|
|
658
711
|
() => state,
|
|
659
|
-
ref
|
|
712
|
+
ref,
|
|
660
713
|
);
|
|
661
714
|
const isSelected = () => itemAria.isSelected;
|
|
662
715
|
const isDisabled = () => itemAria.isDisabled;
|
|
663
716
|
const isPressed = () => itemAria.isPressed;
|
|
664
717
|
|
|
665
|
-
// Create hover
|
|
666
718
|
const { isHovered, hoverProps } = createHover({
|
|
667
719
|
get isDisabled() {
|
|
668
720
|
return isDisabled();
|
|
669
721
|
},
|
|
670
722
|
});
|
|
671
723
|
|
|
672
|
-
// Create focus ring
|
|
673
724
|
const { isFocusVisible, focusProps } = createFocusRing();
|
|
674
725
|
|
|
675
|
-
// Check if focused
|
|
676
726
|
const isFocused = createMemo(() => state.focusedKey === local.id);
|
|
677
727
|
const draggableItem = createMemo(() => {
|
|
678
|
-
if (!listContext?.dragAndDropHooks?.useDraggableItem || !listContext.dragState)
|
|
728
|
+
if (!listContext?.dragAndDropHooks?.useDraggableItem || !listContext.dragState)
|
|
729
|
+
return undefined;
|
|
679
730
|
return listContext.dragAndDropHooks.useDraggableItem(
|
|
680
731
|
{
|
|
681
732
|
key: local.id as string | number,
|
|
682
733
|
},
|
|
683
|
-
listContext.dragState as Parameters<NonNullable<DragAndDropHooks<T>[
|
|
734
|
+
listContext.dragState as Parameters<NonNullable<DragAndDropHooks<T>["useDraggableItem"]>>[1],
|
|
684
735
|
);
|
|
685
736
|
});
|
|
686
737
|
const droppableItem = createMemo(() => {
|
|
687
|
-
if (!listContext?.dragAndDropHooks?.useDroppableItem || !listContext.dropState)
|
|
738
|
+
if (!listContext?.dragAndDropHooks?.useDroppableItem || !listContext.dropState)
|
|
739
|
+
return undefined;
|
|
688
740
|
return listContext.dragAndDropHooks.useDroppableItem(
|
|
689
741
|
{
|
|
690
742
|
key: local.id as string | number,
|
|
691
743
|
},
|
|
692
|
-
listContext.dropState as Parameters<NonNullable<DragAndDropHooks<T>[
|
|
693
|
-
() => ref()
|
|
744
|
+
listContext.dropState as Parameters<NonNullable<DragAndDropHooks<T>["useDroppableItem"]>>[1],
|
|
745
|
+
() => ref(),
|
|
694
746
|
);
|
|
695
747
|
});
|
|
696
748
|
|
|
697
|
-
// Render props values
|
|
698
749
|
const renderValues = createMemo<GridListItemRenderProps>(() => ({
|
|
699
750
|
isSelected: isSelected(),
|
|
700
751
|
isFocused: isFocused(),
|
|
@@ -702,20 +753,20 @@ export function GridListItem<T extends object>(props: GridListItemProps<T>): JSX
|
|
|
702
753
|
isPressed: isPressed(),
|
|
703
754
|
isHovered: isHovered(),
|
|
704
755
|
isDisabled: isDisabled(),
|
|
756
|
+
selectionMode: state.selectionMode,
|
|
757
|
+
selectionBehavior: listContext?.selectionBehavior ?? "replace",
|
|
705
758
|
}));
|
|
706
759
|
|
|
707
|
-
// Resolve render props
|
|
708
760
|
const renderProps = useRenderProps(
|
|
709
761
|
{
|
|
710
762
|
children: props.children,
|
|
711
763
|
class: local.class,
|
|
712
764
|
style: local.style,
|
|
713
|
-
defaultClassName:
|
|
765
|
+
defaultClassName: "solidaria-GridList-item",
|
|
714
766
|
},
|
|
715
|
-
renderValues
|
|
767
|
+
renderValues,
|
|
716
768
|
);
|
|
717
769
|
|
|
718
|
-
// Remove ref from spread props
|
|
719
770
|
const cleanRowProps = () => {
|
|
720
771
|
const { ref: _ref1, ...rest } = itemAria.rowProps as Record<string, unknown>;
|
|
721
772
|
return rest;
|
|
@@ -731,14 +782,17 @@ export function GridListItem<T extends object>(props: GridListItemProps<T>): JSX
|
|
|
731
782
|
|
|
732
783
|
return (
|
|
733
784
|
<div
|
|
734
|
-
ref={
|
|
785
|
+
ref={(element) => {
|
|
786
|
+
setRef(element);
|
|
787
|
+
assignRef(local.ref, element);
|
|
788
|
+
}}
|
|
735
789
|
{...domProps}
|
|
736
790
|
{...mergeProps(
|
|
737
791
|
cleanRowProps(),
|
|
738
792
|
cleanHoverProps(),
|
|
739
793
|
cleanFocusProps(),
|
|
740
794
|
(draggableItem()?.dragProps as Record<string, unknown> | undefined) ?? {},
|
|
741
|
-
(droppableItem()?.dropProps as Record<string, unknown> | undefined) ?? {}
|
|
795
|
+
(droppableItem()?.dropProps as Record<string, unknown> | undefined) ?? {},
|
|
742
796
|
)}
|
|
743
797
|
class={renderProps.class()}
|
|
744
798
|
style={renderProps.style()}
|
|
@@ -759,24 +813,38 @@ export function GridListItem<T extends object>(props: GridListItemProps<T>): JSX
|
|
|
759
813
|
/**
|
|
760
814
|
* A checkbox for item selection in a grid list.
|
|
761
815
|
*/
|
|
762
|
-
export function GridListSelectionCheckbox(props: {
|
|
816
|
+
export function GridListSelectionCheckbox(props: {
|
|
817
|
+
itemKey: Key;
|
|
818
|
+
class?: string;
|
|
819
|
+
style?: JSX.CSSProperties;
|
|
820
|
+
excludeFromTabOrder?: boolean;
|
|
821
|
+
"aria-label"?: string;
|
|
822
|
+
}): JSX.Element {
|
|
763
823
|
const context = useContext(GridListStateContext);
|
|
764
824
|
if (!context) {
|
|
765
|
-
throw new Error(
|
|
825
|
+
throw new Error("GridListSelectionCheckbox must be used within a GridList");
|
|
766
826
|
}
|
|
767
827
|
|
|
768
828
|
const state = context as GridState<object, GridCollection<object>>;
|
|
769
829
|
|
|
770
830
|
const checkboxAria = createGridListSelectionCheckbox<object, GridCollection<object>>(
|
|
771
831
|
() => ({ key: props.itemKey }),
|
|
772
|
-
() => state
|
|
832
|
+
() => state,
|
|
773
833
|
);
|
|
774
834
|
|
|
775
|
-
return
|
|
835
|
+
return (
|
|
836
|
+
<input
|
|
837
|
+
{...checkboxAria.checkboxProps}
|
|
838
|
+
class={props.class}
|
|
839
|
+
style={props.style}
|
|
840
|
+
tabIndex={props.excludeFromTabOrder ? -1 : undefined}
|
|
841
|
+
aria-label={props["aria-label"] ?? "Select"}
|
|
842
|
+
/>
|
|
843
|
+
);
|
|
776
844
|
}
|
|
777
845
|
|
|
778
846
|
export function GridListLoadMoreItem(props: GridListLoadMoreItemProps): JSX.Element {
|
|
779
|
-
let
|
|
847
|
+
let sentinelRef: HTMLDivElement | undefined;
|
|
780
848
|
const [isPending, setIsPending] = createSignal(false);
|
|
781
849
|
const isLoading = () => !!props.isLoading || isPending();
|
|
782
850
|
|
|
@@ -791,46 +859,55 @@ export function GridListLoadMoreItem(props: GridListLoadMoreItemProps): JSX.Elem
|
|
|
791
859
|
};
|
|
792
860
|
|
|
793
861
|
createEffect(() => {
|
|
794
|
-
if (!
|
|
795
|
-
const
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
862
|
+
if (!sentinelRef || typeof IntersectionObserver !== "function") return;
|
|
863
|
+
const offset = props.scrollOffset ?? 1;
|
|
864
|
+
const margin = `0px 0px ${100 * offset}% 0px`;
|
|
865
|
+
const observer = new IntersectionObserver(
|
|
866
|
+
(entries) => {
|
|
867
|
+
if (entries[0]?.isIntersecting) {
|
|
868
|
+
void triggerLoadMore();
|
|
869
|
+
}
|
|
870
|
+
},
|
|
871
|
+
{ rootMargin: margin },
|
|
872
|
+
);
|
|
873
|
+
observer.observe(sentinelRef);
|
|
801
874
|
return () => observer.disconnect();
|
|
802
875
|
});
|
|
803
876
|
|
|
804
877
|
const renderProps = useRenderProps(
|
|
805
878
|
{
|
|
806
|
-
children: props.children ?? (() => (isLoading() ?
|
|
879
|
+
children: props.children ?? (() => (isLoading() ? "Loading more..." : "Load more")),
|
|
807
880
|
class: props.class,
|
|
808
881
|
style: props.style,
|
|
809
|
-
defaultClassName:
|
|
882
|
+
defaultClassName: "solidaria-GridList-loadMore",
|
|
810
883
|
},
|
|
811
|
-
() => ({ isLoading: isLoading() })
|
|
884
|
+
() => ({ isLoading: isLoading() }),
|
|
812
885
|
);
|
|
813
886
|
|
|
814
887
|
return (
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
888
|
+
<>
|
|
889
|
+
<div style={{ position: "relative", width: 0, height: 0, overflow: "hidden" }} inert>
|
|
890
|
+
<div ref={sentinelRef} style={{ position: "absolute", height: "1px", width: "1px" }} />
|
|
891
|
+
</div>
|
|
892
|
+
<div
|
|
893
|
+
role="row"
|
|
894
|
+
tabIndex={0}
|
|
895
|
+
onFocus={() => {
|
|
896
|
+
void triggerLoadMore();
|
|
897
|
+
}}
|
|
898
|
+
class={renderProps.class()}
|
|
899
|
+
style={renderProps.style()}
|
|
900
|
+
data-loading={isLoading() || undefined}
|
|
901
|
+
>
|
|
902
|
+
{renderProps.renderChildren()}
|
|
903
|
+
</div>
|
|
904
|
+
</>
|
|
828
905
|
);
|
|
829
906
|
}
|
|
830
907
|
|
|
831
908
|
export function GridListHeader(props: GridListHeaderProps): JSX.Element {
|
|
832
909
|
return (
|
|
833
|
-
<div class={props.class ??
|
|
910
|
+
<div class={props.class ?? "solidaria-GridListHeader"} style={props.style}>
|
|
834
911
|
{props.children}
|
|
835
912
|
</div>
|
|
836
913
|
);
|
|
@@ -843,7 +920,6 @@ export function GridListSection(props: GridListSectionProps): JSX.Element {
|
|
|
843
920
|
return <Section {...props} />;
|
|
844
921
|
}
|
|
845
922
|
|
|
846
|
-
// Attach Item and SelectionCheckbox as static properties
|
|
847
923
|
GridList.Item = GridListItem;
|
|
848
924
|
GridList.SelectionCheckbox = GridListSelectionCheckbox;
|
|
849
925
|
GridList.LoadMoreItem = GridListLoadMoreItem;
|