@orianatech/pire 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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",
@@ -781,6 +784,7 @@ var esMessages = {
781
784
  dataTableSelectAll: "Seleccionar todas las filas",
782
785
  dataTableSelectRow: "Seleccionar fila",
783
786
  dataTableLoading: "Cargando registros",
787
+ dataTableSummaryRow: "Resumen",
784
788
  dialogClose: "Cerrar",
785
789
  sidePanelClose: "Cerrar panel",
786
790
  inlineMessageDismiss: "Descartar mensaje",
@@ -832,19 +836,19 @@ var esMessages = {
832
836
 
833
837
  // src/i18n/PireIntlProvider.tsx
834
838
  import { jsx as jsx16 } from "react/jsx-runtime";
835
- var MessagesContext = React5.createContext(enMessages);
839
+ var MessagesContext = React6.createContext(enMessages);
836
840
  function PireIntlProvider({ messages, children }) {
837
- const value = React5.useMemo(
841
+ const value = React6.useMemo(
838
842
  () => messages ? { ...enMessages, ...messages } : enMessages,
839
843
  [messages]
840
844
  );
841
845
  return /* @__PURE__ */ jsx16(MessagesContext.Provider, { value, children });
842
846
  }
843
847
  function usePireMessages() {
844
- return React5.useContext(MessagesContext);
848
+ return React6.useContext(MessagesContext);
845
849
  }
846
850
  function useMessage(key, override) {
847
- const messages = React5.useContext(MessagesContext);
851
+ const messages = React6.useContext(MessagesContext);
848
852
  return override ?? messages[key];
849
853
  }
850
854
 
@@ -869,7 +873,7 @@ function Input({
869
873
  }) {
870
874
  const msg = usePireMessages();
871
875
  const isControlled = rest.value !== void 0;
872
- const [ownValue, setOwnValue] = React6.useState(rest.defaultValue ?? "");
876
+ const [ownValue, setOwnValue] = React7.useState(rest.defaultValue ?? "");
873
877
  const currentValue = isControlled ? rest.value : ownValue;
874
878
  const handleChange = (next) => {
875
879
  setOwnValue(next);
@@ -916,10 +920,10 @@ function Input({
916
920
  }
917
921
 
918
922
  // src/components/forms/TextArea.tsx
919
- import * as React7 from "react";
923
+ import * as React8 from "react";
920
924
  import { TextField as TextField2, Label as Label2, TextArea as AriaTextArea, Group as Group2, Text as Text3, FieldError as FieldError2 } from "react-aria-components";
921
925
  import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
922
- var useIsomorphicLayoutEffect = typeof document === "undefined" ? React7.useEffect : React7.useLayoutEffect;
926
+ var useIsomorphicLayoutEffect = typeof document === "undefined" ? React8.useEffect : React8.useLayoutEffect;
923
927
  function TextArea({
924
928
  label,
925
929
  description,
@@ -935,13 +939,13 @@ function TextArea({
935
939
  onChange,
936
940
  ...rest
937
941
  }) {
938
- const innerRef = React7.useRef(null);
939
- const ref = React7.useCallback((node) => {
942
+ const innerRef = React8.useRef(null);
943
+ const ref = React8.useCallback((node) => {
940
944
  innerRef.current = node;
941
945
  if (typeof textAreaRef === "function") textAreaRef(node);
942
946
  else if (textAreaRef) textAreaRef.current = node;
943
947
  }, [textAreaRef]);
944
- const grow = React7.useCallback(() => {
948
+ const grow = React8.useCallback(() => {
945
949
  const el = innerRef.current;
946
950
  if (!el || !autoGrow) return;
947
951
  const styles = getComputedStyle(el);
@@ -1228,7 +1232,7 @@ function ComboBox({
1228
1232
  }
1229
1233
 
1230
1234
  // src/components/forms/MultiComboBox.tsx
1231
- import * as React8 from "react";
1235
+ import * as React9 from "react";
1232
1236
  import {
1233
1237
  ComboBox as AriaComboBox2,
1234
1238
  Label as Label6,
@@ -1267,15 +1271,15 @@ function MultiComboBox({
1267
1271
  ...rest
1268
1272
  }) {
1269
1273
  const msg = usePireMessages();
1270
- const items = React8.useMemo(() => options.map(norm3), [options]);
1274
+ const items = React9.useMemo(() => options.map(norm3), [options]);
1271
1275
  const collection = isFilteredExternally ? { items } : { defaultItems: items };
1272
1276
  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);
1277
+ const [uncontrolled, setUncontrolled] = React9.useState(defaultValue ?? []);
1278
+ const [announcement, setAnnouncement] = React9.useState("");
1279
+ const inputRef = React9.useRef(null);
1276
1280
  const raw = value ?? uncontrolled;
1277
1281
  const contentKey = raw.join("\0");
1278
- const values = React8.useMemo(() => raw, [contentKey]);
1282
+ const values = React9.useMemo(() => raw, [contentKey]);
1279
1283
  const labelOf = (v) => items.find((o) => o.value === v)?.label ?? v;
1280
1284
  const isEditable = !rest.isDisabled && !rest.isReadOnly;
1281
1285
  const commit = (next) => {
@@ -1635,14 +1639,27 @@ function DateRangePicker({
1635
1639
  }
1636
1640
 
1637
1641
  // src/components/forms/ValueHelpField.tsx
1638
- import * as React10 from "react";
1642
+ import * as React12 from "react";
1639
1643
 
1640
1644
  // src/components/patterns/ValueHelpDialog.tsx
1641
- import * as React9 from "react";
1645
+ import * as React11 from "react";
1642
1646
 
1643
1647
  // src/components/feedback/Dialog.tsx
1648
+ import * as React10 from "react";
1644
1649
  import { ModalOverlay, Modal, Dialog as AriaDialog3, Heading as Heading4 } from "react-aria-components";
1645
1650
  import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
1651
+ function DialogTitle({ children, className }) {
1652
+ return /* @__PURE__ */ jsx28(Heading4, { slot: "title", className: cx("pire-dialog-title", className), children });
1653
+ }
1654
+ function DialogDescription({ children, className }) {
1655
+ return /* @__PURE__ */ jsx28("p", { className: cx("pire-dialog-sub", className), style: { margin: 0 }, children });
1656
+ }
1657
+ function DialogBody({ children, className }) {
1658
+ return /* @__PURE__ */ jsx28("div", { className: cx("pire-dialog-body", className), children });
1659
+ }
1660
+ function DialogActions({ children, className }) {
1661
+ return /* @__PURE__ */ jsx28("footer", { className: cx("pire-dialog-foot", className), children });
1662
+ }
1646
1663
  function Dialog({
1647
1664
  isOpen,
1648
1665
  onOpenChange,
@@ -1662,6 +1679,18 @@ function Dialog({
1662
1679
  onClose?.();
1663
1680
  onOpenChange?.(false);
1664
1681
  };
1682
+ const parts = React10.Children.toArray(children);
1683
+ const slotOf = (type) => parts.find((node) => React10.isValidElement(node) && node.type === type);
1684
+ const titleSlot = slotOf(DialogTitle);
1685
+ const descriptionSlot = slotOf(DialogDescription);
1686
+ const bodySlot = slotOf(DialogBody);
1687
+ const actionsSlot = slotOf(DialogActions);
1688
+ const slots = [titleSlot, descriptionSlot, bodySlot, actionsSlot];
1689
+ const loose = parts.filter((node) => !slots.includes(node));
1690
+ const heading = titleSlot ?? (title ? /* @__PURE__ */ jsx28(Heading4, { slot: "title", className: "pire-dialog-title", children: title }) : null);
1691
+ const description = descriptionSlot ?? (subtitle ? /* @__PURE__ */ jsx28("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null);
1692
+ const actions = actionsSlot ?? (footer ? /* @__PURE__ */ jsx28("footer", { className: "pire-dialog-foot", children: footer }) : null);
1693
+ const body = bodySlot ?? (loose.length ? /* @__PURE__ */ jsx28("div", { className: "pire-dialog-body", children: loose }) : null);
1665
1694
  return /* @__PURE__ */ jsx28(
1666
1695
  ModalOverlay,
1667
1696
  {
@@ -1672,15 +1701,15 @@ function Dialog({
1672
1701
  if (!o) close();
1673
1702
  },
1674
1703
  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: [
1704
+ heading || description ? /* @__PURE__ */ jsxs21("header", { className: "pire-dialog-head", children: [
1676
1705
  /* @__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
1706
+ heading,
1707
+ description
1679
1708
  ] }),
1680
1709
  showClose ? /* @__PURE__ */ jsx28(IconButton, { icon: "x", label: msg.dialogClose, size: "sm", onPress: close }) : null
1681
1710
  ] }) : null,
1682
- children ? /* @__PURE__ */ jsx28("div", { className: "pire-dialog-body", children }) : null,
1683
- footer ? /* @__PURE__ */ jsx28("footer", { className: "pire-dialog-foot", children: footer }) : null
1711
+ body,
1712
+ actions
1684
1713
  ] }) })
1685
1714
  }
1686
1715
  );
@@ -1691,6 +1720,7 @@ import {
1691
1720
  Table,
1692
1721
  TableHeader,
1693
1722
  TableBody,
1723
+ TableFooter,
1694
1724
  Column,
1695
1725
  Row,
1696
1726
  Cell
@@ -1758,6 +1788,10 @@ function DataTable({
1758
1788
  isLoading,
1759
1789
  loadingRowCount,
1760
1790
  loadingLabel,
1791
+ footer,
1792
+ rowProps,
1793
+ renderExpanded,
1794
+ expandedIds,
1761
1795
  className,
1762
1796
  style,
1763
1797
  ...rest
@@ -1774,6 +1808,11 @@ function DataTable({
1774
1808
  ...columns.map((c) => ({ width: c.width, align: c.align, numeric: c.numeric }))
1775
1809
  ];
1776
1810
  const body = isLoading ? [] : rows;
1811
+ const presentation = new Map(rows.map((row) => [row.id, rowProps?.(row) ?? {}]));
1812
+ const disabledKeys = rows.filter((row) => presentation.get(row.id)?.isDisabled).map((row) => row.id);
1813
+ const expanded = new Set((expandedIds ?? []).map(String));
1814
+ const spanAll = columns.length + (selectable ? 1 : 0);
1815
+ const expandedKey = (id) => `${id}::__pire_expanded__`;
1777
1816
  return /* @__PURE__ */ jsx30(
1778
1817
  "div",
1779
1818
  {
@@ -1788,6 +1827,7 @@ function DataTable({
1788
1827
  "data-density": density,
1789
1828
  "data-sticky": String(stickyHeader),
1790
1829
  "aria-label": rest["aria-label"],
1830
+ disabledKeys: disabledKeys.length ? new Set(disabledKeys) : void 0,
1791
1831
  selectionMode: selectable ? "multiple" : "none",
1792
1832
  selectedKeys: selected ? new Set(selected) : void 0,
1793
1833
  onSelectionChange: handleSelection,
@@ -1810,7 +1850,7 @@ function DataTable({
1810
1850
  width: c.width,
1811
1851
  "data-align": c.numeric || c.align === "right" ? "right" : c.align,
1812
1852
  "data-allows-sorting": c.sortable ? "true" : void 0,
1813
- children: /* @__PURE__ */ jsxs22("span", { className: "pire-th-inner", children: [
1853
+ children: /* @__PURE__ */ jsxs22("span", { className: cx("pire-th-inner", c.hideLabel && "pire-sr-only"), children: [
1814
1854
  c.label,
1815
1855
  c.sortable ? /* @__PURE__ */ jsx30(
1816
1856
  Icon,
@@ -1831,19 +1871,46 @@ function DataTable({
1831
1871
  // biome-ignore lint/suspicious/noArrayIndexKey: placeholder rows are positional.
1832
1872
  /* @__PURE__ */ jsx30(SkeletonTableRow, { columns: skeletonColumns, density }, i)
1833
1873
  ))
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(
1874
+ ] }) : /* @__PURE__ */ jsx30("div", { className: "pire-table-empty", children: emptyLabel }), children: body.flatMap((row) => {
1875
+ const rowIsDisabled = presentation.get(row.id)?.isDisabled;
1876
+ const record = /* @__PURE__ */ jsxs22(
1877
+ Row,
1878
+ {
1879
+ id: row.id,
1880
+ className: cx("pire-tr", presentation.get(row.id)?.className),
1881
+ "data-pressable": onRowAction && !rowIsDisabled ? "true" : void 0,
1882
+ children: [
1883
+ selectable ? /* @__PURE__ */ jsx30(Cell, { className: "pire-td", children: /* @__PURE__ */ jsx30(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectRow }) }) : null,
1884
+ columns.map((c) => /* @__PURE__ */ jsx30(
1885
+ Cell,
1886
+ {
1887
+ className: "pire-td",
1888
+ "data-numeric": c.numeric ? "true" : void 0,
1889
+ style: { textAlign: c.align && !c.numeric ? c.align : void 0 },
1890
+ children: c.render ? c.render(row) : row[c.key]
1891
+ },
1892
+ c.key
1893
+ ))
1894
+ ]
1895
+ },
1896
+ row.id
1897
+ );
1898
+ if (!renderExpanded || !expanded.has(String(row.id))) return [record];
1899
+ 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))];
1900
+ }) }),
1901
+ footer && !isLoading ? /* @__PURE__ */ jsx30(TableFooter, { className: "pire-tfoot", children: /* @__PURE__ */ jsxs22(Row, { id: "__pire_footer__", className: "pire-tr-footer", children: [
1902
+ selectable ? /* @__PURE__ */ jsx30(Cell, { className: "pire-tf" }) : null,
1903
+ columns.map((c, i) => /* @__PURE__ */ jsx30(
1837
1904
  Cell,
1838
1905
  {
1839
- className: "pire-td",
1906
+ className: "pire-tf",
1840
1907
  "data-numeric": c.numeric ? "true" : void 0,
1841
1908
  style: { textAlign: c.align && !c.numeric ? c.align : void 0 },
1842
- children: c.render ? c.render(row) : row[c.key]
1909
+ children: footer[c.key] ?? (i === 0 && !selectable ? /* @__PURE__ */ jsx30("span", { className: "pire-sr-only", children: msg.dataTableSummaryRow }) : null)
1843
1910
  },
1844
1911
  c.key
1845
1912
  ))
1846
- ] }, row.id)) })
1913
+ ] }) }) : null
1847
1914
  ]
1848
1915
  }
1849
1916
  )
@@ -1868,11 +1935,11 @@ function ValueHelpDialog({
1868
1935
  onClose
1869
1936
  }) {
1870
1937
  const msg = usePireMessages();
1871
- const [query, setQuery] = React9.useState("");
1872
- React9.useEffect(() => {
1938
+ const [query, setQuery] = React11.useState("");
1939
+ React11.useEffect(() => {
1873
1940
  if (isOpen) setQuery("");
1874
1941
  }, [isOpen]);
1875
- const filtered = React9.useMemo(() => {
1942
+ const filtered = React11.useMemo(() => {
1876
1943
  if (isFilteredExternally) return rows;
1877
1944
  const q = query.trim().toLowerCase();
1878
1945
  if (!q) return rows;
@@ -1954,7 +2021,7 @@ function ValueHelpField({
1954
2021
  style
1955
2022
  }) {
1956
2023
  const msg = usePireMessages();
1957
- const [open, setOpen] = React10.useState(false);
2024
+ const [open, setOpen] = React12.useState(false);
1958
2025
  return /* @__PURE__ */ jsxs24("div", { className: cx(className), style, children: [
1959
2026
  /* @__PURE__ */ jsx32(
1960
2027
  Input,
@@ -2010,7 +2077,7 @@ function ValueHelpField({
2010
2077
  }
2011
2078
 
2012
2079
  // src/components/forms/FileUpload.tsx
2013
- import * as React11 from "react";
2080
+ import * as React13 from "react";
2014
2081
  import { FileTrigger, Text as Text11 } from "react-aria-components";
2015
2082
 
2016
2083
  // src/components/feedback/ProgressBar.tsx
@@ -2100,10 +2167,10 @@ function FileUpload({
2100
2167
  style
2101
2168
  }) {
2102
2169
  const msg = usePireMessages();
2103
- const [uncontrolled, setUncontrolled] = React11.useState(defaultValue ?? []);
2170
+ const [uncontrolled, setUncontrolled] = React13.useState(defaultValue ?? []);
2104
2171
  const files = value ?? uncontrolled;
2105
- const created = React11.useRef([]);
2106
- React11.useEffect(() => () => {
2172
+ const created = React13.useRef([]);
2173
+ React13.useEffect(() => () => {
2107
2174
  for (const url of created.current) URL.revokeObjectURL(url);
2108
2175
  }, []);
2109
2176
  const commit = (next) => {
@@ -2214,7 +2281,7 @@ function ShellBar({
2214
2281
  }
2215
2282
 
2216
2283
  // src/components/navigation/SideNav.tsx
2217
- import * as React12 from "react";
2284
+ import * as React14 from "react";
2218
2285
  import {
2219
2286
  Button as AriaButton12,
2220
2287
  Disclosure,
@@ -2314,10 +2381,10 @@ function SideNav({
2314
2381
  const msg = usePireMessages();
2315
2382
  const activeParent = findActiveParent(groups, value);
2316
2383
  const isControlled = expandedIds != null;
2317
- const [ownExpanded, setOwnExpanded] = React12.useState(
2384
+ const [ownExpanded, setOwnExpanded] = React14.useState(
2318
2385
  () => new Set(defaultExpandedIds ?? (activeParent ? [activeParent] : []))
2319
2386
  );
2320
- const [lastValue, setLastValue] = React12.useState(value);
2387
+ const [lastValue, setLastValue] = React14.useState(value);
2321
2388
  if (value !== lastValue) {
2322
2389
  setLastValue(value);
2323
2390
  if (!isControlled && activeParent && !ownExpanded.has(activeParent)) {
@@ -2581,7 +2648,7 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
2581
2648
  }
2582
2649
 
2583
2650
  // src/components/feedback/Toast.tsx
2584
- import * as React13 from "react";
2651
+ import * as React15 from "react";
2585
2652
  import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
2586
2653
  var KIND_ICON2 = {
2587
2654
  info: "info",
@@ -2607,26 +2674,26 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
2607
2674
  }
2608
2675
  );
2609
2676
  }
2610
- var ToastContext = React13.createContext(null);
2677
+ var ToastContext = React15.createContext(null);
2611
2678
  function ToastProvider({ children, timeout = 6e3 }) {
2612
2679
  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) => {
2680
+ const [toasts, setToasts] = React15.useState([]);
2681
+ const close = React15.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2682
+ const add = React15.useCallback((toast) => {
2616
2683
  const id = Math.random().toString(36).slice(2);
2617
2684
  setToasts((t) => [...t, { ...toast, id }]);
2618
2685
  const ms = toast.timeout ?? timeout;
2619
2686
  if (ms > 0) setTimeout(() => close(id), ms);
2620
2687
  return id;
2621
2688
  }, [close, timeout]);
2622
- const value = React13.useMemo(() => ({ add, close }), [add, close]);
2689
+ const value = React15.useMemo(() => ({ add, close }), [add, close]);
2623
2690
  return /* @__PURE__ */ jsxs34(ToastContext.Provider, { value, children: [
2624
2691
  children,
2625
2692
  /* @__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
2693
  ] });
2627
2694
  }
2628
2695
  function useToast() {
2629
- const ctx = React13.useContext(ToastContext);
2696
+ const ctx = React15.useContext(ToastContext);
2630
2697
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
2631
2698
  return ctx;
2632
2699
  }
@@ -2976,14 +3043,14 @@ function BarChart({
2976
3043
  }
2977
3044
 
2978
3045
  // src/components/data/LineChart.tsx
2979
- import * as React14 from "react";
3046
+ import * as React16 from "react";
2980
3047
  import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
2981
3048
  var PLOT_INSET = { top: 10, right: 14, bottom: 24, left: 58 };
2982
3049
  var MARKER_LIMIT = 20;
2983
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React14.useEffect : React14.useLayoutEffect;
3050
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React16.useEffect : React16.useLayoutEffect;
2984
3051
  function useMeasuredWidth() {
2985
- const ref = React14.useRef(null);
2986
- const [width, setWidth] = React14.useState(0);
3052
+ const ref = React16.useRef(null);
3053
+ const [width, setWidth] = React16.useState(0);
2987
3054
  useIsomorphicLayoutEffect2(() => {
2988
3055
  const element = ref.current;
2989
3056
  if (!element) return;
@@ -3146,7 +3213,7 @@ function LineChart({
3146
3213
  }
3147
3214
 
3148
3215
  // src/components/data/DonutChart.tsx
3149
- import * as React15 from "react";
3216
+ import * as React17 from "react";
3150
3217
  import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
3151
3218
  var SEGMENT_GAP_DEGREES = 1.5;
3152
3219
  function DonutChart({
@@ -3167,7 +3234,7 @@ function DonutChart({
3167
3234
  }) {
3168
3235
  const label = rest["aria-label"];
3169
3236
  const msg = usePireMessages();
3170
- const [hoveredIndex, setHoveredIndex] = React15.useState(null);
3237
+ const [hoveredIndex, setHoveredIndex] = React17.useState(null);
3171
3238
  warnOnDonutShape(series, categories.length, label);
3172
3239
  const values = (series[0]?.values ?? []).slice(0, categories.length);
3173
3240
  const segments = categories.map((category, index) => ({ category, index, value: values[index] ?? 0 })).filter((segment) => segment.value > 0);
@@ -3369,7 +3436,7 @@ function ConfirmDialog({
3369
3436
  }
3370
3437
 
3371
3438
  // src/components/patterns/CommandPalette.tsx
3372
- import * as React16 from "react";
3439
+ import * as React18 from "react";
3373
3440
  import {
3374
3441
  Autocomplete,
3375
3442
  ModalOverlay as ModalOverlay2,
@@ -3403,17 +3470,17 @@ function CommandPalette({
3403
3470
  style
3404
3471
  }) {
3405
3472
  const msg = usePireMessages();
3406
- const [query, setQuery] = React16.useState("");
3473
+ const [query, setQuery] = React18.useState("");
3407
3474
  const { contains } = useFilter({ sensitivity: "base" });
3408
- React16.useEffect(() => {
3475
+ React18.useEffect(() => {
3409
3476
  if (isOpen) setQuery("");
3410
3477
  }, [isOpen]);
3411
- const searchableById = React16.useMemo(() => {
3478
+ const searchableById = React18.useMemo(() => {
3412
3479
  const byId = /* @__PURE__ */ new Map();
3413
3480
  for (const group of groups) for (const item of group.items) byId.set(item.id, searchableText(item));
3414
3481
  return byId;
3415
3482
  }, [groups]);
3416
- const filter = React16.useCallback((textValue, inputValue, node) => {
3483
+ const filter = React18.useCallback((textValue, inputValue, node) => {
3417
3484
  if (node.parentKey === RESULTS_SECTION_KEY) return true;
3418
3485
  return contains(searchableById.get(String(node.key)) ?? textValue, inputValue);
3419
3486
  }, [contains, searchableById]);
@@ -3496,9 +3563,9 @@ function CommandPalette({
3496
3563
  );
3497
3564
  }
3498
3565
  function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3499
- const handler = React16.useRef(onTrigger);
3566
+ const handler = React18.useRef(onTrigger);
3500
3567
  handler.current = onTrigger;
3501
- React16.useEffect(() => {
3568
+ React18.useEffect(() => {
3502
3569
  if (isDisabled) return;
3503
3570
  const onKeyDown = (event) => {
3504
3571
  if (!(event.metaKey || event.ctrlKey) || event.altKey) return;
@@ -3552,7 +3619,7 @@ function EmptyState({ icon = "file-text", title, action, compact, children, clas
3552
3619
  }
3553
3620
 
3554
3621
  // src/components/patterns/FileDropZone.tsx
3555
- import * as React17 from "react";
3622
+ import * as React19 from "react";
3556
3623
  import { DropZone, FileTrigger as FileTrigger2, isFileDropItem } from "react-aria-components";
3557
3624
  import { jsx as jsx62, jsxs as jsxs53 } from "react/jsx-runtime";
3558
3625
  var isImage2 = (file) => file.type.startsWith("image/");
@@ -3580,10 +3647,10 @@ function FileDropZone({
3580
3647
  style
3581
3648
  }) {
3582
3649
  const msg = usePireMessages();
3583
- const [uncontrolled, setUncontrolled] = React17.useState(defaultValue ?? []);
3650
+ const [uncontrolled, setUncontrolled] = React19.useState(defaultValue ?? []);
3584
3651
  const files = value ?? uncontrolled;
3585
- const created = React17.useRef([]);
3586
- React17.useEffect(() => () => {
3652
+ const created = React19.useRef([]);
3653
+ React19.useEffect(() => () => {
3587
3654
  for (const url of created.current) URL.revokeObjectURL(url);
3588
3655
  }, []);
3589
3656
  const commit = (next) => {
@@ -3657,6 +3724,7 @@ function FileDropZone({
3657
3724
 
3658
3725
  // src/index.ts
3659
3726
  import { DialogTrigger, MenuTrigger as MenuTrigger3, SubmenuTrigger, Popover as Popover8, RouterProvider, I18nProvider } from "react-aria-components";
3727
+ import { Focusable as Focusable2 } from "react-aria-components";
3660
3728
  export {
3661
3729
  Avatar,
3662
3730
  Badge,
@@ -3673,12 +3741,17 @@ export {
3673
3741
  DateRangePicker,
3674
3742
  DescriptionList,
3675
3743
  Dialog,
3744
+ DialogActions,
3745
+ DialogBody,
3746
+ DialogDescription,
3747
+ DialogTitle,
3676
3748
  DialogTrigger,
3677
3749
  DonutChart,
3678
3750
  EmptyState,
3679
3751
  FileDropZone,
3680
3752
  FileUpload,
3681
3753
  FilterBar,
3754
+ Focusable2 as Focusable,
3682
3755
  FooterBar,
3683
3756
  FormField,
3684
3757
  Heading,