@dryui/ui 1.3.0 → 1.4.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-content.svelte +1 -1
- package/dist/alert/alert.svelte +1 -1
- package/dist/app-frame/app-frame.svelte +125 -0
- package/dist/app-frame/app-frame.svelte.d.ts +10 -0
- package/dist/app-frame/index.d.ts +8 -0
- package/dist/app-frame/index.js +1 -0
- package/dist/aurora/aurora.svelte +22 -59
- package/dist/beam/beam.svelte +28 -9
- package/dist/carousel/carousel-button-dots.svelte +25 -8
- package/dist/carousel/carousel-button-thumbnails.svelte +25 -8
- package/dist/carousel/carousel-root.svelte +115 -4
- package/dist/carousel/carousel-slide.svelte +5 -1
- package/dist/carousel/carousel-viewport.svelte +2 -0
- package/dist/carousel/context.svelte.d.ts +5 -0
- package/dist/chart/chart-bars.svelte +25 -16
- package/dist/chart/chart-donut.svelte +25 -16
- package/dist/chart/chart-root.svelte +134 -30
- package/dist/chart/chart-root.svelte.d.ts +1 -0
- package/dist/chart/context.svelte.d.ts +3 -1
- package/dist/chart/context.svelte.js +1 -0
- package/dist/chart/index.d.ts +1 -0
- package/dist/chromatic-shift/chromatic-shift.svelte +36 -9
- package/dist/collapsible/collapsible-content.svelte +2 -1
- package/dist/combobox/combobox-content.svelte +26 -44
- package/dist/combobox/combobox-content.svelte.d.ts +1 -1
- package/dist/combobox/combobox-input-root.svelte +7 -1
- package/dist/combobox/combobox-input.svelte +21 -8
- package/dist/country-select/country-select-button-input.svelte +124 -260
- package/dist/date-picker/datepicker-content.svelte +18 -26
- package/dist/date-picker/datepicker-content.svelte.d.ts +2 -1
- package/dist/date-picker/datepicker-input-root.svelte +7 -1
- package/dist/date-range-picker/date-range-picker-content.svelte +18 -14
- package/dist/date-range-picker/date-range-picker-content.svelte.d.ts +2 -1
- package/dist/date-range-picker/date-range-picker-root.svelte +7 -1
- package/dist/displacement/displacement.svelte +16 -22
- package/dist/drag-and-drop/context.svelte.d.ts +2 -0
- package/dist/drag-and-drop/drag-and-drop-handle.svelte +34 -5
- package/dist/drag-and-drop/drag-and-drop-item.svelte +23 -14
- package/dist/drag-and-drop/drag-and-drop-root.svelte +60 -16
- package/dist/god-rays/god-rays.svelte +11 -0
- package/dist/gradient-mesh/gradient-mesh.svelte +27 -5
- package/dist/hover-card/context.svelte.d.ts +1 -10
- package/dist/hover-card/context.svelte.js +1 -2
- package/dist/hover-card/hover-card-content.svelte +41 -3
- package/dist/hover-card/hover-card-root.svelte +7 -55
- package/dist/hover-card/hover-card-trigger.svelte +79 -40
- package/dist/hover-card/hover-card-trigger.svelte.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/internal/motion.d.ts +1 -1
- package/dist/internal/motion.js +1 -1
- package/dist/marquee/marquee.svelte +56 -8
- package/dist/mega-menu/context.svelte.d.ts +2 -1
- package/dist/mega-menu/mega-menu-button-trigger.svelte +2 -14
- package/dist/mega-menu/mega-menu-item.svelte +3 -1
- package/dist/mega-menu/mega-menu-panel.svelte +35 -3
- package/dist/mega-menu/mega-menu-root.svelte +28 -13
- package/dist/menubar/context.svelte.d.ts +2 -2
- package/dist/menubar/menubar-button-trigger.svelte +5 -3
- package/dist/menubar/menubar-content.svelte +20 -12
- package/dist/menubar/menubar-root.svelte +4 -4
- package/dist/multi-select-combobox/multi-select-combobox-content.svelte +18 -55
- package/dist/multi-select-combobox/multi-select-combobox-content.svelte.d.ts +1 -1
- package/dist/noise/noise.svelte +38 -6
- package/dist/notification-center/context.svelte.d.ts +0 -1
- package/dist/notification-center/notification-center-panel.svelte +54 -35
- package/dist/notification-center/notification-center-root.svelte +0 -1
- package/dist/notification-center/notification-center-trigger-button.svelte +1 -8
- package/dist/option-picker/option-picker-description.svelte +2 -2
- package/dist/option-picker/option-picker-item.svelte +10 -3
- package/dist/option-picker/option-picker-label.svelte +2 -2
- package/dist/option-picker/option-picker-preview.svelte +18 -13
- package/dist/phone-input/phone-input-select.svelte +2 -152
- package/dist/phone-input/phone-input-select.svelte.d.ts +1 -7
- package/dist/rich-text-editor/rich-text-editor-toolbar-button-input.svelte +84 -29
- package/dist/scroll-area/scroll-area.svelte +16 -4
- package/dist/select/select-content.svelte +21 -31
- package/dist/select/select-content.svelte.d.ts +1 -1
- package/dist/select/select-root-input.svelte +7 -1
- package/dist/shimmer/shimmer.svelte +22 -12
- package/dist/tabs/tabs-list.svelte +12 -0
- package/dist/transfer/transfer-item.svelte +0 -3
- package/dist/transfer/transfer-list-input.svelte +1 -6
- package/dist/tree/context.svelte.d.ts +7 -1
- package/dist/tree/tree-item-children.svelte +12 -10
- package/dist/tree/tree-item-label.svelte +6 -17
- package/dist/tree/tree-item-label.svelte.d.ts +2 -2
- package/dist/tree/tree-item.svelte +28 -1
- package/dist/tree/tree-root.svelte +135 -59
- package/dist/typography/heading.svelte +1 -0
- package/package.json +8 -2
- package/skills/dryui/SKILL.md +1 -0
- package/dist/hover-card/hover-card-root.svelte.d.ts +0 -9
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { onDestroy } from 'svelte';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
5
|
import { getTreeCtx, getTreeItemCtx } from './context.svelte.js';
|
|
@@ -7,18 +8,16 @@
|
|
|
7
8
|
children: Snippet;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
let { class: className, children,
|
|
11
|
+
let { class: className, children, ...rest }: Props = $props();
|
|
11
12
|
|
|
12
13
|
const ctx = getTreeCtx();
|
|
13
14
|
const itemCtx = getTreeItemCtx();
|
|
14
15
|
const open = $derived(ctx.isExpanded(itemCtx.itemId));
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
});
|
|
21
|
-
}
|
|
16
|
+
const branchItemId = itemCtx.itemId;
|
|
17
|
+
ctx.registerBranch(branchItemId);
|
|
18
|
+
onDestroy(() => {
|
|
19
|
+
ctx.unregisterBranch(branchItemId);
|
|
20
|
+
});
|
|
22
21
|
</script>
|
|
23
22
|
|
|
24
23
|
<div
|
|
@@ -28,7 +27,6 @@
|
|
|
28
27
|
data-state={open ? 'open' : 'closed'}
|
|
29
28
|
class={className}
|
|
30
29
|
{...rest}
|
|
31
|
-
{@attach applyStyles}
|
|
32
30
|
>
|
|
33
31
|
<div class="tree-item-inner">
|
|
34
32
|
{@render children()}
|
|
@@ -42,8 +40,12 @@
|
|
|
42
40
|
|
|
43
41
|
[data-part='children'] {
|
|
44
42
|
display: grid;
|
|
45
|
-
grid-template-rows:
|
|
43
|
+
grid-template-rows: 0fr;
|
|
46
44
|
padding-left: var(--dry-tree-indent, var(--dry-space-4));
|
|
47
45
|
transition: grid-template-rows var(--dry-duration-normal) var(--dry-ease-default);
|
|
48
46
|
}
|
|
47
|
+
|
|
48
|
+
[data-part='children'][data-state='open'] {
|
|
49
|
+
grid-template-rows: 1fr;
|
|
50
|
+
}
|
|
49
51
|
</style>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import type {
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
4
|
import { getTreeCtx, getTreeItemCtx } from './context.svelte.js';
|
|
5
5
|
|
|
6
|
-
interface Props extends
|
|
6
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
7
|
children: Snippet;
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -13,24 +13,17 @@
|
|
|
13
13
|
const itemCtx = getTreeItemCtx();
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
<
|
|
17
|
-
type="button"
|
|
16
|
+
<div
|
|
18
17
|
data-part="label"
|
|
19
|
-
data-tree-label
|
|
20
18
|
data-selected={ctx.isSelected(itemCtx.itemId) || undefined}
|
|
21
19
|
class={className}
|
|
22
|
-
onclick={() => {
|
|
23
|
-
ctx.selectItem(itemCtx.itemId);
|
|
24
|
-
ctx.toggleItem(itemCtx.itemId);
|
|
25
|
-
}}
|
|
26
20
|
{...rest}
|
|
27
21
|
>
|
|
28
22
|
{@render children()}
|
|
29
|
-
</
|
|
23
|
+
</div>
|
|
30
24
|
|
|
31
25
|
<style>
|
|
32
26
|
[data-part='label'] {
|
|
33
|
-
appearance: none;
|
|
34
27
|
display: grid;
|
|
35
28
|
grid-auto-flow: column;
|
|
36
29
|
grid-auto-columns: max-content;
|
|
@@ -44,9 +37,10 @@
|
|
|
44
37
|
font-size: var(--dry-type-small-size, var(--dry-text-sm-size));
|
|
45
38
|
font-family: var(--dry-font-sans);
|
|
46
39
|
color: var(--dry-color-text-strong);
|
|
40
|
+
outline: var(--dry-tree-item-focus-ring, none);
|
|
41
|
+
outline-offset: var(--dry-tree-item-focus-offset, 0px);
|
|
47
42
|
cursor: pointer;
|
|
48
43
|
user-select: none;
|
|
49
|
-
outline: none;
|
|
50
44
|
transition: background var(--dry-duration-fast) var(--dry-ease-default);
|
|
51
45
|
}
|
|
52
46
|
|
|
@@ -54,11 +48,6 @@
|
|
|
54
48
|
background: var(--dry-tree-item-hover-bg, var(--dry-color-fill));
|
|
55
49
|
}
|
|
56
50
|
|
|
57
|
-
[data-part='label']:focus-visible {
|
|
58
|
-
outline: var(--dry-focus-ring);
|
|
59
|
-
outline-offset: 2px;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
51
|
[data-part='label'][data-selected] {
|
|
63
52
|
background: var(--dry-tree-item-selected-bg, var(--dry-color-fill-brand-weak));
|
|
64
53
|
color: var(--dry-tree-item-selected-color, var(--dry-color-text-brand));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
import type {
|
|
3
|
-
interface Props extends
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
4
|
children: Snippet;
|
|
5
5
|
}
|
|
6
6
|
declare const TreeItemLabel: import("svelte").Component<Props, {}, "">;
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
const ctx = getTreeCtx();
|
|
14
14
|
const expanded = $derived(ctx.isExpanded(itemId));
|
|
15
|
+
const focused = $derived(ctx.isFocused(itemId));
|
|
16
|
+
const hasChildren = $derived(ctx.hasChildren(itemId));
|
|
15
17
|
const selected = $derived(ctx.isSelected(itemId));
|
|
16
18
|
|
|
17
19
|
setTreeItemCtx({
|
|
@@ -23,14 +25,39 @@
|
|
|
23
25
|
|
|
24
26
|
<div
|
|
25
27
|
role="treeitem"
|
|
26
|
-
|
|
28
|
+
tabindex={focused ? 0 : -1}
|
|
29
|
+
aria-expanded={hasChildren ? expanded : undefined}
|
|
27
30
|
aria-selected={selected}
|
|
31
|
+
data-branch={hasChildren || undefined}
|
|
28
32
|
data-part="item"
|
|
29
33
|
data-expanded={expanded || undefined}
|
|
34
|
+
data-focused={focused || undefined}
|
|
30
35
|
data-selected={selected || undefined}
|
|
31
36
|
data-item-id={itemId}
|
|
32
37
|
class={className}
|
|
38
|
+
onclick={(e) => {
|
|
39
|
+
(e.currentTarget as HTMLElement).focus();
|
|
40
|
+
ctx.selectItem(itemId);
|
|
41
|
+
}}
|
|
42
|
+
ondblclick={() => {
|
|
43
|
+
if (hasChildren) {
|
|
44
|
+
ctx.toggleItem(itemId);
|
|
45
|
+
}
|
|
46
|
+
}}
|
|
33
47
|
{...rest}
|
|
34
48
|
>
|
|
35
49
|
{@render children()}
|
|
36
50
|
</div>
|
|
51
|
+
|
|
52
|
+
<style>
|
|
53
|
+
[data-part='item'] {
|
|
54
|
+
outline: none;
|
|
55
|
+
--dry-tree-item-focus-ring: none;
|
|
56
|
+
--dry-tree-item-focus-offset: 0px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
[data-part='item']:focus-visible {
|
|
60
|
+
--dry-tree-item-focus-ring: var(--dry-focus-ring);
|
|
61
|
+
--dry-tree-item-focus-offset: 2px;
|
|
62
|
+
}
|
|
63
|
+
</style>
|
|
@@ -23,6 +23,38 @@
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
let expandedItems = createExpandedItems();
|
|
26
|
+
let branchItems = new SvelteSet<string>();
|
|
27
|
+
let focusedItem = $state<string | null>(selectedItem);
|
|
28
|
+
|
|
29
|
+
function toggleItem(id: string) {
|
|
30
|
+
if (expandedItems.has(id)) expandedItems.delete(id);
|
|
31
|
+
else expandedItems.add(id);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function expandItem(id: string) {
|
|
35
|
+
expandedItems.add(id);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function collapseItem(id: string) {
|
|
39
|
+
expandedItems.delete(id);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function selectItem(id: string) {
|
|
43
|
+
selectedItem = id;
|
|
44
|
+
focusedItem = id;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function setFocusedItem(id: string) {
|
|
48
|
+
focusedItem = id;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function registerBranch(id: string) {
|
|
52
|
+
branchItems.add(id);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function unregisterBranch(id: string) {
|
|
56
|
+
branchItems.delete(id);
|
|
57
|
+
}
|
|
26
58
|
|
|
27
59
|
setTreeCtx({
|
|
28
60
|
get expandedItems() {
|
|
@@ -31,115 +63,151 @@
|
|
|
31
63
|
get selectedItem() {
|
|
32
64
|
return selectedItem;
|
|
33
65
|
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
else expandedItems.add(id);
|
|
37
|
-
},
|
|
38
|
-
expandItem(id) {
|
|
39
|
-
expandedItems.add(id);
|
|
40
|
-
},
|
|
41
|
-
collapseItem(id) {
|
|
42
|
-
expandedItems.delete(id);
|
|
43
|
-
},
|
|
44
|
-
selectItem(id) {
|
|
45
|
-
selectedItem = id;
|
|
66
|
+
get focusedItem() {
|
|
67
|
+
return focusedItem;
|
|
46
68
|
},
|
|
69
|
+
toggleItem,
|
|
70
|
+
expandItem,
|
|
71
|
+
collapseItem,
|
|
72
|
+
selectItem,
|
|
73
|
+
setFocusedItem,
|
|
74
|
+
registerBranch,
|
|
75
|
+
unregisterBranch,
|
|
47
76
|
isExpanded(id) {
|
|
48
77
|
return expandedItems.has(id);
|
|
49
78
|
},
|
|
50
79
|
isSelected(id) {
|
|
51
80
|
return selectedItem === id;
|
|
81
|
+
},
|
|
82
|
+
isFocused(id) {
|
|
83
|
+
return focusedItem === id;
|
|
84
|
+
},
|
|
85
|
+
hasChildren(id) {
|
|
86
|
+
return branchItems.has(id);
|
|
52
87
|
}
|
|
53
88
|
});
|
|
54
89
|
|
|
55
|
-
function
|
|
56
|
-
|
|
90
|
+
function initializeTree(node: HTMLElement) {
|
|
91
|
+
if (focusedItem !== null) return;
|
|
92
|
+
const itemId = node.querySelector<HTMLElement>('[role="treeitem"]')?.dataset.itemId;
|
|
93
|
+
|
|
94
|
+
if (itemId) {
|
|
95
|
+
focusedItem = itemId;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function getVisibleItems(tree: HTMLElement) {
|
|
57
100
|
const items = Array.from(tree.querySelectorAll('[role="treeitem"]')) as HTMLElement[];
|
|
58
|
-
|
|
101
|
+
|
|
102
|
+
return items.filter((item) => {
|
|
59
103
|
let parent = item.parentElement;
|
|
104
|
+
|
|
60
105
|
while (parent && parent !== tree) {
|
|
61
106
|
if (parent.getAttribute('role') === 'group') {
|
|
62
|
-
const groupParent = parent.closest('[role="treeitem"]');
|
|
63
|
-
if (groupParent
|
|
107
|
+
const groupParent = parent.closest<HTMLElement>('[role="treeitem"]');
|
|
108
|
+
if (groupParent?.getAttribute('aria-expanded') === 'false') {
|
|
64
109
|
return false;
|
|
65
110
|
}
|
|
66
111
|
}
|
|
112
|
+
|
|
67
113
|
parent = parent.parentElement;
|
|
68
114
|
}
|
|
115
|
+
|
|
69
116
|
return true;
|
|
70
117
|
});
|
|
118
|
+
}
|
|
71
119
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
120
|
+
function getCurrentItem(tree: HTMLElement, visibleItems: HTMLElement[]) {
|
|
121
|
+
const activeItem =
|
|
122
|
+
document.activeElement instanceof HTMLElement
|
|
123
|
+
? document.activeElement.closest<HTMLElement>('[role="treeitem"]')
|
|
124
|
+
: null;
|
|
125
|
+
|
|
126
|
+
if (activeItem && tree.contains(activeItem)) {
|
|
127
|
+
return activeItem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (focusedItem !== null) {
|
|
131
|
+
return visibleItems.find((item) => item.dataset.itemId === focusedItem) ?? null;
|
|
132
|
+
}
|
|
76
133
|
|
|
77
|
-
|
|
134
|
+
return visibleItems[0] ?? null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function focusItem(item: HTMLElement | null | undefined) {
|
|
138
|
+
if (!item) return;
|
|
139
|
+
const itemId = item.dataset.itemId;
|
|
140
|
+
if (itemId && itemId !== focusedItem) {
|
|
141
|
+
focusedItem = itemId;
|
|
142
|
+
}
|
|
143
|
+
item.focus();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function handleFocusIn(e: FocusEvent) {
|
|
147
|
+
const item =
|
|
148
|
+
e.target instanceof HTMLElement ? e.target.closest<HTMLElement>('[role="treeitem"]') : null;
|
|
149
|
+
const itemId = item?.dataset.itemId;
|
|
150
|
+
|
|
151
|
+
if (itemId && itemId !== focusedItem) {
|
|
152
|
+
focusedItem = itemId;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function handleKeydown(e: KeyboardEvent) {
|
|
157
|
+
const tree = e.currentTarget as HTMLElement;
|
|
158
|
+
const visibleItems = getVisibleItems(tree);
|
|
159
|
+
const currentItem = getCurrentItem(tree, visibleItems);
|
|
160
|
+
if (!currentItem) return;
|
|
161
|
+
|
|
162
|
+
const currentIndex = visibleItems.indexOf(currentItem);
|
|
78
163
|
const itemId = currentItem.dataset.itemId;
|
|
79
164
|
|
|
80
165
|
switch (e.key) {
|
|
81
166
|
case 'ArrowDown': {
|
|
82
167
|
e.preventDefault();
|
|
83
|
-
|
|
84
|
-
if (next) {
|
|
85
|
-
const label = next.querySelector('[data-tree-label]') as HTMLElement;
|
|
86
|
-
(label ?? next).focus();
|
|
87
|
-
}
|
|
168
|
+
focusItem(visibleItems[currentIndex + 1]);
|
|
88
169
|
break;
|
|
89
170
|
}
|
|
90
171
|
case 'ArrowUp': {
|
|
91
172
|
e.preventDefault();
|
|
92
|
-
|
|
93
|
-
if (prev) {
|
|
94
|
-
const label = prev.querySelector('[data-tree-label]') as HTMLElement;
|
|
95
|
-
(label ?? prev).focus();
|
|
96
|
-
}
|
|
173
|
+
focusItem(visibleItems[currentIndex - 1]);
|
|
97
174
|
break;
|
|
98
175
|
}
|
|
99
176
|
case 'ArrowRight': {
|
|
100
177
|
e.preventDefault();
|
|
101
|
-
if (itemId) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const firstChild = currentItem.querySelector('[role="group"] > [role="treeitem"]');
|
|
107
|
-
if (firstChild) {
|
|
108
|
-
const label = firstChild.querySelector('[data-tree-label]') as HTMLElement;
|
|
109
|
-
(label ?? (firstChild as HTMLElement)).focus();
|
|
110
|
-
}
|
|
178
|
+
if (itemId && branchItems.has(itemId)) {
|
|
179
|
+
if (!expandedItems.has(itemId)) {
|
|
180
|
+
expandItem(itemId);
|
|
181
|
+
} else {
|
|
182
|
+
focusItem(currentItem.querySelector<HTMLElement>('[role="group"] [role="treeitem"]'));
|
|
111
183
|
}
|
|
112
184
|
}
|
|
113
185
|
break;
|
|
114
186
|
}
|
|
115
187
|
case 'ArrowLeft': {
|
|
116
188
|
e.preventDefault();
|
|
117
|
-
if (itemId && expandedItems.has(itemId)) {
|
|
118
|
-
|
|
189
|
+
if (itemId && branchItems.has(itemId) && expandedItems.has(itemId)) {
|
|
190
|
+
collapseItem(itemId);
|
|
119
191
|
} else {
|
|
120
|
-
|
|
121
|
-
if (parentGroup) {
|
|
122
|
-
const label = parentGroup.querySelector('[data-tree-label]') as HTMLElement;
|
|
123
|
-
(label ?? (parentGroup as HTMLElement)).focus();
|
|
124
|
-
}
|
|
192
|
+
focusItem(currentItem.parentElement?.closest<HTMLElement>('[role="treeitem"]'));
|
|
125
193
|
}
|
|
126
194
|
break;
|
|
127
195
|
}
|
|
128
196
|
case 'Home': {
|
|
129
197
|
e.preventDefault();
|
|
130
|
-
|
|
131
|
-
if (first) {
|
|
132
|
-
const label = first.querySelector('[data-tree-label]') as HTMLElement;
|
|
133
|
-
(label ?? first).focus();
|
|
134
|
-
}
|
|
198
|
+
focusItem(visibleItems[0]);
|
|
135
199
|
break;
|
|
136
200
|
}
|
|
137
201
|
case 'End': {
|
|
138
202
|
e.preventDefault();
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
203
|
+
focusItem(visibleItems[visibleItems.length - 1]);
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
case 'Enter':
|
|
207
|
+
case ' ': {
|
|
208
|
+
if (itemId) {
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
selectItem(itemId);
|
|
143
211
|
}
|
|
144
212
|
break;
|
|
145
213
|
}
|
|
@@ -147,7 +215,15 @@
|
|
|
147
215
|
}
|
|
148
216
|
</script>
|
|
149
217
|
|
|
150
|
-
<div
|
|
218
|
+
<div
|
|
219
|
+
role="tree"
|
|
220
|
+
data-part="root"
|
|
221
|
+
class={className}
|
|
222
|
+
onfocusin={handleFocusIn}
|
|
223
|
+
onkeydown={handleKeydown}
|
|
224
|
+
{@attach initializeTree}
|
|
225
|
+
{...rest}
|
|
226
|
+
>
|
|
151
227
|
{@render children()}
|
|
152
228
|
</div>
|
|
153
229
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dryui/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Zero-dependency styled Svelte 5 components with scoped styles and --dry-* CSS variable theming.",
|
|
5
5
|
"author": "Rob Balfre",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,6 +50,11 @@
|
|
|
50
50
|
"svelte": "./dist/alpha-slider/index.js",
|
|
51
51
|
"default": "./dist/alpha-slider/index.js"
|
|
52
52
|
},
|
|
53
|
+
"./app-frame": {
|
|
54
|
+
"types": "./dist/app-frame/index.d.ts",
|
|
55
|
+
"svelte": "./dist/app-frame/index.js",
|
|
56
|
+
"default": "./dist/app-frame/index.js"
|
|
57
|
+
},
|
|
53
58
|
"./aspect-ratio": {
|
|
54
59
|
"types": "./dist/aspect-ratio/index.d.ts",
|
|
55
60
|
"svelte": "./dist/aspect-ratio/index.js",
|
|
@@ -779,12 +784,13 @@
|
|
|
779
784
|
"postpack": "bun ../../scripts/postpack-exports.ts"
|
|
780
785
|
},
|
|
781
786
|
"dependencies": {
|
|
782
|
-
"@dryui/primitives": "^1.
|
|
787
|
+
"@dryui/primitives": "^1.4.0"
|
|
783
788
|
},
|
|
784
789
|
"peerDependencies": {
|
|
785
790
|
"svelte": "^5.55.1"
|
|
786
791
|
},
|
|
787
792
|
"devDependencies": {
|
|
793
|
+
"@dryui/lint": "^0.4.2",
|
|
788
794
|
"svelte": "^5.55.3",
|
|
789
795
|
"@sveltejs/package": "^2.5.7",
|
|
790
796
|
"svelte-check": "^4.4.6",
|
package/skills/dryui/SKILL.md
CHANGED
|
@@ -146,6 +146,7 @@ This works for greenfield (empty directory), brownfield (existing non-SvelteKit
|
|
|
146
146
|
|
|
147
147
|
- Claude Code: `claude plugin marketplace add rob-balfre/dryui && claude plugin install dryui@dryui` (plugin is the canonical Claude skill install path)
|
|
148
148
|
- Codex (0.121.0+): `codex marketplace add rob-balfre/dryui`, then start `codex`, run `/plugins`, and install `DryUI` (plugin is the canonical Codex skill install path)
|
|
149
|
+
- OpenCode: `npx degit rob-balfre/dryui/packages/ui/skills/dryui .opencode/skills/dryui` + add the `dryui` and `dryui-feedback` local MCP servers in `opencode.json` (OpenCode also loads `.agents/skills/dryui` and reads `AGENTS.md`)
|
|
149
150
|
- Copilot/Cursor/Windsurf: `npx degit rob-balfre/dryui/packages/ui/skills/dryui .agents/skills/dryui` + add MCP config (see https://dryui.dev/tools)
|
|
150
151
|
|
|
151
152
|
### Manual setup
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
interface Props {
|
|
3
|
-
openDelay?: number;
|
|
4
|
-
closeDelay?: number;
|
|
5
|
-
children: Snippet;
|
|
6
|
-
}
|
|
7
|
-
declare const HoverCardRoot: import("svelte").Component<Props, {}, "">;
|
|
8
|
-
type HoverCardRoot = ReturnType<typeof HoverCardRoot>;
|
|
9
|
-
export default HoverCardRoot;
|