@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.
Files changed (29) hide show
  1. package/README.md +1 -0
  2. package/dist/components/layout/sidebar-nav/sidebar-nav.d.ts +1 -1
  3. package/dist/components/layout/sidebar-nav/sidebar-nav.js +6 -6
  4. package/dist/components/layout/sidebar-nav/sidebar-nav.js.map +1 -1
  5. package/dist/components/ui/dialog/dialog.d.ts.map +1 -1
  6. package/dist/components/ui/dialog/dialog.js +5 -1
  7. package/dist/components/ui/dialog/dialog.js.map +1 -1
  8. package/dist/components/ui/modal-dialog/modal-dialog.d.ts +6 -0
  9. package/dist/components/ui/modal-dialog/modal-dialog.d.ts.map +1 -1
  10. package/dist/components/ui/modal-dialog/modal-dialog.js +4 -0
  11. package/dist/components/ui/modal-dialog/modal-dialog.js.map +1 -1
  12. package/dist/components/ui/sheet/sheet.d.ts +8 -1
  13. package/dist/components/ui/sheet/sheet.d.ts.map +1 -1
  14. package/dist/components/ui/sheet/sheet.js +43 -19
  15. package/dist/components/ui/sheet/sheet.js.map +1 -1
  16. package/dist/components/ui/toggle-group/toggle-group.d.ts.map +1 -1
  17. package/dist/components/ui/toggle-group/toggle-group.js +20 -7
  18. package/dist/components/ui/toggle-group/toggle-group.js.map +1 -1
  19. package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +6 -6
  20. package/dist/r/src/components/ui/dialog/dialog.tsx +6 -1
  21. package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +20 -0
  22. package/dist/r/src/components/ui/sheet/sheet.tsx +37 -4
  23. package/dist/r/src/components/ui/toggle-group/toggle-group.tsx +18 -1
  24. package/package.json +1 -1
  25. package/src/components/layout/sidebar-nav/sidebar-nav.tsx +6 -6
  26. package/src/components/ui/dialog/dialog.tsx +6 -1
  27. package/src/components/ui/modal-dialog/modal-dialog.tsx +20 -0
  28. package/src/components/ui/sheet/sheet.tsx +37 -4
  29. 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
- * Coarse pointers get a 44px target without changing Kiro's desktop density.
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(hover:none)]:opacity-100">`);
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(hover:none)]:opacity-100">`);
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
- * Coarse pointers get a 44px target without changing Kiro's desktop density.
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;8BAyCJ,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"}
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 || target === element || element.contains(target) || target === (opener instanceof HTMLElement ? opener : null)) return;
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;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;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,eAsFlD"}
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,EAAE,MAAM,IAAI,aAAa,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAG/F,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAEnD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAItD;;;;;;;;;;;GAWG;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;CAClC,CAAA;AAEH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,eA2BpD;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
+ {"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, { get children() {
44
- return [memo(() => local.children), createComponent(Show, {
45
- get when() {
46
- return local.closeButton !== false;
47
- },
48
- get children() {
49
- return createComponent(Dialog.CloseButton, {
50
- "aria-label": "Close",
51
- "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",
52
- get children() {
53
- return local.closeButton ?? createComponent(X, { "class": "size-4" });
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":"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"}
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;AAErC,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,kCAS1D"}
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({ get ["class"]() {
29
- return cn(toggleVariants({
30
- variant: local.variant,
31
- size: local.size
32
- }), local.class);
33
- } }, rest));
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,gBAAgBR,OAA6B;CAC3D,MAAM,CAACC,OAAOC,QAAQZ,WAAWU,OAAO;EAAC;EAAS;EAAW;CAAM,CAAC;CAEpE,OAAAG,gBACGf,YAAmBmB,MAAIH,WAAA,EAAA,KAAA,WAAA;EAAA,OACfZ,GAAGC,eAAe;GAAEI,SAASI,MAAMJ;GAASC,MAAMG,MAAMH;EAAK,CAAC,GAAGG,MAAMI,KAAK;CAAC,EAAA,GAChFH,IAAI,CAAA;AAGd"}
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(hover:none)]:opacity-100">
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(hover:none)]:opacity-100"
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
- * Coarse pointers get a 44px target without changing Kiro's desktop density.
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 { Dialog as KobalteDialog, Content as KobalteDialogContent } from '@kobalte/core/dialog'
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, ['class', 'side', 'children', 'closeButton'])
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/ui",
3
- "version": "0.95.0",
3
+ "version": "0.95.2",
4
4
  "description": "The Adea design system: Kobalte-backed Solid components, semantic OKLCH tokens, and the app-shell layout primitives shared by Adea and Cortana.",
5
5
  "keywords": [
6
6
  "adea",
@@ -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(hover:none)]:opacity-100">
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(hover:none)]:opacity-100"
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
- * Coarse pointers get a 44px target without changing Kiro's desktop density.
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 { Dialog as KobalteDialog, Content as KobalteDialogContent } from '@kobalte/core/dialog'
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, ['class', 'side', 'children', 'closeButton'])
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
  )