@alepha/ui 0.15.2 → 0.15.3

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 (84) hide show
  1. package/dist/admin/AdminAudits-BU-p1g7A.js +3 -0
  2. package/dist/admin/{AdminAudits-C0DPYw0W.js → AdminAudits-Oh7iAfQa.js} +2 -2
  3. package/dist/admin/AdminAudits-Oh7iAfQa.js.map +1 -0
  4. package/dist/admin/{AdminUserCreate-DiXi1EWB.js → AdminUserCreate-BVIm4JdN.js} +2 -2
  5. package/dist/admin/AdminUserCreate-BVIm4JdN.js.map +1 -0
  6. package/dist/admin/{AdminUserCreate-Chr-7hLk.js → AdminUserCreate-C1aInRDk.js} +1 -1
  7. package/dist/admin/{AdminUserLayout-D9bqGt6T.js → AdminUserLayout-BnfBC1gD.js} +2 -2
  8. package/dist/admin/{AdminUserLayout-D9bqGt6T.js.map → AdminUserLayout-BnfBC1gD.js.map} +1 -1
  9. package/dist/admin/{AdminUserLayout-CfeQHH6e.js → AdminUserLayout-gb-nbggz.js} +1 -1
  10. package/dist/admin/{AdminUserSettings-BnzRAcqV.js → AdminUserSettings-DZ9iWhJW.js} +2 -2
  11. package/dist/admin/AdminUserSettings-DZ9iWhJW.js.map +1 -0
  12. package/dist/admin/AdminUserSettings-Dg-wTRzN.js +3 -0
  13. package/dist/admin/{AdminUsers-CYkcUWCg.js → AdminUsers-D6Y5K8Am.js} +2 -2
  14. package/dist/admin/AdminUsers-D6Y5K8Am.js.map +1 -0
  15. package/dist/admin/AdminUsers-RCaxccEW.js +3 -0
  16. package/dist/admin/index.d.ts +37 -33
  17. package/dist/admin/index.d.ts.map +1 -1
  18. package/dist/admin/index.js +20 -13
  19. package/dist/admin/index.js.map +1 -1
  20. package/dist/auth/{Login-BAFVcX_J.js → Login-BBqTosqZ.js} +2 -2
  21. package/dist/auth/Login-BBqTosqZ.js.map +1 -0
  22. package/dist/auth/Login-CoU63mMR.js +4 -0
  23. package/dist/auth/Profile-Bxj8Nwom.js +150 -0
  24. package/dist/auth/Profile-Bxj8Nwom.js.map +1 -0
  25. package/dist/auth/Register-BV_oa_AK.js +4 -0
  26. package/dist/auth/{Register-CZRXEcWy.js → Register-Ce675Crg.js} +4 -4
  27. package/dist/auth/Register-Ce675Crg.js.map +1 -0
  28. package/dist/auth/ResetPassword-D5wC8GAA.js +3 -0
  29. package/dist/auth/{ResetPassword-DTYNsBIj.js → ResetPassword-DWdt7c40.js} +2 -2
  30. package/dist/auth/{ResetPassword-DTYNsBIj.js.map → ResetPassword-DWdt7c40.js.map} +1 -1
  31. package/dist/auth/{VerifyEmail-DolENWGn.js → VerifyEmail-CI4JwByV.js} +2 -2
  32. package/dist/auth/{VerifyEmail-DolENWGn.js.map → VerifyEmail-CI4JwByV.js.map} +1 -1
  33. package/dist/auth/VerifyEmail-DAfqVm5s.js +3 -0
  34. package/dist/auth/index.d.ts +6 -1
  35. package/dist/auth/index.d.ts.map +1 -1
  36. package/dist/auth/index.js +47 -13
  37. package/dist/auth/index.js.map +1 -1
  38. package/dist/core/index.d.ts +111 -29
  39. package/dist/core/index.d.ts.map +1 -1
  40. package/dist/core/index.js +324 -251
  41. package/dist/core/index.js.map +1 -1
  42. package/dist/demo/{DemoLogin-mtkN6340.js → DemoLogin-S-b15cmE.js} +2 -2
  43. package/dist/demo/DemoLogin-S-b15cmE.js.map +1 -0
  44. package/dist/demo/{DemoRegister-C0MW7anp.js → DemoRegister-B29MdAaZ.js} +3 -3
  45. package/dist/demo/DemoRegister-B29MdAaZ.js.map +1 -0
  46. package/dist/demo/index.js +2 -2
  47. package/package.json +3 -2
  48. package/src/admin/AdminRouter.ts +2 -2
  49. package/src/admin/components/audits/AdminAudits.tsx +1 -1
  50. package/src/admin/components/users/AdminUserCreate.tsx +1 -1
  51. package/src/admin/components/users/AdminUserLayout.tsx +1 -1
  52. package/src/admin/components/users/AdminUserSettings.tsx +1 -1
  53. package/src/admin/components/users/AdminUsers.tsx +1 -1
  54. package/src/admin/index.ts +11 -1
  55. package/src/auth/AuthRouter.ts +12 -0
  56. package/src/auth/components/Login.tsx +1 -1
  57. package/src/auth/components/Profile.tsx +157 -0
  58. package/src/auth/components/Register.tsx +2 -2
  59. package/src/auth/components/buttons/UserButton.tsx +34 -2
  60. package/src/auth/index.ts +11 -1
  61. package/src/core/UiRouter.ts +15 -0
  62. package/src/core/atoms/alephaThemeListAtom.ts +3 -1
  63. package/src/core/components/buttons/ActionButton.tsx +2 -2
  64. package/src/core/components/layout/AdminShell.tsx +46 -18
  65. package/src/core/components/layout/AppBar.tsx +235 -18
  66. package/src/core/components/layout/Omnibar.tsx +2 -2
  67. package/src/core/components/layout/Sidebar.tsx +1 -5
  68. package/src/core/index.ts +13 -27
  69. package/dist/admin/AdminAudits-BlGGKLof.js +0 -3
  70. package/dist/admin/AdminAudits-C0DPYw0W.js.map +0 -1
  71. package/dist/admin/AdminUserCreate-DiXi1EWB.js.map +0 -1
  72. package/dist/admin/AdminUserSettings-BnzRAcqV.js.map +0 -1
  73. package/dist/admin/AdminUserSettings-CXs-jtRv.js +0 -3
  74. package/dist/admin/AdminUsers-CYkcUWCg.js.map +0 -1
  75. package/dist/admin/AdminUsers-DdFXzrEn.js +0 -3
  76. package/dist/auth/Login-BAFVcX_J.js.map +0 -1
  77. package/dist/auth/Login-C5PUsp8I.js +0 -4
  78. package/dist/auth/Register-CZRXEcWy.js.map +0 -1
  79. package/dist/auth/Register-DMTs5ep_.js +0 -4
  80. package/dist/auth/ResetPassword-D-mhMtmx.js +0 -3
  81. package/dist/auth/VerifyEmail-BsrCmncc.js +0 -3
  82. package/dist/demo/DemoLogin-mtkN6340.js.map +0 -1
  83. package/dist/demo/DemoRegister-C0MW7anp.js.map +0 -1
  84. package/src/core/RootRouter.ts +0 -9
@@ -3,16 +3,16 @@ import { AlephaReactForm, FormValidationError, useForm, useFormState } from "ale
3
3
  import { $head, AlephaReactHead } from "alepha/react/head";
4
4
  import { AlephaReactI18n, useI18n } from "alepha/react/i18n";
5
5
  import { $cookie } from "alepha/server/cookies";
6
- import { $page, NestedView, useActive, useRouter } from "alepha/react/router";
7
- import { ActionIcon, Anchor, AppShell, Autocomplete, Badge, Box, Burger, Button, Card, Checkbox, Collapse, ColorInput, ColorSchemeScript, CopyButton, Divider, Fieldset, FileInput, Flex, Flex as Flex$1, Grid, Group, Input, Kbd, MantineProvider, Menu, MultiSelect, NumberInput, Pagination, PasswordInput, Popover, ScrollArea, SegmentedControl, Select, Slider, Stack, Switch, Table, TagsInput, Text, Text as Text$1, TextInput, Textarea, ThemeIcon, Tooltip, UnstyledButton, useComputedColorScheme, useMantineColorScheme, useMantineTheme } from "@mantine/core";
6
+ import { ActionIcon, Anchor, AppShell, Autocomplete, Badge, Box, Burger, Button, Card, Checkbox, Collapse, ColorInput, ColorSchemeScript, Container, CopyButton, Divider, Fieldset, FileInput, Flex, Flex as Flex$1, Grid, Group, Image, Input, Kbd, MantineProvider, Menu, MultiSelect, NumberInput, Pagination, PasswordInput, Popover, ScrollArea, SegmentedControl, Select, Slider, Stack, Switch, Table, TagsInput, Text, Text as Text$1, TextInput, Textarea, ThemeIcon, Tooltip, UnstyledButton, useComputedColorScheme, useMantineColorScheme, useMantineTheme } from "@mantine/core";
8
7
  import { ModalsProvider, modals } from "@mantine/modals";
8
+ import { IconAlertTriangle, IconArrowDown, IconArrowLeft, IconArrowUp, IconArrowsSort, IconAt, IconCalendar, IconCheck, IconChevronDown, IconChevronRight, IconClock, IconColorPicker, IconColumns, IconCopy, IconFile, IconFilter, IconGripVertical, IconHash, IconInfoCircle, IconInfoTriangle, IconKey, IconLanguage, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightCollapse, IconLetterCase, IconLink, IconList, IconMail, IconMoon, IconPalette, IconPhone, IconPlus, IconRefresh, IconSearch, IconSelector, IconSquareRounded, IconSun, IconToggleLeft, IconTrash, IconX } from "@tabler/icons-react";
9
+ import { Children, createElement, isValidElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
11
  import { Notifications, notifications } from "@mantine/notifications";
12
+ import { $page, Link, NestedView, useActive, useRouter } from "alepha/react/router";
10
13
  import { NavigationProgress, nprogress } from "@mantine/nprogress";
11
14
  import { ClientOnly, useAction, useEvents, useInject, useStore } from "alepha/react";
12
- import { IconAlertTriangle, IconArrowDown, IconArrowUp, IconArrowsSort, IconAt, IconCalendar, IconCheck, IconChevronDown, IconChevronRight, IconClock, IconColorPicker, IconColumns, IconCopy, IconFile, IconFilter, IconGripVertical, IconHash, IconInfoCircle, IconInfoTriangle, IconKey, IconLanguage, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightCollapse, IconLetterCase, IconLink, IconList, IconMail, IconMoon, IconPalette, IconPhone, IconPlus, IconRefresh, IconSearch, IconSelector, IconSquareRounded, IconSun, IconToggleLeft, IconTrash, IconX } from "@tabler/icons-react";
13
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
15
  import { Spotlight, spotlight } from "@mantine/spotlight";
15
- import { Children, createElement, isValidElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
16
16
  import { ui as ui$1 } from "@alepha/ui";
17
17
  import { useDebouncedCallback, useOs } from "@mantine/hooks";
18
18
  import { DateInput, DateTimePicker, TimeInput } from "@mantine/dates";
@@ -219,222 +219,6 @@ var ThemeProvider = class {
219
219
  }
220
220
  };
221
221
 
222
- //#endregion
223
- //#region ../../src/core/hooks/useTheme.ts
224
- /**
225
- * Hook to get and set the current theme.
226
- *
227
- * Returns a tuple with the current theme and a function to set the theme.
228
- *
229
- * ```tsx
230
- * const [theme, setTheme] = useTheme();
231
- * ```
232
- */
233
- const useTheme = () => {
234
- useStore(alephaThemeAtom);
235
- const themeProvider = useInject(ThemeProvider);
236
- const theme = themeProvider.getTheme();
237
- const setTheme = (theme) => {
238
- themeProvider.setTheme(theme.index);
239
- };
240
- return [theme, setTheme];
241
- };
242
-
243
- //#endregion
244
- //#region ../../src/core/services/ToastService.tsx
245
- var ToastService = class {
246
- raw = notifications;
247
- options = { default: {
248
- radius: "md",
249
- withBorder: true,
250
- withCloseButton: true,
251
- autoClose: 5e3,
252
- position: "top-center"
253
- } };
254
- show(options) {
255
- notifications.show({
256
- ...this.options.default,
257
- ...options
258
- });
259
- }
260
- info(options) {
261
- if (typeof options === "string") options = { message: options };
262
- this.show({
263
- color: "blue",
264
- icon: /* @__PURE__ */ jsx(IconInfoCircle, { size: 20 }),
265
- title: "Info",
266
- message: "Information notification",
267
- ...options
268
- });
269
- }
270
- success(options) {
271
- if (typeof options === "string") options = { message: options };
272
- this.show({
273
- color: "green",
274
- icon: /* @__PURE__ */ jsx(IconCheck, { size: 16 }),
275
- title: "Success",
276
- message: "Operation completed successfully",
277
- ...options
278
- });
279
- }
280
- warning(options) {
281
- if (typeof options === "string") options = { message: options };
282
- this.show({
283
- color: "yellow",
284
- icon: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 20 }),
285
- title: "Warning",
286
- message: "Please review this warning",
287
- ...options
288
- });
289
- }
290
- danger(options) {
291
- if (typeof options === "string") options = { message: options };
292
- this.show({
293
- color: "red",
294
- icon: /* @__PURE__ */ jsx(IconX, { size: 20 }),
295
- title: "Error",
296
- message: "An error occurred",
297
- ...options
298
- });
299
- }
300
- };
301
-
302
- //#endregion
303
- //#region ../../src/core/hooks/useToast.ts
304
- /**
305
- * Use this hook to access the Toast Service for showing notifications.
306
- *
307
- * @example
308
- * ```tsx
309
- * const toast = useToast();
310
- * toast.success({ message: "Operation completed successfully!" });
311
- * toast.error({ title: "Error", message: "Something went wrong" });
312
- * ```
313
- */
314
- const useToast = () => {
315
- return useInject(ToastService);
316
- };
317
-
318
- //#endregion
319
- //#region ../../src/core/constants/ui.ts
320
- const ui = {
321
- colors: {
322
- transparent: "transparent",
323
- background: "var(--alepha-background)",
324
- surface: "var(--alepha-surface)",
325
- elevated: "var(--alepha-elevated)",
326
- border: "var(--alepha-border)"
327
- },
328
- sizes: { icon: {
329
- xs: 12,
330
- sm: 16,
331
- md: 20,
332
- lg: 24,
333
- xl: 32
334
- } }
335
- };
336
-
337
- //#endregion
338
- //#region ../../src/core/helpers/isComponentType.ts
339
- function isComponentType(param) {
340
- if (isValidElement(param)) return false;
341
- return typeof param === "function" || typeof param === "object" && param !== null && "$$typeof" in param;
342
- }
343
-
344
- //#endregion
345
- //#region ../../src/core/helpers/renderIcon.tsx
346
- const renderIcon = (icon) => {
347
- if (!icon) return null;
348
- if (isValidElement(icon)) return icon;
349
- if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: ui$1.sizes.icon.md });
350
- return icon;
351
- };
352
-
353
- //#endregion
354
- //#region ../../src/core/components/layout/Omnibar.tsx
355
- const Omnibar = (props) => {
356
- const shortcut = props.shortcut ?? "mod+K";
357
- const searchPlaceholder = props.searchPlaceholder ?? "Search...";
358
- const nothingFound = props.nothingFound ?? "Nothing found...";
359
- const router = useRouter();
360
- const [user] = useStore("alepha.server.request.user");
361
- return /* @__PURE__ */ jsx(Spotlight, {
362
- actions: useMemo(() => router.concretePages.filter((page) => {
363
- if (page.can && !page.can()) return false;
364
- return true;
365
- }).map((page) => ({
366
- id: page.name,
367
- label: page.label ?? page.name,
368
- description: page.description,
369
- onClick: () => {
370
- if (page.staticName) return router.go(page.staticName, { params: page.params });
371
- return router.go(page.name);
372
- },
373
- leftSection: renderIcon(page.icon)
374
- })), [user]),
375
- shortcut,
376
- limit: 10,
377
- searchProps: {
378
- leftSection: /* @__PURE__ */ jsx(IconSearch, { size: ui.sizes.icon.md }),
379
- placeholder: searchPlaceholder
380
- },
381
- nothingFound
382
- });
383
- };
384
- var Omnibar_default = Omnibar;
385
-
386
- //#endregion
387
- //#region ../../src/core/components/layout/AlephaMantineProvider.tsx
388
- const AlephaMantineProvider = (props) => {
389
- const toast = useToast();
390
- const [theme] = useTheme();
391
- useEvents({
392
- "react:transition:begin": () => {
393
- nprogress.start();
394
- },
395
- "react:transition:end": () => {
396
- nprogress.complete();
397
- },
398
- "react:action:error": ({ error }) => {
399
- if (error instanceof FormValidationError || error instanceof TypeBoxError) return;
400
- toast.danger({
401
- title: error.name || "Error",
402
- message: error.message ?? "An error occurred while processing your action."
403
- });
404
- }
405
- }, []);
406
- const defaultColorScheme = props.mantine?.defaultColorScheme ?? theme.defaultColorScheme;
407
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ColorSchemeScript, {
408
- defaultColorScheme,
409
- ...props.colorSchemeScript
410
- }), /* @__PURE__ */ jsxs(MantineProvider, {
411
- ...props.mantine,
412
- defaultColorScheme,
413
- theme: {
414
- ...theme,
415
- ...props.mantine?.theme
416
- },
417
- children: [
418
- /* @__PURE__ */ jsx(Notifications, { ...props.notifications }),
419
- /* @__PURE__ */ jsx(NavigationProgress, { ...props.navigationProgress }),
420
- /* @__PURE__ */ jsxs(ModalsProvider, {
421
- ...props.modals,
422
- children: [props.omnibar !== false && /* @__PURE__ */ jsx(Omnibar_default, { ...props.omnibar }), props.children ?? /* @__PURE__ */ jsx(NestedView, {})]
423
- })
424
- ]
425
- })] });
426
- };
427
- var AlephaMantineProvider_default = AlephaMantineProvider;
428
-
429
- //#endregion
430
- //#region ../../src/core/RootRouter.ts
431
- var RootRouter = class {
432
- root = $page({
433
- path: "/",
434
- component: AlephaMantineProvider_default
435
- });
436
- };
437
-
438
222
  //#endregion
439
223
  //#region ../../src/core/components/data/ErrorViewer.tsx
440
224
  const getSizeConfig = (size = "sm") => {
@@ -653,6 +437,25 @@ const PromptDialog = ({ options, onSubmit }) => {
653
437
  };
654
438
  var PromptDialog_default = PromptDialog;
655
439
 
440
+ //#endregion
441
+ //#region ../../src/core/constants/ui.ts
442
+ const ui = {
443
+ colors: {
444
+ transparent: "transparent",
445
+ background: "var(--alepha-background)",
446
+ surface: "var(--alepha-surface)",
447
+ elevated: "var(--alepha-elevated)",
448
+ border: "var(--alepha-border)"
449
+ },
450
+ sizes: { icon: {
451
+ xs: 12,
452
+ sm: 16,
453
+ md: 20,
454
+ lg: 24,
455
+ xl: 32
456
+ } }
457
+ };
458
+
656
459
  //#endregion
657
460
  //#region ../../src/core/services/DialogService.tsx
658
461
  var DialogService = class {
@@ -782,6 +585,209 @@ var DialogService = class {
782
585
  image(src, options) {}
783
586
  };
784
587
 
588
+ //#endregion
589
+ //#region ../../src/core/services/ToastService.tsx
590
+ var ToastService = class {
591
+ raw = notifications;
592
+ options = { default: {
593
+ radius: "md",
594
+ withBorder: true,
595
+ withCloseButton: true,
596
+ autoClose: 5e3,
597
+ position: "top-center"
598
+ } };
599
+ show(options) {
600
+ notifications.show({
601
+ ...this.options.default,
602
+ ...options
603
+ });
604
+ }
605
+ info(options) {
606
+ if (typeof options === "string") options = { message: options };
607
+ this.show({
608
+ color: "blue",
609
+ icon: /* @__PURE__ */ jsx(IconInfoCircle, { size: 20 }),
610
+ title: "Info",
611
+ message: "Information notification",
612
+ ...options
613
+ });
614
+ }
615
+ success(options) {
616
+ if (typeof options === "string") options = { message: options };
617
+ this.show({
618
+ color: "green",
619
+ icon: /* @__PURE__ */ jsx(IconCheck, { size: 16 }),
620
+ title: "Success",
621
+ message: "Operation completed successfully",
622
+ ...options
623
+ });
624
+ }
625
+ warning(options) {
626
+ if (typeof options === "string") options = { message: options };
627
+ this.show({
628
+ color: "yellow",
629
+ icon: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 20 }),
630
+ title: "Warning",
631
+ message: "Please review this warning",
632
+ ...options
633
+ });
634
+ }
635
+ danger(options) {
636
+ if (typeof options === "string") options = { message: options };
637
+ this.show({
638
+ color: "red",
639
+ icon: /* @__PURE__ */ jsx(IconX, { size: 20 }),
640
+ title: "Error",
641
+ message: "An error occurred",
642
+ ...options
643
+ });
644
+ }
645
+ };
646
+
647
+ //#endregion
648
+ //#region ../../src/core/hooks/useTheme.ts
649
+ /**
650
+ * Hook to get and set the current theme.
651
+ *
652
+ * Returns a tuple with the current theme and a function to set the theme.
653
+ *
654
+ * ```tsx
655
+ * const [theme, setTheme] = useTheme();
656
+ * ```
657
+ */
658
+ const useTheme = () => {
659
+ useStore(alephaThemeAtom);
660
+ const themeProvider = useInject(ThemeProvider);
661
+ const theme = themeProvider.getTheme();
662
+ const setTheme = (theme) => {
663
+ themeProvider.setTheme(theme.index);
664
+ };
665
+ return [theme, setTheme];
666
+ };
667
+
668
+ //#endregion
669
+ //#region ../../src/core/hooks/useToast.ts
670
+ /**
671
+ * Use this hook to access the Toast Service for showing notifications.
672
+ *
673
+ * @example
674
+ * ```tsx
675
+ * const toast = useToast();
676
+ * toast.success({ message: "Operation completed successfully!" });
677
+ * toast.error({ title: "Error", message: "Something went wrong" });
678
+ * ```
679
+ */
680
+ const useToast = () => {
681
+ return useInject(ToastService);
682
+ };
683
+
684
+ //#endregion
685
+ //#region ../../src/core/helpers/isComponentType.ts
686
+ function isComponentType(param) {
687
+ if (isValidElement(param)) return false;
688
+ return typeof param === "function" || typeof param === "object" && param !== null && "$$typeof" in param;
689
+ }
690
+
691
+ //#endregion
692
+ //#region ../../src/core/helpers/renderIcon.tsx
693
+ const renderIcon = (icon) => {
694
+ if (!icon) return null;
695
+ if (isValidElement(icon)) return icon;
696
+ if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: ui$1.sizes.icon.md });
697
+ return icon;
698
+ };
699
+
700
+ //#endregion
701
+ //#region ../../src/core/components/layout/Omnibar.tsx
702
+ const Omnibar = (props) => {
703
+ const shortcut = props.shortcut ?? "mod+K";
704
+ const searchPlaceholder = props.searchPlaceholder ?? "Search...";
705
+ const nothingFound = props.nothingFound ?? "Nothing found...";
706
+ const router = useRouter();
707
+ const [user] = useStore("alepha.server.request.user");
708
+ return /* @__PURE__ */ jsx(Spotlight, {
709
+ actions: useMemo(() => router.concretePages.filter((page) => {
710
+ if (page.can && !page.can()) return false;
711
+ return true;
712
+ }).map((page) => ({
713
+ id: page.name,
714
+ label: page.label ?? page.name,
715
+ description: page.description,
716
+ onClick: () => {
717
+ if (page.staticName) return router.push(page.staticName, { params: page.params });
718
+ return router.push(page.name);
719
+ },
720
+ leftSection: renderIcon(page.icon)
721
+ })), [user]),
722
+ shortcut,
723
+ limit: 10,
724
+ searchProps: {
725
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: ui.sizes.icon.md }),
726
+ placeholder: searchPlaceholder
727
+ },
728
+ nothingFound
729
+ });
730
+ };
731
+ var Omnibar_default = Omnibar;
732
+
733
+ //#endregion
734
+ //#region ../../src/core/components/layout/AlephaMantineProvider.tsx
735
+ const AlephaMantineProvider = (props) => {
736
+ const toast = useToast();
737
+ const [theme] = useTheme();
738
+ useEvents({
739
+ "react:transition:begin": () => {
740
+ nprogress.start();
741
+ },
742
+ "react:transition:end": () => {
743
+ nprogress.complete();
744
+ },
745
+ "react:action:error": ({ error }) => {
746
+ if (error instanceof FormValidationError || error instanceof TypeBoxError) return;
747
+ toast.danger({
748
+ title: error.name || "Error",
749
+ message: error.message ?? "An error occurred while processing your action."
750
+ });
751
+ }
752
+ }, []);
753
+ const defaultColorScheme = props.mantine?.defaultColorScheme ?? theme.defaultColorScheme;
754
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ColorSchemeScript, {
755
+ defaultColorScheme,
756
+ ...props.colorSchemeScript
757
+ }), /* @__PURE__ */ jsxs(MantineProvider, {
758
+ ...props.mantine,
759
+ defaultColorScheme,
760
+ theme: {
761
+ ...theme,
762
+ ...props.mantine?.theme
763
+ },
764
+ children: [
765
+ /* @__PURE__ */ jsx(Notifications, { ...props.notifications }),
766
+ /* @__PURE__ */ jsx(NavigationProgress, { ...props.navigationProgress }),
767
+ /* @__PURE__ */ jsxs(ModalsProvider, {
768
+ ...props.modals,
769
+ children: [props.omnibar !== false && /* @__PURE__ */ jsx(Omnibar_default, { ...props.omnibar }), props.children ?? /* @__PURE__ */ jsx(NestedView, {})]
770
+ })
771
+ ]
772
+ })] });
773
+ };
774
+ var AlephaMantineProvider_default = AlephaMantineProvider;
775
+
776
+ //#endregion
777
+ //#region ../../src/core/UiRouter.ts
778
+ /**
779
+ * UI Router defining the root page with AlephaMantineProvider.
780
+ *
781
+ * - Use UiRouter when you need Alepha's Mantine-based UI components and theming.
782
+ * - Prefer to use $ui() for convenience. (Custom Factory of UiRouter)
783
+ */
784
+ var UiRouter = class {
785
+ root = $page({
786
+ path: "/",
787
+ component: AlephaMantineProvider_default
788
+ });
789
+ };
790
+
785
791
  //#endregion
786
792
  //#region ../../src/core/components/buttons/ActionButton.tsx
787
793
  const ActionMenuItem = (props) => {
@@ -2634,7 +2640,9 @@ var TypeForm_default = TypeForm;
2634
2640
  //#region ../../src/core/components/layout/AppBar.tsx
2635
2641
  const AppBar = (props) => {
2636
2642
  const { items = [] } = props;
2643
+ const router = useRouter();
2637
2644
  const renderItem = (item, index) => {
2645
+ if (item.can && !item.can()) return null;
2638
2646
  if ("type" in item) {
2639
2647
  if (item.type === "burger") return /* @__PURE__ */ jsx(BurgerButton_default, {}, index);
2640
2648
  if (item.type === "dark") return /* @__PURE__ */ jsx(DarkModeButton_default, { ...item.props }, index);
@@ -2642,17 +2650,70 @@ const AppBar = (props) => {
2642
2650
  if (item.type === "lang") return /* @__PURE__ */ jsx(LanguageButton_default, { ...item.props }, index);
2643
2651
  if (item.type === "spacer") return /* @__PURE__ */ jsx(Flex$1, { w: 16 }, index);
2644
2652
  if (item.type === "divider") return /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }, index);
2653
+ if (item.type === "logo") return renderLogo(item, index);
2654
+ if (item.type === "back") return renderBack(item, index);
2645
2655
  }
2646
2656
  if ("element" in item) return item.element;
2647
2657
  return null;
2648
2658
  };
2659
+ const renderLogo = (item, index) => {
2660
+ const { src, text, icon, href, height = 32, width, fontWeight = 700, fontSize = "lg" } = item.props ?? {};
2661
+ const logoContent = src ? /* @__PURE__ */ jsx(Image, {
2662
+ src,
2663
+ h: height,
2664
+ w: width,
2665
+ fit: "contain"
2666
+ }) : icon ? typeof icon === "function" ? /* @__PURE__ */ jsx(icon, {}) : icon : text ? /* @__PURE__ */ jsx(Text$1, {
2667
+ fw: fontWeight,
2668
+ size: fontSize,
2669
+ children: text
2670
+ }) : null;
2671
+ if (href) return /* @__PURE__ */ jsx(Anchor, {
2672
+ component: Link,
2673
+ href,
2674
+ underline: "never",
2675
+ c: "inherit",
2676
+ children: logoContent
2677
+ }, index);
2678
+ return /* @__PURE__ */ jsx(Flex$1, { children: logoContent }, index);
2679
+ };
2680
+ const renderBack = (item, index) => {
2681
+ const { label = "Back", iconOnly = true, href, icon } = item.props ?? {};
2682
+ const renderIcon = () => {
2683
+ if (!icon) return /* @__PURE__ */ jsx(IconArrowLeft, { size: 18 });
2684
+ if (typeof icon === "function") return /* @__PURE__ */ jsx(icon, { size: 18 });
2685
+ return icon;
2686
+ };
2687
+ const iconElement = renderIcon();
2688
+ const handleClick = () => {
2689
+ if (href) router.push(href);
2690
+ else router.back();
2691
+ };
2692
+ if (iconOnly) return /* @__PURE__ */ jsx(ActionButton_default, {
2693
+ icon: iconElement,
2694
+ variant: "subtle",
2695
+ color: "gray",
2696
+ onClick: handleClick,
2697
+ tooltip: {
2698
+ label,
2699
+ position: "bottom"
2700
+ }
2701
+ }, index);
2702
+ return /* @__PURE__ */ jsx(ActionButton_default, {
2703
+ leftSection: iconElement,
2704
+ variant: "subtle",
2705
+ color: "gray",
2706
+ onClick: handleClick,
2707
+ children: label
2708
+ }, index);
2709
+ };
2649
2710
  const leftItems = items.filter((item) => item.position === "left");
2650
2711
  const centerItems = items.filter((item) => item.position === "center");
2651
2712
  const rightItems = items.filter((item) => item.position === "right");
2652
- return /* @__PURE__ */ jsxs(Flex$1, {
2713
+ const content = /* @__PURE__ */ jsxs(Flex$1, {
2653
2714
  h: "100%",
2654
2715
  align: "center",
2655
- px: "md",
2716
+ px: props.container ? 0 : "md",
2656
2717
  justify: "space-between",
2657
2718
  ...props.flexProps,
2658
2719
  children: [
@@ -2681,6 +2742,12 @@ const AppBar = (props) => {
2681
2742
  })
2682
2743
  ]
2683
2744
  });
2745
+ if (props.container) return /* @__PURE__ */ jsx(Container, {
2746
+ h: "100%",
2747
+ ...typeof props.container === "boolean" ? {} : props.container,
2748
+ children: content
2749
+ });
2750
+ return content;
2684
2751
  };
2685
2752
  var AppBar_default = AppBar;
2686
2753
 
@@ -2826,6 +2893,7 @@ const SidebarItem = (props) => {
2826
2893
  href: props.item.href,
2827
2894
  target: props.item.target,
2828
2895
  size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
2896
+ tooltip: item.description,
2829
2897
  c: "var(--mantine-color-text)",
2830
2898
  color: "gray",
2831
2899
  variant: "subtle",
@@ -2836,13 +2904,9 @@ const SidebarItem = (props) => {
2836
2904
  w: "100%",
2837
2905
  align: "center",
2838
2906
  gap: "sm",
2839
- children: [renderIcon(item.icon), /* @__PURE__ */ jsxs(Flex$1, {
2907
+ children: [renderIcon(item.icon), /* @__PURE__ */ jsx(Flex$1, {
2840
2908
  direction: "column",
2841
- children: [/* @__PURE__ */ jsx(Flex$1, { children: item.label }), item.description && /* @__PURE__ */ jsx(Text$1, {
2842
- size: "xs",
2843
- c: "dimmed",
2844
- children: item.description
2845
- })]
2909
+ children: /* @__PURE__ */ jsx(Flex$1, { children: item.label })
2846
2910
  })]
2847
2911
  }),
2848
2912
  rightSection: item.children ? /* @__PURE__ */ jsx(Flex$1, { children: isOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }) }) : props.item.rightSection,
@@ -2910,7 +2974,7 @@ const AdminShell = (props) => {
2910
2974
  const resizeRef = useRef(null);
2911
2975
  const { collapsedWidth, collapseThreshold, maxWidth, hoverDelay, defaultWidth } = sidebar;
2912
2976
  const handleResizeStart = useCallback((e) => {
2913
- if (!props.resizable) return;
2977
+ if (!props.sidebarResizable) return;
2914
2978
  e.preventDefault();
2915
2979
  if (collapsed) {
2916
2980
  setSidebar({
@@ -2931,7 +2995,7 @@ const AdminShell = (props) => {
2931
2995
  };
2932
2996
  }
2933
2997
  }, [
2934
- props.resizable,
2998
+ props.sidebarResizable,
2935
2999
  collapsed,
2936
3000
  sidebar,
2937
3001
  setSidebar,
@@ -3038,6 +3102,8 @@ const AdminShell = (props) => {
3038
3102
  position: "left",
3039
3103
  type: "burger"
3040
3104
  }];
3105
+ const appBarProps = { ...props.appBarProps };
3106
+ appBarProps.container ??= props.container;
3041
3107
  const hasSidebar = showSidebar && props.sidebarProps !== void 0;
3042
3108
  const hasAppBar = hasSidebar || props.appBarProps || props.header;
3043
3109
  const headerHeight = hasAppBar ? 60 : 0;
@@ -3046,15 +3112,15 @@ const AdminShell = (props) => {
3046
3112
  const isExpandedByHover = collapsed && isHovering;
3047
3113
  const effectiveCollapsed = collapsed && !isHovering;
3048
3114
  const hoverWidth = Math.max(defaultWidth, collapsedWidth);
3049
- const sidebarWidth = hasSidebar ? effectiveCollapsed ? collapsedWidth : isExpandedByHover ? hoverWidth : expandedWidth : 0;
3050
- const canResize = props.resizable && !collapsed;
3115
+ const sidebarWidth = hasSidebar ? effectiveCollapsed || isExpandedByHover ? collapsedWidth : expandedWidth : 0;
3116
+ const canResize = props.sidebarResizable && !collapsed;
3051
3117
  return /* @__PURE__ */ jsxs(AppShell, {
3052
3118
  w: "100%",
3053
3119
  flex: 1,
3054
3120
  padding: "md",
3055
3121
  header: hasAppBar ? { height: 60 } : void 0,
3056
3122
  navbar: hasSidebar ? {
3057
- width: effectiveCollapsed ? { base: collapsedWidth } : isExpandedByHover ? { base: hoverWidth } : { base: expandedWidth },
3123
+ width: effectiveCollapsed || isExpandedByHover ? { base: collapsedWidth } : { base: expandedWidth },
3058
3124
  breakpoint: "sm",
3059
3125
  collapsed: { mobile: !opened }
3060
3126
  } : void 0,
@@ -3066,18 +3132,24 @@ const AdminShell = (props) => {
3066
3132
  ...props.appShellHeaderProps,
3067
3133
  children: props.header ?? /* @__PURE__ */ jsx(AppBar_default, {
3068
3134
  items: defaultAppBarItems,
3069
- ...props.appBarProps
3135
+ ...appBarProps
3070
3136
  })
3071
3137
  }),
3072
3138
  hasSidebar && /* @__PURE__ */ jsxs(AppShell.Navbar, {
3073
3139
  bg: ui.colors.surface,
3074
3140
  className: "alepha-sidebar-navbar",
3075
3141
  "data-resizing": isResizing,
3142
+ "data-hover-expanded": isExpandedByHover,
3076
3143
  onMouseEnter: handleNavbarMouseEnter,
3077
3144
  onMouseLeave: handleNavbarMouseLeave,
3078
3145
  style: {
3079
3146
  transform: collapseEffect.offset ? `translateX(${collapseEffect.offset}px)` : void 0,
3080
- opacity: collapseEffect.opacity
3147
+ opacity: collapseEffect.opacity,
3148
+ ...isExpandedByHover && {
3149
+ width: hoverWidth,
3150
+ zIndex: 200,
3151
+ boxShadow: "var(--mantine-shadow-xl)"
3152
+ }
3081
3153
  },
3082
3154
  ...props.appShellNavbarProps,
3083
3155
  children: [/* @__PURE__ */ jsx(Sidebar, {
@@ -3085,10 +3157,10 @@ const AdminShell = (props) => {
3085
3157
  collapsed: effectiveCollapsed
3086
3158
  }), (canResize || isExpandedByHover) && /* @__PURE__ */ jsx(Flex$1, {
3087
3159
  pos: "absolute",
3088
- right: -2,
3160
+ right: -6,
3089
3161
  top: 0,
3090
3162
  bottom: 0,
3091
- w: 4,
3163
+ w: 12,
3092
3164
  style: {
3093
3165
  cursor: "col-resize",
3094
3166
  userSelect: "none"
@@ -3107,7 +3179,14 @@ const AdminShell = (props) => {
3107
3179
  className: "alepha-sidebar-main",
3108
3180
  "data-resizing": isResizing,
3109
3181
  ...props.appShellMainProps,
3110
- children: props.children ?? /* @__PURE__ */ jsx(NestedView, {})
3182
+ children: props.container ? /* @__PURE__ */ jsx(Container, {
3183
+ w: "100%",
3184
+ flex: 1,
3185
+ display: "flex",
3186
+ style: { flexDirection: "column" },
3187
+ ...typeof props.container === "boolean" ? {} : props.container,
3188
+ children: props.children ?? /* @__PURE__ */ jsx(NestedView, {})
3189
+ }) : props.children ?? /* @__PURE__ */ jsx(NestedView, {})
3111
3190
  }),
3112
3191
  props.footer && /* @__PURE__ */ jsx(AppShell.Footer, {
3113
3192
  bg: ui.colors.surface,
@@ -3829,7 +3908,7 @@ const AlephaUI = $module({
3829
3908
  DialogService,
3830
3909
  ToastService,
3831
3910
  ThemeProvider,
3832
- RootRouter
3911
+ UiRouter
3833
3912
  ],
3834
3913
  register: (alepha) => {
3835
3914
  alepha.with(AlephaReactI18n);
@@ -3841,20 +3920,14 @@ const AlephaUI = $module({
3841
3920
  }
3842
3921
  });
3843
3922
  /**
3844
- * Register UI components and get the RootRouter instance.
3923
+ * Convenience function to configure and inject the UiRouter.
3845
3924
  */
3846
- const $ui = (opts = {}) => {
3925
+ const $ui = (options = {}) => {
3847
3926
  const { alepha } = $context();
3848
- /**
3849
- * If multi ui, should we have N themes ? or one $atom theme but with change based on current ui app ?
3850
- *
3851
- * App (theme=T1) -> Admin (theme=T2) ?
3852
- *
3853
- * > It can be done with onLeave()/onEnter() of the RootRouter to set the theme atom.
3854
- */
3855
- return alepha.inject(RootRouter);
3927
+ if (options.themes) alepha.store.set(alephaThemeListAtom, options.themes);
3928
+ return alepha.inject(UiRouter);
3856
3929
  };
3857
3930
 
3858
3931
  //#endregion
3859
- export { $ui, ActionButton_default as ActionButton, AdminShell_default as AdminShell, AlephaMantineProvider_default as AlephaMantineProvider, AlephaUI, AlertDialog_default as AlertDialog, AppBar_default as AppBar, BurgerButton_default as BurgerButton, ClipboardButton_default as ClipboardButton, ConfirmDialog_default as ConfirmDialog, Control_default as Control, ControlArray_default as ControlArray, ControlDate_default as ControlDate, ControlNumber_default as ControlNumber, ControlObject_default as ControlObject, ControlQueryBuilder_default as ControlQueryBuilder, ControlSelect_default as ControlSelect, DarkModeButton_default as DarkModeButton, DataTable_default as DataTable, DialogService, Flex, LanguageButton_default as LanguageButton, OPERATOR_INFO, Omnibar_default as Omnibar, OmnibarButton_default as OmnibarButton, PromptDialog_default as PromptDialog, RootRouter, Sidebar, Text, ThemeButton_default as ThemeButton, ThemeProvider, ToastService, ToggleSidebarButton_default as ToggleSidebarButton, TypeForm_default as TypeForm, alephaSidebarAtom, alephaThemeAtom, alephaThemeListAtom, capitalize, defaultTheme, extractSchemaFields, getDefaultIcon, getOperatorsForField, midnightTheme, prettyName, ui, useDialog, useToast };
3932
+ export { $ui, ActionButton_default as ActionButton, AdminShell_default as AdminShell, AlephaMantineProvider_default as AlephaMantineProvider, AlephaUI, AlertDialog_default as AlertDialog, AppBar_default as AppBar, BurgerButton_default as BurgerButton, ClipboardButton_default as ClipboardButton, ConfirmDialog_default as ConfirmDialog, Control_default as Control, ControlArray_default as ControlArray, ControlDate_default as ControlDate, ControlNumber_default as ControlNumber, ControlObject_default as ControlObject, ControlQueryBuilder_default as ControlQueryBuilder, ControlSelect_default as ControlSelect, DarkModeButton_default as DarkModeButton, DataTable_default as DataTable, DialogService, Flex, LanguageButton_default as LanguageButton, OPERATOR_INFO, Omnibar_default as Omnibar, OmnibarButton_default as OmnibarButton, PromptDialog_default as PromptDialog, Sidebar, Text, ThemeButton_default as ThemeButton, ThemeProvider, ToastService, ToggleSidebarButton_default as ToggleSidebarButton, TypeForm_default as TypeForm, UiRouter, alephaSidebarAtom, alephaThemeAtom, alephaThemeListAtom, capitalize, defaultTheme, extractSchemaFields, getDefaultIcon, getOperatorsForField, midnightTheme, prettyName, ui, useDialog, useToast };
3860
3933
  //# sourceMappingURL=index.js.map