@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
|
@@ -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/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>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
className?: HTMLAttributes<HTMLDivElement>['class'];
|
|
5
|
+
children: Snippet;
|
|
6
|
+
}
|
|
7
|
+
declare const MenuGroup: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type MenuGroup = ReturnType<typeof MenuGroup>;
|
|
9
|
+
export default MenuGroup;
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
+
close: () => void;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
children: Snippet;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { className, close, disabled, children, onclick, onkeydown, ...rest }: Props = $props();
|
|
13
|
+
|
|
14
|
+
function handleClick(e: MouseEvent & { currentTarget: HTMLDivElement }) {
|
|
15
|
+
if (disabled) return;
|
|
16
|
+
if (onclick) {
|
|
17
|
+
(onclick as (event: MouseEvent & { currentTarget: HTMLDivElement }) => void)(e);
|
|
18
|
+
}
|
|
19
|
+
close();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function handleKeydown(e: KeyboardEvent & { currentTarget: HTMLDivElement }) {
|
|
23
|
+
if (disabled) return;
|
|
24
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
e.currentTarget.click();
|
|
27
|
+
}
|
|
28
|
+
if (onkeydown) {
|
|
29
|
+
(onkeydown as (event: KeyboardEvent & { currentTarget: HTMLDivElement }) => void)(e);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div
|
|
35
|
+
role="menuitem"
|
|
36
|
+
tabindex={disabled ? undefined : -1}
|
|
37
|
+
aria-disabled={disabled || undefined}
|
|
38
|
+
data-disabled={disabled || undefined}
|
|
39
|
+
class={className}
|
|
40
|
+
onclick={handleClick}
|
|
41
|
+
onkeydown={handleKeydown}
|
|
42
|
+
{...rest}
|
|
43
|
+
>
|
|
44
|
+
{@render children()}
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<style>
|
|
48
|
+
div {
|
|
49
|
+
display: grid;
|
|
50
|
+
grid-auto-flow: column;
|
|
51
|
+
grid-auto-columns: max-content;
|
|
52
|
+
align-items: center;
|
|
53
|
+
gap: var(--dry-space-2);
|
|
54
|
+
padding: var(--dry-menu-item-padding, var(--dry-space-2_5) var(--dry-space-2));
|
|
55
|
+
border-radius: var(
|
|
56
|
+
--dry-menu-item-radius,
|
|
57
|
+
min(var(--dry-control-radius, var(--dry-radius-sm)), var(--dry-space-4))
|
|
58
|
+
);
|
|
59
|
+
font-size: var(--dry-type-small-size, var(--dry-text-sm-size));
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
user-select: none;
|
|
62
|
+
outline: none;
|
|
63
|
+
color: var(--dry-color-text-strong);
|
|
64
|
+
min-height: var(--dry-space-11);
|
|
65
|
+
transition: background var(--dry-duration-fast) var(--dry-ease-default);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
div:hover:not([data-disabled]),
|
|
69
|
+
div:focus-visible {
|
|
70
|
+
background: var(--dry-color-fill);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
div:active:not([data-disabled]) {
|
|
74
|
+
background: var(--dry-color-fill-hover);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
div[data-disabled] {
|
|
78
|
+
color: var(--dry-color-text-disabled);
|
|
79
|
+
cursor: not-allowed;
|
|
80
|
+
pointer-events: none;
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
className?: HTMLAttributes<HTMLDivElement>['class'];
|
|
5
|
+
close: () => void;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
children: Snippet;
|
|
8
|
+
}
|
|
9
|
+
declare const MenuItem: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type MenuItem = ReturnType<typeof MenuItem>;
|
|
11
|
+
export default MenuItem;
|
|
@@ -0,0 +1,24 @@
|
|
|
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="presentation" class={className} {...rest}>
|
|
14
|
+
{@render children()}
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
div {
|
|
19
|
+
padding: var(--dry-space-1_5) var(--dry-space-2);
|
|
20
|
+
font-size: var(--dry-type-tiny-size, var(--dry-text-xs-size));
|
|
21
|
+
color: var(--dry-color-text-weak);
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
className?: HTMLAttributes<HTMLDivElement>['class'];
|
|
5
|
+
children: Snippet;
|
|
6
|
+
}
|
|
7
|
+
declare const MenuLabel: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type MenuLabel = ReturnType<typeof MenuLabel>;
|
|
9
|
+
export default MenuLabel;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface MenuRootState {
|
|
2
|
+
readonly open: boolean;
|
|
3
|
+
readonly triggerId: string;
|
|
4
|
+
readonly contentId: string;
|
|
5
|
+
triggerEl: HTMLElement | null;
|
|
6
|
+
show: () => void;
|
|
7
|
+
close: () => void;
|
|
8
|
+
toggle: () => void;
|
|
9
|
+
}
|
|
10
|
+
export interface MenuPosition {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
}
|
|
14
|
+
export interface PositionedMenuRootState extends MenuRootState {
|
|
15
|
+
position: MenuPosition;
|
|
16
|
+
}
|
|
17
|
+
interface CreateMenuRootStateOptions {
|
|
18
|
+
idBase: string;
|
|
19
|
+
getOpen: () => boolean;
|
|
20
|
+
setOpen: (value: boolean) => void;
|
|
21
|
+
}
|
|
22
|
+
export declare function createMenuRootState(options: CreateMenuRootStateOptions): MenuRootState;
|
|
23
|
+
export declare function createPositionedMenuRootState(options: CreateMenuRootStateOptions): PositionedMenuRootState;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { generateFormId } from '@dryui/primitives';
|
|
2
|
+
function createBaseMenuRootState(options) {
|
|
3
|
+
const triggerId = generateFormId(`${options.idBase}-trigger`);
|
|
4
|
+
const contentId = generateFormId(`${options.idBase}-content`);
|
|
5
|
+
return {
|
|
6
|
+
triggerId,
|
|
7
|
+
contentId,
|
|
8
|
+
triggerEl: null,
|
|
9
|
+
show() {
|
|
10
|
+
options.setOpen(true);
|
|
11
|
+
},
|
|
12
|
+
close() {
|
|
13
|
+
options.setOpen(false);
|
|
14
|
+
},
|
|
15
|
+
toggle() {
|
|
16
|
+
options.setOpen(!options.getOpen());
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function createMenuRootState(options) {
|
|
21
|
+
return {
|
|
22
|
+
get open() {
|
|
23
|
+
return options.getOpen();
|
|
24
|
+
},
|
|
25
|
+
...createBaseMenuRootState(options)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function createPositionedMenuRootState(options) {
|
|
29
|
+
let position = $state({ x: 0, y: 0 });
|
|
30
|
+
return {
|
|
31
|
+
get open() {
|
|
32
|
+
return options.getOpen();
|
|
33
|
+
},
|
|
34
|
+
...createBaseMenuRootState(options),
|
|
35
|
+
get position() {
|
|
36
|
+
return position;
|
|
37
|
+
},
|
|
38
|
+
set position(value) {
|
|
39
|
+
position = value;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
|
|
4
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
className?: HTMLAttributes<HTMLDivElement>['class'];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let { className, ...rest }: Props = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<div role="separator" class={className} {...rest}></div>
|
|
12
|
+
|
|
13
|
+
<style>
|
|
14
|
+
div {
|
|
15
|
+
height: 1px;
|
|
16
|
+
background: var(--dry-color-stroke-weak);
|
|
17
|
+
margin: var(--dry-space-1) 0;
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
className?: HTMLAttributes<HTMLDivElement>['class'];
|
|
4
|
+
}
|
|
5
|
+
declare const MenuSeparator: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type MenuSeparator = ReturnType<typeof MenuSeparator>;
|
|
7
|
+
export default MenuSeparator;
|
package/dist/internal/motion.js
CHANGED
|
@@ -11,8 +11,19 @@ export function supportsScrollTimelines() {
|
|
|
11
11
|
return (CSS.supports('animation-timeline: view()') || CSS.supports('scroll-timeline-name: --dry-scroll'));
|
|
12
12
|
}
|
|
13
13
|
export function extractThemeColor(property, element) {
|
|
14
|
+
if (typeof document === 'undefined') {
|
|
15
|
+
return [0, 0, 0];
|
|
16
|
+
}
|
|
17
|
+
const readComputedStyle = typeof getComputedStyle === 'function'
|
|
18
|
+
? getComputedStyle
|
|
19
|
+
: typeof window !== 'undefined' && typeof window.getComputedStyle === 'function'
|
|
20
|
+
? window.getComputedStyle.bind(window)
|
|
21
|
+
: null;
|
|
22
|
+
if (!readComputedStyle) {
|
|
23
|
+
return [0, 0, 0];
|
|
24
|
+
}
|
|
14
25
|
const el = element ?? document.documentElement;
|
|
15
|
-
const value =
|
|
26
|
+
const value = readComputedStyle(el).getPropertyValue(property).trim();
|
|
16
27
|
// Parse hex (#rgb, #rrggbb)
|
|
17
28
|
const hexMatch = value.match(/^#([0-9a-f]{3,8})$/i);
|
|
18
29
|
if (hexMatch) {
|