@orianatech/pire 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -45,12 +45,17 @@ __export(src_exports, {
45
45
  DateRangePicker: () => DateRangePicker,
46
46
  DescriptionList: () => DescriptionList,
47
47
  Dialog: () => Dialog,
48
+ DialogActions: () => DialogActions,
49
+ DialogBody: () => DialogBody,
50
+ DialogDescription: () => DialogDescription,
51
+ DialogTitle: () => DialogTitle,
48
52
  DialogTrigger: () => import_react_aria_components34.DialogTrigger,
49
53
  DonutChart: () => DonutChart,
50
54
  EmptyState: () => EmptyState,
51
55
  FileDropZone: () => FileDropZone,
52
56
  FileUpload: () => FileUpload,
53
57
  FilterBar: () => FilterBar,
58
+ Focusable: () => import_react_aria_components35.Focusable,
54
59
  FooterBar: () => FooterBar,
55
60
  FormField: () => FormField,
56
61
  Heading: () => Heading,
@@ -92,6 +97,7 @@ __export(src_exports, {
92
97
  SidePanel: () => SidePanel,
93
98
  Skeleton: () => Skeleton,
94
99
  SkeletonTableRow: () => SkeletonTableRow,
100
+ SplitPane: () => SplitPane,
95
101
  Strong: () => Strong,
96
102
  SubmenuTrigger: () => import_react_aria_components34.SubmenuTrigger,
97
103
  Switch: () => Switch,
@@ -524,15 +530,17 @@ var Button = React.forwardRef(function Button2({ children, variant = "secondary"
524
530
  });
525
531
 
526
532
  // src/components/core/IconButton.tsx
527
- var React2 = __toESM(require("react"), 1);
533
+ var React3 = __toESM(require("react"), 1);
528
534
  var import_react_aria_components3 = require("react-aria-components");
529
535
 
530
536
  // src/components/feedback/Tooltip.tsx
537
+ var React2 = __toESM(require("react"), 1);
531
538
  var import_react_aria_components2 = require("react-aria-components");
532
539
  var import_jsx_runtime3 = require("react/jsx-runtime");
533
540
  function Tooltip({ label, placement = "top", delay = 500, children }) {
541
+ const target = React2.isValidElement(children) ? React2.cloneElement(children, { className: cx(children.props.className, "pire-tooltip-target") }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "pire-tooltip-target", children });
534
542
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_aria_components2.TooltipTrigger, { delay, closeDelay: 0, children: [
535
- children,
543
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_aria_components2.Focusable, { children: target }),
536
544
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_aria_components2.Tooltip, { className: "pire-tooltip", placement, offset: 6, children: [
537
545
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_aria_components2.OverlayArrow, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", {}) }),
538
546
  label
@@ -542,7 +550,7 @@ function Tooltip({ label, placement = "top", delay = 500, children }) {
542
550
 
543
551
  // src/components/core/IconButton.tsx
544
552
  var import_jsx_runtime4 = require("react/jsx-runtime");
545
- var IconButton = React2.forwardRef(function IconButton2({
553
+ var IconButton = React3.forwardRef(function IconButton2({
546
554
  icon,
547
555
  label,
548
556
  size = "md",
@@ -630,11 +638,11 @@ function Card({ title, subtitle, icon, actions, footer, interactive, children, c
630
638
  }
631
639
 
632
640
  // src/components/core/Avatar.tsx
633
- var React3 = __toESM(require("react"), 1);
641
+ var React4 = __toESM(require("react"), 1);
634
642
  var import_jsx_runtime8 = require("react/jsx-runtime");
635
643
  var initials = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
636
644
  function Avatar({ name, size = "md", src, className, ...rest }) {
637
- const [failed, setFailed] = React3.useState(false);
645
+ const [failed, setFailed] = React4.useState(false);
638
646
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: cx("pire-avatar", className), "data-size": size, role: "img", "aria-label": name, ...rest, children: src && !failed ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
639
647
  "img",
640
648
  {
@@ -647,7 +655,7 @@ function Avatar({ name, size = "md", src, className, ...rest }) {
647
655
  }
648
656
 
649
657
  // src/components/core/SegmentedControl.tsx
650
- var React4 = __toESM(require("react"), 1);
658
+ var React5 = __toESM(require("react"), 1);
651
659
  var import_react_aria_components5 = require("react-aria-components");
652
660
  var import_jsx_runtime9 = require("react/jsx-runtime");
653
661
  function SegmentedControl({
@@ -661,7 +669,7 @@ function SegmentedControl({
661
669
  style,
662
670
  ...rest
663
671
  }) {
664
- const selected = React4.useMemo(() => new Set(value ? [value] : defaultValue ? [defaultValue] : []), [value, defaultValue]);
672
+ const selected = React5.useMemo(() => new Set(value ? [value] : defaultValue ? [defaultValue] : []), [value, defaultValue]);
665
673
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
666
674
  import_react_aria_components5.ToggleButtonGroup,
667
675
  {
@@ -823,11 +831,11 @@ function FormField({ label, htmlFor, isRequired, hint, error, layout = "stacked"
823
831
  }
824
832
 
825
833
  // src/components/forms/Input.tsx
826
- var React6 = __toESM(require("react"), 1);
834
+ var React7 = __toESM(require("react"), 1);
827
835
  var import_react_aria_components9 = require("react-aria-components");
828
836
 
829
837
  // src/i18n/PireIntlProvider.tsx
830
- var React5 = __toESM(require("react"), 1);
838
+ var React6 = __toESM(require("react"), 1);
831
839
 
832
840
  // src/i18n/messages.ts
833
841
  var enMessages = {
@@ -837,6 +845,7 @@ var enMessages = {
837
845
  dataTableSelectAll: "Select all rows",
838
846
  dataTableSelectRow: "Select row",
839
847
  dataTableLoading: "Loading records",
848
+ dataTableSummaryRow: "Summary",
840
849
  dialogClose: "Close",
841
850
  sidePanelClose: "Close panel",
842
851
  inlineMessageDismiss: "Dismiss message",
@@ -868,6 +877,9 @@ var enMessages = {
868
877
  paginationNext: "Next page",
869
878
  paginationRowsPerPage: "Rows per page",
870
879
  sideNavLabel: "Main navigation",
880
+ splitPaneList: "List",
881
+ splitPaneDetail: "Detail",
882
+ splitPaneBack: "Back to list",
871
883
  fileUploadChoose: "Choose files",
872
884
  fileUploadRemoveNamed: "Remove {name}",
873
885
  fileUploadUploading: "Uploading",
@@ -892,6 +904,7 @@ var esMessages = {
892
904
  dataTableSelectAll: "Seleccionar todas las filas",
893
905
  dataTableSelectRow: "Seleccionar fila",
894
906
  dataTableLoading: "Cargando registros",
907
+ dataTableSummaryRow: "Resumen",
895
908
  dialogClose: "Cerrar",
896
909
  sidePanelClose: "Cerrar panel",
897
910
  inlineMessageDismiss: "Descartar mensaje",
@@ -923,6 +936,9 @@ var esMessages = {
923
936
  paginationNext: "P\xE1gina siguiente",
924
937
  paginationRowsPerPage: "Filas por p\xE1gina",
925
938
  sideNavLabel: "Navegaci\xF3n principal",
939
+ splitPaneList: "Lista",
940
+ splitPaneDetail: "Detalle",
941
+ splitPaneBack: "Volver a la lista",
926
942
  fileUploadChoose: "Elegir archivos",
927
943
  fileUploadRemoveNamed: "Quitar {name}",
928
944
  fileUploadUploading: "Subiendo",
@@ -943,19 +959,19 @@ var esMessages = {
943
959
 
944
960
  // src/i18n/PireIntlProvider.tsx
945
961
  var import_jsx_runtime16 = require("react/jsx-runtime");
946
- var MessagesContext = React5.createContext(enMessages);
962
+ var MessagesContext = React6.createContext(enMessages);
947
963
  function PireIntlProvider({ messages, children }) {
948
- const value = React5.useMemo(
964
+ const value = React6.useMemo(
949
965
  () => messages ? { ...enMessages, ...messages } : enMessages,
950
966
  [messages]
951
967
  );
952
968
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MessagesContext.Provider, { value, children });
953
969
  }
954
970
  function usePireMessages() {
955
- return React5.useContext(MessagesContext);
971
+ return React6.useContext(MessagesContext);
956
972
  }
957
973
  function useMessage(key, override) {
958
- const messages = React5.useContext(MessagesContext);
974
+ const messages = React6.useContext(MessagesContext);
959
975
  return override ?? messages[key];
960
976
  }
961
977
 
@@ -980,7 +996,7 @@ function Input({
980
996
  }) {
981
997
  const msg = usePireMessages();
982
998
  const isControlled = rest.value !== void 0;
983
- const [ownValue, setOwnValue] = React6.useState(rest.defaultValue ?? "");
999
+ const [ownValue, setOwnValue] = React7.useState(rest.defaultValue ?? "");
984
1000
  const currentValue = isControlled ? rest.value : ownValue;
985
1001
  const handleChange = (next) => {
986
1002
  setOwnValue(next);
@@ -1027,10 +1043,10 @@ function Input({
1027
1043
  }
1028
1044
 
1029
1045
  // src/components/forms/TextArea.tsx
1030
- var React7 = __toESM(require("react"), 1);
1046
+ var React8 = __toESM(require("react"), 1);
1031
1047
  var import_react_aria_components10 = require("react-aria-components");
1032
1048
  var import_jsx_runtime18 = require("react/jsx-runtime");
1033
- var useIsomorphicLayoutEffect = typeof document === "undefined" ? React7.useEffect : React7.useLayoutEffect;
1049
+ var useIsomorphicLayoutEffect = typeof document === "undefined" ? React8.useEffect : React8.useLayoutEffect;
1034
1050
  function TextArea({
1035
1051
  label,
1036
1052
  description,
@@ -1046,13 +1062,13 @@ function TextArea({
1046
1062
  onChange,
1047
1063
  ...rest
1048
1064
  }) {
1049
- const innerRef = React7.useRef(null);
1050
- const ref = React7.useCallback((node) => {
1065
+ const innerRef = React8.useRef(null);
1066
+ const ref = React8.useCallback((node) => {
1051
1067
  innerRef.current = node;
1052
1068
  if (typeof textAreaRef === "function") textAreaRef(node);
1053
1069
  else if (textAreaRef) textAreaRef.current = node;
1054
1070
  }, [textAreaRef]);
1055
- const grow = React7.useCallback(() => {
1071
+ const grow = React8.useCallback(() => {
1056
1072
  const el = innerRef.current;
1057
1073
  if (!el || !autoGrow) return;
1058
1074
  const styles = getComputedStyle(el);
@@ -1312,7 +1328,7 @@ function ComboBox({
1312
1328
  }
1313
1329
 
1314
1330
  // src/components/forms/MultiComboBox.tsx
1315
- var React8 = __toESM(require("react"), 1);
1331
+ var React9 = __toESM(require("react"), 1);
1316
1332
  var import_react_aria_components16 = require("react-aria-components");
1317
1333
  var import_jsx_runtime24 = require("react/jsx-runtime");
1318
1334
  var norm3 = (o) => typeof o === "string" ? { value: o, label: o } : o;
@@ -1338,15 +1354,15 @@ function MultiComboBox({
1338
1354
  ...rest
1339
1355
  }) {
1340
1356
  const msg = usePireMessages();
1341
- const items = React8.useMemo(() => options.map(norm3), [options]);
1357
+ const items = React9.useMemo(() => options.map(norm3), [options]);
1342
1358
  const collection = isFilteredExternally ? { items } : { defaultItems: items };
1343
1359
  const showsStatus = isLoading || isFilteredExternally && items.length === 0 && emptyLabel != null;
1344
- const [uncontrolled, setUncontrolled] = React8.useState(defaultValue ?? []);
1345
- const [announcement, setAnnouncement] = React8.useState("");
1346
- const inputRef = React8.useRef(null);
1360
+ const [uncontrolled, setUncontrolled] = React9.useState(defaultValue ?? []);
1361
+ const [announcement, setAnnouncement] = React9.useState("");
1362
+ const inputRef = React9.useRef(null);
1347
1363
  const raw = value ?? uncontrolled;
1348
1364
  const contentKey = raw.join("\0");
1349
- const values = React8.useMemo(() => raw, [contentKey]);
1365
+ const values = React9.useMemo(() => raw, [contentKey]);
1350
1366
  const labelOf = (v) => items.find((o) => o.value === v)?.label ?? v;
1351
1367
  const isEditable = !rest.isDisabled && !rest.isReadOnly;
1352
1368
  const commit = (next) => {
@@ -1662,14 +1678,27 @@ function DateRangePicker({
1662
1678
  }
1663
1679
 
1664
1680
  // src/components/forms/ValueHelpField.tsx
1665
- var React10 = __toESM(require("react"), 1);
1681
+ var React12 = __toESM(require("react"), 1);
1666
1682
 
1667
1683
  // src/components/patterns/ValueHelpDialog.tsx
1668
- var React9 = __toESM(require("react"), 1);
1684
+ var React11 = __toESM(require("react"), 1);
1669
1685
 
1670
1686
  // src/components/feedback/Dialog.tsx
1687
+ var React10 = __toESM(require("react"), 1);
1671
1688
  var import_react_aria_components20 = require("react-aria-components");
1672
1689
  var import_jsx_runtime28 = require("react/jsx-runtime");
1690
+ function DialogTitle({ children, className }) {
1691
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_aria_components20.Heading, { slot: "title", className: cx("pire-dialog-title", className), children });
1692
+ }
1693
+ function DialogDescription({ children, className }) {
1694
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: cx("pire-dialog-sub", className), style: { margin: 0 }, children });
1695
+ }
1696
+ function DialogBody({ children, className }) {
1697
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: cx("pire-dialog-body", className), children });
1698
+ }
1699
+ function DialogActions({ children, className }) {
1700
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("footer", { className: cx("pire-dialog-foot", className), children });
1701
+ }
1673
1702
  function Dialog({
1674
1703
  isOpen,
1675
1704
  onOpenChange,
@@ -1689,6 +1718,18 @@ function Dialog({
1689
1718
  onClose?.();
1690
1719
  onOpenChange?.(false);
1691
1720
  };
1721
+ const parts = React10.Children.toArray(children);
1722
+ const slotOf = (type) => parts.find((node) => React10.isValidElement(node) && node.type === type);
1723
+ const titleSlot = slotOf(DialogTitle);
1724
+ const descriptionSlot = slotOf(DialogDescription);
1725
+ const bodySlot = slotOf(DialogBody);
1726
+ const actionsSlot = slotOf(DialogActions);
1727
+ const slots = [titleSlot, descriptionSlot, bodySlot, actionsSlot];
1728
+ const loose = parts.filter((node) => !slots.includes(node));
1729
+ const heading = titleSlot ?? (title ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_aria_components20.Heading, { slot: "title", className: "pire-dialog-title", children: title }) : null);
1730
+ const description = descriptionSlot ?? (subtitle ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null);
1731
+ const actions = actionsSlot ?? (footer ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("footer", { className: "pire-dialog-foot", children: footer }) : null);
1732
+ const body = bodySlot ?? (loose.length ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "pire-dialog-body", children: loose }) : null);
1692
1733
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1693
1734
  import_react_aria_components20.ModalOverlay,
1694
1735
  {
@@ -1699,15 +1740,15 @@ function Dialog({
1699
1740
  if (!o) close();
1700
1741
  },
1701
1742
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_aria_components20.Modal, { className: cx("pire-modal", className), "data-size": size, style, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_react_aria_components20.Dialog, { className: "pire-dialog", children: [
1702
- title ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("header", { className: "pire-dialog-head", children: [
1743
+ heading || description ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("header", { className: "pire-dialog-head", children: [
1703
1744
  /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
1704
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react_aria_components20.Heading, { slot: "title", className: "pire-dialog-title", children: title }),
1705
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
1745
+ heading,
1746
+ description
1706
1747
  ] }),
1707
1748
  showClose ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(IconButton, { icon: "x", label: msg.dialogClose, size: "sm", onPress: close }) : null
1708
1749
  ] }) : null,
1709
- children ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "pire-dialog-body", children }) : null,
1710
- footer ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("footer", { className: "pire-dialog-foot", children: footer }) : null
1750
+ body,
1751
+ actions
1711
1752
  ] }) })
1712
1753
  }
1713
1754
  );
@@ -1778,6 +1819,10 @@ function DataTable({
1778
1819
  isLoading,
1779
1820
  loadingRowCount,
1780
1821
  loadingLabel,
1822
+ footer,
1823
+ rowProps,
1824
+ renderExpanded,
1825
+ expandedIds,
1781
1826
  className,
1782
1827
  style,
1783
1828
  ...rest
@@ -1794,6 +1839,11 @@ function DataTable({
1794
1839
  ...columns.map((c) => ({ width: c.width, align: c.align, numeric: c.numeric }))
1795
1840
  ];
1796
1841
  const body = isLoading ? [] : rows;
1842
+ const presentation = new Map(rows.map((row) => [row.id, rowProps?.(row) ?? {}]));
1843
+ const disabledKeys = rows.filter((row) => presentation.get(row.id)?.isDisabled).map((row) => row.id);
1844
+ const expanded = new Set((expandedIds ?? []).map(String));
1845
+ const spanAll = columns.length + (selectable ? 1 : 0);
1846
+ const expandedKey = (id) => `${id}::__pire_expanded__`;
1797
1847
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1798
1848
  "div",
1799
1849
  {
@@ -1808,6 +1858,7 @@ function DataTable({
1808
1858
  "data-density": density,
1809
1859
  "data-sticky": String(stickyHeader),
1810
1860
  "aria-label": rest["aria-label"],
1861
+ disabledKeys: disabledKeys.length ? new Set(disabledKeys) : void 0,
1811
1862
  selectionMode: selectable ? "multiple" : "none",
1812
1863
  selectedKeys: selected ? new Set(selected) : void 0,
1813
1864
  onSelectionChange: handleSelection,
@@ -1830,7 +1881,7 @@ function DataTable({
1830
1881
  width: c.width,
1831
1882
  "data-align": c.numeric || c.align === "right" ? "right" : c.align,
1832
1883
  "data-allows-sorting": c.sortable ? "true" : void 0,
1833
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "pire-th-inner", children: [
1884
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: cx("pire-th-inner", c.hideLabel && "pire-sr-only"), children: [
1834
1885
  c.label,
1835
1886
  c.sortable ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1836
1887
  Icon,
@@ -1851,19 +1902,46 @@ function DataTable({
1851
1902
  // biome-ignore lint/suspicious/noArrayIndexKey: placeholder rows are positional.
1852
1903
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SkeletonTableRow, { columns: skeletonColumns, density }, i)
1853
1904
  ))
1854
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "pire-table-empty", children: emptyLabel }), children: body.map((row) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_react_aria_components21.Row, { id: row.id, className: "pire-tr", "data-pressable": onRowAction ? "true" : void 0, children: [
1855
- selectable ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react_aria_components21.Cell, { className: "pire-td", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectRow }) }) : null,
1856
- columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1905
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "pire-table-empty", children: emptyLabel }), children: body.flatMap((row) => {
1906
+ const rowIsDisabled = presentation.get(row.id)?.isDisabled;
1907
+ const record = /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
1908
+ import_react_aria_components21.Row,
1909
+ {
1910
+ id: row.id,
1911
+ className: cx("pire-tr", presentation.get(row.id)?.className),
1912
+ "data-pressable": onRowAction && !rowIsDisabled ? "true" : void 0,
1913
+ children: [
1914
+ selectable ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react_aria_components21.Cell, { className: "pire-td", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectRow }) }) : null,
1915
+ columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1916
+ import_react_aria_components21.Cell,
1917
+ {
1918
+ className: "pire-td",
1919
+ "data-numeric": c.numeric ? "true" : void 0,
1920
+ style: { textAlign: c.align && !c.numeric ? c.align : void 0 },
1921
+ children: c.render ? c.render(row) : row[c.key]
1922
+ },
1923
+ c.key
1924
+ ))
1925
+ ]
1926
+ },
1927
+ row.id
1928
+ );
1929
+ if (!renderExpanded || !expanded.has(String(row.id))) return [record];
1930
+ return [record, /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react_aria_components21.Row, { id: expandedKey(row.id), className: "pire-tr-expanded", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react_aria_components21.Cell, { className: "pire-td-expanded", colSpan: spanAll, children: renderExpanded(row) }) }, expandedKey(row.id))];
1931
+ }) }),
1932
+ footer && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react_aria_components21.TableFooter, { className: "pire-tfoot", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_react_aria_components21.Row, { id: "__pire_footer__", className: "pire-tr-footer", children: [
1933
+ selectable ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react_aria_components21.Cell, { className: "pire-tf" }) : null,
1934
+ columns.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1857
1935
  import_react_aria_components21.Cell,
1858
1936
  {
1859
- className: "pire-td",
1937
+ className: "pire-tf",
1860
1938
  "data-numeric": c.numeric ? "true" : void 0,
1861
1939
  style: { textAlign: c.align && !c.numeric ? c.align : void 0 },
1862
- children: c.render ? c.render(row) : row[c.key]
1940
+ children: footer[c.key] ?? (i === 0 && !selectable ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "pire-sr-only", children: msg.dataTableSummaryRow }) : null)
1863
1941
  },
1864
1942
  c.key
1865
1943
  ))
1866
- ] }, row.id)) })
1944
+ ] }) }) : null
1867
1945
  ]
1868
1946
  }
1869
1947
  )
@@ -1888,11 +1966,11 @@ function ValueHelpDialog({
1888
1966
  onClose
1889
1967
  }) {
1890
1968
  const msg = usePireMessages();
1891
- const [query, setQuery] = React9.useState("");
1892
- React9.useEffect(() => {
1969
+ const [query, setQuery] = React11.useState("");
1970
+ React11.useEffect(() => {
1893
1971
  if (isOpen) setQuery("");
1894
1972
  }, [isOpen]);
1895
- const filtered = React9.useMemo(() => {
1973
+ const filtered = React11.useMemo(() => {
1896
1974
  if (isFilteredExternally) return rows;
1897
1975
  const q = query.trim().toLowerCase();
1898
1976
  if (!q) return rows;
@@ -1974,7 +2052,7 @@ function ValueHelpField({
1974
2052
  style
1975
2053
  }) {
1976
2054
  const msg = usePireMessages();
1977
- const [open, setOpen] = React10.useState(false);
2055
+ const [open, setOpen] = React12.useState(false);
1978
2056
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: cx(className), style, children: [
1979
2057
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1980
2058
  Input,
@@ -2030,7 +2108,7 @@ function ValueHelpField({
2030
2108
  }
2031
2109
 
2032
2110
  // src/components/forms/FileUpload.tsx
2033
- var React11 = __toESM(require("react"), 1);
2111
+ var React13 = __toESM(require("react"), 1);
2034
2112
  var import_react_aria_components23 = require("react-aria-components");
2035
2113
 
2036
2114
  // src/components/feedback/ProgressBar.tsx
@@ -2120,10 +2198,10 @@ function FileUpload({
2120
2198
  style
2121
2199
  }) {
2122
2200
  const msg = usePireMessages();
2123
- const [uncontrolled, setUncontrolled] = React11.useState(defaultValue ?? []);
2201
+ const [uncontrolled, setUncontrolled] = React13.useState(defaultValue ?? []);
2124
2202
  const files = value ?? uncontrolled;
2125
- const created = React11.useRef([]);
2126
- React11.useEffect(() => () => {
2203
+ const created = React13.useRef([]);
2204
+ React13.useEffect(() => () => {
2127
2205
  for (const url of created.current) URL.revokeObjectURL(url);
2128
2206
  }, []);
2129
2207
  const commit = (next) => {
@@ -2234,7 +2312,7 @@ function ShellBar({
2234
2312
  }
2235
2313
 
2236
2314
  // src/components/navigation/SideNav.tsx
2237
- var React12 = __toESM(require("react"), 1);
2315
+ var React14 = __toESM(require("react"), 1);
2238
2316
  var import_react_aria_components26 = require("react-aria-components");
2239
2317
 
2240
2318
  // src/components/navigation/Menu.tsx
@@ -2321,10 +2399,10 @@ function SideNav({
2321
2399
  const msg = usePireMessages();
2322
2400
  const activeParent = findActiveParent(groups, value);
2323
2401
  const isControlled = expandedIds != null;
2324
- const [ownExpanded, setOwnExpanded] = React12.useState(
2402
+ const [ownExpanded, setOwnExpanded] = React14.useState(
2325
2403
  () => new Set(defaultExpandedIds ?? (activeParent ? [activeParent] : []))
2326
2404
  );
2327
- const [lastValue, setLastValue] = React12.useState(value);
2405
+ const [lastValue, setLastValue] = React14.useState(value);
2328
2406
  if (value !== lastValue) {
2329
2407
  setLastValue(value);
2330
2408
  if (!isControlled && activeParent && !ownExpanded.has(activeParent)) {
@@ -2588,7 +2666,7 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
2588
2666
  }
2589
2667
 
2590
2668
  // src/components/feedback/Toast.tsx
2591
- var React13 = __toESM(require("react"), 1);
2669
+ var React15 = __toESM(require("react"), 1);
2592
2670
  var import_jsx_runtime42 = require("react/jsx-runtime");
2593
2671
  var KIND_ICON2 = {
2594
2672
  info: "info",
@@ -2614,26 +2692,26 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
2614
2692
  }
2615
2693
  );
2616
2694
  }
2617
- var ToastContext = React13.createContext(null);
2695
+ var ToastContext = React15.createContext(null);
2618
2696
  function ToastProvider({ children, timeout = 6e3 }) {
2619
2697
  const msg = usePireMessages();
2620
- const [toasts, setToasts] = React13.useState([]);
2621
- const close = React13.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2622
- const add = React13.useCallback((toast) => {
2698
+ const [toasts, setToasts] = React15.useState([]);
2699
+ const close = React15.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2700
+ const add = React15.useCallback((toast) => {
2623
2701
  const id = Math.random().toString(36).slice(2);
2624
2702
  setToasts((t) => [...t, { ...toast, id }]);
2625
2703
  const ms = toast.timeout ?? timeout;
2626
2704
  if (ms > 0) setTimeout(() => close(id), ms);
2627
2705
  return id;
2628
2706
  }, [close, timeout]);
2629
- const value = React13.useMemo(() => ({ add, close }), [add, close]);
2707
+ const value = React15.useMemo(() => ({ add, close }), [add, close]);
2630
2708
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(ToastContext.Provider, { value, children: [
2631
2709
  children,
2632
2710
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
2633
2711
  ] });
2634
2712
  }
2635
2713
  function useToast() {
2636
- const ctx = React13.useContext(ToastContext);
2714
+ const ctx = React15.useContext(ToastContext);
2637
2715
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
2638
2716
  return ctx;
2639
2717
  }
@@ -2983,14 +3061,14 @@ function BarChart({
2983
3061
  }
2984
3062
 
2985
3063
  // src/components/data/LineChart.tsx
2986
- var React14 = __toESM(require("react"), 1);
3064
+ var React16 = __toESM(require("react"), 1);
2987
3065
  var import_jsx_runtime50 = require("react/jsx-runtime");
2988
3066
  var PLOT_INSET = { top: 10, right: 14, bottom: 24, left: 58 };
2989
3067
  var MARKER_LIMIT = 20;
2990
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React14.useEffect : React14.useLayoutEffect;
3068
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React16.useEffect : React16.useLayoutEffect;
2991
3069
  function useMeasuredWidth() {
2992
- const ref = React14.useRef(null);
2993
- const [width, setWidth] = React14.useState(0);
3070
+ const ref = React16.useRef(null);
3071
+ const [width, setWidth] = React16.useState(0);
2994
3072
  useIsomorphicLayoutEffect2(() => {
2995
3073
  const element = ref.current;
2996
3074
  if (!element) return;
@@ -3153,7 +3231,7 @@ function LineChart({
3153
3231
  }
3154
3232
 
3155
3233
  // src/components/data/DonutChart.tsx
3156
- var React15 = __toESM(require("react"), 1);
3234
+ var React17 = __toESM(require("react"), 1);
3157
3235
  var import_jsx_runtime51 = require("react/jsx-runtime");
3158
3236
  var SEGMENT_GAP_DEGREES = 1.5;
3159
3237
  function DonutChart({
@@ -3174,7 +3252,7 @@ function DonutChart({
3174
3252
  }) {
3175
3253
  const label = rest["aria-label"];
3176
3254
  const msg = usePireMessages();
3177
- const [hoveredIndex, setHoveredIndex] = React15.useState(null);
3255
+ const [hoveredIndex, setHoveredIndex] = React17.useState(null);
3178
3256
  warnOnDonutShape(series, categories.length, label);
3179
3257
  const values = (series[0]?.values ?? []).slice(0, categories.length);
3180
3258
  const segments = categories.map((category, index) => ({ category, index, value: values[index] ?? 0 })).filter((segment) => segment.value > 0);
@@ -3338,8 +3416,43 @@ function FooterBar({ note, actions, children, className, ...rest }) {
3338
3416
  ] });
3339
3417
  }
3340
3418
 
3341
- // src/components/patterns/ConfirmDialog.tsx
3419
+ // src/components/layout/SplitPane.tsx
3342
3420
  var import_jsx_runtime58 = require("react/jsx-runtime");
3421
+ function SplitPane({
3422
+ list,
3423
+ detail,
3424
+ listWidth = "24rem",
3425
+ listLabel,
3426
+ detailLabel,
3427
+ emptyDetail,
3428
+ onBack,
3429
+ backLabel,
3430
+ className,
3431
+ style,
3432
+ ...rest
3433
+ }) {
3434
+ const msg = usePireMessages();
3435
+ const width = typeof listWidth === "number" ? `${listWidth}px` : listWidth;
3436
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
3437
+ "div",
3438
+ {
3439
+ className: cx("pire-split", className),
3440
+ "data-has-detail": detail != null ? "true" : void 0,
3441
+ style: { ["--pire-split-list-w"]: width, ...style },
3442
+ ...rest,
3443
+ children: [
3444
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("section", { className: "pire-split-list", "aria-label": listLabel ?? msg.splitPaneList, children: list }),
3445
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("section", { className: "pire-split-detail", "aria-label": detailLabel ?? msg.splitPaneDetail, children: [
3446
+ onBack ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pire-split-back", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: "tertiary", size: "sm", icon: "arrow-left", onPress: onBack, children: backLabel ?? msg.splitPaneBack }) }) : null,
3447
+ detail ?? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pire-split-empty", children: emptyDetail })
3448
+ ] })
3449
+ ]
3450
+ }
3451
+ );
3452
+ }
3453
+
3454
+ // src/components/patterns/ConfirmDialog.tsx
3455
+ var import_jsx_runtime59 = require("react/jsx-runtime");
3343
3456
  function ConfirmDialog({
3344
3457
  isOpen,
3345
3458
  title,
@@ -3353,7 +3466,7 @@ function ConfirmDialog({
3353
3466
  onConfirm,
3354
3467
  onCancel
3355
3468
  }) {
3356
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
3469
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
3357
3470
  Dialog,
3358
3471
  {
3359
3472
  isOpen,
@@ -3363,12 +3476,12 @@ function ConfirmDialog({
3363
3476
  onClose: onCancel,
3364
3477
  isDismissable: !isBusy,
3365
3478
  showClose: false,
3366
- footer: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
3367
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3368
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3479
+ footer: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
3480
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3481
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3369
3482
  ] }),
3370
3483
  children: [
3371
- consequence ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3484
+ consequence ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3372
3485
  children
3373
3486
  ]
3374
3487
  }
@@ -3376,9 +3489,9 @@ function ConfirmDialog({
3376
3489
  }
3377
3490
 
3378
3491
  // src/components/patterns/CommandPalette.tsx
3379
- var React16 = __toESM(require("react"), 1);
3492
+ var React18 = __toESM(require("react"), 1);
3380
3493
  var import_react_aria_components31 = require("react-aria-components");
3381
- var import_jsx_runtime59 = require("react/jsx-runtime");
3494
+ var import_jsx_runtime60 = require("react/jsx-runtime");
3382
3495
  var RESULTS_SECTION_KEY = "__pire_results__";
3383
3496
  var searchableText = (item) => [item.label, item.description, item.keywords].filter(Boolean).join(" ");
3384
3497
  function CommandPalette({
@@ -3399,17 +3512,17 @@ function CommandPalette({
3399
3512
  style
3400
3513
  }) {
3401
3514
  const msg = usePireMessages();
3402
- const [query, setQuery] = React16.useState("");
3515
+ const [query, setQuery] = React18.useState("");
3403
3516
  const { contains } = (0, import_react_aria_components31.useFilter)({ sensitivity: "base" });
3404
- React16.useEffect(() => {
3517
+ React18.useEffect(() => {
3405
3518
  if (isOpen) setQuery("");
3406
3519
  }, [isOpen]);
3407
- const searchableById = React16.useMemo(() => {
3520
+ const searchableById = React18.useMemo(() => {
3408
3521
  const byId = /* @__PURE__ */ new Map();
3409
3522
  for (const group of groups) for (const item of group.items) byId.set(item.id, searchableText(item));
3410
3523
  return byId;
3411
3524
  }, [groups]);
3412
- const filter = React16.useCallback((textValue, inputValue, node) => {
3525
+ const filter = React18.useCallback((textValue, inputValue, node) => {
3413
3526
  if (node.parentKey === RESULTS_SECTION_KEY) return true;
3414
3527
  return contains(searchableById.get(String(node.key)) ?? textValue, inputValue);
3415
3528
  }, [contains, searchableById]);
@@ -3419,7 +3532,7 @@ function CommandPalette({
3419
3532
  };
3420
3533
  const sections = [...groups, ...resultsGroup ? [{ ...resultsGroup, id: RESULTS_SECTION_KEY }] : []];
3421
3534
  const status = isLoading ? loadingLabel ?? msg.commandPaletteLoading : emptyLabel ?? msg.commandPaletteEmpty;
3422
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
3535
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3423
3536
  import_react_aria_components31.ModalOverlay,
3424
3537
  {
3425
3538
  className: "pire-cp-overlay",
@@ -3428,11 +3541,11 @@ function CommandPalette({
3428
3541
  onOpenChange: (open) => {
3429
3542
  if (!open) onOpenChange?.(false);
3430
3543
  },
3431
- children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_aria_components31.Modal, { className: cx("pire-cp-modal", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_react_aria_components31.Dialog, { className: "pire-cp-dialog", "aria-label": ariaLabel ?? msg.commandPaletteLabel, children: [
3432
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_react_aria_components31.Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3433
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_react_aria_components31.SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3434
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3435
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
3544
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_aria_components31.Modal, { className: cx("pire-cp-modal", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components31.Dialog, { className: "pire-cp-dialog", "aria-label": ariaLabel ?? msg.commandPaletteLabel, children: [
3545
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components31.Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3546
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components31.SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3547
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3548
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3436
3549
  import_react_aria_components31.Input,
3437
3550
  {
3438
3551
  className: "pire-cp-input",
@@ -3441,16 +3554,16 @@ function CommandPalette({
3441
3554
  }
3442
3555
  )
3443
3556
  ] }),
3444
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3445
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
3557
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3558
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3446
3559
  import_react_aria_components31.Menu,
3447
3560
  {
3448
3561
  className: "pire-cp-list",
3449
3562
  onAction: (key) => onAction?.(String(key)),
3450
- renderEmptyState: () => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "pire-cp-status", children: status }),
3451
- children: sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_react_aria_components31.MenuSection, { id: section.id, className: "pire-cp-section", children: [
3452
- section.label ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_react_aria_components31.Header, { className: "pire-cp-section-title", children: section.label }) : null,
3453
- section.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
3563
+ renderEmptyState: () => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "pire-cp-status", children: status }),
3564
+ children: sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components31.MenuSection, { id: section.id, className: "pire-cp-section", children: [
3565
+ section.label ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_aria_components31.Header, { className: "pire-cp-section-title", children: section.label }) : null,
3566
+ section.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3454
3567
  MenuItem,
3455
3568
  {
3456
3569
  id: item.id,
@@ -3471,18 +3584,18 @@ function CommandPalette({
3471
3584
  // aria-hidden: the glyphs are a sighted affordance for discovering the keys. A screen
3472
3585
  // reader already announces the listbox semantics that make those keys work, so reading
3473
3586
  // "up arrow down arrow navigate" out loud is noise on every open.
3474
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
3475
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "pire-cp-hint", children: [
3476
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Kbd, { children: "\u2191" }),
3477
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Kbd, { children: "\u2193" }),
3587
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
3588
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "pire-cp-hint", children: [
3589
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Kbd, { children: "\u2191" }),
3590
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Kbd, { children: "\u2193" }),
3478
3591
  msg.commandPaletteHintNavigate
3479
3592
  ] }),
3480
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "pire-cp-hint", children: [
3481
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Kbd, { children: "\u21B5" }),
3593
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "pire-cp-hint", children: [
3594
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Kbd, { children: "\u21B5" }),
3482
3595
  msg.commandPaletteHintSelect
3483
3596
  ] }),
3484
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "pire-cp-hint", children: [
3485
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Kbd, { children: "esc" }),
3597
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "pire-cp-hint", children: [
3598
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Kbd, { children: "esc" }),
3486
3599
  msg.commandPaletteHintClose
3487
3600
  ] })
3488
3601
  ] }) })
@@ -3492,9 +3605,9 @@ function CommandPalette({
3492
3605
  );
3493
3606
  }
3494
3607
  function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3495
- const handler = React16.useRef(onTrigger);
3608
+ const handler = React18.useRef(onTrigger);
3496
3609
  handler.current = onTrigger;
3497
- React16.useEffect(() => {
3610
+ React18.useEffect(() => {
3498
3611
  if (isDisabled) return;
3499
3612
  const onKeyDown = (event) => {
3500
3613
  if (!(event.metaKey || event.ctrlKey) || event.altKey) return;
@@ -3509,10 +3622,10 @@ function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3509
3622
 
3510
3623
  // src/components/patterns/SidePanel.tsx
3511
3624
  var import_react_aria_components32 = require("react-aria-components");
3512
- var import_jsx_runtime60 = require("react/jsx-runtime");
3625
+ var import_jsx_runtime61 = require("react/jsx-runtime");
3513
3626
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
3514
3627
  const msg = usePireMessages();
3515
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3628
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
3516
3629
  import_react_aria_components32.ModalOverlay,
3517
3630
  {
3518
3631
  className: "pire-sidepanel-overlay",
@@ -3521,36 +3634,36 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
3521
3634
  onOpenChange: (o) => {
3522
3635
  if (!o) onClose?.();
3523
3636
  },
3524
- children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_aria_components32.Modal, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components32.Dialog, { className: "pire-dialog", style: { height: "100%" }, children: [
3525
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("header", { className: "pire-dialog-head", children: [
3526
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
3527
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_aria_components32.Heading, { slot: "title", className: "pire-dialog-title", children: title }),
3528
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
3637
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_aria_components32.Modal, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_react_aria_components32.Dialog, { className: "pire-dialog", style: { height: "100%" }, children: [
3638
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("header", { className: "pire-dialog-head", children: [
3639
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
3640
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_aria_components32.Heading, { slot: "title", className: "pire-dialog-title", children: title }),
3641
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
3529
3642
  ] }),
3530
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
3643
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
3531
3644
  ] }),
3532
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
3533
- footer ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("footer", { className: "pire-dialog-foot", children: footer }) : null
3645
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
3646
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("footer", { className: "pire-dialog-foot", children: footer }) : null
3534
3647
  ] }) })
3535
3648
  }
3536
3649
  );
3537
3650
  }
3538
3651
 
3539
3652
  // src/components/patterns/EmptyState.tsx
3540
- var import_jsx_runtime61 = require("react/jsx-runtime");
3653
+ var import_jsx_runtime62 = require("react/jsx-runtime");
3541
3654
  function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
3542
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
3543
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
3544
- title ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
3545
- children ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
3655
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
3656
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
3657
+ title ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
3658
+ children ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
3546
3659
  action
3547
3660
  ] });
3548
3661
  }
3549
3662
 
3550
3663
  // src/components/patterns/FileDropZone.tsx
3551
- var React17 = __toESM(require("react"), 1);
3664
+ var React19 = __toESM(require("react"), 1);
3552
3665
  var import_react_aria_components33 = require("react-aria-components");
3553
- var import_jsx_runtime62 = require("react/jsx-runtime");
3666
+ var import_jsx_runtime63 = require("react/jsx-runtime");
3554
3667
  var isImage2 = (file) => file.type.startsWith("image/");
3555
3668
  function FileDropZone({
3556
3669
  label,
@@ -3576,10 +3689,10 @@ function FileDropZone({
3576
3689
  style
3577
3690
  }) {
3578
3691
  const msg = usePireMessages();
3579
- const [uncontrolled, setUncontrolled] = React17.useState(defaultValue ?? []);
3692
+ const [uncontrolled, setUncontrolled] = React19.useState(defaultValue ?? []);
3580
3693
  const files = value ?? uncontrolled;
3581
- const created = React17.useRef([]);
3582
- React17.useEffect(() => () => {
3694
+ const created = React19.useRef([]);
3695
+ React19.useEffect(() => () => {
3583
3696
  for (const url of created.current) URL.revokeObjectURL(url);
3584
3697
  }, []);
3585
3698
  const commit = (next) => {
@@ -3599,12 +3712,12 @@ function FileDropZone({
3599
3712
  commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
3600
3713
  };
3601
3714
  const remove = (target) => commit(files.filter((f) => f.file !== target));
3602
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), children: [
3603
- label ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "pire-field-label", children: [
3715
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), children: [
3716
+ label ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "pire-field-label", children: [
3604
3717
  label,
3605
- isRequired ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
3718
+ isRequired ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
3606
3719
  ] }) : null,
3607
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
3720
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
3608
3721
  import_react_aria_components33.DropZone,
3609
3722
  {
3610
3723
  className: "pire-dropzone",
@@ -3617,25 +3730,25 @@ function FileDropZone({
3617
3730
  accept(dropped);
3618
3731
  },
3619
3732
  children: [
3620
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
3621
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
3622
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
3733
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
3734
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
3735
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
3623
3736
  import_react_aria_components33.FileTrigger,
3624
3737
  {
3625
3738
  acceptedFileTypes,
3626
3739
  allowsMultiple,
3627
3740
  onSelect: (list) => accept(list ? [...list] : []),
3628
- children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
3741
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
3629
3742
  }
3630
3743
  )
3631
3744
  ]
3632
3745
  }
3633
3746
  ),
3634
- files.length ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("li", { className: "pire-fileupload-item", children: [
3635
- previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
3636
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-fileupload-name", children: file.name }),
3637
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
3638
- isDisabled || isReadOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
3747
+ files.length ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("li", { className: "pire-fileupload-item", children: [
3748
+ previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
3749
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-fileupload-name", children: file.name }),
3750
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
3751
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
3639
3752
  IconButton,
3640
3753
  {
3641
3754
  icon: "x",
@@ -3645,14 +3758,15 @@ function FileDropZone({
3645
3758
  }
3646
3759
  )
3647
3760
  ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
3648
- uploadProgress != null ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
3649
- description ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-field-hint", children: description }) : null,
3650
- isInvalid && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-field-error", children: errorMessage }) : null
3761
+ uploadProgress != null ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
3762
+ description ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-field-hint", children: description }) : null,
3763
+ isInvalid && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-field-error", children: errorMessage }) : null
3651
3764
  ] });
3652
3765
  }
3653
3766
 
3654
3767
  // src/index.ts
3655
3768
  var import_react_aria_components34 = require("react-aria-components");
3769
+ var import_react_aria_components35 = require("react-aria-components");
3656
3770
  // Annotate the CommonJS export names for ESM import in node:
3657
3771
  0 && (module.exports = {
3658
3772
  Avatar,
@@ -3670,12 +3784,17 @@ var import_react_aria_components34 = require("react-aria-components");
3670
3784
  DateRangePicker,
3671
3785
  DescriptionList,
3672
3786
  Dialog,
3787
+ DialogActions,
3788
+ DialogBody,
3789
+ DialogDescription,
3790
+ DialogTitle,
3673
3791
  DialogTrigger,
3674
3792
  DonutChart,
3675
3793
  EmptyState,
3676
3794
  FileDropZone,
3677
3795
  FileUpload,
3678
3796
  FilterBar,
3797
+ Focusable,
3679
3798
  FooterBar,
3680
3799
  FormField,
3681
3800
  Heading,
@@ -3717,6 +3836,7 @@ var import_react_aria_components34 = require("react-aria-components");
3717
3836
  SidePanel,
3718
3837
  Skeleton,
3719
3838
  SkeletonTableRow,
3839
+ SplitPane,
3720
3840
  Strong,
3721
3841
  SubmenuTrigger,
3722
3842
  Switch,