@scattered-light/loomiere-base-ui 0.7.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.
Files changed (93) hide show
  1. package/README.md +29 -4
  2. package/dist/{chunk-JUUPOOQQ.js → chunk-LJQ3RZDJ.js} +51 -3
  3. package/dist/chunk-LJQ3RZDJ.js.map +1 -0
  4. package/dist/custom/collection/index.d.ts +13 -2
  5. package/dist/custom/collection/index.js +53 -29
  6. package/dist/custom/collection/index.js.map +1 -1
  7. package/dist/custom/index.d.ts +1 -1
  8. package/dist/custom/index.js +1 -1
  9. package/dist/design-system/components/Collection/README.md +1 -1
  10. package/dist/design-system/components/CollectionToolbar/README.md +7 -2
  11. package/dist/design-system/components/ContextMenu/README.md +1 -1
  12. package/dist/design-system/components/ContextMenu/preview.html +1 -1
  13. package/dist/design-system/components/DataList/README.md +1 -1
  14. package/dist/design-system/components/DataList/preview.html +171 -171
  15. package/dist/design-system/components/DataTable/README.md +1 -1
  16. package/dist/design-system/components/DataTable/preview.html +176 -176
  17. package/dist/design-system/components/DescriptionList/README.md +41 -0
  18. package/dist/design-system/components/DescriptionList/preview.html +19 -0
  19. package/dist/design-system/components/Drawer/README.md +1 -1
  20. package/dist/design-system/components/ScrollArea/preview.html +2 -2
  21. package/dist/design-system/components/Sheet/README.md +46 -0
  22. package/dist/design-system/components/Sheet/preview.html +19 -0
  23. package/dist/design-system/components/StatFigure/README.md +38 -0
  24. package/dist/design-system/components/StatFigure/preview.html +19 -0
  25. package/dist/design-system/components/Table/README.md +2 -2
  26. package/dist/design-system/components/Table/preview.html +2 -2
  27. package/dist/design-system/components/bundle.js +7 -7
  28. package/dist/design-system/components/index.d.ts +1 -1
  29. package/dist/design-system/components/styles.css +457 -60
  30. package/dist/{index-ChJXlxzq.d.ts → index-CBAo353T.d.ts} +55 -1
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.js +1 -1
  33. package/dist/styles/components/Accordion.css +1 -1
  34. package/dist/styles/components/AlertDialog.css +1 -1
  35. package/dist/styles/components/Autocomplete.css +1 -1
  36. package/dist/styles/components/Avatar.css +1 -1
  37. package/dist/styles/components/Button.css +1 -1
  38. package/dist/styles/components/Checkbox.css +1 -1
  39. package/dist/styles/components/CheckboxGroup.css +1 -1
  40. package/dist/styles/components/Collapsible.css +1 -1
  41. package/dist/styles/components/Combobox.css +1 -1
  42. package/dist/styles/components/ContextMenu.css +1 -1
  43. package/dist/styles/components/Dialog.css +1 -1
  44. package/dist/styles/components/Drawer.css +8 -2
  45. package/dist/styles/components/Field.css +1 -1
  46. package/dist/styles/components/Fieldset.css +1 -1
  47. package/dist/styles/components/Form.css +1 -1
  48. package/dist/styles/components/Input.css +1 -1
  49. package/dist/styles/components/Menu.css +1 -1
  50. package/dist/styles/components/Menubar.css +1 -1
  51. package/dist/styles/components/Meter.css +1 -1
  52. package/dist/styles/components/NavigationMenu.css +1 -1
  53. package/dist/styles/components/NumberField.css +1 -1
  54. package/dist/styles/components/OTPField.css +1 -1
  55. package/dist/styles/components/Popover.css +1 -1
  56. package/dist/styles/components/PreviewCard.css +1 -1
  57. package/dist/styles/components/Progress.css +1 -1
  58. package/dist/styles/components/Radio.css +1 -1
  59. package/dist/styles/components/ScrollArea.css +1 -1
  60. package/dist/styles/components/Select.css +1 -1
  61. package/dist/styles/components/Separator.css +1 -1
  62. package/dist/styles/components/Slider.css +1 -1
  63. package/dist/styles/components/Switch.css +1 -1
  64. package/dist/styles/components/Tabs.css +1 -1
  65. package/dist/styles/components/Toast.css +1 -1
  66. package/dist/styles/components/Toggle.css +1 -1
  67. package/dist/styles/components/ToggleGroup.css +1 -1
  68. package/dist/styles/components/Toolbar.css +1 -1
  69. package/dist/styles/components/Tooltip.css +1 -1
  70. package/dist/styles/custom/Badge.css +1 -1
  71. package/dist/styles/custom/Collection.css +2 -2
  72. package/dist/styles/custom/CollectionPagination.css +1 -1
  73. package/dist/styles/custom/CollectionToolbar.css +87 -4
  74. package/dist/styles/custom/DataList.css +19 -1
  75. package/dist/styles/custom/DataTable.css +1 -1
  76. package/dist/styles/custom/DatePicker.css +1 -1
  77. package/dist/styles/custom/DescriptionList.css +75 -0
  78. package/dist/styles/custom/EditableList.css +1 -1
  79. package/dist/styles/custom/EmptyState.css +1 -1
  80. package/dist/styles/custom/ListDetail.css +1 -1
  81. package/dist/styles/custom/MoneyField.css +1 -1
  82. package/dist/styles/custom/Sheet.css +90 -0
  83. package/dist/styles/custom/Splitter.css +1 -1
  84. package/dist/styles/custom/StatFigure.css +60 -0
  85. package/dist/styles/custom/Table.css +63 -1
  86. package/dist/styles/index.css +4 -1
  87. package/dist/styles/reset/accessibility.css +1 -1
  88. package/dist/styles/reset/reset-accessibility.css +1 -1
  89. package/dist/styles/reset/reset-tailwind.css +2 -2
  90. package/dist/styles/reset/reset.css +2 -2
  91. package/dist/styles/tailwind.css +4 -1
  92. package/package.json +2 -2
  93. package/dist/chunk-JUUPOOQQ.js.map +0 -1
@@ -285,6 +285,7 @@ interface CollectionMessages {
285
285
  noResults: string;
286
286
  noResultsDescription: string;
287
287
  clearFilters: string;
288
+ clearSearch: string;
288
289
  nothingHere: string;
289
290
  previous: string;
290
291
  next: string;
@@ -431,12 +432,17 @@ interface DataTableProps<T> extends CollectionViewProps<T> {
431
432
  /** 'scroll' keeps the table. 'list' swaps in DataList when the table is narrower than collection.narrow-width. */
432
433
  narrow?: 'scroll' | 'list';
433
434
  size?: 'sm' | 'md';
435
+ /**
436
+ * How the footer's totals row looks. 'band' (the default) is the header tray. 'subtotal' rules
437
+ * a single line above it; 'grand' adds a double rule under it, as on a working paper.
438
+ */
439
+ totalStyle?: 'band' | 'subtotal' | 'grand';
434
440
  }
435
441
  /**
436
442
  * A data table, the APG pattern: one tab stop for the rows, headers announce sort, and it is
437
443
  * not a grid. A grid would say this is a spreadsheet, and it is not. AG Grid is that tool.
438
444
  */
439
- declare function DataTable<T>({ collection, label, caption, onRowActivate, getRowHref, activeRowId, rowActions, empty, loading, stickyHeader, stickyRowHeader, narrow, size, rowNavigation, className, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
445
+ declare function DataTable<T>({ collection, label, caption, onRowActivate, getRowHref, activeRowId, rowActions, empty, loading, stickyHeader, stickyRowHeader, narrow, size, totalStyle, rowNavigation, className, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
440
446
 
441
447
  interface CollectionPaginationProps {
442
448
  /** 1-based. */
@@ -486,11 +492,16 @@ declare function ToolbarTabs<T>({ collection, column }: {
486
492
  collection: CollectionApi<T>;
487
493
  column: CollectionColumn<T>;
488
494
  }): react_jsx_runtime.JSX.Element;
489
- declare function SearchField({ label, visible, value, onChange }: {
495
+ /**
496
+ * The icon and the clear button sit inside the field. The clear button is the only clear
497
+ * control and shows only when there is text. Escape clears too.
498
+ */
499
+ declare function SearchField({ label, visible, value, onChange, clearLabel }: {
490
500
  label: string;
491
501
  visible?: boolean;
492
502
  value: string;
493
503
  onChange: (value: string) => void;
504
+ clearLabel?: string;
494
505
  }): react_jsx_runtime.JSX.Element;
495
506
  declare function FilterControl<T>({ collection, column }: {
496
507
  collection: CollectionApi<T>;
@@ -443,6 +443,7 @@ function DataTable({
443
443
  stickyRowHeader = false,
444
444
  narrow = "scroll",
445
445
  size = "sm",
446
+ totalStyle = "band",
446
447
  rowNavigation,
447
448
  className
448
449
  }) {
@@ -487,6 +488,7 @@ function DataTable({
487
488
  stickyHeader,
488
489
  stickyRowHeader,
489
490
  size,
491
+ totalStyle,
490
492
  className,
491
493
  onRowActivate,
492
494
  getRowHref,
@@ -496,7 +498,7 @@ function DataTable({
496
498
  );
497
499
  return /* @__PURE__ */ jsx("div", { ref: narrowWidth.ref, className: cn("CollectionView", asList ? className : void 0), "data-narrow": narrowWidth.under ? "" : void 0, children: view });
498
500
  }
499
- function TableView({ collection, columns, label, caption, colSpan, leaves, navigate, allSelected, someSelected, loading, empty, stickyHeader, stickyRowHeader, size, className, onRowActivate, getRowHref, activeRowId, rowActions }) {
501
+ function TableView({ collection, columns, label, caption, colSpan, leaves, navigate, allSelected, someSelected, loading, empty, stickyHeader, stickyRowHeader, size, totalStyle, className, onRowActivate, getRowHref, activeRowId, rowActions }) {
500
502
  const roving = useRovingRows(leaves.length, navigate);
501
503
  const scrollerRef = React4.useRef(null);
502
504
  const [overflows, setOverflows] = React4.useState(false);
@@ -524,6 +526,7 @@ function TableView({ collection, columns, label, caption, colSpan, leaves, navig
524
526
  }, [stickyHeader, leaves.length, columns.length]);
525
527
  const filteredEmpty = collection.totalCount > 0 && collection.filteredCount === 0;
526
528
  const text = collection.messages;
529
+ const ruled = totalStyle !== "band";
527
530
  return /* @__PURE__ */ jsxs(
528
531
  "div",
529
532
  {
@@ -570,17 +573,20 @@ function TableView({ collection, columns, label, caption, colSpan, leaves, navig
570
573
  rowActions ? /* @__PURE__ */ jsx("th", { scope: "col", "data-width": "min", children: /* @__PURE__ */ jsx("span", { className: "visually-hidden", children: "Actions" }) }) : null
571
574
  ] }) }),
572
575
  collection.pageEntries.some((entry) => entry.kind === "group") ? groupedBodies({ collection, columns, leaves, roving, navigate, onRowActivate, getRowHref, activeRowId, rowActions, colSpan, filteredEmpty, empty, loading }) : /* @__PURE__ */ jsx("tbody", { children: bodyRows({ collection, columns, leaves, roving, navigate, onRowActivate, getRowHref, activeRowId, rowActions, colSpan, filteredEmpty, empty, loading }) }),
573
- Object.keys(collection.totals).length ? /* @__PURE__ */ jsx("tfoot", { children: /* @__PURE__ */ jsxs("tr", { children: [
574
- collection.canSelect ? /* @__PURE__ */ jsx("td", {}) : null,
575
- columns.map((column, index) => /* @__PURE__ */ jsxs("td", { "data-align": alignOf(column), children: [
576
- index === 0 ? text.total : typeof column.total === "function" ? column.total(collection.filteredRows) : collection.totals[column.id] ?? "",
577
- index === 0 && collection.isFiltered ? /* @__PURE__ */ jsxs("span", { className: "visually-hidden", children: [
578
- " of ",
579
- collection.filteredCount,
580
- " filtered rows"
581
- ] }) : null
582
- ] }, column.id)),
583
- rowActions ? /* @__PURE__ */ jsx("td", {}) : null
576
+ Object.keys(collection.totals).length ? /* @__PURE__ */ jsx("tfoot", { children: /* @__PURE__ */ jsxs("tr", { "data-total": ruled ? totalStyle : void 0, children: [
577
+ collection.canSelect ? /* @__PURE__ */ jsx("td", { "data-rule": ruled ? "none" : void 0 }) : null,
578
+ columns.map((column, index) => (
579
+ // Ruled totals draw their lines under the figures only, not the label or blank cells.
580
+ /* @__PURE__ */ jsxs("td", { "data-align": alignOf(column), "data-rule": ruled && (index === 0 || !column.total) ? "none" : void 0, children: [
581
+ index === 0 ? text.total : typeof column.total === "function" ? column.total(collection.filteredRows) : collection.totals[column.id] ?? "",
582
+ index === 0 && collection.isFiltered ? /* @__PURE__ */ jsxs("span", { className: "visually-hidden", children: [
583
+ " of ",
584
+ collection.filteredCount,
585
+ " filtered rows"
586
+ ] }) : null
587
+ ] }, column.id)
588
+ )),
589
+ rowActions ? /* @__PURE__ */ jsx("td", { "data-rule": ruled ? "none" : void 0 }) : null
584
590
  ] }) }) : null
585
591
  ]
586
592
  }
@@ -823,7 +829,8 @@ function CollectionToolbarImpl({ collection, searchLabel, searchLabelVisible, sh
823
829
  label: searchLabel ?? "Search",
824
830
  visible: searchLabelVisible,
825
831
  value: collection.search,
826
- onChange: collection.setSearch
832
+ onChange: collection.setSearch,
833
+ clearLabel: collection.messages.clearSearch
827
834
  }
828
835
  ) : null,
829
836
  selecting ? /* @__PURE__ */ jsxs("div", { className: "CollectionSelectionBar", role: "region", "aria-label": "Selection", children: [
@@ -848,7 +855,6 @@ function CollectionToolbarImpl({ collection, searchLabel, searchLabelVisible, sh
848
855
  }
849
856
  ) : null,
850
857
  showSort ? /* @__PURE__ */ jsx(SortControl, { collection }) : null,
851
- collection.isFiltered ? /* @__PURE__ */ jsx(Button, { emphasis: "quiet", onClick: collection.clearFilters, children: "Clear filters" }) : null,
852
858
  actions ? /* @__PURE__ */ jsx("div", { className: "CollectionToolbarActions", children: actions }) : null
853
859
  ] })
854
860
  ] }),
@@ -871,26 +877,43 @@ function ToolbarTabs({ collection, column }) {
871
877
  ] }, tabValue || "all");
872
878
  }) }) });
873
879
  }
874
- function SearchField({ label, visible, value, onChange }) {
880
+ function SearchField({ label, visible, value, onChange, clearLabel = "Clear search" }) {
875
881
  const id = React4.useId();
882
+ const input = React4.useRef(null);
876
883
  return /* @__PURE__ */ jsxs("div", { className: "CollectionSearch", children: [
877
884
  /* @__PURE__ */ jsx("label", { htmlFor: id, className: visible ? void 0 : "visually-hidden", children: label }),
878
- /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined", "aria-hidden": "true", children: "search" }),
879
- /* @__PURE__ */ jsx(
880
- Input,
881
- {
882
- id,
883
- type: "search",
884
- value,
885
- onChange: (event) => onChange(event.target.value),
886
- onKeyDown: (event) => {
887
- if (event.key === "Escape" && value) {
888
- event.preventDefault();
889
- onChange("");
885
+ /* @__PURE__ */ jsxs("div", { className: "CollectionSearchField", "data-filled": value ? "" : void 0, children: [
886
+ /* @__PURE__ */ jsx("span", { className: "CollectionSearchIcon material-symbols-outlined", "aria-hidden": "true", children: "search" }),
887
+ /* @__PURE__ */ jsx(
888
+ Input,
889
+ {
890
+ ref: input,
891
+ id,
892
+ type: "search",
893
+ value,
894
+ onChange: (event) => onChange(event.target.value),
895
+ onKeyDown: (event) => {
896
+ if (event.key === "Escape" && value) {
897
+ event.preventDefault();
898
+ onChange("");
899
+ }
890
900
  }
891
901
  }
892
- }
893
- )
902
+ ),
903
+ value ? /* @__PURE__ */ jsx(
904
+ "button",
905
+ {
906
+ type: "button",
907
+ className: "CollectionSearchClear",
908
+ "aria-label": clearLabel,
909
+ onClick: () => {
910
+ onChange("");
911
+ input.current?.focus();
912
+ },
913
+ children: /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined", "aria-hidden": "true", children: "close" })
914
+ }
915
+ ) : null
916
+ ] })
894
917
  ] });
895
918
  }
896
919
  function FilterControl({ collection, column }) {
@@ -1160,6 +1183,7 @@ var defaultMessages = {
1160
1183
  noResults: "No results",
1161
1184
  noResultsDescription: "Nothing matches the current search or filters.",
1162
1185
  clearFilters: "Clear filters",
1186
+ clearSearch: "Clear search",
1163
1187
  nothingHere: "Nothing here yet",
1164
1188
  previous: "Previous",
1165
1189
  next: "Next",