@olundot/ui 0.16.0 → 0.17.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/CHANGELOG.md +21 -0
- package/dist/index.d.ts +71 -5
- package/dist/index.js +787 -381
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -213,12 +213,13 @@ var buttonVariants = cva(
|
|
|
213
213
|
},
|
|
214
214
|
size: {
|
|
215
215
|
// Cross-control height map: Button sm/md/lg match field controls sm/md/lg (30/32/36px).
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
// Height comes from h-* alone — no vertical padding (py-12 inside h-32 left a 6px content box).
|
|
217
|
+
xs: "h-[28px] gap-[6px] px-pad-compact-x text-[12px] [&_svg]:size-[14px] [&_svg]:stroke-[1.75]",
|
|
218
|
+
sm: "h-[30px] gap-[6px] px-pad-compact-x text-body-sm [&_svg]:size-[16px]",
|
|
219
|
+
md: "h-[32px] gap-[6px] px-pad-default-x text-body-sm [&_svg]:size-[16px]",
|
|
220
|
+
lg: "h-[36px] gap-[var(--space-2)] px-pad-default-x text-[15px] [&_svg]:size-[18px]",
|
|
220
221
|
xl: "h-[40px] gap-[var(--space-2)] px-5 text-[15px] [&_svg]:size-[18px]",
|
|
221
|
-
default: "h-[32px] gap-[6px] px-pad-default-x
|
|
222
|
+
default: "h-[32px] gap-[6px] px-pad-default-x text-body-sm [&_svg]:size-[16px]",
|
|
222
223
|
icon: "size-[36px] p-0 [&_svg]:size-[18px]",
|
|
223
224
|
"icon-xs": "size-[32px] p-0 [&_svg]:size-[14px] [&_svg]:stroke-[1.75]"
|
|
224
225
|
}
|
|
@@ -403,13 +404,13 @@ var selectSurfaceClassNames = {
|
|
|
403
404
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
404
405
|
var inputVariants = cva2(
|
|
405
406
|
[
|
|
406
|
-
"flex rounded-[var(--radius-
|
|
407
|
+
"flex rounded-[var(--radius-md)] border",
|
|
407
408
|
"border-[var(--border)] text-foreground",
|
|
408
409
|
"placeholder:text-text-disabled",
|
|
409
410
|
"transition-[border-color,box-shadow] motion-reduce:transition-none",
|
|
410
411
|
"focus:outline-none focus:border-[var(--focus-ring)] focus:shadow-[0_0_0_1px_var(--focus-ring)]",
|
|
411
412
|
"disabled:cursor-not-allowed disabled:border-[var(--border-subtle)] disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled",
|
|
412
|
-
"read-only:border-[var(--border-subtle)] read-only:bg-[var(--bg-
|
|
413
|
+
"read-only:border-[var(--border-subtle)] read-only:bg-[var(--bg-inset)] read-only:focus:border-[var(--border-subtle)] read-only:focus:shadow-none",
|
|
413
414
|
"file:border-0 file:bg-transparent file:text-sm file:font-medium",
|
|
414
415
|
"data-[state=error]:border-[var(--error)] data-[state=error]:focus:shadow-[0_0_0_1px_var(--error)]",
|
|
415
416
|
"data-[state=success]:border-[var(--success)] data-[state=success]:focus:shadow-[0_0_0_1px_var(--success)]",
|
|
@@ -1125,14 +1126,14 @@ import { AlertCircle as AlertCircle2, CheckCircle2 as CheckCircle22 } from "luci
|
|
|
1125
1126
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1126
1127
|
var textareaVariants = cva4(
|
|
1127
1128
|
[
|
|
1128
|
-
"flex resize-y rounded-[var(--radius-
|
|
1129
|
+
"flex resize-y rounded-[var(--radius-md)] border",
|
|
1129
1130
|
"border-[var(--border)] text-foreground",
|
|
1130
1131
|
"px-pad-default-x py-pad-default-y text-sm leading-normal",
|
|
1131
1132
|
"placeholder:text-text-disabled",
|
|
1132
1133
|
"transition-[border-color,box-shadow] motion-reduce:transition-none",
|
|
1133
1134
|
"focus:outline-none focus:border-[var(--focus-ring)] focus:shadow-[0_0_0_1px_var(--focus-ring)]",
|
|
1134
1135
|
"disabled:cursor-not-allowed disabled:border-[var(--border-subtle)] disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled",
|
|
1135
|
-
"read-only:cursor-default read-only:border-[var(--border-subtle)] read-only:bg-[var(--bg-
|
|
1136
|
+
"read-only:cursor-default read-only:border-[var(--border-subtle)] read-only:bg-[var(--bg-inset)] read-only:text-text-secondary read-only:focus:border-[var(--border-subtle)] read-only:focus:shadow-none",
|
|
1136
1137
|
"data-[state=error]:border-[var(--error)] data-[state=error]:focus:shadow-[0_0_0_1px_var(--error)]",
|
|
1137
1138
|
"data-[state=success]:border-[var(--success)] data-[state=success]:focus:shadow-[0_0_0_1px_var(--success)]",
|
|
1138
1139
|
"aria-[invalid=true]:border-[var(--error)] aria-[invalid=true]:focus:shadow-[0_0_0_1px_var(--error)]",
|
|
@@ -1358,7 +1359,7 @@ import { Select as SelectPrimitive } from "radix-ui";
|
|
|
1358
1359
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1359
1360
|
var selectVariants = cva5(
|
|
1360
1361
|
[
|
|
1361
|
-
"group flex cursor-pointer items-center justify-between rounded-[var(--radius-
|
|
1362
|
+
"group flex cursor-pointer items-center justify-between rounded-[var(--radius-md)] border",
|
|
1362
1363
|
"border-[var(--border)] text-foreground",
|
|
1363
1364
|
"[border-color:var(--border)] [color:var(--text-primary)]",
|
|
1364
1365
|
"transition-[border-color,box-shadow,background-color,color] motion-reduce:transition-none",
|
|
@@ -2940,7 +2941,7 @@ var tabsListVariants = cva8(
|
|
|
2940
2941
|
variants: {
|
|
2941
2942
|
variant: {
|
|
2942
2943
|
line: "",
|
|
2943
|
-
contained: "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-
|
|
2944
|
+
contained: "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-inset)] p-[var(--space-1)]"
|
|
2944
2945
|
},
|
|
2945
2946
|
orientation: {
|
|
2946
2947
|
horizontal: "",
|
|
@@ -3012,7 +3013,7 @@ var tabsBadgeVariants = cva8(
|
|
|
3012
3013
|
[
|
|
3013
3014
|
"inline-flex h-[18px] min-w-[18px] items-center justify-center",
|
|
3014
3015
|
"rounded-[var(--radius-full)] border border-[var(--border-subtle)]",
|
|
3015
|
-
"bg-[var(--bg-
|
|
3016
|
+
"bg-[var(--bg-inset)] px-[var(--space-1)]",
|
|
3016
3017
|
"font-[family-name:var(--font-display)] text-xs font-semibold leading-none tabular-nums",
|
|
3017
3018
|
// R14 — Badge는 metadata, 추가 marker(filled wash)가 아니다. marker 종류는
|
|
3018
3019
|
// trigger underline 하나(active-state doctrine). single-hue-family: active 시 인접
|
|
@@ -3818,7 +3819,7 @@ var chipVariants = cva9(
|
|
|
3818
3819
|
{
|
|
3819
3820
|
pressed: true,
|
|
3820
3821
|
tone: "muted",
|
|
3821
|
-
className: "border-[var(--border-strong)] bg-[var(--bg-
|
|
3822
|
+
className: "border-[var(--border-strong)] bg-[var(--bg-inset)] text-text-secondary"
|
|
3822
3823
|
}
|
|
3823
3824
|
],
|
|
3824
3825
|
defaultVariants: {
|
|
@@ -3838,12 +3839,12 @@ var chipCountVariants = cva9(
|
|
|
3838
3839
|
{
|
|
3839
3840
|
variants: {
|
|
3840
3841
|
tone: {
|
|
3841
|
-
neutral: "bg-[var(--bg-
|
|
3842
|
+
neutral: "bg-[var(--bg-inset)] text-text-tertiary",
|
|
3842
3843
|
accent: "bg-[var(--accent-pop)] text-[var(--accent-on-fill)]",
|
|
3843
3844
|
success: "bg-[var(--success)] text-[var(--success-contrast)]",
|
|
3844
3845
|
warning: "bg-[var(--warning)] text-[var(--warning-contrast)]",
|
|
3845
3846
|
danger: "bg-[var(--error)] text-[var(--error-contrast)]",
|
|
3846
|
-
muted: "bg-[var(--bg-
|
|
3847
|
+
muted: "bg-[var(--bg-inset)] text-text-tertiary"
|
|
3847
3848
|
},
|
|
3848
3849
|
size: {
|
|
3849
3850
|
sm: "h-[var(--space-4)] text-xs",
|
|
@@ -3970,13 +3971,16 @@ var iconButtonVariants = cva10(
|
|
|
3970
3971
|
variant: {
|
|
3971
3972
|
ghost: "border-transparent bg-transparent text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
|
|
3972
3973
|
outline: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-text-secondary hover:border-[var(--border-strong)] hover:bg-[var(--action-hover)] hover:text-foreground",
|
|
3973
|
-
subtle: "border-transparent bg-[var(--bg-
|
|
3974
|
+
subtle: "border-transparent bg-[var(--bg-inset)] text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
|
|
3974
3975
|
danger: "border-transparent bg-[var(--error-bg)] text-[var(--error)] hover:bg-[var(--action-hover)]"
|
|
3975
3976
|
},
|
|
3977
|
+
// Hit area = 44px on every size. The ::before is absolutely positioned, so its
|
|
3978
|
+
// inset is measured from the padding box — inside the 1px border every variant
|
|
3979
|
+
// carries (transparent or not). Inset = (44 - (size - 2 × 1px border)) / 2.
|
|
3976
3980
|
size: {
|
|
3977
|
-
sm: "size-[28px] before:-inset-[
|
|
3978
|
-
md: "size-[32px] before:-inset-[
|
|
3979
|
-
lg: "size-[40px] before:-inset-[
|
|
3981
|
+
sm: "size-[28px] before:-inset-[9px]",
|
|
3982
|
+
md: "size-[32px] before:-inset-[7px]",
|
|
3983
|
+
lg: "size-[40px] before:-inset-[3px]"
|
|
3980
3984
|
},
|
|
3981
3985
|
pressed: {
|
|
3982
3986
|
true: "",
|
|
@@ -5327,7 +5331,7 @@ function SkeletonRows({
|
|
|
5327
5331
|
"div",
|
|
5328
5332
|
{
|
|
5329
5333
|
className: cn(
|
|
5330
|
-
"h-[14px] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-
|
|
5334
|
+
"h-[14px] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]",
|
|
5331
5335
|
columnIndex === 0 ? "w-[72%]" : column.align === "right" ? "ml-auto w-[54%]" : "w-[62%]"
|
|
5332
5336
|
)
|
|
5333
5337
|
}
|
|
@@ -5353,9 +5357,9 @@ function MobileSkeletonCards({ count }) {
|
|
|
5353
5357
|
"data-slot": "data-table-mobile-skeleton-card",
|
|
5354
5358
|
className: "flex flex-col gap-[var(--space-2)] border-t border-[var(--border-subtle)] px-[var(--space-4)] py-[var(--space-4)]",
|
|
5355
5359
|
children: [
|
|
5356
|
-
/* @__PURE__ */ jsx31("div", { className: "h-[14px] w-[72%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-
|
|
5357
|
-
/* @__PURE__ */ jsx31("div", { className: "h-[12px] w-[56%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-
|
|
5358
|
-
/* @__PURE__ */ jsx31("div", { className: "h-[12px] w-[64%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-
|
|
5360
|
+
/* @__PURE__ */ jsx31("div", { className: "h-[14px] w-[72%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
|
|
5361
|
+
/* @__PURE__ */ jsx31("div", { className: "h-[12px] w-[56%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
|
|
5362
|
+
/* @__PURE__ */ jsx31("div", { className: "h-[12px] w-[64%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" })
|
|
5359
5363
|
]
|
|
5360
5364
|
},
|
|
5361
5365
|
rowIndex
|
|
@@ -5363,6 +5367,271 @@ function MobileSkeletonCards({ count }) {
|
|
|
5363
5367
|
}
|
|
5364
5368
|
);
|
|
5365
5369
|
}
|
|
5370
|
+
var rowLinkHostClass = "relative [&_:is(a,button,input,select,textarea,label,[role=button],[role=checkbox]):not([data-slot=data-table-row-link])]:relative [&_:is(a,button,input,select,textarea,label,[role=button],[role=checkbox]):not([data-slot=data-table-row-link])]:z-[1]";
|
|
5371
|
+
var rowLinkClass = cn(
|
|
5372
|
+
"text-inherit no-underline outline-none after:absolute after:inset-0 after:content-['']",
|
|
5373
|
+
"focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-[var(--focus-ring)]"
|
|
5374
|
+
);
|
|
5375
|
+
function useActivationHandlers({ row, href, activatable, onActivate }) {
|
|
5376
|
+
return {
|
|
5377
|
+
onClick: (event) => {
|
|
5378
|
+
if (!activatable || isInteractiveTarget(event.target)) {
|
|
5379
|
+
return;
|
|
5380
|
+
}
|
|
5381
|
+
onActivate(row, href, event);
|
|
5382
|
+
},
|
|
5383
|
+
onKeyDown: (event) => {
|
|
5384
|
+
if (!activatable || isInteractiveTarget(event.target)) {
|
|
5385
|
+
return;
|
|
5386
|
+
}
|
|
5387
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
5388
|
+
event.preventDefault();
|
|
5389
|
+
onActivate(row, href, event);
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
};
|
|
5393
|
+
}
|
|
5394
|
+
function DataTableRowView({
|
|
5395
|
+
row,
|
|
5396
|
+
rowId,
|
|
5397
|
+
columns,
|
|
5398
|
+
selectable,
|
|
5399
|
+
selected,
|
|
5400
|
+
visuallySelected,
|
|
5401
|
+
href,
|
|
5402
|
+
activatable,
|
|
5403
|
+
LinkComponent,
|
|
5404
|
+
onToggle,
|
|
5405
|
+
onActivate,
|
|
5406
|
+
onRowContextMenu,
|
|
5407
|
+
gridTemplateColumns,
|
|
5408
|
+
ariaRowIndex
|
|
5409
|
+
}) {
|
|
5410
|
+
const linked = Boolean(LinkComponent && href);
|
|
5411
|
+
const handlers = useActivationHandlers({ row, href, activatable, onActivate });
|
|
5412
|
+
return /* @__PURE__ */ jsxs30(
|
|
5413
|
+
"div",
|
|
5414
|
+
{
|
|
5415
|
+
"data-slot": "data-table-row",
|
|
5416
|
+
"data-row-id": rowId,
|
|
5417
|
+
"data-href": href,
|
|
5418
|
+
role: "row",
|
|
5419
|
+
"aria-rowindex": ariaRowIndex,
|
|
5420
|
+
tabIndex: activatable ? 0 : void 0,
|
|
5421
|
+
className: cn(
|
|
5422
|
+
dataTableRowVariants({ interactive: activatable || linked, selected: visuallySelected }),
|
|
5423
|
+
linked ? rowLinkHostClass : null
|
|
5424
|
+
),
|
|
5425
|
+
style: { gridTemplateColumns },
|
|
5426
|
+
onContextMenu: (event) => onRowContextMenu?.(rowId, event),
|
|
5427
|
+
onClick: handlers.onClick,
|
|
5428
|
+
onKeyDown: handlers.onKeyDown,
|
|
5429
|
+
children: [
|
|
5430
|
+
selectable ? /* @__PURE__ */ jsx31("div", { role: "cell", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx31(
|
|
5431
|
+
Checkbox,
|
|
5432
|
+
{
|
|
5433
|
+
"aria-label": `${String(row[columns[0]?.key] ?? rowId)} \uD589 \uC120\uD0DD`,
|
|
5434
|
+
checked: selected,
|
|
5435
|
+
onCheckedChange: (nextChecked) => onToggle(rowId, nextChecked === true),
|
|
5436
|
+
children: /* @__PURE__ */ jsxs30("span", { className: "sr-only", children: [
|
|
5437
|
+
rowId,
|
|
5438
|
+
" \uD589 \uC120\uD0DD"
|
|
5439
|
+
] })
|
|
5440
|
+
}
|
|
5441
|
+
) }) : null,
|
|
5442
|
+
columns.map((column, columnIndex) => {
|
|
5443
|
+
const align = column.align ?? "left";
|
|
5444
|
+
const content = getRenderedCell(row, column);
|
|
5445
|
+
return /* @__PURE__ */ jsx31(
|
|
5446
|
+
"div",
|
|
5447
|
+
{
|
|
5448
|
+
"data-slot": "data-table-cell",
|
|
5449
|
+
role: "cell",
|
|
5450
|
+
className: cn(
|
|
5451
|
+
"flex min-w-0 items-center px-[var(--space-4)] py-[var(--space-2)]",
|
|
5452
|
+
alignmentClass[align],
|
|
5453
|
+
column.tabular ? "font-[family-name:var(--font-display)] tabular-nums" : null,
|
|
5454
|
+
align === "right" ? "text-text-tertiary" : null
|
|
5455
|
+
),
|
|
5456
|
+
children: /* @__PURE__ */ jsx31("span", { className: "min-w-0 truncate", children: linked && columnIndex === 0 && LinkComponent ? /* @__PURE__ */ jsx31(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: content }) : content })
|
|
5457
|
+
},
|
|
5458
|
+
column.key
|
|
5459
|
+
);
|
|
5460
|
+
})
|
|
5461
|
+
]
|
|
5462
|
+
}
|
|
5463
|
+
);
|
|
5464
|
+
}
|
|
5465
|
+
function DataTableMobileCardView({
|
|
5466
|
+
row,
|
|
5467
|
+
rowId,
|
|
5468
|
+
columns,
|
|
5469
|
+
selectable,
|
|
5470
|
+
selected,
|
|
5471
|
+
visuallySelected,
|
|
5472
|
+
href,
|
|
5473
|
+
activatable,
|
|
5474
|
+
LinkComponent,
|
|
5475
|
+
onToggle,
|
|
5476
|
+
onActivate,
|
|
5477
|
+
onRowContextMenu,
|
|
5478
|
+
ariaPosInSet,
|
|
5479
|
+
ariaSetSize
|
|
5480
|
+
}) {
|
|
5481
|
+
const linked = Boolean(LinkComponent && href);
|
|
5482
|
+
const handlers = useActivationHandlers({ row, href, activatable, onActivate });
|
|
5483
|
+
const primaryColumn = columns[0];
|
|
5484
|
+
const secondaryColumns = columns.slice(1);
|
|
5485
|
+
const primaryText = getAccessibleCellText(row, primaryColumn, rowId);
|
|
5486
|
+
const primaryLabel = primaryColumn ? getHeaderLabel(primaryColumn) : "\uD589";
|
|
5487
|
+
const primaryContent = primaryColumn ? getRenderedCell(row, primaryColumn) : primaryText;
|
|
5488
|
+
return /* @__PURE__ */ jsxs30(
|
|
5489
|
+
"div",
|
|
5490
|
+
{
|
|
5491
|
+
"data-slot": "data-table-mobile-card",
|
|
5492
|
+
"data-row-id": rowId,
|
|
5493
|
+
"data-href": href,
|
|
5494
|
+
role: "listitem",
|
|
5495
|
+
"aria-posinset": ariaPosInSet,
|
|
5496
|
+
"aria-setsize": ariaSetSize,
|
|
5497
|
+
tabIndex: activatable ? 0 : void 0,
|
|
5498
|
+
"aria-label": `${primaryLabel}: ${primaryText}`,
|
|
5499
|
+
className: cn(
|
|
5500
|
+
"flex min-w-0 flex-col gap-[var(--space-3)] border-t border-[var(--border-subtle)] px-[var(--space-4)] py-[var(--space-4)]",
|
|
5501
|
+
"text-body-sm leading-compact text-foreground transition-colors motion-reduce:transition-none",
|
|
5502
|
+
activatable || linked ? "cursor-pointer hover:bg-[var(--action-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--focus-ring)]" : null,
|
|
5503
|
+
visuallySelected ? "bg-[var(--action-selected)]" : null,
|
|
5504
|
+
linked ? rowLinkHostClass : null
|
|
5505
|
+
),
|
|
5506
|
+
onContextMenu: (event) => onRowContextMenu?.(rowId, event),
|
|
5507
|
+
onClick: handlers.onClick,
|
|
5508
|
+
onKeyDown: handlers.onKeyDown,
|
|
5509
|
+
children: [
|
|
5510
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex min-w-0 items-start gap-[var(--space-3)]", children: [
|
|
5511
|
+
selectable ? /* @__PURE__ */ jsx31("div", { "data-slot": "data-table-mobile-card-select", className: "shrink-0 pt-[2px]", children: /* @__PURE__ */ jsx31(
|
|
5512
|
+
Checkbox,
|
|
5513
|
+
{
|
|
5514
|
+
"aria-label": `${primaryText} \uBAA8\uBC14\uC77C \uCE74\uB4DC \uC120\uD0DD`,
|
|
5515
|
+
checked: selected,
|
|
5516
|
+
onCheckedChange: (nextChecked) => onToggle(rowId, nextChecked === true),
|
|
5517
|
+
children: /* @__PURE__ */ jsxs30("span", { className: "sr-only", children: [
|
|
5518
|
+
rowId,
|
|
5519
|
+
" \uBAA8\uBC14\uC77C \uCE74\uB4DC \uC120\uD0DD"
|
|
5520
|
+
] })
|
|
5521
|
+
}
|
|
5522
|
+
) }) : null,
|
|
5523
|
+
/* @__PURE__ */ jsx31(
|
|
5524
|
+
"div",
|
|
5525
|
+
{
|
|
5526
|
+
"data-slot": "data-table-mobile-card-primary",
|
|
5527
|
+
className: "min-w-0 flex-1 font-medium text-foreground",
|
|
5528
|
+
children: linked && LinkComponent ? /* @__PURE__ */ jsx31(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: primaryContent }) : primaryContent
|
|
5529
|
+
}
|
|
5530
|
+
)
|
|
5531
|
+
] }),
|
|
5532
|
+
secondaryColumns.length > 0 ? /* @__PURE__ */ jsx31("dl", { className: "grid min-w-0 gap-[var(--space-2)]", children: secondaryColumns.map((column) => {
|
|
5533
|
+
const align = column.align ?? "left";
|
|
5534
|
+
return /* @__PURE__ */ jsxs30(
|
|
5535
|
+
"div",
|
|
5536
|
+
{
|
|
5537
|
+
"data-slot": "data-table-mobile-card-field",
|
|
5538
|
+
className: "grid min-w-0 grid-cols-[minmax(0,0.42fr)_minmax(0,1fr)] gap-[var(--space-2)] text-[12px] leading-snug",
|
|
5539
|
+
children: [
|
|
5540
|
+
/* @__PURE__ */ jsx31("dt", { className: "min-w-0 text-text-tertiary", children: /* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header }) }),
|
|
5541
|
+
/* @__PURE__ */ jsx31(
|
|
5542
|
+
"dd",
|
|
5543
|
+
{
|
|
5544
|
+
className: cn(
|
|
5545
|
+
"min-w-0 text-text-secondary",
|
|
5546
|
+
alignmentClass[align],
|
|
5547
|
+
column.tabular ? "font-[family-name:var(--font-display)] tabular-nums" : null
|
|
5548
|
+
),
|
|
5549
|
+
children: /* @__PURE__ */ jsx31("span", { className: "min-w-0 truncate", children: getRenderedCell(row, column) })
|
|
5550
|
+
}
|
|
5551
|
+
)
|
|
5552
|
+
]
|
|
5553
|
+
},
|
|
5554
|
+
column.key
|
|
5555
|
+
);
|
|
5556
|
+
}) }) : null
|
|
5557
|
+
]
|
|
5558
|
+
}
|
|
5559
|
+
);
|
|
5560
|
+
}
|
|
5561
|
+
var MemoDataTableRow = React27.memo(DataTableRowView);
|
|
5562
|
+
var MemoDataTableMobileCard = React27.memo(DataTableMobileCardView);
|
|
5563
|
+
var useIsomorphicLayoutEffect = typeof window === "undefined" ? React27.useEffect : React27.useLayoutEffect;
|
|
5564
|
+
var VIRTUAL_DEFAULT_OVERSCAN = 8;
|
|
5565
|
+
var VIRTUAL_INITIAL_ROWS = 24;
|
|
5566
|
+
var VIRTUAL_FALLBACK_SIZE = { desktop: 48, mobile: 120 };
|
|
5567
|
+
function useVirtualWindow({
|
|
5568
|
+
enabled,
|
|
5569
|
+
count,
|
|
5570
|
+
overscan,
|
|
5571
|
+
desktopRef,
|
|
5572
|
+
desktopListRef,
|
|
5573
|
+
mobileListRef
|
|
5574
|
+
}) {
|
|
5575
|
+
const [win, setWin] = React27.useState({
|
|
5576
|
+
layout: null,
|
|
5577
|
+
start: 0,
|
|
5578
|
+
end: VIRTUAL_INITIAL_ROWS,
|
|
5579
|
+
size: 0
|
|
5580
|
+
});
|
|
5581
|
+
const measuredSize = React27.useRef({ desktop: 0, mobile: 0 });
|
|
5582
|
+
const update = React27.useRef(() => void 0);
|
|
5583
|
+
update.current = () => {
|
|
5584
|
+
if (!enabled) {
|
|
5585
|
+
return;
|
|
5586
|
+
}
|
|
5587
|
+
const desktop = desktopRef.current;
|
|
5588
|
+
const layout = desktop && window.getComputedStyle(desktop).display === "none" ? "mobile" : "desktop";
|
|
5589
|
+
const list = (layout === "desktop" ? desktopListRef : mobileListRef).current;
|
|
5590
|
+
const firstItem = list?.firstElementChild;
|
|
5591
|
+
const itemHeight = firstItem ? firstItem.getBoundingClientRect().height : 0;
|
|
5592
|
+
if (itemHeight > 0) {
|
|
5593
|
+
measuredSize.current[layout] = itemHeight;
|
|
5594
|
+
}
|
|
5595
|
+
const size = measuredSize.current[layout] || VIRTUAL_FALLBACK_SIZE[layout];
|
|
5596
|
+
let start = 0;
|
|
5597
|
+
let end = Math.min(count, VIRTUAL_INITIAL_ROWS);
|
|
5598
|
+
if (list) {
|
|
5599
|
+
const top = list.getBoundingClientRect().top;
|
|
5600
|
+
const viewport = window.innerHeight || document.documentElement.clientHeight;
|
|
5601
|
+
start = Math.min(count, Math.max(0, Math.floor(-top / size) - overscan));
|
|
5602
|
+
end = Math.min(count, Math.max(start, Math.ceil((viewport - top) / size) + overscan));
|
|
5603
|
+
}
|
|
5604
|
+
setWin(
|
|
5605
|
+
(prev) => prev.layout === layout && prev.start === start && prev.end === end && prev.size === size ? prev : { layout, start, end, size }
|
|
5606
|
+
);
|
|
5607
|
+
};
|
|
5608
|
+
useIsomorphicLayoutEffect(() => {
|
|
5609
|
+
update.current();
|
|
5610
|
+
});
|
|
5611
|
+
React27.useEffect(() => {
|
|
5612
|
+
if (!enabled) {
|
|
5613
|
+
return;
|
|
5614
|
+
}
|
|
5615
|
+
let frame = 0;
|
|
5616
|
+
const schedule = () => {
|
|
5617
|
+
if (frame) {
|
|
5618
|
+
return;
|
|
5619
|
+
}
|
|
5620
|
+
frame = window.requestAnimationFrame(() => {
|
|
5621
|
+
frame = 0;
|
|
5622
|
+
update.current();
|
|
5623
|
+
});
|
|
5624
|
+
};
|
|
5625
|
+
window.addEventListener("scroll", schedule, { capture: true, passive: true });
|
|
5626
|
+
window.addEventListener("resize", schedule);
|
|
5627
|
+
return () => {
|
|
5628
|
+
window.removeEventListener("scroll", schedule, { capture: true });
|
|
5629
|
+
window.removeEventListener("resize", schedule);
|
|
5630
|
+
window.cancelAnimationFrame(frame);
|
|
5631
|
+
};
|
|
5632
|
+
}, [enabled]);
|
|
5633
|
+
return win;
|
|
5634
|
+
}
|
|
5366
5635
|
function DataTableInner({
|
|
5367
5636
|
className,
|
|
5368
5637
|
density = "standard",
|
|
@@ -5380,18 +5649,32 @@ function DataTableInner({
|
|
|
5380
5649
|
loading = false,
|
|
5381
5650
|
emptyState,
|
|
5382
5651
|
rowHref,
|
|
5652
|
+
linkComponent,
|
|
5653
|
+
onRowClick,
|
|
5654
|
+
virtual,
|
|
5383
5655
|
skeletonRowCount = 8,
|
|
5384
5656
|
"aria-label": ariaLabel = "\uB370\uC774\uD130 \uD14C\uC774\uBE14",
|
|
5385
5657
|
...props
|
|
5386
5658
|
}, ref) {
|
|
5659
|
+
const virtualOptions = virtual ? virtual === true ? {} : virtual : null;
|
|
5660
|
+
const isVirtual = virtualOptions !== null;
|
|
5661
|
+
const desktopRef = React27.useRef(null);
|
|
5662
|
+
const desktopListRef = React27.useRef(null);
|
|
5663
|
+
const mobileListRef = React27.useRef(null);
|
|
5664
|
+
const virtualWindow = useVirtualWindow({
|
|
5665
|
+
enabled: isVirtual,
|
|
5666
|
+
count: data.length,
|
|
5667
|
+
overscan: virtualOptions?.overscan ?? VIRTUAL_DEFAULT_OVERSCAN,
|
|
5668
|
+
desktopRef,
|
|
5669
|
+
desktopListRef,
|
|
5670
|
+
mobileListRef
|
|
5671
|
+
});
|
|
5387
5672
|
const resolvedSelectedIds = selectedIds ?? /* @__PURE__ */ new Set();
|
|
5388
5673
|
const rowIds = data.map((row) => getRowId(row, keyField));
|
|
5389
5674
|
const selectedCount = rowIds.filter((id) => resolvedSelectedIds.has(id)).length;
|
|
5390
5675
|
const allVisibleRowsSelected = rowIds.length > 0 && selectedCount === rowIds.length;
|
|
5391
5676
|
const partiallySelected = selectedCount > 0 && !allVisibleRowsSelected;
|
|
5392
5677
|
const gridTemplateColumns = getGridTemplate(columns, selectable);
|
|
5393
|
-
const primaryColumn = columns[0];
|
|
5394
|
-
const secondaryColumns = columns.slice(1);
|
|
5395
5678
|
const emitSelection = (nextIds) => {
|
|
5396
5679
|
onSelectionChange?.(nextIds);
|
|
5397
5680
|
};
|
|
@@ -5413,12 +5696,81 @@ function DataTableInner({
|
|
|
5413
5696
|
}
|
|
5414
5697
|
emitSelection(nextIds);
|
|
5415
5698
|
};
|
|
5699
|
+
const activateRow = (row, href, event) => {
|
|
5700
|
+
if (onRowClick) {
|
|
5701
|
+
onRowClick(row, event);
|
|
5702
|
+
} else if (href) {
|
|
5703
|
+
window.location.assign(href);
|
|
5704
|
+
}
|
|
5705
|
+
};
|
|
5706
|
+
const latestHandlers = React27.useRef({ toggleRow, activateRow, onRowContextMenu });
|
|
5707
|
+
useIsomorphicLayoutEffect(() => {
|
|
5708
|
+
latestHandlers.current = { toggleRow, activateRow, onRowContextMenu };
|
|
5709
|
+
});
|
|
5710
|
+
const stableToggleRow = React27.useCallback(
|
|
5711
|
+
(id, checked) => latestHandlers.current.toggleRow(id, checked),
|
|
5712
|
+
[]
|
|
5713
|
+
);
|
|
5714
|
+
const stableActivateRow = React27.useCallback(
|
|
5715
|
+
(row, href, event) => latestHandlers.current.activateRow(row, href, event),
|
|
5716
|
+
[]
|
|
5717
|
+
);
|
|
5718
|
+
const stableRowContextMenu = React27.useCallback(
|
|
5719
|
+
(rowId, event) => latestHandlers.current.onRowContextMenu?.(rowId, event),
|
|
5720
|
+
[]
|
|
5721
|
+
);
|
|
5722
|
+
const getItemProps = (row) => {
|
|
5723
|
+
const rowId = getRowId(row, keyField);
|
|
5724
|
+
const selected = resolvedSelectedIds.has(rowId);
|
|
5725
|
+
const href = rowHref?.(row);
|
|
5726
|
+
const linked = Boolean(linkComponent && href);
|
|
5727
|
+
return {
|
|
5728
|
+
row,
|
|
5729
|
+
rowId,
|
|
5730
|
+
columns,
|
|
5731
|
+
selectable,
|
|
5732
|
+
selected,
|
|
5733
|
+
visuallySelected: selected || rowId === activeRowId,
|
|
5734
|
+
href,
|
|
5735
|
+
activatable: !linked && Boolean(href || onRowClick),
|
|
5736
|
+
LinkComponent: linkComponent,
|
|
5737
|
+
onToggle: isVirtual ? stableToggleRow : toggleRow,
|
|
5738
|
+
onActivate: isVirtual ? stableActivateRow : activateRow,
|
|
5739
|
+
onRowContextMenu: isVirtual ? stableRowContextMenu : onRowContextMenu
|
|
5740
|
+
};
|
|
5741
|
+
};
|
|
5742
|
+
const sliceFor = (layout) => {
|
|
5743
|
+
if (!isVirtual) {
|
|
5744
|
+
return { rows: data, start: 0, style: void 0 };
|
|
5745
|
+
}
|
|
5746
|
+
if (virtualWindow.layout !== null && virtualWindow.layout !== layout) {
|
|
5747
|
+
return { rows: [], start: 0, style: void 0 };
|
|
5748
|
+
}
|
|
5749
|
+
const size = virtualWindow.size || VIRTUAL_FALLBACK_SIZE[layout];
|
|
5750
|
+
const end = Math.min(data.length, virtualWindow.end);
|
|
5751
|
+
const start = Math.min(virtualWindow.start, end);
|
|
5752
|
+
return {
|
|
5753
|
+
rows: data.slice(start, end),
|
|
5754
|
+
start,
|
|
5755
|
+
style: { paddingTop: start * size, paddingBottom: (data.length - end) * size }
|
|
5756
|
+
};
|
|
5757
|
+
};
|
|
5758
|
+
const desktopSlice = sliceFor("desktop");
|
|
5759
|
+
const mobileSlice = sliceFor("mobile");
|
|
5760
|
+
const RowComponent = isVirtual ? MemoDataTableRow : DataTableRowView;
|
|
5761
|
+
const CardComponent = isVirtual ? MemoDataTableMobileCard : DataTableMobileCardView;
|
|
5416
5762
|
return /* @__PURE__ */ jsxs30(
|
|
5417
5763
|
"div",
|
|
5418
5764
|
{
|
|
5419
5765
|
ref,
|
|
5420
5766
|
"data-slot": "data-table",
|
|
5421
|
-
className: cn(
|
|
5767
|
+
className: cn(
|
|
5768
|
+
dataTableVariants({ density, surface }),
|
|
5769
|
+
// clip, not hidden: keeps the rounded corners without becoming the sticky
|
|
5770
|
+
// header's scroll container.
|
|
5771
|
+
isVirtual && "overflow-clip",
|
|
5772
|
+
className
|
|
5773
|
+
),
|
|
5422
5774
|
...props,
|
|
5423
5775
|
children: [
|
|
5424
5776
|
selectable ? /* @__PURE__ */ jsx31(
|
|
@@ -5439,149 +5791,108 @@ function DataTableInner({
|
|
|
5439
5791
|
children: /* @__PURE__ */ jsx31("div", { className: "h-full w-1/3 animate-pulse bg-[var(--primary)]" })
|
|
5440
5792
|
}
|
|
5441
5793
|
) : null,
|
|
5442
|
-
/* @__PURE__ */ jsx31("div", { "data-slot": "data-table-desktop", className: "max-md:hidden md:block", children: /* @__PURE__ */ jsxs30(
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5794
|
+
/* @__PURE__ */ jsx31("div", { ref: desktopRef, "data-slot": "data-table-desktop", className: "max-md:hidden md:block", children: /* @__PURE__ */ jsxs30(
|
|
5795
|
+
"div",
|
|
5796
|
+
{
|
|
5797
|
+
role: "table",
|
|
5798
|
+
"aria-label": ariaLabel,
|
|
5799
|
+
"aria-rowcount": isVirtual && data.length > 0 ? data.length + 1 : void 0,
|
|
5800
|
+
children: [
|
|
5801
|
+
/* @__PURE__ */ jsxs30(
|
|
5802
|
+
"div",
|
|
5803
|
+
{
|
|
5804
|
+
"data-slot": "data-table-header",
|
|
5805
|
+
role: "row",
|
|
5806
|
+
className: cn(
|
|
5807
|
+
"grid min-h-[40px] items-center bg-[var(--bg-raised)] text-[12px] font-semibold uppercase leading-snug text-text-tertiary",
|
|
5808
|
+
// Virtual lists are long: the header sticks inside the scroll container,
|
|
5809
|
+
// below an inline BulkActionBar band (40px, --z-sticky) rendered before
|
|
5810
|
+
// the table — band on top, header under it, rows beneath both.
|
|
5811
|
+
isVirtual && "sticky top-0 z-[2] [[data-slot=bulk-action-bar][data-placement=inline]:not([data-state=idle])~[data-slot=data-table]_&]:top-[40px]"
|
|
5812
|
+
),
|
|
5813
|
+
style: { gridTemplateColumns },
|
|
5814
|
+
children: [
|
|
5815
|
+
selectable ? /* @__PURE__ */ jsx31("div", { role: "columnheader", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx31(
|
|
5816
|
+
Checkbox,
|
|
5817
|
+
{
|
|
5818
|
+
"aria-label": "\uC804\uCCB4 \uD589 \uC120\uD0DD",
|
|
5819
|
+
checked: partiallySelected ? "indeterminate" : allVisibleRowsSelected,
|
|
5820
|
+
onCheckedChange: (nextChecked) => toggleAllRows(nextChecked === true),
|
|
5821
|
+
children: /* @__PURE__ */ jsx31("span", { className: "sr-only", children: "\uC804\uCCB4 \uD589 \uC120\uD0DD" })
|
|
5822
|
+
}
|
|
5823
|
+
) }) : null,
|
|
5824
|
+
columns.map((column) => {
|
|
5825
|
+
const align = column.align ?? "left";
|
|
5826
|
+
const nextSort = getNextSort(sortBy, column.key);
|
|
5827
|
+
const ariaSort = sortBy?.key === column.key ? sortBy.dir === "asc" ? "ascending" : "descending" : void 0;
|
|
5828
|
+
return /* @__PURE__ */ jsx31(
|
|
5829
|
+
"div",
|
|
5475
5830
|
{
|
|
5476
|
-
|
|
5831
|
+
role: "columnheader",
|
|
5832
|
+
"aria-sort": ariaSort,
|
|
5477
5833
|
className: cn(
|
|
5478
|
-
"
|
|
5479
|
-
|
|
5480
|
-
"hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]"
|
|
5834
|
+
"flex min-w-0 items-center gap-[var(--space-1)] px-[var(--space-4)] py-[var(--space-2)]",
|
|
5835
|
+
alignmentClass[align]
|
|
5481
5836
|
),
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
{
|
|
5525
|
-
"data-slot": "data-table-row",
|
|
5526
|
-
"data-row-id": rowId,
|
|
5527
|
-
"data-href": href,
|
|
5528
|
-
role: "row",
|
|
5529
|
-
tabIndex: href ? 0 : void 0,
|
|
5530
|
-
className: cn(dataTableRowVariants({ interactive: Boolean(href), selected: visuallySelected })),
|
|
5531
|
-
style: { gridTemplateColumns },
|
|
5532
|
-
onContextMenu: (event) => onRowContextMenu?.(rowId, event),
|
|
5533
|
-
onClick: (event) => {
|
|
5534
|
-
if (!href || isInteractiveTarget(event.target)) {
|
|
5535
|
-
return;
|
|
5536
|
-
}
|
|
5537
|
-
window.location.assign(href);
|
|
5538
|
-
},
|
|
5539
|
-
onKeyDown: (event) => {
|
|
5540
|
-
if (!href || isInteractiveTarget(event.target)) {
|
|
5541
|
-
return;
|
|
5542
|
-
}
|
|
5543
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
5544
|
-
event.preventDefault();
|
|
5545
|
-
window.location.assign(href);
|
|
5837
|
+
children: column.sortable ? /* @__PURE__ */ jsxs30(
|
|
5838
|
+
"button",
|
|
5839
|
+
{
|
|
5840
|
+
type: "button",
|
|
5841
|
+
className: cn(
|
|
5842
|
+
"inline-flex min-w-0 cursor-pointer items-center gap-[var(--space-1)] rounded-[var(--radius-xs)]",
|
|
5843
|
+
"text-inherit transition-colors motion-reduce:transition-none",
|
|
5844
|
+
"hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]"
|
|
5845
|
+
),
|
|
5846
|
+
onClick: () => onSortChange?.(column.key, nextSort),
|
|
5847
|
+
children: [
|
|
5848
|
+
/* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header }),
|
|
5849
|
+
/* @__PURE__ */ jsx31(SortIcon, { sort: sortBy, columnKey: column.key })
|
|
5850
|
+
]
|
|
5851
|
+
}
|
|
5852
|
+
) : /* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header })
|
|
5853
|
+
},
|
|
5854
|
+
column.key
|
|
5855
|
+
);
|
|
5856
|
+
})
|
|
5857
|
+
]
|
|
5858
|
+
}
|
|
5859
|
+
),
|
|
5860
|
+
loading && data.length === 0 ? /* @__PURE__ */ jsx31(
|
|
5861
|
+
SkeletonRows,
|
|
5862
|
+
{
|
|
5863
|
+
columns,
|
|
5864
|
+
selectable,
|
|
5865
|
+
gridTemplateColumns,
|
|
5866
|
+
count: skeletonRowCount
|
|
5867
|
+
}
|
|
5868
|
+
) : data.length === 0 ? (
|
|
5869
|
+
/* role="table" 직계 자식은 row/rowgroup이어야 한다. data-slot과 테두리는
|
|
5870
|
+
그대로 유지해 시각 계약을 깨지 않는다(빈 상태에서도 표가 테두리를 그린다). */
|
|
5871
|
+
/* @__PURE__ */ jsx31("div", { role: "rowgroup", children: /* @__PURE__ */ jsx31("div", { role: "row", children: /* @__PURE__ */ jsx31(
|
|
5872
|
+
"div",
|
|
5873
|
+
{
|
|
5874
|
+
role: "cell",
|
|
5875
|
+
"aria-colindex": 1,
|
|
5876
|
+
"data-slot": "data-table-empty",
|
|
5877
|
+
className: "border-t border-[var(--border-subtle)] p-[var(--space-4)]",
|
|
5878
|
+
children: emptyState
|
|
5546
5879
|
}
|
|
5547
|
-
}
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
return /* @__PURE__ */ jsx31(
|
|
5564
|
-
"div",
|
|
5565
|
-
{
|
|
5566
|
-
"data-slot": "data-table-cell",
|
|
5567
|
-
role: "cell",
|
|
5568
|
-
className: cn(
|
|
5569
|
-
"flex min-w-0 items-center px-[var(--space-4)] py-[var(--space-2)]",
|
|
5570
|
-
alignmentClass[align],
|
|
5571
|
-
column.tabular ? "font-[family-name:var(--font-display)] tabular-nums" : null,
|
|
5572
|
-
align === "right" ? "text-text-tertiary" : null
|
|
5573
|
-
),
|
|
5574
|
-
children: /* @__PURE__ */ jsx31("span", { className: "min-w-0 truncate", children: getRenderedCell(row, column) })
|
|
5575
|
-
},
|
|
5576
|
-
column.key
|
|
5577
|
-
);
|
|
5578
|
-
})
|
|
5579
|
-
]
|
|
5580
|
-
},
|
|
5581
|
-
rowId
|
|
5582
|
-
);
|
|
5583
|
-
}) })
|
|
5584
|
-
] }) }),
|
|
5880
|
+
) }) })
|
|
5881
|
+
) : /* @__PURE__ */ jsx31("div", { ref: desktopListRef, role: "rowgroup", style: desktopSlice.style, children: desktopSlice.rows.map((row, index) => {
|
|
5882
|
+
const itemProps = getItemProps(row);
|
|
5883
|
+
return /* @__PURE__ */ jsx31(
|
|
5884
|
+
RowComponent,
|
|
5885
|
+
{
|
|
5886
|
+
...itemProps,
|
|
5887
|
+
gridTemplateColumns,
|
|
5888
|
+
ariaRowIndex: isVirtual ? desktopSlice.start + index + 2 : void 0
|
|
5889
|
+
},
|
|
5890
|
+
itemProps.rowId
|
|
5891
|
+
);
|
|
5892
|
+
}) })
|
|
5893
|
+
]
|
|
5894
|
+
}
|
|
5895
|
+
) }),
|
|
5585
5896
|
/* @__PURE__ */ jsx31(
|
|
5586
5897
|
MobileSortControls,
|
|
5587
5898
|
{
|
|
@@ -5602,99 +5913,22 @@ function DataTableInner({
|
|
|
5602
5913
|
) : /* @__PURE__ */ jsx31(
|
|
5603
5914
|
"div",
|
|
5604
5915
|
{
|
|
5916
|
+
ref: mobileListRef,
|
|
5605
5917
|
"data-slot": "data-table-mobile-list",
|
|
5606
5918
|
role: "list",
|
|
5607
5919
|
"aria-label": `${ariaLabel} \uBAA8\uBC14\uC77C \uCE74\uB4DC \uBAA9\uB85D`,
|
|
5608
5920
|
className: "md:hidden",
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
const
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
const primaryText = getAccessibleCellText(row, primaryColumn, rowId);
|
|
5615
|
-
const primaryLabel = primaryColumn ? getHeaderLabel(primaryColumn) : "\uD589";
|
|
5616
|
-
return /* @__PURE__ */ jsxs30(
|
|
5617
|
-
"div",
|
|
5921
|
+
style: mobileSlice.style,
|
|
5922
|
+
children: mobileSlice.rows.map((row, index) => {
|
|
5923
|
+
const itemProps = getItemProps(row);
|
|
5924
|
+
return /* @__PURE__ */ jsx31(
|
|
5925
|
+
CardComponent,
|
|
5618
5926
|
{
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
role: "listitem",
|
|
5623
|
-
tabIndex: href ? 0 : void 0,
|
|
5624
|
-
"aria-label": `${primaryLabel}: ${primaryText}`,
|
|
5625
|
-
className: cn(
|
|
5626
|
-
"flex min-w-0 flex-col gap-[var(--space-3)] border-t border-[var(--border-subtle)] px-[var(--space-4)] py-[var(--space-4)]",
|
|
5627
|
-
"text-body-sm leading-compact text-foreground transition-colors motion-reduce:transition-none",
|
|
5628
|
-
href ? "cursor-pointer hover:bg-[var(--action-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--focus-ring)]" : null,
|
|
5629
|
-
visuallySelected ? "bg-[var(--action-selected)]" : null
|
|
5630
|
-
),
|
|
5631
|
-
onContextMenu: (event) => onRowContextMenu?.(rowId, event),
|
|
5632
|
-
onClick: (event) => {
|
|
5633
|
-
if (!href || isInteractiveTarget(event.target)) {
|
|
5634
|
-
return;
|
|
5635
|
-
}
|
|
5636
|
-
window.location.assign(href);
|
|
5637
|
-
},
|
|
5638
|
-
onKeyDown: (event) => {
|
|
5639
|
-
if (!href || isInteractiveTarget(event.target)) {
|
|
5640
|
-
return;
|
|
5641
|
-
}
|
|
5642
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
5643
|
-
event.preventDefault();
|
|
5644
|
-
window.location.assign(href);
|
|
5645
|
-
}
|
|
5646
|
-
},
|
|
5647
|
-
children: [
|
|
5648
|
-
/* @__PURE__ */ jsxs30("div", { className: "flex min-w-0 items-start gap-[var(--space-3)]", children: [
|
|
5649
|
-
selectable ? /* @__PURE__ */ jsx31("div", { "data-slot": "data-table-mobile-card-select", className: "shrink-0 pt-[2px]", children: /* @__PURE__ */ jsx31(
|
|
5650
|
-
Checkbox,
|
|
5651
|
-
{
|
|
5652
|
-
"aria-label": `${primaryText} \uBAA8\uBC14\uC77C \uCE74\uB4DC \uC120\uD0DD`,
|
|
5653
|
-
checked: selected,
|
|
5654
|
-
onCheckedChange: (nextChecked) => toggleRow(rowId, nextChecked === true),
|
|
5655
|
-
children: /* @__PURE__ */ jsxs30("span", { className: "sr-only", children: [
|
|
5656
|
-
rowId,
|
|
5657
|
-
" \uBAA8\uBC14\uC77C \uCE74\uB4DC \uC120\uD0DD"
|
|
5658
|
-
] })
|
|
5659
|
-
}
|
|
5660
|
-
) }) : null,
|
|
5661
|
-
/* @__PURE__ */ jsx31(
|
|
5662
|
-
"div",
|
|
5663
|
-
{
|
|
5664
|
-
"data-slot": "data-table-mobile-card-primary",
|
|
5665
|
-
className: "min-w-0 flex-1 font-medium text-foreground",
|
|
5666
|
-
children: primaryColumn ? getRenderedCell(row, primaryColumn) : primaryText
|
|
5667
|
-
}
|
|
5668
|
-
)
|
|
5669
|
-
] }),
|
|
5670
|
-
secondaryColumns.length > 0 ? /* @__PURE__ */ jsx31("dl", { className: "grid min-w-0 gap-[var(--space-2)]", children: secondaryColumns.map((column) => {
|
|
5671
|
-
const align = column.align ?? "left";
|
|
5672
|
-
return /* @__PURE__ */ jsxs30(
|
|
5673
|
-
"div",
|
|
5674
|
-
{
|
|
5675
|
-
"data-slot": "data-table-mobile-card-field",
|
|
5676
|
-
className: "grid min-w-0 grid-cols-[minmax(0,0.42fr)_minmax(0,1fr)] gap-[var(--space-2)] text-[12px] leading-snug",
|
|
5677
|
-
children: [
|
|
5678
|
-
/* @__PURE__ */ jsx31("dt", { className: "min-w-0 text-text-tertiary", children: /* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header }) }),
|
|
5679
|
-
/* @__PURE__ */ jsx31(
|
|
5680
|
-
"dd",
|
|
5681
|
-
{
|
|
5682
|
-
className: cn(
|
|
5683
|
-
"min-w-0 text-text-secondary",
|
|
5684
|
-
alignmentClass[align],
|
|
5685
|
-
column.tabular ? "font-[family-name:var(--font-display)] tabular-nums" : null
|
|
5686
|
-
),
|
|
5687
|
-
children: /* @__PURE__ */ jsx31("span", { className: "min-w-0 truncate", children: getRenderedCell(row, column) })
|
|
5688
|
-
}
|
|
5689
|
-
)
|
|
5690
|
-
]
|
|
5691
|
-
},
|
|
5692
|
-
column.key
|
|
5693
|
-
);
|
|
5694
|
-
}) }) : null
|
|
5695
|
-
]
|
|
5927
|
+
...itemProps,
|
|
5928
|
+
ariaPosInSet: isVirtual ? mobileSlice.start + index + 1 : void 0,
|
|
5929
|
+
ariaSetSize: isVirtual ? data.length : void 0
|
|
5696
5930
|
},
|
|
5697
|
-
rowId
|
|
5931
|
+
itemProps.rowId
|
|
5698
5932
|
);
|
|
5699
5933
|
})
|
|
5700
5934
|
}
|
|
@@ -5988,6 +6222,7 @@ function ContextMenu({
|
|
|
5988
6222
|
}
|
|
5989
6223
|
|
|
5990
6224
|
// src/components/ui/bulk-action-bar.tsx
|
|
6225
|
+
import * as React28 from "react";
|
|
5991
6226
|
import { X as X3 } from "lucide-react";
|
|
5992
6227
|
import { jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5993
6228
|
function ActionButton({ action }) {
|
|
@@ -6077,18 +6312,228 @@ function ClearButton({ onClear }) {
|
|
|
6077
6312
|
}
|
|
6078
6313
|
);
|
|
6079
6314
|
}
|
|
6315
|
+
var INLINE_HEIGHT = 40;
|
|
6316
|
+
var floatingStyle = {
|
|
6317
|
+
position: "sticky",
|
|
6318
|
+
bottom: "calc(var(--space-4) + env(safe-area-inset-bottom))",
|
|
6319
|
+
zIndex: 1100,
|
|
6320
|
+
margin: "0 auto",
|
|
6321
|
+
display: "flex",
|
|
6322
|
+
minHeight: 32,
|
|
6323
|
+
width: "fit-content",
|
|
6324
|
+
maxWidth: "calc(100% - var(--space-8))",
|
|
6325
|
+
alignItems: "center",
|
|
6326
|
+
gap: "var(--space-2)",
|
|
6327
|
+
borderRadius: 9999,
|
|
6328
|
+
border: "1px solid var(--border)",
|
|
6329
|
+
background: "var(--bg-raised)",
|
|
6330
|
+
padding: "var(--space-1) var(--space-2)",
|
|
6331
|
+
boxShadow: "var(--shadow-8)"
|
|
6332
|
+
};
|
|
6333
|
+
var inlineStyle = {
|
|
6334
|
+
position: "sticky",
|
|
6335
|
+
top: 0,
|
|
6336
|
+
zIndex: "var(--z-sticky)",
|
|
6337
|
+
display: "flex",
|
|
6338
|
+
boxSizing: "border-box",
|
|
6339
|
+
height: INLINE_HEIGHT,
|
|
6340
|
+
alignItems: "center",
|
|
6341
|
+
gap: "var(--space-2)",
|
|
6342
|
+
borderRadius: "var(--radius-md)",
|
|
6343
|
+
border: "1px solid var(--border)",
|
|
6344
|
+
background: "var(--bg-surface)",
|
|
6345
|
+
padding: "0 var(--space-1) 0 var(--space-3)",
|
|
6346
|
+
boxShadow: "var(--shadow-2)",
|
|
6347
|
+
fontFamily: "var(--font-sans)",
|
|
6348
|
+
fontSize: 13,
|
|
6349
|
+
fontVariantNumeric: "tabular-nums"
|
|
6350
|
+
};
|
|
6351
|
+
var idleLineStyle = {
|
|
6352
|
+
display: "flex",
|
|
6353
|
+
boxSizing: "border-box",
|
|
6354
|
+
height: INLINE_HEIGHT,
|
|
6355
|
+
overflow: "hidden",
|
|
6356
|
+
alignItems: "center",
|
|
6357
|
+
columnGap: "var(--space-3)",
|
|
6358
|
+
whiteSpace: "nowrap",
|
|
6359
|
+
fontFamily: "var(--font-sans)",
|
|
6360
|
+
fontSize: 13,
|
|
6361
|
+
fontVariantNumeric: "tabular-nums",
|
|
6362
|
+
color: "var(--text-secondary)"
|
|
6363
|
+
};
|
|
6364
|
+
var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React28.useEffect : React28.useLayoutEffect;
|
|
6365
|
+
function useCompactSummary(slot, enabled) {
|
|
6366
|
+
const [fullWidth, setFullWidth] = React28.useState(null);
|
|
6367
|
+
const measure = React28.useCallback(() => {
|
|
6368
|
+
if (!slot) return;
|
|
6369
|
+
setFullWidth((prev) => {
|
|
6370
|
+
if (prev === null) return slot.scrollWidth > slot.clientWidth ? slot.scrollWidth : null;
|
|
6371
|
+
return slot.clientWidth >= prev ? null : prev;
|
|
6372
|
+
});
|
|
6373
|
+
}, [slot]);
|
|
6374
|
+
useIsomorphicLayoutEffect2(() => {
|
|
6375
|
+
if (enabled) measure();
|
|
6376
|
+
});
|
|
6377
|
+
React28.useEffect(() => {
|
|
6378
|
+
if (!enabled || !slot || typeof ResizeObserver === "undefined") return;
|
|
6379
|
+
const observer = new ResizeObserver(measure);
|
|
6380
|
+
observer.observe(slot);
|
|
6381
|
+
return () => observer.disconnect();
|
|
6382
|
+
}, [enabled, slot, measure]);
|
|
6383
|
+
return enabled && fullWidth !== null;
|
|
6384
|
+
}
|
|
6080
6385
|
function BulkActionBar({
|
|
6081
6386
|
count,
|
|
6082
6387
|
actions,
|
|
6083
6388
|
onClear,
|
|
6084
6389
|
emptyHint,
|
|
6390
|
+
placement = "floating",
|
|
6391
|
+
unit = "\uAC1C",
|
|
6392
|
+
summary,
|
|
6393
|
+
compactSummary,
|
|
6394
|
+
idleContent,
|
|
6085
6395
|
className,
|
|
6086
6396
|
style,
|
|
6087
6397
|
...props
|
|
6088
6398
|
}) {
|
|
6399
|
+
const inline = placement === "inline";
|
|
6400
|
+
const [summaryElement, setSummaryElement] = React28.useState(null);
|
|
6401
|
+
const compact = useCompactSummary(
|
|
6402
|
+
summaryElement,
|
|
6403
|
+
inline && compactSummary !== void 0 && compactSummary !== null
|
|
6404
|
+
);
|
|
6405
|
+
if (count === 0 && idleContent !== void 0) {
|
|
6406
|
+
return /* @__PURE__ */ jsx34(
|
|
6407
|
+
"div",
|
|
6408
|
+
{
|
|
6409
|
+
role: "status",
|
|
6410
|
+
"data-slot": "bulk-action-bar",
|
|
6411
|
+
"data-placement": placement,
|
|
6412
|
+
"data-state": "idle",
|
|
6413
|
+
className,
|
|
6414
|
+
style: { ...idleLineStyle, ...style },
|
|
6415
|
+
...props,
|
|
6416
|
+
children: idleContent
|
|
6417
|
+
}
|
|
6418
|
+
);
|
|
6419
|
+
}
|
|
6089
6420
|
if (count === 0 && emptyHint === void 0) {
|
|
6090
6421
|
return null;
|
|
6091
6422
|
}
|
|
6423
|
+
const countLabel = /* @__PURE__ */ jsx34(
|
|
6424
|
+
"span",
|
|
6425
|
+
{
|
|
6426
|
+
"data-slot": "bulk-action-bar-count",
|
|
6427
|
+
style: {
|
|
6428
|
+
paddingLeft: inline ? void 0 : "var(--space-2)",
|
|
6429
|
+
paddingRight: "var(--space-1)",
|
|
6430
|
+
fontFamily: "var(--font-sans)",
|
|
6431
|
+
fontSize: 13,
|
|
6432
|
+
fontWeight: inline ? 600 : 500,
|
|
6433
|
+
fontVariantNumeric: "tabular-nums",
|
|
6434
|
+
color: "var(--text-primary)",
|
|
6435
|
+
whiteSpace: "nowrap"
|
|
6436
|
+
},
|
|
6437
|
+
children: count > 0 ? `${count.toLocaleString("ko-KR")}${unit} \uC120\uD0DD\uB428` : emptyHint
|
|
6438
|
+
}
|
|
6439
|
+
);
|
|
6440
|
+
const summarySlot = summary !== void 0 && summary !== null ? /* @__PURE__ */ jsx34(
|
|
6441
|
+
"span",
|
|
6442
|
+
{
|
|
6443
|
+
ref: setSummaryElement,
|
|
6444
|
+
"data-slot": "bulk-action-bar-summary",
|
|
6445
|
+
style: {
|
|
6446
|
+
display: inline ? "flex" : "inline-flex",
|
|
6447
|
+
minWidth: 0,
|
|
6448
|
+
alignItems: "center",
|
|
6449
|
+
columnGap: "var(--space-3)",
|
|
6450
|
+
fontFamily: "var(--font-sans)",
|
|
6451
|
+
fontSize: 13,
|
|
6452
|
+
color: "var(--text-secondary)",
|
|
6453
|
+
...inline ? (
|
|
6454
|
+
// inline-size containment: the summary never widens the band's parent. The
|
|
6455
|
+
// slot is full-height with 3px side gutters so focus rings are not clipped.
|
|
6456
|
+
{
|
|
6457
|
+
flex: "1 1 0",
|
|
6458
|
+
alignSelf: "stretch",
|
|
6459
|
+
margin: "0 -3px",
|
|
6460
|
+
padding: "0 3px",
|
|
6461
|
+
overflow: "hidden",
|
|
6462
|
+
whiteSpace: "nowrap",
|
|
6463
|
+
contain: "inline-size"
|
|
6464
|
+
}
|
|
6465
|
+
) : { flexWrap: "wrap", wordBreak: "keep-all" }
|
|
6466
|
+
},
|
|
6467
|
+
children: compact ? compactSummary : summary
|
|
6468
|
+
}
|
|
6469
|
+
) : null;
|
|
6470
|
+
const actionGroup = /* @__PURE__ */ jsx34(
|
|
6471
|
+
"div",
|
|
6472
|
+
{
|
|
6473
|
+
"data-slot": "bulk-action-bar-actions",
|
|
6474
|
+
style: {
|
|
6475
|
+
display: "flex",
|
|
6476
|
+
minWidth: 0,
|
|
6477
|
+
flexWrap: inline ? "nowrap" : "wrap",
|
|
6478
|
+
alignItems: "center",
|
|
6479
|
+
justifyContent: "flex-end",
|
|
6480
|
+
gap: 2
|
|
6481
|
+
},
|
|
6482
|
+
children: actions.map((action) => /* @__PURE__ */ jsx34(ActionButton, { action }, action.key))
|
|
6483
|
+
}
|
|
6484
|
+
);
|
|
6485
|
+
if (inline) {
|
|
6486
|
+
return /* @__PURE__ */ jsxs33(
|
|
6487
|
+
"div",
|
|
6488
|
+
{
|
|
6489
|
+
role: "toolbar",
|
|
6490
|
+
"aria-label": "\uC120\uD0DD \uD56D\uBAA9 \uC77C\uAD04 \uC791\uC5C5",
|
|
6491
|
+
"data-slot": "bulk-action-bar",
|
|
6492
|
+
"data-placement": "inline",
|
|
6493
|
+
className,
|
|
6494
|
+
style: { ...inlineStyle, ...style },
|
|
6495
|
+
...props,
|
|
6496
|
+
children: [
|
|
6497
|
+
/* @__PURE__ */ jsxs33(
|
|
6498
|
+
"div",
|
|
6499
|
+
{
|
|
6500
|
+
role: "status",
|
|
6501
|
+
"data-slot": "bulk-action-bar-state",
|
|
6502
|
+
style: {
|
|
6503
|
+
display: "flex",
|
|
6504
|
+
flex: "1 1 auto",
|
|
6505
|
+
minWidth: 0,
|
|
6506
|
+
alignItems: "center",
|
|
6507
|
+
columnGap: "var(--space-3)"
|
|
6508
|
+
},
|
|
6509
|
+
children: [
|
|
6510
|
+
countLabel,
|
|
6511
|
+
summarySlot
|
|
6512
|
+
]
|
|
6513
|
+
}
|
|
6514
|
+
),
|
|
6515
|
+
/* @__PURE__ */ jsxs33(
|
|
6516
|
+
"div",
|
|
6517
|
+
{
|
|
6518
|
+
"data-slot": "bulk-action-bar-controls",
|
|
6519
|
+
style: {
|
|
6520
|
+
display: "flex",
|
|
6521
|
+
marginLeft: "auto",
|
|
6522
|
+
alignItems: "center",
|
|
6523
|
+
gap: "var(--space-1)"
|
|
6524
|
+
},
|
|
6525
|
+
children: [
|
|
6526
|
+
count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx34(Divider, {}) : null,
|
|
6527
|
+
actionGroup,
|
|
6528
|
+
/* @__PURE__ */ jsx34(Divider, {}),
|
|
6529
|
+
/* @__PURE__ */ jsx34(ClearButton, { onClear })
|
|
6530
|
+
]
|
|
6531
|
+
}
|
|
6532
|
+
)
|
|
6533
|
+
]
|
|
6534
|
+
}
|
|
6535
|
+
);
|
|
6536
|
+
}
|
|
6092
6537
|
return /* @__PURE__ */ jsxs33(
|
|
6093
6538
|
"div",
|
|
6094
6539
|
{
|
|
@@ -6101,59 +6546,13 @@ function BulkActionBar({
|
|
|
6101
6546
|
"animate-[olun-bulk-action-bar-in_var(--dur-fast)_var(--ease-out)_both] motion-reduce:animate-none",
|
|
6102
6547
|
className
|
|
6103
6548
|
),
|
|
6104
|
-
style: {
|
|
6105
|
-
position: "sticky",
|
|
6106
|
-
bottom: "calc(var(--space-4) + env(safe-area-inset-bottom))",
|
|
6107
|
-
zIndex: 1100,
|
|
6108
|
-
margin: "0 auto",
|
|
6109
|
-
display: "flex",
|
|
6110
|
-
minHeight: 32,
|
|
6111
|
-
width: "fit-content",
|
|
6112
|
-
maxWidth: "calc(100% - var(--space-8))",
|
|
6113
|
-
alignItems: "center",
|
|
6114
|
-
gap: "var(--space-2)",
|
|
6115
|
-
borderRadius: 9999,
|
|
6116
|
-
border: "1px solid var(--border)",
|
|
6117
|
-
background: "var(--bg-raised)",
|
|
6118
|
-
padding: "var(--space-1) var(--space-2)",
|
|
6119
|
-
boxShadow: "var(--shadow-8)",
|
|
6120
|
-
...style
|
|
6121
|
-
},
|
|
6549
|
+
style: { ...floatingStyle, ...style },
|
|
6122
6550
|
...props,
|
|
6123
6551
|
children: [
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
{
|
|
6127
|
-
"data-slot": "bulk-action-bar-count",
|
|
6128
|
-
style: {
|
|
6129
|
-
paddingLeft: "var(--space-2)",
|
|
6130
|
-
paddingRight: "var(--space-1)",
|
|
6131
|
-
fontFamily: "var(--font-sans)",
|
|
6132
|
-
fontSize: 13,
|
|
6133
|
-
fontWeight: 500,
|
|
6134
|
-
fontVariantNumeric: "tabular-nums",
|
|
6135
|
-
color: "var(--text-primary)",
|
|
6136
|
-
whiteSpace: "nowrap"
|
|
6137
|
-
},
|
|
6138
|
-
children: count > 0 ? `${count.toLocaleString("ko-KR")}\uAC1C \uC120\uD0DD\uB428` : emptyHint
|
|
6139
|
-
}
|
|
6140
|
-
),
|
|
6552
|
+
countLabel,
|
|
6553
|
+
summarySlot,
|
|
6141
6554
|
count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx34(Divider, {}) : null,
|
|
6142
|
-
|
|
6143
|
-
"div",
|
|
6144
|
-
{
|
|
6145
|
-
"data-slot": "bulk-action-bar-actions",
|
|
6146
|
-
style: {
|
|
6147
|
-
display: "flex",
|
|
6148
|
-
minWidth: 0,
|
|
6149
|
-
flexWrap: "wrap",
|
|
6150
|
-
alignItems: "center",
|
|
6151
|
-
justifyContent: "flex-end",
|
|
6152
|
-
gap: 2
|
|
6153
|
-
},
|
|
6154
|
-
children: actions.map((action) => /* @__PURE__ */ jsx34(ActionButton, { action }, action.key))
|
|
6155
|
-
}
|
|
6156
|
-
),
|
|
6555
|
+
actionGroup,
|
|
6157
6556
|
/* @__PURE__ */ jsx34(Divider, {}),
|
|
6158
6557
|
/* @__PURE__ */ jsx34(ClearButton, { onClear })
|
|
6159
6558
|
]
|
|
@@ -6162,7 +6561,7 @@ function BulkActionBar({
|
|
|
6162
6561
|
}
|
|
6163
6562
|
|
|
6164
6563
|
// src/components/ui/confirm-dialog.tsx
|
|
6165
|
-
import * as
|
|
6564
|
+
import * as React29 from "react";
|
|
6166
6565
|
import { Fragment as Fragment8, jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
6167
6566
|
var confirmDialogContentClassName = cn(
|
|
6168
6567
|
"fixed left-1/2 top-1/2 z-[var(--z-modal)]",
|
|
@@ -6179,6 +6578,7 @@ var confirmDialogTitleClassName = cn(
|
|
|
6179
6578
|
var confirmDialogDescriptionClassName = cn(
|
|
6180
6579
|
"break-keep text-[14px] leading-relaxed text-text-secondary"
|
|
6181
6580
|
);
|
|
6581
|
+
var confirmDialogBodyClassName = "min-w-0 text-[14px] leading-relaxed text-text-secondary";
|
|
6182
6582
|
var confirmDialogFooterClassName = "flex items-center justify-end gap-[var(--space-3)]";
|
|
6183
6583
|
function ConfirmDialog({
|
|
6184
6584
|
open,
|
|
@@ -6189,12 +6589,14 @@ function ConfirmDialog({
|
|
|
6189
6589
|
confirmLabel,
|
|
6190
6590
|
cancelLabel = "\uCDE8\uC18C",
|
|
6191
6591
|
onConfirm,
|
|
6192
|
-
loading = false
|
|
6592
|
+
loading = false,
|
|
6593
|
+
children,
|
|
6594
|
+
confirmDisabled = false
|
|
6193
6595
|
}) {
|
|
6194
|
-
const [pending, setPending] =
|
|
6195
|
-
const busyRef =
|
|
6596
|
+
const [pending, setPending] = React29.useState(false);
|
|
6597
|
+
const busyRef = React29.useRef(false);
|
|
6196
6598
|
const isBusy = loading || pending;
|
|
6197
|
-
const handleOpenChange =
|
|
6599
|
+
const handleOpenChange = React29.useCallback(
|
|
6198
6600
|
(nextOpen) => {
|
|
6199
6601
|
if (!nextOpen && isBusy) {
|
|
6200
6602
|
return;
|
|
@@ -6203,8 +6605,8 @@ function ConfirmDialog({
|
|
|
6203
6605
|
},
|
|
6204
6606
|
[isBusy, onOpenChange]
|
|
6205
6607
|
);
|
|
6206
|
-
const handleConfirm =
|
|
6207
|
-
if (busyRef.current || loading) {
|
|
6608
|
+
const handleConfirm = React29.useCallback(async () => {
|
|
6609
|
+
if (busyRef.current || loading || confirmDisabled) {
|
|
6208
6610
|
return;
|
|
6209
6611
|
}
|
|
6210
6612
|
busyRef.current = true;
|
|
@@ -6216,7 +6618,7 @@ function ConfirmDialog({
|
|
|
6216
6618
|
busyRef.current = false;
|
|
6217
6619
|
setPending(false);
|
|
6218
6620
|
}
|
|
6219
|
-
}, [loading, onConfirm, onOpenChange]);
|
|
6621
|
+
}, [confirmDisabled, loading, onConfirm, onOpenChange]);
|
|
6220
6622
|
const dialogBody = /* @__PURE__ */ jsxs34(Fragment8, { children: [
|
|
6221
6623
|
/* @__PURE__ */ jsx35("div", { className: "flex items-start justify-between gap-[var(--space-4)]", children: /* @__PURE__ */ jsxs34("div", { className: "min-w-0 space-y-[var(--space-2)]", children: [
|
|
6222
6624
|
/* @__PURE__ */ jsx35(
|
|
@@ -6236,6 +6638,7 @@ function ConfirmDialog({
|
|
|
6236
6638
|
}
|
|
6237
6639
|
) : null
|
|
6238
6640
|
] }) }),
|
|
6641
|
+
children != null ? /* @__PURE__ */ jsx35("div", { "data-slot": "confirm-dialog-body", className: confirmDialogBodyClassName, children }) : null,
|
|
6239
6642
|
/* @__PURE__ */ jsxs34(
|
|
6240
6643
|
"div",
|
|
6241
6644
|
{
|
|
@@ -6248,6 +6651,7 @@ function ConfirmDialog({
|
|
|
6248
6651
|
{
|
|
6249
6652
|
variant: tone === "destructive" ? "destructive" : "primary",
|
|
6250
6653
|
loading: isBusy,
|
|
6654
|
+
disabled: confirmDisabled,
|
|
6251
6655
|
onClick: handleConfirm,
|
|
6252
6656
|
children: confirmLabel
|
|
6253
6657
|
}
|
|
@@ -6301,7 +6705,7 @@ function Avatar({
|
|
|
6301
6705
|
"data-size": size,
|
|
6302
6706
|
className: cn(
|
|
6303
6707
|
"group/avatar relative flex shrink-0 overflow-hidden rounded-full select-none",
|
|
6304
|
-
"border border-[var(--border-subtle)] bg-[var(--bg-
|
|
6708
|
+
"border border-[var(--border-subtle)] bg-[var(--bg-inset)] text-text-secondary",
|
|
6305
6709
|
"h-9 w-9",
|
|
6306
6710
|
"data-[size=sm]:h-8 data-[size=sm]:w-8",
|
|
6307
6711
|
"data-[size=lg]:h-11 data-[size=lg]:w-11",
|
|
@@ -6346,7 +6750,7 @@ function AvatarFallback({
|
|
|
6346
6750
|
"data-slot": "avatar-fallback",
|
|
6347
6751
|
className: cn(
|
|
6348
6752
|
"flex h-full w-full items-center justify-center rounded-full",
|
|
6349
|
-
"bg-[var(--bg-
|
|
6753
|
+
"bg-[var(--bg-inset)] text-sm font-semibold text-text-secondary",
|
|
6350
6754
|
"font-[family-name:var(--font-display)]",
|
|
6351
6755
|
"group-data-[size=sm]/avatar:text-xs",
|
|
6352
6756
|
className
|
|
@@ -6358,7 +6762,7 @@ function AvatarFallback({
|
|
|
6358
6762
|
}
|
|
6359
6763
|
|
|
6360
6764
|
// src/components/ui/badge.tsx
|
|
6361
|
-
import * as
|
|
6765
|
+
import * as React30 from "react";
|
|
6362
6766
|
import { jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
6363
6767
|
var DOT = {
|
|
6364
6768
|
error: "var(--semantic-error-fg)",
|
|
@@ -6368,7 +6772,7 @@ var DOT = {
|
|
|
6368
6772
|
neutral: "var(--text-tertiary)",
|
|
6369
6773
|
brand: "var(--accent-pop)"
|
|
6370
6774
|
};
|
|
6371
|
-
var Badge =
|
|
6775
|
+
var Badge = React30.forwardRef(
|
|
6372
6776
|
({ tone = "neutral", className, children, ...props }, ref) => /* @__PURE__ */ jsxs35(
|
|
6373
6777
|
"span",
|
|
6374
6778
|
{
|
|
@@ -6400,7 +6804,7 @@ var Badge = React29.forwardRef(
|
|
|
6400
6804
|
Badge.displayName = "Badge";
|
|
6401
6805
|
|
|
6402
6806
|
// src/components/ui/two-tier-badge.tsx
|
|
6403
|
-
import * as
|
|
6807
|
+
import * as React31 from "react";
|
|
6404
6808
|
import { jsx as jsx39, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
6405
6809
|
var FG = {
|
|
6406
6810
|
neutral: "var(--text-secondary)",
|
|
@@ -6422,7 +6826,7 @@ var SEGMENT = {
|
|
|
6422
6826
|
md: "gap-[7px] py-[var(--space-1)] px-[var(--space-3)] text-[14px]"
|
|
6423
6827
|
};
|
|
6424
6828
|
var DOT2 = { xs: 5, sm: 6, md: 7 };
|
|
6425
|
-
var TwoTierBadge =
|
|
6829
|
+
var TwoTierBadge = React31.forwardRef(
|
|
6426
6830
|
({ primary, secondary, tone = "neutral", emphasis = "subtle", size = "sm", showDot = false, className, style, ...props }, ref) => {
|
|
6427
6831
|
const strong = emphasis === "strong";
|
|
6428
6832
|
const fg = FG[tone];
|
|
@@ -6492,7 +6896,7 @@ var TwoTierBadge = React30.forwardRef(
|
|
|
6492
6896
|
TwoTierBadge.displayName = "TwoTierBadge";
|
|
6493
6897
|
|
|
6494
6898
|
// src/components/ui/status-badge.tsx
|
|
6495
|
-
import * as
|
|
6899
|
+
import * as React32 from "react";
|
|
6496
6900
|
import { jsx as jsx40, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
6497
6901
|
var ROLE = {
|
|
6498
6902
|
error: "error",
|
|
@@ -6522,7 +6926,7 @@ var SIZE = {
|
|
|
6522
6926
|
sm: { cls: "gap-[6px] py-[var(--space-1)] px-[var(--space-2)] text-[12px]", dot: 6 },
|
|
6523
6927
|
md: { cls: "gap-[var(--space-2)] py-[var(--space-1)] px-[14px] text-[14px]", dot: 7 }
|
|
6524
6928
|
};
|
|
6525
|
-
var StatusBadge =
|
|
6929
|
+
var StatusBadge = React32.forwardRef(
|
|
6526
6930
|
({ status = "active", emphasis = "subtle", size = "sm", showDot = true, pulse = true, className, children, style, ...props }, ref) => {
|
|
6527
6931
|
const role = ROLE[status];
|
|
6528
6932
|
const fg = FG2[role];
|
|
@@ -6573,7 +6977,7 @@ var StatusBadge = React31.forwardRef(
|
|
|
6573
6977
|
StatusBadge.displayName = "StatusBadge";
|
|
6574
6978
|
|
|
6575
6979
|
// src/components/ui/notification-badge.tsx
|
|
6576
|
-
import * as
|
|
6980
|
+
import * as React33 from "react";
|
|
6577
6981
|
import { cva as cva13 } from "class-variance-authority";
|
|
6578
6982
|
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
6579
6983
|
var notificationBadgeVariants = cva13(
|
|
@@ -6606,7 +7010,7 @@ function formatNotificationCount(count, max) {
|
|
|
6606
7010
|
}
|
|
6607
7011
|
return String(count);
|
|
6608
7012
|
}
|
|
6609
|
-
var NotificationBadge =
|
|
7013
|
+
var NotificationBadge = React33.forwardRef(
|
|
6610
7014
|
({
|
|
6611
7015
|
className,
|
|
6612
7016
|
count,
|
|
@@ -6639,7 +7043,7 @@ var NotificationBadge = React32.forwardRef(
|
|
|
6639
7043
|
NotificationBadge.displayName = "NotificationBadge";
|
|
6640
7044
|
|
|
6641
7045
|
// src/components/ui/empty-state.tsx
|
|
6642
|
-
import * as
|
|
7046
|
+
import * as React34 from "react";
|
|
6643
7047
|
import { cva as cva14 } from "class-variance-authority";
|
|
6644
7048
|
import { jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
6645
7049
|
var emptyStateBaseVariants = cva14(
|
|
@@ -6713,7 +7117,7 @@ var iconSize3 = {
|
|
|
6713
7117
|
md: 20,
|
|
6714
7118
|
lg: 24
|
|
6715
7119
|
};
|
|
6716
|
-
var EmptyState =
|
|
7120
|
+
var EmptyState = React34.forwardRef(
|
|
6717
7121
|
({
|
|
6718
7122
|
className,
|
|
6719
7123
|
size = "md",
|
|
@@ -6781,7 +7185,7 @@ var EmptyState = React33.forwardRef(
|
|
|
6781
7185
|
EmptyState.displayName = "EmptyState";
|
|
6782
7186
|
|
|
6783
7187
|
// src/components/ui/error-state.tsx
|
|
6784
|
-
import * as
|
|
7188
|
+
import * as React35 from "react";
|
|
6785
7189
|
import { AlertTriangle } from "lucide-react";
|
|
6786
7190
|
import { cva as cva15 } from "class-variance-authority";
|
|
6787
7191
|
import { jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
@@ -6806,7 +7210,7 @@ var errorStateVariants = cva15(
|
|
|
6806
7210
|
}
|
|
6807
7211
|
}
|
|
6808
7212
|
);
|
|
6809
|
-
var ErrorState =
|
|
7213
|
+
var ErrorState = React35.forwardRef(
|
|
6810
7214
|
({
|
|
6811
7215
|
className,
|
|
6812
7216
|
size = "md",
|
|
@@ -6869,12 +7273,14 @@ var ErrorState = React34.forwardRef(
|
|
|
6869
7273
|
ErrorState.displayName = "ErrorState";
|
|
6870
7274
|
|
|
6871
7275
|
// src/components/ui/skeleton.tsx
|
|
6872
|
-
import * as
|
|
7276
|
+
import * as React36 from "react";
|
|
6873
7277
|
import { cva as cva16 } from "class-variance-authority";
|
|
6874
7278
|
import { jsx as jsx44 } from "react/jsx-runtime";
|
|
6875
7279
|
var skeletonVariants = cva16(
|
|
6876
7280
|
[
|
|
6877
|
-
|
|
7281
|
+
// bg-inset: light #F1F2F4 reads on white surfaces (bg-raised was white = invisible);
|
|
7282
|
+
// dark value equals the old bg-raised (#16181D), so dark mode is unchanged.
|
|
7283
|
+
"animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]",
|
|
6878
7284
|
"motion-reduce:animate-none motion-reduce:opacity-80"
|
|
6879
7285
|
].join(" "),
|
|
6880
7286
|
{
|
|
@@ -6913,7 +7319,7 @@ var spinnerVariants = cva16(
|
|
|
6913
7319
|
}
|
|
6914
7320
|
}
|
|
6915
7321
|
);
|
|
6916
|
-
var Skeleton =
|
|
7322
|
+
var Skeleton = React36.forwardRef(
|
|
6917
7323
|
({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx44(
|
|
6918
7324
|
"div",
|
|
6919
7325
|
{
|
|
@@ -6927,7 +7333,7 @@ var Skeleton = React35.forwardRef(
|
|
|
6927
7333
|
);
|
|
6928
7334
|
Skeleton.displayName = "Skeleton";
|
|
6929
7335
|
var defaultTextWidths = ["92%", "84%", "68%", "76%"];
|
|
6930
|
-
var SkeletonText =
|
|
7336
|
+
var SkeletonText = React36.forwardRef(
|
|
6931
7337
|
({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx44(
|
|
6932
7338
|
"div",
|
|
6933
7339
|
{
|
|
@@ -6947,7 +7353,7 @@ var SkeletonText = React35.forwardRef(
|
|
|
6947
7353
|
)
|
|
6948
7354
|
);
|
|
6949
7355
|
SkeletonText.displayName = "SkeletonText";
|
|
6950
|
-
var SkeletonRow =
|
|
7356
|
+
var SkeletonRow = React36.forwardRef(
|
|
6951
7357
|
({
|
|
6952
7358
|
className,
|
|
6953
7359
|
columns,
|
|
@@ -7004,7 +7410,7 @@ var SkeletonRow = React35.forwardRef(
|
|
|
7004
7410
|
}
|
|
7005
7411
|
);
|
|
7006
7412
|
SkeletonRow.displayName = "SkeletonRow";
|
|
7007
|
-
var Spinner =
|
|
7413
|
+
var Spinner = React36.forwardRef(
|
|
7008
7414
|
({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx44(
|
|
7009
7415
|
"span",
|
|
7010
7416
|
{
|
|
@@ -7020,7 +7426,7 @@ var Spinner = React35.forwardRef(
|
|
|
7020
7426
|
Spinner.displayName = "Spinner";
|
|
7021
7427
|
|
|
7022
7428
|
// src/components/ui/pagination.tsx
|
|
7023
|
-
import * as
|
|
7429
|
+
import * as React37 from "react";
|
|
7024
7430
|
import { ChevronsLeft, ChevronLeft, ChevronRight as ChevronRight2, ChevronsRight } from "lucide-react";
|
|
7025
7431
|
import { cva as cva17 } from "class-variance-authority";
|
|
7026
7432
|
|
|
@@ -7161,7 +7567,7 @@ function NavigationButton({
|
|
|
7161
7567
|
}
|
|
7162
7568
|
);
|
|
7163
7569
|
}
|
|
7164
|
-
var Pagination =
|
|
7570
|
+
var Pagination = React37.forwardRef(
|
|
7165
7571
|
({
|
|
7166
7572
|
className,
|
|
7167
7573
|
size = "standard",
|
|
@@ -7303,7 +7709,7 @@ import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
|
7303
7709
|
var modeToggleVariants = cva18(
|
|
7304
7710
|
[
|
|
7305
7711
|
"inline-flex items-center rounded-[var(--radius-sm)] border border-[var(--border-subtle)]",
|
|
7306
|
-
"bg-[var(--bg-
|
|
7712
|
+
"bg-[var(--bg-inset)] p-[2px]"
|
|
7307
7713
|
].join(" ")
|
|
7308
7714
|
);
|
|
7309
7715
|
var modeToggleItemVariants = cva18(
|
|
@@ -7367,7 +7773,7 @@ function ModeToggle({
|
|
|
7367
7773
|
}
|
|
7368
7774
|
|
|
7369
7775
|
// src/components/ui/action-footer.tsx
|
|
7370
|
-
import * as
|
|
7776
|
+
import * as React38 from "react";
|
|
7371
7777
|
import { cva as cva19 } from "class-variance-authority";
|
|
7372
7778
|
import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
7373
7779
|
var actionFooterVariants = cva19(
|
|
@@ -7454,7 +7860,7 @@ function renderAction(action) {
|
|
|
7454
7860
|
action.id ?? action.label
|
|
7455
7861
|
);
|
|
7456
7862
|
}
|
|
7457
|
-
var ActionFooter =
|
|
7863
|
+
var ActionFooter = React38.forwardRef(
|
|
7458
7864
|
({
|
|
7459
7865
|
className,
|
|
7460
7866
|
status,
|
|
@@ -7524,7 +7930,7 @@ var ActionFooter = React37.forwardRef(
|
|
|
7524
7930
|
ActionFooter.displayName = "ActionFooter";
|
|
7525
7931
|
|
|
7526
7932
|
// src/components/ui/toast.tsx
|
|
7527
|
-
import * as
|
|
7933
|
+
import * as React39 from "react";
|
|
7528
7934
|
import { cva as cva20 } from "class-variance-authority";
|
|
7529
7935
|
import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
7530
7936
|
var DOT3 = {
|
|
@@ -7644,7 +8050,7 @@ var toast = {
|
|
|
7644
8050
|
}
|
|
7645
8051
|
};
|
|
7646
8052
|
var Toast = toast;
|
|
7647
|
-
var ToastRoot =
|
|
8053
|
+
var ToastRoot = React39.forwardRef(
|
|
7648
8054
|
({
|
|
7649
8055
|
className,
|
|
7650
8056
|
id,
|
|
@@ -7661,10 +8067,10 @@ var ToastRoot = React38.forwardRef(
|
|
|
7661
8067
|
...props
|
|
7662
8068
|
}, ref) => {
|
|
7663
8069
|
const durationMs = getToastDuration({ message, variant, duration });
|
|
7664
|
-
const onCloseRef =
|
|
8070
|
+
const onCloseRef = React39.useRef(onClose);
|
|
7665
8071
|
onCloseRef.current = onClose;
|
|
7666
|
-
const timerRef =
|
|
7667
|
-
|
|
8072
|
+
const timerRef = React39.useRef(null);
|
|
8073
|
+
React39.useEffect(() => {
|
|
7668
8074
|
if (!onCloseRef.current) return void 0;
|
|
7669
8075
|
const timer = createToastTimer(durationMs, () => onCloseRef.current?.());
|
|
7670
8076
|
timerRef.current = timer;
|
|
@@ -7761,7 +8167,7 @@ var ToastRoot = React38.forwardRef(
|
|
|
7761
8167
|
}
|
|
7762
8168
|
);
|
|
7763
8169
|
ToastRoot.displayName = "ToastRoot";
|
|
7764
|
-
var ToastViewport =
|
|
8170
|
+
var ToastViewport = React39.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx49(
|
|
7765
8171
|
"ol",
|
|
7766
8172
|
{
|
|
7767
8173
|
ref,
|
|
@@ -7772,8 +8178,8 @@ var ToastViewport = React38.forwardRef(({ className, ...props }, ref) => /* @__P
|
|
|
7772
8178
|
));
|
|
7773
8179
|
ToastViewport.displayName = "ToastViewport";
|
|
7774
8180
|
function ToastProvider({ children, maxToasts = 3, className, ...props }) {
|
|
7775
|
-
const [items, setItems] =
|
|
7776
|
-
|
|
8181
|
+
const [items, setItems] = React39.useState([]);
|
|
8182
|
+
React39.useEffect(
|
|
7777
8183
|
() => toast.subscribe((nextItems) => {
|
|
7778
8184
|
setItems(limitToasts(nextItems, maxToasts));
|
|
7779
8185
|
}),
|
|
@@ -7786,7 +8192,7 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
|
|
|
7786
8192
|
}
|
|
7787
8193
|
|
|
7788
8194
|
// src/components/ui/otp-field.tsx
|
|
7789
|
-
import * as
|
|
8195
|
+
import * as React40 from "react";
|
|
7790
8196
|
import { cva as cva21 } from "class-variance-authority";
|
|
7791
8197
|
import { AlertCircle as AlertCircle4 } from "lucide-react";
|
|
7792
8198
|
import { Fragment as Fragment9, jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
@@ -7819,14 +8225,14 @@ var otpFieldGroupVariants = cva21("flex items-start gap-[var(--space-2)] pt-[var
|
|
|
7819
8225
|
});
|
|
7820
8226
|
var otpCellVariants = cva21(
|
|
7821
8227
|
[
|
|
7822
|
-
"flex items-center justify-center rounded-[var(--radius-
|
|
8228
|
+
"flex items-center justify-center rounded-[var(--radius-md)] border",
|
|
7823
8229
|
"border-[var(--border)] text-foreground",
|
|
7824
8230
|
"font-[family-name:var(--font-display)] tabular-nums",
|
|
7825
8231
|
"text-center leading-none caret-[var(--text-primary)]",
|
|
7826
8232
|
"transition-[border-color,box-shadow,background-color,color] motion-reduce:transition-none",
|
|
7827
8233
|
"focus:outline-none focus:border-[var(--focus-ring)] focus:shadow-[0_0_0_1px_var(--focus-ring)]",
|
|
7828
8234
|
"disabled:cursor-not-allowed disabled:border-[var(--border-subtle)] disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled",
|
|
7829
|
-
"read-only:cursor-default read-only:bg-[var(--bg-
|
|
8235
|
+
"read-only:cursor-default read-only:bg-[var(--bg-inset)] read-only:text-text-secondary",
|
|
7830
8236
|
"aria-[invalid=true]:border-[var(--error)] aria-[invalid=true]:focus:shadow-[0_0_0_1px_var(--error)]",
|
|
7831
8237
|
"data-[state=error]:border-[var(--error)] data-[state=error]:focus:shadow-[0_0_0_1px_var(--error)]",
|
|
7832
8238
|
"data-[state=filled]:border-[var(--border-strong)]"
|
|
@@ -7916,7 +8322,7 @@ function fillDigitsFromIndex(slots, index, inserted, length) {
|
|
|
7916
8322
|
focusIndex: Math.min(cursor, length - 1)
|
|
7917
8323
|
};
|
|
7918
8324
|
}
|
|
7919
|
-
var OTPField =
|
|
8325
|
+
var OTPField = React40.forwardRef(
|
|
7920
8326
|
({
|
|
7921
8327
|
className,
|
|
7922
8328
|
defaultValue,
|
|
@@ -7938,24 +8344,24 @@ var OTPField = React39.forwardRef(
|
|
|
7938
8344
|
required,
|
|
7939
8345
|
...props
|
|
7940
8346
|
}, ref) => {
|
|
7941
|
-
const generatedId =
|
|
8347
|
+
const generatedId = React40.useId();
|
|
7942
8348
|
const fieldId = id ?? generatedId;
|
|
7943
8349
|
const labelId = `${fieldId}-label`;
|
|
7944
8350
|
const helperId = helperText ? `${fieldId}-helper` : void 0;
|
|
7945
8351
|
const errorId = errorText ? `${fieldId}-error` : void 0;
|
|
7946
8352
|
const resolvedState = invalid || errorText ? "error" : "default";
|
|
7947
8353
|
const isControlled = value !== void 0;
|
|
7948
|
-
const [uncontrolledSlots, setUncontrolledSlots] =
|
|
8354
|
+
const [uncontrolledSlots, setUncontrolledSlots] = React40.useState(
|
|
7949
8355
|
() => toDigitsArray(onlyDigits(defaultValue, length), length)
|
|
7950
8356
|
);
|
|
7951
|
-
const resolvedSlots =
|
|
8357
|
+
const resolvedSlots = React40.useMemo(
|
|
7952
8358
|
() => isControlled ? toDigitsArray(onlyDigits(value, length), length) : uncontrolledSlots,
|
|
7953
8359
|
[isControlled, length, uncontrolledSlots, value]
|
|
7954
8360
|
);
|
|
7955
8361
|
const resolvedValue = joinDigits(resolvedSlots).slice(0, length);
|
|
7956
|
-
const cellsRef =
|
|
8362
|
+
const cellsRef = React40.useRef([]);
|
|
7957
8363
|
const groupDescribedBy = [helperId, errorId].filter(Boolean).join(" ") || void 0;
|
|
7958
|
-
const setResolvedValue =
|
|
8364
|
+
const setResolvedValue = React40.useCallback(
|
|
7959
8365
|
(nextSlots, focusIndex) => {
|
|
7960
8366
|
const normalizedSlots = nextSlots.slice(0, length);
|
|
7961
8367
|
const normalizedValue = joinDigits(normalizedSlots).slice(0, length);
|
|
@@ -8145,7 +8551,7 @@ var OTPField = React39.forwardRef(
|
|
|
8145
8551
|
OTPField.displayName = "OTPField";
|
|
8146
8552
|
|
|
8147
8553
|
// src/components/ui/search-field.tsx
|
|
8148
|
-
import * as
|
|
8554
|
+
import * as React41 from "react";
|
|
8149
8555
|
import { Search, X as X4 } from "lucide-react";
|
|
8150
8556
|
import { cva as cva22 } from "class-variance-authority";
|
|
8151
8557
|
import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
@@ -8164,7 +8570,7 @@ var searchFieldVariants = cva22("relative flex w-full items-center", {
|
|
|
8164
8570
|
});
|
|
8165
8571
|
var searchFieldInputVariants = cva22(
|
|
8166
8572
|
[
|
|
8167
|
-
"h-full w-full rounded-[var(--radius-
|
|
8573
|
+
"h-full w-full rounded-[var(--radius-md)] border",
|
|
8168
8574
|
"border-[var(--border)]",
|
|
8169
8575
|
"appearance-none [&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden",
|
|
8170
8576
|
"font-[family-name:var(--font-body)] text-foreground",
|
|
@@ -8213,7 +8619,7 @@ var iconSize4 = {
|
|
|
8213
8619
|
function hasVisibleValue(value) {
|
|
8214
8620
|
return typeof value === "string" ? value.length > 0 : value !== void 0;
|
|
8215
8621
|
}
|
|
8216
|
-
var SearchField =
|
|
8622
|
+
var SearchField = React41.forwardRef(
|
|
8217
8623
|
({
|
|
8218
8624
|
className,
|
|
8219
8625
|
inputMode = "search",
|
|
@@ -8229,12 +8635,12 @@ var SearchField = React40.forwardRef(
|
|
|
8229
8635
|
...props
|
|
8230
8636
|
}, ref) => {
|
|
8231
8637
|
const resolvedSize = size ?? "md";
|
|
8232
|
-
const inputRef =
|
|
8233
|
-
const [hasText, setHasText] =
|
|
8638
|
+
const inputRef = React41.useRef(null);
|
|
8639
|
+
const [hasText, setHasText] = React41.useState(
|
|
8234
8640
|
() => hasVisibleValue(value ?? defaultValue)
|
|
8235
8641
|
);
|
|
8236
|
-
|
|
8237
|
-
|
|
8642
|
+
React41.useImperativeHandle(ref, () => inputRef.current);
|
|
8643
|
+
React41.useEffect(() => {
|
|
8238
8644
|
if (value !== void 0) {
|
|
8239
8645
|
setHasText(hasVisibleValue(value));
|
|
8240
8646
|
}
|
|
@@ -8304,7 +8710,7 @@ var SearchField = React40.forwardRef(
|
|
|
8304
8710
|
SearchField.displayName = "SearchField";
|
|
8305
8711
|
|
|
8306
8712
|
// src/components/ui/checkbox-group.tsx
|
|
8307
|
-
import * as
|
|
8713
|
+
import * as React42 from "react";
|
|
8308
8714
|
import { cva as cva23 } from "class-variance-authority";
|
|
8309
8715
|
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
8310
8716
|
var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
|
|
@@ -8332,7 +8738,7 @@ var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
|
|
|
8332
8738
|
function toSelectionSet(value) {
|
|
8333
8739
|
return new Set(value ?? []);
|
|
8334
8740
|
}
|
|
8335
|
-
var CheckboxGroup =
|
|
8741
|
+
var CheckboxGroup = React42.forwardRef(
|
|
8336
8742
|
({
|
|
8337
8743
|
className,
|
|
8338
8744
|
children,
|
|
@@ -8348,14 +8754,14 @@ var CheckboxGroup = React41.forwardRef(
|
|
|
8348
8754
|
...props
|
|
8349
8755
|
}, ref) => {
|
|
8350
8756
|
const isControlled = value != null;
|
|
8351
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
8757
|
+
const [uncontrolledValue, setUncontrolledValue] = React42.useState(
|
|
8352
8758
|
() => toSelectionSet(defaultValue)
|
|
8353
8759
|
);
|
|
8354
|
-
const selectedValues =
|
|
8760
|
+
const selectedValues = React42.useMemo(
|
|
8355
8761
|
() => isControlled ? toSelectionSet(value) : uncontrolledValue,
|
|
8356
8762
|
[isControlled, uncontrolledValue, value]
|
|
8357
8763
|
);
|
|
8358
|
-
const toggleValue =
|
|
8764
|
+
const toggleValue = React42.useCallback(
|
|
8359
8765
|
(itemValue, checked) => {
|
|
8360
8766
|
const nextValues = new Set(selectedValues);
|
|
8361
8767
|
if (checked) {
|
|
@@ -8371,7 +8777,7 @@ var CheckboxGroup = React41.forwardRef(
|
|
|
8371
8777
|
},
|
|
8372
8778
|
[isControlled, onValueChange, selectedValues]
|
|
8373
8779
|
);
|
|
8374
|
-
const contextValue =
|
|
8780
|
+
const contextValue = React42.useMemo(
|
|
8375
8781
|
() => ({
|
|
8376
8782
|
appearance,
|
|
8377
8783
|
density,
|
|
@@ -8406,7 +8812,7 @@ var CheckboxGroup = React41.forwardRef(
|
|
|
8406
8812
|
CheckboxGroup.displayName = "CheckboxGroup";
|
|
8407
8813
|
|
|
8408
8814
|
// src/components/ui/radio-group.tsx
|
|
8409
|
-
import * as
|
|
8815
|
+
import * as React43 from "react";
|
|
8410
8816
|
import { cva as cva24 } from "class-variance-authority";
|
|
8411
8817
|
import { Circle } from "lucide-react";
|
|
8412
8818
|
import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
|
|
@@ -8499,11 +8905,11 @@ var radioControlVariants = cva24(
|
|
|
8499
8905
|
}
|
|
8500
8906
|
}
|
|
8501
8907
|
);
|
|
8502
|
-
var RadioGroupContext =
|
|
8908
|
+
var RadioGroupContext = React43.createContext({
|
|
8503
8909
|
appearance: "plain",
|
|
8504
8910
|
density: "comfortable"
|
|
8505
8911
|
});
|
|
8506
|
-
var RadioGroup =
|
|
8912
|
+
var RadioGroup = React43.forwardRef(
|
|
8507
8913
|
({
|
|
8508
8914
|
className,
|
|
8509
8915
|
children,
|
|
@@ -8514,7 +8920,7 @@ var RadioGroup = React42.forwardRef(
|
|
|
8514
8920
|
required,
|
|
8515
8921
|
...props
|
|
8516
8922
|
}, ref) => {
|
|
8517
|
-
const contextValue =
|
|
8923
|
+
const contextValue = React43.useMemo(
|
|
8518
8924
|
() => ({ appearance, density }),
|
|
8519
8925
|
[appearance, density]
|
|
8520
8926
|
);
|
|
@@ -8541,9 +8947,9 @@ var RadioGroup = React42.forwardRef(
|
|
|
8541
8947
|
}
|
|
8542
8948
|
);
|
|
8543
8949
|
RadioGroup.displayName = "RadioGroup";
|
|
8544
|
-
var Radio =
|
|
8545
|
-
const { appearance, density } =
|
|
8546
|
-
const generatedId =
|
|
8950
|
+
var Radio = React43.forwardRef(({ className, children, description, id, ...props }, ref) => {
|
|
8951
|
+
const { appearance, density } = React43.useContext(RadioGroupContext);
|
|
8952
|
+
const generatedId = React43.useId();
|
|
8547
8953
|
const radioId = id ?? generatedId;
|
|
8548
8954
|
const labelId = `${radioId}-label`;
|
|
8549
8955
|
const descriptionId = description ? `${radioId}-description` : void 0;
|
|
@@ -8711,7 +9117,7 @@ function Progress({
|
|
|
8711
9117
|
}
|
|
8712
9118
|
|
|
8713
9119
|
// src/components/ui/tree-view.tsx
|
|
8714
|
-
import * as
|
|
9120
|
+
import * as React44 from "react";
|
|
8715
9121
|
import { ChevronRight as ChevronRight3 } from "lucide-react";
|
|
8716
9122
|
import { cva as cva25 } from "class-variance-authority";
|
|
8717
9123
|
import { jsx as jsx56, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
@@ -8817,27 +9223,27 @@ function TreeView({
|
|
|
8817
9223
|
...rest
|
|
8818
9224
|
}) {
|
|
8819
9225
|
const isExpandedControlled = expandedIds !== void 0;
|
|
8820
|
-
const [internalExpanded, setInternalExpanded] =
|
|
9226
|
+
const [internalExpanded, setInternalExpanded] = React44.useState(
|
|
8821
9227
|
() => defaultExpandedIds ?? []
|
|
8822
9228
|
);
|
|
8823
9229
|
const expandedList = isExpandedControlled ? expandedIds : internalExpanded;
|
|
8824
|
-
const expandedSet =
|
|
8825
|
-
const items =
|
|
9230
|
+
const expandedSet = React44.useMemo(() => new Set(expandedList), [expandedList]);
|
|
9231
|
+
const items = React44.useMemo(
|
|
8826
9232
|
() => flattenVisibleNodes(nodes, getChildren, expandedSet),
|
|
8827
9233
|
[nodes, getChildren, expandedSet]
|
|
8828
9234
|
);
|
|
8829
|
-
const [focusedId, setFocusedId] =
|
|
9235
|
+
const [focusedId, setFocusedId] = React44.useState(null);
|
|
8830
9236
|
const visibleIds = items.map((item) => item.id);
|
|
8831
9237
|
const activeId = focusedId && visibleIds.includes(focusedId) ? focusedId : selectedId && visibleIds.includes(selectedId) ? selectedId : visibleIds[0] ?? null;
|
|
8832
|
-
const itemRefs =
|
|
8833
|
-
const commitExpanded =
|
|
9238
|
+
const itemRefs = React44.useRef(/* @__PURE__ */ new Map());
|
|
9239
|
+
const commitExpanded = React44.useCallback(
|
|
8834
9240
|
(next) => {
|
|
8835
9241
|
if (!isExpandedControlled) setInternalExpanded(next);
|
|
8836
9242
|
onExpandedChange?.(next);
|
|
8837
9243
|
},
|
|
8838
9244
|
[isExpandedControlled, onExpandedChange]
|
|
8839
9245
|
);
|
|
8840
|
-
const setExpanded =
|
|
9246
|
+
const setExpanded = React44.useCallback(
|
|
8841
9247
|
(id, expand) => {
|
|
8842
9248
|
const has = expandedSet.has(id);
|
|
8843
9249
|
if (expand && !has) {
|
|
@@ -8848,7 +9254,7 @@ function TreeView({
|
|
|
8848
9254
|
},
|
|
8849
9255
|
[commitExpanded, expandedList, expandedSet]
|
|
8850
9256
|
);
|
|
8851
|
-
const focusItem =
|
|
9257
|
+
const focusItem = React44.useCallback((id) => {
|
|
8852
9258
|
setFocusedId(id);
|
|
8853
9259
|
itemRefs.current.get(id)?.focus();
|
|
8854
9260
|
}, []);
|