@coldsmirk/ledger-mantine 0.4.0 → 0.5.1

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
@@ -1063,6 +1063,10 @@ function resolveIcons(icons) {
1063
1063
  const defaultLabels = {
1064
1064
  paginationSummary: (from, to, total) => `${from}–${to} of ${total}`,
1065
1065
  rowsPerPage: "Rows per page",
1066
+ firstPage: "First page",
1067
+ previousPage: "Previous page",
1068
+ nextPage: "Next page",
1069
+ lastPage: "Last page",
1066
1070
  selectAllRows: "Select all rows",
1067
1071
  selectRow: "Select row",
1068
1072
  selectedCount: (count) => `${count} selected`,
@@ -1091,6 +1095,12 @@ const defaultLabels = {
1091
1095
  filterPlaceholder: "Filter…",
1092
1096
  filterRangeMin: "Min",
1093
1097
  filterRangeMax: "Max",
1098
+ previousMonth: "Previous month",
1099
+ nextMonth: "Next month",
1100
+ previousYear: "Previous year",
1101
+ nextYear: "Next year",
1102
+ previousDecade: "Previous decade",
1103
+ nextDecade: "Next decade",
1094
1104
  searchPlaceholder: "Search…",
1095
1105
  loading: "Loading",
1096
1106
  empty: "No data",
@@ -1576,6 +1586,12 @@ const DEFAULT_PAGE_SIZE_OPTIONS = [
1576
1586
  50,
1577
1587
  100
1578
1588
  ];
1589
+ const CONTROL_LABELS = {
1590
+ first: "firstPage",
1591
+ previous: "previousPage",
1592
+ next: "nextPage",
1593
+ last: "lastPage"
1594
+ };
1579
1595
  function PaginationBarCore({ table, labels, pageSizeOptions, size, className, style }) {
1580
1596
  const pageSizeLabelId = useId();
1581
1597
  const { pageIndex, pageSize } = table.atoms.pagination.get();
@@ -1591,7 +1607,7 @@ function PaginationBarCore({ table, labels, pageSizeOptions, size, className, st
1591
1607
  style,
1592
1608
  wrap: "wrap",
1593
1609
  children: [/* @__PURE__ */ jsx(Text, {
1594
- c: "dimmed",
1610
+ c: "var(--ledger-color-dimmed)",
1595
1611
  size,
1596
1612
  children: labels.paginationSummary(from, to, total)
1597
1613
  }), /* @__PURE__ */ jsxs(Group, {
@@ -1601,7 +1617,7 @@ function PaginationBarCore({ table, labels, pageSizeOptions, size, className, st
1601
1617
  gap: "xs",
1602
1618
  wrap: "nowrap",
1603
1619
  children: [/* @__PURE__ */ jsx(Text, {
1604
- c: "dimmed",
1620
+ c: "var(--ledger-color-dimmed)",
1605
1621
  id: pageSizeLabelId,
1606
1622
  size,
1607
1623
  children: labels.rowsPerPage
@@ -1615,6 +1631,9 @@ function PaginationBarCore({ table, labels, pageSizeOptions, size, className, st
1615
1631
  onChange: (value) => value !== null && table.setPageSize(Number(value))
1616
1632
  })]
1617
1633
  }), /* @__PURE__ */ jsx(Pagination, {
1634
+ getControlProps: (control) => {
1635
+ return { "aria-label": labels[CONTROL_LABELS[control]] };
1636
+ },
1618
1637
  size: SIZES[size].control,
1619
1638
  total: pageCount,
1620
1639
  value: pageIndex + 1,
@@ -3036,6 +3055,14 @@ function autosizeColumn(setColumnSizing, { columnId, minSize, maxSize, hasFilter
3036
3055
  * a black box that may ship no clear of its own — keeps the popover-level fallback.
3037
3056
  */
3038
3057
  const FACETED_OPTIONS_CAP = 100;
3058
+ /**
3059
+ * The smallest pointer target WCAG 2.2 AA accepts without spacing around it, in px.
3060
+ */
3061
+ const MIN_TARGET_SIZE = 24;
3062
+ /**
3063
+ * The calendar's weekend color, as the variable Mantine's day rule reads (see DateRangeFilter).
3064
+ */
3065
+ const WEEKEND_COLOR = { "--mantine-color-red-6": "color-mix(in srgb, var(--mantine-color-red-text), var(--mantine-color-text) 30%)" };
3039
3066
  function FilterPopover({ column }) {
3040
3067
  const { labels, icons, getStyles, filterMode, size } = useDataTableContext();
3041
3068
  const filter = column.columnDef.meta?.filter;
@@ -3049,6 +3076,8 @@ function FilterPopover({ column }) {
3049
3076
  children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(ActionIcon, {
3050
3077
  "aria-label": name,
3051
3078
  "data-active": active || void 0,
3079
+ mih: MIN_TARGET_SIZE,
3080
+ miw: MIN_TARGET_SIZE,
3052
3081
  size: SIZES[size].control,
3053
3082
  variant: active ? "light" : "subtle",
3054
3083
  onClick: (event) => event.stopPropagation(),
@@ -3230,11 +3259,21 @@ function DateRangeFilter({ column, name }) {
3230
3259
  const filterValue = column.getFilterValue();
3231
3260
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DatePicker, {
3232
3261
  allowSingleDateInRange: true,
3262
+ hideOutsideDates: true,
3233
3263
  highlightToday: true,
3234
3264
  "aria-label": name,
3235
3265
  size: "xs",
3266
+ style: WEEKEND_COLOR,
3236
3267
  type: "range",
3237
3268
  value: filterValue ?? [null, null],
3269
+ ariaLabels: {
3270
+ previousMonth: labels.previousMonth,
3271
+ nextMonth: labels.nextMonth,
3272
+ previousYear: labels.previousYear,
3273
+ nextYear: labels.nextYear,
3274
+ previousDecade: labels.previousDecade,
3275
+ nextDecade: labels.nextDecade
3276
+ },
3238
3277
  onChange: (next) => column.setFilterValue(!next[0] && !next[1] ? void 0 : next)
3239
3278
  }), filterValue !== void 0 && /* @__PURE__ */ jsx(Group, {
3240
3279
  justify: "flex-end",
@@ -3812,6 +3851,28 @@ const builtInFilterFns = {
3812
3851
  startsWith: filterFn_startsWith,
3813
3852
  weakEquals: filterFn_weakEquals
3814
3853
  };
3854
+ /**
3855
+ * Typed through the exported definitions on purpose. Since 9.2.5 TanStack's published `.d.ts`
3856
+ * files no longer end in an `export { … }` list (rolldown-plugin-dts 0.28 inlines the exports and
3857
+ * drops the marker), so TypeScript treats every top-level declaration in them as exported: the
3858
+ * private `RangeValue` alias behind the min/max/extent value types becomes nameable only by a
3859
+ * deep path the package's `exports` map hides, and an inferred registry fails declaration emit
3860
+ * (TS2883). Naming each definition by its public export emits the type the upstream fix will
3861
+ * emit anyway. Upstream: sxzz/rolldown-plugin-dts#312 (fix: #310), rolldown/tsdown#1087.
3862
+ */
3863
+ const builtInAggregationFns = {
3864
+ count: aggregationFn_count,
3865
+ extent: aggregationFn_extent,
3866
+ first: aggregationFn_first,
3867
+ last: aggregationFn_last,
3868
+ max: aggregationFn_max,
3869
+ mean: aggregationFn_mean,
3870
+ median: aggregationFn_median,
3871
+ min: aggregationFn_min,
3872
+ sum: aggregationFn_sum,
3873
+ unique: aggregationFn_unique,
3874
+ uniqueCount: aggregationFn_uniqueCount
3875
+ };
3815
3876
  const ledgerFeatures = tableFeatures({
3816
3877
  cellSpanningFeature,
3817
3878
  columnFacetingFeature,
@@ -3836,19 +3897,7 @@ const ledgerFeatures = tableFeatures({
3836
3897
  groupedRowModel: createGroupedRowModel(),
3837
3898
  paginatedRowModel: createPaginatedRowModel(),
3838
3899
  sortedRowModel: createSortedRowModel(),
3839
- aggregationFns: {
3840
- count: aggregationFn_count,
3841
- extent: aggregationFn_extent,
3842
- first: aggregationFn_first,
3843
- last: aggregationFn_last,
3844
- max: aggregationFn_max,
3845
- mean: aggregationFn_mean,
3846
- median: aggregationFn_median,
3847
- min: aggregationFn_min,
3848
- sum: aggregationFn_sum,
3849
- unique: aggregationFn_unique,
3850
- uniqueCount: aggregationFn_uniqueCount
3851
- },
3900
+ aggregationFns: builtInAggregationFns,
3852
3901
  filterFns: {
3853
3902
  ...builtInFilterFns,
3854
3903
  ...ledgerFilterFns
@@ -6369,6 +6418,33 @@ function useStylesRevision(getStyles, selectors) {
6369
6418
  return revision;
6370
6419
  }
6371
6420
  //#endregion
6421
+ //#region src/use-viewport-overflow.ts
6422
+ /**
6423
+ * Whether the body viewport scrolls on either axis. A scroll container has to be reachable by
6424
+ * keyboard to be scrolled by it (WCAG 2.1.1), while a focus stop over content that fits is a
6425
+ * Tab press spent on nothing — so the viewport's focus stop follows this.
6426
+ *
6427
+ * Measured whenever the viewport or its content resizes: rows arriving, columns widening, or
6428
+ * the host resizing the table each change the answer without a scroll event. A 1px tolerance
6429
+ * absorbs fractional layout rounding, which would otherwise flicker the stop on and off.
6430
+ */
6431
+ function useViewportOverflow(viewport) {
6432
+ const [overflowing, setOverflowing] = useState(false);
6433
+ useLayoutEffect(() => {
6434
+ if (!viewport) return;
6435
+ const measure = () => {
6436
+ const next = viewport.scrollHeight - viewport.clientHeight > 1 || viewport.scrollWidth - viewport.clientWidth > 1;
6437
+ setOverflowing(next);
6438
+ };
6439
+ measure();
6440
+ const observer = new ResizeObserver(measure);
6441
+ observer.observe(viewport);
6442
+ if (viewport.firstElementChild) observer.observe(viewport.firstElementChild);
6443
+ return () => observer.disconnect();
6444
+ }, [viewport]);
6445
+ return overflowing;
6446
+ }
6447
+ //#endregion
6372
6448
  //#region src/data-table.tsx
6373
6449
  /**
6374
6450
  * The root component (docs/api.md): a generic Mantine factory with full Styles API,
@@ -6426,7 +6502,7 @@ const STYLE_SELECTORS = Object.keys(classes);
6426
6502
  */
6427
6503
  const NO_ARIA_ROWS = [];
6428
6504
  const EMPTY_STATE_STYLES = { title: {
6429
- color: "var(--mantine-color-dimmed)",
6505
+ color: "var(--ledger-color-dimmed)",
6430
6506
  fontWeight: 500
6431
6507
  } };
6432
6508
  const defaultProps = {
@@ -6618,6 +6694,7 @@ function DataTableCore({ presentation, stylesProps, table }) {
6618
6694
  viewportRef.current = element;
6619
6695
  setViewport(element);
6620
6696
  }, []);
6697
+ const viewportOverflows = useViewportOverflow(viewport);
6621
6698
  const startLeafColumns = table.getStartVisibleLeafColumns();
6622
6699
  const endLeafColumns = table.getEndVisibleLeafColumns();
6623
6700
  const displayColumns = [
@@ -6833,7 +6910,7 @@ function DataTableCore({ presentation, stylesProps, table }) {
6833
6910
  rowPinningActive,
6834
6911
  withDetailPanels
6835
6912
  ]);
6836
- const bodyAriaRowCount = loading && logicalDisplayRowCount === 0 ? skeletonRowCount : logicalDisplayRowCount + (loadMoreError || loadingMore ? 1 : 0);
6913
+ const bodyAriaRowCount = loading && logicalDisplayRowCount === 0 ? skeletonRowCount : logicalDisplayRowCount + (loadMoreError || loadingMore ? 1 : 0) + (isEmpty || errorActive ? 1 : 0);
6837
6914
  const footerRowCount = visibleFooterGroups(table).length;
6838
6915
  const ariaRowCount = headerRowCount + bodyAriaRowCount + footerRowCount;
6839
6916
  const footerAriaRowIndexStart = headerRowCount + bodyAriaRowCount + 1;
@@ -7207,11 +7284,10 @@ function DataTableCore({ presentation, stylesProps, table }) {
7207
7284
  },
7208
7285
  viewportProps: mergeElementProps(viewportProps, {
7209
7286
  style: { overscrollBehavior: "none" },
7287
+ role: "rowgroup",
7210
7288
  "aria-describedby": viewportDescribedBy,
7211
- ...activeRowEnabled && {
7212
- tabIndex: 0,
7213
- onKeyDown: handleActiveRowKeyDown
7214
- }
7289
+ tabIndex: activeRowEnabled || viewportOverflows ? 0 : void 0,
7290
+ ...activeRowEnabled && { onKeyDown: handleActiveRowKeyDown }
7215
7291
  }),
7216
7292
  onScrollPositionChange: handleScrollPositionChange,
7217
7293
  children: [
@@ -7234,43 +7310,59 @@ function DataTableCore({ presentation, stylesProps, table }) {
7234
7310
  })]
7235
7311
  }),
7236
7312
  isEmpty && /* @__PURE__ */ jsx("div", {
7237
- ...getStyles("empty"),
7238
- "data-variant": filtersActive ? "no-results" : "no-data",
7239
- role: "status",
7240
- children: emptyState ?? /* @__PURE__ */ jsx(EmptyState, {
7241
- withIndicatorBackground: true,
7242
- size: "sm",
7243
- styles: EMPTY_STATE_STYLES,
7244
- title: filtersActive ? labels.noResults : labels.empty,
7245
- icon: filtersActive ? /* @__PURE__ */ jsx(icons.noResults, {
7246
- size: 40,
7247
- strokeWidth: 1.5
7248
- }) : /* @__PURE__ */ jsx(icons.empty, {
7249
- size: 40,
7250
- strokeWidth: 1.5
7313
+ "aria-rowindex": virtualEnabled ? headerRowCount + bodyAriaRowCount : void 0,
7314
+ role: "row",
7315
+ children: /* @__PURE__ */ jsx("div", {
7316
+ ...getStyles("empty"),
7317
+ "aria-colspan": visibleLeafColumns.length,
7318
+ "data-variant": filtersActive ? "no-results" : "no-data",
7319
+ role: "cell",
7320
+ children: /* @__PURE__ */ jsx("div", {
7321
+ role: "status",
7322
+ children: emptyState ?? /* @__PURE__ */ jsx(EmptyState, {
7323
+ withIndicatorBackground: true,
7324
+ size: "sm",
7325
+ styles: EMPTY_STATE_STYLES,
7326
+ title: filtersActive ? labels.noResults : labels.empty,
7327
+ icon: filtersActive ? /* @__PURE__ */ jsx(icons.noResults, {
7328
+ size: 40,
7329
+ strokeWidth: 1.5
7330
+ }) : /* @__PURE__ */ jsx(icons.empty, {
7331
+ size: 40,
7332
+ strokeWidth: 1.5
7333
+ })
7334
+ })
7251
7335
  })
7252
7336
  })
7253
7337
  }),
7254
7338
  errorActive && /* @__PURE__ */ jsx("div", {
7255
- ...getStyles("empty"),
7256
- "data-over-rows": rowsLength > 0 || void 0,
7257
- "data-variant": "error",
7258
- role: "alert",
7259
- children: /* @__PURE__ */ jsx(EmptyState, {
7260
- withIndicatorBackground: true,
7261
- icon: /* @__PURE__ */ jsx(icons.error, {
7262
- size: 40,
7263
- strokeWidth: 1.5
7264
- }),
7265
- size: "sm",
7266
- styles: EMPTY_STATE_STYLES,
7267
- title: error === true ? labels.error : error,
7268
- children: onRetry && /* @__PURE__ */ jsx(Button, {
7269
- leftSection: /* @__PURE__ */ jsx(icons.retry, { size: 14 }),
7270
- size: "xs",
7271
- variant: "light",
7272
- onClick: onRetry,
7273
- children: labels.retry
7339
+ "aria-rowindex": virtualEnabled ? headerRowCount + bodyAriaRowCount : void 0,
7340
+ role: "row",
7341
+ children: /* @__PURE__ */ jsx("div", {
7342
+ ...getStyles("empty"),
7343
+ "aria-colspan": visibleLeafColumns.length,
7344
+ "data-over-rows": rowsLength > 0 || void 0,
7345
+ "data-variant": "error",
7346
+ role: "cell",
7347
+ children: /* @__PURE__ */ jsx("div", {
7348
+ role: "alert",
7349
+ children: /* @__PURE__ */ jsx(EmptyState, {
7350
+ withIndicatorBackground: true,
7351
+ icon: /* @__PURE__ */ jsx(icons.error, {
7352
+ size: 40,
7353
+ strokeWidth: 1.5
7354
+ }),
7355
+ size: "sm",
7356
+ styles: EMPTY_STATE_STYLES,
7357
+ title: error === true ? labels.error : error,
7358
+ children: onRetry && /* @__PURE__ */ jsx(Button, {
7359
+ leftSection: /* @__PURE__ */ jsx(icons.retry, { size: 14 }),
7360
+ size: "xs",
7361
+ variant: "light",
7362
+ onClick: onRetry,
7363
+ children: labels.retry
7364
+ })
7365
+ })
7274
7366
  })
7275
7367
  })
7276
7368
  })