@x33025/sveltely 0.1.2 → 0.1.4
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/components/Library/AnimatedNumber/AnimatedNumber.demo.svelte +1 -1
- package/dist/components/Library/AsyncButton/AsyncButton.svelte +42 -16
- package/dist/components/Library/Button/Button.svelte +21 -13
- package/dist/components/Library/Calendar/Calendar.svelte +16 -16
- package/dist/components/Library/Checkbox/Checkbox.svelte +13 -14
- package/dist/components/Library/ChipInput/ChipInput.demo.svelte +1 -1
- package/dist/components/Library/ChipInput/ChipInput.svelte +7 -4
- package/dist/components/Library/Dropdown/Action.svelte +60 -0
- package/dist/components/Library/Dropdown/Action.svelte.d.ts +11 -0
- package/dist/components/Library/Dropdown/Divider.svelte +5 -0
- package/dist/components/Library/Dropdown/Divider.svelte.d.ts +19 -0
- package/dist/components/Library/Dropdown/Dropdown.demo.svelte +182 -72
- package/dist/components/Library/Dropdown/Dropdown.demo.svelte.d.ts +2 -1
- package/dist/components/Library/Dropdown/Dropdown.svelte +78 -267
- package/dist/components/Library/Dropdown/Dropdown.svelte.d.ts +17 -16
- package/dist/components/Library/Dropdown/Item.svelte +73 -0
- package/dist/components/Library/Dropdown/Item.svelte.d.ts +31 -0
- package/dist/components/Library/Dropdown/Section.svelte +34 -0
- package/dist/components/Library/Dropdown/Section.svelte.d.ts +8 -0
- package/dist/components/Library/Dropdown/context.d.ts +34 -0
- package/dist/components/Library/Dropdown/context.js +6 -0
- package/dist/components/Library/Dropdown/index.d.ts +13 -2
- package/dist/components/Library/Dropdown/index.js +11 -1
- package/dist/components/Library/Floating/Floating.svelte +10 -7
- package/dist/components/Library/ImageMask/BrushPreview.svelte +6 -6
- package/dist/components/Library/ImageMask/ImageMask.demo.svelte +7 -7
- package/dist/components/Library/ImageMask/MaskLayer.svelte +3 -3
- package/dist/components/Library/Label/Label.svelte +2 -4
- package/dist/components/Library/NavigationStack/NavigationStack.svelte +17 -7
- package/dist/components/Library/NavigationStack/Toolbar.svelte +7 -2
- package/dist/components/Library/NumberField/NumberField.svelte +14 -9
- package/dist/components/Library/Pagination/Pagination.svelte +16 -20
- package/dist/components/Library/Popover/Popover.demo.svelte +2 -2
- package/dist/components/Library/Popover/Popover.svelte +7 -4
- package/dist/components/Library/ScrollView/ScrollView.svelte +140 -3
- package/dist/components/Library/ScrollView/ScrollView.svelte.d.ts +28 -0
- package/dist/components/Library/ScrollView/index.d.ts +1 -0
- package/dist/components/Library/{SearchInput/SearchInput.demo.svelte → SearchField/SearchField.demo.svelte} +4 -4
- package/dist/components/Library/SearchField/SearchField.demo.svelte.d.ts +8 -0
- package/dist/components/Library/{SearchInput/SearchInput.svelte → SearchField/SearchField.svelte} +26 -30
- package/dist/components/Library/{SearchInput/SearchInput.svelte.d.ts → SearchField/SearchField.svelte.d.ts} +3 -3
- package/dist/components/Library/SearchField/index.d.ts +1 -0
- package/dist/components/Library/SearchField/index.js +1 -0
- package/dist/components/Library/SegmentedPicker/SegmentedPicker.demo.svelte +1 -1
- package/dist/components/Library/SegmentedPicker/SegmentedPicker.svelte +9 -9
- package/dist/components/Library/Sheet/Sheet.demo.svelte +1 -1
- package/dist/components/Library/Sheet/Sheet.svelte +8 -5
- package/dist/components/Library/Slider/Slider.demo.svelte +1 -1
- package/dist/components/Library/Slider/Slider.svelte +11 -10
- package/dist/components/Library/Spinner/Spinner.demo.svelte +1 -1
- package/dist/components/Library/Switch/Switch.svelte +6 -11
- package/dist/components/Library/TextField/TextField.svelte +14 -9
- package/dist/components/Library/{TokenSearchInput/TokenSearchInput.demo.svelte → TokenSearchField/TokenSearchField.demo.svelte} +4 -4
- package/dist/components/Library/TokenSearchField/TokenSearchField.demo.svelte.d.ts +9 -0
- package/dist/components/Library/{TokenSearchInput/TokenSearchInput.svelte → TokenSearchField/TokenSearchField.svelte} +70 -66
- package/dist/components/Library/{TokenSearchInput/TokenSearchInput.svelte.d.ts → TokenSearchField/TokenSearchField.svelte.d.ts} +3 -3
- package/dist/components/Library/TokenSearchField/index.d.ts +1 -0
- package/dist/components/Library/TokenSearchField/index.js +1 -0
- package/dist/components/Library/WheelPicker/WheelColumn.svelte +4 -10
- package/dist/components/Library/WheelPicker/WheelPicker.svelte +5 -9
- package/dist/components/Local/HeroCard.svelte +5 -3
- package/dist/components/Local/StyleControls.svelte +58 -27
- package/dist/components/Local/StyleControls.svelte.d.ts +3 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -2
- package/dist/style/index.css +9 -5
- package/dist/style.css +60 -29
- package/package.json +1 -1
- package/dist/components/Library/Dropdown/types.d.ts +0 -30
- package/dist/components/Library/Dropdown/types.js +0 -1
- package/dist/components/Library/SearchInput/SearchInput.demo.svelte.d.ts +0 -8
- package/dist/components/Library/SearchInput/index.d.ts +0 -1
- package/dist/components/Library/SearchInput/index.js +0 -1
- package/dist/components/Library/TokenSearchInput/TokenSearchInput.demo.svelte.d.ts +0 -9
- package/dist/components/Library/TokenSearchInput/index.d.ts +0 -1
- package/dist/components/Library/TokenSearchInput/index.js +0 -1
|
@@ -1,89 +1,199 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
export const demo = {
|
|
3
3
|
name: 'Dropdown',
|
|
4
|
-
description: '
|
|
4
|
+
description: 'Composable dropdown menu with declarative items, sections, and actions.',
|
|
5
|
+
columnSpan: 2
|
|
5
6
|
};
|
|
6
7
|
</script>
|
|
7
8
|
|
|
8
9
|
<script lang="ts">
|
|
9
|
-
import
|
|
10
|
-
import
|
|
10
|
+
import { CheckIcon, ChevronDownIcon, PlusIcon, UserRoundXIcon } from '@lucide/svelte';
|
|
11
|
+
import SearchField from '../SearchField';
|
|
12
|
+
import ScrollView, { type ScrollGeometry } from '../ScrollView';
|
|
13
|
+
import Dropdown from './index';
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
{ label: 'Draft', value: 'draft' },
|
|
18
|
-
{ label: 'Scheduled', value: 'scheduled' },
|
|
19
|
-
{ type: 'divider' },
|
|
20
|
-
{
|
|
21
|
-
type: 'submenu' as const,
|
|
22
|
-
label: 'Advanced',
|
|
23
|
-
items: [
|
|
24
|
-
{ label: 'Review queue', value: 'review' },
|
|
25
|
-
{ type: 'divider' },
|
|
26
|
-
{
|
|
27
|
-
type: 'action' as const,
|
|
28
|
-
label: 'Open workflow',
|
|
29
|
-
onSelect: () => {
|
|
30
|
-
console.log('Open workflow');
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
]
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
type: 'action' as const,
|
|
37
|
-
label: 'Create new status',
|
|
38
|
-
onSelect: () => {
|
|
39
|
-
console.log('Create new status');
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
]
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
type: 'group' as const,
|
|
46
|
-
label: 'Visibility',
|
|
47
|
-
items: [
|
|
48
|
-
{ label: 'Public', value: 'public' },
|
|
49
|
-
{ label: 'Private', value: 'private', disabled: true }
|
|
50
|
-
]
|
|
51
|
-
}
|
|
52
|
-
];
|
|
15
|
+
type Website = {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
domain: string | null;
|
|
19
|
+
};
|
|
53
20
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
21
|
+
const statusLabels: Record<string, string> = {
|
|
22
|
+
draft: 'Draft',
|
|
23
|
+
scheduled: 'Scheduled',
|
|
24
|
+
public: 'Public',
|
|
25
|
+
private: 'Private'
|
|
26
|
+
};
|
|
57
27
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
28
|
+
const websites: Website[] = [
|
|
29
|
+
{ id: 'sveltely', name: 'Sveltely', domain: 'sveltely.dev' },
|
|
30
|
+
{ id: 'northstar', name: 'Northstar Studio', domain: 'northstar.example' },
|
|
31
|
+
{ id: 'atlas', name: 'Atlas Analytics', domain: 'atlas.example' },
|
|
32
|
+
{ id: 'folio', name: 'Folio', domain: null },
|
|
33
|
+
{ id: 'harbor', name: 'Harbor CMS', domain: 'harbor.example' },
|
|
34
|
+
{ id: 'beam', name: 'Beam Commerce', domain: 'beam.example' },
|
|
35
|
+
{ id: 'signal', name: 'Signal CRM', domain: 'signal.example' },
|
|
36
|
+
{ id: 'lumen', name: 'Lumen Health', domain: 'lumen.example' },
|
|
37
|
+
{ id: 'orbit', name: 'Orbit Travel', domain: 'orbit.example' },
|
|
38
|
+
{ id: 'canvas', name: 'Canvas Studio', domain: 'canvas.example' },
|
|
39
|
+
{ id: 'ledger', name: 'Ledger Works', domain: 'ledger.example' },
|
|
40
|
+
{ id: 'summit', name: 'Summit Labs', domain: 'summit.example' },
|
|
41
|
+
{ id: 'keystone', name: 'Keystone Legal', domain: 'keystone.example' },
|
|
42
|
+
{ id: 'prairie', name: 'Prairie Supply', domain: 'prairie.example' },
|
|
43
|
+
{ id: 'fieldnote', name: 'Fieldnote', domain: null },
|
|
44
|
+
{ id: 'vertex', name: 'Vertex Systems', domain: 'vertex.example' }
|
|
45
|
+
];
|
|
62
46
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
47
|
+
let status = $state<string | null>('draft');
|
|
48
|
+
let selectedWebsiteId = $state<string | null>('sveltely');
|
|
49
|
+
let websiteQuery = $state('');
|
|
50
|
+
let visibleWebsiteCount = $state(6);
|
|
51
|
+
let actionCount = $state(0);
|
|
52
|
+
let lastWebsiteQuery = '';
|
|
53
|
+
const websiteBatchSize = 4;
|
|
67
54
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
55
|
+
const selectedStatusLabel = $derived(status ? statusLabels[status] : null);
|
|
56
|
+
const selectedWebsite = $derived(
|
|
57
|
+
websites.find((website) => website.id === selectedWebsiteId) ?? null
|
|
58
|
+
);
|
|
59
|
+
const filteredWebsites = $derived.by(() => {
|
|
60
|
+
const query = websiteQuery.trim().toLowerCase();
|
|
61
|
+
if (!query) return websites;
|
|
62
|
+
return websites.filter((website) =>
|
|
63
|
+
[website.name, website.domain ?? ''].some((value) => value.toLowerCase().includes(query))
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
const visibleWebsites = $derived(filteredWebsites.slice(0, visibleWebsiteCount));
|
|
76
67
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
68
|
+
function createWebsite() {
|
|
69
|
+
actionCount += 1;
|
|
70
|
+
}
|
|
80
71
|
|
|
81
|
-
|
|
82
|
-
|
|
72
|
+
function loadMoreWebsites() {
|
|
73
|
+
visibleWebsiteCount = Math.min(filteredWebsites.length, visibleWebsiteCount + websiteBatchSize);
|
|
74
|
+
}
|
|
83
75
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
function handleWebsiteScroll(geometry: ScrollGeometry) {
|
|
77
|
+
if (visibleWebsiteCount >= filteredWebsites.length) return;
|
|
78
|
+
if (geometry.progress.y < 0.8) return;
|
|
79
|
+
loadMoreWebsites();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
$effect(() => {
|
|
83
|
+
const nextQuery = websiteQuery.trim().toLowerCase();
|
|
84
|
+
if (nextQuery === lastWebsiteQuery) return;
|
|
85
|
+
lastWebsiteQuery = nextQuery;
|
|
86
|
+
visibleWebsiteCount = 6;
|
|
87
|
+
});
|
|
87
88
|
</script>
|
|
88
89
|
|
|
89
|
-
<
|
|
90
|
+
<div class="grid w-full gap-4 md:grid-cols-2">
|
|
91
|
+
<div class="vstack gap-2">
|
|
92
|
+
<p class="text-sm font-medium text-[var(--sveltely-primary-color)]">Default trigger</p>
|
|
93
|
+
<Dropdown bind:value={status} placeholder="Choose status" selectedLabel={selectedStatusLabel}>
|
|
94
|
+
<Dropdown.Section label="Publishing">
|
|
95
|
+
<Dropdown.Item value="draft">Draft</Dropdown.Item>
|
|
96
|
+
<Dropdown.Item value="scheduled">Scheduled</Dropdown.Item>
|
|
97
|
+
<Dropdown.Divider />
|
|
98
|
+
<Dropdown.Action onclick={() => (actionCount += 1)}>Open workflow</Dropdown.Action>
|
|
99
|
+
<Dropdown.Action onclick={() => (actionCount += 1)}>Create new status</Dropdown.Action>
|
|
100
|
+
</Dropdown.Section>
|
|
101
|
+
<Dropdown.Section label="Visibility">
|
|
102
|
+
<Dropdown.Item value="public">Public</Dropdown.Item>
|
|
103
|
+
<Dropdown.Item value="private" disabled>Private</Dropdown.Item>
|
|
104
|
+
</Dropdown.Section>
|
|
105
|
+
</Dropdown>
|
|
106
|
+
<p class="text-xs text-[var(--sveltely-secondary-color)]">
|
|
107
|
+
Selected: {selectedStatusLabel ?? 'none'}
|
|
108
|
+
</p>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div class="vstack gap-2">
|
|
112
|
+
<p class="text-sm font-medium text-[var(--sveltely-primary-color)]">
|
|
113
|
+
Custom trigger and rich rows
|
|
114
|
+
</p>
|
|
115
|
+
<Dropdown
|
|
116
|
+
bind:value={selectedWebsiteId}
|
|
117
|
+
selectedLabel={selectedWebsite?.name ?? null}
|
|
118
|
+
showCheck={false}
|
|
119
|
+
>
|
|
120
|
+
{#snippet trigger(dropdown)}
|
|
121
|
+
<button
|
|
122
|
+
use:dropdown.useTrigger
|
|
123
|
+
type="button"
|
|
124
|
+
class="hstack w-full items-center gap-2 rounded-full border px-3 py-2 pr-2 text-left text-sm"
|
|
125
|
+
style="border-color: var(--sveltely-border-color); background: var(--sveltely-background-color);"
|
|
126
|
+
aria-expanded={dropdown.open}
|
|
127
|
+
aria-haspopup="dialog"
|
|
128
|
+
onclick={dropdown.toggle}
|
|
129
|
+
>
|
|
130
|
+
{#if selectedWebsite}
|
|
131
|
+
<span class="min-w-0 flex-1 truncate text-[var(--sveltely-primary-color)]"
|
|
132
|
+
>{selectedWebsite.name}</span
|
|
133
|
+
>
|
|
134
|
+
{#if selectedWebsite.domain}
|
|
135
|
+
<span class="max-w-32 truncate text-xs text-[var(--sveltely-secondary-color)]"
|
|
136
|
+
>{selectedWebsite.domain}</span
|
|
137
|
+
>
|
|
138
|
+
{/if}
|
|
139
|
+
{:else}
|
|
140
|
+
<span class="min-w-0 flex-1 text-[var(--sveltely-secondary-color)]">Select website</span
|
|
141
|
+
>
|
|
142
|
+
{/if}
|
|
143
|
+
<ChevronDownIcon size={14} class="shrink-0 text-[var(--sveltely-secondary-color)]" />
|
|
144
|
+
</button>
|
|
145
|
+
{/snippet}
|
|
146
|
+
|
|
147
|
+
<SearchField bind:value={websiteQuery} placeholder="Search websites..." />
|
|
148
|
+
<Dropdown.Action onclick={createWebsite}>
|
|
149
|
+
<PlusIcon size={14} />
|
|
150
|
+
<span>Create website</span>
|
|
151
|
+
</Dropdown.Action>
|
|
152
|
+
<Dropdown.Divider />
|
|
153
|
+
<Dropdown.Item value={null}>
|
|
154
|
+
<UserRoundXIcon size={14} />
|
|
155
|
+
<span>No website</span>
|
|
156
|
+
</Dropdown.Item>
|
|
157
|
+
<Dropdown.Section label="Websites">
|
|
158
|
+
{#if filteredWebsites.length === 0}
|
|
159
|
+
<div class="px-2 py-1 text-sm text-[var(--sveltely-secondary-color)]">
|
|
160
|
+
No websites found.
|
|
161
|
+
</div>
|
|
162
|
+
{:else}
|
|
163
|
+
<div class="h-36">
|
|
164
|
+
<ScrollView
|
|
165
|
+
contentStyles={{ paddingX: 0, paddingY: 0 }}
|
|
166
|
+
borderRadius="var(--sveltely-border-radius-nested)"
|
|
167
|
+
background="white"
|
|
168
|
+
onScroll={handleWebsiteScroll}
|
|
169
|
+
>
|
|
170
|
+
<div class="vstack gap-1">
|
|
171
|
+
{#each visibleWebsites as website (website.id)}
|
|
172
|
+
<Dropdown.Item value={website.id}>
|
|
173
|
+
{#snippet children({ selected })}
|
|
174
|
+
<div class="vstack min-w-0 gap-0.5">
|
|
175
|
+
<span class="truncate">{website.name}</span>
|
|
176
|
+
{#if website.domain}
|
|
177
|
+
<span class="truncate text-xs text-[var(--sveltely-secondary-color)]"
|
|
178
|
+
>{website.domain}</span
|
|
179
|
+
>
|
|
180
|
+
{/if}
|
|
181
|
+
</div>
|
|
182
|
+
{#if selected}
|
|
183
|
+
<CheckIcon
|
|
184
|
+
size={14}
|
|
185
|
+
class="shrink-0 text-[var(--sveltely-primary-color)]"
|
|
186
|
+
/>
|
|
187
|
+
{/if}
|
|
188
|
+
{/snippet}
|
|
189
|
+
</Dropdown.Item>
|
|
190
|
+
{/each}
|
|
191
|
+
</div>
|
|
192
|
+
</ScrollView>
|
|
193
|
+
</div>
|
|
194
|
+
{/if}
|
|
195
|
+
</Dropdown.Section>
|
|
196
|
+
</Dropdown>
|
|
197
|
+
<p class="text-xs text-[var(--sveltely-secondary-color)]">Actions clicked: {actionCount}</p>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export declare const demo: {
|
|
2
2
|
name: string;
|
|
3
3
|
description: string;
|
|
4
|
+
columnSpan: number;
|
|
4
5
|
};
|
|
5
|
-
import Dropdown from './
|
|
6
|
+
import Dropdown from './index';
|
|
6
7
|
declare const Dropdown: import("svelte").Component<Record<string, never>, {}, "">;
|
|
7
8
|
type Dropdown = ReturnType<typeof Dropdown>;
|
|
8
9
|
export default Dropdown;
|