@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.js CHANGED
@@ -405,15 +405,17 @@ var Button = React.forwardRef(function Button2({ children, variant = "secondary"
405
405
  });
406
406
 
407
407
  // src/components/core/IconButton.tsx
408
- import * as React2 from "react";
408
+ import * as React3 from "react";
409
409
  import { Button as AriaButton2 } from "react-aria-components";
410
410
 
411
411
  // src/components/feedback/Tooltip.tsx
412
- import { TooltipTrigger, Tooltip as AriaTooltip, OverlayArrow } from "react-aria-components";
412
+ import * as React2 from "react";
413
+ import { TooltipTrigger, Tooltip as AriaTooltip, OverlayArrow, Focusable } from "react-aria-components";
413
414
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
414
415
  function Tooltip({ label, placement = "top", delay = 500, children }) {
416
+ const target = React2.isValidElement(children) ? React2.cloneElement(children, { className: cx(children.props.className, "pire-tooltip-target") }) : /* @__PURE__ */ jsx3("span", { className: "pire-tooltip-target", children });
415
417
  return /* @__PURE__ */ jsxs2(TooltipTrigger, { delay, closeDelay: 0, children: [
416
- children,
418
+ /* @__PURE__ */ jsx3(Focusable, { children: target }),
417
419
  /* @__PURE__ */ jsxs2(AriaTooltip, { className: "pire-tooltip", placement, offset: 6, children: [
418
420
  /* @__PURE__ */ jsx3(OverlayArrow, { children: /* @__PURE__ */ jsx3("span", {}) }),
419
421
  label
@@ -423,7 +425,7 @@ function Tooltip({ label, placement = "top", delay = 500, children }) {
423
425
 
424
426
  // src/components/core/IconButton.tsx
425
427
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
426
- var IconButton = React2.forwardRef(function IconButton2({
428
+ var IconButton = React3.forwardRef(function IconButton2({
427
429
  icon,
428
430
  label,
429
431
  size = "md",
@@ -511,11 +513,11 @@ function Card({ title, subtitle, icon, actions, footer, interactive, children, c
511
513
  }
512
514
 
513
515
  // src/components/core/Avatar.tsx
514
- import * as React3 from "react";
516
+ import * as React4 from "react";
515
517
  import { jsx as jsx8 } from "react/jsx-runtime";
516
518
  var initials = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
517
519
  function Avatar({ name, size = "md", src, className, ...rest }) {
518
- const [failed, setFailed] = React3.useState(false);
520
+ const [failed, setFailed] = React4.useState(false);
519
521
  return /* @__PURE__ */ jsx8("span", { className: cx("pire-avatar", className), "data-size": size, role: "img", "aria-label": name, ...rest, children: src && !failed ? /* @__PURE__ */ jsx8(
520
522
  "img",
521
523
  {
@@ -528,7 +530,7 @@ function Avatar({ name, size = "md", src, className, ...rest }) {
528
530
  }
529
531
 
530
532
  // src/components/core/SegmentedControl.tsx
531
- import * as React4 from "react";
533
+ import * as React5 from "react";
532
534
  import { ToggleButtonGroup, ToggleButton } from "react-aria-components";
533
535
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
534
536
  function SegmentedControl({
@@ -542,7 +544,7 @@ function SegmentedControl({
542
544
  style,
543
545
  ...rest
544
546
  }) {
545
- const selected = React4.useMemo(() => new Set(value ? [value] : defaultValue ? [defaultValue] : []), [value, defaultValue]);
547
+ const selected = React5.useMemo(() => new Set(value ? [value] : defaultValue ? [defaultValue] : []), [value, defaultValue]);
546
548
  return /* @__PURE__ */ jsx9(
547
549
  ToggleButtonGroup,
548
550
  {
@@ -704,7 +706,7 @@ function FormField({ label, htmlFor, isRequired, hint, error, layout = "stacked"
704
706
  }
705
707
 
706
708
  // src/components/forms/Input.tsx
707
- import * as React6 from "react";
709
+ import * as React7 from "react";
708
710
  import {
709
711
  TextField,
710
712
  Label,
@@ -716,7 +718,7 @@ import {
716
718
  } from "react-aria-components";
717
719
 
718
720
  // src/i18n/PireIntlProvider.tsx
719
- import * as React5 from "react";
721
+ import * as React6 from "react";
720
722
 
721
723
  // src/i18n/messages.ts
722
724
  var enMessages = {
@@ -726,6 +728,7 @@ var enMessages = {
726
728
  dataTableSelectAll: "Select all rows",
727
729
  dataTableSelectRow: "Select row",
728
730
  dataTableLoading: "Loading records",
731
+ dataTableSummaryRow: "Summary",
729
732
  dialogClose: "Close",
730
733
  sidePanelClose: "Close panel",
731
734
  inlineMessageDismiss: "Dismiss message",
@@ -757,6 +760,9 @@ var enMessages = {
757
760
  paginationNext: "Next page",
758
761
  paginationRowsPerPage: "Rows per page",
759
762
  sideNavLabel: "Main navigation",
763
+ splitPaneList: "List",
764
+ splitPaneDetail: "Detail",
765
+ splitPaneBack: "Back to list",
760
766
  fileUploadChoose: "Choose files",
761
767
  fileUploadRemoveNamed: "Remove {name}",
762
768
  fileUploadUploading: "Uploading",
@@ -781,6 +787,7 @@ var esMessages = {
781
787
  dataTableSelectAll: "Seleccionar todas las filas",
782
788
  dataTableSelectRow: "Seleccionar fila",
783
789
  dataTableLoading: "Cargando registros",
790
+ dataTableSummaryRow: "Resumen",
784
791
  dialogClose: "Cerrar",
785
792
  sidePanelClose: "Cerrar panel",
786
793
  inlineMessageDismiss: "Descartar mensaje",
@@ -812,6 +819,9 @@ var esMessages = {
812
819
  paginationNext: "P\xE1gina siguiente",
813
820
  paginationRowsPerPage: "Filas por p\xE1gina",
814
821
  sideNavLabel: "Navegaci\xF3n principal",
822
+ splitPaneList: "Lista",
823
+ splitPaneDetail: "Detalle",
824
+ splitPaneBack: "Volver a la lista",
815
825
  fileUploadChoose: "Elegir archivos",
816
826
  fileUploadRemoveNamed: "Quitar {name}",
817
827
  fileUploadUploading: "Subiendo",
@@ -832,19 +842,19 @@ var esMessages = {
832
842
 
833
843
  // src/i18n/PireIntlProvider.tsx
834
844
  import { jsx as jsx16 } from "react/jsx-runtime";
835
- var MessagesContext = React5.createContext(enMessages);
845
+ var MessagesContext = React6.createContext(enMessages);
836
846
  function PireIntlProvider({ messages, children }) {
837
- const value = React5.useMemo(
847
+ const value = React6.useMemo(
838
848
  () => messages ? { ...enMessages, ...messages } : enMessages,
839
849
  [messages]
840
850
  );
841
851
  return /* @__PURE__ */ jsx16(MessagesContext.Provider, { value, children });
842
852
  }
843
853
  function usePireMessages() {
844
- return React5.useContext(MessagesContext);
854
+ return React6.useContext(MessagesContext);
845
855
  }
846
856
  function useMessage(key, override) {
847
- const messages = React5.useContext(MessagesContext);
857
+ const messages = React6.useContext(MessagesContext);
848
858
  return override ?? messages[key];
849
859
  }
850
860
 
@@ -869,7 +879,7 @@ function Input({
869
879
  }) {
870
880
  const msg = usePireMessages();
871
881
  const isControlled = rest.value !== void 0;
872
- const [ownValue, setOwnValue] = React6.useState(rest.defaultValue ?? "");
882
+ const [ownValue, setOwnValue] = React7.useState(rest.defaultValue ?? "");
873
883
  const currentValue = isControlled ? rest.value : ownValue;
874
884
  const handleChange = (next) => {
875
885
  setOwnValue(next);
@@ -916,10 +926,10 @@ function Input({
916
926
  }
917
927
 
918
928
  // src/components/forms/TextArea.tsx
919
- import * as React7 from "react";
929
+ import * as React8 from "react";
920
930
  import { TextField as TextField2, Label as Label2, TextArea as AriaTextArea, Group as Group2, Text as Text3, FieldError as FieldError2 } from "react-aria-components";
921
931
  import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
922
- var useIsomorphicLayoutEffect = typeof document === "undefined" ? React7.useEffect : React7.useLayoutEffect;
932
+ var useIsomorphicLayoutEffect = typeof document === "undefined" ? React8.useEffect : React8.useLayoutEffect;
923
933
  function TextArea({
924
934
  label,
925
935
  description,
@@ -935,13 +945,13 @@ function TextArea({
935
945
  onChange,
936
946
  ...rest
937
947
  }) {
938
- const innerRef = React7.useRef(null);
939
- const ref = React7.useCallback((node) => {
948
+ const innerRef = React8.useRef(null);
949
+ const ref = React8.useCallback((node) => {
940
950
  innerRef.current = node;
941
951
  if (typeof textAreaRef === "function") textAreaRef(node);
942
952
  else if (textAreaRef) textAreaRef.current = node;
943
953
  }, [textAreaRef]);
944
- const grow = React7.useCallback(() => {
954
+ const grow = React8.useCallback(() => {
945
955
  const el = innerRef.current;
946
956
  if (!el || !autoGrow) return;
947
957
  const styles = getComputedStyle(el);
@@ -1228,7 +1238,7 @@ function ComboBox({
1228
1238
  }
1229
1239
 
1230
1240
  // src/components/forms/MultiComboBox.tsx
1231
- import * as React8 from "react";
1241
+ import * as React9 from "react";
1232
1242
  import {
1233
1243
  ComboBox as AriaComboBox2,
1234
1244
  Label as Label6,
@@ -1267,15 +1277,15 @@ function MultiComboBox({
1267
1277
  ...rest
1268
1278
  }) {
1269
1279
  const msg = usePireMessages();
1270
- const items = React8.useMemo(() => options.map(norm3), [options]);
1280
+ const items = React9.useMemo(() => options.map(norm3), [options]);
1271
1281
  const collection = isFilteredExternally ? { items } : { defaultItems: items };
1272
1282
  const showsStatus = isLoading || isFilteredExternally && items.length === 0 && emptyLabel != null;
1273
- const [uncontrolled, setUncontrolled] = React8.useState(defaultValue ?? []);
1274
- const [announcement, setAnnouncement] = React8.useState("");
1275
- const inputRef = React8.useRef(null);
1283
+ const [uncontrolled, setUncontrolled] = React9.useState(defaultValue ?? []);
1284
+ const [announcement, setAnnouncement] = React9.useState("");
1285
+ const inputRef = React9.useRef(null);
1276
1286
  const raw = value ?? uncontrolled;
1277
1287
  const contentKey = raw.join("\0");
1278
- const values = React8.useMemo(() => raw, [contentKey]);
1288
+ const values = React9.useMemo(() => raw, [contentKey]);
1279
1289
  const labelOf = (v) => items.find((o) => o.value === v)?.label ?? v;
1280
1290
  const isEditable = !rest.isDisabled && !rest.isReadOnly;
1281
1291
  const commit = (next) => {
@@ -1635,14 +1645,27 @@ function DateRangePicker({
1635
1645
  }
1636
1646
 
1637
1647
  // src/components/forms/ValueHelpField.tsx
1638
- import * as React10 from "react";
1648
+ import * as React12 from "react";
1639
1649
 
1640
1650
  // src/components/patterns/ValueHelpDialog.tsx
1641
- import * as React9 from "react";
1651
+ import * as React11 from "react";
1642
1652
 
1643
1653
  // src/components/feedback/Dialog.tsx
1654
+ import * as React10 from "react";
1644
1655
  import { ModalOverlay, Modal, Dialog as AriaDialog3, Heading as Heading4 } from "react-aria-components";
1645
1656
  import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
1657
+ function DialogTitle({ children, className }) {
1658
+ return /* @__PURE__ */ jsx28(Heading4, { slot: "title", className: cx("pire-dialog-title", className), children });
1659
+ }
1660
+ function DialogDescription({ children, className }) {
1661
+ return /* @__PURE__ */ jsx28("p", { className: cx("pire-dialog-sub", className), style: { margin: 0 }, children });
1662
+ }
1663
+ function DialogBody({ children, className }) {
1664
+ return /* @__PURE__ */ jsx28("div", { className: cx("pire-dialog-body", className), children });
1665
+ }
1666
+ function DialogActions({ children, className }) {
1667
+ return /* @__PURE__ */ jsx28("footer", { className: cx("pire-dialog-foot", className), children });
1668
+ }
1646
1669
  function Dialog({
1647
1670
  isOpen,
1648
1671
  onOpenChange,
@@ -1662,6 +1685,18 @@ function Dialog({
1662
1685
  onClose?.();
1663
1686
  onOpenChange?.(false);
1664
1687
  };
1688
+ const parts = React10.Children.toArray(children);
1689
+ const slotOf = (type) => parts.find((node) => React10.isValidElement(node) && node.type === type);
1690
+ const titleSlot = slotOf(DialogTitle);
1691
+ const descriptionSlot = slotOf(DialogDescription);
1692
+ const bodySlot = slotOf(DialogBody);
1693
+ const actionsSlot = slotOf(DialogActions);
1694
+ const slots = [titleSlot, descriptionSlot, bodySlot, actionsSlot];
1695
+ const loose = parts.filter((node) => !slots.includes(node));
1696
+ const heading = titleSlot ?? (title ? /* @__PURE__ */ jsx28(Heading4, { slot: "title", className: "pire-dialog-title", children: title }) : null);
1697
+ const description = descriptionSlot ?? (subtitle ? /* @__PURE__ */ jsx28("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null);
1698
+ const actions = actionsSlot ?? (footer ? /* @__PURE__ */ jsx28("footer", { className: "pire-dialog-foot", children: footer }) : null);
1699
+ const body = bodySlot ?? (loose.length ? /* @__PURE__ */ jsx28("div", { className: "pire-dialog-body", children: loose }) : null);
1665
1700
  return /* @__PURE__ */ jsx28(
1666
1701
  ModalOverlay,
1667
1702
  {
@@ -1672,15 +1707,15 @@ function Dialog({
1672
1707
  if (!o) close();
1673
1708
  },
1674
1709
  children: /* @__PURE__ */ jsx28(Modal, { className: cx("pire-modal", className), "data-size": size, style, children: /* @__PURE__ */ jsxs21(AriaDialog3, { className: "pire-dialog", children: [
1675
- title ? /* @__PURE__ */ jsxs21("header", { className: "pire-dialog-head", children: [
1710
+ heading || description ? /* @__PURE__ */ jsxs21("header", { className: "pire-dialog-head", children: [
1676
1711
  /* @__PURE__ */ jsxs21("div", { style: { flex: 1, minWidth: 0 }, children: [
1677
- /* @__PURE__ */ jsx28(Heading4, { slot: "title", className: "pire-dialog-title", children: title }),
1678
- subtitle ? /* @__PURE__ */ jsx28("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
1712
+ heading,
1713
+ description
1679
1714
  ] }),
1680
1715
  showClose ? /* @__PURE__ */ jsx28(IconButton, { icon: "x", label: msg.dialogClose, size: "sm", onPress: close }) : null
1681
1716
  ] }) : null,
1682
- children ? /* @__PURE__ */ jsx28("div", { className: "pire-dialog-body", children }) : null,
1683
- footer ? /* @__PURE__ */ jsx28("footer", { className: "pire-dialog-foot", children: footer }) : null
1717
+ body,
1718
+ actions
1684
1719
  ] }) })
1685
1720
  }
1686
1721
  );
@@ -1691,6 +1726,7 @@ import {
1691
1726
  Table,
1692
1727
  TableHeader,
1693
1728
  TableBody,
1729
+ TableFooter,
1694
1730
  Column,
1695
1731
  Row,
1696
1732
  Cell
@@ -1758,6 +1794,10 @@ function DataTable({
1758
1794
  isLoading,
1759
1795
  loadingRowCount,
1760
1796
  loadingLabel,
1797
+ footer,
1798
+ rowProps,
1799
+ renderExpanded,
1800
+ expandedIds,
1761
1801
  className,
1762
1802
  style,
1763
1803
  ...rest
@@ -1774,6 +1814,11 @@ function DataTable({
1774
1814
  ...columns.map((c) => ({ width: c.width, align: c.align, numeric: c.numeric }))
1775
1815
  ];
1776
1816
  const body = isLoading ? [] : rows;
1817
+ const presentation = new Map(rows.map((row) => [row.id, rowProps?.(row) ?? {}]));
1818
+ const disabledKeys = rows.filter((row) => presentation.get(row.id)?.isDisabled).map((row) => row.id);
1819
+ const expanded = new Set((expandedIds ?? []).map(String));
1820
+ const spanAll = columns.length + (selectable ? 1 : 0);
1821
+ const expandedKey = (id) => `${id}::__pire_expanded__`;
1777
1822
  return /* @__PURE__ */ jsx30(
1778
1823
  "div",
1779
1824
  {
@@ -1788,6 +1833,7 @@ function DataTable({
1788
1833
  "data-density": density,
1789
1834
  "data-sticky": String(stickyHeader),
1790
1835
  "aria-label": rest["aria-label"],
1836
+ disabledKeys: disabledKeys.length ? new Set(disabledKeys) : void 0,
1791
1837
  selectionMode: selectable ? "multiple" : "none",
1792
1838
  selectedKeys: selected ? new Set(selected) : void 0,
1793
1839
  onSelectionChange: handleSelection,
@@ -1810,7 +1856,7 @@ function DataTable({
1810
1856
  width: c.width,
1811
1857
  "data-align": c.numeric || c.align === "right" ? "right" : c.align,
1812
1858
  "data-allows-sorting": c.sortable ? "true" : void 0,
1813
- children: /* @__PURE__ */ jsxs22("span", { className: "pire-th-inner", children: [
1859
+ children: /* @__PURE__ */ jsxs22("span", { className: cx("pire-th-inner", c.hideLabel && "pire-sr-only"), children: [
1814
1860
  c.label,
1815
1861
  c.sortable ? /* @__PURE__ */ jsx30(
1816
1862
  Icon,
@@ -1831,19 +1877,46 @@ function DataTable({
1831
1877
  // biome-ignore lint/suspicious/noArrayIndexKey: placeholder rows are positional.
1832
1878
  /* @__PURE__ */ jsx30(SkeletonTableRow, { columns: skeletonColumns, density }, i)
1833
1879
  ))
1834
- ] }) : /* @__PURE__ */ jsx30("div", { className: "pire-table-empty", children: emptyLabel }), children: body.map((row) => /* @__PURE__ */ jsxs22(Row, { id: row.id, className: "pire-tr", "data-pressable": onRowAction ? "true" : void 0, children: [
1835
- selectable ? /* @__PURE__ */ jsx30(Cell, { className: "pire-td", children: /* @__PURE__ */ jsx30(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectRow }) }) : null,
1836
- columns.map((c) => /* @__PURE__ */ jsx30(
1880
+ ] }) : /* @__PURE__ */ jsx30("div", { className: "pire-table-empty", children: emptyLabel }), children: body.flatMap((row) => {
1881
+ const rowIsDisabled = presentation.get(row.id)?.isDisabled;
1882
+ const record = /* @__PURE__ */ jsxs22(
1883
+ Row,
1884
+ {
1885
+ id: row.id,
1886
+ className: cx("pire-tr", presentation.get(row.id)?.className),
1887
+ "data-pressable": onRowAction && !rowIsDisabled ? "true" : void 0,
1888
+ children: [
1889
+ selectable ? /* @__PURE__ */ jsx30(Cell, { className: "pire-td", children: /* @__PURE__ */ jsx30(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectRow }) }) : null,
1890
+ columns.map((c) => /* @__PURE__ */ jsx30(
1891
+ Cell,
1892
+ {
1893
+ className: "pire-td",
1894
+ "data-numeric": c.numeric ? "true" : void 0,
1895
+ style: { textAlign: c.align && !c.numeric ? c.align : void 0 },
1896
+ children: c.render ? c.render(row) : row[c.key]
1897
+ },
1898
+ c.key
1899
+ ))
1900
+ ]
1901
+ },
1902
+ row.id
1903
+ );
1904
+ if (!renderExpanded || !expanded.has(String(row.id))) return [record];
1905
+ return [record, /* @__PURE__ */ jsx30(Row, { id: expandedKey(row.id), className: "pire-tr-expanded", children: /* @__PURE__ */ jsx30(Cell, { className: "pire-td-expanded", colSpan: spanAll, children: renderExpanded(row) }) }, expandedKey(row.id))];
1906
+ }) }),
1907
+ footer && !isLoading ? /* @__PURE__ */ jsx30(TableFooter, { className: "pire-tfoot", children: /* @__PURE__ */ jsxs22(Row, { id: "__pire_footer__", className: "pire-tr-footer", children: [
1908
+ selectable ? /* @__PURE__ */ jsx30(Cell, { className: "pire-tf" }) : null,
1909
+ columns.map((c, i) => /* @__PURE__ */ jsx30(
1837
1910
  Cell,
1838
1911
  {
1839
- className: "pire-td",
1912
+ className: "pire-tf",
1840
1913
  "data-numeric": c.numeric ? "true" : void 0,
1841
1914
  style: { textAlign: c.align && !c.numeric ? c.align : void 0 },
1842
- children: c.render ? c.render(row) : row[c.key]
1915
+ children: footer[c.key] ?? (i === 0 && !selectable ? /* @__PURE__ */ jsx30("span", { className: "pire-sr-only", children: msg.dataTableSummaryRow }) : null)
1843
1916
  },
1844
1917
  c.key
1845
1918
  ))
1846
- ] }, row.id)) })
1919
+ ] }) }) : null
1847
1920
  ]
1848
1921
  }
1849
1922
  )
@@ -1868,11 +1941,11 @@ function ValueHelpDialog({
1868
1941
  onClose
1869
1942
  }) {
1870
1943
  const msg = usePireMessages();
1871
- const [query, setQuery] = React9.useState("");
1872
- React9.useEffect(() => {
1944
+ const [query, setQuery] = React11.useState("");
1945
+ React11.useEffect(() => {
1873
1946
  if (isOpen) setQuery("");
1874
1947
  }, [isOpen]);
1875
- const filtered = React9.useMemo(() => {
1948
+ const filtered = React11.useMemo(() => {
1876
1949
  if (isFilteredExternally) return rows;
1877
1950
  const q = query.trim().toLowerCase();
1878
1951
  if (!q) return rows;
@@ -1954,7 +2027,7 @@ function ValueHelpField({
1954
2027
  style
1955
2028
  }) {
1956
2029
  const msg = usePireMessages();
1957
- const [open, setOpen] = React10.useState(false);
2030
+ const [open, setOpen] = React12.useState(false);
1958
2031
  return /* @__PURE__ */ jsxs24("div", { className: cx(className), style, children: [
1959
2032
  /* @__PURE__ */ jsx32(
1960
2033
  Input,
@@ -2010,7 +2083,7 @@ function ValueHelpField({
2010
2083
  }
2011
2084
 
2012
2085
  // src/components/forms/FileUpload.tsx
2013
- import * as React11 from "react";
2086
+ import * as React13 from "react";
2014
2087
  import { FileTrigger, Text as Text11 } from "react-aria-components";
2015
2088
 
2016
2089
  // src/components/feedback/ProgressBar.tsx
@@ -2100,10 +2173,10 @@ function FileUpload({
2100
2173
  style
2101
2174
  }) {
2102
2175
  const msg = usePireMessages();
2103
- const [uncontrolled, setUncontrolled] = React11.useState(defaultValue ?? []);
2176
+ const [uncontrolled, setUncontrolled] = React13.useState(defaultValue ?? []);
2104
2177
  const files = value ?? uncontrolled;
2105
- const created = React11.useRef([]);
2106
- React11.useEffect(() => () => {
2178
+ const created = React13.useRef([]);
2179
+ React13.useEffect(() => () => {
2107
2180
  for (const url of created.current) URL.revokeObjectURL(url);
2108
2181
  }, []);
2109
2182
  const commit = (next) => {
@@ -2214,7 +2287,7 @@ function ShellBar({
2214
2287
  }
2215
2288
 
2216
2289
  // src/components/navigation/SideNav.tsx
2217
- import * as React12 from "react";
2290
+ import * as React14 from "react";
2218
2291
  import {
2219
2292
  Button as AriaButton12,
2220
2293
  Disclosure,
@@ -2314,10 +2387,10 @@ function SideNav({
2314
2387
  const msg = usePireMessages();
2315
2388
  const activeParent = findActiveParent(groups, value);
2316
2389
  const isControlled = expandedIds != null;
2317
- const [ownExpanded, setOwnExpanded] = React12.useState(
2390
+ const [ownExpanded, setOwnExpanded] = React14.useState(
2318
2391
  () => new Set(defaultExpandedIds ?? (activeParent ? [activeParent] : []))
2319
2392
  );
2320
- const [lastValue, setLastValue] = React12.useState(value);
2393
+ const [lastValue, setLastValue] = React14.useState(value);
2321
2394
  if (value !== lastValue) {
2322
2395
  setLastValue(value);
2323
2396
  if (!isControlled && activeParent && !ownExpanded.has(activeParent)) {
@@ -2581,7 +2654,7 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
2581
2654
  }
2582
2655
 
2583
2656
  // src/components/feedback/Toast.tsx
2584
- import * as React13 from "react";
2657
+ import * as React15 from "react";
2585
2658
  import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
2586
2659
  var KIND_ICON2 = {
2587
2660
  info: "info",
@@ -2607,26 +2680,26 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
2607
2680
  }
2608
2681
  );
2609
2682
  }
2610
- var ToastContext = React13.createContext(null);
2683
+ var ToastContext = React15.createContext(null);
2611
2684
  function ToastProvider({ children, timeout = 6e3 }) {
2612
2685
  const msg = usePireMessages();
2613
- const [toasts, setToasts] = React13.useState([]);
2614
- const close = React13.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2615
- const add = React13.useCallback((toast) => {
2686
+ const [toasts, setToasts] = React15.useState([]);
2687
+ const close = React15.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2688
+ const add = React15.useCallback((toast) => {
2616
2689
  const id = Math.random().toString(36).slice(2);
2617
2690
  setToasts((t) => [...t, { ...toast, id }]);
2618
2691
  const ms = toast.timeout ?? timeout;
2619
2692
  if (ms > 0) setTimeout(() => close(id), ms);
2620
2693
  return id;
2621
2694
  }, [close, timeout]);
2622
- const value = React13.useMemo(() => ({ add, close }), [add, close]);
2695
+ const value = React15.useMemo(() => ({ add, close }), [add, close]);
2623
2696
  return /* @__PURE__ */ jsxs34(ToastContext.Provider, { value, children: [
2624
2697
  children,
2625
2698
  /* @__PURE__ */ jsx42("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ jsx42(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
2626
2699
  ] });
2627
2700
  }
2628
2701
  function useToast() {
2629
- const ctx = React13.useContext(ToastContext);
2702
+ const ctx = React15.useContext(ToastContext);
2630
2703
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
2631
2704
  return ctx;
2632
2705
  }
@@ -2976,14 +3049,14 @@ function BarChart({
2976
3049
  }
2977
3050
 
2978
3051
  // src/components/data/LineChart.tsx
2979
- import * as React14 from "react";
3052
+ import * as React16 from "react";
2980
3053
  import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
2981
3054
  var PLOT_INSET = { top: 10, right: 14, bottom: 24, left: 58 };
2982
3055
  var MARKER_LIMIT = 20;
2983
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React14.useEffect : React14.useLayoutEffect;
3056
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React16.useEffect : React16.useLayoutEffect;
2984
3057
  function useMeasuredWidth() {
2985
- const ref = React14.useRef(null);
2986
- const [width, setWidth] = React14.useState(0);
3058
+ const ref = React16.useRef(null);
3059
+ const [width, setWidth] = React16.useState(0);
2987
3060
  useIsomorphicLayoutEffect2(() => {
2988
3061
  const element = ref.current;
2989
3062
  if (!element) return;
@@ -3146,7 +3219,7 @@ function LineChart({
3146
3219
  }
3147
3220
 
3148
3221
  // src/components/data/DonutChart.tsx
3149
- import * as React15 from "react";
3222
+ import * as React17 from "react";
3150
3223
  import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
3151
3224
  var SEGMENT_GAP_DEGREES = 1.5;
3152
3225
  function DonutChart({
@@ -3167,7 +3240,7 @@ function DonutChart({
3167
3240
  }) {
3168
3241
  const label = rest["aria-label"];
3169
3242
  const msg = usePireMessages();
3170
- const [hoveredIndex, setHoveredIndex] = React15.useState(null);
3243
+ const [hoveredIndex, setHoveredIndex] = React17.useState(null);
3171
3244
  warnOnDonutShape(series, categories.length, label);
3172
3245
  const values = (series[0]?.values ?? []).slice(0, categories.length);
3173
3246
  const segments = categories.map((category, index) => ({ category, index, value: values[index] ?? 0 })).filter((segment) => segment.value > 0);
@@ -3331,8 +3404,43 @@ function FooterBar({ note, actions, children, className, ...rest }) {
3331
3404
  ] });
3332
3405
  }
3333
3406
 
3407
+ // src/components/layout/SplitPane.tsx
3408
+ import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
3409
+ function SplitPane({
3410
+ list,
3411
+ detail,
3412
+ listWidth = "24rem",
3413
+ listLabel,
3414
+ detailLabel,
3415
+ emptyDetail,
3416
+ onBack,
3417
+ backLabel,
3418
+ className,
3419
+ style,
3420
+ ...rest
3421
+ }) {
3422
+ const msg = usePireMessages();
3423
+ const width = typeof listWidth === "number" ? `${listWidth}px` : listWidth;
3424
+ return /* @__PURE__ */ jsxs49(
3425
+ "div",
3426
+ {
3427
+ className: cx("pire-split", className),
3428
+ "data-has-detail": detail != null ? "true" : void 0,
3429
+ style: { ["--pire-split-list-w"]: width, ...style },
3430
+ ...rest,
3431
+ children: [
3432
+ /* @__PURE__ */ jsx58("section", { className: "pire-split-list", "aria-label": listLabel ?? msg.splitPaneList, children: list }),
3433
+ /* @__PURE__ */ jsxs49("section", { className: "pire-split-detail", "aria-label": detailLabel ?? msg.splitPaneDetail, children: [
3434
+ onBack ? /* @__PURE__ */ jsx58("div", { className: "pire-split-back", children: /* @__PURE__ */ jsx58(Button, { variant: "tertiary", size: "sm", icon: "arrow-left", onPress: onBack, children: backLabel ?? msg.splitPaneBack }) }) : null,
3435
+ detail ?? /* @__PURE__ */ jsx58("div", { className: "pire-split-empty", children: emptyDetail })
3436
+ ] })
3437
+ ]
3438
+ }
3439
+ );
3440
+ }
3441
+
3334
3442
  // src/components/patterns/ConfirmDialog.tsx
3335
- import { Fragment as Fragment4, jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
3443
+ import { Fragment as Fragment4, jsx as jsx59, jsxs as jsxs50 } from "react/jsx-runtime";
3336
3444
  function ConfirmDialog({
3337
3445
  isOpen,
3338
3446
  title,
@@ -3346,7 +3454,7 @@ function ConfirmDialog({
3346
3454
  onConfirm,
3347
3455
  onCancel
3348
3456
  }) {
3349
- return /* @__PURE__ */ jsxs49(
3457
+ return /* @__PURE__ */ jsxs50(
3350
3458
  Dialog,
3351
3459
  {
3352
3460
  isOpen,
@@ -3356,12 +3464,12 @@ function ConfirmDialog({
3356
3464
  onClose: onCancel,
3357
3465
  isDismissable: !isBusy,
3358
3466
  showClose: false,
3359
- footer: /* @__PURE__ */ jsxs49(Fragment4, { children: [
3360
- /* @__PURE__ */ jsx58(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3361
- /* @__PURE__ */ jsx58(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3467
+ footer: /* @__PURE__ */ jsxs50(Fragment4, { children: [
3468
+ /* @__PURE__ */ jsx59(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3469
+ /* @__PURE__ */ jsx59(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3362
3470
  ] }),
3363
3471
  children: [
3364
- consequence ? /* @__PURE__ */ jsx58(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3472
+ consequence ? /* @__PURE__ */ jsx59(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3365
3473
  children
3366
3474
  ]
3367
3475
  }
@@ -3369,7 +3477,7 @@ function ConfirmDialog({
3369
3477
  }
3370
3478
 
3371
3479
  // src/components/patterns/CommandPalette.tsx
3372
- import * as React16 from "react";
3480
+ import * as React18 from "react";
3373
3481
  import {
3374
3482
  Autocomplete,
3375
3483
  ModalOverlay as ModalOverlay2,
@@ -3382,7 +3490,7 @@ import {
3382
3490
  Header as Header2,
3383
3491
  useFilter
3384
3492
  } from "react-aria-components";
3385
- import { Fragment as Fragment5, jsx as jsx59, jsxs as jsxs50 } from "react/jsx-runtime";
3493
+ import { Fragment as Fragment5, jsx as jsx60, jsxs as jsxs51 } from "react/jsx-runtime";
3386
3494
  var RESULTS_SECTION_KEY = "__pire_results__";
3387
3495
  var searchableText = (item) => [item.label, item.description, item.keywords].filter(Boolean).join(" ");
3388
3496
  function CommandPalette({
@@ -3403,17 +3511,17 @@ function CommandPalette({
3403
3511
  style
3404
3512
  }) {
3405
3513
  const msg = usePireMessages();
3406
- const [query, setQuery] = React16.useState("");
3514
+ const [query, setQuery] = React18.useState("");
3407
3515
  const { contains } = useFilter({ sensitivity: "base" });
3408
- React16.useEffect(() => {
3516
+ React18.useEffect(() => {
3409
3517
  if (isOpen) setQuery("");
3410
3518
  }, [isOpen]);
3411
- const searchableById = React16.useMemo(() => {
3519
+ const searchableById = React18.useMemo(() => {
3412
3520
  const byId = /* @__PURE__ */ new Map();
3413
3521
  for (const group of groups) for (const item of group.items) byId.set(item.id, searchableText(item));
3414
3522
  return byId;
3415
3523
  }, [groups]);
3416
- const filter = React16.useCallback((textValue, inputValue, node) => {
3524
+ const filter = React18.useCallback((textValue, inputValue, node) => {
3417
3525
  if (node.parentKey === RESULTS_SECTION_KEY) return true;
3418
3526
  return contains(searchableById.get(String(node.key)) ?? textValue, inputValue);
3419
3527
  }, [contains, searchableById]);
@@ -3423,7 +3531,7 @@ function CommandPalette({
3423
3531
  };
3424
3532
  const sections = [...groups, ...resultsGroup ? [{ ...resultsGroup, id: RESULTS_SECTION_KEY }] : []];
3425
3533
  const status = isLoading ? loadingLabel ?? msg.commandPaletteLoading : emptyLabel ?? msg.commandPaletteEmpty;
3426
- return /* @__PURE__ */ jsx59(
3534
+ return /* @__PURE__ */ jsx60(
3427
3535
  ModalOverlay2,
3428
3536
  {
3429
3537
  className: "pire-cp-overlay",
@@ -3432,11 +3540,11 @@ function CommandPalette({
3432
3540
  onOpenChange: (open) => {
3433
3541
  if (!open) onOpenChange?.(false);
3434
3542
  },
3435
- children: /* @__PURE__ */ jsx59(Modal2, { className: cx("pire-cp-modal", className), style, children: /* @__PURE__ */ jsxs50(AriaDialog4, { className: "pire-cp-dialog", "aria-label": ariaLabel ?? msg.commandPaletteLabel, children: [
3436
- /* @__PURE__ */ jsxs50(Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3437
- /* @__PURE__ */ jsxs50(SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3438
- /* @__PURE__ */ jsx59(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3439
- /* @__PURE__ */ jsx59(
3543
+ children: /* @__PURE__ */ jsx60(Modal2, { className: cx("pire-cp-modal", className), style, children: /* @__PURE__ */ jsxs51(AriaDialog4, { className: "pire-cp-dialog", "aria-label": ariaLabel ?? msg.commandPaletteLabel, children: [
3544
+ /* @__PURE__ */ jsxs51(Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3545
+ /* @__PURE__ */ jsxs51(SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3546
+ /* @__PURE__ */ jsx60(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3547
+ /* @__PURE__ */ jsx60(
3440
3548
  AriaInput5,
3441
3549
  {
3442
3550
  className: "pire-cp-input",
@@ -3445,16 +3553,16 @@ function CommandPalette({
3445
3553
  }
3446
3554
  )
3447
3555
  ] }),
3448
- isLoading ? /* @__PURE__ */ jsx59("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3449
- /* @__PURE__ */ jsx59(
3556
+ isLoading ? /* @__PURE__ */ jsx60("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3557
+ /* @__PURE__ */ jsx60(
3450
3558
  AriaMenu2,
3451
3559
  {
3452
3560
  className: "pire-cp-list",
3453
3561
  onAction: (key) => onAction?.(String(key)),
3454
- renderEmptyState: () => /* @__PURE__ */ jsx59("div", { className: "pire-cp-status", children: status }),
3455
- children: sections.map((section) => /* @__PURE__ */ jsxs50(AriaMenuSection2, { id: section.id, className: "pire-cp-section", children: [
3456
- section.label ? /* @__PURE__ */ jsx59(Header2, { className: "pire-cp-section-title", children: section.label }) : null,
3457
- section.items.map((item) => /* @__PURE__ */ jsx59(
3562
+ renderEmptyState: () => /* @__PURE__ */ jsx60("div", { className: "pire-cp-status", children: status }),
3563
+ children: sections.map((section) => /* @__PURE__ */ jsxs51(AriaMenuSection2, { id: section.id, className: "pire-cp-section", children: [
3564
+ section.label ? /* @__PURE__ */ jsx60(Header2, { className: "pire-cp-section-title", children: section.label }) : null,
3565
+ section.items.map((item) => /* @__PURE__ */ jsx60(
3458
3566
  MenuItem,
3459
3567
  {
3460
3568
  id: item.id,
@@ -3475,18 +3583,18 @@ function CommandPalette({
3475
3583
  // aria-hidden: the glyphs are a sighted affordance for discovering the keys. A screen
3476
3584
  // reader already announces the listbox semantics that make those keys work, so reading
3477
3585
  // "up arrow down arrow navigate" out loud is noise on every open.
3478
- /* @__PURE__ */ jsx59("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ jsxs50(Fragment5, { children: [
3479
- /* @__PURE__ */ jsxs50("span", { className: "pire-cp-hint", children: [
3480
- /* @__PURE__ */ jsx59(Kbd, { children: "\u2191" }),
3481
- /* @__PURE__ */ jsx59(Kbd, { children: "\u2193" }),
3586
+ /* @__PURE__ */ jsx60("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ jsxs51(Fragment5, { children: [
3587
+ /* @__PURE__ */ jsxs51("span", { className: "pire-cp-hint", children: [
3588
+ /* @__PURE__ */ jsx60(Kbd, { children: "\u2191" }),
3589
+ /* @__PURE__ */ jsx60(Kbd, { children: "\u2193" }),
3482
3590
  msg.commandPaletteHintNavigate
3483
3591
  ] }),
3484
- /* @__PURE__ */ jsxs50("span", { className: "pire-cp-hint", children: [
3485
- /* @__PURE__ */ jsx59(Kbd, { children: "\u21B5" }),
3592
+ /* @__PURE__ */ jsxs51("span", { className: "pire-cp-hint", children: [
3593
+ /* @__PURE__ */ jsx60(Kbd, { children: "\u21B5" }),
3486
3594
  msg.commandPaletteHintSelect
3487
3595
  ] }),
3488
- /* @__PURE__ */ jsxs50("span", { className: "pire-cp-hint", children: [
3489
- /* @__PURE__ */ jsx59(Kbd, { children: "esc" }),
3596
+ /* @__PURE__ */ jsxs51("span", { className: "pire-cp-hint", children: [
3597
+ /* @__PURE__ */ jsx60(Kbd, { children: "esc" }),
3490
3598
  msg.commandPaletteHintClose
3491
3599
  ] })
3492
3600
  ] }) })
@@ -3496,9 +3604,9 @@ function CommandPalette({
3496
3604
  );
3497
3605
  }
3498
3606
  function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3499
- const handler = React16.useRef(onTrigger);
3607
+ const handler = React18.useRef(onTrigger);
3500
3608
  handler.current = onTrigger;
3501
- React16.useEffect(() => {
3609
+ React18.useEffect(() => {
3502
3610
  if (isDisabled) return;
3503
3611
  const onKeyDown = (event) => {
3504
3612
  if (!(event.metaKey || event.ctrlKey) || event.altKey) return;
@@ -3513,10 +3621,10 @@ function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3513
3621
 
3514
3622
  // src/components/patterns/SidePanel.tsx
3515
3623
  import { ModalOverlay as ModalOverlay3, Modal as Modal3, Dialog as AriaDialog5, Heading as Heading5 } from "react-aria-components";
3516
- import { jsx as jsx60, jsxs as jsxs51 } from "react/jsx-runtime";
3624
+ import { jsx as jsx61, jsxs as jsxs52 } from "react/jsx-runtime";
3517
3625
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
3518
3626
  const msg = usePireMessages();
3519
- return /* @__PURE__ */ jsx60(
3627
+ return /* @__PURE__ */ jsx61(
3520
3628
  ModalOverlay3,
3521
3629
  {
3522
3630
  className: "pire-sidepanel-overlay",
@@ -3525,36 +3633,36 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
3525
3633
  onOpenChange: (o) => {
3526
3634
  if (!o) onClose?.();
3527
3635
  },
3528
- children: /* @__PURE__ */ jsx60(Modal3, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs51(AriaDialog5, { className: "pire-dialog", style: { height: "100%" }, children: [
3529
- /* @__PURE__ */ jsxs51("header", { className: "pire-dialog-head", children: [
3530
- /* @__PURE__ */ jsxs51("div", { style: { flex: 1, minWidth: 0 }, children: [
3531
- /* @__PURE__ */ jsx60(Heading5, { slot: "title", className: "pire-dialog-title", children: title }),
3532
- subtitle ? /* @__PURE__ */ jsx60("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
3636
+ children: /* @__PURE__ */ jsx61(Modal3, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs52(AriaDialog5, { className: "pire-dialog", style: { height: "100%" }, children: [
3637
+ /* @__PURE__ */ jsxs52("header", { className: "pire-dialog-head", children: [
3638
+ /* @__PURE__ */ jsxs52("div", { style: { flex: 1, minWidth: 0 }, children: [
3639
+ /* @__PURE__ */ jsx61(Heading5, { slot: "title", className: "pire-dialog-title", children: title }),
3640
+ subtitle ? /* @__PURE__ */ jsx61("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
3533
3641
  ] }),
3534
- /* @__PURE__ */ jsx60(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
3642
+ /* @__PURE__ */ jsx61(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
3535
3643
  ] }),
3536
- /* @__PURE__ */ jsx60("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
3537
- footer ? /* @__PURE__ */ jsx60("footer", { className: "pire-dialog-foot", children: footer }) : null
3644
+ /* @__PURE__ */ jsx61("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
3645
+ footer ? /* @__PURE__ */ jsx61("footer", { className: "pire-dialog-foot", children: footer }) : null
3538
3646
  ] }) })
3539
3647
  }
3540
3648
  );
3541
3649
  }
3542
3650
 
3543
3651
  // src/components/patterns/EmptyState.tsx
3544
- import { jsx as jsx61, jsxs as jsxs52 } from "react/jsx-runtime";
3652
+ import { jsx as jsx62, jsxs as jsxs53 } from "react/jsx-runtime";
3545
3653
  function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
3546
- return /* @__PURE__ */ jsxs52("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
3547
- /* @__PURE__ */ jsx61(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
3548
- title ? /* @__PURE__ */ jsx61("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
3549
- children ? /* @__PURE__ */ jsx61("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
3654
+ return /* @__PURE__ */ jsxs53("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
3655
+ /* @__PURE__ */ jsx62(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
3656
+ title ? /* @__PURE__ */ jsx62("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
3657
+ children ? /* @__PURE__ */ jsx62("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
3550
3658
  action
3551
3659
  ] });
3552
3660
  }
3553
3661
 
3554
3662
  // src/components/patterns/FileDropZone.tsx
3555
- import * as React17 from "react";
3663
+ import * as React19 from "react";
3556
3664
  import { DropZone, FileTrigger as FileTrigger2, isFileDropItem } from "react-aria-components";
3557
- import { jsx as jsx62, jsxs as jsxs53 } from "react/jsx-runtime";
3665
+ import { jsx as jsx63, jsxs as jsxs54 } from "react/jsx-runtime";
3558
3666
  var isImage2 = (file) => file.type.startsWith("image/");
3559
3667
  function FileDropZone({
3560
3668
  label,
@@ -3580,10 +3688,10 @@ function FileDropZone({
3580
3688
  style
3581
3689
  }) {
3582
3690
  const msg = usePireMessages();
3583
- const [uncontrolled, setUncontrolled] = React17.useState(defaultValue ?? []);
3691
+ const [uncontrolled, setUncontrolled] = React19.useState(defaultValue ?? []);
3584
3692
  const files = value ?? uncontrolled;
3585
- const created = React17.useRef([]);
3586
- React17.useEffect(() => () => {
3693
+ const created = React19.useRef([]);
3694
+ React19.useEffect(() => () => {
3587
3695
  for (const url of created.current) URL.revokeObjectURL(url);
3588
3696
  }, []);
3589
3697
  const commit = (next) => {
@@ -3603,12 +3711,12 @@ function FileDropZone({
3603
3711
  commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
3604
3712
  };
3605
3713
  const remove = (target) => commit(files.filter((f) => f.file !== target));
3606
- return /* @__PURE__ */ jsxs53("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), children: [
3607
- label ? /* @__PURE__ */ jsxs53("span", { className: "pire-field-label", children: [
3714
+ return /* @__PURE__ */ jsxs54("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), children: [
3715
+ label ? /* @__PURE__ */ jsxs54("span", { className: "pire-field-label", children: [
3608
3716
  label,
3609
- isRequired ? /* @__PURE__ */ jsx62("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
3717
+ isRequired ? /* @__PURE__ */ jsx63("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
3610
3718
  ] }) : null,
3611
- /* @__PURE__ */ jsxs53(
3719
+ /* @__PURE__ */ jsxs54(
3612
3720
  DropZone,
3613
3721
  {
3614
3722
  className: "pire-dropzone",
@@ -3621,25 +3729,25 @@ function FileDropZone({
3621
3729
  accept(dropped);
3622
3730
  },
3623
3731
  children: [
3624
- /* @__PURE__ */ jsx62(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
3625
- /* @__PURE__ */ jsx62("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
3626
- /* @__PURE__ */ jsx62(
3732
+ /* @__PURE__ */ jsx63(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
3733
+ /* @__PURE__ */ jsx63("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
3734
+ /* @__PURE__ */ jsx63(
3627
3735
  FileTrigger2,
3628
3736
  {
3629
3737
  acceptedFileTypes,
3630
3738
  allowsMultiple,
3631
3739
  onSelect: (list) => accept(list ? [...list] : []),
3632
- children: /* @__PURE__ */ jsx62(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
3740
+ children: /* @__PURE__ */ jsx63(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
3633
3741
  }
3634
3742
  )
3635
3743
  ]
3636
3744
  }
3637
3745
  ),
3638
- files.length ? /* @__PURE__ */ jsx62("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs53("li", { className: "pire-fileupload-item", children: [
3639
- previewUrl ? /* @__PURE__ */ jsx62("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx62(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
3640
- /* @__PURE__ */ jsx62("span", { className: "pire-fileupload-name", children: file.name }),
3641
- /* @__PURE__ */ jsx62("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
3642
- isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx62(
3746
+ files.length ? /* @__PURE__ */ jsx63("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs54("li", { className: "pire-fileupload-item", children: [
3747
+ previewUrl ? /* @__PURE__ */ jsx63("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx63(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
3748
+ /* @__PURE__ */ jsx63("span", { className: "pire-fileupload-name", children: file.name }),
3749
+ /* @__PURE__ */ jsx63("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
3750
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx63(
3643
3751
  IconButton,
3644
3752
  {
3645
3753
  icon: "x",
@@ -3649,14 +3757,15 @@ function FileDropZone({
3649
3757
  }
3650
3758
  )
3651
3759
  ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
3652
- uploadProgress != null ? /* @__PURE__ */ jsx62(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
3653
- description ? /* @__PURE__ */ jsx62("span", { className: "pire-field-hint", children: description }) : null,
3654
- isInvalid && errorMessage ? /* @__PURE__ */ jsx62("span", { className: "pire-field-error", children: errorMessage }) : null
3760
+ uploadProgress != null ? /* @__PURE__ */ jsx63(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
3761
+ description ? /* @__PURE__ */ jsx63("span", { className: "pire-field-hint", children: description }) : null,
3762
+ isInvalid && errorMessage ? /* @__PURE__ */ jsx63("span", { className: "pire-field-error", children: errorMessage }) : null
3655
3763
  ] });
3656
3764
  }
3657
3765
 
3658
3766
  // src/index.ts
3659
3767
  import { DialogTrigger, MenuTrigger as MenuTrigger3, SubmenuTrigger, Popover as Popover8, RouterProvider, I18nProvider } from "react-aria-components";
3768
+ import { Focusable as Focusable2 } from "react-aria-components";
3660
3769
  export {
3661
3770
  Avatar,
3662
3771
  Badge,
@@ -3673,12 +3782,17 @@ export {
3673
3782
  DateRangePicker,
3674
3783
  DescriptionList,
3675
3784
  Dialog,
3785
+ DialogActions,
3786
+ DialogBody,
3787
+ DialogDescription,
3788
+ DialogTitle,
3676
3789
  DialogTrigger,
3677
3790
  DonutChart,
3678
3791
  EmptyState,
3679
3792
  FileDropZone,
3680
3793
  FileUpload,
3681
3794
  FilterBar,
3795
+ Focusable2 as Focusable,
3682
3796
  FooterBar,
3683
3797
  FormField,
3684
3798
  Heading,
@@ -3720,6 +3834,7 @@ export {
3720
3834
  SidePanel,
3721
3835
  Skeleton,
3722
3836
  SkeletonTableRow,
3837
+ SplitPane,
3723
3838
  Strong,
3724
3839
  SubmenuTrigger,
3725
3840
  Switch,