@kilivi/payloadcms-theme-management 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fields/ThemeTokenSelectField.d.ts.map +1 -1
- package/dist/fields/ThemeTokenSelectField.js +48 -9
- package/dist/fields/ThemeTokenSelectField.js.map +1 -1
- package/dist/utils/inferTenant.d.ts +5 -0
- package/dist/utils/inferTenant.d.ts.map +1 -0
- package/dist/utils/inferTenant.js +46 -0
- package/dist/utils/inferTenant.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeTokenSelectField.d.ts","sourceRoot":"","sources":["../../src/fields/ThemeTokenSelectField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"ThemeTokenSelectField.d.ts","sourceRoot":"","sources":["../../src/fields/ThemeTokenSelectField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAgGrD,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,KAAK,EAAE,sBAAsB,+BA+Q1E"}
|
|
@@ -3,6 +3,8 @@ 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
5
|
import { allThemePresets, fetchThemeConfiguration } from '../index.js';
|
|
6
|
+
import { getAdminLanguage } from '../utils/getAdminLanguage.js';
|
|
7
|
+
import { inferTenant } from '../utils/inferTenant.js';
|
|
6
8
|
import { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js';
|
|
7
9
|
const FALLBACK_TOKENS = [
|
|
8
10
|
{
|
|
@@ -124,6 +126,10 @@ export default function ThemeTokenSelectField(props) {
|
|
|
124
126
|
const { value, setValue } = useField({
|
|
125
127
|
path
|
|
126
128
|
});
|
|
129
|
+
// Try to read themeConfiguration from the active form (Site Settings) first
|
|
130
|
+
const { value: formThemeConfiguration } = useField({
|
|
131
|
+
path: 'themeConfiguration'
|
|
132
|
+
});
|
|
127
133
|
const [options, setOptions] = useState(FALLBACK_TOKENS);
|
|
128
134
|
const selectedValue = value || 'background';
|
|
129
135
|
// Get themePresets from admin.custom or use defaults
|
|
@@ -134,14 +140,24 @@ export default function ThemeTokenSelectField(props) {
|
|
|
134
140
|
field.admin?.custom
|
|
135
141
|
]);
|
|
136
142
|
useEffect(()=>{
|
|
143
|
+
// If the active form contains themeConfiguration (e.g., editing Site Settings), prefer it
|
|
144
|
+
if (formThemeConfiguration) {
|
|
145
|
+
setOptions(buildOptionsFromConfiguration(formThemeConfiguration, themePresets));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
137
148
|
let isMounted = true;
|
|
138
149
|
const custom = field.admin?.custom ?? {};
|
|
150
|
+
// Use helper to infer tenant from different sources (custom override, URL params, global runtime, cookies)
|
|
151
|
+
const inferredTenant = inferTenant(custom.tenantSlug);
|
|
152
|
+
// Determine admin language to pass as `locale` to fetch, if not provided
|
|
153
|
+
const adminLang = getAdminLanguage();
|
|
139
154
|
const fetchOpts = custom.fetchThemeConfigurationOptions ?? custom.fetchOptions ?? (custom.collectionSlug || typeof custom.useGlobal !== 'undefined' ? {
|
|
140
155
|
collectionSlug: custom.collectionSlug,
|
|
141
156
|
useGlobal: custom.useGlobal,
|
|
142
|
-
tenantSlug:
|
|
157
|
+
tenantSlug: inferredTenant,
|
|
143
158
|
depth: custom.depth,
|
|
144
|
-
|
|
159
|
+
// prefer explicit custom.locale, otherwise use admin language
|
|
160
|
+
locale: custom.locale ?? adminLang,
|
|
145
161
|
draft: custom.draft,
|
|
146
162
|
queryParams: custom.queryParams
|
|
147
163
|
} : undefined);
|
|
@@ -160,7 +176,9 @@ export default function ThemeTokenSelectField(props) {
|
|
|
160
176
|
const fallbackCollection = custom && custom.collectionSlug || 'appearance-settings';
|
|
161
177
|
const fallbackOpts = {
|
|
162
178
|
useGlobal: true,
|
|
163
|
-
collectionSlug: fallbackCollection
|
|
179
|
+
collectionSlug: fallbackCollection,
|
|
180
|
+
tenantSlug: inferredTenant,
|
|
181
|
+
locale: custom.locale ?? adminLang
|
|
164
182
|
};
|
|
165
183
|
const fallbackConfig = await fetchThemeConfiguration(fallbackOpts);
|
|
166
184
|
if (!isMounted) return;
|
|
@@ -181,27 +199,48 @@ export default function ThemeTokenSelectField(props) {
|
|
|
181
199
|
};
|
|
182
200
|
}, [
|
|
183
201
|
themePresets,
|
|
184
|
-
field.admin?.custom
|
|
202
|
+
field.admin?.custom,
|
|
203
|
+
formThemeConfiguration
|
|
185
204
|
]);
|
|
186
205
|
const handleSelect = useCallback((nextValue)=>{
|
|
187
206
|
setValue(nextValue);
|
|
188
207
|
}, [
|
|
189
208
|
setValue
|
|
190
209
|
]);
|
|
191
|
-
|
|
210
|
+
// Make admin language reactive so switching admin UI language updates labels
|
|
211
|
+
const initialAdminLang = getAdminLanguage();
|
|
212
|
+
const [adminLang, setAdminLang] = useState(initialAdminLang);
|
|
213
|
+
useEffect(()=>{
|
|
214
|
+
if (typeof document === 'undefined' || !('MutationObserver' in window)) return;
|
|
215
|
+
const el = document.documentElement;
|
|
216
|
+
const obs = new MutationObserver(()=>{
|
|
217
|
+
const next = getAdminLanguage();
|
|
218
|
+
if (next !== adminLang) setAdminLang(next);
|
|
219
|
+
});
|
|
220
|
+
obs.observe(el, {
|
|
221
|
+
attributes: true,
|
|
222
|
+
attributeFilter: [
|
|
223
|
+
'lang'
|
|
224
|
+
]
|
|
225
|
+
});
|
|
226
|
+
return ()=>obs.disconnect();
|
|
227
|
+
}, [
|
|
228
|
+
adminLang
|
|
229
|
+
]);
|
|
230
|
+
const label = typeof field.label === 'string' ? field.label : field.label && field.label[adminLang] || field.label?.en || field.label?.cs || '';
|
|
192
231
|
let description = '';
|
|
193
232
|
if (typeof field.admin?.description === 'string') {
|
|
194
233
|
description = field.admin.description;
|
|
195
|
-
} else if (field.admin?.description && typeof field.admin.description === 'object'
|
|
196
|
-
description = field.admin.description.en;
|
|
234
|
+
} else if (field.admin?.description && typeof field.admin.description === 'object') {
|
|
235
|
+
description = field.admin.description[adminLang] || field.admin.description.en || field.admin.description.cs || '';
|
|
197
236
|
}
|
|
198
237
|
// Helper function to get label text from localized or string label
|
|
199
238
|
const getOptionLabel = (option)=>{
|
|
200
239
|
if (typeof option.label === 'string') {
|
|
201
240
|
return option.label;
|
|
202
241
|
}
|
|
203
|
-
// Prefer
|
|
204
|
-
return option.label.en || option.label.cs || Object.values(option.label)[0] || option.value;
|
|
242
|
+
// Prefer current admin language, fallback to English/Czech, then any available language
|
|
243
|
+
return option.label[adminLang] || option.label.en || option.label.cs || Object.values(option.label)[0] || option.value;
|
|
205
244
|
};
|
|
206
245
|
// Resolve CSS variable colors (e.g., 'var(--primary)') to their computed values when possible
|
|
207
246
|
const resolveCssColor = (color)=>{
|
|
@@ -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, 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
|
+
{"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 { getAdminLanguage } from '../utils/getAdminLanguage.js'\nimport { inferTenant } from '../utils/inferTenant.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 // Try to read themeConfiguration from the active form (Site Settings) first\n const { value: formThemeConfiguration } = useField<SiteThemeConfiguration | null>({\n path: 'themeConfiguration',\n })\n\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 // If the active form contains themeConfiguration (e.g., editing Site Settings), prefer it\n if (formThemeConfiguration) {\n setOptions(buildOptionsFromConfiguration(formThemeConfiguration, themePresets))\n return\n }\n\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 // Use helper to infer tenant from different sources (custom override, URL params, global runtime, cookies)\n const inferredTenant = inferTenant(custom.tenantSlug)\n\n // Determine admin language to pass as `locale` to fetch, if not provided\n const adminLang = getAdminLanguage()\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: inferredTenant,\n depth: custom.depth,\n // prefer explicit custom.locale, otherwise use admin language\n locale: custom.locale ?? adminLang,\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 tenantSlug: inferredTenant,\n locale: custom.locale ?? adminLang,\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, formThemeConfiguration])\n\n const handleSelect = useCallback(\n (nextValue: string) => {\n setValue(nextValue)\n },\n [setValue],\n )\n\n // Make admin language reactive so switching admin UI language updates labels\n const initialAdminLang = getAdminLanguage()\n const [adminLang, setAdminLang] = useState<string>(initialAdminLang)\n\n useEffect(() => {\n if (typeof document === 'undefined' || !('MutationObserver' in window)) return\n const el = document.documentElement\n const obs = new MutationObserver(() => {\n const next = getAdminLanguage()\n if (next !== adminLang) setAdminLang(next)\n })\n obs.observe(el, { attributes: true, attributeFilter: ['lang'] })\n return () => obs.disconnect()\n }, [adminLang])\n\n const label =\n typeof field.label === 'string'\n ? field.label\n : (field.label && (field.label as Record<string, string>)[adminLang]) ||\n field.label?.en ||\n field.label?.cs ||\n ''\n\n let description = ''\n if (typeof field.admin?.description === 'string') {\n description = field.admin.description\n } else if (field.admin?.description && typeof field.admin.description === 'object') {\n description =\n (field.admin.description as Record<string, string>)[adminLang] ||\n (field.admin.description as Record<string, string>).en ||\n (field.admin.description as Record<string, string>).cs ||\n ''\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 current admin language, fallback to English/Czech, then any available language\n return (\n (option.label as Record<string, string>)[adminLang] ||\n option.label.en ||\n option.label.cs ||\n Object.values(option.label)[0] ||\n option.value\n )\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","getAdminLanguage","inferTenant","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","formThemeConfiguration","options","setOptions","selectedValue","customPresets","admin","custom","isMounted","inferredTenant","tenantSlug","adminLang","fetchOpts","fetchThemeConfigurationOptions","fetchOptions","collectionSlug","useGlobal","depth","locale","draft","queryParams","undefined","then","explicitlyRequestedGlobal","fallbackCollection","fallbackOpts","fallbackConfig","e","console","warn","handleSelect","nextValue","initialAdminLang","setAdminLang","document","window","el","documentElement","obs","MutationObserver","next","observe","attributes","attributeFilter","disconnect","description","getOptionLabel","option","Object","values","resolveCssColor","startsWith","match","varName","computed","getComputedStyle","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":"AAAA;;AAEA,SAASA,QAAQ,QAAQ,iBAAgB;AAEzC,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACjE,SAASC,eAAe,EAAEC,uBAAuB,QAAQ,cAAa;AAItE,SAASC,gBAAgB,QAAQ,+BAA8B;AAC/D,SAASC,WAAW,QAAQ,0BAAyB;AACrD,SAASC,yBAAyB,QAAQ,wCAAuC;AASjF,MAAMC,kBAAsC;IAC1C;QACEC,OAAO;QACPC,OAAO;YAAEC,IAAI;YAAoBC,IAAI;QAAgB;QACrDC,OAAO;IACT;IACA;QAAEJ,OAAO;QAAQC,OAAO;YAAEC,IAAI;YAAmBC,IAAI;QAAe;QAAGC,OAAO;IAAc;IAC5F;QAAEJ,OAAO;QAASC,OAAO;YAAEC,IAAI;YAAiBC,IAAI;QAAiB;QAAGC,OAAO;IAAe;IAC9F;QACEJ,OAAO;QACPC,OAAO;YAAEC,IAAI;YAAkBC,IAAI;QAAkB;QACrDC,OAAO;IACT;IACA;QACEJ,OAAO;QACPC,OAAO;YAAEC,IAAI;YAAqBC,IAAI;QAAoB;QAC1DC,OAAO;IACT;IACA;QACEJ,OAAO;QACPC,OAAO;YAAEC,IAAI;YAAmBC,IAAI;QAAkB;QACtDC,OAAO;IACT;CACD;AAED,gFAAgF;AAChF,kFAAkF;AAClF,uFAAuF;AAEvF,SAASC,8BACPC,aAAsE,EACtEC,YAA2B;IAE3B,IAAI,CAACD,eAAe;QAClB,OAAOP;IACT;IAEA,MAAMS,WAAWV,0BAA0BQ;IAC3C,MAAMG,YAAYD,SAASC,SAAS,IAAIF,YAAY,CAAC,EAAE,EAAEE,aAAa,CAAC;IACvE,MAAMC,cAAwB;QAC5B;QACA;QACA;QACA;QACA;QACA;QACA;KACD;IAED,MAAMC,iBAAiBF;IAEvB,MAAMG,SAASF,YACZG,GAAG,CAAC,CAACC;QACJ,MAAMd,QAAQW,gBAAgB,CAACG,IAAI;QACnC,IAAI,OAAOd,UAAU,YAAYA,MAAMe,IAAI,GAAGC,MAAM,KAAK,GAAG;YAC1D,OAAO;QACT;QAEA,MAAMC,WAAuD;YAC3DC,YAAY;gBAAEhB,IAAI;gBAAoBC,IAAI;YAAgB;YAC1DgB,MAAM;gBAAEjB,IAAI;gBAAmBC,IAAI;YAAe;YAClDiB,OAAO;gBAAElB,IAAI;gBAAiBC,IAAI;YAAiB;YACnDkB,QAAQ;gBAAEnB,IAAI;gBAAkBC,IAAI;YAAkB;YACtDmB,WAAW;gBAAEpB,IAAI;gBAAqBC,IAAI;YAAoB;YAC9DoB,SAAS;gBAAErB,IAAI;gBAAmBC,IAAI;YAAkB;YACxDqB,SAAS;gBAAEtB,IAAI;gBAAmBC,IAAI;YAAiB;QACzD;QAEA,OAAO;YACLH,OAAOc;YACPb,OAAOgB,QAAQ,CAACH,IAAI,IAAI;gBAAEZ,IAAIY;gBAAKX,IAAIW;YAAI;YAC3CV,OAAOJ;QACT;IACF,GACCyB,MAAM,CAAC,CAACC,QAA8CA,UAAU;IAEnE,OAAOd,OAAOI,MAAM,GAAG,IAAIJ,SAASb;AACtC;AAEA,eAAe,SAAS4B,sBAAsBC,KAA6B;IACzE,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGF;IACxB,MAAM,EAAE5B,KAAK,EAAE+B,QAAQ,EAAE,GAAG1C,SAAiB;QAAEwC;IAAK;IACpD,4EAA4E;IAC5E,MAAM,EAAE7B,OAAOgC,sBAAsB,EAAE,GAAG3C,SAAwC;QAChFwC,MAAM;IACR;IAEA,MAAM,CAACI,SAASC,WAAW,GAAGzC,SAA6BM;IAC3D,MAAMoC,gBAAgBnC,SAAS;IAE/B,qDAAqD;IACrD,MAAMO,eAAef,QAAQ;QAC3B,MAAM4C,gBAAiBN,MAAMO,KAAK,EAAEC,QAA6C/B;QACjF,OAAO6B,iBAAiBA,cAAcpB,MAAM,GAAG,IAAIoB,gBAAgB1C;IACrE,GAAG;QAACoC,MAAMO,KAAK,EAAEC;KAAO;IAExB/C,UAAU;QACR,0FAA0F;QAC1F,IAAIyC,wBAAwB;YAC1BE,WAAW7B,8BAA8B2B,wBAAwBzB;YACjE;QACF;QAEA,IAAIgC,YAAY;QAehB,MAAMD,SAAS,AAACR,MAAMO,KAAK,EAAEC,UAAqC,CAAC;QAEnE,2GAA2G;QAC3G,MAAME,iBAAiB3C,YAAYyC,OAAOG,UAAU;QAEpD,yEAAyE;QACzE,MAAMC,YAAY9C;QAElB,MAAM+C,YACJL,OAAOM,8BAA8B,IACrCN,OAAOO,YAAY,IAClBP,CAAAA,OAAOQ,cAAc,IAAI,OAAOR,OAAOS,SAAS,KAAK,cACjD;YACCD,gBAAgBR,OAAOQ,cAAc;YACrCC,WAAWT,OAAOS,SAAS;YAC3BN,YAAYD;YACZQ,OAAOV,OAAOU,KAAK;YACnB,8DAA8D;YAC9DC,QAAQX,OAAOW,MAAM,IAAIP;YACzBQ,OAAOZ,OAAOY,KAAK;YACnBC,aAAab,OAAOa,WAAW;QACjC,IACAC,SAAQ;QAEdzD,wBAAwBgD,WAAWU,IAAI,CAAC,OAAO/C;YAC7C,IAAI,CAACiC,WAAW;YAChB,IAAIjC,eAAe;gBACjB4B,WAAW7B,8BAA8BC,eAAeC;gBACxD;YACF;YAEA,0FAA0F;YAC1F,qGAAqG;YACrG,MAAM+C,4BAA4B,CAAC,CACjC,CAAA,AAACX,WAA0DI,cAAc,QACzE,AAACJ,WAA0DG,mBACzD,qBAAoB;YAGxB,IAAI,CAACQ,2BAA2B;gBAC9B,IAAI;oBACF,sFAAsF;oBACtF,MAAMC,qBAAqB,AAACjB,UAAUA,OAAOQ,cAAc,IAAK;oBAChE,MAAMU,eAA+C;wBACnDT,WAAW;wBACXD,gBAAgBS;wBAChBd,YAAYD;wBACZS,QAAQX,OAAOW,MAAM,IAAIP;oBAC3B;oBACA,MAAMe,iBAAiB,MAAM9D,wBAAwB6D;oBACrD,IAAI,CAACjB,WAAW;oBAChB,IAAIkB,gBAAgB;wBAClB,uCAAuC;wBACvCvB,WAAW7B,8BAA8BoD,gBAAgBlD;wBACzD;oBACF;gBACF,EAAE,OAAOmD,GAAG;oBACVC,QAAQC,IAAI,CAAC,yDAAyDF;gBACxE;YACF;YAEA,mCAAmC;YACnCxB,WAAW7B,8BAA8BC,eAAeC;QAC1D;QAEA,OAAO;YACLgC,YAAY;QACd;IACF,GAAG;QAAChC;QAAcuB,MAAMO,KAAK,EAAEC;QAAQN;KAAuB;IAE9D,MAAM6B,eAAevE,YACnB,CAACwE;QACC/B,SAAS+B;IACX,GACA;QAAC/B;KAAS;IAGZ,6EAA6E;IAC7E,MAAMgC,mBAAmBnE;IACzB,MAAM,CAAC8C,WAAWsB,aAAa,GAAGvE,SAAiBsE;IAEnDxE,UAAU;QACR,IAAI,OAAO0E,aAAa,eAAe,CAAE,CAAA,sBAAsBC,MAAK,GAAI;QACxE,MAAMC,KAAKF,SAASG,eAAe;QACnC,MAAMC,MAAM,IAAIC,iBAAiB;YAC/B,MAAMC,OAAO3E;YACb,IAAI2E,SAAS7B,WAAWsB,aAAaO;QACvC;QACAF,IAAIG,OAAO,CAACL,IAAI;YAAEM,YAAY;YAAMC,iBAAiB;gBAAC;aAAO;QAAC;QAC9D,OAAO,IAAML,IAAIM,UAAU;IAC7B,GAAG;QAACjC;KAAU;IAEd,MAAMzC,QACJ,OAAO6B,MAAM7B,KAAK,KAAK,WACnB6B,MAAM7B,KAAK,GACX,AAAC6B,MAAM7B,KAAK,IAAI,AAAC6B,MAAM7B,KAAK,AAA2B,CAACyC,UAAU,IAClEZ,MAAM7B,KAAK,EAAEC,MACb4B,MAAM7B,KAAK,EAAEE,MACb;IAEN,IAAIyE,cAAc;IAClB,IAAI,OAAO9C,MAAMO,KAAK,EAAEuC,gBAAgB,UAAU;QAChDA,cAAc9C,MAAMO,KAAK,CAACuC,WAAW;IACvC,OAAO,IAAI9C,MAAMO,KAAK,EAAEuC,eAAe,OAAO9C,MAAMO,KAAK,CAACuC,WAAW,KAAK,UAAU;QAClFA,cACE,AAAC9C,MAAMO,KAAK,CAACuC,WAAW,AAA2B,CAAClC,UAAU,IAC9D,AAACZ,MAAMO,KAAK,CAACuC,WAAW,CAA4B1E,EAAE,IACtD,AAAC4B,MAAMO,KAAK,CAACuC,WAAW,CAA4BzE,EAAE,IACtD;IACJ;IAEA,mEAAmE;IACnE,MAAM0E,iBAAiB,CAACC;QACtB,IAAI,OAAOA,OAAO7E,KAAK,KAAK,UAAU;YACpC,OAAO6E,OAAO7E,KAAK;QACrB;QACA,wFAAwF;QACxF,OACE,AAAC6E,OAAO7E,KAAK,AAA2B,CAACyC,UAAU,IACnDoC,OAAO7E,KAAK,CAACC,EAAE,IACf4E,OAAO7E,KAAK,CAACE,EAAE,IACf4E,OAAOC,MAAM,CAACF,OAAO7E,KAAK,CAAC,CAAC,EAAE,IAC9B6E,OAAO9E,KAAK;IAEhB;IAEA,8FAA8F;IAC9F,MAAMiF,kBAAkB,CAAC7E;QACvB,IAAI,OAAO8D,WAAW,eAAe,CAAC9D,SAAS,CAACA,MAAMW,IAAI,GAAGmE,UAAU,CAAC,SAAS;YAC/E,OAAO9E;QACT;QAEA,IAAI;YACF,MAAM+E,QAAQ/E,MAAMW,IAAI,GAAGoE,KAAK,CAAC;YACjC,IAAI,CAACA,OAAO,OAAO/E;YACnB,MAAMgF,UAAUD,KAAK,CAAC,EAAE;YACxB,MAAME,WAAWC,iBAAiBrB,SAASG,eAAe,EAAEmB,gBAAgB,CAACH,SAASrE,IAAI;YAC1F,OAAOsE,YAAYjF;QACrB,EAAE,OAAOsD,GAAG;YACV,OAAOtD;QACT;IACF;IAEA,qBACE,MAACoF;QAAIC,WAAU;;YACZxF,uBACC,MAACA;gBACCwF,WAAU;gBACVC,SAAS7D;gBACT8D,OAAO;oBAAEC,SAAS;oBAASC,cAAc;gBAAM;;oBAE9C5F;oBACA6B,MAAMgE,QAAQ,kBAAI,KAACC;wBAAKN,WAAU;kCAAW;;;;YAIjDb,6BACC,KAACY;gBACCC,WAAU;gBACVE,OAAO;oBAAEE,cAAc;oBAAQG,UAAU;oBAAQ5F,OAAO;gBAA6B;0BAEpFwE;;0BAIL,KAACY;gBACCC,WAAU;gBACVE,OAAO;oBACLC,SAAS;oBACTK,qBAAqB;oBACrBC,KAAK;gBACP;0BAECjE,QAAQpB,GAAG,CAAC,CAACiE;oBACZ,MAAMqB,WAAWrB,OAAO9E,KAAK,KAAKmC;oBAClC,qBACE,MAACiE;wBACCC,MAAK;wBAELC,SAAS,IAAMzC,aAAaiB,OAAO9E,KAAK;wBACxC2F,OAAO;4BACLC,SAAS;4BACTW,YAAY;4BACZL,KAAK;4BACLM,SAAS;4BACTC,cAAc;4BACdC,QAAQP,WACJ,uCACA;4BACJQ,iBAAiB;4BACjBC,WAAWT,WACP,8CACA;4BACJU,QAAQ;4BACRC,YAAY;wBACd;;0CAEA,KAACf;gCACCgB,aAAW;gCACXpB,OAAO;oCACLqB,OAAO;oCACPC,QAAQ;oCACRR,cAAc;oCACdC,QAAQ;oCACRC,iBAAiB1B,gBAAgBH,OAAO1E,KAAK;oCAC7C8G,YAAY;gCACd;;0CAEF,KAACnB;gCACCJ,OAAO;oCAAEK,UAAU;oCAAQmB,YAAY;oCAAK/G,OAAO;gCAA6B;0CAE/EyE,eAAeC;;;uBAjCbA,OAAO9E,KAAK;gBAqCvB;;0BAGF,KAACoH;gBACCC,IAAIxF;gBACJ7B,OAAOmC;gBACPmF,UAAU,CAACC,QAAU1D,aAAa0D,MAAMC,MAAM,CAACxH,KAAK;gBACpD2F,OAAO;oBAAEC,SAAS;gBAAO;0BAExB3D,QAAQpB,GAAG,CAAC,CAACiE,uBACZ,KAACA;wBAA0B9E,OAAO8E,OAAO9E,KAAK;kCAC3C6E,eAAeC;uBADLA,OAAO9E,KAAK;;;;AAOnC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function inferTenantFromUrl(): string | undefined;
|
|
2
|
+
export declare function inferTenantFromCookie(): string | undefined;
|
|
3
|
+
export declare function inferTenantFromGlobal(): string | undefined;
|
|
4
|
+
export declare function inferTenant(customTenant?: string): string | undefined;
|
|
5
|
+
//# sourceMappingURL=inferTenant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inferTenant.d.ts","sourceRoot":"","sources":["../../src/utils/inferTenant.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAQvD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,SAAS,CAyB1D;AAED,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,SAAS,CAc1D;AAED,wBAAgB,WAAW,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAErE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export function inferTenantFromUrl() {
|
|
2
|
+
if (typeof window === 'undefined') return undefined;
|
|
3
|
+
try {
|
|
4
|
+
const params = new URLSearchParams(window.location.search);
|
|
5
|
+
return params.get('tenant') ?? params.get('tenantSlug') ?? params.get('tenantId') ?? undefined;
|
|
6
|
+
} catch (e) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function inferTenantFromCookie() {
|
|
11
|
+
if (typeof document === 'undefined' || !document.cookie) return undefined;
|
|
12
|
+
try {
|
|
13
|
+
const cookies = document.cookie.split(';').map((c)=>c.trim());
|
|
14
|
+
for (const c of cookies){
|
|
15
|
+
const [k, v] = c.split('=');
|
|
16
|
+
const key = k?.trim().toLowerCase();
|
|
17
|
+
if (!key || !v) continue;
|
|
18
|
+
if ([
|
|
19
|
+
'tenant',
|
|
20
|
+
'tenantslug',
|
|
21
|
+
'tenant-slug',
|
|
22
|
+
'x-tenant-id',
|
|
23
|
+
'x-tenant',
|
|
24
|
+
'payload-tenant',
|
|
25
|
+
'payload-tenant-slug'
|
|
26
|
+
].includes(key)) return decodeURIComponent(v);
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
} catch (e) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function inferTenantFromGlobal() {
|
|
34
|
+
if (typeof window === 'undefined') return undefined;
|
|
35
|
+
try {
|
|
36
|
+
const anyWin = window;
|
|
37
|
+
return anyWin?.__payload?.tenant?.slug || anyWin?.payload?.tenant || anyWin?.__PAYLOAD__?.tenantSlug || anyWin?.PAYLOAD?.tenantSlug || undefined;
|
|
38
|
+
} catch (e) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function inferTenant(customTenant) {
|
|
43
|
+
return customTenant ?? inferTenantFromUrl() ?? inferTenantFromGlobal() ?? inferTenantFromCookie();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=inferTenant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/inferTenant.ts"],"sourcesContent":["export function inferTenantFromUrl(): string | undefined {\n if (typeof window === 'undefined') return undefined\n try {\n const params = new URLSearchParams(window.location.search)\n return params.get('tenant') ?? params.get('tenantSlug') ?? params.get('tenantId') ?? undefined\n } catch (e) {\n return undefined\n }\n}\n\nexport function inferTenantFromCookie(): string | undefined {\n if (typeof document === 'undefined' || !document.cookie) return undefined\n try {\n const cookies = document.cookie.split(';').map((c) => c.trim())\n for (const c of cookies) {\n const [k, v] = c.split('=')\n const key = k?.trim().toLowerCase()\n if (!key || !v) continue\n if (\n [\n 'tenant',\n 'tenantslug',\n 'tenant-slug',\n 'x-tenant-id',\n 'x-tenant',\n 'payload-tenant',\n 'payload-tenant-slug',\n ].includes(key)\n )\n return decodeURIComponent(v)\n }\n return undefined\n } catch (e) {\n return undefined\n }\n}\n\nexport function inferTenantFromGlobal(): string | undefined {\n if (typeof window === 'undefined') return undefined\n try {\n const anyWin = window as unknown as Record<string, any>\n return (\n anyWin?.__payload?.tenant?.slug ||\n anyWin?.payload?.tenant ||\n anyWin?.__PAYLOAD__?.tenantSlug ||\n anyWin?.PAYLOAD?.tenantSlug ||\n undefined\n )\n } catch (e) {\n return undefined\n }\n}\n\nexport function inferTenant(customTenant?: string): string | undefined {\n return customTenant ?? inferTenantFromUrl() ?? inferTenantFromGlobal() ?? inferTenantFromCookie()\n}\n"],"names":["inferTenantFromUrl","window","undefined","params","URLSearchParams","location","search","get","e","inferTenantFromCookie","document","cookie","cookies","split","map","c","trim","k","v","key","toLowerCase","includes","decodeURIComponent","inferTenantFromGlobal","anyWin","__payload","tenant","slug","payload","__PAYLOAD__","tenantSlug","PAYLOAD","inferTenant","customTenant"],"mappings":"AAAA,OAAO,SAASA;IACd,IAAI,OAAOC,WAAW,aAAa,OAAOC;IAC1C,IAAI;QACF,MAAMC,SAAS,IAAIC,gBAAgBH,OAAOI,QAAQ,CAACC,MAAM;QACzD,OAAOH,OAAOI,GAAG,CAAC,aAAaJ,OAAOI,GAAG,CAAC,iBAAiBJ,OAAOI,GAAG,CAAC,eAAeL;IACvF,EAAE,OAAOM,GAAG;QACV,OAAON;IACT;AACF;AAEA,OAAO,SAASO;IACd,IAAI,OAAOC,aAAa,eAAe,CAACA,SAASC,MAAM,EAAE,OAAOT;IAChE,IAAI;QACF,MAAMU,UAAUF,SAASC,MAAM,CAACE,KAAK,CAAC,KAAKC,GAAG,CAAC,CAACC,IAAMA,EAAEC,IAAI;QAC5D,KAAK,MAAMD,KAAKH,QAAS;YACvB,MAAM,CAACK,GAAGC,EAAE,GAAGH,EAAEF,KAAK,CAAC;YACvB,MAAMM,MAAMF,GAAGD,OAAOI;YACtB,IAAI,CAACD,OAAO,CAACD,GAAG;YAChB,IACE;gBACE;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;aACD,CAACG,QAAQ,CAACF,MAEX,OAAOG,mBAAmBJ;QAC9B;QACA,OAAOhB;IACT,EAAE,OAAOM,GAAG;QACV,OAAON;IACT;AACF;AAEA,OAAO,SAASqB;IACd,IAAI,OAAOtB,WAAW,aAAa,OAAOC;IAC1C,IAAI;QACF,MAAMsB,SAASvB;QACf,OACEuB,QAAQC,WAAWC,QAAQC,QAC3BH,QAAQI,SAASF,UACjBF,QAAQK,aAAaC,cACrBN,QAAQO,SAASD,cACjB5B;IAEJ,EAAE,OAAOM,GAAG;QACV,OAAON;IACT;AACF;AAEA,OAAO,SAAS8B,YAAYC,YAAqB;IAC/C,OAAOA,gBAAgBjC,wBAAwBuB,2BAA2Bd;AAC5E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kilivi/payloadcms-theme-management",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Theme configuration plugin for Payload CMS v3 with 60+ professional themes and standalone collection support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|