@dryui/ui 1.3.1 → 1.4.1
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-content.svelte +1 -1
- package/dist/alert/alert.svelte +1 -1
- package/dist/app-frame/app-frame.svelte +131 -0
- package/dist/app-frame/app-frame.svelte.d.ts +10 -0
- package/dist/app-frame/index.d.ts +8 -0
- package/dist/app-frame/index.js +1 -0
- package/dist/aurora/aurora.svelte +22 -59
- package/dist/beam/beam.svelte +28 -9
- package/dist/carousel/carousel-button-dots.svelte +25 -8
- package/dist/carousel/carousel-button-thumbnails.svelte +25 -8
- package/dist/carousel/carousel-root.svelte +115 -4
- package/dist/carousel/carousel-slide.svelte +5 -1
- package/dist/carousel/carousel-viewport.svelte +2 -0
- package/dist/carousel/context.svelte.d.ts +5 -0
- package/dist/chart/chart-bars.svelte +25 -16
- package/dist/chart/chart-donut.svelte +25 -16
- package/dist/chart/chart-root.svelte +134 -30
- package/dist/chart/chart-root.svelte.d.ts +1 -0
- package/dist/chart/context.svelte.d.ts +3 -1
- package/dist/chart/context.svelte.js +1 -0
- package/dist/chart/index.d.ts +1 -0
- package/dist/chromatic-shift/chromatic-shift.svelte +36 -9
- package/dist/collapsible/collapsible-content.svelte +2 -1
- package/dist/combobox/combobox-content.svelte +26 -44
- package/dist/combobox/combobox-content.svelte.d.ts +1 -1
- package/dist/combobox/combobox-input-root.svelte +7 -1
- package/dist/combobox/combobox-input.svelte +21 -8
- package/dist/country-select/country-select-button-input.svelte +124 -260
- package/dist/date-picker/datepicker-content.svelte +18 -26
- package/dist/date-picker/datepicker-content.svelte.d.ts +2 -1
- package/dist/date-picker/datepicker-input-root.svelte +7 -1
- package/dist/date-range-picker/date-range-picker-content.svelte +18 -14
- package/dist/date-range-picker/date-range-picker-content.svelte.d.ts +2 -1
- package/dist/date-range-picker/date-range-picker-root.svelte +7 -1
- package/dist/displacement/displacement.svelte +16 -22
- package/dist/drag-and-drop/context.svelte.d.ts +2 -0
- package/dist/drag-and-drop/drag-and-drop-handle.svelte +34 -5
- package/dist/drag-and-drop/drag-and-drop-item.svelte +23 -14
- package/dist/drag-and-drop/drag-and-drop-root.svelte +60 -16
- package/dist/god-rays/god-rays.svelte +11 -0
- package/dist/gradient-mesh/gradient-mesh.svelte +27 -5
- package/dist/hover-card/context.svelte.d.ts +1 -10
- package/dist/hover-card/context.svelte.js +1 -2
- package/dist/hover-card/hover-card-content.svelte +41 -3
- package/dist/hover-card/hover-card-root.svelte +7 -55
- package/dist/hover-card/hover-card-trigger.svelte +79 -40
- package/dist/hover-card/hover-card-trigger.svelte.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/internal/motion.d.ts +1 -1
- package/dist/internal/motion.js +1 -1
- package/dist/marquee/marquee.svelte +42 -5
- package/dist/mega-menu/context.svelte.d.ts +2 -1
- package/dist/mega-menu/mega-menu-button-trigger.svelte +2 -14
- package/dist/mega-menu/mega-menu-item.svelte +3 -1
- package/dist/mega-menu/mega-menu-panel.svelte +35 -3
- package/dist/mega-menu/mega-menu-root.svelte +28 -13
- package/dist/menubar/context.svelte.d.ts +2 -2
- package/dist/menubar/menubar-button-trigger.svelte +5 -3
- package/dist/menubar/menubar-content.svelte +20 -12
- package/dist/menubar/menubar-root.svelte +4 -4
- package/dist/multi-select-combobox/multi-select-combobox-content.svelte +18 -55
- package/dist/multi-select-combobox/multi-select-combobox-content.svelte.d.ts +1 -1
- package/dist/noise/noise.svelte +38 -6
- package/dist/notification-center/context.svelte.d.ts +0 -1
- package/dist/notification-center/notification-center-panel.svelte +54 -35
- package/dist/notification-center/notification-center-root.svelte +0 -1
- package/dist/notification-center/notification-center-trigger-button.svelte +1 -8
- package/dist/option-picker/option-picker-description.svelte +2 -2
- package/dist/option-picker/option-picker-item.svelte +10 -3
- package/dist/option-picker/option-picker-label.svelte +2 -2
- package/dist/option-picker/option-picker-preview.svelte +18 -13
- package/dist/phone-input/phone-input-select.svelte +2 -152
- package/dist/phone-input/phone-input-select.svelte.d.ts +1 -7
- package/dist/rich-text-editor/rich-text-editor-toolbar-button-input.svelte +84 -29
- package/dist/scroll-area/scroll-area.svelte +16 -4
- package/dist/select/select-content.svelte +21 -31
- package/dist/select/select-content.svelte.d.ts +1 -1
- package/dist/select/select-root-input.svelte +7 -1
- package/dist/shimmer/shimmer.svelte +22 -12
- package/dist/transfer/transfer-item.svelte +0 -3
- package/dist/transfer/transfer-list-input.svelte +1 -6
- package/dist/tree/context.svelte.d.ts +7 -1
- package/dist/tree/tree-item-children.svelte +12 -10
- package/dist/tree/tree-item-label.svelte +6 -17
- package/dist/tree/tree-item-label.svelte.d.ts +2 -2
- package/dist/tree/tree-item.svelte +28 -1
- package/dist/tree/tree-root.svelte +135 -59
- package/package.json +8 -2
- package/skills/dryui/SKILL.md +1 -0
- package/dist/hover-card/hover-card-root.svelte.d.ts +0 -9
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
let { class: className, children, ...rest }: Props = $props();
|
|
11
11
|
const ctx = getCarouselCtx();
|
|
12
12
|
const index = ctx.registerSlide();
|
|
13
|
+
const slideId = ctx.getSlideId(index);
|
|
13
14
|
|
|
14
15
|
$effect(() => {
|
|
15
16
|
return () => ctx.unregisterSlide();
|
|
@@ -17,11 +18,14 @@
|
|
|
17
18
|
</script>
|
|
18
19
|
|
|
19
20
|
<div
|
|
21
|
+
id={slideId}
|
|
20
22
|
role="group"
|
|
21
23
|
aria-roledescription="slide"
|
|
22
|
-
aria-
|
|
24
|
+
aria-hidden={ctx.activeIndex === index ? undefined : true}
|
|
25
|
+
aria-label={`${index + 1} of ${ctx.totalSlides}`}
|
|
23
26
|
data-carousel-slide=""
|
|
24
27
|
data-active={ctx.activeIndex === index ? '' : undefined}
|
|
28
|
+
inert={ctx.activeIndex !== index}
|
|
25
29
|
class={className}
|
|
26
30
|
{...rest}
|
|
27
31
|
>
|
|
@@ -4,10 +4,15 @@ interface CarouselContext {
|
|
|
4
4
|
readonly orientation: 'horizontal' | 'vertical';
|
|
5
5
|
readonly canScrollPrev: boolean;
|
|
6
6
|
readonly canScrollNext: boolean;
|
|
7
|
+
readonly autoplayEnabled: boolean;
|
|
8
|
+
readonly autoplayPaused: boolean;
|
|
9
|
+
readonly autoplayRunning: boolean;
|
|
7
10
|
scrollTo: (index: number) => void;
|
|
8
11
|
syncActiveIndex: (index: number) => void;
|
|
9
12
|
scrollPrev: () => void;
|
|
10
13
|
scrollNext: () => void;
|
|
14
|
+
toggleAutoplay: () => void;
|
|
15
|
+
getSlideId: (index: number) => string;
|
|
11
16
|
registerViewport: (el: HTMLElement) => void;
|
|
12
17
|
registerSlide: () => number;
|
|
13
18
|
unregisterSlide: () => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { SVGAttributes } from 'svelte/elements';
|
|
3
|
-
import { getChartCtx } from './context.svelte.js';
|
|
3
|
+
import { getChartCtx, registerChartInteractive } from './context.svelte.js';
|
|
4
4
|
|
|
5
5
|
interface Props extends Omit<SVGAttributes<SVGGElement>, 'onclick'> {
|
|
6
6
|
radius?: number;
|
|
@@ -31,12 +31,32 @@
|
|
|
31
31
|
function handleClick(bar: (typeof bars)[number]) {
|
|
32
32
|
onclick?.({ label: bar.point.label, value: bar.point.value, index: bar.index });
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
function attachBarClick(bar: (typeof bars)[number]) {
|
|
36
|
+
if (!onclick) return undefined;
|
|
37
|
+
|
|
38
|
+
return (node: SVGRectElement) => {
|
|
39
|
+
const handleNodeClick = () => handleClick(bar);
|
|
40
|
+
node.addEventListener('click', handleNodeClick);
|
|
41
|
+
return () => node.removeEventListener('click', handleNodeClick);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const registeredHandler = $derived(
|
|
46
|
+
onclick
|
|
47
|
+
? (index: number) => {
|
|
48
|
+
const point = ctx.data[index];
|
|
49
|
+
if (!point) return;
|
|
50
|
+
onclick({ label: point.label, value: point.value, index });
|
|
51
|
+
}
|
|
52
|
+
: undefined
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
registerChartInteractive(ctx, () => registeredHandler);
|
|
34
56
|
</script>
|
|
35
57
|
|
|
36
58
|
<g role="list" aria-label="Bar chart data" data-chart-bars class={className} {...rest}>
|
|
37
|
-
{#each bars as bar}
|
|
38
|
-
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
39
|
-
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
59
|
+
{#each bars as bar (bar.index)}
|
|
40
60
|
<rect
|
|
41
61
|
x={bar.x}
|
|
42
62
|
y={bar.y}
|
|
@@ -44,20 +64,9 @@
|
|
|
44
64
|
height={bar.height}
|
|
45
65
|
rx={radius}
|
|
46
66
|
fill={bar.point.color ?? 'currentColor'}
|
|
47
|
-
role={onclick ? 'button' : 'listitem'}
|
|
48
|
-
tabindex={onclick ? 0 : undefined}
|
|
49
|
-
aria-label="{bar.point.label}: {bar.point.value}"
|
|
50
67
|
data-part="bar"
|
|
51
68
|
data-clickable={onclick ? '' : undefined}
|
|
52
|
-
|
|
53
|
-
onkeydown={onclick
|
|
54
|
-
? (e: KeyboardEvent) => {
|
|
55
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
56
|
-
e.preventDefault();
|
|
57
|
-
handleClick(bar);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
: undefined}
|
|
69
|
+
{@attach attachBarClick(bar)}
|
|
61
70
|
/>
|
|
62
71
|
{/each}
|
|
63
72
|
</g>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { SVGAttributes } from 'svelte/elements';
|
|
4
|
-
import { getChartCtx } from './context.svelte.js';
|
|
4
|
+
import { getChartCtx, registerChartInteractive } from './context.svelte.js';
|
|
5
5
|
|
|
6
6
|
interface Props extends Omit<SVGAttributes<SVGGElement>, 'onclick'> {
|
|
7
7
|
innerRadius?: number;
|
|
@@ -50,12 +50,32 @@
|
|
|
50
50
|
function handleClick(seg: (typeof segments)[number]) {
|
|
51
51
|
onclick?.({ label: seg.point.label, value: seg.point.value, index: seg.index });
|
|
52
52
|
}
|
|
53
|
+
|
|
54
|
+
function attachSegmentClick(seg: (typeof segments)[number]) {
|
|
55
|
+
if (!onclick) return undefined;
|
|
56
|
+
|
|
57
|
+
return (node: SVGCircleElement) => {
|
|
58
|
+
const handleNodeClick = () => handleClick(seg);
|
|
59
|
+
node.addEventListener('click', handleNodeClick);
|
|
60
|
+
return () => node.removeEventListener('click', handleNodeClick);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const registeredHandler = $derived(
|
|
65
|
+
onclick
|
|
66
|
+
? (index: number) => {
|
|
67
|
+
const point = ctx.data[index];
|
|
68
|
+
if (!point) return;
|
|
69
|
+
onclick({ label: point.label, value: point.value, index });
|
|
70
|
+
}
|
|
71
|
+
: undefined
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
registerChartInteractive(ctx, () => registeredHandler);
|
|
53
75
|
</script>
|
|
54
76
|
|
|
55
77
|
<g role="list" aria-label="Donut chart data" data-chart-donut class={className} {...rest}>
|
|
56
|
-
{#each segments as seg}
|
|
57
|
-
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
58
|
-
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
78
|
+
{#each segments as seg (seg.index)}
|
|
59
79
|
<circle
|
|
60
80
|
{cx}
|
|
61
81
|
{cy}
|
|
@@ -66,20 +86,9 @@
|
|
|
66
86
|
stroke-dasharray={seg.dasharray}
|
|
67
87
|
stroke-dashoffset={seg.dashoffset}
|
|
68
88
|
transform="rotate(-90 {cx} {cy})"
|
|
69
|
-
role={onclick ? 'button' : 'listitem'}
|
|
70
|
-
tabindex={onclick ? 0 : undefined}
|
|
71
|
-
aria-label="{seg.point.label}: {seg.point.value}"
|
|
72
89
|
data-part="donut-segment"
|
|
73
90
|
data-clickable={onclick ? '' : undefined}
|
|
74
|
-
|
|
75
|
-
onkeydown={onclick
|
|
76
|
-
? (e: KeyboardEvent) => {
|
|
77
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
78
|
-
e.preventDefault();
|
|
79
|
-
handleClick(seg);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
: undefined}
|
|
91
|
+
{@attach attachSegmentClick(seg)}
|
|
83
92
|
/>
|
|
84
93
|
{/each}
|
|
85
94
|
{#if label}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { SVGAttributes } from 'svelte/elements';
|
|
4
|
+
import Button from '../button/button.svelte';
|
|
4
5
|
import { setChartCtx, type ChartDataPoint } from './context.svelte.js';
|
|
5
6
|
|
|
6
7
|
interface Props extends SVGAttributes<SVGSVGElement> {
|
|
@@ -8,6 +9,7 @@
|
|
|
8
9
|
width?: number;
|
|
9
10
|
height?: number;
|
|
10
11
|
padding?: { top?: number; right?: number; bottom?: number; left?: number };
|
|
12
|
+
summary?: string;
|
|
11
13
|
children: Snippet;
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -16,22 +18,24 @@
|
|
|
16
18
|
width: widthProp,
|
|
17
19
|
height: heightProp,
|
|
18
20
|
padding: paddingProp,
|
|
21
|
+
summary,
|
|
22
|
+
'aria-label': ariaLabel = 'Chart',
|
|
19
23
|
class: className,
|
|
20
24
|
children,
|
|
21
25
|
...rest
|
|
22
26
|
}: Props = $props();
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
const chartId = $props.id();
|
|
29
|
+
|
|
25
30
|
let observedWidth = $state(400);
|
|
26
31
|
let observedHeight = $state(300);
|
|
32
|
+
let interactiveHandler: ((index: number) => void) | undefined = $state();
|
|
33
|
+
let interactiveOwner: symbol | undefined = $state();
|
|
27
34
|
|
|
28
35
|
const width = $derived(widthProp ?? observedWidth);
|
|
29
36
|
const height = $derived(heightProp ?? observedHeight);
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
if (widthProp !== undefined && heightProp !== undefined) return;
|
|
33
|
-
if (!containerEl) return;
|
|
34
|
-
|
|
38
|
+
function observeSize(node: HTMLDivElement) {
|
|
35
39
|
const ro = new ResizeObserver((entries) => {
|
|
36
40
|
for (const entry of entries) {
|
|
37
41
|
const cr = entry.contentRect;
|
|
@@ -40,9 +44,9 @@
|
|
|
40
44
|
}
|
|
41
45
|
});
|
|
42
46
|
|
|
43
|
-
ro.observe(
|
|
47
|
+
ro.observe(node);
|
|
44
48
|
return () => ro.disconnect();
|
|
45
|
-
}
|
|
49
|
+
}
|
|
46
50
|
|
|
47
51
|
const padding = $derived({
|
|
48
52
|
top: paddingProp?.top ?? 20,
|
|
@@ -51,9 +55,34 @@
|
|
|
51
55
|
left: paddingProp?.left ?? 50
|
|
52
56
|
});
|
|
53
57
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
const stats = $derived.by(() => {
|
|
59
|
+
let min = 0;
|
|
60
|
+
let max = -Infinity;
|
|
61
|
+
let total = 0;
|
|
62
|
+
let highest: ChartDataPoint | undefined;
|
|
63
|
+
let lowest: ChartDataPoint | undefined;
|
|
64
|
+
for (const point of data) {
|
|
65
|
+
const value = point.value;
|
|
66
|
+
if (value < min) min = value;
|
|
67
|
+
if (value > max) max = value;
|
|
68
|
+
total += value;
|
|
69
|
+
if (!highest || value > highest.value) highest = point;
|
|
70
|
+
if (!lowest || value < lowest.value) lowest = point;
|
|
71
|
+
}
|
|
72
|
+
return { min, max, total, highest, lowest };
|
|
73
|
+
});
|
|
74
|
+
const minValue = $derived(stats.min);
|
|
75
|
+
const maxValue = $derived(stats.max);
|
|
76
|
+
const total = $derived(stats.total);
|
|
77
|
+
const summaryText = $derived.by(() => {
|
|
78
|
+
if (summary?.trim()) return summary;
|
|
79
|
+
if (data.length === 0) return 'No data points available.';
|
|
80
|
+
if (data.length === 1) return `${data[0]!.label}: ${data[0]!.value}.`;
|
|
81
|
+
const { highest, lowest } = stats;
|
|
82
|
+
if (!highest || !lowest) return `${data.length} data points available.`;
|
|
83
|
+
return `${data.length} data points. Highest is ${highest.label} at ${highest.value}. Lowest is ${lowest.label} at ${lowest.value}. Total is ${stats.total}.`;
|
|
84
|
+
});
|
|
85
|
+
const isInteractive = $derived(Boolean(interactiveHandler));
|
|
57
86
|
|
|
58
87
|
setChartCtx({
|
|
59
88
|
get data() {
|
|
@@ -78,41 +107,116 @@
|
|
|
78
107
|
return padding;
|
|
79
108
|
},
|
|
80
109
|
hasBars: false,
|
|
81
|
-
hasHorizontalBars: false
|
|
110
|
+
hasHorizontalBars: false,
|
|
111
|
+
get interactiveHandler() {
|
|
112
|
+
return interactiveHandler;
|
|
113
|
+
},
|
|
114
|
+
set interactiveHandler(handler) {
|
|
115
|
+
interactiveHandler = handler;
|
|
116
|
+
},
|
|
117
|
+
get interactiveOwner() {
|
|
118
|
+
return interactiveOwner;
|
|
119
|
+
},
|
|
120
|
+
set interactiveOwner(owner) {
|
|
121
|
+
interactiveOwner = owner;
|
|
122
|
+
}
|
|
82
123
|
});
|
|
83
124
|
</script>
|
|
84
125
|
|
|
85
|
-
|
|
86
|
-
<div
|
|
126
|
+
<div data-chart-root>
|
|
127
|
+
<div data-chart-a11y data-interactive={isInteractive || undefined}>
|
|
128
|
+
<p id={`${chartId}-summary`} data-chart-summary>
|
|
129
|
+
<strong>{ariaLabel}</strong>
|
|
130
|
+
<span>{summaryText}</span>
|
|
131
|
+
</p>
|
|
132
|
+
<ul data-chart-data-list>
|
|
133
|
+
{#each data as point, index (point.label)}
|
|
134
|
+
<li>
|
|
135
|
+
{#if interactiveHandler}
|
|
136
|
+
<Button variant="bare" type="button" onclick={() => interactiveHandler?.(index)}>
|
|
137
|
+
{point.label}: {point.value}
|
|
138
|
+
</Button>
|
|
139
|
+
{:else}
|
|
140
|
+
<span>{point.label}: {point.value}</span>
|
|
141
|
+
{/if}
|
|
142
|
+
</li>
|
|
143
|
+
{/each}
|
|
144
|
+
</ul>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
{#if widthProp === undefined || heightProp === undefined}
|
|
148
|
+
<div data-chart-container {@attach observeSize}>
|
|
149
|
+
<svg
|
|
150
|
+
viewBox="0 0 {width} {height}"
|
|
151
|
+
{width}
|
|
152
|
+
{height}
|
|
153
|
+
data-chart
|
|
154
|
+
class={className}
|
|
155
|
+
{...rest}
|
|
156
|
+
aria-hidden="true"
|
|
157
|
+
focusable="false"
|
|
158
|
+
>
|
|
159
|
+
{@render children()}
|
|
160
|
+
</svg>
|
|
161
|
+
</div>
|
|
162
|
+
{:else}
|
|
87
163
|
<svg
|
|
88
164
|
viewBox="0 0 {width} {height}"
|
|
89
|
-
role="img"
|
|
90
165
|
{width}
|
|
91
166
|
{height}
|
|
92
|
-
aria-label="Chart"
|
|
93
167
|
data-chart
|
|
94
168
|
class={className}
|
|
95
169
|
{...rest}
|
|
170
|
+
aria-hidden="true"
|
|
171
|
+
focusable="false"
|
|
96
172
|
>
|
|
97
173
|
{@render children()}
|
|
98
174
|
</svg>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
<svg
|
|
102
|
-
viewBox="0 0 {width} {height}"
|
|
103
|
-
role="img"
|
|
104
|
-
{width}
|
|
105
|
-
{height}
|
|
106
|
-
aria-label="Chart"
|
|
107
|
-
data-chart
|
|
108
|
-
class={className}
|
|
109
|
-
{...rest}
|
|
110
|
-
>
|
|
111
|
-
{@render children()}
|
|
112
|
-
</svg>
|
|
113
|
-
{/if}
|
|
175
|
+
{/if}
|
|
176
|
+
</div>
|
|
114
177
|
|
|
115
178
|
<style>
|
|
179
|
+
[data-chart-root] {
|
|
180
|
+
display: grid;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
[data-chart-a11y] {
|
|
184
|
+
position: absolute;
|
|
185
|
+
height: 1px;
|
|
186
|
+
aspect-ratio: 1;
|
|
187
|
+
padding: 0;
|
|
188
|
+
margin: -1px;
|
|
189
|
+
overflow: hidden;
|
|
190
|
+
clip: rect(0 0 0 0);
|
|
191
|
+
clip-path: inset(50%);
|
|
192
|
+
border: 0;
|
|
193
|
+
white-space: nowrap;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
[data-chart-a11y][data-interactive]:focus-within {
|
|
197
|
+
position: static;
|
|
198
|
+
height: auto;
|
|
199
|
+
aspect-ratio: auto;
|
|
200
|
+
margin: 0 0 var(--dry-space-3);
|
|
201
|
+
overflow: visible;
|
|
202
|
+
clip: auto;
|
|
203
|
+
clip-path: none;
|
|
204
|
+
white-space: normal;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
[data-chart-summary] {
|
|
208
|
+
margin: 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
[data-chart-summary] strong {
|
|
212
|
+
margin-inline-end: var(--dry-space-1);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
[data-chart-data-list] {
|
|
216
|
+
margin: var(--dry-space-2) 0 0;
|
|
217
|
+
padding-inline-start: 1.25rem;
|
|
218
|
+
}
|
|
219
|
+
|
|
116
220
|
[data-chart-container] {
|
|
117
221
|
display: grid;
|
|
118
222
|
min-height: 200px;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { registerChartInteractive } from '@dryui/primitives';
|
|
1
2
|
export interface ChartDataPoint {
|
|
2
3
|
label: string;
|
|
3
4
|
value: number;
|
|
@@ -25,6 +26,7 @@ interface ChartContext {
|
|
|
25
26
|
};
|
|
26
27
|
hasBars: boolean;
|
|
27
28
|
hasHorizontalBars: boolean;
|
|
29
|
+
interactiveHandler?: (index: number) => void;
|
|
30
|
+
interactiveOwner?: symbol;
|
|
28
31
|
}
|
|
29
32
|
export declare const setChartCtx: (ctx: ChartContext) => ChartContext, getChartCtx: () => ChartContext;
|
|
30
|
-
export {};
|
package/dist/chart/index.d.ts
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
4
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
+
import {
|
|
6
|
+
observeInViewport,
|
|
7
|
+
observePageVisibility,
|
|
8
|
+
observeReducedMotionPreference
|
|
9
|
+
} from '@dryui/primitives/internal/motion';
|
|
5
10
|
|
|
6
11
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
12
|
offset?: number;
|
|
@@ -24,6 +29,9 @@
|
|
|
24
29
|
|
|
25
30
|
let active = $state(false);
|
|
26
31
|
let prefersReducedMotion = $state(false);
|
|
32
|
+
let onScreen = $state(true);
|
|
33
|
+
let tabVisible = $state(true);
|
|
34
|
+
const paused = $derived(!onScreen || !tabVisible);
|
|
27
35
|
|
|
28
36
|
const shouldActivate = $derived.by(() => {
|
|
29
37
|
if (prefersReducedMotion) return false;
|
|
@@ -42,21 +50,34 @@
|
|
|
42
50
|
|
|
43
51
|
const offsetValue = $derived(`${Math.max(0, offset)}px`);
|
|
44
52
|
|
|
45
|
-
onMount(() =>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
};
|
|
51
|
-
mql.addEventListener('change', handler);
|
|
52
|
-
return () => mql.removeEventListener('change', handler);
|
|
53
|
-
});
|
|
53
|
+
onMount(() =>
|
|
54
|
+
observeReducedMotionPreference((matches) => {
|
|
55
|
+
prefersReducedMotion = matches;
|
|
56
|
+
})
|
|
57
|
+
);
|
|
54
58
|
|
|
55
59
|
function applyStyles(node: HTMLElement) {
|
|
56
60
|
$effect(() => {
|
|
57
61
|
node.style.cssText = style || '';
|
|
58
62
|
node.style.setProperty('--dry-chromatic-offset', offsetValue);
|
|
59
63
|
});
|
|
64
|
+
|
|
65
|
+
$effect(() => {
|
|
66
|
+
const stopViewport = observeInViewport(
|
|
67
|
+
node,
|
|
68
|
+
(inView) => {
|
|
69
|
+
onScreen = inView;
|
|
70
|
+
},
|
|
71
|
+
{ rootMargin: '200px' }
|
|
72
|
+
);
|
|
73
|
+
const stopVisibility = observePageVisibility((visible) => {
|
|
74
|
+
tabVisible = visible;
|
|
75
|
+
});
|
|
76
|
+
return () => {
|
|
77
|
+
stopViewport();
|
|
78
|
+
stopVisibility();
|
|
79
|
+
};
|
|
80
|
+
});
|
|
60
81
|
}
|
|
61
82
|
</script>
|
|
62
83
|
|
|
@@ -67,6 +88,7 @@
|
|
|
67
88
|
data-channels={channels}
|
|
68
89
|
data-animated={(animated && !prefersReducedMotion) || undefined}
|
|
69
90
|
data-reduced-motion={prefersReducedMotion || undefined}
|
|
91
|
+
data-paused={paused || undefined}
|
|
70
92
|
onpointerenter={trigger === 'hover' ? handlePointerEnter : undefined}
|
|
71
93
|
onpointerleave={trigger === 'hover' ? handlePointerLeave : undefined}
|
|
72
94
|
{...rest}
|
|
@@ -143,6 +165,11 @@
|
|
|
143
165
|
animation: chromatic-drift-b 4s ease-in-out infinite alternate-reverse;
|
|
144
166
|
}
|
|
145
167
|
|
|
168
|
+
[data-chromatic-shift][data-animated][data-paused]::before,
|
|
169
|
+
[data-chromatic-shift][data-animated][data-paused]::after {
|
|
170
|
+
animation-play-state: paused;
|
|
171
|
+
}
|
|
172
|
+
|
|
146
173
|
@keyframes chromatic-drift-r {
|
|
147
174
|
0% {
|
|
148
175
|
transform: translate(var(--dry-chromatic-offset), 0);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { fromAction } from 'svelte/attachments';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import {
|
|
5
|
-
import type { Placement } from '@dryui/primitives';
|
|
5
|
+
import { createAnchoredPopover, createDismiss, type Placement } from '@dryui/primitives';
|
|
6
6
|
import { getComboboxCtx } from './context.svelte.js';
|
|
7
7
|
|
|
8
8
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -26,56 +26,38 @@
|
|
|
26
26
|
|
|
27
27
|
const ctx = getComboboxCtx();
|
|
28
28
|
|
|
29
|
-
let el = $state<HTMLDivElement>();
|
|
30
|
-
|
|
31
|
-
const anchor = createAnchorPosition(
|
|
32
|
-
() => ctx.inputEl,
|
|
33
|
-
() => el ?? null,
|
|
34
|
-
{
|
|
35
|
-
get placement() {
|
|
36
|
-
return placement;
|
|
37
|
-
},
|
|
38
|
-
get offset() {
|
|
39
|
-
return offset;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
);
|
|
29
|
+
let el = $state<HTMLDivElement | null>(null);
|
|
43
30
|
|
|
44
|
-
|
|
45
|
-
|
|
31
|
+
function attachContent(node: HTMLDivElement) {
|
|
32
|
+
el = node;
|
|
46
33
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
}
|
|
34
|
+
return () => {
|
|
35
|
+
if (el === node) {
|
|
36
|
+
el = null;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
53
40
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
41
|
+
const popover = createAnchoredPopover({
|
|
42
|
+
triggerEl: () => ctx.inputEl,
|
|
43
|
+
contentEl: () => el ?? null,
|
|
44
|
+
open: () => ctx.open,
|
|
45
|
+
placement: () => placement,
|
|
46
|
+
offset: () => offset
|
|
60
47
|
});
|
|
61
48
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (ctx.inputEl?.contains(target) || el?.contains(target)) return;
|
|
69
|
-
ctx.close();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
document.addEventListener('pointerdown', handlePointerDown);
|
|
73
|
-
return () => document.removeEventListener('pointerdown', handlePointerDown);
|
|
49
|
+
createDismiss({
|
|
50
|
+
enabled: () => ctx.open,
|
|
51
|
+
escapeKey: false,
|
|
52
|
+
onDismiss: () => ctx.close(),
|
|
53
|
+
contentEl: () => el ?? null,
|
|
54
|
+
triggerEl: () => ctx.inputEl
|
|
74
55
|
});
|
|
75
56
|
</script>
|
|
76
57
|
|
|
77
58
|
<div
|
|
78
|
-
|
|
59
|
+
{@attach attachContent}
|
|
60
|
+
{@attach fromAction(popover.applyPosition, () => style)}
|
|
79
61
|
popover="manual"
|
|
80
62
|
role="listbox"
|
|
81
63
|
id={ctx.contentId}
|
|
@@ -105,7 +87,7 @@
|
|
|
105
87
|
margin: 0;
|
|
106
88
|
|
|
107
89
|
display: grid;
|
|
108
|
-
grid-template-columns: minmax(12rem, max-content);
|
|
90
|
+
grid-template-columns: minmax(max(12rem, anchor-size(inline)), max-content);
|
|
109
91
|
background: var(--dry-color-bg-overlay);
|
|
110
92
|
border: 1px solid var(--dry-color-stroke-weak);
|
|
111
93
|
border-radius: var(--dry-radius-md);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
import type
|
|
3
|
+
import { type Placement } from '@dryui/primitives';
|
|
4
4
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
5
5
|
placement?: Placement;
|
|
6
6
|
offset?: number;
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
let displayText = $state('');
|
|
26
26
|
let inputValue = $state('');
|
|
27
27
|
let activeIndex = $state(-1);
|
|
28
|
+
let inputEl = $state<HTMLInputElement | null>(null);
|
|
28
29
|
|
|
29
30
|
setComboboxCtx({
|
|
30
31
|
get open() {
|
|
@@ -47,7 +48,12 @@
|
|
|
47
48
|
},
|
|
48
49
|
inputId,
|
|
49
50
|
contentId,
|
|
50
|
-
inputEl
|
|
51
|
+
get inputEl() {
|
|
52
|
+
return inputEl;
|
|
53
|
+
},
|
|
54
|
+
set inputEl(element: HTMLInputElement | null) {
|
|
55
|
+
inputEl = element;
|
|
56
|
+
},
|
|
51
57
|
show() {
|
|
52
58
|
if (!disabled) open = true;
|
|
53
59
|
},
|