@alepha/ui 0.11.11 → 0.11.12

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 (34) hide show
  1. package/README.md +17 -306
  2. package/dist/{AlephaMantineProvider-DCF5kidi.cjs → AlephaMantineProvider-CGpgWDt8.cjs} +1 -1
  3. package/dist/{AlephaMantineProvider-CzMrw7V3.js → AlephaMantineProvider-D8cHYAge.js} +3 -1
  4. package/dist/AlephaMantineProvider-D8cHYAge.js.map +1 -0
  5. package/dist/{AlephaMantineProvider-DlOEv9f0.cjs → AlephaMantineProvider-DuvZFAuk.cjs} +3 -1
  6. package/dist/AlephaMantineProvider-DuvZFAuk.cjs.map +1 -0
  7. package/dist/AlephaMantineProvider-twBqV4IO.js +3 -0
  8. package/dist/index.cjs +43 -40
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +36 -28
  11. package/dist/index.d.cts.map +1 -1
  12. package/dist/index.d.ts +36 -28
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +26 -24
  15. package/dist/index.js.map +1 -1
  16. package/package.json +55 -74
  17. package/src/components/buttons/ActionButton.tsx +1 -1
  18. package/src/components/buttons/LanguageButton.tsx +1 -1
  19. package/src/components/form/Control.tsx +1 -1
  20. package/src/components/form/ControlDate.tsx +1 -1
  21. package/src/components/form/ControlNumber.tsx +1 -1
  22. package/src/components/form/ControlQueryBuilder.tsx +2 -2
  23. package/src/components/form/ControlSelect.tsx +1 -1
  24. package/src/components/form/TypeForm.tsx +3 -3
  25. package/src/components/layout/AdminShell.tsx +1 -1
  26. package/src/components/table/DataTable.tsx +11 -11
  27. package/src/hooks/useDialog.ts +2 -0
  28. package/src/hooks/useToast.ts +2 -0
  29. package/src/index.ts +9 -5
  30. package/src/utils/extractSchemaFields.ts +1 -1
  31. package/src/utils/parseInput.ts +2 -2
  32. package/dist/AlephaMantineProvider-B4TwQ4tY.js +0 -3
  33. package/dist/AlephaMantineProvider-CzMrw7V3.js.map +0 -1
  34. package/dist/AlephaMantineProvider-DlOEv9f0.cjs.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,4 @@
1
- # Alepha Batch
2
-
3
- Efficiently process operations in groups by size or time.
1
+ # Alepha Ui
4
2
 
5
3
  ## Installation
6
4
 
@@ -12,318 +10,31 @@ npm install alepha
12
10
 
13
11
  ## Module
14
12
 
15
- This module allows you to group multiple asynchronous operations into a single "batch," which is then processed together.
16
- This is an essential pattern for improving performance, reducing I/O, and interacting efficiently with rate-limited APIs or databases.
17
-
18
- ```ts
19
- import { Alepha, $hook, run, t } from "alepha";
20
- import { $batch } from "alepha/batch";
21
-
22
- class LoggingService {
23
- // define the batch processor
24
- logBatch = $batch({
25
- schema: t.text(),
26
- maxSize: 10,
27
- maxDuration: [5, "seconds"],
28
- handler: async (items) => {
29
- console.log(`[BATCH LOG] Processing ${items.length} events:`, items);
30
- },
31
- });
32
-
33
- // example of how to use it
34
- onReady = $hook({
35
- on: "ready",
36
- handler: async () => {
37
- this.logBatch.push("Application started.");
38
- this.logBatch.push("User authenticated.");
39
- // ... more events pushed from elsewhere in the app
40
- },
41
- });
42
- }
43
- ```
44
-
45
- This module can be imported and used as follows:
46
-
47
- ```typescript
48
- import { Alepha, run } from "alepha";
49
- import { AlephaBatch } from "alepha/batch";
50
-
51
- const alepha = Alepha.create()
52
- .with(AlephaBatch);
53
-
54
- run(alepha);
55
- ```
13
+ Mantine
56
14
 
57
15
  ## API Reference
58
16
 
59
- ### Descriptors
60
-
61
- Descriptors are functions that define and configure various aspects of your application. They follow the convention of starting with ` $ ` and return configured descriptor instances.
62
-
63
- For more details, see the [Descriptors documentation](/docs/descriptors).
64
-
65
- #### $batch()
66
-
67
- Creates a batch processing descriptor for efficient grouping and processing of multiple operations.
68
-
69
- This descriptor provides a powerful batching mechanism that collects multiple individual items
70
- and processes them together in groups, significantly improving performance by reducing overhead
71
- and enabling bulk operations. It supports partitioning, concurrent processing, automatic flushing,
72
- and intelligent retry mechanisms for robust batch processing workflows.
73
-
74
- **Key Features**
75
-
76
- - **Intelligent Batching**: Groups items based on size and time thresholds
77
- - **Partitioning Support**: Process different types of items in separate batches
78
- - **Concurrent Processing**: Handle multiple batches simultaneously with configurable limits
79
- - **Automatic Flushing**: Time-based and size-based automatic batch execution
80
- - **Type Safety**: Full TypeScript support with schema validation using TypeBox
81
- - **Retry Logic**: Built-in retry mechanisms for failed batch operations
82
- - **Resource Management**: Automatic cleanup and graceful shutdown handling
83
-
84
- **Use Cases**
85
-
86
- Perfect for optimizing high-throughput operations:
87
- - Database bulk inserts and updates
88
- - API call batching and rate limit optimization
89
- - Log aggregation and bulk shipping
90
- - File processing and bulk uploads
91
- - Event processing and analytics ingestion
92
- - Notification delivery optimization
93
- - Cache invalidation batching
94
-
95
- **Basic database batch operations:**
96
- ```ts
97
- import { $batch } from "alepha/batch";
98
- import { t } from "alepha";
17
+ ### Hooks
99
18
 
100
- class UserService {
101
- userBatch = $batch({
102
- schema: t.object({
103
- id: t.text(),
104
- name: t.text(),
105
- email: t.text(),
106
- createdAt: t.optional(t.text())
107
- }),
108
- maxSize: 50, // Process up to 50 users at once
109
- maxDuration: [5, "seconds"], // Or flush every 5 seconds
110
- handler: async (users) => {
111
- // Bulk insert users - much faster than individual inserts
112
- console.log(`Processing batch of ${users.length} users`);
19
+ Hooks provide a way to tap into various lifecycle events and extend functionality. They follow the convention of starting with `use` and return configured hook instances.
113
20
 
114
- const result = await this.database.users.insertMany(users.map(user => ({
115
- ...user,
116
- createdAt: user.createdAt || new Date().toISOString()
117
- })));
21
+ #### useDialog()
118
22
 
119
- console.log(`Successfully inserted ${result.length} users`);
120
- return { inserted: result.length, userIds: result.map(r => r.id) };
121
- }
122
- });
23
+ Use this hook to access the Dialog Service for showing various dialog types.
123
24
 
124
- async createUser(userData: { name: string; email: string }) {
125
- // Individual calls are automatically batched
126
- const result = await this.userBatch.push({
127
- id: generateId(),
128
- name: userData.name,
129
- email: userData.email
130
- });
131
-
132
- return result; // Returns the batch result once batch is processed
133
- }
134
- }
135
- ```
136
-
137
- **API call batching with partitioning:**
138
- ```ts
139
- class NotificationService {
140
- notificationBatch = $batch({
141
- schema: t.object({
142
- userId: t.text(),
143
- type: t.enum(["email", "sms", "push"]),
144
- message: t.text(),
145
- priority: t.enum(["high", "normal", "low"])
146
- }),
147
- maxSize: 100,
148
- maxDuration: [10, "seconds"],
149
- // Partition by notification type for different processing
150
- partitionBy: (notification) => notification.type,
151
- concurrency: 3, // Process up to 3 different types simultaneously
152
- handler: async (notifications) => {
153
- const type = notifications[0].type; // All items in batch have same type
154
- console.log(`Processing ${notifications.length} ${type} notifications`);
155
-
156
- switch (type) {
157
- case 'email':
158
- return await this.emailProvider.sendBulk(notifications.map(n => ({
159
- to: n.userId,
160
- subject: 'Notification',
161
- body: n.message,
162
- priority: n.priority
163
- })));
164
-
165
- case 'sms':
166
- return await this.smsProvider.sendBulk(notifications.map(n => ({
167
- to: n.userId,
168
- message: n.message
169
- })));
170
-
171
- case 'push':
172
- return await this.pushProvider.sendBulk(notifications.map(n => ({
173
- userId: n.userId,
174
- title: 'Notification',
175
- body: n.message,
176
- priority: n.priority
177
- })));
178
- }
179
- }
180
- });
181
-
182
- async sendNotification(userId: string, type: 'email' | 'sms' | 'push', message: string, priority: 'high' | 'normal' | 'low' = 'normal') {
183
- // Notifications are automatically batched by type
184
- return await this.notificationBatch.push({
185
- userId,
186
- type,
187
- message,
188
- priority
189
- });
190
- }
191
- }
25
+ ```tsx
26
+ const dialog = useDialog();
27
+ await dialog.alert({ title: "Alert", message: "This is an alert message" });
28
+ const confirmed = await dialog.confirm({ title: "Confirm", message: "Are you sure?" });
29
+ const input = await dialog.prompt({ title: "Input", message: "Enter your name:" });
192
30
  ```
193
31
 
194
- **Log aggregation with retry logic:**
195
- ```ts
196
- class LoggingService {
197
- logBatch = $batch({
198
- schema: t.object({
199
- timestamp: t.number(),
200
- level: t.enum(["info", "warn", "error"]),
201
- message: t.text(),
202
- metadata: t.optional(t.record(t.text(), t.any())),
203
- source: t.text()
204
- }),
205
- maxSize: 1000, // Large batches for log efficiency
206
- maxDuration: [30, "seconds"], // Longer duration for log aggregation
207
- concurrency: 2, // Limit concurrent log shipments
208
- retry: {
209
- maxAttempts: 5,
210
- delay: [2, "seconds"],
211
- backoff: "exponential"
212
- },
213
- handler: async (logEntries) => {
214
- console.log(`Shipping ${logEntries.length} log entries`);
215
-
216
- try {
217
- // Ship logs to external service (e.g., Elasticsearch, Splunk)
218
- const response = await this.logShipper.bulkIndex({
219
- index: 'application-logs',
220
- body: logEntries.map(entry => ([
221
- { index: { _index: 'application-logs' } },
222
- {
223
- ...entry,
224
- '@timestamp': new Date(entry.timestamp).toISOString()
225
- }
226
- ])).flat()
227
- });
228
-
229
- if (response.errors) {
230
- console.error(`Some log entries failed to index`, response.errors);
231
- // Retry will be triggered by throwing
232
- throw new Error(`Failed to index ${response.errors.length} log entries`);
233
- }
234
-
235
- console.log(`Successfully shipped ${logEntries.length} log entries`);
236
- return { shipped: logEntries.length, indexedAt: Date.now() };
237
-
238
- } catch (error) {
239
- console.error(`Failed to ship logs batch`, error);
240
- throw error; // Trigger retry mechanism
241
- }
242
- }
243
- });
244
-
245
- async log(level: 'info' | 'warn' | 'error', message: string, metadata?: Record<string, any>, source: string = 'application') {
246
- // Individual log calls are batched and shipped efficiently
247
- return await this.logBatch.push({
248
- timestamp: Date.now(),
249
- level,
250
- message,
251
- metadata,
252
- source
253
- });
254
- }
255
- }
256
- ```
257
-
258
- **File processing with dynamic partitioning:**
259
- ```ts
260
- class FileProcessingService {
261
- fileProcessingBatch = $batch({
262
- schema: t.object({
263
- filePath: t.text(),
264
- fileType: t.enum(["image", "video", "document"]),
265
- processingOptions: t.object({
266
- quality: t.optional(t.enum(["low", "medium", "high"])),
267
- format: t.optional(t.text()),
268
- compress: t.optional(t.boolean())
269
- }),
270
- priority: t.enum(["urgent", "normal", "background"])
271
- }),
272
- maxSize: 20, // Smaller batches for file processing
273
- maxDuration: [2, "minutes"], // Reasonable time for file accumulation
274
- // Partition by file type and priority for optimal resource usage
275
- partitionBy: (file) => `${file.fileType}-${file.priority}`,
276
- concurrency: 4, // Multiple concurrent processing pipelines
277
- retry: {
278
- maxAttempts: 3,
279
- delay: [5, "seconds"]
280
- },
281
- handler: async (files) => {
282
- const fileType = files[0].fileType;
283
- const priority = files[0].priority;
284
-
285
- console.log(`Processing ${files.length} ${fileType} files with ${priority} priority`);
286
-
287
- try {
288
- const results = [];
289
-
290
- for (const file of files) {
291
- const result = await this.processFile(file.filePath, file.fileType, file.processingOptions);
292
- results.push({
293
- originalPath: file.filePath,
294
- processedPath: result.outputPath,
295
- size: result.size,
296
- duration: result.processingTime
297
- });
298
- }
299
-
300
- // Update database with batch results
301
- await this.updateProcessingStatus(results);
302
-
303
- console.log(`Successfully processed ${files.length} ${fileType} files`);
304
- return {
305
- processed: files.length,
306
- fileType,
307
- priority,
308
- totalSize: results.reduce((sum, r) => sum + r.size, 0),
309
- results
310
- };
32
+ #### useToast()
311
33
 
312
- } catch (error) {
313
- console.error(`Batch file processing failed for ${fileType} files`, error);
314
- throw error;
315
- }
316
- }
317
- });
34
+ Use this hook to access the Toast Service for showing notifications.
318
35
 
319
- async processFile(filePath: string, fileType: 'image' | 'video' | 'document', options: any, priority: 'urgent' | 'normal' | 'background' = 'normal') {
320
- // Files are automatically batched by type and priority
321
- return await this.fileProcessingBatch.push({
322
- filePath,
323
- fileType,
324
- processingOptions: options,
325
- priority
326
- });
327
- }
328
- }
36
+ ```tsx
37
+ const toast = useToast();
38
+ toast.success({ message: "Operation completed successfully!" });
39
+ toast.error({ title: "Error", message: "Something went wrong" });
329
40
  ```
@@ -1,3 +1,3 @@
1
- const require_AlephaMantineProvider = require('./AlephaMantineProvider-DlOEv9f0.cjs');
1
+ const require_AlephaMantineProvider = require('./AlephaMantineProvider-DuvZFAuk.cjs');
2
2
 
3
3
  exports.default = require_AlephaMantineProvider.AlephaMantineProvider_default;
@@ -70,9 +70,11 @@ var ToastService = class {
70
70
  * Use this hook to access the Toast Service for showing notifications.
71
71
  *
72
72
  * @example
73
+ * ```tsx
73
74
  * const toast = useToast();
74
75
  * toast.success({ message: "Operation completed successfully!" });
75
76
  * toast.error({ title: "Error", message: "Something went wrong" });
77
+ * ```
76
78
  */
77
79
  const useToast = () => {
78
80
  return useInject(ToastService);
@@ -147,4 +149,4 @@ var AlephaMantineProvider_default = AlephaMantineProvider;
147
149
 
148
150
  //#endregion
149
151
  export { ToastService as i, Omnibar_default as n, useToast as r, AlephaMantineProvider_default as t };
150
- //# sourceMappingURL=AlephaMantineProvider-CzMrw7V3.js.map
152
+ //# sourceMappingURL=AlephaMantineProvider-D8cHYAge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AlephaMantineProvider-D8cHYAge.js","names":["Omnibar"],"sources":["../src/services/ToastService.tsx","../src/hooks/useToast.ts","../src/components/layout/Omnibar.tsx","../src/components/layout/AlephaMantineProvider.tsx"],"sourcesContent":["import type { NotificationData } from \"@mantine/notifications\";\nimport { notifications } from \"@mantine/notifications\";\nimport {\n IconAlertTriangle,\n IconCheck,\n IconInfoCircle,\n IconX,\n} from \"@tabler/icons-react\";\n\nexport interface ToastServiceOptions {\n default?: Partial<NotificationData>;\n}\n\nexport class ToastService {\n protected readonly raw = notifications;\n\n public readonly options: ToastServiceOptions = {\n default: {\n autoClose: 5000,\n withCloseButton: true,\n position: \"top-center\",\n },\n };\n\n public show(options: NotificationData) {\n notifications.show({\n ...this.options.default,\n ...options,\n });\n }\n\n public info(options: Partial<NotificationData> | string) {\n if (typeof options === \"string\") {\n options = { message: options };\n }\n this.show({\n color: \"blue\",\n icon: <IconInfoCircle size={20} />,\n title: \"Info\",\n message: \"Information notification\",\n ...options,\n });\n }\n\n public success(options: Partial<NotificationData> | string) {\n if (typeof options === \"string\") {\n options = { message: options };\n }\n this.show({\n color: \"green\",\n icon: <IconCheck size={16} />,\n title: \"Success\",\n message: \"Operation completed successfully\",\n ...options,\n });\n }\n\n public warning(options: Partial<NotificationData> | string) {\n if (typeof options === \"string\") {\n options = { message: options };\n }\n this.show({\n color: \"yellow\",\n icon: <IconAlertTriangle size={20} />,\n title: \"Warning\",\n message: \"Please review this warning\",\n ...options,\n });\n }\n\n public danger(options: Partial<NotificationData> | string) {\n if (typeof options === \"string\") {\n options = { message: options };\n }\n this.show({\n color: \"red\",\n icon: <IconX size={20} />,\n title: \"Error\",\n message: \"An error occurred\",\n ...options,\n });\n }\n}\n","import { useInject } from \"@alepha/react\";\nimport { ToastService } from \"../services/ToastService.tsx\";\n\n/**\n * Use this hook to access the Toast Service for showing notifications.\n *\n * @example\n * ```tsx\n * const toast = useToast();\n * toast.success({ message: \"Operation completed successfully!\" });\n * toast.error({ title: \"Error\", message: \"Something went wrong\" });\n * ```\n */\nexport const useToast = (): ToastService => {\n return useInject(ToastService);\n};\n","import { useRouter } from \"@alepha/react\";\nimport { Spotlight, type SpotlightActionData } from \"@mantine/spotlight\";\nimport { IconSearch } from \"@tabler/icons-react\";\nimport { type ReactNode, useMemo } from \"react\";\n\nexport interface OmnibarProps {\n shortcut?: string | string[];\n searchPlaceholder?: string;\n nothingFound?: ReactNode;\n}\n\nconst Omnibar = (props: OmnibarProps) => {\n const shortcut = props.shortcut ?? \"mod+K\";\n const searchPlaceholder = props.searchPlaceholder ?? \"Search...\";\n const nothingFound = props.nothingFound ?? \"Nothing found...\";\n const router = useRouter();\n const actions: SpotlightActionData[] = useMemo(\n () =>\n router.concretePages.map((page) => ({\n id: page.name,\n label: page.label ?? page.name,\n description: page.description,\n onClick: () => router.go(page.path ?? page.name),\n leftSection: page.icon,\n })),\n [],\n );\n\n return (\n <Spotlight\n actions={actions}\n shortcut={shortcut}\n limit={10}\n searchProps={{\n leftSection: <IconSearch size={20} />,\n placeholder: searchPlaceholder,\n }}\n nothingFound={nothingFound}\n />\n );\n};\n\nexport default Omnibar;\n","import { NestedView, useEvents } from \"@alepha/react\";\nimport type {\n ColorSchemeScriptProps,\n MantineProviderProps,\n} from \"@mantine/core\";\nimport { ColorSchemeScript, MantineProvider } from \"@mantine/core\";\nimport { ModalsProvider, type ModalsProviderProps } from \"@mantine/modals\";\nimport { Notifications, type NotificationsProps } from \"@mantine/notifications\";\nimport type { NavigationProgressProps } from \"@mantine/nprogress\";\nimport { NavigationProgress, nprogress } from \"@mantine/nprogress\";\nimport type { ReactNode } from \"react\";\nimport { useToast } from \"../../hooks/useToast.ts\";\nimport Omnibar, { type OmnibarProps } from \"./Omnibar.tsx\";\n\nexport interface AlephaMantineProviderProps {\n children?: ReactNode;\n mantine?: MantineProviderProps;\n colorSchemeScript?: ColorSchemeScriptProps;\n navigationProgress?: NavigationProgressProps;\n notifications?: NotificationsProps;\n modals?: ModalsProviderProps;\n omnibar?: OmnibarProps;\n}\n\nconst AlephaMantineProvider = (props: AlephaMantineProviderProps) => {\n const toast = useToast();\n\n useEvents(\n {\n \"react:transition:begin\": () => {\n nprogress.start();\n },\n \"react:transition:end\": () => {\n nprogress.complete();\n },\n \"react:action:error\": () => {\n toast.danger(\"An error occurred while processing your action.\");\n },\n },\n [],\n );\n\n return (\n <>\n <ColorSchemeScript\n defaultColorScheme={props.mantine?.defaultColorScheme}\n {...props.colorSchemeScript}\n />\n <MantineProvider\n {...props.mantine}\n theme={{\n primaryColor: \"gray\",\n primaryShade: {\n light: 9,\n dark: 8,\n },\n cursorType: \"pointer\",\n ...props.mantine?.theme,\n }}\n >\n <Notifications {...props.notifications} />\n <NavigationProgress {...props.navigationProgress} />\n <ModalsProvider {...props.modals}>\n <Omnibar {...props.omnibar} />\n {props.children ?? <NestedView />}\n </ModalsProvider>\n </MantineProvider>\n </>\n );\n};\n\nexport default AlephaMantineProvider;\n"],"mappings":";;;;;;;;;;;AAaA,IAAa,eAAb,MAA0B;CACxB,AAAmB,MAAM;CAEzB,AAAgB,UAA+B,EAC7C,SAAS;EACP,WAAW;EACX,iBAAiB;EACjB,UAAU;EACX,EACF;CAED,AAAO,KAAK,SAA2B;AACrC,gBAAc,KAAK;GACjB,GAAG,KAAK,QAAQ;GAChB,GAAG;GACJ,CAAC;;CAGJ,AAAO,KAAK,SAA6C;AACvD,MAAI,OAAO,YAAY,SACrB,WAAU,EAAE,SAAS,SAAS;AAEhC,OAAK,KAAK;GACR,OAAO;GACP,MAAM,oBAAC,kBAAe,MAAM,KAAM;GAClC,OAAO;GACP,SAAS;GACT,GAAG;GACJ,CAAC;;CAGJ,AAAO,QAAQ,SAA6C;AAC1D,MAAI,OAAO,YAAY,SACrB,WAAU,EAAE,SAAS,SAAS;AAEhC,OAAK,KAAK;GACR,OAAO;GACP,MAAM,oBAAC,aAAU,MAAM,KAAM;GAC7B,OAAO;GACP,SAAS;GACT,GAAG;GACJ,CAAC;;CAGJ,AAAO,QAAQ,SAA6C;AAC1D,MAAI,OAAO,YAAY,SACrB,WAAU,EAAE,SAAS,SAAS;AAEhC,OAAK,KAAK;GACR,OAAO;GACP,MAAM,oBAAC,qBAAkB,MAAM,KAAM;GACrC,OAAO;GACP,SAAS;GACT,GAAG;GACJ,CAAC;;CAGJ,AAAO,OAAO,SAA6C;AACzD,MAAI,OAAO,YAAY,SACrB,WAAU,EAAE,SAAS,SAAS;AAEhC,OAAK,KAAK;GACR,OAAO;GACP,MAAM,oBAAC,SAAM,MAAM,KAAM;GACzB,OAAO;GACP,SAAS;GACT,GAAG;GACJ,CAAC;;;;;;;;;;;;;;;;ACnEN,MAAa,iBAA+B;AAC1C,QAAO,UAAU,aAAa;;;;;ACHhC,MAAM,WAAW,UAAwB;CACvC,MAAM,WAAW,MAAM,YAAY;CACnC,MAAM,oBAAoB,MAAM,qBAAqB;CACrD,MAAM,eAAe,MAAM,gBAAgB;CAC3C,MAAM,SAAS,WAAW;AAa1B,QACE,oBAAC;EACC,SAdmC,cAEnC,OAAO,cAAc,KAAK,UAAU;GAClC,IAAI,KAAK;GACT,OAAO,KAAK,SAAS,KAAK;GAC1B,aAAa,KAAK;GAClB,eAAe,OAAO,GAAG,KAAK,QAAQ,KAAK,KAAK;GAChD,aAAa,KAAK;GACnB,EAAE,EACL,EAAE,CACH;EAKa;EACV,OAAO;EACP,aAAa;GACX,aAAa,oBAAC,cAAW,MAAM,KAAM;GACrC,aAAa;GACd;EACa;GACd;;AAIN,sBAAe;;;;AClBf,MAAM,yBAAyB,UAAsC;CACnE,MAAM,QAAQ,UAAU;AAExB,WACE;EACE,gCAAgC;AAC9B,aAAU,OAAO;;EAEnB,8BAA8B;AAC5B,aAAU,UAAU;;EAEtB,4BAA4B;AAC1B,SAAM,OAAO,kDAAkD;;EAElE,EACD,EAAE,CACH;AAED,QACE,4CACE,oBAAC;EACC,oBAAoB,MAAM,SAAS;EACnC,GAAI,MAAM;GACV,EACF,qBAAC;EACC,GAAI,MAAM;EACV,OAAO;GACL,cAAc;GACd,cAAc;IACZ,OAAO;IACP,MAAM;IACP;GACD,YAAY;GACZ,GAAG,MAAM,SAAS;GACnB;;GAED,oBAAC,iBAAc,GAAI,MAAM,gBAAiB;GAC1C,oBAAC,sBAAmB,GAAI,MAAM,qBAAsB;GACpD,qBAAC;IAAe,GAAI,MAAM;eACxB,oBAACA,mBAAQ,GAAI,MAAM,UAAW,EAC7B,MAAM,YAAY,oBAAC,eAAa;KAClB;;GACD,IACjB;;AAIP,oCAAe"}
@@ -70,9 +70,11 @@ var ToastService = class {
70
70
  * Use this hook to access the Toast Service for showing notifications.
71
71
  *
72
72
  * @example
73
+ * ```tsx
73
74
  * const toast = useToast();
74
75
  * toast.success({ message: "Operation completed successfully!" });
75
76
  * toast.error({ title: "Error", message: "Something went wrong" });
77
+ * ```
76
78
  */
77
79
  const useToast = () => {
78
80
  return (0, __alepha_react.useInject)(ToastService);
@@ -170,4 +172,4 @@ Object.defineProperty(exports, 'useToast', {
170
172
  return useToast;
171
173
  }
172
174
  });
173
- //# sourceMappingURL=AlephaMantineProvider-DlOEv9f0.cjs.map
175
+ //# sourceMappingURL=AlephaMantineProvider-DuvZFAuk.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AlephaMantineProvider-DuvZFAuk.cjs","names":["notifications","IconInfoCircle","IconCheck","IconAlertTriangle","IconX","Spotlight","IconSearch","ColorSchemeScript","MantineProvider","Notifications","NavigationProgress","ModalsProvider","Omnibar","NestedView"],"sources":["../src/services/ToastService.tsx","../src/hooks/useToast.ts","../src/components/layout/Omnibar.tsx","../src/components/layout/AlephaMantineProvider.tsx"],"sourcesContent":["import type { NotificationData } from \"@mantine/notifications\";\nimport { notifications } from \"@mantine/notifications\";\nimport {\n IconAlertTriangle,\n IconCheck,\n IconInfoCircle,\n IconX,\n} from \"@tabler/icons-react\";\n\nexport interface ToastServiceOptions {\n default?: Partial<NotificationData>;\n}\n\nexport class ToastService {\n protected readonly raw = notifications;\n\n public readonly options: ToastServiceOptions = {\n default: {\n autoClose: 5000,\n withCloseButton: true,\n position: \"top-center\",\n },\n };\n\n public show(options: NotificationData) {\n notifications.show({\n ...this.options.default,\n ...options,\n });\n }\n\n public info(options: Partial<NotificationData> | string) {\n if (typeof options === \"string\") {\n options = { message: options };\n }\n this.show({\n color: \"blue\",\n icon: <IconInfoCircle size={20} />,\n title: \"Info\",\n message: \"Information notification\",\n ...options,\n });\n }\n\n public success(options: Partial<NotificationData> | string) {\n if (typeof options === \"string\") {\n options = { message: options };\n }\n this.show({\n color: \"green\",\n icon: <IconCheck size={16} />,\n title: \"Success\",\n message: \"Operation completed successfully\",\n ...options,\n });\n }\n\n public warning(options: Partial<NotificationData> | string) {\n if (typeof options === \"string\") {\n options = { message: options };\n }\n this.show({\n color: \"yellow\",\n icon: <IconAlertTriangle size={20} />,\n title: \"Warning\",\n message: \"Please review this warning\",\n ...options,\n });\n }\n\n public danger(options: Partial<NotificationData> | string) {\n if (typeof options === \"string\") {\n options = { message: options };\n }\n this.show({\n color: \"red\",\n icon: <IconX size={20} />,\n title: \"Error\",\n message: \"An error occurred\",\n ...options,\n });\n }\n}\n","import { useInject } from \"@alepha/react\";\nimport { ToastService } from \"../services/ToastService.tsx\";\n\n/**\n * Use this hook to access the Toast Service for showing notifications.\n *\n * @example\n * ```tsx\n * const toast = useToast();\n * toast.success({ message: \"Operation completed successfully!\" });\n * toast.error({ title: \"Error\", message: \"Something went wrong\" });\n * ```\n */\nexport const useToast = (): ToastService => {\n return useInject(ToastService);\n};\n","import { useRouter } from \"@alepha/react\";\nimport { Spotlight, type SpotlightActionData } from \"@mantine/spotlight\";\nimport { IconSearch } from \"@tabler/icons-react\";\nimport { type ReactNode, useMemo } from \"react\";\n\nexport interface OmnibarProps {\n shortcut?: string | string[];\n searchPlaceholder?: string;\n nothingFound?: ReactNode;\n}\n\nconst Omnibar = (props: OmnibarProps) => {\n const shortcut = props.shortcut ?? \"mod+K\";\n const searchPlaceholder = props.searchPlaceholder ?? \"Search...\";\n const nothingFound = props.nothingFound ?? \"Nothing found...\";\n const router = useRouter();\n const actions: SpotlightActionData[] = useMemo(\n () =>\n router.concretePages.map((page) => ({\n id: page.name,\n label: page.label ?? page.name,\n description: page.description,\n onClick: () => router.go(page.path ?? page.name),\n leftSection: page.icon,\n })),\n [],\n );\n\n return (\n <Spotlight\n actions={actions}\n shortcut={shortcut}\n limit={10}\n searchProps={{\n leftSection: <IconSearch size={20} />,\n placeholder: searchPlaceholder,\n }}\n nothingFound={nothingFound}\n />\n );\n};\n\nexport default Omnibar;\n","import { NestedView, useEvents } from \"@alepha/react\";\nimport type {\n ColorSchemeScriptProps,\n MantineProviderProps,\n} from \"@mantine/core\";\nimport { ColorSchemeScript, MantineProvider } from \"@mantine/core\";\nimport { ModalsProvider, type ModalsProviderProps } from \"@mantine/modals\";\nimport { Notifications, type NotificationsProps } from \"@mantine/notifications\";\nimport type { NavigationProgressProps } from \"@mantine/nprogress\";\nimport { NavigationProgress, nprogress } from \"@mantine/nprogress\";\nimport type { ReactNode } from \"react\";\nimport { useToast } from \"../../hooks/useToast.ts\";\nimport Omnibar, { type OmnibarProps } from \"./Omnibar.tsx\";\n\nexport interface AlephaMantineProviderProps {\n children?: ReactNode;\n mantine?: MantineProviderProps;\n colorSchemeScript?: ColorSchemeScriptProps;\n navigationProgress?: NavigationProgressProps;\n notifications?: NotificationsProps;\n modals?: ModalsProviderProps;\n omnibar?: OmnibarProps;\n}\n\nconst AlephaMantineProvider = (props: AlephaMantineProviderProps) => {\n const toast = useToast();\n\n useEvents(\n {\n \"react:transition:begin\": () => {\n nprogress.start();\n },\n \"react:transition:end\": () => {\n nprogress.complete();\n },\n \"react:action:error\": () => {\n toast.danger(\"An error occurred while processing your action.\");\n },\n },\n [],\n );\n\n return (\n <>\n <ColorSchemeScript\n defaultColorScheme={props.mantine?.defaultColorScheme}\n {...props.colorSchemeScript}\n />\n <MantineProvider\n {...props.mantine}\n theme={{\n primaryColor: \"gray\",\n primaryShade: {\n light: 9,\n dark: 8,\n },\n cursorType: \"pointer\",\n ...props.mantine?.theme,\n }}\n >\n <Notifications {...props.notifications} />\n <NavigationProgress {...props.navigationProgress} />\n <ModalsProvider {...props.modals}>\n <Omnibar {...props.omnibar} />\n {props.children ?? <NestedView />}\n </ModalsProvider>\n </MantineProvider>\n </>\n );\n};\n\nexport default AlephaMantineProvider;\n"],"mappings":";;;;;;;;;;;AAaA,IAAa,eAAb,MAA0B;CACxB,AAAmB,MAAMA;CAEzB,AAAgB,UAA+B,EAC7C,SAAS;EACP,WAAW;EACX,iBAAiB;EACjB,UAAU;EACX,EACF;CAED,AAAO,KAAK,SAA2B;AACrC,wCAAc,KAAK;GACjB,GAAG,KAAK,QAAQ;GAChB,GAAG;GACJ,CAAC;;CAGJ,AAAO,KAAK,SAA6C;AACvD,MAAI,OAAO,YAAY,SACrB,WAAU,EAAE,SAAS,SAAS;AAEhC,OAAK,KAAK;GACR,OAAO;GACP,MAAM,2CAACC,uCAAe,MAAM,KAAM;GAClC,OAAO;GACP,SAAS;GACT,GAAG;GACJ,CAAC;;CAGJ,AAAO,QAAQ,SAA6C;AAC1D,MAAI,OAAO,YAAY,SACrB,WAAU,EAAE,SAAS,SAAS;AAEhC,OAAK,KAAK;GACR,OAAO;GACP,MAAM,2CAACC,kCAAU,MAAM,KAAM;GAC7B,OAAO;GACP,SAAS;GACT,GAAG;GACJ,CAAC;;CAGJ,AAAO,QAAQ,SAA6C;AAC1D,MAAI,OAAO,YAAY,SACrB,WAAU,EAAE,SAAS,SAAS;AAEhC,OAAK,KAAK;GACR,OAAO;GACP,MAAM,2CAACC,0CAAkB,MAAM,KAAM;GACrC,OAAO;GACP,SAAS;GACT,GAAG;GACJ,CAAC;;CAGJ,AAAO,OAAO,SAA6C;AACzD,MAAI,OAAO,YAAY,SACrB,WAAU,EAAE,SAAS,SAAS;AAEhC,OAAK,KAAK;GACR,OAAO;GACP,MAAM,2CAACC,8BAAM,MAAM,KAAM;GACzB,OAAO;GACP,SAAS;GACT,GAAG;GACJ,CAAC;;;;;;;;;;;;;;;;ACnEN,MAAa,iBAA+B;AAC1C,sCAAiB,aAAa;;;;;ACHhC,MAAM,WAAW,UAAwB;CACvC,MAAM,WAAW,MAAM,YAAY;CACnC,MAAM,oBAAoB,MAAM,qBAAqB;CACrD,MAAM,eAAe,MAAM,gBAAgB;CAC3C,MAAM,wCAAoB;AAa1B,QACE,2CAACC;EACC,kCAZA,OAAO,cAAc,KAAK,UAAU;GAClC,IAAI,KAAK;GACT,OAAO,KAAK,SAAS,KAAK;GAC1B,aAAa,KAAK;GAClB,eAAe,OAAO,GAAG,KAAK,QAAQ,KAAK,KAAK;GAChD,aAAa,KAAK;GACnB,EAAE,EACL,EAAE,CACH;EAKa;EACV,OAAO;EACP,aAAa;GACX,aAAa,2CAACC,mCAAW,MAAM,KAAM;GACrC,aAAa;GACd;EACa;GACd;;AAIN,sBAAe;;;;AClBf,MAAM,yBAAyB,UAAsC;CACnE,MAAM,QAAQ,UAAU;AAExB,+BACE;EACE,gCAAgC;AAC9B,iCAAU,OAAO;;EAEnB,8BAA8B;AAC5B,iCAAU,UAAU;;EAEtB,4BAA4B;AAC1B,SAAM,OAAO,kDAAkD;;EAElE,EACD,EAAE,CACH;AAED,QACE,qFACE,2CAACC;EACC,oBAAoB,MAAM,SAAS;EACnC,GAAI,MAAM;GACV,EACF,4CAACC;EACC,GAAI,MAAM;EACV,OAAO;GACL,cAAc;GACd,cAAc;IACZ,OAAO;IACP,MAAM;IACP;GACD,YAAY;GACZ,GAAG,MAAM,SAAS;GACnB;;GAED,2CAACC,yCAAc,GAAI,MAAM,gBAAiB;GAC1C,2CAACC,0CAAmB,GAAI,MAAM,qBAAsB;GACpD,4CAACC;IAAe,GAAI,MAAM;eACxB,2CAACC,mBAAQ,GAAI,MAAM,UAAW,EAC7B,MAAM,YAAY,2CAACC,8BAAa;KAClB;;GACD,IACjB;;AAIP,oCAAe"}
@@ -0,0 +1,3 @@
1
+ import { t as AlephaMantineProvider_default } from "./AlephaMantineProvider-D8cHYAge.js";
2
+
3
+ export { AlephaMantineProvider_default as default };
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
- const require_AlephaMantineProvider = require('./AlephaMantineProvider-DlOEv9f0.cjs');
2
- let __alepha_core = require("@alepha/core");
3
- let __alepha_react_form = require("@alepha/react-form");
4
- let __alepha_react_head = require("@alepha/react-head");
5
- let __alepha_react_i18n = require("@alepha/react-i18n");
1
+ const require_AlephaMantineProvider = require('./AlephaMantineProvider-DuvZFAuk.cjs');
2
+ let __alepha_react_form = require("@alepha/react/form");
3
+ let __alepha_react_head = require("@alepha/react/head");
4
+ let __alepha_react_i18n = require("@alepha/react/i18n");
5
+ let alepha = require("alepha");
6
6
  let __alepha_react = require("@alepha/react");
7
7
  let __mantine_core = require("@mantine/core");
8
8
  let __mantine_modals = require("@mantine/modals");
@@ -11,15 +11,15 @@ let react = require("react");
11
11
  let react_jsx_runtime = require("react/jsx-runtime");
12
12
  let __mantine_spotlight = require("@mantine/spotlight");
13
13
  let __mantine_dates = require("@mantine/dates");
14
- let __alepha_orm = require("@alepha/orm");
15
- let __alepha_datetime = require("@alepha/datetime");
14
+ let alepha_orm = require("alepha/orm");
16
15
  let __mantine_hooks = require("@mantine/hooks");
16
+ let alepha_datetime = require("alepha/datetime");
17
17
 
18
18
  //#region src/RootRouter.ts
19
19
  var RootRouter = class {
20
20
  root = (0, __alepha_react.$page)({
21
21
  path: "/",
22
- lazy: () => Promise.resolve().then(() => require("./AlephaMantineProvider-DCF5kidi.cjs"))
22
+ lazy: () => Promise.resolve().then(() => require("./AlephaMantineProvider-CGpgWDt8.cjs"))
23
23
  });
24
24
  };
25
25
 
@@ -792,6 +792,20 @@ const ActionHrefButton = (props) => {
792
792
  });
793
793
  };
794
794
 
795
+ //#endregion
796
+ //#region src/components/buttons/BurgerButton.tsx
797
+ const BurgerButton = (props) => {
798
+ const [opened, setOpened] = (0, __alepha_react.useStore)("alepha.ui.sidebar.opened");
799
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__mantine_core.Burger, {
800
+ opened,
801
+ onClick: () => setOpened(!opened),
802
+ hiddenFrom: "sm",
803
+ size: "sm",
804
+ ...props
805
+ });
806
+ };
807
+ var BurgerButton_default = BurgerButton;
808
+
795
809
  //#endregion
796
810
  //#region src/components/buttons/DarkModeButton.tsx
797
811
  const DarkModeButton = (props) => {
@@ -956,7 +970,7 @@ const parseInput = (props, form) => {
956
970
  const id = props.input.props.id;
957
971
  const label = props.title ?? ("title" in props.input.schema && typeof props.input.schema.title === "string" ? props.input.schema.title : void 0) ?? prettyName(props.input.path);
958
972
  const description = props.description ?? ("description" in props.input.schema && typeof props.input.schema.description === "string" ? props.input.schema.description : void 0);
959
- const error = form.error && form.error instanceof __alepha_core.TypeBoxError ? form.error.value.message : void 0;
973
+ const error = form.error && form.error instanceof alepha.TypeBoxError ? form.error.value.message : void 0;
960
974
  const icon = props.icon ?? getDefaultIcon({
961
975
  type: props.input.schema && "type" in props.input.schema ? String(props.input.schema.type) : void 0,
962
976
  format: props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0,
@@ -1244,7 +1258,7 @@ const ControlQueryBuilder = ({ schema, value = "", onChange, placeholder = "Ente
1244
1258
  const [error, setError] = (0, react.useState)(null);
1245
1259
  const isValid = (value$1) => {
1246
1260
  try {
1247
- (0, __alepha_orm.parseQueryString)(value$1.trim());
1261
+ (0, alepha_orm.parseQueryString)(value$1.trim());
1248
1262
  } catch (e) {
1249
1263
  setError(e.message);
1250
1264
  return false;
@@ -1748,7 +1762,7 @@ var Control_default = Control;
1748
1762
  * @example
1749
1763
  * ```tsx
1750
1764
  * import { t } from "alepha";
1751
- * import { useForm } from "@alepha/react-form";
1765
+ * import { useForm } from "@alepha/react/form";
1752
1766
  * import { TypeForm } from "@alepha/ui";
1753
1767
  *
1754
1768
  * const form = useForm({
@@ -1829,20 +1843,6 @@ const TypeForm = (props) => {
1829
1843
  };
1830
1844
  var TypeForm_default = TypeForm;
1831
1845
 
1832
- //#endregion
1833
- //#region src/components/buttons/BurgerButton.tsx
1834
- const BurgerButton = (props) => {
1835
- const [opened, setOpened] = (0, __alepha_react.useStore)("alepha.ui.sidebar.opened");
1836
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__mantine_core.Burger, {
1837
- opened,
1838
- onClick: () => setOpened(!opened),
1839
- hiddenFrom: "sm",
1840
- size: "sm",
1841
- ...props
1842
- });
1843
- };
1844
- var BurgerButton_default = BurgerButton;
1845
-
1846
1846
  //#endregion
1847
1847
  //#region src/components/buttons/LanguageButton.tsx
1848
1848
  const LanguageButton = (props) => {
@@ -2189,13 +2189,13 @@ const DataTable = (props) => {
2189
2189
  const [page, setPage] = (0, react.useState)(1);
2190
2190
  const [size, setSize] = (0, react.useState)(String(defaultSize));
2191
2191
  const [currentPage, setCurrentPage] = (0, react.useState)(0);
2192
- const alepha = (0, __alepha_react.useInject)(__alepha_core.Alepha);
2192
+ const alepha$1 = (0, __alepha_react.useInject)(alepha.Alepha);
2193
2193
  const form = (0, __alepha_react_form.useForm)({
2194
- schema: __alepha_core.t.object({
2194
+ schema: alepha.t.object({
2195
2195
  ...props.filters ? props.filters.properties : {},
2196
- page: __alepha_core.t.number({ default: 0 }),
2197
- size: __alepha_core.t.number({ default: defaultSize }),
2198
- sort: __alepha_core.t.optional(__alepha_core.t.string())
2196
+ page: alepha.t.number({ default: 0 }),
2197
+ size: alepha.t.number({ default: defaultSize }),
2198
+ sort: alepha.t.optional(alepha.t.string())
2199
2199
  }),
2200
2200
  handler: async (values, args) => {
2201
2201
  if (typeof props.items === "function") {
@@ -2228,7 +2228,7 @@ const DataTable = (props) => {
2228
2228
  }
2229
2229
  }, [items]);
2230
2230
  (0, __mantine_hooks.useDebouncedCallback)(() => form.submit(), { delay: 800 });
2231
- const dt = (0, __alepha_react.useInject)(__alepha_datetime.DateTimeProvider);
2231
+ const dt = (0, __alepha_react.useInject)(alepha_datetime.DateTimeProvider);
2232
2232
  (0, react.useEffect)(() => {
2233
2233
  if (props.submitOnInit) form.submit();
2234
2234
  if (props.submitEvery) {
@@ -2282,11 +2282,11 @@ const DataTable = (props) => {
2282
2282
  children: Object.entries(props.columns).map(([key, col]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__mantine_core.Table.Td, { children: col.value(item, {
2283
2283
  index,
2284
2284
  form,
2285
- alepha
2285
+ alepha: alepha$1
2286
2286
  }) }, key))
2287
2287
  }, JSON.stringify(item));
2288
2288
  });
2289
- const schema = __alepha_core.t.omit(form.options.schema, [
2289
+ const schema = alepha.t.omit(form.options.schema, [
2290
2290
  "page",
2291
2291
  "size",
2292
2292
  "sort"
@@ -2364,10 +2364,12 @@ var DataTable_default = DataTable;
2364
2364
  * Use this hook to access the Dialog Service for showing various dialog types.
2365
2365
  *
2366
2366
  * @example
2367
+ * ```tsx
2367
2368
  * const dialog = useDialog();
2368
2369
  * await dialog.alert({ title: "Alert", message: "This is an alert message" });
2369
2370
  * const confirmed = await dialog.confirm({ title: "Confirm", message: "Are you sure?" });
2370
2371
  * const input = await dialog.prompt({ title: "Input", message: "Enter your name:" });
2372
+ * ```
2371
2373
  */
2372
2374
  const useDialog = () => {
2373
2375
  return (0, __alepha_react.useInject)(DialogService);
@@ -2380,19 +2382,19 @@ const useDialog = () => {
2380
2382
  *
2381
2383
  * @module alepha.ui
2382
2384
  */
2383
- const AlephaUI = (0, __alepha_core.$module)({
2385
+ const AlephaUI = (0, alepha.$module)({
2384
2386
  name: "alepha.ui",
2385
2387
  services: [
2386
2388
  DialogService,
2387
2389
  require_AlephaMantineProvider.ToastService,
2388
2390
  RootRouter
2389
2391
  ],
2390
- register: (alepha) => {
2391
- alepha.with(__alepha_react_i18n.AlephaReactI18n);
2392
- alepha.with(__alepha_react_head.AlephaReactHead);
2393
- alepha.with(__alepha_react_form.AlephaReactForm);
2394
- alepha.with(DialogService);
2395
- alepha.with(require_AlephaMantineProvider.ToastService);
2392
+ register: (alepha$1) => {
2393
+ alepha$1.with(__alepha_react_i18n.AlephaReactI18n);
2394
+ alepha$1.with(__alepha_react_head.AlephaReactHead);
2395
+ alepha$1.with(__alepha_react_form.AlephaReactForm);
2396
+ alepha$1.with(DialogService);
2397
+ alepha$1.with(require_AlephaMantineProvider.ToastService);
2396
2398
  }
2397
2399
  });
2398
2400
 
@@ -2403,6 +2405,7 @@ exports.AlephaMantineProvider = require_AlephaMantineProvider.AlephaMantineProvi
2403
2405
  exports.AlephaUI = AlephaUI;
2404
2406
  exports.AlertDialog = AlertDialog_default;
2405
2407
  exports.AppBar = AppBar_default;
2408
+ exports.BurgerButton = BurgerButton_default;
2406
2409
  exports.ConfirmDialog = ConfirmDialog_default;
2407
2410
  exports.Control = Control_default;
2408
2411
  exports.ControlDate = ControlDate_default;