@salt-ds/core 1.71.0 → 1.72.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/CHANGELOG.md +82 -0
- package/css/salt-core.css +189 -77
- package/dist-cjs/accordion/AccordionHeader.css.js +1 -1
- package/dist-cjs/avatar/Avatar.css.js +1 -1
- package/dist-cjs/badge/Badge.css.js +1 -1
- package/dist-cjs/banner/Banner.css.js +1 -1
- package/dist-cjs/breadcrumbs/Breadcrumb.css.js +1 -1
- package/dist-cjs/breadcrumbs/Breadcrumbs.css.js +1 -1
- package/dist-cjs/checkbox/Checkbox.css.js +1 -1
- package/dist-cjs/checkbox/CheckboxIcon.css.js +1 -1
- package/dist-cjs/combo-box/ComboBox.js +18 -36
- package/dist-cjs/combo-box/ComboBox.js.map +1 -1
- package/dist-cjs/combo-box/useComboBox.js +21 -21
- package/dist-cjs/combo-box/useComboBox.js.map +1 -1
- package/dist-cjs/dropdown/Dropdown.js +29 -30
- package/dist-cjs/dropdown/Dropdown.js.map +1 -1
- package/dist-cjs/file-drop-zone/FileDropZone.css.js +1 -1
- package/dist-cjs/form-field/FormField.css.js +1 -1
- package/dist-cjs/form-field/FormFieldHelperText.css.js +1 -1
- package/dist-cjs/form-field/FormFieldLabel.css.js +1 -1
- package/dist-cjs/form-field/FormFieldLabel.js +1 -1
- package/dist-cjs/form-field/FormFieldLabel.js.map +1 -1
- package/dist-cjs/index.js +2 -0
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/input/Input.css.js +1 -1
- package/dist-cjs/interactable-card/InteractableCard.css.js +1 -1
- package/dist-cjs/interactable-card/InteractableCard.js +18 -7
- package/dist-cjs/interactable-card/InteractableCard.js.map +1 -1
- package/dist-cjs/interactable-card/InteractableCardGroup.js +71 -39
- package/dist-cjs/interactable-card/InteractableCardGroup.js.map +1 -1
- package/dist-cjs/interactable-card/InteractableCardGroupContext.js.map +1 -1
- package/dist-cjs/interactable-card/useInteractableCard.js +2 -3
- package/dist-cjs/interactable-card/useInteractableCard.js.map +1 -1
- package/dist-cjs/kbd/Kbd.css.js +1 -1
- package/dist-cjs/link/Link.css.js +1 -1
- package/dist-cjs/list-box/ListBox.js +19 -26
- package/dist-cjs/list-box/ListBox.js.map +1 -1
- package/dist-cjs/list-control/ListControlNavigationKeys.js +74 -0
- package/dist-cjs/list-control/ListControlNavigationKeys.js.map +1 -0
- package/dist-cjs/list-control/ListControlOptionContext.js +47 -0
- package/dist-cjs/list-control/ListControlOptionContext.js.map +1 -0
- package/dist-cjs/list-control/ListControlOptionStore.js +159 -0
- package/dist-cjs/list-control/ListControlOptionStore.js.map +1 -0
- package/dist-cjs/list-control/ListControlProvider.js +39 -0
- package/dist-cjs/list-control/ListControlProvider.js.map +1 -0
- package/dist-cjs/list-control/ListControlRegistry.js +161 -0
- package/dist-cjs/list-control/ListControlRegistry.js.map +1 -0
- package/dist-cjs/list-control/ListControlState.js +137 -109
- package/dist-cjs/list-control/ListControlState.js.map +1 -1
- package/dist-cjs/mega-menu/MegaMenuGroupHeading.css.js +1 -1
- package/dist-cjs/mega-menu/MegaMenuListItem.css.js +1 -1
- package/dist-cjs/menu/MenuGroup.css.js +1 -1
- package/dist-cjs/menu/MenuItem.css.js +1 -1
- package/dist-cjs/navigation-item/NavigationItem.css.js +1 -1
- package/dist-cjs/number-input/NumberInput.js +2 -2
- package/dist-cjs/number-input/NumberInput.js.map +1 -1
- package/dist-cjs/option/Option.js +58 -39
- package/dist-cjs/option/Option.js.map +1 -1
- package/dist-cjs/option/OptionGroup.css.js +1 -1
- package/dist-cjs/overlay/Overlay.js +12 -2
- package/dist-cjs/overlay/Overlay.js.map +1 -1
- package/dist-cjs/overlay/OverlayContext.js +6 -0
- package/dist-cjs/overlay/OverlayContext.js.map +1 -1
- package/dist-cjs/overlay/OverlayFooter.css.js +6 -0
- package/dist-cjs/overlay/OverlayFooter.css.js.map +1 -0
- package/dist-cjs/overlay/OverlayFooter.js +30 -0
- package/dist-cjs/overlay/OverlayFooter.js.map +1 -0
- package/dist-cjs/overlay/OverlayHeader.css.js +1 -1
- package/dist-cjs/overlay/OverlayHeader.js +51 -11
- package/dist-cjs/overlay/OverlayHeader.js.map +1 -1
- package/dist-cjs/overlay/OverlayPanel.css.js +1 -1
- package/dist-cjs/overlay/OverlayPanel.js +20 -7
- package/dist-cjs/overlay/OverlayPanel.js.map +1 -1
- package/dist-cjs/overlay/OverlayPanelContent.css.js +1 -1
- package/dist-cjs/overlay/OverlayPanelContent.js +11 -13
- package/dist-cjs/overlay/OverlayPanelContent.js.map +1 -1
- package/dist-cjs/overlay/hasOverlaySection.js +24 -0
- package/dist-cjs/overlay/hasOverlaySection.js.map +1 -0
- package/dist-cjs/pill-input/PillInput.css.js +1 -1
- package/dist-cjs/pill-input/PillInput.js +2 -2
- package/dist-cjs/pill-input/PillInput.js.map +1 -1
- package/dist-cjs/radio-button/RadioButton.css.js +1 -1
- package/dist-cjs/radio-button/RadioButtonIcon.css.js +1 -1
- package/dist-cjs/rating/Rating.css.js +1 -1
- package/dist-cjs/slider/internal/SliderTrack.css.js +1 -1
- package/dist-cjs/stepper/internal/StepText.css.js +1 -1
- package/dist-cjs/switch/Switch.css.js +1 -1
- package/dist-cjs/table/Table.css.js +1 -1
- package/dist-cjs/tag/Tag.css.js +1 -1
- package/dist-cjs/text/Text.css.js +1 -1
- package/dist-cjs/toast/Toast.css.js +1 -1
- package/dist-cjs/toggle-button/ToggleButton.js +8 -2
- package/dist-cjs/toggle-button/ToggleButton.js.map +1 -1
- package/dist-cjs/toggle-button-group/ToggleButtonGroup.js +71 -8
- package/dist-cjs/toggle-button-group/ToggleButtonGroup.js.map +1 -1
- package/dist-cjs/toggle-button-group/ToggleButtonGroupContext.js.map +1 -1
- package/dist-cjs/toggletip/ToggletipPanel.css.js +1 -1
- package/dist-cjs/tooltip/Tooltip.css.js +1 -1
- package/dist-cjs/vertical-navigation/VerticalNavigationItemContent.css.js +1 -1
- package/dist-cjs/vertical-navigation/VerticalNavigationSubMenu.css.js +1 -1
- package/dist-es/accordion/AccordionHeader.css.js +1 -1
- package/dist-es/avatar/Avatar.css.js +1 -1
- package/dist-es/badge/Badge.css.js +1 -1
- package/dist-es/banner/Banner.css.js +1 -1
- package/dist-es/breadcrumbs/Breadcrumb.css.js +1 -1
- package/dist-es/breadcrumbs/Breadcrumbs.css.js +1 -1
- package/dist-es/checkbox/Checkbox.css.js +1 -1
- package/dist-es/checkbox/CheckboxIcon.css.js +1 -1
- package/dist-es/combo-box/ComboBox.js +18 -36
- package/dist-es/combo-box/ComboBox.js.map +1 -1
- package/dist-es/combo-box/useComboBox.js +21 -21
- package/dist-es/combo-box/useComboBox.js.map +1 -1
- package/dist-es/dropdown/Dropdown.js +29 -30
- package/dist-es/dropdown/Dropdown.js.map +1 -1
- package/dist-es/file-drop-zone/FileDropZone.css.js +1 -1
- package/dist-es/form-field/FormField.css.js +1 -1
- package/dist-es/form-field/FormFieldHelperText.css.js +1 -1
- package/dist-es/form-field/FormFieldLabel.css.js +1 -1
- package/dist-es/form-field/FormFieldLabel.js +1 -1
- package/dist-es/form-field/FormFieldLabel.js.map +1 -1
- package/dist-es/index.js +1 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/input/Input.css.js +1 -1
- package/dist-es/interactable-card/InteractableCard.css.js +1 -1
- package/dist-es/interactable-card/InteractableCard.js +18 -7
- package/dist-es/interactable-card/InteractableCard.js.map +1 -1
- package/dist-es/interactable-card/InteractableCardGroup.js +72 -40
- package/dist-es/interactable-card/InteractableCardGroup.js.map +1 -1
- package/dist-es/interactable-card/InteractableCardGroupContext.js.map +1 -1
- package/dist-es/interactable-card/useInteractableCard.js +2 -3
- package/dist-es/interactable-card/useInteractableCard.js.map +1 -1
- package/dist-es/kbd/Kbd.css.js +1 -1
- package/dist-es/link/Link.css.js +1 -1
- package/dist-es/list-box/ListBox.js +19 -26
- package/dist-es/list-box/ListBox.js.map +1 -1
- package/dist-es/list-control/ListControlNavigationKeys.js +69 -0
- package/dist-es/list-control/ListControlNavigationKeys.js.map +1 -0
- package/dist-es/list-control/ListControlOptionContext.js +44 -0
- package/dist-es/list-control/ListControlOptionContext.js.map +1 -0
- package/dist-es/list-control/ListControlOptionStore.js +153 -0
- package/dist-es/list-control/ListControlOptionStore.js.map +1 -0
- package/dist-es/list-control/ListControlProvider.js +37 -0
- package/dist-es/list-control/ListControlProvider.js.map +1 -0
- package/dist-es/list-control/ListControlRegistry.js +158 -0
- package/dist-es/list-control/ListControlRegistry.js.map +1 -0
- package/dist-es/list-control/ListControlState.js +137 -110
- package/dist-es/list-control/ListControlState.js.map +1 -1
- package/dist-es/mega-menu/MegaMenuGroupHeading.css.js +1 -1
- package/dist-es/mega-menu/MegaMenuListItem.css.js +1 -1
- package/dist-es/menu/MenuGroup.css.js +1 -1
- package/dist-es/menu/MenuItem.css.js +1 -1
- package/dist-es/navigation-item/NavigationItem.css.js +1 -1
- package/dist-es/number-input/NumberInput.js +2 -2
- package/dist-es/number-input/NumberInput.js.map +1 -1
- package/dist-es/option/Option.js +59 -40
- package/dist-es/option/Option.js.map +1 -1
- package/dist-es/option/OptionGroup.css.js +1 -1
- package/dist-es/overlay/Overlay.js +13 -3
- package/dist-es/overlay/Overlay.js.map +1 -1
- package/dist-es/overlay/OverlayContext.js +6 -0
- package/dist-es/overlay/OverlayContext.js.map +1 -1
- package/dist-es/overlay/OverlayFooter.css.js +4 -0
- package/dist-es/overlay/OverlayFooter.css.js.map +1 -0
- package/dist-es/overlay/OverlayFooter.js +28 -0
- package/dist-es/overlay/OverlayFooter.js.map +1 -0
- package/dist-es/overlay/OverlayHeader.css.js +1 -1
- package/dist-es/overlay/OverlayHeader.js +51 -11
- package/dist-es/overlay/OverlayHeader.js.map +1 -1
- package/dist-es/overlay/OverlayPanel.css.js +1 -1
- package/dist-es/overlay/OverlayPanel.js +20 -7
- package/dist-es/overlay/OverlayPanel.js.map +1 -1
- package/dist-es/overlay/OverlayPanelContent.css.js +1 -1
- package/dist-es/overlay/OverlayPanelContent.js +11 -13
- package/dist-es/overlay/OverlayPanelContent.js.map +1 -1
- package/dist-es/overlay/hasOverlaySection.js +22 -0
- package/dist-es/overlay/hasOverlaySection.js.map +1 -0
- package/dist-es/pill-input/PillInput.css.js +1 -1
- package/dist-es/pill-input/PillInput.js +2 -2
- package/dist-es/pill-input/PillInput.js.map +1 -1
- package/dist-es/radio-button/RadioButton.css.js +1 -1
- package/dist-es/radio-button/RadioButtonIcon.css.js +1 -1
- package/dist-es/rating/Rating.css.js +1 -1
- package/dist-es/slider/internal/SliderTrack.css.js +1 -1
- package/dist-es/stepper/internal/StepText.css.js +1 -1
- package/dist-es/switch/Switch.css.js +1 -1
- package/dist-es/table/Table.css.js +1 -1
- package/dist-es/tag/Tag.css.js +1 -1
- package/dist-es/text/Text.css.js +1 -1
- package/dist-es/toast/Toast.css.js +1 -1
- package/dist-es/toggle-button/ToggleButton.js +8 -2
- package/dist-es/toggle-button/ToggleButton.js.map +1 -1
- package/dist-es/toggle-button-group/ToggleButtonGroup.js +71 -8
- package/dist-es/toggle-button-group/ToggleButtonGroup.js.map +1 -1
- package/dist-es/toggle-button-group/ToggleButtonGroupContext.js.map +1 -1
- package/dist-es/toggletip/ToggletipPanel.css.js +1 -1
- package/dist-es/tooltip/Tooltip.css.js +1 -1
- package/dist-es/vertical-navigation/VerticalNavigationItemContent.css.js +1 -1
- package/dist-es/vertical-navigation/VerticalNavigationSubMenu.css.js +1 -1
- package/dist-types/combo-box/useComboBox.d.ts +3 -6
- package/dist-types/interactable-card/InteractableCardGroupContext.d.ts +2 -0
- package/dist-types/interactable-card/useInteractableCard.d.ts +1 -2
- package/dist-types/list-control/ListControlNavigationKeys.d.ts +30 -0
- package/dist-types/list-control/ListControlOptionContext.d.ts +18 -0
- package/dist-types/list-control/ListControlOptionStore.d.ts +17 -0
- package/dist-types/list-control/ListControlProvider.d.ts +11 -0
- package/dist-types/list-control/ListControlRegistry.d.ts +22 -0
- package/dist-types/list-control/ListControlState.d.ts +6 -6
- package/dist-types/option/Option.d.ts +3 -1
- package/dist-types/overlay/Overlay.d.ts +2 -1
- package/dist-types/overlay/OverlayContext.d.ts +4 -0
- package/dist-types/overlay/OverlayFooter.d.ts +4 -0
- package/dist-types/overlay/hasOverlaySection.d.ts +2 -0
- package/dist-types/overlay/index.d.ts +1 -0
- package/dist-types/toggle-button-group/ToggleButtonGroupContext.d.ts +2 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListControlOptionStore.js","sources":["../src/list-control/ListControlOptionStore.ts"],"sourcesContent":["import type { OptionValue } from \"./ListControlContext\";\n\nexport const OPTION_STATE_ACTIVE = 1;\nexport const OPTION_STATE_SELECTED = 2;\nexport const OPTION_STATE_FOCUS_VISIBLE = 4;\n\nexport type OptionStateSnapshot = number;\n\nexport function hasOptionState(\n snapshot: OptionStateSnapshot,\n state: OptionStateSnapshot,\n): boolean {\n return (snapshot & state) !== 0;\n}\n\ninterface OptionEntry<Item> {\n generation: number;\n option: OptionValue<Item>;\n}\n\n/** Internal per-list store used to target updates at affected Options. */\nexport class ListControlOptionStore<Item> {\n readonly #listeners = new Map<string, Set<() => void>>();\n readonly #options = new Map<string, OptionEntry<Item>>();\n readonly #optionIdsByValue = new Map<Item, string | Set<string>>();\n #activeId: string | undefined;\n #focusVisible = false;\n #nextGeneration = 0;\n #selected: ReadonlySet<Item>;\n\n constructor(selected: readonly Item[] = []) {\n this.#selected = new Set(selected);\n }\n\n subscribe(id: string, listener: () => void): () => void {\n let listeners = this.#listeners.get(id);\n if (!listeners) {\n listeners = new Set();\n this.#listeners.set(id, listeners);\n }\n listeners.add(listener);\n\n return () => {\n const currentListeners = this.#listeners.get(id);\n currentListeners?.delete(listener);\n if (currentListeners?.size === 0) {\n this.#listeners.delete(id);\n }\n };\n }\n\n register(option: OptionValue<Item>): () => void {\n const previousEntry = this.#options.get(option.id);\n const previousSnapshot = this.getSnapshot(option.id);\n if (previousEntry) {\n this.#deleteValueId(previousEntry.option.value, option.id);\n }\n const entry = {\n generation: this.#nextGeneration++,\n option,\n };\n this.#options.set(option.id, entry);\n const valueIds = this.#optionIdsByValue.get(option.value);\n if (valueIds === undefined) {\n this.#optionIdsByValue.set(option.value, option.id);\n } else if (typeof valueIds === \"string\") {\n this.#optionIdsByValue.set(option.value, new Set([valueIds, option.id]));\n } else {\n valueIds.add(option.id);\n }\n\n if (\n previousEntry !== undefined ||\n previousSnapshot !== this.getSnapshot(option.id)\n ) {\n this.#notify(option.id);\n }\n\n return () => {\n const current = this.#options.get(option.id);\n if (current?.generation !== entry.generation) return;\n const previousSnapshot = this.getSnapshot(option.id);\n this.#options.delete(option.id);\n this.#deleteValueId(option.value, option.id);\n if (previousSnapshot !== 0) this.#notify(option.id);\n };\n }\n\n getSnapshot(\n id: string,\n currentOption?: OptionValue<Item>,\n ): OptionStateSnapshot {\n const option = currentOption ?? this.#options.get(id)?.option;\n if (!option) return 0;\n\n let snapshot = 0;\n if (id === this.#activeId) {\n snapshot |= OPTION_STATE_ACTIVE;\n if (this.#focusVisible) snapshot |= OPTION_STATE_FOCUS_VISIBLE;\n }\n if (this.#selected.has(option.value)) {\n snapshot |= OPTION_STATE_SELECTED;\n }\n return snapshot;\n }\n\n setActiveId(id: string | undefined): void {\n if (id === this.#activeId) return;\n const previousId = this.#activeId;\n this.#activeId = id;\n if (previousId !== undefined) this.#notify(previousId);\n if (id !== undefined) this.#notify(id);\n }\n\n setFocusVisible(focusVisible: boolean): void {\n if (focusVisible === this.#focusVisible) return;\n this.#focusVisible = focusVisible;\n if (this.#activeId !== undefined) this.#notify(this.#activeId);\n }\n\n setSelected(selected: readonly Item[]): void {\n const previous = this.#selected;\n const nextSelected = new Set(selected);\n this.#selected = nextSelected;\n\n const candidateValues = new Set([...previous, ...nextSelected]);\n for (const value of candidateValues) {\n if (previous.has(value) !== nextSelected.has(value)) {\n const ids = this.#optionIdsByValue.get(value);\n if (typeof ids === \"string\") {\n this.#notify(ids);\n } else if (ids !== undefined) {\n for (const id of ids) this.#notify(id);\n }\n }\n }\n }\n\n #notify(id: string): void {\n const listeners = this.#listeners.get(id);\n if (!listeners) return;\n for (const listener of [...listeners]) listener();\n }\n\n #deleteValueId(value: Item, id: string): void {\n const ids = this.#optionIdsByValue.get(value);\n if (typeof ids === \"string\") {\n if (ids === id) this.#optionIdsByValue.delete(value);\n return;\n }\n ids?.delete(id);\n if (ids?.size === 1) {\n this.#optionIdsByValue.set(value, ids.values().next().value as string);\n } else if (ids?.size === 0) {\n this.#optionIdsByValue.delete(value);\n }\n }\n}\n"],"names":["previousSnapshot"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var ListControlContext = require('./ListControlContext.js');
|
|
6
|
+
var ListControlOptionContext = require('./ListControlOptionContext.js');
|
|
7
|
+
|
|
8
|
+
function ListControlProvider({
|
|
9
|
+
children,
|
|
10
|
+
value
|
|
11
|
+
}) {
|
|
12
|
+
const { optionStateStore, ...publicValue } = value;
|
|
13
|
+
const optionValue = React.useMemo(
|
|
14
|
+
() => ({
|
|
15
|
+
disabled: value.disabled,
|
|
16
|
+
listRef: value.listRef,
|
|
17
|
+
multiselect: value.multiselect,
|
|
18
|
+
optionStateStore,
|
|
19
|
+
register: value.register,
|
|
20
|
+
select: value.select,
|
|
21
|
+
setActive: value.setActive,
|
|
22
|
+
valueToString: value.valueToString
|
|
23
|
+
}),
|
|
24
|
+
[
|
|
25
|
+
optionStateStore,
|
|
26
|
+
value.disabled,
|
|
27
|
+
value.listRef,
|
|
28
|
+
value.multiselect,
|
|
29
|
+
value.register,
|
|
30
|
+
value.select,
|
|
31
|
+
value.setActive,
|
|
32
|
+
value.valueToString
|
|
33
|
+
]
|
|
34
|
+
);
|
|
35
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ListControlContext.ListControlContext.Provider, { value: publicValue, children: /* @__PURE__ */ jsxRuntime.jsx(ListControlOptionContext.ListControlOptionContextProvider, { value: optionValue, children }) });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
exports.ListControlProvider = ListControlProvider;
|
|
39
|
+
//# sourceMappingURL=ListControlProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListControlProvider.js","sources":["../src/list-control/ListControlProvider.tsx"],"sourcesContent":["import { type ReactNode, useMemo } from \"react\";\nimport {\n ListControlContext,\n type ListControlContextValue,\n} from \"./ListControlContext\";\nimport {\n ListControlOptionContextProvider,\n type ListControlOptionContextValue,\n} from \"./ListControlOptionContext\";\nimport type { ListControlOptionStore } from \"./ListControlOptionStore\";\n\ntype ListControlProviderValue<Item> = ListControlContextValue<Item> & {\n optionStateStore: ListControlOptionStore<Item>;\n};\n\nexport function ListControlProvider<Item>({\n children,\n value,\n}: {\n children: ReactNode;\n value: ListControlProviderValue<Item>;\n}) {\n const { optionStateStore, ...publicValue } = value;\n const optionValue = useMemo<ListControlOptionContextValue<Item>>(\n () => ({\n disabled: value.disabled,\n listRef: value.listRef,\n multiselect: value.multiselect,\n optionStateStore,\n register: value.register,\n select: value.select,\n setActive: value.setActive,\n valueToString: value.valueToString,\n }),\n [\n optionStateStore,\n value.disabled,\n value.listRef,\n value.multiselect,\n value.register,\n value.select,\n value.setActive,\n value.valueToString,\n ],\n );\n\n return (\n <ListControlContext.Provider value={publicValue}>\n <ListControlOptionContextProvider value={optionValue}>\n {children}\n </ListControlOptionContextProvider>\n </ListControlContext.Provider>\n );\n}\n"],"names":["useMemo","jsx","ListControlContext","ListControlOptionContextProvider"],"mappings":";;;;;;;AAeO,SAAS,mBAAA,CAA0B;AAAA,EACxC,QAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,MAAM,EAAE,gBAAA,EAAkB,GAAG,WAAA,EAAY,GAAI,KAAA;AAC7C,EAAA,MAAM,WAAA,GAAcA,aAAA;AAAA,IAClB,OAAO;AAAA,MACL,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,gBAAA;AAAA,MACA,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,WAAW,KAAA,CAAM,SAAA;AAAA,MACjB,eAAe,KAAA,CAAM;AAAA,KACvB,CAAA;AAAA,IACA;AAAA,MACE,gBAAA;AAAA,MACA,KAAA,CAAM,QAAA;AAAA,MACN,KAAA,CAAM,OAAA;AAAA,MACN,KAAA,CAAM,WAAA;AAAA,MACN,KAAA,CAAM,QAAA;AAAA,MACN,KAAA,CAAM,MAAA;AAAA,MACN,KAAA,CAAM,SAAA;AAAA,MACN,KAAA,CAAM;AAAA;AACR,GACF;AAEA,EAAA,uBACEC,cAAA,CAACC,qCAAA,CAAmB,QAAA,EAAnB,EAA4B,KAAA,EAAO,WAAA,EAClC,QAAA,kBAAAD,cAAA,CAACE,yDAAA,EAAA,EAAiC,KAAA,EAAO,WAAA,EACtC,QAAA,EACH,CAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __typeError = (msg) => {
|
|
4
|
+
throw TypeError(msg);
|
|
5
|
+
};
|
|
6
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
7
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
8
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
9
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
10
|
+
var __privateWrapper = (obj, member, setter, getter) => ({
|
|
11
|
+
set _(value) {
|
|
12
|
+
__privateSet(obj, member, value);
|
|
13
|
+
},
|
|
14
|
+
get _() {
|
|
15
|
+
return __privateGet(obj, member, getter);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
var _entries, _ordered, _indexById, _nextGeneration, _hasGaps;
|
|
19
|
+
function createCoalescedRebuild(rebuild, enqueue = (callback) => {
|
|
20
|
+
Promise.resolve().then(callback);
|
|
21
|
+
}) {
|
|
22
|
+
let pending = false;
|
|
23
|
+
let cancelled = false;
|
|
24
|
+
return {
|
|
25
|
+
schedule() {
|
|
26
|
+
if (pending || cancelled) return;
|
|
27
|
+
pending = true;
|
|
28
|
+
enqueue(() => {
|
|
29
|
+
pending = false;
|
|
30
|
+
if (!cancelled) rebuild();
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
cancel() {
|
|
34
|
+
cancelled = true;
|
|
35
|
+
pending = false;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
class ListControlRegistry {
|
|
40
|
+
constructor() {
|
|
41
|
+
__privateAdd(this, _entries, /* @__PURE__ */ new Map());
|
|
42
|
+
__privateAdd(this, _ordered, []);
|
|
43
|
+
__privateAdd(this, _indexById, /* @__PURE__ */ new Map());
|
|
44
|
+
__privateAdd(this, _nextGeneration, 0);
|
|
45
|
+
__privateAdd(this, _hasGaps, false);
|
|
46
|
+
}
|
|
47
|
+
register(option, element) {
|
|
48
|
+
const entry = {
|
|
49
|
+
data: option,
|
|
50
|
+
element,
|
|
51
|
+
generation: __privateWrapper(this, _nextGeneration)._++
|
|
52
|
+
};
|
|
53
|
+
__privateGet(this, _entries).set(option.id, entry);
|
|
54
|
+
const currentIndex = __privateGet(this, _indexById).get(option.id);
|
|
55
|
+
if (currentIndex === void 0) {
|
|
56
|
+
__privateGet(this, _indexById).set(option.id, __privateGet(this, _ordered).length);
|
|
57
|
+
__privateGet(this, _ordered).push(entry);
|
|
58
|
+
} else {
|
|
59
|
+
__privateGet(this, _ordered)[currentIndex] = entry;
|
|
60
|
+
}
|
|
61
|
+
return () => {
|
|
62
|
+
const current = __privateGet(this, _entries).get(option.id);
|
|
63
|
+
if ((current == null ? void 0 : current.generation) !== entry.generation) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
__privateGet(this, _entries).delete(option.id);
|
|
67
|
+
const index = __privateGet(this, _indexById).get(option.id);
|
|
68
|
+
if (index !== void 0 && __privateGet(this, _ordered)[index] === entry) {
|
|
69
|
+
__privateGet(this, _ordered)[index] = void 0;
|
|
70
|
+
__privateGet(this, _indexById).delete(option.id);
|
|
71
|
+
__privateSet(this, _hasGaps, true);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
rebuild(listElement) {
|
|
76
|
+
const ordered = [];
|
|
77
|
+
const indexById = /* @__PURE__ */ new Map();
|
|
78
|
+
for (const element of listElement.querySelectorAll(
|
|
79
|
+
'[role="option"]'
|
|
80
|
+
)) {
|
|
81
|
+
const entry = __privateGet(this, _entries).get(element.id);
|
|
82
|
+
if ((entry == null ? void 0 : entry.element) === element && element.isConnected) {
|
|
83
|
+
indexById.set(entry.data.id, ordered.length);
|
|
84
|
+
ordered.push(entry);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
for (const id of __privateGet(this, _entries).keys()) {
|
|
88
|
+
if (!indexById.has(id)) {
|
|
89
|
+
__privateGet(this, _entries).delete(id);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
__privateSet(this, _ordered, ordered);
|
|
93
|
+
__privateSet(this, _indexById, indexById);
|
|
94
|
+
__privateSet(this, _hasGaps, false);
|
|
95
|
+
}
|
|
96
|
+
getAt(index) {
|
|
97
|
+
if (!__privateGet(this, _hasGaps)) {
|
|
98
|
+
return __privateGet(this, _ordered)[index];
|
|
99
|
+
}
|
|
100
|
+
let currentIndex = 0;
|
|
101
|
+
for (const entry of __privateGet(this, _ordered)) {
|
|
102
|
+
if (entry && __privateGet(this, _entries).get(entry.data.id) === entry) {
|
|
103
|
+
if (currentIndex === index) return entry;
|
|
104
|
+
currentIndex++;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return void 0;
|
|
108
|
+
}
|
|
109
|
+
get length() {
|
|
110
|
+
return __privateGet(this, _hasGaps) ? __privateGet(this, _entries).size : __privateGet(this, _ordered).length;
|
|
111
|
+
}
|
|
112
|
+
indexOfId(id) {
|
|
113
|
+
const physicalIndex = __privateGet(this, _indexById).get(id);
|
|
114
|
+
if (physicalIndex === void 0 || !__privateGet(this, _hasGaps)) {
|
|
115
|
+
return physicalIndex ?? -1;
|
|
116
|
+
}
|
|
117
|
+
let logicalIndex = 0;
|
|
118
|
+
for (let index = 0; index < physicalIndex; index++) {
|
|
119
|
+
const entry = __privateGet(this, _ordered)[index];
|
|
120
|
+
if (entry && __privateGet(this, _entries).get(entry.data.id) === entry) logicalIndex++;
|
|
121
|
+
}
|
|
122
|
+
return logicalIndex;
|
|
123
|
+
}
|
|
124
|
+
indexOfValue(value) {
|
|
125
|
+
let logicalIndex = 0;
|
|
126
|
+
for (const entry of __privateGet(this, _ordered)) {
|
|
127
|
+
if (entry && __privateGet(this, _entries).get(entry.data.id) === entry) {
|
|
128
|
+
if (entry.data.value === value) return logicalIndex;
|
|
129
|
+
logicalIndex++;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return -1;
|
|
133
|
+
}
|
|
134
|
+
findByData(option) {
|
|
135
|
+
const entry = __privateGet(this, _entries).get(option.id);
|
|
136
|
+
return (entry == null ? void 0 : entry.data) === option ? entry : void 0;
|
|
137
|
+
}
|
|
138
|
+
matching(predicate) {
|
|
139
|
+
const matches = [];
|
|
140
|
+
for (const entry of __privateGet(this, _ordered)) {
|
|
141
|
+
if (entry !== void 0 && __privateGet(this, _entries).get(entry.data.id) === entry && predicate(entry.data)) {
|
|
142
|
+
matches.push(entry);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return matches;
|
|
146
|
+
}
|
|
147
|
+
snapshot() {
|
|
148
|
+
return __privateGet(this, _ordered).filter(
|
|
149
|
+
(entry) => entry !== void 0
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
_entries = new WeakMap();
|
|
154
|
+
_ordered = new WeakMap();
|
|
155
|
+
_indexById = new WeakMap();
|
|
156
|
+
_nextGeneration = new WeakMap();
|
|
157
|
+
_hasGaps = new WeakMap();
|
|
158
|
+
|
|
159
|
+
exports.ListControlRegistry = ListControlRegistry;
|
|
160
|
+
exports.createCoalescedRebuild = createCoalescedRebuild;
|
|
161
|
+
//# sourceMappingURL=ListControlRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListControlRegistry.js","sources":["../src/list-control/ListControlRegistry.ts"],"sourcesContent":["import type { OptionValue } from \"./ListControlContext\";\n\nexport interface RegisteredOption<Item> {\n data: OptionValue<Item>;\n element: HTMLElement;\n}\n\ninterface RegistryEntry<Item> extends RegisteredOption<Item> {\n generation: number;\n}\n\nexport function createCoalescedRebuild(\n rebuild: () => void,\n enqueue: (callback: () => void) => void = (callback) => {\n // Promise jobs are supported by Chrome 86.\n Promise.resolve().then(callback);\n },\n): { schedule: () => void; cancel: () => void } {\n let pending = false;\n let cancelled = false;\n\n return {\n schedule() {\n if (pending || cancelled) return;\n pending = true;\n enqueue(() => {\n pending = false;\n if (!cancelled) rebuild();\n });\n },\n cancel() {\n cancelled = true;\n pending = false;\n },\n };\n}\n\n/** Internal option registry optimized for large, non-virtualized lists. */\nexport class ListControlRegistry<Item> {\n readonly #entries = new Map<string, RegistryEntry<Item>>();\n #ordered: (RegistryEntry<Item> | undefined)[] = [];\n #indexById = new Map<string, number>();\n #nextGeneration = 0;\n #hasGaps = false;\n\n register(option: OptionValue<Item>, element: HTMLElement): () => void {\n const entry: RegistryEntry<Item> = {\n data: option,\n element,\n generation: this.#nextGeneration++,\n };\n this.#entries.set(option.id, entry);\n\n const currentIndex = this.#indexById.get(option.id);\n if (currentIndex === undefined) {\n this.#indexById.set(option.id, this.#ordered.length);\n this.#ordered.push(entry);\n } else {\n this.#ordered[currentIndex] = entry;\n }\n\n return () => {\n const current = this.#entries.get(option.id);\n if (current?.generation !== entry.generation) {\n return;\n }\n this.#entries.delete(option.id);\n\n const index = this.#indexById.get(option.id);\n if (index !== undefined && this.#ordered[index] === entry) {\n // Rebuild compacts the snapshot after the corresponding DOM removal.\n this.#ordered[index] = undefined;\n this.#indexById.delete(option.id);\n this.#hasGaps = true;\n }\n };\n }\n\n rebuild(listElement: Pick<HTMLElement, \"querySelectorAll\">): void {\n const ordered: RegistryEntry<Item>[] = [];\n const indexById = new Map<string, number>();\n\n for (const element of listElement.querySelectorAll<HTMLElement>(\n '[role=\"option\"]',\n )) {\n const entry = this.#entries.get(element.id);\n if (entry?.element === element && element.isConnected) {\n indexById.set(entry.data.id, ordered.length);\n ordered.push(entry);\n }\n }\n\n for (const id of this.#entries.keys()) {\n if (!indexById.has(id)) {\n this.#entries.delete(id);\n }\n }\n\n this.#ordered = ordered;\n this.#indexById = indexById;\n this.#hasGaps = false;\n }\n\n getAt(index: number): RegisteredOption<Item> | undefined {\n if (!this.#hasGaps) {\n return this.#ordered[index];\n }\n\n let currentIndex = 0;\n for (const entry of this.#ordered) {\n if (entry && this.#entries.get(entry.data.id) === entry) {\n if (currentIndex === index) return entry;\n currentIndex++;\n }\n }\n return undefined;\n }\n\n get length(): number {\n return this.#hasGaps ? this.#entries.size : this.#ordered.length;\n }\n\n indexOfId(id: string): number {\n const physicalIndex = this.#indexById.get(id);\n if (physicalIndex === undefined || !this.#hasGaps) {\n return physicalIndex ?? -1;\n }\n\n let logicalIndex = 0;\n for (let index = 0; index < physicalIndex; index++) {\n const entry = this.#ordered[index];\n if (entry && this.#entries.get(entry.data.id) === entry) logicalIndex++;\n }\n return logicalIndex;\n }\n\n indexOfValue(value: Item): number {\n let logicalIndex = 0;\n for (const entry of this.#ordered) {\n if (entry && this.#entries.get(entry.data.id) === entry) {\n if (entry.data.value === value) return logicalIndex;\n logicalIndex++;\n }\n }\n return -1;\n }\n\n findByData(option: OptionValue<Item>): RegisteredOption<Item> | undefined {\n const entry = this.#entries.get(option.id);\n return entry?.data === option ? entry : undefined;\n }\n\n matching(\n predicate: (option: OptionValue<Item>) => boolean,\n ): RegisteredOption<Item>[] {\n const matches: RegistryEntry<Item>[] = [];\n for (const entry of this.#ordered) {\n if (\n entry !== undefined &&\n this.#entries.get(entry.data.id) === entry &&\n predicate(entry.data)\n ) {\n matches.push(entry);\n }\n }\n return matches;\n }\n\n snapshot(): readonly RegisteredOption<Item>[] {\n return this.#ordered.filter(\n (entry): entry is RegistryEntry<Item> => entry !== undefined,\n );\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -4,15 +4,53 @@ var React = require('react');
|
|
|
4
4
|
require('clsx');
|
|
5
5
|
require('react/jsx-runtime');
|
|
6
6
|
var useControlled = require('../utils/useControlled.js');
|
|
7
|
+
var useEventCallback = require('../utils/useEventCallback.js');
|
|
7
8
|
require('../utils/useFloatingUI/useFloatingUI.js');
|
|
8
9
|
var useForkRef = require('../utils/useForkRef.js');
|
|
9
10
|
require('../utils/useId.js');
|
|
11
|
+
var useIsomorphicLayoutEffect = require('../utils/useIsomorphicLayoutEffect.js');
|
|
10
12
|
require('../salt-provider/SaltProvider.js');
|
|
11
13
|
require('../viewport/ViewportProvider.js');
|
|
14
|
+
var ListControlOptionStore = require('./ListControlOptionStore.js');
|
|
15
|
+
var ListControlRegistry = require('./ListControlRegistry.js');
|
|
12
16
|
|
|
13
17
|
function defaultValueToString(item) {
|
|
14
18
|
return String(item);
|
|
15
19
|
}
|
|
20
|
+
function findOptionFromSearch(options, search, valueToString, startFrom) {
|
|
21
|
+
var _a;
|
|
22
|
+
const collator = new Intl.Collator("en", {
|
|
23
|
+
usage: "search",
|
|
24
|
+
sensitivity: "base"
|
|
25
|
+
});
|
|
26
|
+
const startFromIndex = startFrom ? options.findIndex((item) => item.data.value === startFrom.value) : -1;
|
|
27
|
+
const startIndex = startFrom ? startFromIndex + 1 : 0;
|
|
28
|
+
const firstIndexByValue = /* @__PURE__ */ new Map();
|
|
29
|
+
for (let index = 0; index < options.length; index++) {
|
|
30
|
+
const value = options[index].data.value;
|
|
31
|
+
if ((typeof value !== "number" || !Number.isNaN(value)) && !firstIndexByValue.has(value)) {
|
|
32
|
+
firstIndexByValue.set(value, index);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const letters = search.split("");
|
|
36
|
+
const allSameLetter = letters.length > 0 && letters.every((letter) => collator.compare(letter, letters[0]) === 0);
|
|
37
|
+
let repeatedCharacterMatch;
|
|
38
|
+
for (let offset = 0; offset < options.length; offset++) {
|
|
39
|
+
const index = (startIndex + offset) % options.length;
|
|
40
|
+
const option = options[index].data;
|
|
41
|
+
if (firstIndexByValue.get(option.value) !== index) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const optionText = valueToString(option.value);
|
|
45
|
+
if (collator.compare(optionText.substring(0, search.length), search) === 0) {
|
|
46
|
+
return option;
|
|
47
|
+
}
|
|
48
|
+
if (repeatedCharacterMatch === void 0 && allSameLetter && collator.compare((_a = optionText[0]) == null ? void 0 : _a.toLowerCase(), letters[0]) === 0) {
|
|
49
|
+
repeatedCharacterMatch = option;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return repeatedCharacterMatch;
|
|
53
|
+
}
|
|
16
54
|
function useListControl(props) {
|
|
17
55
|
const {
|
|
18
56
|
open: openProp,
|
|
@@ -26,6 +64,13 @@ function useListControl(props) {
|
|
|
26
64
|
readOnly,
|
|
27
65
|
valueToString = defaultValueToString
|
|
28
66
|
} = props;
|
|
67
|
+
const optionStateStoreRef = React.useRef(null);
|
|
68
|
+
if (optionStateStoreRef.current === null) {
|
|
69
|
+
optionStateStoreRef.current = new ListControlOptionStore.ListControlOptionStore(
|
|
70
|
+
selectedProp ?? defaultSelected ?? []
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
const optionStateStore = optionStateStoreRef.current;
|
|
29
74
|
const listRef = React.useRef(null);
|
|
30
75
|
const [listElement, setListElement] = React.useState(null);
|
|
31
76
|
const setListRef = useForkRef.useForkRef(listRef, setListElement);
|
|
@@ -37,16 +82,9 @@ function useListControl(props) {
|
|
|
37
82
|
setFocusVisibleState(false);
|
|
38
83
|
}
|
|
39
84
|
}, [disabled, focusedState]);
|
|
40
|
-
const [activeState,
|
|
85
|
+
const [activeState, setActive] = React.useState(
|
|
41
86
|
void 0
|
|
42
87
|
);
|
|
43
|
-
const setActive = React.useCallback((option) => {
|
|
44
|
-
if (option) {
|
|
45
|
-
setActiveState(option);
|
|
46
|
-
} else {
|
|
47
|
-
setActiveState(void 0);
|
|
48
|
-
}
|
|
49
|
-
}, []);
|
|
50
88
|
const [openState, setOpenState] = useControlled.useControlled({
|
|
51
89
|
controlled: openProp,
|
|
52
90
|
default: Boolean(defaultOpen),
|
|
@@ -70,152 +108,143 @@ function useListControl(props) {
|
|
|
70
108
|
name: "ListControl",
|
|
71
109
|
state: "selected"
|
|
72
110
|
});
|
|
73
|
-
const select = (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
111
|
+
const select = useEventCallback.useEventCallback(
|
|
112
|
+
(event, option) => {
|
|
113
|
+
if (option.disabled || readOnly || disabled) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
let newSelected = [option.value];
|
|
117
|
+
if (multiselect) {
|
|
118
|
+
if (selectedState.includes(option.value)) {
|
|
119
|
+
newSelected = selectedState.filter((item) => item !== option.value);
|
|
120
|
+
} else {
|
|
121
|
+
newSelected = selectedState.concat([option.value]);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
setSelectedState(newSelected);
|
|
125
|
+
onSelectionChange == null ? void 0 : onSelectionChange(event, newSelected);
|
|
126
|
+
if (!multiselect) {
|
|
127
|
+
setOpen(false);
|
|
83
128
|
}
|
|
84
129
|
}
|
|
85
|
-
|
|
86
|
-
onSelectionChange == null ? void 0 : onSelectionChange(event, newSelected);
|
|
87
|
-
if (!multiselect) {
|
|
88
|
-
setOpen(false);
|
|
89
|
-
}
|
|
90
|
-
};
|
|
130
|
+
);
|
|
91
131
|
const clear = (event) => {
|
|
92
132
|
setSelectedState([]);
|
|
93
133
|
if (selectedState.length !== 0) {
|
|
94
134
|
onSelectionChange == null ? void 0 : onSelectionChange(event, []);
|
|
95
135
|
}
|
|
96
136
|
};
|
|
97
|
-
const
|
|
137
|
+
const registryRef = React.useRef(null);
|
|
138
|
+
if (registryRef.current === null) {
|
|
139
|
+
registryRef.current = new ListControlRegistry.ListControlRegistry();
|
|
140
|
+
}
|
|
141
|
+
const registry = registryRef.current;
|
|
142
|
+
const scheduleRebuildRef = React.useRef(void 0);
|
|
143
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
144
|
+
optionStateStore.setActiveId(activeState == null ? void 0 : activeState.id);
|
|
145
|
+
}, [activeState == null ? void 0 : activeState.id, optionStateStore]);
|
|
146
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
147
|
+
optionStateStore.setFocusVisible(focusVisibleState);
|
|
148
|
+
}, [focusVisibleState, optionStateStore]);
|
|
149
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
150
|
+
optionStateStore.setSelected(selectedState);
|
|
151
|
+
}, [optionStateStore, selectedState]);
|
|
98
152
|
const register = React.useCallback(
|
|
99
153
|
(optionValue, element) => {
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
);
|
|
104
|
-
if (existingIndex !== -1) {
|
|
105
|
-
optionsRef.current.splice(existingIndex, 1);
|
|
106
|
-
}
|
|
107
|
-
optionsRef.current.push({ data: optionValue, element });
|
|
154
|
+
var _a;
|
|
155
|
+
const unregisterOptionState = optionStateStore.register(optionValue);
|
|
156
|
+
const unregisterRegistry = registry.register(optionValue, element);
|
|
157
|
+
(_a = scheduleRebuildRef.current) == null ? void 0 : _a.call(scheduleRebuildRef);
|
|
108
158
|
return () => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
);
|
|
159
|
+
var _a2;
|
|
160
|
+
unregisterRegistry();
|
|
161
|
+
unregisterOptionState();
|
|
162
|
+
(_a2 = scheduleRebuildRef.current) == null ? void 0 : _a2.call(scheduleRebuildRef);
|
|
112
163
|
};
|
|
113
164
|
},
|
|
114
|
-
[]
|
|
165
|
+
[optionStateStore, registry]
|
|
115
166
|
);
|
|
116
167
|
React.useEffect(() => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (pos & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
|
|
122
|
-
if (pos & Node.DOCUMENT_POSITION_PRECEDING) return 1;
|
|
123
|
-
return 0;
|
|
124
|
-
});
|
|
168
|
+
if (!listElement) return;
|
|
169
|
+
const rebuild = () => {
|
|
170
|
+
mutationObserver.takeRecords();
|
|
171
|
+
registry.rebuild(listElement);
|
|
125
172
|
};
|
|
173
|
+
const coalescedRebuild = ListControlRegistry.createCoalescedRebuild(rebuild);
|
|
174
|
+
scheduleRebuildRef.current = coalescedRebuild.schedule;
|
|
175
|
+
const containsOption = (node) => node.nodeType === Node.ELEMENT_NODE && (node.matches('[role="option"]') || node.querySelector('[role="option"]') !== null);
|
|
126
176
|
const mutationObserver = new MutationObserver((mutations) => {
|
|
127
|
-
|
|
128
|
-
(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return node instanceof HTMLElement && ((_a = node.matches) == null ? void 0 : _a.call(node, '[role="option"]'));
|
|
132
|
-
}
|
|
133
|
-
)
|
|
134
|
-
);
|
|
135
|
-
if (optionsChanged) {
|
|
136
|
-
sortOptions();
|
|
177
|
+
if (mutations.some(
|
|
178
|
+
({ addedNodes, removedNodes }) => Array.from(addedNodes).some(containsOption) || Array.from(removedNodes).some(containsOption)
|
|
179
|
+
)) {
|
|
180
|
+
coalescedRebuild.schedule();
|
|
137
181
|
}
|
|
138
182
|
});
|
|
139
|
-
if (!listElement) return;
|
|
140
183
|
mutationObserver.observe(listElement, {
|
|
141
184
|
childList: true,
|
|
142
185
|
subtree: true
|
|
143
186
|
});
|
|
144
|
-
|
|
145
|
-
return () =>
|
|
146
|
-
|
|
187
|
+
rebuild();
|
|
188
|
+
return () => {
|
|
189
|
+
scheduleRebuildRef.current = void 0;
|
|
190
|
+
coalescedRebuild.cancel();
|
|
191
|
+
mutationObserver.disconnect();
|
|
192
|
+
};
|
|
193
|
+
}, [listElement, registry]);
|
|
147
194
|
const getOptionAtIndex = React.useCallback(
|
|
148
195
|
(index) => {
|
|
149
|
-
return
|
|
196
|
+
return registry.getAt(index);
|
|
150
197
|
},
|
|
151
|
-
[]
|
|
198
|
+
[registry]
|
|
199
|
+
);
|
|
200
|
+
const getIndexOfOption = React.useCallback(
|
|
201
|
+
(option) => {
|
|
202
|
+
return registry.indexOfValue(option.value);
|
|
203
|
+
},
|
|
204
|
+
[registry]
|
|
152
205
|
);
|
|
153
|
-
const getIndexOfOption = React.useCallback((option) => {
|
|
154
|
-
return optionsRef.current.findIndex(
|
|
155
|
-
(item) => item.data.value === option.value
|
|
156
|
-
);
|
|
157
|
-
}, []);
|
|
158
206
|
const getOptionsMatching = React.useCallback(
|
|
159
207
|
(predicate) => {
|
|
160
|
-
return
|
|
208
|
+
return registry.matching(predicate);
|
|
161
209
|
},
|
|
162
|
-
[]
|
|
210
|
+
[registry]
|
|
163
211
|
);
|
|
164
212
|
const getOptionFromSearch = React.useCallback(
|
|
165
213
|
(search, startFrom) => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const searchList = optionsRef.current.map((item) => item.data);
|
|
172
|
-
let matches = searchList.filter(
|
|
173
|
-
(option) => collator.compare(
|
|
174
|
-
valueToString(option.value).substring(0, search.length),
|
|
175
|
-
search
|
|
176
|
-
) === 0
|
|
214
|
+
return findOptionFromSearch(
|
|
215
|
+
registry.snapshot(),
|
|
216
|
+
search,
|
|
217
|
+
valueToString,
|
|
218
|
+
startFrom
|
|
177
219
|
);
|
|
178
|
-
if (matches.length === 0) {
|
|
179
|
-
const letters = search.split("");
|
|
180
|
-
const allSameLetter = letters.length > 0 && letters.every((letter) => collator.compare(letter, letters[0]) === 0);
|
|
181
|
-
if (allSameLetter) {
|
|
182
|
-
matches = searchList.filter(
|
|
183
|
-
(option) => collator.compare(
|
|
184
|
-
valueToString(option.value)[0].toLowerCase(),
|
|
185
|
-
letters[0]
|
|
186
|
-
) === 0
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return matches.find((option) => getIndexOfOption(option) >= startIndex);
|
|
191
220
|
},
|
|
192
|
-
[
|
|
221
|
+
[registry, valueToString]
|
|
193
222
|
);
|
|
194
223
|
const getFirstOption = React.useCallback(() => {
|
|
195
224
|
return getOptionAtIndex(0);
|
|
196
225
|
}, [getOptionAtIndex]);
|
|
197
226
|
const getLastOption = React.useCallback(() => {
|
|
198
|
-
return getOptionAtIndex(
|
|
199
|
-
}, [getOptionAtIndex]);
|
|
227
|
+
return getOptionAtIndex(registry.length - 1);
|
|
228
|
+
}, [getOptionAtIndex, registry]);
|
|
200
229
|
const getOptionBefore = React.useCallback(
|
|
201
230
|
(option) => {
|
|
202
|
-
const index =
|
|
231
|
+
const index = registry.indexOfId(option.id);
|
|
203
232
|
return getOptionAtIndex(index - 1);
|
|
204
233
|
},
|
|
205
|
-
[
|
|
234
|
+
[getOptionAtIndex, registry]
|
|
206
235
|
);
|
|
207
236
|
const getOptionAfter = React.useCallback(
|
|
208
237
|
(option) => {
|
|
209
|
-
const index =
|
|
238
|
+
const index = registry.indexOfId(option.id);
|
|
210
239
|
return getOptionAtIndex(index + 1);
|
|
211
240
|
},
|
|
212
|
-
[
|
|
241
|
+
[getOptionAtIndex, registry]
|
|
213
242
|
);
|
|
214
243
|
const getOptionPageAbove = React.useCallback(
|
|
215
244
|
(start) => {
|
|
216
245
|
var _a;
|
|
217
246
|
const list = listRef.current;
|
|
218
|
-
let option =
|
|
247
|
+
let option = registry.findByData(start);
|
|
219
248
|
if (!list || !option) {
|
|
220
249
|
return void 0;
|
|
221
250
|
}
|
|
@@ -232,12 +261,12 @@ function useListControl(props) {
|
|
|
232
261
|
}
|
|
233
262
|
return option ?? getFirstOption();
|
|
234
263
|
},
|
|
235
|
-
[getFirstOption, getOptionBefore]
|
|
264
|
+
[getFirstOption, getOptionBefore, registry]
|
|
236
265
|
);
|
|
237
266
|
const getOptionPageBelow = React.useCallback(
|
|
238
267
|
(start) => {
|
|
239
268
|
const list = listRef.current;
|
|
240
|
-
let option =
|
|
269
|
+
let option = registry.findByData(start);
|
|
241
270
|
if (!list || !option) {
|
|
242
271
|
return void 0;
|
|
243
272
|
}
|
|
@@ -254,14 +283,12 @@ function useListControl(props) {
|
|
|
254
283
|
}
|
|
255
284
|
return option ?? getLastOption();
|
|
256
285
|
},
|
|
257
|
-
[getLastOption, getOptionAfter]
|
|
286
|
+
[getLastOption, getOptionAfter, registry]
|
|
258
287
|
);
|
|
259
288
|
React.useEffect(() => {
|
|
260
289
|
var _a;
|
|
261
290
|
if (listRef.current) {
|
|
262
|
-
const activeElement = (_a =
|
|
263
|
-
(option) => option.data === activeState
|
|
264
|
-
)) == null ? void 0 : _a.element;
|
|
291
|
+
const activeElement = activeState ? (_a = registry.findByData(activeState)) == null ? void 0 : _a.element : void 0;
|
|
265
292
|
if (!activeElement) {
|
|
266
293
|
return;
|
|
267
294
|
}
|
|
@@ -270,7 +297,7 @@ function useListControl(props) {
|
|
|
270
297
|
inline: "nearest"
|
|
271
298
|
});
|
|
272
299
|
}
|
|
273
|
-
}, [activeState]);
|
|
300
|
+
}, [activeState, registry]);
|
|
274
301
|
return {
|
|
275
302
|
multiselect: Boolean(multiselect),
|
|
276
303
|
openState,
|
|
@@ -288,7 +315,6 @@ function useListControl(props) {
|
|
|
288
315
|
setFocusedState,
|
|
289
316
|
setListRef,
|
|
290
317
|
listRef,
|
|
291
|
-
options: optionsRef.current.map((option) => option.element),
|
|
292
318
|
register,
|
|
293
319
|
getOptionAtIndex,
|
|
294
320
|
getIndexOfOption,
|
|
@@ -301,10 +327,12 @@ function useListControl(props) {
|
|
|
301
327
|
getFirstOption,
|
|
302
328
|
getLastOption,
|
|
303
329
|
valueToString,
|
|
304
|
-
disabled
|
|
330
|
+
disabled,
|
|
331
|
+
optionStateStore
|
|
305
332
|
};
|
|
306
333
|
}
|
|
307
334
|
|
|
308
335
|
exports.defaultValueToString = defaultValueToString;
|
|
336
|
+
exports.findOptionFromSearch = findOptionFromSearch;
|
|
309
337
|
exports.useListControl = useListControl;
|
|
310
338
|
//# sourceMappingURL=ListControlState.js.map
|