@kilivi/payloadcms-theme-management 2.0.0 → 2.2.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/README.md +346 -845
- package/dist/components/AppearanceSessionControls.d.ts +15 -0
- package/dist/components/AppearanceSessionControls.d.ts.map +1 -0
- package/dist/components/AppearanceSessionControls.js +152 -0
- package/dist/components/AppearanceSessionControls.js.map +1 -0
- package/dist/components/ColorModeToggle.css +42 -0
- package/dist/components/ColorModeToggle.d.ts +40 -0
- package/dist/components/ColorModeToggle.d.ts.map +1 -0
- package/dist/components/ColorModeToggle.js +111 -0
- package/dist/components/ColorModeToggle.js.map +1 -0
- package/dist/components/ServerThemeInjector.d.ts +13 -1
- package/dist/components/ServerThemeInjector.d.ts.map +1 -1
- package/dist/components/ServerThemeInjector.js +65 -15
- package/dist/components/ServerThemeInjector.js.map +1 -1
- package/dist/components/ThemeLivePreviewSync.d.ts +4 -0
- package/dist/components/ThemeLivePreviewSync.d.ts.map +1 -1
- package/dist/components/ThemeLivePreviewSync.js +28 -4
- package/dist/components/ThemeLivePreviewSync.js.map +1 -1
- package/dist/components/ThemeSwitcher.d.ts +36 -0
- package/dist/components/ThemeSwitcher.d.ts.map +1 -0
- package/dist/components/ThemeSwitcher.js +89 -0
- package/dist/components/ThemeSwitcher.js.map +1 -0
- package/dist/components/typographyPreviewUtils.d.ts +5 -0
- package/dist/components/typographyPreviewUtils.d.ts.map +1 -1
- package/dist/components/typographyPreviewUtils.js +24 -11
- package/dist/components/typographyPreviewUtils.js.map +1 -1
- package/dist/constants/devicePreviews.d.ts +35 -0
- package/dist/constants/devicePreviews.d.ts.map +1 -0
- package/dist/constants/devicePreviews.js +43 -0
- package/dist/constants/devicePreviews.js.map +1 -0
- package/dist/constants/themeFonts.d.ts +94 -168
- package/dist/constants/themeFonts.d.ts.map +1 -1
- package/dist/constants/themeFonts.js +260 -140
- package/dist/constants/themeFonts.js.map +1 -1
- package/dist/endpoints/themeFonts.d.ts +5 -0
- package/dist/endpoints/themeFonts.d.ts.map +1 -0
- package/dist/endpoints/themeFonts.js +138 -0
- package/dist/endpoints/themeFonts.js.map +1 -0
- package/dist/extended-presets.d.ts +0 -4
- package/dist/extended-presets.d.ts.map +1 -1
- package/dist/extended-presets.js +1 -18
- package/dist/extended-presets.js.map +1 -1
- package/dist/extended-themes.d.ts.map +1 -1
- package/dist/extended-themes.js +428 -0
- package/dist/extended-themes.js.map +1 -1
- package/dist/fields/AccessibilityAuditField.d.ts +2 -0
- package/dist/fields/AccessibilityAuditField.d.ts.map +1 -0
- package/dist/fields/AccessibilityAuditField.js +303 -0
- package/dist/fields/AccessibilityAuditField.js.map +1 -0
- package/dist/fields/AppearancePreviewField.d.ts +2 -0
- package/dist/fields/AppearancePreviewField.d.ts.map +1 -0
- package/dist/fields/AppearancePreviewField.js +826 -0
- package/dist/fields/AppearancePreviewField.js.map +1 -0
- package/dist/fields/ColorPickerField.d.ts.map +1 -1
- package/dist/fields/ColorPickerField.js +89 -85
- package/dist/fields/ColorPickerField.js.map +1 -1
- package/dist/fields/FontSelectField.css +155 -0
- package/dist/fields/FontSelectField.d.ts +8 -0
- package/dist/fields/FontSelectField.d.ts.map +1 -1
- package/dist/fields/FontSelectField.js +223 -188
- package/dist/fields/FontSelectField.js.map +1 -1
- package/dist/fields/PaletteGeneratorField.d.ts +7 -0
- package/dist/fields/PaletteGeneratorField.d.ts.map +1 -0
- package/dist/fields/PaletteGeneratorField.js +327 -0
- package/dist/fields/PaletteGeneratorField.js.map +1 -0
- package/dist/fields/StylePresetField.d.ts +3 -0
- package/dist/fields/StylePresetField.d.ts.map +1 -0
- package/dist/fields/StylePresetField.js +463 -0
- package/dist/fields/StylePresetField.js.map +1 -0
- package/dist/fields/ThemeColorPickerField.css +115 -35
- package/dist/fields/ThemeColorPickerField.d.ts.map +1 -1
- package/dist/fields/ThemeColorPickerField.js +204 -70
- package/dist/fields/ThemeColorPickerField.js.map +1 -1
- package/dist/fields/ThemeExportField.d.ts +6 -0
- package/dist/fields/ThemeExportField.d.ts.map +1 -0
- package/dist/fields/ThemeExportField.js +202 -0
- package/dist/fields/ThemeExportField.js.map +1 -0
- package/dist/fields/ThemePresetImportField.d.ts.map +1 -1
- package/dist/fields/ThemePresetImportField.js +56 -25
- package/dist/fields/ThemePresetImportField.js.map +1 -1
- package/dist/fields/ThemePreviewField.css +444 -5
- package/dist/fields/ThemePreviewField.d.ts.map +1 -1
- package/dist/fields/ThemePreviewField.js +265 -170
- package/dist/fields/ThemePreviewField.js.map +1 -1
- package/dist/fields/ThemeTokenSelectField.d.ts.map +1 -1
- package/dist/fields/ThemeTokenSelectField.js +278 -80
- package/dist/fields/ThemeTokenSelectField.js.map +1 -1
- package/dist/fields/colorFieldHelpers.d.ts +90 -0
- package/dist/fields/colorFieldHelpers.d.ts.map +1 -0
- package/dist/fields/colorFieldHelpers.js +133 -0
- package/dist/fields/colorFieldHelpers.js.map +1 -0
- package/dist/fields/colorModeFields.d.ts +1 -1
- package/dist/fields/colorModeFields.d.ts.map +1 -1
- package/dist/fields/colorModeFields.js +49 -7
- package/dist/fields/colorModeFields.js.map +1 -1
- package/dist/fields/themeConfigurationField.d.ts +8 -1
- package/dist/fields/themeConfigurationField.d.ts.map +1 -1
- package/dist/fields/themeConfigurationField.js +1209 -228
- package/dist/fields/themeConfigurationField.js.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.js +8 -4
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.js.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/index.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/index.js +81 -26
- package/dist/globals/ThemeSettings/FontPicker/index.js.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/styles.css +98 -41
- package/dist/globals/ThemeSettings/FontPicker/translations.d.ts +6 -0
- package/dist/globals/ThemeSettings/FontPicker/translations.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/translations.js +14 -2
- package/dist/globals/ThemeSettings/FontPicker/translations.js.map +1 -1
- package/dist/globals/ThemeSettings/config.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/config.js +76 -79
- package/dist/globals/ThemeSettings/config.js.map +1 -1
- package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.js +63 -62
- package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.js.map +1 -1
- package/dist/globals/ThemeSettings/fields/TypographyInfoField.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/fields/TypographyInfoField.js +22 -25
- package/dist/globals/ThemeSettings/fields/TypographyInfoField.js.map +1 -1
- package/dist/hooks/useAppearanceSession.d.ts +50 -0
- package/dist/hooks/useAppearanceSession.d.ts.map +1 -0
- package/dist/hooks/useAppearanceSession.js +91 -0
- package/dist/hooks/useAppearanceSession.js.map +1 -0
- package/dist/hooks/useNativeLivePreview.d.ts +15 -0
- package/dist/hooks/useNativeLivePreview.d.ts.map +1 -0
- package/dist/hooks/useNativeLivePreview.js +18 -0
- package/dist/hooks/useNativeLivePreview.js.map +1 -0
- package/dist/hooks/useThemeFonts.d.ts +10 -0
- package/dist/hooks/useThemeFonts.d.ts.map +1 -0
- package/dist/hooks/useThemeFonts.js +36 -0
- package/dist/hooks/useThemeFonts.js.map +1 -0
- package/dist/hooks/useThemeTranslations.d.ts +13 -0
- package/dist/hooks/useThemeTranslations.d.ts.map +1 -0
- package/dist/hooks/useThemeTranslations.js +22 -0
- package/dist/hooks/useThemeTranslations.js.map +1 -0
- package/dist/i18n.d.ts +53 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +53 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +59 -29
- package/dist/index.js.map +1 -1
- package/dist/next-fonts.d.ts +3 -0
- package/dist/next-fonts.d.ts.map +1 -0
- package/dist/next-fonts.js +360 -0
- package/dist/next-fonts.js.map +1 -0
- package/dist/payload-types.d.ts +34 -6
- package/dist/payload-types.d.ts.map +1 -1
- package/dist/payload-types.js.map +1 -1
- package/dist/presets.d.ts +14 -0
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js.map +1 -1
- package/dist/providers/Theme/index.d.ts.map +1 -1
- package/dist/providers/Theme/index.js +75 -11
- package/dist/providers/Theme/index.js.map +1 -1
- package/dist/providers/Theme/themeConfig.d.ts.map +1 -1
- package/dist/providers/Theme/themeConfig.js +104 -0
- package/dist/providers/Theme/themeConfig.js.map +1 -1
- package/dist/providers/Theme/types.d.ts +1 -1
- package/dist/providers/Theme/types.d.ts.map +1 -1
- package/dist/providers/Theme/types.js +10 -1
- package/dist/providers/Theme/types.js.map +1 -1
- package/dist/style-presets.d.ts +75 -0
- package/dist/style-presets.d.ts.map +1 -0
- package/dist/style-presets.js +738 -0
- package/dist/style-presets.js.map +1 -0
- package/dist/translations.d.ts +164 -1
- package/dist/translations.d.ts.map +1 -1
- package/dist/translations.js +320 -9
- package/dist/translations.js.map +1 -1
- package/dist/tweakcn-special-themes.d.ts.map +1 -1
- package/dist/tweakcn-special-themes.js +585 -9
- package/dist/tweakcn-special-themes.js.map +1 -1
- package/dist/types/css.d.js +3 -0
- package/dist/types/css.d.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities/getThemeSettings.d.ts.map +1 -1
- package/dist/utilities/getThemeSettings.js +2 -14
- package/dist/utilities/getThemeSettings.js.map +1 -1
- package/dist/utils/contrast.d.ts +63 -0
- package/dist/utils/contrast.d.ts.map +1 -0
- package/dist/utils/contrast.js +158 -0
- package/dist/utils/contrast.js.map +1 -0
- package/dist/utils/exportTokens.d.ts +30 -0
- package/dist/utils/exportTokens.d.ts.map +1 -0
- package/dist/utils/exportTokens.js +183 -0
- package/dist/utils/exportTokens.js.map +1 -0
- package/dist/utils/generatePalette.d.ts +46 -0
- package/dist/utils/generatePalette.d.ts.map +1 -0
- package/dist/utils/generatePalette.js +127 -0
- package/dist/utils/generatePalette.js.map +1 -0
- package/dist/utils/generateThemeCSS.d.ts.map +1 -1
- package/dist/utils/generateThemeCSS.js +2 -40
- package/dist/utils/generateThemeCSS.js.map +1 -1
- package/dist/utils/livePreviewThemeRuntime.d.ts +22 -3
- package/dist/utils/livePreviewThemeRuntime.d.ts.map +1 -1
- package/dist/utils/livePreviewThemeRuntime.js +48 -15
- package/dist/utils/livePreviewThemeRuntime.js.map +1 -1
- package/dist/utils/localizedText.d.ts +8 -0
- package/dist/utils/localizedText.d.ts.map +1 -0
- package/dist/utils/localizedText.js +21 -0
- package/dist/utils/localizedText.js.map +1 -0
- package/dist/utils/resolveThemeConfiguration.d.ts +60 -1
- package/dist/utils/resolveThemeConfiguration.d.ts.map +1 -1
- package/dist/utils/resolveThemeConfiguration.js +53 -13
- package/dist/utils/resolveThemeConfiguration.js.map +1 -1
- package/dist/utils/themeColors.d.ts +3 -0
- package/dist/utils/themeColors.d.ts.map +1 -1
- package/dist/utils/themeColors.js +30 -1
- package/dist/utils/themeColors.js.map +1 -1
- package/dist/utils/themeHtmlAttributes.d.ts +32 -12
- package/dist/utils/themeHtmlAttributes.d.ts.map +1 -1
- package/dist/utils/themeHtmlAttributes.js +38 -5
- package/dist/utils/themeHtmlAttributes.js.map +1 -1
- package/dist/utils/themeUtils.d.ts +3 -5
- package/dist/utils/themeUtils.d.ts.map +1 -1
- package/dist/utils/themeUtils.js +474 -6
- package/dist/utils/themeUtils.js.map +1 -1
- package/dist/utils/tweakcnConverter.d.ts +1 -3
- package/dist/utils/tweakcnConverter.d.ts.map +1 -1
- package/dist/utils/tweakcnConverter.js +1 -3
- package/dist/utils/tweakcnConverter.js.map +1 -1
- package/package.json +15 -5
- package/dist/components/ThemePreview.d.ts +0 -3
- package/dist/components/ThemePreview.d.ts.map +0 -1
- package/dist/components/ThemePreview.js +0 -321
- package/dist/components/ThemePreview.js.map +0 -1
- package/dist/plugin.d.ts +0 -2
- package/dist/plugin.d.ts.map +0 -1
- package/dist/plugin.js +0 -3
- package/dist/plugin.js.map +0 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useLivePreview } from '@payloadcms/live-preview-react';
|
|
3
|
-
import { useEffect, useMemo } from 'react';
|
|
3
|
+
import React, { useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { buildLivePreviewThemeRuntime, extractThemeConfigurationFromLiveData } from '../utils/livePreviewThemeRuntime.js';
|
|
5
|
-
export const ThemeLivePreviewSync = ({ initialData, serverURL, apiRoute, depth, themeConfigurationKey = 'themeConfiguration', styleElementId = 'theme-live-preview-css' })=>{
|
|
5
|
+
export const ThemeLivePreviewSync = ({ initialData, serverURL, apiRoute, depth, themeConfigurationKey = 'themeConfiguration', styleElementId = 'theme-live-preview-css', fontLoading = 'self-hosted' })=>{
|
|
6
6
|
const { data } = useLivePreview({
|
|
7
7
|
apiRoute,
|
|
8
8
|
depth,
|
|
9
9
|
initialData,
|
|
10
10
|
serverURL
|
|
11
11
|
});
|
|
12
|
+
const appliedAttributes = useRef([]);
|
|
12
13
|
const themeConfiguration = useMemo(()=>extractThemeConfigurationFromLiveData(data, themeConfigurationKey), [
|
|
13
14
|
data,
|
|
14
15
|
themeConfigurationKey
|
|
@@ -17,7 +18,7 @@ export const ThemeLivePreviewSync = ({ initialData, serverURL, apiRoute, depth,
|
|
|
17
18
|
if (typeof document === 'undefined' || !themeConfiguration) {
|
|
18
19
|
return;
|
|
19
20
|
}
|
|
20
|
-
const runtime = buildLivePreviewThemeRuntime(themeConfiguration);
|
|
21
|
+
const runtime = buildLivePreviewThemeRuntime(themeConfiguration, apiRoute, fontLoading);
|
|
21
22
|
let styleElement = document.getElementById(styleElementId);
|
|
22
23
|
if (!styleElement) {
|
|
23
24
|
styleElement = document.createElement('style');
|
|
@@ -25,6 +26,27 @@ export const ThemeLivePreviewSync = ({ initialData, serverURL, apiRoute, depth,
|
|
|
25
26
|
document.head.appendChild(styleElement);
|
|
26
27
|
}
|
|
27
28
|
styleElement.innerHTML = runtime.css;
|
|
29
|
+
const fontsLinkId = `${styleElementId}-fonts`;
|
|
30
|
+
let fontsLink = document.getElementById(fontsLinkId);
|
|
31
|
+
const fontsAlreadyLoaded = runtime.fontsHref !== null && [
|
|
32
|
+
...document.querySelectorAll('link[rel="stylesheet"]')
|
|
33
|
+
].some((link)=>link !== fontsLink && link.getAttribute('href') === runtime.fontsHref);
|
|
34
|
+
if (runtime.fontsHref && !fontsAlreadyLoaded) {
|
|
35
|
+
if (!fontsLink) {
|
|
36
|
+
fontsLink = document.createElement('link');
|
|
37
|
+
fontsLink.id = fontsLinkId;
|
|
38
|
+
fontsLink.rel = 'stylesheet';
|
|
39
|
+
document.head.appendChild(fontsLink);
|
|
40
|
+
}
|
|
41
|
+
if (fontsLink.getAttribute('href') !== runtime.fontsHref) fontsLink.href = runtime.fontsHref;
|
|
42
|
+
} else {
|
|
43
|
+
fontsLink?.remove();
|
|
44
|
+
}
|
|
45
|
+
const root = document.documentElement;
|
|
46
|
+
// Drop style attributes that are no longer configured, then apply the current set.
|
|
47
|
+
appliedAttributes.current.filter((name)=>!(name in runtime.attributes)).forEach((name)=>root.removeAttribute(name));
|
|
48
|
+
Object.entries(runtime.attributes).forEach(([name, value])=>root.setAttribute(name, value));
|
|
49
|
+
appliedAttributes.current = Object.keys(runtime.attributes);
|
|
28
50
|
document.documentElement.dataset.theme = runtime.theme;
|
|
29
51
|
document.documentElement.dataset.colorMode = runtime.mode;
|
|
30
52
|
document.documentElement.dataset.themeMode = runtime.mode;
|
|
@@ -32,7 +54,9 @@ export const ThemeLivePreviewSync = ({ initialData, serverURL, apiRoute, depth,
|
|
|
32
54
|
document.documentElement.classList.add(runtime.mode);
|
|
33
55
|
}, [
|
|
34
56
|
themeConfiguration,
|
|
35
|
-
styleElementId
|
|
57
|
+
styleElementId,
|
|
58
|
+
apiRoute,
|
|
59
|
+
fontLoading
|
|
36
60
|
]);
|
|
37
61
|
return null;
|
|
38
62
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ThemeLivePreviewSync.tsx"],"sourcesContent":["'use client'\n\nimport { useLivePreview } from '@payloadcms/live-preview-react'\nimport { useEffect, useMemo } from 'react'\nimport {\n buildLivePreviewThemeRuntime,\n extractThemeConfigurationFromLiveData,\n} from '../utils/livePreviewThemeRuntime.js'\n\ninterface ThemeLivePreviewSyncProps {\n initialData: Record<string, unknown>\n serverURL: string\n apiRoute?: string\n depth?: number\n themeConfigurationKey?: string\n styleElementId?: string\n}\n\nexport const ThemeLivePreviewSync: React.FC<ThemeLivePreviewSyncProps> = ({\n initialData,\n serverURL,\n apiRoute,\n depth,\n themeConfigurationKey = 'themeConfiguration',\n styleElementId = 'theme-live-preview-css',\n}) => {\n const { data } = useLivePreview<Record<string, unknown>>({\n apiRoute,\n depth,\n initialData,\n serverURL,\n })\n\n const themeConfiguration = useMemo(\n () => extractThemeConfigurationFromLiveData(data, themeConfigurationKey),\n [data, themeConfigurationKey],\n )\n\n useEffect(() => {\n if (typeof document === 'undefined' || !themeConfiguration) {\n return\n }\n\n const runtime = buildLivePreviewThemeRuntime(themeConfiguration)\n\n let styleElement = document.getElementById(styleElementId) as HTMLStyleElement | null\n if (!styleElement) {\n styleElement = document.createElement('style')\n styleElement.id = styleElementId\n document.head.appendChild(styleElement)\n }\n\n styleElement.innerHTML = runtime.css\n\n document.documentElement.dataset.theme = runtime.theme\n document.documentElement.dataset.colorMode = runtime.mode\n document.documentElement.dataset.themeMode = runtime.mode\n document.documentElement.classList.remove('light', 'dark', 'auto')\n document.documentElement.classList.add(runtime.mode)\n }, [themeConfiguration, styleElementId])\n\n return null\n}\n"],"names":["useLivePreview","useEffect","useMemo","buildLivePreviewThemeRuntime","extractThemeConfigurationFromLiveData","ThemeLivePreviewSync","initialData","serverURL","apiRoute","depth","themeConfigurationKey","styleElementId","data","themeConfiguration","document","runtime","styleElement","getElementById","createElement","id","head","appendChild","innerHTML","css","documentElement","dataset","theme","colorMode","mode","themeMode","classList","
|
|
1
|
+
{"version":3,"sources":["../../src/components/ThemeLivePreviewSync.tsx"],"sourcesContent":["'use client'\n\nimport { useLivePreview } from '@payloadcms/live-preview-react'\nimport React, { useEffect, useMemo, useRef } from 'react'\nimport type { ThemeFontLoading } from '../constants/themeFonts.js'\nimport {\n buildLivePreviewThemeRuntime,\n extractThemeConfigurationFromLiveData,\n} from '../utils/livePreviewThemeRuntime.js'\n\ninterface ThemeLivePreviewSyncProps {\n initialData: Record<string, unknown>\n serverURL: string\n apiRoute?: string\n depth?: number\n themeConfigurationKey?: string\n styleElementId?: string\n /** Same as ServerThemeInjector's `fontLoading`; use 'none' with next/font. */\n fontLoading?: ThemeFontLoading\n}\n\nexport const ThemeLivePreviewSync: React.FC<ThemeLivePreviewSyncProps> = ({\n initialData,\n serverURL,\n apiRoute,\n depth,\n themeConfigurationKey = 'themeConfiguration',\n styleElementId = 'theme-live-preview-css',\n fontLoading = 'self-hosted',\n}) => {\n const { data } = useLivePreview<Record<string, unknown>>({\n apiRoute,\n depth,\n initialData,\n serverURL,\n })\n\n const appliedAttributes = useRef<string[]>([])\n\n const themeConfiguration = useMemo(\n () => extractThemeConfigurationFromLiveData(data, themeConfigurationKey),\n [data, themeConfigurationKey],\n )\n\n useEffect(() => {\n if (typeof document === 'undefined' || !themeConfiguration) {\n return\n }\n\n const runtime = buildLivePreviewThemeRuntime(themeConfiguration, apiRoute, fontLoading)\n\n let styleElement = document.getElementById(styleElementId) as HTMLStyleElement | null\n if (!styleElement) {\n styleElement = document.createElement('style')\n styleElement.id = styleElementId\n document.head.appendChild(styleElement)\n }\n\n styleElement.innerHTML = runtime.css\n\n const fontsLinkId = `${styleElementId}-fonts`\n let fontsLink = document.getElementById(fontsLinkId) as HTMLLinkElement | null\n const fontsAlreadyLoaded =\n runtime.fontsHref !== null &&\n [...document.querySelectorAll<HTMLLinkElement>('link[rel=\"stylesheet\"]')].some(\n (link) => link !== fontsLink && link.getAttribute('href') === runtime.fontsHref,\n )\n if (runtime.fontsHref && !fontsAlreadyLoaded) {\n if (!fontsLink) {\n fontsLink = document.createElement('link')\n fontsLink.id = fontsLinkId\n fontsLink.rel = 'stylesheet'\n document.head.appendChild(fontsLink)\n }\n if (fontsLink.getAttribute('href') !== runtime.fontsHref) fontsLink.href = runtime.fontsHref\n } else {\n fontsLink?.remove()\n }\n\n const root = document.documentElement\n // Drop style attributes that are no longer configured, then apply the current set.\n appliedAttributes.current\n .filter((name) => !(name in runtime.attributes))\n .forEach((name) => root.removeAttribute(name))\n Object.entries(runtime.attributes).forEach(([name, value]) => root.setAttribute(name, value))\n appliedAttributes.current = Object.keys(runtime.attributes)\n\n document.documentElement.dataset.theme = runtime.theme\n document.documentElement.dataset.colorMode = runtime.mode\n document.documentElement.dataset.themeMode = runtime.mode\n document.documentElement.classList.remove('light', 'dark', 'auto')\n document.documentElement.classList.add(runtime.mode)\n }, [themeConfiguration, styleElementId, apiRoute, fontLoading])\n\n return null\n}\n"],"names":["useLivePreview","React","useEffect","useMemo","useRef","buildLivePreviewThemeRuntime","extractThemeConfigurationFromLiveData","ThemeLivePreviewSync","initialData","serverURL","apiRoute","depth","themeConfigurationKey","styleElementId","fontLoading","data","appliedAttributes","themeConfiguration","document","runtime","styleElement","getElementById","createElement","id","head","appendChild","innerHTML","css","fontsLinkId","fontsLink","fontsAlreadyLoaded","fontsHref","querySelectorAll","some","link","getAttribute","rel","href","remove","root","documentElement","current","filter","name","attributes","forEach","removeAttribute","Object","entries","value","setAttribute","keys","dataset","theme","colorMode","mode","themeMode","classList","add"],"mappings":"AAAA;AAEA,SAASA,cAAc,QAAQ,iCAAgC;AAC/D,OAAOC,SAASC,SAAS,EAAEC,OAAO,EAAEC,MAAM,QAAQ,QAAO;AAEzD,SACEC,4BAA4B,EAC5BC,qCAAqC,QAChC,sCAAqC;AAa5C,OAAO,MAAMC,uBAA4D,CAAC,EACxEC,WAAW,EACXC,SAAS,EACTC,QAAQ,EACRC,KAAK,EACLC,wBAAwB,oBAAoB,EAC5CC,iBAAiB,wBAAwB,EACzCC,cAAc,aAAa,EAC5B;IACC,MAAM,EAAEC,IAAI,EAAE,GAAGf,eAAwC;QACvDU;QACAC;QACAH;QACAC;IACF;IAEA,MAAMO,oBAAoBZ,OAAiB,EAAE;IAE7C,MAAMa,qBAAqBd,QACzB,IAAMG,sCAAsCS,MAAMH,wBAClD;QAACG;QAAMH;KAAsB;IAG/BV,UAAU;QACR,IAAI,OAAOgB,aAAa,eAAe,CAACD,oBAAoB;YAC1D;QACF;QAEA,MAAME,UAAUd,6BAA6BY,oBAAoBP,UAAUI;QAE3E,IAAIM,eAAeF,SAASG,cAAc,CAACR;QAC3C,IAAI,CAACO,cAAc;YACjBA,eAAeF,SAASI,aAAa,CAAC;YACtCF,aAAaG,EAAE,GAAGV;YAClBK,SAASM,IAAI,CAACC,WAAW,CAACL;QAC5B;QAEAA,aAAaM,SAAS,GAAGP,QAAQQ,GAAG;QAEpC,MAAMC,cAAc,GAAGf,eAAe,MAAM,CAAC;QAC7C,IAAIgB,YAAYX,SAASG,cAAc,CAACO;QACxC,MAAME,qBACJX,QAAQY,SAAS,KAAK,QACtB;eAAIb,SAASc,gBAAgB,CAAkB;SAA0B,CAACC,IAAI,CAC5E,CAACC,OAASA,SAASL,aAAaK,KAAKC,YAAY,CAAC,YAAYhB,QAAQY,SAAS;QAEnF,IAAIZ,QAAQY,SAAS,IAAI,CAACD,oBAAoB;YAC5C,IAAI,CAACD,WAAW;gBACdA,YAAYX,SAASI,aAAa,CAAC;gBACnCO,UAAUN,EAAE,GAAGK;gBACfC,UAAUO,GAAG,GAAG;gBAChBlB,SAASM,IAAI,CAACC,WAAW,CAACI;YAC5B;YACA,IAAIA,UAAUM,YAAY,CAAC,YAAYhB,QAAQY,SAAS,EAAEF,UAAUQ,IAAI,GAAGlB,QAAQY,SAAS;QAC9F,OAAO;YACLF,WAAWS;QACb;QAEA,MAAMC,OAAOrB,SAASsB,eAAe;QACrC,mFAAmF;QACnFxB,kBAAkByB,OAAO,CACtBC,MAAM,CAAC,CAACC,OAAS,CAAEA,CAAAA,QAAQxB,QAAQyB,UAAU,AAAD,GAC5CC,OAAO,CAAC,CAACF,OAASJ,KAAKO,eAAe,CAACH;QAC1CI,OAAOC,OAAO,CAAC7B,QAAQyB,UAAU,EAAEC,OAAO,CAAC,CAAC,CAACF,MAAMM,MAAM,GAAKV,KAAKW,YAAY,CAACP,MAAMM;QACtFjC,kBAAkByB,OAAO,GAAGM,OAAOI,IAAI,CAAChC,QAAQyB,UAAU;QAE1D1B,SAASsB,eAAe,CAACY,OAAO,CAACC,KAAK,GAAGlC,QAAQkC,KAAK;QACtDnC,SAASsB,eAAe,CAACY,OAAO,CAACE,SAAS,GAAGnC,QAAQoC,IAAI;QACzDrC,SAASsB,eAAe,CAACY,OAAO,CAACI,SAAS,GAAGrC,QAAQoC,IAAI;QACzDrC,SAASsB,eAAe,CAACiB,SAAS,CAACnB,MAAM,CAAC,SAAS,QAAQ;QAC3DpB,SAASsB,eAAe,CAACiB,SAAS,CAACC,GAAG,CAACvC,QAAQoC,IAAI;IACrD,GAAG;QAACtC;QAAoBJ;QAAgBH;QAAUI;KAAY;IAE9D,OAAO;AACT,EAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ThemePreset } from '../presets.js';
|
|
3
|
+
export type SwitchablePreset = Pick<ThemePreset, 'name' | 'label' | 'lightMode' | 'darkMode'>;
|
|
4
|
+
export interface ThemeSwitcherProps {
|
|
5
|
+
/**
|
|
6
|
+
* Presets the visitor can switch between. Defaults to all bundled presets.
|
|
7
|
+
* Pass a curated subset for a focused switcher.
|
|
8
|
+
*/
|
|
9
|
+
presets?: SwitchablePreset[];
|
|
10
|
+
className?: string;
|
|
11
|
+
style?: React.CSSProperties;
|
|
12
|
+
'aria-label'?: string;
|
|
13
|
+
/** Persist the choice to localStorage and restore it on load. Default true. */
|
|
14
|
+
persist?: boolean;
|
|
15
|
+
/** Called after a preset is applied. */
|
|
16
|
+
onChange?: (presetName: string) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Front-end theme-preset switcher. Lets visitors swap between bundled (or a
|
|
20
|
+
* curated subset of) theme presets at runtime by injecting the preset's colour
|
|
21
|
+
* CSS and updating `data-theme`. The choice is persisted to localStorage and
|
|
22
|
+
* restored on the next visit.
|
|
23
|
+
*
|
|
24
|
+
* Note: colour-mode (light/dark) is handled by {@link ColorModeToggle} and the
|
|
25
|
+
* SSR injector with no flash; preset switching re-applies on mount, so a brief
|
|
26
|
+
* flash to the SSR default can occur before the stored preset is restored.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* import { ThemeSwitcher } from '@kilivi/payloadcms-theme-management/components/ThemeSwitcher'
|
|
31
|
+
* <ThemeSwitcher presets={[oceanPreset, forestPreset]} />
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare const ThemeSwitcher: React.FC<ThemeSwitcherProps>;
|
|
35
|
+
export default ThemeSwitcher;
|
|
36
|
+
//# sourceMappingURL=ThemeSwitcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeSwitcher.d.ts","sourceRoot":"","sources":["../../src/components/ThemeSwitcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAA;AAC/D,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAA;AAMjE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,UAAU,CAAC,CAAA;AAE7F,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CACxC;AAuBD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6DtD,CAAA;AAED,eAAe,aAAa,CAAA"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
4
|
+
import { allThemePresets } from '../presets.js';
|
|
5
|
+
import { themeLocalStorageKey } from '../providers/Theme/shared.js';
|
|
6
|
+
import { generateThemeColorsCss } from '../utils/themeColors.js';
|
|
7
|
+
const STYLE_ID = 'tm-theme-switcher-css';
|
|
8
|
+
const applyPreset = (preset)=>{
|
|
9
|
+
if (typeof document === 'undefined') return;
|
|
10
|
+
// Generate with the preset name so selectors match `:root[data-theme='name']`
|
|
11
|
+
// and override the SSR-injected theme (same specificity, injected later wins).
|
|
12
|
+
const css = generateThemeColorsCss({
|
|
13
|
+
themeName: preset.name,
|
|
14
|
+
lightMode: preset.lightMode,
|
|
15
|
+
darkMode: preset.darkMode
|
|
16
|
+
});
|
|
17
|
+
let styleElement = document.getElementById(STYLE_ID);
|
|
18
|
+
if (!styleElement) {
|
|
19
|
+
styleElement = document.createElement('style');
|
|
20
|
+
styleElement.id = STYLE_ID;
|
|
21
|
+
document.head.appendChild(styleElement);
|
|
22
|
+
}
|
|
23
|
+
styleElement.innerHTML = css;
|
|
24
|
+
document.documentElement.setAttribute('data-theme', preset.name);
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Front-end theme-preset switcher. Lets visitors swap between bundled (or a
|
|
28
|
+
* curated subset of) theme presets at runtime by injecting the preset's colour
|
|
29
|
+
* CSS and updating `data-theme`. The choice is persisted to localStorage and
|
|
30
|
+
* restored on the next visit.
|
|
31
|
+
*
|
|
32
|
+
* Note: colour-mode (light/dark) is handled by {@link ColorModeToggle} and the
|
|
33
|
+
* SSR injector with no flash; preset switching re-applies on mount, so a brief
|
|
34
|
+
* flash to the SSR default can occur before the stored preset is restored.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* import { ThemeSwitcher } from '@kilivi/payloadcms-theme-management/components/ThemeSwitcher'
|
|
39
|
+
* <ThemeSwitcher presets={[oceanPreset, forestPreset]} />
|
|
40
|
+
* ```
|
|
41
|
+
*/ export const ThemeSwitcher = ({ presets, className, style, 'aria-label': ariaLabel, persist = true, onChange })=>{
|
|
42
|
+
const list = presets && presets.length > 0 ? presets : allThemePresets;
|
|
43
|
+
const [selected, setSelected] = useState('');
|
|
44
|
+
// Restore the stored preset (or reflect the current data-theme) after mount.
|
|
45
|
+
useEffect(()=>{
|
|
46
|
+
if (typeof document === 'undefined') return;
|
|
47
|
+
const current = document.documentElement.getAttribute('data-theme') ?? '';
|
|
48
|
+
const stored = persist ? window.localStorage.getItem(themeLocalStorageKey) : null;
|
|
49
|
+
const initial = stored && list.some((p)=>p.name === stored) ? stored : current;
|
|
50
|
+
if (initial) {
|
|
51
|
+
setSelected(initial);
|
|
52
|
+
const preset = list.find((p)=>p.name === initial);
|
|
53
|
+
// Only re-inject when the stored preset differs from what SSR rendered.
|
|
54
|
+
if (preset && stored && stored !== current) {
|
|
55
|
+
applyPreset(preset);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Intentionally run once on mount to restore the persisted preset.
|
|
59
|
+
}, []);
|
|
60
|
+
const handleChange = useCallback((event)=>{
|
|
61
|
+
const name = event.target.value;
|
|
62
|
+
const preset = list.find((p)=>p.name === name);
|
|
63
|
+
if (!preset) return;
|
|
64
|
+
setSelected(name);
|
|
65
|
+
applyPreset(preset);
|
|
66
|
+
if (persist) {
|
|
67
|
+
window.localStorage.setItem(themeLocalStorageKey, name);
|
|
68
|
+
}
|
|
69
|
+
onChange?.(name);
|
|
70
|
+
}, [
|
|
71
|
+
list,
|
|
72
|
+
persist,
|
|
73
|
+
onChange
|
|
74
|
+
]);
|
|
75
|
+
return /*#__PURE__*/ _jsx("select", {
|
|
76
|
+
value: selected,
|
|
77
|
+
onChange: handleChange,
|
|
78
|
+
className: className,
|
|
79
|
+
style: style,
|
|
80
|
+
"aria-label": ariaLabel ?? 'Select theme',
|
|
81
|
+
children: list.map((preset)=>/*#__PURE__*/ _jsx("option", {
|
|
82
|
+
value: preset.name,
|
|
83
|
+
children: preset.label
|
|
84
|
+
}, preset.name))
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
export default ThemeSwitcher;
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=ThemeSwitcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/ThemeSwitcher.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useEffect, useState } from 'react'\nimport { allThemePresets, type ThemePreset } from '../presets.js'\nimport { themeLocalStorageKey } from '../providers/Theme/shared.js'\nimport { generateThemeColorsCss } from '../utils/themeColors.js'\n\nconst STYLE_ID = 'tm-theme-switcher-css'\n\nexport type SwitchablePreset = Pick<ThemePreset, 'name' | 'label' | 'lightMode' | 'darkMode'>\n\nexport interface ThemeSwitcherProps {\n /**\n * Presets the visitor can switch between. Defaults to all bundled presets.\n * Pass a curated subset for a focused switcher.\n */\n presets?: SwitchablePreset[]\n className?: string\n style?: React.CSSProperties\n 'aria-label'?: string\n /** Persist the choice to localStorage and restore it on load. Default true. */\n persist?: boolean\n /** Called after a preset is applied. */\n onChange?: (presetName: string) => void\n}\n\nconst applyPreset = (preset: SwitchablePreset): void => {\n if (typeof document === 'undefined') return\n\n // Generate with the preset name so selectors match `:root[data-theme='name']`\n // and override the SSR-injected theme (same specificity, injected later wins).\n const css = generateThemeColorsCss({\n themeName: preset.name,\n lightMode: preset.lightMode,\n darkMode: preset.darkMode,\n })\n\n let styleElement = document.getElementById(STYLE_ID) as HTMLStyleElement | null\n if (!styleElement) {\n styleElement = document.createElement('style')\n styleElement.id = STYLE_ID\n document.head.appendChild(styleElement)\n }\n styleElement.innerHTML = css\n document.documentElement.setAttribute('data-theme', preset.name)\n}\n\n/**\n * Front-end theme-preset switcher. Lets visitors swap between bundled (or a\n * curated subset of) theme presets at runtime by injecting the preset's colour\n * CSS and updating `data-theme`. The choice is persisted to localStorage and\n * restored on the next visit.\n *\n * Note: colour-mode (light/dark) is handled by {@link ColorModeToggle} and the\n * SSR injector with no flash; preset switching re-applies on mount, so a brief\n * flash to the SSR default can occur before the stored preset is restored.\n *\n * @example\n * ```tsx\n * import { ThemeSwitcher } from '@kilivi/payloadcms-theme-management/components/ThemeSwitcher'\n * <ThemeSwitcher presets={[oceanPreset, forestPreset]} />\n * ```\n */\nexport const ThemeSwitcher: React.FC<ThemeSwitcherProps> = ({\n presets,\n className,\n style,\n 'aria-label': ariaLabel,\n persist = true,\n onChange,\n}) => {\n const list: SwitchablePreset[] = presets && presets.length > 0 ? presets : allThemePresets\n const [selected, setSelected] = useState<string>('')\n\n // Restore the stored preset (or reflect the current data-theme) after mount.\n useEffect(() => {\n if (typeof document === 'undefined') return\n\n const current = document.documentElement.getAttribute('data-theme') ?? ''\n const stored = persist ? window.localStorage.getItem(themeLocalStorageKey) : null\n const initial = stored && list.some((p) => p.name === stored) ? stored : current\n\n if (initial) {\n setSelected(initial)\n const preset = list.find((p) => p.name === initial)\n // Only re-inject when the stored preset differs from what SSR rendered.\n if (preset && stored && stored !== current) {\n applyPreset(preset)\n }\n }\n // Intentionally run once on mount to restore the persisted preset.\n }, [])\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLSelectElement>) => {\n const name = event.target.value\n const preset = list.find((p) => p.name === name)\n if (!preset) return\n\n setSelected(name)\n applyPreset(preset)\n if (persist) {\n window.localStorage.setItem(themeLocalStorageKey, name)\n }\n onChange?.(name)\n },\n [list, persist, onChange],\n )\n\n return (\n <select\n value={selected}\n onChange={handleChange}\n className={className}\n style={style}\n aria-label={ariaLabel ?? 'Select theme'}\n >\n {list.map((preset) => (\n <option key={preset.name} value={preset.name}>\n {preset.label}\n </option>\n ))}\n </select>\n )\n}\n\nexport default ThemeSwitcher\n"],"names":["React","useCallback","useEffect","useState","allThemePresets","themeLocalStorageKey","generateThemeColorsCss","STYLE_ID","applyPreset","preset","document","css","themeName","name","lightMode","darkMode","styleElement","getElementById","createElement","id","head","appendChild","innerHTML","documentElement","setAttribute","ThemeSwitcher","presets","className","style","ariaLabel","persist","onChange","list","length","selected","setSelected","current","getAttribute","stored","window","localStorage","getItem","initial","some","p","find","handleChange","event","target","value","setItem","select","aria-label","map","option","label"],"mappings":"AAAA;;AAEA,OAAOA,SAASC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAC/D,SAASC,eAAe,QAA0B,gBAAe;AACjE,SAASC,oBAAoB,QAAQ,+BAA8B;AACnE,SAASC,sBAAsB,QAAQ,0BAAyB;AAEhE,MAAMC,WAAW;AAmBjB,MAAMC,cAAc,CAACC;IACnB,IAAI,OAAOC,aAAa,aAAa;IAErC,8EAA8E;IAC9E,+EAA+E;IAC/E,MAAMC,MAAML,uBAAuB;QACjCM,WAAWH,OAAOI,IAAI;QACtBC,WAAWL,OAAOK,SAAS;QAC3BC,UAAUN,OAAOM,QAAQ;IAC3B;IAEA,IAAIC,eAAeN,SAASO,cAAc,CAACV;IAC3C,IAAI,CAACS,cAAc;QACjBA,eAAeN,SAASQ,aAAa,CAAC;QACtCF,aAAaG,EAAE,GAAGZ;QAClBG,SAASU,IAAI,CAACC,WAAW,CAACL;IAC5B;IACAA,aAAaM,SAAS,GAAGX;IACzBD,SAASa,eAAe,CAACC,YAAY,CAAC,cAAcf,OAAOI,IAAI;AACjE;AAEA;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMY,gBAA8C,CAAC,EAC1DC,OAAO,EACPC,SAAS,EACTC,KAAK,EACL,cAAcC,SAAS,EACvBC,UAAU,IAAI,EACdC,QAAQ,EACT;IACC,MAAMC,OAA2BN,WAAWA,QAAQO,MAAM,GAAG,IAAIP,UAAUtB;IAC3E,MAAM,CAAC8B,UAAUC,YAAY,GAAGhC,SAAiB;IAEjD,6EAA6E;IAC7ED,UAAU;QACR,IAAI,OAAOQ,aAAa,aAAa;QAErC,MAAM0B,UAAU1B,SAASa,eAAe,CAACc,YAAY,CAAC,iBAAiB;QACvE,MAAMC,SAASR,UAAUS,OAAOC,YAAY,CAACC,OAAO,CAACpC,wBAAwB;QAC7E,MAAMqC,UAAUJ,UAAUN,KAAKW,IAAI,CAAC,CAACC,IAAMA,EAAE/B,IAAI,KAAKyB,UAAUA,SAASF;QAEzE,IAAIM,SAAS;YACXP,YAAYO;YACZ,MAAMjC,SAASuB,KAAKa,IAAI,CAAC,CAACD,IAAMA,EAAE/B,IAAI,KAAK6B;YAC3C,wEAAwE;YACxE,IAAIjC,UAAU6B,UAAUA,WAAWF,SAAS;gBAC1C5B,YAAYC;YACd;QACF;IACA,mEAAmE;IACrE,GAAG,EAAE;IAEL,MAAMqC,eAAe7C,YACnB,CAAC8C;QACC,MAAMlC,OAAOkC,MAAMC,MAAM,CAACC,KAAK;QAC/B,MAAMxC,SAASuB,KAAKa,IAAI,CAAC,CAACD,IAAMA,EAAE/B,IAAI,KAAKA;QAC3C,IAAI,CAACJ,QAAQ;QAEb0B,YAAYtB;QACZL,YAAYC;QACZ,IAAIqB,SAAS;YACXS,OAAOC,YAAY,CAACU,OAAO,CAAC7C,sBAAsBQ;QACpD;QACAkB,WAAWlB;IACb,GACA;QAACmB;QAAMF;QAASC;KAAS;IAG3B,qBACE,KAACoB;QACCF,OAAOf;QACPH,UAAUe;QACVnB,WAAWA;QACXC,OAAOA;QACPwB,cAAYvB,aAAa;kBAExBG,KAAKqB,GAAG,CAAC,CAAC5C,uBACT,KAAC6C;gBAAyBL,OAAOxC,OAAOI,IAAI;0BACzCJ,OAAO8C,KAAK;eADF9C,OAAOI,IAAI;;AAMhC,EAAC;AAED,eAAeY,cAAa"}
|
|
@@ -5,12 +5,17 @@ export interface TypographySelection {
|
|
|
5
5
|
headingFontCustom?: string | null;
|
|
6
6
|
baseFontSize?: string | null;
|
|
7
7
|
lineHeight?: string | null;
|
|
8
|
+
headingWeight?: string | null;
|
|
9
|
+
letterSpacing?: string | null;
|
|
8
10
|
}
|
|
9
11
|
export interface ResolvedTypographyPreview {
|
|
10
12
|
bodyFont: string;
|
|
11
13
|
headingFont: string;
|
|
12
14
|
baseFontSize: string;
|
|
13
15
|
lineHeight: string;
|
|
16
|
+
headingWeight: string;
|
|
17
|
+
headingLetterSpacing: string;
|
|
18
|
+
headingTransform: 'none' | 'uppercase';
|
|
14
19
|
bodyLabel: string;
|
|
15
20
|
headingLabel: string;
|
|
16
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typographyPreviewUtils.d.ts","sourceRoot":"","sources":["../../src/components/typographyPreviewUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"typographyPreviewUtils.d.ts","sourceRoot":"","sources":["../../src/components/typographyPreviewUtils.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,gBAAgB,EAAE,MAAM,GAAG,WAAW,CAAA;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AA+ED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,mBAAmB,GAAG,IAAI,GAAG,SAAS,EACjD,SAAS,CAAC,EAAE,MAAM,GACjB,yBAAyB,CAyC3B"}
|
|
@@ -1,24 +1,33 @@
|
|
|
1
|
-
import { BODY_FONT_OPTIONS,
|
|
1
|
+
import { BODY_FONT_OPTIONS, getFontCatalogEntry, HEADING_FONT_OPTIONS, LETTER_SPACING_TO_CSS, toFontSizeCss } from '../constants/themeFonts.js';
|
|
2
2
|
import { defaultThemePresets } from '../presets.js';
|
|
3
3
|
const FALLBACK_THEME = defaultThemePresets[0]?.name ?? 'cool';
|
|
4
4
|
const fallbackPreset = defaultThemePresets.find((preset)=>preset.name === FALLBACK_THEME) ?? defaultThemePresets[0];
|
|
5
5
|
const FONT_VAR_FALLBACK = {
|
|
6
|
+
'var(--font-inter)': '"Inter", system-ui, sans-serif',
|
|
6
7
|
'var(--font-geist-sans)': '"Geist Sans", system-ui, sans-serif',
|
|
7
8
|
'var(--font-geist-mono)': '"Geist Mono", SFMono-Regular, ui-monospace, monospace',
|
|
8
|
-
'var(--font-
|
|
9
|
+
'var(--font-roboto)': '"Roboto", system-ui, sans-serif',
|
|
10
|
+
'var(--font-open-sans)': '"Open Sans", system-ui, sans-serif',
|
|
11
|
+
'var(--font-lato)': '"Lato", system-ui, sans-serif',
|
|
12
|
+
'var(--font-montserrat)': '"Montserrat", system-ui, sans-serif',
|
|
13
|
+
'var(--font-poppins)': '"Poppins", system-ui, sans-serif',
|
|
9
14
|
'var(--font-outfit)': '"Outfit", system-ui, sans-serif',
|
|
10
15
|
'var(--font-playfair)': '"Playfair Display", "Times New Roman", serif',
|
|
16
|
+
'var(--font-merriweather)': '"Merriweather", "Times New Roman", serif',
|
|
17
|
+
'var(--font-raleway)': '"Raleway", system-ui, sans-serif',
|
|
11
18
|
'var(--font-lora)': '"Lora", "Times New Roman", serif',
|
|
12
19
|
'var(--font-manrope)': '"Manrope", system-ui, sans-serif',
|
|
13
20
|
'var(--font-urbanist)': '"Urbanist", system-ui, sans-serif'
|
|
14
21
|
};
|
|
15
22
|
function withFallback(fontFamily, fallback) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
const value = fontFamily?.trim() || fallback;
|
|
24
|
+
// A `var(--font-x)` without a fallback whose variable is not defined (always the
|
|
25
|
+
// case in the admin) makes the whole font-family declaration invalid. Give every
|
|
26
|
+
// such reference a fallback stack so the preview always renders a real face.
|
|
27
|
+
return value.replace(/var\((--[\w-]+)\)/g, (match, name)=>{
|
|
28
|
+
const mapped = FONT_VAR_FALLBACK[match] ?? 'system-ui, sans-serif';
|
|
29
|
+
return `var(${name}, ${mapped})`;
|
|
30
|
+
});
|
|
22
31
|
}
|
|
23
32
|
function getPresetTypography(themeName) {
|
|
24
33
|
const preset = defaultThemePresets.find((item)=>item.name === themeName) ?? fallbackPreset;
|
|
@@ -34,9 +43,10 @@ function resolveFontFamily(value, customValue, fallback) {
|
|
|
34
43
|
}
|
|
35
44
|
return withFallback(fallback, fallbackPreset?.typography?.fontFamily ?? 'system-ui, sans-serif');
|
|
36
45
|
}
|
|
37
|
-
|
|
46
|
+
// Catalog stacks are complete (variable with fallback + generic family).
|
|
47
|
+
const preconfigured = getFontCatalogEntry(value)?.fontFamily;
|
|
38
48
|
if (preconfigured) {
|
|
39
|
-
return
|
|
49
|
+
return preconfigured;
|
|
40
50
|
}
|
|
41
51
|
return withFallback(fallback, fallbackPreset?.typography?.fontFamily ?? 'system-ui, sans-serif');
|
|
42
52
|
}
|
|
@@ -60,13 +70,16 @@ export function resolveTypographyPreview(selection, themeName) {
|
|
|
60
70
|
const headingFontCustom = selection?.headingFontCustom ?? undefined;
|
|
61
71
|
const resolvedBodyFont = resolveFontFamily(bodyFontValue, bodyFontCustom, fallbackBody);
|
|
62
72
|
const resolvedHeadingFont = resolveFontFamily(headingFontValue, headingFontCustom, fallbackHeading);
|
|
63
|
-
const baseFontSize = selection?.baseFontSize
|
|
73
|
+
const baseFontSize = toFontSizeCss(selection?.baseFontSize) ?? fallbackSize;
|
|
64
74
|
const lineHeight = selection?.lineHeight && selection.lineHeight !== 'preset' ? selection.lineHeight : fallbackLineHeight;
|
|
65
75
|
return {
|
|
66
76
|
bodyFont: resolvedBodyFont,
|
|
67
77
|
headingFont: resolvedHeadingFont,
|
|
68
78
|
baseFontSize,
|
|
69
79
|
lineHeight,
|
|
80
|
+
headingWeight: selection?.headingWeight && selection.headingWeight !== 'preset' ? selection.headingWeight : presetTypography?.headingWeight ?? '700',
|
|
81
|
+
headingLetterSpacing: (selection?.letterSpacing && LETTER_SPACING_TO_CSS[selection.letterSpacing]) ?? presetTypography?.headingLetterSpacing ?? 'normal',
|
|
82
|
+
headingTransform: selection?.letterSpacing === 'wider' ? 'uppercase' : 'none',
|
|
70
83
|
bodyLabel: resolveOptionLabel(BODY_FONT_OPTIONS, bodyFontValue),
|
|
71
84
|
headingLabel: resolveOptionLabel(HEADING_FONT_OPTIONS, headingFontValue)
|
|
72
85
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/typographyPreviewUtils.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../src/components/typographyPreviewUtils.ts"],"sourcesContent":["import {\n BODY_FONT_OPTIONS,\n getFontCatalogEntry,\n HEADING_FONT_OPTIONS,\n LETTER_SPACING_TO_CSS,\n toFontSizeCss,\n} from '../constants/themeFonts.js'\nimport { defaultThemePresets } from '../presets.js'\n\nexport interface TypographySelection {\n bodyFont?: string | null\n headingFont?: string | null\n bodyFontCustom?: string | null\n headingFontCustom?: string | null\n baseFontSize?: string | null\n lineHeight?: string | null\n headingWeight?: string | null\n letterSpacing?: string | null\n}\n\nexport interface ResolvedTypographyPreview {\n bodyFont: string\n headingFont: string\n baseFontSize: string\n lineHeight: string\n headingWeight: string\n headingLetterSpacing: string\n headingTransform: 'none' | 'uppercase'\n bodyLabel: string\n headingLabel: string\n}\n\nconst FALLBACK_THEME = defaultThemePresets[0]?.name ?? 'cool'\nconst fallbackPreset =\n defaultThemePresets.find((preset) => preset.name === FALLBACK_THEME) ?? defaultThemePresets[0]\n\nconst FONT_VAR_FALLBACK: Record<string, string> = {\n 'var(--font-inter)': '\"Inter\", system-ui, sans-serif',\n 'var(--font-geist-sans)': '\"Geist Sans\", system-ui, sans-serif',\n 'var(--font-geist-mono)': '\"Geist Mono\", SFMono-Regular, ui-monospace, monospace',\n 'var(--font-roboto)': '\"Roboto\", system-ui, sans-serif',\n 'var(--font-open-sans)': '\"Open Sans\", system-ui, sans-serif',\n 'var(--font-lato)': '\"Lato\", system-ui, sans-serif',\n 'var(--font-montserrat)': '\"Montserrat\", system-ui, sans-serif',\n 'var(--font-poppins)': '\"Poppins\", system-ui, sans-serif',\n 'var(--font-outfit)': '\"Outfit\", system-ui, sans-serif',\n 'var(--font-playfair)': '\"Playfair Display\", \"Times New Roman\", serif',\n 'var(--font-merriweather)': '\"Merriweather\", \"Times New Roman\", serif',\n 'var(--font-raleway)': '\"Raleway\", system-ui, sans-serif',\n 'var(--font-lora)': '\"Lora\", \"Times New Roman\", serif',\n 'var(--font-manrope)': '\"Manrope\", system-ui, sans-serif',\n 'var(--font-urbanist)': '\"Urbanist\", system-ui, sans-serif',\n}\n\nfunction withFallback(fontFamily: string, fallback: string): string {\n const value = fontFamily?.trim() || fallback\n\n // A `var(--font-x)` without a fallback whose variable is not defined (always the\n // case in the admin) makes the whole font-family declaration invalid. Give every\n // such reference a fallback stack so the preview always renders a real face.\n return value.replace(/var\\((--[\\w-]+)\\)/g, (match, name: string) => {\n const mapped = FONT_VAR_FALLBACK[match] ?? 'system-ui, sans-serif'\n return `var(${name}, ${mapped})`\n })\n}\n\nfunction getPresetTypography(themeName?: string) {\n const preset = defaultThemePresets.find((item) => item.name === themeName) ?? fallbackPreset\n return preset?.typography\n}\n\nfunction resolveFontFamily(\n value: string | null | undefined,\n customValue: string | null | undefined,\n fallback: string,\n): string {\n if (!value || value === 'preset') {\n return withFallback(fallback, fallbackPreset?.typography?.fontFamily ?? 'system-ui, sans-serif')\n }\n\n if (value === 'custom') {\n if (customValue && customValue.trim().length > 0) {\n return customValue.trim()\n }\n return withFallback(fallback, fallbackPreset?.typography?.fontFamily ?? 'system-ui, sans-serif')\n }\n\n // Catalog stacks are complete (variable with fallback + generic family).\n const preconfigured = getFontCatalogEntry(value)?.fontFamily\n if (preconfigured) {\n return preconfigured\n }\n\n return withFallback(fallback, fallbackPreset?.typography?.fontFamily ?? 'system-ui, sans-serif')\n}\n\nfunction resolveOptionLabel(\n options: ReadonlyArray<{ label: string | Record<string, string>; value: string }>,\n value?: string | null,\n locale: 'en' | 'cs' = 'en',\n): string {\n const option = options.find((item) => item.value === value)\n if (!option) return value ?? ''\n if (typeof option.label === 'string') {\n return option.label\n }\n return option.label?.[locale] ?? Object.values(option.label)[0] ?? option.value\n}\n\nexport function resolveTypographyPreview(\n selection: TypographySelection | null | undefined,\n themeName?: string,\n): ResolvedTypographyPreview {\n const presetTypography = getPresetTypography(themeName)\n const fallbackBody = presetTypography?.fontFamily ?? 'system-ui, sans-serif'\n const fallbackHeading = presetTypography?.headingFamily ?? fallbackBody\n const fallbackSize = presetTypography?.baseFontSize ?? '16px'\n const fallbackLineHeight = presetTypography?.lineHeight ?? '1.6'\n\n const bodyFontValue = selection?.bodyFont ?? 'preset'\n const headingFontValue = selection?.headingFont ?? 'preset'\n const bodyFontCustom = selection?.bodyFontCustom ?? undefined\n const headingFontCustom = selection?.headingFontCustom ?? undefined\n const resolvedBodyFont = resolveFontFamily(bodyFontValue, bodyFontCustom, fallbackBody)\n const resolvedHeadingFont = resolveFontFamily(\n headingFontValue,\n headingFontCustom,\n fallbackHeading,\n )\n\n const baseFontSize = toFontSizeCss(selection?.baseFontSize) ?? fallbackSize\n const lineHeight =\n selection?.lineHeight && selection.lineHeight !== 'preset'\n ? selection.lineHeight\n : fallbackLineHeight\n\n return {\n bodyFont: resolvedBodyFont,\n headingFont: resolvedHeadingFont,\n baseFontSize,\n lineHeight,\n headingWeight:\n selection?.headingWeight && selection.headingWeight !== 'preset'\n ? selection.headingWeight\n : (presetTypography?.headingWeight ?? '700'),\n headingLetterSpacing:\n (selection?.letterSpacing && LETTER_SPACING_TO_CSS[selection.letterSpacing]) ??\n presetTypography?.headingLetterSpacing ??\n 'normal',\n headingTransform: selection?.letterSpacing === 'wider' ? 'uppercase' : 'none',\n bodyLabel: resolveOptionLabel(BODY_FONT_OPTIONS, bodyFontValue),\n headingLabel: resolveOptionLabel(HEADING_FONT_OPTIONS, headingFontValue),\n }\n}\n"],"names":["BODY_FONT_OPTIONS","getFontCatalogEntry","HEADING_FONT_OPTIONS","LETTER_SPACING_TO_CSS","toFontSizeCss","defaultThemePresets","FALLBACK_THEME","name","fallbackPreset","find","preset","FONT_VAR_FALLBACK","withFallback","fontFamily","fallback","value","trim","replace","match","mapped","getPresetTypography","themeName","item","typography","resolveFontFamily","customValue","length","preconfigured","resolveOptionLabel","options","locale","option","label","Object","values","resolveTypographyPreview","selection","presetTypography","fallbackBody","fallbackHeading","headingFamily","fallbackSize","baseFontSize","fallbackLineHeight","lineHeight","bodyFontValue","bodyFont","headingFontValue","headingFont","bodyFontCustom","undefined","headingFontCustom","resolvedBodyFont","resolvedHeadingFont","headingWeight","headingLetterSpacing","letterSpacing","headingTransform","bodyLabel","headingLabel"],"mappings":"AAAA,SACEA,iBAAiB,EACjBC,mBAAmB,EACnBC,oBAAoB,EACpBC,qBAAqB,EACrBC,aAAa,QACR,6BAA4B;AACnC,SAASC,mBAAmB,QAAQ,gBAAe;AAyBnD,MAAMC,iBAAiBD,mBAAmB,CAAC,EAAE,EAAEE,QAAQ;AACvD,MAAMC,iBACJH,oBAAoBI,IAAI,CAAC,CAACC,SAAWA,OAAOH,IAAI,KAAKD,mBAAmBD,mBAAmB,CAAC,EAAE;AAEhG,MAAMM,oBAA4C;IAChD,qBAAqB;IACrB,0BAA0B;IAC1B,0BAA0B;IAC1B,sBAAsB;IACtB,yBAAyB;IACzB,oBAAoB;IACpB,0BAA0B;IAC1B,uBAAuB;IACvB,sBAAsB;IACtB,wBAAwB;IACxB,4BAA4B;IAC5B,uBAAuB;IACvB,oBAAoB;IACpB,uBAAuB;IACvB,wBAAwB;AAC1B;AAEA,SAASC,aAAaC,UAAkB,EAAEC,QAAgB;IACxD,MAAMC,QAAQF,YAAYG,UAAUF;IAEpC,iFAAiF;IACjF,iFAAiF;IACjF,6EAA6E;IAC7E,OAAOC,MAAME,OAAO,CAAC,sBAAsB,CAACC,OAAOX;QACjD,MAAMY,SAASR,iBAAiB,CAACO,MAAM,IAAI;QAC3C,OAAO,CAAC,IAAI,EAAEX,KAAK,EAAE,EAAEY,OAAO,CAAC,CAAC;IAClC;AACF;AAEA,SAASC,oBAAoBC,SAAkB;IAC7C,MAAMX,SAASL,oBAAoBI,IAAI,CAAC,CAACa,OAASA,KAAKf,IAAI,KAAKc,cAAcb;IAC9E,OAAOE,QAAQa;AACjB;AAEA,SAASC,kBACPT,KAAgC,EAChCU,WAAsC,EACtCX,QAAgB;IAEhB,IAAI,CAACC,SAASA,UAAU,UAAU;QAChC,OAAOH,aAAaE,UAAUN,gBAAgBe,YAAYV,cAAc;IAC1E;IAEA,IAAIE,UAAU,UAAU;QACtB,IAAIU,eAAeA,YAAYT,IAAI,GAAGU,MAAM,GAAG,GAAG;YAChD,OAAOD,YAAYT,IAAI;QACzB;QACA,OAAOJ,aAAaE,UAAUN,gBAAgBe,YAAYV,cAAc;IAC1E;IAEA,yEAAyE;IACzE,MAAMc,gBAAgB1B,oBAAoBc,QAAQF;IAClD,IAAIc,eAAe;QACjB,OAAOA;IACT;IAEA,OAAOf,aAAaE,UAAUN,gBAAgBe,YAAYV,cAAc;AAC1E;AAEA,SAASe,mBACPC,OAAiF,EACjFd,KAAqB,EACrBe,SAAsB,IAAI;IAE1B,MAAMC,SAASF,QAAQpB,IAAI,CAAC,CAACa,OAASA,KAAKP,KAAK,KAAKA;IACrD,IAAI,CAACgB,QAAQ,OAAOhB,SAAS;IAC7B,IAAI,OAAOgB,OAAOC,KAAK,KAAK,UAAU;QACpC,OAAOD,OAAOC,KAAK;IACrB;IACA,OAAOD,OAAOC,KAAK,EAAE,CAACF,OAAO,IAAIG,OAAOC,MAAM,CAACH,OAAOC,KAAK,CAAC,CAAC,EAAE,IAAID,OAAOhB,KAAK;AACjF;AAEA,OAAO,SAASoB,yBACdC,SAAiD,EACjDf,SAAkB;IAElB,MAAMgB,mBAAmBjB,oBAAoBC;IAC7C,MAAMiB,eAAeD,kBAAkBxB,cAAc;IACrD,MAAM0B,kBAAkBF,kBAAkBG,iBAAiBF;IAC3D,MAAMG,eAAeJ,kBAAkBK,gBAAgB;IACvD,MAAMC,qBAAqBN,kBAAkBO,cAAc;IAE3D,MAAMC,gBAAgBT,WAAWU,YAAY;IAC7C,MAAMC,mBAAmBX,WAAWY,eAAe;IACnD,MAAMC,iBAAiBb,WAAWa,kBAAkBC;IACpD,MAAMC,oBAAoBf,WAAWe,qBAAqBD;IAC1D,MAAME,mBAAmB5B,kBAAkBqB,eAAeI,gBAAgBX;IAC1E,MAAMe,sBAAsB7B,kBAC1BuB,kBACAI,mBACAZ;IAGF,MAAMG,eAAetC,cAAcgC,WAAWM,iBAAiBD;IAC/D,MAAMG,aACJR,WAAWQ,cAAcR,UAAUQ,UAAU,KAAK,WAC9CR,UAAUQ,UAAU,GACpBD;IAEN,OAAO;QACLG,UAAUM;QACVJ,aAAaK;QACbX;QACAE;QACAU,eACElB,WAAWkB,iBAAiBlB,UAAUkB,aAAa,KAAK,WACpDlB,UAAUkB,aAAa,GACtBjB,kBAAkBiB,iBAAiB;QAC1CC,sBACE,AAACnB,CAAAA,WAAWoB,iBAAiBrD,qBAAqB,CAACiC,UAAUoB,aAAa,CAAC,AAAD,KAC1EnB,kBAAkBkB,wBAClB;QACFE,kBAAkBrB,WAAWoB,kBAAkB,UAAU,cAAc;QACvEE,WAAW9B,mBAAmB5B,mBAAmB6C;QACjDc,cAAc/B,mBAAmB1B,sBAAsB6C;IACzD;AACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared device-preview definitions used by:
|
|
3
|
+
* - the in-admin live preview panels (AppearancePreviewField / ThemePreviewField device switcher)
|
|
4
|
+
* - the native Payload Live Preview toolbar (admin.livePreview.breakpoints)
|
|
5
|
+
*
|
|
6
|
+
* Keeping a single source of truth means the device chrome shown inside the
|
|
7
|
+
* theme editor matches the iframe sizes editors get in the real Live Preview.
|
|
8
|
+
*/
|
|
9
|
+
export type DevicePreviewId = 'mobile' | 'tablet' | 'desktop';
|
|
10
|
+
export type DevicePreview = {
|
|
11
|
+
/** Stable identifier, also used as Payload breakpoint `name`. */
|
|
12
|
+
id: DevicePreviewId;
|
|
13
|
+
/** Human-readable label (bilingual handled at the UI layer). */
|
|
14
|
+
label: string;
|
|
15
|
+
/** Czech label for admin UI. */
|
|
16
|
+
labelCs: string;
|
|
17
|
+
/** Viewport width in px. */
|
|
18
|
+
width: number;
|
|
19
|
+
/** Viewport height in px. */
|
|
20
|
+
height: number;
|
|
21
|
+
};
|
|
22
|
+
export declare const DEVICE_PREVIEWS: readonly DevicePreview[];
|
|
23
|
+
export declare const DEFAULT_DEVICE_PREVIEW_ID: DevicePreviewId;
|
|
24
|
+
export declare const getDevicePreview: (id: DevicePreviewId) => DevicePreview;
|
|
25
|
+
/**
|
|
26
|
+
* Default breakpoints for Payload's native Live Preview toolbar.
|
|
27
|
+
* Derived from DEVICE_PREVIEWS so both stay in sync.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DEFAULT_LIVE_PREVIEW_BREAKPOINTS: Array<{
|
|
30
|
+
name: string;
|
|
31
|
+
label: string;
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
}>;
|
|
35
|
+
//# sourceMappingURL=devicePreviews.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devicePreviews.d.ts","sourceRoot":"","sources":["../../src/constants/devicePreviews.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;AAE7D,MAAM,MAAM,aAAa,GAAG;IAC1B,iEAAiE;IACjE,EAAE,EAAE,eAAe,CAAA;IACnB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAsB1C,CAAA;AAEV,eAAO,MAAM,yBAAyB,EAAE,eAA2B,CAAA;AAEnE,eAAO,MAAM,gBAAgB,GAAI,IAAI,eAAe,KAAG,aAC4C,CAAA;AAEnG;;;GAGG;AACH,eAAO,MAAM,gCAAgC,EAAE,KAAK,CAAC;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAKE,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared device-preview definitions used by:
|
|
3
|
+
* - the in-admin live preview panels (AppearancePreviewField / ThemePreviewField device switcher)
|
|
4
|
+
* - the native Payload Live Preview toolbar (admin.livePreview.breakpoints)
|
|
5
|
+
*
|
|
6
|
+
* Keeping a single source of truth means the device chrome shown inside the
|
|
7
|
+
* theme editor matches the iframe sizes editors get in the real Live Preview.
|
|
8
|
+
*/ export const DEVICE_PREVIEWS = [
|
|
9
|
+
{
|
|
10
|
+
id: 'mobile',
|
|
11
|
+
label: 'Mobile',
|
|
12
|
+
labelCs: 'Mobil',
|
|
13
|
+
width: 390,
|
|
14
|
+
height: 844
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'tablet',
|
|
18
|
+
label: 'Tablet',
|
|
19
|
+
labelCs: 'Tablet',
|
|
20
|
+
width: 768,
|
|
21
|
+
height: 1024
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'desktop',
|
|
25
|
+
label: 'Desktop',
|
|
26
|
+
labelCs: 'Desktop',
|
|
27
|
+
width: 1440,
|
|
28
|
+
height: 900
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
export const DEFAULT_DEVICE_PREVIEW_ID = 'desktop';
|
|
32
|
+
export const getDevicePreview = (id)=>DEVICE_PREVIEWS.find((device)=>device.id === id) ?? DEVICE_PREVIEWS[DEVICE_PREVIEWS.length - 1];
|
|
33
|
+
/**
|
|
34
|
+
* Default breakpoints for Payload's native Live Preview toolbar.
|
|
35
|
+
* Derived from DEVICE_PREVIEWS so both stay in sync.
|
|
36
|
+
*/ export const DEFAULT_LIVE_PREVIEW_BREAKPOINTS = DEVICE_PREVIEWS.map((device)=>({
|
|
37
|
+
name: device.id,
|
|
38
|
+
label: device.label,
|
|
39
|
+
width: device.width,
|
|
40
|
+
height: device.height
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=devicePreviews.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/constants/devicePreviews.ts"],"sourcesContent":["/**\n * Shared device-preview definitions used by:\n * - the in-admin live preview panels (AppearancePreviewField / ThemePreviewField device switcher)\n * - the native Payload Live Preview toolbar (admin.livePreview.breakpoints)\n *\n * Keeping a single source of truth means the device chrome shown inside the\n * theme editor matches the iframe sizes editors get in the real Live Preview.\n */\n\nexport type DevicePreviewId = 'mobile' | 'tablet' | 'desktop'\n\nexport type DevicePreview = {\n /** Stable identifier, also used as Payload breakpoint `name`. */\n id: DevicePreviewId\n /** Human-readable label (bilingual handled at the UI layer). */\n label: string\n /** Czech label for admin UI. */\n labelCs: string\n /** Viewport width in px. */\n width: number\n /** Viewport height in px. */\n height: number\n}\n\nexport const DEVICE_PREVIEWS: readonly DevicePreview[] = [\n {\n id: 'mobile',\n label: 'Mobile',\n labelCs: 'Mobil',\n width: 390,\n height: 844,\n },\n {\n id: 'tablet',\n label: 'Tablet',\n labelCs: 'Tablet',\n width: 768,\n height: 1024,\n },\n {\n id: 'desktop',\n label: 'Desktop',\n labelCs: 'Desktop',\n width: 1440,\n height: 900,\n },\n] as const\n\nexport const DEFAULT_DEVICE_PREVIEW_ID: DevicePreviewId = 'desktop'\n\nexport const getDevicePreview = (id: DevicePreviewId): DevicePreview =>\n DEVICE_PREVIEWS.find((device) => device.id === id) ?? DEVICE_PREVIEWS[DEVICE_PREVIEWS.length - 1]\n\n/**\n * Default breakpoints for Payload's native Live Preview toolbar.\n * Derived from DEVICE_PREVIEWS so both stay in sync.\n */\nexport const DEFAULT_LIVE_PREVIEW_BREAKPOINTS: Array<{\n name: string\n label: string\n width: number\n height: number\n}> = DEVICE_PREVIEWS.map((device) => ({\n name: device.id,\n label: device.label,\n width: device.width,\n height: device.height,\n}))\n"],"names":["DEVICE_PREVIEWS","id","label","labelCs","width","height","DEFAULT_DEVICE_PREVIEW_ID","getDevicePreview","find","device","length","DEFAULT_LIVE_PREVIEW_BREAKPOINTS","map","name"],"mappings":"AAAA;;;;;;;CAOC,GAiBD,OAAO,MAAMA,kBAA4C;IACvD;QACEC,IAAI;QACJC,OAAO;QACPC,SAAS;QACTC,OAAO;QACPC,QAAQ;IACV;IACA;QACEJ,IAAI;QACJC,OAAO;QACPC,SAAS;QACTC,OAAO;QACPC,QAAQ;IACV;IACA;QACEJ,IAAI;QACJC,OAAO;QACPC,SAAS;QACTC,OAAO;QACPC,QAAQ;IACV;CACD,CAAS;AAEV,OAAO,MAAMC,4BAA6C,UAAS;AAEnE,OAAO,MAAMC,mBAAmB,CAACN,KAC/BD,gBAAgBQ,IAAI,CAAC,CAACC,SAAWA,OAAOR,EAAE,KAAKA,OAAOD,eAAe,CAACA,gBAAgBU,MAAM,GAAG,EAAE,CAAA;AAEnG;;;CAGC,GACD,OAAO,MAAMC,mCAKRX,gBAAgBY,GAAG,CAAC,CAACH,SAAY,CAAA;QACpCI,MAAMJ,OAAOR,EAAE;QACfC,OAAOO,OAAOP,KAAK;QACnBE,OAAOK,OAAOL,KAAK;QACnBC,QAAQI,OAAOJ,MAAM;IACvB,CAAA,GAAG"}
|