@brunosouzas/design-system 0.5.3 → 0.6.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.
- package/README.md +15 -2
- package/dist/src/pieces/bank-objects.d.ts +12 -0
- package/dist/src/pieces/bank-objects.js +44 -0
- package/dist/src/pieces/brand-cast.d.ts +72 -0
- package/dist/src/pieces/brand-cast.js +163 -0
- package/dist/src/pieces/brand-notation-icons.d.ts +12 -0
- package/dist/src/pieces/brand-notation-icons.js +79 -0
- package/dist/src/pieces/category-icon.d.ts +12 -0
- package/dist/src/pieces/category-icon.js +26 -0
- package/dist/src/pieces/cover.d.ts +37 -5
- package/dist/src/pieces/cover.js +81 -11
- package/dist/src/pieces/index.d.ts +5 -0
- package/dist/src/pieces/index.js +4 -0
- package/dist/src/pieces/library.d.ts +16 -1
- package/dist/src/pieces/library.js +15 -1
- package/dist/src/pieces/node.d.ts +1 -1
- package/dist/src/pieces/node.js +1 -0
- package/dist/src/pieces/skin.d.ts +22 -0
- package/dist/src/pieces/skin.js +13 -0
- package/dist/src/pieces/symbol.d.ts +9 -0
- package/dist/src/pieces/symbol.js +20 -0
- package/dist/tokens/generated/tokens.d.ts +63 -0
- package/dist/tokens/generated/tokens.js +63 -0
- package/package.json +1 -1
- package/tokens/generated/tokens.css +47 -0
- package/tokens/generated/tokens.json +63 -0
- package/tokens/generated/tokens.ts +63 -0
package/dist/src/pieces/cover.js
CHANGED
|
@@ -12,14 +12,23 @@ import { tokens } from "../../tokens/generated/tokens.js";
|
|
|
12
12
|
import { PIECE_NAMES, PIECES, rings } from "./library.js";
|
|
13
13
|
import { EIP_ICON_HEIGHT, EIP_ICON_WIDTH, EIP_ICONS } from "./eip-icons.js";
|
|
14
14
|
import { LINK_ICON_SIZE } from "./link-icons.js";
|
|
15
|
+
import { mira } from "./brand-cast.js";
|
|
16
|
+
import { symbol } from "./symbol.js";
|
|
15
17
|
import { el, g, r2 } from "./node.js";
|
|
16
18
|
import { UI_ICON_SIZE } from "./ui-icons.js";
|
|
17
19
|
import { COLOUR_TOKENS, CURRENT_COLOUR, checkParams, isColourLiteral, MAX_SIZE, PATH_DATA } from "./params.js";
|
|
18
20
|
export const SAFE_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
19
|
-
const TOP_LEVEL = ["id", "title", "description", "format", "background", "rings", "pieces", "custom", "customAt", "height", "text"];
|
|
20
|
-
/** Cover (800x420, the default), banner (1200x420, rounded corners), body diagram (560 laid out, 800 shown)
|
|
21
|
-
*
|
|
22
|
-
|
|
21
|
+
const TOP_LEVEL = ["id", "title", "description", "format", "background", "rings", "pieces", "custom", "customAt", "height", "text", "signature"];
|
|
22
|
+
/** Cover (800x420, the default), banner (1200x420, rounded corners), body diagram (560 laid out, 800 shown),
|
|
23
|
+
* icon, favicon (the symbol, both themes), linkedin-card (1080x1080) or avatar (500x500, the symbol only):
|
|
24
|
+
* spec cover-cli, "Banner output", "Diagram output", "Icon output", "New icon formats". */
|
|
25
|
+
export const FORMATS = ["cover", "banner", "diagram", "icon", "favicon", "linkedin-card", "og", "avatar"];
|
|
26
|
+
/** Fixed frame sizes of the platform-shaped formats (not style, so not tokens — like EIP_ICON_WIDTH). */
|
|
27
|
+
export const FAVICON_SIZE = 32;
|
|
28
|
+
export const AVATAR_SIZE = 500;
|
|
29
|
+
export const LINKEDIN_CARD_SIZE = 1080;
|
|
30
|
+
export const OG_WIDTH = 1200;
|
|
31
|
+
export const OG_HEIGHT = 630;
|
|
23
32
|
const CUSTOM_TAGS = ["g", "rect", "circle", "ellipse", "line", "polyline", "polygon", "path", "text"];
|
|
24
33
|
// Attributes a free-form object may use (design §6): geometry, paint, text and transform.
|
|
25
34
|
const CUSTOM_ATTRS = new Set([
|
|
@@ -323,10 +332,21 @@ const validateResolved = (spec) => {
|
|
|
323
332
|
if (spec[key] !== undefined)
|
|
324
333
|
blocked.push(key);
|
|
325
334
|
}
|
|
335
|
+
else if (format === "favicon" || format === "avatar") {
|
|
336
|
+
for (const key of ["background", "rings", "custom", "customAt", "height", "signature"]) {
|
|
337
|
+
if (spec[key] !== undefined)
|
|
338
|
+
out.push({ path: key, message: `not used by the ${format} format` });
|
|
339
|
+
}
|
|
340
|
+
for (const key of ["background", "rings", "custom"])
|
|
341
|
+
if (spec[key] !== undefined)
|
|
342
|
+
blocked.push(key);
|
|
343
|
+
}
|
|
326
344
|
else {
|
|
327
345
|
if (format === "diagram") {
|
|
328
346
|
if (spec.background !== undefined)
|
|
329
347
|
out.push({ path: "background", message: "a diagram is drawn on color.panel; background is for covers and banners" });
|
|
348
|
+
if (spec.signature !== undefined)
|
|
349
|
+
out.push({ path: "signature", message: "not used by the diagram format" });
|
|
330
350
|
const height = spec.height;
|
|
331
351
|
if (typeof height !== "number" || !Number.isFinite(height) || height < 1 || height > MAX_SIZE)
|
|
332
352
|
out.push({ path: "height", message: `expected a number from 1 to ${MAX_SIZE}` });
|
|
@@ -337,6 +357,8 @@ const validateResolved = (spec) => {
|
|
|
337
357
|
}
|
|
338
358
|
if (spec.height !== undefined)
|
|
339
359
|
out.push({ path: "height", message: "only a diagram takes a height" });
|
|
360
|
+
if (spec.signature !== undefined && typeof spec.signature !== "boolean")
|
|
361
|
+
out.push({ path: "signature", message: "expected true or false" });
|
|
340
362
|
}
|
|
341
363
|
checkRings(spec, out);
|
|
342
364
|
if (!isPlainObject(spec.rings) && spec.rings !== undefined)
|
|
@@ -364,9 +386,12 @@ const validateResolved = (spec) => {
|
|
|
364
386
|
}
|
|
365
387
|
}
|
|
366
388
|
if (!Array.isArray(pieces)) {
|
|
367
|
-
|
|
368
|
-
if (
|
|
369
|
-
|
|
389
|
+
const piecesOptional = (format === "favicon" || format === "avatar") && pieces === undefined;
|
|
390
|
+
if (!piecesOptional) {
|
|
391
|
+
out.push({ path: "pieces", message: "missing or not an array" });
|
|
392
|
+
if (pieces !== undefined)
|
|
393
|
+
blocked.push("pieces");
|
|
394
|
+
}
|
|
370
395
|
}
|
|
371
396
|
else if (format === "icon") {
|
|
372
397
|
const entry = pieces[0];
|
|
@@ -382,6 +407,12 @@ const validateResolved = (spec) => {
|
|
|
382
407
|
checkEntry(piece, { ...params, x: 0, y: 0 }, "pieces[0]", out);
|
|
383
408
|
}
|
|
384
409
|
}
|
|
410
|
+
else if (format === "favicon" || format === "avatar") {
|
|
411
|
+
if (pieces.length > 0) {
|
|
412
|
+
out.push({ path: "pieces", message: `not used by the ${format} format` });
|
|
413
|
+
blocked.push("pieces");
|
|
414
|
+
}
|
|
415
|
+
}
|
|
385
416
|
else {
|
|
386
417
|
for (let index = 0; index < pieces.length; index++) {
|
|
387
418
|
const entry = pieces[index];
|
|
@@ -495,23 +526,62 @@ const diagramTree = (spec) => {
|
|
|
495
526
|
const drawnPieces = spec.pieces.map(draw);
|
|
496
527
|
return root(spec.id, tokens.bodyDiagram.width, r2(height / LAYOUT_SCALE), `0 0 ${width} ${height}`, el("title", { id: `${spec.id}-title` }, spec.title), el("desc", { id: `${spec.id}-desc` }, spec.description), el("defs", {}, el("clipPath", { id: `${spec.id}-frame` }, el("rect", { width, height, rx }))), el("rect", { width, height, rx, fill: tokens.color.panel }), g({ "clip-path": frame }, g({ fill: "none", stroke: tokens.color.ring, "stroke-width": r2(ring.width) }, ...Array.from({ length: ring.count }, (_, i) => el("circle", { cx: spec.rings.cx, cy: spec.rings.cy, r: r2(ring.radius + i * ring.step) })))), g({ "clip-path": frame }, g({ stroke: tokens.color.ink, "stroke-width": tokens.map.outline, "stroke-linejoin": "round" }, ...bodies(spec, drawnPieces)), g({ "font-size": tokens.map.labelSize, "font-weight": tokens.cover.labelWeight, fill: tokens.color.ink, "text-anchor": "middle" }, ...drawnPieces.flatMap((d) => d.text))));
|
|
497
528
|
};
|
|
498
|
-
/**
|
|
529
|
+
/** Mira (scale 0.25) and the symbol, bottom-right corner, `cover.signatureMargin` from both edges (spec cover-cli, "Signature lockup"). */
|
|
530
|
+
const signatureGroup = (width, height) => {
|
|
531
|
+
const margin = tokens.cover.signatureMargin;
|
|
532
|
+
const miraScale = 0.25;
|
|
533
|
+
// Mira's own viewBox (sheet7.py's VB): 220 wide, 175 tall, ground at the box's bottom.
|
|
534
|
+
const miraWidth = 220 * miraScale;
|
|
535
|
+
const miraHeight = 175 * miraScale;
|
|
536
|
+
const symbolSize = 24;
|
|
537
|
+
const gap = 6;
|
|
538
|
+
const groupWidth = miraWidth + gap + symbolSize;
|
|
539
|
+
const groupHeight = Math.max(miraHeight, symbolSize);
|
|
540
|
+
const left = width - margin - groupWidth;
|
|
541
|
+
const top = height - margin - groupHeight;
|
|
542
|
+
return g({ "data-piece": "signature" }, ...mira({ x: r2(left + miraWidth / 2), y: r2(top + miraHeight), scale: miraScale }).body, ...symbol({ x: r2(left + miraWidth + gap), y: r2(top + (groupHeight - symbolSize) / 2), scale: symbolSize / 32 }).body);
|
|
543
|
+
};
|
|
544
|
+
/** A favicon (spec cover-cli, "New icon formats"): the symbol, both themes, switched by `prefers-color-scheme`. */
|
|
545
|
+
const faviconTree = (spec) => {
|
|
546
|
+
const size = FAVICON_SIZE;
|
|
547
|
+
return root(spec.id, size, size, `0 0 ${size} ${size}`, el("title", { id: `${spec.id}-title` }, spec.title), el("desc", { id: `${spec.id}-desc` }, spec.description), el("style", {}, `.ds-favicon-dark{display:none}@media (prefers-color-scheme:dark){.ds-favicon-light{display:none}.ds-favicon-dark{display:inline}}`), g({ class: "ds-favicon-light" }, ...symbol({ x: 0, y: 0, surface: "light" }).body), g({ class: "ds-favicon-dark" }, ...symbol({ x: 0, y: 0, surface: "dark" }).body));
|
|
548
|
+
};
|
|
549
|
+
/** An avatar (spec cover-cli, "New icon formats"): the symbol only, filling the frame. */
|
|
550
|
+
const avatarTree = (spec) => {
|
|
551
|
+
const size = AVATAR_SIZE;
|
|
552
|
+
const scale = size / 32;
|
|
553
|
+
return root(spec.id, size, size, `0 0 ${size} ${size}`, el("title", { id: `${spec.id}-title` }, spec.title), el("desc", { id: `${spec.id}-desc` }, spec.description), el("rect", { width: size, height: size, fill: tokens.brand.light.accentText }), g({ transform: `scale(${scale})` }, ...symbol({ x: 0, y: 0, surface: "light" }).body));
|
|
554
|
+
};
|
|
555
|
+
/** The cover's (banner's, diagram's, icon's, favicon's, avatar's) node tree. The spec must be valid for `lang` (validateCoverSpec returned no problem). */
|
|
499
556
|
export const coverTree = (input, options = {}) => {
|
|
500
557
|
const spec = forLanguage(input, options.lang);
|
|
501
558
|
if (spec.format === "icon")
|
|
502
559
|
return iconTree(spec);
|
|
503
560
|
if (spec.format === "diagram")
|
|
504
561
|
return diagramTree(spec);
|
|
562
|
+
if (spec.format === "favicon")
|
|
563
|
+
return faviconTree(spec);
|
|
564
|
+
if (spec.format === "avatar")
|
|
565
|
+
return avatarTree(spec);
|
|
505
566
|
const banner = spec.format === "banner";
|
|
506
|
-
const
|
|
507
|
-
|
|
567
|
+
const linkedinCard = spec.format === "linkedin-card";
|
|
568
|
+
const og = spec.format === "og";
|
|
569
|
+
const { width, height } = linkedinCard
|
|
570
|
+
? { width: LINKEDIN_CARD_SIZE, height: LINKEDIN_CARD_SIZE }
|
|
571
|
+
: og
|
|
572
|
+
? { width: OG_WIDTH, height: OG_HEIGHT }
|
|
573
|
+
: banner
|
|
574
|
+
? tokens.banner
|
|
575
|
+
: tokens.cover;
|
|
576
|
+
// A banner's corners are rounded; a cover, a LinkedIn card and an og image keep the square frame, attribute for attribute.
|
|
508
577
|
const corner = banner ? { rx: tokens.banner.radius } : {};
|
|
509
578
|
const pair = tokens.coverBackground[spec.background];
|
|
510
579
|
const drawnPieces = spec.pieces.map(draw);
|
|
511
580
|
const ringPath = `coverBackground.${spec.background}.ring`;
|
|
512
581
|
const ringCount = banner ? { count: bannerRingCount(spec.rings.cx, spec.rings.cy, spec.rings.radius) } : {};
|
|
513
582
|
const frame = `url(#${spec.id}-frame)`;
|
|
514
|
-
const
|
|
583
|
+
const signature = spec.signature ? signatureGroup(width, height) : null;
|
|
584
|
+
const outlined = g({ stroke: tokens.color.ink, "stroke-width": tokens.outline.block, "stroke-linejoin": "round" }, ...bodies(spec, drawnPieces), signature);
|
|
515
585
|
const labels = g({ "font-size": tokens.cover.labelSize, "font-weight": tokens.cover.labelWeight, fill: tokens.color.ink, "text-anchor": "middle" }, ...drawnPieces.flatMap((d) => d.text));
|
|
516
586
|
return root(spec.id, width, height, `0 0 ${width} ${height}`, el("title", { id: `${spec.id}-title` }, spec.title), el("desc", { id: `${spec.id}-desc` }, spec.description), el("defs", {}, el("clipPath", { id: `${spec.id}-frame` }, el("rect", { width, height, ...corner }))), el("rect", { width, height, ...corner, fill: pair.fill }), g({ "clip-path": frame }, ...rings({ ...spec.rings, color: ringPath, ...ringCount }).body),
|
|
517
587
|
// On a banner, pieces and labels are clipped too, so nothing pokes past a rounded corner.
|
|
@@ -8,3 +8,8 @@ export { EIP_ICONS, EIP_ICON_NAMES, EIP_ICON_HEIGHT, EIP_ICON_WIDTH, type EipIco
|
|
|
8
8
|
export { FORMATS, LANGUAGE, SAFE_ID, backgroundNames, bannerRingCount, comparePaths, coverTree, diagramRings, validateCoverSpec, type CoverFormat, type CoverOptions, type CoverPiece, type CoverRings, type CoverSpec, type CustomNode } from "./cover.ts";
|
|
9
9
|
export { tokens, type Tokens } from "../../tokens/generated/tokens.ts";
|
|
10
10
|
export { EMOTE_KINDS, MASCOTS, MASCOT_ACTIONS, MASCOT_FACES, type EmoteKind, type EmoteParams, type MascotAction, type MascotFace, type MascotName, type MascotParams } from "./cast.ts";
|
|
11
|
+
export { CAST_EXPRESSIONS, CAST_VIEWS, type CastExpression, type CastView, type MiraParams, type VisorParams, type DroneParams, type KiuParams, type SinalParams } from "./brand-cast.ts";
|
|
12
|
+
export { BANK_OBJECT_NAMES, type BankObjectName, type BankObjectParams } from "./bank-objects.ts";
|
|
13
|
+
export { type SymbolParams } from "./symbol.ts";
|
|
14
|
+
export { BRAND_NOTATION_ICON_NAMES, type BrandNotationIconName, type BrandNotationIconParams } from "./brand-notation-icons.ts";
|
|
15
|
+
export { CATEGORY_ICON_NAMES, type CategoryIconName, type CategoryIconParams } from "./category-icon.ts";
|
package/dist/src/pieces/index.js
CHANGED
|
@@ -13,3 +13,7 @@ export { EIP_ICONS, EIP_ICON_NAMES, EIP_ICON_HEIGHT, EIP_ICON_WIDTH } from "./ei
|
|
|
13
13
|
export { FORMATS, LANGUAGE, SAFE_ID, backgroundNames, bannerRingCount, comparePaths, coverTree, diagramRings, validateCoverSpec } from "./cover.js";
|
|
14
14
|
export { tokens } from "../../tokens/generated/tokens.js";
|
|
15
15
|
export { EMOTE_KINDS, MASCOTS, MASCOT_ACTIONS, MASCOT_FACES } from "./cast.js";
|
|
16
|
+
export { CAST_EXPRESSIONS, CAST_VIEWS } from "./brand-cast.js";
|
|
17
|
+
export { BANK_OBJECT_NAMES } from "./bank-objects.js";
|
|
18
|
+
export { BRAND_NOTATION_ICON_NAMES } from "./brand-notation-icons.js";
|
|
19
|
+
export { CATEGORY_ICON_NAMES } from "./category-icon.js";
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { emote, mascot } from "./cast.ts";
|
|
2
|
-
|
|
2
|
+
import { mira, visor, drone, kiu, sinal, type MiraParams, type VisorParams, type DroneParams, type KiuParams, type SinalParams } from "./brand-cast.ts";
|
|
3
|
+
import { bankObject, type BankObjectName, type BankObjectParams } from "./bank-objects.ts";
|
|
4
|
+
import { symbol, type SymbolParams } from "./symbol.ts";
|
|
5
|
+
import { brandNotationIcon, type BrandNotationIconName, type BrandNotationIconParams } from "./brand-notation-icons.ts";
|
|
6
|
+
import { categoryIcon, type CategoryIconParams } from "./category-icon.ts";
|
|
7
|
+
export { emote, mascot, mira, visor, drone, kiu, sinal, bankObject, symbol, brandNotationIcon, categoryIcon };
|
|
8
|
+
export type { MiraParams, VisorParams, DroneParams, KiuParams, SinalParams, BankObjectName, BankObjectParams, SymbolParams, BrandNotationIconName, BrandNotationIconParams, CategoryIconParams };
|
|
3
9
|
export * from "./metro.ts";
|
|
4
10
|
export * from "./diagram.ts";
|
|
5
11
|
export * from "./ui-icons.ts";
|
|
@@ -332,6 +338,15 @@ export declare const PIECES: {
|
|
|
332
338
|
readonly stateStart: import("./piece.ts").Piece<import("./diagram.ts").StateStartParams>;
|
|
333
339
|
readonly mascot: import("./piece.ts").Piece<import("./cast.ts").MascotParams>;
|
|
334
340
|
readonly emote: import("./piece.ts").Piece<import("./cast.ts").EmoteParams>;
|
|
341
|
+
readonly mira: import("./piece.ts").Piece<MiraParams>;
|
|
342
|
+
readonly visor: import("./piece.ts").Piece<VisorParams>;
|
|
343
|
+
readonly drone: import("./piece.ts").Piece<DroneParams>;
|
|
344
|
+
readonly kiu: import("./piece.ts").Piece<KiuParams>;
|
|
345
|
+
readonly sinal: import("./piece.ts").Piece<SinalParams>;
|
|
346
|
+
readonly bankObject: import("./piece.ts").Piece<BankObjectParams>;
|
|
347
|
+
readonly symbol: import("./piece.ts").Piece<SymbolParams>;
|
|
348
|
+
readonly brandNotationIcon: import("./piece.ts").Piece<BrandNotationIconParams>;
|
|
349
|
+
readonly categoryIcon: import("./piece.ts").Piece<CategoryIconParams>;
|
|
335
350
|
};
|
|
336
351
|
export type PieceName = keyof typeof PIECES;
|
|
337
352
|
export declare const PIECE_NAMES: PieceName[];
|
|
@@ -16,8 +16,13 @@ import { DIAGRAM_PIECES, stateStart } from "./diagram.js";
|
|
|
16
16
|
import { uiIcon } from "./ui-icons.js";
|
|
17
17
|
import { linkIcon } from "./link-icons.js";
|
|
18
18
|
import { emote, mascot } from "./cast.js";
|
|
19
|
+
import { mira, visor, drone, kiu, sinal } from "./brand-cast.js";
|
|
20
|
+
import { bankObject } from "./bank-objects.js";
|
|
21
|
+
import { symbol } from "./symbol.js";
|
|
22
|
+
import { brandNotationIcon } from "./brand-notation-icons.js";
|
|
23
|
+
import { categoryIcon } from "./category-icon.js";
|
|
19
24
|
import { codeLength, spans } from "./ink.js";
|
|
20
|
-
export { emote, mascot };
|
|
25
|
+
export { emote, mascot, mira, visor, drone, kiu, sinal, bankObject, symbol, brandNotationIcon, categoryIcon };
|
|
21
26
|
export * from "./metro.js";
|
|
22
27
|
export * from "./diagram.js";
|
|
23
28
|
export * from "./ui-icons.js";
|
|
@@ -397,5 +402,14 @@ export const PIECES = {
|
|
|
397
402
|
stateStart,
|
|
398
403
|
mascot,
|
|
399
404
|
emote,
|
|
405
|
+
mira,
|
|
406
|
+
visor,
|
|
407
|
+
drone,
|
|
408
|
+
kiu,
|
|
409
|
+
sinal,
|
|
410
|
+
bankObject,
|
|
411
|
+
symbol,
|
|
412
|
+
brandNotationIcon,
|
|
413
|
+
categoryIcon,
|
|
400
414
|
};
|
|
401
415
|
export const PIECE_NAMES = Object.keys(PIECES);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const SVG_TAGS: readonly ["svg", "g", "title", "desc", "defs", "clipPath", "rect", "circle", "ellipse", "line", "polyline", "polygon", "path", "text", "tspan"];
|
|
1
|
+
export declare const SVG_TAGS: readonly ["svg", "g", "title", "desc", "defs", "clipPath", "style", "rect", "circle", "ellipse", "line", "polyline", "polygon", "path", "text", "tspan"];
|
|
2
2
|
export type SvgTag = (typeof SVG_TAGS)[number];
|
|
3
3
|
export type AttrValue = string | number;
|
|
4
4
|
export type Attrs = Readonly<Record<string, AttrValue>>;
|
package/dist/src/pieces/node.js
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type SurfaceName } from "./ink.ts";
|
|
2
|
+
export type Skin = {
|
|
3
|
+
readonly body: string;
|
|
4
|
+
readonly outline: string;
|
|
5
|
+
readonly visor: string;
|
|
6
|
+
readonly eye: string;
|
|
7
|
+
readonly accent: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The cast's resolved colours for one surface. The visor is deliberately not
|
|
11
|
+
* the mirror of the outline: the approved sheets keep the screen face
|
|
12
|
+
* near-black in both themes (contrast against the white body), so dark-theme
|
|
13
|
+
* visor reads `brand.dark.bg`, not the light cream `brand.dark.text`.
|
|
14
|
+
*/
|
|
15
|
+
export declare const skin: (surface: SurfaceName) => Skin;
|
|
16
|
+
/** `fill`/`stroke`/`stroke-width`/`stroke-linejoin` for an outlined body shape (the sheets' `ob()`). */
|
|
17
|
+
export declare const outlined: (s: Skin, width?: number) => {
|
|
18
|
+
fill: string;
|
|
19
|
+
stroke: string;
|
|
20
|
+
"stroke-width": number;
|
|
21
|
+
"stroke-linejoin": "round";
|
|
22
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { colour } from "./params.js";
|
|
2
|
+
const c = (path) => colour(path);
|
|
3
|
+
/**
|
|
4
|
+
* The cast's resolved colours for one surface. The visor is deliberately not
|
|
5
|
+
* the mirror of the outline: the approved sheets keep the screen face
|
|
6
|
+
* near-black in both themes (contrast against the white body), so dark-theme
|
|
7
|
+
* visor reads `brand.dark.bg`, not the light cream `brand.dark.text`.
|
|
8
|
+
*/
|
|
9
|
+
export const skin = (surface) => surface === "light"
|
|
10
|
+
? { body: c("color.white"), outline: c("brand.light.text"), visor: c("brand.light.text"), eye: c("cast.eyes"), accent: c("brand.light.accent") }
|
|
11
|
+
: { body: c("color.white"), outline: c("brand.dark.textMuted"), visor: c("brand.dark.bg"), eye: c("cast.eyes"), accent: c("brand.dark.accent") };
|
|
12
|
+
/** `fill`/`stroke`/`stroke-width`/`stroke-linejoin` for an outlined body shape (the sheets' `ob()`). */
|
|
13
|
+
export const outlined = (s, width = 8) => ({ fill: s.body, stroke: s.outline, "stroke-width": width, "stroke-linejoin": "round" });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type SurfaceName } from "./ink.ts";
|
|
2
|
+
export type SymbolParams = {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
surface?: SurfaceName;
|
|
6
|
+
scale?: number;
|
|
7
|
+
};
|
|
8
|
+
/** The brand symbol ("b" with a moon, I5), in a 32×32 box before `scale`. Favicon and avatar are built from this. */
|
|
9
|
+
export declare const symbol: import("./piece.ts").Piece<SymbolParams>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// The brand symbol: the "b" with a moon (identity studio I5): the haste and
|
|
2
|
+
// the ring read as a lowercase b, the moon sits on the accent of the ring.
|
|
3
|
+
// Ported from `~/.hermes/cache/scratch/ab267/board4.py`'s `bmoon()`, the
|
|
4
|
+
// approved source (reused unchanged by every later script, through `final.py`).
|
|
5
|
+
import { drawn, el, g } from "./node.js";
|
|
6
|
+
import { surfaceParam } from "./ink.js";
|
|
7
|
+
import { pos, num } from "./params.js";
|
|
8
|
+
import { definePiece } from "./piece.js";
|
|
9
|
+
import { colour } from "./params.js";
|
|
10
|
+
const c = (path) => colour(path);
|
|
11
|
+
const drawSymbol = (p) => {
|
|
12
|
+
const light = (p.surface ?? "light") === "light";
|
|
13
|
+
const color = light ? c("brand.light.text") : c("brand.dark.text");
|
|
14
|
+
const moon = light ? c("brand.light.accent") : c("brand.dark.accent");
|
|
15
|
+
const scale = p.scale ?? 1; // size is in the 32×32 glyph box, scaled like any other piece
|
|
16
|
+
const body = g({ transform: `translate(${p.x} ${p.y}) scale(${scale})` }, el("rect", { x: 5, y: 3, width: 5.5, height: 26, rx: 2.75, fill: color }), el("circle", { cx: 17.5, cy: 20.5, r: 7.3, fill: "none", stroke: color, "stroke-width": 4.6 }), el("circle", { cx: 27.5, cy: 9, r: 2.8, fill: moon }));
|
|
17
|
+
return drawn([body]);
|
|
18
|
+
};
|
|
19
|
+
/** The brand symbol ("b" with a moon, I5), in a 32×32 box before `scale`. Favicon and avatar are built from this. */
|
|
20
|
+
export const symbol = definePiece("symbol", { x: pos(), y: pos(), surface: surfaceParam, scale: num({ min: 0.1, max: 20 }) }, drawSymbol);
|
|
@@ -11,6 +11,42 @@ export declare const tokens: {
|
|
|
11
11
|
readonly startRadius: 11;
|
|
12
12
|
readonly width: 800;
|
|
13
13
|
};
|
|
14
|
+
readonly brand: {
|
|
15
|
+
readonly dark: {
|
|
16
|
+
readonly accent: "#FF7A45";
|
|
17
|
+
readonly accentText: "#FF7A45";
|
|
18
|
+
readonly bg: "#121110";
|
|
19
|
+
readonly border: "#3B3834";
|
|
20
|
+
readonly borderStrong: "#ADA79D";
|
|
21
|
+
readonly cardBg: "#1D1C1A";
|
|
22
|
+
readonly failure: "#FF6696";
|
|
23
|
+
readonly onAccent: "#121110";
|
|
24
|
+
readonly success: "#5BBF86";
|
|
25
|
+
readonly text: "#F1EEE8";
|
|
26
|
+
readonly textMuted: "#ADA79D";
|
|
27
|
+
readonly trackAi: "#1B1F28";
|
|
28
|
+
readonly trackDelivery: "#18231D";
|
|
29
|
+
readonly trackIntegration: "#2A1C15";
|
|
30
|
+
readonly warning: "#EBB34B";
|
|
31
|
+
};
|
|
32
|
+
readonly light: {
|
|
33
|
+
readonly accent: "#E04E17";
|
|
34
|
+
readonly accentText: "#B83A0C";
|
|
35
|
+
readonly bg: "#F6F3EC";
|
|
36
|
+
readonly border: "#D7D1C5";
|
|
37
|
+
readonly borderStrong: "#5C5852";
|
|
38
|
+
readonly cardBg: "#FFFFFF";
|
|
39
|
+
readonly failure: "#A1124B";
|
|
40
|
+
readonly onAccent: "#FFFFFF";
|
|
41
|
+
readonly success: "#2B7A4B";
|
|
42
|
+
readonly text: "#121212";
|
|
43
|
+
readonly textMuted: "#5C5852";
|
|
44
|
+
readonly trackAi: "#E2E4EC";
|
|
45
|
+
readonly trackDelivery: "#DFE8E1";
|
|
46
|
+
readonly trackIntegration: "#F4E4D8";
|
|
47
|
+
readonly warning: "#8F5F00";
|
|
48
|
+
};
|
|
49
|
+
};
|
|
14
50
|
readonly cast: {
|
|
15
51
|
readonly agent: {
|
|
16
52
|
readonly neck: "#E3E8F5";
|
|
@@ -40,6 +76,7 @@ export declare const tokens: {
|
|
|
40
76
|
readonly mass: 0.7;
|
|
41
77
|
readonly stiffness: 170;
|
|
42
78
|
};
|
|
79
|
+
readonly eyes: "#FFC98A";
|
|
43
80
|
readonly glow: "#7FD1FF";
|
|
44
81
|
readonly ground: "#D3DBF5";
|
|
45
82
|
readonly metal: "#C9D2E8";
|
|
@@ -58,6 +95,15 @@ export declare const tokens: {
|
|
|
58
95
|
readonly ink: "#0A1033";
|
|
59
96
|
readonly panel: "#EEF2FF";
|
|
60
97
|
readonly ring: "#E0E7FB";
|
|
98
|
+
readonly state: {
|
|
99
|
+
readonly backend: "#FF6B6B";
|
|
100
|
+
readonly blocked: "#FF8A3D";
|
|
101
|
+
readonly caller: "#8FB2FF";
|
|
102
|
+
readonly failFast: "#E0661F";
|
|
103
|
+
readonly failure: "#E04848";
|
|
104
|
+
readonly healthy: "#3DDC84";
|
|
105
|
+
readonly transitional: "#FFD25A";
|
|
106
|
+
};
|
|
61
107
|
readonly transitional: "#FFD25A";
|
|
62
108
|
readonly white: "#FFFFFF";
|
|
63
109
|
};
|
|
@@ -69,6 +115,7 @@ export declare const tokens: {
|
|
|
69
115
|
readonly ringRadius: 90;
|
|
70
116
|
readonly ringStep: 28;
|
|
71
117
|
readonly ringWidth: 2;
|
|
118
|
+
readonly signatureMargin: 24;
|
|
72
119
|
readonly width: 800;
|
|
73
120
|
};
|
|
74
121
|
readonly coverBackground: {
|
|
@@ -116,6 +163,10 @@ export declare const tokens: {
|
|
|
116
163
|
readonly fill: "#14215A";
|
|
117
164
|
readonly ring: "#1C2D74";
|
|
118
165
|
};
|
|
166
|
+
readonly neutral: {
|
|
167
|
+
readonly fill: "#F6F3EC";
|
|
168
|
+
readonly ring: "#D8D6D0";
|
|
169
|
+
};
|
|
119
170
|
readonly olive: {
|
|
120
171
|
readonly fill: "#8A9A3B";
|
|
121
172
|
readonly ring: "#7E8E33";
|
|
@@ -148,6 +199,18 @@ export declare const tokens: {
|
|
|
148
199
|
readonly fill: "#1F8A8A";
|
|
149
200
|
readonly ring: "#2A9A99";
|
|
150
201
|
};
|
|
202
|
+
readonly trackAi: {
|
|
203
|
+
readonly fill: "#E2E4EC";
|
|
204
|
+
readonly ring: "#C7C9D0";
|
|
205
|
+
};
|
|
206
|
+
readonly trackDelivery: {
|
|
207
|
+
readonly fill: "#DFE8E1";
|
|
208
|
+
readonly ring: "#C4CCC6";
|
|
209
|
+
};
|
|
210
|
+
readonly trackIntegration: {
|
|
211
|
+
readonly fill: "#F4E4D8";
|
|
212
|
+
readonly ring: "#D7C9BE";
|
|
213
|
+
};
|
|
151
214
|
readonly violet: {
|
|
152
215
|
readonly fill: "#5B3CC4";
|
|
153
216
|
readonly ring: "#6748CF";
|
|
@@ -12,6 +12,42 @@ export const tokens = {
|
|
|
12
12
|
"startRadius": 11,
|
|
13
13
|
"width": 800
|
|
14
14
|
},
|
|
15
|
+
"brand": {
|
|
16
|
+
"dark": {
|
|
17
|
+
"accent": "#FF7A45",
|
|
18
|
+
"accentText": "#FF7A45",
|
|
19
|
+
"bg": "#121110",
|
|
20
|
+
"border": "#3B3834",
|
|
21
|
+
"borderStrong": "#ADA79D",
|
|
22
|
+
"cardBg": "#1D1C1A",
|
|
23
|
+
"failure": "#FF6696",
|
|
24
|
+
"onAccent": "#121110",
|
|
25
|
+
"success": "#5BBF86",
|
|
26
|
+
"text": "#F1EEE8",
|
|
27
|
+
"textMuted": "#ADA79D",
|
|
28
|
+
"trackAi": "#1B1F28",
|
|
29
|
+
"trackDelivery": "#18231D",
|
|
30
|
+
"trackIntegration": "#2A1C15",
|
|
31
|
+
"warning": "#EBB34B"
|
|
32
|
+
},
|
|
33
|
+
"light": {
|
|
34
|
+
"accent": "#E04E17",
|
|
35
|
+
"accentText": "#B83A0C",
|
|
36
|
+
"bg": "#F6F3EC",
|
|
37
|
+
"border": "#D7D1C5",
|
|
38
|
+
"borderStrong": "#5C5852",
|
|
39
|
+
"cardBg": "#FFFFFF",
|
|
40
|
+
"failure": "#A1124B",
|
|
41
|
+
"onAccent": "#FFFFFF",
|
|
42
|
+
"success": "#2B7A4B",
|
|
43
|
+
"text": "#121212",
|
|
44
|
+
"textMuted": "#5C5852",
|
|
45
|
+
"trackAi": "#E2E4EC",
|
|
46
|
+
"trackDelivery": "#DFE8E1",
|
|
47
|
+
"trackIntegration": "#F4E4D8",
|
|
48
|
+
"warning": "#8F5F00"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
15
51
|
"cast": {
|
|
16
52
|
"agent": {
|
|
17
53
|
"neck": "#E3E8F5",
|
|
@@ -41,6 +77,7 @@ export const tokens = {
|
|
|
41
77
|
"mass": 0.7,
|
|
42
78
|
"stiffness": 170
|
|
43
79
|
},
|
|
80
|
+
"eyes": "#FFC98A",
|
|
44
81
|
"glow": "#7FD1FF",
|
|
45
82
|
"ground": "#D3DBF5",
|
|
46
83
|
"metal": "#C9D2E8",
|
|
@@ -59,6 +96,15 @@ export const tokens = {
|
|
|
59
96
|
"ink": "#0A1033",
|
|
60
97
|
"panel": "#EEF2FF",
|
|
61
98
|
"ring": "#E0E7FB",
|
|
99
|
+
"state": {
|
|
100
|
+
"backend": "#FF6B6B",
|
|
101
|
+
"blocked": "#FF8A3D",
|
|
102
|
+
"caller": "#8FB2FF",
|
|
103
|
+
"failFast": "#E0661F",
|
|
104
|
+
"failure": "#E04848",
|
|
105
|
+
"healthy": "#3DDC84",
|
|
106
|
+
"transitional": "#FFD25A"
|
|
107
|
+
},
|
|
62
108
|
"transitional": "#FFD25A",
|
|
63
109
|
"white": "#FFFFFF"
|
|
64
110
|
},
|
|
@@ -70,6 +116,7 @@ export const tokens = {
|
|
|
70
116
|
"ringRadius": 90,
|
|
71
117
|
"ringStep": 28,
|
|
72
118
|
"ringWidth": 2,
|
|
119
|
+
"signatureMargin": 24,
|
|
73
120
|
"width": 800
|
|
74
121
|
},
|
|
75
122
|
"coverBackground": {
|
|
@@ -117,6 +164,10 @@ export const tokens = {
|
|
|
117
164
|
"fill": "#14215A",
|
|
118
165
|
"ring": "#1C2D74"
|
|
119
166
|
},
|
|
167
|
+
"neutral": {
|
|
168
|
+
"fill": "#F6F3EC",
|
|
169
|
+
"ring": "#D8D6D0"
|
|
170
|
+
},
|
|
120
171
|
"olive": {
|
|
121
172
|
"fill": "#8A9A3B",
|
|
122
173
|
"ring": "#7E8E33"
|
|
@@ -149,6 +200,18 @@ export const tokens = {
|
|
|
149
200
|
"fill": "#1F8A8A",
|
|
150
201
|
"ring": "#2A9A99"
|
|
151
202
|
},
|
|
203
|
+
"trackAi": {
|
|
204
|
+
"fill": "#E2E4EC",
|
|
205
|
+
"ring": "#C7C9D0"
|
|
206
|
+
},
|
|
207
|
+
"trackDelivery": {
|
|
208
|
+
"fill": "#DFE8E1",
|
|
209
|
+
"ring": "#C4CCC6"
|
|
210
|
+
},
|
|
211
|
+
"trackIntegration": {
|
|
212
|
+
"fill": "#F4E4D8",
|
|
213
|
+
"ring": "#D7C9BE"
|
|
214
|
+
},
|
|
152
215
|
"violet": {
|
|
153
216
|
"fill": "#5B3CC4",
|
|
154
217
|
"ring": "#6748CF"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brunosouzas/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Design tokens and illustration pieces of brunosouzas.com: tokens as CSS, JSON and TypeScript, pieces that draw SVG (and React), and a cover command.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -8,6 +8,36 @@
|
|
|
8
8
|
--ds-body-diagram-ring-radius: 70px;
|
|
9
9
|
--ds-body-diagram-start-radius: 11px;
|
|
10
10
|
--ds-body-diagram-width: 800px;
|
|
11
|
+
--ds-brand-dark-accent: #FF7A45;
|
|
12
|
+
--ds-brand-dark-accent-text: #FF7A45;
|
|
13
|
+
--ds-brand-dark-bg: #121110;
|
|
14
|
+
--ds-brand-dark-border: #3B3834;
|
|
15
|
+
--ds-brand-dark-border-strong: #ADA79D;
|
|
16
|
+
--ds-brand-dark-card-bg: #1D1C1A;
|
|
17
|
+
--ds-brand-dark-failure: #FF6696;
|
|
18
|
+
--ds-brand-dark-on-accent: #121110;
|
|
19
|
+
--ds-brand-dark-success: #5BBF86;
|
|
20
|
+
--ds-brand-dark-text: #F1EEE8;
|
|
21
|
+
--ds-brand-dark-text-muted: #ADA79D;
|
|
22
|
+
--ds-brand-dark-track-ai: #1B1F28;
|
|
23
|
+
--ds-brand-dark-track-delivery: #18231D;
|
|
24
|
+
--ds-brand-dark-track-integration: #2A1C15;
|
|
25
|
+
--ds-brand-dark-warning: #EBB34B;
|
|
26
|
+
--ds-brand-light-accent: #E04E17;
|
|
27
|
+
--ds-brand-light-accent-text: #B83A0C;
|
|
28
|
+
--ds-brand-light-bg: #F6F3EC;
|
|
29
|
+
--ds-brand-light-border: #D7D1C5;
|
|
30
|
+
--ds-brand-light-border-strong: #5C5852;
|
|
31
|
+
--ds-brand-light-card-bg: #FFFFFF;
|
|
32
|
+
--ds-brand-light-failure: #A1124B;
|
|
33
|
+
--ds-brand-light-on-accent: #FFFFFF;
|
|
34
|
+
--ds-brand-light-success: #2B7A4B;
|
|
35
|
+
--ds-brand-light-text: #121212;
|
|
36
|
+
--ds-brand-light-text-muted: #5C5852;
|
|
37
|
+
--ds-brand-light-track-ai: #E2E4EC;
|
|
38
|
+
--ds-brand-light-track-delivery: #DFE8E1;
|
|
39
|
+
--ds-brand-light-track-integration: #F4E4D8;
|
|
40
|
+
--ds-brand-light-warning: #8F5F00;
|
|
11
41
|
--ds-cast-agent-neck: #E3E8F5;
|
|
12
42
|
--ds-cast-agent-shine: #E6ECFF;
|
|
13
43
|
--ds-cast-architect-fill: #22B5A4;
|
|
@@ -24,6 +54,7 @@
|
|
|
24
54
|
--ds-cast-emote-pop-damping: 9;
|
|
25
55
|
--ds-cast-emote-pop-mass: 0.7;
|
|
26
56
|
--ds-cast-emote-pop-stiffness: 170;
|
|
57
|
+
--ds-cast-eyes: #FFC98A;
|
|
27
58
|
--ds-cast-glow: #7FD1FF;
|
|
28
59
|
--ds-cast-ground: #D3DBF5;
|
|
29
60
|
--ds-cast-metal: #C9D2E8;
|
|
@@ -38,6 +69,13 @@
|
|
|
38
69
|
--ds-color-ink: #0A1033;
|
|
39
70
|
--ds-color-panel: #EEF2FF;
|
|
40
71
|
--ds-color-ring: #E0E7FB;
|
|
72
|
+
--ds-color-state-backend: #FF6B6B;
|
|
73
|
+
--ds-color-state-blocked: #FF8A3D;
|
|
74
|
+
--ds-color-state-caller: #8FB2FF;
|
|
75
|
+
--ds-color-state-fail-fast: #E0661F;
|
|
76
|
+
--ds-color-state-failure: #E04848;
|
|
77
|
+
--ds-color-state-healthy: #3DDC84;
|
|
78
|
+
--ds-color-state-transitional: #FFD25A;
|
|
41
79
|
--ds-color-transitional: #FFD25A;
|
|
42
80
|
--ds-color-white: #FFFFFF;
|
|
43
81
|
--ds-cover-height: 420px;
|
|
@@ -47,6 +85,7 @@
|
|
|
47
85
|
--ds-cover-ring-radius: 90px;
|
|
48
86
|
--ds-cover-ring-step: 28px;
|
|
49
87
|
--ds-cover-ring-width: 2px;
|
|
88
|
+
--ds-cover-signature-margin: 24px;
|
|
50
89
|
--ds-cover-width: 800px;
|
|
51
90
|
--ds-cover-background-blush-fill: #F6CFE0;
|
|
52
91
|
--ds-cover-background-blush-ring: #ECBAD0;
|
|
@@ -70,6 +109,8 @@
|
|
|
70
109
|
--ds-cover-background-mustard-ring: #E6B33E;
|
|
71
110
|
--ds-cover-background-navy-fill: #14215A;
|
|
72
111
|
--ds-cover-background-navy-ring: #1C2D74;
|
|
112
|
+
--ds-cover-background-neutral-fill: #F6F3EC;
|
|
113
|
+
--ds-cover-background-neutral-ring: #D8D6D0;
|
|
73
114
|
--ds-cover-background-olive-fill: #8A9A3B;
|
|
74
115
|
--ds-cover-background-olive-ring: #7E8E33;
|
|
75
116
|
--ds-cover-background-peach-fill: #F4D8BC;
|
|
@@ -86,6 +127,12 @@
|
|
|
86
127
|
--ds-cover-background-slate-ring: #38466A;
|
|
87
128
|
--ds-cover-background-teal-fill: #1F8A8A;
|
|
88
129
|
--ds-cover-background-teal-ring: #2A9A99;
|
|
130
|
+
--ds-cover-background-track-ai-fill: #E2E4EC;
|
|
131
|
+
--ds-cover-background-track-ai-ring: #C7C9D0;
|
|
132
|
+
--ds-cover-background-track-delivery-fill: #DFE8E1;
|
|
133
|
+
--ds-cover-background-track-delivery-ring: #C4CCC6;
|
|
134
|
+
--ds-cover-background-track-integration-fill: #F4E4D8;
|
|
135
|
+
--ds-cover-background-track-integration-ring: #D7C9BE;
|
|
89
136
|
--ds-cover-background-violet-fill: #5B3CC4;
|
|
90
137
|
--ds-cover-background-violet-ring: #6748CF;
|
|
91
138
|
--ds-cover-background-wine-fill: #6B2340;
|