@021.is/brand-studio 0.3.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +15 -5
- package/README.md +26 -0
- package/dist/{BrandStudio-D2DcT8Fu.d.ts → BrandStudio-D1QR4hIC.d.ts} +1 -1
- package/dist/app/index.d.ts +2 -2
- package/dist/app/index.js +3 -2
- package/dist/chunk-6J2NFZLN.js +50 -0
- package/dist/{chunk-ZE5UZAY6.js → chunk-F4CFQDS7.js} +2 -1
- package/dist/{chunk-Z2DJJJDC.js → chunk-JGLPUAM6.js} +150 -17
- package/dist/chunk-MDTU2JR5.js +35 -0
- package/dist/{chunk-55AYEWNQ.js → chunk-YDZA26YU.js} +1 -22
- package/dist/define/index.d.ts +45 -3
- package/dist/define/index.js +2 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -4
- package/dist/loading/index.d.ts +1 -1
- package/dist/loading/index.js +3 -2
- package/dist/types-BycZ2igw.d.ts +119 -0
- package/package.json +2 -2
- package/dist/chunk-QT5N4K7D.js +0 -8
- package/dist/types-PWNYyaBF.d.ts +0 -66
package/AGENTS.md
CHANGED
|
@@ -46,16 +46,26 @@ src/
|
|
|
46
46
|
- **Named exports only.** **No CSS framework lock-in** — inline `style` / `var(--md-*)`, accept `className`.
|
|
47
47
|
- Sections theme from `var(--md-<role>)`, never from a hand-authored palette.
|
|
48
48
|
|
|
49
|
+
## The downloads contract — MANDATORY (v0.4+)
|
|
50
|
+
|
|
51
|
+
Every consumer ships icon + logo download URLs under `/brand/download`. Wire `BrandConfig.downloads = buildStandardDownloads({ basePath })` (or supply explicit `BrandDownload[]`). The lib renders the link grid; the host app serves each URL — one Next.js route handler that renders the SVG sized + recoloured per path params is the canonical pattern.
|
|
52
|
+
|
|
53
|
+
- URL shape: `<basePath>/<kind>/<size>/<mode>.<format>` — `kind` ∈ {icon, logo} · `mode` ∈ {light, dark} · `format` defaults to `svg`.
|
|
54
|
+
- Canonical sizes: icon 64/128/256/512/1024 (square edge); logo 32/48/64/96/128 (height).
|
|
55
|
+
- Consumers that don't wire `downloads` fall back to the legacy on-click SVG-blob generator with a banner pointing at this contract. The fallback is for migration only — every published app must wire the matrix.
|
|
56
|
+
- Enforce: `grep -L "buildStandardDownloads\|downloads:" brand.config.ts` in every consumer repo's CI = regression.
|
|
57
|
+
|
|
49
58
|
## Build + publish
|
|
50
59
|
|
|
51
|
-
- `bun run build` (tsup + `scripts/add-use-client.mjs`) → `dist/`. `bun run typecheck` + `bun run lint` green before commit.
|
|
52
|
-
- `npm pack` → tgz (
|
|
53
|
-
- Bump `version` on
|
|
60
|
+
- `bun run build` (tsup + `scripts/add-use-client.mjs`) → `dist/`. `bun run typecheck` + `bun run lint` + `bun run test` green before commit.
|
|
61
|
+
- `npm pack` → tgz (`021is-brand-studio-<version>.tgz`). Publish destination is **`registry.npmjs.org`** as `@021.is/brand-studio` (verified live for 0.3.0 — earlier note about GitHub Packages is stale). `npm publish` needs Edvard's classic npm token + **his explicit OK** — never auto-publish.
|
|
62
|
+
- Bump `version` on every change; consumers update via `bun add @021.is/brand-studio@<version>`.
|
|
54
63
|
|
|
55
64
|
## Active threads
|
|
56
65
|
|
|
57
|
-
- **v0.
|
|
58
|
-
- **v0.
|
|
66
|
+
- **v0.4.0 (current) — downloads URL contract.** ✅ Added `BrandConfig.downloads` + `buildStandardDownloads()` helper + rewrote `<DownloadSection>` as a URL link grid (open · copy · save). Legacy on-click SVG generator kept as fallback for v0.3.x consumers. zeropost is the reference wiring.
|
|
67
|
+
- **v0.3.0 — generic + MD3.** ✅ Ripped out all zeropost/postal content (icons, mailbox marks, FlagDroop/Stamp motions, forest/cream defaults). Added the MD3 color engine + seed-based `defineBrand`. `private:false`, publishable. Live on npm 2026-06-03.
|
|
68
|
+
- **v0.5.0 — export CLI.** `npx brand-studio export ./brand.config.ts` → icon.svg / apple-icon.png / og.png (satori/resvg). Complements the runtime URL contract for static-export use cases.
|
|
59
69
|
- **v1.0.0 — visual editor + plugin API.**
|
|
60
70
|
|
|
61
71
|
## See
|
package/README.md
CHANGED
|
@@ -54,6 +54,32 @@ export default defineBrand({
|
|
|
54
54
|
|
|
55
55
|
`defineBrand` eagerly resolves `config.scheme` (the full `{ light, dark }` role set) so downstream consumers never wait on a derivation.
|
|
56
56
|
|
|
57
|
+
## Expose the download matrix (mandatory, v0.4+)
|
|
58
|
+
|
|
59
|
+
Every consumer ships a `/brand/download` link grid for the **app icon** and **logo** at **multiple sizes** in **both light and dark** variants. Wire `BrandConfig.downloads` with `buildStandardDownloads(basePath)` and serve the URLs from your host app:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
// brand.config.ts
|
|
63
|
+
import { defineBrand, buildStandardDownloads } from "@021.is/brand-studio/define";
|
|
64
|
+
|
|
65
|
+
export default defineBrand({
|
|
66
|
+
name: "Acme",
|
|
67
|
+
// ... color, type, voice ...
|
|
68
|
+
downloads: buildStandardDownloads({ basePath: "/brand/download" }),
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Default URL shape: `<basePath>/<kind>/<size>/<mode>.<format>`
|
|
73
|
+
Example: `/brand/download/icon/256/light.svg` · `/brand/download/logo/64/dark.svg`
|
|
74
|
+
|
|
75
|
+
Canonical matrix:
|
|
76
|
+
- **Icon** sizes: 64 / 128 / 256 / 512 / 1024 (square edge px)
|
|
77
|
+
- **Logo** sizes: 32 / 48 / 64 / 96 / 128 (height px)
|
|
78
|
+
- Each size in both `light` and `dark`
|
|
79
|
+
- Format: `svg` by default (PNG opt-in via the `formats` option)
|
|
80
|
+
|
|
81
|
+
The host app serves each URL — typically one Next.js route handler that renders the SVG mark sized + recoloured per the path params. Consumers that don't wire `downloads` keep working: the Download section falls back to the v0.3.x on-click SVG-blob generator, with a banner pointing at this section.
|
|
82
|
+
|
|
57
83
|
## Mount the brand page
|
|
58
84
|
|
|
59
85
|
```tsx
|
package/dist/app/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { B as BrandIcon, a as BrandStudio, b as BrandStudioProps } from '../BrandStudio-
|
|
1
|
+
export { B as BrandIcon, a as BrandStudio, b as BrandStudioProps } from '../BrandStudio-D1QR4hIC.js';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { c as BrandStudioSection } from '../types-BycZ2igw.js';
|
|
5
5
|
export { c as contrastBadge, a as contrastRatio, r as relativeLuminance } from '../contrast-TVW3pzdd.js';
|
|
6
6
|
import '../generateScheme-BDDcIzA3.js';
|
|
7
7
|
|
package/dist/app/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { BrandStudio, Navigation, buildNavigation } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
2
|
+
export { BrandStudio, Navigation, buildNavigation } from '../chunk-JGLPUAM6.js';
|
|
3
|
+
import '../chunk-YDZA26YU.js';
|
|
4
|
+
import '../chunk-MDTU2JR5.js';
|
|
4
5
|
export { contrastBadge, contrastRatio, relativeLuminance } from '../chunk-JQV3ASME.js';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DownloadKind, DownloadFormat, DownloadMode } from './chunk-MDTU2JR5.js';
|
|
2
|
+
import { generateScheme } from './chunk-JQV3ASME.js';
|
|
3
|
+
|
|
4
|
+
// src/define/defineBrand.ts
|
|
5
|
+
function defineBrand(config) {
|
|
6
|
+
return { ...config, scheme: config.scheme ?? generateScheme(config.color) };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// src/define/downloads.ts
|
|
10
|
+
var STANDARD_ICON_SIZES = [64, 128, 256, 512, 1024];
|
|
11
|
+
var STANDARD_LOGO_SIZES = [32, 48, 64, 96, 128];
|
|
12
|
+
var KIND_PATH = {
|
|
13
|
+
[DownloadKind.Icon]: "app-icon",
|
|
14
|
+
[DownloadKind.Logo]: "logo"
|
|
15
|
+
};
|
|
16
|
+
function buildStandardDownloads(input) {
|
|
17
|
+
const brand = slugify(input.brand);
|
|
18
|
+
if (!brand) throw new Error("buildStandardDownloads: `brand` is required (non-empty after slug)");
|
|
19
|
+
const basePath = (input.basePath ?? "/brand").replace(/\/+$/, "");
|
|
20
|
+
const iconSizes = input.iconSizes ?? STANDARD_ICON_SIZES;
|
|
21
|
+
const logoSizes = input.logoSizes ?? STANDARD_LOGO_SIZES;
|
|
22
|
+
const formats = input.formats ?? [DownloadFormat.Svg];
|
|
23
|
+
const modes = [DownloadMode.Light, DownloadMode.Dark];
|
|
24
|
+
const items = [];
|
|
25
|
+
for (const kind of [DownloadKind.Icon, DownloadKind.Logo]) {
|
|
26
|
+
const sizes = kind === DownloadKind.Icon ? iconSizes : logoSizes;
|
|
27
|
+
const kindPath = KIND_PATH[kind];
|
|
28
|
+
for (const size of sizes) {
|
|
29
|
+
for (const mode of modes) {
|
|
30
|
+
for (const format of formats) {
|
|
31
|
+
const filename = `${brand}-${size}-${mode}.${format}`;
|
|
32
|
+
items.push({
|
|
33
|
+
kind,
|
|
34
|
+
mode,
|
|
35
|
+
size,
|
|
36
|
+
format,
|
|
37
|
+
url: `${basePath}/${kindPath}/${filename}`,
|
|
38
|
+
filename
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { items };
|
|
45
|
+
}
|
|
46
|
+
function slugify(input) {
|
|
47
|
+
return input.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { STANDARD_ICON_SIZES, STANDARD_LOGO_SIZES, buildStandardDownloads, defineBrand, slugify };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { SpinnerLoadingMark } from './chunk-YDZA26YU.js';
|
|
3
|
+
import { LoadingVariant } from './chunk-MDTU2JR5.js';
|
|
3
4
|
import { motion } from 'framer-motion';
|
|
4
5
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
6
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SpinnerLoadingMark } from './chunk-YDZA26YU.js';
|
|
2
|
+
import { BrandStudioSection, DownloadMode, DownloadKind, DownloadFormat } from './chunk-MDTU2JR5.js';
|
|
2
3
|
import { generateScheme, schemeToCssText, ROLE_GROUPS, contrastBadge, contrastRatio } from './chunk-JQV3ASME.js';
|
|
3
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
5
|
import { useRef, useState } from 'react';
|
|
@@ -178,17 +179,6 @@ function ColorsSection({ scheme }) {
|
|
|
178
179
|
}
|
|
179
180
|
var ICON_SIZES = [64, 128, 256, 512, 1024];
|
|
180
181
|
var WORDMARK_HEIGHTS = [32, 48, 64, 96, 128];
|
|
181
|
-
function triggerDownload(svgString, filename) {
|
|
182
|
-
const blob = new Blob([svgString], { type: "image/svg+xml;charset=utf-8" });
|
|
183
|
-
const url = URL.createObjectURL(blob);
|
|
184
|
-
const a = document.createElement("a");
|
|
185
|
-
a.href = url;
|
|
186
|
-
a.download = filename;
|
|
187
|
-
document.body.appendChild(a);
|
|
188
|
-
a.click();
|
|
189
|
-
a.remove();
|
|
190
|
-
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
191
|
-
}
|
|
192
182
|
function DownloadSection({
|
|
193
183
|
config,
|
|
194
184
|
staticLogo,
|
|
@@ -209,6 +199,11 @@ function DownloadSection({
|
|
|
209
199
|
const darkLabel = scheme.dark.onSurfaceVariant;
|
|
210
200
|
const iconDarkNode = staticLogoDark ?? staticLogo;
|
|
211
201
|
const hasDistinctDark = staticLogoDark !== void 0 && staticLogoDark !== null;
|
|
202
|
+
const downloads = config.downloads?.items ?? [];
|
|
203
|
+
const iconLight = findEntry(downloads, DownloadKind.Icon, DownloadMode.Light, iconSize);
|
|
204
|
+
const iconDark = findEntry(downloads, DownloadKind.Icon, DownloadMode.Dark, iconSize);
|
|
205
|
+
const logoLight = findEntry(downloads, DownloadKind.Logo, DownloadMode.Light, wmHeight);
|
|
206
|
+
const logoDark = findEntry(downloads, DownloadKind.Logo, DownloadMode.Dark, wmHeight);
|
|
212
207
|
function downloadIcon(mode) {
|
|
213
208
|
const ref = mode === "light" ? iconLightRef : iconDarkRef;
|
|
214
209
|
const svg = ref.current?.querySelector("svg");
|
|
@@ -217,7 +212,7 @@ function DownloadSection({
|
|
|
217
212
|
clone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
|
|
218
213
|
clone.setAttribute("width", String(iconSize));
|
|
219
214
|
clone.setAttribute("height", String(iconSize));
|
|
220
|
-
|
|
215
|
+
triggerBlobDownload(
|
|
221
216
|
new XMLSerializer().serializeToString(clone),
|
|
222
217
|
`${config.name}-icon-${iconSize}-${mode}.svg`
|
|
223
218
|
);
|
|
@@ -237,7 +232,7 @@ function DownloadSection({
|
|
|
237
232
|
`<text x="${(pad - bbox.x).toFixed(1)}" y="${pad.toFixed(1)}" dominant-baseline="text-before-edge" font-family="${sans}, system-ui, sans-serif" font-weight="600" font-size="100" letter-spacing="-3" fill="${fill}">${config.name}</text>`,
|
|
238
233
|
"</svg>"
|
|
239
234
|
].join("");
|
|
240
|
-
|
|
235
|
+
triggerBlobDownload(out, `${config.name}-wordmark-${wmHeight}-${mode}.svg`);
|
|
241
236
|
}
|
|
242
237
|
return /* @__PURE__ */ jsxs("section", { children: [
|
|
243
238
|
/* @__PURE__ */ jsx(
|
|
@@ -257,11 +252,11 @@ function DownloadSection({
|
|
|
257
252
|
{
|
|
258
253
|
style: {
|
|
259
254
|
color: "var(--md-on-surface-variant)",
|
|
260
|
-
maxWidth: "
|
|
255
|
+
maxWidth: "44rem",
|
|
261
256
|
margin: "0 0 2.5rem",
|
|
262
257
|
lineHeight: 1.6
|
|
263
258
|
},
|
|
264
|
-
children: "Export the app icon and wordmark as standalone SVGs in light and dark variants. Pick a size, download,
|
|
259
|
+
children: "Export the app icon and wordmark as standalone SVGs in light and dark variants. Pick a size, download, or copy the stable URL beneath the buttons to embed or share."
|
|
265
260
|
}
|
|
266
261
|
),
|
|
267
262
|
/* @__PURE__ */ jsxs(
|
|
@@ -302,6 +297,7 @@ function DownloadSection({
|
|
|
302
297
|
}
|
|
303
298
|
)
|
|
304
299
|
] }),
|
|
300
|
+
iconLight || iconDark ? /* @__PURE__ */ jsx(UrlPair, { light: iconLight, dark: iconDark }) : null,
|
|
305
301
|
staticLogo && !hasDistinctDark ? /* @__PURE__ */ jsxs(Note, { children: [
|
|
306
302
|
"No dark icon supplied \u2014 dark export reuses the light mark. Pass",
|
|
307
303
|
" ",
|
|
@@ -343,7 +339,8 @@ function DownloadSection({
|
|
|
343
339
|
children: "Dark SVG"
|
|
344
340
|
}
|
|
345
341
|
)
|
|
346
|
-
] })
|
|
342
|
+
] }),
|
|
343
|
+
logoLight || logoDark ? /* @__PURE__ */ jsx(UrlPair, { light: logoLight, dark: logoDark }) : null
|
|
347
344
|
] })
|
|
348
345
|
]
|
|
349
346
|
}
|
|
@@ -390,6 +387,122 @@ function DownloadSection({
|
|
|
390
387
|
)
|
|
391
388
|
] });
|
|
392
389
|
}
|
|
390
|
+
function findEntry(items, kind, mode, size) {
|
|
391
|
+
const entry = items.find(
|
|
392
|
+
(it) => it.kind === kind && it.mode === mode && it.size === size && it.format === DownloadFormat.Svg
|
|
393
|
+
);
|
|
394
|
+
return entry ?? null;
|
|
395
|
+
}
|
|
396
|
+
function triggerBlobDownload(svgString, filename) {
|
|
397
|
+
const blob = new Blob([svgString], { type: "image/svg+xml;charset=utf-8" });
|
|
398
|
+
const url = URL.createObjectURL(blob);
|
|
399
|
+
const a = document.createElement("a");
|
|
400
|
+
a.href = url;
|
|
401
|
+
a.download = filename;
|
|
402
|
+
document.body.appendChild(a);
|
|
403
|
+
a.click();
|
|
404
|
+
a.remove();
|
|
405
|
+
window.setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
406
|
+
}
|
|
407
|
+
function UrlPair({ light, dark }) {
|
|
408
|
+
return /* @__PURE__ */ jsxs(
|
|
409
|
+
"div",
|
|
410
|
+
{
|
|
411
|
+
style: {
|
|
412
|
+
marginTop: "0.7rem",
|
|
413
|
+
display: "grid",
|
|
414
|
+
gap: "0.35rem"
|
|
415
|
+
},
|
|
416
|
+
children: [
|
|
417
|
+
/* @__PURE__ */ jsx(UrlRow, { label: "LIGHT", entry: light }),
|
|
418
|
+
/* @__PURE__ */ jsx(UrlRow, { label: "DARK", entry: dark })
|
|
419
|
+
]
|
|
420
|
+
}
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
function UrlRow({ label, entry }) {
|
|
424
|
+
const [copied, setCopied] = useState(false);
|
|
425
|
+
const url = entry?.url ?? null;
|
|
426
|
+
function onCopy() {
|
|
427
|
+
if (!url || typeof navigator === "undefined" || !navigator.clipboard) return;
|
|
428
|
+
navigator.clipboard.writeText(toAbsolute(url)).then(() => {
|
|
429
|
+
setCopied(true);
|
|
430
|
+
window.setTimeout(() => setCopied(false), 1200);
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
const disabled = !url;
|
|
434
|
+
const downloadName = entry?.filename ?? lastSegment(url ?? "");
|
|
435
|
+
return /* @__PURE__ */ jsxs(
|
|
436
|
+
"div",
|
|
437
|
+
{
|
|
438
|
+
style: {
|
|
439
|
+
display: "flex",
|
|
440
|
+
alignItems: "center",
|
|
441
|
+
gap: "0.4rem",
|
|
442
|
+
padding: "0.4rem 0.6rem",
|
|
443
|
+
borderRadius: "0.45rem",
|
|
444
|
+
background: "var(--md-surface-container-low)",
|
|
445
|
+
border: "1px solid var(--md-outline-variant)",
|
|
446
|
+
opacity: disabled ? 0.55 : 1
|
|
447
|
+
},
|
|
448
|
+
children: [
|
|
449
|
+
/* @__PURE__ */ jsx("span", { style: urlLabelStyle, children: label }),
|
|
450
|
+
/* @__PURE__ */ jsx(
|
|
451
|
+
"a",
|
|
452
|
+
{
|
|
453
|
+
href: url ?? "#",
|
|
454
|
+
target: "_blank",
|
|
455
|
+
rel: "noreferrer",
|
|
456
|
+
download: downloadName || void 0,
|
|
457
|
+
style: {
|
|
458
|
+
flex: 1,
|
|
459
|
+
color: "var(--md-on-surface)",
|
|
460
|
+
textDecoration: "none",
|
|
461
|
+
fontFamily: "var(--bs-mono, ui-monospace, monospace)",
|
|
462
|
+
fontSize: "0.74rem",
|
|
463
|
+
letterSpacing: "0.01em",
|
|
464
|
+
minWidth: 0,
|
|
465
|
+
overflow: "hidden",
|
|
466
|
+
textOverflow: "ellipsis",
|
|
467
|
+
whiteSpace: "nowrap",
|
|
468
|
+
pointerEvents: disabled ? "none" : "auto"
|
|
469
|
+
},
|
|
470
|
+
title: url ?? "no URL configured for this size",
|
|
471
|
+
children: url ?? "\u2014"
|
|
472
|
+
}
|
|
473
|
+
),
|
|
474
|
+
/* @__PURE__ */ jsx(
|
|
475
|
+
"button",
|
|
476
|
+
{
|
|
477
|
+
type: "button",
|
|
478
|
+
onClick: onCopy,
|
|
479
|
+
disabled,
|
|
480
|
+
title: "Copy URL",
|
|
481
|
+
style: {
|
|
482
|
+
...copyButtonStyle,
|
|
483
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
484
|
+
},
|
|
485
|
+
children: copied ? "Copied" : "Copy"
|
|
486
|
+
}
|
|
487
|
+
)
|
|
488
|
+
]
|
|
489
|
+
}
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
function lastSegment(url) {
|
|
493
|
+
const noQuery = url.split("?")[0] ?? "";
|
|
494
|
+
const parts = noQuery.split("/");
|
|
495
|
+
return parts[parts.length - 1] ?? "";
|
|
496
|
+
}
|
|
497
|
+
function toAbsolute(url) {
|
|
498
|
+
if (/^https?:\/\//.test(url)) return url;
|
|
499
|
+
if (typeof window === "undefined") return url;
|
|
500
|
+
try {
|
|
501
|
+
return new URL(url, window.location.origin).toString();
|
|
502
|
+
} catch {
|
|
503
|
+
return url;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
393
506
|
var mono = { fontFamily: "var(--bs-mono)" };
|
|
394
507
|
function NoAsset() {
|
|
395
508
|
return /* @__PURE__ */ jsx("span", { style: { color: "var(--md-on-surface-variant)", fontSize: "0.8rem" }, children: "no icon" });
|
|
@@ -518,6 +631,26 @@ var eyebrowStyle = {
|
|
|
518
631
|
color: "var(--md-primary)",
|
|
519
632
|
margin: 0
|
|
520
633
|
};
|
|
634
|
+
var urlLabelStyle = {
|
|
635
|
+
fontFamily: "var(--bs-mono, ui-monospace, monospace)",
|
|
636
|
+
fontSize: "0.62rem",
|
|
637
|
+
letterSpacing: "0.14em",
|
|
638
|
+
textTransform: "uppercase",
|
|
639
|
+
color: "var(--md-on-surface-variant)",
|
|
640
|
+
flexShrink: 0,
|
|
641
|
+
width: "3rem"
|
|
642
|
+
};
|
|
643
|
+
var copyButtonStyle = {
|
|
644
|
+
padding: "0.3rem 0.55rem",
|
|
645
|
+
borderRadius: "0.35rem",
|
|
646
|
+
border: "1px solid var(--md-outline-variant)",
|
|
647
|
+
background: "transparent",
|
|
648
|
+
color: "var(--md-primary)",
|
|
649
|
+
fontFamily: "var(--bs-mono, ui-monospace, monospace)",
|
|
650
|
+
fontSize: "0.68rem",
|
|
651
|
+
fontWeight: 600,
|
|
652
|
+
whiteSpace: "nowrap"
|
|
653
|
+
};
|
|
521
654
|
function buttonStyle(disabled, kind) {
|
|
522
655
|
const isPrimary = kind === "primary";
|
|
523
656
|
return {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var LoadingVariant = {
|
|
3
|
+
Spinner: "spinner",
|
|
4
|
+
Ring: "ring",
|
|
5
|
+
Pulse: "pulse"
|
|
6
|
+
};
|
|
7
|
+
var BrandStudioSection = {
|
|
8
|
+
Overview: "overview",
|
|
9
|
+
Logo: "logo",
|
|
10
|
+
Colors: "colors",
|
|
11
|
+
Typography: "typography",
|
|
12
|
+
Icons: "icons",
|
|
13
|
+
Motion: "motion",
|
|
14
|
+
Download: "download"
|
|
15
|
+
};
|
|
16
|
+
var MotionState = {
|
|
17
|
+
Idle: "idle",
|
|
18
|
+
Loading: "loading",
|
|
19
|
+
Success: "success",
|
|
20
|
+
Empty: "empty"
|
|
21
|
+
};
|
|
22
|
+
var DownloadKind = {
|
|
23
|
+
Icon: "icon",
|
|
24
|
+
Logo: "logo"
|
|
25
|
+
};
|
|
26
|
+
var DownloadMode = {
|
|
27
|
+
Light: "light",
|
|
28
|
+
Dark: "dark"
|
|
29
|
+
};
|
|
30
|
+
var DownloadFormat = {
|
|
31
|
+
Svg: "svg",
|
|
32
|
+
Png: "png"
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export { BrandStudioSection, DownloadFormat, DownloadKind, DownloadMode, LoadingVariant, MotionState };
|
|
@@ -2,27 +2,6 @@
|
|
|
2
2
|
import { motion } from 'framer-motion';
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
|
-
// src/types.ts
|
|
6
|
-
var LoadingVariant = {
|
|
7
|
-
Spinner: "spinner",
|
|
8
|
-
Ring: "ring",
|
|
9
|
-
Pulse: "pulse"
|
|
10
|
-
};
|
|
11
|
-
var BrandStudioSection = {
|
|
12
|
-
Overview: "overview",
|
|
13
|
-
Logo: "logo",
|
|
14
|
-
Colors: "colors",
|
|
15
|
-
Typography: "typography",
|
|
16
|
-
Icons: "icons",
|
|
17
|
-
Motion: "motion",
|
|
18
|
-
Download: "download"
|
|
19
|
-
};
|
|
20
|
-
var MotionState = {
|
|
21
|
-
Idle: "idle",
|
|
22
|
-
Loading: "loading",
|
|
23
|
-
Success: "success",
|
|
24
|
-
Empty: "empty"
|
|
25
|
-
};
|
|
26
5
|
function SpinnerLoadingMark({
|
|
27
6
|
size = 200,
|
|
28
7
|
background = "transparent",
|
|
@@ -81,4 +60,4 @@ function SpinnerLoadingMark({
|
|
|
81
60
|
);
|
|
82
61
|
}
|
|
83
62
|
|
|
84
|
-
export {
|
|
63
|
+
export { SpinnerLoadingMark };
|
package/dist/define/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B as BrandConfig, R as ResolvedBrandConfig } from '../types-
|
|
2
|
-
export {
|
|
1
|
+
import { B as BrandConfig, R as ResolvedBrandConfig, D as DownloadFormat, b as BrandDownloads } from '../types-BycZ2igw.js';
|
|
2
|
+
export { a as BrandDownload, d as BrandType, e as DownloadKind, f as DownloadMode } from '../types-BycZ2igw.js';
|
|
3
3
|
export { B as BrandScheme, C as ColorScheme, a as ColorSpec, H as Hex, d as Role, S as SchemeVariant, g as generateScheme } from '../generateScheme-BDDcIzA3.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -22,4 +22,46 @@ export { B as BrandScheme, C as ColorScheme, a as ColorSpec, H as Hex, d as Role
|
|
|
22
22
|
*/
|
|
23
23
|
declare function defineBrand(config: BrandConfig): ResolvedBrandConfig;
|
|
24
24
|
|
|
25
|
-
export
|
|
25
|
+
/** Canonical icon export sizes — square pixel edges. */
|
|
26
|
+
declare const STANDARD_ICON_SIZES: readonly [64, 128, 256, 512, 1024];
|
|
27
|
+
/** Canonical logo export sizes — pixel heights. */
|
|
28
|
+
declare const STANDARD_LOGO_SIZES: readonly [32, 48, 64, 96, 128];
|
|
29
|
+
type StandardDownloadsInput = {
|
|
30
|
+
/**
|
|
31
|
+
* The brand slug embedded in every URL. Required — this is the SEO win;
|
|
32
|
+
* `/brand/app-icon/zeropost-256-light.svg` indexes far better than
|
|
33
|
+
* `/brand/light.svg`. Pass the lowercased brand name (e.g. `"zeropost"`)
|
|
34
|
+
* or any slug. Auto-slugified to lowercase ASCII + hyphens.
|
|
35
|
+
*/
|
|
36
|
+
brand: string;
|
|
37
|
+
/**
|
|
38
|
+
* Mount path the host app serves the assets under, no trailing slash.
|
|
39
|
+
* Default `/brand`. Full URL shape:
|
|
40
|
+
* `<basePath>/<kind-path>/<brand>-<size>-<mode>.<format>`
|
|
41
|
+
* Example: `/brand/app-icon/zeropost-256-light.svg`
|
|
42
|
+
* Kind paths: `app-icon` (square mark) · `logo` (wordmark).
|
|
43
|
+
*
|
|
44
|
+
* The kind segment never collides with brand-studio's own section routes
|
|
45
|
+
* (`/brand/logo`, `/brand/colors`, …) because assets are two-segment URLs
|
|
46
|
+
* (`/brand/logo/<slug>.svg`) while sections are one-segment (`/brand/logo`).
|
|
47
|
+
* The host route handler at `app/brand/[kind]/[slug]/route.ts` beats the
|
|
48
|
+
* brand-page catch-all for two-segment URLs.
|
|
49
|
+
*/
|
|
50
|
+
basePath?: string;
|
|
51
|
+
/** Icon edges in px. Default `STANDARD_ICON_SIZES`. */
|
|
52
|
+
iconSizes?: readonly number[];
|
|
53
|
+
/** Logo heights in px. Default `STANDARD_LOGO_SIZES`. */
|
|
54
|
+
logoSizes?: readonly number[];
|
|
55
|
+
/** Formats to emit per (kind, size, mode). Default `["svg"]`. */
|
|
56
|
+
formats?: readonly (typeof DownloadFormat)[keyof typeof DownloadFormat][];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Build the canonical icon + logo × {light, dark} × sizes × formats matrix.
|
|
60
|
+
* Every brand-studio consumer ships this (or a superset) so users always have
|
|
61
|
+
* shareable, SEO-friendly URLs to the brand marks.
|
|
62
|
+
*/
|
|
63
|
+
declare function buildStandardDownloads(input: StandardDownloadsInput): BrandDownloads;
|
|
64
|
+
/** Lowercase ASCII, replace non-alphanumeric with hyphens, collapse + trim. */
|
|
65
|
+
declare function slugify(input: string): string;
|
|
66
|
+
|
|
67
|
+
export { BrandConfig, BrandDownloads, DownloadFormat, ResolvedBrandConfig, STANDARD_ICON_SIZES, STANDARD_LOGO_SIZES, type StandardDownloadsInput, buildStandardDownloads, defineBrand, slugify };
|
package/dist/define/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { defineBrand } from '../chunk-
|
|
1
|
+
export { STANDARD_ICON_SIZES, STANDARD_LOGO_SIZES, buildStandardDownloads, defineBrand, slugify } from '../chunk-6J2NFZLN.js';
|
|
2
|
+
export { DownloadFormat, DownloadKind, DownloadMode } from '../chunk-MDTU2JR5.js';
|
|
2
3
|
export { SchemeVariant, generateScheme } from '../chunk-JQV3ASME.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { Disc, DiscProps, Ring, RingProps, Squircle, SquircleProps } from './shapes/index.js';
|
|
2
2
|
export { AppearGrow, AppearGrowProps, Drift, DriftProps, PulseLoop, PulseLoopProps, RingDraw, RingDrawProps, Sequence, SequenceProps, SequenceStep, SequenceStepProps, Strikethrough, StrikethroughProps, Sweep, SweepDirection, SweepProps, Wobble, WobbleProps } from './motion/index.js';
|
|
3
3
|
export { LoadingMark, LoadingMarkProps, PulseLoadingMark, PulseLoadingMarkProps, RingLoadingMark, RingLoadingMarkProps, SpinnerLoadingMark, SpinnerLoadingMarkProps } from './loading/index.js';
|
|
4
|
-
export { B as BrandConfig, a as
|
|
4
|
+
export { B as BrandConfig, a as BrandDownload, b as BrandDownloads, c as BrandStudioSection, d as BrandType, D as DownloadFormat, e as DownloadKind, f as DownloadMode, L as LoadingVariant, M as MotionState, R as ResolvedBrandConfig } from './types-BycZ2igw.js';
|
|
5
5
|
export { B as BrandScheme, C as ColorScheme, a as ColorSpec, H as Hex, R as ROLE, b as ROLE_GROUPS, c as ROLE_ORDER, d as Role, S as SchemeVariant, g as generateScheme } from './generateScheme-BDDcIzA3.js';
|
|
6
6
|
export { cssVarName, schemeToCssText, schemeVars } from './color/index.js';
|
|
7
7
|
export { C as ContrastTier, c as contrastBadge, a as contrastRatio, r as relativeLuminance } from './contrast-TVW3pzdd.js';
|
|
8
|
-
export { a as BrandStudio, b as BrandStudioProps } from './BrandStudio-
|
|
9
|
-
export { defineBrand } from './define/index.js';
|
|
8
|
+
export { a as BrandStudio, b as BrandStudioProps } from './BrandStudio-D1QR4hIC.js';
|
|
9
|
+
export { STANDARD_ICON_SIZES, STANDARD_LOGO_SIZES, StandardDownloadsInput, buildStandardDownloads, defineBrand, slugify } from './define/index.js';
|
|
10
10
|
import 'react/jsx-runtime';
|
|
11
11
|
import 'react';
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
export { Disc, Ring, Squircle } from './chunk-LJ4HZCAP.js';
|
|
3
3
|
export { AppearGrow, Drift, PulseLoop, RingDraw, Sequence, SequenceStep, Strikethrough, Sweep, Wobble } from './chunk-7325RQRP.js';
|
|
4
|
-
export { LoadingMark, PulseLoadingMark, RingLoadingMark } from './chunk-
|
|
5
|
-
export { BrandStudio } from './chunk-
|
|
6
|
-
export {
|
|
7
|
-
export { defineBrand } from './chunk-
|
|
4
|
+
export { LoadingMark, PulseLoadingMark, RingLoadingMark } from './chunk-F4CFQDS7.js';
|
|
5
|
+
export { BrandStudio } from './chunk-JGLPUAM6.js';
|
|
6
|
+
export { SpinnerLoadingMark } from './chunk-YDZA26YU.js';
|
|
7
|
+
export { STANDARD_ICON_SIZES, STANDARD_LOGO_SIZES, buildStandardDownloads, defineBrand, slugify } from './chunk-6J2NFZLN.js';
|
|
8
|
+
export { BrandStudioSection, DownloadFormat, DownloadKind, DownloadMode, LoadingVariant, MotionState } from './chunk-MDTU2JR5.js';
|
|
8
9
|
export { ContrastTier, ROLE, ROLE_GROUPS, ROLE_ORDER, SchemeVariant, contrastBadge, contrastRatio, cssVarName, generateScheme, relativeLuminance, schemeToCssText, schemeVars } from './chunk-JQV3ASME.js';
|
package/dist/loading/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, CSSProperties } from 'react';
|
|
3
|
-
import { L as LoadingVariant } from '../types-
|
|
3
|
+
import { L as LoadingVariant } from '../types-BycZ2igw.js';
|
|
4
4
|
import '../generateScheme-BDDcIzA3.js';
|
|
5
5
|
|
|
6
6
|
type LoadingMarkProps = {
|
package/dist/loading/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { LoadingMark, PulseLoadingMark, RingLoadingMark } from '../chunk-
|
|
3
|
-
export {
|
|
2
|
+
export { LoadingMark, PulseLoadingMark, RingLoadingMark } from '../chunk-F4CFQDS7.js';
|
|
3
|
+
export { SpinnerLoadingMark } from '../chunk-YDZA26YU.js';
|
|
4
|
+
export { LoadingVariant } from '../chunk-MDTU2JR5.js';
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { a as ColorSpec, B as BrandScheme } from './generateScheme-BDDcIzA3.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared types for @021.is/brand-studio.
|
|
5
|
+
*
|
|
6
|
+
* Const-as-object enums (no inline string-literal unions in public signatures).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Generic loading-mark variants. No brand-coded marks live in the lib. */
|
|
10
|
+
declare const LoadingVariant: {
|
|
11
|
+
readonly Spinner: "spinner";
|
|
12
|
+
readonly Ring: "ring";
|
|
13
|
+
readonly Pulse: "pulse";
|
|
14
|
+
};
|
|
15
|
+
type LoadingVariant = (typeof LoadingVariant)[keyof typeof LoadingVariant];
|
|
16
|
+
declare const BrandStudioSection: {
|
|
17
|
+
readonly Overview: "overview";
|
|
18
|
+
readonly Logo: "logo";
|
|
19
|
+
readonly Colors: "colors";
|
|
20
|
+
readonly Typography: "typography";
|
|
21
|
+
readonly Icons: "icons";
|
|
22
|
+
readonly Motion: "motion";
|
|
23
|
+
readonly Download: "download";
|
|
24
|
+
};
|
|
25
|
+
type BrandStudioSection = (typeof BrandStudioSection)[keyof typeof BrandStudioSection];
|
|
26
|
+
declare const MotionState: {
|
|
27
|
+
readonly Idle: "idle";
|
|
28
|
+
readonly Loading: "loading";
|
|
29
|
+
readonly Success: "success";
|
|
30
|
+
readonly Empty: "empty";
|
|
31
|
+
};
|
|
32
|
+
type MotionState = (typeof MotionState)[keyof typeof MotionState];
|
|
33
|
+
/**
|
|
34
|
+
* Mandatory download contract — every brand-studio consumer SHOULD expose its
|
|
35
|
+
* app icon + logo at multiple sizes, in both light- and dark-surface variants,
|
|
36
|
+
* as shareable URLs. The lib renders them as a link grid on `/brand/download`.
|
|
37
|
+
*
|
|
38
|
+
* Host apps wire `BrandConfig.downloads` to a route handler (or static files)
|
|
39
|
+
* that returns the asset. Use `buildStandardDownloads(basePath)` for the
|
|
40
|
+
* canonical 5×2×2 matrix.
|
|
41
|
+
*/
|
|
42
|
+
declare const DownloadKind: {
|
|
43
|
+
readonly Icon: "icon";
|
|
44
|
+
readonly Logo: "logo";
|
|
45
|
+
};
|
|
46
|
+
type DownloadKind = (typeof DownloadKind)[keyof typeof DownloadKind];
|
|
47
|
+
declare const DownloadMode: {
|
|
48
|
+
readonly Light: "light";
|
|
49
|
+
readonly Dark: "dark";
|
|
50
|
+
};
|
|
51
|
+
type DownloadMode = (typeof DownloadMode)[keyof typeof DownloadMode];
|
|
52
|
+
declare const DownloadFormat: {
|
|
53
|
+
readonly Svg: "svg";
|
|
54
|
+
readonly Png: "png";
|
|
55
|
+
};
|
|
56
|
+
type DownloadFormat = (typeof DownloadFormat)[keyof typeof DownloadFormat];
|
|
57
|
+
type BrandDownload = {
|
|
58
|
+
kind: DownloadKind;
|
|
59
|
+
mode: DownloadMode;
|
|
60
|
+
/** Pixel size — square edge for icons, height for logos. */
|
|
61
|
+
size: number;
|
|
62
|
+
/** Asset format. SVG is the canonical export; PNG is optional raster. */
|
|
63
|
+
format: DownloadFormat;
|
|
64
|
+
/** Absolute or root-relative URL the host app serves. */
|
|
65
|
+
url: string;
|
|
66
|
+
/**
|
|
67
|
+
* Filename the user should see when downloading. Used as the
|
|
68
|
+
* `<a download="…">` attribute. Defaults to the URL's last segment.
|
|
69
|
+
*/
|
|
70
|
+
filename?: string;
|
|
71
|
+
/** Optional override for the link label. */
|
|
72
|
+
label?: string;
|
|
73
|
+
};
|
|
74
|
+
type BrandDownloads = {
|
|
75
|
+
/** Linear list of download entries. Order is preserved for the link grid. */
|
|
76
|
+
items: readonly BrandDownload[];
|
|
77
|
+
};
|
|
78
|
+
type BrandType = {
|
|
79
|
+
sans: string;
|
|
80
|
+
mono?: string;
|
|
81
|
+
serif?: string;
|
|
82
|
+
};
|
|
83
|
+
type BrandConfig = {
|
|
84
|
+
/** Brand display name, shown on the overview + exports. */
|
|
85
|
+
name: string;
|
|
86
|
+
/** Short tagline shown on the brand-kit overview. */
|
|
87
|
+
tagline?: string;
|
|
88
|
+
/** Operator legal entity, shown in the brand-kit footer. */
|
|
89
|
+
operator?: string;
|
|
90
|
+
/** Domain (used for "view live" links). */
|
|
91
|
+
domain?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Color spec — a seed (+ optional key colors / overrides) the MD3 engine
|
|
94
|
+
* derives a complete light + dark role set from. See `defineBrand`.
|
|
95
|
+
*/
|
|
96
|
+
color: ColorSpec;
|
|
97
|
+
type: BrandType;
|
|
98
|
+
/** Voice rules, rendered as a bullet list. */
|
|
99
|
+
voice?: readonly string[];
|
|
100
|
+
/**
|
|
101
|
+
* Download URL contract — icon + logo at multiple sizes × {light, dark}.
|
|
102
|
+
* Rendered as a link grid under `/brand/download`. Use
|
|
103
|
+
* `buildStandardDownloads(basePath)` for the canonical matrix or supply
|
|
104
|
+
* explicit entries. When absent, the Download section falls back to
|
|
105
|
+
* on-click SVG-blob generation (legacy behaviour).
|
|
106
|
+
*/
|
|
107
|
+
downloads?: BrandDownloads;
|
|
108
|
+
/**
|
|
109
|
+
* Resolved MD3 light + dark role sets. Populated by `defineBrand`; do not set
|
|
110
|
+
* by hand. Sections read it (and the injected `--md-*` CSS vars) for theming.
|
|
111
|
+
*/
|
|
112
|
+
scheme?: BrandScheme;
|
|
113
|
+
};
|
|
114
|
+
/** A `BrandConfig` after `defineBrand` has resolved its `scheme`. */
|
|
115
|
+
type ResolvedBrandConfig = BrandConfig & {
|
|
116
|
+
scheme: BrandScheme;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export { type BrandConfig as B, DownloadFormat as D, LoadingVariant as L, MotionState as M, type ResolvedBrandConfig as R, type BrandDownload as a, type BrandDownloads as b, BrandStudioSection as c, type BrandType as d, DownloadKind as e, DownloadMode as f };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@021.is/brand-studio",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Generic MD3 brand-kit toolkit: seed → full light + dark role set, composable SVG shapes + motion + loading marks,
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Generic MD3 brand-kit toolkit: seed → full light + dark role set, composable SVG shapes + motion + loading marks, mountable <BrandStudio> /brand page, mandatory icon + logo download-URL contract. Ships no brand content — every app supplies its own logo, icons, and seed colour.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "edvone",
|
package/dist/chunk-QT5N4K7D.js
DELETED
package/dist/types-PWNYyaBF.d.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { a as ColorSpec, B as BrandScheme } from './generateScheme-BDDcIzA3.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shared types for @021.is/brand-studio.
|
|
5
|
-
*
|
|
6
|
-
* Const-as-object enums (no inline string-literal unions in public signatures).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/** Generic loading-mark variants. No brand-coded marks live in the lib. */
|
|
10
|
-
declare const LoadingVariant: {
|
|
11
|
-
readonly Spinner: "spinner";
|
|
12
|
-
readonly Ring: "ring";
|
|
13
|
-
readonly Pulse: "pulse";
|
|
14
|
-
};
|
|
15
|
-
type LoadingVariant = (typeof LoadingVariant)[keyof typeof LoadingVariant];
|
|
16
|
-
declare const BrandStudioSection: {
|
|
17
|
-
readonly Overview: "overview";
|
|
18
|
-
readonly Logo: "logo";
|
|
19
|
-
readonly Colors: "colors";
|
|
20
|
-
readonly Typography: "typography";
|
|
21
|
-
readonly Icons: "icons";
|
|
22
|
-
readonly Motion: "motion";
|
|
23
|
-
readonly Download: "download";
|
|
24
|
-
};
|
|
25
|
-
type BrandStudioSection = (typeof BrandStudioSection)[keyof typeof BrandStudioSection];
|
|
26
|
-
declare const MotionState: {
|
|
27
|
-
readonly Idle: "idle";
|
|
28
|
-
readonly Loading: "loading";
|
|
29
|
-
readonly Success: "success";
|
|
30
|
-
readonly Empty: "empty";
|
|
31
|
-
};
|
|
32
|
-
type MotionState = (typeof MotionState)[keyof typeof MotionState];
|
|
33
|
-
type BrandType = {
|
|
34
|
-
sans: string;
|
|
35
|
-
mono?: string;
|
|
36
|
-
serif?: string;
|
|
37
|
-
};
|
|
38
|
-
type BrandConfig = {
|
|
39
|
-
/** Brand display name, shown on the overview + exports. */
|
|
40
|
-
name: string;
|
|
41
|
-
/** Short tagline shown on the brand-kit overview. */
|
|
42
|
-
tagline?: string;
|
|
43
|
-
/** Operator legal entity, shown in the brand-kit footer. */
|
|
44
|
-
operator?: string;
|
|
45
|
-
/** Domain (used for "view live" links). */
|
|
46
|
-
domain?: string;
|
|
47
|
-
/**
|
|
48
|
-
* Color spec — a seed (+ optional key colors / overrides) the MD3 engine
|
|
49
|
-
* derives a complete light + dark role set from. See `defineBrand`.
|
|
50
|
-
*/
|
|
51
|
-
color: ColorSpec;
|
|
52
|
-
type: BrandType;
|
|
53
|
-
/** Voice rules, rendered as a bullet list. */
|
|
54
|
-
voice?: readonly string[];
|
|
55
|
-
/**
|
|
56
|
-
* Resolved MD3 light + dark role sets. Populated by `defineBrand`; do not set
|
|
57
|
-
* by hand. Sections read it (and the injected `--md-*` CSS vars) for theming.
|
|
58
|
-
*/
|
|
59
|
-
scheme?: BrandScheme;
|
|
60
|
-
};
|
|
61
|
-
/** A `BrandConfig` after `defineBrand` has resolved its `scheme`. */
|
|
62
|
-
type ResolvedBrandConfig = BrandConfig & {
|
|
63
|
-
scheme: BrandScheme;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export { type BrandConfig as B, LoadingVariant as L, MotionState as M, type ResolvedBrandConfig as R, BrandStudioSection as a, type BrandType as b };
|