fulldev-ui 0.11.0 → 0.12.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/CHANGELOG.md +29 -0
- package/package.json +24 -20
- package/public/r/accordion.json +2 -2
- package/public/r/alert-dialog.json +2 -2
- package/public/r/banner-2.json +1 -1
- package/public/r/banner.json +1 -5
- package/public/r/blocks-1.json +1 -1
- package/public/r/button.json +1 -1
- package/public/r/collapsible.json +2 -2
- package/public/r/combobox.json +4 -3
- package/public/r/command.json +5 -4
- package/public/r/contact-1.json +1 -1
- package/public/r/contact-2.json +1 -1
- package/public/r/contact-3.json +1 -1
- package/public/r/dialog.json +2 -2
- package/public/r/doc-1.json +1 -1
- package/public/r/dropdown-menu.json +4 -4
- package/public/r/hover-card.json +4 -4
- package/public/r/input-group.json +0 -1
- package/public/r/layout.json +3 -0
- package/public/r/navigation-menu.json +3 -3
- package/public/r/popover.json +3 -3
- package/public/r/radio-group.json +2 -2
- package/public/r/registry.json +26 -26
- package/public/r/select.json +3 -3
- package/public/r/sheet.json +2 -2
- package/public/r/sidebar-1.json +1 -1
- package/public/r/sidebar.json +1 -1
- package/public/r/slider.json +2 -2
- package/public/r/switch.json +2 -2
- package/public/r/tabs.json +4 -4
- package/public/r/toggle.json +2 -2
- package/public/r/tooltip.json +3 -3
- package/public/r/typography.json +1 -1
- package/registry.json +31 -21
- package/src/components/blocks/banner-2.astro +7 -4
- package/src/components/blocks/blocks-1.astro +23 -23
- package/src/components/blocks/contact-1.astro +2 -1
- package/src/components/blocks/contact-2.astro +2 -1
- package/src/components/blocks/contact-3.astro +2 -1
- package/src/components/blocks/doc-1.astro +40 -26
- package/src/components/blocks/sidebar-1.astro +48 -46
- package/src/components/ui/accordion/accordion.astro +8 -2
- package/src/components/ui/alert-dialog/alert-dialog.astro +8 -2
- package/src/components/ui/banner/banner.astro +23 -41
- package/src/components/ui/button/button.astro +4 -1
- package/src/components/ui/collapsible/collapsible.astro +8 -2
- package/src/components/ui/combobox/combobox-content.astro +1 -1
- package/src/components/ui/combobox/combobox.astro +9 -17
- package/src/components/ui/command/command-dialog.astro +1 -0
- package/src/components/ui/command/command.astro +40 -25
- package/src/components/ui/dialog/dialog.astro +8 -2
- package/src/components/ui/dropdown-menu/dropdown-menu-content.astro +1 -1
- package/src/components/ui/dropdown-menu/dropdown-menu-item.astro +40 -9
- package/src/components/ui/dropdown-menu/dropdown-menu.astro +8 -2
- package/src/components/ui/hover-card/hover-card-content.astro +1 -1
- package/src/components/ui/hover-card/hover-card.astro +15 -4
- package/src/components/ui/navigation-menu/navigation-menu-positioner.astro +1 -1
- package/src/components/ui/navigation-menu/navigation-menu.astro +11 -2
- package/src/components/ui/popover/popover-content.astro +2 -1
- package/src/components/ui/popover/popover.astro +9 -2
- package/src/components/ui/radio-group/radio-group.astro +8 -2
- package/src/components/ui/select/select-content.astro +2 -2
- package/src/components/ui/select/select.astro +11 -7
- package/src/components/ui/sheet/sheet.astro +8 -2
- package/src/components/ui/slider/slider.astro +10 -4
- package/src/components/ui/switch/switch.astro +8 -2
- package/src/components/ui/tabs/tabs-content.astro +1 -1
- package/src/components/ui/tabs/tabs-trigger.astro +3 -2
- package/src/components/ui/tabs/tabs.astro +8 -2
- package/src/components/ui/toggle/toggle.astro +8 -2
- package/src/components/ui/tooltip/tooltip-content.astro +1 -1
- package/src/components/ui/tooltip/tooltip.astro +11 -2
- package/src/components/ui/typography/typography.astro +1 -1
- package/src/styles/global.css +2 -2
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
DropdownMenu,
|
|
23
23
|
DropdownMenuContent,
|
|
24
|
+
DropdownMenuItem,
|
|
24
25
|
DropdownMenuTrigger,
|
|
25
26
|
} from "@/components/ui/dropdown-menu"
|
|
26
27
|
import { SectionContainer } from "@/components/ui/section"
|
|
@@ -180,11 +181,10 @@ const openLinks = markdownUrl
|
|
|
180
181
|
</DropdownMenuTrigger>
|
|
181
182
|
<DropdownMenuContent align="end" sideOffset={6} class="w-56">
|
|
182
183
|
{openLinks.map((link) => (
|
|
183
|
-
<
|
|
184
|
+
<DropdownMenuItem
|
|
184
185
|
href={link.href}
|
|
185
186
|
target="_blank"
|
|
186
187
|
rel="noreferrer noopener"
|
|
187
|
-
class="hover:bg-accent hover:text-accent-foreground flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none"
|
|
188
188
|
>
|
|
189
189
|
{link.icon === "markdown" && <Markdown class="size-4" />}
|
|
190
190
|
{link.icon === "chatgpt" && (
|
|
@@ -202,7 +202,7 @@ const openLinks = markdownUrl
|
|
|
202
202
|
{link.icon === "cursor" && <Cursor class="size-4" />}
|
|
203
203
|
<span>{link.label}</span>
|
|
204
204
|
<ExternalLink class="text-muted-foreground ml-auto size-3.5" />
|
|
205
|
-
</
|
|
205
|
+
</DropdownMenuItem>
|
|
206
206
|
))}
|
|
207
207
|
</DropdownMenuContent>
|
|
208
208
|
</DropdownMenu>
|
|
@@ -299,38 +299,52 @@ const openLinks = markdownUrl
|
|
|
299
299
|
}
|
|
300
300
|
</SectionContainer>
|
|
301
301
|
|
|
302
|
-
<script
|
|
302
|
+
<script>
|
|
303
303
|
const copyIcon = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></svg>`
|
|
304
304
|
const checkIcon = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"></path></svg>`
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
305
|
+
const initializeCodeBlocks = () => {
|
|
306
|
+
document
|
|
307
|
+
.querySelectorAll("[data-slot='typography'] > pre")
|
|
308
|
+
.forEach((pre) => {
|
|
309
|
+
if (pre.closest(".docs-code-block")) return
|
|
310
|
+
const wrapper = document.createElement("div")
|
|
311
|
+
const button = document.createElement("button")
|
|
312
|
+
wrapper.className = "docs-code-block"
|
|
313
|
+
button.type = "button"
|
|
314
|
+
button.className = "docs-code-copy"
|
|
315
|
+
button.ariaLabel = "Copy code"
|
|
316
|
+
button.innerHTML = `<span data-copy-icon>${copyIcon}</span><span data-check-icon class="hidden">${checkIcon}</span>`
|
|
317
|
+
pre.before(wrapper)
|
|
318
|
+
wrapper.append(pre, button)
|
|
319
|
+
})
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
initializeCodeBlocks()
|
|
323
|
+
document.addEventListener("astro:page-load", initializeCodeBlocks)
|
|
324
|
+
|
|
325
|
+
document.addEventListener("click", async (event) => {
|
|
326
|
+
if (!(event.target instanceof Element)) return
|
|
327
|
+
const button = event.target.closest(
|
|
319
328
|
"[id^='docs-copy-page-'], .docs-code-copy"
|
|
320
329
|
)
|
|
321
|
-
if (!button) return
|
|
330
|
+
if (!(button instanceof HTMLButtonElement)) return
|
|
322
331
|
const source =
|
|
323
332
|
button.dataset.source ??
|
|
324
333
|
button
|
|
325
334
|
.closest(".docs-code-block")
|
|
326
335
|
?.querySelector("pre")
|
|
327
336
|
?.textContent?.replace(/\n$/, "")
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
button.querySelector("[data-
|
|
333
|
-
|
|
334
|
-
|
|
337
|
+
|
|
338
|
+
try {
|
|
339
|
+
await navigator.clipboard.writeText(source ?? "")
|
|
340
|
+
button.querySelector("[data-copy-icon]")?.classList.add("hidden")
|
|
341
|
+
button.querySelector("[data-check-icon]")?.classList.remove("hidden")
|
|
342
|
+
setTimeout(() => {
|
|
343
|
+
button.querySelector("[data-copy-icon]")?.classList.remove("hidden")
|
|
344
|
+
button.querySelector("[data-check-icon]")?.classList.add("hidden")
|
|
345
|
+
}, 1200)
|
|
346
|
+
} catch {
|
|
347
|
+
// Keep the copy state unchanged so the action can be retried.
|
|
348
|
+
}
|
|
335
349
|
})
|
|
336
350
|
</script>
|
|
@@ -23,11 +23,12 @@ import {
|
|
|
23
23
|
CommandList,
|
|
24
24
|
CommandShortcut,
|
|
25
25
|
} from "@/components/ui/command"
|
|
26
|
-
import {
|
|
26
|
+
import { DialogTrigger } from "@/components/ui/dialog"
|
|
27
27
|
import {
|
|
28
28
|
DropdownMenu,
|
|
29
29
|
DropdownMenuContent,
|
|
30
30
|
DropdownMenuGroup,
|
|
31
|
+
DropdownMenuItem,
|
|
31
32
|
DropdownMenuTrigger,
|
|
32
33
|
} from "@/components/ui/dropdown-menu"
|
|
33
34
|
import { Header, HeaderContainer, HeaderGroup } from "@/components/ui/header"
|
|
@@ -139,7 +140,7 @@ try {
|
|
|
139
140
|
<SidebarProvider>
|
|
140
141
|
<Sidebar class={cn("", className)} collapsible="offcanvas" variant="inset">
|
|
141
142
|
<SidebarHeader class="flex-col">
|
|
142
|
-
<SidebarMenuButton size="lg"
|
|
143
|
+
<SidebarMenuButton size="lg" href={logo.href}>
|
|
143
144
|
<LogoImage
|
|
144
145
|
src={logo.src}
|
|
145
146
|
srcLight={logo.srcLight}
|
|
@@ -148,8 +149,14 @@ try {
|
|
|
148
149
|
/>
|
|
149
150
|
<LogoText class="font-semibold">{logo.label}</LogoText>
|
|
150
151
|
</SidebarMenuButton>
|
|
151
|
-
<
|
|
152
|
+
<CommandDialog
|
|
153
|
+
class="w-full"
|
|
154
|
+
data-search-dialog
|
|
155
|
+
title={search.label}
|
|
156
|
+
description={search.label}
|
|
157
|
+
>
|
|
152
158
|
<DialogTrigger
|
|
159
|
+
slot="trigger"
|
|
153
160
|
variant="outline"
|
|
154
161
|
size="sm"
|
|
155
162
|
class="w-full justify-start shadow-none"
|
|
@@ -165,40 +172,38 @@ try {
|
|
|
165
172
|
</Kbd>
|
|
166
173
|
</DialogTrigger>
|
|
167
174
|
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
<
|
|
174
|
-
<CommandEmpty>{search.empty}</CommandEmpty>
|
|
175
|
+
<Command
|
|
176
|
+
class="[&_[data-slot=command-item][data-selected]]:bg-accent [&_[data-slot=command-item][data-selected]]:text-accent-foreground"
|
|
177
|
+
>
|
|
178
|
+
<CommandInput autofocus placeholder={search.label} />
|
|
179
|
+
<CommandList>
|
|
180
|
+
<CommandEmpty>{search.empty}</CommandEmpty>
|
|
175
181
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
</Dialog>
|
|
182
|
+
{
|
|
183
|
+
searchGroups.map((group) => (
|
|
184
|
+
<CommandGroup heading={group.label}>
|
|
185
|
+
{group.items.map((item) => (
|
|
186
|
+
<CommandItem
|
|
187
|
+
href={item.href}
|
|
188
|
+
value={`${item.group} ${item.label}`}
|
|
189
|
+
label={item.label}
|
|
190
|
+
keywords={[
|
|
191
|
+
item.group,
|
|
192
|
+
item.title,
|
|
193
|
+
item.path,
|
|
194
|
+
item.description,
|
|
195
|
+
]}
|
|
196
|
+
>
|
|
197
|
+
{item.label}
|
|
198
|
+
<CommandShortcut>{item.href}</CommandShortcut>
|
|
199
|
+
</CommandItem>
|
|
200
|
+
))}
|
|
201
|
+
</CommandGroup>
|
|
202
|
+
))
|
|
203
|
+
}
|
|
204
|
+
</CommandList>
|
|
205
|
+
</Command>
|
|
206
|
+
</CommandDialog>
|
|
202
207
|
</SidebarHeader>
|
|
203
208
|
<SidebarContent
|
|
204
209
|
class="[mask-image:linear-gradient(to_bottom,transparent,black_1rem,black_calc(100%_-_1rem),transparent)] [-webkit-mask-image:linear-gradient(to_bottom,transparent,black_1rem,black_calc(100%_-_1rem),transparent)] group-data-[collapsible=icon]:[mask-image:none] group-data-[collapsible=icon]:[-webkit-mask-image:none]"
|
|
@@ -268,7 +273,7 @@ try {
|
|
|
268
273
|
<DropdownMenuContent align="start">
|
|
269
274
|
<DropdownMenuGroup>
|
|
270
275
|
{breadcrumb.menu.map((menuItem) => (
|
|
271
|
-
<
|
|
276
|
+
<DropdownMenuItem
|
|
272
277
|
href={menuItem.href}
|
|
273
278
|
aria-current={
|
|
274
279
|
normalizePath(menuItem.href) ===
|
|
@@ -276,10 +281,10 @@ try {
|
|
|
276
281
|
? "page"
|
|
277
282
|
: undefined
|
|
278
283
|
}
|
|
279
|
-
class="
|
|
284
|
+
class="aria-[current=page]:text-foreground"
|
|
280
285
|
>
|
|
281
286
|
{menuItem.label}
|
|
282
|
-
</
|
|
287
|
+
</DropdownMenuItem>
|
|
283
288
|
))}
|
|
284
289
|
</DropdownMenuGroup>
|
|
285
290
|
</DropdownMenuContent>
|
|
@@ -308,12 +313,9 @@ try {
|
|
|
308
313
|
<DropdownMenuContent align="start">
|
|
309
314
|
<DropdownMenuGroup>
|
|
310
315
|
{breadcrumb.menu.map((item) => (
|
|
311
|
-
<
|
|
312
|
-
href={item.href}
|
|
313
|
-
class="hover:bg-accent hover:text-accent-foreground flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none"
|
|
314
|
-
>
|
|
316
|
+
<DropdownMenuItem href={item.href}>
|
|
315
317
|
{item.label}
|
|
316
|
-
</
|
|
318
|
+
</DropdownMenuItem>
|
|
317
319
|
))}
|
|
318
320
|
</DropdownMenuGroup>
|
|
319
321
|
</DropdownMenuContent>
|
|
@@ -325,7 +327,7 @@ try {
|
|
|
325
327
|
</BreadcrumbList>
|
|
326
328
|
</Breadcrumb>
|
|
327
329
|
</HeaderGroup>
|
|
328
|
-
<HeaderGroup>
|
|
330
|
+
<HeaderGroup class="shrink-0">
|
|
329
331
|
<Button
|
|
330
332
|
as="a"
|
|
331
333
|
href={`https://github.com/${githubRepo}`}
|
|
@@ -336,7 +338,7 @@ try {
|
|
|
336
338
|
aria-label={`View ${githubRepo} on GitHub`}
|
|
337
339
|
>
|
|
338
340
|
<Icon name="github" />
|
|
339
|
-
<span>{githubStars}</span>
|
|
341
|
+
<span class="hidden sm:inline">{githubStars}</span>
|
|
340
342
|
</Button>
|
|
341
343
|
<ThemeToggle />
|
|
342
344
|
</HeaderGroup>
|
|
@@ -48,6 +48,12 @@ const serializedDefaultValue = Array.isArray(defaultValue)
|
|
|
48
48
|
<script>
|
|
49
49
|
import { create } from "@data-slot/accordion"
|
|
50
50
|
|
|
51
|
-
create
|
|
52
|
-
|
|
51
|
+
const controllers: ReturnType<typeof create> = []
|
|
52
|
+
const initialize = () => controllers.push(...create())
|
|
53
|
+
initialize()
|
|
54
|
+
document.addEventListener("astro:page-load", initialize)
|
|
55
|
+
document.addEventListener("astro:before-swap", () => {
|
|
56
|
+
for (const controller of controllers) controller.destroy()
|
|
57
|
+
controllers.length = 0
|
|
58
|
+
})
|
|
53
59
|
</script>
|
|
@@ -33,6 +33,12 @@ const {
|
|
|
33
33
|
<script>
|
|
34
34
|
import { create } from "@data-slot/alert-dialog"
|
|
35
35
|
|
|
36
|
-
create
|
|
37
|
-
|
|
36
|
+
const controllers: ReturnType<typeof create> = []
|
|
37
|
+
const initialize = () => controllers.push(...create())
|
|
38
|
+
initialize()
|
|
39
|
+
document.addEventListener("astro:page-load", initialize)
|
|
40
|
+
document.addEventListener("astro:before-swap", () => {
|
|
41
|
+
for (const controller of controllers) controller.destroy()
|
|
42
|
+
controllers.length = 0
|
|
43
|
+
})
|
|
38
44
|
</script>
|
|
@@ -35,51 +35,33 @@ const { class: className, variant, storageKey, ...props } = Astro.props
|
|
|
35
35
|
<slot />
|
|
36
36
|
</aside>
|
|
37
37
|
|
|
38
|
-
<script
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
if (!document.documentElement.dataset[initializedKey]) {
|
|
42
|
-
document.documentElement.dataset[initializedKey] = "true"
|
|
43
|
-
|
|
44
|
-
const getStorageToken = (key) => `banner:${key}`
|
|
45
|
-
|
|
46
|
-
const syncBanners = () => {
|
|
47
|
-
document.querySelectorAll("[data-slot='banner']").forEach((banner) => {
|
|
48
|
-
if (!(banner instanceof HTMLElement)) return
|
|
49
|
-
|
|
50
|
-
const storageKey = banner.dataset.bannerStorageKey
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
storageKey &&
|
|
54
|
-
sessionStorage.getItem(getStorageToken(storageKey)) === "hidden"
|
|
55
|
-
) {
|
|
56
|
-
banner.hidden = true
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
syncBanners()
|
|
62
|
-
|
|
63
|
-
document.addEventListener("click", (event) => {
|
|
64
|
-
const target = event.target
|
|
65
|
-
|
|
66
|
-
if (!(target instanceof Element)) return
|
|
67
|
-
|
|
68
|
-
const closeButton = target.closest("[data-slot='banner-close']")
|
|
69
|
-
|
|
70
|
-
if (!(closeButton instanceof HTMLElement)) return
|
|
71
|
-
|
|
72
|
-
const banner = closeButton.closest("[data-slot='banner']")
|
|
38
|
+
<script>
|
|
39
|
+
const getStorageToken = (key: string) => `banner:${key}`
|
|
73
40
|
|
|
41
|
+
const syncBanners = () => {
|
|
42
|
+
document.querySelectorAll("[data-slot='banner']").forEach((banner) => {
|
|
74
43
|
if (!(banner instanceof HTMLElement)) return
|
|
75
|
-
|
|
76
|
-
banner.hidden = true
|
|
77
|
-
|
|
78
44
|
const storageKey = banner.dataset.bannerStorageKey
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
sessionStorage.
|
|
45
|
+
if (
|
|
46
|
+
storageKey &&
|
|
47
|
+
sessionStorage.getItem(getStorageToken(storageKey)) === "hidden"
|
|
48
|
+
) {
|
|
49
|
+
banner.hidden = true
|
|
82
50
|
}
|
|
83
51
|
})
|
|
84
52
|
}
|
|
53
|
+
|
|
54
|
+
syncBanners()
|
|
55
|
+
document.addEventListener("astro:page-load", syncBanners)
|
|
56
|
+
|
|
57
|
+
document.addEventListener("click", (event) => {
|
|
58
|
+
if (!(event.target instanceof Element)) return
|
|
59
|
+
const closeButton = event.target.closest("[data-slot='banner-close']")
|
|
60
|
+
const banner = closeButton?.closest("[data-slot='banner']")
|
|
61
|
+
if (!(banner instanceof HTMLElement)) return
|
|
62
|
+
banner.hidden = true
|
|
63
|
+
const storageKey = banner.dataset.bannerStorageKey
|
|
64
|
+
if (storageKey)
|
|
65
|
+
sessionStorage.setItem(getStorageToken(storageKey), "hidden")
|
|
66
|
+
})
|
|
85
67
|
</script>
|
|
@@ -15,12 +15,15 @@ const {
|
|
|
15
15
|
size,
|
|
16
16
|
...props
|
|
17
17
|
} = Astro.props
|
|
18
|
+
|
|
19
|
+
const attributes: Record<string, unknown> = { ...props }
|
|
20
|
+
if (Tag === "button") attributes.type ??= "button"
|
|
18
21
|
---
|
|
19
22
|
|
|
20
23
|
<Tag
|
|
21
24
|
data-slot="button"
|
|
22
25
|
class={cn(buttonVariants({ variant, size }), className)}
|
|
23
|
-
{...
|
|
26
|
+
{...attributes}
|
|
24
27
|
>
|
|
25
28
|
<slot />
|
|
26
29
|
</Tag>
|
|
@@ -29,6 +29,12 @@ const {
|
|
|
29
29
|
<script>
|
|
30
30
|
import { create } from "@data-slot/collapsible"
|
|
31
31
|
|
|
32
|
-
create
|
|
33
|
-
|
|
32
|
+
const controllers: ReturnType<typeof create> = []
|
|
33
|
+
const initialize = () => controllers.push(...create())
|
|
34
|
+
initialize()
|
|
35
|
+
document.addEventListener("astro:page-load", initialize)
|
|
36
|
+
document.addEventListener("astro:before-swap", () => {
|
|
37
|
+
for (const controller of controllers) controller.destroy()
|
|
38
|
+
controllers.length = 0
|
|
39
|
+
})
|
|
34
40
|
</script>
|
|
@@ -67,22 +67,14 @@ const {
|
|
|
67
67
|
</div>
|
|
68
68
|
|
|
69
69
|
<script>
|
|
70
|
-
import {
|
|
70
|
+
import { create } from "@data-slot/combobox"
|
|
71
71
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
createCombobox(root as HTMLElement)
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
initCombobox()
|
|
86
|
-
|
|
87
|
-
document.addEventListener("astro:page-load", initCombobox)
|
|
72
|
+
const controllers: ReturnType<typeof create> = []
|
|
73
|
+
const initialize = () => controllers.push(...create())
|
|
74
|
+
initialize()
|
|
75
|
+
document.addEventListener("astro:page-load", initialize)
|
|
76
|
+
document.addEventListener("astro:before-swap", () => {
|
|
77
|
+
for (const controller of controllers) controller.destroy()
|
|
78
|
+
controllers.length = 0
|
|
79
|
+
})
|
|
88
80
|
</script>
|
|
@@ -46,31 +46,46 @@ const {
|
|
|
46
46
|
|
|
47
47
|
<script>
|
|
48
48
|
import { create } from "@data-slot/command"
|
|
49
|
+
import { getParts } from "@data-slot/core"
|
|
49
50
|
|
|
50
|
-
const
|
|
51
|
-
|
|
51
|
+
const controllers: ReturnType<typeof create> = []
|
|
52
|
+
const initialize = () => controllers.push(...create())
|
|
53
|
+
initialize()
|
|
54
|
+
document.addEventListener("astro:page-load", initialize)
|
|
55
|
+
document.addEventListener("astro:before-swap", () => {
|
|
56
|
+
for (const controller of controllers) controller.destroy()
|
|
57
|
+
controllers.length = 0
|
|
58
|
+
})
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
60
|
+
// Data Slot selection does not activate links. Preserve native navigation.
|
|
61
|
+
document.addEventListener(
|
|
62
|
+
"keydown",
|
|
63
|
+
(event) => {
|
|
64
|
+
if (
|
|
65
|
+
event.key !== "Enter" ||
|
|
66
|
+
event.defaultPrevented ||
|
|
67
|
+
event.isComposing ||
|
|
68
|
+
event.keyCode === 229
|
|
69
|
+
)
|
|
70
|
+
return
|
|
71
|
+
const input = event.target
|
|
72
|
+
if (
|
|
73
|
+
!(input instanceof HTMLInputElement) ||
|
|
74
|
+
input.dataset.slot !== "command-input"
|
|
75
|
+
)
|
|
76
|
+
return
|
|
77
|
+
const root = input.closest('[data-slot="command"]')
|
|
78
|
+
if (!root) return
|
|
79
|
+
const item = getParts<HTMLAnchorElement>(root, "command-item").find(
|
|
80
|
+
(item) =>
|
|
81
|
+
item.hasAttribute("data-selected") &&
|
|
82
|
+
item.hasAttribute("href") &&
|
|
83
|
+
item.getAttribute("aria-disabled") !== "true"
|
|
84
|
+
)
|
|
85
|
+
if (!item) return
|
|
86
|
+
event.preventDefault()
|
|
87
|
+
item.click()
|
|
88
|
+
},
|
|
89
|
+
true
|
|
90
|
+
)
|
|
76
91
|
</script>
|
|
@@ -36,6 +36,12 @@ const {
|
|
|
36
36
|
<script>
|
|
37
37
|
import { create } from "@data-slot/dialog"
|
|
38
38
|
|
|
39
|
-
create
|
|
40
|
-
|
|
39
|
+
const controllers: ReturnType<typeof create> = []
|
|
40
|
+
const initialize = () => controllers.push(...create())
|
|
41
|
+
initialize()
|
|
42
|
+
document.addEventListener("astro:page-load", initialize)
|
|
43
|
+
document.addEventListener("astro:before-swap", () => {
|
|
44
|
+
for (const controller of controllers) controller.destroy()
|
|
45
|
+
controllers.length = 0
|
|
46
|
+
})
|
|
41
47
|
</script>
|
|
@@ -3,13 +3,16 @@ import type { HTMLAttributes } from "astro/types"
|
|
|
3
3
|
|
|
4
4
|
import { cn } from "@/lib/utils"
|
|
5
5
|
|
|
6
|
-
type Props = HTMLAttributes<"button"> &
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
type Props = HTMLAttributes<"button"> &
|
|
7
|
+
HTMLAttributes<"a"> & {
|
|
8
|
+
as?: "button" | "a"
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
variant?: "default" | "destructive"
|
|
11
|
+
inset?: boolean
|
|
12
|
+
}
|
|
11
13
|
|
|
12
14
|
const {
|
|
15
|
+
as: Tag = "href" in Astro.props ? "a" : "button",
|
|
13
16
|
class: className,
|
|
14
17
|
type = "button",
|
|
15
18
|
disabled,
|
|
@@ -19,13 +22,13 @@ const {
|
|
|
19
22
|
} = Astro.props
|
|
20
23
|
---
|
|
21
24
|
|
|
22
|
-
<
|
|
25
|
+
<Tag
|
|
23
26
|
data-slot="dropdown-menu-item"
|
|
24
27
|
data-disabled={disabled}
|
|
25
28
|
data-variant={variant}
|
|
26
29
|
data-inset={inset}
|
|
27
|
-
disabled={disabled ? true : undefined}
|
|
28
|
-
type={type}
|
|
30
|
+
disabled={Tag === "button" && disabled ? true : undefined}
|
|
31
|
+
type={Tag === "button" ? type : undefined}
|
|
29
32
|
class={cn(
|
|
30
33
|
"group/dropdown-menu-item data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground not-data-[variant=destructive]:data-[highlighted]:**:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:data-[highlighted]:bg-destructive/10 data-[variant=destructive]:data-[highlighted]:text-destructive dark:data-[variant=destructive]:data-[highlighted]:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive relative flex w-full cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
31
34
|
className
|
|
@@ -33,4 +36,32 @@ const {
|
|
|
33
36
|
{...props}
|
|
34
37
|
>
|
|
35
38
|
<slot />
|
|
36
|
-
</
|
|
39
|
+
</Tag>
|
|
40
|
+
|
|
41
|
+
<script>
|
|
42
|
+
// Data Slot owns selection; links also need native keyboard activation.
|
|
43
|
+
document.addEventListener(
|
|
44
|
+
"keydown",
|
|
45
|
+
(event) => {
|
|
46
|
+
if (
|
|
47
|
+
event.defaultPrevented ||
|
|
48
|
+
event.isComposing ||
|
|
49
|
+
!["Enter", " "].includes(event.key)
|
|
50
|
+
)
|
|
51
|
+
return
|
|
52
|
+
const item =
|
|
53
|
+
event.target instanceof Element
|
|
54
|
+
? event.target.closest('[data-slot="dropdown-menu-item"][href]')
|
|
55
|
+
: null
|
|
56
|
+
if (
|
|
57
|
+
!(item instanceof HTMLAnchorElement) ||
|
|
58
|
+
item.getAttribute("aria-disabled") === "true"
|
|
59
|
+
)
|
|
60
|
+
return
|
|
61
|
+
event.preventDefault()
|
|
62
|
+
event.stopPropagation()
|
|
63
|
+
item.click()
|
|
64
|
+
},
|
|
65
|
+
true
|
|
66
|
+
)
|
|
67
|
+
</script>
|
|
@@ -67,6 +67,12 @@ const defaultValuesAttr =
|
|
|
67
67
|
<script>
|
|
68
68
|
import { create } from "@data-slot/dropdown-menu"
|
|
69
69
|
|
|
70
|
-
create
|
|
71
|
-
|
|
70
|
+
const controllers: ReturnType<typeof create> = []
|
|
71
|
+
const initialize = () => controllers.push(...create())
|
|
72
|
+
initialize()
|
|
73
|
+
document.addEventListener("astro:page-load", initialize)
|
|
74
|
+
document.addEventListener("astro:before-swap", () => {
|
|
75
|
+
for (const controller of controllers) controller.destroy()
|
|
76
|
+
controllers.length = 0
|
|
77
|
+
})
|
|
72
78
|
</script>
|