@dryui/ui 1.5.1 → 1.6.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/button-group/context.svelte.js +4 -7
- package/dist/calendar/calendar-root.svelte +15 -32
- package/dist/chip-group/context.svelte.d.ts +2 -4
- package/dist/chip-group/context.svelte.js +2 -9
- package/dist/context-menu/context-menu-content.svelte +24 -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/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 +15 -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/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 +82 -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/motion.js +12 -1
- 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/popover/popover-content.svelte +9 -11
- package/dist/range-calendar/range-calendar-root.svelte +13 -19
- package/dist/text/index.d.ts +1 -0
- package/dist/text/text.svelte +3 -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 +189 -0
- package/dist/theme-toggle/theme-toggle.svelte.d.ts +40 -0
- package/dist/tooltip/tooltip-content.svelte +8 -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/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
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { fromAction } from 'svelte/attachments';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
+
import { createAnchoredPopover, type Placement } from '@dryui/primitives';
|
|
6
|
+
import type { PickerPopoverController } from './date-family-controller.svelte.js';
|
|
7
|
+
|
|
8
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
9
|
+
controller: PickerPopoverController;
|
|
10
|
+
dataAttribute: 'data-dp-content' | 'data-drp-content';
|
|
11
|
+
placement?: Placement;
|
|
12
|
+
offset?: number;
|
|
13
|
+
contentClass?: HTMLAttributes<HTMLDivElement>['class'];
|
|
14
|
+
contentStyle?: HTMLAttributes<HTMLDivElement>['style'];
|
|
15
|
+
children: Snippet;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
controller,
|
|
20
|
+
dataAttribute,
|
|
21
|
+
placement = 'bottom-start',
|
|
22
|
+
offset = 8,
|
|
23
|
+
contentClass,
|
|
24
|
+
contentStyle,
|
|
25
|
+
children,
|
|
26
|
+
...rest
|
|
27
|
+
}: Props = $props();
|
|
28
|
+
|
|
29
|
+
let el = $state<HTMLDivElement | null>(null);
|
|
30
|
+
|
|
31
|
+
const markerAttrs = $derived.by<Record<string, string>>(() => ({
|
|
32
|
+
'data-picker-popover-content': '',
|
|
33
|
+
[dataAttribute]: ''
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
function attachContent(node: HTMLDivElement) {
|
|
37
|
+
el = node;
|
|
38
|
+
|
|
39
|
+
return () => {
|
|
40
|
+
if (el === node) {
|
|
41
|
+
el = null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const popover = createAnchoredPopover({
|
|
47
|
+
triggerEl: () => controller.triggerEl,
|
|
48
|
+
contentEl: () => el ?? null,
|
|
49
|
+
open: () => controller.open,
|
|
50
|
+
placement: () => placement,
|
|
51
|
+
offset: () => offset
|
|
52
|
+
});
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<div
|
|
56
|
+
{@attach attachContent}
|
|
57
|
+
{@attach fromAction(popover.applyPosition, () => contentStyle)}
|
|
58
|
+
popover="auto"
|
|
59
|
+
role="dialog"
|
|
60
|
+
id={controller.contentId}
|
|
61
|
+
aria-labelledby={controller.triggerId}
|
|
62
|
+
data-state={controller.open ? 'open' : 'closed'}
|
|
63
|
+
class={contentClass}
|
|
64
|
+
{...markerAttrs}
|
|
65
|
+
ontoggle={(e) => {
|
|
66
|
+
const newState = (e as ToggleEvent).newState === 'open';
|
|
67
|
+
|
|
68
|
+
if (newState && !controller.open) {
|
|
69
|
+
controller.show();
|
|
70
|
+
} else if (!newState && controller.open) {
|
|
71
|
+
controller.close();
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
{...rest}
|
|
75
|
+
>
|
|
76
|
+
{@render children()}
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<style>
|
|
80
|
+
[data-picker-popover-content] {
|
|
81
|
+
inset: unset;
|
|
82
|
+
margin: 0;
|
|
83
|
+
display: inline-grid;
|
|
84
|
+
padding: var(--dry-space-3);
|
|
85
|
+
border: 1px solid var(--dry-color-stroke-weak);
|
|
86
|
+
border-radius: var(--dry-radius-lg);
|
|
87
|
+
background: var(--dry-color-bg-overlay);
|
|
88
|
+
box-shadow: var(--dry-shadow-lg);
|
|
89
|
+
color: var(--dry-color-text-strong);
|
|
90
|
+
transition:
|
|
91
|
+
opacity var(--dry-duration-fast) var(--dry-ease-emphasized),
|
|
92
|
+
transform var(--dry-duration-fast) var(--dry-ease-emphasized);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
[data-picker-popover-content]:not(:popover-open) {
|
|
96
|
+
display: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
[data-picker-popover-content]:popover-open {
|
|
100
|
+
display: inline-grid;
|
|
101
|
+
opacity: 1;
|
|
102
|
+
transform: translateY(0) scale(1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@starting-style {
|
|
106
|
+
[data-picker-popover-content]:popover-open {
|
|
107
|
+
opacity: 0;
|
|
108
|
+
transform: translateY(calc(var(--dry-motion-distance-xs) * -1))
|
|
109
|
+
scale(var(--dry-motion-scale-enter));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Placement } from '@dryui/primitives';
|
|
4
|
+
import type { PickerPopoverController } from './date-family-controller.svelte.js';
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
controller: PickerPopoverController;
|
|
7
|
+
dataAttribute: 'data-dp-content' | 'data-drp-content';
|
|
8
|
+
placement?: Placement;
|
|
9
|
+
offset?: number;
|
|
10
|
+
contentClass?: HTMLAttributes<HTMLDivElement>['class'];
|
|
11
|
+
contentStyle?: HTMLAttributes<HTMLDivElement>['style'];
|
|
12
|
+
children: Snippet;
|
|
13
|
+
}
|
|
14
|
+
declare const PickerPopoverContent: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type PickerPopoverContent = ReturnType<typeof PickerPopoverContent>;
|
|
16
|
+
export default PickerPopoverContent;
|
|
@@ -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 { getLinkPreviewCtx } from './context.svelte.js';
|
|
7
7
|
|
|
8
8
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -22,25 +22,22 @@
|
|
|
22
22
|
|
|
23
23
|
const ctx = getLinkPreviewCtx();
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const popover = createAnchoredPopover({
|
|
28
|
-
triggerEl: () => ctx.triggerEl,
|
|
29
|
-
contentEl: () => contentEl ?? null,
|
|
30
|
-
open: () => ctx.open,
|
|
25
|
+
const overlay = createAnchoredOverlayContent({
|
|
26
|
+
ctx,
|
|
31
27
|
placement: () => placement,
|
|
32
|
-
offset: () => offset
|
|
28
|
+
offset: () => offset,
|
|
29
|
+
style: () => style
|
|
33
30
|
});
|
|
34
31
|
</script>
|
|
35
32
|
|
|
36
33
|
<div
|
|
37
|
-
|
|
34
|
+
{@attach overlay.bindContent}
|
|
35
|
+
{@attach overlay.position}
|
|
38
36
|
id={ctx.contentId}
|
|
39
37
|
role="tooltip"
|
|
40
38
|
popover="manual"
|
|
41
39
|
data-link-preview-content
|
|
42
40
|
data-state={ctx.open ? 'open' : 'closed'}
|
|
43
|
-
use:popover.applyPosition={style}
|
|
44
41
|
onmouseenter={() => ctx.showImmediate()}
|
|
45
42
|
onmouseleave={() => ctx.close()}
|
|
46
43
|
class={className}
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
4
|
|
|
5
|
-
interface Props extends HTMLAttributes<
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
6
6
|
children: Snippet;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
let { class: className, children, ...rest }: Props = $props();
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
|
-
<
|
|
12
|
+
<span data-list-item-icon class={className} {...rest}>
|
|
13
13
|
{@render children()}
|
|
14
|
-
</
|
|
14
|
+
</span>
|
|
15
15
|
|
|
16
16
|
<style>
|
|
17
17
|
[data-list-item-icon] {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
interface Props extends HTMLAttributes<
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
4
4
|
children: Snippet;
|
|
5
5
|
}
|
|
6
6
|
declare const ListItemIcon: import("svelte").Component<Props, {}, "">;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
4
|
|
|
5
|
-
interface Props extends HTMLAttributes<
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
6
6
|
primary?: Snippet;
|
|
7
7
|
secondary?: Snippet;
|
|
8
8
|
children?: Snippet;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
let { class: className, primary, secondary, children, ...rest }: Props = $props();
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
|
-
<
|
|
14
|
+
<span data-list-item-text class={className} {...rest}>
|
|
15
15
|
{#if primary}
|
|
16
16
|
<span data-list-item-primary>{@render primary()}</span>
|
|
17
17
|
{:else if children}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
{#if secondary}
|
|
21
21
|
<span data-list-item-secondary>{@render secondary()}</span>
|
|
22
22
|
{/if}
|
|
23
|
-
</
|
|
23
|
+
</span>
|
|
24
24
|
|
|
25
25
|
<style>
|
|
26
26
|
[data-list-item-text] {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
interface Props extends HTMLAttributes<
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
4
4
|
primary?: Snippet;
|
|
5
5
|
secondary?: Snippet;
|
|
6
6
|
children?: Snippet;
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { ClassValue, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
+
import Button from '../button/button.svelte';
|
|
4
5
|
import { getListCtx } from './context.svelte.js';
|
|
5
6
|
|
|
6
|
-
interface Props extends
|
|
7
|
+
interface Props extends Omit<
|
|
8
|
+
HTMLAttributes<HTMLLIElement>,
|
|
9
|
+
'children' | 'class' | 'onclick' | 'onkeydown' | 'aria-label' | 'aria-labelledby' | 'title'
|
|
10
|
+
> {
|
|
7
11
|
interactive?: boolean;
|
|
8
12
|
disabled?: boolean;
|
|
13
|
+
class?: ClassValue;
|
|
9
14
|
children: Snippet;
|
|
15
|
+
onclick?: HTMLButtonAttributes['onclick'];
|
|
16
|
+
onkeydown?: HTMLButtonAttributes['onkeydown'];
|
|
17
|
+
'aria-label'?: HTMLButtonAttributes['aria-label'];
|
|
18
|
+
'aria-labelledby'?: HTMLButtonAttributes['aria-labelledby'];
|
|
19
|
+
title?: string;
|
|
10
20
|
}
|
|
11
21
|
|
|
12
22
|
let {
|
|
@@ -15,74 +25,87 @@
|
|
|
15
25
|
class: className,
|
|
16
26
|
children,
|
|
17
27
|
onclick,
|
|
28
|
+
onkeydown,
|
|
29
|
+
'aria-label': ariaLabel,
|
|
30
|
+
'aria-labelledby': ariaLabelledBy,
|
|
31
|
+
title,
|
|
18
32
|
...rest
|
|
19
33
|
}: Props = $props();
|
|
20
34
|
|
|
21
35
|
const ctx = getListCtx();
|
|
22
|
-
|
|
23
|
-
function handleKeydown(e: KeyboardEvent) {
|
|
24
|
-
if (!interactive || disabled) return;
|
|
25
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
26
|
-
e.preventDefault();
|
|
27
|
-
if (onclick) {
|
|
28
|
-
(onclick as (e: Event) => void)(e);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
36
|
</script>
|
|
33
37
|
|
|
34
|
-
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
35
38
|
<li
|
|
36
39
|
data-list-item
|
|
37
40
|
data-interactive={interactive || undefined}
|
|
38
41
|
data-disabled={disabled || undefined}
|
|
39
42
|
data-dense={ctx.dense || undefined}
|
|
40
|
-
role={interactive ? 'button' : undefined}
|
|
41
|
-
tabindex={interactive && !disabled ? 0 : undefined}
|
|
42
|
-
aria-disabled={disabled || undefined}
|
|
43
43
|
class={className}
|
|
44
|
-
{onclick}
|
|
45
|
-
onkeydown={interactive ? handleKeydown : undefined}
|
|
46
44
|
{...rest}
|
|
47
45
|
>
|
|
48
|
-
{
|
|
46
|
+
{#if interactive}
|
|
47
|
+
<Button
|
|
48
|
+
variant="secondary"
|
|
49
|
+
{disabled}
|
|
50
|
+
aria-label={ariaLabel}
|
|
51
|
+
aria-labelledby={ariaLabelledBy}
|
|
52
|
+
{title}
|
|
53
|
+
{onclick}
|
|
54
|
+
{onkeydown}
|
|
55
|
+
>
|
|
56
|
+
<span data-list-item-surface>
|
|
57
|
+
{@render children()}
|
|
58
|
+
</span>
|
|
59
|
+
</Button>
|
|
60
|
+
{:else}
|
|
61
|
+
<div data-list-item-surface>
|
|
62
|
+
{@render children()}
|
|
63
|
+
</div>
|
|
64
|
+
{/if}
|
|
49
65
|
</li>
|
|
50
66
|
|
|
51
67
|
<style>
|
|
52
68
|
[data-list-item] {
|
|
69
|
+
display: grid;
|
|
70
|
+
list-style: none;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
[data-list-item-surface] {
|
|
53
74
|
display: grid;
|
|
54
75
|
grid-template-columns: auto minmax(0, 1fr);
|
|
55
76
|
align-items: start;
|
|
56
77
|
gap: var(--dry-list-item-gap);
|
|
57
78
|
padding: var(--dry-list-item-padding);
|
|
79
|
+
border: 0;
|
|
58
80
|
border-radius: var(--dry-list-item-radius);
|
|
81
|
+
background: transparent;
|
|
82
|
+
color: inherit;
|
|
83
|
+
font: inherit;
|
|
84
|
+
text-align: left;
|
|
59
85
|
transition:
|
|
60
86
|
background var(--dry-duration-fast) var(--dry-ease-default),
|
|
61
87
|
color var(--dry-duration-fast) var(--dry-ease-default);
|
|
62
88
|
}
|
|
63
89
|
|
|
64
90
|
[data-list-item][data-interactive='true'] {
|
|
91
|
+
--dry-btn-bg: transparent;
|
|
92
|
+
--dry-btn-border: transparent;
|
|
93
|
+
--dry-btn-color: inherit;
|
|
94
|
+
--dry-btn-padding-x: 0;
|
|
95
|
+
--dry-btn-padding-y: 0;
|
|
96
|
+
--dry-btn-min-height: 0;
|
|
97
|
+
--dry-btn-accent: var(--dry-list-item-active-bg);
|
|
98
|
+
--dry-btn-accent-fg: inherit;
|
|
99
|
+
--dry-btn-accent-stroke: transparent;
|
|
100
|
+
--dry-btn-accent-weak: var(--dry-list-item-hover-bg);
|
|
101
|
+
--dry-btn-on-accent: inherit;
|
|
102
|
+
--dry-btn-radius: var(--dry-list-item-radius);
|
|
103
|
+
box-shadow: none;
|
|
65
104
|
cursor: pointer;
|
|
66
105
|
}
|
|
67
106
|
|
|
68
|
-
[data-list-item][data-interactive='true']:hover,
|
|
69
|
-
[data-list-item][data-interactive='true']:focus-visible {
|
|
70
|
-
background: var(--dry-list-item-hover-bg);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
[data-list-item][data-interactive='true']:active {
|
|
74
|
-
background: var(--dry-list-item-active-bg);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
[data-list-item][data-interactive='true']:focus-visible {
|
|
78
|
-
outline: var(--dry-focus-ring);
|
|
79
|
-
outline-offset: -2px;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
107
|
[data-list-item][data-disabled='true'] {
|
|
83
108
|
opacity: var(--dry-state-disabled-opacity);
|
|
84
|
-
cursor: not-allowed;
|
|
85
|
-
pointer-events: none;
|
|
86
109
|
}
|
|
87
110
|
|
|
88
111
|
[data-list-item][data-dense='true'] {
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
interface Props extends HTMLAttributes<HTMLLIElement> {
|
|
2
|
+
import type { ClassValue, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends Omit<HTMLAttributes<HTMLLIElement>, 'children' | 'class' | 'onclick' | 'onkeydown' | 'aria-label' | 'aria-labelledby' | 'title'> {
|
|
4
4
|
interactive?: boolean;
|
|
5
5
|
disabled?: boolean;
|
|
6
|
+
class?: ClassValue;
|
|
6
7
|
children: Snippet;
|
|
8
|
+
onclick?: HTMLButtonAttributes['onclick'];
|
|
9
|
+
onkeydown?: HTMLButtonAttributes['onkeydown'];
|
|
10
|
+
'aria-label'?: HTMLButtonAttributes['aria-label'];
|
|
11
|
+
'aria-labelledby'?: HTMLButtonAttributes['aria-labelledby'];
|
|
12
|
+
title?: string;
|
|
7
13
|
}
|
|
8
14
|
declare const ListItem: import("svelte").Component<Props, {}, "">;
|
|
9
15
|
type ListItem = ReturnType<typeof ListItem>;
|
|
@@ -1,8 +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 { createDismiss } from '@dryui/primitives';
|
|
5
5
|
import type { Placement } from '@dryui/primitives';
|
|
6
|
+
import { createAnchoredOverlayContent } from '../internal/anchored-overlay-content.svelte.js';
|
|
6
7
|
import { getPopoverCtx } from './context.svelte.js';
|
|
7
8
|
|
|
8
9
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -22,20 +23,17 @@
|
|
|
22
23
|
|
|
23
24
|
const ctx = getPopoverCtx();
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const popover = createAnchoredPopover({
|
|
28
|
-
triggerEl: () => ctx.triggerEl,
|
|
29
|
-
contentEl: () => contentEl ?? null,
|
|
30
|
-
open: () => ctx.open,
|
|
26
|
+
const overlay = createAnchoredOverlayContent({
|
|
27
|
+
ctx,
|
|
31
28
|
placement: () => placement,
|
|
32
|
-
offset: () => offset
|
|
29
|
+
offset: () => offset,
|
|
30
|
+
style: () => style
|
|
33
31
|
});
|
|
34
32
|
|
|
35
33
|
createDismiss({
|
|
36
34
|
enabled: () => ctx.open,
|
|
37
35
|
onDismiss: () => ctx.close(),
|
|
38
|
-
contentEl:
|
|
36
|
+
contentEl: overlay.contentEl,
|
|
39
37
|
triggerEl: () => ctx.triggerEl,
|
|
40
38
|
preventDefaultOnEscape: true,
|
|
41
39
|
returnFocusTo: () => ctx.triggerEl
|
|
@@ -43,12 +41,12 @@
|
|
|
43
41
|
</script>
|
|
44
42
|
|
|
45
43
|
<div
|
|
46
|
-
|
|
44
|
+
{@attach overlay.bindContent}
|
|
45
|
+
{@attach overlay.position}
|
|
47
46
|
id={ctx.contentId}
|
|
48
47
|
popover="manual"
|
|
49
48
|
data-popover-content
|
|
50
49
|
data-state={ctx.open ? 'open' : 'closed'}
|
|
51
|
-
use:popover.applyPosition={style}
|
|
52
50
|
class={className}
|
|
53
51
|
{...rest}
|
|
54
52
|
>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import {
|
|
4
|
+
import { createDateViewController } from '../internal/date-family-controller.svelte.js';
|
|
5
5
|
import { setRangeCalendarCtx } from './context.svelte.js';
|
|
6
6
|
|
|
7
7
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
...rest
|
|
27
27
|
}: Props = $props();
|
|
28
28
|
|
|
29
|
-
const
|
|
29
|
+
const view = createDateViewController({
|
|
30
|
+
initialDate: startDate,
|
|
31
|
+
locale: () => locale
|
|
32
|
+
});
|
|
30
33
|
|
|
31
|
-
let viewMonth = $state(startDate ? startDate.getMonth() : new Date().getMonth());
|
|
32
|
-
let viewYear = $state(startDate ? startDate.getFullYear() : new Date().getFullYear());
|
|
33
|
-
let focusedDate = $state<Date>(startDate ?? new Date());
|
|
34
34
|
let hoveredDate = $state<Date | null>(null);
|
|
35
35
|
|
|
36
36
|
let selecting = $state(false);
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
return hoveredDate;
|
|
47
47
|
},
|
|
48
48
|
get focusedDate() {
|
|
49
|
-
return focusedDate;
|
|
49
|
+
return view.focusedDate;
|
|
50
50
|
},
|
|
51
51
|
get viewMonth() {
|
|
52
|
-
return viewMonth;
|
|
52
|
+
return view.viewMonth;
|
|
53
53
|
},
|
|
54
54
|
get viewYear() {
|
|
55
|
-
return viewYear;
|
|
55
|
+
return view.viewYear;
|
|
56
56
|
},
|
|
57
57
|
get locale() {
|
|
58
58
|
return locale;
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
return disabled;
|
|
68
68
|
},
|
|
69
69
|
get weekStartDay() {
|
|
70
|
-
return weekStartDay;
|
|
70
|
+
return view.weekStartDay;
|
|
71
71
|
},
|
|
72
72
|
selectDate(date: Date) {
|
|
73
73
|
if (!selecting) {
|
|
@@ -83,25 +83,19 @@
|
|
|
83
83
|
}
|
|
84
84
|
selecting = false;
|
|
85
85
|
}
|
|
86
|
-
|
|
86
|
+
view.focusDate(date);
|
|
87
87
|
},
|
|
88
88
|
setHoveredDate(date: Date | null) {
|
|
89
89
|
hoveredDate = date;
|
|
90
90
|
},
|
|
91
91
|
nextMonth() {
|
|
92
|
-
|
|
93
|
-
viewMonth = next.getMonth();
|
|
94
|
-
viewYear = next.getFullYear();
|
|
92
|
+
view.nextMonth();
|
|
95
93
|
},
|
|
96
94
|
prevMonth() {
|
|
97
|
-
|
|
98
|
-
viewMonth = prev.getMonth();
|
|
99
|
-
viewYear = prev.getFullYear();
|
|
95
|
+
view.prevMonth();
|
|
100
96
|
},
|
|
101
97
|
setFocusedDate(date: Date) {
|
|
102
|
-
|
|
103
|
-
viewMonth = date.getMonth();
|
|
104
|
-
viewYear = date.getFullYear();
|
|
98
|
+
view.setFocusedDate(date);
|
|
105
99
|
}
|
|
106
100
|
});
|
|
107
101
|
</script>
|
package/dist/text/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface TextProps extends HTMLAttributes<HTMLElement> {
|
|
|
7
7
|
font?: 'sans' | 'mono';
|
|
8
8
|
weight?: 'normal' | 'medium' | 'semibold' | 'bold';
|
|
9
9
|
variant?: 'default' | 'label';
|
|
10
|
+
className?: HTMLAttributes<HTMLElement>['class'];
|
|
10
11
|
children: Snippet;
|
|
11
12
|
}
|
|
12
13
|
export { default as Text } from './text.svelte';
|
package/dist/text/text.svelte
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
font?: 'sans' | 'mono';
|
|
11
11
|
weight?: 'normal' | 'medium' | 'semibold' | 'bold';
|
|
12
12
|
variant?: 'default' | 'label';
|
|
13
|
+
className?: HTMLAttributes<HTMLElement>['class'];
|
|
13
14
|
children: Snippet;
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -20,7 +21,8 @@
|
|
|
20
21
|
font = 'sans',
|
|
21
22
|
weight,
|
|
22
23
|
variant = 'default',
|
|
23
|
-
class:
|
|
24
|
+
class: classAttr,
|
|
25
|
+
className = classAttr,
|
|
24
26
|
children,
|
|
25
27
|
...rest
|
|
26
28
|
}: Props = $props();
|
|
@@ -7,6 +7,7 @@ interface Props extends HTMLAttributes<HTMLElement> {
|
|
|
7
7
|
font?: 'sans' | 'mono';
|
|
8
8
|
weight?: 'normal' | 'medium' | 'semibold' | 'bold';
|
|
9
9
|
variant?: 'default' | 'label';
|
|
10
|
+
className?: HTMLAttributes<HTMLElement>['class'];
|
|
10
11
|
children: Snippet;
|
|
11
12
|
}
|
|
12
13
|
declare const Text: import("svelte").Component<Props, {}, "">;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ClassValue, HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
export { createThemeController } from './theme-controller.svelte.js';
|
|
4
|
+
export type { ThemeMode, ThemeController, ThemeControllerOptions } from './theme-controller.svelte.js';
|
|
5
|
+
export { themeFlashScript } from './theme-flash.js';
|
|
6
|
+
import type { ThemeController, ThemeMode } from './theme-controller.svelte.js';
|
|
7
|
+
export interface ThemeToggleProps extends Omit<HTMLButtonAttributes, 'onclick' | 'onkeydown' | 'disabled' | 'class'> {
|
|
8
|
+
storageKey?: string;
|
|
9
|
+
size?: 'sm' | 'md' | 'lg';
|
|
10
|
+
controller?: ThemeController;
|
|
11
|
+
'aria-label'?: string;
|
|
12
|
+
sunIcon?: Snippet;
|
|
13
|
+
moonIcon?: Snippet;
|
|
14
|
+
onModeChange?: (mode: ThemeMode) => void;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
class?: ClassValue;
|
|
17
|
+
}
|
|
18
|
+
export { default as ThemeToggle } from './theme-toggle.svelte';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export type ThemeMode = 'system' | 'light' | 'dark';
|
|
2
|
+
export interface ThemeControllerOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Storage key used to persist the explicit theme preference.
|
|
5
|
+
* When the user selects system mode the key is removed.
|
|
6
|
+
* Defaults to `'dryui-theme'`.
|
|
7
|
+
*/
|
|
8
|
+
storageKey?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ThemeController {
|
|
11
|
+
/** Current stored preference: `'system'`, `'light'`, or `'dark'`. */
|
|
12
|
+
readonly mode: ThemeMode;
|
|
13
|
+
/**
|
|
14
|
+
* Whether the active rendered theme is dark. Tracks `prefers-color-scheme`
|
|
15
|
+
* when the mode is `'system'`.
|
|
16
|
+
*/
|
|
17
|
+
readonly isDark: boolean;
|
|
18
|
+
/** Whether the system color-scheme preference is currently dark. */
|
|
19
|
+
readonly systemPrefersDark: boolean;
|
|
20
|
+
/** Apply an explicit mode and persist it (or clear persistence for `'system'`). */
|
|
21
|
+
setMode(mode: ThemeMode): void;
|
|
22
|
+
/** Toggle between the two rendered themes, writing an explicit preference. */
|
|
23
|
+
cycle(): void;
|
|
24
|
+
/** Return to system mode and clear any persisted preference. */
|
|
25
|
+
reset(): void;
|
|
26
|
+
/** Stop watching `matchMedia` changes. Called automatically on HMR disposal. */
|
|
27
|
+
destroy(): void;
|
|
28
|
+
}
|
|
29
|
+
export declare const DARK_MEDIA_QUERY = "(prefers-color-scheme: dark)";
|
|
30
|
+
export declare const DEFAULT_STORAGE_KEY = "dryui-theme";
|
|
31
|
+
/**
|
|
32
|
+
* Read the stored theme mode. Exported for testing; production callers
|
|
33
|
+
* should go through `createThemeController`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function readStoredMode(storageKey: string): ThemeMode;
|
|
36
|
+
/**
|
|
37
|
+
* Persist the theme mode. When `mode === 'system'`, removes the key.
|
|
38
|
+
* Exported for testing.
|
|
39
|
+
*/
|
|
40
|
+
export declare function writeStoredMode(storageKey: string, mode: ThemeMode): void;
|
|
41
|
+
/**
|
|
42
|
+
* Apply the mode to `<html>` via `classList.theme-auto` and `dataset.theme`.
|
|
43
|
+
* Exported for testing.
|
|
44
|
+
*/
|
|
45
|
+
export declare function applyModeToDom(mode: ThemeMode): void;
|
|
46
|
+
/**
|
|
47
|
+
* Create a theme controller that reads the current preference from storage,
|
|
48
|
+
* applies it to `<html>`, and watches the system color-scheme for changes.
|
|
49
|
+
*
|
|
50
|
+
* The returned object exposes reactive `mode`, `isDark`, and `systemPrefersDark`
|
|
51
|
+
* properties backed by Svelte 5 `$state`, plus imperative methods for changing
|
|
52
|
+
* or resetting the mode.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createThemeController(options?: ThemeControllerOptions): ThemeController;
|