@geomak/ui 3.0.0 → 4.0.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.
- package/dist/index.cjs +231 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -15
- package/dist/index.d.ts +59 -15
- package/dist/index.js +231 -86
- package/dist/index.js.map +1 -1
- package/dist/styles.css +14 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3176,6 +3176,26 @@ function AutoComplete({
|
|
|
3176
3176
|
}
|
|
3177
3177
|
) });
|
|
3178
3178
|
}
|
|
3179
|
+
function flattenVisible(items, expanded, depth = 0, out = []) {
|
|
3180
|
+
for (const node of items) {
|
|
3181
|
+
const isParent2 = !!node.children && node.children.length > 0;
|
|
3182
|
+
out.push({ node, depth, isParent: isParent2 });
|
|
3183
|
+
if (isParent2 && expanded.has(node.key)) {
|
|
3184
|
+
flattenVisible(node.children, expanded, depth + 1, out);
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
return out;
|
|
3188
|
+
}
|
|
3189
|
+
function findNodeByKey(items, key) {
|
|
3190
|
+
for (const n of items) {
|
|
3191
|
+
if (n.key === key) return n;
|
|
3192
|
+
if (n.children) {
|
|
3193
|
+
const found = findNodeByKey(n.children, key);
|
|
3194
|
+
if (found) return found;
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
return null;
|
|
3198
|
+
}
|
|
3179
3199
|
function TreeSelect({
|
|
3180
3200
|
label,
|
|
3181
3201
|
name,
|
|
@@ -3184,106 +3204,231 @@ function TreeSelect({
|
|
|
3184
3204
|
disabled,
|
|
3185
3205
|
layout = "horizontal",
|
|
3186
3206
|
errorMessage,
|
|
3187
|
-
style
|
|
3207
|
+
style,
|
|
3188
3208
|
htmlFor,
|
|
3189
|
-
items = []
|
|
3209
|
+
items = [],
|
|
3210
|
+
placeholder = "Select\u2026",
|
|
3211
|
+
parentsSelectable = true,
|
|
3212
|
+
defaultExpandedKeys = []
|
|
3190
3213
|
}) {
|
|
3214
|
+
const errorId = React8.useId();
|
|
3215
|
+
const hasError = errorMessage != null;
|
|
3191
3216
|
const [open, setOpen] = React8.useState(false);
|
|
3192
|
-
const [
|
|
3193
|
-
const [
|
|
3217
|
+
const [expanded, setExpanded] = React8.useState(() => new Set(defaultExpandedKeys));
|
|
3218
|
+
const [activeIndex, setActiveIndex] = React8.useState(0);
|
|
3219
|
+
const listRef = React8.useRef(null);
|
|
3220
|
+
const visible = React8.useMemo(() => flattenVisible(items, expanded), [items, expanded]);
|
|
3194
3221
|
React8.useEffect(() => {
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3222
|
+
if (!open) return;
|
|
3223
|
+
const selectedIdx = visible.findIndex((v) => v.node.key === value);
|
|
3224
|
+
setActiveIndex(selectedIdx >= 0 ? selectedIdx : 0);
|
|
3225
|
+
}, [open, visible, value]);
|
|
3226
|
+
const selectedNode = React8.useMemo(
|
|
3227
|
+
() => value != null ? findNodeByKey(items, value) : null,
|
|
3228
|
+
[items, value]
|
|
3229
|
+
);
|
|
3230
|
+
const toggleExpand = (key) => {
|
|
3231
|
+
setExpanded((prev) => {
|
|
3232
|
+
const next = new Set(prev);
|
|
3233
|
+
if (next.has(key)) next.delete(key);
|
|
3234
|
+
else next.add(key);
|
|
3235
|
+
return next;
|
|
3236
|
+
});
|
|
3237
|
+
};
|
|
3238
|
+
const selectKey = (key) => {
|
|
3198
3239
|
onChange?.({ target: { value: key, id: htmlFor, name } });
|
|
3199
3240
|
setOpen(false);
|
|
3200
3241
|
};
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3242
|
+
const onListKey = (e) => {
|
|
3243
|
+
if (visible.length === 0) return;
|
|
3244
|
+
const cur = visible[activeIndex];
|
|
3245
|
+
if (e.key === "ArrowDown") {
|
|
3246
|
+
e.preventDefault();
|
|
3247
|
+
setActiveIndex((i) => Math.min(i + 1, visible.length - 1));
|
|
3248
|
+
} else if (e.key === "ArrowUp") {
|
|
3249
|
+
e.preventDefault();
|
|
3250
|
+
setActiveIndex((i) => Math.max(i - 1, 0));
|
|
3251
|
+
} else if (e.key === "ArrowRight") {
|
|
3252
|
+
e.preventDefault();
|
|
3253
|
+
if (cur.isParent) {
|
|
3254
|
+
if (!expanded.has(cur.node.key)) toggleExpand(cur.node.key);
|
|
3255
|
+
else setActiveIndex((i) => Math.min(i + 1, visible.length - 1));
|
|
3256
|
+
}
|
|
3257
|
+
} else if (e.key === "ArrowLeft") {
|
|
3258
|
+
e.preventDefault();
|
|
3259
|
+
if (cur.isParent && expanded.has(cur.node.key)) {
|
|
3260
|
+
toggleExpand(cur.node.key);
|
|
3261
|
+
} else if (cur.depth > 0) {
|
|
3262
|
+
for (let i = activeIndex - 1; i >= 0; i--) {
|
|
3263
|
+
if (visible[i].depth < cur.depth) {
|
|
3264
|
+
setActiveIndex(i);
|
|
3265
|
+
break;
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
} else if (e.key === "Enter" || e.key === " ") {
|
|
3270
|
+
e.preventDefault();
|
|
3271
|
+
if (cur.node.disabled) return;
|
|
3272
|
+
if (cur.isParent && !parentsSelectable) {
|
|
3273
|
+
toggleExpand(cur.node.key);
|
|
3274
|
+
} else {
|
|
3275
|
+
selectKey(cur.node.key);
|
|
3276
|
+
}
|
|
3277
|
+
} else if (e.key === "Escape") {
|
|
3278
|
+
e.preventDefault();
|
|
3279
|
+
setOpen(false);
|
|
3280
|
+
}
|
|
3281
|
+
};
|
|
3282
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3283
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex ${layout === "vertical" ? "flex-col gap-1" : "flex-row items-center gap-2"}`, children: [
|
|
3284
|
+
label && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3285
|
+
"label",
|
|
3286
|
+
{
|
|
3287
|
+
className: "text-sm font-medium ml-1 max-content select-none text-foreground",
|
|
3288
|
+
htmlFor,
|
|
3289
|
+
children: label
|
|
3290
|
+
}
|
|
3291
|
+
),
|
|
3292
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
3293
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3294
|
+
"button",
|
|
3295
|
+
{
|
|
3296
|
+
id: htmlFor,
|
|
3297
|
+
type: "button",
|
|
3298
|
+
style,
|
|
3299
|
+
role: "combobox",
|
|
3300
|
+
"aria-expanded": open,
|
|
3301
|
+
"aria-haspopup": "listbox",
|
|
3302
|
+
"aria-invalid": hasError || void 0,
|
|
3303
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
3304
|
+
disabled,
|
|
3305
|
+
className: `flex items-center justify-between h-9 rounded-lg border ${hasError ? "border-status-error" : "border-border"} px-3 cursor-pointer select-none focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${disabled ? "cursor-not-allowed bg-surface-raised text-foreground-muted" : "bg-surface text-foreground"} ${!style?.width ? "min-w-[240px]" : ""}`,
|
|
3306
|
+
children: [
|
|
3307
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm truncate text-left", children: selectedNode ? selectedNode.label : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted", children: placeholder }) }),
|
|
3308
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: `h-4 w-4 flex-shrink-0 transition-transform duration-200 ${open ? "rotate-180" : ""}`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
|
|
3309
|
+
]
|
|
3310
|
+
}
|
|
3311
|
+
) }),
|
|
3312
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3313
|
+
Popover__namespace.Content,
|
|
3314
|
+
{
|
|
3315
|
+
align: "start",
|
|
3316
|
+
sideOffset: 4,
|
|
3317
|
+
style: { width: style?.width || 280 },
|
|
3318
|
+
className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-1 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
3319
|
+
onOpenAutoFocus: (e) => {
|
|
3320
|
+
e.preventDefault();
|
|
3321
|
+
listRef.current?.focus();
|
|
3322
|
+
},
|
|
3323
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3217
3324
|
"div",
|
|
3218
3325
|
{
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
"aria-
|
|
3223
|
-
|
|
3224
|
-
className:
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-7 ${!style?.width ? "min-w-[240px]" : ""} focus:outline-none text-prussian-blue flex items-center gap-1`, children: Array.isArray(value) ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3228
|
-
value.slice(0, 1).map((val, id) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3229
|
-
DropdownPill,
|
|
3230
|
-
{
|
|
3231
|
-
hasSiblings: value.length > 1,
|
|
3232
|
-
value: innerItems.find((it) => it.key === val)?.label
|
|
3233
|
-
},
|
|
3234
|
-
id
|
|
3235
|
-
)),
|
|
3236
|
-
value.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(DropdownPill, { value: `+${value.length - 1} more` })
|
|
3237
|
-
] }) : value != null ? /* @__PURE__ */ jsxRuntime.jsx(DropdownPill, { value: innerItems.find((it) => it.key === value)?.label }) : null }),
|
|
3238
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `transition-transform duration-300 ml-2 ${open ? "rotate-180" : "rotate-0"}`, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: chunk255PCZIW_cjs.colors_default.PALETTE["prussian-blue"], strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
|
|
3239
|
-
]
|
|
3240
|
-
}
|
|
3241
|
-
) }),
|
|
3242
|
-
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3243
|
-
Popover__namespace.Content,
|
|
3244
|
-
{
|
|
3245
|
-
align: "start",
|
|
3246
|
-
sideOffset: 4,
|
|
3247
|
-
style: { width: style?.width || 240 },
|
|
3248
|
-
className: "bg-ice rounded-lg shadow-md z-50 p-2 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
3249
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", className: "max-h-40 overflow-y-auto", children: innerItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3250
|
-
"div",
|
|
3326
|
+
ref: listRef,
|
|
3327
|
+
role: "tree",
|
|
3328
|
+
tabIndex: -1,
|
|
3329
|
+
"aria-activedescendant": visible[activeIndex] ? `tree-opt-${visible[activeIndex].node.key}` : void 0,
|
|
3330
|
+
onKeyDown: onListKey,
|
|
3331
|
+
className: "max-h-72 overflow-y-auto outline-none",
|
|
3332
|
+
children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-4 text-sm text-foreground-secondary text-center", children: "No items" }) : visible.map((v, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3333
|
+
TreeNodeRow,
|
|
3251
3334
|
{
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
{
|
|
3267
|
-
d: "M4 10l4.5 4.5L16 6",
|
|
3268
|
-
stroke: hoveredItem === item.key ? "#fff" : chunk255PCZIW_cjs.colors_default.PALETTE["prussian-blue"],
|
|
3269
|
-
strokeWidth: "2",
|
|
3270
|
-
strokeLinecap: "round",
|
|
3271
|
-
strokeLinejoin: "round"
|
|
3272
|
-
}
|
|
3273
|
-
) })
|
|
3274
|
-
]
|
|
3335
|
+
node: v.node,
|
|
3336
|
+
depth: v.depth,
|
|
3337
|
+
isParent: v.isParent,
|
|
3338
|
+
isExpanded: expanded.has(v.node.key),
|
|
3339
|
+
isActive: idx === activeIndex,
|
|
3340
|
+
isSelected: value === v.node.key,
|
|
3341
|
+
parentsSelectable,
|
|
3342
|
+
onActivate: () => {
|
|
3343
|
+
if (v.node.disabled) return;
|
|
3344
|
+
if (v.isParent && !parentsSelectable) toggleExpand(v.node.key);
|
|
3345
|
+
else selectKey(v.node.key);
|
|
3346
|
+
},
|
|
3347
|
+
onToggle: () => toggleExpand(v.node.key),
|
|
3348
|
+
onHover: () => setActiveIndex(idx)
|
|
3275
3349
|
},
|
|
3276
|
-
|
|
3277
|
-
))
|
|
3350
|
+
v.node.key
|
|
3351
|
+
))
|
|
3278
3352
|
}
|
|
3279
|
-
)
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
}
|
|
3283
|
-
),
|
|
3284
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-
|
|
3353
|
+
)
|
|
3354
|
+
}
|
|
3355
|
+
) })
|
|
3356
|
+
] })
|
|
3357
|
+
] }),
|
|
3358
|
+
hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-xs text-status-error ml-1", children: errorMessage })
|
|
3285
3359
|
] });
|
|
3286
3360
|
}
|
|
3361
|
+
function TreeNodeRow({
|
|
3362
|
+
node,
|
|
3363
|
+
depth,
|
|
3364
|
+
isParent: isParent2,
|
|
3365
|
+
isExpanded,
|
|
3366
|
+
isActive,
|
|
3367
|
+
isSelected,
|
|
3368
|
+
parentsSelectable,
|
|
3369
|
+
onActivate,
|
|
3370
|
+
onToggle,
|
|
3371
|
+
onHover
|
|
3372
|
+
}) {
|
|
3373
|
+
const disabled = node.disabled;
|
|
3374
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3375
|
+
"div",
|
|
3376
|
+
{
|
|
3377
|
+
id: `tree-opt-${node.key}`,
|
|
3378
|
+
role: "treeitem",
|
|
3379
|
+
"aria-selected": isSelected,
|
|
3380
|
+
"aria-expanded": isParent2 ? isExpanded : void 0,
|
|
3381
|
+
"aria-disabled": disabled || void 0,
|
|
3382
|
+
"data-active": isActive ? "" : void 0,
|
|
3383
|
+
onMouseEnter: onHover,
|
|
3384
|
+
className: `flex items-center gap-1 rounded-md px-1 py-1.5 select-none cursor-pointer transition-colors duration-100 ${disabled ? "opacity-40 cursor-not-allowed" : isActive ? "bg-accent text-accent-fg" : isSelected ? "bg-surface-raised" : "hover:bg-surface-raised"}`,
|
|
3385
|
+
style: { paddingLeft: depth * 16 + 4 },
|
|
3386
|
+
children: [
|
|
3387
|
+
isParent2 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3388
|
+
"button",
|
|
3389
|
+
{
|
|
3390
|
+
type: "button",
|
|
3391
|
+
onClick: (e) => {
|
|
3392
|
+
e.stopPropagation();
|
|
3393
|
+
onToggle();
|
|
3394
|
+
},
|
|
3395
|
+
"aria-label": isExpanded ? "Collapse" : "Expand",
|
|
3396
|
+
tabIndex: -1,
|
|
3397
|
+
className: "w-5 h-5 inline-flex items-center justify-center rounded hover:bg-black/10 focus:outline-none",
|
|
3398
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3399
|
+
"svg",
|
|
3400
|
+
{
|
|
3401
|
+
viewBox: "0 0 24 24",
|
|
3402
|
+
fill: "none",
|
|
3403
|
+
stroke: "currentColor",
|
|
3404
|
+
strokeWidth: 2.5,
|
|
3405
|
+
className: `h-3 w-3 transition-transform duration-150 ${isExpanded ? "rotate-0" : "-rotate-90"}`,
|
|
3406
|
+
"aria-hidden": "true",
|
|
3407
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
|
|
3408
|
+
}
|
|
3409
|
+
)
|
|
3410
|
+
}
|
|
3411
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-5 h-5 inline-block", "aria-hidden": "true" }),
|
|
3412
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3413
|
+
"button",
|
|
3414
|
+
{
|
|
3415
|
+
type: "button",
|
|
3416
|
+
onClick: onActivate,
|
|
3417
|
+
disabled,
|
|
3418
|
+
tabIndex: -1,
|
|
3419
|
+
className: "flex-1 flex items-center gap-2 text-sm text-left focus:outline-none disabled:cursor-not-allowed",
|
|
3420
|
+
children: [
|
|
3421
|
+
node.icon,
|
|
3422
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: node.label }),
|
|
3423
|
+
isParent2 && !parentsSelectable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-foreground-muted", children: "parent" })
|
|
3424
|
+
]
|
|
3425
|
+
}
|
|
3426
|
+
),
|
|
3427
|
+
isSelected && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", className: "ml-1", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 10l4.5 4.5L16 6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
3428
|
+
]
|
|
3429
|
+
}
|
|
3430
|
+
);
|
|
3431
|
+
}
|
|
3287
3432
|
function FileInput({
|
|
3288
3433
|
allowMultiple = false,
|
|
3289
3434
|
onChange,
|