@adea-ai/ui 0.95.0 → 0.95.2
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/README.md +1 -0
- package/dist/components/layout/sidebar-nav/sidebar-nav.d.ts +1 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.js +6 -6
- package/dist/components/layout/sidebar-nav/sidebar-nav.js.map +1 -1
- package/dist/components/ui/dialog/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog/dialog.js +5 -1
- package/dist/components/ui/dialog/dialog.js.map +1 -1
- package/dist/components/ui/modal-dialog/modal-dialog.d.ts +6 -0
- package/dist/components/ui/modal-dialog/modal-dialog.d.ts.map +1 -1
- package/dist/components/ui/modal-dialog/modal-dialog.js +4 -0
- package/dist/components/ui/modal-dialog/modal-dialog.js.map +1 -1
- package/dist/components/ui/sheet/sheet.d.ts +8 -1
- package/dist/components/ui/sheet/sheet.d.ts.map +1 -1
- package/dist/components/ui/sheet/sheet.js +43 -19
- package/dist/components/ui/sheet/sheet.js.map +1 -1
- package/dist/components/ui/toggle-group/toggle-group.d.ts.map +1 -1
- package/dist/components/ui/toggle-group/toggle-group.js +20 -7
- package/dist/components/ui/toggle-group/toggle-group.js.map +1 -1
- package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +6 -6
- package/dist/r/src/components/ui/dialog/dialog.tsx +6 -1
- package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +20 -0
- package/dist/r/src/components/ui/sheet/sheet.tsx +37 -4
- package/dist/r/src/components/ui/toggle-group/toggle-group.tsx +18 -1
- package/package.json +1 -1
- package/src/components/layout/sidebar-nav/sidebar-nav.tsx +6 -6
- package/src/components/ui/dialog/dialog.tsx +6 -1
- package/src/components/ui/modal-dialog/modal-dialog.tsx +20 -0
- package/src/components/ui/sheet/sheet.tsx +37 -4
- package/src/components/ui/toggle-group/toggle-group.tsx +18 -1
package/README.md
CHANGED
|
@@ -94,6 +94,7 @@ updates, navigation, and other effects remain host callbacks.
|
|
|
94
94
|
|
|
95
95
|
`SidebarNavTitle` accepts polymorphic `as` for a host's title heading.
|
|
96
96
|
`SidebarNavLabel` keeps a row's complete accessible text while truncating its visible label, leaving room for adjacent controls. The navigation root clamps its preferred width to the containing lane at narrow widths and enlarged root text. `SidebarNavRow` moves adjacent actions onto a second line when the item's preferred label space and the controls cannot fit together.
|
|
97
|
+
Row and section actions remain visible when any coarse pointer is available, including on hybrid devices; hover, keyboard focus, and an expanded menu continue to reveal them as well. Action hit-area size remains determined by the supplied shared control size.
|
|
97
98
|
Use `SidebarNavSection.headingAs` (h1 through h6) for section headings.
|
|
98
99
|
Sections may be uncontrolled with `defaultOpen` or controlled with `open` and
|
|
99
100
|
`onOpenChange`. Put disclosure-button attributes and host-owned row interactions
|
|
@@ -88,7 +88,7 @@ export type SidebarNavItemProps<T extends ValidComponent = 'a'> = PolymorphicPro
|
|
|
88
88
|
}>;
|
|
89
89
|
/**
|
|
90
90
|
* A sidebar row. Exported classes, so a caller's own element can match it.
|
|
91
|
-
*
|
|
91
|
+
* Any coarse pointer gets a 44px target without changing desktop density.
|
|
92
92
|
*/
|
|
93
93
|
export declare const sidebarNavItemClass: string;
|
|
94
94
|
export declare const sidebarNavItemStateClass: {
|
|
@@ -10,10 +10,10 @@ var _tmpl$3 = /*#__PURE__*/ template(`<div data-slot=sidebar-nav-footer>`);
|
|
|
10
10
|
var _tmpl$4 = /*#__PURE__*/ template(`<span class="min-w-0 flex-1 truncate">`);
|
|
11
11
|
var _tmpl$5 = /*#__PURE__*/ template(`<span class="shrink-0 tabular-nums text-muted-foreground">`);
|
|
12
12
|
var _tmpl$6 = /*#__PURE__*/ template(`<button>`);
|
|
13
|
-
var _tmpl$7 = /*#__PURE__*/ template(`<span class="shrink-0 opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(
|
|
13
|
+
var _tmpl$7 = /*#__PURE__*/ template(`<span class="shrink-0 opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(any-pointer:coarse)]:opacity-100">`);
|
|
14
14
|
var _tmpl$8 = /*#__PURE__*/ template(`<div class="flex flex-col gap-0.5">`);
|
|
15
15
|
var _tmpl$9 = /*#__PURE__*/ template(`<div data-slot=sidebar-nav-section><div data-slot=sidebar-nav-section-header>`);
|
|
16
|
-
var _tmpl$0 = /*#__PURE__*/ template(`<span data-slot=sidebar-nav-row-actions class="ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(
|
|
16
|
+
var _tmpl$0 = /*#__PURE__*/ template(`<span data-slot=sidebar-nav-row-actions class="ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(any-pointer:coarse)]:opacity-100">`);
|
|
17
17
|
var _tmpl$1 = /*#__PURE__*/ template(`<div data-slot=sidebar-nav-row>`);
|
|
18
18
|
var _tmpl$10 = /*#__PURE__*/ template(`<span data-slot=sidebar-nav-label>`);
|
|
19
19
|
var _tmpl$11 = /*#__PURE__*/ template(`<span class="ms-auto flex shrink-0 items-center gap-1">`);
|
|
@@ -184,7 +184,7 @@ function SidebarNavSection(props) {
|
|
|
184
184
|
trigger.onReorder?.(event.key === "ArrowUp" ? "up" : "down");
|
|
185
185
|
},
|
|
186
186
|
get ["class"]() {
|
|
187
|
-
return cn("flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(pointer:coarse)]:min-h-11", local.active ? "text-foreground" : "text-sidebar-muted-foreground");
|
|
187
|
+
return cn("flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11", local.active ? "text-foreground" : "text-sidebar-muted-foreground");
|
|
188
188
|
}
|
|
189
189
|
}), false, true);
|
|
190
190
|
insert(_el$8, heading);
|
|
@@ -214,7 +214,7 @@ function SidebarNavSection(props) {
|
|
|
214
214
|
}
|
|
215
215
|
}), null);
|
|
216
216
|
effect((_p$) => {
|
|
217
|
-
var _v$ = local.active ? "" : void 0, _v$2 = cn("group/section-header flex items-center gap-1 rounded-md px-2 py-1.5", { "[@media(pointer:coarse)]:py-0": local.collapsible }, local.active ? "bg-primary-subtle text-foreground" : "hover:bg-sidebar-accent/60");
|
|
217
|
+
var _v$ = local.active ? "" : void 0, _v$2 = cn("group/section-header flex items-center gap-1 rounded-md px-2 py-1.5", { "[@media(any-pointer:coarse)]:py-0": local.collapsible }, local.active ? "bg-primary-subtle text-foreground" : "hover:bg-sidebar-accent/60");
|
|
218
218
|
_v$ !== _p$.e && setAttribute(_el$7, "data-active", _p$.e = _v$);
|
|
219
219
|
_v$2 !== _p$.t && className(_el$7, _p$.t = _v$2);
|
|
220
220
|
return _p$;
|
|
@@ -269,11 +269,11 @@ function SidebarNavLabel(props) {
|
|
|
269
269
|
}
|
|
270
270
|
/**
|
|
271
271
|
* A sidebar row. Exported classes, so a caller's own element can match it.
|
|
272
|
-
*
|
|
272
|
+
* Any coarse pointer gets a 44px target without changing desktop density.
|
|
273
273
|
*/
|
|
274
274
|
var sidebarNavItemClass = [
|
|
275
275
|
"group/nav-item relative flex min-w-0 items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium",
|
|
276
|
-
"whitespace-nowrap transition-colors ease-out outline-none select-none [@media(pointer:coarse)]:min-h-11",
|
|
276
|
+
"whitespace-nowrap transition-colors ease-out outline-none select-none [@media(any-pointer:coarse)]:min-h-11",
|
|
277
277
|
"focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle",
|
|
278
278
|
"[&_svg]:size-4 [&_svg]:shrink-0"
|
|
279
279
|
].join(" ");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar-nav.js","names":["PolymorphicProps","Polymorphic","ChevronRight","ComponentProps","JSX","ValidComponent","Show","createSignal","splitProps","cn","invokeEventHandler","handler","event","Event","Array","isArray","callback","data","SidebarNavProps","T","class","SidebarNav","props","local","rest","_$createComponent","_$mergeProps","as","aria-label","children","SidebarNavHeader","_el$","_tmpl$","_$spread","SidebarNavTitleProps","SidebarNavTitle","SidebarNavContent","_el$2","_tmpl$2","SidebarNavFooter","_el$3","_tmpl$3","SidebarNavSectionTriggerProps","Omit","onReorder","direction","onClick","onKeyDown","SidebarNavSectionProps","label","collapsible","defaultOpen","active","open","onOpenChange","triggerProps","count","action","Element","headingAs","SidebarNavSection","uncontrolledOpen","setUncontrolledOpen","setOpen","next","undefined","trigger","triggerRest","heading","when","_el$4","_tmpl$4","_$insert","_el$5","_tmpl$5","_el$6","_tmpl$9","_el$7","firstChild","_$memo","fallback","_el$8","_tmpl$6","aria-expanded","aria-current","defaultPrevented","altKey","key","preventDefault","stopPropagation","_el$9","_tmpl$7","_el$0","_tmpl$8","_$effect","_p$","_v$","_v$2","e","_$setAttribute","t","_$className","SidebarNavRowProps","actions","SidebarNavRow","_el$1","_tmpl$1","_el$10","_tmpl$0","SidebarNavLabel","_el$11","_tmpl$10","SidebarNavItemProps","nested","trailing","sidebarNavItemClass","join","sidebarNavItemStateClass","idle","SidebarNavItem","data-active","_el$12","_tmpl$11","SidebarNavButton","_el$13","_tmpl$12","_$createComponent","_$mergeProps","_$memo","_$setAttribute","_$className"],"sources":["../../../../src/components/layout/sidebar-nav/sidebar-nav.tsx"],"sourcesContent":["import type { PolymorphicProps } from '@kobalte/core/polymorphic'\nimport { Polymorphic } from '@kobalte/core/polymorphic'\nimport { ChevronRight } from 'lucide-solid'\nimport type { ComponentProps, JSX, ValidComponent } from 'solid-js'\nimport { Show, createSignal, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\nfunction invokeEventHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n ;(handler as (event: Event) => void)(event)\n }\n}\n\n/**\n * SidebarNav.\n *\n * The secondary navigation column: the list of things inside the destination\n * the rail selected — projects, sessions, files, threads. It is a different\n * object from the rail, not a wider version of it, which is why it is a separate\n * component rather than the rail with labels on.\n *\n * Rows share one recipe with the rail's, so a row in a sidebar and a row in a\n * rail read as the same kind of thing at the same density. That recipe is\n * exactly KiroCrew's nav row: `text-sm font-medium`, `gap-2.5`, `px-3 py-2`,\n * `rounded-md`, `transition-colors`.\n *\n * The width comes from `--sidebar-width`. Sections collapse by default only when\n * the caller says so, because a section that starts collapsed and holds the\n * user's own work is a hidden default.\n */\nexport type SidebarNavProps<T extends ValidComponent = 'nav'> = PolymorphicProps<\n T,\n { class?: string; 'aria-label'?: string }\n>\n\nexport function SidebarNav<T extends ValidComponent = 'nav'>(props: SidebarNavProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavProps, ['class', 'aria-label', 'children'])\n\n return (\n <Polymorphic\n as=\"nav\"\n aria-label={local['aria-label'] ?? 'Section'}\n class={cn(\n 'bg-sidebar text-sidebar-foreground flex h-full w-sidebar min-w-0 max-w-full shrink-0 flex-col border-e border-sidebar-border',\n local.class\n )}\n {...(rest as ComponentProps<'nav'>)}\n >\n {local.children}\n </Polymorphic>\n )\n}\n\nexport function SidebarNavHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-header\"\n class={cn('flex h-topbar shrink-0 items-center justify-between gap-2 px-3', local.class)}\n {...rest}\n />\n )\n}\n\nexport type SidebarNavTitleProps<T extends ValidComponent = 'div'> = PolymorphicProps<\n T,\n { class?: string }\n>\n\nexport function SidebarNavTitle<T extends ValidComponent = 'div'>(props: SidebarNavTitleProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavTitleProps, ['class'])\n return (\n <Polymorphic\n as=\"div\"\n data-slot=\"sidebar-nav-title\"\n class={cn('truncate text-sm font-semibold tracking-tight', local.class)}\n {...(rest as ComponentProps<'div'>)}\n />\n )\n}\n\n/** The scrolling middle of the sidebar. */\nexport function SidebarNavContent(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-content\"\n class={cn('flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-2 py-2', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SidebarNavFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-footer\"\n class={cn('flex shrink-0 items-center gap-1 border-t border-sidebar-border p-2', local.class)}\n {...rest}\n />\n )\n}\n\n/** Props forwarded to a collapsible section's disclosure button. */\nexport type SidebarNavSectionTriggerProps = Omit<\n ComponentProps<'button'>,\n 'type' | 'aria-expanded' | 'onClick' | 'onKeyDown' | 'children' | 'class' | 'style'\n> & {\n /** Called for Alt+ArrowUp/Down; the host owns ordering and row identity. */\n onReorder?: (direction: 'up' | 'down') => void\n /** Runs before the section toggle and may cancel it with `preventDefault()`. */\n onClick?: ComponentProps<'button'>['onClick']\n /** Runs before shared Alt+Arrow handling and may cancel it with `preventDefault()`. */\n onKeyDown?: ComponentProps<'button'>['onKeyDown']\n}\n\n/**\n * A titled, collapsible group. Collapsible because a list of projects\n * inevitably outgrows the column, and the user needs to put the ones they are\n * not using away *without* them disappearing into a menu.\n */\nexport type SidebarNavSectionProps = ComponentProps<'div'> & {\n label: string\n /** Render a disclosure control instead of a plain heading. */\n collapsible?: boolean\n defaultOpen?: boolean\n /** Mark the current project/group without changing its disclosure state. */\n active?: boolean\n /** Controlled disclosure state. When supplied, the host owns changes. */\n open?: boolean\n /** Called for user-initiated disclosure changes. */\n onOpenChange?: (open: boolean) => void\n /** Native props and reorder callbacks for the disclosure control. */\n triggerProps?: SidebarNavSectionTriggerProps\n /** Count shown beside the label. */\n count?: number\n /** A control at the trailing edge of the heading row. */\n action?: JSX.Element\n /** Semantic heading element for a host's section hierarchy. */\n headingAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n}\n\nexport function SidebarNavSection(props: SidebarNavSectionProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'collapsible',\n 'defaultOpen',\n 'active',\n 'open',\n 'onOpenChange',\n 'triggerProps',\n 'count',\n 'action',\n 'headingAs',\n 'children',\n ])\n const [uncontrolledOpen, setUncontrolledOpen] = createSignal(local.defaultOpen ?? true)\n const open = () => local.open ?? uncontrolledOpen()\n const setOpen = (next: boolean) => {\n if (local.open === undefined) setUncontrolledOpen(next)\n local.onOpenChange?.(next)\n }\n\n const [trigger, triggerRest] = splitProps(local.triggerProps ?? {}, [\n 'onClick',\n 'onKeyDown',\n 'onReorder',\n ])\n\n const heading = (\n <>\n <Show when={local.collapsible}>\n <ChevronRight\n aria-hidden=\"true\"\n class={cn('size-3.5 shrink-0 text-muted-foreground transition-transform ease-out', {\n 'rotate-90': open(),\n })}\n />\n </Show>\n <span class=\"min-w-0 flex-1 truncate\">{local.label}</span>\n <Show when={local.count !== undefined}>\n <span class=\"shrink-0 tabular-nums text-muted-foreground\">{local.count}</span>\n </Show>\n </>\n )\n\n return (\n <div data-slot=\"sidebar-nav-section\" class={cn('flex flex-col gap-0.5', local.class)} {...rest}>\n <div\n data-slot=\"sidebar-nav-section-header\"\n data-active={local.active ? '' : undefined}\n class={cn(\n 'group/section-header flex items-center gap-1 rounded-md px-2 py-1.5',\n { '[@media(pointer:coarse)]:py-0': local.collapsible },\n local.active ? 'bg-primary-subtle text-foreground' : 'hover:bg-sidebar-accent/60'\n )}\n >\n <Polymorphic\n as={local.headingAs ?? 'div'}\n aria-label={local.headingAs ? local.label : undefined}\n class={cn(\n 'flex min-w-0 flex-1 items-center gap-1.5 text-2xs font-medium tracking-wide uppercase',\n local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'\n )}\n >\n <Show when={local.collapsible} fallback={heading}>\n <button\n {...(triggerRest as ComponentProps<'button'>)}\n type=\"button\"\n aria-expanded={open()}\n aria-current={local.active ? 'page' : triggerRest['aria-current']}\n onClick={(event) => {\n invokeEventHandler(trigger.onClick, event)\n if (event.defaultPrevented) return\n setOpen(!open())\n }}\n onKeyDown={(event) => {\n invokeEventHandler(trigger.onKeyDown, event)\n if (event.defaultPrevented || !event.altKey) return\n if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') return\n event.preventDefault()\n event.stopPropagation()\n trigger.onReorder?.(event.key === 'ArrowUp' ? 'up' : 'down')\n }}\n class={cn(\n 'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(pointer:coarse)]:min-h-11',\n local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'\n )}\n >\n {heading}\n </button>\n </Show>\n </Polymorphic>\n <Show when={local.action}>\n <span class=\"shrink-0 opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100\">\n {local.action}\n </span>\n </Show>\n </div>\n <Show when={!local.collapsible || open()}>\n <div class=\"flex flex-col gap-0.5\">{local.children}</div>\n </Show>\n </div>\n )\n}\n\nexport type SidebarNavRowProps = ComponentProps<'div'> & {\n /** Adjacent controls, outside the navigation item's interactive element. */\n actions?: JSX.Element\n}\n\n/**\n * A navigation item and its adjacent controls. Actions stay outside the item\n * to avoid nested buttons; touch, keyboard focus, and expanded menus expose\n * them without requiring a pointer hover. A narrow lane or enlarged text\n * may move actions onto a second line rather than clipping the label or controls.\n */\nexport function SidebarNavRow(props: SidebarNavRowProps) {\n const [local, rest] = splitProps(props, ['class', 'children', 'actions'])\n return (\n <div\n data-slot=\"sidebar-nav-row\"\n class={cn(\n 'group/sidebar-nav-row flex min-w-0 flex-wrap items-center gap-0.5 [&>[data-slot=sidebar-nav-item]]:flex-1 [&>[data-slot=sidebar-nav-item]]:basis-36',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <Show when={local.actions}>\n <span\n data-slot=\"sidebar-nav-row-actions\"\n class=\"ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(hover:none)]:opacity-100\"\n >\n {local.actions}\n </span>\n </Show>\n </div>\n )\n}\n\n/** Row text may truncate visually; its complete content remains the accessible name. */\nexport function SidebarNavLabel(props: ComponentProps<'span'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <span\n data-slot=\"sidebar-nav-label\"\n class={cn('min-w-0 flex-1 truncate', local.class)}\n {...rest}\n />\n )\n}\n\nexport type SidebarNavItemProps<T extends ValidComponent = 'a'> = PolymorphicProps<\n T,\n {\n class?: string\n active?: boolean\n /** Indent one level, for a child row such as a branch under a project. */\n nested?: boolean\n /** Trailing slot: a count, a status dot, a hover action. */\n trailing?: JSX.Element\n }\n>\n\n/**\n * A sidebar row. Exported classes, so a caller's own element can match it.\n * Coarse pointers get a 44px target without changing Kiro's desktop density.\n */\nexport const sidebarNavItemClass = [\n 'group/nav-item relative flex min-w-0 items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium',\n 'whitespace-nowrap transition-colors ease-out outline-none select-none [@media(pointer:coarse)]:min-h-11',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n '[&_svg]:size-4 [&_svg]:shrink-0',\n].join(' ')\n\nexport const sidebarNavItemStateClass = {\n active: 'bg-primary-subtle text-foreground',\n idle: 'text-muted-foreground hover:bg-surface-hover hover:text-foreground',\n}\n\nexport function SidebarNavItem<T extends ValidComponent = 'a'>(props: SidebarNavItemProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavItemProps, [\n 'class',\n 'active',\n 'nested',\n 'trailing',\n 'children',\n ])\n\n return (\n <Polymorphic\n as=\"a\"\n data-slot=\"sidebar-nav-item\"\n aria-current={local.active ? 'page' : undefined}\n data-active={local.active ? '' : undefined}\n class={cn(\n sidebarNavItemClass,\n local.active ? sidebarNavItemStateClass.active : sidebarNavItemStateClass.idle,\n { 'ps-8': local.nested },\n local.class\n )}\n {...(rest as ComponentProps<'a'>)}\n >\n {local.children}\n <Show when={local.trailing}>\n <span class=\"ms-auto flex shrink-0 items-center gap-1\">{local.trailing}</span>\n </Show>\n </Polymorphic>\n )\n}\n\n/** A row that is a button rather than a destination — \"New project\". */\nexport function SidebarNavButton(props: ComponentProps<'button'>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <button\n type=\"button\"\n class={cn(\n sidebarNavItemClass,\n sidebarNavItemStateClass.idle,\n 'w-full disabled:pointer-events-none disabled:opacity-50',\n local.class\n )}\n {...rest}\n >\n {local.children}\n </button>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sidebar-nav.js","names":["PolymorphicProps","Polymorphic","ChevronRight","ComponentProps","JSX","ValidComponent","Show","createSignal","splitProps","cn","invokeEventHandler","handler","event","Event","Array","isArray","callback","data","SidebarNavProps","T","class","SidebarNav","props","local","rest","_$createComponent","_$mergeProps","as","aria-label","children","SidebarNavHeader","_el$","_tmpl$","_$spread","SidebarNavTitleProps","SidebarNavTitle","SidebarNavContent","_el$2","_tmpl$2","SidebarNavFooter","_el$3","_tmpl$3","SidebarNavSectionTriggerProps","Omit","onReorder","direction","onClick","onKeyDown","SidebarNavSectionProps","label","collapsible","defaultOpen","active","open","onOpenChange","triggerProps","count","action","Element","headingAs","SidebarNavSection","uncontrolledOpen","setUncontrolledOpen","setOpen","next","undefined","trigger","triggerRest","heading","when","_el$4","_tmpl$4","_$insert","_el$5","_tmpl$5","_el$6","_tmpl$9","_el$7","firstChild","_$memo","fallback","_el$8","_tmpl$6","aria-expanded","aria-current","defaultPrevented","altKey","key","preventDefault","stopPropagation","_el$9","_tmpl$7","_el$0","_tmpl$8","_$effect","_p$","_v$","_v$2","e","_$setAttribute","t","_$className","SidebarNavRowProps","actions","SidebarNavRow","_el$1","_tmpl$1","_el$10","_tmpl$0","SidebarNavLabel","_el$11","_tmpl$10","SidebarNavItemProps","nested","trailing","sidebarNavItemClass","join","sidebarNavItemStateClass","idle","SidebarNavItem","data-active","_el$12","_tmpl$11","SidebarNavButton","_el$13","_tmpl$12","_$createComponent","_$mergeProps","_$memo","_$setAttribute","_$className"],"sources":["../../../../src/components/layout/sidebar-nav/sidebar-nav.tsx"],"sourcesContent":["import type { PolymorphicProps } from '@kobalte/core/polymorphic'\nimport { Polymorphic } from '@kobalte/core/polymorphic'\nimport { ChevronRight } from 'lucide-solid'\nimport type { ComponentProps, JSX, ValidComponent } from 'solid-js'\nimport { Show, createSignal, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\nfunction invokeEventHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n ;(handler as (event: Event) => void)(event)\n }\n}\n\n/**\n * SidebarNav.\n *\n * The secondary navigation column: the list of things inside the destination\n * the rail selected — projects, sessions, files, threads. It is a different\n * object from the rail, not a wider version of it, which is why it is a separate\n * component rather than the rail with labels on.\n *\n * Rows share one recipe with the rail's, so a row in a sidebar and a row in a\n * rail read as the same kind of thing at the same density. That recipe is\n * exactly KiroCrew's nav row: `text-sm font-medium`, `gap-2.5`, `px-3 py-2`,\n * `rounded-md`, `transition-colors`.\n *\n * The width comes from `--sidebar-width`. Sections collapse by default only when\n * the caller says so, because a section that starts collapsed and holds the\n * user's own work is a hidden default.\n */\nexport type SidebarNavProps<T extends ValidComponent = 'nav'> = PolymorphicProps<\n T,\n { class?: string; 'aria-label'?: string }\n>\n\nexport function SidebarNav<T extends ValidComponent = 'nav'>(props: SidebarNavProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavProps, ['class', 'aria-label', 'children'])\n\n return (\n <Polymorphic\n as=\"nav\"\n aria-label={local['aria-label'] ?? 'Section'}\n class={cn(\n 'bg-sidebar text-sidebar-foreground flex h-full w-sidebar min-w-0 max-w-full shrink-0 flex-col border-e border-sidebar-border',\n local.class\n )}\n {...(rest as ComponentProps<'nav'>)}\n >\n {local.children}\n </Polymorphic>\n )\n}\n\nexport function SidebarNavHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-header\"\n class={cn('flex h-topbar shrink-0 items-center justify-between gap-2 px-3', local.class)}\n {...rest}\n />\n )\n}\n\nexport type SidebarNavTitleProps<T extends ValidComponent = 'div'> = PolymorphicProps<\n T,\n { class?: string }\n>\n\nexport function SidebarNavTitle<T extends ValidComponent = 'div'>(props: SidebarNavTitleProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavTitleProps, ['class'])\n return (\n <Polymorphic\n as=\"div\"\n data-slot=\"sidebar-nav-title\"\n class={cn('truncate text-sm font-semibold tracking-tight', local.class)}\n {...(rest as ComponentProps<'div'>)}\n />\n )\n}\n\n/** The scrolling middle of the sidebar. */\nexport function SidebarNavContent(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-content\"\n class={cn('flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-2 py-2', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SidebarNavFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-footer\"\n class={cn('flex shrink-0 items-center gap-1 border-t border-sidebar-border p-2', local.class)}\n {...rest}\n />\n )\n}\n\n/** Props forwarded to a collapsible section's disclosure button. */\nexport type SidebarNavSectionTriggerProps = Omit<\n ComponentProps<'button'>,\n 'type' | 'aria-expanded' | 'onClick' | 'onKeyDown' | 'children' | 'class' | 'style'\n> & {\n /** Called for Alt+ArrowUp/Down; the host owns ordering and row identity. */\n onReorder?: (direction: 'up' | 'down') => void\n /** Runs before the section toggle and may cancel it with `preventDefault()`. */\n onClick?: ComponentProps<'button'>['onClick']\n /** Runs before shared Alt+Arrow handling and may cancel it with `preventDefault()`. */\n onKeyDown?: ComponentProps<'button'>['onKeyDown']\n}\n\n/**\n * A titled, collapsible group. Collapsible because a list of projects\n * inevitably outgrows the column, and the user needs to put the ones they are\n * not using away *without* them disappearing into a menu.\n */\nexport type SidebarNavSectionProps = ComponentProps<'div'> & {\n label: string\n /** Render a disclosure control instead of a plain heading. */\n collapsible?: boolean\n defaultOpen?: boolean\n /** Mark the current project/group without changing its disclosure state. */\n active?: boolean\n /** Controlled disclosure state. When supplied, the host owns changes. */\n open?: boolean\n /** Called for user-initiated disclosure changes. */\n onOpenChange?: (open: boolean) => void\n /** Native props and reorder callbacks for the disclosure control. */\n triggerProps?: SidebarNavSectionTriggerProps\n /** Count shown beside the label. */\n count?: number\n /** A control at the trailing edge of the heading row. */\n action?: JSX.Element\n /** Semantic heading element for a host's section hierarchy. */\n headingAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n}\n\nexport function SidebarNavSection(props: SidebarNavSectionProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'collapsible',\n 'defaultOpen',\n 'active',\n 'open',\n 'onOpenChange',\n 'triggerProps',\n 'count',\n 'action',\n 'headingAs',\n 'children',\n ])\n const [uncontrolledOpen, setUncontrolledOpen] = createSignal(local.defaultOpen ?? true)\n const open = () => local.open ?? uncontrolledOpen()\n const setOpen = (next: boolean) => {\n if (local.open === undefined) setUncontrolledOpen(next)\n local.onOpenChange?.(next)\n }\n\n const [trigger, triggerRest] = splitProps(local.triggerProps ?? {}, [\n 'onClick',\n 'onKeyDown',\n 'onReorder',\n ])\n\n const heading = (\n <>\n <Show when={local.collapsible}>\n <ChevronRight\n aria-hidden=\"true\"\n class={cn('size-3.5 shrink-0 text-muted-foreground transition-transform ease-out', {\n 'rotate-90': open(),\n })}\n />\n </Show>\n <span class=\"min-w-0 flex-1 truncate\">{local.label}</span>\n <Show when={local.count !== undefined}>\n <span class=\"shrink-0 tabular-nums text-muted-foreground\">{local.count}</span>\n </Show>\n </>\n )\n\n return (\n <div data-slot=\"sidebar-nav-section\" class={cn('flex flex-col gap-0.5', local.class)} {...rest}>\n <div\n data-slot=\"sidebar-nav-section-header\"\n data-active={local.active ? '' : undefined}\n class={cn(\n 'group/section-header flex items-center gap-1 rounded-md px-2 py-1.5',\n { '[@media(any-pointer:coarse)]:py-0': local.collapsible },\n local.active ? 'bg-primary-subtle text-foreground' : 'hover:bg-sidebar-accent/60'\n )}\n >\n <Polymorphic\n as={local.headingAs ?? 'div'}\n aria-label={local.headingAs ? local.label : undefined}\n class={cn(\n 'flex min-w-0 flex-1 items-center gap-1.5 text-2xs font-medium tracking-wide uppercase',\n local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'\n )}\n >\n <Show when={local.collapsible} fallback={heading}>\n <button\n {...(triggerRest as ComponentProps<'button'>)}\n type=\"button\"\n aria-expanded={open()}\n aria-current={local.active ? 'page' : triggerRest['aria-current']}\n onClick={(event) => {\n invokeEventHandler(trigger.onClick, event)\n if (event.defaultPrevented) return\n setOpen(!open())\n }}\n onKeyDown={(event) => {\n invokeEventHandler(trigger.onKeyDown, event)\n if (event.defaultPrevented || !event.altKey) return\n if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') return\n event.preventDefault()\n event.stopPropagation()\n trigger.onReorder?.(event.key === 'ArrowUp' ? 'up' : 'down')\n }}\n class={cn(\n 'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11',\n local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'\n )}\n >\n {heading}\n </button>\n </Show>\n </Polymorphic>\n <Show when={local.action}>\n <span class=\"shrink-0 opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(any-pointer:coarse)]:opacity-100\">\n {local.action}\n </span>\n </Show>\n </div>\n <Show when={!local.collapsible || open()}>\n <div class=\"flex flex-col gap-0.5\">{local.children}</div>\n </Show>\n </div>\n )\n}\n\nexport type SidebarNavRowProps = ComponentProps<'div'> & {\n /** Adjacent controls, outside the navigation item's interactive element. */\n actions?: JSX.Element\n}\n\n/**\n * A navigation item and its adjacent controls. Actions stay outside the item\n * to avoid nested buttons; touch, keyboard focus, and expanded menus expose\n * them without requiring a pointer hover. A narrow lane or enlarged text\n * may move actions onto a second line rather than clipping the label or controls.\n */\nexport function SidebarNavRow(props: SidebarNavRowProps) {\n const [local, rest] = splitProps(props, ['class', 'children', 'actions'])\n return (\n <div\n data-slot=\"sidebar-nav-row\"\n class={cn(\n 'group/sidebar-nav-row flex min-w-0 flex-wrap items-center gap-0.5 [&>[data-slot=sidebar-nav-item]]:flex-1 [&>[data-slot=sidebar-nav-item]]:basis-36',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <Show when={local.actions}>\n <span\n data-slot=\"sidebar-nav-row-actions\"\n class=\"ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(any-pointer:coarse)]:opacity-100\"\n >\n {local.actions}\n </span>\n </Show>\n </div>\n )\n}\n\n/** Row text may truncate visually; its complete content remains the accessible name. */\nexport function SidebarNavLabel(props: ComponentProps<'span'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <span\n data-slot=\"sidebar-nav-label\"\n class={cn('min-w-0 flex-1 truncate', local.class)}\n {...rest}\n />\n )\n}\n\nexport type SidebarNavItemProps<T extends ValidComponent = 'a'> = PolymorphicProps<\n T,\n {\n class?: string\n active?: boolean\n /** Indent one level, for a child row such as a branch under a project. */\n nested?: boolean\n /** Trailing slot: a count, a status dot, a hover action. */\n trailing?: JSX.Element\n }\n>\n\n/**\n * A sidebar row. Exported classes, so a caller's own element can match it.\n * Any coarse pointer gets a 44px target without changing desktop density.\n */\nexport const sidebarNavItemClass = [\n 'group/nav-item relative flex min-w-0 items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium',\n 'whitespace-nowrap transition-colors ease-out outline-none select-none [@media(any-pointer:coarse)]:min-h-11',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n '[&_svg]:size-4 [&_svg]:shrink-0',\n].join(' ')\n\nexport const sidebarNavItemStateClass = {\n active: 'bg-primary-subtle text-foreground',\n idle: 'text-muted-foreground hover:bg-surface-hover hover:text-foreground',\n}\n\nexport function SidebarNavItem<T extends ValidComponent = 'a'>(props: SidebarNavItemProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavItemProps, [\n 'class',\n 'active',\n 'nested',\n 'trailing',\n 'children',\n ])\n\n return (\n <Polymorphic\n as=\"a\"\n data-slot=\"sidebar-nav-item\"\n aria-current={local.active ? 'page' : undefined}\n data-active={local.active ? '' : undefined}\n class={cn(\n sidebarNavItemClass,\n local.active ? sidebarNavItemStateClass.active : sidebarNavItemStateClass.idle,\n { 'ps-8': local.nested },\n local.class\n )}\n {...(rest as ComponentProps<'a'>)}\n >\n {local.children}\n <Show when={local.trailing}>\n <span class=\"ms-auto flex shrink-0 items-center gap-1\">{local.trailing}</span>\n </Show>\n </Polymorphic>\n )\n}\n\n/** A row that is a button rather than a destination — \"New project\". */\nexport function SidebarNavButton(props: ComponentProps<'button'>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <button\n type=\"button\"\n class={cn(\n sidebarNavItemClass,\n sidebarNavItemStateClass.idle,\n 'w-full disabled:pointer-events-none disabled:opacity-50',\n local.class\n )}\n {...rest}\n >\n {local.children}\n </button>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dialog/dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,IAAI,aAAa,EACvB,OAAO,IAAI,oBAAoB,EAC/B,OAAO,IAAI,oBAAoB,EAChC,MAAM,sBAAsB,CAAA;AAG7B,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAwC7D,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IACvB,eAAe,CAAC,EAAE,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;IACnD,eAAe,CAAC,EAAE,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC,iBAAiB,CAAC,CAAA;IAChF,gBAAgB,CAAC,EAAE,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC,kBAAkB,CAAC,CAAA;CACnF,CAAA;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,EAC3C,IAAI,EACJ,eAAe,EACf,eAAe,EAAE,qBAAqB,EACtC,gBAAgB,EAAE,sBAAsB,GACzC,EAAE,6BAA6B;6BA6DE,KAAK;
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dialog/dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,IAAI,aAAa,EACvB,OAAO,IAAI,oBAAoB,EAC/B,OAAO,IAAI,oBAAoB,EAChC,MAAM,sBAAsB,CAAA;AAG7B,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAwC7D,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IACvB,eAAe,CAAC,EAAE,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;IACnD,eAAe,CAAC,EAAE,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC,iBAAiB,CAAC,CAAA;IAChF,gBAAgB,CAAC,EAAE,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC,kBAAkB,CAAC,CAAA;CACnF,CAAA;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,EAC3C,IAAI,EACJ,eAAe,EACf,eAAe,EAAE,qBAAqB,EACtC,gBAAgB,EAAE,sBAAsB,GACzC,EAAE,6BAA6B;6BA6DE,KAAK;8BA8CJ,KAAK;EA8CvC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,eAEjE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,eAEhF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,MAAM,CAAC,eAE9E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,oBAAoB,CAAC,eAY/E;AAED,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,oBAAoB,CAAC,GAAG;IAC7E;;;;OAIG;IACH,WAAW,CAAC,EAAE,GAAG,CAAC,OAAO,GAAG,KAAK,CAAA;IACjC,qFAAqF;IACrF,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;CACjC,CAAA;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,eAiCtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,eASxD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,eASxD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,KAAK,CAAC,eAQ5E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,WAAW,CAAC,eAKxF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,WAAW,CAAC,eAGxF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,WAAW,CAAC,eAGlF"}
|
|
@@ -75,7 +75,11 @@ function createDialogFocusRestoration({ open, restoreFocusRef, onOpenAutoFocus:
|
|
|
75
75
|
closeAutoFocusScheduled: false,
|
|
76
76
|
onFocusIn: (focusEvent) => {
|
|
77
77
|
const target = focusEvent.target;
|
|
78
|
-
if (!(target instanceof HTMLElement) || target === document.body || target === document.documentElement
|
|
78
|
+
if (!(target instanceof HTMLElement) || target === document.body || target === document.documentElement) return;
|
|
79
|
+
if (target === element || element.contains(target) || target === (opener instanceof HTMLElement ? opener : null)) {
|
|
80
|
+
if (!cycle.closed) cycle.focusMovedOutside = false;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
79
83
|
cycle.focusMovedOutside = true;
|
|
80
84
|
}
|
|
81
85
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","names":["Dialog","KobalteDialog","Content","KobalteDialogContent","Overlay","KobalteDialogOverlay","X","Accessor","ComponentProps","JSX","createRenderEffect","onCleanup","Show","splitProps","overlayMotion","overlayPositioner","overlayScrim","overlaySurface","cn","FocusCycle","content","HTMLElement","opener","openerEligible","closed","focusMovedOutside","closeAutoFocusScheduled","frame","fallbackTimer","observer","MutationObserver","onFocusIn","event","FocusEvent","canRestoreFocus","target","isConnected","document","body","documentElement","closest","matches","getClientRects","length","hasOtherOverlay","querySelectorAll","some","overlay","contains","DialogFocusRestorationOptions","open","restoreFocusRef","onOpenAutoFocus","onCloseAutoFocus","createDialogFocusRestoration","callerOnOpenAutoFocus","callerOnCloseAutoFocus","focusCycles","WeakMap","activeFocusCycle","pendingOpener","pendingOpenerEligible","active","activeElement","finishFocusCycle","cycle","undefined","window","cancelAnimationFrame","clearTimeout","disconnect","removeEventListener","scheduleFocusRestore","requestAnimationFrame","focusIsAvailable","Node","focus","preventScroll","Event","element","currentTarget","openerWasCaptured","focusEvent","set","addEventListener","get","defaultPrevented","observe","attributes","attributeFilter","childList","subtree","queueMicrotask","setTimeout","props","_$createComponent","DialogTrigger","Trigger","DialogPortal","Portal","DialogOverlay","local","rest","_$mergeProps","class","DialogContentProps","closeButton","Element","positioner","DialogContent","children","_el$","_tmpl$","_$insert","_$memo","when","CloseButton","_$effect","_$className","DialogHeader","_el$2","_tmpl$2","_$spread","DialogFooter","_el$3","_tmpl$3","DialogTitle","Title","DialogDescription","Description","DialogCloseButton","DialogClose","Dialog","_$createComponent","KobalteDialog","KobalteDialogOverlay","_$mergeProps","KobalteDialogContent","_$memo","_$className"],"sources":["../../../../src/components/ui/dialog/dialog.tsx"],"sourcesContent":["import {\n Dialog as KobalteDialog,\n Content as KobalteDialogContent,\n Overlay as KobalteDialogOverlay,\n} from '@kobalte/core/dialog'\n// AlertDialog assigns to the shared DialogRoot.Content object, so these named exports stay role-stable.\nimport { X } from 'lucide-solid'\nimport type { Accessor, ComponentProps, JSX } from 'solid-js'\nimport { createRenderEffect, onCleanup, Show, splitProps } from 'solid-js'\nimport { overlayMotion, overlayPositioner, overlayScrim, overlaySurface } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\ntype FocusCycle = {\n content: HTMLElement\n opener: HTMLElement | null\n openerEligible: boolean\n closed: boolean\n focusMovedOutside: boolean\n closeAutoFocusScheduled: boolean\n frame?: number\n fallbackTimer?: number\n observer?: MutationObserver\n onFocusIn: (event: FocusEvent) => void\n}\n\nfunction canRestoreFocus(target: HTMLElement): boolean {\n return (\n target.isConnected &&\n target !== document.body &&\n target !== document.documentElement &&\n !target.closest('[inert], [aria-hidden=\"true\"]') &&\n !target.matches(':disabled') &&\n target.getClientRects().length > 0\n )\n}\n\nfunction hasOtherOverlay(content: HTMLElement, opener: HTMLElement): boolean {\n return [...document.querySelectorAll<HTMLElement>('[role=\"dialog\"], [role=\"alertdialog\"]')].some(\n (overlay) =>\n overlay !== content &&\n !content.contains(overlay) &&\n !overlay.contains(opener) &&\n !overlay.closest('[aria-hidden=\"true\"], [inert]') &&\n overlay.getClientRects().length > 0\n )\n}\n\ntype DialogFocusRestorationOptions = {\n open: Accessor<boolean>\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n onOpenAutoFocus?: ComponentProps<typeof KobalteDialogContent>['onOpenAutoFocus']\n onCloseAutoFocus?: ComponentProps<typeof KobalteDialogContent>['onCloseAutoFocus']\n}\n\n/**\n * Adds guarded opener capture and restoration to a Kobalte dialog content.\n * Composed surfaces use this internal helper; it is omitted from the public\n * dialog barrel so the restoration policy stays with the dialog components.\n */\nexport function createDialogFocusRestoration({\n open,\n restoreFocusRef,\n onOpenAutoFocus: callerOnOpenAutoFocus,\n onCloseAutoFocus: callerOnCloseAutoFocus,\n}: DialogFocusRestorationOptions) {\n const focusCycles = new WeakMap<HTMLElement, FocusCycle>()\n let activeFocusCycle: FocusCycle | undefined\n let pendingOpener: HTMLElement | null = null\n let pendingOpenerEligible = false\n\n createRenderEffect(() => {\n if (!open() || typeof document === 'undefined') {\n pendingOpener = null\n pendingOpenerEligible = false\n return\n }\n const active = restoreFocusRef?.() ?? document.activeElement\n pendingOpener = active instanceof HTMLElement ? active : null\n pendingOpenerEligible = active instanceof HTMLElement && canRestoreFocus(active)\n })\n\n const finishFocusCycle = (cycle: FocusCycle) => {\n if (cycle.frame !== undefined) window.cancelAnimationFrame(cycle.frame)\n if (cycle.fallbackTimer !== undefined) window.clearTimeout(cycle.fallbackTimer)\n cycle.observer?.disconnect()\n document.removeEventListener('focusin', cycle.onFocusIn)\n if (activeFocusCycle === cycle) activeFocusCycle = undefined\n }\n\n const scheduleFocusRestore = (cycle: FocusCycle) => {\n if (cycle.frame !== undefined) return\n cycle.frame = window.requestAnimationFrame(() => {\n cycle.frame = undefined\n const opener = cycle.opener\n const active = document.activeElement\n const focusIsAvailable =\n active === document.body ||\n active === document.documentElement ||\n active === cycle.content ||\n (active instanceof Node && cycle.content.contains(active))\n if (\n activeFocusCycle !== cycle ||\n !cycle.closed ||\n cycle.focusMovedOutside ||\n !opener ||\n !opener.isConnected ||\n opener.matches(':disabled') ||\n opener.getClientRects().length === 0 ||\n !focusIsAvailable ||\n hasOtherOverlay(cycle.content, opener)\n ) {\n finishFocusCycle(cycle)\n return\n }\n\n // Inert and aria-hidden are removed by the dialog's containment cleanup.\n // Wait for that cleanup before returning focus to the original control.\n if (opener.closest('[inert], [aria-hidden=\"true\"]')) return\n if (cycle.openerEligible && canRestoreFocus(opener)) {\n opener.focus({ preventScroll: true })\n }\n finishFocusCycle(cycle)\n })\n }\n\n const onOpenAutoFocus = (event: Event) => {\n const element = event.currentTarget\n if (element instanceof HTMLElement) {\n if (activeFocusCycle) finishFocusCycle(activeFocusCycle)\n\n const openerWasCaptured = pendingOpener !== null\n const opener = pendingOpener ?? document.activeElement\n const openerEligible = openerWasCaptured\n ? pendingOpenerEligible\n : opener instanceof HTMLElement && canRestoreFocus(opener)\n pendingOpener = null\n pendingOpenerEligible = false\n const cycle: FocusCycle = {\n content: element,\n opener: opener instanceof HTMLElement ? opener : null,\n openerEligible,\n closed: false,\n focusMovedOutside: false,\n closeAutoFocusScheduled: false,\n onFocusIn: (focusEvent) => {\n const target = focusEvent.target\n if (\n !(target instanceof HTMLElement) ||\n target === document.body ||\n target === document.documentElement ||\n target === element ||\n element.contains(target) ||\n target === (opener instanceof HTMLElement ? opener : null)\n ) {\n return\n }\n cycle.focusMovedOutside = true\n },\n }\n focusCycles.set(element, cycle)\n activeFocusCycle = cycle\n document.addEventListener('focusin', cycle.onFocusIn)\n }\n callerOnOpenAutoFocus?.(event)\n }\n\n const onCloseAutoFocus = (event: Event) => {\n const element = event.currentTarget\n const cycle = element instanceof HTMLElement ? focusCycles.get(element) : undefined\n callerOnCloseAutoFocus?.(event)\n\n if (!cycle) return\n cycle.closed = true\n\n // A caller that prevents Kobalte's close autofocus owns the focus decision.\n if (event.defaultPrevented) {\n finishFocusCycle(cycle)\n return\n }\n\n if (cycle.fallbackTimer !== undefined) {\n window.clearTimeout(cycle.fallbackTimer)\n cycle.fallbackTimer = undefined\n }\n cycle.closeAutoFocusScheduled = true\n cycle.observer = new MutationObserver(() => scheduleFocusRestore(cycle))\n cycle.observer.observe(document.body, {\n attributes: true,\n attributeFilter: ['aria-hidden', 'inert'],\n childList: true,\n subtree: true,\n })\n scheduleFocusRestore(cycle)\n }\n\n onCleanup(() => {\n const cycle = activeFocusCycle\n if (!cycle) return\n cycle.closed = true\n\n // Kobalte dispatches unmount autofocus from a timer. This fallback only\n // releases the scoped focus listener if the content did not dispatch it.\n queueMicrotask(() => {\n if (cycle.closeAutoFocusScheduled) return\n cycle.fallbackTimer = window.setTimeout(() => {\n cycle.fallbackTimer = undefined\n if (!cycle.closeAutoFocusScheduled) finishFocusCycle(cycle)\n }, 0)\n })\n })\n\n return { onOpenAutoFocus, onCloseAutoFocus }\n}\n\n/**\n * Dialog.\n *\n * A modal surface for a decision or a short task. `Dialog.Portal` keeps the\n * panel out of the app's stacking and overflow contexts, `Dialog.Overlay`\n * dims what is behind it, and Kobalte handles the focus trap, the escape key,\n * scroll locking and returning focus to the trigger on close.\n *\n * The close button is part of the content rather than optional, because every\n * modal needs a way out that is not the keyboard. A dialog whose only exit is\n * Escape is a trap for anyone using a pointer.\n */\nexport function Dialog(props: ComponentProps<typeof KobalteDialog>) {\n return <KobalteDialog {...props} />\n}\n\nexport function DialogTrigger(props: ComponentProps<typeof KobalteDialog.Trigger>) {\n return <KobalteDialog.Trigger {...props} />\n}\n\nexport function DialogPortal(props: ComponentProps<typeof KobalteDialog.Portal>) {\n return <KobalteDialog.Portal {...props} />\n}\n\nexport function DialogOverlay(props: ComponentProps<typeof KobalteDialogOverlay>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialogOverlay\n class={cn(\n overlayScrim,\n 'data-expanded:animate-in data-expanded:fade-in-0 data-closed:animate-out data-closed:fade-out-0',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type DialogContentProps = ComponentProps<typeof KobalteDialogContent> & {\n /**\n * Replaces the default close button. Pass `false` to remove it — only for a\n * dialog that cannot be dismissed (an update that must finish); anything the\n * user can escape from needs the button.\n */\n closeButton?: JSX.Element | false\n /** Use a 1rem inset as the positioner bounds for tall, viewport-filling surfaces. */\n positioner?: 'default' | 'inset'\n}\n\nexport function DialogContent(props: DialogContentProps) {\n const [local, rest] = splitProps(props, ['class', 'children', 'closeButton', 'positioner'])\n\n return (\n <KobalteDialog.Portal>\n <DialogOverlay />\n <div class={cn(overlayPositioner, local.positioner === 'inset' && 'inset-4 grid-rows-1 p-0')}>\n <KobalteDialogContent\n class={cn(\n overlaySurface,\n overlayMotion,\n 'relative grid w-full max-w-lg gap-4 p-5',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <Show when={local.closeButton !== false}>\n <KobalteDialog.CloseButton\n aria-label=\"Close\"\n class={cn(\n 'absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground',\n 'transition-colors ease-out hover:bg-surface-hover hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle outline-none'\n )}\n >\n {local.closeButton ?? <X class=\"size-4\" />}\n </KobalteDialog.CloseButton>\n </Show>\n </KobalteDialogContent>\n </div>\n </KobalteDialog.Portal>\n )\n}\n\nexport function DialogHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"dialog-header\"\n class={cn('flex flex-col gap-1.5 pe-6 text-start', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"dialog-footer\"\n class={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogTitle(props: ComponentProps<typeof KobalteDialog.Title>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Title\n class={cn('text-base leading-none font-semibold tracking-tight', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogDescription(props: ComponentProps<typeof KobalteDialog.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Description class={cn('text-muted-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport function DialogCloseButton(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn('focus-ring', local.class)} {...rest} />\n}\n\n/**\n * The close control, unstyled and polymorphic — for a footer's text \"Cancel\" or\n * \"Close\", which is a different control from the corner icon `DialogCloseButton`\n * draws. Take it as `as={Button}` so it carries the button's variants rather than\n * a copied class string.\n */\nexport function DialogClose(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn('focus-ring', local.class)} {...rest} />\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dialog.js","names":["Dialog","KobalteDialog","Content","KobalteDialogContent","Overlay","KobalteDialogOverlay","X","Accessor","ComponentProps","JSX","createRenderEffect","onCleanup","Show","splitProps","overlayMotion","overlayPositioner","overlayScrim","overlaySurface","cn","FocusCycle","content","HTMLElement","opener","openerEligible","closed","focusMovedOutside","closeAutoFocusScheduled","frame","fallbackTimer","observer","MutationObserver","onFocusIn","event","FocusEvent","canRestoreFocus","target","isConnected","document","body","documentElement","closest","matches","getClientRects","length","hasOtherOverlay","querySelectorAll","some","overlay","contains","DialogFocusRestorationOptions","open","restoreFocusRef","onOpenAutoFocus","onCloseAutoFocus","createDialogFocusRestoration","callerOnOpenAutoFocus","callerOnCloseAutoFocus","focusCycles","WeakMap","activeFocusCycle","pendingOpener","pendingOpenerEligible","active","activeElement","finishFocusCycle","cycle","undefined","window","cancelAnimationFrame","clearTimeout","disconnect","removeEventListener","scheduleFocusRestore","requestAnimationFrame","focusIsAvailable","Node","focus","preventScroll","Event","element","currentTarget","openerWasCaptured","focusEvent","set","addEventListener","get","defaultPrevented","observe","attributes","attributeFilter","childList","subtree","queueMicrotask","setTimeout","props","_$createComponent","DialogTrigger","Trigger","DialogPortal","Portal","DialogOverlay","local","rest","_$mergeProps","class","DialogContentProps","closeButton","Element","positioner","DialogContent","children","_el$","_tmpl$","_$insert","_$memo","when","CloseButton","_$effect","_$className","DialogHeader","_el$2","_tmpl$2","_$spread","DialogFooter","_el$3","_tmpl$3","DialogTitle","Title","DialogDescription","Description","DialogCloseButton","DialogClose","Dialog","_$createComponent","KobalteDialog","KobalteDialogOverlay","_$mergeProps","KobalteDialogContent","_$memo","_$className"],"sources":["../../../../src/components/ui/dialog/dialog.tsx"],"sourcesContent":["import {\n Dialog as KobalteDialog,\n Content as KobalteDialogContent,\n Overlay as KobalteDialogOverlay,\n} from '@kobalte/core/dialog'\n// AlertDialog assigns to the shared DialogRoot.Content object, so these named exports stay role-stable.\nimport { X } from 'lucide-solid'\nimport type { Accessor, ComponentProps, JSX } from 'solid-js'\nimport { createRenderEffect, onCleanup, Show, splitProps } from 'solid-js'\nimport { overlayMotion, overlayPositioner, overlayScrim, overlaySurface } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\ntype FocusCycle = {\n content: HTMLElement\n opener: HTMLElement | null\n openerEligible: boolean\n closed: boolean\n focusMovedOutside: boolean\n closeAutoFocusScheduled: boolean\n frame?: number\n fallbackTimer?: number\n observer?: MutationObserver\n onFocusIn: (event: FocusEvent) => void\n}\n\nfunction canRestoreFocus(target: HTMLElement): boolean {\n return (\n target.isConnected &&\n target !== document.body &&\n target !== document.documentElement &&\n !target.closest('[inert], [aria-hidden=\"true\"]') &&\n !target.matches(':disabled') &&\n target.getClientRects().length > 0\n )\n}\n\nfunction hasOtherOverlay(content: HTMLElement, opener: HTMLElement): boolean {\n return [...document.querySelectorAll<HTMLElement>('[role=\"dialog\"], [role=\"alertdialog\"]')].some(\n (overlay) =>\n overlay !== content &&\n !content.contains(overlay) &&\n !overlay.contains(opener) &&\n !overlay.closest('[aria-hidden=\"true\"], [inert]') &&\n overlay.getClientRects().length > 0\n )\n}\n\ntype DialogFocusRestorationOptions = {\n open: Accessor<boolean>\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n onOpenAutoFocus?: ComponentProps<typeof KobalteDialogContent>['onOpenAutoFocus']\n onCloseAutoFocus?: ComponentProps<typeof KobalteDialogContent>['onCloseAutoFocus']\n}\n\n/**\n * Adds guarded opener capture and restoration to a Kobalte dialog content.\n * Composed surfaces use this internal helper; it is omitted from the public\n * dialog barrel so the restoration policy stays with the dialog components.\n */\nexport function createDialogFocusRestoration({\n open,\n restoreFocusRef,\n onOpenAutoFocus: callerOnOpenAutoFocus,\n onCloseAutoFocus: callerOnCloseAutoFocus,\n}: DialogFocusRestorationOptions) {\n const focusCycles = new WeakMap<HTMLElement, FocusCycle>()\n let activeFocusCycle: FocusCycle | undefined\n let pendingOpener: HTMLElement | null = null\n let pendingOpenerEligible = false\n\n createRenderEffect(() => {\n if (!open() || typeof document === 'undefined') {\n pendingOpener = null\n pendingOpenerEligible = false\n return\n }\n const active = restoreFocusRef?.() ?? document.activeElement\n pendingOpener = active instanceof HTMLElement ? active : null\n pendingOpenerEligible = active instanceof HTMLElement && canRestoreFocus(active)\n })\n\n const finishFocusCycle = (cycle: FocusCycle) => {\n if (cycle.frame !== undefined) window.cancelAnimationFrame(cycle.frame)\n if (cycle.fallbackTimer !== undefined) window.clearTimeout(cycle.fallbackTimer)\n cycle.observer?.disconnect()\n document.removeEventListener('focusin', cycle.onFocusIn)\n if (activeFocusCycle === cycle) activeFocusCycle = undefined\n }\n\n const scheduleFocusRestore = (cycle: FocusCycle) => {\n if (cycle.frame !== undefined) return\n cycle.frame = window.requestAnimationFrame(() => {\n cycle.frame = undefined\n const opener = cycle.opener\n const active = document.activeElement\n const focusIsAvailable =\n active === document.body ||\n active === document.documentElement ||\n active === cycle.content ||\n (active instanceof Node && cycle.content.contains(active))\n if (\n activeFocusCycle !== cycle ||\n !cycle.closed ||\n cycle.focusMovedOutside ||\n !opener ||\n !opener.isConnected ||\n opener.matches(':disabled') ||\n opener.getClientRects().length === 0 ||\n !focusIsAvailable ||\n hasOtherOverlay(cycle.content, opener)\n ) {\n finishFocusCycle(cycle)\n return\n }\n\n // Inert and aria-hidden are removed by the dialog's containment cleanup.\n // Wait for that cleanup before returning focus to the original control.\n if (opener.closest('[inert], [aria-hidden=\"true\"]')) return\n if (cycle.openerEligible && canRestoreFocus(opener)) {\n opener.focus({ preventScroll: true })\n }\n finishFocusCycle(cycle)\n })\n }\n\n const onOpenAutoFocus = (event: Event) => {\n const element = event.currentTarget\n if (element instanceof HTMLElement) {\n if (activeFocusCycle) finishFocusCycle(activeFocusCycle)\n\n const openerWasCaptured = pendingOpener !== null\n const opener = pendingOpener ?? document.activeElement\n const openerEligible = openerWasCaptured\n ? pendingOpenerEligible\n : opener instanceof HTMLElement && canRestoreFocus(opener)\n pendingOpener = null\n pendingOpenerEligible = false\n const cycle: FocusCycle = {\n content: element,\n opener: opener instanceof HTMLElement ? opener : null,\n openerEligible,\n closed: false,\n focusMovedOutside: false,\n closeAutoFocusScheduled: false,\n onFocusIn: (focusEvent) => {\n const target = focusEvent.target\n if (\n !(target instanceof HTMLElement) ||\n target === document.body ||\n target === document.documentElement\n ) {\n return\n }\n if (\n target === element ||\n element.contains(target) ||\n target === (opener instanceof HTMLElement ? opener : null)\n ) {\n if (!cycle.closed) cycle.focusMovedOutside = false\n return\n }\n cycle.focusMovedOutside = true\n },\n }\n focusCycles.set(element, cycle)\n activeFocusCycle = cycle\n document.addEventListener('focusin', cycle.onFocusIn)\n }\n callerOnOpenAutoFocus?.(event)\n }\n\n const onCloseAutoFocus = (event: Event) => {\n const element = event.currentTarget\n const cycle = element instanceof HTMLElement ? focusCycles.get(element) : undefined\n callerOnCloseAutoFocus?.(event)\n\n if (!cycle) return\n cycle.closed = true\n\n // A caller that prevents Kobalte's close autofocus owns the focus decision.\n if (event.defaultPrevented) {\n finishFocusCycle(cycle)\n return\n }\n\n if (cycle.fallbackTimer !== undefined) {\n window.clearTimeout(cycle.fallbackTimer)\n cycle.fallbackTimer = undefined\n }\n cycle.closeAutoFocusScheduled = true\n cycle.observer = new MutationObserver(() => scheduleFocusRestore(cycle))\n cycle.observer.observe(document.body, {\n attributes: true,\n attributeFilter: ['aria-hidden', 'inert'],\n childList: true,\n subtree: true,\n })\n scheduleFocusRestore(cycle)\n }\n\n onCleanup(() => {\n const cycle = activeFocusCycle\n if (!cycle) return\n cycle.closed = true\n\n // Kobalte dispatches unmount autofocus from a timer. This fallback only\n // releases the scoped focus listener if the content did not dispatch it.\n queueMicrotask(() => {\n if (cycle.closeAutoFocusScheduled) return\n cycle.fallbackTimer = window.setTimeout(() => {\n cycle.fallbackTimer = undefined\n if (!cycle.closeAutoFocusScheduled) finishFocusCycle(cycle)\n }, 0)\n })\n })\n\n return { onOpenAutoFocus, onCloseAutoFocus }\n}\n\n/**\n * Dialog.\n *\n * A modal surface for a decision or a short task. `Dialog.Portal` keeps the\n * panel out of the app's stacking and overflow contexts, `Dialog.Overlay`\n * dims what is behind it, and Kobalte handles the focus trap, the escape key,\n * scroll locking and returning focus to the trigger on close.\n *\n * The close button is part of the content rather than optional, because every\n * modal needs a way out that is not the keyboard. A dialog whose only exit is\n * Escape is a trap for anyone using a pointer.\n */\nexport function Dialog(props: ComponentProps<typeof KobalteDialog>) {\n return <KobalteDialog {...props} />\n}\n\nexport function DialogTrigger(props: ComponentProps<typeof KobalteDialog.Trigger>) {\n return <KobalteDialog.Trigger {...props} />\n}\n\nexport function DialogPortal(props: ComponentProps<typeof KobalteDialog.Portal>) {\n return <KobalteDialog.Portal {...props} />\n}\n\nexport function DialogOverlay(props: ComponentProps<typeof KobalteDialogOverlay>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialogOverlay\n class={cn(\n overlayScrim,\n 'data-expanded:animate-in data-expanded:fade-in-0 data-closed:animate-out data-closed:fade-out-0',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type DialogContentProps = ComponentProps<typeof KobalteDialogContent> & {\n /**\n * Replaces the default close button. Pass `false` to remove it — only for a\n * dialog that cannot be dismissed (an update that must finish); anything the\n * user can escape from needs the button.\n */\n closeButton?: JSX.Element | false\n /** Use a 1rem inset as the positioner bounds for tall, viewport-filling surfaces. */\n positioner?: 'default' | 'inset'\n}\n\nexport function DialogContent(props: DialogContentProps) {\n const [local, rest] = splitProps(props, ['class', 'children', 'closeButton', 'positioner'])\n\n return (\n <KobalteDialog.Portal>\n <DialogOverlay />\n <div class={cn(overlayPositioner, local.positioner === 'inset' && 'inset-4 grid-rows-1 p-0')}>\n <KobalteDialogContent\n class={cn(\n overlaySurface,\n overlayMotion,\n 'relative grid w-full max-w-lg gap-4 p-5',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <Show when={local.closeButton !== false}>\n <KobalteDialog.CloseButton\n aria-label=\"Close\"\n class={cn(\n 'absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground',\n 'transition-colors ease-out hover:bg-surface-hover hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle outline-none'\n )}\n >\n {local.closeButton ?? <X class=\"size-4\" />}\n </KobalteDialog.CloseButton>\n </Show>\n </KobalteDialogContent>\n </div>\n </KobalteDialog.Portal>\n )\n}\n\nexport function DialogHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"dialog-header\"\n class={cn('flex flex-col gap-1.5 pe-6 text-start', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"dialog-footer\"\n class={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogTitle(props: ComponentProps<typeof KobalteDialog.Title>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Title\n class={cn('text-base leading-none font-semibold tracking-tight', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DialogDescription(props: ComponentProps<typeof KobalteDialog.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Description class={cn('text-muted-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport function DialogCloseButton(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn('focus-ring', local.class)} {...rest} />\n}\n\n/**\n * The close control, unstyled and polymorphic — for a footer's text \"Cancel\" or\n * \"Close\", which is a different control from the corner icon `DialogCloseButton`\n * draws. Take it as `as={Button}` so it carries the button's variants rather than\n * a copied class string.\n */\nexport function DialogClose(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn('focus-ring', local.class)} {...rest} />\n}\n"],"mappings":"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"}
|
|
@@ -23,6 +23,12 @@ import { DialogContent } from '../dialog/dialog';
|
|
|
23
23
|
* handler takes control or focus has moved to another layer. For controlled
|
|
24
24
|
* dialogs without a composed trigger, pass `restoreFocusRef` when the opener
|
|
25
25
|
* cannot be inferred from the focused element.
|
|
26
|
+
* 5. **It keeps its own portal out of an enclosing layer's `aria-hidden`
|
|
27
|
+
* bookkeeping.** A non-modal dialog opened while a modal `Sheet` is alive would
|
|
28
|
+
* otherwise be aria-hidden one frame after it mounts — the enclosing layer's
|
|
29
|
+
* hide-outside observer walks late-arriving body children as background. The
|
|
30
|
+
* portal carries the marker that observer exempts; a modal layer opened above
|
|
31
|
+
* still hides it, because that path matches a different attribute.
|
|
26
32
|
*
|
|
27
33
|
* Use `Dialog` directly when you need its composition; use this when you want a
|
|
28
34
|
* dialog that is correct by default. `size="settings"` supplies a wide, bounded
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/modal-dialog/modal-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG7D,OAAO,EAGL,aAAa,EAId,MAAM,kBAAkB,CAAA;AAEzB
|
|
1
|
+
{"version":3,"file":"modal-dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/modal-dialog/modal-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG7D,OAAO,EAGL,aAAa,EAId,MAAM,kBAAkB,CAAA;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,CAAC,OAAO,aAAa,CAAC,EACpC,UAAU,GAAG,YAAY,GAAG,iBAAiB,GAAG,YAAY,CAC7D,GAAG;IACF,iFAAiF;IACjF,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;OAGG;IACH,eAAe,CAAC,EAAE,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;IACnD,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;CACvB,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,eAoGlD"}
|
|
@@ -39,6 +39,10 @@ function ModalDialog(props) {
|
|
|
39
39
|
if (!wasInert[index]) node.removeAttribute("inert");
|
|
40
40
|
});
|
|
41
41
|
});
|
|
42
|
+
let portal = element;
|
|
43
|
+
while (portal.parentElement !== null && portal.parentElement !== document.body) portal = portal.parentElement;
|
|
44
|
+
portal.setAttribute("data-react-aria-top-layer", "true");
|
|
45
|
+
onCleanup(() => portal.removeAttribute("data-react-aria-top-layer"));
|
|
42
46
|
});
|
|
43
47
|
return createComponent(Show, {
|
|
44
48
|
get when() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-dialog.js","names":["Accessor","ComponentProps","JSX","Show","createEffect","createSignal","onCleanup","splitProps","cn","createDialogFocusRestoration","Dialog","DialogContent","DialogDescription","DialogHeader","DialogTitle","ModalDialogProps","Omit","size","open","onClose","title","modal","description","headerLeading","Element","restoreFocusRef","HTMLElement","children","ModalDialog","props","local","rest","content","setContent","focusRestoration","onOpenAutoFocus","onCloseAutoFocus","element","background","document","body","filter","child","contains","wasInert","map","node","hasAttribute","setAttribute","forEach","index","removeAttribute","_$createComponent","when","onOpenChange","next","_$mergeProps","ref","positioner","class","aria-label","aria-labelledby","undefined","_$memo","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/modal-dialog/modal-dialog.tsx"],"sourcesContent":["import type { Accessor, ComponentProps, JSX } from 'solid-js'\nimport { Show, createEffect, createSignal, onCleanup, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport {\n createDialogFocusRestoration,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '../dialog/dialog'\n\n/**\n * ModalDialog.\n *\n * A dialog that owns four things `Dialog` leaves to its caller, each of which is a\n * real defect when it is missed:\n *\n * 1. **It unmounts while closed.** An always-mounted dialog that closes as a side\n * effect of an async action can leave Kobalte's `aria-hidden` bookkeeping behind,\n * which hides the rest of the application from assistive technology. Unmounting\n * the whole owner makes cleanup the only way the layer can end.\n * 2. **It marks the background `inert`.** `inert` keeps the background out of the\n * tab order and the accessibility tree without depending on that bookkeeping, and\n * it restores exactly the elements that did not already have it — so a nested\n * dialog does not un-inert its parent.\n * 3. **It sets an explicit accessible name.** The content receives `aria-label`\n * from `title`, so its name does not depend on the title id registration effect.\n * Pass `aria-label` to use a different name while keeping the visible title;\n * pass `aria-labelledby` when another visible label should take precedence.\n * 4. **It returns focus to the opener.** The opener is captured before the dialog\n * autofocuses and restored after the owner closes, unless a close-autofocus\n * handler takes control or focus has moved to another layer. For controlled\n * dialogs without a composed trigger, pass `restoreFocusRef` when the opener\n * cannot be inferred from the focused element.\n *\n * Use `Dialog` directly when you need its composition; use this when you want a\n * dialog that is correct by default. `size=\"settings\"` supplies a wide, bounded\n * shell for a shared settings layout; ordinary dialogs keep their compact default.\n */\nexport type ModalDialogProps = Omit<\n ComponentProps<typeof DialogContent>,\n 'children' | 'aria-label' | 'aria-labelledby' | 'positioner'\n> & {\n /** Selects the bounded, scrollable shell used for grouped workspace settings. */\n size?: 'default' | 'settings'\n open: boolean\n onClose: () => void\n title: string\n /**\n * Controls Kobalte's focus, scroll and accessibility modality. Defaults to `true`;\n * background body children remain inert in either mode.\n */\n modal?: boolean\n description?: string\n /** A mark or icon drawn before the title. */\n headerLeading?: JSX.Element\n /** Replaces `title` as the accessible name while keeping the visible title. */\n 'aria-label'?: string\n /** Names the dialog from a visible element; ARIA gives it precedence over `aria-label`. */\n 'aria-labelledby'?: string\n /**\n * Supplies the external control to focus when this controlled dialog closes.\n * Defaults to the element focused immediately before the dialog opens.\n */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n children?: JSX.Element\n}\n\nexport function ModalDialog(props: ModalDialogProps) {\n const [local, rest] = splitProps(props, [\n 'open',\n 'onClose',\n 'title',\n 'modal',\n 'size',\n 'description',\n 'headerLeading',\n 'class',\n 'children',\n 'aria-label',\n 'aria-labelledby',\n 'restoreFocusRef',\n 'onOpenAutoFocus',\n 'onCloseAutoFocus',\n ])\n\n const [content, setContent] = createSignal<HTMLElement>()\n const focusRestoration = createDialogFocusRestoration({\n open: () => local.open,\n restoreFocusRef: local.restoreFocusRef,\n onOpenAutoFocus: local.onOpenAutoFocus,\n onCloseAutoFocus: local.onCloseAutoFocus,\n })\n\n createEffect(() => {\n if (!local.open) return\n const element = content()\n if (!element) return\n\n const background = [...document.body.children].filter(\n (child): child is HTMLElement => child instanceof HTMLElement && !child.contains(element)\n )\n const wasInert = background.map((node) => node.hasAttribute('inert'))\n for (const node of background) node.setAttribute('inert', '')\n\n onCleanup(() => {\n background.forEach((node, index) => {\n // Only the elements that were not already inert are restored, so a nested\n // dialog closing does not undo its parent's containment.\n if (!wasInert[index]) node.removeAttribute('inert')\n })\n })\n })\n\n return (\n <Show when={local.open}>\n <Dialog open modal={local.modal ?? true} onOpenChange={(next) => !next && local.onClose()}>\n <DialogContent\n ref={setContent}\n positioner={local.size === 'settings' ? 'inset' : 'default'}\n class={cn(\n 'gap-4',\n local.size === 'settings' &&\n 'flex h-208 max-h-full min-h-0 max-w-6xl flex-col gap-0 overflow-hidden p-0',\n local.class\n )}\n aria-label={local['aria-label'] ?? local.title}\n aria-labelledby={\n local['aria-labelledby'] ?? (local['aria-label'] !== undefined ? '' : undefined)\n }\n {...rest}\n onOpenAutoFocus={focusRestoration.onOpenAutoFocus}\n onCloseAutoFocus={focusRestoration.onCloseAutoFocus}\n >\n <DialogHeader\n class={\n local.size === 'settings'\n ? 'shrink-0 gap-1 border-b border-border px-5 pt-4 pb-3 pe-14'\n : undefined\n }\n >\n <DialogTitle class=\"flex items-center gap-2\">\n <Show when={local.headerLeading}>{local.headerLeading}</Show>\n {local.title}\n </DialogTitle>\n <Show when={local.description}>\n <DialogDescription>{local.description}</DialogDescription>\n </Show>\n </DialogHeader>\n {local.children}\n </DialogContent>\n </Dialog>\n </Show>\n )\n}\n"],"mappings":";;;;;AAqEA,SAAgB4B,YAAYC,OAAyB;CACnD,MAAM,CAACC,OAAOC,QAAQxB,WAAWsB,OAAO;EACtC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAAkB,CACnB;CAED,MAAM,CAACG,SAASC,cAAc5B,aAA0B;CACxD,MAAM6B,mBAAmBzB,6BAA6B;EACpDS,YAAYY,MAAMZ;EAClBO,iBAAiBK,MAAML;EACvBU,iBAAiBL,MAAMK;EACvBC,kBAAkBN,MAAMM;CAC1B,CAAC;CAEDhC,mBAAmB;EACjB,IAAI,CAAC0B,MAAMZ,MAAM;EACjB,MAAMmB,UAAUL,QAAQ;EACxB,IAAI,CAACK,SAAS;EAEd,MAAMC,aAAa,CAAC,GAAGC,SAASC,KAAKb,QAAQ,CAAC,CAACc,QAC5CC,UAAgCA,iBAAiBhB,eAAe,CAACgB,MAAMC,SAASN,OAAO,CAC1F;EACA,MAAMO,WAAWN,WAAWO,KAAKC,SAASA,KAAKC,aAAa,OAAO,CAAC;EACpE,KAAK,MAAMD,QAAQR,YAAYQ,KAAKE,aAAa,SAAS,EAAE;EAE5D1C,gBAAgB;GACdgC,WAAWW,SAASH,MAAMI,UAAU;IAGlC,IAAI,CAACN,SAASM,QAAQJ,KAAKK,gBAAgB,OAAO;GACpD,CAAC;EACH,CAAC;CACH,CAAC;CAED,OAAAC,gBACGjD,MAAI;EAAA,IAACkD,OAAI;GAAA,OAAEvB,MAAMZ;EAAI;EAAA,IAAAS,WAAA;GAAA,OAAAyB,gBACnB1C,QAAM;IAACQ,MAAI;IAAA,IAACG,QAAK;KAAA,OAAES,MAAMT,SAAS;IAAI;IAAEiC,eAAeC,SAAS,CAACA,QAAQzB,MAAMX,QAAQ;IAAC,IAAAQ,WAAA;KAAA,OAAAyB,gBACtFzC,eAAa6C,WAAA;MAAAC,KACPxB;MAAU,IACfyB,aAAU;OAAA,OAAE5B,MAAMb,SAAS,aAAa,UAAU;MAAS;MAAA,KAAA,WAAA;OAAA,OACpDT,GACL,SACAsB,MAAMb,SAAS,cACb,8EACFa,MAAM6B,KACR;MAAC;MAAA,KAAA,gBAAA;OAAA,OACW7B,MAAM,iBAAiBA,MAAMV;MAAK;MAAA,KAAA,qBAAA;OAAA,OAE5CU,MAAM,uBAAuBA,MAAM,kBAAkBgC,KAAAA,IAAY,KAAKA,KAAAA;MAAU;KAAA,GAE9E/B,MAAI;MAAA,IACRI,kBAAe;OAAA,OAAED,iBAAiBC;MAAe;MAAA,IACjDC,mBAAgB;OAAA,OAAEF,iBAAiBE;MAAgB;MAAA,IAAAT,WAAA;OAAA,OAAA,CAAAyB,gBAElDvC,cAAY;QAAA,KAAA,WAAA;SAAA,OAETiB,MAAMb,SAAS,aACX,+DACA6C,KAAAA;QAAS;QAAA,IAAAnC,WAAA;SAAA,OAAA,CAAAyB,gBAGdtC,aAAW;UAAA,SAAA;UAAA,IAAAa,WAAA;WAAA,OAAA,CAAAyB,gBACTjD,MAAI;YAAA,IAACkD,OAAI;aAAA,OAAEvB,MAAMP;YAAa;YAAA,IAAAI,WAAA;aAAA,OAAGG,MAAMP;YAAa;WAAA,CAAA,GAAAwC,WACpDjC,MAAMV,KAAK,CAAA;UAAA;SAAA,CAAA,GAAAgC,gBAEbjD,MAAI;UAAA,IAACkD,OAAI;WAAA,OAAEvB,MAAMR;UAAW;UAAA,IAAAK,WAAA;WAAA,OAAAyB,gBAC1BxC,mBAAiB,EAAA,IAAAe,WAAA;YAAA,OAAEG,MAAMR;WAAW,EAAA,CAAA;UAAA;SAAA,CAAA,CAAA;QAAA;OAAA,CAAA,GAAAyC,WAGxCjC,MAAMH,QAAQ,CAAA;MAAA;KAAA,CAAA,CAAA;IAAA;GAAA,CAAA;EAAA;CAAA,CAAA;AAKzB"}
|
|
1
|
+
{"version":3,"file":"modal-dialog.js","names":["Accessor","ComponentProps","JSX","Show","createEffect","createSignal","onCleanup","splitProps","cn","createDialogFocusRestoration","Dialog","DialogContent","DialogDescription","DialogHeader","DialogTitle","ModalDialogProps","Omit","size","open","onClose","title","modal","description","headerLeading","Element","restoreFocusRef","HTMLElement","children","ModalDialog","props","local","rest","content","setContent","focusRestoration","onOpenAutoFocus","onCloseAutoFocus","element","background","document","body","filter","child","contains","wasInert","map","node","hasAttribute","setAttribute","forEach","index","removeAttribute","portal","parentElement","_$createComponent","when","onOpenChange","next","_$mergeProps","ref","positioner","class","aria-label","aria-labelledby","undefined","_$memo","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/modal-dialog/modal-dialog.tsx"],"sourcesContent":["import type { Accessor, ComponentProps, JSX } from 'solid-js'\nimport { Show, createEffect, createSignal, onCleanup, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport {\n createDialogFocusRestoration,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '../dialog/dialog'\n\n/**\n * ModalDialog.\n *\n * A dialog that owns four things `Dialog` leaves to its caller, each of which is a\n * real defect when it is missed:\n *\n * 1. **It unmounts while closed.** An always-mounted dialog that closes as a side\n * effect of an async action can leave Kobalte's `aria-hidden` bookkeeping behind,\n * which hides the rest of the application from assistive technology. Unmounting\n * the whole owner makes cleanup the only way the layer can end.\n * 2. **It marks the background `inert`.** `inert` keeps the background out of the\n * tab order and the accessibility tree without depending on that bookkeeping, and\n * it restores exactly the elements that did not already have it — so a nested\n * dialog does not un-inert its parent.\n * 3. **It sets an explicit accessible name.** The content receives `aria-label`\n * from `title`, so its name does not depend on the title id registration effect.\n * Pass `aria-label` to use a different name while keeping the visible title;\n * pass `aria-labelledby` when another visible label should take precedence.\n * 4. **It returns focus to the opener.** The opener is captured before the dialog\n * autofocuses and restored after the owner closes, unless a close-autofocus\n * handler takes control or focus has moved to another layer. For controlled\n * dialogs without a composed trigger, pass `restoreFocusRef` when the opener\n * cannot be inferred from the focused element.\n * 5. **It keeps its own portal out of an enclosing layer's `aria-hidden`\n * bookkeeping.** A non-modal dialog opened while a modal `Sheet` is alive would\n * otherwise be aria-hidden one frame after it mounts — the enclosing layer's\n * hide-outside observer walks late-arriving body children as background. The\n * portal carries the marker that observer exempts; a modal layer opened above\n * still hides it, because that path matches a different attribute.\n *\n * Use `Dialog` directly when you need its composition; use this when you want a\n * dialog that is correct by default. `size=\"settings\"` supplies a wide, bounded\n * shell for a shared settings layout; ordinary dialogs keep their compact default.\n */\nexport type ModalDialogProps = Omit<\n ComponentProps<typeof DialogContent>,\n 'children' | 'aria-label' | 'aria-labelledby' | 'positioner'\n> & {\n /** Selects the bounded, scrollable shell used for grouped workspace settings. */\n size?: 'default' | 'settings'\n open: boolean\n onClose: () => void\n title: string\n /**\n * Controls Kobalte's focus, scroll and accessibility modality. Defaults to `true`;\n * background body children remain inert in either mode.\n */\n modal?: boolean\n description?: string\n /** A mark or icon drawn before the title. */\n headerLeading?: JSX.Element\n /** Replaces `title` as the accessible name while keeping the visible title. */\n 'aria-label'?: string\n /** Names the dialog from a visible element; ARIA gives it precedence over `aria-label`. */\n 'aria-labelledby'?: string\n /**\n * Supplies the external control to focus when this controlled dialog closes.\n * Defaults to the element focused immediately before the dialog opens.\n */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n children?: JSX.Element\n}\n\nexport function ModalDialog(props: ModalDialogProps) {\n const [local, rest] = splitProps(props, [\n 'open',\n 'onClose',\n 'title',\n 'modal',\n 'size',\n 'description',\n 'headerLeading',\n 'class',\n 'children',\n 'aria-label',\n 'aria-labelledby',\n 'restoreFocusRef',\n 'onOpenAutoFocus',\n 'onCloseAutoFocus',\n ])\n\n const [content, setContent] = createSignal<HTMLElement>()\n const focusRestoration = createDialogFocusRestoration({\n open: () => local.open,\n restoreFocusRef: local.restoreFocusRef,\n onOpenAutoFocus: local.onOpenAutoFocus,\n onCloseAutoFocus: local.onCloseAutoFocus,\n })\n\n createEffect(() => {\n if (!local.open) return\n const element = content()\n if (!element) return\n\n const background = [...document.body.children].filter(\n (child): child is HTMLElement => child instanceof HTMLElement && !child.contains(element)\n )\n const wasInert = background.map((node) => node.hasAttribute('inert'))\n for (const node of background) node.setAttribute('inert', '')\n\n onCleanup(() => {\n background.forEach((node, index) => {\n // Only the elements that were not already inert are restored, so a nested\n // dialog closing does not undo its parent's containment.\n if (!wasInert[index]) node.removeAttribute('inert')\n })\n })\n\n // Kobalte's hide-outside observer walks body children added after its layer\n // opened and aria-hides them one frame later, so a non-modal dialog portaled\n // in during that window would land outside the accessibility tree — role\n // queries never resolve it again while the enclosing layer stays open. The\n // observer exempts added nodes carrying its top-layer marker (it checks the\n // React Aria spelling it ported; `data-kb-top-layer` is only matched by a\n // newer layer's initial walk, which must still hide this dialog).\n let portal = element\n while (portal.parentElement !== null && portal.parentElement !== document.body) {\n portal = portal.parentElement\n }\n portal.setAttribute('data-react-aria-top-layer', 'true')\n onCleanup(() => portal.removeAttribute('data-react-aria-top-layer'))\n })\n\n return (\n <Show when={local.open}>\n <Dialog open modal={local.modal ?? true} onOpenChange={(next) => !next && local.onClose()}>\n <DialogContent\n ref={setContent}\n positioner={local.size === 'settings' ? 'inset' : 'default'}\n class={cn(\n 'gap-4',\n local.size === 'settings' &&\n 'flex h-208 max-h-full min-h-0 max-w-6xl flex-col gap-0 overflow-hidden p-0',\n local.class\n )}\n aria-label={local['aria-label'] ?? local.title}\n aria-labelledby={\n local['aria-labelledby'] ?? (local['aria-label'] !== undefined ? '' : undefined)\n }\n {...rest}\n onOpenAutoFocus={focusRestoration.onOpenAutoFocus}\n onCloseAutoFocus={focusRestoration.onCloseAutoFocus}\n >\n <DialogHeader\n class={\n local.size === 'settings'\n ? 'shrink-0 gap-1 border-b border-border px-5 pt-4 pb-3 pe-14'\n : undefined\n }\n >\n <DialogTitle class=\"flex items-center gap-2\">\n <Show when={local.headerLeading}>{local.headerLeading}</Show>\n {local.title}\n </DialogTitle>\n <Show when={local.description}>\n <DialogDescription>{local.description}</DialogDescription>\n </Show>\n </DialogHeader>\n {local.children}\n </DialogContent>\n </Dialog>\n </Show>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dialog as KobalteDialog, Content as KobalteDialogContent } from '@kobalte/core/dialog';
|
|
2
|
-
import type { ComponentProps, JSX } from 'solid-js';
|
|
2
|
+
import type { Accessor, ComponentProps, JSX } from 'solid-js';
|
|
3
3
|
import { type VariantProps } from '#lib/variants';
|
|
4
4
|
/**
|
|
5
5
|
* Sheet.
|
|
@@ -12,12 +12,19 @@ import { type VariantProps } from '#lib/variants';
|
|
|
12
12
|
* `side` decides which edge; the panel is a full-height column for `start` and
|
|
13
13
|
* `end`, and a full-width row for `top` and `bottom`. The slide-in direction
|
|
14
14
|
* follows from the side, so a caller never pairs them by hand.
|
|
15
|
+
*
|
|
16
|
+
* Controlled sheets opened from outside a `SheetTrigger` restore focus to the
|
|
17
|
+
* element focused before opening. Pass `restoreFocusRef` when a stable external
|
|
18
|
+
* opener must be used instead, such as when another layer closes before the
|
|
19
|
+
* sheet opens.
|
|
15
20
|
*/
|
|
16
21
|
declare const sheetVariants: (props?: ({
|
|
17
22
|
side?: "end" | "start" | "bottom" | "top" | null | undefined;
|
|
18
23
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
19
24
|
export type SheetContentProps = ComponentProps<typeof KobalteDialogContent> & VariantProps<typeof sheetVariants> & {
|
|
20
25
|
closeButton?: JSX.Element | false;
|
|
26
|
+
/** Supplies the stable external element to focus when the controlled sheet closes. */
|
|
27
|
+
restoreFocusRef?: Accessor<HTMLElement | undefined>;
|
|
21
28
|
};
|
|
22
29
|
export declare function SheetContent(props: SheetContentProps): JSX.Element;
|
|
23
30
|
export declare function Sheet(props: ComponentProps<typeof KobalteDialog>): JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sheet/sheet.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"sheet.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/sheet/sheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,IAAI,aAAa,EACvB,OAAO,IAAI,oBAAoB,EAEhC,MAAM,sBAAsB,CAAA;AAG7B,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAE7D,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAItD;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,aAAa;;8EAelB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,oBAAoB,CAAC,GACzE,YAAY,CAAC,OAAO,aAAa,CAAC,GAAG;IACnC,WAAW,CAAC,EAAE,GAAG,CAAC,OAAO,GAAG,KAAK,CAAA;IACjC,sFAAsF;IACtF,eAAe,CAAC,EAAE,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;CACpD,CAAA;AAEH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,eAiDpD;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,eAEhE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,eAE/E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,WAAW,CAAC,eAGvF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,eASvD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,eASrD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,eASvD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,KAAK,CAAC,eAK3E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,WAAW,CAAC,eAKvF;AAED,OAAO,EAAE,aAAa,EAAE,CAAA"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
2
|
import { cva } from "../../../lib/variants.js";
|
|
3
|
-
import { DialogOverlay } from "../dialog/dialog.js";
|
|
3
|
+
import { DialogOverlay, createDialogFocusRestoration } from "../dialog/dialog.js";
|
|
4
4
|
import { createComponent, memo, mergeProps, spread, template } from "solid-js/web";
|
|
5
5
|
import { X } from "lucide-solid";
|
|
6
6
|
import { Show, splitProps } from "solid-js";
|
|
7
|
-
import { Content, Dialog } from "@kobalte/core/dialog";
|
|
7
|
+
import { Content, Dialog, useDialogContext } from "@kobalte/core/dialog";
|
|
8
8
|
//#region src/components/ui/sheet/sheet.tsx
|
|
9
9
|
var _tmpl$ = /*#__PURE__*/ template(`<div data-slot=sheet-header>`);
|
|
10
10
|
var _tmpl$2 = /*#__PURE__*/ template(`<div data-slot=sheet-body>`);
|
|
@@ -20,6 +20,11 @@ var _tmpl$3 = /*#__PURE__*/ template(`<div data-slot=sheet-footer>`);
|
|
|
20
20
|
* `side` decides which edge; the panel is a full-height column for `start` and
|
|
21
21
|
* `end`, and a full-width row for `top` and `bottom`. The slide-in direction
|
|
22
22
|
* follows from the side, so a caller never pairs them by hand.
|
|
23
|
+
*
|
|
24
|
+
* Controlled sheets opened from outside a `SheetTrigger` restore focus to the
|
|
25
|
+
* element focused before opening. Pass `restoreFocusRef` when a stable external
|
|
26
|
+
* opener must be used instead, such as when another layer closes before the
|
|
27
|
+
* sheet opens.
|
|
23
28
|
*/
|
|
24
29
|
var sheetVariants = cva("bg-popover text-popover-foreground fixed z-(--z-dialog) flex flex-col gap-4 border-border shadow-lg", {
|
|
25
30
|
variants: { side: {
|
|
@@ -35,27 +40,46 @@ function SheetContent(props) {
|
|
|
35
40
|
"class",
|
|
36
41
|
"side",
|
|
37
42
|
"children",
|
|
38
|
-
"closeButton"
|
|
43
|
+
"closeButton",
|
|
44
|
+
"restoreFocusRef",
|
|
45
|
+
"onOpenAutoFocus",
|
|
46
|
+
"onCloseAutoFocus"
|
|
39
47
|
]);
|
|
48
|
+
const dialog = useDialogContext();
|
|
49
|
+
const focusRestoration = createDialogFocusRestoration({
|
|
50
|
+
open: dialog.isOpen,
|
|
51
|
+
restoreFocusRef: local.restoreFocusRef,
|
|
52
|
+
onOpenAutoFocus: local.onOpenAutoFocus,
|
|
53
|
+
onCloseAutoFocus: local.onCloseAutoFocus
|
|
54
|
+
});
|
|
40
55
|
return createComponent(Dialog.Portal, { get children() {
|
|
41
56
|
return [createComponent(DialogOverlay, {}), createComponent(Content, mergeProps({ get ["class"]() {
|
|
42
57
|
return cn(sheetVariants({ side: local.side }), "data-expanded:animate-in data-expanded:fade-in-0 data-expanded:duration-200", "data-closed:animate-out data-closed:fade-out-0 data-closed:duration-150", local.class);
|
|
43
|
-
} }, rest, {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
} }, rest, {
|
|
59
|
+
get onOpenAutoFocus() {
|
|
60
|
+
return focusRestoration.onOpenAutoFocus;
|
|
61
|
+
},
|
|
62
|
+
get onCloseAutoFocus() {
|
|
63
|
+
return focusRestoration.onCloseAutoFocus;
|
|
64
|
+
},
|
|
65
|
+
get children() {
|
|
66
|
+
return [memo(() => local.children), createComponent(Show, {
|
|
67
|
+
get when() {
|
|
68
|
+
return local.closeButton !== false;
|
|
69
|
+
},
|
|
70
|
+
get children() {
|
|
71
|
+
return createComponent(Dialog.CloseButton, {
|
|
72
|
+
"aria-label": "Close",
|
|
73
|
+
tabindex: "0",
|
|
74
|
+
"class": "absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground transition-colors ease-out outline-none hover:bg-surface-hover hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle",
|
|
75
|
+
get children() {
|
|
76
|
+
return local.closeButton ?? createComponent(X, { "class": "size-4" });
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
})];
|
|
81
|
+
}
|
|
82
|
+
}))];
|
|
59
83
|
} });
|
|
60
84
|
}
|
|
61
85
|
function Sheet(props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet.js","names":["Dialog","KobalteDialog","Content","KobalteDialogContent","X","ComponentProps","JSX","Show","splitProps","cva","VariantProps","cn","DialogOverlay","sheetVariants","variants","side","top","bottom","start","end","defaultVariants","SheetContentProps","closeButton","Element","SheetContent","props","local","rest","_$createComponent","Portal","children","_$mergeProps","class","_$memo","when","CloseButton","Sheet","SheetTrigger","Trigger","SheetCloseButton","SheetHeader","_el$","_tmpl$","_$spread","SheetBody","_el$2","_tmpl$2","SheetFooter","_el$3","_tmpl$3","SheetTitle","Title","SheetDescription","Description","_$createComponent","KobalteDialog","KobalteDialogContent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/sheet/sheet.tsx"],"sourcesContent":["import { Dialog as KobalteDialog, Content as KobalteDialogContent } from '@kobalte/core/dialog'\n// AlertDialog shares DialogRoot.Content; Sheet uses the stable named primitive.\nimport { X } from 'lucide-solid'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\nimport { DialogOverlay } from '../dialog/dialog'\n\n/**\n * Sheet.\n *\n * A dialog anchored to an edge of the window rather than centred. Use it when\n * the content is a *panel beside* the work — a details inspector, a filter rail,\n * a settings flyout — so the user keeps the context it belongs to in view.\n * A centred dialog interrupts; a sheet is inspected.\n *\n * `side` decides which edge; the panel is a full-height column for `start` and\n * `end`, and a full-width row for `top` and `bottom`. The slide-in direction\n * follows from the side, so a caller never pairs them by hand.\n */\nconst sheetVariants = cva(\n 'bg-popover text-popover-foreground fixed z-(--z-dialog) flex flex-col gap-4 border-border shadow-lg',\n {\n variants: {\n side: {\n top: 'inset-x-0 top-0 h-auto max-h-[85vh] rounded-b-xl border-b data-expanded:slide-in-from-top data-closed:slide-out-to-top',\n bottom:\n 'inset-x-0 bottom-0 h-auto max-h-[85vh] rounded-t-xl border-t data-expanded:slide-in-from-bottom data-closed:slide-out-to-bottom',\n start:\n 'inset-y-0 start-0 h-full w-80 max-w-[85vw] rounded-e-xl border-e data-expanded:slide-in-from-left data-closed:slide-out-to-left',\n end: 'inset-y-0 end-0 h-full w-80 max-w-[85vw] rounded-s-xl border-s data-expanded:slide-in-from-right data-closed:slide-out-to-right',\n },\n },\n defaultVariants: { side: 'end' },\n }\n)\n\nexport type SheetContentProps = ComponentProps<typeof KobalteDialogContent> &\n VariantProps<typeof sheetVariants> & {\n closeButton?: JSX.Element | false\n }\n\nexport function SheetContent(props: SheetContentProps) {\n const [local, rest] = splitProps(props, ['class', 'side', 'children', 'closeButton'])\n\n return (\n <KobalteDialog.Portal>\n <DialogOverlay />\n <KobalteDialogContent\n class={cn(\n sheetVariants({ side: local.side }),\n 'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:duration-200',\n 'data-closed:animate-out data-closed:fade-out-0 data-closed:duration-150',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <Show when={local.closeButton !== false}>\n <KobalteDialog.CloseButton\n aria-label=\"Close\"\n class=\"absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground transition-colors ease-out outline-none hover:bg-surface-hover hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle\"\n >\n {local.closeButton ?? <X class=\"size-4\" />}\n </KobalteDialog.CloseButton>\n </Show>\n </KobalteDialogContent>\n </KobalteDialog.Portal>\n )\n}\n\nexport function Sheet(props: ComponentProps<typeof KobalteDialog>) {\n return <KobalteDialog {...props} />\n}\n\nexport function SheetTrigger(props: ComponentProps<typeof KobalteDialog.Trigger>) {\n return <KobalteDialog.Trigger {...props} />\n}\n\nexport function SheetCloseButton(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn(local.class)} {...rest} />\n}\n\nexport function SheetHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sheet-header\"\n class={cn('flex flex-col gap-1.5 border-b border-border p-4 pe-12 text-start', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SheetBody(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sheet-body\"\n class={cn('flex-1 overflow-y-auto px-4 pb-4', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SheetFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sheet-footer\"\n class={cn('flex items-center justify-end gap-2 border-t border-border p-4', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SheetTitle(props: ComponentProps<typeof KobalteDialog.Title>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Title class={cn('text-sm leading-none font-semibold', local.class)} {...rest} />\n )\n}\n\nexport function SheetDescription(props: ComponentProps<typeof KobalteDialog.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Description class={cn('text-muted-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport { sheetVariants }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAMa,gBAAgBJ,IACpB,uGACA;CACEK,UAAU,EACRC,MAAM;EACJC,KAAK;EACLC,QACE;EACFC,OACE;EACFC,KAAK;CACP,EACF;CACAC,iBAAiB,EAAEL,MAAM,MAAM;AACjC,CACF;AAOA,SAAgBS,aAAaC,OAA0B;CACrD,MAAM,CAACC,OAAOC,QAAQnB,WAAWiB,OAAO;EAAC;EAAS;EAAQ;EAAY;CAAa,CAAC;CAEpF,OAAAG,gBACG3B,OAAc4B,QAAM,EAAA,IAAAC,WAAA;EAAA,OAAA,CAAAF,gBAClBhB,eAAa,CAAA,CAAA,GAAAgB,gBACbzB,SAAoB4B,WAAA,EAAA,KAAA,WAAA;GAAA,OACZpB,GACLE,cAAc,EAAEE,MAAMW,MAAMX,KAAK,CAAC,GAClC,+EACA,2EACAW,MAAMM,KACR;EAAC,EAAA,GACGL,MAAI,EAAA,IAAAG,WAAA;GAAA,OAAA,CAAAG,WAEPP,MAAMI,QAAQ,GAAAF,gBACdrB,MAAI;IAAA,IAAC2B,OAAI;KAAA,OAAER,MAAMJ,gBAAgB;IAAK;IAAA,IAAAQ,WAAA;KAAA,OAAAF,gBACpC3B,OAAckC,aAAW;MAAA,cAAA;MAAA,SAAA;MAAA,IAAAL,WAAA;OAAA,OAIvBJ,MAAMJ,eAAWM,gBAAKxB,GAAC,EAAA,SAAA,SAAA,CAAA;MAAkB;KAAA,CAAA;IAAA;GAAA,CAAA,CAAA;EAAA,EAAA,CAAA,CAAA,CAAA;CAAA,EAAA,CAAA;AAMtD;AAEA,SAAgBgC,MAAMX,OAA6C;CACjE,OAAAG,gBAAQ3B,QAAkBwB,KAAK;AACjC;AAEA,SAAgBY,aAAaZ,OAAqD;CAChF,OAAAG,gBAAQ3B,OAAcqC,SAAYb,KAAK;AACzC;AAEA,SAAgBc,iBAAiBd,OAAyD;CACxF,MAAM,CAACC,OAAOC,QAAQnB,WAAWiB,OAAO,CAAC,OAAO,CAAC;CACjD,OAAAG,gBAAQ3B,OAAckC,aAAWJ,WAAA,EAAA,KAAA,WAAA;EAAA,OAAQpB,GAAGe,MAAMM,KAAK;CAAC,EAAA,GAAML,IAAI,CAAA;AACpE;AAEA,SAAgBa,YAAYf,OAA8B;CACxD,MAAM,CAACC,OAAOC,QAAQnB,WAAWiB,OAAO,CAAC,OAAO,CAAC;CACjD,cAAA;EAAA,IAAAgB,OAAAC,OAAA;EAAAC,OAAAF,MAAAV,WAAA,EAAA,KAAA,WAAA;GAAA,OAGWpB,GAAG,qEAAqEe,MAAMM,KAAK;EAAC,EAAA,GACvFL,IAAI,GAAA,OAAA,KAAA;EAAA,OAAAc;CAAA,EAAA,CAAA;AAGd;AAEA,SAAgBG,UAAUnB,OAA8B;CACtD,MAAM,CAACC,OAAOC,QAAQnB,WAAWiB,OAAO,CAAC,OAAO,CAAC;CACjD,cAAA;EAAA,IAAAoB,QAAAC,QAAA;EAAAH,OAAAE,OAAAd,WAAA,EAAA,KAAA,WAAA;GAAA,OAGWpB,GAAG,oCAAoCe,MAAMM,KAAK;EAAC,EAAA,GACtDL,IAAI,GAAA,OAAA,KAAA;EAAA,OAAAkB;CAAA,EAAA,CAAA;AAGd;AAEA,SAAgBE,YAAYtB,OAA8B;CACxD,MAAM,CAACC,OAAOC,QAAQnB,WAAWiB,OAAO,CAAC,OAAO,CAAC;CACjD,cAAA;EAAA,IAAAuB,QAAAC,QAAA;EAAAN,OAAAK,OAAAjB,WAAA,EAAA,KAAA,WAAA;GAAA,OAGWpB,GAAG,kEAAkEe,MAAMM,KAAK;EAAC,EAAA,GACpFL,IAAI,GAAA,OAAA,KAAA;EAAA,OAAAqB;CAAA,EAAA,CAAA;AAGd;AAEA,SAAgBE,WAAWzB,OAAmD;CAC5E,MAAM,CAACC,OAAOC,QAAQnB,WAAWiB,OAAO,CAAC,OAAO,CAAC;CACjD,OAAAG,gBACG3B,OAAckD,OAAKpB,WAAA,EAAA,KAAA,WAAA;EAAA,OAAQpB,GAAG,sCAAsCe,MAAMM,KAAK;CAAC,EAAA,GAAML,IAAI,CAAA;AAE/F;AAEA,SAAgByB,iBAAiB3B,OAAyD;CACxF,MAAM,CAACC,OAAOC,QAAQnB,WAAWiB,OAAO,CAAC,OAAO,CAAC;CACjD,OAAAG,gBACG3B,OAAcoD,aAAWtB,WAAA,EAAA,KAAA,WAAA;EAAA,OAAQpB,GAAG,iCAAiCe,MAAMM,KAAK;CAAC,EAAA,GAAML,IAAI,CAAA;AAEhG"}
|
|
1
|
+
{"version":3,"file":"sheet.js","names":["Dialog","KobalteDialog","Content","KobalteDialogContent","useDialogContext","X","Accessor","ComponentProps","JSX","Show","splitProps","cva","VariantProps","cn","createDialogFocusRestoration","DialogOverlay","sheetVariants","variants","side","top","bottom","start","end","defaultVariants","SheetContentProps","closeButton","Element","restoreFocusRef","HTMLElement","SheetContent","props","local","rest","dialog","focusRestoration","open","isOpen","onOpenAutoFocus","onCloseAutoFocus","_$createComponent","Portal","children","_$mergeProps","class","_$memo","when","CloseButton","tabindex","Sheet","SheetTrigger","Trigger","SheetCloseButton","SheetHeader","_el$","_tmpl$","_$spread","SheetBody","_el$2","_tmpl$2","SheetFooter","_el$3","_tmpl$3","SheetTitle","Title","SheetDescription","Description","_$createComponent","KobalteDialog","KobalteDialogContent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/sheet/sheet.tsx"],"sourcesContent":["import {\n Dialog as KobalteDialog,\n Content as KobalteDialogContent,\n useDialogContext,\n} from '@kobalte/core/dialog'\n// AlertDialog shares DialogRoot.Content; Sheet uses the stable named primitive.\nimport { X } from 'lucide-solid'\nimport type { Accessor, ComponentProps, JSX } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\nimport { createDialogFocusRestoration, DialogOverlay } from '../dialog/dialog'\n\n/**\n * Sheet.\n *\n * A dialog anchored to an edge of the window rather than centred. Use it when\n * the content is a *panel beside* the work — a details inspector, a filter rail,\n * a settings flyout — so the user keeps the context it belongs to in view.\n * A centred dialog interrupts; a sheet is inspected.\n *\n * `side` decides which edge; the panel is a full-height column for `start` and\n * `end`, and a full-width row for `top` and `bottom`. The slide-in direction\n * follows from the side, so a caller never pairs them by hand.\n *\n * Controlled sheets opened from outside a `SheetTrigger` restore focus to the\n * element focused before opening. Pass `restoreFocusRef` when a stable external\n * opener must be used instead, such as when another layer closes before the\n * sheet opens.\n */\nconst sheetVariants = cva(\n 'bg-popover text-popover-foreground fixed z-(--z-dialog) flex flex-col gap-4 border-border shadow-lg',\n {\n variants: {\n side: {\n top: 'inset-x-0 top-0 h-auto max-h-[85vh] rounded-b-xl border-b data-expanded:slide-in-from-top data-closed:slide-out-to-top',\n bottom:\n 'inset-x-0 bottom-0 h-auto max-h-[85vh] rounded-t-xl border-t data-expanded:slide-in-from-bottom data-closed:slide-out-to-bottom',\n start:\n 'inset-y-0 start-0 h-full w-80 max-w-[85vw] rounded-e-xl border-e data-expanded:slide-in-from-left data-closed:slide-out-to-left',\n end: 'inset-y-0 end-0 h-full w-80 max-w-[85vw] rounded-s-xl border-s data-expanded:slide-in-from-right data-closed:slide-out-to-right',\n },\n },\n defaultVariants: { side: 'end' },\n }\n)\n\nexport type SheetContentProps = ComponentProps<typeof KobalteDialogContent> &\n VariantProps<typeof sheetVariants> & {\n closeButton?: JSX.Element | false\n /** Supplies the stable external element to focus when the controlled sheet closes. */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n }\n\nexport function SheetContent(props: SheetContentProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'side',\n 'children',\n 'closeButton',\n 'restoreFocusRef',\n 'onOpenAutoFocus',\n 'onCloseAutoFocus',\n ])\n const dialog = useDialogContext()\n const focusRestoration = createDialogFocusRestoration({\n open: dialog.isOpen,\n restoreFocusRef: local.restoreFocusRef,\n onOpenAutoFocus: local.onOpenAutoFocus,\n onCloseAutoFocus: local.onCloseAutoFocus,\n })\n\n return (\n <KobalteDialog.Portal>\n <DialogOverlay />\n <KobalteDialogContent\n class={cn(\n sheetVariants({ side: local.side }),\n 'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:duration-200',\n 'data-closed:animate-out data-closed:fade-out-0 data-closed:duration-150',\n local.class\n )}\n {...rest}\n onOpenAutoFocus={focusRestoration.onOpenAutoFocus}\n onCloseAutoFocus={focusRestoration.onCloseAutoFocus}\n >\n {local.children}\n <Show when={local.closeButton !== false}>\n {/* The close action opts into the tab order explicitly. Engines that\n derive tabbability from the DOM instead of the host (Playwright's\n WebKit walks only explicit tabindex and form controls) would skip\n an implicitly-tabbable button and jump past the sheet's end. */}\n <KobalteDialog.CloseButton\n aria-label=\"Close\"\n tabindex=\"0\"\n class=\"absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground transition-colors ease-out outline-none hover:bg-surface-hover hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle\"\n >\n {local.closeButton ?? <X class=\"size-4\" />}\n </KobalteDialog.CloseButton>\n </Show>\n </KobalteDialogContent>\n </KobalteDialog.Portal>\n )\n}\n\nexport function Sheet(props: ComponentProps<typeof KobalteDialog>) {\n return <KobalteDialog {...props} />\n}\n\nexport function SheetTrigger(props: ComponentProps<typeof KobalteDialog.Trigger>) {\n return <KobalteDialog.Trigger {...props} />\n}\n\nexport function SheetCloseButton(props: ComponentProps<typeof KobalteDialog.CloseButton>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDialog.CloseButton class={cn(local.class)} {...rest} />\n}\n\nexport function SheetHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sheet-header\"\n class={cn('flex flex-col gap-1.5 border-b border-border p-4 pe-12 text-start', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SheetBody(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sheet-body\"\n class={cn('flex-1 overflow-y-auto px-4 pb-4', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SheetFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sheet-footer\"\n class={cn('flex items-center justify-end gap-2 border-t border-border p-4', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SheetTitle(props: ComponentProps<typeof KobalteDialog.Title>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Title class={cn('text-sm leading-none font-semibold', local.class)} {...rest} />\n )\n}\n\nexport function SheetDescription(props: ComponentProps<typeof KobalteDialog.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteDialog.Description class={cn('text-muted-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport { sheetVariants }\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle-group.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/toggle-group/toggle-group.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD;;;;;;;;;;;;;GAaG;AACH;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3F,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC,SAAS,CAAC,CAAA;IACxD,IAAI,CAAC,EAAE,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;IAClD,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,kCAgBlD;AAED,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,IAAI,CAAC,GAC/E,YAAY,CAAC,OAAO,cAAc,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"toggle-group.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/toggle-group/toggle-group.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD;;;;;;;;;;;;;GAaG;AACH;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3F,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC,SAAS,CAAC,CAAA;IACxD,IAAI,CAAC,EAAE,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;IAClD,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,kCAgBlD;AAED,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,IAAI,CAAC,GAC/E,YAAY,CAAC,OAAO,cAAc,CAAC,CAAA;AAWrC,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,kCAiB1D"}
|
|
@@ -19,18 +19,31 @@ function ToggleGroup$1(props) {
|
|
|
19
19
|
}
|
|
20
20
|
}, rest));
|
|
21
21
|
}
|
|
22
|
+
function invokeEventHandler(handler, event) {
|
|
23
|
+
if (Array.isArray(handler)) {
|
|
24
|
+
const [callback, data] = handler;
|
|
25
|
+
callback(data, event);
|
|
26
|
+
} else if (typeof handler === "function") handler(event);
|
|
27
|
+
}
|
|
22
28
|
function ToggleGroupItem(props) {
|
|
23
29
|
const [local, rest] = splitProps(props, [
|
|
24
30
|
"class",
|
|
25
31
|
"variant",
|
|
26
|
-
"size"
|
|
32
|
+
"size",
|
|
33
|
+
"onKeyDown"
|
|
27
34
|
]);
|
|
28
|
-
return createComponent(ToggleGroup.Item, mergeProps({
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
return createComponent(ToggleGroup.Item, mergeProps({
|
|
36
|
+
get ["class"]() {
|
|
37
|
+
return cn(toggleVariants({
|
|
38
|
+
variant: local.variant,
|
|
39
|
+
size: local.size
|
|
40
|
+
}), local.class);
|
|
41
|
+
},
|
|
42
|
+
onKeyDown: (event) => {
|
|
43
|
+
invokeEventHandler(local.onKeyDown, event);
|
|
44
|
+
if (event.key === "Escape") event.stopPropagation();
|
|
45
|
+
}
|
|
46
|
+
}, rest));
|
|
34
47
|
}
|
|
35
48
|
//#endregion
|
|
36
49
|
export { ToggleGroup$1 as ToggleGroup, ToggleGroupItem };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle-group.js","names":["ToggleGroup","KobalteToggleGroup","ComponentProps","splitProps","VariantProps","cn","toggleVariants","ToggleGroupProps","Omit","multiple","variant","size","attached","props","local","rest","_$createComponent","_$mergeProps","class","ToggleGroupItemProps","Item","ToggleGroupItem","ToggleGroup","_$createComponent","KobalteToggleGroup","_$mergeProps"],"sources":["../../../../src/components/ui/toggle-group/toggle-group.tsx"],"sourcesContent":["import { ToggleGroup as KobalteToggleGroup } from '@kobalte/core/toggle-group'\nimport type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport type { VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\nimport { toggleVariants } from '../toggle/toggle'\n\n/**\n * ToggleGroup.\n *\n * A set of related toggles that behave as one control: at most one pressed\n * (`multiple={false}`, the default) or any number (`multiple={true}`). The\n * group owns the selection and the roving focus, which is what makes arrow keys\n * move between items and a screen reader announce the position within the set.\n * A row of independent Toggles looks identical and does neither.\n *\n * `attached` joins the items into one rounded run for a segmented control. The\n * joining lives on the *group*, via child selectors, so an item never has to\n * know whether it sits at an end — which is also where the border collapse\n * (`-ms-px`) belongs.\n */\n/**\n * `multiple` is optional here although Kobalte requires it: the primitive models\n * single and multiple selection as two shapes, which forces every caller to state\n * the obvious. Defaulting to single selection keeps the common case a one-word\n * component, and a caller that wants many passes `multiple`.\n */\nexport type ToggleGroupProps = Omit<ComponentProps<typeof KobalteToggleGroup>, 'multiple'> & {\n multiple?: boolean\n variant?: VariantProps<typeof toggleVariants>['variant']\n size?: VariantProps<typeof toggleVariants>['size']\n /** Join the items into one rounded run instead of a spaced row. */\n attached?: boolean\n}\n\nexport function ToggleGroup(props: ToggleGroupProps) {\n const [local, rest] = splitProps(props, ['class', 'attached', 'multiple'])\n\n return (\n <KobalteToggleGroup\n multiple={local.multiple ?? false}\n class={cn(\n 'flex w-fit flex-row items-center',\n local.attached\n ? '[&>*:first-child]:rounded-e-none [&>*:last-child]:rounded-s-none [&>*:not(:first-child):not(:last-child)]:rounded-none [&>*:not(:first-child)]:-ms-px'\n : 'gap-1',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type ToggleGroupItemProps = ComponentProps<typeof KobalteToggleGroup.Item> &\n VariantProps<typeof toggleVariants>\n\nexport function ToggleGroupItem(props: ToggleGroupItemProps) {\n const [local, rest] = splitProps(props, ['class', 'variant', 'size'])\n\n return (\n <KobalteToggleGroup.Item\n class={cn(toggleVariants({ variant: local.variant, size: local.size }), local.class)}\n {...rest}\n />\n )\n}\n"],"mappings":";;;;;;AAmCA,SAAgBA,cAAYa,OAAyB;CACnD,MAAM,CAACC,OAAOC,QAAQZ,WAAWU,OAAO;EAAC;EAAS;EAAY;CAAU,CAAC;CAEzE,OAAAG,gBACGf,aAAkBgB,WAAA;EAAA,IACjBR,WAAQ;GAAA,OAAEK,MAAML,YAAY;EAAK;EAAA,KAAA,WAAA;GAAA,OAC1BJ,GACL,oCACAS,MAAMF,WACF,0JACA,SACJE,MAAMI,KACR;EAAC;CAAA,GACGH,IAAI,CAAA;AAGd;AAKA,SAAgBM,
|
|
1
|
+
{"version":3,"file":"toggle-group.js","names":["ToggleGroup","KobalteToggleGroup","ComponentProps","splitProps","VariantProps","cn","toggleVariants","ToggleGroupProps","Omit","multiple","variant","size","attached","props","local","rest","_$createComponent","_$mergeProps","class","ToggleGroupItemProps","Item","invokeEventHandler","handler","event","Event","Array","isArray","callback","data","ToggleGroupItem","onKeyDown","key","stopPropagation","ToggleGroup","_$createComponent","KobalteToggleGroup","_$mergeProps"],"sources":["../../../../src/components/ui/toggle-group/toggle-group.tsx"],"sourcesContent":["import { ToggleGroup as KobalteToggleGroup } from '@kobalte/core/toggle-group'\nimport type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport type { VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\nimport { toggleVariants } from '../toggle/toggle'\n\n/**\n * ToggleGroup.\n *\n * A set of related toggles that behave as one control: at most one pressed\n * (`multiple={false}`, the default) or any number (`multiple={true}`). The\n * group owns the selection and the roving focus, which is what makes arrow keys\n * move between items and a screen reader announce the position within the set.\n * A row of independent Toggles looks identical and does neither.\n *\n * `attached` joins the items into one rounded run for a segmented control. The\n * joining lives on the *group*, via child selectors, so an item never has to\n * know whether it sits at an end — which is also where the border collapse\n * (`-ms-px`) belongs.\n */\n/**\n * `multiple` is optional here although Kobalte requires it: the primitive models\n * single and multiple selection as two shapes, which forces every caller to state\n * the obvious. Defaulting to single selection keeps the common case a one-word\n * component, and a caller that wants many passes `multiple`.\n */\nexport type ToggleGroupProps = Omit<ComponentProps<typeof KobalteToggleGroup>, 'multiple'> & {\n multiple?: boolean\n variant?: VariantProps<typeof toggleVariants>['variant']\n size?: VariantProps<typeof toggleVariants>['size']\n /** Join the items into one rounded run instead of a spaced row. */\n attached?: boolean\n}\n\nexport function ToggleGroup(props: ToggleGroupProps) {\n const [local, rest] = splitProps(props, ['class', 'attached', 'multiple'])\n\n return (\n <KobalteToggleGroup\n multiple={local.multiple ?? false}\n class={cn(\n 'flex w-fit flex-row items-center',\n local.attached\n ? '[&>*:first-child]:rounded-e-none [&>*:last-child]:rounded-s-none [&>*:not(:first-child):not(:last-child)]:rounded-none [&>*:not(:first-child)]:-ms-px'\n : 'gap-1',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type ToggleGroupItemProps = ComponentProps<typeof KobalteToggleGroup.Item> &\n VariantProps<typeof toggleVariants>\n\nfunction invokeEventHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n ;(handler as (event: Event) => void)(event)\n }\n}\n\nexport function ToggleGroupItem(props: ToggleGroupItemProps) {\n const [local, rest] = splitProps(props, ['class', 'variant', 'size', 'onKeyDown'])\n\n return (\n <KobalteToggleGroup.Item\n class={cn(toggleVariants({ variant: local.variant, size: local.size }), local.class)}\n onKeyDown={(event) => {\n invokeEventHandler(local.onKeyDown, event)\n // The group root's selection collection clears the selection and marks\n // Escape handled, which starves an enclosing dialog or drawer of the\n // Escape it needs to dismiss. Stopping at the focused item is the only\n // point before that handler, so pass Escape through from here.\n if (event.key === 'Escape') event.stopPropagation()\n }}\n {...rest}\n />\n )\n}\n"],"mappings":";;;;;;AAmCA,SAAgBA,cAAYa,OAAyB;CACnD,MAAM,CAACC,OAAOC,QAAQZ,WAAWU,OAAO;EAAC;EAAS;EAAY;CAAU,CAAC;CAEzE,OAAAG,gBACGf,aAAkBgB,WAAA;EAAA,IACjBR,WAAQ;GAAA,OAAEK,MAAML,YAAY;EAAK;EAAA,KAAA,WAAA;GAAA,OAC1BJ,GACL,oCACAS,MAAMF,WACF,0JACA,SACJE,MAAMI,KACR;EAAC;CAAA,GACGH,IAAI,CAAA;AAGd;AAKA,SAASM,mBAAmBC,SAAkBC,OAAc;CAC1D,IAAIE,MAAMC,QAAQJ,OAAO,GAAG;EAC1B,MAAM,CAACK,UAAUC,QAAQN;EACzBK,SAASC,MAAML,KAAK;CACtB,OAAO,IAAI,OAAOD,YAAY,YAC3B,QAAoCC,KAAK;AAE9C;AAEA,SAAgBM,gBAAgBhB,OAA6B;CAC3D,MAAM,CAACC,OAAOC,QAAQZ,WAAWU,OAAO;EAAC;EAAS;EAAW;EAAQ;CAAW,CAAC;CAEjF,OAAAG,gBACGf,YAAmBmB,MAAIH,WAAA;EAAA,KAAA,WAAA;GAAA,OACfZ,GAAGC,eAAe;IAAEI,SAASI,MAAMJ;IAASC,MAAMG,MAAMH;GAAK,CAAC,GAAGG,MAAMI,KAAK;EAAC;EACpFY,YAAYP,UAAU;GACpBF,mBAAmBP,MAAMgB,WAAWP,KAAK;GAKzC,IAAIA,MAAMQ,QAAQ,UAAUR,MAAMS,gBAAgB;EACpD;CAAC,GACGjB,IAAI,CAAA;AAGd"}
|
|
@@ -196,7 +196,7 @@ export function SidebarNavSection(props: SidebarNavSectionProps) {
|
|
|
196
196
|
data-active={local.active ? '' : undefined}
|
|
197
197
|
class={cn(
|
|
198
198
|
'group/section-header flex items-center gap-1 rounded-md px-2 py-1.5',
|
|
199
|
-
{ '[@media(pointer:coarse)]:py-0': local.collapsible },
|
|
199
|
+
{ '[@media(any-pointer:coarse)]:py-0': local.collapsible },
|
|
200
200
|
local.active ? 'bg-primary-subtle text-foreground' : 'hover:bg-sidebar-accent/60'
|
|
201
201
|
)}
|
|
202
202
|
>
|
|
@@ -228,7 +228,7 @@ export function SidebarNavSection(props: SidebarNavSectionProps) {
|
|
|
228
228
|
trigger.onReorder?.(event.key === 'ArrowUp' ? 'up' : 'down')
|
|
229
229
|
}}
|
|
230
230
|
class={cn(
|
|
231
|
-
'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(pointer:coarse)]:min-h-11',
|
|
231
|
+
'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11',
|
|
232
232
|
local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'
|
|
233
233
|
)}
|
|
234
234
|
>
|
|
@@ -237,7 +237,7 @@ export function SidebarNavSection(props: SidebarNavSectionProps) {
|
|
|
237
237
|
</Show>
|
|
238
238
|
</Polymorphic>
|
|
239
239
|
<Show when={local.action}>
|
|
240
|
-
<span class="shrink-0 opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(
|
|
240
|
+
<span class="shrink-0 opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(any-pointer:coarse)]:opacity-100">
|
|
241
241
|
{local.action}
|
|
242
242
|
</span>
|
|
243
243
|
</Show>
|
|
@@ -275,7 +275,7 @@ export function SidebarNavRow(props: SidebarNavRowProps) {
|
|
|
275
275
|
<Show when={local.actions}>
|
|
276
276
|
<span
|
|
277
277
|
data-slot="sidebar-nav-row-actions"
|
|
278
|
-
class="ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(
|
|
278
|
+
class="ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(any-pointer:coarse)]:opacity-100"
|
|
279
279
|
>
|
|
280
280
|
{local.actions}
|
|
281
281
|
</span>
|
|
@@ -310,11 +310,11 @@ export type SidebarNavItemProps<T extends ValidComponent = 'a'> = PolymorphicPro
|
|
|
310
310
|
|
|
311
311
|
/**
|
|
312
312
|
* A sidebar row. Exported classes, so a caller's own element can match it.
|
|
313
|
-
*
|
|
313
|
+
* Any coarse pointer gets a 44px target without changing desktop density.
|
|
314
314
|
*/
|
|
315
315
|
export const sidebarNavItemClass = [
|
|
316
316
|
'group/nav-item relative flex min-w-0 items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium',
|
|
317
|
-
'whitespace-nowrap transition-colors ease-out outline-none select-none [@media(pointer:coarse)]:min-h-11',
|
|
317
|
+
'whitespace-nowrap transition-colors ease-out outline-none select-none [@media(any-pointer:coarse)]:min-h-11',
|
|
318
318
|
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
319
319
|
'[&_svg]:size-4 [&_svg]:shrink-0',
|
|
320
320
|
].join(' ')
|
|
@@ -147,11 +147,16 @@ export function createDialogFocusRestoration({
|
|
|
147
147
|
if (
|
|
148
148
|
!(target instanceof HTMLElement) ||
|
|
149
149
|
target === document.body ||
|
|
150
|
-
target === document.documentElement
|
|
150
|
+
target === document.documentElement
|
|
151
|
+
) {
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
if (
|
|
151
155
|
target === element ||
|
|
152
156
|
element.contains(target) ||
|
|
153
157
|
target === (opener instanceof HTMLElement ? opener : null)
|
|
154
158
|
) {
|
|
159
|
+
if (!cycle.closed) cycle.focusMovedOutside = false
|
|
155
160
|
return
|
|
156
161
|
}
|
|
157
162
|
cycle.focusMovedOutside = true
|
|
@@ -33,6 +33,12 @@ import {
|
|
|
33
33
|
* handler takes control or focus has moved to another layer. For controlled
|
|
34
34
|
* dialogs without a composed trigger, pass `restoreFocusRef` when the opener
|
|
35
35
|
* cannot be inferred from the focused element.
|
|
36
|
+
* 5. **It keeps its own portal out of an enclosing layer's `aria-hidden`
|
|
37
|
+
* bookkeeping.** A non-modal dialog opened while a modal `Sheet` is alive would
|
|
38
|
+
* otherwise be aria-hidden one frame after it mounts — the enclosing layer's
|
|
39
|
+
* hide-outside observer walks late-arriving body children as background. The
|
|
40
|
+
* portal carries the marker that observer exempts; a modal layer opened above
|
|
41
|
+
* still hides it, because that path matches a different attribute.
|
|
36
42
|
*
|
|
37
43
|
* Use `Dialog` directly when you need its composition; use this when you want a
|
|
38
44
|
* dialog that is correct by default. `size="settings"` supplies a wide, bounded
|
|
@@ -111,6 +117,20 @@ export function ModalDialog(props: ModalDialogProps) {
|
|
|
111
117
|
if (!wasInert[index]) node.removeAttribute('inert')
|
|
112
118
|
})
|
|
113
119
|
})
|
|
120
|
+
|
|
121
|
+
// Kobalte's hide-outside observer walks body children added after its layer
|
|
122
|
+
// opened and aria-hides them one frame later, so a non-modal dialog portaled
|
|
123
|
+
// in during that window would land outside the accessibility tree — role
|
|
124
|
+
// queries never resolve it again while the enclosing layer stays open. The
|
|
125
|
+
// observer exempts added nodes carrying its top-layer marker (it checks the
|
|
126
|
+
// React Aria spelling it ported; `data-kb-top-layer` is only matched by a
|
|
127
|
+
// newer layer's initial walk, which must still hide this dialog).
|
|
128
|
+
let portal = element
|
|
129
|
+
while (portal.parentElement !== null && portal.parentElement !== document.body) {
|
|
130
|
+
portal = portal.parentElement
|
|
131
|
+
}
|
|
132
|
+
portal.setAttribute('data-react-aria-top-layer', 'true')
|
|
133
|
+
onCleanup(() => portal.removeAttribute('data-react-aria-top-layer'))
|
|
114
134
|
})
|
|
115
135
|
|
|
116
136
|
return (
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Dialog as KobalteDialog,
|
|
3
|
+
Content as KobalteDialogContent,
|
|
4
|
+
useDialogContext,
|
|
5
|
+
} from '@kobalte/core/dialog'
|
|
2
6
|
// AlertDialog shares DialogRoot.Content; Sheet uses the stable named primitive.
|
|
3
7
|
import { X } from 'lucide-solid'
|
|
4
|
-
import type { ComponentProps, JSX } from 'solid-js'
|
|
8
|
+
import type { Accessor, ComponentProps, JSX } from 'solid-js'
|
|
5
9
|
import { Show, splitProps } from 'solid-js'
|
|
6
10
|
import { cva, type VariantProps } from '../../../lib/variants'
|
|
7
11
|
import { cn } from '../../../lib/utils'
|
|
8
|
-
import { DialogOverlay } from '../dialog/dialog'
|
|
12
|
+
import { createDialogFocusRestoration, DialogOverlay } from '../dialog/dialog'
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* Sheet.
|
|
@@ -18,6 +22,11 @@ import { DialogOverlay } from '../dialog/dialog'
|
|
|
18
22
|
* `side` decides which edge; the panel is a full-height column for `start` and
|
|
19
23
|
* `end`, and a full-width row for `top` and `bottom`. The slide-in direction
|
|
20
24
|
* follows from the side, so a caller never pairs them by hand.
|
|
25
|
+
*
|
|
26
|
+
* Controlled sheets opened from outside a `SheetTrigger` restore focus to the
|
|
27
|
+
* element focused before opening. Pass `restoreFocusRef` when a stable external
|
|
28
|
+
* opener must be used instead, such as when another layer closes before the
|
|
29
|
+
* sheet opens.
|
|
21
30
|
*/
|
|
22
31
|
const sheetVariants = cva(
|
|
23
32
|
'bg-popover text-popover-foreground fixed z-(--z-dialog) flex flex-col gap-4 border-border shadow-lg',
|
|
@@ -39,10 +48,27 @@ const sheetVariants = cva(
|
|
|
39
48
|
export type SheetContentProps = ComponentProps<typeof KobalteDialogContent> &
|
|
40
49
|
VariantProps<typeof sheetVariants> & {
|
|
41
50
|
closeButton?: JSX.Element | false
|
|
51
|
+
/** Supplies the stable external element to focus when the controlled sheet closes. */
|
|
52
|
+
restoreFocusRef?: Accessor<HTMLElement | undefined>
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
export function SheetContent(props: SheetContentProps) {
|
|
45
|
-
const [local, rest] = splitProps(props, [
|
|
56
|
+
const [local, rest] = splitProps(props, [
|
|
57
|
+
'class',
|
|
58
|
+
'side',
|
|
59
|
+
'children',
|
|
60
|
+
'closeButton',
|
|
61
|
+
'restoreFocusRef',
|
|
62
|
+
'onOpenAutoFocus',
|
|
63
|
+
'onCloseAutoFocus',
|
|
64
|
+
])
|
|
65
|
+
const dialog = useDialogContext()
|
|
66
|
+
const focusRestoration = createDialogFocusRestoration({
|
|
67
|
+
open: dialog.isOpen,
|
|
68
|
+
restoreFocusRef: local.restoreFocusRef,
|
|
69
|
+
onOpenAutoFocus: local.onOpenAutoFocus,
|
|
70
|
+
onCloseAutoFocus: local.onCloseAutoFocus,
|
|
71
|
+
})
|
|
46
72
|
|
|
47
73
|
return (
|
|
48
74
|
<KobalteDialog.Portal>
|
|
@@ -55,11 +81,18 @@ export function SheetContent(props: SheetContentProps) {
|
|
|
55
81
|
local.class
|
|
56
82
|
)}
|
|
57
83
|
{...rest}
|
|
84
|
+
onOpenAutoFocus={focusRestoration.onOpenAutoFocus}
|
|
85
|
+
onCloseAutoFocus={focusRestoration.onCloseAutoFocus}
|
|
58
86
|
>
|
|
59
87
|
{local.children}
|
|
60
88
|
<Show when={local.closeButton !== false}>
|
|
89
|
+
{/* The close action opts into the tab order explicitly. Engines that
|
|
90
|
+
derive tabbability from the DOM instead of the host (Playwright's
|
|
91
|
+
WebKit walks only explicit tabindex and form controls) would skip
|
|
92
|
+
an implicitly-tabbable button and jump past the sheet's end. */}
|
|
61
93
|
<KobalteDialog.CloseButton
|
|
62
94
|
aria-label="Close"
|
|
95
|
+
tabindex="0"
|
|
63
96
|
class="absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground transition-colors ease-out outline-none hover:bg-surface-hover hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle"
|
|
64
97
|
>
|
|
65
98
|
{local.closeButton ?? <X class="size-4" />}
|
|
@@ -54,12 +54,29 @@ export function ToggleGroup(props: ToggleGroupProps) {
|
|
|
54
54
|
export type ToggleGroupItemProps = ComponentProps<typeof KobalteToggleGroup.Item> &
|
|
55
55
|
VariantProps<typeof toggleVariants>
|
|
56
56
|
|
|
57
|
+
function invokeEventHandler(handler: unknown, event: Event) {
|
|
58
|
+
if (Array.isArray(handler)) {
|
|
59
|
+
const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]
|
|
60
|
+
callback(data, event)
|
|
61
|
+
} else if (typeof handler === 'function') {
|
|
62
|
+
;(handler as (event: Event) => void)(event)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
57
66
|
export function ToggleGroupItem(props: ToggleGroupItemProps) {
|
|
58
|
-
const [local, rest] = splitProps(props, ['class', 'variant', 'size'])
|
|
67
|
+
const [local, rest] = splitProps(props, ['class', 'variant', 'size', 'onKeyDown'])
|
|
59
68
|
|
|
60
69
|
return (
|
|
61
70
|
<KobalteToggleGroup.Item
|
|
62
71
|
class={cn(toggleVariants({ variant: local.variant, size: local.size }), local.class)}
|
|
72
|
+
onKeyDown={(event) => {
|
|
73
|
+
invokeEventHandler(local.onKeyDown, event)
|
|
74
|
+
// The group root's selection collection clears the selection and marks
|
|
75
|
+
// Escape handled, which starves an enclosing dialog or drawer of the
|
|
76
|
+
// Escape it needs to dismiss. Stopping at the focused item is the only
|
|
77
|
+
// point before that handler, so pass Escape through from here.
|
|
78
|
+
if (event.key === 'Escape') event.stopPropagation()
|
|
79
|
+
}}
|
|
63
80
|
{...rest}
|
|
64
81
|
/>
|
|
65
82
|
)
|
package/package.json
CHANGED
|
@@ -196,7 +196,7 @@ export function SidebarNavSection(props: SidebarNavSectionProps) {
|
|
|
196
196
|
data-active={local.active ? '' : undefined}
|
|
197
197
|
class={cn(
|
|
198
198
|
'group/section-header flex items-center gap-1 rounded-md px-2 py-1.5',
|
|
199
|
-
{ '[@media(pointer:coarse)]:py-0': local.collapsible },
|
|
199
|
+
{ '[@media(any-pointer:coarse)]:py-0': local.collapsible },
|
|
200
200
|
local.active ? 'bg-primary-subtle text-foreground' : 'hover:bg-sidebar-accent/60'
|
|
201
201
|
)}
|
|
202
202
|
>
|
|
@@ -228,7 +228,7 @@ export function SidebarNavSection(props: SidebarNavSectionProps) {
|
|
|
228
228
|
trigger.onReorder?.(event.key === 'ArrowUp' ? 'up' : 'down')
|
|
229
229
|
}}
|
|
230
230
|
class={cn(
|
|
231
|
-
'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(pointer:coarse)]:min-h-11',
|
|
231
|
+
'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11',
|
|
232
232
|
local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'
|
|
233
233
|
)}
|
|
234
234
|
>
|
|
@@ -237,7 +237,7 @@ export function SidebarNavSection(props: SidebarNavSectionProps) {
|
|
|
237
237
|
</Show>
|
|
238
238
|
</Polymorphic>
|
|
239
239
|
<Show when={local.action}>
|
|
240
|
-
<span class="shrink-0 opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(
|
|
240
|
+
<span class="shrink-0 opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(any-pointer:coarse)]:opacity-100">
|
|
241
241
|
{local.action}
|
|
242
242
|
</span>
|
|
243
243
|
</Show>
|
|
@@ -275,7 +275,7 @@ export function SidebarNavRow(props: SidebarNavRowProps) {
|
|
|
275
275
|
<Show when={local.actions}>
|
|
276
276
|
<span
|
|
277
277
|
data-slot="sidebar-nav-row-actions"
|
|
278
|
-
class="ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(
|
|
278
|
+
class="ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(any-pointer:coarse)]:opacity-100"
|
|
279
279
|
>
|
|
280
280
|
{local.actions}
|
|
281
281
|
</span>
|
|
@@ -310,11 +310,11 @@ export type SidebarNavItemProps<T extends ValidComponent = 'a'> = PolymorphicPro
|
|
|
310
310
|
|
|
311
311
|
/**
|
|
312
312
|
* A sidebar row. Exported classes, so a caller's own element can match it.
|
|
313
|
-
*
|
|
313
|
+
* Any coarse pointer gets a 44px target without changing desktop density.
|
|
314
314
|
*/
|
|
315
315
|
export const sidebarNavItemClass = [
|
|
316
316
|
'group/nav-item relative flex min-w-0 items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium',
|
|
317
|
-
'whitespace-nowrap transition-colors ease-out outline-none select-none [@media(pointer:coarse)]:min-h-11',
|
|
317
|
+
'whitespace-nowrap transition-colors ease-out outline-none select-none [@media(any-pointer:coarse)]:min-h-11',
|
|
318
318
|
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
319
319
|
'[&_svg]:size-4 [&_svg]:shrink-0',
|
|
320
320
|
].join(' ')
|
|
@@ -147,11 +147,16 @@ export function createDialogFocusRestoration({
|
|
|
147
147
|
if (
|
|
148
148
|
!(target instanceof HTMLElement) ||
|
|
149
149
|
target === document.body ||
|
|
150
|
-
target === document.documentElement
|
|
150
|
+
target === document.documentElement
|
|
151
|
+
) {
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
if (
|
|
151
155
|
target === element ||
|
|
152
156
|
element.contains(target) ||
|
|
153
157
|
target === (opener instanceof HTMLElement ? opener : null)
|
|
154
158
|
) {
|
|
159
|
+
if (!cycle.closed) cycle.focusMovedOutside = false
|
|
155
160
|
return
|
|
156
161
|
}
|
|
157
162
|
cycle.focusMovedOutside = true
|
|
@@ -33,6 +33,12 @@ import {
|
|
|
33
33
|
* handler takes control or focus has moved to another layer. For controlled
|
|
34
34
|
* dialogs without a composed trigger, pass `restoreFocusRef` when the opener
|
|
35
35
|
* cannot be inferred from the focused element.
|
|
36
|
+
* 5. **It keeps its own portal out of an enclosing layer's `aria-hidden`
|
|
37
|
+
* bookkeeping.** A non-modal dialog opened while a modal `Sheet` is alive would
|
|
38
|
+
* otherwise be aria-hidden one frame after it mounts — the enclosing layer's
|
|
39
|
+
* hide-outside observer walks late-arriving body children as background. The
|
|
40
|
+
* portal carries the marker that observer exempts; a modal layer opened above
|
|
41
|
+
* still hides it, because that path matches a different attribute.
|
|
36
42
|
*
|
|
37
43
|
* Use `Dialog` directly when you need its composition; use this when you want a
|
|
38
44
|
* dialog that is correct by default. `size="settings"` supplies a wide, bounded
|
|
@@ -111,6 +117,20 @@ export function ModalDialog(props: ModalDialogProps) {
|
|
|
111
117
|
if (!wasInert[index]) node.removeAttribute('inert')
|
|
112
118
|
})
|
|
113
119
|
})
|
|
120
|
+
|
|
121
|
+
// Kobalte's hide-outside observer walks body children added after its layer
|
|
122
|
+
// opened and aria-hides them one frame later, so a non-modal dialog portaled
|
|
123
|
+
// in during that window would land outside the accessibility tree — role
|
|
124
|
+
// queries never resolve it again while the enclosing layer stays open. The
|
|
125
|
+
// observer exempts added nodes carrying its top-layer marker (it checks the
|
|
126
|
+
// React Aria spelling it ported; `data-kb-top-layer` is only matched by a
|
|
127
|
+
// newer layer's initial walk, which must still hide this dialog).
|
|
128
|
+
let portal = element
|
|
129
|
+
while (portal.parentElement !== null && portal.parentElement !== document.body) {
|
|
130
|
+
portal = portal.parentElement
|
|
131
|
+
}
|
|
132
|
+
portal.setAttribute('data-react-aria-top-layer', 'true')
|
|
133
|
+
onCleanup(() => portal.removeAttribute('data-react-aria-top-layer'))
|
|
114
134
|
})
|
|
115
135
|
|
|
116
136
|
return (
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Dialog as KobalteDialog,
|
|
3
|
+
Content as KobalteDialogContent,
|
|
4
|
+
useDialogContext,
|
|
5
|
+
} from '@kobalte/core/dialog'
|
|
2
6
|
// AlertDialog shares DialogRoot.Content; Sheet uses the stable named primitive.
|
|
3
7
|
import { X } from 'lucide-solid'
|
|
4
|
-
import type { ComponentProps, JSX } from 'solid-js'
|
|
8
|
+
import type { Accessor, ComponentProps, JSX } from 'solid-js'
|
|
5
9
|
import { Show, splitProps } from 'solid-js'
|
|
6
10
|
import { cva, type VariantProps } from '#lib/variants'
|
|
7
11
|
import { cn } from '#lib/utils'
|
|
8
|
-
import { DialogOverlay } from '../dialog/dialog'
|
|
12
|
+
import { createDialogFocusRestoration, DialogOverlay } from '../dialog/dialog'
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* Sheet.
|
|
@@ -18,6 +22,11 @@ import { DialogOverlay } from '../dialog/dialog'
|
|
|
18
22
|
* `side` decides which edge; the panel is a full-height column for `start` and
|
|
19
23
|
* `end`, and a full-width row for `top` and `bottom`. The slide-in direction
|
|
20
24
|
* follows from the side, so a caller never pairs them by hand.
|
|
25
|
+
*
|
|
26
|
+
* Controlled sheets opened from outside a `SheetTrigger` restore focus to the
|
|
27
|
+
* element focused before opening. Pass `restoreFocusRef` when a stable external
|
|
28
|
+
* opener must be used instead, such as when another layer closes before the
|
|
29
|
+
* sheet opens.
|
|
21
30
|
*/
|
|
22
31
|
const sheetVariants = cva(
|
|
23
32
|
'bg-popover text-popover-foreground fixed z-(--z-dialog) flex flex-col gap-4 border-border shadow-lg',
|
|
@@ -39,10 +48,27 @@ const sheetVariants = cva(
|
|
|
39
48
|
export type SheetContentProps = ComponentProps<typeof KobalteDialogContent> &
|
|
40
49
|
VariantProps<typeof sheetVariants> & {
|
|
41
50
|
closeButton?: JSX.Element | false
|
|
51
|
+
/** Supplies the stable external element to focus when the controlled sheet closes. */
|
|
52
|
+
restoreFocusRef?: Accessor<HTMLElement | undefined>
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
export function SheetContent(props: SheetContentProps) {
|
|
45
|
-
const [local, rest] = splitProps(props, [
|
|
56
|
+
const [local, rest] = splitProps(props, [
|
|
57
|
+
'class',
|
|
58
|
+
'side',
|
|
59
|
+
'children',
|
|
60
|
+
'closeButton',
|
|
61
|
+
'restoreFocusRef',
|
|
62
|
+
'onOpenAutoFocus',
|
|
63
|
+
'onCloseAutoFocus',
|
|
64
|
+
])
|
|
65
|
+
const dialog = useDialogContext()
|
|
66
|
+
const focusRestoration = createDialogFocusRestoration({
|
|
67
|
+
open: dialog.isOpen,
|
|
68
|
+
restoreFocusRef: local.restoreFocusRef,
|
|
69
|
+
onOpenAutoFocus: local.onOpenAutoFocus,
|
|
70
|
+
onCloseAutoFocus: local.onCloseAutoFocus,
|
|
71
|
+
})
|
|
46
72
|
|
|
47
73
|
return (
|
|
48
74
|
<KobalteDialog.Portal>
|
|
@@ -55,11 +81,18 @@ export function SheetContent(props: SheetContentProps) {
|
|
|
55
81
|
local.class
|
|
56
82
|
)}
|
|
57
83
|
{...rest}
|
|
84
|
+
onOpenAutoFocus={focusRestoration.onOpenAutoFocus}
|
|
85
|
+
onCloseAutoFocus={focusRestoration.onCloseAutoFocus}
|
|
58
86
|
>
|
|
59
87
|
{local.children}
|
|
60
88
|
<Show when={local.closeButton !== false}>
|
|
89
|
+
{/* The close action opts into the tab order explicitly. Engines that
|
|
90
|
+
derive tabbability from the DOM instead of the host (Playwright's
|
|
91
|
+
WebKit walks only explicit tabindex and form controls) would skip
|
|
92
|
+
an implicitly-tabbable button and jump past the sheet's end. */}
|
|
61
93
|
<KobalteDialog.CloseButton
|
|
62
94
|
aria-label="Close"
|
|
95
|
+
tabindex="0"
|
|
63
96
|
class="absolute top-3.5 end-3.5 rounded-md p-1 text-muted-foreground transition-colors ease-out outline-none hover:bg-surface-hover hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle"
|
|
64
97
|
>
|
|
65
98
|
{local.closeButton ?? <X class="size-4" />}
|
|
@@ -54,12 +54,29 @@ export function ToggleGroup(props: ToggleGroupProps) {
|
|
|
54
54
|
export type ToggleGroupItemProps = ComponentProps<typeof KobalteToggleGroup.Item> &
|
|
55
55
|
VariantProps<typeof toggleVariants>
|
|
56
56
|
|
|
57
|
+
function invokeEventHandler(handler: unknown, event: Event) {
|
|
58
|
+
if (Array.isArray(handler)) {
|
|
59
|
+
const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]
|
|
60
|
+
callback(data, event)
|
|
61
|
+
} else if (typeof handler === 'function') {
|
|
62
|
+
;(handler as (event: Event) => void)(event)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
57
66
|
export function ToggleGroupItem(props: ToggleGroupItemProps) {
|
|
58
|
-
const [local, rest] = splitProps(props, ['class', 'variant', 'size'])
|
|
67
|
+
const [local, rest] = splitProps(props, ['class', 'variant', 'size', 'onKeyDown'])
|
|
59
68
|
|
|
60
69
|
return (
|
|
61
70
|
<KobalteToggleGroup.Item
|
|
62
71
|
class={cn(toggleVariants({ variant: local.variant, size: local.size }), local.class)}
|
|
72
|
+
onKeyDown={(event) => {
|
|
73
|
+
invokeEventHandler(local.onKeyDown, event)
|
|
74
|
+
// The group root's selection collection clears the selection and marks
|
|
75
|
+
// Escape handled, which starves an enclosing dialog or drawer of the
|
|
76
|
+
// Escape it needs to dismiss. Stopping at the focused item is the only
|
|
77
|
+
// point before that handler, so pass Escape through from here.
|
|
78
|
+
if (event.key === 'Escape') event.stopPropagation()
|
|
79
|
+
}}
|
|
63
80
|
{...rest}
|
|
64
81
|
/>
|
|
65
82
|
)
|