@kilivi/payloadcms-theme-management 1.0.1 → 1.0.3
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/LICENSE.MD +9 -0
- package/dist/components/ThemePreview.d.ts.map +1 -1
- package/dist/components/ThemePreview.js +14 -11
- package/dist/components/ThemePreview.js.map +1 -1
- package/dist/constants/themeFonts.d.ts +74 -17
- package/dist/constants/themeFonts.d.ts.map +1 -1
- package/dist/constants/themeFonts.js +76 -17
- package/dist/constants/themeFonts.js.map +1 -1
- package/dist/fields/FontSelectField.d.ts.map +1 -1
- package/dist/fields/FontSelectField.js +16 -7
- package/dist/fields/FontSelectField.js.map +1 -1
- package/dist/fields/ThemePreviewField.d.ts.map +1 -1
- package/dist/fields/ThemePreviewField.js +33 -28
- package/dist/fields/ThemePreviewField.js.map +1 -1
- package/dist/fields/ThemeTokenSelectField.d.ts.map +1 -1
- package/dist/fields/ThemeTokenSelectField.js +131 -35
- package/dist/fields/ThemeTokenSelectField.js.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.js +7 -4
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.js.map +1 -1
- package/dist/globals/ThemeSettings/config.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/config.js +32 -8
- package/dist/globals/ThemeSettings/config.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -12
- package/dist/index.js.map +1 -1
- package/dist/translations.d.ts +49 -0
- package/dist/translations.d.ts.map +1 -0
- package/dist/translations.js +121 -0
- package/dist/translations.js.map +1 -0
- package/dist/utilities/getThemeSettings.d.ts.map +1 -1
- package/dist/utilities/getThemeSettings.js +8 -2
- package/dist/utilities/getThemeSettings.js.map +1 -1
- package/dist/utils/getAdminLanguage.d.ts +2 -0
- package/dist/utils/getAdminLanguage.d.ts.map +1 -0
- package/dist/utils/getAdminLanguage.js +21 -0
- package/dist/utils/getAdminLanguage.js.map +1 -0
- package/package.json +22 -23
|
@@ -2,53 +2,61 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useField } from '@payloadcms/ui';
|
|
4
4
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
5
|
-
import { allThemePresets } from '../index.js';
|
|
5
|
+
import { allThemePresets, fetchThemeConfiguration } from '../index.js';
|
|
6
6
|
import { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js';
|
|
7
7
|
const FALLBACK_TOKENS = [
|
|
8
8
|
{
|
|
9
9
|
value: 'background',
|
|
10
|
-
label:
|
|
10
|
+
label: {
|
|
11
|
+
en: 'Theme background',
|
|
12
|
+
cs: 'Pozadí tématu'
|
|
13
|
+
},
|
|
11
14
|
color: 'var(--background)'
|
|
12
15
|
},
|
|
13
16
|
{
|
|
14
17
|
value: 'card',
|
|
15
|
-
label:
|
|
18
|
+
label: {
|
|
19
|
+
en: 'Card background',
|
|
20
|
+
cs: 'Pozadí karty'
|
|
21
|
+
},
|
|
16
22
|
color: 'var(--card)'
|
|
17
23
|
},
|
|
18
24
|
{
|
|
19
25
|
value: 'muted',
|
|
20
|
-
label:
|
|
26
|
+
label: {
|
|
27
|
+
en: 'Muted surface',
|
|
28
|
+
cs: 'Tlumený povrch'
|
|
29
|
+
},
|
|
21
30
|
color: 'var(--muted)'
|
|
22
31
|
},
|
|
23
32
|
{
|
|
24
33
|
value: 'accent',
|
|
25
|
-
label:
|
|
34
|
+
label: {
|
|
35
|
+
en: 'Accent surface',
|
|
36
|
+
cs: 'Akcentní povrch'
|
|
37
|
+
},
|
|
26
38
|
color: 'var(--accent)'
|
|
27
39
|
},
|
|
28
40
|
{
|
|
29
41
|
value: 'secondary',
|
|
30
|
-
label:
|
|
42
|
+
label: {
|
|
43
|
+
en: 'Secondary surface',
|
|
44
|
+
cs: 'Sekundární povrch'
|
|
45
|
+
},
|
|
31
46
|
color: 'var(--secondary)'
|
|
32
47
|
},
|
|
33
48
|
{
|
|
34
49
|
value: 'primary',
|
|
35
|
-
label:
|
|
50
|
+
label: {
|
|
51
|
+
en: 'Primary surface',
|
|
52
|
+
cs: 'Primární povrch'
|
|
53
|
+
},
|
|
36
54
|
color: 'var(--primary)'
|
|
37
55
|
}
|
|
38
56
|
];
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (!response.ok) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
const data = await response.json();
|
|
46
|
-
return data?.docs?.[0]?.themeConfiguration ?? null;
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.warn('[ThemeTokenSelectField] Failed to fetch theme configuration:', error);
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
57
|
+
// Use plugin-provided fetch helper which supports collection/global and options
|
|
58
|
+
// This will use `collectionSlug`, `useGlobal`, tenant, locale, depth, draft, etc.
|
|
59
|
+
// Accept fetch options from field.admin.custom to allow overrides in different setups.
|
|
52
60
|
function buildOptionsFromConfiguration(configuration, themePresets) {
|
|
53
61
|
if (!configuration) {
|
|
54
62
|
return FALLBACK_TOKENS;
|
|
@@ -71,20 +79,44 @@ function buildOptionsFromConfiguration(configuration, themePresets) {
|
|
|
71
79
|
return null;
|
|
72
80
|
}
|
|
73
81
|
const labelMap = {
|
|
74
|
-
background:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
background: {
|
|
83
|
+
en: 'Theme background',
|
|
84
|
+
cs: 'Pozadí tématu'
|
|
85
|
+
},
|
|
86
|
+
card: {
|
|
87
|
+
en: 'Card background',
|
|
88
|
+
cs: 'Pozadí karty'
|
|
89
|
+
},
|
|
90
|
+
muted: {
|
|
91
|
+
en: 'Muted surface',
|
|
92
|
+
cs: 'Tlumený povrch'
|
|
93
|
+
},
|
|
94
|
+
accent: {
|
|
95
|
+
en: 'Accent surface',
|
|
96
|
+
cs: 'Akcentní povrch'
|
|
97
|
+
},
|
|
98
|
+
secondary: {
|
|
99
|
+
en: 'Secondary surface',
|
|
100
|
+
cs: 'Sekundární povrch'
|
|
101
|
+
},
|
|
102
|
+
primary: {
|
|
103
|
+
en: 'Primary surface',
|
|
104
|
+
cs: 'Primární povrch'
|
|
105
|
+
},
|
|
106
|
+
popover: {
|
|
107
|
+
en: 'Popover surface',
|
|
108
|
+
cs: 'Popover povrch'
|
|
109
|
+
}
|
|
81
110
|
};
|
|
82
111
|
return {
|
|
83
112
|
value: key,
|
|
84
|
-
label: labelMap[key] ??
|
|
113
|
+
label: labelMap[key] ?? {
|
|
114
|
+
en: key,
|
|
115
|
+
cs: key
|
|
116
|
+
},
|
|
85
117
|
color: value
|
|
86
118
|
};
|
|
87
|
-
}).filter((token)=>
|
|
119
|
+
}).filter((token)=>token !== null);
|
|
88
120
|
return tokens.length > 0 ? tokens : FALLBACK_TOKENS;
|
|
89
121
|
}
|
|
90
122
|
export default function ThemeTokenSelectField(props) {
|
|
@@ -103,26 +135,89 @@ export default function ThemeTokenSelectField(props) {
|
|
|
103
135
|
]);
|
|
104
136
|
useEffect(()=>{
|
|
105
137
|
let isMounted = true;
|
|
106
|
-
|
|
138
|
+
const custom = field.admin?.custom ?? {};
|
|
139
|
+
const fetchOpts = custom.fetchThemeConfigurationOptions ?? custom.fetchOptions ?? (custom.collectionSlug || typeof custom.useGlobal !== 'undefined' ? {
|
|
140
|
+
collectionSlug: custom.collectionSlug,
|
|
141
|
+
useGlobal: custom.useGlobal,
|
|
142
|
+
tenantSlug: custom.tenantSlug,
|
|
143
|
+
depth: custom.depth,
|
|
144
|
+
locale: custom.locale,
|
|
145
|
+
draft: custom.draft,
|
|
146
|
+
queryParams: custom.queryParams
|
|
147
|
+
} : undefined);
|
|
148
|
+
fetchThemeConfiguration(fetchOpts).then(async (configuration)=>{
|
|
107
149
|
if (!isMounted) return;
|
|
150
|
+
if (configuration) {
|
|
151
|
+
setOptions(buildOptionsFromConfiguration(configuration, themePresets));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// If nothing found and fetchOpts didn't explicitly request global, try fallback to global
|
|
155
|
+
// This helps in setups where plugin created a standalone global (default slug 'appearance-settings')
|
|
156
|
+
const explicitlyRequestedGlobal = !!(fetchOpts?.useGlobal === true || fetchOpts?.collectionSlug === 'appearance-settings');
|
|
157
|
+
if (!explicitlyRequestedGlobal) {
|
|
158
|
+
try {
|
|
159
|
+
// Prefer custom.collectionSlug if provided, otherwise try the default standalone slug
|
|
160
|
+
const fallbackCollection = custom && custom.collectionSlug || 'appearance-settings';
|
|
161
|
+
const fallbackOpts = {
|
|
162
|
+
useGlobal: true,
|
|
163
|
+
collectionSlug: fallbackCollection
|
|
164
|
+
};
|
|
165
|
+
const fallbackConfig = await fetchThemeConfiguration(fallbackOpts);
|
|
166
|
+
if (!isMounted) return;
|
|
167
|
+
if (fallbackConfig) {
|
|
168
|
+
// Found theme config in global, use it
|
|
169
|
+
setOptions(buildOptionsFromConfiguration(fallbackConfig, themePresets));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
} catch (e) {
|
|
173
|
+
console.warn('[ThemeTokenSelectField] Fallback global fetch failed:', e);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// final fallback: use empty tokens
|
|
108
177
|
setOptions(buildOptionsFromConfiguration(configuration, themePresets));
|
|
109
178
|
});
|
|
110
179
|
return ()=>{
|
|
111
180
|
isMounted = false;
|
|
112
181
|
};
|
|
113
|
-
}, [
|
|
182
|
+
}, [
|
|
183
|
+
themePresets,
|
|
184
|
+
field.admin?.custom
|
|
185
|
+
]);
|
|
114
186
|
const handleSelect = useCallback((nextValue)=>{
|
|
115
187
|
setValue(nextValue);
|
|
116
188
|
}, [
|
|
117
189
|
setValue
|
|
118
190
|
]);
|
|
119
|
-
const label = typeof field.label === 'string' ? field.label : '';
|
|
191
|
+
const label = typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || '';
|
|
120
192
|
let description = '';
|
|
121
193
|
if (typeof field.admin?.description === 'string') {
|
|
122
194
|
description = field.admin.description;
|
|
123
195
|
} else if (field.admin?.description && typeof field.admin.description === 'object' && typeof field.admin.description.en === 'string') {
|
|
124
196
|
description = field.admin.description.en;
|
|
125
197
|
}
|
|
198
|
+
// Helper function to get label text from localized or string label
|
|
199
|
+
const getOptionLabel = (option)=>{
|
|
200
|
+
if (typeof option.label === 'string') {
|
|
201
|
+
return option.label;
|
|
202
|
+
}
|
|
203
|
+
// Prefer English, fallback to Czech, then any available language
|
|
204
|
+
return option.label.en || option.label.cs || Object.values(option.label)[0] || option.value;
|
|
205
|
+
};
|
|
206
|
+
// Resolve CSS variable colors (e.g., 'var(--primary)') to their computed values when possible
|
|
207
|
+
const resolveCssColor = (color)=>{
|
|
208
|
+
if (typeof window === 'undefined' || !color || !color.trim().startsWith('var(')) {
|
|
209
|
+
return color;
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
const match = color.trim().match(/var\((--[^)]+)\)/);
|
|
213
|
+
if (!match) return color;
|
|
214
|
+
const varName = match[1];
|
|
215
|
+
const computed = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
|
|
216
|
+
return computed || color;
|
|
217
|
+
} catch (e) {
|
|
218
|
+
return color;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
126
221
|
return /*#__PURE__*/ _jsxs("div", {
|
|
127
222
|
className: "field-type theme-token-select",
|
|
128
223
|
children: [
|
|
@@ -182,7 +277,8 @@ export default function ThemeTokenSelectField(props) {
|
|
|
182
277
|
height: '32px',
|
|
183
278
|
borderRadius: '8px',
|
|
184
279
|
border: '1px solid rgba(15, 23, 42, 0.08)',
|
|
185
|
-
|
|
280
|
+
backgroundColor: resolveCssColor(option.color),
|
|
281
|
+
flexShrink: 0
|
|
186
282
|
}
|
|
187
283
|
}),
|
|
188
284
|
/*#__PURE__*/ _jsx("span", {
|
|
@@ -191,7 +287,7 @@ export default function ThemeTokenSelectField(props) {
|
|
|
191
287
|
fontWeight: 600,
|
|
192
288
|
color: 'var(--theme-elevation-800)'
|
|
193
289
|
},
|
|
194
|
-
children: option
|
|
290
|
+
children: getOptionLabel(option)
|
|
195
291
|
})
|
|
196
292
|
]
|
|
197
293
|
}, option.value);
|
|
@@ -206,7 +302,7 @@ export default function ThemeTokenSelectField(props) {
|
|
|
206
302
|
},
|
|
207
303
|
children: options.map((option)=>/*#__PURE__*/ _jsx("option", {
|
|
208
304
|
value: option.value,
|
|
209
|
-
children: option
|
|
305
|
+
children: getOptionLabel(option)
|
|
210
306
|
}, option.value))
|
|
211
307
|
})
|
|
212
308
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fields/ThemeTokenSelectField.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport type { SelectFieldClientProps } from 'payload'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { allThemePresets } from '../index.js'\nimport type { ThemePreset } from '../presets.js'\nimport { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\n\ninterface ThemeColorOption {\n value: string\n label: string\n color: string\n description?: string\n}\n\nconst FALLBACK_TOKENS: ThemeColorOption[] = [\n { value: 'background', label: 'Theme background', color: 'var(--background)' },\n { value: 'card', label: 'Card background', color: 'var(--card)' },\n { value: 'muted', label: 'Muted surface', color: 'var(--muted)' },\n { value: 'accent', label: 'Accent surface', color: 'var(--accent)' },\n { value: 'secondary', label: 'Secondary surface', color: 'var(--secondary)' },\n { value: 'primary', label: 'Primary surface', color: 'var(--primary)' },\n]\n\nasync function fetchThemeConfiguration(): Promise<Record<string, unknown> | null> {\n try {\n const response = await fetch('/api/site-settings')\n if (!response.ok) {\n return null\n }\n const data = await response.json()\n return data?.docs?.[0]?.themeConfiguration ?? null\n } catch (error) {\n console.warn('[ThemeTokenSelectField] Failed to fetch theme configuration:', error)\n return null\n }\n}\n\nfunction buildOptionsFromConfiguration(\n configuration: Record<string, unknown> | null,\n themePresets: ThemePreset[],\n): ThemeColorOption[] {\n if (!configuration) {\n return FALLBACK_TOKENS\n }\n\n const resolved = resolveThemeConfiguration(configuration)\n const lightMode = resolved.lightMode ?? themePresets[0]?.lightMode ?? {}\n const orderedKeys: string[] = [\n 'background',\n 'card',\n 'muted',\n 'accent',\n 'secondary',\n 'primary',\n 'popover',\n ]\n\n const typedLightMode = lightMode as Record<string, string | null | undefined>\n\n const tokens = orderedKeys\n .map((key) => {\n const value = typedLightMode?.[key]\n if (typeof value !== 'string' || value.trim().length === 0) {\n return null\n }\n\n const labelMap: Record<string, string> = {\n background: 'Theme background',\n card: 'Card background',\n muted: 'Muted surface',\n accent: 'Accent surface',\n secondary: 'Secondary surface',\n primary: 'Primary surface',\n popover: 'Popover surface',\n }\n\n return {\n value: key,\n label: labelMap[key] ?? key,\n color: value,\n }\n })\n .filter((token): token is ThemeColorOption => Boolean(token))\n\n return tokens.length > 0 ? tokens : FALLBACK_TOKENS\n}\n\nexport default function ThemeTokenSelectField(props: SelectFieldClientProps) {\n const { path, field } = props\n const { value, setValue } = useField<string>({ path })\n const [options, setOptions] = useState<ThemeColorOption[]>(FALLBACK_TOKENS)\n const selectedValue = value || 'background'\n\n // Get themePresets from admin.custom or use defaults\n const themePresets = useMemo(() => {\n const customPresets = (field.admin?.custom as { themePresets?: ThemePreset[] })?.themePresets\n return customPresets && customPresets.length > 0 ? customPresets : allThemePresets\n }, [field.admin?.custom])\n\n useEffect(() => {\n let isMounted = true\n\n fetchThemeConfiguration().then((configuration) => {\n if (!isMounted) return\n setOptions(buildOptionsFromConfiguration(configuration, themePresets))\n })\n\n return () => {\n isMounted = false\n }\n }, [])\n\n const handleSelect = useCallback(\n (nextValue: string) => {\n setValue(nextValue)\n },\n [setValue],\n )\n\n const label = typeof field.label === 'string' ? field.label : ''\n let description = ''\n if (typeof field.admin?.description === 'string') {\n description = field.admin.description\n } else if (\n field.admin?.description &&\n typeof field.admin.description === 'object' &&\n typeof field.admin.description.en === 'string'\n ) {\n description = field.admin.description.en\n }\n\n return (\n <div className=\"field-type theme-token-select\">\n {label && (\n <label\n className=\"field-label\"\n htmlFor={path}\n style={{ display: 'block', marginBottom: '8px' }}\n >\n {label}\n {field.required && <span className=\"required\">*</span>}\n </label>\n )}\n\n {description && (\n <div\n className=\"field-description\"\n style={{ marginBottom: '12px', fontSize: '13px', color: 'var(--theme-elevation-500)' }}\n >\n {description}\n </div>\n )}\n\n <div\n className=\"token-grid\"\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',\n gap: '10px',\n }}\n >\n {options.map((option) => {\n const isActive = option.value === selectedValue\n return (\n <button\n type=\"button\"\n key={option.value}\n onClick={() => handleSelect(option.value)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '10px 12px',\n borderRadius: '10px',\n border: isActive\n ? '2px solid var(--theme-success-500)'\n : '1px solid var(--theme-elevation-150)',\n backgroundColor: 'var(--theme-elevation-0)',\n boxShadow: isActive\n ? '0 10px 20px -10px rgba(59, 130, 246, 0.4)'\n : '0 1px 2px rgba(15, 23, 42, 0.08)',\n cursor: 'pointer',\n transition: 'border-color 0.2s ease, box-shadow 0.2s ease',\n }}\n >\n <span\n aria-hidden\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n border: '1px solid rgba(15, 23, 42, 0.08)',\n background: option.color,\n }}\n />\n <span\n style={{ fontSize: '13px', fontWeight: 600, color: 'var(--theme-elevation-800)' }}\n >\n {option.label}\n </span>\n </button>\n )\n })}\n </div>\n\n <select\n id={path}\n value={selectedValue}\n onChange={(event) => handleSelect(event.target.value)}\n style={{ display: 'none' }}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n )\n}\n"],"names":["useField","useCallback","useEffect","useMemo","useState","allThemePresets","resolveThemeConfiguration","FALLBACK_TOKENS","value","label","color","fetchThemeConfiguration","response","fetch","ok","data","json","docs","themeConfiguration","error","console","warn","buildOptionsFromConfiguration","configuration","themePresets","resolved","lightMode","orderedKeys","typedLightMode","tokens","map","key","trim","length","labelMap","background","card","muted","accent","secondary","primary","popover","filter","token","Boolean","ThemeTokenSelectField","props","path","field","setValue","options","setOptions","selectedValue","customPresets","admin","custom","isMounted","then","handleSelect","nextValue","description","en","div","className","htmlFor","style","display","marginBottom","required","span","fontSize","gridTemplateColumns","gap","option","isActive","button","type","onClick","alignItems","padding","borderRadius","border","backgroundColor","boxShadow","cursor","transition","aria-hidden","width","height","fontWeight","select","id","onChange","event","target"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/fields/ThemeTokenSelectField.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport type { SelectFieldClientProps } from 'payload'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { allThemePresets, fetchThemeConfiguration } from '../index.js'\nimport type { SiteThemeConfiguration } from '../payload-types.js'\nimport type { ThemePreset } from '../presets.js'\nimport type { FetchThemeConfigurationOptions } from '../types.js'\nimport { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\n\ninterface ThemeColorOption {\n value: string\n label: string | { [key: string]: string | undefined }\n color: string\n description?: string\n}\n\nconst FALLBACK_TOKENS: ThemeColorOption[] = [\n {\n value: 'background',\n label: { en: 'Theme background', cs: 'Pozadí tématu' },\n color: 'var(--background)',\n },\n { value: 'card', label: { en: 'Card background', cs: 'Pozadí karty' }, color: 'var(--card)' },\n { value: 'muted', label: { en: 'Muted surface', cs: 'Tlumený povrch' }, color: 'var(--muted)' },\n {\n value: 'accent',\n label: { en: 'Accent surface', cs: 'Akcentní povrch' },\n color: 'var(--accent)',\n },\n {\n value: 'secondary',\n label: { en: 'Secondary surface', cs: 'Sekundární povrch' },\n color: 'var(--secondary)',\n },\n {\n value: 'primary',\n label: { en: 'Primary surface', cs: 'Primární povrch' },\n color: 'var(--primary)',\n },\n]\n\n// Use plugin-provided fetch helper which supports collection/global and options\n// This will use `collectionSlug`, `useGlobal`, tenant, locale, depth, draft, etc.\n// Accept fetch options from field.admin.custom to allow overrides in different setups.\n\nfunction buildOptionsFromConfiguration(\n configuration: SiteThemeConfiguration | Record<string, unknown> | null,\n themePresets: ThemePreset[],\n): ThemeColorOption[] {\n if (!configuration) {\n return FALLBACK_TOKENS\n }\n\n const resolved = resolveThemeConfiguration(configuration)\n const lightMode = resolved.lightMode ?? themePresets[0]?.lightMode ?? {}\n const orderedKeys: string[] = [\n 'background',\n 'card',\n 'muted',\n 'accent',\n 'secondary',\n 'primary',\n 'popover',\n ]\n\n const typedLightMode = lightMode as Record<string, string | null | undefined>\n\n const tokens = orderedKeys\n .map((key) => {\n const value = typedLightMode?.[key]\n if (typeof value !== 'string' || value.trim().length === 0) {\n return null\n }\n\n const labelMap: Record<string, { en: string; cs: string }> = {\n background: { en: 'Theme background', cs: 'Pozadí tématu' },\n card: { en: 'Card background', cs: 'Pozadí karty' },\n muted: { en: 'Muted surface', cs: 'Tlumený povrch' },\n accent: { en: 'Accent surface', cs: 'Akcentní povrch' },\n secondary: { en: 'Secondary surface', cs: 'Sekundární povrch' },\n primary: { en: 'Primary surface', cs: 'Primární povrch' },\n popover: { en: 'Popover surface', cs: 'Popover povrch' },\n }\n\n return {\n value: key,\n label: labelMap[key] ?? { en: key, cs: key },\n color: value,\n }\n })\n .filter((token): token is NonNullable<typeof token> => token !== null)\n\n return tokens.length > 0 ? tokens : FALLBACK_TOKENS\n}\n\nexport default function ThemeTokenSelectField(props: SelectFieldClientProps) {\n const { path, field } = props\n const { value, setValue } = useField<string>({ path })\n const [options, setOptions] = useState<ThemeColorOption[]>(FALLBACK_TOKENS)\n const selectedValue = value || 'background'\n\n // Get themePresets from admin.custom or use defaults\n const themePresets = useMemo(() => {\n const customPresets = (field.admin?.custom as { themePresets?: ThemePreset[] })?.themePresets\n return customPresets && customPresets.length > 0 ? customPresets : allThemePresets\n }, [field.admin?.custom])\n\n useEffect(() => {\n let isMounted = true\n\n // Allow fields to override fetch options via admin.custom\n type CustomAdmin = {\n fetchThemeConfigurationOptions?: FetchThemeConfigurationOptions\n fetchOptions?: FetchThemeConfigurationOptions\n collectionSlug?: string\n useGlobal?: boolean\n tenantSlug?: string\n depth?: number\n locale?: string\n draft?: boolean\n queryParams?: Record<string, unknown>\n }\n\n const custom = (field.admin?.custom as unknown as CustomAdmin) ?? {}\n\n const fetchOpts: FetchThemeConfigurationOptions | undefined =\n custom.fetchThemeConfigurationOptions ??\n custom.fetchOptions ??\n (custom.collectionSlug || typeof custom.useGlobal !== 'undefined'\n ? ({\n collectionSlug: custom.collectionSlug,\n useGlobal: custom.useGlobal,\n tenantSlug: custom.tenantSlug,\n depth: custom.depth,\n locale: custom.locale,\n draft: custom.draft,\n queryParams: custom.queryParams,\n } as unknown as FetchThemeConfigurationOptions)\n : undefined)\n\n fetchThemeConfiguration(fetchOpts).then(async (configuration) => {\n if (!isMounted) return\n if (configuration) {\n setOptions(buildOptionsFromConfiguration(configuration, themePresets))\n return\n }\n\n // If nothing found and fetchOpts didn't explicitly request global, try fallback to global\n // This helps in setups where plugin created a standalone global (default slug 'appearance-settings')\n const explicitlyRequestedGlobal = !!(\n (fetchOpts as FetchThemeConfigurationOptions | undefined)?.useGlobal === true ||\n (fetchOpts as FetchThemeConfigurationOptions | undefined)?.collectionSlug ===\n 'appearance-settings'\n )\n\n if (!explicitlyRequestedGlobal) {\n try {\n // Prefer custom.collectionSlug if provided, otherwise try the default standalone slug\n const fallbackCollection = (custom && custom.collectionSlug) || 'appearance-settings'\n const fallbackOpts: FetchThemeConfigurationOptions = {\n useGlobal: true,\n collectionSlug: fallbackCollection,\n }\n const fallbackConfig = await fetchThemeConfiguration(fallbackOpts)\n if (!isMounted) return\n if (fallbackConfig) {\n // Found theme config in global, use it\n setOptions(buildOptionsFromConfiguration(fallbackConfig, themePresets))\n return\n }\n } catch (e) {\n console.warn('[ThemeTokenSelectField] Fallback global fetch failed:', e)\n }\n }\n\n // final fallback: use empty tokens\n setOptions(buildOptionsFromConfiguration(configuration, themePresets))\n })\n\n return () => {\n isMounted = false\n }\n }, [themePresets, field.admin?.custom])\n\n const handleSelect = useCallback(\n (nextValue: string) => {\n setValue(nextValue)\n },\n [setValue],\n )\n\n const label =\n typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || ''\n let description = ''\n if (typeof field.admin?.description === 'string') {\n description = field.admin.description\n } else if (\n field.admin?.description &&\n typeof field.admin.description === 'object' &&\n typeof field.admin.description.en === 'string'\n ) {\n description = field.admin.description.en\n }\n\n // Helper function to get label text from localized or string label\n const getOptionLabel = (option: ThemeColorOption): string => {\n if (typeof option.label === 'string') {\n return option.label\n }\n // Prefer English, fallback to Czech, then any available language\n return option.label.en || option.label.cs || Object.values(option.label)[0] || option.value\n }\n\n // Resolve CSS variable colors (e.g., 'var(--primary)') to their computed values when possible\n const resolveCssColor = (color: string): string => {\n if (typeof window === 'undefined' || !color || !color.trim().startsWith('var(')) {\n return color\n }\n\n try {\n const match = color.trim().match(/var\\((--[^)]+)\\)/)\n if (!match) return color\n const varName = match[1]\n const computed = getComputedStyle(document.documentElement).getPropertyValue(varName).trim()\n return computed || color\n } catch (e) {\n return color\n }\n }\n\n return (\n <div className=\"field-type theme-token-select\">\n {label && (\n <label\n className=\"field-label\"\n htmlFor={path}\n style={{ display: 'block', marginBottom: '8px' }}\n >\n {label}\n {field.required && <span className=\"required\">*</span>}\n </label>\n )}\n\n {description && (\n <div\n className=\"field-description\"\n style={{ marginBottom: '12px', fontSize: '13px', color: 'var(--theme-elevation-500)' }}\n >\n {description}\n </div>\n )}\n\n <div\n className=\"token-grid\"\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',\n gap: '10px',\n }}\n >\n {options.map((option) => {\n const isActive = option.value === selectedValue\n return (\n <button\n type=\"button\"\n key={option.value}\n onClick={() => handleSelect(option.value)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '10px 12px',\n borderRadius: '10px',\n border: isActive\n ? '2px solid var(--theme-success-500)'\n : '1px solid var(--theme-elevation-150)',\n backgroundColor: 'var(--theme-elevation-0)',\n boxShadow: isActive\n ? '0 10px 20px -10px rgba(59, 130, 246, 0.4)'\n : '0 1px 2px rgba(15, 23, 42, 0.08)',\n cursor: 'pointer',\n transition: 'border-color 0.2s ease, box-shadow 0.2s ease',\n }}\n >\n <span\n aria-hidden\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n border: '1px solid rgba(15, 23, 42, 0.08)',\n backgroundColor: resolveCssColor(option.color),\n flexShrink: 0,\n }}\n />\n <span\n style={{ fontSize: '13px', fontWeight: 600, color: 'var(--theme-elevation-800)' }}\n >\n {getOptionLabel(option)}\n </span>\n </button>\n )\n })}\n </div>\n\n <select\n id={path}\n value={selectedValue}\n onChange={(event) => handleSelect(event.target.value)}\n style={{ display: 'none' }}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {getOptionLabel(option)}\n </option>\n ))}\n </select>\n </div>\n )\n}\n"],"names":["useField","useCallback","useEffect","useMemo","useState","allThemePresets","fetchThemeConfiguration","resolveThemeConfiguration","FALLBACK_TOKENS","value","label","en","cs","color","buildOptionsFromConfiguration","configuration","themePresets","resolved","lightMode","orderedKeys","typedLightMode","tokens","map","key","trim","length","labelMap","background","card","muted","accent","secondary","primary","popover","filter","token","ThemeTokenSelectField","props","path","field","setValue","options","setOptions","selectedValue","customPresets","admin","custom","isMounted","fetchOpts","fetchThemeConfigurationOptions","fetchOptions","collectionSlug","useGlobal","tenantSlug","depth","locale","draft","queryParams","undefined","then","explicitlyRequestedGlobal","fallbackCollection","fallbackOpts","fallbackConfig","e","console","warn","handleSelect","nextValue","description","getOptionLabel","option","Object","values","resolveCssColor","window","startsWith","match","varName","computed","getComputedStyle","document","documentElement","getPropertyValue","div","className","htmlFor","style","display","marginBottom","required","span","fontSize","gridTemplateColumns","gap","isActive","button","type","onClick","alignItems","padding","borderRadius","border","backgroundColor","boxShadow","cursor","transition","aria-hidden","width","height","flexShrink","fontWeight","select","id","onChange","event","target"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FontPreview.d.ts","sourceRoot":"","sources":["../../../../src/globals/ThemeSettings/FontPicker/FontPreview.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAA;
|
|
1
|
+
{"version":3,"file":"FontPreview.d.ts","sourceRoot":"","sources":["../../../../src/globals/ThemeSettings/FontPicker/FontPreview.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAA;AAIrE,MAAM,MAAM,cAAc,GACtB,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,MAAM,GACN,OAAO,GACP,OAAO,GACP,SAAS,GACT,MAAM,GACN,KAAK,GACL,MAAM,CAAA;AAEV,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,cAAc,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CACpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAgPlD,CAAA"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import React, { useEffect, useRef } from 'react';
|
|
4
|
+
import { getTranslations } from '../../../translations.js';
|
|
5
|
+
import { getAdminLanguage } from '../../../utils/getAdminLanguage.js';
|
|
4
6
|
/**
|
|
5
7
|
* FontPreview component with Shadow DOM isolation
|
|
6
8
|
*
|
|
@@ -54,6 +56,7 @@ import React, { useEffect, useRef } from 'react';
|
|
|
54
56
|
padding: 0;
|
|
55
57
|
`;
|
|
56
58
|
let content;
|
|
59
|
+
const t = getTranslations(getAdminLanguage());
|
|
57
60
|
switch(variant){
|
|
58
61
|
case 'h1':
|
|
59
62
|
content = document.createElement('h1');
|
|
@@ -127,7 +130,7 @@ import React, { useEffect, useRef } from 'react';
|
|
|
127
130
|
line-height: 1.8;
|
|
128
131
|
margin: 4px 0;
|
|
129
132
|
`;
|
|
130
|
-
line.textContent = `${weight} -
|
|
133
|
+
line.textContent = `${weight} - ${t.ui.sampleSentence}`;
|
|
131
134
|
content.appendChild(line);
|
|
132
135
|
});
|
|
133
136
|
break;
|
|
@@ -153,9 +156,9 @@ import React, { useEffect, useRef } from 'react';
|
|
|
153
156
|
font-weight: 400;
|
|
154
157
|
line-height: 1.5;
|
|
155
158
|
margin: 0;
|
|
156
|
-
color: var(--theme-text-secondary, #6b7280);
|
|
159
|
+
color: var(--theme-text-secondary, #6b7280); // visual only (no text change)
|
|
157
160
|
`;
|
|
158
|
-
description.textContent = text ||
|
|
161
|
+
description.textContent = text || t.ui.sampleSentence;
|
|
159
162
|
content.appendChild(title);
|
|
160
163
|
content.appendChild(description);
|
|
161
164
|
break;
|
|
@@ -182,7 +185,7 @@ import React, { useEffect, useRef } from 'react';
|
|
|
182
185
|
flex: 1;
|
|
183
186
|
opacity: 0.7;
|
|
184
187
|
`;
|
|
185
|
-
sampleSpan.textContent = text ||
|
|
188
|
+
sampleSpan.textContent = text || t.ui.sampleSentence;
|
|
186
189
|
content.appendChild(nameSpan);
|
|
187
190
|
content.appendChild(sampleSpan);
|
|
188
191
|
break;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/globals/ThemeSettings/FontPicker/FontPreview.tsx"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useRef } from 'react'\nimport type { GoogleFont } from '../../../app/api/google-fonts/route'\n\nexport type PreviewVariant =\n | 'h1'\n | 'h2'\n | 'h3'\n | 'body'\n | 'small'\n | 'chars'\n | 'weights'\n | 'card'\n | 'row'\n | 'name'\n\nexport interface FontPreviewProps {\n font: GoogleFont\n variant: PreviewVariant\n text?: string\n onLoad?: () => void\n}\n\n/**\n * FontPreview component with Shadow DOM isolation\n *\n * This component renders font previews in an isolated Shadow DOM\n * to prevent Payload CMS admin styles from affecting the preview.\n */\nexport const FontPreview: React.FC<FontPreviewProps> = ({ font, variant, text, onLoad }) => {\n const shadowHostRef = useRef<HTMLDivElement>(null)\n const shadowRootRef = useRef<ShadowRoot | null>(null)\n const fontLoadedRef = useRef(false)\n\n useEffect(() => {\n if (!shadowHostRef.current) return\n\n // Create Shadow DOM if not already created\n if (!shadowRootRef.current) {\n shadowRootRef.current = shadowHostRef.current.attachShadow({ mode: 'open' })\n }\n\n const shadowRoot = shadowRootRef.current\n\n // Get font weights\n const weights = font.variants.filter((v) => !v.includes('italic')).join(';')\n const fontFamily = font.family\n\n // Load font CSS\n const loadFont = async () => {\n if (fontLoadedRef.current) return\n\n try {\n // Create font face CSS\n const fontUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(\n fontFamily,\n )}:wght@${weights}&display=swap`\n\n // Check if font is already loaded\n const link = document.createElement('link')\n link.rel = 'stylesheet'\n link.href = fontUrl\n\n // Wait for font to load\n link.onload = () => {\n fontLoadedRef.current = true\n onLoad?.()\n }\n\n // Add link to shadow root\n shadowRoot.appendChild(link)\n } catch (error) {\n console.error('Error loading font:', error)\n }\n }\n\n loadFont()\n\n // Render preview based on variant\n const renderPreview = () => {\n const container = document.createElement('div')\n container.style.cssText = `\n font-family: '${fontFamily}', sans-serif;\n color: inherit;\n margin: 0;\n padding: 0;\n `\n\n let content: HTMLElement\n\n switch (variant) {\n case 'h1':\n content = document.createElement('h1')\n content.style.cssText = `\n font-size: 48px;\n font-weight: 700;\n line-height: 1.2;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'h2':\n content = document.createElement('h2')\n content.style.cssText = `\n font-size: 36px;\n font-weight: 600;\n line-height: 1.3;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'h3':\n content = document.createElement('h3')\n content.style.cssText = `\n font-size: 24px;\n font-weight: 500;\n line-height: 1.4;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'body':\n content = document.createElement('p')\n content.style.cssText = `\n font-size: 16px;\n font-weight: 400;\n line-height: 1.6;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'small':\n content = document.createElement('p')\n content.style.cssText = `\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'chars':\n content = document.createElement('div')\n content.style.cssText = `\n font-size: 18px;\n font-weight: 400;\n line-height: 1.5;\n margin: 0;\n `\n content.textContent = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz 0123456789'\n break\n\n case 'weights':\n content = document.createElement('div')\n content.style.cssText = `margin: 0;`\n const availableWeights = font.variants\n .filter((v) => !v.includes('italic'))\n .map((v) => parseInt(v))\n .filter((w) => !isNaN(w))\n .sort((a, b) => a - b)\n\n availableWeights.forEach((weight) => {\n const line = document.createElement('div')\n line.style.cssText = `\n font-size: 16px;\n font-weight: ${weight};\n line-height: 1.8;\n margin: 4px 0;\n `\n line.textContent = `${weight} - The quick brown fox jumps over the lazy dog`\n content.appendChild(line)\n })\n break\n\n case 'card':\n content = document.createElement('div')\n content.style.cssText = `\n padding: 16px;\n background: var(--theme-bg, #ffffff);\n border: 1px solid var(--theme-border, #e5e7eb);\n border-radius: 8px;\n margin: 0;\n `\n const title = document.createElement('h3')\n title.style.cssText = `\n font-size: 20px;\n font-weight: 600;\n margin: 0 0 8px 0;\n `\n title.textContent = font.family\n const description = document.createElement('p')\n description.style.cssText = `\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n margin: 0;\n color: var(--theme-text-secondary, #6b7280);\n `\n description.textContent = text || 'The quick brown fox jumps over the lazy dog'\n content.appendChild(title)\n content.appendChild(description)\n break\n\n case 'row':\n content = document.createElement('div')\n content.style.cssText = `\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 12px 16px;\n margin: 0;\n `\n const nameSpan = document.createElement('span')\n nameSpan.style.cssText = `\n font-size: 16px;\n font-weight: 500;\n min-width: 150px;\n `\n nameSpan.textContent = font.family\n const sampleSpan = document.createElement('span')\n sampleSpan.style.cssText = `\n font-size: 16px;\n font-weight: 400;\n flex: 1;\n opacity: 0.7;\n `\n sampleSpan.textContent = text || 'The quick brown fox jumps over the lazy dog'\n content.appendChild(nameSpan)\n content.appendChild(sampleSpan)\n break\n\n case 'name':\n default:\n content = document.createElement('span')\n content.style.cssText = `\n font-size: 16px;\n font-weight: 500;\n margin: 0;\n `\n content.textContent = font.family\n break\n }\n\n container.appendChild(content)\n return container\n }\n\n // Clear previous content\n shadowRoot.innerHTML = ''\n\n // Render preview\n const preview = renderPreview()\n shadowRoot.appendChild(preview)\n\n // Cleanup\n return () => {\n if (shadowRoot) {\n shadowRoot.innerHTML = ''\n }\n }\n }, [font, variant, text, onLoad])\n\n return <div ref={shadowHostRef} style={{ width: '100%', minHeight: '20px' }} />\n}\n"],"names":["React","useEffect","useRef","FontPreview","font","variant","text","onLoad","shadowHostRef","shadowRootRef","fontLoadedRef","current","attachShadow","mode","shadowRoot","weights","variants","filter","v","includes","join","fontFamily","family","loadFont","fontUrl","encodeURIComponent","link","document","createElement","rel","href","onload","appendChild","error","console","renderPreview","container","style","cssText","content","textContent","availableWeights","map","parseInt","w","isNaN","sort","a","b","forEach","weight","line","title","description","nameSpan","sampleSpan","innerHTML","preview","div","ref","width","minHeight"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/globals/ThemeSettings/FontPicker/FontPreview.tsx"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useRef } from 'react'\nimport type { GoogleFont } from '../../../app/api/google-fonts/route'\nimport { getTranslations } from '../../../translations.js'\nimport { getAdminLanguage } from '../../../utils/getAdminLanguage.js'\n\nexport type PreviewVariant =\n | 'h1'\n | 'h2'\n | 'h3'\n | 'body'\n | 'small'\n | 'chars'\n | 'weights'\n | 'card'\n | 'row'\n | 'name'\n\nexport interface FontPreviewProps {\n font: GoogleFont\n variant: PreviewVariant\n text?: string\n onLoad?: () => void\n}\n\n/**\n * FontPreview component with Shadow DOM isolation\n *\n * This component renders font previews in an isolated Shadow DOM\n * to prevent Payload CMS admin styles from affecting the preview.\n */\nexport const FontPreview: React.FC<FontPreviewProps> = ({ font, variant, text, onLoad }) => {\n const shadowHostRef = useRef<HTMLDivElement>(null)\n const shadowRootRef = useRef<ShadowRoot | null>(null)\n const fontLoadedRef = useRef(false)\n\n useEffect(() => {\n if (!shadowHostRef.current) return\n\n // Create Shadow DOM if not already created\n if (!shadowRootRef.current) {\n shadowRootRef.current = shadowHostRef.current.attachShadow({ mode: 'open' })\n }\n\n const shadowRoot = shadowRootRef.current\n\n // Get font weights\n const weights = font.variants.filter((v) => !v.includes('italic')).join(';')\n const fontFamily = font.family\n\n // Load font CSS\n const loadFont = async () => {\n if (fontLoadedRef.current) return\n\n try {\n // Create font face CSS\n const fontUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(\n fontFamily,\n )}:wght@${weights}&display=swap`\n\n // Check if font is already loaded\n const link = document.createElement('link')\n link.rel = 'stylesheet'\n link.href = fontUrl\n\n // Wait for font to load\n link.onload = () => {\n fontLoadedRef.current = true\n onLoad?.()\n }\n\n // Add link to shadow root\n shadowRoot.appendChild(link)\n } catch (error) {\n console.error('Error loading font:', error)\n }\n }\n\n loadFont()\n\n // Render preview based on variant\n const renderPreview = () => {\n const container = document.createElement('div')\n container.style.cssText = `\n font-family: '${fontFamily}', sans-serif;\n color: inherit;\n margin: 0;\n padding: 0;\n `\n\n let content: HTMLElement\n const t = getTranslations(getAdminLanguage())\n\n switch (variant) {\n case 'h1':\n content = document.createElement('h1')\n content.style.cssText = `\n font-size: 48px;\n font-weight: 700;\n line-height: 1.2;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'h2':\n content = document.createElement('h2')\n content.style.cssText = `\n font-size: 36px;\n font-weight: 600;\n line-height: 1.3;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'h3':\n content = document.createElement('h3')\n content.style.cssText = `\n font-size: 24px;\n font-weight: 500;\n line-height: 1.4;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'body':\n content = document.createElement('p')\n content.style.cssText = `\n font-size: 16px;\n font-weight: 400;\n line-height: 1.6;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'small':\n content = document.createElement('p')\n content.style.cssText = `\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n margin: 0;\n `\n content.textContent = text || font.family\n break\n\n case 'chars':\n content = document.createElement('div')\n content.style.cssText = `\n font-size: 18px;\n font-weight: 400;\n line-height: 1.5;\n margin: 0;\n `\n content.textContent = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz 0123456789'\n break\n\n case 'weights':\n content = document.createElement('div')\n content.style.cssText = `margin: 0;`\n const availableWeights = font.variants\n .filter((v) => !v.includes('italic'))\n .map((v) => parseInt(v))\n .filter((w) => !isNaN(w))\n .sort((a, b) => a - b)\n\n availableWeights.forEach((weight) => {\n const line = document.createElement('div')\n line.style.cssText = `\n font-size: 16px;\n font-weight: ${weight};\n line-height: 1.8;\n margin: 4px 0;\n `\n line.textContent = `${weight} - ${t.ui.sampleSentence}`\n content.appendChild(line)\n })\n break\n\n case 'card':\n content = document.createElement('div')\n content.style.cssText = `\n padding: 16px;\n background: var(--theme-bg, #ffffff);\n border: 1px solid var(--theme-border, #e5e7eb);\n border-radius: 8px;\n margin: 0;\n `\n const title = document.createElement('h3')\n title.style.cssText = `\n font-size: 20px;\n font-weight: 600;\n margin: 0 0 8px 0;\n `\n title.textContent = font.family\n const description = document.createElement('p')\n description.style.cssText = `\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n margin: 0;\n color: var(--theme-text-secondary, #6b7280); // visual only (no text change)\n `\n description.textContent = text || t.ui.sampleSentence\n content.appendChild(title)\n content.appendChild(description)\n break\n\n case 'row':\n content = document.createElement('div')\n content.style.cssText = `\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 12px 16px;\n margin: 0;\n `\n const nameSpan = document.createElement('span')\n nameSpan.style.cssText = `\n font-size: 16px;\n font-weight: 500;\n min-width: 150px;\n `\n nameSpan.textContent = font.family\n const sampleSpan = document.createElement('span')\n sampleSpan.style.cssText = `\n font-size: 16px;\n font-weight: 400;\n flex: 1;\n opacity: 0.7;\n `\n sampleSpan.textContent = text || t.ui.sampleSentence\n content.appendChild(nameSpan)\n content.appendChild(sampleSpan)\n break\n\n case 'name':\n default:\n content = document.createElement('span')\n content.style.cssText = `\n font-size: 16px;\n font-weight: 500;\n margin: 0;\n `\n content.textContent = font.family\n break\n }\n\n container.appendChild(content)\n return container\n }\n\n // Clear previous content\n shadowRoot.innerHTML = ''\n\n // Render preview\n const preview = renderPreview()\n shadowRoot.appendChild(preview)\n\n // Cleanup\n return () => {\n if (shadowRoot) {\n shadowRoot.innerHTML = ''\n }\n }\n }, [font, variant, text, onLoad])\n\n return <div ref={shadowHostRef} style={{ width: '100%', minHeight: '20px' }} />\n}\n"],"names":["React","useEffect","useRef","getTranslations","getAdminLanguage","FontPreview","font","variant","text","onLoad","shadowHostRef","shadowRootRef","fontLoadedRef","current","attachShadow","mode","shadowRoot","weights","variants","filter","v","includes","join","fontFamily","family","loadFont","fontUrl","encodeURIComponent","link","document","createElement","rel","href","onload","appendChild","error","console","renderPreview","container","style","cssText","content","t","textContent","availableWeights","map","parseInt","w","isNaN","sort","a","b","forEach","weight","line","ui","sampleSentence","title","description","nameSpan","sampleSpan","innerHTML","preview","div","ref","width","minHeight"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/globals/ThemeSettings/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/globals/ThemeSettings/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,YAqH3B,CAAA"}
|
|
@@ -6,9 +6,15 @@
|
|
|
6
6
|
* - Google Fonts API key (optional, for extended font library)
|
|
7
7
|
*/ export const ThemeSettings = {
|
|
8
8
|
slug: 'themeSettings',
|
|
9
|
-
label:
|
|
9
|
+
label: {
|
|
10
|
+
en: 'Theme Settings',
|
|
11
|
+
cs: 'Nastavení témat'
|
|
12
|
+
},
|
|
10
13
|
admin: {
|
|
11
|
-
group:
|
|
14
|
+
group: {
|
|
15
|
+
en: 'Settings',
|
|
16
|
+
cs: 'Nastavení'
|
|
17
|
+
}
|
|
12
18
|
},
|
|
13
19
|
access: {
|
|
14
20
|
read: ()=>true,
|
|
@@ -22,15 +28,24 @@
|
|
|
22
28
|
type: 'tabs',
|
|
23
29
|
tabs: [
|
|
24
30
|
{
|
|
25
|
-
label:
|
|
31
|
+
label: {
|
|
32
|
+
en: 'Typography',
|
|
33
|
+
cs: 'Typografie'
|
|
34
|
+
},
|
|
26
35
|
fields: [
|
|
27
36
|
{
|
|
28
37
|
name: 'activeFont',
|
|
29
38
|
type: 'text',
|
|
30
|
-
label:
|
|
39
|
+
label: {
|
|
40
|
+
en: 'Active Font Family',
|
|
41
|
+
cs: 'Aktivní rodina písem'
|
|
42
|
+
},
|
|
31
43
|
defaultValue: 'Inter',
|
|
32
44
|
admin: {
|
|
33
|
-
description:
|
|
45
|
+
description: {
|
|
46
|
+
en: 'The currently active font family for your website',
|
|
47
|
+
cs: 'Aktuální rodina písem pro váš web'
|
|
48
|
+
},
|
|
34
49
|
components: {
|
|
35
50
|
Field: '@kilivi/payloadcms-theme-management/globals/ThemeSettings/FontPicker'
|
|
36
51
|
}
|
|
@@ -39,9 +54,15 @@
|
|
|
39
54
|
{
|
|
40
55
|
name: 'googleFontsApiKey',
|
|
41
56
|
type: 'text',
|
|
42
|
-
label:
|
|
57
|
+
label: {
|
|
58
|
+
en: 'Google Fonts API Key',
|
|
59
|
+
cs: 'Google Fonts API klíč'
|
|
60
|
+
},
|
|
43
61
|
admin: {
|
|
44
|
-
description:
|
|
62
|
+
description: {
|
|
63
|
+
en: "Optional: Add your Google Fonts API key to access the full library of 1400+ fonts. Without this, you'll have access to 35 popular fonts.",
|
|
64
|
+
cs: 'Volitelné: přidejte svůj Google Fonts API klíč pro přístup k plné knihovně 1400+ písem. Bez něj máte k dispozici 35 populárních písem.'
|
|
65
|
+
},
|
|
45
66
|
placeholder: 'AIzaSy...'
|
|
46
67
|
}
|
|
47
68
|
},
|
|
@@ -150,7 +171,10 @@
|
|
|
150
171
|
]
|
|
151
172
|
},
|
|
152
173
|
{
|
|
153
|
-
label:
|
|
174
|
+
label: {
|
|
175
|
+
en: 'Font Loading',
|
|
176
|
+
cs: 'Načítání písem'
|
|
177
|
+
},
|
|
154
178
|
fields: [
|
|
155
179
|
{
|
|
156
180
|
type: 'ui',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/globals/ThemeSettings/config.ts"],"sourcesContent":["import type { GlobalConfig } from 'payload'\n\n/**\n * ThemeSettings Global Configuration\n *\n * This global stores theme-related settings including:\n * - Active font family (selected via FontPicker)\n * - Google Fonts API key (optional, for extended font library)\n */\nexport const ThemeSettings: GlobalConfig = {\n slug: 'themeSettings',\n label: 'Theme Settings',\n admin: {\n group: 'Settings',\n },\n access: {\n read: () => true,\n update: ({ req }) => {\n // Only admins can update theme settings\n return req.user?.roles?.includes('admin') || false\n },\n },\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n label: 'Typography',\n fields: [\n {\n name: 'activeFont',\n type: 'text',\n label: 'Active Font Family',\n defaultValue: 'Inter',\n admin: {\n description: 'The currently active font family for your website',\n components: {\n Field: '@kilivi/payloadcms-theme-management/globals/ThemeSettings/FontPicker',\n },\n },\n },\n {\n name: 'googleFontsApiKey',\n type: 'text',\n label: 'Google Fonts API Key',\n admin: {\n description
|
|
1
|
+
{"version":3,"sources":["../../../src/globals/ThemeSettings/config.ts"],"sourcesContent":["import type { GlobalConfig } from 'payload'\n\n/**\n * ThemeSettings Global Configuration\n *\n * This global stores theme-related settings including:\n * - Active font family (selected via FontPicker)\n * - Google Fonts API key (optional, for extended font library)\n */\nexport const ThemeSettings: GlobalConfig = {\n slug: 'themeSettings',\n label: { en: 'Theme Settings', cs: 'Nastavení témat' },\n admin: {\n group: { en: 'Settings', cs: 'Nastavení' },\n },\n access: {\n read: () => true,\n update: ({ req }) => {\n // Only admins can update theme settings\n return req.user?.roles?.includes('admin') || false\n },\n },\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n label: { en: 'Typography', cs: 'Typografie' },\n fields: [\n {\n name: 'activeFont',\n type: 'text',\n label: { en: 'Active Font Family', cs: 'Aktivní rodina písem' },\n defaultValue: 'Inter',\n admin: {\n description: {\n en: 'The currently active font family for your website',\n cs: 'Aktuální rodina písem pro váš web',\n },\n components: {\n Field: '@kilivi/payloadcms-theme-management/globals/ThemeSettings/FontPicker',\n },\n },\n },\n {\n name: 'googleFontsApiKey',\n type: 'text',\n label: { en: 'Google Fonts API Key', cs: 'Google Fonts API klíč' },\n admin: {\n description: {\n en: \"Optional: Add your Google Fonts API key to access the full library of 1400+ fonts. Without this, you'll have access to 35 popular fonts.\",\n cs: 'Volitelné: přidejte svůj Google Fonts API klíč pro přístup k plné knihovně 1400+ písem. Bez něj máte k dispozici 35 populárních písem.',\n },\n placeholder: 'AIzaSy...',\n },\n },\n\n {\n type: 'row',\n fields: [\n {\n name: 'fontWeightHeading',\n type: 'select',\n label: 'Heading Font Weight',\n defaultValue: '700',\n options: [\n { label: '100 - Thin', value: '100' },\n { label: '200 - Extra Light', value: '200' },\n { label: '300 - Light', value: '300' },\n { label: '400 - Regular', value: '400' },\n { label: '500 - Medium', value: '500' },\n { label: '600 - Semi Bold', value: '600' },\n { label: '700 - Bold', value: '700' },\n { label: '800 - Extra Bold', value: '800' },\n { label: '900 - Black', value: '900' },\n ],\n },\n {\n name: 'fontWeightBody',\n type: 'select',\n label: 'Body Font Weight',\n defaultValue: '400',\n options: [\n { label: '100 - Thin', value: '100' },\n { label: '200 - Extra Light', value: '200' },\n { label: '300 - Light', value: '300' },\n { label: '400 - Regular', value: '400' },\n { label: '500 - Medium', value: '500' },\n { label: '600 - Semi Bold', value: '600' },\n { label: '700 - Bold', value: '700' },\n { label: '800 - Extra Bold', value: '800' },\n { label: '900 - Black', value: '900' },\n ],\n },\n ],\n },\n {\n type: 'ui',\n name: 'typographyInfo',\n admin: {\n components: {\n Field:\n '@kilivi/payloadcms-theme-management/globals/ThemeSettings/fields/TypographyInfoField',\n },\n },\n },\n ],\n },\n {\n label: { en: 'Font Loading', cs: 'Načítání písem' },\n fields: [\n {\n type: 'ui',\n name: 'fontLoadingGuide',\n admin: {\n components: {\n Field:\n '@kilivi/payloadcms-theme-management/globals/ThemeSettings/fields/FontLoadingGuideField',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n}\n"],"names":["ThemeSettings","slug","label","en","cs","admin","group","access","read","update","req","user","roles","includes","fields","type","tabs","name","defaultValue","description","components","Field","placeholder","options","value"],"mappings":"AAEA;;;;;;CAMC,GACD,OAAO,MAAMA,gBAA8B;IACzCC,MAAM;IACNC,OAAO;QAAEC,IAAI;QAAkBC,IAAI;IAAkB;IACrDC,OAAO;QACLC,OAAO;YAAEH,IAAI;YAAYC,IAAI;QAAY;IAC3C;IACAG,QAAQ;QACNC,MAAM,IAAM;QACZC,QAAQ,CAAC,EAAEC,GAAG,EAAE;YACd,wCAAwC;YACxC,OAAOA,IAAIC,IAAI,EAAEC,OAAOC,SAAS,YAAY;QAC/C;IACF;IACAC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;gBACJ;oBACEd,OAAO;wBAAEC,IAAI;wBAAcC,IAAI;oBAAa;oBAC5CU,QAAQ;wBACN;4BACEG,MAAM;4BACNF,MAAM;4BACNb,OAAO;gCAAEC,IAAI;gCAAsBC,IAAI;4BAAuB;4BAC9Dc,cAAc;4BACdb,OAAO;gCACLc,aAAa;oCACXhB,IAAI;oCACJC,IAAI;gCACN;gCACAgB,YAAY;oCACVC,OAAO;gCACT;4BACF;wBACF;wBACA;4BACEJ,MAAM;4BACNF,MAAM;4BACNb,OAAO;gCAAEC,IAAI;gCAAwBC,IAAI;4BAAwB;4BACjEC,OAAO;gCACLc,aAAa;oCACXhB,IAAI;oCACJC,IAAI;gCACN;gCACAkB,aAAa;4BACf;wBACF;wBAEA;4BACEP,MAAM;4BACND,QAAQ;gCACN;oCACEG,MAAM;oCACNF,MAAM;oCACNb,OAAO;oCACPgB,cAAc;oCACdK,SAAS;wCACP;4CAAErB,OAAO;4CAAcsB,OAAO;wCAAM;wCACpC;4CAAEtB,OAAO;4CAAqBsB,OAAO;wCAAM;wCAC3C;4CAAEtB,OAAO;4CAAesB,OAAO;wCAAM;wCACrC;4CAAEtB,OAAO;4CAAiBsB,OAAO;wCAAM;wCACvC;4CAAEtB,OAAO;4CAAgBsB,OAAO;wCAAM;wCACtC;4CAAEtB,OAAO;4CAAmBsB,OAAO;wCAAM;wCACzC;4CAAEtB,OAAO;4CAAcsB,OAAO;wCAAM;wCACpC;4CAAEtB,OAAO;4CAAoBsB,OAAO;wCAAM;wCAC1C;4CAAEtB,OAAO;4CAAesB,OAAO;wCAAM;qCACtC;gCACH;gCACA;oCACEP,MAAM;oCACNF,MAAM;oCACNb,OAAO;oCACPgB,cAAc;oCACdK,SAAS;wCACP;4CAAErB,OAAO;4CAAcsB,OAAO;wCAAM;wCACpC;4CAAEtB,OAAO;4CAAqBsB,OAAO;wCAAM;wCAC3C;4CAAEtB,OAAO;4CAAesB,OAAO;wCAAM;wCACrC;4CAAEtB,OAAO;4CAAiBsB,OAAO;wCAAM;wCACvC;4CAAEtB,OAAO;4CAAgBsB,OAAO;wCAAM;wCACtC;4CAAEtB,OAAO;4CAAmBsB,OAAO;wCAAM;wCACzC;4CAAEtB,OAAO;4CAAcsB,OAAO;wCAAM;wCACpC;4CAAEtB,OAAO;4CAAoBsB,OAAO;wCAAM;wCAC1C;4CAAEtB,OAAO;4CAAesB,OAAO;wCAAM;qCACtC;gCACH;6BACD;wBACH;wBACA;4BACET,MAAM;4BACNE,MAAM;4BACNZ,OAAO;gCACLe,YAAY;oCACVC,OACE;gCACJ;4BACF;wBACF;qBACD;gBACH;gBACA;oBACEnB,OAAO;wBAAEC,IAAI;wBAAgBC,IAAI;oBAAiB;oBAClDU,QAAQ;wBACN;4BACEC,MAAM;4BACNE,MAAM;4BACNZ,OAAO;gCACLe,YAAY;oCACVC,OACE;gCACJ;4BACF;wBACF;qBACD;gBACH;aACD;QACH;KACD;AACH,EAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -27,5 +27,6 @@ export { getFontLoaderCode, getThemeFontFamilies, ThemeFontProvider, useThemeFon
|
|
|
27
27
|
export declare const ThemeManagementPlugin: (options?: ThemeManagementPluginOptions) => Plugin;
|
|
28
28
|
/** @deprecated use {@link themeManagementPlugin} */
|
|
29
29
|
export declare const themeConfigurationPlugin: (options?: ThemeManagementPluginOptions) => Plugin;
|
|
30
|
+
export { translations, getTranslations, registerTranslations, availableLanguages, } from './translations.js';
|
|
30
31
|
export default themeManagementPlugin;
|
|
31
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiD,MAAM,EAAa,MAAM,SAAS,CAAA;AAG/F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C,OAAO,KAAK,EAAE,8BAA8B,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAqG9F,eAAO,MAAM,qBAAqB,GAAI,UAAS,4BAAiC,KAAG,MA4KlF,CAAA;AAED,KAAK,iBAAiB,GAAG,MAAM,GAAG,8BAA8B,CAAA;AAEhE,eAAO,MAAM,uBAAuB,GAClC,UAAU,iBAAiB,KAC1B,OAAO,CAAC,sBAAsB,GAAG,IAAI,CA0EvC,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,WAAW,MAAM,KAAG,WAAW,GAAG,IAEhE,CAAA;AAED,eAAO,MAAM,wBAAwB,QAAO,WAAW,EAEtD,CAAA;AAED,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnE,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACtE,YAAY,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAA;AACnE,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACnF,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,iCAAiC,CAAA;AACxC,YAAY,EAAE,4BAA4B,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAA;AAC9F,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,sCAAsC,CAAA;AAC7C,YAAY,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAA;AACtF,OAAO,EAAE,sBAAsB,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAGvE,OAAO,EACL,gBAAgB,IAAI,iBAAiB,EACrC,oBAAoB,GACrB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEhF,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAG1D,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,eAAe,GAChB,MAAM,4BAA4B,CAAA;AAMnC,eAAO,MAAM,qBAAqB,aAxTa,4BAA4B,KAAQ,MAwTzB,CAAA;AAC1D,oDAAoD;AACpD,eAAO,MAAM,wBAAwB,aA1TU,4BAA4B,KAAQ,MA0TtB,CAAA;AAG7D,OAAO,EACL,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAE1B,eAAe,qBAAqB,CAAA"}
|