@orianatech/pire 0.8.0 → 0.10.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
@@ -817,6 +817,7 @@ var enMessages = {
817
817
  datePickerOpenCalendar: "Open calendar",
818
818
  datePickerPreviousMonth: "Previous month",
819
819
  datePickerNextMonth: "Next month",
820
+ dateRangePresetsLabel: "Date range shortcuts",
820
821
  numberFieldIncrease: "Increase",
821
822
  numberFieldDecrease: "Decrease",
822
823
  valueHelpFieldClear: "Clear selection",
@@ -830,7 +831,11 @@ var enMessages = {
830
831
  paginationPrevious: "Previous page",
831
832
  paginationNext: "Next page",
832
833
  paginationRowsPerPage: "Rows per page",
833
- sideNavLabel: "Main navigation"
834
+ sideNavLabel: "Main navigation",
835
+ fileUploadChoose: "Choose files",
836
+ fileUploadRemoveNamed: "Remove {name}",
837
+ fileUploadUploading: "Uploading",
838
+ fileDropZonePrompt: "Drag files here, or choose them"
834
839
  };
835
840
  var esMessages = {
836
841
  filterBarLabel: "Filtros",
@@ -849,6 +854,7 @@ var esMessages = {
849
854
  datePickerOpenCalendar: "Abrir calendario",
850
855
  datePickerPreviousMonth: "Mes anterior",
851
856
  datePickerNextMonth: "Mes siguiente",
857
+ dateRangePresetsLabel: "Atajos de rango de fechas",
852
858
  numberFieldIncrease: "Aumentar",
853
859
  numberFieldDecrease: "Disminuir",
854
860
  valueHelpFieldClear: "Limpiar selecci\xF3n",
@@ -862,7 +868,11 @@ var esMessages = {
862
868
  paginationPrevious: "P\xE1gina anterior",
863
869
  paginationNext: "P\xE1gina siguiente",
864
870
  paginationRowsPerPage: "Filas por p\xE1gina",
865
- sideNavLabel: "Navegaci\xF3n principal"
871
+ sideNavLabel: "Navegaci\xF3n principal",
872
+ fileUploadChoose: "Elegir archivos",
873
+ fileUploadRemoveNamed: "Quitar {name}",
874
+ fileUploadUploading: "Subiendo",
875
+ fileDropZonePrompt: "Arrastr\xE1 archivos ac\xE1, o elegilos"
866
876
  };
867
877
 
868
878
  // src/i18n/PireIntlProvider.tsx
@@ -1243,6 +1253,138 @@ function DatePicker({
1243
1253
  ] });
1244
1254
  }
1245
1255
 
1256
+ // src/components/forms/DateRangePicker.tsx
1257
+ import {
1258
+ DateRangePicker as AriaDateRangePicker,
1259
+ Label as Label9,
1260
+ Group as Group7,
1261
+ DateInput as DateInput2,
1262
+ DateSegment as DateSegment2,
1263
+ Button as AriaButton9,
1264
+ Popover as Popover5,
1265
+ Dialog as AriaDialog2,
1266
+ RangeCalendar,
1267
+ CalendarGrid as CalendarGrid2,
1268
+ CalendarGridHeader as CalendarGridHeader2,
1269
+ CalendarHeaderCell as CalendarHeaderCell2,
1270
+ CalendarGridBody as CalendarGridBody2,
1271
+ CalendarCell as CalendarCell2,
1272
+ Heading as Heading3,
1273
+ Text as Text10,
1274
+ FieldError as FieldError9
1275
+ } from "react-aria-components";
1276
+ import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
1277
+ function rangeLengthInDays(range) {
1278
+ return range.end.toDate("UTC").getTime() / 864e5 - range.start.toDate("UTC").getTime() / 864e5 + 1;
1279
+ }
1280
+ function DateRangePicker({
1281
+ label,
1282
+ description,
1283
+ errorMessage,
1284
+ maxRangeDays,
1285
+ presets,
1286
+ size = "md",
1287
+ fullWidth = true,
1288
+ startName,
1289
+ endName,
1290
+ className,
1291
+ style,
1292
+ ...rest
1293
+ }) {
1294
+ const msg = usePireMessages();
1295
+ const current = rest.value ?? rest.defaultValue ?? null;
1296
+ const tooLong = maxRangeDays != null && current != null && rangeLengthInDays(current) > maxRangeDays;
1297
+ return /* @__PURE__ */ jsxs20(
1298
+ AriaDateRangePicker,
1299
+ {
1300
+ className: cx("pire-field", className),
1301
+ style,
1302
+ startName,
1303
+ endName,
1304
+ validationBehavior: "aria",
1305
+ ...rest,
1306
+ isInvalid: rest.isInvalid || tooLong,
1307
+ children: [
1308
+ label ? /* @__PURE__ */ jsxs20(Label9, { className: "pire-field-label", children: [
1309
+ label,
1310
+ rest.isRequired ? /* @__PURE__ */ jsx26("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
1311
+ ] }) : null,
1312
+ /* @__PURE__ */ jsxs20(
1313
+ Group7,
1314
+ {
1315
+ className: "pire-control pire-daterange-control",
1316
+ "data-size": size,
1317
+ "data-full-width": String(fullWidth),
1318
+ "data-invalid": rest.isInvalid || tooLong ? "true" : void 0,
1319
+ "data-readonly": rest.isReadOnly ? "true" : void 0,
1320
+ children: [
1321
+ /* @__PURE__ */ jsx26(DateInput2, { slot: "start", className: "pire-datefield", children: (segment) => /* @__PURE__ */ jsx26(DateSegment2, { segment, className: "pire-datesegment" }) }),
1322
+ /* @__PURE__ */ jsx26("span", { "aria-hidden": "true", className: "pire-daterange-dash", children: "\u2013" }),
1323
+ /* @__PURE__ */ jsx26(DateInput2, { slot: "end", className: "pire-datefield", children: (segment) => /* @__PURE__ */ jsx26(DateSegment2, { segment, className: "pire-datesegment" }) }),
1324
+ /* @__PURE__ */ jsx26(
1325
+ AriaButton9,
1326
+ {
1327
+ className: "pire-iconbtn",
1328
+ "data-size": "sm",
1329
+ "aria-label": msg.datePickerOpenCalendar,
1330
+ style: { width: 24, height: 24 },
1331
+ children: /* @__PURE__ */ jsx26(Icon, { name: "calendar", size: 16 })
1332
+ }
1333
+ )
1334
+ ]
1335
+ }
1336
+ ),
1337
+ description ? /* @__PURE__ */ jsx26(Text10, { slot: "description", className: "pire-field-hint", children: description }) : null,
1338
+ /* @__PURE__ */ jsx26(FieldError9, { className: "pire-field-error", children: errorMessage }),
1339
+ /* @__PURE__ */ jsx26(Popover5, { className: "pire-popover", children: /* @__PURE__ */ jsxs20(AriaDialog2, { className: "pire-daterange-dialog", children: [
1340
+ presets?.length ? (
1341
+ // Before the calendar in the DOM, so keyboard users reach the shortcut without
1342
+ // arrowing through a month first.
1343
+ /* @__PURE__ */ jsx26("div", { className: "pire-daterange-presets", role: "group", "aria-label": msg.dateRangePresetsLabel, children: presets.map((preset) => /* @__PURE__ */ jsx26(
1344
+ AriaButton9,
1345
+ {
1346
+ className: "pire-daterange-preset",
1347
+ onPress: () => rest.onChange?.(preset.range()),
1348
+ children: preset.label
1349
+ },
1350
+ preset.id
1351
+ )) })
1352
+ ) : null,
1353
+ /* @__PURE__ */ jsxs20(RangeCalendar, { className: "pire-calendar", children: [
1354
+ /* @__PURE__ */ jsxs20("header", { className: "pire-calendar-head", children: [
1355
+ /* @__PURE__ */ jsx26(
1356
+ AriaButton9,
1357
+ {
1358
+ slot: "previous",
1359
+ className: "pire-iconbtn",
1360
+ "data-size": "sm",
1361
+ "aria-label": msg.datePickerPreviousMonth,
1362
+ children: /* @__PURE__ */ jsx26(Icon, { name: "chevron-left", size: 16 })
1363
+ }
1364
+ ),
1365
+ /* @__PURE__ */ jsx26(Heading3, { className: "pire-calendar-title" }),
1366
+ /* @__PURE__ */ jsx26(
1367
+ AriaButton9,
1368
+ {
1369
+ slot: "next",
1370
+ className: "pire-iconbtn",
1371
+ "data-size": "sm",
1372
+ "aria-label": msg.datePickerNextMonth,
1373
+ children: /* @__PURE__ */ jsx26(Icon, { name: "chevron-right", size: 16 })
1374
+ }
1375
+ )
1376
+ ] }),
1377
+ /* @__PURE__ */ jsxs20(CalendarGrid2, { className: "pire-calendar-grid", children: [
1378
+ /* @__PURE__ */ jsx26(CalendarGridHeader2, { children: (day) => /* @__PURE__ */ jsx26(CalendarHeaderCell2, { children: day }) }),
1379
+ /* @__PURE__ */ jsx26(CalendarGridBody2, { children: (date) => /* @__PURE__ */ jsx26(CalendarCell2, { date, className: "pire-calendar-cell" }) })
1380
+ ] })
1381
+ ] })
1382
+ ] }) })
1383
+ ]
1384
+ }
1385
+ );
1386
+ }
1387
+
1246
1388
  // src/components/forms/ValueHelpField.tsx
1247
1389
  import * as React9 from "react";
1248
1390
 
@@ -1250,8 +1392,8 @@ import * as React9 from "react";
1250
1392
  import * as React8 from "react";
1251
1393
 
1252
1394
  // src/components/feedback/Dialog.tsx
1253
- import { ModalOverlay, Modal, Dialog as AriaDialog2, Heading as Heading3 } from "react-aria-components";
1254
- import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
1395
+ import { ModalOverlay, Modal, Dialog as AriaDialog3, Heading as Heading4 } from "react-aria-components";
1396
+ import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
1255
1397
  function Dialog({
1256
1398
  isOpen,
1257
1399
  onOpenChange,
@@ -1271,7 +1413,7 @@ function Dialog({
1271
1413
  onClose?.();
1272
1414
  onOpenChange?.(false);
1273
1415
  };
1274
- return /* @__PURE__ */ jsx26(
1416
+ return /* @__PURE__ */ jsx27(
1275
1417
  ModalOverlay,
1276
1418
  {
1277
1419
  className: "pire-modal-overlay",
@@ -1280,16 +1422,16 @@ function Dialog({
1280
1422
  onOpenChange: (o) => {
1281
1423
  if (!o) close();
1282
1424
  },
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: [
1286
- /* @__PURE__ */ jsx26(Heading3, { slot: "title", className: "pire-dialog-title", children: title }),
1287
- subtitle ? /* @__PURE__ */ jsx26("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
1425
+ children: /* @__PURE__ */ jsx27(Modal, { className: cx("pire-modal", className), "data-size": size, style, children: /* @__PURE__ */ jsxs21(AriaDialog3, { className: "pire-dialog", children: [
1426
+ title ? /* @__PURE__ */ jsxs21("header", { className: "pire-dialog-head", children: [
1427
+ /* @__PURE__ */ jsxs21("div", { style: { flex: 1, minWidth: 0 }, children: [
1428
+ /* @__PURE__ */ jsx27(Heading4, { slot: "title", className: "pire-dialog-title", children: title }),
1429
+ subtitle ? /* @__PURE__ */ jsx27("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
1288
1430
  ] }),
1289
- showClose ? /* @__PURE__ */ jsx26(IconButton, { icon: "x", label: msg.dialogClose, size: "sm", onPress: close }) : null
1431
+ showClose ? /* @__PURE__ */ jsx27(IconButton, { icon: "x", label: msg.dialogClose, size: "sm", onPress: close }) : null
1290
1432
  ] }) : null,
1291
- /* @__PURE__ */ jsx26("div", { className: "pire-dialog-body", children }),
1292
- footer ? /* @__PURE__ */ jsx26("footer", { className: "pire-dialog-foot", children: footer }) : null
1433
+ /* @__PURE__ */ jsx27("div", { className: "pire-dialog-body", children }),
1434
+ footer ? /* @__PURE__ */ jsx27("footer", { className: "pire-dialog-foot", children: footer }) : null
1293
1435
  ] }) })
1294
1436
  }
1295
1437
  );
@@ -1306,9 +1448,9 @@ import {
1306
1448
  } from "react-aria-components";
1307
1449
 
1308
1450
  // src/components/feedback/Skeleton.tsx
1309
- import { jsx as jsx27 } from "react/jsx-runtime";
1451
+ import { jsx as jsx28 } from "react/jsx-runtime";
1310
1452
  function Skeleton({ shape = "text", width, height, className, style, ...rest }) {
1311
- return /* @__PURE__ */ jsx27(
1453
+ return /* @__PURE__ */ jsx28(
1312
1454
  "div",
1313
1455
  {
1314
1456
  className: cx("pire-skeleton", className),
@@ -1322,7 +1464,7 @@ function Skeleton({ shape = "text", width, height, className, style, ...rest })
1322
1464
  var BAR_WIDTHS = ["72%", "54%", "86%", "63%"];
1323
1465
  function SkeletonTableRow({ columns, density = "regular", className, style, ...rest }) {
1324
1466
  const cells = typeof columns === "number" ? Array.from({ length: columns }, () => ({})) : columns;
1325
- return /* @__PURE__ */ jsx27(
1467
+ return /* @__PURE__ */ jsx28(
1326
1468
  "div",
1327
1469
  {
1328
1470
  className: cx("pire-skeleton-row", className),
@@ -1334,13 +1476,13 @@ function SkeletonTableRow({ columns, density = "regular", className, style, ...r
1334
1476
  const align = c.numeric ? "right" : c.align ?? "left";
1335
1477
  return (
1336
1478
  // biome-ignore lint/suspicious/noArrayIndexKey: columns are positional and never reordered.
1337
- /* @__PURE__ */ jsx27(
1479
+ /* @__PURE__ */ jsx28(
1338
1480
  "div",
1339
1481
  {
1340
1482
  className: "pire-skeleton-cell",
1341
1483
  "data-align": align,
1342
1484
  style: { width: c.width, flex: c.width ? "0 0 auto" : void 0 },
1343
- children: /* @__PURE__ */ jsx27(Skeleton, { width: BAR_WIDTHS[i % BAR_WIDTHS.length] })
1485
+ children: /* @__PURE__ */ jsx28(Skeleton, { width: BAR_WIDTHS[i % BAR_WIDTHS.length] })
1344
1486
  },
1345
1487
  i
1346
1488
  )
@@ -1351,7 +1493,7 @@ function SkeletonTableRow({ columns, density = "regular", className, style, ...r
1351
1493
  }
1352
1494
 
1353
1495
  // src/components/data/DataTable.tsx
1354
- import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
1496
+ import { jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
1355
1497
  function DataTable({
1356
1498
  columns,
1357
1499
  rows,
@@ -1383,14 +1525,14 @@ function DataTable({
1383
1525
  ...columns.map((c) => ({ width: c.width, align: c.align, numeric: c.numeric }))
1384
1526
  ];
1385
1527
  const body = isLoading ? [] : rows;
1386
- return /* @__PURE__ */ jsx28(
1528
+ return /* @__PURE__ */ jsx29(
1387
1529
  "div",
1388
1530
  {
1389
1531
  className: cx("pire-table-wrap", className),
1390
1532
  style,
1391
1533
  "data-loading": isLoading ? "true" : void 0,
1392
1534
  "aria-busy": isLoading ? "true" : void 0,
1393
- children: /* @__PURE__ */ jsxs21(
1535
+ children: /* @__PURE__ */ jsxs22(
1394
1536
  Table,
1395
1537
  {
1396
1538
  className: "pire-table",
@@ -1407,9 +1549,9 @@ function DataTable({
1407
1549
  if (row) onRowAction(row);
1408
1550
  } : void 0,
1409
1551
  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(
1552
+ /* @__PURE__ */ jsxs22(TableHeader, { className: "pire-thead-row", children: [
1553
+ selectable ? /* @__PURE__ */ jsx29(Column, { className: "pire-th", width: 44, children: /* @__PURE__ */ jsx29(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectAll }) }) : null,
1554
+ columns.map((c, i) => /* @__PURE__ */ jsx29(
1413
1555
  Column,
1414
1556
  {
1415
1557
  id: c.key,
@@ -1419,9 +1561,9 @@ function DataTable({
1419
1561
  width: c.width,
1420
1562
  "data-align": c.numeric || c.align === "right" ? "right" : c.align,
1421
1563
  "data-allows-sorting": c.sortable ? "true" : void 0,
1422
- children: /* @__PURE__ */ jsxs21("span", { className: "pire-th-inner", children: [
1564
+ children: /* @__PURE__ */ jsxs22("span", { className: "pire-th-inner", children: [
1423
1565
  c.label,
1424
- c.sortable ? /* @__PURE__ */ jsx28(
1566
+ c.sortable ? /* @__PURE__ */ jsx29(
1425
1567
  Icon,
1426
1568
  {
1427
1569
  size: 12,
@@ -1434,15 +1576,15 @@ function DataTable({
1434
1576
  c.key
1435
1577
  ))
1436
1578
  ] }),
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 }),
1579
+ /* @__PURE__ */ jsx29(TableBody, { renderEmptyState: () => isLoading ? /* @__PURE__ */ jsxs22("div", { className: "pire-table-loading", role: "status", "aria-live": "polite", children: [
1580
+ /* @__PURE__ */ jsx29("span", { className: "pire-sr-only", children: loadingLabel ?? msg.dataTableLoading }),
1439
1581
  Array.from({ length: skeletonRows }, (_, i) => (
1440
1582
  // biome-ignore lint/suspicious/noArrayIndexKey: placeholder rows are positional.
1441
- /* @__PURE__ */ jsx28(SkeletonTableRow, { columns: skeletonColumns, density }, i)
1583
+ /* @__PURE__ */ jsx29(SkeletonTableRow, { columns: skeletonColumns, density }, i)
1442
1584
  ))
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(
1585
+ ] }) : /* @__PURE__ */ jsx29("div", { className: "pire-table-empty", children: emptyLabel }), children: body.map((row) => /* @__PURE__ */ jsxs22(Row, { id: row.id, className: "pire-tr", "data-pressable": onRowAction ? "true" : void 0, children: [
1586
+ selectable ? /* @__PURE__ */ jsx29(Cell, { className: "pire-td", children: /* @__PURE__ */ jsx29(Checkbox, { slot: "selection", "aria-label": msg.dataTableSelectRow }) }) : null,
1587
+ columns.map((c) => /* @__PURE__ */ jsx29(
1446
1588
  Cell,
1447
1589
  {
1448
1590
  className: "pire-td",
@@ -1461,7 +1603,7 @@ function DataTable({
1461
1603
  }
1462
1604
 
1463
1605
  // src/components/patterns/ValueHelpDialog.tsx
1464
- import { jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
1606
+ import { jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
1465
1607
  function ValueHelpDialog({
1466
1608
  isOpen,
1467
1609
  title = "Select a record",
@@ -1482,16 +1624,16 @@ function ValueHelpDialog({
1482
1624
  if (!q) return rows;
1483
1625
  return rows.filter((row) => Object.values(row).some((v) => String(v).toLowerCase().includes(q)));
1484
1626
  }, [rows, query]);
1485
- return /* @__PURE__ */ jsx29(
1627
+ return /* @__PURE__ */ jsx30(
1486
1628
  Dialog,
1487
1629
  {
1488
1630
  isOpen,
1489
1631
  size: "lg",
1490
1632
  title,
1491
1633
  onClose,
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(
1634
+ footer: /* @__PURE__ */ jsx30(Button, { variant: "tertiary", onPress: onClose, children: msg.valueHelpDialogCancel }),
1635
+ children: /* @__PURE__ */ jsxs23("div", { style: { display: "flex", flexDirection: "column", gap: "var(--sp-3)" }, children: [
1636
+ /* @__PURE__ */ jsx30(
1495
1637
  Input,
1496
1638
  {
1497
1639
  "aria-label": msg.valueHelpDialogSearch,
@@ -1503,7 +1645,7 @@ function ValueHelpDialog({
1503
1645
  autoFocus: true
1504
1646
  }
1505
1647
  ),
1506
- /* @__PURE__ */ jsx29(
1648
+ /* @__PURE__ */ jsx30(
1507
1649
  DataTable,
1508
1650
  {
1509
1651
  "aria-label": typeof title === "string" ? title : "Records",
@@ -1523,7 +1665,7 @@ function ValueHelpDialog({
1523
1665
  }
1524
1666
 
1525
1667
  // src/components/forms/ValueHelpField.tsx
1526
- import { jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
1668
+ import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
1527
1669
  var defaultFormat = (row) => [row.id, row.name ?? row.label ?? row.text].filter(Boolean).join(" \u2014 ");
1528
1670
  function ValueHelpField({
1529
1671
  label,
@@ -1545,9 +1687,9 @@ function ValueHelpField({
1545
1687
  }) {
1546
1688
  const msg = usePireMessages();
1547
1689
  const [open, setOpen] = React9.useState(false);
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(
1690
+ return /* @__PURE__ */ jsxs24("div", { className: cx(className), style, children: [
1691
+ /* @__PURE__ */ jsxs24("div", { style: { display: "flex", gap: "var(--sp-2)", alignItems: "flex-end" }, children: [
1692
+ /* @__PURE__ */ jsx31(
1551
1693
  Input,
1552
1694
  {
1553
1695
  label,
@@ -1561,7 +1703,7 @@ function ValueHelpField({
1561
1703
  errorMessage
1562
1704
  }
1563
1705
  ),
1564
- allowsClear && value ? /* @__PURE__ */ jsx30(
1706
+ allowsClear && value ? /* @__PURE__ */ jsx31(
1565
1707
  IconButton,
1566
1708
  {
1567
1709
  icon: "x",
@@ -1571,7 +1713,7 @@ function ValueHelpField({
1571
1713
  onPress: () => onChange?.(null)
1572
1714
  }
1573
1715
  ) : null,
1574
- /* @__PURE__ */ jsx30(
1716
+ /* @__PURE__ */ jsx31(
1575
1717
  IconButton,
1576
1718
  {
1577
1719
  icon: "search",
@@ -1582,7 +1724,7 @@ function ValueHelpField({
1582
1724
  }
1583
1725
  )
1584
1726
  ] }),
1585
- /* @__PURE__ */ jsx30(
1727
+ /* @__PURE__ */ jsx31(
1586
1728
  ValueHelpDialog,
1587
1729
  {
1588
1730
  isOpen: open,
@@ -1596,8 +1738,165 @@ function ValueHelpField({
1596
1738
  ] });
1597
1739
  }
1598
1740
 
1741
+ // src/components/forms/FileUpload.tsx
1742
+ import * as React10 from "react";
1743
+ import { FileTrigger, Text as Text11 } from "react-aria-components";
1744
+
1745
+ // src/components/feedback/ProgressBar.tsx
1746
+ import { ProgressBar as AriaProgressBar, Label as Label10 } from "react-aria-components";
1747
+ import { Fragment as Fragment2, jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
1748
+ function ProgressBar({
1749
+ value = 0,
1750
+ minValue = 0,
1751
+ maxValue = 100,
1752
+ label,
1753
+ showValue = true,
1754
+ isIndeterminate,
1755
+ status = "informative",
1756
+ size = "md",
1757
+ className,
1758
+ style
1759
+ }) {
1760
+ return /* @__PURE__ */ jsx32(
1761
+ AriaProgressBar,
1762
+ {
1763
+ className: cx("pire-progress", className),
1764
+ "data-status": status,
1765
+ "data-size": size,
1766
+ value,
1767
+ minValue,
1768
+ maxValue,
1769
+ isIndeterminate,
1770
+ style,
1771
+ children: ({ percentage, valueText }) => /* @__PURE__ */ jsxs25(Fragment2, { children: [
1772
+ label || showValue ? /* @__PURE__ */ jsxs25("div", { className: "pire-progress-head", children: [
1773
+ label ? /* @__PURE__ */ jsx32(Label10, { children: label }) : /* @__PURE__ */ jsx32("span", {}),
1774
+ showValue && !isIndeterminate ? /* @__PURE__ */ jsx32("span", { className: "pire-numeric", children: valueText }) : null
1775
+ ] }) : null,
1776
+ /* @__PURE__ */ jsx32("div", { className: "pire-progress-track", children: /* @__PURE__ */ jsx32("div", { className: "pire-progress-fill", style: { width: `${isIndeterminate ? 40 : percentage}%` } }) })
1777
+ ] })
1778
+ }
1779
+ );
1780
+ }
1781
+
1782
+ // src/components/forms/FileUpload.tsx
1783
+ import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
1784
+ var isImage = (file) => file.type.startsWith("image/");
1785
+ function formatFileSize(bytes) {
1786
+ if (bytes < 1024) return `${bytes} B`;
1787
+ if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024).toLocaleString()} KB`;
1788
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1789
+ }
1790
+ function screenFiles(files, { maxSize, acceptedFileTypes }) {
1791
+ const accepted = [];
1792
+ const rejected = [];
1793
+ for (const file of files) {
1794
+ if (maxSize != null && file.size > maxSize) {
1795
+ rejected.push({ file, reason: "size" });
1796
+ continue;
1797
+ }
1798
+ if (acceptedFileTypes?.length) {
1799
+ const ok = acceptedFileTypes.some((t) => t.startsWith(".") ? file.name.toLowerCase().endsWith(t.toLowerCase()) : t.endsWith("/*") ? file.type.startsWith(t.slice(0, -1)) : file.type === t);
1800
+ if (!ok) {
1801
+ rejected.push({ file, reason: "type" });
1802
+ continue;
1803
+ }
1804
+ }
1805
+ accepted.push(file);
1806
+ }
1807
+ return { accepted, rejected };
1808
+ }
1809
+ function FileUpload({
1810
+ label,
1811
+ value,
1812
+ defaultValue,
1813
+ onChange,
1814
+ acceptedFileTypes,
1815
+ allowsMultiple,
1816
+ maxSize,
1817
+ onError,
1818
+ showPreview = true,
1819
+ uploadProgress,
1820
+ chooseLabel,
1821
+ description,
1822
+ errorMessage,
1823
+ isInvalid,
1824
+ isDisabled,
1825
+ isReadOnly,
1826
+ isRequired,
1827
+ fullWidth = true,
1828
+ className,
1829
+ style
1830
+ }) {
1831
+ const msg = usePireMessages();
1832
+ const [uncontrolled, setUncontrolled] = React10.useState(defaultValue ?? []);
1833
+ const files = value ?? uncontrolled;
1834
+ const created = React10.useRef([]);
1835
+ React10.useEffect(() => () => {
1836
+ for (const url of created.current) URL.revokeObjectURL(url);
1837
+ }, []);
1838
+ const commit = (next) => {
1839
+ if (value === void 0) setUncontrolled(next);
1840
+ onChange?.(next);
1841
+ };
1842
+ const accept = (picked) => {
1843
+ if (!picked || isDisabled || isReadOnly) return;
1844
+ const { accepted, rejected } = screenFiles([...picked], { maxSize, acceptedFileTypes });
1845
+ if (rejected.length) onError?.(rejected);
1846
+ if (!accepted.length) return;
1847
+ const wrapped = accepted.map((file) => {
1848
+ const previewUrl = showPreview && isImage(file) ? URL.createObjectURL(file) : void 0;
1849
+ if (previewUrl) created.current.push(previewUrl);
1850
+ return { file, previewUrl };
1851
+ });
1852
+ commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
1853
+ };
1854
+ const remove = (target) => commit(files.filter((f) => f.file !== target));
1855
+ return /* @__PURE__ */ jsxs26(
1856
+ "div",
1857
+ {
1858
+ className: cx("pire-field", "pire-fileupload", className),
1859
+ style,
1860
+ "data-full-width": String(fullWidth),
1861
+ "data-invalid": isInvalid ? "true" : void 0,
1862
+ children: [
1863
+ label ? /* @__PURE__ */ jsxs26("span", { className: "pire-field-label", children: [
1864
+ label,
1865
+ isRequired ? /* @__PURE__ */ jsx33("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
1866
+ ] }) : null,
1867
+ /* @__PURE__ */ jsx33(
1868
+ FileTrigger,
1869
+ {
1870
+ acceptedFileTypes,
1871
+ allowsMultiple,
1872
+ onSelect: accept,
1873
+ children: /* @__PURE__ */ jsx33(Button, { icon: "paperclip", isDisabled: isDisabled || isReadOnly, children: chooseLabel ?? msg.fileUploadChoose })
1874
+ }
1875
+ ),
1876
+ files.length ? /* @__PURE__ */ jsx33("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs26("li", { className: "pire-fileupload-item", children: [
1877
+ previewUrl ? /* @__PURE__ */ jsx33("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx33(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
1878
+ /* @__PURE__ */ jsx33("span", { className: "pire-fileupload-name", children: file.name }),
1879
+ /* @__PURE__ */ jsx33("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
1880
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx33(
1881
+ IconButton,
1882
+ {
1883
+ icon: "x",
1884
+ size: "sm",
1885
+ label: msg.fileUploadRemoveNamed.replace("{name}", file.name),
1886
+ onPress: () => remove(file)
1887
+ }
1888
+ )
1889
+ ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
1890
+ uploadProgress != null ? /* @__PURE__ */ jsx33(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
1891
+ description ? /* @__PURE__ */ jsx33(Text11, { slot: "description", className: "pire-field-hint", children: description }) : null,
1892
+ isInvalid && errorMessage ? /* @__PURE__ */ jsx33("span", { className: "pire-field-error", children: errorMessage }) : null
1893
+ ]
1894
+ }
1895
+ );
1896
+ }
1897
+
1599
1898
  // src/components/navigation/ShellBar.tsx
1600
- import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
1899
+ import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
1601
1900
  var initials2 = (name) => name.trim().split(/\s+/).slice(0, 2).map((p) => p[0]).join("").toUpperCase();
1602
1901
  function ShellBar({
1603
1902
  product,
@@ -1612,22 +1911,88 @@ function ShellBar({
1612
1911
  className,
1613
1912
  ...rest
1614
1913
  }) {
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,
1914
+ return /* @__PURE__ */ jsxs27("header", { className: cx("pire-shellbar", className), ...rest, children: [
1915
+ onMenu ? /* @__PURE__ */ jsx34(IconButton, { icon: "menu", label: menuLabel, variant: "inverse", size: "sm", onPress: onMenu }) : null,
1916
+ monogram ? /* @__PURE__ */ jsx34("span", { className: "pire-shellbar-mono", "aria-hidden": "true", children: monogram }) : null,
1917
+ product ? /* @__PURE__ */ jsx34("span", { className: "pire-shellbar-product", children: product }) : null,
1918
+ title ? /* @__PURE__ */ jsx34("span", { className: "pire-shellbar-title", children: title }) : null,
1919
+ /* @__PURE__ */ jsx34("span", { className: "pire-shellbar-spacer" }),
1920
+ onSearch ? /* @__PURE__ */ jsx34(IconButton, { icon: "search", label: searchLabel, variant: "inverse", size: "sm", onPress: onSearch }) : null,
1622
1921
  actions,
1623
- user ? /* @__PURE__ */ jsx31("span", { className: "pire-avatar", title: user, "aria-label": user, role: "img", children: initials2(user) }) : null
1922
+ user ? /* @__PURE__ */ jsx34("span", { className: "pire-avatar", title: user, "aria-label": user, role: "img", children: initials2(user) }) : null
1624
1923
  ] });
1625
1924
  }
1626
1925
 
1627
1926
  // src/components/navigation/SideNav.tsx
1628
- import * as React10 from "react";
1629
- import { Button as AriaButton9, Disclosure, DisclosureGroup, DisclosurePanel } from "react-aria-components";
1630
- import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
1927
+ import * as React11 from "react";
1928
+ import {
1929
+ Button as AriaButton10,
1930
+ Disclosure,
1931
+ DisclosureGroup,
1932
+ DisclosurePanel,
1933
+ MenuTrigger,
1934
+ Popover as Popover6
1935
+ } from "react-aria-components";
1936
+
1937
+ // src/components/navigation/Menu.tsx
1938
+ import {
1939
+ Menu as AriaMenu,
1940
+ MenuItem as AriaMenuItem,
1941
+ MenuSection as AriaMenuSection,
1942
+ Separator as AriaSeparator2,
1943
+ Header
1944
+ } from "react-aria-components";
1945
+ import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
1946
+ function Menu({ minWidth, className, style, ...rest }) {
1947
+ const width = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
1948
+ const menuStyle = width == null ? style : { ["--pire-menu-min-w"]: width, ...style };
1949
+ return /* @__PURE__ */ jsx35(
1950
+ AriaMenu,
1951
+ {
1952
+ className: cx("pire-menu", className),
1953
+ style: menuStyle,
1954
+ ...rest
1955
+ }
1956
+ );
1957
+ }
1958
+ function MenuItem({
1959
+ children,
1960
+ icon,
1961
+ description,
1962
+ shortcut,
1963
+ tone = "default",
1964
+ className,
1965
+ ...rest
1966
+ }) {
1967
+ return /* @__PURE__ */ jsxs28(
1968
+ AriaMenuItem,
1969
+ {
1970
+ className: cx("pire-menu-item", className),
1971
+ "data-tone": tone === "danger" ? "danger" : void 0,
1972
+ ...rest,
1973
+ children: [
1974
+ icon ? /* @__PURE__ */ jsx35(Icon, { name: icon, size: 16, className: "pire-menu-item-icon" }) : null,
1975
+ /* @__PURE__ */ jsxs28("span", { className: "pire-menu-item-body", children: [
1976
+ /* @__PURE__ */ jsx35("span", { className: "pire-menu-item-label", children }),
1977
+ description ? /* @__PURE__ */ jsx35("span", { className: "pire-menu-item-desc", children: description }) : null
1978
+ ] }),
1979
+ shortcut ? /* @__PURE__ */ jsx35("kbd", { className: "pire-menu-item-shortcut", children: shortcut }) : null
1980
+ ]
1981
+ }
1982
+ );
1983
+ }
1984
+ function MenuSection({ title, children, className, ...rest }) {
1985
+ return /* @__PURE__ */ jsxs28(AriaMenuSection, { className: cx("pire-menu-section", className), ...rest, children: [
1986
+ title ? /* @__PURE__ */ jsx35(Header, { className: "pire-menu-section-title", children: title }) : null,
1987
+ children
1988
+ ] });
1989
+ }
1990
+ function MenuSeparator({ className }) {
1991
+ return /* @__PURE__ */ jsx35(AriaSeparator2, { className: cx("pire-menu-separator", className) });
1992
+ }
1993
+
1994
+ // src/components/navigation/SideNav.tsx
1995
+ import { jsx as jsx36, jsxs as jsxs29 } from "react/jsx-runtime";
1631
1996
  function findActiveParent(groups, value) {
1632
1997
  if (value == null) return void 0;
1633
1998
  for (const group of groups) {
@@ -1645,6 +2010,7 @@ function SideNav({
1645
2010
  defaultExpandedIds,
1646
2011
  onExpandedChange,
1647
2012
  collapsed,
2013
+ railFlyout = true,
1648
2014
  footer,
1649
2015
  className,
1650
2016
  ...rest
@@ -1652,10 +2018,10 @@ function SideNav({
1652
2018
  const msg = usePireMessages();
1653
2019
  const activeParent = findActiveParent(groups, value);
1654
2020
  const isControlled = expandedIds != null;
1655
- const [ownExpanded, setOwnExpanded] = React10.useState(
2021
+ const [ownExpanded, setOwnExpanded] = React11.useState(
1656
2022
  () => new Set(defaultExpandedIds ?? (activeParent ? [activeParent] : []))
1657
2023
  );
1658
- const [lastValue, setLastValue] = React10.useState(value);
2024
+ const [lastValue, setLastValue] = React11.useState(value);
1659
2025
  if (value !== lastValue) {
1660
2026
  setLastValue(value);
1661
2027
  if (!isControlled && activeParent && !ownExpanded.has(activeParent)) {
@@ -1675,8 +2041,8 @@ function SideNav({
1675
2041
  };
1676
2042
  const renderRow = (item, onPress, isGroup) => {
1677
2043
  const selected = !isGroup && item.id === value;
1678
- const button = /* @__PURE__ */ jsxs25(
1679
- AriaButton9,
2044
+ const button = /* @__PURE__ */ jsxs29(
2045
+ AriaButton10,
1680
2046
  {
1681
2047
  className: "pire-sidenav-item",
1682
2048
  "data-selected": selected ? "true" : void 0,
@@ -1685,50 +2051,70 @@ function SideNav({
1685
2051
  "aria-label": collapsed ? item.label : void 0,
1686
2052
  onPress,
1687
2053
  children: [
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
2054
+ item.icon ? /* @__PURE__ */ jsx36(Icon, { name: item.icon, size: 16 }) : null,
2055
+ collapsed ? null : /* @__PURE__ */ jsx36("span", { children: item.label }),
2056
+ item.count != null && !collapsed ? /* @__PURE__ */ jsx36("span", { className: "pire-sidenav-count", children: item.count }) : null
1691
2057
  ]
1692
2058
  },
1693
2059
  item.id
1694
2060
  );
1695
- return collapsed ? /* @__PURE__ */ jsx32(Tooltip, { label: item.label, placement: "right", children: button }, item.id) : button;
2061
+ return collapsed ? /* @__PURE__ */ jsx36(Tooltip, { label: item.label, placement: "right", children: button }, item.id) : button;
1696
2062
  };
1697
- const renderSection = (item) => /* @__PURE__ */ jsxs25(Disclosure, { id: item.id, className: "pire-sidenav-section", children: [
1698
- /* @__PURE__ */ jsxs25(
1699
- AriaButton9,
2063
+ const renderRailFlyout = (item) => /* @__PURE__ */ jsxs29(MenuTrigger, { children: [
2064
+ /* @__PURE__ */ jsx36(
2065
+ AriaButton10,
2066
+ {
2067
+ className: "pire-sidenav-item",
2068
+ "aria-label": item.label,
2069
+ "data-active-child": item.id === activeParent ? "true" : void 0,
2070
+ children: item.icon ? /* @__PURE__ */ jsx36(Icon, { name: item.icon, size: 16 }) : null
2071
+ }
2072
+ ),
2073
+ /* @__PURE__ */ jsx36(Popover6, { className: "pire-popover", placement: "right top", offset: 4, children: /* @__PURE__ */ jsx36(
2074
+ Menu,
2075
+ {
2076
+ "aria-label": item.label,
2077
+ className: "pire-sidenav-flyout",
2078
+ onAction: (key) => onChange?.(String(key)),
2079
+ children: (item.items ?? []).map((child) => /* @__PURE__ */ jsx36(MenuItem, { id: child.id, children: child.label }, child.id))
2080
+ }
2081
+ ) })
2082
+ ] }, item.id);
2083
+ const renderSection = (item) => /* @__PURE__ */ jsxs29(Disclosure, { id: item.id, className: "pire-sidenav-section", children: [
2084
+ /* @__PURE__ */ jsxs29(
2085
+ AriaButton10,
1700
2086
  {
1701
2087
  slot: "trigger",
1702
2088
  className: "pire-sidenav-item",
1703
2089
  "data-kind": "group",
1704
2090
  "data-active-child": item.id === activeParent ? "true" : void 0,
1705
2091
  children: [
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" })
2092
+ item.icon ? /* @__PURE__ */ jsx36(Icon, { name: item.icon, size: 16 }) : null,
2093
+ /* @__PURE__ */ jsx36("span", { children: item.label }),
2094
+ item.count != null ? /* @__PURE__ */ jsx36("span", { className: "pire-sidenav-count", children: item.count }) : null,
2095
+ /* @__PURE__ */ jsx36(Icon, { name: "chevron-down", size: 16, className: "pire-sidenav-chevron" })
1710
2096
  ]
1711
2097
  }
1712
2098
  ),
1713
- /* @__PURE__ */ jsx32(DisclosurePanel, { className: "pire-sidenav-subnav", children: item.items?.map((child) => {
2099
+ /* @__PURE__ */ jsx36(DisclosurePanel, { className: "pire-sidenav-subnav", children: item.items?.map((child) => {
1714
2100
  const selected = child.id === value;
1715
- return /* @__PURE__ */ jsxs25(
1716
- AriaButton9,
2101
+ return /* @__PURE__ */ jsxs29(
2102
+ AriaButton10,
1717
2103
  {
1718
2104
  className: "pire-sidenav-item pire-sidenav-subitem",
1719
2105
  "data-selected": selected ? "true" : void 0,
1720
2106
  "aria-current": selected ? "page" : void 0,
1721
2107
  onPress: () => onChange?.(child.id),
1722
2108
  children: [
1723
- /* @__PURE__ */ jsx32("span", { children: child.label }),
1724
- child.count != null ? /* @__PURE__ */ jsx32("span", { className: "pire-sidenav-count", children: child.count }) : null
2109
+ /* @__PURE__ */ jsx36("span", { children: child.label }),
2110
+ child.count != null ? /* @__PURE__ */ jsx36("span", { className: "pire-sidenav-count", children: child.count }) : null
1725
2111
  ]
1726
2112
  },
1727
2113
  child.id
1728
2114
  );
1729
2115
  }) })
1730
2116
  ] }, item.id);
1731
- return /* @__PURE__ */ jsxs25(
2117
+ return /* @__PURE__ */ jsxs29(
1732
2118
  "nav",
1733
2119
  {
1734
2120
  className: cx("pire-sidenav", className),
@@ -1741,11 +2127,12 @@ function SideNav({
1741
2127
  const rows = group.items.map((item) => {
1742
2128
  const isGroup = Boolean(item.items?.length);
1743
2129
  if (isGroup && !collapsed) return renderSection(item);
2130
+ if (isGroup && collapsed && railFlyout) return renderRailFlyout(item);
1744
2131
  return renderRow(item, () => isGroup ? toggleExpanded(item.id) : onChange?.(item.id), isGroup);
1745
2132
  });
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(
2133
+ return /* @__PURE__ */ jsxs29("div", { className: "pire-sidenav-group", children: [
2134
+ group.label && !collapsed ? /* @__PURE__ */ jsx36("div", { className: "pire-sidenav-label", children: group.label }) : null,
2135
+ hasSections ? /* @__PURE__ */ jsx36(
1749
2136
  DisclosureGroup,
1750
2137
  {
1751
2138
  className: "pire-sidenav-tree",
@@ -1757,7 +2144,7 @@ function SideNav({
1757
2144
  ) : rows
1758
2145
  ] }, group.label ?? gi);
1759
2146
  }),
1760
- footer ? /* @__PURE__ */ jsx32("div", { className: "pire-sidenav-footer", children: footer }) : null
2147
+ footer ? /* @__PURE__ */ jsx36("div", { className: "pire-sidenav-footer", children: footer }) : null
1761
2148
  ]
1762
2149
  }
1763
2150
  );
@@ -1765,9 +2152,9 @@ function SideNav({
1765
2152
 
1766
2153
  // src/components/navigation/Tabs.tsx
1767
2154
  import { Tabs as AriaTabs, TabList, Tab as AriaTab, TabPanel } from "react-aria-components";
1768
- import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
2155
+ import { jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
1769
2156
  function Tabs({ items, value, defaultValue, onChange, panels, className, style, ...rest }) {
1770
- return /* @__PURE__ */ jsxs26(
2157
+ return /* @__PURE__ */ jsxs30(
1771
2158
  AriaTabs,
1772
2159
  {
1773
2160
  className,
@@ -1776,12 +2163,12 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
1776
2163
  defaultSelectedKey: defaultValue,
1777
2164
  onSelectionChange: (k) => onChange?.(String(k)),
1778
2165
  children: [
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,
2166
+ /* @__PURE__ */ jsx37(TabList, { className: "pire-tablist", items, "aria-label": rest["aria-label"] ?? "Views", children: (item) => /* @__PURE__ */ jsxs30(AriaTab, { className: cx("pire-tab"), id: item.id, isDisabled: item.isDisabled, children: [
2167
+ item.icon ? /* @__PURE__ */ jsx37(Icon, { name: item.icon, size: 16 }) : null,
1781
2168
  item.label,
1782
- item.count != null ? /* @__PURE__ */ jsx33("span", { className: "pire-tab-count", children: item.count }) : null
2169
+ item.count != null ? /* @__PURE__ */ jsx37("span", { className: "pire-tab-count", children: item.count }) : null
1783
2170
  ] }) }),
1784
- items.map((item) => /* @__PURE__ */ jsx33(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
2171
+ items.map((item) => /* @__PURE__ */ jsx37(TabPanel, { id: item.id, className: panels ? "pire-tabpanel" : void 0, children: panels?.[item.id] }, item.id))
1785
2172
  ]
1786
2173
  }
1787
2174
  );
@@ -1789,9 +2176,9 @@ function Tabs({ items, value, defaultValue, onChange, panels, className, style,
1789
2176
 
1790
2177
  // src/components/navigation/Breadcrumb.tsx
1791
2178
  import { Breadcrumbs as AriaBreadcrumbs, Breadcrumb as AriaBreadcrumb, Link as Link2 } from "react-aria-components";
1792
- import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
2179
+ import { jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
1793
2180
  function Breadcrumb({ items, onNavigate, className, style }) {
1794
- return /* @__PURE__ */ jsx34(
2181
+ return /* @__PURE__ */ jsx38(
1795
2182
  AriaBreadcrumbs,
1796
2183
  {
1797
2184
  className: cx("pire-breadcrumbs", className),
@@ -1800,9 +2187,9 @@ function Breadcrumb({ items, onNavigate, className, style }) {
1800
2187
  onAction: (key) => onNavigate?.(String(key)),
1801
2188
  children: (item) => {
1802
2189
  const last = items[items.length - 1] === item;
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)" } })
2190
+ return /* @__PURE__ */ jsxs31(AriaBreadcrumb, { className: "pire-breadcrumb", id: item.id ?? item.label, children: [
2191
+ last ? item.label : /* @__PURE__ */ jsx38(Link2, { href: item.href, children: item.label }),
2192
+ last ? null : /* @__PURE__ */ jsx38(Icon, { name: "chevron-right", size: 12, style: { color: "var(--text-tertiary)" } })
1806
2193
  ] });
1807
2194
  }
1808
2195
  }
@@ -1810,7 +2197,7 @@ function Breadcrumb({ items, onNavigate, className, style }) {
1810
2197
  }
1811
2198
 
1812
2199
  // src/components/navigation/Pagination.tsx
1813
- import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
2200
+ import { jsx as jsx39, jsxs as jsxs32 } from "react/jsx-runtime";
1814
2201
  function Pagination({
1815
2202
  page = 1,
1816
2203
  pageSize = 25,
@@ -1825,9 +2212,9 @@ function Pagination({
1825
2212
  const pages = Math.max(1, Math.ceil(total / pageSize));
1826
2213
  const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
1827
2214
  const to = Math.min(total, page * pageSize);
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(
2215
+ return /* @__PURE__ */ jsxs32("nav", { className: cx("pire-pagination", className), style, "aria-label": msg.paginationLabel, children: [
2216
+ /* @__PURE__ */ jsx39("span", { className: "pire-pagination-count", children: msg.paginationRange.replace("{from}", from.toLocaleString()).replace("{to}", to.toLocaleString()).replace("{total}", total.toLocaleString()) }),
2217
+ /* @__PURE__ */ jsx39(
1831
2218
  IconButton,
1832
2219
  {
1833
2220
  icon: "chevron-left",
@@ -1838,8 +2225,8 @@ function Pagination({
1838
2225
  onPress: () => onPageChange?.(page - 1)
1839
2226
  }
1840
2227
  ),
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(
2228
+ /* @__PURE__ */ jsx39("span", { className: "pire-pagination-count", "aria-live": "polite", children: msg.paginationPageOf.replace("{page}", String(page)).replace("{pages}", String(pages)) }),
2229
+ /* @__PURE__ */ jsx39(
1843
2230
  IconButton,
1844
2231
  {
1845
2232
  icon: "chevron-right",
@@ -1850,7 +2237,7 @@ function Pagination({
1850
2237
  onPress: () => onPageChange?.(page + 1)
1851
2238
  }
1852
2239
  ),
1853
- onPageSizeChange ? /* @__PURE__ */ jsx35(
2240
+ onPageSizeChange ? /* @__PURE__ */ jsx39(
1854
2241
  Select,
1855
2242
  {
1856
2243
  "aria-label": msg.paginationRowsPerPage,
@@ -1865,65 +2252,8 @@ function Pagination({
1865
2252
  ] });
1866
2253
  }
1867
2254
 
1868
- // src/components/navigation/Menu.tsx
1869
- import {
1870
- Menu as AriaMenu,
1871
- MenuItem as AriaMenuItem,
1872
- MenuSection as AriaMenuSection,
1873
- Separator as AriaSeparator2,
1874
- Header
1875
- } from "react-aria-components";
1876
- import { jsx as jsx36, jsxs as jsxs29 } from "react/jsx-runtime";
1877
- function Menu({ minWidth, className, style, ...rest }) {
1878
- const width = typeof minWidth === "number" ? `${minWidth}px` : minWidth;
1879
- const menuStyle = width == null ? style : { ["--pire-menu-min-w"]: width, ...style };
1880
- return /* @__PURE__ */ jsx36(
1881
- AriaMenu,
1882
- {
1883
- className: cx("pire-menu", className),
1884
- style: menuStyle,
1885
- ...rest
1886
- }
1887
- );
1888
- }
1889
- function MenuItem({
1890
- children,
1891
- icon,
1892
- description,
1893
- shortcut,
1894
- tone = "default",
1895
- className,
1896
- ...rest
1897
- }) {
1898
- return /* @__PURE__ */ jsxs29(
1899
- AriaMenuItem,
1900
- {
1901
- className: cx("pire-menu-item", className),
1902
- "data-tone": tone === "danger" ? "danger" : void 0,
1903
- ...rest,
1904
- children: [
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
1909
- ] }),
1910
- shortcut ? /* @__PURE__ */ jsx36("kbd", { className: "pire-menu-item-shortcut", children: shortcut }) : null
1911
- ]
1912
- }
1913
- );
1914
- }
1915
- function MenuSection({ title, children, className, ...rest }) {
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,
1918
- children
1919
- ] });
1920
- }
1921
- function MenuSeparator({ className }) {
1922
- return /* @__PURE__ */ jsx36(AriaSeparator2, { className: cx("pire-menu-separator", className) });
1923
- }
1924
-
1925
2255
  // src/components/feedback/InlineMessage.tsx
1926
- import { jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
2256
+ import { jsx as jsx40, jsxs as jsxs33 } from "react/jsx-runtime";
1927
2257
  var KIND_ICON = {
1928
2258
  info: "info",
1929
2259
  success: "check-circle-2",
@@ -1933,7 +2263,7 @@ var KIND_ICON = {
1933
2263
  function InlineMessage({ kind = "info", title, action, onClose, children, className, ...rest }) {
1934
2264
  const msg = usePireMessages();
1935
2265
  const assertive = kind === "error" || kind === "warning";
1936
- return /* @__PURE__ */ jsxs30(
2266
+ return /* @__PURE__ */ jsxs33(
1937
2267
  "div",
1938
2268
  {
1939
2269
  className: cx("pire-msg", className),
@@ -1942,58 +2272,21 @@ function InlineMessage({ kind = "info", title, action, onClose, children, classN
1942
2272
  "aria-live": assertive ? "assertive" : "polite",
1943
2273
  ...rest,
1944
2274
  children: [
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,
2275
+ /* @__PURE__ */ jsx40(Icon, { name: KIND_ICON[kind], size: 16, style: { marginTop: 2 } }),
2276
+ /* @__PURE__ */ jsxs33("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "var(--sp-1)" }, children: [
2277
+ title ? /* @__PURE__ */ jsx40("span", { className: "pire-msg-title", children: title }) : null,
2278
+ children ? /* @__PURE__ */ jsx40("span", { className: "pire-msg-body", children }) : null,
1949
2279
  action
1950
2280
  ] }),
1951
- onClose ? /* @__PURE__ */ jsx37(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
2281
+ onClose ? /* @__PURE__ */ jsx40(IconButton, { icon: "x", label: msg.inlineMessageDismiss, size: "sm", onPress: onClose }) : null
1952
2282
  ]
1953
2283
  }
1954
2284
  );
1955
2285
  }
1956
2286
 
1957
- // src/components/feedback/ProgressBar.tsx
1958
- import { ProgressBar as AriaProgressBar, Label as Label9 } from "react-aria-components";
1959
- import { Fragment as Fragment2, jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
1960
- function ProgressBar({
1961
- value = 0,
1962
- minValue = 0,
1963
- maxValue = 100,
1964
- label,
1965
- showValue = true,
1966
- isIndeterminate,
1967
- status = "informative",
1968
- size = "md",
1969
- className,
1970
- style
1971
- }) {
1972
- return /* @__PURE__ */ jsx38(
1973
- AriaProgressBar,
1974
- {
1975
- className: cx("pire-progress", className),
1976
- "data-status": status,
1977
- "data-size": size,
1978
- value,
1979
- minValue,
1980
- maxValue,
1981
- isIndeterminate,
1982
- style,
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
1987
- ] }) : null,
1988
- /* @__PURE__ */ jsx38("div", { className: "pire-progress-track", children: /* @__PURE__ */ jsx38("div", { className: "pire-progress-fill", style: { width: `${isIndeterminate ? 40 : percentage}%` } }) })
1989
- ] })
1990
- }
1991
- );
1992
- }
1993
-
1994
2287
  // src/components/feedback/Toast.tsx
1995
- import * as React11 from "react";
1996
- import { jsx as jsx39, jsxs as jsxs32 } from "react/jsx-runtime";
2288
+ import * as React12 from "react";
2289
+ import { jsx as jsx41, jsxs as jsxs34 } from "react/jsx-runtime";
1997
2290
  var KIND_ICON2 = {
1998
2291
  info: "info",
1999
2292
  success: "check-circle-2",
@@ -2002,7 +2295,7 @@ var KIND_ICON2 = {
2002
2295
  };
2003
2296
  function Toast({ kind = "success", onClose, position = "bottom-center", children, className, ...rest }) {
2004
2297
  const msg = usePireMessages();
2005
- return /* @__PURE__ */ jsxs32(
2298
+ return /* @__PURE__ */ jsxs34(
2006
2299
  "div",
2007
2300
  {
2008
2301
  className: cx("pire-toast", className),
@@ -2011,40 +2304,40 @@ function Toast({ kind = "success", onClose, position = "bottom-center", children
2011
2304
  "aria-live": kind === "error" ? "assertive" : "polite",
2012
2305
  ...rest,
2013
2306
  children: [
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
2307
+ /* @__PURE__ */ jsx41(Icon, { name: KIND_ICON2[kind], size: 16 }),
2308
+ /* @__PURE__ */ jsx41("span", { style: { flex: 1 }, children }),
2309
+ onClose ? /* @__PURE__ */ jsx41(IconButton, { icon: "x", label: msg.toastDismiss, size: "sm", variant: "inverse", onPress: onClose }) : null
2017
2310
  ]
2018
2311
  }
2019
2312
  );
2020
2313
  }
2021
- var ToastContext = React11.createContext(null);
2314
+ var ToastContext = React12.createContext(null);
2022
2315
  function ToastProvider({ children, timeout = 6e3 }) {
2023
2316
  const msg = usePireMessages();
2024
- const [toasts, setToasts] = React11.useState([]);
2025
- const close = React11.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2026
- const add = React11.useCallback((toast) => {
2317
+ const [toasts, setToasts] = React12.useState([]);
2318
+ const close = React12.useCallback((id) => setToasts((t) => t.filter((x) => x.id !== id)), []);
2319
+ const add = React12.useCallback((toast) => {
2027
2320
  const id = Math.random().toString(36).slice(2);
2028
2321
  setToasts((t) => [...t, { ...toast, id }]);
2029
2322
  const ms = toast.timeout ?? timeout;
2030
2323
  if (ms > 0) setTimeout(() => close(id), ms);
2031
2324
  return id;
2032
2325
  }, [close, timeout]);
2033
- const value = React11.useMemo(() => ({ add, close }), [add, close]);
2034
- return /* @__PURE__ */ jsxs32(ToastContext.Provider, { value, children: [
2326
+ const value = React12.useMemo(() => ({ add, close }), [add, close]);
2327
+ return /* @__PURE__ */ jsxs34(ToastContext.Provider, { value, children: [
2035
2328
  children,
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)) })
2329
+ /* @__PURE__ */ jsx41("div", { className: "pire-toast-region", role: "region", "aria-label": msg.toastRegionLabel, children: toasts.map((t) => /* @__PURE__ */ jsx41(Toast, { kind: t.kind, onClose: () => close(t.id), style: { position: "static", transform: "none" }, children: t.message }, t.id)) })
2037
2330
  ] });
2038
2331
  }
2039
2332
  function useToast() {
2040
- const ctx = React11.useContext(ToastContext);
2333
+ const ctx = React12.useContext(ToastContext);
2041
2334
  if (!ctx) throw new Error("useToast must be used inside <ToastProvider>");
2042
2335
  return ctx;
2043
2336
  }
2044
2337
 
2045
2338
  // src/components/data/KpiTile.tsx
2046
- import { Button as AriaButton10 } from "react-aria-components";
2047
- import { Fragment as Fragment3, jsx as jsx40, jsxs as jsxs33 } from "react/jsx-runtime";
2339
+ import { Button as AriaButton11 } from "react-aria-components";
2340
+ import { Fragment as Fragment3, jsx as jsx42, jsxs as jsxs35 } from "react/jsx-runtime";
2048
2341
  function KpiTile({
2049
2342
  label,
2050
2343
  value,
@@ -2060,50 +2353,50 @@ function KpiTile({
2060
2353
  style
2061
2354
  }) {
2062
2355
  const tone = deltaTone ?? (deltaDirection === "down" ? "negative" : "positive");
2063
- const body = /* @__PURE__ */ jsxs33(Fragment3, { children: [
2064
- /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-label", children: [
2065
- icon ? /* @__PURE__ */ jsx40(Icon, { name: icon, size: 16 }) : null,
2356
+ const body = /* @__PURE__ */ jsxs35(Fragment3, { children: [
2357
+ /* @__PURE__ */ jsxs35("span", { className: "pire-kpi-label", children: [
2358
+ icon ? /* @__PURE__ */ jsx42(Icon, { name: icon, size: 16 }) : null,
2066
2359
  label
2067
2360
  ] }),
2068
- /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-value", children: [
2361
+ /* @__PURE__ */ jsxs35("span", { className: "pire-kpi-value", children: [
2069
2362
  value,
2070
- unit ? /* @__PURE__ */ jsx40("span", { className: "pire-kpi-unit", children: unit }) : null
2363
+ unit ? /* @__PURE__ */ jsx42("span", { className: "pire-kpi-unit", children: unit }) : null
2071
2364
  ] }),
2072
- delta ? /* @__PURE__ */ jsxs33("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
2073
- deltaDirection ? /* @__PURE__ */ jsx40(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
2365
+ delta ? /* @__PURE__ */ jsxs35("span", { className: "pire-kpi-delta", "data-tone": tone, children: [
2366
+ deltaDirection ? /* @__PURE__ */ jsx42(Icon, { name: deltaDirection === "up" ? "trending-up" : "trending-down", size: 12 }) : null,
2074
2367
  delta
2075
2368
  ] }) : null,
2076
- footnote ? /* @__PURE__ */ jsx40("span", { className: "pire-kpi-foot", children: footnote }) : null
2369
+ footnote ? /* @__PURE__ */ jsx42("span", { className: "pire-kpi-foot", children: footnote }) : null
2077
2370
  ] });
2078
2371
  const props = { className: cx("pire-kpi", className), "data-status": status, style };
2079
- return onPress ? /* @__PURE__ */ jsx40(AriaButton10, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ jsx40("div", { ...props, children: body });
2372
+ return onPress ? /* @__PURE__ */ jsx42(AriaButton11, { ...props, "data-pressable": "true", onPress, children: body }) : /* @__PURE__ */ jsx42("div", { ...props, children: body });
2080
2373
  }
2081
2374
 
2082
2375
  // src/components/data/ObjectHeader.tsx
2083
- import { jsx as jsx41, jsxs as jsxs34 } from "react/jsx-runtime";
2376
+ import { jsx as jsx43, jsxs as jsxs36 } from "react/jsx-runtime";
2084
2377
  function ObjectHeader({ title, subtitle, id, breadcrumb, badge, facts, actions, className, ...rest }) {
2085
- return /* @__PURE__ */ jsxs34("header", { className: cx("pire-objheader", className), ...rest, children: [
2378
+ return /* @__PURE__ */ jsxs36("header", { className: cx("pire-objheader", className), ...rest, children: [
2086
2379
  breadcrumb,
2087
- /* @__PURE__ */ jsxs34("div", { className: "pire-objheader-row", children: [
2088
- /* @__PURE__ */ jsxs34("div", { style: { minWidth: 0 }, children: [
2089
- /* @__PURE__ */ jsx41("h1", { className: "pire-objheader-title", children: title }),
2090
- subtitle || id ? /* @__PURE__ */ jsxs34("div", { className: "pire-objheader-sub", children: [
2380
+ /* @__PURE__ */ jsxs36("div", { className: "pire-objheader-row", children: [
2381
+ /* @__PURE__ */ jsxs36("div", { style: { minWidth: 0 }, children: [
2382
+ /* @__PURE__ */ jsx43("h1", { className: "pire-objheader-title", children: title }),
2383
+ subtitle || id ? /* @__PURE__ */ jsxs36("div", { className: "pire-objheader-sub", children: [
2091
2384
  subtitle,
2092
- id ? /* @__PURE__ */ jsx41("span", { className: "pire-objheader-id", children: id }) : null
2385
+ id ? /* @__PURE__ */ jsx43("span", { className: "pire-objheader-id", children: id }) : null
2093
2386
  ] }) : null
2094
2387
  ] }),
2095
2388
  badge,
2096
- actions ? /* @__PURE__ */ jsx41("div", { className: "pire-objheader-actions", children: actions }) : null
2389
+ actions ? /* @__PURE__ */ jsx43("div", { className: "pire-objheader-actions", children: actions }) : null
2097
2390
  ] }),
2098
- facts?.length ? /* @__PURE__ */ jsx41("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs34("div", { children: [
2099
- /* @__PURE__ */ jsx41("dt", { className: "pire-fact-label", children: fact.label }),
2100
- /* @__PURE__ */ jsx41("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
2391
+ facts?.length ? /* @__PURE__ */ jsx43("dl", { className: "pire-facts", style: { margin: 0 }, children: facts.map((fact) => /* @__PURE__ */ jsxs36("div", { children: [
2392
+ /* @__PURE__ */ jsx43("dt", { className: "pire-fact-label", children: fact.label }),
2393
+ /* @__PURE__ */ jsx43("dd", { className: "pire-fact-value", "data-numeric": fact.numeric ? "true" : void 0, style: { margin: 0 }, children: fact.value })
2101
2394
  ] }, fact.label)) }) : null
2102
2395
  ] });
2103
2396
  }
2104
2397
 
2105
2398
  // src/components/data/FilterBar.tsx
2106
- import { jsx as jsx42, jsxs as jsxs35 } from "react/jsx-runtime";
2399
+ import { jsx as jsx44, jsxs as jsxs37 } from "react/jsx-runtime";
2107
2400
  function FilterBar({
2108
2401
  children,
2109
2402
  activeFilters = [],
@@ -2120,66 +2413,66 @@ function FilterBar({
2120
2413
  const label = useMessage("filterBarLabel", rest["aria-label"]);
2121
2414
  const go = useMessage("filterBarGo", goLabel);
2122
2415
  const clearAll = useMessage("filterBarClearAll", clearAllLabel);
2123
- return /* @__PURE__ */ jsxs35("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
2124
- /* @__PURE__ */ jsxs35("div", { className: "pire-filterbar-controls", children: [
2416
+ return /* @__PURE__ */ jsxs37("section", { className: cx("pire-filterbar", className), ...rest, "aria-label": label, children: [
2417
+ /* @__PURE__ */ jsxs37("div", { className: "pire-filterbar-controls", children: [
2125
2418
  children,
2126
- onGo ? /* @__PURE__ */ jsx42(Button, { variant: "primary", onPress: onGo, children: go }) : null
2419
+ onGo ? /* @__PURE__ */ jsx44(Button, { variant: "primary", onPress: onGo, children: go }) : null
2127
2420
  ] }),
2128
- activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs35("div", { className: "pire-filterbar-foot", children: [
2129
- activeFilters.map((filter) => /* @__PURE__ */ jsx42(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
2130
- activeFilters.length && onClear ? /* @__PURE__ */ jsx42(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
2131
- resultLabel ? /* @__PURE__ */ jsx42("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
2132
- actions ? /* @__PURE__ */ jsx42("div", { className: "pire-filterbar-actions", children: actions }) : null
2421
+ activeFilters.length || resultLabel || actions ? /* @__PURE__ */ jsxs37("div", { className: "pire-filterbar-foot", children: [
2422
+ activeFilters.map((filter) => /* @__PURE__ */ jsx44(Tag, { onRemove: onRemoveFilter ? () => onRemoveFilter(filter.id) : void 0, children: filter.label }, filter.id)),
2423
+ activeFilters.length && onClear ? /* @__PURE__ */ jsx44(Button, { variant: "tertiary", size: "sm", onPress: onClear, children: clearAll }) : null,
2424
+ resultLabel ? /* @__PURE__ */ jsx44("span", { className: "pire-filterbar-result", "aria-live": "polite", children: resultLabel }) : null,
2425
+ actions ? /* @__PURE__ */ jsx44("div", { className: "pire-filterbar-actions", children: actions }) : null
2133
2426
  ] }) : null
2134
2427
  ] });
2135
2428
  }
2136
2429
 
2137
2430
  // src/components/data/DescriptionList.tsx
2138
- import { jsx as jsx43, jsxs as jsxs36 } from "react/jsx-runtime";
2431
+ import { jsx as jsx45, jsxs as jsxs38 } from "react/jsx-runtime";
2139
2432
  function DescriptionList({ items, layout = "rows", columns = 3, className, style, ...rest }) {
2140
- return /* @__PURE__ */ jsx43(
2433
+ return /* @__PURE__ */ jsx45(
2141
2434
  "dl",
2142
2435
  {
2143
2436
  className: cx("pire-dl", className),
2144
2437
  "data-layout": layout,
2145
2438
  style: { ...layout === "grid" ? { "--pire-dl-cols": columns } : null, ...style },
2146
2439
  ...rest,
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: [
2440
+ children: items.map((item, i) => /* @__PURE__ */ jsxs38("div", { className: "pire-dl-row", "data-emphasis": item.emphasis ? "true" : void 0, children: [
2441
+ /* @__PURE__ */ jsxs38("dt", { className: "pire-dl-term", children: [
2149
2442
  item.label,
2150
2443
  item.hint
2151
2444
  ] }),
2152
- /* @__PURE__ */ jsx43("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
2445
+ /* @__PURE__ */ jsx45("dd", { className: "pire-dl-value", "data-numeric": item.numeric ? "true" : void 0, children: item.value })
2153
2446
  ] }, i))
2154
2447
  }
2155
2448
  );
2156
2449
  }
2157
2450
 
2158
2451
  // src/components/data/Timeline.tsx
2159
- import { jsx as jsx44, jsxs as jsxs37 } from "react/jsx-runtime";
2452
+ import { jsx as jsx46, jsxs as jsxs39 } from "react/jsx-runtime";
2160
2453
  function Timeline({ entries, reverse = false, className, ...rest }) {
2161
2454
  const list = reverse ? [...entries].reverse() : entries;
2162
- return /* @__PURE__ */ jsx44("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs37("li", { className: "pire-timeline-item", children: [
2163
- /* @__PURE__ */ jsx44("span", { className: "pire-timeline-time", children: entry.time }),
2164
- /* @__PURE__ */ jsx44("span", { className: "pire-timeline-text", children: entry.event }),
2165
- entry.actor ? /* @__PURE__ */ jsx44("span", { className: "pire-timeline-actor", children: entry.actor }) : null
2455
+ return /* @__PURE__ */ jsx46("ol", { className: cx("pire-timeline", className), ...rest, children: list.map((entry, i) => /* @__PURE__ */ jsxs39("li", { className: "pire-timeline-item", children: [
2456
+ /* @__PURE__ */ jsx46("span", { className: "pire-timeline-time", children: entry.time }),
2457
+ /* @__PURE__ */ jsx46("span", { className: "pire-timeline-text", children: entry.event }),
2458
+ entry.actor ? /* @__PURE__ */ jsx46("span", { className: "pire-timeline-actor", children: entry.actor }) : null
2166
2459
  ] }, entry.id ?? i)) });
2167
2460
  }
2168
2461
 
2169
2462
  // src/components/data/LinkList.tsx
2170
- import { Button as AriaButton11 } from "react-aria-components";
2171
- import { jsx as jsx45, jsxs as jsxs38 } from "react/jsx-runtime";
2463
+ import { Button as AriaButton12 } from "react-aria-components";
2464
+ import { jsx as jsx47, jsxs as jsxs40 } from "react/jsx-runtime";
2172
2465
  function LinkList({ items, onSelect, className, ...rest }) {
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: [
2174
- item.icon ? /* @__PURE__ */ jsx45(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
2175
- item.key ? /* @__PURE__ */ jsx45("span", { className: "pire-linklist-key", children: item.key }) : null,
2176
- item.text ? /* @__PURE__ */ jsx45("span", { className: "pire-linklist-text", children: item.text }) : null,
2466
+ return /* @__PURE__ */ jsx47("div", { className: cx("pire-linklist", className), role: "list", ...rest, children: items.map((item) => /* @__PURE__ */ jsxs40(AriaButton12, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
2467
+ item.icon ? /* @__PURE__ */ jsx47(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
2468
+ item.key ? /* @__PURE__ */ jsx47("span", { className: "pire-linklist-key", children: item.key }) : null,
2469
+ item.text ? /* @__PURE__ */ jsx47("span", { className: "pire-linklist-text", children: item.text }) : null,
2177
2470
  item.trailing
2178
2471
  ] }, item.id)) });
2179
2472
  }
2180
2473
 
2181
2474
  // src/components/layout/PageBand.tsx
2182
- import { jsx as jsx46 } from "react/jsx-runtime";
2475
+ import { jsx as jsx48 } from "react/jsx-runtime";
2183
2476
  function PageBand({
2184
2477
  surface = "card",
2185
2478
  hasBorder = true,
@@ -2187,7 +2480,7 @@ function PageBand({
2187
2480
  className,
2188
2481
  ...rest
2189
2482
  }) {
2190
- return /* @__PURE__ */ jsx46(
2483
+ return /* @__PURE__ */ jsx48(
2191
2484
  "div",
2192
2485
  {
2193
2486
  className: cx("pire-pageband", className),
@@ -2200,56 +2493,56 @@ function PageBand({
2200
2493
  }
2201
2494
 
2202
2495
  // src/components/layout/PageHeader.tsx
2203
- import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
2496
+ import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
2204
2497
  function PageHeader({ title, subtitle, actions, className, ...rest }) {
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
2498
+ return /* @__PURE__ */ jsxs41("header", { className: cx("pire-pageheader", className), ...rest, children: [
2499
+ /* @__PURE__ */ jsxs41("div", { style: { minWidth: 0 }, children: [
2500
+ /* @__PURE__ */ jsx49("h1", { className: "pire-pageheader-title", children: title }),
2501
+ subtitle ? /* @__PURE__ */ jsx49("p", { className: "pire-pageheader-sub", children: subtitle }) : null
2209
2502
  ] }),
2210
- actions ? /* @__PURE__ */ jsx47("div", { className: "pire-pageheader-actions", children: actions }) : null
2503
+ actions ? /* @__PURE__ */ jsx49("div", { className: "pire-pageheader-actions", children: actions }) : null
2211
2504
  ] });
2212
2505
  }
2213
2506
 
2214
2507
  // src/components/layout/SectionHeader.tsx
2215
- import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
2508
+ import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
2216
2509
  function SectionHeader({ title, meta, actions, className, ...rest }) {
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
2510
+ return /* @__PURE__ */ jsxs42("div", { className: cx("pire-sectionhead", className), ...rest, children: [
2511
+ /* @__PURE__ */ jsx50("span", { className: "pire-eyebrow", children: title }),
2512
+ meta ? /* @__PURE__ */ jsx50("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
2513
+ actions ? /* @__PURE__ */ jsx50("div", { className: "pire-sectionhead-actions", children: actions }) : null
2221
2514
  ] });
2222
2515
  }
2223
2516
 
2224
2517
  // src/components/layout/SelectionBar.tsx
2225
- import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
2518
+ import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
2226
2519
  function SelectionBar({ count, noun = "record", children, actions, className, ...rest }) {
2227
2520
  if (!count) return null;
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: [
2521
+ return /* @__PURE__ */ jsxs43("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
2522
+ /* @__PURE__ */ jsxs43("span", { className: "pire-selectionbar-count", children: [
2230
2523
  count.toLocaleString(),
2231
2524
  " ",
2232
2525
  noun,
2233
2526
  count === 1 ? "" : "s",
2234
2527
  " selected"
2235
2528
  ] }),
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
2529
+ children ? /* @__PURE__ */ jsx51("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
2530
+ actions ? /* @__PURE__ */ jsx51("div", { className: "pire-selectionbar-actions", children: actions }) : null
2238
2531
  ] });
2239
2532
  }
2240
2533
 
2241
2534
  // src/components/layout/FooterBar.tsx
2242
- import { jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
2535
+ import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
2243
2536
  function FooterBar({ note, actions, children, className, ...rest }) {
2244
- return /* @__PURE__ */ jsxs42("footer", { className: cx("pire-footerbar", className), ...rest, children: [
2245
- note ? /* @__PURE__ */ jsx50("span", { className: "pire-footerbar-note", children: note }) : null,
2537
+ return /* @__PURE__ */ jsxs44("footer", { className: cx("pire-footerbar", className), ...rest, children: [
2538
+ note ? /* @__PURE__ */ jsx52("span", { className: "pire-footerbar-note", children: note }) : null,
2246
2539
  children,
2247
- actions ? /* @__PURE__ */ jsx50("div", { className: "pire-footerbar-actions", children: actions }) : null
2540
+ actions ? /* @__PURE__ */ jsx52("div", { className: "pire-footerbar-actions", children: actions }) : null
2248
2541
  ] });
2249
2542
  }
2250
2543
 
2251
2544
  // src/components/patterns/ConfirmDialog.tsx
2252
- import { Fragment as Fragment4, jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
2545
+ import { Fragment as Fragment4, jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
2253
2546
  function ConfirmDialog({
2254
2547
  isOpen,
2255
2548
  title,
@@ -2263,7 +2556,7 @@ function ConfirmDialog({
2263
2556
  onConfirm,
2264
2557
  onCancel
2265
2558
  }) {
2266
- return /* @__PURE__ */ jsxs43(
2559
+ return /* @__PURE__ */ jsxs45(
2267
2560
  Dialog,
2268
2561
  {
2269
2562
  isOpen,
@@ -2273,12 +2566,12 @@ function ConfirmDialog({
2273
2566
  onClose: onCancel,
2274
2567
  isDismissable: !isBusy,
2275
2568
  showClose: false,
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 })
2569
+ footer: /* @__PURE__ */ jsxs45(Fragment4, { children: [
2570
+ /* @__PURE__ */ jsx53(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
2571
+ /* @__PURE__ */ jsx53(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
2279
2572
  ] }),
2280
2573
  children: [
2281
- consequence ? /* @__PURE__ */ jsx51(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
2574
+ consequence ? /* @__PURE__ */ jsx53(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
2282
2575
  children
2283
2576
  ]
2284
2577
  }
@@ -2286,11 +2579,11 @@ function ConfirmDialog({
2286
2579
  }
2287
2580
 
2288
2581
  // src/components/patterns/SidePanel.tsx
2289
- import { ModalOverlay as ModalOverlay2, Modal as Modal2, Dialog as AriaDialog3, Heading as Heading4 } from "react-aria-components";
2290
- import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
2582
+ import { ModalOverlay as ModalOverlay2, Modal as Modal2, Dialog as AriaDialog4, Heading as Heading5 } from "react-aria-components";
2583
+ import { jsx as jsx54, jsxs as jsxs46 } from "react/jsx-runtime";
2291
2584
  function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
2292
2585
  const msg = usePireMessages();
2293
- return /* @__PURE__ */ jsx52(
2586
+ return /* @__PURE__ */ jsx54(
2294
2587
  ModalOverlay2,
2295
2588
  {
2296
2589
  className: "pire-sidepanel-overlay",
@@ -2299,34 +2592,138 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
2299
2592
  onOpenChange: (o) => {
2300
2593
  if (!o) onClose?.();
2301
2594
  },
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
2595
+ children: /* @__PURE__ */ jsx54(Modal2, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs46(AriaDialog4, { className: "pire-dialog", style: { height: "100%" }, children: [
2596
+ /* @__PURE__ */ jsxs46("header", { className: "pire-dialog-head", children: [
2597
+ /* @__PURE__ */ jsxs46("div", { style: { flex: 1, minWidth: 0 }, children: [
2598
+ /* @__PURE__ */ jsx54(Heading5, { slot: "title", className: "pire-dialog-title", children: title }),
2599
+ subtitle ? /* @__PURE__ */ jsx54("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
2307
2600
  ] }),
2308
- /* @__PURE__ */ jsx52(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
2601
+ /* @__PURE__ */ jsx54(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
2309
2602
  ] }),
2310
- /* @__PURE__ */ jsx52("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
2311
- footer ? /* @__PURE__ */ jsx52("footer", { className: "pire-dialog-foot", children: footer }) : null
2603
+ /* @__PURE__ */ jsx54("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
2604
+ footer ? /* @__PURE__ */ jsx54("footer", { className: "pire-dialog-foot", children: footer }) : null
2312
2605
  ] }) })
2313
2606
  }
2314
2607
  );
2315
2608
  }
2316
2609
 
2317
2610
  // src/components/patterns/EmptyState.tsx
2318
- import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
2611
+ import { jsx as jsx55, jsxs as jsxs47 } from "react/jsx-runtime";
2319
2612
  function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
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,
2613
+ return /* @__PURE__ */ jsxs47("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
2614
+ /* @__PURE__ */ jsx55(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
2615
+ title ? /* @__PURE__ */ jsx55("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
2616
+ children ? /* @__PURE__ */ jsx55("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
2324
2617
  action
2325
2618
  ] });
2326
2619
  }
2327
2620
 
2621
+ // src/components/patterns/FileDropZone.tsx
2622
+ import * as React13 from "react";
2623
+ import { DropZone, FileTrigger as FileTrigger2, isFileDropItem } from "react-aria-components";
2624
+ import { jsx as jsx56, jsxs as jsxs48 } from "react/jsx-runtime";
2625
+ var isImage2 = (file) => file.type.startsWith("image/");
2626
+ function FileDropZone({
2627
+ label,
2628
+ value,
2629
+ defaultValue,
2630
+ onChange,
2631
+ acceptedFileTypes,
2632
+ allowsMultiple,
2633
+ maxSize,
2634
+ onError,
2635
+ showPreview = true,
2636
+ uploadProgress,
2637
+ promptLabel,
2638
+ height = "regular",
2639
+ description,
2640
+ errorMessage,
2641
+ isInvalid,
2642
+ isDisabled,
2643
+ isReadOnly,
2644
+ isRequired,
2645
+ fullWidth = true,
2646
+ className,
2647
+ style
2648
+ }) {
2649
+ const msg = usePireMessages();
2650
+ const [uncontrolled, setUncontrolled] = React13.useState(defaultValue ?? []);
2651
+ const files = value ?? uncontrolled;
2652
+ const created = React13.useRef([]);
2653
+ React13.useEffect(() => () => {
2654
+ for (const url of created.current) URL.revokeObjectURL(url);
2655
+ }, []);
2656
+ const commit = (next) => {
2657
+ if (value === void 0) setUncontrolled(next);
2658
+ onChange?.(next);
2659
+ };
2660
+ const accept = (picked) => {
2661
+ if (isDisabled || isReadOnly || !picked.length) return;
2662
+ const { accepted, rejected } = screenFiles(picked, { maxSize, acceptedFileTypes });
2663
+ if (rejected.length) onError?.(rejected);
2664
+ if (!accepted.length) return;
2665
+ const wrapped = accepted.map((file) => {
2666
+ const previewUrl = showPreview && isImage2(file) ? URL.createObjectURL(file) : void 0;
2667
+ if (previewUrl) created.current.push(previewUrl);
2668
+ return { file, previewUrl };
2669
+ });
2670
+ commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
2671
+ };
2672
+ const remove = (target) => commit(files.filter((f) => f.file !== target));
2673
+ return /* @__PURE__ */ jsxs48("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), children: [
2674
+ label ? /* @__PURE__ */ jsxs48("span", { className: "pire-field-label", children: [
2675
+ label,
2676
+ isRequired ? /* @__PURE__ */ jsx56("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
2677
+ ] }) : null,
2678
+ /* @__PURE__ */ jsxs48(
2679
+ DropZone,
2680
+ {
2681
+ className: "pire-dropzone",
2682
+ "data-height": height,
2683
+ isDisabled: isDisabled || isReadOnly,
2684
+ onDrop: async (e) => {
2685
+ const dropped = await Promise.all(
2686
+ e.items.filter(isFileDropItem).map((item) => item.getFile())
2687
+ );
2688
+ accept(dropped);
2689
+ },
2690
+ children: [
2691
+ /* @__PURE__ */ jsx56(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
2692
+ /* @__PURE__ */ jsx56("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
2693
+ /* @__PURE__ */ jsx56(
2694
+ FileTrigger2,
2695
+ {
2696
+ acceptedFileTypes,
2697
+ allowsMultiple,
2698
+ onSelect: (list) => accept(list ? [...list] : []),
2699
+ children: /* @__PURE__ */ jsx56(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
2700
+ }
2701
+ )
2702
+ ]
2703
+ }
2704
+ ),
2705
+ files.length ? /* @__PURE__ */ jsx56("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs48("li", { className: "pire-fileupload-item", children: [
2706
+ previewUrl ? /* @__PURE__ */ jsx56("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx56(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
2707
+ /* @__PURE__ */ jsx56("span", { className: "pire-fileupload-name", children: file.name }),
2708
+ /* @__PURE__ */ jsx56("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
2709
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx56(
2710
+ IconButton,
2711
+ {
2712
+ icon: "x",
2713
+ size: "sm",
2714
+ label: msg.fileUploadRemoveNamed.replace("{name}", file.name),
2715
+ onPress: () => remove(file)
2716
+ }
2717
+ )
2718
+ ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
2719
+ uploadProgress != null ? /* @__PURE__ */ jsx56(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
2720
+ description ? /* @__PURE__ */ jsx56("span", { className: "pire-field-hint", children: description }) : null,
2721
+ isInvalid && errorMessage ? /* @__PURE__ */ jsx56("span", { className: "pire-field-error", children: errorMessage }) : null
2722
+ ] });
2723
+ }
2724
+
2328
2725
  // src/index.ts
2329
- import { DialogTrigger, MenuTrigger, SubmenuTrigger, Popover as Popover5, RouterProvider, I18nProvider } from "react-aria-components";
2726
+ import { DialogTrigger, MenuTrigger as MenuTrigger2, SubmenuTrigger, Popover as Popover7, RouterProvider, I18nProvider } from "react-aria-components";
2330
2727
  export {
2331
2728
  Avatar,
2332
2729
  Badge,
@@ -2338,10 +2735,13 @@ export {
2338
2735
  ConfirmDialog,
2339
2736
  DataTable,
2340
2737
  DatePicker,
2738
+ DateRangePicker,
2341
2739
  DescriptionList,
2342
2740
  Dialog,
2343
2741
  DialogTrigger,
2344
2742
  EmptyState,
2743
+ FileDropZone,
2744
+ FileUpload,
2345
2745
  FilterBar,
2346
2746
  FooterBar,
2347
2747
  FormField,
@@ -2358,7 +2758,7 @@ export {
2358
2758
  MenuItem,
2359
2759
  MenuSection,
2360
2760
  MenuSeparator,
2361
- MenuTrigger,
2761
+ MenuTrigger2 as MenuTrigger,
2362
2762
  MultiComboBox,
2363
2763
  NumberField,
2364
2764
  ObjectHeader,
@@ -2366,7 +2766,7 @@ export {
2366
2766
  PageHeader,
2367
2767
  Pagination,
2368
2768
  PireIntlProvider,
2369
- Popover5 as Popover,
2769
+ Popover7 as Popover,
2370
2770
  ProgressBar,
2371
2771
  Radio,
2372
2772
  RadioGroup,
@@ -2397,6 +2797,8 @@ export {
2397
2797
  configureIcons,
2398
2798
  enMessages,
2399
2799
  esMessages,
2800
+ formatFileSize,
2801
+ rangeLengthInDays,
2400
2802
  usePireMessages,
2401
2803
  useToast
2402
2804
  };