@codedartdev/coinsentry-sdk 0.1.0 → 0.1.1

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.
Files changed (44) hide show
  1. package/README.md +98 -1
  2. package/dist/brand/config.d.ts +35 -1
  3. package/dist/brand/config.d.ts.map +1 -1
  4. package/dist/brand/config.js +119 -15
  5. package/dist/brand/config.js.map +1 -1
  6. package/dist/brand/index.d.ts +2 -2
  7. package/dist/brand/index.d.ts.map +1 -1
  8. package/dist/brand/index.js +1 -1
  9. package/dist/brand/index.js.map +1 -1
  10. package/dist/brand/types.d.ts +31 -1
  11. package/dist/brand/types.d.ts.map +1 -1
  12. package/dist/brand/types.js.map +1 -1
  13. package/dist/client.d.ts +10 -4
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +49 -6
  16. package/dist/client.js.map +1 -1
  17. package/dist/errors.d.ts +1 -0
  18. package/dist/errors.d.ts.map +1 -1
  19. package/dist/errors.js +7 -0
  20. package/dist/errors.js.map +1 -1
  21. package/dist/http.d.ts +1 -1
  22. package/dist/http.d.ts.map +1 -1
  23. package/dist/http.js +38 -5
  24. package/dist/http.js.map +1 -1
  25. package/dist/index.d.ts +7 -5
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +3 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/market.d.ts +97 -0
  30. package/dist/market.d.ts.map +1 -0
  31. package/dist/market.js +264 -0
  32. package/dist/market.js.map +1 -0
  33. package/dist/products.d.ts +16 -2
  34. package/dist/products.d.ts.map +1 -1
  35. package/dist/products.js +70 -6
  36. package/dist/products.js.map +1 -1
  37. package/dist/realtime.d.ts +2 -0
  38. package/dist/realtime.d.ts.map +1 -1
  39. package/dist/realtime.js +3 -0
  40. package/dist/realtime.js.map +1 -1
  41. package/dist/types.d.ts +12 -9
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js.map +1 -1
  44. package/package.json +6 -1
package/README.md CHANGED
@@ -65,6 +65,42 @@ cs.locale.clearKyc();
65
65
  `locale.setKyc()` afeta apenas requests para `/api/v1/kyc*`. Isso preserva o
66
66
  comportamento da whitelabel atual sem colocar fallback de fluxo no browser.
67
67
 
68
+ ## Brand
69
+
70
+ `client.brand.getConfig()` consome o contrato publico `GET /api/brand/theme`.
71
+ Ele aceita `brandKey` e `etag`, normaliza o payload canonico e retorna metadata
72
+ de cache quando disponivel.
73
+
74
+ ```ts
75
+ const response = await cs.brand.getConfig({
76
+ brandKey: 'default',
77
+ etag: previousEtag,
78
+ });
79
+
80
+ if (!response.notModified && response.config) {
81
+ renderBrand(response.config);
82
+ }
83
+ ```
84
+
85
+ O subpath `@codedartdev/coinsentry-sdk/brand` contem helpers puros para aplicar
86
+ o contrato em qualquer framework:
87
+
88
+ ```ts
89
+ import {
90
+ buildBrandCss,
91
+ getBrandCssVariables,
92
+ normalizeBrandConfig,
93
+ } from '@codedartdev/coinsentry-sdk/brand';
94
+
95
+ const brand = normalizeBrandConfig(response.config);
96
+ const css = buildBrandCss(brand);
97
+ const darkVars = getBrandCssVariables(brand, 'dark');
98
+ ```
99
+
100
+ Os tipos cobrem fonte base, tipografia, logo textual/imagem, favicon claro e
101
+ escuro, tokens de mercado (`rising`/`downing`) e tokens opcionais de superficie,
102
+ texto e estado enviados pelo backend.
103
+
68
104
  ## Transporte HTTP
69
105
 
70
106
  `client.request<T>()` e o transporte headless oficial. Use-o para endpoints
@@ -177,6 +213,53 @@ const quote = await cs.otc.createQuote({
177
213
  Esses modulos continuam headless: nao exibem toast, nao redirecionam e nao
178
214
  conhecem componentes da whitelabel.
179
215
 
216
+ ### Market E Orderbook
217
+
218
+ O modulo `market` tambem expoe helpers puros para consumers que precisam de
219
+ orderbook realtime sem conhecer o formato interno de canais:
220
+
221
+ ```ts
222
+ import {
223
+ buildCreateOrderPayload,
224
+ getOrderbookChannel,
225
+ normalizeMarketSymbol,
226
+ normalizeOrderbookSnapshot,
227
+ } from '@codedartdev/coinsentry-sdk/market';
228
+
229
+ const symbol = normalizeMarketSymbol('btc-brl'); // BTC_BRL
230
+ const markets = await cs.market.listMarkets();
231
+ const ticker = await cs.market.getTicker(symbol);
232
+ const details = await cs.market.getMarketDetails(symbol);
233
+ const snapshot = await cs.market.getOrderbookSnapshot('BTC_USDT', 50);
234
+ const trades = await cs.market.getTrades('BTC_USDT', { limit: 50 });
235
+ const channel = getOrderbookChannel('BTC_USDT'); // orderbook.btc-usdt
236
+
237
+ await cs.market.createOrder(buildCreateOrderPayload({
238
+ symbol: 'BTC_USDT',
239
+ side: 'BUY',
240
+ type: 'LIMIT',
241
+ price: '67000',
242
+ quantity: '0.01',
243
+ }));
244
+ ```
245
+
246
+ O book publico e tratado como snapshot-only: o client deve carregar
247
+ `GET /api/v1/orderbook/{symbol}` e substituir o estado local em
248
+ `.orderbook.updated`. O SDK nao expoe diffs incrementais publicos porque o
249
+ backend atual nao publica sequencia nem delta canonico.
250
+
251
+ Endpoints publicos de mercado:
252
+
253
+ - `market.listMarkets()` -> `GET /api/v1/market`;
254
+ - `market.getTicker(symbol)` -> `GET /api/v1/ticker/{symbol}`;
255
+ - `market.getOrderbookSnapshot(symbol, depth?)` -> `GET /api/v1/orderbook/{symbol}`;
256
+ - `market.getTrades(symbol, { limit? })` -> `GET /api/v1/trades/{symbol}`.
257
+
258
+ `market.getMarketDetails(symbol)` e o agregado autenticado
259
+ `GET /api/v1/market/{symbol}` para saldos, ordens do usuario e enriquecimento
260
+ privado. `market.getMarket(symbol)` continua como alias por compatibilidade,
261
+ mas orderbook e trades publicos nao dependem desse agregado.
262
+
180
263
  ## KYC Headless
181
264
 
182
265
  ```ts
@@ -213,11 +296,16 @@ Guards KYC publicos:
213
296
  O SDK normaliza falhas em `CoinSentryApiError`:
214
297
 
215
298
  ```ts
216
- import { normalizeCoinSentryError } from '@codedartdev/coinsentry-sdk';
299
+ import {
300
+ isCoinSentryAbortError,
301
+ normalizeCoinSentryError,
302
+ } from '@codedartdev/coinsentry-sdk';
217
303
 
218
304
  try {
219
305
  await cs.kyc.getOverview();
220
306
  } catch (error) {
307
+ if (isCoinSentryAbortError(error)) return;
308
+
221
309
  const normalized = normalizeCoinSentryError(error);
222
310
  if (normalized.code === 'kyc_required') {
223
311
  openKyc();
@@ -241,6 +329,10 @@ Codigos estaveis:
241
329
  - `server_error`
242
330
  - `unknown_error`
243
331
 
332
+ Cancelamentos iniciados pelo caller via `request.signal` sao repropagados como
333
+ abort e nao chamam `onError`. Use `isCoinSentryAbortError(error)` para ignorar
334
+ esse caso. Timeout interno continua sendo falha de rede normalizada.
335
+
244
336
  ## Realtime
245
337
 
246
338
  `createCoinSentryRealtime(adapter)` define a interface publica. A implementacao
@@ -251,6 +343,11 @@ compativel.
251
343
  const realtime = createCoinSentryRealtime(adapter);
252
344
  realtime.connect();
253
345
  realtime.subscribeToEntity(entityUuid, 'balance.updated', onBalance);
346
+ realtime.subscribeStatus?.((status) => {
347
+ if (status === 'connected') {
348
+ // reancore snapshots locais se necessario
349
+ }
350
+ });
254
351
  ```
255
352
 
256
353
  O payload recomendado para saldo e `CoinSentryBalanceUpdate`:
@@ -1,4 +1,4 @@
1
- import type { BrandConfig, BackendBrandLogoType, BrandLogoType } from './types.js';
1
+ import type { BrandConfig, BackendBrandLogoType, BrandLogoType, BrandTypography } from './types.js';
2
2
  export type BrandMode = 'light' | 'dark';
3
3
  export interface BrandManifestIcon {
4
4
  src: string;
@@ -31,6 +31,9 @@ export declare function normalizeLogoDimension(value: string | number | null | u
31
31
  export declare function normalizeLogoLayout(layout: BrandConfig['brand']['logo']['layout'] | null | undefined): NormalizedLogoLayout;
32
32
  export declare function normalizeFontSans(value: string | null | undefined): string;
33
33
  export declare function fontSansToCssFamily(value: string | null | undefined): string;
34
+ export declare function normalizeFontBaseSize(value: string | null | undefined): string;
35
+ export declare function normalizeTypographyValue(value: string | null | undefined, fallback: string): string;
36
+ export declare function normalizeBrandTypography(value: BrandTypography | null | undefined): Required<BrandTypography>;
34
37
  export declare function normalizeBrandConfig(config: BrandConfig): BrandConfig;
35
38
  export declare function getLogoImageUrl(logo: BrandConfig['brand']['logo'], mode?: BrandMode): string | null;
36
39
  export declare function getLogoTextFontFamily(config: BrandConfig): string;
@@ -39,6 +42,18 @@ export declare function getLogoTextColors(config: BrandConfig, mode: BrandMode):
39
42
  accent?: string | null;
40
43
  };
41
44
  export declare function getBrandCssVariables(config: BrandConfig, mode: BrandMode): {
45
+ '--font-sans': string;
46
+ '--font-size-base': string;
47
+ '--font-size': string;
48
+ '--text-display': string;
49
+ '--text-title': string;
50
+ '--text-subtitle': string;
51
+ '--text-body': string;
52
+ '--text-label': string;
53
+ '--text-caption': string;
54
+ '--text-button': string;
55
+ '--text-code': string;
56
+ '--text-overline': string;
42
57
  '--radius': string;
43
58
  '--primary': string;
44
59
  '--primary-foreground': string;
@@ -52,8 +67,27 @@ export declare function getBrandCssVariables(config: BrandConfig, mode: BrandMod
52
67
  '--muted-foreground': string;
53
68
  '--accent': string;
54
69
  '--accent-foreground': string;
70
+ '--destructive': string;
71
+ '--destructive-foreground': string;
72
+ '--danger': string;
73
+ '--danger-foreground': string;
74
+ '--success': string;
75
+ '--success-foreground': string;
76
+ '--warning': string;
77
+ '--warning-foreground': string;
78
+ '--rising': string;
79
+ '--rising-foreground': string;
80
+ '--downing': string;
81
+ '--downing-foreground': string;
55
82
  '--border': string;
83
+ '--input': string;
56
84
  '--ring': string;
85
+ '--text-title-color': string;
86
+ '--text-subtitle-color': string;
87
+ '--text-primary': string;
88
+ '--text-secondary': string;
89
+ '--text-link': string;
90
+ '--text-button-color': string;
57
91
  '--sidebar': string;
58
92
  '--sidebar-foreground': string;
59
93
  '--sidebar-primary': string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/brand/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/brand/config.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,23 @@
1
1
  const FALLBACK_FAVICON = '/favicon.ico';
2
2
  const FALLBACK_FONT = 'Inter';
3
+ const FALLBACK_BASE_SIZE = '16px';
3
4
  const FALLBACK_LOGO_WIDTH = '160px';
4
5
  const FALLBACK_LOGO_HEIGHT = '40px';
5
6
  const SAFE_LOGO_KEYWORDS = new Set(['auto', 'fit-content']);
6
7
  const SAFE_LOGO_DIMENSION_PATTERN = /^(\d+(?:\.\d+)?)(px|rem|em|%|vw|vh)$/i;
8
+ const SAFE_BASE_SIZE_PATTERN = /^(\d+(?:\.\d+)?)px$/i;
9
+ const SAFE_REM_PATTERN = /^(\d+(?:\.\d+)?)rem$/i;
10
+ const DEFAULT_TYPOGRAPHY = {
11
+ display: '1.875rem',
12
+ title: '1.25rem',
13
+ subtitle: '1rem',
14
+ body: '0.875rem',
15
+ label: '0.75rem',
16
+ caption: '0.6875rem',
17
+ button: '0.875rem',
18
+ code: '0.8125rem',
19
+ overline: '0.625rem',
20
+ };
7
21
  export function normalizeLogoType(type) {
8
22
  return type === 'text' ? 'text' : 'image';
9
23
  }
@@ -53,6 +67,36 @@ function quoteFontFamily(name) {
53
67
  export function fontSansToCssFamily(value) {
54
68
  return quoteFontFamily(normalizeFontSans(value));
55
69
  }
70
+ export function normalizeFontBaseSize(value) {
71
+ const raw = value?.trim();
72
+ if (!raw)
73
+ return FALLBACK_BASE_SIZE;
74
+ const match = raw.match(SAFE_BASE_SIZE_PATTERN);
75
+ if (!match)
76
+ return FALLBACK_BASE_SIZE;
77
+ const amount = Number(match[1]);
78
+ return Number.isFinite(amount) && amount >= 8 && amount <= 24
79
+ ? `${match[1]}px`
80
+ : FALLBACK_BASE_SIZE;
81
+ }
82
+ export function normalizeTypographyValue(value, fallback) {
83
+ const raw = value?.trim();
84
+ if (!raw)
85
+ return fallback;
86
+ const match = raw.match(SAFE_REM_PATTERN);
87
+ if (!match)
88
+ return fallback;
89
+ const amount = Number(match[1]);
90
+ return Number.isFinite(amount) && amount >= 0.5 && amount <= 3
91
+ ? `${match[1]}rem`
92
+ : fallback;
93
+ }
94
+ export function normalizeBrandTypography(value) {
95
+ return Object.fromEntries(Object.entries(DEFAULT_TYPOGRAPHY).map(([token, fallback]) => [
96
+ token,
97
+ normalizeTypographyValue(value?.[token], fallback),
98
+ ]));
99
+ }
56
100
  export function normalizeBrandConfig(config) {
57
101
  const logo = config.brand.logo;
58
102
  const text = logo.text ?? { base: config.brand.name, accent: '' };
@@ -83,7 +127,9 @@ export function normalizeBrandConfig(config) {
83
127
  font: {
84
128
  ...config.theme.font,
85
129
  sans: normalizeFontSans(config.theme.font?.sans),
130
+ baseSize: normalizeFontBaseSize(config.theme.font?.baseSize),
86
131
  },
132
+ typography: normalizeBrandTypography(config.theme.typography),
87
133
  },
88
134
  };
89
135
  }
@@ -134,40 +180,94 @@ function hex2(n) {
134
180
  }
135
181
  function buildModeVars(colors, mode) {
136
182
  const isDark = mode === 'dark';
137
- const secondary = colorMixHex(colors.background, isDark ? '#ffffff' : '#000000', isDark ? 0.12 : 0.05);
138
- const muted = colorMixHex(colors.background, isDark ? '#ffffff' : '#888888', isDark ? 0.08 : 0.07);
139
- const accent = colorMixHex(colors.background, isDark ? '#ffffff' : '#000000', isDark ? 0.16 : 0.08);
140
- const border = hexToRgbaValue(colors.foreground, isDark ? 0.12 : 0.1);
141
- const mutedForeground = hexToRgbaValue(colors.foreground, isDark ? 0.68 : 0.62);
183
+ const secondary = colors.secondary ?? colorMixHex(colors.background, isDark ? '#ffffff' : '#000000', isDark ? 0.12 : 0.05);
184
+ const secondaryForeground = colors.secondaryForeground ?? colors.foreground;
185
+ const muted = colors.muted ?? colorMixHex(colors.background, isDark ? '#ffffff' : '#888888', isDark ? 0.08 : 0.07);
186
+ const mutedForeground = colors.mutedForeground ?? hexToRgbaValue(colors.foreground, isDark ? 0.68 : 0.62);
187
+ const accent = colors.secondary ?? colorMixHex(colors.background, isDark ? '#ffffff' : '#000000', isDark ? 0.16 : 0.08);
188
+ const border = colors.border ?? hexToRgbaValue(colors.foreground, isDark ? 0.12 : 0.1);
189
+ const danger = colors.danger ?? (isDark ? '#EF4444' : '#DC2626');
190
+ const dangerForeground = colors.dangerForeground ?? '#ffffff';
191
+ const success = colors.success ?? colors.rising ?? (isDark ? '#22C55E' : '#16A34A');
192
+ const successForeground = colors.successForeground ?? '#ffffff';
193
+ const warning = colors.warning ?? (isDark ? '#F59E0B' : '#D97706');
194
+ const warningForeground = colors.warningForeground ?? (isDark ? '#111827' : '#ffffff');
195
+ const rising = colors.rising ?? success;
196
+ const risingForeground = colors.risingForeground ?? successForeground;
197
+ const downing = colors.downing ?? danger;
198
+ const downingForeground = colors.downingForeground ?? dangerForeground;
199
+ const card = colors.card ?? colors.background;
200
+ const cardForeground = colors.cardForeground ?? colors.foreground;
201
+ const input = colors.input ?? border;
202
+ const ring = colors.ring ?? colors.primary;
203
+ const textTitle = colors.textTitle ?? colors.foreground;
204
+ const textSubtitle = colors.textSubtitle ?? mutedForeground;
205
+ const textPrimary = colors.textPrimary ?? colors.foreground;
206
+ const textSecondary = colors.textSecondary ?? mutedForeground;
207
+ const textLink = colors.textLink ?? colors.primary;
208
+ const textButton = colors.textButton ?? colors.primaryForeground;
142
209
  return {
143
210
  '--primary': colors.primary,
144
211
  '--primary-foreground': colors.primaryForeground,
145
212
  '--background': colors.background,
146
213
  '--foreground': colors.foreground,
147
- '--card': colors.background,
148
- '--card-foreground': colors.foreground,
214
+ '--card': card,
215
+ '--card-foreground': cardForeground,
149
216
  '--secondary': secondary,
150
- '--secondary-foreground': colors.foreground,
217
+ '--secondary-foreground': secondaryForeground,
151
218
  '--muted': muted,
152
219
  '--muted-foreground': mutedForeground,
153
220
  '--accent': accent,
154
- '--accent-foreground': colors.foreground,
221
+ '--accent-foreground': secondaryForeground,
222
+ '--destructive': danger,
223
+ '--destructive-foreground': dangerForeground,
224
+ '--danger': danger,
225
+ '--danger-foreground': dangerForeground,
226
+ '--success': success,
227
+ '--success-foreground': successForeground,
228
+ '--warning': warning,
229
+ '--warning-foreground': warningForeground,
230
+ '--rising': rising,
231
+ '--rising-foreground': risingForeground,
232
+ '--downing': downing,
233
+ '--downing-foreground': downingForeground,
155
234
  '--border': border,
156
- '--ring': colors.primary,
157
- '--sidebar': colors.background,
158
- '--sidebar-foreground': colors.foreground,
235
+ '--input': input,
236
+ '--ring': ring,
237
+ '--text-title-color': textTitle,
238
+ '--text-subtitle-color': textSubtitle,
239
+ '--text-primary': textPrimary,
240
+ '--text-secondary': textSecondary,
241
+ '--text-link': textLink,
242
+ '--text-button-color': textButton,
243
+ '--sidebar': card,
244
+ '--sidebar-foreground': cardForeground,
159
245
  '--sidebar-primary': colors.primary,
160
246
  '--sidebar-primary-foreground': colors.primaryForeground,
161
247
  '--sidebar-accent': accent,
162
- '--sidebar-accent-foreground': colors.foreground,
248
+ '--sidebar-accent-foreground': secondaryForeground,
163
249
  '--sidebar-border': border,
164
250
  };
165
251
  }
166
252
  export function getBrandCssVariables(config, mode) {
167
- const colors = mode === 'dark' ? config.theme.colors.dark : config.theme.colors.light;
253
+ const normalized = normalizeBrandConfig(config);
254
+ const colors = mode === 'dark' ? normalized.theme.colors.dark : normalized.theme.colors.light;
255
+ const typography = normalizeBrandTypography(normalized.theme.typography);
168
256
  return {
169
257
  ...buildModeVars(colors, mode),
170
- '--radius': config.theme.radius,
258
+ '--font-sans': fontSansToCssFamily(normalized.theme.font.sans),
259
+ '--font-size-base': normalizeFontBaseSize(normalized.theme.font.baseSize),
260
+ '--font-size': normalizeFontBaseSize(normalized.theme.font.baseSize),
261
+ '--text-display': typography.display,
262
+ '--text-title': typography.title,
263
+ '--text-subtitle': typography.subtitle,
264
+ '--text-body': typography.body,
265
+ '--text-label': typography.label,
266
+ '--text-caption': typography.caption,
267
+ '--text-button': typography.button,
268
+ '--text-code': typography.code,
269
+ '--text-overline': typography.overline,
270
+ '--radius': normalized.theme.radius,
171
271
  };
172
272
  }
173
273
  function formatCssVars(vars) {
@@ -192,6 +292,10 @@ ${formatCssVars(darkVars)}
192
292
  html, body, button, input, select, textarea {
193
293
  font-family: ${fontFamily};
194
294
  }
295
+
296
+ html {
297
+ font-size: ${normalized.theme.font.baseSize};
298
+ }
195
299
  `.trim();
196
300
  }
197
301
  export function resolveBrandThemeMode(config, preferredMode) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/brand/config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BrandConfig, BackendBrandLogoType, BrandLogoType, ColorSet } from './types.js';\n\nexport type BrandMode = 'light' | 'dark';\n\nexport interface BrandManifestIcon {\n src: string;\n sizes: string;\n type?: string;\n purpose?: 'any' | 'maskable' | 'monochrome';\n}\n\nexport interface BrandWebManifest {\n name: string;\n short_name: string;\n description: string;\n icons: BrandManifestIcon[];\n theme_color: string;\n background_color: string;\n display: 'standalone';\n start_url: string;\n}\n\nexport interface BrandIconDescriptor {\n url: string;\n type?: string;\n media?: string;\n}\n\nconst FALLBACK_FAVICON = '/favicon.ico';\nconst FALLBACK_FONT = 'Inter';\nconst FALLBACK_LOGO_WIDTH = '160px';\nconst FALLBACK_LOGO_HEIGHT = '40px';\nconst SAFE_LOGO_KEYWORDS = new Set(['auto', 'fit-content']);\nconst SAFE_LOGO_DIMENSION_PATTERN = /^(\\d+(?:\\.\\d+)?)(px|rem|em|%|vw|vh)$/i;\n\nexport interface NormalizedLogoLayout {\n width: string;\n height: string;\n}\n\nexport function normalizeLogoType(type: BackendBrandLogoType | string | null | undefined): BrandLogoType {\n return type === 'text' ? 'text' : 'image';\n}\n\nexport function isImageLogoType(type: BackendBrandLogoType | string | null | undefined): boolean {\n return normalizeLogoType(type) === 'image';\n}\n\nexport function normalizeLogoDimension(\n value: string | number | null | undefined,\n fallback: string,\n): string {\n if (typeof value === 'number') {\n return Number.isFinite(value) && value >= 0 ? `${value}px` : fallback;\n }\n\n const raw = value?.trim();\n if (!raw) return fallback;\n\n const lower = raw.toLowerCase();\n if (SAFE_LOGO_KEYWORDS.has(lower)) return lower;\n\n const match = lower.match(SAFE_LOGO_DIMENSION_PATTERN);\n if (!match) return fallback;\n\n const amount = Number(match[1]);\n if (!Number.isFinite(amount) || amount < 0) return fallback;\n\n return `${match[1]}${match[2].toLowerCase()}`;\n}\n\nexport function normalizeLogoLayout(\n layout: BrandConfig['brand']['logo']['layout'] | null | undefined,\n): NormalizedLogoLayout {\n return {\n width: normalizeLogoDimension(layout?.width, FALLBACK_LOGO_WIDTH),\n height: normalizeLogoDimension(layout?.height, FALLBACK_LOGO_HEIGHT),\n };\n}\n\nexport function normalizeFontSans(value: string | null | undefined): string {\n const raw = value?.trim();\n if (!raw) return FALLBACK_FONT;\n\n if (!raw.includes(',')) {\n return raw.replace(/['\"`]/g, '').trim() || FALLBACK_FONT;\n }\n\n return raw.split(',')[0]?.replace(/['\"`]/g, '').trim() || FALLBACK_FONT;\n}\n\nfunction quoteFontFamily(name: string): string {\n const clean = name.replace(/['\"`]/g, '').trim();\n if (!clean || clean === 'System') {\n return 'ui-sans-serif, system-ui, sans-serif';\n }\n\n return `'${clean}', ui-sans-serif, system-ui, sans-serif`;\n}\n\nexport function fontSansToCssFamily(value: string | null | undefined): string {\n return quoteFontFamily(normalizeFontSans(value));\n}\n\nexport function normalizeBrandConfig(config: BrandConfig): BrandConfig {\n const logo = config.brand.logo;\n const text = logo.text ?? { base: config.brand.name, accent: '' };\n\n return {\n ...config,\n brand: {\n ...config.brand,\n logo: {\n ...logo,\n type: normalizeLogoType(logo.type),\n imageUrl: logo.imageUrl ?? '',\n darkImageUrl: logo.darkImageUrl ?? null,\n layout: normalizeLogoLayout(logo.layout),\n text: {\n ...text,\n base: text.base ?? config.brand.name,\n accent: text.accent ?? '',\n fontFamily: text.fontFamily ? normalizeFontSans(text.fontFamily) : text.fontFamily,\n },\n },\n },\n favicon: {\n default: config.favicon?.default ?? FALLBACK_FAVICON,\n dark: config.favicon?.dark ?? null,\n },\n theme: {\n ...config.theme,\n font: {\n ...config.theme.font,\n sans: normalizeFontSans(config.theme.font?.sans),\n },\n },\n };\n}\n\nexport function getLogoImageUrl(\n logo: BrandConfig['brand']['logo'],\n mode: BrandMode = 'light',\n): string | null {\n if (!isImageLogoType(logo.type)) return null;\n\n const darkUrl = logo.darkImageUrl?.trim();\n const defaultUrl = logo.imageUrl?.trim();\n\n return (mode === 'dark' && darkUrl ? darkUrl : defaultUrl) || null;\n}\n\nexport function getLogoTextFontFamily(config: BrandConfig): string {\n return fontSansToCssFamily(config.brand.logo.text.fontFamily || config.theme.font.sans);\n}\n\nexport function getLogoTextColors(config: BrandConfig, mode: BrandMode) {\n return config.brand.logo.text.colors?.[mode] ?? {};\n}\n\nfunction colorMixHex(a: string, b: string, t: number): string {\n const pa = parseHex(a);\n const pb = parseHex(b);\n if (!pa || !pb) return a;\n\n const r = Math.round(pa[0] + (pb[0] - pa[0]) * t);\n const g = Math.round(pa[1] + (pb[1] - pa[1]) * t);\n const bl = Math.round(pa[2] + (pb[2] - pa[2]) * t);\n\n return `#${hex2(r)}${hex2(g)}${hex2(bl)}`;\n}\n\nfunction hexToRgbaValue(hex: string, alpha: number): string {\n const parsed = parseHex(hex);\n if (!parsed) return `rgba(128,128,128,${alpha})`;\n\n return `rgba(${parsed[0]},${parsed[1]},${parsed[2]},${alpha})`;\n}\n\nfunction parseHex(hex: string): [number, number, number] | null {\n const clean = hex.replace('#', '');\n const full = clean.length === 3\n ? clean.split('').map((c) => c + c).join('')\n : clean;\n\n if (!/^[0-9a-fA-F]{6}$/.test(full)) return null;\n\n return [\n parseInt(full.slice(0, 2), 16),\n parseInt(full.slice(2, 4), 16),\n parseInt(full.slice(4, 6), 16),\n ];\n}\n\nfunction hex2(n: number): string {\n return n.toString(16).padStart(2, '0');\n}\n\nfunction buildModeVars(colors: ColorSet, mode: BrandMode) {\n const isDark = mode === 'dark';\n const secondary = colorMixHex(colors.background, isDark ? '#ffffff' : '#000000', isDark ? 0.12 : 0.05);\n const muted = colorMixHex(colors.background, isDark ? '#ffffff' : '#888888', isDark ? 0.08 : 0.07);\n const accent = colorMixHex(colors.background, isDark ? '#ffffff' : '#000000', isDark ? 0.16 : 0.08);\n const border = hexToRgbaValue(colors.foreground, isDark ? 0.12 : 0.1);\n const mutedForeground = hexToRgbaValue(colors.foreground, isDark ? 0.68 : 0.62);\n\n return {\n '--primary': colors.primary,\n '--primary-foreground': colors.primaryForeground,\n '--background': colors.background,\n '--foreground': colors.foreground,\n '--card': colors.background,\n '--card-foreground': colors.foreground,\n '--secondary': secondary,\n '--secondary-foreground': colors.foreground,\n '--muted': muted,\n '--muted-foreground': mutedForeground,\n '--accent': accent,\n '--accent-foreground': colors.foreground,\n '--border': border,\n '--ring': colors.primary,\n '--sidebar': colors.background,\n '--sidebar-foreground': colors.foreground,\n '--sidebar-primary': colors.primary,\n '--sidebar-primary-foreground': colors.primaryForeground,\n '--sidebar-accent': accent,\n '--sidebar-accent-foreground': colors.foreground,\n '--sidebar-border': border,\n };\n}\n\nexport function getBrandCssVariables(config: BrandConfig, mode: BrandMode) {\n const colors = mode === 'dark' ? config.theme.colors.dark : config.theme.colors.light;\n return {\n ...buildModeVars(colors, mode),\n '--radius': config.theme.radius,\n };\n}\n\nfunction formatCssVars(vars: Record<string, string>): string {\n return Object.entries(vars)\n .map(([key, value]) => ` ${key}: ${value};`)\n .join('\\n');\n}\n\nexport function buildBrandCss(config: BrandConfig): string {\n const normalized = normalizeBrandConfig(config);\n const lightVars = getBrandCssVariables(normalized, 'light');\n const darkVars = getBrandCssVariables(normalized, 'dark');\n const fontFamily = fontSansToCssFamily(normalized.theme.font.sans);\n\n return `\n :root {\n${formatCssVars(lightVars)}\n }\n\n html[data-theme=\"dark\"] {\n${formatCssVars(darkVars)}\n }\n\n html, body, button, input, select, textarea {\n font-family: ${fontFamily};\n }\n `.trim();\n}\n\nexport function resolveBrandThemeMode(config: BrandConfig, preferredMode?: string | null): BrandMode {\n if (preferredMode === 'light' || preferredMode === 'dark') {\n return preferredMode;\n }\n\n const defaultMode = config.theme.defaultMode;\n return defaultMode === 'dark' ? 'dark' : 'light';\n}\n\nfunction stripQueryAndHash(url: string): string {\n return url.split(/[?#]/)[0] ?? url;\n}\n\nexport function inferImageMimeType(url: string): string | undefined {\n const lower = stripQueryAndHash(url).toLowerCase();\n if (lower.endsWith('.svg')) return 'image/svg+xml';\n if (lower.endsWith('.png')) return 'image/png';\n if (lower.endsWith('.webp')) return 'image/webp';\n if (lower.endsWith('.jpg') || lower.endsWith('.jpeg')) return 'image/jpeg';\n if (lower.endsWith('.ico')) return 'image/x-icon';\n return undefined;\n}\n\nfunction inferIconSizes(url: string): string {\n const path = stripQueryAndHash(url);\n if (/\\.(svg|ico)$/i.test(path)) return 'any';\n\n const match = path.match(/(?:^|[^\\d])(\\d{2,4})x\\1(?:[^\\d]|$)|(?:^|[^\\d])(\\d{2,4})(?:[^\\d]|$)/);\n const size = match?.[1] ?? match?.[2];\n return size ? `${size}x${size}` : 'any';\n}\n\nfunction buildManifestIcon(src: string): BrandManifestIcon {\n return {\n src,\n sizes: inferIconSizes(src),\n type: inferImageMimeType(src),\n purpose: 'any',\n };\n}\n\nexport function buildBrandManifest(config: BrandConfig): BrandWebManifest {\n const normalized = normalizeBrandConfig(config);\n const mode = resolveBrandThemeMode(normalized);\n const colors = mode === 'dark' ? normalized.theme.colors.dark : normalized.theme.colors.light;\n const defaultFavicon = normalized.favicon.default || FALLBACK_FAVICON;\n const darkFavicon = normalized.favicon.dark?.trim();\n const icons = [buildManifestIcon(defaultFavicon)];\n\n if (darkFavicon && darkFavicon !== defaultFavicon) {\n icons.push(buildManifestIcon(darkFavicon));\n }\n\n return {\n name: normalized.brand.name,\n short_name: normalized.brand.name,\n description: normalized.brand.description || normalized.brand.tagline || normalized.brand.name,\n icons,\n theme_color: colors.primary,\n background_color: colors.background,\n display: 'standalone',\n start_url: '/',\n };\n}\n\nexport function getBrandFaviconUrl(\n favicon: BrandConfig['favicon'],\n mode: BrandMode = 'light',\n): string {\n const defaultFavicon = favicon?.default || FALLBACK_FAVICON;\n const darkFavicon = favicon?.dark?.trim();\n return mode === 'dark' && darkFavicon ? darkFavicon : defaultFavicon;\n}\n\nexport function buildBrandIconsMetadata(\n favicon: BrandConfig['favicon'],\n mode: BrandMode = 'light',\n) {\n const activeFavicon = getBrandFaviconUrl(favicon, mode);\n\n return {\n icon: [{\n url: activeFavicon,\n type: inferImageMimeType(activeFavicon),\n media: 'all',\n }],\n shortcut: activeFavicon,\n };\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/brand/config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BrandConfig, BackendBrandLogoType, BrandLogoType, BrandTypography, ColorSet } from './types.js';\n\nexport type BrandMode = 'light' | 'dark';\n\nexport interface BrandManifestIcon {\n src: string;\n sizes: string;\n type?: string;\n purpose?: 'any' | 'maskable' | 'monochrome';\n}\n\nexport interface BrandWebManifest {\n name: string;\n short_name: string;\n description: string;\n icons: BrandManifestIcon[];\n theme_color: string;\n background_color: string;\n display: 'standalone';\n start_url: string;\n}\n\nexport interface BrandIconDescriptor {\n url: string;\n type?: string;\n media?: string;\n}\n\nconst FALLBACK_FAVICON = '/favicon.ico';\nconst FALLBACK_FONT = 'Inter';\nconst FALLBACK_BASE_SIZE = '16px';\nconst FALLBACK_LOGO_WIDTH = '160px';\nconst FALLBACK_LOGO_HEIGHT = '40px';\nconst SAFE_LOGO_KEYWORDS = new Set(['auto', 'fit-content']);\nconst SAFE_LOGO_DIMENSION_PATTERN = /^(\\d+(?:\\.\\d+)?)(px|rem|em|%|vw|vh)$/i;\nconst SAFE_BASE_SIZE_PATTERN = /^(\\d+(?:\\.\\d+)?)px$/i;\nconst SAFE_REM_PATTERN = /^(\\d+(?:\\.\\d+)?)rem$/i;\nconst DEFAULT_TYPOGRAPHY: Required<BrandTypography> = {\n display: '1.875rem',\n title: '1.25rem',\n subtitle: '1rem',\n body: '0.875rem',\n label: '0.75rem',\n caption: '0.6875rem',\n button: '0.875rem',\n code: '0.8125rem',\n overline: '0.625rem',\n};\n\nexport interface NormalizedLogoLayout {\n width: string;\n height: string;\n}\n\nexport function normalizeLogoType(type: BackendBrandLogoType | string | null | undefined): BrandLogoType {\n return type === 'text' ? 'text' : 'image';\n}\n\nexport function isImageLogoType(type: BackendBrandLogoType | string | null | undefined): boolean {\n return normalizeLogoType(type) === 'image';\n}\n\nexport function normalizeLogoDimension(\n value: string | number | null | undefined,\n fallback: string,\n): string {\n if (typeof value === 'number') {\n return Number.isFinite(value) && value >= 0 ? `${value}px` : fallback;\n }\n\n const raw = value?.trim();\n if (!raw) return fallback;\n\n const lower = raw.toLowerCase();\n if (SAFE_LOGO_KEYWORDS.has(lower)) return lower;\n\n const match = lower.match(SAFE_LOGO_DIMENSION_PATTERN);\n if (!match) return fallback;\n\n const amount = Number(match[1]);\n if (!Number.isFinite(amount) || amount < 0) return fallback;\n\n return `${match[1]}${match[2].toLowerCase()}`;\n}\n\nexport function normalizeLogoLayout(\n layout: BrandConfig['brand']['logo']['layout'] | null | undefined,\n): NormalizedLogoLayout {\n return {\n width: normalizeLogoDimension(layout?.width, FALLBACK_LOGO_WIDTH),\n height: normalizeLogoDimension(layout?.height, FALLBACK_LOGO_HEIGHT),\n };\n}\n\nexport function normalizeFontSans(value: string | null | undefined): string {\n const raw = value?.trim();\n if (!raw) return FALLBACK_FONT;\n\n if (!raw.includes(',')) {\n return raw.replace(/['\"`]/g, '').trim() || FALLBACK_FONT;\n }\n\n return raw.split(',')[0]?.replace(/['\"`]/g, '').trim() || FALLBACK_FONT;\n}\n\nfunction quoteFontFamily(name: string): string {\n const clean = name.replace(/['\"`]/g, '').trim();\n if (!clean || clean === 'System') {\n return 'ui-sans-serif, system-ui, sans-serif';\n }\n\n return `'${clean}', ui-sans-serif, system-ui, sans-serif`;\n}\n\nexport function fontSansToCssFamily(value: string | null | undefined): string {\n return quoteFontFamily(normalizeFontSans(value));\n}\n\nexport function normalizeFontBaseSize(value: string | null | undefined): string {\n const raw = value?.trim();\n if (!raw) return FALLBACK_BASE_SIZE;\n\n const match = raw.match(SAFE_BASE_SIZE_PATTERN);\n if (!match) return FALLBACK_BASE_SIZE;\n\n const amount = Number(match[1]);\n return Number.isFinite(amount) && amount >= 8 && amount <= 24\n ? `${match[1]}px`\n : FALLBACK_BASE_SIZE;\n}\n\nexport function normalizeTypographyValue(value: string | null | undefined, fallback: string): string {\n const raw = value?.trim();\n if (!raw) return fallback;\n\n const match = raw.match(SAFE_REM_PATTERN);\n if (!match) return fallback;\n\n const amount = Number(match[1]);\n return Number.isFinite(amount) && amount >= 0.5 && amount <= 3\n ? `${match[1]}rem`\n : fallback;\n}\n\nexport function normalizeBrandTypography(value: BrandTypography | null | undefined): Required<BrandTypography> {\n return Object.fromEntries(\n Object.entries(DEFAULT_TYPOGRAPHY).map(([token, fallback]) => [\n token,\n normalizeTypographyValue(value?.[token as keyof BrandTypography], fallback),\n ]),\n ) as Required<BrandTypography>;\n}\n\nexport function normalizeBrandConfig(config: BrandConfig): BrandConfig {\n const logo = config.brand.logo;\n const text = logo.text ?? { base: config.brand.name, accent: '' };\n\n return {\n ...config,\n brand: {\n ...config.brand,\n logo: {\n ...logo,\n type: normalizeLogoType(logo.type),\n imageUrl: logo.imageUrl ?? '',\n darkImageUrl: logo.darkImageUrl ?? null,\n layout: normalizeLogoLayout(logo.layout),\n text: {\n ...text,\n base: text.base ?? config.brand.name,\n accent: text.accent ?? '',\n fontFamily: text.fontFamily ? normalizeFontSans(text.fontFamily) : text.fontFamily,\n },\n },\n },\n favicon: {\n default: config.favicon?.default ?? FALLBACK_FAVICON,\n dark: config.favicon?.dark ?? null,\n },\n theme: {\n ...config.theme,\n font: {\n ...config.theme.font,\n sans: normalizeFontSans(config.theme.font?.sans),\n baseSize: normalizeFontBaseSize(config.theme.font?.baseSize),\n },\n typography: normalizeBrandTypography(config.theme.typography),\n },\n };\n}\n\nexport function getLogoImageUrl(\n logo: BrandConfig['brand']['logo'],\n mode: BrandMode = 'light',\n): string | null {\n if (!isImageLogoType(logo.type)) return null;\n\n const darkUrl = logo.darkImageUrl?.trim();\n const defaultUrl = logo.imageUrl?.trim();\n\n return (mode === 'dark' && darkUrl ? darkUrl : defaultUrl) || null;\n}\n\nexport function getLogoTextFontFamily(config: BrandConfig): string {\n return fontSansToCssFamily(config.brand.logo.text.fontFamily || config.theme.font.sans);\n}\n\nexport function getLogoTextColors(config: BrandConfig, mode: BrandMode) {\n return config.brand.logo.text.colors?.[mode] ?? {};\n}\n\nfunction colorMixHex(a: string, b: string, t: number): string {\n const pa = parseHex(a);\n const pb = parseHex(b);\n if (!pa || !pb) return a;\n\n const r = Math.round(pa[0] + (pb[0] - pa[0]) * t);\n const g = Math.round(pa[1] + (pb[1] - pa[1]) * t);\n const bl = Math.round(pa[2] + (pb[2] - pa[2]) * t);\n\n return `#${hex2(r)}${hex2(g)}${hex2(bl)}`;\n}\n\nfunction hexToRgbaValue(hex: string, alpha: number): string {\n const parsed = parseHex(hex);\n if (!parsed) return `rgba(128,128,128,${alpha})`;\n\n return `rgba(${parsed[0]},${parsed[1]},${parsed[2]},${alpha})`;\n}\n\nfunction parseHex(hex: string): [number, number, number] | null {\n const clean = hex.replace('#', '');\n const full = clean.length === 3\n ? clean.split('').map((c) => c + c).join('')\n : clean;\n\n if (!/^[0-9a-fA-F]{6}$/.test(full)) return null;\n\n return [\n parseInt(full.slice(0, 2), 16),\n parseInt(full.slice(2, 4), 16),\n parseInt(full.slice(4, 6), 16),\n ];\n}\n\nfunction hex2(n: number): string {\n return n.toString(16).padStart(2, '0');\n}\n\nfunction buildModeVars(colors: ColorSet, mode: BrandMode) {\n const isDark = mode === 'dark';\n const secondary = colors.secondary ?? colorMixHex(colors.background, isDark ? '#ffffff' : '#000000', isDark ? 0.12 : 0.05);\n const secondaryForeground = colors.secondaryForeground ?? colors.foreground;\n const muted = colors.muted ?? colorMixHex(colors.background, isDark ? '#ffffff' : '#888888', isDark ? 0.08 : 0.07);\n const mutedForeground = colors.mutedForeground ?? hexToRgbaValue(colors.foreground, isDark ? 0.68 : 0.62);\n const accent = colors.secondary ?? colorMixHex(colors.background, isDark ? '#ffffff' : '#000000', isDark ? 0.16 : 0.08);\n const border = colors.border ?? hexToRgbaValue(colors.foreground, isDark ? 0.12 : 0.1);\n const danger = colors.danger ?? (isDark ? '#EF4444' : '#DC2626');\n const dangerForeground = colors.dangerForeground ?? '#ffffff';\n const success = colors.success ?? colors.rising ?? (isDark ? '#22C55E' : '#16A34A');\n const successForeground = colors.successForeground ?? '#ffffff';\n const warning = colors.warning ?? (isDark ? '#F59E0B' : '#D97706');\n const warningForeground = colors.warningForeground ?? (isDark ? '#111827' : '#ffffff');\n const rising = colors.rising ?? success;\n const risingForeground = colors.risingForeground ?? successForeground;\n const downing = colors.downing ?? danger;\n const downingForeground = colors.downingForeground ?? dangerForeground;\n const card = colors.card ?? colors.background;\n const cardForeground = colors.cardForeground ?? colors.foreground;\n const input = colors.input ?? border;\n const ring = colors.ring ?? colors.primary;\n const textTitle = colors.textTitle ?? colors.foreground;\n const textSubtitle = colors.textSubtitle ?? mutedForeground;\n const textPrimary = colors.textPrimary ?? colors.foreground;\n const textSecondary = colors.textSecondary ?? mutedForeground;\n const textLink = colors.textLink ?? colors.primary;\n const textButton = colors.textButton ?? colors.primaryForeground;\n\n return {\n '--primary': colors.primary,\n '--primary-foreground': colors.primaryForeground,\n '--background': colors.background,\n '--foreground': colors.foreground,\n '--card': card,\n '--card-foreground': cardForeground,\n '--secondary': secondary,\n '--secondary-foreground': secondaryForeground,\n '--muted': muted,\n '--muted-foreground': mutedForeground,\n '--accent': accent,\n '--accent-foreground': secondaryForeground,\n '--destructive': danger,\n '--destructive-foreground': dangerForeground,\n '--danger': danger,\n '--danger-foreground': dangerForeground,\n '--success': success,\n '--success-foreground': successForeground,\n '--warning': warning,\n '--warning-foreground': warningForeground,\n '--rising': rising,\n '--rising-foreground': risingForeground,\n '--downing': downing,\n '--downing-foreground': downingForeground,\n '--border': border,\n '--input': input,\n '--ring': ring,\n '--text-title-color': textTitle,\n '--text-subtitle-color': textSubtitle,\n '--text-primary': textPrimary,\n '--text-secondary': textSecondary,\n '--text-link': textLink,\n '--text-button-color': textButton,\n '--sidebar': card,\n '--sidebar-foreground': cardForeground,\n '--sidebar-primary': colors.primary,\n '--sidebar-primary-foreground': colors.primaryForeground,\n '--sidebar-accent': accent,\n '--sidebar-accent-foreground': secondaryForeground,\n '--sidebar-border': border,\n };\n}\n\nexport function getBrandCssVariables(config: BrandConfig, mode: BrandMode) {\n const normalized = normalizeBrandConfig(config);\n const colors = mode === 'dark' ? normalized.theme.colors.dark : normalized.theme.colors.light;\n const typography = normalizeBrandTypography(normalized.theme.typography);\n return {\n ...buildModeVars(colors, mode),\n '--font-sans': fontSansToCssFamily(normalized.theme.font.sans),\n '--font-size-base': normalizeFontBaseSize(normalized.theme.font.baseSize),\n '--font-size': normalizeFontBaseSize(normalized.theme.font.baseSize),\n '--text-display': typography.display,\n '--text-title': typography.title,\n '--text-subtitle': typography.subtitle,\n '--text-body': typography.body,\n '--text-label': typography.label,\n '--text-caption': typography.caption,\n '--text-button': typography.button,\n '--text-code': typography.code,\n '--text-overline': typography.overline,\n '--radius': normalized.theme.radius,\n };\n}\n\nfunction formatCssVars(vars: Record<string, string>): string {\n return Object.entries(vars)\n .map(([key, value]) => ` ${key}: ${value};`)\n .join('\\n');\n}\n\nexport function buildBrandCss(config: BrandConfig): string {\n const normalized = normalizeBrandConfig(config);\n const lightVars = getBrandCssVariables(normalized, 'light');\n const darkVars = getBrandCssVariables(normalized, 'dark');\n const fontFamily = fontSansToCssFamily(normalized.theme.font.sans);\n\n return `\n :root {\n${formatCssVars(lightVars)}\n }\n\n html[data-theme=\"dark\"] {\n${formatCssVars(darkVars)}\n }\n\n html, body, button, input, select, textarea {\n font-family: ${fontFamily};\n }\n\n html {\n font-size: ${normalized.theme.font.baseSize};\n }\n `.trim();\n}\n\nexport function resolveBrandThemeMode(config: BrandConfig, preferredMode?: string | null): BrandMode {\n if (preferredMode === 'light' || preferredMode === 'dark') {\n return preferredMode;\n }\n\n const defaultMode = config.theme.defaultMode;\n return defaultMode === 'dark' ? 'dark' : 'light';\n}\n\nfunction stripQueryAndHash(url: string): string {\n return url.split(/[?#]/)[0] ?? url;\n}\n\nexport function inferImageMimeType(url: string): string | undefined {\n const lower = stripQueryAndHash(url).toLowerCase();\n if (lower.endsWith('.svg')) return 'image/svg+xml';\n if (lower.endsWith('.png')) return 'image/png';\n if (lower.endsWith('.webp')) return 'image/webp';\n if (lower.endsWith('.jpg') || lower.endsWith('.jpeg')) return 'image/jpeg';\n if (lower.endsWith('.ico')) return 'image/x-icon';\n return undefined;\n}\n\nfunction inferIconSizes(url: string): string {\n const path = stripQueryAndHash(url);\n if (/\\.(svg|ico)$/i.test(path)) return 'any';\n\n const match = path.match(/(?:^|[^\\d])(\\d{2,4})x\\1(?:[^\\d]|$)|(?:^|[^\\d])(\\d{2,4})(?:[^\\d]|$)/);\n const size = match?.[1] ?? match?.[2];\n return size ? `${size}x${size}` : 'any';\n}\n\nfunction buildManifestIcon(src: string): BrandManifestIcon {\n return {\n src,\n sizes: inferIconSizes(src),\n type: inferImageMimeType(src),\n purpose: 'any',\n };\n}\n\nexport function buildBrandManifest(config: BrandConfig): BrandWebManifest {\n const normalized = normalizeBrandConfig(config);\n const mode = resolveBrandThemeMode(normalized);\n const colors = mode === 'dark' ? normalized.theme.colors.dark : normalized.theme.colors.light;\n const defaultFavicon = normalized.favicon.default || FALLBACK_FAVICON;\n const darkFavicon = normalized.favicon.dark?.trim();\n const icons = [buildManifestIcon(defaultFavicon)];\n\n if (darkFavicon && darkFavicon !== defaultFavicon) {\n icons.push(buildManifestIcon(darkFavicon));\n }\n\n return {\n name: normalized.brand.name,\n short_name: normalized.brand.name,\n description: normalized.brand.description || normalized.brand.tagline || normalized.brand.name,\n icons,\n theme_color: colors.primary,\n background_color: colors.background,\n display: 'standalone',\n start_url: '/',\n };\n}\n\nexport function getBrandFaviconUrl(\n favicon: BrandConfig['favicon'],\n mode: BrandMode = 'light',\n): string {\n const defaultFavicon = favicon?.default || FALLBACK_FAVICON;\n const darkFavicon = favicon?.dark?.trim();\n return mode === 'dark' && darkFavicon ? darkFavicon : defaultFavicon;\n}\n\nexport function buildBrandIconsMetadata(\n favicon: BrandConfig['favicon'],\n mode: BrandMode = 'light',\n) {\n const activeFavicon = getBrandFaviconUrl(favicon, mode);\n\n return {\n icon: [{\n url: activeFavicon,\n type: inferImageMimeType(activeFavicon),\n media: 'all',\n }],\n shortcut: activeFavicon,\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- export type { BackendBrandLogoType, BrandConfig, BrandLogoType, ColorSet, DeepPartial, SecurityTxtConfig, } from './types.js';
2
- export { buildBrandCss, buildBrandIconsMetadata, buildBrandManifest, fontSansToCssFamily, getBrandCssVariables, getBrandFaviconUrl, getLogoImageUrl, getLogoTextColors, getLogoTextFontFamily, inferImageMimeType, isImageLogoType, normalizeBrandConfig, normalizeFontSans, normalizeLogoDimension, normalizeLogoLayout, normalizeLogoType, resolveBrandThemeMode, } from './config.js';
1
+ export type { BackendBrandLogoType, BrandThemeMode, BrandTypography, BrandTypographyToken, BrandConfig, BrandLogoType, ColorSet, DeepPartial, SecurityTxtConfig, } from './types.js';
2
+ export { buildBrandCss, buildBrandIconsMetadata, buildBrandManifest, fontSansToCssFamily, getBrandCssVariables, getBrandFaviconUrl, getLogoImageUrl, getLogoTextColors, getLogoTextFontFamily, inferImageMimeType, isImageLogoType, normalizeBrandConfig, normalizeBrandTypography, normalizeFontBaseSize, normalizeFontSans, normalizeLogoDimension, normalizeLogoLayout, normalizeLogoType, normalizeTypographyValue, resolveBrandThemeMode, } from './config.js';
3
3
  export type { BrandIconDescriptor, BrandManifestIcon, BrandMode, BrandWebManifest, NormalizedLogoLayout, } from './config.js';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/brand/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,QAAQ,EACR,WAAW,EACX,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/brand/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,QAAQ,EACR,WAAW,EACX,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
@@ -1,2 +1,2 @@
1
- export { buildBrandCss, buildBrandIconsMetadata, buildBrandManifest, fontSansToCssFamily, getBrandCssVariables, getBrandFaviconUrl, getLogoImageUrl, getLogoTextColors, getLogoTextFontFamily, inferImageMimeType, isImageLogoType, normalizeBrandConfig, normalizeFontSans, normalizeLogoDimension, normalizeLogoLayout, normalizeLogoType, resolveBrandThemeMode, } from './config.js';
1
+ export { buildBrandCss, buildBrandIconsMetadata, buildBrandManifest, fontSansToCssFamily, getBrandCssVariables, getBrandFaviconUrl, getLogoImageUrl, getLogoTextColors, getLogoTextFontFamily, inferImageMimeType, isImageLogoType, normalizeBrandConfig, normalizeBrandTypography, normalizeFontBaseSize, normalizeFontSans, normalizeLogoDimension, normalizeLogoLayout, normalizeLogoType, normalizeTypographyValue, resolveBrandThemeMode, } from './config.js';
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/brand/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,aAAa,CAAC","sourcesContent":["export type {\n BackendBrandLogoType,\n BrandConfig,\n BrandLogoType,\n ColorSet,\n DeepPartial,\n SecurityTxtConfig,\n} from './types.js';\n\nexport {\n buildBrandCss,\n buildBrandIconsMetadata,\n buildBrandManifest,\n fontSansToCssFamily,\n getBrandCssVariables,\n getBrandFaviconUrl,\n getLogoImageUrl,\n getLogoTextColors,\n getLogoTextFontFamily,\n inferImageMimeType,\n isImageLogoType,\n normalizeBrandConfig,\n normalizeFontSans,\n normalizeLogoDimension,\n normalizeLogoLayout,\n normalizeLogoType,\n resolveBrandThemeMode,\n} from './config.js';\n\nexport type {\n BrandIconDescriptor,\n BrandManifestIcon,\n BrandMode,\n BrandWebManifest,\n NormalizedLogoLayout,\n} from './config.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/brand/index.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,aAAa,CAAC","sourcesContent":["export type {\n BackendBrandLogoType,\n BrandThemeMode,\n BrandTypography,\n BrandTypographyToken,\n BrandConfig,\n BrandLogoType,\n ColorSet,\n DeepPartial,\n SecurityTxtConfig,\n} from './types.js';\n\nexport {\n buildBrandCss,\n buildBrandIconsMetadata,\n buildBrandManifest,\n fontSansToCssFamily,\n getBrandCssVariables,\n getBrandFaviconUrl,\n getLogoImageUrl,\n getLogoTextColors,\n getLogoTextFontFamily,\n inferImageMimeType,\n isImageLogoType,\n normalizeBrandConfig,\n normalizeBrandTypography,\n normalizeFontBaseSize,\n normalizeFontSans,\n normalizeLogoDimension,\n normalizeLogoLayout,\n normalizeLogoType,\n normalizeTypographyValue,\n resolveBrandThemeMode,\n} from './config.js';\n\nexport type {\n BrandIconDescriptor,\n BrandManifestIcon,\n BrandMode,\n BrandWebManifest,\n NormalizedLogoLayout,\n} from './config.js';\n"]}
@@ -8,6 +8,9 @@ export interface SecurityTxtConfig {
8
8
  }
9
9
  export type BrandLogoType = 'text' | 'image';
10
10
  export type BackendBrandLogoType = BrandLogoType | 'url' | 'upload';
11
+ export type BrandThemeMode = 'light' | 'dark' | 'system';
12
+ export type BrandTypographyToken = 'display' | 'title' | 'subtitle' | 'body' | 'label' | 'caption' | 'button' | 'code' | 'overline';
13
+ export type BrandTypography = Partial<Record<BrandTypographyToken, string>>;
11
14
  /** Shape of the canonical payload returned by GET /api/brand/theme. */
12
15
  export interface BrandConfig {
13
16
  brand: {
@@ -54,10 +57,12 @@ export interface BrandConfig {
54
57
  defaultLocale: string;
55
58
  availableLocales?: string[];
56
59
  theme: {
57
- defaultMode: 'light' | 'dark' | 'system';
60
+ defaultMode: BrandThemeMode;
58
61
  font: {
59
62
  sans: string;
63
+ baseSize?: string | null;
60
64
  };
65
+ typography?: BrandTypography | null;
61
66
  radius: string;
62
67
  colors: {
63
68
  light: ColorSet;
@@ -114,6 +119,31 @@ export interface ColorSet {
114
119
  primaryForeground: string;
115
120
  background: string;
116
121
  foreground: string;
122
+ secondary?: string;
123
+ secondaryForeground?: string;
124
+ warning?: string;
125
+ warningForeground?: string;
126
+ danger?: string;
127
+ dangerForeground?: string;
128
+ success?: string;
129
+ successForeground?: string;
130
+ rising?: string;
131
+ risingForeground?: string;
132
+ downing?: string;
133
+ downingForeground?: string;
134
+ card?: string;
135
+ cardForeground?: string;
136
+ muted?: string;
137
+ mutedForeground?: string;
138
+ border?: string;
139
+ input?: string;
140
+ ring?: string;
141
+ textTitle?: string;
142
+ textSubtitle?: string;
143
+ textPrimary?: string;
144
+ textSecondary?: string;
145
+ textLink?: string;
146
+ textButton?: string;
117
147
  }
118
148
  /** Utility: deep-partial for update patches */
119
149
  export type DeepPartial<T> = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/brand/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/brand/types.ts"],"names":[],"mappings":"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"}