@marianmeres/stuic 3.167.0 → 3.168.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/AGENTS.md +6 -6
- package/dist/attachments/index.d.ts +1 -0
- package/dist/attachments/index.js +1 -0
- package/dist/attachments/long-press.d.ts +43 -0
- package/dist/attachments/long-press.js +107 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.svelte +198 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.svelte.d.ts +60 -0
- package/dist/components/Breadcrumbs/README.md +174 -0
- package/dist/components/Breadcrumbs/i18n-sk.d.ts +17 -0
- package/dist/components/Breadcrumbs/i18n-sk.js +19 -0
- package/dist/components/Breadcrumbs/i18n.d.ts +31 -0
- package/dist/components/Breadcrumbs/i18n.js +40 -0
- package/dist/components/Breadcrumbs/index.css +84 -0
- package/dist/components/Breadcrumbs/index.d.ts +4 -0
- package/dist/components/Breadcrumbs/index.js +4 -0
- package/dist/components/Breadcrumbs/json-ld.d.ts +58 -0
- package/dist/components/Breadcrumbs/json-ld.js +56 -0
- package/dist/components/Collapsible/Collapsible.svelte +84 -15
- package/dist/components/Collapsible/Collapsible.svelte.d.ts +29 -2
- package/dist/components/Collapsible/README.md +82 -23
- package/dist/components/Collapsible/index.css +38 -0
- package/dist/components/Collapsible/index.d.ts +1 -1
- package/dist/components/ContextMenu/ContextMenu.svelte +302 -0
- package/dist/components/ContextMenu/ContextMenu.svelte.d.ts +94 -0
- package/dist/components/ContextMenu/README.md +159 -0
- package/dist/components/ContextMenu/i18n-sk.d.ts +17 -0
- package/dist/components/ContextMenu/i18n-sk.js +18 -0
- package/dist/components/ContextMenu/i18n.d.ts +30 -0
- package/dist/components/ContextMenu/i18n.js +38 -0
- package/dist/components/ContextMenu/index.css +26 -0
- package/dist/components/ContextMenu/index.d.ts +3 -0
- package/dist/components/ContextMenu/index.js +3 -0
- package/dist/components/CopyButton/CopyButton.svelte +278 -0
- package/dist/components/CopyButton/CopyButton.svelte.d.ts +76 -0
- package/dist/components/CopyButton/README.md +241 -0
- package/dist/components/CopyButton/i18n-sk.d.ts +17 -0
- package/dist/components/CopyButton/i18n-sk.js +20 -0
- package/dist/components/CopyButton/i18n.d.ts +35 -0
- package/dist/components/CopyButton/i18n.js +43 -0
- package/dist/components/CopyButton/index.css +67 -0
- package/dist/components/CopyButton/index.d.ts +3 -0
- package/dist/components/CopyButton/index.js +3 -0
- package/dist/components/DataTable/DataTable.svelte +41 -34
- package/dist/components/DataTable/README.md +45 -0
- package/dist/components/DataTable/i18n-sk.js +1 -0
- package/dist/components/DataTable/i18n.d.ts +1 -0
- package/dist/components/DataTable/i18n.js +3 -0
- package/dist/components/DataTable/index.css +41 -3
- package/dist/components/EmptyState/EmptyState.svelte +121 -0
- package/dist/components/EmptyState/EmptyState.svelte.d.ts +40 -0
- package/dist/components/EmptyState/README.md +188 -0
- package/dist/components/EmptyState/index.css +154 -0
- package/dist/components/EmptyState/index.d.ts +1 -0
- package/dist/components/EmptyState/index.js +1 -0
- package/dist/components/Pagination/Pagination.svelte +250 -0
- package/dist/components/Pagination/Pagination.svelte.d.ts +69 -0
- package/dist/components/Pagination/README.md +152 -0
- package/dist/components/Pagination/i18n-sk.d.ts +17 -0
- package/dist/components/Pagination/i18n-sk.js +24 -0
- package/dist/components/Pagination/i18n.d.ts +41 -0
- package/dist/components/Pagination/i18n.js +49 -0
- package/dist/components/Pagination/index.css +50 -0
- package/dist/components/Pagination/index.d.ts +4 -0
- package/dist/components/Pagination/index.js +4 -0
- package/dist/components/Pagination/pagination-range.d.ts +21 -0
- package/dist/components/Pagination/pagination-range.js +41 -0
- package/dist/components/Stat/README.md +157 -0
- package/dist/components/Stat/Stat.svelte +226 -0
- package/dist/components/Stat/Stat.svelte.d.ts +54 -0
- package/dist/components/Stat/index.css +217 -0
- package/dist/components/Stat/index.d.ts +1 -0
- package/dist/components/Stat/index.js +1 -0
- package/dist/components/Stepper/README.md +181 -0
- package/dist/components/Stepper/Stepper.svelte +240 -0
- package/dist/components/Stepper/Stepper.svelte.d.ts +86 -0
- package/dist/components/Stepper/i18n-sk.d.ts +17 -0
- package/dist/components/Stepper/i18n-sk.js +21 -0
- package/dist/components/Stepper/i18n.d.ts +35 -0
- package/dist/components/Stepper/i18n.js +43 -0
- package/dist/components/Stepper/index.css +302 -0
- package/dist/components/Stepper/index.d.ts +3 -0
- package/dist/components/Stepper/index.js +3 -0
- package/dist/components/TrendChart/README.md +123 -0
- package/dist/components/TrendChart/TrendChart.svelte +114 -0
- package/dist/components/TrendChart/TrendChart.svelte.d.ts +36 -0
- package/dist/components/TrendChart/index.css +51 -0
- package/dist/components/TrendChart/index.d.ts +1 -0
- package/dist/components/TrendChart/index.js +1 -0
- package/dist/icons/index.d.ts +4 -0
- package/dist/icons/index.js +4 -0
- package/dist/index.css +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +12 -0
- package/dist/utils/copy-to-clipboard.d.ts +43 -0
- package/dist/utils/copy-to-clipboard.js +102 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/docs/architecture.md +1 -1
- package/docs/domains/attachments.md +41 -4
- package/docs/domains/components.md +280 -13
- package/docs/domains/utils.md +8 -6
- package/docs/maybe-todo.md +111 -0
- package/package.json +11 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { TranslateFn } from "../../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The built-in (English) message catalog of `CopyButton`. Also the fallback of every
|
|
4
|
+
* other bundled locale, so a locale missing a key still renders text.
|
|
5
|
+
*/
|
|
6
|
+
export declare const COPY_BUTTON_MESSAGES_EN: {
|
|
7
|
+
/** Idle: accessible name of the icon-only button, and the default `label` */
|
|
8
|
+
copy: string;
|
|
9
|
+
/** After a successful copy: label, accessible name, and the live announcement */
|
|
10
|
+
copied: string;
|
|
11
|
+
/** After a failed copy: label, accessible name, and the live announcement */
|
|
12
|
+
copy_failed: string;
|
|
13
|
+
};
|
|
14
|
+
/** Every message key `CopyButton` may look up. */
|
|
15
|
+
export type CopyButtonMessageKey = keyof typeof COPY_BUTTON_MESSAGES_EN;
|
|
16
|
+
/** A (possibly partial) catalog for one locale. */
|
|
17
|
+
export type CopyButtonMessages = Record<CopyButtonMessageKey, string>;
|
|
18
|
+
/**
|
|
19
|
+
* Builds the `t` prop of `CopyButton` from a message catalog. Unknown or untranslated
|
|
20
|
+
* keys fall back to `fallbackMessages` (English by default), so a catalog may safely be
|
|
21
|
+
* partial and never renders a raw key.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```svelte
|
|
25
|
+
* <script>
|
|
26
|
+
* import { CopyButton, createCopyButtonT, COPY_BUTTON_MESSAGES_SK } from "@marianmeres/stuic";
|
|
27
|
+
* const t = createCopyButtonT(COPY_BUTTON_MESSAGES_SK);
|
|
28
|
+
* </script>
|
|
29
|
+
*
|
|
30
|
+
* <CopyButton text={url} {t} />
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function createCopyButtonT(messages: Partial<CopyButtonMessages> | Record<string, string>, fallbackMessages?: Partial<CopyButtonMessages> | Record<string, string>): TranslateFn;
|
|
34
|
+
/** The component's built-in English `t`. */
|
|
35
|
+
export declare const t_default: TranslateFn;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { isPlainObject } from "../../utils/is-plain-object.js";
|
|
2
|
+
import { replaceMap } from "../../utils/replace-map.js";
|
|
3
|
+
/**
|
|
4
|
+
* The built-in (English) message catalog of `CopyButton`. Also the fallback of every
|
|
5
|
+
* other bundled locale, so a locale missing a key still renders text.
|
|
6
|
+
*/
|
|
7
|
+
export const COPY_BUTTON_MESSAGES_EN = {
|
|
8
|
+
/** Idle: accessible name of the icon-only button, and the default `label` */
|
|
9
|
+
copy: "Copy",
|
|
10
|
+
/** After a successful copy: label, accessible name, and the live announcement */
|
|
11
|
+
copied: "Copied",
|
|
12
|
+
/** After a failed copy: label, accessible name, and the live announcement */
|
|
13
|
+
copy_failed: "Copy failed",
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Builds the `t` prop of `CopyButton` from a message catalog. Unknown or untranslated
|
|
17
|
+
* keys fall back to `fallbackMessages` (English by default), so a catalog may safely be
|
|
18
|
+
* partial and never renders a raw key.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```svelte
|
|
22
|
+
* <script>
|
|
23
|
+
* import { CopyButton, createCopyButtonT, COPY_BUTTON_MESSAGES_SK } from "@marianmeres/stuic";
|
|
24
|
+
* const t = createCopyButtonT(COPY_BUTTON_MESSAGES_SK);
|
|
25
|
+
* </script>
|
|
26
|
+
*
|
|
27
|
+
* <CopyButton text={url} {t} />
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function createCopyButtonT(messages, fallbackMessages = COPY_BUTTON_MESSAGES_EN) {
|
|
31
|
+
return (k, values = null, fallback = "") => {
|
|
32
|
+
const out = messages[k] ??
|
|
33
|
+
fallbackMessages[k] ??
|
|
34
|
+
(typeof fallback === "string" ? fallback : k);
|
|
35
|
+
return isPlainObject(values)
|
|
36
|
+
? replaceMap(out, values, {
|
|
37
|
+
preSearchKeyTransform: (k) => `{${k}}`,
|
|
38
|
+
})
|
|
39
|
+
: out;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** The component's built-in English `t`. */
|
|
43
|
+
export const t_default = createCopyButtonT(COPY_BUTTON_MESSAGES_EN);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
COPY BUTTON COMPONENT TOKENS
|
|
3
|
+
The button itself IS a Button — colors, sizes, radius and focus ring theme via
|
|
4
|
+
the --stuic-button-* tokens. These tokens only cover the icon and the feedback
|
|
5
|
+
"pop" when the state flips to copied/error.
|
|
6
|
+
Override globally: :root { --stuic-copy-button-icon-size: 1em; }
|
|
7
|
+
Override locally: <CopyButton style="--stuic-copy-button-icon-size: 1em;">
|
|
8
|
+
============================================================================ */
|
|
9
|
+
|
|
10
|
+
/* prettier-ignore */
|
|
11
|
+
:root {
|
|
12
|
+
/* Icon (any svg inside the icon wrapper is normalized to this) */
|
|
13
|
+
--stuic-copy-button-icon-size: 1.25em;
|
|
14
|
+
|
|
15
|
+
/* Feedback pop: the icon scales up from this factor when the state changes */
|
|
16
|
+
--stuic-copy-button-icon-pop-duration: 200ms;
|
|
17
|
+
--stuic-copy-button-icon-pop-scale: 0.6;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@layer components {
|
|
21
|
+
/* ============================================================================
|
|
22
|
+
ICON
|
|
23
|
+
============================================================================ */
|
|
24
|
+
|
|
25
|
+
.stuic-copy-button-icon {
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
flex: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.stuic-copy-button-icon svg {
|
|
33
|
+
width: var(--stuic-copy-button-icon-size);
|
|
34
|
+
height: var(--stuic-copy-button-icon-size);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* ============================================================================
|
|
38
|
+
FEEDBACK POP
|
|
39
|
+
Runs once when [data-state] flips to copied/error (the selector starts
|
|
40
|
+
matching). Re-clicking within the feedback window keeps the state and so
|
|
41
|
+
does not replay it.
|
|
42
|
+
============================================================================ */
|
|
43
|
+
|
|
44
|
+
.stuic-copy-button[data-state="copied"] .stuic-copy-button-icon,
|
|
45
|
+
.stuic-copy-button[data-state="error"] .stuic-copy-button-icon {
|
|
46
|
+
animation: stuic-copy-button-icon-pop var(--stuic-copy-button-icon-pop-duration)
|
|
47
|
+
ease-out;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@media (prefers-reduced-motion: reduce) {
|
|
51
|
+
.stuic-copy-button[data-state="copied"] .stuic-copy-button-icon,
|
|
52
|
+
.stuic-copy-button[data-state="error"] .stuic-copy-button-icon {
|
|
53
|
+
animation: none;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@keyframes stuic-copy-button-icon-pop {
|
|
59
|
+
from {
|
|
60
|
+
transform: scale(var(--stuic-copy-button-icon-pop-scale));
|
|
61
|
+
opacity: 0.4;
|
|
62
|
+
}
|
|
63
|
+
to {
|
|
64
|
+
transform: scale(1);
|
|
65
|
+
opacity: 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { default as CopyButton, type Props as CopyButtonProps, type CopyButtonState, type CopyButtonText, } from "./CopyButton.svelte";
|
|
2
|
+
export { createCopyButtonT, COPY_BUTTON_MESSAGES_EN, type CopyButtonMessageKey, type CopyButtonMessages, } from "./i18n.js";
|
|
3
|
+
export { COPY_BUTTON_MESSAGES_SK } from "./i18n-sk.js";
|
|
@@ -235,6 +235,8 @@
|
|
|
235
235
|
import { Breakpoint } from "../../utils/breakpoint.svelte.js";
|
|
236
236
|
import Spinner from "../Spinner/Spinner.svelte";
|
|
237
237
|
import Button from "../Button/Button.svelte";
|
|
238
|
+
import EmptyState from "../EmptyState/EmptyState.svelte";
|
|
239
|
+
import Pagination from "../Pagination/Pagination.svelte";
|
|
238
240
|
import Thc, { isTHCNotEmpty, getTHCStringContent } from "../Thc/Thc.svelte";
|
|
239
241
|
|
|
240
242
|
let {
|
|
@@ -517,6 +519,25 @@
|
|
|
517
519
|
{/if}
|
|
518
520
|
{/snippet}
|
|
519
521
|
|
|
522
|
+
<!--
|
|
523
|
+
The empty state, shared by both layouts. The built-in one is an `EmptyState`; its
|
|
524
|
+
typography is pulled back to table chrome (muted, cell-sized, no headline weight) by
|
|
525
|
+
the `--stuic-empty-state-*` overrides in index.css, so it reads exactly as the bare
|
|
526
|
+
`t("no_data")` string it replaces. An `empty` snippet still replaces it whole.
|
|
527
|
+
-->
|
|
528
|
+
{#snippet emptyBody()}
|
|
529
|
+
{#if empty}
|
|
530
|
+
{@render empty()}
|
|
531
|
+
{:else}
|
|
532
|
+
<EmptyState
|
|
533
|
+
title={t("no_data")}
|
|
534
|
+
size="sm"
|
|
535
|
+
{unstyled}
|
|
536
|
+
class={!unstyled ? "stuic-data-table-empty-state" : undefined}
|
|
537
|
+
/>
|
|
538
|
+
{/if}
|
|
539
|
+
{/snippet}
|
|
540
|
+
|
|
520
541
|
<!--
|
|
521
542
|
Selection bar -- one strip carrying the selection status, the consumer's
|
|
522
543
|
`batchActions`, and the select-all-across-pages offer. Deliberately a single element
|
|
@@ -668,11 +689,7 @@
|
|
|
668
689
|
colspan={columns.length + (selectable ? 1 : 0)}
|
|
669
690
|
class={!unstyled ? "stuic-data-table-empty" : undefined}
|
|
670
691
|
>
|
|
671
|
-
{
|
|
672
|
-
{@render empty()}
|
|
673
|
-
{:else}
|
|
674
|
-
{t("no_data")}
|
|
675
|
-
{/if}
|
|
692
|
+
{@render emptyBody()}
|
|
676
693
|
</td>
|
|
677
694
|
</tr>
|
|
678
695
|
{/each}
|
|
@@ -749,11 +766,7 @@
|
|
|
749
766
|
{/if}
|
|
750
767
|
{:else}
|
|
751
768
|
<div class={!unstyled ? "stuic-data-table-empty" : undefined}>
|
|
752
|
-
{
|
|
753
|
-
{@render empty()}
|
|
754
|
-
{:else}
|
|
755
|
-
{t("no_data")}
|
|
756
|
-
{/if}
|
|
769
|
+
{@render emptyBody()}
|
|
757
770
|
</div>
|
|
758
771
|
{/each}
|
|
759
772
|
</div>
|
|
@@ -766,30 +779,24 @@
|
|
|
766
779
|
</div>
|
|
767
780
|
{/if}
|
|
768
781
|
|
|
769
|
-
<!--
|
|
782
|
+
<!--
|
|
783
|
+
Paging -- the built-in pager IS a `Pagination` in its default "compact" variant,
|
|
784
|
+
which is exactly the prev / "Page X of Y" / next control this used to inline.
|
|
785
|
+
`.stuic-data-table-paging` moves onto its `<nav>` rather than wrapping it, so the
|
|
786
|
+
region keeps its class (and its `--stuic-data-table-paging-*` tokens, re-pointed
|
|
787
|
+
at Pagination's in index.css) without an extra node.
|
|
788
|
+
|
|
789
|
+
Note `Pagination`'s own single-page rule is left at its default: `renderPager`
|
|
790
|
+
already encodes it, plus `showPager`.
|
|
791
|
+
-->
|
|
770
792
|
{#if renderPager && paging}
|
|
771
|
-
<
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
‹ {t("previous_page")}
|
|
780
|
-
</Button>
|
|
781
|
-
<span class={!unstyled ? "stuic-data-table-paging-info" : undefined}>
|
|
782
|
-
{t("page_x_of_y", { page: paging.currentPage, pageCount: paging.pageCount })}
|
|
783
|
-
</span>
|
|
784
|
-
<Button
|
|
785
|
-
variant="ghost"
|
|
786
|
-
size="sm"
|
|
787
|
-
disabled={!paging.hasNext}
|
|
788
|
-
onclick={() => onPageChange?.(paging!.nextOffset)}
|
|
789
|
-
aria-label={t("next_page")}
|
|
790
|
-
>
|
|
791
|
-
{t("next_page")} ›
|
|
792
|
-
</Button>
|
|
793
|
-
</div>
|
|
793
|
+
<Pagination
|
|
794
|
+
{paging}
|
|
795
|
+
{onPageChange}
|
|
796
|
+
{t}
|
|
797
|
+
{unstyled}
|
|
798
|
+
class={!unstyled ? "stuic-data-table-paging" : undefined}
|
|
799
|
+
classInfo={!unstyled ? "stuic-data-table-paging-info" : undefined}
|
|
800
|
+
/>
|
|
794
801
|
{/if}
|
|
795
802
|
</div>
|
|
@@ -75,6 +75,50 @@ so your own control is the single thing driving the offset; don't wire both.
|
|
|
75
75
|
(The node's class stays `.stuic-data-table-paging` and its `--stuic-data-table-paging-*`
|
|
76
76
|
tokens are unchanged -- `showPager` names the control, the CSS names the region.)
|
|
77
77
|
|
|
78
|
+
### What the built-in pager and empty state are made of
|
|
79
|
+
|
|
80
|
+
Neither is bespoke markup any more:
|
|
81
|
+
|
|
82
|
+
- the pager is a [`Pagination`](../Pagination/README.md) in its default `"compact"`
|
|
83
|
+
variant, rendered with `.stuic-data-table-paging` on its own `<nav>`;
|
|
84
|
+
- the default empty state (no `empty` snippet) is an
|
|
85
|
+
[`EmptyState`](../EmptyState/README.md) at `size="sm"`, carrying the marker class
|
|
86
|
+
`.stuic-data-table-empty-state` inside the usual `.stuic-data-table-empty` cell.
|
|
87
|
+
|
|
88
|
+
The table's `--stuic-data-table-*` tokens are re-pointed at the inner components' own
|
|
89
|
+
tokens, so an existing override still drives them, and the `t` you pass `DataTable` is
|
|
90
|
+
the one the pager uses -- the shared `previous_page`, `next_page` and `page_x_of_y`
|
|
91
|
+
keys are identical in both catalogs, so nothing to wire.
|
|
92
|
+
|
|
93
|
+
Two things did change:
|
|
94
|
+
|
|
95
|
+
- the pager is a `<nav>` landmark named by the new `pagination` key, where it used to
|
|
96
|
+
be a plain `<div>`. Same buttons, same labels, same `onPageChange` offsets;
|
|
97
|
+
- the built-in empty state now gets the `2rem` of padding `.stuic-data-table-empty` has
|
|
98
|
+
always declared. On desktop it never actually got it (the more specific
|
|
99
|
+
`.stuic-data-table td` padding rule won), so that cell is taller than it was, and now
|
|
100
|
+
matches the mobile card layout, which already had it. Typography is unchanged.
|
|
101
|
+
|
|
102
|
+
An `empty` snippet is untouched by any of this -- it replaces the built-in `EmptyState`
|
|
103
|
+
outright and keeps the container padding it has always had. Rendering your own
|
|
104
|
+
`EmptyState` in it is a perfectly good way to get an icon, a description and a CTA:
|
|
105
|
+
|
|
106
|
+
```svelte
|
|
107
|
+
<DataTable {columns} {data}>
|
|
108
|
+
{#snippet empty()}
|
|
109
|
+
<EmptyState
|
|
110
|
+
icon={{ html: iconSearch({ size: 48 }) }}
|
|
111
|
+
title="No matches"
|
|
112
|
+
description="Try widening the filter."
|
|
113
|
+
>
|
|
114
|
+
{#snippet actions()}
|
|
115
|
+
<Button onclick={resetFilters}>Reset filters</Button>
|
|
116
|
+
{/snippet}
|
|
117
|
+
</EmptyState>
|
|
118
|
+
{/snippet}
|
|
119
|
+
</DataTable>
|
|
120
|
+
```
|
|
121
|
+
|
|
78
122
|
### With Selection
|
|
79
123
|
|
|
80
124
|
```svelte
|
|
@@ -437,6 +481,7 @@ const t = createDataTableT({ ...DATA_TABLE_MESSAGES_SK, no_data: "Nič tu nie je
|
|
|
437
481
|
| `previous_page` | Prev | Paging |
|
|
438
482
|
| `next_page` | Next | Paging |
|
|
439
483
|
| `page_x_of_y` | Page {page} of {pageCount} | Paging |
|
|
484
|
+
| `pagination` | Pagination | Pager `<nav>` `aria-label` |
|
|
440
485
|
| `no_data` | No data | Empty state (no `empty` snippet) |
|
|
441
486
|
| `select_all_rows` | Select all rows on this page | Header checkbox `aria-label` |
|
|
442
487
|
| `select_row` | Select row | Row checkbox `aria-label` |
|
|
@@ -17,6 +17,7 @@ export const DATA_TABLE_MESSAGES_SK = {
|
|
|
17
17
|
previous_page: "Späť",
|
|
18
18
|
next_page: "Ďalej",
|
|
19
19
|
page_x_of_y: "Strana {page} z {pageCount}",
|
|
20
|
+
pagination: "Stránkovanie",
|
|
20
21
|
no_data: "Žiadne údaje",
|
|
21
22
|
select_all_rows: "Vybrať všetky riadky na tejto strane",
|
|
22
23
|
select_row: "Vybrať riadok",
|
|
@@ -10,6 +10,9 @@ export const DATA_TABLE_MESSAGES_EN = {
|
|
|
10
10
|
previous_page: "Prev",
|
|
11
11
|
next_page: "Next",
|
|
12
12
|
page_x_of_y: "Page {page} of {pageCount}",
|
|
13
|
+
// The pager is a `Pagination`; this is its `<nav>` accessible name. Identical to
|
|
14
|
+
// `PAGINATION_MESSAGES_EN` so one merged catalog can still serve both components.
|
|
15
|
+
pagination: "Pagination",
|
|
13
16
|
no_data: "No data",
|
|
14
17
|
select_all_rows: "Select all rows on this page",
|
|
15
18
|
select_row: "Select row",
|
|
@@ -224,18 +224,31 @@
|
|
|
224
224
|
PAGING
|
|
225
225
|
============================================================================ */
|
|
226
226
|
|
|
227
|
+
/*
|
|
228
|
+
The built-in pager IS a `Pagination` (compact variant), so these two classes now
|
|
229
|
+
sit on Pagination's own nodes alongside `.stuic-pagination`. They add the region's
|
|
230
|
+
top padding (which Pagination has no notion of) and re-point Pagination's tokens
|
|
231
|
+
at the table's -- as custom properties rather than plain declarations on purpose:
|
|
232
|
+
an existing `--stuic-data-table-paging-*` / `--stuic-data-table-cell-font-size`
|
|
233
|
+
override keeps driving the pager, with no dependence on which of the two
|
|
234
|
+
same-specificity rules happens to win the cascade. The layout declarations below
|
|
235
|
+
are a deliberate duplicate of Pagination's own, so the region class stays
|
|
236
|
+
self-sufficient.
|
|
237
|
+
*/
|
|
227
238
|
.stuic-data-table-paging {
|
|
228
239
|
display: flex;
|
|
229
240
|
align-items: center;
|
|
230
241
|
justify-content: center;
|
|
231
|
-
gap: var(--stuic-data-table-paging-gap);
|
|
232
242
|
padding-top: var(--stuic-data-table-paging-padding-y);
|
|
243
|
+
|
|
244
|
+
--stuic-pagination-gap: var(--stuic-data-table-paging-gap);
|
|
233
245
|
}
|
|
234
246
|
|
|
235
247
|
.stuic-data-table-paging-info {
|
|
236
|
-
font-size: var(--stuic-data-table-cell-font-size);
|
|
237
|
-
color: var(--stuic-data-table-header-color);
|
|
238
248
|
white-space: nowrap;
|
|
249
|
+
|
|
250
|
+
--stuic-pagination-info-font-size: var(--stuic-data-table-cell-font-size);
|
|
251
|
+
--stuic-pagination-info-text: var(--stuic-data-table-header-color);
|
|
239
252
|
}
|
|
240
253
|
|
|
241
254
|
/* ============================================================================
|
|
@@ -322,6 +335,31 @@
|
|
|
322
335
|
justify-content: center;
|
|
323
336
|
}
|
|
324
337
|
|
|
338
|
+
/*
|
|
339
|
+
The built-in empty state is an `EmptyState`, which brings its own padding -- which
|
|
340
|
+
would otherwise stack on the container's. Keyed on the marker class rather than on
|
|
341
|
+
`.stuic-empty-state` so that an `empty` snippet rendering an EmptyState of its own
|
|
342
|
+
is left alone: it keeps the container padding it has always had, and the
|
|
343
|
+
component's own look.
|
|
344
|
+
*/
|
|
345
|
+
.stuic-data-table-empty:has(> .stuic-data-table-empty-state) {
|
|
346
|
+
padding: 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/*
|
|
350
|
+
Pull the built-in EmptyState back to table chrome: the "No data" line is a cell
|
|
351
|
+
note, not a headline. Fed from the tokens the rest of the table uses, so it stays
|
|
352
|
+
in sync with a consumer's overrides.
|
|
353
|
+
*/
|
|
354
|
+
.stuic-data-table-empty-state {
|
|
355
|
+
--stuic-empty-state-padding-sm: 2rem;
|
|
356
|
+
--stuic-empty-state-title-font-size-sm: var(--stuic-data-table-cell-font-size);
|
|
357
|
+
/* NOT `inherit`: a CSS-wide keyword in a custom property applies to the property
|
|
358
|
+
itself, so it would inherit the :root value (semibold) rather than the cell's. */
|
|
359
|
+
--stuic-empty-state-title-font-weight: normal;
|
|
360
|
+
--stuic-empty-state-title-text: var(--stuic-data-table-header-color);
|
|
361
|
+
}
|
|
362
|
+
|
|
325
363
|
/* ============================================================================
|
|
326
364
|
MOBILE CARDS
|
|
327
365
|
============================================================================ */
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
import type { THC } from "../Thc/Thc.svelte";
|
|
5
|
+
|
|
6
|
+
export type EmptyStateVariant = "plain" | "outline" | "dashed";
|
|
7
|
+
export type EmptyStateSize = "sm" | "md" | "lg";
|
|
8
|
+
|
|
9
|
+
export interface Props extends Omit<
|
|
10
|
+
HTMLAttributes<HTMLDivElement>,
|
|
11
|
+
"children" | "title"
|
|
12
|
+
> {
|
|
13
|
+
/** Icon area content (typically `{ html: iconSearch({ size: 48 }) }`) */
|
|
14
|
+
icon?: THC;
|
|
15
|
+
/** Title (the "Nothing here yet" headline) */
|
|
16
|
+
title?: THC;
|
|
17
|
+
/** Short supporting description below the title */
|
|
18
|
+
description?: THC;
|
|
19
|
+
/** Container treatment */
|
|
20
|
+
variant?: EmptyStateVariant;
|
|
21
|
+
/** Size preset (padding, icon and typography scale) */
|
|
22
|
+
size?: EmptyStateSize;
|
|
23
|
+
/** CTA area below the description (buttons, links) */
|
|
24
|
+
actions?: Snippet;
|
|
25
|
+
/** Override the entire default layout */
|
|
26
|
+
children?: Snippet;
|
|
27
|
+
/** Override the icon area */
|
|
28
|
+
renderIcon?: Snippet;
|
|
29
|
+
/** Skip all default styling */
|
|
30
|
+
unstyled?: boolean;
|
|
31
|
+
/** Additional CSS classes */
|
|
32
|
+
class?: string;
|
|
33
|
+
/** Class for the icon area */
|
|
34
|
+
classIcon?: string;
|
|
35
|
+
/** Class for the title */
|
|
36
|
+
classTitle?: string;
|
|
37
|
+
/** Class for the description */
|
|
38
|
+
classDescription?: string;
|
|
39
|
+
/** Class for the actions area */
|
|
40
|
+
classActions?: string;
|
|
41
|
+
/** Bindable element reference */
|
|
42
|
+
el?: HTMLElement;
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<script lang="ts">
|
|
47
|
+
import { twMerge } from "../../utils/tw-merge.js";
|
|
48
|
+
import Thc from "../Thc/Thc.svelte";
|
|
49
|
+
|
|
50
|
+
let {
|
|
51
|
+
icon,
|
|
52
|
+
title,
|
|
53
|
+
description,
|
|
54
|
+
variant = "plain",
|
|
55
|
+
size = "md",
|
|
56
|
+
actions,
|
|
57
|
+
children,
|
|
58
|
+
renderIcon,
|
|
59
|
+
unstyled = false,
|
|
60
|
+
class: classProp,
|
|
61
|
+
classIcon: classIconProp,
|
|
62
|
+
classTitle: classTitleProp,
|
|
63
|
+
classDescription: classDescriptionProp,
|
|
64
|
+
classActions: classActionsProp,
|
|
65
|
+
el = $bindable(),
|
|
66
|
+
...rest
|
|
67
|
+
}: Props = $props();
|
|
68
|
+
|
|
69
|
+
let _class = $derived(unstyled ? classProp : twMerge("stuic-empty-state", classProp));
|
|
70
|
+
let _classIcon = $derived(
|
|
71
|
+
unstyled ? classIconProp : twMerge("stuic-empty-state-icon", classIconProp)
|
|
72
|
+
);
|
|
73
|
+
let _classTitle = $derived(
|
|
74
|
+
unstyled ? classTitleProp : twMerge("stuic-empty-state-title", classTitleProp)
|
|
75
|
+
);
|
|
76
|
+
let _classDescription = $derived(
|
|
77
|
+
unstyled
|
|
78
|
+
? classDescriptionProp
|
|
79
|
+
: twMerge("stuic-empty-state-description", classDescriptionProp)
|
|
80
|
+
);
|
|
81
|
+
let _classActions = $derived(
|
|
82
|
+
unstyled ? classActionsProp : twMerge("stuic-empty-state-actions", classActionsProp)
|
|
83
|
+
);
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<div
|
|
87
|
+
bind:this={el}
|
|
88
|
+
class={_class}
|
|
89
|
+
data-variant={!unstyled ? variant : undefined}
|
|
90
|
+
data-size={!unstyled ? size : undefined}
|
|
91
|
+
{...rest}
|
|
92
|
+
>
|
|
93
|
+
{#if children}
|
|
94
|
+
{@render children()}
|
|
95
|
+
{:else}
|
|
96
|
+
{#if renderIcon || icon}
|
|
97
|
+
<div class={_classIcon}>
|
|
98
|
+
{#if renderIcon}
|
|
99
|
+
{@render renderIcon()}
|
|
100
|
+
{:else if icon}
|
|
101
|
+
<Thc thc={icon} />
|
|
102
|
+
{/if}
|
|
103
|
+
</div>
|
|
104
|
+
{/if}
|
|
105
|
+
{#if title}
|
|
106
|
+
<div class={_classTitle}>
|
|
107
|
+
<Thc thc={title} />
|
|
108
|
+
</div>
|
|
109
|
+
{/if}
|
|
110
|
+
{#if description}
|
|
111
|
+
<div class={_classDescription}>
|
|
112
|
+
<Thc thc={description} />
|
|
113
|
+
</div>
|
|
114
|
+
{/if}
|
|
115
|
+
{#if actions}
|
|
116
|
+
<div class={_classActions}>
|
|
117
|
+
{@render actions()}
|
|
118
|
+
</div>
|
|
119
|
+
{/if}
|
|
120
|
+
{/if}
|
|
121
|
+
</div>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { THC } from "../Thc/Thc.svelte";
|
|
4
|
+
export type EmptyStateVariant = "plain" | "outline" | "dashed";
|
|
5
|
+
export type EmptyStateSize = "sm" | "md" | "lg";
|
|
6
|
+
export interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "title"> {
|
|
7
|
+
/** Icon area content (typically `{ html: iconSearch({ size: 48 }) }`) */
|
|
8
|
+
icon?: THC;
|
|
9
|
+
/** Title (the "Nothing here yet" headline) */
|
|
10
|
+
title?: THC;
|
|
11
|
+
/** Short supporting description below the title */
|
|
12
|
+
description?: THC;
|
|
13
|
+
/** Container treatment */
|
|
14
|
+
variant?: EmptyStateVariant;
|
|
15
|
+
/** Size preset (padding, icon and typography scale) */
|
|
16
|
+
size?: EmptyStateSize;
|
|
17
|
+
/** CTA area below the description (buttons, links) */
|
|
18
|
+
actions?: Snippet;
|
|
19
|
+
/** Override the entire default layout */
|
|
20
|
+
children?: Snippet;
|
|
21
|
+
/** Override the icon area */
|
|
22
|
+
renderIcon?: Snippet;
|
|
23
|
+
/** Skip all default styling */
|
|
24
|
+
unstyled?: boolean;
|
|
25
|
+
/** Additional CSS classes */
|
|
26
|
+
class?: string;
|
|
27
|
+
/** Class for the icon area */
|
|
28
|
+
classIcon?: string;
|
|
29
|
+
/** Class for the title */
|
|
30
|
+
classTitle?: string;
|
|
31
|
+
/** Class for the description */
|
|
32
|
+
classDescription?: string;
|
|
33
|
+
/** Class for the actions area */
|
|
34
|
+
classActions?: string;
|
|
35
|
+
/** Bindable element reference */
|
|
36
|
+
el?: HTMLElement;
|
|
37
|
+
}
|
|
38
|
+
declare const EmptyState: import("svelte").Component<Props, {}, "el">;
|
|
39
|
+
type EmptyState = ReturnType<typeof EmptyState>;
|
|
40
|
+
export default EmptyState;
|