@orianatech/pire 0.7.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.cjs CHANGED
@@ -42,13 +42,15 @@ __export(src_exports, {
42
42
  DatePicker: () => DatePicker,
43
43
  DescriptionList: () => DescriptionList,
44
44
  Dialog: () => Dialog,
45
- DialogTrigger: () => import_react_aria_components29.DialogTrigger,
45
+ DialogTrigger: () => import_react_aria_components31.DialogTrigger,
46
46
  EmptyState: () => EmptyState,
47
+ FileDropZone: () => FileDropZone,
48
+ FileUpload: () => FileUpload,
47
49
  FilterBar: () => FilterBar,
48
50
  FooterBar: () => FooterBar,
49
51
  FormField: () => FormField,
50
52
  Heading: () => Heading,
51
- I18nProvider: () => import_react_aria_components29.I18nProvider,
53
+ I18nProvider: () => import_react_aria_components31.I18nProvider,
52
54
  Icon: () => Icon,
53
55
  IconButton: () => IconButton,
54
56
  InlineMessage: () => InlineMessage,
@@ -60,7 +62,7 @@ __export(src_exports, {
60
62
  MenuItem: () => MenuItem,
61
63
  MenuSection: () => MenuSection,
62
64
  MenuSeparator: () => MenuSeparator,
63
- MenuTrigger: () => import_react_aria_components29.MenuTrigger,
65
+ MenuTrigger: () => import_react_aria_components31.MenuTrigger,
64
66
  MultiComboBox: () => MultiComboBox,
65
67
  NumberField: () => NumberField,
66
68
  ObjectHeader: () => ObjectHeader,
@@ -68,11 +70,11 @@ __export(src_exports, {
68
70
  PageHeader: () => PageHeader,
69
71
  Pagination: () => Pagination,
70
72
  PireIntlProvider: () => PireIntlProvider,
71
- Popover: () => import_react_aria_components29.Popover,
73
+ Popover: () => import_react_aria_components31.Popover,
72
74
  ProgressBar: () => ProgressBar,
73
75
  Radio: () => Radio,
74
76
  RadioGroup: () => RadioGroup,
75
- RouterProvider: () => import_react_aria_components29.RouterProvider,
77
+ RouterProvider: () => import_react_aria_components31.RouterProvider,
76
78
  SectionHeader: () => SectionHeader,
77
79
  SegmentedControl: () => SegmentedControl,
78
80
  Select: () => Select,
@@ -84,7 +86,7 @@ __export(src_exports, {
84
86
  Skeleton: () => Skeleton,
85
87
  SkeletonTableRow: () => SkeletonTableRow,
86
88
  Strong: () => Strong,
87
- SubmenuTrigger: () => import_react_aria_components29.SubmenuTrigger,
89
+ SubmenuTrigger: () => import_react_aria_components31.SubmenuTrigger,
88
90
  Switch: () => Switch,
89
91
  Tabs: () => Tabs,
90
92
  Tag: () => Tag,
@@ -99,6 +101,7 @@ __export(src_exports, {
99
101
  configureIcons: () => configureIcons,
100
102
  enMessages: () => enMessages,
101
103
  esMessages: () => esMessages,
104
+ formatFileSize: () => formatFileSize,
102
105
  usePireMessages: () => usePireMessages,
103
106
  useToast: () => useToast
104
107
  });
@@ -892,6 +895,7 @@ var enMessages = {
892
895
  toastDismiss: "Dismiss",
893
896
  toastRegionLabel: "Notifications",
894
897
  comboBoxShowSuggestions: "Show suggestions",
898
+ comboBoxLoading: "Searching\u2026",
895
899
  datePickerOpenCalendar: "Open calendar",
896
900
  datePickerPreviousMonth: "Previous month",
897
901
  datePickerNextMonth: "Next month",
@@ -908,7 +912,11 @@ var enMessages = {
908
912
  paginationPrevious: "Previous page",
909
913
  paginationNext: "Next page",
910
914
  paginationRowsPerPage: "Rows per page",
911
- sideNavLabel: "Main navigation"
915
+ sideNavLabel: "Main navigation",
916
+ fileUploadChoose: "Choose files",
917
+ fileUploadRemoveNamed: "Remove {name}",
918
+ fileUploadUploading: "Uploading",
919
+ fileDropZonePrompt: "Drag files here, or choose them"
912
920
  };
913
921
  var esMessages = {
914
922
  filterBarLabel: "Filtros",
@@ -923,6 +931,7 @@ var esMessages = {
923
931
  toastDismiss: "Descartar",
924
932
  toastRegionLabel: "Notificaciones",
925
933
  comboBoxShowSuggestions: "Mostrar sugerencias",
934
+ comboBoxLoading: "Buscando\u2026",
926
935
  datePickerOpenCalendar: "Abrir calendario",
927
936
  datePickerPreviousMonth: "Mes anterior",
928
937
  datePickerNextMonth: "Mes siguiente",
@@ -939,7 +948,11 @@ var esMessages = {
939
948
  paginationPrevious: "P\xE1gina anterior",
940
949
  paginationNext: "P\xE1gina siguiente",
941
950
  paginationRowsPerPage: "Filas por p\xE1gina",
942
- sideNavLabel: "Navegaci\xF3n principal"
951
+ sideNavLabel: "Navegaci\xF3n principal",
952
+ fileUploadChoose: "Elegir archivos",
953
+ fileUploadRemoveNamed: "Quitar {name}",
954
+ fileUploadUploading: "Subiendo",
955
+ fileDropZonePrompt: "Arrastr\xE1 archivos ac\xE1, o elegilos"
943
956
  };
944
957
 
945
958
  // src/i18n/PireIntlProvider.tsx
@@ -974,12 +987,19 @@ function ComboBox({
974
987
  errorMessage,
975
988
  size = "md",
976
989
  fullWidth = true,
990
+ isFilteredExternally,
991
+ isLoading,
992
+ loadingLabel,
993
+ emptyLabel,
994
+ onLoadMore,
977
995
  className,
978
996
  style,
979
997
  ...rest
980
998
  }) {
981
999
  const msg = usePireMessages();
982
1000
  const items = options.map(norm2);
1001
+ const collection = isFilteredExternally ? { items } : { defaultItems: items };
1002
+ const showsStatus = isLoading || isFilteredExternally && items.length === 0 && emptyLabel != null;
983
1003
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
984
1004
  import_react_aria_components15.ComboBox,
985
1005
  {
@@ -987,9 +1007,13 @@ function ComboBox({
987
1007
  style,
988
1008
  selectedKey: value,
989
1009
  defaultSelectedKey: defaultValue,
990
- onSelectionChange: (k) => onChange?.(k == null ? null : String(k)),
1010
+ onSelectionChange: (k) => {
1011
+ if (isLoading) return;
1012
+ onChange?.(k == null ? null : String(k));
1013
+ },
991
1014
  onInputChange,
992
- defaultItems: items,
1015
+ ...collection,
1016
+ allowsEmptyCollection: isFilteredExternally || isLoading,
993
1017
  menuTrigger: "input",
994
1018
  validationBehavior: "aria",
995
1019
  ...rest,
@@ -1014,10 +1038,21 @@ function ComboBox({
1014
1038
  ),
1015
1039
  description ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_aria_components15.Text, { slot: "description", className: "pire-field-hint", children: description }) : null,
1016
1040
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_aria_components15.FieldError, { className: "pire-field-error", children: errorMessage }),
1017
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_aria_components15.Popover, { className: "pire-popover", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_aria_components15.ListBox, { className: "pire-listbox", children: (item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_aria_components15.ListBoxItem, { className: "pire-option", id: item.value, textValue: item.label, isDisabled: item.isDisabled, children: [
1018
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { flex: 1 }, children: item.label }),
1019
- item.secondary ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { font: "var(--type-code)", color: "var(--text-tertiary)" }, children: item.secondary }) : null
1020
- ] }) }) })
1041
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_aria_components15.Popover, { className: "pire-popover", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1042
+ import_react_aria_components15.ListBox,
1043
+ {
1044
+ className: "pire-listbox",
1045
+ onScroll: onLoadMore ? (e) => {
1046
+ const el = e.currentTarget;
1047
+ if (el.scrollHeight - el.scrollTop - el.clientHeight < 48) onLoadMore();
1048
+ } : void 0,
1049
+ renderEmptyState: showsStatus ? () => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "pire-listbox-status", role: "status", "aria-live": "polite", children: isLoading ? loadingLabel ?? msg.comboBoxLoading : emptyLabel }) : void 0,
1050
+ children: (item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_aria_components15.ListBoxItem, { className: "pire-option", id: item.value, textValue: item.label, isDisabled: item.isDisabled, children: [
1051
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "pire-option-label", children: item.label }),
1052
+ item.secondary ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "pire-option-secondary", children: item.secondary }) : null
1053
+ ] })
1054
+ }
1055
+ ) })
1021
1056
  ]
1022
1057
  }
1023
1058
  );
@@ -1039,6 +1074,11 @@ function MultiComboBox({
1039
1074
  errorMessage,
1040
1075
  allowsCustomValue,
1041
1076
  size = "md",
1077
+ isFilteredExternally,
1078
+ isLoading,
1079
+ loadingLabel,
1080
+ emptyLabel,
1081
+ onLoadMore,
1042
1082
  fullWidth = true,
1043
1083
  className,
1044
1084
  style,
@@ -1046,6 +1086,8 @@ function MultiComboBox({
1046
1086
  }) {
1047
1087
  const msg = usePireMessages();
1048
1088
  const items = React7.useMemo(() => options.map(norm3), [options]);
1089
+ const collection = isFilteredExternally ? { items } : { defaultItems: items };
1090
+ const showsStatus = isLoading || isFilteredExternally && items.length === 0 && emptyLabel != null;
1049
1091
  const [uncontrolled, setUncontrolled] = React7.useState(defaultValue ?? []);
1050
1092
  const [announcement, setAnnouncement] = React7.useState("");
1051
1093
  const inputRef = React7.useRef(null);
@@ -1091,9 +1133,12 @@ function MultiComboBox({
1091
1133
  style,
1092
1134
  selectionMode: "multiple",
1093
1135
  value: values,
1094
- onChange: (keys) => commit(keys.map(String)),
1136
+ onChange: (keys) => {
1137
+ if (!isLoading) commit(keys.map(String));
1138
+ },
1095
1139
  onInputChange,
1096
- defaultItems: items,
1140
+ ...collection,
1141
+ allowsEmptyCollection: isFilteredExternally || isLoading,
1097
1142
  menuTrigger: "input",
1098
1143
  validationBehavior: "aria",
1099
1144
  ...rest,
@@ -1136,10 +1181,21 @@ function MultiComboBox({
1136
1181
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_aria_components16.VisuallyHidden, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { "aria-live": "polite", children: announcement }) }),
1137
1182
  description ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_aria_components16.Text, { slot: "description", className: "pire-field-hint", children: description }) : null,
1138
1183
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_aria_components16.FieldError, { className: "pire-field-error", children: errorMessage }),
1139
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_aria_components16.Popover, { className: "pire-popover", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_aria_components16.ListBox, { className: "pire-listbox", children: (item) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react_aria_components16.ListBoxItem, { className: "pire-option", id: item.value, textValue: item.label, isDisabled: item.isDisabled, children: [
1140
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { flex: 1 }, children: item.label }),
1141
- item.secondary ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { font: "var(--type-code)", color: "var(--text-tertiary)" }, children: item.secondary }) : null
1142
- ] }) }) })
1184
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_aria_components16.Popover, { className: "pire-popover", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1185
+ import_react_aria_components16.ListBox,
1186
+ {
1187
+ className: "pire-listbox",
1188
+ onScroll: onLoadMore ? (e) => {
1189
+ const el = e.currentTarget;
1190
+ if (el.scrollHeight - el.scrollTop - el.clientHeight < 48) onLoadMore();
1191
+ } : void 0,
1192
+ renderEmptyState: showsStatus ? () => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "pire-listbox-status", role: "status", "aria-live": "polite", children: isLoading ? loadingLabel ?? msg.comboBoxLoading : emptyLabel }) : void 0,
1193
+ children: (item) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react_aria_components16.ListBoxItem, { className: "pire-option", id: item.value, textValue: item.label, isDisabled: item.isDisabled, children: [
1194
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "pire-option-label", children: item.label }),
1195
+ item.secondary ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "pire-option-secondary", children: item.secondary }) : null
1196
+ ] })
1197
+ }
1198
+ ) })
1143
1199
  ]
1144
1200
  }
1145
1201
  );
@@ -1584,8 +1640,165 @@ function ValueHelpField({
1584
1640
  ] });
1585
1641
  }
1586
1642
 
1587
- // src/components/navigation/ShellBar.tsx
1643
+ // src/components/forms/FileUpload.tsx
1644
+ var React10 = __toESM(require("react"), 1);
1645
+ var import_react_aria_components22 = require("react-aria-components");
1646
+
1647
+ // src/components/feedback/ProgressBar.tsx
1648
+ var import_react_aria_components21 = require("react-aria-components");
1588
1649
  var import_jsx_runtime31 = require("react/jsx-runtime");
1650
+ function ProgressBar({
1651
+ value = 0,
1652
+ minValue = 0,
1653
+ maxValue = 100,
1654
+ label,
1655
+ showValue = true,
1656
+ isIndeterminate,
1657
+ status = "informative",
1658
+ size = "md",
1659
+ className,
1660
+ style
1661
+ }) {
1662
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
1663
+ import_react_aria_components21.ProgressBar,
1664
+ {
1665
+ className: cx("pire-progress", className),
1666
+ "data-status": status,
1667
+ "data-size": size,
1668
+ value,
1669
+ minValue,
1670
+ maxValue,
1671
+ isIndeterminate,
1672
+ style,
1673
+ children: ({ percentage, valueText }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
1674
+ label || showValue ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "pire-progress-head", children: [
1675
+ label ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react_aria_components21.Label, { children: label }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", {}),
1676
+ showValue && !isIndeterminate ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "pire-numeric", children: valueText }) : null
1677
+ ] }) : null,
1678
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pire-progress-track", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pire-progress-fill", style: { width: `${isIndeterminate ? 40 : percentage}%` } }) })
1679
+ ] })
1680
+ }
1681
+ );
1682
+ }
1683
+
1684
+ // src/components/forms/FileUpload.tsx
1685
+ var import_jsx_runtime32 = require("react/jsx-runtime");
1686
+ var isImage = (file) => file.type.startsWith("image/");
1687
+ function formatFileSize(bytes) {
1688
+ if (bytes < 1024) return `${bytes} B`;
1689
+ if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024).toLocaleString()} KB`;
1690
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1691
+ }
1692
+ function screenFiles(files, { maxSize, acceptedFileTypes }) {
1693
+ const accepted = [];
1694
+ const rejected = [];
1695
+ for (const file of files) {
1696
+ if (maxSize != null && file.size > maxSize) {
1697
+ rejected.push({ file, reason: "size" });
1698
+ continue;
1699
+ }
1700
+ if (acceptedFileTypes?.length) {
1701
+ 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);
1702
+ if (!ok) {
1703
+ rejected.push({ file, reason: "type" });
1704
+ continue;
1705
+ }
1706
+ }
1707
+ accepted.push(file);
1708
+ }
1709
+ return { accepted, rejected };
1710
+ }
1711
+ function FileUpload({
1712
+ label,
1713
+ value,
1714
+ defaultValue,
1715
+ onChange,
1716
+ acceptedFileTypes,
1717
+ allowsMultiple,
1718
+ maxSize,
1719
+ onError,
1720
+ showPreview = true,
1721
+ uploadProgress,
1722
+ chooseLabel,
1723
+ description,
1724
+ errorMessage,
1725
+ isInvalid,
1726
+ isDisabled,
1727
+ isReadOnly,
1728
+ isRequired,
1729
+ fullWidth = true,
1730
+ className,
1731
+ style
1732
+ }) {
1733
+ const msg = usePireMessages();
1734
+ const [uncontrolled, setUncontrolled] = React10.useState(defaultValue ?? []);
1735
+ const files = value ?? uncontrolled;
1736
+ const created = React10.useRef([]);
1737
+ React10.useEffect(() => () => {
1738
+ for (const url of created.current) URL.revokeObjectURL(url);
1739
+ }, []);
1740
+ const commit = (next) => {
1741
+ if (value === void 0) setUncontrolled(next);
1742
+ onChange?.(next);
1743
+ };
1744
+ const accept = (picked) => {
1745
+ if (!picked || isDisabled || isReadOnly) return;
1746
+ const { accepted, rejected } = screenFiles([...picked], { maxSize, acceptedFileTypes });
1747
+ if (rejected.length) onError?.(rejected);
1748
+ if (!accepted.length) return;
1749
+ const wrapped = accepted.map((file) => {
1750
+ const previewUrl = showPreview && isImage(file) ? URL.createObjectURL(file) : void 0;
1751
+ if (previewUrl) created.current.push(previewUrl);
1752
+ return { file, previewUrl };
1753
+ });
1754
+ commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
1755
+ };
1756
+ const remove = (target) => commit(files.filter((f) => f.file !== target));
1757
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1758
+ "div",
1759
+ {
1760
+ className: cx("pire-field", "pire-fileupload", className),
1761
+ style,
1762
+ "data-full-width": String(fullWidth),
1763
+ "data-invalid": isInvalid ? "true" : void 0,
1764
+ children: [
1765
+ label ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "pire-field-label", children: [
1766
+ label,
1767
+ isRequired ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
1768
+ ] }) : null,
1769
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1770
+ import_react_aria_components22.FileTrigger,
1771
+ {
1772
+ acceptedFileTypes,
1773
+ allowsMultiple,
1774
+ onSelect: accept,
1775
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Button, { icon: "paperclip", isDisabled: isDisabled || isReadOnly, children: chooseLabel ?? msg.fileUploadChoose })
1776
+ }
1777
+ ),
1778
+ files.length ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("li", { className: "pire-fileupload-item", children: [
1779
+ previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
1780
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "pire-fileupload-name", children: file.name }),
1781
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
1782
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1783
+ IconButton,
1784
+ {
1785
+ icon: "x",
1786
+ size: "sm",
1787
+ label: msg.fileUploadRemoveNamed.replace("{name}", file.name),
1788
+ onPress: () => remove(file)
1789
+ }
1790
+ )
1791
+ ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
1792
+ uploadProgress != null ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
1793
+ description ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_aria_components22.Text, { slot: "description", className: "pire-field-hint", children: description }) : null,
1794
+ isInvalid && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "pire-field-error", children: errorMessage }) : null
1795
+ ]
1796
+ }
1797
+ );
1798
+ }
1799
+
1800
+ // src/components/navigation/ShellBar.tsx
1801
+ var import_jsx_runtime33 = require("react/jsx-runtime");
1589
1802
  var initials2 = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
1590
1803
  function ShellBar({
1591
1804
  product,
@@ -1600,22 +1813,75 @@ function ShellBar({
1600
1813
  className,
1601
1814
  ...rest
1602
1815
  }) {
1603
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("header", { className: cx("pire-shellbar", className), ...rest, children: [
1604
- onMenu ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
1605
- monogram ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
1606
- product ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "pire-shellbar-product", children: product }) : null,
1607
- title ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "pire-shellbar-title", children: title }) : null,
1608
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "pire-shellbar-spacer" }),
1609
- onSearch ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(IconButton, { icon: "search", label: searchLabel, variant: "inverse", size: "sm", onPress: onSearch }) : null,
1816
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("header", { className: cx("pire-shellbar", className), ...rest, children: [
1817
+ onMenu ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
1818
+ monogram ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
1819
+ product ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "pire-shellbar-product", children: product }) : null,
1820
+ title ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "pire-shellbar-title", children: title }) : null,
1821
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "pire-shellbar-spacer" }),
1822
+ onSearch ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(IconButton, { icon: "search", label: searchLabel, variant: "inverse", size: "sm", onPress: onSearch }) : null,
1610
1823
  actions,
1611
- user ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "pire-avatar", title: user, "aria-label": user, role: "img", children: initials2(user) }) : null
1824
+ user ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "pire-avatar", title: user, "aria-label": user, role: "img", children: initials2(user) }) : null
1612
1825
  ] });
1613
1826
  }
1614
1827
 
1615
1828
  // src/components/navigation/SideNav.tsx
1616
- var React10 = __toESM(require("react"), 1);
1617
- var import_react_aria_components21 = require("react-aria-components");
1618
- var import_jsx_runtime32 = require("react/jsx-runtime");
1829
+ var React11 = __toESM(require("react"), 1);
1830
+ var import_react_aria_components24 = require("react-aria-components");
1831
+
1832
+ // src/components/navigation/Menu.tsx
1833
+ var import_react_aria_components23 = require("react-aria-components");
1834
+ var import_jsx_runtime34 = require("react/jsx-runtime");
1835
+ function Menu({ minWidth, className, style, ...rest }) {
1836
+ const width = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
1837
+ const menuStyle = width == null ? style : { ["--pire-menu-min-w"]: width, ...style };
1838
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1839
+ import_react_aria_components23.Menu,
1840
+ {
1841
+ className: cx("pire-menu", className),
1842
+ style: menuStyle,
1843
+ ...rest
1844
+ }
1845
+ );
1846
+ }
1847
+ function MenuItem({
1848
+ children,
1849
+ icon,
1850
+ description,
1851
+ shortcut,
1852
+ tone = "default",
1853
+ className,
1854
+ ...rest
1855
+ }) {
1856
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
1857
+ import_react_aria_components23.MenuItem,
1858
+ {
1859
+ className: cx("pire-menu-item", className),
1860
+ "data-tone": tone === "danger" ? "danger" : void 0,
1861
+ ...rest,
1862
+ children: [
1863
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Icon, { name: icon, size: 16, className: "pire-menu-item-icon" }) : null,
1864
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "pire-menu-item-body", children: [
1865
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "pire-menu-item-label", children }),
1866
+ description ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "pire-menu-item-desc", children: description }) : null
1867
+ ] }),
1868
+ shortcut ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("kbd", { className: "pire-menu-item-shortcut", children: shortcut }) : null
1869
+ ]
1870
+ }
1871
+ );
1872
+ }
1873
+ function MenuSection({ title, children, className, ...rest }) {
1874
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_aria_components23.MenuSection, { className: cx("pire-menu-section", className), ...rest, children: [
1875
+ title ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_aria_components23.Header, { className: "pire-menu-section-title", children: title }) : null,
1876
+ children
1877
+ ] });
1878
+ }
1879
+ function MenuSeparator({ className }) {
1880
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_aria_components23.Separator, { className: cx("pire-menu-separator", className) });
1881
+ }
1882
+
1883
+ // src/components/navigation/SideNav.tsx
1884
+ var import_jsx_runtime35 = require("react/jsx-runtime");
1619
1885
  function findActiveParent(groups, value) {
1620
1886
  if (value == null) return void 0;
1621
1887
  for (const group of groups) {
@@ -1633,6 +1899,7 @@ function SideNav({
1633
1899
  defaultExpandedIds,
1634
1900
  onExpandedChange,
1635
1901
  collapsed,
1902
+ railFlyout = true,
1636
1903
  footer,
1637
1904
  className,
1638
1905
  ...rest
@@ -1640,10 +1907,10 @@ function SideNav({
1640
1907
  const msg = usePireMessages();
1641
1908
  const activeParent = findActiveParent(groups, value);
1642
1909
  const isControlled = expandedIds != null;
1643
- const [ownExpanded, setOwnExpanded] = React10.useState(
1910
+ const [ownExpanded, setOwnExpanded] = React11.useState(
1644
1911
  () => new Set(defaultExpandedIds ?? (activeParent ? [activeParent] : []))
1645
1912
  );
1646
- const [lastValue, setLastValue] = React10.useState(value);
1913
+ const [lastValue, setLastValue] = React11.useState(value);
1647
1914
  if (value !== lastValue) {
1648
1915
  setLastValue(value);
1649
1916
  if (!isControlled && activeParent && !ownExpanded.has(activeParent)) {
@@ -1663,8 +1930,8 @@ function SideNav({
1663
1930
  };
1664
1931
  const renderRow = (item, onPress, isGroup) => {
1665
1932
  const selected = !isGroup && item.id === value;
1666
- const button = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1667
- import_react_aria_components21.Button,
1933
+ const button = /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
1934
+ import_react_aria_components24.Button,
1668
1935
  {
1669
1936
  className: "pire-sidenav-item",
1670
1937
  "data-selected": selected ? "true" : void 0,
@@ -1673,50 +1940,70 @@ function SideNav({
1673
1940
  "aria-label": collapsed ? item.label : void 0,
1674
1941
  onPress,
1675
1942
  children: [
1676
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Icon, { name: item.icon, size: 16 }) : null,
1677
- collapsed ? null : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: item.label }),
1678
- item.count != null && !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "pire-sidenav-count", children: item.count }) : null
1943
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Icon, { name: item.icon, size: 16 }) : null,
1944
+ collapsed ? null : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: item.label }),
1945
+ item.count != null && !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "pire-sidenav-count", children: item.count }) : null
1679
1946
  ]
1680
1947
  },
1681
1948
  item.id
1682
1949
  );
1683
- return collapsed ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Tooltip, { label: item.label, placement: "right", children: button }, item.id) : button;
1950
+ return collapsed ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Tooltip, { label: item.label, placement: "right", children: button }, item.id) : button;
1684
1951
  };
1685
- const renderSection = (item) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react_aria_components21.Disclosure, { id: item.id, className: "pire-sidenav-section", children: [
1686
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1687
- import_react_aria_components21.Button,
1952
+ const renderRailFlyout = (item) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_react_aria_components24.MenuTrigger, { children: [
1953
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1954
+ import_react_aria_components24.Button,
1955
+ {
1956
+ className: "pire-sidenav-item",
1957
+ "aria-label": item.label,
1958
+ "data-active-child": item.id === activeParent ? "true" : void 0,
1959
+ children: item.icon ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Icon, { name: item.icon, size: 16 }) : null
1960
+ }
1961
+ ),
1962
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react_aria_components24.Popover, { className: "pire-popover", placement: "right top", offset: 4, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1963
+ Menu,
1964
+ {
1965
+ "aria-label": item.label,
1966
+ className: "pire-sidenav-flyout",
1967
+ onAction: (key) => onChange?.(String(key)),
1968
+ children: (item.items ?? []).map((child) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(MenuItem, { id: child.id, children: child.label }, child.id))
1969
+ }
1970
+ ) })
1971
+ ] }, item.id);
1972
+ const renderSection = (item) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_react_aria_components24.Disclosure, { id: item.id, className: "pire-sidenav-section", children: [
1973
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
1974
+ import_react_aria_components24.Button,
1688
1975
  {
1689
1976
  slot: "trigger",
1690
1977
  className: "pire-sidenav-item",
1691
1978
  "data-kind": "group",
1692
1979
  "data-active-child": item.id === activeParent ? "true" : void 0,
1693
1980
  children: [
1694
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Icon, { name: item.icon, size: 16 }) : null,
1695
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: item.label }),
1696
- item.count != null ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "pire-sidenav-count", children: item.count }) : null,
1697
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Icon, { name: "chevron-down", size: 16, className: "pire-sidenav-chevron" })
1981
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Icon, { name: item.icon, size: 16 }) : null,
1982
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: item.label }),
1983
+ item.count != null ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "pire-sidenav-count", children: item.count }) : null,
1984
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Icon, { name: "chevron-down", size: 16, className: "pire-sidenav-chevron" })
1698
1985
  ]
1699
1986
  }
1700
1987
  ),
1701
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_aria_components21.DisclosurePanel, { className: "pire-sidenav-subnav", children: item.items?.map((child) => {
1988
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react_aria_components24.DisclosurePanel, { className: "pire-sidenav-subnav", children: item.items?.map((child) => {
1702
1989
  const selected = child.id === value;
1703
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1704
- import_react_aria_components21.Button,
1990
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
1991
+ import_react_aria_components24.Button,
1705
1992
  {
1706
1993
  className: "pire-sidenav-item pire-sidenav-subitem",
1707
1994
  "data-selected": selected ? "true" : void 0,
1708
1995
  "aria-current": selected ? "page" : void 0,
1709
1996
  onPress: () => onChange?.(child.id),
1710
1997
  children: [
1711
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: child.label }),
1712
- child.count != null ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "pire-sidenav-count", children: child.count }) : null
1998
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: child.label }),
1999
+ child.count != null ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "pire-sidenav-count", children: child.count }) : null
1713
2000
  ]
1714
2001
  },
1715
2002
  child.id
1716
2003
  );
1717
2004
  }) })
1718
2005
  ] }, item.id);
1719
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
2006
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
1720
2007
  "nav",
1721
2008
  {
1722
2009
  className: cx("pire-sidenav", className),
@@ -1729,12 +2016,13 @@ function SideNav({
1729
2016
  const rows = group.items.map((item) => {
1730
2017
  const isGroup = Boolean(item.items?.length);
1731
2018
  if (isGroup && !collapsed) return renderSection(item);
2019
+ if (isGroup && collapsed && railFlyout) return renderRailFlyout(item);
1732
2020
  return renderRow(item, () => isGroup ? toggleExpanded(item.id) : onChange?.(item.id), isGroup);
1733
2021
  });
1734
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "pire-sidenav-group", children: [
1735
- group.label && !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "pire-sidenav-label", children: group.label }) : null,
1736
- hasSections ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1737
- import_react_aria_components21.DisclosureGroup,
2022
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "pire-sidenav-group", children: [
2023
+ group.label && !collapsed ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "pire-sidenav-label", children: group.label }) : null,
2024
+ hasSections ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2025
+ import_react_aria_components24.DisclosureGroup,
1738
2026
  {
1739
2027
  className: "pire-sidenav-tree",
1740
2028
  allowsMultipleExpanded: true,
@@ -1745,18 +2033,18 @@ function SideNav({
1745
2033
  ) : rows
1746
2034
  ] }, group.label ?? gi);
1747
2035
  }),
1748
- footer ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "pire-sidenav-footer", children: footer }) : null
2036
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "pire-sidenav-footer", children: footer }) : null
1749
2037
  ]
1750
2038
  }
1751
2039
  );
1752
2040
  }
1753
2041
 
1754
2042
  // src/components/navigation/Tabs.tsx
1755
- var import_react_aria_components22 = require("react-aria-components");
1756
- var import_jsx_runtime33 = require("react/jsx-runtime");
2043
+ var import_react_aria_components25 = require("react-aria-components");
2044
+ var import_jsx_runtime36 = require("react/jsx-runtime");
1757
2045
  function Tabs({ items, value, defaultValue, onChange, panels, className, style, ...rest }) {
1758
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
1759
- import_react_aria_components22.Tabs,
2046
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
2047
+ import_react_aria_components25.Tabs,
1760
2048
  {
1761
2049
  className,
1762
2050
  style,
@@ -1764,23 +2052,23 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
1764
2052
  defaultSelectedKey: defaultValue,
1765
2053
  onSelectionChange: (k) => onChange?.(String(k)),
1766
2054
  children: [
1767
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react_aria_components22.TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react_aria_components22.Tab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
1768
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Icon, { name: item.icon, size: 16 }) : null,
2055
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_aria_components25.TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_aria_components25.Tab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
2056
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Icon, { name: item.icon, size: 16 }) : null,
1769
2057
  item.label,
1770
- item.count != null ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "pire-tab-count", children: item.count }) : null
2058
+ item.count != null ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "pire-tab-count", children: item.count }) : null
1771
2059
  ] }) }),
1772
- items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react_aria_components22.TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2060
+ items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_aria_components25.TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
1773
2061
  ]
1774
2062
  }
1775
2063
  );
1776
2064
  }
1777
2065
 
1778
2066
  // src/components/navigation/Breadcrumb.tsx
1779
- var import_react_aria_components23 = require("react-aria-components");
1780
- var import_jsx_runtime34 = require("react/jsx-runtime");
2067
+ var import_react_aria_components26 = require("react-aria-components");
2068
+ var import_jsx_runtime37 = require("react/jsx-runtime");
1781
2069
  function Breadcrumb({ items, onNavigate, className, style }) {
1782
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1783
- import_react_aria_components23.Breadcrumbs,
2070
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2071
+ import_react_aria_components26.Breadcrumbs,
1784
2072
  {
1785
2073
  className: cx("pire-breadcrumbs", className),
1786
2074
  style,
@@ -1788,9 +2076,9 @@ function Breadcrumb({ items, onNavigate, className, style }) {
1788
2076
  onAction: (key) => onNavigate?.(String(key)),
1789
2077
  children: (item) => {
1790
2078
  const last = items[items.length - 1] === item;
1791
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react_aria_components23.Breadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
1792
- last ? item.label : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_aria_components23.Link, { href: item.href, children: item.label }),
1793
- last ? null : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
2079
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react_aria_components26.Breadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
2080
+ last ? item.label : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_aria_components26.Link, { href: item.href, children: item.label }),
2081
+ last ? null : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
1794
2082
  ] });
1795
2083
  }
1796
2084
  }
@@ -1798,7 +2086,7 @@ function Breadcrumb({ items, onNavigate, className, style }) {
1798
2086
  }
1799
2087
 
1800
2088
  // src/components/navigation/Pagination.tsx
1801
- var import_jsx_runtime35 = require("react/jsx-runtime");
2089
+ var import_jsx_runtime38 = require("react/jsx-runtime");
1802
2090
  function Pagination({
1803
2091
  page = 1,
1804
2092
  pageSize = 25,
@@ -1813,9 +2101,9 @@ function Pagination({
1813
2101
  const pages = Math.max(1, Math.ceil(total / pageSize));
1814
2102
  const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
1815
2103
  const to = Math.min(total, page * pageSize);
1816
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
1817
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
1818
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2104
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
2105
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
2106
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1819
2107
  IconButton,
1820
2108
  {
1821
2109
  icon: "chevron-left",
@@ -1826,8 +2114,8 @@ function Pagination({
1826
2114
  onPress: () => onPageChange?.(page - 1)
1827
2115
  }
1828
2116
  ),
1829
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
1830
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2117
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
2118
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1831
2119
  IconButton,
1832
2120
  {
1833
2121
  icon: "chevron-right",
@@ -1838,7 +2126,7 @@ function Pagination({
1838
2126
  onPress: () => onPageChange?.(page + 1)
1839
2127
  }
1840
2128
  ),
1841
- onPageSizeChange ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2129
+ onPageSizeChange ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1842
2130
  Select,
1843
2131
  {
1844
2132
  "aria-label": msg.paginationRowsPerPage,
@@ -1853,59 +2141,8 @@ function Pagination({
1853
2141
  ] });
1854
2142
  }
1855
2143
 
1856
- // src/components/navigation/Menu.tsx
1857
- var import_react_aria_components24 = require("react-aria-components");
1858
- var import_jsx_runtime36 = require("react/jsx-runtime");
1859
- function Menu({ minWidth, className, style, ...rest }) {
1860
- const width = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
1861
- const menuStyle = width == null ? style : { ["--pire-menu-min-w"]: width, ...style };
1862
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1863
- import_react_aria_components24.Menu,
1864
- {
1865
- className: cx("pire-menu", className),
1866
- style: menuStyle,
1867
- ...rest
1868
- }
1869
- );
1870
- }
1871
- function MenuItem({
1872
- children,
1873
- icon,
1874
- description,
1875
- shortcut,
1876
- tone = "default",
1877
- className,
1878
- ...rest
1879
- }) {
1880
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
1881
- import_react_aria_components24.MenuItem,
1882
- {
1883
- className: cx("pire-menu-item", className),
1884
- "data-tone": tone === "danger" ? "danger" : void 0,
1885
- ...rest,
1886
- children: [
1887
- icon ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Icon, { name: icon, size: 16, className: "pire-menu-item-icon" }) : null,
1888
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "pire-menu-item-body", children: [
1889
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "pire-menu-item-label", children }),
1890
- description ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "pire-menu-item-desc", children: description }) : null
1891
- ] }),
1892
- shortcut ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("kbd", { className: "pire-menu-item-shortcut", children: shortcut }) : null
1893
- ]
1894
- }
1895
- );
1896
- }
1897
- function MenuSection({ title, children, className, ...rest }) {
1898
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react_aria_components24.MenuSection, { className: cx("pire-menu-section", className), ...rest, children: [
1899
- title ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_aria_components24.Header, { className: "pire-menu-section-title", children: title }) : null,
1900
- children
1901
- ] });
1902
- }
1903
- function MenuSeparator({ className }) {
1904
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react_aria_components24.Separator, { className: cx("pire-menu-separator", className) });
1905
- }
1906
-
1907
2144
  // src/components/feedback/InlineMessage.tsx
1908
- var import_jsx_runtime37 = require("react/jsx-runtime");
2145
+ var import_jsx_runtime39 = require("react/jsx-runtime");
1909
2146
  var KIND_ICON = {
1910
2147
  info: "info",
1911
2148
  success: "check-circle-2",
@@ -1915,7 +2152,7 @@ var KIND_ICON = {
1915
2152
  function InlineMessage({ kind = "info", title, action, onClose, children, className, ...rest }) {
1916
2153
  const msg = usePireMessages();
1917
2154
  const assertive = kind === "error" || kind === "warning";
1918
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
2155
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
1919
2156
  "div",
1920
2157
  {
1921
2158
  className: cx("pire-msg", className),
@@ -1924,58 +2161,21 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
1924
2161
  "aria-live": assertive ? "assertive" : "polite",
1925
2162
  ...rest,
1926
2163
  children: [
1927
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
1928
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
1929
- title ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "pire-msg-title", children: title }) : null,
1930
- children ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "pire-msg-body", children }) : null,
2164
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
2165
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
2166
+ title ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "pire-msg-title", children: title }) : null,
2167
+ children ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "pire-msg-body", children }) : null,
1931
2168
  action
1932
2169
  ] }),
1933
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
2170
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
1934
2171
  ]
1935
2172
  }
1936
2173
  );
1937
2174
  }
1938
2175
 
1939
- // src/components/feedback/ProgressBar.tsx
1940
- var import_react_aria_components25 = require("react-aria-components");
1941
- var import_jsx_runtime38 = require("react/jsx-runtime");
1942
- function ProgressBar({
1943
- value = 0,
1944
- minValue = 0,
1945
- maxValue = 100,
1946
- label,
1947
- showValue = true,
1948
- isIndeterminate,
1949
- status = "informative",
1950
- size = "md",
1951
- className,
1952
- style
1953
- }) {
1954
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1955
- import_react_aria_components25.ProgressBar,
1956
- {
1957
- className: cx("pire-progress", className),
1958
- "data-status": status,
1959
- "data-size": size,
1960
- value,
1961
- minValue,
1962
- maxValue,
1963
- isIndeterminate,
1964
- style,
1965
- children: ({ percentage, valueText }) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
1966
- label || showValue ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "pire-progress-head", children: [
1967
- label ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_aria_components25.Label, { children: label }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", {}),
1968
- showValue && !isIndeterminate ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "pire-numeric", children: valueText }) : null
1969
- ] }) : null,
1970
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "pire-progress-track", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "pire-progress-fill", style: { width: `${isIndeterminate ? 40 : percentage}%` } }) })
1971
- ] })
1972
- }
1973
- );
1974
- }
1975
-
1976
2176
  // src/components/feedback/Toast.tsx
1977
- var React11 = __toESM(require("react"), 1);
1978
- var import_jsx_runtime39 = require("react/jsx-runtime");
2177
+ var React12 = __toESM(require("react"), 1);
2178
+ var import_jsx_runtime40 = require("react/jsx-runtime");
1979
2179
  var KIND_ICON2 = {
1980
2180
  info: "info",
1981
2181
  success: "check-circle-2",
@@ -1984,7 +2184,7 @@ var KIND_ICON2 = {
1984
2184
  };
1985
2185
  function Toast({ kind = "success", onClose, position = "bottom-center", children, className, ...rest }) {
1986
2186
  const msg = usePireMessages();
1987
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
2187
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
1988
2188
  "div",
1989
2189
  {
1990
2190
  className: cx("pire-toast", className),
@@ -1993,40 +2193,40 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
1993
2193
  "aria-live": kind === "error" ? "assertive" : "polite",
1994
2194
  ...rest,
1995
2195
  children: [
1996
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Icon, { name: KIND_ICON2[kind], size: 16 }),
1997
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { style: { flex: 1 }, children }),
1998
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
2196
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Icon, { name: KIND_ICON2[kind], size: 16 }),
2197
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { style: { flex: 1 }, children }),
2198
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
1999
2199
  ]
2000
2200
  }
2001
2201
  );
2002
2202
  }
2003
- var ToastContext = React11.createContext(null);
2203
+ var ToastContext = React12.createContext(null);
2004
2204
  function ToastProvider({ children, timeout = 6e3 }) {
2005
2205
  const msg = usePireMessages();
2006
- const [toasts, setToasts] = React11.useState([]);
2007
- const close = React11.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2008
- const add = React11.useCallback((toast) => {
2206
+ const [toasts, setToasts] = React12.useState([]);
2207
+ const close = React12.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2208
+ const add = React12.useCallback((toast) => {
2009
2209
  const id = Math.random().toString(36).slice(2);
2010
2210
  setToasts((t) => [...t, { ...toast, id }]);
2011
2211
  const ms = toast.timeout ?? timeout;
2012
2212
  if (ms > 0) setTimeout(() => close(id), ms);
2013
2213
  return id;
2014
2214
  }, [close, timeout]);
2015
- const value = React11.useMemo(() => ({ add, close }), [add, close]);
2016
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(ToastContext.Provider, { value, children: [
2215
+ const value = React12.useMemo(() => ({ add, close }), [add, close]);
2216
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(ToastContext.Provider, { value, children: [
2017
2217
  children,
2018
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
2218
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
2019
2219
  ] });
2020
2220
  }
2021
2221
  function useToast() {
2022
- const ctx = React11.useContext(ToastContext);
2222
+ const ctx = React12.useContext(ToastContext);
2023
2223
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
2024
2224
  return ctx;
2025
2225
  }
2026
2226
 
2027
2227
  // src/components/data/KpiTile.tsx
2028
- var import_react_aria_components26 = require("react-aria-components");
2029
- var import_jsx_runtime40 = require("react/jsx-runtime");
2228
+ var import_react_aria_components27 = require("react-aria-components");
2229
+ var import_jsx_runtime41 = require("react/jsx-runtime");
2030
2230
  function KpiTile({
2031
2231
  label,
2032
2232
  value,
@@ -2042,50 +2242,50 @@ function KpiTile({
2042
2242
  style
2043
2243
  }) {
2044
2244
  const tone = deltaTone ?? (deltaDirection === "down" ? "negative" : "positive");
2045
- const body = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
2046
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "pire-kpi-label", children: [
2047
- icon ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Icon, { name: icon, size: 16 }) : null,
2245
+ const body = /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
2246
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "pire-kpi-label", children: [
2247
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Icon, { name: icon, size: 16 }) : null,
2048
2248
  label
2049
2249
  ] }),
2050
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "pire-kpi-value", children: [
2250
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "pire-kpi-value", children: [
2051
2251
  value,
2052
- unit ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "pire-kpi-unit", children: unit }) : null
2252
+ unit ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "pire-kpi-unit", children: unit }) : null
2053
2253
  ] }),
2054
- delta ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
2055
- deltaDirection ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
2254
+ delta ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
2255
+ deltaDirection ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
2056
2256
  delta
2057
2257
  ] }) : null,
2058
- footnote ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "pire-kpi-foot", children: footnote }) : null
2258
+ footnote ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "pire-kpi-foot", children: footnote }) : null
2059
2259
  ] });
2060
2260
  const props = { className: cx("pire-kpi", className), "data-status": status, style };
2061
- return onPress ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_aria_components26.Button, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { ...props, children: body });
2261
+ return onPress ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react_aria_components27.Button, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { ...props, children: body });
2062
2262
  }
2063
2263
 
2064
2264
  // src/components/data/ObjectHeader.tsx
2065
- var import_jsx_runtime41 = require("react/jsx-runtime");
2265
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2066
2266
  function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions, className, ...rest }) {
2067
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("header", { className: cx("pire-objheader", className), ...rest, children: [
2267
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("header", { className: cx("pire-objheader", className), ...rest, children: [
2068
2268
  breadcrumb,
2069
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "pire-objheader-row", children: [
2070
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { minWidth: 0 }, children: [
2071
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h1", { className: "pire-objheader-title", children: title }),
2072
- subtitle || id ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "pire-objheader-sub", children: [
2269
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "pire-objheader-row", children: [
2270
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { minWidth: 0 }, children: [
2271
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h1", { className: "pire-objheader-title", children: title }),
2272
+ subtitle || id ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "pire-objheader-sub", children: [
2073
2273
  subtitle,
2074
- id ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "pire-objheader-id", children: id }) : null
2274
+ id ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "pire-objheader-id", children: id }) : null
2075
2275
  ] }) : null
2076
2276
  ] }),
2077
2277
  badge,
2078
- actions ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "pire-objheader-actions", children: actions }) : null
2278
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "pire-objheader-actions", children: actions }) : null
2079
2279
  ] }),
2080
- facts?.length ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
2081
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("dt", { className: "pire-fact-label", children: fact.label }),
2082
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
2280
+ facts?.length ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { children: [
2281
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("dt", { className: "pire-fact-label", children: fact.label }),
2282
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
2083
2283
  ] }, fact.label)) }) : null
2084
2284
  ] });
2085
2285
  }
2086
2286
 
2087
2287
  // src/components/data/FilterBar.tsx
2088
- var import_jsx_runtime42 = require("react/jsx-runtime");
2288
+ var import_jsx_runtime43 = require("react/jsx-runtime");
2089
2289
  function FilterBar({
2090
2290
  children,
2091
2291
  activeFilters = [],
@@ -2102,66 +2302,66 @@ function FilterBar({
2102
2302
  const label = useMessage("filterBarLabel", rest["aria-label"]);
2103
2303
  const go = useMessage("filterBarGo", goLabel);
2104
2304
  const clearAll = useMessage("filterBarClearAll", clearAllLabel);
2105
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
2106
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "pire-filterbar-controls", children: [
2305
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
2306
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "pire-filterbar-controls", children: [
2107
2307
  children,
2108
- onGo ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Button, { variant: "primary", onPress: onGo, children: go }) : null
2308
+ onGo ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Button, { variant: "primary", onPress: onGo, children: go }) : null
2109
2309
  ] }),
2110
- activeFilters.length || resultLabel || actions ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "pire-filterbar-foot", children: [
2111
- activeFilters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
2112
- activeFilters.length && onClear ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
2113
- resultLabel ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
2114
- actions ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "pire-filterbar-actions", children: actions }) : null
2310
+ activeFilters.length || resultLabel || actions ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "pire-filterbar-foot", children: [
2311
+ activeFilters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
2312
+ activeFilters.length && onClear ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
2313
+ resultLabel ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
2314
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "pire-filterbar-actions", children: actions }) : null
2115
2315
  ] }) : null
2116
2316
  ] });
2117
2317
  }
2118
2318
 
2119
2319
  // src/components/data/DescriptionList.tsx
2120
- var import_jsx_runtime43 = require("react/jsx-runtime");
2320
+ var import_jsx_runtime44 = require("react/jsx-runtime");
2121
2321
  function DescriptionList({ items, layout = "rows", columns = 3, className, style, ...rest }) {
2122
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
2322
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2123
2323
  "dl",
2124
2324
  {
2125
2325
  className: cx("pire-dl", className),
2126
2326
  "data-layout": layout,
2127
2327
  style: { ...layout === "grid" ? { "--pire-dl-cols": columns } : null, ...style },
2128
2328
  ...rest,
2129
- children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
2130
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("dt", { className: "pire-dl-term", children: [
2329
+ children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
2330
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("dt", { className: "pire-dl-term", children: [
2131
2331
  item.label,
2132
2332
  item.hint
2133
2333
  ] }),
2134
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
2334
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
2135
2335
  ] }, i))
2136
2336
  }
2137
2337
  );
2138
2338
  }
2139
2339
 
2140
2340
  // src/components/data/Timeline.tsx
2141
- var import_jsx_runtime44 = require("react/jsx-runtime");
2341
+ var import_jsx_runtime45 = require("react/jsx-runtime");
2142
2342
  function Timeline({ entries, reverse = false, className, ...rest }) {
2143
2343
  const list = reverse ? [...entries].reverse() : entries;
2144
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { className: "pire-timeline-item", children: [
2145
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "pire-timeline-time", children: entry.time }),
2146
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "pire-timeline-text", children: entry.event }),
2147
- entry.actor ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "pire-timeline-actor", children: entry.actor }) : null
2344
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("li", { className: "pire-timeline-item", children: [
2345
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "pire-timeline-time", children: entry.time }),
2346
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "pire-timeline-text", children: entry.event }),
2347
+ entry.actor ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "pire-timeline-actor", children: entry.actor }) : null
2148
2348
  ] }, entry.id ?? i)) });
2149
2349
  }
2150
2350
 
2151
2351
  // src/components/data/LinkList.tsx
2152
- var import_react_aria_components27 = require("react-aria-components");
2153
- var import_jsx_runtime45 = require("react/jsx-runtime");
2352
+ var import_react_aria_components28 = require("react-aria-components");
2353
+ var import_jsx_runtime46 = require("react/jsx-runtime");
2154
2354
  function LinkList({ items, onSelect, className, ...rest }) {
2155
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cx("pire-linklist", className), role: "list", ...rest, children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_react_aria_components27.Button, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
2156
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
2157
- item.key ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "pire-linklist-key", children: item.key }) : null,
2158
- item.text ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "pire-linklist-text", children: item.text }) : null,
2355
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: cx("pire-linklist", className), role: "list", ...rest, children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_react_aria_components28.Button, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
2356
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
2357
+ item.key ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "pire-linklist-key", children: item.key }) : null,
2358
+ item.text ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "pire-linklist-text", children: item.text }) : null,
2159
2359
  item.trailing
2160
2360
  ] }, item.id)) });
2161
2361
  }
2162
2362
 
2163
2363
  // src/components/layout/PageBand.tsx
2164
- var import_jsx_runtime46 = require("react/jsx-runtime");
2364
+ var import_jsx_runtime47 = require("react/jsx-runtime");
2165
2365
  function PageBand({
2166
2366
  surface = "card",
2167
2367
  hasBorder = true,
@@ -2169,7 +2369,7 @@ function PageBand({
2169
2369
  className,
2170
2370
  ...rest
2171
2371
  }) {
2172
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
2372
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2173
2373
  "div",
2174
2374
  {
2175
2375
  className: cx("pire-pageband", className),
@@ -2182,56 +2382,56 @@ function PageBand({
2182
2382
  }
2183
2383
 
2184
2384
  // src/components/layout/PageHeader.tsx
2185
- var import_jsx_runtime47 = require("react/jsx-runtime");
2385
+ var import_jsx_runtime48 = require("react/jsx-runtime");
2186
2386
  function PageHeader({ title, subtitle, actions, className, ...rest }) {
2187
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("header", { className: cx("pire-pageheader", className), ...rest, children: [
2188
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { style: { minWidth: 0 }, children: [
2189
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h1", { className: "pire-pageheader-title", children: title }),
2190
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "pire-pageheader-sub", children: subtitle }) : null
2387
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("header", { className: cx("pire-pageheader", className), ...rest, children: [
2388
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { style: { minWidth: 0 }, children: [
2389
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h1", { className: "pire-pageheader-title", children: title }),
2390
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "pire-pageheader-sub", children: subtitle }) : null
2191
2391
  ] }),
2192
- actions ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "pire-pageheader-actions", children: actions }) : null
2392
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "pire-pageheader-actions", children: actions }) : null
2193
2393
  ] });
2194
2394
  }
2195
2395
 
2196
2396
  // src/components/layout/SectionHeader.tsx
2197
- var import_jsx_runtime48 = require("react/jsx-runtime");
2397
+ var import_jsx_runtime49 = require("react/jsx-runtime");
2198
2398
  function SectionHeader({ title, meta, actions, className, ...rest }) {
2199
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: cx("pire-sectionhead", className), ...rest, children: [
2200
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "pire-eyebrow", children: title }),
2201
- meta ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
2202
- actions ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "pire-sectionhead-actions", children: actions }) : null
2399
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: cx("pire-sectionhead", className), ...rest, children: [
2400
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "pire-eyebrow", children: title }),
2401
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
2402
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "pire-sectionhead-actions", children: actions }) : null
2203
2403
  ] });
2204
2404
  }
2205
2405
 
2206
2406
  // src/components/layout/SelectionBar.tsx
2207
- var import_jsx_runtime49 = require("react/jsx-runtime");
2407
+ var import_jsx_runtime50 = require("react/jsx-runtime");
2208
2408
  function SelectionBar({ count, noun = "record", children, actions, className, ...rest }) {
2209
2409
  if (!count) return null;
2210
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
2211
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "pire-selectionbar-count", children: [
2410
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
2411
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "pire-selectionbar-count", children: [
2212
2412
  count.toLocaleString(),
2213
2413
  " ",
2214
2414
  noun,
2215
2415
  count === 1 ? "" : "s",
2216
2416
  " selected"
2217
2417
  ] }),
2218
- children ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
2219
- actions ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "pire-selectionbar-actions", children: actions }) : null
2418
+ children ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
2419
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "pire-selectionbar-actions", children: actions }) : null
2220
2420
  ] });
2221
2421
  }
2222
2422
 
2223
2423
  // src/components/layout/FooterBar.tsx
2224
- var import_jsx_runtime50 = require("react/jsx-runtime");
2424
+ var import_jsx_runtime51 = require("react/jsx-runtime");
2225
2425
  function FooterBar({ note, actions, children, className, ...rest }) {
2226
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("footer", { className: cx("pire-footerbar", className), ...rest, children: [
2227
- note ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "pire-footerbar-note", children: note }) : null,
2426
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("footer", { className: cx("pire-footerbar", className), ...rest, children: [
2427
+ note ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "pire-footerbar-note", children: note }) : null,
2228
2428
  children,
2229
- actions ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "pire-footerbar-actions", children: actions }) : null
2429
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "pire-footerbar-actions", children: actions }) : null
2230
2430
  ] });
2231
2431
  }
2232
2432
 
2233
2433
  // src/components/patterns/ConfirmDialog.tsx
2234
- var import_jsx_runtime51 = require("react/jsx-runtime");
2434
+ var import_jsx_runtime52 = require("react/jsx-runtime");
2235
2435
  function ConfirmDialog({
2236
2436
  isOpen,
2237
2437
  title,
@@ -2245,7 +2445,7 @@ function ConfirmDialog({
2245
2445
  onConfirm,
2246
2446
  onCancel
2247
2447
  }) {
2248
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
2448
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
2249
2449
  Dialog,
2250
2450
  {
2251
2451
  isOpen,
@@ -2255,12 +2455,12 @@ function ConfirmDialog({
2255
2455
  onClose: onCancel,
2256
2456
  isDismissable: !isBusy,
2257
2457
  showClose: false,
2258
- footer: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
2259
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
2260
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
2458
+ footer: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_jsx_runtime52.Fragment, { children: [
2459
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
2460
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
2261
2461
  ] }),
2262
2462
  children: [
2263
- consequence ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
2463
+ consequence ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
2264
2464
  children
2265
2465
  ]
2266
2466
  }
@@ -2268,12 +2468,12 @@ function ConfirmDialog({
2268
2468
  }
2269
2469
 
2270
2470
  // src/components/patterns/SidePanel.tsx
2271
- var import_react_aria_components28 = require("react-aria-components");
2272
- var import_jsx_runtime52 = require("react/jsx-runtime");
2471
+ var import_react_aria_components29 = require("react-aria-components");
2472
+ var import_jsx_runtime53 = require("react/jsx-runtime");
2273
2473
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
2274
2474
  const msg = usePireMessages();
2275
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
2276
- import_react_aria_components28.ModalOverlay,
2475
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
2476
+ import_react_aria_components29.ModalOverlay,
2277
2477
  {
2278
2478
  className: "pire-sidepanel-overlay",
2279
2479
  isOpen,
@@ -2281,34 +2481,138 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
2281
2481
  onOpenChange: (o) => {
2282
2482
  if (!o) onClose?.();
2283
2483
  },
2284
- children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_react_aria_components28.Modal, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_react_aria_components28.Dialog, { className: "pire-dialog", style: { height: "100%" }, children: [
2285
- /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("header", { className: "pire-dialog-head", children: [
2286
- /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2287
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_react_aria_components28.Heading, { slot: "title", className: "pire-dialog-title", children: title }),
2288
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
2484
+ children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_aria_components29.Modal, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_aria_components29.Dialog, { className: "pire-dialog", style: { height: "100%" }, children: [
2485
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("header", { className: "pire-dialog-head", children: [
2486
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2487
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_react_aria_components29.Heading, { slot: "title", className: "pire-dialog-title", children: title }),
2488
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
2289
2489
  ] }),
2290
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
2490
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
2291
2491
  ] }),
2292
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
2293
- footer ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("footer", { className: "pire-dialog-foot", children: footer }) : null
2492
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
2493
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("footer", { className: "pire-dialog-foot", children: footer }) : null
2294
2494
  ] }) })
2295
2495
  }
2296
2496
  );
2297
2497
  }
2298
2498
 
2299
2499
  // src/components/patterns/EmptyState.tsx
2300
- var import_jsx_runtime53 = require("react/jsx-runtime");
2500
+ var import_jsx_runtime54 = require("react/jsx-runtime");
2301
2501
  function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
2302
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
2303
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
2304
- title ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
2305
- children ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
2502
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
2503
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
2504
+ title ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
2505
+ children ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
2306
2506
  action
2307
2507
  ] });
2308
2508
  }
2309
2509
 
2510
+ // src/components/patterns/FileDropZone.tsx
2511
+ var React13 = __toESM(require("react"), 1);
2512
+ var import_react_aria_components30 = require("react-aria-components");
2513
+ var import_jsx_runtime55 = require("react/jsx-runtime");
2514
+ var isImage2 = (file) => file.type.startsWith("image/");
2515
+ function FileDropZone({
2516
+ label,
2517
+ value,
2518
+ defaultValue,
2519
+ onChange,
2520
+ acceptedFileTypes,
2521
+ allowsMultiple,
2522
+ maxSize,
2523
+ onError,
2524
+ showPreview = true,
2525
+ uploadProgress,
2526
+ promptLabel,
2527
+ height = "regular",
2528
+ description,
2529
+ errorMessage,
2530
+ isInvalid,
2531
+ isDisabled,
2532
+ isReadOnly,
2533
+ isRequired,
2534
+ fullWidth = true,
2535
+ className,
2536
+ style
2537
+ }) {
2538
+ const msg = usePireMessages();
2539
+ const [uncontrolled, setUncontrolled] = React13.useState(defaultValue ?? []);
2540
+ const files = value ?? uncontrolled;
2541
+ const created = React13.useRef([]);
2542
+ React13.useEffect(() => () => {
2543
+ for (const url of created.current) URL.revokeObjectURL(url);
2544
+ }, []);
2545
+ const commit = (next) => {
2546
+ if (value === void 0) setUncontrolled(next);
2547
+ onChange?.(next);
2548
+ };
2549
+ const accept = (picked) => {
2550
+ if (isDisabled || isReadOnly || !picked.length) return;
2551
+ const { accepted, rejected } = screenFiles(picked, { maxSize, acceptedFileTypes });
2552
+ if (rejected.length) onError?.(rejected);
2553
+ if (!accepted.length) return;
2554
+ const wrapped = accepted.map((file) => {
2555
+ const previewUrl = showPreview && isImage2(file) ? URL.createObjectURL(file) : void 0;
2556
+ if (previewUrl) created.current.push(previewUrl);
2557
+ return { file, previewUrl };
2558
+ });
2559
+ commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
2560
+ };
2561
+ const remove = (target) => commit(files.filter((f) => f.file !== target));
2562
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), children: [
2563
+ label ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "pire-field-label", children: [
2564
+ label,
2565
+ isRequired ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
2566
+ ] }) : null,
2567
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
2568
+ import_react_aria_components30.DropZone,
2569
+ {
2570
+ className: "pire-dropzone",
2571
+ "data-height": height,
2572
+ isDisabled: isDisabled || isReadOnly,
2573
+ onDrop: async (e) => {
2574
+ const dropped = await Promise.all(
2575
+ e.items.filter(import_react_aria_components30.isFileDropItem).map((item) => item.getFile())
2576
+ );
2577
+ accept(dropped);
2578
+ },
2579
+ children: [
2580
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
2581
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
2582
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
2583
+ import_react_aria_components30.FileTrigger,
2584
+ {
2585
+ acceptedFileTypes,
2586
+ allowsMultiple,
2587
+ onSelect: (list) => accept(list ? [...list] : []),
2588
+ children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
2589
+ }
2590
+ )
2591
+ ]
2592
+ }
2593
+ ),
2594
+ files.length ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("li", { className: "pire-fileupload-item", children: [
2595
+ previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
2596
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "pire-fileupload-name", children: file.name }),
2597
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
2598
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
2599
+ IconButton,
2600
+ {
2601
+ icon: "x",
2602
+ size: "sm",
2603
+ label: msg.fileUploadRemoveNamed.replace("{name}", file.name),
2604
+ onPress: () => remove(file)
2605
+ }
2606
+ )
2607
+ ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
2608
+ uploadProgress != null ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
2609
+ description ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "pire-field-hint", children: description }) : null,
2610
+ isInvalid && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "pire-field-error", children: errorMessage }) : null
2611
+ ] });
2612
+ }
2613
+
2310
2614
  // src/index.ts
2311
- var import_react_aria_components29 = require("react-aria-components");
2615
+ var import_react_aria_components31 = require("react-aria-components");
2312
2616
  // Annotate the CommonJS export names for ESM import in node:
2313
2617
  0 && (module.exports = {
2314
2618
  Avatar,
@@ -2325,6 +2629,8 @@ var import_react_aria_components29 = require("react-aria-components");
2325
2629
  Dialog,
2326
2630
  DialogTrigger,
2327
2631
  EmptyState,
2632
+ FileDropZone,
2633
+ FileUpload,
2328
2634
  FilterBar,
2329
2635
  FooterBar,
2330
2636
  FormField,
@@ -2380,6 +2686,7 @@ var import_react_aria_components29 = require("react-aria-components");
2380
2686
  configureIcons,
2381
2687
  enMessages,
2382
2688
  esMessages,
2689
+ formatFileSize,
2383
2690
  usePireMessages,
2384
2691
  useToast
2385
2692
  });