@baloise/ds-tokens 20.0.0-next.7 → 20.0.0-next.9
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/dist/css/base.tokens.css +244 -244
- package/dist/docs/base.tokens.json +41726 -41727
- package/dist/js/base.tokens.js +268 -268
- package/dist/out-tsc/config.brand.js +1 -1
- package/dist/out-tsc/css-naming.js +26 -0
- package/dist/out-tsc/css-preview.js +8 -0
- package/dist/out-tsc/css-value.js +86 -0
- package/dist/out-tsc/formatter.js +3 -3
- package/dist/out-tsc/transformers.js +6 -79
- package/dist/sass/base.tokens.scss +233 -233
- package/dist/web/base.tokens.json +273 -273
- package/package.json +6 -1
- package/sbom.cdx.json +35379 -17251
|
@@ -5,7 +5,7 @@ const basePxFontSize = 16;
|
|
|
5
5
|
* `$value` differs from the base. Keeps the full hierarchy so Style
|
|
6
6
|
* Dictionary can still resolve references.
|
|
7
7
|
*/
|
|
8
|
-
function computeTokenDiff(base, brand) {
|
|
8
|
+
export function computeTokenDiff(base, brand) {
|
|
9
9
|
const result = {};
|
|
10
10
|
for (const [key, brandVal] of Object.entries(brand)) {
|
|
11
11
|
if (typeof brandVal !== 'object' || brandVal === null)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { kebabCase } from 'change-case';
|
|
2
|
+
/**
|
|
3
|
+
* Turns a token's path into its final CSS custom property name, matching Style Dictionary's
|
|
4
|
+
* `css` transformGroup (`name/kebab`, which itself uses `change-case`'s `kebabCase`) followed by
|
|
5
|
+
* the `ds/css/name` transform (`transformers.ts`). Returns the bare name (no leading `--`), the
|
|
6
|
+
* same shape Style Dictionary expects from a `name`-type transform - the SD transform is a thin
|
|
7
|
+
* wrapper around this function, and `apps/toky`'s live preview imports it directly so both stay
|
|
8
|
+
* in sync (see ADR-0021).
|
|
9
|
+
*/
|
|
10
|
+
export const tokenNameToCssVar = (pathSegments, prefix = 'ds') => {
|
|
11
|
+
let tokenName = kebabCase([prefix, ...pathSegments].join(' '));
|
|
12
|
+
const isComponent = pathSegments.includes('🧩 Component');
|
|
13
|
+
if (isComponent) {
|
|
14
|
+
tokenName = tokenName.replace('-component', '');
|
|
15
|
+
}
|
|
16
|
+
// we use t-shirt sizes and need to make sure that 2xl becomes 2xl and not 2-xl
|
|
17
|
+
// check if token names has number followed by xl or xs and replace it with numberxl without dash
|
|
18
|
+
if (/-?([0-9]+)-(xl|xs)/.test(tokenName)) {
|
|
19
|
+
tokenName = tokenName.replace(/-?([0-9]+)-(xl|xs)/, '-$1$2');
|
|
20
|
+
}
|
|
21
|
+
// check that no name has double dash and replace it with single dash
|
|
22
|
+
if (tokenName.includes('--')) {
|
|
23
|
+
tokenName = tokenName.replace(/--+/g, '-');
|
|
24
|
+
}
|
|
25
|
+
return tokenName;
|
|
26
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public subpath (`@baloise/ds-tokens/css-preview`) for consumers outside the build pipeline —
|
|
3
|
+
* currently `apps/toky`'s live token preview — that need to turn a token path/resolved value into
|
|
4
|
+
* the same CSS the build actually produces, without duplicating the Style Dictionary transforms.
|
|
5
|
+
* See ADR-0021.
|
|
6
|
+
*/
|
|
7
|
+
export { tokenNameToCssVar } from './css-naming.js';
|
|
8
|
+
export { resolvedValueToCss } from './css-value.js';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { tokenNameToCssVar } from './css-naming.js';
|
|
2
|
+
/**
|
|
3
|
+
* Mirrors the `ds/color/rgba` transform: DTCG color values already carry a `hex` field in this
|
|
4
|
+
* token set (see `tokens/Base.tokens.json`), so this only needs to add an `rgba()` wrapper when
|
|
5
|
+
* `alpha < 1`.
|
|
6
|
+
*/
|
|
7
|
+
export const colorValueToCss = (value) => {
|
|
8
|
+
if (typeof value !== 'object' || value === null || !('hex' in value)) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const { hex, alpha } = value;
|
|
12
|
+
if (typeof hex !== 'string') {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
if (typeof alpha === 'number' && alpha < 1) {
|
|
16
|
+
const stripped = hex.replace('#', '');
|
|
17
|
+
const r = parseInt(stripped.substring(0, 2), 16);
|
|
18
|
+
const g = parseInt(stripped.substring(2, 4), 16);
|
|
19
|
+
const b = parseInt(stripped.substring(4, 6), 16);
|
|
20
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
21
|
+
}
|
|
22
|
+
return hex;
|
|
23
|
+
};
|
|
24
|
+
const ROUND_TOKEN_NAME_MARKERS = ['line-height', 'lineheight', 'opacity'];
|
|
25
|
+
/**
|
|
26
|
+
* Mirrors `ds/size/round`. Case-insensitive because callers pass different name casings
|
|
27
|
+
* depending on the platform's name transform - kebab-case for CSS/SCSS (`ds/css/name`), PascalCase
|
|
28
|
+
* for JS (`ds/js/name`).
|
|
29
|
+
*/
|
|
30
|
+
export const roundNumberValue = (value, tokenName) => {
|
|
31
|
+
const lowerName = tokenName.toLowerCase();
|
|
32
|
+
if (ROUND_TOKEN_NAME_MARKERS.some(marker => lowerName.includes(marker))) {
|
|
33
|
+
return Math.round(value * 10) / 10;
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
};
|
|
37
|
+
const NUMBER_ONLY_PATH_MARKERS = [
|
|
38
|
+
'LineHeight',
|
|
39
|
+
'FontWeight',
|
|
40
|
+
'Opacity',
|
|
41
|
+
'🌫️ Opacity',
|
|
42
|
+
'ZIndex',
|
|
43
|
+
'Z-Index',
|
|
44
|
+
'🗂️ ZIndex',
|
|
45
|
+
'🗂️ Z-Index',
|
|
46
|
+
'Interaction',
|
|
47
|
+
'✨ Interaction',
|
|
48
|
+
];
|
|
49
|
+
const PIXEL_PATH_MARKERS = ['📐 Breakpoint', 'Breakpoint', '🗃️ Container', 'Container'];
|
|
50
|
+
/** Mirrors `ds/size/rem`: converts a px number into rem, unless the token's path says otherwise. */
|
|
51
|
+
export const numberValueToCssSize = (value, path) => {
|
|
52
|
+
if (`${value}`.endsWith('px') || `${value}`.endsWith('rem')) {
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
if (NUMBER_ONLY_PATH_MARKERS.some(marker => path.includes(marker))) {
|
|
56
|
+
return Math.round(value * 10) / 10;
|
|
57
|
+
}
|
|
58
|
+
if (PIXEL_PATH_MARKERS.some(marker => path.includes(marker))) {
|
|
59
|
+
return `${value}px`;
|
|
60
|
+
}
|
|
61
|
+
if (value === 9999) {
|
|
62
|
+
return `${value}px`;
|
|
63
|
+
}
|
|
64
|
+
return `${value / 16}rem`;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Turns a resolved DTCG token value into a CSS-ready string, for the live token preview
|
|
68
|
+
* (`apps/toky`) to send as a `--ds-*` custom property value. Mirrors the `ds/color/rgba` /
|
|
69
|
+
* `ds/size/round` / `ds/size/rem` Style Dictionary transforms via the functions above, so the
|
|
70
|
+
* preview never drifts from what the build actually produces (see ADR-0021). Returns `null` for
|
|
71
|
+
* value shapes it doesn't recognize, so the caller can skip that token rather than send garbage.
|
|
72
|
+
*/
|
|
73
|
+
export const resolvedValueToCss = (value, type, path) => {
|
|
74
|
+
if (type === 'color') {
|
|
75
|
+
return colorValueToCss(value);
|
|
76
|
+
}
|
|
77
|
+
if (type === 'number' && typeof value === 'number') {
|
|
78
|
+
const cssVarName = tokenNameToCssVar(path);
|
|
79
|
+
const rounded = roundNumberValue(value, cssVarName);
|
|
80
|
+
return `${numberValueToCssSize(rounded, path)}`;
|
|
81
|
+
}
|
|
82
|
+
if (type === 'string' && typeof value === 'string') {
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
};
|
|
@@ -100,7 +100,7 @@ export const registerCustomFormatters = (sd) => {
|
|
|
100
100
|
// `\n}\n` +
|
|
101
101
|
// '\n'
|
|
102
102
|
return (header +
|
|
103
|
-
':root {\n' +
|
|
103
|
+
':root, :host {\n' +
|
|
104
104
|
formattedVariables({
|
|
105
105
|
format: propertyFormatNames.css,
|
|
106
106
|
dictionary,
|
|
@@ -126,7 +126,7 @@ export const registerCustomFormatters = (sd) => {
|
|
|
126
126
|
'\n}\n\n' +
|
|
127
127
|
'/* Device tokens: Tablet */\n' +
|
|
128
128
|
`\n@media (min-width: 769px) {\n` +
|
|
129
|
-
':root {\n' +
|
|
129
|
+
':root, :host {\n' +
|
|
130
130
|
formattedVariables({
|
|
131
131
|
format: propertyFormatNames.css,
|
|
132
132
|
dictionary: deviceTabletDictionary,
|
|
@@ -137,7 +137,7 @@ export const registerCustomFormatters = (sd) => {
|
|
|
137
137
|
`\n}\n\n` +
|
|
138
138
|
'/* Device tokens: Desktop */\n' +
|
|
139
139
|
`\n@media (min-width: 1024px) {\n` +
|
|
140
|
-
':root {\n' +
|
|
140
|
+
':root, :host {\n' +
|
|
141
141
|
formattedVariables({
|
|
142
142
|
format: propertyFormatNames.css,
|
|
143
143
|
dictionary: deviceDesktopDictionary,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { colorValueToCss, numberValueToCssSize, roundNumberValue } from './css-value.js';
|
|
2
|
+
import { tokenNameToCssVar } from './css-naming.js';
|
|
1
3
|
export const registerCustomTransformers = (sd) => {
|
|
2
4
|
/**
|
|
3
5
|
* Transform color tokens with hex and alpha properties to rgba() format
|
|
@@ -9,19 +11,7 @@ export const registerCustomTransformers = (sd) => {
|
|
|
9
11
|
filter: token => token.$type === 'color',
|
|
10
12
|
transform: token => {
|
|
11
13
|
const value = token.$value ?? token.value;
|
|
12
|
-
|
|
13
|
-
if (typeof value === 'object' && value !== null && 'hex' in value && 'alpha' in value && value.alpha < 1) {
|
|
14
|
-
const hex = value.hex.replace('#', '');
|
|
15
|
-
const r = parseInt(hex.substring(0, 2), 16);
|
|
16
|
-
const g = parseInt(hex.substring(2, 4), 16);
|
|
17
|
-
const b = parseInt(hex.substring(4, 6), 16);
|
|
18
|
-
const a = parseFloat(value.alpha);
|
|
19
|
-
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
20
|
-
}
|
|
21
|
-
if (value.hex) {
|
|
22
|
-
return value.hex;
|
|
23
|
-
}
|
|
24
|
-
return value;
|
|
14
|
+
return colorValueToCss(value) ?? value;
|
|
25
15
|
},
|
|
26
16
|
});
|
|
27
17
|
/**
|
|
@@ -48,23 +38,7 @@ export const registerCustomTransformers = (sd) => {
|
|
|
48
38
|
type: `name`,
|
|
49
39
|
transitive: true,
|
|
50
40
|
name: `ds/css/name`,
|
|
51
|
-
transform: token =>
|
|
52
|
-
let tokenName = token.name;
|
|
53
|
-
const isComponent = token.path.includes('🧩 Component');
|
|
54
|
-
if (isComponent) {
|
|
55
|
-
tokenName = tokenName.replace('-component', '');
|
|
56
|
-
}
|
|
57
|
-
// we use t-shirt sizes and need to make sure that 2xl becomes 2xl and not 2-xl
|
|
58
|
-
// check if token names has number followed by xl or xs and replace it with numberxl without dash
|
|
59
|
-
if (/-?([0-9]+)-(xl|xs)/.test(tokenName)) {
|
|
60
|
-
tokenName = tokenName.replace(/-?([0-9]+)-(xl|xs)/, '-$1$2');
|
|
61
|
-
}
|
|
62
|
-
// check that no name has double dash and replace it with single dash
|
|
63
|
-
if (tokenName.includes('--')) {
|
|
64
|
-
tokenName = tokenName.replace(/--+/g, '-');
|
|
65
|
-
}
|
|
66
|
-
return tokenName;
|
|
67
|
-
},
|
|
41
|
+
transform: (token, config) => tokenNameToCssVar(token.path, config.prefix ?? 'ds'),
|
|
68
42
|
});
|
|
69
43
|
/**
|
|
70
44
|
* Transform token names for CSS usage
|
|
@@ -88,47 +62,7 @@ export const registerCustomTransformers = (sd) => {
|
|
|
88
62
|
transitive: true,
|
|
89
63
|
name: `ds/size/rem`,
|
|
90
64
|
filter: token => token.$type === 'number',
|
|
91
|
-
transform: token =>
|
|
92
|
-
// const name = token.name
|
|
93
|
-
const value = token.$value;
|
|
94
|
-
// const originalValue = token.original.$value
|
|
95
|
-
const path = token.path;
|
|
96
|
-
// const isReference =
|
|
97
|
-
// typeof originalValue === 'string' && originalValue.startsWith('{') && originalValue.endsWith('}')
|
|
98
|
-
if (`${value}`.endsWith('px')) {
|
|
99
|
-
return value;
|
|
100
|
-
}
|
|
101
|
-
if (`${value}`.endsWith('rem')) {
|
|
102
|
-
return value;
|
|
103
|
-
}
|
|
104
|
-
// Number only values with no unit
|
|
105
|
-
const tokenToBeNumberOnly = [
|
|
106
|
-
'LineHeight',
|
|
107
|
-
'FontWeight',
|
|
108
|
-
'Opacity',
|
|
109
|
-
'🌫️ Opacity',
|
|
110
|
-
'ZIndex',
|
|
111
|
-
'Z-Index',
|
|
112
|
-
'🗂️ ZIndex',
|
|
113
|
-
'🗂️ Z-Index',
|
|
114
|
-
'Interaction',
|
|
115
|
-
'✨ Interaction',
|
|
116
|
-
];
|
|
117
|
-
if (tokenToBeNumberOnly.some(ignored => path.includes(ignored))) {
|
|
118
|
-
return Math.round(value * 10) / 10;
|
|
119
|
-
}
|
|
120
|
-
// Number only values with no unit
|
|
121
|
-
const tokenToBeNumberPixel = ['📐 Breakpoint', 'Breakpoint', '🗃️ Container', 'Container'];
|
|
122
|
-
if (tokenToBeNumberPixel.some(ignored => path.includes(ignored))) {
|
|
123
|
-
return value + 'px';
|
|
124
|
-
}
|
|
125
|
-
// Extra case for rounded radius
|
|
126
|
-
if (value === 9999) {
|
|
127
|
-
return value + 'px';
|
|
128
|
-
}
|
|
129
|
-
// turn pixel into rem
|
|
130
|
-
return value / 16 + 'rem';
|
|
131
|
-
},
|
|
65
|
+
transform: token => numberValueToCssSize(token.$value, token.path),
|
|
132
66
|
});
|
|
133
67
|
sd.registerTransform({
|
|
134
68
|
type: `value`,
|
|
@@ -139,14 +73,7 @@ export const registerCustomTransformers = (sd) => {
|
|
|
139
73
|
const value = token.$value ?? token.value;
|
|
140
74
|
const name = token.name;
|
|
141
75
|
const tokenName = Array.isArray(name) ? name.join('-') : String(name ?? '');
|
|
142
|
-
|
|
143
|
-
if (tokenName.includes('line-height') ||
|
|
144
|
-
tokenName.includes('opacity') ||
|
|
145
|
-
tokenName.includes('LineHeight') ||
|
|
146
|
-
tokenName.includes('Opacity')) {
|
|
147
|
-
return Math.round(value * 10) / 10;
|
|
148
|
-
}
|
|
149
|
-
return value;
|
|
76
|
+
return roundNumberValue(value, tokenName);
|
|
150
77
|
},
|
|
151
78
|
});
|
|
152
79
|
};
|