@alepha/ui 0.11.3 → 0.11.4

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 (44) hide show
  1. package/dist/AlephaMantineProvider-CtIV-8MV.mjs +150 -0
  2. package/dist/AlephaMantineProvider-CtIV-8MV.mjs.map +1 -0
  3. package/dist/AlephaMantineProvider-D-vu9aCD.mjs +3 -0
  4. package/dist/{index.d.ts → index.d.mts} +290 -226
  5. package/dist/index.d.mts.map +1 -0
  6. package/dist/{index.js → index.mjs} +651 -730
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +14 -12
  9. package/src/RootRouter.ts +1 -1
  10. package/src/components/buttons/ActionButton.tsx +542 -0
  11. package/src/components/buttons/BurgerButton.tsx +20 -0
  12. package/src/components/{DarkModeButton.tsx → buttons/DarkModeButton.tsx} +27 -14
  13. package/src/components/buttons/LanguageButton.tsx +28 -0
  14. package/src/components/buttons/OmnibarButton.tsx +32 -0
  15. package/src/components/buttons/ToggleSidebarButton.tsx +28 -0
  16. package/src/components/dialogs/AlertDialog.tsx +10 -10
  17. package/src/components/dialogs/ConfirmDialog.tsx +18 -18
  18. package/src/components/dialogs/PromptDialog.tsx +5 -3
  19. package/src/components/{Control.tsx → form/Control.tsx} +6 -3
  20. package/src/components/{ControlDate.tsx → form/ControlDate.tsx} +4 -1
  21. package/src/components/{ControlSelect.tsx → form/ControlSelect.tsx} +4 -1
  22. package/src/components/{TypeForm.tsx → form/TypeForm.tsx} +8 -6
  23. package/src/components/layout/AdminShell.tsx +97 -0
  24. package/src/components/{AlephaMantineProvider.tsx → layout/AlephaMantineProvider.tsx} +30 -10
  25. package/src/components/layout/AppBar.tsx +133 -0
  26. package/src/components/layout/Omnibar.tsx +43 -0
  27. package/src/components/layout/Sidebar.tsx +410 -0
  28. package/src/components/table/DataTable.tsx +63 -0
  29. package/src/constants/ui.ts +8 -0
  30. package/src/index.ts +89 -24
  31. package/src/services/DialogService.tsx +13 -32
  32. package/src/services/ToastService.tsx +16 -4
  33. package/src/utils/parseInput.ts +1 -1
  34. package/dist/AlephaMantineProvider-DDbIijPF.js +0 -96
  35. package/dist/AlephaMantineProvider-DDbIijPF.js.map +0 -1
  36. package/dist/AlephaMantineProvider-pOu8hOzK.js +0 -3
  37. package/dist/index.d.ts.map +0 -1
  38. package/dist/index.js.map +0 -1
  39. package/src/components/Action.tsx +0 -345
  40. package/src/components/DataTable.css +0 -199
  41. package/src/components/DataTable.tsx +0 -724
  42. package/src/components/Omnibar.tsx +0 -77
  43. package/src/components/Sidebar.css +0 -217
  44. package/src/components/Sidebar.tsx +0 -255
@@ -0,0 +1,410 @@
1
+ import { useEvents, useRouter } from "@alepha/react";
2
+ import {
3
+ Flex,
4
+ type FlexProps,
5
+ type MantineBreakpoint,
6
+ Text,
7
+ ThemeIcon,
8
+ } from "@mantine/core";
9
+ import {
10
+ IconChevronDown,
11
+ IconChevronRight,
12
+ IconSquareRounded,
13
+ } from "@tabler/icons-react";
14
+ import { type ReactNode, useCallback, useState } from "react";
15
+ import ActionButton, { type ActionProps } from "../buttons/ActionButton.tsx";
16
+ import OmnibarButton from "../buttons/OmnibarButton.tsx";
17
+
18
+ export interface SidebarProps {
19
+ menu?: SidebarNode[];
20
+ top?: SidebarNode[];
21
+ bottom?: SidebarNode[];
22
+ onItemClick?: (item: SidebarMenuItem) => void;
23
+ onSearchClick?: () => void;
24
+ theme?: SidebarTheme;
25
+ flexProps?: Partial<FlexProps>;
26
+ collapsed?: boolean;
27
+ gap?: MantineBreakpoint;
28
+ }
29
+
30
+ export const Sidebar = (props: SidebarProps) => {
31
+ const router = useRouter();
32
+ const { top = [], bottom = [], onItemClick } = props;
33
+
34
+ const renderNode = (item: SidebarNode, key: number) => {
35
+ if ("type" in item) {
36
+ if (item.type === "spacer") {
37
+ return <Flex key={key} h={16} />;
38
+ }
39
+
40
+ if (item.type === "divider") {
41
+ return (
42
+ <Flex
43
+ key={key}
44
+ h={1}
45
+ bg={"var(--alepha-border)"}
46
+ my={"md"}
47
+ mx={"sm"}
48
+ />
49
+ );
50
+ }
51
+
52
+ if (item.type === "search") {
53
+ return <OmnibarButton collapsed={props.collapsed} key={key} />;
54
+ }
55
+
56
+ if (item.type === "section") {
57
+ if (props.collapsed) return;
58
+ return (
59
+ <Text
60
+ key={key}
61
+ size={"xs"}
62
+ c={"dimmed"}
63
+ mt={"md"}
64
+ mb={"xs"}
65
+ mx={"sm"}
66
+ tt={"uppercase"}
67
+ fw={"bold"}
68
+ >
69
+ {item.label}
70
+ </Text>
71
+ );
72
+ }
73
+ }
74
+
75
+ if ("element" in item) {
76
+ return <Flex key={key}>{item.element}</Flex>;
77
+ }
78
+
79
+ if (props.collapsed) {
80
+ return (
81
+ <SidebarCollapsedItem
82
+ key={key}
83
+ item={item}
84
+ level={0}
85
+ onItemClick={onItemClick}
86
+ theme={props.theme ?? {}}
87
+ />
88
+ );
89
+ }
90
+
91
+ return (
92
+ <SidebarItem
93
+ key={key}
94
+ item={item}
95
+ level={0}
96
+ onItemClick={onItemClick}
97
+ theme={props.theme ?? {}}
98
+ />
99
+ );
100
+ };
101
+
102
+ const padding = "md";
103
+ const gap = props.gap;
104
+ const menu =
105
+ props.menu ??
106
+ (router.concretePages.map((page) => ({
107
+ label: page.label ?? page.name,
108
+ description: page.description,
109
+ icon: page.icon,
110
+ href: page.path,
111
+ })) as SidebarMenuItem[]);
112
+
113
+ return (
114
+ <Flex
115
+ flex={1}
116
+ py={padding}
117
+ direction={"column"}
118
+ className={"overflow-auto"}
119
+ {...props.flexProps}
120
+ >
121
+ <Flex gap={gap} px={padding} direction={"column"}>
122
+ {top.map((item, index) => renderNode(item, index))}
123
+ {menu
124
+ .filter((it) => it.position === "top")
125
+ .map((item, index) => renderNode(item, index + top.length))}
126
+ </Flex>
127
+ <Flex
128
+ gap={gap}
129
+ px={padding}
130
+ direction={"column"}
131
+ flex={1}
132
+ className={"overflow-auto"}
133
+ >
134
+ {menu
135
+ .filter((it) => !it.position)
136
+ .map((item, index) => renderNode(item, index))}
137
+ </Flex>
138
+ <Flex gap={gap} px={padding} direction={"column"}>
139
+ {bottom.map((item, index) => renderNode(item, index))}
140
+ {menu
141
+ .filter((it) => it.position === "bottom")
142
+ .map((item, index) => renderNode(item, index + bottom.length))}
143
+ </Flex>
144
+ </Flex>
145
+ );
146
+ };
147
+
148
+ // ---------------------------------------------------------------------------------------------------------------------
149
+
150
+ export interface SidebarItemProps {
151
+ item: SidebarMenuItem;
152
+ level: number;
153
+ onItemClick?: (item: SidebarMenuItem) => void;
154
+ theme: SidebarTheme;
155
+ }
156
+
157
+ export const SidebarItem = (props: SidebarItemProps) => {
158
+ const { item, level } = props;
159
+ const maxLevel = 2; // 0, 1, 2 = 3 levels total
160
+
161
+ const router = useRouter();
162
+ const isActive = useCallback((item: SidebarMenuItem): boolean => {
163
+ if (!item.children) return false;
164
+ for (const child of item.children) {
165
+ if (child.href) {
166
+ if (router.isActive(child.href)) {
167
+ return true;
168
+ }
169
+ }
170
+ if (isActive(child)) {
171
+ return true;
172
+ }
173
+ }
174
+ return false;
175
+ }, []);
176
+
177
+ const [isOpen, setIsOpen] = useState<boolean>(isActive(item));
178
+
179
+ useEvents(
180
+ {
181
+ "react:transition:end": () => {
182
+ // recalculate open state on transition end to ensure correct state after navigation
183
+ if (isActive(item)) {
184
+ setIsOpen(true);
185
+ }
186
+ },
187
+ },
188
+ [],
189
+ );
190
+
191
+ if (level > maxLevel) return null;
192
+
193
+ const handleItemClick = (e: MouseEvent) => {
194
+ e.preventDefault();
195
+ if (item.children && item.children.length > 0) {
196
+ setIsOpen(!isOpen);
197
+ } else {
198
+ props.onItemClick?.(item);
199
+ item.onClick?.();
200
+ }
201
+ };
202
+
203
+ return (
204
+ <Flex direction={"column"} ps={level === 0 ? 0 : 32} pos={"relative"}>
205
+ <ActionButton
206
+ w={"100%"}
207
+ justify="space-between"
208
+ href={props.item.href}
209
+ variant={"subtle"}
210
+ size={
211
+ props.item.theme?.size ??
212
+ props.theme.button?.size ??
213
+ (level === 0 ? "sm" : "xs")
214
+ }
215
+ variantActive={"default"}
216
+ radius={props.item.theme?.radius ?? props.theme.button?.radius ?? "md"}
217
+ onClick={handleItemClick}
218
+ leftSection={
219
+ <Flex w={"100%"} align="center" gap={"sm"}>
220
+ {item.icon && (
221
+ <ThemeIcon
222
+ size={level === 0 ? "sm" : "xs"}
223
+ variant={"transparent"}
224
+ >
225
+ {item.icon}
226
+ </ThemeIcon>
227
+ )}
228
+ <Flex direction={"column"}>
229
+ <Flex>{item.label}</Flex>
230
+ {item.description && (
231
+ <Text size={"xs"} c={"dimmed"}>
232
+ {item.description}
233
+ </Text>
234
+ )}
235
+ </Flex>
236
+ </Flex>
237
+ }
238
+ rightSection={
239
+ item.children ? (
240
+ <Flex>
241
+ {isOpen ? (
242
+ <IconChevronDown size={14} />
243
+ ) : (
244
+ <IconChevronRight size={14} />
245
+ )}
246
+ </Flex>
247
+ ) : (
248
+ props.item.rightSection
249
+ )
250
+ }
251
+ {...props.item.actionProps}
252
+ />
253
+
254
+ {item.children && isOpen && (
255
+ <Flex direction={"column"} data-parent-level={level}>
256
+ <Flex
257
+ style={{
258
+ position: "absolute",
259
+ width: 1,
260
+ background:
261
+ "linear-gradient(to bottom, transparent, var(--alepha-border), transparent)",
262
+ top: 48,
263
+ left: 20 + 32 * level,
264
+ bottom: 16,
265
+ }}
266
+ />
267
+ {item.children.map((child, index) => (
268
+ <SidebarItem
269
+ key={index}
270
+ item={child}
271
+ level={level + 1}
272
+ onItemClick={props.onItemClick}
273
+ theme={props.theme}
274
+ />
275
+ ))}
276
+ </Flex>
277
+ )}
278
+ </Flex>
279
+ );
280
+ };
281
+
282
+ // ---------------------------------------------------------------------------------------------------------------------
283
+
284
+ export interface SidebarItemProps {
285
+ item: SidebarMenuItem;
286
+ level: number;
287
+ onItemClick?: (item: SidebarMenuItem) => void;
288
+ theme: SidebarTheme;
289
+ }
290
+
291
+ const SidebarCollapsedItem = (props: SidebarItemProps) => {
292
+ const { item, level } = props;
293
+
294
+ const router = useRouter();
295
+ const isActive = useCallback((item: SidebarMenuItem): boolean => {
296
+ if (!item.children) return false;
297
+ for (const child of item.children) {
298
+ if (child.href) {
299
+ if (router.isActive(child.href)) {
300
+ return true;
301
+ }
302
+ }
303
+ if (isActive(child)) {
304
+ return true;
305
+ }
306
+ }
307
+ return false;
308
+ }, []);
309
+
310
+ const [isOpen, setIsOpen] = useState<boolean>(isActive(item));
311
+
312
+ const handleItemClick = (e: MouseEvent) => {
313
+ e.preventDefault();
314
+ if (item.children && item.children.length > 0) {
315
+ setIsOpen(!isOpen);
316
+ } else {
317
+ props.onItemClick?.(item);
318
+ item.onClick?.();
319
+ }
320
+ };
321
+
322
+ return (
323
+ <ActionButton
324
+ variant={"subtle"}
325
+ size={
326
+ props.item.theme?.size ??
327
+ props.theme.button?.size ??
328
+ (level === 0 ? "sm" : "xs")
329
+ }
330
+ variantActive={"default"}
331
+ radius={props.item.theme?.radius ?? props.theme.button?.radius ?? "md"}
332
+ onClick={handleItemClick}
333
+ icon={item.icon ?? <IconSquareRounded />}
334
+ href={props.item.href}
335
+ menu={
336
+ item.children
337
+ ? {
338
+ position: "right",
339
+ on: "hover",
340
+ items: item.children.map((child) => ({
341
+ label: child.label,
342
+ href: child.href,
343
+ icon: child.icon,
344
+ children: child.children,
345
+ })),
346
+ }
347
+ : undefined
348
+ }
349
+ {...props.item.actionProps}
350
+ />
351
+ );
352
+ };
353
+
354
+ // ---------------------------------------------------------------------------------------------------------------------
355
+
356
+ export type SidebarNode =
357
+ | SidebarMenuItem
358
+ | SidebarSpacer
359
+ | SidebarDivider
360
+ | SidebarSearch
361
+ | SidebarElement
362
+ | SidebarSection;
363
+
364
+ export interface SidebarAbstractItem {
365
+ position?: "top" | "bottom";
366
+ }
367
+
368
+ export interface SidebarElement extends SidebarAbstractItem {
369
+ element: ReactNode;
370
+ }
371
+
372
+ export interface SidebarSpacer extends SidebarAbstractItem {
373
+ type: "spacer";
374
+ }
375
+
376
+ export interface SidebarDivider extends SidebarAbstractItem {
377
+ type: "divider";
378
+ }
379
+
380
+ export interface SidebarSearch extends SidebarAbstractItem {
381
+ type: "search";
382
+ }
383
+
384
+ export interface SidebarSection extends SidebarAbstractItem {
385
+ type: "section";
386
+ label: string;
387
+ }
388
+
389
+ export interface SidebarMenuItem extends SidebarAbstractItem {
390
+ label: string | ReactNode;
391
+ description?: string;
392
+ icon?: ReactNode;
393
+ href?: string;
394
+ activeStartsWith?: boolean; // Use startWith matching for active state
395
+ onClick?: () => void;
396
+ children?: SidebarMenuItem[];
397
+ rightSection?: ReactNode;
398
+ theme?: SidebarButtonTheme;
399
+ actionProps?: ActionProps;
400
+ }
401
+
402
+ export interface SidebarButtonTheme {
403
+ radius?: MantineBreakpoint;
404
+ size?: MantineBreakpoint;
405
+ }
406
+
407
+ export interface SidebarTheme {
408
+ button?: SidebarButtonTheme;
409
+ search?: SidebarButtonTheme;
410
+ }
@@ -0,0 +1,63 @@
1
+ import type { Async } from "@alepha/core";
2
+ import type { TableTrProps } from "@mantine/core";
3
+ import { Table, type TableProps } from "@mantine/core";
4
+ import { type ReactNode, useEffect, useState } from "react";
5
+ import ActionButton from "../buttons/ActionButton.tsx";
6
+
7
+ export interface DataTableColumn<T extends object> {
8
+ label: string;
9
+ value: (item: T) => ReactNode;
10
+ }
11
+
12
+ export interface DataTableProps<T extends object> {
13
+ items: T[] | (() => Async<T[]>);
14
+ columns: {
15
+ [key: string]: DataTableColumn<T>;
16
+ };
17
+ tableProps?: TableProps;
18
+ tableTrProps?: (item: T) => TableTrProps;
19
+ }
20
+
21
+ const DataTable = <T extends object>(props: DataTableProps<T>) => {
22
+ const [items, setItems] = useState<object[]>(
23
+ typeof props.items === "function" ? [] : props.items,
24
+ );
25
+
26
+ useEffect(() => {
27
+ if (typeof props.items !== "function") {
28
+ setItems(props.items);
29
+ }
30
+ }, [props.items]);
31
+
32
+ const head = Object.entries(props.columns).map(([key, col]) => (
33
+ <Table.Th key={key}>
34
+ <ActionButton justify={"space-between"} radius={0} fullWidth size={"xs"}>
35
+ {col.label}
36
+ </ActionButton>
37
+ </Table.Th>
38
+ ));
39
+
40
+ const rows = items.map((item, index) => {
41
+ const trProps = props.tableTrProps
42
+ ? props.tableTrProps(item as T)
43
+ : ({} as TableTrProps);
44
+ return (
45
+ <Table.Tr key={JSON.stringify(item)} {...trProps}>
46
+ {Object.entries(props.columns).map(([key, col]) => (
47
+ <Table.Td key={key}>{col.value(item as T)}</Table.Td>
48
+ ))}
49
+ </Table.Tr>
50
+ );
51
+ });
52
+
53
+ return (
54
+ <Table {...props.tableProps}>
55
+ <Table.Thead>
56
+ <Table.Tr>{head}</Table.Tr>
57
+ </Table.Thead>
58
+ <Table.Tbody>{rows}</Table.Tbody>
59
+ </Table>
60
+ );
61
+ };
62
+
63
+ export default DataTable;
@@ -0,0 +1,8 @@
1
+ export const ui = {
2
+ colors: {
3
+ transparent: "transparent",
4
+ background: "var(--alepha-background)",
5
+ surface: "var(--alepha-surface)",
6
+ elevated: "var(--alepha-elevated)",
7
+ },
8
+ };
package/src/index.ts CHANGED
@@ -1,37 +1,71 @@
1
1
  import { $module } from "@alepha/core";
2
- import { AlephaReact } from "@alepha/react";
3
- import type { ControlProps } from "./components/Control.tsx";
2
+ import { AlephaReactForm } from "@alepha/react-form";
3
+ import { AlephaReactHead } from "@alepha/react-head";
4
+ import { AlephaReactI18n } from "@alepha/react-i18n";
5
+ import type { ReactNode } from "react";
6
+ import type { ControlProps } from "./components/form/Control.tsx";
4
7
  import { RootRouter } from "./RootRouter.ts";
5
8
  import { DialogService } from "./services/DialogService.tsx";
6
9
  import { ToastService } from "./services/ToastService.tsx";
7
10
 
8
11
  // ---------------------------------------------------------------------------------------------------------------------
9
12
 
10
- export { Flex } from "@mantine/core";
11
- export { default as Action } from "./components/Action.tsx";
12
- export { default as AlephaMantineProvider } from "./components/AlephaMantineProvider.tsx";
13
- export { default as Control } from "./components/Control.tsx";
14
- export { default as ControlDate } from "./components/ControlDate.tsx";
15
- export { default as ControlSelect } from "./components/ControlSelect.tsx";
16
- export { default as DarkModeButton } from "./components/DarkModeButton.tsx";
13
+ export { Flex, Text } from "@mantine/core";
17
14
  export type {
18
- DataTableColumn,
19
- DataTableFilter,
20
- DataTableProps,
21
- DataTableSort,
22
- } from "./components/DataTable.tsx";
23
- export { default as DataTable } from "./components/DataTable.tsx";
24
- export { AlertDialog } from "./components/dialogs/AlertDialog.tsx";
25
- export { ConfirmDialog } from "./components/dialogs/ConfirmDialog.tsx";
26
- export { PromptDialog } from "./components/dialogs/PromptDialog.tsx";
27
- export { default as Omnibar } from "./components/Omnibar.tsx";
15
+ ActionClickButtonProps,
16
+ ActionCommonProps,
17
+ ActionMenuConfig,
18
+ ActionMenuItem,
19
+ ActionNavigationButtonProps,
20
+ ActionProps,
21
+ ActionSubmitButtonProps,
22
+ } from "./components/buttons/ActionButton.tsx";
23
+ export { default as ActionButton } from "./components/buttons/ActionButton.tsx";
24
+ export { default as DarkModeButton } from "./components/buttons/DarkModeButton.tsx";
25
+ export { default as OmnibarButton } from "./components/buttons/OmnibarButton.tsx";
26
+ export { default as AlertDialog } from "./components/dialogs/AlertDialog.tsx";
27
+ export { default as ConfirmDialog } from "./components/dialogs/ConfirmDialog.tsx";
28
+ export { default as PromptDialog } from "./components/dialogs/PromptDialog.tsx";
29
+ export { default as Control } from "./components/form/Control.tsx";
30
+ export { default as ControlDate } from "./components/form/ControlDate.tsx";
31
+ export { default as ControlSelect } from "./components/form/ControlSelect.tsx";
32
+ export { default as TypeForm } from "./components/form/TypeForm.tsx";
33
+ export { default as AdminShell } from "./components/layout/AdminShell.tsx";
34
+ export { default as AlephaMantineProvider } from "./components/layout/AlephaMantineProvider.tsx";
35
+ export type {
36
+ AppBarBurger,
37
+ AppBarDark,
38
+ AppBarDivider,
39
+ AppBarElement,
40
+ AppBarItem,
41
+ AppBarLang,
42
+ AppBarProps,
43
+ AppBarSearch,
44
+ AppBarSpacer,
45
+ } from "./components/layout/AppBar.tsx";
46
+ export { default as AppBar } from "./components/layout/AppBar.tsx";
47
+ export { default as Omnibar } from "./components/layout/Omnibar.tsx";
28
48
  export type {
29
- MenuItem,
49
+ SidebarAbstractItem,
50
+ SidebarButtonTheme,
51
+ SidebarDivider,
52
+ SidebarElement,
30
53
  SidebarItemProps,
54
+ SidebarMenuItem,
55
+ SidebarNode,
31
56
  SidebarProps,
32
- } from "./components/Sidebar.tsx";
33
- export { Sidebar, SidebarItem } from "./components/Sidebar.tsx";
34
- export { default as TypeForm } from "./components/TypeForm.tsx";
57
+ SidebarSearch,
58
+ SidebarSection,
59
+ SidebarSpacer,
60
+ SidebarTheme,
61
+ } from "./components/layout/Sidebar.tsx";
62
+ export { Sidebar } from "./components/layout/Sidebar.tsx";
63
+ export type {
64
+ DataTableColumn,
65
+ DataTableProps,
66
+ } from "./components/table/DataTable.tsx";
67
+ export { default as DataTable } from "./components/table/DataTable.tsx";
68
+ export * from "./constants/ui.ts";
35
69
  export { useDialog } from "./hooks/useDialog.ts";
36
70
  export { useToast } from "./hooks/useToast.ts";
37
71
  export * from "./RootRouter.ts";
@@ -57,6 +91,30 @@ declare module "typebox" {
57
91
  }
58
92
  }
59
93
 
94
+ declare module "@alepha/react" {
95
+ interface PageDescriptorOptions {
96
+ /**
97
+ * Human-readable title for the page.
98
+ * - for Sidebar navigation
99
+ * - for Omnibar navigation
100
+ * (soon)
101
+ * - for Breadcrumbs
102
+ * - for document title (with AlephaReactHead)
103
+ */
104
+ label?: string;
105
+
106
+ /**
107
+ * Optional description of the page.
108
+ */
109
+ description?: string;
110
+
111
+ /**
112
+ * Optional icon for the page.
113
+ */
114
+ icon?: ReactNode;
115
+ }
116
+ }
117
+
60
118
  // ---------------------------------------------------------------------------------------------------------------------
61
119
 
62
120
  /**
@@ -66,5 +124,12 @@ declare module "typebox" {
66
124
  */
67
125
  export const AlephaUI = $module({
68
126
  name: "alepha.ui",
69
- services: [AlephaReact, DialogService, ToastService, RootRouter],
127
+ services: [DialogService, ToastService, RootRouter],
128
+ register: (alepha) => {
129
+ alepha.with(AlephaReactI18n);
130
+ alepha.with(AlephaReactHead);
131
+ alepha.with(AlephaReactForm);
132
+ alepha.with(DialogService);
133
+ alepha.with(ToastService);
134
+ },
70
135
  });
@@ -1,9 +1,9 @@
1
1
  import type { ModalProps } from "@mantine/core";
2
2
  import { modals } from "@mantine/modals";
3
3
  import type { ReactNode } from "react";
4
- import { AlertDialog } from "../components/dialogs/AlertDialog";
5
- import { ConfirmDialog } from "../components/dialogs/ConfirmDialog";
6
- import { PromptDialog } from "../components/dialogs/PromptDialog";
4
+ import AlertDialog from "../components/dialogs/AlertDialog";
5
+ import ConfirmDialog from "../components/dialogs/ConfirmDialog";
6
+ import PromptDialog from "../components/dialogs/PromptDialog";
7
7
 
8
8
  // Base interfaces
9
9
  export interface BaseDialogOptions extends Partial<ModalProps> {
@@ -139,27 +139,11 @@ export class DialogService {
139
139
  * Open a custom dialog with provided content
140
140
  */
141
141
  public open(options?: BaseDialogOptions): string {
142
- const modalId = modals.open({
142
+ return modals.open({
143
143
  ...this.options.default,
144
144
  ...options,
145
145
  children: options?.content || options?.message,
146
146
  });
147
- return modalId;
148
- }
149
-
150
- /**
151
- * Show a JSON editor/viewer dialog
152
- */
153
- public json(data?: any, options?: BaseDialogOptions): void {
154
- // Implementation to be added
155
- }
156
-
157
- /**
158
- * Show a form dialog for structured input
159
- */
160
- public form(options?: BaseDialogOptions): Promise<any> {
161
- // Implementation to be added
162
- return Promise.resolve(null);
163
147
  }
164
148
 
165
149
  /**
@@ -174,34 +158,31 @@ export class DialogService {
174
158
  }
175
159
 
176
160
  /**
177
- * Show a loading/progress dialog with optional progress percentage
161
+ * Show a JSON editor/viewer dialog
178
162
  */
179
- public loading(options?: BaseDialogOptions & { progress?: number }): void {
163
+ public json(data?: any, options?: BaseDialogOptions): void {
180
164
  // Implementation to be added
181
165
  }
182
166
 
183
167
  /**
184
- * Show an image viewer/gallery dialog
168
+ * Show a form dialog for structured input
185
169
  */
186
- public image(src: string | string[], options?: BaseDialogOptions): void {
170
+ public form(options?: BaseDialogOptions): Promise<any> {
187
171
  // Implementation to be added
172
+ return Promise.resolve(null);
188
173
  }
189
174
 
190
175
  /**
191
- * Show a table/data grid dialog for displaying tabular data
176
+ * Show a loading/progress dialog with optional progress percentage
192
177
  */
193
- public table(
194
- data: any[],
195
- options?: BaseDialogOptions & { columns?: any[] },
196
- ): void {
178
+ public loading(options?: BaseDialogOptions & { progress?: number }): void {
197
179
  // Implementation to be added
198
180
  }
199
181
 
200
182
  /**
201
- * Show a multi-step wizard dialog
183
+ * Show an image viewer/gallery dialog
202
184
  */
203
- public wizard(steps: any[], options?: BaseDialogOptions): Promise<any> {
185
+ public image(src: string | string[], options?: BaseDialogOptions): void {
204
186
  // Implementation to be added
205
- return Promise.resolve(null);
206
187
  }
207
188
  }