@hartl-services/medusa-base 2.6.0 → 2.7.0
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/.medusa/server/src/admin/admin-components/features/plugin-features/components/ImageSettingInput.d.ts +3 -2
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/ImageSettingInput.js +4 -4
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginActionsSection.js +4 -4
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginBreadcrumb.d.ts +16 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginBreadcrumb.js +25 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginDetailPage.js +1 -1
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginFeatureSections.d.ts +5 -4
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginFeatureSections.js +8 -5
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginFeaturesCard.d.ts +4 -4
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginFeaturesCard.js +24 -27
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.d.ts +2 -2
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.js +9 -9
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginHubCard.d.ts +5 -1
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginHubCard.js +11 -15
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginPageShell.d.ts +10 -4
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginPageShell.js +10 -5
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginSettingsForm.d.ts +0 -1
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginSettingsForm.js +73 -26
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginStatusChips.d.ts +5 -1
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginStatusChips.js +8 -6
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/ShopMasterDataBanner.d.ts +11 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/ShopMasterDataBanner.js +15 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.d.ts +36 -5
- package/.medusa/server/src/admin/admin-components/features/plugin-features/hooks/usePluginFeatures.d.ts +144 -20
- package/.medusa/server/src/admin/admin-components/features/plugin-features/hooks/usePluginSettingsForm.d.ts +36 -5
- package/.medusa/server/src/admin/admin-components/features/plugin-features/hooks/usePluginSwitch.d.ts +15 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/hooks/usePluginSwitch.js +66 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/plugin-features-admin-client.d.ts +144 -20
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/plugin-view.d.ts +49 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/plugin-view.js +72 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/settings-draft.d.ts +1 -12
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/settings-draft.js +4 -20
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/settings-layout.d.ts +43 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/settings-layout.js +66 -0
- package/.medusa/server/src/admin/admin-components/i18n/texts.d.ts +22 -2
- package/.medusa/server/src/admin/admin-components/i18n/texts.js +29 -7
- package/.medusa/server/src/admin/admin-components/index.d.ts +12 -0
- package/.medusa/server/src/admin/admin-components/index.js +11 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/AdminPageHeader.d.ts +22 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/AdminPageHeader.js +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/AdminSection.d.ts +26 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/AdminSection.js +12 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/BreadcrumbTrail.d.ts +23 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/BreadcrumbTrail.js +20 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/FileDropField.d.ts +21 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/FileDropField.js +33 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/FocusModalShell.d.ts +27 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/FocusModalShell.js +13 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/InfoTooltip.d.ts +13 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/InfoTooltip.js +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/MultiSelectDropdown.d.ts +22 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/MultiSelectDropdown.js +14 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/PdfPreviewModal.js +1 -1
- package/.medusa/server/src/admin/admin-components/shared/ui/PluginIcon.d.ts +10 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/PluginIcon.js +10 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/SwitchRow.d.ts +27 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/SwitchRow.js +15 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/WidgetHeader.d.ts +15 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/WidgetHeader.js +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/file-drop.d.ts +13 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/file-drop.js +16 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/multi-select.d.ts +13 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/multi-select.js +11 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/plugin-icon.d.ts +12 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/plugin-icon.js +29 -0
- package/.medusa/server/src/admin/index.js +3123 -2019
- package/.medusa/server/src/admin/index.mjs +3126 -2022
- package/.medusa/server/src/api/admin-first-login-password-policy.js +56 -0
- package/.medusa/server/src/api/answer-actor-type-casing-not-found.js +26 -0
- package/.medusa/server/src/api/answer-code-provider-route-not-found.js +34 -0
- package/.medusa/server/src/api/code-account-password-routes.js +92 -0
- package/.medusa/server/src/api/middlewares.js +82 -17
- package/.medusa/server/src/api/password-policy.js +55 -10
- package/.medusa/server/src/api/require-login-code-customer-email.js +40 -0
- package/.medusa/server/src/api/store/customer-auth/login-code/route.js +17 -0
- package/.medusa/server/src/api/store/customer-auth/password-policy/route.js +19 -0
- package/.medusa/server/src/customer-auth/application/prepare-code-account-password-reset.js +111 -0
- package/.medusa/server/src/customer-auth/application/request-login-code.js +145 -0
- package/.medusa/server/src/customer-auth/customer-auth-methods-snapshot.js +55 -0
- package/.medusa/server/src/customer-auth/customer-password-policy.js +40 -0
- package/.medusa/server/src/customer-auth/domain/account-linking.js +53 -0
- package/.medusa/server/src/customer-auth/domain/auth-methods.js +32 -0
- package/.medusa/server/src/customer-auth/domain/login-code.js +39 -0
- package/.medusa/server/src/customer-auth/login-code-accounts.js +146 -0
- package/.medusa/server/src/customer-auth/login-code-state.js +139 -0
- package/.medusa/server/src/customer-auth/plugin-features.js +80 -0
- package/.medusa/server/src/customer-auth/remove-provider-identity.js +18 -0
- package/.medusa/server/src/customer-auth/start-customer-auth-methods.js +20 -0
- package/.medusa/server/src/documents/plugin-features.js +8 -2
- package/.medusa/server/src/email/application/deliver-ephemeral-auth-mail.js +186 -0
- package/.medusa/server/src/email/application/deliver-login-code.js +89 -0
- package/.medusa/server/src/email/application/handle-customer-verification-event.js +29 -168
- package/.medusa/server/src/email/application/handle-password-reset-event.js +27 -166
- package/.medusa/server/src/email/customer-verification-snapshot.js +20 -108
- package/.medusa/server/src/email/domain/business-keys.js +15 -2
- package/.medusa/server/src/email/plugin-features.js +8 -3
- package/.medusa/server/src/email/rendering/default-templates.js +2 -1
- package/.medusa/server/src/email/templates/blocks/dynamic-blocks.js +19 -1
- package/.medusa/server/src/email/templates/defaults/documents.js +7 -1
- package/.medusa/server/src/email/templates/defaults/subjects.js +3 -1
- package/.medusa/server/src/email/templates/defaults/texts.js +5 -2
- package/.medusa/server/src/email/templates/render.js +2 -1
- package/.medusa/server/src/email/templates/sample-data.js +2 -1
- package/.medusa/server/src/email/templates/validate.js +8 -3
- package/.medusa/server/src/email/types/email-kinds.js +4 -2
- package/.medusa/server/src/email/types/template-data.js +9 -1
- package/.medusa/server/src/modules/customer-auth/index.js +14 -0
- package/.medusa/server/src/modules/customer-auth/service.js +35 -0
- package/.medusa/server/src/modules/email/migrations/Migration20261010090000.js +20 -0
- package/.medusa/server/src/modules/plugin-features/domain/plugin-settings.js +4 -1
- package/.medusa/server/src/modules/plugin-features/service.js +26 -1
- package/.medusa/server/src/providers/email-otp/index.js +8 -0
- package/.medusa/server/src/providers/email-otp/service.js +96 -0
- package/.medusa/server/src/public/descriptor.js +117 -5
- package/.medusa/server/src/public/effective-features.js +22 -1
- package/.medusa/server/src/public/index.js +4 -2
- package/.medusa/server/src/public/plugin-icons.js +28 -0
- package/.medusa/server/src/public/shop-master-data.js +33 -14
- package/.medusa/server/src/shared/lib/index.js +2 -1
- package/.medusa/server/src/shared/lib/refreshing-snapshot.js +122 -0
- package/.medusa/server/src/shop-config/build-food-shop-config.js +38 -1
- package/README.md +436 -87
- package/dist/customer-auth/customer-auth-methods-snapshot.d.ts +25 -0
- package/dist/customer-auth/customer-auth-methods-snapshot.js +54 -0
- package/dist/customer-auth/domain/auth-methods.d.ts +16 -0
- package/dist/customer-auth/domain/auth-methods.js +31 -0
- package/dist/customer-auth/plugin-features.d.ts +2 -0
- package/dist/customer-auth/plugin-features.js +79 -0
- package/dist/email/customer-verification-snapshot.d.ts +3 -15
- package/dist/email/customer-verification-snapshot.js +19 -107
- package/dist/email/types/email-kinds.d.ts +4 -3
- package/dist/email/types/email-kinds.js +3 -1
- package/dist/email/types/template-data.d.ts +8 -0
- package/dist/email/types/template-data.js +8 -0
- package/dist/public/descriptor.js +116 -4
- package/dist/public/effective-features.d.ts +10 -0
- package/dist/public/effective-features.js +21 -0
- package/dist/public/index.d.ts +2 -1
- package/dist/public/index.js +3 -1
- package/dist/public/plugin-icons.d.ts +7 -0
- package/dist/public/plugin-icons.js +27 -0
- package/dist/public/shop-master-data.js +32 -13
- package/dist/public/types.d.ts +63 -1
- package/dist/shared/lib/index.d.ts +1 -0
- package/dist/shared/lib/index.js +1 -0
- package/dist/shared/lib/refreshing-snapshot.d.ts +52 -0
- package/dist/shared/lib/refreshing-snapshot.js +121 -0
- package/dist/shop-config/build-food-shop-config.js +37 -0
- package/package.json +8 -3
|
@@ -2,9 +2,16 @@ export declare const texts: {
|
|
|
2
2
|
menu: {
|
|
3
3
|
label: string;
|
|
4
4
|
};
|
|
5
|
+
breadcrumbs: {
|
|
6
|
+
hub: string;
|
|
7
|
+
emailAttachments: string;
|
|
8
|
+
};
|
|
5
9
|
page: {
|
|
6
10
|
title: string;
|
|
7
11
|
description: string;
|
|
12
|
+
pluginsHeading: string;
|
|
13
|
+
installed: (count: number) => string;
|
|
14
|
+
editShop: string;
|
|
8
15
|
};
|
|
9
16
|
states: {
|
|
10
17
|
loading: string;
|
|
@@ -15,14 +22,19 @@ export declare const texts: {
|
|
|
15
22
|
};
|
|
16
23
|
plugin: {
|
|
17
24
|
switchLabel: (label: string) => string;
|
|
25
|
+
switchRow: string;
|
|
18
26
|
open: string;
|
|
19
27
|
openLabel: (label: string) => string;
|
|
28
|
+
disableTitle: (label: string) => string;
|
|
29
|
+
disableConfirmDefault: string;
|
|
30
|
+
disable: string;
|
|
31
|
+
cancel: string;
|
|
20
32
|
};
|
|
21
33
|
chips: {
|
|
22
34
|
enabled: string;
|
|
23
35
|
disabled: string;
|
|
24
36
|
configured: string;
|
|
25
|
-
notConfigured:
|
|
37
|
+
notConfigured: string;
|
|
26
38
|
};
|
|
27
39
|
detail: {
|
|
28
40
|
back: string;
|
|
@@ -32,9 +44,13 @@ export declare const texts: {
|
|
|
32
44
|
settings: string;
|
|
33
45
|
actions: string;
|
|
34
46
|
};
|
|
47
|
+
info: {
|
|
48
|
+
label: (label: string) => string;
|
|
49
|
+
};
|
|
35
50
|
hints: {
|
|
36
51
|
pluginDisabled: string;
|
|
37
52
|
parentDisabled: (parentLabel: string) => string;
|
|
53
|
+
lastRequiredFeature: string;
|
|
38
54
|
saving: string;
|
|
39
55
|
};
|
|
40
56
|
gate: {
|
|
@@ -44,6 +60,7 @@ export declare const texts: {
|
|
|
44
60
|
};
|
|
45
61
|
settings: {
|
|
46
62
|
missing: (labels: string) => string;
|
|
63
|
+
requiredLegend: string;
|
|
47
64
|
save: string;
|
|
48
65
|
secretPlaceholder: string;
|
|
49
66
|
secretClear: string;
|
|
@@ -51,8 +68,10 @@ export declare const texts: {
|
|
|
51
68
|
secretClearUndo: string;
|
|
52
69
|
secretClearLabel: (label: string) => string;
|
|
53
70
|
secretClearUndoLabel: (label: string) => string;
|
|
71
|
+
/** Shown on a secret: the settings whose change deletes it ("A", "A oder B"). */
|
|
72
|
+
invalidatedBy: (labels: readonly string[]) => string;
|
|
73
|
+
/** Shown on the changing setting: the secrets its change deletes. */
|
|
54
74
|
invalidates: (labels: string) => string;
|
|
55
|
-
required: string;
|
|
56
75
|
invalidNumber: string;
|
|
57
76
|
invalidColor: string;
|
|
58
77
|
colorPlaceholder: string;
|
|
@@ -61,6 +80,7 @@ export declare const texts: {
|
|
|
61
80
|
numberMin: (min: number) => string;
|
|
62
81
|
numberMax: (max: number) => string;
|
|
63
82
|
numberRange: (min: number, max: number) => string;
|
|
83
|
+
numberInteger: string;
|
|
64
84
|
selectPlaceholder: string;
|
|
65
85
|
imageUpload: string;
|
|
66
86
|
imageReplace: string;
|
|
@@ -2,9 +2,16 @@ export const texts = {
|
|
|
2
2
|
menu: {
|
|
3
3
|
label: "Hartl Services Plugins",
|
|
4
4
|
},
|
|
5
|
+
breadcrumbs: {
|
|
6
|
+
hub: "Plugins",
|
|
7
|
+
emailAttachments: "Anhänge",
|
|
8
|
+
},
|
|
5
9
|
page: {
|
|
6
10
|
title: "Hartl Services Plugins",
|
|
7
|
-
description: "Plugins ein- oder ausschalten und öffnen, um Funktionen, Einstellungen und Aktionen zu verwalten. Änderungen gelten sofort
|
|
11
|
+
description: "Plugins ein- oder ausschalten und öffnen, um Funktionen, Einstellungen und Aktionen zu verwalten. Änderungen gelten sofort.",
|
|
12
|
+
pluginsHeading: "Plugins",
|
|
13
|
+
installed: (count) => `${count} installiert`,
|
|
14
|
+
editShop: "Bearbeiten",
|
|
8
15
|
},
|
|
9
16
|
states: {
|
|
10
17
|
loading: "Plugins werden geladen…",
|
|
@@ -14,15 +21,20 @@ export const texts = {
|
|
|
14
21
|
notFound: "Dieses Plugin ist nicht installiert.",
|
|
15
22
|
},
|
|
16
23
|
plugin: {
|
|
17
|
-
switchLabel: (label) => `${label}
|
|
24
|
+
switchLabel: (label) => `${label} eingeschaltet`,
|
|
25
|
+
switchRow: "Plugin eingeschaltet",
|
|
18
26
|
open: "Öffnen",
|
|
19
27
|
openLabel: (label) => `${label} öffnen`,
|
|
28
|
+
disableTitle: (label) => `${label} ausschalten?`,
|
|
29
|
+
disableConfirmDefault: "Die Funktionen des Plugins sind dann im Shop nicht mehr erreichbar. Gespeicherte Einstellungen und Daten bleiben erhalten.",
|
|
30
|
+
disable: "Ausschalten",
|
|
31
|
+
cancel: "Abbrechen",
|
|
20
32
|
},
|
|
21
33
|
chips: {
|
|
22
|
-
enabled: "
|
|
23
|
-
disabled: "
|
|
24
|
-
configured: "
|
|
25
|
-
notConfigured:
|
|
34
|
+
enabled: "Aktiv",
|
|
35
|
+
disabled: "Aus",
|
|
36
|
+
configured: "Konfiguriert",
|
|
37
|
+
notConfigured: "Nicht konfiguriert",
|
|
26
38
|
},
|
|
27
39
|
detail: {
|
|
28
40
|
back: "Zurück zu Hartl Services Plugins",
|
|
@@ -32,9 +44,13 @@ export const texts = {
|
|
|
32
44
|
settings: "Einstellungen",
|
|
33
45
|
actions: "Aktionen",
|
|
34
46
|
},
|
|
47
|
+
info: {
|
|
48
|
+
label: (label) => `Erklärung zu ${label}`,
|
|
49
|
+
},
|
|
35
50
|
hints: {
|
|
36
51
|
pluginDisabled: "Das Plugin ist ausgeschaltet. Alle Funktionen sind inaktiv, ihre Einstellungen bleiben erhalten.",
|
|
37
52
|
parentDisabled: (parentLabel) => `Inaktiv, solange „${parentLabel}“ ausgeschaltet ist.`,
|
|
53
|
+
lastRequiredFeature: "Mindestens eine Funktion muss eingeschaltet bleiben.",
|
|
38
54
|
saving: "Wird gespeichert…",
|
|
39
55
|
},
|
|
40
56
|
gate: {
|
|
@@ -44,6 +60,7 @@ export const texts = {
|
|
|
44
60
|
},
|
|
45
61
|
settings: {
|
|
46
62
|
missing: (labels) => `Nicht konfiguriert: ${labels}`,
|
|
63
|
+
requiredLegend: "* Pflichtfeld",
|
|
47
64
|
save: "Einstellungen speichern",
|
|
48
65
|
secretPlaceholder: "gesetzt",
|
|
49
66
|
secretClear: "Löschen",
|
|
@@ -51,8 +68,12 @@ export const texts = {
|
|
|
51
68
|
secretClearUndo: "Nicht löschen",
|
|
52
69
|
secretClearLabel: (label) => `${label} löschen`,
|
|
53
70
|
secretClearUndoLabel: (label) => `${label} nicht löschen`,
|
|
71
|
+
/** Shown on a secret: the settings whose change deletes it ("A", "A oder B"). */
|
|
72
|
+
invalidatedBy: (labels) => `Wird gelöscht, wenn ${labels.length > 1
|
|
73
|
+
? `${labels.slice(0, -1).join(", ")} oder ${labels[labels.length - 1]}`
|
|
74
|
+
: labels.join("")} sich ändert.`,
|
|
75
|
+
/** Shown on the changing setting: the secrets its change deletes. */
|
|
54
76
|
invalidates: (labels) => `Beim Ändern muss ${labels} neu eingegeben werden.`,
|
|
55
|
-
required: "Pflichtfeld",
|
|
56
77
|
invalidNumber: "Bitte eine gültige Zahl eingeben.",
|
|
57
78
|
invalidColor: "Bitte eine Hex-Farbe wie #1a2b3c eingeben.",
|
|
58
79
|
colorPlaceholder: "Standard",
|
|
@@ -61,6 +82,7 @@ export const texts = {
|
|
|
61
82
|
numberMin: (min) => `Mindestens ${min}.`,
|
|
62
83
|
numberMax: (max) => `Höchstens ${max}.`,
|
|
63
84
|
numberRange: (min, max) => `Zwischen ${min} und ${max}.`,
|
|
85
|
+
numberInteger: "Ganze Zahl.",
|
|
64
86
|
selectPlaceholder: "Bitte auswählen",
|
|
65
87
|
imageUpload: "Bild hochladen",
|
|
66
88
|
imageReplace: "Anderes Bild hochladen",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { PluginPageShell } from "./features/plugin-features/components/PluginPageShell";
|
|
11
11
|
export { PluginFeatureSections } from "./features/plugin-features/components/PluginFeatureSections";
|
|
12
|
+
export { PluginLabelCrumb, pluginBreadcrumb, } from "./features/plugin-features/components/PluginBreadcrumb";
|
|
12
13
|
export { PluginFeatureDisabledNotice, PluginFeatureGate, } from "./features/plugin-features/components/PluginFeatureGate";
|
|
13
14
|
export { usePluginFeature } from "./features/plugin-features/hooks/usePluginFeatures";
|
|
14
15
|
export { usePluginFeatureEnabled, type PluginFeatureEnabledState, } from "./features/plugin-features/hooks/usePluginFeatureEnabled";
|
|
@@ -22,15 +23,26 @@ export { fetchPdfObjectUrl } from "./shared/lib/pdf";
|
|
|
22
23
|
export { usePdfPreview, type PdfPreviewState } from "./shared/lib/use-pdf-preview";
|
|
23
24
|
export { useDebouncedValue } from "./shared/lib/use-debounced-value";
|
|
24
25
|
export { AdminDatePicker } from "./shared/ui/AdminDatePicker";
|
|
26
|
+
export { AdminPageHeader } from "./shared/ui/AdminPageHeader";
|
|
27
|
+
export { AdminSection } from "./shared/ui/AdminSection";
|
|
28
|
+
export { BreadcrumbTrail, type BreadcrumbTrailItem, } from "./shared/ui/BreadcrumbTrail";
|
|
25
29
|
export { DateRangeFilter } from "./shared/ui/DateRangeFilter";
|
|
30
|
+
export { InfoTooltip } from "./shared/ui/InfoTooltip";
|
|
31
|
+
export { FileDropField } from "./shared/ui/FileDropField";
|
|
26
32
|
export { FilePickerButton } from "./shared/ui/FilePickerButton";
|
|
33
|
+
export { FocusModalShell } from "./shared/ui/FocusModalShell";
|
|
27
34
|
export { BackLink } from "./shared/ui/BackLink";
|
|
28
35
|
export { MappedStatusBadge, type MappedStatus } from "./shared/ui/MappedStatusBadge";
|
|
36
|
+
export { MultiSelectDropdown } from "./shared/ui/MultiSelectDropdown";
|
|
37
|
+
export type { MultiSelectOption } from "./shared/ui/multi-select";
|
|
29
38
|
export { OffsetTablePagination } from "./shared/ui/OffsetTablePagination";
|
|
30
39
|
export { PdfPreviewModal } from "./shared/ui/PdfPreviewModal";
|
|
31
40
|
export { PluginFeatureRoute } from "./shared/ui/PluginFeatureRoute";
|
|
41
|
+
export { PluginIcon } from "./shared/ui/PluginIcon";
|
|
32
42
|
export { QueryState } from "./shared/ui/QueryState";
|
|
33
43
|
export { SearchableReferenceField, type SearchableReferenceFieldProps, type SearchableReferenceSelected, } from "./shared/ui/SearchableReferenceField";
|
|
34
44
|
export { SectionHeader } from "./shared/ui/SectionHeader";
|
|
45
|
+
export { SwitchRow } from "./shared/ui/SwitchRow";
|
|
46
|
+
export { WidgetHeader } from "./shared/ui/WidgetHeader";
|
|
35
47
|
export { Extension, filterSlashItems, InsertMenu, isDefaultAllowedHref, Mark, mergeAttributes, Node, NodeSelection, NodeViewContent, NodeViewWrapper, normalizeLinkHref, Plugin, PluginKey, ReactNodeViewRenderer, RichTextEditor, TextSelection, useEditorState, useRichTextEditor, } from "./shared/ui/rich-text-editor";
|
|
36
48
|
export type { AnyExtension, ChainedCommands, Editor, JSONContent, NestedContainer, NodeViewProps, Range, RichTextEditorConfig, SlashContext, SlashItem, } from "./shared/ui/rich-text-editor";
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { PluginPageShell } from "./features/plugin-features/components/PluginPageShell";
|
|
11
11
|
export { PluginFeatureSections } from "./features/plugin-features/components/PluginFeatureSections";
|
|
12
|
+
export { PluginLabelCrumb, pluginBreadcrumb, } from "./features/plugin-features/components/PluginBreadcrumb";
|
|
12
13
|
export { PluginFeatureDisabledNotice, PluginFeatureGate, } from "./features/plugin-features/components/PluginFeatureGate";
|
|
13
14
|
export { usePluginFeature } from "./features/plugin-features/hooks/usePluginFeatures";
|
|
14
15
|
export { usePluginFeatureEnabled, } from "./features/plugin-features/hooks/usePluginFeatureEnabled";
|
|
@@ -23,15 +24,25 @@ export { usePdfPreview } from "./shared/lib/use-pdf-preview";
|
|
|
23
24
|
export { useDebouncedValue } from "./shared/lib/use-debounced-value";
|
|
24
25
|
// Shared UI
|
|
25
26
|
export { AdminDatePicker } from "./shared/ui/AdminDatePicker";
|
|
27
|
+
export { AdminPageHeader } from "./shared/ui/AdminPageHeader";
|
|
28
|
+
export { AdminSection } from "./shared/ui/AdminSection";
|
|
29
|
+
export { BreadcrumbTrail, } from "./shared/ui/BreadcrumbTrail";
|
|
26
30
|
export { DateRangeFilter } from "./shared/ui/DateRangeFilter";
|
|
31
|
+
export { InfoTooltip } from "./shared/ui/InfoTooltip";
|
|
32
|
+
export { FileDropField } from "./shared/ui/FileDropField";
|
|
27
33
|
export { FilePickerButton } from "./shared/ui/FilePickerButton";
|
|
34
|
+
export { FocusModalShell } from "./shared/ui/FocusModalShell";
|
|
28
35
|
export { BackLink } from "./shared/ui/BackLink";
|
|
29
36
|
export { MappedStatusBadge } from "./shared/ui/MappedStatusBadge";
|
|
37
|
+
export { MultiSelectDropdown } from "./shared/ui/MultiSelectDropdown";
|
|
30
38
|
export { OffsetTablePagination } from "./shared/ui/OffsetTablePagination";
|
|
31
39
|
export { PdfPreviewModal } from "./shared/ui/PdfPreviewModal";
|
|
32
40
|
export { PluginFeatureRoute } from "./shared/ui/PluginFeatureRoute";
|
|
41
|
+
export { PluginIcon } from "./shared/ui/PluginIcon";
|
|
33
42
|
export { QueryState } from "./shared/ui/QueryState";
|
|
34
43
|
export { SearchableReferenceField, } from "./shared/ui/SearchableReferenceField";
|
|
35
44
|
export { SectionHeader } from "./shared/ui/SectionHeader";
|
|
45
|
+
export { SwitchRow } from "./shared/ui/SwitchRow";
|
|
46
|
+
export { WidgetHeader } from "./shared/ui/WidgetHeader";
|
|
36
47
|
// Rich-text editor
|
|
37
48
|
export { Extension, filterSlashItems, InsertMenu, isDefaultAllowedHref, Mark, mergeAttributes, Node, NodeSelection, NodeViewContent, NodeViewWrapper, normalizeLinkHref, Plugin, PluginKey, ReactNodeViewRenderer, RichTextEditor, TextSelection, useEditorState, useRichTextEditor, } from "./shared/ui/rich-text-editor";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
type AdminPageHeaderProps = {
|
|
3
|
+
/** Icon element for the badge, e.g. `<Buildings />` or `<PluginIcon name="Users" />`. */
|
|
4
|
+
icon: ReactNode;
|
|
5
|
+
/** The page's `h1`. */
|
|
6
|
+
title: ReactNode;
|
|
7
|
+
/** One short subtitle line under the title. */
|
|
8
|
+
description?: ReactNode;
|
|
9
|
+
/** Info button (`InfoTooltip`) next to the title, for the longer description. */
|
|
10
|
+
info?: ReactNode;
|
|
11
|
+
/** Status badges at the end (`StatusBadge`s); they wrap below the text on narrow screens. */
|
|
12
|
+
badges?: ReactNode;
|
|
13
|
+
/** Buttons at the end, after the badges. */
|
|
14
|
+
actions?: ReactNode;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Title container of an Admin page: large `IconBadge`, `h1`, subtle subtitle
|
|
18
|
+
* and a slot at the end for status badges and actions. The route's
|
|
19
|
+
* breadcrumb belongs in the route `handle`, not in the page.
|
|
20
|
+
*/
|
|
21
|
+
export declare const AdminPageHeader: ({ icon, title, description, info, badges, actions, }: AdminPageHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Container, Heading, IconBadge, Text } from "@medusajs/ui";
|
|
3
|
+
/**
|
|
4
|
+
* Title container of an Admin page: large `IconBadge`, `h1`, subtle subtitle
|
|
5
|
+
* and a slot at the end for status badges and actions. The route's
|
|
6
|
+
* breadcrumb belongs in the route `handle`, not in the page.
|
|
7
|
+
*/
|
|
8
|
+
export const AdminPageHeader = ({ icon, title, description, info, badges, actions, }) => (_jsx(Container, { children: _jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-3", children: [_jsx(IconBadge, { size: "large", children: icon }), _jsxs("div", { className: "flex min-w-0 flex-[1_1_320px] flex-col gap-y-0.5", children: [_jsxs("div", { className: "flex items-center gap-x-1", children: [_jsx(Heading, { level: "h1", children: title }), info] }), description ? (_jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: description })) : null] }), badges || actions ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [badges, actions] })) : null] }) }));
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
type AdminSectionProps = Omit<HTMLAttributes<HTMLDivElement>, "title"> & {
|
|
3
|
+
/** The section's `h2`; omit it (and the other header props) for a section without header row. */
|
|
4
|
+
title?: ReactNode;
|
|
5
|
+
/** Subtle line under the title. */
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
/** Short subtle note at the end of the header row, e.g. "Version 3". */
|
|
8
|
+
note?: ReactNode;
|
|
9
|
+
/** Buttons at the end of the header row. */
|
|
10
|
+
actions?: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Content of the right-aligned last row, usually the save `Button`. Add
|
|
13
|
+
* `className="mr-auto"` to an element that should sit on the left instead.
|
|
14
|
+
*/
|
|
15
|
+
footer?: ReactNode;
|
|
16
|
+
/** The rows. Each direct child is separated from the next by a divider. */
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* A section as the Admin builds it: `Container` with dividers, an optional
|
|
21
|
+
* header row (title, description, note, actions), the given rows and an
|
|
22
|
+
* optional right-aligned footer row. Rows are `SwitchRow`s or your own
|
|
23
|
+
* `px-6 py-5` blocks.
|
|
24
|
+
*/
|
|
25
|
+
export declare const AdminSection: ({ title, description, note, actions, footer, children, className, ...rest }: AdminSectionProps) => import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clx, Container, Heading, Text } from "@medusajs/ui";
|
|
3
|
+
/**
|
|
4
|
+
* A section as the Admin builds it: `Container` with dividers, an optional
|
|
5
|
+
* header row (title, description, note, actions), the given rows and an
|
|
6
|
+
* optional right-aligned footer row. Rows are `SwitchRow`s or your own
|
|
7
|
+
* `px-6 py-5` blocks.
|
|
8
|
+
*/
|
|
9
|
+
export const AdminSection = ({ title, description, note, actions, footer, children, className, ...rest }) => {
|
|
10
|
+
const hasHeader = Boolean(title || description || note || actions);
|
|
11
|
+
return (_jsxs(Container, { className: clx("divide-y p-0", className), ...rest, children: [hasHeader ? (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-x-4 gap-y-2 px-6 py-4", children: [_jsxs("div", { className: "flex min-w-0 flex-col gap-y-0.5", children: [title ? _jsx(Heading, { level: "h2", children: title }) : null, description ? (_jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: description })) : null] }), note || actions ? (_jsxs("div", { className: "flex flex-wrap items-center justify-end gap-x-4 gap-y-2", children: [note ? (_jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: note })) : null, actions] })) : null] })) : null, children, footer ? (_jsx("div", { className: "flex flex-wrap items-center justify-end gap-x-4 gap-y-2 px-6 py-3", children: footer })) : null] }));
|
|
12
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export type BreadcrumbTrailItem = {
|
|
3
|
+
label: ReactNode;
|
|
4
|
+
/** Admin path of the crumb; the last item is never a link. */
|
|
5
|
+
to?: string;
|
|
6
|
+
};
|
|
7
|
+
type BreadcrumbTrailProps = {
|
|
8
|
+
items: readonly BreadcrumbTrailItem[];
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Several breadcrumbs in ONE route-`handle` crumb. The Admin renders
|
|
12
|
+
* `handle.breadcrumb(match)` per matched route, and a plugin's route map
|
|
13
|
+
* only contains parent routes that have a page in the same plugin; use this
|
|
14
|
+
* as the label of the last crumb when a parent lives in another plugin:
|
|
15
|
+
*
|
|
16
|
+
* `export const handle = { breadcrumb: () => <BreadcrumbTrail items={[{ label: "Plugins", to: "/settings/hartl-services" }, { label: "Affiliate" }]} /> }`
|
|
17
|
+
*
|
|
18
|
+
* Looks like the Admin's own crumbs (muted text, linked parents, triangle
|
|
19
|
+
* separator). Only for a leaf route: the Admin wraps a crumb that has a child
|
|
20
|
+
* route in a link of its own.
|
|
21
|
+
*/
|
|
22
|
+
export declare const BreadcrumbTrail: ({ items }: BreadcrumbTrailProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { TriangleRightMini } from "@medusajs/icons";
|
|
3
|
+
import { Fragment } from "react";
|
|
4
|
+
import { Link } from "react-router-dom";
|
|
5
|
+
/**
|
|
6
|
+
* Several breadcrumbs in ONE route-`handle` crumb. The Admin renders
|
|
7
|
+
* `handle.breadcrumb(match)` per matched route, and a plugin's route map
|
|
8
|
+
* only contains parent routes that have a page in the same plugin; use this
|
|
9
|
+
* as the label of the last crumb when a parent lives in another plugin:
|
|
10
|
+
*
|
|
11
|
+
* `export const handle = { breadcrumb: () => <BreadcrumbTrail items={[{ label: "Plugins", to: "/settings/hartl-services" }, { label: "Affiliate" }]} /> }`
|
|
12
|
+
*
|
|
13
|
+
* Looks like the Admin's own crumbs (muted text, linked parents, triangle
|
|
14
|
+
* separator). Only for a leaf route: the Admin wraps a crumb that has a child
|
|
15
|
+
* route in a link of its own.
|
|
16
|
+
*/
|
|
17
|
+
export const BreadcrumbTrail = ({ items }) => (_jsx("span", { className: "inline-flex items-center", children: items.map((item, index) => {
|
|
18
|
+
const last = index === items.length - 1;
|
|
19
|
+
return (_jsxs(Fragment, { children: [item.to && !last ? (_jsx(Link, { className: "transition-fg hover:text-ui-fg-subtle", to: item.to, children: item.label })) : (_jsx("span", { children: item.label })), last ? null : (_jsx("span", { className: "mx-2", children: _jsx(TriangleRightMini, { className: "rtl:rotate-180" }) }))] }, index));
|
|
20
|
+
}) }));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type FileDropFieldProps = {
|
|
2
|
+
/** Value of the file input's `accept` attribute. */
|
|
3
|
+
accept: string;
|
|
4
|
+
/** Text of the button that opens the file dialog. */
|
|
5
|
+
label: string;
|
|
6
|
+
/** Line under the button: the chosen file, a hint about allowed files, … */
|
|
7
|
+
text?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
isLoading?: boolean;
|
|
10
|
+
/** Id of the hidden input (for a `Label htmlFor`). */
|
|
11
|
+
id?: string;
|
|
12
|
+
"aria-describedby"?: string;
|
|
13
|
+
/** Called with the chosen or dropped file; the caller validates it. */
|
|
14
|
+
onFileSelected: (file: File) => void;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Dashed drop area for one file: the file dialog button plus drag and drop.
|
|
18
|
+
* Medusa UI has no such field; the Admin docs show nothing for it either.
|
|
19
|
+
*/
|
|
20
|
+
export declare const FileDropField: ({ accept, label, text, disabled, isLoading, id, "aria-describedby": describedBy, onFileSelected, }: FileDropFieldProps) => import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowUpTray } from "@medusajs/icons";
|
|
3
|
+
import { Text } from "@medusajs/ui";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { leavesDropArea, pickDroppedFile } from "./file-drop";
|
|
6
|
+
import { FilePickerButton } from "./FilePickerButton";
|
|
7
|
+
/**
|
|
8
|
+
* Dashed drop area for one file: the file dialog button plus drag and drop.
|
|
9
|
+
* Medusa UI has no such field; the Admin docs show nothing for it either.
|
|
10
|
+
*/
|
|
11
|
+
export const FileDropField = ({ accept, label, text, disabled, isLoading, id, "aria-describedby": describedBy, onFileSelected, }) => {
|
|
12
|
+
const [dragging, setDragging] = useState(false);
|
|
13
|
+
const locked = disabled || isLoading === true;
|
|
14
|
+
return (_jsxs("div", { className: `flex min-h-[120px] flex-col items-center justify-center gap-y-2 rounded-lg border border-dashed p-4 text-center transition-fg ${dragging
|
|
15
|
+
? "border-ui-border-interactive bg-ui-bg-base-hover"
|
|
16
|
+
: "border-ui-border-strong bg-ui-bg-subtle"}`, onDragOver: (event) => {
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
if (!locked) {
|
|
19
|
+
setDragging(true);
|
|
20
|
+
}
|
|
21
|
+
}, onDragLeave: (event) => {
|
|
22
|
+
if (leavesDropArea(event.currentTarget, event.relatedTarget)) {
|
|
23
|
+
setDragging(false);
|
|
24
|
+
}
|
|
25
|
+
}, onDrop: (event) => {
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
setDragging(false);
|
|
28
|
+
const file = pickDroppedFile(event.dataTransfer.files, locked);
|
|
29
|
+
if (file) {
|
|
30
|
+
onFileSelected(file);
|
|
31
|
+
}
|
|
32
|
+
}, children: [_jsx(ArrowUpTray, { className: "text-ui-fg-muted" }), _jsx(FilePickerButton, { accept: accept, label: label, disabled: disabled, isLoading: isLoading, id: id, "aria-describedby": describedBy, onFileSelected: onFileSelected }), text ? (_jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-muted", children: text })) : null] }));
|
|
33
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
type FocusModalShellProps = {
|
|
3
|
+
open: boolean;
|
|
4
|
+
onOpenChange: (open: boolean) => void;
|
|
5
|
+
/** Accessible title (screen readers only; the page behind gives the context). */
|
|
6
|
+
title: string;
|
|
7
|
+
/** Accessible description (screen readers only). */
|
|
8
|
+
description: string;
|
|
9
|
+
/** Label of the primary button in the header, e.g. "Anhang anlegen". */
|
|
10
|
+
submitLabel: string;
|
|
11
|
+
onSubmit: () => void;
|
|
12
|
+
/** Blocks closing and shows the loading state on the primary button. */
|
|
13
|
+
isPending?: boolean;
|
|
14
|
+
/** Disables the primary button, e.g. while the form is invalid. */
|
|
15
|
+
submitDisabled?: boolean;
|
|
16
|
+
cancelLabel?: string;
|
|
17
|
+
/** The sections of the form, one block per section. */
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Full-screen form dialog as the Admin builds it: the actions (cancel and the
|
|
22
|
+
* primary button) in the header at the right, a centered body (720px) with
|
|
23
|
+
* the sections below. Closing is blocked while `isPending`. Put one
|
|
24
|
+
* `<section className="flex flex-col gap-y-5">` per section in `children`.
|
|
25
|
+
*/
|
|
26
|
+
export declare const FocusModalShell: ({ open, onOpenChange, title, description, submitLabel, onSubmit, isPending, submitDisabled, cancelLabel, children, }: FocusModalShellProps) => import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, FocusModal } from "@medusajs/ui";
|
|
3
|
+
/**
|
|
4
|
+
* Full-screen form dialog as the Admin builds it: the actions (cancel and the
|
|
5
|
+
* primary button) in the header at the right, a centered body (720px) with
|
|
6
|
+
* the sections below. Closing is blocked while `isPending`. Put one
|
|
7
|
+
* `<section className="flex flex-col gap-y-5">` per section in `children`.
|
|
8
|
+
*/
|
|
9
|
+
export const FocusModalShell = ({ open, onOpenChange, title, description, submitLabel, onSubmit, isPending = false, submitDisabled = false, cancelLabel = "Abbrechen", children, }) => (_jsx(FocusModal, { onOpenChange: (next) => {
|
|
10
|
+
if (!next && !isPending) {
|
|
11
|
+
onOpenChange(false);
|
|
12
|
+
}
|
|
13
|
+
}, open: open, children: _jsx(FocusModal.Content, { children: _jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [_jsxs(FocusModal.Header, { children: [_jsx(FocusModal.Title, { className: "sr-only", children: title }), _jsx(FocusModal.Description, { className: "sr-only", children: description }), _jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [_jsx(FocusModal.Close, { asChild: true, children: _jsx(Button, { disabled: isPending, size: "small", variant: "secondary", children: cancelLabel }) }), _jsx(Button, { disabled: isPending || submitDisabled, isLoading: isPending, onClick: onSubmit, size: "small", type: "button", children: submitLabel })] })] }), _jsx(FocusModal.Body, { className: "flex flex-1 flex-col items-center overflow-y-auto", children: _jsx("div", { className: "mx-auto flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16", children: children }) })] }) }) }));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
type InfoTooltipProps = {
|
|
3
|
+
/** Accessible name of the button, e.g. "Erklärung zu Mindestlänge". */
|
|
4
|
+
label: string;
|
|
5
|
+
/** The explanation shown in the tooltip. */
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Small info button next to a label or heading; hovering or focusing it
|
|
10
|
+
* shows the longer explanation that does not fit under the field.
|
|
11
|
+
*/
|
|
12
|
+
export declare const InfoTooltip: ({ label, children }: InfoTooltipProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { InformationCircle } from "@medusajs/icons";
|
|
3
|
+
import { IconButton, Tooltip } from "@medusajs/ui";
|
|
4
|
+
/**
|
|
5
|
+
* Small info button next to a label or heading; hovering or focusing it
|
|
6
|
+
* shows the longer explanation that does not fit under the field.
|
|
7
|
+
*/
|
|
8
|
+
export const InfoTooltip = ({ label, children }) => (_jsx(Tooltip, { content: children, maxWidth: 320, children: _jsx(IconButton, { type: "button", variant: "transparent", size: "2xsmall", "aria-label": label, children: _jsx(InformationCircle, {}) }) }));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type MultiSelectOption } from "./multi-select";
|
|
2
|
+
type MultiSelectDropdownProps<T extends string> = {
|
|
3
|
+
options: readonly MultiSelectOption<T>[];
|
|
4
|
+
value: readonly T[];
|
|
5
|
+
onChange: (value: T[]) => void;
|
|
6
|
+
/** Id of the trigger button (for a `Label htmlFor`). */
|
|
7
|
+
id?: string;
|
|
8
|
+
"aria-labelledby"?: string;
|
|
9
|
+
/** Accessible name when there is no visible label. */
|
|
10
|
+
"aria-label"?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
/** Shown when nothing is selected. */
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Select for several values: the trigger shows the chosen labels as badges
|
|
17
|
+
* (or the placeholder), the menu holds one checkbox item per option. The menu
|
|
18
|
+
* stays open while ticking. Medusa UI has no multi select; this is the
|
|
19
|
+
* Admin's own with the same look as its `Select`.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MultiSelectDropdown: <T extends string>({ options, value, onChange, id, "aria-labelledby": labelledBy, "aria-label": ariaLabel, disabled, placeholder, }: MultiSelectDropdownProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronDownMini } from "@medusajs/icons";
|
|
3
|
+
import { Badge, clx, DropdownMenu } from "@medusajs/ui";
|
|
4
|
+
import { selectedMultiSelectLabels, toggleMultiSelectValue, } from "./multi-select";
|
|
5
|
+
/**
|
|
6
|
+
* Select for several values: the trigger shows the chosen labels as badges
|
|
7
|
+
* (or the placeholder), the menu holds one checkbox item per option. The menu
|
|
8
|
+
* stays open while ticking. Medusa UI has no multi select; this is the
|
|
9
|
+
* Admin's own with the same look as its `Select`.
|
|
10
|
+
*/
|
|
11
|
+
export const MultiSelectDropdown = ({ options, value, onChange, id, "aria-labelledby": labelledBy, "aria-label": ariaLabel, disabled, placeholder = "Keine", }) => {
|
|
12
|
+
const labels = selectedMultiSelectLabels(options, value);
|
|
13
|
+
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenu.Trigger, { asChild: true, disabled: disabled, children: _jsxs("button", { "aria-label": ariaLabel, "aria-labelledby": labelledBy, className: clx("bg-ui-bg-field shadow-borders-base txt-compact-small text-ui-fg-base flex min-h-8 w-full items-center justify-between gap-x-2 rounded-md px-2 py-[3px] text-left transition-fg", "hover:bg-ui-bg-field-hover focus-visible:shadow-borders-interactive-with-active outline-none", "disabled:bg-ui-bg-disabled disabled:text-ui-fg-disabled disabled:cursor-not-allowed"), id: id, type: "button", children: [_jsx("span", { className: "flex min-w-0 flex-wrap items-center gap-1", children: labels.length ? (labels.map((label) => (_jsx(Badge, { size: "2xsmall", children: label }, label)))) : (_jsx("span", { className: "text-ui-fg-muted", children: placeholder })) }), _jsx(ChevronDownMini, { className: "text-ui-fg-muted flex-none" })] }) }), _jsx(DropdownMenu.Content, { align: "start", className: "min-w-[var(--radix-dropdown-menu-trigger-width)]", children: options.map((option) => (_jsx(DropdownMenu.CheckboxItem, { checked: value.includes(option.value), disabled: option.disabled, onCheckedChange: (checked) => onChange(toggleMultiSelectValue(options, value, option.value, checked === true)), onSelect: (event) => event.preventDefault(), children: option.label }, option.value))) })] }));
|
|
14
|
+
};
|
|
@@ -4,4 +4,4 @@ import { Button, FocusModal, Text } from "@medusajs/ui";
|
|
|
4
4
|
* Full-screen PDF preview. Owns no URL: the caller creates the object URL and
|
|
5
5
|
* revokes it when the modal closes (see `fetchPdfObjectUrl`).
|
|
6
6
|
*/
|
|
7
|
-
export const PdfPreviewModal = ({ open, onOpenChange, title, url, isLoading = false, error = null, frameTitle = "Vorschau", loadingText = "Wird geladen.", closeLabel = "Schließen", }) => (_jsx(FocusModal, { onOpenChange: onOpenChange, open: open, children: _jsxs(FocusModal.Content, { children: [
|
|
7
|
+
export const PdfPreviewModal = ({ open, onOpenChange, title, url, isLoading = false, error = null, frameTitle = "Vorschau", loadingText = "Wird geladen.", closeLabel = "Schließen", }) => (_jsx(FocusModal, { onOpenChange: onOpenChange, open: open, children: _jsxs(FocusModal.Content, { children: [_jsxs(FocusModal.Header, { children: [_jsx(FocusModal.Title, { children: title }), _jsxs(FocusModal.Description, { className: "sr-only", children: ["PDF-Vorschau: ", title] })] }), _jsx(FocusModal.Body, { className: "h-[75vh] p-0", children: url && !isLoading ? (_jsx("iframe", { className: "h-full w-full border-0", src: url, title: frameTitle })) : error ? (_jsx(Text, { "aria-atomic": "true", "aria-live": "assertive", className: "p-6 text-ui-fg-error", role: "alert", children: error })) : (_jsx(Text, { "aria-atomic": "true", "aria-live": "polite", className: "p-6 text-ui-fg-subtle", role: "status", children: loadingText })) }), _jsx(FocusModal.Footer, { children: _jsx(FocusModal.Close, { asChild: true, children: _jsx(Button, { variant: "secondary", children: closeLabel }) }) })] }) }));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type PluginIconProps = {
|
|
2
|
+
/** `icon` of the plugin as the Admin API reports it (`@medusajs/icons` component name). */
|
|
3
|
+
name: string | null | undefined;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* The `@medusajs/icons` icon a plugin descriptor names; a default icon for no
|
|
7
|
+
* or an unknown name. Put it into `IconBadge` / `AdminPageHeader`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PluginIcon: ({ name }: PluginIconProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { resolvePluginIcon } from "./plugin-icon";
|
|
3
|
+
/**
|
|
4
|
+
* The `@medusajs/icons` icon a plugin descriptor names; a default icon for no
|
|
5
|
+
* or an unknown name. Put it into `IconBadge` / `AdminPageHeader`.
|
|
6
|
+
*/
|
|
7
|
+
export const PluginIcon = ({ name }) => {
|
|
8
|
+
const Icon = resolvePluginIcon(name);
|
|
9
|
+
return _jsx(Icon, {});
|
|
10
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
type SwitchRowProps = {
|
|
3
|
+
/** Id of the switch; the label points to it. */
|
|
4
|
+
id: string;
|
|
5
|
+
label: ReactNode;
|
|
6
|
+
/** Info button (`InfoTooltip`) next to the label, for a longer explanation. */
|
|
7
|
+
info?: ReactNode;
|
|
8
|
+
/** Subtle explanation under the label. */
|
|
9
|
+
description?: ReactNode;
|
|
10
|
+
/** Further muted line under the description, e.g. why the switch is locked. */
|
|
11
|
+
hint?: ReactNode;
|
|
12
|
+
checked: boolean;
|
|
13
|
+
onCheckedChange: (checked: boolean) => void;
|
|
14
|
+
/** Locks the switch. Dim the row itself through `className` (e.g. `opacity-50`). */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/** Child row of a parent switch: indented. */
|
|
17
|
+
indent?: boolean;
|
|
18
|
+
/** Element after the switch, e.g. an "Öffnen" button. */
|
|
19
|
+
trailing?: ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* One row of switches in an `AdminSection`: label with optional description
|
|
24
|
+
* on the left, `Switch` (and optional `trailing` element) on the right (`px-6 py-3`).
|
|
25
|
+
*/
|
|
26
|
+
export declare const SwitchRow: ({ id, label, info, description, hint, checked, onCheckedChange, disabled, indent, trailing, className, }: SwitchRowProps) => import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { clx, Label, Switch, Text } from "@medusajs/ui";
|
|
3
|
+
/**
|
|
4
|
+
* One row of switches in an `AdminSection`: label with optional description
|
|
5
|
+
* on the left, `Switch` (and optional `trailing` element) on the right (`px-6 py-3`).
|
|
6
|
+
*/
|
|
7
|
+
export const SwitchRow = ({ id, label, info, description, hint, checked, onCheckedChange, disabled, indent, trailing, className, }) => {
|
|
8
|
+
const describedBy = [
|
|
9
|
+
description ? `${id}-description` : null,
|
|
10
|
+
hint ? `${id}-hint` : null,
|
|
11
|
+
]
|
|
12
|
+
.filter(Boolean)
|
|
13
|
+
.join(" ");
|
|
14
|
+
return (_jsxs("div", { className: clx("flex items-center gap-4 py-3 pr-6", indent ? "pl-12" : "pl-6", className), children: [_jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-y-0.5", children: [_jsxs("div", { className: "flex items-center gap-x-1", children: [_jsx(Label, { htmlFor: id, size: "small", weight: "plus", children: label }), info] }), description ? (_jsx(Text, { id: `${id}-description`, size: "small", leading: "compact", className: "text-ui-fg-subtle", children: description })) : null, hint ? (_jsx(Text, { id: `${id}-hint`, size: "small", leading: "compact", className: "text-ui-fg-muted", children: hint })) : null] }), _jsx(Switch, { id: id, "aria-describedby": describedBy || undefined, className: "shrink-0", checked: checked, disabled: disabled, onCheckedChange: (next) => onCheckedChange(next === true) }), trailing] }));
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
type WidgetHeaderProps = {
|
|
3
|
+
title: ReactNode;
|
|
4
|
+
/** Info button (`InfoTooltip`) next to the title, for the explanation that used to be a description. */
|
|
5
|
+
info?: ReactNode;
|
|
6
|
+
/** Button at the end, e.g. "Rechnung ausstellen". */
|
|
7
|
+
actions?: ReactNode;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Header of a compact side widget: `h2` with an optional info button and
|
|
11
|
+
* optional actions on one line (`px-6 py-3`). Sits at the top of a
|
|
12
|
+
* `Container className="divide-y p-0"`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const WidgetHeader: ({ title, info, actions }: WidgetHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Heading } from "@medusajs/ui";
|
|
3
|
+
/**
|
|
4
|
+
* Header of a compact side widget: `h2` with an optional info button and
|
|
5
|
+
* optional actions on one line (`px-6 py-3`). Sits at the top of a
|
|
6
|
+
* `Container className="divide-y p-0"`.
|
|
7
|
+
*/
|
|
8
|
+
export const WidgetHeader = ({ title, info, actions }) => (_jsxs("div", { className: "flex items-center justify-between gap-3 px-6 py-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-x-1", children: [_jsx(Heading, { level: "h2", children: title }), info] }), actions ? _jsx("div", { className: "flex shrink-0 items-center gap-2", children: actions }) : null] }));
|