@bccampus/ui-components 0.3.0 → 0.4.1

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.
@@ -1,303 +1,6 @@
1
- import { jsx as h } from "react/jsx-runtime";
2
- import { useMemo as M } from "react";
3
- import { c as d } from "./utils-CRiPKpXj.js";
4
- const $ = {
5
- Blank: 0,
6
- Rand: 1,
7
- Mosaic: 2,
8
- MosaicCircle: 3,
9
- MosaicDiamond: 4,
10
- Square: 6,
11
- Circle: 7,
12
- Diamond: 8,
13
- Hexagon: 9,
14
- RandBasic: 10,
15
- TriangleSE: 11,
16
- TriangleSW: 12,
17
- TriangleNW: 13,
18
- TriangleNE: 14,
19
- TriangleRand: 15,
20
- CaretN: 16,
21
- CaretE: 17,
22
- CaretS: 18,
23
- CaretW: 19,
24
- CaretRand: 20,
25
- PieSE: 21,
26
- PieSW: 22,
27
- PieNW: 23,
28
- PieNE: 24,
29
- PieRand: 25
30
- }, p = [
31
- $.Square,
32
- $.Circle,
33
- $.Diamond,
34
- $.Hexagon,
35
- $.TriangleSE,
36
- $.TriangleSW,
37
- $.TriangleNW,
38
- $.TriangleNE,
39
- $.PieSE,
40
- $.PieSW,
41
- $.PieNW,
42
- $.PieNE
43
- ], N = {
44
- [$.Blank]: () => null,
45
- [$.Rand]: (c, r, a, s) => N[p[Math.floor(Math.random() * p.length)]](c, r, a, s),
46
- [$.Mosaic]: (c, r, a, s) => N[Math.random() > 0.8 ? $.Blank : $.Square](c, r, a, s),
47
- [$.MosaicCircle]: (c, r, a, s) => N[Math.random() > 0.8 ? $.Blank : $.Circle](c, r, a, s),
48
- [$.MosaicDiamond]: (c, r, a, s) => N[Math.random() > 0.8 ? $.Blank : $.Diamond](c, r, a, s),
49
- [$.Square]: (c, r, a, s) => /* @__PURE__ */ h(
50
- "rect",
51
- {
52
- x: a * c,
53
- y: a * r,
54
- width: a * s.scale,
55
- height: a * s.scale,
56
- className: d("fill-current stroke-none", s?.className)
57
- },
58
- `tile-${c}-${r}`
59
- ),
60
- [$.Circle]: (c, r, a, s) => /* @__PURE__ */ h(
61
- "circle",
62
- {
63
- cx: a * (c + 0.5 * s.scale),
64
- cy: a * (r + 0.5 * s.scale),
65
- r: a / 2 * s.scale,
66
- className: d("fill-current stroke-none", s?.className)
67
- },
68
- `tile-${c}-${r}`
69
- ),
70
- [$.Diamond]: (c, r, a, s) => /* @__PURE__ */ h(
71
- "path",
72
- {
73
- d: `M ${a * (c + 0.5 * s.scale)} ${a * r}
74
- L ${a * (c + s.scale)} ${a * (r + 0.5 * s.scale)}
75
- L ${a * (c + 0.5 * s.scale)} ${a * (r + s.scale)}
76
- L ${a * c} ${a * (r + 0.5 * s.scale)} Z`,
77
- className: d("fill-current stroke-none", s?.className)
78
- },
79
- `tile-${c}-${r}`
80
- ),
81
- [$.Hexagon]: (c, r, a, s) => {
82
- const o = a / Math.sqrt(3), m = (a - o) / 2;
83
- return /* @__PURE__ */ h(
84
- "path",
85
- {
86
- rotate: 45,
87
- d: `M ${a * c + m * s.scale} ${a * r}
88
- L ${a * c + (m + o) * s.scale} ${a * r}
89
- L ${a * (c + s.scale)} ${a * (r + 0.5 * s.scale)}
90
- L ${a * c + (m + o) * s.scale} ${a * (r + s.scale)}
91
- L ${a * c + m * s.scale} ${a * (r + s.scale)}
92
- L ${a * c} ${a * (r + 0.5 * s.scale)} Z`,
93
- className: d("fill-current stroke-none", s?.className)
94
- },
95
- `tile-${c}-${r}`
96
- );
97
- },
98
- [$.RandBasic]: (c, r, a, s) => N[$.Square + Math.floor(Math.random() * 4)](c, r, a, s),
99
- [$.TriangleSE]: (c, r, a, s) => /* @__PURE__ */ h(
100
- "path",
101
- {
102
- d: `M ${a * (c + s.scale)} ${a * r}
103
- L ${a * c} ${a * (r + s.scale)}
104
- L ${a * (c + s.scale)} ${a * (r + s.scale)} Z`,
105
- className: d("fill-current stroke-none", s?.className)
106
- },
107
- `tile-${c}-${r}`
108
- ),
109
- [$.TriangleSW]: (c, r, a, s) => /* @__PURE__ */ h(
110
- "path",
111
- {
112
- d: `M ${a * c} ${a * r}
113
- L ${a * (c + s.scale)} ${a * (r + s.scale)}
114
- L ${a * c} ${a * (r + s.scale)} Z`,
115
- className: d("fill-current stroke-none", s?.className)
116
- },
117
- `tile-${c}-${r}`
118
- ),
119
- [$.TriangleNW]: (c, r, a, s) => /* @__PURE__ */ h(
120
- "path",
121
- {
122
- d: `M ${a * (c + s.scale)} ${a * r}
123
- L ${a * c} ${a * (r + s.scale)}
124
- L ${a * c} ${a * r} Z`,
125
- className: d("fill-current stroke-none", s?.className)
126
- },
127
- `tile-${c}-${r}`
128
- ),
129
- [$.TriangleNE]: (c, r, a, s) => /* @__PURE__ */ h(
130
- "path",
131
- {
132
- d: `M ${a * c} ${a * r}
133
- L ${a * (c + s.scale)} ${a * (r + s.scale)}
134
- L ${a * (c + s.scale)} ${a * r} Z`,
135
- className: d("fill-current stroke-none", s?.className)
136
- },
137
- `tile-${c}-${r}`
138
- ),
139
- [$.TriangleRand]: (c, r, a, s) => N[$.TriangleSE + Math.floor(Math.random() * 4)](
140
- c,
141
- r,
142
- a,
143
- s
144
- ),
145
- [$.CaretN]: (c, r, a, s) => /* @__PURE__ */ h(
146
- "path",
147
- {
148
- d: `M ${a * c} ${a * (r + s.scale)}
149
- L ${a * (c + s.scale)} ${a * (r + s.scale)}
150
- L ${a * (c + 0.5 * s.scale)} ${a * r} Z`,
151
- className: d("fill-current stroke-none", s?.className)
152
- },
153
- `tile-${c}-${r}`
154
- ),
155
- [$.CaretE]: (c, r, a, s) => /* @__PURE__ */ h(
156
- "path",
157
- {
158
- d: `M ${a * c} ${a * r}
159
- L ${a * (c + s.scale)} ${a * (r + 0.5 * s.scale)}
160
- L ${a * c} ${a * (r + s.scale)} Z`,
161
- className: d("fill-current stroke-none", s?.className)
162
- },
163
- `tile-${c}-${r}`
164
- ),
165
- [$.CaretS]: (c, r, a, s) => /* @__PURE__ */ h(
166
- "path",
167
- {
168
- d: `M ${a * c} ${a * r}
169
- L ${a * (c + s.scale)} ${a * r}
170
- L ${a * (c + 0.5 * s.scale)} ${a * (r + s.scale)} Z`,
171
- className: d("fill-current stroke-none", s?.className)
172
- },
173
- `tile-${c}-${r}`
174
- ),
175
- [$.CaretW]: (c, r, a, s) => /* @__PURE__ */ h(
176
- "path",
177
- {
178
- d: `M ${a * (c + s.scale)} ${a * r}
179
- L ${a * c} ${a * (r + 0.5 * s.scale)}
180
- L ${a * (c + s.scale)} ${a * (r + s.scale)} Z`,
181
- className: d("fill-current stroke-none", s?.className)
182
- },
183
- `tile-${c}-${r}`
184
- ),
185
- [$.CaretRand]: (c, r, a, s) => N[$.CaretN + Math.floor(Math.random() * 4)](c, r, a, s),
186
- [$.PieSE]: (c, r, a, s) => /* @__PURE__ */ h(
187
- "path",
188
- {
189
- d: `M ${a * s.scale + a * c} ${a * r}
190
- A ${a * s.scale} ${a * s.scale}, 0, 0, 0, ${a * c} ${a * s.scale + a * r}
191
- L ${a * s.scale + a * c} ${a * s.scale + a * r} Z`,
192
- className: d("fill-current stroke-none", s?.className)
193
- },
194
- `tile-${c}-${r}`
195
- ),
196
- [$.PieSW]: (c, r, a, s) => /* @__PURE__ */ h(
197
- "path",
198
- {
199
- d: `M ${a * s.scale + a * c} ${a * s.scale + a * r}
200
- A ${a * s.scale} ${a * s.scale}, 0, 0, 0, ${a * c} ${a * r}
201
- L ${a * c} ${a * s.scale + a * r} Z`,
202
- className: d("fill-current stroke-none", s?.className)
203
- },
204
- `tile-${c}-${r}`
205
- ),
206
- [$.PieNW]: (c, r, a, s) => /* @__PURE__ */ h(
207
- "path",
208
- {
209
- d: `M ${a * c} ${a * s.scale + a * r}
210
- A ${a * s.scale} ${a * s.scale}, 0, 0, 0, ${a * s.scale + a * c} ${a * r}
211
- L ${a * c} ${a * r} Z`,
212
- className: d("fill-current stroke-none", s?.className)
213
- },
214
- `tile-${c}-${r}`
215
- ),
216
- [$.PieNE]: (c, r, a, s) => /* @__PURE__ */ h(
217
- "path",
218
- {
219
- d: `M ${a * c} ${a * r}
220
- A ${a * s.scale} ${a * s.scale}, 0, 0, 0, ${a * s.scale + a * c} ${a * s.scale + a * r}
221
- L ${a * s.scale + a * c} ${a * r} Z`,
222
- className: d("fill-current stroke-none", s?.className)
223
- },
224
- `tile-${c}-${r}`
225
- ),
226
- [$.PieRand]: (c, r, a, s) => N[$.PieSE + Math.floor(Math.random() * 4)](c, r, a, s)
227
- }, w = (c, r, a) => c.map(
228
- (s, o) => s.map((m, L) => {
229
- const n = typeof m == "object" ? { className: d(a, m.className), scale: m.scale ?? 1, shape: m.shape } : { className: a, scale: 1, shape: m };
230
- return N[n.shape](L, o, r, n);
231
- })
232
- ).flat(), R = [
233
- [$.PieRand, $.PieRand],
234
- [$.PieRand, $.PieRand]
235
- ];
236
- function x({
237
- pattern: c = R,
238
- tileSize: r = 64,
239
- tileClassName: a,
240
- tileBgClassName: s,
241
- renderChildren: o,
242
- fit: m = "none",
243
- ...L
244
- }) {
245
- const n = M(
246
- () => ({
247
- width: c.reduce((u, E) => Math.max(u, E.length), 0) * r,
248
- height: c.length * r
249
- }),
250
- [c, r]
251
- ), k = M(() => {
252
- const u = w(c, r, a);
253
- return s && u.unshift(
254
- /* @__PURE__ */ h(
255
- "rect",
256
- {
257
- x: 0,
258
- y: 0,
259
- width: n.width,
260
- height: n.height,
261
- className: d("fill-black stroke-2 stroke-black", s)
262
- },
263
- "svg-mask-invert"
264
- )
265
- ), u;
266
- }, [c, n, a, s, r]), P = M(() => {
267
- switch (m) {
268
- case "fill":
269
- return n.width <= n.height ? "100%" : void 0;
270
- case "width":
271
- return "100%";
272
- case "none":
273
- return n.width;
274
- default:
275
- return;
276
- }
277
- }, [m, n]), T = M(() => {
278
- switch (m) {
279
- case "fill":
280
- return n.height < n.width ? "100%" : void 0;
281
- case "height":
282
- return "100%";
283
- case "none":
284
- return n.height;
285
- default:
286
- return;
287
- }
288
- }, [m, n]);
289
- return /* @__PURE__ */ h(
290
- "svg",
291
- {
292
- width: P,
293
- height: T,
294
- viewBox: `0 0 ${n.width} ${n.height}`,
295
- overflow: "visible",
296
- ...L,
297
- children: o ? o(k, n.width, n.height) : k
298
- }
299
- );
300
- }
1
+ import { I as r } from "./icon-generator-tuhuqdpL.js";
2
+ import { T as p } from "./generate-tiles-DuagGD1d.js";
301
3
  export {
302
- x as IconGenerator
4
+ r as IconGenerator,
5
+ p as TileShape
303
6
  };
@@ -1,12 +1,12 @@
1
1
  import { jsx as o, jsxs as c, Fragment as d } from "react/jsx-runtime";
2
2
  import { useId as p, useMemo as l } from "react";
3
- import { IconGenerator as M } from "./icon-generator.js";
3
+ import { I as M } from "./icon-generator-tuhuqdpL.js";
4
4
  const h = { cover: "slice", contain: "meet", fill: "none" }, k = { top: "xMidYMin", center: "xMidYMid", bottom: "xMidYMax" };
5
- function u({
6
- src: n,
5
+ function g({
6
+ src: s,
7
7
  imageFit: e = "cover",
8
8
  imagePosition: r = "top",
9
- maskType: s = "alpha",
9
+ maskType: n = "alpha",
10
10
  ...a
11
11
  }) {
12
12
  const t = p(), i = l(
@@ -18,12 +18,12 @@ function u({
18
18
  {
19
19
  ...a,
20
20
  renderChildren: (m) => /* @__PURE__ */ c(d, { children: [
21
- /* @__PURE__ */ o("mask", { id: `svg-mask${t}`, "mask-type": s, children: m }),
22
- /* @__PURE__ */ o("image", { href: n, width: "100%", height: "100%", mask: `url(#svg-mask${t})`, preserveAspectRatio: i })
21
+ /* @__PURE__ */ o("mask", { id: `svg-mask${t}`, "mask-type": n, children: m }),
22
+ /* @__PURE__ */ o("image", { href: s, width: "100%", height: "100%", mask: `url(#svg-mask${t})`, preserveAspectRatio: i })
23
23
  ] })
24
24
  }
25
25
  );
26
26
  }
27
27
  export {
28
- u as MaskedImageGenerator
28
+ g as MaskedImageGenerator
29
29
  };
@@ -1,9 +1,9 @@
1
- import { IconGenerator as o } from "./icon-generator.js";
1
+ import { I as o } from "./icon-generator-tuhuqdpL.js";
2
2
  import { MaskedImageGenerator as e } from "./masked-image-generator.js";
3
3
  import { Caption as i, captionVariants as p } from "./caption.js";
4
4
  import { Banner as m } from "./banner.js";
5
5
  import { Button as u, buttonVariants as C } from "./button.js";
6
- import { Card as x, CardArea as M, CardCaption as v, CardContent as I, CardImage as N, CardItemGroup as c, CardMedia as l, CardMeta as s, CardSubcaption as S, CardSubtitle as T, CardTitle as b, CardToolbar as V } from "./card.js";
6
+ import { Card as x, CardArea as M, CardCaption as v, CardContent as I, CardImage as N, CardItemGroup as s, CardMedia as c, CardMeta as l, CardSubcaption as S, CardSubtitle as T, CardTitle as b, CardToolbar as V } from "./card.js";
7
7
  import { HorizontalList as L } from "./horizontal-list.js";
8
8
  import { Input as k } from "./input.js";
9
9
  import { NavigationMenu as B, NavigationMenuContent as H, NavigationMenuIndicator as h, NavigationMenuItem as w, NavigationMenuLink as z, NavigationMenuList as A, NavigationMenuTrigger as O, NavigationMenuViewport as j, navigationMenuTriggerStyle as q } from "./navigation-menu.js";
@@ -22,9 +22,9 @@ export {
22
22
  v as CardCaption,
23
23
  I as CardContent,
24
24
  N as CardImage,
25
- c as CardItemGroup,
26
- l as CardMedia,
27
- s as CardMeta,
25
+ s as CardItemGroup,
26
+ c as CardMedia,
27
+ l as CardMeta,
28
28
  S as CardSubcaption,
29
29
  T as CardSubtitle,
30
30
  b as CardTitle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bccampus/ui-components",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "packageManager": "yarn@4.10.3",
6
6
  "exports": {
@@ -8,10 +8,18 @@
8
8
  "types": "./dist/ui-components.d.ts",
9
9
  "import": "./dist/ui-components.js"
10
10
  },
11
+ "./composite": {
12
+ "types": "./dist/composite.d.ts",
13
+ "import": "./dist/composite.js"
14
+ },
11
15
  "./icon-generator": {
12
16
  "types": "./dist/icon-generator.d.ts",
13
17
  "import": "./dist/icon-generator.js"
14
18
  },
19
+ "./generate-tiles": {
20
+ "types": "./dist/generate-tiles.d.ts",
21
+ "import": "./dist/generate-tiles.js"
22
+ },
15
23
  "./masked-image-generator": {
16
24
  "types": "./dist/masked-image-generator.d.ts",
17
25
  "import": "./dist/masked-image-generator.js"
@@ -89,11 +97,14 @@
89
97
  "@bcgov/bc-sans": "^2.1.0",
90
98
  "@fontsource-variable/inter-tight": "^5.2.7",
91
99
  "@ladle/react": "^5.0.3",
100
+ "@nanostores/react": "^1.0.0",
92
101
  "@radix-ui/react-navigation-menu": "^1.2.14",
102
+ "@radix-ui/react-popover": "^1.1.15",
93
103
  "@radix-ui/react-slot": "^1.2.3",
94
104
  "class-variance-authority": "^0.7.1",
95
105
  "clsx": "^2.1.1",
96
106
  "lucide-react": "^0.544.0",
107
+ "nanostores": "^1.0.1",
97
108
  "react": "^19.1.1",
98
109
  "react-dom": "^19.1.1",
99
110
  "tailwind-merge": "^3.3.1",
@@ -0,0 +1,215 @@
1
+ import { difference, union } from "@/lib/set-operations";
2
+ import { atom, type PreinitializedWritableAtom } from "nanostores";
3
+ import type { CompositeDataOptions, CompositeItemKey, CompositeOptions } from "./types";
4
+ import { CompositeDataItem } from "./CompositeDataItem";
5
+
6
+ export class CompositeData<T extends object> implements Iterable<CompositeDataItem<T>> {
7
+ #options: CompositeDataOptions<T>;
8
+
9
+ lookup: Map<CompositeItemKey, CompositeDataItem<T>> = new Map();
10
+
11
+ firstFocusableItem!: CompositeDataItem<T> | null;
12
+ focusedItem: PreinitializedWritableAtom<CompositeDataItem<T> | null> = atom(null);
13
+ disabledKeys: PreinitializedWritableAtom<Set<CompositeItemKey>> = atom(new Set());
14
+ selectedKeys: PreinitializedWritableAtom<Set<CompositeItemKey>> = atom(new Set());
15
+
16
+ root!: CompositeDataItem<T>;
17
+
18
+ constructor(items: T[], options?: CompositeOptions) {
19
+ this.#options = {
20
+ itemKeyProp: "key",
21
+ itemChildrenProp: "children",
22
+ disabledKeys: [],
23
+ selectedKeys: [],
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ getItemKey: (item: any) => item[this.#options.itemKeyProp] as CompositeItemKey,
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ getItemChildren: (item: any) => item[this.#options.itemChildrenProp] ? item[this.#options.itemChildrenProp] as T[] : undefined,
28
+
29
+ ...options
30
+ };
31
+
32
+ this.init(items);
33
+ }
34
+
35
+ *[Symbol.iterator](): Iterator<CompositeDataItem<T>> {
36
+ if (this.root.children) {
37
+ for (const node of this.root.children) {
38
+ yield node;
39
+ }
40
+ }
41
+ }
42
+
43
+ toJSON() {
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ const json: any = this.root.toJSON()
46
+
47
+ return json[this.#options.itemChildrenProp] as T[];
48
+ }
49
+
50
+
51
+ init(items: T[]) {
52
+ // this.itemAtoms = this.#setItemMap(items);
53
+ this.root = new CompositeDataItem(
54
+ { [this.#options.itemKeyProp]: "ALL", [this.#options.itemChildrenProp]: items } as T,
55
+ this.#options,
56
+ null
57
+ );
58
+
59
+ // Build item lookup table
60
+ this.lookup = new Map([...this.root].map(item => [item.key, item]));
61
+
62
+ // Set initially disabled items
63
+ this.#options.disabledKeys.forEach(disabledKey => this.disable(disabledKey));
64
+
65
+ // Set initially selected items : SelectionProvider
66
+ this.#options.selectedKeys.forEach(selectedKey => this.select(selectedKey));
67
+
68
+ // Set initially focused items : FocusProvider
69
+ this.firstFocusableItem = this.getFirstFocusableItem() ?? null;
70
+ if (this.firstFocusableItem) {
71
+ this.firstFocusableItem.state.setKey("focused", true);
72
+ this.focusedItem.set(this.firstFocusableItem);
73
+ }
74
+
75
+ // Set focus pointers: FocusProvider
76
+ const lookupData = [...this.lookup];
77
+ for (let index = 0; index < lookupData.length; index++) {
78
+ const [key, item] = lookupData[index];
79
+
80
+ if (!this.isFocusable(item)) continue;
81
+
82
+ if (index < lookupData.length - 1) {
83
+ let newIndex = index === lookupData.length - 1 ? 0 : index + 1;
84
+ while (newIndex < lookupData.length && !this.isFocusable(lookupData[newIndex][1])) {
85
+ newIndex = (newIndex + 1) % lookupData.length;
86
+ }
87
+
88
+ item.pointers.down = lookupData[newIndex][0];
89
+ lookupData[newIndex][1].pointers.up = key;
90
+ }
91
+ }
92
+ }
93
+
94
+
95
+ isFocusable(itemAtom: CompositeDataItem<T>) {
96
+ return !itemAtom.state.get().disabled;
97
+ }
98
+
99
+ getFirstFocusableItem() {
100
+ let iterItem = this.lookup.values().next();
101
+
102
+ while (iterItem.value && !this.isFocusable(iterItem.value)) {
103
+ iterItem = this.lookup.values().next();
104
+ }
105
+
106
+ return iterItem.value;
107
+ }
108
+
109
+ item(key: CompositeItemKey) { return this.lookup.get(key) };
110
+
111
+ descendants(itemKey: CompositeItemKey) {
112
+ const item = this.lookup.get(itemKey);
113
+ if (!item) return undefined;
114
+
115
+ return item.descendants();
116
+ }
117
+
118
+ ancestors(itemKey: CompositeItemKey) {
119
+ const item = this.lookup.get(itemKey);
120
+ if (!item) return undefined;
121
+
122
+ return item.ancestors();
123
+ }
124
+
125
+ focus(itemKey: CompositeItemKey): void;
126
+ focus(item: CompositeDataItem<T>): void;
127
+ focus(item: CompositeDataItem<T> | CompositeItemKey) {
128
+ const _item = item instanceof CompositeDataItem ? item : this.lookup.get(item);
129
+ if (!_item) return;
130
+
131
+ if (this.focusedItem.get()) {
132
+ if (_item.key === this.focusedItem.get()?.key) return;
133
+
134
+ this.focusedItem.get()!.state.setKey("focused", false);
135
+ }
136
+
137
+ _item.state.setKey("focused", true);
138
+ this.focusedItem.set(_item);
139
+ }
140
+
141
+ toggleSelect(itemKey: CompositeItemKey, recursive?: boolean): void;
142
+ toggleSelect(item: CompositeDataItem<T>, recursive?: boolean): void;
143
+ toggleSelect(item: CompositeDataItem<T> | CompositeItemKey, recursive: boolean = false) {
144
+ const _item = item instanceof CompositeDataItem ? item : this.lookup.get(item);
145
+ if (!_item) return;
146
+
147
+ if (_item.state.get().selected) this.deselect(_item, recursive);
148
+ else this.select(_item, recursive);
149
+ }
150
+
151
+ select(itemKey: CompositeItemKey, recursive?: boolean): void;
152
+ select(item: CompositeDataItem<T>, recursive?: boolean): void;
153
+ select(item: CompositeDataItem<T> | CompositeItemKey, recursive: boolean = false) {
154
+ const _item = item instanceof CompositeDataItem ? item : this.lookup.get(item);
155
+ if (!_item) return;
156
+
157
+ const selectedKeys = _item.select(recursive);
158
+ this.selectedKeys.set(union(this.selectedKeys.get(), selectedKeys));
159
+ }
160
+
161
+ deselect(itemKey: CompositeItemKey, recursive?: boolean): void;
162
+ deselect(item: CompositeDataItem<T>, recursive?: boolean): void;
163
+ deselect(item: CompositeDataItem<T> | CompositeItemKey, recursive: boolean = false) {
164
+ const _item = item instanceof CompositeDataItem ? item : this.lookup.get(item);
165
+ if (!_item) return;
166
+
167
+ const deselectedKeys = _item.deselect(recursive);
168
+ this.selectedKeys.set(difference(this.selectedKeys.get(), deselectedKeys));
169
+ }
170
+
171
+ disable(itemKey: CompositeItemKey, recursive?: boolean): void;
172
+ disable(item: CompositeDataItem<T>, recursive?: boolean): void;
173
+ disable(item: CompositeDataItem<T> | CompositeItemKey, recursive: boolean = false) {
174
+ const _item = item instanceof CompositeDataItem ? item : this.lookup.get(item);
175
+ if (!_item) return;
176
+
177
+ const disabledKeys = _item.disable(recursive);
178
+ this.disabledKeys.set(union(this.selectedKeys.get(), disabledKeys));
179
+ }
180
+
181
+
182
+ enable(itemKey: CompositeItemKey, recursive?: boolean): void;
183
+ enable(item: CompositeDataItem<T>, recursive?: boolean): void;
184
+ enable(item: CompositeDataItem<T> | CompositeItemKey, recursive: boolean = false) {
185
+ const _item = item instanceof CompositeDataItem ? item : this.lookup.get(item);
186
+ if (!_item) return;
187
+
188
+ const enabledKeys = _item.enable(recursive);
189
+ this.disabledKeys.set(union(this.selectedKeys.get(), enabledKeys));
190
+ }
191
+
192
+
193
+ updateItem(key: CompositeItemKey, data: Partial<T> | ((item: T) => Partial<T>)) {
194
+ const item = this.lookup.get(key);
195
+ if (item) {
196
+ const newData = {
197
+ ...item.data.get(), ...(
198
+ (typeof data === "function") ? data(item.data.get()) : data
199
+ )
200
+ };
201
+
202
+ const newKey = this.#options.getItemKey(newData);
203
+ if (item.key !== newKey) throw "Item key cannot be updated!";
204
+
205
+ this.#updateIfSelectedItem(key);
206
+ item.data.set(newData);
207
+ }
208
+ }
209
+
210
+ #updateIfSelectedItem(key: CompositeItemKey) {
211
+ if (this.selectedKeys.get().has(key)) {
212
+ this.selectedKeys.set(new Set([...this.selectedKeys.get()]));
213
+ }
214
+ }
215
+ }