@questpie/admin 3.0.2 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -5
- package/dist/client/blocks/block-renderer.d.mts +2 -2
- package/dist/client/blocks/block-renderer.mjs +4 -1
- package/dist/client/builder/types/action-types.d.mts +31 -3
- package/dist/client/builder/types/collection-types.d.mts +140 -0
- package/dist/client/builder/types/ui-config.d.mts +16 -2
- package/dist/client/builder/types/views.d.mts +57 -0
- package/dist/client/builder/types/widget-types.d.mts +5 -0
- package/dist/client/components/actions/action-button.mjs +137 -199
- package/dist/client/components/actions/action-dialog.mjs +198 -156
- package/dist/client/components/actions/confirmation-dialog.mjs +2 -2
- package/dist/client/components/actions/header-actions.mjs +52 -53
- package/dist/client/components/admin-link.d.mts +2 -2
- package/dist/client/components/auth/auth-loading.mjs +41 -18
- package/dist/client/components/blocks/block-fields-renderer.mjs +64 -28
- package/dist/client/components/blocks/block-insert-button.mjs +4 -4
- package/dist/client/components/blocks/block-item.mjs +2 -2
- package/dist/client/components/blocks/block-library-sidebar.mjs +2 -2
- package/dist/client/components/component-renderer.mjs +1 -1
- package/dist/client/components/fields/array-field.mjs +14 -14
- package/dist/client/components/fields/asset-preview-field.mjs +1 -1
- package/dist/client/components/fields/blocks-field/blocks-field.mjs +84 -104
- package/dist/client/components/fields/json-field.mjs +2 -2
- package/dist/client/components/fields/object-array-field.mjs +22 -22
- package/dist/client/components/fields/object-field.mjs +5 -5
- package/dist/client/components/fields/relation/displays/cards-display.mjs +16 -9
- package/dist/client/components/fields/relation/displays/chips-display.mjs +15 -12
- package/dist/client/components/fields/relation/displays/grid-display.mjs +15 -11
- package/dist/client/components/fields/relation/displays/list-display.mjs +33 -20
- package/dist/client/components/fields/relation/displays/table-display.mjs +62 -93
- package/dist/client/components/fields/relation/relation-items-display.mjs +1 -1
- package/dist/client/components/fields/relation-picker.mjs +7 -6
- package/dist/client/components/fields/relation-select.mjs +71 -47
- package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +392 -82
- package/dist/client/components/fields/rich-text-editor/extensions.mjs +54 -23
- package/dist/client/components/fields/rich-text-editor/image-popover.mjs +24 -50
- package/dist/client/components/fields/rich-text-editor/image-upload.mjs +66 -0
- package/dist/client/components/fields/rich-text-editor/index.d.mts +38 -0
- package/dist/client/components/fields/rich-text-editor/index.mjs +637 -376
- package/dist/client/components/fields/rich-text-editor/link-utils.mjs +26 -0
- package/dist/client/components/fields/rich-text-editor/presets.d.mts +10 -0
- package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +27 -6
- package/dist/client/components/fields/rich-text-editor/toolbar.mjs +464 -346
- package/dist/client/components/fields/rich-text-editor/types.d.mts +77 -0
- package/dist/client/components/fields/upload-field.mjs +45 -49
- package/dist/client/components/filter-builder/columns-tab.mjs +69 -62
- package/dist/client/components/filter-builder/filter-builder-sheet.mjs +473 -308
- package/dist/client/components/filter-builder/filters-tab.mjs +109 -82
- package/dist/client/components/filter-builder/saved-views-tab.mjs +300 -198
- package/dist/client/components/history-sidebar.mjs +850 -340
- package/dist/client/components/layout/field-layout-renderer.mjs +6 -5
- package/dist/client/components/locale-switcher.mjs +8 -8
- package/dist/client/components/media/media-grid.mjs +12 -9
- package/dist/client/components/media/media-picker-dialog.mjs +242 -230
- package/dist/client/components/preview/live-preview-mode.mjs +1 -1
- package/dist/client/components/primitives/asset-preview.mjs +37 -22
- package/dist/client/components/primitives/date-input.mjs +212 -249
- package/dist/client/components/primitives/dropzone.mjs +192 -159
- package/dist/client/components/primitives/field-select-control.mjs +93 -0
- package/dist/client/components/primitives/select-multi.mjs +251 -230
- package/dist/client/components/primitives/select-single.mjs +345 -290
- package/dist/client/components/primitives/time-input.mjs +2 -2
- package/dist/client/components/sheets/resource-sheet.mjs +2 -0
- package/dist/client/components/ui/accordion.mjs +4 -4
- package/dist/client/components/ui/alert.mjs +3 -3
- package/dist/client/components/ui/badge.mjs +4 -4
- package/dist/client/components/ui/button.mjs +47 -37
- package/dist/client/components/ui/card.mjs +2 -2
- package/dist/client/components/ui/checkbox.mjs +1 -1
- package/dist/client/components/ui/command.mjs +5 -5
- package/dist/client/components/ui/dialog.mjs +3 -3
- package/dist/client/components/ui/drawer.mjs +1 -1
- package/dist/client/components/ui/dropdown-menu.mjs +157 -15
- package/dist/client/components/ui/empty-state.mjs +88 -59
- package/dist/client/components/ui/field.mjs +2 -2
- package/dist/client/components/ui/input-group.mjs +3 -3
- package/dist/client/components/ui/input.mjs +1 -1
- package/dist/client/components/ui/kbd.mjs +1 -1
- package/dist/client/components/ui/label.mjs +1 -1
- package/dist/client/components/ui/popover.mjs +19 -11
- package/dist/client/components/ui/scroll-fade.mjs +170 -0
- package/dist/client/components/ui/search-input.mjs +1 -1
- package/dist/client/components/ui/select.mjs +129 -27
- package/dist/client/components/ui/sheet.mjs +54 -34
- package/dist/client/components/ui/sidebar.mjs +15 -14
- package/dist/client/components/ui/skeleton.mjs +28 -12
- package/dist/client/components/ui/switch.mjs +2 -2
- package/dist/client/components/ui/table.mjs +82 -74
- package/dist/client/components/ui/tabs.mjs +26 -31
- package/dist/client/components/ui/textarea.mjs +1 -1
- package/dist/client/components/ui/tooltip.mjs +1 -1
- package/dist/client/components/widgets/chart-widget.mjs +134 -96
- package/dist/client/components/widgets/progress-widget.mjs +59 -34
- package/dist/client/components/widgets/quick-actions-widget.mjs +184 -113
- package/dist/client/components/widgets/recent-items-widget.mjs +144 -102
- package/dist/client/components/widgets/stats-widget.mjs +91 -72
- package/dist/client/components/widgets/table-widget.mjs +159 -246
- package/dist/client/components/widgets/timeline-widget.mjs +66 -43
- package/dist/client/components/widgets/value-widget.mjs +261 -152
- package/dist/client/components/widgets/widget-empty-state.mjs +88 -0
- package/dist/client/components/widgets/widget-skeletons.mjs +53 -20
- package/dist/client/contexts/focus-context.d.mts +2 -2
- package/dist/client/hooks/use-action.mjs +63 -55
- package/dist/client/hooks/use-audit-history.mjs +1 -65
- package/dist/client/hooks/use-collection-validation.mjs +36 -23
- package/dist/client/hooks/use-collection.mjs +96 -1
- package/dist/client/hooks/use-saved-views.mjs +70 -49
- package/dist/client/hooks/use-server-actions.mjs +59 -40
- package/dist/client/hooks/use-server-validation.mjs +156 -41
- package/dist/client/hooks/use-server-widget-data.mjs +1 -1
- package/dist/client/hooks/use-setup-status.d.mts +3 -3
- package/dist/client/hooks/use-setup-status.mjs +2 -2
- package/dist/client/hooks/use-transition-stage.mjs +2 -10
- package/dist/client/hooks/use-validation-error-map.mjs +31 -13
- package/dist/client/hooks/use-view-state.mjs +238 -174
- package/dist/client/i18n/date-locale.mjs +33 -0
- package/dist/client/i18n/hooks.mjs +17 -1
- package/dist/client/lib/utils.mjs +3 -2
- package/dist/client/preview/block-scope-context.d.mts +2 -2
- package/dist/client/preview/preview-banner.d.mts +2 -2
- package/dist/client/preview/preview-field.d.mts +4 -4
- package/dist/client/preview/preview-field.mjs +2 -2
- package/dist/client/runtime/provider.mjs +8 -1
- package/dist/client/runtime/translations-provider.mjs +1 -1
- package/dist/client/scope/picker.d.mts +2 -2
- package/dist/client/scope/provider.d.mts +2 -2
- package/dist/client/styles/base.css +1022 -0
- package/dist/client/styles/index.css +3 -589
- package/dist/client/utils/auto-expand-fields.mjs +4 -2
- package/dist/client/utils/keyboard-shortcuts.mjs +26 -0
- package/dist/client/utils/use-lazy-component.mjs +80 -0
- package/dist/client/views/auth/auth-layout.d.mts +18 -11
- package/dist/client/views/auth/auth-layout.mjs +291 -80
- package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
- package/dist/client/views/auth/forgot-password-form.mjs +2 -2
- package/dist/client/views/auth/login-form.d.mts +2 -2
- package/dist/client/views/auth/login-form.mjs +1 -1
- package/dist/client/views/auth/reset-password-form.d.mts +2 -2
- package/dist/client/views/auth/reset-password-form.mjs +2 -2
- package/dist/client/views/auth/setup-form.d.mts +2 -2
- package/dist/client/views/collection/auto-form-fields.mjs +11 -9
- package/dist/client/views/collection/bulk-action-toolbar.mjs +173 -138
- package/dist/client/views/collection/cells/complex-cells.mjs +22 -22
- package/dist/client/views/collection/cells/primitive-cells.mjs +1 -1
- package/dist/client/views/collection/cells/relation-cells.mjs +147 -129
- package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +224 -278
- package/dist/client/views/collection/cells/shared/relation-chip.mjs +64 -36
- package/dist/client/views/collection/cells/upload-cells.mjs +199 -9
- package/dist/client/views/collection/columns/build-columns.mjs +29 -9
- package/dist/client/views/collection/columns/column-defaults.mjs +2 -2
- package/dist/client/views/collection/field-renderer.mjs +50 -89
- package/dist/client/views/collection/form-view.mjs +237 -227
- package/dist/client/views/collection/table-view.mjs +1162 -229
- package/dist/client/views/collection/view-skeletons.mjs +222 -79
- package/dist/client/views/common/global-search.mjs +29 -18
- package/dist/client/views/dashboard/dashboard-grid.mjs +678 -501
- package/dist/client/views/dashboard/dashboard-widget.mjs +6 -3
- package/dist/client/views/dashboard/widget-card.mjs +23 -14
- package/dist/client/views/globals/global-form-view.mjs +634 -589
- package/dist/client/views/layout/admin-layout-provider.mjs +67 -70
- package/dist/client/views/layout/admin-layout.d.mts +3 -6
- package/dist/client/views/layout/admin-layout.mjs +149 -172
- package/dist/client/views/layout/admin-router.mjs +747 -544
- package/dist/client/views/layout/admin-sidebar.d.mts +38 -1
- package/dist/client/views/layout/admin-sidebar.mjs +751 -591
- package/dist/client/views/layout/admin-theme.d.mts +10 -0
- package/dist/client/views/layout/admin-theme.mjs +84 -0
- package/dist/client/views/layout/admin-view-layout.mjs +161 -0
- package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
- package/dist/client/views/pages/accept-invite-page.mjs +49 -26
- package/dist/client/views/pages/dashboard-page.d.mts +2 -2
- package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
- package/dist/client/views/pages/forgot-password-page.mjs +2 -19
- package/dist/client/views/pages/invite-page.d.mts +2 -2
- package/dist/client/views/pages/invite-page.mjs +2 -19
- package/dist/client/views/pages/login-page.d.mts +3 -3
- package/dist/client/views/pages/login-page.mjs +4 -21
- package/dist/client/views/pages/reset-password-page.d.mts +2 -2
- package/dist/client/views/pages/reset-password-page.mjs +3 -20
- package/dist/client/views/pages/setup-page.d.mts +2 -2
- package/dist/client/views/pages/setup-page.mjs +3 -20
- package/dist/client.d.mts +6 -2
- package/dist/client.mjs +2 -1
- package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
- package/dist/index.d.mts +6 -2
- package/dist/index.mjs +2 -1
- package/dist/server/augmentation/dashboard.d.mts +67 -3
- package/dist/server/augmentation/form-layout.d.mts +21 -0
- package/dist/server/augmentation/index.d.mts +1 -1
- package/dist/server/codegen/admin-client-template.mjs +4 -0
- package/dist/server/fields/blocks.d.mts +1 -1
- package/dist/server/fields/blocks.mjs +12 -0
- package/dist/server/fields/rich-text.d.mts +1 -1
- package/dist/server/fields/rich-text.mjs +8 -0
- package/dist/server/i18n/index.mjs +17 -1
- package/dist/server/i18n/messages/cs.mjs +23 -0
- package/dist/server/i18n/messages/de.mjs +23 -0
- package/dist/server/i18n/messages/en.mjs +64 -1
- package/dist/server/i18n/messages/es.mjs +23 -0
- package/dist/server/i18n/messages/fr.mjs +23 -0
- package/dist/server/i18n/messages/pl.mjs +23 -0
- package/dist/server/i18n/messages/pt.mjs +23 -0
- package/dist/server/i18n/messages/sk.mjs +83 -1
- package/dist/server/modules/admin/block/introspection.mjs +4 -1
- package/dist/server/modules/admin/block/prefetch.mjs +12 -2
- package/dist/server/modules/admin/collections/account.d.mts +50 -50
- package/dist/server/modules/admin/collections/admin-locks.d.mts +54 -54
- package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
- package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
- package/dist/server/modules/admin/collections/apikey.d.mts +64 -64
- package/dist/server/modules/admin/collections/assets.d.mts +20 -20
- package/dist/server/modules/admin/collections/assets.mjs +0 -1
- package/dist/server/modules/admin/collections/session.d.mts +42 -42
- package/dist/server/modules/admin/collections/user.d.mts +40 -28
- package/dist/server/modules/admin/collections/user.mjs +40 -9
- package/dist/server/modules/admin/collections/verification.d.mts +36 -36
- package/dist/server/modules/admin/dto/admin-config.dto.mjs +2 -0
- package/dist/server/modules/admin/factories.mjs +7 -18
- package/dist/server/modules/admin/index.d.mts +1 -1
- package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
- package/dist/server/modules/admin/routes/admin-config.mjs +34 -16
- package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
- package/dist/server/modules/admin/routes/execute-action.mjs +33 -0
- package/dist/server/modules/admin/routes/locales.d.mts +2 -2
- package/dist/server/modules/admin/routes/preview.d.mts +11 -11
- package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
- package/dist/server/modules/admin/routes/setup.d.mts +10 -10
- package/dist/server/modules/admin/routes/setup.mjs +7 -7
- package/dist/server/modules/admin/routes/translations.d.mts +4 -4
- package/dist/server/modules/admin/routes/translations.mjs +5 -1
- package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
- package/dist/server/modules/admin-preferences/collections/admin-preferences.mjs +1 -1
- package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +25 -25
- package/dist/server/modules/audit/.generated/module.d.mts +7 -7
- package/dist/server/modules/audit/.generated/module.mjs +1 -1
- package/dist/server/modules/audit/collections/audit-log.d.mts +39 -39
- package/dist/server/modules/audit/collections/audit-log.mjs +1 -1
- package/dist/server/modules/audit/config/app.mjs +99 -42
- package/dist/server/modules/audit/jobs/audit-cleanup.mjs +1 -1
- package/dist/server/plugin.mjs +4 -2
- package/dist/server/proxy-factories.d.mts +4 -3
- package/dist/server/proxy-factories.mjs +34 -8
- package/dist/shared/types/saved-views.types.d.mts +2 -0
- package/package.json +6 -4
- package/dist/client/components/fields/rich-text-editor/link-popover.mjs +0 -85
- package/dist/client/components/ui/spinner.mjs +0 -52
- package/dist/client/components/ui/toolbar.mjs +0 -136
- package/dist/client/contexts/breadcrumb-context.mjs +0 -60
- package/dist/client/views/layout/admin-topbar.mjs +0 -236
|
@@ -1,590 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
@import "shadcn/tailwind.css";
|
|
4
|
-
@import "@fontsource-variable/geist";
|
|
5
|
-
@import "@fontsource-variable/jetbrains-mono";
|
|
1
|
+
/* QUESTPIE Admin — Default stylesheet
|
|
2
|
+
Alias for base.css. Import base.css directly for explicit intent. */
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
QUESTPIE ADMIN THEME — Brutalist Flat
|
|
9
|
-
================================================================
|
|
10
|
-
|
|
11
|
-
HOW THEMING WORKS
|
|
12
|
-
-----------------
|
|
13
|
-
This file is the ONLY place that controls the visual appearance
|
|
14
|
-
of the admin UI. Components use standard Tailwind utilities
|
|
15
|
-
(bg-card, border-border, rounded-md, shadow-sm) which resolve
|
|
16
|
-
to the values defined here.
|
|
17
|
-
|
|
18
|
-
TO CREATE A CUSTOM THEME
|
|
19
|
-
------------------------
|
|
20
|
-
1. Copy this file
|
|
21
|
-
2. Change the variable values below
|
|
22
|
-
3. Import your copy instead of this one
|
|
23
|
-
4. That's it — zero component changes needed
|
|
24
|
-
|
|
25
|
-
VARIABLE REFERENCE
|
|
26
|
-
------------------
|
|
27
|
-
|
|
28
|
-
-- Surface Colors -----------------------------------------
|
|
29
|
-
--background Page background (darkest/lightest surface)
|
|
30
|
-
--foreground Primary text color on background
|
|
31
|
-
--card Elevated surface: cards, panels, sidebar
|
|
32
|
-
--card-foreground Text on card surfaces
|
|
33
|
-
--popover Floating surfaces: dropdowns, tooltips, dialogs
|
|
34
|
-
--popover-foreground Text on floating surfaces
|
|
35
|
-
--input Form input backgrounds
|
|
36
|
-
--muted Subtle backgrounds: hover, table headers, toggles
|
|
37
|
-
--muted-foreground Secondary/dimmed text (helper text, placeholders)
|
|
38
|
-
--accent Interactive hover backgrounds
|
|
39
|
-
--accent-foreground Text on accent backgrounds
|
|
40
|
-
|
|
41
|
-
-- Brand Colors -------------------------------------------
|
|
42
|
-
--primary Brand accent: CTAs, focus rings, active states
|
|
43
|
-
--primary-foreground Text on primary color backgrounds
|
|
44
|
-
--secondary Secondary action backgrounds
|
|
45
|
-
--secondary-foreground Text on secondary backgrounds
|
|
46
|
-
|
|
47
|
-
-- Semantic Colors ----------------------------------------
|
|
48
|
-
--destructive Errors, delete actions, danger states
|
|
49
|
-
--success Confirmations, positive states
|
|
50
|
-
--warning Caution states
|
|
51
|
-
--info Informational emphasis
|
|
52
|
-
|
|
53
|
-
-- Structure ----------------------------------------------
|
|
54
|
-
--border Default border color (all structural borders)
|
|
55
|
-
--ring Focus ring color (usually same as --primary)
|
|
56
|
-
|
|
57
|
-
-- Sidebar ------------------------------------------------
|
|
58
|
-
Separate tokens for sidebar to allow independent theming.
|
|
59
|
-
--sidebar, --sidebar-foreground, --sidebar-primary,
|
|
60
|
-
--sidebar-accent, --sidebar-border, --sidebar-ring, etc.
|
|
61
|
-
|
|
62
|
-
-- Shape & Depth ------------------------------------------
|
|
63
|
-
--radius Base border-radius
|
|
64
|
-
0 -> brutalist sharp corners
|
|
65
|
-
8px -> soft rounded corners
|
|
66
|
-
--shadow-* Shadow scale (defined in @theme inline)
|
|
67
|
-
none -> brutalist flat (no elevation)
|
|
68
|
-
normal -> standard shadow depth
|
|
69
|
-
|
|
70
|
-
-- Typography ---------------------------------------------
|
|
71
|
-
--font-sans Body text, descriptions, user content
|
|
72
|
-
--font-mono UI chrome: nav, buttons, tabs, badges, labels
|
|
73
|
-
|
|
74
|
-
-- Spacing ------------------------------------------------
|
|
75
|
-
--spacing-card Internal card/panel padding (default: 16px)
|
|
76
|
-
--spacing-section Section gaps (default: 24px)
|
|
77
|
-
--spacing-input Input internal padding (default: 12px)
|
|
78
|
-
|
|
79
|
-
-- Grid Texture -------------------------------------------
|
|
80
|
-
Controlled via body::before pseudo-element.
|
|
81
|
-
Uses --primary color, 40px grid, 3% opacity.
|
|
82
|
-
To disable: set body::before { display: none }
|
|
83
|
-
================================================================ */
|
|
84
|
-
|
|
85
|
-
/* Light theme (default — :root)
|
|
86
|
-
All colors use OKLCH for perceptually uniform contrast management.
|
|
87
|
-
L = lightness (0–1), C = chroma (saturation), H = hue angle. */
|
|
88
|
-
:root {
|
|
89
|
-
--background: oklch(1 0 0);
|
|
90
|
-
--foreground: oklch(0.269 0 0);
|
|
91
|
-
--card: oklch(0.98 0 0);
|
|
92
|
-
--card-foreground: oklch(0.269 0 0);
|
|
93
|
-
--popover: oklch(1 0 0);
|
|
94
|
-
--popover-foreground: oklch(0.269 0 0);
|
|
95
|
-
--input: oklch(0.922 0 0);
|
|
96
|
-
--muted: oklch(0.955 0 0);
|
|
97
|
-
--muted-foreground: oklch(0.48 0 0);
|
|
98
|
-
--accent: oklch(0.955 0 0);
|
|
99
|
-
--accent-foreground: oklch(0.145 0 0);
|
|
100
|
-
--secondary: oklch(0.955 0 0);
|
|
101
|
-
--secondary-foreground: oklch(0.269 0 0);
|
|
102
|
-
--primary: oklch(0.541 0.281 303.5);
|
|
103
|
-
--primary-foreground: oklch(1 0 0);
|
|
104
|
-
--destructive: oklch(0.637 0.237 25);
|
|
105
|
-
--destructive-foreground: oklch(1 0 0);
|
|
106
|
-
--success: oklch(0.7 0.2 155);
|
|
107
|
-
--success-foreground: oklch(1 0 0);
|
|
108
|
-
--warning: oklch(0.7 0.16 65);
|
|
109
|
-
--warning-foreground: oklch(1 0 0);
|
|
110
|
-
--info: oklch(0.6 0.16 240);
|
|
111
|
-
--info-foreground: oklch(1 0 0);
|
|
112
|
-
--border: oklch(0.922 0 0);
|
|
113
|
-
--ring: oklch(0.541 0.281 303.5);
|
|
114
|
-
--radius: 0px;
|
|
115
|
-
--grid-opacity: 0.025;
|
|
116
|
-
|
|
117
|
-
/* Chart Colors */
|
|
118
|
-
--chart-1: oklch(0.541 0.281 303.5);
|
|
119
|
-
--chart-2: oklch(0.7 0.2 155);
|
|
120
|
-
--chart-3: oklch(0.6 0.16 240);
|
|
121
|
-
--chart-4: oklch(0.7 0.16 65);
|
|
122
|
-
--chart-5: oklch(0.637 0.237 25);
|
|
123
|
-
|
|
124
|
-
/* Typography */
|
|
125
|
-
--font-sans: "Geist Variable", "Inter", sans-serif;
|
|
126
|
-
--font-mono: "JetBrains Mono Variable", "JetBrains Mono", ui-monospace, monospace;
|
|
127
|
-
|
|
128
|
-
/* Spacing Scale */
|
|
129
|
-
--spacing-section: 1.5rem;
|
|
130
|
-
--spacing-card: 1rem;
|
|
131
|
-
--spacing-input: 0.75rem;
|
|
132
|
-
|
|
133
|
-
/* Sidebar */
|
|
134
|
-
--sidebar: oklch(0.975 0 0);
|
|
135
|
-
--sidebar-foreground: oklch(0.269 0 0);
|
|
136
|
-
--sidebar-primary: oklch(0.541 0.281 303.5);
|
|
137
|
-
--sidebar-primary-foreground: oklch(1 0 0);
|
|
138
|
-
--sidebar-accent: oklch(0.955 0 0);
|
|
139
|
-
--sidebar-accent-foreground: oklch(0.269 0 0);
|
|
140
|
-
--sidebar-border: oklch(0.922 0 0);
|
|
141
|
-
--sidebar-ring: oklch(0.541 0.281 303.5);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/* Dark theme (.dark class) */
|
|
145
|
-
.dark {
|
|
146
|
-
--background: oklch(0.145 0 0);
|
|
147
|
-
--foreground: oklch(0.922 0 0);
|
|
148
|
-
--card: oklch(0.205 0 0);
|
|
149
|
-
--card-foreground: oklch(0.922 0 0);
|
|
150
|
-
--popover: oklch(0.205 0 0);
|
|
151
|
-
--popover-foreground: oklch(0.922 0 0);
|
|
152
|
-
--muted: oklch(0.269 0 0);
|
|
153
|
-
--muted-foreground: oklch(0.637 0 0);
|
|
154
|
-
--accent: oklch(0.269 0 0);
|
|
155
|
-
--accent-foreground: oklch(1 0 0);
|
|
156
|
-
--secondary: oklch(0.269 0 0);
|
|
157
|
-
--secondary-foreground: oklch(0.922 0 0);
|
|
158
|
-
--destructive: oklch(0.637 0.237 25);
|
|
159
|
-
--destructive-foreground: oklch(1 0 0);
|
|
160
|
-
--border: oklch(0.371 0 0);
|
|
161
|
-
--input: oklch(0.371 0 0);
|
|
162
|
-
--ring: oklch(0.541 0.281 303.5);
|
|
163
|
-
--success: oklch(0.765 0.219 155);
|
|
164
|
-
--success-foreground: oklch(1 0 0);
|
|
165
|
-
--warning: oklch(0.793 0.155 82);
|
|
166
|
-
--warning-foreground: oklch(0.145 0 0);
|
|
167
|
-
--info: oklch(0.77 0.119 222);
|
|
168
|
-
--info-foreground: oklch(0.145 0 0);
|
|
169
|
-
--grid-opacity: 0.06;
|
|
170
|
-
|
|
171
|
-
/* Chart Colors */
|
|
172
|
-
--chart-1: oklch(0.541 0.281 303.5);
|
|
173
|
-
--chart-2: oklch(0.765 0.219 155);
|
|
174
|
-
--chart-3: oklch(0.77 0.119 222);
|
|
175
|
-
--chart-4: oklch(0.793 0.155 82);
|
|
176
|
-
--chart-5: oklch(0.637 0.237 25);
|
|
177
|
-
|
|
178
|
-
/* Sidebar */
|
|
179
|
-
--sidebar: oklch(0.205 0 0);
|
|
180
|
-
--sidebar-foreground: oklch(0.922 0 0);
|
|
181
|
-
--sidebar-primary: oklch(0.541 0.281 303.5);
|
|
182
|
-
--sidebar-primary-foreground: oklch(1 0 0);
|
|
183
|
-
--sidebar-accent: oklch(0.269 0 0);
|
|
184
|
-
--sidebar-accent-foreground: oklch(0.922 0 0);
|
|
185
|
-
--sidebar-border: oklch(0.371 0 0);
|
|
186
|
-
--sidebar-ring: oklch(0.541 0.281 303.5);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
@theme inline {
|
|
190
|
-
/* Typography */
|
|
191
|
-
--font-sans: "Geist Variable", "Inter", sans-serif;
|
|
192
|
-
--font-mono:
|
|
193
|
-
"JetBrains Mono Variable", "JetBrains Mono", ui-monospace, monospace;
|
|
194
|
-
|
|
195
|
-
/* Shadow scale: none for brutalist flat */
|
|
196
|
-
--shadow-xs: none;
|
|
197
|
-
--shadow-sm: none;
|
|
198
|
-
--shadow: none;
|
|
199
|
-
--shadow-md: none;
|
|
200
|
-
--shadow-lg: none;
|
|
201
|
-
--shadow-xl: none;
|
|
202
|
-
--shadow-2xl: none;
|
|
203
|
-
|
|
204
|
-
/* Radius: all resolve to --radius (except full for avatars/pills) */
|
|
205
|
-
--radius-sm: var(--radius);
|
|
206
|
-
--radius-md: var(--radius);
|
|
207
|
-
--radius-lg: var(--radius);
|
|
208
|
-
--radius-xl: var(--radius);
|
|
209
|
-
--radius-2xl: var(--radius);
|
|
210
|
-
--radius-3xl: var(--radius);
|
|
211
|
-
--radius-4xl: var(--radius);
|
|
212
|
-
--radius-full: 9999px;
|
|
213
|
-
|
|
214
|
-
/* Color mappings */
|
|
215
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
216
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
217
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
218
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
219
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
220
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
221
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
222
|
-
--color-sidebar: var(--sidebar);
|
|
223
|
-
--color-chart-5: var(--chart-5);
|
|
224
|
-
--color-chart-4: var(--chart-4);
|
|
225
|
-
--color-chart-3: var(--chart-3);
|
|
226
|
-
--color-chart-2: var(--chart-2);
|
|
227
|
-
--color-chart-1: var(--chart-1);
|
|
228
|
-
--color-ring: var(--ring);
|
|
229
|
-
--color-input: var(--input);
|
|
230
|
-
--color-border: var(--border);
|
|
231
|
-
--color-destructive: var(--destructive);
|
|
232
|
-
--color-destructive-foreground: var(--destructive-foreground);
|
|
233
|
-
--color-success: var(--success);
|
|
234
|
-
--color-success-foreground: var(--success-foreground);
|
|
235
|
-
--color-warning: var(--warning);
|
|
236
|
-
--color-warning-foreground: var(--warning-foreground);
|
|
237
|
-
--color-info: var(--info);
|
|
238
|
-
--color-info-foreground: var(--info-foreground);
|
|
239
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
240
|
-
--color-accent: var(--accent);
|
|
241
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
242
|
-
--color-muted: var(--muted);
|
|
243
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
244
|
-
--color-secondary: var(--secondary);
|
|
245
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
246
|
-
--color-primary: var(--primary);
|
|
247
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
248
|
-
--color-popover: var(--popover);
|
|
249
|
-
--color-card-foreground: var(--card-foreground);
|
|
250
|
-
--color-card: var(--card);
|
|
251
|
-
--color-foreground: var(--foreground);
|
|
252
|
-
--color-background: var(--background);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/* =============================================================================
|
|
256
|
-
Grid Texture (matches landing page)
|
|
257
|
-
============================================================================= */
|
|
258
|
-
|
|
259
|
-
body::before {
|
|
260
|
-
content: "";
|
|
261
|
-
position: fixed;
|
|
262
|
-
inset: 0;
|
|
263
|
-
z-index: 0;
|
|
264
|
-
pointer-events: none;
|
|
265
|
-
background-image:
|
|
266
|
-
linear-gradient(var(--primary) 1px, transparent 1px),
|
|
267
|
-
linear-gradient(90deg, var(--primary) 1px, transparent 1px);
|
|
268
|
-
background-size: 40px 40px;
|
|
269
|
-
opacity: var(--grid-opacity, 0.025);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/* =============================================================================
|
|
273
|
-
Rich Text Editor Styles
|
|
274
|
-
============================================================================= */
|
|
275
|
-
|
|
276
|
-
.qp-rich-text-editor__content {
|
|
277
|
-
min-height: 200px;
|
|
278
|
-
padding: 0.75rem;
|
|
279
|
-
outline: none;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
.qp-rich-text-editor__content > *:first-child {
|
|
283
|
-
margin-top: 0;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
.qp-rich-text-editor__content > *:last-child {
|
|
287
|
-
margin-bottom: 0;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
.qp-rich-text-editor__content p {
|
|
291
|
-
margin: 0 0 0.75rem;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
.qp-rich-text-editor__content h1 {
|
|
295
|
-
font-size: 1.5rem;
|
|
296
|
-
font-weight: 600;
|
|
297
|
-
margin: 1rem 0 0.75rem;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
.qp-rich-text-editor__content h2 {
|
|
301
|
-
font-size: 1.25rem;
|
|
302
|
-
font-weight: 600;
|
|
303
|
-
margin: 1rem 0 0.75rem;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.qp-rich-text-editor__content h3 {
|
|
307
|
-
font-size: 1.125rem;
|
|
308
|
-
font-weight: 600;
|
|
309
|
-
margin: 1rem 0 0.75rem;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
.qp-rich-text-editor__content ul,
|
|
313
|
-
.qp-rich-text-editor__content ol {
|
|
314
|
-
padding-left: 1.5rem;
|
|
315
|
-
margin: 0.75rem 0;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
.qp-rich-text-editor__content blockquote {
|
|
319
|
-
border-left: 2px solid var(--border);
|
|
320
|
-
padding-left: 0.75rem;
|
|
321
|
-
color: var(--muted-foreground);
|
|
322
|
-
margin: 0.75rem 0;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
.qp-rich-text-editor__content code {
|
|
326
|
-
background: var(--muted);
|
|
327
|
-
padding: 0.1rem 0.25rem;
|
|
328
|
-
font-size: 0.875em;
|
|
329
|
-
font-family: var(--font-mono);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.qp-rich-text-editor__content pre {
|
|
333
|
-
background: var(--muted);
|
|
334
|
-
padding: 0.75rem;
|
|
335
|
-
overflow-x: auto;
|
|
336
|
-
font-family: var(--font-mono);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
.qp-rich-text-editor__content hr {
|
|
340
|
-
border: none;
|
|
341
|
-
border-top: 1px solid var(--border);
|
|
342
|
-
margin: 1rem 0;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
.qp-rich-text-editor__content table {
|
|
346
|
-
border-collapse: collapse;
|
|
347
|
-
margin: 1rem 0;
|
|
348
|
-
width: 100%;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.qp-rich-text-editor__content th,
|
|
352
|
-
.qp-rich-text-editor__content td {
|
|
353
|
-
border: 1px solid var(--border);
|
|
354
|
-
padding: 0.5rem;
|
|
355
|
-
text-align: left;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
.tippy-box[data-theme~="qp-rich-text-editor"] {
|
|
359
|
-
background: var(--popover);
|
|
360
|
-
color: var(--popover-foreground);
|
|
361
|
-
border: 1px solid var(--border);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.qp-rich-text-editor__slash {
|
|
365
|
-
display: flex;
|
|
366
|
-
flex-direction: column;
|
|
367
|
-
gap: 0.25rem;
|
|
368
|
-
padding: 0.5rem;
|
|
369
|
-
min-width: 220px;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
.qp-rich-text-editor__slash-item {
|
|
373
|
-
display: flex;
|
|
374
|
-
flex-direction: column;
|
|
375
|
-
align-items: flex-start;
|
|
376
|
-
gap: 0.125rem;
|
|
377
|
-
padding: 0.5rem;
|
|
378
|
-
font-size: 0.75rem;
|
|
379
|
-
line-height: 1.2;
|
|
380
|
-
color: var(--foreground);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
.qp-rich-text-editor__slash-item--active,
|
|
384
|
-
.qp-rich-text-editor__slash-item:hover {
|
|
385
|
-
background: var(--muted);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
.qp-rich-text-editor__slash-title {
|
|
389
|
-
font-weight: 600;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
.qp-rich-text-editor__slash-description {
|
|
393
|
-
color: var(--muted-foreground);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
.qp-rich-text-editor__slash-empty {
|
|
397
|
-
padding: 0.5rem;
|
|
398
|
-
font-size: 0.75rem;
|
|
399
|
-
color: var(--muted-foreground);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/* =============================================================================
|
|
403
|
-
Base Styles
|
|
404
|
-
============================================================================= */
|
|
405
|
-
|
|
406
|
-
@layer base {
|
|
407
|
-
* {
|
|
408
|
-
@apply border-border outline-ring/50;
|
|
409
|
-
}
|
|
410
|
-
body {
|
|
411
|
-
@apply bg-background text-foreground;
|
|
412
|
-
font-family: var(--font-sans);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/* =============================================================================
|
|
417
|
-
Custom Scrollbar Styles
|
|
418
|
-
============================================================================= */
|
|
419
|
-
|
|
420
|
-
@utility scrollbar-thin {
|
|
421
|
-
scrollbar-width: thin;
|
|
422
|
-
scrollbar-color: color-mix(in oklch, var(--border) 50%, transparent)
|
|
423
|
-
transparent;
|
|
424
|
-
|
|
425
|
-
&::-webkit-scrollbar {
|
|
426
|
-
width: 6px;
|
|
427
|
-
height: 6px;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
&::-webkit-scrollbar-track {
|
|
431
|
-
background: transparent;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
&::-webkit-scrollbar-thumb {
|
|
435
|
-
background: color-mix(in oklch, var(--border) 60%, transparent);
|
|
436
|
-
border-radius: 3px;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
&::-webkit-scrollbar-thumb:hover {
|
|
440
|
-
background: var(--border);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
&::-webkit-scrollbar-corner {
|
|
444
|
-
background: transparent;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
/* =============================================================================
|
|
449
|
-
Field Focus Animation
|
|
450
|
-
============================================================================= */
|
|
451
|
-
|
|
452
|
-
@keyframes field-glow {
|
|
453
|
-
0%,
|
|
454
|
-
100% {
|
|
455
|
-
background-color: transparent;
|
|
456
|
-
}
|
|
457
|
-
50% {
|
|
458
|
-
background-color: color-mix(in oklch, var(--primary) 8%, transparent);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
.animate-field-glow {
|
|
463
|
-
animation: field-glow 2s ease-in-out;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/* =============================================================================
|
|
467
|
-
Realtime Highlight Animation
|
|
468
|
-
============================================================================= */
|
|
469
|
-
|
|
470
|
-
@keyframes realtime-pulse {
|
|
471
|
-
0% {
|
|
472
|
-
border-left-color: var(--primary);
|
|
473
|
-
}
|
|
474
|
-
100% {
|
|
475
|
-
border-left-color: transparent;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
.animate-realtime-pulse {
|
|
480
|
-
border-left: 3px solid transparent;
|
|
481
|
-
animation: realtime-pulse 1.5s ease-out;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
/* Delete animation - red pulse + fade out */
|
|
485
|
-
@keyframes realtime-delete {
|
|
486
|
-
0% {
|
|
487
|
-
background-color: color-mix(in oklch, var(--destructive) 25%, transparent);
|
|
488
|
-
opacity: 1;
|
|
489
|
-
}
|
|
490
|
-
70% {
|
|
491
|
-
background-color: color-mix(in oklch, var(--destructive) 15%, transparent);
|
|
492
|
-
opacity: 0.7;
|
|
493
|
-
}
|
|
494
|
-
100% {
|
|
495
|
-
background-color: color-mix(in oklch, var(--destructive) 10%, transparent);
|
|
496
|
-
opacity: 0;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
.animate-realtime-delete {
|
|
501
|
-
animation: realtime-delete 1.5s ease-out forwards;
|
|
502
|
-
pointer-events: none;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
/* =============================================================================
|
|
506
|
-
Reduced Motion — Respect user's motion preferences (WCAG 2.1 AA)
|
|
507
|
-
============================================================================= */
|
|
508
|
-
|
|
509
|
-
@media (prefers-reduced-motion: reduce) {
|
|
510
|
-
*,
|
|
511
|
-
*::before,
|
|
512
|
-
*::after {
|
|
513
|
-
animation-duration: 0.01ms !important;
|
|
514
|
-
animation-iteration-count: 1 !important;
|
|
515
|
-
transition-duration: 0.01ms !important;
|
|
516
|
-
scroll-behavior: auto !important;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
.animate-field-glow,
|
|
520
|
-
.animate-realtime-pulse,
|
|
521
|
-
.animate-realtime-delete,
|
|
522
|
-
.animate-spin {
|
|
523
|
-
animation: none !important;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
/* =============================================================================
|
|
528
|
-
High Contrast — Improve visibility for users needing more contrast
|
|
529
|
-
============================================================================= */
|
|
530
|
-
|
|
531
|
-
@media (prefers-contrast: more) {
|
|
532
|
-
:root {
|
|
533
|
-
--muted-foreground: oklch(0.37 0 0);
|
|
534
|
-
--border: oklch(0.66 0 0);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
.dark {
|
|
538
|
-
--muted-foreground: oklch(0.73 0 0);
|
|
539
|
-
--border: oklch(0.56 0 0);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/* =============================================================================
|
|
544
|
-
Focus Visible — Enhanced focus styles for keyboard navigation
|
|
545
|
-
============================================================================= */
|
|
546
|
-
|
|
547
|
-
@layer base {
|
|
548
|
-
:focus-visible {
|
|
549
|
-
outline: 2px solid var(--ring);
|
|
550
|
-
outline-offset: 2px;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/* Skip link styles */
|
|
554
|
-
[href="#main-content"]:focus {
|
|
555
|
-
clip: auto;
|
|
556
|
-
clip-path: none;
|
|
557
|
-
height: auto;
|
|
558
|
-
width: auto;
|
|
559
|
-
overflow: visible;
|
|
560
|
-
white-space: nowrap;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
/* Field focus pulse animation (preview click-to-focus) */
|
|
564
|
-
@keyframes field-focus-pulse {
|
|
565
|
-
0% {
|
|
566
|
-
box-shadow: 0 0 0 0 var(--primary);
|
|
567
|
-
}
|
|
568
|
-
50% {
|
|
569
|
-
box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 30%, transparent);
|
|
570
|
-
}
|
|
571
|
-
100% {
|
|
572
|
-
box-shadow: 0 0 0 0 transparent;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
.field-focus-pulse {
|
|
577
|
-
animation: field-focus-pulse 0.6s ease-out;
|
|
578
|
-
border-radius: var(--radius);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
iconify-icon {
|
|
584
|
-
display: inline-block;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
iconify-icon:not([width]) {
|
|
588
|
-
width: 1em;
|
|
589
|
-
height: 1em;
|
|
590
|
-
}
|
|
4
|
+
@import "./base.css";
|
|
@@ -56,8 +56,10 @@ function autoExpandFields(config) {
|
|
|
56
56
|
const fieldDef = config.fields?.[fieldName];
|
|
57
57
|
if (fieldDef) {
|
|
58
58
|
const fieldType = fieldDef.name;
|
|
59
|
-
if (fieldType === "upload" || fieldType === "uploadMany")
|
|
60
|
-
|
|
59
|
+
if (fieldType === "upload" || fieldType === "uploadMany") {
|
|
60
|
+
const relationName = fieldDef["~options"]?.relationName ?? fieldName;
|
|
61
|
+
if (relationName) withFields[relationName] = true;
|
|
62
|
+
} else if (fieldType === "relation") {
|
|
61
63
|
const relationName = fieldDef["~options"]?.relationName ?? fieldName;
|
|
62
64
|
const nestedAvatarRelation = getNestedAvatarRelation(fieldDef);
|
|
63
65
|
const knownRelations = config.relations;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/client/utils/keyboard-shortcuts.ts
|
|
2
|
+
function isModifierShortcut(event) {
|
|
3
|
+
return event.metaKey || event.ctrlKey;
|
|
4
|
+
}
|
|
5
|
+
function isEditableShortcutTarget(target) {
|
|
6
|
+
if (!(target instanceof Element)) return false;
|
|
7
|
+
return Boolean(target.closest([
|
|
8
|
+
"input",
|
|
9
|
+
"textarea",
|
|
10
|
+
"select",
|
|
11
|
+
"[contenteditable='true']",
|
|
12
|
+
"[role='textbox']",
|
|
13
|
+
".ProseMirror",
|
|
14
|
+
"[data-admin-rich-text-editor]"
|
|
15
|
+
].join(",")));
|
|
16
|
+
}
|
|
17
|
+
function shouldHandleAdminShortcut(event, options) {
|
|
18
|
+
if (event.defaultPrevented) return false;
|
|
19
|
+
if (!isModifierShortcut(event)) return false;
|
|
20
|
+
if (event.key.toLowerCase() !== options.key.toLowerCase()) return false;
|
|
21
|
+
if (!options.allowEditableTarget && isEditableShortcutTarget(event.target)) return false;
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { isModifierShortcut, shouldHandleAdminShortcut };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/client/utils/use-lazy-component.ts
|
|
4
|
+
/**
|
|
5
|
+
* Shared lazy component resolution helper.
|
|
6
|
+
*
|
|
7
|
+
* Handles three `MaybeLazyComponent` forms:
|
|
8
|
+
* - `React.ComponentType` — used directly, no async
|
|
9
|
+
* - `React.lazy(...)` — exotic component, used directly
|
|
10
|
+
* - `() => import(...)` — dynamic loader, resolved async
|
|
11
|
+
*
|
|
12
|
+
* @internal Not part of the public API.
|
|
13
|
+
*/
|
|
14
|
+
function isLazyLoader(loader, allowDynamicImportLoaders) {
|
|
15
|
+
if (!allowDynamicImportLoaders) return false;
|
|
16
|
+
return typeof loader === "function" && !loader.prototype?.render && !loader.prototype?.isReactComponent && loader.length === 0 && !loader.$$typeof;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a MaybeLazyComponent to a concrete React component.
|
|
20
|
+
*
|
|
21
|
+
* Returns `{ Component, loading }`:
|
|
22
|
+
* - `loading: true` while a lazy loader is in-flight
|
|
23
|
+
* - `Component: null` if loader is undefined or failed to resolve
|
|
24
|
+
* - Falls back to null on error (callers should fall back to built-in)
|
|
25
|
+
*/
|
|
26
|
+
function useLazyComponent(loader, options = {}) {
|
|
27
|
+
const { allowDynamicImportLoaders = true } = options;
|
|
28
|
+
const [state, setState] = React.useState(() => {
|
|
29
|
+
if (!loader) return {
|
|
30
|
+
Component: null,
|
|
31
|
+
loading: false
|
|
32
|
+
};
|
|
33
|
+
if (!isLazyLoader(loader, allowDynamicImportLoaders)) return {
|
|
34
|
+
Component: loader,
|
|
35
|
+
loading: false
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
Component: null,
|
|
39
|
+
loading: true
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
if (!loader) {
|
|
44
|
+
setState({
|
|
45
|
+
Component: null,
|
|
46
|
+
loading: false
|
|
47
|
+
});
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!isLazyLoader(loader, allowDynamicImportLoaders)) {
|
|
51
|
+
setState({
|
|
52
|
+
Component: loader,
|
|
53
|
+
loading: false
|
|
54
|
+
});
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
let mounted = true;
|
|
58
|
+
(async () => {
|
|
59
|
+
try {
|
|
60
|
+
const result = await loader();
|
|
61
|
+
if (mounted) setState({
|
|
62
|
+
Component: result.default || result,
|
|
63
|
+
loading: false
|
|
64
|
+
});
|
|
65
|
+
} catch {
|
|
66
|
+
if (mounted) setState({
|
|
67
|
+
Component: null,
|
|
68
|
+
loading: false
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
})();
|
|
72
|
+
return () => {
|
|
73
|
+
mounted = false;
|
|
74
|
+
};
|
|
75
|
+
}, [allowDynamicImportLoaders, loader]);
|
|
76
|
+
return state;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
export { useLazyComponent };
|