@carbon/ibm-products-web-components 0.41.0 → 0.41.1-rc.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.
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import { version } from "../../package.js";
8
+ import { version } from "../../ibm-products-web-components/package.js";
9
9
  //#region src/globals/internal/storybook-cdn.ts
10
10
  /**
11
11
  * @license
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Copyright IBM Corp. 2020, 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ //#region ../ibm-products-utilities/src/utils/add-select/add-select-data.ts
9
+ /**
10
+ * AddSelectData - A lightweight, framework-agnostic utility for managing hierarchical data
11
+ *
12
+ * This utility provides standard APIs for common operations such as setting, selecting,
13
+ * traversing, searching, and sorting hierarchical data structures. It encapsulates data
14
+ * logic separate from UI, allowing both React and Web Components to reuse the same
15
+ * data management functions.
16
+ */
17
+ var AddSelectData = class {
18
+ constructor() {
19
+ this.items = [];
20
+ this.itemMap = /* @__PURE__ */ new Map();
21
+ this.parentMap = /* @__PURE__ */ new Map();
22
+ this.selectedIds = /* @__PURE__ */ new Set();
23
+ this.depthCache = /* @__PURE__ */ new Map();
24
+ this.selectedItemsCache = null;
25
+ }
26
+ /**
27
+ * Initialize or replace the hierarchical data
28
+ * @param items - Array of hierarchical items
29
+ */
30
+ setItems(items) {
31
+ this.items = items;
32
+ this._invalidateCaches();
33
+ this._buildMaps(items);
34
+ }
35
+ /**
36
+ * Get the full list of items
37
+ * @returns Array of all items
38
+ */
39
+ getItems() {
40
+ return this.items;
41
+ }
42
+ /**
43
+ * Retrieve a single item by its id
44
+ * @param id - The item id
45
+ * @returns The item or undefined if not found
46
+ */
47
+ getItem(id) {
48
+ return this.itemMap.get(id);
49
+ }
50
+ /**
51
+ * Update a given item with new properties
52
+ * @param id - The item id
53
+ * @param newProperties - Properties to update
54
+ * @returns true if item was found and updated, false otherwise
55
+ */
56
+ setItem(id, newProperties) {
57
+ const item = this.itemMap.get(id);
58
+ if (!item) return false;
59
+ Object.assign(item, newProperties);
60
+ if ("selected" in newProperties || "status" in newProperties) this._invalidateSelectionCache();
61
+ return true;
62
+ }
63
+ /**
64
+ * Returns an array of items marked as selected (memoized)
65
+ * @returns Array of selected items
66
+ */
67
+ getSelectedItems() {
68
+ if (this.selectedItemsCache !== null) return this.selectedItemsCache;
69
+ const selected = [];
70
+ this.selectedIds.forEach((id) => {
71
+ const item = this.itemMap.get(id);
72
+ if (item) selected.push(item);
73
+ });
74
+ this.selectedItemsCache = selected;
75
+ return selected;
76
+ }
77
+ /**
78
+ * Mark one or more items (by id) as selected
79
+ * @param ids - Single id or array of ids to select
80
+ * @param exclusive - If true, deselect all other items (default: false)
81
+ */
82
+ setSelectedItems(ids, exclusive = false) {
83
+ const idArray = Array.isArray(ids) ? ids : [ids];
84
+ if (exclusive) {
85
+ this.selectedIds.forEach((id) => {
86
+ const item = this.itemMap.get(id);
87
+ if (item) {
88
+ item.selected = false;
89
+ item.status = "unchecked";
90
+ }
91
+ });
92
+ this.selectedIds.clear();
93
+ }
94
+ idArray.forEach((id) => {
95
+ const item = this.itemMap.get(id);
96
+ if (item) {
97
+ item.selected = true;
98
+ item.status = "checked";
99
+ this.selectedIds.add(id);
100
+ }
101
+ });
102
+ this._invalidateSelectionCache();
103
+ }
104
+ /**
105
+ * Get direct children of a node
106
+ * @param id - The parent item id
107
+ * @returns Array of child items or empty array if no children
108
+ */
109
+ getItemChildren(id) {
110
+ const item = this.itemMap.get(id);
111
+ if (!item) return [];
112
+ return item.children?.entries ?? [];
113
+ }
114
+ /**
115
+ * Get the parent of a node
116
+ * @param id - The child item id
117
+ * @returns The parent item or undefined if no parent (root level)
118
+ */
119
+ getItemParent(id) {
120
+ const parentId = this.parentMap.get(id);
121
+ return parentId ? this.itemMap.get(parentId) : void 0;
122
+ }
123
+ /**
124
+ * Get all ancestors (parents up to the root) of a node
125
+ * @param id - The item id
126
+ * @returns Array of ancestor items from immediate parent to root
127
+ */
128
+ getItemParents(id) {
129
+ const parents = [];
130
+ let currentId = id;
131
+ while (currentId) {
132
+ const parentId = this.parentMap.get(currentId);
133
+ if (!parentId) break;
134
+ const parent = this.itemMap.get(parentId);
135
+ if (parent) parents.push(parent);
136
+ currentId = parentId;
137
+ }
138
+ return parents;
139
+ }
140
+ /**
141
+ * Retrieve the selected state status of an item
142
+ * @param id - The item id
143
+ * @returns The status or undefined if item not found
144
+ */
145
+ getItemStatus(id) {
146
+ return this.itemMap.get(id)?.status;
147
+ }
148
+ /**
149
+ * Set or update the status of an item
150
+ * @param id - The item id
151
+ * @param status - The new status
152
+ * @returns true if item was found and updated, false otherwise
153
+ */
154
+ setItemStatus(id, status) {
155
+ const item = this.itemMap.get(id);
156
+ if (!item) return false;
157
+ const wasSelected = item.selected;
158
+ item.status = status;
159
+ item.selected = status === "checked";
160
+ if (item.selected) this.selectedIds.add(id);
161
+ else this.selectedIds.delete(id);
162
+ if (wasSelected !== item.selected) this._invalidateSelectionCache();
163
+ return true;
164
+ }
165
+ /**
166
+ * Check whether an item is selected (O(1) lookup)
167
+ * @param id - The item id
168
+ * @returns true if selected, false otherwise
169
+ */
170
+ isSelected(id) {
171
+ return this.selectedIds.has(id);
172
+ }
173
+ /**
174
+ * Search items based on a query and return matching items
175
+ * @param query - The search query string
176
+ * @param options - Search options
177
+ * @returns Array of matching items
178
+ */
179
+ search(query, options = {}) {
180
+ if (!query) return [];
181
+ const { caseSensitive = false, searchFields = ["title", "value"], maxResults } = options;
182
+ const searchTerm = caseSensitive ? query : query.toLowerCase();
183
+ const results = [];
184
+ const shouldContinue = () => {
185
+ return !maxResults || results.length < maxResults;
186
+ };
187
+ this._traverseItems(this.items, (item) => {
188
+ if (!shouldContinue()) return;
189
+ for (const field of searchFields) {
190
+ const fieldValue = item[field];
191
+ if (fieldValue) {
192
+ if ((caseSensitive ? String(fieldValue) : String(fieldValue).toLowerCase()).includes(searchTerm)) {
193
+ results.push(item);
194
+ break;
195
+ }
196
+ }
197
+ }
198
+ });
199
+ return results;
200
+ }
201
+ /**
202
+ * Sort items based on a comparator function
203
+ * @param compareFn - Comparison function for sorting
204
+ * @param recursive - If true, sort children recursively (default: false)
205
+ */
206
+ sort(compareFn, recursive = false) {
207
+ if (recursive) this._sortRecursive(this.items, compareFn);
208
+ this.items.sort(compareFn);
209
+ this._invalidateCaches();
210
+ this._buildMaps(this.items);
211
+ }
212
+ /**
213
+ * Clear all selections (optimized with Set)
214
+ */
215
+ clearSelections() {
216
+ this.selectedIds.forEach((id) => {
217
+ const item = this.itemMap.get(id);
218
+ if (item) {
219
+ item.selected = false;
220
+ item.status = "unchecked";
221
+ }
222
+ });
223
+ this.selectedIds.clear();
224
+ this._invalidateSelectionCache();
225
+ }
226
+ /**
227
+ * Get the depth/level of an item in the hierarchy (cached)
228
+ * @param id - The item id
229
+ * @returns The depth (0 for root level items) or -1 if not found
230
+ */
231
+ getItemDepth(id) {
232
+ const cachedDepth = this.depthCache.get(id);
233
+ if (cachedDepth !== void 0) return cachedDepth;
234
+ if (!this.itemMap.has(id)) return -1;
235
+ let depth = 0;
236
+ let currentId = id;
237
+ while (currentId) {
238
+ const parentId = this.parentMap.get(currentId);
239
+ if (!parentId) break;
240
+ depth++;
241
+ currentId = parentId;
242
+ }
243
+ this.depthCache.set(id, depth);
244
+ return depth;
245
+ }
246
+ /**
247
+ * Check if an item has children
248
+ * @param id - The item id
249
+ * @returns true if item has children, false otherwise
250
+ */
251
+ hasChildren(id) {
252
+ return !!this.itemMap.get(id)?.children?.entries?.length;
253
+ }
254
+ /**
255
+ * Get all descendant items of a node
256
+ * @param id - The parent item id
257
+ * @returns Array of all descendant items
258
+ */
259
+ getItemDescendants(id) {
260
+ const item = this.itemMap.get(id);
261
+ if (!item?.children?.entries) return [];
262
+ const descendants = [];
263
+ this._traverseItems(item.children.entries, (child) => {
264
+ descendants.push(child);
265
+ });
266
+ return descendants;
267
+ }
268
+ /**
269
+ * Check if an item has any selected descendants (optimized)
270
+ * @param id - The item id
271
+ * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)
272
+ * @returns true if any descendant is selected, false otherwise
273
+ */
274
+ hasSelectedDescendants(id, selectedIds = this.selectedIds) {
275
+ const children = this.getItemChildren(id);
276
+ if (!children.length) return false;
277
+ for (const child of children) if (selectedIds.has(child.id) || this.hasSelectedDescendants(child.id, selectedIds)) return true;
278
+ return false;
279
+ }
280
+ /**
281
+ * Check if all descendants of an item are selected (optimized)
282
+ * @param id - The item id
283
+ * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)
284
+ * @returns true if all descendants are selected, false otherwise
285
+ */
286
+ allDescendantsSelected(id, selectedIds = this.selectedIds) {
287
+ const item = this.itemMap.get(id);
288
+ if (!item) return false;
289
+ const children = this.getItemChildren(id);
290
+ if (!children.length) return selectedIds.has(item.id);
291
+ for (const child of children) if (!selectedIds.has(child.id) || !this.allDescendantsSelected(child.id, selectedIds)) return false;
292
+ return true;
293
+ }
294
+ /**
295
+ * Get all descendant IDs from an item (including the item itself)
296
+ * @param id - The item id
297
+ * @returns Array of all descendant IDs including the item itself
298
+ */
299
+ getAllDescendantIds(id) {
300
+ if (!this.itemMap.get(id)) return [];
301
+ const ids = [id];
302
+ const children = this.getItemChildren(id);
303
+ for (const child of children) ids.push(...this.getAllDescendantIds(child.id));
304
+ return ids;
305
+ }
306
+ /**
307
+ * Get only top-level selected items (items without selected ancestors)
308
+ * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)
309
+ * @returns Array of top-level selected items
310
+ */
311
+ getTopLevelSelectedItems(selectedIds = this.selectedIds) {
312
+ const topLevelItems = [];
313
+ const processedIds = /* @__PURE__ */ new Set();
314
+ const hasSelectedAncestor = (itemId) => {
315
+ return this.getItemParents(itemId).some((parent) => selectedIds.has(parent.id));
316
+ };
317
+ selectedIds.forEach((id) => {
318
+ if (!processedIds.has(id) && !hasSelectedAncestor(id)) {
319
+ const item = this.itemMap.get(id);
320
+ if (item) {
321
+ topLevelItems.push(item);
322
+ this.getAllDescendantIds(id).forEach((descId) => processedIds.add(descId));
323
+ }
324
+ }
325
+ });
326
+ return topLevelItems;
327
+ }
328
+ /**
329
+ * Invalidate all caches
330
+ * @private
331
+ */
332
+ _invalidateCaches() {
333
+ this.selectedItemsCache = null;
334
+ this.depthCache.clear();
335
+ }
336
+ /**
337
+ * Invalidate selection cache only
338
+ * @private
339
+ */
340
+ _invalidateSelectionCache() {
341
+ this.selectedItemsCache = null;
342
+ }
343
+ /**
344
+ * Build internal maps for efficient lookups (optimized with depth caching)
345
+ * @private
346
+ */
347
+ _buildMaps(items, parentId, depth = 0) {
348
+ if (!parentId) {
349
+ this.itemMap.clear();
350
+ this.parentMap.clear();
351
+ this.selectedIds.clear();
352
+ this.depthCache.clear();
353
+ }
354
+ items.forEach((item) => {
355
+ this.itemMap.set(item.id, item);
356
+ this.depthCache.set(item.id, depth);
357
+ if (parentId) this.parentMap.set(item.id, parentId);
358
+ if (item.selected) this.selectedIds.add(item.id);
359
+ if (item.children?.entries) this._buildMaps(item.children.entries, item.id, depth + 1);
360
+ });
361
+ }
362
+ /**
363
+ * Traverse all items and apply a callback function
364
+ * @private
365
+ */
366
+ _traverseItems(items, callback) {
367
+ for (const item of items) {
368
+ callback(item);
369
+ if (item.children?.entries) this._traverseItems(item.children.entries, callback);
370
+ }
371
+ }
372
+ /**
373
+ * Sort items recursively
374
+ * @private
375
+ */
376
+ _sortRecursive(items, compareFn) {
377
+ for (const item of items) if (item.children?.entries) {
378
+ item.children.entries.sort(compareFn);
379
+ this._sortRecursive(item.children.entries, compareFn);
380
+ }
381
+ }
382
+ };
383
+ //#endregion
384
+ export { AddSelectData };
385
+
386
+ //# sourceMappingURL=add-select-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-select-data.js","names":[],"sources":["../../../../../../ibm-products-utilities/src/utils/add-select/add-select-data.ts"],"sourcesContent":["/**\n * Copyright IBM Corp. 2026\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { ReactNode } from 'react';\n\n/**\n * Status types for items in the hierarchical data structure\n */\nexport type ItemStatus = 'checked' | 'unchecked' | 'indeterminate';\n\n/**\n * Interface for item details metadata\n */\nexport interface ItemDetails {\n [key: string]: unknown;\n}\n\n/**\n * Interface for hierarchical data items\n */\nexport interface AddSelectItem {\n /** Unique identifier for the item */\n id: string;\n /** Display title for the item */\n title?: string;\n /** Value associated with the item */\n value?: string;\n /** Subtitle or secondary text */\n subtitle?: string;\n /** Whether the item is currently selected */\n selected?: boolean;\n /** Selection status (checked, unchecked, or indeterminate for parent nodes) */\n status?: ItemStatus;\n /** Whether the item is disabled and cannot be selected */\n disabled?: boolean;\n /** Icon or visual element to display with the item */\n icon?: ReactNode;\n /** Nested children items */\n children?: {\n entries: AddSelectItem[];\n };\n /** Additional metadata and details about the item */\n itemDetails?: ItemDetails;\n [key: string]: unknown; // Allow additional properties\n}\n\n/**\n * Options for search functionality\n */\nexport interface SearchOptions {\n caseSensitive?: boolean;\n searchFields?: string[]; // Fields to search in (default: ['title', 'value'])\n maxResults?: number; // Maximum number of results to return\n}\n\n/**\n * AddSelectData - A lightweight, framework-agnostic utility for managing hierarchical data\n *\n * This utility provides standard APIs for common operations such as setting, selecting,\n * traversing, searching, and sorting hierarchical data structures. It encapsulates data\n * logic separate from UI, allowing both React and Web Components to reuse the same\n * data management functions.\n */\nexport class AddSelectData {\n private items: AddSelectItem[] = [];\n private itemMap: Map<string, AddSelectItem> = new Map();\n private parentMap: Map<string, string> = new Map(); // child id -> parent id\n private selectedIds: Set<string> = new Set(); // Track selected IDs for O(1) lookup\n private depthCache: Map<string, number> = new Map(); // Cache item depths\n private selectedItemsCache: AddSelectItem[] | null = null; // Memoized selected items\n\n /**\n * Initialize or replace the hierarchical data\n * @param items - Array of hierarchical items\n */\n setItems(items: AddSelectItem[]): void {\n this.items = items;\n this._invalidateCaches();\n this._buildMaps(items);\n }\n\n /**\n * Get the full list of items\n * @returns Array of all items\n */\n getItems(): AddSelectItem[] {\n return this.items;\n }\n\n /**\n * Retrieve a single item by its id\n * @param id - The item id\n * @returns The item or undefined if not found\n */\n getItem(id: string): AddSelectItem | undefined {\n return this.itemMap.get(id);\n }\n\n /**\n * Update a given item with new properties\n * @param id - The item id\n * @param newProperties - Properties to update\n * @returns true if item was found and updated, false otherwise\n */\n setItem(id: string, newProperties: Partial<AddSelectItem>): boolean {\n const item = this.itemMap.get(id);\n if (!item) {\n return false;\n }\n\n Object.assign(item, newProperties);\n\n // Invalidate cache if selection-related properties changed\n if ('selected' in newProperties || 'status' in newProperties) {\n this._invalidateSelectionCache();\n }\n\n return true;\n }\n\n /**\n * Returns an array of items marked as selected (memoized)\n * @returns Array of selected items\n */\n getSelectedItems(): AddSelectItem[] {\n // Return cached result if available\n if (this.selectedItemsCache !== null) {\n return this.selectedItemsCache;\n }\n\n // Build and cache the result\n const selected: AddSelectItem[] = [];\n this.selectedIds.forEach((id) => {\n const item = this.itemMap.get(id);\n if (item) {\n selected.push(item);\n }\n });\n\n this.selectedItemsCache = selected;\n return selected;\n }\n\n /**\n * Mark one or more items (by id) as selected\n * @param ids - Single id or array of ids to select\n * @param exclusive - If true, deselect all other items (default: false)\n */\n setSelectedItems(ids: string | string[], exclusive: boolean = false): void {\n const idArray = Array.isArray(ids) ? ids : [ids];\n\n if (exclusive) {\n // Efficiently clear all selections using the Set\n this.selectedIds.forEach((id) => {\n const item = this.itemMap.get(id);\n if (item) {\n item.selected = false;\n item.status = 'unchecked';\n }\n });\n this.selectedIds.clear();\n }\n\n // Select specified items\n idArray.forEach((id) => {\n const item = this.itemMap.get(id);\n if (item) {\n item.selected = true;\n item.status = 'checked';\n this.selectedIds.add(id);\n }\n });\n\n this._invalidateSelectionCache();\n }\n\n /**\n * Get direct children of a node\n * @param id - The parent item id\n * @returns Array of child items or empty array if no children\n */\n getItemChildren(id: string): AddSelectItem[] {\n const item = this.itemMap.get(id);\n if (!item) {\n return [];\n }\n return item.children?.entries ?? [];\n }\n\n /**\n * Get the parent of a node\n * @param id - The child item id\n * @returns The parent item or undefined if no parent (root level)\n */\n getItemParent(id: string): AddSelectItem | undefined {\n const parentId = this.parentMap.get(id);\n return parentId ? this.itemMap.get(parentId) : undefined;\n }\n\n /**\n * Get all ancestors (parents up to the root) of a node\n * @param id - The item id\n * @returns Array of ancestor items from immediate parent to root\n */\n getItemParents(id: string): AddSelectItem[] {\n const parents: AddSelectItem[] = [];\n let currentId: string | undefined = id;\n\n while (currentId) {\n const parentId = this.parentMap.get(currentId);\n if (!parentId) {\n break;\n }\n\n const parent = this.itemMap.get(parentId);\n if (parent) {\n parents.push(parent);\n }\n currentId = parentId;\n }\n\n return parents;\n }\n\n /**\n * Retrieve the selected state status of an item\n * @param id - The item id\n * @returns The status or undefined if item not found\n */\n getItemStatus(id: string): ItemStatus | undefined {\n return this.itemMap.get(id)?.status;\n }\n\n /**\n * Set or update the status of an item\n * @param id - The item id\n * @param status - The new status\n * @returns true if item was found and updated, false otherwise\n */\n setItemStatus(id: string, status: ItemStatus): boolean {\n const item = this.itemMap.get(id);\n if (!item) {\n return false;\n }\n\n const wasSelected = item.selected;\n item.status = status;\n item.selected = status === 'checked';\n\n // Update selectedIds Set\n if (item.selected) {\n this.selectedIds.add(id);\n } else {\n this.selectedIds.delete(id);\n }\n\n // Invalidate cache if selection changed\n if (wasSelected !== item.selected) {\n this._invalidateSelectionCache();\n }\n\n return true;\n }\n\n /**\n * Check whether an item is selected (O(1) lookup)\n * @param id - The item id\n * @returns true if selected, false otherwise\n */\n isSelected(id: string): boolean {\n return this.selectedIds.has(id);\n }\n\n /**\n * Search items based on a query and return matching items\n * @param query - The search query string\n * @param options - Search options\n * @returns Array of matching items\n */\n search(query: string, options: SearchOptions = {}): AddSelectItem[] {\n // Early return for empty query\n if (!query) {\n return [];\n }\n\n const {\n caseSensitive = false,\n searchFields = ['title', 'value'],\n maxResults,\n } = options;\n\n const searchTerm = caseSensitive ? query : query.toLowerCase();\n const results: AddSelectItem[] = [];\n\n // Use early termination if maxResults is specified\n const shouldContinue = (): boolean => {\n return !maxResults || results.length < maxResults;\n };\n\n this._traverseItems(this.items, (item) => {\n if (!shouldContinue()) {\n return;\n }\n\n for (const field of searchFields) {\n const fieldValue = item[field];\n if (fieldValue) {\n const valueToSearch = caseSensitive\n ? String(fieldValue)\n : String(fieldValue).toLowerCase();\n\n if (valueToSearch.includes(searchTerm)) {\n results.push(item);\n break; // Don't add the same item multiple times\n }\n }\n }\n });\n\n return results;\n }\n\n /**\n * Sort items based on a comparator function\n * @param compareFn - Comparison function for sorting\n * @param recursive - If true, sort children recursively (default: false)\n */\n sort(\n compareFn: (a: AddSelectItem, b: AddSelectItem) => number,\n recursive: boolean = false\n ): void {\n // Sort recursively first if needed\n if (recursive) {\n this._sortRecursive(this.items, compareFn);\n }\n\n // Then sort the top level\n this.items.sort(compareFn);\n\n // Rebuild maps and caches after sorting\n this._invalidateCaches();\n this._buildMaps(this.items);\n }\n\n /**\n * Clear all selections (optimized with Set)\n */\n clearSelections(): void {\n // Efficiently clear using the selectedIds Set\n this.selectedIds.forEach((id) => {\n const item = this.itemMap.get(id);\n if (item) {\n item.selected = false;\n item.status = 'unchecked';\n }\n });\n this.selectedIds.clear();\n this._invalidateSelectionCache();\n }\n\n /**\n * Get the depth/level of an item in the hierarchy (cached)\n * @param id - The item id\n * @returns The depth (0 for root level items) or -1 if not found\n */\n getItemDepth(id: string): number {\n // Check cache first\n const cachedDepth = this.depthCache.get(id);\n if (cachedDepth !== undefined) {\n return cachedDepth;\n }\n\n // Item doesn't exist\n if (!this.itemMap.has(id)) {\n return -1;\n }\n\n // Calculate and cache depth\n let depth = 0;\n let currentId: string | undefined = id;\n\n while (currentId) {\n const parentId = this.parentMap.get(currentId);\n if (!parentId) {\n break;\n }\n depth++;\n currentId = parentId;\n }\n\n this.depthCache.set(id, depth);\n return depth;\n }\n\n /**\n * Check if an item has children\n * @param id - The item id\n * @returns true if item has children, false otherwise\n */\n hasChildren(id: string): boolean {\n const item = this.itemMap.get(id);\n return !!item?.children?.entries?.length;\n }\n\n /**\n * Get all descendant items of a node\n * @param id - The parent item id\n * @returns Array of all descendant items\n */\n getItemDescendants(id: string): AddSelectItem[] {\n const item = this.itemMap.get(id);\n if (!item?.children?.entries) {\n return [];\n }\n\n const descendants: AddSelectItem[] = [];\n this._traverseItems(item.children.entries, (child) => {\n descendants.push(child);\n });\n\n return descendants;\n }\n\n /**\n * Check if an item has any selected descendants (optimized)\n * @param id - The item id\n * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)\n * @returns true if any descendant is selected, false otherwise\n */\n hasSelectedDescendants(\n id: string,\n selectedIds: Set<string> = this.selectedIds\n ): boolean {\n const children = this.getItemChildren(id);\n if (!children.length) {\n return false;\n }\n\n // Check if any child or their descendants are selected\n for (const child of children) {\n if (\n selectedIds.has(child.id) ||\n this.hasSelectedDescendants(child.id, selectedIds)\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Check if all descendants of an item are selected (optimized)\n * @param id - The item id\n * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)\n * @returns true if all descendants are selected, false otherwise\n */\n allDescendantsSelected(\n id: string,\n selectedIds: Set<string> = this.selectedIds\n ): boolean {\n const item = this.itemMap.get(id);\n if (!item) {\n return false;\n }\n\n const children = this.getItemChildren(id);\n if (!children.length) {\n return selectedIds.has(item.id);\n }\n\n // All children must be selected and all their descendants must be selected\n for (const child of children) {\n if (\n !selectedIds.has(child.id) ||\n !this.allDescendantsSelected(child.id, selectedIds)\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Get all descendant IDs from an item (including the item itself)\n * @param id - The item id\n * @returns Array of all descendant IDs including the item itself\n */\n getAllDescendantIds(id: string): string[] {\n const item = this.itemMap.get(id);\n if (!item) {\n return [];\n }\n\n const ids: string[] = [id];\n const children = this.getItemChildren(id);\n\n for (const child of children) {\n ids.push(...this.getAllDescendantIds(child.id));\n }\n\n return ids;\n }\n\n /**\n * Get only top-level selected items (items without selected ancestors)\n * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)\n * @returns Array of top-level selected items\n */\n getTopLevelSelectedItems(\n selectedIds: Set<string> = this.selectedIds\n ): AddSelectItem[] {\n const topLevelItems: AddSelectItem[] = [];\n const processedIds = new Set<string>();\n\n // Helper to check if any ancestor is selected\n const hasSelectedAncestor = (itemId: string): boolean => {\n const parents = this.getItemParents(itemId);\n return parents.some((parent) => selectedIds.has(parent.id));\n };\n\n // Collect all selected items that don't have a selected ancestor\n selectedIds.forEach((id) => {\n if (!processedIds.has(id) && !hasSelectedAncestor(id)) {\n const item = this.itemMap.get(id);\n if (item) {\n topLevelItems.push(item);\n // Mark all descendants as processed\n const descendantIds = this.getAllDescendantIds(id);\n descendantIds.forEach((descId) => processedIds.add(descId));\n }\n }\n });\n\n return topLevelItems;\n }\n\n /**\n * Invalidate all caches\n * @private\n */\n private _invalidateCaches(): void {\n this.selectedItemsCache = null;\n this.depthCache.clear();\n }\n\n /**\n * Invalidate selection cache only\n * @private\n */\n private _invalidateSelectionCache(): void {\n this.selectedItemsCache = null;\n }\n\n /**\n * Build internal maps for efficient lookups (optimized with depth caching)\n * @private\n */\n private _buildMaps(\n items: AddSelectItem[],\n parentId?: string,\n depth: number = 0\n ): void {\n if (!parentId) {\n // Clear maps when building from root\n this.itemMap.clear();\n this.parentMap.clear();\n this.selectedIds.clear();\n this.depthCache.clear();\n }\n\n items.forEach((item) => {\n this.itemMap.set(item.id, item);\n this.depthCache.set(item.id, depth);\n\n if (parentId) {\n this.parentMap.set(item.id, parentId);\n }\n\n // Track selected items\n if (item.selected) {\n this.selectedIds.add(item.id);\n }\n\n if (item.children?.entries) {\n this._buildMaps(item.children.entries, item.id, depth + 1);\n }\n });\n }\n\n /**\n * Traverse all items and apply a callback function\n * @private\n */\n private _traverseItems(\n items: AddSelectItem[],\n callback: (item: AddSelectItem) => void\n ): void {\n for (const item of items) {\n callback(item);\n if (item.children?.entries) {\n this._traverseItems(item.children.entries, callback);\n }\n }\n }\n\n /**\n * Sort items recursively\n * @private\n */\n private _sortRecursive(\n items: AddSelectItem[],\n compareFn: (a: AddSelectItem, b: AddSelectItem) => number\n ): void {\n for (const item of items) {\n if (item.children?.entries) {\n item.children.entries.sort(compareFn);\n this._sortRecursive(item.children.entries, compareFn);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmEA,IAAa,gBAAb,MAA2B;;eACQ,EAAE;iCACW,IAAI,KAAK;mCACd,IAAI,KAAK;qCACf,IAAI,KAAK;oCACF,IAAI,KAAK;4BACE;;;;;;CAMrD,SAAS,OAA8B;AACrC,OAAK,QAAQ;AACb,OAAK,mBAAmB;AACxB,OAAK,WAAW,MAAM;;;;;;CAOxB,WAA4B;AAC1B,SAAO,KAAK;;;;;;;CAQd,QAAQ,IAAuC;AAC7C,SAAO,KAAK,QAAQ,IAAI,GAAG;;;;;;;;CAS7B,QAAQ,IAAY,eAAgD;EAClE,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,MAAI,CAAC,KACH,QAAO;AAGT,SAAO,OAAO,MAAM,cAAc;AAGlC,MAAI,cAAc,iBAAiB,YAAY,cAC7C,MAAK,2BAA2B;AAGlC,SAAO;;;;;;CAOT,mBAAoC;AAElC,MAAI,KAAK,uBAAuB,KAC9B,QAAO,KAAK;EAId,MAAM,WAA4B,EAAE;AACpC,OAAK,YAAY,SAAS,OAAO;GAC/B,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,OAAI,KACF,UAAS,KAAK,KAAK;IAErB;AAEF,OAAK,qBAAqB;AAC1B,SAAO;;;;;;;CAQT,iBAAiB,KAAwB,YAAqB,OAAa;EACzE,MAAM,UAAU,MAAM,QAAQ,IAAI,GAAG,MAAM,CAAC,IAAI;AAEhD,MAAI,WAAW;AAEb,QAAK,YAAY,SAAS,OAAO;IAC/B,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,QAAI,MAAM;AACR,UAAK,WAAW;AAChB,UAAK,SAAS;;KAEhB;AACF,QAAK,YAAY,OAAO;;AAI1B,UAAQ,SAAS,OAAO;GACtB,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,OAAI,MAAM;AACR,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,YAAY,IAAI,GAAG;;IAE1B;AAEF,OAAK,2BAA2B;;;;;;;CAQlC,gBAAgB,IAA6B;EAC3C,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,MAAI,CAAC,KACH,QAAO,EAAE;AAEX,SAAO,KAAK,UAAU,WAAW,EAAE;;;;;;;CAQrC,cAAc,IAAuC;EACnD,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;AACvC,SAAO,WAAW,KAAK,QAAQ,IAAI,SAAS,GAAG,KAAA;;;;;;;CAQjD,eAAe,IAA6B;EAC1C,MAAM,UAA2B,EAAE;EACnC,IAAI,YAAgC;AAEpC,SAAO,WAAW;GAChB,MAAM,WAAW,KAAK,UAAU,IAAI,UAAU;AAC9C,OAAI,CAAC,SACH;GAGF,MAAM,SAAS,KAAK,QAAQ,IAAI,SAAS;AACzC,OAAI,OACF,SAAQ,KAAK,OAAO;AAEtB,eAAY;;AAGd,SAAO;;;;;;;CAQT,cAAc,IAAoC;AAChD,SAAO,KAAK,QAAQ,IAAI,GAAG,EAAE;;;;;;;;CAS/B,cAAc,IAAY,QAA6B;EACrD,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,MAAI,CAAC,KACH,QAAO;EAGT,MAAM,cAAc,KAAK;AACzB,OAAK,SAAS;AACd,OAAK,WAAW,WAAW;AAG3B,MAAI,KAAK,SACP,MAAK,YAAY,IAAI,GAAG;MAExB,MAAK,YAAY,OAAO,GAAG;AAI7B,MAAI,gBAAgB,KAAK,SACvB,MAAK,2BAA2B;AAGlC,SAAO;;;;;;;CAQT,WAAW,IAAqB;AAC9B,SAAO,KAAK,YAAY,IAAI,GAAG;;;;;;;;CASjC,OAAO,OAAe,UAAyB,EAAE,EAAmB;AAElE,MAAI,CAAC,MACH,QAAO,EAAE;EAGX,MAAM,EACJ,gBAAgB,OAChB,eAAe,CAAC,SAAS,QAAQ,EACjC,eACE;EAEJ,MAAM,aAAa,gBAAgB,QAAQ,MAAM,aAAa;EAC9D,MAAM,UAA2B,EAAE;EAGnC,MAAM,uBAAgC;AACpC,UAAO,CAAC,cAAc,QAAQ,SAAS;;AAGzC,OAAK,eAAe,KAAK,QAAQ,SAAS;AACxC,OAAI,CAAC,gBAAgB,CACnB;AAGF,QAAK,MAAM,SAAS,cAAc;IAChC,MAAM,aAAa,KAAK;AACxB,QAAI;UACoB,gBAClB,OAAO,WAAW,GAClB,OAAO,WAAW,CAAC,aAAa,EAElB,SAAS,WAAW,EAAE;AACtC,cAAQ,KAAK,KAAK;AAClB;;;;IAIN;AAEF,SAAO;;;;;;;CAQT,KACE,WACA,YAAqB,OACf;AAEN,MAAI,UACF,MAAK,eAAe,KAAK,OAAO,UAAU;AAI5C,OAAK,MAAM,KAAK,UAAU;AAG1B,OAAK,mBAAmB;AACxB,OAAK,WAAW,KAAK,MAAM;;;;;CAM7B,kBAAwB;AAEtB,OAAK,YAAY,SAAS,OAAO;GAC/B,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,OAAI,MAAM;AACR,SAAK,WAAW;AAChB,SAAK,SAAS;;IAEhB;AACF,OAAK,YAAY,OAAO;AACxB,OAAK,2BAA2B;;;;;;;CAQlC,aAAa,IAAoB;EAE/B,MAAM,cAAc,KAAK,WAAW,IAAI,GAAG;AAC3C,MAAI,gBAAgB,KAAA,EAClB,QAAO;AAIT,MAAI,CAAC,KAAK,QAAQ,IAAI,GAAG,CACvB,QAAO;EAIT,IAAI,QAAQ;EACZ,IAAI,YAAgC;AAEpC,SAAO,WAAW;GAChB,MAAM,WAAW,KAAK,UAAU,IAAI,UAAU;AAC9C,OAAI,CAAC,SACH;AAEF;AACA,eAAY;;AAGd,OAAK,WAAW,IAAI,IAAI,MAAM;AAC9B,SAAO;;;;;;;CAQT,YAAY,IAAqB;AAE/B,SAAO,CAAC,CADK,KAAK,QAAQ,IAAI,GACjB,EAAE,UAAU,SAAS;;;;;;;CAQpC,mBAAmB,IAA6B;EAC9C,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,MAAI,CAAC,MAAM,UAAU,QACnB,QAAO,EAAE;EAGX,MAAM,cAA+B,EAAE;AACvC,OAAK,eAAe,KAAK,SAAS,UAAU,UAAU;AACpD,eAAY,KAAK,MAAM;IACvB;AAEF,SAAO;;;;;;;;CAST,uBACE,IACA,cAA2B,KAAK,aACvB;EACT,MAAM,WAAW,KAAK,gBAAgB,GAAG;AACzC,MAAI,CAAC,SAAS,OACZ,QAAO;AAIT,OAAK,MAAM,SAAS,SAClB,KACE,YAAY,IAAI,MAAM,GAAG,IACzB,KAAK,uBAAuB,MAAM,IAAI,YAAY,CAElD,QAAO;AAIX,SAAO;;;;;;;;CAST,uBACE,IACA,cAA2B,KAAK,aACvB;EACT,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,MAAI,CAAC,KACH,QAAO;EAGT,MAAM,WAAW,KAAK,gBAAgB,GAAG;AACzC,MAAI,CAAC,SAAS,OACZ,QAAO,YAAY,IAAI,KAAK,GAAG;AAIjC,OAAK,MAAM,SAAS,SAClB,KACE,CAAC,YAAY,IAAI,MAAM,GAAG,IAC1B,CAAC,KAAK,uBAAuB,MAAM,IAAI,YAAY,CAEnD,QAAO;AAIX,SAAO;;;;;;;CAQT,oBAAoB,IAAsB;AAExC,MAAI,CADS,KAAK,QAAQ,IAAI,GACrB,CACP,QAAO,EAAE;EAGX,MAAM,MAAgB,CAAC,GAAG;EAC1B,MAAM,WAAW,KAAK,gBAAgB,GAAG;AAEzC,OAAK,MAAM,SAAS,SAClB,KAAI,KAAK,GAAG,KAAK,oBAAoB,MAAM,GAAG,CAAC;AAGjD,SAAO;;;;;;;CAQT,yBACE,cAA2B,KAAK,aACf;EACjB,MAAM,gBAAiC,EAAE;EACzC,MAAM,+BAAe,IAAI,KAAa;EAGtC,MAAM,uBAAuB,WAA4B;AAEvD,UADgB,KAAK,eAAe,OACtB,CAAC,MAAM,WAAW,YAAY,IAAI,OAAO,GAAG,CAAC;;AAI7D,cAAY,SAAS,OAAO;AAC1B,OAAI,CAAC,aAAa,IAAI,GAAG,IAAI,CAAC,oBAAoB,GAAG,EAAE;IACrD,MAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,QAAI,MAAM;AACR,mBAAc,KAAK,KAAK;AAEF,UAAK,oBAAoB,GAClC,CAAC,SAAS,WAAW,aAAa,IAAI,OAAO,CAAC;;;IAG/D;AAEF,SAAO;;;;;;CAOT,oBAAkC;AAChC,OAAK,qBAAqB;AAC1B,OAAK,WAAW,OAAO;;;;;;CAOzB,4BAA0C;AACxC,OAAK,qBAAqB;;;;;;CAO5B,WACE,OACA,UACA,QAAgB,GACV;AACN,MAAI,CAAC,UAAU;AAEb,QAAK,QAAQ,OAAO;AACpB,QAAK,UAAU,OAAO;AACtB,QAAK,YAAY,OAAO;AACxB,QAAK,WAAW,OAAO;;AAGzB,QAAM,SAAS,SAAS;AACtB,QAAK,QAAQ,IAAI,KAAK,IAAI,KAAK;AAC/B,QAAK,WAAW,IAAI,KAAK,IAAI,MAAM;AAEnC,OAAI,SACF,MAAK,UAAU,IAAI,KAAK,IAAI,SAAS;AAIvC,OAAI,KAAK,SACP,MAAK,YAAY,IAAI,KAAK,GAAG;AAG/B,OAAI,KAAK,UAAU,QACjB,MAAK,WAAW,KAAK,SAAS,SAAS,KAAK,IAAI,QAAQ,EAAE;IAE5D;;;;;;CAOJ,eACE,OACA,UACM;AACN,OAAK,MAAM,QAAQ,OAAO;AACxB,YAAS,KAAK;AACd,OAAI,KAAK,UAAU,QACjB,MAAK,eAAe,KAAK,SAAS,SAAS,SAAS;;;;;;;CAS1D,eACE,OACA,WACM;AACN,OAAK,MAAM,QAAQ,MACjB,KAAI,KAAK,UAAU,SAAS;AAC1B,QAAK,SAAS,QAAQ,KAAK,UAAU;AACrC,QAAK,eAAe,KAAK,SAAS,SAAS,UAAU"}
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  //#region package.json
9
- var version = "0.41.0-rc.1";
9
+ var version = "0.41.0";
10
10
  //#endregion
11
11
  export { version };
12
12
 
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":[""],"mappings":""}
package/es/index.js CHANGED
@@ -36,5 +36,5 @@ import coachmark_tagline_default from "./components/coachmark/coachmark-tagline/
36
36
  import big_number_skeleton_default from "./components/big-number/big-number-skeleton.js";
37
37
  import big_number_default from "./components/big-number/big-number.js";
38
38
  import edit_in_place_default from "./components/edit-in-place/edit-in-place.js";
39
- import { AddSelectData } from "@carbon/ibm-products-utilities";
39
+ import { AddSelectData } from "./ibm-products-utilities/src/utils/add-select/add-select-data.js";
40
40
  export { AddSelectData, about_modal_default as CDSAboutModal, action_set_default as CDSActionSet, big_number_default as CDSBigNumber, big_number_skeleton_default as CDSBigNumberSkeleton, coachmark_default as CDSCoachmark, coachmark_beacon_default as CDSCoachmarkBeacon, coachmark_tagline_default as CDSCoachmarkTagline, edit_in_place_default as CDSEditInPlace, full_page_error_default as CDSFullPageError, guide_banner_default as CDSGuideBanner, guide_banner_element_default as CDSGuideBannerElement, options_tile_default as CDSOptionsTile, page_header_default as CDSPageHeader, page_header_breadcrumb_default as CDSPageHeaderBreadcrumb, page_header_content_default as CDSPageHeaderContent, page_header_content_text_default as CDSPageHeaderContentText, page_header_hero_image_default as CDSPageHeaderHeroImage, page_header_tabs_default as CDSPageHeaderTabs, side_panel_default as CDSSidePanel, tearsheet_default as CDSTearsheet, tearsheet_body_default as CDSTearsheetBody, tearsheet_footer_default as CDSTearsheetFooter, tearsheet_header_default as CDSTearsheetHeader, tearsheet_header_content_default as CDSTearsheetHeaderContent, tearsheet_influencer_default as CDSTearsheetInfluencer, tearsheet_navigation_bar_default as CDSTearsheetNavigationBar, tearsheet_default$1 as CDSTearsheetPreview, tearsheet_scroller_default as CDSTearsheetScroller, tearsheet_summary_content_default as CDSTearsheetSummaryContent, truncated_text_default as CDSTruncatedText, user_avatar_default as CDSUserAvatar };
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import { version } from "../../package.js";
8
+ import { version } from "../../ibm-products-web-components/package.js";
9
9
  //#region src/globals/internal/storybook-cdn.ts
10
10
  /**
11
11
  * @license
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Copyright IBM Corp. 2020, 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ //#region ../ibm-products-utilities/src/utils/add-select/add-select-data.ts
9
+ /**
10
+ * AddSelectData - A lightweight, framework-agnostic utility for managing hierarchical data
11
+ *
12
+ * This utility provides standard APIs for common operations such as setting, selecting,
13
+ * traversing, searching, and sorting hierarchical data structures. It encapsulates data
14
+ * logic separate from UI, allowing both React and Web Components to reuse the same
15
+ * data management functions.
16
+ */
17
+ var AddSelectData = class {
18
+ constructor() {
19
+ this.items = [];
20
+ this.itemMap = /* @__PURE__ */ new Map();
21
+ this.parentMap = /* @__PURE__ */ new Map();
22
+ this.selectedIds = /* @__PURE__ */ new Set();
23
+ this.depthCache = /* @__PURE__ */ new Map();
24
+ this.selectedItemsCache = null;
25
+ }
26
+ /**
27
+ * Initialize or replace the hierarchical data
28
+ * @param items - Array of hierarchical items
29
+ */
30
+ setItems(items) {
31
+ this.items = items;
32
+ this._invalidateCaches();
33
+ this._buildMaps(items);
34
+ }
35
+ /**
36
+ * Get the full list of items
37
+ * @returns Array of all items
38
+ */
39
+ getItems() {
40
+ return this.items;
41
+ }
42
+ /**
43
+ * Retrieve a single item by its id
44
+ * @param id - The item id
45
+ * @returns The item or undefined if not found
46
+ */
47
+ getItem(id) {
48
+ return this.itemMap.get(id);
49
+ }
50
+ /**
51
+ * Update a given item with new properties
52
+ * @param id - The item id
53
+ * @param newProperties - Properties to update
54
+ * @returns true if item was found and updated, false otherwise
55
+ */
56
+ setItem(id, newProperties) {
57
+ const item = this.itemMap.get(id);
58
+ if (!item) return false;
59
+ Object.assign(item, newProperties);
60
+ if ("selected" in newProperties || "status" in newProperties) this._invalidateSelectionCache();
61
+ return true;
62
+ }
63
+ /**
64
+ * Returns an array of items marked as selected (memoized)
65
+ * @returns Array of selected items
66
+ */
67
+ getSelectedItems() {
68
+ if (this.selectedItemsCache !== null) return this.selectedItemsCache;
69
+ const selected = [];
70
+ this.selectedIds.forEach((id) => {
71
+ const item = this.itemMap.get(id);
72
+ if (item) selected.push(item);
73
+ });
74
+ this.selectedItemsCache = selected;
75
+ return selected;
76
+ }
77
+ /**
78
+ * Mark one or more items (by id) as selected
79
+ * @param ids - Single id or array of ids to select
80
+ * @param exclusive - If true, deselect all other items (default: false)
81
+ */
82
+ setSelectedItems(ids, exclusive = false) {
83
+ const idArray = Array.isArray(ids) ? ids : [ids];
84
+ if (exclusive) {
85
+ this.selectedIds.forEach((id) => {
86
+ const item = this.itemMap.get(id);
87
+ if (item) {
88
+ item.selected = false;
89
+ item.status = "unchecked";
90
+ }
91
+ });
92
+ this.selectedIds.clear();
93
+ }
94
+ idArray.forEach((id) => {
95
+ const item = this.itemMap.get(id);
96
+ if (item) {
97
+ item.selected = true;
98
+ item.status = "checked";
99
+ this.selectedIds.add(id);
100
+ }
101
+ });
102
+ this._invalidateSelectionCache();
103
+ }
104
+ /**
105
+ * Get direct children of a node
106
+ * @param id - The parent item id
107
+ * @returns Array of child items or empty array if no children
108
+ */
109
+ getItemChildren(id) {
110
+ const item = this.itemMap.get(id);
111
+ if (!item) return [];
112
+ return item.children?.entries ?? [];
113
+ }
114
+ /**
115
+ * Get the parent of a node
116
+ * @param id - The child item id
117
+ * @returns The parent item or undefined if no parent (root level)
118
+ */
119
+ getItemParent(id) {
120
+ const parentId = this.parentMap.get(id);
121
+ return parentId ? this.itemMap.get(parentId) : void 0;
122
+ }
123
+ /**
124
+ * Get all ancestors (parents up to the root) of a node
125
+ * @param id - The item id
126
+ * @returns Array of ancestor items from immediate parent to root
127
+ */
128
+ getItemParents(id) {
129
+ const parents = [];
130
+ let currentId = id;
131
+ while (currentId) {
132
+ const parentId = this.parentMap.get(currentId);
133
+ if (!parentId) break;
134
+ const parent = this.itemMap.get(parentId);
135
+ if (parent) parents.push(parent);
136
+ currentId = parentId;
137
+ }
138
+ return parents;
139
+ }
140
+ /**
141
+ * Retrieve the selected state status of an item
142
+ * @param id - The item id
143
+ * @returns The status or undefined if item not found
144
+ */
145
+ getItemStatus(id) {
146
+ return this.itemMap.get(id)?.status;
147
+ }
148
+ /**
149
+ * Set or update the status of an item
150
+ * @param id - The item id
151
+ * @param status - The new status
152
+ * @returns true if item was found and updated, false otherwise
153
+ */
154
+ setItemStatus(id, status) {
155
+ const item = this.itemMap.get(id);
156
+ if (!item) return false;
157
+ const wasSelected = item.selected;
158
+ item.status = status;
159
+ item.selected = status === "checked";
160
+ if (item.selected) this.selectedIds.add(id);
161
+ else this.selectedIds.delete(id);
162
+ if (wasSelected !== item.selected) this._invalidateSelectionCache();
163
+ return true;
164
+ }
165
+ /**
166
+ * Check whether an item is selected (O(1) lookup)
167
+ * @param id - The item id
168
+ * @returns true if selected, false otherwise
169
+ */
170
+ isSelected(id) {
171
+ return this.selectedIds.has(id);
172
+ }
173
+ /**
174
+ * Search items based on a query and return matching items
175
+ * @param query - The search query string
176
+ * @param options - Search options
177
+ * @returns Array of matching items
178
+ */
179
+ search(query, options = {}) {
180
+ if (!query) return [];
181
+ const { caseSensitive = false, searchFields = ["title", "value"], maxResults } = options;
182
+ const searchTerm = caseSensitive ? query : query.toLowerCase();
183
+ const results = [];
184
+ const shouldContinue = () => {
185
+ return !maxResults || results.length < maxResults;
186
+ };
187
+ this._traverseItems(this.items, (item) => {
188
+ if (!shouldContinue()) return;
189
+ for (const field of searchFields) {
190
+ const fieldValue = item[field];
191
+ if (fieldValue) {
192
+ if ((caseSensitive ? String(fieldValue) : String(fieldValue).toLowerCase()).includes(searchTerm)) {
193
+ results.push(item);
194
+ break;
195
+ }
196
+ }
197
+ }
198
+ });
199
+ return results;
200
+ }
201
+ /**
202
+ * Sort items based on a comparator function
203
+ * @param compareFn - Comparison function for sorting
204
+ * @param recursive - If true, sort children recursively (default: false)
205
+ */
206
+ sort(compareFn, recursive = false) {
207
+ if (recursive) this._sortRecursive(this.items, compareFn);
208
+ this.items.sort(compareFn);
209
+ this._invalidateCaches();
210
+ this._buildMaps(this.items);
211
+ }
212
+ /**
213
+ * Clear all selections (optimized with Set)
214
+ */
215
+ clearSelections() {
216
+ this.selectedIds.forEach((id) => {
217
+ const item = this.itemMap.get(id);
218
+ if (item) {
219
+ item.selected = false;
220
+ item.status = "unchecked";
221
+ }
222
+ });
223
+ this.selectedIds.clear();
224
+ this._invalidateSelectionCache();
225
+ }
226
+ /**
227
+ * Get the depth/level of an item in the hierarchy (cached)
228
+ * @param id - The item id
229
+ * @returns The depth (0 for root level items) or -1 if not found
230
+ */
231
+ getItemDepth(id) {
232
+ const cachedDepth = this.depthCache.get(id);
233
+ if (cachedDepth !== void 0) return cachedDepth;
234
+ if (!this.itemMap.has(id)) return -1;
235
+ let depth = 0;
236
+ let currentId = id;
237
+ while (currentId) {
238
+ const parentId = this.parentMap.get(currentId);
239
+ if (!parentId) break;
240
+ depth++;
241
+ currentId = parentId;
242
+ }
243
+ this.depthCache.set(id, depth);
244
+ return depth;
245
+ }
246
+ /**
247
+ * Check if an item has children
248
+ * @param id - The item id
249
+ * @returns true if item has children, false otherwise
250
+ */
251
+ hasChildren(id) {
252
+ return !!this.itemMap.get(id)?.children?.entries?.length;
253
+ }
254
+ /**
255
+ * Get all descendant items of a node
256
+ * @param id - The parent item id
257
+ * @returns Array of all descendant items
258
+ */
259
+ getItemDescendants(id) {
260
+ const item = this.itemMap.get(id);
261
+ if (!item?.children?.entries) return [];
262
+ const descendants = [];
263
+ this._traverseItems(item.children.entries, (child) => {
264
+ descendants.push(child);
265
+ });
266
+ return descendants;
267
+ }
268
+ /**
269
+ * Check if an item has any selected descendants (optimized)
270
+ * @param id - The item id
271
+ * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)
272
+ * @returns true if any descendant is selected, false otherwise
273
+ */
274
+ hasSelectedDescendants(id, selectedIds = this.selectedIds) {
275
+ const children = this.getItemChildren(id);
276
+ if (!children.length) return false;
277
+ for (const child of children) if (selectedIds.has(child.id) || this.hasSelectedDescendants(child.id, selectedIds)) return true;
278
+ return false;
279
+ }
280
+ /**
281
+ * Check if all descendants of an item are selected (optimized)
282
+ * @param id - The item id
283
+ * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)
284
+ * @returns true if all descendants are selected, false otherwise
285
+ */
286
+ allDescendantsSelected(id, selectedIds = this.selectedIds) {
287
+ const item = this.itemMap.get(id);
288
+ if (!item) return false;
289
+ const children = this.getItemChildren(id);
290
+ if (!children.length) return selectedIds.has(item.id);
291
+ for (const child of children) if (!selectedIds.has(child.id) || !this.allDescendantsSelected(child.id, selectedIds)) return false;
292
+ return true;
293
+ }
294
+ /**
295
+ * Get all descendant IDs from an item (including the item itself)
296
+ * @param id - The item id
297
+ * @returns Array of all descendant IDs including the item itself
298
+ */
299
+ getAllDescendantIds(id) {
300
+ if (!this.itemMap.get(id)) return [];
301
+ const ids = [id];
302
+ const children = this.getItemChildren(id);
303
+ for (const child of children) ids.push(...this.getAllDescendantIds(child.id));
304
+ return ids;
305
+ }
306
+ /**
307
+ * Get only top-level selected items (items without selected ancestors)
308
+ * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)
309
+ * @returns Array of top-level selected items
310
+ */
311
+ getTopLevelSelectedItems(selectedIds = this.selectedIds) {
312
+ const topLevelItems = [];
313
+ const processedIds = /* @__PURE__ */ new Set();
314
+ const hasSelectedAncestor = (itemId) => {
315
+ return this.getItemParents(itemId).some((parent) => selectedIds.has(parent.id));
316
+ };
317
+ selectedIds.forEach((id) => {
318
+ if (!processedIds.has(id) && !hasSelectedAncestor(id)) {
319
+ const item = this.itemMap.get(id);
320
+ if (item) {
321
+ topLevelItems.push(item);
322
+ this.getAllDescendantIds(id).forEach((descId) => processedIds.add(descId));
323
+ }
324
+ }
325
+ });
326
+ return topLevelItems;
327
+ }
328
+ /**
329
+ * Invalidate all caches
330
+ * @private
331
+ */
332
+ _invalidateCaches() {
333
+ this.selectedItemsCache = null;
334
+ this.depthCache.clear();
335
+ }
336
+ /**
337
+ * Invalidate selection cache only
338
+ * @private
339
+ */
340
+ _invalidateSelectionCache() {
341
+ this.selectedItemsCache = null;
342
+ }
343
+ /**
344
+ * Build internal maps for efficient lookups (optimized with depth caching)
345
+ * @private
346
+ */
347
+ _buildMaps(items, parentId, depth = 0) {
348
+ if (!parentId) {
349
+ this.itemMap.clear();
350
+ this.parentMap.clear();
351
+ this.selectedIds.clear();
352
+ this.depthCache.clear();
353
+ }
354
+ items.forEach((item) => {
355
+ this.itemMap.set(item.id, item);
356
+ this.depthCache.set(item.id, depth);
357
+ if (parentId) this.parentMap.set(item.id, parentId);
358
+ if (item.selected) this.selectedIds.add(item.id);
359
+ if (item.children?.entries) this._buildMaps(item.children.entries, item.id, depth + 1);
360
+ });
361
+ }
362
+ /**
363
+ * Traverse all items and apply a callback function
364
+ * @private
365
+ */
366
+ _traverseItems(items, callback) {
367
+ for (const item of items) {
368
+ callback(item);
369
+ if (item.children?.entries) this._traverseItems(item.children.entries, callback);
370
+ }
371
+ }
372
+ /**
373
+ * Sort items recursively
374
+ * @private
375
+ */
376
+ _sortRecursive(items, compareFn) {
377
+ for (const item of items) if (item.children?.entries) {
378
+ item.children.entries.sort(compareFn);
379
+ this._sortRecursive(item.children.entries, compareFn);
380
+ }
381
+ }
382
+ };
383
+ //#endregion
384
+ export { AddSelectData };
385
+
386
+ //# sourceMappingURL=add-select-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-select-data.js","names":[],"sources":["../../../../../../ibm-products-utilities/src/utils/add-select/add-select-data.ts"],"sourcesContent":["/**\n * Copyright IBM Corp. 2026\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { ReactNode } from 'react';\n\n/**\n * Status types for items in the hierarchical data structure\n */\nexport type ItemStatus = 'checked' | 'unchecked' | 'indeterminate';\n\n/**\n * Interface for item details metadata\n */\nexport interface ItemDetails {\n [key: string]: unknown;\n}\n\n/**\n * Interface for hierarchical data items\n */\nexport interface AddSelectItem {\n /** Unique identifier for the item */\n id: string;\n /** Display title for the item */\n title?: string;\n /** Value associated with the item */\n value?: string;\n /** Subtitle or secondary text */\n subtitle?: string;\n /** Whether the item is currently selected */\n selected?: boolean;\n /** Selection status (checked, unchecked, or indeterminate for parent nodes) */\n status?: ItemStatus;\n /** Whether the item is disabled and cannot be selected */\n disabled?: boolean;\n /** Icon or visual element to display with the item */\n icon?: ReactNode;\n /** Nested children items */\n children?: {\n entries: AddSelectItem[];\n };\n /** Additional metadata and details about the item */\n itemDetails?: ItemDetails;\n [key: string]: unknown; // Allow additional properties\n}\n\n/**\n * Options for search functionality\n */\nexport interface SearchOptions {\n caseSensitive?: boolean;\n searchFields?: string[]; // Fields to search in (default: ['title', 'value'])\n maxResults?: number; // Maximum number of results to return\n}\n\n/**\n * AddSelectData - A lightweight, framework-agnostic utility for managing hierarchical data\n *\n * This utility provides standard APIs for common operations such as setting, selecting,\n * traversing, searching, and sorting hierarchical data structures. It encapsulates data\n * logic separate from UI, allowing both React and Web Components to reuse the same\n * data management functions.\n */\nexport class AddSelectData {\n private items: AddSelectItem[] = [];\n private itemMap: Map<string, AddSelectItem> = new Map();\n private parentMap: Map<string, string> = new Map(); // child id -> parent id\n private selectedIds: Set<string> = new Set(); // Track selected IDs for O(1) lookup\n private depthCache: Map<string, number> = new Map(); // Cache item depths\n private selectedItemsCache: AddSelectItem[] | null = null; // Memoized selected items\n\n /**\n * Initialize or replace the hierarchical data\n * @param items - Array of hierarchical items\n */\n setItems(items: AddSelectItem[]): void {\n this.items = items;\n this._invalidateCaches();\n this._buildMaps(items);\n }\n\n /**\n * Get the full list of items\n * @returns Array of all items\n */\n getItems(): AddSelectItem[] {\n return this.items;\n }\n\n /**\n * Retrieve a single item by its id\n * @param id - The item id\n * @returns The item or undefined if not found\n */\n getItem(id: string): AddSelectItem | undefined {\n return this.itemMap.get(id);\n }\n\n /**\n * Update a given item with new properties\n * @param id - The item id\n * @param newProperties - Properties to update\n * @returns true if item was found and updated, false otherwise\n */\n setItem(id: string, newProperties: Partial<AddSelectItem>): boolean {\n const item = this.itemMap.get(id);\n if (!item) {\n return false;\n }\n\n Object.assign(item, newProperties);\n\n // Invalidate cache if selection-related properties changed\n if ('selected' in newProperties || 'status' in newProperties) {\n this._invalidateSelectionCache();\n }\n\n return true;\n }\n\n /**\n * Returns an array of items marked as selected (memoized)\n * @returns Array of selected items\n */\n getSelectedItems(): AddSelectItem[] {\n // Return cached result if available\n if (this.selectedItemsCache !== null) {\n return this.selectedItemsCache;\n }\n\n // Build and cache the result\n const selected: AddSelectItem[] = [];\n this.selectedIds.forEach((id) => {\n const item = this.itemMap.get(id);\n if (item) {\n selected.push(item);\n }\n });\n\n this.selectedItemsCache = selected;\n return selected;\n }\n\n /**\n * Mark one or more items (by id) as selected\n * @param ids - Single id or array of ids to select\n * @param exclusive - If true, deselect all other items (default: false)\n */\n setSelectedItems(ids: string | string[], exclusive: boolean = false): void {\n const idArray = Array.isArray(ids) ? ids : [ids];\n\n if (exclusive) {\n // Efficiently clear all selections using the Set\n this.selectedIds.forEach((id) => {\n const item = this.itemMap.get(id);\n if (item) {\n item.selected = false;\n item.status = 'unchecked';\n }\n });\n this.selectedIds.clear();\n }\n\n // Select specified items\n idArray.forEach((id) => {\n const item = this.itemMap.get(id);\n if (item) {\n item.selected = true;\n item.status = 'checked';\n this.selectedIds.add(id);\n }\n });\n\n this._invalidateSelectionCache();\n }\n\n /**\n * Get direct children of a node\n * @param id - The parent item id\n * @returns Array of child items or empty array if no children\n */\n getItemChildren(id: string): AddSelectItem[] {\n const item = this.itemMap.get(id);\n if (!item) {\n return [];\n }\n return item.children?.entries ?? [];\n }\n\n /**\n * Get the parent of a node\n * @param id - The child item id\n * @returns The parent item or undefined if no parent (root level)\n */\n getItemParent(id: string): AddSelectItem | undefined {\n const parentId = this.parentMap.get(id);\n return parentId ? this.itemMap.get(parentId) : undefined;\n }\n\n /**\n * Get all ancestors (parents up to the root) of a node\n * @param id - The item id\n * @returns Array of ancestor items from immediate parent to root\n */\n getItemParents(id: string): AddSelectItem[] {\n const parents: AddSelectItem[] = [];\n let currentId: string | undefined = id;\n\n while (currentId) {\n const parentId = this.parentMap.get(currentId);\n if (!parentId) {\n break;\n }\n\n const parent = this.itemMap.get(parentId);\n if (parent) {\n parents.push(parent);\n }\n currentId = parentId;\n }\n\n return parents;\n }\n\n /**\n * Retrieve the selected state status of an item\n * @param id - The item id\n * @returns The status or undefined if item not found\n */\n getItemStatus(id: string): ItemStatus | undefined {\n return this.itemMap.get(id)?.status;\n }\n\n /**\n * Set or update the status of an item\n * @param id - The item id\n * @param status - The new status\n * @returns true if item was found and updated, false otherwise\n */\n setItemStatus(id: string, status: ItemStatus): boolean {\n const item = this.itemMap.get(id);\n if (!item) {\n return false;\n }\n\n const wasSelected = item.selected;\n item.status = status;\n item.selected = status === 'checked';\n\n // Update selectedIds Set\n if (item.selected) {\n this.selectedIds.add(id);\n } else {\n this.selectedIds.delete(id);\n }\n\n // Invalidate cache if selection changed\n if (wasSelected !== item.selected) {\n this._invalidateSelectionCache();\n }\n\n return true;\n }\n\n /**\n * Check whether an item is selected (O(1) lookup)\n * @param id - The item id\n * @returns true if selected, false otherwise\n */\n isSelected(id: string): boolean {\n return this.selectedIds.has(id);\n }\n\n /**\n * Search items based on a query and return matching items\n * @param query - The search query string\n * @param options - Search options\n * @returns Array of matching items\n */\n search(query: string, options: SearchOptions = {}): AddSelectItem[] {\n // Early return for empty query\n if (!query) {\n return [];\n }\n\n const {\n caseSensitive = false,\n searchFields = ['title', 'value'],\n maxResults,\n } = options;\n\n const searchTerm = caseSensitive ? query : query.toLowerCase();\n const results: AddSelectItem[] = [];\n\n // Use early termination if maxResults is specified\n const shouldContinue = (): boolean => {\n return !maxResults || results.length < maxResults;\n };\n\n this._traverseItems(this.items, (item) => {\n if (!shouldContinue()) {\n return;\n }\n\n for (const field of searchFields) {\n const fieldValue = item[field];\n if (fieldValue) {\n const valueToSearch = caseSensitive\n ? String(fieldValue)\n : String(fieldValue).toLowerCase();\n\n if (valueToSearch.includes(searchTerm)) {\n results.push(item);\n break; // Don't add the same item multiple times\n }\n }\n }\n });\n\n return results;\n }\n\n /**\n * Sort items based on a comparator function\n * @param compareFn - Comparison function for sorting\n * @param recursive - If true, sort children recursively (default: false)\n */\n sort(\n compareFn: (a: AddSelectItem, b: AddSelectItem) => number,\n recursive: boolean = false\n ): void {\n // Sort recursively first if needed\n if (recursive) {\n this._sortRecursive(this.items, compareFn);\n }\n\n // Then sort the top level\n this.items.sort(compareFn);\n\n // Rebuild maps and caches after sorting\n this._invalidateCaches();\n this._buildMaps(this.items);\n }\n\n /**\n * Clear all selections (optimized with Set)\n */\n clearSelections(): void {\n // Efficiently clear using the selectedIds Set\n this.selectedIds.forEach((id) => {\n const item = this.itemMap.get(id);\n if (item) {\n item.selected = false;\n item.status = 'unchecked';\n }\n });\n this.selectedIds.clear();\n this._invalidateSelectionCache();\n }\n\n /**\n * Get the depth/level of an item in the hierarchy (cached)\n * @param id - The item id\n * @returns The depth (0 for root level items) or -1 if not found\n */\n getItemDepth(id: string): number {\n // Check cache first\n const cachedDepth = this.depthCache.get(id);\n if (cachedDepth !== undefined) {\n return cachedDepth;\n }\n\n // Item doesn't exist\n if (!this.itemMap.has(id)) {\n return -1;\n }\n\n // Calculate and cache depth\n let depth = 0;\n let currentId: string | undefined = id;\n\n while (currentId) {\n const parentId = this.parentMap.get(currentId);\n if (!parentId) {\n break;\n }\n depth++;\n currentId = parentId;\n }\n\n this.depthCache.set(id, depth);\n return depth;\n }\n\n /**\n * Check if an item has children\n * @param id - The item id\n * @returns true if item has children, false otherwise\n */\n hasChildren(id: string): boolean {\n const item = this.itemMap.get(id);\n return !!item?.children?.entries?.length;\n }\n\n /**\n * Get all descendant items of a node\n * @param id - The parent item id\n * @returns Array of all descendant items\n */\n getItemDescendants(id: string): AddSelectItem[] {\n const item = this.itemMap.get(id);\n if (!item?.children?.entries) {\n return [];\n }\n\n const descendants: AddSelectItem[] = [];\n this._traverseItems(item.children.entries, (child) => {\n descendants.push(child);\n });\n\n return descendants;\n }\n\n /**\n * Check if an item has any selected descendants (optimized)\n * @param id - The item id\n * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)\n * @returns true if any descendant is selected, false otherwise\n */\n hasSelectedDescendants(\n id: string,\n selectedIds: Set<string> = this.selectedIds\n ): boolean {\n const children = this.getItemChildren(id);\n if (!children.length) {\n return false;\n }\n\n // Check if any child or their descendants are selected\n for (const child of children) {\n if (\n selectedIds.has(child.id) ||\n this.hasSelectedDescendants(child.id, selectedIds)\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Check if all descendants of an item are selected (optimized)\n * @param id - The item id\n * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)\n * @returns true if all descendants are selected, false otherwise\n */\n allDescendantsSelected(\n id: string,\n selectedIds: Set<string> = this.selectedIds\n ): boolean {\n const item = this.itemMap.get(id);\n if (!item) {\n return false;\n }\n\n const children = this.getItemChildren(id);\n if (!children.length) {\n return selectedIds.has(item.id);\n }\n\n // All children must be selected and all their descendants must be selected\n for (const child of children) {\n if (\n !selectedIds.has(child.id) ||\n !this.allDescendantsSelected(child.id, selectedIds)\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Get all descendant IDs from an item (including the item itself)\n * @param id - The item id\n * @returns Array of all descendant IDs including the item itself\n */\n getAllDescendantIds(id: string): string[] {\n const item = this.itemMap.get(id);\n if (!item) {\n return [];\n }\n\n const ids: string[] = [id];\n const children = this.getItemChildren(id);\n\n for (const child of children) {\n ids.push(...this.getAllDescendantIds(child.id));\n }\n\n return ids;\n }\n\n /**\n * Get only top-level selected items (items without selected ancestors)\n * @param selectedIds - Set of selected item IDs (defaults to internal selectedIds)\n * @returns Array of top-level selected items\n */\n getTopLevelSelectedItems(\n selectedIds: Set<string> = this.selectedIds\n ): AddSelectItem[] {\n const topLevelItems: AddSelectItem[] = [];\n const processedIds = new Set<string>();\n\n // Helper to check if any ancestor is selected\n const hasSelectedAncestor = (itemId: string): boolean => {\n const parents = this.getItemParents(itemId);\n return parents.some((parent) => selectedIds.has(parent.id));\n };\n\n // Collect all selected items that don't have a selected ancestor\n selectedIds.forEach((id) => {\n if (!processedIds.has(id) && !hasSelectedAncestor(id)) {\n const item = this.itemMap.get(id);\n if (item) {\n topLevelItems.push(item);\n // Mark all descendants as processed\n const descendantIds = this.getAllDescendantIds(id);\n descendantIds.forEach((descId) => processedIds.add(descId));\n }\n }\n });\n\n return topLevelItems;\n }\n\n /**\n * Invalidate all caches\n * @private\n */\n private _invalidateCaches(): void {\n this.selectedItemsCache = null;\n this.depthCache.clear();\n }\n\n /**\n * Invalidate selection cache only\n * @private\n */\n private _invalidateSelectionCache(): void {\n this.selectedItemsCache = null;\n }\n\n /**\n * Build internal maps for efficient lookups (optimized with depth caching)\n * @private\n */\n private _buildMaps(\n items: AddSelectItem[],\n parentId?: string,\n depth: number = 0\n ): void {\n if (!parentId) {\n // Clear maps when building from root\n this.itemMap.clear();\n this.parentMap.clear();\n this.selectedIds.clear();\n this.depthCache.clear();\n }\n\n items.forEach((item) => {\n this.itemMap.set(item.id, item);\n this.depthCache.set(item.id, depth);\n\n if (parentId) {\n this.parentMap.set(item.id, parentId);\n }\n\n // Track selected items\n if (item.selected) {\n this.selectedIds.add(item.id);\n }\n\n if (item.children?.entries) {\n this._buildMaps(item.children.entries, item.id, depth + 1);\n }\n });\n }\n\n /**\n * Traverse all items and apply a callback function\n * @private\n */\n private _traverseItems(\n items: AddSelectItem[],\n callback: (item: AddSelectItem) => void\n ): void {\n for (const item of items) {\n callback(item);\n if (item.children?.entries) {\n this._traverseItems(item.children.entries, callback);\n }\n }\n }\n\n /**\n * Sort items recursively\n * @private\n */\n private _sortRecursive(\n items: AddSelectItem[],\n compareFn: (a: AddSelectItem, b: AddSelectItem) => number\n ): void {\n for (const item of items) {\n if (item.children?.entries) {\n item.children.entries.sort(compareFn);\n this._sortRecursive(item.children.entries, compareFn);\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  //#region package.json
9
- var version = "0.41.0-rc.1";
9
+ var version = "0.41.0";
10
10
  //#endregion
11
11
  export { version };
12
12
 
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":[""],"mappings":""}
@@ -36,5 +36,5 @@ import coachmark_tagline_default from "./components/coachmark/coachmark-tagline/
36
36
  import big_number_skeleton_default from "./components/big-number/big-number-skeleton.js";
37
37
  import big_number_default from "./components/big-number/big-number.js";
38
38
  import edit_in_place_default from "./components/edit-in-place/edit-in-place.js";
39
- import { AddSelectData } from "@carbon/ibm-products-utilities";
39
+ import { AddSelectData } from "./ibm-products-utilities/src/utils/add-select/add-select-data.js";
40
40
  export { AddSelectData, about_modal_default as CDSAboutModal, action_set_default as CDSActionSet, big_number_default as CDSBigNumber, big_number_skeleton_default as CDSBigNumberSkeleton, coachmark_default as CDSCoachmark, coachmark_beacon_default as CDSCoachmarkBeacon, coachmark_tagline_default as CDSCoachmarkTagline, edit_in_place_default as CDSEditInPlace, full_page_error_default as CDSFullPageError, guide_banner_default as CDSGuideBanner, guide_banner_element_default as CDSGuideBannerElement, options_tile_default as CDSOptionsTile, page_header_default as CDSPageHeader, page_header_breadcrumb_default as CDSPageHeaderBreadcrumb, page_header_content_default as CDSPageHeaderContent, page_header_content_text_default as CDSPageHeaderContentText, page_header_hero_image_default as CDSPageHeaderHeroImage, page_header_tabs_default as CDSPageHeaderTabs, side_panel_default as CDSSidePanel, tearsheet_default as CDSTearsheet, tearsheet_body_default as CDSTearsheetBody, tearsheet_footer_default as CDSTearsheetFooter, tearsheet_header_default as CDSTearsheetHeader, tearsheet_header_content_default as CDSTearsheetHeaderContent, tearsheet_influencer_default as CDSTearsheetInfluencer, tearsheet_navigation_bar_default as CDSTearsheetNavigationBar, tearsheet_default$1 as CDSTearsheetPreview, tearsheet_scroller_default as CDSTearsheetScroller, tearsheet_summary_content_default as CDSTearsheetSummaryContent, truncated_text_default as CDSTruncatedText, user_avatar_default as CDSUserAvatar };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/ibm-products-web-components",
3
3
  "description": "Carbon for IBM Products Web Components",
4
- "version": "0.41.0",
4
+ "version": "0.41.1-rc.0",
5
5
  "license": "Apache-2.0",
6
6
  "main": "es/index.js",
7
7
  "module": "es/index.js",
@@ -58,7 +58,6 @@
58
58
  "dependencies": {
59
59
  "@carbon-labs/wc-empty-state": "^0.21.0",
60
60
  "@carbon/ibm-products-styles": "^2.88.0",
61
- "@carbon/ibm-products-utilities": "^1.1.0",
62
61
  "@carbon/layout": "^11.52.0",
63
62
  "@carbon/styles": "^1.106.0",
64
63
  "@carbon/utilities": "^0.19.0",
@@ -71,6 +70,7 @@
71
70
  "devDependencies": {
72
71
  "@aarsteinmedia/dotlottie-player": "^6.0.5",
73
72
  "@blockquote/rollup-plugin-externalize-source-dependencies": "^1.0.0",
73
+ "@carbon/ibm-products-utilities": "1.1.0",
74
74
  "@carbon/icon-helpers": "^10.75.0",
75
75
  "@carbon/icons": "^11.80.0",
76
76
  "@carbon/motion": "^11.45.0",
@@ -108,5 +108,5 @@
108
108
  "vitest": "^3.2.0",
109
109
  "web-component-analyzer": "2.0.0"
110
110
  },
111
- "gitHead": "3fdb86b45ca8f5b56aeb198d2660877fff326990"
111
+ "gitHead": "873abb7b28373ab7d8bb5d4c93ae98ee99112723"
112
112
  }
package/es/package.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}