theme-ops-sdk 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -9
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -21,25 +21,37 @@ npm install react react-dom
|
|
|
21
21
|
## Usage
|
|
22
22
|
|
|
23
23
|
```tsx
|
|
24
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
25
|
+
|
|
26
|
+
import { ConfigProvider, theme } from 'antd';
|
|
27
|
+
|
|
24
28
|
import { useThemeOps } from 'theme-ops-sdk';
|
|
25
29
|
|
|
26
30
|
function App() {
|
|
27
|
-
const
|
|
31
|
+
const [colorMode, setColorMode] = useState('light');
|
|
32
|
+
|
|
33
|
+
const { isLoading, getTheme, insertStyles } = useThemeOps({
|
|
28
34
|
organizationId: 'your-org-id',
|
|
29
35
|
appId: 'your-app-id', // optional
|
|
30
36
|
});
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!isLoading) {
|
|
40
|
+
insertStyles();
|
|
41
|
+
}
|
|
42
|
+
}, [isLoading, insertStyles]);
|
|
34
43
|
|
|
35
|
-
|
|
44
|
+
const antdTheme = useMemo(() => ({
|
|
45
|
+
cssVar: { key: 'theme-ops' },
|
|
46
|
+
...getTheme(colorMode),
|
|
47
|
+
algorithm:
|
|
48
|
+
colorMode === 'dark' ? theme.darkAlgorithm : theme.defaultAlgorithm,
|
|
49
|
+
}), [colorMode, getTheme]);
|
|
36
50
|
|
|
37
|
-
|
|
38
|
-
const lightTokens = theme('light');
|
|
39
|
-
const darkTokens = theme('dark');
|
|
51
|
+
if (isLoading) return <div>Loading theme...</div>;
|
|
40
52
|
|
|
41
53
|
return (
|
|
42
|
-
<ConfigProvider theme={
|
|
54
|
+
<ConfigProvider theme={antdTheme}>
|
|
43
55
|
<YourApp />
|
|
44
56
|
</ConfigProvider>
|
|
45
57
|
);
|
|
@@ -64,7 +76,7 @@ Main hook that fetches theme assets from the Theme Ops CDN.
|
|
|
64
76
|
| Property | Type | Description |
|
|
65
77
|
| -------------- | -------------------------------------------- | -------------------------------------------------------- |
|
|
66
78
|
| `isLoading` | `boolean` | `true` while fetching theme assets from the CDN |
|
|
67
|
-
| `
|
|
79
|
+
| `getTheme` | `(mode: 'light' \| 'dark') => ThemeConfig` | Returns design tokens for the given color mode |
|
|
68
80
|
| `insertStyles` | `() => void` | Inserts a `<link>` stylesheet into `document.head` |
|
|
69
81
|
|
|
70
82
|
## Types
|
package/dist/index.cjs
CHANGED
|
@@ -176,7 +176,7 @@ function useThemeOps(options) {
|
|
|
176
176
|
};
|
|
177
177
|
}, [organizationId, appId, releaseId, apiUrl]);
|
|
178
178
|
const resolvedThemeState = state.status === "ready" ? state.themeState : EMPTY_THEME_STATE;
|
|
179
|
-
const
|
|
179
|
+
const getTheme = react.useCallback(
|
|
180
180
|
(mode) => resolveThemeTokens(mode, resolvedThemeState),
|
|
181
181
|
[resolvedThemeState]
|
|
182
182
|
);
|
|
@@ -189,7 +189,7 @@ function useThemeOps(options) {
|
|
|
189
189
|
insertStylesIntoDOM(resolvedThemeState.cssUrl);
|
|
190
190
|
}
|
|
191
191
|
}, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);
|
|
192
|
-
return { isLoading: state.status === "loading",
|
|
192
|
+
return { isLoading: state.status === "loading", getTheme, insertStyles };
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
exports.useThemeOps = useThemeOps;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/buildCdnUrls.ts","../src/fetchReleaseFromApi.ts","../src/fetchThemeAssets.ts","../src/insertStylesIntoDOM.ts","../src/useThemeOps.ts"],"names":["themeLight","themeDark","appendCacheBuster","useReducer","useRef","useEffect","useCallback"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { BuildCdnUrlsOptions, CdnUrls } from \"./types\";\n\nconst CDN_BASE_URL = \"https://theme-ops.s3.sa-east-1.amazonaws.com\";\n\nfunction buildBasePath(organizationId: string, appId?: string): string {\n return appId ? `${organizationId}/${appId}` : organizationId;\n}\n\nexport function buildCdnUrls({\n organizationId,\n appId,\n}: BuildCdnUrlsOptions): CdnUrls {\n const assetPath = buildBasePath(organizationId, appId);\n\n return {\n theme: `${CDN_BASE_URL}/${assetPath}/theme.json`,\n themeFallback: `${CDN_BASE_URL}/${assetPath}/theme-fallback.json`,\n css: `${CDN_BASE_URL}/${assetPath}/css.css`,\n };\n}\n","import type { ApiReleaseResponse, ThemeState } from \"./types\";\n\nfunction buildReleaseUrl(apiUrl: string, releaseId: string): string {\n const base = apiUrl.replace(/\\/+$/, \"\");\n return `${base}/sdk/releases/${releaseId}`;\n}\n\nexport async function fetchReleaseFromApi(\n apiUrl: string,\n releaseId: string,\n): Promise<ThemeState> {\n const url = buildReleaseUrl(apiUrl, releaseId);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch release: ${response.status}`);\n }\n\n const data = (await response.json()) as ApiReleaseResponse;\n\n return {\n themeLight: data.themeLight,\n themeDark: data.themeDark,\n cssUrl: null,\n cssContent: data.css || null,\n };\n}\n","import type { CdnUrls, ThemeAssets, ThemeJson, ThemeTokens } from \"./types\";\n\nfunction appendCacheBuster(url: string): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}_t=${Date.now()}`;\n}\n\nasync function fetchJson<T>(url: string): Promise<T | null> {\n try {\n const response = await fetch(appendCacheBuster(url));\n if (!response.ok) return null;\n\n return (await response.json()) as T;\n } catch {\n return null;\n }\n}\n\nfunction extractThemesFromJson(json: ThemeJson | null): {\n themeLight: ThemeTokens | null;\n themeDark: ThemeTokens | null;\n} {\n return {\n themeLight: json?.light ?? null,\n themeDark: json?.dark ?? null,\n };\n}\n\nfunction isThemeJsonValid(json: ThemeJson | null): boolean {\n return json !== null && (json.light !== undefined || json.dark !== undefined);\n}\n\nexport async function fetchThemeAssets(urls: CdnUrls): Promise<ThemeAssets> {\n const activeJson = await fetchJson<ThemeJson>(urls.theme);\n const cacheBustedCssUrl = appendCacheBuster(urls.css);\n\n if (isThemeJsonValid(activeJson)) {\n const { themeLight, themeDark } = extractThemesFromJson(activeJson);\n return { themeLight, themeDark, cssUrl: cacheBustedCssUrl, usingFallback: false };\n }\n\n const fallbackJson = await fetchJson<ThemeJson>(urls.themeFallback);\n const { themeLight, themeDark } = extractThemesFromJson(fallbackJson);\n\n return {\n themeLight,\n themeDark,\n cssUrl: cacheBustedCssUrl,\n usingFallback: true,\n };\n}\n","const LINK_ELEMENT_ID = \"theme-ops-css\";\nconst STYLE_ELEMENT_ID = \"theme-ops-css-inline\";\n\nfunction appendCacheBuster(url: string): string {\n const baseUrl = url.replace(/[?&]_t=\\d+/, \"\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}_t=${Date.now()}`;\n}\n\nfunction findExistingLinkElement(): HTMLLinkElement | null {\n return document.getElementById(LINK_ELEMENT_ID) as HTMLLinkElement | null;\n}\n\nfunction findExistingInlineStyle(): HTMLStyleElement | null {\n return document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n}\n\nfunction createLinkElement(href: string): HTMLLinkElement {\n const link = document.createElement(\"link\");\n link.id = LINK_ELEMENT_ID;\n link.rel = \"stylesheet\";\n link.href = href;\n return link;\n}\n\nfunction removeElement(id: string): void {\n document.getElementById(id)?.remove();\n}\n\nexport function insertStylesIntoDOM(cssUrl: string): void {\n removeElement(STYLE_ELEMENT_ID);\n\n const freshUrl = appendCacheBuster(cssUrl);\n const existing = findExistingLinkElement();\n\n if (existing) {\n existing.href = freshUrl;\n return;\n }\n\n const link = createLinkElement(freshUrl);\n document.head.appendChild(link);\n}\n\nexport function insertInlineStylesIntoDOM(cssContent: string): void {\n removeElement(LINK_ELEMENT_ID);\n\n const existing = findExistingInlineStyle();\n\n if (existing) {\n existing.textContent = cssContent;\n return;\n }\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = cssContent;\n document.head.appendChild(style);\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\n\nimport { buildCdnUrls } from \"./buildCdnUrls\";\nimport { fetchReleaseFromApi } from \"./fetchReleaseFromApi\";\nimport { fetchThemeAssets } from \"./fetchThemeAssets\";\nimport {\n insertInlineStylesIntoDOM,\n insertStylesIntoDOM,\n} from \"./insertStylesIntoDOM\";\nimport type {\n ThemeConfig,\n ThemeState,\n UseThemeOpsOptions,\n UseThemeOpsResult,\n} from \"./types\";\n\ntype HookState =\n | { status: \"loading\" }\n | { status: \"ready\"; themeState: ThemeState };\n\ntype HookAction =\n | { type: \"FETCH_START\" }\n | { type: \"FETCH_SUCCESS\"; payload: ThemeState };\n\nfunction hookReducer(_state: HookState, action: HookAction): HookState {\n switch (action.type) {\n case \"FETCH_START\":\n return { status: \"loading\" };\n case \"FETCH_SUCCESS\":\n return { status: \"ready\", themeState: action.payload };\n }\n}\n\nconst EMPTY_THEME_STATE: ThemeState = {\n themeLight: null,\n themeDark: null,\n cssUrl: null,\n cssContent: null,\n};\n\nfunction resolveThemeTokens(\n mode: \"light\" | \"dark\",\n themeState: ThemeState,\n): ThemeConfig {\n const tokens = mode === \"dark\" ? themeState.themeDark : themeState.themeLight;\n if (!tokens) return {};\n\n return tokens as ThemeConfig;\n}\n\nfunction isReleasePreview(\n options: UseThemeOpsOptions,\n): options is UseThemeOpsOptions & { releaseId: string; apiUrl: string } {\n return Boolean(options.releaseId && options.apiUrl);\n}\n\nexport function useThemeOps(options: UseThemeOpsOptions): UseThemeOpsResult {\n const { organizationId, appId, releaseId, apiUrl } = options;\n const [state, dispatch] = useReducer(hookReducer, { status: \"loading\" });\n\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n dispatch({ type: \"FETCH_START\" });\n\n const fetchPromise = isReleasePreview(options)\n ? fetchReleaseFromApi(options.apiUrl, options.releaseId)\n : fetchThemeAssets(buildCdnUrls({ organizationId, appId })).then(\n (assets) => ({\n themeLight: assets.themeLight,\n themeDark: assets.themeDark,\n cssUrl: assets.cssUrl,\n cssContent: null,\n }),\n );\n\n fetchPromise.then((payload) => {\n if (!isMountedRef.current) return;\n\n dispatch({ type: \"FETCH_SUCCESS\", payload });\n });\n\n return () => {\n isMountedRef.current = false;\n };\n }, [organizationId, appId, releaseId, apiUrl]);\n\n const resolvedThemeState =\n state.status === \"ready\" ? state.themeState : EMPTY_THEME_STATE;\n\n const theme = useCallback(\n (mode: \"light\" | \"dark\"): ThemeConfig =>\n resolveThemeTokens(mode, resolvedThemeState),\n [resolvedThemeState],\n );\n\n const insertStyles = useCallback(() => {\n if (resolvedThemeState.cssContent) {\n insertInlineStylesIntoDOM(resolvedThemeState.cssContent);\n return;\n }\n\n if (resolvedThemeState.cssUrl) {\n insertStylesIntoDOM(resolvedThemeState.cssUrl);\n }\n }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);\n\n return { isLoading: state.status === \"loading\", theme, insertStyles };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/buildCdnUrls.ts","../src/fetchReleaseFromApi.ts","../src/fetchThemeAssets.ts","../src/insertStylesIntoDOM.ts","../src/useThemeOps.ts"],"names":["themeLight","themeDark","appendCacheBuster","useReducer","useRef","useEffect","useCallback"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { BuildCdnUrlsOptions, CdnUrls } from \"./types\";\n\nconst CDN_BASE_URL = \"https://theme-ops.s3.sa-east-1.amazonaws.com\";\n\nfunction buildBasePath(organizationId: string, appId?: string): string {\n return appId ? `${organizationId}/${appId}` : organizationId;\n}\n\nexport function buildCdnUrls({\n organizationId,\n appId,\n}: BuildCdnUrlsOptions): CdnUrls {\n const assetPath = buildBasePath(organizationId, appId);\n\n return {\n theme: `${CDN_BASE_URL}/${assetPath}/theme.json`,\n themeFallback: `${CDN_BASE_URL}/${assetPath}/theme-fallback.json`,\n css: `${CDN_BASE_URL}/${assetPath}/css.css`,\n };\n}\n","import type { ApiReleaseResponse, ThemeState } from \"./types\";\n\nfunction buildReleaseUrl(apiUrl: string, releaseId: string): string {\n const base = apiUrl.replace(/\\/+$/, \"\");\n return `${base}/sdk/releases/${releaseId}`;\n}\n\nexport async function fetchReleaseFromApi(\n apiUrl: string,\n releaseId: string,\n): Promise<ThemeState> {\n const url = buildReleaseUrl(apiUrl, releaseId);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch release: ${response.status}`);\n }\n\n const data = (await response.json()) as ApiReleaseResponse;\n\n return {\n themeLight: data.themeLight,\n themeDark: data.themeDark,\n cssUrl: null,\n cssContent: data.css || null,\n };\n}\n","import type { CdnUrls, ThemeAssets, ThemeJson, ThemeTokens } from \"./types\";\n\nfunction appendCacheBuster(url: string): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}_t=${Date.now()}`;\n}\n\nasync function fetchJson<T>(url: string): Promise<T | null> {\n try {\n const response = await fetch(appendCacheBuster(url));\n if (!response.ok) return null;\n\n return (await response.json()) as T;\n } catch {\n return null;\n }\n}\n\nfunction extractThemesFromJson(json: ThemeJson | null): {\n themeLight: ThemeTokens | null;\n themeDark: ThemeTokens | null;\n} {\n return {\n themeLight: json?.light ?? null,\n themeDark: json?.dark ?? null,\n };\n}\n\nfunction isThemeJsonValid(json: ThemeJson | null): boolean {\n return json !== null && (json.light !== undefined || json.dark !== undefined);\n}\n\nexport async function fetchThemeAssets(urls: CdnUrls): Promise<ThemeAssets> {\n const activeJson = await fetchJson<ThemeJson>(urls.theme);\n const cacheBustedCssUrl = appendCacheBuster(urls.css);\n\n if (isThemeJsonValid(activeJson)) {\n const { themeLight, themeDark } = extractThemesFromJson(activeJson);\n return { themeLight, themeDark, cssUrl: cacheBustedCssUrl, usingFallback: false };\n }\n\n const fallbackJson = await fetchJson<ThemeJson>(urls.themeFallback);\n const { themeLight, themeDark } = extractThemesFromJson(fallbackJson);\n\n return {\n themeLight,\n themeDark,\n cssUrl: cacheBustedCssUrl,\n usingFallback: true,\n };\n}\n","const LINK_ELEMENT_ID = \"theme-ops-css\";\nconst STYLE_ELEMENT_ID = \"theme-ops-css-inline\";\n\nfunction appendCacheBuster(url: string): string {\n const baseUrl = url.replace(/[?&]_t=\\d+/, \"\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}_t=${Date.now()}`;\n}\n\nfunction findExistingLinkElement(): HTMLLinkElement | null {\n return document.getElementById(LINK_ELEMENT_ID) as HTMLLinkElement | null;\n}\n\nfunction findExistingInlineStyle(): HTMLStyleElement | null {\n return document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n}\n\nfunction createLinkElement(href: string): HTMLLinkElement {\n const link = document.createElement(\"link\");\n link.id = LINK_ELEMENT_ID;\n link.rel = \"stylesheet\";\n link.href = href;\n return link;\n}\n\nfunction removeElement(id: string): void {\n document.getElementById(id)?.remove();\n}\n\nexport function insertStylesIntoDOM(cssUrl: string): void {\n removeElement(STYLE_ELEMENT_ID);\n\n const freshUrl = appendCacheBuster(cssUrl);\n const existing = findExistingLinkElement();\n\n if (existing) {\n existing.href = freshUrl;\n return;\n }\n\n const link = createLinkElement(freshUrl);\n document.head.appendChild(link);\n}\n\nexport function insertInlineStylesIntoDOM(cssContent: string): void {\n removeElement(LINK_ELEMENT_ID);\n\n const existing = findExistingInlineStyle();\n\n if (existing) {\n existing.textContent = cssContent;\n return;\n }\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = cssContent;\n document.head.appendChild(style);\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\n\nimport { buildCdnUrls } from \"./buildCdnUrls\";\nimport { fetchReleaseFromApi } from \"./fetchReleaseFromApi\";\nimport { fetchThemeAssets } from \"./fetchThemeAssets\";\nimport {\n insertInlineStylesIntoDOM,\n insertStylesIntoDOM,\n} from \"./insertStylesIntoDOM\";\nimport type {\n ThemeConfig,\n ThemeState,\n UseThemeOpsOptions,\n UseThemeOpsResult,\n} from \"./types\";\n\ntype HookState =\n | { status: \"loading\" }\n | { status: \"ready\"; themeState: ThemeState };\n\ntype HookAction =\n | { type: \"FETCH_START\" }\n | { type: \"FETCH_SUCCESS\"; payload: ThemeState };\n\nfunction hookReducer(_state: HookState, action: HookAction): HookState {\n switch (action.type) {\n case \"FETCH_START\":\n return { status: \"loading\" };\n case \"FETCH_SUCCESS\":\n return { status: \"ready\", themeState: action.payload };\n }\n}\n\nconst EMPTY_THEME_STATE: ThemeState = {\n themeLight: null,\n themeDark: null,\n cssUrl: null,\n cssContent: null,\n};\n\nfunction resolveThemeTokens(\n mode: \"light\" | \"dark\",\n themeState: ThemeState,\n): ThemeConfig {\n const tokens = mode === \"dark\" ? themeState.themeDark : themeState.themeLight;\n if (!tokens) return {};\n\n return tokens as ThemeConfig;\n}\n\nfunction isReleasePreview(\n options: UseThemeOpsOptions,\n): options is UseThemeOpsOptions & { releaseId: string; apiUrl: string } {\n return Boolean(options.releaseId && options.apiUrl);\n}\n\nexport function useThemeOps(options: UseThemeOpsOptions): UseThemeOpsResult {\n const { organizationId, appId, releaseId, apiUrl } = options;\n const [state, dispatch] = useReducer(hookReducer, { status: \"loading\" });\n\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n dispatch({ type: \"FETCH_START\" });\n\n const fetchPromise = isReleasePreview(options)\n ? fetchReleaseFromApi(options.apiUrl, options.releaseId)\n : fetchThemeAssets(buildCdnUrls({ organizationId, appId })).then(\n (assets) => ({\n themeLight: assets.themeLight,\n themeDark: assets.themeDark,\n cssUrl: assets.cssUrl,\n cssContent: null,\n }),\n );\n\n fetchPromise.then((payload) => {\n if (!isMountedRef.current) return;\n\n dispatch({ type: \"FETCH_SUCCESS\", payload });\n });\n\n return () => {\n isMountedRef.current = false;\n };\n }, [organizationId, appId, releaseId, apiUrl]);\n\n const resolvedThemeState =\n state.status === \"ready\" ? state.themeState : EMPTY_THEME_STATE;\n\n const getTheme = useCallback(\n (mode: \"light\" | \"dark\"): ThemeConfig =>\n resolveThemeTokens(mode, resolvedThemeState),\n [resolvedThemeState],\n );\n\n const insertStyles = useCallback(() => {\n if (resolvedThemeState.cssContent) {\n insertInlineStylesIntoDOM(resolvedThemeState.cssContent);\n return;\n }\n\n if (resolvedThemeState.cssUrl) {\n insertStylesIntoDOM(resolvedThemeState.cssUrl);\n }\n }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);\n\n return { isLoading: state.status === \"loading\", getTheme, insertStyles };\n}\n"]}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -174,7 +174,7 @@ function useThemeOps(options) {
|
|
|
174
174
|
};
|
|
175
175
|
}, [organizationId, appId, releaseId, apiUrl]);
|
|
176
176
|
const resolvedThemeState = state.status === "ready" ? state.themeState : EMPTY_THEME_STATE;
|
|
177
|
-
const
|
|
177
|
+
const getTheme = useCallback(
|
|
178
178
|
(mode) => resolveThemeTokens(mode, resolvedThemeState),
|
|
179
179
|
[resolvedThemeState]
|
|
180
180
|
);
|
|
@@ -187,7 +187,7 @@ function useThemeOps(options) {
|
|
|
187
187
|
insertStylesIntoDOM(resolvedThemeState.cssUrl);
|
|
188
188
|
}
|
|
189
189
|
}, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);
|
|
190
|
-
return { isLoading: state.status === "loading",
|
|
190
|
+
return { isLoading: state.status === "loading", getTheme, insertStyles };
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
export { useThemeOps };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/buildCdnUrls.ts","../src/fetchReleaseFromApi.ts","../src/fetchThemeAssets.ts","../src/insertStylesIntoDOM.ts","../src/useThemeOps.ts"],"names":["themeLight","themeDark","appendCacheBuster"],"mappings":"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","file":"index.js","sourcesContent":["import type { BuildCdnUrlsOptions, CdnUrls } from \"./types\";\n\nconst CDN_BASE_URL = \"https://theme-ops.s3.sa-east-1.amazonaws.com\";\n\nfunction buildBasePath(organizationId: string, appId?: string): string {\n return appId ? `${organizationId}/${appId}` : organizationId;\n}\n\nexport function buildCdnUrls({\n organizationId,\n appId,\n}: BuildCdnUrlsOptions): CdnUrls {\n const assetPath = buildBasePath(organizationId, appId);\n\n return {\n theme: `${CDN_BASE_URL}/${assetPath}/theme.json`,\n themeFallback: `${CDN_BASE_URL}/${assetPath}/theme-fallback.json`,\n css: `${CDN_BASE_URL}/${assetPath}/css.css`,\n };\n}\n","import type { ApiReleaseResponse, ThemeState } from \"./types\";\n\nfunction buildReleaseUrl(apiUrl: string, releaseId: string): string {\n const base = apiUrl.replace(/\\/+$/, \"\");\n return `${base}/sdk/releases/${releaseId}`;\n}\n\nexport async function fetchReleaseFromApi(\n apiUrl: string,\n releaseId: string,\n): Promise<ThemeState> {\n const url = buildReleaseUrl(apiUrl, releaseId);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch release: ${response.status}`);\n }\n\n const data = (await response.json()) as ApiReleaseResponse;\n\n return {\n themeLight: data.themeLight,\n themeDark: data.themeDark,\n cssUrl: null,\n cssContent: data.css || null,\n };\n}\n","import type { CdnUrls, ThemeAssets, ThemeJson, ThemeTokens } from \"./types\";\n\nfunction appendCacheBuster(url: string): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}_t=${Date.now()}`;\n}\n\nasync function fetchJson<T>(url: string): Promise<T | null> {\n try {\n const response = await fetch(appendCacheBuster(url));\n if (!response.ok) return null;\n\n return (await response.json()) as T;\n } catch {\n return null;\n }\n}\n\nfunction extractThemesFromJson(json: ThemeJson | null): {\n themeLight: ThemeTokens | null;\n themeDark: ThemeTokens | null;\n} {\n return {\n themeLight: json?.light ?? null,\n themeDark: json?.dark ?? null,\n };\n}\n\nfunction isThemeJsonValid(json: ThemeJson | null): boolean {\n return json !== null && (json.light !== undefined || json.dark !== undefined);\n}\n\nexport async function fetchThemeAssets(urls: CdnUrls): Promise<ThemeAssets> {\n const activeJson = await fetchJson<ThemeJson>(urls.theme);\n const cacheBustedCssUrl = appendCacheBuster(urls.css);\n\n if (isThemeJsonValid(activeJson)) {\n const { themeLight, themeDark } = extractThemesFromJson(activeJson);\n return { themeLight, themeDark, cssUrl: cacheBustedCssUrl, usingFallback: false };\n }\n\n const fallbackJson = await fetchJson<ThemeJson>(urls.themeFallback);\n const { themeLight, themeDark } = extractThemesFromJson(fallbackJson);\n\n return {\n themeLight,\n themeDark,\n cssUrl: cacheBustedCssUrl,\n usingFallback: true,\n };\n}\n","const LINK_ELEMENT_ID = \"theme-ops-css\";\nconst STYLE_ELEMENT_ID = \"theme-ops-css-inline\";\n\nfunction appendCacheBuster(url: string): string {\n const baseUrl = url.replace(/[?&]_t=\\d+/, \"\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}_t=${Date.now()}`;\n}\n\nfunction findExistingLinkElement(): HTMLLinkElement | null {\n return document.getElementById(LINK_ELEMENT_ID) as HTMLLinkElement | null;\n}\n\nfunction findExistingInlineStyle(): HTMLStyleElement | null {\n return document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n}\n\nfunction createLinkElement(href: string): HTMLLinkElement {\n const link = document.createElement(\"link\");\n link.id = LINK_ELEMENT_ID;\n link.rel = \"stylesheet\";\n link.href = href;\n return link;\n}\n\nfunction removeElement(id: string): void {\n document.getElementById(id)?.remove();\n}\n\nexport function insertStylesIntoDOM(cssUrl: string): void {\n removeElement(STYLE_ELEMENT_ID);\n\n const freshUrl = appendCacheBuster(cssUrl);\n const existing = findExistingLinkElement();\n\n if (existing) {\n existing.href = freshUrl;\n return;\n }\n\n const link = createLinkElement(freshUrl);\n document.head.appendChild(link);\n}\n\nexport function insertInlineStylesIntoDOM(cssContent: string): void {\n removeElement(LINK_ELEMENT_ID);\n\n const existing = findExistingInlineStyle();\n\n if (existing) {\n existing.textContent = cssContent;\n return;\n }\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = cssContent;\n document.head.appendChild(style);\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\n\nimport { buildCdnUrls } from \"./buildCdnUrls\";\nimport { fetchReleaseFromApi } from \"./fetchReleaseFromApi\";\nimport { fetchThemeAssets } from \"./fetchThemeAssets\";\nimport {\n insertInlineStylesIntoDOM,\n insertStylesIntoDOM,\n} from \"./insertStylesIntoDOM\";\nimport type {\n ThemeConfig,\n ThemeState,\n UseThemeOpsOptions,\n UseThemeOpsResult,\n} from \"./types\";\n\ntype HookState =\n | { status: \"loading\" }\n | { status: \"ready\"; themeState: ThemeState };\n\ntype HookAction =\n | { type: \"FETCH_START\" }\n | { type: \"FETCH_SUCCESS\"; payload: ThemeState };\n\nfunction hookReducer(_state: HookState, action: HookAction): HookState {\n switch (action.type) {\n case \"FETCH_START\":\n return { status: \"loading\" };\n case \"FETCH_SUCCESS\":\n return { status: \"ready\", themeState: action.payload };\n }\n}\n\nconst EMPTY_THEME_STATE: ThemeState = {\n themeLight: null,\n themeDark: null,\n cssUrl: null,\n cssContent: null,\n};\n\nfunction resolveThemeTokens(\n mode: \"light\" | \"dark\",\n themeState: ThemeState,\n): ThemeConfig {\n const tokens = mode === \"dark\" ? themeState.themeDark : themeState.themeLight;\n if (!tokens) return {};\n\n return tokens as ThemeConfig;\n}\n\nfunction isReleasePreview(\n options: UseThemeOpsOptions,\n): options is UseThemeOpsOptions & { releaseId: string; apiUrl: string } {\n return Boolean(options.releaseId && options.apiUrl);\n}\n\nexport function useThemeOps(options: UseThemeOpsOptions): UseThemeOpsResult {\n const { organizationId, appId, releaseId, apiUrl } = options;\n const [state, dispatch] = useReducer(hookReducer, { status: \"loading\" });\n\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n dispatch({ type: \"FETCH_START\" });\n\n const fetchPromise = isReleasePreview(options)\n ? fetchReleaseFromApi(options.apiUrl, options.releaseId)\n : fetchThemeAssets(buildCdnUrls({ organizationId, appId })).then(\n (assets) => ({\n themeLight: assets.themeLight,\n themeDark: assets.themeDark,\n cssUrl: assets.cssUrl,\n cssContent: null,\n }),\n );\n\n fetchPromise.then((payload) => {\n if (!isMountedRef.current) return;\n\n dispatch({ type: \"FETCH_SUCCESS\", payload });\n });\n\n return () => {\n isMountedRef.current = false;\n };\n }, [organizationId, appId, releaseId, apiUrl]);\n\n const resolvedThemeState =\n state.status === \"ready\" ? state.themeState : EMPTY_THEME_STATE;\n\n const theme = useCallback(\n (mode: \"light\" | \"dark\"): ThemeConfig =>\n resolveThemeTokens(mode, resolvedThemeState),\n [resolvedThemeState],\n );\n\n const insertStyles = useCallback(() => {\n if (resolvedThemeState.cssContent) {\n insertInlineStylesIntoDOM(resolvedThemeState.cssContent);\n return;\n }\n\n if (resolvedThemeState.cssUrl) {\n insertStylesIntoDOM(resolvedThemeState.cssUrl);\n }\n }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);\n\n return { isLoading: state.status === \"loading\", theme, insertStyles };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/buildCdnUrls.ts","../src/fetchReleaseFromApi.ts","../src/fetchThemeAssets.ts","../src/insertStylesIntoDOM.ts","../src/useThemeOps.ts"],"names":["themeLight","themeDark","appendCacheBuster"],"mappings":";;;;;AAEA,IAAM,YAAA,GAAe,8CAAA;AAErB,SAAS,aAAA,CAAc,gBAAwB,KAAA,EAAwB;AACrE,EAAA,OAAO,KAAA,GAAQ,CAAA,EAAG,cAAc,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,GAAK,cAAA;AAChD;AAEO,SAAS,YAAA,CAAa;AAAA,EAC3B,cAAA;AAAA,EACA;AACF,CAAA,EAAiC;AAC/B,EAAA,MAAM,SAAA,GAAY,aAAA,CAAc,cAAA,EAAgB,KAAK,CAAA;AAErD,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,SAAS,CAAA,WAAA,CAAA;AAAA,IACnC,aAAA,EAAe,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,SAAS,CAAA,oBAAA,CAAA;AAAA,IAC3C,GAAA,EAAK,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,SAAS,CAAA,QAAA;AAAA,GACnC;AACF;;;ACjBA,SAAS,eAAA,CAAgB,QAAgB,SAAA,EAA2B;AAClE,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AACtC,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,cAAA,EAAiB,SAAS,CAAA,CAAA;AAC1C;AAEA,eAAsB,mBAAA,CACpB,QACA,SAAA,EACqB;AACrB,EAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,MAAA,EAAQ,SAAS,CAAA;AAE7C,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAG,CAAA;AAEhC,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,EAC/D;AAEA,EAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAElC,EAAA,OAAO;AAAA,IACL,YAAY,IAAA,CAAK,UAAA;AAAA,IACjB,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,MAAA,EAAQ,IAAA;AAAA,IACR,UAAA,EAAY,KAAK,GAAA,IAAO;AAAA,GAC1B;AACF;;;ACzBA,SAAS,kBAAkB,GAAA,EAAqB;AAC9C,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,QAAA,CAAS,GAAG,IAAI,GAAA,GAAM,GAAA;AAC5C,EAAA,OAAO,GAAG,GAAG,CAAA,EAAG,SAAS,CAAA,GAAA,EAAM,IAAA,CAAK,KAAK,CAAA,CAAA;AAC3C;AAEA,eAAe,UAAa,GAAA,EAAgC;AAC1D,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,iBAAA,CAAkB,GAAG,CAAC,CAAA;AACnD,IAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,OAAO,IAAA;AAEzB,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,sBAAsB,IAAA,EAG7B;AACA,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,MAAM,KAAA,IAAS,IAAA;AAAA,IAC3B,SAAA,EAAW,MAAM,IAAA,IAAQ;AAAA,GAC3B;AACF;AAEA,SAAS,iBAAiB,IAAA,EAAiC;AACzD,EAAA,OAAO,SAAS,IAAA,KAAS,IAAA,CAAK,KAAA,KAAU,MAAA,IAAa,KAAK,IAAA,KAAS,MAAA,CAAA;AACrE;AAEA,eAAsB,iBAAiB,IAAA,EAAqC;AAC1E,EAAA,MAAM,UAAA,GAAa,MAAM,SAAA,CAAqB,IAAA,CAAK,KAAK,CAAA;AACxD,EAAA,MAAM,iBAAA,GAAoB,iBAAA,CAAkB,IAAA,CAAK,GAAG,CAAA;AAEpD,EAAA,IAAI,gBAAA,CAAiB,UAAU,CAAA,EAAG;AAChC,IAAA,MAAM,EAAE,UAAA,EAAAA,WAAAA,EAAY,WAAAC,UAAAA,EAAU,GAAI,sBAAsB,UAAU,CAAA;AAClE,IAAA,OAAO,EAAE,YAAAD,WAAAA,EAAY,SAAA,EAAAC,YAAW,MAAA,EAAQ,iBAAA,EAAmB,eAAe,KAAA,EAAM;AAAA,EAClF;AAEA,EAAA,MAAM,YAAA,GAAe,MAAM,SAAA,CAAqB,IAAA,CAAK,aAAa,CAAA;AAClE,EAAA,MAAM,EAAE,UAAA,EAAY,SAAA,EAAU,GAAI,sBAAsB,YAAY,CAAA;AAEpE,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA,EAAQ,iBAAA;AAAA,IACR,aAAA,EAAe;AAAA,GACjB;AACF;;;AClDA,IAAM,eAAA,GAAkB,eAAA;AACxB,IAAM,gBAAA,GAAmB,sBAAA;AAEzB,SAASC,mBAAkB,GAAA,EAAqB;AAC9C,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA;AAC5C,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,QAAA,CAAS,GAAG,IAAI,GAAA,GAAM,GAAA;AAChD,EAAA,OAAO,GAAG,OAAO,CAAA,EAAG,SAAS,CAAA,GAAA,EAAM,IAAA,CAAK,KAAK,CAAA,CAAA;AAC/C;AAEA,SAAS,uBAAA,GAAkD;AACzD,EAAA,OAAO,QAAA,CAAS,eAAe,eAAe,CAAA;AAChD;AAEA,SAAS,uBAAA,GAAmD;AAC1D,EAAA,OAAO,QAAA,CAAS,eAAe,gBAAgB,CAAA;AACjD;AAEA,SAAS,kBAAkB,IAAA,EAA+B;AACxD,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AAC1C,EAAA,IAAA,CAAK,EAAA,GAAK,eAAA;AACV,EAAA,IAAA,CAAK,GAAA,GAAM,YAAA;AACX,EAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,cAAc,EAAA,EAAkB;AACvC,EAAA,QAAA,CAAS,cAAA,CAAe,EAAE,CAAA,EAAG,MAAA,EAAO;AACtC;AAEO,SAAS,oBAAoB,MAAA,EAAsB;AACxD,EAAA,aAAA,CAAc,gBAAgB,CAAA;AAE9B,EAAA,MAAM,QAAA,GAAWA,mBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,WAAW,uBAAA,EAAwB;AAEzC,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,QAAA,CAAS,IAAA,GAAO,QAAA;AAChB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,IAAA,GAAO,kBAAkB,QAAQ,CAAA;AACvC,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,IAAI,CAAA;AAChC;AAEO,SAAS,0BAA0B,UAAA,EAA0B;AAClE,EAAA,aAAA,CAAc,eAAe,CAAA;AAE7B,EAAA,MAAM,WAAW,uBAAA,EAAwB;AAEzC,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,QAAA,CAAS,WAAA,GAAc,UAAA;AACvB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AAC5C,EAAA,KAAA,CAAM,EAAA,GAAK,gBAAA;AACX,EAAA,KAAA,CAAM,WAAA,GAAc,UAAA;AACpB,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,KAAK,CAAA;AACjC;;;AClCA,SAAS,WAAA,CAAY,QAAmB,MAAA,EAA+B;AACrE,EAAA,QAAQ,OAAO,IAAA;AAAM,IACnB,KAAK,aAAA;AACH,MAAA,OAAO,EAAE,QAAQ,SAAA,EAAU;AAAA,IAC7B,KAAK,eAAA;AACH,MAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,UAAA,EAAY,OAAO,OAAA,EAAQ;AAAA;AAE3D;AAEA,IAAM,iBAAA,GAAgC;AAAA,EACpC,UAAA,EAAY,IAAA;AAAA,EACZ,SAAA,EAAW,IAAA;AAAA,EACX,MAAA,EAAQ,IAAA;AAAA,EACR,UAAA,EAAY;AACd,CAAA;AAEA,SAAS,kBAAA,CACP,MACA,UAAA,EACa;AACb,EAAA,MAAM,MAAA,GAAS,IAAA,KAAS,MAAA,GAAS,UAAA,CAAW,YAAY,UAAA,CAAW,UAAA;AACnE,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,iBACP,OAAA,EACuE;AACvE,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,SAAA,IAAa,OAAA,CAAQ,MAAM,CAAA;AACpD;AAEO,SAAS,YAAY,OAAA,EAAgD;AAC1E,EAAA,MAAM,EAAE,cAAA,EAAgB,KAAA,EAAO,SAAA,EAAW,QAAO,GAAI,OAAA;AACrD,EAAA,MAAM,CAAC,OAAO,QAAQ,CAAA,GAAI,WAAW,WAAA,EAAa,EAAE,MAAA,EAAQ,SAAA,EAAW,CAAA;AAEvE,EAAA,MAAM,YAAA,GAAe,OAAO,IAAI,CAAA;AAEhC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AAEvB,IAAA,QAAA,CAAS,EAAE,IAAA,EAAM,aAAA,EAAe,CAAA;AAEhC,IAAA,MAAM,eAAe,gBAAA,CAAiB,OAAO,CAAA,GACzC,mBAAA,CAAoB,QAAQ,MAAA,EAAQ,OAAA,CAAQ,SAAS,CAAA,GACrD,iBAAiB,YAAA,CAAa,EAAE,gBAAgB,KAAA,EAAO,CAAC,CAAA,CAAE,IAAA;AAAA,MACxD,CAAC,MAAA,MAAY;AAAA,QACX,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,UAAA,EAAY;AAAA,OACd;AAAA,KACF;AAEJ,IAAA,YAAA,CAAa,IAAA,CAAK,CAAC,OAAA,KAAY;AAC7B,MAAA,IAAI,CAAC,aAAa,OAAA,EAAS;AAE3B,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,eAAA,EAAiB,OAAA,EAAS,CAAA;AAAA,IAC7C,CAAC,CAAA;AAED,IAAA,OAAO,MAAM;AACX,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AAAA,IACzB,CAAA;AAAA,EACF,GAAG,CAAC,cAAA,EAAgB,KAAA,EAAO,SAAA,EAAW,MAAM,CAAC,CAAA;AAE7C,EAAA,MAAM,kBAAA,GACJ,KAAA,CAAM,MAAA,KAAW,OAAA,GAAU,MAAM,UAAA,GAAa,iBAAA;AAEhD,EAAA,MAAM,QAAA,GAAW,WAAA;AAAA,IACf,CAAC,IAAA,KACC,kBAAA,CAAmB,IAAA,EAAM,kBAAkB,CAAA;AAAA,IAC7C,CAAC,kBAAkB;AAAA,GACrB;AAEA,EAAA,MAAM,YAAA,GAAe,YAAY,MAAM;AACrC,IAAA,IAAI,mBAAmB,UAAA,EAAY;AACjC,MAAA,yBAAA,CAA0B,mBAAmB,UAAU,CAAA;AACvD,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,mBAAmB,MAAA,EAAQ;AAC7B,MAAA,mBAAA,CAAoB,mBAAmB,MAAM,CAAA;AAAA,IAC/C;AAAA,EACF,GAAG,CAAC,kBAAA,CAAmB,MAAA,EAAQ,kBAAA,CAAmB,UAAU,CAAC,CAAA;AAE7D,EAAA,OAAO,EAAE,SAAA,EAAW,KAAA,CAAM,MAAA,KAAW,SAAA,EAAW,UAAU,YAAA,EAAa;AACzE","file":"index.js","sourcesContent":["import type { BuildCdnUrlsOptions, CdnUrls } from \"./types\";\n\nconst CDN_BASE_URL = \"https://theme-ops.s3.sa-east-1.amazonaws.com\";\n\nfunction buildBasePath(organizationId: string, appId?: string): string {\n return appId ? `${organizationId}/${appId}` : organizationId;\n}\n\nexport function buildCdnUrls({\n organizationId,\n appId,\n}: BuildCdnUrlsOptions): CdnUrls {\n const assetPath = buildBasePath(organizationId, appId);\n\n return {\n theme: `${CDN_BASE_URL}/${assetPath}/theme.json`,\n themeFallback: `${CDN_BASE_URL}/${assetPath}/theme-fallback.json`,\n css: `${CDN_BASE_URL}/${assetPath}/css.css`,\n };\n}\n","import type { ApiReleaseResponse, ThemeState } from \"./types\";\n\nfunction buildReleaseUrl(apiUrl: string, releaseId: string): string {\n const base = apiUrl.replace(/\\/+$/, \"\");\n return `${base}/sdk/releases/${releaseId}`;\n}\n\nexport async function fetchReleaseFromApi(\n apiUrl: string,\n releaseId: string,\n): Promise<ThemeState> {\n const url = buildReleaseUrl(apiUrl, releaseId);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch release: ${response.status}`);\n }\n\n const data = (await response.json()) as ApiReleaseResponse;\n\n return {\n themeLight: data.themeLight,\n themeDark: data.themeDark,\n cssUrl: null,\n cssContent: data.css || null,\n };\n}\n","import type { CdnUrls, ThemeAssets, ThemeJson, ThemeTokens } from \"./types\";\n\nfunction appendCacheBuster(url: string): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}_t=${Date.now()}`;\n}\n\nasync function fetchJson<T>(url: string): Promise<T | null> {\n try {\n const response = await fetch(appendCacheBuster(url));\n if (!response.ok) return null;\n\n return (await response.json()) as T;\n } catch {\n return null;\n }\n}\n\nfunction extractThemesFromJson(json: ThemeJson | null): {\n themeLight: ThemeTokens | null;\n themeDark: ThemeTokens | null;\n} {\n return {\n themeLight: json?.light ?? null,\n themeDark: json?.dark ?? null,\n };\n}\n\nfunction isThemeJsonValid(json: ThemeJson | null): boolean {\n return json !== null && (json.light !== undefined || json.dark !== undefined);\n}\n\nexport async function fetchThemeAssets(urls: CdnUrls): Promise<ThemeAssets> {\n const activeJson = await fetchJson<ThemeJson>(urls.theme);\n const cacheBustedCssUrl = appendCacheBuster(urls.css);\n\n if (isThemeJsonValid(activeJson)) {\n const { themeLight, themeDark } = extractThemesFromJson(activeJson);\n return { themeLight, themeDark, cssUrl: cacheBustedCssUrl, usingFallback: false };\n }\n\n const fallbackJson = await fetchJson<ThemeJson>(urls.themeFallback);\n const { themeLight, themeDark } = extractThemesFromJson(fallbackJson);\n\n return {\n themeLight,\n themeDark,\n cssUrl: cacheBustedCssUrl,\n usingFallback: true,\n };\n}\n","const LINK_ELEMENT_ID = \"theme-ops-css\";\nconst STYLE_ELEMENT_ID = \"theme-ops-css-inline\";\n\nfunction appendCacheBuster(url: string): string {\n const baseUrl = url.replace(/[?&]_t=\\d+/, \"\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}_t=${Date.now()}`;\n}\n\nfunction findExistingLinkElement(): HTMLLinkElement | null {\n return document.getElementById(LINK_ELEMENT_ID) as HTMLLinkElement | null;\n}\n\nfunction findExistingInlineStyle(): HTMLStyleElement | null {\n return document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n}\n\nfunction createLinkElement(href: string): HTMLLinkElement {\n const link = document.createElement(\"link\");\n link.id = LINK_ELEMENT_ID;\n link.rel = \"stylesheet\";\n link.href = href;\n return link;\n}\n\nfunction removeElement(id: string): void {\n document.getElementById(id)?.remove();\n}\n\nexport function insertStylesIntoDOM(cssUrl: string): void {\n removeElement(STYLE_ELEMENT_ID);\n\n const freshUrl = appendCacheBuster(cssUrl);\n const existing = findExistingLinkElement();\n\n if (existing) {\n existing.href = freshUrl;\n return;\n }\n\n const link = createLinkElement(freshUrl);\n document.head.appendChild(link);\n}\n\nexport function insertInlineStylesIntoDOM(cssContent: string): void {\n removeElement(LINK_ELEMENT_ID);\n\n const existing = findExistingInlineStyle();\n\n if (existing) {\n existing.textContent = cssContent;\n return;\n }\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = cssContent;\n document.head.appendChild(style);\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\n\nimport { buildCdnUrls } from \"./buildCdnUrls\";\nimport { fetchReleaseFromApi } from \"./fetchReleaseFromApi\";\nimport { fetchThemeAssets } from \"./fetchThemeAssets\";\nimport {\n insertInlineStylesIntoDOM,\n insertStylesIntoDOM,\n} from \"./insertStylesIntoDOM\";\nimport type {\n ThemeConfig,\n ThemeState,\n UseThemeOpsOptions,\n UseThemeOpsResult,\n} from \"./types\";\n\ntype HookState =\n | { status: \"loading\" }\n | { status: \"ready\"; themeState: ThemeState };\n\ntype HookAction =\n | { type: \"FETCH_START\" }\n | { type: \"FETCH_SUCCESS\"; payload: ThemeState };\n\nfunction hookReducer(_state: HookState, action: HookAction): HookState {\n switch (action.type) {\n case \"FETCH_START\":\n return { status: \"loading\" };\n case \"FETCH_SUCCESS\":\n return { status: \"ready\", themeState: action.payload };\n }\n}\n\nconst EMPTY_THEME_STATE: ThemeState = {\n themeLight: null,\n themeDark: null,\n cssUrl: null,\n cssContent: null,\n};\n\nfunction resolveThemeTokens(\n mode: \"light\" | \"dark\",\n themeState: ThemeState,\n): ThemeConfig {\n const tokens = mode === \"dark\" ? themeState.themeDark : themeState.themeLight;\n if (!tokens) return {};\n\n return tokens as ThemeConfig;\n}\n\nfunction isReleasePreview(\n options: UseThemeOpsOptions,\n): options is UseThemeOpsOptions & { releaseId: string; apiUrl: string } {\n return Boolean(options.releaseId && options.apiUrl);\n}\n\nexport function useThemeOps(options: UseThemeOpsOptions): UseThemeOpsResult {\n const { organizationId, appId, releaseId, apiUrl } = options;\n const [state, dispatch] = useReducer(hookReducer, { status: \"loading\" });\n\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n isMountedRef.current = true;\n\n dispatch({ type: \"FETCH_START\" });\n\n const fetchPromise = isReleasePreview(options)\n ? fetchReleaseFromApi(options.apiUrl, options.releaseId)\n : fetchThemeAssets(buildCdnUrls({ organizationId, appId })).then(\n (assets) => ({\n themeLight: assets.themeLight,\n themeDark: assets.themeDark,\n cssUrl: assets.cssUrl,\n cssContent: null,\n }),\n );\n\n fetchPromise.then((payload) => {\n if (!isMountedRef.current) return;\n\n dispatch({ type: \"FETCH_SUCCESS\", payload });\n });\n\n return () => {\n isMountedRef.current = false;\n };\n }, [organizationId, appId, releaseId, apiUrl]);\n\n const resolvedThemeState =\n state.status === \"ready\" ? state.themeState : EMPTY_THEME_STATE;\n\n const getTheme = useCallback(\n (mode: \"light\" | \"dark\"): ThemeConfig =>\n resolveThemeTokens(mode, resolvedThemeState),\n [resolvedThemeState],\n );\n\n const insertStyles = useCallback(() => {\n if (resolvedThemeState.cssContent) {\n insertInlineStylesIntoDOM(resolvedThemeState.cssContent);\n return;\n }\n\n if (resolvedThemeState.cssUrl) {\n insertStylesIntoDOM(resolvedThemeState.cssUrl);\n }\n }, [resolvedThemeState.cssUrl, resolvedThemeState.cssContent]);\n\n return { isLoading: state.status === \"loading\", getTheme, insertStyles };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theme-ops-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "React SDK for Theme Ops — fetch and apply themes from CDN",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -56,4 +56,4 @@
|
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public"
|
|
58
58
|
}
|
|
59
|
-
}
|
|
59
|
+
}
|