@svelte-lean/table 0.13.4 → 0.14.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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @svelte-lean/table
2
2
 
3
+ ## 0.14.1
4
+
5
+ No changes in this release.
6
+
7
+ ## 0.14.0
8
+
9
+ ### Minor Changes
10
+
11
+ - 6e9ed18: The theme hooks follow the palette names: `--slean-table-accent` is renamed `--slean-table-primary` and `--slean-table-danger` is renamed `--slean-table-error` (breaking in 0.x; no alias).
12
+ - ab929e6: `DataTable` takes `refreshing` for a quiet background refresh (a poll, an invalidation): the root carries `data-refreshing` and the stylesheet draws a thin line along the top edge (`--slean-table-refreshing-color`, the accent; `--slean-table-refreshing-height`, 2px), which pulses only when the user has not asked for reduced motion. Rows stay as they are: no skeleton, no dimming, no `aria-busy`, no status text, and the page clamp stays active. `loading` and `fetching` win over it. New token `--slean-table-skeleton-delay` (default `0s`) keeps skeleton rows invisible for that long with a CSS animation delay and no timer, so an answer faster than the delay shows no skeleton flash.
13
+
14
+ Size budget raised for this feature: the table stylesheet from 7950 B to 8250 B gzip (8102 B measured, was 7873 B). The renderer stays within its budget (22734 B of 22800 B).
15
+
16
+ ### Patch Changes
17
+
18
+ - a9d1e1f: Follows the renamed `@svelte-lean/styles` tokens (`--slean-primary-main`, `--slean-error-main`, `--slean-elevation-*`, …; fallbacks kept) and writes `data-size="small"` on the page-size select (ADR 0011 §3.3).
19
+
3
20
  ## 0.13.4
4
21
 
5
22
  ### Patch Changes
package/README.md CHANGED
@@ -70,7 +70,8 @@ Composition hooks:
70
70
  - Server tables: `manual` with `rowCount`, or `pageCount` when the total is unknown; `searchDelay`
71
71
  debounces the search box and the filter inputs; `searchText` replaces what a row is searched by;
72
72
  `state.search` applies without the table's own search box. `loading` without rows draws
73
- `skeletonRows`; `fetching` dims the body.
73
+ `skeletonRows` (held invisible for `--slean-table-skeleton-delay`); `fetching` dims the body;
74
+ `refreshing` (a poll, an invalidation) only draws a thin line along the top edge.
74
75
  - `pageSizeOptions`, numbered pages, `placeholder` for empty values, `headerClass`, per-row `class`.
75
76
 
76
77
  ## Below the component
@@ -117,7 +118,7 @@ import '@svelte-lean/table/style.css';
117
118
 
118
119
  `style.css` styles the `slean-table-` classes. Its rules sit in the `slean.components` cascade layer
119
120
  with `:where()` selectors, so unlayered application CSS overrides them without `!important`. It reads
120
- `@svelte-lean/styles` tokens (`--slean-surface`, `--slean-fg`, `--slean-border`, `--slean-accent`,
121
+ `@svelte-lean/styles` tokens (`--slean-surface`, `--slean-fg`, `--slean-border`, `--slean-primary-main`,
121
122
  `--slean-radius-*`, …) when they are defined; the fallbacks are the same defaults written with
122
123
  `light-dark()`, so they follow the page's `color-scheme`. Override any `--slean-table-*` property
123
124
  (`--slean-table-header-bg`, `--slean-table-row-hover`, `--slean-table-cell-padding-y`, … listed on
package/dist/style.css CHANGED
@@ -13,7 +13,7 @@
13
13
  inline-size: 1rem;
14
14
  block-size: 1rem;
15
15
  margin: 0;
16
- accent-color: var(--slean-table-accent);
16
+ accent-color: var(--slean-table-primary);
17
17
  vertical-align: middle;
18
18
  cursor: pointer;
19
19
  }
@@ -35,15 +35,18 @@
35
35
  --slean-muted,
36
36
  light-dark(oklch(95.8% 0.004 260), oklch(26% 0.011 260))
37
37
  );
38
- --slean-table-accent: var(--slean-accent, light-dark(oklch(54% 0.19 258), oklch(56% 0.18 258)));
38
+ --slean-table-primary: var(
39
+ --slean-primary-main,
40
+ light-dark(oklch(54% 0.19 258), oklch(56% 0.18 258))
41
+ );
39
42
  --slean-table-selected: var(
40
- --slean-accent-soft,
43
+ --slean-primary-soft,
41
44
  light-dark(oklch(95% 0.03 258), oklch(28% 0.07 258))
42
45
  );
43
- --slean-table-danger: var(--slean-danger, light-dark(oklch(55% 0.2 25), oklch(58% 0.19 25)));
44
- --slean-table-focus: var(--slean-focus-ring-color, var(--slean-table-accent));
46
+ --slean-table-error: var(--slean-error-main, light-dark(oklch(55% 0.2 25), oklch(58% 0.19 25)));
47
+ --slean-table-focus: var(--slean-focus-ring-color, var(--slean-table-primary));
45
48
  --slean-table-shadow: var(
46
- --slean-shadow-lg,
49
+ --slean-elevation-4,
47
50
  0 16px 40px oklch(0% 0 0 / 0.18),
48
51
  0 2px 6px oklch(0% 0 0 / 0.08)
49
52
  );
@@ -78,11 +81,14 @@
78
81
  --slean-table-row-selected: var(--slean-table-selected);
79
82
  --slean-table-pin-shadow: light-dark(oklch(0% 0 0 / 0.1), oklch(0% 0 0 / 0.45));
80
83
  --slean-table-row-lifted-shadow: var(
81
- --slean-shadow-md,
84
+ --slean-elevation-3,
82
85
  0 4px 12px light-dark(oklch(0% 0 0 / 0.1), oklch(0% 0 0 / 0.5)),
83
86
  0 1px 3px light-dark(oklch(0% 0 0 / 0.08), oklch(0% 0 0 / 0.4))
84
87
  );
85
88
  --slean-table-fetching-opacity: 0.55;
89
+ --slean-table-skeleton-delay: 0s;
90
+ --slean-table-refreshing-color: var(--slean-table-primary);
91
+ --slean-table-refreshing-height: 2px;
86
92
  /* Set per row by hover, stripes, selection or `rowClass`; reset here so it never leaks into a
87
93
  table nested in a detail row. */
88
94
  --slean-table-row-bg: initial;
@@ -162,10 +168,7 @@
162
168
  :where(.slean-table-input:focus-visible) {
163
169
  border-color: var(--slean-table-focus);
164
170
  outline: 2px solid transparent;
165
- box-shadow: var(
166
- --slean-control-ring,
167
- 0 0 0 3px color-mix(in oklab, var(--slean-table-focus) 22%, transparent)
168
- );
171
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--slean-table-focus) 22%, transparent);
169
172
  }
170
173
  :where(
171
174
  .slean-table-button,
@@ -451,7 +454,7 @@
451
454
  touch-action: none;
452
455
  }
453
456
  :where(.slean-table-resize:hover, .slean-table-resize:focus-visible) {
454
- background: linear-gradient(var(--slean-table-accent), var(--slean-table-accent)) center / 2px
457
+ background: linear-gradient(var(--slean-table-primary), var(--slean-table-primary)) center / 2px
455
458
  100% no-repeat;
456
459
  }
457
460
  :where(.slean-table-filter) {
@@ -500,7 +503,7 @@
500
503
  stroke-width: 2.5;
501
504
  }
502
505
 
503
- /* Row controls: 24px ghost icon buttons. */
506
+ /* Row controls: 24px borderless icon buttons. */
504
507
  :where(.slean-table-expand, .slean-table-edit, .slean-table-grip) {
505
508
  min-inline-size: 1.5rem;
506
509
  min-block-size: 1.5rem;
@@ -652,7 +655,7 @@
652
655
  }
653
656
  :where(.slean-table-scroll > table > tbody > tr > td[data-range='true']) {
654
657
  background: var(--slean-table-selected);
655
- box-shadow: inset 0 0 0 1px var(--slean-table-accent);
658
+ box-shadow: inset 0 0 0 1px var(--slean-table-primary);
656
659
  }
657
660
 
658
661
  /* A dragged row (row-drag.ts): opaque and raised over the body, below the sticky header (5);
@@ -713,13 +716,31 @@
713
716
  :where(.slean-table[data-fetching] > .slean-table-scroll > table > tbody) {
714
717
  opacity: var(--slean-table-fetching-opacity);
715
718
  }
719
+ /* Skeleton rows stay invisible for the delay (no timer); `refreshing` draws a top line. */
720
+ :where(.slean-table-skeleton-row) {
721
+ animation: slean-table-appear 0s var(--slean-table-skeleton-delay) both;
722
+ }
723
+ :where(.slean-table[data-refreshing]) {
724
+ position: relative;
725
+ }
726
+ :where(.slean-table[data-refreshing])::after {
727
+ content: '';
728
+ position: absolute;
729
+ inset-block-start: 0;
730
+ inset-inline: var(--slean-table-radius);
731
+ z-index: 6;
732
+ block-size: var(--slean-table-refreshing-height);
733
+ background: var(--slean-table-refreshing-color);
734
+ opacity: 0.6;
735
+ pointer-events: none;
736
+ }
716
737
  :where(.slean-table-error) {
717
738
  display: flex;
718
739
  align-items: center;
719
740
  gap: 0.75rem;
720
741
  padding: 0.625rem 0.75rem;
721
- color: var(--slean-table-danger);
722
- background: color-mix(in oklab, var(--slean-table-danger) 8%, var(--slean-table-bg));
742
+ color: var(--slean-table-error);
743
+ background: color-mix(in oklab, var(--slean-table-error) 8%, var(--slean-table-bg));
723
744
  }
724
745
  :where(.slean-table-editor) {
725
746
  display: flex;
@@ -732,7 +753,7 @@
732
753
  min-width: 4.5rem;
733
754
  }
734
755
  :where(.slean-table-editor > [role='alert']) {
735
- color: var(--slean-table-danger);
756
+ color: var(--slean-table-error);
736
757
  width: 100%;
737
758
  font-size: 0.75rem;
738
759
  }
@@ -863,6 +884,20 @@
863
884
  0 0 / 200% 100% var(--slean-table-soft);
864
885
  animation: slean-table-shimmer 1.6s linear infinite;
865
886
  }
887
+ /* The line pulses; with reduced motion it stays still. */
888
+ :where(.slean-table[data-refreshing])::after {
889
+ animation: slean-table-pulse 0.8s ease-in-out infinite alternate;
890
+ }
891
+ }
892
+ @keyframes slean-table-appear {
893
+ from {
894
+ opacity: 0;
895
+ }
896
+ }
897
+ @keyframes slean-table-pulse {
898
+ from {
899
+ opacity: 0.2;
900
+ }
866
901
  }
867
902
  @keyframes slean-table-shimmer {
868
903
  from {
@@ -111,6 +111,7 @@
111
111
  onExpandedRowsChange,
112
112
  loading = false,
113
113
  fetching = false,
114
+ refreshing = false,
114
115
  skeletonRows,
115
116
  measureKey,
116
117
  error,
@@ -1608,6 +1609,7 @@
1608
1609
  data-bordered={bordered}
1609
1610
  data-hoverable={rowHoverable}
1610
1611
  data-fetching={fetching || undefined}
1612
+ data-refreshing={(refreshing && !loading && !fetching) || undefined}
1611
1613
  {...dir ? { dir } : {}}
1612
1614
  >
1613
1615
  {#if title}<div class="slean-table-title">{@render title(model)}</div>{/if}
@@ -1879,7 +1881,7 @@
1879
1881
  · <span class="slean-table-selected">{m.selected(s.selection.length)}</span>{/if}</span
1880
1882
  >{#if pageSizeSelect === 'custom'}<span class="slean-table-page-size"
1881
1883
  ><span id="{uid}-page-size">{m.pageSize}</span>
1882
- <div class="slean-table-page-select" {...SELECT_ROOT} data-size="sm">
1884
+ <div class="slean-table-page-select" {...SELECT_ROOT} data-size="small">
1883
1885
  <select
1884
1886
  data-slean-part="native"
1885
1887
  aria-labelledby="{uid}-page-size"
package/dist/types.d.ts CHANGED
@@ -274,9 +274,17 @@ export interface TableProps<T> {
274
274
  onExpandedRowsChange?: (rows: RowId[]) => void;
275
275
  loading?: boolean;
276
276
  fetching?: boolean;
277
+ /**
278
+ * A quiet background refresh (a poll, an invalidation): a thin line along the top edge, nothing
279
+ * else. Rows are never replaced by skeletons or dimmed, no `aria-busy`, no status text, and page
280
+ * clamping stays active. Ignored while `loading` or `fetching` is set, which say more.
281
+ */
282
+ refreshing?: boolean;
277
283
  /**
278
284
  * Skeleton rows drawn while `loading` and no row is present. Default: the page size, at most
279
285
  * 25, when paginated (so nothing below the table moves when the rows arrive); otherwise 5.
286
+ * `--slean-table-skeleton-delay` holds them invisible for a moment (CSS only, no timer), so a
287
+ * fast first answer shows no skeleton flash.
280
288
  */
281
289
  skeletonRows?: number;
282
290
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svelte-lean/table",
3
- "version": "0.13.4",
3
+ "version": "0.14.1",
4
4
  "description": "A Svelte-native table and data-grid engine that ships only the features you use.",
5
5
  "license": "MIT",
6
6
  "author": "Ömer Say",