@dryui/ui 1.5.1 → 1.7.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/accordion/accordion-item.svelte +9 -0
- package/dist/accordion/accordion-root.svelte +1 -1
- package/dist/alert/alert.svelte +1 -0
- package/dist/avatar/avatar.svelte +1 -1
- package/dist/button/button.svelte +3 -2
- package/dist/button-group/context.svelte.js +4 -7
- package/dist/calendar/calendar-root.svelte +15 -32
- package/dist/card/card-root.svelte +1 -0
- package/dist/chart/chart-y-axis.svelte +5 -0
- package/dist/checkbox/checkbox-input.svelte +30 -31
- package/dist/chip-group/context.svelte.d.ts +2 -4
- package/dist/chip-group/context.svelte.js +2 -9
- package/dist/combobox/combobox-content.svelte +1 -0
- package/dist/combobox/combobox-item.svelte +9 -0
- package/dist/command-palette/command-palette-item.svelte +9 -0
- package/dist/command-palette/command-palette-list.svelte +1 -0
- package/dist/context-menu/context-menu-content.svelte +25 -12
- package/dist/context-menu/context-menu-group.svelte +3 -2
- package/dist/context-menu/context-menu-item.svelte +8 -61
- package/dist/context-menu/context-menu-label.svelte +3 -11
- package/dist/context-menu/context-menu-root.svelte +10 -29
- package/dist/context-menu/context-menu-separator.svelte +2 -9
- package/dist/context-menu/context.svelte.d.ts +2 -12
- package/dist/data-grid/data-grid-cell.svelte +5 -0
- package/dist/date-picker/datepicker-content.svelte +11 -81
- package/dist/date-picker/datepicker-content.svelte.d.ts +1 -1
- package/dist/date-picker/datepicker-input-root.svelte +39 -47
- package/dist/date-range-picker/date-range-picker-content.svelte +11 -75
- package/dist/date-range-picker/date-range-picker-content.svelte.d.ts +1 -1
- package/dist/date-range-picker/date-range-picker-root.svelte +44 -49
- package/dist/drag-and-drop/group-context.svelte.d.ts +1 -1
- package/dist/drag-and-drop/group-context.svelte.js +4 -4
- package/dist/dropdown-menu/context.svelte.d.ts +2 -8
- package/dist/dropdown-menu/dropdown-menu-content.svelte +22 -3
- package/dist/dropdown-menu/dropdown-menu-group.svelte +3 -2
- package/dist/dropdown-menu/dropdown-menu-item.svelte +8 -61
- package/dist/dropdown-menu/dropdown-menu-label.svelte +3 -11
- package/dist/dropdown-menu/dropdown-menu-root.svelte +10 -21
- package/dist/dropdown-menu/dropdown-menu-separator.svelte +2 -9
- package/dist/flip-card/context.svelte.d.ts +5 -0
- package/dist/flip-card/context.svelte.js +2 -0
- package/dist/flip-card/flip-card-back.svelte +2 -2
- package/dist/flip-card/flip-card-root.svelte +42 -15
- package/dist/heading/heading.svelte +10 -1
- package/dist/heading/heading.svelte.d.ts +1 -0
- package/dist/heading/index.d.ts +1 -0
- package/dist/hover-card/hover-card-content.svelte +9 -21
- package/dist/hover-card/hover-card-root.svelte +2 -2
- package/dist/hover-card/hover-card-root.svelte.d.ts +4 -0
- package/dist/image/image.svelte +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/internal/anchored-overlay-content.svelte.d.ts +20 -0
- package/dist/internal/anchored-overlay-content.svelte.js +28 -0
- package/dist/internal/date-family-controller.svelte.d.ts +45 -0
- package/dist/internal/date-family-controller.svelte.js +99 -0
- package/dist/internal/menu-group.svelte +15 -0
- package/dist/internal/menu-group.svelte.d.ts +9 -0
- package/dist/internal/menu-item.svelte +91 -0
- package/dist/internal/menu-item.svelte.d.ts +11 -0
- package/dist/internal/menu-label.svelte +24 -0
- package/dist/internal/menu-label.svelte.d.ts +9 -0
- package/dist/internal/menu-root-state.svelte.d.ts +24 -0
- package/dist/internal/menu-root-state.svelte.js +42 -0
- package/dist/internal/menu-separator.svelte +19 -0
- package/dist/internal/menu-separator.svelte.d.ts +7 -0
- package/dist/internal/modal-content.svelte +18 -0
- package/dist/internal/motion.js +12 -1
- package/dist/internal/nav-arrow-button.svelte +21 -5
- package/dist/internal/picker-popover-content.svelte +112 -0
- package/dist/internal/picker-popover-content.svelte.d.ts +16 -0
- package/dist/link-preview/link-preview-content.svelte +7 -10
- package/dist/list/list-item-icon.svelte +3 -3
- package/dist/list/list-item-icon.svelte.d.ts +1 -1
- package/dist/list/list-item-text.svelte +3 -3
- package/dist/list/list-item-text.svelte.d.ts +1 -1
- package/dist/list/list-item.svelte +58 -35
- package/dist/list/list-item.svelte.d.ts +8 -2
- package/dist/menubar/menubar-content.svelte +1 -0
- package/dist/menubar/menubar-item.svelte +10 -1
- package/dist/number-input/number-input-button.svelte +1 -0
- package/dist/pin-input/pin-input-cell.svelte +1 -0
- package/dist/popover/popover-content.svelte +15 -11
- package/dist/progress/progress.svelte +1 -0
- package/dist/radio-group/radio-group-item-input.svelte +17 -2
- package/dist/range-calendar/range-calendar-root.svelte +13 -19
- package/dist/reveal/reveal.svelte +1 -1
- package/dist/select/select-content.svelte +1 -0
- package/dist/select/select-item.svelte +9 -0
- package/dist/select/select-trigger-button.svelte +18 -1
- package/dist/skeleton/skeleton.svelte +2 -0
- package/dist/slider/slider-input.svelte +1 -0
- package/dist/text/index.d.ts +1 -0
- package/dist/text/text.svelte +4 -1
- package/dist/text/text.svelte.d.ts +1 -0
- package/dist/theme-toggle/index.d.ts +18 -0
- package/dist/theme-toggle/index.js +3 -0
- package/dist/theme-toggle/theme-controller.svelte.d.ts +54 -0
- package/dist/theme-toggle/theme-controller.svelte.js +121 -0
- package/dist/theme-toggle/theme-flash.d.ts +16 -0
- package/dist/theme-toggle/theme-flash.js +38 -0
- package/dist/theme-toggle/theme-toggle.svelte +199 -0
- package/dist/theme-toggle/theme-toggle.svelte.d.ts +40 -0
- package/dist/themes/dark.css +6 -0
- package/dist/themes/default.css +92 -0
- package/dist/toast/toast-provider.svelte +1 -0
- package/dist/toast/toast-root.svelte +1 -0
- package/dist/tooltip/tooltip-content.svelte +13 -10
- package/dist/typography/heading.svelte +13 -89
- package/dist/typography/heading.svelte.d.ts +3 -8
- package/dist/typography/index.d.ts +8 -7
- package/dist/typography/text.svelte +12 -84
- package/dist/typography/text.svelte.d.ts +3 -10
- package/dist/video-embed/video-embed-button.svelte +2 -1
- package/package.json +7 -2
- package/skills/dryui/SKILL.md +18 -5
- package/skills/dryui/rules/composition.md +1 -1
- package/skills/dryui/rules/theming.md +1 -2
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
4
|
import { getDropdownMenuCtx } from './context.svelte.js';
|
|
5
|
+
import MenuItem from '../internal/menu-item.svelte';
|
|
5
6
|
|
|
6
7
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
8
|
disabled?: boolean;
|
|
@@ -11,70 +12,16 @@
|
|
|
11
12
|
let { class: className, disabled, children, onclick, onkeydown, ...rest }: Props = $props();
|
|
12
13
|
|
|
13
14
|
const ctx = getDropdownMenuCtx();
|
|
14
|
-
|
|
15
|
-
function handleClick(e: MouseEvent & { currentTarget: HTMLDivElement }) {
|
|
16
|
-
if (disabled) return;
|
|
17
|
-
if (onclick) (onclick as (e: MouseEvent & { currentTarget: HTMLDivElement }) => void)(e);
|
|
18
|
-
ctx.close();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function handleKeydown(e: KeyboardEvent & { currentTarget: HTMLDivElement }) {
|
|
22
|
-
if (disabled) return;
|
|
23
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
24
|
-
e.preventDefault();
|
|
25
|
-
(e.currentTarget as HTMLElement).click();
|
|
26
|
-
}
|
|
27
|
-
if (onkeydown) (onkeydown as (e: KeyboardEvent & { currentTarget: HTMLDivElement }) => void)(e);
|
|
28
|
-
}
|
|
29
15
|
</script>
|
|
30
16
|
|
|
31
|
-
<
|
|
32
|
-
role="menuitem"
|
|
33
|
-
tabindex={disabled ? undefined : -1}
|
|
34
|
-
aria-disabled={disabled || undefined}
|
|
17
|
+
<MenuItem
|
|
35
18
|
data-dropdown-menu-item
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
19
|
+
{className}
|
|
20
|
+
close={ctx.close}
|
|
21
|
+
{disabled}
|
|
22
|
+
{onclick}
|
|
23
|
+
{onkeydown}
|
|
40
24
|
{...rest}
|
|
41
25
|
>
|
|
42
26
|
{@render children()}
|
|
43
|
-
</
|
|
44
|
-
|
|
45
|
-
<style>
|
|
46
|
-
[data-dropdown-menu-item] {
|
|
47
|
-
display: grid;
|
|
48
|
-
grid-auto-flow: column;
|
|
49
|
-
grid-auto-columns: max-content;
|
|
50
|
-
align-items: center;
|
|
51
|
-
gap: var(--dry-space-2);
|
|
52
|
-
padding: var(--dry-menu-item-padding, var(--dry-space-3) var(--dry-space-4));
|
|
53
|
-
border-radius: var(
|
|
54
|
-
--dry-menu-item-radius,
|
|
55
|
-
min(var(--dry-control-radius, var(--dry-radius-sm)), var(--dry-space-4))
|
|
56
|
-
);
|
|
57
|
-
font-size: var(--dry-type-small-size, var(--dry-text-sm-size));
|
|
58
|
-
cursor: pointer;
|
|
59
|
-
user-select: none;
|
|
60
|
-
outline: none;
|
|
61
|
-
color: var(--dry-color-text-strong);
|
|
62
|
-
min-height: var(--dry-space-11);
|
|
63
|
-
transition: background var(--dry-duration-fast) var(--dry-ease-default);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
[data-dropdown-menu-item]:hover:not([data-disabled]),
|
|
67
|
-
[data-dropdown-menu-item]:focus-visible {
|
|
68
|
-
background: var(--dry-color-fill);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
[data-dropdown-menu-item]:active:not([data-disabled]) {
|
|
72
|
-
background: var(--dry-color-fill-hover);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
[data-dropdown-menu-item][data-disabled] {
|
|
76
|
-
color: var(--dry-color-text-disabled);
|
|
77
|
-
cursor: not-allowed;
|
|
78
|
-
pointer-events: none;
|
|
79
|
-
}
|
|
80
|
-
</style>
|
|
27
|
+
</MenuItem>
|
|
@@ -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 MenuLabel from '../internal/menu-label.svelte';
|
|
4
5
|
|
|
5
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
6
7
|
children: Snippet;
|
|
@@ -9,15 +10,6 @@
|
|
|
9
10
|
let { class: className, children, ...rest }: Props = $props();
|
|
10
11
|
</script>
|
|
11
12
|
|
|
12
|
-
<
|
|
13
|
+
<MenuLabel data-dropdown-menu-label {className} {...rest}>
|
|
13
14
|
{@render children()}
|
|
14
|
-
</
|
|
15
|
-
|
|
16
|
-
<style>
|
|
17
|
-
[data-dropdown-menu-label] {
|
|
18
|
-
padding: var(--dry-space-1_5) var(--dry-space-2);
|
|
19
|
-
font-size: var(--dry-type-tiny-size, var(--dry-text-xs-size));
|
|
20
|
-
color: var(--dry-color-text-weak);
|
|
21
|
-
font-weight: 500;
|
|
22
|
-
}
|
|
23
|
-
</style>
|
|
15
|
+
</MenuLabel>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { generateFormId } from '@dryui/primitives';
|
|
4
3
|
import { setDropdownMenuCtx } from './context.svelte.js';
|
|
4
|
+
import { createMenuRootState } from '../internal/menu-root-state.svelte.js';
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
7
7
|
open?: boolean;
|
|
@@ -10,26 +10,15 @@
|
|
|
10
10
|
|
|
11
11
|
let { open = $bindable(false), children }: Props = $props();
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
triggerEl: null,
|
|
23
|
-
show() {
|
|
24
|
-
open = true;
|
|
25
|
-
},
|
|
26
|
-
close() {
|
|
27
|
-
open = false;
|
|
28
|
-
},
|
|
29
|
-
toggle() {
|
|
30
|
-
open = !open;
|
|
31
|
-
}
|
|
32
|
-
});
|
|
13
|
+
setDropdownMenuCtx(
|
|
14
|
+
createMenuRootState({
|
|
15
|
+
idBase: 'dropdown',
|
|
16
|
+
getOpen: () => open,
|
|
17
|
+
setOpen: (value) => {
|
|
18
|
+
open = value;
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
);
|
|
33
22
|
</script>
|
|
34
23
|
|
|
35
24
|
{@render children()}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import MenuSeparator from '../internal/menu-separator.svelte';
|
|
3
4
|
|
|
4
5
|
interface Props extends HTMLAttributes<HTMLDivElement> {}
|
|
5
6
|
|
|
6
7
|
let { class: className, ...rest }: Props = $props();
|
|
7
8
|
</script>
|
|
8
9
|
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
<style>
|
|
12
|
-
[data-dropdown-menu-separator] {
|
|
13
|
-
height: 1px;
|
|
14
|
-
background: var(--dry-color-stroke-weak);
|
|
15
|
-
margin: var(--dry-space-1) 0;
|
|
16
|
-
}
|
|
17
|
-
</style>
|
|
10
|
+
<MenuSeparator data-dropdown-menu-separator {className} {...rest}></MenuSeparator>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import {
|
|
4
|
+
import { getFlipCardCtx } from './context.svelte.js';
|
|
5
5
|
|
|
6
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
7
|
children: Snippet;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
let { class: className, children, ...rest }: Props = $props();
|
|
11
|
-
const ctx =
|
|
11
|
+
const ctx = getFlipCardCtx();
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
14
|
<div
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import
|
|
4
|
+
import Button from '../button/button.svelte';
|
|
5
|
+
import VisuallyHidden from '../visually-hidden/visually-hidden.svelte';
|
|
6
|
+
import { setFlipCardCtx } from './context.svelte.js';
|
|
5
7
|
|
|
6
8
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
9
|
trigger?: 'hover' | 'click';
|
|
@@ -14,6 +16,8 @@
|
|
|
14
16
|
trigger = 'hover',
|
|
15
17
|
direction = 'horizontal',
|
|
16
18
|
flipped = $bindable(false),
|
|
19
|
+
'aria-label': ariaLabel,
|
|
20
|
+
'aria-labelledby': ariaLabelledBy,
|
|
17
21
|
class: className,
|
|
18
22
|
children,
|
|
19
23
|
...rest
|
|
@@ -23,7 +27,9 @@
|
|
|
23
27
|
flipped = !flipped;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
const toggleLabel = $derived(flipped ? 'Show front of card' : 'Show back of card');
|
|
31
|
+
|
|
32
|
+
setFlipCardCtx({
|
|
27
33
|
get flipped() {
|
|
28
34
|
return flipped;
|
|
29
35
|
},
|
|
@@ -33,29 +39,34 @@
|
|
|
33
39
|
});
|
|
34
40
|
</script>
|
|
35
41
|
|
|
36
|
-
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
37
42
|
<div
|
|
38
43
|
data-flip-card
|
|
44
|
+
data-part="root"
|
|
39
45
|
data-flipped={flipped ? '' : undefined}
|
|
40
46
|
data-trigger={trigger}
|
|
41
47
|
data-direction={direction}
|
|
42
|
-
role={trigger === '
|
|
43
|
-
aria-roledescription=
|
|
44
|
-
|
|
48
|
+
role={trigger === 'hover' ? 'group' : undefined}
|
|
49
|
+
aria-roledescription={trigger === 'hover' ? 'flip card' : undefined}
|
|
50
|
+
aria-label={trigger === 'hover' ? ariaLabel : undefined}
|
|
51
|
+
aria-labelledby={trigger === 'hover' ? ariaLabelledBy : undefined}
|
|
45
52
|
onmouseenter={trigger === 'hover' ? () => (flipped = true) : undefined}
|
|
46
53
|
onmouseleave={trigger === 'hover' ? () => (flipped = false) : undefined}
|
|
47
|
-
onclick={trigger === 'click' ? toggle : undefined}
|
|
48
|
-
onkeydown={trigger === 'click'
|
|
49
|
-
? (e) => {
|
|
50
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
51
|
-
e.preventDefault();
|
|
52
|
-
toggle();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
: undefined}
|
|
56
54
|
class={className}
|
|
57
55
|
{...rest}
|
|
58
56
|
>
|
|
57
|
+
{#if trigger === 'click'}
|
|
58
|
+
<span data-flip-card-toggle-shell>
|
|
59
|
+
<Button
|
|
60
|
+
variant="bare"
|
|
61
|
+
aria-pressed={flipped}
|
|
62
|
+
aria-label={ariaLabel ?? toggleLabel}
|
|
63
|
+
aria-labelledby={ariaLabelledBy}
|
|
64
|
+
onclick={toggle}
|
|
65
|
+
>
|
|
66
|
+
<VisuallyHidden>{toggleLabel}</VisuallyHidden>
|
|
67
|
+
</Button>
|
|
68
|
+
</span>
|
|
69
|
+
{/if}
|
|
59
70
|
{@render children()}
|
|
60
71
|
</div>
|
|
61
72
|
|
|
@@ -72,6 +83,22 @@
|
|
|
72
83
|
transform-style: preserve-3d;
|
|
73
84
|
}
|
|
74
85
|
|
|
86
|
+
[data-flip-card-toggle-shell] {
|
|
87
|
+
position: absolute;
|
|
88
|
+
inset: 0;
|
|
89
|
+
z-index: 3;
|
|
90
|
+
display: grid;
|
|
91
|
+
border-radius: inherit;
|
|
92
|
+
--dry-btn-bg: transparent;
|
|
93
|
+
--dry-btn-border: transparent;
|
|
94
|
+
--dry-btn-color: inherit;
|
|
95
|
+
--dry-btn-padding-x: 0;
|
|
96
|
+
--dry-btn-padding-y: 0;
|
|
97
|
+
--dry-btn-min-height: 0;
|
|
98
|
+
--dry-btn-radius: inherit;
|
|
99
|
+
box-shadow: none;
|
|
100
|
+
}
|
|
101
|
+
|
|
75
102
|
[data-flip-card][data-direction='horizontal'][data-flipped] {
|
|
76
103
|
--dry-flip-card-front-transform: rotateY(180deg);
|
|
77
104
|
--dry-flip-card-back-transform: rotateY(360deg);
|
|
@@ -6,10 +6,18 @@
|
|
|
6
6
|
interface Props extends HTMLAttributes<HTMLHeadingElement> {
|
|
7
7
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
8
8
|
variant?: 'default' | 'display';
|
|
9
|
+
className?: HTMLAttributes<HTMLHeadingElement>['class'];
|
|
9
10
|
children: Snippet;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
let {
|
|
13
|
+
let {
|
|
14
|
+
level = 2,
|
|
15
|
+
variant = 'default',
|
|
16
|
+
class: classAttr,
|
|
17
|
+
className = classAttr,
|
|
18
|
+
children,
|
|
19
|
+
...rest
|
|
20
|
+
}: Props = $props();
|
|
13
21
|
</script>
|
|
14
22
|
|
|
15
23
|
{#if level === 1}
|
|
@@ -51,6 +59,7 @@
|
|
|
51
59
|
font-weight: 700;
|
|
52
60
|
line-height: var(--dry-type-heading-2-leading, 2.5rem);
|
|
53
61
|
letter-spacing: -0.03em;
|
|
62
|
+
text-wrap: balance;
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
[data-level='1'] {
|
|
@@ -3,6 +3,7 @@ import type { HTMLAttributes } from 'svelte/elements';
|
|
|
3
3
|
interface Props extends HTMLAttributes<HTMLHeadingElement> {
|
|
4
4
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
5
5
|
variant?: 'default' | 'display';
|
|
6
|
+
className?: HTMLAttributes<HTMLHeadingElement>['class'];
|
|
6
7
|
children: Snippet;
|
|
7
8
|
}
|
|
8
9
|
declare const Heading: import("svelte").Component<Props, {}, "">;
|
package/dist/heading/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { HTMLAttributes } from 'svelte/elements';
|
|
|
3
3
|
export interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {
|
|
4
4
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
5
5
|
variant?: 'default' | 'display';
|
|
6
|
+
className?: HTMLAttributes<HTMLHeadingElement>['class'];
|
|
6
7
|
children: Snippet;
|
|
7
8
|
}
|
|
8
9
|
export { default as Heading } from './heading.svelte';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import { createAnchoredPopover } from '@dryui/primitives';
|
|
5
4
|
import type { Placement } from '@dryui/primitives';
|
|
5
|
+
import { createAnchoredOverlayContent } from '../internal/anchored-overlay-content.svelte.js';
|
|
6
6
|
import { getHoverCardCtx } from './context.svelte.js';
|
|
7
7
|
|
|
8
8
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -22,28 +22,16 @@
|
|
|
22
22
|
|
|
23
23
|
const ctx = getHoverCardCtx();
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
const overlay = createAnchoredOverlayContent({
|
|
26
|
+
ctx,
|
|
27
|
+
placement: () => placement,
|
|
28
|
+
offset: () => offset,
|
|
29
|
+
style: () => style,
|
|
30
|
+
onContentChange: (contentEl) => {
|
|
29
31
|
ctx.contentEl = contentEl;
|
|
30
|
-
|
|
31
|
-
return () => {
|
|
32
|
-
if (ctx.contentEl === contentEl) {
|
|
33
|
-
ctx.contentEl = null;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
32
|
}
|
|
37
33
|
});
|
|
38
34
|
|
|
39
|
-
const popover = createAnchoredPopover({
|
|
40
|
-
triggerEl: () => ctx.triggerEl,
|
|
41
|
-
contentEl: () => contentEl ?? null,
|
|
42
|
-
open: () => ctx.open,
|
|
43
|
-
placement: () => placement,
|
|
44
|
-
offset: () => offset
|
|
45
|
-
});
|
|
46
|
-
|
|
47
35
|
function handleKeydown(e: KeyboardEvent) {
|
|
48
36
|
if (e.key === 'Escape') {
|
|
49
37
|
e.preventDefault();
|
|
@@ -75,14 +63,14 @@
|
|
|
75
63
|
</script>
|
|
76
64
|
|
|
77
65
|
<div
|
|
78
|
-
|
|
66
|
+
{@attach overlay.bindContent}
|
|
67
|
+
{@attach overlay.position}
|
|
79
68
|
id={ctx.contentId}
|
|
80
69
|
popover="manual"
|
|
81
70
|
role="dialog"
|
|
82
71
|
aria-labelledby={ctx.triggerId}
|
|
83
72
|
data-hover-card-content
|
|
84
73
|
data-state={ctx.open ? 'open' : 'closed'}
|
|
85
|
-
use:popover.applyPosition={style}
|
|
86
74
|
onpointerenter={handlePointerEnter}
|
|
87
75
|
onpointerleave={handlePointerLeave}
|
|
88
76
|
onfocusin={handleFocusIn}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type {
|
|
2
|
+
import type { HoverCardRootProps } from '@dryui/primitives';
|
|
3
3
|
import { HoverCard as PrimitiveHoverCard } from '@dryui/primitives';
|
|
4
4
|
|
|
5
5
|
// The styled hover-card only adds theme tokens to trigger/content, so root
|
|
6
6
|
// is a pure re-export of the primitives implementation. The ctx set here is
|
|
7
7
|
// consumed by the ui trigger/content via the shared primitives ctx key.
|
|
8
|
-
let props:
|
|
8
|
+
let props: HoverCardRootProps = $props();
|
|
9
9
|
</script>
|
|
10
10
|
|
|
11
11
|
<PrimitiveHoverCard.Root {...props} />
|
package/dist/image/image.svelte
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,8 @@ export { Toggle } from './toggle/index.js';
|
|
|
52
52
|
export type { ToggleProps } from './toggle/index.js';
|
|
53
53
|
export { ToggleGroup } from './toggle-group/index.js';
|
|
54
54
|
export type { ToggleGroupRootProps, ToggleGroupItemProps } from './toggle-group/index.js';
|
|
55
|
+
export { ThemeToggle, createThemeController, themeFlashScript } from './theme-toggle/index.js';
|
|
56
|
+
export type { ThemeToggleProps, ThemeMode, ThemeController, ThemeControllerOptions } from './theme-toggle/index.js';
|
|
55
57
|
export { InputGroup } from './input-group/index.js';
|
|
56
58
|
export type { InputGroupRootProps, InputGroupPrefixProps, InputGroupInputProps, InputGroupSuffixProps, InputGroupSelectProps, InputGroupSeparatorProps, InputGroupActionProps } from './input-group/index.js';
|
|
57
59
|
export { OptionPicker } from './option-picker/index.js';
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ export { SegmentedControl } from './segmented-control/index.js';
|
|
|
26
26
|
export { Slider } from './slider/index.js';
|
|
27
27
|
export { Toggle } from './toggle/index.js';
|
|
28
28
|
export { ToggleGroup } from './toggle-group/index.js';
|
|
29
|
+
export { ThemeToggle, createThemeController, themeFlashScript } from './theme-toggle/index.js';
|
|
29
30
|
export { InputGroup } from './input-group/index.js';
|
|
30
31
|
export { OptionPicker } from './option-picker/index.js';
|
|
31
32
|
// Phase 4 — Layout Primitives
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
import { type Placement } from '@dryui/primitives';
|
|
3
|
+
interface AnchoredOverlayContentContext {
|
|
4
|
+
readonly open: boolean;
|
|
5
|
+
readonly contentId: string;
|
|
6
|
+
triggerEl: HTMLElement | null;
|
|
7
|
+
}
|
|
8
|
+
interface AnchoredOverlayContentOptions {
|
|
9
|
+
ctx: AnchoredOverlayContentContext;
|
|
10
|
+
placement: () => Placement;
|
|
11
|
+
offset: () => number;
|
|
12
|
+
style: () => HTMLAttributes<HTMLDivElement>['style'];
|
|
13
|
+
onContentChange?: (contentEl: HTMLDivElement | null) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function createAnchoredOverlayContent(options: AnchoredOverlayContentOptions): {
|
|
16
|
+
bindContent: (node: HTMLDivElement) => () => void;
|
|
17
|
+
contentEl: () => HTMLDivElement | null;
|
|
18
|
+
position: import("svelte/attachments").Attachment<HTMLElement>;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { fromAction } from 'svelte/attachments';
|
|
2
|
+
import { createAnchoredPopover } from '@dryui/primitives';
|
|
3
|
+
export function createAnchoredOverlayContent(options) {
|
|
4
|
+
let contentEl = $state();
|
|
5
|
+
const popover = createAnchoredPopover({
|
|
6
|
+
triggerEl: () => options.ctx.triggerEl,
|
|
7
|
+
contentEl: () => contentEl ?? null,
|
|
8
|
+
open: () => options.ctx.open,
|
|
9
|
+
placement: options.placement,
|
|
10
|
+
offset: options.offset
|
|
11
|
+
});
|
|
12
|
+
const position = fromAction(popover.applyPosition, options.style);
|
|
13
|
+
function bindContent(node) {
|
|
14
|
+
contentEl = node;
|
|
15
|
+
options.onContentChange?.(node);
|
|
16
|
+
return () => {
|
|
17
|
+
if (contentEl === node) {
|
|
18
|
+
contentEl = undefined;
|
|
19
|
+
}
|
|
20
|
+
options.onContentChange?.(null);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
bindContent,
|
|
25
|
+
contentEl: () => contentEl ?? null,
|
|
26
|
+
position
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
interface DateViewControllerConfig {
|
|
2
|
+
initialDate?: Date | null;
|
|
3
|
+
locale: () => string;
|
|
4
|
+
}
|
|
5
|
+
export interface DateViewController {
|
|
6
|
+
readonly focusedDate: Date;
|
|
7
|
+
readonly viewMonth: number;
|
|
8
|
+
readonly viewYear: number;
|
|
9
|
+
readonly weekStartDay: number;
|
|
10
|
+
focusDate: (date: Date) => void;
|
|
11
|
+
setFocusedDate: (date: Date) => void;
|
|
12
|
+
goToMonth: (month: number) => void;
|
|
13
|
+
goToYear: (year: number) => void;
|
|
14
|
+
nextMonth: () => void;
|
|
15
|
+
prevMonth: () => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function createDateViewController({ initialDate, locale }: DateViewControllerConfig): DateViewController;
|
|
18
|
+
interface PickerPopoverControllerConfig {
|
|
19
|
+
triggerIdPrefix: string;
|
|
20
|
+
contentIdPrefix: string;
|
|
21
|
+
open: () => boolean;
|
|
22
|
+
setOpen: (open: boolean) => void;
|
|
23
|
+
disabled: () => boolean;
|
|
24
|
+
onShow?: () => void;
|
|
25
|
+
onClose?: () => void;
|
|
26
|
+
}
|
|
27
|
+
export interface PickerPopoverController {
|
|
28
|
+
readonly open: boolean;
|
|
29
|
+
readonly triggerId: string;
|
|
30
|
+
readonly contentId: string;
|
|
31
|
+
readonly triggerEl: HTMLElement | null;
|
|
32
|
+
show: () => void;
|
|
33
|
+
close: () => void;
|
|
34
|
+
toggle: () => void;
|
|
35
|
+
}
|
|
36
|
+
export declare function createPickerPopoverController({ triggerIdPrefix, contentIdPrefix, open, setOpen, disabled, onShow, onClose }: PickerPopoverControllerConfig): {
|
|
37
|
+
readonly triggerId: string;
|
|
38
|
+
readonly contentId: string;
|
|
39
|
+
readonly triggerEl: HTMLElement | null;
|
|
40
|
+
setTriggerEl(element: HTMLElement | null): void;
|
|
41
|
+
show(): void;
|
|
42
|
+
close(): void;
|
|
43
|
+
toggle(): void;
|
|
44
|
+
};
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { generateFormId, getWeekStartDay } from '@dryui/primitives';
|
|
2
|
+
import { SvelteDate } from 'svelte/reactivity';
|
|
3
|
+
export function createDateViewController({ initialDate = null, locale }) {
|
|
4
|
+
const seedDate = initialDate ? new SvelteDate(initialDate.getTime()) : new SvelteDate();
|
|
5
|
+
let viewMonth = $state(seedDate.getMonth());
|
|
6
|
+
let viewYear = $state(seedDate.getFullYear());
|
|
7
|
+
let focusedTime = $state(seedDate.getTime());
|
|
8
|
+
const weekStartDay = $derived(getWeekStartDay(locale()));
|
|
9
|
+
function updateViewFromDate(date) {
|
|
10
|
+
viewMonth = date.getMonth();
|
|
11
|
+
viewYear = date.getFullYear();
|
|
12
|
+
}
|
|
13
|
+
function goToMonth(month) {
|
|
14
|
+
if (month < 0) {
|
|
15
|
+
viewMonth = 11;
|
|
16
|
+
viewYear -= 1;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (month > 11) {
|
|
20
|
+
viewMonth = 0;
|
|
21
|
+
viewYear += 1;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
viewMonth = month;
|
|
25
|
+
}
|
|
26
|
+
function goToYear(year) {
|
|
27
|
+
viewYear = year;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
get focusedDate() {
|
|
31
|
+
return new SvelteDate(focusedTime);
|
|
32
|
+
},
|
|
33
|
+
get viewMonth() {
|
|
34
|
+
return viewMonth;
|
|
35
|
+
},
|
|
36
|
+
get viewYear() {
|
|
37
|
+
return viewYear;
|
|
38
|
+
},
|
|
39
|
+
get weekStartDay() {
|
|
40
|
+
return weekStartDay;
|
|
41
|
+
},
|
|
42
|
+
focusDate(date) {
|
|
43
|
+
focusedTime = date.getTime();
|
|
44
|
+
},
|
|
45
|
+
setFocusedDate(date) {
|
|
46
|
+
focusedTime = date.getTime();
|
|
47
|
+
updateViewFromDate(date);
|
|
48
|
+
},
|
|
49
|
+
goToMonth,
|
|
50
|
+
goToYear,
|
|
51
|
+
nextMonth() {
|
|
52
|
+
goToMonth(viewMonth + 1);
|
|
53
|
+
},
|
|
54
|
+
prevMonth() {
|
|
55
|
+
goToMonth(viewMonth - 1);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function createPickerPopoverController({ triggerIdPrefix, contentIdPrefix, open, setOpen, disabled, onShow, onClose }) {
|
|
60
|
+
const triggerId = generateFormId(triggerIdPrefix);
|
|
61
|
+
const contentId = generateFormId(contentIdPrefix);
|
|
62
|
+
let triggerEl = $state(null);
|
|
63
|
+
return {
|
|
64
|
+
get triggerId() {
|
|
65
|
+
return triggerId;
|
|
66
|
+
},
|
|
67
|
+
get contentId() {
|
|
68
|
+
return contentId;
|
|
69
|
+
},
|
|
70
|
+
get triggerEl() {
|
|
71
|
+
return triggerEl;
|
|
72
|
+
},
|
|
73
|
+
setTriggerEl(element) {
|
|
74
|
+
triggerEl = element;
|
|
75
|
+
},
|
|
76
|
+
show() {
|
|
77
|
+
if (disabled())
|
|
78
|
+
return;
|
|
79
|
+
onShow?.();
|
|
80
|
+
setOpen(true);
|
|
81
|
+
},
|
|
82
|
+
close() {
|
|
83
|
+
setOpen(false);
|
|
84
|
+
onClose?.();
|
|
85
|
+
},
|
|
86
|
+
toggle() {
|
|
87
|
+
if (disabled())
|
|
88
|
+
return;
|
|
89
|
+
const nextOpen = !open();
|
|
90
|
+
if (nextOpen) {
|
|
91
|
+
onShow?.();
|
|
92
|
+
}
|
|
93
|
+
setOpen(nextOpen);
|
|
94
|
+
if (!nextOpen) {
|
|
95
|
+
onClose?.();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
className?: HTMLAttributes<HTMLDivElement>['class'];
|
|
7
|
+
children: Snippet;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { className, children, ...rest }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div role="group" class={className} {...rest}>
|
|
14
|
+
{@render children()}
|
|
15
|
+
</div>
|