@orianatech/pire 0.8.0 → 0.9.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
@@ -830,7 +830,11 @@ var enMessages = {
830
830
  paginationPrevious: "Previous page",
831
831
  paginationNext: "Next page",
832
832
  paginationRowsPerPage: "Rows per page",
833
- sideNavLabel: "Main navigation"
833
+ sideNavLabel: "Main navigation",
834
+ fileUploadChoose: "Choose files",
835
+ fileUploadRemoveNamed: "Remove {name}",
836
+ fileUploadUploading: "Uploading",
837
+ fileDropZonePrompt: "Drag files here, or choose them"
834
838
  };
835
839
  var esMessages = {
836
840
  filterBarLabel: "Filtros",
@@ -862,7 +866,11 @@ var esMessages = {
862
866
  paginationPrevious: "P\xE1gina anterior",
863
867
  paginationNext: "P\xE1gina siguiente",
864
868
  paginationRowsPerPage: "Filas por p\xE1gina",
865
- sideNavLabel: "Navegaci\xF3n principal"
869
+ sideNavLabel: "Navegaci\xF3n principal",
870
+ fileUploadChoose: "Elegir archivos",
871
+ fileUploadRemoveNamed: "Quitar {name}",
872
+ fileUploadUploading: "Subiendo",
873
+ fileDropZonePrompt: "Arrastr\xE1 archivos ac\xE1, o elegilos"
866
874
  };
867
875
 
868
876
  // src/i18n/PireIntlProvider.tsx
@@ -1596,8 +1604,165 @@ function ValueHelpField({
1596
1604
  ] });
1597
1605
  }
1598
1606
 
1607
+ // src/components/forms/FileUpload.tsx
1608
+ import * as React10 from "react";
1609
+ import { FileTrigger, Text as Text10 } from "react-aria-components";
1610
+
1611
+ // src/components/feedback/ProgressBar.tsx
1612
+ import { ProgressBar as AriaProgressBar, Label as Label9 } from "react-aria-components";
1613
+ import { Fragment as Fragment2, jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
1614
+ function ProgressBar({
1615
+ value = 0,
1616
+ minValue = 0,
1617
+ maxValue = 100,
1618
+ label,
1619
+ showValue = true,
1620
+ isIndeterminate,
1621
+ status = "informative",
1622
+ size = "md",
1623
+ className,
1624
+ style
1625
+ }) {
1626
+ return /* @__PURE__ */ jsx31(
1627
+ AriaProgressBar,
1628
+ {
1629
+ className: cx("pire-progress", className),
1630
+ "data-status": status,
1631
+ "data-size": size,
1632
+ value,
1633
+ minValue,
1634
+ maxValue,
1635
+ isIndeterminate,
1636
+ style,
1637
+ children: ({ percentage, valueText }) => /* @__PURE__ */ jsxs24(Fragment2, { children: [
1638
+ label || showValue ? /* @__PURE__ */ jsxs24("div", { className: "pire-progress-head", children: [
1639
+ label ? /* @__PURE__ */ jsx31(Label9, { children: label }) : /* @__PURE__ */ jsx31("span", {}),
1640
+ showValue && !isIndeterminate ? /* @__PURE__ */ jsx31("span", { className: "pire-numeric", children: valueText }) : null
1641
+ ] }) : null,
1642
+ /* @__PURE__ */ jsx31("div", { className: "pire-progress-track", children: /* @__PURE__ */ jsx31("div", { className: "pire-progress-fill", style: { width: `${isIndeterminate ? 40 : percentage}%` } }) })
1643
+ ] })
1644
+ }
1645
+ );
1646
+ }
1647
+
1648
+ // src/components/forms/FileUpload.tsx
1649
+ import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
1650
+ var isImage = (file) => file.type.startsWith("image/");
1651
+ function formatFileSize(bytes) {
1652
+ if (bytes < 1024) return `${bytes} B`;
1653
+ if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024).toLocaleString()} KB`;
1654
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1655
+ }
1656
+ function screenFiles(files, { maxSize, acceptedFileTypes }) {
1657
+ const accepted = [];
1658
+ const rejected = [];
1659
+ for (const file of files) {
1660
+ if (maxSize != null && file.size > maxSize) {
1661
+ rejected.push({ file, reason: "size" });
1662
+ continue;
1663
+ }
1664
+ if (acceptedFileTypes?.length) {
1665
+ const ok = acceptedFileTypes.some((t) => t.startsWith(".") ? file.name.toLowerCase().endsWith(t.toLowerCase()) : t.endsWith("/*") ? file.type.startsWith(t.slice(0, -1)) : file.type === t);
1666
+ if (!ok) {
1667
+ rejected.push({ file, reason: "type" });
1668
+ continue;
1669
+ }
1670
+ }
1671
+ accepted.push(file);
1672
+ }
1673
+ return { accepted, rejected };
1674
+ }
1675
+ function FileUpload({
1676
+ label,
1677
+ value,
1678
+ defaultValue,
1679
+ onChange,
1680
+ acceptedFileTypes,
1681
+ allowsMultiple,
1682
+ maxSize,
1683
+ onError,
1684
+ showPreview = true,
1685
+ uploadProgress,
1686
+ chooseLabel,
1687
+ description,
1688
+ errorMessage,
1689
+ isInvalid,
1690
+ isDisabled,
1691
+ isReadOnly,
1692
+ isRequired,
1693
+ fullWidth = true,
1694
+ className,
1695
+ style
1696
+ }) {
1697
+ const msg = usePireMessages();
1698
+ const [uncontrolled, setUncontrolled] = React10.useState(defaultValue ?? []);
1699
+ const files = value ?? uncontrolled;
1700
+ const created = React10.useRef([]);
1701
+ React10.useEffect(() => () => {
1702
+ for (const url of created.current) URL.revokeObjectURL(url);
1703
+ }, []);
1704
+ const commit = (next) => {
1705
+ if (value === void 0) setUncontrolled(next);
1706
+ onChange?.(next);
1707
+ };
1708
+ const accept = (picked) => {
1709
+ if (!picked || isDisabled || isReadOnly) return;
1710
+ const { accepted, rejected } = screenFiles([...picked], { maxSize, acceptedFileTypes });
1711
+ if (rejected.length) onError?.(rejected);
1712
+ if (!accepted.length) return;
1713
+ const wrapped = accepted.map((file) => {
1714
+ const previewUrl = showPreview && isImage(file) ? URL.createObjectURL(file) : void 0;
1715
+ if (previewUrl) created.current.push(previewUrl);
1716
+ return { file, previewUrl };
1717
+ });
1718
+ commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
1719
+ };
1720
+ const remove = (target) => commit(files.filter((f) => f.file !== target));
1721
+ return /* @__PURE__ */ jsxs25(
1722
+ "div",
1723
+ {
1724
+ className: cx("pire-field", "pire-fileupload", className),
1725
+ style,
1726
+ "data-full-width": String(fullWidth),
1727
+ "data-invalid": isInvalid ? "true" : void 0,
1728
+ children: [
1729
+ label ? /* @__PURE__ */ jsxs25("span", { className: "pire-field-label", children: [
1730
+ label,
1731
+ isRequired ? /* @__PURE__ */ jsx32("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
1732
+ ] }) : null,
1733
+ /* @__PURE__ */ jsx32(
1734
+ FileTrigger,
1735
+ {
1736
+ acceptedFileTypes,
1737
+ allowsMultiple,
1738
+ onSelect: accept,
1739
+ children: /* @__PURE__ */ jsx32(Button, { icon: "paperclip", isDisabled: isDisabled || isReadOnly, children: chooseLabel ?? msg.fileUploadChoose })
1740
+ }
1741
+ ),
1742
+ files.length ? /* @__PURE__ */ jsx32("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs25("li", { className: "pire-fileupload-item", children: [
1743
+ previewUrl ? /* @__PURE__ */ jsx32("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx32(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
1744
+ /* @__PURE__ */ jsx32("span", { className: "pire-fileupload-name", children: file.name }),
1745
+ /* @__PURE__ */ jsx32("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
1746
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx32(
1747
+ IconButton,
1748
+ {
1749
+ icon: "x",
1750
+ size: "sm",
1751
+ label: msg.fileUploadRemoveNamed.replace("{name}", file.name),
1752
+ onPress: () => remove(file)
1753
+ }
1754
+ )
1755
+ ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
1756
+ uploadProgress != null ? /* @__PURE__ */ jsx32(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
1757
+ description ? /* @__PURE__ */ jsx32(Text10, { slot: "description", className: "pire-field-hint", children: description }) : null,
1758
+ isInvalid && errorMessage ? /* @__PURE__ */ jsx32("span", { className: "pire-field-error", children: errorMessage }) : null
1759
+ ]
1760
+ }
1761
+ );
1762
+ }
1763
+
1599
1764
  // src/components/navigation/ShellBar.tsx
1600
- import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
1765
+ import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
1601
1766
  var initials2 = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
1602
1767
  function ShellBar({
1603
1768
  product,
@@ -1612,22 +1777,88 @@ function ShellBar({
1612
1777
  className,
1613
1778
  ...rest
1614
1779
  }) {
1615
- return /* @__PURE__ */ jsxs24("header", { className: cx("pire-shellbar", className), ...rest, children: [
1616
- onMenu ? /* @__PURE__ */ jsx31(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
1617
- monogram ? /* @__PURE__ */ jsx31("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
1618
- product ? /* @__PURE__ */ jsx31("span", { className: "pire-shellbar-product", children: product }) : null,
1619
- title ? /* @__PURE__ */ jsx31("span", { className: "pire-shellbar-title", children: title }) : null,
1620
- /* @__PURE__ */ jsx31("span", { className: "pire-shellbar-spacer" }),
1621
- onSearch ? /* @__PURE__ */ jsx31(IconButton, { icon: "search", label: searchLabel, variant: "inverse", size: "sm", onPress: onSearch }) : null,
1780
+ return /* @__PURE__ */ jsxs26("header", { className: cx("pire-shellbar", className), ...rest, children: [
1781
+ onMenu ? /* @__PURE__ */ jsx33(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
1782
+ monogram ? /* @__PURE__ */ jsx33("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
1783
+ product ? /* @__PURE__ */ jsx33("span", { className: "pire-shellbar-product", children: product }) : null,
1784
+ title ? /* @__PURE__ */ jsx33("span", { className: "pire-shellbar-title", children: title }) : null,
1785
+ /* @__PURE__ */ jsx33("span", { className: "pire-shellbar-spacer" }),
1786
+ onSearch ? /* @__PURE__ */ jsx33(IconButton, { icon: "search", label: searchLabel, variant: "inverse", size: "sm", onPress: onSearch }) : null,
1622
1787
  actions,
1623
- user ? /* @__PURE__ */ jsx31("span", { className: "pire-avatar", title: user, "aria-label": user, role: "img", children: initials2(user) }) : null
1788
+ user ? /* @__PURE__ */ jsx33("span", { className: "pire-avatar", title: user, "aria-label": user, role: "img", children: initials2(user) }) : null
1624
1789
  ] });
1625
1790
  }
1626
1791
 
1627
1792
  // src/components/navigation/SideNav.tsx
1628
- import * as React10 from "react";
1629
- import { Button as AriaButton9, Disclosure, DisclosureGroup, DisclosurePanel } from "react-aria-components";
1630
- import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
1793
+ import * as React11 from "react";
1794
+ import {
1795
+ Button as AriaButton9,
1796
+ Disclosure,
1797
+ DisclosureGroup,
1798
+ DisclosurePanel,
1799
+ MenuTrigger,
1800
+ Popover as Popover5
1801
+ } from "react-aria-components";
1802
+
1803
+ // src/components/navigation/Menu.tsx
1804
+ import {
1805
+ Menu as AriaMenu,
1806
+ MenuItem as AriaMenuItem,
1807
+ MenuSection as AriaMenuSection,
1808
+ Separator as AriaSeparator2,
1809
+ Header
1810
+ } from "react-aria-components";
1811
+ import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
1812
+ function Menu({ minWidth, className, style, ...rest }) {
1813
+ const width = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
1814
+ const menuStyle = width == null ? style : { ["--pire-menu-min-w"]: width, ...style };
1815
+ return /* @__PURE__ */ jsx34(
1816
+ AriaMenu,
1817
+ {
1818
+ className: cx("pire-menu", className),
1819
+ style: menuStyle,
1820
+ ...rest
1821
+ }
1822
+ );
1823
+ }
1824
+ function MenuItem({
1825
+ children,
1826
+ icon,
1827
+ description,
1828
+ shortcut,
1829
+ tone = "default",
1830
+ className,
1831
+ ...rest
1832
+ }) {
1833
+ return /* @__PURE__ */ jsxs27(
1834
+ AriaMenuItem,
1835
+ {
1836
+ className: cx("pire-menu-item", className),
1837
+ "data-tone": tone === "danger" ? "danger" : void 0,
1838
+ ...rest,
1839
+ children: [
1840
+ icon ? /* @__PURE__ */ jsx34(Icon, { name: icon, size: 16, className: "pire-menu-item-icon" }) : null,
1841
+ /* @__PURE__ */ jsxs27("span", { className: "pire-menu-item-body", children: [
1842
+ /* @__PURE__ */ jsx34("span", { className: "pire-menu-item-label", children }),
1843
+ description ? /* @__PURE__ */ jsx34("span", { className: "pire-menu-item-desc", children: description }) : null
1844
+ ] }),
1845
+ shortcut ? /* @__PURE__ */ jsx34("kbd", { className: "pire-menu-item-shortcut", children: shortcut }) : null
1846
+ ]
1847
+ }
1848
+ );
1849
+ }
1850
+ function MenuSection({ title, children, className, ...rest }) {
1851
+ return /* @__PURE__ */ jsxs27(AriaMenuSection, { className: cx("pire-menu-section", className), ...rest, children: [
1852
+ title ? /* @__PURE__ */ jsx34(Header, { className: "pire-menu-section-title", children: title }) : null,
1853
+ children
1854
+ ] });
1855
+ }
1856
+ function MenuSeparator({ className }) {
1857
+ return /* @__PURE__ */ jsx34(AriaSeparator2, { className: cx("pire-menu-separator", className) });
1858
+ }
1859
+
1860
+ // src/components/navigation/SideNav.tsx
1861
+ import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
1631
1862
  function findActiveParent(groups, value) {
1632
1863
  if (value == null) return void 0;
1633
1864
  for (const group of groups) {
@@ -1645,6 +1876,7 @@ function SideNav({
1645
1876
  defaultExpandedIds,
1646
1877
  onExpandedChange,
1647
1878
  collapsed,
1879
+ railFlyout = true,
1648
1880
  footer,
1649
1881
  className,
1650
1882
  ...rest
@@ -1652,10 +1884,10 @@ function SideNav({
1652
1884
  const msg = usePireMessages();
1653
1885
  const activeParent = findActiveParent(groups, value);
1654
1886
  const isControlled = expandedIds != null;
1655
- const [ownExpanded, setOwnExpanded] = React10.useState(
1887
+ const [ownExpanded, setOwnExpanded] = React11.useState(
1656
1888
  () => new Set(defaultExpandedIds ?? (activeParent ? [activeParent] : []))
1657
1889
  );
1658
- const [lastValue, setLastValue] = React10.useState(value);
1890
+ const [lastValue, setLastValue] = React11.useState(value);
1659
1891
  if (value !== lastValue) {
1660
1892
  setLastValue(value);
1661
1893
  if (!isControlled && activeParent && !ownExpanded.has(activeParent)) {
@@ -1675,7 +1907,7 @@ function SideNav({
1675
1907
  };
1676
1908
  const renderRow = (item, onPress, isGroup) => {
1677
1909
  const selected = !isGroup && item.id === value;
1678
- const button = /* @__PURE__ */ jsxs25(
1910
+ const button = /* @__PURE__ */ jsxs28(
1679
1911
  AriaButton9,
1680
1912
  {
1681
1913
  className: "pire-sidenav-item",
@@ -1685,17 +1917,37 @@ function SideNav({
1685
1917
  "aria-label": collapsed ? item.label : void 0,
1686
1918
  onPress,
1687
1919
  children: [
1688
- item.icon ? /* @__PURE__ */ jsx32(Icon, { name: item.icon, size: 16 }) : null,
1689
- collapsed ? null : /* @__PURE__ */ jsx32("span", { children: item.label }),
1690
- item.count != null && !collapsed ? /* @__PURE__ */ jsx32("span", { className: "pire-sidenav-count", children: item.count }) : null
1920
+ item.icon ? /* @__PURE__ */ jsx35(Icon, { name: item.icon, size: 16 }) : null,
1921
+ collapsed ? null : /* @__PURE__ */ jsx35("span", { children: item.label }),
1922
+ item.count != null && !collapsed ? /* @__PURE__ */ jsx35("span", { className: "pire-sidenav-count", children: item.count }) : null
1691
1923
  ]
1692
1924
  },
1693
1925
  item.id
1694
1926
  );
1695
- return collapsed ? /* @__PURE__ */ jsx32(Tooltip, { label: item.label, placement: "right", children: button }, item.id) : button;
1927
+ return collapsed ? /* @__PURE__ */ jsx35(Tooltip, { label: item.label, placement: "right", children: button }, item.id) : button;
1696
1928
  };
1697
- const renderSection = (item) => /* @__PURE__ */ jsxs25(Disclosure, { id: item.id, className: "pire-sidenav-section", children: [
1698
- /* @__PURE__ */ jsxs25(
1929
+ const renderRailFlyout = (item) => /* @__PURE__ */ jsxs28(MenuTrigger, { children: [
1930
+ /* @__PURE__ */ jsx35(
1931
+ AriaButton9,
1932
+ {
1933
+ className: "pire-sidenav-item",
1934
+ "aria-label": item.label,
1935
+ "data-active-child": item.id === activeParent ? "true" : void 0,
1936
+ children: item.icon ? /* @__PURE__ */ jsx35(Icon, { name: item.icon, size: 16 }) : null
1937
+ }
1938
+ ),
1939
+ /* @__PURE__ */ jsx35(Popover5, { className: "pire-popover", placement: "right top", offset: 4, children: /* @__PURE__ */ jsx35(
1940
+ Menu,
1941
+ {
1942
+ "aria-label": item.label,
1943
+ className: "pire-sidenav-flyout",
1944
+ onAction: (key) => onChange?.(String(key)),
1945
+ children: (item.items ?? []).map((child) => /* @__PURE__ */ jsx35(MenuItem, { id: child.id, children: child.label }, child.id))
1946
+ }
1947
+ ) })
1948
+ ] }, item.id);
1949
+ const renderSection = (item) => /* @__PURE__ */ jsxs28(Disclosure, { id: item.id, className: "pire-sidenav-section", children: [
1950
+ /* @__PURE__ */ jsxs28(
1699
1951
  AriaButton9,
1700
1952
  {
1701
1953
  slot: "trigger",
@@ -1703,16 +1955,16 @@ function SideNav({
1703
1955
  "data-kind": "group",
1704
1956
  "data-active-child": item.id === activeParent ? "true" : void 0,
1705
1957
  children: [
1706
- item.icon ? /* @__PURE__ */ jsx32(Icon, { name: item.icon, size: 16 }) : null,
1707
- /* @__PURE__ */ jsx32("span", { children: item.label }),
1708
- item.count != null ? /* @__PURE__ */ jsx32("span", { className: "pire-sidenav-count", children: item.count }) : null,
1709
- /* @__PURE__ */ jsx32(Icon, { name: "chevron-down", size: 16, className: "pire-sidenav-chevron" })
1958
+ item.icon ? /* @__PURE__ */ jsx35(Icon, { name: item.icon, size: 16 }) : null,
1959
+ /* @__PURE__ */ jsx35("span", { children: item.label }),
1960
+ item.count != null ? /* @__PURE__ */ jsx35("span", { className: "pire-sidenav-count", children: item.count }) : null,
1961
+ /* @__PURE__ */ jsx35(Icon, { name: "chevron-down", size: 16, className: "pire-sidenav-chevron" })
1710
1962
  ]
1711
1963
  }
1712
1964
  ),
1713
- /* @__PURE__ */ jsx32(DisclosurePanel, { className: "pire-sidenav-subnav", children: item.items?.map((child) => {
1965
+ /* @__PURE__ */ jsx35(DisclosurePanel, { className: "pire-sidenav-subnav", children: item.items?.map((child) => {
1714
1966
  const selected = child.id === value;
1715
- return /* @__PURE__ */ jsxs25(
1967
+ return /* @__PURE__ */ jsxs28(
1716
1968
  AriaButton9,
1717
1969
  {
1718
1970
  className: "pire-sidenav-item pire-sidenav-subitem",
@@ -1720,15 +1972,15 @@ function SideNav({
1720
1972
  "aria-current": selected ? "page" : void 0,
1721
1973
  onPress: () => onChange?.(child.id),
1722
1974
  children: [
1723
- /* @__PURE__ */ jsx32("span", { children: child.label }),
1724
- child.count != null ? /* @__PURE__ */ jsx32("span", { className: "pire-sidenav-count", children: child.count }) : null
1975
+ /* @__PURE__ */ jsx35("span", { children: child.label }),
1976
+ child.count != null ? /* @__PURE__ */ jsx35("span", { className: "pire-sidenav-count", children: child.count }) : null
1725
1977
  ]
1726
1978
  },
1727
1979
  child.id
1728
1980
  );
1729
1981
  }) })
1730
1982
  ] }, item.id);
1731
- return /* @__PURE__ */ jsxs25(
1983
+ return /* @__PURE__ */ jsxs28(
1732
1984
  "nav",
1733
1985
  {
1734
1986
  className: cx("pire-sidenav", className),
@@ -1741,11 +1993,12 @@ function SideNav({
1741
1993
  const rows = group.items.map((item) => {
1742
1994
  const isGroup = Boolean(item.items?.length);
1743
1995
  if (isGroup && !collapsed) return renderSection(item);
1996
+ if (isGroup && collapsed && railFlyout) return renderRailFlyout(item);
1744
1997
  return renderRow(item, () => isGroup ? toggleExpanded(item.id) : onChange?.(item.id), isGroup);
1745
1998
  });
1746
- return /* @__PURE__ */ jsxs25("div", { className: "pire-sidenav-group", children: [
1747
- group.label && !collapsed ? /* @__PURE__ */ jsx32("div", { className: "pire-sidenav-label", children: group.label }) : null,
1748
- hasSections ? /* @__PURE__ */ jsx32(
1999
+ return /* @__PURE__ */ jsxs28("div", { className: "pire-sidenav-group", children: [
2000
+ group.label && !collapsed ? /* @__PURE__ */ jsx35("div", { className: "pire-sidenav-label", children: group.label }) : null,
2001
+ hasSections ? /* @__PURE__ */ jsx35(
1749
2002
  DisclosureGroup,
1750
2003
  {
1751
2004
  className: "pire-sidenav-tree",
@@ -1757,7 +2010,7 @@ function SideNav({
1757
2010
  ) : rows
1758
2011
  ] }, group.label ?? gi);
1759
2012
  }),
1760
- footer ? /* @__PURE__ */ jsx32("div", { className: "pire-sidenav-footer", children: footer }) : null
2013
+ footer ? /* @__PURE__ */ jsx35("div", { className: "pire-sidenav-footer", children: footer }) : null
1761
2014
  ]
1762
2015
  }
1763
2016
  );
@@ -1765,9 +2018,9 @@ function SideNav({
1765
2018
 
1766
2019
  // src/components/navigation/Tabs.tsx
1767
2020
  import { Tabs as AriaTabs, TabList, Tab as AriaTab, TabPanel } from "react-aria-components";
1768
- import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
2021
+ import { jsx as jsx36, jsxs as jsxs29 } from "react/jsx-runtime";
1769
2022
  function Tabs({ items, value, defaultValue, onChange, panels, className, style, ...rest }) {
1770
- return /* @__PURE__ */ jsxs26(
2023
+ return /* @__PURE__ */ jsxs29(
1771
2024
  AriaTabs,
1772
2025
  {
1773
2026
  className,
@@ -1776,12 +2029,12 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
1776
2029
  defaultSelectedKey: defaultValue,
1777
2030
  onSelectionChange: (k) => onChange?.(String(k)),
1778
2031
  children: [
1779
- /* @__PURE__ */ jsx33(TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ jsxs26(AriaTab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
1780
- item.icon ? /* @__PURE__ */ jsx33(Icon, { name: item.icon, size: 16 }) : null,
2032
+ /* @__PURE__ */ jsx36(TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ jsxs29(AriaTab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
2033
+ item.icon ? /* @__PURE__ */ jsx36(Icon, { name: item.icon, size: 16 }) : null,
1781
2034
  item.label,
1782
- item.count != null ? /* @__PURE__ */ jsx33("span", { className: "pire-tab-count", children: item.count }) : null
2035
+ item.count != null ? /* @__PURE__ */ jsx36("span", { className: "pire-tab-count", children: item.count }) : null
1783
2036
  ] }) }),
1784
- items.map((item) => /* @__PURE__ */ jsx33(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2037
+ items.map((item) => /* @__PURE__ */ jsx36(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
1785
2038
  ]
1786
2039
  }
1787
2040
  );
@@ -1789,9 +2042,9 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
1789
2042
 
1790
2043
  // src/components/navigation/Breadcrumb.tsx
1791
2044
  import { Breadcrumbs as AriaBreadcrumbs, Breadcrumb as AriaBreadcrumb, Link as Link2 } from "react-aria-components";
1792
- import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
2045
+ import { jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
1793
2046
  function Breadcrumb({ items, onNavigate, className, style }) {
1794
- return /* @__PURE__ */ jsx34(
2047
+ return /* @__PURE__ */ jsx37(
1795
2048
  AriaBreadcrumbs,
1796
2049
  {
1797
2050
  className: cx("pire-breadcrumbs", className),
@@ -1800,9 +2053,9 @@ function Breadcrumb({ items, onNavigate, className, style }) {
1800
2053
  onAction: (key) => onNavigate?.(String(key)),
1801
2054
  children: (item) => {
1802
2055
  const last = items[items.length - 1] === item;
1803
- return /* @__PURE__ */ jsxs27(AriaBreadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
1804
- last ? item.label : /* @__PURE__ */ jsx34(Link2, { href: item.href, children: item.label }),
1805
- last ? null : /* @__PURE__ */ jsx34(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
2056
+ return /* @__PURE__ */ jsxs30(AriaBreadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
2057
+ last ? item.label : /* @__PURE__ */ jsx37(Link2, { href: item.href, children: item.label }),
2058
+ last ? null : /* @__PURE__ */ jsx37(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
1806
2059
  ] });
1807
2060
  }
1808
2061
  }
@@ -1810,7 +2063,7 @@ function Breadcrumb({ items, onNavigate, className, style }) {
1810
2063
  }
1811
2064
 
1812
2065
  // src/components/navigation/Pagination.tsx
1813
- import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
2066
+ import { jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
1814
2067
  function Pagination({
1815
2068
  page = 1,
1816
2069
  pageSize = 25,
@@ -1825,9 +2078,9 @@ function Pagination({
1825
2078
  const pages = Math.max(1, Math.ceil(total / pageSize));
1826
2079
  const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
1827
2080
  const to = Math.min(total, page * pageSize);
1828
- return /* @__PURE__ */ jsxs28("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
1829
- /* @__PURE__ */ jsx35("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
1830
- /* @__PURE__ */ jsx35(
2081
+ return /* @__PURE__ */ jsxs31("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
2082
+ /* @__PURE__ */ jsx38("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
2083
+ /* @__PURE__ */ jsx38(
1831
2084
  IconButton,
1832
2085
  {
1833
2086
  icon: "chevron-left",
@@ -1838,8 +2091,8 @@ function Pagination({
1838
2091
  onPress: () => onPageChange?.(page - 1)
1839
2092
  }
1840
2093
  ),
1841
- /* @__PURE__ */ jsx35("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
1842
- /* @__PURE__ */ jsx35(
2094
+ /* @__PURE__ */ jsx38("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
2095
+ /* @__PURE__ */ jsx38(
1843
2096
  IconButton,
1844
2097
  {
1845
2098
  icon: "chevron-right",
@@ -1850,7 +2103,7 @@ function Pagination({
1850
2103
  onPress: () => onPageChange?.(page + 1)
1851
2104
  }
1852
2105
  ),
1853
- onPageSizeChange ? /* @__PURE__ */ jsx35(
2106
+ onPageSizeChange ? /* @__PURE__ */ jsx38(
1854
2107
  Select,
1855
2108
  {
1856
2109
  "aria-label": msg.paginationRowsPerPage,
@@ -1865,65 +2118,8 @@ function Pagination({
1865
2118
  ] });
1866
2119
  }
1867
2120
 
1868
- // src/components/navigation/Menu.tsx
1869
- import {
1870
- Menu as AriaMenu,
1871
- MenuItem as AriaMenuItem,
1872
- MenuSection as AriaMenuSection,
1873
- Separator as AriaSeparator2,
1874
- Header
1875
- } from "react-aria-components";
1876
- import { jsx as jsx36, jsxs as jsxs29 } from "react/jsx-runtime";
1877
- function Menu({ minWidth, className, style, ...rest }) {
1878
- const width = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
1879
- const menuStyle = width == null ? style : { ["--pire-menu-min-w"]: width, ...style };
1880
- return /* @__PURE__ */ jsx36(
1881
- AriaMenu,
1882
- {
1883
- className: cx("pire-menu", className),
1884
- style: menuStyle,
1885
- ...rest
1886
- }
1887
- );
1888
- }
1889
- function MenuItem({
1890
- children,
1891
- icon,
1892
- description,
1893
- shortcut,
1894
- tone = "default",
1895
- className,
1896
- ...rest
1897
- }) {
1898
- return /* @__PURE__ */ jsxs29(
1899
- AriaMenuItem,
1900
- {
1901
- className: cx("pire-menu-item", className),
1902
- "data-tone": tone === "danger" ? "danger" : void 0,
1903
- ...rest,
1904
- children: [
1905
- icon ? /* @__PURE__ */ jsx36(Icon, { name: icon, size: 16, className: "pire-menu-item-icon" }) : null,
1906
- /* @__PURE__ */ jsxs29("span", { className: "pire-menu-item-body", children: [
1907
- /* @__PURE__ */ jsx36("span", { className: "pire-menu-item-label", children }),
1908
- description ? /* @__PURE__ */ jsx36("span", { className: "pire-menu-item-desc", children: description }) : null
1909
- ] }),
1910
- shortcut ? /* @__PURE__ */ jsx36("kbd", { className: "pire-menu-item-shortcut", children: shortcut }) : null
1911
- ]
1912
- }
1913
- );
1914
- }
1915
- function MenuSection({ title, children, className, ...rest }) {
1916
- return /* @__PURE__ */ jsxs29(AriaMenuSection, { className: cx("pire-menu-section", className), ...rest, children: [
1917
- title ? /* @__PURE__ */ jsx36(Header, { className: "pire-menu-section-title", children: title }) : null,
1918
- children
1919
- ] });
1920
- }
1921
- function MenuSeparator({ className }) {
1922
- return /* @__PURE__ */ jsx36(AriaSeparator2, { className: cx("pire-menu-separator", className) });
1923
- }
1924
-
1925
2121
  // src/components/feedback/InlineMessage.tsx
1926
- import { jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
2122
+ import { jsx as jsx39, jsxs as jsxs32 } from "react/jsx-runtime";
1927
2123
  var KIND_ICON = {
1928
2124
  info: "info",
1929
2125
  success: "check-circle-2",
@@ -1933,7 +2129,7 @@ var KIND_ICON = {
1933
2129
  function InlineMessage({ kind = "info", title, action, onClose, children, className, ...rest }) {
1934
2130
  const msg = usePireMessages();
1935
2131
  const assertive = kind === "error" || kind === "warning";
1936
- return /* @__PURE__ */ jsxs30(
2132
+ return /* @__PURE__ */ jsxs32(
1937
2133
  "div",
1938
2134
  {
1939
2135
  className: cx("pire-msg", className),
@@ -1942,58 +2138,21 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
1942
2138
  "aria-live": assertive ? "assertive" : "polite",
1943
2139
  ...rest,
1944
2140
  children: [
1945
- /* @__PURE__ */ jsx37(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
1946
- /* @__PURE__ */ jsxs30("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
1947
- title ? /* @__PURE__ */ jsx37("span", { className: "pire-msg-title", children: title }) : null,
1948
- children ? /* @__PURE__ */ jsx37("span", { className: "pire-msg-body", children }) : null,
2141
+ /* @__PURE__ */ jsx39(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
2142
+ /* @__PURE__ */ jsxs32("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
2143
+ title ? /* @__PURE__ */ jsx39("span", { className: "pire-msg-title", children: title }) : null,
2144
+ children ? /* @__PURE__ */ jsx39("span", { className: "pire-msg-body", children }) : null,
1949
2145
  action
1950
2146
  ] }),
1951
- onClose ? /* @__PURE__ */ jsx37(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
2147
+ onClose ? /* @__PURE__ */ jsx39(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
1952
2148
  ]
1953
2149
  }
1954
2150
  );
1955
2151
  }
1956
2152
 
1957
- // src/components/feedback/ProgressBar.tsx
1958
- import { ProgressBar as AriaProgressBar, Label as Label9 } from "react-aria-components";
1959
- import { Fragment as Fragment2, jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
1960
- function ProgressBar({
1961
- value = 0,
1962
- minValue = 0,
1963
- maxValue = 100,
1964
- label,
1965
- showValue = true,
1966
- isIndeterminate,
1967
- status = "informative",
1968
- size = "md",
1969
- className,
1970
- style
1971
- }) {
1972
- return /* @__PURE__ */ jsx38(
1973
- AriaProgressBar,
1974
- {
1975
- className: cx("pire-progress", className),
1976
- "data-status": status,
1977
- "data-size": size,
1978
- value,
1979
- minValue,
1980
- maxValue,
1981
- isIndeterminate,
1982
- style,
1983
- children: ({ percentage, valueText }) => /* @__PURE__ */ jsxs31(Fragment2, { children: [
1984
- label || showValue ? /* @__PURE__ */ jsxs31("div", { className: "pire-progress-head", children: [
1985
- label ? /* @__PURE__ */ jsx38(Label9, { children: label }) : /* @__PURE__ */ jsx38("span", {}),
1986
- showValue && !isIndeterminate ? /* @__PURE__ */ jsx38("span", { className: "pire-numeric", children: valueText }) : null
1987
- ] }) : null,
1988
- /* @__PURE__ */ jsx38("div", { className: "pire-progress-track", children: /* @__PURE__ */ jsx38("div", { className: "pire-progress-fill", style: { width: `${isIndeterminate ? 40 : percentage}%` } }) })
1989
- ] })
1990
- }
1991
- );
1992
- }
1993
-
1994
2153
  // src/components/feedback/Toast.tsx
1995
- import * as React11 from "react";
1996
- import { jsx as jsx39, jsxs as jsxs32 } from "react/jsx-runtime";
2154
+ import * as React12 from "react";
2155
+ import { jsx as jsx40, jsxs as jsxs33 } from "react/jsx-runtime";
1997
2156
  var KIND_ICON2 = {
1998
2157
  info: "info",
1999
2158
  success: "check-circle-2",
@@ -2002,7 +2161,7 @@ var KIND_ICON2 = {
2002
2161
  };
2003
2162
  function Toast({ kind = "success", onClose, position = "bottom-center", children, className, ...rest }) {
2004
2163
  const msg = usePireMessages();
2005
- return /* @__PURE__ */ jsxs32(
2164
+ return /* @__PURE__ */ jsxs33(
2006
2165
  "div",
2007
2166
  {
2008
2167
  className: cx("pire-toast", className),
@@ -2011,40 +2170,40 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
2011
2170
  "aria-live": kind === "error" ? "assertive" : "polite",
2012
2171
  ...rest,
2013
2172
  children: [
2014
- /* @__PURE__ */ jsx39(Icon, { name: KIND_ICON2[kind], size: 16 }),
2015
- /* @__PURE__ */ jsx39("span", { style: { flex: 1 }, children }),
2016
- onClose ? /* @__PURE__ */ jsx39(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
2173
+ /* @__PURE__ */ jsx40(Icon, { name: KIND_ICON2[kind], size: 16 }),
2174
+ /* @__PURE__ */ jsx40("span", { style: { flex: 1 }, children }),
2175
+ onClose ? /* @__PURE__ */ jsx40(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
2017
2176
  ]
2018
2177
  }
2019
2178
  );
2020
2179
  }
2021
- var ToastContext = React11.createContext(null);
2180
+ var ToastContext = React12.createContext(null);
2022
2181
  function ToastProvider({ children, timeout = 6e3 }) {
2023
2182
  const msg = usePireMessages();
2024
- const [toasts, setToasts] = React11.useState([]);
2025
- const close = React11.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2026
- const add = React11.useCallback((toast) => {
2183
+ const [toasts, setToasts] = React12.useState([]);
2184
+ const close = React12.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2185
+ const add = React12.useCallback((toast) => {
2027
2186
  const id = Math.random().toString(36).slice(2);
2028
2187
  setToasts((t) => [...t, { ...toast, id }]);
2029
2188
  const ms = toast.timeout ?? timeout;
2030
2189
  if (ms > 0) setTimeout(() => close(id), ms);
2031
2190
  return id;
2032
2191
  }, [close, timeout]);
2033
- const value = React11.useMemo(() => ({ add, close }), [add, close]);
2034
- return /* @__PURE__ */ jsxs32(ToastContext.Provider, { value, children: [
2192
+ const value = React12.useMemo(() => ({ add, close }), [add, close]);
2193
+ return /* @__PURE__ */ jsxs33(ToastContext.Provider, { value, children: [
2035
2194
  children,
2036
- /* @__PURE__ */ jsx39("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ jsx39(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
2195
+ /* @__PURE__ */ jsx40("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ jsx40(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
2037
2196
  ] });
2038
2197
  }
2039
2198
  function useToast() {
2040
- const ctx = React11.useContext(ToastContext);
2199
+ const ctx = React12.useContext(ToastContext);
2041
2200
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
2042
2201
  return ctx;
2043
2202
  }
2044
2203
 
2045
2204
  // src/components/data/KpiTile.tsx
2046
2205
  import { Button as AriaButton10 } from "react-aria-components";
2047
- import { Fragment as Fragment3, jsx as jsx40, jsxs as jsxs33 } from "react/jsx-runtime";
2206
+ import { Fragment as Fragment3, jsx as jsx41, jsxs as jsxs34 } from "react/jsx-runtime";
2048
2207
  function KpiTile({
2049
2208
  label,
2050
2209
  value,
@@ -2060,50 +2219,50 @@ function KpiTile({
2060
2219
  style
2061
2220
  }) {
2062
2221
  const tone = deltaTone ?? (deltaDirection === "down" ? "negative" : "positive");
2063
- const body = /* @__PURE__ */ jsxs33(Fragment3, { children: [
2064
- /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-label", children: [
2065
- icon ? /* @__PURE__ */ jsx40(Icon, { name: icon, size: 16 }) : null,
2222
+ const body = /* @__PURE__ */ jsxs34(Fragment3, { children: [
2223
+ /* @__PURE__ */ jsxs34("span", { className: "pire-kpi-label", children: [
2224
+ icon ? /* @__PURE__ */ jsx41(Icon, { name: icon, size: 16 }) : null,
2066
2225
  label
2067
2226
  ] }),
2068
- /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-value", children: [
2227
+ /* @__PURE__ */ jsxs34("span", { className: "pire-kpi-value", children: [
2069
2228
  value,
2070
- unit ? /* @__PURE__ */ jsx40("span", { className: "pire-kpi-unit", children: unit }) : null
2229
+ unit ? /* @__PURE__ */ jsx41("span", { className: "pire-kpi-unit", children: unit }) : null
2071
2230
  ] }),
2072
- delta ? /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
2073
- deltaDirection ? /* @__PURE__ */ jsx40(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
2231
+ delta ? /* @__PURE__ */ jsxs34("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
2232
+ deltaDirection ? /* @__PURE__ */ jsx41(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
2074
2233
  delta
2075
2234
  ] }) : null,
2076
- footnote ? /* @__PURE__ */ jsx40("span", { className: "pire-kpi-foot", children: footnote }) : null
2235
+ footnote ? /* @__PURE__ */ jsx41("span", { className: "pire-kpi-foot", children: footnote }) : null
2077
2236
  ] });
2078
2237
  const props = { className: cx("pire-kpi", className), "data-status": status, style };
2079
- return onPress ? /* @__PURE__ */ jsx40(AriaButton10, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ jsx40("div", { ...props, children: body });
2238
+ return onPress ? /* @__PURE__ */ jsx41(AriaButton10, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ jsx41("div", { ...props, children: body });
2080
2239
  }
2081
2240
 
2082
2241
  // src/components/data/ObjectHeader.tsx
2083
- import { jsx as jsx41, jsxs as jsxs34 } from "react/jsx-runtime";
2242
+ import { jsx as jsx42, jsxs as jsxs35 } from "react/jsx-runtime";
2084
2243
  function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions, className, ...rest }) {
2085
- return /* @__PURE__ */ jsxs34("header", { className: cx("pire-objheader", className), ...rest, children: [
2244
+ return /* @__PURE__ */ jsxs35("header", { className: cx("pire-objheader", className), ...rest, children: [
2086
2245
  breadcrumb,
2087
- /* @__PURE__ */ jsxs34("div", { className: "pire-objheader-row", children: [
2088
- /* @__PURE__ */ jsxs34("div", { style: { minWidth: 0 }, children: [
2089
- /* @__PURE__ */ jsx41("h1", { className: "pire-objheader-title", children: title }),
2090
- subtitle || id ? /* @__PURE__ */ jsxs34("div", { className: "pire-objheader-sub", children: [
2246
+ /* @__PURE__ */ jsxs35("div", { className: "pire-objheader-row", children: [
2247
+ /* @__PURE__ */ jsxs35("div", { style: { minWidth: 0 }, children: [
2248
+ /* @__PURE__ */ jsx42("h1", { className: "pire-objheader-title", children: title }),
2249
+ subtitle || id ? /* @__PURE__ */ jsxs35("div", { className: "pire-objheader-sub", children: [
2091
2250
  subtitle,
2092
- id ? /* @__PURE__ */ jsx41("span", { className: "pire-objheader-id", children: id }) : null
2251
+ id ? /* @__PURE__ */ jsx42("span", { className: "pire-objheader-id", children: id }) : null
2093
2252
  ] }) : null
2094
2253
  ] }),
2095
2254
  badge,
2096
- actions ? /* @__PURE__ */ jsx41("div", { className: "pire-objheader-actions", children: actions }) : null
2255
+ actions ? /* @__PURE__ */ jsx42("div", { className: "pire-objheader-actions", children: actions }) : null
2097
2256
  ] }),
2098
- facts?.length ? /* @__PURE__ */ jsx41("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs34("div", { children: [
2099
- /* @__PURE__ */ jsx41("dt", { className: "pire-fact-label", children: fact.label }),
2100
- /* @__PURE__ */ jsx41("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
2257
+ facts?.length ? /* @__PURE__ */ jsx42("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs35("div", { children: [
2258
+ /* @__PURE__ */ jsx42("dt", { className: "pire-fact-label", children: fact.label }),
2259
+ /* @__PURE__ */ jsx42("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
2101
2260
  ] }, fact.label)) }) : null
2102
2261
  ] });
2103
2262
  }
2104
2263
 
2105
2264
  // src/components/data/FilterBar.tsx
2106
- import { jsx as jsx42, jsxs as jsxs35 } from "react/jsx-runtime";
2265
+ import { jsx as jsx43, jsxs as jsxs36 } from "react/jsx-runtime";
2107
2266
  function FilterBar({
2108
2267
  children,
2109
2268
  activeFilters = [],
@@ -2120,66 +2279,66 @@ function FilterBar({
2120
2279
  const label = useMessage("filterBarLabel", rest["aria-label"]);
2121
2280
  const go = useMessage("filterBarGo", goLabel);
2122
2281
  const clearAll = useMessage("filterBarClearAll", clearAllLabel);
2123
- return /* @__PURE__ */ jsxs35("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
2124
- /* @__PURE__ */ jsxs35("div", { className: "pire-filterbar-controls", children: [
2282
+ return /* @__PURE__ */ jsxs36("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
2283
+ /* @__PURE__ */ jsxs36("div", { className: "pire-filterbar-controls", children: [
2125
2284
  children,
2126
- onGo ? /* @__PURE__ */ jsx42(Button, { variant: "primary", onPress: onGo, children: go }) : null
2285
+ onGo ? /* @__PURE__ */ jsx43(Button, { variant: "primary", onPress: onGo, children: go }) : null
2127
2286
  ] }),
2128
- activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs35("div", { className: "pire-filterbar-foot", children: [
2129
- activeFilters.map((filter) => /* @__PURE__ */ jsx42(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
2130
- activeFilters.length && onClear ? /* @__PURE__ */ jsx42(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
2131
- resultLabel ? /* @__PURE__ */ jsx42("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
2132
- actions ? /* @__PURE__ */ jsx42("div", { className: "pire-filterbar-actions", children: actions }) : null
2287
+ activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs36("div", { className: "pire-filterbar-foot", children: [
2288
+ activeFilters.map((filter) => /* @__PURE__ */ jsx43(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
2289
+ activeFilters.length && onClear ? /* @__PURE__ */ jsx43(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
2290
+ resultLabel ? /* @__PURE__ */ jsx43("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
2291
+ actions ? /* @__PURE__ */ jsx43("div", { className: "pire-filterbar-actions", children: actions }) : null
2133
2292
  ] }) : null
2134
2293
  ] });
2135
2294
  }
2136
2295
 
2137
2296
  // src/components/data/DescriptionList.tsx
2138
- import { jsx as jsx43, jsxs as jsxs36 } from "react/jsx-runtime";
2297
+ import { jsx as jsx44, jsxs as jsxs37 } from "react/jsx-runtime";
2139
2298
  function DescriptionList({ items, layout = "rows", columns = 3, className, style, ...rest }) {
2140
- return /* @__PURE__ */ jsx43(
2299
+ return /* @__PURE__ */ jsx44(
2141
2300
  "dl",
2142
2301
  {
2143
2302
  className: cx("pire-dl", className),
2144
2303
  "data-layout": layout,
2145
2304
  style: { ...layout === "grid" ? { "--pire-dl-cols": columns } : null, ...style },
2146
2305
  ...rest,
2147
- children: items.map((item, i) => /* @__PURE__ */ jsxs36("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
2148
- /* @__PURE__ */ jsxs36("dt", { className: "pire-dl-term", children: [
2306
+ children: items.map((item, i) => /* @__PURE__ */ jsxs37("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
2307
+ /* @__PURE__ */ jsxs37("dt", { className: "pire-dl-term", children: [
2149
2308
  item.label,
2150
2309
  item.hint
2151
2310
  ] }),
2152
- /* @__PURE__ */ jsx43("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
2311
+ /* @__PURE__ */ jsx44("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
2153
2312
  ] }, i))
2154
2313
  }
2155
2314
  );
2156
2315
  }
2157
2316
 
2158
2317
  // src/components/data/Timeline.tsx
2159
- import { jsx as jsx44, jsxs as jsxs37 } from "react/jsx-runtime";
2318
+ import { jsx as jsx45, jsxs as jsxs38 } from "react/jsx-runtime";
2160
2319
  function Timeline({ entries, reverse = false, className, ...rest }) {
2161
2320
  const list = reverse ? [...entries].reverse() : entries;
2162
- return /* @__PURE__ */ jsx44("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs37("li", { className: "pire-timeline-item", children: [
2163
- /* @__PURE__ */ jsx44("span", { className: "pire-timeline-time", children: entry.time }),
2164
- /* @__PURE__ */ jsx44("span", { className: "pire-timeline-text", children: entry.event }),
2165
- entry.actor ? /* @__PURE__ */ jsx44("span", { className: "pire-timeline-actor", children: entry.actor }) : null
2321
+ return /* @__PURE__ */ jsx45("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs38("li", { className: "pire-timeline-item", children: [
2322
+ /* @__PURE__ */ jsx45("span", { className: "pire-timeline-time", children: entry.time }),
2323
+ /* @__PURE__ */ jsx45("span", { className: "pire-timeline-text", children: entry.event }),
2324
+ entry.actor ? /* @__PURE__ */ jsx45("span", { className: "pire-timeline-actor", children: entry.actor }) : null
2166
2325
  ] }, entry.id ?? i)) });
2167
2326
  }
2168
2327
 
2169
2328
  // src/components/data/LinkList.tsx
2170
2329
  import { Button as AriaButton11 } from "react-aria-components";
2171
- import { jsx as jsx45, jsxs as jsxs38 } from "react/jsx-runtime";
2330
+ import { jsx as jsx46, jsxs as jsxs39 } from "react/jsx-runtime";
2172
2331
  function LinkList({ items, onSelect, className, ...rest }) {
2173
- return /* @__PURE__ */ jsx45("div", { className: cx("pire-linklist", className), role: "list", ...rest, children: items.map((item) => /* @__PURE__ */ jsxs38(AriaButton11, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
2174
- item.icon ? /* @__PURE__ */ jsx45(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
2175
- item.key ? /* @__PURE__ */ jsx45("span", { className: "pire-linklist-key", children: item.key }) : null,
2176
- item.text ? /* @__PURE__ */ jsx45("span", { className: "pire-linklist-text", children: item.text }) : null,
2332
+ return /* @__PURE__ */ jsx46("div", { className: cx("pire-linklist", className), role: "list", ...rest, children: items.map((item) => /* @__PURE__ */ jsxs39(AriaButton11, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
2333
+ item.icon ? /* @__PURE__ */ jsx46(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
2334
+ item.key ? /* @__PURE__ */ jsx46("span", { className: "pire-linklist-key", children: item.key }) : null,
2335
+ item.text ? /* @__PURE__ */ jsx46("span", { className: "pire-linklist-text", children: item.text }) : null,
2177
2336
  item.trailing
2178
2337
  ] }, item.id)) });
2179
2338
  }
2180
2339
 
2181
2340
  // src/components/layout/PageBand.tsx
2182
- import { jsx as jsx46 } from "react/jsx-runtime";
2341
+ import { jsx as jsx47 } from "react/jsx-runtime";
2183
2342
  function PageBand({
2184
2343
  surface = "card",
2185
2344
  hasBorder = true,
@@ -2187,7 +2346,7 @@ function PageBand({
2187
2346
  className,
2188
2347
  ...rest
2189
2348
  }) {
2190
- return /* @__PURE__ */ jsx46(
2349
+ return /* @__PURE__ */ jsx47(
2191
2350
  "div",
2192
2351
  {
2193
2352
  className: cx("pire-pageband", className),
@@ -2200,56 +2359,56 @@ function PageBand({
2200
2359
  }
2201
2360
 
2202
2361
  // src/components/layout/PageHeader.tsx
2203
- import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
2362
+ import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
2204
2363
  function PageHeader({ title, subtitle, actions, className, ...rest }) {
2205
- return /* @__PURE__ */ jsxs39("header", { className: cx("pire-pageheader", className), ...rest, children: [
2206
- /* @__PURE__ */ jsxs39("div", { style: { minWidth: 0 }, children: [
2207
- /* @__PURE__ */ jsx47("h1", { className: "pire-pageheader-title", children: title }),
2208
- subtitle ? /* @__PURE__ */ jsx47("p", { className: "pire-pageheader-sub", children: subtitle }) : null
2364
+ return /* @__PURE__ */ jsxs40("header", { className: cx("pire-pageheader", className), ...rest, children: [
2365
+ /* @__PURE__ */ jsxs40("div", { style: { minWidth: 0 }, children: [
2366
+ /* @__PURE__ */ jsx48("h1", { className: "pire-pageheader-title", children: title }),
2367
+ subtitle ? /* @__PURE__ */ jsx48("p", { className: "pire-pageheader-sub", children: subtitle }) : null
2209
2368
  ] }),
2210
- actions ? /* @__PURE__ */ jsx47("div", { className: "pire-pageheader-actions", children: actions }) : null
2369
+ actions ? /* @__PURE__ */ jsx48("div", { className: "pire-pageheader-actions", children: actions }) : null
2211
2370
  ] });
2212
2371
  }
2213
2372
 
2214
2373
  // src/components/layout/SectionHeader.tsx
2215
- import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
2374
+ import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
2216
2375
  function SectionHeader({ title, meta, actions, className, ...rest }) {
2217
- return /* @__PURE__ */ jsxs40("div", { className: cx("pire-sectionhead", className), ...rest, children: [
2218
- /* @__PURE__ */ jsx48("span", { className: "pire-eyebrow", children: title }),
2219
- meta ? /* @__PURE__ */ jsx48("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
2220
- actions ? /* @__PURE__ */ jsx48("div", { className: "pire-sectionhead-actions", children: actions }) : null
2376
+ return /* @__PURE__ */ jsxs41("div", { className: cx("pire-sectionhead", className), ...rest, children: [
2377
+ /* @__PURE__ */ jsx49("span", { className: "pire-eyebrow", children: title }),
2378
+ meta ? /* @__PURE__ */ jsx49("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
2379
+ actions ? /* @__PURE__ */ jsx49("div", { className: "pire-sectionhead-actions", children: actions }) : null
2221
2380
  ] });
2222
2381
  }
2223
2382
 
2224
2383
  // src/components/layout/SelectionBar.tsx
2225
- import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
2384
+ import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
2226
2385
  function SelectionBar({ count, noun = "record", children, actions, className, ...rest }) {
2227
2386
  if (!count) return null;
2228
- return /* @__PURE__ */ jsxs41("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
2229
- /* @__PURE__ */ jsxs41("span", { className: "pire-selectionbar-count", children: [
2387
+ return /* @__PURE__ */ jsxs42("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
2388
+ /* @__PURE__ */ jsxs42("span", { className: "pire-selectionbar-count", children: [
2230
2389
  count.toLocaleString(),
2231
2390
  " ",
2232
2391
  noun,
2233
2392
  count === 1 ? "" : "s",
2234
2393
  " selected"
2235
2394
  ] }),
2236
- children ? /* @__PURE__ */ jsx49("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
2237
- actions ? /* @__PURE__ */ jsx49("div", { className: "pire-selectionbar-actions", children: actions }) : null
2395
+ children ? /* @__PURE__ */ jsx50("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
2396
+ actions ? /* @__PURE__ */ jsx50("div", { className: "pire-selectionbar-actions", children: actions }) : null
2238
2397
  ] });
2239
2398
  }
2240
2399
 
2241
2400
  // src/components/layout/FooterBar.tsx
2242
- import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
2401
+ import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
2243
2402
  function FooterBar({ note, actions, children, className, ...rest }) {
2244
- return /* @__PURE__ */ jsxs42("footer", { className: cx("pire-footerbar", className), ...rest, children: [
2245
- note ? /* @__PURE__ */ jsx50("span", { className: "pire-footerbar-note", children: note }) : null,
2403
+ return /* @__PURE__ */ jsxs43("footer", { className: cx("pire-footerbar", className), ...rest, children: [
2404
+ note ? /* @__PURE__ */ jsx51("span", { className: "pire-footerbar-note", children: note }) : null,
2246
2405
  children,
2247
- actions ? /* @__PURE__ */ jsx50("div", { className: "pire-footerbar-actions", children: actions }) : null
2406
+ actions ? /* @__PURE__ */ jsx51("div", { className: "pire-footerbar-actions", children: actions }) : null
2248
2407
  ] });
2249
2408
  }
2250
2409
 
2251
2410
  // src/components/patterns/ConfirmDialog.tsx
2252
- import { Fragment as Fragment4, jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
2411
+ import { Fragment as Fragment4, jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
2253
2412
  function ConfirmDialog({
2254
2413
  isOpen,
2255
2414
  title,
@@ -2263,7 +2422,7 @@ function ConfirmDialog({
2263
2422
  onConfirm,
2264
2423
  onCancel
2265
2424
  }) {
2266
- return /* @__PURE__ */ jsxs43(
2425
+ return /* @__PURE__ */ jsxs44(
2267
2426
  Dialog,
2268
2427
  {
2269
2428
  isOpen,
@@ -2273,12 +2432,12 @@ function ConfirmDialog({
2273
2432
  onClose: onCancel,
2274
2433
  isDismissable: !isBusy,
2275
2434
  showClose: false,
2276
- footer: /* @__PURE__ */ jsxs43(Fragment4, { children: [
2277
- /* @__PURE__ */ jsx51(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
2278
- /* @__PURE__ */ jsx51(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
2435
+ footer: /* @__PURE__ */ jsxs44(Fragment4, { children: [
2436
+ /* @__PURE__ */ jsx52(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
2437
+ /* @__PURE__ */ jsx52(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
2279
2438
  ] }),
2280
2439
  children: [
2281
- consequence ? /* @__PURE__ */ jsx51(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
2440
+ consequence ? /* @__PURE__ */ jsx52(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
2282
2441
  children
2283
2442
  ]
2284
2443
  }
@@ -2287,10 +2446,10 @@ function ConfirmDialog({
2287
2446
 
2288
2447
  // src/components/patterns/SidePanel.tsx
2289
2448
  import { ModalOverlay as ModalOverlay2, Modal as Modal2, Dialog as AriaDialog3, Heading as Heading4 } from "react-aria-components";
2290
- import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
2449
+ import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
2291
2450
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
2292
2451
  const msg = usePireMessages();
2293
- return /* @__PURE__ */ jsx52(
2452
+ return /* @__PURE__ */ jsx53(
2294
2453
  ModalOverlay2,
2295
2454
  {
2296
2455
  className: "pire-sidepanel-overlay",
@@ -2299,34 +2458,138 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
2299
2458
  onOpenChange: (o) => {
2300
2459
  if (!o) onClose?.();
2301
2460
  },
2302
- children: /* @__PURE__ */ jsx52(Modal2, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs44(AriaDialog3, { className: "pire-dialog", style: { height: "100%" }, children: [
2303
- /* @__PURE__ */ jsxs44("header", { className: "pire-dialog-head", children: [
2304
- /* @__PURE__ */ jsxs44("div", { style: { flex: 1, minWidth: 0 }, children: [
2305
- /* @__PURE__ */ jsx52(Heading4, { slot: "title", className: "pire-dialog-title", children: title }),
2306
- subtitle ? /* @__PURE__ */ jsx52("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
2461
+ children: /* @__PURE__ */ jsx53(Modal2, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs45(AriaDialog3, { className: "pire-dialog", style: { height: "100%" }, children: [
2462
+ /* @__PURE__ */ jsxs45("header", { className: "pire-dialog-head", children: [
2463
+ /* @__PURE__ */ jsxs45("div", { style: { flex: 1, minWidth: 0 }, children: [
2464
+ /* @__PURE__ */ jsx53(Heading4, { slot: "title", className: "pire-dialog-title", children: title }),
2465
+ subtitle ? /* @__PURE__ */ jsx53("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
2307
2466
  ] }),
2308
- /* @__PURE__ */ jsx52(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
2467
+ /* @__PURE__ */ jsx53(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
2309
2468
  ] }),
2310
- /* @__PURE__ */ jsx52("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
2311
- footer ? /* @__PURE__ */ jsx52("footer", { className: "pire-dialog-foot", children: footer }) : null
2469
+ /* @__PURE__ */ jsx53("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
2470
+ footer ? /* @__PURE__ */ jsx53("footer", { className: "pire-dialog-foot", children: footer }) : null
2312
2471
  ] }) })
2313
2472
  }
2314
2473
  );
2315
2474
  }
2316
2475
 
2317
2476
  // src/components/patterns/EmptyState.tsx
2318
- import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
2477
+ import { jsx as jsx54, jsxs as jsxs46 } from "react/jsx-runtime";
2319
2478
  function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
2320
- return /* @__PURE__ */ jsxs45("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
2321
- /* @__PURE__ */ jsx53(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
2322
- title ? /* @__PURE__ */ jsx53("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
2323
- children ? /* @__PURE__ */ jsx53("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
2479
+ return /* @__PURE__ */ jsxs46("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
2480
+ /* @__PURE__ */ jsx54(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
2481
+ title ? /* @__PURE__ */ jsx54("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
2482
+ children ? /* @__PURE__ */ jsx54("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
2324
2483
  action
2325
2484
  ] });
2326
2485
  }
2327
2486
 
2487
+ // src/components/patterns/FileDropZone.tsx
2488
+ import * as React13 from "react";
2489
+ import { DropZone, FileTrigger as FileTrigger2, isFileDropItem } from "react-aria-components";
2490
+ import { jsx as jsx55, jsxs as jsxs47 } from "react/jsx-runtime";
2491
+ var isImage2 = (file) => file.type.startsWith("image/");
2492
+ function FileDropZone({
2493
+ label,
2494
+ value,
2495
+ defaultValue,
2496
+ onChange,
2497
+ acceptedFileTypes,
2498
+ allowsMultiple,
2499
+ maxSize,
2500
+ onError,
2501
+ showPreview = true,
2502
+ uploadProgress,
2503
+ promptLabel,
2504
+ height = "regular",
2505
+ description,
2506
+ errorMessage,
2507
+ isInvalid,
2508
+ isDisabled,
2509
+ isReadOnly,
2510
+ isRequired,
2511
+ fullWidth = true,
2512
+ className,
2513
+ style
2514
+ }) {
2515
+ const msg = usePireMessages();
2516
+ const [uncontrolled, setUncontrolled] = React13.useState(defaultValue ?? []);
2517
+ const files = value ?? uncontrolled;
2518
+ const created = React13.useRef([]);
2519
+ React13.useEffect(() => () => {
2520
+ for (const url of created.current) URL.revokeObjectURL(url);
2521
+ }, []);
2522
+ const commit = (next) => {
2523
+ if (value === void 0) setUncontrolled(next);
2524
+ onChange?.(next);
2525
+ };
2526
+ const accept = (picked) => {
2527
+ if (isDisabled || isReadOnly || !picked.length) return;
2528
+ const { accepted, rejected } = screenFiles(picked, { maxSize, acceptedFileTypes });
2529
+ if (rejected.length) onError?.(rejected);
2530
+ if (!accepted.length) return;
2531
+ const wrapped = accepted.map((file) => {
2532
+ const previewUrl = showPreview && isImage2(file) ? URL.createObjectURL(file) : void 0;
2533
+ if (previewUrl) created.current.push(previewUrl);
2534
+ return { file, previewUrl };
2535
+ });
2536
+ commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
2537
+ };
2538
+ const remove = (target) => commit(files.filter((f) => f.file !== target));
2539
+ return /* @__PURE__ */ jsxs47("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), children: [
2540
+ label ? /* @__PURE__ */ jsxs47("span", { className: "pire-field-label", children: [
2541
+ label,
2542
+ isRequired ? /* @__PURE__ */ jsx55("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
2543
+ ] }) : null,
2544
+ /* @__PURE__ */ jsxs47(
2545
+ DropZone,
2546
+ {
2547
+ className: "pire-dropzone",
2548
+ "data-height": height,
2549
+ isDisabled: isDisabled || isReadOnly,
2550
+ onDrop: async (e) => {
2551
+ const dropped = await Promise.all(
2552
+ e.items.filter(isFileDropItem).map((item) => item.getFile())
2553
+ );
2554
+ accept(dropped);
2555
+ },
2556
+ children: [
2557
+ /* @__PURE__ */ jsx55(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
2558
+ /* @__PURE__ */ jsx55("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
2559
+ /* @__PURE__ */ jsx55(
2560
+ FileTrigger2,
2561
+ {
2562
+ acceptedFileTypes,
2563
+ allowsMultiple,
2564
+ onSelect: (list) => accept(list ? [...list] : []),
2565
+ children: /* @__PURE__ */ jsx55(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
2566
+ }
2567
+ )
2568
+ ]
2569
+ }
2570
+ ),
2571
+ files.length ? /* @__PURE__ */ jsx55("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs47("li", { className: "pire-fileupload-item", children: [
2572
+ previewUrl ? /* @__PURE__ */ jsx55("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx55(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
2573
+ /* @__PURE__ */ jsx55("span", { className: "pire-fileupload-name", children: file.name }),
2574
+ /* @__PURE__ */ jsx55("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
2575
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx55(
2576
+ IconButton,
2577
+ {
2578
+ icon: "x",
2579
+ size: "sm",
2580
+ label: msg.fileUploadRemoveNamed.replace("{name}", file.name),
2581
+ onPress: () => remove(file)
2582
+ }
2583
+ )
2584
+ ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
2585
+ uploadProgress != null ? /* @__PURE__ */ jsx55(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
2586
+ description ? /* @__PURE__ */ jsx55("span", { className: "pire-field-hint", children: description }) : null,
2587
+ isInvalid && errorMessage ? /* @__PURE__ */ jsx55("span", { className: "pire-field-error", children: errorMessage }) : null
2588
+ ] });
2589
+ }
2590
+
2328
2591
  // src/index.ts
2329
- import { DialogTrigger, MenuTrigger, SubmenuTrigger, Popover as Popover5, RouterProvider, I18nProvider } from "react-aria-components";
2592
+ import { DialogTrigger, MenuTrigger as MenuTrigger2, SubmenuTrigger, Popover as Popover6, RouterProvider, I18nProvider } from "react-aria-components";
2330
2593
  export {
2331
2594
  Avatar,
2332
2595
  Badge,
@@ -2342,6 +2605,8 @@ export {
2342
2605
  Dialog,
2343
2606
  DialogTrigger,
2344
2607
  EmptyState,
2608
+ FileDropZone,
2609
+ FileUpload,
2345
2610
  FilterBar,
2346
2611
  FooterBar,
2347
2612
  FormField,
@@ -2358,7 +2623,7 @@ export {
2358
2623
  MenuItem,
2359
2624
  MenuSection,
2360
2625
  MenuSeparator,
2361
- MenuTrigger,
2626
+ MenuTrigger2 as MenuTrigger,
2362
2627
  MultiComboBox,
2363
2628
  NumberField,
2364
2629
  ObjectHeader,
@@ -2366,7 +2631,7 @@ export {
2366
2631
  PageHeader,
2367
2632
  Pagination,
2368
2633
  PireIntlProvider,
2369
- Popover5 as Popover,
2634
+ Popover6 as Popover,
2370
2635
  ProgressBar,
2371
2636
  Radio,
2372
2637
  RadioGroup,
@@ -2397,6 +2662,7 @@ export {
2397
2662
  configureIcons,
2398
2663
  enMessages,
2399
2664
  esMessages,
2665
+ formatFileSize,
2400
2666
  usePireMessages,
2401
2667
  useToast
2402
2668
  };