@martinsura/ui 0.1.3 → 0.1.4

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 CHANGED
@@ -327,7 +327,9 @@ var buttonVariants = classVarianceAuthority.cva(
327
327
  danger: "bg-(--ui-danger) text-(--ui-danger-text) hover:bg-(--ui-danger-hover) active:bg-(--ui-danger-hover)",
328
328
  success: "bg-(--ui-success) text-(--ui-success-text) hover:bg-(--ui-success-hover) active:bg-(--ui-success-hover)",
329
329
  default: "bg-white text-(--ui-text) border border-(--ui-border-strong) hover:bg-(--ui-surface-subtle) active:bg-(--ui-surface-muted)",
330
+ subtle: "bg-(--ui-surface-subtle) text-(--ui-text) border border-transparent hover:bg-(--ui-surface-muted) active:bg-(--ui-surface-muted)",
330
331
  ghost: "text-(--ui-text) hover:bg-(--ui-surface-muted) active:bg-(--ui-surface-subtle)",
332
+ text: "text-(--ui-text) hover:text-(--ui-text-strong) active:text-(--ui-text-strong) px-0! bg-transparent",
331
333
  link: "text-(--ui-primary) hover:underline p-0! h-auto!"
332
334
  },
333
335
  size: {
@@ -363,12 +365,14 @@ var Button = ({
363
365
  size = "middle",
364
366
  shape = "default",
365
367
  block = false,
368
+ fullWidthOnMobile = false,
366
369
  iconPosition = "left",
367
370
  ...props
368
371
  }) => {
369
372
  const iconSize = props.iconSize ?? iconSizeMap[size];
370
373
  const IconComponent = props.icon ?? (props.iconType ? getIcon(props.iconType) : void 0);
371
374
  const iconNode = IconComponent ? /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { size: iconSize, strokeWidth: 1.5, className: props.classNames?.icon }) : void 0;
375
+ const content = props.text ?? props.children;
372
376
  const handleClick = () => {
373
377
  if (props.disabled || props.loading) {
374
378
  return;
@@ -380,11 +384,16 @@ var Button = ({
380
384
  {
381
385
  type: props.htmlType ?? "button",
382
386
  disabled: props.disabled || props.loading,
383
- className: tailwindMerge.twMerge(buttonVariants({ variant, size, block, shape }), props.className),
387
+ className: tailwindMerge.twMerge(
388
+ buttonVariants({ variant, size, block, shape }),
389
+ fullWidthOnMobile && !block && "w-full sm:w-auto",
390
+ props.iconOnly && "px-0!",
391
+ props.className
392
+ ),
384
393
  onClick: props.confirm ? void 0 : handleClick,
385
394
  children: [
386
395
  props.loading ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: iconSize, color: "current", className: props.classNames?.spinner }) : iconPosition === "left" && iconNode,
387
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: props.classNames?.content, children: props.text ?? props.children }),
396
+ !props.iconOnly && content !== void 0 && content !== null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: props.classNames?.content, children: content }),
388
397
  !props.loading && iconPosition === "right" && iconNode
389
398
  ]
390
399
  }
@@ -404,6 +413,21 @@ var Button = ({
404
413
  }
405
414
  );
406
415
  };
416
+ var ConfirmButton = (props) => /* @__PURE__ */ jsxRuntime.jsx(
417
+ Button,
418
+ {
419
+ text: props.text,
420
+ onClick: props.onClick,
421
+ disabled: props.disabled,
422
+ loading: props.loading,
423
+ variant: props.variant,
424
+ size: props.size,
425
+ icon: props.icon,
426
+ className: props.className,
427
+ confirm: props.confirm,
428
+ children: props.children
429
+ }
430
+ );
407
431
  var InputField = ({ noMargin, className, children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex flex-col gap-1", !noMargin && "mb-3", className), children });
408
432
  var InputLabel = ({ label, required, className, requiredMarkClassName }) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: tailwindMerge.twMerge("text-sm text-(--ui-text)", className), children: [
409
433
  label,
@@ -479,6 +503,26 @@ var TextInput = react.forwardRef(({
479
503
  ] });
480
504
  });
481
505
  TextInput.displayName = "TextInput";
506
+ var Textarea = ({ rows = 4, ...props }) => {
507
+ const resolveError = useErrorResolver();
508
+ const resolvedErrors = props.errorName ? resolveError(props.errorName) : [];
509
+ const errorDisplay = props.error ?? props.customError ?? (resolvedErrors.length > 0 ? resolvedErrors.join(", ") : void 0);
510
+ return /* @__PURE__ */ jsxRuntime.jsxs(InputField, { noMargin: props.noMargin, className: props.className, children: [
511
+ props.label && /* @__PURE__ */ jsxRuntime.jsx(InputLabel, { label: props.label, required: props.required }),
512
+ /* @__PURE__ */ jsxRuntime.jsx(
513
+ "textarea",
514
+ {
515
+ rows,
516
+ value: props.value ?? "",
517
+ placeholder: props.placeholder,
518
+ disabled: props.disabled,
519
+ onChange: (e) => props.onChange?.(e.target.value),
520
+ className: tailwindMerge.twMerge(inputBaseClass, "min-h-24 py-2", errorDisplay && "border-(--ui-danger)")
521
+ }
522
+ ),
523
+ errorDisplay && /* @__PURE__ */ jsxRuntime.jsx(InputError, { error: String(errorDisplay) })
524
+ ] });
525
+ };
482
526
  var numberInputClass = inputBaseClass + " [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none";
483
527
  var NumberInput = ({
484
528
  size = "middle",
@@ -586,6 +630,49 @@ var CheckboxInput = ({
586
630
  errorDisplay && /* @__PURE__ */ jsxRuntime.jsx(InputError, { error: String(errorDisplay), className: props.classNames?.error })
587
631
  ] });
588
632
  };
633
+ var RadioGroup = ({
634
+ direction = "column",
635
+ ...props
636
+ }) => {
637
+ const resolveError = useErrorResolver();
638
+ const resolvedErrors = props.errorName ? resolveError(props.errorName) : [];
639
+ const errorDisplay = props.error ?? props.customError ?? (resolvedErrors.length > 0 ? resolvedErrors.join(", ") : void 0);
640
+ return /* @__PURE__ */ jsxRuntime.jsxs(InputField, { noMargin: props.noMargin, className: props.className, children: [
641
+ props.label && /* @__PURE__ */ jsxRuntime.jsx(InputLabel, { label: props.label, required: props.required }),
642
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex gap-2", direction === "column" ? "flex-col" : "flex-wrap items-stretch"), children: props.options.map((option) => {
643
+ const checked = props.value === option.value;
644
+ const isDisabled = props.disabled || option.disabled;
645
+ return /* @__PURE__ */ jsxRuntime.jsxs(
646
+ "label",
647
+ {
648
+ className: tailwindMerge.twMerge(
649
+ "flex items-start gap-3 rounded-(--ui-radius-md) border border-(--ui-border) bg-white px-3 py-2",
650
+ checked && "border-(--ui-border-focus) bg-(--ui-surface-subtle)",
651
+ isDisabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
652
+ ),
653
+ children: [
654
+ /* @__PURE__ */ jsxRuntime.jsx(
655
+ "input",
656
+ {
657
+ type: "radio",
658
+ className: "mt-1 h-4 w-4 accent-(--ui-primary)",
659
+ checked,
660
+ disabled: isDisabled,
661
+ onChange: () => props.onChange?.(option.value)
662
+ }
663
+ ),
664
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0", children: [
665
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm text-(--ui-text)", children: option.label }),
666
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("block text-xs", neutralTextClasses.soft), children: option.description })
667
+ ] })
668
+ ]
669
+ },
670
+ option.value
671
+ );
672
+ }) }),
673
+ errorDisplay && /* @__PURE__ */ jsxRuntime.jsx(InputError, { error: String(errorDisplay) })
674
+ ] });
675
+ };
589
676
  var SwitchInput = ({
590
677
  value = false,
591
678
  size = "middle",
@@ -1297,6 +1384,65 @@ var ColorInput = ({
1297
1384
  errorDisplay && /* @__PURE__ */ jsxRuntime.jsx(InputError, { error: String(errorDisplay), className: props.classNames?.error })
1298
1385
  ] });
1299
1386
  };
1387
+ var SearchInput = ({ ...props }) => {
1388
+ const resolveError = useErrorResolver();
1389
+ const resolvedErrors = props.errorName ? resolveError(props.errorName) : [];
1390
+ const errorDisplay = props.error ?? props.customError ?? (resolvedErrors.length > 0 ? resolvedErrors.join(", ") : void 0);
1391
+ const hasValue = !!props.value;
1392
+ return /* @__PURE__ */ jsxRuntime.jsxs(InputField, { noMargin: props.noMargin, className: props.className, children: [
1393
+ props.label && /* @__PURE__ */ jsxRuntime.jsx(InputLabel, { label: props.label }),
1394
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1395
+ /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconSearch, { size: 15, strokeWidth: 1.75, className: tailwindMerge.twMerge("pointer-events-none absolute left-3 top-1/2 -translate-y-1/2", neutralIconClasses.default) }),
1396
+ /* @__PURE__ */ jsxRuntime.jsx(
1397
+ "input",
1398
+ {
1399
+ value: props.value ?? "",
1400
+ onChange: (e) => props.onChange?.(e.target.value),
1401
+ placeholder: props.placeholder ?? "Hledat...",
1402
+ className: tailwindMerge.twMerge(inputBaseClass, "pl-9 pr-9", errorDisplay && "border-(--ui-danger)")
1403
+ }
1404
+ ),
1405
+ hasValue && /* @__PURE__ */ jsxRuntime.jsx(
1406
+ "button",
1407
+ {
1408
+ type: "button",
1409
+ onClick: () => {
1410
+ props.onChange?.("");
1411
+ props.onClear?.();
1412
+ },
1413
+ className: tailwindMerge.twMerge("absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer", neutralIconClasses.default, neutralIconClasses.hover),
1414
+ children: /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconX, { size: 14, strokeWidth: 2 })
1415
+ }
1416
+ )
1417
+ ] }),
1418
+ errorDisplay && /* @__PURE__ */ jsxRuntime.jsx(InputError, { error: String(errorDisplay) })
1419
+ ] });
1420
+ };
1421
+ var InlineEdit = ({ value, placeholder = "Klikn\u011Bte pro editaci", multiline = false, onSave, label, className }) => {
1422
+ const [editing, setEditing] = react.useState(false);
1423
+ const [draft, setDraft] = react.useState(value ?? "");
1424
+ const cancel = () => {
1425
+ setDraft(value ?? "");
1426
+ setEditing(false);
1427
+ };
1428
+ const save = () => {
1429
+ onSave?.(draft);
1430
+ setEditing(false);
1431
+ };
1432
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("rounded-(--ui-radius-md) border border-(--ui-border) bg-white p-3", className), children: [
1433
+ label && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 text-xs font-medium uppercase tracking-[0.08em] text-(--ui-text-soft)", children: label }),
1434
+ editing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
1435
+ multiline ? /* @__PURE__ */ jsxRuntime.jsx(Textarea, { value: draft, onChange: setDraft, noMargin: true, rows: 4 }) : /* @__PURE__ */ jsxRuntime.jsx(TextInput, { value: draft, onChange: setDraft, noMargin: true }),
1436
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1437
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "small", text: "Ulo\u017Eit", icon: iconsReact.IconCheck, onClick: save }),
1438
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "small", variant: "default", text: "Zru\u0161it", icon: iconsReact.IconX, onClick: cancel })
1439
+ ] })
1440
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: () => setEditing(true), className: "flex w-full items-start justify-between gap-3 text-left cursor-pointer", children: [
1441
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: value ? "text-(--ui-text)" : tailwindMerge.twMerge("italic", neutralTextClasses.soft), children: value || placeholder }),
1442
+ /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconPencil, { size: 14, strokeWidth: 1.75, className: neutralTextClasses.soft })
1443
+ ] })
1444
+ ] });
1445
+ };
1300
1446
  var Empty = ({
1301
1447
  text = "\u017D\xE1dn\xE9 z\xE1znamy k dispozici",
1302
1448
  description,
@@ -1627,145 +1773,155 @@ var Grid = (props) => {
1627
1773
  const next = selectedKeys.has(key) ? props.selection.selectedItems.filter((s) => getKey2(s, props.items, props.rowKey) !== key) : [...props.selection.selectedItems, item];
1628
1774
  props.selection.onChange(next);
1629
1775
  };
1630
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("relative border border-(--ui-border) rounded-(--ui-radius-lg) overflow-hidden", props.className), children: [
1631
- props.loading && !isInitialLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("absolute inset-0 z-10 bg-white/60 flex items-center justify-center", props.classNames?.overlay), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "large", color: "primary" }) }),
1632
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: tailwindMerge.twMerge("w-full border-collapse", props.classNames?.table), children: [
1633
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: tailwindMerge.twMerge("bg-(--ui-primary) text-(--ui-primary-text)", props.classNames?.headerRow), children: [
1634
- props.selection && /* @__PURE__ */ jsxRuntime.jsx("th", { className: tailwindMerge.twMerge(sc.th, "w-9", verticalBorders && tableHeaderVerticalBorderClass, props.classNames?.headerCell), children: /* @__PURE__ */ jsxRuntime.jsx(
1635
- "input",
1636
- {
1637
- type: "checkbox",
1638
- checked: allSelected,
1639
- ref: (el) => {
1640
- if (el) el.indeterminate = someSelected;
1641
- },
1642
- onChange: toggleAll,
1643
- className: "cursor-pointer accent-white"
1644
- }
1645
- ) }),
1646
- props.columns.map((col, i) => {
1647
- const isSortable = col.sortBy !== void 0;
1648
- const isCurrent = isSortable && grid.sortBy === col.sortBy;
1649
- return /* @__PURE__ */ jsxRuntime.jsx(
1650
- "th",
1651
- {
1652
- style: { width: col.width ?? columnTypeWidth2[col.type] },
1653
- onClick: isSortable ? () => handleSort(col) : void 0,
1654
- className: tailwindMerge.twMerge(
1655
- sc.th,
1656
- "font-normal text-left whitespace-nowrap",
1657
- verticalBorders && tableHeaderVerticalBorderClass,
1658
- isSortable && "cursor-pointer select-none hover:bg-white/10",
1659
- col.align === "center" && "text-center",
1660
- col.align === "right" && "text-right",
1661
- props.classNames?.headerCell
1662
- ),
1663
- children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
1664
- col.title,
1665
- isSortable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-70", children: isCurrent ? grid.direction === SortDirection.Asc ? /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconChevronUp, { size: 12, strokeWidth: 2 }) : /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconChevronDown, { size: 12, strokeWidth: 2 }) : /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconSelector, { size: 12, strokeWidth: 2 }) })
1666
- ] })
1667
- },
1668
- i
1669
- );
1670
- })
1671
- ] }) }),
1672
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: isInitialLoading ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
1673
- "td",
1674
- {
1675
- colSpan: props.columns.length + (props.selection ? 1 : 0),
1676
- className: tailwindMerge.twMerge("px-3 py-0", props.classNames?.loadingCell),
1677
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-28 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "large", color: "primary" }) })
1678
- }
1679
- ) }) : isEmpty ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
1680
- "td",
1681
- {
1682
- colSpan: props.columns.length + (props.selection ? 1 : 0),
1683
- className: tailwindMerge.twMerge("px-3", props.classNames?.emptyCell),
1684
- children: /* @__PURE__ */ jsxRuntime.jsx(Empty, { size: "compact", text: props.emptyText ?? "\u017D\xE1dn\xE9 z\xE1znamy", className: sc.emptyPy })
1685
- }
1686
- ) }) : props.items.map((item, rowIdx) => {
1687
- const key = getKey2(item, props.items, props.rowKey);
1688
- const isSelected = selectedKeys.has(key);
1689
- return /* @__PURE__ */ jsxRuntime.jsxs(
1690
- "tr",
1691
- {
1692
- onClick: props.onRowClick ? () => props.onRowClick(item) : void 0,
1693
- className: tailwindMerge.twMerge(
1694
- "border-t border-(--ui-border) transition-colors",
1695
- rowIdx % 2 === 1 && !isSelected && neutralSurfaceClasses.subtle,
1696
- isSelected && "bg-blue-50",
1697
- props.onRowClick && "cursor-pointer hover:bg-blue-50",
1698
- props.classNames?.bodyRow
1699
- ),
1700
- children: [
1701
- props.selection && /* @__PURE__ */ jsxRuntime.jsx(
1702
- "td",
1776
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1777
+ "div",
1778
+ {
1779
+ className: tailwindMerge.twMerge(
1780
+ "relative border border-(--ui-border) rounded-(--ui-radius-lg) overflow-hidden",
1781
+ props.attachedTop && "rounded-t-none border-t-0",
1782
+ props.className
1783
+ ),
1784
+ children: [
1785
+ props.loading && !isInitialLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("absolute inset-0 z-10 bg-white/60 flex items-center justify-center", props.classNames?.overlay), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "large", color: "primary" }) }),
1786
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: tailwindMerge.twMerge("w-full border-collapse", props.classNames?.table), children: [
1787
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: tailwindMerge.twMerge("bg-(--ui-primary) text-(--ui-primary-text)", props.classNames?.headerRow), children: [
1788
+ props.selection && /* @__PURE__ */ jsxRuntime.jsx("th", { className: tailwindMerge.twMerge(sc.th, "w-9", verticalBorders && tableHeaderVerticalBorderClass, props.classNames?.headerCell), children: /* @__PURE__ */ jsxRuntime.jsx(
1789
+ "input",
1790
+ {
1791
+ type: "checkbox",
1792
+ checked: allSelected,
1793
+ ref: (el) => {
1794
+ if (el) el.indeterminate = someSelected;
1795
+ },
1796
+ onChange: toggleAll,
1797
+ className: "cursor-pointer accent-white"
1798
+ }
1799
+ ) }),
1800
+ props.columns.map((col, i) => {
1801
+ const isSortable = col.sortBy !== void 0;
1802
+ const isCurrent = isSortable && grid.sortBy === col.sortBy;
1803
+ return /* @__PURE__ */ jsxRuntime.jsx(
1804
+ "th",
1703
1805
  {
1704
- className: tailwindMerge.twMerge(sc.td, "w-9 align-middle", verticalBorders && tableCellVerticalBorderClass, props.classNames?.bodyCell),
1705
- onClick: (e) => e.stopPropagation(),
1706
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
1707
- "input",
1806
+ style: { width: col.width ?? columnTypeWidth2[col.type] },
1807
+ onClick: isSortable ? () => handleSort(col) : void 0,
1808
+ className: tailwindMerge.twMerge(
1809
+ sc.th,
1810
+ "font-normal text-left whitespace-nowrap",
1811
+ verticalBorders && tableHeaderVerticalBorderClass,
1812
+ isSortable && "cursor-pointer select-none hover:bg-white/10",
1813
+ col.align === "center" && "text-center",
1814
+ col.align === "right" && "text-right",
1815
+ props.classNames?.headerCell
1816
+ ),
1817
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
1818
+ col.title,
1819
+ isSortable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-70", children: isCurrent ? grid.direction === SortDirection.Asc ? /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconChevronUp, { size: 12, strokeWidth: 2 }) : /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconChevronDown, { size: 12, strokeWidth: 2 }) : /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconSelector, { size: 12, strokeWidth: 2 }) })
1820
+ ] })
1821
+ },
1822
+ i
1823
+ );
1824
+ })
1825
+ ] }) }),
1826
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: isInitialLoading ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
1827
+ "td",
1828
+ {
1829
+ colSpan: props.columns.length + (props.selection ? 1 : 0),
1830
+ className: tailwindMerge.twMerge("px-3 py-0", props.classNames?.loadingCell),
1831
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-28 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "large", color: "primary" }) })
1832
+ }
1833
+ ) }) : isEmpty ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
1834
+ "td",
1835
+ {
1836
+ colSpan: props.columns.length + (props.selection ? 1 : 0),
1837
+ className: tailwindMerge.twMerge("px-3", props.classNames?.emptyCell),
1838
+ children: /* @__PURE__ */ jsxRuntime.jsx(Empty, { size: "compact", text: props.emptyText ?? "\u017D\xE1dn\xE9 z\xE1znamy", className: sc.emptyPy })
1839
+ }
1840
+ ) }) : props.items.map((item, rowIdx) => {
1841
+ const key = getKey2(item, props.items, props.rowKey);
1842
+ const isSelected = selectedKeys.has(key);
1843
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1844
+ "tr",
1845
+ {
1846
+ onClick: props.onRowClick ? () => props.onRowClick(item) : void 0,
1847
+ className: tailwindMerge.twMerge(
1848
+ "border-t border-(--ui-border) transition-colors",
1849
+ rowIdx % 2 === 1 && !isSelected && neutralSurfaceClasses.subtle,
1850
+ isSelected && "bg-blue-50",
1851
+ props.onRowClick && "cursor-pointer hover:bg-blue-50",
1852
+ props.classNames?.bodyRow
1853
+ ),
1854
+ children: [
1855
+ props.selection && /* @__PURE__ */ jsxRuntime.jsx(
1856
+ "td",
1708
1857
  {
1709
- type: "checkbox",
1710
- checked: isSelected,
1711
- onChange: () => toggleRow(item),
1712
- className: "cursor-pointer"
1858
+ className: tailwindMerge.twMerge(sc.td, "w-9 align-middle", verticalBorders && tableCellVerticalBorderClass, props.classNames?.bodyCell),
1859
+ onClick: (e) => e.stopPropagation(),
1860
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
1861
+ "input",
1862
+ {
1863
+ type: "checkbox",
1864
+ checked: isSelected,
1865
+ onChange: () => toggleRow(item),
1866
+ className: "cursor-pointer"
1867
+ }
1868
+ ) })
1713
1869
  }
1714
- ) })
1715
- }
1716
- ),
1717
- props.columns.map((col, colIdx) => {
1718
- const content = col.render ? col.render(item) : col.dataField ? formatCellValue(item[col.dataField], col.type) : null;
1719
- const centeredContent = col.align === "center";
1720
- const rightAlignedContent = col.align === "right";
1721
- return /* @__PURE__ */ jsxRuntime.jsx(
1722
- "td",
1723
- {
1724
- onClick: col.type === "dot" ? (e) => e.stopPropagation() : void 0,
1725
- className: tailwindMerge.twMerge(
1726
- sc.td,
1727
- "align-middle",
1728
- verticalBorders && tableCellVerticalBorderClass,
1729
- col.ellipsis && "max-w-60 truncate",
1730
- col.wrap && "whitespace-normal",
1731
- col.align === "center" && "text-center",
1732
- col.align === "right" && "text-right",
1733
- col.type === "dot" && "w-9",
1734
- props.classNames?.bodyCell
1735
- ),
1736
- children: centeredContent || rightAlignedContent ? /* @__PURE__ */ jsxRuntime.jsx(
1737
- "div",
1870
+ ),
1871
+ props.columns.map((col, colIdx) => {
1872
+ const content = col.render ? col.render(item) : col.dataField ? formatCellValue(item[col.dataField], col.type) : null;
1873
+ const centeredContent = col.align === "center";
1874
+ const rightAlignedContent = col.align === "right";
1875
+ return /* @__PURE__ */ jsxRuntime.jsx(
1876
+ "td",
1738
1877
  {
1878
+ onClick: col.type === "dot" ? (e) => e.stopPropagation() : void 0,
1739
1879
  className: tailwindMerge.twMerge(
1740
- "flex w-full items-center",
1741
- centeredContent ? "justify-center" : "justify-end"
1880
+ sc.td,
1881
+ "align-middle",
1882
+ verticalBorders && tableCellVerticalBorderClass,
1883
+ col.ellipsis && "max-w-60 truncate",
1884
+ col.wrap && "whitespace-normal",
1885
+ col.align === "center" && "text-center",
1886
+ col.align === "right" && "text-right",
1887
+ col.type === "dot" && "w-9",
1888
+ props.classNames?.bodyCell
1742
1889
  ),
1743
- children: content
1744
- }
1745
- ) : content
1746
- },
1747
- colIdx
1748
- );
1749
- })
1750
- ]
1751
- },
1752
- key
1753
- );
1754
- }) })
1755
- ] }) }),
1756
- /* @__PURE__ */ jsxRuntime.jsx(
1757
- Pagination,
1758
- {
1759
- current: grid.pageNumber,
1760
- pageSize: grid.pageSize,
1761
- total: props.totalCount,
1762
- showPageNumberChanger: props.showPageNumberChanger ?? false,
1763
- showPageSizeChanger: props.showPageSizeChanger ?? false,
1764
- onChange: (page, pageSize) => grid.onChange({ pageNumber: page, pageSize }),
1765
- classNames: props.classNames?.pagination
1766
- }
1767
- )
1768
- ] });
1890
+ children: centeredContent || rightAlignedContent ? /* @__PURE__ */ jsxRuntime.jsx(
1891
+ "div",
1892
+ {
1893
+ className: tailwindMerge.twMerge(
1894
+ "flex w-full items-center",
1895
+ centeredContent ? "justify-center" : "justify-end"
1896
+ ),
1897
+ children: content
1898
+ }
1899
+ ) : content
1900
+ },
1901
+ colIdx
1902
+ );
1903
+ })
1904
+ ]
1905
+ },
1906
+ key
1907
+ );
1908
+ }) })
1909
+ ] }) }),
1910
+ /* @__PURE__ */ jsxRuntime.jsx(
1911
+ Pagination,
1912
+ {
1913
+ current: grid.pageNumber,
1914
+ pageSize: grid.pageSize,
1915
+ total: props.totalCount,
1916
+ showPageNumberChanger: props.showPageNumberChanger ?? false,
1917
+ showPageSizeChanger: props.showPageSizeChanger ?? false,
1918
+ onChange: (page, pageSize) => grid.onChange({ pageNumber: page, pageSize }),
1919
+ classNames: props.classNames?.pagination
1920
+ }
1921
+ )
1922
+ ]
1923
+ }
1924
+ );
1769
1925
  };
1770
1926
  function isValueSet(v) {
1771
1927
  if (Array.isArray(v)) return v.length > 0;
@@ -3390,31 +3546,214 @@ var Panel = ({
3390
3546
  }
3391
3547
  );
3392
3548
  };
3549
+ var Toolbar = ({ children, start, end, wrapped = true, inset = false, className, classNames }) => /* @__PURE__ */ jsxRuntime.jsxs(
3550
+ "div",
3551
+ {
3552
+ className: tailwindMerge.twMerge(
3553
+ "flex items-center justify-between gap-3 rounded-(--ui-radius-lg) border border-(--ui-border)",
3554
+ neutralSurfaceClasses.subtle,
3555
+ wrapped && "flex-wrap",
3556
+ inset ? "px-3 py-2" : "px-4 py-3",
3557
+ className
3558
+ ),
3559
+ children: [
3560
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex min-w-0 flex-1 items-center gap-2", wrapped && "flex-wrap", classNames?.start), children: start ?? children }),
3561
+ end && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex items-center gap-2", wrapped && "flex-wrap justify-end", classNames?.end), children: end })
3562
+ ]
3563
+ }
3564
+ );
3565
+ var ActionBar = Toolbar;
3566
+ var SectionHeader = ({ title, subtitle, actions, className }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("flex items-start justify-between gap-4", className), children: [
3567
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
3568
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-(--ui-text-strong)", children: title }),
3569
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: tailwindMerge.twMerge("mt-1 text-sm", neutralTextClasses.muted), children: subtitle })
3570
+ ] }),
3571
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-2", children: actions })
3572
+ ] });
3573
+ var PageHeader = ({ title, subtitle, breadcrumbs, actions, extra, className }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("rounded-(--ui-radius-lg) border border-(--ui-border) bg-white p-5", className), children: [
3574
+ breadcrumbs && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("mb-2 text-xs", neutralTextClasses.soft), children: breadcrumbs }),
3575
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
3576
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
3577
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-semibold text-(--ui-text-strong)", children: title }),
3578
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: tailwindMerge.twMerge("mt-1 text-sm", neutralTextClasses.muted), children: subtitle })
3579
+ ] }),
3580
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-2", children: actions })
3581
+ ] }),
3582
+ extra && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 border-t border-(--ui-border) pt-4", children: extra })
3583
+ ] });
3584
+ var AVATAR_COLORS = [
3585
+ "bg-blue-500",
3586
+ "bg-green-500",
3587
+ "bg-purple-500",
3588
+ "bg-orange-500",
3589
+ "bg-pink-500",
3590
+ "bg-teal-500",
3591
+ "bg-red-500",
3592
+ "bg-indigo-500"
3593
+ ];
3594
+ function colorFromString(str) {
3595
+ let hash = 0;
3596
+ for (let i = 0; i < str.length; i++) {
3597
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
3598
+ }
3599
+ return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
3600
+ }
3601
+ function getInitials(name) {
3602
+ const parts = name.trim().split(/\s+/);
3603
+ if (parts.length === 1) {
3604
+ return parts[0].slice(0, 2).toUpperCase();
3605
+ }
3606
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
3607
+ }
3608
+ var sizeClasses = {
3609
+ xs: "w-6 h-6 text-[10px]",
3610
+ sm: "w-7 h-7 text-xs",
3611
+ md: "w-8 h-8 text-sm",
3612
+ lg: "w-10 h-10 text-base",
3613
+ xl: "w-12 h-12 text-lg"
3614
+ };
3615
+ var Avatar = ({ size = "md", ...props }) => {
3616
+ const initials = props.name ? getInitials(props.name) : "?";
3617
+ const bgColor = props.color ?? (props.name ? colorFromString(props.name) : "bg-gray-400");
3618
+ if (props.src) {
3619
+ return /* @__PURE__ */ jsxRuntime.jsx(
3620
+ "img",
3621
+ {
3622
+ src: props.src,
3623
+ alt: props.name ?? "avatar",
3624
+ className: tailwindMerge.twMerge(
3625
+ "rounded-full object-cover shrink-0",
3626
+ sizeClasses[size],
3627
+ props.className
3628
+ )
3629
+ }
3630
+ );
3631
+ }
3632
+ return /* @__PURE__ */ jsxRuntime.jsx(
3633
+ "span",
3634
+ {
3635
+ title: props.name,
3636
+ className: tailwindMerge.twMerge(
3637
+ "inline-flex items-center justify-center rounded-full text-white font-medium shrink-0 select-none",
3638
+ sizeClasses[size],
3639
+ bgColor,
3640
+ props.className
3641
+ ),
3642
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: props.initialsClassName, children: initials })
3643
+ }
3644
+ );
3645
+ };
3646
+ var EntityHeader = ({ title, subtitle, avatarName, icon: Icon, meta, tags, actions, className }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("rounded-(--ui-radius-lg) border border-(--ui-border) bg-white p-5", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
3647
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-start gap-3", children: [
3648
+ avatarName ? /* @__PURE__ */ jsxRuntime.jsx(Avatar, { name: avatarName, size: "lg" }) : Icon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-11 items-center justify-center rounded-(--ui-radius-lg) bg-(--ui-surface-subtle)", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: 20, strokeWidth: 1.8, className: "text-(--ui-text)" }) }) : null,
3649
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
3650
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xl font-semibold text-(--ui-text-strong)", children: title }),
3651
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("mt-1 text-sm", neutralTextClasses.muted), children: subtitle }),
3652
+ (meta || tags) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
3653
+ meta,
3654
+ tags
3655
+ ] })
3656
+ ] })
3657
+ ] }),
3658
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-2", children: actions })
3659
+ ] }) });
3660
+ var alignClass3 = {
3661
+ left: "justify-start",
3662
+ center: "justify-center",
3663
+ right: "justify-end",
3664
+ between: "justify-between"
3665
+ };
3666
+ var FormActions = ({ children, align = "right", className }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex flex-wrap items-center gap-2 border-t border-(--ui-border) pt-4", alignClass3[align], className), children });
3667
+ var FormSection = ({ title, description, actions, children, className }) => /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className: tailwindMerge.twMerge("rounded-(--ui-radius-lg) border border-(--ui-border) bg-white p-4", className), children: [
3668
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-start justify-between gap-4", children: [
3669
+ /* @__PURE__ */ jsxRuntime.jsxs("legend", { className: "min-w-0", children: [
3670
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-(--ui-text-strong)", children: title }),
3671
+ description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("mt-1 text-xs", neutralTextClasses.soft), children: description })
3672
+ ] }),
3673
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: actions })
3674
+ ] }),
3675
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children })
3676
+ ] });
3677
+ var Fieldset = FormSection;
3678
+ var listVariantClass = {
3679
+ segmented: "inline-flex gap-0 rounded-(--ui-radius-lg) p-1",
3680
+ underline: "inline-flex gap-1 border-b border-(--ui-border-strong)",
3681
+ cards: "inline-flex gap-2"
3682
+ };
3683
+ var listSurfaceClass = {
3684
+ segmented: neutralSurfaceClasses.subtle,
3685
+ underline: "",
3686
+ cards: ""
3687
+ };
3688
+ var tabSizeClass = {
3689
+ small: "h-8 px-3 text-[12px]",
3690
+ middle: "h-9 px-4 text-[14px]",
3691
+ large: "h-10 px-5 text-[15px]"
3692
+ };
3693
+ var tabVariantClass = {
3694
+ segmented: "rounded-[calc(var(--ui-radius-lg)-4px)]",
3695
+ underline: "border-b-2 border-transparent rounded-none -mb-px",
3696
+ cards: "rounded-(--ui-radius-lg) border border-(--ui-border) bg-white shadow-sm"
3697
+ };
3698
+ var activeVariantClass = {
3699
+ segmented: "bg-white text-(--ui-text-strong) shadow-sm font-semibold",
3700
+ underline: "border-(--ui-primary) text-(--ui-text-strong) font-semibold",
3701
+ cards: "border-(--ui-border-focus) bg-(--ui-surface-subtle) text-(--ui-text-strong) font-semibold shadow-none"
3702
+ };
3703
+ var inactiveVariantClass = {
3704
+ segmented: "text-(--ui-text-muted) hover:text-(--ui-text)",
3705
+ underline: "text-(--ui-text-muted) hover:text-(--ui-text)",
3706
+ cards: "text-(--ui-text-muted) hover:border-(--ui-border-focus) hover:text-(--ui-text)"
3707
+ };
3393
3708
  var Tabs = ({
3394
3709
  block = true,
3710
+ variant = "segmented",
3711
+ size = "middle",
3395
3712
  ...props
3396
3713
  }) => /* @__PURE__ */ jsxRuntime.jsx(
3397
3714
  "div",
3398
3715
  {
3716
+ role: "tablist",
3399
3717
  className: tailwindMerge.twMerge(
3400
- "inline-flex gap-0 rounded-(--ui-radius-lg) p-1",
3401
- neutralSurfaceClasses.subtle,
3718
+ listVariantClass[variant],
3719
+ listSurfaceClass[variant],
3402
3720
  block && "flex w-full",
3403
3721
  props.className,
3404
3722
  props.classNames?.list
3405
3723
  ),
3406
- children: props.options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
3724
+ children: props.options.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
3407
3725
  "button",
3408
3726
  {
3409
3727
  type: "button",
3410
- onClick: () => props.onChange(opt.value),
3728
+ role: "tab",
3729
+ "aria-selected": props.value === opt.value,
3730
+ disabled: opt.disabled,
3731
+ onClick: () => !opt.disabled && props.onChange(opt.value),
3411
3732
  className: tailwindMerge.twMerge(
3412
- "flex-1 h-9 px-4 text-[14px] rounded-[calc(var(--ui-radius-lg)-4px)] transition-all duration-150 cursor-pointer select-none whitespace-nowrap",
3413
- props.value === opt.value ? "bg-white text-(--ui-text-strong) shadow-sm font-semibold" : "text-(--ui-text-muted) hover:text-(--ui-text)",
3733
+ "flex-1 min-w-0 transition-all duration-150 cursor-pointer select-none whitespace-nowrap",
3734
+ "inline-flex items-center justify-center gap-2",
3735
+ tabSizeClass[size],
3736
+ tabVariantClass[variant],
3737
+ props.value === opt.value ? activeVariantClass[variant] : inactiveVariantClass[variant],
3738
+ opt.disabled && "cursor-not-allowed opacity-45 hover:border-(--ui-border) hover:text-(--ui-text-muted)",
3414
3739
  props.classNames?.tab,
3415
3740
  props.value === opt.value ? props.classNames?.activeTab : props.classNames?.inactiveTab
3416
3741
  ),
3417
- children: opt.label
3742
+ children: [
3743
+ opt.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("shrink-0", props.classNames?.icon), children: opt.icon }),
3744
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: opt.label }),
3745
+ opt.badge && /* @__PURE__ */ jsxRuntime.jsx(
3746
+ "span",
3747
+ {
3748
+ className: tailwindMerge.twMerge(
3749
+ "shrink-0 rounded-full px-2 py-0.5 text-[11px] leading-none",
3750
+ props.value === opt.value ? "bg-(--ui-primary) text-(--ui-primary-text)" : "bg-(--ui-surface-muted) text-(--ui-text-muted)",
3751
+ props.classNames?.badge
3752
+ ),
3753
+ children: opt.badge
3754
+ }
3755
+ )
3756
+ ]
3418
3757
  },
3419
3758
  opt.value
3420
3759
  ))
@@ -3496,68 +3835,6 @@ var FlagTag = ({ value, label, color = "geekblue", variant }) => {
3496
3835
  }
3497
3836
  return /* @__PURE__ */ jsxRuntime.jsx(Tag, { color, variant, children: label });
3498
3837
  };
3499
- var AVATAR_COLORS = [
3500
- "bg-blue-500",
3501
- "bg-green-500",
3502
- "bg-purple-500",
3503
- "bg-orange-500",
3504
- "bg-pink-500",
3505
- "bg-teal-500",
3506
- "bg-red-500",
3507
- "bg-indigo-500"
3508
- ];
3509
- function colorFromString(str) {
3510
- let hash = 0;
3511
- for (let i = 0; i < str.length; i++) {
3512
- hash = str.charCodeAt(i) + ((hash << 5) - hash);
3513
- }
3514
- return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
3515
- }
3516
- function getInitials(name) {
3517
- const parts = name.trim().split(/\s+/);
3518
- if (parts.length === 1) {
3519
- return parts[0].slice(0, 2).toUpperCase();
3520
- }
3521
- return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
3522
- }
3523
- var sizeClasses = {
3524
- xs: "w-6 h-6 text-[10px]",
3525
- sm: "w-7 h-7 text-xs",
3526
- md: "w-8 h-8 text-sm",
3527
- lg: "w-10 h-10 text-base",
3528
- xl: "w-12 h-12 text-lg"
3529
- };
3530
- var Avatar = ({ size = "md", ...props }) => {
3531
- const initials = props.name ? getInitials(props.name) : "?";
3532
- const bgColor = props.color ?? (props.name ? colorFromString(props.name) : "bg-gray-400");
3533
- if (props.src) {
3534
- return /* @__PURE__ */ jsxRuntime.jsx(
3535
- "img",
3536
- {
3537
- src: props.src,
3538
- alt: props.name ?? "avatar",
3539
- className: tailwindMerge.twMerge(
3540
- "rounded-full object-cover shrink-0",
3541
- sizeClasses[size],
3542
- props.className
3543
- )
3544
- }
3545
- );
3546
- }
3547
- return /* @__PURE__ */ jsxRuntime.jsx(
3548
- "span",
3549
- {
3550
- title: props.name,
3551
- className: tailwindMerge.twMerge(
3552
- "inline-flex items-center justify-center rounded-full text-white font-medium shrink-0 select-none",
3553
- sizeClasses[size],
3554
- bgColor,
3555
- props.className
3556
- ),
3557
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: props.initialsClassName, children: initials })
3558
- }
3559
- );
3560
- };
3561
3838
  var defaultToolbar = [
3562
3839
  "bold",
3563
3840
  "italic",
@@ -4231,6 +4508,88 @@ var useNotification = () => {
4231
4508
  info: (message, options) => add("info", message, options)
4232
4509
  };
4233
4510
  };
4511
+ var EmptyState = ({
4512
+ primaryActionText,
4513
+ onPrimaryAction,
4514
+ secondaryActionText,
4515
+ onSecondaryAction,
4516
+ extra,
4517
+ className,
4518
+ classNames,
4519
+ ...props
4520
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("rounded-(--ui-radius-lg) border border-(--ui-border) bg-white", className), children: [
4521
+ /* @__PURE__ */ jsxRuntime.jsx(Empty, { className: "py-10", ...props }),
4522
+ (primaryActionText || secondaryActionText || extra) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("flex flex-wrap items-center justify-center gap-2 px-4 pb-6", classNames?.actions), children: [
4523
+ secondaryActionText && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "default", text: secondaryActionText, onClick: onSecondaryAction }),
4524
+ primaryActionText && /* @__PURE__ */ jsxRuntime.jsx(Button, { text: primaryActionText, onClick: onPrimaryAction }),
4525
+ extra && /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames?.extra, children: extra })
4526
+ ] })
4527
+ ] });
4528
+ var trendConfig = {
4529
+ up: {
4530
+ icon: iconsReact.IconArrowUpRight,
4531
+ className: "text-(--ui-success)"
4532
+ },
4533
+ down: {
4534
+ icon: iconsReact.IconArrowDownRight,
4535
+ className: "text-(--ui-danger)"
4536
+ },
4537
+ neutral: {
4538
+ icon: iconsReact.IconMinus,
4539
+ className: neutralTextClasses.soft
4540
+ }
4541
+ };
4542
+ var StatCard = ({ label, value, description, icon: Icon, trend, footer, className }) => {
4543
+ const trendDirection = trend?.direction ?? "neutral";
4544
+ const TrendIcon = trend ? trendConfig[trendDirection].icon : null;
4545
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("rounded-(--ui-radius-lg) border border-(--ui-border) bg-white p-4 shadow-sm", className), children: [
4546
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
4547
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
4548
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: tailwindMerge.twMerge("text-sm", neutralTextClasses.muted), children: label }),
4549
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-2xl font-semibold text-(--ui-text-strong)", children: value }),
4550
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: tailwindMerge.twMerge("mt-1 text-xs", neutralTextClasses.soft), children: description })
4551
+ ] }),
4552
+ Icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex h-10 w-10 items-center justify-center rounded-(--ui-radius-lg)", neutralSurfaceClasses.subtle), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: 18, strokeWidth: 1.75, className: neutralTextClasses.default }) })
4553
+ ] }),
4554
+ trend && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center gap-2 text-sm", children: [
4555
+ TrendIcon && /* @__PURE__ */ jsxRuntime.jsx(TrendIcon, { size: 15, strokeWidth: 2, className: trendConfig[trendDirection].className }),
4556
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("font-medium", trendConfig[trendDirection].className), children: trend.value }),
4557
+ trend.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: neutralTextClasses.soft, children: trend.label })
4558
+ ] }),
4559
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 border-t border-(--ui-border) pt-3", children: footer })
4560
+ ] });
4561
+ };
4562
+ var DescriptionList = ({ items, columns = 2, className }) => /* @__PURE__ */ jsxRuntime.jsx(
4563
+ "div",
4564
+ {
4565
+ className: tailwindMerge.twMerge(
4566
+ "grid gap-x-6 gap-y-4 rounded-(--ui-radius-lg) border border-(--ui-border) bg-white p-4",
4567
+ columns === 1 && "grid-cols-1",
4568
+ columns === 2 && "grid-cols-1 md:grid-cols-2",
4569
+ columns === 3 && "grid-cols-1 md:grid-cols-3",
4570
+ className
4571
+ ),
4572
+ children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
4573
+ "div",
4574
+ {
4575
+ className: tailwindMerge.twMerge(
4576
+ "min-w-0",
4577
+ item.span === 2 && columns > 1 && "md:col-span-2",
4578
+ item.span === 3 && columns > 2 && "md:col-span-3"
4579
+ ),
4580
+ children: [
4581
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: tailwindMerge.twMerge("text-xs font-medium uppercase tracking-[0.08em]", neutralTextClasses.soft), children: item.label }),
4582
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "mt-1 text-sm text-(--ui-text)", children: item.value })
4583
+ ]
4584
+ },
4585
+ index
4586
+ ))
4587
+ }
4588
+ );
4589
+ var KeyValue = ({ label, value, className }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("flex items-start justify-between gap-4 border-b border-(--ui-border) py-2 last:border-b-0", className), children: [
4590
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("text-sm", neutralTextClasses.muted), children: label }),
4591
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-right text-sm text-(--ui-text)", children: value })
4592
+ ] });
4234
4593
  var Pretty = ({ data, className }) => /* @__PURE__ */ jsxRuntime.jsx(
4235
4594
  "pre",
4236
4595
  {
@@ -4241,6 +4600,10 @@ var Pretty = ({ data, className }) => /* @__PURE__ */ jsxRuntime.jsx(
4241
4600
  children: JSON.stringify(data, null, 2)
4242
4601
  }
4243
4602
  );
4603
+ var SkeletonTable = ({ rows = 5, columns = 4, className }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("overflow-hidden rounded-(--ui-radius-lg) border border-(--ui-border) bg-white", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse", children: [
4604
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid bg-(--ui-primary) px-4 py-3", style: { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` }, children: Array.from({ length: columns }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 w-20 rounded bg-white/30" }, index)) }),
4605
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-(--ui-border)", children: Array.from({ length: rows }).map((_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-4 px-4 py-3", style: { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` }, children: Array.from({ length: columns }).map((__, columnIndex) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 rounded bg-(--ui-surface-muted)" }, columnIndex)) }, rowIndex)) })
4606
+ ] }) });
4244
4607
  var GAP2 = 10;
4245
4608
  var VIEWPORT_MARGIN2 = 8;
4246
4609
  function calcPosition3(trigger, tooltip, placement) {
@@ -4395,6 +4758,47 @@ var Tooltip = ({
4395
4758
  )
4396
4759
  ] });
4397
4760
  };
4761
+ var Stepper = ({ items, className }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex flex-wrap gap-4", className), children: items.map((item, index) => {
4762
+ const status = item.status ?? "upcoming";
4763
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-40 flex-1 items-start gap-3", children: [
4764
+ /* @__PURE__ */ jsxRuntime.jsx(
4765
+ "div",
4766
+ {
4767
+ className: tailwindMerge.twMerge(
4768
+ "mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full border text-xs font-semibold",
4769
+ status === "complete" && "border-(--ui-success) bg-(--ui-success) text-white",
4770
+ status === "current" && "border-(--ui-primary) bg-(--ui-primary) text-white",
4771
+ status === "upcoming" && "border-(--ui-border) bg-white text-(--ui-text-soft)"
4772
+ ),
4773
+ children: status === "complete" ? /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconCheck, { size: 14, strokeWidth: 2.5 }) : index + 1
4774
+ }
4775
+ ),
4776
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
4777
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("text-sm font-medium", status === "upcoming" ? neutralTextClasses.muted : "text-(--ui-text-strong)"), children: item.title }),
4778
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("mt-1 text-xs", neutralTextClasses.soft), children: item.description })
4779
+ ] })
4780
+ ] }, index);
4781
+ }) });
4782
+ var colorClass = {
4783
+ primary: "bg-(--ui-primary)",
4784
+ success: "bg-(--ui-success)",
4785
+ danger: "bg-(--ui-danger)",
4786
+ warning: "bg-(--ui-warning)",
4787
+ neutral: "bg-(--ui-border-strong)"
4788
+ };
4789
+ var Timeline = ({ items, className }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("space-y-4", className), children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex gap-3 pl-1", children: [
4790
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col items-center", children: [
4791
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("mt-1 h-2.5 w-2.5 rounded-full", colorClass[item.color ?? "primary"]) }),
4792
+ index < items.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 h-full w-px bg-(--ui-border)" })
4793
+ ] }),
4794
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 pb-4", children: [
4795
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4796
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-(--ui-text-strong)", children: item.title }),
4797
+ item.time && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("text-xs", neutralTextClasses.soft), children: item.time })
4798
+ ] }),
4799
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("mt-1 text-sm", neutralTextClasses.muted), children: item.description })
4800
+ ] })
4801
+ ] }, index)) });
4398
4802
 
4399
4803
  // src/initUI.ts
4400
4804
  function initUI(config) {
@@ -4508,6 +4912,7 @@ function initUI(config) {
4508
4912
  r.style.setProperty("--ui-empty-compact-description", layout.empty.compactDescription);
4509
4913
  }
4510
4914
 
4915
+ exports.ActionBar = ActionBar;
4511
4916
  exports.ActiveTag = ActiveTag;
4512
4917
  exports.Alert = Alert;
4513
4918
  exports.Avatar = Avatar;
@@ -4515,14 +4920,19 @@ exports.Badge = Badge;
4515
4920
  exports.Button = Button;
4516
4921
  exports.CheckboxInput = CheckboxInput;
4517
4922
  exports.ColorInput = ColorInput;
4923
+ exports.ConfirmButton = ConfirmButton;
4518
4924
  exports.DateInput = DateInput;
4925
+ exports.DescriptionList = DescriptionList;
4519
4926
  exports.Drawer = Drawer;
4520
4927
  exports.DrawerContent = DrawerContent;
4521
4928
  exports.DrawerFooter = DrawerFooter;
4522
4929
  exports.DrawerTitle = DrawerTitle;
4523
4930
  exports.Dropdown = Dropdown;
4524
4931
  exports.Empty = Empty;
4932
+ exports.EmptyState = EmptyState;
4933
+ exports.EntityHeader = EntityHeader;
4525
4934
  exports.ErrorProvider = ErrorProvider;
4935
+ exports.Fieldset = Fieldset;
4526
4936
  exports.FilterCheckboxInput = FilterCheckboxInput;
4527
4937
  exports.FilterDateInput = FilterDateInput;
4528
4938
  exports.FilterDateRangePopover = FilterDateRangePopover;
@@ -4531,12 +4941,16 @@ exports.FilterSelectGroupPopover = FilterSelectGroupPopover;
4531
4941
  exports.FilterSelectInput = FilterSelectInput;
4532
4942
  exports.FilterTextInput = FilterTextInput;
4533
4943
  exports.FlagTag = FlagTag;
4944
+ exports.FormActions = FormActions;
4945
+ exports.FormSection = FormSection;
4534
4946
  exports.Grid = Grid;
4535
4947
  exports.GridFilters = GridFilters;
4536
4948
  exports.HtmlInput = HtmlInput;
4949
+ exports.InlineEdit = InlineEdit;
4537
4950
  exports.InputError = InputError;
4538
4951
  exports.InputField = InputField;
4539
4952
  exports.InputLabel = InputLabel;
4953
+ exports.KeyValue = KeyValue;
4540
4954
  exports.Modal = Modal;
4541
4955
  exports.ModalContent = ModalContent;
4542
4956
  exports.ModalFooter = ModalFooter;
@@ -4544,19 +4958,29 @@ exports.ModalTitle = ModalTitle;
4544
4958
  exports.MultiSelectInput = MultiSelectInput;
4545
4959
  exports.NotificationProvider = NotificationProvider;
4546
4960
  exports.NumberInput = NumberInput;
4961
+ exports.PageHeader = PageHeader;
4547
4962
  exports.Panel = Panel;
4548
4963
  exports.Popconfirm = Popconfirm;
4549
4964
  exports.Pretty = Pretty;
4965
+ exports.RadioGroup = RadioGroup;
4966
+ exports.SearchInput = SearchInput;
4967
+ exports.SectionHeader = SectionHeader;
4550
4968
  exports.SelectInput = SelectInput;
4551
4969
  exports.ServerError = ServerError;
4552
4970
  exports.Skeleton = Skeleton;
4971
+ exports.SkeletonTable = SkeletonTable;
4553
4972
  exports.SortDirection = SortDirection;
4554
4973
  exports.Spinner = Spinner;
4974
+ exports.StatCard = StatCard;
4975
+ exports.Stepper = Stepper;
4555
4976
  exports.SwitchInput = SwitchInput;
4556
4977
  exports.Table = Table;
4557
4978
  exports.Tabs = Tabs;
4558
4979
  exports.Tag = Tag;
4559
4980
  exports.TextInput = TextInput;
4981
+ exports.Textarea = Textarea;
4982
+ exports.Timeline = Timeline;
4983
+ exports.Toolbar = Toolbar;
4560
4984
  exports.Tooltip = Tooltip;
4561
4985
  exports.UploadInput = UploadInput;
4562
4986
  exports.UploadProvider = UploadProvider;