@marianmeres/stuic 3.165.0 → 3.167.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/API.md CHANGED
@@ -582,11 +582,13 @@ Closeable message banner with intent styling.
582
582
 
583
583
  #### `Progress`
584
584
 
585
- Progress bar.
585
+ Progress bar or circle.
586
586
 
587
- | Prop | Type | Default | Description |
588
- | ------- | -------- | ------- | ------------------------ |
589
- | `value` | `number` | `0` | Current progress (0-100) |
587
+ | Prop | Type | Default | Description |
588
+ | ---------- | ------------------- | ------- | --------------------------------- |
589
+ | `progress` | `number` | `0` | Current progress (0-100, clamped) |
590
+ | `type` | `"bar" \| "circle"` | `"bar"` | Rendering variant |
591
+ | `classBar` | `string` | - | Classes for the inner fill (bar) |
590
592
 
591
593
  #### `Spinner`
592
594
 
@@ -1085,19 +1087,20 @@ Swap visibility between N states with opacity transitions. Commonly used for ham
1085
1087
 
1086
1088
  Responsive data table with paging, row selection, batch actions, and mobile card view.
1087
1089
 
1088
- | Prop | Type | Default | Description |
1089
- | ------------------ | --------------------------------------------- | -------- | --------------------------------------------------- |
1090
- | `columns` | `DataTableColumn<T>[]` | required | Column definitions |
1091
- | `data` | `T[]` | required | Row data objects |
1092
- | `getRowId` | `(row: T, index: number) => string \| number` | index | Unique row ID extractor |
1093
- | `paging` | `PagingCalcResult` | — | Paging calculation from `@marianmeres/paging-store` |
1094
- | `onPageChange` | `(offset: number) => void` | — | Page navigation callback |
1095
- | `selectable` | `boolean` | `false` | Enable row selection checkboxes |
1096
- | `selected` | `Set<string \| number>` | | Bindable set of selected row IDs |
1097
- | `selectOnRowClick` | `boolean` | `false` | Toggle selection on row click |
1098
- | `onRowClick` | `(row: T, index: number) => void` | — | Row click callback |
1099
- | `loading` | `boolean` | `false` | Show loading overlay |
1100
- | `t` | `TranslateFn` | built-in | Translation function for i18n |
1090
+ | Prop | Type | Default | Description |
1091
+ | ------------------ | --------------------------------------------- | -------- | ------------------------------------------------------------ |
1092
+ | `columns` | `DataTableColumn<T>[]` | required | Column definitions |
1093
+ | `data` | `T[]` | required | Row data objects |
1094
+ | `getRowId` | `(row: T, index: number) => string \| number` | index | Unique row ID extractor |
1095
+ | `paging` | `PagingCalcResult` | — | Paging calculation from `@marianmeres/paging-store` |
1096
+ | `onPageChange` | `(offset: number) => void` | — | Page navigation callback |
1097
+ | `showPager` | `boolean` | `true` | Render the built-in pager (`false` keeps `paging` data only) |
1098
+ | `selectable` | `boolean` | `false` | Enable row selection checkboxes |
1099
+ | `selected` | `Set<string \| number>` | | Bindable set of selected row IDs |
1100
+ | `selectOnRowClick` | `boolean` | `false` | Toggle selection on row click |
1101
+ | `onRowClick` | `(row: T, index: number) => void` | | Row click callback |
1102
+ | `loading` | `boolean` | `false` | Show loading overlay |
1103
+ | `t` | `TranslateFn` | built-in | Translation function for i18n |
1101
1104
 
1102
1105
  **Snippets:** `cell`, `batchActions`, `empty`, `mobileRow`
1103
1106
 
@@ -1206,12 +1209,26 @@ Responsive wrapper around Book that intelligently switches between book mode (du
1206
1209
 
1207
1210
  #### `Circle`
1208
1211
 
1209
- SVG-based circular progress indicator with configurable stroke width and rotation.
1212
+ SVG-based circular progress indicator (a Svelte wrapper around the [`svgCircle`](#svgcircleoptions)
1213
+ utility). The svg fills its container over a fixed `100x100` viewBox, so the container
1214
+ sets the size and `strokeWidth` is in viewBox units. The stroke is `currentColor`.
1215
+
1216
+ | Prop | Type | Default | Description |
1217
+ | ----------------------- | --------- | ------- | ---------------------------------------------------------------- |
1218
+ | `completeness` | `number` | `1` | Progress from 0 to 1 (clamped) |
1219
+ | `strokeWidth` | `number` | `10` | Stroke width in viewBox units (radius = `50 - strokeWidth / 2`) |
1220
+ | `strokeWidthRatio` | `number` | `0` | Caps `strokeWidth` at this fraction of the radius (`0` = no cap) |
1221
+ | `bgStrokeColor` | `string` | - | CSS color of the background ring behind the arc |
1222
+ | `roundedEdges` | `boolean` | `true` | Rounded (vs butt) stroke line caps |
1223
+ | `rotate` | `number` | `0` | Rotation in degrees (arc starts at 3 o'clock; `-90` = top) |
1224
+ | `animateCompletenessMs` | `number` | `0` | CSS transition duration on `stroke-dashoffset` (ms) |
1225
+ | `class` / `style` | `string` | - | Container div class / inline style |
1226
+ | `circleClass` | `string` | - | Classes for the `<svg>` element |
1227
+ | `circleStyle` | `string` | - | Inline styles for the `<circle>` element |
1210
1228
 
1211
- | Prop | Type | Default | Description |
1212
- | ------------- | -------- | ------- | ---------------------- |
1213
- | `value` | `number` | `0` | Progress value (0-100) |
1214
- | `strokeWidth` | `number` | `8` | Stroke width |
1229
+ ```svelte
1230
+ <Circle completeness={0.75} rotate={-90} bgStrokeColor="#e5e5e5" class="size-16" />
1231
+ ```
1215
1232
 
1216
1233
  #### `H`
1217
1234
 
@@ -1935,9 +1952,48 @@ Generate deterministic avatar colors from a name string.
1935
1952
 
1936
1953
  HSL color generation.
1937
1954
 
1938
- #### `svgCircle(radius, strokeWidth)`
1955
+ #### `svgCircle(options?)`
1956
+
1957
+ Build an SVG ring as a plain DOM node, with setters to update it in place. Framework
1958
+ agnostic - it returns the element, mounting it is up to the caller. Used by `Circle` and
1959
+ `Progress` internally.
1960
+
1961
+ The svg is `width/height: 100%` over a fixed `100x100` viewBox, so the container decides
1962
+ the rendered size; `strokeWidth` is in viewBox units and the radius is derived from it
1963
+ (`50 - strokeWidth / 2`).
1964
+
1965
+ **Options** (all optional):
1966
+
1967
+ | Option | Type | Default | Description |
1968
+ | ------------------ | --------- | ------- | ---------------------------------------------------------------- |
1969
+ | `completeness` | `number` | `1` | Arc length from 0 to 1 (clamped) |
1970
+ | `strokeWidth` | `number` | `10` | Stroke width in viewBox units |
1971
+ | `strokeWidthRatio` | `number` | `0` | Caps `strokeWidth` at this fraction of the radius (`0` = no cap) |
1972
+ | `rotate` | `number` | `0` | Rotation in degrees, modulo 360 (arc starts at 3 o'clock) |
1973
+ | `roundedEdges` | `boolean` | `true` | Rounded (vs butt) line caps |
1974
+ | `bgStrokeColor` | `string` | - | CSS color of a full background ring behind the arc |
1975
+ | `class` | `string` | - | Classes for the `<svg>` element |
1976
+ | `circleStyle` | `string` | - | Inline styles for the `<circle>` element |
1977
+ | `radius` | `number` | - | Currently ignored (derived from the viewBox and stroke width) |
1939
1978
 
1940
- Generate SVG circle path data.
1979
+ **Returns:** `{ svg: SVGSVGElement, setCompleteness(v: number): void, setRotate(deg: number): void }`
1980
+
1981
+ The setters mutate the existing element - reach for them instead of rebuilding when only
1982
+ the progress or rotation changes.
1983
+
1984
+ ```ts
1985
+ import { svgCircle } from "@marianmeres/stuic";
1986
+
1987
+ const { svg, setCompleteness } = svgCircle({
1988
+ completeness: 0.75,
1989
+ strokeWidth: 8,
1990
+ rotate: -90,
1991
+ bgStrokeColor: "#e5e5e5",
1992
+ });
1993
+ container.appendChild(svg);
1994
+
1995
+ setCompleteness(0.9); // no rebuild
1996
+ ```
1941
1997
 
1942
1998
  #### `oscillate(min, max, step)`
1943
1999
 
@@ -1,5 +1,24 @@
1
+ <script lang="ts" module>
2
+ import type { SvgCircleOptions } from "../../utils/svg-circle.js";
3
+
4
+ export interface Props extends Partial<SvgCircleOptions> {
5
+ /** Inline styles for the container element */
6
+ style?: string;
7
+ /**
8
+ * CSS classes for the `<svg>` element (forwarded to the helper's `class`
9
+ * option). Since the stroke is `currentColor`, a text color utility here
10
+ * colors the ring.
11
+ */
12
+ circleClass?: string;
13
+ /** Inline styles for the `<circle>` element */
14
+ circleStyle?: string;
15
+ /** Transition duration in ms on the stroke-dashoffset */
16
+ animateCompletenessMs?: number;
17
+ }
18
+ </script>
19
+
1
20
  <script lang="ts">
2
- import { svgCircle, type SvgCircleOptions } from "../../utils/svg-circle.js";
21
+ import { svgCircle } from "../../utils/svg-circle.js";
3
22
  import { twMerge } from "../../utils/tw-merge.js";
4
23
 
5
24
  let {
@@ -14,13 +33,7 @@
14
33
  circleClass,
15
34
  circleStyle = "",
16
35
  animateCompletenessMs = 0,
17
- }: Partial<SvgCircleOptions> & {
18
- style?: string;
19
- circleClass?: string;
20
- circleStyle?: string;
21
- // transition duration in ms on the stroke-dashoffset
22
- animateCompletenessMs?: number;
23
- } = $props();
36
+ }: Props = $props();
24
37
 
25
38
  let container: HTMLDivElement = $state()!;
26
39
 
@@ -42,10 +55,12 @@
42
55
  );
43
56
 
44
57
  $effect(() => {
45
- container.appendChild(circle.svg);
46
- return () => {
47
- circle.svg.remove();
48
- };
58
+ // Capture the current instance: `circle` is a derived, so reading it again in the
59
+ // teardown would resolve to the freshly rebuilt svg and leave the previous node
60
+ // behind (stacking one <svg> per structural prop change).
61
+ const { svg } = circle;
62
+ container.appendChild(svg);
63
+ return () => svg.remove();
49
64
  });
50
65
 
51
66
  $effect(() => {
@@ -1,10 +1,18 @@
1
- import { type SvgCircleOptions } from "../../utils/svg-circle.js";
2
- type $$ComponentProps = Partial<SvgCircleOptions> & {
1
+ import type { SvgCircleOptions } from "../../utils/svg-circle.js";
2
+ export interface Props extends Partial<SvgCircleOptions> {
3
+ /** Inline styles for the container element */
3
4
  style?: string;
5
+ /**
6
+ * CSS classes for the `<svg>` element (forwarded to the helper's `class`
7
+ * option). Since the stroke is `currentColor`, a text color utility here
8
+ * colors the ring.
9
+ */
4
10
  circleClass?: string;
11
+ /** Inline styles for the `<circle>` element */
5
12
  circleStyle?: string;
13
+ /** Transition duration in ms on the stroke-dashoffset */
6
14
  animateCompletenessMs?: number;
7
- };
8
- declare const Circle: import("svelte").Component<$$ComponentProps, {}, "">;
15
+ }
16
+ declare const Circle: import("svelte").Component<Props, {}, "">;
9
17
  type Circle = ReturnType<typeof Circle>;
10
18
  export default Circle;
@@ -1,22 +1,31 @@
1
1
  # Circle
2
2
 
3
- An SVG circle progress indicator with configurable stroke, rotation, and animated transitions.
3
+ An SVG circle progress indicator with configurable stroke, rotation, and animated
4
+ transitions. A thin Svelte wrapper around the [`svgCircle`](../../utils/svg-circle.ts)
5
+ utility.
6
+
7
+ The svg is rendered at `width/height: 100%` over a fixed `100x100` viewBox, so **the
8
+ container decides the size** (default `size-6`) and `strokeWidth` is expressed in viewBox
9
+ units - i.e. it scales with the box. The stroke defaults to `currentColor`.
4
10
 
5
11
  ## Props
6
12
 
7
- | Prop | Type | Default | Description |
8
- | ----------------------- | --------- | ------- | --------------------------------------------- |
9
- | `completeness` | `number` | `1` | Progress value from 0 to 1 |
10
- | `strokeWidth` | `number` | `10` | Stroke width in SVG units |
11
- | `bgStrokeColor` | `string` | - | Background circle stroke color |
12
- | `roundedEdges` | `boolean` | `true` | Use rounded stroke line caps |
13
- | `rotate` | `number` | `0` | Rotation in degrees |
14
- | `strokeWidthRatio` | `number` | `0` | Ratio for background stroke width |
15
- | `animateCompletenessMs` | `number` | `0` | Transition duration for progress changes (ms) |
16
- | `class` | `string` | - | CSS for container div |
17
- | `style` | `string` | - | Inline styles for container |
18
- | `circleClass` | `string` | - | CSS for SVG circle element |
19
- | `circleStyle` | `string` | - | Inline styles for circle |
13
+ | Prop | Type | Default | Description |
14
+ | ----------------------- | --------- | ------- | ---------------------------------------------------------------------- |
15
+ | `completeness` | `number` | `1` | Progress from 0 to 1 (clamped) |
16
+ | `strokeWidth` | `number` | `10` | Stroke width in viewBox units (radius = `50 - strokeWidth / 2`) |
17
+ | `strokeWidthRatio` | `number` | `0` | Caps `strokeWidth` at this fraction of the radius; `0` means no cap |
18
+ | `bgStrokeColor` | `string` | - | Any CSS color; adds a full background ring behind the arc |
19
+ | `roundedEdges` | `boolean` | `true` | Rounded (vs butt) stroke line caps |
20
+ | `rotate` | `number` | `0` | Rotation in degrees; the arc starts at 3 o'clock, so use `-90` for top |
21
+ | `animateCompletenessMs` | `number` | `0` | CSS transition duration on `stroke-dashoffset` (ms) |
22
+ | `class` | `string` | - | CSS classes for the container div |
23
+ | `style` | `string` | - | Inline styles for the container div |
24
+ | `circleClass` | `string` | - | CSS classes for the `<svg>` element |
25
+ | `circleStyle` | `string` | - | Inline styles for the `<circle>` element |
26
+
27
+ `completeness` and `rotate` are applied through the helper's setters, so changing them
28
+ only rewrites two attributes. Every other prop rebuilds the svg.
20
29
 
21
30
  ## Usage
22
31
 
@@ -24,17 +33,17 @@ An SVG circle progress indicator with configurable stroke, rotation, and animate
24
33
 
25
34
  ```svelte
26
35
  <script lang="ts">
27
- import { Circle } from "stuic";
36
+ import { Circle } from "@marianmeres/stuic";
28
37
  </script>
29
38
 
30
- <Circle completeness={0.75} class="size-16" />
39
+ <Circle completeness={0.75} rotate={-90} class="size-16" />
31
40
  ```
32
41
 
33
42
  ### Animated Progress
34
43
 
35
44
  ```svelte
36
45
  <script lang="ts">
37
- import { Circle } from "stuic";
46
+ import { Circle } from "@marianmeres/stuic";
38
47
 
39
48
  let progress = $state(0);
40
49
 
@@ -54,13 +63,40 @@ An SVG circle progress indicator with configurable stroke, rotation, and animate
54
63
 
55
64
  ### Custom Styling
56
65
 
66
+ The ring's stroke is `currentColor`, so a text color on the container (or on the svg via
67
+ `circleClass`) colors it. To set the stroke directly, use `circleStyle` - it lands on the
68
+ `<circle>` element, which is the only place that beats the `stroke="currentColor"`
69
+ presentation attribute.
70
+
57
71
  ```svelte
72
+ <!-- via currentColor -->
58
73
  <Circle
59
74
  completeness={0.5}
60
75
  strokeWidth={8}
61
76
  rotate={-90}
62
77
  bgStrokeColor="rgba(0,0,0,0.1)"
78
+ class="size-24 text-blue-500"
79
+ />
80
+
81
+ <!-- or explicitly on the circle element -->
82
+ <Circle
83
+ completeness={0.5}
84
+ rotate={-90}
63
85
  class="size-24"
64
- circleClass="stroke-blue-500"
86
+ circleStyle="stroke: var(--stuic-color-primary);"
65
87
  />
66
88
  ```
89
+
90
+ ### Content Inside the Ring
91
+
92
+ ```svelte
93
+ <div class="relative size-24">
94
+ <Circle
95
+ completeness={0.62}
96
+ rotate={-90}
97
+ bgStrokeColor="#e5e5e5"
98
+ class="absolute inset-0"
99
+ />
100
+ <div class="absolute inset-0 flex items-center justify-center">62%</div>
101
+ </div>
102
+ ```
@@ -0,0 +1 @@
1
+ export { default as Circle, type Props as CircleProps } from "./Circle.svelte";
@@ -0,0 +1 @@
1
+ export { default as Circle } from "./Circle.svelte";
@@ -41,6 +41,18 @@
41
41
  paging?: PagingCalcResult;
42
42
  /** Callback when the user navigates to a different page (receives new offset) */
43
43
  onPageChange?: (offset: number) => void;
44
+ /**
45
+ * Render the built-in pager. Set `false` to keep feeding `paging` -- which the
46
+ * select-all-across-pages banner, `effectiveCount` and `totalCount` need -- while
47
+ * paging the data from your own control elsewhere on the page.
48
+ *
49
+ * With the pager hidden `onPageChange` never fires (nothing else calls it), so the
50
+ * caller's own control is the single thing driving the offset -- don't wire both.
51
+ *
52
+ * Orthogonal to the existing "one page of results needs no pager" rule: a single-page
53
+ * `paging` renders no pager either way.
54
+ */
55
+ showPager?: boolean;
44
56
 
45
57
  /** Enable row selection checkboxes */
46
58
  selectable?: boolean;
@@ -231,6 +243,7 @@
231
243
  getRowId = (_row: T, index: number) => index,
232
244
  paging,
233
245
  onPageChange,
246
+ showPager = true,
234
247
  selectable = false,
235
248
  selected = $bindable(new Set()),
236
249
  selectOnRowClick = false,
@@ -265,7 +278,9 @@
265
278
  let isDesktop = $derived(small ? false : bp.md);
266
279
 
267
280
  // --- Paging ---
268
- let showPaging = $derived(paging != null && paging.pageCount > 1);
281
+ // The prop only ADDs to the existing rule -- a single-page result still renders no
282
+ // pager, regardless of `showPager`.
283
+ let renderPager = $derived(showPager && paging != null && paging.pageCount > 1);
269
284
 
270
285
  // --- Selection ---
271
286
  let allRowIds = $derived(data.map((row, i) => getRowId(row, i)));
@@ -752,7 +767,7 @@
752
767
  {/if}
753
768
 
754
769
  <!-- Paging -->
755
- {#if showPaging && paging}
770
+ {#if renderPager && paging}
756
771
  <div class={!unstyled ? "stuic-data-table-paging" : undefined}>
757
772
  <Button
758
773
  variant="ghost"
@@ -32,6 +32,18 @@ export interface Props<T = Record<string, any>> extends Omit<HTMLAttributes<HTML
32
32
  paging?: PagingCalcResult;
33
33
  /** Callback when the user navigates to a different page (receives new offset) */
34
34
  onPageChange?: (offset: number) => void;
35
+ /**
36
+ * Render the built-in pager. Set `false` to keep feeding `paging` -- which the
37
+ * select-all-across-pages banner, `effectiveCount` and `totalCount` need -- while
38
+ * paging the data from your own control elsewhere on the page.
39
+ *
40
+ * With the pager hidden `onPageChange` never fires (nothing else calls it), so the
41
+ * caller's own control is the single thing driving the offset -- don't wire both.
42
+ *
43
+ * Orthogonal to the existing "one page of results needs no pager" rule: a single-page
44
+ * `paging` renders no pager either way.
45
+ */
46
+ showPager?: boolean;
35
47
  /** Enable row selection checkboxes */
36
48
  selectable?: boolean;
37
49
  /** Set of selected row IDs (bindable) */
@@ -46,6 +46,35 @@ DataTable integrates with [`@marianmeres/paging-store`](https://github.com/maria
46
46
  />
47
47
  ```
48
48
 
49
+ A single-page result renders no pager -- there is nothing to page through.
50
+
51
+ #### Bringing your own pager
52
+
53
+ `paging` does two unrelated jobs: it renders the built-in pager, and it feeds the
54
+ select-all-across-pages banner, `effectiveCount` and `totalCount`. `showPager={false}`
55
+ asks for the second without the first, for a page that already pages the data from its own
56
+ control (one with a rows-per-page selector, say):
57
+
58
+ ```svelte
59
+ <DataTable
60
+ {columns}
61
+ {data}
62
+ paging={pagingResult}
63
+ showPager={false}
64
+ selectable
65
+ allowSelectAllPages
66
+ />
67
+
68
+ <MyOwnPager … />
69
+ ```
70
+
71
+ The pager node is then absent from the DOM, not hidden -- it takes no space and holds no
72
+ focusable buttons. `onPageChange` never fires while it is hidden (nothing else calls it),
73
+ so your own control is the single thing driving the offset; don't wire both.
74
+
75
+ (The node's class stays `.stuic-data-table-paging` and its `--stuic-data-table-paging-*`
76
+ tokens are unchanged -- `showPager` names the control, the CSS names the region.)
77
+
49
78
  ### With Selection
50
79
 
51
80
  ```svelte
@@ -311,39 +340,40 @@ Replace the entire `<tr>` on desktop. When this snippet is provided, DataTable d
311
340
 
312
341
  ## Props
313
342
 
314
- | Prop | Type | Default | Description |
315
- | --------------------- | ------------------------------------- | ------------- | -------------------------------------------------------------------------- |
316
- | `columns` | `DataTableColumn<T>[]` | required | Column definitions |
317
- | `data` | `T[]` | required | Array of row data |
318
- | `getRowId` | `(row, index) => string \| number` | `(_, i) => i` | Row ID extractor |
319
- | `paging` | `PagingCalcResult` | - | Paging state (from `@marianmeres/paging-store`) |
320
- | `onPageChange` | `(offset: number) => void` | - | Called with the new offset when the user navigates pages |
321
- | `selectable` | `boolean` | `false` | Enable selection checkboxes |
322
- | `selected` | `Set<string \| number>` | `new Set()` | Selected row IDs (bindable) |
323
- | `selectOnRowClick` | `boolean` | `false` | Clicking anywhere on a row toggles its selection |
324
- | `selectDisabledBy` | `(row, index) => boolean` | - | Return `true` to disable selection for a specific row |
325
- | `allowSelectAllPages` | `boolean` | `false` | Show a banner offering "select all results" across paged data |
326
- | `selectedAll` | `boolean` | `false` | All-pages mode flag (bindable). In this mode `excluded` drives selection |
327
- | `excluded` | `Set<string \| number>` | `new Set()` | Deselected row IDs while in all-pages mode (bindable) |
328
- | `reserveBatchBar` | `boolean` | `true` | Keep the selection bar in the layout while nothing is selected |
329
- | `onRowClick` | `(row, index) => void` | - | Row click callback |
330
- | `rowHref` | `(row, index) => string \| undefined` | - | Wrap the lead cell's content in an `<a href>` (keyboard/⌘-click reachable) |
331
- | `rowHrefColumn` | `string` | first column | Which column is the lead cell for `rowHref` |
332
- | `classRowLink` | `string` | - | Extra classes for the `rowHref` anchor |
333
- | `rowActivatable` | `boolean` | `false` | Make the desktop `<tr>` focusable + `Enter`-activatable (no `role`) |
334
- | `rowLabel` | `(row, index) => string \| undefined` | - | Accessible name for an activatable row |
335
- | `loading` | `boolean` | `false` | Show loading overlay |
336
- | `small` | `boolean` | `false` | Force mobile/card layout regardless of viewport |
337
- | `t` | `TranslateFn` | built-in | Optional translation function |
338
- | `cell` | `Snippet` | - | Custom cell renderer (desktop + mobile) |
339
- | `row` | `Snippet` | - | Custom desktop `<tr>` renderer (overrides default row) |
340
- | `mobileRow` | `Snippet` | - | Custom mobile card renderer |
341
- | `batchActions` | `Snippet` | - | Selection bar content while something is selected |
342
- | `selectAllBanner` | `Snippet` | - | Override default "select all across pages" offer |
343
- | `empty` | `Snippet` | - | Custom empty state |
344
- | `unstyled` | `boolean` | `false` | Skip default styling |
345
- | `class` | `string` | - | Additional CSS classes |
346
- | `el` | `HTMLDivElement` | - | Bindable element ref |
343
+ | Prop | Type | Default | Description |
344
+ | --------------------- | ------------------------------------- | ------------- | ------------------------------------------------------------------------------------ |
345
+ | `columns` | `DataTableColumn<T>[]` | required | Column definitions |
346
+ | `data` | `T[]` | required | Array of row data |
347
+ | `getRowId` | `(row, index) => string \| number` | `(_, i) => i` | Row ID extractor |
348
+ | `paging` | `PagingCalcResult` | - | Paging state (from `@marianmeres/paging-store`) |
349
+ | `onPageChange` | `(offset: number) => void` | - | Called with the new offset when the user navigates pages |
350
+ | `showPager` | `boolean` | `true` | Render the built-in pager. `false` keeps `paging` feeding the select-all banner only |
351
+ | `selectable` | `boolean` | `false` | Enable selection checkboxes |
352
+ | `selected` | `Set<string \| number>` | `new Set()` | Selected row IDs (bindable) |
353
+ | `selectOnRowClick` | `boolean` | `false` | Clicking anywhere on a row toggles its selection |
354
+ | `selectDisabledBy` | `(row, index) => boolean` | - | Return `true` to disable selection for a specific row |
355
+ | `allowSelectAllPages` | `boolean` | `false` | Show a banner offering "select all results" across paged data |
356
+ | `selectedAll` | `boolean` | `false` | All-pages mode flag (bindable). In this mode `excluded` drives selection |
357
+ | `excluded` | `Set<string \| number>` | `new Set()` | Deselected row IDs while in all-pages mode (bindable) |
358
+ | `reserveBatchBar` | `boolean` | `true` | Keep the selection bar in the layout while nothing is selected |
359
+ | `onRowClick` | `(row, index) => void` | - | Row click callback |
360
+ | `rowHref` | `(row, index) => string \| undefined` | - | Wrap the lead cell's content in an `<a href>` (keyboard/⌘-click reachable) |
361
+ | `rowHrefColumn` | `string` | first column | Which column is the lead cell for `rowHref` |
362
+ | `classRowLink` | `string` | - | Extra classes for the `rowHref` anchor |
363
+ | `rowActivatable` | `boolean` | `false` | Make the desktop `<tr>` focusable + `Enter`-activatable (no `role`) |
364
+ | `rowLabel` | `(row, index) => string \| undefined` | - | Accessible name for an activatable row |
365
+ | `loading` | `boolean` | `false` | Show loading overlay |
366
+ | `small` | `boolean` | `false` | Force mobile/card layout regardless of viewport |
367
+ | `t` | `TranslateFn` | built-in | Optional translation function |
368
+ | `cell` | `Snippet` | - | Custom cell renderer (desktop + mobile) |
369
+ | `row` | `Snippet` | - | Custom desktop `<tr>` renderer (overrides default row) |
370
+ | `mobileRow` | `Snippet` | - | Custom mobile card renderer |
371
+ | `batchActions` | `Snippet` | - | Selection bar content while something is selected |
372
+ | `selectAllBanner` | `Snippet` | - | Override default "select all across pages" offer |
373
+ | `empty` | `Snippet` | - | Custom empty state |
374
+ | `unstyled` | `boolean` | `false` | Skip default styling |
375
+ | `class` | `string` | - | Additional CSS classes |
376
+ | `el` | `HTMLDivElement` | - | Bindable element ref |
347
377
 
348
378
  ### Snippet signatures
349
379
 
package/dist/index.d.ts CHANGED
@@ -35,6 +35,7 @@ export * from "./components/Cart/index.js";
35
35
  export * from "./components/Card/index.js";
36
36
  export * from "./components/Carousel/index.js";
37
37
  export * from "./components/Checkout/index.js";
38
+ export * from "./components/Circle/index.js";
38
39
  export * from "./components/Collapsible/index.js";
39
40
  export * from "./components/ColorScheme/index.js";
40
41
  export * from "./components/CommandMenu/index.js";
package/dist/index.js CHANGED
@@ -36,6 +36,7 @@ export * from "./components/Cart/index.js";
36
36
  export * from "./components/Card/index.js";
37
37
  export * from "./components/Carousel/index.js";
38
38
  export * from "./components/Checkout/index.js";
39
+ export * from "./components/Circle/index.js";
39
40
  export * from "./components/Collapsible/index.js";
40
41
  export * from "./components/ColorScheme/index.js";
41
42
  export * from "./components/CommandMenu/index.js";
@@ -110,7 +110,7 @@ const search = debounce((query: string) => {
110
110
  | `colors` | Color manipulation |
111
111
  | `avatarColors` | Deterministic avatar colors |
112
112
  | `paint` | HSL color generation |
113
- | `svgCircle` | SVG circle path |
113
+ | `svgCircle` | SVG progress ring (DOM node) |
114
114
  | `oscillate` | Value oscillation for animation |
115
115
 
116
116
  ### Example: Class Merging
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "3.165.0",
3
+ "version": "3.167.0",
4
4
  "packageManager": "pnpm@11.5.0",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -162,12 +162,12 @@
162
162
  "prettier": "^3.9.6",
163
163
  "prettier-plugin-svelte": "^3.5.2",
164
164
  "publint": "^0.3.24",
165
- "svelte": "^5.56.10",
165
+ "svelte": "^5.57.0",
166
166
  "svelte-check": "^4.7.6",
167
167
  "tailwindcss": "^4.3.3",
168
- "tsx": "^4.23.12",
168
+ "tsx": "^4.23.13",
169
169
  "typescript": "^5.9.3",
170
- "typescript-eslint": "^8.67.0",
170
+ "typescript-eslint": "^8.68.0",
171
171
  "vite": "^7.3.6",
172
172
  "vitest": "^4.1.11",
173
173
  "vitest-browser-svelte": "^2.2.1"
@@ -183,7 +183,7 @@
183
183
  "@marianmeres/parse-boolean": "^2.1.0",
184
184
  "@marianmeres/ticker": "^1.17.1",
185
185
  "@marianmeres/tree": "^2.3.0",
186
- "libphonenumber-js": "^1.13.11",
186
+ "libphonenumber-js": "^1.13.12",
187
187
  "runed": "^0.23.4",
188
188
  "tailwind-merge": "^3.6.0"
189
189
  }