@orianatech/pire 0.6.0 → 0.8.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
@@ -252,9 +252,22 @@ function Tooltip({ label, placement = "top", delay = 500, children }) {
252
252
  }
253
253
 
254
254
  // src/components/core/IconButton.tsx
255
- import { jsx as jsx4 } from "react/jsx-runtime";
256
- var IconButton = React2.forwardRef(function IconButton2({ icon, label, size = "md", variant = "tertiary", selected, hideTooltip, className, ...rest }, ref) {
257
- const button = /* @__PURE__ */ jsx4(
255
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
256
+ var IconButton = React2.forwardRef(function IconButton2({
257
+ icon,
258
+ label,
259
+ size = "md",
260
+ variant = "tertiary",
261
+ selected,
262
+ hideTooltip,
263
+ count,
264
+ countMax = 9,
265
+ countVariant = "number",
266
+ className,
267
+ ...rest
268
+ }, ref) {
269
+ const showsCount = count != null && count > 0;
270
+ const button = /* @__PURE__ */ jsxs3(
258
271
  AriaButton2,
259
272
  {
260
273
  ref,
@@ -264,15 +277,19 @@ var IconButton = React2.forwardRef(function IconButton2({ icon, label, size = "m
264
277
  "data-size": size,
265
278
  "data-variant": variant,
266
279
  "data-selected": selected ? "true" : void 0,
280
+ "data-has-count": showsCount ? "true" : void 0,
267
281
  ...rest,
268
- children: /* @__PURE__ */ jsx4(Icon, { name: icon, size: size === "lg" ? 20 : 16 })
282
+ children: [
283
+ /* @__PURE__ */ jsx4(Icon, { name: icon, size: size === "lg" ? 20 : 16 }),
284
+ showsCount ? /* @__PURE__ */ jsx4("span", { className: "pire-iconbtn-count", "data-variant": countVariant, "aria-hidden": "true", children: countVariant === "number" ? count > countMax ? `${countMax}+` : count : null }) : null
285
+ ]
269
286
  }
270
287
  );
271
288
  return hideTooltip ? button : /* @__PURE__ */ jsx4(Tooltip, { label, children: button });
272
289
  });
273
290
 
274
291
  // src/components/core/Badge.tsx
275
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
292
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
276
293
  var STATUS_ICON = {
277
294
  positive: "check-circle-2",
278
295
  critical: "alert-triangle",
@@ -281,7 +298,7 @@ var STATUS_ICON = {
281
298
  neutral: "circle"
282
299
  };
283
300
  function Badge({ children, status = "neutral", showIcon = true, className, ...rest }) {
284
- return /* @__PURE__ */ jsxs3("span", { className: cx("pire-badge", className), "data-status": status, ...rest, children: [
301
+ return /* @__PURE__ */ jsxs4("span", { className: cx("pire-badge", className), "data-status": status, ...rest, children: [
285
302
  showIcon ? /* @__PURE__ */ jsx5(Icon, { name: STATUS_ICON[status], size: 12 }) : null,
286
303
  children
287
304
  ] });
@@ -289,9 +306,9 @@ function Badge({ children, status = "neutral", showIcon = true, className, ...re
289
306
 
290
307
  // src/components/core/Tag.tsx
291
308
  import { Button as AriaButton3 } from "react-aria-components";
292
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
309
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
293
310
  function Tag({ children, onRemove, isDisabled, className, ...rest }) {
294
- return /* @__PURE__ */ jsxs4("span", { className: cx("pire-tag", className), "data-disabled": isDisabled ? "true" : void 0, ...rest, children: [
311
+ return /* @__PURE__ */ jsxs5("span", { className: cx("pire-tag", className), "data-disabled": isDisabled ? "true" : void 0, ...rest, children: [
295
312
  children,
296
313
  onRemove ? /* @__PURE__ */ jsx6(
297
314
  AriaButton3,
@@ -307,12 +324,12 @@ function Tag({ children, onRemove, isDisabled, className, ...rest }) {
307
324
  }
308
325
 
309
326
  // src/components/core/Card.tsx
310
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
327
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
311
328
  function Card({ title, subtitle, icon, actions, footer, interactive, children, className, ...rest }) {
312
- return /* @__PURE__ */ jsxs5("section", { className: cx("pire-card", className), "data-interactive": interactive ? "true" : void 0, ...rest, children: [
313
- title || actions ? /* @__PURE__ */ jsxs5("header", { className: "pire-card-head", children: [
329
+ return /* @__PURE__ */ jsxs6("section", { className: cx("pire-card", className), "data-interactive": interactive ? "true" : void 0, ...rest, children: [
330
+ title || actions ? /* @__PURE__ */ jsxs6("header", { className: "pire-card-head", children: [
314
331
  icon ? /* @__PURE__ */ jsx7(Icon, { name: icon, size: 20, style: { color: "var(--text-secondary)" } }) : null,
315
- /* @__PURE__ */ jsxs5("div", { style: { flex: 1, minWidth: 0 }, children: [
332
+ /* @__PURE__ */ jsxs6("div", { style: { flex: 1, minWidth: 0 }, children: [
316
333
  /* @__PURE__ */ jsx7("h3", { className: "pire-card-title", children: title }),
317
334
  subtitle ? /* @__PURE__ */ jsx7("p", { className: "pire-card-sub", style: { margin: 0 }, children: subtitle }) : null
318
335
  ] }),
@@ -343,7 +360,7 @@ function Avatar({ name, size = "md", src, className, ...rest }) {
343
360
  // src/components/core/SegmentedControl.tsx
344
361
  import * as React4 from "react";
345
362
  import { ToggleButtonGroup, ToggleButton } from "react-aria-components";
346
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
363
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
347
364
  function SegmentedControl({
348
365
  options,
349
366
  value,
@@ -370,7 +387,7 @@ function SegmentedControl({
370
387
  const first = [...keys][0];
371
388
  if (first != null) onChange?.(String(first));
372
389
  },
373
- children: options.map((option) => /* @__PURE__ */ jsxs6(
390
+ children: options.map((option) => /* @__PURE__ */ jsxs7(
374
391
  ToggleButton,
375
392
  {
376
393
  id: option.id,
@@ -453,9 +470,9 @@ function Heading({
453
470
 
454
471
  // src/components/core/Link.tsx
455
472
  import { Link as AriaLink } from "react-aria-components";
456
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
473
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
457
474
  function Link({ children, size, isExternal, className, rel, ...rest }) {
458
- return /* @__PURE__ */ jsxs7(
475
+ return /* @__PURE__ */ jsxs8(
459
476
  AriaLink,
460
477
  {
461
478
  className: cx("pire-link", className),
@@ -495,15 +512,15 @@ function Separator({
495
512
  }
496
513
 
497
514
  // src/components/forms/FormField.tsx
498
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
515
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
499
516
  function FormField({ label, htmlFor, isRequired, hint, error, layout = "stacked", children, className, ...rest }) {
500
- return /* @__PURE__ */ jsxs8("div", { className: cx("pire-field", className), "data-layout": layout, ...rest, children: [
501
- /* @__PURE__ */ jsxs8("label", { className: "pire-field-label", htmlFor, children: [
517
+ return /* @__PURE__ */ jsxs9("div", { className: cx("pire-field", className), "data-layout": layout, ...rest, children: [
518
+ /* @__PURE__ */ jsxs9("label", { className: "pire-field-label", htmlFor, children: [
502
519
  label,
503
520
  isRequired ? /* @__PURE__ */ jsx14("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
504
521
  ] }),
505
522
  children,
506
- error ? /* @__PURE__ */ jsxs8("span", { className: "pire-field-error", role: "alert", children: [
523
+ error ? /* @__PURE__ */ jsxs9("span", { className: "pire-field-error", role: "alert", children: [
507
524
  /* @__PURE__ */ jsx14(Icon, { name: "alert-circle", size: 12 }),
508
525
  error
509
526
  ] }) : hint ? /* @__PURE__ */ jsx14("span", { className: "pire-field-hint", children: hint }) : null
@@ -512,7 +529,7 @@ function FormField({ label, htmlFor, isRequired, hint, error, layout = "stacked"
512
529
 
513
530
  // src/components/forms/Input.tsx
514
531
  import { TextField, Label, Input as AriaInput, Group, Text as Text2, FieldError } from "react-aria-components";
515
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
532
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
516
533
  function Input({
517
534
  label,
518
535
  icon,
@@ -528,7 +545,7 @@ function Input({
528
545
  onChange,
529
546
  ...rest
530
547
  }) {
531
- return /* @__PURE__ */ jsxs9(
548
+ return /* @__PURE__ */ jsxs10(
532
549
  TextField,
533
550
  {
534
551
  className: cx("pire-field", className),
@@ -537,11 +554,11 @@ function Input({
537
554
  validationBehavior: "aria",
538
555
  ...rest,
539
556
  children: [
540
- label ? /* @__PURE__ */ jsxs9(Label, { className: "pire-field-label", children: [
557
+ label ? /* @__PURE__ */ jsxs10(Label, { className: "pire-field-label", children: [
541
558
  label,
542
559
  rest.isRequired ? /* @__PURE__ */ jsx15("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
543
560
  ] }) : null,
544
- /* @__PURE__ */ jsxs9(
561
+ /* @__PURE__ */ jsxs10(
545
562
  Group,
546
563
  {
547
564
  className: "pire-control",
@@ -566,7 +583,7 @@ function Input({
566
583
  // src/components/forms/TextArea.tsx
567
584
  import * as React5 from "react";
568
585
  import { TextField as TextField2, Label as Label2, TextArea as AriaTextArea, Group as Group2, Text as Text3, FieldError as FieldError2 } from "react-aria-components";
569
- import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
586
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
570
587
  var useIsomorphicLayoutEffect = typeof document === "undefined" ? React5.useEffect : React5.useLayoutEffect;
571
588
  function TextArea({
572
589
  label,
@@ -607,7 +624,7 @@ function TextArea({
607
624
  }
608
625
  grow();
609
626
  }, [autoGrow, grow, rest.value]);
610
- return /* @__PURE__ */ jsxs10(
627
+ return /* @__PURE__ */ jsxs11(
611
628
  TextField2,
612
629
  {
613
630
  className: cx("pire-field", className),
@@ -616,7 +633,7 @@ function TextArea({
616
633
  validationBehavior: "aria",
617
634
  ...rest,
618
635
  children: [
619
- label ? /* @__PURE__ */ jsxs10(Label2, { className: "pire-field-label", children: [
636
+ label ? /* @__PURE__ */ jsxs11(Label2, { className: "pire-field-label", children: [
620
637
  label,
621
638
  rest.isRequired ? /* @__PURE__ */ jsx16("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
622
639
  ] }) : null,
@@ -660,7 +677,7 @@ import {
660
677
  Text as Text4,
661
678
  FieldError as FieldError3
662
679
  } from "react-aria-components";
663
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
680
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
664
681
  var norm = (o) => typeof o === "string" ? { value: o, label: o, isDisabled: false } : o;
665
682
  function Select({
666
683
  label,
@@ -678,7 +695,7 @@ function Select({
678
695
  ...rest
679
696
  }) {
680
697
  const items = options.map(norm);
681
- return /* @__PURE__ */ jsxs11(
698
+ return /* @__PURE__ */ jsxs12(
682
699
  AriaSelect,
683
700
  {
684
701
  className: cx("pire-field", className),
@@ -690,11 +707,11 @@ function Select({
690
707
  validationBehavior: "aria",
691
708
  ...rest,
692
709
  children: [
693
- label ? /* @__PURE__ */ jsxs11(Label3, { className: "pire-field-label", children: [
710
+ label ? /* @__PURE__ */ jsxs12(Label3, { className: "pire-field-label", children: [
694
711
  label,
695
712
  rest.isRequired ? /* @__PURE__ */ jsx17("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
696
713
  ] }) : null,
697
- /* @__PURE__ */ jsxs11(
714
+ /* @__PURE__ */ jsxs12(
698
715
  AriaButton4,
699
716
  {
700
717
  className: "pire-control",
@@ -717,11 +734,11 @@ function Select({
717
734
 
718
735
  // src/components/forms/Checkbox.tsx
719
736
  import { Checkbox as AriaCheckbox } from "react-aria-components";
720
- import { Fragment, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
737
+ import { Fragment, jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
721
738
  function Checkbox({ label, hint, children, className, ...rest }) {
722
- return /* @__PURE__ */ jsx18(AriaCheckbox, { className: cx("pire-choice", className), ...rest, children: ({ isSelected, isIndeterminate }) => /* @__PURE__ */ jsxs12(Fragment, { children: [
739
+ return /* @__PURE__ */ jsx18(AriaCheckbox, { className: cx("pire-choice", className), ...rest, children: ({ isSelected, isIndeterminate }) => /* @__PURE__ */ jsxs13(Fragment, { children: [
723
740
  /* @__PURE__ */ jsx18("span", { className: "pire-choice-box", "aria-hidden": "true", children: isIndeterminate ? /* @__PURE__ */ jsx18(Icon, { name: "minus", size: 12 }) : isSelected ? /* @__PURE__ */ jsx18(Icon, { name: "check", size: 12 }) : null }),
724
- /* @__PURE__ */ jsxs12("span", { children: [
741
+ /* @__PURE__ */ jsxs13("span", { children: [
725
742
  label ?? children,
726
743
  hint ? /* @__PURE__ */ jsx18("span", { className: "pire-choice-hint", children: hint }) : null
727
744
  ] })
@@ -736,9 +753,9 @@ import {
736
753
  Text as Text5,
737
754
  FieldError as FieldError4
738
755
  } from "react-aria-components";
739
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
756
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
740
757
  function RadioGroup({ label, description, errorMessage, children, className, ...rest }) {
741
- return /* @__PURE__ */ jsxs13(AriaRadioGroup, { className: cx("pire-field", className), validationBehavior: "aria", ...rest, children: [
758
+ return /* @__PURE__ */ jsxs14(AriaRadioGroup, { className: cx("pire-field", className), validationBehavior: "aria", ...rest, children: [
742
759
  label ? /* @__PURE__ */ jsx19(Label4, { className: "pire-field-label", children: label }) : null,
743
760
  /* @__PURE__ */ jsx19("div", { className: "pire-radiogroup", children }),
744
761
  description ? /* @__PURE__ */ jsx19(Text5, { slot: "description", className: "pire-field-hint", children: description }) : null,
@@ -746,9 +763,9 @@ function RadioGroup({ label, description, errorMessage, children, className, ...
746
763
  ] });
747
764
  }
748
765
  function Radio({ label, hint, children, className, ...rest }) {
749
- return /* @__PURE__ */ jsxs13(AriaRadio, { className: cx("pire-choice", className), ...rest, children: [
766
+ return /* @__PURE__ */ jsxs14(AriaRadio, { className: cx("pire-choice", className), ...rest, children: [
750
767
  /* @__PURE__ */ jsx19("span", { className: "pire-choice-box", "data-radio": "true", "aria-hidden": "true" }),
751
- /* @__PURE__ */ jsxs13("span", { children: [
768
+ /* @__PURE__ */ jsxs14("span", { children: [
752
769
  label ?? children,
753
770
  hint ? /* @__PURE__ */ jsx19("span", { className: "pire-choice-hint", children: hint }) : null
754
771
  ] })
@@ -757,9 +774,9 @@ function Radio({ label, hint, children, className, ...rest }) {
757
774
 
758
775
  // src/components/forms/Switch.tsx
759
776
  import { Switch as AriaSwitch } from "react-aria-components";
760
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
777
+ import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
761
778
  function Switch({ label, children, className, ...rest }) {
762
- return /* @__PURE__ */ jsxs14(AriaSwitch, { className: cx("pire-choice", className), ...rest, children: [
779
+ return /* @__PURE__ */ jsxs15(AriaSwitch, { className: cx("pire-choice", className), ...rest, children: [
763
780
  /* @__PURE__ */ jsx20("span", { className: "pire-switch-track", "aria-hidden": "true", children: /* @__PURE__ */ jsx20("span", { className: "pire-switch-thumb" }) }),
764
781
  /* @__PURE__ */ jsx20("span", { children: label ?? children })
765
782
  ] });
@@ -789,12 +806,14 @@ var enMessages = {
789
806
  filterBarClearAll: "Clear all",
790
807
  dataTableSelectAll: "Select all rows",
791
808
  dataTableSelectRow: "Select row",
809
+ dataTableLoading: "Loading records",
792
810
  dialogClose: "Close",
793
811
  sidePanelClose: "Close panel",
794
812
  inlineMessageDismiss: "Dismiss message",
795
813
  toastDismiss: "Dismiss",
796
814
  toastRegionLabel: "Notifications",
797
815
  comboBoxShowSuggestions: "Show suggestions",
816
+ comboBoxLoading: "Searching\u2026",
798
817
  datePickerOpenCalendar: "Open calendar",
799
818
  datePickerPreviousMonth: "Previous month",
800
819
  datePickerNextMonth: "Next month",
@@ -819,12 +838,14 @@ var esMessages = {
819
838
  filterBarClearAll: "Limpiar todo",
820
839
  dataTableSelectAll: "Seleccionar todas las filas",
821
840
  dataTableSelectRow: "Seleccionar fila",
841
+ dataTableLoading: "Cargando registros",
822
842
  dialogClose: "Cerrar",
823
843
  sidePanelClose: "Cerrar panel",
824
844
  inlineMessageDismiss: "Descartar mensaje",
825
845
  toastDismiss: "Descartar",
826
846
  toastRegionLabel: "Notificaciones",
827
847
  comboBoxShowSuggestions: "Mostrar sugerencias",
848
+ comboBoxLoading: "Buscando\u2026",
828
849
  datePickerOpenCalendar: "Abrir calendario",
829
850
  datePickerPreviousMonth: "Mes anterior",
830
851
  datePickerNextMonth: "Mes siguiente",
@@ -863,7 +884,7 @@ function useMessage(key, override) {
863
884
  }
864
885
 
865
886
  // src/components/forms/ComboBox.tsx
866
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
887
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
867
888
  var norm2 = (o) => typeof o === "string" ? { value: o, label: o } : o;
868
889
  function ComboBox({
869
890
  label,
@@ -876,31 +897,42 @@ function ComboBox({
876
897
  errorMessage,
877
898
  size = "md",
878
899
  fullWidth = true,
900
+ isFilteredExternally,
901
+ isLoading,
902
+ loadingLabel,
903
+ emptyLabel,
904
+ onLoadMore,
879
905
  className,
880
906
  style,
881
907
  ...rest
882
908
  }) {
883
909
  const msg = usePireMessages();
884
910
  const items = options.map(norm2);
885
- return /* @__PURE__ */ jsxs15(
911
+ const collection = isFilteredExternally ? { items } : { defaultItems: items };
912
+ const showsStatus = isLoading || isFilteredExternally && items.length === 0 && emptyLabel != null;
913
+ return /* @__PURE__ */ jsxs16(
886
914
  AriaComboBox,
887
915
  {
888
916
  className: cx("pire-field", className),
889
917
  style,
890
918
  selectedKey: value,
891
919
  defaultSelectedKey: defaultValue,
892
- onSelectionChange: (k) => onChange?.(k == null ? null : String(k)),
920
+ onSelectionChange: (k) => {
921
+ if (isLoading) return;
922
+ onChange?.(k == null ? null : String(k));
923
+ },
893
924
  onInputChange,
894
- defaultItems: items,
925
+ ...collection,
926
+ allowsEmptyCollection: isFilteredExternally || isLoading,
895
927
  menuTrigger: "input",
896
928
  validationBehavior: "aria",
897
929
  ...rest,
898
930
  children: [
899
- label ? /* @__PURE__ */ jsxs15(Label5, { className: "pire-field-label", children: [
931
+ label ? /* @__PURE__ */ jsxs16(Label5, { className: "pire-field-label", children: [
900
932
  label,
901
933
  rest.isRequired ? /* @__PURE__ */ jsx22("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
902
934
  ] }) : null,
903
- /* @__PURE__ */ jsxs15(
935
+ /* @__PURE__ */ jsxs16(
904
936
  Group3,
905
937
  {
906
938
  className: "pire-control",
@@ -916,10 +948,21 @@ function ComboBox({
916
948
  ),
917
949
  description ? /* @__PURE__ */ jsx22(Text6, { slot: "description", className: "pire-field-hint", children: description }) : null,
918
950
  /* @__PURE__ */ jsx22(FieldError5, { className: "pire-field-error", children: errorMessage }),
919
- /* @__PURE__ */ jsx22(Popover2, { className: "pire-popover", children: /* @__PURE__ */ jsx22(ListBox2, { className: "pire-listbox", children: (item) => /* @__PURE__ */ jsxs15(ListBoxItem2, { className: "pire-option", id: item.value, textValue: item.label, isDisabled: item.isDisabled, children: [
920
- /* @__PURE__ */ jsx22("span", { style: { flex: 1 }, children: item.label }),
921
- item.secondary ? /* @__PURE__ */ jsx22("span", { style: { font: "var(--type-code)", color: "var(--text-tertiary)" }, children: item.secondary }) : null
922
- ] }) }) })
951
+ /* @__PURE__ */ jsx22(Popover2, { className: "pire-popover", children: /* @__PURE__ */ jsx22(
952
+ ListBox2,
953
+ {
954
+ className: "pire-listbox",
955
+ onScroll: onLoadMore ? (e) => {
956
+ const el = e.currentTarget;
957
+ if (el.scrollHeight - el.scrollTop - el.clientHeight < 48) onLoadMore();
958
+ } : void 0,
959
+ renderEmptyState: showsStatus ? () => /* @__PURE__ */ jsx22("div", { className: "pire-listbox-status", role: "status", "aria-live": "polite", children: isLoading ? loadingLabel ?? msg.comboBoxLoading : emptyLabel }) : void 0,
960
+ children: (item) => /* @__PURE__ */ jsxs16(ListBoxItem2, { className: "pire-option", id: item.value, textValue: item.label, isDisabled: item.isDisabled, children: [
961
+ /* @__PURE__ */ jsx22("span", { className: "pire-option-label", children: item.label }),
962
+ item.secondary ? /* @__PURE__ */ jsx22("span", { className: "pire-option-secondary", children: item.secondary }) : null
963
+ ] })
964
+ }
965
+ ) })
923
966
  ]
924
967
  }
925
968
  );
@@ -941,7 +984,7 @@ import {
941
984
  FieldError as FieldError6,
942
985
  VisuallyHidden
943
986
  } from "react-aria-components";
944
- import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
987
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
945
988
  var norm3 = (o) => typeof o === "string" ? { value: o, label: o } : o;
946
989
  function MultiComboBox({
947
990
  label,
@@ -954,6 +997,11 @@ function MultiComboBox({
954
997
  errorMessage,
955
998
  allowsCustomValue,
956
999
  size = "md",
1000
+ isFilteredExternally,
1001
+ isLoading,
1002
+ loadingLabel,
1003
+ emptyLabel,
1004
+ onLoadMore,
957
1005
  fullWidth = true,
958
1006
  className,
959
1007
  style,
@@ -961,6 +1009,8 @@ function MultiComboBox({
961
1009
  }) {
962
1010
  const msg = usePireMessages();
963
1011
  const items = React7.useMemo(() => options.map(norm3), [options]);
1012
+ const collection = isFilteredExternally ? { items } : { defaultItems: items };
1013
+ const showsStatus = isLoading || isFilteredExternally && items.length === 0 && emptyLabel != null;
964
1014
  const [uncontrolled, setUncontrolled] = React7.useState(defaultValue ?? []);
965
1015
  const [announcement, setAnnouncement] = React7.useState("");
966
1016
  const inputRef = React7.useRef(null);
@@ -999,25 +1049,28 @@ function MultiComboBox({
999
1049
  e.stopPropagation();
1000
1050
  if (!values.includes(next)) commit([...values, next]);
1001
1051
  };
1002
- return /* @__PURE__ */ jsxs16(
1052
+ return /* @__PURE__ */ jsxs17(
1003
1053
  AriaComboBox2,
1004
1054
  {
1005
1055
  className: cx("pire-field", className),
1006
1056
  style,
1007
1057
  selectionMode: "multiple",
1008
1058
  value: values,
1009
- onChange: (keys) => commit(keys.map(String)),
1059
+ onChange: (keys) => {
1060
+ if (!isLoading) commit(keys.map(String));
1061
+ },
1010
1062
  onInputChange,
1011
- defaultItems: items,
1063
+ ...collection,
1064
+ allowsEmptyCollection: isFilteredExternally || isLoading,
1012
1065
  menuTrigger: "input",
1013
1066
  validationBehavior: "aria",
1014
1067
  ...rest,
1015
1068
  children: [
1016
- label ? /* @__PURE__ */ jsxs16(Label6, { className: "pire-field-label", children: [
1069
+ label ? /* @__PURE__ */ jsxs17(Label6, { className: "pire-field-label", children: [
1017
1070
  label,
1018
1071
  rest.isRequired ? /* @__PURE__ */ jsx23("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
1019
1072
  ] }) : null,
1020
- /* @__PURE__ */ jsxs16(
1073
+ /* @__PURE__ */ jsxs17(
1021
1074
  Group4,
1022
1075
  {
1023
1076
  className: "pire-control",
@@ -1028,7 +1081,7 @@ function MultiComboBox({
1028
1081
  "data-readonly": rest.isReadOnly ? "true" : void 0,
1029
1082
  children: [
1030
1083
  /* @__PURE__ */ jsx23(Icon, { name: "search", size: 16, className: "pire-leading-icon" }),
1031
- /* @__PURE__ */ jsxs16("div", { className: "pire-chipfield", children: [
1084
+ /* @__PURE__ */ jsxs17("div", { className: "pire-chipfield", children: [
1032
1085
  /* @__PURE__ */ jsx23(ButtonContext.Provider, { value: null, children: values.map((v) => (
1033
1086
  /* Disabled follows the field, not `isEditable`: a read-only field's chips are
1034
1087
  real, current values and should read as such — they simply lose the × . */
@@ -1051,10 +1104,21 @@ function MultiComboBox({
1051
1104
  /* @__PURE__ */ jsx23(VisuallyHidden, { children: /* @__PURE__ */ jsx23("span", { "aria-live": "polite", children: announcement }) }),
1052
1105
  description ? /* @__PURE__ */ jsx23(Text7, { slot: "description", className: "pire-field-hint", children: description }) : null,
1053
1106
  /* @__PURE__ */ jsx23(FieldError6, { className: "pire-field-error", children: errorMessage }),
1054
- /* @__PURE__ */ jsx23(Popover3, { className: "pire-popover", children: /* @__PURE__ */ jsx23(ListBox3, { className: "pire-listbox", children: (item) => /* @__PURE__ */ jsxs16(ListBoxItem3, { className: "pire-option", id: item.value, textValue: item.label, isDisabled: item.isDisabled, children: [
1055
- /* @__PURE__ */ jsx23("span", { style: { flex: 1 }, children: item.label }),
1056
- item.secondary ? /* @__PURE__ */ jsx23("span", { style: { font: "var(--type-code)", color: "var(--text-tertiary)" }, children: item.secondary }) : null
1057
- ] }) }) })
1107
+ /* @__PURE__ */ jsx23(Popover3, { className: "pire-popover", children: /* @__PURE__ */ jsx23(
1108
+ ListBox3,
1109
+ {
1110
+ className: "pire-listbox",
1111
+ onScroll: onLoadMore ? (e) => {
1112
+ const el = e.currentTarget;
1113
+ if (el.scrollHeight - el.scrollTop - el.clientHeight < 48) onLoadMore();
1114
+ } : void 0,
1115
+ renderEmptyState: showsStatus ? () => /* @__PURE__ */ jsx23("div", { className: "pire-listbox-status", role: "status", "aria-live": "polite", children: isLoading ? loadingLabel ?? msg.comboBoxLoading : emptyLabel }) : void 0,
1116
+ children: (item) => /* @__PURE__ */ jsxs17(ListBoxItem3, { className: "pire-option", id: item.value, textValue: item.label, isDisabled: item.isDisabled, children: [
1117
+ /* @__PURE__ */ jsx23("span", { className: "pire-option-label", children: item.label }),
1118
+ item.secondary ? /* @__PURE__ */ jsx23("span", { className: "pire-option-secondary", children: item.secondary }) : null
1119
+ ] })
1120
+ }
1121
+ ) })
1058
1122
  ]
1059
1123
  }
1060
1124
  );
@@ -1070,7 +1134,7 @@ import {
1070
1134
  Text as Text8,
1071
1135
  FieldError as FieldError7
1072
1136
  } from "react-aria-components";
1073
- import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1137
+ import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
1074
1138
  function NumberField({
1075
1139
  label,
1076
1140
  suffix,
@@ -1084,12 +1148,12 @@ function NumberField({
1084
1148
  ...rest
1085
1149
  }) {
1086
1150
  const msg = usePireMessages();
1087
- return /* @__PURE__ */ jsxs17(AriaNumberField, { className: cx("pire-field", className), style, validationBehavior: "aria", ...rest, children: [
1088
- label ? /* @__PURE__ */ jsxs17(Label7, { className: "pire-field-label", children: [
1151
+ return /* @__PURE__ */ jsxs18(AriaNumberField, { className: cx("pire-field", className), style, validationBehavior: "aria", ...rest, children: [
1152
+ label ? /* @__PURE__ */ jsxs18(Label7, { className: "pire-field-label", children: [
1089
1153
  label,
1090
1154
  rest.isRequired ? /* @__PURE__ */ jsx24("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
1091
1155
  ] }) : null,
1092
- /* @__PURE__ */ jsxs17(
1156
+ /* @__PURE__ */ jsxs18(
1093
1157
  Group5,
1094
1158
  {
1095
1159
  className: "pire-control",
@@ -1100,7 +1164,7 @@ function NumberField({
1100
1164
  children: [
1101
1165
  /* @__PURE__ */ jsx24(AriaInput4, { className: "pire-input", "data-numeric": "true" }),
1102
1166
  suffix ? /* @__PURE__ */ jsx24("span", { className: "pire-affix", children: suffix }) : null,
1103
- hideStepper ? null : /* @__PURE__ */ jsxs17("span", { className: "pire-stepper", children: [
1167
+ hideStepper ? null : /* @__PURE__ */ jsxs18("span", { className: "pire-stepper", children: [
1104
1168
  /* @__PURE__ */ jsx24(AriaButton7, { slot: "increment", className: "pire-stepper-btn", "aria-label": msg.numberFieldIncrease, children: /* @__PURE__ */ jsx24(Icon, { name: "plus", size: 10 }) }),
1105
1169
  /* @__PURE__ */ jsx24(AriaButton7, { slot: "decrement", className: "pire-stepper-btn", "aria-label": msg.numberFieldDecrease, children: /* @__PURE__ */ jsx24(Icon, { name: "minus", size: 10 }) })
1106
1170
  ] })
@@ -1132,7 +1196,7 @@ import {
1132
1196
  Text as Text9,
1133
1197
  FieldError as FieldError8
1134
1198
  } from "react-aria-components";
1135
- import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1199
+ import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
1136
1200
  function DatePicker({
1137
1201
  label,
1138
1202
  description,
@@ -1144,12 +1208,12 @@ function DatePicker({
1144
1208
  ...rest
1145
1209
  }) {
1146
1210
  const msg = usePireMessages();
1147
- return /* @__PURE__ */ jsxs18(AriaDatePicker, { className: cx("pire-field", className), style, validationBehavior: "aria", ...rest, children: [
1148
- label ? /* @__PURE__ */ jsxs18(Label8, { className: "pire-field-label", children: [
1211
+ return /* @__PURE__ */ jsxs19(AriaDatePicker, { className: cx("pire-field", className), style, validationBehavior: "aria", ...rest, children: [
1212
+ label ? /* @__PURE__ */ jsxs19(Label8, { className: "pire-field-label", children: [
1149
1213
  label,
1150
1214
  rest.isRequired ? /* @__PURE__ */ jsx25("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
1151
1215
  ] }) : null,
1152
- /* @__PURE__ */ jsxs18(
1216
+ /* @__PURE__ */ jsxs19(
1153
1217
  Group6,
1154
1218
  {
1155
1219
  className: "pire-control",
@@ -1165,13 +1229,13 @@ function DatePicker({
1165
1229
  ),
1166
1230
  description ? /* @__PURE__ */ jsx25(Text9, { slot: "description", className: "pire-field-hint", children: description }) : null,
1167
1231
  /* @__PURE__ */ jsx25(FieldError8, { className: "pire-field-error", children: errorMessage }),
1168
- /* @__PURE__ */ jsx25(Popover4, { className: "pire-popover", children: /* @__PURE__ */ jsx25(AriaDialog, { children: /* @__PURE__ */ jsxs18(Calendar, { className: "pire-calendar", children: [
1169
- /* @__PURE__ */ jsxs18("header", { className: "pire-calendar-head", children: [
1232
+ /* @__PURE__ */ jsx25(Popover4, { className: "pire-popover", children: /* @__PURE__ */ jsx25(AriaDialog, { children: /* @__PURE__ */ jsxs19(Calendar, { className: "pire-calendar", children: [
1233
+ /* @__PURE__ */ jsxs19("header", { className: "pire-calendar-head", children: [
1170
1234
  /* @__PURE__ */ jsx25(AriaButton8, { slot: "previous", className: "pire-iconbtn", "data-size": "sm", "aria-label": msg.datePickerPreviousMonth, children: /* @__PURE__ */ jsx25(Icon, { name: "chevron-left", size: 16 }) }),
1171
1235
  /* @__PURE__ */ jsx25(Heading2, { className: "pire-calendar-title" }),
1172
1236
  /* @__PURE__ */ jsx25(AriaButton8, { slot: "next", className: "pire-iconbtn", "data-size": "sm", "aria-label": msg.datePickerNextMonth, children: /* @__PURE__ */ jsx25(Icon, { name: "chevron-right", size: 16 }) })
1173
1237
  ] }),
1174
- /* @__PURE__ */ jsxs18(CalendarGrid, { className: "pire-calendar-grid", children: [
1238
+ /* @__PURE__ */ jsxs19(CalendarGrid, { className: "pire-calendar-grid", children: [
1175
1239
  /* @__PURE__ */ jsx25(CalendarGridHeader, { children: (day) => /* @__PURE__ */ jsx25(CalendarHeaderCell, { children: day }) }),
1176
1240
  /* @__PURE__ */ jsx25(CalendarGridBody, { children: (date) => /* @__PURE__ */ jsx25(CalendarCell, { date, className: "pire-calendar-cell" }) })
1177
1241
  ] })
@@ -1187,7 +1251,7 @@ import * as React8 from "react";
1187
1251
 
1188
1252
  // src/components/feedback/Dialog.tsx
1189
1253
  import { ModalOverlay, Modal, Dialog as AriaDialog2, Heading as Heading3 } from "react-aria-components";
1190
- import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
1254
+ import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
1191
1255
  function Dialog({
1192
1256
  isOpen,
1193
1257
  onOpenChange,
@@ -1216,9 +1280,9 @@ function Dialog({
1216
1280
  onOpenChange: (o) => {
1217
1281
  if (!o) close();
1218
1282
  },
1219
- children: /* @__PURE__ */ jsx26(Modal, { className: cx("pire-modal", className), "data-size": size, style, children: /* @__PURE__ */ jsxs19(AriaDialog2, { className: "pire-dialog", children: [
1220
- title ? /* @__PURE__ */ jsxs19("header", { className: "pire-dialog-head", children: [
1221
- /* @__PURE__ */ jsxs19("div", { style: { flex: 1, minWidth: 0 }, children: [
1283
+ children: /* @__PURE__ */ jsx26(Modal, { className: cx("pire-modal", className), "data-size": size, style, children: /* @__PURE__ */ jsxs20(AriaDialog2, { className: "pire-dialog", children: [
1284
+ title ? /* @__PURE__ */ jsxs20("header", { className: "pire-dialog-head", children: [
1285
+ /* @__PURE__ */ jsxs20("div", { style: { flex: 1, minWidth: 0 }, children: [
1222
1286
  /* @__PURE__ */ jsx26(Heading3, { slot: "title", className: "pire-dialog-title", children: title }),
1223
1287
  subtitle ? /* @__PURE__ */ jsx26("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
1224
1288
  ] }),
@@ -1240,7 +1304,54 @@ import {
1240
1304
  Row,
1241
1305
  Cell
1242
1306
  } from "react-aria-components";
1243
- import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
1307
+
1308
+ // src/components/feedback/Skeleton.tsx
1309
+ import { jsx as jsx27 } from "react/jsx-runtime";
1310
+ function Skeleton({ shape = "text", width, height, className, style, ...rest }) {
1311
+ return /* @__PURE__ */ jsx27(
1312
+ "div",
1313
+ {
1314
+ className: cx("pire-skeleton", className),
1315
+ "data-shape": shape,
1316
+ "aria-hidden": "true",
1317
+ style: { width, height, ...style },
1318
+ ...rest
1319
+ }
1320
+ );
1321
+ }
1322
+ var BAR_WIDTHS = ["72%", "54%", "86%", "63%"];
1323
+ function SkeletonTableRow({ columns, density = "regular", className, style, ...rest }) {
1324
+ const cells = typeof columns === "number" ? Array.from({ length: columns }, () => ({})) : columns;
1325
+ return /* @__PURE__ */ jsx27(
1326
+ "div",
1327
+ {
1328
+ className: cx("pire-skeleton-row", className),
1329
+ "data-density": density,
1330
+ "aria-hidden": "true",
1331
+ style,
1332
+ ...rest,
1333
+ children: cells.map((c, i) => {
1334
+ const align = c.numeric ? "right" : c.align ?? "left";
1335
+ return (
1336
+ // biome-ignore lint/suspicious/noArrayIndexKey: columns are positional and never reordered.
1337
+ /* @__PURE__ */ jsx27(
1338
+ "div",
1339
+ {
1340
+ className: "pire-skeleton-cell",
1341
+ "data-align": align,
1342
+ style: { width: c.width, flex: c.width ? "0 0 auto" : void 0 },
1343
+ children: /* @__PURE__ */ jsx27(Skeleton, { width: BAR_WIDTHS[i % BAR_WIDTHS.length] })
1344
+ },
1345
+ i
1346
+ )
1347
+ );
1348
+ })
1349
+ }
1350
+ );
1351
+ }
1352
+
1353
+ // src/components/data/DataTable.tsx
1354
+ import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
1244
1355
  function DataTable({
1245
1356
  columns,
1246
1357
  rows,
@@ -1253,6 +1364,9 @@ function DataTable({
1253
1364
  onRowAction,
1254
1365
  stickyHeader = true,
1255
1366
  emptyLabel = "No records match the current filters.",
1367
+ isLoading,
1368
+ loadingRowCount,
1369
+ loadingLabel,
1256
1370
  className,
1257
1371
  style,
1258
1372
  ...rest
@@ -1263,70 +1377,91 @@ function DataTable({
1263
1377
  if (keys === "all") return onSelectionChange?.(rows.map((r) => r.id));
1264
1378
  onSelectionChange?.([...keys]);
1265
1379
  };
1266
- return /* @__PURE__ */ jsx27("div", { className: cx("pire-table-wrap", className), style, children: /* @__PURE__ */ jsxs20(
1267
- Table,
1380
+ const skeletonRows = loadingRowCount ?? (rows.length || 5);
1381
+ const skeletonColumns = [
1382
+ ...selectable ? [{ width: 44 }] : [],
1383
+ ...columns.map((c) => ({ width: c.width, align: c.align, numeric: c.numeric }))
1384
+ ];
1385
+ const body = isLoading ? [] : rows;
1386
+ return /* @__PURE__ */ jsx28(
1387
+ "div",
1268
1388
  {
1269
- className: "pire-table",
1270
- "data-density": density,
1271
- "data-sticky": String(stickyHeader),
1272
- "aria-label": rest["aria-label"],
1273
- selectionMode: selectable ? "multiple" : "none",
1274
- selectedKeys: selected ? new Set(selected) : void 0,
1275
- onSelectionChange: handleSelection,
1276
- sortDescriptor,
1277
- onSortChange: (d) => onSortChange?.({ key: String(d.column), dir: d.direction === "ascending" ? "asc" : "desc" }),
1278
- onRowAction: onRowAction ? (key) => {
1279
- const row = rows.find((r) => String(r.id) === String(key));
1280
- if (row) onRowAction(row);
1281
- } : void 0,
1282
- children: [
1283
- /* @__PURE__ */ jsxs20(TableHeader, { className: "pire-thead-row", children: [
1284
- selectable ? /* @__PURE__ */ jsx27(Column, { className: "pire-th", width: 44, children: /* @__PURE__ */ jsx27(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectAll }) }) : null,
1285
- columns.map((c, i) => /* @__PURE__ */ jsx27(
1286
- Column,
1287
- {
1288
- id: c.key,
1289
- className: "pire-th",
1290
- isRowHeader: i === 0 && !selectable,
1291
- allowsSorting: c.sortable,
1292
- width: c.width,
1293
- "data-align": c.numeric || c.align === "right" ? "right" : c.align,
1294
- "data-allows-sorting": c.sortable ? "true" : void 0,
1295
- children: /* @__PURE__ */ jsxs20("span", { className: "pire-th-inner", children: [
1296
- c.label,
1297
- c.sortable ? /* @__PURE__ */ jsx27(
1298
- Icon,
1299
- {
1300
- size: 12,
1301
- name: sort?.key === c.key ? sort.dir === "asc" ? "arrow-up" : "arrow-down" : "chevrons-up-down",
1302
- style: { color: sort?.key === c.key ? "var(--accent-subtle-fg)" : "var(--text-tertiary)" }
1303
- }
1304
- ) : null
1305
- ] })
1306
- },
1307
- c.key
1308
- ))
1309
- ] }),
1310
- /* @__PURE__ */ jsx27(TableBody, { renderEmptyState: () => /* @__PURE__ */ jsx27("div", { className: "pire-table-empty", children: emptyLabel }), children: rows.map((row) => /* @__PURE__ */ jsxs20(Row, { id: row.id, className: "pire-tr", "data-pressable": onRowAction ? "true" : void 0, children: [
1311
- selectable ? /* @__PURE__ */ jsx27(Cell, { className: "pire-td", children: /* @__PURE__ */ jsx27(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectRow }) }) : null,
1312
- columns.map((c) => /* @__PURE__ */ jsx27(
1313
- Cell,
1314
- {
1315
- className: "pire-td",
1316
- "data-numeric": c.numeric ? "true" : void 0,
1317
- style: { textAlign: c.align && !c.numeric ? c.align : void 0 },
1318
- children: c.render ? c.render(row) : row[c.key]
1319
- },
1320
- c.key
1321
- ))
1322
- ] }, row.id)) })
1323
- ]
1389
+ className: cx("pire-table-wrap", className),
1390
+ style,
1391
+ "data-loading": isLoading ? "true" : void 0,
1392
+ "aria-busy": isLoading ? "true" : void 0,
1393
+ children: /* @__PURE__ */ jsxs21(
1394
+ Table,
1395
+ {
1396
+ className: "pire-table",
1397
+ "data-density": density,
1398
+ "data-sticky": String(stickyHeader),
1399
+ "aria-label": rest["aria-label"],
1400
+ selectionMode: selectable ? "multiple" : "none",
1401
+ selectedKeys: selected ? new Set(selected) : void 0,
1402
+ onSelectionChange: handleSelection,
1403
+ sortDescriptor,
1404
+ onSortChange: (d) => onSortChange?.({ key: String(d.column), dir: d.direction === "ascending" ? "asc" : "desc" }),
1405
+ onRowAction: onRowAction ? (key) => {
1406
+ const row = rows.find((r) => String(r.id) === String(key));
1407
+ if (row) onRowAction(row);
1408
+ } : void 0,
1409
+ children: [
1410
+ /* @__PURE__ */ jsxs21(TableHeader, { className: "pire-thead-row", children: [
1411
+ selectable ? /* @__PURE__ */ jsx28(Column, { className: "pire-th", width: 44, children: /* @__PURE__ */ jsx28(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectAll }) }) : null,
1412
+ columns.map((c, i) => /* @__PURE__ */ jsx28(
1413
+ Column,
1414
+ {
1415
+ id: c.key,
1416
+ className: "pire-th",
1417
+ isRowHeader: i === 0 && !selectable,
1418
+ allowsSorting: c.sortable,
1419
+ width: c.width,
1420
+ "data-align": c.numeric || c.align === "right" ? "right" : c.align,
1421
+ "data-allows-sorting": c.sortable ? "true" : void 0,
1422
+ children: /* @__PURE__ */ jsxs21("span", { className: "pire-th-inner", children: [
1423
+ c.label,
1424
+ c.sortable ? /* @__PURE__ */ jsx28(
1425
+ Icon,
1426
+ {
1427
+ size: 12,
1428
+ name: sort?.key === c.key ? sort.dir === "asc" ? "arrow-up" : "arrow-down" : "chevrons-up-down",
1429
+ style: { color: sort?.key === c.key ? "var(--accent-subtle-fg)" : "var(--text-tertiary)" }
1430
+ }
1431
+ ) : null
1432
+ ] })
1433
+ },
1434
+ c.key
1435
+ ))
1436
+ ] }),
1437
+ /* @__PURE__ */ jsx28(TableBody, { renderEmptyState: () => isLoading ? /* @__PURE__ */ jsxs21("div", { className: "pire-table-loading", role: "status", "aria-live": "polite", children: [
1438
+ /* @__PURE__ */ jsx28("span", { className: "pire-sr-only", children: loadingLabel ?? msg.dataTableLoading }),
1439
+ Array.from({ length: skeletonRows }, (_, i) => (
1440
+ // biome-ignore lint/suspicious/noArrayIndexKey: placeholder rows are positional.
1441
+ /* @__PURE__ */ jsx28(SkeletonTableRow, { columns: skeletonColumns, density }, i)
1442
+ ))
1443
+ ] }) : /* @__PURE__ */ jsx28("div", { className: "pire-table-empty", children: emptyLabel }), children: body.map((row) => /* @__PURE__ */ jsxs21(Row, { id: row.id, className: "pire-tr", "data-pressable": onRowAction ? "true" : void 0, children: [
1444
+ selectable ? /* @__PURE__ */ jsx28(Cell, { className: "pire-td", children: /* @__PURE__ */ jsx28(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectRow }) }) : null,
1445
+ columns.map((c) => /* @__PURE__ */ jsx28(
1446
+ Cell,
1447
+ {
1448
+ className: "pire-td",
1449
+ "data-numeric": c.numeric ? "true" : void 0,
1450
+ style: { textAlign: c.align && !c.numeric ? c.align : void 0 },
1451
+ children: c.render ? c.render(row) : row[c.key]
1452
+ },
1453
+ c.key
1454
+ ))
1455
+ ] }, row.id)) })
1456
+ ]
1457
+ }
1458
+ )
1324
1459
  }
1325
- ) });
1460
+ );
1326
1461
  }
1327
1462
 
1328
1463
  // src/components/patterns/ValueHelpDialog.tsx
1329
- import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
1464
+ import { jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
1330
1465
  function ValueHelpDialog({
1331
1466
  isOpen,
1332
1467
  title = "Select a record",
@@ -1347,16 +1482,16 @@ function ValueHelpDialog({
1347
1482
  if (!q) return rows;
1348
1483
  return rows.filter((row) => Object.values(row).some((v) => String(v).toLowerCase().includes(q)));
1349
1484
  }, [rows, query]);
1350
- return /* @__PURE__ */ jsx28(
1485
+ return /* @__PURE__ */ jsx29(
1351
1486
  Dialog,
1352
1487
  {
1353
1488
  isOpen,
1354
1489
  size: "lg",
1355
1490
  title,
1356
1491
  onClose,
1357
- footer: /* @__PURE__ */ jsx28(Button, { variant: "tertiary", onPress: onClose, children: msg.valueHelpDialogCancel }),
1358
- children: /* @__PURE__ */ jsxs21("div", { style: { display: "flex", flexDirection: "column", gap: "var(--sp-3)" }, children: [
1359
- /* @__PURE__ */ jsx28(
1492
+ footer: /* @__PURE__ */ jsx29(Button, { variant: "tertiary", onPress: onClose, children: msg.valueHelpDialogCancel }),
1493
+ children: /* @__PURE__ */ jsxs22("div", { style: { display: "flex", flexDirection: "column", gap: "var(--sp-3)" }, children: [
1494
+ /* @__PURE__ */ jsx29(
1360
1495
  Input,
1361
1496
  {
1362
1497
  "aria-label": msg.valueHelpDialogSearch,
@@ -1368,7 +1503,7 @@ function ValueHelpDialog({
1368
1503
  autoFocus: true
1369
1504
  }
1370
1505
  ),
1371
- /* @__PURE__ */ jsx28(
1506
+ /* @__PURE__ */ jsx29(
1372
1507
  DataTable,
1373
1508
  {
1374
1509
  "aria-label": typeof title === "string" ? title : "Records",
@@ -1388,7 +1523,7 @@ function ValueHelpDialog({
1388
1523
  }
1389
1524
 
1390
1525
  // src/components/forms/ValueHelpField.tsx
1391
- import { jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
1526
+ import { jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
1392
1527
  var defaultFormat = (row) => [row.id, row.name ?? row.label ?? row.text].filter(Boolean).join(" \u2014 ");
1393
1528
  function ValueHelpField({
1394
1529
  label,
@@ -1410,9 +1545,9 @@ function ValueHelpField({
1410
1545
  }) {
1411
1546
  const msg = usePireMessages();
1412
1547
  const [open, setOpen] = React9.useState(false);
1413
- return /* @__PURE__ */ jsxs22("div", { className: cx(className), style, children: [
1414
- /* @__PURE__ */ jsxs22("div", { style: { display: "flex", gap: "var(--sp-2)", alignItems: "flex-end" }, children: [
1415
- /* @__PURE__ */ jsx29(
1548
+ return /* @__PURE__ */ jsxs23("div", { className: cx(className), style, children: [
1549
+ /* @__PURE__ */ jsxs23("div", { style: { display: "flex", gap: "var(--sp-2)", alignItems: "flex-end" }, children: [
1550
+ /* @__PURE__ */ jsx30(
1416
1551
  Input,
1417
1552
  {
1418
1553
  label,
@@ -1426,7 +1561,7 @@ function ValueHelpField({
1426
1561
  errorMessage
1427
1562
  }
1428
1563
  ),
1429
- allowsClear && value ? /* @__PURE__ */ jsx29(
1564
+ allowsClear && value ? /* @__PURE__ */ jsx30(
1430
1565
  IconButton,
1431
1566
  {
1432
1567
  icon: "x",
@@ -1436,7 +1571,7 @@ function ValueHelpField({
1436
1571
  onPress: () => onChange?.(null)
1437
1572
  }
1438
1573
  ) : null,
1439
- /* @__PURE__ */ jsx29(
1574
+ /* @__PURE__ */ jsx30(
1440
1575
  IconButton,
1441
1576
  {
1442
1577
  icon: "search",
@@ -1447,7 +1582,7 @@ function ValueHelpField({
1447
1582
  }
1448
1583
  )
1449
1584
  ] }),
1450
- /* @__PURE__ */ jsx29(
1585
+ /* @__PURE__ */ jsx30(
1451
1586
  ValueHelpDialog,
1452
1587
  {
1453
1588
  isOpen: open,
@@ -1462,7 +1597,7 @@ function ValueHelpField({
1462
1597
  }
1463
1598
 
1464
1599
  // src/components/navigation/ShellBar.tsx
1465
- import { jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
1600
+ import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
1466
1601
  var initials2 = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
1467
1602
  function ShellBar({
1468
1603
  product,
@@ -1477,22 +1612,22 @@ function ShellBar({
1477
1612
  className,
1478
1613
  ...rest
1479
1614
  }) {
1480
- return /* @__PURE__ */ jsxs23("header", { className: cx("pire-shellbar", className), ...rest, children: [
1481
- onMenu ? /* @__PURE__ */ jsx30(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
1482
- monogram ? /* @__PURE__ */ jsx30("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
1483
- product ? /* @__PURE__ */ jsx30("span", { className: "pire-shellbar-product", children: product }) : null,
1484
- title ? /* @__PURE__ */ jsx30("span", { className: "pire-shellbar-title", children: title }) : null,
1485
- /* @__PURE__ */ jsx30("span", { className: "pire-shellbar-spacer" }),
1486
- onSearch ? /* @__PURE__ */ jsx30(IconButton, { icon: "search", label: searchLabel, variant: "inverse", size: "sm", onPress: onSearch }) : null,
1615
+ return /* @__PURE__ */ jsxs24("header", { className: cx("pire-shellbar", className), ...rest, children: [
1616
+ onMenu ? /* @__PURE__ */ jsx31(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
1617
+ monogram ? /* @__PURE__ */ jsx31("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
1618
+ product ? /* @__PURE__ */ jsx31("span", { className: "pire-shellbar-product", children: product }) : null,
1619
+ title ? /* @__PURE__ */ jsx31("span", { className: "pire-shellbar-title", children: title }) : null,
1620
+ /* @__PURE__ */ jsx31("span", { className: "pire-shellbar-spacer" }),
1621
+ onSearch ? /* @__PURE__ */ jsx31(IconButton, { icon: "search", label: searchLabel, variant: "inverse", size: "sm", onPress: onSearch }) : null,
1487
1622
  actions,
1488
- user ? /* @__PURE__ */ jsx30("span", { className: "pire-avatar", title: user, "aria-label": user, role: "img", children: initials2(user) }) : null
1623
+ user ? /* @__PURE__ */ jsx31("span", { className: "pire-avatar", title: user, "aria-label": user, role: "img", children: initials2(user) }) : null
1489
1624
  ] });
1490
1625
  }
1491
1626
 
1492
1627
  // src/components/navigation/SideNav.tsx
1493
1628
  import * as React10 from "react";
1494
1629
  import { Button as AriaButton9, Disclosure, DisclosureGroup, DisclosurePanel } from "react-aria-components";
1495
- import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
1630
+ import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
1496
1631
  function findActiveParent(groups, value) {
1497
1632
  if (value == null) return void 0;
1498
1633
  for (const group of groups) {
@@ -1540,7 +1675,7 @@ function SideNav({
1540
1675
  };
1541
1676
  const renderRow = (item, onPress, isGroup) => {
1542
1677
  const selected = !isGroup && item.id === value;
1543
- const button = /* @__PURE__ */ jsxs24(
1678
+ const button = /* @__PURE__ */ jsxs25(
1544
1679
  AriaButton9,
1545
1680
  {
1546
1681
  className: "pire-sidenav-item",
@@ -1550,17 +1685,17 @@ function SideNav({
1550
1685
  "aria-label": collapsed ? item.label : void 0,
1551
1686
  onPress,
1552
1687
  children: [
1553
- item.icon ? /* @__PURE__ */ jsx31(Icon, { name: item.icon, size: 16 }) : null,
1554
- collapsed ? null : /* @__PURE__ */ jsx31("span", { children: item.label }),
1555
- item.count != null && !collapsed ? /* @__PURE__ */ jsx31("span", { className: "pire-sidenav-count", children: item.count }) : null
1688
+ item.icon ? /* @__PURE__ */ jsx32(Icon, { name: item.icon, size: 16 }) : null,
1689
+ collapsed ? null : /* @__PURE__ */ jsx32("span", { children: item.label }),
1690
+ item.count != null && !collapsed ? /* @__PURE__ */ jsx32("span", { className: "pire-sidenav-count", children: item.count }) : null
1556
1691
  ]
1557
1692
  },
1558
1693
  item.id
1559
1694
  );
1560
- return collapsed ? /* @__PURE__ */ jsx31(Tooltip, { label: item.label, placement: "right", children: button }, item.id) : button;
1695
+ return collapsed ? /* @__PURE__ */ jsx32(Tooltip, { label: item.label, placement: "right", children: button }, item.id) : button;
1561
1696
  };
1562
- const renderSection = (item) => /* @__PURE__ */ jsxs24(Disclosure, { id: item.id, className: "pire-sidenav-section", children: [
1563
- /* @__PURE__ */ jsxs24(
1697
+ const renderSection = (item) => /* @__PURE__ */ jsxs25(Disclosure, { id: item.id, className: "pire-sidenav-section", children: [
1698
+ /* @__PURE__ */ jsxs25(
1564
1699
  AriaButton9,
1565
1700
  {
1566
1701
  slot: "trigger",
@@ -1568,16 +1703,16 @@ function SideNav({
1568
1703
  "data-kind": "group",
1569
1704
  "data-active-child": item.id === activeParent ? "true" : void 0,
1570
1705
  children: [
1571
- item.icon ? /* @__PURE__ */ jsx31(Icon, { name: item.icon, size: 16 }) : null,
1572
- /* @__PURE__ */ jsx31("span", { children: item.label }),
1573
- item.count != null ? /* @__PURE__ */ jsx31("span", { className: "pire-sidenav-count", children: item.count }) : null,
1574
- /* @__PURE__ */ jsx31(Icon, { name: "chevron-down", size: 16, className: "pire-sidenav-chevron" })
1706
+ item.icon ? /* @__PURE__ */ jsx32(Icon, { name: item.icon, size: 16 }) : null,
1707
+ /* @__PURE__ */ jsx32("span", { children: item.label }),
1708
+ item.count != null ? /* @__PURE__ */ jsx32("span", { className: "pire-sidenav-count", children: item.count }) : null,
1709
+ /* @__PURE__ */ jsx32(Icon, { name: "chevron-down", size: 16, className: "pire-sidenav-chevron" })
1575
1710
  ]
1576
1711
  }
1577
1712
  ),
1578
- /* @__PURE__ */ jsx31(DisclosurePanel, { className: "pire-sidenav-subnav", children: item.items?.map((child) => {
1713
+ /* @__PURE__ */ jsx32(DisclosurePanel, { className: "pire-sidenav-subnav", children: item.items?.map((child) => {
1579
1714
  const selected = child.id === value;
1580
- return /* @__PURE__ */ jsxs24(
1715
+ return /* @__PURE__ */ jsxs25(
1581
1716
  AriaButton9,
1582
1717
  {
1583
1718
  className: "pire-sidenav-item pire-sidenav-subitem",
@@ -1585,15 +1720,15 @@ function SideNav({
1585
1720
  "aria-current": selected ? "page" : void 0,
1586
1721
  onPress: () => onChange?.(child.id),
1587
1722
  children: [
1588
- /* @__PURE__ */ jsx31("span", { children: child.label }),
1589
- child.count != null ? /* @__PURE__ */ jsx31("span", { className: "pire-sidenav-count", children: child.count }) : null
1723
+ /* @__PURE__ */ jsx32("span", { children: child.label }),
1724
+ child.count != null ? /* @__PURE__ */ jsx32("span", { className: "pire-sidenav-count", children: child.count }) : null
1590
1725
  ]
1591
1726
  },
1592
1727
  child.id
1593
1728
  );
1594
1729
  }) })
1595
1730
  ] }, item.id);
1596
- return /* @__PURE__ */ jsxs24(
1731
+ return /* @__PURE__ */ jsxs25(
1597
1732
  "nav",
1598
1733
  {
1599
1734
  className: cx("pire-sidenav", className),
@@ -1608,9 +1743,9 @@ function SideNav({
1608
1743
  if (isGroup && !collapsed) return renderSection(item);
1609
1744
  return renderRow(item, () => isGroup ? toggleExpanded(item.id) : onChange?.(item.id), isGroup);
1610
1745
  });
1611
- return /* @__PURE__ */ jsxs24("div", { className: "pire-sidenav-group", children: [
1612
- group.label && !collapsed ? /* @__PURE__ */ jsx31("div", { className: "pire-sidenav-label", children: group.label }) : null,
1613
- hasSections ? /* @__PURE__ */ jsx31(
1746
+ return /* @__PURE__ */ jsxs25("div", { className: "pire-sidenav-group", children: [
1747
+ group.label && !collapsed ? /* @__PURE__ */ jsx32("div", { className: "pire-sidenav-label", children: group.label }) : null,
1748
+ hasSections ? /* @__PURE__ */ jsx32(
1614
1749
  DisclosureGroup,
1615
1750
  {
1616
1751
  className: "pire-sidenav-tree",
@@ -1622,7 +1757,7 @@ function SideNav({
1622
1757
  ) : rows
1623
1758
  ] }, group.label ?? gi);
1624
1759
  }),
1625
- footer ? /* @__PURE__ */ jsx31("div", { className: "pire-sidenav-footer", children: footer }) : null
1760
+ footer ? /* @__PURE__ */ jsx32("div", { className: "pire-sidenav-footer", children: footer }) : null
1626
1761
  ]
1627
1762
  }
1628
1763
  );
@@ -1630,9 +1765,9 @@ function SideNav({
1630
1765
 
1631
1766
  // src/components/navigation/Tabs.tsx
1632
1767
  import { Tabs as AriaTabs, TabList, Tab as AriaTab, TabPanel } from "react-aria-components";
1633
- import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
1768
+ import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
1634
1769
  function Tabs({ items, value, defaultValue, onChange, panels, className, style, ...rest }) {
1635
- return /* @__PURE__ */ jsxs25(
1770
+ return /* @__PURE__ */ jsxs26(
1636
1771
  AriaTabs,
1637
1772
  {
1638
1773
  className,
@@ -1641,12 +1776,12 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
1641
1776
  defaultSelectedKey: defaultValue,
1642
1777
  onSelectionChange: (k) => onChange?.(String(k)),
1643
1778
  children: [
1644
- /* @__PURE__ */ jsx32(TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ jsxs25(AriaTab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
1645
- item.icon ? /* @__PURE__ */ jsx32(Icon, { name: item.icon, size: 16 }) : null,
1779
+ /* @__PURE__ */ jsx33(TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ jsxs26(AriaTab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
1780
+ item.icon ? /* @__PURE__ */ jsx33(Icon, { name: item.icon, size: 16 }) : null,
1646
1781
  item.label,
1647
- item.count != null ? /* @__PURE__ */ jsx32("span", { className: "pire-tab-count", children: item.count }) : null
1782
+ item.count != null ? /* @__PURE__ */ jsx33("span", { className: "pire-tab-count", children: item.count }) : null
1648
1783
  ] }) }),
1649
- items.map((item) => /* @__PURE__ */ jsx32(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
1784
+ items.map((item) => /* @__PURE__ */ jsx33(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
1650
1785
  ]
1651
1786
  }
1652
1787
  );
@@ -1654,9 +1789,9 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
1654
1789
 
1655
1790
  // src/components/navigation/Breadcrumb.tsx
1656
1791
  import { Breadcrumbs as AriaBreadcrumbs, Breadcrumb as AriaBreadcrumb, Link as Link2 } from "react-aria-components";
1657
- import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
1792
+ import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
1658
1793
  function Breadcrumb({ items, onNavigate, className, style }) {
1659
- return /* @__PURE__ */ jsx33(
1794
+ return /* @__PURE__ */ jsx34(
1660
1795
  AriaBreadcrumbs,
1661
1796
  {
1662
1797
  className: cx("pire-breadcrumbs", className),
@@ -1665,9 +1800,9 @@ function Breadcrumb({ items, onNavigate, className, style }) {
1665
1800
  onAction: (key) => onNavigate?.(String(key)),
1666
1801
  children: (item) => {
1667
1802
  const last = items[items.length - 1] === item;
1668
- return /* @__PURE__ */ jsxs26(AriaBreadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
1669
- last ? item.label : /* @__PURE__ */ jsx33(Link2, { href: item.href, children: item.label }),
1670
- last ? null : /* @__PURE__ */ jsx33(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
1803
+ return /* @__PURE__ */ jsxs27(AriaBreadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
1804
+ last ? item.label : /* @__PURE__ */ jsx34(Link2, { href: item.href, children: item.label }),
1805
+ last ? null : /* @__PURE__ */ jsx34(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
1671
1806
  ] });
1672
1807
  }
1673
1808
  }
@@ -1675,7 +1810,7 @@ function Breadcrumb({ items, onNavigate, className, style }) {
1675
1810
  }
1676
1811
 
1677
1812
  // src/components/navigation/Pagination.tsx
1678
- import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
1813
+ import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
1679
1814
  function Pagination({
1680
1815
  page = 1,
1681
1816
  pageSize = 25,
@@ -1690,9 +1825,9 @@ function Pagination({
1690
1825
  const pages = Math.max(1, Math.ceil(total / pageSize));
1691
1826
  const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
1692
1827
  const to = Math.min(total, page * pageSize);
1693
- return /* @__PURE__ */ jsxs27("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
1694
- /* @__PURE__ */ jsx34("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
1695
- /* @__PURE__ */ jsx34(
1828
+ return /* @__PURE__ */ jsxs28("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
1829
+ /* @__PURE__ */ jsx35("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
1830
+ /* @__PURE__ */ jsx35(
1696
1831
  IconButton,
1697
1832
  {
1698
1833
  icon: "chevron-left",
@@ -1703,8 +1838,8 @@ function Pagination({
1703
1838
  onPress: () => onPageChange?.(page - 1)
1704
1839
  }
1705
1840
  ),
1706
- /* @__PURE__ */ jsx34("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
1707
- /* @__PURE__ */ jsx34(
1841
+ /* @__PURE__ */ jsx35("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
1842
+ /* @__PURE__ */ jsx35(
1708
1843
  IconButton,
1709
1844
  {
1710
1845
  icon: "chevron-right",
@@ -1715,7 +1850,7 @@ function Pagination({
1715
1850
  onPress: () => onPageChange?.(page + 1)
1716
1851
  }
1717
1852
  ),
1718
- onPageSizeChange ? /* @__PURE__ */ jsx34(
1853
+ onPageSizeChange ? /* @__PURE__ */ jsx35(
1719
1854
  Select,
1720
1855
  {
1721
1856
  "aria-label": msg.paginationRowsPerPage,
@@ -1738,11 +1873,11 @@ import {
1738
1873
  Separator as AriaSeparator2,
1739
1874
  Header
1740
1875
  } from "react-aria-components";
1741
- import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
1876
+ import { jsx as jsx36, jsxs as jsxs29 } from "react/jsx-runtime";
1742
1877
  function Menu({ minWidth, className, style, ...rest }) {
1743
1878
  const width = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
1744
1879
  const menuStyle = width == null ? style : { ["--pire-menu-min-w"]: width, ...style };
1745
- return /* @__PURE__ */ jsx35(
1880
+ return /* @__PURE__ */ jsx36(
1746
1881
  AriaMenu,
1747
1882
  {
1748
1883
  className: cx("pire-menu", className),
@@ -1760,35 +1895,35 @@ function MenuItem({
1760
1895
  className,
1761
1896
  ...rest
1762
1897
  }) {
1763
- return /* @__PURE__ */ jsxs28(
1898
+ return /* @__PURE__ */ jsxs29(
1764
1899
  AriaMenuItem,
1765
1900
  {
1766
1901
  className: cx("pire-menu-item", className),
1767
1902
  "data-tone": tone === "danger" ? "danger" : void 0,
1768
1903
  ...rest,
1769
1904
  children: [
1770
- icon ? /* @__PURE__ */ jsx35(Icon, { name: icon, size: 16, className: "pire-menu-item-icon" }) : null,
1771
- /* @__PURE__ */ jsxs28("span", { className: "pire-menu-item-body", children: [
1772
- /* @__PURE__ */ jsx35("span", { className: "pire-menu-item-label", children }),
1773
- description ? /* @__PURE__ */ jsx35("span", { className: "pire-menu-item-desc", children: description }) : null
1905
+ icon ? /* @__PURE__ */ jsx36(Icon, { name: icon, size: 16, className: "pire-menu-item-icon" }) : null,
1906
+ /* @__PURE__ */ jsxs29("span", { className: "pire-menu-item-body", children: [
1907
+ /* @__PURE__ */ jsx36("span", { className: "pire-menu-item-label", children }),
1908
+ description ? /* @__PURE__ */ jsx36("span", { className: "pire-menu-item-desc", children: description }) : null
1774
1909
  ] }),
1775
- shortcut ? /* @__PURE__ */ jsx35("kbd", { className: "pire-menu-item-shortcut", children: shortcut }) : null
1910
+ shortcut ? /* @__PURE__ */ jsx36("kbd", { className: "pire-menu-item-shortcut", children: shortcut }) : null
1776
1911
  ]
1777
1912
  }
1778
1913
  );
1779
1914
  }
1780
1915
  function MenuSection({ title, children, className, ...rest }) {
1781
- return /* @__PURE__ */ jsxs28(AriaMenuSection, { className: cx("pire-menu-section", className), ...rest, children: [
1782
- title ? /* @__PURE__ */ jsx35(Header, { className: "pire-menu-section-title", children: title }) : null,
1916
+ return /* @__PURE__ */ jsxs29(AriaMenuSection, { className: cx("pire-menu-section", className), ...rest, children: [
1917
+ title ? /* @__PURE__ */ jsx36(Header, { className: "pire-menu-section-title", children: title }) : null,
1783
1918
  children
1784
1919
  ] });
1785
1920
  }
1786
1921
  function MenuSeparator({ className }) {
1787
- return /* @__PURE__ */ jsx35(AriaSeparator2, { className: cx("pire-menu-separator", className) });
1922
+ return /* @__PURE__ */ jsx36(AriaSeparator2, { className: cx("pire-menu-separator", className) });
1788
1923
  }
1789
1924
 
1790
1925
  // src/components/feedback/InlineMessage.tsx
1791
- import { jsx as jsx36, jsxs as jsxs29 } from "react/jsx-runtime";
1926
+ import { jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
1792
1927
  var KIND_ICON = {
1793
1928
  info: "info",
1794
1929
  success: "check-circle-2",
@@ -1798,7 +1933,7 @@ var KIND_ICON = {
1798
1933
  function InlineMessage({ kind = "info", title, action, onClose, children, className, ...rest }) {
1799
1934
  const msg = usePireMessages();
1800
1935
  const assertive = kind === "error" || kind === "warning";
1801
- return /* @__PURE__ */ jsxs29(
1936
+ return /* @__PURE__ */ jsxs30(
1802
1937
  "div",
1803
1938
  {
1804
1939
  className: cx("pire-msg", className),
@@ -1807,13 +1942,13 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
1807
1942
  "aria-live": assertive ? "assertive" : "polite",
1808
1943
  ...rest,
1809
1944
  children: [
1810
- /* @__PURE__ */ jsx36(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
1811
- /* @__PURE__ */ jsxs29("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
1812
- title ? /* @__PURE__ */ jsx36("span", { className: "pire-msg-title", children: title }) : null,
1813
- children ? /* @__PURE__ */ jsx36("span", { className: "pire-msg-body", children }) : null,
1945
+ /* @__PURE__ */ jsx37(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
1946
+ /* @__PURE__ */ jsxs30("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
1947
+ title ? /* @__PURE__ */ jsx37("span", { className: "pire-msg-title", children: title }) : null,
1948
+ children ? /* @__PURE__ */ jsx37("span", { className: "pire-msg-body", children }) : null,
1814
1949
  action
1815
1950
  ] }),
1816
- onClose ? /* @__PURE__ */ jsx36(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
1951
+ onClose ? /* @__PURE__ */ jsx37(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
1817
1952
  ]
1818
1953
  }
1819
1954
  );
@@ -1821,7 +1956,7 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
1821
1956
 
1822
1957
  // src/components/feedback/ProgressBar.tsx
1823
1958
  import { ProgressBar as AriaProgressBar, Label as Label9 } from "react-aria-components";
1824
- import { Fragment as Fragment2, jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
1959
+ import { Fragment as Fragment2, jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
1825
1960
  function ProgressBar({
1826
1961
  value = 0,
1827
1962
  minValue = 0,
@@ -1834,7 +1969,7 @@ function ProgressBar({
1834
1969
  className,
1835
1970
  style
1836
1971
  }) {
1837
- return /* @__PURE__ */ jsx37(
1972
+ return /* @__PURE__ */ jsx38(
1838
1973
  AriaProgressBar,
1839
1974
  {
1840
1975
  className: cx("pire-progress", className),
@@ -1845,12 +1980,12 @@ function ProgressBar({
1845
1980
  maxValue,
1846
1981
  isIndeterminate,
1847
1982
  style,
1848
- children: ({ percentage, valueText }) => /* @__PURE__ */ jsxs30(Fragment2, { children: [
1849
- label || showValue ? /* @__PURE__ */ jsxs30("div", { className: "pire-progress-head", children: [
1850
- label ? /* @__PURE__ */ jsx37(Label9, { children: label }) : /* @__PURE__ */ jsx37("span", {}),
1851
- showValue && !isIndeterminate ? /* @__PURE__ */ jsx37("span", { className: "pire-numeric", children: valueText }) : null
1983
+ children: ({ percentage, valueText }) => /* @__PURE__ */ jsxs31(Fragment2, { children: [
1984
+ label || showValue ? /* @__PURE__ */ jsxs31("div", { className: "pire-progress-head", children: [
1985
+ label ? /* @__PURE__ */ jsx38(Label9, { children: label }) : /* @__PURE__ */ jsx38("span", {}),
1986
+ showValue && !isIndeterminate ? /* @__PURE__ */ jsx38("span", { className: "pire-numeric", children: valueText }) : null
1852
1987
  ] }) : null,
1853
- /* @__PURE__ */ jsx37("div", { className: "pire-progress-track", children: /* @__PURE__ */ jsx37("div", { className: "pire-progress-fill", style: { width: `${isIndeterminate ? 40 : percentage}%` } }) })
1988
+ /* @__PURE__ */ jsx38("div", { className: "pire-progress-track", children: /* @__PURE__ */ jsx38("div", { className: "pire-progress-fill", style: { width: `${isIndeterminate ? 40 : percentage}%` } }) })
1854
1989
  ] })
1855
1990
  }
1856
1991
  );
@@ -1858,7 +1993,7 @@ function ProgressBar({
1858
1993
 
1859
1994
  // src/components/feedback/Toast.tsx
1860
1995
  import * as React11 from "react";
1861
- import { jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
1996
+ import { jsx as jsx39, jsxs as jsxs32 } from "react/jsx-runtime";
1862
1997
  var KIND_ICON2 = {
1863
1998
  info: "info",
1864
1999
  success: "check-circle-2",
@@ -1867,7 +2002,7 @@ var KIND_ICON2 = {
1867
2002
  };
1868
2003
  function Toast({ kind = "success", onClose, position = "bottom-center", children, className, ...rest }) {
1869
2004
  const msg = usePireMessages();
1870
- return /* @__PURE__ */ jsxs31(
2005
+ return /* @__PURE__ */ jsxs32(
1871
2006
  "div",
1872
2007
  {
1873
2008
  className: cx("pire-toast", className),
@@ -1876,9 +2011,9 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
1876
2011
  "aria-live": kind === "error" ? "assertive" : "polite",
1877
2012
  ...rest,
1878
2013
  children: [
1879
- /* @__PURE__ */ jsx38(Icon, { name: KIND_ICON2[kind], size: 16 }),
1880
- /* @__PURE__ */ jsx38("span", { style: { flex: 1 }, children }),
1881
- onClose ? /* @__PURE__ */ jsx38(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
2014
+ /* @__PURE__ */ jsx39(Icon, { name: KIND_ICON2[kind], size: 16 }),
2015
+ /* @__PURE__ */ jsx39("span", { style: { flex: 1 }, children }),
2016
+ onClose ? /* @__PURE__ */ jsx39(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
1882
2017
  ]
1883
2018
  }
1884
2019
  );
@@ -1896,9 +2031,9 @@ function ToastProvider({ children, timeout = 6e3 }) {
1896
2031
  return id;
1897
2032
  }, [close, timeout]);
1898
2033
  const value = React11.useMemo(() => ({ add, close }), [add, close]);
1899
- return /* @__PURE__ */ jsxs31(ToastContext.Provider, { value, children: [
2034
+ return /* @__PURE__ */ jsxs32(ToastContext.Provider, { value, children: [
1900
2035
  children,
1901
- /* @__PURE__ */ jsx38("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ jsx38(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
2036
+ /* @__PURE__ */ jsx39("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ jsx39(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
1902
2037
  ] });
1903
2038
  }
1904
2039
  function useToast() {
@@ -1907,54 +2042,9 @@ function useToast() {
1907
2042
  return ctx;
1908
2043
  }
1909
2044
 
1910
- // src/components/feedback/Skeleton.tsx
1911
- import { jsx as jsx39 } from "react/jsx-runtime";
1912
- function Skeleton({ shape = "text", width, height, className, style, ...rest }) {
1913
- return /* @__PURE__ */ jsx39(
1914
- "div",
1915
- {
1916
- className: cx("pire-skeleton", className),
1917
- "data-shape": shape,
1918
- "aria-hidden": "true",
1919
- style: { width, height, ...style },
1920
- ...rest
1921
- }
1922
- );
1923
- }
1924
- var BAR_WIDTHS = ["72%", "54%", "86%", "63%"];
1925
- function SkeletonTableRow({ columns, density = "regular", className, style, ...rest }) {
1926
- const cells = typeof columns === "number" ? Array.from({ length: columns }, () => ({})) : columns;
1927
- return /* @__PURE__ */ jsx39(
1928
- "div",
1929
- {
1930
- className: cx("pire-skeleton-row", className),
1931
- "data-density": density,
1932
- "aria-hidden": "true",
1933
- style,
1934
- ...rest,
1935
- children: cells.map((c, i) => {
1936
- const align = c.numeric ? "right" : c.align ?? "left";
1937
- return (
1938
- // biome-ignore lint/suspicious/noArrayIndexKey: columns are positional and never reordered.
1939
- /* @__PURE__ */ jsx39(
1940
- "div",
1941
- {
1942
- className: "pire-skeleton-cell",
1943
- "data-align": align,
1944
- style: { width: c.width, flex: c.width ? "0 0 auto" : void 0 },
1945
- children: /* @__PURE__ */ jsx39(Skeleton, { width: BAR_WIDTHS[i % BAR_WIDTHS.length] })
1946
- },
1947
- i
1948
- )
1949
- );
1950
- })
1951
- }
1952
- );
1953
- }
1954
-
1955
2045
  // src/components/data/KpiTile.tsx
1956
2046
  import { Button as AriaButton10 } from "react-aria-components";
1957
- import { Fragment as Fragment3, jsx as jsx40, jsxs as jsxs32 } from "react/jsx-runtime";
2047
+ import { Fragment as Fragment3, jsx as jsx40, jsxs as jsxs33 } from "react/jsx-runtime";
1958
2048
  function KpiTile({
1959
2049
  label,
1960
2050
  value,
@@ -1970,16 +2060,16 @@ function KpiTile({
1970
2060
  style
1971
2061
  }) {
1972
2062
  const tone = deltaTone ?? (deltaDirection === "down" ? "negative" : "positive");
1973
- const body = /* @__PURE__ */ jsxs32(Fragment3, { children: [
1974
- /* @__PURE__ */ jsxs32("span", { className: "pire-kpi-label", children: [
2063
+ const body = /* @__PURE__ */ jsxs33(Fragment3, { children: [
2064
+ /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-label", children: [
1975
2065
  icon ? /* @__PURE__ */ jsx40(Icon, { name: icon, size: 16 }) : null,
1976
2066
  label
1977
2067
  ] }),
1978
- /* @__PURE__ */ jsxs32("span", { className: "pire-kpi-value", children: [
2068
+ /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-value", children: [
1979
2069
  value,
1980
2070
  unit ? /* @__PURE__ */ jsx40("span", { className: "pire-kpi-unit", children: unit }) : null
1981
2071
  ] }),
1982
- delta ? /* @__PURE__ */ jsxs32("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
2072
+ delta ? /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
1983
2073
  deltaDirection ? /* @__PURE__ */ jsx40(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
1984
2074
  delta
1985
2075
  ] }) : null,
@@ -1990,14 +2080,14 @@ function KpiTile({
1990
2080
  }
1991
2081
 
1992
2082
  // src/components/data/ObjectHeader.tsx
1993
- import { jsx as jsx41, jsxs as jsxs33 } from "react/jsx-runtime";
2083
+ import { jsx as jsx41, jsxs as jsxs34 } from "react/jsx-runtime";
1994
2084
  function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions, className, ...rest }) {
1995
- return /* @__PURE__ */ jsxs33("header", { className: cx("pire-objheader", className), ...rest, children: [
2085
+ return /* @__PURE__ */ jsxs34("header", { className: cx("pire-objheader", className), ...rest, children: [
1996
2086
  breadcrumb,
1997
- /* @__PURE__ */ jsxs33("div", { className: "pire-objheader-row", children: [
1998
- /* @__PURE__ */ jsxs33("div", { style: { minWidth: 0 }, children: [
2087
+ /* @__PURE__ */ jsxs34("div", { className: "pire-objheader-row", children: [
2088
+ /* @__PURE__ */ jsxs34("div", { style: { minWidth: 0 }, children: [
1999
2089
  /* @__PURE__ */ jsx41("h1", { className: "pire-objheader-title", children: title }),
2000
- subtitle || id ? /* @__PURE__ */ jsxs33("div", { className: "pire-objheader-sub", children: [
2090
+ subtitle || id ? /* @__PURE__ */ jsxs34("div", { className: "pire-objheader-sub", children: [
2001
2091
  subtitle,
2002
2092
  id ? /* @__PURE__ */ jsx41("span", { className: "pire-objheader-id", children: id }) : null
2003
2093
  ] }) : null
@@ -2005,7 +2095,7 @@ function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions,
2005
2095
  badge,
2006
2096
  actions ? /* @__PURE__ */ jsx41("div", { className: "pire-objheader-actions", children: actions }) : null
2007
2097
  ] }),
2008
- facts?.length ? /* @__PURE__ */ jsx41("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs33("div", { children: [
2098
+ facts?.length ? /* @__PURE__ */ jsx41("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs34("div", { children: [
2009
2099
  /* @__PURE__ */ jsx41("dt", { className: "pire-fact-label", children: fact.label }),
2010
2100
  /* @__PURE__ */ jsx41("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
2011
2101
  ] }, fact.label)) }) : null
@@ -2013,7 +2103,7 @@ function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions,
2013
2103
  }
2014
2104
 
2015
2105
  // src/components/data/FilterBar.tsx
2016
- import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
2106
+ import { jsx as jsx42, jsxs as jsxs35 } from "react/jsx-runtime";
2017
2107
  function FilterBar({
2018
2108
  children,
2019
2109
  activeFilters = [],
@@ -2030,12 +2120,12 @@ function FilterBar({
2030
2120
  const label = useMessage("filterBarLabel", rest["aria-label"]);
2031
2121
  const go = useMessage("filterBarGo", goLabel);
2032
2122
  const clearAll = useMessage("filterBarClearAll", clearAllLabel);
2033
- return /* @__PURE__ */ jsxs34("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
2034
- /* @__PURE__ */ jsxs34("div", { className: "pire-filterbar-controls", children: [
2123
+ return /* @__PURE__ */ jsxs35("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
2124
+ /* @__PURE__ */ jsxs35("div", { className: "pire-filterbar-controls", children: [
2035
2125
  children,
2036
2126
  onGo ? /* @__PURE__ */ jsx42(Button, { variant: "primary", onPress: onGo, children: go }) : null
2037
2127
  ] }),
2038
- activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs34("div", { className: "pire-filterbar-foot", children: [
2128
+ activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs35("div", { className: "pire-filterbar-foot", children: [
2039
2129
  activeFilters.map((filter) => /* @__PURE__ */ jsx42(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
2040
2130
  activeFilters.length && onClear ? /* @__PURE__ */ jsx42(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
2041
2131
  resultLabel ? /* @__PURE__ */ jsx42("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
@@ -2045,7 +2135,7 @@ function FilterBar({
2045
2135
  }
2046
2136
 
2047
2137
  // src/components/data/DescriptionList.tsx
2048
- import { jsx as jsx43, jsxs as jsxs35 } from "react/jsx-runtime";
2138
+ import { jsx as jsx43, jsxs as jsxs36 } from "react/jsx-runtime";
2049
2139
  function DescriptionList({ items, layout = "rows", columns = 3, className, style, ...rest }) {
2050
2140
  return /* @__PURE__ */ jsx43(
2051
2141
  "dl",
@@ -2054,8 +2144,8 @@ function DescriptionList({ items, layout = "rows", columns = 3, className, style
2054
2144
  "data-layout": layout,
2055
2145
  style: { ...layout === "grid" ? { "--pire-dl-cols": columns } : null, ...style },
2056
2146
  ...rest,
2057
- children: items.map((item, i) => /* @__PURE__ */ jsxs35("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
2058
- /* @__PURE__ */ jsxs35("dt", { className: "pire-dl-term", children: [
2147
+ children: items.map((item, i) => /* @__PURE__ */ jsxs36("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
2148
+ /* @__PURE__ */ jsxs36("dt", { className: "pire-dl-term", children: [
2059
2149
  item.label,
2060
2150
  item.hint
2061
2151
  ] }),
@@ -2066,10 +2156,10 @@ function DescriptionList({ items, layout = "rows", columns = 3, className, style
2066
2156
  }
2067
2157
 
2068
2158
  // src/components/data/Timeline.tsx
2069
- import { jsx as jsx44, jsxs as jsxs36 } from "react/jsx-runtime";
2159
+ import { jsx as jsx44, jsxs as jsxs37 } from "react/jsx-runtime";
2070
2160
  function Timeline({ entries, reverse = false, className, ...rest }) {
2071
2161
  const list = reverse ? [...entries].reverse() : entries;
2072
- return /* @__PURE__ */ jsx44("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs36("li", { className: "pire-timeline-item", children: [
2162
+ return /* @__PURE__ */ jsx44("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs37("li", { className: "pire-timeline-item", children: [
2073
2163
  /* @__PURE__ */ jsx44("span", { className: "pire-timeline-time", children: entry.time }),
2074
2164
  /* @__PURE__ */ jsx44("span", { className: "pire-timeline-text", children: entry.event }),
2075
2165
  entry.actor ? /* @__PURE__ */ jsx44("span", { className: "pire-timeline-actor", children: entry.actor }) : null
@@ -2078,9 +2168,9 @@ function Timeline({ entries, reverse = false, className, ...rest }) {
2078
2168
 
2079
2169
  // src/components/data/LinkList.tsx
2080
2170
  import { Button as AriaButton11 } from "react-aria-components";
2081
- import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
2171
+ import { jsx as jsx45, jsxs as jsxs38 } from "react/jsx-runtime";
2082
2172
  function LinkList({ items, onSelect, className, ...rest }) {
2083
- return /* @__PURE__ */ jsx45("div", { className: cx("pire-linklist", className), role: "list", ...rest, children: items.map((item) => /* @__PURE__ */ jsxs37(AriaButton11, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
2173
+ return /* @__PURE__ */ jsx45("div", { className: cx("pire-linklist", className), role: "list", ...rest, children: items.map((item) => /* @__PURE__ */ jsxs38(AriaButton11, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
2084
2174
  item.icon ? /* @__PURE__ */ jsx45(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
2085
2175
  item.key ? /* @__PURE__ */ jsx45("span", { className: "pire-linklist-key", children: item.key }) : null,
2086
2176
  item.text ? /* @__PURE__ */ jsx45("span", { className: "pire-linklist-text", children: item.text }) : null,
@@ -2088,57 +2178,78 @@ function LinkList({ items, onSelect, className, ...rest }) {
2088
2178
  ] }, item.id)) });
2089
2179
  }
2090
2180
 
2181
+ // src/components/layout/PageBand.tsx
2182
+ import { jsx as jsx46 } from "react/jsx-runtime";
2183
+ function PageBand({
2184
+ surface = "card",
2185
+ hasBorder = true,
2186
+ children,
2187
+ className,
2188
+ ...rest
2189
+ }) {
2190
+ return /* @__PURE__ */ jsx46(
2191
+ "div",
2192
+ {
2193
+ className: cx("pire-pageband", className),
2194
+ "data-surface": surface,
2195
+ "data-border": hasBorder ? "true" : void 0,
2196
+ ...rest,
2197
+ children
2198
+ }
2199
+ );
2200
+ }
2201
+
2091
2202
  // src/components/layout/PageHeader.tsx
2092
- import { jsx as jsx46, jsxs as jsxs38 } from "react/jsx-runtime";
2203
+ import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
2093
2204
  function PageHeader({ title, subtitle, actions, className, ...rest }) {
2094
- return /* @__PURE__ */ jsxs38("header", { className: cx("pire-pageheader", className), ...rest, children: [
2095
- /* @__PURE__ */ jsxs38("div", { style: { minWidth: 0 }, children: [
2096
- /* @__PURE__ */ jsx46("h1", { className: "pire-pageheader-title", children: title }),
2097
- subtitle ? /* @__PURE__ */ jsx46("p", { className: "pire-pageheader-sub", children: subtitle }) : null
2205
+ return /* @__PURE__ */ jsxs39("header", { className: cx("pire-pageheader", className), ...rest, children: [
2206
+ /* @__PURE__ */ jsxs39("div", { style: { minWidth: 0 }, children: [
2207
+ /* @__PURE__ */ jsx47("h1", { className: "pire-pageheader-title", children: title }),
2208
+ subtitle ? /* @__PURE__ */ jsx47("p", { className: "pire-pageheader-sub", children: subtitle }) : null
2098
2209
  ] }),
2099
- actions ? /* @__PURE__ */ jsx46("div", { className: "pire-pageheader-actions", children: actions }) : null
2210
+ actions ? /* @__PURE__ */ jsx47("div", { className: "pire-pageheader-actions", children: actions }) : null
2100
2211
  ] });
2101
2212
  }
2102
2213
 
2103
2214
  // src/components/layout/SectionHeader.tsx
2104
- import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
2215
+ import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
2105
2216
  function SectionHeader({ title, meta, actions, className, ...rest }) {
2106
- return /* @__PURE__ */ jsxs39("div", { className: cx("pire-sectionhead", className), ...rest, children: [
2107
- /* @__PURE__ */ jsx47("span", { className: "pire-eyebrow", children: title }),
2108
- meta ? /* @__PURE__ */ jsx47("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
2109
- actions ? /* @__PURE__ */ jsx47("div", { className: "pire-sectionhead-actions", children: actions }) : null
2217
+ return /* @__PURE__ */ jsxs40("div", { className: cx("pire-sectionhead", className), ...rest, children: [
2218
+ /* @__PURE__ */ jsx48("span", { className: "pire-eyebrow", children: title }),
2219
+ meta ? /* @__PURE__ */ jsx48("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
2220
+ actions ? /* @__PURE__ */ jsx48("div", { className: "pire-sectionhead-actions", children: actions }) : null
2110
2221
  ] });
2111
2222
  }
2112
2223
 
2113
2224
  // src/components/layout/SelectionBar.tsx
2114
- import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
2225
+ import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
2115
2226
  function SelectionBar({ count, noun = "record", children, actions, className, ...rest }) {
2116
2227
  if (!count) return null;
2117
- return /* @__PURE__ */ jsxs40("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
2118
- /* @__PURE__ */ jsxs40("span", { className: "pire-selectionbar-count", children: [
2228
+ return /* @__PURE__ */ jsxs41("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
2229
+ /* @__PURE__ */ jsxs41("span", { className: "pire-selectionbar-count", children: [
2119
2230
  count.toLocaleString(),
2120
2231
  " ",
2121
2232
  noun,
2122
2233
  count === 1 ? "" : "s",
2123
2234
  " selected"
2124
2235
  ] }),
2125
- children ? /* @__PURE__ */ jsx48("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
2126
- actions ? /* @__PURE__ */ jsx48("div", { className: "pire-selectionbar-actions", children: actions }) : null
2236
+ children ? /* @__PURE__ */ jsx49("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
2237
+ actions ? /* @__PURE__ */ jsx49("div", { className: "pire-selectionbar-actions", children: actions }) : null
2127
2238
  ] });
2128
2239
  }
2129
2240
 
2130
2241
  // src/components/layout/FooterBar.tsx
2131
- import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
2242
+ import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
2132
2243
  function FooterBar({ note, actions, children, className, ...rest }) {
2133
- return /* @__PURE__ */ jsxs41("footer", { className: cx("pire-footerbar", className), ...rest, children: [
2134
- note ? /* @__PURE__ */ jsx49("span", { className: "pire-footerbar-note", children: note }) : null,
2244
+ return /* @__PURE__ */ jsxs42("footer", { className: cx("pire-footerbar", className), ...rest, children: [
2245
+ note ? /* @__PURE__ */ jsx50("span", { className: "pire-footerbar-note", children: note }) : null,
2135
2246
  children,
2136
- actions ? /* @__PURE__ */ jsx49("div", { className: "pire-footerbar-actions", children: actions }) : null
2247
+ actions ? /* @__PURE__ */ jsx50("div", { className: "pire-footerbar-actions", children: actions }) : null
2137
2248
  ] });
2138
2249
  }
2139
2250
 
2140
2251
  // src/components/patterns/ConfirmDialog.tsx
2141
- import { Fragment as Fragment4, jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
2252
+ import { Fragment as Fragment4, jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
2142
2253
  function ConfirmDialog({
2143
2254
  isOpen,
2144
2255
  title,
@@ -2152,7 +2263,7 @@ function ConfirmDialog({
2152
2263
  onConfirm,
2153
2264
  onCancel
2154
2265
  }) {
2155
- return /* @__PURE__ */ jsxs42(
2266
+ return /* @__PURE__ */ jsxs43(
2156
2267
  Dialog,
2157
2268
  {
2158
2269
  isOpen,
@@ -2162,12 +2273,12 @@ function ConfirmDialog({
2162
2273
  onClose: onCancel,
2163
2274
  isDismissable: !isBusy,
2164
2275
  showClose: false,
2165
- footer: /* @__PURE__ */ jsxs42(Fragment4, { children: [
2166
- /* @__PURE__ */ jsx50(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
2167
- /* @__PURE__ */ jsx50(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
2276
+ footer: /* @__PURE__ */ jsxs43(Fragment4, { children: [
2277
+ /* @__PURE__ */ jsx51(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
2278
+ /* @__PURE__ */ jsx51(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
2168
2279
  ] }),
2169
2280
  children: [
2170
- consequence ? /* @__PURE__ */ jsx50(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
2281
+ consequence ? /* @__PURE__ */ jsx51(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
2171
2282
  children
2172
2283
  ]
2173
2284
  }
@@ -2176,10 +2287,10 @@ function ConfirmDialog({
2176
2287
 
2177
2288
  // src/components/patterns/SidePanel.tsx
2178
2289
  import { ModalOverlay as ModalOverlay2, Modal as Modal2, Dialog as AriaDialog3, Heading as Heading4 } from "react-aria-components";
2179
- import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
2290
+ import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
2180
2291
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
2181
2292
  const msg = usePireMessages();
2182
- return /* @__PURE__ */ jsx51(
2293
+ return /* @__PURE__ */ jsx52(
2183
2294
  ModalOverlay2,
2184
2295
  {
2185
2296
  className: "pire-sidepanel-overlay",
@@ -2188,28 +2299,28 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
2188
2299
  onOpenChange: (o) => {
2189
2300
  if (!o) onClose?.();
2190
2301
  },
2191
- children: /* @__PURE__ */ jsx51(Modal2, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs43(AriaDialog3, { className: "pire-dialog", style: { height: "100%" }, children: [
2192
- /* @__PURE__ */ jsxs43("header", { className: "pire-dialog-head", children: [
2193
- /* @__PURE__ */ jsxs43("div", { style: { flex: 1, minWidth: 0 }, children: [
2194
- /* @__PURE__ */ jsx51(Heading4, { slot: "title", className: "pire-dialog-title", children: title }),
2195
- subtitle ? /* @__PURE__ */ jsx51("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
2302
+ children: /* @__PURE__ */ jsx52(Modal2, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs44(AriaDialog3, { className: "pire-dialog", style: { height: "100%" }, children: [
2303
+ /* @__PURE__ */ jsxs44("header", { className: "pire-dialog-head", children: [
2304
+ /* @__PURE__ */ jsxs44("div", { style: { flex: 1, minWidth: 0 }, children: [
2305
+ /* @__PURE__ */ jsx52(Heading4, { slot: "title", className: "pire-dialog-title", children: title }),
2306
+ subtitle ? /* @__PURE__ */ jsx52("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
2196
2307
  ] }),
2197
- /* @__PURE__ */ jsx51(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
2308
+ /* @__PURE__ */ jsx52(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
2198
2309
  ] }),
2199
- /* @__PURE__ */ jsx51("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
2200
- footer ? /* @__PURE__ */ jsx51("footer", { className: "pire-dialog-foot", children: footer }) : null
2310
+ /* @__PURE__ */ jsx52("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
2311
+ footer ? /* @__PURE__ */ jsx52("footer", { className: "pire-dialog-foot", children: footer }) : null
2201
2312
  ] }) })
2202
2313
  }
2203
2314
  );
2204
2315
  }
2205
2316
 
2206
2317
  // src/components/patterns/EmptyState.tsx
2207
- import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
2318
+ import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
2208
2319
  function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
2209
- return /* @__PURE__ */ jsxs44("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
2210
- /* @__PURE__ */ jsx52(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
2211
- title ? /* @__PURE__ */ jsx52("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
2212
- children ? /* @__PURE__ */ jsx52("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
2320
+ return /* @__PURE__ */ jsxs45("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
2321
+ /* @__PURE__ */ jsx53(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
2322
+ title ? /* @__PURE__ */ jsx53("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
2323
+ children ? /* @__PURE__ */ jsx53("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
2213
2324
  action
2214
2325
  ] });
2215
2326
  }
@@ -2251,6 +2362,7 @@ export {
2251
2362
  MultiComboBox,
2252
2363
  NumberField,
2253
2364
  ObjectHeader,
2365
+ PageBand,
2254
2366
  PageHeader,
2255
2367
  Pagination,
2256
2368
  PireIntlProvider,