@orianatech/pire 1.1.0 → 1.2.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
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
+ AppLauncher: () => AppLauncher,
33
34
  Avatar: () => Avatar,
34
35
  Badge: () => Badge,
35
36
  BarChart: () => BarChart,
@@ -49,17 +50,17 @@ __export(src_exports, {
49
50
  DialogBody: () => DialogBody,
50
51
  DialogDescription: () => DialogDescription,
51
52
  DialogTitle: () => DialogTitle,
52
- DialogTrigger: () => import_react_aria_components34.DialogTrigger,
53
+ DialogTrigger: () => import_react_aria_components36.DialogTrigger,
53
54
  DonutChart: () => DonutChart,
54
55
  EmptyState: () => EmptyState,
55
56
  FileDropZone: () => FileDropZone,
56
57
  FileUpload: () => FileUpload,
57
58
  FilterBar: () => FilterBar,
58
- Focusable: () => import_react_aria_components35.Focusable,
59
+ Focusable: () => import_react_aria_components37.Focusable,
59
60
  FooterBar: () => FooterBar,
60
61
  FormField: () => FormField,
61
62
  Heading: () => Heading,
62
- I18nProvider: () => import_react_aria_components34.I18nProvider,
63
+ I18nProvider: () => import_react_aria_components36.I18nProvider,
63
64
  ICON_NAMES: () => ICON_NAMES,
64
65
  Icon: () => Icon,
65
66
  IconButton: () => IconButton,
@@ -74,7 +75,7 @@ __export(src_exports, {
74
75
  MenuItem: () => MenuItem,
75
76
  MenuSection: () => MenuSection,
76
77
  MenuSeparator: () => MenuSeparator,
77
- MenuTrigger: () => import_react_aria_components34.MenuTrigger,
78
+ MenuTrigger: () => import_react_aria_components36.MenuTrigger,
78
79
  MultiComboBox: () => MultiComboBox,
79
80
  NumberField: () => NumberField,
80
81
  ObjectHeader: () => ObjectHeader,
@@ -82,24 +83,25 @@ __export(src_exports, {
82
83
  PageHeader: () => PageHeader,
83
84
  Pagination: () => Pagination,
84
85
  PireIntlProvider: () => PireIntlProvider,
85
- Popover: () => import_react_aria_components34.Popover,
86
+ Popover: () => import_react_aria_components36.Popover,
86
87
  ProgressBar: () => ProgressBar,
87
88
  Radio: () => Radio,
88
89
  RadioGroup: () => RadioGroup,
89
- RouterProvider: () => import_react_aria_components34.RouterProvider,
90
+ RouterProvider: () => import_react_aria_components36.RouterProvider,
90
91
  SectionHeader: () => SectionHeader,
91
92
  SegmentedControl: () => SegmentedControl,
92
93
  Select: () => Select,
93
94
  SelectionBar: () => SelectionBar,
94
95
  Separator: () => Separator,
95
96
  ShellBar: () => ShellBar,
97
+ ShellRail: () => ShellRail,
96
98
  SideNav: () => SideNav,
97
99
  SidePanel: () => SidePanel,
98
100
  Skeleton: () => Skeleton,
99
101
  SkeletonTableRow: () => SkeletonTableRow,
100
102
  SplitPane: () => SplitPane,
101
103
  Strong: () => Strong,
102
- SubmenuTrigger: () => import_react_aria_components34.SubmenuTrigger,
104
+ SubmenuTrigger: () => import_react_aria_components36.SubmenuTrigger,
103
105
  Switch: () => Switch,
104
106
  Tabs: () => Tabs,
105
107
  Tag: () => Tag,
@@ -245,6 +247,7 @@ var ICON_MARKUP = {
245
247
  "sort--descending": '<path d="M18 22 19.414 20.586 23 24.172 23 4 25 4 25 24.172 28.586 20.586 30 22 24 28 18 22z"/><path d="M2 6H16V8H2z"/><path d="M6 12H16V14H6z"/><path d="M10 18H16V20H10z"/>',
246
248
  "star": '<path d="M16,6.52l2.76,5.58.46,1,1,.15,6.16.89L22,18.44l-.75.73.18,1,1.05,6.13-5.51-2.89L16,23l-.93.49L9.56,26.34l1-6.13.18-1L10,18.44,5.58,14.09l6.16-.89,1-.15.46-1L16,6.52M16,2l-4.55,9.22L1.28,12.69l7.36,7.18L6.9,30,16,25.22,25.1,30,23.36,19.87l7.36-7.17L20.55,11.22Z"/>',
247
249
  "star--filled": '<path d="M16,2l-4.55,9.22L1.28,12.69l7.36,7.18L6.9,30,16,25.22,25.1,30,23.36,19.87l7.36-7.17L20.55,11.22Z"/>',
250
+ "store": '<path d="M30,10.68l-2-6A1,1,0,0,0,27,4H5a1,1,0,0,0-1,.68l-2,6A1.19,1.19,0,0,0,2,11v6a1,1,0,0,0,1,1H4V28H6V18h6V28H28V18h1a1,1,0,0,0,1-1V11A1.19,1.19,0,0,0,30,10.68ZM26,26H14V18H26Zm2-10H24V12H22v4H17V12H15v4H10V12H8v4H4V11.16L5.72,6H26.28L28,11.16Z"/>',
248
251
  "subtract": '<path d="M8 15H24V17H8z"/>',
249
252
  "table--split": '<path d="M27,3H5A2,2,0,0,0,3,5V27a2,2,0,0,0,2,2H27a2,2,0,0,0,2-2V5A2,2,0,0,0,27,3Zm0,2V9H5V5ZM17,11H27v7H17Zm-2,7H5V11H15ZM5,20H15v7H5Zm12,7V20H27v7Z"/>',
250
253
  "tag": '<path d="M10,14a4,4,0,1,1,4-4A4.0045,4.0045,0,0,1,10,14Zm0-6a2,2,0,1,0,1.998,2.0044A2.002,2.002,0,0,0,10,8Z"/><path d="M16.6436,29.4145,2.5858,15.3555A2,2,0,0,1,2,13.9414V4A2,2,0,0,1,4,2h9.9413a2,2,0,0,1,1.4142.5858L29.4144,16.6436a2.0005,2.0005,0,0,1,0,2.8285l-9.9424,9.9425a2.0008,2.0008,0,0,1-2.8285,0ZM4,4v9.9417L18.0578,28,28,18.0579,13.9416,4Z"/>',
@@ -272,6 +275,9 @@ var CARBON_MAP = {
272
275
  "bell": "notification",
273
276
  "help-circle": "help",
274
277
  "grid-3x3": "grid",
278
+ /* The app launcher's trigger. Carbon has no 2x2 grid, and `apps` is the glyph it uses for
279
+ exactly this affordance, so the Lucide name maps onto it rather than onto plain `grid`. */
280
+ "grid-2x2": "apps",
275
281
  "home": "home",
276
282
  "file-text": "document",
277
283
  "clipboard-list": "list--checked",
@@ -316,6 +322,7 @@ var CARBON_MAP = {
316
322
  "trending-up": "arrow--up",
317
323
  "trending-down": "arrow--down",
318
324
  "shopping-cart": "shopping--cart",
325
+ "store": "store",
319
326
  "user": "user",
320
327
  "shapes": "apps",
321
328
  "type": "text--font",
@@ -883,6 +890,12 @@ var enMessages = {
883
890
  paginationNext: "Next page",
884
891
  paginationRowsPerPage: "Rows per page",
885
892
  sideNavLabel: "Main navigation",
893
+ shellRailLabel: "Applications",
894
+ appLauncherLabel: "All applications",
895
+ appLauncherTitle: "All applications",
896
+ appLauncherSearch: "Search for an application",
897
+ appLauncherEmpty: "No application matches that search.",
898
+ appLauncherLoading: "Loading applications\u2026",
886
899
  splitPaneList: "List",
887
900
  splitPaneDetail: "Detail",
888
901
  splitPaneBack: "Back to list",
@@ -943,6 +956,12 @@ var esMessages = {
943
956
  paginationNext: "P\xE1gina siguiente",
944
957
  paginationRowsPerPage: "Filas por p\xE1gina",
945
958
  sideNavLabel: "Navegaci\xF3n principal",
959
+ shellRailLabel: "Aplicaciones",
960
+ appLauncherLabel: "Todas las aplicaciones",
961
+ appLauncherTitle: "Todas las aplicaciones",
962
+ appLauncherSearch: "Busc\xE1 una aplicaci\xF3n",
963
+ appLauncherEmpty: "Ninguna aplicaci\xF3n coincide con esa b\xFAsqueda.",
964
+ appLauncherLoading: "Cargando aplicaciones\u2026",
946
965
  splitPaneList: "Lista",
947
966
  splitPaneDetail: "Detalle",
948
967
  splitPaneBack: "Volver a la lista",
@@ -2594,6 +2613,7 @@ var import_react_aria_components24 = require("react-aria-components");
2594
2613
  var import_jsx_runtime35 = require("react/jsx-runtime");
2595
2614
  var initials2 = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
2596
2615
  function ShellBar({
2616
+ launcher,
2597
2617
  product,
2598
2618
  monogram,
2599
2619
  title,
@@ -2610,6 +2630,7 @@ function ShellBar({
2610
2630
  }) {
2611
2631
  const msg = usePireMessages();
2612
2632
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("header", { className: cx("pire-shellbar", className), ...rest, children: [
2633
+ launcher,
2613
2634
  onMenu ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
2614
2635
  monogram ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
2615
2636
  product ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "pire-shellbar-product", children: product }) : null,
@@ -2856,12 +2877,38 @@ function SideNav({
2856
2877
  );
2857
2878
  }
2858
2879
 
2859
- // src/components/navigation/Tabs.tsx
2880
+ // src/components/navigation/ShellRail.tsx
2881
+ var React22 = __toESM(require("react"), 1);
2860
2882
  var import_react_aria_components27 = require("react-aria-components");
2861
- var import_jsx_runtime38 = require("react/jsx-runtime");
2883
+ var import_jsx_runtime38 = (
2884
+ // The divider is a sibling of the groups rather than a pseudo-element on one, because the
2885
+ // scrolling zone would carry its own rule out of view on the first wheel event.
2886
+ require("react/jsx-runtime")
2887
+ );
2888
+ function ShellRail({ groups, value, onChange, className, ...rest }) {
2889
+ const msg = usePireMessages();
2890
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("nav", { className: cx("pire-shellrail", className), "aria-label": msg.shellRailLabel, ...rest, children: groups.map((group, gi) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(React22.Fragment, { children: [
2891
+ gi > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "pire-shellrail-divider" }) : null,
2892
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "pire-shellrail-group", "data-scroll": group.isScrollable ? "true" : void 0, children: group.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Tooltip, { label: item.label, placement: "right", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
2893
+ import_react_aria_components27.Button,
2894
+ {
2895
+ className: "pire-shellrail-item",
2896
+ "aria-label": item.label,
2897
+ "data-selected": item.id === value ? "true" : void 0,
2898
+ "aria-current": item.id === value ? "true" : void 0,
2899
+ onPress: () => onChange?.(item.id),
2900
+ children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "pire-shellrail-tile", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Icon, { name: item.icon, size: 20 }) })
2901
+ }
2902
+ ) }, item.id)) })
2903
+ ] }, group.items[0]?.id ?? gi)) });
2904
+ }
2905
+
2906
+ // src/components/navigation/Tabs.tsx
2907
+ var import_react_aria_components28 = require("react-aria-components");
2908
+ var import_jsx_runtime39 = require("react/jsx-runtime");
2862
2909
  function Tabs({ items, value, defaultValue, onChange, panels, className, style, ...rest }) {
2863
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
2864
- import_react_aria_components27.Tabs,
2910
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
2911
+ import_react_aria_components28.Tabs,
2865
2912
  {
2866
2913
  className,
2867
2914
  style,
@@ -2869,23 +2916,23 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
2869
2916
  defaultSelectedKey: defaultValue,
2870
2917
  onSelectionChange: (k) => onChange?.(String(k)),
2871
2918
  children: [
2872
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_aria_components27.TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react_aria_components27.Tab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
2873
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Icon, { name: item.icon, size: 16 }) : null,
2919
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_aria_components28.TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_react_aria_components28.Tab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
2920
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Icon, { name: item.icon, size: 16 }) : null,
2874
2921
  item.label,
2875
- item.count != null ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "pire-tab-count", children: item.count }) : null
2922
+ item.count != null ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "pire-tab-count", children: item.count }) : null
2876
2923
  ] }) }),
2877
- items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_aria_components27.TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2924
+ items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_aria_components28.TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2878
2925
  ]
2879
2926
  }
2880
2927
  );
2881
2928
  }
2882
2929
 
2883
2930
  // src/components/navigation/Breadcrumb.tsx
2884
- var import_react_aria_components28 = require("react-aria-components");
2885
- var import_jsx_runtime39 = require("react/jsx-runtime");
2931
+ var import_react_aria_components29 = require("react-aria-components");
2932
+ var import_jsx_runtime40 = require("react/jsx-runtime");
2886
2933
  function Breadcrumb({ items, onNavigate, className, style }) {
2887
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
2888
- import_react_aria_components28.Breadcrumbs,
2934
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
2935
+ import_react_aria_components29.Breadcrumbs,
2889
2936
  {
2890
2937
  className: cx("pire-breadcrumbs", className),
2891
2938
  style,
@@ -2893,9 +2940,9 @@ function Breadcrumb({ items, onNavigate, className, style }) {
2893
2940
  onAction: (key) => onNavigate?.(String(key)),
2894
2941
  children: (item) => {
2895
2942
  const last = items[items.length - 1] === item;
2896
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_react_aria_components28.Breadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
2897
- last ? item.label : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_aria_components28.Link, { href: item.href, children: item.label }),
2898
- last ? null : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
2943
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_aria_components29.Breadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
2944
+ last ? item.label : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_react_aria_components29.Link, { href: item.href, children: item.label }),
2945
+ last ? null : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
2899
2946
  ] });
2900
2947
  }
2901
2948
  }
@@ -2903,7 +2950,7 @@ function Breadcrumb({ items, onNavigate, className, style }) {
2903
2950
  }
2904
2951
 
2905
2952
  // src/components/navigation/Pagination.tsx
2906
- var import_jsx_runtime40 = require("react/jsx-runtime");
2953
+ var import_jsx_runtime41 = require("react/jsx-runtime");
2907
2954
  function Pagination({
2908
2955
  page = 1,
2909
2956
  pageSize = 25,
@@ -2918,9 +2965,9 @@ function Pagination({
2918
2965
  const pages = Math.max(1, Math.ceil(total / pageSize));
2919
2966
  const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
2920
2967
  const to = Math.min(total, page * pageSize);
2921
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
2922
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
2923
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
2968
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
2969
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
2970
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2924
2971
  IconButton,
2925
2972
  {
2926
2973
  icon: "chevron-left",
@@ -2931,8 +2978,8 @@ function Pagination({
2931
2978
  onPress: () => onPageChange?.(page - 1)
2932
2979
  }
2933
2980
  ),
2934
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
2935
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
2981
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
2982
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2936
2983
  IconButton,
2937
2984
  {
2938
2985
  icon: "chevron-right",
@@ -2943,7 +2990,7 @@ function Pagination({
2943
2990
  onPress: () => onPageChange?.(page + 1)
2944
2991
  }
2945
2992
  ),
2946
- onPageSizeChange ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
2993
+ onPageSizeChange ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2947
2994
  Select,
2948
2995
  {
2949
2996
  "aria-label": msg.paginationRowsPerPage,
@@ -2959,7 +3006,7 @@ function Pagination({
2959
3006
  }
2960
3007
 
2961
3008
  // src/components/feedback/InlineMessage.tsx
2962
- var import_jsx_runtime41 = require("react/jsx-runtime");
3009
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2963
3010
  var KIND_ICON = {
2964
3011
  info: "info",
2965
3012
  success: "check-circle-2",
@@ -2969,7 +3016,7 @@ var KIND_ICON = {
2969
3016
  function InlineMessage({ kind = "info", title, action, onClose, children, className, ...rest }) {
2970
3017
  const msg = usePireMessages();
2971
3018
  const assertive = kind === "error" || kind === "warning";
2972
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
3019
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2973
3020
  "div",
2974
3021
  {
2975
3022
  className: cx("pire-msg", className),
@@ -2978,21 +3025,21 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
2978
3025
  "aria-live": assertive ? "assertive" : "polite",
2979
3026
  ...rest,
2980
3027
  children: [
2981
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
2982
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
2983
- title ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "pire-msg-title", children: title }) : null,
2984
- children ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "pire-msg-body", children }) : null,
3028
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
3029
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
3030
+ title ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "pire-msg-title", children: title }) : null,
3031
+ children ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "pire-msg-body", children }) : null,
2985
3032
  action
2986
3033
  ] }),
2987
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
3034
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
2988
3035
  ]
2989
3036
  }
2990
3037
  );
2991
3038
  }
2992
3039
 
2993
3040
  // src/components/feedback/Toast.tsx
2994
- var React22 = __toESM(require("react"), 1);
2995
- var import_jsx_runtime42 = require("react/jsx-runtime");
3041
+ var React23 = __toESM(require("react"), 1);
3042
+ var import_jsx_runtime43 = require("react/jsx-runtime");
2996
3043
  var KIND_ICON2 = {
2997
3044
  info: "info",
2998
3045
  success: "check-circle-2",
@@ -3001,7 +3048,7 @@ var KIND_ICON2 = {
3001
3048
  };
3002
3049
  function Toast({ kind = "success", onClose, position = "bottom-center", children, className, ...rest }) {
3003
3050
  const msg = usePireMessages();
3004
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
3051
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
3005
3052
  "div",
3006
3053
  {
3007
3054
  className: cx("pire-toast", className),
@@ -3010,40 +3057,40 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
3010
3057
  "aria-live": kind === "error" ? "assertive" : "polite",
3011
3058
  ...rest,
3012
3059
  children: [
3013
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Icon, { name: KIND_ICON2[kind], size: 16 }),
3014
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { style: { flex: 1 }, children }),
3015
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
3060
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Icon, { name: KIND_ICON2[kind], size: 16 }),
3061
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { style: { flex: 1 }, children }),
3062
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
3016
3063
  ]
3017
3064
  }
3018
3065
  );
3019
3066
  }
3020
- var ToastContext = React22.createContext(null);
3067
+ var ToastContext = React23.createContext(null);
3021
3068
  function ToastProvider({ children, timeout = 6e3 }) {
3022
3069
  const msg = usePireMessages();
3023
- const [toasts, setToasts] = React22.useState([]);
3024
- const close = React22.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
3025
- const add = React22.useCallback((toast) => {
3070
+ const [toasts, setToasts] = React23.useState([]);
3071
+ const close = React23.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
3072
+ const add = React23.useCallback((toast) => {
3026
3073
  const id = Math.random().toString(36).slice(2);
3027
3074
  setToasts((t) => [...t, { ...toast, id }]);
3028
3075
  const ms = toast.timeout ?? timeout;
3029
3076
  if (ms > 0) setTimeout(() => close(id), ms);
3030
3077
  return id;
3031
3078
  }, [close, timeout]);
3032
- const value = React22.useMemo(() => ({ add, close }), [add, close]);
3033
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(ToastContext.Provider, { value, children: [
3079
+ const value = React23.useMemo(() => ({ add, close }), [add, close]);
3080
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(ToastContext.Provider, { value, children: [
3034
3081
  children,
3035
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
3082
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
3036
3083
  ] });
3037
3084
  }
3038
3085
  function useToast() {
3039
- const ctx = React22.useContext(ToastContext);
3086
+ const ctx = React23.useContext(ToastContext);
3040
3087
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
3041
3088
  return ctx;
3042
3089
  }
3043
3090
 
3044
3091
  // src/components/data/KpiTile.tsx
3045
- var import_react_aria_components29 = require("react-aria-components");
3046
- var import_jsx_runtime43 = require("react/jsx-runtime");
3092
+ var import_react_aria_components30 = require("react-aria-components");
3093
+ var import_jsx_runtime44 = require("react/jsx-runtime");
3047
3094
  function KpiTile({
3048
3095
  label,
3049
3096
  value,
@@ -3059,50 +3106,50 @@ function KpiTile({
3059
3106
  style
3060
3107
  }) {
3061
3108
  const tone = deltaTone ?? (deltaDirection === "down" ? "negative" : "positive");
3062
- const body = /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
3063
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "pire-kpi-label", children: [
3064
- icon ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Icon, { name: icon, size: 16 }) : null,
3109
+ const body = /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
3110
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "pire-kpi-label", children: [
3111
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Icon, { name: icon, size: 16 }) : null,
3065
3112
  label
3066
3113
  ] }),
3067
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "pire-kpi-value", children: [
3114
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "pire-kpi-value", children: [
3068
3115
  value,
3069
- unit ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "pire-kpi-unit", children: unit }) : null
3116
+ unit ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "pire-kpi-unit", children: unit }) : null
3070
3117
  ] }),
3071
- delta ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
3072
- deltaDirection ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
3118
+ delta ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
3119
+ deltaDirection ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
3073
3120
  delta
3074
3121
  ] }) : null,
3075
- footnote ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "pire-kpi-foot", children: footnote }) : null
3122
+ footnote ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "pire-kpi-foot", children: footnote }) : null
3076
3123
  ] });
3077
3124
  const props = { className: cx("pire-kpi", className), "data-status": status, style };
3078
- return onPress ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_aria_components29.Button, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { ...props, children: body });
3125
+ return onPress ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_aria_components30.Button, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { ...props, children: body });
3079
3126
  }
3080
3127
 
3081
3128
  // src/components/data/ObjectHeader.tsx
3082
- var import_jsx_runtime44 = require("react/jsx-runtime");
3129
+ var import_jsx_runtime45 = require("react/jsx-runtime");
3083
3130
  function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions, className, ...rest }) {
3084
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("header", { className: cx("pire-objheader", className), ...rest, children: [
3131
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("header", { className: cx("pire-objheader", className), ...rest, children: [
3085
3132
  breadcrumb,
3086
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "pire-objheader-row", children: [
3087
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { style: { minWidth: 0 }, children: [
3088
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h1", { className: "pire-objheader-title", children: title }),
3089
- subtitle || id ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "pire-objheader-sub", children: [
3133
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "pire-objheader-row", children: [
3134
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { style: { minWidth: 0 }, children: [
3135
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("h1", { className: "pire-objheader-title", children: title }),
3136
+ subtitle || id ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "pire-objheader-sub", children: [
3090
3137
  subtitle,
3091
- id ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "pire-objheader-id", children: id }) : null
3138
+ id ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "pire-objheader-id", children: id }) : null
3092
3139
  ] }) : null
3093
3140
  ] }),
3094
3141
  badge,
3095
- actions ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "pire-objheader-actions", children: actions }) : null
3142
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "pire-objheader-actions", children: actions }) : null
3096
3143
  ] }),
3097
- facts?.length ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { children: [
3098
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("dt", { className: "pire-fact-label", children: fact.label }),
3099
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
3144
+ facts?.length ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { children: [
3145
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("dt", { className: "pire-fact-label", children: fact.label }),
3146
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
3100
3147
  ] }, fact.label)) }) : null
3101
3148
  ] });
3102
3149
  }
3103
3150
 
3104
3151
  // src/components/data/FilterBar.tsx
3105
- var import_jsx_runtime45 = require("react/jsx-runtime");
3152
+ var import_jsx_runtime46 = require("react/jsx-runtime");
3106
3153
  function FilterBar({
3107
3154
  children,
3108
3155
  activeFilters = [],
@@ -3119,49 +3166,49 @@ function FilterBar({
3119
3166
  const label = useMessage("filterBarLabel", rest["aria-label"]);
3120
3167
  const go = useMessage("filterBarGo", goLabel);
3121
3168
  const clearAll = useMessage("filterBarClearAll", clearAllLabel);
3122
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
3123
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "pire-filterbar-controls", children: [
3169
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
3170
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "pire-filterbar-controls", children: [
3124
3171
  children,
3125
- onGo ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Button, { variant: "primary", onPress: onGo, children: go }) : null
3172
+ onGo ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Button, { variant: "primary", onPress: onGo, children: go }) : null
3126
3173
  ] }),
3127
- activeFilters.length || resultLabel || actions ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "pire-filterbar-foot", children: [
3128
- activeFilters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
3129
- activeFilters.length && onClear ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
3130
- resultLabel ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
3131
- actions ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "pire-filterbar-actions", children: actions }) : null
3174
+ activeFilters.length || resultLabel || actions ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "pire-filterbar-foot", children: [
3175
+ activeFilters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
3176
+ activeFilters.length && onClear ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
3177
+ resultLabel ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
3178
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "pire-filterbar-actions", children: actions }) : null
3132
3179
  ] }) : null
3133
3180
  ] });
3134
3181
  }
3135
3182
 
3136
3183
  // src/components/data/DescriptionList.tsx
3137
- var import_jsx_runtime46 = require("react/jsx-runtime");
3184
+ var import_jsx_runtime47 = require("react/jsx-runtime");
3138
3185
  function DescriptionList({ items, layout = "rows", columns = 3, className, style, ...rest }) {
3139
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3186
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3140
3187
  "dl",
3141
3188
  {
3142
3189
  className: cx("pire-dl", className),
3143
3190
  "data-layout": layout,
3144
3191
  style: { ...layout === "grid" ? { "--pire-dl-cols": columns } : null, ...style },
3145
3192
  ...rest,
3146
- children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
3147
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("dt", { className: "pire-dl-term", children: [
3193
+ children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
3194
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("dt", { className: "pire-dl-term", children: [
3148
3195
  item.label,
3149
3196
  item.hint
3150
3197
  ] }),
3151
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
3198
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
3152
3199
  ] }, i))
3153
3200
  }
3154
3201
  );
3155
3202
  }
3156
3203
 
3157
3204
  // src/components/data/Timeline.tsx
3158
- var import_jsx_runtime47 = require("react/jsx-runtime");
3205
+ var import_jsx_runtime48 = require("react/jsx-runtime");
3159
3206
  function Timeline({ entries, reverse = false, className, ...rest }) {
3160
3207
  const list = reverse ? [...entries].reverse() : entries;
3161
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("li", { className: "pire-timeline-item", children: [
3162
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "pire-timeline-time", children: entry.time }),
3163
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "pire-timeline-text", children: entry.event }),
3164
- entry.actor ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "pire-timeline-actor", children: entry.actor }) : null
3208
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("li", { className: "pire-timeline-item", children: [
3209
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "pire-timeline-time", children: entry.time }),
3210
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "pire-timeline-text", children: entry.event }),
3211
+ entry.actor ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "pire-timeline-actor", children: entry.actor }) : null
3165
3212
  ] }, entry.id ?? i)) });
3166
3213
  }
3167
3214
 
@@ -3244,7 +3291,7 @@ function alignToCategories(series, categoryCount) {
3244
3291
  }
3245
3292
 
3246
3293
  // src/components/data/ChartFrame.tsx
3247
- var import_jsx_runtime48 = require("react/jsx-runtime");
3294
+ var import_jsx_runtime49 = require("react/jsx-runtime");
3248
3295
  function seriesLegend(series) {
3249
3296
  return series.map((one, index) => ({
3250
3297
  key: one.id,
@@ -3267,29 +3314,29 @@ function ChartFrame({
3267
3314
  children
3268
3315
  }) {
3269
3316
  const msg = usePireMessages();
3270
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("figure", { className: cx("pire-chart", className), style, children: [
3271
- title || description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("figcaption", { className: "pire-chart-head", children: [
3272
- title ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "pire-chart-title", children: title }) : null,
3273
- description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "pire-chart-desc", children: description }) : null
3317
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("figure", { className: cx("pire-chart", className), style, children: [
3318
+ title || description ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("figcaption", { className: "pire-chart-head", children: [
3319
+ title ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "pire-chart-title", children: title }) : null,
3320
+ description ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "pire-chart-desc", children: description }) : null
3274
3321
  ] }) : null,
3275
- legend && legend.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ul", { className: "pire-chart-legend", children: legend.map((item) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("li", { className: "pire-chart-legend-item", children: [
3276
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "pire-chart-swatch", style: { background: item.color } }),
3322
+ legend && legend.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ul", { className: "pire-chart-legend", children: legend.map((item) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("li", { className: "pire-chart-legend-item", children: [
3323
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "pire-chart-swatch", style: { background: item.color } }),
3277
3324
  item.label
3278
3325
  ] }, item.key)) }) : null,
3279
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "pire-chart-plot", "aria-hidden": "true", children }),
3280
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: showDataTable ? "pire-chart-table" : "pire-sr-only", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("table", { children: [
3281
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("caption", { children: label }),
3282
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("tr", { children: [
3283
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("th", { scope: "col", children: msg.chartCategoryHeader }),
3284
- series.map((one) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("th", { scope: "col", children: one.label }, one.id))
3326
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "pire-chart-plot", "aria-hidden": "true", children }),
3327
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: showDataTable ? "pire-chart-table" : "pire-sr-only", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("table", { children: [
3328
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("caption", { children: label }),
3329
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("tr", { children: [
3330
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("th", { scope: "col", children: msg.chartCategoryHeader }),
3331
+ series.map((one) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("th", { scope: "col", children: one.label }, one.id))
3285
3332
  ] }) }),
3286
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("tbody", { children: categories.map((category, categoryIndex) => (
3333
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("tbody", { children: categories.map((category, categoryIndex) => (
3287
3334
  // biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
3288
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("tr", { children: [
3289
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("th", { scope: "row", children: category }),
3335
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("tr", { children: [
3336
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("th", { scope: "row", children: category }),
3290
3337
  series.map((one) => {
3291
3338
  const value = one.values[categoryIndex];
3292
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("td", { children: value == null ? msg.chartNoValue : formatValue(value) }, one.id);
3339
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("td", { children: value == null ? msg.chartNoValue : formatValue(value) }, one.id);
3293
3340
  })
3294
3341
  ] }, categoryIndex)
3295
3342
  )) })
@@ -3298,7 +3345,7 @@ function ChartFrame({
3298
3345
  }
3299
3346
 
3300
3347
  // src/components/data/BarChart.tsx
3301
- var import_jsx_runtime49 = require("react/jsx-runtime");
3348
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3302
3349
  function BarChart({
3303
3350
  categories,
3304
3351
  series: rawSeries,
@@ -3330,7 +3377,7 @@ function BarChart({
3330
3377
  const value = series[0].values[categoryIndex];
3331
3378
  return value == null ? msg.chartNoValue : formatValue(value);
3332
3379
  };
3333
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3380
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3334
3381
  ChartFrame,
3335
3382
  {
3336
3383
  label,
@@ -3343,7 +3390,7 @@ function BarChart({
3343
3390
  showDataTable,
3344
3391
  className,
3345
3392
  style,
3346
- children: !hasData ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3393
+ children: !hasData ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3347
3394
  "div",
3348
3395
  {
3349
3396
  className: "pire-chart-bars",
@@ -3352,12 +3399,12 @@ function BarChart({
3352
3399
  style: { "--pire-chart-height": `${height}px` },
3353
3400
  children: categories.map((category, categoryIndex) => (
3354
3401
  // biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
3355
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "pire-chart-group", children: [
3356
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "pire-chart-cat", children: category }),
3357
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "pire-chart-track", children: series.map((one, seriesIndex) => {
3402
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "pire-chart-group", children: [
3403
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "pire-chart-cat", children: category }),
3404
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "pire-chart-track", children: series.map((one, seriesIndex) => {
3358
3405
  const value = one.values[categoryIndex];
3359
3406
  if (value == null) return null;
3360
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
3407
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
3361
3408
  "div",
3362
3409
  {
3363
3410
  className: "pire-chart-bar",
@@ -3366,8 +3413,8 @@ function BarChart({
3366
3413
  "--pire-bar-color": seriesColor(one, seriesIndex)
3367
3414
  },
3368
3415
  children: [
3369
- withValues && orientation === "vertical" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "pire-chart-barval", children: formatValue(value) }) : null,
3370
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "pire-chart-tip", role: "presentation", children: [
3416
+ withValues && orientation === "vertical" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "pire-chart-barval", children: formatValue(value) }) : null,
3417
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "pire-chart-tip", role: "presentation", children: [
3371
3418
  series.length > 1 ? `${one.label}: ` : "",
3372
3419
  formatValue(value)
3373
3420
  ] })
@@ -3376,7 +3423,7 @@ function BarChart({
3376
3423
  one.id
3377
3424
  );
3378
3425
  }) }),
3379
- withValues && orientation === "horizontal" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "pire-chart-val", children: horizontalLabelFor(categoryIndex) }) : null
3426
+ withValues && orientation === "horizontal" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "pire-chart-val", children: horizontalLabelFor(categoryIndex) }) : null
3380
3427
  ] }, categoryIndex)
3381
3428
  ))
3382
3429
  }
@@ -3386,14 +3433,14 @@ function BarChart({
3386
3433
  }
3387
3434
 
3388
3435
  // src/components/data/LineChart.tsx
3389
- var React23 = __toESM(require("react"), 1);
3390
- var import_jsx_runtime50 = require("react/jsx-runtime");
3436
+ var React24 = __toESM(require("react"), 1);
3437
+ var import_jsx_runtime51 = require("react/jsx-runtime");
3391
3438
  var PLOT_INSET = { top: 10, right: 14, bottom: 24, left: 58 };
3392
3439
  var MARKER_LIMIT = 20;
3393
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React23.useEffect : React23.useLayoutEffect;
3440
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React24.useEffect : React24.useLayoutEffect;
3394
3441
  function useMeasuredWidth() {
3395
- const ref = React23.useRef(null);
3396
- const [width, setWidth] = React23.useState(0);
3442
+ const ref = React24.useRef(null);
3443
+ const [width, setWidth] = React24.useState(0);
3397
3444
  useIsomorphicLayoutEffect2(() => {
3398
3445
  const element = ref.current;
3399
3446
  if (!element) return;
@@ -3454,7 +3501,7 @@ function LineChart({
3454
3501
  return `M${xAt(present[0].index)} ${baseline} L${line} L${xAt(last.index)} ${baseline} Z`;
3455
3502
  };
3456
3503
  const labelEvery = Math.max(1, Math.ceil(categories.length / Math.max(2, Math.floor(innerWidth / 64))));
3457
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3504
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3458
3505
  ChartFrame,
3459
3506
  {
3460
3507
  label,
@@ -3467,8 +3514,8 @@ function LineChart({
3467
3514
  showDataTable,
3468
3515
  className,
3469
3516
  style,
3470
- children: !hasData ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "pire-chart-lines", ref: plotRef, style: { height }, children: [
3471
- width > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
3517
+ children: !hasData ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "pire-chart-lines", ref: plotRef, style: { height }, children: [
3518
+ width > 0 ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
3472
3519
  "svg",
3473
3520
  {
3474
3521
  width,
@@ -3477,7 +3524,7 @@ function LineChart({
3477
3524
  "aria-hidden": "true",
3478
3525
  focusable: "false",
3479
3526
  children: [
3480
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("g", { className: "pire-chart-grid", children: scale.ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3527
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("g", { className: "pire-chart-grid", children: scale.ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3481
3528
  "line",
3482
3529
  {
3483
3530
  x1: PLOT_INSET.left,
@@ -3487,8 +3534,8 @@ function LineChart({
3487
3534
  },
3488
3535
  tick
3489
3536
  )) }),
3490
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("g", { className: "pire-chart-tick", children: [
3491
- scale.ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3537
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("g", { className: "pire-chart-tick", children: [
3538
+ scale.ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3492
3539
  "text",
3493
3540
  {
3494
3541
  x: PLOT_INSET.left - 8,
@@ -3501,10 +3548,10 @@ function LineChart({
3501
3548
  )),
3502
3549
  categories.map((category, index) => index % labelEvery === 0 ? (
3503
3550
  // biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
3504
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("text", { x: xAt(index), y: height - 6, textAnchor: "middle", children: category }, index)
3551
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("text", { x: xAt(index), y: height - 6, textAnchor: "middle", children: category }, index)
3505
3552
  ) : null)
3506
3553
  ] }),
3507
- showArea && series[0] ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3554
+ showArea && series[0] ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3508
3555
  "path",
3509
3556
  {
3510
3557
  d: areaFor(series[0].values),
@@ -3512,10 +3559,10 @@ function LineChart({
3512
3559
  style: { fill: seriesColor(series[0], 0) }
3513
3560
  }
3514
3561
  ) : null,
3515
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("g", { className: "pire-chart-line", fill: "none", children: series.map((one, index) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("path", { d: pathFor(one.values), stroke: seriesColor(one, index) }, one.id)) }),
3516
- withMarkers ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("g", { className: "pire-chart-marker", children: series.map((one, seriesIndex) => one.values.map((value, index) => value == null ? null : (
3562
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("g", { className: "pire-chart-line", fill: "none", children: series.map((one, index) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("path", { d: pathFor(one.values), stroke: seriesColor(one, index) }, one.id)) }),
3563
+ withMarkers ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("g", { className: "pire-chart-marker", children: series.map((one, seriesIndex) => one.values.map((value, index) => value == null ? null : (
3517
3564
  // biome-ignore lint/suspicious/noArrayIndexKey: a series is positional — the index is the point's identity, and category labels repeat.
3518
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3565
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3519
3566
  "circle",
3520
3567
  {
3521
3568
  cx: xAt(index),
@@ -3529,18 +3576,18 @@ function LineChart({
3529
3576
  ]
3530
3577
  }
3531
3578
  ) : null,
3532
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3579
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3533
3580
  "div",
3534
3581
  {
3535
3582
  className: "pire-chart-hover",
3536
3583
  style: { inset: `${PLOT_INSET.top}px ${PLOT_INSET.right}px ${PLOT_INSET.bottom}px ${PLOT_INSET.left}px` },
3537
3584
  children: categories.map((category, categoryIndex) => (
3538
3585
  // biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
3539
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "pire-chart-band", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "pire-chart-tip", role: "presentation", children: [
3540
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("strong", { children: category }),
3586
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "pire-chart-band", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "pire-chart-tip", role: "presentation", children: [
3587
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("strong", { children: category }),
3541
3588
  series.map((one) => {
3542
3589
  const value = one.values[categoryIndex];
3543
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "pire-chart-tip-row", children: [
3590
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "pire-chart-tip-row", children: [
3544
3591
  one.label,
3545
3592
  ": ",
3546
3593
  value == null ? "No data" : formatValue(value)
@@ -3556,8 +3603,8 @@ function LineChart({
3556
3603
  }
3557
3604
 
3558
3605
  // src/components/data/DonutChart.tsx
3559
- var React24 = __toESM(require("react"), 1);
3560
- var import_jsx_runtime51 = require("react/jsx-runtime");
3606
+ var React25 = __toESM(require("react"), 1);
3607
+ var import_jsx_runtime52 = require("react/jsx-runtime");
3561
3608
  var SEGMENT_GAP_DEGREES = 1.5;
3562
3609
  function DonutChart({
3563
3610
  categories,
@@ -3577,7 +3624,7 @@ function DonutChart({
3577
3624
  }) {
3578
3625
  const label = rest["aria-label"];
3579
3626
  const msg = usePireMessages();
3580
- const [hoveredIndex, setHoveredIndex] = React24.useState(null);
3627
+ const [hoveredIndex, setHoveredIndex] = React25.useState(null);
3581
3628
  warnOnDonutShape(series, categories.length, label);
3582
3629
  const values = (series[0]?.values ?? []).slice(0, categories.length);
3583
3630
  const segments = categories.map((category, index) => ({ category, index, value: values[index] ?? 0 })).filter((segment) => segment.value > 0);
@@ -3594,7 +3641,7 @@ function DonutChart({
3594
3641
  }));
3595
3642
  const hovered = hoveredIndex == null ? null : segments.find((segment) => segment.index === hoveredIndex) ?? null;
3596
3643
  let arcStart = 0;
3597
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3644
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3598
3645
  ChartFrame,
3599
3646
  {
3600
3647
  label,
@@ -3607,8 +3654,8 @@ function DonutChart({
3607
3654
  showDataTable,
3608
3655
  className,
3609
3656
  style,
3610
- children: !hasData ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "pire-chart-donut", style: { height: size }, children: [
3611
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3657
+ children: !hasData ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "pire-chart-donut", style: { height: size }, children: [
3658
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3612
3659
  "svg",
3613
3660
  {
3614
3661
  width: size,
@@ -3616,13 +3663,13 @@ function DonutChart({
3616
3663
  "aria-hidden": "true",
3617
3664
  focusable: "false",
3618
3665
  onMouseLeave: () => setHoveredIndex(null),
3619
- children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("g", { transform: `rotate(-90 ${size / 2} ${size / 2})`, children: segments.map((segment) => {
3666
+ children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("g", { transform: `rotate(-90 ${size / 2} ${size / 2})`, children: segments.map((segment) => {
3620
3667
  const arcLength = segment.value / total * circumference;
3621
3668
  const offset = arcStart;
3622
3669
  arcStart += arcLength;
3623
3670
  return (
3624
3671
  // biome-ignore lint/a11y/noStaticElementInteractions: pointer-only enhancement inside an aria-hidden plot — the arcs carry nothing the data table does not, so there is nothing here for a keyboard to reach.
3625
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3672
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3626
3673
  "circle",
3627
3674
  {
3628
3675
  className: "pire-chart-arc",
@@ -3642,9 +3689,9 @@ function DonutChart({
3642
3689
  }) })
3643
3690
  }
3644
3691
  ),
3645
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "pire-chart-donut-center", style: { width: size - thickness * 2 - 8 }, children: [
3646
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "pire-chart-donut-value", children: hovered ? formatValue(hovered.value) : centerLabel ?? formatValue(total) }),
3647
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "pire-chart-donut-caption", children: hovered ? hovered.category : centerCaption })
3692
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "pire-chart-donut-center", style: { width: size - thickness * 2 - 8 }, children: [
3693
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "pire-chart-donut-value", children: hovered ? formatValue(hovered.value) : centerLabel ?? formatValue(total) }),
3694
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "pire-chart-donut-caption", children: hovered ? hovered.category : centerCaption })
3648
3695
  ] })
3649
3696
  ] })
3650
3697
  }
@@ -3655,15 +3702,15 @@ function colorForSegment(index) {
3655
3702
  }
3656
3703
 
3657
3704
  // src/components/data/LinkList.tsx
3658
- var import_react_aria_components30 = require("react-aria-components");
3659
- var import_jsx_runtime52 = require("react/jsx-runtime");
3705
+ var import_react_aria_components31 = require("react-aria-components");
3706
+ var import_jsx_runtime53 = require("react/jsx-runtime");
3660
3707
  function LinkList({ items, onSelect, emphasis = "key", className, ...rest }) {
3661
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: cx("pire-linklist", className), role: "list", "data-emphasis": emphasis, ...rest, children: items.map((item) => {
3662
- const keySlot = item.key ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "pire-linklist-key", children: item.key }) : null;
3663
- const textSlot = item.text ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "pire-linklist-text", children: item.text }) : null;
3708
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: cx("pire-linklist", className), role: "list", "data-emphasis": emphasis, ...rest, children: items.map((item) => {
3709
+ const keySlot = item.key ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "pire-linklist-key", children: item.key }) : null;
3710
+ const textSlot = item.text ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "pire-linklist-text", children: item.text }) : null;
3664
3711
  const [first, second] = emphasis === "text" ? [textSlot, keySlot] : [keySlot, textSlot];
3665
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { role: "listitem", className: "pire-linklist-row", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_react_aria_components30.Button, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
3666
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
3712
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { role: "listitem", className: "pire-linklist-row", children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_aria_components31.Button, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
3713
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
3667
3714
  first,
3668
3715
  second,
3669
3716
  item.trailing
@@ -3672,7 +3719,7 @@ function LinkList({ items, onSelect, emphasis = "key", className, ...rest }) {
3672
3719
  }
3673
3720
 
3674
3721
  // src/components/layout/PageBand.tsx
3675
- var import_jsx_runtime53 = require("react/jsx-runtime");
3722
+ var import_jsx_runtime54 = require("react/jsx-runtime");
3676
3723
  function PageBand({
3677
3724
  surface = "card",
3678
3725
  hasBorder = true,
@@ -3680,7 +3727,7 @@ function PageBand({
3680
3727
  className,
3681
3728
  ...rest
3682
3729
  }) {
3683
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
3730
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
3684
3731
  "div",
3685
3732
  {
3686
3733
  className: cx("pire-pageband", className),
@@ -3693,56 +3740,56 @@ function PageBand({
3693
3740
  }
3694
3741
 
3695
3742
  // src/components/layout/PageHeader.tsx
3696
- var import_jsx_runtime54 = require("react/jsx-runtime");
3743
+ var import_jsx_runtime55 = require("react/jsx-runtime");
3697
3744
  function PageHeader({ title, subtitle, actions, className, ...rest }) {
3698
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("header", { className: cx("pire-pageheader", className), ...rest, children: [
3699
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { style: { minWidth: 0 }, children: [
3700
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("h1", { className: "pire-pageheader-title", children: title }),
3701
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "pire-pageheader-sub", children: subtitle }) : null
3745
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("header", { className: cx("pire-pageheader", className), ...rest, children: [
3746
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { style: { minWidth: 0 }, children: [
3747
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h1", { className: "pire-pageheader-title", children: title }),
3748
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "pire-pageheader-sub", children: subtitle }) : null
3702
3749
  ] }),
3703
- actions ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "pire-pageheader-actions", children: actions }) : null
3750
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "pire-pageheader-actions", children: actions }) : null
3704
3751
  ] });
3705
3752
  }
3706
3753
 
3707
3754
  // src/components/layout/SectionHeader.tsx
3708
- var import_jsx_runtime55 = require("react/jsx-runtime");
3755
+ var import_jsx_runtime56 = require("react/jsx-runtime");
3709
3756
  function SectionHeader({ title, meta, actions, className, ...rest }) {
3710
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("pire-sectionhead", className), ...rest, children: [
3711
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "pire-eyebrow", children: title }),
3712
- meta ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
3713
- actions ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "pire-sectionhead-actions", children: actions }) : null
3757
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: cx("pire-sectionhead", className), ...rest, children: [
3758
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "pire-eyebrow", children: title }),
3759
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
3760
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "pire-sectionhead-actions", children: actions }) : null
3714
3761
  ] });
3715
3762
  }
3716
3763
 
3717
3764
  // src/components/layout/SelectionBar.tsx
3718
- var import_jsx_runtime56 = require("react/jsx-runtime");
3765
+ var import_jsx_runtime57 = require("react/jsx-runtime");
3719
3766
  function SelectionBar({ count, noun = "record", children, actions, className, ...rest }) {
3720
3767
  if (!count) return null;
3721
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
3722
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "pire-selectionbar-count", children: [
3768
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
3769
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "pire-selectionbar-count", children: [
3723
3770
  count.toLocaleString(),
3724
3771
  " ",
3725
3772
  noun,
3726
3773
  count === 1 ? "" : "s",
3727
3774
  " selected"
3728
3775
  ] }),
3729
- children ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
3730
- actions ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "pire-selectionbar-actions", children: actions }) : null
3776
+ children ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
3777
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "pire-selectionbar-actions", children: actions }) : null
3731
3778
  ] });
3732
3779
  }
3733
3780
 
3734
3781
  // src/components/layout/FooterBar.tsx
3735
- var import_jsx_runtime57 = require("react/jsx-runtime");
3782
+ var import_jsx_runtime58 = require("react/jsx-runtime");
3736
3783
  function FooterBar({ note, actions, children, className, ...rest }) {
3737
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("footer", { className: cx("pire-footerbar", className), ...rest, children: [
3738
- note ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "pire-footerbar-note", children: note }) : null,
3784
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("footer", { className: cx("pire-footerbar", className), ...rest, children: [
3785
+ note ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "pire-footerbar-note", children: note }) : null,
3739
3786
  children,
3740
- actions ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "pire-footerbar-actions", children: actions }) : null
3787
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pire-footerbar-actions", children: actions }) : null
3741
3788
  ] });
3742
3789
  }
3743
3790
 
3744
3791
  // src/components/layout/SplitPane.tsx
3745
- var import_jsx_runtime58 = require("react/jsx-runtime");
3792
+ var import_jsx_runtime59 = require("react/jsx-runtime");
3746
3793
  function SplitPane({
3747
3794
  list,
3748
3795
  detail,
@@ -3758,7 +3805,7 @@ function SplitPane({
3758
3805
  }) {
3759
3806
  const msg = usePireMessages();
3760
3807
  const width = typeof listWidth === "number" ? `${listWidth}px` : listWidth;
3761
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
3808
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
3762
3809
  "div",
3763
3810
  {
3764
3811
  className: cx("pire-split", className),
@@ -3766,10 +3813,10 @@ function SplitPane({
3766
3813
  style: { ["--pire-split-list-w"]: width, ...style },
3767
3814
  ...rest,
3768
3815
  children: [
3769
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("section", { className: "pire-split-list", "aria-label": listLabel ?? msg.splitPaneList, children: list }),
3770
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("section", { className: "pire-split-detail", "aria-label": detailLabel ?? msg.splitPaneDetail, children: [
3771
- onBack ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pire-split-back", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: "tertiary", size: "sm", icon: "arrow-left", onPress: onBack, children: backLabel ?? msg.splitPaneBack }) }) : null,
3772
- detail ?? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pire-split-empty", children: emptyDetail })
3816
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("section", { className: "pire-split-list", "aria-label": listLabel ?? msg.splitPaneList, children: list }),
3817
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("section", { className: "pire-split-detail", "aria-label": detailLabel ?? msg.splitPaneDetail, children: [
3818
+ onBack ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "pire-split-back", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Button, { variant: "tertiary", size: "sm", icon: "arrow-left", onPress: onBack, children: backLabel ?? msg.splitPaneBack }) }) : null,
3819
+ detail ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "pire-split-empty", children: emptyDetail })
3773
3820
  ] })
3774
3821
  ]
3775
3822
  }
@@ -3777,7 +3824,7 @@ function SplitPane({
3777
3824
  }
3778
3825
 
3779
3826
  // src/components/patterns/ConfirmDialog.tsx
3780
- var import_jsx_runtime59 = require("react/jsx-runtime");
3827
+ var import_jsx_runtime60 = require("react/jsx-runtime");
3781
3828
  function ConfirmDialog({
3782
3829
  isOpen,
3783
3830
  title,
@@ -3791,7 +3838,7 @@ function ConfirmDialog({
3791
3838
  onConfirm,
3792
3839
  onCancel
3793
3840
  }) {
3794
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
3841
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
3795
3842
  Dialog,
3796
3843
  {
3797
3844
  isOpen,
@@ -3801,12 +3848,12 @@ function ConfirmDialog({
3801
3848
  onClose: onCancel,
3802
3849
  isDismissable: !isBusy,
3803
3850
  showClose: false,
3804
- footer: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
3805
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3806
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3851
+ footer: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
3852
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3853
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3807
3854
  ] }),
3808
3855
  children: [
3809
- consequence ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3856
+ consequence ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3810
3857
  children
3811
3858
  ]
3812
3859
  }
@@ -3814,9 +3861,9 @@ function ConfirmDialog({
3814
3861
  }
3815
3862
 
3816
3863
  // src/components/patterns/CommandPalette.tsx
3817
- var React25 = __toESM(require("react"), 1);
3818
- var import_react_aria_components31 = require("react-aria-components");
3819
- var import_jsx_runtime60 = require("react/jsx-runtime");
3864
+ var React26 = __toESM(require("react"), 1);
3865
+ var import_react_aria_components32 = require("react-aria-components");
3866
+ var import_jsx_runtime61 = require("react/jsx-runtime");
3820
3867
  var RESULTS_SECTION_KEY = "__pire_results__";
3821
3868
  var searchableText = (item) => [item.label, item.description, item.keywords].filter(Boolean).join(" ");
3822
3869
  function CommandPalette({
@@ -3837,17 +3884,17 @@ function CommandPalette({
3837
3884
  style
3838
3885
  }) {
3839
3886
  const msg = usePireMessages();
3840
- const [query, setQuery] = React25.useState("");
3841
- const { contains } = (0, import_react_aria_components31.useFilter)({ sensitivity: "base" });
3842
- React25.useEffect(() => {
3887
+ const [query, setQuery] = React26.useState("");
3888
+ const { contains } = (0, import_react_aria_components32.useFilter)({ sensitivity: "base" });
3889
+ React26.useEffect(() => {
3843
3890
  if (isOpen) setQuery("");
3844
3891
  }, [isOpen]);
3845
- const searchableById = React25.useMemo(() => {
3892
+ const searchableById = React26.useMemo(() => {
3846
3893
  const byId = /* @__PURE__ */ new Map();
3847
3894
  for (const group of groups) for (const item of group.items) byId.set(item.id, searchableText(item));
3848
3895
  return byId;
3849
3896
  }, [groups]);
3850
- const filter = React25.useCallback((textValue, inputValue, node) => {
3897
+ const filter = React26.useCallback((textValue, inputValue, node) => {
3851
3898
  if (node.parentKey === RESULTS_SECTION_KEY) return true;
3852
3899
  return contains(searchableById.get(String(node.key)) ?? textValue, inputValue);
3853
3900
  }, [contains, searchableById]);
@@ -3857,8 +3904,8 @@ function CommandPalette({
3857
3904
  };
3858
3905
  const sections = [...groups, ...resultsGroup ? [{ ...resultsGroup, id: RESULTS_SECTION_KEY }] : []];
3859
3906
  const status = isLoading ? loadingLabel ?? msg.commandPaletteLoading : emptyLabel ?? msg.commandPaletteEmpty;
3860
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3861
- import_react_aria_components31.ModalOverlay,
3907
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
3908
+ import_react_aria_components32.ModalOverlay,
3862
3909
  {
3863
3910
  className: "pire-cp-overlay",
3864
3911
  isOpen,
@@ -3866,12 +3913,12 @@ function CommandPalette({
3866
3913
  onOpenChange: (open) => {
3867
3914
  if (!open) onOpenChange?.(false);
3868
3915
  },
3869
- children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_aria_components31.Modal, { className: cx("pire-cp-modal", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components31.Dialog, { className: "pire-cp-dialog", "aria-label": ariaLabel ?? msg.commandPaletteLabel, children: [
3870
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components31.Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3871
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components31.SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3872
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3873
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3874
- import_react_aria_components31.Input,
3916
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_aria_components32.Modal, { className: cx("pire-cp-modal", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_react_aria_components32.Dialog, { className: "pire-cp-dialog", "aria-label": ariaLabel ?? msg.commandPaletteLabel, children: [
3917
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_react_aria_components32.Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3918
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_react_aria_components32.SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3919
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3920
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
3921
+ import_react_aria_components32.Input,
3875
3922
  {
3876
3923
  className: "pire-cp-input",
3877
3924
  autoFocus: true,
@@ -3879,16 +3926,16 @@ function CommandPalette({
3879
3926
  }
3880
3927
  )
3881
3928
  ] }),
3882
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3883
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3884
- import_react_aria_components31.Menu,
3929
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3930
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
3931
+ import_react_aria_components32.Menu,
3885
3932
  {
3886
3933
  className: "pire-cp-list",
3887
3934
  onAction: (key) => onAction?.(String(key)),
3888
- renderEmptyState: () => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "pire-cp-status", children: status }),
3889
- children: sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_aria_components31.MenuSection, { id: section.id, className: "pire-cp-section", children: [
3890
- section.label ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_aria_components31.Header, { className: "pire-cp-section-title", children: section.label }) : null,
3891
- section.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
3935
+ renderEmptyState: () => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "pire-cp-status", children: status }),
3936
+ children: sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_react_aria_components32.MenuSection, { id: section.id, className: "pire-cp-section", children: [
3937
+ section.label ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_aria_components32.Header, { className: "pire-cp-section-title", children: section.label }) : null,
3938
+ section.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
3892
3939
  MenuItem,
3893
3940
  {
3894
3941
  id: item.id,
@@ -3909,18 +3956,18 @@ function CommandPalette({
3909
3956
  // aria-hidden: the glyphs are a sighted affordance for discovering the keys. A screen
3910
3957
  // reader already announces the listbox semantics that make those keys work, so reading
3911
3958
  // "up arrow down arrow navigate" out loud is noise on every open.
3912
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
3913
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "pire-cp-hint", children: [
3914
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Kbd, { children: "\u2191" }),
3915
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Kbd, { children: "\u2193" }),
3959
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_jsx_runtime61.Fragment, { children: [
3960
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "pire-cp-hint", children: [
3961
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Kbd, { children: "\u2191" }),
3962
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Kbd, { children: "\u2193" }),
3916
3963
  msg.commandPaletteHintNavigate
3917
3964
  ] }),
3918
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "pire-cp-hint", children: [
3919
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Kbd, { children: "\u21B5" }),
3965
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "pire-cp-hint", children: [
3966
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Kbd, { children: "\u21B5" }),
3920
3967
  msg.commandPaletteHintSelect
3921
3968
  ] }),
3922
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "pire-cp-hint", children: [
3923
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Kbd, { children: "esc" }),
3969
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "pire-cp-hint", children: [
3970
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Kbd, { children: "esc" }),
3924
3971
  msg.commandPaletteHintClose
3925
3972
  ] })
3926
3973
  ] }) })
@@ -3930,9 +3977,9 @@ function CommandPalette({
3930
3977
  );
3931
3978
  }
3932
3979
  function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3933
- const handler = React25.useRef(onTrigger);
3980
+ const handler = React26.useRef(onTrigger);
3934
3981
  handler.current = onTrigger;
3935
- React25.useEffect(() => {
3982
+ React26.useEffect(() => {
3936
3983
  if (isDisabled) return;
3937
3984
  const onKeyDown = (event) => {
3938
3985
  if (!(event.metaKey || event.ctrlKey) || event.altKey) return;
@@ -3945,13 +3992,120 @@ function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3945
3992
  }, [key, isDisabled]);
3946
3993
  }
3947
3994
 
3995
+ // src/components/patterns/AppLauncher.tsx
3996
+ var React27 = __toESM(require("react"), 1);
3997
+ var import_react_aria_components33 = require("react-aria-components");
3998
+ var import_jsx_runtime62 = require("react/jsx-runtime");
3999
+ var searchableText2 = (item) => [item.label, item.description, item.keywords].filter(Boolean).join(" ");
4000
+ function AppLauncher({
4001
+ sections,
4002
+ onAction,
4003
+ value,
4004
+ title,
4005
+ meta,
4006
+ isSearchable = true,
4007
+ onSearchChange,
4008
+ isFilteredExternally,
4009
+ isLoading,
4010
+ emptyLabel,
4011
+ searchPlaceholder,
4012
+ "aria-label": ariaLabel,
4013
+ icon = "grid-2x2",
4014
+ className
4015
+ }) {
4016
+ const msg = usePireMessages();
4017
+ const [query, setQuery] = React27.useState("");
4018
+ const { contains } = (0, import_react_aria_components33.useFilter)({ sensitivity: "base" });
4019
+ const handleSearch = (next) => {
4020
+ setQuery(next);
4021
+ onSearchChange?.(next);
4022
+ };
4023
+ const visible = React27.useMemo(() => {
4024
+ if (isFilteredExternally) return sections;
4025
+ const q = query.trim();
4026
+ if (!q) return sections;
4027
+ return sections.map((section) => ({ ...section, items: section.items.filter((i) => contains(searchableText2(i), q)) })).filter((section) => section.items.length > 0);
4028
+ }, [sections, query, isFilteredExternally, contains]);
4029
+ const isEmpty = !isLoading && visible.length === 0;
4030
+ const label = ariaLabel ?? msg.appLauncherLabel;
4031
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_react_aria_components33.DialogTrigger, { children: [
4032
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_react_aria_components33.Button, { className: "pire-launcher-trigger", "aria-label": label, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Icon, { name: icon, size: 20 }) }),
4033
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4034
+ import_react_aria_components33.Popover,
4035
+ {
4036
+ className: cx("pire-launcher-popover", className),
4037
+ placement: "bottom start",
4038
+ offset: 0,
4039
+ crossOffset: 0,
4040
+ containerPadding: 0,
4041
+ children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_react_aria_components33.Dialog, { className: "pire-launcher", "aria-label": label, children: ({ close }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
4042
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "pire-launcher-head", children: [
4043
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-launcher-title", children: title ?? msg.appLauncherTitle }),
4044
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-launcher-meta", children: meta }) : null
4045
+ ] }),
4046
+ isSearchable ? (
4047
+ // autoFocus is right here specifically: the panel exists to be searched, and the
4048
+ // user just chose to open it, so taking the caret is what they asked for.
4049
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4050
+ Input,
4051
+ {
4052
+ "aria-label": msg.appLauncherSearch,
4053
+ icon: "search",
4054
+ type: "search",
4055
+ autoFocus: true,
4056
+ isClearable: true,
4057
+ value: query,
4058
+ onChange: handleSearch,
4059
+ placeholder: searchPlaceholder ?? msg.appLauncherSearch
4060
+ }
4061
+ )
4062
+ ) : null,
4063
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "pire-launcher-empty", role: "status", "aria-live": "polite", children: msg.appLauncherLoading }) : null,
4064
+ isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "pire-launcher-empty", children: emptyLabel ?? msg.appLauncherEmpty }) : null,
4065
+ visible.map((section, si) => (
4066
+ // Sections are positional zones with no record identity, so the heading is the key
4067
+ // where there is one. Same reasoning as ShellRail's groups.
4068
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "pire-launcher-section", children: [
4069
+ section.label ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "pire-eyebrow", children: section.label }) : null,
4070
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "pire-launcher-grid", "data-variant": section.variant ?? "tile", children: section.items.map((item) => {
4071
+ const isCurrent = item.id === value;
4072
+ const showsDescription = (section.variant ?? "tile") === "tile" && Boolean(item.description);
4073
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
4074
+ import_react_aria_components33.Button,
4075
+ {
4076
+ className: "pire-launcher-item",
4077
+ "data-selected": isCurrent ? "true" : void 0,
4078
+ "aria-current": isCurrent ? "true" : void 0,
4079
+ onPress: () => {
4080
+ close();
4081
+ onAction?.(item.id);
4082
+ },
4083
+ children: [
4084
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-launcher-item-icon", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Icon, { name: item.icon, size: (section.variant ?? "tile") === "tile" ? 20 : 16 }) }) : null,
4085
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "pire-launcher-item-text", children: [
4086
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-launcher-item-label", children: item.label }),
4087
+ showsDescription ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "pire-launcher-item-desc", children: item.description }) : null
4088
+ ] })
4089
+ ]
4090
+ },
4091
+ item.id
4092
+ );
4093
+ }) })
4094
+ ] }, section.label ?? section.items[0]?.id ?? si)
4095
+ ))
4096
+ ] }) })
4097
+ }
4098
+ )
4099
+ ] });
4100
+ }
4101
+
3948
4102
  // src/components/patterns/SidePanel.tsx
3949
- var import_react_aria_components32 = require("react-aria-components");
3950
- var import_jsx_runtime61 = require("react/jsx-runtime");
4103
+ var import_react_aria_components34 = require("react-aria-components");
4104
+ var import_jsx_runtime63 = require("react/jsx-runtime");
3951
4105
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
3952
4106
  const msg = usePireMessages();
3953
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
3954
- import_react_aria_components32.ModalOverlay,
4107
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4108
+ import_react_aria_components34.ModalOverlay,
3955
4109
  {
3956
4110
  className: "pire-sidepanel-overlay",
3957
4111
  isOpen,
@@ -3959,36 +4113,36 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
3959
4113
  onOpenChange: (o) => {
3960
4114
  if (!o) onClose?.();
3961
4115
  },
3962
- children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_aria_components32.Modal, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_react_aria_components32.Dialog, { className: "pire-dialog", style: { height: "100%" }, children: [
3963
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("header", { className: "pire-dialog-head", children: [
3964
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
3965
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_aria_components32.Heading, { slot: "title", className: "pire-dialog-title", children: title }),
3966
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
4116
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_react_aria_components34.Modal, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_react_aria_components34.Dialog, { className: "pire-dialog", style: { height: "100%" }, children: [
4117
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("header", { className: "pire-dialog-head", children: [
4118
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
4119
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_react_aria_components34.Heading, { slot: "title", className: "pire-dialog-title", children: title }),
4120
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
3967
4121
  ] }),
3968
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
4122
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
3969
4123
  ] }),
3970
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
3971
- footer ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("footer", { className: "pire-dialog-foot", children: footer }) : null
4124
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
4125
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("footer", { className: "pire-dialog-foot", children: footer }) : null
3972
4126
  ] }) })
3973
4127
  }
3974
4128
  );
3975
4129
  }
3976
4130
 
3977
4131
  // src/components/patterns/EmptyState.tsx
3978
- var import_jsx_runtime62 = require("react/jsx-runtime");
4132
+ var import_jsx_runtime64 = require("react/jsx-runtime");
3979
4133
  function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
3980
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
3981
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
3982
- title ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
3983
- children ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
4134
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
4135
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
4136
+ title ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
4137
+ children ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
3984
4138
  action
3985
4139
  ] });
3986
4140
  }
3987
4141
 
3988
4142
  // src/components/patterns/FileDropZone.tsx
3989
- var React26 = __toESM(require("react"), 1);
3990
- var import_react_aria_components33 = require("react-aria-components");
3991
- var import_jsx_runtime63 = require("react/jsx-runtime");
4143
+ var React28 = __toESM(require("react"), 1);
4144
+ var import_react_aria_components35 = require("react-aria-components");
4145
+ var import_jsx_runtime65 = require("react/jsx-runtime");
3992
4146
  var isImage2 = (file) => file.type.startsWith("image/");
3993
4147
  function FileDropZone({
3994
4148
  label,
@@ -4016,10 +4170,10 @@ function FileDropZone({
4016
4170
  ...rest
4017
4171
  }) {
4018
4172
  const msg = usePireMessages();
4019
- const [uncontrolled, setUncontrolled] = React26.useState(defaultValue ?? []);
4173
+ const [uncontrolled, setUncontrolled] = React28.useState(defaultValue ?? []);
4020
4174
  const files = value ?? uncontrolled;
4021
- const created = React26.useRef([]);
4022
- React26.useEffect(() => () => {
4175
+ const created = React28.useRef([]);
4176
+ React28.useEffect(() => () => {
4023
4177
  for (const url of created.current) URL.revokeObjectURL(url);
4024
4178
  }, []);
4025
4179
  const commit = (next) => {
@@ -4039,13 +4193,13 @@ function FileDropZone({
4039
4193
  commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
4040
4194
  };
4041
4195
  const remove = (target) => commit(files.filter((f) => f.file !== target));
4042
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), ...rest, children: [
4043
- label ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "pire-field-label", children: [
4196
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), ...rest, children: [
4197
+ label ? /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "pire-field-label", children: [
4044
4198
  label,
4045
- isRequired ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
4199
+ isRequired ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
4046
4200
  ] }) : null,
4047
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
4048
- import_react_aria_components33.DropZone,
4201
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
4202
+ import_react_aria_components35.DropZone,
4049
4203
  {
4050
4204
  className: "pire-dropzone",
4051
4205
  "aria-label": ariaLabel,
@@ -4053,30 +4207,30 @@ function FileDropZone({
4053
4207
  isDisabled: isDisabled || isReadOnly,
4054
4208
  onDrop: async (e) => {
4055
4209
  const dropped = await Promise.all(
4056
- e.items.filter(import_react_aria_components33.isFileDropItem).map((item) => item.getFile())
4210
+ e.items.filter(import_react_aria_components35.isFileDropItem).map((item) => item.getFile())
4057
4211
  );
4058
4212
  accept(dropped);
4059
4213
  },
4060
4214
  children: [
4061
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
4062
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
4063
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4064
- import_react_aria_components33.FileTrigger,
4215
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
4216
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
4217
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
4218
+ import_react_aria_components35.FileTrigger,
4065
4219
  {
4066
4220
  acceptedFileTypes,
4067
4221
  allowsMultiple,
4068
4222
  onSelect: (list) => accept(list ? [...list] : []),
4069
- children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
4223
+ children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
4070
4224
  }
4071
4225
  )
4072
4226
  ]
4073
4227
  }
4074
4228
  ),
4075
- files.length ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("li", { className: "pire-fileupload-item", children: [
4076
- previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
4077
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-fileupload-name", children: file.name }),
4078
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
4079
- isDisabled || isReadOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4229
+ files.length ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("li", { className: "pire-fileupload-item", children: [
4230
+ previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
4231
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-fileupload-name", children: file.name }),
4232
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
4233
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
4080
4234
  IconButton,
4081
4235
  {
4082
4236
  icon: "x",
@@ -4086,17 +4240,18 @@ function FileDropZone({
4086
4240
  }
4087
4241
  )
4088
4242
  ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
4089
- uploadProgress != null ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
4090
- description ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-field-hint", children: description }) : null,
4091
- isInvalid && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "pire-field-error", children: errorMessage }) : null
4243
+ uploadProgress != null ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
4244
+ description ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-field-hint", children: description }) : null,
4245
+ isInvalid && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-field-error", children: errorMessage }) : null
4092
4246
  ] });
4093
4247
  }
4094
4248
 
4095
4249
  // src/index.ts
4096
- var import_react_aria_components34 = require("react-aria-components");
4097
- var import_react_aria_components35 = require("react-aria-components");
4250
+ var import_react_aria_components36 = require("react-aria-components");
4251
+ var import_react_aria_components37 = require("react-aria-components");
4098
4252
  // Annotate the CommonJS export names for ESM import in node:
4099
4253
  0 && (module.exports = {
4254
+ AppLauncher,
4100
4255
  Avatar,
4101
4256
  Badge,
4102
4257
  BarChart,
@@ -4160,6 +4315,7 @@ var import_react_aria_components35 = require("react-aria-components");
4160
4315
  SelectionBar,
4161
4316
  Separator,
4162
4317
  ShellBar,
4318
+ ShellRail,
4163
4319
  SideNav,
4164
4320
  SidePanel,
4165
4321
  Skeleton,