@ai-matrx/design-system 0.86.328 → 0.86.330
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -8281
- package/dist/item.cjs +3 -27
- package/dist/item.cjs.map +1 -1
- package/dist/item.d.cts +1 -9
- package/dist/item.d.ts +1 -9
- package/dist/item.js +3 -27
- package/dist/item.js.map +1 -1
- package/dist/menu-look.cjs +27 -8
- package/dist/menu-look.cjs.map +1 -1
- package/dist/menu-look.css +29 -0
- package/dist/menu-look.d.cts +25 -7
- package/dist/menu-look.d.ts +25 -7
- package/dist/menu-look.js +27 -8
- package/dist/menu-look.js.map +1 -1
- package/dist/writing-field.cjs +225 -524
- package/dist/writing-field.cjs.map +1 -1
- package/dist/writing-field.d.cts +5 -49
- package/dist/writing-field.d.ts +5 -49
- package/dist/writing-field.js +97 -393
- package/dist/writing-field.js.map +1 -1
- package/package.json +2 -2
package/dist/item.d.cts
CHANGED
|
@@ -402,12 +402,6 @@ interface ProductSidebarTopSearch {
|
|
|
402
402
|
/** Screen-reader name ("Search conversations"). */
|
|
403
403
|
ariaLabel: string;
|
|
404
404
|
placeholder?: string | undefined;
|
|
405
|
-
/**
|
|
406
|
-
* Searches the places themselves: while the field holds a query the rows become every place
|
|
407
|
-
* (chosen, More, More groups and this pool) whose label matches, and Enter opens the first.
|
|
408
|
-
* Absent = the host searches its own list (the conversation sidebar) and the rows stay.
|
|
409
|
-
*/
|
|
410
|
-
pool?: readonly SidebarPlace[] | undefined;
|
|
411
405
|
}
|
|
412
406
|
interface ProductSidebarTopProps {
|
|
413
407
|
/** Above Search: one status line (a refusal, a notice). Render it only when it has something to say. */
|
|
@@ -440,8 +434,6 @@ declare function splitSidebarPlaces(places: readonly SidebarPlace[], chosen: rea
|
|
|
440
434
|
above: SidebarPlace[];
|
|
441
435
|
more: SidebarPlace[];
|
|
442
436
|
};
|
|
443
|
-
/** Every place a search can reach, de-duplicated by id, matched on its label (and its sub-list). */
|
|
444
|
-
declare function matchSidebarPlaces(pool: readonly SidebarPlace[], query: string): SidebarPlace[];
|
|
445
437
|
declare function ProductSidebarTop({ status, search, newItem, places, chosen, onOpenPlace, moreGroups, onEditSidebar, children, sourceFeature, className, }: ProductSidebarTopProps): react.JSX.Element;
|
|
446
438
|
/** "Above More": which places sit above More (the host saves it on its layered knob). */
|
|
447
439
|
declare function SidebarPlacesChooser({ places, chosen, onChange, title, }: {
|
|
@@ -462,4 +454,4 @@ declare function SidebarEditDialog({ open, onOpenChange, onSave, refusal, saveLa
|
|
|
462
454
|
children: ReactNode;
|
|
463
455
|
}): react.JSX.Element;
|
|
464
456
|
|
|
465
|
-
export { ItemContextMenu, type ItemContextMenuProps, type ItemEntityRef, ItemMenu, type ItemMenuCheckbox, type ItemMenuCommand, type ItemMenuConfig, type ItemMenuConfigInput, type ItemMenuEntry, type ItemMenuHeader, type ItemMenuHost, ItemMenuHostProvider, type ItemMenuIcon, type ItemMenuLink, type ItemMenuProps, type ItemMenuSection, type ItemMenuSubmenu, type ItemMenuSurface, type ItemMenuToast, type ItemMenuTone, ItemRow, type ItemRowDisclosure, type ItemRowProps, type ItemRowRename, type ItemRowSize, type ItemToastPromise, ProductSidebarTop, type ProductSidebarTopProps, type ProductSidebarTopSearch, SidebarEditDialog, type SidebarMoreGroup, type SidebarPlace, SidebarPlacesChooser, isCheckbox, isCommand, isLink, isSubmenu,
|
|
457
|
+
export { ItemContextMenu, type ItemContextMenuProps, type ItemEntityRef, ItemMenu, type ItemMenuCheckbox, type ItemMenuCommand, type ItemMenuConfig, type ItemMenuConfigInput, type ItemMenuEntry, type ItemMenuHeader, type ItemMenuHost, ItemMenuHostProvider, type ItemMenuIcon, type ItemMenuLink, type ItemMenuProps, type ItemMenuSection, type ItemMenuSubmenu, type ItemMenuSurface, type ItemMenuToast, type ItemMenuTone, ItemRow, type ItemRowDisclosure, type ItemRowProps, type ItemRowRename, type ItemRowSize, type ItemToastPromise, ProductSidebarTop, type ProductSidebarTopProps, type ProductSidebarTopSearch, SidebarEditDialog, type SidebarMoreGroup, type SidebarPlace, SidebarPlacesChooser, isCheckbox, isCommand, isLink, isSubmenu, resolveItemMenuConfig, runCommand, runToggle, splitSidebarPlaces, useItemMenuHost };
|
package/dist/item.d.ts
CHANGED
|
@@ -402,12 +402,6 @@ interface ProductSidebarTopSearch {
|
|
|
402
402
|
/** Screen-reader name ("Search conversations"). */
|
|
403
403
|
ariaLabel: string;
|
|
404
404
|
placeholder?: string | undefined;
|
|
405
|
-
/**
|
|
406
|
-
* Searches the places themselves: while the field holds a query the rows become every place
|
|
407
|
-
* (chosen, More, More groups and this pool) whose label matches, and Enter opens the first.
|
|
408
|
-
* Absent = the host searches its own list (the conversation sidebar) and the rows stay.
|
|
409
|
-
*/
|
|
410
|
-
pool?: readonly SidebarPlace[] | undefined;
|
|
411
405
|
}
|
|
412
406
|
interface ProductSidebarTopProps {
|
|
413
407
|
/** Above Search: one status line (a refusal, a notice). Render it only when it has something to say. */
|
|
@@ -440,8 +434,6 @@ declare function splitSidebarPlaces(places: readonly SidebarPlace[], chosen: rea
|
|
|
440
434
|
above: SidebarPlace[];
|
|
441
435
|
more: SidebarPlace[];
|
|
442
436
|
};
|
|
443
|
-
/** Every place a search can reach, de-duplicated by id, matched on its label (and its sub-list). */
|
|
444
|
-
declare function matchSidebarPlaces(pool: readonly SidebarPlace[], query: string): SidebarPlace[];
|
|
445
437
|
declare function ProductSidebarTop({ status, search, newItem, places, chosen, onOpenPlace, moreGroups, onEditSidebar, children, sourceFeature, className, }: ProductSidebarTopProps): react.JSX.Element;
|
|
446
438
|
/** "Above More": which places sit above More (the host saves it on its layered knob). */
|
|
447
439
|
declare function SidebarPlacesChooser({ places, chosen, onChange, title, }: {
|
|
@@ -462,4 +454,4 @@ declare function SidebarEditDialog({ open, onOpenChange, onSave, refusal, saveLa
|
|
|
462
454
|
children: ReactNode;
|
|
463
455
|
}): react.JSX.Element;
|
|
464
456
|
|
|
465
|
-
export { ItemContextMenu, type ItemContextMenuProps, type ItemEntityRef, ItemMenu, type ItemMenuCheckbox, type ItemMenuCommand, type ItemMenuConfig, type ItemMenuConfigInput, type ItemMenuEntry, type ItemMenuHeader, type ItemMenuHost, ItemMenuHostProvider, type ItemMenuIcon, type ItemMenuLink, type ItemMenuProps, type ItemMenuSection, type ItemMenuSubmenu, type ItemMenuSurface, type ItemMenuToast, type ItemMenuTone, ItemRow, type ItemRowDisclosure, type ItemRowProps, type ItemRowRename, type ItemRowSize, type ItemToastPromise, ProductSidebarTop, type ProductSidebarTopProps, type ProductSidebarTopSearch, SidebarEditDialog, type SidebarMoreGroup, type SidebarPlace, SidebarPlacesChooser, isCheckbox, isCommand, isLink, isSubmenu,
|
|
457
|
+
export { ItemContextMenu, type ItemContextMenuProps, type ItemEntityRef, ItemMenu, type ItemMenuCheckbox, type ItemMenuCommand, type ItemMenuConfig, type ItemMenuConfigInput, type ItemMenuEntry, type ItemMenuHeader, type ItemMenuHost, ItemMenuHostProvider, type ItemMenuIcon, type ItemMenuLink, type ItemMenuProps, type ItemMenuSection, type ItemMenuSubmenu, type ItemMenuSurface, type ItemMenuToast, type ItemMenuTone, ItemRow, type ItemRowDisclosure, type ItemRowProps, type ItemRowRename, type ItemRowSize, type ItemToastPromise, ProductSidebarTop, type ProductSidebarTopProps, type ProductSidebarTopSearch, SidebarEditDialog, type SidebarMoreGroup, type SidebarPlace, SidebarPlacesChooser, isCheckbox, isCommand, isLink, isSubmenu, resolveItemMenuConfig, runCommand, runToggle, splitSidebarPlaces, useItemMenuHost };
|
package/dist/item.js
CHANGED
|
@@ -78,21 +78,6 @@ function splitSidebarPlaces(places, chosen) {
|
|
|
78
78
|
const aboveIds = new Set(above.map((p) => p.id));
|
|
79
79
|
return { above, more: places.filter((p) => !aboveIds.has(p.id)) };
|
|
80
80
|
}
|
|
81
|
-
function matchSidebarPlaces(pool, query) {
|
|
82
|
-
const q = query.trim().toLowerCase();
|
|
83
|
-
if (!q) return [];
|
|
84
|
-
const seen = /* @__PURE__ */ new Set();
|
|
85
|
-
const out = [];
|
|
86
|
-
const visit = (p) => {
|
|
87
|
-
if (!seen.has(p.id) && p.label.toLowerCase().includes(q)) {
|
|
88
|
-
seen.add(p.id);
|
|
89
|
-
out.push({ ...p, children: void 0 });
|
|
90
|
-
}
|
|
91
|
-
p.children?.forEach(visit);
|
|
92
|
-
};
|
|
93
|
-
pool.forEach(visit);
|
|
94
|
-
return out;
|
|
95
|
-
}
|
|
96
81
|
function ProductSidebarTop({
|
|
97
82
|
status,
|
|
98
83
|
search,
|
|
@@ -108,19 +93,11 @@ function ProductSidebarTop({
|
|
|
108
93
|
}) {
|
|
109
94
|
const { above, more } = splitSidebarPlaces(places, chosen);
|
|
110
95
|
const groups = (moreGroups ?? []).filter((g) => g.places.length > 0);
|
|
111
|
-
const searching = !!search?.pool && search.value.trim().length > 0;
|
|
112
|
-
const matches = searching ? matchSidebarPlaces([...places, ...groups.flatMap((g) => g.places), ...search?.pool ?? []], search.value) : [];
|
|
113
96
|
const open = (place) => onOpenPlace?.(place);
|
|
114
97
|
const onSearchKeyDown = (e) => {
|
|
115
|
-
if (
|
|
116
|
-
if (e.key === "Escape" && search.value) {
|
|
98
|
+
if (search && e.key === "Escape" && search.value) {
|
|
117
99
|
e.preventDefault();
|
|
118
100
|
search.onChange("");
|
|
119
|
-
} else if (e.key === "Enter" && searching && matches[0]) {
|
|
120
|
-
e.preventDefault();
|
|
121
|
-
const first = matches[0];
|
|
122
|
-
if (onOpenPlace) open(first);
|
|
123
|
-
else if (first.href && typeof window !== "undefined") window.location.assign(first.href);
|
|
124
101
|
}
|
|
125
102
|
};
|
|
126
103
|
return /* @__PURE__ */ jsxs("div", { "data-product-sidebar-top": "", className: cn("flex shrink-0 flex-col gap-1 px-2 pb-1 pt-2", className), children: [
|
|
@@ -138,7 +115,7 @@ function ProductSidebarTop({
|
|
|
138
115
|
className: "h-8"
|
|
139
116
|
}
|
|
140
117
|
) : null,
|
|
141
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", search && "pt-1"), children: [
|
|
142
119
|
newItem ? /* @__PURE__ */ jsx(
|
|
143
120
|
ItemRow,
|
|
144
121
|
{
|
|
@@ -177,7 +154,7 @@ function ProductSidebarTop({
|
|
|
177
154
|
] }) : null
|
|
178
155
|
] })
|
|
179
156
|
] }) : null
|
|
180
|
-
] })
|
|
157
|
+
] }),
|
|
181
158
|
children
|
|
182
159
|
] });
|
|
183
160
|
}
|
|
@@ -309,7 +286,6 @@ export {
|
|
|
309
286
|
isCommand,
|
|
310
287
|
isLink,
|
|
311
288
|
isSubmenu,
|
|
312
|
-
matchSidebarPlaces,
|
|
313
289
|
resolveItemMenuConfig,
|
|
314
290
|
runCommand,
|
|
315
291
|
runToggle,
|
package/dist/item.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/item/ProductSidebarTop.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * THE TOP OF EVERY PRODUCT SIDEBAR (Arman, 2026-10-22: \"This is a very important missing thing that\n * we have to establish or our system will fail.\" — common-docs projects/app-frame/VISION.md).\n *\n * Extracted from the conversation sidebar's top (`@ai-matrx/chat` ConversationSidebar, approved\n * 2026-10-22), so every product sidebar — the web frame, desktop, the extension — has ONE shape and\n * ONE component:\n *\n * [status] optional one line (a refusal, a notice); absent = no band\n * ( Search ) the host owns the value; `pool` makes it search places here\n * (+) New optional\n * Agents › the chosen related places, in order\n * Workflows › a place with `children` opens a flyout of them; else it opens\n * Scheduled ›\n * … More every other place, the host's extra groups, \"Edit sidebar…\"\n * [children] optional (the conversation sidebar's one row of filter buttons)\n *\n * ONE LEFT EDGE (Arman, 2026-10-23): the Search glyph, every row's icon and the host's list below\n * share one left edge, 16px in from the column (this component's 8px padding + the row's 8px); a\n * place's `›` and every other chevron sit on the RIGHT. The modes (Chat, Work…) are never here —\n * they live in the page header.\n *\n * The product's own list sits below, outside this component. WHICH places sit above More is a\n * layered knob (system → organization → person) the HOST reads and writes; this component only\n * draws `chosen` and calls `onEditSidebar`. `SidebarPlacesChooser` is the \"Above More\" section of\n * the host's Edit sidebar dialog (`SidebarEditDialog` is the dialog's chrome).\n */\n\nimport type { ComponentType, KeyboardEvent, ReactNode } from \"react\";\nimport {\n ChevronRightIcon as ChevronRight,\n MoreHorizontalIcon as MoreHorizontal,\n PlusIcon as Plus,\n SearchIcon as Search,\n} from \"../icons\";\nimport { Button } from \"../button\";\nimport { Checkbox } from \"../checkbox\";\nimport { cn } from \"../cn\";\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from \"../dialog\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"../dropdown-menu\";\nimport { InputWithPrefix } from \"../input\";\nimport { ItemRow } from \"./ItemRow\";\n\n/** One related place a product sidebar can offer (another product, a page, a list). */\nexport interface SidebarPlace {\n /** Stable id: what the layered \"above More\" knob stores. */\n id: string;\n label: string;\n icon: ComponentType<{ className?: string }>;\n /** Its address. Set it and the row is a real link (cmd/ctrl/middle-click opens a new tab). */\n href?: string | undefined;\n /** A sub-list: the row opens a flyout of these (the place itself first) instead of navigating. */\n children?: readonly SidebarPlace[] | undefined;\n}\n\n/** An extra group at the end of More (a product's own other pages, under its name). */\nexport interface SidebarMoreGroup {\n id: string;\n label?: string | undefined;\n places: readonly SidebarPlace[];\n}\n\nexport interface ProductSidebarTopSearch {\n value: string;\n onChange: (value: string) => void;\n /** Screen-reader name (\"Search conversations\"). */\n ariaLabel: string;\n placeholder?: string | undefined;\n /**\n * Searches the places themselves: while the field holds a query the rows become every place\n * (chosen, More, More groups and this pool) whose label matches, and Enter opens the first.\n * Absent = the host searches its own list (the conversation sidebar) and the rows stay.\n */\n pool?: readonly SidebarPlace[] | undefined;\n}\n\nexport interface ProductSidebarTopProps {\n /** Above Search: one status line (a refusal, a notice). Render it only when it has something to say. */\n status?: ReactNode;\n search?: ProductSidebarTopSearch | undefined;\n /** \"New\" row; absent = none. */\n newItem?: { label?: string | undefined; href?: string | undefined; onOpen?: (() => void) | undefined } | undefined;\n /** Every related place, in order. */\n places: readonly SidebarPlace[];\n /** Ids shown above More, in this order (unknown ids are skipped). */\n chosen: readonly string[];\n /** A place was opened (plain click). Absent + `href` = the link navigates. */\n onOpenPlace?: ((place: SidebarPlace) => void) | undefined;\n /** Extra groups at the end of More, before \"Edit sidebar…\". */\n moreGroups?: readonly SidebarMoreGroup[] | undefined;\n /** \"Edit sidebar…\" in More; absent = not offered. */\n onEditSidebar?: (() => void) | undefined;\n /** Below the rows: the conversation sidebar's bucket toggles. */\n children?: ReactNode;\n /** The right-click menu's feature tag on every row. */\n sourceFeature: string;\n className?: string | undefined;\n}\n\n/** Places above More, in `chosen` order; the rest in `places` order. */\nexport function splitSidebarPlaces(\n places: readonly SidebarPlace[],\n chosen: readonly string[],\n): { above: SidebarPlace[]; more: SidebarPlace[] } {\n const byId = new Map(places.map((p) => [p.id, p]));\n const above = chosen.map((id) => byId.get(id)).filter((p): p is SidebarPlace => p != null);\n const aboveIds = new Set(above.map((p) => p.id));\n return { above, more: places.filter((p) => !aboveIds.has(p.id)) };\n}\n\n/** Every place a search can reach, de-duplicated by id, matched on its label (and its sub-list). */\nexport function matchSidebarPlaces(pool: readonly SidebarPlace[], query: string): SidebarPlace[] {\n const q = query.trim().toLowerCase();\n if (!q) return [];\n const seen = new Set<string>();\n const out: SidebarPlace[] = [];\n const visit = (p: SidebarPlace) => {\n if (!seen.has(p.id) && p.label.toLowerCase().includes(q)) {\n seen.add(p.id);\n out.push({ ...p, children: undefined });\n }\n p.children?.forEach(visit);\n };\n pool.forEach(visit);\n return out;\n}\n\nexport function ProductSidebarTop({\n status,\n search,\n newItem,\n places,\n chosen,\n onOpenPlace,\n moreGroups,\n onEditSidebar,\n children,\n sourceFeature,\n className,\n}: ProductSidebarTopProps) {\n const { above, more } = splitSidebarPlaces(places, chosen);\n const groups = (moreGroups ?? []).filter((g) => g.places.length > 0);\n const searching = !!search?.pool && search.value.trim().length > 0;\n const matches = searching\n ? matchSidebarPlaces([...places, ...groups.flatMap((g) => g.places), ...(search?.pool ?? [])], search!.value)\n : [];\n const open = (place: SidebarPlace) => onOpenPlace?.(place);\n\n const onSearchKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (!search) return;\n if (e.key === \"Escape\" && search.value) {\n e.preventDefault();\n search.onChange(\"\");\n } else if (e.key === \"Enter\" && searching && matches[0]) {\n e.preventDefault();\n const first = matches[0];\n if (onOpenPlace) open(first);\n else if (first.href && typeof window !== \"undefined\") window.location.assign(first.href);\n }\n };\n\n return (\n <div data-product-sidebar-top=\"\" className={cn(\"flex shrink-0 flex-col gap-1 px-2 pb-1 pt-2\", className)}>\n {status}\n {search ? (\n <InputWithPrefix\n prefix={<Search className=\"size-4\" />}\n prefixInset=\"edge\"\n value={search.value}\n onChange={(e) => search.onChange(e.target.value)}\n onKeyDown={onSearchKeyDown}\n placeholder={search.placeholder ?? \"Search\"}\n aria-label={search.ariaLabel}\n className=\"h-8\"\n />\n ) : null}\n\n <div className=\"flex flex-col pt-1\">\n {searching ? (\n matches.length > 0 ? (\n matches.map((p) => (\n <PlaceRow key={p.id} place={p} onOpen={onOpenPlace ? open : undefined} sourceFeature={sourceFeature} />\n ))\n ) : (\n <div className=\"flex h-7 items-center px-2 type-secondary text-muted-foreground\" data-sidebar-places-empty=\"\">\n No matches\n </div>\n )\n ) : (\n <>\n {newItem ? (\n <ItemRow\n size=\"sm\"\n label={newItem.label ?? \"New\"}\n leading={<Plus className=\"size-4\" />}\n href={newItem.href}\n openInPlace={newItem.href ? true : undefined}\n onOpen={newItem.onOpen}\n sourceFeature={sourceFeature}\n disableContextMenu\n />\n ) : null}\n {above.map((p) => (\n <PlaceRow key={p.id} place={p} onOpen={onOpenPlace ? open : undefined} sourceFeature={sourceFeature} chevron />\n ))}\n {more.length > 0 || groups.length > 0 || onEditSidebar ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div data-sidebar-more-trigger=\"\">\n <ItemRow\n size=\"sm\"\n label=\"More\"\n leading={<MoreHorizontal className=\"size-4\" />}\n sourceFeature={sourceFeature}\n disableContextMenu\n />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-56\">\n {more.map((p) => (\n <PlaceMenuItem key={p.id} place={p} onOpen={open} />\n ))}\n {groups.map((g, i) => (\n <div key={g.id} role=\"group\" aria-label={g.label}>\n {more.length > 0 || i > 0 ? <DropdownMenuSeparator /> : null}\n {g.label ? <DropdownMenuLabel>{g.label}</DropdownMenuLabel> : null}\n {g.places.map((p) => (\n <PlaceMenuItem key={p.id} place={p} onOpen={open} />\n ))}\n </div>\n ))}\n {onEditSidebar ? (\n <>\n {more.length > 0 || groups.length > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuItem onSelect={onEditSidebar}>Edit sidebar…</DropdownMenuItem>\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </>\n )}\n </div>\n\n {children}\n </div>\n );\n}\n\n/** A place above More: a link row, or a flyout of its sub-list. */\nfunction PlaceRow({\n place,\n onOpen,\n sourceFeature,\n chevron,\n}: {\n place: SidebarPlace;\n onOpen: ((place: SidebarPlace) => void) | undefined;\n sourceFeature: string;\n chevron?: boolean;\n}) {\n const Icon = place.icon;\n const trailing = chevron ? <ChevronRight className=\"size-4 text-muted-foreground\" /> : undefined;\n if (place.children && place.children.length > 0) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div data-sidebar-place={place.id} data-sidebar-place-flyout=\"\">\n <ItemRow\n size=\"sm\"\n label={place.label}\n leading={<Icon className=\"size-4\" />}\n trailing={trailing}\n sourceFeature={sourceFeature}\n disableContextMenu\n />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent side=\"right\" align=\"start\" className=\"w-56\">\n <FlyoutItems place={place} onOpen={(p) => (onOpen ? onOpen(p) : goTo(p))} />\n </DropdownMenuContent>\n </DropdownMenu>\n );\n }\n return (\n <div data-sidebar-place={place.id}>\n <ItemRow\n size=\"sm\"\n label={place.label}\n leading={<Icon className=\"size-4\" />}\n trailing={trailing}\n href={place.href}\n openInPlace={place.href && onOpen ? true : undefined}\n onOpen={onOpen ? () => onOpen(place) : undefined}\n sourceFeature={sourceFeature}\n disableContextMenu\n />\n </div>\n );\n}\n\n/** The place itself first, then its sub-list. */\nfunction FlyoutItems({ place, onOpen }: { place: SidebarPlace; onOpen: (place: SidebarPlace) => void }) {\n const Icon = place.icon;\n return (\n <>\n {place.href ? (\n <>\n <DropdownMenuItem onSelect={() => onOpen({ ...place, children: undefined })}>\n <Icon className=\"size-4\" />\n {place.label}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n </>\n ) : null}\n {(place.children ?? []).map((c) => {\n const CIcon = c.icon;\n return (\n <DropdownMenuItem key={c.id} onSelect={() => onOpen(c)}>\n <CIcon className=\"size-4\" />\n {c.label}\n </DropdownMenuItem>\n );\n })}\n </>\n );\n}\n\nfunction PlaceMenuItem({ place, onOpen }: { place: SidebarPlace; onOpen: (place: SidebarPlace) => void }) {\n const Icon = place.icon;\n if (place.children && place.children.length > 0) {\n return (\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n <Icon className=\"size-4\" />\n {place.label}\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent className=\"w-56\">\n <FlyoutItems place={place} onOpen={onOpen} />\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n );\n }\n return (\n <DropdownMenuItem onSelect={() => onOpen(place)}>\n <Icon className=\"size-4\" />\n {place.label}\n </DropdownMenuItem>\n );\n}\n\n/** No host handler: a place with an address is a plain navigation. */\nfunction goTo(place: SidebarPlace) {\n if (place.href && typeof window !== \"undefined\") window.location.assign(place.href);\n}\n\n/** \"Above More\": which places sit above More (the host saves it on its layered knob). */\nexport function SidebarPlacesChooser({\n places,\n chosen,\n onChange,\n title = \"Above More\",\n}: {\n places: readonly SidebarPlace[];\n chosen: readonly string[];\n /** The next chosen ids, in `places` order. */\n onChange: (next: string[]) => void;\n title?: string;\n}) {\n const flip = (id: string) =>\n onChange(places.filter((p) => (p.id === id ? !chosen.includes(id) : chosen.includes(p.id))).map((p) => p.id));\n return (\n <section className=\"flex flex-col gap-1\" data-sidebar-places-chooser=\"\">\n <span className=\"text-sm font-medium text-foreground\">{title}</span>\n {places.map((p) => {\n const Icon = p.icon;\n return (\n <label key={p.id} className=\"flex h-8 cursor-pointer items-center gap-2 rounded-md px-1 text-sm hover:bg-muted\">\n <Checkbox size=\"sm\" checked={chosen.includes(p.id)} onCheckedChange={() => flip(p.id)} />\n <Icon className=\"size-4 text-muted-foreground\" />\n <span className=\"text-foreground\">{p.label}</span>\n </label>\n );\n })}\n </section>\n );\n}\n\n/** The Edit sidebar dialog's chrome: title, the host's sections, a refusal line, Cancel / Save. */\nexport function SidebarEditDialog({\n open,\n onOpenChange,\n onSave,\n refusal,\n saveLabel = \"Save as my default\",\n children,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSave: () => void;\n /** Why the last save was refused; shown in the dialog. */\n refusal?: string | null | undefined;\n saveLabel?: string;\n children: ReactNode;\n}) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent size=\"sm\" onOpenAutoFocus={(e) => e.preventDefault()}>\n <DialogHeader>\n <DialogTitle>Edit sidebar</DialogTitle>\n </DialogHeader>\n <div className=\"flex flex-col gap-4\">\n {children}\n <div className=\"h-5 truncate text-sm text-destructive\" role=\"status\">\n {refusal ?? \"\"}\n </div>\n </div>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n <Button onClick={onSave}>{saveLabel}</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/item/ProductSidebarTop.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * THE TOP OF EVERY PRODUCT SIDEBAR (Arman, 2026-10-22: \"This is a very important missing thing that\n * we have to establish or our system will fail.\" — common-docs projects/app-frame/VISION.md).\n *\n * Extracted from the conversation sidebar's top (`@ai-matrx/chat` ConversationSidebar, approved\n * 2026-10-22), so every product sidebar — the web frame, desktop, the extension — has ONE shape and\n * ONE component:\n *\n * [status] optional one line (a refusal, a notice); absent = no band\n * ( Search ) only a host whose LIST has its own filter and no search door above\n * (+) New optional\n * Agents › the chosen related places, in order\n * Workflows › a place with `children` opens a flyout of them; else it opens\n * Scheduled ›\n * … More every other place, the host's extra groups, \"Edit sidebar…\"\n * [children] optional (the conversation sidebar's one row of filter buttons)\n *\n * ONE LEFT EDGE (Arman, 2026-10-23): the Search glyph, every row's icon and the host's list below\n * share one left edge, 16px in from the column (this component's 8px padding + the row's 8px); a\n * place's `›` and every other chevron sit on the RIGHT. The modes (Chat, Work…) are never here —\n * they live in the page header.\n *\n * ONE SEARCH DOOR (Arman, 2026-10-23: \"You cannot have a search icon and also a searchbar\"): a\n * sidebar whose top row carries a search icon (the web frame's Go to) passes no `search` — that icon\n * finds every place and page this field used to. The field is only a list's own filter.\n *\n * The product's own list sits below, outside this component. WHICH places sit above More is a\n * layered knob (system → organization → person) the HOST reads and writes; this component only\n * draws `chosen` and calls `onEditSidebar`. `SidebarPlacesChooser` is the \"Above More\" section of\n * the host's Edit sidebar dialog (`SidebarEditDialog` is the dialog's chrome).\n */\n\nimport type { ComponentType, KeyboardEvent, ReactNode } from \"react\";\nimport {\n ChevronRightIcon as ChevronRight,\n MoreHorizontalIcon as MoreHorizontal,\n PlusIcon as Plus,\n SearchIcon as Search,\n} from \"../icons\";\nimport { Button } from \"../button\";\nimport { Checkbox } from \"../checkbox\";\nimport { cn } from \"../cn\";\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from \"../dialog\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"../dropdown-menu\";\nimport { InputWithPrefix } from \"../input\";\nimport { ItemRow } from \"./ItemRow\";\n\n/** One related place a product sidebar can offer (another product, a page, a list). */\nexport interface SidebarPlace {\n /** Stable id: what the layered \"above More\" knob stores. */\n id: string;\n label: string;\n icon: ComponentType<{ className?: string }>;\n /** Its address. Set it and the row is a real link (cmd/ctrl/middle-click opens a new tab). */\n href?: string | undefined;\n /** A sub-list: the row opens a flyout of these (the place itself first) instead of navigating. */\n children?: readonly SidebarPlace[] | undefined;\n}\n\n/** An extra group at the end of More (a product's own other pages, under its name). */\nexport interface SidebarMoreGroup {\n id: string;\n label?: string | undefined;\n places: readonly SidebarPlace[];\n}\n\nexport interface ProductSidebarTopSearch {\n value: string;\n onChange: (value: string) => void;\n /** Screen-reader name (\"Search conversations\"). */\n ariaLabel: string;\n placeholder?: string | undefined;\n}\n\nexport interface ProductSidebarTopProps {\n /** Above Search: one status line (a refusal, a notice). Render it only when it has something to say. */\n status?: ReactNode;\n search?: ProductSidebarTopSearch | undefined;\n /** \"New\" row; absent = none. */\n newItem?: { label?: string | undefined; href?: string | undefined; onOpen?: (() => void) | undefined } | undefined;\n /** Every related place, in order. */\n places: readonly SidebarPlace[];\n /** Ids shown above More, in this order (unknown ids are skipped). */\n chosen: readonly string[];\n /** A place was opened (plain click). Absent + `href` = the link navigates. */\n onOpenPlace?: ((place: SidebarPlace) => void) | undefined;\n /** Extra groups at the end of More, before \"Edit sidebar…\". */\n moreGroups?: readonly SidebarMoreGroup[] | undefined;\n /** \"Edit sidebar…\" in More; absent = not offered. */\n onEditSidebar?: (() => void) | undefined;\n /** Below the rows: the conversation sidebar's bucket toggles. */\n children?: ReactNode;\n /** The right-click menu's feature tag on every row. */\n sourceFeature: string;\n className?: string | undefined;\n}\n\n/** Places above More, in `chosen` order; the rest in `places` order. */\nexport function splitSidebarPlaces(\n places: readonly SidebarPlace[],\n chosen: readonly string[],\n): { above: SidebarPlace[]; more: SidebarPlace[] } {\n const byId = new Map(places.map((p) => [p.id, p]));\n const above = chosen.map((id) => byId.get(id)).filter((p): p is SidebarPlace => p != null);\n const aboveIds = new Set(above.map((p) => p.id));\n return { above, more: places.filter((p) => !aboveIds.has(p.id)) };\n}\n\nexport function ProductSidebarTop({\n status,\n search,\n newItem,\n places,\n chosen,\n onOpenPlace,\n moreGroups,\n onEditSidebar,\n children,\n sourceFeature,\n className,\n}: ProductSidebarTopProps) {\n const { above, more } = splitSidebarPlaces(places, chosen);\n const groups = (moreGroups ?? []).filter((g) => g.places.length > 0);\n const open = (place: SidebarPlace) => onOpenPlace?.(place);\n\n const onSearchKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (search && e.key === \"Escape\" && search.value) {\n e.preventDefault();\n search.onChange(\"\");\n }\n };\n\n return (\n <div data-product-sidebar-top=\"\" className={cn(\"flex shrink-0 flex-col gap-1 px-2 pb-1 pt-2\", className)}>\n {status}\n {search ? (\n <InputWithPrefix\n prefix={<Search className=\"size-4\" />}\n prefixInset=\"edge\"\n value={search.value}\n onChange={(e) => search.onChange(e.target.value)}\n onKeyDown={onSearchKeyDown}\n placeholder={search.placeholder ?? \"Search\"}\n aria-label={search.ariaLabel}\n className=\"h-8\"\n />\n ) : null}\n\n <div className={cn(\"flex flex-col\", search && \"pt-1\")}>\n {newItem ? (\n <ItemRow\n size=\"sm\"\n label={newItem.label ?? \"New\"}\n leading={<Plus className=\"size-4\" />}\n href={newItem.href}\n openInPlace={newItem.href ? true : undefined}\n onOpen={newItem.onOpen}\n sourceFeature={sourceFeature}\n disableContextMenu\n />\n ) : null}\n {above.map((p) => (\n <PlaceRow key={p.id} place={p} onOpen={onOpenPlace ? open : undefined} sourceFeature={sourceFeature} chevron />\n ))}\n {more.length > 0 || groups.length > 0 || onEditSidebar ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div data-sidebar-more-trigger=\"\">\n <ItemRow\n size=\"sm\"\n label=\"More\"\n leading={<MoreHorizontal className=\"size-4\" />}\n sourceFeature={sourceFeature}\n disableContextMenu\n />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-56\">\n {more.map((p) => (\n <PlaceMenuItem key={p.id} place={p} onOpen={open} />\n ))}\n {groups.map((g, i) => (\n <div key={g.id} role=\"group\" aria-label={g.label}>\n {more.length > 0 || i > 0 ? <DropdownMenuSeparator /> : null}\n {g.label ? <DropdownMenuLabel>{g.label}</DropdownMenuLabel> : null}\n {g.places.map((p) => (\n <PlaceMenuItem key={p.id} place={p} onOpen={open} />\n ))}\n </div>\n ))}\n {onEditSidebar ? (\n <>\n {more.length > 0 || groups.length > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuItem onSelect={onEditSidebar}>Edit sidebar…</DropdownMenuItem>\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n\n {children}\n </div>\n );\n}\n\n/** A place above More: a link row, or a flyout of its sub-list. */\nfunction PlaceRow({\n place,\n onOpen,\n sourceFeature,\n chevron,\n}: {\n place: SidebarPlace;\n onOpen: ((place: SidebarPlace) => void) | undefined;\n sourceFeature: string;\n chevron?: boolean;\n}) {\n const Icon = place.icon;\n const trailing = chevron ? <ChevronRight className=\"size-4 text-muted-foreground\" /> : undefined;\n if (place.children && place.children.length > 0) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div data-sidebar-place={place.id} data-sidebar-place-flyout=\"\">\n <ItemRow\n size=\"sm\"\n label={place.label}\n leading={<Icon className=\"size-4\" />}\n trailing={trailing}\n sourceFeature={sourceFeature}\n disableContextMenu\n />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent side=\"right\" align=\"start\" className=\"w-56\">\n <FlyoutItems place={place} onOpen={(p) => (onOpen ? onOpen(p) : goTo(p))} />\n </DropdownMenuContent>\n </DropdownMenu>\n );\n }\n return (\n <div data-sidebar-place={place.id}>\n <ItemRow\n size=\"sm\"\n label={place.label}\n leading={<Icon className=\"size-4\" />}\n trailing={trailing}\n href={place.href}\n openInPlace={place.href && onOpen ? true : undefined}\n onOpen={onOpen ? () => onOpen(place) : undefined}\n sourceFeature={sourceFeature}\n disableContextMenu\n />\n </div>\n );\n}\n\n/** The place itself first, then its sub-list. */\nfunction FlyoutItems({ place, onOpen }: { place: SidebarPlace; onOpen: (place: SidebarPlace) => void }) {\n const Icon = place.icon;\n return (\n <>\n {place.href ? (\n <>\n <DropdownMenuItem onSelect={() => onOpen({ ...place, children: undefined })}>\n <Icon className=\"size-4\" />\n {place.label}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n </>\n ) : null}\n {(place.children ?? []).map((c) => {\n const CIcon = c.icon;\n return (\n <DropdownMenuItem key={c.id} onSelect={() => onOpen(c)}>\n <CIcon className=\"size-4\" />\n {c.label}\n </DropdownMenuItem>\n );\n })}\n </>\n );\n}\n\nfunction PlaceMenuItem({ place, onOpen }: { place: SidebarPlace; onOpen: (place: SidebarPlace) => void }) {\n const Icon = place.icon;\n if (place.children && place.children.length > 0) {\n return (\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n <Icon className=\"size-4\" />\n {place.label}\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent className=\"w-56\">\n <FlyoutItems place={place} onOpen={onOpen} />\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n );\n }\n return (\n <DropdownMenuItem onSelect={() => onOpen(place)}>\n <Icon className=\"size-4\" />\n {place.label}\n </DropdownMenuItem>\n );\n}\n\n/** No host handler: a place with an address is a plain navigation. */\nfunction goTo(place: SidebarPlace) {\n if (place.href && typeof window !== \"undefined\") window.location.assign(place.href);\n}\n\n/** \"Above More\": which places sit above More (the host saves it on its layered knob). */\nexport function SidebarPlacesChooser({\n places,\n chosen,\n onChange,\n title = \"Above More\",\n}: {\n places: readonly SidebarPlace[];\n chosen: readonly string[];\n /** The next chosen ids, in `places` order. */\n onChange: (next: string[]) => void;\n title?: string;\n}) {\n const flip = (id: string) =>\n onChange(places.filter((p) => (p.id === id ? !chosen.includes(id) : chosen.includes(p.id))).map((p) => p.id));\n return (\n <section className=\"flex flex-col gap-1\" data-sidebar-places-chooser=\"\">\n <span className=\"text-sm font-medium text-foreground\">{title}</span>\n {places.map((p) => {\n const Icon = p.icon;\n return (\n <label key={p.id} className=\"flex h-8 cursor-pointer items-center gap-2 rounded-md px-1 text-sm hover:bg-muted\">\n <Checkbox size=\"sm\" checked={chosen.includes(p.id)} onCheckedChange={() => flip(p.id)} />\n <Icon className=\"size-4 text-muted-foreground\" />\n <span className=\"text-foreground\">{p.label}</span>\n </label>\n );\n })}\n </section>\n );\n}\n\n/** The Edit sidebar dialog's chrome: title, the host's sections, a refusal line, Cancel / Save. */\nexport function SidebarEditDialog({\n open,\n onOpenChange,\n onSave,\n refusal,\n saveLabel = \"Save as my default\",\n children,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSave: () => void;\n /** Why the last save was refused; shown in the dialog. */\n refusal?: string | null | undefined;\n saveLabel?: string;\n children: ReactNode;\n}) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent size=\"sm\" onOpenAutoFocus={(e) => e.preventDefault()}>\n <DialogHeader>\n <DialogTitle>Edit sidebar</DialogTitle>\n </DialogHeader>\n <div className=\"flex flex-col gap-4\">\n {children}\n <div className=\"h-5 truncate text-sm text-destructive\" role=\"status\">\n {refusal ?? \"\"}\n </div>\n </div>\n <DialogFooter>\n <Button variant=\"ghost\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n <Button onClick={onSave}>{saveLabel}</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/menu-look.cjs
CHANGED
|
@@ -39,6 +39,7 @@ __export(menu_look_exports, {
|
|
|
39
39
|
MenuLookItem: () => MenuLookItem,
|
|
40
40
|
MenuLookLabel: () => MenuLookLabel,
|
|
41
41
|
MenuLookRowBody: () => MenuLookRowBody,
|
|
42
|
+
MenuLookSearch: () => MenuLookSearch,
|
|
42
43
|
MenuLookSeparator: () => MenuLookSeparator,
|
|
43
44
|
MenuLookSubContent: () => MenuLookSubContent,
|
|
44
45
|
MenuLookSubTrigger: () => MenuLookSubTrigger,
|
|
@@ -567,6 +568,8 @@ var MENU_LOOK_CLASS = {
|
|
|
567
568
|
text: "cm-text",
|
|
568
569
|
label: "cm-label",
|
|
569
570
|
hint: "cm-hint",
|
|
571
|
+
current: "cm-current",
|
|
572
|
+
search: "cm-search",
|
|
570
573
|
trail: "cm-trail",
|
|
571
574
|
shortcut: "cm-shortcut",
|
|
572
575
|
divider: "cm-divider",
|
|
@@ -577,14 +580,15 @@ var MENU_LOOK_CLASS = {
|
|
|
577
580
|
function MenuLookIconSlot({ children }) {
|
|
578
581
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: MENU_LOOK_CLASS.iconSlot, children });
|
|
579
582
|
}
|
|
580
|
-
function MenuLookRowBody({ icon, label, description, trail }) {
|
|
583
|
+
function MenuLookRowBody({ icon, label, description, trail, current }) {
|
|
581
584
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
582
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MenuLookIconSlot, { children: icon }),
|
|
585
|
+
icon ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MenuLookIconSlot, { children: icon }) : null,
|
|
583
586
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: MENU_LOOK_CLASS.text, children: [
|
|
584
587
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: MENU_LOOK_CLASS.label, children: label }),
|
|
585
588
|
description ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: MENU_LOOK_CLASS.hint, children: description }) : null
|
|
586
589
|
] }),
|
|
587
|
-
trail ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: MENU_LOOK_CLASS.trail, children: trail }) : null
|
|
590
|
+
trail ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: MENU_LOOK_CLASS.trail, children: trail }) : null,
|
|
591
|
+
current ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RadixCheckIcon, { className: MENU_LOOK_CLASS.current, "aria-hidden": "true", "data-menu-current-mark": "" }) : null
|
|
588
592
|
] });
|
|
589
593
|
}
|
|
590
594
|
function menuLookItemClass({ destructive, dimmed } = {}) {
|
|
@@ -618,20 +622,21 @@ var MenuLookSubContent = React6.forwardRef(function MenuLookSubContent2({ size =
|
|
|
618
622
|
}
|
|
619
623
|
);
|
|
620
624
|
});
|
|
621
|
-
var MenuLookItem = React6.forwardRef(function MenuLookItem2({ icon, label, description, trail, destructive, dimmed, href, target, linkProps, ...props }, ref) {
|
|
625
|
+
var MenuLookItem = React6.forwardRef(function MenuLookItem2({ icon, label, description, trail, current, destructive, dimmed, href, target, linkProps, ...props }, ref) {
|
|
622
626
|
const className = menuLookItemClass({ destructive, dimmed });
|
|
623
|
-
const body = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MenuLookRowBody, { icon, label, description, trail });
|
|
627
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MenuLookRowBody, { icon, label, description, trail, current });
|
|
628
|
+
const mark = current ? { "data-current": "" } : {};
|
|
624
629
|
if (href) {
|
|
625
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive2.Item, { ref, asChild: true, ...props, className, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href, target, rel: target === "_blank" ? "noopener noreferrer" : void 0, ...linkProps, children: body }) });
|
|
630
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive2.Item, { ref, asChild: true, ...props, ...mark, className, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href, target, rel: target === "_blank" ? "noopener noreferrer" : void 0, ...linkProps, children: body }) });
|
|
626
631
|
}
|
|
627
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive2.Item, { ref, ...props, className, children: body });
|
|
632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive2.Item, { ref, ...props, ...mark, className, children: body });
|
|
628
633
|
});
|
|
629
634
|
var MenuLookSubTrigger = React6.forwardRef(function MenuLookSubTrigger2({ icon, label, description, trail, ...props }, ref) {
|
|
630
635
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuSubTrigger, { ref, ...props, className: MENU_LOOK_CLASS.item, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MenuLookRowBody, { icon, label, description, trail }) });
|
|
631
636
|
});
|
|
632
637
|
var MenuLookCheckboxItem = React6.forwardRef(function MenuLookCheckboxItem2({ icon, label, description, trail, checked, ...props }, ref) {
|
|
633
638
|
const on = checked === true;
|
|
634
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive2.CheckboxItem, { ref, ...checked === void 0 ? {} : { checked }, ...props, className: MENU_LOOK_CLASS.item, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MenuLookRowBody, { icon: on ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RadixCheckIcon, { className: MENU_LOOK_CLASS.icon }) : icon, label, description, trail }) });
|
|
639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive2.CheckboxItem, { ref, ...checked === void 0 ? {} : { checked }, ...props, className: MENU_LOOK_CLASS.item, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MenuLookRowBody, { icon: on ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RadixCheckIcon, { className: MENU_LOOK_CLASS.icon }) : icon ?? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: MENU_LOOK_CLASS.icon, "aria-hidden": "true" }), label, description, trail }) });
|
|
635
640
|
});
|
|
636
641
|
var MenuLookLabel = React6.forwardRef(function MenuLookLabel2(props, ref) {
|
|
637
642
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive2.Label, { ref, ...props, className: MENU_LOOK_CLASS.sectionLabel });
|
|
@@ -639,4 +644,18 @@ var MenuLookLabel = React6.forwardRef(function MenuLookLabel2(props, ref) {
|
|
|
639
644
|
var MenuLookSeparator = React6.forwardRef(function MenuLookSeparator2(props, ref) {
|
|
640
645
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive2.Separator, { ref, ...props, className: MENU_LOOK_CLASS.divider });
|
|
641
646
|
});
|
|
647
|
+
var MenuLookSearch = React6.forwardRef(function MenuLookSearch2({ placeholder = "Search", ...props }, ref) {
|
|
648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: MENU_LOOK_CLASS.search, "data-menu-look-search": "", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
649
|
+
"input",
|
|
650
|
+
{
|
|
651
|
+
ref,
|
|
652
|
+
type: "search",
|
|
653
|
+
autoComplete: "off",
|
|
654
|
+
spellCheck: false,
|
|
655
|
+
placeholder,
|
|
656
|
+
"aria-label": props["aria-label"] ?? placeholder,
|
|
657
|
+
...props
|
|
658
|
+
}
|
|
659
|
+
) });
|
|
660
|
+
});
|
|
642
661
|
//# sourceMappingURL=menu-look.cjs.map
|