@salt-ds/lab 1.0.0-alpha.88 → 1.0.0-alpha.89
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 +14 -0
- package/css/salt-lab.css +53 -25
- package/dist-cjs/list-deprecated/ListStateContext.js +1 -1
- package/dist-cjs/list-deprecated/ListStateContext.js.map +1 -1
- package/dist-cjs/tabs-next/TabBar.css.js +1 -1
- package/dist-cjs/tabs-next/TabBar.js +1 -1
- package/dist-cjs/tabs-next/TabBar.js.map +1 -1
- package/dist-cjs/tabs-next/TabListLayoutContext.js +13 -0
- package/dist-cjs/tabs-next/TabListLayoutContext.js.map +1 -0
- package/dist-cjs/tabs-next/TabListNext.css.js +1 -1
- package/dist-cjs/tabs-next/TabListNext.js +179 -33
- package/dist-cjs/tabs-next/TabListNext.js.map +1 -1
- package/dist-cjs/tabs-next/TabNext.js +111 -7
- package/dist-cjs/tabs-next/TabNext.js.map +1 -1
- package/dist-cjs/tabs-next/TabNextAction.js +25 -2
- package/dist-cjs/tabs-next/TabNextAction.js.map +1 -1
- package/dist-cjs/tabs-next/TabNextPanel.js +31 -16
- package/dist-cjs/tabs-next/TabNextPanel.js.map +1 -1
- package/dist-cjs/tabs-next/TabNextTrigger.js +110 -9
- package/dist-cjs/tabs-next/TabNextTrigger.js.map +1 -1
- package/dist-cjs/tabs-next/TabOverflowList.css.js +1 -1
- package/dist-cjs/tabs-next/TabOverflowList.js +168 -64
- package/dist-cjs/tabs-next/TabOverflowList.js.map +1 -1
- package/dist-cjs/tabs-next/TabSlot.js +30 -0
- package/dist-cjs/tabs-next/TabSlot.js.map +1 -0
- package/dist-cjs/tabs-next/TabSlotRegistryContext.js +16 -0
- package/dist-cjs/tabs-next/TabSlotRegistryContext.js.map +1 -0
- package/dist-cjs/tabs-next/TabsNext.css.js +6 -0
- package/dist-cjs/tabs-next/TabsNext.css.js.map +1 -0
- package/dist-cjs/tabs-next/TabsNext.js +113 -47
- package/dist-cjs/tabs-next/TabsNext.js.map +1 -1
- package/dist-cjs/tabs-next/TabsNextContext.js +17 -3
- package/dist-cjs/tabs-next/TabsNextContext.js.map +1 -1
- package/dist-cjs/tabs-next/domUtils.js +13 -0
- package/dist-cjs/tabs-next/domUtils.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/overflowMath.js +86 -0
- package/dist-cjs/tabs-next/hooks/overflowMath.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useCollection.js +147 -41
- package/dist-cjs/tabs-next/hooks/useCollection.js.map +1 -1
- package/dist-cjs/tabs-next/hooks/useFocusWithRetry.js +64 -0
- package/dist-cjs/tabs-next/hooks/useFocusWithRetry.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useOverflow.js +240 -156
- package/dist-cjs/tabs-next/hooks/useOverflow.js.map +1 -1
- package/dist-cjs/tabs-next/hooks/useOverflowLayoutState.js +99 -0
- package/dist-cjs/tabs-next/hooks/useOverflowLayoutState.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useOverflowSelectionState.js +60 -0
- package/dist-cjs/tabs-next/hooks/useOverflowSelectionState.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useRenderedTabWidth.js +92 -0
- package/dist-cjs/tabs-next/hooks/useRenderedTabWidth.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useRenderedTabsRegistry.js +200 -0
- package/dist-cjs/tabs-next/hooks/useRenderedTabsRegistry.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useTabListRecovery.js +76 -0
- package/dist-cjs/tabs-next/hooks/useTabListRecovery.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useTabRemovalHandler.js +165 -0
- package/dist-cjs/tabs-next/hooks/useTabRemovalHandler.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useTabSelectionFocus.js +80 -0
- package/dist-cjs/tabs-next/hooks/useTabSelectionFocus.js.map +1 -0
- package/dist-cjs/tabs-next/widthMeasurement.js +42 -0
- package/dist-cjs/tabs-next/widthMeasurement.js.map +1 -0
- package/dist-cjs/tree/Tree.css.js +1 -1
- package/dist-cjs/tree/TreeNode.css.js +1 -1
- package/dist-cjs/tree/TreeNode.js +1 -1
- package/dist-cjs/tree/TreeNode.js.map +1 -1
- package/dist-cjs/tree/TreeNodeExpansionIcon.css.js +1 -1
- package/dist-cjs/tree/TreeNodeTrigger.css.js +1 -1
- package/dist-cjs/tree/TreeNodeTrigger.js +2 -2
- package/dist-cjs/tree/TreeNodeTrigger.js.map +1 -1
- package/dist-cjs/utils/useEventCallback.js +5 -5
- package/dist-cjs/utils/useEventCallback.js.map +1 -1
- package/dist-es/list-deprecated/ListStateContext.js +1 -1
- package/dist-es/list-deprecated/ListStateContext.js.map +1 -1
- package/dist-es/tabs-next/TabBar.css.js +1 -1
- package/dist-es/tabs-next/TabBar.js +1 -1
- package/dist-es/tabs-next/TabBar.js.map +1 -1
- package/dist-es/tabs-next/TabListLayoutContext.js +10 -0
- package/dist-es/tabs-next/TabListLayoutContext.js.map +1 -0
- package/dist-es/tabs-next/TabListNext.css.js +1 -1
- package/dist-es/tabs-next/TabListNext.js +182 -36
- package/dist-es/tabs-next/TabListNext.js.map +1 -1
- package/dist-es/tabs-next/TabNext.js +113 -9
- package/dist-es/tabs-next/TabNext.js.map +1 -1
- package/dist-es/tabs-next/TabNextAction.js +25 -2
- package/dist-es/tabs-next/TabNextAction.js.map +1 -1
- package/dist-es/tabs-next/TabNextPanel.js +31 -16
- package/dist-es/tabs-next/TabNextPanel.js.map +1 -1
- package/dist-es/tabs-next/TabNextTrigger.js +110 -9
- package/dist-es/tabs-next/TabNextTrigger.js.map +1 -1
- package/dist-es/tabs-next/TabOverflowList.css.js +1 -1
- package/dist-es/tabs-next/TabOverflowList.js +172 -68
- package/dist-es/tabs-next/TabOverflowList.js.map +1 -1
- package/dist-es/tabs-next/TabSlot.js +28 -0
- package/dist-es/tabs-next/TabSlot.js.map +1 -0
- package/dist-es/tabs-next/TabSlotRegistryContext.js +13 -0
- package/dist-es/tabs-next/TabSlotRegistryContext.js.map +1 -0
- package/dist-es/tabs-next/TabsNext.css.js +4 -0
- package/dist-es/tabs-next/TabsNext.css.js.map +1 -0
- package/dist-es/tabs-next/TabsNext.js +114 -48
- package/dist-es/tabs-next/TabsNext.js.map +1 -1
- package/dist-es/tabs-next/TabsNextContext.js +17 -3
- package/dist-es/tabs-next/TabsNextContext.js.map +1 -1
- package/dist-es/tabs-next/domUtils.js +11 -0
- package/dist-es/tabs-next/domUtils.js.map +1 -0
- package/dist-es/tabs-next/hooks/overflowMath.js +82 -0
- package/dist-es/tabs-next/hooks/overflowMath.js.map +1 -0
- package/dist-es/tabs-next/hooks/useCollection.js +148 -42
- package/dist-es/tabs-next/hooks/useCollection.js.map +1 -1
- package/dist-es/tabs-next/hooks/useFocusWithRetry.js +62 -0
- package/dist-es/tabs-next/hooks/useFocusWithRetry.js.map +1 -0
- package/dist-es/tabs-next/hooks/useOverflow.js +242 -158
- package/dist-es/tabs-next/hooks/useOverflow.js.map +1 -1
- package/dist-es/tabs-next/hooks/useOverflowLayoutState.js +97 -0
- package/dist-es/tabs-next/hooks/useOverflowLayoutState.js.map +1 -0
- package/dist-es/tabs-next/hooks/useOverflowSelectionState.js +58 -0
- package/dist-es/tabs-next/hooks/useOverflowSelectionState.js.map +1 -0
- package/dist-es/tabs-next/hooks/useRenderedTabWidth.js +90 -0
- package/dist-es/tabs-next/hooks/useRenderedTabWidth.js.map +1 -0
- package/dist-es/tabs-next/hooks/useRenderedTabsRegistry.js +198 -0
- package/dist-es/tabs-next/hooks/useRenderedTabsRegistry.js.map +1 -0
- package/dist-es/tabs-next/hooks/useTabListRecovery.js +74 -0
- package/dist-es/tabs-next/hooks/useTabListRecovery.js.map +1 -0
- package/dist-es/tabs-next/hooks/useTabRemovalHandler.js +163 -0
- package/dist-es/tabs-next/hooks/useTabRemovalHandler.js.map +1 -0
- package/dist-es/tabs-next/hooks/useTabSelectionFocus.js +78 -0
- package/dist-es/tabs-next/hooks/useTabSelectionFocus.js.map +1 -0
- package/dist-es/tabs-next/widthMeasurement.js +36 -0
- package/dist-es/tabs-next/widthMeasurement.js.map +1 -0
- package/dist-es/tree/Tree.css.js +1 -1
- package/dist-es/tree/TreeNode.css.js +1 -1
- package/dist-es/tree/TreeNode.js +1 -1
- package/dist-es/tree/TreeNode.js.map +1 -1
- package/dist-es/tree/TreeNodeExpansionIcon.css.js +1 -1
- package/dist-es/tree/TreeNodeTrigger.css.js +1 -1
- package/dist-es/tree/TreeNodeTrigger.js +2 -2
- package/dist-es/tree/TreeNodeTrigger.js.map +1 -1
- package/dist-es/utils/useEventCallback.js +5 -5
- package/dist-es/utils/useEventCallback.js.map +1 -1
- package/dist-types/cascading-menu/internal/useMenuTriggerHandlers.d.ts +1 -1
- package/dist-types/list-deprecated/ListStateContext.d.ts +7 -2
- package/dist-types/tabs-next/TabListLayoutContext.d.ts +9 -0
- package/dist-types/tabs-next/TabNext.d.ts +1 -1
- package/dist-types/tabs-next/TabNextPanel.d.ts +2 -1
- package/dist-types/tabs-next/TabOverflowList.d.ts +3 -4
- package/dist-types/tabs-next/TabSlot.d.ts +6 -0
- package/dist-types/tabs-next/TabSlotRegistryContext.d.ts +5 -0
- package/dist-types/tabs-next/TabsNext.d.ts +2 -1
- package/dist-types/tabs-next/TabsNextContext.d.ts +26 -4
- package/dist-types/tabs-next/domUtils.d.ts +1 -0
- package/dist-types/tabs-next/hooks/overflowMath.d.ts +18 -0
- package/dist-types/tabs-next/hooks/useCollection.d.ts +15 -3
- package/dist-types/tabs-next/hooks/useFocusWithRetry.d.ts +9 -0
- package/dist-types/tabs-next/hooks/useOverflow.d.ts +5 -5
- package/dist-types/tabs-next/hooks/useOverflowLayoutState.d.ts +13 -0
- package/dist-types/tabs-next/hooks/useOverflowSelectionState.d.ts +13 -0
- package/dist-types/tabs-next/hooks/useRenderedTabWidth.d.ts +12 -0
- package/dist-types/tabs-next/hooks/useRenderedTabsRegistry.d.ts +12 -0
- package/dist-types/tabs-next/hooks/useTabListRecovery.d.ts +12 -0
- package/dist-types/tabs-next/hooks/useTabRemovalHandler.d.ts +32 -0
- package/dist-types/tabs-next/hooks/useTabSelectionFocus.d.ts +15 -0
- package/dist-types/tabs-next/widthMeasurement.d.ts +5 -0
- package/dist-types/utils/useEventCallback.d.ts +1 -1
- package/package.json +2 -2
- package/dist-cjs/tabs-next/hooks/useFocusOutside.js +0 -25
- package/dist-cjs/tabs-next/hooks/useFocusOutside.js.map +0 -1
- package/dist-cjs/tabs-next/hooks/useRestoreActiveTab.js +0 -93
- package/dist-cjs/tabs-next/hooks/useRestoreActiveTab.js.map +0 -1
- package/dist-es/tabs-next/hooks/useFocusOutside.js +0 -23
- package/dist-es/tabs-next/hooks/useFocusOutside.js.map +0 -1
- package/dist-es/tabs-next/hooks/useRestoreActiveTab.js +0 -91
- package/dist-es/tabs-next/hooks/useRestoreActiveTab.js.map +0 -1
- package/dist-types/tabs-next/hooks/useFocusOutside.d.ts +0 -2
- package/dist-types/tabs-next/hooks/useRestoreActiveTab.d.ts +0 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabsNext.js","sources":["../src/tabs-next/TabsNext.tsx"],"sourcesContent":["import { makePrefixer, useControlled, useEventCallback } from \"@salt-ds/core\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n type SyntheticEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useCollection } from \"./hooks/useCollection\";\nimport { type Item, TabsNextContext } from \"./TabsNextContext\";\n\nexport interface TabsNextProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n children?: ReactNode;\n /**\n * The default value. Use when the component is not controlled.\n */\n defaultValue?: string;\n /**\n * The value. Use when the component is controlled.\n */\n value?: string;\n /**\n * Callback fired when the selection changes. The event will be null when selection is moved automatically.\n */\n onChange?: (event: SyntheticEvent | null, value: string) => void;\n}\n\nconst withBaseName = makePrefixer(\"saltTabsNext\");\n\nexport const TabsNext = forwardRef<HTMLDivElement, TabsNextProps>(\n function TabsNext(props, ref) {\n const { className, children, value, defaultValue, onChange, ...rest } =\n props;\n\n const [valueToTabIdMap, setValueToIdMap] = useState({\n map: new Map<string, string>(),\n });\n const [valueToPanelIdMap, setValueToPanelIdMap] = useState({\n map: new Map<string, string>(),\n });\n\n const {\n registerItem,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n items,\n } = useCollection({ wrap: true });\n\n const activeTab = useRef<Pick<Item, \"id\" | \"value\">>();\n const removedActiveTabRef = useRef<string | undefined>(undefined);\n\n const [menuOpen, setMenuOpen] = useState(false);\n\n const [selected, setSelectedState] = useControlled({\n controlled: value,\n default: defaultValue,\n name: \"TabListNext\",\n state: \"selected\",\n });\n\n const setSelected = useCallback(\n (event: SyntheticEvent | null, value: string) => {\n setMenuOpen(false);\n setSelectedState(value);\n onChange?.(event, value);\n },\n [onChange],\n );\n\n const registerTab = useEventCallback((item: Item) => {\n const cleanup = registerItem(item);\n setValueToIdMap(({ map }) => {\n map.set(item.value, item.id);\n return { map };\n });\n\n return () => {\n cleanup();\n setValueToIdMap(({ map }) => {\n map.delete(item.value);\n return { map };\n });\n\n if (activeTab.current?.value !== item.value) {\n return;\n }\n\n removedActiveTabRef.current = item.value;\n };\n });\n\n const registerPanel = useCallback((id: string, value: string) => {\n setValueToPanelIdMap(({ map }) => {\n map.set(value, id);\n return { map };\n });\n return () => {\n setValueToIdMap(({ map }) => {\n map.delete(value);\n return { map };\n });\n };\n }, []);\n\n const getPanelId = useCallback(\n (value: string) => {\n return valueToPanelIdMap.map.get(value);\n },\n [valueToPanelIdMap],\n );\n\n const getTabId = useCallback(\n (value: string) => {\n return valueToTabIdMap.map.get(value);\n },\n [valueToTabIdMap],\n );\n\n const context = useMemo(\n () => ({\n registerTab,\n registerPanel,\n getPanelId,\n getTabId,\n selected,\n setSelected,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n items,\n activeTab,\n menuOpen,\n setMenuOpen,\n removedActiveTabRef,\n }),\n [\n registerPanel,\n registerTab,\n getPanelId,\n getTabId,\n selected,\n setSelected,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n items,\n menuOpen,\n ],\n );\n\n return (\n <TabsNextContext.Provider value={context}>\n <div className={clsx(withBaseName(), className)} ref={ref} {...rest}>\n {children}\n </div>\n </TabsNextContext.Provider>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","TabsNext","useState","useCollection","useRef","useControlled","useCallback","value","useEventCallback","item","useMemo","TabsNextContext","clsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TabsNext.js","sources":["../src/tabs-next/TabsNext.tsx"],"sourcesContent":["import { makePrefixer, useControlled } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n type SyntheticEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useCollection } from \"./hooks/useCollection\";\nimport { useOverflowSelectionState } from \"./hooks/useOverflowSelectionState\";\nimport { useRenderedTabsRegistry } from \"./hooks/useRenderedTabsRegistry\";\nimport tabsNextCss from \"./TabsNext.css\";\nimport { type Item, TabsNextContext } from \"./TabsNextContext\";\n\nexport interface TabsNextProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n children?: ReactNode;\n /**\n * The default value. Use when the component is not controlled.\n */\n defaultValue?: string;\n /**\n * The value. Use when the component is controlled.\n */\n value?: string;\n /**\n * Callback fired when the selection changes. The event will be null when\n * selection is moved automatically.\n */\n onChange?: (event: SyntheticEvent | null, value: string) => void;\n}\n\nconst withBaseName = makePrefixer(\"saltTabsNext\");\n\nfunction setValueIdMapEntry(\n map: Map<string, string>,\n value: string,\n id: string,\n) {\n if (map.get(value) === id) {\n return map;\n }\n\n const next = new Map(map);\n next.set(value, id);\n return next;\n}\n\nfunction removeValueIdMapEntry(\n map: Map<string, string>,\n value: string,\n id: string,\n) {\n if (map.get(value) !== id) {\n return map;\n }\n\n const next = new Map(map);\n next.delete(value);\n return next;\n}\n\nexport const TabsNext = forwardRef<HTMLDivElement, TabsNextProps>(\n function TabsNext(props, ref) {\n const { className, children, value, defaultValue, onChange, ...rest } =\n props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tabs-next\",\n css: tabsNextCss,\n window: targetWindow,\n });\n\n const [valueToTabIdMap, setValueToIdMap] = useState(\n () => new Map<string, string>(),\n );\n const [valueToPanelIdMap, setValueToPanelIdMap] = useState(\n () => new Map<string, string>(),\n );\n const {\n renderMode,\n registerBootstrapTab,\n setBootstrapTabReady,\n setBootstrapOverflowReady,\n registerRenderedTab,\n updateRenderedTab,\n getRenderedTab,\n getRenderedTabOrder,\n renderedTabs,\n } = useRenderedTabsRegistry();\n\n const {\n registerItem,\n updateItem,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n itemAt,\n getIndex,\n sortItems,\n removalVersion,\n getRemovedItems,\n } = useCollection({ targetWindow, wrap: true });\n\n const activeTab = useRef<Pick<Item, \"id\" | \"value\">>();\n\n const [menuOpen, setMenuOpen] = useState(false);\n\n const [selected, setSelectedState] = useControlled({\n controlled: value,\n default: defaultValue,\n name: \"TabsNext\",\n state: \"selected\",\n });\n\n const commitSelection = useCallback(\n (event: SyntheticEvent | null, newValue: string) => {\n setSelectedState(newValue);\n if (selected !== newValue) {\n onChange?.(event, newValue);\n }\n },\n [onChange, selected],\n );\n const { selectionFromOverflowValueRef, setSelected } =\n useOverflowSelectionState({\n commitSelection,\n menuOpen,\n selected,\n setMenuOpen,\n });\n\n const registerTab = useCallback(\n (tab: Item) => {\n const cleanup = registerItem(tab);\n setValueToIdMap((map) => setValueIdMapEntry(map, tab.value, tab.id));\n\n return () => {\n cleanup();\n setValueToIdMap((map) =>\n removeValueIdMapEntry(map, tab.value, tab.id),\n );\n };\n },\n [registerItem],\n );\n\n const registerPanel = useCallback((id: string, value: string) => {\n setValueToPanelIdMap((map) => setValueIdMapEntry(map, value, id));\n return () => {\n setValueToPanelIdMap((map) => removeValueIdMapEntry(map, value, id));\n };\n }, []);\n\n const getPanelId = useCallback(\n (value: string) => {\n return valueToPanelIdMap.get(value);\n },\n [valueToPanelIdMap],\n );\n\n const getTabId = useCallback(\n (value: string) => {\n return valueToTabIdMap.get(value);\n },\n [valueToTabIdMap],\n );\n\n const context = useMemo(\n () => ({\n renderMode,\n registerBootstrapTab,\n setBootstrapTabReady,\n setBootstrapOverflowReady,\n registerTab,\n updateTab: updateItem,\n registerRenderedTab,\n updateRenderedTab,\n getRenderedTab,\n getRenderedTabOrder,\n renderedTabs,\n registerPanel,\n getPanelId,\n getTabId,\n selected,\n setSelected,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n activeTab,\n selectionFromOverflowValueRef,\n menuOpen,\n setMenuOpen,\n itemAt,\n getIndex,\n sortItems,\n removalVersion,\n getRemovedItems,\n }),\n [\n renderMode,\n registerBootstrapTab,\n setBootstrapTabReady,\n setBootstrapOverflowReady,\n registerPanel,\n registerTab,\n updateItem,\n registerRenderedTab,\n updateRenderedTab,\n getRenderedTab,\n getRenderedTabOrder,\n renderedTabs,\n getPanelId,\n getTabId,\n selected,\n setSelected,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n menuOpen,\n itemAt,\n getIndex,\n sortItems,\n removalVersion,\n getRemovedItems,\n selectionFromOverflowValueRef,\n ],\n );\n\n return (\n <TabsNextContext.Provider value={context}>\n <div className={clsx(withBaseName(), className)} ref={ref} {...rest}>\n {children}\n </div>\n </TabsNextContext.Provider>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","TabsNext","useWindow","useComponentCssInjection","tabsNextCss","useState","useRenderedTabsRegistry","useCollection","useRef","useControlled","useCallback","useOverflowSelectionState","value","useMemo","TabsNextContext","clsx"],"mappings":"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"}
|
|
@@ -11,17 +11,31 @@ const TabsNextContext = core.createContext(
|
|
|
11
11
|
getNext: () => null,
|
|
12
12
|
getPrevious: () => null,
|
|
13
13
|
item: () => null,
|
|
14
|
-
|
|
14
|
+
getIndex: () => -1,
|
|
15
|
+
itemAt: () => null,
|
|
16
|
+
sortItems: () => void 0,
|
|
17
|
+
renderMode: "inline",
|
|
18
|
+
registerBootstrapTab: () => () => void 0,
|
|
19
|
+
setBootstrapTabReady: () => void 0,
|
|
20
|
+
setBootstrapOverflowReady: () => void 0,
|
|
15
21
|
selected: void 0,
|
|
16
22
|
registerTab: () => () => void 0,
|
|
23
|
+
updateTab: () => void 0,
|
|
24
|
+
registerRenderedTab: () => () => void 0,
|
|
25
|
+
updateRenderedTab: () => void 0,
|
|
26
|
+
getRenderedTab: () => void 0,
|
|
27
|
+
getRenderedTabOrder: () => -1,
|
|
28
|
+
renderedTabs: [],
|
|
17
29
|
registerPanel: () => () => void 0,
|
|
18
30
|
getPanelId: () => void 0,
|
|
19
31
|
getTabId: () => void 0,
|
|
20
32
|
setSelected: () => void 0,
|
|
21
33
|
activeTab: { current: void 0 },
|
|
22
|
-
|
|
34
|
+
selectionFromOverflowValueRef: { current: null },
|
|
23
35
|
menuOpen: false,
|
|
24
|
-
setMenuOpen: () => void 0
|
|
36
|
+
setMenuOpen: () => void 0,
|
|
37
|
+
removalVersion: 0,
|
|
38
|
+
getRemovedItems: () => /* @__PURE__ */ new Map()
|
|
25
39
|
}
|
|
26
40
|
);
|
|
27
41
|
function useTabsNext() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabsNextContext.js","sources":["../src/tabs-next/TabsNextContext.tsx"],"sourcesContent":["import { createContext } from \"@salt-ds/core\";\nimport {\n type Dispatch,\n type MutableRefObject,\n type SetStateAction,\n type SyntheticEvent,\n useContext,\n} from \"react\";\nimport type { useCollection } from \"./hooks/useCollection\";\n\nexport interface Item {\n id: string;\n value: string;\n element: HTMLElement;\n}\n\nexport interface TabsNextContextValue\n extends Omit
|
|
1
|
+
{"version":3,"file":"TabsNextContext.js","sources":["../src/tabs-next/TabsNextContext.tsx"],"sourcesContent":["import { createContext } from \"@salt-ds/core\";\nimport {\n type Dispatch,\n type MutableRefObject,\n type SetStateAction,\n type SyntheticEvent,\n useContext,\n} from \"react\";\nimport type { useCollection } from \"./hooks/useCollection\";\n\nexport interface Item {\n id: string;\n value: string;\n element: HTMLElement | null;\n location?: \"hidden\" | \"main\" | \"overflow\";\n order?: number;\n}\n\nexport interface RenderedTab {\n host: HTMLDivElement;\n id: string;\n marker: HTMLElement | null;\n root: HTMLElement | null;\n trigger: HTMLButtonElement | null;\n value: string;\n width: number;\n}\n\nexport type TabsNextRenderMode = \"inline\" | \"portal\";\n\nexport interface TabsNextContextValue\n extends Omit<\n ReturnType<typeof useCollection>,\n \"registerItem\" | \"updateItem\"\n > {\n renderMode: TabsNextRenderMode;\n registerBootstrapTab: (value: string) => () => void;\n setBootstrapTabReady: (value: string, ready: boolean) => void;\n setBootstrapOverflowReady: (ready: boolean) => void;\n registerTab: (item: Item) => () => void;\n updateTab: (id: string, updates: Partial<Omit<Item, \"id\" | \"value\">>) => void;\n registerRenderedTab: (tab: RenderedTab) => () => void;\n updateRenderedTab: (\n value: string,\n updates: Partial<Omit<RenderedTab, \"value\">>,\n ) => void;\n getRenderedTab: (value: string) => RenderedTab | undefined;\n getRenderedTabOrder: (value: string) => number;\n renderedTabs: RenderedTab[];\n registerPanel: (id: string, value: string) => () => void;\n getPanelId: (value: string) => string | undefined;\n getTabId: (value: string) => string | undefined;\n selected?: string;\n setSelected: (\n event: SyntheticEvent | null,\n value: string,\n source?: \"main\" | \"overflow\",\n ) => void;\n activeTab: MutableRefObject<Pick<Item, \"id\" | \"value\"> | undefined>;\n selectionFromOverflowValueRef: MutableRefObject<string | null>;\n menuOpen: boolean;\n setMenuOpen: Dispatch<SetStateAction<boolean>>;\n}\n\nexport const TabsNextContext = createContext<TabsNextContextValue>(\n \"TabsNextContext\",\n {\n getFirst: () => null,\n getLast: () => null,\n getNext: () => null,\n getPrevious: () => null,\n item: () => null,\n getIndex: () => -1,\n itemAt: () => null,\n sortItems: () => undefined,\n renderMode: \"inline\",\n registerBootstrapTab: () => () => undefined,\n setBootstrapTabReady: () => undefined,\n setBootstrapOverflowReady: () => undefined,\n selected: undefined,\n registerTab: () => () => undefined,\n updateTab: () => undefined,\n registerRenderedTab: () => () => undefined,\n updateRenderedTab: () => undefined,\n getRenderedTab: () => undefined,\n getRenderedTabOrder: () => -1,\n renderedTabs: [],\n registerPanel: () => () => undefined,\n getPanelId: () => undefined,\n getTabId: () => undefined,\n setSelected: () => undefined,\n activeTab: { current: undefined },\n selectionFromOverflowValueRef: { current: null },\n menuOpen: false,\n setMenuOpen: () => undefined,\n removalVersion: 0,\n getRemovedItems: () => new Map(),\n },\n);\n\nexport function useTabsNext() {\n return useContext(TabsNextContext);\n}\n"],"names":["createContext","useContext"],"mappings":";;;;;AAgEO,MAAM,eAAA,GAAkBA,kBAAA;AAAA,EAC7B,iBAAA;AAAA,EACA;AAAA,IACE,UAAU,MAAM,IAAA;AAAA,IAChB,SAAS,MAAM,IAAA;AAAA,IACf,SAAS,MAAM,IAAA;AAAA,IACf,aAAa,MAAM,IAAA;AAAA,IACnB,MAAM,MAAM,IAAA;AAAA,IACZ,UAAU,MAAM,EAAA;AAAA,IAChB,QAAQ,MAAM,IAAA;AAAA,IACd,WAAW,MAAM,MAAA;AAAA,IACjB,UAAA,EAAY,QAAA;AAAA,IACZ,oBAAA,EAAsB,MAAM,MAAM,MAAA;AAAA,IAClC,sBAAsB,MAAM,MAAA;AAAA,IAC5B,2BAA2B,MAAM,MAAA;AAAA,IACjC,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,MAAM,MAAM,MAAA;AAAA,IACzB,WAAW,MAAM,MAAA;AAAA,IACjB,mBAAA,EAAqB,MAAM,MAAM,MAAA;AAAA,IACjC,mBAAmB,MAAM,MAAA;AAAA,IACzB,gBAAgB,MAAM,MAAA;AAAA,IACtB,qBAAqB,MAAM,EAAA;AAAA,IAC3B,cAAc,EAAC;AAAA,IACf,aAAA,EAAe,MAAM,MAAM,MAAA;AAAA,IAC3B,YAAY,MAAM,MAAA;AAAA,IAClB,UAAU,MAAM,MAAA;AAAA,IAChB,aAAa,MAAM,MAAA;AAAA,IACnB,SAAA,EAAW,EAAE,OAAA,EAAS,MAAA,EAAU;AAAA,IAChC,6BAAA,EAA+B,EAAE,OAAA,EAAS,IAAA,EAAK;AAAA,IAC/C,QAAA,EAAU,KAAA;AAAA,IACV,aAAa,MAAM,MAAA;AAAA,IACnB,cAAA,EAAgB,CAAA;AAAA,IAChB,eAAA,EAAiB,sBAAM,IAAI,GAAA;AAAI;AAEnC;AAEO,SAAS,WAAA,GAAc;AAC5B,EAAA,OAAOC,iBAAW,eAAe,CAAA;AACnC;;;;;"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function isHTMLElement(node) {
|
|
4
|
+
if (!node || typeof node !== "object") {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
const ownerDocument = node.ownerDocument;
|
|
8
|
+
const defaultView = ownerDocument == null ? void 0 : ownerDocument.defaultView;
|
|
9
|
+
return !!defaultView && node instanceof defaultView.HTMLElement;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
exports.isHTMLElement = isHTMLElement;
|
|
13
|
+
//# sourceMappingURL=domUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domUtils.js","sources":["../src/tabs-next/domUtils.ts"],"sourcesContent":["export function isHTMLElement(node: unknown): node is HTMLElement {\n if (!node || typeof node !== \"object\") {\n return false;\n }\n\n const ownerDocument = (node as { ownerDocument?: Document | null })\n .ownerDocument;\n const defaultView = ownerDocument?.defaultView;\n\n return !!defaultView && node instanceof defaultView.HTMLElement;\n}\n"],"names":[],"mappings":";;AAAO,SAAS,cAAc,IAAA,EAAoC;AAChE,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,gBAAiB,IAAA,CACpB,aAAA;AACH,EAAA,MAAM,cAAc,aAAA,IAAA,IAAA,GAAA,MAAA,GAAA,aAAA,CAAe,WAAA;AAEnC,EAAA,OAAO,CAAC,CAAC,WAAA,IAAe,IAAA,YAAgB,WAAA,CAAY,WAAA;AACtD;;;;"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const MIN_TRUSTED_TAB_WIDTH = 0.5;
|
|
4
|
+
function calculateVisibleCount({
|
|
5
|
+
gap,
|
|
6
|
+
maxWidth: initialMaxWidth,
|
|
7
|
+
overflowWidth,
|
|
8
|
+
pinnedValue,
|
|
9
|
+
tabs
|
|
10
|
+
}) {
|
|
11
|
+
let maxWidth = initialMaxWidth;
|
|
12
|
+
let currentWidth = 0;
|
|
13
|
+
let nextVisibleCount = 0;
|
|
14
|
+
const visibleItems = [];
|
|
15
|
+
while (nextVisibleCount < tabs.length) {
|
|
16
|
+
const item = tabs[nextVisibleCount];
|
|
17
|
+
if (!item) {
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
if (item.width == null) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const itemWidth = item.width + gap;
|
|
24
|
+
if (currentWidth + itemWidth > maxWidth) {
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
currentWidth += itemWidth;
|
|
28
|
+
visibleItems.push(item);
|
|
29
|
+
nextVisibleCount += 1;
|
|
30
|
+
}
|
|
31
|
+
const allTabsFit = nextVisibleCount >= tabs.length;
|
|
32
|
+
if (allTabsFit) {
|
|
33
|
+
return nextVisibleCount;
|
|
34
|
+
}
|
|
35
|
+
maxWidth -= overflowWidth;
|
|
36
|
+
while (currentWidth > maxWidth) {
|
|
37
|
+
const removed = visibleItems.pop();
|
|
38
|
+
if (!removed) {
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
if (removed.width == null) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
currentWidth -= removed.width + gap;
|
|
45
|
+
nextVisibleCount -= 1;
|
|
46
|
+
}
|
|
47
|
+
const pinnedItem = pinnedValue == null ? null : tabs.find((item) => item.value === pinnedValue) ?? null;
|
|
48
|
+
if (pinnedItem && !visibleItems.includes(pinnedItem)) {
|
|
49
|
+
if (pinnedItem.width == null) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const pinnedWidth = pinnedItem.width + gap;
|
|
53
|
+
while (currentWidth + pinnedWidth > maxWidth) {
|
|
54
|
+
const removed = visibleItems.pop();
|
|
55
|
+
if (!removed) {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
if (removed.width == null) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
currentWidth -= removed.width + gap;
|
|
62
|
+
nextVisibleCount -= 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return Math.max(0, nextVisibleCount);
|
|
66
|
+
}
|
|
67
|
+
function partitionVisibleValues(orderedValues, visibleCount, pinnedValue) {
|
|
68
|
+
let visibleValues = orderedValues.slice(0, visibleCount);
|
|
69
|
+
let hiddenValues = orderedValues.slice(visibleCount);
|
|
70
|
+
const hiddenPinnedIndex = pinnedValue != null ? hiddenValues.indexOf(pinnedValue) : -1;
|
|
71
|
+
if (hiddenPinnedIndex !== -1) {
|
|
72
|
+
const pinnedHiddenValue = hiddenValues[hiddenPinnedIndex];
|
|
73
|
+
hiddenValues = hiddenValues.filter(
|
|
74
|
+
(_, index) => index !== hiddenPinnedIndex
|
|
75
|
+
);
|
|
76
|
+
if (pinnedHiddenValue !== void 0) {
|
|
77
|
+
visibleValues = [...visibleValues, pinnedHiddenValue];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return { visibleValues, hiddenValues };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
exports.MIN_TRUSTED_TAB_WIDTH = MIN_TRUSTED_TAB_WIDTH;
|
|
84
|
+
exports.calculateVisibleCount = calculateVisibleCount;
|
|
85
|
+
exports.partitionVisibleValues = partitionVisibleValues;
|
|
86
|
+
//# sourceMappingURL=overflowMath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overflowMath.js","sources":["../src/tabs-next/hooks/overflowMath.ts"],"sourcesContent":["export const MIN_TRUSTED_TAB_WIDTH = 0.5;\n\nexport interface MeasuredOverflowTab {\n value: string;\n width: number | null;\n}\n\ninterface CalculateVisibleCountProps {\n gap: number;\n maxWidth: number;\n overflowWidth: number;\n pinnedValue?: string;\n tabs: MeasuredOverflowTab[];\n}\n\nexport function calculateVisibleCount({\n gap,\n maxWidth: initialMaxWidth,\n overflowWidth,\n pinnedValue,\n tabs,\n}: CalculateVisibleCountProps) {\n let maxWidth = initialMaxWidth;\n let currentWidth = 0;\n let nextVisibleCount = 0;\n const visibleItems: MeasuredOverflowTab[] = [];\n\n while (nextVisibleCount < tabs.length) {\n const item = tabs[nextVisibleCount];\n if (!item) {\n break;\n }\n\n if (item.width == null) {\n return null;\n }\n\n const itemWidth = item.width + gap;\n if (currentWidth + itemWidth > maxWidth) {\n break;\n }\n\n currentWidth += itemWidth;\n visibleItems.push(item);\n nextVisibleCount += 1;\n }\n\n const allTabsFit = nextVisibleCount >= tabs.length;\n if (allTabsFit) {\n return nextVisibleCount;\n }\n\n maxWidth -= overflowWidth;\n\n while (currentWidth > maxWidth) {\n const removed = visibleItems.pop();\n if (!removed) {\n break;\n }\n if (removed.width == null) {\n return null;\n }\n currentWidth -= removed.width + gap;\n nextVisibleCount -= 1;\n }\n\n const pinnedItem =\n pinnedValue == null\n ? null\n : (tabs.find((item) => item.value === pinnedValue) ?? null);\n\n if (pinnedItem && !visibleItems.includes(pinnedItem)) {\n if (pinnedItem.width == null) {\n return null;\n }\n\n const pinnedWidth = pinnedItem.width + gap;\n while (currentWidth + pinnedWidth > maxWidth) {\n const removed = visibleItems.pop();\n if (!removed) {\n break;\n }\n if (removed.width == null) {\n return null;\n }\n currentWidth -= removed.width + gap;\n nextVisibleCount -= 1;\n }\n }\n\n return Math.max(0, nextVisibleCount);\n}\n\nexport function partitionVisibleValues(\n orderedValues: string[],\n visibleCount: number,\n pinnedValue?: string,\n) {\n let visibleValues = orderedValues.slice(0, visibleCount);\n let hiddenValues = orderedValues.slice(visibleCount);\n\n const hiddenPinnedIndex =\n pinnedValue != null ? hiddenValues.indexOf(pinnedValue) : -1;\n\n if (hiddenPinnedIndex !== -1) {\n const pinnedHiddenValue = hiddenValues[hiddenPinnedIndex];\n hiddenValues = hiddenValues.filter(\n (_, index) => index !== hiddenPinnedIndex,\n );\n if (pinnedHiddenValue !== undefined) {\n visibleValues = [...visibleValues, pinnedHiddenValue];\n }\n }\n\n return { visibleValues, hiddenValues };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -6,11 +6,19 @@ function sortBasedOnDOMPosition(items) {
|
|
|
6
6
|
const indexedItems = items.map((item, index) => [index, item]);
|
|
7
7
|
let orderChanged = false;
|
|
8
8
|
indexedItems.sort(([itemAIndex, itemA], [itemBIndex, itemB]) => {
|
|
9
|
+
if (itemA.order != null && itemA.order >= 0 && itemB.order != null && itemB.order >= 0 && itemA.order !== itemB.order) {
|
|
10
|
+
if (itemA.order < itemB.order && itemAIndex > itemBIndex || itemA.order > itemB.order && itemAIndex < itemBIndex) {
|
|
11
|
+
orderChanged = true;
|
|
12
|
+
}
|
|
13
|
+
return itemA.order - itemB.order;
|
|
14
|
+
}
|
|
9
15
|
const itemAElement = itemA.element;
|
|
10
16
|
const itemBElement = itemB.element;
|
|
11
17
|
if (itemAElement === itemBElement) return 0;
|
|
12
18
|
if (!itemAElement || !itemBElement) return 0;
|
|
13
|
-
|
|
19
|
+
const pos = itemAElement.compareDocumentPosition(itemBElement);
|
|
20
|
+
if (pos & Node.DOCUMENT_POSITION_DISCONNECTED) return 0;
|
|
21
|
+
if (pos & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
14
22
|
if (itemAIndex > itemBIndex) {
|
|
15
23
|
orderChanged = true;
|
|
16
24
|
}
|
|
@@ -26,64 +34,162 @@ function sortBasedOnDOMPosition(items) {
|
|
|
26
34
|
}
|
|
27
35
|
return items;
|
|
28
36
|
}
|
|
29
|
-
function useCollection({ wrap }) {
|
|
30
|
-
const [items, setItems] = react.useState([]);
|
|
37
|
+
function useCollection({ wrap, targetWindow }) {
|
|
31
38
|
const itemsRef = react.useRef([]);
|
|
32
39
|
const itemMap = react.useRef(/* @__PURE__ */ new Map());
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
newItems.push(item);
|
|
43
|
-
itemMap.current.set(item.id, item);
|
|
40
|
+
const removedItems = react.useRef(/* @__PURE__ */ new Map());
|
|
41
|
+
const [removalVersion, setRemovalVersion] = react.useState(0);
|
|
42
|
+
const getOrderedItems = react.useCallback(() => {
|
|
43
|
+
return sortBasedOnDOMPosition(Array.from(itemMap.current.values()));
|
|
44
|
+
}, []);
|
|
45
|
+
const getNavigableItems = react.useCallback(() => {
|
|
46
|
+
return getOrderedItems().filter((item) => {
|
|
47
|
+
if (item.location === "hidden") {
|
|
48
|
+
return false;
|
|
44
49
|
}
|
|
45
|
-
|
|
46
|
-
itemsRef.current = value;
|
|
47
|
-
return value;
|
|
50
|
+
return !!item.element;
|
|
48
51
|
});
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
}, [getOrderedItems]);
|
|
53
|
+
const sortItems = react.useCallback(() => {
|
|
54
|
+
itemsRef.current = getOrderedItems();
|
|
55
|
+
}, [getOrderedItems]);
|
|
56
|
+
const getRemovedItems = react.useCallback(() => {
|
|
57
|
+
const items = new Map(removedItems.current);
|
|
58
|
+
removedItems.current.clear();
|
|
59
|
+
return items;
|
|
60
|
+
}, []);
|
|
61
|
+
const rafId = react.useRef(null);
|
|
62
|
+
const scheduleSort = react.useCallback(() => {
|
|
63
|
+
if (!(targetWindow == null ? void 0 : targetWindow.requestAnimationFrame)) {
|
|
64
|
+
sortItems();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (rafId.current != null) {
|
|
68
|
+
targetWindow.cancelAnimationFrame(rafId.current);
|
|
69
|
+
}
|
|
70
|
+
rafId.current = targetWindow.requestAnimationFrame(() => {
|
|
71
|
+
rafId.current = null;
|
|
72
|
+
sortItems();
|
|
73
|
+
});
|
|
74
|
+
}, [sortItems, targetWindow]);
|
|
75
|
+
const registerItem = react.useCallback(
|
|
76
|
+
(item) => {
|
|
77
|
+
itemMap.current.set(item.id, item);
|
|
78
|
+
removedItems.current.delete(item.id);
|
|
79
|
+
scheduleSort();
|
|
80
|
+
return () => {
|
|
81
|
+
const currentItems = getOrderedItems();
|
|
82
|
+
const currentItem = itemMap.current.get(item.id) ?? item;
|
|
83
|
+
const staleIndex = currentItems.findIndex(({ id }) => id === item.id);
|
|
84
|
+
removedItems.current.set(item.id, {
|
|
85
|
+
...currentItem,
|
|
86
|
+
staleIndex
|
|
87
|
+
});
|
|
88
|
+
itemsRef.current = currentItems.filter(({ id }) => id !== item.id);
|
|
51
89
|
itemMap.current.delete(item.id);
|
|
52
|
-
|
|
90
|
+
setRemovalVersion((currentVersion) => currentVersion + 1);
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
[getOrderedItems, scheduleSort]
|
|
94
|
+
);
|
|
95
|
+
const updateItem = react.useCallback(
|
|
96
|
+
(id, updates) => {
|
|
97
|
+
const currentItem = itemMap.current.get(id);
|
|
98
|
+
if (!currentItem) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let changed = false;
|
|
102
|
+
const nextItem = { ...currentItem };
|
|
103
|
+
for (const [key, nextValue] of Object.entries(updates)) {
|
|
104
|
+
const typedKey = key;
|
|
105
|
+
if (nextItem[typedKey] !== nextValue) {
|
|
106
|
+
changed = true;
|
|
107
|
+
nextItem[typedKey] = nextValue;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!changed) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
itemMap.current.set(id, nextItem);
|
|
114
|
+
itemsRef.current = itemsRef.current.map((item) => {
|
|
115
|
+
if (item.id !== id) {
|
|
116
|
+
return item;
|
|
117
|
+
}
|
|
118
|
+
return nextItem;
|
|
53
119
|
});
|
|
54
|
-
|
|
120
|
+
scheduleSort();
|
|
121
|
+
},
|
|
122
|
+
[scheduleSort]
|
|
123
|
+
);
|
|
124
|
+
react.useEffect(() => {
|
|
125
|
+
return () => {
|
|
126
|
+
if (rafId.current != null && targetWindow) {
|
|
127
|
+
targetWindow.cancelAnimationFrame(rafId.current);
|
|
128
|
+
}
|
|
55
129
|
};
|
|
56
|
-
}, []);
|
|
130
|
+
}, [targetWindow]);
|
|
57
131
|
return {
|
|
58
132
|
registerItem,
|
|
59
|
-
item: (id) => {
|
|
133
|
+
item: react.useCallback((id) => {
|
|
60
134
|
if (!id) return null;
|
|
61
135
|
let item = itemMap.current.get(id);
|
|
62
136
|
if (!item) {
|
|
63
|
-
item =
|
|
137
|
+
item = itemsRef.current.find((item2) => item2.id === id);
|
|
64
138
|
if (item) {
|
|
65
139
|
itemMap.current.set(item.id, item);
|
|
66
140
|
}
|
|
67
141
|
}
|
|
68
142
|
return item ?? null;
|
|
69
|
-
},
|
|
70
|
-
getNext: (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
143
|
+
}, []),
|
|
144
|
+
getNext: react.useCallback(
|
|
145
|
+
(current) => {
|
|
146
|
+
const items = getNavigableItems();
|
|
147
|
+
if (items.length === 0) return null;
|
|
148
|
+
const index = items.findIndex(({ id }) => id === current);
|
|
149
|
+
if (index === -1) {
|
|
150
|
+
return items[0] ;
|
|
151
|
+
}
|
|
152
|
+
const newIndex = (index + 1) % items.length ;
|
|
153
|
+
return items[newIndex] ?? null;
|
|
154
|
+
},
|
|
155
|
+
[getNavigableItems, wrap]
|
|
156
|
+
),
|
|
157
|
+
getPrevious: react.useCallback(
|
|
158
|
+
(current) => {
|
|
159
|
+
const items = getNavigableItems();
|
|
160
|
+
if (items.length === 0) return null;
|
|
161
|
+
const index = items.findIndex(({ id }) => id === current);
|
|
162
|
+
if (index === -1) {
|
|
163
|
+
return items[items.length - 1] ;
|
|
164
|
+
}
|
|
165
|
+
const newIndex = (index - 1 + items.length) % items.length ;
|
|
166
|
+
return items[newIndex] ?? null;
|
|
167
|
+
},
|
|
168
|
+
[getNavigableItems, wrap]
|
|
169
|
+
),
|
|
170
|
+
getFirst: react.useCallback(() => {
|
|
171
|
+
return getNavigableItems()[0] ?? null;
|
|
172
|
+
}, [getNavigableItems]),
|
|
173
|
+
getLast: react.useCallback(() => {
|
|
174
|
+
const items = getNavigableItems();
|
|
84
175
|
return items[items.length - 1] ?? null;
|
|
85
|
-
},
|
|
86
|
-
|
|
176
|
+
}, [getNavigableItems]),
|
|
177
|
+
getIndex: react.useCallback(
|
|
178
|
+
(current) => {
|
|
179
|
+
return getNavigableItems().findIndex(({ id }) => id === current);
|
|
180
|
+
},
|
|
181
|
+
[getNavigableItems]
|
|
182
|
+
),
|
|
183
|
+
itemAt: react.useCallback(
|
|
184
|
+
(index) => {
|
|
185
|
+
return getNavigableItems()[index] ?? null;
|
|
186
|
+
},
|
|
187
|
+
[getNavigableItems]
|
|
188
|
+
),
|
|
189
|
+
updateItem,
|
|
190
|
+
getRemovedItems,
|
|
191
|
+
removalVersion,
|
|
192
|
+
sortItems
|
|
87
193
|
};
|
|
88
194
|
}
|
|
89
195
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCollection.js","sources":["../src/tabs-next/hooks/useCollection.ts"],"sourcesContent":["import { useCallback, useRef, useState } from \"react\";\n\nexport interface Item {\n id: string;\n element?: HTMLElement | null;\n value: string;\n}\n\nfunction sortBasedOnDOMPosition(items: Item[]): Item[] {\n const indexedItems = items.map((item, index) => [index, item] as const);\n let orderChanged = false;\n indexedItems.sort(([itemAIndex, itemA], [itemBIndex, itemB]) => {\n const itemAElement = itemA.element;\n const itemBElement = itemB.element;\n if (itemAElement === itemBElement) return 0;\n if (!itemAElement || !itemBElement) return 0;\n\n if (\n itemAElement.compareDocumentPosition(itemBElement) &\n Node.DOCUMENT_POSITION_FOLLOWING\n ) {\n if (itemAIndex > itemBIndex) {\n orderChanged = true;\n }\n return -1;\n }\n\n if (itemAIndex < itemBIndex) {\n orderChanged = true;\n }\n return 1;\n });\n\n if (orderChanged) {\n return indexedItems.map(([_, item]) => item);\n }\n return items;\n}\n\ninterface UseCollectionProps {\n wrap: boolean;\n}\n\nexport function useCollection({ wrap }: UseCollectionProps) {\n const [items, setItems] = useState<Item[]>([]);\n const itemsRef = useRef<Item[]>([]);\n const itemMap = useRef<Map<string, Item>>(new Map());\n\n const registerItem = useCallback((item: Item) => {\n setItems((old) => {\n const newItems = old.slice();\n const index = newItems.findIndex(({ id }) => id === item.id);\n if (index !== -1) {\n const newItem = { ...newItems[index], ...item };\n newItems[index] = newItem;\n itemMap.current.set(item.id, newItem);\n } else {\n newItems.push(item);\n itemMap.current.set(item.id, item);\n }\n const value = sortBasedOnDOMPosition(newItems);\n itemsRef.current = value;\n return value;\n });\n\n return () => {\n setItems((old) => {\n itemMap.current.delete(item.id);\n return old.filter(({ id }) => id !== item.id);\n });\n return itemsRef;\n };\n }, []);\n\n return {\n registerItem,\n item: (id?: string | null): Item | null => {\n if (!id) return null;\n let item = itemMap.current.get(id);\n if (!item) {\n item = items.find((item) => item.id === id);\n if (item) {\n itemMap.current.set(item.id, item);\n }\n }\n return item ?? null;\n },\n getNext: (current: string): Item | null => {\n const index = items.findIndex(({ id }) => id === current);\n\n const newIndex = wrap\n ? (index + 1) % items.length\n : Math.min(index + 1, items.length - 1);\n\n return items[newIndex] ?? null;\n },\n getPrevious: (current: string): Item | null => {\n const index = items.findIndex(({ id }) => id === current);\n\n const newIndex = wrap\n ? (index - 1 + items.length) % items.length\n : Math.max(index - 1, 0);\n\n return items[newIndex] ?? null;\n },\n getFirst: (): Item | null => {\n return items[0] ?? null;\n },\n getLast: (): Item | null => {\n return items[items.length - 1] ?? null;\n },\n items,\n };\n}\n"],"names":["useState","useRef","useCallback","item"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useCollection.js","sources":["../src/tabs-next/hooks/useCollection.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface Item {\n id: string;\n element?: HTMLElement | null;\n value: string;\n location?: \"hidden\" | \"main\" | \"overflow\";\n order?: number;\n stale?: boolean;\n}\n\ninterface StaleItem extends Item {\n staleIndex?: number;\n}\n\nfunction sortBasedOnDOMPosition(items: Item[]): Item[] {\n const indexedItems = items.map((item, index) => [index, item] as const);\n let orderChanged = false;\n indexedItems.sort(([itemAIndex, itemA], [itemBIndex, itemB]) => {\n if (\n itemA.order != null &&\n itemA.order >= 0 &&\n itemB.order != null &&\n itemB.order >= 0 &&\n itemA.order !== itemB.order\n ) {\n if (\n (itemA.order < itemB.order && itemAIndex > itemBIndex) ||\n (itemA.order > itemB.order && itemAIndex < itemBIndex)\n ) {\n orderChanged = true;\n }\n return itemA.order - itemB.order;\n }\n\n const itemAElement = itemA.element;\n const itemBElement = itemB.element;\n if (itemAElement === itemBElement) return 0;\n if (!itemAElement || !itemBElement) return 0;\n\n const pos = itemAElement.compareDocumentPosition(itemBElement);\n if (pos & Node.DOCUMENT_POSITION_DISCONNECTED) return 0;\n\n if (pos & Node.DOCUMENT_POSITION_FOLLOWING) {\n if (itemAIndex > itemBIndex) {\n orderChanged = true;\n }\n return -1;\n }\n\n if (itemAIndex < itemBIndex) {\n orderChanged = true;\n }\n return 1;\n });\n\n if (orderChanged) {\n return indexedItems.map(([_, item]) => item);\n }\n return items;\n}\n\ninterface UseCollectionProps {\n targetWindow: Window | null | undefined;\n wrap: boolean;\n}\n\nexport function useCollection({ wrap, targetWindow }: UseCollectionProps) {\n const itemsRef = useRef<Item[]>([]);\n const itemMap = useRef<Map<string, Item>>(new Map());\n const removedItems = useRef<Map<string, StaleItem>>(new Map());\n const [removalVersion, setRemovalVersion] = useState(0);\n\n const getOrderedItems = useCallback(() => {\n return sortBasedOnDOMPosition(Array.from(itemMap.current.values()));\n }, []);\n\n const getNavigableItems = useCallback(() => {\n return getOrderedItems().filter((item) => {\n if (item.location === \"hidden\") {\n return false;\n }\n\n return !!item.element;\n });\n }, [getOrderedItems]);\n\n const sortItems = useCallback(() => {\n itemsRef.current = getOrderedItems();\n }, [getOrderedItems]);\n\n const getRemovedItems = useCallback(() => {\n const items = new Map(removedItems.current);\n removedItems.current.clear();\n\n return items;\n }, []);\n\n const rafId = useRef<number | null>(null);\n\n const scheduleSort = useCallback(() => {\n if (!targetWindow?.requestAnimationFrame) {\n sortItems();\n return;\n }\n\n if (rafId.current != null) {\n targetWindow.cancelAnimationFrame(rafId.current);\n }\n\n rafId.current = targetWindow.requestAnimationFrame(() => {\n rafId.current = null;\n sortItems();\n });\n }, [sortItems, targetWindow]);\n\n const registerItem = useCallback(\n (item: Item) => {\n itemMap.current.set(item.id, item);\n removedItems.current.delete(item.id);\n scheduleSort();\n\n return () => {\n const currentItems = getOrderedItems();\n const currentItem = itemMap.current.get(item.id) ?? item;\n const staleIndex = currentItems.findIndex(({ id }) => id === item.id);\n\n removedItems.current.set(item.id, {\n ...currentItem,\n staleIndex,\n });\n\n itemsRef.current = currentItems.filter(({ id }) => id !== item.id);\n itemMap.current.delete(item.id);\n setRemovalVersion((currentVersion) => currentVersion + 1);\n };\n },\n [getOrderedItems, scheduleSort],\n );\n\n const updateItem = useCallback(\n (id: string, updates: Partial<Omit<Item, \"id\" | \"value\">>) => {\n const currentItem = itemMap.current.get(id);\n if (!currentItem) {\n return;\n }\n\n let changed = false;\n const nextItem = { ...currentItem };\n\n for (const [key, nextValue] of Object.entries(updates)) {\n const typedKey = key as keyof Omit<Item, \"id\" | \"value\">;\n if (nextItem[typedKey] !== nextValue) {\n changed = true;\n nextItem[typedKey] = nextValue as never;\n }\n }\n\n if (!changed) {\n return;\n }\n\n itemMap.current.set(id, nextItem);\n itemsRef.current = itemsRef.current.map((item) => {\n if (item.id !== id) {\n return item;\n }\n\n return nextItem;\n });\n scheduleSort();\n },\n [scheduleSort],\n );\n\n useEffect(() => {\n return () => {\n if (rafId.current != null && targetWindow) {\n targetWindow.cancelAnimationFrame(rafId.current);\n }\n };\n }, [targetWindow]);\n\n return {\n registerItem,\n item: useCallback((id?: string | null): Item | null => {\n if (!id) return null;\n let item = itemMap.current.get(id);\n if (!item) {\n item = itemsRef.current.find((item) => item.id === id);\n if (item) {\n itemMap.current.set(item.id, item);\n }\n }\n return item ?? null;\n }, []),\n getNext: useCallback(\n (current: string): Item | null => {\n const items = getNavigableItems();\n if (items.length === 0) return null;\n\n const index = items.findIndex(({ id }) => id === current);\n\n if (index === -1) {\n return wrap ? items[0] : null;\n }\n\n const newIndex = wrap\n ? (index + 1) % items.length\n : Math.min(index + 1, items.length - 1);\n\n return items[newIndex] ?? null;\n },\n [getNavigableItems, wrap],\n ),\n getPrevious: useCallback(\n (current: string): Item | null => {\n const items = getNavigableItems();\n if (items.length === 0) return null;\n\n const index = items.findIndex(({ id }) => id === current);\n\n if (index === -1) {\n return wrap ? items[items.length - 1] : null;\n }\n\n const newIndex = wrap\n ? (index - 1 + items.length) % items.length\n : Math.max(index - 1, 0);\n\n return items[newIndex] ?? null;\n },\n [getNavigableItems, wrap],\n ),\n getFirst: useCallback((): Item | null => {\n return getNavigableItems()[0] ?? null;\n }, [getNavigableItems]),\n getLast: useCallback((): Item | null => {\n const items = getNavigableItems();\n return items[items.length - 1] ?? null;\n }, [getNavigableItems]),\n getIndex: useCallback(\n (current: string): number => {\n return getNavigableItems().findIndex(({ id }) => id === current);\n },\n [getNavigableItems],\n ),\n itemAt: useCallback(\n (index: number): Item | null => {\n return getNavigableItems()[index] ?? null;\n },\n [getNavigableItems],\n ),\n updateItem,\n getRemovedItems,\n removalVersion,\n sortItems,\n };\n}\n"],"names":["useRef","useState","useCallback","useEffect","item"],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
function useFocusWithRetry({
|
|
6
|
+
maxAttempts = 120,
|
|
7
|
+
targetWindow
|
|
8
|
+
}) {
|
|
9
|
+
const focusRafRef = react.useRef(null);
|
|
10
|
+
const cancelScheduledFocus = react.useCallback(() => {
|
|
11
|
+
if (focusRafRef.current != null && targetWindow) {
|
|
12
|
+
targetWindow.cancelAnimationFrame(focusRafRef.current);
|
|
13
|
+
focusRafRef.current = null;
|
|
14
|
+
}
|
|
15
|
+
}, [targetWindow]);
|
|
16
|
+
const focusElementWithRetry = react.useCallback(
|
|
17
|
+
(getElement) => {
|
|
18
|
+
var _a;
|
|
19
|
+
const doc = targetWindow == null ? void 0 : targetWindow.document;
|
|
20
|
+
if (!doc) {
|
|
21
|
+
(_a = getElement()) == null ? void 0 : _a.focus({ preventScroll: true });
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
cancelScheduledFocus();
|
|
25
|
+
let attempts = 0;
|
|
26
|
+
const focusElement = () => {
|
|
27
|
+
const element = getElement();
|
|
28
|
+
if (!(element == null ? void 0 : element.isConnected)) {
|
|
29
|
+
if (attempts >= maxAttempts || !(targetWindow == null ? void 0 : targetWindow.requestAnimationFrame)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
attempts += 1;
|
|
33
|
+
focusRafRef.current = targetWindow.requestAnimationFrame(focusElement);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
element.focus({ preventScroll: true });
|
|
37
|
+
if (doc.activeElement === element || attempts >= maxAttempts) {
|
|
38
|
+
focusRafRef.current = null;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
attempts += 1;
|
|
42
|
+
if (targetWindow == null ? void 0 : targetWindow.requestAnimationFrame) {
|
|
43
|
+
focusRafRef.current = targetWindow.requestAnimationFrame(focusElement);
|
|
44
|
+
} else {
|
|
45
|
+
queueMicrotask(focusElement);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
focusElement();
|
|
49
|
+
},
|
|
50
|
+
[cancelScheduledFocus, maxAttempts, targetWindow]
|
|
51
|
+
);
|
|
52
|
+
react.useEffect(() => {
|
|
53
|
+
return () => {
|
|
54
|
+
cancelScheduledFocus();
|
|
55
|
+
};
|
|
56
|
+
}, [cancelScheduledFocus]);
|
|
57
|
+
return {
|
|
58
|
+
cancelScheduledFocus,
|
|
59
|
+
focusElementWithRetry
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
exports.useFocusWithRetry = useFocusWithRetry;
|
|
64
|
+
//# sourceMappingURL=useFocusWithRetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFocusWithRetry.js","sources":["../src/tabs-next/hooks/useFocusWithRetry.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\n\ninterface UseFocusWithRetryArgs {\n maxAttempts?: number;\n targetWindow: Window | null | undefined;\n}\n\nexport function useFocusWithRetry({\n maxAttempts = 120,\n targetWindow,\n}: UseFocusWithRetryArgs) {\n const focusRafRef = useRef<number | null>(null);\n\n const cancelScheduledFocus = useCallback(() => {\n if (focusRafRef.current != null && targetWindow) {\n targetWindow.cancelAnimationFrame(focusRafRef.current);\n focusRafRef.current = null;\n }\n }, [targetWindow]);\n\n const focusElementWithRetry = useCallback(\n (getElement: () => HTMLElement | null | undefined) => {\n const doc = targetWindow?.document;\n if (!doc) {\n getElement()?.focus({ preventScroll: true });\n return;\n }\n\n cancelScheduledFocus();\n\n let attempts = 0;\n\n const focusElement = () => {\n const element = getElement();\n if (!element?.isConnected) {\n if (attempts >= maxAttempts || !targetWindow?.requestAnimationFrame) {\n return;\n }\n\n attempts += 1;\n focusRafRef.current =\n targetWindow.requestAnimationFrame(focusElement);\n return;\n }\n\n element.focus({ preventScroll: true });\n\n if (doc.activeElement === element || attempts >= maxAttempts) {\n focusRafRef.current = null;\n return;\n }\n\n attempts += 1;\n if (targetWindow?.requestAnimationFrame) {\n focusRafRef.current =\n targetWindow.requestAnimationFrame(focusElement);\n } else {\n queueMicrotask(focusElement);\n }\n };\n\n focusElement();\n },\n [cancelScheduledFocus, maxAttempts, targetWindow],\n );\n\n useEffect(() => {\n return () => {\n cancelScheduledFocus();\n };\n }, [cancelScheduledFocus]);\n\n return {\n cancelScheduledFocus,\n focusElementWithRetry,\n };\n}\n"],"names":["useRef","useCallback","useEffect"],"mappings":";;;;AAOO,SAAS,iBAAA,CAAkB;AAAA,EAChC,WAAA,GAAc,GAAA;AAAA,EACd;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,WAAA,GAAcA,aAAsB,IAAI,CAAA;AAE9C,EAAA,MAAM,oBAAA,GAAuBC,kBAAY,MAAM;AAC7C,IAAA,IAAI,WAAA,CAAY,OAAA,IAAW,IAAA,IAAQ,YAAA,EAAc;AAC/C,MAAA,YAAA,CAAa,oBAAA,CAAqB,YAAY,OAAO,CAAA;AACrD,MAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AAAA,IACxB;AAAA,EACF,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,MAAM,qBAAA,GAAwBA,iBAAA;AAAA,IAC5B,CAAC,UAAA,KAAqD;AArB1D,MAAA,IAAA,EAAA;AAsBM,MAAA,MAAM,MAAM,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAc,QAAA;AAC1B,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,CAAA,EAAA,GAAA,UAAA,EAAW,KAAX,IAAA,GAAA,MAAA,GAAA,EAAA,CAAc,KAAA,CAAM,EAAE,eAAe,IAAA,EAAK,CAAA;AAC1C,QAAA;AAAA,MACF;AAEA,MAAA,oBAAA,EAAqB;AAErB,MAAA,IAAI,QAAA,GAAW,CAAA;AAEf,MAAA,MAAM,eAAe,MAAM;AACzB,QAAA,MAAM,UAAU,UAAA,EAAW;AAC3B,QAAA,IAAI,EAAC,mCAAS,WAAA,CAAA,EAAa;AACzB,UAAA,IAAI,QAAA,IAAY,WAAA,IAAe,EAAC,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAc,qBAAA,CAAA,EAAuB;AACnE,YAAA;AAAA,UACF;AAEA,UAAA,QAAA,IAAY,CAAA;AACZ,UAAA,WAAA,CAAY,OAAA,GACV,YAAA,CAAa,qBAAA,CAAsB,YAAY,CAAA;AACjD,UAAA;AAAA,QACF;AAEA,QAAA,OAAA,CAAQ,KAAA,CAAM,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA;AAErC,QAAA,IAAI,GAAA,CAAI,aAAA,KAAkB,OAAA,IAAW,QAAA,IAAY,WAAA,EAAa;AAC5D,UAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,UAAA;AAAA,QACF;AAEA,QAAA,QAAA,IAAY,CAAA;AACZ,QAAA,IAAI,6CAAc,qBAAA,EAAuB;AACvC,UAAA,WAAA,CAAY,OAAA,GACV,YAAA,CAAa,qBAAA,CAAsB,YAAY,CAAA;AAAA,QACnD,CAAA,MAAO;AACL,UAAA,cAAA,CAAe,YAAY,CAAA;AAAA,QAC7B;AAAA,MACF,CAAA;AAEA,MAAA,YAAA,EAAa;AAAA,IACf,CAAA;AAAA,IACA,CAAC,oBAAA,EAAsB,WAAA,EAAa,YAAY;AAAA,GAClD;AAEA,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,oBAAA,EAAqB;AAAA,IACvB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,oBAAoB,CAAC,CAAA;AAEzB,EAAA,OAAO;AAAA,IACL,oBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|