@mesob/ui 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/components/app-breadcrumbs.d.ts +34 -0
  2. package/dist/components/app-breadcrumbs.js +177 -0
  3. package/dist/components/app-breadcrumbs.js.map +1 -0
  4. package/dist/components/app-header-actions.d.ts +39 -0
  5. package/dist/components/app-header-actions.js +629 -0
  6. package/dist/components/app-header-actions.js.map +1 -0
  7. package/dist/components/app-sidebar.d.ts +24 -0
  8. package/dist/components/app-sidebar.js +669 -0
  9. package/dist/components/app-sidebar.js.map +1 -0
  10. package/dist/components/data-table/index.d.ts +9 -2
  11. package/dist/components/data-table/index.js +276 -101
  12. package/dist/components/data-table/index.js.map +1 -1
  13. package/dist/components/entity/index.d.ts +85 -9
  14. package/dist/components/entity/index.js +424 -304
  15. package/dist/components/entity/index.js.map +1 -1
  16. package/dist/components/input-group.d.ts +1 -1
  17. package/dist/components/link.d.ts +12 -0
  18. package/dist/components/link.js +51 -0
  19. package/dist/components/link.js.map +1 -0
  20. package/dist/components/mesob-context.d.ts +34 -0
  21. package/dist/components/mesob-context.js +53 -0
  22. package/dist/components/mesob-context.js.map +1 -0
  23. package/dist/components/page/index.d.ts +46 -0
  24. package/dist/components/page/index.js +197 -0
  25. package/dist/components/page/index.js.map +1 -0
  26. package/dist/components/powered-by.d.ts +4 -1
  27. package/dist/components/powered-by.js +28 -12
  28. package/dist/components/powered-by.js.map +1 -1
  29. package/dist/components/shell.d.ts +13 -0
  30. package/dist/components/shell.js +545 -0
  31. package/dist/components/shell.js.map +1 -0
  32. package/dist/components/sidebar.d.ts +4 -0
  33. package/dist/components/sidebar.js +37 -8
  34. package/dist/components/sidebar.js.map +1 -1
  35. package/dist/components/table.js +1 -1
  36. package/dist/components/table.js.map +1 -1
  37. package/dist/components/tooltip.d.ts +1 -1
  38. package/dist/components/tooltip.js +2 -1
  39. package/dist/components/tooltip.js.map +1 -1
  40. package/dist/hooks/use-router.d.ts +7 -0
  41. package/dist/hooks/use-router.js +36 -0
  42. package/dist/hooks/use-router.js.map +1 -0
  43. package/dist/hooks/use-translation.d.ts +5 -0
  44. package/dist/hooks/use-translation.js +41 -0
  45. package/dist/hooks/use-translation.js.map +1 -0
  46. package/package.json +7 -1
  47. package/src/styles/globals.css +4 -0
@@ -0,0 +1,629 @@
1
+ "use client";
2
+
3
+ // src/lib/utils.ts
4
+ import { clsx } from "clsx";
5
+ import { twMerge } from "tailwind-merge";
6
+ function cn(...inputs) {
7
+ return twMerge(clsx(inputs));
8
+ }
9
+
10
+ // src/components/avatar.tsx
11
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
12
+ import { jsx } from "react/jsx-runtime";
13
+ function Avatar({
14
+ className,
15
+ ...props
16
+ }) {
17
+ return /* @__PURE__ */ jsx(
18
+ AvatarPrimitive.Root,
19
+ {
20
+ "data-slot": "avatar",
21
+ className: cn(
22
+ "relative flex size-8 shrink-0 overflow-hidden rounded-full",
23
+ className
24
+ ),
25
+ ...props
26
+ }
27
+ );
28
+ }
29
+ function AvatarImage({
30
+ className,
31
+ ...props
32
+ }) {
33
+ return /* @__PURE__ */ jsx(
34
+ AvatarPrimitive.Image,
35
+ {
36
+ "data-slot": "avatar-image",
37
+ className: cn("aspect-square size-full", className),
38
+ ...props
39
+ }
40
+ );
41
+ }
42
+ function AvatarFallback({
43
+ className,
44
+ ...props
45
+ }) {
46
+ return /* @__PURE__ */ jsx(
47
+ AvatarPrimitive.Fallback,
48
+ {
49
+ "data-slot": "avatar-fallback",
50
+ className: cn(
51
+ "bg-muted flex size-full items-center justify-center rounded-full",
52
+ className
53
+ ),
54
+ ...props
55
+ }
56
+ );
57
+ }
58
+
59
+ // src/components/button.tsx
60
+ import { Slot } from "@radix-ui/react-slot";
61
+ import { cva } from "class-variance-authority";
62
+ import { jsx as jsx2 } from "react/jsx-runtime";
63
+ var buttonVariants = cva(
64
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
65
+ {
66
+ variants: {
67
+ variant: {
68
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
69
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
70
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
71
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
72
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
73
+ link: "text-primary underline-offset-4 hover:underline"
74
+ },
75
+ size: {
76
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
77
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
78
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
79
+ icon: "size-9",
80
+ "icon-sm": "size-8",
81
+ "icon-lg": "size-10"
82
+ }
83
+ },
84
+ defaultVariants: {
85
+ variant: "default",
86
+ size: "default"
87
+ }
88
+ }
89
+ );
90
+ function Button({
91
+ className,
92
+ variant,
93
+ size,
94
+ asChild = false,
95
+ ...props
96
+ }) {
97
+ const Comp = asChild ? Slot : "button";
98
+ return /* @__PURE__ */ jsx2(
99
+ Comp,
100
+ {
101
+ "data-slot": "button",
102
+ className: cn(buttonVariants({ variant, size, className })),
103
+ ...props
104
+ }
105
+ );
106
+ }
107
+
108
+ // src/components/dropdown-menu.tsx
109
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
110
+ import { IconCheck, IconChevronRight, IconCircle } from "@tabler/icons-react";
111
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
112
+ function DropdownMenu({
113
+ ...props
114
+ }) {
115
+ return /* @__PURE__ */ jsx3(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
116
+ }
117
+ function DropdownMenuTrigger({
118
+ ...props
119
+ }) {
120
+ return /* @__PURE__ */ jsx3(
121
+ DropdownMenuPrimitive.Trigger,
122
+ {
123
+ "data-slot": "dropdown-menu-trigger",
124
+ ...props
125
+ }
126
+ );
127
+ }
128
+ function DropdownMenuContent({
129
+ className,
130
+ sideOffset = 4,
131
+ ...props
132
+ }) {
133
+ return /* @__PURE__ */ jsx3(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx3(
134
+ DropdownMenuPrimitive.Content,
135
+ {
136
+ "data-slot": "dropdown-menu-content",
137
+ sideOffset,
138
+ className: cn(
139
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
140
+ className
141
+ ),
142
+ ...props
143
+ }
144
+ ) });
145
+ }
146
+ function DropdownMenuItem({
147
+ className,
148
+ inset,
149
+ variant = "default",
150
+ ...props
151
+ }) {
152
+ return /* @__PURE__ */ jsx3(
153
+ DropdownMenuPrimitive.Item,
154
+ {
155
+ "data-slot": "dropdown-menu-item",
156
+ "data-inset": inset,
157
+ "data-variant": variant,
158
+ className: cn(
159
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
160
+ className
161
+ ),
162
+ ...props
163
+ }
164
+ );
165
+ }
166
+ function DropdownMenuSeparator({
167
+ className,
168
+ ...props
169
+ }) {
170
+ return /* @__PURE__ */ jsx3(
171
+ DropdownMenuPrimitive.Separator,
172
+ {
173
+ "data-slot": "dropdown-menu-separator",
174
+ className: cn("bg-border -mx-1 my-1 h-px", className),
175
+ ...props
176
+ }
177
+ );
178
+ }
179
+
180
+ // src/components/tooltip.tsx
181
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
182
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
183
+
184
+ // src/components/mesob-context.tsx
185
+ import {
186
+ createContext,
187
+ useContext,
188
+ useMemo
189
+ } from "react";
190
+ import { jsx as jsx5 } from "react/jsx-runtime";
191
+ var MesobContext = createContext(null);
192
+ function useMesob() {
193
+ return useContext(MesobContext);
194
+ }
195
+
196
+ // src/components/link.tsx
197
+ import { jsx as jsx6 } from "react/jsx-runtime";
198
+ function Link({
199
+ href,
200
+ children,
201
+ className,
202
+ onClick,
203
+ ...props
204
+ }) {
205
+ const mesob = useMesob();
206
+ const LinkComponent = mesob?.linkComponent ?? "a";
207
+ if (LinkComponent === "a") {
208
+ return /* @__PURE__ */ jsx6("a", { href, className, onClick, ...props, children });
209
+ }
210
+ return /* @__PURE__ */ jsx6(
211
+ LinkComponent,
212
+ {
213
+ href,
214
+ className,
215
+ onClick,
216
+ ...props,
217
+ children
218
+ }
219
+ );
220
+ }
221
+
222
+ // src/components/dialog.tsx
223
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
224
+ import { IconX } from "@tabler/icons-react";
225
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
226
+ function Dialog({
227
+ ...props
228
+ }) {
229
+ return /* @__PURE__ */ jsx7(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
230
+ }
231
+ function DialogPortal({
232
+ ...props
233
+ }) {
234
+ return /* @__PURE__ */ jsx7(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
235
+ }
236
+ function DialogOverlay({
237
+ className,
238
+ ...props
239
+ }) {
240
+ return /* @__PURE__ */ jsx7(
241
+ DialogPrimitive.Overlay,
242
+ {
243
+ "data-slot": "dialog-overlay",
244
+ className: cn(
245
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
246
+ className
247
+ ),
248
+ ...props
249
+ }
250
+ );
251
+ }
252
+ function DialogContent({
253
+ className,
254
+ children,
255
+ showCloseButton = true,
256
+ ...props
257
+ }) {
258
+ return /* @__PURE__ */ jsxs3(DialogPortal, { "data-slot": "dialog-portal", children: [
259
+ /* @__PURE__ */ jsx7(DialogOverlay, {}),
260
+ /* @__PURE__ */ jsxs3(
261
+ DialogPrimitive.Content,
262
+ {
263
+ "data-slot": "dialog-content",
264
+ className: cn(
265
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
266
+ className
267
+ ),
268
+ ...props,
269
+ children: [
270
+ children,
271
+ showCloseButton && /* @__PURE__ */ jsxs3(
272
+ DialogPrimitive.Close,
273
+ {
274
+ "data-slot": "dialog-close",
275
+ className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
276
+ children: [
277
+ /* @__PURE__ */ jsx7(IconX, {}),
278
+ /* @__PURE__ */ jsx7("span", { className: "sr-only", children: "Close" })
279
+ ]
280
+ }
281
+ )
282
+ ]
283
+ }
284
+ )
285
+ ] });
286
+ }
287
+ function DialogHeader({ className, ...props }) {
288
+ return /* @__PURE__ */ jsx7(
289
+ "div",
290
+ {
291
+ "data-slot": "dialog-header",
292
+ className: cn("flex flex-col gap-2 text-center sm:text-left", className),
293
+ ...props
294
+ }
295
+ );
296
+ }
297
+ function DialogTitle({
298
+ className,
299
+ ...props
300
+ }) {
301
+ return /* @__PURE__ */ jsx7(
302
+ DialogPrimitive.Title,
303
+ {
304
+ "data-slot": "dialog-title",
305
+ className: cn("text-lg leading-none font-semibold", className),
306
+ ...props
307
+ }
308
+ );
309
+ }
310
+ function DialogDescription({
311
+ className,
312
+ ...props
313
+ }) {
314
+ return /* @__PURE__ */ jsx7(
315
+ DialogPrimitive.Description,
316
+ {
317
+ "data-slot": "dialog-description",
318
+ className: cn("text-muted-foreground text-sm", className),
319
+ ...props
320
+ }
321
+ );
322
+ }
323
+
324
+ // src/components/command.tsx
325
+ import { IconSearch } from "@tabler/icons-react";
326
+ import { Command as CommandPrimitive } from "cmdk";
327
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
328
+ function Command({
329
+ className,
330
+ ...props
331
+ }) {
332
+ return /* @__PURE__ */ jsx8(
333
+ CommandPrimitive,
334
+ {
335
+ "data-slot": "command",
336
+ className: cn(
337
+ "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
338
+ className
339
+ ),
340
+ ...props
341
+ }
342
+ );
343
+ }
344
+ function CommandDialog({
345
+ title = "Command Palette",
346
+ description = "Search for a command to run...",
347
+ children,
348
+ className,
349
+ showCloseButton = true,
350
+ ...props
351
+ }) {
352
+ return /* @__PURE__ */ jsxs4(Dialog, { ...props, children: [
353
+ /* @__PURE__ */ jsxs4(DialogHeader, { className: "sr-only", children: [
354
+ /* @__PURE__ */ jsx8(DialogTitle, { children: title }),
355
+ /* @__PURE__ */ jsx8(DialogDescription, { children: description })
356
+ ] }),
357
+ /* @__PURE__ */ jsx8(
358
+ DialogContent,
359
+ {
360
+ className: cn("overflow-hidden p-0", className),
361
+ showCloseButton,
362
+ children: /* @__PURE__ */ jsx8(Command, { className: "[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5", children })
363
+ }
364
+ )
365
+ ] });
366
+ }
367
+ function CommandInput({
368
+ className,
369
+ ...props
370
+ }) {
371
+ return /* @__PURE__ */ jsxs4(
372
+ "div",
373
+ {
374
+ "data-slot": "command-input-wrapper",
375
+ className: "flex h-9 items-center gap-2 border-b px-3",
376
+ children: [
377
+ /* @__PURE__ */ jsx8(IconSearch, { className: "size-4 shrink-0 opacity-50" }),
378
+ /* @__PURE__ */ jsx8(
379
+ CommandPrimitive.Input,
380
+ {
381
+ "data-slot": "command-input",
382
+ className: cn(
383
+ "placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
384
+ className
385
+ ),
386
+ ...props
387
+ }
388
+ )
389
+ ]
390
+ }
391
+ );
392
+ }
393
+ function CommandList({
394
+ className,
395
+ ...props
396
+ }) {
397
+ return /* @__PURE__ */ jsx8(
398
+ CommandPrimitive.List,
399
+ {
400
+ "data-slot": "command-list",
401
+ className: cn(
402
+ "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
403
+ className
404
+ ),
405
+ ...props
406
+ }
407
+ );
408
+ }
409
+ function CommandEmpty({
410
+ ...props
411
+ }) {
412
+ return /* @__PURE__ */ jsx8(
413
+ CommandPrimitive.Empty,
414
+ {
415
+ "data-slot": "command-empty",
416
+ className: "py-6 text-center text-sm",
417
+ ...props
418
+ }
419
+ );
420
+ }
421
+ function CommandGroup({
422
+ className,
423
+ ...props
424
+ }) {
425
+ return /* @__PURE__ */ jsx8(
426
+ CommandPrimitive.Group,
427
+ {
428
+ "data-slot": "command-group",
429
+ className: cn(
430
+ "text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
431
+ className
432
+ ),
433
+ ...props
434
+ }
435
+ );
436
+ }
437
+ function CommandSeparator({
438
+ className,
439
+ ...props
440
+ }) {
441
+ return /* @__PURE__ */ jsx8(
442
+ CommandPrimitive.Separator,
443
+ {
444
+ "data-slot": "command-separator",
445
+ className: cn("bg-border -mx-1 h-px", className),
446
+ ...props
447
+ }
448
+ );
449
+ }
450
+ function CommandItem({
451
+ className,
452
+ ...props
453
+ }) {
454
+ return /* @__PURE__ */ jsx8(
455
+ CommandPrimitive.Item,
456
+ {
457
+ "data-slot": "command-item",
458
+ className: cn(
459
+ "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
460
+ className
461
+ ),
462
+ ...props
463
+ }
464
+ );
465
+ }
466
+
467
+ // src/components/spotlight-search.tsx
468
+ import { IconSearch as IconSearch2 } from "@tabler/icons-react";
469
+ import * as React from "react";
470
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
471
+ function SpotlightSearch({
472
+ groups = [],
473
+ placeholder = "Search...",
474
+ emptyMessage = "No results found.",
475
+ className,
476
+ triggerClassName,
477
+ onSearch
478
+ }) {
479
+ const [open, setOpen] = React.useState(false);
480
+ React.useEffect(() => {
481
+ const down = (e) => {
482
+ if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
483
+ e.preventDefault();
484
+ setOpen((open2) => !open2);
485
+ }
486
+ };
487
+ document.addEventListener("keydown", down);
488
+ return () => document.removeEventListener("keydown", down);
489
+ }, []);
490
+ return /* @__PURE__ */ jsxs5(Fragment2, { children: [
491
+ /* @__PURE__ */ jsxs5(
492
+ Button,
493
+ {
494
+ variant: "outline",
495
+ className: cn(
496
+ "relative h-9 w-9 p-0 xl:h-9 xl:w-60 xl:justify-start xl:px-3 xl:py-2",
497
+ triggerClassName
498
+ ),
499
+ onClick: () => setOpen(true),
500
+ children: [
501
+ /* @__PURE__ */ jsx9(IconSearch2, { className: "h-4 w-4 xl:mr-2" }),
502
+ /* @__PURE__ */ jsx9("span", { className: "hidden xl:inline-flex", children: "Search..." }),
503
+ /* @__PURE__ */ jsxs5("kbd", { className: "pointer-events-none absolute right-1.5 top-1/2 hidden h-5 -translate-y-1/2 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 xl:flex", children: [
504
+ /* @__PURE__ */ jsx9("span", { className: "text-xs", children: "\u2318" }),
505
+ "K"
506
+ ] })
507
+ ]
508
+ }
509
+ ),
510
+ /* @__PURE__ */ jsxs5(
511
+ CommandDialog,
512
+ {
513
+ open,
514
+ onOpenChange: setOpen,
515
+ title: "Search",
516
+ description: "Search for pages, actions, and more",
517
+ showCloseButton: false,
518
+ className,
519
+ children: [
520
+ /* @__PURE__ */ jsx9(CommandInput, { placeholder, onValueChange: onSearch }),
521
+ /* @__PURE__ */ jsxs5(CommandList, { children: [
522
+ /* @__PURE__ */ jsx9(CommandEmpty, { children: emptyMessage }),
523
+ groups.map((group, index) => /* @__PURE__ */ jsxs5(React.Fragment, { children: [
524
+ index > 0 && /* @__PURE__ */ jsx9(CommandSeparator, {}),
525
+ /* @__PURE__ */ jsx9(CommandGroup, { heading: group.heading, children: group.items.map((item) => /* @__PURE__ */ jsxs5(
526
+ CommandItem,
527
+ {
528
+ onSelect: () => {
529
+ item.onSelect?.();
530
+ setOpen(false);
531
+ },
532
+ children: [
533
+ item.icon,
534
+ /* @__PURE__ */ jsx9("span", { children: item.title }),
535
+ item.shortcut && /* @__PURE__ */ jsx9("kbd", { className: "pointer-events-none ml-auto hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex", children: item.shortcut })
536
+ ]
537
+ },
538
+ item.id
539
+ )) })
540
+ ] }, group.heading))
541
+ ] })
542
+ ]
543
+ }
544
+ )
545
+ ] });
546
+ }
547
+
548
+ // src/components/app-header-actions.tsx
549
+ import { IconBell, IconLogout } from "@tabler/icons-react";
550
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
551
+ function AppHeaderActions({
552
+ user,
553
+ onLogout,
554
+ isLoggingOut = false,
555
+ searchGroups = [],
556
+ menuItems = [],
557
+ topMenuItems = [],
558
+ actions,
559
+ accountMenuFooter
560
+ }) {
561
+ const initials = user?.fullName?.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) || "U";
562
+ const displayName = user?.fullName ?? "Account";
563
+ const displaySubtext = user?.email ?? user?.phone ?? user?.handle ?? "";
564
+ return /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
565
+ /* @__PURE__ */ jsx10(SpotlightSearch, { groups: searchGroups }),
566
+ actions,
567
+ /* @__PURE__ */ jsx10(Button, { variant: "ghost", size: "icon", className: "relative", children: /* @__PURE__ */ jsx10(IconBell, { className: "size-5" }) }),
568
+ /* @__PURE__ */ jsxs6(DropdownMenu, { children: [
569
+ /* @__PURE__ */ jsx10(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(Button, { variant: "ghost", className: "flex items-center gap-2 px-2", children: [
570
+ /* @__PURE__ */ jsxs6(Avatar, { className: "size-8", children: [
571
+ /* @__PURE__ */ jsx10(AvatarImage, { src: user?.image ?? void 0 }),
572
+ /* @__PURE__ */ jsx10(AvatarFallback, { className: "text-xs", children: initials })
573
+ ] }),
574
+ /* @__PURE__ */ jsxs6("div", { className: "hidden flex-col items-start text-left md:flex", children: [
575
+ /* @__PURE__ */ jsx10("span", { className: "text-sm font-medium", children: displayName }),
576
+ /* @__PURE__ */ jsx10("span", { className: "text-xs text-muted-foreground", children: displaySubtext })
577
+ ] })
578
+ ] }) }),
579
+ /* @__PURE__ */ jsxs6(DropdownMenuContent, { align: "end", className: "w-56", children: [
580
+ topMenuItems.map((item) => /* @__PURE__ */ jsx10(
581
+ DropdownMenuItem,
582
+ {
583
+ onClick: item.onClick,
584
+ variant: item.variant,
585
+ asChild: item.href ? true : void 0,
586
+ children: item.href ? /* @__PURE__ */ jsxs6(Link, { href: item.href, onClick: item.onClick, children: [
587
+ item.icon && /* @__PURE__ */ jsx10("span", { className: "mr-2", children: item.icon }),
588
+ item.label
589
+ ] }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
590
+ item.icon && /* @__PURE__ */ jsx10("span", { className: "mr-2", children: item.icon }),
591
+ item.label
592
+ ] })
593
+ },
594
+ item.href ?? item.label
595
+ )),
596
+ topMenuItems.length > 0 && menuItems.length > 0 && /* @__PURE__ */ jsx10(DropdownMenuSeparator, {}),
597
+ menuItems.map((item) => /* @__PURE__ */ jsx10(
598
+ DropdownMenuItem,
599
+ {
600
+ onClick: item.onClick,
601
+ variant: item.variant,
602
+ asChild: item.href ? true : void 0,
603
+ children: item.href ? /* @__PURE__ */ jsxs6(Link, { href: item.href, onClick: item.onClick, children: [
604
+ item.icon && /* @__PURE__ */ jsx10("span", { className: "mr-2", children: item.icon }),
605
+ item.label
606
+ ] }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
607
+ item.icon && /* @__PURE__ */ jsx10("span", { className: "mr-2", children: item.icon }),
608
+ item.label
609
+ ] })
610
+ },
611
+ item.href ?? item.label
612
+ )),
613
+ accountMenuFooter && (topMenuItems.length > 0 || menuItems.length > 0) && /* @__PURE__ */ jsx10(DropdownMenuSeparator, {}),
614
+ accountMenuFooter,
615
+ onLogout && /* @__PURE__ */ jsxs6(Fragment3, { children: [
616
+ (topMenuItems.length > 0 || menuItems.length > 0 || accountMenuFooter) && /* @__PURE__ */ jsx10(DropdownMenuSeparator, {}),
617
+ /* @__PURE__ */ jsxs6(DropdownMenuItem, { onClick: onLogout, variant: "destructive", children: [
618
+ isLoggingOut ? /* @__PURE__ */ jsx10("span", { className: "mr-2", children: "..." }) : /* @__PURE__ */ jsx10(IconLogout, { className: "mr-2 size-4" }),
619
+ "Log out"
620
+ ] })
621
+ ] })
622
+ ] })
623
+ ] })
624
+ ] });
625
+ }
626
+ export {
627
+ AppHeaderActions
628
+ };
629
+ //# sourceMappingURL=app-header-actions.js.map