@ztwoint/z-ui 0.1.63 → 0.1.64

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,12 +1,12 @@
1
- import { jsx as e, jsxs as o } from "react/jsx-runtime";
1
+ import { jsx as e, jsxs as i } from "react/jsx-runtime";
2
2
  import * as t from "@radix-ui/react-checkbox";
3
- import { cn as i } from "../../lib/utils.js";
3
+ import { cn as n } from "../../lib/utils.js";
4
4
  function s({ className: r, ...a }) {
5
- return /* @__PURE__ */ e(
5
+ return /* @__PURE__ */ e("div", { className: "inline-flex items-center justify-center", children: /* @__PURE__ */ e(
6
6
  t.Root,
7
7
  {
8
8
  "data-slot": "checkbox",
9
- className: i(
9
+ className: n(
10
10
  [
11
11
  "group border-box size-3.5 rounded-[5px] border-[2px] border-stroke-solid-high",
12
12
  "hover:border-stroke-solid-hover",
@@ -18,14 +18,14 @@ function s({ className: r, ...a }) {
18
18
  "data-[state=indeterminate]:hover:bg-accent-hover",
19
19
  "data-[state=indeterminate]:text-text-inverted-primary",
20
20
  "focus-visible:border-ring",
21
- "shrink-0",
21
+ // 'shrink-0',
22
22
  "transition-all duration-100 ease-in-out",
23
- "flex items-center justify-center"
23
+ "inline-flex items-center justify-center"
24
24
  ],
25
25
  r
26
26
  ),
27
27
  ...a,
28
- children: /* @__PURE__ */ o(
28
+ children: /* @__PURE__ */ i(
29
29
  t.Indicator,
30
30
  {
31
31
  "data-slot": "checkbox-indicator",
@@ -34,7 +34,7 @@ function s({ className: r, ...a }) {
34
34
  /* @__PURE__ */ e(
35
35
  "svg",
36
36
  {
37
- className: "hidden group-data-[state=checked]:block",
37
+ className: "hidden group-data-[state=checked]:block size-3.5",
38
38
  xmlns: "http://www.w3.org/2000/svg",
39
39
  width: "14",
40
40
  height: "14",
@@ -52,7 +52,7 @@ function s({ className: r, ...a }) {
52
52
  /* @__PURE__ */ e(
53
53
  "svg",
54
54
  {
55
- className: "hidden group-data-[state=indeterminate]:block",
55
+ className: "hidden group-data-[state=indeterminate]:block size-3.5",
56
56
  xmlns: "http://www.w3.org/2000/svg",
57
57
  width: "14",
58
58
  height: "14",
@@ -71,7 +71,7 @@ function s({ className: r, ...a }) {
71
71
  }
72
72
  )
73
73
  }
74
- );
74
+ ) });
75
75
  }
76
76
  export {
77
77
  s as Z2Checkbox
@@ -0,0 +1,4 @@
1
+ import { default as React } from 'react';
2
+ import { TreeCheckboxSelectProps } from './TreeCheckboxSelect.types';
3
+ declare const TreeCheckboxSelect: React.FC<TreeCheckboxSelectProps>;
4
+ export default TreeCheckboxSelect;
@@ -0,0 +1,301 @@
1
+ import { jsx as g, jsxs as w } from "react/jsx-runtime";
2
+ import { useMemo as V, useCallback as d, useState as Q } from "react";
3
+ import { Z2Checkbox as J } from "../checkbox/checkbox.js";
4
+ import { cn as R } from "../../lib/utils.js";
5
+ import { Input as ee } from "../input/input.js";
6
+ import { MagnifierIcon as te } from "../assets/icons/magnifier-icon.js";
7
+ const le = (N) => {
8
+ const x = /* @__PURE__ */ new Map(), k = [];
9
+ N.forEach((s) => {
10
+ const h = s.key.split(".");
11
+ let n = "";
12
+ h.forEach((o, p) => {
13
+ const m = p === h.length - 1;
14
+ if (n = n ? `${n}.${o}` : o, x.has(n)) {
15
+ if (m) {
16
+ const b = x.get(n);
17
+ b.label = s.label, b.disabled = s.disabled, b.hint = s.hint, b.isLeaf = !0;
18
+ }
19
+ } else {
20
+ const b = {
21
+ id: n,
22
+ label: m ? s.label : o,
23
+ // Use original label for leaf, path part for intermediate
24
+ children: [],
25
+ disabled: m ? s.disabled : void 0,
26
+ hint: m ? s.hint : void 0,
27
+ isLeaf: m
28
+ };
29
+ x.set(n, b);
30
+ }
31
+ });
32
+ }), x.forEach((s, h) => {
33
+ const n = h.split(".");
34
+ if (n.length === 1)
35
+ k.push(s);
36
+ else {
37
+ const o = n.slice(0, -1).join("."), p = x.get(o);
38
+ p && !p.children.find((m) => m.id === s.id) && p.children.push(s);
39
+ }
40
+ });
41
+ const c = (s) => s.sort((h, n) => h.label.localeCompare(n.label)).map((h) => ({
42
+ ...h,
43
+ children: h.children && h.children.length > 0 ? c(h.children) : void 0
44
+ }));
45
+ return c(k);
46
+ }, de = ({
47
+ items: N,
48
+ defaultValue: x = [],
49
+ onChange: k,
50
+ selectionMode: c = "all-nodes",
51
+ defaultExpandedIds: s,
52
+ searchable: h = !0,
53
+ searchPlaceholder: n = "Search items...",
54
+ filterFn: o,
55
+ onSearchChange: p,
56
+ showSelectAll: m = !0,
57
+ selectAllLabel: b = "Select all",
58
+ cascade: z = !0,
59
+ renderLabel: $,
60
+ ariaLabel: K,
61
+ ariaLabelledby: O,
62
+ disabled: v = !1
63
+ }) => {
64
+ const S = V(() => le(N), [N]), U = d((e) => e.map((t) => t.id), []), [f, W] = Q(new Set(x)), [I, X] = Q(
65
+ new Set(s || U(S))
66
+ ), [j, Y] = Q(""), C = d(
67
+ (e) => {
68
+ const t = [], i = (l) => {
69
+ l.children && l.children.forEach((r) => {
70
+ r.disabled || (c === "leaves-only" ? (!r.children || r.children.length === 0) && t.push(r.id) : t.push(r.id)), i(r);
71
+ });
72
+ };
73
+ return i(e), t;
74
+ },
75
+ [c]
76
+ ), L = d(
77
+ (e, t, i) => {
78
+ for (const l of e) {
79
+ if (l.id === t) return i || null;
80
+ if (l.children) {
81
+ const r = L(l.children, t, l.id);
82
+ if (r !== null) return r;
83
+ }
84
+ }
85
+ return null;
86
+ },
87
+ []
88
+ ), y = d((e, t) => e.label.toLowerCase().includes(t.toLowerCase()), []), F = d(
89
+ (e, t) => {
90
+ if (!t) return e;
91
+ const i = o || y, l = (u) => i(u, t) ? !0 : u.children ? u.children.some((a) => l(a)) : !1, r = (u) => u.filter((a) => l(a)).map((a) => i(a, t) ? a.children && a.children.length > 0 ? {
92
+ ...a,
93
+ children: a.children
94
+ // Include all children as-is
95
+ } : a : {
96
+ ...a,
97
+ children: a.children ? r(a.children) : void 0
98
+ });
99
+ return r(e);
100
+ },
101
+ [o, y]
102
+ ), Z = V(() => F(S, j), [S, j, F]), B = d(
103
+ (e, t = 0) => {
104
+ const i = [];
105
+ return e.forEach((l) => {
106
+ const r = !!(l.children && l.children.length > 0), u = I.has(l.id);
107
+ i.push({
108
+ node: l,
109
+ level: t,
110
+ isBranch: r,
111
+ visibleChildrenCount: u && l.children ? l.children.length : 0
112
+ }), u && l.children && i.push(...B(l.children, t + 1));
113
+ }), i;
114
+ },
115
+ [I]
116
+ ), E = V(() => B(Z), [Z, B]), P = d(
117
+ (e) => {
118
+ const t = f.has(e.id);
119
+ if (!e.children || e.children.length === 0)
120
+ return t ? "checked" : "unchecked";
121
+ const i = C(e);
122
+ if (i.length === 0)
123
+ return t ? "checked" : "unchecked";
124
+ const l = i.filter((r) => f.has(r));
125
+ return l.length === 0 ? t && c === "all-nodes" ? "checked" : "unchecked" : l.length === i.length ? "checked" : "mixed";
126
+ },
127
+ [f, C, c]
128
+ ), A = d(
129
+ (e) => {
130
+ W(e), k == null || k(Array.from(e));
131
+ },
132
+ [k]
133
+ ), G = d((e) => {
134
+ X(e);
135
+ }, []), T = d(
136
+ (e) => {
137
+ if (e.disabled || v) return;
138
+ const t = new Set(f), i = P(e);
139
+ if (z && e.children && e.children.length > 0) {
140
+ const l = C(e);
141
+ i === "checked" ? (l.forEach((r) => t.delete(r)), c === "all-nodes" && t.delete(e.id)) : (l.forEach((r) => t.add(r)), c === "all-nodes" && t.add(e.id));
142
+ } else
143
+ (c === "all-nodes" || !e.children || e.children.length === 0) && (f.has(e.id) ? t.delete(e.id) : t.add(e.id));
144
+ A(t);
145
+ },
146
+ [
147
+ f,
148
+ P,
149
+ z,
150
+ c,
151
+ C,
152
+ v,
153
+ A
154
+ ]
155
+ ), _ = d(() => {
156
+ const t = E.filter(
157
+ ({ node: r }) => !r.disabled && (c === "all-nodes" || !r.children || r.children.length === 0)
158
+ ).map(({ node: r }) => r.id), i = t.every((r) => f.has(r)), l = new Set(f);
159
+ i ? t.forEach((r) => l.delete(r)) : t.forEach((r) => l.add(r)), A(l);
160
+ }, [E, f, c, A]), H = d(() => {
161
+ const e = E.filter(
162
+ ({ node: l }) => !l.disabled && (c === "all-nodes" || !l.children || l.children.length === 0)
163
+ );
164
+ if (e.length === 0) return "unchecked";
165
+ const t = e.map(({ node: l }) => l.id), i = t.filter((l) => f.has(l)).length;
166
+ return i === 0 ? "unchecked" : i === t.length ? "checked" : "mixed";
167
+ }, [E, f, c]), q = d(
168
+ (e) => {
169
+ if (Y(e), p == null || p(e), e) {
170
+ const t = new Set(I), i = (l, r) => {
171
+ l.forEach((u) => {
172
+ if ((o || y)(u, e)) {
173
+ let D = r;
174
+ for (; D; )
175
+ t.add(D), D = L(S, D) || void 0;
176
+ }
177
+ u.children && i(u.children, u.id);
178
+ });
179
+ };
180
+ i(S), G(t);
181
+ }
182
+ },
183
+ [I, o, y, L, S, G, p]
184
+ ), M = d(
185
+ ({ node: e, level: t }) => {
186
+ const i = P(e), l = !0, r = !!(e.children && e.children.length > 0);
187
+ return /* @__PURE__ */ g(
188
+ "div",
189
+ {
190
+ className: R([
191
+ "flex items-center gap-2 py-1.5",
192
+ "leading-none-medium-sm",
193
+ "text-text-neutral-primary"
194
+ ]),
195
+ children: /* @__PURE__ */ w(
196
+ "div",
197
+ {
198
+ className: R(["flex items-center gap-2"]),
199
+ role: "treeitem",
200
+ "aria-level": t + 1,
201
+ "aria-expanded": r ? l : void 0,
202
+ "aria-checked": i === "mixed" ? "mixed" : i === "checked",
203
+ style: { paddingLeft: `${t * 23 + 6}px` },
204
+ "data-testid": `tree-node-${e.id}`,
205
+ children: [
206
+ /* @__PURE__ */ g(
207
+ "svg",
208
+ {
209
+ className: "self-start ml-auto",
210
+ xmlns: "http://www.w3.org/2000/svg",
211
+ width: "9",
212
+ height: "9",
213
+ viewBox: "0 0 9 9",
214
+ fill: "none",
215
+ children: /* @__PURE__ */ g("path", { d: "M1 1V1C1 4.86599 4.13401 8 8 8V8", stroke: "#E0E0E0", strokeLinecap: "round" })
216
+ }
217
+ ),
218
+ /* @__PURE__ */ g(
219
+ J,
220
+ {
221
+ checked: i === "checked" ? !0 : i === "mixed" ? "indeterminate" : !1,
222
+ onCheckedChange: () => T(e),
223
+ disabled: e.disabled || v,
224
+ "aria-label": `Select ${e.label}`
225
+ }
226
+ ),
227
+ /* @__PURE__ */ w(
228
+ "span",
229
+ {
230
+ className: "cursor-pointer select-none",
231
+ onClick: () => !e.disabled && !v && T(e),
232
+ children: [
233
+ $ ? $(e) : e.label,
234
+ e.hint && /* @__PURE__ */ w("span", { children: [
235
+ " ",
236
+ e.hint
237
+ ] })
238
+ ]
239
+ }
240
+ )
241
+ ]
242
+ },
243
+ e.id
244
+ )
245
+ }
246
+ );
247
+ },
248
+ [P, v, T, $]
249
+ );
250
+ return /* @__PURE__ */ w(
251
+ "div",
252
+ {
253
+ role: "tree",
254
+ "aria-multiselectable": "true",
255
+ "aria-label": K,
256
+ "aria-labelledby": O,
257
+ children: [
258
+ /* @__PURE__ */ w(
259
+ "div",
260
+ {
261
+ className: R([
262
+ "flex items-center gap-2 justify-between",
263
+ "leading-none-medium-sm",
264
+ "text-text-neutral-primary"
265
+ ]),
266
+ children: [
267
+ m && /* @__PURE__ */ w("div", { role: "treeitem", "aria-level": 1, className: "flex items-center gap-2", children: [
268
+ /* @__PURE__ */ g(
269
+ J,
270
+ {
271
+ checked: H() === "checked" ? !0 : H() === "mixed" ? "indeterminate" : !1,
272
+ onCheckedChange: _,
273
+ disabled: v,
274
+ "aria-label": b
275
+ }
276
+ ),
277
+ /* @__PURE__ */ g("span", { children: b })
278
+ ] }),
279
+ h && /* @__PURE__ */ g(
280
+ ee,
281
+ {
282
+ size: "small",
283
+ type: "text",
284
+ leftIcon: /* @__PURE__ */ g(te, {}),
285
+ placeholder: n,
286
+ value: j,
287
+ onChange: (e) => q(e.target.value),
288
+ disabled: v
289
+ }
290
+ )
291
+ ]
292
+ }
293
+ ),
294
+ /* @__PURE__ */ g("div", { role: "group", children: E.map((e) => M(e)) })
295
+ ]
296
+ }
297
+ );
298
+ };
299
+ export {
300
+ de as default
301
+ };
@@ -0,0 +1,55 @@
1
+ export type FlatItem = {
2
+ key: string;
3
+ label: string;
4
+ disabled?: boolean;
5
+ hint?: string;
6
+ };
7
+ export type TreeNode = {
8
+ id: string;
9
+ label: string;
10
+ children?: TreeNode[];
11
+ disabled?: boolean;
12
+ hint?: string;
13
+ isLeaf?: boolean;
14
+ };
15
+ export type SelectionMode = 'leaves-only' | 'all-nodes';
16
+ export interface TreeCheckboxSelectProps {
17
+ /** Flat array of items with hierarchical keys */
18
+ items: FlatItem[];
19
+ /** Initial selection */
20
+ defaultValue?: string[];
21
+ /** Change handler returns normalized selected ids */
22
+ onChange?: (nextIds: string[]) => void;
23
+ /** Control which nodes are selectable */
24
+ selectionMode?: SelectionMode;
25
+ /** Default expanded ids (default: expand all roots) */
26
+ defaultExpandedIds?: string[];
27
+ /** Search behavior */
28
+ searchable?: boolean;
29
+ searchPlaceholder?: string;
30
+ /** Custom filter function; default matches label (case-insensitive) */
31
+ filterFn?: (node: TreeNode, query: string) => boolean;
32
+ onSearchChange?: (query: string) => void;
33
+ /** "Select all" behavior scoped to current filtered view */
34
+ showSelectAll?: boolean;
35
+ selectAllLabel?: string;
36
+ /** If true, checking a parent cascades to all descendants; unchecking clears all */
37
+ cascade?: boolean;
38
+ /** Optional render override for labels (no styling) */
39
+ renderLabel?: (node: TreeNode) => React.ReactNode;
40
+ /** Accessibility */
41
+ ariaLabel?: string;
42
+ ariaLabelledby?: string;
43
+ /** Disable component */
44
+ disabled?: boolean;
45
+ /** Test id */
46
+ dataTestId?: string;
47
+ }
48
+ export interface FlatNode {
49
+ node: TreeNode;
50
+ level: number;
51
+ isBranch: boolean;
52
+ visibleChildrenCount: number;
53
+ parentId?: string;
54
+ }
55
+ export type CheckState = 'checked' | 'unchecked' | 'mixed';
@@ -0,0 +1,2 @@
1
+ export { default as TreeCheckboxSelect } from './TreeCheckboxSelect';
2
+ export type { FlatItem, TreeNode, TreeCheckboxSelectProps, SelectionMode, } from './TreeCheckboxSelect.types';