@dryui/ui 0.1.3 → 0.1.5
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/accordion/accordion-trigger.svelte +5 -6
- package/dist/alert-dialog/alert-dialog-action.svelte +42 -6
- package/dist/alert-dialog/alert-dialog-cancel.svelte +44 -5
- package/dist/alert-dialog/alert-dialog-footer.svelte +3 -2
- package/dist/aurora/aurora.svelte.d.ts +6 -0
- package/dist/beam/beam.svelte +17 -10
- package/dist/chromatic-aberration/chromatic-aberration.svelte +7 -9
- package/dist/collapsible/collapsible-trigger.svelte +4 -7
- package/dist/color-picker/color-picker-eyedropper.svelte +4 -11
- package/dist/data-grid/data-grid-pagination.svelte +20 -2
- package/dist/data-grid/data-grid-root.svelte +1 -0
- package/dist/date-field/date-field-root.svelte +66 -20
- package/dist/date-field/date-field-segment.svelte +11 -9
- package/dist/date-field/date-field-separator.svelte +9 -1
- package/dist/date-picker/datepicker-calendar.svelte +168 -13
- package/dist/date-picker/datepicker-trigger.svelte +3 -8
- package/dist/date-range-picker/date-range-picker-calendar.svelte +177 -13
- package/dist/date-range-picker/date-range-picker-trigger.svelte +18 -12
- package/dist/dialog/dialog-content.svelte +1 -0
- package/dist/field/field-root.svelte +0 -1
- package/dist/file-select/file-select-clear.svelte +2 -8
- package/dist/file-upload/file-upload-item-delete.svelte +4 -7
- package/dist/flip-card/flip-card-back.svelte +2 -2
- package/dist/flip-card/flip-card-front.svelte +2 -2
- package/dist/flip-card/flip-card-root.svelte +2 -0
- package/dist/float-button/float-button-root.svelte +2 -1
- package/dist/image-comparison/image-comparison.svelte +16 -24
- package/dist/input-group/input-group-action.svelte +5 -0
- package/dist/input-group/input-group-input.svelte +7 -2
- package/dist/input-group/input-group-prefix.svelte +5 -0
- package/dist/input-group/input-group-root.svelte +10 -2
- package/dist/input-group/input-group-select.svelte +5 -0
- package/dist/input-group/input-group-separator.svelte +10 -0
- package/dist/input-group/input-group-suffix.svelte +5 -0
- package/dist/option-swatch-group/option-swatch-group-item.svelte +46 -0
- package/dist/option-swatch-group/option-swatch-group-label.svelte +10 -0
- package/dist/option-swatch-group/option-swatch-group-meta.svelte +10 -0
- package/dist/option-swatch-group/option-swatch-group-root.svelte +0 -79
- package/dist/option-swatch-group/option-swatch-group-swatch.svelte +25 -6
- package/dist/pin-input/pin-input-cell.svelte +4 -1
- package/dist/range-calendar/range-calendar-grid.svelte +219 -181
- package/dist/range-calendar/range-calendar-root.svelte +24 -10
- package/dist/select/select-trigger.svelte +5 -8
- package/dist/system-map/system-map.svelte +120 -674
- package/dist/tags-input/tags-input-input.svelte +3 -0
- package/dist/tags-input/tags-input-root.svelte +4 -13
- package/dist/tags-input/tags-input-tag.svelte +3 -0
- package/dist/themes/dark.css +6 -0
- package/dist/themes/default.css +3 -0
- package/dist/toast/toast-action.svelte +1 -0
- package/dist/toast/toast-close.svelte +4 -0
- package/dist/toast/toast-provider.svelte +5 -26
- package/dist/toast/toast-root.svelte +5 -10
- package/package.json +441 -1182
- package/skills/dryui/SKILL.md +24 -4
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
{...rest}
|
|
27
27
|
>
|
|
28
28
|
{@render children()}
|
|
29
|
+
<svg data-indicator xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
|
|
29
30
|
</button>
|
|
30
31
|
|
|
31
32
|
<style>
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
display: grid;
|
|
34
35
|
grid-template-columns: 1fr 1rem;
|
|
35
36
|
align-items: center;
|
|
37
|
+
gap: var(--dry-space-2);
|
|
36
38
|
padding: var(--dry-space-4);
|
|
37
39
|
background: none;
|
|
38
40
|
border: none;
|
|
@@ -65,17 +67,14 @@
|
|
|
65
67
|
cursor: not-allowed;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
&[data-state='open']
|
|
70
|
+
&[data-state='open'] [data-indicator] {
|
|
69
71
|
transform: rotate(180deg);
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
content: '';
|
|
74
|
+
& [data-indicator] {
|
|
74
75
|
height: 1rem;
|
|
75
76
|
aspect-ratio: 1;
|
|
76
|
-
|
|
77
|
-
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
|
78
|
-
mask-size: contain;
|
|
77
|
+
opacity: 0.5;
|
|
79
78
|
transition: transform var(--dry-duration-fast) var(--dry-ease-default);
|
|
80
79
|
}
|
|
81
80
|
}
|
|
@@ -15,24 +15,60 @@
|
|
|
15
15
|
|
|
16
16
|
<style>
|
|
17
17
|
[data-alert-dialog-action] {
|
|
18
|
+
--dry-btn-accent: var(--dry-color-fill-error);
|
|
19
|
+
--dry-btn-accent-hover: var(--dry-color-fill-error-hover);
|
|
20
|
+
--dry-btn-accent-active: var(--dry-color-fill-error-hover);
|
|
21
|
+
--dry-btn-on-accent: var(--dry-color-on-error);
|
|
22
|
+
--dry-btn-border: transparent;
|
|
23
|
+
|
|
18
24
|
cursor: pointer;
|
|
19
|
-
background: var(--dry-
|
|
20
|
-
color: var(--dry-
|
|
21
|
-
border:
|
|
22
|
-
padding: var(--dry-space-
|
|
25
|
+
background: var(--dry-btn-accent);
|
|
26
|
+
color: var(--dry-btn-on-accent);
|
|
27
|
+
border: 1px solid var(--dry-btn-border);
|
|
28
|
+
padding: var(--dry-space-2_5) var(--dry-space-4);
|
|
23
29
|
border-radius: var(--dry-radius-md);
|
|
30
|
+
box-shadow: var(--dry-shadow-raised);
|
|
31
|
+
font-family: var(--dry-font-sans);
|
|
32
|
+
font-size: var(--dry-type-small-size, var(--dry-text-sm-size));
|
|
24
33
|
font-weight: 500;
|
|
25
|
-
|
|
34
|
+
line-height: 1.25;
|
|
35
|
+
letter-spacing: -0.01em;
|
|
36
|
+
min-height: var(--dry-space-12);
|
|
26
37
|
display: inline-grid;
|
|
38
|
+
grid-auto-flow: column;
|
|
27
39
|
place-items: center;
|
|
40
|
+
gap: var(--dry-space-2);
|
|
41
|
+
text-decoration: none;
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
user-select: none;
|
|
44
|
+
transition:
|
|
45
|
+
background var(--dry-duration-fast) var(--dry-ease-default),
|
|
46
|
+
border-color var(--dry-duration-fast) var(--dry-ease-default),
|
|
47
|
+
box-shadow var(--dry-duration-fast) var(--dry-ease-default),
|
|
48
|
+
color var(--dry-duration-fast) var(--dry-ease-default),
|
|
49
|
+
opacity var(--dry-duration-fast) var(--dry-ease-default);
|
|
28
50
|
}
|
|
29
51
|
|
|
30
52
|
[data-alert-dialog-action]:hover {
|
|
31
|
-
background: var(--dry-
|
|
53
|
+
background: var(--dry-btn-accent-hover);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
[data-alert-dialog-action]:active:not(:disabled) {
|
|
57
|
+
background: var(--dry-btn-accent-active);
|
|
58
|
+
transform: translateY(1px);
|
|
32
59
|
}
|
|
33
60
|
|
|
34
61
|
[data-alert-dialog-action]:focus-visible {
|
|
35
62
|
outline: 2px solid var(--dry-color-focus-ring);
|
|
36
63
|
outline-offset: 2px;
|
|
64
|
+
box-shadow: 0 0 0 1px var(--dry-color-stroke-focus);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
[data-alert-dialog-action]:disabled {
|
|
68
|
+
background: var(--dry-color-fill-disabled);
|
|
69
|
+
color: var(--dry-color-text-disabled);
|
|
70
|
+
border-color: var(--dry-color-stroke-disabled);
|
|
71
|
+
cursor: not-allowed;
|
|
72
|
+
box-shadow: none;
|
|
37
73
|
}
|
|
38
74
|
</style>
|
|
@@ -24,23 +24,62 @@
|
|
|
24
24
|
|
|
25
25
|
<style>
|
|
26
26
|
[data-alert-dialog-cancel] {
|
|
27
|
+
--dry-btn-accent-fg: var(--dry-color-text-brand);
|
|
28
|
+
--dry-btn-accent-stroke: var(--dry-color-stroke-brand);
|
|
29
|
+
|
|
27
30
|
cursor: pointer;
|
|
28
|
-
background:
|
|
29
|
-
border:
|
|
30
|
-
padding: var(--dry-space-
|
|
31
|
-
color: var(--dry-
|
|
31
|
+
background: transparent;
|
|
32
|
+
border: 1px solid var(--dry-btn-accent-stroke);
|
|
33
|
+
padding: var(--dry-space-2_5) var(--dry-space-4);
|
|
34
|
+
color: var(--dry-btn-accent-fg);
|
|
32
35
|
border-radius: var(--dry-radius-sm);
|
|
33
|
-
|
|
36
|
+
box-shadow: var(--dry-shadow-raised);
|
|
37
|
+
font-family: var(--dry-font-sans);
|
|
38
|
+
font-size: var(--dry-type-small-size, var(--dry-text-sm-size));
|
|
39
|
+
font-weight: 500;
|
|
40
|
+
line-height: 1.25;
|
|
41
|
+
letter-spacing: -0.01em;
|
|
42
|
+
min-height: var(--dry-space-12);
|
|
34
43
|
display: inline-grid;
|
|
44
|
+
grid-auto-flow: column;
|
|
35
45
|
place-items: center;
|
|
46
|
+
gap: var(--dry-space-2);
|
|
47
|
+
text-decoration: none;
|
|
48
|
+
white-space: nowrap;
|
|
49
|
+
user-select: none;
|
|
50
|
+
transition:
|
|
51
|
+
background var(--dry-duration-fast) var(--dry-ease-default),
|
|
52
|
+
border-color var(--dry-duration-fast) var(--dry-ease-default),
|
|
53
|
+
box-shadow var(--dry-duration-fast) var(--dry-ease-default),
|
|
54
|
+
color var(--dry-duration-fast) var(--dry-ease-default),
|
|
55
|
+
opacity var(--dry-duration-fast) var(--dry-ease-default);
|
|
36
56
|
}
|
|
37
57
|
|
|
38
58
|
[data-alert-dialog-cancel]:hover {
|
|
59
|
+
background: var(--dry-color-bg-alternate);
|
|
60
|
+
border-color: var(--dry-color-stroke-strong);
|
|
61
|
+
color: var(--dry-color-text-strong);
|
|
62
|
+
box-shadow: var(--dry-shadow-sm);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
[data-alert-dialog-cancel]:active:not(:disabled) {
|
|
66
|
+
background: var(--dry-color-fill);
|
|
67
|
+
border-color: var(--dry-color-stroke-strong);
|
|
39
68
|
color: var(--dry-color-text-strong);
|
|
69
|
+
transform: translateY(1px);
|
|
40
70
|
}
|
|
41
71
|
|
|
42
72
|
[data-alert-dialog-cancel]:focus-visible {
|
|
43
73
|
outline: 2px solid var(--dry-color-focus-ring);
|
|
44
74
|
outline-offset: 2px;
|
|
75
|
+
box-shadow: 0 0 0 1px var(--dry-color-stroke-focus);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
[data-alert-dialog-cancel]:disabled {
|
|
79
|
+
background: var(--dry-color-fill-disabled);
|
|
80
|
+
color: var(--dry-color-text-disabled);
|
|
81
|
+
border-color: var(--dry-color-stroke-disabled);
|
|
82
|
+
cursor: not-allowed;
|
|
83
|
+
box-shadow: none;
|
|
45
84
|
}
|
|
46
85
|
</style>
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { BlendMode } from '@dryui/primitives/aurora';
|
|
3
4
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
5
|
palette?: 'sunrise' | 'ocean' | 'forest' | 'cosmic' | readonly [string, string, string];
|
|
5
6
|
speed?: 'slow' | 'normal' | 'fast' | number;
|
|
7
|
+
intensity?: number;
|
|
8
|
+
waviness?: number;
|
|
9
|
+
colorSpace?: 'srgb' | 'oklch' | 'oklab';
|
|
10
|
+
blendMode?: BlendMode;
|
|
11
|
+
layerOpacity?: number;
|
|
6
12
|
children?: Snippet;
|
|
7
13
|
}
|
|
8
14
|
declare const Aurora: import('svelte').Component<Props, {}, ''>;
|
package/dist/beam/beam.svelte
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
angle = 45,
|
|
20
20
|
speed = 3,
|
|
21
21
|
intensity = 70,
|
|
22
|
-
blendMode
|
|
22
|
+
blendMode,
|
|
23
23
|
children,
|
|
24
24
|
class: className,
|
|
25
25
|
style,
|
|
@@ -31,26 +31,33 @@
|
|
|
31
31
|
const gradientString = $derived(
|
|
32
32
|
`linear-gradient(${angle}deg, transparent 0%, transparent calc(50% - ${width}px), ${color} 50%, transparent calc(50% + ${width}px), transparent 100%)`
|
|
33
33
|
);
|
|
34
|
+
const rootStyle = $derived.by(() => {
|
|
35
|
+
const declarations = [
|
|
36
|
+
style,
|
|
37
|
+
`--dry-beam-speed: ${speedValue}`,
|
|
38
|
+
`--dry-beam-intensity: ${clampedIntensity}`,
|
|
39
|
+
`--dry-beam-width: ${width}px`,
|
|
40
|
+
blendMode ? `--dry-beam-blend: ${blendMode}` : null
|
|
41
|
+
].filter(Boolean);
|
|
42
|
+
return declarations.join('; ');
|
|
43
|
+
});
|
|
44
|
+
const layerStyle = $derived(`background-image: ${gradientString};`);
|
|
34
45
|
|
|
35
46
|
function applyRootStyles(node: HTMLElement) {
|
|
36
47
|
$effect(() => {
|
|
37
|
-
node.style.cssText =
|
|
38
|
-
node.style.setProperty('--dry-beam-speed', speedValue);
|
|
39
|
-
node.style.setProperty('--dry-beam-intensity', clampedIntensity);
|
|
40
|
-
node.style.setProperty('--dry-beam-blend', blendMode);
|
|
41
|
-
node.style.setProperty('--dry-beam-width', `${width}px`);
|
|
48
|
+
node.style.cssText = rootStyle;
|
|
42
49
|
});
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
function applyLayerStyles(node: HTMLElement) {
|
|
46
53
|
$effect(() => {
|
|
47
|
-
node.style.
|
|
54
|
+
node.style.cssText = layerStyle;
|
|
48
55
|
});
|
|
49
56
|
}
|
|
50
57
|
</script>
|
|
51
58
|
|
|
52
|
-
<div data-beam class={className} {...rest}
|
|
53
|
-
<div data-beam-layer
|
|
59
|
+
<div data-beam class={className} {...rest} {@attach applyRootStyles}>
|
|
60
|
+
<div data-beam-layer {@attach applyLayerStyles}></div>
|
|
54
61
|
{#if children}
|
|
55
62
|
{@render children()}
|
|
56
63
|
{/if}
|
|
@@ -69,7 +76,7 @@
|
|
|
69
76
|
pointer-events: none;
|
|
70
77
|
background-size: 300% 300%;
|
|
71
78
|
opacity: calc(var(--dry-beam-intensity, 70) / 100);
|
|
72
|
-
mix-blend-mode: var(--dry-beam-blend,
|
|
79
|
+
mix-blend-mode: var(--dry-beam-blend, var(--dry-beam-default-blend, multiply));
|
|
73
80
|
filter: blur(calc(var(--dry-beam-width, 2px) * 2));
|
|
74
81
|
animation: beam-sweep var(--dry-beam-speed, 3s) ease-in-out infinite;
|
|
75
82
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { createId } from '@dryui/primitives';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
5
|
|
|
@@ -8,24 +9,20 @@
|
|
|
8
9
|
children: Snippet;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
let instanceCounter = 0;
|
|
12
|
-
|
|
13
12
|
let { offset = 3, angle = 0, children, class: className, style, ...rest }: Props = $props();
|
|
14
13
|
|
|
15
|
-
const filterId =
|
|
14
|
+
const filterId = createId('dry-chromatic');
|
|
16
15
|
|
|
17
16
|
const offsetX = $derived(Math.round(offset * Math.cos((angle * Math.PI) / 180)));
|
|
18
17
|
const offsetY = $derived(Math.round(offset * Math.sin((angle * Math.PI) / 180)));
|
|
19
18
|
|
|
20
19
|
function applyFilterStyles(node: HTMLElement) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
node.style.setProperty('filter', `url(#${filterId})`);
|
|
24
|
-
});
|
|
20
|
+
node.style.cssText = style || '';
|
|
21
|
+
node.style.setProperty('filter', `url(#${filterId})`);
|
|
25
22
|
}
|
|
26
23
|
</script>
|
|
27
24
|
|
|
28
|
-
<svg data-chromatic-aberration-svg aria-hidden="true">
|
|
25
|
+
<svg data-chromatic-aberration-svg width="0" height="0" aria-hidden="true">
|
|
29
26
|
<defs>
|
|
30
27
|
<filter id={filterId} color-interpolation-filters="sRGB">
|
|
31
28
|
<feOffset in="SourceGraphic" dx={offsetX} dy={offsetY} result="red" />
|
|
@@ -53,7 +50,7 @@
|
|
|
53
50
|
</filter>
|
|
54
51
|
</defs>
|
|
55
52
|
</svg>
|
|
56
|
-
<div data-chromatic-aberration class={className}
|
|
53
|
+
<div data-chromatic-aberration class={className} {@attach applyFilterStyles} {...rest}>
|
|
57
54
|
{@render children()}
|
|
58
55
|
</div>
|
|
59
56
|
|
|
@@ -62,6 +59,7 @@
|
|
|
62
59
|
position: absolute;
|
|
63
60
|
height: 0;
|
|
64
61
|
overflow: hidden;
|
|
62
|
+
pointer-events: none;
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
[data-chromatic-aberration] {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
{...rest}
|
|
26
26
|
>
|
|
27
27
|
{@render children()}
|
|
28
|
+
<svg data-indicator xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
|
|
28
29
|
</button>
|
|
29
30
|
|
|
30
31
|
<style>
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
display: grid;
|
|
33
34
|
grid-template-columns: 1fr 1rem;
|
|
34
35
|
align-items: center;
|
|
36
|
+
gap: var(--dry-space-2);
|
|
35
37
|
padding: var(--dry-space-3) var(--dry-space-4);
|
|
36
38
|
background: none;
|
|
37
39
|
border: 1px solid var(--dry-color-stroke-weak);
|
|
@@ -41,19 +43,14 @@
|
|
|
41
43
|
cursor: pointer;
|
|
42
44
|
color: var(--dry-color-text-strong);
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
content: '';
|
|
46
|
+
& [data-indicator] {
|
|
46
47
|
height: 1rem;
|
|
47
48
|
aspect-ratio: 1;
|
|
48
|
-
background: currentColor;
|
|
49
|
-
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
|
50
|
-
mask-size: contain;
|
|
51
|
-
mask-repeat: no-repeat;
|
|
52
49
|
opacity: 0.5;
|
|
53
50
|
transition: transform var(--dry-duration-fast) var(--dry-ease-default);
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
&[data-state='open']
|
|
53
|
+
&[data-state='open'] [data-indicator] {
|
|
57
54
|
transform: rotate(180deg);
|
|
58
55
|
}
|
|
59
56
|
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
>
|
|
43
43
|
{#if children}
|
|
44
44
|
{@render children()}
|
|
45
|
+
{:else}
|
|
46
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3l8 8M3 9l8 8m-8-8 1.5 1.5M11 17l-1 4-4 1 1-4"/></svg>
|
|
45
47
|
{/if}
|
|
46
48
|
</button>
|
|
47
49
|
{/if}
|
|
@@ -65,18 +67,9 @@
|
|
|
65
67
|
border-color var(--dry-duration-fast) var(--dry-ease-default);
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
[data-cp-eyedropper]
|
|
69
|
-
|
|
70
|
-
display: inline-block;
|
|
71
|
-
height: 16px;
|
|
70
|
+
[data-cp-eyedropper] svg {
|
|
71
|
+
height: 1rem;
|
|
72
72
|
aspect-ratio: 1;
|
|
73
|
-
background-color: currentColor;
|
|
74
|
-
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3l8 8M3 9l8 8m-8-8 1.5 1.5M11 17l-1 4-4 1 1-4'/%3E%3C/svg%3E");
|
|
75
|
-
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3l8 8M3 9l8 8m-8-8 1.5 1.5M11 17l-1 4-4 1 1-4'/%3E%3C/svg%3E");
|
|
76
|
-
-webkit-mask-repeat: no-repeat;
|
|
77
|
-
mask-repeat: no-repeat;
|
|
78
|
-
-webkit-mask-size: contain;
|
|
79
|
-
mask-size: contain;
|
|
80
73
|
}
|
|
81
74
|
|
|
82
75
|
[data-cp-eyedropper]:hover:not([data-disabled]):not(:disabled) {
|
|
@@ -82,8 +82,10 @@
|
|
|
82
82
|
<style>
|
|
83
83
|
[data-dg-pagination] {
|
|
84
84
|
display: grid;
|
|
85
|
-
grid-template-columns:
|
|
85
|
+
grid-template-columns: minmax(0, 1fr) max-content minmax(0, 1fr);
|
|
86
|
+
grid-template-areas: 'prev info next';
|
|
86
87
|
align-items: center;
|
|
88
|
+
column-gap: var(--dry-data-grid-pagination-gap);
|
|
87
89
|
padding: var(--dry-space-3) var(--dry-data-grid-padding-x);
|
|
88
90
|
border-top: 1px solid var(--dry-data-grid-border);
|
|
89
91
|
font-size: var(--dry-type-small-size, var(--dry-type-small-size));
|
|
@@ -122,18 +124,34 @@
|
|
|
122
124
|
outline-offset: 2px;
|
|
123
125
|
}
|
|
124
126
|
|
|
127
|
+
[data-dg-pagination] button[data-pagination-prev] {
|
|
128
|
+
grid-area: prev;
|
|
129
|
+
justify-self: start;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
[data-dg-pagination] button[data-pagination-next] {
|
|
133
|
+
grid-area: next;
|
|
134
|
+
justify-self: end;
|
|
135
|
+
}
|
|
136
|
+
|
|
125
137
|
[data-dg-pagination] button:disabled {
|
|
126
138
|
opacity: 0.4;
|
|
127
139
|
cursor: not-allowed;
|
|
128
140
|
}
|
|
129
141
|
|
|
130
142
|
[data-dg-pagination] [data-pagination-info] {
|
|
143
|
+
grid-area: info;
|
|
144
|
+
justify-self: center;
|
|
145
|
+
text-align: center;
|
|
131
146
|
font-variant-numeric: tabular-nums;
|
|
132
147
|
}
|
|
133
148
|
|
|
134
149
|
@container (max-width: 400px) {
|
|
135
150
|
[data-dg-pagination] {
|
|
136
|
-
grid-template-columns: 1fr;
|
|
151
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
152
|
+
grid-template-areas:
|
|
153
|
+
'info info'
|
|
154
|
+
'prev next';
|
|
137
155
|
gap: var(--dry-space-2);
|
|
138
156
|
}
|
|
139
157
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
4
5
|
import { setDateFieldCtx, getLocaleFormat, type DateSegmentType } from './context.svelte.js';
|
|
5
6
|
|
|
6
7
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -14,6 +15,12 @@
|
|
|
14
15
|
children: Snippet;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
interface SegmentValues {
|
|
19
|
+
month: number | null;
|
|
20
|
+
day: number | null;
|
|
21
|
+
year: number | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
let {
|
|
18
25
|
value = $bindable<Date | null>(null),
|
|
19
26
|
name,
|
|
@@ -27,37 +34,61 @@
|
|
|
27
34
|
...rest
|
|
28
35
|
}: Props = $props();
|
|
29
36
|
|
|
30
|
-
let
|
|
31
|
-
let day = $state<number | null>(value ? value.getDate() : null);
|
|
32
|
-
let year = $state<number | null>(value ? value.getFullYear() : null);
|
|
37
|
+
let draftValues = $state<SegmentValues | null>(null);
|
|
33
38
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
month = value.getMonth() + 1;
|
|
38
|
-
day = value.getDate();
|
|
39
|
-
year = value.getFullYear();
|
|
39
|
+
function getSegmentValues(date: Date | null): SegmentValues {
|
|
40
|
+
if (!date) {
|
|
41
|
+
return { month: null, day: null, year: null };
|
|
40
42
|
}
|
|
41
|
-
});
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
return {
|
|
45
|
+
month: date.getMonth() + 1,
|
|
46
|
+
day: date.getDate(),
|
|
47
|
+
year: date.getFullYear()
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function commitSegments(nextValues: SegmentValues) {
|
|
52
|
+
if (
|
|
53
|
+
nextValues.month !== null &&
|
|
54
|
+
nextValues.day !== null &&
|
|
55
|
+
nextValues.year !== null &&
|
|
56
|
+
nextValues.year >= 1000
|
|
57
|
+
) {
|
|
58
|
+
const d = new Date(nextValues.year, nextValues.month - 1, nextValues.day);
|
|
59
|
+
if (d.getMonth() === nextValues.month - 1 && d.getDate() === nextValues.day) {
|
|
47
60
|
value = d;
|
|
61
|
+
draftValues = null;
|
|
62
|
+
return;
|
|
48
63
|
}
|
|
49
64
|
}
|
|
65
|
+
|
|
66
|
+
draftValues = nextValues;
|
|
50
67
|
}
|
|
51
68
|
|
|
52
69
|
const localeFormat = $derived(getLocaleFormat(locale));
|
|
70
|
+
const committedValues = $derived(getSegmentValues(value));
|
|
71
|
+
const activeValues = $derived(draftValues ?? committedValues);
|
|
53
72
|
|
|
54
73
|
const segments = $derived(
|
|
55
74
|
localeFormat.order.map((type) => ({
|
|
56
75
|
type,
|
|
57
|
-
value:
|
|
76
|
+
value:
|
|
77
|
+
type === 'month'
|
|
78
|
+
? activeValues.month
|
|
79
|
+
: type === 'day'
|
|
80
|
+
? activeValues.day
|
|
81
|
+
: activeValues.year
|
|
58
82
|
}))
|
|
59
83
|
);
|
|
60
84
|
|
|
85
|
+
function focusPreferredSegment() {
|
|
86
|
+
const targetType =
|
|
87
|
+
segments.find((segment) => segment.value === null)?.type ?? localeFormat.order[0];
|
|
88
|
+
if (!targetType) return;
|
|
89
|
+
segmentElements.get(targetType)?.focus();
|
|
90
|
+
}
|
|
91
|
+
|
|
61
92
|
function serializeDateValue(date: Date | null): string {
|
|
62
93
|
if (!date) return '';
|
|
63
94
|
|
|
@@ -69,7 +100,7 @@
|
|
|
69
100
|
}
|
|
70
101
|
|
|
71
102
|
// Segment element registry for index-based navigation
|
|
72
|
-
const segmentElements = new
|
|
103
|
+
const segmentElements = new SvelteMap<DateSegmentType, HTMLElement>();
|
|
73
104
|
|
|
74
105
|
setDateFieldCtx({
|
|
75
106
|
get value() {
|
|
@@ -97,10 +128,11 @@
|
|
|
97
128
|
return segments;
|
|
98
129
|
},
|
|
99
130
|
updateSegment(type: DateSegmentType, val: number) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
131
|
+
commitSegments({
|
|
132
|
+
month: type === 'month' ? val : activeValues.month,
|
|
133
|
+
day: type === 'day' ? val : activeValues.day,
|
|
134
|
+
year: type === 'year' ? val : activeValues.year
|
|
135
|
+
});
|
|
104
136
|
},
|
|
105
137
|
registerSegment(type: DateSegmentType, el: HTMLElement) {
|
|
106
138
|
segmentElements.set(type, el);
|
|
@@ -119,12 +151,26 @@
|
|
|
119
151
|
}
|
|
120
152
|
}
|
|
121
153
|
});
|
|
154
|
+
|
|
155
|
+
function handleMousedown(event: MouseEvent) {
|
|
156
|
+
if (disabled) return;
|
|
157
|
+
const target = event.target;
|
|
158
|
+
if (!(target instanceof HTMLElement)) return;
|
|
159
|
+
if (target.closest('[data-df-segment]')) return;
|
|
160
|
+
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
focusPreferredSegment();
|
|
163
|
+
}
|
|
122
164
|
</script>
|
|
123
165
|
|
|
124
166
|
<div
|
|
125
167
|
role="group"
|
|
126
168
|
aria-label="Date"
|
|
169
|
+
data-df-wrapper
|
|
170
|
+
data-df-root
|
|
171
|
+
data-size={size}
|
|
127
172
|
data-disabled={disabled || undefined}
|
|
173
|
+
onmousedown={handleMousedown}
|
|
128
174
|
{...rest}
|
|
129
175
|
class={className}
|
|
130
176
|
>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
import { getDateFieldCtx, type DateSegmentType } from './context.svelte.js';
|
|
4
|
-
import { onMount } from 'svelte';
|
|
5
4
|
|
|
6
5
|
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
7
6
|
type: DateSegmentType;
|
|
@@ -11,13 +10,6 @@
|
|
|
11
10
|
|
|
12
11
|
const ctx = getDateFieldCtx();
|
|
13
12
|
|
|
14
|
-
let el: HTMLSpanElement;
|
|
15
|
-
|
|
16
|
-
onMount(() => {
|
|
17
|
-
ctx.registerSegment(type, el);
|
|
18
|
-
return () => ctx.unregisterSegment(type);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
13
|
const segmentData = $derived(ctx.segments.find((s) => s.type === type));
|
|
22
14
|
|
|
23
15
|
const minValue = $derived(type === 'month' ? 1 : type === 'day' ? 1 : 1000);
|
|
@@ -35,6 +27,15 @@
|
|
|
35
27
|
let inputBuffer = '';
|
|
36
28
|
let bufferTimeout: ReturnType<typeof setTimeout>;
|
|
37
29
|
|
|
30
|
+
function registerSegment(node: HTMLSpanElement) {
|
|
31
|
+
ctx.registerSegment(type, node);
|
|
32
|
+
return {
|
|
33
|
+
destroy() {
|
|
34
|
+
ctx.unregisterSegment(type);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
38
39
|
function increment() {
|
|
39
40
|
const current = segmentData?.value ?? minValue - 1;
|
|
40
41
|
const next = current >= maxValue ? minValue : current + 1;
|
|
@@ -111,7 +112,7 @@
|
|
|
111
112
|
</script>
|
|
112
113
|
|
|
113
114
|
<span
|
|
114
|
-
|
|
115
|
+
{@attach registerSegment}
|
|
115
116
|
role="spinbutton"
|
|
116
117
|
tabindex={ctx.disabled ? undefined : 0}
|
|
117
118
|
aria-label={type}
|
|
@@ -119,6 +120,7 @@
|
|
|
119
120
|
aria-valuemax={maxValue}
|
|
120
121
|
aria-valuenow={segmentData?.value ?? undefined}
|
|
121
122
|
aria-valuetext={displayValue}
|
|
123
|
+
data-df-segment
|
|
122
124
|
data-segment={type}
|
|
123
125
|
data-placeholder={segmentData?.value === null ? '' : undefined}
|
|
124
126
|
data-disabled={ctx.disabled || undefined}
|
|
@@ -13,7 +13,15 @@
|
|
|
13
13
|
const display = $derived(separator ?? ctx.separator);
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
<span
|
|
16
|
+
<span
|
|
17
|
+
aria-hidden="true"
|
|
18
|
+
data-df-separator
|
|
19
|
+
data-separator=""
|
|
20
|
+
{...rest}
|
|
21
|
+
class={className}
|
|
22
|
+
>
|
|
23
|
+
{display}
|
|
24
|
+
</span>
|
|
17
25
|
|
|
18
26
|
<style>
|
|
19
27
|
[data-df-separator] {
|