@alepha/ui 0.17.2 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/{AdminApiKeys-CF_qOO3u.js → AdminApiKeys-C-6_Q-lH.js} +56 -192
- package/dist/admin/AdminApiKeys-C-6_Q-lH.js.map +1 -0
- package/dist/admin/{AdminAudits-BQno3hZG.js → AdminAudits-Bgbf04hO.js} +25 -61
- package/dist/admin/AdminAudits-Bgbf04hO.js.map +1 -0
- package/dist/admin/{AdminFiles-kvuUaASF.js → AdminFiles-B9a7G3cY.js} +6 -8
- package/dist/admin/AdminFiles-B9a7G3cY.js.map +1 -0
- package/dist/admin/{AdminJobDashboard-CrPxp0W1.js → AdminJobDashboard-DaTwf5OY.js} +55 -186
- package/dist/admin/AdminJobDashboard-DaTwf5OY.js.map +1 -0
- package/dist/admin/{AdminJobExecutions-D-b4Zt7W.js → AdminJobExecutions-B9cek5dl.js} +132 -168
- package/dist/admin/AdminJobExecutions-B9cek5dl.js.map +1 -0
- package/dist/admin/{AdminJobRegistry-CNX5cpDx.js → AdminJobRegistry-DFgV3oqx.js} +60 -83
- package/dist/admin/AdminJobRegistry-DFgV3oqx.js.map +1 -0
- package/dist/admin/AdminLayout-DHsvWxVB.js +70 -0
- package/dist/admin/AdminLayout-DHsvWxVB.js.map +1 -0
- package/dist/admin/{AdminParameters-DCGbpt2c.js → AdminParameters-DHw9ATgl.js} +53 -53
- package/dist/admin/AdminParameters-DHw9ATgl.js.map +1 -0
- package/dist/admin/{AdminSessions-DyhW6RZv.js → AdminSessions-BhGJPI3z.js} +11 -18
- package/dist/admin/AdminSessions-BhGJPI3z.js.map +1 -0
- package/dist/admin/{AdminUserLayout-CrBj4UuI.js → AdminUserLayout-BdC4Te8m.js} +112 -151
- package/dist/admin/AdminUserLayout-BdC4Te8m.js.map +1 -0
- package/dist/admin/AdminUserProfile-DAt23fqY.js +69 -0
- package/dist/admin/AdminUserProfile-DAt23fqY.js.map +1 -0
- package/dist/admin/AdminUserSessions-1uzcx02z.js +109 -0
- package/dist/admin/AdminUserSessions-1uzcx02z.js.map +1 -0
- package/dist/admin/AdminUsers-C85c3eiQ.js +121 -0
- package/dist/admin/AdminUsers-C85c3eiQ.js.map +1 -0
- package/dist/{auth/AuthLayout-CdJcrPs4.js → admin/AuthLayout-DFJvCvzw.js} +3 -3
- package/dist/{auth/AuthLayout-CdJcrPs4.js.map → admin/AuthLayout-DFJvCvzw.js.map} +1 -1
- package/dist/{auth/IconGoogle-Bm18QD2q.js → admin/IconGoogle-CSQLPYwX.js} +1 -1
- package/dist/{auth/IconGoogle-Bm18QD2q.js.map → admin/IconGoogle-CSQLPYwX.js.map} +1 -1
- package/dist/{demo/DemoLogin-DjJ9314c.js → admin/Login-BGheURrg.js} +15 -129
- package/dist/{auth/Login-BS_FYTy0.js.map → admin/Login-BGheURrg.js.map} +1 -1
- package/dist/{auth/Profile-CjDsW378.js → admin/Profile-B-c9pCPf.js} +5 -5
- package/dist/{auth/Profile-CjDsW378.js.map → admin/Profile-B-c9pCPf.js.map} +1 -1
- package/dist/{demo/DemoRegister-DzkJ5M83.js → admin/Register-Cs10l8vX.js} +20 -146
- package/dist/{auth/Register-C5eqzAaD.js.map → admin/Register-Cs10l8vX.js.map} +1 -1
- package/dist/{demo/DemoResetPassword-DWh4_BpQ.js → admin/ResetPassword-BwDdfkGH.js} +20 -82
- package/dist/{auth/ResetPassword-XifinVao.js.map → admin/ResetPassword-BwDdfkGH.js.map} +1 -1
- package/dist/{demo/DemoVerifyEmail-DbU_tCj8.js → admin/VerifyEmail-DfXHAiQl.js} +15 -32
- package/dist/{auth/VerifyEmail-DTgbeJOO.js.map → admin/VerifyEmail-DfXHAiQl.js.map} +1 -1
- package/dist/admin/auth-Dr0Cf8I7.js +319 -0
- package/dist/admin/auth-Dr0Cf8I7.js.map +1 -0
- package/dist/admin/core-2xoLiT0o.js +4031 -0
- package/dist/admin/core-2xoLiT0o.js.map +1 -0
- package/dist/admin/index.d.ts +739 -13
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +79 -111
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/rolldown-runtime-CjeV3_4I.js +18 -0
- package/dist/auth/AuthLayout-CAE1pX9s.js +22 -0
- package/dist/auth/AuthLayout-CAE1pX9s.js.map +1 -0
- package/dist/auth/{Login-BS_FYTy0.js → Login-Denw_UGy.js} +8 -8
- package/dist/auth/Login-Denw_UGy.js.map +1 -0
- package/dist/auth/Profile-BMX_Ar_s.js +155 -0
- package/dist/auth/Profile-BMX_Ar_s.js.map +1 -0
- package/dist/auth/{Register-C5eqzAaD.js → Register-6hi_cpfF.js} +8 -8
- package/dist/auth/Register-6hi_cpfF.js.map +1 -0
- package/dist/auth/{ResetPassword-XifinVao.js → ResetPassword-CqfTk1FI.js} +6 -6
- package/dist/auth/ResetPassword-CqfTk1FI.js.map +1 -0
- package/dist/auth/{VerifyEmail-DTgbeJOO.js → VerifyEmail-nWiSTMjF.js} +5 -5
- package/dist/auth/VerifyEmail-nWiSTMjF.js.map +1 -0
- package/dist/auth/core-niW0sFLv.js +2264 -0
- package/dist/auth/core-niW0sFLv.js.map +1 -0
- package/dist/auth/index.d.ts +336 -8
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +18 -22
- package/dist/auth/index.js.map +1 -1
- package/dist/core/index.d.ts +1033 -843
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1626 -1354
- package/dist/core/index.js.map +1 -1
- package/dist/demo/AuthLayout-jLa0aKsI.js +22 -0
- package/dist/demo/AuthLayout-jLa0aKsI.js.map +1 -0
- package/dist/demo/DemoButton-BmaWZVwf.js +178 -0
- package/dist/demo/DemoButton-BmaWZVwf.js.map +1 -0
- package/dist/demo/{DemoDataTable-lnBKWBf8.js → DemoDataTable-Z9xyV221.js} +18 -18
- package/dist/demo/DemoDataTable-Z9xyV221.js.map +1 -0
- package/dist/demo/DemoDialog-4ItHLf9t.js +101 -0
- package/dist/demo/DemoDialog-4ItHLf9t.js.map +1 -0
- package/dist/demo/DemoFlex-EtVq8QfX.js +105 -0
- package/dist/demo/DemoFlex-EtVq8QfX.js.map +1 -0
- package/dist/demo/DemoHeading-BS-vGfkI.js +18 -0
- package/dist/demo/DemoHeading-BS-vGfkI.js.map +1 -0
- package/dist/demo/{DemoHome-CUMZsYaH.js → DemoHome-Clbn8AmS.js} +9 -12
- package/dist/demo/DemoHome-Clbn8AmS.js.map +1 -0
- package/dist/demo/DemoJsonViewer-DkIX_ky2.js +109 -0
- package/dist/demo/DemoJsonViewer-DkIX_ky2.js.map +1 -0
- package/dist/demo/DemoLayout-C56xb5EE.js +73 -0
- package/dist/demo/DemoLayout-C56xb5EE.js.map +1 -0
- package/dist/demo/DemoLogin-BZwpicOS.js +128 -0
- package/dist/demo/DemoLogin-BZwpicOS.js.map +1 -0
- package/dist/demo/DemoRegister-C7_qc4MJ.js +140 -0
- package/dist/demo/DemoRegister-C7_qc4MJ.js.map +1 -0
- package/dist/demo/DemoResetPassword-BI1Ct4Dw.js +76 -0
- package/dist/demo/DemoResetPassword-BI1Ct4Dw.js.map +1 -0
- package/dist/demo/{DemoSidebar-C1csnGhX.js → DemoSidebar-CcBo4ltC.js} +6 -9
- package/dist/demo/DemoSidebar-CcBo4ltC.js.map +1 -0
- package/dist/demo/DemoText-CzXuUn3g.js +124 -0
- package/dist/demo/DemoText-CzXuUn3g.js.map +1 -0
- package/dist/demo/DemoToast-BgHDhWrX.js +95 -0
- package/dist/demo/DemoToast-BgHDhWrX.js.map +1 -0
- package/dist/demo/{DemoTypeForm-CWz6fJrJ.js → DemoTypeForm-DDzWoMSV.js} +4 -4
- package/dist/demo/{DemoTypeForm-CWz6fJrJ.js.map → DemoTypeForm-DDzWoMSV.js.map} +1 -1
- package/dist/demo/DemoVerifyEmail-C_Irdnov.js +30 -0
- package/dist/demo/DemoVerifyEmail-C_Irdnov.js.map +1 -0
- package/dist/demo/IconGoogle-CSQLPYwX.js +56 -0
- package/dist/demo/IconGoogle-CSQLPYwX.js.map +1 -0
- package/dist/demo/Login-hSOU3jZc.js +219 -0
- package/dist/demo/Login-hSOU3jZc.js.map +1 -0
- package/dist/demo/Profile-CWqti7FB.js +155 -0
- package/dist/demo/Profile-CWqti7FB.js.map +1 -0
- package/dist/demo/Register-a70LPgs2.js +375 -0
- package/dist/demo/Register-a70LPgs2.js.map +1 -0
- package/dist/demo/ResetPassword-DWN0lzr5.js +286 -0
- package/dist/demo/ResetPassword-DWN0lzr5.js.map +1 -0
- package/dist/demo/Showcase-Dq3MISpd.js +232 -0
- package/dist/demo/Showcase-Dq3MISpd.js.map +1 -0
- package/dist/demo/VerifyEmail-DZWL72K4.js +135 -0
- package/dist/demo/VerifyEmail-DZWL72K4.js.map +1 -0
- package/dist/demo/auth-d6n3xbug.js +257 -0
- package/dist/demo/auth-d6n3xbug.js.map +1 -0
- package/dist/demo/core-RCUw1Q-a.js +4217 -0
- package/dist/demo/core-RCUw1Q-a.js.map +1 -0
- package/dist/demo/index.d.ts +17 -6
- package/dist/demo/index.d.ts.map +1 -1
- package/dist/demo/index.js +92 -24
- package/dist/demo/index.js.map +1 -1
- package/dist/demo/rolldown-runtime-CjeV3_4I.js +18 -0
- package/package.json +16 -20
- package/src/admin/AdminRouter.ts +10 -39
- package/src/admin/components/AdminLayout.tsx +42 -10
- package/src/admin/components/audits/AdminAudits.tsx +10 -64
- package/src/admin/components/files/AdminFiles.tsx +2 -3
- package/src/admin/components/jobs/AdminJobDashboard.tsx +36 -142
- package/src/admin/components/jobs/AdminJobExecutions.tsx +117 -175
- package/src/admin/components/jobs/AdminJobRegistry.tsx +58 -73
- package/src/admin/components/keys/AdminApiKeys.tsx +21 -169
- package/src/admin/components/parameters/AdminParameters.tsx +4 -4
- package/src/admin/components/parameters/ParameterEmptyState.tsx +1 -2
- package/src/admin/components/parameters/ParameterHistory.tsx +3 -3
- package/src/admin/components/parameters/ParameterTree.tsx +2 -8
- package/src/admin/components/parameters/types.ts +3 -3
- package/src/admin/components/sessions/AdminSessions.tsx +8 -16
- package/src/admin/components/users/AdminUserLayout.tsx +113 -150
- package/src/admin/components/users/AdminUserProfile.tsx +50 -0
- package/src/admin/components/users/AdminUserSessions.tsx +106 -126
- package/src/admin/components/users/AdminUsers.tsx +46 -62
- package/src/admin/index.ts +0 -4
- package/src/auth/components/buttons/UserButton.tsx +1 -1
- package/src/auth/index.ts +0 -4
- package/src/core/UiRouter.ts +1 -1
- package/src/core/atoms/alephaSidebarAtom.ts +7 -31
- package/src/core/components/{layout/AlephaMantineProvider.tsx → AlephaMantineProvider.tsx} +3 -4
- package/src/core/components/Flex.tsx +63 -0
- package/src/core/components/Heading.tsx +19 -0
- package/src/core/components/Text.tsx +140 -0
- package/src/core/components/buttons/ActionButton.tsx +12 -1
- package/src/core/components/buttons/BurgerButton.tsx +3 -3
- package/src/core/components/buttons/LanguageButton.tsx +1 -1
- package/src/core/components/buttons/ToggleSidebarButton.tsx +1 -4
- package/src/core/components/data/DetailDrawer.tsx +144 -0
- package/src/core/components/data/DetailList.tsx +64 -0
- package/src/core/components/data/StatCards.tsx +50 -0
- package/src/core/components/layout/AppBar.tsx +11 -10
- package/src/core/components/layout/Breadcrumb.tsx +8 -8
- package/src/core/components/layout/Container.tsx +15 -0
- package/src/core/components/layout/DashboardShell.tsx +23 -238
- package/src/core/components/layout/Omnibar.tsx +1 -2
- package/src/core/components/layout/Sidebar.tsx +103 -71
- package/src/core/components/layout/index.ts +65 -0
- package/src/core/{components/form → form/components}/Control.tsx +32 -14
- package/src/core/{components/form → form/components}/ControlArray.tsx +2 -5
- package/src/core/{components/form → form/components}/ControlDate.tsx +1 -4
- package/src/core/{components/form → form/components}/ControlNumber.tsx +1 -4
- package/src/core/{components/form → form/components}/ControlObject.tsx +1 -4
- package/src/core/{components/form → form/components}/ControlQueryBuilder.tsx +7 -7
- package/src/core/{components/form → form/components}/ControlSelect.tsx +2 -4
- package/src/core/{components/form → form/components}/TypeForm.browser.spec.tsx +22 -64
- package/src/core/{components/form → form/components}/TypeForm.tsx +1 -3
- package/src/core/form/factories/dialogForm.tsx +31 -0
- package/src/core/form/index.ts +23 -0
- package/src/core/{utils → form/utils}/parseInput.ts +2 -4
- package/src/core/index.ts +43 -51
- package/src/core/interfaces/AlephaIntent.ts +6 -0
- package/src/core/interfaces/AlephaTheme.ts +0 -1
- package/src/core/json/factories/dialogJson.tsx +24 -0
- package/src/core/json/index.ts +2 -0
- package/src/core/primitives/$ui.ts +17 -0
- package/src/core/services/DialogService.tsx +1 -48
- package/src/core/styles.css +1 -8
- package/src/core/{components/table → table/components}/ColumnPicker.tsx +2 -3
- package/src/core/{components/table → table/components}/DataTable.tsx +8 -9
- package/src/core/{components/table → table/components}/DataTableFilters.tsx +6 -3
- package/src/core/{components/table → table/components}/DataTableToolbar.tsx +4 -5
- package/src/core/{components/table → table/components}/FilterPicker.tsx +2 -3
- package/src/core/table/index.ts +12 -0
- package/src/core/{components/table → table/interfaces}/types.ts +2 -2
- package/src/demo/DemoRouter.ts +87 -6
- package/src/demo/components/DemoHome.tsx +6 -10
- package/src/demo/components/DemoLayout.tsx +38 -8
- package/src/demo/components/auth/DemoLogin.tsx +1 -1
- package/src/demo/components/auth/DemoRegister.tsx +1 -1
- package/src/demo/components/auth/DemoResetPassword.tsx +1 -1
- package/src/demo/components/auth/DemoVerifyEmail.tsx +1 -1
- package/src/demo/components/core/DemoButton.tsx +160 -0
- package/src/demo/components/core/DemoFlex.tsx +101 -0
- package/src/demo/components/core/DemoHeading.tsx +13 -0
- package/src/demo/components/core/DemoText.tsx +110 -0
- package/src/demo/components/json/DemoJsonViewer.tsx +1 -1
- package/src/demo/components/layout/DemoDialog.tsx +103 -0
- package/src/demo/components/{core → layout}/DemoSidebar.tsx +0 -1
- package/src/demo/components/layout/DemoToast.tsx +96 -0
- package/src/demo/components/shared/MacWindow.tsx +149 -74
- package/src/demo/components/shared/Showcase.tsx +4 -8
- package/src/demo/index.ts +1 -4
- package/src/demo/primitives/$uiDemo.ts +10 -0
- package/dist/admin/AdminApiKeys-CF_qOO3u.js.map +0 -1
- package/dist/admin/AdminAudits-BQno3hZG.js.map +0 -1
- package/dist/admin/AdminFiles-kvuUaASF.js.map +0 -1
- package/dist/admin/AdminJobDashboard-CrPxp0W1.js.map +0 -1
- package/dist/admin/AdminJobExecutions-D-b4Zt7W.js.map +0 -1
- package/dist/admin/AdminJobRegistry-CNX5cpDx.js.map +0 -1
- package/dist/admin/AdminLayout-e-ZP5nWw.js +0 -37
- package/dist/admin/AdminLayout-e-ZP5nWw.js.map +0 -1
- package/dist/admin/AdminParameters-DCGbpt2c.js.map +0 -1
- package/dist/admin/AdminSessions-DyhW6RZv.js.map +0 -1
- package/dist/admin/AdminUserAudits-D1GcREEE.js +0 -177
- package/dist/admin/AdminUserAudits-D1GcREEE.js.map +0 -1
- package/dist/admin/AdminUserCreate-DR8LA0tv.js +0 -104
- package/dist/admin/AdminUserCreate-DR8LA0tv.js.map +0 -1
- package/dist/admin/AdminUserDetails-CDkZNHQD.js +0 -477
- package/dist/admin/AdminUserDetails-CDkZNHQD.js.map +0 -1
- package/dist/admin/AdminUserLayout-CrBj4UuI.js.map +0 -1
- package/dist/admin/AdminUserSessions-srgFHrqy.js +0 -129
- package/dist/admin/AdminUserSessions-srgFHrqy.js.map +0 -1
- package/dist/admin/AdminUserSettings-BFuxl-xT.js +0 -167
- package/dist/admin/AdminUserSettings-BFuxl-xT.js.map +0 -1
- package/dist/admin/AdminUsers-D1pDpiwK.js +0 -118
- package/dist/admin/AdminUsers-D1pDpiwK.js.map +0 -1
- package/dist/demo/DemoDataTable-lnBKWBf8.js.map +0 -1
- package/dist/demo/DemoHome-CUMZsYaH.js.map +0 -1
- package/dist/demo/DemoJsonViewer-_uokbGaW.js +0 -429
- package/dist/demo/DemoJsonViewer-_uokbGaW.js.map +0 -1
- package/dist/demo/DemoLayout-DHVoacE6.js +0 -46
- package/dist/demo/DemoLayout-DHVoacE6.js.map +0 -1
- package/dist/demo/DemoLogin-DjJ9314c.js.map +0 -1
- package/dist/demo/DemoRegister-DzkJ5M83.js.map +0 -1
- package/dist/demo/DemoResetPassword-DWh4_BpQ.js.map +0 -1
- package/dist/demo/DemoSidebar-C1csnGhX.js.map +0 -1
- package/dist/demo/DemoVerifyEmail-DbU_tCj8.js.map +0 -1
- package/dist/demo/Showcase-BzoXNlCn.js +0 -185
- package/dist/demo/Showcase-BzoXNlCn.js.map +0 -1
- package/dist/json/index.d.ts +0 -57
- package/dist/json/index.d.ts.map +0 -1
- package/dist/json/index.js +0 -325
- package/dist/json/index.js.map +0 -1
- package/src/admin/components/users/AdminUserAudits.tsx +0 -184
- package/src/admin/components/users/AdminUserCreate.tsx +0 -85
- package/src/admin/components/users/AdminUserDetails.tsx +0 -431
- package/src/admin/components/users/AdminUserSettings.tsx +0 -171
- package/src/core/components/data/ErrorViewer.tsx +0 -171
- package/src/json/extensions/DialogService.tsx +0 -31
- package/src/json/index.ts +0 -18
- package/src/json/styles.css +0 -1
- /package/dist/{demo → auth}/IconGoogle-Ch1m3Uzl.js +0 -0
- /package/dist/{demo → auth}/IconGoogle-Ch1m3Uzl.js.map +0 -0
- /package/src/{json → core/json}/components/JsonViewer.css +0 -0
- /package/src/{json → core/json}/components/JsonViewer.tsx +0 -0
- /package/src/core/{components/table → table/components}/DataTablePagination.tsx +0 -0
- /package/src/core/{components/table → table/components}/useTableSelection.ts +0 -0
package/dist/core/index.js
CHANGED
|
@@ -3,18 +3,17 @@ 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 { ActionIcon, Anchor, AppShell, Autocomplete, Badge, Burger, Button, Card, Checkbox, Collapse, ColorInput, ColorSchemeScript, Container, CopyButton, Divider, Drawer, Fieldset, FileInput, Flex, Flex as Flex$1, Grid, Image, Input, Kbd, MantineProvider, Menu, MultiSelect, NumberInput, Pagination, PasswordInput, Popover, ScrollArea, SegmentedControl, Select, Slider, Switch, Table, TagsInput, Text, Text as Text$1, TextInput, Textarea, ThemeIcon, Tooltip, UnstyledButton, useMantineColorScheme, useMantineTheme } from "@mantine/core";
|
|
7
6
|
import { ModalsProvider, modals } from "@mantine/modals";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { Fragment as Fragment$1,
|
|
7
|
+
import { ActionIcon, Anchor, AppShell, Autocomplete, Badge, Burger, Button, Card, Checkbox, ColorInput, ColorSchemeScript, Container as Container$1, CopyButton, Divider, Drawer, Fieldset, FileInput, Flex as Flex$1, Grid, Image, Input, Kbd, Loader, MantineProvider, Menu, MultiSelect, NumberInput, Pagination, Paper, PasswordInput, Popover, ScrollArea, SegmentedControl, Select, Slider, Switch, Table, Tabs, TagsInput, Text as Text$1, TextInput, Textarea, ThemeIcon, Tooltip, Tree, UnstyledButton, getTreeExpandedState, useMantineColorScheme, useMantineTheme, useTree } from "@mantine/core";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Children, Fragment as Fragment$1, createElement, forwardRef, isValidElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
11
10
|
import { Notifications, notifications } from "@mantine/notifications";
|
|
11
|
+
import { IconAlertTriangle, IconArrowDown, IconArrowLeft, IconArrowUp, IconArrowsSort, IconAt, IconCalendar, IconCheck, IconChevronDown, IconChevronRight, IconClipboard, IconClock, IconColorPicker, IconColumns, IconCopy, IconDownload, 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";
|
|
12
12
|
import { $page, Link, NestedView, useActive, useRouter, useRouterState } from "alepha/react/router";
|
|
13
13
|
import { NavigationProgress, nprogress } from "@mantine/nprogress";
|
|
14
14
|
import { ClientOnly, useAction, useAlepha, useEvents, useInject, useStore } from "alepha/react";
|
|
15
15
|
import { Spotlight, spotlight } from "@mantine/spotlight";
|
|
16
16
|
import { currentUserAtom } from "alepha/security";
|
|
17
|
-
import { ui as ui$1 } from "@alepha/ui";
|
|
18
17
|
import { useOs } from "@mantine/hooks";
|
|
19
18
|
import { DateInput, DateTimePicker, TimeInput } from "@mantine/dates";
|
|
20
19
|
import { parseQueryString } from "alepha/orm";
|
|
@@ -24,24 +23,16 @@ import { DateTimeProvider } from "alepha/datetime";
|
|
|
24
23
|
const alephaSidebarAtom = $atom({
|
|
25
24
|
name: "alepha.ui.sidebar",
|
|
26
25
|
schema: t.object({
|
|
27
|
-
|
|
26
|
+
closed: t.boolean(),
|
|
28
27
|
collapsed: t.boolean(),
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
collapsedWidth: t.number(),
|
|
32
|
-
maxWidth: t.number(),
|
|
33
|
-
collapseThreshold: t.number(),
|
|
34
|
-
hoverDelay: t.number()
|
|
28
|
+
expandedWidth: t.number(),
|
|
29
|
+
collapsedWidth: t.number()
|
|
35
30
|
}),
|
|
36
31
|
default: {
|
|
37
|
-
|
|
32
|
+
closed: true,
|
|
38
33
|
collapsed: false,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
collapsedWidth: 78,
|
|
42
|
-
maxWidth: 500,
|
|
43
|
-
collapseThreshold: 240,
|
|
44
|
-
hoverDelay: 300
|
|
34
|
+
expandedWidth: 300,
|
|
35
|
+
collapsedWidth: 78
|
|
45
36
|
}
|
|
46
37
|
});
|
|
47
38
|
|
|
@@ -220,148 +211,9 @@ var ThemeProvider = class {
|
|
|
220
211
|
}
|
|
221
212
|
};
|
|
222
213
|
|
|
223
|
-
//#endregion
|
|
224
|
-
//#region ../../src/core/components/data/ErrorViewer.tsx
|
|
225
|
-
const getSizeConfig = (size = "sm") => {
|
|
226
|
-
const configs = {
|
|
227
|
-
xs: {
|
|
228
|
-
text: "xs",
|
|
229
|
-
icon: 12,
|
|
230
|
-
gap: 2
|
|
231
|
-
},
|
|
232
|
-
sm: {
|
|
233
|
-
text: "sm",
|
|
234
|
-
icon: 14,
|
|
235
|
-
gap: 4
|
|
236
|
-
},
|
|
237
|
-
md: {
|
|
238
|
-
text: "md",
|
|
239
|
-
icon: 16,
|
|
240
|
-
gap: 6
|
|
241
|
-
},
|
|
242
|
-
lg: {
|
|
243
|
-
text: "lg",
|
|
244
|
-
icon: 18,
|
|
245
|
-
gap: 8
|
|
246
|
-
},
|
|
247
|
-
xl: {
|
|
248
|
-
text: "xl",
|
|
249
|
-
icon: 20,
|
|
250
|
-
gap: 10
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
return configs[size] || configs.sm;
|
|
254
|
-
};
|
|
255
|
-
const parseStackTrace = (stack) => {
|
|
256
|
-
return stack.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
257
|
-
};
|
|
258
|
-
const ErrorViewer = ({ error, showStack = true, copyable = true, size = "sm" }) => {
|
|
259
|
-
const [stackExpanded, setStackExpanded] = useState(false);
|
|
260
|
-
const sizeConfig = getSizeConfig(size);
|
|
261
|
-
const copyIconSize = sizeConfig.icon + 2;
|
|
262
|
-
const isError = error instanceof Error;
|
|
263
|
-
const errorName = isError ? error.name : "Error";
|
|
264
|
-
const errorMessage = isError ? error.message : String(error);
|
|
265
|
-
const errorStack = isError ? error.stack : void 0;
|
|
266
|
-
const stackLines = errorStack ? parseStackTrace(errorStack) : [];
|
|
267
|
-
const getCopyContent = () => {
|
|
268
|
-
if (isError) return `${errorName}: ${errorMessage}${errorStack ? `\n\n${errorStack}` : ""}`;
|
|
269
|
-
return String(error);
|
|
270
|
-
};
|
|
271
|
-
return /* @__PURE__ */ jsxs(Flex$1, {
|
|
272
|
-
pos: "relative",
|
|
273
|
-
w: "100%",
|
|
274
|
-
children: [copyable && /* @__PURE__ */ jsx(Flex$1, {
|
|
275
|
-
pos: "absolute",
|
|
276
|
-
top: 0,
|
|
277
|
-
right: 0,
|
|
278
|
-
style: { zIndex: 1 },
|
|
279
|
-
children: /* @__PURE__ */ jsx(CopyButton, {
|
|
280
|
-
value: getCopyContent(),
|
|
281
|
-
children: ({ copied, copy }) => /* @__PURE__ */ jsx(Tooltip, {
|
|
282
|
-
label: copied ? "Copied" : "Copy Error",
|
|
283
|
-
children: /* @__PURE__ */ jsx(ActionIcon, {
|
|
284
|
-
color: copied ? "teal" : "gray",
|
|
285
|
-
variant: "subtle",
|
|
286
|
-
onClick: copy,
|
|
287
|
-
size,
|
|
288
|
-
children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: copyIconSize }) : /* @__PURE__ */ jsx(IconCopy, { size: copyIconSize })
|
|
289
|
-
})
|
|
290
|
-
})
|
|
291
|
-
})
|
|
292
|
-
}), /* @__PURE__ */ jsxs(Flex$1, {
|
|
293
|
-
pt: copyable ? 30 : 0,
|
|
294
|
-
children: [/* @__PURE__ */ jsxs(Flex$1, {
|
|
295
|
-
style: {
|
|
296
|
-
display: "flex",
|
|
297
|
-
alignItems: "flex-start",
|
|
298
|
-
gap: sizeConfig.gap
|
|
299
|
-
},
|
|
300
|
-
children: [/* @__PURE__ */ jsxs(Text$1, {
|
|
301
|
-
component: "span",
|
|
302
|
-
c: "red",
|
|
303
|
-
ff: "monospace",
|
|
304
|
-
fw: 600,
|
|
305
|
-
size: sizeConfig.text,
|
|
306
|
-
children: [errorName, ":"]
|
|
307
|
-
}), /* @__PURE__ */ jsx(Text$1, {
|
|
308
|
-
component: "span",
|
|
309
|
-
ff: "monospace",
|
|
310
|
-
size: sizeConfig.text,
|
|
311
|
-
style: { wordBreak: "break-word" },
|
|
312
|
-
children: errorMessage
|
|
313
|
-
})]
|
|
314
|
-
}), showStack && stackLines.length > 1 && /* @__PURE__ */ jsxs(Flex$1, {
|
|
315
|
-
mt: "sm",
|
|
316
|
-
children: [/* @__PURE__ */ jsxs(Flex$1, {
|
|
317
|
-
style: {
|
|
318
|
-
display: "flex",
|
|
319
|
-
alignItems: "center",
|
|
320
|
-
gap: sizeConfig.gap,
|
|
321
|
-
cursor: "pointer"
|
|
322
|
-
},
|
|
323
|
-
onClick: () => setStackExpanded(!stackExpanded),
|
|
324
|
-
children: [/* @__PURE__ */ jsx(ActionIcon, {
|
|
325
|
-
size: "xs",
|
|
326
|
-
variant: "transparent",
|
|
327
|
-
c: "dimmed",
|
|
328
|
-
children: stackExpanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: sizeConfig.icon }) : /* @__PURE__ */ jsx(IconChevronRight, { size: sizeConfig.icon })
|
|
329
|
-
}), /* @__PURE__ */ jsxs(Text$1, {
|
|
330
|
-
c: "dimmed",
|
|
331
|
-
size: sizeConfig.text,
|
|
332
|
-
fw: 500,
|
|
333
|
-
children: [
|
|
334
|
-
"Stack Trace (",
|
|
335
|
-
stackLines.length - 1,
|
|
336
|
-
" frames)"
|
|
337
|
-
]
|
|
338
|
-
})]
|
|
339
|
-
}), /* @__PURE__ */ jsx(Collapse, {
|
|
340
|
-
in: stackExpanded,
|
|
341
|
-
children: /* @__PURE__ */ jsx(Flex$1, {
|
|
342
|
-
mt: "xs",
|
|
343
|
-
pl: "md",
|
|
344
|
-
style: { borderLeft: "1px solid var(--mantine-color-default-border)" },
|
|
345
|
-
children: stackLines.slice(1).map((line, index) => /* @__PURE__ */ jsx(Text$1, {
|
|
346
|
-
ff: "monospace",
|
|
347
|
-
size: "xs",
|
|
348
|
-
c: "dimmed",
|
|
349
|
-
style: {
|
|
350
|
-
whiteSpace: "pre-wrap",
|
|
351
|
-
wordBreak: "break-all"
|
|
352
|
-
},
|
|
353
|
-
children: line
|
|
354
|
-
}, index))
|
|
355
|
-
})
|
|
356
|
-
})]
|
|
357
|
-
})]
|
|
358
|
-
})]
|
|
359
|
-
});
|
|
360
|
-
};
|
|
361
|
-
|
|
362
214
|
//#endregion
|
|
363
215
|
//#region ../../src/core/components/dialogs/AlertDialog.tsx
|
|
364
|
-
const AlertDialog = ({ options, onClose }) => /* @__PURE__ */ jsxs(Fragment
|
|
216
|
+
const AlertDialog = ({ options, onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [options?.message && /* @__PURE__ */ jsx(Text$1, {
|
|
365
217
|
mb: "md",
|
|
366
218
|
children: options.message
|
|
367
219
|
}), /* @__PURE__ */ jsx(Flex$1, {
|
|
@@ -374,7 +226,7 @@ const AlertDialog = ({ options, onClose }) => /* @__PURE__ */ jsxs(Fragment$1, {
|
|
|
374
226
|
|
|
375
227
|
//#endregion
|
|
376
228
|
//#region ../../src/core/components/dialogs/ConfirmDialog.tsx
|
|
377
|
-
const ConfirmDialog = ({ options, onConfirm }) => /* @__PURE__ */ jsxs(Fragment
|
|
229
|
+
const ConfirmDialog = ({ options, onConfirm }) => /* @__PURE__ */ jsxs(Fragment, { children: [options?.message && /* @__PURE__ */ jsx(Text$1, {
|
|
378
230
|
mb: "md",
|
|
379
231
|
children: options.message
|
|
380
232
|
}), /* @__PURE__ */ jsxs(Flex$1, {
|
|
@@ -404,7 +256,7 @@ const PromptDialog = ({ options, onSubmit }) => {
|
|
|
404
256
|
const handleKeyDown = (event) => {
|
|
405
257
|
if (event.key === "Enter") handleSubmit();
|
|
406
258
|
};
|
|
407
|
-
return /* @__PURE__ */ jsxs(Fragment
|
|
259
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
408
260
|
options?.message && /* @__PURE__ */ jsx(Text$1, {
|
|
409
261
|
mb: "md",
|
|
410
262
|
children: options.message
|
|
@@ -434,25 +286,6 @@ const PromptDialog = ({ options, onSubmit }) => {
|
|
|
434
286
|
] });
|
|
435
287
|
};
|
|
436
288
|
|
|
437
|
-
//#endregion
|
|
438
|
-
//#region ../../src/core/constants/ui.ts
|
|
439
|
-
const ui = {
|
|
440
|
-
colors: {
|
|
441
|
-
transparent: "transparent",
|
|
442
|
-
background: "var(--alepha-background)",
|
|
443
|
-
surface: "var(--alepha-surface)",
|
|
444
|
-
elevated: "var(--alepha-elevated)",
|
|
445
|
-
border: "var(--alepha-border)"
|
|
446
|
-
},
|
|
447
|
-
sizes: { icon: {
|
|
448
|
-
xs: 14,
|
|
449
|
-
sm: 16,
|
|
450
|
-
md: 20,
|
|
451
|
-
lg: 24,
|
|
452
|
-
xl: 32
|
|
453
|
-
} }
|
|
454
|
-
};
|
|
455
|
-
|
|
456
289
|
//#endregion
|
|
457
290
|
//#region ../../src/core/services/DialogService.tsx
|
|
458
291
|
var DialogService = class {
|
|
@@ -544,42 +377,6 @@ var DialogService = class {
|
|
|
544
377
|
if (modalId) modals.close(modalId);
|
|
545
378
|
else modals.closeAll();
|
|
546
379
|
}
|
|
547
|
-
/**
|
|
548
|
-
* Show an error viewer dialog
|
|
549
|
-
*/
|
|
550
|
-
error(error, options) {
|
|
551
|
-
this.open({
|
|
552
|
-
size: "lg",
|
|
553
|
-
title: options?.title || "Error",
|
|
554
|
-
...options,
|
|
555
|
-
content: /* @__PURE__ */ jsx(Flex$1, {
|
|
556
|
-
bdrs: "md",
|
|
557
|
-
w: "100%",
|
|
558
|
-
flex: 1,
|
|
559
|
-
p: "sm",
|
|
560
|
-
bg: ui.colors.surface,
|
|
561
|
-
children: /* @__PURE__ */ jsx(ErrorViewer, {
|
|
562
|
-
size: "xs",
|
|
563
|
-
error,
|
|
564
|
-
showStack: options?.showStack ?? true
|
|
565
|
-
})
|
|
566
|
-
})
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Show a form dialog for structured input
|
|
571
|
-
*/
|
|
572
|
-
form(options) {
|
|
573
|
-
return Promise.resolve(null);
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* Show a loading/progress dialog with optional progress percentage
|
|
577
|
-
*/
|
|
578
|
-
loading(options) {}
|
|
579
|
-
/**
|
|
580
|
-
* Show an image viewer/gallery dialog
|
|
581
|
-
*/
|
|
582
|
-
image(src, options) {}
|
|
583
380
|
};
|
|
584
381
|
|
|
585
382
|
//#endregion
|
|
@@ -641,6 +438,21 @@ var ToastService = class {
|
|
|
641
438
|
}
|
|
642
439
|
};
|
|
643
440
|
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region ../../src/core/UiRouter.ts
|
|
443
|
+
/**
|
|
444
|
+
* UI Router defining the root page with AlephaMantineProvider.
|
|
445
|
+
*
|
|
446
|
+
* - Use UiRouter when you need Alepha's Mantine-based UI components and theming.
|
|
447
|
+
* - Prefer to use $ui() for convenience. (Custom Factory of UiRouter)
|
|
448
|
+
*/
|
|
449
|
+
var UiRouter = class {
|
|
450
|
+
root = $page({
|
|
451
|
+
path: "/",
|
|
452
|
+
component: AlephaMantineProvider
|
|
453
|
+
});
|
|
454
|
+
};
|
|
455
|
+
|
|
644
456
|
//#endregion
|
|
645
457
|
//#region ../../src/core/hooks/useTheme.ts
|
|
646
458
|
/**
|
|
@@ -678,22 +490,6 @@ const useToast = () => {
|
|
|
678
490
|
return useInject(ToastService);
|
|
679
491
|
};
|
|
680
492
|
|
|
681
|
-
//#endregion
|
|
682
|
-
//#region ../../src/core/helpers/isComponentType.ts
|
|
683
|
-
function isComponentType(param) {
|
|
684
|
-
if (isValidElement(param)) return false;
|
|
685
|
-
return typeof param === "function" || typeof param === "object" && param !== null && "$$typeof" in param;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
//#endregion
|
|
689
|
-
//#region ../../src/core/helpers/renderIcon.tsx
|
|
690
|
-
const renderIcon = (icon, size) => {
|
|
691
|
-
if (!icon) return null;
|
|
692
|
-
if (isValidElement(icon)) return icon;
|
|
693
|
-
if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: size ?? ui$1.sizes.icon.md });
|
|
694
|
-
return icon;
|
|
695
|
-
};
|
|
696
|
-
|
|
697
493
|
//#endregion
|
|
698
494
|
//#region ../../src/core/components/layout/Omnibar.tsx
|
|
699
495
|
const Omnibar = (props) => {
|
|
@@ -727,7 +523,7 @@ const Omnibar = (props) => {
|
|
|
727
523
|
};
|
|
728
524
|
|
|
729
525
|
//#endregion
|
|
730
|
-
//#region ../../src/core/components/
|
|
526
|
+
//#region ../../src/core/components/AlephaMantineProvider.tsx
|
|
731
527
|
const AlephaMantineProvider = (props) => {
|
|
732
528
|
const toast = useToast();
|
|
733
529
|
const [theme] = useTheme();
|
|
@@ -747,14 +543,13 @@ const AlephaMantineProvider = (props) => {
|
|
|
747
543
|
}
|
|
748
544
|
}, []);
|
|
749
545
|
const defaultColorScheme = props.mantine?.defaultColorScheme ?? theme.defaultColorScheme;
|
|
750
|
-
return /* @__PURE__ */ jsxs(Fragment
|
|
546
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ColorSchemeScript, {
|
|
751
547
|
defaultColorScheme,
|
|
752
548
|
...props.colorSchemeScript
|
|
753
549
|
}), /* @__PURE__ */ jsxs(MantineProvider, {
|
|
754
550
|
...props.mantine,
|
|
755
551
|
defaultColorScheme,
|
|
756
552
|
theme: {
|
|
757
|
-
cursorType: "pointer",
|
|
758
553
|
...theme,
|
|
759
554
|
...props.mantine?.theme
|
|
760
555
|
},
|
|
@@ -770,20 +565,31 @@ const AlephaMantineProvider = (props) => {
|
|
|
770
565
|
};
|
|
771
566
|
|
|
772
567
|
//#endregion
|
|
773
|
-
//#region ../../src/core/
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
var
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
568
|
+
//#region ../../src/core/constants/ui.ts
|
|
569
|
+
const ui = {
|
|
570
|
+
colors: {
|
|
571
|
+
transparent: "transparent",
|
|
572
|
+
background: "var(--alepha-background)",
|
|
573
|
+
surface: "var(--alepha-surface)",
|
|
574
|
+
elevated: "var(--alepha-elevated)",
|
|
575
|
+
border: "var(--alepha-border)"
|
|
576
|
+
},
|
|
577
|
+
sizes: { icon: {
|
|
578
|
+
xs: 14,
|
|
579
|
+
sm: 16,
|
|
580
|
+
md: 20,
|
|
581
|
+
lg: 24,
|
|
582
|
+
xl: 32
|
|
583
|
+
} }
|
|
785
584
|
};
|
|
786
585
|
|
|
586
|
+
//#endregion
|
|
587
|
+
//#region ../../src/core/helpers/isComponentType.ts
|
|
588
|
+
function isComponentType(param) {
|
|
589
|
+
if (isValidElement(param)) return false;
|
|
590
|
+
return typeof param === "function" || typeof param === "object" && param !== null && "$$typeof" in param;
|
|
591
|
+
}
|
|
592
|
+
|
|
787
593
|
//#endregion
|
|
788
594
|
//#region ../../src/core/components/buttons/ActionButton.tsx
|
|
789
595
|
const ActionMenuItem = (props) => {
|
|
@@ -854,7 +660,7 @@ const ActionButton = (_props) => {
|
|
|
854
660
|
if (props.leftSection && !props.children) restProps.px ??= "xs";
|
|
855
661
|
if (props.textVisibleFrom) {
|
|
856
662
|
const { children, textVisibleFrom, leftSection, ...rest } = restProps;
|
|
857
|
-
return /* @__PURE__ */ jsxs(Fragment
|
|
663
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Flex$1, {
|
|
858
664
|
w: "100%",
|
|
859
665
|
visibleFrom: textVisibleFrom,
|
|
860
666
|
children: /* @__PURE__ */ jsx(ActionButton, {
|
|
@@ -892,6 +698,7 @@ const ActionButton = (_props) => {
|
|
|
892
698
|
}
|
|
893
699
|
delete restProps.classNameActive;
|
|
894
700
|
delete restProps.variantActive;
|
|
701
|
+
delete restProps.propsActive;
|
|
895
702
|
if ("action" in restProps && restProps.action) return /* @__PURE__ */ jsx(ActionHookButton, {
|
|
896
703
|
...restProps,
|
|
897
704
|
action: restProps.action,
|
|
@@ -1026,22 +833,24 @@ const ActionClickButton = ({ preventDefault, ...props }) => {
|
|
|
1026
833
|
* Action for navigation with active state support.
|
|
1027
834
|
*/
|
|
1028
835
|
const ActionNavigationButton = (props) => {
|
|
1029
|
-
const { active: options, classNameActive, variantActive, routerGoOptions, onClick: propsOnClick, ...buttonProps } = props;
|
|
836
|
+
const { active: options, classNameActive, variantActive, propsActive, routerGoOptions, onClick: propsOnClick, anchor, ...buttonProps } = props;
|
|
1030
837
|
const router = useRouter();
|
|
1031
838
|
const { isPending, isActive } = useActive(options ? {
|
|
1032
839
|
href: props.href,
|
|
1033
840
|
...options
|
|
1034
841
|
} : { href: props.href });
|
|
1035
842
|
const anchorProps = router.anchor(props.href, routerGoOptions);
|
|
843
|
+
if (propsActive && isActive) Object.assign(buttonProps, propsActive);
|
|
1036
844
|
const combinedOnClick = (e) => {
|
|
1037
845
|
propsOnClick?.(e);
|
|
1038
846
|
anchorProps.onClick?.(e);
|
|
1039
847
|
};
|
|
1040
848
|
const className = buttonProps.className || "";
|
|
1041
849
|
if (isActive && options !== false && classNameActive) buttonProps.className = `${className} ${classNameActive}`.trim();
|
|
1042
|
-
if (props.anchorProps) return /* @__PURE__ */ jsx(Anchor, {
|
|
850
|
+
if (props.anchorProps || anchor) return /* @__PURE__ */ jsx(Anchor, {
|
|
1043
851
|
component: "a",
|
|
1044
852
|
...anchorProps,
|
|
853
|
+
...buttonProps,
|
|
1045
854
|
...props.anchorProps,
|
|
1046
855
|
onClick: combinedOnClick,
|
|
1047
856
|
children: props.children
|
|
@@ -1057,7 +866,7 @@ const ActionNavigationButton = (props) => {
|
|
|
1057
866
|
});
|
|
1058
867
|
};
|
|
1059
868
|
const ActionHrefButton = (props) => {
|
|
1060
|
-
const { active: options, classNameActive, variantActive, routerGoOptions, target, ...buttonProps } = props;
|
|
869
|
+
const { active: options, classNameActive, variantActive, propsActive, routerGoOptions, target, ...buttonProps } = props;
|
|
1061
870
|
return /* @__PURE__ */ jsx(Button, {
|
|
1062
871
|
component: "a",
|
|
1063
872
|
target,
|
|
@@ -1071,12 +880,12 @@ const ActionHrefButton = (props) => {
|
|
|
1071
880
|
const BurgerButton = (props) => {
|
|
1072
881
|
const [sidebar, setSidebar] = useStore(alephaSidebarAtom);
|
|
1073
882
|
return /* @__PURE__ */ jsx(Burger, {
|
|
1074
|
-
opened: sidebar.
|
|
883
|
+
opened: !sidebar.closed,
|
|
1075
884
|
onClick: () => setSidebar({
|
|
1076
885
|
...sidebar,
|
|
1077
|
-
|
|
886
|
+
closed: !sidebar.closed
|
|
1078
887
|
}),
|
|
1079
|
-
hiddenFrom: "
|
|
888
|
+
hiddenFrom: "md",
|
|
1080
889
|
size: "sm",
|
|
1081
890
|
...props
|
|
1082
891
|
});
|
|
@@ -1124,7 +933,7 @@ const DarkModeButton = (props) => {
|
|
|
1124
933
|
variant: props.variant ?? "subtle",
|
|
1125
934
|
size,
|
|
1126
935
|
"aria-label": "Toggle color scheme",
|
|
1127
|
-
icon: /* @__PURE__ */ jsxs(Fragment
|
|
936
|
+
icon: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(IconSun, {
|
|
1128
937
|
size: iconSize,
|
|
1129
938
|
className: "alepha-light-hidden"
|
|
1130
939
|
}), /* @__PURE__ */ jsx(IconMoon, {
|
|
@@ -1140,7 +949,7 @@ const DarkModeButton = (props) => {
|
|
|
1140
949
|
const LanguageButton = (props) => {
|
|
1141
950
|
const i18n = useI18n();
|
|
1142
951
|
return /* @__PURE__ */ jsx(ActionButton, {
|
|
1143
|
-
variant: "
|
|
952
|
+
variant: "subtle",
|
|
1144
953
|
icon: IconLanguage,
|
|
1145
954
|
menu: { items: i18n.languages.map((lang) => ({
|
|
1146
955
|
label: i18n.tr(lang),
|
|
@@ -1220,15 +1029,13 @@ const ToggleSidebarButton = (props) => {
|
|
|
1220
1029
|
const [sidebar, setSidebar] = useStore(alephaSidebarAtom);
|
|
1221
1030
|
return /* @__PURE__ */ jsx(ActionButton, {
|
|
1222
1031
|
icon: sidebar.collapsed ? IconLayoutSidebarRightCollapse : IconLayoutSidebarLeftCollapse,
|
|
1223
|
-
visibleFrom: "
|
|
1032
|
+
visibleFrom: "md",
|
|
1224
1033
|
variant: "subtle",
|
|
1225
1034
|
size: "md",
|
|
1226
1035
|
onClick: () => {
|
|
1227
|
-
const expanding = sidebar.collapsed;
|
|
1228
1036
|
setSidebar({
|
|
1229
1037
|
...sidebar,
|
|
1230
|
-
collapsed: !sidebar.collapsed
|
|
1231
|
-
width: expanding ? sidebar.defaultWidth : sidebar.width
|
|
1038
|
+
collapsed: !sidebar.collapsed
|
|
1232
1039
|
});
|
|
1233
1040
|
},
|
|
1234
1041
|
tooltip: {
|
|
@@ -1240,190 +1047,837 @@ const ToggleSidebarButton = (props) => {
|
|
|
1240
1047
|
};
|
|
1241
1048
|
|
|
1242
1049
|
//#endregion
|
|
1243
|
-
//#region ../../src/core/
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1050
|
+
//#region ../../src/core/components/data/DetailDrawer.tsx
|
|
1051
|
+
const DetailDrawer = ({ opened, onClose, title, subtitle, status, actions, tabs, children, loading, size = "xl", defaultTab }) => /* @__PURE__ */ jsxs(Drawer, {
|
|
1052
|
+
opened,
|
|
1053
|
+
onClose,
|
|
1054
|
+
position: "right",
|
|
1055
|
+
size,
|
|
1056
|
+
withCloseButton: false,
|
|
1057
|
+
padding: 0,
|
|
1058
|
+
children: [/* @__PURE__ */ jsxs(Flex$1, {
|
|
1059
|
+
p: "md",
|
|
1060
|
+
justify: "space-between",
|
|
1061
|
+
align: "flex-start",
|
|
1062
|
+
style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
|
|
1063
|
+
children: [/* @__PURE__ */ jsxs(Flex$1, {
|
|
1064
|
+
direction: "column",
|
|
1065
|
+
gap: 2,
|
|
1066
|
+
style: {
|
|
1067
|
+
minWidth: 0,
|
|
1068
|
+
flex: 1
|
|
1069
|
+
},
|
|
1070
|
+
children: [/* @__PURE__ */ jsxs(Flex$1, {
|
|
1071
|
+
gap: "xs",
|
|
1072
|
+
align: "center",
|
|
1073
|
+
children: [status && /* @__PURE__ */ jsx(Flex$1, {
|
|
1074
|
+
w: 8,
|
|
1075
|
+
h: 8,
|
|
1076
|
+
style: {
|
|
1077
|
+
borderRadius: "50%",
|
|
1078
|
+
backgroundColor: status.active ? "var(--mantine-color-green-6)" : "var(--mantine-color-red-6)",
|
|
1079
|
+
flexShrink: 0
|
|
1080
|
+
}
|
|
1081
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
1082
|
+
size: "lg",
|
|
1083
|
+
fw: 600,
|
|
1084
|
+
truncate: true,
|
|
1085
|
+
children: title
|
|
1086
|
+
})]
|
|
1087
|
+
}), subtitle && /* @__PURE__ */ jsx(Text$1, {
|
|
1088
|
+
size: "sm",
|
|
1089
|
+
c: "dimmed",
|
|
1090
|
+
truncate: true,
|
|
1091
|
+
children: subtitle
|
|
1092
|
+
})]
|
|
1093
|
+
}), /* @__PURE__ */ jsxs(Flex$1, {
|
|
1094
|
+
gap: "xs",
|
|
1095
|
+
align: "center",
|
|
1096
|
+
style: { flexShrink: 0 },
|
|
1097
|
+
children: [actions && actions.length > 0 && /* @__PURE__ */ jsx(ActionButton, {
|
|
1098
|
+
variant: "default",
|
|
1099
|
+
size: "xs",
|
|
1100
|
+
menu: {
|
|
1101
|
+
items: actions,
|
|
1102
|
+
position: "bottom-end",
|
|
1103
|
+
width: 200
|
|
1104
|
+
},
|
|
1105
|
+
children: "Actions"
|
|
1106
|
+
}), /* @__PURE__ */ jsx(ActionButton, {
|
|
1107
|
+
variant: "subtle",
|
|
1108
|
+
size: "xs",
|
|
1109
|
+
c: "dimmed",
|
|
1110
|
+
onClick: onClose,
|
|
1111
|
+
children: "Close"
|
|
1112
|
+
})]
|
|
1113
|
+
})]
|
|
1114
|
+
}), loading ? /* @__PURE__ */ jsx(Flex$1, {
|
|
1115
|
+
flex: 1,
|
|
1116
|
+
justify: "center",
|
|
1117
|
+
align: "center",
|
|
1118
|
+
py: "xl",
|
|
1119
|
+
children: /* @__PURE__ */ jsx(Loader, {})
|
|
1120
|
+
}) : tabs && tabs.length > 0 ? /* @__PURE__ */ jsxs(Tabs, {
|
|
1121
|
+
defaultValue: defaultTab || tabs[0].value,
|
|
1122
|
+
children: [/* @__PURE__ */ jsx(Tabs.List, {
|
|
1123
|
+
px: "md",
|
|
1124
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsx(Tabs.Tab, {
|
|
1125
|
+
value: tab.value,
|
|
1126
|
+
leftSection: tab.icon ? /* @__PURE__ */ jsx(tab.icon, { size: 14 }) : void 0,
|
|
1127
|
+
children: tab.label
|
|
1128
|
+
}, tab.value))
|
|
1129
|
+
}), tabs.map((tab) => /* @__PURE__ */ jsx(Tabs.Panel, {
|
|
1130
|
+
value: tab.value,
|
|
1131
|
+
p: "md",
|
|
1132
|
+
children: tab.content
|
|
1133
|
+
}, tab.value))]
|
|
1134
|
+
}) : /* @__PURE__ */ jsx(Flex$1, {
|
|
1135
|
+
direction: "column",
|
|
1136
|
+
p: "md",
|
|
1137
|
+
children
|
|
1138
|
+
})]
|
|
1139
|
+
});
|
|
1283
1140
|
|
|
1284
1141
|
//#endregion
|
|
1285
|
-
//#region ../../src/core/
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
*/
|
|
1292
|
-
|
|
1293
|
-
|
|
1142
|
+
//#region ../../src/core/components/data/DetailList.tsx
|
|
1143
|
+
const DetailList = ({ items, columns = 1 }) => {
|
|
1144
|
+
return /* @__PURE__ */ jsx(Grid, {
|
|
1145
|
+
gutter: "xs",
|
|
1146
|
+
children: items.filter((item) => !item.hidden).map((item) => /* @__PURE__ */ jsx(Grid.Col, {
|
|
1147
|
+
span: 12 / columns,
|
|
1148
|
+
children: /* @__PURE__ */ jsxs(Flex$1, {
|
|
1149
|
+
py: 6,
|
|
1150
|
+
justify: "space-between",
|
|
1151
|
+
align: "center",
|
|
1152
|
+
style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
|
|
1153
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
1154
|
+
size: "xs",
|
|
1155
|
+
c: "dimmed",
|
|
1156
|
+
style: { flexShrink: 0 },
|
|
1157
|
+
children: item.label
|
|
1158
|
+
}), /* @__PURE__ */ jsxs(Flex$1, {
|
|
1159
|
+
gap: 4,
|
|
1160
|
+
align: "center",
|
|
1161
|
+
style: { minWidth: 0 },
|
|
1162
|
+
children: [typeof item.value === "string" || typeof item.value === "number" ? /* @__PURE__ */ jsx(Text$1, {
|
|
1163
|
+
size: "sm",
|
|
1164
|
+
fw: 500,
|
|
1165
|
+
truncate: true,
|
|
1166
|
+
children: item.value || "—"
|
|
1167
|
+
}) : item.value ?? /* @__PURE__ */ jsx(Text$1, {
|
|
1168
|
+
size: "sm",
|
|
1169
|
+
c: "dimmed",
|
|
1170
|
+
children: "—"
|
|
1171
|
+
}), item.copyable && /* @__PURE__ */ jsx(ClipboardButton, {
|
|
1172
|
+
value: item.copyable,
|
|
1173
|
+
size: "xs",
|
|
1174
|
+
variant: "subtle",
|
|
1175
|
+
c: "dimmed"
|
|
1176
|
+
})]
|
|
1177
|
+
})]
|
|
1178
|
+
})
|
|
1179
|
+
}, item.label))
|
|
1180
|
+
});
|
|
1294
1181
|
};
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
*/
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1182
|
+
|
|
1183
|
+
//#endregion
|
|
1184
|
+
//#region ../../src/core/components/data/StatCards.tsx
|
|
1185
|
+
const StatCards = ({ items }) => /* @__PURE__ */ jsx(Flex$1, {
|
|
1186
|
+
gap: "sm",
|
|
1187
|
+
wrap: "wrap",
|
|
1188
|
+
children: items.map((item) => {
|
|
1189
|
+
(item.icon && typeof item.icon === "function" ? item.icon : null) ? ui.sizes.icon.md : item.icon;
|
|
1190
|
+
return /* @__PURE__ */ jsx(Paper, {
|
|
1191
|
+
p: "md",
|
|
1192
|
+
radius: "md",
|
|
1193
|
+
withBorder: true,
|
|
1194
|
+
style: {
|
|
1195
|
+
flex: "1 1 0",
|
|
1196
|
+
minWidth: 120
|
|
1197
|
+
},
|
|
1198
|
+
children: /* @__PURE__ */ jsx(Flex$1, {
|
|
1199
|
+
gap: "sm",
|
|
1200
|
+
align: "center",
|
|
1201
|
+
children: /* @__PURE__ */ jsxs(Flex$1, {
|
|
1202
|
+
direction: "column",
|
|
1203
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
1204
|
+
size: "xl",
|
|
1205
|
+
fw: 700,
|
|
1206
|
+
lh: 1,
|
|
1207
|
+
children: item.value
|
|
1208
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
1209
|
+
size: "xs",
|
|
1210
|
+
c: "dimmed",
|
|
1211
|
+
children: item.label
|
|
1212
|
+
})]
|
|
1213
|
+
})
|
|
1214
|
+
})
|
|
1215
|
+
}, item.label);
|
|
1216
|
+
})
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
//#endregion
|
|
1220
|
+
//#region ../../src/core/components/Flex.tsx
|
|
1221
|
+
const Flex = forwardRef((props, ref) => {
|
|
1222
|
+
const { fill, center, centerX, centerY, col, ...rest } = props;
|
|
1223
|
+
if (fill) rest.flex ??= 1;
|
|
1224
|
+
if (col) rest.direction ??= "column";
|
|
1225
|
+
if (center) {
|
|
1226
|
+
rest.align ??= "center";
|
|
1227
|
+
rest.justify ??= "center";
|
|
1228
|
+
}
|
|
1229
|
+
if (centerX) rest.justify ??= "center";
|
|
1230
|
+
if (centerY) rest.align ??= "center";
|
|
1231
|
+
return /* @__PURE__ */ jsx(Flex$1, {
|
|
1232
|
+
ref,
|
|
1233
|
+
...rest
|
|
1234
|
+
});
|
|
1235
|
+
});
|
|
1236
|
+
Flex.displayName = "Flex";
|
|
1237
|
+
|
|
1238
|
+
//#endregion
|
|
1239
|
+
//#region ../../src/core/components/Heading.tsx
|
|
1240
|
+
const Heading = (props) => {
|
|
1241
|
+
return /* @__PURE__ */ jsx("h1", { children: "Heading" });
|
|
1320
1242
|
};
|
|
1321
1243
|
|
|
1322
1244
|
//#endregion
|
|
1323
|
-
//#region ../../src/core/
|
|
1324
|
-
const
|
|
1325
|
-
const
|
|
1326
|
-
const
|
|
1327
|
-
const
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
label,
|
|
1342
|
-
description,
|
|
1343
|
-
error,
|
|
1344
|
-
required,
|
|
1345
|
-
disabled
|
|
1245
|
+
//#region ../../src/core/components/layout/AppBar.tsx
|
|
1246
|
+
const AppBar = (props) => {
|
|
1247
|
+
const { items = [] } = props;
|
|
1248
|
+
const router = useRouter();
|
|
1249
|
+
const renderItem = (item, index) => {
|
|
1250
|
+
if (item.can && !item.can()) return null;
|
|
1251
|
+
if ("type" in item) {
|
|
1252
|
+
if (item.type === "burger") return /* @__PURE__ */ jsx(BurgerButton, {}, index);
|
|
1253
|
+
if (item.type === "dark") return /* @__PURE__ */ jsx(DarkModeButton, { ...item.props }, index);
|
|
1254
|
+
if (item.type === "search") return /* @__PURE__ */ jsx(OmnibarButton, { ...item.props }, index);
|
|
1255
|
+
if (item.type === "lang") return /* @__PURE__ */ jsx(LanguageButton, { ...item.props }, index);
|
|
1256
|
+
if (item.type === "spacer") return /* @__PURE__ */ jsx(Flex, { w: 16 }, index);
|
|
1257
|
+
if (item.type === "divider") return /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }, index);
|
|
1258
|
+
if (item.type === "logo") return renderLogo(item, index);
|
|
1259
|
+
if (item.type === "back") return renderBack(item, index);
|
|
1260
|
+
}
|
|
1261
|
+
if ("element" in item) return item.element;
|
|
1262
|
+
return null;
|
|
1346
1263
|
};
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1264
|
+
const renderLogo = (item, index) => {
|
|
1265
|
+
const { src, text, icon, href, height = 32, width, fontWeight = 700, fontSize = "lg" } = item.props ?? {};
|
|
1266
|
+
const logoContent = src ? /* @__PURE__ */ jsx(Image, {
|
|
1267
|
+
src,
|
|
1268
|
+
h: height,
|
|
1269
|
+
w: width,
|
|
1270
|
+
fit: "contain"
|
|
1271
|
+
}) : icon ? typeof icon === "function" ? /* @__PURE__ */ jsx(icon, {}) : icon : text ? /* @__PURE__ */ jsx(Text, {
|
|
1272
|
+
fw: fontWeight,
|
|
1273
|
+
size: fontSize,
|
|
1274
|
+
children: text
|
|
1275
|
+
}) : null;
|
|
1276
|
+
if (href) return /* @__PURE__ */ jsx(Anchor, {
|
|
1277
|
+
component: Link,
|
|
1278
|
+
href,
|
|
1279
|
+
underline: "never",
|
|
1280
|
+
c: "inherit",
|
|
1281
|
+
children: logoContent
|
|
1282
|
+
}, index);
|
|
1283
|
+
return /* @__PURE__ */ jsx(Flex, { children: logoContent }, index);
|
|
1284
|
+
};
|
|
1285
|
+
const renderBack = (item, index) => {
|
|
1286
|
+
const { label = "Back", iconOnly = true, href, icon } = item.props ?? {};
|
|
1287
|
+
const renderIcon = () => {
|
|
1288
|
+
if (!icon) return /* @__PURE__ */ jsx(IconArrowLeft, { size: 18 });
|
|
1289
|
+
if (typeof icon === "function") return /* @__PURE__ */ jsx(icon, { size: 18 });
|
|
1290
|
+
return icon;
|
|
1291
|
+
};
|
|
1292
|
+
const iconElement = renderIcon();
|
|
1293
|
+
const handleClick = () => {
|
|
1294
|
+
if (href) router.push(href);
|
|
1295
|
+
else router.back();
|
|
1296
|
+
};
|
|
1297
|
+
if (iconOnly) return /* @__PURE__ */ jsx(ActionButton, {
|
|
1298
|
+
icon: iconElement,
|
|
1299
|
+
variant: "subtle",
|
|
1300
|
+
color: "gray",
|
|
1301
|
+
onClick: handleClick,
|
|
1302
|
+
tooltip: {
|
|
1303
|
+
label,
|
|
1304
|
+
position: "bottom"
|
|
1305
|
+
}
|
|
1306
|
+
}, index);
|
|
1307
|
+
return /* @__PURE__ */ jsx(ActionButton, {
|
|
1308
|
+
leftSection: iconElement,
|
|
1309
|
+
variant: "subtle",
|
|
1310
|
+
color: "gray",
|
|
1311
|
+
onClick: handleClick,
|
|
1312
|
+
children: label
|
|
1313
|
+
}, index);
|
|
1357
1314
|
};
|
|
1315
|
+
const leftItems = items.filter((item) => item.position === "left");
|
|
1316
|
+
const centerItems = items.filter((item) => item.position === "center");
|
|
1317
|
+
const rightItems = items.filter((item) => item.position === "right");
|
|
1318
|
+
const content = /* @__PURE__ */ jsxs(Flex, {
|
|
1319
|
+
h: "100%",
|
|
1320
|
+
align: "center",
|
|
1321
|
+
px: props.container ? 0 : "md",
|
|
1322
|
+
justify: "space-between",
|
|
1323
|
+
...props.flexProps,
|
|
1324
|
+
children: [
|
|
1325
|
+
/* @__PURE__ */ jsx(Flex, {
|
|
1326
|
+
flex: 1,
|
|
1327
|
+
children: leftItems.map((item, index) => /* @__PURE__ */ jsx(Flex, {
|
|
1328
|
+
ml: index === 0 ? 0 : "md",
|
|
1329
|
+
align: "center",
|
|
1330
|
+
children: renderItem(item, index)
|
|
1331
|
+
}, index))
|
|
1332
|
+
}),
|
|
1333
|
+
/* @__PURE__ */ jsx(Flex, { children: centerItems.map((item, index) => /* @__PURE__ */ jsx(Flex, {
|
|
1334
|
+
mx: "md",
|
|
1335
|
+
align: "center",
|
|
1336
|
+
children: renderItem(item, index)
|
|
1337
|
+
}, index)) }),
|
|
1338
|
+
/* @__PURE__ */ jsx(Flex, {
|
|
1339
|
+
flex: 1,
|
|
1340
|
+
align: "center",
|
|
1341
|
+
justify: "end",
|
|
1342
|
+
children: rightItems.map((item, index) => /* @__PURE__ */ jsx(Flex, {
|
|
1343
|
+
ml: index === 0 ? 0 : "md",
|
|
1344
|
+
align: "center",
|
|
1345
|
+
children: renderItem(item, index)
|
|
1346
|
+
}, index))
|
|
1347
|
+
})
|
|
1348
|
+
]
|
|
1349
|
+
});
|
|
1350
|
+
if (props.container) return /* @__PURE__ */ jsx(Container$1, {
|
|
1351
|
+
h: "100%",
|
|
1352
|
+
...typeof props.container === "boolean" ? {} : props.container,
|
|
1353
|
+
children: content
|
|
1354
|
+
});
|
|
1355
|
+
return content;
|
|
1358
1356
|
};
|
|
1359
1357
|
|
|
1360
1358
|
//#endregion
|
|
1361
|
-
//#region ../../src/core/components/
|
|
1359
|
+
//#region ../../src/core/components/layout/Breadcrumb.tsx
|
|
1362
1360
|
/**
|
|
1363
|
-
*
|
|
1364
|
-
*
|
|
1361
|
+
* Automatic breadcrumb component that reads the current route hierarchy
|
|
1362
|
+
* from the Alepha router's layer stack.
|
|
1363
|
+
*
|
|
1364
|
+
* Pages should define a `label` in their `$page()` options for best results.
|
|
1365
|
+
* Falls back to the page name converted to Title Case.
|
|
1365
1366
|
*/
|
|
1366
|
-
const
|
|
1367
|
-
const
|
|
1368
|
-
const
|
|
1369
|
-
const
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
value
|
|
1374
|
-
}));
|
|
1375
|
-
return [];
|
|
1367
|
+
const Breadcrumb = ({ home = "Home", separator, size = "sm", ...groupProps }) => {
|
|
1368
|
+
const state = useRouterState();
|
|
1369
|
+
const router = useRouter();
|
|
1370
|
+
const crumbs = [];
|
|
1371
|
+
if (home !== false) crumbs.push({
|
|
1372
|
+
label: home,
|
|
1373
|
+
href: "/"
|
|
1376
1374
|
});
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
keyCounter.current = 0;
|
|
1387
|
-
return formValue.map((value) => ({
|
|
1388
|
-
key: keyCounter.current++,
|
|
1389
|
-
value
|
|
1390
|
-
}));
|
|
1375
|
+
for (let i = 1; i < state.layers.length; i++) {
|
|
1376
|
+
const layer = state.layers[i];
|
|
1377
|
+
const route = layer.route;
|
|
1378
|
+
if (route?.path === "/" || route?.path === "") continue;
|
|
1379
|
+
const label = route?.label ?? toTitleCase(layer.name);
|
|
1380
|
+
const href = router.path(layer.name);
|
|
1381
|
+
crumbs.push({
|
|
1382
|
+
label,
|
|
1383
|
+
href
|
|
1391
1384
|
});
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
};
|
|
1426
|
-
};
|
|
1385
|
+
}
|
|
1386
|
+
if (crumbs.length === 0) return null;
|
|
1387
|
+
const sep = separator ?? /* @__PURE__ */ jsx(IconChevronRight, {
|
|
1388
|
+
size: 12,
|
|
1389
|
+
color: "#9ca3af"
|
|
1390
|
+
});
|
|
1391
|
+
return /* @__PURE__ */ jsx(Flex, {
|
|
1392
|
+
gap: "sm",
|
|
1393
|
+
...groupProps,
|
|
1394
|
+
children: crumbs.map((crumb, i) => /* @__PURE__ */ jsxs(Flex, {
|
|
1395
|
+
align: "center",
|
|
1396
|
+
gap: "sm",
|
|
1397
|
+
children: [i > 0 && sep, i < crumbs.length - 1 ? /* @__PURE__ */ jsx(ActionButton, {
|
|
1398
|
+
anchor: true,
|
|
1399
|
+
href: crumb.href,
|
|
1400
|
+
size,
|
|
1401
|
+
c: "dimmed",
|
|
1402
|
+
children: crumb.label
|
|
1403
|
+
}) : /* @__PURE__ */ jsx(Text, {
|
|
1404
|
+
size,
|
|
1405
|
+
fw: 500,
|
|
1406
|
+
children: crumb.label
|
|
1407
|
+
})]
|
|
1408
|
+
}, crumb.href))
|
|
1409
|
+
});
|
|
1410
|
+
};
|
|
1411
|
+
|
|
1412
|
+
//#endregion
|
|
1413
|
+
//#region ../../src/core/components/layout/Container.tsx
|
|
1414
|
+
const Container = forwardRef((props, ref) => {
|
|
1415
|
+
return /* @__PURE__ */ jsx(Container$1, {
|
|
1416
|
+
ref,
|
|
1417
|
+
...props
|
|
1418
|
+
});
|
|
1419
|
+
});
|
|
1420
|
+
Container.displayName = "Container";
|
|
1421
|
+
|
|
1422
|
+
//#endregion
|
|
1423
|
+
//#region ../../src/core/components/layout/Sidebar.tsx
|
|
1424
|
+
const Sidebar = (props) => {
|
|
1425
|
+
const router = useRouter();
|
|
1426
|
+
const { onItemClick } = props;
|
|
1427
|
+
const divider = (key, fill, collapsed) => {
|
|
1428
|
+
return /* @__PURE__ */ jsx(Flex, {
|
|
1429
|
+
h: 1,
|
|
1430
|
+
bg: "var(--mantine-color-default-border)",
|
|
1431
|
+
my: "xs",
|
|
1432
|
+
mx: fill ? "calc(-1 * var(--mantine-spacing-md))" : collapsed ? 0 : "sm"
|
|
1433
|
+
}, key);
|
|
1434
|
+
};
|
|
1435
|
+
const renderNode = (item, key, collapsed) => {
|
|
1436
|
+
if ("type" in item) {
|
|
1437
|
+
if (item.type === "spacer") {
|
|
1438
|
+
if (collapsed) return null;
|
|
1439
|
+
return /* @__PURE__ */ jsx(Flex, { h: 16 }, key);
|
|
1440
|
+
}
|
|
1441
|
+
if (item.type === "divider") return divider(key, item.fill, collapsed);
|
|
1442
|
+
if (item.type === "search") return /* @__PURE__ */ jsx(Flex, {
|
|
1443
|
+
mb: "xs",
|
|
1444
|
+
children: /* @__PURE__ */ jsx(OmnibarButton, { collapsed })
|
|
1445
|
+
}, key);
|
|
1446
|
+
if (item.type === "toggle") return /* @__PURE__ */ jsx(ToggleSidebarButton, {}, key);
|
|
1447
|
+
if (item.type === "section") {
|
|
1448
|
+
if (item.children && item.children.length > 0) {
|
|
1449
|
+
if (!item.children.some((child) => !("can" in child) || !child.can || child.can())) return null;
|
|
1450
|
+
}
|
|
1451
|
+
if (collapsed) return /* @__PURE__ */ jsxs(Fragment$1, { children: [divider(`${key}-d`, void 0, collapsed), item.children?.map((child, index) => renderNode(child, `s${key}-${index}`, collapsed))] }, key);
|
|
1452
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Flex, {
|
|
1453
|
+
mt: "md",
|
|
1454
|
+
align: "center",
|
|
1455
|
+
gap: "xs",
|
|
1456
|
+
children: [renderIcon(item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Text, {
|
|
1457
|
+
size: "xs",
|
|
1458
|
+
c: "dimmed",
|
|
1459
|
+
tt: "uppercase",
|
|
1460
|
+
fw: "bold",
|
|
1461
|
+
children: item.label
|
|
1462
|
+
})]
|
|
1463
|
+
}), item.children?.map((child, index) => renderNode(child, `s${key}-${index}`, collapsed))] }, key);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
if ("element" in item) return /* @__PURE__ */ jsx(Fragment$1, { children: item.element }, key);
|
|
1467
|
+
if (item.can && !item.can()) return null;
|
|
1468
|
+
if (item.children && item.children.length > 0) {
|
|
1469
|
+
if (!item.children.some((child) => !child.can || child.can())) return null;
|
|
1470
|
+
}
|
|
1471
|
+
if (collapsed) return /* @__PURE__ */ jsx(SidebarCollapsedItem, {
|
|
1472
|
+
item,
|
|
1473
|
+
level: 0,
|
|
1474
|
+
onItemClick,
|
|
1475
|
+
theme: props.theme ?? {}
|
|
1476
|
+
}, key);
|
|
1477
|
+
return /* @__PURE__ */ jsx(SidebarItem, {
|
|
1478
|
+
item,
|
|
1479
|
+
level: 0,
|
|
1480
|
+
onItemClick,
|
|
1481
|
+
theme: props.theme ?? {}
|
|
1482
|
+
}, key);
|
|
1483
|
+
};
|
|
1484
|
+
const getSidebarNodes = () => {
|
|
1485
|
+
if (props.items) return props.items;
|
|
1486
|
+
if (props.autoPopulateMenu) {
|
|
1487
|
+
const items = router.concretePages.filter((page) => !page.can || page.can()).map((page) => ({
|
|
1488
|
+
label: page.label ?? page.name,
|
|
1489
|
+
icon: renderIcon(page.icon),
|
|
1490
|
+
href: router.path(page.name)
|
|
1491
|
+
}));
|
|
1492
|
+
if (typeof props.autoPopulateMenu === "object" && props.autoPopulateMenu.startsWith) {
|
|
1493
|
+
const startsWith = props.autoPopulateMenu.startsWith;
|
|
1494
|
+
return items.filter((item) => item.href?.startsWith(startsWith));
|
|
1495
|
+
}
|
|
1496
|
+
return items;
|
|
1497
|
+
}
|
|
1498
|
+
return [];
|
|
1499
|
+
};
|
|
1500
|
+
const padding = "md";
|
|
1501
|
+
const gap = props.items ? props.gap ?? 4 : "xs";
|
|
1502
|
+
const menu = useMemo(() => getSidebarNodes(), [props.items, props.autoPopulateMenu]);
|
|
1503
|
+
const renderSidebar = (collapsed) => /* @__PURE__ */ jsxs(Flex, {
|
|
1504
|
+
flex: 1,
|
|
1505
|
+
py: padding,
|
|
1506
|
+
direction: "column",
|
|
1507
|
+
...props.flexProps,
|
|
1508
|
+
children: [
|
|
1509
|
+
/* @__PURE__ */ jsx(Flex, {
|
|
1510
|
+
gap,
|
|
1511
|
+
px: padding,
|
|
1512
|
+
direction: "column",
|
|
1513
|
+
children: menu.filter((it) => it.position === "top").map((item, index) => renderNode(item, index, collapsed))
|
|
1514
|
+
}),
|
|
1515
|
+
/* @__PURE__ */ jsx(Flex, {
|
|
1516
|
+
gap,
|
|
1517
|
+
px: padding,
|
|
1518
|
+
direction: "column",
|
|
1519
|
+
flex: 1,
|
|
1520
|
+
children: menu.filter((it) => !it.position).map((item, index) => renderNode(item, index, collapsed))
|
|
1521
|
+
}),
|
|
1522
|
+
/* @__PURE__ */ jsx(Flex, {
|
|
1523
|
+
gap,
|
|
1524
|
+
px: padding,
|
|
1525
|
+
direction: "column",
|
|
1526
|
+
children: menu.filter((it) => it.position === "bottom").map((item, index) => renderNode(item, index, collapsed))
|
|
1527
|
+
})
|
|
1528
|
+
]
|
|
1529
|
+
});
|
|
1530
|
+
if (props.collapsed) return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Flex, {
|
|
1531
|
+
flex: 1,
|
|
1532
|
+
direction: "column",
|
|
1533
|
+
visibleFrom: "md",
|
|
1534
|
+
children: renderSidebar(true)
|
|
1535
|
+
}), /* @__PURE__ */ jsx(Flex, {
|
|
1536
|
+
flex: 1,
|
|
1537
|
+
direction: "column",
|
|
1538
|
+
hiddenFrom: "md",
|
|
1539
|
+
children: renderSidebar(false)
|
|
1540
|
+
})] });
|
|
1541
|
+
return renderSidebar(false);
|
|
1542
|
+
};
|
|
1543
|
+
const SidebarItem = (props) => {
|
|
1544
|
+
const { item, level } = props;
|
|
1545
|
+
const maxLevel = 2;
|
|
1546
|
+
const router = useRouter();
|
|
1547
|
+
const isActive = useCallback((item) => {
|
|
1548
|
+
if (!item.children) return false;
|
|
1549
|
+
for (const child of item.children) {
|
|
1550
|
+
if (child.href) {
|
|
1551
|
+
if (router.isActive(child.href)) return true;
|
|
1552
|
+
}
|
|
1553
|
+
if (isActive(child)) return true;
|
|
1554
|
+
}
|
|
1555
|
+
return false;
|
|
1556
|
+
}, []);
|
|
1557
|
+
const [isOpen, setIsOpen] = useState(isActive(item));
|
|
1558
|
+
useEvents({ "react:transition:end": () => {
|
|
1559
|
+
if (isActive(item)) setIsOpen(true);
|
|
1560
|
+
} }, []);
|
|
1561
|
+
if (level > maxLevel) return null;
|
|
1562
|
+
const handleItemClick = (e) => {
|
|
1563
|
+
if (!props.item.target) e.preventDefault();
|
|
1564
|
+
if (item.children && item.children.length > 0) setIsOpen(!isOpen);
|
|
1565
|
+
else {
|
|
1566
|
+
props.onItemClick?.(item);
|
|
1567
|
+
item.onClick?.();
|
|
1568
|
+
}
|
|
1569
|
+
};
|
|
1570
|
+
return /* @__PURE__ */ jsxs(Flex, {
|
|
1571
|
+
direction: "column",
|
|
1572
|
+
ps: level === 0 ? 0 : 32,
|
|
1573
|
+
pos: "relative",
|
|
1574
|
+
children: [/* @__PURE__ */ jsx(ActionButton, {
|
|
1575
|
+
w: "100%",
|
|
1576
|
+
justify: "space-between",
|
|
1577
|
+
href: props.item.href,
|
|
1578
|
+
target: props.item.target,
|
|
1579
|
+
size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
|
|
1580
|
+
bd: 0,
|
|
1581
|
+
fw: "normal",
|
|
1582
|
+
variant: "default",
|
|
1583
|
+
propsActive: {
|
|
1584
|
+
variant: "outline",
|
|
1585
|
+
fw: "bold"
|
|
1586
|
+
},
|
|
1587
|
+
radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
|
|
1588
|
+
onClick: handleItemClick,
|
|
1589
|
+
leftSection: /* @__PURE__ */ jsxs(Flex, {
|
|
1590
|
+
w: "100%",
|
|
1591
|
+
align: "center",
|
|
1592
|
+
gap: "sm",
|
|
1593
|
+
children: [renderIcon(item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Flex, {
|
|
1594
|
+
direction: "column",
|
|
1595
|
+
children: /* @__PURE__ */ jsx(Flex, { children: item.label })
|
|
1596
|
+
})]
|
|
1597
|
+
}),
|
|
1598
|
+
rightSection: item.children ? /* @__PURE__ */ jsx(Flex, { children: isOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }) }) : props.item.rightSection,
|
|
1599
|
+
...props.item.actionProps
|
|
1600
|
+
}), item.children && isOpen && /* @__PURE__ */ jsxs(Flex, {
|
|
1601
|
+
direction: "column",
|
|
1602
|
+
"data-parent-level": level,
|
|
1603
|
+
children: [/* @__PURE__ */ jsx(Flex, { style: {
|
|
1604
|
+
position: "absolute",
|
|
1605
|
+
width: 1,
|
|
1606
|
+
background: "linear-gradient(to bottom, transparent, var(--mantine-color-default-border), transparent)",
|
|
1607
|
+
top: 48,
|
|
1608
|
+
left: 20 + 32 * level,
|
|
1609
|
+
bottom: 16
|
|
1610
|
+
} }), item.children.filter((child) => !child.can || child.can()).map((child, index) => /* @__PURE__ */ jsx(SidebarItem, {
|
|
1611
|
+
item: child,
|
|
1612
|
+
level: level + 1,
|
|
1613
|
+
onItemClick: props.onItemClick,
|
|
1614
|
+
theme: props.theme
|
|
1615
|
+
}, index))]
|
|
1616
|
+
})]
|
|
1617
|
+
});
|
|
1618
|
+
};
|
|
1619
|
+
const SidebarCollapsedItem = (props) => {
|
|
1620
|
+
const { item, level } = props;
|
|
1621
|
+
const router = useRouter();
|
|
1622
|
+
const handleItemClick = () => {
|
|
1623
|
+
props.onItemClick?.(item);
|
|
1624
|
+
item.onClick?.();
|
|
1625
|
+
};
|
|
1626
|
+
const hasChildren = item.children && item.children.length > 0;
|
|
1627
|
+
const menu = hasChildren ? {
|
|
1628
|
+
on: "hover",
|
|
1629
|
+
position: "right",
|
|
1630
|
+
items: item.children.filter((child) => !child.can || child.can()).map((child) => ({
|
|
1631
|
+
label: child.label,
|
|
1632
|
+
icon: renderIcon(child.icon, ui.sizes.icon.sm),
|
|
1633
|
+
href: child.href,
|
|
1634
|
+
active: child.href ? router.isActive(child.href, { startWith: child.activeStartsWith }) : void 0
|
|
1635
|
+
}))
|
|
1636
|
+
} : void 0;
|
|
1637
|
+
return /* @__PURE__ */ jsx(ActionButton, {
|
|
1638
|
+
size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
|
|
1639
|
+
variant: "subtle",
|
|
1640
|
+
variantActive: "default",
|
|
1641
|
+
tooltip: hasChildren ? void 0 : {
|
|
1642
|
+
label: item.label,
|
|
1643
|
+
position: "right"
|
|
1644
|
+
},
|
|
1645
|
+
radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
|
|
1646
|
+
onClick: hasChildren ? void 0 : handleItemClick,
|
|
1647
|
+
icon: renderIcon(item.icon, ui.sizes.icon.sm) ?? /* @__PURE__ */ jsx(IconSquareRounded, { size: ui.sizes.icon.sm }),
|
|
1648
|
+
href: hasChildren ? void 0 : props.item.href,
|
|
1649
|
+
target: hasChildren ? void 0 : props.item.target,
|
|
1650
|
+
menu,
|
|
1651
|
+
...props.item.actionProps
|
|
1652
|
+
});
|
|
1653
|
+
};
|
|
1654
|
+
|
|
1655
|
+
//#endregion
|
|
1656
|
+
//#region ../../src/core/components/layout/DashboardShell.tsx
|
|
1657
|
+
const DashboardShell = (props) => {
|
|
1658
|
+
const router = useRouter();
|
|
1659
|
+
const [sidebar, setSidebar] = useStore(alephaSidebarAtom);
|
|
1660
|
+
const collapsed = props.sidebarProps?.collapsed !== void 0 ? props.sidebarProps.collapsed : sidebar.collapsed;
|
|
1661
|
+
const { collapsedWidth, expandedWidth } = sidebar;
|
|
1662
|
+
const shouldShowSidebar = () => {
|
|
1663
|
+
if (props.noSidebarWhen?.paths) {
|
|
1664
|
+
for (const path of props.noSidebarWhen.paths) if (router.isActive(path, { startWith: true })) return false;
|
|
1665
|
+
}
|
|
1666
|
+
return true;
|
|
1667
|
+
};
|
|
1668
|
+
const [showSidebar, setShowSidebar] = useState(shouldShowSidebar());
|
|
1669
|
+
useEvents({
|
|
1670
|
+
"react:transition:end": () => {
|
|
1671
|
+
setShowSidebar(shouldShowSidebar());
|
|
1672
|
+
},
|
|
1673
|
+
"react:transition:begin": () => {
|
|
1674
|
+
setSidebar({
|
|
1675
|
+
...sidebar,
|
|
1676
|
+
closed: true
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
}, [sidebar]);
|
|
1680
|
+
const defaultAppBarItems = [{
|
|
1681
|
+
position: "left",
|
|
1682
|
+
type: "burger"
|
|
1683
|
+
}];
|
|
1684
|
+
const appBarProps = { ...props.appBarProps };
|
|
1685
|
+
appBarProps.container ??= props.container;
|
|
1686
|
+
const hasSidebar = showSidebar && props.sidebarProps !== void 0;
|
|
1687
|
+
const hasAppBar = props.appBarProps || props.header;
|
|
1688
|
+
let footerElement = props.footer;
|
|
1689
|
+
if (props.footerHeight) footerElement ??= /* @__PURE__ */ jsx(Flex, { h: props.footerHeight });
|
|
1690
|
+
const hHeight = props.headerHeight ?? 60;
|
|
1691
|
+
const fHeight = props.footerHeight ?? 24;
|
|
1692
|
+
const headerHeight = hasAppBar ? hHeight : 0;
|
|
1693
|
+
const footerHeight = footerElement ? fHeight : 0;
|
|
1694
|
+
return /* @__PURE__ */ jsxs(AppShell, {
|
|
1695
|
+
layout: "alt",
|
|
1696
|
+
w: "100%",
|
|
1697
|
+
flex: 1,
|
|
1698
|
+
header: hasAppBar ? { height: hHeight } : void 0,
|
|
1699
|
+
navbar: hasSidebar ? {
|
|
1700
|
+
width: { base: collapsed ? collapsedWidth : expandedWidth },
|
|
1701
|
+
breakpoint: "md",
|
|
1702
|
+
collapsed: { mobile: sidebar.closed }
|
|
1703
|
+
} : void 0,
|
|
1704
|
+
footer: footerElement ? { height: fHeight } : void 0,
|
|
1705
|
+
...props.appShellProps,
|
|
1706
|
+
children: [
|
|
1707
|
+
hasAppBar && /* @__PURE__ */ jsx(AppShell.Header, {
|
|
1708
|
+
...props.appShellHeaderProps,
|
|
1709
|
+
children: props.header ?? /* @__PURE__ */ jsx(AppBar, {
|
|
1710
|
+
items: defaultAppBarItems,
|
|
1711
|
+
...appBarProps
|
|
1712
|
+
})
|
|
1713
|
+
}),
|
|
1714
|
+
hasSidebar && /* @__PURE__ */ jsxs(AppShell.Navbar, {
|
|
1715
|
+
className: "alepha-sidebar-navbar",
|
|
1716
|
+
...props.appShellNavbarProps,
|
|
1717
|
+
children: [
|
|
1718
|
+
props.navbarHeader ? /* @__PURE__ */ jsx(Flex, {
|
|
1719
|
+
style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
|
|
1720
|
+
h: headerHeight,
|
|
1721
|
+
children: props.navbarHeader
|
|
1722
|
+
}) : null,
|
|
1723
|
+
/* @__PURE__ */ jsx(Sidebar, {
|
|
1724
|
+
...props.sidebarProps ?? {},
|
|
1725
|
+
collapsed
|
|
1726
|
+
}),
|
|
1727
|
+
props.navbarFooter ? /* @__PURE__ */ jsx(Flex, {
|
|
1728
|
+
style: { borderTop: "1px solid var(--mantine-color-default-border)" },
|
|
1729
|
+
h: footerHeight,
|
|
1730
|
+
children: props.navbarFooter
|
|
1731
|
+
}) : null
|
|
1732
|
+
]
|
|
1733
|
+
}),
|
|
1734
|
+
/* @__PURE__ */ jsx(AppShell.Main, {
|
|
1735
|
+
pos: "relative",
|
|
1736
|
+
...props.appShellMainProps,
|
|
1737
|
+
children: props.children ?? /* @__PURE__ */ jsx(NestedView, {})
|
|
1738
|
+
}),
|
|
1739
|
+
footerElement && /* @__PURE__ */ jsx(AppShell.Footer, {
|
|
1740
|
+
...props.appShellFooterProps,
|
|
1741
|
+
children: footerElement
|
|
1742
|
+
})
|
|
1743
|
+
]
|
|
1744
|
+
});
|
|
1745
|
+
};
|
|
1746
|
+
|
|
1747
|
+
//#endregion
|
|
1748
|
+
//#region ../../src/core/components/Text.tsx
|
|
1749
|
+
const INTENT_COLORS = {
|
|
1750
|
+
primary: "blue",
|
|
1751
|
+
info: "cyan",
|
|
1752
|
+
success: "green",
|
|
1753
|
+
warning: "yellow",
|
|
1754
|
+
danger: "red"
|
|
1755
|
+
};
|
|
1756
|
+
const Text = forwardRef((props, ref) => {
|
|
1757
|
+
const { intent, bold, italic, light, muted, small, uppercase, capitalize, center, monospace, title, ...rest } = props;
|
|
1758
|
+
if (intent) rest.c ??= INTENT_COLORS[intent];
|
|
1759
|
+
if (bold) rest.fw ??= 700;
|
|
1760
|
+
if (light) rest.fw ??= 300;
|
|
1761
|
+
if (italic) rest.fs ??= "italic";
|
|
1762
|
+
if (muted) rest.c ??= "dimmed";
|
|
1763
|
+
if (small) rest.size ??= "sm";
|
|
1764
|
+
if (uppercase) rest.tt ??= "uppercase";
|
|
1765
|
+
if (capitalize) rest.tt ??= "capitalize";
|
|
1766
|
+
if (center) rest.ta ??= "center";
|
|
1767
|
+
if (monospace) rest.ff ??= "monospace";
|
|
1768
|
+
if (title) rest.size ??= "xl";
|
|
1769
|
+
return /* @__PURE__ */ jsx(Text$1, {
|
|
1770
|
+
ref,
|
|
1771
|
+
...rest
|
|
1772
|
+
});
|
|
1773
|
+
});
|
|
1774
|
+
Text.displayName = "Text";
|
|
1775
|
+
|
|
1776
|
+
//#endregion
|
|
1777
|
+
//#region ../../src/core/form/utils/parseInput.ts
|
|
1778
|
+
const parseInput = (props, form) => {
|
|
1779
|
+
const disabled = false;
|
|
1780
|
+
const id = props.input.props.id;
|
|
1781
|
+
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);
|
|
1782
|
+
const description = props.description ?? ("description" in props.input.schema && typeof props.input.schema.description === "string" ? props.input.schema.description : void 0);
|
|
1783
|
+
const error = form.error && form.error instanceof TypeBoxError ? form.error.value.message : void 0;
|
|
1784
|
+
const icon = !props.icon ? getDefaultIcon({
|
|
1785
|
+
type: props.input.schema && "type" in props.input.schema ? String(props.input.schema.type) : void 0,
|
|
1786
|
+
format: props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0,
|
|
1787
|
+
name: props.input.props.name,
|
|
1788
|
+
isEnum: props.input.schema && "enum" in props.input.schema && Boolean(props.input.schema.enum),
|
|
1789
|
+
isArray: props.input.schema && "type" in props.input.schema && props.input.schema.type === "array"
|
|
1790
|
+
}) : isValidElement(props.icon) ? props.icon : createElement(props.icon, { size: ui.sizes.icon.md });
|
|
1791
|
+
const format = props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0;
|
|
1792
|
+
const required = props.input.required;
|
|
1793
|
+
const schema = props.input.schema;
|
|
1794
|
+
const inputProps = {
|
|
1795
|
+
label,
|
|
1796
|
+
description,
|
|
1797
|
+
error,
|
|
1798
|
+
required,
|
|
1799
|
+
disabled
|
|
1800
|
+
};
|
|
1801
|
+
if ("minLength" in schema && typeof schema.minLength === "number") inputProps.minLength = schema.minLength;
|
|
1802
|
+
if ("maxLength" in schema && typeof schema.maxLength === "number") inputProps.maxLength = schema.maxLength;
|
|
1803
|
+
if ("minimum" in schema && typeof schema.minimum === "number") inputProps.minimum = schema.minimum;
|
|
1804
|
+
if ("maximum" in schema && typeof schema.maximum === "number") inputProps.maximum = schema.maximum;
|
|
1805
|
+
return {
|
|
1806
|
+
id,
|
|
1807
|
+
icon,
|
|
1808
|
+
format,
|
|
1809
|
+
schema: props.input.schema,
|
|
1810
|
+
inputProps
|
|
1811
|
+
};
|
|
1812
|
+
};
|
|
1813
|
+
|
|
1814
|
+
//#endregion
|
|
1815
|
+
//#region ../../src/core/form/components/ControlArray.tsx
|
|
1816
|
+
/**
|
|
1817
|
+
* Custom hook to sync array items with form state.
|
|
1818
|
+
* Uses form events as the source of truth, eliminating dual-state issues.
|
|
1819
|
+
*/
|
|
1820
|
+
const useArrayItems = (input) => {
|
|
1821
|
+
const alepha = useAlepha();
|
|
1822
|
+
const keyCounter = useRef(0);
|
|
1823
|
+
const [items, setItemsState] = useState(() => {
|
|
1824
|
+
const defaultValue = input?.props?.defaultValue;
|
|
1825
|
+
if (Array.isArray(defaultValue)) return defaultValue.map((value) => ({
|
|
1826
|
+
key: keyCounter.current++,
|
|
1827
|
+
value
|
|
1828
|
+
}));
|
|
1829
|
+
return [];
|
|
1830
|
+
});
|
|
1831
|
+
const syncFromFormValue = useCallback((formValue) => {
|
|
1832
|
+
if (!Array.isArray(formValue)) {
|
|
1833
|
+
setItemsState([]);
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1836
|
+
setItemsState((prevItems) => {
|
|
1837
|
+
if (prevItems.length === formValue.length) {
|
|
1838
|
+
if (prevItems.every((item, i) => item.value === formValue[i])) return prevItems;
|
|
1839
|
+
}
|
|
1840
|
+
keyCounter.current = 0;
|
|
1841
|
+
return formValue.map((value) => ({
|
|
1842
|
+
key: keyCounter.current++,
|
|
1843
|
+
value
|
|
1844
|
+
}));
|
|
1845
|
+
});
|
|
1846
|
+
}, []);
|
|
1847
|
+
useEffect(() => {
|
|
1848
|
+
if (!input?.form) return;
|
|
1849
|
+
const formId = input.form.id;
|
|
1850
|
+
const fieldPath = input.path;
|
|
1851
|
+
const listeners = [alepha.events.on("form:reset", (event) => {
|
|
1852
|
+
if (event.id === formId) {
|
|
1853
|
+
const defaultValue = input.props?.defaultValue;
|
|
1854
|
+
keyCounter.current = 0;
|
|
1855
|
+
if (Array.isArray(defaultValue)) setItemsState(defaultValue.map((value) => ({
|
|
1856
|
+
key: keyCounter.current++,
|
|
1857
|
+
value
|
|
1858
|
+
})));
|
|
1859
|
+
else setItemsState([]);
|
|
1860
|
+
}
|
|
1861
|
+
}), alepha.events.on("form:change", (event) => {
|
|
1862
|
+
if (event.id === formId && event.path === fieldPath) syncFromFormValue(event.value);
|
|
1863
|
+
})];
|
|
1864
|
+
return () => {
|
|
1865
|
+
for (const unsub of listeners) unsub();
|
|
1866
|
+
};
|
|
1867
|
+
}, [
|
|
1868
|
+
alepha,
|
|
1869
|
+
input,
|
|
1870
|
+
syncFromFormValue
|
|
1871
|
+
]);
|
|
1872
|
+
return {
|
|
1873
|
+
items,
|
|
1874
|
+
setItems: useCallback((newItems) => {
|
|
1875
|
+
setItemsState(newItems);
|
|
1876
|
+
input?.set(newItems.map((item) => item.value));
|
|
1877
|
+
}, [input]),
|
|
1878
|
+
nextKey: useCallback(() => keyCounter.current++, [])
|
|
1879
|
+
};
|
|
1880
|
+
};
|
|
1427
1881
|
/**
|
|
1428
1882
|
* Creates a proper InputField for an array item that integrates with the form system.
|
|
1429
1883
|
* Uses array index for test IDs to ensure predictable, testable element identifiers.
|
|
@@ -1661,7 +2115,7 @@ const ControlArray = (props) => {
|
|
|
1661
2115
|
};
|
|
1662
2116
|
|
|
1663
2117
|
//#endregion
|
|
1664
|
-
//#region ../../src/core/components/
|
|
2118
|
+
//#region ../../src/core/form/components/ControlDate.tsx
|
|
1665
2119
|
/**
|
|
1666
2120
|
* ControlDate component for handling date, datetime, and time inputs.
|
|
1667
2121
|
*
|
|
@@ -1718,7 +2172,7 @@ const ControlDate = (props) => {
|
|
|
1718
2172
|
};
|
|
1719
2173
|
|
|
1720
2174
|
//#endregion
|
|
1721
|
-
//#region ../../src/core/components/
|
|
2175
|
+
//#region ../../src/core/form/components/ControlNumber.tsx
|
|
1722
2176
|
/**
|
|
1723
2177
|
*
|
|
1724
2178
|
*/
|
|
@@ -1776,7 +2230,7 @@ const ControlNumber = (props) => {
|
|
|
1776
2230
|
};
|
|
1777
2231
|
|
|
1778
2232
|
//#endregion
|
|
1779
|
-
//#region ../../src/core/components/
|
|
2233
|
+
//#region ../../src/core/form/components/ControlObject.tsx
|
|
1780
2234
|
/**
|
|
1781
2235
|
* ControlObject component for editing nested object schemas.
|
|
1782
2236
|
*
|
|
@@ -1853,125 +2307,7 @@ const ControlObject = (props) => {
|
|
|
1853
2307
|
};
|
|
1854
2308
|
|
|
1855
2309
|
//#endregion
|
|
1856
|
-
//#region ../../src/core/
|
|
1857
|
-
/**
|
|
1858
|
-
* Extract field information from a TypeBox schema for query building.
|
|
1859
|
-
* Supports nested objects and provides field metadata for autocomplete.
|
|
1860
|
-
*/
|
|
1861
|
-
function extractSchemaFields(schema, prefix = "") {
|
|
1862
|
-
const fields = [];
|
|
1863
|
-
if (!schema || typeof schema !== "object") return fields;
|
|
1864
|
-
const properties = "properties" in schema ? schema.properties : schema;
|
|
1865
|
-
if (!properties || typeof properties !== "object") return fields;
|
|
1866
|
-
for (const [key, value] of Object.entries(properties)) {
|
|
1867
|
-
if (typeof value !== "object" || value === null) continue;
|
|
1868
|
-
const fieldSchema = value;
|
|
1869
|
-
const path = prefix ? `${prefix}.${key}` : key;
|
|
1870
|
-
const format = "format" in fieldSchema ? fieldSchema.format : void 0;
|
|
1871
|
-
let displayType = "type" in fieldSchema ? fieldSchema.type : "object";
|
|
1872
|
-
if (format === "date-time") displayType = "datetime";
|
|
1873
|
-
else if (format === "date") displayType = "date";
|
|
1874
|
-
else if (format === "time") displayType = "time";
|
|
1875
|
-
else if (format === "duration") displayType = "duration";
|
|
1876
|
-
const field = {
|
|
1877
|
-
name: key,
|
|
1878
|
-
path,
|
|
1879
|
-
type: displayType,
|
|
1880
|
-
format,
|
|
1881
|
-
description: "description" in fieldSchema ? fieldSchema.description : void 0
|
|
1882
|
-
};
|
|
1883
|
-
if ("enum" in fieldSchema && fieldSchema.enum) {
|
|
1884
|
-
field.enum = fieldSchema.enum;
|
|
1885
|
-
field.type = "enum";
|
|
1886
|
-
}
|
|
1887
|
-
if ("type" in fieldSchema && fieldSchema.type === "object" && "properties" in fieldSchema && typeof fieldSchema.properties === "object") field.nested = extractSchemaFields(fieldSchema.properties, path);
|
|
1888
|
-
fields.push(field);
|
|
1889
|
-
if (field.nested) fields.push(...field.nested);
|
|
1890
|
-
}
|
|
1891
|
-
return fields;
|
|
1892
|
-
}
|
|
1893
|
-
/**
|
|
1894
|
-
* Get suggested operators based on field type
|
|
1895
|
-
*/
|
|
1896
|
-
function getOperatorsForField(field) {
|
|
1897
|
-
const allOperators = ["=", "!="];
|
|
1898
|
-
if (field.enum) return [...allOperators, "in"];
|
|
1899
|
-
switch (field.type) {
|
|
1900
|
-
case "string":
|
|
1901
|
-
case "text": return [...allOperators, "null"];
|
|
1902
|
-
case "number":
|
|
1903
|
-
case "integer": return [
|
|
1904
|
-
...allOperators,
|
|
1905
|
-
">",
|
|
1906
|
-
">=",
|
|
1907
|
-
"<",
|
|
1908
|
-
"<="
|
|
1909
|
-
];
|
|
1910
|
-
case "boolean": return allOperators;
|
|
1911
|
-
case "datetime":
|
|
1912
|
-
case "date": return [
|
|
1913
|
-
...allOperators,
|
|
1914
|
-
">",
|
|
1915
|
-
">=",
|
|
1916
|
-
"<",
|
|
1917
|
-
"<="
|
|
1918
|
-
];
|
|
1919
|
-
default: return [...allOperators, "null"];
|
|
1920
|
-
}
|
|
1921
|
-
}
|
|
1922
|
-
/**
|
|
1923
|
-
* Get operator symbol and description
|
|
1924
|
-
*/
|
|
1925
|
-
const OPERATOR_INFO = {
|
|
1926
|
-
eq: {
|
|
1927
|
-
symbol: "=",
|
|
1928
|
-
label: "equals",
|
|
1929
|
-
example: "name=John"
|
|
1930
|
-
},
|
|
1931
|
-
ne: {
|
|
1932
|
-
symbol: "!=",
|
|
1933
|
-
label: "not equals",
|
|
1934
|
-
example: "status!=archived"
|
|
1935
|
-
},
|
|
1936
|
-
gt: {
|
|
1937
|
-
symbol: ">",
|
|
1938
|
-
label: "greater than",
|
|
1939
|
-
example: "age>18"
|
|
1940
|
-
},
|
|
1941
|
-
gte: {
|
|
1942
|
-
symbol: ">=",
|
|
1943
|
-
label: "greater or equal",
|
|
1944
|
-
example: "age>=18"
|
|
1945
|
-
},
|
|
1946
|
-
lt: {
|
|
1947
|
-
symbol: "<",
|
|
1948
|
-
label: "less than",
|
|
1949
|
-
example: "age<65"
|
|
1950
|
-
},
|
|
1951
|
-
lte: {
|
|
1952
|
-
symbol: "<=",
|
|
1953
|
-
label: "less or equal",
|
|
1954
|
-
example: "age<=65"
|
|
1955
|
-
},
|
|
1956
|
-
null: {
|
|
1957
|
-
symbol: "=null",
|
|
1958
|
-
label: "is null",
|
|
1959
|
-
example: "deletedAt=null"
|
|
1960
|
-
},
|
|
1961
|
-
notNull: {
|
|
1962
|
-
symbol: "!=null",
|
|
1963
|
-
label: "is not null",
|
|
1964
|
-
example: "email!=null"
|
|
1965
|
-
},
|
|
1966
|
-
in: {
|
|
1967
|
-
symbol: "[...]",
|
|
1968
|
-
label: "in array",
|
|
1969
|
-
example: "status=[active,pending]"
|
|
1970
|
-
}
|
|
1971
|
-
};
|
|
1972
|
-
|
|
1973
|
-
//#endregion
|
|
1974
|
-
//#region ../../src/core/components/form/ControlQueryBuilder.tsx
|
|
2310
|
+
//#region ../../src/core/form/components/ControlQueryBuilder.tsx
|
|
1975
2311
|
/**
|
|
1976
2312
|
* Query builder with text input and help popover.
|
|
1977
2313
|
* Generates query strings for parseQueryString syntax.
|
|
@@ -2222,7 +2558,7 @@ function QueryHelp({ fields, onInsert }) {
|
|
|
2222
2558
|
}
|
|
2223
2559
|
|
|
2224
2560
|
//#endregion
|
|
2225
|
-
//#region ../../src/core/components/
|
|
2561
|
+
//#region ../../src/core/form/components/ControlSelect.tsx
|
|
2226
2562
|
/**
|
|
2227
2563
|
* ControlSelect component for handling Select, MultiSelect, and TagsInput.
|
|
2228
2564
|
*
|
|
@@ -2318,6 +2654,7 @@ const ControlSelect = (props) => {
|
|
|
2318
2654
|
size: props.size,
|
|
2319
2655
|
id,
|
|
2320
2656
|
leftSection: icon,
|
|
2657
|
+
rightSection: null,
|
|
2321
2658
|
data,
|
|
2322
2659
|
...props.input.props,
|
|
2323
2660
|
...selectProps
|
|
@@ -2325,7 +2662,7 @@ const ControlSelect = (props) => {
|
|
|
2325
2662
|
};
|
|
2326
2663
|
|
|
2327
2664
|
//#endregion
|
|
2328
|
-
//#region ../../src/core/components/
|
|
2665
|
+
//#region ../../src/core/form/components/Control.tsx
|
|
2329
2666
|
/**
|
|
2330
2667
|
* Generic form control that renders the appropriate input based on the schema and props.
|
|
2331
2668
|
*
|
|
@@ -2445,27 +2782,46 @@ const Control = (_props) => {
|
|
|
2445
2782
|
if (props.segmented) opts.segmented ??= {};
|
|
2446
2783
|
return /* @__PURE__ */ jsx(ControlSelect, {
|
|
2447
2784
|
size: props.size,
|
|
2448
|
-
input: props.input,
|
|
2785
|
+
input: props.input,
|
|
2786
|
+
title: props.title,
|
|
2787
|
+
description: props.description,
|
|
2788
|
+
icon,
|
|
2789
|
+
...opts
|
|
2790
|
+
});
|
|
2791
|
+
}
|
|
2792
|
+
if (props.input.schema && "type" in props.input.schema && props.input.schema.type === "boolean") {
|
|
2793
|
+
if (props.switch) {
|
|
2794
|
+
const switchProps = typeof props.switch === "object" ? props.switch : {};
|
|
2795
|
+
return /* @__PURE__ */ jsx(Switch, {
|
|
2796
|
+
...inputProps,
|
|
2797
|
+
size: props.size,
|
|
2798
|
+
id,
|
|
2799
|
+
color: "blue",
|
|
2800
|
+
defaultChecked: props.input.props.defaultValue,
|
|
2801
|
+
onChange: (event) => {
|
|
2802
|
+
props.input.set(event.currentTarget.checked);
|
|
2803
|
+
},
|
|
2804
|
+
...switchProps
|
|
2805
|
+
});
|
|
2806
|
+
}
|
|
2807
|
+
const opts = {
|
|
2808
|
+
input: props.input,
|
|
2809
|
+
select: { data: [{
|
|
2810
|
+
value: "true",
|
|
2811
|
+
label: "Yes"
|
|
2812
|
+
}, {
|
|
2813
|
+
value: "false",
|
|
2814
|
+
label: "No"
|
|
2815
|
+
}] }
|
|
2816
|
+
};
|
|
2817
|
+
return /* @__PURE__ */ jsx(ControlSelect, {
|
|
2818
|
+
size: props.size,
|
|
2449
2819
|
title: props.title,
|
|
2450
2820
|
description: props.description,
|
|
2451
2821
|
icon,
|
|
2452
2822
|
...opts
|
|
2453
2823
|
});
|
|
2454
2824
|
}
|
|
2455
|
-
if (props.input.schema && "type" in props.input.schema && props.input.schema.type === "boolean") {
|
|
2456
|
-
const switchProps = typeof props.switch === "object" ? props.switch : {};
|
|
2457
|
-
return /* @__PURE__ */ jsx(Switch, {
|
|
2458
|
-
...inputProps,
|
|
2459
|
-
size: props.size,
|
|
2460
|
-
id,
|
|
2461
|
-
color: "blue",
|
|
2462
|
-
defaultChecked: props.input.props.defaultValue,
|
|
2463
|
-
onChange: (event) => {
|
|
2464
|
-
props.input.set(event.currentTarget.checked);
|
|
2465
|
-
},
|
|
2466
|
-
...switchProps
|
|
2467
|
-
});
|
|
2468
|
-
}
|
|
2469
2825
|
if (props.password || props.input.props.name?.includes("password")) {
|
|
2470
2826
|
const passwordInputProps = typeof props.password === "object" ? props.password : {};
|
|
2471
2827
|
return /* @__PURE__ */ jsx(PasswordInput, {
|
|
@@ -2505,788 +2861,539 @@ const Control = (_props) => {
|
|
|
2505
2861
|
case "url":
|
|
2506
2862
|
case "uri": return "url";
|
|
2507
2863
|
case "tel":
|
|
2508
|
-
case "phone": return "tel";
|
|
2509
|
-
default: return;
|
|
2510
|
-
}
|
|
2511
|
-
};
|
|
2512
|
-
return /* @__PURE__ */ jsx(TextInput, {
|
|
2513
|
-
...inputProps,
|
|
2514
|
-
size: props.size,
|
|
2515
|
-
id,
|
|
2516
|
-
leftSection: icon,
|
|
2517
|
-
type: getInputType(),
|
|
2518
|
-
...props.input.props,
|
|
2519
|
-
...textInputProps,
|
|
2520
|
-
inputWrapperOrder: [
|
|
2521
|
-
"label",
|
|
2522
|
-
"input",
|
|
2523
|
-
"description",
|
|
2524
|
-
"error"
|
|
2525
|
-
]
|
|
2526
|
-
});
|
|
2527
|
-
};
|
|
2528
|
-
|
|
2529
|
-
//#endregion
|
|
2530
|
-
//#region ../../src/core/components/form/TypeForm.tsx
|
|
2531
|
-
/**
|
|
2532
|
-
* TypeForm component that automatically renders all form inputs based on schema.
|
|
2533
|
-
* Uses the Control component to render individual fields and Mantine Grid for responsive layout.
|
|
2534
|
-
*
|
|
2535
|
-
* Supports all field types including:
|
|
2536
|
-
* - Primitive types (string, number, boolean, etc.)
|
|
2537
|
-
* - Enum types (rendered as Select)
|
|
2538
|
-
* - Arrays of primitives (rendered as MultiSelect/TagsInput)
|
|
2539
|
-
* - Arrays of objects (rendered as ControlArray)
|
|
2540
|
-
* - Nested objects (rendered as ControlObject)
|
|
2541
|
-
*
|
|
2542
|
-
* @example
|
|
2543
|
-
* ```tsx
|
|
2544
|
-
* import { t } from "alepha";
|
|
2545
|
-
* import { useForm } from "alepha/react/form";
|
|
2546
|
-
* import { TypeForm } from "@alepha/ui";
|
|
2547
|
-
*
|
|
2548
|
-
* const form = useForm({
|
|
2549
|
-
* schema: t.object({
|
|
2550
|
-
* username: t.text(),
|
|
2551
|
-
* email: t.text(),
|
|
2552
|
-
* age: t.integer(),
|
|
2553
|
-
* subscribe: t.boolean(),
|
|
2554
|
-
* address: t.object({
|
|
2555
|
-
* street: t.text(),
|
|
2556
|
-
* city: t.text(),
|
|
2557
|
-
* }),
|
|
2558
|
-
* tags: t.array(t.text()),
|
|
2559
|
-
* contacts: t.array(t.object({
|
|
2560
|
-
* name: t.text(),
|
|
2561
|
-
* email: t.text(),
|
|
2562
|
-
* })),
|
|
2563
|
-
* }),
|
|
2564
|
-
* handler: (values) => {
|
|
2565
|
-
* console.log(values);
|
|
2566
|
-
* },
|
|
2567
|
-
* });
|
|
2568
|
-
*
|
|
2569
|
-
* return <TypeForm form={form} columns={2} />;
|
|
2570
|
-
* ```
|
|
2571
|
-
*/
|
|
2572
|
-
const TypeForm = (props) => {
|
|
2573
|
-
const { form, columns = 3, children, controlProps, fieldControlProps, skipFormElement = false, skipSubmitButton = false, submitButtonProps, fill = true, size } = props;
|
|
2574
|
-
const schema = props.schema || form.options.schema;
|
|
2575
|
-
if (!schema?.properties) return null;
|
|
2576
|
-
const supportedFields = Object.keys(schema.properties);
|
|
2577
|
-
const colSpan = typeof columns === "number" ? {
|
|
2578
|
-
xs: 12,
|
|
2579
|
-
sm: 6,
|
|
2580
|
-
lg: 12 / columns
|
|
2581
|
-
} : {
|
|
2582
|
-
base: columns.base ? 12 / columns.base : void 0,
|
|
2583
|
-
xs: columns.xs ? 12 / columns.xs : 12,
|
|
2584
|
-
sm: columns.sm ? 12 / columns.sm : 6,
|
|
2585
|
-
md: columns.md ? 12 / columns.md : void 0,
|
|
2586
|
-
lg: columns.lg ? 12 / columns.lg : 4,
|
|
2587
|
-
xl: columns.xl ? 12 / columns.xl : void 0
|
|
2588
|
-
};
|
|
2589
|
-
const renderFields = () => {
|
|
2590
|
-
if (children) return /* @__PURE__ */ jsx(Fragment$1, { children: children(form.input) });
|
|
2591
|
-
return /* @__PURE__ */ jsx(Grid, { children: supportedFields.map((fieldName) => {
|
|
2592
|
-
const field = form.input[fieldName];
|
|
2593
|
-
const fieldSchema = schema.properties[fieldName];
|
|
2594
|
-
if (!field || !fieldSchema) return null;
|
|
2595
|
-
const isObject = fieldSchema && "type" in fieldSchema && fieldSchema.type === "object";
|
|
2596
|
-
const isArrayOfObjects = fieldSchema && "type" in fieldSchema && fieldSchema.type === "array" && "items" in fieldSchema && fieldSchema.items && "properties" in fieldSchema.items;
|
|
2597
|
-
const span = isObject || isArrayOfObjects ? 12 : colSpan;
|
|
2598
|
-
const mergedControlProps = {
|
|
2599
|
-
...controlProps,
|
|
2600
|
-
...fieldControlProps?.[fieldName]
|
|
2601
|
-
};
|
|
2602
|
-
if (size) mergedControlProps.size = size;
|
|
2603
|
-
return /* @__PURE__ */ jsx(Grid.Col, {
|
|
2604
|
-
span,
|
|
2605
|
-
children: /* @__PURE__ */ jsx(Control, {
|
|
2606
|
-
input: field,
|
|
2607
|
-
...mergedControlProps
|
|
2608
|
-
})
|
|
2609
|
-
}, fieldName);
|
|
2610
|
-
}) });
|
|
2611
|
-
};
|
|
2612
|
-
const content = /* @__PURE__ */ jsxs(Flex$1, {
|
|
2613
|
-
direction: "column",
|
|
2614
|
-
gap: "sm",
|
|
2615
|
-
flex: fill ? 1 : void 0,
|
|
2616
|
-
...props.flexProps,
|
|
2617
|
-
children: [/* @__PURE__ */ jsx(Flex$1, {
|
|
2618
|
-
direction: "column",
|
|
2619
|
-
gap: "sm",
|
|
2620
|
-
flex: 1,
|
|
2621
|
-
children: renderFields()
|
|
2622
|
-
}), !skipSubmitButton && /* @__PURE__ */ jsx(Card, {
|
|
2623
|
-
w: "100%",
|
|
2624
|
-
withBorder: true,
|
|
2625
|
-
children: /* @__PURE__ */ jsxs(Flex$1, {
|
|
2626
|
-
gap: "sm",
|
|
2627
|
-
flex: 1,
|
|
2628
|
-
children: [
|
|
2629
|
-
/* @__PURE__ */ jsx(Flex$1, {}),
|
|
2630
|
-
/* @__PURE__ */ jsx(Flex$1, { flex: 1 }),
|
|
2631
|
-
/* @__PURE__ */ jsxs(Flex$1, {
|
|
2632
|
-
gap: "sm",
|
|
2633
|
-
children: [/* @__PURE__ */ jsx(ActionButton, {
|
|
2634
|
-
variant: "subtle",
|
|
2635
|
-
type: "reset",
|
|
2636
|
-
children: "Reset"
|
|
2637
|
-
}), /* @__PURE__ */ jsx(ActionButton, {
|
|
2638
|
-
intent: "primary",
|
|
2639
|
-
form,
|
|
2640
|
-
...submitButtonProps,
|
|
2641
|
-
children: submitButtonProps?.children ?? "Submit"
|
|
2642
|
-
})]
|
|
2643
|
-
})
|
|
2644
|
-
]
|
|
2645
|
-
})
|
|
2646
|
-
})]
|
|
2647
|
-
});
|
|
2648
|
-
if (skipFormElement) return content;
|
|
2649
|
-
return /* @__PURE__ */ jsx(Flex$1, {
|
|
2650
|
-
component: "form",
|
|
2651
|
-
flex: fill ? 1 : void 0,
|
|
2652
|
-
...form.props,
|
|
2653
|
-
...props.flexProps,
|
|
2654
|
-
children: content
|
|
2655
|
-
});
|
|
2656
|
-
};
|
|
2657
|
-
|
|
2658
|
-
//#endregion
|
|
2659
|
-
//#region ../../src/core/components/layout/AppBar.tsx
|
|
2660
|
-
const AppBar = (props) => {
|
|
2661
|
-
const { items = [] } = props;
|
|
2662
|
-
const router = useRouter();
|
|
2663
|
-
const renderItem = (item, index) => {
|
|
2664
|
-
if (item.can && !item.can()) return null;
|
|
2665
|
-
if ("type" in item) {
|
|
2666
|
-
if (item.type === "burger") return /* @__PURE__ */ jsx(BurgerButton, {}, index);
|
|
2667
|
-
if (item.type === "dark") return /* @__PURE__ */ jsx(DarkModeButton, { ...item.props }, index);
|
|
2668
|
-
if (item.type === "search") return /* @__PURE__ */ jsx(OmnibarButton, { ...item.props }, index);
|
|
2669
|
-
if (item.type === "lang") return /* @__PURE__ */ jsx(LanguageButton, { ...item.props }, index);
|
|
2670
|
-
if (item.type === "spacer") return /* @__PURE__ */ jsx(Flex$1, { w: 16 }, index);
|
|
2671
|
-
if (item.type === "divider") return /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }, index);
|
|
2672
|
-
if (item.type === "logo") return renderLogo(item, index);
|
|
2673
|
-
if (item.type === "back") return renderBack(item, index);
|
|
2674
|
-
}
|
|
2675
|
-
if ("element" in item) return item.element;
|
|
2676
|
-
return null;
|
|
2677
|
-
};
|
|
2678
|
-
const renderLogo = (item, index) => {
|
|
2679
|
-
const { src, text, icon, href, height = 32, width, fontWeight = 700, fontSize = "lg" } = item.props ?? {};
|
|
2680
|
-
const logoContent = src ? /* @__PURE__ */ jsx(Image, {
|
|
2681
|
-
src,
|
|
2682
|
-
h: height,
|
|
2683
|
-
w: width,
|
|
2684
|
-
fit: "contain"
|
|
2685
|
-
}) : icon ? typeof icon === "function" ? /* @__PURE__ */ jsx(icon, {}) : icon : text ? /* @__PURE__ */ jsx(Text$1, {
|
|
2686
|
-
fw: fontWeight,
|
|
2687
|
-
size: fontSize,
|
|
2688
|
-
children: text
|
|
2689
|
-
}) : null;
|
|
2690
|
-
if (href) return /* @__PURE__ */ jsx(Anchor, {
|
|
2691
|
-
component: Link,
|
|
2692
|
-
href,
|
|
2693
|
-
underline: "never",
|
|
2694
|
-
c: "inherit",
|
|
2695
|
-
children: logoContent
|
|
2696
|
-
}, index);
|
|
2697
|
-
return /* @__PURE__ */ jsx(Flex$1, { children: logoContent }, index);
|
|
2698
|
-
};
|
|
2699
|
-
const renderBack = (item, index) => {
|
|
2700
|
-
const { label = "Back", iconOnly = true, href, icon } = item.props ?? {};
|
|
2701
|
-
const renderIcon = () => {
|
|
2702
|
-
if (!icon) return /* @__PURE__ */ jsx(IconArrowLeft, { size: 18 });
|
|
2703
|
-
if (typeof icon === "function") return /* @__PURE__ */ jsx(icon, { size: 18 });
|
|
2704
|
-
return icon;
|
|
2705
|
-
};
|
|
2706
|
-
const iconElement = renderIcon();
|
|
2707
|
-
const handleClick = () => {
|
|
2708
|
-
if (href) router.push(href);
|
|
2709
|
-
else router.back();
|
|
2710
|
-
};
|
|
2711
|
-
if (iconOnly) return /* @__PURE__ */ jsx(ActionButton, {
|
|
2712
|
-
icon: iconElement,
|
|
2713
|
-
variant: "subtle",
|
|
2714
|
-
color: "gray",
|
|
2715
|
-
onClick: handleClick,
|
|
2716
|
-
tooltip: {
|
|
2717
|
-
label,
|
|
2718
|
-
position: "bottom"
|
|
2719
|
-
}
|
|
2720
|
-
}, index);
|
|
2721
|
-
return /* @__PURE__ */ jsx(ActionButton, {
|
|
2722
|
-
leftSection: iconElement,
|
|
2723
|
-
variant: "subtle",
|
|
2724
|
-
color: "gray",
|
|
2725
|
-
onClick: handleClick,
|
|
2726
|
-
children: label
|
|
2727
|
-
}, index);
|
|
2728
|
-
};
|
|
2729
|
-
const leftItems = items.filter((item) => item.position === "left");
|
|
2730
|
-
const centerItems = items.filter((item) => item.position === "center");
|
|
2731
|
-
const rightItems = items.filter((item) => item.position === "right");
|
|
2732
|
-
const content = /* @__PURE__ */ jsxs(Flex$1, {
|
|
2733
|
-
h: "100%",
|
|
2734
|
-
align: "center",
|
|
2735
|
-
px: props.container ? 0 : "md",
|
|
2736
|
-
justify: "space-between",
|
|
2737
|
-
...props.flexProps,
|
|
2738
|
-
children: [
|
|
2739
|
-
/* @__PURE__ */ jsx(Flex$1, {
|
|
2740
|
-
flex: 1,
|
|
2741
|
-
children: leftItems.map((item, index) => /* @__PURE__ */ jsx(Flex$1, {
|
|
2742
|
-
ml: index === 0 ? 0 : "md",
|
|
2743
|
-
align: "center",
|
|
2744
|
-
children: renderItem(item, index)
|
|
2745
|
-
}, index))
|
|
2746
|
-
}),
|
|
2747
|
-
/* @__PURE__ */ jsx(Flex$1, { children: centerItems.map((item, index) => /* @__PURE__ */ jsx(Flex$1, {
|
|
2748
|
-
mx: "md",
|
|
2749
|
-
align: "center",
|
|
2750
|
-
children: renderItem(item, index)
|
|
2751
|
-
}, index)) }),
|
|
2752
|
-
/* @__PURE__ */ jsx(Flex$1, {
|
|
2753
|
-
flex: 1,
|
|
2754
|
-
align: "center",
|
|
2755
|
-
justify: "end",
|
|
2756
|
-
children: rightItems.map((item, index) => /* @__PURE__ */ jsx(Flex$1, {
|
|
2757
|
-
ml: index === 0 ? 0 : "md",
|
|
2758
|
-
align: "center",
|
|
2759
|
-
children: renderItem(item, index)
|
|
2760
|
-
}, index))
|
|
2761
|
-
})
|
|
2864
|
+
case "phone": return "tel";
|
|
2865
|
+
default: return;
|
|
2866
|
+
}
|
|
2867
|
+
};
|
|
2868
|
+
return /* @__PURE__ */ jsx(TextInput, {
|
|
2869
|
+
...inputProps,
|
|
2870
|
+
size: props.size,
|
|
2871
|
+
id,
|
|
2872
|
+
leftSection: icon,
|
|
2873
|
+
type: getInputType(),
|
|
2874
|
+
...props.input.props,
|
|
2875
|
+
...textInputProps,
|
|
2876
|
+
inputWrapperOrder: [
|
|
2877
|
+
"label",
|
|
2878
|
+
"input",
|
|
2879
|
+
"description",
|
|
2880
|
+
"error"
|
|
2762
2881
|
]
|
|
2763
2882
|
});
|
|
2764
|
-
if (props.container) return /* @__PURE__ */ jsx(Container, {
|
|
2765
|
-
h: "100%",
|
|
2766
|
-
...typeof props.container === "boolean" ? {} : props.container,
|
|
2767
|
-
children: content
|
|
2768
|
-
});
|
|
2769
|
-
return content;
|
|
2770
2883
|
};
|
|
2771
2884
|
|
|
2772
2885
|
//#endregion
|
|
2773
|
-
//#region ../../src/core/components/
|
|
2886
|
+
//#region ../../src/core/form/components/TypeForm.tsx
|
|
2774
2887
|
/**
|
|
2775
|
-
*
|
|
2776
|
-
*
|
|
2888
|
+
* TypeForm component that automatically renders all form inputs based on schema.
|
|
2889
|
+
* Uses the Control component to render individual fields and Mantine Grid for responsive layout.
|
|
2777
2890
|
*
|
|
2778
|
-
*
|
|
2779
|
-
*
|
|
2891
|
+
* Supports all field types including:
|
|
2892
|
+
* - Primitive types (string, number, boolean, etc.)
|
|
2893
|
+
* - Enum types (rendered as Select)
|
|
2894
|
+
* - Arrays of primitives (rendered as MultiSelect/TagsInput)
|
|
2895
|
+
* - Arrays of objects (rendered as ControlArray)
|
|
2896
|
+
* - Nested objects (rendered as ControlObject)
|
|
2897
|
+
*
|
|
2898
|
+
* @example
|
|
2899
|
+
* ```tsx
|
|
2900
|
+
* import { t } from "alepha";
|
|
2901
|
+
* import { useForm } from "alepha/react/form";
|
|
2902
|
+
* import { TypeForm } from "@alepha/ui";
|
|
2903
|
+
*
|
|
2904
|
+
* const form = useForm({
|
|
2905
|
+
* schema: t.object({
|
|
2906
|
+
* username: t.text(),
|
|
2907
|
+
* email: t.text(),
|
|
2908
|
+
* age: t.integer(),
|
|
2909
|
+
* subscribe: t.boolean(),
|
|
2910
|
+
* address: t.object({
|
|
2911
|
+
* street: t.text(),
|
|
2912
|
+
* city: t.text(),
|
|
2913
|
+
* }),
|
|
2914
|
+
* tags: t.array(t.text()),
|
|
2915
|
+
* contacts: t.array(t.object({
|
|
2916
|
+
* name: t.text(),
|
|
2917
|
+
* email: t.text(),
|
|
2918
|
+
* })),
|
|
2919
|
+
* }),
|
|
2920
|
+
* handler: (values) => {
|
|
2921
|
+
* console.log(values);
|
|
2922
|
+
* },
|
|
2923
|
+
* });
|
|
2924
|
+
*
|
|
2925
|
+
* return <TypeForm form={form} columns={2} />;
|
|
2926
|
+
* ```
|
|
2780
2927
|
*/
|
|
2781
|
-
const
|
|
2782
|
-
const
|
|
2783
|
-
const
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
href
|
|
2798
|
-
});
|
|
2799
|
-
}
|
|
2800
|
-
if (crumbs.length === 0) return null;
|
|
2801
|
-
const sep = separator ?? /* @__PURE__ */ jsx(IconChevronRight, {
|
|
2802
|
-
size: 12,
|
|
2803
|
-
color: "#9ca3af"
|
|
2804
|
-
});
|
|
2805
|
-
return /* @__PURE__ */ jsx(Flex$1, {
|
|
2806
|
-
gap: 4,
|
|
2807
|
-
...groupProps,
|
|
2808
|
-
children: crumbs.map((crumb, i) => /* @__PURE__ */ jsxs(Flex$1, {
|
|
2809
|
-
gap: 4,
|
|
2810
|
-
children: [i > 0 && sep, i < crumbs.length - 1 ? /* @__PURE__ */ jsx(Anchor, {
|
|
2811
|
-
component: Link,
|
|
2812
|
-
href: crumb.href,
|
|
2813
|
-
size,
|
|
2814
|
-
c: "dimmed",
|
|
2815
|
-
children: crumb.label
|
|
2816
|
-
}) : /* @__PURE__ */ jsx(Text$1, {
|
|
2817
|
-
size,
|
|
2818
|
-
fw: 500,
|
|
2819
|
-
children: crumb.label
|
|
2820
|
-
})]
|
|
2821
|
-
}, crumb.href))
|
|
2822
|
-
});
|
|
2823
|
-
};
|
|
2824
|
-
|
|
2825
|
-
//#endregion
|
|
2826
|
-
//#region ../../src/core/components/layout/Sidebar.tsx
|
|
2827
|
-
const Sidebar = (props) => {
|
|
2828
|
-
const router = useRouter();
|
|
2829
|
-
const { onItemClick } = props;
|
|
2830
|
-
const divider = (key, fill) => {
|
|
2831
|
-
return /* @__PURE__ */ jsx(Flex$1, {
|
|
2832
|
-
h: 1,
|
|
2833
|
-
bg: "var(--mantine-color-default-border)",
|
|
2834
|
-
my: "xs",
|
|
2835
|
-
mx: fill ? "calc(-1 * var(--mantine-spacing-md))" : props.collapsed ? 0 : "sm"
|
|
2836
|
-
}, key);
|
|
2837
|
-
};
|
|
2838
|
-
const renderNode = (item, key) => {
|
|
2839
|
-
if ("type" in item) {
|
|
2840
|
-
if (item.type === "spacer") {
|
|
2841
|
-
if (props.collapsed) return null;
|
|
2842
|
-
return /* @__PURE__ */ jsx(Flex$1, { h: 16 }, key);
|
|
2843
|
-
}
|
|
2844
|
-
if (item.type === "divider") return divider(key, item.fill);
|
|
2845
|
-
if (item.type === "search") return /* @__PURE__ */ jsx(Flex$1, {
|
|
2846
|
-
mb: "xs",
|
|
2847
|
-
children: /* @__PURE__ */ jsx(OmnibarButton, { collapsed: props.collapsed })
|
|
2848
|
-
}, key);
|
|
2849
|
-
if (item.type === "toggle") return /* @__PURE__ */ jsx(ToggleSidebarButton, {}, key);
|
|
2850
|
-
if (item.type === "section") {
|
|
2851
|
-
if (item.children && item.children.length > 0) {
|
|
2852
|
-
if (!item.children.some((child) => !("can" in child) || !child.can || child.can())) return null;
|
|
2853
|
-
}
|
|
2854
|
-
if (props.collapsed) return /* @__PURE__ */ jsxs(Fragment, { children: [divider(`${key}-d`), item.children?.map((child, index) => renderNode(child, `s${key}-${index}`))] }, key);
|
|
2855
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Flex$1, {
|
|
2856
|
-
mt: "md",
|
|
2857
|
-
align: "center",
|
|
2858
|
-
gap: "xs",
|
|
2859
|
-
children: [renderIcon(item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Text$1, {
|
|
2860
|
-
size: "xs",
|
|
2861
|
-
c: "dimmed",
|
|
2862
|
-
tt: "uppercase",
|
|
2863
|
-
fw: "bold",
|
|
2864
|
-
children: item.label
|
|
2865
|
-
})]
|
|
2866
|
-
}), item.children?.map((child, index) => renderNode(child, `s${key}-${index}`))] }, key);
|
|
2867
|
-
}
|
|
2868
|
-
}
|
|
2869
|
-
if ("element" in item) return /* @__PURE__ */ jsx(Fragment, { children: item.element }, key);
|
|
2870
|
-
if (item.can && !item.can()) return null;
|
|
2871
|
-
if (item.children && item.children.length > 0) {
|
|
2872
|
-
if (!item.children.some((child) => !child.can || child.can())) return null;
|
|
2873
|
-
}
|
|
2874
|
-
if (props.collapsed) return /* @__PURE__ */ jsx(SidebarCollapsedItem, {
|
|
2875
|
-
item,
|
|
2876
|
-
level: 0,
|
|
2877
|
-
onItemClick,
|
|
2878
|
-
theme: props.theme ?? {}
|
|
2879
|
-
}, key);
|
|
2880
|
-
return /* @__PURE__ */ jsx(SidebarItem, {
|
|
2881
|
-
item,
|
|
2882
|
-
level: 0,
|
|
2883
|
-
onItemClick,
|
|
2884
|
-
theme: props.theme ?? {}
|
|
2885
|
-
}, key);
|
|
2886
|
-
};
|
|
2887
|
-
const getSidebarNodes = () => {
|
|
2888
|
-
if (props.items) return props.items;
|
|
2889
|
-
if (props.autoPopulateMenu) {
|
|
2890
|
-
const items = router.concretePages.filter((page) => !page.can || page.can()).map((page) => ({
|
|
2891
|
-
label: page.label ?? page.name,
|
|
2892
|
-
icon: renderIcon(page.icon),
|
|
2893
|
-
href: router.path(page.name)
|
|
2894
|
-
}));
|
|
2895
|
-
if (typeof props.autoPopulateMenu === "object" && props.autoPopulateMenu.startsWith) {
|
|
2896
|
-
const startsWith = props.autoPopulateMenu.startsWith;
|
|
2897
|
-
return items.filter((item) => item.href?.startsWith(startsWith));
|
|
2898
|
-
}
|
|
2899
|
-
return items;
|
|
2900
|
-
}
|
|
2901
|
-
return [];
|
|
2928
|
+
const TypeForm = (props) => {
|
|
2929
|
+
const { form, columns = 3, children, controlProps, fieldControlProps, skipFormElement = false, skipSubmitButton = false, submitButtonProps, fill = true, size } = props;
|
|
2930
|
+
const schema = props.schema || form.options.schema;
|
|
2931
|
+
if (!schema?.properties) return null;
|
|
2932
|
+
const supportedFields = Object.keys(schema.properties);
|
|
2933
|
+
const colSpan = typeof columns === "number" ? {
|
|
2934
|
+
xs: 12,
|
|
2935
|
+
sm: 6,
|
|
2936
|
+
lg: 12 / columns
|
|
2937
|
+
} : {
|
|
2938
|
+
base: columns.base ? 12 / columns.base : void 0,
|
|
2939
|
+
xs: columns.xs ? 12 / columns.xs : 12,
|
|
2940
|
+
sm: columns.sm ? 12 / columns.sm : 6,
|
|
2941
|
+
md: columns.md ? 12 / columns.md : void 0,
|
|
2942
|
+
lg: columns.lg ? 12 / columns.lg : 4,
|
|
2943
|
+
xl: columns.xl ? 12 / columns.xl : void 0
|
|
2902
2944
|
};
|
|
2903
|
-
const
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
children: menu.filter((it) => !it.position).map((item, index) => renderNode(item, index))
|
|
2926
|
-
}),
|
|
2927
|
-
/* @__PURE__ */ jsx(Flex$1, {
|
|
2928
|
-
gap,
|
|
2929
|
-
px: padding,
|
|
2930
|
-
direction: "column",
|
|
2931
|
-
children: menu.filter((it) => it.position === "bottom").map((item, index) => renderNode(item, index))
|
|
2932
|
-
})
|
|
2933
|
-
]
|
|
2934
|
-
});
|
|
2935
|
-
};
|
|
2936
|
-
const SidebarItem = (props) => {
|
|
2937
|
-
const { item, level } = props;
|
|
2938
|
-
const maxLevel = 2;
|
|
2939
|
-
const router = useRouter();
|
|
2940
|
-
const isActive = useCallback((item) => {
|
|
2941
|
-
if (!item.children) return false;
|
|
2942
|
-
for (const child of item.children) {
|
|
2943
|
-
if (child.href) {
|
|
2944
|
-
if (router.isActive(child.href)) return true;
|
|
2945
|
-
}
|
|
2946
|
-
if (isActive(child)) return true;
|
|
2947
|
-
}
|
|
2948
|
-
return false;
|
|
2949
|
-
}, []);
|
|
2950
|
-
const [isOpen, setIsOpen] = useState(isActive(item));
|
|
2951
|
-
useEvents({ "react:transition:end": () => {
|
|
2952
|
-
if (isActive(item)) setIsOpen(true);
|
|
2953
|
-
} }, []);
|
|
2954
|
-
if (level > maxLevel) return null;
|
|
2955
|
-
const handleItemClick = (e) => {
|
|
2956
|
-
if (!props.item.target) e.preventDefault();
|
|
2957
|
-
if (item.children && item.children.length > 0) setIsOpen(!isOpen);
|
|
2958
|
-
else {
|
|
2959
|
-
props.onItemClick?.(item);
|
|
2960
|
-
item.onClick?.();
|
|
2961
|
-
}
|
|
2945
|
+
const renderFields = () => {
|
|
2946
|
+
if (children) return /* @__PURE__ */ jsx(Fragment, { children: children(form.input) });
|
|
2947
|
+
return /* @__PURE__ */ jsx(Grid, { children: supportedFields.map((fieldName) => {
|
|
2948
|
+
const field = form.input[fieldName];
|
|
2949
|
+
const fieldSchema = schema.properties[fieldName];
|
|
2950
|
+
if (!field || !fieldSchema) return null;
|
|
2951
|
+
const isObject = fieldSchema && "type" in fieldSchema && fieldSchema.type === "object";
|
|
2952
|
+
const isArrayOfObjects = fieldSchema && "type" in fieldSchema && fieldSchema.type === "array" && "items" in fieldSchema && fieldSchema.items && "properties" in fieldSchema.items;
|
|
2953
|
+
const span = isObject || isArrayOfObjects ? 12 : colSpan;
|
|
2954
|
+
const mergedControlProps = {
|
|
2955
|
+
...controlProps,
|
|
2956
|
+
...fieldControlProps?.[fieldName]
|
|
2957
|
+
};
|
|
2958
|
+
if (size) mergedControlProps.size = size;
|
|
2959
|
+
return /* @__PURE__ */ jsx(Grid.Col, {
|
|
2960
|
+
span,
|
|
2961
|
+
children: /* @__PURE__ */ jsx(Control, {
|
|
2962
|
+
input: field,
|
|
2963
|
+
...mergedControlProps
|
|
2964
|
+
})
|
|
2965
|
+
}, fieldName);
|
|
2966
|
+
}) });
|
|
2962
2967
|
};
|
|
2963
|
-
|
|
2968
|
+
const content = /* @__PURE__ */ jsxs(Flex$1, {
|
|
2964
2969
|
direction: "column",
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2970
|
+
gap: "sm",
|
|
2971
|
+
flex: fill ? 1 : void 0,
|
|
2972
|
+
...props.flexProps,
|
|
2973
|
+
children: [/* @__PURE__ */ jsx(Flex$1, {
|
|
2974
|
+
direction: "column",
|
|
2975
|
+
gap: "sm",
|
|
2976
|
+
flex: 1,
|
|
2977
|
+
children: renderFields()
|
|
2978
|
+
}), !skipSubmitButton && /* @__PURE__ */ jsx(Card, {
|
|
2968
2979
|
w: "100%",
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
target: props.item.target,
|
|
2972
|
-
size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
|
|
2973
|
-
tooltip: item.description ? {
|
|
2974
|
-
label: item.description,
|
|
2975
|
-
position: "right"
|
|
2976
|
-
} : void 0,
|
|
2977
|
-
color: "gray",
|
|
2978
|
-
variant: "subtle",
|
|
2979
|
-
variantActive: "default",
|
|
2980
|
-
radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
|
|
2981
|
-
onClick: handleItemClick,
|
|
2982
|
-
leftSection: /* @__PURE__ */ jsxs(Flex$1, {
|
|
2983
|
-
w: "100%",
|
|
2984
|
-
align: "center",
|
|
2980
|
+
withBorder: true,
|
|
2981
|
+
children: /* @__PURE__ */ jsxs(Flex$1, {
|
|
2985
2982
|
gap: "sm",
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
level: level + 1,
|
|
3006
|
-
onItemClick: props.onItemClick,
|
|
3007
|
-
theme: props.theme
|
|
3008
|
-
}, index))]
|
|
2983
|
+
flex: 1,
|
|
2984
|
+
children: [
|
|
2985
|
+
/* @__PURE__ */ jsx(Flex$1, {}),
|
|
2986
|
+
/* @__PURE__ */ jsx(Flex$1, { flex: 1 }),
|
|
2987
|
+
/* @__PURE__ */ jsxs(Flex$1, {
|
|
2988
|
+
gap: "sm",
|
|
2989
|
+
children: [/* @__PURE__ */ jsx(ActionButton, {
|
|
2990
|
+
variant: "subtle",
|
|
2991
|
+
type: "reset",
|
|
2992
|
+
children: "Reset"
|
|
2993
|
+
}), /* @__PURE__ */ jsx(ActionButton, {
|
|
2994
|
+
intent: "primary",
|
|
2995
|
+
form,
|
|
2996
|
+
...submitButtonProps,
|
|
2997
|
+
children: submitButtonProps?.children ?? "Submit"
|
|
2998
|
+
})]
|
|
2999
|
+
})
|
|
3000
|
+
]
|
|
3001
|
+
})
|
|
3009
3002
|
})]
|
|
3010
3003
|
});
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
props
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
return /* @__PURE__ */ jsx(ActionButton, {
|
|
3019
|
-
size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
|
|
3020
|
-
variant: "subtle",
|
|
3021
|
-
variantActive: "default",
|
|
3022
|
-
tooltip: {
|
|
3023
|
-
label: item.label,
|
|
3024
|
-
position: "right"
|
|
3025
|
-
},
|
|
3026
|
-
radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
|
|
3027
|
-
onClick: handleItemClick,
|
|
3028
|
-
icon: renderIcon(item.icon, ui.sizes.icon.sm) ?? /* @__PURE__ */ jsx(IconSquareRounded, { size: ui.sizes.icon.sm }),
|
|
3029
|
-
href: props.item.href,
|
|
3030
|
-
target: props.item.target,
|
|
3031
|
-
...props.item.actionProps
|
|
3004
|
+
if (skipFormElement) return content;
|
|
3005
|
+
return /* @__PURE__ */ jsx(Flex$1, {
|
|
3006
|
+
component: "form",
|
|
3007
|
+
flex: fill ? 1 : void 0,
|
|
3008
|
+
...form.props,
|
|
3009
|
+
...props.flexProps,
|
|
3010
|
+
children: content
|
|
3032
3011
|
});
|
|
3033
3012
|
};
|
|
3034
3013
|
|
|
3035
3014
|
//#endregion
|
|
3036
|
-
//#region ../../src/core/
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3015
|
+
//#region ../../src/core/form/factories/dialogForm.tsx
|
|
3016
|
+
/**
|
|
3017
|
+
* Creates dialog options for a form dialog.
|
|
3018
|
+
*
|
|
3019
|
+
* @param form - The form model to render.
|
|
3020
|
+
* @param options - Additional dialog and TypeForm options.
|
|
3021
|
+
*/
|
|
3022
|
+
const dialogForm = (form, options) => ({
|
|
3023
|
+
size: "lg",
|
|
3024
|
+
title: options?.title || "Form",
|
|
3025
|
+
...options,
|
|
3026
|
+
content: /* @__PURE__ */ jsx(TypeForm, {
|
|
3027
|
+
form,
|
|
3028
|
+
skipSubmitButton: false,
|
|
3029
|
+
...options?.typeFormProps
|
|
3030
|
+
})
|
|
3031
|
+
});
|
|
3032
|
+
|
|
3033
|
+
//#endregion
|
|
3034
|
+
//#region ../../src/core/helpers/renderIcon.tsx
|
|
3035
|
+
const renderIcon = (icon, size) => {
|
|
3036
|
+
if (!icon) return null;
|
|
3037
|
+
if (isValidElement(icon)) return icon;
|
|
3038
|
+
if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: size ?? ui.sizes.icon.md });
|
|
3039
|
+
return icon;
|
|
3040
|
+
};
|
|
3041
|
+
|
|
3042
|
+
//#endregion
|
|
3043
|
+
//#region ../../src/core/hooks/useDialog.ts
|
|
3044
|
+
/**
|
|
3045
|
+
* Use this hook to access the Dialog Service for showing various dialog types.
|
|
3046
|
+
*
|
|
3047
|
+
* @example
|
|
3048
|
+
* ```tsx
|
|
3049
|
+
* const dialog = useDialog();
|
|
3050
|
+
* await dialog.alert({ title: "Alert", message: "This is an alert message" });
|
|
3051
|
+
* const confirmed = await dialog.confirm({ title: "Confirm", message: "Are you sure?" });
|
|
3052
|
+
* const input = await dialog.prompt({ title: "Input", message: "Enter your name:" });
|
|
3053
|
+
* ```
|
|
3054
|
+
*/
|
|
3055
|
+
const useDialog = () => {
|
|
3056
|
+
return useInject(DialogService);
|
|
3057
|
+
};
|
|
3058
|
+
|
|
3059
|
+
//#endregion
|
|
3060
|
+
//#region ../../src/core/json/components/JsonViewer.tsx
|
|
3061
|
+
const SIZE_CONFIG = {
|
|
3062
|
+
xs: {
|
|
3063
|
+
icon: 14,
|
|
3064
|
+
levelOffset: 16
|
|
3065
|
+
},
|
|
3066
|
+
sm: {
|
|
3067
|
+
icon: 16,
|
|
3068
|
+
levelOffset: 20
|
|
3069
|
+
},
|
|
3070
|
+
md: {
|
|
3071
|
+
icon: 18,
|
|
3072
|
+
levelOffset: 24
|
|
3073
|
+
},
|
|
3074
|
+
lg: {
|
|
3075
|
+
icon: 20,
|
|
3076
|
+
levelOffset: 28
|
|
3077
|
+
},
|
|
3078
|
+
xl: {
|
|
3079
|
+
icon: 22,
|
|
3080
|
+
levelOffset: 32
|
|
3081
|
+
}
|
|
3082
|
+
};
|
|
3083
|
+
const STYLES = {
|
|
3084
|
+
root: { fontFamily: "var(--mantine-font-family-monospace)" },
|
|
3085
|
+
chevron: {
|
|
3086
|
+
flexShrink: 0,
|
|
3087
|
+
color: "var(--mantine-color-dimmed)"
|
|
3088
|
+
},
|
|
3089
|
+
key: {
|
|
3090
|
+
color: "var(--mantine-color-cyan-text)",
|
|
3091
|
+
fontWeight: 500
|
|
3092
|
+
},
|
|
3093
|
+
colon: { color: "var(--mantine-color-dimmed)" },
|
|
3094
|
+
string: { color: "var(--mantine-color-teal-text)" },
|
|
3095
|
+
number: { color: "var(--mantine-color-blue-text)" },
|
|
3096
|
+
boolean: { color: "var(--mantine-color-violet-text)" },
|
|
3097
|
+
null: {
|
|
3098
|
+
color: "var(--mantine-color-dimmed)",
|
|
3099
|
+
fontStyle: "italic"
|
|
3100
|
+
},
|
|
3101
|
+
preview: { color: "var(--mantine-color-dimmed)" }
|
|
3102
|
+
};
|
|
3103
|
+
const getValueType = (val) => {
|
|
3104
|
+
if (val === null) return "null";
|
|
3105
|
+
if (val === void 0) return "undefined";
|
|
3106
|
+
if (Array.isArray(val)) return "array";
|
|
3107
|
+
return typeof val;
|
|
3108
|
+
};
|
|
3109
|
+
function buildTreeNodes(data, path = [], key, isArrayItem = false, maxDepth = 10) {
|
|
3110
|
+
const currentPath = key !== void 0 ? [...path, key] : path;
|
|
3111
|
+
const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
|
|
3112
|
+
if (currentPath.length > maxDepth) return {
|
|
3113
|
+
value: nodeId,
|
|
3114
|
+
label: key ?? "",
|
|
3115
|
+
nodeValue: data,
|
|
3116
|
+
nodeKey: key,
|
|
3117
|
+
path: currentPath,
|
|
3118
|
+
isArrayItem
|
|
3119
|
+
};
|
|
3120
|
+
const type = getValueType(data);
|
|
3121
|
+
if (type === "object" || type === "array") {
|
|
3122
|
+
const children = (type === "array" ? data.map((v, i) => [String(i), v]) : Object.entries(data)).map(([k, v]) => buildTreeNodes(v, currentPath, k, type === "array", maxDepth)).filter((n) => n !== null);
|
|
3123
|
+
return {
|
|
3124
|
+
value: nodeId,
|
|
3125
|
+
label: key ?? "",
|
|
3126
|
+
nodeValue: data,
|
|
3127
|
+
nodeKey: key,
|
|
3128
|
+
path: currentPath,
|
|
3129
|
+
isArrayItem,
|
|
3130
|
+
children: children.length > 0 ? children : void 0
|
|
3125
3131
|
};
|
|
3126
|
-
}
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
]);
|
|
3135
|
-
const hoverTimeoutRef = useRef(null);
|
|
3136
|
-
const expandOnHover = props.sidebarProps?.expandOnHover !== false;
|
|
3137
|
-
const handleNavbarMouseEnter = useCallback(() => {
|
|
3138
|
-
if (collapsed && expandOnHover) hoverTimeoutRef.current = setTimeout(() => {
|
|
3139
|
-
setIsHovering(true);
|
|
3140
|
-
}, hoverDelay);
|
|
3141
|
-
}, [
|
|
3142
|
-
collapsed,
|
|
3143
|
-
expandOnHover,
|
|
3144
|
-
hoverDelay
|
|
3145
|
-
]);
|
|
3146
|
-
const handleNavbarMouseLeave = useCallback(() => {
|
|
3147
|
-
if (hoverTimeoutRef.current) {
|
|
3148
|
-
clearTimeout(hoverTimeoutRef.current);
|
|
3149
|
-
hoverTimeoutRef.current = null;
|
|
3150
|
-
}
|
|
3151
|
-
setIsHovering(false);
|
|
3152
|
-
}, []);
|
|
3153
|
-
useEffect(() => {
|
|
3154
|
-
if (collapsed) {
|
|
3155
|
-
setIsHovering(false);
|
|
3156
|
-
if (hoverTimeoutRef.current) {
|
|
3157
|
-
clearTimeout(hoverTimeoutRef.current);
|
|
3158
|
-
hoverTimeoutRef.current = null;
|
|
3159
|
-
}
|
|
3160
|
-
}
|
|
3161
|
-
}, [collapsed]);
|
|
3162
|
-
const shouldShowSidebar = () => {
|
|
3163
|
-
if (props.noSidebarWhen?.paths) {
|
|
3164
|
-
for (const path of props.noSidebarWhen.paths) if (router.isActive(path, { startWith: true })) return false;
|
|
3165
|
-
}
|
|
3166
|
-
return true;
|
|
3132
|
+
}
|
|
3133
|
+
return {
|
|
3134
|
+
value: nodeId,
|
|
3135
|
+
label: key ?? "",
|
|
3136
|
+
nodeValue: data,
|
|
3137
|
+
nodeKey: key,
|
|
3138
|
+
path: currentPath,
|
|
3139
|
+
isArrayItem
|
|
3167
3140
|
};
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
const
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
const
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3141
|
+
}
|
|
3142
|
+
function getExpandedIds(nodes, targetDepth, currentDepth = 0) {
|
|
3143
|
+
if (currentDepth >= targetDepth) return [];
|
|
3144
|
+
const ids = [];
|
|
3145
|
+
for (const node of nodes) if (node.children) {
|
|
3146
|
+
ids.push(node.value);
|
|
3147
|
+
ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
|
|
3148
|
+
}
|
|
3149
|
+
return ids;
|
|
3150
|
+
}
|
|
3151
|
+
const CopyButton$1 = ({ value, iconSize }) => {
|
|
3152
|
+
const [copied, setCopied] = useState(false);
|
|
3153
|
+
const handleCopy = useCallback((e) => {
|
|
3154
|
+
e.stopPropagation();
|
|
3155
|
+
navigator.clipboard.writeText(value);
|
|
3156
|
+
setCopied(true);
|
|
3157
|
+
setTimeout(() => setCopied(false), 1500);
|
|
3158
|
+
}, [value]);
|
|
3159
|
+
return /* @__PURE__ */ jsx(ActionIcon, {
|
|
3160
|
+
size: iconSize + 4,
|
|
3161
|
+
variant: "transparent",
|
|
3162
|
+
c: copied ? "green" : "dimmed",
|
|
3163
|
+
onClick: handleCopy,
|
|
3164
|
+
className: "alepha-json-viewer-copy",
|
|
3165
|
+
children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: iconSize }) : /* @__PURE__ */ jsx(IconCopy, { size: iconSize })
|
|
3166
|
+
});
|
|
3167
|
+
};
|
|
3168
|
+
const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, showQuotes, showCopyButton, renderValue }) => {
|
|
3169
|
+
const { nodeValue, nodeKey, path, isArrayItem, isRoot } = node;
|
|
3170
|
+
const type = getValueType(nodeValue);
|
|
3171
|
+
const isExpandable = type === "object" || type === "array";
|
|
3172
|
+
const getPreview = () => {
|
|
3173
|
+
if (!isExpandable) return null;
|
|
3174
|
+
const count = (type === "array" ? nodeValue : Object.keys(nodeValue)).length;
|
|
3175
|
+
const label = type === "array" ? "item" : "key";
|
|
3176
|
+
if (!expanded) return /* @__PURE__ */ jsx(Text$1, {
|
|
3177
|
+
fs: "italic",
|
|
3178
|
+
component: "span",
|
|
3179
|
+
size,
|
|
3180
|
+
style: STYLES.preview,
|
|
3181
|
+
children: count === 0 ? type === "array" ? "[]" : "{}" : type === "array" ? `[ ${count} ${count === 1 ? label : `${label}s`} ]` : `{ ${count} ${count === 1 ? label : `${label}s`} }`
|
|
3182
|
+
});
|
|
3183
|
+
return null;
|
|
3184
|
+
};
|
|
3185
|
+
const getCopyValue = () => isExpandable ? JSON.stringify(nodeValue, null, 2) : String(nodeValue ?? "");
|
|
3186
|
+
return /* @__PURE__ */ jsxs(Flex$1, {
|
|
3187
|
+
gap: 6,
|
|
3188
|
+
wrap: "nowrap",
|
|
3189
|
+
...elementProps,
|
|
3190
|
+
className: `alepha-json-viewer-row ${elementProps.className || ""}`,
|
|
3213
3191
|
children: [
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
}),
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
}
|
|
3235
|
-
},
|
|
3236
|
-
...props.appShellNavbarProps,
|
|
3237
|
-
children: [
|
|
3238
|
-
props.navbarHeader ? /* @__PURE__ */ jsx(Flex$1, {
|
|
3239
|
-
style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
|
|
3240
|
-
h: headerHeight,
|
|
3241
|
-
children: props.navbarHeader
|
|
3242
|
-
}) : null,
|
|
3243
|
-
/* @__PURE__ */ jsx(Sidebar, {
|
|
3244
|
-
...props.sidebarProps ?? {},
|
|
3245
|
-
collapsed: effectiveCollapsed,
|
|
3246
|
-
onItemClick: handleSidebarItemClick
|
|
3247
|
-
}),
|
|
3248
|
-
props.navbarFooter ? /* @__PURE__ */ jsx(Flex$1, {
|
|
3249
|
-
style: { borderTop: "1px solid var(--mantine-color-default-border)" },
|
|
3250
|
-
h: footerHeight,
|
|
3251
|
-
children: props.navbarFooter
|
|
3252
|
-
}) : null,
|
|
3253
|
-
(canResize || isExpandedByHover) && /* @__PURE__ */ jsx(Flex$1, {
|
|
3254
|
-
pos: "absolute",
|
|
3255
|
-
right: -6,
|
|
3256
|
-
top: 0,
|
|
3257
|
-
bottom: 0,
|
|
3258
|
-
w: 12,
|
|
3259
|
-
style: {
|
|
3260
|
-
cursor: "col-resize",
|
|
3261
|
-
userSelect: "none"
|
|
3262
|
-
},
|
|
3263
|
-
onMouseDown: handleResizeStart
|
|
3264
|
-
})
|
|
3265
|
-
]
|
|
3192
|
+
hasChildren ? expanded ? /* @__PURE__ */ jsx(IconChevronDown, {
|
|
3193
|
+
size: config.icon,
|
|
3194
|
+
style: STYLES.chevron
|
|
3195
|
+
}) : /* @__PURE__ */ jsx(IconChevronRight, {
|
|
3196
|
+
size: config.icon,
|
|
3197
|
+
style: STYLES.chevron
|
|
3198
|
+
}) : /* @__PURE__ */ jsx("span", { style: {
|
|
3199
|
+
width: config.icon,
|
|
3200
|
+
flexShrink: 0
|
|
3201
|
+
} }),
|
|
3202
|
+
nodeKey !== void 0 && !isArrayItem && /* @__PURE__ */ jsxs(Text$1, {
|
|
3203
|
+
component: "span",
|
|
3204
|
+
size,
|
|
3205
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3206
|
+
style: STYLES.key,
|
|
3207
|
+
children: showQuotes ? `"${nodeKey}"` : nodeKey
|
|
3208
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
3209
|
+
style: STYLES.colon,
|
|
3210
|
+
children: ":"
|
|
3211
|
+
})]
|
|
3266
3212
|
}),
|
|
3267
|
-
/* @__PURE__ */
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
children: props.children ?? /* @__PURE__ */ jsx(NestedView, {})
|
|
3278
|
-
}) : props.children ?? /* @__PURE__ */ jsx(NestedView, {})
|
|
3213
|
+
nodeKey !== void 0 && isArrayItem && /* @__PURE__ */ jsxs(Text$1, {
|
|
3214
|
+
component: "span",
|
|
3215
|
+
size,
|
|
3216
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3217
|
+
style: STYLES.key,
|
|
3218
|
+
children: nodeKey
|
|
3219
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
3220
|
+
style: STYLES.colon,
|
|
3221
|
+
children: ":"
|
|
3222
|
+
})]
|
|
3279
3223
|
}),
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3224
|
+
hasChildren ? getPreview() : isExpandable ? type === "array" ? /* @__PURE__ */ jsx(Text$1, {
|
|
3225
|
+
component: "span",
|
|
3226
|
+
size,
|
|
3227
|
+
style: STYLES.preview,
|
|
3228
|
+
children: "[]"
|
|
3229
|
+
}) : /* @__PURE__ */ jsx(Text$1, {
|
|
3230
|
+
component: "span",
|
|
3231
|
+
size,
|
|
3232
|
+
style: STYLES.preview,
|
|
3233
|
+
children: "{}"
|
|
3234
|
+
}) : renderValue(nodeValue, nodeKey, path),
|
|
3235
|
+
showCopyButton && /* @__PURE__ */ jsx(CopyButton$1, {
|
|
3236
|
+
value: getCopyValue(),
|
|
3237
|
+
iconSize: config.icon
|
|
3283
3238
|
})
|
|
3284
3239
|
]
|
|
3285
3240
|
});
|
|
3286
3241
|
};
|
|
3242
|
+
const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm", showQuotes = false, showCopyButton = true, formatValue }) => {
|
|
3243
|
+
const config = SIZE_CONFIG[size] || SIZE_CONFIG.sm;
|
|
3244
|
+
const treeData = useMemo(() => {
|
|
3245
|
+
const type = getValueType(data);
|
|
3246
|
+
if (type === "object" || type === "array") {
|
|
3247
|
+
const children = (type === "array" ? data.map((v, i) => [String(i), v]) : Object.entries(data)).map(([k, v]) => buildTreeNodes(v, [], k, type === "array", maxDepth)).filter((n) => n !== null);
|
|
3248
|
+
return [{
|
|
3249
|
+
value: "root",
|
|
3250
|
+
label: "",
|
|
3251
|
+
nodeValue: data,
|
|
3252
|
+
nodeKey: void 0,
|
|
3253
|
+
path: [],
|
|
3254
|
+
isArrayItem: false,
|
|
3255
|
+
isRoot: true,
|
|
3256
|
+
children: children.length > 0 ? children : void 0
|
|
3257
|
+
}];
|
|
3258
|
+
}
|
|
3259
|
+
const node = buildTreeNodes(data, [], void 0, false, maxDepth);
|
|
3260
|
+
return node ? [node] : [];
|
|
3261
|
+
}, [data, maxDepth]);
|
|
3262
|
+
const tree = useTree({ initialExpandedState: useMemo(() => {
|
|
3263
|
+
if (defaultExpandedDepth === 0) return {};
|
|
3264
|
+
if (defaultExpandedDepth === Infinity) return getTreeExpandedState(treeData, "*");
|
|
3265
|
+
return getTreeExpandedState(treeData, getExpandedIds(treeData, defaultExpandedDepth + 1));
|
|
3266
|
+
}, [treeData, defaultExpandedDepth]) });
|
|
3267
|
+
const renderValue = useCallback((val, key, path) => {
|
|
3268
|
+
const custom = formatValue?.(key, val, path);
|
|
3269
|
+
if (custom !== void 0) return /* @__PURE__ */ jsx(Text$1, {
|
|
3270
|
+
component: "span",
|
|
3271
|
+
size,
|
|
3272
|
+
style: STYLES.string,
|
|
3273
|
+
className: "alepha-json-viewer-value",
|
|
3274
|
+
title: String(val),
|
|
3275
|
+
children: custom
|
|
3276
|
+
});
|
|
3277
|
+
const type = getValueType(val);
|
|
3278
|
+
switch (type) {
|
|
3279
|
+
case "string": return /* @__PURE__ */ jsxs(Text$1, {
|
|
3280
|
+
style: STYLES.string,
|
|
3281
|
+
component: "span",
|
|
3282
|
+
size,
|
|
3283
|
+
className: "alepha-json-viewer-value",
|
|
3284
|
+
title: val,
|
|
3285
|
+
children: [
|
|
3286
|
+
"\"",
|
|
3287
|
+
val,
|
|
3288
|
+
"\""
|
|
3289
|
+
]
|
|
3290
|
+
});
|
|
3291
|
+
case "number": return /* @__PURE__ */ jsx(Text$1, {
|
|
3292
|
+
component: "span",
|
|
3293
|
+
size,
|
|
3294
|
+
style: STYLES.number,
|
|
3295
|
+
children: val
|
|
3296
|
+
});
|
|
3297
|
+
case "boolean": return /* @__PURE__ */ jsx(Text$1, {
|
|
3298
|
+
component: "span",
|
|
3299
|
+
size,
|
|
3300
|
+
style: STYLES.boolean,
|
|
3301
|
+
children: String(val)
|
|
3302
|
+
});
|
|
3303
|
+
case "null":
|
|
3304
|
+
case "undefined": return /* @__PURE__ */ jsx(Text$1, {
|
|
3305
|
+
component: "span",
|
|
3306
|
+
size,
|
|
3307
|
+
style: STYLES.null,
|
|
3308
|
+
children: type
|
|
3309
|
+
});
|
|
3310
|
+
default: return /* @__PURE__ */ jsx(Text$1, {
|
|
3311
|
+
component: "span",
|
|
3312
|
+
size,
|
|
3313
|
+
children: String(val)
|
|
3314
|
+
});
|
|
3315
|
+
}
|
|
3316
|
+
}, [
|
|
3317
|
+
formatValue,
|
|
3318
|
+
showQuotes,
|
|
3319
|
+
size
|
|
3320
|
+
]);
|
|
3321
|
+
const renderNode = useCallback(({ node, expanded, hasChildren, elementProps }) => {
|
|
3322
|
+
return /* @__PURE__ */ jsx(RowNode, {
|
|
3323
|
+
node,
|
|
3324
|
+
expanded,
|
|
3325
|
+
hasChildren,
|
|
3326
|
+
elementProps,
|
|
3327
|
+
size,
|
|
3328
|
+
config,
|
|
3329
|
+
showQuotes,
|
|
3330
|
+
showCopyButton,
|
|
3331
|
+
renderValue
|
|
3332
|
+
});
|
|
3333
|
+
}, [
|
|
3334
|
+
config,
|
|
3335
|
+
renderValue,
|
|
3336
|
+
showCopyButton,
|
|
3337
|
+
showQuotes,
|
|
3338
|
+
size
|
|
3339
|
+
]);
|
|
3340
|
+
if (treeData.length === 0) return /* @__PURE__ */ jsx(Text$1, {
|
|
3341
|
+
size,
|
|
3342
|
+
style: STYLES.null,
|
|
3343
|
+
children: data === null ? "null" : data === void 0 ? "undefined" : "{}"
|
|
3344
|
+
});
|
|
3345
|
+
return /* @__PURE__ */ jsx(Tree, {
|
|
3346
|
+
data: treeData,
|
|
3347
|
+
tree,
|
|
3348
|
+
levelOffset: config.levelOffset,
|
|
3349
|
+
expandOnClick: true,
|
|
3350
|
+
renderNode,
|
|
3351
|
+
styles: { root: STYLES.root }
|
|
3352
|
+
});
|
|
3353
|
+
};
|
|
3354
|
+
|
|
3355
|
+
//#endregion
|
|
3356
|
+
//#region ../../src/core/json/factories/dialogJson.tsx
|
|
3357
|
+
/**
|
|
3358
|
+
* Creates dialog options for a JSON viewer dialog.
|
|
3359
|
+
*
|
|
3360
|
+
* @param data - The JSON data to display.
|
|
3361
|
+
* @param options - Additional dialog options.
|
|
3362
|
+
*/
|
|
3363
|
+
const dialogJson = (data, options) => ({
|
|
3364
|
+
size: "lg",
|
|
3365
|
+
title: options?.title || "Json Viewer",
|
|
3366
|
+
...options,
|
|
3367
|
+
content: /* @__PURE__ */ jsx(Flex$1, {
|
|
3368
|
+
bdrs: "md",
|
|
3369
|
+
w: "100%",
|
|
3370
|
+
flex: 1,
|
|
3371
|
+
p: "sm",
|
|
3372
|
+
bg: ui.colors.surface,
|
|
3373
|
+
children: /* @__PURE__ */ jsx(JsonViewer, {
|
|
3374
|
+
size: "xs",
|
|
3375
|
+
data
|
|
3376
|
+
})
|
|
3377
|
+
})
|
|
3378
|
+
});
|
|
3379
|
+
|
|
3380
|
+
//#endregion
|
|
3381
|
+
//#region ../../src/core/primitives/$ui.ts
|
|
3382
|
+
/**
|
|
3383
|
+
* Convenience function to configure and inject the UiRouter.
|
|
3384
|
+
*/
|
|
3385
|
+
const $ui = (options = {}) => {
|
|
3386
|
+
const { alepha } = $context();
|
|
3387
|
+
if (options.themes) alepha.store.set(alephaThemeListAtom, options.themes);
|
|
3388
|
+
return alepha.inject(UiRouter);
|
|
3389
|
+
};
|
|
3287
3390
|
|
|
3288
3391
|
//#endregion
|
|
3289
|
-
//#region ../../src/core/
|
|
3392
|
+
//#region ../../src/core/table/interfaces/types.ts
|
|
3393
|
+
const DEFAULT_MAX_VISIBLE_COLUMNS = 8;
|
|
3394
|
+
|
|
3395
|
+
//#endregion
|
|
3396
|
+
//#region ../../src/core/table/components/DataTableFilters.tsx
|
|
3290
3397
|
const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) => {
|
|
3291
3398
|
const visibleSchema = useMemo(() => {
|
|
3292
3399
|
const visibleKeys = Object.keys(schema.properties).filter((key) => filterVisibility[key] !== false);
|
|
@@ -3322,7 +3429,7 @@ const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) =>
|
|
|
3322
3429
|
};
|
|
3323
3430
|
|
|
3324
3431
|
//#endregion
|
|
3325
|
-
//#region ../../src/core/components/
|
|
3432
|
+
//#region ../../src/core/table/components/DataTablePagination.tsx
|
|
3326
3433
|
const DataTablePagination = ({ page, size, totalPages, onPageChange, onSizeChange }) => {
|
|
3327
3434
|
return /* @__PURE__ */ jsxs(Flex$1, {
|
|
3328
3435
|
align: "center",
|
|
@@ -3369,11 +3476,7 @@ const DataTablePagination = ({ page, size, totalPages, onPageChange, onSizeChang
|
|
|
3369
3476
|
};
|
|
3370
3477
|
|
|
3371
3478
|
//#endregion
|
|
3372
|
-
//#region ../../src/core/components/
|
|
3373
|
-
const DEFAULT_MAX_VISIBLE_COLUMNS = 8;
|
|
3374
|
-
|
|
3375
|
-
//#endregion
|
|
3376
|
-
//#region ../../src/core/components/table/ColumnPicker.tsx
|
|
3479
|
+
//#region ../../src/core/table/components/ColumnPicker.tsx
|
|
3377
3480
|
const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
|
|
3378
3481
|
const [opened, setOpened] = useState(false);
|
|
3379
3482
|
const columnEntries = Object.entries(columns);
|
|
@@ -3474,7 +3577,7 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
|
|
|
3474
3577
|
};
|
|
3475
3578
|
|
|
3476
3579
|
//#endregion
|
|
3477
|
-
//#region ../../src/core/components/
|
|
3580
|
+
//#region ../../src/core/table/components/FilterPicker.tsx
|
|
3478
3581
|
const getFieldLabel = (schema, key) => {
|
|
3479
3582
|
const prop = schema.properties[key];
|
|
3480
3583
|
if (prop && typeof prop === "object" && "title" in prop && prop.title) return prop.title;
|
|
@@ -3575,7 +3678,7 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
|
|
|
3575
3678
|
};
|
|
3576
3679
|
|
|
3577
3680
|
//#endregion
|
|
3578
|
-
//#region ../../src/core/components/
|
|
3681
|
+
//#region ../../src/core/table/components/DataTableToolbar.tsx
|
|
3579
3682
|
const escapeCsvField = (value) => {
|
|
3580
3683
|
if (value.includes(",") || value.includes("\"") || value.includes("\n")) return `"${value.replace(/"/g, "\"\"")}"`;
|
|
3581
3684
|
return value;
|
|
@@ -3658,7 +3761,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
|
|
|
3658
3761
|
onClick: exportClipboard
|
|
3659
3762
|
}] }
|
|
3660
3763
|
}),
|
|
3661
|
-
hasSelection && /* @__PURE__ */ jsxs(Fragment
|
|
3764
|
+
hasSelection && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3662
3765
|
/* @__PURE__ */ jsx(Divider, {
|
|
3663
3766
|
orientation: "vertical",
|
|
3664
3767
|
mx: "xs"
|
|
@@ -3703,7 +3806,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
|
|
|
3703
3806
|
};
|
|
3704
3807
|
|
|
3705
3808
|
//#endregion
|
|
3706
|
-
//#region ../../src/core/components/
|
|
3809
|
+
//#region ../../src/core/table/components/useTableSelection.ts
|
|
3707
3810
|
const useTableSelection = (items, getItemKey, enabled) => {
|
|
3708
3811
|
const [selectedKeys, setSelectedKeys] = useState(/* @__PURE__ */ new Set());
|
|
3709
3812
|
const selectedItems = useMemo(() => {
|
|
@@ -3766,7 +3869,7 @@ const useTableSelection = (items, getItemKey, enabled) => {
|
|
|
3766
3869
|
};
|
|
3767
3870
|
|
|
3768
3871
|
//#endregion
|
|
3769
|
-
//#region ../../src/core/components/
|
|
3872
|
+
//#region ../../src/core/table/components/DataTable.tsx
|
|
3770
3873
|
/**
|
|
3771
3874
|
* Parse the sort string to get direction for a specific field.
|
|
3772
3875
|
* Alepha convention: 'field' = ASC, '-field' = DESC
|
|
@@ -4165,29 +4268,206 @@ const DataTable = (props) => {
|
|
|
4165
4268
|
};
|
|
4166
4269
|
|
|
4167
4270
|
//#endregion
|
|
4168
|
-
//#region ../../src/core/
|
|
4271
|
+
//#region ../../src/core/utils/extractSchemaFields.ts
|
|
4169
4272
|
/**
|
|
4170
|
-
*
|
|
4273
|
+
* Extract field information from a TypeBox schema for query building.
|
|
4274
|
+
* Supports nested objects and provides field metadata for autocomplete.
|
|
4275
|
+
*/
|
|
4276
|
+
function extractSchemaFields(schema, prefix = "") {
|
|
4277
|
+
const fields = [];
|
|
4278
|
+
if (!schema || typeof schema !== "object") return fields;
|
|
4279
|
+
const properties = "properties" in schema ? schema.properties : schema;
|
|
4280
|
+
if (!properties || typeof properties !== "object") return fields;
|
|
4281
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
4282
|
+
if (typeof value !== "object" || value === null) continue;
|
|
4283
|
+
const fieldSchema = value;
|
|
4284
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
4285
|
+
const format = "format" in fieldSchema ? fieldSchema.format : void 0;
|
|
4286
|
+
let displayType = "type" in fieldSchema ? fieldSchema.type : "object";
|
|
4287
|
+
if (format === "date-time") displayType = "datetime";
|
|
4288
|
+
else if (format === "date") displayType = "date";
|
|
4289
|
+
else if (format === "time") displayType = "time";
|
|
4290
|
+
else if (format === "duration") displayType = "duration";
|
|
4291
|
+
const field = {
|
|
4292
|
+
name: key,
|
|
4293
|
+
path,
|
|
4294
|
+
type: displayType,
|
|
4295
|
+
format,
|
|
4296
|
+
description: "description" in fieldSchema ? fieldSchema.description : void 0
|
|
4297
|
+
};
|
|
4298
|
+
if ("enum" in fieldSchema && fieldSchema.enum) {
|
|
4299
|
+
field.enum = fieldSchema.enum;
|
|
4300
|
+
field.type = "enum";
|
|
4301
|
+
}
|
|
4302
|
+
if ("type" in fieldSchema && fieldSchema.type === "object" && "properties" in fieldSchema && typeof fieldSchema.properties === "object") field.nested = extractSchemaFields(fieldSchema.properties, path);
|
|
4303
|
+
fields.push(field);
|
|
4304
|
+
if (field.nested) fields.push(...field.nested);
|
|
4305
|
+
}
|
|
4306
|
+
return fields;
|
|
4307
|
+
}
|
|
4308
|
+
/**
|
|
4309
|
+
* Get suggested operators based on field type
|
|
4310
|
+
*/
|
|
4311
|
+
function getOperatorsForField(field) {
|
|
4312
|
+
const allOperators = ["=", "!="];
|
|
4313
|
+
if (field.enum) return [...allOperators, "in"];
|
|
4314
|
+
switch (field.type) {
|
|
4315
|
+
case "string":
|
|
4316
|
+
case "text": return [...allOperators, "null"];
|
|
4317
|
+
case "number":
|
|
4318
|
+
case "integer": return [
|
|
4319
|
+
...allOperators,
|
|
4320
|
+
">",
|
|
4321
|
+
">=",
|
|
4322
|
+
"<",
|
|
4323
|
+
"<="
|
|
4324
|
+
];
|
|
4325
|
+
case "boolean": return allOperators;
|
|
4326
|
+
case "datetime":
|
|
4327
|
+
case "date": return [
|
|
4328
|
+
...allOperators,
|
|
4329
|
+
">",
|
|
4330
|
+
">=",
|
|
4331
|
+
"<",
|
|
4332
|
+
"<="
|
|
4333
|
+
];
|
|
4334
|
+
default: return [...allOperators, "null"];
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
4337
|
+
/**
|
|
4338
|
+
* Get operator symbol and description
|
|
4339
|
+
*/
|
|
4340
|
+
const OPERATOR_INFO = {
|
|
4341
|
+
eq: {
|
|
4342
|
+
symbol: "=",
|
|
4343
|
+
label: "equals",
|
|
4344
|
+
example: "name=John"
|
|
4345
|
+
},
|
|
4346
|
+
ne: {
|
|
4347
|
+
symbol: "!=",
|
|
4348
|
+
label: "not equals",
|
|
4349
|
+
example: "status!=archived"
|
|
4350
|
+
},
|
|
4351
|
+
gt: {
|
|
4352
|
+
symbol: ">",
|
|
4353
|
+
label: "greater than",
|
|
4354
|
+
example: "age>18"
|
|
4355
|
+
},
|
|
4356
|
+
gte: {
|
|
4357
|
+
symbol: ">=",
|
|
4358
|
+
label: "greater or equal",
|
|
4359
|
+
example: "age>=18"
|
|
4360
|
+
},
|
|
4361
|
+
lt: {
|
|
4362
|
+
symbol: "<",
|
|
4363
|
+
label: "less than",
|
|
4364
|
+
example: "age<65"
|
|
4365
|
+
},
|
|
4366
|
+
lte: {
|
|
4367
|
+
symbol: "<=",
|
|
4368
|
+
label: "less or equal",
|
|
4369
|
+
example: "age<=65"
|
|
4370
|
+
},
|
|
4371
|
+
null: {
|
|
4372
|
+
symbol: "=null",
|
|
4373
|
+
label: "is null",
|
|
4374
|
+
example: "deletedAt=null"
|
|
4375
|
+
},
|
|
4376
|
+
notNull: {
|
|
4377
|
+
symbol: "!=null",
|
|
4378
|
+
label: "is not null",
|
|
4379
|
+
example: "email!=null"
|
|
4380
|
+
},
|
|
4381
|
+
in: {
|
|
4382
|
+
symbol: "[...]",
|
|
4383
|
+
label: "in array",
|
|
4384
|
+
example: "status=[active,pending]"
|
|
4385
|
+
}
|
|
4386
|
+
};
|
|
4387
|
+
|
|
4388
|
+
//#endregion
|
|
4389
|
+
//#region ../../src/core/utils/icons.tsx
|
|
4390
|
+
/**
|
|
4391
|
+
* Get the default icon for an input based on its type, format, or name.
|
|
4392
|
+
*/
|
|
4393
|
+
const getDefaultIcon = (params) => {
|
|
4394
|
+
const { type, format, name, isEnum, isArray, size = "sm" } = params;
|
|
4395
|
+
const iconSize = ui.sizes.icon[size];
|
|
4396
|
+
if (format) switch (format) {
|
|
4397
|
+
case "email": return /* @__PURE__ */ jsx(IconMail, { size: iconSize });
|
|
4398
|
+
case "url":
|
|
4399
|
+
case "uri": return /* @__PURE__ */ jsx(IconLink, { size: iconSize });
|
|
4400
|
+
case "tel":
|
|
4401
|
+
case "phone": return /* @__PURE__ */ jsx(IconPhone, { size: iconSize });
|
|
4402
|
+
case "date": return /* @__PURE__ */ jsx(IconCalendar, { size: iconSize });
|
|
4403
|
+
case "date-time": return /* @__PURE__ */ jsx(IconCalendar, { size: iconSize });
|
|
4404
|
+
case "time": return /* @__PURE__ */ jsx(IconClock, { size: iconSize });
|
|
4405
|
+
case "color": return /* @__PURE__ */ jsx(IconColorPicker, { size: iconSize });
|
|
4406
|
+
case "uuid": return /* @__PURE__ */ jsx(IconKey, { size: iconSize });
|
|
4407
|
+
}
|
|
4408
|
+
if (name) {
|
|
4409
|
+
const nameLower = name.toLowerCase();
|
|
4410
|
+
if (nameLower.includes("password") || nameLower.includes("secret")) return /* @__PURE__ */ jsx(IconKey, { size: iconSize });
|
|
4411
|
+
if (nameLower.includes("email") || nameLower.includes("mail")) return /* @__PURE__ */ jsx(IconMail, { size: iconSize });
|
|
4412
|
+
if (nameLower.includes("url") || nameLower.includes("link")) return /* @__PURE__ */ jsx(IconLink, { size: iconSize });
|
|
4413
|
+
if (nameLower.includes("phone") || nameLower.includes("tel")) return /* @__PURE__ */ jsx(IconPhone, { size: iconSize });
|
|
4414
|
+
if (nameLower.includes("color")) return /* @__PURE__ */ jsx(IconPalette, { size: iconSize });
|
|
4415
|
+
if (nameLower.includes("file") || nameLower.includes("upload")) return /* @__PURE__ */ jsx(IconFile, { size: iconSize });
|
|
4416
|
+
if (nameLower.includes("date")) return /* @__PURE__ */ jsx(IconCalendar, { size: iconSize });
|
|
4417
|
+
if (nameLower.includes("time")) return /* @__PURE__ */ jsx(IconClock, { size: iconSize });
|
|
4418
|
+
}
|
|
4419
|
+
if (isEnum || isArray) return /* @__PURE__ */ jsx(IconSelector, { size: iconSize });
|
|
4420
|
+
if (type) switch (type) {
|
|
4421
|
+
case "boolean": return /* @__PURE__ */ jsx(IconToggleLeft, { size: iconSize });
|
|
4422
|
+
case "number":
|
|
4423
|
+
case "integer": return /* @__PURE__ */ jsx(IconHash, { size: iconSize });
|
|
4424
|
+
case "array": return /* @__PURE__ */ jsx(IconList, { size: iconSize });
|
|
4425
|
+
case "string": return /* @__PURE__ */ jsx(IconLetterCase, { size: iconSize });
|
|
4426
|
+
}
|
|
4427
|
+
return /* @__PURE__ */ jsx(IconAt, { size: iconSize });
|
|
4428
|
+
};
|
|
4429
|
+
|
|
4430
|
+
//#endregion
|
|
4431
|
+
//#region ../../src/core/utils/string.ts
|
|
4432
|
+
/**
|
|
4433
|
+
* Capitalizes the first letter of a string.
|
|
4171
4434
|
*
|
|
4172
4435
|
* @example
|
|
4173
|
-
*
|
|
4174
|
-
* const dialog = useDialog();
|
|
4175
|
-
* await dialog.alert({ title: "Alert", message: "This is an alert message" });
|
|
4176
|
-
* const confirmed = await dialog.confirm({ title: "Confirm", message: "Are you sure?" });
|
|
4177
|
-
* const input = await dialog.prompt({ title: "Input", message: "Enter your name:" });
|
|
4178
|
-
* ```
|
|
4436
|
+
* capitalize("hello") // "Hello"
|
|
4179
4437
|
*/
|
|
4180
|
-
const
|
|
4181
|
-
return
|
|
4438
|
+
const capitalize = (str) => {
|
|
4439
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
4440
|
+
};
|
|
4441
|
+
/**
|
|
4442
|
+
* Converts camelCase or snake_case to Title Case with spaces.
|
|
4443
|
+
*
|
|
4444
|
+
* @example
|
|
4445
|
+
* toTitleCase("userName") // "User Name"
|
|
4446
|
+
* toTitleCase("first_name") // "First Name"
|
|
4447
|
+
* toTitleCase("email") // "Email"
|
|
4448
|
+
*/
|
|
4449
|
+
const toTitleCase = (str) => {
|
|
4450
|
+
return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
4451
|
+
};
|
|
4452
|
+
/**
|
|
4453
|
+
* Converts a path or identifier string into a pretty display name.
|
|
4454
|
+
* For paths like "/contacts/0/name", extracts just the field name "Name".
|
|
4455
|
+
* Handles camelCase and snake_case conversion to Title Case.
|
|
4456
|
+
*
|
|
4457
|
+
* @example
|
|
4458
|
+
* prettyName("/userName") // "User Name"
|
|
4459
|
+
* prettyName("/contacts/0/email") // "Email"
|
|
4460
|
+
* prettyName("/address/streetName") // "Street Name"
|
|
4461
|
+
* prettyName("first_name") // "First Name"
|
|
4462
|
+
*/
|
|
4463
|
+
const prettyName = (name) => {
|
|
4464
|
+
const segments = name.split("/").filter((s) => s && !/^\d+$/.test(s));
|
|
4465
|
+
return toTitleCase(segments[segments.length - 1] || name.replaceAll("/", ""));
|
|
4182
4466
|
};
|
|
4183
4467
|
|
|
4184
4468
|
//#endregion
|
|
4185
4469
|
//#region ../../src/core/index.ts
|
|
4186
4470
|
/**
|
|
4187
|
-
* | Stability | Since | Runtime |
|
|
4188
|
-
* |-----------|-------|---------|
|
|
4189
|
-
* | 2 - beta | 0.12.0 | node, bun, workerd, browser|
|
|
4190
|
-
*
|
|
4191
4471
|
* Core UI components based on Mantine UI v8.
|
|
4192
4472
|
*
|
|
4193
4473
|
* **Features:**
|
|
@@ -4223,15 +4503,7 @@ const AlephaUI = $module({
|
|
|
4223
4503
|
alepha.with(ToastService);
|
|
4224
4504
|
}
|
|
4225
4505
|
});
|
|
4226
|
-
/**
|
|
4227
|
-
* Convenience function to configure and inject the UiRouter.
|
|
4228
|
-
*/
|
|
4229
|
-
const $ui = (options = {}) => {
|
|
4230
|
-
const { alepha } = $context();
|
|
4231
|
-
if (options.themes) alepha.store.set(alephaThemeListAtom, options.themes);
|
|
4232
|
-
return alepha.inject(UiRouter);
|
|
4233
|
-
};
|
|
4234
4506
|
|
|
4235
4507
|
//#endregion
|
|
4236
|
-
export { $ui, ActionButton, DashboardShell as AdminShell, DashboardShell, AlephaMantineProvider, AlephaUI, AlertDialog, AppBar, Breadcrumb, BurgerButton, ClipboardButton, ConfirmDialog, Control, ControlArray, ControlDate, ControlNumber, ControlObject, ControlQueryBuilder, ControlSelect, DarkModeButton, DataTable, DialogService, Flex, LanguageButton, OPERATOR_INFO, Omnibar, OmnibarButton, PromptDialog, Sidebar, Text, ThemeButton, ThemeProvider, ToastService,
|
|
4508
|
+
export { $ui, ActionButton, DashboardShell as AdminShell, DashboardShell, AlephaMantineProvider, AlephaUI, AlertDialog, AppBar, Breadcrumb as Breadcrumbs, BurgerButton, ClipboardButton, ConfirmDialog, Container, Control, ControlArray, ControlDate, ControlNumber, ControlObject, ControlQueryBuilder, ControlSelect, DarkModeButton, DataTable, DetailDrawer, DetailList, DialogService, Flex, Heading, JsonViewer, LanguageButton, OPERATOR_INFO, Omnibar, OmnibarButton, PromptDialog, Sidebar, ToggleSidebarButton as SidebarCollapseButton, StatCards, Text, ThemeButton, ThemeProvider, ToastService, TypeForm, UiRouter, alephaSidebarAtom, alephaThemeAtom, alephaThemeListAtom, capitalize, defaultTheme, dialogForm, dialogJson, extractSchemaFields, getDefaultIcon, getOperatorsForField, isComponentType, midnightTheme, prettyName, renderIcon, toTitleCase, ui, useDialog, useTheme, useToast };
|
|
4237
4509
|
//# sourceMappingURL=index.js.map
|