@adea-ai/ui 0.121.0 → 0.122.1

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.
@@ -60,6 +60,14 @@ export type AccountMenuProps = {
60
60
  platform?: 'desktop' | 'web';
61
61
  /** Whether a session exists. Decides the sign-in/sign-out row. */
62
62
  authenticated: boolean;
63
+ /**
64
+ * Draw the pending-update indicator: an accent dot on the trigger and on the
65
+ * `updates` row — the id `createAppMenuItems` mints, the same convention the
66
+ * fallback icons follow — and extend both accessible names with "update
67
+ * available", because the dot itself carries no text. The updater remains the
68
+ * caller's: the prop only mirrors its state into the menu.
69
+ */
70
+ updateAvailable?: boolean;
63
71
  /** Local-only applications can omit the session actions altogether. */
64
72
  showSession?: boolean;
65
73
  /** Disable the session row while a sign-in or sign-out is in flight. */
@@ -1 +1 @@
1
- {"version":3,"file":"account-menu.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/account-menu/account-menu.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAGnD,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEjE,OAAO,EACL,YAAY,EAMb,MAAM,sCAAsC,CAAA;AAG7C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC5B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,KAAK,IAAI,CAAA;CACtE,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mFAAmF;IACnF,SAAS,CAAC,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,WAAW,CAAC,CAAA;IAC5D,qDAAqD;IACrD,MAAM,CAAC,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAA;IACtD,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,uCAAuC;IACvC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;IACjC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC5B,kEAAkE;IAClE,aAAa,EAAE,OAAO,CAAA;IACtB,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB,CAAA;AAWD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,eAoJlD;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,WAAW,CAAC,EAAE,eAAe,CAAA;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IAC/C,MAAM,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IAC9C,UAAU,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IAClD,SAAS,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IACjD,UAAU,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;CACnD,GAAG,eAAe,EAAE,CAoCpB"}
1
+ {"version":3,"file":"account-menu.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/account-menu/account-menu.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAGnD,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEjE,OAAO,EACL,YAAY,EAMb,MAAM,sCAAsC,CAAA;AAG7C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC5B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,KAAK,IAAI,CAAA;CACtE,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mFAAmF;IACnF,SAAS,CAAC,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,WAAW,CAAC,CAAA;IAC5D,qDAAqD;IACrD,MAAM,CAAC,EAAE,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAA;IACtD,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,uCAAuC;IACvC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;IACjC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;IAC5B,kEAAkE;IAClE,aAAa,EAAE,OAAO,CAAA;IACtB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB,CAAA;AAWD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,eAoLlD;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,WAAW,CAAC,EAAE,eAAe,CAAA;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IAC/C,MAAM,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IAC9C,UAAU,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IAClD,SAAS,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;IACjD,UAAU,CAAC,EAAE,eAAe,CAAC,oBAAoB,CAAC,CAAA;CACnD,GAAG,eAAe,EAAE,CAoCpB"}
@@ -7,7 +7,9 @@ import { createComponent, insert, memo, mergeProps, template } from "solid-js/we
7
7
  import { CircleHelp, Info, LogIn, LogOut, Megaphone, RefreshCw, Settings2, Smartphone, UserRound } from "lucide-solid";
8
8
  import { For, Show, createSignal, onCleanup, splitProps } from "solid-js";
9
9
  //#region src/components/composites/account-menu/account-menu.tsx
10
- var _tmpl$ = /*#__PURE__*/ template(`<span>`);
10
+ var _tmpl$ = /*#__PURE__*/ template(`<span data-slot=account-menu-update-dot aria-hidden=true class="absolute top-1.5 right-2.5 size-2 rounded-full bg-primary">`);
11
+ var _tmpl$2 = /*#__PURE__*/ template(`<span>`);
12
+ var _tmpl$3 = /*#__PURE__*/ template(`<span data-slot=account-menu-update-dot aria-hidden=true class="ms-auto size-2 shrink-0 rounded-full bg-primary">`);
11
13
  var FALLBACK_ICONS = {
12
14
  mobile: Smartphone,
13
15
  settings: Settings2,
@@ -27,6 +29,7 @@ function AccountMenu(props) {
27
29
  "items",
28
30
  "platform",
29
31
  "authenticated",
32
+ "updateAvailable",
30
33
  "showSession",
31
34
  "busy",
32
35
  "label",
@@ -44,6 +47,15 @@ function AccountMenu(props) {
44
47
  scheduledAfterClose = void 0;
45
48
  });
46
49
  const visible = () => local.items.filter((item) => !item.platform || item.platform === (local.platform ?? "desktop"));
50
+ const triggerName = () => `${local.label ?? "Account and settings"}${local.updateAvailable ? ", update available" : ""}`;
51
+ const updateDot = () => createComponent(Show, {
52
+ get when() {
53
+ return local.updateAvailable;
54
+ },
55
+ get children() {
56
+ return _tmpl$();
57
+ }
58
+ });
47
59
  const menu = () => createComponent(DropdownMenu, {
48
60
  modal: false,
49
61
  get placement() {
@@ -70,15 +82,16 @@ function AccountMenu(props) {
70
82
  return local.size ?? "icon-md";
71
83
  },
72
84
  get ["class"]() {
73
- return cn("text-muted-foreground", local.class);
85
+ return cn("relative text-muted-foreground", local.class);
74
86
  },
87
+ "data-slot": "account-menu-trigger",
75
88
  get ["aria-label"]() {
76
- return local.label ?? "Account and settings";
89
+ return triggerName();
77
90
  },
78
91
  onFocus: () => local.onIntent?.(),
79
92
  onPointerEnter: () => local.onIntent?.()
80
93
  }, rest, { get children() {
81
- return createComponent(UserRound, { "aria-hidden": "true" });
94
+ return [createComponent(UserRound, { "aria-hidden": "true" }), memo(() => updateDot())];
82
95
  } }));
83
96
  },
84
97
  get children() {
@@ -86,15 +99,16 @@ function AccountMenu(props) {
86
99
  as: SideRailButton,
87
100
  ref: (element) => trigger = element,
88
101
  get label() {
89
- return local.label ?? "Account and settings";
102
+ return triggerName();
90
103
  },
91
104
  get ["class"]() {
92
- return local.class;
105
+ return cn("relative", local.class);
93
106
  },
107
+ "data-slot": "account-menu-trigger",
94
108
  onFocus: () => local.onIntent?.(),
95
109
  onPointerEnter: () => local.onIntent?.()
96
110
  }, rest, { get children() {
97
- return createComponent(UserRound, { "aria-hidden": "true" });
111
+ return [createComponent(UserRound, { "aria-hidden": "true" }), memo(() => updateDot())];
98
112
  } }));
99
113
  }
100
114
  }), createComponent(DropdownMenuContent, {
@@ -124,6 +138,9 @@ function AccountMenu(props) {
124
138
  get disabled() {
125
139
  return item.disabled;
126
140
  },
141
+ get ["aria-label"]() {
142
+ return memo(() => !!(local.updateAvailable && item.id === "updates"))() ? `${item.label}, update available` : void 0;
143
+ },
127
144
  onSelect: () => {
128
145
  pendingAfterClose = item.onSelectAfterClose ? { callback: item.onSelectAfterClose } : void 0;
129
146
  item.onSelect?.();
@@ -135,11 +152,22 @@ function AccountMenu(props) {
135
152
  return item.keyshortcuts;
136
153
  },
137
154
  get children() {
138
- return [memo(() => item.icon ?? renderFallbackIcon(item.id)), (() => {
139
- var _el$2 = _tmpl$();
140
- insert(_el$2, () => item.label);
141
- return _el$2;
142
- })()];
155
+ return [
156
+ memo(() => item.icon ?? renderFallbackIcon(item.id)),
157
+ (() => {
158
+ var _el$3 = _tmpl$2();
159
+ insert(_el$3, () => item.label);
160
+ return _el$3;
161
+ })(),
162
+ createComponent(Show, {
163
+ get when() {
164
+ return memo(() => !!local.updateAvailable)() && item.id === "updates";
165
+ },
166
+ get children() {
167
+ return _tmpl$3();
168
+ }
169
+ })
170
+ ];
143
171
  }
144
172
  })
145
173
  });
@@ -166,9 +194,9 @@ function AccountMenu(props) {
166
194
  return createComponent(LogOut, { "aria-hidden": "true" });
167
195
  }
168
196
  }), (() => {
169
- var _el$ = _tmpl$();
170
- insert(_el$, () => local.authenticated ? "Sign out" : "Sign in");
171
- return _el$;
197
+ var _el$2 = _tmpl$2();
198
+ insert(_el$2, () => local.authenticated ? "Sign out" : "Sign in");
199
+ return _el$2;
172
200
  })()];
173
201
  }
174
202
  });
@@ -1 +1 @@
1
- {"version":3,"file":"account-menu.js","names":["CircleHelp","Info","LogIn","LogOut","Megaphone","RefreshCw","Settings2","Smartphone","UserRound","ComponentProps","JSX","For","Show","createSignal","onCleanup","splitProps","cn","Button","ButtonProps","SideRailButton","DropdownMenu","DropdownMenuContent","DropdownMenuGroup","DropdownMenuItem","DropdownMenuSeparator","DropdownMenuTrigger","Tooltip","TooltipContent","TooltipTrigger","AccountMenuItem","id","label","icon","Element","shortcut","keyshortcuts","disabled","platform","onSelect","onSelectAfterClose","trigger","HTMLButtonElement","AccountMenuProps","class","placement","gutter","hideArrow","size","railTrigger","items","authenticated","showSession","busy","onSignIn","onSignOut","onIntent","FALLBACK_ICONS","Record","mobile","settings","about","help","feedback","updates","AccountMenu","props","local","rest","pendingAfterClose","callback","NonNullable","scheduledAfterClose","menuOpen","setMenuOpen","tooltipOpen","setTooltipOpen","undefined","visible","filter","item","menu","_$createComponent","modal","onOpenChange","open","children","when","fallback","_$mergeProps","as","AccountMenuButton","ref","element","variant","aria-label","onFocus","onPointerEnter","onCloseAutoFocus","event","selection","preventDefault","queueMicrotask","each","_$memo","renderFallbackIcon","_el$2","_tmpl$","_$insert","_el$","createAppMenuItems","options","primaryItem","settingsShortcut","onAbout","onHelp","onFeedback","onUpdates","onSettings","Icon","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/composites/account-menu/account-menu.tsx"],"sourcesContent":["import {\n CircleHelp,\n Info,\n LogIn,\n LogOut,\n Megaphone,\n RefreshCw,\n Settings2,\n Smartphone,\n UserRound,\n} from 'lucide-solid'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { For, Show, createSignal, onCleanup, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport { Button, type ButtonProps } from '../../ui/button/button'\nimport { SideRailButton } from '../../layout/side-rail/side-rail'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../../ui/dropdown-menu/dropdown-menu'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/tooltip/tooltip'\n\n/**\n * AccountMenu.\n *\n * The trailing control in a rail or a top bar: the account, the way into settings,\n * and the way out. Every desktop application has one and they are all the same menu,\n * which is why it belongs here rather than being redrawn per app.\n *\n * ## The items are the caller's\n *\n * The menu takes a list rather than hard-coding one. An application adds and removes\n * entries — a mobile hand-off that only makes sense on desktop, a feedback link that\n * only exists once there is somewhere to send it — and a component that decided the\n * list could not be used by two products.\n *\n * `disabled` on an item is deliberately visible rather than hidden: a greyed \"Help\n * Center\" says the destination is coming, while an absent one says it does not exist.\n */\nexport type AccountMenuItem = {\n id: string\n label: string\n icon?: JSX.Element\n /** A chord drawn at the trailing edge, e.g. `⌘,`. */\n shortcut?: string\n /**\n * The parseable chord behind `shortcut`, e.g. `Meta+,`. The glyph is\n * `aria-hidden` so the item's accessible name stays exactly its label —\n * same contract as `SideRailItem`. Supply it whenever `shortcut` is drawn.\n */\n keyshortcuts?: string\n disabled?: boolean\n /** Render only on this platform. Omit to always render. */\n platform?: 'desktop' | 'web'\n onSelect?: () => void\n /** Run after the menu's close-focus cycle, with its trigger as a stable opener. */\n onSelectAfterClose?: (trigger: HTMLButtonElement | undefined) => void\n}\n\nexport type AccountMenuProps = {\n class?: string\n /** Anchor a rail menu beside its trigger, or keep the default upward placement. */\n placement?: ComponentProps<typeof DropdownMenu>['placement']\n /** Space between the trigger and menu, in pixels. */\n gutter?: ComponentProps<typeof DropdownMenu>['gutter']\n /** Hide the menu pointer when aligning it beside a compact rail. */\n hideArrow?: boolean\n /** The trigger size. Icon-only menus default to the standard icon size. */\n size?: ButtonProps['size']\n /**\n * Render the trigger as a `SideRailButton` row instead of a bare icon\n * button: same geometry, hover treatment, and flush collapsed-rail tip as\n * every other entry in the surrounding rail. The component's own tooltip\n * is skipped — the rail row owns its help.\n */\n railTrigger?: boolean\n /** The entries above the separator. */\n items: readonly AccountMenuItem[]\n /** Which platform this is rendered on, for items that declare one. */\n platform?: 'desktop' | 'web'\n /** Whether a session exists. Decides the sign-in/sign-out row. */\n authenticated: boolean\n /** Local-only applications can omit the session actions altogether. */\n showSession?: boolean\n /** Disable the session row while a sign-in or sign-out is in flight. */\n busy?: boolean\n /** The name shown on the trigger's accessible label. */\n label?: string\n onSignIn?: () => void\n onSignOut?: () => void\n /** Fires on hover or focus of the trigger — a chance to prefetch. */\n onIntent?: () => void\n}\n\nconst FALLBACK_ICONS: Record<string, typeof Settings2> = {\n mobile: Smartphone,\n settings: Settings2,\n about: Info,\n help: CircleHelp,\n feedback: Megaphone,\n updates: RefreshCw,\n}\n\nexport function AccountMenu(props: AccountMenuProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'placement',\n 'gutter',\n 'hideArrow',\n 'size',\n 'railTrigger',\n 'items',\n 'platform',\n 'authenticated',\n 'showSession',\n 'busy',\n 'label',\n 'onSignIn',\n 'onSignOut',\n 'onIntent',\n ])\n\n let trigger: HTMLButtonElement | undefined\n let pendingAfterClose:\n | { callback: NonNullable<AccountMenuItem['onSelectAfterClose']> }\n | undefined\n let scheduledAfterClose:\n | { callback: NonNullable<AccountMenuItem['onSelectAfterClose']> }\n | undefined\n const [menuOpen, setMenuOpen] = createSignal(false)\n const [tooltipOpen, setTooltipOpen] = createSignal(false)\n\n onCleanup(() => {\n pendingAfterClose = undefined\n scheduledAfterClose = undefined\n })\n\n const visible = () =>\n local.items.filter((item) => !item.platform || item.platform === (local.platform ?? 'desktop'))\n\n // Built by reference at each return, not once up front: Solid fixes a node's\n // owner chain when the JSX expression runs, and an eagerly created tree would\n // never see the Tooltip provider below — Kobalte's TooltipTrigger then throws\n // `useTooltipContext must be used within a Tooltip component`.\n const menu = () => (\n <DropdownMenu\n modal={false}\n placement={local.placement ?? 'top-start'}\n gutter={local.gutter}\n onOpenChange={(open) => {\n setMenuOpen(open)\n if (open) setTooltipOpen(false)\n }}\n >\n <Show\n when={local.railTrigger}\n fallback={\n <TooltipTrigger\n as={AccountMenuButton}\n ref={(element: HTMLButtonElement) => (trigger = element)}\n variant=\"ghost\"\n size={local.size ?? 'icon-md'}\n class={cn('text-muted-foreground', local.class)}\n aria-label={local.label ?? 'Account and settings'}\n onFocus={() => local.onIntent?.()}\n onPointerEnter={() => local.onIntent?.()}\n {...rest}\n >\n <UserRound aria-hidden=\"true\" />\n </TooltipTrigger>\n }\n >\n {/* Rail parity: the trigger is a SideRailButton row — the same\n geometry and flush collapsed-rail tip as every other rail entry —\n so the composite's own tooltip stays out of the way. */}\n <DropdownMenuTrigger\n as={SideRailButton}\n ref={(element: HTMLButtonElement) => (trigger = element)}\n label={local.label ?? 'Account and settings'}\n class={local.class}\n onFocus={() => local.onIntent?.()}\n onPointerEnter={() => local.onIntent?.()}\n {...rest}\n >\n <UserRound aria-hidden=\"true\" />\n </DropdownMenuTrigger>\n </Show>\n <DropdownMenuContent\n hideArrow={local.hideArrow}\n class=\"min-w-56 max-h-(--kb-popper-available-height) overflow-x-hidden overflow-y-auto\"\n onCloseAutoFocus={(event) => {\n const selection = pendingAfterClose\n pendingAfterClose = undefined\n if (!selection) return\n\n event.preventDefault()\n scheduledAfterClose = selection\n queueMicrotask(() => {\n if (scheduledAfterClose !== selection) return\n scheduledAfterClose = undefined\n selection.callback(trigger)\n })\n }}\n >\n <DropdownMenuGroup>\n <For each={visible()}>\n {(item) => (\n <DropdownMenuItem\n disabled={item.disabled}\n onSelect={() => {\n pendingAfterClose = item.onSelectAfterClose\n ? { callback: item.onSelectAfterClose }\n : undefined\n item.onSelect?.()\n }}\n shortcut={item.shortcut}\n keyshortcuts={item.keyshortcuts}\n >\n {item.icon ?? renderFallbackIcon(item.id)}\n <span>{item.label}</span>\n </DropdownMenuItem>\n )}\n </For>\n </DropdownMenuGroup>\n <Show when={local.showSession !== false}>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem\n disabled={local.busy}\n onSelect={() => (local.authenticated ? local.onSignOut?.() : local.onSignIn?.())}\n >\n <Show when={local.authenticated} fallback={<LogIn aria-hidden=\"true\" />}>\n <LogOut aria-hidden=\"true\" />\n </Show>\n <span>{local.authenticated ? 'Sign out' : 'Sign in'}</span>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </Show>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n\n if (local.railTrigger) return menu()\n\n return (\n <Tooltip open={tooltipOpen()} onOpenChange={(open) => setTooltipOpen(open && !menuOpen())}>\n {menu()}\n {/* Both overlays own a Popper context; the tooltip must stay outside the menu root. */}\n <TooltipContent placement=\"top\">{local.label ?? 'Account and settings'}</TooltipContent>\n </Tooltip>\n )\n}\n\n/** The common support menu, with one app-specific entry before the shared items. */\nexport function createAppMenuItems(options: {\n primaryItem?: AccountMenuItem\n settingsShortcut?: string\n onAbout?: AccountMenuItem['onSelectAfterClose']\n onHelp?: AccountMenuItem['onSelectAfterClose']\n onFeedback?: AccountMenuItem['onSelectAfterClose']\n onUpdates?: AccountMenuItem['onSelectAfterClose']\n onSettings?: AccountMenuItem['onSelectAfterClose']\n}): AccountMenuItem[] {\n return [\n ...(options.primaryItem ? [options.primaryItem] : []),\n {\n id: 'about',\n label: 'About',\n disabled: !options.onAbout,\n onSelectAfterClose: options.onAbout,\n },\n {\n id: 'help',\n label: 'Help Center',\n disabled: !options.onHelp,\n onSelectAfterClose: options.onHelp,\n },\n {\n id: 'feedback',\n label: 'Send Feedback',\n disabled: !options.onFeedback,\n onSelectAfterClose: options.onFeedback,\n },\n {\n id: 'updates',\n label: 'Updates',\n platform: 'desktop',\n disabled: !options.onUpdates,\n onSelectAfterClose: options.onUpdates,\n },\n {\n id: 'settings',\n label: 'Settings',\n shortcut: options.settingsShortcut,\n disabled: !options.onSettings,\n onSelectAfterClose: options.onSettings,\n },\n ]\n}\n\nfunction AccountMenuButton(props: ComponentProps<typeof Button>) {\n return <DropdownMenuTrigger as={Button} {...props} />\n}\n\n/**\n * A known item id gets its conventional glyph, so a caller that only wants the\n * standard menu does not have to import six icons to get it.\n */\nfunction renderFallbackIcon(id: string): JSX.Element {\n const Icon = FALLBACK_ICONS[id]\n return Icon ? <Icon aria-hidden=\"true\" /> : null\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"account-menu.js","names":["CircleHelp","Info","LogIn","LogOut","Megaphone","RefreshCw","Settings2","Smartphone","UserRound","ComponentProps","JSX","For","Show","createSignal","onCleanup","splitProps","cn","Button","ButtonProps","SideRailButton","DropdownMenu","DropdownMenuContent","DropdownMenuGroup","DropdownMenuItem","DropdownMenuSeparator","DropdownMenuTrigger","Tooltip","TooltipContent","TooltipTrigger","AccountMenuItem","id","label","icon","Element","shortcut","keyshortcuts","disabled","platform","onSelect","onSelectAfterClose","trigger","HTMLButtonElement","AccountMenuProps","class","placement","gutter","hideArrow","size","railTrigger","items","authenticated","updateAvailable","showSession","busy","onSignIn","onSignOut","onIntent","FALLBACK_ICONS","Record","mobile","settings","about","help","feedback","updates","AccountMenu","props","local","rest","pendingAfterClose","callback","NonNullable","scheduledAfterClose","menuOpen","setMenuOpen","tooltipOpen","setTooltipOpen","undefined","visible","filter","item","triggerName","updateDot","_$createComponent","when","children","_tmpl$","menu","modal","onOpenChange","open","fallback","_$mergeProps","as","AccountMenuButton","ref","element","variant","aria-label","onFocus","onPointerEnter","_$memo","onCloseAutoFocus","event","selection","preventDefault","queueMicrotask","each","renderFallbackIcon","_el$3","_tmpl$2","_$insert","_tmpl$3","_el$2","createAppMenuItems","options","primaryItem","settingsShortcut","onAbout","onHelp","onFeedback","onUpdates","onSettings","Icon","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/composites/account-menu/account-menu.tsx"],"sourcesContent":["import {\n CircleHelp,\n Info,\n LogIn,\n LogOut,\n Megaphone,\n RefreshCw,\n Settings2,\n Smartphone,\n UserRound,\n} from 'lucide-solid'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { For, Show, createSignal, onCleanup, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport { Button, type ButtonProps } from '../../ui/button/button'\nimport { SideRailButton } from '../../layout/side-rail/side-rail'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../../ui/dropdown-menu/dropdown-menu'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/tooltip/tooltip'\n\n/**\n * AccountMenu.\n *\n * The trailing control in a rail or a top bar: the account, the way into settings,\n * and the way out. Every desktop application has one and they are all the same menu,\n * which is why it belongs here rather than being redrawn per app.\n *\n * ## The items are the caller's\n *\n * The menu takes a list rather than hard-coding one. An application adds and removes\n * entries — a mobile hand-off that only makes sense on desktop, a feedback link that\n * only exists once there is somewhere to send it — and a component that decided the\n * list could not be used by two products.\n *\n * `disabled` on an item is deliberately visible rather than hidden: a greyed \"Help\n * Center\" says the destination is coming, while an absent one says it does not exist.\n */\nexport type AccountMenuItem = {\n id: string\n label: string\n icon?: JSX.Element\n /** A chord drawn at the trailing edge, e.g. `⌘,`. */\n shortcut?: string\n /**\n * The parseable chord behind `shortcut`, e.g. `Meta+,`. The glyph is\n * `aria-hidden` so the item's accessible name stays exactly its label —\n * same contract as `SideRailItem`. Supply it whenever `shortcut` is drawn.\n */\n keyshortcuts?: string\n disabled?: boolean\n /** Render only on this platform. Omit to always render. */\n platform?: 'desktop' | 'web'\n onSelect?: () => void\n /** Run after the menu's close-focus cycle, with its trigger as a stable opener. */\n onSelectAfterClose?: (trigger: HTMLButtonElement | undefined) => void\n}\n\nexport type AccountMenuProps = {\n class?: string\n /** Anchor a rail menu beside its trigger, or keep the default upward placement. */\n placement?: ComponentProps<typeof DropdownMenu>['placement']\n /** Space between the trigger and menu, in pixels. */\n gutter?: ComponentProps<typeof DropdownMenu>['gutter']\n /** Hide the menu pointer when aligning it beside a compact rail. */\n hideArrow?: boolean\n /** The trigger size. Icon-only menus default to the standard icon size. */\n size?: ButtonProps['size']\n /**\n * Render the trigger as a `SideRailButton` row instead of a bare icon\n * button: same geometry, hover treatment, and flush collapsed-rail tip as\n * every other entry in the surrounding rail. The component's own tooltip\n * is skipped — the rail row owns its help.\n */\n railTrigger?: boolean\n /** The entries above the separator. */\n items: readonly AccountMenuItem[]\n /** Which platform this is rendered on, for items that declare one. */\n platform?: 'desktop' | 'web'\n /** Whether a session exists. Decides the sign-in/sign-out row. */\n authenticated: boolean\n /**\n * Draw the pending-update indicator: an accent dot on the trigger and on the\n * `updates` row — the id `createAppMenuItems` mints, the same convention the\n * fallback icons follow — and extend both accessible names with \"update\n * available\", because the dot itself carries no text. The updater remains the\n * caller's: the prop only mirrors its state into the menu.\n */\n updateAvailable?: boolean\n /** Local-only applications can omit the session actions altogether. */\n showSession?: boolean\n /** Disable the session row while a sign-in or sign-out is in flight. */\n busy?: boolean\n /** The name shown on the trigger's accessible label. */\n label?: string\n onSignIn?: () => void\n onSignOut?: () => void\n /** Fires on hover or focus of the trigger — a chance to prefetch. */\n onIntent?: () => void\n}\n\nconst FALLBACK_ICONS: Record<string, typeof Settings2> = {\n mobile: Smartphone,\n settings: Settings2,\n about: Info,\n help: CircleHelp,\n feedback: Megaphone,\n updates: RefreshCw,\n}\n\nexport function AccountMenu(props: AccountMenuProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'placement',\n 'gutter',\n 'hideArrow',\n 'size',\n 'railTrigger',\n 'items',\n 'platform',\n 'authenticated',\n 'updateAvailable',\n 'showSession',\n 'busy',\n 'label',\n 'onSignIn',\n 'onSignOut',\n 'onIntent',\n ])\n\n let trigger: HTMLButtonElement | undefined\n let pendingAfterClose:\n | { callback: NonNullable<AccountMenuItem['onSelectAfterClose']> }\n | undefined\n let scheduledAfterClose:\n | { callback: NonNullable<AccountMenuItem['onSelectAfterClose']> }\n | undefined\n const [menuOpen, setMenuOpen] = createSignal(false)\n const [tooltipOpen, setTooltipOpen] = createSignal(false)\n\n onCleanup(() => {\n pendingAfterClose = undefined\n scheduledAfterClose = undefined\n })\n\n const visible = () =>\n local.items.filter((item) => !item.platform || item.platform === (local.platform ?? 'desktop'))\n\n // The pending update reaches the user twice on each surface: as a dot and as\n // words. The dot is aria-hidden, so the accessible names carry the state —\n // which is why the names are extended here rather than left to the caller.\n const triggerName = () =>\n `${local.label ?? 'Account and settings'}${local.updateAvailable ? ', update available' : ''}`\n const updateDot = () => (\n <Show when={local.updateAvailable}>\n <span\n data-slot=\"account-menu-update-dot\"\n aria-hidden=\"true\"\n class=\"absolute top-1.5 right-2.5 size-2 rounded-full bg-primary\"\n />\n </Show>\n )\n\n // Built by reference at each return, not once up front: Solid fixes a node's\n // owner chain when the JSX expression runs, and an eagerly created tree would\n // never see the Tooltip provider below — Kobalte's TooltipTrigger then throws\n // `useTooltipContext must be used within a Tooltip component`.\n const menu = () => (\n <DropdownMenu\n modal={false}\n placement={local.placement ?? 'top-start'}\n gutter={local.gutter}\n onOpenChange={(open) => {\n setMenuOpen(open)\n if (open) setTooltipOpen(false)\n }}\n >\n <Show\n when={local.railTrigger}\n fallback={\n <TooltipTrigger\n as={AccountMenuButton}\n ref={(element: HTMLButtonElement) => (trigger = element)}\n variant=\"ghost\"\n size={local.size ?? 'icon-md'}\n class={cn('relative text-muted-foreground', local.class)}\n data-slot=\"account-menu-trigger\"\n aria-label={triggerName()}\n onFocus={() => local.onIntent?.()}\n onPointerEnter={() => local.onIntent?.()}\n {...rest}\n >\n <UserRound aria-hidden=\"true\" />\n {updateDot()}\n </TooltipTrigger>\n }\n >\n {/* Rail parity: the trigger is a SideRailButton row — the same\n geometry and flush collapsed-rail tip as every other rail entry —\n so the composite's own tooltip stays out of the way. */}\n <DropdownMenuTrigger\n as={SideRailButton}\n ref={(element: HTMLButtonElement) => (trigger = element)}\n label={triggerName()}\n class={cn('relative', local.class)}\n data-slot=\"account-menu-trigger\"\n onFocus={() => local.onIntent?.()}\n onPointerEnter={() => local.onIntent?.()}\n {...rest}\n >\n <UserRound aria-hidden=\"true\" />\n {updateDot()}\n </DropdownMenuTrigger>\n </Show>\n <DropdownMenuContent\n hideArrow={local.hideArrow}\n class=\"min-w-56 max-h-(--kb-popper-available-height) overflow-x-hidden overflow-y-auto\"\n onCloseAutoFocus={(event) => {\n const selection = pendingAfterClose\n pendingAfterClose = undefined\n if (!selection) return\n\n event.preventDefault()\n scheduledAfterClose = selection\n queueMicrotask(() => {\n if (scheduledAfterClose !== selection) return\n scheduledAfterClose = undefined\n selection.callback(trigger)\n })\n }}\n >\n <DropdownMenuGroup>\n <For each={visible()}>\n {(item) => (\n <DropdownMenuItem\n disabled={item.disabled}\n aria-label={\n local.updateAvailable && item.id === 'updates'\n ? `${item.label}, update available`\n : undefined\n }\n onSelect={() => {\n pendingAfterClose = item.onSelectAfterClose\n ? { callback: item.onSelectAfterClose }\n : undefined\n item.onSelect?.()\n }}\n shortcut={item.shortcut}\n keyshortcuts={item.keyshortcuts}\n >\n {item.icon ?? renderFallbackIcon(item.id)}\n <span>{item.label}</span>\n <Show when={local.updateAvailable && item.id === 'updates'}>\n <span\n data-slot=\"account-menu-update-dot\"\n aria-hidden=\"true\"\n class=\"ms-auto size-2 shrink-0 rounded-full bg-primary\"\n />\n </Show>\n </DropdownMenuItem>\n )}\n </For>\n </DropdownMenuGroup>\n <Show when={local.showSession !== false}>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem\n disabled={local.busy}\n onSelect={() => (local.authenticated ? local.onSignOut?.() : local.onSignIn?.())}\n >\n <Show when={local.authenticated} fallback={<LogIn aria-hidden=\"true\" />}>\n <LogOut aria-hidden=\"true\" />\n </Show>\n <span>{local.authenticated ? 'Sign out' : 'Sign in'}</span>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </Show>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n\n if (local.railTrigger) return menu()\n\n return (\n <Tooltip open={tooltipOpen()} onOpenChange={(open) => setTooltipOpen(open && !menuOpen())}>\n {menu()}\n {/* Both overlays own a Popper context; the tooltip must stay outside the menu root. */}\n <TooltipContent placement=\"top\">{local.label ?? 'Account and settings'}</TooltipContent>\n </Tooltip>\n )\n}\n\n/** The common support menu, with one app-specific entry before the shared items. */\nexport function createAppMenuItems(options: {\n primaryItem?: AccountMenuItem\n settingsShortcut?: string\n onAbout?: AccountMenuItem['onSelectAfterClose']\n onHelp?: AccountMenuItem['onSelectAfterClose']\n onFeedback?: AccountMenuItem['onSelectAfterClose']\n onUpdates?: AccountMenuItem['onSelectAfterClose']\n onSettings?: AccountMenuItem['onSelectAfterClose']\n}): AccountMenuItem[] {\n return [\n ...(options.primaryItem ? [options.primaryItem] : []),\n {\n id: 'about',\n label: 'About',\n disabled: !options.onAbout,\n onSelectAfterClose: options.onAbout,\n },\n {\n id: 'help',\n label: 'Help Center',\n disabled: !options.onHelp,\n onSelectAfterClose: options.onHelp,\n },\n {\n id: 'feedback',\n label: 'Send Feedback',\n disabled: !options.onFeedback,\n onSelectAfterClose: options.onFeedback,\n },\n {\n id: 'updates',\n label: 'Updates',\n platform: 'desktop',\n disabled: !options.onUpdates,\n onSelectAfterClose: options.onUpdates,\n },\n {\n id: 'settings',\n label: 'Settings',\n shortcut: options.settingsShortcut,\n disabled: !options.onSettings,\n onSelectAfterClose: options.onSettings,\n },\n ]\n}\n\nfunction AccountMenuButton(props: ComponentProps<typeof Button>) {\n return <DropdownMenuTrigger as={Button} {...props} />\n}\n\n/**\n * A known item id gets its conventional glyph, so a caller that only wants the\n * standard menu does not have to import six icons to get it.\n */\nfunction renderFallbackIcon(id: string): JSX.Element {\n const Icon = FALLBACK_ICONS[id]\n return Icon ? <Icon aria-hidden=\"true\" /> : null\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/button/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAC9E,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAC/E,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAGvF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc;;;;8EA0D1B,CAAA;AAED,KAAK,kBAAkB,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAA;AAE7D,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,IAAI,gBAAgB,CAC7E,CAAC,EACD,kBAAkB,GAAG;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CACF,CAAA;AAED,wBAAgB,MAAM,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,kCAwBhF"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/button/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAC9E,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAC/E,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAGvF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc;;;;8EA6D1B,CAAA;AAED,KAAK,kBAAkB,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAA;AAE7D,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,IAAI,gBAAgB,CAC7E,CAAC,EACD,kBAAkB,GAAG;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CACF,CAAA;AAED,wBAAgB,MAAM,CAAC,CAAC,SAAS,cAAc,GAAG,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,kCAwBhF"}
@@ -34,11 +34,13 @@ var buttonVariants = cva(`${controlInteractive} inline-flex shrink-0 items-cente
34
34
  ghost: "text-foreground hover:bg-surface-hover",
35
35
  /**
36
36
  * A ghost that opens something: a sheet, menu or popover trigger in a
37
- * toolbar. While its surface is open it holds the menubar's pressed
38
- * rung, so the open control never reads identical to its closed
39
- * neighbours.
37
+ * toolbar. While its surface is open it holds the accent's own tint —
38
+ * the same treatment that drives the side rail's active destination —
39
+ * so the open control never reads identical to its closed neighbours
40
+ * and the app's pressed chrome reads as one accent chroma. The
41
+ * compound hover keeps the tint when an open control is pointed at.
40
42
  */
41
- toolbar: "text-foreground hover:bg-surface-hover data-[expanded]:bg-surface-active",
43
+ toolbar: "text-foreground hover:bg-surface-hover data-[expanded]:bg-primary-subtle data-[expanded]:text-primary data-[expanded]:hover:bg-primary-subtle",
42
44
  /** A tinted primary, for a secondary action inside a primary flow. */
43
45
  subtle: "bg-primary-subtle text-primary hover:bg-primary-subtle/80",
44
46
  success: "bg-success text-success-foreground hover:bg-success/90",
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","names":["Polymorphic","PolymorphicProps","ComponentProps","splitProps","ValidComponent","cva","controlInteractive","controlSize","VariantProps","cn","buttonVariants","variants","variant","default","secondary","destructive","outline","ghost","toolbar","subtle","success","link","size","xs","sm","md","lg","xl","touchTarget","comfortable","defaultVariants","ButtonVariantProps","ButtonProps","T","class","Button","props","local","rest","_$createComponent","_$mergeProps","as","type","_$createComponent","_$mergeProps"],"sources":["../../../../src/components/ui/button/button.tsx"],"sourcesContent":["import { Polymorphic, type PolymorphicProps } from '@kobalte/core/polymorphic'\nimport { type ComponentProps, splitProps, type ValidComponent } from 'solid-js'\nimport { cva, controlInteractive, controlSize, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * Button.\n *\n * One appearance ladder shared by every pressable thing in the system: a\n * button, a toolbar control, a dialog action, and a menu row all draw from the\n * same tokens, so a row of them cannot drift apart.\n *\n * The variants answer \"what is this for\", never \"what colour is it\". A caller\n * that wants a red button writes `variant=\"destructive\"`; the red lives here.\n * That is also what lets the design-system linter tell a caller which variant\n * to use instead of only which class was wrong.\n *\n * Polymorphic: pass `as=\"a\"` (or any component) and the button becomes it\n * while keeping the same styling contract. This replaces the React-era\n * `asChild` primitive, which has no Solid equivalent that preserves props.\n */\nexport const buttonVariants = cva(\n `${controlInteractive} inline-flex shrink-0 items-center justify-center rounded-md font-medium whitespace-nowrap select-none [&_svg]:pointer-events-none [&_svg]:shrink-0`,\n {\n variants: {\n variant: {\n /** The one primary action in a view. */\n default: 'bg-primary text-primary-foreground hover:bg-primary-hover',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-surface-hover',\n /** For the action that destroys something. Never the default. */\n destructive:\n 'bg-destructive-action text-destructive-action-foreground hover:bg-destructive-action/90 focus-visible:ring-destructive-subtle',\n /** A bordered button for a surface that already has a fill. */\n outline:\n 'border border-border bg-transparent text-foreground hover:bg-surface-hover hover:border-input',\n /** No chrome until hover. The default for toolbar and row actions. */\n ghost: 'text-foreground hover:bg-surface-hover',\n /**\n * A ghost that opens something: a sheet, menu or popover trigger in a\n * toolbar. While its surface is open it holds the menubar's pressed\n * rung, so the open control never reads identical to its closed\n * neighbours.\n */\n toolbar: 'text-foreground hover:bg-surface-hover data-[expanded]:bg-surface-active',\n /** A tinted primary, for a secondary action inside a primary flow. */\n subtle: 'bg-primary-subtle text-primary hover:bg-primary-subtle/80',\n success: 'bg-success text-success-foreground hover:bg-success/90',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n '2xs': `${controlSize['2xs']} [&_svg]:size-3`,\n xs: `${controlSize.xs} [&_svg]:size-3.5`,\n sm: `${controlSize.sm} [&_svg]:size-3.5`,\n md: `${controlSize.md} [&_svg]:size-4`,\n lg: `${controlSize.lg} [&_svg]:size-4`,\n xl: `${controlSize.xl} [&_svg]:size-5`,\n '2xl': `${controlSize['2xl']} [&_svg]:size-6`,\n /* Square, for an icon with no label. The accessible name then has to\n come from `aria-label` or a visually hidden label — an icon-only\n button with neither is the accessibility finding the Storybook lane\n catches on every story. */\n 'icon-2xs': 'size-control-2xs p-0 [&_svg]:size-3',\n 'icon-xs': 'size-control-xs p-0 [&_svg]:size-3.5',\n 'icon-sm': 'size-control-sm p-0 [&_svg]:size-3.5',\n 'icon-md': 'size-control-md p-0 [&_svg]:size-4',\n 'icon-lg': 'size-control-lg p-0 [&_svg]:size-4',\n 'icon-xl': 'size-control-xl p-0 [&_svg]:size-5',\n 'icon-2xl': 'size-control-2xl p-0 [&_svg]:size-6',\n },\n /** Opt in to a stable touch target on devices with any coarse pointer. */\n touchTarget: {\n comfortable: 'touch-target-comfortable',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n },\n }\n)\n\ntype ButtonVariantProps = VariantProps<typeof buttonVariants>\n\nexport type ButtonProps<T extends ValidComponent = 'button'> = PolymorphicProps<\n T,\n ButtonVariantProps & {\n class?: string\n }\n>\n\nexport function Button<T extends ValidComponent = 'button'>(props: ButtonProps<T>) {\n const [local, rest] = splitProps(props as ButtonProps, [\n 'variant',\n 'size',\n 'touchTarget',\n 'class',\n ])\n\n return (\n <Polymorphic\n as=\"button\"\n type=\"button\"\n data-slot=\"button\"\n class={cn(\n buttonVariants({\n variant: local.variant,\n size: local.size,\n touchTarget: local.touchTarget,\n }),\n local.class\n )}\n {...(rest as ComponentProps<'button'>)}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAaU,iBAAiBL,IAC5B,GAAGC,mBAAkB,sJACrB;CACEK,UAAU;EACRC,SAAS;;GAEPC,SAAS;GACTC,WAAW;;GAEXC,aACE;;GAEFC,SACE;;GAEFC,OAAO;;;;;;;GAOPC,SAAS;;GAETC,QAAQ;GACRC,SAAS;GACTC,MAAM;EACR;EACAC,MAAM;GACJ,OAAO,GAAGf,YAAY,OAAM;GAC5BgB,IAAI,GAAGhB,YAAYgB,GAAE;GACrBC,IAAI,GAAGjB,YAAYiB,GAAE;GACrBC,IAAI,GAAGlB,YAAYkB,GAAE;GACrBC,IAAI,GAAGnB,YAAYmB,GAAE;GACrBC,IAAI,GAAGpB,YAAYoB,GAAE;GACrB,OAAO,GAAGpB,YAAY,OAAM;GAK5B,YAAY;GACZ,WAAW;GACX,WAAW;GACX,WAAW;GACX,WAAW;GACX,WAAW;GACX,YAAY;EACd;;EAEAqB,aAAa,EACXC,aAAa,2BACf;CACF;CACAC,iBAAiB;EACflB,SAAS;EACTU,MAAM;CACR;AACF,CACF;AAWA,SAAgBa,OAA4CC,OAAuB;CACjF,MAAM,CAACC,OAAOC,QAAQnC,WAAWiC,OAAsB;EACrD;EACA;EACA;EACA;CAAO,CACR;CAED,OAAAG,gBACGvC,aAAWwC,WAAA;EACVC,IAAE;EACFC,MAAI;EAAA,aAAA;EAAA,KAAA,WAAA;GAAA,OAEGjC,GACLC,eAAe;IACbE,SAASyB,MAAMzB;IACfU,MAAMe,MAAMf;IACZM,aAAaS,MAAMT;GACrB,CAAC,GACDS,MAAMH,KACR;EAAC;CAAA,GACII,IAAgC,CAAA;AAG3C"}
1
+ {"version":3,"file":"button.js","names":["Polymorphic","PolymorphicProps","ComponentProps","splitProps","ValidComponent","cva","controlInteractive","controlSize","VariantProps","cn","buttonVariants","variants","variant","default","secondary","destructive","outline","ghost","toolbar","subtle","success","link","size","xs","sm","md","lg","xl","touchTarget","comfortable","defaultVariants","ButtonVariantProps","ButtonProps","T","class","Button","props","local","rest","_$createComponent","_$mergeProps","as","type","_$createComponent","_$mergeProps"],"sources":["../../../../src/components/ui/button/button.tsx"],"sourcesContent":["import { Polymorphic, type PolymorphicProps } from '@kobalte/core/polymorphic'\nimport { type ComponentProps, splitProps, type ValidComponent } from 'solid-js'\nimport { cva, controlInteractive, controlSize, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * Button.\n *\n * One appearance ladder shared by every pressable thing in the system: a\n * button, a toolbar control, a dialog action, and a menu row all draw from the\n * same tokens, so a row of them cannot drift apart.\n *\n * The variants answer \"what is this for\", never \"what colour is it\". A caller\n * that wants a red button writes `variant=\"destructive\"`; the red lives here.\n * That is also what lets the design-system linter tell a caller which variant\n * to use instead of only which class was wrong.\n *\n * Polymorphic: pass `as=\"a\"` (or any component) and the button becomes it\n * while keeping the same styling contract. This replaces the React-era\n * `asChild` primitive, which has no Solid equivalent that preserves props.\n */\nexport const buttonVariants = cva(\n `${controlInteractive} inline-flex shrink-0 items-center justify-center rounded-md font-medium whitespace-nowrap select-none [&_svg]:pointer-events-none [&_svg]:shrink-0`,\n {\n variants: {\n variant: {\n /** The one primary action in a view. */\n default: 'bg-primary text-primary-foreground hover:bg-primary-hover',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-surface-hover',\n /** For the action that destroys something. Never the default. */\n destructive:\n 'bg-destructive-action text-destructive-action-foreground hover:bg-destructive-action/90 focus-visible:ring-destructive-subtle',\n /** A bordered button for a surface that already has a fill. */\n outline:\n 'border border-border bg-transparent text-foreground hover:bg-surface-hover hover:border-input',\n /** No chrome until hover. The default for toolbar and row actions. */\n ghost: 'text-foreground hover:bg-surface-hover',\n /**\n * A ghost that opens something: a sheet, menu or popover trigger in a\n * toolbar. While its surface is open it holds the accent's own tint —\n * the same treatment that drives the side rail's active destination —\n * so the open control never reads identical to its closed neighbours\n * and the app's pressed chrome reads as one accent chroma. The\n * compound hover keeps the tint when an open control is pointed at.\n */\n toolbar:\n 'text-foreground hover:bg-surface-hover data-[expanded]:bg-primary-subtle data-[expanded]:text-primary data-[expanded]:hover:bg-primary-subtle',\n /** A tinted primary, for a secondary action inside a primary flow. */\n subtle: 'bg-primary-subtle text-primary hover:bg-primary-subtle/80',\n success: 'bg-success text-success-foreground hover:bg-success/90',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n '2xs': `${controlSize['2xs']} [&_svg]:size-3`,\n xs: `${controlSize.xs} [&_svg]:size-3.5`,\n sm: `${controlSize.sm} [&_svg]:size-3.5`,\n md: `${controlSize.md} [&_svg]:size-4`,\n lg: `${controlSize.lg} [&_svg]:size-4`,\n xl: `${controlSize.xl} [&_svg]:size-5`,\n '2xl': `${controlSize['2xl']} [&_svg]:size-6`,\n /* Square, for an icon with no label. The accessible name then has to\n come from `aria-label` or a visually hidden label — an icon-only\n button with neither is the accessibility finding the Storybook lane\n catches on every story. */\n 'icon-2xs': 'size-control-2xs p-0 [&_svg]:size-3',\n 'icon-xs': 'size-control-xs p-0 [&_svg]:size-3.5',\n 'icon-sm': 'size-control-sm p-0 [&_svg]:size-3.5',\n 'icon-md': 'size-control-md p-0 [&_svg]:size-4',\n 'icon-lg': 'size-control-lg p-0 [&_svg]:size-4',\n 'icon-xl': 'size-control-xl p-0 [&_svg]:size-5',\n 'icon-2xl': 'size-control-2xl p-0 [&_svg]:size-6',\n },\n /** Opt in to a stable touch target on devices with any coarse pointer. */\n touchTarget: {\n comfortable: 'touch-target-comfortable',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n },\n }\n)\n\ntype ButtonVariantProps = VariantProps<typeof buttonVariants>\n\nexport type ButtonProps<T extends ValidComponent = 'button'> = PolymorphicProps<\n T,\n ButtonVariantProps & {\n class?: string\n }\n>\n\nexport function Button<T extends ValidComponent = 'button'>(props: ButtonProps<T>) {\n const [local, rest] = splitProps(props as ButtonProps, [\n 'variant',\n 'size',\n 'touchTarget',\n 'class',\n ])\n\n return (\n <Polymorphic\n as=\"button\"\n type=\"button\"\n data-slot=\"button\"\n class={cn(\n buttonVariants({\n variant: local.variant,\n size: local.size,\n touchTarget: local.touchTarget,\n }),\n local.class\n )}\n {...(rest as ComponentProps<'button'>)}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAaU,iBAAiBL,IAC5B,GAAGC,mBAAkB,sJACrB;CACEK,UAAU;EACRC,SAAS;;GAEPC,SAAS;GACTC,WAAW;;GAEXC,aACE;;GAEFC,SACE;;GAEFC,OAAO;;;;;;;;;GASPC,SACE;;GAEFC,QAAQ;GACRC,SAAS;GACTC,MAAM;EACR;EACAC,MAAM;GACJ,OAAO,GAAGf,YAAY,OAAM;GAC5BgB,IAAI,GAAGhB,YAAYgB,GAAE;GACrBC,IAAI,GAAGjB,YAAYiB,GAAE;GACrBC,IAAI,GAAGlB,YAAYkB,GAAE;GACrBC,IAAI,GAAGnB,YAAYmB,GAAE;GACrBC,IAAI,GAAGpB,YAAYoB,GAAE;GACrB,OAAO,GAAGpB,YAAY,OAAM;GAK5B,YAAY;GACZ,WAAW;GACX,WAAW;GACX,WAAW;GACX,WAAW;GACX,WAAW;GACX,YAAY;EACd;;EAEAqB,aAAa,EACXC,aAAa,2BACf;CACF;CACAC,iBAAiB;EACflB,SAAS;EACTU,MAAM;CACR;AACF,CACF;AAWA,SAAgBa,OAA4CC,OAAuB;CACjF,MAAM,CAACC,OAAOC,QAAQnC,WAAWiC,OAAsB;EACrD;EACA;EACA;EACA;CAAO,CACR;CAED,OAAAG,gBACGvC,aAAWwC,WAAA;EACVC,IAAE;EACFC,MAAI;EAAA,aAAA;EAAA,KAAA,WAAA;GAAA,OAEGjC,GACLC,eAAe;IACbE,SAASyB,MAAMzB;IACfU,MAAMe,MAAMf;IACZM,aAAaS,MAAMT;GACrB,CAAC,GACDS,MAAMH,KACR;EAAC;CAAA,GACII,IAAgC,CAAA;AAG3C"}
@@ -52,5 +52,18 @@ export declare function CommandShortcut(props: {
52
52
  class?: string;
53
53
  children?: ComponentProps<'span'>['children'];
54
54
  }): import("solid-js").JSX.Element;
55
+ /**
56
+ * The status line a command surface reports under its list: searching, offline,
57
+ * a partial result caveat. The copy and the live-role semantics (`status`,
58
+ * `alert`) are the caller's — a palette's failure modes are app facts — but the
59
+ * line's shape is not something every caller should redraw.
60
+ */
61
+ export declare function CommandStatus(props: ComponentProps<'p'>): import("solid-js").JSX.Element;
62
+ /**
63
+ * The keyboard hint a palette footer carries, right-aligned under the list so
64
+ * it reads as furniture rather than a result. Muted on purpose: the arrows are
65
+ * what the user has already been doing by the time they read it.
66
+ */
67
+ export declare function CommandHint(props: ComponentProps<'p'>): import("solid-js").JSX.Element;
55
68
  export {};
56
69
  //# sourceMappingURL=command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/command/command.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,IAAI,UAAU,EAC3B,YAAY,IAAI,SAAS,EACzB,YAAY,IAAI,SAAS,EACzB,YAAY,IAAI,SAAS,EACzB,WAAW,IAAI,QAAQ,EACvB,WAAW,IAAI,QAAQ,EACvB,cAAc,IAAI,WAAW,EAC7B,WAAW,IAAI,QAAQ,EACvB,gBAAgB,IAAI,aAAa,EAElC,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAa9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAY7D;AAED,KAAK,kBAAkB,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,GACzD,IAAI,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAAC,CAAA;AAE5F,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,kCAqEtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAmBnE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAgCjE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAcnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAanE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAkBjE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,kCAG3E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,WAAW,CAAC,kCAQvE;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAA;CAC9C,kCAWA"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/command/command.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,IAAI,UAAU,EAC3B,YAAY,IAAI,SAAS,EACzB,YAAY,IAAI,SAAS,EACzB,YAAY,IAAI,SAAS,EACzB,WAAW,IAAI,QAAQ,EACvB,WAAW,IAAI,QAAQ,EACvB,cAAc,IAAI,WAAW,EAC7B,WAAW,IAAI,QAAQ,EACvB,gBAAgB,IAAI,aAAa,EAElC,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAa9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAY7D;AAED,KAAK,kBAAkB,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,GACzD,IAAI,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CAAC,CAAA;AAE5F,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,kCAqEtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAmBnE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAgCjE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAcnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,kCAanE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,kCAkBjE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,kCAG3E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,WAAW,CAAC,kCAQvE;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAA;CAC9C,kCAWA;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,kCAUvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,kCAUrD"}
@@ -1,7 +1,7 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
2
  import { menuItem } from "../../../lib/overlay.js";
3
3
  import { createDialogFocusRestoration } from "../dialog/dialog.js";
4
- import { className, createComponent, effect, insert, mergeProps, template, use } from "solid-js/web";
4
+ import { className, createComponent, effect, insert, mergeProps, spread, template, use } from "solid-js/web";
5
5
  import { Search } from "lucide-solid";
6
6
  import { createEffect, createSignal, splitProps } from "solid-js";
7
7
  import { CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandRoot, CommandSeparator, useCommandState } from "cmdk-solid";
@@ -10,6 +10,8 @@ import { Dialog } from "@kobalte/core/dialog";
10
10
  var _tmpl$ = /*#__PURE__*/ template(`<div data-slot=command-input-wrapper class="flex h-11 items-center gap-2 border-b border-border px-3">`);
11
11
  var _tmpl$2 = /*#__PURE__*/ template(`<div class=contents>`);
12
12
  var _tmpl$3 = /*#__PURE__*/ template(`<span>`);
13
+ var _tmpl$4 = /*#__PURE__*/ template(`<p data-slot=command-status>`);
14
+ var _tmpl$5 = /*#__PURE__*/ template(`<p data-slot=command-hint>`);
13
15
  var commandItem = menuItem.replace("data-[disabled]:pointer-events-none", "").replace("data-[disabled]:text-muted-foreground", "");
14
16
  /**
15
17
  * Command.
@@ -195,7 +197,38 @@ function CommandShortcut(props) {
195
197
  return _el$3;
196
198
  })();
197
199
  }
200
+ /**
201
+ * The status line a command surface reports under its list: searching, offline,
202
+ * a partial result caveat. The copy and the live-role semantics (`status`,
203
+ * `alert`) are the caller's — a palette's failure modes are app facts — but the
204
+ * line's shape is not something every caller should redraw.
205
+ */
206
+ function CommandStatus(props) {
207
+ const [local, rest] = splitProps(props, ["class"]);
208
+ return (() => {
209
+ var _el$4 = _tmpl$4();
210
+ spread(_el$4, mergeProps({ get ["class"]() {
211
+ return cn("text-muted-foreground px-4 py-4 text-center text-sm", local.class);
212
+ } }, rest), false, false);
213
+ return _el$4;
214
+ })();
215
+ }
216
+ /**
217
+ * The keyboard hint a palette footer carries, right-aligned under the list so
218
+ * it reads as furniture rather than a result. Muted on purpose: the arrows are
219
+ * what the user has already been doing by the time they read it.
220
+ */
221
+ function CommandHint(props) {
222
+ const [local, rest] = splitProps(props, ["class"]);
223
+ return (() => {
224
+ var _el$5 = _tmpl$5();
225
+ spread(_el$5, mergeProps({ get ["class"]() {
226
+ return cn("text-muted-foreground px-4 pb-1.5 text-right text-xs", local.class);
227
+ } }, rest), false, false);
228
+ return _el$5;
229
+ })();
230
+ }
198
231
  //#endregion
199
- export { Command, CommandDialog, CommandEmpty$1 as CommandEmpty, CommandGroup$1 as CommandGroup, CommandInput$1 as CommandInput, CommandItem$1 as CommandItem, CommandList$1 as CommandList, CommandLoading$1 as CommandLoading, CommandSeparator$1 as CommandSeparator, CommandShortcut };
232
+ export { Command, CommandDialog, CommandEmpty$1 as CommandEmpty, CommandGroup$1 as CommandGroup, CommandHint, CommandInput$1 as CommandInput, CommandItem$1 as CommandItem, CommandList$1 as CommandList, CommandLoading$1 as CommandLoading, CommandSeparator$1 as CommandSeparator, CommandShortcut, CommandStatus };
200
233
 
201
234
  //# sourceMappingURL=command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","names":["CommandDialog","CmdkDialog","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandInput","CmdkInput","CommandItem","CmdkItem","CommandList","CmdkList","CommandLoading","CmdkLoading","CommandRoot","CmdkRoot","CommandSeparator","CmdkSeparator","useCommandState","Dialog","KobalteDialog","Search","ComponentProps","createEffect","createSignal","splitProps","createDialogFocusRestoration","menuItem","cn","commandItem","replace","Command","props","local","rest","_$createComponent","_$mergeProps","class","CommandDialogProps","Pick","Content","dialogProps","commandProps","isOpen","setIsOpen","open","defaultOpen","undefined","focus","onCloseAutoFocus","onOpenAutoFocus","onOpenChange","children","Portal","mount","container","Overlay","overlayClassName","aria-label","label","role","contentClassName","_el$","_tmpl$","_$insert","wrapper","setWrapper","HTMLDivElement","resultCount","state","filtered","count","root","selector","querySelector","setAttribute","_el$2","_tmpl$2","_$use","CommandShortcut","_el$3","_tmpl$3","_$effect","_$className","_$createComponent","CmdkRoot","_$mergeProps","KobalteDialog","CommandInput","CmdkInput","CommandList","CmdkList","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandItem","CmdkItem","CommandSeparator","CmdkSeparator","CommandLoading","CmdkLoading","_$className"],"sources":["../../../../src/components/ui/command/command.tsx"],"sourcesContent":["import {\n CommandDialog as CmdkDialog,\n CommandEmpty as CmdkEmpty,\n CommandGroup as CmdkGroup,\n CommandInput as CmdkInput,\n CommandItem as CmdkItem,\n CommandList as CmdkList,\n CommandLoading as CmdkLoading,\n CommandRoot as CmdkRoot,\n CommandSeparator as CmdkSeparator,\n useCommandState,\n} from 'cmdk-solid'\nimport { Dialog as KobalteDialog } from '@kobalte/core/dialog'\nimport { Search } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { createEffect, createSignal, splitProps } from 'solid-js'\nimport { createDialogFocusRestoration } from '../dialog/dialog'\nimport { menuItem } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n// cmdk emits data-disabled=\"false\" on enabled items, unlike the presence-only\n// attributes Kobalte menu rows use. Apply those shared disabled styles only when\n// cmdk's value is true.\nconst commandItem = menuItem\n .replace('data-[disabled]:pointer-events-none', '')\n .replace('data-[disabled]:text-muted-foreground', '')\n\n/**\n * Command.\n *\n * The command palette: a filtered list of everything the user can do, ranked\n * by fuzzy match. It is the one place in an app where a keyboard-first surface\n * is the *primary* one, so it carries rules the rest of the system does not:\n *\n * - Every item must be reachable by typing its name. If a user has to\n * remember which group it lives in, the palette has failed at its job.\n * - Groups exist for reading, not for navigation. The ranking crosses them.\n * - The empty state is not an apology — it should offer the closest thing\n * the app could guess, or say plainly that nothing matched.\n *\n * cmdk-solid supplies the filter, the scoring, the `aria-activedescendant`\n * wiring and the arrow-key navigation.\n */\nexport function Command(props: ComponentProps<typeof CmdkRoot>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkRoot\n class={cn(\n 'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-xl',\n local.class\n )}\n {...rest}\n />\n )\n}\n\ntype CommandDialogProps = ComponentProps<typeof CmdkDialog> &\n Pick<ComponentProps<typeof KobalteDialog.Content>, 'onCloseAutoFocus' | 'onOpenAutoFocus'>\n\nexport function CommandDialog(props: CommandDialogProps) {\n // cmdk-solid's Dialog does not forward Content autofocus props: unknown\n // props fall through to its Command root. Compose Kobalte's dialog surface\n // here so Escape and other close paths can restore focus to the real opener.\n // Preserve the shared wrapper's `class` contract on the dialog surface;\n // `contentClassName` adds to it, while the nested Command keeps its own API.\n const [local, dialogProps, commandProps] = splitProps(\n props,\n [\n 'class',\n 'contentClassName',\n 'overlayClassName',\n 'container',\n 'onCloseAutoFocus',\n 'onOpenAutoFocus',\n ],\n [\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'id',\n 'modal',\n 'preventScroll',\n 'forceMount',\n 'translations',\n ]\n )\n const [isOpen, setIsOpen] = createSignal(dialogProps.open ?? dialogProps.defaultOpen ?? false)\n\n createEffect(() => {\n if (dialogProps.open !== undefined) setIsOpen(dialogProps.open)\n })\n\n const focus = createDialogFocusRestoration({\n open: isOpen,\n onCloseAutoFocus: local.onCloseAutoFocus,\n onOpenAutoFocus: local.onOpenAutoFocus,\n })\n\n return (\n <KobalteDialog\n {...dialogProps}\n onOpenChange={(open) => {\n setIsOpen(open)\n dialogProps.onOpenChange?.(open)\n }}\n >\n <KobalteDialog.Portal mount={local.container}>\n <KobalteDialog.Overlay cmdk-overlay=\"\" class={local.overlayClassName} />\n <KobalteDialog.Content\n aria-label={commandProps.label}\n cmdk-dialog=\"\"\n role=\"dialog\"\n class={cn(\n 'bg-popover text-popover-foreground fixed top-1/3 left-1/2 z-(--z-dialog) w-full max-w-lg -translate-x-1/2 -translate-y-1/2',\n 'overflow-hidden rounded-xl border border-border shadow-xl',\n 'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95',\n 'data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',\n local.class,\n local.contentClassName\n )}\n onOpenAutoFocus={focus.onOpenAutoFocus}\n onCloseAutoFocus={focus.onCloseAutoFocus}\n >\n <Command {...commandProps} />\n </KobalteDialog.Content>\n </KobalteDialog.Portal>\n </KobalteDialog>\n )\n}\n\nexport function CommandInput(props: ComponentProps<typeof CmdkInput>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <div\n data-slot=\"command-input-wrapper\"\n class=\"flex h-11 items-center gap-2 border-b border-border px-3\"\n >\n <Search class=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <CmdkInput\n class={cn(\n 'h-full w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n </div>\n )\n}\n\n/**\n * The scrolling list.\n *\n * Two DOM corrections, and both are deliberate. cmdk builds a `role=\"listbox\"`\n * whose children include two elements ARIA does not allow there:\n *\n * - a bare `<div cmdk-list-sizer>` with no role, wrapped around every group;\n * - a `<div cmdk-separator role=\"separator\">`, and `separator` is a menu and\n * toolbar role — inside a listbox the only owned elements may be `option`\n * and `group`.\n *\n * Both are pure presentation: the sizer is layout, and the separator is a\n * hairline between groups that the groups already structure. `role=\"presentation\"`\n * is their accurate role rather than a workaround — each is flattened out of the\n * accessibility tree, and the options inside are reached exactly as before.\n *\n * Written onto the mounted nodes rather than through props, because cmdk owns\n * this markup and does not forward a `ref`; in an effect rather than `onMount`,\n * because cmdk renders the sizer with the first item, after the list itself.\n */\nexport function CommandList(props: ComponentProps<typeof CmdkList>) {\n const [local, rest] = splitProps(props, ['class'])\n const [wrapper, setWrapper] = createSignal<HTMLDivElement>()\n const resultCount = useCommandState((state) => state.filtered.count)\n\n createEffect(() => {\n const root = wrapper()\n if (!root) return\n for (const selector of ['[cmdk-list-sizer]', '[cmdk-separator]']) {\n root.querySelector(selector)?.setAttribute('role', 'presentation')\n }\n\n /*\n * A `listbox` must own at least one `option`, so a listbox with nothing in it\n * is invalid ARIA — which is what a search with no matches produces. When\n * there are no results the list is inert, so it becomes presentational and\n * the empty message carries the information instead. It keeps its `id`, so\n * the input's `aria-controls` still resolves.\n */\n root\n .querySelector('[cmdk-list]')\n ?.setAttribute('role', resultCount() > 0 ? 'listbox' : 'presentation')\n })\n\n return (\n <div ref={setWrapper} class=\"contents\">\n <CmdkList\n class={cn('max-h-80 scroll-py-1 overflow-y-auto overflow-x-hidden p-1', local.class)}\n {...rest}\n />\n </div>\n )\n}\n\nexport function CommandEmpty(props: ComponentProps<typeof CmdkEmpty>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkEmpty\n /*\n * A status rather than plain text: when the list is presentational, this is\n * the only thing that tells a screen reader the search matched nothing.\n */\n role=\"status\"\n class={cn('text-muted-foreground py-8 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CommandGroup(props: ComponentProps<typeof CmdkGroup>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkGroup\n class={cn(\n 'text-foreground overflow-hidden p-1',\n '[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-2xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:tracking-wide [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:uppercase',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandItem(props: ComponentProps<typeof CmdkItem>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkItem\n class={cn(\n commandItem,\n 'data-[disabled=true]:pointer-events-none data-[disabled=true]:text-muted-foreground',\n // The selected row sits on the accent rung — the same primary-subtle\n // fill the settings navigation's selected row owns — instead of the\n // popover rung, so what is chosen keeps the accent the checked menus\n // already carry in their indicators.\n 'group/command-item text-popover-foreground data-[selected=true]:bg-primary-subtle data-[selected=true]:text-foreground',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandSeparator(props: ComponentProps<typeof CmdkSeparator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <CmdkSeparator class={cn('bg-border -mx-1 my-1 h-px', local.class)} {...rest} />\n}\n\nexport function CommandLoading(props: ComponentProps<typeof CmdkLoading>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <CmdkLoading\n class={cn('text-muted-foreground py-6 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\n/** The keyboard hint a palette item usually carries. */\nexport function CommandShortcut(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n return (\n <span\n class={cn(\n 'text-muted-foreground ms-auto font-code text-code tracking-widest group-data-[selected=true]/command-item:text-foreground',\n props.class\n )}\n >\n {props.children}\n </span>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"command.js","names":["CommandDialog","CmdkDialog","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandInput","CmdkInput","CommandItem","CmdkItem","CommandList","CmdkList","CommandLoading","CmdkLoading","CommandRoot","CmdkRoot","CommandSeparator","CmdkSeparator","useCommandState","Dialog","KobalteDialog","Search","ComponentProps","createEffect","createSignal","splitProps","createDialogFocusRestoration","menuItem","cn","commandItem","replace","Command","props","local","rest","_$createComponent","_$mergeProps","class","CommandDialogProps","Pick","Content","dialogProps","commandProps","isOpen","setIsOpen","open","defaultOpen","undefined","focus","onCloseAutoFocus","onOpenAutoFocus","onOpenChange","children","Portal","mount","container","Overlay","overlayClassName","aria-label","label","role","contentClassName","_el$","_tmpl$","_$insert","wrapper","setWrapper","HTMLDivElement","resultCount","state","filtered","count","root","selector","querySelector","setAttribute","_el$2","_tmpl$2","_$use","CommandShortcut","_el$3","_tmpl$3","_$effect","_$className","CommandStatus","_el$4","_tmpl$4","_$spread","CommandHint","_el$5","_tmpl$5","_$createComponent","CmdkRoot","_$mergeProps","KobalteDialog","CommandInput","CmdkInput","CommandList","CmdkList","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandItem","CmdkItem","CommandSeparator","CmdkSeparator","CommandLoading","CmdkLoading","_$className"],"sources":["../../../../src/components/ui/command/command.tsx"],"sourcesContent":["import {\n CommandDialog as CmdkDialog,\n CommandEmpty as CmdkEmpty,\n CommandGroup as CmdkGroup,\n CommandInput as CmdkInput,\n CommandItem as CmdkItem,\n CommandList as CmdkList,\n CommandLoading as CmdkLoading,\n CommandRoot as CmdkRoot,\n CommandSeparator as CmdkSeparator,\n useCommandState,\n} from 'cmdk-solid'\nimport { Dialog as KobalteDialog } from '@kobalte/core/dialog'\nimport { Search } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { createEffect, createSignal, splitProps } from 'solid-js'\nimport { createDialogFocusRestoration } from '../dialog/dialog'\nimport { menuItem } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n// cmdk emits data-disabled=\"false\" on enabled items, unlike the presence-only\n// attributes Kobalte menu rows use. Apply those shared disabled styles only when\n// cmdk's value is true.\nconst commandItem = menuItem\n .replace('data-[disabled]:pointer-events-none', '')\n .replace('data-[disabled]:text-muted-foreground', '')\n\n/**\n * Command.\n *\n * The command palette: a filtered list of everything the user can do, ranked\n * by fuzzy match. It is the one place in an app where a keyboard-first surface\n * is the *primary* one, so it carries rules the rest of the system does not:\n *\n * - Every item must be reachable by typing its name. If a user has to\n * remember which group it lives in, the palette has failed at its job.\n * - Groups exist for reading, not for navigation. The ranking crosses them.\n * - The empty state is not an apology — it should offer the closest thing\n * the app could guess, or say plainly that nothing matched.\n *\n * cmdk-solid supplies the filter, the scoring, the `aria-activedescendant`\n * wiring and the arrow-key navigation.\n */\nexport function Command(props: ComponentProps<typeof CmdkRoot>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkRoot\n class={cn(\n 'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-xl',\n local.class\n )}\n {...rest}\n />\n )\n}\n\ntype CommandDialogProps = ComponentProps<typeof CmdkDialog> &\n Pick<ComponentProps<typeof KobalteDialog.Content>, 'onCloseAutoFocus' | 'onOpenAutoFocus'>\n\nexport function CommandDialog(props: CommandDialogProps) {\n // cmdk-solid's Dialog does not forward Content autofocus props: unknown\n // props fall through to its Command root. Compose Kobalte's dialog surface\n // here so Escape and other close paths can restore focus to the real opener.\n // Preserve the shared wrapper's `class` contract on the dialog surface;\n // `contentClassName` adds to it, while the nested Command keeps its own API.\n const [local, dialogProps, commandProps] = splitProps(\n props,\n [\n 'class',\n 'contentClassName',\n 'overlayClassName',\n 'container',\n 'onCloseAutoFocus',\n 'onOpenAutoFocus',\n ],\n [\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'id',\n 'modal',\n 'preventScroll',\n 'forceMount',\n 'translations',\n ]\n )\n const [isOpen, setIsOpen] = createSignal(dialogProps.open ?? dialogProps.defaultOpen ?? false)\n\n createEffect(() => {\n if (dialogProps.open !== undefined) setIsOpen(dialogProps.open)\n })\n\n const focus = createDialogFocusRestoration({\n open: isOpen,\n onCloseAutoFocus: local.onCloseAutoFocus,\n onOpenAutoFocus: local.onOpenAutoFocus,\n })\n\n return (\n <KobalteDialog\n {...dialogProps}\n onOpenChange={(open) => {\n setIsOpen(open)\n dialogProps.onOpenChange?.(open)\n }}\n >\n <KobalteDialog.Portal mount={local.container}>\n <KobalteDialog.Overlay cmdk-overlay=\"\" class={local.overlayClassName} />\n <KobalteDialog.Content\n aria-label={commandProps.label}\n cmdk-dialog=\"\"\n role=\"dialog\"\n class={cn(\n 'bg-popover text-popover-foreground fixed top-1/3 left-1/2 z-(--z-dialog) w-full max-w-lg -translate-x-1/2 -translate-y-1/2',\n 'overflow-hidden rounded-xl border border-border shadow-xl',\n 'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95',\n 'data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',\n local.class,\n local.contentClassName\n )}\n onOpenAutoFocus={focus.onOpenAutoFocus}\n onCloseAutoFocus={focus.onCloseAutoFocus}\n >\n <Command {...commandProps} />\n </KobalteDialog.Content>\n </KobalteDialog.Portal>\n </KobalteDialog>\n )\n}\n\nexport function CommandInput(props: ComponentProps<typeof CmdkInput>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <div\n data-slot=\"command-input-wrapper\"\n class=\"flex h-11 items-center gap-2 border-b border-border px-3\"\n >\n <Search class=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <CmdkInput\n class={cn(\n 'h-full w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n </div>\n )\n}\n\n/**\n * The scrolling list.\n *\n * Two DOM corrections, and both are deliberate. cmdk builds a `role=\"listbox\"`\n * whose children include two elements ARIA does not allow there:\n *\n * - a bare `<div cmdk-list-sizer>` with no role, wrapped around every group;\n * - a `<div cmdk-separator role=\"separator\">`, and `separator` is a menu and\n * toolbar role — inside a listbox the only owned elements may be `option`\n * and `group`.\n *\n * Both are pure presentation: the sizer is layout, and the separator is a\n * hairline between groups that the groups already structure. `role=\"presentation\"`\n * is their accurate role rather than a workaround — each is flattened out of the\n * accessibility tree, and the options inside are reached exactly as before.\n *\n * Written onto the mounted nodes rather than through props, because cmdk owns\n * this markup and does not forward a `ref`; in an effect rather than `onMount`,\n * because cmdk renders the sizer with the first item, after the list itself.\n */\nexport function CommandList(props: ComponentProps<typeof CmdkList>) {\n const [local, rest] = splitProps(props, ['class'])\n const [wrapper, setWrapper] = createSignal<HTMLDivElement>()\n const resultCount = useCommandState((state) => state.filtered.count)\n\n createEffect(() => {\n const root = wrapper()\n if (!root) return\n for (const selector of ['[cmdk-list-sizer]', '[cmdk-separator]']) {\n root.querySelector(selector)?.setAttribute('role', 'presentation')\n }\n\n /*\n * A `listbox` must own at least one `option`, so a listbox with nothing in it\n * is invalid ARIA — which is what a search with no matches produces. When\n * there are no results the list is inert, so it becomes presentational and\n * the empty message carries the information instead. It keeps its `id`, so\n * the input's `aria-controls` still resolves.\n */\n root\n .querySelector('[cmdk-list]')\n ?.setAttribute('role', resultCount() > 0 ? 'listbox' : 'presentation')\n })\n\n return (\n <div ref={setWrapper} class=\"contents\">\n <CmdkList\n class={cn('max-h-80 scroll-py-1 overflow-y-auto overflow-x-hidden p-1', local.class)}\n {...rest}\n />\n </div>\n )\n}\n\nexport function CommandEmpty(props: ComponentProps<typeof CmdkEmpty>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkEmpty\n /*\n * A status rather than plain text: when the list is presentational, this is\n * the only thing that tells a screen reader the search matched nothing.\n */\n role=\"status\"\n class={cn('text-muted-foreground py-8 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CommandGroup(props: ComponentProps<typeof CmdkGroup>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkGroup\n class={cn(\n 'text-foreground overflow-hidden p-1',\n '[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-2xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:tracking-wide [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:uppercase',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandItem(props: ComponentProps<typeof CmdkItem>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkItem\n class={cn(\n commandItem,\n 'data-[disabled=true]:pointer-events-none data-[disabled=true]:text-muted-foreground',\n // The selected row sits on the accent rung — the same primary-subtle\n // fill the settings navigation's selected row owns — instead of the\n // popover rung, so what is chosen keeps the accent the checked menus\n // already carry in their indicators.\n 'group/command-item text-popover-foreground data-[selected=true]:bg-primary-subtle data-[selected=true]:text-foreground',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandSeparator(props: ComponentProps<typeof CmdkSeparator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <CmdkSeparator class={cn('bg-border -mx-1 my-1 h-px', local.class)} {...rest} />\n}\n\nexport function CommandLoading(props: ComponentProps<typeof CmdkLoading>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <CmdkLoading\n class={cn('text-muted-foreground py-6 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\n/** The keyboard hint a palette item usually carries. */\nexport function CommandShortcut(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n return (\n <span\n class={cn(\n 'text-muted-foreground ms-auto font-code text-code tracking-widest group-data-[selected=true]/command-item:text-foreground',\n props.class\n )}\n >\n {props.children}\n </span>\n )\n}\n\n/**\n * The status line a command surface reports under its list: searching, offline,\n * a partial result caveat. The copy and the live-role semantics (`status`,\n * `alert`) are the caller's — a palette's failure modes are app facts — but the\n * line's shape is not something every caller should redraw.\n */\nexport function CommandStatus(props: ComponentProps<'p'>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <p\n data-slot=\"command-status\"\n class={cn('text-muted-foreground px-4 py-4 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\n/**\n * The keyboard hint a palette footer carries, right-aligned under the list so\n * it reads as furniture rather than a result. Muted on purpose: the arrows are\n * what the user has already been doing by the time they read it.\n */\nexport function CommandHint(props: ComponentProps<'p'>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <p\n data-slot=\"command-hint\"\n class={cn('text-muted-foreground px-4 pb-1.5 text-right text-xs', local.class)}\n {...rest}\n />\n )\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, } from './command';
1
+ export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus, } from './command';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/command/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/command/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,WAAW,CAAA"}
@@ -1,2 +1,2 @@
1
- import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut } from "./command.js";
2
- export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut };
1
+ import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus } from "./command.js";
2
+ export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus };
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import { ValueCombobox } from "./components/ui/combobox/value-combobox.js";
22
22
  import { CodeBlock, InlineCode, TALL_CODE_BLOCK_PX } from "./components/ui/code-block/code-block.js";
23
23
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./components/ui/tooltip/tooltip.js";
24
24
  import { Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "./components/ui/dialog/dialog.js";
25
- import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut } from "./components/ui/command/command.js";
25
+ import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus } from "./components/ui/command/command.js";
26
26
  import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from "./components/ui/context-menu/context-menu.js";
27
27
  import { DiffBlock, DiffSummary, diffLineVariants, diffStats, diffTargetPath, parseDiff } from "./components/ui/diff-block/diff-block.js";
28
28
  import { DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection } from "./components/ui/detail-panel/detail-panel.js";
@@ -133,4 +133,4 @@ import { AboutDialog } from "./components/composites/about-dialog/about-dialog.j
133
133
  import { HelpCenter } from "./components/composites/help-center/help-center.js";
134
134
  import { WorkspaceMark } from "./components/composites/workspace-mark/workspace-mark.js";
135
135
  import { writeClipboardText } from "./lib/clipboard.js";
136
- export { APPEARANCE_EDITOR_FONT_AXES, APPEARANCE_EDITOR_FONT_SIZE_MAX, APPEARANCE_EDITOR_FONT_SIZE_MIN, AboutDialog, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, ActionButton, Alert, AlertAction, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AnnotationSurface, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearanceEditorActions, AppearanceFontSettingsGroup, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogBrowser, CatalogDetail, CatalogDetailSection, ChatComposer, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposerAttachmentButton, ComposerHint, ComposerMenu, ComposerMenuItem, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContextualSidebar, ConversationAvatar, ConversationPane, ConversationSurface, DEFAULT_APPEARANCE_EDITOR_FONT_SETTINGS, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, EntityIcon, FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FloatingPreview, FormField, Heading, HelpCenter, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputControl, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdChord, KbdGroup, Label, ListGroup, ListRow, ListRowControl, MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, NativeSelect, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, NumberField, OrbitItem, OrbitLayout, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, PixelResizeHandle, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, SceneControls, ScrollArea, SecretInputGroup, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsLayout, SettingsNavigation, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavLabel, SidebarNavResizeHandle, SidebarNavRow, SidebarNavSection, SidebarNavTitle, Skeleton, SkipLink, Slider, Spinner, SplitLayout, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, TextLink, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemeModeToggle, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, TranscriptComposition, Tree, TreeRow, TreeRowActions, UpdateChannelControl, UpdateDialog, ValueCombobox, VirtualWindow, WorkspaceMark, accentPresets, alertVariants, allTokens, appearancePreviewThemes, applyAppearanceFontSettings, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, cardVariants, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, closePane, cn, colorTokens, computeLayoutFrames, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, countLeaves, countLines, createAppMenuItems, createLayoutState, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, expandAll, findTokenRanges, focusPane, fontOptions, fontSettingsBootstrapScript, formatBytes, formatReleaseDate, formatToken, headingElement, headingVariants, initialsFrom, inlineScriptLiteral, isPasteBlock, isThemeAccentId, itemVariants, kbdChordKeys, kbdGroupVariants, kbdVariants, keyedRows, layoutDepth, listLeaves, monogram, motionTokens, movePane, neighborLeaf, nextSeq, normalizeAppearanceEditorFontSettings, normalizeAppearanceEditorFontSize, normalizeLayout, parseDiff, plainTextFromMarkdown, platformModifierKey, pruneBlocks, radiusTokens, recollapsePastes, remapCarriedBlocks, resizeFloatingPreview, resizePreviewMiniPlayer, resizeSplit, resolveAccentPreset, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame, resolvedDensity, searchShortcutKeyshortcuts, searchShortcutLabel, sheetVariants, shouldCollapse, sidebarNavItemClass, sidebarNavItemStateClass, splitPane, splitPaneBalanced, statusDotVariants, stripTrailingBlankLines, surfaceInteractive, swapPanes, textElement, textVariants, textareaVariants, themeAccentsFor, themeById, themeCssVariables, themeFamilies, themeRecordById, themeRecords, themeScript, themesForAppearance, toast, toaster, toggleVariants, tokenRangeAt, transcriptDisclosureKey, typographyTokens, undoClosePane, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, withAccent, writeClipboardText, zIndexTokens };
136
+ export { APPEARANCE_EDITOR_FONT_AXES, APPEARANCE_EDITOR_FONT_SIZE_MAX, APPEARANCE_EDITOR_FONT_SIZE_MIN, AboutDialog, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, ActionButton, Alert, AlertAction, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AnnotationSurface, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearanceEditorActions, AppearanceFontSettingsGroup, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogBrowser, CatalogDetail, CatalogDetailSection, ChatComposer, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandHint, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, CommandStatus, ComposerAttachmentButton, ComposerHint, ComposerMenu, ComposerMenuItem, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContextualSidebar, ConversationAvatar, ConversationPane, ConversationSurface, DEFAULT_APPEARANCE_EDITOR_FONT_SETTINGS, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, EntityIcon, FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FloatingPreview, FormField, Heading, HelpCenter, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputControl, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdChord, KbdGroup, Label, ListGroup, ListRow, ListRowControl, MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, NativeSelect, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, NumberField, OrbitItem, OrbitLayout, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, PixelResizeHandle, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, SceneControls, ScrollArea, SecretInputGroup, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsLayout, SettingsNavigation, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavLabel, SidebarNavResizeHandle, SidebarNavRow, SidebarNavSection, SidebarNavTitle, Skeleton, SkipLink, Slider, Spinner, SplitLayout, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, TextLink, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemeModeToggle, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, TranscriptComposition, Tree, TreeRow, TreeRowActions, UpdateChannelControl, UpdateDialog, ValueCombobox, VirtualWindow, WorkspaceMark, accentPresets, alertVariants, allTokens, appearancePreviewThemes, applyAppearanceFontSettings, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, cardVariants, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, closePane, cn, colorTokens, computeLayoutFrames, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, countLeaves, countLines, createAppMenuItems, createLayoutState, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, expandAll, findTokenRanges, focusPane, fontOptions, fontSettingsBootstrapScript, formatBytes, formatReleaseDate, formatToken, headingElement, headingVariants, initialsFrom, inlineScriptLiteral, isPasteBlock, isThemeAccentId, itemVariants, kbdChordKeys, kbdGroupVariants, kbdVariants, keyedRows, layoutDepth, listLeaves, monogram, motionTokens, movePane, neighborLeaf, nextSeq, normalizeAppearanceEditorFontSettings, normalizeAppearanceEditorFontSize, normalizeLayout, parseDiff, plainTextFromMarkdown, platformModifierKey, pruneBlocks, radiusTokens, recollapsePastes, remapCarriedBlocks, resizeFloatingPreview, resizePreviewMiniPlayer, resizeSplit, resolveAccentPreset, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame, resolvedDensity, searchShortcutKeyshortcuts, searchShortcutLabel, sheetVariants, shouldCollapse, sidebarNavItemClass, sidebarNavItemStateClass, splitPane, splitPaneBalanced, statusDotVariants, stripTrailingBlankLines, surfaceInteractive, swapPanes, textElement, textVariants, textareaVariants, themeAccentsFor, themeById, themeCssVariables, themeFamilies, themeRecordById, themeRecords, themeScript, themesForAppearance, toast, toaster, toggleVariants, tokenRangeAt, transcriptDisclosureKey, typographyTokens, undoClosePane, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, withAccent, writeClipboardText, zIndexTokens };
@@ -84,6 +84,14 @@ export type AccountMenuProps = {
84
84
  platform?: 'desktop' | 'web'
85
85
  /** Whether a session exists. Decides the sign-in/sign-out row. */
86
86
  authenticated: boolean
87
+ /**
88
+ * Draw the pending-update indicator: an accent dot on the trigger and on the
89
+ * `updates` row — the id `createAppMenuItems` mints, the same convention the
90
+ * fallback icons follow — and extend both accessible names with "update
91
+ * available", because the dot itself carries no text. The updater remains the
92
+ * caller's: the prop only mirrors its state into the menu.
93
+ */
94
+ updateAvailable?: boolean
87
95
  /** Local-only applications can omit the session actions altogether. */
88
96
  showSession?: boolean
89
97
  /** Disable the session row while a sign-in or sign-out is in flight. */
@@ -116,6 +124,7 @@ export function AccountMenu(props: AccountMenuProps) {
116
124
  'items',
117
125
  'platform',
118
126
  'authenticated',
127
+ 'updateAvailable',
119
128
  'showSession',
120
129
  'busy',
121
130
  'label',
@@ -142,6 +151,21 @@ export function AccountMenu(props: AccountMenuProps) {
142
151
  const visible = () =>
143
152
  local.items.filter((item) => !item.platform || item.platform === (local.platform ?? 'desktop'))
144
153
 
154
+ // The pending update reaches the user twice on each surface: as a dot and as
155
+ // words. The dot is aria-hidden, so the accessible names carry the state —
156
+ // which is why the names are extended here rather than left to the caller.
157
+ const triggerName = () =>
158
+ `${local.label ?? 'Account and settings'}${local.updateAvailable ? ', update available' : ''}`
159
+ const updateDot = () => (
160
+ <Show when={local.updateAvailable}>
161
+ <span
162
+ data-slot="account-menu-update-dot"
163
+ aria-hidden="true"
164
+ class="absolute top-1.5 right-2.5 size-2 rounded-full bg-primary"
165
+ />
166
+ </Show>
167
+ )
168
+
145
169
  // Built by reference at each return, not once up front: Solid fixes a node's
146
170
  // owner chain when the JSX expression runs, and an eagerly created tree would
147
171
  // never see the Tooltip provider below — Kobalte's TooltipTrigger then throws
@@ -164,13 +188,15 @@ export function AccountMenu(props: AccountMenuProps) {
164
188
  ref={(element: HTMLButtonElement) => (trigger = element)}
165
189
  variant="ghost"
166
190
  size={local.size ?? 'icon-md'}
167
- class={cn('text-muted-foreground', local.class)}
168
- aria-label={local.label ?? 'Account and settings'}
191
+ class={cn('relative text-muted-foreground', local.class)}
192
+ data-slot="account-menu-trigger"
193
+ aria-label={triggerName()}
169
194
  onFocus={() => local.onIntent?.()}
170
195
  onPointerEnter={() => local.onIntent?.()}
171
196
  {...rest}
172
197
  >
173
198
  <UserRound aria-hidden="true" />
199
+ {updateDot()}
174
200
  </TooltipTrigger>
175
201
  }
176
202
  >
@@ -180,13 +206,15 @@ export function AccountMenu(props: AccountMenuProps) {
180
206
  <DropdownMenuTrigger
181
207
  as={SideRailButton}
182
208
  ref={(element: HTMLButtonElement) => (trigger = element)}
183
- label={local.label ?? 'Account and settings'}
184
- class={local.class}
209
+ label={triggerName()}
210
+ class={cn('relative', local.class)}
211
+ data-slot="account-menu-trigger"
185
212
  onFocus={() => local.onIntent?.()}
186
213
  onPointerEnter={() => local.onIntent?.()}
187
214
  {...rest}
188
215
  >
189
216
  <UserRound aria-hidden="true" />
217
+ {updateDot()}
190
218
  </DropdownMenuTrigger>
191
219
  </Show>
192
220
  <DropdownMenuContent
@@ -211,6 +239,11 @@ export function AccountMenu(props: AccountMenuProps) {
211
239
  {(item) => (
212
240
  <DropdownMenuItem
213
241
  disabled={item.disabled}
242
+ aria-label={
243
+ local.updateAvailable && item.id === 'updates'
244
+ ? `${item.label}, update available`
245
+ : undefined
246
+ }
214
247
  onSelect={() => {
215
248
  pendingAfterClose = item.onSelectAfterClose
216
249
  ? { callback: item.onSelectAfterClose }
@@ -222,6 +255,13 @@ export function AccountMenu(props: AccountMenuProps) {
222
255
  >
223
256
  {item.icon ?? renderFallbackIcon(item.id)}
224
257
  <span>{item.label}</span>
258
+ <Show when={local.updateAvailable && item.id === 'updates'}>
259
+ <span
260
+ data-slot="account-menu-update-dot"
261
+ aria-hidden="true"
262
+ class="ms-auto size-2 shrink-0 rounded-full bg-primary"
263
+ />
264
+ </Show>
225
265
  </DropdownMenuItem>
226
266
  )}
227
267
  </For>
@@ -37,11 +37,14 @@ export const buttonVariants = cva(
37
37
  ghost: 'text-foreground hover:bg-surface-hover',
38
38
  /**
39
39
  * A ghost that opens something: a sheet, menu or popover trigger in a
40
- * toolbar. While its surface is open it holds the menubar's pressed
41
- * rung, so the open control never reads identical to its closed
42
- * neighbours.
40
+ * toolbar. While its surface is open it holds the accent's own tint —
41
+ * the same treatment that drives the side rail's active destination —
42
+ * so the open control never reads identical to its closed neighbours
43
+ * and the app's pressed chrome reads as one accent chroma. The
44
+ * compound hover keeps the tint when an open control is pointed at.
43
45
  */
44
- toolbar: 'text-foreground hover:bg-surface-hover data-[expanded]:bg-surface-active',
46
+ toolbar:
47
+ 'text-foreground hover:bg-surface-hover data-[expanded]:bg-primary-subtle data-[expanded]:text-primary data-[expanded]:hover:bg-primary-subtle',
45
48
  /** A tinted primary, for a secondary action inside a primary flow. */
46
49
  subtle: 'bg-primary-subtle text-primary hover:bg-primary-subtle/80',
47
50
  success: 'bg-success text-success-foreground hover:bg-success/90',
@@ -286,3 +286,38 @@ export function CommandShortcut(props: {
286
286
  </span>
287
287
  )
288
288
  }
289
+
290
+ /**
291
+ * The status line a command surface reports under its list: searching, offline,
292
+ * a partial result caveat. The copy and the live-role semantics (`status`,
293
+ * `alert`) are the caller's — a palette's failure modes are app facts — but the
294
+ * line's shape is not something every caller should redraw.
295
+ */
296
+ export function CommandStatus(props: ComponentProps<'p'>) {
297
+ const [local, rest] = splitProps(props, ['class'])
298
+
299
+ return (
300
+ <p
301
+ data-slot="command-status"
302
+ class={cn('text-muted-foreground px-4 py-4 text-center text-sm', local.class)}
303
+ {...rest}
304
+ />
305
+ )
306
+ }
307
+
308
+ /**
309
+ * The keyboard hint a palette footer carries, right-aligned under the list so
310
+ * it reads as furniture rather than a result. Muted on purpose: the arrows are
311
+ * what the user has already been doing by the time they read it.
312
+ */
313
+ export function CommandHint(props: ComponentProps<'p'>) {
314
+ const [local, rest] = splitProps(props, ['class'])
315
+
316
+ return (
317
+ <p
318
+ data-slot="command-hint"
319
+ class={cn('text-muted-foreground px-4 pb-1.5 text-right text-xs', local.class)}
320
+ {...rest}
321
+ />
322
+ )
323
+ }
@@ -3,10 +3,12 @@ export {
3
3
  CommandDialog,
4
4
  CommandEmpty,
5
5
  CommandGroup,
6
+ CommandHint,
6
7
  CommandInput,
7
8
  CommandItem,
8
9
  CommandList,
9
10
  CommandLoading,
10
11
  CommandSeparator,
11
12
  CommandShortcut,
13
+ CommandStatus,
12
14
  } from './command'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/ui",
3
- "version": "0.121.0",
3
+ "version": "0.122.1",
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",
@@ -84,6 +84,14 @@ export type AccountMenuProps = {
84
84
  platform?: 'desktop' | 'web'
85
85
  /** Whether a session exists. Decides the sign-in/sign-out row. */
86
86
  authenticated: boolean
87
+ /**
88
+ * Draw the pending-update indicator: an accent dot on the trigger and on the
89
+ * `updates` row — the id `createAppMenuItems` mints, the same convention the
90
+ * fallback icons follow — and extend both accessible names with "update
91
+ * available", because the dot itself carries no text. The updater remains the
92
+ * caller's: the prop only mirrors its state into the menu.
93
+ */
94
+ updateAvailable?: boolean
87
95
  /** Local-only applications can omit the session actions altogether. */
88
96
  showSession?: boolean
89
97
  /** Disable the session row while a sign-in or sign-out is in flight. */
@@ -116,6 +124,7 @@ export function AccountMenu(props: AccountMenuProps) {
116
124
  'items',
117
125
  'platform',
118
126
  'authenticated',
127
+ 'updateAvailable',
119
128
  'showSession',
120
129
  'busy',
121
130
  'label',
@@ -142,6 +151,21 @@ export function AccountMenu(props: AccountMenuProps) {
142
151
  const visible = () =>
143
152
  local.items.filter((item) => !item.platform || item.platform === (local.platform ?? 'desktop'))
144
153
 
154
+ // The pending update reaches the user twice on each surface: as a dot and as
155
+ // words. The dot is aria-hidden, so the accessible names carry the state —
156
+ // which is why the names are extended here rather than left to the caller.
157
+ const triggerName = () =>
158
+ `${local.label ?? 'Account and settings'}${local.updateAvailable ? ', update available' : ''}`
159
+ const updateDot = () => (
160
+ <Show when={local.updateAvailable}>
161
+ <span
162
+ data-slot="account-menu-update-dot"
163
+ aria-hidden="true"
164
+ class="absolute top-1.5 right-2.5 size-2 rounded-full bg-primary"
165
+ />
166
+ </Show>
167
+ )
168
+
145
169
  // Built by reference at each return, not once up front: Solid fixes a node's
146
170
  // owner chain when the JSX expression runs, and an eagerly created tree would
147
171
  // never see the Tooltip provider below — Kobalte's TooltipTrigger then throws
@@ -164,13 +188,15 @@ export function AccountMenu(props: AccountMenuProps) {
164
188
  ref={(element: HTMLButtonElement) => (trigger = element)}
165
189
  variant="ghost"
166
190
  size={local.size ?? 'icon-md'}
167
- class={cn('text-muted-foreground', local.class)}
168
- aria-label={local.label ?? 'Account and settings'}
191
+ class={cn('relative text-muted-foreground', local.class)}
192
+ data-slot="account-menu-trigger"
193
+ aria-label={triggerName()}
169
194
  onFocus={() => local.onIntent?.()}
170
195
  onPointerEnter={() => local.onIntent?.()}
171
196
  {...rest}
172
197
  >
173
198
  <UserRound aria-hidden="true" />
199
+ {updateDot()}
174
200
  </TooltipTrigger>
175
201
  }
176
202
  >
@@ -180,13 +206,15 @@ export function AccountMenu(props: AccountMenuProps) {
180
206
  <DropdownMenuTrigger
181
207
  as={SideRailButton}
182
208
  ref={(element: HTMLButtonElement) => (trigger = element)}
183
- label={local.label ?? 'Account and settings'}
184
- class={local.class}
209
+ label={triggerName()}
210
+ class={cn('relative', local.class)}
211
+ data-slot="account-menu-trigger"
185
212
  onFocus={() => local.onIntent?.()}
186
213
  onPointerEnter={() => local.onIntent?.()}
187
214
  {...rest}
188
215
  >
189
216
  <UserRound aria-hidden="true" />
217
+ {updateDot()}
190
218
  </DropdownMenuTrigger>
191
219
  </Show>
192
220
  <DropdownMenuContent
@@ -211,6 +239,11 @@ export function AccountMenu(props: AccountMenuProps) {
211
239
  {(item) => (
212
240
  <DropdownMenuItem
213
241
  disabled={item.disabled}
242
+ aria-label={
243
+ local.updateAvailable && item.id === 'updates'
244
+ ? `${item.label}, update available`
245
+ : undefined
246
+ }
214
247
  onSelect={() => {
215
248
  pendingAfterClose = item.onSelectAfterClose
216
249
  ? { callback: item.onSelectAfterClose }
@@ -222,6 +255,13 @@ export function AccountMenu(props: AccountMenuProps) {
222
255
  >
223
256
  {item.icon ?? renderFallbackIcon(item.id)}
224
257
  <span>{item.label}</span>
258
+ <Show when={local.updateAvailable && item.id === 'updates'}>
259
+ <span
260
+ data-slot="account-menu-update-dot"
261
+ aria-hidden="true"
262
+ class="ms-auto size-2 shrink-0 rounded-full bg-primary"
263
+ />
264
+ </Show>
225
265
  </DropdownMenuItem>
226
266
  )}
227
267
  </For>
@@ -37,11 +37,14 @@ export const buttonVariants = cva(
37
37
  ghost: 'text-foreground hover:bg-surface-hover',
38
38
  /**
39
39
  * A ghost that opens something: a sheet, menu or popover trigger in a
40
- * toolbar. While its surface is open it holds the menubar's pressed
41
- * rung, so the open control never reads identical to its closed
42
- * neighbours.
40
+ * toolbar. While its surface is open it holds the accent's own tint —
41
+ * the same treatment that drives the side rail's active destination —
42
+ * so the open control never reads identical to its closed neighbours
43
+ * and the app's pressed chrome reads as one accent chroma. The
44
+ * compound hover keeps the tint when an open control is pointed at.
43
45
  */
44
- toolbar: 'text-foreground hover:bg-surface-hover data-[expanded]:bg-surface-active',
46
+ toolbar:
47
+ 'text-foreground hover:bg-surface-hover data-[expanded]:bg-primary-subtle data-[expanded]:text-primary data-[expanded]:hover:bg-primary-subtle',
45
48
  /** A tinted primary, for a secondary action inside a primary flow. */
46
49
  subtle: 'bg-primary-subtle text-primary hover:bg-primary-subtle/80',
47
50
  success: 'bg-success text-success-foreground hover:bg-success/90',
@@ -286,3 +286,38 @@ export function CommandShortcut(props: {
286
286
  </span>
287
287
  )
288
288
  }
289
+
290
+ /**
291
+ * The status line a command surface reports under its list: searching, offline,
292
+ * a partial result caveat. The copy and the live-role semantics (`status`,
293
+ * `alert`) are the caller's — a palette's failure modes are app facts — but the
294
+ * line's shape is not something every caller should redraw.
295
+ */
296
+ export function CommandStatus(props: ComponentProps<'p'>) {
297
+ const [local, rest] = splitProps(props, ['class'])
298
+
299
+ return (
300
+ <p
301
+ data-slot="command-status"
302
+ class={cn('text-muted-foreground px-4 py-4 text-center text-sm', local.class)}
303
+ {...rest}
304
+ />
305
+ )
306
+ }
307
+
308
+ /**
309
+ * The keyboard hint a palette footer carries, right-aligned under the list so
310
+ * it reads as furniture rather than a result. Muted on purpose: the arrows are
311
+ * what the user has already been doing by the time they read it.
312
+ */
313
+ export function CommandHint(props: ComponentProps<'p'>) {
314
+ const [local, rest] = splitProps(props, ['class'])
315
+
316
+ return (
317
+ <p
318
+ data-slot="command-hint"
319
+ class={cn('text-muted-foreground px-4 pb-1.5 text-right text-xs', local.class)}
320
+ {...rest}
321
+ />
322
+ )
323
+ }
@@ -3,10 +3,12 @@ export {
3
3
  CommandDialog,
4
4
  CommandEmpty,
5
5
  CommandGroup,
6
+ CommandHint,
6
7
  CommandInput,
7
8
  CommandItem,
8
9
  CommandList,
9
10
  CommandLoading,
10
11
  CommandSeparator,
11
12
  CommandShortcut,
13
+ CommandStatus,
12
14
  } from './command'