@streamscloud/kit 0.75.0 → 0.76.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/core/i18n/resolve-plural-form.js +2 -1
- package/dist/core/utils/dom-helper.d.ts +2 -1
- package/dist/core/utils/dom-helper.js +4 -2
- package/dist/ui/color-picker/cmp.color-picker.svelte +24 -29
- package/dist/ui/color-picker/cmp.color-picker.svelte.d.ts +1 -14
- package/dist/ui/cropper/image-editor-dialog/cmp.image-editor-dialog.svelte +13 -3
- package/dist/ui/dialog/cmp.dialog-button.svelte +2 -2
- package/dist/ui/dialog/cmp.dialog-button.svelte.d.ts +3 -1
- package/dist/ui/dialog/cmp.dialog-cancel-button.svelte +2 -2
- package/dist/ui/dialog/cmp.dialog-cancel-button.svelte.d.ts +3 -0
- package/dist/ui/dialog/cmp.dialog.svelte +5 -1
- package/dist/ui/dialog/cmp.dialog.svelte.d.ts +2 -0
- package/dist/ui/popover/validate-trigger.js +2 -1
- package/package.json +3 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DEV } from 'esm-env';
|
|
1
2
|
/**
|
|
2
3
|
* Picks the plural form matching `count` for `locale`.
|
|
3
4
|
*
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
*/
|
|
18
19
|
export const resolvePluralForm = ({ count, candidates, locale }) => {
|
|
19
20
|
const { index, categoriesLength } = indexerFor(locale);
|
|
20
|
-
if (
|
|
21
|
+
if (DEV && candidates.length !== categoriesLength) {
|
|
21
22
|
throw new Error(`resolvePluralForm(): locale "${locale}" needs ${categoriesLength} candidate(s), got ${JSON.stringify(candidates)}.`);
|
|
22
23
|
}
|
|
23
24
|
const template = candidates[index(count)] ?? candidates[candidates.length - 1];
|
|
@@ -2,7 +2,8 @@ export declare class DomHelper {
|
|
|
2
2
|
private static readonly _interactiveSelector;
|
|
3
3
|
/**
|
|
4
4
|
* First interactive descendant of `root`, or `null`. Use to reject interactive content from a
|
|
5
|
-
* container that must stay non-interactive (a `<button>` trigger, a `<label>`).
|
|
5
|
+
* container that must stay non-interactive (a `<button>` trigger, a `<label>`). Anything inside an
|
|
6
|
+
* `inert` subtree is skipped — it takes neither focus nor clicks.
|
|
6
7
|
*/
|
|
7
8
|
static findInteractiveDescendant(root: Element): HTMLElement | null;
|
|
8
9
|
/**
|
|
@@ -2,10 +2,12 @@ export class DomHelper {
|
|
|
2
2
|
static _interactiveSelector = 'button, a[href], input:not([type="hidden"]), select, textarea, [role="button"], [role="link"], [role="menuitem"], [tabindex]:not([tabindex="-1"])';
|
|
3
3
|
/**
|
|
4
4
|
* First interactive descendant of `root`, or `null`. Use to reject interactive content from a
|
|
5
|
-
* container that must stay non-interactive (a `<button>` trigger, a `<label>`).
|
|
5
|
+
* container that must stay non-interactive (a `<button>` trigger, a `<label>`). Anything inside an
|
|
6
|
+
* `inert` subtree is skipped — it takes neither focus nor clicks.
|
|
6
7
|
*/
|
|
7
8
|
static findInteractiveDescendant(root) {
|
|
8
|
-
|
|
9
|
+
const candidates = root.querySelectorAll(DomHelper._interactiveSelector);
|
|
10
|
+
return Array.from(candidates).find((candidate) => !candidate.closest('[inert]')) ?? null;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* True when the target is, or sits inside, interactive content — i.e. something that owns its own
|
|
@@ -35,12 +35,9 @@ const previewBackgroundColor = $derived.by(() => {
|
|
|
35
35
|
});
|
|
36
36
|
const alphaPercent = $derived(displayColor ? `${Math.round(colord(displayColor).alpha() * 100)}%` : '');
|
|
37
37
|
const triggerPlaceholder = $derived(placeholder ?? loc.notSet);
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (clearable) {
|
|
42
|
-
on?.change?.('');
|
|
43
|
-
}
|
|
38
|
+
const clearButtonVisible = $derived(clearable && !disabled && !children && variant === 'fill' && !!value);
|
|
39
|
+
const resetValue = () => {
|
|
40
|
+
on?.change?.('');
|
|
44
41
|
};
|
|
45
42
|
const onColorPickerInput = ({ hex }) => {
|
|
46
43
|
on?.change?.(ColorHelper.normalizeHex(hex));
|
|
@@ -88,10 +85,8 @@ const onColorPickerInput = ({ hex }) => {
|
|
|
88
85
|
<span class="color-picker__chevron" aria-hidden="true">
|
|
89
86
|
<Icon src={IconChevronDown} color={displayColor ? undefined : 'muted'} />
|
|
90
87
|
</span>
|
|
91
|
-
{:else if
|
|
92
|
-
<
|
|
93
|
-
<Icon src={IconDismiss} />
|
|
94
|
-
</button>
|
|
88
|
+
{:else if clearButtonVisible}
|
|
89
|
+
<span class="color-picker__clear-glyph"><Icon src={IconDismiss} /></span>
|
|
95
90
|
{:else}
|
|
96
91
|
<span class="color-picker__chevron" aria-hidden="true">
|
|
97
92
|
<Icon src={IconChevronDown} />
|
|
@@ -111,6 +106,9 @@ const onColorPickerInput = ({ hex }) => {
|
|
|
111
106
|
textInputModes={['hex']} />
|
|
112
107
|
</div>
|
|
113
108
|
</Popover>
|
|
109
|
+
{#if clearButtonVisible}
|
|
110
|
+
<button type="button" class="color-picker__clear" class:color-picker__clear--sm={size === 'sm'} aria-label={loc.clear} onclick={resetValue}></button>
|
|
111
|
+
{/if}
|
|
114
112
|
</div>
|
|
115
113
|
|
|
116
114
|
<!--
|
|
@@ -123,19 +121,6 @@ same height.
|
|
|
123
121
|
When `value` is set, the trigger's background fills with the color and the swatch text auto-flips
|
|
124
122
|
between black and white for contrast.
|
|
125
123
|
|
|
126
|
-
### Props
|
|
127
|
-
| Prop | Type | Default |
|
|
128
|
-
|---|---|---|
|
|
129
|
-
| `value` | `string \| null \| undefined` | required |
|
|
130
|
-
| `variant` | `'fill' \| 'field'` | `'fill'` |
|
|
131
|
-
| `label` | `string` (field variant row label) | — |
|
|
132
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` |
|
|
133
|
-
| `clearable` | `boolean` | `false` |
|
|
134
|
-
| `disabled` | `boolean` | `false` |
|
|
135
|
-
| `defaultColor` | `string \| undefined` | `undefined` |
|
|
136
|
-
| `placeholder` | `string \| undefined` | localized "not set" |
|
|
137
|
-
| `previewIcon` | `string \| Snippet` | color-droplet glyph |
|
|
138
|
-
|
|
139
124
|
### CSS Custom Properties
|
|
140
125
|
| Property | Description | Default |
|
|
141
126
|
|---|---|---|
|
|
@@ -206,19 +191,29 @@ between black and white for contrast.
|
|
|
206
191
|
color: var(--sc-kit--color--text--secondary);
|
|
207
192
|
font-size: var(--sc-kit--font-size--sm);
|
|
208
193
|
}
|
|
209
|
-
.color-picker__chevron, .color-picker__clear {
|
|
194
|
+
.color-picker__chevron, .color-picker__clear-glyph {
|
|
210
195
|
display: inline-flex;
|
|
211
196
|
align-items: center;
|
|
212
197
|
justify-content: center;
|
|
198
|
+
line-height: 0;
|
|
199
|
+
}
|
|
200
|
+
.color-picker__clear {
|
|
201
|
+
position: absolute;
|
|
202
|
+
inset-block: 0;
|
|
203
|
+
inset-inline-end: 0;
|
|
204
|
+
aspect-ratio: 1;
|
|
205
|
+
padding: 0;
|
|
213
206
|
background: transparent;
|
|
214
207
|
border: 0;
|
|
215
|
-
|
|
216
|
-
line-height: 0;
|
|
217
|
-
color: inherit;
|
|
208
|
+
border-radius: var(--sc-kit--field--border-radius--md);
|
|
218
209
|
cursor: pointer;
|
|
219
210
|
}
|
|
220
|
-
.color-
|
|
221
|
-
|
|
211
|
+
.color-picker__clear:focus-visible {
|
|
212
|
+
outline: 2px solid var(--sc-kit--color--border--focus);
|
|
213
|
+
outline-offset: -2px;
|
|
214
|
+
}
|
|
215
|
+
.color-picker__clear--sm {
|
|
216
|
+
border-radius: var(--sc-kit--field--border-radius--sm);
|
|
222
217
|
}
|
|
223
218
|
.color-picker__panel {
|
|
224
219
|
--focus-color: none;
|
|
@@ -13,7 +13,7 @@ type Props = {
|
|
|
13
13
|
clearable?: boolean;
|
|
14
14
|
/** Visual disabled state — popover won't open. */
|
|
15
15
|
disabled?: boolean;
|
|
16
|
-
/** Placeholder shown on the swatch trigger when no value is selected. */
|
|
16
|
+
/** Placeholder shown on the swatch trigger when no value is selected. @default localized "Not set" */
|
|
17
17
|
placeholder?: string;
|
|
18
18
|
on?: {
|
|
19
19
|
change?: (value: string) => void;
|
|
@@ -35,19 +35,6 @@ type Props = {
|
|
|
35
35
|
* When `value` is set, the trigger's background fills with the color and the swatch text auto-flips
|
|
36
36
|
* between black and white for contrast.
|
|
37
37
|
*
|
|
38
|
-
* ### Props
|
|
39
|
-
* | Prop | Type | Default |
|
|
40
|
-
* |---|---|---|
|
|
41
|
-
* | `value` | `string \| null \| undefined` | required |
|
|
42
|
-
* | `variant` | `'fill' \| 'field'` | `'fill'` |
|
|
43
|
-
* | `label` | `string` (field variant row label) | — |
|
|
44
|
-
* | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` |
|
|
45
|
-
* | `clearable` | `boolean` | `false` |
|
|
46
|
-
* | `disabled` | `boolean` | `false` |
|
|
47
|
-
* | `defaultColor` | `string \| undefined` | `undefined` |
|
|
48
|
-
* | `placeholder` | `string \| undefined` | localized "not set" |
|
|
49
|
-
* | `previewIcon` | `string \| Snippet` | color-droplet glyph |
|
|
50
|
-
*
|
|
51
38
|
* ### CSS Custom Properties
|
|
52
39
|
* | Property | Description | Default |
|
|
53
40
|
* |---|---|---|
|
|
@@ -54,8 +54,8 @@ $effect(() => untrack(() => {
|
|
|
54
54
|
{/snippet}
|
|
55
55
|
{#snippet footer()}
|
|
56
56
|
<div class="image-editor-dialog__footer">
|
|
57
|
-
<DialogCancelButton on={{ click: cancel }}>{loc.cancel}</DialogCancelButton>
|
|
58
|
-
<DialogButton on={{ click: save }}>{loc.save}</DialogButton>
|
|
57
|
+
<DialogCancelButton size="sm" on={{ click: cancel }}>{loc.cancel}</DialogCancelButton>
|
|
58
|
+
<DialogButton size="sm" on={{ click: save }}>{loc.save}</DialogButton>
|
|
59
59
|
</div>
|
|
60
60
|
{/snippet}
|
|
61
61
|
</Dialog>
|
|
@@ -63,6 +63,14 @@ $effect(() => untrack(() => {
|
|
|
63
63
|
|
|
64
64
|
<style>.image-editor-dialog {
|
|
65
65
|
--sc-kit--dialog--height: calc(100vh - 2.5rem);
|
|
66
|
+
--sc-kit--dialog--footer--padding-block: var(--sc-kit--space--2);
|
|
67
|
+
--sc-kit--dialog--footer--padding-inline: var(--sc-kit--space--4);
|
|
68
|
+
--sc-kit--dialog--header--padding-block: var(--sc-kit--space--1);
|
|
69
|
+
--sc-kit--dialog--header--padding-inline: var(--sc-kit--space--3);
|
|
70
|
+
--sc-kit--dialog--title--font-size: var(--sc-kit--font-size--sm);
|
|
71
|
+
--sc-kit--dialog--title--line-height: var(--sc-kit--line-height--sm);
|
|
72
|
+
--sc-kit--dialog-close-button--size: 1.5rem;
|
|
73
|
+
--sc-kit--dialog-close-button--icon--size: 1rem;
|
|
66
74
|
display: contents;
|
|
67
75
|
}
|
|
68
76
|
.image-editor-dialog__workspace {
|
|
@@ -70,7 +78,9 @@ $effect(() => untrack(() => {
|
|
|
70
78
|
min-block-size: 0;
|
|
71
79
|
}
|
|
72
80
|
.image-editor-dialog__footer {
|
|
81
|
+
--sc-kit--dialog-cancel-button--min-width: 4.5rem;
|
|
82
|
+
--sc-kit--dialog-button--min-width: 7rem;
|
|
73
83
|
display: flex;
|
|
74
84
|
justify-content: flex-end;
|
|
75
|
-
gap:
|
|
85
|
+
gap: var(--sc-kit--space--4);
|
|
76
86
|
}</style>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script lang="ts">import { default as Button } from '../button/cmp.button.svelte';
|
|
2
|
-
let { type = 'button', disabled = false, loading = false, variant = 'primary', icon, on, children } = $props();
|
|
2
|
+
let { type = 'button', disabled = false, loading = false, variant = 'primary', size = 'md', icon, on, children } = $props();
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<div class="dialog-button">
|
|
6
|
-
<Button type={type} disabled={disabled} loading={loading} variant={variant} icon={icon} on={on}>
|
|
6
|
+
<Button type={type} disabled={disabled} loading={loading} variant={variant} size={size} icon={icon} on={on}>
|
|
7
7
|
{@render children()}
|
|
8
8
|
</Button>
|
|
9
9
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ButtonVariant } from '../button/types';
|
|
1
|
+
import type { ButtonSize, ButtonVariant } from '../button/types';
|
|
2
2
|
import type { IconProp } from '../icon';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
4
|
type Props = {
|
|
@@ -9,6 +9,8 @@ type Props = {
|
|
|
9
9
|
loading?: boolean;
|
|
10
10
|
/** Button color variant @default 'primary' */
|
|
11
11
|
variant?: ButtonVariant;
|
|
12
|
+
/** @default 'md' */
|
|
13
|
+
size?: ButtonSize;
|
|
12
14
|
/** Leading icon — passed through to Button. */
|
|
13
15
|
icon?: IconProp;
|
|
14
16
|
on?: {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script lang="ts">import { default as Button } from '../button/cmp.button.svelte';
|
|
2
|
-
let { disabled = false, on, children } = $props();
|
|
2
|
+
let { disabled = false, size = 'md', on, children } = $props();
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<div class="dialog-cancel-button">
|
|
6
|
-
<Button type="button" disabled={disabled} variant="secondary" on={on}>
|
|
6
|
+
<Button type="button" disabled={disabled} variant="secondary" size={size} on={on}>
|
|
7
7
|
{@render children()}
|
|
8
8
|
</Button>
|
|
9
9
|
</div>
|
|
@@ -58,6 +58,8 @@ A structured dialog panel with header (title + close button), scrollable body, a
|
|
|
58
58
|
| `--sc-kit--dialog--body--padding-inline` | Body-specific horizontal padding | inherits `--padding-inline` |
|
|
59
59
|
| `--sc-kit--dialog--header--padding-block` | Header-specific vertical padding | inherits `--padding-block` |
|
|
60
60
|
| `--sc-kit--dialog--header--padding-inline` | Header-specific horizontal padding | inherits `--padding-inline` |
|
|
61
|
+
| `--sc-kit--dialog--footer--padding-block` | Footer-specific vertical padding | inherits `--padding-block` |
|
|
62
|
+
| `--sc-kit--dialog--footer--padding-inline` | Footer-specific horizontal padding | inherits `--padding-inline` |
|
|
61
63
|
| `--sc-kit--dialog--title--font-size` | Title font size | `1.125rem` (18px) |
|
|
62
64
|
| `--sc-kit--dialog--title--line-height` | Title line height | `1.4` |
|
|
63
65
|
-->
|
|
@@ -78,6 +80,8 @@ A structured dialog panel with header (title + close button), scrollable body, a
|
|
|
78
80
|
--_dialog--body--padding-inline: var(--sc-kit--dialog--body--padding-inline, var(--_dialog--padding-inline));
|
|
79
81
|
--_dialog--header--padding-block: var(--sc-kit--dialog--header--padding-block, var(--_dialog--padding-block));
|
|
80
82
|
--_dialog--header--padding-inline: var(--sc-kit--dialog--header--padding-inline, var(--_dialog--padding-inline));
|
|
83
|
+
--_dialog--footer--padding-block: var(--sc-kit--dialog--footer--padding-block, var(--_dialog--padding-block));
|
|
84
|
+
--_dialog--footer--padding-inline: var(--sc-kit--dialog--footer--padding-inline, var(--_dialog--padding-inline));
|
|
81
85
|
--_dialog--title-font-size: var(--sc-kit--dialog--title--font-size, 1.125rem);
|
|
82
86
|
--_dialog--title-line-height: var(--sc-kit--dialog--title--line-height, 1.4);
|
|
83
87
|
display: flex;
|
|
@@ -155,7 +159,7 @@ A structured dialog panel with header (title + close button), scrollable body, a
|
|
|
155
159
|
align-items: center;
|
|
156
160
|
justify-content: flex-end;
|
|
157
161
|
gap: var(--sc-kit--space--3);
|
|
158
|
-
padding: var(--_dialog--padding-block) var(--_dialog--padding-inline);
|
|
162
|
+
padding: var(--_dialog--footer--padding-block) var(--_dialog--footer--padding-inline);
|
|
159
163
|
border-top: 1px solid var(--_dialog--border-color);
|
|
160
164
|
-webkit-user-drag: none;
|
|
161
165
|
user-select: none;
|
|
@@ -59,6 +59,8 @@ interface $$IsomorphicComponent {
|
|
|
59
59
|
* | `--sc-kit--dialog--body--padding-inline` | Body-specific horizontal padding | inherits `--padding-inline` |
|
|
60
60
|
* | `--sc-kit--dialog--header--padding-block` | Header-specific vertical padding | inherits `--padding-block` |
|
|
61
61
|
* | `--sc-kit--dialog--header--padding-inline` | Header-specific horizontal padding | inherits `--padding-inline` |
|
|
62
|
+
* | `--sc-kit--dialog--footer--padding-block` | Footer-specific vertical padding | inherits `--padding-block` |
|
|
63
|
+
* | `--sc-kit--dialog--footer--padding-inline` | Footer-specific horizontal padding | inherits `--padding-inline` |
|
|
62
64
|
* | `--sc-kit--dialog--title--font-size` | Title font size | `1.125rem` (18px) |
|
|
63
65
|
* | `--sc-kit--dialog--title--line-height` | Title line height | `1.4` |
|
|
64
66
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DomHelper } from '../../core/utils';
|
|
2
|
+
import { DEV } from 'esm-env';
|
|
2
3
|
/**
|
|
3
4
|
* Dev-only guard for the Popover trigger. The trigger renders inside a `<button>`, so its content
|
|
4
5
|
* must be non-interactive (use `Button` with `type="presentational"` for a button-looking trigger).
|
|
@@ -6,7 +7,7 @@ import { DomHelper } from '../../core/utils';
|
|
|
6
7
|
* node and outlines the trigger in red. No-op in production.
|
|
7
8
|
*/
|
|
8
9
|
export const validateTrigger = (node) => {
|
|
9
|
-
if (!
|
|
10
|
+
if (!DEV) {
|
|
10
11
|
return;
|
|
11
12
|
}
|
|
12
13
|
const check = () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamscloud/kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.0",
|
|
4
4
|
"author": "StreamsCloud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -495,6 +495,7 @@
|
|
|
495
495
|
"colord": "^2.9.3",
|
|
496
496
|
"dequal": "^2.0.3",
|
|
497
497
|
"dompurify": "^3.4.5",
|
|
498
|
+
"esm-env": "^1.2.2",
|
|
498
499
|
"fuse.js": "^7.3.0",
|
|
499
500
|
"hugerte": "^1.0.10",
|
|
500
501
|
"mime": "^4.1.0",
|
|
@@ -534,6 +535,7 @@
|
|
|
534
535
|
"eslint-plugin-promise": "^7.3.0",
|
|
535
536
|
"eslint-plugin-svelte": "^3.23.0",
|
|
536
537
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
538
|
+
"esm-env": "^1.2.2",
|
|
537
539
|
"fuse.js": "^7.3.0",
|
|
538
540
|
"globals": "^17.12.0",
|
|
539
541
|
"hugerte": "^1.0.10",
|