@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.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",
@@ -826,6 +837,12 @@ var esMessages = {
826
837
  paginationNext: "P\xE1gina siguiente",
827
838
  paginationRowsPerPage: "Filas por p\xE1gina",
828
839
  sideNavLabel: "Navegaci\xF3n principal",
840
+ shellRailLabel: "Aplicaciones",
841
+ appLauncherLabel: "Todas las aplicaciones",
842
+ appLauncherTitle: "Todas las aplicaciones",
843
+ appLauncherSearch: "Busc\xE1 una aplicaci\xF3n",
844
+ appLauncherEmpty: "Ninguna aplicaci\xF3n coincide con esa b\xFAsqueda.",
845
+ appLauncherLoading: "Cargando aplicaciones\u2026",
829
846
  splitPaneList: "Lista",
830
847
  splitPaneDetail: "Detalle",
831
848
  splitPaneBack: "Volver a la lista",
@@ -2573,6 +2590,7 @@ import { MenuTrigger, Button as AriaButton11, Popover as Popover6 } from "react-
2573
2590
  import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2574
2591
  var initials2 = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
2575
2592
  function ShellBar({
2593
+ launcher,
2576
2594
  product,
2577
2595
  monogram,
2578
2596
  title,
@@ -2589,6 +2607,7 @@ function ShellBar({
2589
2607
  }) {
2590
2608
  const msg = usePireMessages();
2591
2609
  return /* @__PURE__ */ jsxs27("header", { className: cx("pire-shellbar", className), ...rest, children: [
2610
+ launcher,
2592
2611
  onMenu ? /* @__PURE__ */ jsx35(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
2593
2612
  monogram ? /* @__PURE__ */ jsx35("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
2594
2613
  product ? /* @__PURE__ */ jsx35("span", { className: "pire-shellbar-product", children: product }) : null,
@@ -2848,11 +2867,37 @@ function SideNav({
2848
2867
  );
2849
2868
  }
2850
2869
 
2870
+ // src/components/navigation/ShellRail.tsx
2871
+ import * as React22 from "react";
2872
+ import { Button as AriaButton13 } from "react-aria-components";
2873
+ import { jsx as jsx38, jsxs as jsxs30 } from "react/jsx-runtime";
2874
+ function ShellRail({ groups, value, onChange, className, ...rest }) {
2875
+ const msg = usePireMessages();
2876
+ return /* @__PURE__ */ jsx38("nav", { className: cx("pire-shellrail", className), "aria-label": msg.shellRailLabel, ...rest, children: groups.map((group, gi) => (
2877
+ // The divider is a sibling of the groups rather than a pseudo-element on one, because the
2878
+ // scrolling zone would carry its own rule out of view on the first wheel event.
2879
+ /* @__PURE__ */ jsxs30(React22.Fragment, { children: [
2880
+ gi > 0 ? /* @__PURE__ */ jsx38("div", { className: "pire-shellrail-divider" }) : null,
2881
+ /* @__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(
2882
+ AriaButton13,
2883
+ {
2884
+ className: "pire-shellrail-item",
2885
+ "aria-label": item.label,
2886
+ "data-selected": item.id === value ? "true" : void 0,
2887
+ "aria-current": item.id === value ? "true" : void 0,
2888
+ onPress: () => onChange?.(item.id),
2889
+ children: /* @__PURE__ */ jsx38("span", { className: "pire-shellrail-tile", children: /* @__PURE__ */ jsx38(Icon, { name: item.icon, size: 20 }) })
2890
+ }
2891
+ ) }, item.id)) })
2892
+ ] }, group.items[0]?.id ?? gi)
2893
+ )) });
2894
+ }
2895
+
2851
2896
  // src/components/navigation/Tabs.tsx
2852
2897
  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";
2898
+ import { jsx as jsx39, jsxs as jsxs31 } from "react/jsx-runtime";
2854
2899
  function Tabs({ items, value, defaultValue, onChange, panels, className, style, ...rest }) {
2855
- return /* @__PURE__ */ jsxs30(
2900
+ return /* @__PURE__ */ jsxs31(
2856
2901
  AriaTabs,
2857
2902
  {
2858
2903
  className,
@@ -2861,12 +2906,12 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
2861
2906
  defaultSelectedKey: defaultValue,
2862
2907
  onSelectionChange: (k) => onChange?.(String(k)),
2863
2908
  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,
2909
+ /* @__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: [
2910
+ item.icon ? /* @__PURE__ */ jsx39(Icon, { name: item.icon, size: 16 }) : null,
2866
2911
  item.label,
2867
- item.count != null ? /* @__PURE__ */ jsx38("span", { className: "pire-tab-count", children: item.count }) : null
2912
+ item.count != null ? /* @__PURE__ */ jsx39("span", { className: "pire-tab-count", children: item.count }) : null
2868
2913
  ] }) }),
2869
- items.map((item) => /* @__PURE__ */ jsx38(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2914
+ items.map((item) => /* @__PURE__ */ jsx39(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2870
2915
  ]
2871
2916
  }
2872
2917
  );
@@ -2874,9 +2919,9 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
2874
2919
 
2875
2920
  // src/components/navigation/Breadcrumb.tsx
2876
2921
  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";
2922
+ import { jsx as jsx40, jsxs as jsxs32 } from "react/jsx-runtime";
2878
2923
  function Breadcrumb({ items, onNavigate, className, style }) {
2879
- return /* @__PURE__ */ jsx39(
2924
+ return /* @__PURE__ */ jsx40(
2880
2925
  AriaBreadcrumbs,
2881
2926
  {
2882
2927
  className: cx("pire-breadcrumbs", className),
@@ -2885,9 +2930,9 @@ function Breadcrumb({ items, onNavigate, className, style }) {
2885
2930
  onAction: (key) => onNavigate?.(String(key)),
2886
2931
  children: (item) => {
2887
2932
  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)" } })
2933
+ return /* @__PURE__ */ jsxs32(AriaBreadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
2934
+ last ? item.label : /* @__PURE__ */ jsx40(Link2, { href: item.href, children: item.label }),
2935
+ last ? null : /* @__PURE__ */ jsx40(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
2891
2936
  ] });
2892
2937
  }
2893
2938
  }
@@ -2895,7 +2940,7 @@ function Breadcrumb({ items, onNavigate, className, style }) {
2895
2940
  }
2896
2941
 
2897
2942
  // src/components/navigation/Pagination.tsx
2898
- import { jsx as jsx40, jsxs as jsxs32 } from "react/jsx-runtime";
2943
+ import { jsx as jsx41, jsxs as jsxs33 } from "react/jsx-runtime";
2899
2944
  function Pagination({
2900
2945
  page = 1,
2901
2946
  pageSize = 25,
@@ -2910,9 +2955,9 @@ function Pagination({
2910
2955
  const pages = Math.max(1, Math.ceil(total / pageSize));
2911
2956
  const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
2912
2957
  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(
2958
+ return /* @__PURE__ */ jsxs33("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
2959
+ /* @__PURE__ */ jsx41("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
2960
+ /* @__PURE__ */ jsx41(
2916
2961
  IconButton,
2917
2962
  {
2918
2963
  icon: "chevron-left",
@@ -2923,8 +2968,8 @@ function Pagination({
2923
2968
  onPress: () => onPageChange?.(page - 1)
2924
2969
  }
2925
2970
  ),
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(
2971
+ /* @__PURE__ */ jsx41("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
2972
+ /* @__PURE__ */ jsx41(
2928
2973
  IconButton,
2929
2974
  {
2930
2975
  icon: "chevron-right",
@@ -2935,7 +2980,7 @@ function Pagination({
2935
2980
  onPress: () => onPageChange?.(page + 1)
2936
2981
  }
2937
2982
  ),
2938
- onPageSizeChange ? /* @__PURE__ */ jsx40(
2983
+ onPageSizeChange ? /* @__PURE__ */ jsx41(
2939
2984
  Select,
2940
2985
  {
2941
2986
  "aria-label": msg.paginationRowsPerPage,
@@ -2951,7 +2996,7 @@ function Pagination({
2951
2996
  }
2952
2997
 
2953
2998
  // src/components/feedback/InlineMessage.tsx
2954
- import { jsx as jsx41, jsxs as jsxs33 } from "react/jsx-runtime";
2999
+ import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
2955
3000
  var KIND_ICON = {
2956
3001
  info: "info",
2957
3002
  success: "check-circle-2",
@@ -2961,7 +3006,7 @@ var KIND_ICON = {
2961
3006
  function InlineMessage({ kind = "info", title, action, onClose, children, className, ...rest }) {
2962
3007
  const msg = usePireMessages();
2963
3008
  const assertive = kind === "error" || kind === "warning";
2964
- return /* @__PURE__ */ jsxs33(
3009
+ return /* @__PURE__ */ jsxs34(
2965
3010
  "div",
2966
3011
  {
2967
3012
  className: cx("pire-msg", className),
@@ -2970,21 +3015,21 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
2970
3015
  "aria-live": assertive ? "assertive" : "polite",
2971
3016
  ...rest,
2972
3017
  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,
3018
+ /* @__PURE__ */ jsx42(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
3019
+ /* @__PURE__ */ jsxs34("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
3020
+ title ? /* @__PURE__ */ jsx42("span", { className: "pire-msg-title", children: title }) : null,
3021
+ children ? /* @__PURE__ */ jsx42("span", { className: "pire-msg-body", children }) : null,
2977
3022
  action
2978
3023
  ] }),
2979
- onClose ? /* @__PURE__ */ jsx41(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
3024
+ onClose ? /* @__PURE__ */ jsx42(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
2980
3025
  ]
2981
3026
  }
2982
3027
  );
2983
3028
  }
2984
3029
 
2985
3030
  // src/components/feedback/Toast.tsx
2986
- import * as React22 from "react";
2987
- import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
3031
+ import * as React23 from "react";
3032
+ import { jsx as jsx43, jsxs as jsxs35 } from "react/jsx-runtime";
2988
3033
  var KIND_ICON2 = {
2989
3034
  info: "info",
2990
3035
  success: "check-circle-2",
@@ -2993,7 +3038,7 @@ var KIND_ICON2 = {
2993
3038
  };
2994
3039
  function Toast({ kind = "success", onClose, position = "bottom-center", children, className, ...rest }) {
2995
3040
  const msg = usePireMessages();
2996
- return /* @__PURE__ */ jsxs34(
3041
+ return /* @__PURE__ */ jsxs35(
2997
3042
  "div",
2998
3043
  {
2999
3044
  className: cx("pire-toast", className),
@@ -3002,40 +3047,40 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
3002
3047
  "aria-live": kind === "error" ? "assertive" : "polite",
3003
3048
  ...rest,
3004
3049
  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
3050
+ /* @__PURE__ */ jsx43(Icon, { name: KIND_ICON2[kind], size: 16 }),
3051
+ /* @__PURE__ */ jsx43("span", { style: { flex: 1 }, children }),
3052
+ onClose ? /* @__PURE__ */ jsx43(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
3008
3053
  ]
3009
3054
  }
3010
3055
  );
3011
3056
  }
3012
- var ToastContext = React22.createContext(null);
3057
+ var ToastContext = React23.createContext(null);
3013
3058
  function ToastProvider({ children, timeout = 6e3 }) {
3014
3059
  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) => {
3060
+ const [toasts, setToasts] = React23.useState([]);
3061
+ const close = React23.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
3062
+ const add = React23.useCallback((toast) => {
3018
3063
  const id = Math.random().toString(36).slice(2);
3019
3064
  setToasts((t) => [...t, { ...toast, id }]);
3020
3065
  const ms = toast.timeout ?? timeout;
3021
3066
  if (ms > 0) setTimeout(() => close(id), ms);
3022
3067
  return id;
3023
3068
  }, [close, timeout]);
3024
- const value = React22.useMemo(() => ({ add, close }), [add, close]);
3025
- return /* @__PURE__ */ jsxs34(ToastContext.Provider, { value, children: [
3069
+ const value = React23.useMemo(() => ({ add, close }), [add, close]);
3070
+ return /* @__PURE__ */ jsxs35(ToastContext.Provider, { value, children: [
3026
3071
  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)) })
3072
+ /* @__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
3073
  ] });
3029
3074
  }
3030
3075
  function useToast() {
3031
- const ctx = React22.useContext(ToastContext);
3076
+ const ctx = React23.useContext(ToastContext);
3032
3077
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
3033
3078
  return ctx;
3034
3079
  }
3035
3080
 
3036
3081
  // 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";
3082
+ import { Button as AriaButton14 } from "react-aria-components";
3083
+ import { Fragment as Fragment4, jsx as jsx44, jsxs as jsxs36 } from "react/jsx-runtime";
3039
3084
  function KpiTile({
3040
3085
  label,
3041
3086
  value,
@@ -3051,50 +3096,50 @@ function KpiTile({
3051
3096
  style
3052
3097
  }) {
3053
3098
  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,
3099
+ const body = /* @__PURE__ */ jsxs36(Fragment4, { children: [
3100
+ /* @__PURE__ */ jsxs36("span", { className: "pire-kpi-label", children: [
3101
+ icon ? /* @__PURE__ */ jsx44(Icon, { name: icon, size: 16 }) : null,
3057
3102
  label
3058
3103
  ] }),
3059
- /* @__PURE__ */ jsxs35("span", { className: "pire-kpi-value", children: [
3104
+ /* @__PURE__ */ jsxs36("span", { className: "pire-kpi-value", children: [
3060
3105
  value,
3061
- unit ? /* @__PURE__ */ jsx43("span", { className: "pire-kpi-unit", children: unit }) : null
3106
+ unit ? /* @__PURE__ */ jsx44("span", { className: "pire-kpi-unit", children: unit }) : null
3062
3107
  ] }),
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,
3108
+ delta ? /* @__PURE__ */ jsxs36("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
3109
+ deltaDirection ? /* @__PURE__ */ jsx44(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
3065
3110
  delta
3066
3111
  ] }) : null,
3067
- footnote ? /* @__PURE__ */ jsx43("span", { className: "pire-kpi-foot", children: footnote }) : null
3112
+ footnote ? /* @__PURE__ */ jsx44("span", { className: "pire-kpi-foot", children: footnote }) : null
3068
3113
  ] });
3069
3114
  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 });
3115
+ return onPress ? /* @__PURE__ */ jsx44(AriaButton14, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ jsx44("div", { ...props, children: body });
3071
3116
  }
3072
3117
 
3073
3118
  // src/components/data/ObjectHeader.tsx
3074
- import { jsx as jsx44, jsxs as jsxs36 } from "react/jsx-runtime";
3119
+ import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
3075
3120
  function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions, className, ...rest }) {
3076
- return /* @__PURE__ */ jsxs36("header", { className: cx("pire-objheader", className), ...rest, children: [
3121
+ return /* @__PURE__ */ jsxs37("header", { className: cx("pire-objheader", className), ...rest, children: [
3077
3122
  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: [
3123
+ /* @__PURE__ */ jsxs37("div", { className: "pire-objheader-row", children: [
3124
+ /* @__PURE__ */ jsxs37("div", { style: { minWidth: 0 }, children: [
3125
+ /* @__PURE__ */ jsx45("h1", { className: "pire-objheader-title", children: title }),
3126
+ subtitle || id ? /* @__PURE__ */ jsxs37("div", { className: "pire-objheader-sub", children: [
3082
3127
  subtitle,
3083
- id ? /* @__PURE__ */ jsx44("span", { className: "pire-objheader-id", children: id }) : null
3128
+ id ? /* @__PURE__ */ jsx45("span", { className: "pire-objheader-id", children: id }) : null
3084
3129
  ] }) : null
3085
3130
  ] }),
3086
3131
  badge,
3087
- actions ? /* @__PURE__ */ jsx44("div", { className: "pire-objheader-actions", children: actions }) : null
3132
+ actions ? /* @__PURE__ */ jsx45("div", { className: "pire-objheader-actions", children: actions }) : null
3088
3133
  ] }),
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 })
3134
+ facts?.length ? /* @__PURE__ */ jsx45("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs37("div", { children: [
3135
+ /* @__PURE__ */ jsx45("dt", { className: "pire-fact-label", children: fact.label }),
3136
+ /* @__PURE__ */ jsx45("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
3092
3137
  ] }, fact.label)) }) : null
3093
3138
  ] });
3094
3139
  }
3095
3140
 
3096
3141
  // src/components/data/FilterBar.tsx
3097
- import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
3142
+ import { jsx as jsx46, jsxs as jsxs38 } from "react/jsx-runtime";
3098
3143
  function FilterBar({
3099
3144
  children,
3100
3145
  activeFilters = [],
@@ -3111,49 +3156,49 @@ function FilterBar({
3111
3156
  const label = useMessage("filterBarLabel", rest["aria-label"]);
3112
3157
  const go = useMessage("filterBarGo", goLabel);
3113
3158
  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: [
3159
+ return /* @__PURE__ */ jsxs38("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
3160
+ /* @__PURE__ */ jsxs38("div", { className: "pire-filterbar-controls", children: [
3116
3161
  children,
3117
- onGo ? /* @__PURE__ */ jsx45(Button, { variant: "primary", onPress: onGo, children: go }) : null
3162
+ onGo ? /* @__PURE__ */ jsx46(Button, { variant: "primary", onPress: onGo, children: go }) : null
3118
3163
  ] }),
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
3164
+ activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs38("div", { className: "pire-filterbar-foot", children: [
3165
+ activeFilters.map((filter) => /* @__PURE__ */ jsx46(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
3166
+ activeFilters.length && onClear ? /* @__PURE__ */ jsx46(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
3167
+ resultLabel ? /* @__PURE__ */ jsx46("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
3168
+ actions ? /* @__PURE__ */ jsx46("div", { className: "pire-filterbar-actions", children: actions }) : null
3124
3169
  ] }) : null
3125
3170
  ] });
3126
3171
  }
3127
3172
 
3128
3173
  // src/components/data/DescriptionList.tsx
3129
- import { jsx as jsx46, jsxs as jsxs38 } from "react/jsx-runtime";
3174
+ import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
3130
3175
  function DescriptionList({ items, layout = "rows", columns = 3, className, style, ...rest }) {
3131
- return /* @__PURE__ */ jsx46(
3176
+ return /* @__PURE__ */ jsx47(
3132
3177
  "dl",
3133
3178
  {
3134
3179
  className: cx("pire-dl", className),
3135
3180
  "data-layout": layout,
3136
3181
  style: { ...layout === "grid" ? { "--pire-dl-cols": columns } : null, ...style },
3137
3182
  ...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: [
3183
+ children: items.map((item, i) => /* @__PURE__ */ jsxs39("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
3184
+ /* @__PURE__ */ jsxs39("dt", { className: "pire-dl-term", children: [
3140
3185
  item.label,
3141
3186
  item.hint
3142
3187
  ] }),
3143
- /* @__PURE__ */ jsx46("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
3188
+ /* @__PURE__ */ jsx47("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
3144
3189
  ] }, i))
3145
3190
  }
3146
3191
  );
3147
3192
  }
3148
3193
 
3149
3194
  // src/components/data/Timeline.tsx
3150
- import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
3195
+ import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
3151
3196
  function Timeline({ entries, reverse = false, className, ...rest }) {
3152
3197
  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
3198
+ return /* @__PURE__ */ jsx48("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs40("li", { className: "pire-timeline-item", children: [
3199
+ /* @__PURE__ */ jsx48("span", { className: "pire-timeline-time", children: entry.time }),
3200
+ /* @__PURE__ */ jsx48("span", { className: "pire-timeline-text", children: entry.event }),
3201
+ entry.actor ? /* @__PURE__ */ jsx48("span", { className: "pire-timeline-actor", children: entry.actor }) : null
3157
3202
  ] }, entry.id ?? i)) });
3158
3203
  }
3159
3204
 
@@ -3236,7 +3281,7 @@ function alignToCategories(series, categoryCount) {
3236
3281
  }
3237
3282
 
3238
3283
  // src/components/data/ChartFrame.tsx
3239
- import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
3284
+ import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
3240
3285
  function seriesLegend(series) {
3241
3286
  return series.map((one, index) => ({
3242
3287
  key: one.id,
@@ -3259,29 +3304,29 @@ function ChartFrame({
3259
3304
  children
3260
3305
  }) {
3261
3306
  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
3307
+ return /* @__PURE__ */ jsxs41("figure", { className: cx("pire-chart", className), style, children: [
3308
+ title || description ? /* @__PURE__ */ jsxs41("figcaption", { className: "pire-chart-head", children: [
3309
+ title ? /* @__PURE__ */ jsx49("span", { className: "pire-chart-title", children: title }) : null,
3310
+ description ? /* @__PURE__ */ jsx49("span", { className: "pire-chart-desc", children: description }) : null
3266
3311
  ] }) : 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 } }),
3312
+ legend && legend.length > 1 ? /* @__PURE__ */ jsx49("ul", { className: "pire-chart-legend", children: legend.map((item) => /* @__PURE__ */ jsxs41("li", { className: "pire-chart-legend-item", children: [
3313
+ /* @__PURE__ */ jsx49("span", { className: "pire-chart-swatch", style: { background: item.color } }),
3269
3314
  item.label
3270
3315
  ] }, 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))
3316
+ /* @__PURE__ */ jsx49("div", { className: "pire-chart-plot", "aria-hidden": "true", children }),
3317
+ /* @__PURE__ */ jsx49("div", { className: showDataTable ? "pire-chart-table" : "pire-sr-only", children: /* @__PURE__ */ jsxs41("table", { children: [
3318
+ /* @__PURE__ */ jsx49("caption", { children: label }),
3319
+ /* @__PURE__ */ jsx49("thead", { children: /* @__PURE__ */ jsxs41("tr", { children: [
3320
+ /* @__PURE__ */ jsx49("th", { scope: "col", children: msg.chartCategoryHeader }),
3321
+ series.map((one) => /* @__PURE__ */ jsx49("th", { scope: "col", children: one.label }, one.id))
3277
3322
  ] }) }),
3278
- /* @__PURE__ */ jsx48("tbody", { children: categories.map((category, categoryIndex) => (
3323
+ /* @__PURE__ */ jsx49("tbody", { children: categories.map((category, categoryIndex) => (
3279
3324
  // 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 }),
3325
+ /* @__PURE__ */ jsxs41("tr", { children: [
3326
+ /* @__PURE__ */ jsx49("th", { scope: "row", children: category }),
3282
3327
  series.map((one) => {
3283
3328
  const value = one.values[categoryIndex];
3284
- return /* @__PURE__ */ jsx48("td", { children: value == null ? msg.chartNoValue : formatValue(value) }, one.id);
3329
+ return /* @__PURE__ */ jsx49("td", { children: value == null ? msg.chartNoValue : formatValue(value) }, one.id);
3285
3330
  })
3286
3331
  ] }, categoryIndex)
3287
3332
  )) })
@@ -3290,7 +3335,7 @@ function ChartFrame({
3290
3335
  }
3291
3336
 
3292
3337
  // src/components/data/BarChart.tsx
3293
- import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
3338
+ import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
3294
3339
  function BarChart({
3295
3340
  categories,
3296
3341
  series: rawSeries,
@@ -3322,7 +3367,7 @@ function BarChart({
3322
3367
  const value = series[0].values[categoryIndex];
3323
3368
  return value == null ? msg.chartNoValue : formatValue(value);
3324
3369
  };
3325
- return /* @__PURE__ */ jsx49(
3370
+ return /* @__PURE__ */ jsx50(
3326
3371
  ChartFrame,
3327
3372
  {
3328
3373
  label,
@@ -3335,7 +3380,7 @@ function BarChart({
3335
3380
  showDataTable,
3336
3381
  className,
3337
3382
  style,
3338
- children: !hasData ? /* @__PURE__ */ jsx49("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsx49(
3383
+ children: !hasData ? /* @__PURE__ */ jsx50("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsx50(
3339
3384
  "div",
3340
3385
  {
3341
3386
  className: "pire-chart-bars",
@@ -3344,12 +3389,12 @@ function BarChart({
3344
3389
  style: { "--pire-chart-height": `${height}px` },
3345
3390
  children: categories.map((category, categoryIndex) => (
3346
3391
  // 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) => {
3392
+ /* @__PURE__ */ jsxs42("div", { className: "pire-chart-group", children: [
3393
+ /* @__PURE__ */ jsx50("span", { className: "pire-chart-cat", children: category }),
3394
+ /* @__PURE__ */ jsx50("div", { className: "pire-chart-track", children: series.map((one, seriesIndex) => {
3350
3395
  const value = one.values[categoryIndex];
3351
3396
  if (value == null) return null;
3352
- return /* @__PURE__ */ jsxs41(
3397
+ return /* @__PURE__ */ jsxs42(
3353
3398
  "div",
3354
3399
  {
3355
3400
  className: "pire-chart-bar",
@@ -3358,8 +3403,8 @@ function BarChart({
3358
3403
  "--pire-bar-color": seriesColor(one, seriesIndex)
3359
3404
  },
3360
3405
  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: [
3406
+ withValues && orientation === "vertical" ? /* @__PURE__ */ jsx50("span", { className: "pire-chart-barval", children: formatValue(value) }) : null,
3407
+ /* @__PURE__ */ jsxs42("span", { className: "pire-chart-tip", role: "presentation", children: [
3363
3408
  series.length > 1 ? `${one.label}: ` : "",
3364
3409
  formatValue(value)
3365
3410
  ] })
@@ -3368,7 +3413,7 @@ function BarChart({
3368
3413
  one.id
3369
3414
  );
3370
3415
  }) }),
3371
- withValues && orientation === "horizontal" ? /* @__PURE__ */ jsx49("span", { className: "pire-chart-val", children: horizontalLabelFor(categoryIndex) }) : null
3416
+ withValues && orientation === "horizontal" ? /* @__PURE__ */ jsx50("span", { className: "pire-chart-val", children: horizontalLabelFor(categoryIndex) }) : null
3372
3417
  ] }, categoryIndex)
3373
3418
  ))
3374
3419
  }
@@ -3378,14 +3423,14 @@ function BarChart({
3378
3423
  }
3379
3424
 
3380
3425
  // src/components/data/LineChart.tsx
3381
- import * as React23 from "react";
3382
- import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
3426
+ import * as React24 from "react";
3427
+ import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
3383
3428
  var PLOT_INSET = { top: 10, right: 14, bottom: 24, left: 58 };
3384
3429
  var MARKER_LIMIT = 20;
3385
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React23.useEffect : React23.useLayoutEffect;
3430
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React24.useEffect : React24.useLayoutEffect;
3386
3431
  function useMeasuredWidth() {
3387
- const ref = React23.useRef(null);
3388
- const [width, setWidth] = React23.useState(0);
3432
+ const ref = React24.useRef(null);
3433
+ const [width, setWidth] = React24.useState(0);
3389
3434
  useIsomorphicLayoutEffect2(() => {
3390
3435
  const element = ref.current;
3391
3436
  if (!element) return;
@@ -3446,7 +3491,7 @@ function LineChart({
3446
3491
  return `M${xAt(present[0].index)} ${baseline} L${line} L${xAt(last.index)} ${baseline} Z`;
3447
3492
  };
3448
3493
  const labelEvery = Math.max(1, Math.ceil(categories.length / Math.max(2, Math.floor(innerWidth / 64))));
3449
- return /* @__PURE__ */ jsx50(
3494
+ return /* @__PURE__ */ jsx51(
3450
3495
  ChartFrame,
3451
3496
  {
3452
3497
  label,
@@ -3459,8 +3504,8 @@ function LineChart({
3459
3504
  showDataTable,
3460
3505
  className,
3461
3506
  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(
3507
+ 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: [
3508
+ width > 0 ? /* @__PURE__ */ jsxs43(
3464
3509
  "svg",
3465
3510
  {
3466
3511
  width,
@@ -3469,7 +3514,7 @@ function LineChart({
3469
3514
  "aria-hidden": "true",
3470
3515
  focusable: "false",
3471
3516
  children: [
3472
- /* @__PURE__ */ jsx50("g", { className: "pire-chart-grid", children: scale.ticks.map((tick) => /* @__PURE__ */ jsx50(
3517
+ /* @__PURE__ */ jsx51("g", { className: "pire-chart-grid", children: scale.ticks.map((tick) => /* @__PURE__ */ jsx51(
3473
3518
  "line",
3474
3519
  {
3475
3520
  x1: PLOT_INSET.left,
@@ -3479,8 +3524,8 @@ function LineChart({
3479
3524
  },
3480
3525
  tick
3481
3526
  )) }),
3482
- /* @__PURE__ */ jsxs42("g", { className: "pire-chart-tick", children: [
3483
- scale.ticks.map((tick) => /* @__PURE__ */ jsx50(
3527
+ /* @__PURE__ */ jsxs43("g", { className: "pire-chart-tick", children: [
3528
+ scale.ticks.map((tick) => /* @__PURE__ */ jsx51(
3484
3529
  "text",
3485
3530
  {
3486
3531
  x: PLOT_INSET.left - 8,
@@ -3493,10 +3538,10 @@ function LineChart({
3493
3538
  )),
3494
3539
  categories.map((category, index) => index % labelEvery === 0 ? (
3495
3540
  // 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)
3541
+ /* @__PURE__ */ jsx51("text", { x: xAt(index), y: height - 6, textAnchor: "middle", children: category }, index)
3497
3542
  ) : null)
3498
3543
  ] }),
3499
- showArea && series[0] ? /* @__PURE__ */ jsx50(
3544
+ showArea && series[0] ? /* @__PURE__ */ jsx51(
3500
3545
  "path",
3501
3546
  {
3502
3547
  d: areaFor(series[0].values),
@@ -3504,10 +3549,10 @@ function LineChart({
3504
3549
  style: { fill: seriesColor(series[0], 0) }
3505
3550
  }
3506
3551
  ) : 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 : (
3552
+ /* @__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)) }),
3553
+ withMarkers ? /* @__PURE__ */ jsx51("g", { className: "pire-chart-marker", children: series.map((one, seriesIndex) => one.values.map((value, index) => value == null ? null : (
3509
3554
  // biome-ignore lint/suspicious/noArrayIndexKey: a series is positional — the index is the point's identity, and category labels repeat.
3510
- /* @__PURE__ */ jsx50(
3555
+ /* @__PURE__ */ jsx51(
3511
3556
  "circle",
3512
3557
  {
3513
3558
  cx: xAt(index),
@@ -3521,18 +3566,18 @@ function LineChart({
3521
3566
  ]
3522
3567
  }
3523
3568
  ) : null,
3524
- /* @__PURE__ */ jsx50(
3569
+ /* @__PURE__ */ jsx51(
3525
3570
  "div",
3526
3571
  {
3527
3572
  className: "pire-chart-hover",
3528
3573
  style: { inset: `${PLOT_INSET.top}px ${PLOT_INSET.right}px ${PLOT_INSET.bottom}px ${PLOT_INSET.left}px` },
3529
3574
  children: categories.map((category, categoryIndex) => (
3530
3575
  // 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 }),
3576
+ /* @__PURE__ */ jsx51("div", { className: "pire-chart-band", children: /* @__PURE__ */ jsxs43("span", { className: "pire-chart-tip", role: "presentation", children: [
3577
+ /* @__PURE__ */ jsx51("strong", { children: category }),
3533
3578
  series.map((one) => {
3534
3579
  const value = one.values[categoryIndex];
3535
- return /* @__PURE__ */ jsxs42("span", { className: "pire-chart-tip-row", children: [
3580
+ return /* @__PURE__ */ jsxs43("span", { className: "pire-chart-tip-row", children: [
3536
3581
  one.label,
3537
3582
  ": ",
3538
3583
  value == null ? "No data" : formatValue(value)
@@ -3548,8 +3593,8 @@ function LineChart({
3548
3593
  }
3549
3594
 
3550
3595
  // src/components/data/DonutChart.tsx
3551
- import * as React24 from "react";
3552
- import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
3596
+ import * as React25 from "react";
3597
+ import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
3553
3598
  var SEGMENT_GAP_DEGREES = 1.5;
3554
3599
  function DonutChart({
3555
3600
  categories,
@@ -3569,7 +3614,7 @@ function DonutChart({
3569
3614
  }) {
3570
3615
  const label = rest["aria-label"];
3571
3616
  const msg = usePireMessages();
3572
- const [hoveredIndex, setHoveredIndex] = React24.useState(null);
3617
+ const [hoveredIndex, setHoveredIndex] = React25.useState(null);
3573
3618
  warnOnDonutShape(series, categories.length, label);
3574
3619
  const values = (series[0]?.values ?? []).slice(0, categories.length);
3575
3620
  const segments = categories.map((category, index) => ({ category, index, value: values[index] ?? 0 })).filter((segment) => segment.value > 0);
@@ -3586,7 +3631,7 @@ function DonutChart({
3586
3631
  }));
3587
3632
  const hovered = hoveredIndex == null ? null : segments.find((segment) => segment.index === hoveredIndex) ?? null;
3588
3633
  let arcStart = 0;
3589
- return /* @__PURE__ */ jsx51(
3634
+ return /* @__PURE__ */ jsx52(
3590
3635
  ChartFrame,
3591
3636
  {
3592
3637
  label,
@@ -3599,8 +3644,8 @@ function DonutChart({
3599
3644
  showDataTable,
3600
3645
  className,
3601
3646
  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(
3647
+ children: !hasData ? /* @__PURE__ */ jsx52("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsxs44("div", { className: "pire-chart-donut", style: { height: size }, children: [
3648
+ /* @__PURE__ */ jsx52(
3604
3649
  "svg",
3605
3650
  {
3606
3651
  width: size,
@@ -3608,13 +3653,13 @@ function DonutChart({
3608
3653
  "aria-hidden": "true",
3609
3654
  focusable: "false",
3610
3655
  onMouseLeave: () => setHoveredIndex(null),
3611
- children: /* @__PURE__ */ jsx51("g", { transform: `rotate(-90 ${size / 2} ${size / 2})`, children: segments.map((segment) => {
3656
+ children: /* @__PURE__ */ jsx52("g", { transform: `rotate(-90 ${size / 2} ${size / 2})`, children: segments.map((segment) => {
3612
3657
  const arcLength = segment.value / total * circumference;
3613
3658
  const offset = arcStart;
3614
3659
  arcStart += arcLength;
3615
3660
  return (
3616
3661
  // 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(
3662
+ /* @__PURE__ */ jsx52(
3618
3663
  "circle",
3619
3664
  {
3620
3665
  className: "pire-chart-arc",
@@ -3634,9 +3679,9 @@ function DonutChart({
3634
3679
  }) })
3635
3680
  }
3636
3681
  ),
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 })
3682
+ /* @__PURE__ */ jsxs44("div", { className: "pire-chart-donut-center", style: { width: size - thickness * 2 - 8 }, children: [
3683
+ /* @__PURE__ */ jsx52("span", { className: "pire-chart-donut-value", children: hovered ? formatValue(hovered.value) : centerLabel ?? formatValue(total) }),
3684
+ /* @__PURE__ */ jsx52("span", { className: "pire-chart-donut-caption", children: hovered ? hovered.category : centerCaption })
3640
3685
  ] })
3641
3686
  ] })
3642
3687
  }
@@ -3647,15 +3692,15 @@ function colorForSegment(index) {
3647
3692
  }
3648
3693
 
3649
3694
  // 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";
3695
+ import { Button as AriaButton15 } from "react-aria-components";
3696
+ import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
3652
3697
  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;
3698
+ return /* @__PURE__ */ jsx53("div", { className: cx("pire-linklist", className), role: "list", "data-emphasis": emphasis, ...rest, children: items.map((item) => {
3699
+ const keySlot = item.key ? /* @__PURE__ */ jsx53("span", { className: "pire-linklist-key", children: item.key }) : null;
3700
+ const textSlot = item.text ? /* @__PURE__ */ jsx53("span", { className: "pire-linklist-text", children: item.text }) : null;
3656
3701
  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,
3702
+ return /* @__PURE__ */ jsx53("div", { role: "listitem", className: "pire-linklist-row", children: /* @__PURE__ */ jsxs45(AriaButton15, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
3703
+ item.icon ? /* @__PURE__ */ jsx53(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
3659
3704
  first,
3660
3705
  second,
3661
3706
  item.trailing
@@ -3664,7 +3709,7 @@ function LinkList({ items, onSelect, emphasis = "key", className, ...rest }) {
3664
3709
  }
3665
3710
 
3666
3711
  // src/components/layout/PageBand.tsx
3667
- import { jsx as jsx53 } from "react/jsx-runtime";
3712
+ import { jsx as jsx54 } from "react/jsx-runtime";
3668
3713
  function PageBand({
3669
3714
  surface = "card",
3670
3715
  hasBorder = true,
@@ -3672,7 +3717,7 @@ function PageBand({
3672
3717
  className,
3673
3718
  ...rest
3674
3719
  }) {
3675
- return /* @__PURE__ */ jsx53(
3720
+ return /* @__PURE__ */ jsx54(
3676
3721
  "div",
3677
3722
  {
3678
3723
  className: cx("pire-pageband", className),
@@ -3685,56 +3730,56 @@ function PageBand({
3685
3730
  }
3686
3731
 
3687
3732
  // src/components/layout/PageHeader.tsx
3688
- import { jsx as jsx54, jsxs as jsxs45 } from "react/jsx-runtime";
3733
+ import { jsx as jsx55, jsxs as jsxs46 } from "react/jsx-runtime";
3689
3734
  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
3735
+ return /* @__PURE__ */ jsxs46("header", { className: cx("pire-pageheader", className), ...rest, children: [
3736
+ /* @__PURE__ */ jsxs46("div", { style: { minWidth: 0 }, children: [
3737
+ /* @__PURE__ */ jsx55("h1", { className: "pire-pageheader-title", children: title }),
3738
+ subtitle ? /* @__PURE__ */ jsx55("p", { className: "pire-pageheader-sub", children: subtitle }) : null
3694
3739
  ] }),
3695
- actions ? /* @__PURE__ */ jsx54("div", { className: "pire-pageheader-actions", children: actions }) : null
3740
+ actions ? /* @__PURE__ */ jsx55("div", { className: "pire-pageheader-actions", children: actions }) : null
3696
3741
  ] });
3697
3742
  }
3698
3743
 
3699
3744
  // src/components/layout/SectionHeader.tsx
3700
- import { jsx as jsx55, jsxs as jsxs46 } from "react/jsx-runtime";
3745
+ import { jsx as jsx56, jsxs as jsxs47 } from "react/jsx-runtime";
3701
3746
  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
3747
+ return /* @__PURE__ */ jsxs47("div", { className: cx("pire-sectionhead", className), ...rest, children: [
3748
+ /* @__PURE__ */ jsx56("span", { className: "pire-eyebrow", children: title }),
3749
+ meta ? /* @__PURE__ */ jsx56("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
3750
+ actions ? /* @__PURE__ */ jsx56("div", { className: "pire-sectionhead-actions", children: actions }) : null
3706
3751
  ] });
3707
3752
  }
3708
3753
 
3709
3754
  // src/components/layout/SelectionBar.tsx
3710
- import { jsx as jsx56, jsxs as jsxs47 } from "react/jsx-runtime";
3755
+ import { jsx as jsx57, jsxs as jsxs48 } from "react/jsx-runtime";
3711
3756
  function SelectionBar({ count, noun = "record", children, actions, className, ...rest }) {
3712
3757
  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: [
3758
+ return /* @__PURE__ */ jsxs48("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
3759
+ /* @__PURE__ */ jsxs48("span", { className: "pire-selectionbar-count", children: [
3715
3760
  count.toLocaleString(),
3716
3761
  " ",
3717
3762
  noun,
3718
3763
  count === 1 ? "" : "s",
3719
3764
  " selected"
3720
3765
  ] }),
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
3766
+ children ? /* @__PURE__ */ jsx57("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
3767
+ actions ? /* @__PURE__ */ jsx57("div", { className: "pire-selectionbar-actions", children: actions }) : null
3723
3768
  ] });
3724
3769
  }
3725
3770
 
3726
3771
  // src/components/layout/FooterBar.tsx
3727
- import { jsx as jsx57, jsxs as jsxs48 } from "react/jsx-runtime";
3772
+ import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
3728
3773
  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,
3774
+ return /* @__PURE__ */ jsxs49("footer", { className: cx("pire-footerbar", className), ...rest, children: [
3775
+ note ? /* @__PURE__ */ jsx58("span", { className: "pire-footerbar-note", children: note }) : null,
3731
3776
  children,
3732
- actions ? /* @__PURE__ */ jsx57("div", { className: "pire-footerbar-actions", children: actions }) : null
3777
+ actions ? /* @__PURE__ */ jsx58("div", { className: "pire-footerbar-actions", children: actions }) : null
3733
3778
  ] });
3734
3779
  }
3735
3780
 
3736
3781
  // src/components/layout/SplitPane.tsx
3737
- import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
3782
+ import { jsx as jsx59, jsxs as jsxs50 } from "react/jsx-runtime";
3738
3783
  function SplitPane({
3739
3784
  list,
3740
3785
  detail,
@@ -3750,7 +3795,7 @@ function SplitPane({
3750
3795
  }) {
3751
3796
  const msg = usePireMessages();
3752
3797
  const width = typeof listWidth === "number" ? `${listWidth}px` : listWidth;
3753
- return /* @__PURE__ */ jsxs49(
3798
+ return /* @__PURE__ */ jsxs50(
3754
3799
  "div",
3755
3800
  {
3756
3801
  className: cx("pire-split", className),
@@ -3758,10 +3803,10 @@ function SplitPane({
3758
3803
  style: { ["--pire-split-list-w"]: width, ...style },
3759
3804
  ...rest,
3760
3805
  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 })
3806
+ /* @__PURE__ */ jsx59("section", { className: "pire-split-list", "aria-label": listLabel ?? msg.splitPaneList, children: list }),
3807
+ /* @__PURE__ */ jsxs50("section", { className: "pire-split-detail", "aria-label": detailLabel ?? msg.splitPaneDetail, children: [
3808
+ 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,
3809
+ detail ?? /* @__PURE__ */ jsx59("div", { className: "pire-split-empty", children: emptyDetail })
3765
3810
  ] })
3766
3811
  ]
3767
3812
  }
@@ -3769,7 +3814,7 @@ function SplitPane({
3769
3814
  }
3770
3815
 
3771
3816
  // src/components/patterns/ConfirmDialog.tsx
3772
- import { Fragment as Fragment4, jsx as jsx59, jsxs as jsxs50 } from "react/jsx-runtime";
3817
+ import { Fragment as Fragment5, jsx as jsx60, jsxs as jsxs51 } from "react/jsx-runtime";
3773
3818
  function ConfirmDialog({
3774
3819
  isOpen,
3775
3820
  title,
@@ -3783,7 +3828,7 @@ function ConfirmDialog({
3783
3828
  onConfirm,
3784
3829
  onCancel
3785
3830
  }) {
3786
- return /* @__PURE__ */ jsxs50(
3831
+ return /* @__PURE__ */ jsxs51(
3787
3832
  Dialog,
3788
3833
  {
3789
3834
  isOpen,
@@ -3793,12 +3838,12 @@ function ConfirmDialog({
3793
3838
  onClose: onCancel,
3794
3839
  isDismissable: !isBusy,
3795
3840
  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 })
3841
+ footer: /* @__PURE__ */ jsxs51(Fragment5, { children: [
3842
+ /* @__PURE__ */ jsx60(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
3843
+ /* @__PURE__ */ jsx60(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
3799
3844
  ] }),
3800
3845
  children: [
3801
- consequence ? /* @__PURE__ */ jsx59(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3846
+ consequence ? /* @__PURE__ */ jsx60(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
3802
3847
  children
3803
3848
  ]
3804
3849
  }
@@ -3806,7 +3851,7 @@ function ConfirmDialog({
3806
3851
  }
3807
3852
 
3808
3853
  // src/components/patterns/CommandPalette.tsx
3809
- import * as React25 from "react";
3854
+ import * as React26 from "react";
3810
3855
  import {
3811
3856
  Autocomplete,
3812
3857
  ModalOverlay as ModalOverlay2,
@@ -3819,7 +3864,7 @@ import {
3819
3864
  Header as Header2,
3820
3865
  useFilter
3821
3866
  } from "react-aria-components";
3822
- import { Fragment as Fragment5, jsx as jsx60, jsxs as jsxs51 } from "react/jsx-runtime";
3867
+ import { Fragment as Fragment6, jsx as jsx61, jsxs as jsxs52 } from "react/jsx-runtime";
3823
3868
  var RESULTS_SECTION_KEY = "__pire_results__";
3824
3869
  var searchableText = (item) => [item.label, item.description, item.keywords].filter(Boolean).join(" ");
3825
3870
  function CommandPalette({
@@ -3840,17 +3885,17 @@ function CommandPalette({
3840
3885
  style
3841
3886
  }) {
3842
3887
  const msg = usePireMessages();
3843
- const [query, setQuery] = React25.useState("");
3888
+ const [query, setQuery] = React26.useState("");
3844
3889
  const { contains } = useFilter({ sensitivity: "base" });
3845
- React25.useEffect(() => {
3890
+ React26.useEffect(() => {
3846
3891
  if (isOpen) setQuery("");
3847
3892
  }, [isOpen]);
3848
- const searchableById = React25.useMemo(() => {
3893
+ const searchableById = React26.useMemo(() => {
3849
3894
  const byId = /* @__PURE__ */ new Map();
3850
3895
  for (const group of groups) for (const item of group.items) byId.set(item.id, searchableText(item));
3851
3896
  return byId;
3852
3897
  }, [groups]);
3853
- const filter = React25.useCallback((textValue, inputValue, node) => {
3898
+ const filter = React26.useCallback((textValue, inputValue, node) => {
3854
3899
  if (node.parentKey === RESULTS_SECTION_KEY) return true;
3855
3900
  return contains(searchableById.get(String(node.key)) ?? textValue, inputValue);
3856
3901
  }, [contains, searchableById]);
@@ -3860,7 +3905,7 @@ function CommandPalette({
3860
3905
  };
3861
3906
  const sections = [...groups, ...resultsGroup ? [{ ...resultsGroup, id: RESULTS_SECTION_KEY }] : []];
3862
3907
  const status = isLoading ? loadingLabel ?? msg.commandPaletteLoading : emptyLabel ?? msg.commandPaletteEmpty;
3863
- return /* @__PURE__ */ jsx60(
3908
+ return /* @__PURE__ */ jsx61(
3864
3909
  ModalOverlay2,
3865
3910
  {
3866
3911
  className: "pire-cp-overlay",
@@ -3869,11 +3914,11 @@ function CommandPalette({
3869
3914
  onOpenChange: (open) => {
3870
3915
  if (!open) onOpenChange?.(false);
3871
3916
  },
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(
3917
+ 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: [
3918
+ /* @__PURE__ */ jsxs52(Autocomplete, { filter, inputValue: query, onInputChange: handleInputChange, children: [
3919
+ /* @__PURE__ */ jsxs52(SearchField, { className: "pire-cp-search", "aria-label": msg.commandPaletteSearchLabel, children: [
3920
+ /* @__PURE__ */ jsx61(Icon, { name: "search", size: 18, className: "pire-cp-search-icon" }),
3921
+ /* @__PURE__ */ jsx61(
3877
3922
  AriaInput5,
3878
3923
  {
3879
3924
  className: "pire-cp-input",
@@ -3882,16 +3927,16 @@ function CommandPalette({
3882
3927
  }
3883
3928
  )
3884
3929
  ] }),
3885
- isLoading ? /* @__PURE__ */ jsx60("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3886
- /* @__PURE__ */ jsx60(
3930
+ isLoading ? /* @__PURE__ */ jsx61("div", { className: "pire-cp-loading", role: "status", "aria-live": "polite", children: loadingLabel ?? msg.commandPaletteLoading }) : null,
3931
+ /* @__PURE__ */ jsx61(
3887
3932
  AriaMenu2,
3888
3933
  {
3889
3934
  className: "pire-cp-list",
3890
3935
  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(
3936
+ renderEmptyState: () => /* @__PURE__ */ jsx61("div", { className: "pire-cp-status", children: status }),
3937
+ children: sections.map((section) => /* @__PURE__ */ jsxs52(AriaMenuSection2, { id: section.id, className: "pire-cp-section", children: [
3938
+ section.label ? /* @__PURE__ */ jsx61(Header2, { className: "pire-cp-section-title", children: section.label }) : null,
3939
+ section.items.map((item) => /* @__PURE__ */ jsx61(
3895
3940
  MenuItem,
3896
3941
  {
3897
3942
  id: item.id,
@@ -3912,18 +3957,18 @@ function CommandPalette({
3912
3957
  // aria-hidden: the glyphs are a sighted affordance for discovering the keys. A screen
3913
3958
  // reader already announces the listbox semantics that make those keys work, so reading
3914
3959
  // "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" }),
3960
+ /* @__PURE__ */ jsx61("div", { className: "pire-cp-foot", "aria-hidden": "true", children: footer ?? /* @__PURE__ */ jsxs52(Fragment6, { children: [
3961
+ /* @__PURE__ */ jsxs52("span", { className: "pire-cp-hint", children: [
3962
+ /* @__PURE__ */ jsx61(Kbd, { children: "\u2191" }),
3963
+ /* @__PURE__ */ jsx61(Kbd, { children: "\u2193" }),
3919
3964
  msg.commandPaletteHintNavigate
3920
3965
  ] }),
3921
- /* @__PURE__ */ jsxs51("span", { className: "pire-cp-hint", children: [
3922
- /* @__PURE__ */ jsx60(Kbd, { children: "\u21B5" }),
3966
+ /* @__PURE__ */ jsxs52("span", { className: "pire-cp-hint", children: [
3967
+ /* @__PURE__ */ jsx61(Kbd, { children: "\u21B5" }),
3923
3968
  msg.commandPaletteHintSelect
3924
3969
  ] }),
3925
- /* @__PURE__ */ jsxs51("span", { className: "pire-cp-hint", children: [
3926
- /* @__PURE__ */ jsx60(Kbd, { children: "esc" }),
3970
+ /* @__PURE__ */ jsxs52("span", { className: "pire-cp-hint", children: [
3971
+ /* @__PURE__ */ jsx61(Kbd, { children: "esc" }),
3927
3972
  msg.commandPaletteHintClose
3928
3973
  ] })
3929
3974
  ] }) })
@@ -3933,9 +3978,9 @@ function CommandPalette({
3933
3978
  );
3934
3979
  }
3935
3980
  function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3936
- const handler = React25.useRef(onTrigger);
3981
+ const handler = React26.useRef(onTrigger);
3937
3982
  handler.current = onTrigger;
3938
- React25.useEffect(() => {
3983
+ React26.useEffect(() => {
3939
3984
  if (isDisabled) return;
3940
3985
  const onKeyDown = (event) => {
3941
3986
  if (!(event.metaKey || event.ctrlKey) || event.altKey) return;
@@ -3948,12 +3993,125 @@ function useCommandPaletteShortcut(onTrigger, { key = "k", isDisabled } = {}) {
3948
3993
  }, [key, isDisabled]);
3949
3994
  }
3950
3995
 
3996
+ // src/components/patterns/AppLauncher.tsx
3997
+ import * as React27 from "react";
3998
+ import {
3999
+ DialogTrigger,
4000
+ Button as AriaButton16,
4001
+ Popover as Popover8,
4002
+ Dialog as AriaDialog5,
4003
+ useFilter as useFilter2
4004
+ } from "react-aria-components";
4005
+ import { Fragment as Fragment7, jsx as jsx62, jsxs as jsxs53 } from "react/jsx-runtime";
4006
+ var searchableText2 = (item) => [item.label, item.description, item.keywords].filter(Boolean).join(" ");
4007
+ function AppLauncher({
4008
+ sections,
4009
+ onAction,
4010
+ value,
4011
+ title,
4012
+ meta,
4013
+ isSearchable = true,
4014
+ onSearchChange,
4015
+ isFilteredExternally,
4016
+ isLoading,
4017
+ emptyLabel,
4018
+ searchPlaceholder,
4019
+ "aria-label": ariaLabel,
4020
+ icon = "grid-2x2",
4021
+ className
4022
+ }) {
4023
+ const msg = usePireMessages();
4024
+ const [query, setQuery] = React27.useState("");
4025
+ const { contains } = useFilter2({ sensitivity: "base" });
4026
+ const handleSearch = (next) => {
4027
+ setQuery(next);
4028
+ onSearchChange?.(next);
4029
+ };
4030
+ const visible = React27.useMemo(() => {
4031
+ if (isFilteredExternally) return sections;
4032
+ const q = query.trim();
4033
+ if (!q) return sections;
4034
+ return sections.map((section) => ({ ...section, items: section.items.filter((i) => contains(searchableText2(i), q)) })).filter((section) => section.items.length > 0);
4035
+ }, [sections, query, isFilteredExternally, contains]);
4036
+ const isEmpty = !isLoading && visible.length === 0;
4037
+ const label = ariaLabel ?? msg.appLauncherLabel;
4038
+ return /* @__PURE__ */ jsxs53(DialogTrigger, { children: [
4039
+ /* @__PURE__ */ jsx62(AriaButton16, { className: "pire-launcher-trigger", "aria-label": label, children: /* @__PURE__ */ jsx62(Icon, { name: icon, size: 20 }) }),
4040
+ /* @__PURE__ */ jsx62(
4041
+ Popover8,
4042
+ {
4043
+ className: cx("pire-launcher-popover", className),
4044
+ placement: "bottom start",
4045
+ offset: 0,
4046
+ crossOffset: 0,
4047
+ containerPadding: 0,
4048
+ children: /* @__PURE__ */ jsx62(AriaDialog5, { className: "pire-launcher", "aria-label": label, children: ({ close }) => /* @__PURE__ */ jsxs53(Fragment7, { children: [
4049
+ /* @__PURE__ */ jsxs53("div", { className: "pire-launcher-head", children: [
4050
+ /* @__PURE__ */ jsx62("span", { className: "pire-launcher-title", children: title ?? msg.appLauncherTitle }),
4051
+ meta ? /* @__PURE__ */ jsx62("span", { className: "pire-launcher-meta", children: meta }) : null
4052
+ ] }),
4053
+ isSearchable ? (
4054
+ // autoFocus is right here specifically: the panel exists to be searched, and the
4055
+ // user just chose to open it, so taking the caret is what they asked for.
4056
+ /* @__PURE__ */ jsx62(
4057
+ Input,
4058
+ {
4059
+ "aria-label": msg.appLauncherSearch,
4060
+ icon: "search",
4061
+ type: "search",
4062
+ autoFocus: true,
4063
+ isClearable: true,
4064
+ value: query,
4065
+ onChange: handleSearch,
4066
+ placeholder: searchPlaceholder ?? msg.appLauncherSearch
4067
+ }
4068
+ )
4069
+ ) : null,
4070
+ isLoading ? /* @__PURE__ */ jsx62("div", { className: "pire-launcher-empty", role: "status", "aria-live": "polite", children: msg.appLauncherLoading }) : null,
4071
+ isEmpty ? /* @__PURE__ */ jsx62("div", { className: "pire-launcher-empty", children: emptyLabel ?? msg.appLauncherEmpty }) : null,
4072
+ visible.map((section, si) => (
4073
+ // Sections are positional zones with no record identity, so the heading is the key
4074
+ // where there is one. Same reasoning as ShellRail's groups.
4075
+ /* @__PURE__ */ jsxs53("div", { className: "pire-launcher-section", children: [
4076
+ section.label ? /* @__PURE__ */ jsx62("div", { className: "pire-eyebrow", children: section.label }) : null,
4077
+ /* @__PURE__ */ jsx62("div", { className: "pire-launcher-grid", "data-variant": section.variant ?? "tile", children: section.items.map((item) => {
4078
+ const isCurrent = item.id === value;
4079
+ const showsDescription = (section.variant ?? "tile") === "tile" && Boolean(item.description);
4080
+ return /* @__PURE__ */ jsxs53(
4081
+ AriaButton16,
4082
+ {
4083
+ className: "pire-launcher-item",
4084
+ "data-selected": isCurrent ? "true" : void 0,
4085
+ "aria-current": isCurrent ? "true" : void 0,
4086
+ onPress: () => {
4087
+ close();
4088
+ onAction?.(item.id);
4089
+ },
4090
+ children: [
4091
+ 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,
4092
+ /* @__PURE__ */ jsxs53("span", { className: "pire-launcher-item-text", children: [
4093
+ /* @__PURE__ */ jsx62("span", { className: "pire-launcher-item-label", children: item.label }),
4094
+ showsDescription ? /* @__PURE__ */ jsx62("span", { className: "pire-launcher-item-desc", children: item.description }) : null
4095
+ ] })
4096
+ ]
4097
+ },
4098
+ item.id
4099
+ );
4100
+ }) })
4101
+ ] }, section.label ?? section.items[0]?.id ?? si)
4102
+ ))
4103
+ ] }) })
4104
+ }
4105
+ )
4106
+ ] });
4107
+ }
4108
+
3951
4109
  // 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";
4110
+ import { ModalOverlay as ModalOverlay3, Modal as Modal3, Dialog as AriaDialog6, Heading as Heading5 } from "react-aria-components";
4111
+ import { jsx as jsx63, jsxs as jsxs54 } from "react/jsx-runtime";
3954
4112
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
3955
4113
  const msg = usePireMessages();
3956
- return /* @__PURE__ */ jsx61(
4114
+ return /* @__PURE__ */ jsx63(
3957
4115
  ModalOverlay3,
3958
4116
  {
3959
4117
  className: "pire-sidepanel-overlay",
@@ -3962,36 +4120,36 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
3962
4120
  onOpenChange: (o) => {
3963
4121
  if (!o) onClose?.();
3964
4122
  },
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
4123
+ children: /* @__PURE__ */ jsx63(Modal3, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs54(AriaDialog6, { className: "pire-dialog", style: { height: "100%" }, children: [
4124
+ /* @__PURE__ */ jsxs54("header", { className: "pire-dialog-head", children: [
4125
+ /* @__PURE__ */ jsxs54("div", { style: { flex: 1, minWidth: 0 }, children: [
4126
+ /* @__PURE__ */ jsx63(Heading5, { slot: "title", className: "pire-dialog-title", children: title }),
4127
+ subtitle ? /* @__PURE__ */ jsx63("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
3970
4128
  ] }),
3971
- /* @__PURE__ */ jsx61(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
4129
+ /* @__PURE__ */ jsx63(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
3972
4130
  ] }),
3973
- /* @__PURE__ */ jsx61("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
3974
- footer ? /* @__PURE__ */ jsx61("footer", { className: "pire-dialog-foot", children: footer }) : null
4131
+ /* @__PURE__ */ jsx63("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
4132
+ footer ? /* @__PURE__ */ jsx63("footer", { className: "pire-dialog-foot", children: footer }) : null
3975
4133
  ] }) })
3976
4134
  }
3977
4135
  );
3978
4136
  }
3979
4137
 
3980
4138
  // src/components/patterns/EmptyState.tsx
3981
- import { jsx as jsx62, jsxs as jsxs53 } from "react/jsx-runtime";
4139
+ import { jsx as jsx64, jsxs as jsxs55 } from "react/jsx-runtime";
3982
4140
  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,
4141
+ return /* @__PURE__ */ jsxs55("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
4142
+ /* @__PURE__ */ jsx64(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
4143
+ title ? /* @__PURE__ */ jsx64("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
4144
+ children ? /* @__PURE__ */ jsx64("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
3987
4145
  action
3988
4146
  ] });
3989
4147
  }
3990
4148
 
3991
4149
  // src/components/patterns/FileDropZone.tsx
3992
- import * as React26 from "react";
4150
+ import * as React28 from "react";
3993
4151
  import { DropZone, FileTrigger as FileTrigger2, isFileDropItem } from "react-aria-components";
3994
- import { jsx as jsx63, jsxs as jsxs54 } from "react/jsx-runtime";
4152
+ import { jsx as jsx65, jsxs as jsxs56 } from "react/jsx-runtime";
3995
4153
  var isImage2 = (file) => file.type.startsWith("image/");
3996
4154
  function FileDropZone({
3997
4155
  label,
@@ -4019,10 +4177,10 @@ function FileDropZone({
4019
4177
  ...rest
4020
4178
  }) {
4021
4179
  const msg = usePireMessages();
4022
- const [uncontrolled, setUncontrolled] = React26.useState(defaultValue ?? []);
4180
+ const [uncontrolled, setUncontrolled] = React28.useState(defaultValue ?? []);
4023
4181
  const files = value ?? uncontrolled;
4024
- const created = React26.useRef([]);
4025
- React26.useEffect(() => () => {
4182
+ const created = React28.useRef([]);
4183
+ React28.useEffect(() => () => {
4026
4184
  for (const url of created.current) URL.revokeObjectURL(url);
4027
4185
  }, []);
4028
4186
  const commit = (next) => {
@@ -4042,12 +4200,12 @@ function FileDropZone({
4042
4200
  commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
4043
4201
  };
4044
4202
  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: [
4203
+ return /* @__PURE__ */ jsxs56("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), ...rest, children: [
4204
+ label ? /* @__PURE__ */ jsxs56("span", { className: "pire-field-label", children: [
4047
4205
  label,
4048
- isRequired ? /* @__PURE__ */ jsx63("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
4206
+ isRequired ? /* @__PURE__ */ jsx65("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
4049
4207
  ] }) : null,
4050
- /* @__PURE__ */ jsxs54(
4208
+ /* @__PURE__ */ jsxs56(
4051
4209
  DropZone,
4052
4210
  {
4053
4211
  className: "pire-dropzone",
@@ -4061,25 +4219,25 @@ function FileDropZone({
4061
4219
  accept(dropped);
4062
4220
  },
4063
4221
  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(
4222
+ /* @__PURE__ */ jsx65(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
4223
+ /* @__PURE__ */ jsx65("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
4224
+ /* @__PURE__ */ jsx65(
4067
4225
  FileTrigger2,
4068
4226
  {
4069
4227
  acceptedFileTypes,
4070
4228
  allowsMultiple,
4071
4229
  onSelect: (list) => accept(list ? [...list] : []),
4072
- children: /* @__PURE__ */ jsx63(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
4230
+ children: /* @__PURE__ */ jsx65(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
4073
4231
  }
4074
4232
  )
4075
4233
  ]
4076
4234
  }
4077
4235
  ),
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(
4236
+ files.length ? /* @__PURE__ */ jsx65("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs56("li", { className: "pire-fileupload-item", children: [
4237
+ previewUrl ? /* @__PURE__ */ jsx65("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx65(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
4238
+ /* @__PURE__ */ jsx65("span", { className: "pire-fileupload-name", children: file.name }),
4239
+ /* @__PURE__ */ jsx65("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
4240
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx65(
4083
4241
  IconButton,
4084
4242
  {
4085
4243
  icon: "x",
@@ -4089,16 +4247,17 @@ function FileDropZone({
4089
4247
  }
4090
4248
  )
4091
4249
  ] }, `${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
4250
+ uploadProgress != null ? /* @__PURE__ */ jsx65(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
4251
+ description ? /* @__PURE__ */ jsx65("span", { className: "pire-field-hint", children: description }) : null,
4252
+ isInvalid && errorMessage ? /* @__PURE__ */ jsx65("span", { className: "pire-field-error", children: errorMessage }) : null
4095
4253
  ] });
4096
4254
  }
4097
4255
 
4098
4256
  // src/index.ts
4099
- import { DialogTrigger, MenuTrigger as MenuTrigger3, SubmenuTrigger, Popover as Popover8, RouterProvider, I18nProvider } from "react-aria-components";
4257
+ import { DialogTrigger as DialogTrigger2, MenuTrigger as MenuTrigger3, SubmenuTrigger, Popover as Popover9, RouterProvider, I18nProvider } from "react-aria-components";
4100
4258
  import { Focusable as Focusable2 } from "react-aria-components";
4101
4259
  export {
4260
+ AppLauncher,
4102
4261
  Avatar,
4103
4262
  Badge,
4104
4263
  BarChart,
@@ -4118,7 +4277,7 @@ export {
4118
4277
  DialogBody,
4119
4278
  DialogDescription,
4120
4279
  DialogTitle,
4121
- DialogTrigger,
4280
+ DialogTrigger2 as DialogTrigger,
4122
4281
  DonutChart,
4123
4282
  EmptyState,
4124
4283
  FileDropZone,
@@ -4151,7 +4310,7 @@ export {
4151
4310
  PageHeader,
4152
4311
  Pagination,
4153
4312
  PireIntlProvider,
4154
- Popover8 as Popover,
4313
+ Popover9 as Popover,
4155
4314
  ProgressBar,
4156
4315
  Radio,
4157
4316
  RadioGroup,
@@ -4162,6 +4321,7 @@ export {
4162
4321
  SelectionBar,
4163
4322
  Separator,
4164
4323
  ShellBar,
4324
+ ShellRail,
4165
4325
  SideNav,
4166
4326
  SidePanel,
4167
4327
  Skeleton,