@streamscloud/kit 0.23.0 → 0.25.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/dist/styles/_semantic.scss +16 -0
- package/dist/ui/badge/cmp.badge.svelte +30 -19
- package/dist/ui/badge/cmp.badge.svelte.d.ts +5 -3
- package/dist/ui/badge/index.d.ts +1 -1
- package/dist/ui/badge/types.d.ts +2 -1
- package/dist/ui/grid-card/fields/cmp.grid-card-progress-field.svelte +5 -60
- package/dist/ui/grid-card/fields/cmp.grid-card-progress-field.svelte.d.ts +5 -17
- package/dist/ui/page-toolbar/cmp.toolbar-icon-button.svelte +9 -8
- package/dist/ui/page-toolbar/cmp.toolbar-icon-button.svelte.d.ts +6 -5
- package/dist/ui/page-toolbar/cmp.toolbar-sort-select.svelte +26 -9
- package/dist/ui/page-toolbar/cmp.toolbar-sort-select.svelte.d.ts +7 -5
- package/dist/ui/page-toolbar/cmp.toolbar-value-stepper.svelte +8 -8
- package/dist/ui/page-toolbar/cmp.toolbar-value-stepper.svelte.d.ts +4 -4
- package/dist/ui/page-toolbar/cmp.toolbar-view-controls.svelte +11 -6
- package/dist/ui/page-toolbar/cmp.toolbar-view-controls.svelte.d.ts +7 -4
- package/dist/ui/page-toolbar/toolbar-sort-select-localization.d.ts +1 -0
- package/dist/ui/page-toolbar/toolbar-sort-select-localization.js +5 -1
- package/dist/ui/page-toolbar/toolbar-view-controls-localization.d.ts +1 -0
- package/dist/ui/page-toolbar/toolbar-view-controls-localization.js +5 -1
- package/dist/ui/progress-bar/cmp.progress-bar.svelte +111 -0
- package/dist/ui/progress-bar/cmp.progress-bar.svelte.d.ts +37 -0
- package/dist/ui/progress-bar/index.d.ts +2 -0
- package/dist/ui/progress-bar/index.js +1 -0
- package/dist/ui/progress-bar/progress-bar-localization.d.ts +3 -0
- package/dist/ui/progress-bar/progress-bar-localization.js +9 -0
- package/dist/ui/progress-bar/types.d.ts +7 -0
- package/dist/ui/progress-bar/types.js +1 -0
- package/dist/ui/table/table-cells/table-badge-cell.svelte +1 -1
- package/dist/ui/table/table-cells/table-cell.svelte +0 -3
- package/dist/ui/table/table-cells/table-image-cell.svelte +19 -2
- package/dist/ui/table/types.d.ts +6 -9
- package/dist/ui/table/types.js +1 -1
- package/package.json +5 -1
- package/dist/ui/table/table-cells/table-custom-cell.svelte +0 -5
- package/dist/ui/table/table-cells/table-custom-cell.svelte.d.ts +0 -38
|
@@ -61,6 +61,22 @@
|
|
|
61
61
|
--sc-kit--color--info--hover: light-dark(#{$color-blue-700}, #{$color-blue-300});
|
|
62
62
|
--sc-kit--color--info--soft: light-dark(#{$color-blue-50}, #{$color-blue-900});
|
|
63
63
|
|
|
64
|
+
// ============================================================
|
|
65
|
+
// COLOR — TONES (categorical palette; fg + soft bg, component-neutral)
|
|
66
|
+
// ============================================================
|
|
67
|
+
--sc-kit--tone--gray--fg: light-dark(#{$color-neutral-500}, #{$color-neutral-400});
|
|
68
|
+
--sc-kit--tone--gray--bg: light-dark(#{$color-neutral-50}, #{$color-dark-600});
|
|
69
|
+
--sc-kit--tone--blue--fg: light-dark(#{$color-blue-500}, #{$color-blue-400});
|
|
70
|
+
--sc-kit--tone--blue--bg: light-dark(#{$color-blue-50}, #{$color-blue-900});
|
|
71
|
+
--sc-kit--tone--green--fg: light-dark(#{$color-green-500}, #{$color-green-400});
|
|
72
|
+
--sc-kit--tone--green--bg: light-dark(#{$color-green-50}, #{$color-green-900});
|
|
73
|
+
--sc-kit--tone--red--fg: light-dark(#{$color-red-500}, #{$color-red-400});
|
|
74
|
+
--sc-kit--tone--red--bg: light-dark(#{$color-red-50}, #{$color-red-900});
|
|
75
|
+
--sc-kit--tone--orange--fg: light-dark(#{$color-orange-500}, #{$color-orange-400});
|
|
76
|
+
--sc-kit--tone--orange--bg: light-dark(#{$color-orange-100}, #{$color-orange-900});
|
|
77
|
+
--sc-kit--tone--teal--fg: light-dark(#3d7068, #5f938a);
|
|
78
|
+
--sc-kit--tone--teal--bg: light-dark(#eef4f3, #16302b);
|
|
79
|
+
|
|
64
80
|
// ============================================================
|
|
65
81
|
// COLOR — OVERLAYS
|
|
66
82
|
// ============================================================
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">import { IconSlot } from '../icon';
|
|
2
|
-
const { variant = 'neutral', size = 'md', style = 'soft', fullWidth = false, icon, children } = $props();
|
|
2
|
+
const { variant = 'neutral', size = 'md', style = 'soft', shape = 'pill', fullWidth = false, icon, children } = $props();
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
|
-
<span class="badge badge--{size} badge--{variant}-{style}" class:badge--full={fullWidth}>
|
|
5
|
+
<span class="badge badge--{size} badge--{variant}-{style}" class:badge--square={shape === 'square'} class:badge--full={fullWidth}>
|
|
6
6
|
{#if icon}
|
|
7
7
|
<span class="badge__icon" aria-hidden="true"><IconSlot icon={icon} /></span>
|
|
8
8
|
{/if}
|
|
@@ -11,7 +11,7 @@ const { variant = 'neutral', size = 'md', style = 'soft', fullWidth = false, ico
|
|
|
11
11
|
|
|
12
12
|
<!--
|
|
13
13
|
@component
|
|
14
|
-
|
|
14
|
+
Status indicator, pill-shaped by default (`shape="square"` for a 4px-radius chip). Use `solid` for stronger emphasis, `soft` (default) for a calm tinted fill that pairs with body content. Optional leading `icon` renders in its own slot; the text content keeps its own ellipsis when it overflows.
|
|
15
15
|
|
|
16
16
|
### CSS Custom Properties
|
|
17
17
|
| Property | Description | Default |
|
|
@@ -20,7 +20,7 @@ Pill-shaped status indicator. Use `solid` for stronger emphasis, `soft` (default
|
|
|
20
20
|
| `--sc-kit--badge--background` | Background color | per variant + style |
|
|
21
21
|
| `--sc-kit--badge--height` | Badge height | per size (20 / 24px) |
|
|
22
22
|
| `--sc-kit--badge--padding-inline` | Horizontal padding | `0.875rem 0.75rem` |
|
|
23
|
-
| `--sc-kit--badge--border-radius` | Corner radius | `var(--sc-kit--radius--pill)` |
|
|
23
|
+
| `--sc-kit--badge--border-radius` | Corner radius | `shape="square"` → `var(--sc-kit--radius--sm)`, else `var(--sc-kit--radius--pill)` |
|
|
24
24
|
| `--sc-kit--badge--font-size` | Content font size | per size |
|
|
25
25
|
| `--sc-kit--badge--icon-size` | Leading icon size | per size (14 / 16px) |
|
|
26
26
|
| `--sc-kit--badge--font-weight` | Font weight | `var(--sc-kit--font-weight--medium)` |
|
|
@@ -57,6 +57,9 @@ Pill-shaped status indicator. Use `solid` for stronger emphasis, `soft` (default
|
|
|
57
57
|
text-overflow: ellipsis;
|
|
58
58
|
white-space: nowrap;
|
|
59
59
|
}
|
|
60
|
+
.badge--square {
|
|
61
|
+
--_badge--border-radius: var(--sc-kit--badge--border-radius, var(--sc-kit--radius--sm));
|
|
62
|
+
}
|
|
60
63
|
.badge--full {
|
|
61
64
|
display: flex;
|
|
62
65
|
width: 100%;
|
|
@@ -73,42 +76,50 @@ Pill-shaped status indicator. Use `solid` for stronger emphasis, `soft` (default
|
|
|
73
76
|
--_badge--icon-size: var(--sc-kit--badge--icon-size, 1rem);
|
|
74
77
|
}
|
|
75
78
|
.badge--neutral-soft {
|
|
76
|
-
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--
|
|
77
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
79
|
+
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--tone--gray--fg));
|
|
80
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--gray--bg));
|
|
78
81
|
}
|
|
79
82
|
.badge--accent-soft {
|
|
80
|
-
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--
|
|
81
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
83
|
+
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--tone--blue--fg));
|
|
84
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--blue--bg));
|
|
85
|
+
}
|
|
86
|
+
.badge--auxiliary-soft {
|
|
87
|
+
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--tone--teal--fg));
|
|
88
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--teal--bg));
|
|
82
89
|
}
|
|
83
90
|
.badge--success-soft {
|
|
84
|
-
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--
|
|
85
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
91
|
+
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--tone--green--fg));
|
|
92
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--green--bg));
|
|
86
93
|
}
|
|
87
94
|
.badge--warning-soft {
|
|
88
|
-
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--
|
|
89
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
95
|
+
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--tone--orange--fg));
|
|
96
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--orange--bg));
|
|
90
97
|
}
|
|
91
98
|
.badge--danger-soft {
|
|
92
|
-
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--
|
|
93
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
99
|
+
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--tone--red--fg));
|
|
100
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--red--bg));
|
|
94
101
|
}
|
|
95
102
|
.badge--neutral-solid {
|
|
96
103
|
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--color--bg--panel));
|
|
97
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
104
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--gray--fg));
|
|
98
105
|
}
|
|
99
106
|
.badge--accent-solid {
|
|
100
107
|
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--color--text--on-accent));
|
|
101
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
108
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--blue--fg));
|
|
109
|
+
}
|
|
110
|
+
.badge--auxiliary-solid {
|
|
111
|
+
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--color--text--on-accent));
|
|
112
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--teal--fg));
|
|
102
113
|
}
|
|
103
114
|
.badge--success-solid {
|
|
104
115
|
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--color--text--on-accent));
|
|
105
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
116
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--green--fg));
|
|
106
117
|
}
|
|
107
118
|
.badge--warning-solid {
|
|
108
119
|
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--color--text--primary));
|
|
109
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
120
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--orange--fg));
|
|
110
121
|
}
|
|
111
122
|
.badge--danger-solid {
|
|
112
123
|
--_badge--color: var(--sc-kit--badge--color, var(--sc-kit--color--text--on-accent));
|
|
113
|
-
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--
|
|
124
|
+
--_badge--background: var(--sc-kit--badge--background, var(--sc-kit--tone--red--fg));
|
|
114
125
|
}</style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type IconProp } from '../icon';
|
|
2
|
-
import type { BadgeVariant } from './types';
|
|
2
|
+
import type { BadgeShape, BadgeVariant } from './types';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
4
|
type Props = {
|
|
5
5
|
/** Color variant @default 'neutral' */
|
|
@@ -8,6 +8,8 @@ type Props = {
|
|
|
8
8
|
size?: 'sm' | 'md';
|
|
9
9
|
/** Filled chip vs soft-tinted fill @default 'soft' */
|
|
10
10
|
style?: 'soft' | 'solid';
|
|
11
|
+
/** Corner style — pill (fully rounded) vs square (4px radius). @default 'pill' */
|
|
12
|
+
shape?: BadgeShape;
|
|
11
13
|
/** Stretch to fill the parent's inline axis, centering the content. @default false */
|
|
12
14
|
fullWidth?: boolean;
|
|
13
15
|
/** Optional leading icon. */
|
|
@@ -15,7 +17,7 @@ type Props = {
|
|
|
15
17
|
children: Snippet;
|
|
16
18
|
};
|
|
17
19
|
/**
|
|
18
|
-
*
|
|
20
|
+
* Status indicator, pill-shaped by default (`shape="square"` for a 4px-radius chip). Use `solid` for stronger emphasis, `soft` (default) for a calm tinted fill that pairs with body content. Optional leading `icon` renders in its own slot; the text content keeps its own ellipsis when it overflows.
|
|
19
21
|
*
|
|
20
22
|
* ### CSS Custom Properties
|
|
21
23
|
* | Property | Description | Default |
|
|
@@ -24,7 +26,7 @@ type Props = {
|
|
|
24
26
|
* | `--sc-kit--badge--background` | Background color | per variant + style |
|
|
25
27
|
* | `--sc-kit--badge--height` | Badge height | per size (20 / 24px) |
|
|
26
28
|
* | `--sc-kit--badge--padding-inline` | Horizontal padding | `0.875rem 0.75rem` |
|
|
27
|
-
* | `--sc-kit--badge--border-radius` | Corner radius | `var(--sc-kit--radius--pill)` |
|
|
29
|
+
* | `--sc-kit--badge--border-radius` | Corner radius | `shape="square"` → `var(--sc-kit--radius--sm)`, else `var(--sc-kit--radius--pill)` |
|
|
28
30
|
* | `--sc-kit--badge--font-size` | Content font size | per size |
|
|
29
31
|
* | `--sc-kit--badge--icon-size` | Leading icon size | per size (14 / 16px) |
|
|
30
32
|
* | `--sc-kit--badge--font-weight` | Font weight | `var(--sc-kit--font-weight--medium)` |
|
package/dist/ui/badge/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as Badge } from './cmp.badge.svelte';
|
|
2
|
-
export type { BadgeVariant } from './types';
|
|
2
|
+
export type { BadgeShape, BadgeVariant } from './types';
|
package/dist/ui/badge/types.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export type BadgeVariant = 'neutral' | 'accent' | 'success' | 'warning' | 'danger';
|
|
1
|
+
export type BadgeVariant = 'neutral' | 'accent' | 'auxiliary' | 'success' | 'warning' | 'danger';
|
|
2
|
+
export type BadgeShape = 'pill' | 'square';
|
|
@@ -1,69 +1,14 @@
|
|
|
1
|
-
<script lang="ts">import
|
|
1
|
+
<script lang="ts">import { ProgressBar } from '../../progress-bar';
|
|
2
|
+
import GridCardField from './cmp.grid-card-field.svelte';
|
|
2
3
|
const { label, stage, stages } = $props();
|
|
3
|
-
const currentStage = $derived(stages[Math.max(0, Math.min(stage, stages.length - 1))]);
|
|
4
|
-
const currentLabel = $derived(currentStage?.label ?? '');
|
|
5
4
|
</script>
|
|
6
5
|
|
|
7
6
|
<GridCardField label={label}>
|
|
8
|
-
<
|
|
9
|
-
<div
|
|
10
|
-
class="grid-card-progress-field__bar"
|
|
11
|
-
role="progressbar"
|
|
12
|
-
aria-valuemin={1}
|
|
13
|
-
aria-valuemax={stages.length}
|
|
14
|
-
aria-valuenow={stage + 1}
|
|
15
|
-
aria-label={currentLabel}>
|
|
16
|
-
{#each stages as s, i (i)}
|
|
17
|
-
<span class="grid-card-progress-field__segment" class:grid-card-progress-field__segment--filled={i <= stage} style:--_seg-color={s.color}></span>
|
|
18
|
-
{/each}
|
|
19
|
-
</div>
|
|
20
|
-
{#if currentLabel}
|
|
21
|
-
<span class="grid-card-progress-field__label">{currentLabel}</span>
|
|
22
|
-
{/if}
|
|
23
|
-
</div>
|
|
7
|
+
<ProgressBar stage={stage} stages={stages} />
|
|
24
8
|
</GridCardField>
|
|
25
9
|
|
|
26
10
|
<!--
|
|
27
11
|
@component
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
filled with the per-stage color, the rest are muted. Consumer supplies the per-stage color
|
|
31
|
-
(string — any valid CSS color or `var(--sc-kit--color--*)` reference). Useful for content
|
|
32
|
-
lifecycle indicators (Ideas → Draft → Review → Scheduled → Published).
|
|
33
|
-
|
|
34
|
-
### CSS Custom Properties
|
|
35
|
-
| Property | Description | Default |
|
|
36
|
-
|---|---|---|
|
|
37
|
-
| `--sc-kit--grid-card-progress-field--segment--height` | Bar segment height | `4px` |
|
|
38
|
-
| `--sc-kit--grid-card-progress-field--segment--gap` | Gap between segments | `2px` |
|
|
39
|
-
| `--sc-kit--grid-card-progress-field--segment--background--empty` | Empty segment color | `var(--sc-kit--color--bg--active)` |
|
|
12
|
+
Grid-card field pairing a field label with a multi-stage `ProgressBar`. See `ProgressBar`
|
|
13
|
+
(`@streamscloud/kit/ui/progress-bar`) for the bar's own CSS Custom Properties.
|
|
40
14
|
-->
|
|
41
|
-
|
|
42
|
-
<style>.grid-card-progress-field {
|
|
43
|
-
--_gcp--seg-height: var(--sc-kit--grid-card-progress-field--segment--height, 0.25rem);
|
|
44
|
-
--_gcp--seg-gap: var(--sc-kit--grid-card-progress-field--segment--gap, 0.125rem);
|
|
45
|
-
--_gcp--seg-empty: var(--sc-kit--grid-card-progress-field--segment--background--empty, var(--sc-kit--color--bg--active));
|
|
46
|
-
display: flex;
|
|
47
|
-
flex-direction: column;
|
|
48
|
-
gap: 0.125rem;
|
|
49
|
-
min-width: 0;
|
|
50
|
-
}
|
|
51
|
-
.grid-card-progress-field__bar {
|
|
52
|
-
display: flex;
|
|
53
|
-
gap: var(--_gcp--seg-gap);
|
|
54
|
-
width: 100%;
|
|
55
|
-
}
|
|
56
|
-
.grid-card-progress-field__segment {
|
|
57
|
-
flex: 1;
|
|
58
|
-
height: var(--_gcp--seg-height);
|
|
59
|
-
background: var(--_gcp--seg-empty);
|
|
60
|
-
border-radius: 0.0625rem;
|
|
61
|
-
}
|
|
62
|
-
.grid-card-progress-field__segment--filled {
|
|
63
|
-
background: var(--_seg-color);
|
|
64
|
-
}
|
|
65
|
-
.grid-card-progress-field__label {
|
|
66
|
-
font-size: 0.625rem;
|
|
67
|
-
color: var(--sc-kit--color--text--secondary);
|
|
68
|
-
line-height: var(--sc-kit--leading--tight);
|
|
69
|
-
}</style>
|
|
@@ -1,29 +1,17 @@
|
|
|
1
|
+
import { type ProgressBarStage } from '../../progress-bar';
|
|
1
2
|
type Props = {
|
|
2
3
|
label: string;
|
|
3
4
|
/** Current stage index, 0-based. Stages 0..stage (inclusive) are filled. */
|
|
4
5
|
stage: number;
|
|
5
6
|
/**
|
|
6
7
|
* Stage descriptors — at minimum `{ color }` per stage (consumer provides the CSS color).
|
|
7
|
-
* Length determines the total segment count.
|
|
8
|
+
* Length determines the total segment count.
|
|
8
9
|
*/
|
|
9
|
-
stages:
|
|
10
|
-
color: string;
|
|
11
|
-
label?: string;
|
|
12
|
-
}[];
|
|
10
|
+
stages: ProgressBarStage[];
|
|
13
11
|
};
|
|
14
12
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* filled with the per-stage color, the rest are muted. Consumer supplies the per-stage color
|
|
18
|
-
* (string — any valid CSS color or `var(--sc-kit--color--*)` reference). Useful for content
|
|
19
|
-
* lifecycle indicators (Ideas → Draft → Review → Scheduled → Published).
|
|
20
|
-
*
|
|
21
|
-
* ### CSS Custom Properties
|
|
22
|
-
* | Property | Description | Default |
|
|
23
|
-
* |---|---|---|
|
|
24
|
-
* | `--sc-kit--grid-card-progress-field--segment--height` | Bar segment height | `4px` |
|
|
25
|
-
* | `--sc-kit--grid-card-progress-field--segment--gap` | Gap between segments | `2px` |
|
|
26
|
-
* | `--sc-kit--grid-card-progress-field--segment--background--empty` | Empty segment color | `var(--sc-kit--color--bg--active)` |
|
|
13
|
+
* Grid-card field pairing a field label with a multi-stage `ProgressBar`. See `ProgressBar`
|
|
14
|
+
* (`@streamscloud/kit/ui/progress-bar`) for the bar's own CSS Custom Properties.
|
|
27
15
|
*/
|
|
28
16
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
29
17
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -4,7 +4,7 @@ const { icon, 'aria-label': ariaLabel, size = 'sm', active = false, disabled = f
|
|
|
4
4
|
|
|
5
5
|
{#if presentational}
|
|
6
6
|
<span class="toolbar-icon-button toolbar-icon-button--{size}" class:toolbar-icon-button--active={active}>
|
|
7
|
-
<Icon src={icon} size=
|
|
7
|
+
<Icon src={icon} size={size === 'sm' ? 'control-md' : 'md'} />
|
|
8
8
|
</span>
|
|
9
9
|
{:else}
|
|
10
10
|
<button
|
|
@@ -15,28 +15,29 @@ const { icon, 'aria-label': ariaLabel, size = 'sm', active = false, disabled = f
|
|
|
15
15
|
aria-label={ariaLabel}
|
|
16
16
|
aria-pressed={active}
|
|
17
17
|
onclick={() => on?.click?.()}>
|
|
18
|
-
<Icon src={icon} size=
|
|
18
|
+
<Icon src={icon} size={size === 'sm' ? 'control-md' : 'md'} />
|
|
19
19
|
</button>
|
|
20
20
|
{/if}
|
|
21
21
|
|
|
22
22
|
<!--
|
|
23
23
|
@component
|
|
24
|
-
A flat, square toolbar icon button (28px at `sm`, 32px at `md`, with a
|
|
25
|
-
hover only; `active` tints the glyph with the
|
|
26
|
-
a non-interactive `<span>` for use inside a wrapper that owns the click +
|
|
27
|
-
Shared by `ToolbarViewControls` and the `
|
|
24
|
+
A flat, square toolbar icon button (28px at `sm`, 32px at `md`, with a 16px glyph at `sm` / 20px at `md`).
|
|
25
|
+
Background appears on hover only; `active` tints the glyph with the primary text color (no background). Pass
|
|
26
|
+
`presentational` to render a non-interactive `<span>` for use inside a wrapper that owns the click +
|
|
27
|
+
semantics (e.g. a Popover trigger). Shared by `ToolbarViewControls` and the `ToolbarSortSelect` icon trigger
|
|
28
|
+
so they stay visually identical.
|
|
28
29
|
|
|
29
30
|
### CSS Custom Properties
|
|
30
31
|
| Property | Description | Default |
|
|
31
32
|
|---|---|---|
|
|
32
33
|
| `--sc-kit--toolbar-icon-button--color` | Idle glyph color | `var(--sc-kit--color--text--muted)` |
|
|
33
|
-
| `--sc-kit--toolbar-icon-button--color--active` | Active glyph color | `var(--sc-kit--color--
|
|
34
|
+
| `--sc-kit--toolbar-icon-button--color--active` | Active glyph color | `var(--sc-kit--color--text--primary)` |
|
|
34
35
|
| `--sc-kit--toolbar-icon-button--background--hover` | Hover background | `var(--sc-kit--color--bg--hover)` |
|
|
35
36
|
-->
|
|
36
37
|
|
|
37
38
|
<style>.toolbar-icon-button {
|
|
38
39
|
--_tib--color: var(--sc-kit--toolbar-icon-button--color, var(--sc-kit--color--text--muted));
|
|
39
|
-
--_tib--color-active: var(--sc-kit--toolbar-icon-button--color--active, var(--sc-kit--color--
|
|
40
|
+
--_tib--color-active: var(--sc-kit--toolbar-icon-button--color--active, var(--sc-kit--color--text--primary));
|
|
40
41
|
--_tib--background-hover: var(--sc-kit--toolbar-icon-button--background--hover, var(--sc-kit--color--bg--hover));
|
|
41
42
|
--_tib--size: var(--_tib--size-height);
|
|
42
43
|
--sc-kit--icon--color: var(--_tib--color);
|
|
@@ -15,16 +15,17 @@ type Props = {
|
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
|
-
* A flat, square toolbar icon button (28px at `sm`, 32px at `md`, with a
|
|
19
|
-
* hover only; `active` tints the glyph with the
|
|
20
|
-
* a non-interactive `<span>` for use inside a wrapper that owns the click +
|
|
21
|
-
* Shared by `ToolbarViewControls` and the `
|
|
18
|
+
* A flat, square toolbar icon button (28px at `sm`, 32px at `md`, with a 16px glyph at `sm` / 20px at `md`).
|
|
19
|
+
* Background appears on hover only; `active` tints the glyph with the primary text color (no background). Pass
|
|
20
|
+
* `presentational` to render a non-interactive `<span>` for use inside a wrapper that owns the click +
|
|
21
|
+
* semantics (e.g. a Popover trigger). Shared by `ToolbarViewControls` and the `ToolbarSortSelect` icon trigger
|
|
22
|
+
* so they stay visually identical.
|
|
22
23
|
*
|
|
23
24
|
* ### CSS Custom Properties
|
|
24
25
|
* | Property | Description | Default |
|
|
25
26
|
* |---|---|---|
|
|
26
27
|
* | `--sc-kit--toolbar-icon-button--color` | Idle glyph color | `var(--sc-kit--color--text--muted)` |
|
|
27
|
-
* | `--sc-kit--toolbar-icon-button--color--active` | Active glyph color | `var(--sc-kit--color--
|
|
28
|
+
* | `--sc-kit--toolbar-icon-button--color--active` | Active glyph color | `var(--sc-kit--color--text--primary)` |
|
|
28
29
|
* | `--sc-kit--toolbar-icon-button--background--hover` | Hover background | `var(--sc-kit--color--bg--hover)` |
|
|
29
30
|
*/
|
|
30
31
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
<script lang="ts" generics="S">import
|
|
1
|
+
<script lang="ts" generics="S">import { Button } from '../button';
|
|
2
|
+
import ToolbarFilterSelect from './cmp.toolbar-filter-select.svelte';
|
|
2
3
|
import ToolbarIconButton from './cmp.toolbar-icon-button.svelte';
|
|
3
4
|
import ToolbarSectionTitle from './cmp.toolbar-section-title.svelte';
|
|
4
5
|
import { ToolbarSortSelectLocalization } from './toolbar-sort-select-localization';
|
|
5
6
|
import IconFilter from '@fluentui/svg-icons/icons/filter_20_regular.svg?raw';
|
|
6
|
-
const { options, value, label, size = 'sm', icon, compare, on } = $props();
|
|
7
|
+
const { options, value, label, size = 'sm', trigger = 'icon', compare, on } = $props();
|
|
7
8
|
const localization = new ToolbarSortSelectLocalization();
|
|
8
9
|
const orderByLabel = $derived(label ?? localization.orderBy);
|
|
9
10
|
const selection = $derived([value]);
|
|
11
|
+
const resolvedTrigger = $derived(typeof trigger === 'function' ? trigger : trigger === 'button' ? buttonTrigger : iconTrigger);
|
|
10
12
|
const onChange = (next) => {
|
|
11
13
|
if (next.length > 0) {
|
|
12
14
|
on?.change?.(next[0]);
|
|
@@ -14,18 +16,33 @@ const onChange = (next) => {
|
|
|
14
16
|
};
|
|
15
17
|
</script>
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
{#snippet iconTrigger()}
|
|
20
|
+
<ToolbarIconButton presentational icon={IconFilter} size={size} />
|
|
21
|
+
{/snippet}
|
|
22
|
+
|
|
23
|
+
{#snippet buttonTrigger()}
|
|
24
|
+
<Button type="presentational" variant="secondary" size={size} icon={IconFilter}>{localization.sorting}</Button>
|
|
25
|
+
{/snippet}
|
|
26
|
+
|
|
27
|
+
<ToolbarFilterSelect
|
|
28
|
+
label={orderByLabel}
|
|
29
|
+
single
|
|
30
|
+
footer={false}
|
|
31
|
+
size={size}
|
|
32
|
+
options={options}
|
|
33
|
+
value={selection}
|
|
34
|
+
compare={compare}
|
|
35
|
+
trigger={resolvedTrigger}
|
|
36
|
+
on={{ change: onChange }}>
|
|
18
37
|
{#snippet header()}
|
|
19
38
|
<ToolbarSectionTitle>{orderByLabel}</ToolbarSectionTitle>
|
|
20
39
|
{/snippet}
|
|
21
|
-
{#snippet trigger()}
|
|
22
|
-
<ToolbarIconButton presentational icon={icon ?? IconFilter} size={size} />
|
|
23
|
-
{/snippet}
|
|
24
40
|
</ToolbarFilterSelect>
|
|
25
41
|
|
|
26
42
|
<!--
|
|
27
43
|
@component
|
|
28
|
-
A toolbar sort control: a `ToolbarFilterSelect` in single-select mode behind a
|
|
29
|
-
(
|
|
30
|
-
`
|
|
44
|
+
A toolbar sort control: a `ToolbarFilterSelect` in single-select mode behind a `trigger` — `'icon'`
|
|
45
|
+
(default, flat icon button), `'button'` (labelled secondary button), or a custom snippet — with an
|
|
46
|
+
`Order by` section title above the options. Stand-alone, or composed into `ToolbarViewControls` via
|
|
47
|
+
its `prepend` snippet.
|
|
31
48
|
-->
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SelectItem } from '../select';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
2
3
|
declare function $$render<S>(): {
|
|
3
4
|
props: {
|
|
4
5
|
options: SelectItem<S>[];
|
|
@@ -7,8 +8,8 @@ declare function $$render<S>(): {
|
|
|
7
8
|
label?: string;
|
|
8
9
|
/** Button size preset — sm = 28px, md = 32px. @default 'sm' */
|
|
9
10
|
size?: "sm" | "md";
|
|
10
|
-
/**
|
|
11
|
-
|
|
11
|
+
/** Presentational trigger — `'icon'` (flat icon button), `'button'` (labelled secondary button), or a custom snippet. The popover owns the click and is named by `label`. @default 'icon' */
|
|
12
|
+
trigger?: "icon" | "button" | Snippet;
|
|
12
13
|
/** Equality comparator — required when `S` is an object. */
|
|
13
14
|
compare?: (a: S, b: S) => boolean;
|
|
14
15
|
on?: {
|
|
@@ -35,9 +36,10 @@ interface $$IsomorphicComponent {
|
|
|
35
36
|
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
38
|
-
* A toolbar sort control: a `ToolbarFilterSelect` in single-select mode behind a
|
|
39
|
-
* (
|
|
40
|
-
* `
|
|
39
|
+
* A toolbar sort control: a `ToolbarFilterSelect` in single-select mode behind a `trigger` — `'icon'`
|
|
40
|
+
* (default, flat icon button), `'button'` (labelled secondary button), or a custom snippet — with an
|
|
41
|
+
* `Order by` section title above the options. Stand-alone, or composed into `ToolbarViewControls` via
|
|
42
|
+
* its `prepend` snippet.
|
|
41
43
|
*/
|
|
42
44
|
declare const Cmp: $$IsomorphicComponent;
|
|
43
45
|
type Cmp<S> = InstanceType<typeof Cmp<S>>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">import { CONTROL_ICON_SIZE, Icon, scaleUp } from '../icon';
|
|
2
2
|
import { ToolbarValueStepperLocalization } from './toolbar-value-stepper-localization';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import IconAdd from '@fluentui/svg-icons/icons/add_16_regular.svg?raw';
|
|
4
|
+
import IconSubtract from '@fluentui/svg-icons/icons/subtract_16_regular.svg?raw';
|
|
5
5
|
const { value, min = 0, max = 100, step = 1, valueSuffix = '', size = 'sm', on } = $props();
|
|
6
6
|
const localization = new ToolbarValueStepperLocalization();
|
|
7
7
|
const iconSize = $derived(scaleUp(CONTROL_ICON_SIZE[size]));
|
|
@@ -17,25 +17,25 @@ const increase = () => {
|
|
|
17
17
|
|
|
18
18
|
<div class="toolbar-value-stepper toolbar-value-stepper--{size}" role="group" aria-label={localization.value}>
|
|
19
19
|
<button type="button" class="toolbar-value-stepper__btn" onclick={decrease} disabled={atMin} aria-label={localization.decreaseValue}>
|
|
20
|
-
<Icon src={
|
|
20
|
+
<Icon src={IconSubtract} size={iconSize} />
|
|
21
21
|
</button>
|
|
22
22
|
<span class="toolbar-value-stepper__value">{value}{valueSuffix}</span>
|
|
23
23
|
<button type="button" class="toolbar-value-stepper__btn" onclick={increase} disabled={atMax} aria-label={localization.increaseValue}>
|
|
24
|
-
<Icon src={
|
|
24
|
+
<Icon src={IconAdd} size={iconSize} />
|
|
25
25
|
</button>
|
|
26
26
|
</div>
|
|
27
27
|
|
|
28
28
|
<!--
|
|
29
29
|
@component
|
|
30
|
-
A compact `[
|
|
31
|
-
and `max` by `step`, with an optional `valueSuffix` (e.g. ` %`).
|
|
30
|
+
A compact `[−] value [+]` stepper for toolbars — increment / decrement a numeric value between `min`
|
|
31
|
+
and `max` by `step`, with an optional `valueSuffix` (e.g. ` %`). The − / + buttons disable at the limits.
|
|
32
32
|
Shares the field-height preset so it lines up with other toolbar controls.
|
|
33
33
|
|
|
34
34
|
### CSS Custom Properties
|
|
35
35
|
| Property | Description | Default |
|
|
36
36
|
|---|---|---|
|
|
37
|
-
| `--sc-kit--toolbar-value-stepper--value--min-inline-size` | Min width of the value readout (keeps
|
|
38
|
-
| `--sc-kit--toolbar-value-stepper--icon--color` |
|
|
37
|
+
| `--sc-kit--toolbar-value-stepper--value--min-inline-size` | Min width of the value readout (keeps the buttons from shifting) | `2.25rem` |
|
|
38
|
+
| `--sc-kit--toolbar-value-stepper--icon--color` | Button icon color | `var(--sc-kit--color--accent)` |
|
|
39
39
|
-->
|
|
40
40
|
|
|
41
41
|
<style>.toolbar-value-stepper {
|
|
@@ -15,15 +15,15 @@ type Props = {
|
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
|
-
* A compact `[
|
|
19
|
-
* and `max` by `step`, with an optional `valueSuffix` (e.g. ` %`).
|
|
18
|
+
* A compact `[−] value [+]` stepper for toolbars — increment / decrement a numeric value between `min`
|
|
19
|
+
* and `max` by `step`, with an optional `valueSuffix` (e.g. ` %`). The − / + buttons disable at the limits.
|
|
20
20
|
* Shares the field-height preset so it lines up with other toolbar controls.
|
|
21
21
|
*
|
|
22
22
|
* ### CSS Custom Properties
|
|
23
23
|
* | Property | Description | Default |
|
|
24
24
|
* |---|---|---|
|
|
25
|
-
* | `--sc-kit--toolbar-value-stepper--value--min-inline-size` | Min width of the value readout (keeps
|
|
26
|
-
* | `--sc-kit--toolbar-value-stepper--icon--color` |
|
|
25
|
+
* | `--sc-kit--toolbar-value-stepper--value--min-inline-size` | Min width of the value readout (keeps the buttons from shifting) | `2.25rem` |
|
|
26
|
+
* | `--sc-kit--toolbar-value-stepper--icon--color` | Button icon color | `var(--sc-kit--color--accent)` |
|
|
27
27
|
*/
|
|
28
28
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
29
29
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -3,8 +3,9 @@ import ToolbarIconButton from './cmp.toolbar-icon-button.svelte';
|
|
|
3
3
|
import { ToolbarViewControlsLocalization } from './toolbar-view-controls-localization';
|
|
4
4
|
import IconAppsList from '@fluentui/svg-icons/icons/apps_list_20_regular.svg?raw';
|
|
5
5
|
import IconGrid from '@fluentui/svg-icons/icons/grid_20_regular.svg?raw';
|
|
6
|
+
import IconCard from '@fluentui/svg-icons/icons/square_20_regular.svg?raw';
|
|
6
7
|
import { untrack } from 'svelte';
|
|
7
|
-
const { view, size = 'sm', viewStorageKey, prepend, on } = $props();
|
|
8
|
+
const { view, size = 'sm', showCard = false, viewStorageKey, prepend, on } = $props();
|
|
8
9
|
const localization = new ToolbarViewControlsLocalization();
|
|
9
10
|
let storage = null;
|
|
10
11
|
$effect(() => untrack(() => {
|
|
@@ -13,7 +14,7 @@ $effect(() => untrack(() => {
|
|
|
13
14
|
}
|
|
14
15
|
storage = LocalStorageItem.of(viewStorageKey);
|
|
15
16
|
const saved = storage.get();
|
|
16
|
-
if (saved === 'list' || saved === 'grid') {
|
|
17
|
+
if (saved === 'list' || saved === 'grid' || (saved === 'card' && showCard)) {
|
|
17
18
|
on?.viewChange?.(saved);
|
|
18
19
|
}
|
|
19
20
|
}));
|
|
@@ -29,22 +30,26 @@ const setView = (next) => {
|
|
|
29
30
|
{/if}
|
|
30
31
|
<ToolbarIconButton icon={IconAppsList} size={size} active={view === 'list'} aria-label={localization.listView} on={{ click: () => setView('list') }} />
|
|
31
32
|
<ToolbarIconButton icon={IconGrid} size={size} active={view === 'grid'} aria-label={localization.gridView} on={{ click: () => setView('grid') }} />
|
|
33
|
+
{#if showCard}
|
|
34
|
+
<ToolbarIconButton icon={IconCard} size={size} active={view === 'card'} aria-label={localization.cardView} on={{ click: () => setView('card') }} />
|
|
35
|
+
{/if}
|
|
32
36
|
</div>
|
|
33
37
|
|
|
34
38
|
<!--
|
|
35
39
|
@component
|
|
36
40
|
A toolbar view switcher: a `list` / `grid` toggle built on the shared `ToolbarIconButton` (flat, 28px at
|
|
37
|
-
`sm` / 32px at `md`, 20px glyph)
|
|
38
|
-
leading control — e.g. `ToolbarSortSelect` — through the
|
|
41
|
+
`sm` / 32px at `md`, 20px glyph), with an opt-in `card` button via `showCard`. Pass `viewStorageKey` to
|
|
42
|
+
persist the view across reloads, and compose a leading control — e.g. `ToolbarSortSelect` — through the
|
|
43
|
+
`prepend` snippet.
|
|
39
44
|
|
|
40
45
|
### CSS Custom Properties
|
|
41
46
|
| Property | Description | Default |
|
|
42
47
|
|---|---|---|
|
|
43
|
-
| `--sc-kit--toolbar-view-controls--gap` | Gap between the controls | `var(--sc-kit--space--
|
|
48
|
+
| `--sc-kit--toolbar-view-controls--gap` | Gap between the controls | `var(--sc-kit--space--2)` |
|
|
44
49
|
-->
|
|
45
50
|
|
|
46
51
|
<style>.toolbar-view-controls {
|
|
47
|
-
--_tvc--gap: var(--sc-kit--toolbar-view-controls--gap, var(--sc-kit--space--
|
|
52
|
+
--_tvc--gap: var(--sc-kit--toolbar-view-controls--gap, var(--sc-kit--space--2));
|
|
48
53
|
display: inline-flex;
|
|
49
54
|
align-items: center;
|
|
50
55
|
gap: var(--_tvc--gap);
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
type ViewMode = 'list' | 'grid';
|
|
2
|
+
type ViewMode = 'list' | 'grid' | 'card';
|
|
3
3
|
type Props = {
|
|
4
4
|
view: ViewMode;
|
|
5
5
|
/** Button size preset — sm = 28px, md = 32px. @default 'sm' */
|
|
6
6
|
size?: 'sm' | 'md';
|
|
7
|
+
/** Reveal the `card` view button alongside list / grid. @default false */
|
|
8
|
+
showCard?: boolean;
|
|
7
9
|
/** Persist the view mode under this localStorage key. */
|
|
8
10
|
viewStorageKey?: string;
|
|
9
11
|
/** Leading content before the view toggle — e.g. a composed `ToolbarSortSelect`. */
|
|
@@ -14,13 +16,14 @@ type Props = {
|
|
|
14
16
|
};
|
|
15
17
|
/**
|
|
16
18
|
* A toolbar view switcher: a `list` / `grid` toggle built on the shared `ToolbarIconButton` (flat, 28px at
|
|
17
|
-
* `sm` / 32px at `md`, 20px glyph)
|
|
18
|
-
* leading control — e.g. `ToolbarSortSelect` — through the
|
|
19
|
+
* `sm` / 32px at `md`, 20px glyph), with an opt-in `card` button via `showCard`. Pass `viewStorageKey` to
|
|
20
|
+
* persist the view across reloads, and compose a leading control — e.g. `ToolbarSortSelect` — through the
|
|
21
|
+
* `prepend` snippet.
|
|
19
22
|
*
|
|
20
23
|
* ### CSS Custom Properties
|
|
21
24
|
* | Property | Description | Default |
|
|
22
25
|
* |---|---|---|
|
|
23
|
-
* | `--sc-kit--toolbar-view-controls--gap` | Gap between the controls | `var(--sc-kit--space--
|
|
26
|
+
* | `--sc-kit--toolbar-view-controls--gap` | Gap between the controls | `var(--sc-kit--space--2)` |
|
|
24
27
|
*/
|
|
25
28
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
26
29
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { AppLocale } from '../../core/locale';
|
|
2
2
|
const loc = {
|
|
3
|
-
orderBy: { en: 'Order by', no: 'Sorter etter' }
|
|
3
|
+
orderBy: { en: 'Order by', no: 'Sorter etter' },
|
|
4
|
+
sorting: { en: 'Sorting', no: 'Sortering' }
|
|
4
5
|
};
|
|
5
6
|
export class ToolbarSortSelectLocalization {
|
|
6
7
|
get orderBy() {
|
|
7
8
|
return loc.orderBy[AppLocale.current];
|
|
8
9
|
}
|
|
10
|
+
get sorting() {
|
|
11
|
+
return loc.sorting[AppLocale.current];
|
|
12
|
+
}
|
|
9
13
|
}
|
|
@@ -2,7 +2,8 @@ import { AppLocale } from '../../core/locale';
|
|
|
2
2
|
const loc = {
|
|
3
3
|
label: { en: 'View options', no: 'Visningsalternativer' },
|
|
4
4
|
listView: { en: 'List view', no: 'Listevisning' },
|
|
5
|
-
gridView: { en: 'Grid view', no: 'Rutenettvisning' }
|
|
5
|
+
gridView: { en: 'Grid view', no: 'Rutenettvisning' },
|
|
6
|
+
cardView: { en: 'Card view', no: 'Kortvisning' }
|
|
6
7
|
};
|
|
7
8
|
export class ToolbarViewControlsLocalization {
|
|
8
9
|
get label() {
|
|
@@ -14,4 +15,7 @@ export class ToolbarViewControlsLocalization {
|
|
|
14
15
|
get gridView() {
|
|
15
16
|
return loc.gridView[AppLocale.current];
|
|
16
17
|
}
|
|
18
|
+
get cardView() {
|
|
19
|
+
return loc.cardView[AppLocale.current];
|
|
20
|
+
}
|
|
17
21
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<script lang="ts">import { Tooltip } from '../tooltip';
|
|
2
|
+
import { ProgressBarLocalization } from './progress-bar-localization';
|
|
3
|
+
import { PROGRESS_BAR_TONES } from './types';
|
|
4
|
+
const { stage, stages, variant = 'bar', showLabel = true } = $props();
|
|
5
|
+
const localization = new ProgressBarLocalization();
|
|
6
|
+
const currentStage = $derived(stages[Math.max(0, Math.min(stage, stages.length - 1))]);
|
|
7
|
+
const currentLabel = $derived(currentStage?.label ?? '');
|
|
8
|
+
const tooltipLabel = $derived(!showLabel ? currentLabel : '');
|
|
9
|
+
const segmentColor = (s) => {
|
|
10
|
+
const value = s.color ?? 'gray';
|
|
11
|
+
return PROGRESS_BAR_TONES.includes(value) ? `var(--sc-kit--tone--${value}--fg)` : value;
|
|
12
|
+
};
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div class="progress-bar" class:progress-bar--pips={variant === 'pips'}>
|
|
16
|
+
{#if tooltipLabel}
|
|
17
|
+
<Tooltip text={tooltipLabel}>
|
|
18
|
+
{@render track()}
|
|
19
|
+
</Tooltip>
|
|
20
|
+
{:else}
|
|
21
|
+
{@render track()}
|
|
22
|
+
{/if}
|
|
23
|
+
{#if showLabel && currentLabel}
|
|
24
|
+
<span class="progress-bar__label">{currentLabel}</span>
|
|
25
|
+
{/if}
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
{#snippet track()}
|
|
29
|
+
<div
|
|
30
|
+
class="progress-bar__track"
|
|
31
|
+
role="progressbar"
|
|
32
|
+
aria-valuemin={1}
|
|
33
|
+
aria-valuemax={stages.length}
|
|
34
|
+
aria-valuenow={stage + 1}
|
|
35
|
+
aria-valuetext={currentLabel || undefined}
|
|
36
|
+
aria-label={localization.label}>
|
|
37
|
+
{#each stages as s, i (i)}
|
|
38
|
+
<span class="progress-bar__segment" class:progress-bar__segment--filled={i <= stage} style:--_--pb--segment-color={segmentColor(s)}></span>
|
|
39
|
+
{/each}
|
|
40
|
+
</div>
|
|
41
|
+
{/snippet}
|
|
42
|
+
|
|
43
|
+
<!--
|
|
44
|
+
@component
|
|
45
|
+
Multi-stage workflow progress indicator. Pass `stages` as an array of `{ color, label? }`
|
|
46
|
+
descriptors — the bar renders one segment per stage; segments `0..stage` (inclusive) are filled,
|
|
47
|
+
the rest use the empty-segment color. Each stage's `color` is either a named tone from the shared
|
|
48
|
+
palette (same schemes as `Badge`, e.g. `'green'`) or a raw CSS color / `var(--sc-kit--*)`. Useful
|
|
49
|
+
for content-lifecycle indicators (Ideas → Draft → Review → Scheduled → Published) in cards, table
|
|
50
|
+
cells, or post pages. `variant="pips"` renders compact fixed-size ticks (left-aligned) instead of
|
|
51
|
+
full-width segments — for dense table cells. `showLabel={false}` drops the inline current-stage
|
|
52
|
+
label (e.g. in a compact table cell) and surfaces it in a hover tooltip instead.
|
|
53
|
+
|
|
54
|
+
### CSS Custom Properties
|
|
55
|
+
| Property | Description | Default |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `--sc-kit--progress-bar--segment--height` | Segment height | `bar` 4px / `pips` 12px |
|
|
58
|
+
| `--sc-kit--progress-bar--segment--width` | Segment width | `bar` auto (stretches) / `pips` 6px |
|
|
59
|
+
| `--sc-kit--progress-bar--segment--gap` | Gap between segments | `bar` 2px / `pips` 4px |
|
|
60
|
+
| `--sc-kit--progress-bar--segment--border-radius` | Segment corner radius | `bar` 1px / `pips` 2px |
|
|
61
|
+
| `--sc-kit--progress-bar--segment--background--empty` | Empty segment color | `var(--sc-kit--color--bg--active)` |
|
|
62
|
+
| `--sc-kit--progress-bar--track--padding-block` | Vertical padding around the bar (enlarges the hover/click target) | `5px` |
|
|
63
|
+
-->
|
|
64
|
+
|
|
65
|
+
<style>.progress-bar {
|
|
66
|
+
--_pb--seg-height: var(--sc-kit--progress-bar--segment--height, var(--_pb--seg-height-default, 0.25rem));
|
|
67
|
+
--_pb--seg-gap: var(--sc-kit--progress-bar--segment--gap, var(--_pb--seg-gap-default, 0.125rem));
|
|
68
|
+
--_pb--seg-width: var(--sc-kit--progress-bar--segment--width, var(--_pb--seg-width-default, auto));
|
|
69
|
+
--_pb--seg-radius: var(--sc-kit--progress-bar--segment--border-radius, var(--_pb--seg-radius-default, 0.0625rem));
|
|
70
|
+
--_pb--seg-empty: var(--sc-kit--progress-bar--segment--background--empty, var(--sc-kit--color--bg--active));
|
|
71
|
+
--_pb--track-padding-block: var(--sc-kit--progress-bar--track--padding-block, 0.3125rem);
|
|
72
|
+
--_pb--seg-flex: 1;
|
|
73
|
+
--_pb--track-width: 100%;
|
|
74
|
+
display: flex;
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
gap: 0.125rem;
|
|
77
|
+
width: 100%;
|
|
78
|
+
min-width: 0;
|
|
79
|
+
}
|
|
80
|
+
.progress-bar--pips {
|
|
81
|
+
--_pb--seg-height-default: 0.75rem;
|
|
82
|
+
--_pb--seg-gap-default: 0.25rem;
|
|
83
|
+
--_pb--seg-width-default: 0.375rem;
|
|
84
|
+
--_pb--seg-radius-default: 0.125rem;
|
|
85
|
+
--_pb--seg-flex: 0 0 auto;
|
|
86
|
+
--_pb--track-width: auto;
|
|
87
|
+
align-items: flex-start;
|
|
88
|
+
}
|
|
89
|
+
.progress-bar__track {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
gap: var(--_pb--seg-gap);
|
|
93
|
+
width: var(--_pb--track-width);
|
|
94
|
+
padding-block: var(--_pb--track-padding-block);
|
|
95
|
+
}
|
|
96
|
+
.progress-bar__segment {
|
|
97
|
+
--_pb--seg-color: var(--_--pb--segment-color);
|
|
98
|
+
flex: var(--_pb--seg-flex);
|
|
99
|
+
width: var(--_pb--seg-width);
|
|
100
|
+
height: var(--_pb--seg-height);
|
|
101
|
+
background: var(--_pb--seg-empty);
|
|
102
|
+
border-radius: var(--_pb--seg-radius);
|
|
103
|
+
}
|
|
104
|
+
.progress-bar__segment--filled {
|
|
105
|
+
background: var(--_pb--seg-color);
|
|
106
|
+
}
|
|
107
|
+
.progress-bar__label {
|
|
108
|
+
font-size: 0.625rem;
|
|
109
|
+
color: var(--sc-kit--color--text--secondary);
|
|
110
|
+
line-height: var(--sc-kit--leading--tight);
|
|
111
|
+
}</style>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ProgressBarStage } from './types';
|
|
2
|
+
type Props = {
|
|
3
|
+
/** Current stage index, 0-based. Stages 0..stage (inclusive) are filled. */
|
|
4
|
+
stage: number;
|
|
5
|
+
/**
|
|
6
|
+
* Stage descriptors — at minimum `{ color }` per stage (consumer provides the CSS color).
|
|
7
|
+
* Length determines the total segment count.
|
|
8
|
+
*/
|
|
9
|
+
stages: ProgressBarStage[];
|
|
10
|
+
/** Segment shape — `bar` = full-width stretched segments, `pips` = compact fixed-size ticks (e.g. a table cell). @default 'bar' */
|
|
11
|
+
variant?: 'bar' | 'pips';
|
|
12
|
+
/** Show the current stage's label below the bar. When `false`, the label surfaces in a tooltip on hover instead. @default true */
|
|
13
|
+
showLabel?: boolean;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Multi-stage workflow progress indicator. Pass `stages` as an array of `{ color, label? }`
|
|
17
|
+
* descriptors — the bar renders one segment per stage; segments `0..stage` (inclusive) are filled,
|
|
18
|
+
* the rest use the empty-segment color. Each stage's `color` is either a named tone from the shared
|
|
19
|
+
* palette (same schemes as `Badge`, e.g. `'green'`) or a raw CSS color / `var(--sc-kit--*)`. Useful
|
|
20
|
+
* for content-lifecycle indicators (Ideas → Draft → Review → Scheduled → Published) in cards, table
|
|
21
|
+
* cells, or post pages. `variant="pips"` renders compact fixed-size ticks (left-aligned) instead of
|
|
22
|
+
* full-width segments — for dense table cells. `showLabel={false}` drops the inline current-stage
|
|
23
|
+
* label (e.g. in a compact table cell) and surfaces it in a hover tooltip instead.
|
|
24
|
+
*
|
|
25
|
+
* ### CSS Custom Properties
|
|
26
|
+
* | Property | Description | Default |
|
|
27
|
+
* |---|---|---|
|
|
28
|
+
* | `--sc-kit--progress-bar--segment--height` | Segment height | `bar` 4px / `pips` 12px |
|
|
29
|
+
* | `--sc-kit--progress-bar--segment--width` | Segment width | `bar` auto (stretches) / `pips` 6px |
|
|
30
|
+
* | `--sc-kit--progress-bar--segment--gap` | Gap between segments | `bar` 2px / `pips` 4px |
|
|
31
|
+
* | `--sc-kit--progress-bar--segment--border-radius` | Segment corner radius | `bar` 1px / `pips` 2px |
|
|
32
|
+
* | `--sc-kit--progress-bar--segment--background--empty` | Empty segment color | `var(--sc-kit--color--bg--active)` |
|
|
33
|
+
* | `--sc-kit--progress-bar--track--padding-block` | Vertical padding around the bar (enlarges the hover/click target) | `5px` |
|
|
34
|
+
*/
|
|
35
|
+
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
36
|
+
type Cmp = ReturnType<typeof Cmp>;
|
|
37
|
+
export default Cmp;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as ProgressBar } from './cmp.progress-bar.svelte';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const PROGRESS_BAR_TONES: readonly ["gray", "blue", "green", "red", "orange", "teal"];
|
|
2
|
+
export type ProgressBarTone = (typeof PROGRESS_BAR_TONES)[number];
|
|
3
|
+
export type ProgressBarStage = {
|
|
4
|
+
/** A named tone from the shared palette (→ `--sc-kit--tone--<tone>--fg`) or any raw CSS color / `var(--sc-kit--*)`. @default 'gray' */
|
|
5
|
+
color?: ProgressBarTone | (string & {});
|
|
6
|
+
label?: string;
|
|
7
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const PROGRESS_BAR_TONES = ['gray', 'blue', 'green', 'red', 'orange', 'teal'];
|
|
@@ -6,7 +6,7 @@ const variant = $derived(column.variantFactory ? column.variantFactory(item) : '
|
|
|
6
6
|
|
|
7
7
|
{#if getValueForColumn(column, item) !== null}
|
|
8
8
|
<div class="table-badge-cell" class:table-badge-cell--centered={centered}>
|
|
9
|
-
<Badge variant={variant} fullWidth={column.fullWidth}>{getValueForColumn(column, item)}</Badge>
|
|
9
|
+
<Badge variant={variant} shape={column.shape ?? 'pill'} fullWidth={column.fullWidth}>{getValueForColumn(column, item)}</Badge>
|
|
10
10
|
</div>
|
|
11
11
|
{/if}
|
|
12
12
|
|
|
@@ -5,7 +5,6 @@ import { default as TableBadgeCell } from './table-badge-cell.svelte';
|
|
|
5
5
|
import { default as TableButtonCell } from './table-button-cell.svelte';
|
|
6
6
|
import { default as TableByCell } from './table-by-cell.svelte';
|
|
7
7
|
import { default as TableCheckboxCell } from './table-checkbox-cell.svelte';
|
|
8
|
-
import { default as TableCustomCell } from './table-custom-cell.svelte';
|
|
9
8
|
import { default as TableIconCell } from './table-icon-cell.svelte';
|
|
10
9
|
import { default as TableImageCell } from './table-image-cell.svelte';
|
|
11
10
|
import { default as TableMoveRowCell } from './table-move-row-cell.svelte';
|
|
@@ -52,8 +51,6 @@ const changeItemPosition = (target, positionChange) => {
|
|
|
52
51
|
<TableByCell column={def} item={item} />
|
|
53
52
|
{:else if def.type === 'checkbox'}
|
|
54
53
|
<TableCheckboxCell item={item} selection={model.selection} />
|
|
55
|
-
{:else if def.type === 'custom'}
|
|
56
|
-
<TableCustomCell column={def} item={item} />
|
|
57
54
|
{:else if def.type === 'icon'}
|
|
58
55
|
<TableIconCell column={def} item={item} centered={column.centered} />
|
|
59
56
|
{:else if def.type === 'image'}
|
|
@@ -21,6 +21,14 @@ const getValueForColumn = (column, item) => (column.valueFactory ? column.valueF
|
|
|
21
21
|
</div>
|
|
22
22
|
</ProportionalContainer>
|
|
23
23
|
</div>
|
|
24
|
+
{:else if column.format === 'vertical-cover'}
|
|
25
|
+
<div class="table-image-cell__image table-image-cell__image--vertical-cover">
|
|
26
|
+
<Image src={getValueForColumn(column, item)} />
|
|
27
|
+
</div>
|
|
28
|
+
{:else if column.format === 'horizontal-cover'}
|
|
29
|
+
<div class="table-image-cell__image table-image-cell__image--horizontal-cover">
|
|
30
|
+
<Image src={getValueForColumn(column, item)} />
|
|
31
|
+
</div>
|
|
24
32
|
{/if}
|
|
25
33
|
</div>
|
|
26
34
|
|
|
@@ -35,6 +43,7 @@ const getValueForColumn = (column, item) => (column.valueFactory ? column.valueF
|
|
|
35
43
|
justify-content: center;
|
|
36
44
|
}
|
|
37
45
|
.table-image-cell__image {
|
|
46
|
+
--_table-image-cell--cover-height: var(--_table-image-cell--image--size, 2.5em);
|
|
38
47
|
display: flex;
|
|
39
48
|
justify-content: center;
|
|
40
49
|
align-items: center;
|
|
@@ -51,10 +60,18 @@ const getValueForColumn = (column, item) => (column.valueFactory ? column.valueF
|
|
|
51
60
|
}
|
|
52
61
|
.table-image-cell__image--contain {
|
|
53
62
|
--sc-kit--image--object-fit: contain;
|
|
54
|
-
height:
|
|
63
|
+
height: var(--_table-image-cell--cover-height);
|
|
55
64
|
}
|
|
56
65
|
.table-image-cell__image--cover {
|
|
57
|
-
height:
|
|
66
|
+
height: var(--_table-image-cell--cover-height);
|
|
67
|
+
}
|
|
68
|
+
.table-image-cell__image--vertical-cover {
|
|
69
|
+
height: var(--_table-image-cell--cover-height);
|
|
70
|
+
width: calc(var(--_table-image-cell--cover-height) * 9 / 16);
|
|
71
|
+
}
|
|
72
|
+
.table-image-cell__image--horizontal-cover {
|
|
73
|
+
height: var(--_table-image-cell--cover-height);
|
|
74
|
+
width: calc(var(--_table-image-cell--cover-height) * 16 / 9);
|
|
58
75
|
}
|
|
59
76
|
.table-image-cell__cover-image-placer {
|
|
60
77
|
width: 100%;
|
package/dist/ui/table/types.d.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { Repository } from '../../core/repository';
|
|
2
|
-
import type { BadgeVariant } from '../badge';
|
|
2
|
+
import type { BadgeShape, BadgeVariant } from '../badge';
|
|
3
3
|
import type { ButtonSize, ButtonVariant } from '../button';
|
|
4
|
-
import { DynamicComponentModel } from '../dynamic-component';
|
|
5
4
|
import type { IconProp } from '../icon';
|
|
6
5
|
import type { Snippet } from 'svelte';
|
|
7
6
|
export type WithId = {
|
|
8
7
|
id: string;
|
|
9
8
|
};
|
|
10
9
|
export type IAnyTableColumn<T> = IOneOfTableColumn<T>;
|
|
11
|
-
export type IOneOfTableColumn<T> = ITableBadgeColumn<T> | ITableButtonColumn<T> | ITableByColumn<T> | ITableCheckboxColumn |
|
|
12
|
-
export type TableColumnType = 'actions' | 'badge' | 'button' | 'by' | 'checkbox' | '
|
|
10
|
+
export type IOneOfTableColumn<T> = ITableBadgeColumn<T> | ITableButtonColumn<T> | ITableByColumn<T> | ITableCheckboxColumn | ITableIconColumn<T> | ITableImageColumn<T> | ITableMoveRowColumn | ITableSnippetColumn<T> | ITableTextColumn<T>;
|
|
11
|
+
export type TableColumnType = 'actions' | 'badge' | 'button' | 'by' | 'checkbox' | 'icon' | 'image' | 'move-row' | 'snippet' | 'text';
|
|
13
12
|
interface ITableColumnBase {
|
|
14
13
|
type: TableColumnType;
|
|
15
14
|
fixedCssWidth?: string;
|
|
@@ -37,6 +36,8 @@ export interface ITableBadgeColumn<T> extends ITableColumn<T> {
|
|
|
37
36
|
valueFactory?: ((item: T) => string) | null;
|
|
38
37
|
/** Stretch the badge to fill the column width. @default false */
|
|
39
38
|
fullWidth?: boolean;
|
|
39
|
+
/** Corner style of the rendered badge. @default 'pill' */
|
|
40
|
+
shape?: BadgeShape;
|
|
40
41
|
}
|
|
41
42
|
export interface ITableByColumn<T> extends ITableColumn<T> {
|
|
42
43
|
type: 'by';
|
|
@@ -68,10 +69,6 @@ export interface ITableButtonColumn<T> extends ITableColumn<T> {
|
|
|
68
69
|
export interface ITableCheckboxColumn extends ITableColumnBase {
|
|
69
70
|
type: 'checkbox';
|
|
70
71
|
}
|
|
71
|
-
export interface ITableCustomColumn<T> extends ITableColumn<T> {
|
|
72
|
-
type: 'custom';
|
|
73
|
-
componentFactory: (item: T) => DynamicComponentModel;
|
|
74
|
-
}
|
|
75
72
|
export interface ITableIconColumn<T> extends ITableColumn<T> {
|
|
76
73
|
type: 'icon';
|
|
77
74
|
iconFactory?: ((item: T) => IconProp) | null;
|
|
@@ -101,7 +98,7 @@ export interface ITableTextColumn<T> extends ITableColumn<T> {
|
|
|
101
98
|
valueFactory?: ((item: T) => string) | null;
|
|
102
99
|
}
|
|
103
100
|
export type TableTextColumnFormat = 'text' | 'html' | 'money' | 'date' | 'date-time';
|
|
104
|
-
export type TableImageColumnFormat = 'circle' | 'square-contain' | 'square-cover';
|
|
101
|
+
export type TableImageColumnFormat = 'circle' | 'square-contain' | 'square-cover' | 'vertical-cover' | 'horizontal-cover';
|
|
105
102
|
export type TableItemAction<T> = {
|
|
106
103
|
title: string;
|
|
107
104
|
icon?: IconProp;
|
package/dist/ui/table/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamscloud/kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"author": "StreamsCloud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -335,6 +335,10 @@
|
|
|
335
335
|
"types": "./dist/ui/progress/index.d.ts",
|
|
336
336
|
"svelte": "./dist/ui/progress/index.js"
|
|
337
337
|
},
|
|
338
|
+
"./ui/progress-bar": {
|
|
339
|
+
"types": "./dist/ui/progress-bar/index.d.ts",
|
|
340
|
+
"svelte": "./dist/ui/progress-bar/index.js"
|
|
341
|
+
},
|
|
338
342
|
"./ui/proportional-container": {
|
|
339
343
|
"types": "./dist/ui/proportional-container/index.d.ts",
|
|
340
344
|
"svelte": "./dist/ui/proportional-container/index.js"
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { ITableCustomColumn } from '../types';
|
|
2
|
-
declare function $$render<T extends {
|
|
3
|
-
id: string;
|
|
4
|
-
}>(): {
|
|
5
|
-
props: {
|
|
6
|
-
item: T;
|
|
7
|
-
column: ITableCustomColumn<T>;
|
|
8
|
-
};
|
|
9
|
-
exports: {};
|
|
10
|
-
bindings: "";
|
|
11
|
-
slots: {};
|
|
12
|
-
events: {};
|
|
13
|
-
};
|
|
14
|
-
declare class __sveltets_Render<T extends {
|
|
15
|
-
id: string;
|
|
16
|
-
}> {
|
|
17
|
-
props(): ReturnType<typeof $$render<T>>['props'];
|
|
18
|
-
events(): ReturnType<typeof $$render<T>>['events'];
|
|
19
|
-
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
20
|
-
bindings(): "";
|
|
21
|
-
exports(): {};
|
|
22
|
-
}
|
|
23
|
-
interface $$IsomorphicComponent {
|
|
24
|
-
new <T extends {
|
|
25
|
-
id: string;
|
|
26
|
-
}>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
27
|
-
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
28
|
-
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
29
|
-
<T extends {
|
|
30
|
-
id: string;
|
|
31
|
-
}>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
32
|
-
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
33
|
-
}
|
|
34
|
-
declare const TableCustomCell: $$IsomorphicComponent;
|
|
35
|
-
type TableCustomCell<T extends {
|
|
36
|
-
id: string;
|
|
37
|
-
}> = InstanceType<typeof TableCustomCell<T>>;
|
|
38
|
-
export default TableCustomCell;
|