ropav 0.3.1 → 0.5.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/dist/components/autocomplete/autocomplete-root.js +3 -1
- package/dist/components/autocomplete/index.d.ts +3 -0
- package/dist/components/avatar/avatar-image.js +13 -2
- package/dist/components/avatar/avatar.types.d.ts +7 -1
- package/dist/components/breadcrumbs/breadcrumbs-item.js +1 -0
- package/dist/components/breadcrumbs/index.d.ts +1 -0
- package/dist/components/calendar/calendar-header.js +1 -1
- package/dist/components/calendar/index.d.ts +5 -3
- package/dist/components/calendar-year-picker/index.d.ts +4 -2
- package/dist/components/checkbox/checkbox-content.js +1 -1
- package/dist/components/color-field/index.d.ts +3 -2
- package/dist/components/color-input-group/color-input-group-root.js +2 -0
- package/dist/components/color-input-group/color-input-group.types.d.ts +2 -0
- package/dist/components/color-input-group/index.d.ts +2 -0
- package/dist/components/combo-box/combo-box-root.js +9 -2
- package/dist/components/combo-box/combo-box.types.d.ts +3 -0
- package/dist/components/combo-box/index.d.ts +3 -0
- package/dist/components/date-field/index.d.ts +1 -0
- package/dist/components/date-input-group/date-input-group-root.js +2 -0
- package/dist/components/date-input-group/date-input-group-segment.js +1 -1
- package/dist/components/date-input-group/date-input-group.types.d.ts +2 -0
- package/dist/{composables → components/date-input-group}/use-date-segment.d.ts +2 -2
- package/dist/{composables → components/date-input-group}/use-date-segment.js +9 -9
- package/dist/components/date-picker/index.d.ts +3 -2
- package/dist/components/date-picker/index.js +2 -2
- package/dist/components/date-range-picker/date-range-picker-root.js +1 -1
- package/dist/components/date-range-picker/index.d.ts +18 -16
- package/dist/components/date-range-picker/index.js +2 -2
- package/dist/{composables → components/date-range-picker}/use-date-range-picker.d.ts +7 -7
- package/dist/{composables → components/date-range-picker}/use-date-range-picker.js +10 -10
- package/dist/components/drawer/drawer-dialog.js +1 -1
- package/dist/{composables → components/drawer}/use-drawer-drag.d.ts +1 -1
- package/dist/{composables → components/drawer}/use-drawer-drag.js +1 -1
- package/dist/components/dropdown/dropdown-menu.js +3 -1
- package/dist/components/dropdown/dropdown-submenu-trigger.js +1 -1
- package/dist/components/dropdown/dropdown.types.d.ts +3 -3
- package/dist/components/dropdown/index.d.ts +4 -2
- package/dist/{composables → components/dropdown}/use-safely-mouse-to-submenu.js +1 -1
- package/dist/components/icons/icon-overlay-arrow.js +1 -1
- package/dist/components/index.d.ts +5 -0
- package/dist/components/input/index.d.ts +12 -4
- package/dist/components/input/input-root.d.ts +5 -2
- package/dist/components/input/input-root.js +46 -5
- package/dist/components/input/input.types.d.ts +11 -0
- package/dist/components/input-group/index.d.ts +2 -0
- package/dist/components/input-group/input-group-root.js +3 -0
- package/dist/components/input-group/input-group.types.d.ts +5 -0
- package/dist/components/input-otp/index.d.ts +6 -4
- package/dist/components/link/index.d.ts +2 -0
- package/dist/components/link/link-root.js +22 -5
- package/dist/components/link/link.types.d.ts +14 -3
- package/dist/{composables → components/list-box}/drag-collection.d.ts +2 -2
- package/dist/{composables → components/list-box}/drag-collection.js +1 -1
- package/dist/components/list-box/index.d.ts +4 -0
- package/dist/components/list-box/list-box-root.js +60 -35
- package/dist/components/list-box/list-box.types.d.ts +2 -0
- package/dist/components/menu/index.d.ts +4 -0
- package/dist/components/menu/menu-root.js +9 -2
- package/dist/components/menu/menu.types.d.ts +5 -0
- package/dist/components/number-field/index.d.ts +3 -0
- package/dist/components/number-field/number-field-root.js +2 -0
- package/dist/components/number-field/number-field.types.d.ts +2 -0
- package/dist/components/overlay/overlay-arrow.js +64 -11
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/pagination-root.js +8 -3
- package/dist/components/pagination/pagination.types.d.ts +8 -0
- package/dist/components/popover/popover-trigger.js +14 -7
- package/dist/components/radio/radio-content.js +1 -1
- package/dist/components/range-calendar/index.d.ts +18 -15
- package/dist/components/range-calendar/range-calendar-header.js +1 -1
- package/dist/components/router-provider/index.d.ts +5 -0
- package/dist/components/router-provider/index.js +3 -0
- package/dist/components/router-provider/router-provider.context.d.ts +40 -0
- package/dist/components/router-provider/router-provider.context.js +16 -0
- package/dist/components/router-provider/router-provider.d.ts +21 -0
- package/dist/components/router-provider/router-provider.js +22 -0
- package/dist/components/router-provider/router-provider.types.d.ts +23 -0
- package/dist/components/scroll-shadow/scroll-shadow-root.js +7 -1
- package/dist/components/scroll-shadow/use-scroll-shadow.js +25 -1
- package/dist/components/search-field/index.d.ts +2 -0
- package/dist/components/search-field/search-field-root.js +3 -1
- package/dist/components/search-field/search-field.types.d.ts +2 -0
- package/dist/{composables → components/search-field}/use-search-field.d.ts +2 -2
- package/dist/{composables → components/search-field}/use-search-field.js +3 -3
- package/dist/components/segmented-control/index.d.ts +134 -0
- package/dist/components/segmented-control/index.js +15 -0
- package/dist/components/segmented-control/segmented-control-indicator.d.ts +19 -0
- package/dist/components/segmented-control/segmented-control-indicator.js +36 -0
- package/dist/components/segmented-control/segmented-control-item.d.ts +21 -0
- package/dist/components/segmented-control/segmented-control-item.js +96 -0
- package/dist/components/segmented-control/segmented-control-root.d.ts +25 -0
- package/dist/components/segmented-control/segmented-control-root.js +112 -0
- package/dist/components/segmented-control/segmented-control-separator.d.ts +19 -0
- package/dist/components/segmented-control/segmented-control-separator.js +18 -0
- package/dist/components/segmented-control/segmented-control.context.d.ts +17 -0
- package/dist/components/segmented-control/segmented-control.context.js +12 -0
- package/dist/components/segmented-control/segmented-control.types.d.ts +67 -0
- package/dist/components/select/index.d.ts +3 -0
- package/dist/components/select/select-hidden-select.js +1 -1
- package/dist/components/select/select-root.js +2 -0
- package/dist/components/select/select.types.d.ts +2 -0
- package/dist/components/separator/separator-root.js +11 -5
- package/dist/components/separator/separator.context.d.ts +7 -0
- package/dist/components/sidebar/index.d.ts +544 -0
- package/dist/components/sidebar/index.js +47 -0
- package/dist/components/sidebar/sidebar-collapsible-trigger.d.ts +21 -0
- package/dist/components/sidebar/sidebar-collapsible-trigger.js +70 -0
- package/dist/components/sidebar/sidebar-collapsible.d.ts +24 -0
- package/dist/components/sidebar/sidebar-collapsible.js +78 -0
- package/dist/components/sidebar/sidebar-content.d.ts +21 -0
- package/dist/components/sidebar/sidebar-content.js +37 -0
- package/dist/components/sidebar/sidebar-footer.d.ts +21 -0
- package/dist/components/sidebar/sidebar-footer.js +24 -0
- package/dist/components/sidebar/sidebar-group-label.d.ts +21 -0
- package/dist/components/sidebar/sidebar-group-label.js +32 -0
- package/dist/components/sidebar/sidebar-group.d.ts +21 -0
- package/dist/components/sidebar/sidebar-group.js +48 -0
- package/dist/components/sidebar/sidebar-header.d.ts +21 -0
- package/dist/components/sidebar/sidebar-header.js +24 -0
- package/dist/components/sidebar/sidebar-inset.d.ts +21 -0
- package/dist/components/sidebar/sidebar-inset.js +24 -0
- package/dist/components/sidebar/sidebar-item-icon.d.ts +21 -0
- package/dist/components/sidebar/sidebar-item-icon.js +20 -0
- package/dist/components/sidebar/sidebar-item-indicator.d.ts +21 -0
- package/dist/components/sidebar/sidebar-item-indicator.js +48 -0
- package/dist/components/sidebar/sidebar-item-label.d.ts +21 -0
- package/dist/components/sidebar/sidebar-item-label.js +28 -0
- package/dist/components/sidebar/sidebar-item-tooltip.d.ts +21 -0
- package/dist/components/sidebar/sidebar-item-tooltip.js +38 -0
- package/dist/components/sidebar/sidebar-item-trailing.d.ts +21 -0
- package/dist/components/sidebar/sidebar-item-trailing.js +28 -0
- package/dist/components/sidebar/sidebar-item.d.ts +23 -0
- package/dist/components/sidebar/sidebar-item.js +160 -0
- package/dist/components/sidebar/sidebar-panel.d.ts +21 -0
- package/dist/components/sidebar/sidebar-panel.js +88 -0
- package/dist/components/sidebar/sidebar-rail.d.ts +21 -0
- package/dist/components/sidebar/sidebar-rail.js +210 -0
- package/dist/components/sidebar/sidebar-root.d.ts +31 -0
- package/dist/components/sidebar/sidebar-root.js +138 -0
- package/dist/components/sidebar/sidebar-separator.d.ts +19 -0
- package/dist/components/sidebar/sidebar-separator.js +16 -0
- package/dist/components/sidebar/sidebar-sub-menu.d.ts +23 -0
- package/dist/components/sidebar/sidebar-sub-menu.js +40 -0
- package/dist/components/sidebar/sidebar-trigger.d.ts +21 -0
- package/dist/components/sidebar/sidebar-trigger.js +69 -0
- package/dist/components/sidebar/sidebar.context.d.ts +75 -0
- package/dist/components/sidebar/sidebar.context.js +30 -0
- package/dist/components/sidebar/sidebar.state.d.ts +73 -0
- package/dist/components/sidebar/sidebar.state.js +76 -0
- package/dist/components/sidebar/sidebar.storage.d.ts +8 -0
- package/dist/components/sidebar/sidebar.storage.js +45 -0
- package/dist/components/sidebar/sidebar.types.d.ts +259 -0
- package/dist/components/splitter/index.d.ts +143 -0
- package/dist/components/splitter/index.js +13 -0
- package/dist/components/splitter/splitter-handle.d.ts +21 -0
- package/dist/components/splitter/splitter-handle.js +209 -0
- package/dist/components/splitter/splitter-panel.d.ts +21 -0
- package/dist/components/splitter/splitter-panel.js +70 -0
- package/dist/components/splitter/splitter-root.d.ts +31 -0
- package/dist/components/splitter/splitter-root.js +152 -0
- package/dist/components/splitter/splitter.context.d.ts +15 -0
- package/dist/components/splitter/splitter.context.js +5 -0
- package/dist/components/splitter/splitter.state.d.ts +87 -0
- package/dist/components/splitter/splitter.state.js +322 -0
- package/dist/components/splitter/splitter.storage.d.ts +15 -0
- package/dist/components/splitter/splitter.storage.js +56 -0
- package/dist/components/splitter/splitter.types.d.ts +98 -0
- package/dist/components/switch/switch-content.js +1 -1
- package/dist/components/table/index.d.ts +10 -9
- package/dist/components/table/table-body.js +13 -13
- package/dist/components/table/table-cell.js +49 -46
- package/dist/components/table/table-column-resizer.js +1 -1
- package/dist/components/table/table-column.js +1 -1
- package/dist/components/table/table-content.js +37 -18
- package/dist/{composables → components/table}/table-drag-collection.d.ts +1 -1
- package/dist/{composables → components/table}/table-drag-collection.js +1 -1
- package/dist/components/table/table-drop-indicator.js +3 -1
- package/dist/components/table/table-resizable-container.d.ts +4 -5
- package/dist/components/table/table-row.js +45 -14
- package/dist/components/table/table-virtualizer-item.d.ts +2 -7
- package/dist/components/table/table-virtualizer-item.js +20 -9
- package/dist/components/table/table.context.d.ts +11 -3
- package/dist/components/table/table.types.d.ts +1 -1
- package/dist/{composables → components/table}/use-grid-keyboard.d.ts +3 -3
- package/dist/{composables → components/table}/use-grid-keyboard.js +57 -55
- package/dist/{composables → components/table}/use-grid-selection-announcement.d.ts +2 -2
- package/dist/{composables → components/table}/use-grid-selection-announcement.js +2 -2
- package/dist/{composables → components/table}/use-table-collection.d.ts +2 -2
- package/dist/{composables → components/table}/use-table-collection.js +4 -4
- package/dist/{composables → components/table}/use-table-column-layout.d.ts +13 -20
- package/dist/components/table/use-table-column-layout.js +115 -0
- package/dist/components/tabs/tabs-panel.js +5 -1
- package/dist/components/tabs/tabs-tab.js +1 -1
- package/dist/components/textarea/index.d.ts +12 -4
- package/dist/components/textarea/textarea-root.d.ts +5 -2
- package/dist/components/textarea/textarea-root.js +40 -5
- package/dist/components/textarea/textarea.types.d.ts +11 -0
- package/dist/components/textfield/index.d.ts +2 -0
- package/dist/components/textfield/textfield-root.js +5 -1
- package/dist/components/textfield/textfield.context.d.ts +2 -0
- package/dist/components/textfield/textfield.types.d.ts +5 -0
- package/dist/components/time-field/index.d.ts +1 -0
- package/dist/components/toast/index.d.ts +1 -0
- package/dist/components/toast/toast-default-content.js +1 -1
- package/dist/components/toggle-button-group/toggle-button-group-root.js +3 -3
- package/dist/components/toolbar/index.d.ts +3 -2
- package/dist/components/toolbar/toolbar-root.js +3 -3
- package/dist/components/tooltip/index.js +1 -1
- package/dist/components/tooltip/tooltip-root.js +1 -1
- package/dist/components/tooltip/tooltip-trigger.js +13 -5
- package/dist/components/virtualizer/index.d.ts +3 -1
- package/dist/components/virtualizer/index.js +2 -1
- package/dist/components/virtualizer/use-virtualizer-item.d.ts +23 -0
- package/dist/components/virtualizer/use-virtualizer-item.js +45 -0
- package/dist/components/virtualizer/virtualizer-item.js +7 -41
- package/dist/components/virtualizer/virtualizer-scrollbar-track.d.ts +20 -0
- package/dist/components/virtualizer/virtualizer-scrollbar-track.js +141 -0
- package/dist/components/virtualizer/virtualizer-scrollbar.d.ts +18 -0
- package/dist/components/virtualizer/virtualizer-scrollbar.js +55 -0
- package/dist/components/virtualizer/virtualizer.context.d.ts +17 -1
- package/dist/composables/drag-manager.js +1 -13
- package/dist/composables/index.d.ts +3 -71
- package/dist/composables/use-collection.d.ts +22 -3
- package/dist/composables/use-collection.js +67 -14
- package/dist/composables/use-color-area.js +2 -2
- package/dist/composables/use-color-field.js +1 -1
- package/dist/composables/use-combo-box.js +1 -1
- package/dist/composables/use-date-field.js +1 -1
- package/dist/composables/use-drag-and-drop.js +1 -1
- package/dist/composables/use-drag.d.ts +6 -5
- package/dist/composables/use-draggable-item.d.ts +2 -2
- package/dist/composables/use-droppable-collection.js +2 -2
- package/dist/composables/use-droppable-item.js +1 -1
- package/dist/composables/use-form-reset.d.ts +6 -2
- package/dist/composables/use-form-reset.js +9 -5
- package/dist/composables/use-list-keyboard.js +64 -62
- package/dist/composables/use-menu.d.ts +10 -0
- package/dist/composables/use-menu.js +22 -0
- package/dist/composables/use-number-field.js +1 -1
- package/dist/composables/use-select.js +2 -3
- package/dist/composables/use-selection-manager.js +4 -4
- package/dist/composables/use-single-select-list-state.d.ts +37 -0
- package/dist/composables/use-single-select-list-state.js +110 -0
- package/dist/composables/use-slider-thumb.js +2 -2
- package/dist/composables/use-slider.js +1 -1
- package/dist/composables/use-tab-list-state.d.ts +20 -29
- package/dist/composables/use-tab-list-state.js +20 -99
- package/dist/composables/use-text-field.js +1 -1
- package/dist/composables/use-virtualizer-scroll.d.ts +52 -2
- package/dist/composables/use-virtualizer-scroll.js +79 -13
- package/dist/composables/use-virtualizer.d.ts +24 -4
- package/dist/composables/use-virtualizer.js +40 -6
- package/dist/index.js +58 -80
- package/dist/utils/document-order.d.ts +14 -0
- package/dist/utils/document-order.js +17 -0
- package/dist/utils/flex-sizing.d.ts +41 -0
- package/dist/utils/flex-sizing.js +140 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/open-link.d.ts +31 -0
- package/dist/utils/open-link.js +32 -0
- package/dist/utils/story-truncation.d.ts +20 -0
- package/dist/utils/story-users.d.ts +11 -0
- package/dist/utils/virtualizer-collection.d.ts +14 -4
- package/dist/utils/virtualizer-collection.js +9 -14
- package/dist/utils/virtualizer-layout-info.js +3 -2
- package/dist/utils/virtualizer-list-layout.d.ts +75 -29
- package/dist/utils/virtualizer-list-layout.js +182 -99
- package/dist/utils/virtualizer-offsets.d.ts +111 -0
- package/dist/utils/virtualizer-offsets.js +159 -0
- package/dist/utils/virtualizer-overscan.d.ts +9 -15
- package/dist/utils/virtualizer-overscan.js +14 -33
- package/dist/utils/virtualizer-table-layout.d.ts +50 -21
- package/dist/utils/virtualizer-table-layout.js +130 -89
- package/dist/version.js +1 -1
- package/package.json +19 -3
- package/dist/composables/use-table-column-layout.js +0 -214
- /package/dist/{composables → components/dropdown}/use-safely-mouse-to-submenu.d.ts +0 -0
|
@@ -7,6 +7,14 @@ export interface UseMenuOptions {
|
|
|
7
7
|
id?: MaybeRefOrGetter<string | undefined>;
|
|
8
8
|
/** The id of the element naming the menu, normally the trigger. */
|
|
9
9
|
labelledBy?: MaybeRefOrGetter<string | undefined>;
|
|
10
|
+
/**
|
|
11
|
+
* Names the menu when there is no element to point `labelledBy` at.
|
|
12
|
+
*
|
|
13
|
+
* A menu inside a trigger is named by it and never needs this; a menu standing on its own has
|
|
14
|
+
* nothing to borrow a name from, and a name is not something axe checks for `role="menu"` — so
|
|
15
|
+
* without a string to pass, a standalone menu ships unnamed and nothing says so.
|
|
16
|
+
*/
|
|
17
|
+
label?: MaybeRefOrGetter<string | undefined>;
|
|
10
18
|
selectionMode?: MaybeRefOrGetter<SelectionMode | undefined>;
|
|
11
19
|
selectionBehavior?: MaybeRefOrGetter<SelectionBehavior | undefined>;
|
|
12
20
|
selectedKeys?: MaybeRefOrGetter<"all" | Iterable<CollectionKey> | undefined>;
|
|
@@ -33,6 +41,8 @@ export interface UseMenuReturn {
|
|
|
33
41
|
collectionId: ComputedRef<string>;
|
|
34
42
|
/** Attributes the menu element renders, beside its own class and `data-slot`. */
|
|
35
43
|
menuAttributes: ComputedRef<Record<string, string | number | boolean | undefined>>;
|
|
44
|
+
/** Attributes the wrapper around the empty slot renders. */
|
|
45
|
+
emptyAttributes: ComputedRef<Record<string, string | number | boolean | undefined>>;
|
|
36
46
|
onKeydown: (event: KeyboardEvent) => void;
|
|
37
47
|
onKeydownCapture: (event: KeyboardEvent) => void;
|
|
38
48
|
onFocusin: (event: FocusEvent) => void;
|
|
@@ -84,8 +84,30 @@ var useMenu = (options = {}) => {
|
|
|
84
84
|
return {
|
|
85
85
|
collectionId,
|
|
86
86
|
element,
|
|
87
|
+
/**
|
|
88
|
+
* The empty slot is a disabled item of the menu, not a bare wrapper inside it.
|
|
89
|
+
*
|
|
90
|
+
* `role="menu"` may only own `menuitem`, `menuitemradio`, `menuitemcheckbox` or `group`, and
|
|
91
|
+
* the empty state's content is the caller's, carrying no role at all. A `presentation` wrapper
|
|
92
|
+
* does not help: it flattens out of the tree, so what the menu ends up owning is that content
|
|
93
|
+
* — which is why the virtualizer's `presentation` wrapper is fine and this one was not. It
|
|
94
|
+
* holds real items; this holds prose.
|
|
95
|
+
*
|
|
96
|
+
* Measured against axe: `presentation`, `none`, `status`, `group` alone and a bare `div` all
|
|
97
|
+
* fail, while a disabled `menuitem` passes — and so does a menu with no children whatsoever. It
|
|
98
|
+
* is the unallowed child that breaks it rather than the missing item.
|
|
99
|
+
*
|
|
100
|
+
* A disabled item is also the truer reading. The menu still is a menu, it has one thing in it,
|
|
101
|
+
* and that thing says there is nothing to choose and cannot be chosen. It never registers with
|
|
102
|
+
* the collection, so the keyboard never reaches it either.
|
|
103
|
+
*/
|
|
104
|
+
emptyAttributes: computed(() => ({
|
|
105
|
+
"aria-disabled": true,
|
|
106
|
+
role: "menuitem"
|
|
107
|
+
})),
|
|
87
108
|
isEmpty: computed(() => collection.size.value === 0),
|
|
88
109
|
menuAttributes: computed(() => ({
|
|
110
|
+
"aria-label": toValue(options.label),
|
|
89
111
|
"aria-labelledby": toValue(options.labelledBy),
|
|
90
112
|
"data-collection": collectionId.value,
|
|
91
113
|
"data-empty": collection.size.value === 0 ? "true" : void 0,
|
|
@@ -128,7 +128,7 @@ var useNumberField = (options = {}) => {
|
|
|
128
128
|
setInputValue: state.setInputValue,
|
|
129
129
|
validate: state.validate
|
|
130
130
|
});
|
|
131
|
-
useFormReset(element, () => state.defaultNumberValue.value, state.setNumberValue);
|
|
131
|
+
useFormReset(element, () => state.defaultNumberValue.value, state.setNumberValue, options.form);
|
|
132
132
|
/**
|
|
133
133
|
* Range validation borrowed from a real number input.
|
|
134
134
|
*
|
|
@@ -46,7 +46,7 @@ var useSelect = (options, state) => {
|
|
|
46
46
|
sensitivity: "base",
|
|
47
47
|
usage: "search"
|
|
48
48
|
});
|
|
49
|
-
const getKeyForSearch = (search, fromKey) => {
|
|
49
|
+
const getKeyForSearch = (search, fromKey) => state.collection.withOrder(() => {
|
|
50
50
|
let key = fromKey ?? state.collection.getFirstKey();
|
|
51
51
|
while (key != null) {
|
|
52
52
|
const item = state.collection.getItem(key);
|
|
@@ -56,7 +56,7 @@ var useSelect = (options, state) => {
|
|
|
56
56
|
key = state.collection.getKeyAfter(key);
|
|
57
57
|
}
|
|
58
58
|
return null;
|
|
59
|
-
};
|
|
59
|
+
});
|
|
60
60
|
const typeahead = useTypeahead({
|
|
61
61
|
focusedKey: () => state.selectedKey.value,
|
|
62
62
|
getKeyForSearch,
|
|
@@ -120,7 +120,6 @@ var useSelect = (options, state) => {
|
|
|
120
120
|
"aria-invalid": isInvalid.value || void 0,
|
|
121
121
|
"aria-label": toValue(options.ariaLabel),
|
|
122
122
|
"aria-labelledby": [valueId.value, toValue(options.ariaLabelledby) ?? fieldIds.labelId.value].filter(Boolean).join(" "),
|
|
123
|
-
"aria-required": toValue(options.isRequired) || void 0,
|
|
124
123
|
disabled: toValue(options.isDisabled) || void 0,
|
|
125
124
|
id: trigger.triggerId.value,
|
|
126
125
|
type: "button"
|
|
@@ -73,13 +73,13 @@ var useSelectionManager = (options) => {
|
|
|
73
73
|
commit(next);
|
|
74
74
|
};
|
|
75
75
|
/** The keys from `from` to `to` inclusive, in document order whichever way round they are. */
|
|
76
|
-
const keyRange = (from, to) => {
|
|
76
|
+
const keyRange = (from, to) => collection.withOrder(() => {
|
|
77
77
|
const keys = collection.orderedKeys();
|
|
78
|
-
const start =
|
|
79
|
-
const end =
|
|
78
|
+
const start = collection.getIndex(from);
|
|
79
|
+
const end = collection.getIndex(to);
|
|
80
80
|
if (start === -1 || end === -1) return [];
|
|
81
81
|
return keys.slice(Math.min(start, end), Math.max(start, end) + 1);
|
|
82
|
-
};
|
|
82
|
+
});
|
|
83
83
|
const extendSelection = (key) => {
|
|
84
84
|
if (selectionMode.value === "none") return;
|
|
85
85
|
if (selectionMode.value === "single") {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { CollectionKey, UseCollectionReturn } from "./use-collection.js";
|
|
2
|
+
import type { UseSelectionManagerReturn } from "./use-selection-manager.js";
|
|
3
|
+
import type { ComputedRef, MaybeRefOrGetter } from "vue";
|
|
4
|
+
export interface UseSingleSelectListStateOptions {
|
|
5
|
+
/** The selected item, when the caller drives it. */
|
|
6
|
+
selectedKey?: MaybeRefOrGetter<CollectionKey | undefined>;
|
|
7
|
+
/** The initially selected item. Falls back to the first item that is not disabled. */
|
|
8
|
+
defaultSelectedKey?: CollectionKey;
|
|
9
|
+
onSelectionChange?: (key: CollectionKey) => void;
|
|
10
|
+
disabledKeys?: MaybeRefOrGetter<Iterable<CollectionKey> | undefined>;
|
|
11
|
+
/** Whether the whole list is disabled: a selection that exists but cannot be changed. */
|
|
12
|
+
isDisabled?: MaybeRefOrGetter<boolean | undefined>;
|
|
13
|
+
}
|
|
14
|
+
export interface UseSingleSelectListStateReturn {
|
|
15
|
+
collection: UseCollectionReturn;
|
|
16
|
+
selection: UseSelectionManagerReturn;
|
|
17
|
+
/** The selected item, with the default resolved against the collection. */
|
|
18
|
+
selectedKey: ComputedRef<CollectionKey | null>;
|
|
19
|
+
setSelectedKey: (key: CollectionKey) => void;
|
|
20
|
+
isDisabled: ComputedRef<boolean>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Which item of a collection is selected, for a list that always has exactly one.
|
|
24
|
+
*
|
|
25
|
+
* Ported from React Stately's `useSingleSelectListState`
|
|
26
|
+
* (`react-stately/src/list/useSingleSelectListState.ts`, react-stately 3.49.0).
|
|
27
|
+
*
|
|
28
|
+
* "Always exactly one" is `disallowEmptySelection` plus a fallback for the case where nothing says
|
|
29
|
+
* which. The selection behaviour is deliberately left at toggle: whether the arrow keys choose is a
|
|
30
|
+
* question about how activation works, asked by the caller through `selectOnFocus`, not a question
|
|
31
|
+
* about what a press means.
|
|
32
|
+
*
|
|
33
|
+
* The three pieces have to be built in one order — the collection, then the fallback that reads it,
|
|
34
|
+
* then the selection manager the fallback feeds — which is the reason this is a composable rather
|
|
35
|
+
* than a few lines in the root component.
|
|
36
|
+
*/
|
|
37
|
+
export declare const useSingleSelectListState: (options?: UseSingleSelectListStateOptions) => UseSingleSelectListStateReturn;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { useControllableState } from "./use-controllable-state.js";
|
|
2
|
+
import { useCollection } from "./use-collection.js";
|
|
3
|
+
import { useSelectionManager } from "./use-selection-manager.js";
|
|
4
|
+
import { computed, toValue, watch } from "vue";
|
|
5
|
+
//#region src/composables/use-single-select-list-state.ts
|
|
6
|
+
/**
|
|
7
|
+
* Which item of a collection is selected, for a list that always has exactly one.
|
|
8
|
+
*
|
|
9
|
+
* Ported from React Stately's `useSingleSelectListState`
|
|
10
|
+
* (`react-stately/src/list/useSingleSelectListState.ts`, react-stately 3.49.0).
|
|
11
|
+
*
|
|
12
|
+
* "Always exactly one" is `disallowEmptySelection` plus a fallback for the case where nothing says
|
|
13
|
+
* which. The selection behaviour is deliberately left at toggle: whether the arrow keys choose is a
|
|
14
|
+
* question about how activation works, asked by the caller through `selectOnFocus`, not a question
|
|
15
|
+
* about what a press means.
|
|
16
|
+
*
|
|
17
|
+
* The three pieces have to be built in one order — the collection, then the fallback that reads it,
|
|
18
|
+
* then the selection manager the fallback feeds — which is the reason this is a composable rather
|
|
19
|
+
* than a few lines in the root component.
|
|
20
|
+
*/
|
|
21
|
+
var useSingleSelectListState = (options = {}) => {
|
|
22
|
+
const collection = useCollection();
|
|
23
|
+
const disabledKeySet = computed(() => new Set(toValue(options.disabledKeys) ?? []));
|
|
24
|
+
/**
|
|
25
|
+
* Whether an item can be selected, asked of the collection rather than of the selection manager.
|
|
26
|
+
*
|
|
27
|
+
* Two reasons, and either alone would be enough: the fallback below runs before the manager
|
|
28
|
+
* exists, and React Stately asks the same question the same way — an item's own disabled state
|
|
29
|
+
* or the group's disabled keys, with no `disabledBehavior` in it.
|
|
30
|
+
*/
|
|
31
|
+
const isKeyDisabled = (key) => disabledKeySet.value.has(key) || Boolean(collection.getItem(key)?.isDisabled());
|
|
32
|
+
/** The first item that can be selected, or the first item when none of them can. */
|
|
33
|
+
const findDefaultSelectedKey = () => collection.withOrder(() => {
|
|
34
|
+
let key = collection.getFirstKey();
|
|
35
|
+
while (key != null && isKeyDisabled(key) && key !== collection.getLastKey()) key = collection.getKeyAfter(key);
|
|
36
|
+
if (key != null && isKeyDisabled(key) && key === collection.getLastKey()) key = collection.getFirstKey();
|
|
37
|
+
return key;
|
|
38
|
+
});
|
|
39
|
+
const stored = useControllableState({
|
|
40
|
+
defaultValue: options.defaultSelectedKey ?? null,
|
|
41
|
+
onValueChange: (key) => {
|
|
42
|
+
if (key != null) options.onSelectionChange?.(key);
|
|
43
|
+
},
|
|
44
|
+
value: () => toValue(options.selectedKey)
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* The selected item, with the fallback resolved as a read rather than written back.
|
|
48
|
+
*
|
|
49
|
+
* React Stately can resolve it before the first render, because the collection is built by a
|
|
50
|
+
* pass that runs before it. Rendering is what creates the collection here, so writing the
|
|
51
|
+
* fallback into the selection would report a selection change nobody made, on every mount of
|
|
52
|
+
* every uncontrolled list.
|
|
53
|
+
*
|
|
54
|
+
* `collection.size` is read for its own sake: the fallback walks the collection through
|
|
55
|
+
* calls that stay outside reactivity on purpose, so without it this would resolve against the
|
|
56
|
+
* empty collection of the first render and keep that answer.
|
|
57
|
+
*/
|
|
58
|
+
const selectedKey = computed(() => {
|
|
59
|
+
const key = stored.state.value;
|
|
60
|
+
if (stored.isControlled.value) return key ?? null;
|
|
61
|
+
if (key != null && collection.getItem(key)) return key;
|
|
62
|
+
return findDefaultSelectedKey();
|
|
63
|
+
});
|
|
64
|
+
const selection = useSelectionManager({
|
|
65
|
+
collection,
|
|
66
|
+
disabledKeys: () => toValue(options.disabledKeys),
|
|
67
|
+
disallowEmptySelection: true,
|
|
68
|
+
onSelectionChange: (keys) => {
|
|
69
|
+
if (keys === "all") return;
|
|
70
|
+
const [key] = [...keys];
|
|
71
|
+
if (key != null) stored.setState(key);
|
|
72
|
+
},
|
|
73
|
+
selectedKeys: () => selectedKey.value != null ? [selectedKey.value] : [],
|
|
74
|
+
selectionMode: "single"
|
|
75
|
+
});
|
|
76
|
+
let lastSelectedKey = selectedKey.value;
|
|
77
|
+
/**
|
|
78
|
+
* The selection places focus, because on a list like this it is the only thing that can.
|
|
79
|
+
*
|
|
80
|
+
* React Aria's tab list element ends up with no tab index of its own, so the roving index on
|
|
81
|
+
* the selected item is the only way in — and with no focused key nothing inside is tabbable
|
|
82
|
+
* either, which would put the whole list out of the tab order.
|
|
83
|
+
*
|
|
84
|
+
* Post-flush and keyed on the collection's size, because setting a focused key the collection
|
|
85
|
+
* does not hold is refused: the first attempt runs before the items have registered, and the
|
|
86
|
+
* registration is what makes the retry land.
|
|
87
|
+
*/
|
|
88
|
+
watch([
|
|
89
|
+
selectedKey,
|
|
90
|
+
collection.size,
|
|
91
|
+
() => selection.focusedKey.value == null
|
|
92
|
+
], () => {
|
|
93
|
+
const key = selectedKey.value;
|
|
94
|
+
if (key == null) return;
|
|
95
|
+
if (selection.focusedKey.value == null || !selection.isFocused.value && key !== lastSelectedKey) selection.setFocusedKey(key);
|
|
96
|
+
lastSelectedKey = key;
|
|
97
|
+
}, {
|
|
98
|
+
flush: "post",
|
|
99
|
+
immediate: true
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
collection,
|
|
103
|
+
isDisabled: computed(() => Boolean(toValue(options.isDisabled))),
|
|
104
|
+
selectedKey,
|
|
105
|
+
selection,
|
|
106
|
+
setSelectedKey: (key) => stored.setState(key)
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
//#endregion
|
|
110
|
+
export { useSingleSelectListState };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { useMove } from "./use-move.js";
|
|
1
2
|
import { useFormReset } from "./use-form-reset.js";
|
|
2
3
|
import { setFormValue } from "../utils/form-value.js";
|
|
3
4
|
import { clamp } from "../utils/number.js";
|
|
4
|
-
import { useMove } from "./use-move.js";
|
|
5
5
|
import { computed, nextTick, onScopeDispose, toValue, watch, watchEffect } from "vue";
|
|
6
6
|
//#region src/composables/use-slider-thumb.ts
|
|
7
7
|
/**
|
|
@@ -110,7 +110,7 @@ var useSliderThumb = (options) => {
|
|
|
110
110
|
nextTick(() => {
|
|
111
111
|
setFormValue(inputEl.value, String(state.getThumbValue(index.value)));
|
|
112
112
|
});
|
|
113
|
-
});
|
|
113
|
+
}, options.form);
|
|
114
114
|
watch([inputEl, () => state.getThumbValue(index.value)], ([input, value]) => setFormValue(input, String(value)), {
|
|
115
115
|
flush: "post",
|
|
116
116
|
immediate: true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { setInteractionModality } from "./use-interaction-states.js";
|
|
2
|
-
import { clamp } from "../utils/number.js";
|
|
3
2
|
import { useMove } from "./use-move.js";
|
|
3
|
+
import { clamp } from "../utils/number.js";
|
|
4
4
|
import { computed, onScopeDispose, toValue } from "vue";
|
|
5
5
|
//#region src/composables/use-slider.ts
|
|
6
6
|
/**
|
|
@@ -1,45 +1,36 @@
|
|
|
1
|
-
import type { CollectionKey
|
|
2
|
-
import type {
|
|
1
|
+
import type { CollectionKey } from "./use-collection.js";
|
|
2
|
+
import type { UseSingleSelectListStateOptions, UseSingleSelectListStateReturn } from "./use-single-select-list-state.js";
|
|
3
3
|
import type { ComputedRef, MaybeRefOrGetter } from "vue";
|
|
4
|
-
export interface UseTabListStateOptions {
|
|
5
|
-
/** The selected tab, when the caller drives it. */
|
|
6
|
-
selectedKey?: MaybeRefOrGetter<CollectionKey | undefined>;
|
|
7
|
-
/** The initially selected tab. Falls back to the first tab that is not disabled. */
|
|
8
|
-
defaultSelectedKey?: CollectionKey;
|
|
9
|
-
onSelectionChange?: (key: CollectionKey) => void;
|
|
10
|
-
disabledKeys?: MaybeRefOrGetter<Iterable<CollectionKey> | undefined>;
|
|
11
|
-
/** Whether the whole tab list is disabled: a selection that exists but cannot be changed. */
|
|
12
|
-
isDisabled?: MaybeRefOrGetter<boolean | undefined>;
|
|
4
|
+
export interface UseTabListStateOptions extends UseSingleSelectListStateOptions {
|
|
13
5
|
/** A base the tab and panel ids are derived from. Generated when absent. */
|
|
14
6
|
id?: MaybeRefOrGetter<string | undefined>;
|
|
15
7
|
}
|
|
16
|
-
export interface UseTabListStateReturn {
|
|
17
|
-
collection: UseCollectionReturn;
|
|
18
|
-
selection: UseSelectionManagerReturn;
|
|
19
|
-
/** The selected tab, with the default resolved against the collection. */
|
|
20
|
-
selectedKey: ComputedRef<CollectionKey | null>;
|
|
21
|
-
setSelectedKey: (key: CollectionKey) => void;
|
|
22
|
-
isDisabled: ComputedRef<boolean>;
|
|
8
|
+
export interface UseTabListStateReturn extends UseSingleSelectListStateReturn {
|
|
23
9
|
/** The tab list's own id, which the tab and panel ids hang off. */
|
|
24
10
|
tabsId: ComputedRef<string>;
|
|
25
11
|
/** `undefined` for a key that does not exist, so no attribute points at nothing. */
|
|
26
12
|
tabId: (key: CollectionKey | null | undefined) => string | undefined;
|
|
27
13
|
tabPanelId: (key: CollectionKey | null | undefined) => string | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Whether a panel for this key is in the document.
|
|
16
|
+
*
|
|
17
|
+
* Tabs are usable without panels - driving something rendered elsewhere on the page is a normal
|
|
18
|
+
* arrangement - and a tab that points `aria-controls` at an element that was never rendered is
|
|
19
|
+
* worse than one that points nowhere.
|
|
20
|
+
*/
|
|
21
|
+
hasPanel: (key: CollectionKey | null | undefined) => boolean;
|
|
22
|
+
/** Called by a panel while it is mounted. Returns the matching unregister. */
|
|
23
|
+
registerPanel: (key: CollectionKey) => () => void;
|
|
28
24
|
}
|
|
29
25
|
/**
|
|
30
26
|
* Which tab is selected, and the ids that tie each tab to its panel.
|
|
31
27
|
*
|
|
32
|
-
* Ported from React Stately's `useTabListState`
|
|
33
|
-
*
|
|
34
|
-
*
|
|
28
|
+
* Ported from React Stately's `useTabListState` (`react-stately/src/tabs/useTabListState.ts`,
|
|
29
|
+
* react-stately 3.49.0), together with the id scheme from `react-aria/src/tabs/utils.ts`
|
|
30
|
+
* (react-aria 3.51.0).
|
|
35
31
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* caller through `selectOnFocus`, not a question about what a press means.
|
|
40
|
-
*
|
|
41
|
-
* The three pieces have to be built in one order — the collection, then the fallback that reads
|
|
42
|
-
* it, then the selection manager the fallback feeds — which is the reason this is a composable
|
|
43
|
-
* rather than a few lines in the root component.
|
|
32
|
+
* The selection itself is {@link useSingleSelectListState}, the layer React Stately builds this
|
|
33
|
+
* one on. What is left here is what makes a tab list a tab list rather than any other list with
|
|
34
|
+
* one selection: the ids, and the panels they point at.
|
|
44
35
|
*/
|
|
45
36
|
export declare const useTabListState: (options?: UseTabListStateOptions) => UseTabListStateReturn;
|
|
@@ -1,114 +1,35 @@
|
|
|
1
1
|
import { useId as useId$1 } from "./use-id.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { useSelectionManager } from "./use-selection-manager.js";
|
|
5
|
-
import { computed, toValue, watch } from "vue";
|
|
2
|
+
import { useSingleSelectListState } from "./use-single-select-list-state.js";
|
|
3
|
+
import { shallowRef, toValue } from "vue";
|
|
6
4
|
//#region src/composables/use-tab-list-state.ts
|
|
7
5
|
/**
|
|
8
6
|
* Which tab is selected, and the ids that tie each tab to its panel.
|
|
9
7
|
*
|
|
10
|
-
* Ported from React Stately's `useTabListState`
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* Ported from React Stately's `useTabListState` (`react-stately/src/tabs/useTabListState.ts`,
|
|
9
|
+
* react-stately 3.49.0), together with the id scheme from `react-aria/src/tabs/utils.ts`
|
|
10
|
+
* (react-aria 3.51.0).
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* caller through `selectOnFocus`, not a question about what a press means.
|
|
18
|
-
*
|
|
19
|
-
* The three pieces have to be built in one order — the collection, then the fallback that reads
|
|
20
|
-
* it, then the selection manager the fallback feeds — which is the reason this is a composable
|
|
21
|
-
* rather than a few lines in the root component.
|
|
12
|
+
* The selection itself is {@link useSingleSelectListState}, the layer React Stately builds this
|
|
13
|
+
* one on. What is left here is what makes a tab list a tab list rather than any other list with
|
|
14
|
+
* one selection: the ids, and the panels they point at.
|
|
22
15
|
*/
|
|
23
16
|
var useTabListState = (options = {}) => {
|
|
24
|
-
const
|
|
25
|
-
const disabledKeySet = computed(() => new Set(toValue(options.disabledKeys) ?? []));
|
|
26
|
-
/**
|
|
27
|
-
* Whether a tab can be selected, asked of the collection rather than of the selection manager.
|
|
28
|
-
*
|
|
29
|
-
* Two reasons, and either alone would be enough: the fallback below runs before the manager
|
|
30
|
-
* exists, and React Stately asks the same question the same way — an item's own disabled state
|
|
31
|
-
* or the group's disabled keys, with no `disabledBehavior` in it.
|
|
32
|
-
*/
|
|
33
|
-
const isKeyDisabled = (key) => disabledKeySet.value.has(key) || Boolean(collection.getItem(key)?.isDisabled());
|
|
34
|
-
/** The first tab that can be selected, or the first tab when none of them can. */
|
|
35
|
-
const findDefaultSelectedKey = () => {
|
|
36
|
-
let key = collection.getFirstKey();
|
|
37
|
-
while (key != null && isKeyDisabled(key) && key !== collection.getLastKey()) key = collection.getKeyAfter(key);
|
|
38
|
-
if (key != null && isKeyDisabled(key) && key === collection.getLastKey()) key = collection.getFirstKey();
|
|
39
|
-
return key;
|
|
40
|
-
};
|
|
41
|
-
const stored = useControllableState({
|
|
42
|
-
defaultValue: options.defaultSelectedKey ?? null,
|
|
43
|
-
onValueChange: (key) => {
|
|
44
|
-
if (key != null) options.onSelectionChange?.(key);
|
|
45
|
-
},
|
|
46
|
-
value: () => toValue(options.selectedKey)
|
|
47
|
-
});
|
|
48
|
-
/**
|
|
49
|
-
* The selected tab, with the fallback resolved as a read rather than written back.
|
|
50
|
-
*
|
|
51
|
-
* React Stately can resolve it before the first render, because the collection is built by a
|
|
52
|
-
* pass that runs before it. Rendering is what creates the collection here, so writing the
|
|
53
|
-
* fallback into the selection would report a selection change nobody made, on every mount of
|
|
54
|
-
* every uncontrolled tab list.
|
|
55
|
-
*
|
|
56
|
-
* `collection.size` is read for its own sake: the fallback walks the collection through
|
|
57
|
-
* calls that stay outside reactivity on purpose, so without it this would resolve against the
|
|
58
|
-
* empty collection of the first render and keep that answer.
|
|
59
|
-
*/
|
|
60
|
-
const selectedKey = computed(() => {
|
|
61
|
-
const key = stored.state.value;
|
|
62
|
-
if (stored.isControlled.value) return key ?? null;
|
|
63
|
-
if (key != null && collection.getItem(key)) return key;
|
|
64
|
-
return findDefaultSelectedKey();
|
|
65
|
-
});
|
|
66
|
-
const selection = useSelectionManager({
|
|
67
|
-
collection,
|
|
68
|
-
disabledKeys: () => toValue(options.disabledKeys),
|
|
69
|
-
disallowEmptySelection: true,
|
|
70
|
-
onSelectionChange: (keys) => {
|
|
71
|
-
if (keys === "all") return;
|
|
72
|
-
const [key] = [...keys];
|
|
73
|
-
if (key != null) stored.setState(key);
|
|
74
|
-
},
|
|
75
|
-
selectedKeys: () => selectedKey.value != null ? [selectedKey.value] : [],
|
|
76
|
-
selectionMode: "single"
|
|
77
|
-
});
|
|
78
|
-
let lastSelectedKey = selectedKey.value;
|
|
79
|
-
/**
|
|
80
|
-
* The selection places focus, because on a tab list it is the only thing that can.
|
|
81
|
-
*
|
|
82
|
-
* React Aria's tab list element ends up with no tab index of its own, so the roving index on
|
|
83
|
-
* the selected tab is the only way in — and with no focused key nothing inside is tabbable
|
|
84
|
-
* either, which would put the whole tab list out of the tab order.
|
|
85
|
-
*
|
|
86
|
-
* Post-flush and keyed on the collection's size, because setting a focused key the collection
|
|
87
|
-
* does not hold is refused: the first attempt runs before the tabs have registered, and the
|
|
88
|
-
* registration is what makes the retry land.
|
|
89
|
-
*/
|
|
90
|
-
watch([
|
|
91
|
-
selectedKey,
|
|
92
|
-
collection.size,
|
|
93
|
-
() => selection.focusedKey.value == null
|
|
94
|
-
], () => {
|
|
95
|
-
const key = selectedKey.value;
|
|
96
|
-
if (key == null) return;
|
|
97
|
-
if (selection.focusedKey.value == null || !selection.isFocused.value && key !== lastSelectedKey) selection.setFocusedKey(key);
|
|
98
|
-
lastSelectedKey = key;
|
|
99
|
-
}, {
|
|
100
|
-
flush: "post",
|
|
101
|
-
immediate: true
|
|
102
|
-
});
|
|
17
|
+
const list = useSingleSelectListState(options);
|
|
103
18
|
const tabsId = useId$1(() => toValue(options.id));
|
|
104
19
|
/** React Aria strips whitespace out of a string key so the id stays a single token. */
|
|
105
20
|
const idFor = (key, role) => key == null ? void 0 : `${tabsId.value}-${role}-${String(key).replace(/\s+/g, "")}`;
|
|
21
|
+
const panelKeys = shallowRef(/* @__PURE__ */ new Set());
|
|
106
22
|
return {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
23
|
+
...list,
|
|
24
|
+
hasPanel: (key) => key != null && panelKeys.value.has(key),
|
|
25
|
+
registerPanel: (key) => {
|
|
26
|
+
panelKeys.value = new Set(panelKeys.value).add(key);
|
|
27
|
+
return () => {
|
|
28
|
+
const next = new Set(panelKeys.value);
|
|
29
|
+
next.delete(key);
|
|
30
|
+
panelKeys.value = next;
|
|
31
|
+
};
|
|
32
|
+
},
|
|
112
33
|
tabId: (key) => idFor(key, "tab"),
|
|
113
34
|
tabPanelId: (key) => idFor(key, "tabpanel"),
|
|
114
35
|
tabsId
|
|
@@ -91,7 +91,7 @@ var useTextField = (options = {}) => {
|
|
|
91
91
|
reassert();
|
|
92
92
|
};
|
|
93
93
|
const initialValue = value.value;
|
|
94
|
-
if (!options.skipFormReset) useFormReset(element, () => toValue(options.defaultValue) ?? initialValue, setState);
|
|
94
|
+
if (!options.skipFormReset) useFormReset(element, () => toValue(options.defaultValue) ?? initialValue, setState, options.form);
|
|
95
95
|
useFormValidation(element, validation, { commitOnBlur: () => toValue(options.commitOnBlur) });
|
|
96
96
|
watch(element, (control, previous) => {
|
|
97
97
|
if (control && !previous && toValue(options.autoFocus)) control.focus();
|
|
@@ -1,22 +1,72 @@
|
|
|
1
1
|
import type { Size } from "../utils/virtualizer-geometry.js";
|
|
2
2
|
import type { ComputedRef, MaybeRefOrGetter } from "vue";
|
|
3
|
-
import { Rect } from "../utils/virtualizer-geometry.js";
|
|
3
|
+
import { Point, Rect } from "../utils/virtualizer-geometry.js";
|
|
4
4
|
export interface UseVirtualizerScrollOptions {
|
|
5
5
|
/** The element that scrolls — the collection itself. */
|
|
6
6
|
element: MaybeRefOrGetter<HTMLElement | null | undefined>;
|
|
7
|
-
/** The size of everything the layout produced,
|
|
7
|
+
/** The size of everything the layout produced, which is what gives the container its scroll. */
|
|
8
8
|
contentSize: () => Size;
|
|
9
9
|
/** Whether the collection is mid-scroll, which the content wrapper turns off pointers for. */
|
|
10
10
|
isScrolling: () => boolean;
|
|
11
11
|
onVisibleRectChange: (rect: Rect) => void;
|
|
12
12
|
onSizeChange: (size: Size) => void;
|
|
13
|
+
/**
|
|
14
|
+
* How far rows measured above the window have pushed the content under it, and a way to say the
|
|
15
|
+
* shift has been applied.
|
|
16
|
+
*
|
|
17
|
+
* Rows of a height nobody declared are placed at an estimate and corrected once they are in the
|
|
18
|
+
* DOM. A correction above the window moves everything below it — so without putting the shift
|
|
19
|
+
* back into the scroll offset, the collection slides under the pointer while it is read.
|
|
20
|
+
*/
|
|
21
|
+
scrollAdjustment?: () => number;
|
|
22
|
+
takeScrollAdjustment?: () => number;
|
|
13
23
|
onScrollStart?: () => void;
|
|
14
24
|
onScrollEnd?: () => void;
|
|
15
25
|
}
|
|
26
|
+
/** Where to scroll the container to. An axis left out stays where it is. */
|
|
27
|
+
export interface ScrollToOffset {
|
|
28
|
+
left?: number;
|
|
29
|
+
top?: number;
|
|
30
|
+
}
|
|
31
|
+
/** What the container's own style says about it, as far as a scrollbar drawn for it has to know. */
|
|
32
|
+
export interface ScrollBoxInfo {
|
|
33
|
+
/** Which way the inline axis runs, which decides which edge the content starts at. */
|
|
34
|
+
direction: "ltr" | "rtl";
|
|
35
|
+
/** How far the content sits in from the container's top edge. */
|
|
36
|
+
paddingTop: number;
|
|
37
|
+
/** How far the content sits in from the container's inline start edge. */
|
|
38
|
+
paddingInlineStart: number;
|
|
39
|
+
/** Whether the container scrolls along the inline axis, rather than clipping or letting content out. */
|
|
40
|
+
scrollsX: boolean;
|
|
41
|
+
/** Whether the container scrolls along the block axis. */
|
|
42
|
+
scrollsY: boolean;
|
|
43
|
+
}
|
|
16
44
|
export interface UseVirtualizerScrollReturn {
|
|
17
45
|
/** The style for the wrapper that gives the container something to scroll. */
|
|
18
46
|
contentStyle: ComputedRef<Record<string, string | undefined>>;
|
|
19
47
|
/** Re-measures the container. Called on mount, on resize, and by tests. */
|
|
20
48
|
measure: () => void;
|
|
49
|
+
/** The container's padding and which of its axes scroll, read whenever it is measured. */
|
|
50
|
+
scrollBox: ComputedRef<ScrollBoxInfo>;
|
|
51
|
+
/**
|
|
52
|
+
* How far the container is scrolled, as the element reports it.
|
|
53
|
+
*
|
|
54
|
+
* Along the block axis the offset is clamped into the content, as the visible rectangle is.
|
|
55
|
+
* Along the inline axis it keeps its sign: a right-to-left box scrolls into negative offsets,
|
|
56
|
+
* and a scrollbar drawn for it has to know which way the content ran.
|
|
57
|
+
*/
|
|
58
|
+
scrollOffset: ComputedRef<Point>;
|
|
59
|
+
/** The container's scrollable overflow, per axis — what the offset runs up to, less the box. */
|
|
60
|
+
scrollSize: ComputedRef<Size>;
|
|
61
|
+
/**
|
|
62
|
+
* Scrolls the container from here, and moves the window in the same task.
|
|
63
|
+
*
|
|
64
|
+
* A scroll the browser makes on its own reaches this composable a frame after the offset moved,
|
|
65
|
+
* and the compositor has already drawn that frame with the rows built for the old offset. A
|
|
66
|
+
* scroll made here is read back at once, so the offset and the rows it calls for are committed
|
|
67
|
+
* by the same frame — which is what lets a scrollbar the collection draws itself never show an
|
|
68
|
+
* empty window.
|
|
69
|
+
*/
|
|
70
|
+
scrollTo: (offset: ScrollToOffset) => void;
|
|
21
71
|
}
|
|
22
72
|
export declare const useVirtualizerScroll: (options: UseVirtualizerScrollOptions) => UseVirtualizerScrollReturn;
|