@dryui/ui 1.9.0 → 2.0.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/alert-dialog/alert-dialog-root.svelte +2 -2
- package/dist/avatar/avatar.svelte +2 -0
- package/dist/badge/badge.svelte +34 -32
- package/dist/button/button.svelte +67 -38
- package/dist/chromatic-aberration/chromatic-aberration.svelte +2 -2
- package/dist/collapsible/collapsible-root.svelte +3 -2
- package/dist/collapsible/context.svelte.d.ts +1 -2
- package/dist/collapsible/context.svelte.js +1 -2
- package/dist/color-picker/color-picker-channel-input.svelte +1 -0
- package/dist/combobox/combobox-content.svelte +1 -0
- package/dist/combobox/combobox-input-root.svelte +3 -3
- package/dist/command-palette/command-palette-dialog-root.svelte +3 -3
- package/dist/command-palette/command-palette-item.svelte +3 -3
- package/dist/context-menu/context-menu-root.svelte +2 -0
- package/dist/date-field/date-field-segment.svelte +26 -4
- package/dist/date-picker/datepicker-input-root.svelte +2 -0
- package/dist/date-range-picker/date-range-picker-root.svelte +2 -0
- package/dist/dialog/dialog-root.svelte +2 -2
- package/dist/drag-and-drop/drag-and-drop-root.svelte +34 -3
- package/dist/drawer/drawer-root.svelte +2 -2
- package/dist/dropdown-menu/dropdown-menu-root.svelte +2 -0
- package/dist/field/field-root.svelte +3 -2
- package/dist/file-select/file-select-root.svelte +1 -0
- package/dist/file-upload/file-upload-item.svelte +1 -0
- package/dist/heading/heading.svelte +6 -2
- package/dist/image/image.svelte +2 -0
- package/dist/internal/date-family-controller.svelte.d.ts +2 -1
- package/dist/internal/date-family-controller.svelte.js +4 -4
- package/dist/internal/menu-root-state.svelte.d.ts +1 -0
- package/dist/internal/menu-root-state.svelte.js +2 -3
- package/dist/internal/modal-content.svelte +2 -0
- package/dist/internal/picker-popover-content.svelte +1 -0
- package/dist/link-preview/link-preview-root.svelte +3 -3
- package/dist/logo-mark/logo-mark.svelte +1 -0
- package/dist/markdown-renderer/markdown-renderer.svelte +9 -3
- package/dist/markdown-renderer/markdown-renderer.svelte.d.ts +1 -1
- package/dist/mega-menu/mega-menu-item.svelte +4 -4
- package/dist/menubar/menubar-content.svelte +1 -0
- package/dist/menubar/menubar-menu.svelte +2 -2
- package/dist/menubar/menubar-root.svelte +1 -0
- package/dist/multi-select-combobox/multi-select-combobox-content.svelte +1 -0
- package/dist/multi-select-combobox/multi-select-combobox-item.svelte +2 -2
- package/dist/multi-select-combobox/multi-select-combobox-root-input.svelte +4 -3
- package/dist/navigation-menu/context.svelte.d.ts +0 -2
- package/dist/navigation-menu/context.svelte.js +1 -2
- package/dist/navigation-menu/navigation-menu-item.svelte +5 -8
- package/dist/notification-center/notification-center-root.svelte +3 -3
- package/dist/popover/popover-root.svelte +3 -3
- package/dist/radio-group/radio-group.svelte +2 -2
- package/dist/rich-text-editor/rich-text-editor-content.svelte +14 -6
- package/dist/rich-text-editor/rich-text-editor-root.svelte +19 -9
- package/dist/rich-text-editor/rich-text-editor-root.svelte.d.ts +1 -0
- package/dist/rich-text-editor/rich-text-editor-toolbar-button-input.svelte +1 -0
- package/dist/select/select-root-input.svelte +3 -3
- package/dist/tags-input/tags-input-root.svelte +1 -0
- package/dist/timeline/timeline-title.svelte +6 -0
- package/dist/toast/toast-root.svelte +1 -0
- package/dist/toolbar/toolbar-root.svelte +1 -0
- package/dist/tooltip/tooltip-root.svelte +3 -3
- package/dist/video-embed/video-embed-button.svelte +1 -0
- package/package.json +3 -3
- package/skills/dryui/SKILL.md +4 -1
- package/skills/dryui/rules/composition.md +1 -1
- package/skills/dryui/rules/theming.md +2 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { onDestroy } from 'svelte';
|
|
2
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
4
|
import { getDateFieldCtx, type DateSegmentType } from './context.svelte.js';
|
|
4
5
|
|
|
@@ -25,12 +26,31 @@
|
|
|
25
26
|
);
|
|
26
27
|
|
|
27
28
|
let inputBuffer = '';
|
|
28
|
-
let
|
|
29
|
+
let segmentEl: HTMLSpanElement | undefined;
|
|
30
|
+
let bufferTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
31
|
+
|
|
32
|
+
function clearBufferTimeout() {
|
|
33
|
+
if (bufferTimeout === undefined) return;
|
|
34
|
+
clearTimeout(bufferTimeout);
|
|
35
|
+
bufferTimeout = undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function resetInputBuffer() {
|
|
39
|
+
clearBufferTimeout();
|
|
40
|
+
inputBuffer = '';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onDestroy(resetInputBuffer);
|
|
29
44
|
|
|
30
45
|
function registerSegment(node: HTMLSpanElement) {
|
|
46
|
+
segmentEl = node;
|
|
31
47
|
ctx.registerSegment(type, node);
|
|
48
|
+
node.addEventListener('blur', resetInputBuffer);
|
|
32
49
|
return {
|
|
33
50
|
destroy() {
|
|
51
|
+
node.removeEventListener('blur', resetInputBuffer);
|
|
52
|
+
resetInputBuffer();
|
|
53
|
+
if (segmentEl === node) segmentEl = undefined;
|
|
34
54
|
ctx.unregisterSegment(type);
|
|
35
55
|
}
|
|
36
56
|
};
|
|
@@ -77,21 +97,21 @@
|
|
|
77
97
|
break;
|
|
78
98
|
case 'Backspace': {
|
|
79
99
|
e.preventDefault();
|
|
80
|
-
|
|
100
|
+
resetInputBuffer();
|
|
81
101
|
ctx.updateSegment(type, minValue);
|
|
82
102
|
break;
|
|
83
103
|
}
|
|
84
104
|
default: {
|
|
85
105
|
if (/^\d$/.test(e.key)) {
|
|
86
106
|
e.preventDefault();
|
|
87
|
-
|
|
107
|
+
clearBufferTimeout();
|
|
88
108
|
inputBuffer += e.key;
|
|
89
109
|
const num = parseInt(inputBuffer, 10);
|
|
90
110
|
const maxDigits = type === 'year' ? 4 : 2;
|
|
91
111
|
|
|
92
112
|
if (inputBuffer.length >= maxDigits || num > maxValue) {
|
|
93
113
|
ctx.updateSegment(type, Math.min(Math.max(num, minValue), maxValue));
|
|
94
|
-
|
|
114
|
+
resetInputBuffer();
|
|
95
115
|
// Auto-advance to next segment
|
|
96
116
|
if (type !== 'year') {
|
|
97
117
|
ctx.focusSegment(type, 'next');
|
|
@@ -100,6 +120,8 @@
|
|
|
100
120
|
ctx.updateSegment(type, num);
|
|
101
121
|
bufferTimeout = setTimeout(() => {
|
|
102
122
|
inputBuffer = '';
|
|
123
|
+
bufferTimeout = undefined;
|
|
124
|
+
if (document.activeElement !== segmentEl) return;
|
|
103
125
|
if (type !== 'year') {
|
|
104
126
|
ctx.focusSegment(type, 'next');
|
|
105
127
|
}
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
disabled = false,
|
|
28
28
|
children
|
|
29
29
|
}: Props = $props();
|
|
30
|
+
const uid = $props.id();
|
|
30
31
|
|
|
31
32
|
const view = createDateViewController({
|
|
32
33
|
initialDate: value,
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
const popover = createPickerPopoverController({
|
|
37
38
|
triggerIdPrefix: 'datepicker-trigger',
|
|
38
39
|
contentIdPrefix: 'datepicker-content',
|
|
40
|
+
uid,
|
|
39
41
|
open: () => open,
|
|
40
42
|
setOpen: (nextOpen) => {
|
|
41
43
|
open = nextOpen;
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
disabled = false,
|
|
28
28
|
children
|
|
29
29
|
}: Props = $props();
|
|
30
|
+
const uid = $props.id();
|
|
30
31
|
|
|
31
32
|
const view = createDateViewController({
|
|
32
33
|
initialDate: startDate,
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
const popover = createPickerPopoverController({
|
|
43
44
|
triggerIdPrefix: 'date-range-picker-trigger',
|
|
44
45
|
contentIdPrefix: 'date-range-picker-content',
|
|
46
|
+
uid,
|
|
45
47
|
open: () => open,
|
|
46
48
|
setOpen: (nextOpen) => {
|
|
47
49
|
open = nextOpen;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { generateFormId } from '@dryui/primitives';
|
|
4
3
|
import { setDialogCtx } from './context.svelte.js';
|
|
5
4
|
|
|
6
5
|
interface Props {
|
|
@@ -10,7 +9,8 @@
|
|
|
10
9
|
|
|
11
10
|
let { open = $bindable(false), children }: Props = $props();
|
|
12
11
|
|
|
13
|
-
const
|
|
12
|
+
const uid = $props.id();
|
|
13
|
+
const headerId = `dialog-${uid}`;
|
|
14
14
|
|
|
15
15
|
setDialogCtx({
|
|
16
16
|
get open() {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts" generics="T">
|
|
2
|
-
import { flushSync } from 'svelte';
|
|
2
|
+
import { flushSync, onDestroy } from 'svelte';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
4
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
-
import {
|
|
5
|
+
import { mergeIds } from '@dryui/primitives';
|
|
6
6
|
import { setDragAndDropCtx } from './context.svelte.js';
|
|
7
7
|
import { getGroupCtx } from './group-context.svelte.js';
|
|
8
8
|
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
let crossListIndex: number | null = null;
|
|
49
49
|
|
|
50
50
|
const groupCtx = getGroupCtx();
|
|
51
|
-
const
|
|
51
|
+
const uid = $props.id();
|
|
52
|
+
const instructionsId = `dry-dnd-instructions-${uid}`;
|
|
52
53
|
|
|
53
54
|
let keyboardInstructions = $derived.by(() => {
|
|
54
55
|
const arrowKeys =
|
|
@@ -172,6 +173,7 @@
|
|
|
172
173
|
|
|
173
174
|
const clone = draggedEl.cloneNode(true) as HTMLElement;
|
|
174
175
|
clone.setAttribute('data-dnd-preview', '');
|
|
176
|
+
scrubPreviewClone(clone);
|
|
175
177
|
clone.removeAttribute('data-index');
|
|
176
178
|
clone.removeAttribute('data-dragging');
|
|
177
179
|
clone.removeAttribute('data-drag-active');
|
|
@@ -204,6 +206,33 @@
|
|
|
204
206
|
updatePreviewPosition();
|
|
205
207
|
}
|
|
206
208
|
|
|
209
|
+
function scrubPreviewClone(clone: HTMLElement) {
|
|
210
|
+
clone.setAttribute('aria-hidden', 'true');
|
|
211
|
+
clone.setAttribute('inert', '');
|
|
212
|
+
clone.removeAttribute('id');
|
|
213
|
+
|
|
214
|
+
for (const el of clone.querySelectorAll<HTMLElement>('[id]')) {
|
|
215
|
+
el.removeAttribute('id');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const relationshipAttrs = [
|
|
219
|
+
'for',
|
|
220
|
+
'aria-activedescendant',
|
|
221
|
+
'aria-controls',
|
|
222
|
+
'aria-describedby',
|
|
223
|
+
'aria-details',
|
|
224
|
+
'aria-labelledby',
|
|
225
|
+
'aria-owns'
|
|
226
|
+
];
|
|
227
|
+
const selector = relationshipAttrs.map((attr) => `[${attr}]`).join(',');
|
|
228
|
+
|
|
229
|
+
for (const el of clone.querySelectorAll<HTMLElement>(selector)) {
|
|
230
|
+
for (const attr of relationshipAttrs) {
|
|
231
|
+
el.removeAttribute(attr);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
207
236
|
function updatePreviewPosition() {
|
|
208
237
|
if (!previewEl) return;
|
|
209
238
|
const dx = pointerX - startX;
|
|
@@ -358,6 +387,8 @@
|
|
|
358
387
|
}
|
|
359
388
|
}
|
|
360
389
|
|
|
390
|
+
onDestroy(removePreview);
|
|
391
|
+
|
|
361
392
|
function handlePointerMove(e: PointerEvent) {
|
|
362
393
|
if (isAnimating) return;
|
|
363
394
|
if (!isPending && !isDragging) return;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { generateFormId } from '@dryui/primitives';
|
|
4
3
|
import { setDrawerCtx } from './context.svelte.js';
|
|
5
4
|
|
|
6
5
|
interface Props {
|
|
@@ -11,7 +10,8 @@
|
|
|
11
10
|
|
|
12
11
|
let { open = $bindable(false), side = 'right', children }: Props = $props();
|
|
13
12
|
|
|
14
|
-
const
|
|
13
|
+
const uid = $props.id();
|
|
14
|
+
const headerId = `drawer-${uid}`;
|
|
15
15
|
|
|
16
16
|
setDrawerCtx({
|
|
17
17
|
get open() {
|
|
@@ -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 { setFormControlCtx
|
|
4
|
+
import { setFormControlCtx } from '@dryui/primitives';
|
|
5
5
|
|
|
6
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
7
|
children: Snippet;
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
...rest
|
|
22
22
|
}: Props = $props();
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const uid = $props.id();
|
|
25
|
+
const id = `field-${uid}`;
|
|
25
26
|
let hasDescription = $state(false);
|
|
26
27
|
let hasErrorMessage = $state(false);
|
|
27
28
|
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
padding: var(--dry-space-2) var(--dry-space-3);
|
|
86
86
|
font-family: var(--dry-font-sans);
|
|
87
87
|
background: var(--dry-color-bg-raised);
|
|
88
|
+
/* dryui-allow solid-border-on-raised: file select is a form control and needs a persistent field edge. */
|
|
88
89
|
border: 1px solid var(--dry-color-stroke-strong);
|
|
89
90
|
border-radius: var(--dry-radius-md);
|
|
90
91
|
transition:
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
font-family: var(--dry-font-sans);
|
|
28
28
|
color: var(--dry-color-text-strong);
|
|
29
29
|
background: var(--dry-color-bg-raised);
|
|
30
|
+
/* dryui-allow solid-border-on-raised: uploaded file rows need a visible item boundary in dense lists. */
|
|
30
31
|
border: 1px solid var(--dry-color-stroke-weak);
|
|
31
32
|
border-radius: var(--dry-radius-md);
|
|
32
33
|
}
|
|
@@ -27,26 +27,32 @@
|
|
|
27
27
|
</script>
|
|
28
28
|
|
|
29
29
|
{#if level === 1}
|
|
30
|
+
<!-- dryui-allow raw-heading: Heading is the canonical component that renders semantic h1-h6 output. -->
|
|
30
31
|
<h1 class={className} {...variantAttrs({ level, variant, measure })} {...rest}>
|
|
31
32
|
{@render children()}
|
|
32
33
|
</h1>
|
|
33
34
|
{:else if level === 2}
|
|
35
|
+
<!-- dryui-allow raw-heading: Heading is the canonical component that renders semantic h1-h6 output. -->
|
|
34
36
|
<h2 class={className} {...variantAttrs({ level, variant, measure })} {...rest}>
|
|
35
37
|
{@render children()}
|
|
36
38
|
</h2>
|
|
37
39
|
{:else if level === 3}
|
|
40
|
+
<!-- dryui-allow raw-heading: Heading is the canonical component that renders semantic h1-h6 output. -->
|
|
38
41
|
<h3 class={className} {...variantAttrs({ level, variant, measure })} {...rest}>
|
|
39
42
|
{@render children()}
|
|
40
43
|
</h3>
|
|
41
44
|
{:else if level === 4}
|
|
45
|
+
<!-- dryui-allow raw-heading: Heading is the canonical component that renders semantic h1-h6 output. -->
|
|
42
46
|
<h4 class={className} {...variantAttrs({ level, variant, measure })} {...rest}>
|
|
43
47
|
{@render children()}
|
|
44
48
|
</h4>
|
|
45
49
|
{:else if level === 5}
|
|
50
|
+
<!-- dryui-allow raw-heading: Heading is the canonical component that renders semantic h1-h6 output. -->
|
|
46
51
|
<h5 class={className} {...variantAttrs({ level, variant, measure })} {...rest}>
|
|
47
52
|
{@render children()}
|
|
48
53
|
</h5>
|
|
49
54
|
{:else}
|
|
55
|
+
<!-- dryui-allow raw-heading: Heading is the canonical component that renders semantic h1-h6 output. -->
|
|
50
56
|
<h6 class={className} {...variantAttrs({ level, variant, measure })} {...rest}>
|
|
51
57
|
{@render children()}
|
|
52
58
|
</h6>
|
|
@@ -64,7 +70,6 @@
|
|
|
64
70
|
font-family: var(--dry-font-sans);
|
|
65
71
|
font-weight: 700;
|
|
66
72
|
line-height: var(--dry-type-heading-2-leading, 2.5rem);
|
|
67
|
-
letter-spacing: -0.03em;
|
|
68
73
|
text-wrap: balance;
|
|
69
74
|
}
|
|
70
75
|
|
|
@@ -102,7 +107,6 @@
|
|
|
102
107
|
font-family: var(--dry-font-display, var(--dry-font-sans));
|
|
103
108
|
font-size: var(--dry-type-display-size, var(--dry-text-4xl-size, 2.25rem));
|
|
104
109
|
line-height: var(--dry-type-display-leading, 4rem);
|
|
105
|
-
letter-spacing: -0.04em;
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
/* ── Measure (max-inline-size) ─────────────────────────────────────────────
|
package/dist/image/image.svelte
CHANGED
|
@@ -37,8 +37,10 @@
|
|
|
37
37
|
{#if status === 'error' && fallbackSnippet}
|
|
38
38
|
{@render fallbackSnippet()}
|
|
39
39
|
{:else if status === 'error' && fallback}
|
|
40
|
+
<!-- dryui-allow raw-img: Image is the canonical component that renders the underlying img element. -->
|
|
40
41
|
<img class={className} src={fallback} {alt} data-state="fallback" {...rest} />
|
|
41
42
|
{:else}
|
|
43
|
+
<!-- dryui-allow raw-img: Image is the canonical component that renders the underlying img element. -->
|
|
42
44
|
<img
|
|
43
45
|
class={className}
|
|
44
46
|
{src}
|
|
@@ -18,6 +18,7 @@ export declare function createDateViewController({ initialDate, locale }: DateVi
|
|
|
18
18
|
interface PickerPopoverControllerConfig {
|
|
19
19
|
triggerIdPrefix: string;
|
|
20
20
|
contentIdPrefix: string;
|
|
21
|
+
uid: string;
|
|
21
22
|
open: () => boolean;
|
|
22
23
|
setOpen: (open: boolean) => void;
|
|
23
24
|
disabled: () => boolean;
|
|
@@ -33,7 +34,7 @@ export interface PickerPopoverController {
|
|
|
33
34
|
close: () => void;
|
|
34
35
|
toggle: () => void;
|
|
35
36
|
}
|
|
36
|
-
export declare function createPickerPopoverController({ triggerIdPrefix, contentIdPrefix, open, setOpen, disabled, onShow, onClose }: PickerPopoverControllerConfig): {
|
|
37
|
+
export declare function createPickerPopoverController({ triggerIdPrefix, contentIdPrefix, uid, open, setOpen, disabled, onShow, onClose }: PickerPopoverControllerConfig): {
|
|
37
38
|
readonly triggerId: string;
|
|
38
39
|
readonly contentId: string;
|
|
39
40
|
readonly triggerEl: HTMLElement | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getWeekStartDay } from '@dryui/primitives';
|
|
2
2
|
import { SvelteDate } from 'svelte/reactivity';
|
|
3
3
|
export function createDateViewController({ initialDate = null, locale }) {
|
|
4
4
|
const seedDate = initialDate ? new SvelteDate(initialDate.getTime()) : new SvelteDate();
|
|
@@ -56,9 +56,9 @@ export function createDateViewController({ initialDate = null, locale }) {
|
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
|
-
export function createPickerPopoverController({ triggerIdPrefix, contentIdPrefix, open, setOpen, disabled, onShow, onClose }) {
|
|
60
|
-
const triggerId =
|
|
61
|
-
const contentId =
|
|
59
|
+
export function createPickerPopoverController({ triggerIdPrefix, contentIdPrefix, uid, open, setOpen, disabled, onShow, onClose }) {
|
|
60
|
+
const triggerId = `${triggerIdPrefix}-${uid}`;
|
|
61
|
+
const contentId = `${contentIdPrefix}-${uid}`;
|
|
62
62
|
let triggerEl = $state(null);
|
|
63
63
|
return {
|
|
64
64
|
get triggerId() {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { generateFormId } from '@dryui/primitives';
|
|
2
1
|
function createBaseMenuRootState(options) {
|
|
3
|
-
const triggerId =
|
|
4
|
-
const contentId =
|
|
2
|
+
const triggerId = `${options.idBase}-trigger-${options.uid}`;
|
|
3
|
+
const contentId = `${options.idBase}-content-${options.uid}`;
|
|
5
4
|
return {
|
|
6
5
|
triggerId,
|
|
7
6
|
contentId,
|
|
@@ -319,6 +319,7 @@
|
|
|
319
319
|
|
|
320
320
|
[data-modal-content][data-variant='drawer'][data-side='top'] [data-modal-panel] {
|
|
321
321
|
--_drawer-rest-transform: translateY(0);
|
|
322
|
+
/* dryui-allow symmetric-exit-animation: this is the off-canvas enter position for a top drawer, not the exit animation. */
|
|
322
323
|
--_drawer-enter-transform: translateY(-100%);
|
|
323
324
|
grid-row: 1;
|
|
324
325
|
height: var(--dry-drawer-size);
|
|
@@ -327,6 +328,7 @@
|
|
|
327
328
|
|
|
328
329
|
[data-modal-content][data-variant='drawer'][data-side='bottom'] [data-modal-panel] {
|
|
329
330
|
--_drawer-rest-transform: translateY(0);
|
|
331
|
+
/* dryui-allow symmetric-exit-animation: this is the off-canvas enter position for a bottom drawer, not the exit animation. */
|
|
330
332
|
--_drawer-enter-transform: translateY(100%);
|
|
331
333
|
grid-row: 2;
|
|
332
334
|
height: var(--dry-drawer-size);
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
margin: 0;
|
|
83
83
|
display: inline-grid;
|
|
84
84
|
padding: var(--dry-space-3);
|
|
85
|
+
/* dryui-allow solid-border-on-raised: date picker popovers need a clear calendar boundary. */
|
|
85
86
|
border: 1px solid var(--dry-color-stroke-weak);
|
|
86
87
|
border-radius: var(--dry-radius-lg);
|
|
87
88
|
background: var(--dry-color-bg-overlay);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { generateFormId } from '@dryui/primitives';
|
|
4
3
|
import { setLinkPreviewCtx } from './context.svelte.js';
|
|
5
4
|
|
|
6
5
|
interface Props {
|
|
@@ -12,8 +11,9 @@
|
|
|
12
11
|
|
|
13
12
|
let { open = $bindable(false), openDelay = 700, closeDelay = 300, children }: Props = $props();
|
|
14
13
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
14
|
+
const uid = $props.id();
|
|
15
|
+
const triggerId = `link-preview-trigger-${uid}`;
|
|
16
|
+
const contentId = `link-preview-content-${uid}`;
|
|
17
17
|
|
|
18
18
|
let openTimeout: ReturnType<typeof setTimeout>;
|
|
19
19
|
let closeTimeout: ReturnType<typeof setTimeout>;
|
|
@@ -5,22 +5,28 @@
|
|
|
5
5
|
import { Separator } from '../separator/index.js';
|
|
6
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
7
|
content: string;
|
|
8
|
-
|
|
8
|
+
dangerouslyAllowRawHtml?: boolean;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
let { content,
|
|
11
|
+
let { content, dangerouslyAllowRawHtml = false, class: className, ...rest }: Props = $props();
|
|
12
12
|
|
|
13
|
-
const nodes = $derived(parseMarkdownToAst(content, { sanitize }));
|
|
13
|
+
const nodes = $derived(parseMarkdownToAst(content, { sanitize: !dangerouslyAllowRawHtml }));
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
16
|
{#snippet renderNodes(items: MarkdownNode[])}
|
|
17
17
|
{#each items as node}
|
|
18
18
|
{#if node.type === 'heading'}
|
|
19
|
+
<!-- dryui-allow raw-heading: MarkdownRenderer maps parsed markdown heading nodes to their semantic HTML tag. -->
|
|
19
20
|
{#if node.level === 1}<h1>{@html node.content}</h1>
|
|
21
|
+
<!-- dryui-allow raw-heading: MarkdownRenderer maps parsed markdown heading nodes to their semantic HTML tag. -->
|
|
20
22
|
{:else if node.level === 2}<h2>{@html node.content}</h2>
|
|
23
|
+
<!-- dryui-allow raw-heading: MarkdownRenderer maps parsed markdown heading nodes to their semantic HTML tag. -->
|
|
21
24
|
{:else if node.level === 3}<h3>{@html node.content}</h3>
|
|
25
|
+
<!-- dryui-allow raw-heading: MarkdownRenderer maps parsed markdown heading nodes to their semantic HTML tag. -->
|
|
22
26
|
{:else if node.level === 4}<h4>{@html node.content}</h4>
|
|
27
|
+
<!-- dryui-allow raw-heading: MarkdownRenderer maps parsed markdown heading nodes to their semantic HTML tag. -->
|
|
23
28
|
{:else if node.level === 5}<h5>{@html node.content}</h5>
|
|
29
|
+
<!-- dryui-allow raw-heading: MarkdownRenderer maps parsed markdown heading nodes to their semantic HTML tag. -->
|
|
24
30
|
{:else}<h6>{@html node.content}</h6>
|
|
25
31
|
{/if}
|
|
26
32
|
{:else if node.type === 'paragraph'}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
2
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
3
3
|
content: string;
|
|
4
|
-
|
|
4
|
+
dangerouslyAllowRawHtml?: boolean;
|
|
5
5
|
}
|
|
6
6
|
declare const MarkdownRenderer: import("svelte").Component<Props, {}, "">;
|
|
7
7
|
type MarkdownRenderer = ReturnType<typeof MarkdownRenderer>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import { generateFormId } from '@dryui/primitives';
|
|
5
4
|
import { getMegaMenuCtx, setMegaMenuItemCtx } from './context.svelte.js';
|
|
6
5
|
|
|
7
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -11,9 +10,10 @@
|
|
|
11
10
|
let { class: className, children, ...rest }: Props = $props();
|
|
12
11
|
|
|
13
12
|
const ctx = getMegaMenuCtx();
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
13
|
+
const uid = $props.id();
|
|
14
|
+
const itemId = `mm-item-${uid}`;
|
|
15
|
+
const triggerId = `mm-trigger-${uid}`;
|
|
16
|
+
const panelId = `mm-panel-${uid}`;
|
|
17
17
|
|
|
18
18
|
setMegaMenuItemCtx({
|
|
19
19
|
itemId,
|
|
@@ -123,6 +123,7 @@
|
|
|
123
123
|
|
|
124
124
|
background: var(--dry-color-bg-overlay);
|
|
125
125
|
color: var(--dry-color-text-strong);
|
|
126
|
+
/* dryui-allow solid-border-on-raised: menu popover keeps a visible edge while floating above varied content. */
|
|
126
127
|
border: 1px solid var(--dry-color-stroke-weak);
|
|
127
128
|
border-radius: var(--dry-radius-popover);
|
|
128
129
|
box-shadow: var(--dry-shadow-overlay);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
|
-
import { generateFormId } from '@dryui/primitives';
|
|
5
4
|
import { getMenubarCtx, setMenubarMenuCtx } from './context.svelte.js';
|
|
6
5
|
|
|
7
6
|
interface Props {
|
|
@@ -10,7 +9,8 @@
|
|
|
10
9
|
|
|
11
10
|
let { children }: Props = $props();
|
|
12
11
|
|
|
13
|
-
const
|
|
12
|
+
const uid = $props.id();
|
|
13
|
+
const menuId = `menubar-menu-${uid}`;
|
|
14
14
|
const ctx = getMenubarCtx();
|
|
15
15
|
|
|
16
16
|
onMount(() => {
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
gap: var(--dry-space-1);
|
|
83
83
|
padding: var(--dry-space-1);
|
|
84
84
|
background: var(--dry-color-bg-overlay);
|
|
85
|
+
/* dryui-allow solid-border-on-raised: menubar root presents a persistent command strip boundary. */
|
|
85
86
|
border: 1px solid var(--dry-color-stroke-weak);
|
|
86
87
|
border-radius: var(--dry-radius-lg);
|
|
87
88
|
}
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
margin: 0;
|
|
88
88
|
grid-template-columns: minmax(anchor-size(inline), max-content);
|
|
89
89
|
background: var(--dry-color-bg-overlay);
|
|
90
|
+
/* dryui-allow solid-border-on-raised: popover menu keeps an explicit edge for contrast against busy app surfaces. */
|
|
90
91
|
border: 1px solid var(--dry-color-stroke-weak);
|
|
91
92
|
border-radius: var(--dry-radius-md);
|
|
92
93
|
box-shadow: var(--dry-shadow-lg);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import { generateFormId } from '@dryui/primitives';
|
|
5
4
|
import { getMultiSelectComboboxCtx } from './context.svelte.js';
|
|
6
5
|
|
|
7
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -24,7 +23,8 @@
|
|
|
24
23
|
}: Props = $props();
|
|
25
24
|
|
|
26
25
|
const ctx = getMultiSelectComboboxCtx();
|
|
27
|
-
const
|
|
26
|
+
const uid = $props.id();
|
|
27
|
+
const id = `multi-select-combobox-item-${uid}`;
|
|
28
28
|
|
|
29
29
|
const isSelected = $derived(ctx.isSelected(value));
|
|
30
30
|
const isUnavailable = $derived(disabled || !ctx.canSelect(value));
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { untrack } from 'svelte';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
4
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
-
import { generateFormId } from '@dryui/primitives';
|
|
6
5
|
import { setMultiSelectComboboxCtx } from './context.svelte.js';
|
|
7
6
|
|
|
8
7
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -31,8 +30,9 @@
|
|
|
31
30
|
...rest
|
|
32
31
|
}: Props = $props();
|
|
33
32
|
|
|
34
|
-
const
|
|
35
|
-
const
|
|
33
|
+
const uid = $props.id();
|
|
34
|
+
const inputId = `multi-select-combobox-input-${uid}`;
|
|
35
|
+
const contentId = `multi-select-combobox-content-${uid}`;
|
|
36
36
|
|
|
37
37
|
let rootEl = $state<HTMLDivElement | null>(null);
|
|
38
38
|
let inputEl = $state<HTMLInputElement | null>(null);
|
|
@@ -251,6 +251,7 @@
|
|
|
251
251
|
justify-content: start;
|
|
252
252
|
gap: var(--dry-space-1_5);
|
|
253
253
|
padding: var(--dry-space-2);
|
|
254
|
+
/* dryui-allow solid-border-on-raised: composite input needs a persistent field edge plus raised fill for token contrast. */
|
|
254
255
|
border: 1px solid var(--dry-color-stroke-strong);
|
|
255
256
|
border-radius: var(--dry-radius-md);
|
|
256
257
|
background: var(--dry-color-bg-raised);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { generateFormId } from '@dryui/primitives';
|
|
2
1
|
export interface NavigationMenuContext {
|
|
3
2
|
readonly activeItem: string | null;
|
|
4
3
|
openItem: (id: string) => void;
|
|
@@ -12,4 +11,3 @@ export interface NavigationMenuItemContext {
|
|
|
12
11
|
readonly open: boolean;
|
|
13
12
|
}
|
|
14
13
|
export declare const setNavigationMenuItemCtx: (ctx: NavigationMenuItemContext) => NavigationMenuItemContext, getNavigationMenuItemCtx: () => NavigationMenuItemContext;
|
|
15
|
-
export { generateFormId };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { createContext
|
|
1
|
+
import { createContext } from '@dryui/primitives';
|
|
2
2
|
export const [setNavigationMenuCtx, getNavigationMenuCtx] = createContext('navigation-menu');
|
|
3
3
|
export const [setNavigationMenuItemCtx, getNavigationMenuItemCtx] = createContext('navigation-menu-item');
|
|
4
|
-
export { generateFormId };
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import {
|
|
4
|
-
setNavigationMenuItemCtx,
|
|
5
|
-
getNavigationMenuCtx,
|
|
6
|
-
generateFormId
|
|
7
|
-
} from './context.svelte.js';
|
|
3
|
+
import { setNavigationMenuItemCtx, getNavigationMenuCtx } from './context.svelte.js';
|
|
8
4
|
|
|
9
5
|
interface Props {
|
|
10
6
|
children: Snippet;
|
|
@@ -13,9 +9,10 @@
|
|
|
13
9
|
let { children }: Props = $props();
|
|
14
10
|
|
|
15
11
|
const ctx = getNavigationMenuCtx();
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
12
|
+
const uid = $props.id();
|
|
13
|
+
const itemId = `nav-item-${uid}`;
|
|
14
|
+
const triggerId = `nav-trigger-${uid}`;
|
|
15
|
+
const contentId = `nav-content-${uid}`;
|
|
19
16
|
|
|
20
17
|
setNavigationMenuItemCtx({
|
|
21
18
|
itemId,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { generateFormId } from '@dryui/primitives';
|
|
4
3
|
import { setNotificationCenterCtx, type NotificationItem } from './context.svelte.js';
|
|
5
4
|
|
|
6
5
|
interface Props {
|
|
@@ -15,8 +14,9 @@
|
|
|
15
14
|
children
|
|
16
15
|
}: Props = $props();
|
|
17
16
|
|
|
18
|
-
const
|
|
19
|
-
const
|
|
17
|
+
const uid = $props.id();
|
|
18
|
+
const triggerId = `nc-trigger-${uid}`;
|
|
19
|
+
const panelId = `nc-panel-${uid}`;
|
|
20
20
|
|
|
21
21
|
const unreadCount = $derived(items.filter((item) => !item.read).length);
|
|
22
22
|
|