@orianatech/pire 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -120,6 +120,7 @@ var ICON_MARKUP = {
120
120
  "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"/>',
121
121
  "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"/>',
122
122
  "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"/>',
123
+ "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"/>',
123
124
  "subtract": '<path d="M8 15H24V17H8z"/>',
124
125
  "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"/>',
125
126
  "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"/>',
@@ -147,6 +148,9 @@ var CARBON_MAP = {
147
148
  "bell": "notification",
148
149
  "help-circle": "help",
149
150
  "grid-3x3": "grid",
151
+ /* The app launcher's trigger. Carbon has no 2x2 grid, and `apps` is the glyph it uses for
152
+ exactly this affordance, so the Lucide name maps onto it rather than onto plain `grid`. */
153
+ "grid-2x2": "apps",
150
154
  "home": "home",
151
155
  "file-text": "document",
152
156
  "clipboard-list": "list--checked",
@@ -191,6 +195,7 @@ var CARBON_MAP = {
191
195
  "trending-up": "arrow--up",
192
196
  "trending-down": "arrow--down",
193
197
  "shopping-cart": "shopping--cart",
198
+ "store": "store",
194
199
  "user": "user",
195
200
  "shapes": "apps",
196
201
  "type": "text--font",
@@ -766,6 +771,12 @@ var enMessages = {
766
771
  paginationNext: "Next page",
767
772
  paginationRowsPerPage: "Rows per page",
768
773
  sideNavLabel: "Main navigation",
774
+ shellRailLabel: "Applications",
775
+ appLauncherLabel: "All applications",
776
+ appLauncherTitle: "All applications",
777
+ appLauncherSearch: "Search for an application",
778
+ appLauncherEmpty: "No application matches that search.",
779
+ appLauncherLoading: "Loading applications\u2026",
769
780
  splitPaneList: "List",
770
781
  splitPaneDetail: "Detail",
771
782
  splitPaneBack: "Back to list",
@@ -784,7 +795,9 @@ var enMessages = {
784
795
  commandPaletteHintClose: "close",
785
796
  chartCategoryHeader: "Category",
786
797
  chartNoValue: "No data",
787
- chartEmpty: "No data for this period"
798
+ chartEmpty: "No data for this period",
799
+ numPadClear: "Clear",
800
+ numPadBackspace: "Remove last digit"
788
801
  };
789
802
  var esMessages = {
790
803
  filterBarLabel: "Filtros",
@@ -826,6 +839,12 @@ var esMessages = {
826
839
  paginationNext: "P\xE1gina siguiente",
827
840
  paginationRowsPerPage: "Filas por p\xE1gina",
828
841
  sideNavLabel: "Navegaci\xF3n principal",
842
+ shellRailLabel: "Aplicaciones",
843
+ appLauncherLabel: "Todas las aplicaciones",
844
+ appLauncherTitle: "Todas las aplicaciones",
845
+ appLauncherSearch: "Busc\xE1 una aplicaci\xF3n",
846
+ appLauncherEmpty: "Ninguna aplicaci\xF3n coincide con esa b\xFAsqueda.",
847
+ appLauncherLoading: "Cargando aplicaciones\u2026",
829
848
  splitPaneList: "Lista",
830
849
  splitPaneDetail: "Detalle",
831
850
  splitPaneBack: "Volver a la lista",
@@ -844,7 +863,9 @@ var esMessages = {
844
863
  commandPaletteHintClose: "cerrar",
845
864
  chartCategoryHeader: "Categor\xEDa",
846
865
  chartNoValue: "Sin datos",
847
- chartEmpty: "Sin datos para este per\xEDodo"
866
+ chartEmpty: "Sin datos para este per\xEDodo",
867
+ numPadClear: "Limpiar",
868
+ numPadBackspace: "Borrar \xFAltimo d\xEDgito"
848
869
  };
849
870
 
850
871
  // src/i18n/PireIntlProvider.tsx
@@ -2573,6 +2594,7 @@ import { MenuTrigger, Button as AriaButton11, Popover as Popover6 } from "react-
2573
2594
  import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2574
2595
  var initials2 = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
2575
2596
  function ShellBar({
2597
+ launcher,
2576
2598
  product,
2577
2599
  monogram,
2578
2600
  title,
@@ -2589,6 +2611,7 @@ function ShellBar({
2589
2611
  }) {
2590
2612
  const msg = usePireMessages();
2591
2613
  return /* @__PURE__ */ jsxs27("header", { className: cx("pire-shellbar", className), ...rest, children: [
2614
+ launcher,
2592
2615
  onMenu ? /* @__PURE__ */ jsx35(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
2593
2616
  monogram ? /* @__PURE__ */ jsx35("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
2594
2617
  product ? /* @__PURE__ */ jsx35("span", { className: "pire-shellbar-product", children: product }) : null,
@@ -2848,11 +2871,37 @@ function SideNav({
2848
2871
  );
2849
2872
  }
2850
2873
 
2874
+ // src/components/navigation/ShellRail.tsx
2875
+ import * as React22 from "react";
2876
+ import { Button as AriaButton13 } from "react-aria-components";
2877
+ import { jsx as jsx38, jsxs as jsxs30 } from "react/jsx-runtime";
2878
+ function ShellRail({ groups, value, onChange, className, ...rest }) {
2879
+ const msg = usePireMessages();
2880
+ return /* @__PURE__ */ jsx38("nav", { className: cx("pire-shellrail", className), "aria-label": msg.shellRailLabel, ...rest, children: groups.map((group, gi) => (
2881
+ // The divider is a sibling of the groups rather than a pseudo-element on one, because the
2882
+ // scrolling zone would carry its own rule out of view on the first wheel event.
2883
+ /* @__PURE__ */ jsxs30(React22.Fragment, { children: [
2884
+ gi > 0 ? /* @__PURE__ */ jsx38("div", { className: "pire-shellrail-divider" }) : null,
2885
+ /* @__PURE__ */ jsx38("div", { className: "pire-shellrail-group", "data-scroll": group.isScrollable ? "true" : void 0, children: group.items.map((item) => /* @__PURE__ */ jsx38(Tooltip, { label: item.label, placement: "right", children: /* @__PURE__ */ jsx38(
2886
+ AriaButton13,
2887
+ {
2888
+ className: "pire-shellrail-item",
2889
+ "aria-label": item.label,
2890
+ "data-selected": item.id === value ? "true" : void 0,
2891
+ "aria-current": item.id === value ? "true" : void 0,
2892
+ onPress: () => onChange?.(item.id),
2893
+ children: /* @__PURE__ */ jsx38("span", { className: "pire-shellrail-tile", children: /* @__PURE__ */ jsx38(Icon, { name: item.icon, size: 20 }) })
2894
+ }
2895
+ ) }, item.id)) })
2896
+ ] }, group.items[0]?.id ?? gi)
2897
+ )) });
2898
+ }
2899
+
2851
2900
  // src/components/navigation/Tabs.tsx
2852
2901
  import { Tabs as AriaTabs, TabList, Tab as AriaTab, TabPanel } from "react-aria-components";
2853
- import { jsx as jsx38, jsxs as jsxs30 } from "react/jsx-runtime";
2902
+ import { jsx as jsx39, jsxs as jsxs31 } from "react/jsx-runtime";
2854
2903
  function Tabs({ items, value, defaultValue, onChange, panels, className, style, ...rest }) {
2855
- return /* @__PURE__ */ jsxs30(
2904
+ return /* @__PURE__ */ jsxs31(
2856
2905
  AriaTabs,
2857
2906
  {
2858
2907
  className,
@@ -2861,12 +2910,12 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
2861
2910
  defaultSelectedKey: defaultValue,
2862
2911
  onSelectionChange: (k) => onChange?.(String(k)),
2863
2912
  children: [
2864
- /* @__PURE__ */ jsx38(TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ jsxs30(AriaTab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
2865
- item.icon ? /* @__PURE__ */ jsx38(Icon, { name: item.icon, size: 16 }) : null,
2913
+ /* @__PURE__ */ jsx39(TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ jsxs31(AriaTab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
2914
+ item.icon ? /* @__PURE__ */ jsx39(Icon, { name: item.icon, size: 16 }) : null,
2866
2915
  item.label,
2867
- item.count != null ? /* @__PURE__ */ jsx38("span", { className: "pire-tab-count", children: item.count }) : null
2916
+ item.count != null ? /* @__PURE__ */ jsx39("span", { className: "pire-tab-count", children: item.count }) : null
2868
2917
  ] }) }),
2869
- items.map((item) => /* @__PURE__ */ jsx38(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2918
+ items.map((item) => /* @__PURE__ */ jsx39(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2870
2919
  ]
2871
2920
  }
2872
2921
  );
@@ -2874,9 +2923,9 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
2874
2923
 
2875
2924
  // src/components/navigation/Breadcrumb.tsx
2876
2925
  import { Breadcrumbs as AriaBreadcrumbs, Breadcrumb as AriaBreadcrumb, Link as Link2 } from "react-aria-components";
2877
- import { jsx as jsx39, jsxs as jsxs31 } from "react/jsx-runtime";
2926
+ import { jsx as jsx40, jsxs as jsxs32 } from "react/jsx-runtime";
2878
2927
  function Breadcrumb({ items, onNavigate, className, style }) {
2879
- return /* @__PURE__ */ jsx39(
2928
+ return /* @__PURE__ */ jsx40(
2880
2929
  AriaBreadcrumbs,
2881
2930
  {
2882
2931
  className: cx("pire-breadcrumbs", className),
@@ -2885,9 +2934,9 @@ function Breadcrumb({ items, onNavigate, className, style }) {
2885
2934
  onAction: (key) => onNavigate?.(String(key)),
2886
2935
  children: (item) => {
2887
2936
  const last = items[items.length - 1] === item;
2888
- return /* @__PURE__ */ jsxs31(AriaBreadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
2889
- last ? item.label : /* @__PURE__ */ jsx39(Link2, { href: item.href, children: item.label }),
2890
- last ? null : /* @__PURE__ */ jsx39(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
2937
+ return /* @__PURE__ */ jsxs32(AriaBreadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
2938
+ last ? item.label : /* @__PURE__ */ jsx40(Link2, { href: item.href, children: item.label }),
2939
+ last ? null : /* @__PURE__ */ jsx40(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
2891
2940
  ] });
2892
2941
  }
2893
2942
  }
@@ -2895,7 +2944,7 @@ function Breadcrumb({ items, onNavigate, className, style }) {
2895
2944
  }
2896
2945
 
2897
2946
  // src/components/navigation/Pagination.tsx
2898
- import { jsx as jsx40, jsxs as jsxs32 } from "react/jsx-runtime";
2947
+ import { jsx as jsx41, jsxs as jsxs33 } from "react/jsx-runtime";
2899
2948
  function Pagination({
2900
2949
  page = 1,
2901
2950
  pageSize = 25,
@@ -2910,9 +2959,9 @@ function Pagination({
2910
2959
  const pages = Math.max(1, Math.ceil(total / pageSize));
2911
2960
  const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
2912
2961
  const to = Math.min(total, page * pageSize);
2913
- return /* @__PURE__ */ jsxs32("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
2914
- /* @__PURE__ */ jsx40("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
2915
- /* @__PURE__ */ jsx40(
2962
+ return /* @__PURE__ */ jsxs33("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
2963
+ /* @__PURE__ */ jsx41("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
2964
+ /* @__PURE__ */ jsx41(
2916
2965
  IconButton,
2917
2966
  {
2918
2967
  icon: "chevron-left",
@@ -2923,8 +2972,8 @@ function Pagination({
2923
2972
  onPress: () => onPageChange?.(page - 1)
2924
2973
  }
2925
2974
  ),
2926
- /* @__PURE__ */ jsx40("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
2927
- /* @__PURE__ */ jsx40(
2975
+ /* @__PURE__ */ jsx41("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
2976
+ /* @__PURE__ */ jsx41(
2928
2977
  IconButton,
2929
2978
  {
2930
2979
  icon: "chevron-right",
@@ -2935,7 +2984,7 @@ function Pagination({
2935
2984
  onPress: () => onPageChange?.(page + 1)
2936
2985
  }
2937
2986
  ),
2938
- onPageSizeChange ? /* @__PURE__ */ jsx40(
2987
+ onPageSizeChange ? /* @__PURE__ */ jsx41(
2939
2988
  Select,
2940
2989
  {
2941
2990
  "aria-label": msg.paginationRowsPerPage,
@@ -2951,7 +3000,7 @@ function Pagination({
2951
3000
  }
2952
3001
 
2953
3002
  // src/components/feedback/InlineMessage.tsx
2954
- import { jsx as jsx41, jsxs as jsxs33 } from "react/jsx-runtime";
3003
+ import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
2955
3004
  var KIND_ICON = {
2956
3005
  info: "info",
2957
3006
  success: "check-circle-2",
@@ -2961,7 +3010,7 @@ var KIND_ICON = {
2961
3010
  function InlineMessage({ kind = "info", title, action, onClose, children, className, ...rest }) {
2962
3011
  const msg = usePireMessages();
2963
3012
  const assertive = kind === "error" || kind === "warning";
2964
- return /* @__PURE__ */ jsxs33(
3013
+ return /* @__PURE__ */ jsxs34(
2965
3014
  "div",
2966
3015
  {
2967
3016
  className: cx("pire-msg", className),
@@ -2970,21 +3019,21 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
2970
3019
  "aria-live": assertive ? "assertive" : "polite",
2971
3020
  ...rest,
2972
3021
  children: [
2973
- /* @__PURE__ */ jsx41(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
2974
- /* @__PURE__ */ jsxs33("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
2975
- title ? /* @__PURE__ */ jsx41("span", { className: "pire-msg-title", children: title }) : null,
2976
- children ? /* @__PURE__ */ jsx41("span", { className: "pire-msg-body", children }) : null,
3022
+ /* @__PURE__ */ jsx42(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
3023
+ /* @__PURE__ */ jsxs34("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
3024
+ title ? /* @__PURE__ */ jsx42("span", { className: "pire-msg-title", children: title }) : null,
3025
+ children ? /* @__PURE__ */ jsx42("span", { className: "pire-msg-body", children }) : null,
2977
3026
  action
2978
3027
  ] }),
2979
- onClose ? /* @__PURE__ */ jsx41(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
3028
+ onClose ? /* @__PURE__ */ jsx42(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
2980
3029
  ]
2981
3030
  }
2982
3031
  );
2983
3032
  }
2984
3033
 
2985
3034
  // src/components/feedback/Toast.tsx
2986
- import * as React22 from "react";
2987
- import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
3035
+ import * as React23 from "react";
3036
+ import { jsx as jsx43, jsxs as jsxs35 } from "react/jsx-runtime";
2988
3037
  var KIND_ICON2 = {
2989
3038
  info: "info",
2990
3039
  success: "check-circle-2",
@@ -2993,7 +3042,7 @@ var KIND_ICON2 = {
2993
3042
  };
2994
3043
  function Toast({ kind = "success", onClose, position = "bottom-center", children, className, ...rest }) {
2995
3044
  const msg = usePireMessages();
2996
- return /* @__PURE__ */ jsxs34(
3045
+ return /* @__PURE__ */ jsxs35(
2997
3046
  "div",
2998
3047
  {
2999
3048
  className: cx("pire-toast", className),
@@ -3002,40 +3051,40 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
3002
3051
  "aria-live": kind === "error" ? "assertive" : "polite",
3003
3052
  ...rest,
3004
3053
  children: [
3005
- /* @__PURE__ */ jsx42(Icon, { name: KIND_ICON2[kind], size: 16 }),
3006
- /* @__PURE__ */ jsx42("span", { style: { flex: 1 }, children }),
3007
- onClose ? /* @__PURE__ */ jsx42(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
3054
+ /* @__PURE__ */ jsx43(Icon, { name: KIND_ICON2[kind], size: 16 }),
3055
+ /* @__PURE__ */ jsx43("span", { style: { flex: 1 }, children }),
3056
+ onClose ? /* @__PURE__ */ jsx43(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
3008
3057
  ]
3009
3058
  }
3010
3059
  );
3011
3060
  }
3012
- var ToastContext = React22.createContext(null);
3061
+ var ToastContext = React23.createContext(null);
3013
3062
  function ToastProvider({ children, timeout = 6e3 }) {
3014
3063
  const msg = usePireMessages();
3015
- const [toasts, setToasts] = React22.useState([]);
3016
- const close = React22.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
3017
- const add = React22.useCallback((toast) => {
3064
+ const [toasts, setToasts] = React23.useState([]);
3065
+ const close = React23.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
3066
+ const add = React23.useCallback((toast) => {
3018
3067
  const id = Math.random().toString(36).slice(2);
3019
3068
  setToasts((t) => [...t, { ...toast, id }]);
3020
3069
  const ms = toast.timeout ?? timeout;
3021
3070
  if (ms > 0) setTimeout(() => close(id), ms);
3022
3071
  return id;
3023
3072
  }, [close, timeout]);
3024
- const value = React22.useMemo(() => ({ add, close }), [add, close]);
3025
- return /* @__PURE__ */ jsxs34(ToastContext.Provider, { value, children: [
3073
+ const value = React23.useMemo(() => ({ add, close }), [add, close]);
3074
+ return /* @__PURE__ */ jsxs35(ToastContext.Provider, { value, children: [
3026
3075
  children,
3027
- /* @__PURE__ */ jsx42("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ jsx42(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
3076
+ /* @__PURE__ */ jsx43("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ jsx43(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
3028
3077
  ] });
3029
3078
  }
3030
3079
  function useToast() {
3031
- const ctx = React22.useContext(ToastContext);
3080
+ const ctx = React23.useContext(ToastContext);
3032
3081
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
3033
3082
  return ctx;
3034
3083
  }
3035
3084
 
3036
3085
  // src/components/data/KpiTile.tsx
3037
- import { Button as AriaButton13 } from "react-aria-components";
3038
- import { Fragment as Fragment3, jsx as jsx43, jsxs as jsxs35 } from "react/jsx-runtime";
3086
+ import { Button as AriaButton14 } from "react-aria-components";
3087
+ import { Fragment as Fragment4, jsx as jsx44, jsxs as jsxs36 } from "react/jsx-runtime";
3039
3088
  function KpiTile({
3040
3089
  label,
3041
3090
  value,
@@ -3051,50 +3100,50 @@ function KpiTile({
3051
3100
  style
3052
3101
  }) {
3053
3102
  const tone = deltaTone ?? (deltaDirection === "down" ? "negative" : "positive");
3054
- const body = /* @__PURE__ */ jsxs35(Fragment3, { children: [
3055
- /* @__PURE__ */ jsxs35("span", { className: "pire-kpi-label", children: [
3056
- icon ? /* @__PURE__ */ jsx43(Icon, { name: icon, size: 16 }) : null,
3103
+ const body = /* @__PURE__ */ jsxs36(Fragment4, { children: [
3104
+ /* @__PURE__ */ jsxs36("span", { className: "pire-kpi-label", children: [
3105
+ icon ? /* @__PURE__ */ jsx44(Icon, { name: icon, size: 16 }) : null,
3057
3106
  label
3058
3107
  ] }),
3059
- /* @__PURE__ */ jsxs35("span", { className: "pire-kpi-value", children: [
3108
+ /* @__PURE__ */ jsxs36("span", { className: "pire-kpi-value", children: [
3060
3109
  value,
3061
- unit ? /* @__PURE__ */ jsx43("span", { className: "pire-kpi-unit", children: unit }) : null
3110
+ unit ? /* @__PURE__ */ jsx44("span", { className: "pire-kpi-unit", children: unit }) : null
3062
3111
  ] }),
3063
- delta ? /* @__PURE__ */ jsxs35("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
3064
- deltaDirection ? /* @__PURE__ */ jsx43(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
3112
+ delta ? /* @__PURE__ */ jsxs36("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
3113
+ deltaDirection ? /* @__PURE__ */ jsx44(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
3065
3114
  delta
3066
3115
  ] }) : null,
3067
- footnote ? /* @__PURE__ */ jsx43("span", { className: "pire-kpi-foot", children: footnote }) : null
3116
+ footnote ? /* @__PURE__ */ jsx44("span", { className: "pire-kpi-foot", children: footnote }) : null
3068
3117
  ] });
3069
3118
  const props = { className: cx("pire-kpi", className), "data-status": status, style };
3070
- return onPress ? /* @__PURE__ */ jsx43(AriaButton13, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ jsx43("div", { ...props, children: body });
3119
+ return onPress ? /* @__PURE__ */ jsx44(AriaButton14, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ jsx44("div", { ...props, children: body });
3071
3120
  }
3072
3121
 
3073
3122
  // src/components/data/ObjectHeader.tsx
3074
- import { jsx as jsx44, jsxs as jsxs36 } from "react/jsx-runtime";
3123
+ import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
3075
3124
  function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions, className, ...rest }) {
3076
- return /* @__PURE__ */ jsxs36("header", { className: cx("pire-objheader", className), ...rest, children: [
3125
+ return /* @__PURE__ */ jsxs37("header", { className: cx("pire-objheader", className), ...rest, children: [
3077
3126
  breadcrumb,
3078
- /* @__PURE__ */ jsxs36("div", { className: "pire-objheader-row", children: [
3079
- /* @__PURE__ */ jsxs36("div", { style: { minWidth: 0 }, children: [
3080
- /* @__PURE__ */ jsx44("h1", { className: "pire-objheader-title", children: title }),
3081
- subtitle || id ? /* @__PURE__ */ jsxs36("div", { className: "pire-objheader-sub", children: [
3127
+ /* @__PURE__ */ jsxs37("div", { className: "pire-objheader-row", children: [
3128
+ /* @__PURE__ */ jsxs37("div", { style: { minWidth: 0 }, children: [
3129
+ /* @__PURE__ */ jsx45("h1", { className: "pire-objheader-title", children: title }),
3130
+ subtitle || id ? /* @__PURE__ */ jsxs37("div", { className: "pire-objheader-sub", children: [
3082
3131
  subtitle,
3083
- id ? /* @__PURE__ */ jsx44("span", { className: "pire-objheader-id", children: id }) : null
3132
+ id ? /* @__PURE__ */ jsx45("span", { className: "pire-objheader-id", children: id }) : null
3084
3133
  ] }) : null
3085
3134
  ] }),
3086
3135
  badge,
3087
- actions ? /* @__PURE__ */ jsx44("div", { className: "pire-objheader-actions", children: actions }) : null
3136
+ actions ? /* @__PURE__ */ jsx45("div", { className: "pire-objheader-actions", children: actions }) : null
3088
3137
  ] }),
3089
- facts?.length ? /* @__PURE__ */ jsx44("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs36("div", { children: [
3090
- /* @__PURE__ */ jsx44("dt", { className: "pire-fact-label", children: fact.label }),
3091
- /* @__PURE__ */ jsx44("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
3138
+ facts?.length ? /* @__PURE__ */ jsx45("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs37("div", { children: [
3139
+ /* @__PURE__ */ jsx45("dt", { className: "pire-fact-label", children: fact.label }),
3140
+ /* @__PURE__ */ jsx45("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
3092
3141
  ] }, fact.label)) }) : null
3093
3142
  ] });
3094
3143
  }
3095
3144
 
3096
3145
  // src/components/data/FilterBar.tsx
3097
- import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
3146
+ import { jsx as jsx46, jsxs as jsxs38 } from "react/jsx-runtime";
3098
3147
  function FilterBar({
3099
3148
  children,
3100
3149
  activeFilters = [],
@@ -3111,49 +3160,49 @@ function FilterBar({
3111
3160
  const label = useMessage("filterBarLabel", rest["aria-label"]);
3112
3161
  const go = useMessage("filterBarGo", goLabel);
3113
3162
  const clearAll = useMessage("filterBarClearAll", clearAllLabel);
3114
- return /* @__PURE__ */ jsxs37("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
3115
- /* @__PURE__ */ jsxs37("div", { className: "pire-filterbar-controls", children: [
3163
+ return /* @__PURE__ */ jsxs38("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
3164
+ /* @__PURE__ */ jsxs38("div", { className: "pire-filterbar-controls", children: [
3116
3165
  children,
3117
- onGo ? /* @__PURE__ */ jsx45(Button, { variant: "primary", onPress: onGo, children: go }) : null
3166
+ onGo ? /* @__PURE__ */ jsx46(Button, { variant: "primary", onPress: onGo, children: go }) : null
3118
3167
  ] }),
3119
- activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs37("div", { className: "pire-filterbar-foot", children: [
3120
- activeFilters.map((filter) => /* @__PURE__ */ jsx45(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
3121
- activeFilters.length && onClear ? /* @__PURE__ */ jsx45(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
3122
- resultLabel ? /* @__PURE__ */ jsx45("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
3123
- actions ? /* @__PURE__ */ jsx45("div", { className: "pire-filterbar-actions", children: actions }) : null
3168
+ activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs38("div", { className: "pire-filterbar-foot", children: [
3169
+ activeFilters.map((filter) => /* @__PURE__ */ jsx46(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
3170
+ activeFilters.length && onClear ? /* @__PURE__ */ jsx46(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
3171
+ resultLabel ? /* @__PURE__ */ jsx46("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
3172
+ actions ? /* @__PURE__ */ jsx46("div", { className: "pire-filterbar-actions", children: actions }) : null
3124
3173
  ] }) : null
3125
3174
  ] });
3126
3175
  }
3127
3176
 
3128
3177
  // src/components/data/DescriptionList.tsx
3129
- import { jsx as jsx46, jsxs as jsxs38 } from "react/jsx-runtime";
3178
+ import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
3130
3179
  function DescriptionList({ items, layout = "rows", columns = 3, className, style, ...rest }) {
3131
- return /* @__PURE__ */ jsx46(
3180
+ return /* @__PURE__ */ jsx47(
3132
3181
  "dl",
3133
3182
  {
3134
3183
  className: cx("pire-dl", className),
3135
3184
  "data-layout": layout,
3136
3185
  style: { ...layout === "grid" ? { "--pire-dl-cols": columns } : null, ...style },
3137
3186
  ...rest,
3138
- children: items.map((item, i) => /* @__PURE__ */ jsxs38("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
3139
- /* @__PURE__ */ jsxs38("dt", { className: "pire-dl-term", children: [
3187
+ children: items.map((item, i) => /* @__PURE__ */ jsxs39("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
3188
+ /* @__PURE__ */ jsxs39("dt", { className: "pire-dl-term", children: [
3140
3189
  item.label,
3141
3190
  item.hint
3142
3191
  ] }),
3143
- /* @__PURE__ */ jsx46("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
3192
+ /* @__PURE__ */ jsx47("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
3144
3193
  ] }, i))
3145
3194
  }
3146
3195
  );
3147
3196
  }
3148
3197
 
3149
3198
  // src/components/data/Timeline.tsx
3150
- import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
3199
+ import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
3151
3200
  function Timeline({ entries, reverse = false, className, ...rest }) {
3152
3201
  const list = reverse ? [...entries].reverse() : entries;
3153
- return /* @__PURE__ */ jsx47("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs39("li", { className: "pire-timeline-item", children: [
3154
- /* @__PURE__ */ jsx47("span", { className: "pire-timeline-time", children: entry.time }),
3155
- /* @__PURE__ */ jsx47("span", { className: "pire-timeline-text", children: entry.event }),
3156
- entry.actor ? /* @__PURE__ */ jsx47("span", { className: "pire-timeline-actor", children: entry.actor }) : null
3202
+ return /* @__PURE__ */ jsx48("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs40("li", { className: "pire-timeline-item", children: [
3203
+ /* @__PURE__ */ jsx48("span", { className: "pire-timeline-time", children: entry.time }),
3204
+ /* @__PURE__ */ jsx48("span", { className: "pire-timeline-text", children: entry.event }),
3205
+ entry.actor ? /* @__PURE__ */ jsx48("span", { className: "pire-timeline-actor", children: entry.actor }) : null
3157
3206
  ] }, entry.id ?? i)) });
3158
3207
  }
3159
3208
 
@@ -3236,7 +3285,7 @@ function alignToCategories(series, categoryCount) {
3236
3285
  }
3237
3286
 
3238
3287
  // src/components/data/ChartFrame.tsx
3239
- import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
3288
+ import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
3240
3289
  function seriesLegend(series) {
3241
3290
  return series.map((one, index) => ({
3242
3291
  key: one.id,
@@ -3259,29 +3308,29 @@ function ChartFrame({
3259
3308
  children
3260
3309
  }) {
3261
3310
  const msg = usePireMessages();
3262
- return /* @__PURE__ */ jsxs40("figure", { className: cx("pire-chart", className), style, children: [
3263
- title || description ? /* @__PURE__ */ jsxs40("figcaption", { className: "pire-chart-head", children: [
3264
- title ? /* @__PURE__ */ jsx48("span", { className: "pire-chart-title", children: title }) : null,
3265
- description ? /* @__PURE__ */ jsx48("span", { className: "pire-chart-desc", children: description }) : null
3311
+ return /* @__PURE__ */ jsxs41("figure", { className: cx("pire-chart", className), style, children: [
3312
+ title || description ? /* @__PURE__ */ jsxs41("figcaption", { className: "pire-chart-head", children: [
3313
+ title ? /* @__PURE__ */ jsx49("span", { className: "pire-chart-title", children: title }) : null,
3314
+ description ? /* @__PURE__ */ jsx49("span", { className: "pire-chart-desc", children: description }) : null
3266
3315
  ] }) : null,
3267
- legend && legend.length > 1 ? /* @__PURE__ */ jsx48("ul", { className: "pire-chart-legend", children: legend.map((item) => /* @__PURE__ */ jsxs40("li", { className: "pire-chart-legend-item", children: [
3268
- /* @__PURE__ */ jsx48("span", { className: "pire-chart-swatch", style: { background: item.color } }),
3316
+ legend && legend.length > 1 ? /* @__PURE__ */ jsx49("ul", { className: "pire-chart-legend", children: legend.map((item) => /* @__PURE__ */ jsxs41("li", { className: "pire-chart-legend-item", children: [
3317
+ /* @__PURE__ */ jsx49("span", { className: "pire-chart-swatch", style: { background: item.color } }),
3269
3318
  item.label
3270
3319
  ] }, item.key)) }) : null,
3271
- /* @__PURE__ */ jsx48("div", { className: "pire-chart-plot", "aria-hidden": "true", children }),
3272
- /* @__PURE__ */ jsx48("div", { className: showDataTable ? "pire-chart-table" : "pire-sr-only", children: /* @__PURE__ */ jsxs40("table", { children: [
3273
- /* @__PURE__ */ jsx48("caption", { children: label }),
3274
- /* @__PURE__ */ jsx48("thead", { children: /* @__PURE__ */ jsxs40("tr", { children: [
3275
- /* @__PURE__ */ jsx48("th", { scope: "col", children: msg.chartCategoryHeader }),
3276
- series.map((one) => /* @__PURE__ */ jsx48("th", { scope: "col", children: one.label }, one.id))
3320
+ /* @__PURE__ */ jsx49("div", { className: "pire-chart-plot", "aria-hidden": "true", children }),
3321
+ /* @__PURE__ */ jsx49("div", { className: showDataTable ? "pire-chart-table" : "pire-sr-only", children: /* @__PURE__ */ jsxs41("table", { children: [
3322
+ /* @__PURE__ */ jsx49("caption", { children: label }),
3323
+ /* @__PURE__ */ jsx49("thead", { children: /* @__PURE__ */ jsxs41("tr", { children: [
3324
+ /* @__PURE__ */ jsx49("th", { scope: "col", children: msg.chartCategoryHeader }),
3325
+ series.map((one) => /* @__PURE__ */ jsx49("th", { scope: "col", children: one.label }, one.id))
3277
3326
  ] }) }),
3278
- /* @__PURE__ */ jsx48("tbody", { children: categories.map((category, categoryIndex) => (
3327
+ /* @__PURE__ */ jsx49("tbody", { children: categories.map((category, categoryIndex) => (
3279
3328
  // biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
3280
- /* @__PURE__ */ jsxs40("tr", { children: [
3281
- /* @__PURE__ */ jsx48("th", { scope: "row", children: category }),
3329
+ /* @__PURE__ */ jsxs41("tr", { children: [
3330
+ /* @__PURE__ */ jsx49("th", { scope: "row", children: category }),
3282
3331
  series.map((one) => {
3283
3332
  const value = one.values[categoryIndex];
3284
- return /* @__PURE__ */ jsx48("td", { children: value == null ? msg.chartNoValue : formatValue(value) }, one.id);
3333
+ return /* @__PURE__ */ jsx49("td", { children: value == null ? msg.chartNoValue : formatValue(value) }, one.id);
3285
3334
  })
3286
3335
  ] }, categoryIndex)
3287
3336
  )) })
@@ -3290,7 +3339,7 @@ function ChartFrame({
3290
3339
  }
3291
3340
 
3292
3341
  // src/components/data/BarChart.tsx
3293
- import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
3342
+ import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
3294
3343
  function BarChart({
3295
3344
  categories,
3296
3345
  series: rawSeries,
@@ -3322,7 +3371,7 @@ function BarChart({
3322
3371
  const value = series[0].values[categoryIndex];
3323
3372
  return value == null ? msg.chartNoValue : formatValue(value);
3324
3373
  };
3325
- return /* @__PURE__ */ jsx49(
3374
+ return /* @__PURE__ */ jsx50(
3326
3375
  ChartFrame,
3327
3376
  {
3328
3377
  label,
@@ -3335,7 +3384,7 @@ function BarChart({
3335
3384
  showDataTable,
3336
3385
  className,
3337
3386
  style,
3338
- children: !hasData ? /* @__PURE__ */ jsx49("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsx49(
3387
+ children: !hasData ? /* @__PURE__ */ jsx50("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsx50(
3339
3388
  "div",
3340
3389
  {
3341
3390
  className: "pire-chart-bars",
@@ -3344,12 +3393,12 @@ function BarChart({
3344
3393
  style: { "--pire-chart-height": `${height}px` },
3345
3394
  children: categories.map((category, categoryIndex) => (
3346
3395
  // biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
3347
- /* @__PURE__ */ jsxs41("div", { className: "pire-chart-group", children: [
3348
- /* @__PURE__ */ jsx49("span", { className: "pire-chart-cat", children: category }),
3349
- /* @__PURE__ */ jsx49("div", { className: "pire-chart-track", children: series.map((one, seriesIndex) => {
3396
+ /* @__PURE__ */ jsxs42("div", { className: "pire-chart-group", children: [
3397
+ /* @__PURE__ */ jsx50("span", { className: "pire-chart-cat", children: category }),
3398
+ /* @__PURE__ */ jsx50("div", { className: "pire-chart-track", children: series.map((one, seriesIndex) => {
3350
3399
  const value = one.values[categoryIndex];
3351
3400
  if (value == null) return null;
3352
- return /* @__PURE__ */ jsxs41(
3401
+ return /* @__PURE__ */ jsxs42(
3353
3402
  "div",
3354
3403
  {
3355
3404
  className: "pire-chart-bar",
@@ -3358,8 +3407,8 @@ function BarChart({
3358
3407
  "--pire-bar-color": seriesColor(one, seriesIndex)
3359
3408
  },
3360
3409
  children: [
3361
- withValues && orientation === "vertical" ? /* @__PURE__ */ jsx49("span", { className: "pire-chart-barval", children: formatValue(value) }) : null,
3362
- /* @__PURE__ */ jsxs41("span", { className: "pire-chart-tip", role: "presentation", children: [
3410
+ withValues && orientation === "vertical" ? /* @__PURE__ */ jsx50("span", { className: "pire-chart-barval", children: formatValue(value) }) : null,
3411
+ /* @__PURE__ */ jsxs42("span", { className: "pire-chart-tip", role: "presentation", children: [
3363
3412
  series.length > 1 ? `${one.label}: ` : "",
3364
3413
  formatValue(value)
3365
3414
  ] })
@@ -3368,7 +3417,7 @@ function BarChart({
3368
3417
  one.id
3369
3418
  );
3370
3419
  }) }),
3371
- withValues && orientation === "horizontal" ? /* @__PURE__ */ jsx49("span", { className: "pire-chart-val", children: horizontalLabelFor(categoryIndex) }) : null
3420
+ withValues && orientation === "horizontal" ? /* @__PURE__ */ jsx50("span", { className: "pire-chart-val", children: horizontalLabelFor(categoryIndex) }) : null
3372
3421
  ] }, categoryIndex)
3373
3422
  ))
3374
3423
  }
@@ -3378,14 +3427,14 @@ function BarChart({
3378
3427
  }
3379
3428
 
3380
3429
  // src/components/data/LineChart.tsx
3381
- import * as React23 from "react";
3382
- import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
3430
+ import * as React24 from "react";
3431
+ import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
3383
3432
  var PLOT_INSET = { top: 10, right: 14, bottom: 24, left: 58 };
3384
3433
  var MARKER_LIMIT = 20;
3385
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React23.useEffect : React23.useLayoutEffect;
3434
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React24.useEffect : React24.useLayoutEffect;
3386
3435
  function useMeasuredWidth() {
3387
- const ref = React23.useRef(null);
3388
- const [width, setWidth] = React23.useState(0);
3436
+ const ref = React24.useRef(null);
3437
+ const [width, setWidth] = React24.useState(0);
3389
3438
  useIsomorphicLayoutEffect2(() => {
3390
3439
  const element = ref.current;
3391
3440
  if (!element) return;
@@ -3446,7 +3495,7 @@ function LineChart({
3446
3495
  return `M${xAt(present[0].index)} ${baseline} L${line} L${xAt(last.index)} ${baseline} Z`;
3447
3496
  };
3448
3497
  const labelEvery = Math.max(1, Math.ceil(categories.length / Math.max(2, Math.floor(innerWidth / 64))));
3449
- return /* @__PURE__ */ jsx50(
3498
+ return /* @__PURE__ */ jsx51(
3450
3499
  ChartFrame,
3451
3500
  {
3452
3501
  label,
@@ -3459,8 +3508,8 @@ function LineChart({
3459
3508
  showDataTable,
3460
3509
  className,
3461
3510
  style,
3462
- children: !hasData ? /* @__PURE__ */ jsx50("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsxs42("div", { className: "pire-chart-lines", ref: plotRef, style: { height }, children: [
3463
- width > 0 ? /* @__PURE__ */ jsxs42(
3511
+ children: !hasData ? /* @__PURE__ */ jsx51("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsxs43("div", { className: "pire-chart-lines", ref: plotRef, style: { height }, children: [
3512
+ width > 0 ? /* @__PURE__ */ jsxs43(
3464
3513
  "svg",
3465
3514
  {
3466
3515
  width,
@@ -3469,7 +3518,7 @@ function LineChart({
3469
3518
  "aria-hidden": "true",
3470
3519
  focusable: "false",
3471
3520
  children: [
3472
- /* @__PURE__ */ jsx50("g", { className: "pire-chart-grid", children: scale.ticks.map((tick) => /* @__PURE__ */ jsx50(
3521
+ /* @__PURE__ */ jsx51("g", { className: "pire-chart-grid", children: scale.ticks.map((tick) => /* @__PURE__ */ jsx51(
3473
3522
  "line",
3474
3523
  {
3475
3524
  x1: PLOT_INSET.left,
@@ -3479,8 +3528,8 @@ function LineChart({
3479
3528
  },
3480
3529
  tick
3481
3530
  )) }),
3482
- /* @__PURE__ */ jsxs42("g", { className: "pire-chart-tick", children: [
3483
- scale.ticks.map((tick) => /* @__PURE__ */ jsx50(
3531
+ /* @__PURE__ */ jsxs43("g", { className: "pire-chart-tick", children: [
3532
+ scale.ticks.map((tick) => /* @__PURE__ */ jsx51(
3484
3533
  "text",
3485
3534
  {
3486
3535
  x: PLOT_INSET.left - 8,
@@ -3493,10 +3542,10 @@ function LineChart({
3493
3542
  )),
3494
3543
  categories.map((category, index) => index % labelEvery === 0 ? (
3495
3544
  // biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
3496
- /* @__PURE__ */ jsx50("text", { x: xAt(index), y: height - 6, textAnchor: "middle", children: category }, index)
3545
+ /* @__PURE__ */ jsx51("text", { x: xAt(index), y: height - 6, textAnchor: "middle", children: category }, index)
3497
3546
  ) : null)
3498
3547
  ] }),
3499
- showArea && series[0] ? /* @__PURE__ */ jsx50(
3548
+ showArea && series[0] ? /* @__PURE__ */ jsx51(
3500
3549
  "path",
3501
3550
  {
3502
3551
  d: areaFor(series[0].values),
@@ -3504,10 +3553,10 @@ function LineChart({
3504
3553
  style: { fill: seriesColor(series[0], 0) }
3505
3554
  }
3506
3555
  ) : null,
3507
- /* @__PURE__ */ jsx50("g", { className: "pire-chart-line", fill: "none", children: series.map((one, index) => /* @__PURE__ */ jsx50("path", { d: pathFor(one.values), stroke: seriesColor(one, index) }, one.id)) }),
3508
- withMarkers ? /* @__PURE__ */ jsx50("g", { className: "pire-chart-marker", children: series.map((one, seriesIndex) => one.values.map((value, index) => value == null ? null : (
3556
+ /* @__PURE__ */ jsx51("g", { className: "pire-chart-line", fill: "none", children: series.map((one, index) => /* @__PURE__ */ jsx51("path", { d: pathFor(one.values), stroke: seriesColor(one, index) }, one.id)) }),
3557
+ withMarkers ? /* @__PURE__ */ jsx51("g", { className: "pire-chart-marker", children: series.map((one, seriesIndex) => one.values.map((value, index) => value == null ? null : (
3509
3558
  // biome-ignore lint/suspicious/noArrayIndexKey: a series is positional — the index is the point's identity, and category labels repeat.
3510
- /* @__PURE__ */ jsx50(
3559
+ /* @__PURE__ */ jsx51(
3511
3560
  "circle",
3512
3561
  {
3513
3562
  cx: xAt(index),
@@ -3521,18 +3570,18 @@ function LineChart({
3521
3570
  ]
3522
3571
  }
3523
3572
  ) : null,
3524
- /* @__PURE__ */ jsx50(
3573
+ /* @__PURE__ */ jsx51(
3525
3574
  "div",
3526
3575
  {
3527
3576
  className: "pire-chart-hover",
3528
3577
  style: { inset: `${PLOT_INSET.top}px ${PLOT_INSET.right}px ${PLOT_INSET.bottom}px ${PLOT_INSET.left}px` },
3529
3578
  children: categories.map((category, categoryIndex) => (
3530
3579
  // biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
3531
- /* @__PURE__ */ jsx50("div", { className: "pire-chart-band", children: /* @__PURE__ */ jsxs42("span", { className: "pire-chart-tip", role: "presentation", children: [
3532
- /* @__PURE__ */ jsx50("strong", { children: category }),
3580
+ /* @__PURE__ */ jsx51("div", { className: "pire-chart-band", children: /* @__PURE__ */ jsxs43("span", { className: "pire-chart-tip", role: "presentation", children: [
3581
+ /* @__PURE__ */ jsx51("strong", { children: category }),
3533
3582
  series.map((one) => {
3534
3583
  const value = one.values[categoryIndex];
3535
- return /* @__PURE__ */ jsxs42("span", { className: "pire-chart-tip-row", children: [
3584
+ return /* @__PURE__ */ jsxs43("span", { className: "pire-chart-tip-row", children: [
3536
3585
  one.label,
3537
3586
  ": ",
3538
3587
  value == null ? "No data" : formatValue(value)
@@ -3548,8 +3597,8 @@ function LineChart({
3548
3597
  }
3549
3598
 
3550
3599
  // src/components/data/DonutChart.tsx
3551
- import * as React24 from "react";
3552
- import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
3600
+ import * as React25 from "react";
3601
+ import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
3553
3602
  var SEGMENT_GAP_DEGREES = 1.5;
3554
3603
  function DonutChart({
3555
3604
  categories,
@@ -3569,7 +3618,7 @@ function DonutChart({
3569
3618
  }) {
3570
3619
  const label = rest["aria-label"];
3571
3620
  const msg = usePireMessages();
3572
- const [hoveredIndex, setHoveredIndex] = React24.useState(null);
3621
+ const [hoveredIndex, setHoveredIndex] = React25.useState(null);
3573
3622
  warnOnDonutShape(series, categories.length, label);
3574
3623
  const values = (series[0]?.values ?? []).slice(0, categories.length);
3575
3624
  const segments = categories.map((category, index) => ({ category, index, value: values[index] ?? 0 })).filter((segment) => segment.value > 0);
@@ -3586,7 +3635,7 @@ function DonutChart({
3586
3635
  }));
3587
3636
  const hovered = hoveredIndex == null ? null : segments.find((segment) => segment.index === hoveredIndex) ?? null;
3588
3637
  let arcStart = 0;
3589
- return /* @__PURE__ */ jsx51(
3638
+ return /* @__PURE__ */ jsx52(
3590
3639
  ChartFrame,
3591
3640
  {
3592
3641
  label,
@@ -3599,8 +3648,8 @@ function DonutChart({
3599
3648
  showDataTable,
3600
3649
  className,
3601
3650
  style,
3602
- children: !hasData ? /* @__PURE__ */ jsx51("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsxs43("div", { className: "pire-chart-donut", style: { height: size }, children: [
3603
- /* @__PURE__ */ jsx51(
3651
+ children: !hasData ? /* @__PURE__ */ jsx52("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsxs44("div", { className: "pire-chart-donut", style: { height: size }, children: [
3652
+ /* @__PURE__ */ jsx52(
3604
3653
  "svg",
3605
3654
  {
3606
3655
  width: size,
@@ -3608,13 +3657,13 @@ function DonutChart({
3608
3657
  "aria-hidden": "true",
3609
3658
  focusable: "false",
3610
3659
  onMouseLeave: () => setHoveredIndex(null),
3611
- children: /* @__PURE__ */ jsx51("g", { transform: `rotate(-90 ${size / 2} ${size / 2})`, children: segments.map((segment) => {
3660
+ children: /* @__PURE__ */ jsx52("g", { transform: `rotate(-90 ${size / 2} ${size / 2})`, children: segments.map((segment) => {
3612
3661
  const arcLength = segment.value / total * circumference;
3613
3662
  const offset = arcStart;
3614
3663
  arcStart += arcLength;
3615
3664
  return (
3616
3665
  // 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.
3617
- /* @__PURE__ */ jsx51(
3666
+ /* @__PURE__ */ jsx52(
3618
3667
  "circle",
3619
3668
  {
3620
3669
  className: "pire-chart-arc",
@@ -3634,9 +3683,9 @@ function DonutChart({
3634
3683
  }) })
3635
3684
  }
3636
3685
  ),
3637
- /* @__PURE__ */ jsxs43("div", { className: "pire-chart-donut-center", style: { width: size - thickness * 2 - 8 }, children: [
3638
- /* @__PURE__ */ jsx51("span", { className: "pire-chart-donut-value", children: hovered ? formatValue(hovered.value) : centerLabel ?? formatValue(total) }),
3639
- /* @__PURE__ */ jsx51("span", { className: "pire-chart-donut-caption", children: hovered ? hovered.category : centerCaption })
3686
+ /* @__PURE__ */ jsxs44("div", { className: "pire-chart-donut-center", style: { width: size - thickness * 2 - 8 }, children: [
3687
+ /* @__PURE__ */ jsx52("span", { className: "pire-chart-donut-value", children: hovered ? formatValue(hovered.value) : centerLabel ?? formatValue(total) }),
3688
+ /* @__PURE__ */ jsx52("span", { className: "pire-chart-donut-caption", children: hovered ? hovered.category : centerCaption })
3640
3689
  ] })
3641
3690
  ] })
3642
3691
  }
@@ -3647,15 +3696,15 @@ function colorForSegment(index) {
3647
3696
  }
3648
3697
 
3649
3698
  // src/components/data/LinkList.tsx
3650
- import { Button as AriaButton14 } from "react-aria-components";
3651
- import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
3699
+ import { Button as AriaButton15 } from "react-aria-components";
3700
+ import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
3652
3701
  function LinkList({ items, onSelect, emphasis = "key", className, ...rest }) {
3653
- return /* @__PURE__ */ jsx52("div", { className: cx("pire-linklist", className), role: "list", "data-emphasis": emphasis, ...rest, children: items.map((item) => {
3654
- const keySlot = item.key ? /* @__PURE__ */ jsx52("span", { className: "pire-linklist-key", children: item.key }) : null;
3655
- const textSlot = item.text ? /* @__PURE__ */ jsx52("span", { className: "pire-linklist-text", children: item.text }) : null;
3702
+ return /* @__PURE__ */ jsx53("div", { className: cx("pire-linklist", className), role: "list", "data-emphasis": emphasis, ...rest, children: items.map((item) => {
3703
+ const keySlot = item.key ? /* @__PURE__ */ jsx53("span", { className: "pire-linklist-key", children: item.key }) : null;
3704
+ const textSlot = item.text ? /* @__PURE__ */ jsx53("span", { className: "pire-linklist-text", children: item.text }) : null;
3656
3705
  const [first, second] = emphasis === "text" ? [textSlot, keySlot] : [keySlot, textSlot];
3657
- return /* @__PURE__ */ jsx52("div", { role: "listitem", className: "pire-linklist-row", children: /* @__PURE__ */ jsxs44(AriaButton14, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
3658
- item.icon ? /* @__PURE__ */ jsx52(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
3706
+ return /* @__PURE__ */ jsx53("div", { role: "listitem", className: "pire-linklist-row", children: /* @__PURE__ */ jsxs45(AriaButton15, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
3707
+ item.icon ? /* @__PURE__ */ jsx53(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
3659
3708
  first,
3660
3709
  second,
3661
3710
  item.trailing
@@ -3664,7 +3713,7 @@ function LinkList({ items, onSelect, emphasis = "key", className, ...rest }) {
3664
3713
  }
3665
3714
 
3666
3715
  // src/components/layout/PageBand.tsx
3667
- import { jsx as jsx53 } from "react/jsx-runtime";
3716
+ import { jsx as jsx54 } from "react/jsx-runtime";
3668
3717
  function PageBand({
3669
3718
  surface = "card",
3670
3719
  hasBorder = true,
@@ -3672,7 +3721,7 @@ function PageBand({
3672
3721
  className,
3673
3722
  ...rest
3674
3723
  }) {
3675
- return /* @__PURE__ */ jsx53(
3724
+ return /* @__PURE__ */ jsx54(
3676
3725
  "div",
3677
3726
  {
3678
3727
  className: cx("pire-pageband", className),
@@ -3685,56 +3734,56 @@ function PageBand({
3685
3734
  }
3686
3735
 
3687
3736
  // src/components/layout/PageHeader.tsx
3688
- import { jsx as jsx54, jsxs as jsxs45 } from "react/jsx-runtime";
3737
+ import { jsx as jsx55, jsxs as jsxs46 } from "react/jsx-runtime";
3689
3738
  function PageHeader({ title, subtitle, actions, className, ...rest }) {
3690
- return /* @__PURE__ */ jsxs45("header", { className: cx("pire-pageheader", className), ...rest, children: [
3691
- /* @__PURE__ */ jsxs45("div", { style: { minWidth: 0 }, children: [
3692
- /* @__PURE__ */ jsx54("h1", { className: "pire-pageheader-title", children: title }),
3693
- subtitle ? /* @__PURE__ */ jsx54("p", { className: "pire-pageheader-sub", children: subtitle }) : null
3739
+ return /* @__PURE__ */ jsxs46("header", { className: cx("pire-pageheader", className), ...rest, children: [
3740
+ /* @__PURE__ */ jsxs46("div", { style: { minWidth: 0 }, children: [
3741
+ /* @__PURE__ */ jsx55("h1", { className: "pire-pageheader-title", children: title }),
3742
+ subtitle ? /* @__PURE__ */ jsx55("p", { className: "pire-pageheader-sub", children: subtitle }) : null
3694
3743
  ] }),
3695
- actions ? /* @__PURE__ */ jsx54("div", { className: "pire-pageheader-actions", children: actions }) : null
3744
+ actions ? /* @__PURE__ */ jsx55("div", { className: "pire-pageheader-actions", children: actions }) : null
3696
3745
  ] });
3697
3746
  }
3698
3747
 
3699
3748
  // src/components/layout/SectionHeader.tsx
3700
- import { jsx as jsx55, jsxs as jsxs46 } from "react/jsx-runtime";
3749
+ import { jsx as jsx56, jsxs as jsxs47 } from "react/jsx-runtime";
3701
3750
  function SectionHeader({ title, meta, actions, className, ...rest }) {
3702
- return /* @__PURE__ */ jsxs46("div", { className: cx("pire-sectionhead", className), ...rest, children: [
3703
- /* @__PURE__ */ jsx55("span", { className: "pire-eyebrow", children: title }),
3704
- meta ? /* @__PURE__ */ jsx55("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
3705
- actions ? /* @__PURE__ */ jsx55("div", { className: "pire-sectionhead-actions", children: actions }) : null
3751
+ return /* @__PURE__ */ jsxs47("div", { className: cx("pire-sectionhead", className), ...rest, children: [
3752
+ /* @__PURE__ */ jsx56("span", { className: "pire-eyebrow", children: title }),
3753
+ meta ? /* @__PURE__ */ jsx56("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
3754
+ actions ? /* @__PURE__ */ jsx56("div", { className: "pire-sectionhead-actions", children: actions }) : null
3706
3755
  ] });
3707
3756
  }
3708
3757
 
3709
3758
  // src/components/layout/SelectionBar.tsx
3710
- import { jsx as jsx56, jsxs as jsxs47 } from "react/jsx-runtime";
3759
+ import { jsx as jsx57, jsxs as jsxs48 } from "react/jsx-runtime";
3711
3760
  function SelectionBar({ count, noun = "record", children, actions, className, ...rest }) {
3712
3761
  if (!count) return null;
3713
- return /* @__PURE__ */ jsxs47("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
3714
- /* @__PURE__ */ jsxs47("span", { className: "pire-selectionbar-count", children: [
3762
+ return /* @__PURE__ */ jsxs48("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
3763
+ /* @__PURE__ */ jsxs48("span", { className: "pire-selectionbar-count", children: [
3715
3764
  count.toLocaleString(),
3716
3765
  " ",
3717
3766
  noun,
3718
3767
  count === 1 ? "" : "s",
3719
3768
  " selected"
3720
3769
  ] }),
3721
- children ? /* @__PURE__ */ jsx56("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
3722
- actions ? /* @__PURE__ */ jsx56("div", { className: "pire-selectionbar-actions", children: actions }) : null
3770
+ children ? /* @__PURE__ */ jsx57("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
3771
+ actions ? /* @__PURE__ */ jsx57("div", { className: "pire-selectionbar-actions", children: actions }) : null
3723
3772
  ] });
3724
3773
  }
3725
3774
 
3726
3775
  // src/components/layout/FooterBar.tsx
3727
- import { jsx as jsx57, jsxs as jsxs48 } from "react/jsx-runtime";
3776
+ import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
3728
3777
  function FooterBar({ note, actions, children, className, ...rest }) {
3729
- return /* @__PURE__ */ jsxs48("footer", { className: cx("pire-footerbar", className), ...rest, children: [
3730
- note ? /* @__PURE__ */ jsx57("span", { className: "pire-footerbar-note", children: note }) : null,
3778
+ return /* @__PURE__ */ jsxs49("footer", { className: cx("pire-footerbar", className), ...rest, children: [
3779
+ note ? /* @__PURE__ */ jsx58("span", { className: "pire-footerbar-note", children: note }) : null,
3731
3780
  children,
3732
- actions ? /* @__PURE__ */ jsx57("div", { className: "pire-footerbar-actions", children: actions }) : null
3781
+ actions ? /* @__PURE__ */ jsx58("div", { className: "pire-footerbar-actions", children: actions }) : null
3733
3782
  ] });
3734
3783
  }
3735
3784
 
3736
3785
  // src/components/layout/SplitPane.tsx
3737
- import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
3786
+ import { jsx as jsx59, jsxs as jsxs50 } from "react/jsx-runtime";
3738
3787
  function SplitPane({
3739
3788
  list,
3740
3789
  detail,
@@ -3750,7 +3799,7 @@ function SplitPane({
3750
3799
  }) {
3751
3800
  const msg = usePireMessages();
3752
3801
  const width = typeof listWidth === "number" ? `${listWidth}px` : listWidth;
3753
- return /* @__PURE__ */ jsxs49(
3802
+ return /* @__PURE__ */ jsxs50(
3754
3803
  "div",
3755
3804
  {
3756
3805
  className: cx("pire-split", className),
@@ -3758,10 +3807,10 @@ function SplitPane({
3758
3807
  style: { ["--pire-split-list-w"]: width, ...style },
3759
3808
  ...rest,
3760
3809
  children: [
3761
- /* @__PURE__ */ jsx58("section", { className: "pire-split-list", "aria-label": listLabel ?? msg.splitPaneList, children: list }),
3762
- /* @__PURE__ */ jsxs49("section", { className: "pire-split-detail", "aria-label": detailLabel ?? msg.splitPaneDetail, children: [
3763
- onBack ? /* @__PURE__ */ jsx58("div", { className: "pire-split-back", children: /* @__PURE__ */ jsx58(Button, { variant: "tertiary", size: "sm", icon: "arrow-left", onPress: onBack, children: backLabel ?? msg.splitPaneBack }) }) : null,
3764
- detail ?? /* @__PURE__ */ jsx58("div", { className: "pire-split-empty", children: emptyDetail })
3810
+ /* @__PURE__ */ jsx59("section", { className: "pire-split-list", "aria-label": listLabel ?? msg.splitPaneList, children: list }),
3811
+ /* @__PURE__ */ jsxs50("section", { className: "pire-split-detail", "aria-label": detailLabel ?? msg.splitPaneDetail, children: [
3812
+ onBack ? /* @__PURE__ */ jsx59("div", { className: "pire-split-back", children: /* @__PURE__ */ jsx59(Button, { variant: "tertiary", size: "sm", icon: "arrow-left", onPress: onBack, children: backLabel ?? msg.splitPaneBack }) }) : null,
3813
+ detail ?? /* @__PURE__ */ jsx59("div", { className: "pire-split-empty", children: emptyDetail })
3765
3814
  ] })
3766
3815
  ]
3767
3816
  }
@@ -3769,7 +3818,7 @@ function SplitPane({
3769
3818
  }
3770
3819
 
3771
3820
  // src/components/patterns/ConfirmDialog.tsx
3772
- import { Fragment as Fragment4, jsx as jsx59, jsxs as jsxs50 } from "react/jsx-runtime";
3821
+ import { Fragment as Fragment5, jsx as jsx60, jsxs as jsxs51 } from "react/jsx-runtime";
3773
3822
  function ConfirmDialog({
3774
3823
  isOpen,
3775
3824
  title,
@@ -3783,7 +3832,7 @@ function ConfirmDialog({
3783
3832
  onConfirm,
3784
3833
  onCancel
3785
3834
  }) {
3786
- return /* @__PURE__ */ jsxs50(
3835
+ return /* @__PURE__ */ jsxs51(
3787
3836
  Dialog,
3788
3837
  {
3789
3838
  isOpen,
@@ -3793,12 +3842,12 @@ function ConfirmDialog({
3793
3842
  onClose: onCancel,
3794
3843
  isDismissable: !isBusy,
3795
3844
  showClose: false,
3796
- footer: /* @__PURE__ */ jsxs50(Fragment4, { children: [
3797
- /* @__PURE__ */ jsx59(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3798
- /* @__PURE__ */ jsx59(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3845
+ footer: /* @__PURE__ */ jsxs51(Fragment5, { children: [
3846
+ /* @__PURE__ */ jsx60(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3847
+ /* @__PURE__ */ jsx60(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3799
3848
  ] }),
3800
3849
  children: [
3801
- consequence ? /* @__PURE__ */ jsx59(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3850
+ consequence ? /* @__PURE__ */ jsx60(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3802
3851
  children
3803
3852
  ]
3804
3853
  }
@@ -3806,7 +3855,7 @@ function ConfirmDialog({
3806
3855
  }
3807
3856
 
3808
3857
  // src/components/patterns/CommandPalette.tsx
3809
- import * as React25 from "react";
3858
+ import * as React26 from "react";
3810
3859
  import {
3811
3860
  Autocomplete,
3812
3861
  ModalOverlay as ModalOverlay2,
@@ -3819,7 +3868,7 @@ import {
3819
3868
  Header as Header2,
3820
3869
  useFilter
3821
3870
  } from "react-aria-components";
3822
- import { Fragment as Fragment5, jsx as jsx60, jsxs as jsxs51 } from "react/jsx-runtime";
3871
+ import { Fragment as Fragment6, jsx as jsx61, jsxs as jsxs52 } from "react/jsx-runtime";
3823
3872
  var RESULTS_SECTION_KEY = "__pire_results__";
3824
3873
  var searchableText = (item) => [item.label, item.description, item.keywords].filter(Boolean).join(" ");
3825
3874
  function CommandPalette({
@@ -3840,17 +3889,17 @@ function CommandPalette({
3840
3889
  style
3841
3890
  }) {
3842
3891
  const msg = usePireMessages();
3843
- const [query, setQuery] = React25.useState("");
3892
+ const [query, setQuery] = React26.useState("");
3844
3893
  const { contains } = useFilter({ sensitivity: "base" });
3845
- React25.useEffect(() => {
3894
+ React26.useEffect(() => {
3846
3895
  if (isOpen) setQuery("");
3847
3896
  }, [isOpen]);
3848
- const searchableById = React25.useMemo(() => {
3897
+ const searchableById = React26.useMemo(() => {
3849
3898
  const byId = /* @__PURE__ */ new Map();
3850
3899
  for (const group of groups) for (const item of group.items) byId.set(item.id, searchableText(item));
3851
3900
  return byId;
3852
3901
  }, [groups]);
3853
- const filter = React25.useCallback((textValue, inputValue, node) => {
3902
+ const filter = React26.useCallback((textValue, inputValue, node) => {
3854
3903
  if (node.parentKey === RESULTS_SECTION_KEY) return true;
3855
3904
  return contains(searchableById.get(String(node.key)) ?? textValue, inputValue);
3856
3905
  }, [contains, searchableById]);
@@ -3860,7 +3909,7 @@ function CommandPalette({
3860
3909
  };
3861
3910
  const sections = [...groups, ...resultsGroup ? [{ ...resultsGroup, id: RESULTS_SECTION_KEY }] : []];
3862
3911
  const status = isLoading ? loadingLabel ?? msg.commandPaletteLoading : emptyLabel ?? msg.commandPaletteEmpty;
3863
- return /* @__PURE__ */ jsx60(
3912
+ return /* @__PURE__ */ jsx61(
3864
3913
  ModalOverlay2,
3865
3914
  {
3866
3915
  className: "pire-cp-overlay",
@@ -3869,11 +3918,11 @@ function CommandPalette({
3869
3918
  onOpenChange: (open) => {
3870
3919
  if (!open) onOpenChange?.(false);
3871
3920
  },
3872
- children: /* @__PURE__ */ jsx60(Modal2, { className: cx("pire-cp-modal", className), style, children: /* @__PURE__ */ jsxs51(AriaDialog4, { className: "pire-cp-dialog", "aria-label": ariaLabel ?? msg.commandPaletteLabel, children: [
3873
- /* @__PURE__ */ jsxs51(Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3874
- /* @__PURE__ */ jsxs51(SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3875
- /* @__PURE__ */ jsx60(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3876
- /* @__PURE__ */ jsx60(
3921
+ children: /* @__PURE__ */ jsx61(Modal2, { className: cx("pire-cp-modal", className), style, children: /* @__PURE__ */ jsxs52(AriaDialog4, { className: "pire-cp-dialog", "aria-label": ariaLabel ?? msg.commandPaletteLabel, children: [
3922
+ /* @__PURE__ */ jsxs52(Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3923
+ /* @__PURE__ */ jsxs52(SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3924
+ /* @__PURE__ */ jsx61(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3925
+ /* @__PURE__ */ jsx61(
3877
3926
  AriaInput5,
3878
3927
  {
3879
3928
  className: "pire-cp-input",
@@ -3882,16 +3931,16 @@ function CommandPalette({
3882
3931
  }
3883
3932
  )
3884
3933
  ] }),
3885
- isLoading ? /* @__PURE__ */ jsx60("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3886
- /* @__PURE__ */ jsx60(
3934
+ isLoading ? /* @__PURE__ */ jsx61("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3935
+ /* @__PURE__ */ jsx61(
3887
3936
  AriaMenu2,
3888
3937
  {
3889
3938
  className: "pire-cp-list",
3890
3939
  onAction: (key) => onAction?.(String(key)),
3891
- renderEmptyState: () => /* @__PURE__ */ jsx60("div", { className: "pire-cp-status", children: status }),
3892
- children: sections.map((section) => /* @__PURE__ */ jsxs51(AriaMenuSection2, { id: section.id, className: "pire-cp-section", children: [
3893
- section.label ? /* @__PURE__ */ jsx60(Header2, { className: "pire-cp-section-title", children: section.label }) : null,
3894
- section.items.map((item) => /* @__PURE__ */ jsx60(
3940
+ renderEmptyState: () => /* @__PURE__ */ jsx61("div", { className: "pire-cp-status", children: status }),
3941
+ children: sections.map((section) => /* @__PURE__ */ jsxs52(AriaMenuSection2, { id: section.id, className: "pire-cp-section", children: [
3942
+ section.label ? /* @__PURE__ */ jsx61(Header2, { className: "pire-cp-section-title", children: section.label }) : null,
3943
+ section.items.map((item) => /* @__PURE__ */ jsx61(
3895
3944
  MenuItem,
3896
3945
  {
3897
3946
  id: item.id,
@@ -3912,18 +3961,18 @@ function CommandPalette({
3912
3961
  // aria-hidden: the glyphs are a sighted affordance for discovering the keys. A screen
3913
3962
  // reader already announces the listbox semantics that make those keys work, so reading
3914
3963
  // "up arrow down arrow navigate" out loud is noise on every open.
3915
- /* @__PURE__ */ jsx60("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ jsxs51(Fragment5, { children: [
3916
- /* @__PURE__ */ jsxs51("span", { className: "pire-cp-hint", children: [
3917
- /* @__PURE__ */ jsx60(Kbd, { children: "\u2191" }),
3918
- /* @__PURE__ */ jsx60(Kbd, { children: "\u2193" }),
3964
+ /* @__PURE__ */ jsx61("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ jsxs52(Fragment6, { children: [
3965
+ /* @__PURE__ */ jsxs52("span", { className: "pire-cp-hint", children: [
3966
+ /* @__PURE__ */ jsx61(Kbd, { children: "\u2191" }),
3967
+ /* @__PURE__ */ jsx61(Kbd, { children: "\u2193" }),
3919
3968
  msg.commandPaletteHintNavigate
3920
3969
  ] }),
3921
- /* @__PURE__ */ jsxs51("span", { className: "pire-cp-hint", children: [
3922
- /* @__PURE__ */ jsx60(Kbd, { children: "\u21B5" }),
3970
+ /* @__PURE__ */ jsxs52("span", { className: "pire-cp-hint", children: [
3971
+ /* @__PURE__ */ jsx61(Kbd, { children: "\u21B5" }),
3923
3972
  msg.commandPaletteHintSelect
3924
3973
  ] }),
3925
- /* @__PURE__ */ jsxs51("span", { className: "pire-cp-hint", children: [
3926
- /* @__PURE__ */ jsx60(Kbd, { children: "esc" }),
3974
+ /* @__PURE__ */ jsxs52("span", { className: "pire-cp-hint", children: [
3975
+ /* @__PURE__ */ jsx61(Kbd, { children: "esc" }),
3927
3976
  msg.commandPaletteHintClose
3928
3977
  ] })
3929
3978
  ] }) })
@@ -3933,9 +3982,9 @@ function CommandPalette({
3933
3982
  );
3934
3983
  }
3935
3984
  function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3936
- const handler = React25.useRef(onTrigger);
3985
+ const handler = React26.useRef(onTrigger);
3937
3986
  handler.current = onTrigger;
3938
- React25.useEffect(() => {
3987
+ React26.useEffect(() => {
3939
3988
  if (isDisabled) return;
3940
3989
  const onKeyDown = (event) => {
3941
3990
  if (!(event.metaKey || event.ctrlKey) || event.altKey) return;
@@ -3948,12 +3997,125 @@ function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3948
3997
  }, [key, isDisabled]);
3949
3998
  }
3950
3999
 
4000
+ // src/components/patterns/AppLauncher.tsx
4001
+ import * as React27 from "react";
4002
+ import {
4003
+ DialogTrigger,
4004
+ Button as AriaButton16,
4005
+ Popover as Popover8,
4006
+ Dialog as AriaDialog5,
4007
+ useFilter as useFilter2
4008
+ } from "react-aria-components";
4009
+ import { Fragment as Fragment7, jsx as jsx62, jsxs as jsxs53 } from "react/jsx-runtime";
4010
+ var searchableText2 = (item) => [item.label, item.description, item.keywords].filter(Boolean).join(" ");
4011
+ function AppLauncher({
4012
+ sections,
4013
+ onAction,
4014
+ value,
4015
+ title,
4016
+ meta,
4017
+ isSearchable = true,
4018
+ onSearchChange,
4019
+ isFilteredExternally,
4020
+ isLoading,
4021
+ emptyLabel,
4022
+ searchPlaceholder,
4023
+ "aria-label": ariaLabel,
4024
+ icon = "grid-2x2",
4025
+ className
4026
+ }) {
4027
+ const msg = usePireMessages();
4028
+ const [query, setQuery] = React27.useState("");
4029
+ const { contains } = useFilter2({ sensitivity: "base" });
4030
+ const handleSearch = (next) => {
4031
+ setQuery(next);
4032
+ onSearchChange?.(next);
4033
+ };
4034
+ const visible = React27.useMemo(() => {
4035
+ if (isFilteredExternally) return sections;
4036
+ const q = query.trim();
4037
+ if (!q) return sections;
4038
+ return sections.map((section) => ({ ...section, items: section.items.filter((i) => contains(searchableText2(i), q)) })).filter((section) => section.items.length > 0);
4039
+ }, [sections, query, isFilteredExternally, contains]);
4040
+ const isEmpty = !isLoading && visible.length === 0;
4041
+ const label = ariaLabel ?? msg.appLauncherLabel;
4042
+ return /* @__PURE__ */ jsxs53(DialogTrigger, { children: [
4043
+ /* @__PURE__ */ jsx62(AriaButton16, { className: "pire-launcher-trigger", "aria-label": label, children: /* @__PURE__ */ jsx62(Icon, { name: icon, size: 20 }) }),
4044
+ /* @__PURE__ */ jsx62(
4045
+ Popover8,
4046
+ {
4047
+ className: cx("pire-launcher-popover", className),
4048
+ placement: "bottom start",
4049
+ offset: 0,
4050
+ crossOffset: 0,
4051
+ containerPadding: 0,
4052
+ children: /* @__PURE__ */ jsx62(AriaDialog5, { className: "pire-launcher", "aria-label": label, children: ({ close }) => /* @__PURE__ */ jsxs53(Fragment7, { children: [
4053
+ /* @__PURE__ */ jsxs53("div", { className: "pire-launcher-head", children: [
4054
+ /* @__PURE__ */ jsx62("span", { className: "pire-launcher-title", children: title ?? msg.appLauncherTitle }),
4055
+ meta ? /* @__PURE__ */ jsx62("span", { className: "pire-launcher-meta", children: meta }) : null
4056
+ ] }),
4057
+ isSearchable ? (
4058
+ // autoFocus is right here specifically: the panel exists to be searched, and the
4059
+ // user just chose to open it, so taking the caret is what they asked for.
4060
+ /* @__PURE__ */ jsx62(
4061
+ Input,
4062
+ {
4063
+ "aria-label": msg.appLauncherSearch,
4064
+ icon: "search",
4065
+ type: "search",
4066
+ autoFocus: true,
4067
+ isClearable: true,
4068
+ value: query,
4069
+ onChange: handleSearch,
4070
+ placeholder: searchPlaceholder ?? msg.appLauncherSearch
4071
+ }
4072
+ )
4073
+ ) : null,
4074
+ isLoading ? /* @__PURE__ */ jsx62("div", { className: "pire-launcher-empty", role: "status", "aria-live": "polite", children: msg.appLauncherLoading }) : null,
4075
+ isEmpty ? /* @__PURE__ */ jsx62("div", { className: "pire-launcher-empty", children: emptyLabel ?? msg.appLauncherEmpty }) : null,
4076
+ visible.map((section, si) => (
4077
+ // Sections are positional zones with no record identity, so the heading is the key
4078
+ // where there is one. Same reasoning as ShellRail's groups.
4079
+ /* @__PURE__ */ jsxs53("div", { className: "pire-launcher-section", children: [
4080
+ section.label ? /* @__PURE__ */ jsx62("div", { className: "pire-eyebrow", children: section.label }) : null,
4081
+ /* @__PURE__ */ jsx62("div", { className: "pire-launcher-grid", "data-variant": section.variant ?? "tile", children: section.items.map((item) => {
4082
+ const isCurrent = item.id === value;
4083
+ const showsDescription = (section.variant ?? "tile") === "tile" && Boolean(item.description);
4084
+ return /* @__PURE__ */ jsxs53(
4085
+ AriaButton16,
4086
+ {
4087
+ className: "pire-launcher-item",
4088
+ "data-selected": isCurrent ? "true" : void 0,
4089
+ "aria-current": isCurrent ? "true" : void 0,
4090
+ onPress: () => {
4091
+ close();
4092
+ onAction?.(item.id);
4093
+ },
4094
+ children: [
4095
+ item.icon ? /* @__PURE__ */ jsx62("span", { className: "pire-launcher-item-icon", children: /* @__PURE__ */ jsx62(Icon, { name: item.icon, size: (section.variant ?? "tile") === "tile" ? 20 : 16 }) }) : null,
4096
+ /* @__PURE__ */ jsxs53("span", { className: "pire-launcher-item-text", children: [
4097
+ /* @__PURE__ */ jsx62("span", { className: "pire-launcher-item-label", children: item.label }),
4098
+ showsDescription ? /* @__PURE__ */ jsx62("span", { className: "pire-launcher-item-desc", children: item.description }) : null
4099
+ ] })
4100
+ ]
4101
+ },
4102
+ item.id
4103
+ );
4104
+ }) })
4105
+ ] }, section.label ?? section.items[0]?.id ?? si)
4106
+ ))
4107
+ ] }) })
4108
+ }
4109
+ )
4110
+ ] });
4111
+ }
4112
+
3951
4113
  // src/components/patterns/SidePanel.tsx
3952
- import { ModalOverlay as ModalOverlay3, Modal as Modal3, Dialog as AriaDialog5, Heading as Heading5 } from "react-aria-components";
3953
- import { jsx as jsx61, jsxs as jsxs52 } from "react/jsx-runtime";
4114
+ import { ModalOverlay as ModalOverlay3, Modal as Modal3, Dialog as AriaDialog6, Heading as Heading5 } from "react-aria-components";
4115
+ import { jsx as jsx63, jsxs as jsxs54 } from "react/jsx-runtime";
3954
4116
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
3955
4117
  const msg = usePireMessages();
3956
- return /* @__PURE__ */ jsx61(
4118
+ return /* @__PURE__ */ jsx63(
3957
4119
  ModalOverlay3,
3958
4120
  {
3959
4121
  className: "pire-sidepanel-overlay",
@@ -3962,36 +4124,151 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
3962
4124
  onOpenChange: (o) => {
3963
4125
  if (!o) onClose?.();
3964
4126
  },
3965
- children: /* @__PURE__ */ jsx61(Modal3, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs52(AriaDialog5, { className: "pire-dialog", style: { height: "100%" }, children: [
3966
- /* @__PURE__ */ jsxs52("header", { className: "pire-dialog-head", children: [
3967
- /* @__PURE__ */ jsxs52("div", { style: { flex: 1, minWidth: 0 }, children: [
3968
- /* @__PURE__ */ jsx61(Heading5, { slot: "title", className: "pire-dialog-title", children: title }),
3969
- subtitle ? /* @__PURE__ */ jsx61("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
4127
+ children: /* @__PURE__ */ jsx63(Modal3, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs54(AriaDialog6, { className: "pire-dialog", style: { height: "100%" }, children: [
4128
+ /* @__PURE__ */ jsxs54("header", { className: "pire-dialog-head", children: [
4129
+ /* @__PURE__ */ jsxs54("div", { style: { flex: 1, minWidth: 0 }, children: [
4130
+ /* @__PURE__ */ jsx63(Heading5, { slot: "title", className: "pire-dialog-title", children: title }),
4131
+ subtitle ? /* @__PURE__ */ jsx63("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
3970
4132
  ] }),
3971
- /* @__PURE__ */ jsx61(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
4133
+ /* @__PURE__ */ jsx63(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
3972
4134
  ] }),
3973
- /* @__PURE__ */ jsx61("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
3974
- footer ? /* @__PURE__ */ jsx61("footer", { className: "pire-dialog-foot", children: footer }) : null
4135
+ /* @__PURE__ */ jsx63("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
4136
+ footer ? /* @__PURE__ */ jsx63("footer", { className: "pire-dialog-foot", children: footer }) : null
3975
4137
  ] }) })
3976
4138
  }
3977
4139
  );
3978
4140
  }
3979
4141
 
3980
4142
  // src/components/patterns/EmptyState.tsx
3981
- import { jsx as jsx62, jsxs as jsxs53 } from "react/jsx-runtime";
4143
+ import { jsx as jsx64, jsxs as jsxs55 } from "react/jsx-runtime";
3982
4144
  function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
3983
- return /* @__PURE__ */ jsxs53("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
3984
- /* @__PURE__ */ jsx62(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
3985
- title ? /* @__PURE__ */ jsx62("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
3986
- children ? /* @__PURE__ */ jsx62("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
4145
+ return /* @__PURE__ */ jsxs55("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
4146
+ /* @__PURE__ */ jsx64(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
4147
+ title ? /* @__PURE__ */ jsx64("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
4148
+ children ? /* @__PURE__ */ jsx64("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
3987
4149
  action
3988
4150
  ] });
3989
4151
  }
3990
4152
 
4153
+ // src/components/patterns/NumPad.tsx
4154
+ import * as React28 from "react";
4155
+ import { jsx as jsx65, jsxs as jsxs56 } from "react/jsx-runtime";
4156
+ var BASE_KEYS = [
4157
+ { value: "7" },
4158
+ { value: "8" },
4159
+ { value: "9" },
4160
+ { value: "clear", label: "C" },
4161
+ { value: "4" },
4162
+ { value: "5" },
4163
+ { value: "6" },
4164
+ { value: "backspace", label: "\u232B" },
4165
+ { value: "1" },
4166
+ { value: "2" },
4167
+ { value: "3" },
4168
+ { value: "0" }
4169
+ ];
4170
+ var isInsertable = (value) => /^[0-9]+$/.test(value);
4171
+ function useNumPadKeyboard(onKey, isDisabled, containerRef) {
4172
+ const handler = React28.useRef(onKey);
4173
+ handler.current = onKey;
4174
+ React28.useEffect(() => {
4175
+ if (isDisabled) return;
4176
+ const isEditingElsewhere = () => {
4177
+ const el = document.activeElement;
4178
+ if (!el) return false;
4179
+ const tag = el.tagName;
4180
+ return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || el.hasAttribute("contenteditable");
4181
+ };
4182
+ const isBackgroundedByAnOverlay = () => containerRef.current?.closest("[inert]") != null;
4183
+ const onKeyDown = (event) => {
4184
+ if (event.metaKey || event.ctrlKey || event.altKey) return;
4185
+ if (isEditingElsewhere() || isBackgroundedByAnOverlay()) return;
4186
+ if (event.key >= "0" && event.key <= "9") {
4187
+ handler.current(event.key);
4188
+ return;
4189
+ }
4190
+ if (event.key === "Backspace") {
4191
+ handler.current("backspace");
4192
+ return;
4193
+ }
4194
+ if (event.key === "Escape") {
4195
+ handler.current("clear");
4196
+ return;
4197
+ }
4198
+ };
4199
+ document.addEventListener("keydown", onKeyDown);
4200
+ return () => document.removeEventListener("keydown", onKeyDown);
4201
+ }, [isDisabled, containerRef]);
4202
+ }
4203
+ function NumPad({
4204
+ "aria-label": ariaLabel,
4205
+ target,
4206
+ value,
4207
+ onChange,
4208
+ extraKeys = [],
4209
+ onAction,
4210
+ isDisabled,
4211
+ size = "md",
4212
+ className,
4213
+ style
4214
+ }) {
4215
+ const msg = usePireMessages();
4216
+ const containerRef = React28.useRef(null);
4217
+ const applyKey = React28.useCallback((key) => {
4218
+ if (isDisabled) return;
4219
+ if (key.value === "backspace") {
4220
+ onChange(value.slice(0, -1));
4221
+ return;
4222
+ }
4223
+ if (key.value === "clear") {
4224
+ onChange("");
4225
+ return;
4226
+ }
4227
+ if (isInsertable(key.value)) {
4228
+ onChange(value + key.value);
4229
+ return;
4230
+ }
4231
+ onAction?.(key.value);
4232
+ }, [isDisabled, value, onChange, onAction]);
4233
+ useNumPadKeyboard((keyValue) => applyKey({ value: keyValue }), isDisabled, containerRef);
4234
+ const keys = [...BASE_KEYS, ...extraKeys];
4235
+ return /* @__PURE__ */ jsxs56(
4236
+ "div",
4237
+ {
4238
+ ref: containerRef,
4239
+ className: cx("pire-numpad", className),
4240
+ style,
4241
+ "data-size": size,
4242
+ "data-disabled": isDisabled ? "true" : void 0,
4243
+ children: [
4244
+ target !== void 0 ? /* @__PURE__ */ jsx65("div", { className: "pire-numpad-target", role: "status", "aria-live": "polite", children: target }) : null,
4245
+ /* @__PURE__ */ jsx65("div", { className: "pire-numpad-grid", role: "group", "aria-label": ariaLabel, children: keys.map((key) => {
4246
+ const accessibleLabel = key.value === "backspace" ? msg.numPadBackspace : key.value === "clear" ? msg.numPadClear : void 0;
4247
+ return /* @__PURE__ */ jsx65(
4248
+ Button,
4249
+ {
4250
+ variant: "secondary",
4251
+ size,
4252
+ fullWidth: true,
4253
+ className: "pire-numpad-key",
4254
+ "data-span": key.span === 2 ? "2" : void 0,
4255
+ isDisabled,
4256
+ "aria-label": accessibleLabel,
4257
+ onPress: () => applyKey(key),
4258
+ children: key.label ?? key.value
4259
+ },
4260
+ key.value
4261
+ );
4262
+ }) })
4263
+ ]
4264
+ }
4265
+ );
4266
+ }
4267
+
3991
4268
  // src/components/patterns/FileDropZone.tsx
3992
- import * as React26 from "react";
4269
+ import * as React29 from "react";
3993
4270
  import { DropZone, FileTrigger as FileTrigger2, isFileDropItem } from "react-aria-components";
3994
- import { jsx as jsx63, jsxs as jsxs54 } from "react/jsx-runtime";
4271
+ import { jsx as jsx66, jsxs as jsxs57 } from "react/jsx-runtime";
3995
4272
  var isImage2 = (file) => file.type.startsWith("image/");
3996
4273
  function FileDropZone({
3997
4274
  label,
@@ -4019,10 +4296,10 @@ function FileDropZone({
4019
4296
  ...rest
4020
4297
  }) {
4021
4298
  const msg = usePireMessages();
4022
- const [uncontrolled, setUncontrolled] = React26.useState(defaultValue ?? []);
4299
+ const [uncontrolled, setUncontrolled] = React29.useState(defaultValue ?? []);
4023
4300
  const files = value ?? uncontrolled;
4024
- const created = React26.useRef([]);
4025
- React26.useEffect(() => () => {
4301
+ const created = React29.useRef([]);
4302
+ React29.useEffect(() => () => {
4026
4303
  for (const url of created.current) URL.revokeObjectURL(url);
4027
4304
  }, []);
4028
4305
  const commit = (next) => {
@@ -4042,12 +4319,12 @@ function FileDropZone({
4042
4319
  commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
4043
4320
  };
4044
4321
  const remove = (target) => commit(files.filter((f) => f.file !== target));
4045
- return /* @__PURE__ */ jsxs54("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), ...rest, children: [
4046
- label ? /* @__PURE__ */ jsxs54("span", { className: "pire-field-label", children: [
4322
+ return /* @__PURE__ */ jsxs57("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), ...rest, children: [
4323
+ label ? /* @__PURE__ */ jsxs57("span", { className: "pire-field-label", children: [
4047
4324
  label,
4048
- isRequired ? /* @__PURE__ */ jsx63("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
4325
+ isRequired ? /* @__PURE__ */ jsx66("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
4049
4326
  ] }) : null,
4050
- /* @__PURE__ */ jsxs54(
4327
+ /* @__PURE__ */ jsxs57(
4051
4328
  DropZone,
4052
4329
  {
4053
4330
  className: "pire-dropzone",
@@ -4061,25 +4338,25 @@ function FileDropZone({
4061
4338
  accept(dropped);
4062
4339
  },
4063
4340
  children: [
4064
- /* @__PURE__ */ jsx63(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
4065
- /* @__PURE__ */ jsx63("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
4066
- /* @__PURE__ */ jsx63(
4341
+ /* @__PURE__ */ jsx66(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
4342
+ /* @__PURE__ */ jsx66("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
4343
+ /* @__PURE__ */ jsx66(
4067
4344
  FileTrigger2,
4068
4345
  {
4069
4346
  acceptedFileTypes,
4070
4347
  allowsMultiple,
4071
4348
  onSelect: (list) => accept(list ? [...list] : []),
4072
- children: /* @__PURE__ */ jsx63(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
4349
+ children: /* @__PURE__ */ jsx66(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
4073
4350
  }
4074
4351
  )
4075
4352
  ]
4076
4353
  }
4077
4354
  ),
4078
- files.length ? /* @__PURE__ */ jsx63("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs54("li", { className: "pire-fileupload-item", children: [
4079
- previewUrl ? /* @__PURE__ */ jsx63("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx63(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
4080
- /* @__PURE__ */ jsx63("span", { className: "pire-fileupload-name", children: file.name }),
4081
- /* @__PURE__ */ jsx63("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
4082
- isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx63(
4355
+ files.length ? /* @__PURE__ */ jsx66("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs57("li", { className: "pire-fileupload-item", children: [
4356
+ previewUrl ? /* @__PURE__ */ jsx66("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx66(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
4357
+ /* @__PURE__ */ jsx66("span", { className: "pire-fileupload-name", children: file.name }),
4358
+ /* @__PURE__ */ jsx66("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
4359
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx66(
4083
4360
  IconButton,
4084
4361
  {
4085
4362
  icon: "x",
@@ -4089,16 +4366,17 @@ function FileDropZone({
4089
4366
  }
4090
4367
  )
4091
4368
  ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
4092
- uploadProgress != null ? /* @__PURE__ */ jsx63(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
4093
- description ? /* @__PURE__ */ jsx63("span", { className: "pire-field-hint", children: description }) : null,
4094
- isInvalid && errorMessage ? /* @__PURE__ */ jsx63("span", { className: "pire-field-error", children: errorMessage }) : null
4369
+ uploadProgress != null ? /* @__PURE__ */ jsx66(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
4370
+ description ? /* @__PURE__ */ jsx66("span", { className: "pire-field-hint", children: description }) : null,
4371
+ isInvalid && errorMessage ? /* @__PURE__ */ jsx66("span", { className: "pire-field-error", children: errorMessage }) : null
4095
4372
  ] });
4096
4373
  }
4097
4374
 
4098
4375
  // src/index.ts
4099
- import { DialogTrigger, MenuTrigger as MenuTrigger3, SubmenuTrigger, Popover as Popover8, RouterProvider, I18nProvider } from "react-aria-components";
4376
+ import { DialogTrigger as DialogTrigger2, MenuTrigger as MenuTrigger3, SubmenuTrigger, Popover as Popover9, RouterProvider, I18nProvider } from "react-aria-components";
4100
4377
  import { Focusable as Focusable2 } from "react-aria-components";
4101
4378
  export {
4379
+ AppLauncher,
4102
4380
  Avatar,
4103
4381
  Badge,
4104
4382
  BarChart,
@@ -4118,7 +4396,7 @@ export {
4118
4396
  DialogBody,
4119
4397
  DialogDescription,
4120
4398
  DialogTitle,
4121
- DialogTrigger,
4399
+ DialogTrigger2 as DialogTrigger,
4122
4400
  DonutChart,
4123
4401
  EmptyState,
4124
4402
  FileDropZone,
@@ -4145,13 +4423,14 @@ export {
4145
4423
  MenuSeparator,
4146
4424
  MenuTrigger3 as MenuTrigger,
4147
4425
  MultiComboBox,
4426
+ NumPad,
4148
4427
  NumberField,
4149
4428
  ObjectHeader,
4150
4429
  PageBand,
4151
4430
  PageHeader,
4152
4431
  Pagination,
4153
4432
  PireIntlProvider,
4154
- Popover8 as Popover,
4433
+ Popover9 as Popover,
4155
4434
  ProgressBar,
4156
4435
  Radio,
4157
4436
  RadioGroup,
@@ -4162,6 +4441,7 @@ export {
4162
4441
  SelectionBar,
4163
4442
  Separator,
4164
4443
  ShellBar,
4444
+ ShellRail,
4165
4445
  SideNav,
4166
4446
  SidePanel,
4167
4447
  Skeleton,