@dkile/react-multiselect
Version:
React hook wrapper for multiselect-core
1 lines • 45.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/use-multiselect.ts","../../multiselect-core/src/scheduler.ts","../../multiselect-core/src/utils.ts","../../multiselect-core/src/item.ts","../../multiselect-core/src/group.ts","../../multiselect-core/src/filter.ts","../../multiselect-core/src/group-filter.ts","../../multiselect-core/src/group-utils.ts","../../multiselect-core/src/collapse/collapse-strategy.ts","../../multiselect-core/src/collapse/collapse-manager.ts","../../multiselect-core/src/multiselect.ts"],"sourcesContent":["import { useRef, useState, useEffect } from \"react\";\nimport {\n createMultiSelect,\n rafScheduler,\n type MultiSelectOptions,\n type MultiSelect,\n} from \"multiselect-core\";\n\nexport function useMultiSelect<Data, Meta = unknown, GroupMeta = unknown>(\n options: MultiSelectOptions<Data, Meta, GroupMeta>\n): MultiSelect<Data, Meta, GroupMeta> {\n const coreRef = useRef(\n createMultiSelect<Data, Meta, GroupMeta>({\n ...options,\n scheduler: rafScheduler,\n })\n );\n\n coreRef.current.setFilter(options.filter);\n\n const [, setTick] = useState(0);\n\n useEffect(() => {\n const unsubscribe = coreRef.current.subscribe(() => {\n setTick((t) => t + 1);\n });\n\n return unsubscribe;\n }, []);\n\n return coreRef.current;\n}\n\nexport { CollapsePositionFirst, CollapsePositionLast } from \"multiselect-core\";\nexport type { PositionStrategy } from \"multiselect-core\";\n","export interface Scheduler {\n schedule(fn: () => void): void;\n}\n\nexport const rafScheduler: Scheduler = {\n schedule: (fn: () => void) => {\n requestAnimationFrame(fn);\n },\n};\n","import type { Accessor, ID } from \"./types\";\n\nexport const isID = (value: unknown): value is ID =>\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"bigint\";\n\nexport const accessObjectValue = <Data>(\n accessor: Accessor<Data>,\n item: Data\n): ID | undefined => {\n if (typeof accessor === \"string\") {\n const pathKeys = accessor.split(\".\");\n const value = pathKeys.reduce<unknown>((acc, key) => {\n if (acc && typeof acc === \"object\" && key in acc) {\n return (acc as Record<string, unknown>)[key];\n }\n return undefined;\n }, item as unknown);\n return isID(value) ? value : undefined;\n }\n\n const value = accessor(item);\n return value;\n};\n","import type { StrictAccessor, ID } from \"./types\";\nimport { accessObjectValue } from \"./utils\";\n\nexport type SelectItem<Data, Meta> = {\n id: ID;\n data: Data;\n isSelected: boolean;\n meta?: Meta;\n select: () => void;\n unselect: () => void;\n toggle: () => void;\n};\n\nexport interface ItemDef<Data, Meta> {\n id_accessor: StrictAccessor<Data>;\n meta?: (item: Data) => Meta;\n}\n\nexport function createCoreSelectItem<Data, Meta>(\n data: Data,\n idAccessor: StrictAccessor<Data>,\n metaFn: ((item: Data) => Meta) | undefined,\n selectedIds: Set<ID>,\n applyChange: (change: { added?: ID[]; removed?: ID[] }) => void\n): SelectItem<Data, Meta> {\n const rawId = accessObjectValue(idAccessor, data);\n if (rawId === undefined) {\n throw new Error(\n `id_accessor returned undefined for item: ${JSON.stringify(data)}`\n );\n }\n const id: ID = rawId;\n const wrapper: SelectItem<Data, Meta> = {\n id,\n data,\n get isSelected() {\n return selectedIds.has(id);\n },\n meta: metaFn ? metaFn(data) : undefined,\n select: () => {\n if (!selectedIds.has(id)) {\n applyChange({ added: [id] });\n }\n },\n unselect: () => {\n if (selectedIds.has(id)) {\n applyChange({ removed: [id] });\n }\n },\n toggle: () => {\n if (selectedIds.has(id)) {\n wrapper.unselect();\n } else {\n wrapper.select();\n }\n },\n };\n return wrapper;\n}\n","import type { ID, Accessor } from \"./types\";\nimport type { SelectItem } from \"./item\";\nimport { accessObjectValue } from \"./utils\";\n\nexport interface GroupNode<Data, Meta> {\n key: ID;\n level: number;\n path: ID[];\n items: SelectItem<Data, Meta>[];\n children?: GroupNode<Data, Meta>[];\n hasChildren(): this is GroupNode<Data, Meta> & {\n children: GroupNode<Data, Meta>[];\n };\n select(): void;\n unselect(): void;\n toggle(): void;\n isAllSelected(): boolean;\n}\n\nexport class GroupManager<Data, Meta> {\n private items: SelectItem<Data, Meta>[];\n private groupBy: Array<Accessor<Data>>;\n\n constructor(items: SelectItem<Data, Meta>[], groupBy: Array<Accessor<Data>>) {\n this.items = items;\n this.groupBy = groupBy;\n }\n\n public getGroupTree(): GroupNode<Data, Meta>[] {\n return this.groupItemsRecursive(this.items, 0, []);\n }\n\n public selectGroup(node: GroupNode<Data, Meta>): void {\n for (const leaf of this.collectLeaves(node)) {\n leaf.select();\n }\n }\n\n public unselectGroup(node: GroupNode<Data, Meta>): void {\n for (const leaf of this.collectLeaves(node)) {\n leaf.unselect();\n }\n }\n\n public toggleGroup(node: GroupNode<Data, Meta>): void {\n const leaves = this.collectLeaves(node);\n const allSelected = leaves.every((i) => i.isSelected);\n if (allSelected) {\n this.unselectGroup(node);\n } else {\n this.selectGroup(node);\n }\n }\n\n private groupItemsRecursive(\n items: SelectItem<Data, Meta>[],\n level: number,\n path: ID[]\n ): GroupNodeImpl<Data, Meta>[] {\n if (level >= this.groupBy.length) return [];\n const accessor = this.groupBy[level];\n const map = new Map<ID, SelectItem<Data, Meta>[]>();\n for (const item of items) {\n const rawValue = accessObjectValue(accessor, item.data);\n if (rawValue === undefined) {\n if (typeof accessor === \"string\") {\n throw new Error(\n `Grouping by path '${accessor}' returned undefined for item`\n );\n }\n continue;\n }\n const arr = map.get(rawValue) ?? [];\n arr.push(item);\n map.set(rawValue, arr);\n }\n const nodes: GroupNodeImpl<Data, Meta>[] = [];\n for (const [key, groupItems] of map.entries()) {\n const currentPath = [...path, key];\n const children = this.groupItemsRecursive(\n groupItems,\n level + 1,\n currentPath\n );\n const node = new GroupNodeImpl(\n this,\n key,\n level,\n currentPath,\n children.length > 0 ? [] : groupItems,\n children.length > 0 ? children : undefined\n );\n nodes.push(node);\n }\n return nodes;\n }\n\n private collectLeaves(node: GroupNode<Data, Meta>): SelectItem<Data, Meta>[] {\n if (node.children) {\n let leaves: SelectItem<Data, Meta>[] = [];\n for (const child of node.children) {\n leaves = leaves.concat(this.collectLeaves(child));\n }\n return leaves;\n }\n return node.items;\n }\n}\n\nclass GroupNodeImpl<Data, Meta> implements GroupNode<Data, Meta> {\n public key: ID;\n public level: number;\n public path: ID[];\n public items: SelectItem<Data, Meta>[];\n public children?: GroupNodeImpl<Data, Meta>[];\n private manager: GroupManager<Data, Meta>;\n\n constructor(\n manager: GroupManager<Data, Meta>,\n key: ID,\n level: number,\n path: ID[],\n items: SelectItem<Data, Meta>[],\n children?: GroupNodeImpl<Data, Meta>[]\n ) {\n this.manager = manager;\n this.key = key;\n this.level = level;\n this.path = path;\n this.items = items;\n this.children = children;\n }\n\n public select(): void {\n this.manager.selectGroup(this);\n }\n\n public unselect(): void {\n this.manager.unselectGroup(this);\n }\n\n public toggle(): void {\n this.manager.toggleGroup(this);\n }\n\n public hasChildren(): this is GroupNodeImpl<Data, Meta> & {\n children: GroupNodeImpl<Data, Meta>[];\n } {\n return Array.isArray(this.children) && this.children.length > 0;\n }\n\n public isAllSelected(): boolean {\n if (this.hasChildren()) {\n return this.children.every((child) => child.isAllSelected());\n }\n return this.items.every((item) => item.isSelected);\n }\n}\n","import type { SelectItem } from \"./item\";\n\nexport interface MultiSelectFilter<Data, Meta> {\n query: string;\n predicate: (item: Data, query: string, meta: Meta) => boolean;\n}\n\nexport class FilterManager<Data, Meta> {\n private items: SelectItem<Data, Meta>[];\n private filter?: MultiSelectFilter<Data, Meta>;\n\n constructor(\n items: SelectItem<Data, Meta>[],\n initialFilter?: MultiSelectFilter<Data, Meta>\n ) {\n this.items = items;\n this.filter = initialFilter;\n }\n\n public setFilter(filter?: MultiSelectFilter<Data, Meta>): void {\n this.filter = filter;\n }\n\n public getFilteredItems(): SelectItem<Data, Meta>[] {\n if (!this.filter) return this.items;\n const { query, predicate } = this.filter;\n return this.items.filter((item) =>\n predicate(item.data, query, item.meta as Meta)\n );\n }\n\n public isAllFilteredSelected(): boolean {\n const filtered = this.getFilteredItems();\n return filtered.length > 0 && filtered.every((item) => item.isSelected);\n }\n\n public selectAllFiltered(): void {\n for (const item of this.getFilteredItems()) {\n item.select();\n }\n }\n\n public unselectAllFiltered(): void {\n for (const item of this.getFilteredItems()) {\n item.unselect();\n }\n }\n\n public toggleAllFiltered(): void {\n if (this.isAllFilteredSelected()) {\n this.unselectAllFiltered();\n } else {\n this.selectAllFiltered();\n }\n }\n\n public getFilter(): MultiSelectFilter<Data, Meta> | undefined {\n return this.filter;\n }\n}\n","import type { ID } from \"./types\";\nimport type { SelectItem } from \"./item\";\nimport type { GroupNode } from \"./group\";\n\nexport interface ScopeOptions {\n filteredOnly?: boolean;\n}\n\nexport interface UnifiedGroupNode<Data, Meta, GroupMeta = unknown> {\n key: ID;\n level: number;\n path: ID[];\n getItems(options?: ScopeOptions): SelectItem<Data, Meta>[];\n getSubGroups(\n options?: ScopeOptions\n ): UnifiedGroupNode<Data, Meta, GroupMeta>[];\n getSubGroup(key: ID): UnifiedGroupNode<Data, Meta, GroupMeta> | undefined;\n hasSubGroups(options?: ScopeOptions): boolean;\n select(options?: { filteredOnly?: boolean }): void;\n unselect(options?: { filteredOnly?: boolean }): void;\n toggle(options?: { filteredOnly?: boolean }): void;\n isAllSelected(options?: { filteredOnly?: boolean }): boolean;\n totalCount: number;\n filteredCount: number;\n getMeta(): GroupMeta | undefined;\n}\n\nfunction collectRawLeaves<Data, Meta>(\n node: GroupNode<Data, Meta>\n): SelectItem<Data, Meta>[] {\n if (node.children) {\n let leaves: SelectItem<Data, Meta>[] = [];\n for (const child of node.children) {\n leaves = leaves.concat(collectRawLeaves(child));\n }\n return leaves;\n }\n return node.items;\n}\n\nexport function unifyGroupNodes<Data, Meta, GroupMeta = unknown>(\n nodes: GroupNode<Data, Meta>[],\n filteredSet: Set<ID>,\n filteredOnly: boolean\n): UnifiedGroupNode<Data, Meta, GroupMeta>[] {\n const result: UnifiedGroupNode<Data, Meta, GroupMeta>[] = [];\n for (const node of nodes) {\n const allLeaves = collectRawLeaves(node);\n const filteredLeaves = allLeaves.filter((i) => filteredSet.has(i.id));\n if (filteredOnly && filteredLeaves.length === 0) continue;\n const childrenUnified = unifyGroupNodes<Data, Meta, GroupMeta>(\n node.children ?? [],\n filteredSet,\n filteredOnly\n );\n const unified: UnifiedGroupNode<Data, Meta, GroupMeta> = {\n key: node.key,\n level: node.level,\n path: node.path,\n getMeta(): GroupMeta | undefined {\n return undefined;\n },\n getItems({ filteredOnly: fo } = {}): SelectItem<Data, Meta>[] {\n return fo ? filteredLeaves : allLeaves;\n },\n getSubGroups(): UnifiedGroupNode<Data, Meta, GroupMeta>[] {\n return childrenUnified;\n },\n getSubGroup(\n key: ID\n ): UnifiedGroupNode<Data, Meta, GroupMeta> | undefined {\n return childrenUnified.find((child) => child.key === key);\n },\n hasSubGroups(): boolean {\n return childrenUnified.length > 0;\n },\n select({ filteredOnly: fo } = {}): void {\n for (const item of fo ? filteredLeaves : allLeaves) item.select();\n },\n unselect({ filteredOnly: fo } = {}): void {\n for (const item of fo ? filteredLeaves : allLeaves) item.unselect();\n },\n toggle({ filteredOnly: fo } = {}): void {\n const target = fo ? filteredLeaves : allLeaves;\n const allSel = target.length > 0 && target.every((i) => i.isSelected);\n if (allSel) {\n for (const item of target) {\n item.unselect();\n }\n } else {\n for (const item of target) {\n item.select();\n }\n }\n },\n isAllSelected({ filteredOnly: fo } = {}): boolean {\n const target = fo ? filteredLeaves : allLeaves;\n return target.length > 0 && target.every((i) => i.isSelected);\n },\n totalCount: allLeaves.length,\n filteredCount: filteredLeaves.length,\n };\n result.push(unified as UnifiedGroupNode<Data, Meta, GroupMeta>);\n }\n return result;\n}\n","import type { ID } from \"./types\";\nimport type { SelectItem } from \"./item\";\nimport type { GroupNode } from \"./group\";\nimport type { UnifiedGroupNode } from \"./group-filter\";\n\nexport interface GroupTreeOptions {\n filter?: { filteredOnly?: boolean };\n selection?: { selectedOnly?: boolean; includePartial?: boolean };\n}\n\nfunction collectRawLeaves<Data, Meta>(\n node: GroupNode<Data, Meta>\n): SelectItem<Data, Meta>[] {\n if (node.children) {\n let leaves: SelectItem<Data, Meta>[] = [];\n for (const child of node.children) {\n leaves = leaves.concat(collectRawLeaves(child));\n }\n return leaves;\n }\n return node.items;\n}\n\nexport function pruneTreeByFilter<Data, Meta>(\n nodes: GroupNode<Data, Meta>[],\n filteredSet: Set<ID>,\n filteredOnly: boolean\n): GroupNode<Data, Meta>[] {\n if (!filteredOnly) return nodes;\n const result: GroupNode<Data, Meta>[] = [];\n for (const node of nodes) {\n const leaves = collectRawLeaves(node);\n const hasFiltered = leaves.some((item) => filteredSet.has(item.id));\n const childrenPruned = pruneTreeByFilter(\n node.children ?? [],\n filteredSet,\n filteredOnly\n );\n if (hasFiltered || childrenPruned.length > 0) {\n const clone = Object.assign(\n Object.create(Object.getPrototypeOf(node)),\n node\n );\n if (childrenPruned.length > 0) {\n clone.children = childrenPruned;\n }\n result.push(clone);\n }\n }\n return result;\n}\n\nexport function pruneUnifiedBySelection<Data, Meta, GroupHeader = unknown>(\n nodes: UnifiedGroupNode<Data, Meta, GroupHeader>[],\n selectionSet: Set<ID>,\n selectedOnly: boolean,\n includePartial: boolean\n): UnifiedGroupNode<Data, Meta, GroupHeader>[] {\n if (!selectedOnly) return nodes;\n const result: UnifiedGroupNode<Data, Meta, GroupHeader>[] = [];\n for (const node of nodes) {\n const allItems = node.getItems({ filteredOnly: false });\n const selLeaves = allItems.filter((item) => selectionSet.has(item.id));\n if (selectedOnly) {\n if (includePartial) {\n if (selLeaves.length === 0) continue;\n } else {\n if (selLeaves.length !== allItems.length) continue;\n }\n }\n const childrenPruned = pruneUnifiedBySelection(\n node.getSubGroups({ filteredOnly: false }),\n selectionSet,\n selectedOnly,\n includePartial\n );\n\n const clone: UnifiedGroupNode<Data, Meta, GroupHeader> = Object.assign(\n Object.create(Object.getPrototypeOf(node)),\n node\n );\n clone.getSubGroups = () => childrenPruned;\n clone.hasSubGroups = () => childrenPruned.length > 0;\n result.push(clone as UnifiedGroupNode<Data, Meta, GroupHeader>);\n }\n return result;\n}\n","import type { ID } from \"../types\";\nimport type { UnifiedGroupNode } from \"../group-filter\";\nimport type { SelectItem } from \"../item\";\n\nexport type PositionStrategy = (indices: number[]) => number;\n\nexport const CollapsePositionFirst: PositionStrategy = (inds) =>\n Math.min(...inds);\n\nexport const CollapsePositionLast: PositionStrategy = (inds) =>\n Math.max(...inds);\n\nexport type CollapsedNode<Data, Meta, GroupMeta = unknown> =\n | { type: \"item\"; node: SelectItem<Data, Meta>; order: number }\n | {\n type: \"group\";\n node: UnifiedGroupNode<Data, Meta, GroupMeta>;\n order: number;\n };\n\nexport interface CollapseOptions {\n filteredOnly?: boolean;\n positionStrategy?: PositionStrategy;\n}\n\nexport function collapseSelection<Data, Meta, GroupMeta = unknown>(\n tree: UnifiedGroupNode<Data, Meta, GroupMeta>[],\n orderMap: Map<ID, number>,\n options: CollapseOptions = {}\n): CollapsedNode<Data, Meta, GroupMeta>[] {\n const { filteredOnly = false, positionStrategy = CollapsePositionFirst } =\n options;\n const out: CollapsedNode<Data, Meta, GroupMeta>[] = [];\n\n function walk(nodes: UnifiedGroupNode<Data, Meta, GroupMeta>[]) {\n for (const node of nodes) {\n const items = node.getItems({ filteredOnly });\n const sel = items.filter((i) => i.isSelected);\n const children = node.getSubGroups({ filteredOnly });\n\n if (sel.length === items.length && sel.length > 0) {\n const idxs = sel.map(\n (i) => orderMap.get(i.id) ?? Number.MAX_SAFE_INTEGER\n );\n out.push({ type: \"group\", node, order: positionStrategy(idxs) });\n } else {\n if (children.length === 0) {\n for (const item of sel) {\n const ord = orderMap.get(item.id) ?? Number.MAX_SAFE_INTEGER;\n out.push({ type: \"item\", node: item, order: ord });\n }\n }\n\n walk(children);\n }\n }\n }\n\n walk(tree);\n\n return out.sort((a, b) => a.order - b.order);\n}\n","import type { ID } from \"../types\";\nimport type { MultiSelect } from \"../multiselect\";\nimport { collapseSelection, CollapsePositionFirst } from \"./collapse-strategy\";\nimport type {\n CollapseOptions,\n CollapsedNode,\n PositionStrategy,\n} from \"./collapse-strategy\";\n\nexport class CollapseManager<Data, Meta = unknown, GroupMeta = unknown> {\n private orderMap = new Map<ID, number>();\n private counter = 0;\n\n constructor(private ms: MultiSelect<Data, Meta, GroupMeta>) {\n ms.subscribe((_state, diff) => {\n for (const id of diff.added) {\n this.orderMap.set(id, this.counter++);\n }\n for (const id of diff.removed) {\n this.orderMap.delete(id);\n }\n });\n }\n\n public getCollapsedSelection(\n options: CollapseOptions = {}\n ): CollapsedNode<Data, Meta, GroupMeta>[] {\n const filteredOnly = options.filteredOnly;\n const positionStrategy: PositionStrategy =\n options.positionStrategy ?? CollapsePositionFirst;\n\n const tree = this.ms.getGroupTree({ filter: { filteredOnly } });\n\n const collapsed = collapseSelection(tree, this.orderMap, {\n filteredOnly,\n positionStrategy,\n });\n\n const treeItemIds = new Set<ID>();\n for (const node of tree) {\n for (const item of node.getItems({ filteredOnly })) {\n treeItemIds.add(item.id);\n }\n }\n const selectedItems = this.ms.getSelectedItems({ filteredOnly });\n for (const item of selectedItems) {\n if (!treeItemIds.has(item.id)) {\n const order = this.orderMap.get(item.id) ?? Number.MAX_SAFE_INTEGER;\n collapsed.push({ type: \"item\", node: item, order });\n }\n }\n\n return collapsed.sort((a, b) => a.order - b.order);\n }\n}\n","import type { ID, Accessor } from \"./types\";\nimport type { ItemDef, SelectItem } from \"./item\";\nimport type { Scheduler } from \"./scheduler\";\nimport { rafScheduler } from \"./scheduler\";\nimport { createCoreSelectItem } from \"./item\";\nimport { GroupManager, type GroupNode } from \"./group\";\nimport type { MultiSelectFilter } from \"./filter\";\nimport { FilterManager } from \"./filter\";\nimport type { UnifiedGroupNode } from \"./group-filter\";\nimport { unifyGroupNodes } from \"./group-filter\";\nimport type { GroupTreeOptions } from \"./group-utils\";\nimport { pruneTreeByFilter, pruneUnifiedBySelection } from \"./group-utils\";\nimport { CollapseManager } from \"./collapse/collapse-manager\";\nimport type {\n CollapseOptions,\n CollapsedNode,\n} from \"./collapse/collapse-strategy\";\n\nexport interface GroupByDescriptor<Data, Meta = unknown, GroupMeta = unknown> {\n accessor: Accessor<Data>;\n getMeta?: (groupKey: ID, items: Data[], level: number) => GroupMeta;\n}\n\nexport interface MultiSelectState {\n selectedIds: Set<ID>;\n}\n\nexport interface MultiSelectOptions<Data, Meta = unknown, GroupMeta = unknown> {\n data: Data[];\n itemDef: ItemDef<Data, Meta>;\n initialState?: Omit<MultiSelectState, \"selectedIds\"> & {\n selectedIds: Array<ID>;\n };\n filter?: MultiSelectFilter<Data, Meta>;\n scheduler?: Scheduler;\n groupBy?: Array<Accessor<Data> | GroupByDescriptor<Data, Meta, GroupMeta>>;\n}\n\ntype Listener = (\n state: MultiSelectState,\n diff: { added: ID[]; removed: ID[] }\n) => void;\n\nexport interface MultiSelect<Data, Meta = unknown, GroupMeta = unknown> {\n subscribe(listener: Listener): () => void;\n getItems(): SelectItem<Data, Meta>[];\n getSelectedIds(options?: { filteredOnly?: boolean }): ID[];\n getSelectedItems(options?: {\n filteredOnly?: boolean;\n }): SelectItem<Data, Meta>[];\n isAllSelected(): boolean;\n selectAll(): void;\n unselectAll(): void;\n toggleAll(): void;\n getFilteredItems(): SelectItem<Data, Meta>[];\n isAllFilteredSelected(): boolean;\n selectAllFiltered(): void;\n unselectAllFiltered(): void;\n toggleAllFiltered(): void;\n setFilter(filter?: MultiSelectFilter<Data, Meta>): void;\n getGroupTree(\n options?: GroupTreeOptions\n ): UnifiedGroupNode<Data, Meta, GroupMeta>[];\n getSelectionSummary(options?: { filteredOnly?: boolean }): {\n total: number;\n selected: number;\n };\n getCollapsedSelection(\n options?: CollapseOptions\n ): CollapsedNode<Data, Meta, GroupMeta>[];\n getGroup(key: ID): UnifiedGroupNode<Data, Meta, GroupMeta> | undefined;\n getItem(key: ID): SelectItem<Data, Meta> | undefined;\n getGroupMeta(groupKey: ID): GroupMeta | undefined;\n}\n\nexport class MultiSelectCore<Data, Meta = unknown, GroupMeta = unknown>\n implements MultiSelect<Data, Meta, GroupMeta>\n{\n private rawGroupTree: GroupNode<Data, Meta>[];\n private filterManager: FilterManager<Data, Meta>;\n private lastCacheKey?: string;\n private lastUnifiedTree?: UnifiedGroupNode<Data, Meta, GroupMeta>[];\n private data: Data[];\n private items: SelectItem<Data, Meta>[];\n private itemMap: Map<ID, SelectItem<Data, Meta>>;\n private groupMap: Map<ID, UnifiedGroupNode<Data, Meta, GroupMeta>>;\n private selectedIds: Set<ID>;\n private listeners = new Set<Listener>();\n\n private pendingDiff: { added: Set<ID>; removed: Set<ID> } = {\n added: new Set<ID>(),\n removed: new Set<ID>(),\n };\n private isFlushScheduled = false;\n private scheduler: Scheduler;\n private groupManager: GroupManager<Data, Meta>;\n private collapseManager: CollapseManager<Data, Meta, GroupMeta>;\n private metaFns: Array<\n ((groupKey: ID, items: Data[], level: number) => GroupMeta) | undefined\n >;\n\n constructor(options: MultiSelectOptions<Data, Meta, GroupMeta>) {\n this.data = options.data;\n const idAccessor = options.itemDef.id_accessor;\n this.selectedIds = new Set(options.initialState?.selectedIds);\n this.items = this.data.map((dataItem) =>\n createCoreSelectItem(\n dataItem,\n idAccessor,\n options.itemDef.meta,\n this.selectedIds,\n this.applyChange.bind(this)\n )\n );\n this.itemMap = new Map();\n for (const item of this.items) {\n this.itemMap.set(item.id, item);\n }\n this.groupMap = new Map();\n this.filterManager = new FilterManager(this.items, options.filter);\n const groupBySpecs =\n options.groupBy ??\n ([] as Array<Accessor<Data> | GroupByDescriptor<Data, Meta, GroupMeta>>);\n const accessors = groupBySpecs.map((spec) =>\n typeof spec === \"object\" ? spec.accessor : spec\n );\n this.groupManager = new GroupManager(this.items, accessors);\n this.metaFns = groupBySpecs.map((spec) =>\n typeof spec === \"object\" ? spec.getMeta : undefined\n );\n\n this.rawGroupTree = this.groupManager.getGroupTree();\n this.scheduler = options.scheduler ?? rafScheduler;\n this.collapseManager = new CollapseManager<Data, Meta, GroupMeta>(this);\n }\n\n private applyChange(change: { added?: ID[]; removed?: ID[] }) {\n if (change.added) {\n for (const id of change.added) {\n this.selectedIds.add(id);\n this.pendingDiff.removed.delete(id);\n this.pendingDiff.added.add(id);\n }\n }\n if (change.removed) {\n for (const id of change.removed) {\n this.selectedIds.delete(id);\n this.pendingDiff.added.delete(id);\n this.pendingDiff.removed.add(id);\n }\n }\n this.scheduleFlush();\n }\n\n private emit(diff: { added?: ID[]; removed?: ID[] }) {\n const state: MultiSelectState = { selectedIds: new Set(this.selectedIds) };\n for (const listener of this.listeners) {\n listener(state, { added: diff.added ?? [], removed: diff.removed ?? [] });\n }\n }\n\n public getItems(): SelectItem<Data, Meta>[] {\n return this.items;\n }\n\n public getSelectedIds({\n filteredOnly,\n }: { filteredOnly?: boolean } = {}): ID[] {\n return this.getSelectedItems({ filteredOnly }).map((item) => item.id);\n }\n\n public getSelectedItems({\n filteredOnly,\n }: { filteredOnly?: boolean } = {}): SelectItem<Data, Meta>[] {\n const items = filteredOnly\n ? this.filterManager.getFilteredItems()\n : this.items;\n return items.filter((item) => item.isSelected);\n }\n\n public isAllSelected(): boolean {\n return this.items.length > 0 && this.items.every((item) => item.isSelected);\n }\n\n public selectAll(): void {\n for (const item of this.items) {\n item.select();\n }\n }\n\n public unselectAll(): void {\n for (const item of this.items) {\n item.unselect();\n }\n }\n\n public toggleAll(): void {\n if (this.isAllSelected()) {\n this.unselectAll();\n } else {\n this.selectAll();\n }\n }\n\n public subscribe(listener: Listener): () => void {\n this.listeners.add(listener);\n listener(\n { selectedIds: new Set(this.selectedIds) },\n { added: [], removed: [] }\n );\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n private scheduleFlush(): void {\n if (this.isFlushScheduled) return;\n this.isFlushScheduled = true;\n this.scheduler.schedule(() => this.flush());\n }\n\n private flush(): void {\n const diff = {\n added: Array.from(this.pendingDiff.added),\n removed: Array.from(this.pendingDiff.removed),\n };\n this.pendingDiff.added.clear();\n this.pendingDiff.removed.clear();\n this.isFlushScheduled = false;\n this.emit(diff);\n }\n\n public getFilteredItems(): SelectItem<Data, Meta>[] {\n return this.filterManager.getFilteredItems();\n }\n\n public isAllFilteredSelected(): boolean {\n return this.filterManager.isAllFilteredSelected();\n }\n\n public selectAllFiltered(): void {\n this.filterManager.selectAllFiltered();\n }\n\n public unselectAllFiltered(): void {\n this.filterManager.unselectAllFiltered();\n }\n\n public toggleAllFiltered(): void {\n this.filterManager.toggleAllFiltered();\n }\n\n public setFilter(filter?: MultiSelectFilter<Data, Meta>): void {\n this.filterManager.setFilter(filter);\n }\n\n public getGroupTree(\n options?: GroupTreeOptions\n ): UnifiedGroupNode<Data, Meta, GroupMeta>[] {\n const filteredOnly = options?.filter?.filteredOnly ?? false;\n const selectedOnly = options?.selection?.selectedOnly ?? false;\n const includePartial = options?.selection?.includePartial ?? false;\n\n const filterQuery = this.filterManager.getFilter()?.query ?? \"\";\n const effectiveFilteredOnly = filteredOnly && filterQuery.length > 0;\n const cacheKey = `${filterQuery}|${effectiveFilteredOnly}|${selectedOnly}|${includePartial}`;\n if (this.lastUnifiedTree && cacheKey === this.lastCacheKey) {\n return this.lastUnifiedTree;\n }\n\n const filteredSet = new Set(\n this.filterManager.getFilteredItems().map((i) => i.id)\n );\n const prunedFilter = pruneTreeByFilter(\n this.rawGroupTree,\n filteredSet,\n effectiveFilteredOnly\n );\n const unifiedByFilter = unifyGroupNodes<Data, Meta, GroupMeta>(\n prunedFilter,\n filteredSet,\n effectiveFilteredOnly\n );\n const selectionSet = new Set(this.getSelectedIds({ filteredOnly }));\n const finalTree = pruneUnifiedBySelection<Data, Meta, GroupMeta>(\n unifiedByFilter,\n selectionSet,\n selectedOnly,\n includePartial\n );\n\n this.lastUnifiedTree = finalTree;\n this.lastCacheKey = cacheKey;\n this.groupMap.clear();\n const walk = (nodes: UnifiedGroupNode<Data, Meta, GroupMeta>[]) => {\n for (const node of nodes) {\n this.groupMap.set(node.key, node);\n walk(node.getSubGroups({ filteredOnly: false }));\n }\n };\n walk(finalTree);\n\n const attachMeta = (\n nodes: UnifiedGroupNode<Data, Meta, GroupMeta>[]\n ): void => {\n for (const node of nodes) {\n const fn = this.metaFns[node.level];\n node.getMeta = () =>\n fn\n ? fn(\n node.key,\n node.getItems({ filteredOnly: false }).map((i) => i.data),\n node.level\n )\n : undefined;\n attachMeta(node.getSubGroups({ filteredOnly: false }));\n }\n };\n attachMeta(finalTree);\n return finalTree;\n }\n\n public getSelectionSummary(options?: { filteredOnly?: boolean }): {\n total: number;\n selected: number;\n } {\n const total = options?.filteredOnly\n ? this.filterManager.getFilteredItems().length\n : this.items.length;\n const selected = this.getSelectedItems(options).length;\n return { total, selected };\n }\n\n public getCollapsedSelection(\n options?: CollapseOptions\n ): CollapsedNode<Data, Meta, GroupMeta>[] {\n return this.collapseManager.getCollapsedSelection(options);\n }\n\n public getGroup(\n key: ID\n ): UnifiedGroupNode<Data, Meta, GroupMeta> | undefined {\n this.getGroupTree();\n return this.groupMap.get(key);\n }\n\n public getItem(key: ID): SelectItem<Data, Meta> | undefined {\n return this.itemMap.get(key);\n }\n\n public getGroupMeta(groupKey: ID): GroupMeta | undefined {\n return this.getGroup(groupKey)?.getMeta();\n }\n}\n\nexport function createMultiSelect<Data, Meta = unknown, GroupMeta = unknown>(\n options: MultiSelectOptions<Data, Meta, GroupMeta>\n): MultiSelect<Data, Meta, GroupMeta> {\n return new MultiSelectCore<Data, Meta, GroupMeta>(options);\n}\n"],"mappings":"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","names":["value","collectRawLeaves"]}