@brunosouzas/design-system 0.2.0 → 0.3.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/README.md +21 -7
- package/dist/src/pieces/library.d.ts +8 -0
- package/dist/src/pieces/library.js +6 -0
- package/dist/src/pieces/link-icons.d.ts +22 -0
- package/dist/src/pieces/link-icons.js +80 -0
- package/dist/src/pieces/metro.d.ts +42 -3
- package/dist/src/pieces/metro.js +73 -12
- package/dist/src/pieces/ui-icons.d.ts +20 -0
- package/dist/src/pieces/ui-icons.js +34 -0
- package/dist/tokens/generated/tokens.d.ts +7 -0
- package/dist/tokens/generated/tokens.js +10 -3
- package/package.json +1 -1
- package/tokens/generated/tokens.css +7 -0
- package/tokens/generated/tokens.json +10 -3
- package/tokens/generated/tokens.ts +10 -3
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ The visual identity of [brunosouzas.com](https://brunosouzas.com): design tokens
|
|
|
25
25
|
|
|
26
26
|
## Status
|
|
27
27
|
|
|
28
|
-
Early. The first change of the [roadmap](docs/roadmap.md) is implemented: the token source and its CSS, TypeScript and JSON exports, the motion components, and the circuit-breaker state machine as the first catalogue scene (16:9 and 4:5, Portuguese and English), with commands to render its stills and videos. The first variety scene, `publish-subscribe`, is implemented with independent message copies, Publish acceptance, two ACKs and a local invoice NACK. Its owner stills/video approval is pending; implementation is not visual approval. The illustration pieces (roadmap item 3)
|
|
28
|
+
Early. The first change of the [roadmap](docs/roadmap.md) is implemented: the token source and its CSS, TypeScript and JSON exports, the motion components, and the circuit-breaker state machine as the first catalogue scene (16:9 and 4:5, Portuguese and English), with commands to render its stills and videos. The first variety scene, `publish-subscribe`, is implemented with independent message copies, Publish acceptance, two ACKs and a local invoice NACK. Its owner stills/video approval is pending; implementation is not visual approval. The illustration pieces (roadmap item 3), the metro and diagram pieces (item 6) and stackledger's map markers, zones and icons (AB#167, 0.3.0) are implemented: the static drawing library that covers, banners, diagrams and scenes share, with a command that builds a blog cover from a JSON spec. The published covers are not ported to it yet (item 5).
|
|
29
29
|
|
|
30
30
|
## What it is
|
|
31
31
|
|
|
@@ -130,17 +130,20 @@ The components take every colour and size from the tokens, and what is visible a
|
|
|
130
130
|
|
|
131
131
|
- `toSvg(node)` writes a tree as SVG text; `toReact(node)` turns the same tree into React elements. Both describe the same elements, attributes and text, which the tests check.
|
|
132
132
|
- `pose(node, { x, y, tilt, squash, hop, scale, shake, opacity })` animates any piece around its base point; a scene recomputes the numbers every frame.
|
|
133
|
-
- Every colour parameter is a token path (`"color.healthy"`, `"illustration.accent"`), never a hex value, except the
|
|
134
|
-
- The
|
|
133
|
+
- Every colour parameter is a token path (`"color.healthy"`, `"illustration.accent"`), never a hex value, except the three data fills of the map pieces below. Each piece checks its parameters before drawing and names the first wrong one. Positions and points take any finite number, because a map has no edge; sizes stay within 10000. A drawing that would hold a non-finite number throws `<piece>: the drawing overflows`.
|
|
134
|
+
- The 41 pieces, with their anchors, parameters and defaults, are listed in [design §4](openspec/changes/archive/2026-10-23-illustration-pieces/design.md) (the 26 cover pieces), in [design §3](openspec/changes/archive/2026-10-23-metro-and-diagram-pieces/design.md) of `metro-and-diagram-pieces` (the nine map and diagram pieces) and in [design §3, §5 and §6](openspec/changes/archive/2026-10-23-stackledger-map-and-link-pieces/design.md) of `stackledger-map-and-link-pieces` (the six markers, zones and icons); the rules are in [`openspec/specs/illustration-pieces/`](openspec/specs/illustration-pieces/spec.md). `npm run pieces:sheet -- --out <file.svg>` draws them all.
|
|
135
135
|
|
|
136
136
|
### Maps and diagrams
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
Thirteen pieces draw a metro map and its page diagrams, for [stackledger](https://github.com/brunosouzas/stackledger) and any other map in this style: `lineBadge`, `stationMarker` (stop, interchange as a capsule, deprecated), `pipe`, `countBadge`, `nodeBlock`, `pillNode`, `hexNode` (normal, focus, placeholder), `messageArrow` (curved or straight, with a head and an optional label) `ledgerMark` (stackledger's mark; `surface: "dark"` lines it with a light rim), `renewalRing` (orange bands round a station), `suggestedHalo` (a dashed muted circle), `licenceMark` (a 10-unit disc, green when held, white to buy) and `zone` (the outline the caller gives, widened by a round 32-unit stroke at the surface's zone opacity, with an optional title). They paint what the caller lays out: positions, hulls, text measurement and truncation stay with the map engine.
|
|
139
139
|
|
|
140
|
-
-
|
|
140
|
+
- A `placeholder` node may have a `subtitle` (drawn like a normal node's, all muted), and `lineBadge` may have no `text` (the pill alone, 30 wide by default).
|
|
141
|
+
- The licence's disc is small, so it has its own room rule: `size` at least three outlines (9 at ink scale 1).
|
|
142
|
+
|
|
143
|
+
- `surface: "light" | "dark"` picks the background they sit on (`surface.*` tokens); every map and diagram piece takes it except `pipe`; `ledgerMark` takes only `surface`. On dark the hard shadow takes `surface.dark.shadow` and the outline gets a light rim ([ADR 0003](docs/adr/0003-visual-language-and-colour-meaning.md), amendment of AB#157).
|
|
141
144
|
- `inkScale` (0.25 to 8) thickens the outline, rim and shadow without changing the geometry, on `lineBadge`, `stationMarker`, `countBadge` and the three nodes; the map uses 1, the page diagrams 1.6. A shape's height (a marker's diameter) must be at least four outlines; a placeholder node, which draws no ink, is exempt.
|
|
142
|
-
- A line's colour comes from the map's data, so `pipe.fill` and `
|
|
143
|
-
- The `map.*` tokens hold the measures (outline 3, shadow 3.5, line 12, casing 6, badge 20, node 46…), and `site.*` the page palette, fonts and type scale of brunosouzas.com in light and dark.
|
|
145
|
+
- A line's colour comes from the map's data, so `pipe.fill`, `lineBadge.fill` and `zone.fill` also accept `#RRGGBB`. Every other colour is a token path, and a cover spec rejects any hex.
|
|
146
|
+
- The `map.*` tokens hold the measures (outline 3, shadow 3.5, line 12, casing 6, badge 20, node 46, ring 3, halo 1.5, licence 10, zone padding 32…), `surface.*.zoneOpacity` the zone's opacity (0.12, dark 0.22), and `site.*` the page palette, fonts and type scale of brunosouzas.com in light and dark.
|
|
144
147
|
|
|
145
148
|
```ts
|
|
146
149
|
import { lineBadge, pipe, stationMarker, toSvg } from "@brunosouzas/design-system";
|
|
@@ -186,6 +189,17 @@ The banner is one image that scales down as a whole. Words in it become small on
|
|
|
186
189
|
|
|
187
190
|
Add it to `src/pieces/library.ts` (or `src/pieces/metro.ts` for a map or diagram piece) with `definePiece(name, schema, draw)`, take its colours and sizes from the tokens (a new colour goes to `tokens/source.json` first), register it in `PIECES`, and give it a sample in `scripts/pieces-sheet.ts`. The catalogue test then checks that it draws with only its required parameters and uses token colours only.
|
|
188
191
|
|
|
192
|
+
### UI and link icons
|
|
193
|
+
|
|
194
|
+
- `uiIcon({ name, x, y, size, colour })` draws one of seven glyphs of the sites' chrome in a 24-unit box and one token colour: `sun`, `moon`, `zoomIn`, `zoomOut`, `reset`, `calendar`, `download` (data in `UI_ICONS`).
|
|
195
|
+
- `linkIcon({ icon, x, y, size, surface })` draws a link sticker as brunosouzas.com draws its social icons (46-unit box, light or dark frame): `github`, `linkedin`, `email`, `website` (data in `LINK_ICONS`). The GitHub mark is from [Font Awesome](https://fontawesome.com/), licensed [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
|
|
196
|
+
- Neither holds a link, a style, a script or a URL, so a consumer can write one with `toSvg` inside its own `<svg xmlns=…>` and ship it as a static file.
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
import { el, linkIcon, toSvg } from "@brunosouzas/design-system";
|
|
200
|
+
const github = toSvg(el("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 46 46", width: 28, height: 28 }, ...linkIcon({ icon: "github", x: 0, y: 0, surface: "dark" }).body));
|
|
201
|
+
```
|
|
202
|
+
|
|
189
203
|
### EIP icons
|
|
190
204
|
|
|
191
205
|
`src/pieces/eip-icons.ts` holds the 26 Enterprise Integration Patterns icons as data. They are redrawn from the icons by Gregor Hohpe and Bobby Woolf ([enterpriseintegrationpatterns.com](https://www.enterpriseintegrationpatterns.com/)), licensed [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); each icon keeps that credit in its description.
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from "./metro.ts";
|
|
2
|
+
export * from "./ui-icons.ts";
|
|
3
|
+
export * from "./link-icons.ts";
|
|
2
4
|
type Point = [number, number];
|
|
3
5
|
export type PillParams = {
|
|
4
6
|
x: number;
|
|
@@ -269,6 +271,10 @@ export declare const PIECES: {
|
|
|
269
271
|
readonly hexNode: import("./piece.ts").Piece<import("./metro.ts").NodeParams>;
|
|
270
272
|
readonly messageArrow: import("./piece.ts").Piece<import("./metro.ts").MessageArrowParams>;
|
|
271
273
|
readonly ledgerMark: import("./piece.ts").Piece<import("./metro.ts").LedgerMarkParams>;
|
|
274
|
+
readonly renewalRing: import("./piece.ts").Piece<import("./metro.ts").RenewalRingParams>;
|
|
275
|
+
readonly suggestedHalo: import("./piece.ts").Piece<import("./metro.ts").SuggestedHaloParams>;
|
|
276
|
+
readonly licenceMark: import("./piece.ts").Piece<import("./metro.ts").LicenceMarkParams>;
|
|
277
|
+
readonly zone: import("./piece.ts").Piece<import("./metro.ts").ZoneParams>;
|
|
272
278
|
readonly pill: import("./piece.ts").Piece<PillParams>;
|
|
273
279
|
readonly rings: import("./piece.ts").Piece<RingsParams>;
|
|
274
280
|
readonly sheet: import("./piece.ts").Piece<SheetParams>;
|
|
@@ -295,6 +301,8 @@ export declare const PIECES: {
|
|
|
295
301
|
readonly book: import("./piece.ts").Piece<BookParams>;
|
|
296
302
|
readonly muleFlow: import("./piece.ts").Piece<MuleFlowParams>;
|
|
297
303
|
readonly eipIcon: import("./piece.ts").Piece<EipIconParams>;
|
|
304
|
+
readonly uiIcon: import("./piece.ts").Piece<import("./ui-icons.ts").UiIconParams>;
|
|
305
|
+
readonly linkIcon: import("./piece.ts").Piece<import("./link-icons.ts").LinkIconParams>;
|
|
298
306
|
};
|
|
299
307
|
export type PieceName = keyof typeof PIECES;
|
|
300
308
|
export declare const PIECE_NAMES: PieceName[];
|
|
@@ -12,7 +12,11 @@ import { drawn, el, g, r2, shadowed } from "./node.js";
|
|
|
12
12
|
import { col, colour, count, label, MAX_SIZE, PATH_DATA, pos, size } from "./params.js";
|
|
13
13
|
import { definePiece } from "./piece.js";
|
|
14
14
|
import { METRO_PIECES } from "./metro.js";
|
|
15
|
+
import { uiIcon } from "./ui-icons.js";
|
|
16
|
+
import { linkIcon } from "./link-icons.js";
|
|
15
17
|
export * from "./metro.js";
|
|
18
|
+
export * from "./ui-icons.js";
|
|
19
|
+
export * from "./link-icons.js";
|
|
16
20
|
const ink = tokens.color.ink;
|
|
17
21
|
const mono = tokens.font.mono;
|
|
18
22
|
/** Pill label centred on (x, y), usually overlapping the top edge of what it names. */
|
|
@@ -375,5 +379,7 @@ export const PIECES = {
|
|
|
375
379
|
muleFlow,
|
|
376
380
|
eipIcon,
|
|
377
381
|
...METRO_PIECES,
|
|
382
|
+
uiIcon,
|
|
383
|
+
linkIcon,
|
|
378
384
|
};
|
|
379
385
|
export const PIECE_NAMES = Object.keys(PIECES);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type SvgNode } from "./node.ts";
|
|
2
|
+
import { type SurfaceName } from "./metro.ts";
|
|
3
|
+
export type LinkIcon = {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly title: string;
|
|
6
|
+
readonly description: string; /** A colour token path. */
|
|
7
|
+
readonly face: string;
|
|
8
|
+
readonly glyph: readonly SvgNode[];
|
|
9
|
+
};
|
|
10
|
+
/** Every link icon draws in a 46x46 box. */
|
|
11
|
+
export declare const LINK_ICON_SIZE = 46;
|
|
12
|
+
export declare const LINK_ICONS: readonly LinkIcon[];
|
|
13
|
+
export declare const LINK_ICON_NAMES: string[];
|
|
14
|
+
export type LinkIconParams = {
|
|
15
|
+
icon: string;
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
size?: number;
|
|
19
|
+
surface?: SurfaceName;
|
|
20
|
+
};
|
|
21
|
+
/** One link sticker at (x, y), `size` wide (46 by default), on the light or the dark page. */
|
|
22
|
+
export declare const linkIcon: import("./piece.ts").Piece<LinkIconParams>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Link icons as data (spec illustration-pieces, "Link icons as data"; design §6
|
|
2
|
+
// of stackledger-map-and-link-pieces): the social stickers of brunosouzas.com
|
|
3
|
+
// (public/images/home/social-*.svg at e29b3dd), with every colour replaced by
|
|
4
|
+
// its token, plus a `website` globe in the same style. `linkIcon` draws the
|
|
5
|
+
// site's frame (light, or dark with its rim) around the face and the glyph, at
|
|
6
|
+
// the site's measures (46 box, face 38 at 2, radius 9, outline 2.5).
|
|
7
|
+
//
|
|
8
|
+
// Credit: the GitHub mark is Font Awesome's (fontawesome.com), licensed
|
|
9
|
+
// CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/); its description
|
|
10
|
+
// keeps the credit.
|
|
11
|
+
//
|
|
12
|
+
// What can go wrong: an unknown icon is rejected by the schema. No node holds
|
|
13
|
+
// a link, a style, a script or a URL, so the output can ship as a static file.
|
|
14
|
+
import { tokens } from "../../tokens/generated/tokens.js";
|
|
15
|
+
import { drawn, el, g, r2 } from "./node.js";
|
|
16
|
+
import { colour, pos, size } from "./params.js";
|
|
17
|
+
import { definePiece } from "./piece.js";
|
|
18
|
+
import { SURFACES } from "./metro.js";
|
|
19
|
+
const C = tokens.color;
|
|
20
|
+
const INK = C.ink;
|
|
21
|
+
/** Every link icon draws in a 46x46 box. */
|
|
22
|
+
export const LINK_ICON_SIZE = 46;
|
|
23
|
+
export const LINK_ICONS = [
|
|
24
|
+
{
|
|
25
|
+
name: "github",
|
|
26
|
+
title: "GitHub",
|
|
27
|
+
description: "GitHub icon. The GitHub mark is from Font Awesome (fontawesome.com), CC BY 4.0.",
|
|
28
|
+
face: "color.white",
|
|
29
|
+
glyph: [g({ transform: "translate(9.5 9) scale(0.0455)" }, el("path", { d: "M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z", fill: INK, stroke: "none" }))],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "linkedin",
|
|
33
|
+
title: "LinkedIn",
|
|
34
|
+
description: "LinkedIn icon.",
|
|
35
|
+
face: "color.caller",
|
|
36
|
+
glyph: [
|
|
37
|
+
el("rect", { x: 12, y: 18.5, width: 4, height: 11.5, rx: 1, fill: INK, stroke: "none" }),
|
|
38
|
+
el("circle", { cx: 14, cy: 13.8, r: 2.4, fill: INK, stroke: "none" }),
|
|
39
|
+
el("path", { d: "M19.5,30 V18.5 H23.5 V20.3 C24.5,19 26.2,18.1 28,18.1 C31.2,18.1 32.5,20.2 32.5,23.6 V30 H28.5 V24.3 C28.5,22.7 27.8,21.9 26.6,21.9 C25.2,21.9 23.5,22.8 23.5,24.7 V30 Z", fill: INK, stroke: "none" }),
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "email",
|
|
44
|
+
title: "Email",
|
|
45
|
+
description: "Email icon.",
|
|
46
|
+
face: "color.transitional",
|
|
47
|
+
glyph: [
|
|
48
|
+
el("rect", { x: 9, y: 13, width: 24, height: 17, rx: 3, fill: C.white, stroke: INK, "stroke-width": 2.5 }),
|
|
49
|
+
el("path", { d: "M10,15 L21,23 L32,15", fill: "none", stroke: INK, "stroke-width": 2.5, "stroke-linejoin": "round" }),
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "website",
|
|
54
|
+
title: "Website",
|
|
55
|
+
description: "Website icon: a globe.",
|
|
56
|
+
face: "color.healthy",
|
|
57
|
+
glyph: [
|
|
58
|
+
el("circle", { cx: 21, cy: 21, r: 10.5, fill: C.white, stroke: INK, "stroke-width": 2.5 }),
|
|
59
|
+
el("ellipse", { cx: 21, cy: 21, rx: 4.6, ry: 10.5, fill: "none", stroke: INK, "stroke-width": 2 }),
|
|
60
|
+
el("path", { d: "M10.5 21H31.5M12.5 15.5H29.5M12.5 26.5H29.5", fill: "none", stroke: INK, "stroke-width": 2, "stroke-linecap": "round" }),
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
export const LINK_ICON_NAMES = LINK_ICONS.map((icon) => icon.name);
|
|
65
|
+
/** The site's frame: the shadow (and on dark the rim) behind the face. */
|
|
66
|
+
const frame = (surface) => {
|
|
67
|
+
const s = tokens.surface[surface];
|
|
68
|
+
return s.rimWidth > 0
|
|
69
|
+
? [
|
|
70
|
+
el("rect", { x: 4, y: 4, width: 41, height: 41, rx: 11, fill: s.shadow, stroke: "none" }),
|
|
71
|
+
el("rect", { x: 0.5, y: 0.5, width: 41, height: 41, rx: 11, fill: s.rim, stroke: "none" }),
|
|
72
|
+
]
|
|
73
|
+
: [el("rect", { x: 5, y: 5, width: 38, height: 38, rx: 9, fill: s.shadow, stroke: "none" })];
|
|
74
|
+
};
|
|
75
|
+
/** One link sticker at (x, y), `size` wide (46 by default), on the light or the dark page. */
|
|
76
|
+
export const linkIcon = definePiece("linkIcon", { icon: { kind: "enum", required: true, values: LINK_ICON_NAMES }, x: pos(), y: pos(), size: size(), surface: { kind: "enum", values: SURFACES } }, ({ icon, x, y, size: side = LINK_ICON_SIZE, surface = "light" }) => {
|
|
77
|
+
const data = LINK_ICONS.find((candidate) => candidate.name === icon);
|
|
78
|
+
const face = el("rect", { x: 2, y: 2, width: 38, height: 38, rx: 9, fill: colour(data.face, "face"), stroke: INK, "stroke-width": 2.5 });
|
|
79
|
+
return drawn([g({ transform: `translate(${r2(x)} ${r2(y)}) scale(${side / LINK_ICON_SIZE})`, stroke: "none" }, ...frame(surface), face, ...data.glyph)]);
|
|
80
|
+
});
|
|
@@ -8,13 +8,13 @@ export type Ink = {
|
|
|
8
8
|
export type LineBadgeParams = Ink & {
|
|
9
9
|
x: number;
|
|
10
10
|
y: number;
|
|
11
|
-
text
|
|
11
|
+
text?: string;
|
|
12
12
|
fill: string;
|
|
13
13
|
width?: number;
|
|
14
14
|
height?: number;
|
|
15
15
|
flat?: boolean;
|
|
16
16
|
};
|
|
17
|
-
/** A line's terminal badge: a pill in the line colour with its code in white, centred on (x, y). */
|
|
17
|
+
/** A line's terminal badge: a pill in the line colour with its code in white, centred on (x, y); without `text`, the pill alone. */
|
|
18
18
|
export declare const lineBadge: import("./piece.ts").Piece<LineBadgeParams>;
|
|
19
19
|
export type StationMarkerParams = Ink & {
|
|
20
20
|
cx: number;
|
|
@@ -76,9 +76,44 @@ export type LedgerMarkParams = {
|
|
|
76
76
|
y: number;
|
|
77
77
|
size?: number;
|
|
78
78
|
line?: string;
|
|
79
|
+
surface?: SurfaceName;
|
|
79
80
|
};
|
|
80
|
-
/** stackledger's mark (favicon, header): an ink square with a bent line and two stations, 32 units scaled to `size`.
|
|
81
|
+
/** stackledger's mark (favicon, header): an ink square with a bent line and two stations, 32 units scaled to `size`.
|
|
82
|
+
* On a surface with a rim (dark), a light rim of 2 × rimWidth lines the square inside its 32 box (card 167). */
|
|
81
83
|
export declare const ledgerMark: import("./piece.ts").Piece<LedgerMarkParams>;
|
|
84
|
+
export type RenewalRingParams = Ink & {
|
|
85
|
+
cx: number;
|
|
86
|
+
cy: number;
|
|
87
|
+
r: number;
|
|
88
|
+
width?: number;
|
|
89
|
+
};
|
|
90
|
+
/** The renewal ring: bands like a bent pipe round a station (rim on dark, ink, then color.blocked), no shadow. */
|
|
91
|
+
export declare const renewalRing: import("./piece.ts").Piece<RenewalRingParams>;
|
|
92
|
+
export type SuggestedHaloParams = {
|
|
93
|
+
cx: number;
|
|
94
|
+
cy: number;
|
|
95
|
+
r: number;
|
|
96
|
+
surface?: SurfaceName;
|
|
97
|
+
};
|
|
98
|
+
/** The suggested-position halo: a dashed muted circle, no ink. */
|
|
99
|
+
export declare const suggestedHalo: import("./piece.ts").Piece<SuggestedHaloParams>;
|
|
100
|
+
export type LicenceMarkParams = Ink & {
|
|
101
|
+
cx: number;
|
|
102
|
+
cy: number;
|
|
103
|
+
state?: "owned" | "toBuy";
|
|
104
|
+
size?: number;
|
|
105
|
+
};
|
|
106
|
+
/** A licence: a small disc sticker, green when held, white to buy. Its own room rule: size ≥ 3 × outline. */
|
|
107
|
+
export declare const licenceMark: import("./piece.ts").Piece<LicenceMarkParams>;
|
|
108
|
+
export type ZoneParams = {
|
|
109
|
+
points: Point[];
|
|
110
|
+
fill: string;
|
|
111
|
+
title?: string;
|
|
112
|
+
titleAt?: Point;
|
|
113
|
+
surface?: SurfaceName;
|
|
114
|
+
};
|
|
115
|
+
/** A zone: the outline the caller gives (stackledger's hull), widened by a round stroke, at the surface's zone opacity; an optional title. */
|
|
116
|
+
export declare const zone: import("./piece.ts").Piece<ZoneParams>;
|
|
82
117
|
export declare const METRO_PIECES: {
|
|
83
118
|
readonly lineBadge: import("./piece.ts").Piece<LineBadgeParams>;
|
|
84
119
|
readonly stationMarker: import("./piece.ts").Piece<StationMarkerParams>;
|
|
@@ -89,5 +124,9 @@ export declare const METRO_PIECES: {
|
|
|
89
124
|
readonly hexNode: import("./piece.ts").Piece<NodeParams>;
|
|
90
125
|
readonly messageArrow: import("./piece.ts").Piece<MessageArrowParams>;
|
|
91
126
|
readonly ledgerMark: import("./piece.ts").Piece<LedgerMarkParams>;
|
|
127
|
+
readonly renewalRing: import("./piece.ts").Piece<RenewalRingParams>;
|
|
128
|
+
readonly suggestedHalo: import("./piece.ts").Piece<SuggestedHaloParams>;
|
|
129
|
+
readonly licenceMark: import("./piece.ts").Piece<LicenceMarkParams>;
|
|
130
|
+
readonly zone: import("./piece.ts").Piece<ZoneParams>;
|
|
92
131
|
};
|
|
93
132
|
export {};
|
package/dist/src/pieces/metro.js
CHANGED
|
@@ -50,9 +50,10 @@ const sticker = (shape, face, inkParams) => {
|
|
|
50
50
|
// Every text sets its own anchor, size and weight, so a surrounding group (a cover's label style) does not leak in.
|
|
51
51
|
const words = (x, y, value, attrs) => el("text", { x: r2(x), y: r2(y), "font-family": font, ...attrs }, value);
|
|
52
52
|
const pill = (x, y, w, h) => (dx, dy, attrs) => el("rect", { x: r2(x + dx), y: r2(y + dy), width: r2(w), height: r2(h), rx: r2(h / 2), ...attrs });
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
// Without a text, the default width is the one-character width (card 167).
|
|
54
|
+
const badgeWidth = ({ width, text }) => width ?? Math.max(30, 7.6 * (text === undefined ? 1 : Array.from(text).length) + 18);
|
|
55
|
+
/** A line's terminal badge: a pill in the line colour with its code in white, centred on (x, y); without `text`, the pill alone. */
|
|
56
|
+
export const lineBadge = definePiece("lineBadge", { x: pos(), y: pos(), text: label(false), fill: dataColour(), width: size(), height: size(), flat: { kind: "boolean" }, ...inkSchema }, (params) => {
|
|
56
57
|
const { x, y, text, fill, height = M.badgeHeight, flat = false } = params;
|
|
57
58
|
const width = badgeWidth(params);
|
|
58
59
|
const face = paint(fill);
|
|
@@ -60,7 +61,7 @@ export const lineBadge = definePiece("lineBadge", { x: pos(), y: pos(), text: la
|
|
|
60
61
|
const inset = flat ? outline / 2 : 0;
|
|
61
62
|
const shape = pill(x - width / 2 + inset, y - height / 2 + inset, width - 2 * inset, height - 2 * inset);
|
|
62
63
|
const body = flat ? [shape(0, 0, { fill: face, stroke: ink, "stroke-width": r2(outline), "stroke-linejoin": "round" })] : sticker(shape, face, params);
|
|
63
|
-
return drawn(body, [words(x, y + 4.5, text, { fill: white, "font-size": M.badgeTextSize, "font-weight": bold, "text-anchor": "middle" })]);
|
|
64
|
+
return drawn(body, text === undefined ? [] : [words(x, y + 4.5, text, { fill: white, "font-size": M.badgeTextSize, "font-weight": bold, "text-anchor": "middle" })]);
|
|
64
65
|
}, (params) => {
|
|
65
66
|
const height = params.height ?? M.badgeHeight;
|
|
66
67
|
return limits(atLeast("width", badgeWidth(params), height, "the height"), roomFor("height", height, params));
|
|
@@ -125,10 +126,11 @@ const nodeSchema = {
|
|
|
125
126
|
const nodeLimits = (kind) => (params) => {
|
|
126
127
|
const { width, height = M.nodeHeight, subtitle, state = "normal" } = params;
|
|
127
128
|
const radius = params.radius ?? M.nodeRadius;
|
|
128
|
-
return limits(atLeast("width", width, 2 * height, "twice the height"), kind === "box" && radius > height / 2 && { path: "radius", message: `must be at most half the height (${r2(height / 2)}), found ${r2(radius)}` }, state
|
|
129
|
+
return limits(atLeast("width", width, 2 * height, "twice the height"), kind === "box" && radius > height / 2 && { path: "radius", message: `must be at most half the height (${r2(height / 2)}), found ${r2(radius)}` }, state !== "placeholder" && roomFor("height", height, params));
|
|
129
130
|
};
|
|
130
131
|
const drawNode = (kind, params) => {
|
|
131
132
|
const { x, y, width, height = M.nodeHeight, title, subtitle, state = "normal" } = params;
|
|
133
|
+
const inset = kind === "box" ? 12 : height / 2;
|
|
132
134
|
const radius = kind === "pill" ? height / 2 : (params.radius ?? M.nodeRadius);
|
|
133
135
|
const shape = kind === "hex"
|
|
134
136
|
? (dx, dy, attrs) => {
|
|
@@ -140,10 +142,16 @@ const drawNode = (kind, params) => {
|
|
|
140
142
|
const { s } = inkOf(params);
|
|
141
143
|
const middle = y + height / 2;
|
|
142
144
|
if (state === "placeholder") {
|
|
143
|
-
|
|
145
|
+
const dashed = [shape(0, 0, { fill: "none", stroke: s.muted, "stroke-width": 1.5, "stroke-dasharray": "5 4", "stroke-linejoin": "round" })];
|
|
146
|
+
// With a subtitle, a normal node's text layout, every word muted (stackledger's unlinked box; card 167).
|
|
147
|
+
return drawn(dashed, subtitle === undefined
|
|
148
|
+
? [words(x + width / 2, middle + 4.5, title, { fill: s.muted, "font-size": M.labelSize, "font-weight": 400, "text-anchor": "middle" })]
|
|
149
|
+
: [
|
|
150
|
+
words(x + inset, middle - 3, title, { fill: s.muted, "font-size": M.labelSize, "font-weight": bold, "text-anchor": "start" }),
|
|
151
|
+
words(x + inset, middle + 14, subtitle, { fill: s.muted, "font-size": 11, "font-weight": 400, "text-anchor": "start" }),
|
|
152
|
+
]);
|
|
144
153
|
}
|
|
145
154
|
const focus = state === "focus";
|
|
146
|
-
const inset = kind === "box" ? 12 : height / 2;
|
|
147
155
|
const titleFill = focus ? ink : s.text;
|
|
148
156
|
const text = subtitle === undefined
|
|
149
157
|
? [words(x + inset, middle + 4.5, title, { fill: titleFill, "font-size": M.labelSize, "font-weight": bold, "text-anchor": "start" })]
|
|
@@ -198,8 +206,61 @@ export const messageArrow = definePiece("messageArrow", {
|
|
|
198
206
|
const distance = Math.hypot(to[0] - from[0], to[1] - from[1]);
|
|
199
207
|
return limits(distance === 0 && { path: "to", message: "must differ from from" }, distance > 0 && head && distance < 10 * width && { path: "to", message: `is too close to from for the head: needs at least ${r2(10 * width)}, found ${r2(distance)}` });
|
|
200
208
|
});
|
|
201
|
-
/** stackledger's mark (favicon, header): an ink square with a bent line and two stations, 32 units scaled to `size`.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
]
|
|
205
|
-
|
|
209
|
+
/** stackledger's mark (favicon, header): an ink square with a bent line and two stations, 32 units scaled to `size`.
|
|
210
|
+
* On a surface with a rim (dark), a light rim of 2 × rimWidth lines the square inside its 32 box (card 167). */
|
|
211
|
+
export const ledgerMark = definePiece("ledgerMark", { x: pos(), y: pos(), size: { kind: "number", min: 12, max: 512 }, line: col(), surface: surfaceParam }, ({ x, y, size: side = 32, line = "illustration.accent", surface = "light" }) => {
|
|
212
|
+
const { rimWidth, rim } = tokens.surface[surface];
|
|
213
|
+
const band = 2 * rimWidth;
|
|
214
|
+
const square = rimWidth > 0
|
|
215
|
+
? [
|
|
216
|
+
el("rect", { x: 0, y: 0, width: 32, height: 32, rx: 7, fill: rim, stroke: "none" }),
|
|
217
|
+
el("rect", { x: band, y: band, width: 32 - 2 * band, height: 32 - 2 * band, rx: 7 - band, fill: ink, stroke: "none" }),
|
|
218
|
+
]
|
|
219
|
+
: [el("rect", { x: 0, y: 0, width: 32, height: 32, rx: 7, fill: ink, stroke: "none" })];
|
|
220
|
+
return drawn([
|
|
221
|
+
g({ transform: `translate(${r2(x)} ${r2(y)}) scale(${side / 32})` }, ...square, el("path", { d: "M7 23 L14 16 L25 16", fill: "none", stroke: colour(line, "line"), "stroke-width": 4.5, "stroke-linecap": "round", "stroke-linejoin": "round" }), el("circle", { cx: 14, cy: 16, r: 4, fill: white, stroke: ink, "stroke-width": 2 }), el("circle", { cx: 25, cy: 16, r: 2.6, fill: white, stroke: ink, "stroke-width": 1.6 })),
|
|
222
|
+
]);
|
|
223
|
+
});
|
|
224
|
+
/** The renewal ring: bands like a bent pipe round a station (rim on dark, ink, then color.blocked), no shadow. */
|
|
225
|
+
export const renewalRing = definePiece("renewalRing", { cx: pos(), cy: pos(), r: size(true), width: { kind: "number", min: 0, exclusiveMin: true, max: 50 }, ...inkSchema }, (params) => {
|
|
226
|
+
const { cx, cy, r, width = M.ringWidth } = params;
|
|
227
|
+
const { s, outline, rim } = inkOf(params);
|
|
228
|
+
// Radius and band widths as given, like pipe's widths: a valid hairline must not round to zero.
|
|
229
|
+
const band = (stroke, strokeWidth) => el("circle", { cx: r2(cx), cy: r2(cy), r, fill: "none", stroke, "stroke-width": strokeWidth });
|
|
230
|
+
return drawn([...(s.rimWidth > 0 ? [band(s.rim, width + outline + 2 * rim)] : []), band(ink, width + outline), band(tokens.color.blocked, width)]);
|
|
231
|
+
}, (params) => {
|
|
232
|
+
const { outline, rim } = inkOf(params);
|
|
233
|
+
const need = ((params.width ?? M.ringWidth) + outline + 2 * rim) / 2;
|
|
234
|
+
return limits(params.r < need && { path: "r", message: `leaves no room for the ring's bands: needs at least ${r2(need)}` });
|
|
235
|
+
});
|
|
236
|
+
/** The suggested-position halo: a dashed muted circle, no ink. */
|
|
237
|
+
export const suggestedHalo = definePiece("suggestedHalo", { cx: pos(), cy: pos(), r: size(true), surface: surfaceParam }, ({ cx, cy, r, surface = "light" }) => drawn([el("circle", { cx: r2(cx), cy: r2(cy), r, fill: "none", stroke: tokens.surface[surface].muted, "stroke-width": M.haloWidth, "stroke-dasharray": "4 3" })]));
|
|
238
|
+
/** A licence: a small disc sticker, green when held, white to buy. Its own room rule: size ≥ 3 × outline. */
|
|
239
|
+
export const licenceMark = definePiece("licenceMark", { cx: pos(), cy: pos(), state: { kind: "enum", values: ["owned", "toBuy"] }, size: size(), ...inkSchema }, (params) => {
|
|
240
|
+
const { cx, cy, state = "owned", size: side = M.licenceSize } = params;
|
|
241
|
+
const shape = (dx, dy, attrs) => el("circle", { cx: r2(cx + dx), cy: r2(cy + dy), r: r2(side / 2), ...attrs });
|
|
242
|
+
return drawn(sticker(shape, state === "owned" ? tokens.color.healthy : white, params));
|
|
243
|
+
}, (params) => {
|
|
244
|
+
const need = 3 * inkOf(params).outline;
|
|
245
|
+
const side = params.size ?? M.licenceSize;
|
|
246
|
+
return limits(side < need && { path: "size", message: `leaves no room for the licence's face: needs at least ${r2(need)} at this ink scale` });
|
|
247
|
+
});
|
|
248
|
+
/** Mixes a #RRGGBB colour with white by `amount` (stackledger's zone title tint). */
|
|
249
|
+
const tint = (hex, amount) => "#" + [1, 3, 5].map((i) => Math.round(parseInt(hex.slice(i, i + 2), 16) * (1 - amount) + 255 * amount).toString(16).padStart(2, "0").toUpperCase()).join("");
|
|
250
|
+
/** A zone: the outline the caller gives (stackledger's hull), widened by a round stroke, at the surface's zone opacity; an optional title. */
|
|
251
|
+
export const zone = definePiece("zone", { points: { kind: "array", required: true, minItems: 1, maxItems: 10000, of: point() }, fill: dataColour(), title: label(false), titleAt: point(false), surface: surfaceParam }, ({ points, fill, title, titleAt, surface = "light" }) => {
|
|
252
|
+
const colourOf = paint(fill);
|
|
253
|
+
const pad = M.zonePadding;
|
|
254
|
+
const at = (p) => `${r2(p[0])},${r2(p[1])}`;
|
|
255
|
+
const shape = points.length === 1
|
|
256
|
+
? el("circle", { cx: r2(points[0][0]), cy: r2(points[0][1]), r: pad, fill: colourOf })
|
|
257
|
+
: points.length === 2
|
|
258
|
+
? el("line", { x1: r2(points[0][0]), y1: r2(points[0][1]), x2: r2(points[1][0]), y2: r2(points[1][1]), stroke: colourOf, "stroke-width": 2 * pad, "stroke-linecap": "round" })
|
|
259
|
+
: el("polygon", { points: points.map(at).join(" "), fill: colourOf, stroke: colourOf, "stroke-width": 2 * pad, "stroke-linejoin": "round" });
|
|
260
|
+
const titleFill = surface === "dark" ? tint(colourOf, M.zoneTitleTint) : colourOf;
|
|
261
|
+
const text = title !== undefined && titleAt !== undefined
|
|
262
|
+
? [words(titleAt[0], titleAt[1] + 13, title, { fill: titleFill, "font-size": M.labelSize, "font-weight": bold, "text-anchor": "start" })]
|
|
263
|
+
: [];
|
|
264
|
+
return drawn([g({ opacity: tokens.surface[surface].zoneOpacity, stroke: "none" }, shape)], text);
|
|
265
|
+
}, ({ title, titleAt }) => limits(title !== undefined && titleAt === undefined && { path: "titleAt", message: "is required with a title" }, titleAt !== undefined && title === undefined && { path: "title", message: "is required with titleAt" }));
|
|
266
|
+
export const METRO_PIECES = { lineBadge, stationMarker, pipe, countBadge, nodeBlock, pillNode, hexNode, messageArrow, ledgerMark, renewalRing, suggestedHalo, licenceMark, zone };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SvgNode } from "./node.ts";
|
|
2
|
+
export type UiIcon = {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly title: string;
|
|
5
|
+
readonly description: string;
|
|
6
|
+
readonly nodes: readonly SvgNode[];
|
|
7
|
+
};
|
|
8
|
+
/** Every UI icon draws in a 24x24 box. */
|
|
9
|
+
export declare const UI_ICON_SIZE = 24;
|
|
10
|
+
export declare const UI_ICONS: readonly UiIcon[];
|
|
11
|
+
export declare const UI_ICON_NAMES: string[];
|
|
12
|
+
export type UiIconParams = {
|
|
13
|
+
name: string;
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
size?: number;
|
|
17
|
+
colour?: string;
|
|
18
|
+
};
|
|
19
|
+
/** One UI icon at (x, y), `size` wide (24 by default), in one token colour (`color.ink` by default). */
|
|
20
|
+
export declare const uiIcon: import("./piece.ts").Piece<UiIconParams>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { el, g, drawn, r2 } from "./node.js";
|
|
2
|
+
import { col, pos, size } from "./params.js";
|
|
3
|
+
import { definePiece } from "./piece.js";
|
|
4
|
+
import { colour } from "./params.js";
|
|
5
|
+
/** Every UI icon draws in a 24x24 box. */
|
|
6
|
+
export const UI_ICON_SIZE = 24;
|
|
7
|
+
const stroked = (d) => el("path", { d, fill: "none", "stroke-width": 2, "stroke-linecap": "round", "stroke-linejoin": "round" });
|
|
8
|
+
const filled = (d) => el("path", { d, stroke: "none" });
|
|
9
|
+
export const UI_ICONS = [
|
|
10
|
+
{
|
|
11
|
+
name: "sun",
|
|
12
|
+
title: "Sun",
|
|
13
|
+
description: "Light theme: a disc with eight rays.",
|
|
14
|
+
nodes: [el("circle", { cx: 12, cy: 12, r: 4.5, stroke: "none" }), stroked("M12 2.5v2.5M12 19v2.5M2.5 12H5M19 12h2.5M5.3 5.3l1.8 1.8M16.9 16.9l1.8 1.8M5.3 18.7l1.8-1.8M16.9 7.1l1.8-1.8")],
|
|
15
|
+
},
|
|
16
|
+
{ name: "moon", title: "Moon", description: "Dark theme: a crescent moon.", nodes: [filled("M20.5 14.6A8.6 8.6 0 0 1 9.4 3.5a8.6 8.6 0 1 0 11.1 11.1Z")] },
|
|
17
|
+
{ name: "zoomIn", title: "Zoom in", description: "A magnifier with a plus.", nodes: [stroked("M10.5 4a6.5 6.5 0 1 0 0 13a6.5 6.5 0 1 0 0-13ZM15.3 15.3l5.2 5.2M7.5 10.5h6M10.5 7.5v6")] },
|
|
18
|
+
{ name: "zoomOut", title: "Zoom out", description: "A magnifier with a minus.", nodes: [stroked("M10.5 4a6.5 6.5 0 1 0 0 13a6.5 6.5 0 1 0 0-13ZM15.3 15.3l5.2 5.2M7.5 10.5h6")] },
|
|
19
|
+
{ name: "reset", title: "Reset", description: "A circular arrow: back to the start.", nodes: [stroked("M4.5 12A7.5 7.5 0 1 0 6.7 6.7M4 3.5v4.5h4.5")] },
|
|
20
|
+
{
|
|
21
|
+
name: "calendar",
|
|
22
|
+
title: "Calendar",
|
|
23
|
+
description: "A calendar page with one day marked.",
|
|
24
|
+
nodes: [stroked("M5.5 5h13a2 2 0 0 1 2 2v11.5a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2ZM3.5 10h17M8 3v4M16 3v4"), el("rect", { x: 7, y: 13, width: 3, height: 3, rx: 0.5, stroke: "none" })],
|
|
25
|
+
},
|
|
26
|
+
{ name: "download", title: "Download", description: "An arrow down into a tray.", nodes: [stroked("M12 3.5v11M7.5 10l4.5 4.5 4.5-4.5M4.5 16.5v3h15v-3")] },
|
|
27
|
+
];
|
|
28
|
+
export const UI_ICON_NAMES = UI_ICONS.map((icon) => icon.name);
|
|
29
|
+
/** One UI icon at (x, y), `size` wide (24 by default), in one token colour (`color.ink` by default). */
|
|
30
|
+
export const uiIcon = definePiece("uiIcon", { name: { kind: "enum", required: true, values: UI_ICON_NAMES }, x: pos(), y: pos(), size: size(), colour: col() }, ({ name, x, y, size: side = UI_ICON_SIZE, colour: path = "color.ink" }) => {
|
|
31
|
+
const icon = UI_ICONS.find((candidate) => candidate.name === name);
|
|
32
|
+
const paint = colour(path, "colour");
|
|
33
|
+
return drawn([g({ transform: `translate(${r2(x)} ${r2(y)}) scale(${side / UI_ICON_SIZE})`, fill: paint, stroke: paint }, ...icon.nodes)]);
|
|
34
|
+
});
|
|
@@ -136,14 +136,19 @@ export declare const tokens: {
|
|
|
136
136
|
readonly countHeight: 16;
|
|
137
137
|
readonly countTextSize: 11;
|
|
138
138
|
readonly edgeWidth: 2.5;
|
|
139
|
+
readonly haloWidth: 1.5;
|
|
139
140
|
readonly interchangeExtra: 2;
|
|
140
141
|
readonly labelSize: 13;
|
|
142
|
+
readonly licenceSize: 10;
|
|
141
143
|
readonly lineWidth: 12;
|
|
142
144
|
readonly nodeHeight: 46;
|
|
143
145
|
readonly nodeRadius: 10;
|
|
144
146
|
readonly outline: 3;
|
|
147
|
+
readonly ringWidth: 3;
|
|
145
148
|
readonly shadow: 3.5;
|
|
146
149
|
readonly stopRadius: 12;
|
|
150
|
+
readonly zonePadding: 32;
|
|
151
|
+
readonly zoneTitleTint: 0.6;
|
|
147
152
|
};
|
|
148
153
|
readonly motion: {
|
|
149
154
|
readonly dimOpacity: 0.42;
|
|
@@ -233,6 +238,7 @@ export declare const tokens: {
|
|
|
233
238
|
readonly rimWidth: 1;
|
|
234
239
|
readonly shadow: "#4C5CB8";
|
|
235
240
|
readonly text: "#EEF2FF";
|
|
241
|
+
readonly zoneOpacity: 0.22;
|
|
236
242
|
};
|
|
237
243
|
readonly light: {
|
|
238
244
|
readonly background: "#EEF2FF";
|
|
@@ -243,6 +249,7 @@ export declare const tokens: {
|
|
|
243
249
|
readonly rimWidth: 0;
|
|
244
250
|
readonly shadow: "#0A1033";
|
|
245
251
|
readonly text: "#0A1033";
|
|
252
|
+
readonly zoneOpacity: 0.12;
|
|
246
253
|
};
|
|
247
254
|
};
|
|
248
255
|
};
|
|
@@ -137,14 +137,19 @@ export const tokens = {
|
|
|
137
137
|
"countHeight": 16,
|
|
138
138
|
"countTextSize": 11,
|
|
139
139
|
"edgeWidth": 2.5,
|
|
140
|
+
"haloWidth": 1.5,
|
|
140
141
|
"interchangeExtra": 2,
|
|
141
142
|
"labelSize": 13,
|
|
143
|
+
"licenceSize": 10,
|
|
142
144
|
"lineWidth": 12,
|
|
143
145
|
"nodeHeight": 46,
|
|
144
146
|
"nodeRadius": 10,
|
|
145
147
|
"outline": 3,
|
|
148
|
+
"ringWidth": 3,
|
|
146
149
|
"shadow": 3.5,
|
|
147
|
-
"stopRadius": 12
|
|
150
|
+
"stopRadius": 12,
|
|
151
|
+
"zonePadding": 32,
|
|
152
|
+
"zoneTitleTint": 0.6
|
|
148
153
|
},
|
|
149
154
|
"motion": {
|
|
150
155
|
"dimOpacity": 0.42,
|
|
@@ -233,7 +238,8 @@ export const tokens = {
|
|
|
233
238
|
"rim": "#EEF2FF",
|
|
234
239
|
"rimWidth": 1,
|
|
235
240
|
"shadow": "#4C5CB8",
|
|
236
|
-
"text": "#EEF2FF"
|
|
241
|
+
"text": "#EEF2FF",
|
|
242
|
+
"zoneOpacity": 0.22
|
|
237
243
|
},
|
|
238
244
|
"light": {
|
|
239
245
|
"background": "#EEF2FF",
|
|
@@ -243,7 +249,8 @@ export const tokens = {
|
|
|
243
249
|
"rim": "#EEF2FF",
|
|
244
250
|
"rimWidth": 0,
|
|
245
251
|
"shadow": "#0A1033",
|
|
246
|
-
"text": "#0A1033"
|
|
252
|
+
"text": "#0A1033",
|
|
253
|
+
"zoneOpacity": 0.12
|
|
247
254
|
}
|
|
248
255
|
}
|
|
249
256
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brunosouzas/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
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": {
|
|
@@ -82,14 +82,19 @@
|
|
|
82
82
|
--ds-map-count-height: 16px;
|
|
83
83
|
--ds-map-count-text-size: 11px;
|
|
84
84
|
--ds-map-edge-width: 2.5px;
|
|
85
|
+
--ds-map-halo-width: 1.5px;
|
|
85
86
|
--ds-map-interchange-extra: 2px;
|
|
86
87
|
--ds-map-label-size: 13px;
|
|
88
|
+
--ds-map-licence-size: 10px;
|
|
87
89
|
--ds-map-line-width: 12px;
|
|
88
90
|
--ds-map-node-height: 46px;
|
|
89
91
|
--ds-map-node-radius: 10px;
|
|
90
92
|
--ds-map-outline: 3px;
|
|
93
|
+
--ds-map-ring-width: 3px;
|
|
91
94
|
--ds-map-shadow: 3.5px;
|
|
92
95
|
--ds-map-stop-radius: 12px;
|
|
96
|
+
--ds-map-zone-padding: 32px;
|
|
97
|
+
--ds-map-zone-title-tint: 0.6;
|
|
93
98
|
--ds-motion-dim-opacity: 0.42;
|
|
94
99
|
--ds-motion-draw-arrow: 20;
|
|
95
100
|
--ds-motion-fade: 10;
|
|
@@ -152,6 +157,7 @@
|
|
|
152
157
|
--ds-surface-dark-rim-width: 1px;
|
|
153
158
|
--ds-surface-dark-shadow: #4C5CB8;
|
|
154
159
|
--ds-surface-dark-text: #EEF2FF;
|
|
160
|
+
--ds-surface-dark-zone-opacity: 0.22;
|
|
155
161
|
--ds-surface-light-background: #EEF2FF;
|
|
156
162
|
--ds-surface-light-grid: #E0E7FB;
|
|
157
163
|
--ds-surface-light-muted: #5B6694;
|
|
@@ -160,4 +166,5 @@
|
|
|
160
166
|
--ds-surface-light-rim-width: 0px;
|
|
161
167
|
--ds-surface-light-shadow: #0A1033;
|
|
162
168
|
--ds-surface-light-text: #0A1033;
|
|
169
|
+
--ds-surface-light-zone-opacity: 0.12;
|
|
163
170
|
}
|
|
@@ -136,14 +136,19 @@
|
|
|
136
136
|
"countHeight": 16,
|
|
137
137
|
"countTextSize": 11,
|
|
138
138
|
"edgeWidth": 2.5,
|
|
139
|
+
"haloWidth": 1.5,
|
|
139
140
|
"interchangeExtra": 2,
|
|
140
141
|
"labelSize": 13,
|
|
142
|
+
"licenceSize": 10,
|
|
141
143
|
"lineWidth": 12,
|
|
142
144
|
"nodeHeight": 46,
|
|
143
145
|
"nodeRadius": 10,
|
|
144
146
|
"outline": 3,
|
|
147
|
+
"ringWidth": 3,
|
|
145
148
|
"shadow": 3.5,
|
|
146
|
-
"stopRadius": 12
|
|
149
|
+
"stopRadius": 12,
|
|
150
|
+
"zonePadding": 32,
|
|
151
|
+
"zoneTitleTint": 0.6
|
|
147
152
|
},
|
|
148
153
|
"motion": {
|
|
149
154
|
"dimOpacity": 0.42,
|
|
@@ -232,7 +237,8 @@
|
|
|
232
237
|
"rim": "#EEF2FF",
|
|
233
238
|
"rimWidth": 1,
|
|
234
239
|
"shadow": "#4C5CB8",
|
|
235
|
-
"text": "#EEF2FF"
|
|
240
|
+
"text": "#EEF2FF",
|
|
241
|
+
"zoneOpacity": 0.22
|
|
236
242
|
},
|
|
237
243
|
"light": {
|
|
238
244
|
"background": "#EEF2FF",
|
|
@@ -242,7 +248,8 @@
|
|
|
242
248
|
"rim": "#EEF2FF",
|
|
243
249
|
"rimWidth": 0,
|
|
244
250
|
"shadow": "#0A1033",
|
|
245
|
-
"text": "#0A1033"
|
|
251
|
+
"text": "#0A1033",
|
|
252
|
+
"zoneOpacity": 0.12
|
|
246
253
|
}
|
|
247
254
|
}
|
|
248
255
|
}
|
|
@@ -138,14 +138,19 @@ export const tokens = {
|
|
|
138
138
|
"countHeight": 16,
|
|
139
139
|
"countTextSize": 11,
|
|
140
140
|
"edgeWidth": 2.5,
|
|
141
|
+
"haloWidth": 1.5,
|
|
141
142
|
"interchangeExtra": 2,
|
|
142
143
|
"labelSize": 13,
|
|
144
|
+
"licenceSize": 10,
|
|
143
145
|
"lineWidth": 12,
|
|
144
146
|
"nodeHeight": 46,
|
|
145
147
|
"nodeRadius": 10,
|
|
146
148
|
"outline": 3,
|
|
149
|
+
"ringWidth": 3,
|
|
147
150
|
"shadow": 3.5,
|
|
148
|
-
"stopRadius": 12
|
|
151
|
+
"stopRadius": 12,
|
|
152
|
+
"zonePadding": 32,
|
|
153
|
+
"zoneTitleTint": 0.6
|
|
149
154
|
},
|
|
150
155
|
"motion": {
|
|
151
156
|
"dimOpacity": 0.42,
|
|
@@ -234,7 +239,8 @@ export const tokens = {
|
|
|
234
239
|
"rim": "#EEF2FF",
|
|
235
240
|
"rimWidth": 1,
|
|
236
241
|
"shadow": "#4C5CB8",
|
|
237
|
-
"text": "#EEF2FF"
|
|
242
|
+
"text": "#EEF2FF",
|
|
243
|
+
"zoneOpacity": 0.22
|
|
238
244
|
},
|
|
239
245
|
"light": {
|
|
240
246
|
"background": "#EEF2FF",
|
|
@@ -244,7 +250,8 @@ export const tokens = {
|
|
|
244
250
|
"rim": "#EEF2FF",
|
|
245
251
|
"rimWidth": 0,
|
|
246
252
|
"shadow": "#0A1033",
|
|
247
|
-
"text": "#0A1033"
|
|
253
|
+
"text": "#0A1033",
|
|
254
|
+
"zoneOpacity": 0.12
|
|
248
255
|
}
|
|
249
256
|
}
|
|
250
257
|
} as const;
|