@martinsura/ui 0.1.3 → 0.1.5

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,34 +3546,220 @@ 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(
3407
- "button",
3408
- {
3409
- type: "button",
3410
- onClick: () => props.onChange(opt.value),
3411
- 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)",
3414
- props.classNames?.tab,
3415
- props.value === opt.value ? props.classNames?.activeTab : props.classNames?.inactiveTab
3416
- ),
3417
- children: opt.label
3418
- },
3419
- opt.value
3420
- ))
3724
+ children: props.options.map((opt) => {
3725
+ const isSimpleLabel = typeof opt.label === "string" || typeof opt.label === "number";
3726
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3727
+ "button",
3728
+ {
3729
+ type: "button",
3730
+ role: "tab",
3731
+ "aria-selected": props.value === opt.value,
3732
+ disabled: opt.disabled,
3733
+ onClick: () => !opt.disabled && props.onChange(opt.value),
3734
+ className: tailwindMerge.twMerge(
3735
+ "flex-1 min-w-0 transition-all duration-150 cursor-pointer select-none whitespace-nowrap",
3736
+ "inline-flex items-center justify-center gap-2",
3737
+ tabSizeClass[size],
3738
+ tabVariantClass[variant],
3739
+ props.value === opt.value ? activeVariantClass[variant] : inactiveVariantClass[variant],
3740
+ opt.disabled && "cursor-not-allowed opacity-45 hover:border-(--ui-border) hover:text-(--ui-text-muted)",
3741
+ props.classNames?.tab,
3742
+ props.value === opt.value ? props.classNames?.activeTab : props.classNames?.inactiveTab
3743
+ ),
3744
+ children: [
3745
+ opt.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("shrink-0", props.classNames?.icon), children: opt.icon }),
3746
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("min-w-0", isSimpleLabel && "truncate"), children: opt.label }),
3747
+ opt.badge && /* @__PURE__ */ jsxRuntime.jsx(
3748
+ "span",
3749
+ {
3750
+ className: tailwindMerge.twMerge(
3751
+ "shrink-0 rounded-full px-2 py-0.5 text-[11px] leading-none",
3752
+ props.value === opt.value ? "bg-(--ui-primary) text-(--ui-primary-text)" : "bg-(--ui-surface-muted) text-(--ui-text-muted)",
3753
+ props.classNames?.badge
3754
+ ),
3755
+ children: opt.badge
3756
+ }
3757
+ )
3758
+ ]
3759
+ },
3760
+ opt.value
3761
+ );
3762
+ })
3421
3763
  }
3422
3764
  );
3423
3765
  var colorClasses = {
@@ -3496,68 +3838,6 @@ var FlagTag = ({ value, label, color = "geekblue", variant }) => {
3496
3838
  }
3497
3839
  return /* @__PURE__ */ jsxRuntime.jsx(Tag, { color, variant, children: label });
3498
3840
  };
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
3841
  var defaultToolbar = [
3562
3842
  "bold",
3563
3843
  "italic",
@@ -4231,6 +4511,88 @@ var useNotification = () => {
4231
4511
  info: (message, options) => add("info", message, options)
4232
4512
  };
4233
4513
  };
4514
+ var EmptyState = ({
4515
+ primaryActionText,
4516
+ onPrimaryAction,
4517
+ secondaryActionText,
4518
+ onSecondaryAction,
4519
+ extra,
4520
+ className,
4521
+ classNames,
4522
+ ...props
4523
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("rounded-(--ui-radius-lg) border border-(--ui-border) bg-white", className), children: [
4524
+ /* @__PURE__ */ jsxRuntime.jsx(Empty, { className: "py-10", ...props }),
4525
+ (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: [
4526
+ secondaryActionText && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "default", text: secondaryActionText, onClick: onSecondaryAction }),
4527
+ primaryActionText && /* @__PURE__ */ jsxRuntime.jsx(Button, { text: primaryActionText, onClick: onPrimaryAction }),
4528
+ extra && /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames?.extra, children: extra })
4529
+ ] })
4530
+ ] });
4531
+ var trendConfig = {
4532
+ up: {
4533
+ icon: iconsReact.IconArrowUpRight,
4534
+ className: "text-(--ui-success)"
4535
+ },
4536
+ down: {
4537
+ icon: iconsReact.IconArrowDownRight,
4538
+ className: "text-(--ui-danger)"
4539
+ },
4540
+ neutral: {
4541
+ icon: iconsReact.IconMinus,
4542
+ className: neutralTextClasses.soft
4543
+ }
4544
+ };
4545
+ var StatCard = ({ label, value, description, icon: Icon, trend, footer, className }) => {
4546
+ const trendDirection = trend?.direction ?? "neutral";
4547
+ const TrendIcon = trend ? trendConfig[trendDirection].icon : null;
4548
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("rounded-(--ui-radius-lg) border border-(--ui-border) bg-white p-4 shadow-sm", className), children: [
4549
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
4550
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
4551
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: tailwindMerge.twMerge("text-sm", neutralTextClasses.muted), children: label }),
4552
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-2xl font-semibold text-(--ui-text-strong)", children: value }),
4553
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: tailwindMerge.twMerge("mt-1 text-xs", neutralTextClasses.soft), children: description })
4554
+ ] }),
4555
+ 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 }) })
4556
+ ] }),
4557
+ trend && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center gap-2 text-sm", children: [
4558
+ TrendIcon && /* @__PURE__ */ jsxRuntime.jsx(TrendIcon, { size: 15, strokeWidth: 2, className: trendConfig[trendDirection].className }),
4559
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("font-medium", trendConfig[trendDirection].className), children: trend.value }),
4560
+ trend.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: neutralTextClasses.soft, children: trend.label })
4561
+ ] }),
4562
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 border-t border-(--ui-border) pt-3", children: footer })
4563
+ ] });
4564
+ };
4565
+ var DescriptionList = ({ items, columns = 2, className }) => /* @__PURE__ */ jsxRuntime.jsx(
4566
+ "div",
4567
+ {
4568
+ className: tailwindMerge.twMerge(
4569
+ "grid gap-x-6 gap-y-4 rounded-(--ui-radius-lg) border border-(--ui-border) bg-white p-4",
4570
+ columns === 1 && "grid-cols-1",
4571
+ columns === 2 && "grid-cols-1 md:grid-cols-2",
4572
+ columns === 3 && "grid-cols-1 md:grid-cols-3",
4573
+ className
4574
+ ),
4575
+ children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
4576
+ "div",
4577
+ {
4578
+ className: tailwindMerge.twMerge(
4579
+ "min-w-0",
4580
+ item.span === 2 && columns > 1 && "md:col-span-2",
4581
+ item.span === 3 && columns > 2 && "md:col-span-3"
4582
+ ),
4583
+ children: [
4584
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: tailwindMerge.twMerge("text-xs font-medium uppercase tracking-[0.08em]", neutralTextClasses.soft), children: item.label }),
4585
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "mt-1 text-sm text-(--ui-text)", children: item.value })
4586
+ ]
4587
+ },
4588
+ index
4589
+ ))
4590
+ }
4591
+ );
4592
+ 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: [
4593
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("text-sm", neutralTextClasses.muted), children: label }),
4594
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-right text-sm text-(--ui-text)", children: value })
4595
+ ] });
4234
4596
  var Pretty = ({ data, className }) => /* @__PURE__ */ jsxRuntime.jsx(
4235
4597
  "pre",
4236
4598
  {
@@ -4241,6 +4603,10 @@ var Pretty = ({ data, className }) => /* @__PURE__ */ jsxRuntime.jsx(
4241
4603
  children: JSON.stringify(data, null, 2)
4242
4604
  }
4243
4605
  );
4606
+ 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: [
4607
+ /* @__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)) }),
4608
+ /* @__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)) })
4609
+ ] }) });
4244
4610
  var GAP2 = 10;
4245
4611
  var VIEWPORT_MARGIN2 = 8;
4246
4612
  function calcPosition3(trigger, tooltip, placement) {
@@ -4395,6 +4761,47 @@ var Tooltip = ({
4395
4761
  )
4396
4762
  ] });
4397
4763
  };
4764
+ var Stepper = ({ items, className }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex flex-wrap gap-4", className), children: items.map((item, index) => {
4765
+ const status = item.status ?? "upcoming";
4766
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-40 flex-1 items-start gap-3", children: [
4767
+ /* @__PURE__ */ jsxRuntime.jsx(
4768
+ "div",
4769
+ {
4770
+ className: tailwindMerge.twMerge(
4771
+ "mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full border text-xs font-semibold",
4772
+ status === "complete" && "border-(--ui-success) bg-(--ui-success) text-white",
4773
+ status === "current" && "border-(--ui-primary) bg-(--ui-primary) text-white",
4774
+ status === "upcoming" && "border-(--ui-border) bg-white text-(--ui-text-soft)"
4775
+ ),
4776
+ children: status === "complete" ? /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconCheck, { size: 14, strokeWidth: 2.5 }) : index + 1
4777
+ }
4778
+ ),
4779
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
4780
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("text-sm font-medium", status === "upcoming" ? neutralTextClasses.muted : "text-(--ui-text-strong)"), children: item.title }),
4781
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("mt-1 text-xs", neutralTextClasses.soft), children: item.description })
4782
+ ] })
4783
+ ] }, index);
4784
+ }) });
4785
+ var colorClass = {
4786
+ primary: "bg-(--ui-primary)",
4787
+ success: "bg-(--ui-success)",
4788
+ danger: "bg-(--ui-danger)",
4789
+ warning: "bg-(--ui-warning)",
4790
+ neutral: "bg-(--ui-border-strong)"
4791
+ };
4792
+ 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: [
4793
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col items-center", children: [
4794
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("mt-1 h-2.5 w-2.5 rounded-full", colorClass[item.color ?? "primary"]) }),
4795
+ index < items.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 h-full w-px bg-(--ui-border)" })
4796
+ ] }),
4797
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 pb-4", children: [
4798
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4799
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-(--ui-text-strong)", children: item.title }),
4800
+ item.time && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("text-xs", neutralTextClasses.soft), children: item.time })
4801
+ ] }),
4802
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("mt-1 text-sm", neutralTextClasses.muted), children: item.description })
4803
+ ] })
4804
+ ] }, index)) });
4398
4805
 
4399
4806
  // src/initUI.ts
4400
4807
  function initUI(config) {
@@ -4508,6 +4915,7 @@ function initUI(config) {
4508
4915
  r.style.setProperty("--ui-empty-compact-description", layout.empty.compactDescription);
4509
4916
  }
4510
4917
 
4918
+ exports.ActionBar = ActionBar;
4511
4919
  exports.ActiveTag = ActiveTag;
4512
4920
  exports.Alert = Alert;
4513
4921
  exports.Avatar = Avatar;
@@ -4515,14 +4923,19 @@ exports.Badge = Badge;
4515
4923
  exports.Button = Button;
4516
4924
  exports.CheckboxInput = CheckboxInput;
4517
4925
  exports.ColorInput = ColorInput;
4926
+ exports.ConfirmButton = ConfirmButton;
4518
4927
  exports.DateInput = DateInput;
4928
+ exports.DescriptionList = DescriptionList;
4519
4929
  exports.Drawer = Drawer;
4520
4930
  exports.DrawerContent = DrawerContent;
4521
4931
  exports.DrawerFooter = DrawerFooter;
4522
4932
  exports.DrawerTitle = DrawerTitle;
4523
4933
  exports.Dropdown = Dropdown;
4524
4934
  exports.Empty = Empty;
4935
+ exports.EmptyState = EmptyState;
4936
+ exports.EntityHeader = EntityHeader;
4525
4937
  exports.ErrorProvider = ErrorProvider;
4938
+ exports.Fieldset = Fieldset;
4526
4939
  exports.FilterCheckboxInput = FilterCheckboxInput;
4527
4940
  exports.FilterDateInput = FilterDateInput;
4528
4941
  exports.FilterDateRangePopover = FilterDateRangePopover;
@@ -4531,12 +4944,16 @@ exports.FilterSelectGroupPopover = FilterSelectGroupPopover;
4531
4944
  exports.FilterSelectInput = FilterSelectInput;
4532
4945
  exports.FilterTextInput = FilterTextInput;
4533
4946
  exports.FlagTag = FlagTag;
4947
+ exports.FormActions = FormActions;
4948
+ exports.FormSection = FormSection;
4534
4949
  exports.Grid = Grid;
4535
4950
  exports.GridFilters = GridFilters;
4536
4951
  exports.HtmlInput = HtmlInput;
4952
+ exports.InlineEdit = InlineEdit;
4537
4953
  exports.InputError = InputError;
4538
4954
  exports.InputField = InputField;
4539
4955
  exports.InputLabel = InputLabel;
4956
+ exports.KeyValue = KeyValue;
4540
4957
  exports.Modal = Modal;
4541
4958
  exports.ModalContent = ModalContent;
4542
4959
  exports.ModalFooter = ModalFooter;
@@ -4544,19 +4961,29 @@ exports.ModalTitle = ModalTitle;
4544
4961
  exports.MultiSelectInput = MultiSelectInput;
4545
4962
  exports.NotificationProvider = NotificationProvider;
4546
4963
  exports.NumberInput = NumberInput;
4964
+ exports.PageHeader = PageHeader;
4547
4965
  exports.Panel = Panel;
4548
4966
  exports.Popconfirm = Popconfirm;
4549
4967
  exports.Pretty = Pretty;
4968
+ exports.RadioGroup = RadioGroup;
4969
+ exports.SearchInput = SearchInput;
4970
+ exports.SectionHeader = SectionHeader;
4550
4971
  exports.SelectInput = SelectInput;
4551
4972
  exports.ServerError = ServerError;
4552
4973
  exports.Skeleton = Skeleton;
4974
+ exports.SkeletonTable = SkeletonTable;
4553
4975
  exports.SortDirection = SortDirection;
4554
4976
  exports.Spinner = Spinner;
4977
+ exports.StatCard = StatCard;
4978
+ exports.Stepper = Stepper;
4555
4979
  exports.SwitchInput = SwitchInput;
4556
4980
  exports.Table = Table;
4557
4981
  exports.Tabs = Tabs;
4558
4982
  exports.Tag = Tag;
4559
4983
  exports.TextInput = TextInput;
4984
+ exports.Textarea = Textarea;
4985
+ exports.Timeline = Timeline;
4986
+ exports.Toolbar = Toolbar;
4560
4987
  exports.Tooltip = Tooltip;
4561
4988
  exports.UploadInput = UploadInput;
4562
4989
  exports.UploadProvider = UploadProvider;