@vectoriox/iox-ui 5.32.1 → 5.34.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/composite-core/index.d.ts +4 -1
- package/design-core/index.d.ts +59 -5
- package/fesm2022/vectoriox-iox-ui-composite-core.mjs +9 -8
- package/fesm2022/vectoriox-iox-ui-composite-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-design-core.mjs +740 -604
- package/fesm2022/vectoriox-iox-ui-design-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs +25 -51
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui.mjs +42 -1
- package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
- package/index.d.ts +16 -1
- package/package.json +1 -1
- package/src/composite-core/badge.ts +4 -3
- package/src/composite-core/card.ts +4 -4
- package/src/design-core/contrast-audit.ts +50 -1
- package/src/design-core/flavor-spec.generated.ts +20 -0
- package/src/design-core/node-classes.ts +49 -1
- package/src/design-core/token-css.ts +39 -11
- package/src/generation-core/node-baselines.generated.ts +25 -51
|
@@ -1341,6 +1341,7 @@ const SPEC_SCHEMES = {
|
|
|
1341
1341
|
"set": {
|
|
1342
1342
|
"section-bg": "{{accent}}",
|
|
1343
1343
|
"bg": "{{accent}}",
|
|
1344
|
+
"nav-bg": "{{accent}}",
|
|
1344
1345
|
"surface": "{{accent-hover}}",
|
|
1345
1346
|
"surface-2": "{{accent-hover}}",
|
|
1346
1347
|
"surface-glass": "{{accent-hover}}",
|
|
@@ -1363,6 +1364,7 @@ const SPEC_SCHEMES = {
|
|
|
1363
1364
|
}
|
|
1364
1365
|
}
|
|
1365
1366
|
};
|
|
1367
|
+
const SPEC_SCHEME_INK = "var(--iox-text)";
|
|
1366
1368
|
const SPEC_A11Y = {
|
|
1367
1369
|
"reducedMotion": {
|
|
1368
1370
|
"dur-fast": "0ms",
|
|
@@ -2003,6 +2005,23 @@ const SPEC_ELEMENT_STYLES = [
|
|
|
2003
2005
|
"fontWeight": "var(--iox-weight-label)"
|
|
2004
2006
|
}
|
|
2005
2007
|
},
|
|
2008
|
+
{
|
|
2009
|
+
"id": "badge-label",
|
|
2010
|
+
"label": "Badge label",
|
|
2011
|
+
"group": "Content blocks",
|
|
2012
|
+
"appliesTo": [
|
|
2013
|
+
"Text"
|
|
2014
|
+
],
|
|
2015
|
+
"base": {
|
|
2016
|
+
"fontFamily": "var(--iox-font-label)",
|
|
2017
|
+
"fontSize": "var(--iox-badge-size)",
|
|
2018
|
+
"fontWeight": "var(--iox-weight-label)",
|
|
2019
|
+
"lineHeight": "inherit",
|
|
2020
|
+
"letterSpacing": "inherit",
|
|
2021
|
+
"textTransform": "inherit",
|
|
2022
|
+
"color": "inherit"
|
|
2023
|
+
}
|
|
2024
|
+
},
|
|
2006
2025
|
{
|
|
2007
2026
|
"id": "media-scrim",
|
|
2008
2027
|
"label": "Text over image",
|
|
@@ -12226,570 +12245,754 @@ function styleKeyToKebab(key) {
|
|
|
12226
12245
|
}
|
|
12227
12246
|
|
|
12228
12247
|
/**
|
|
12229
|
-
*
|
|
12230
|
-
*
|
|
12231
|
-
*
|
|
12232
|
-
*
|
|
12233
|
-
*
|
|
12248
|
+
* Element styles — the author's "classes" (design-system plan §3b). A named look is an EXACT trait
|
|
12249
|
+
* map written into a node; every value is a `var(--iox-…)` reference or a flavor-independent
|
|
12250
|
+
* keyword, so a re-theme rewrites token rows and every node wearing the style follows. No renderer
|
|
12251
|
+
* reads `elementStyle`: it records which look a node wears, for the panel row, Reset, adopt and AI.
|
|
12252
|
+
*
|
|
12253
|
+
* Works on two node shapes through one minimal interface, so the builder (a ComponentNode whose
|
|
12254
|
+
* values live in `styleTraits[].traits[].default`) and the server-side composer (a plain serialized
|
|
12255
|
+
* layout node with `styleProps`) share every function here.
|
|
12234
12256
|
*/
|
|
12235
|
-
|
|
12236
|
-
function
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
]
|
|
12257
|
+
var ElementStyleState;
|
|
12258
|
+
(function (ElementStyleState) {
|
|
12259
|
+
ElementStyleState["Hover"] = "hover";
|
|
12260
|
+
ElementStyleState["Active"] = "active";
|
|
12261
|
+
ElementStyleState["Focus"] = "focus";
|
|
12262
|
+
/** The page you're on (CC1 N2): compiles to `[aria-current="page"]`, never a pseudo-class. */
|
|
12263
|
+
ElementStyleState["Current"] = "current";
|
|
12264
|
+
})(ElementStyleState || (ElementStyleState = {}));
|
|
12265
|
+
const ELEMENT_STYLE_STATES = [ElementStyleState.Hover, ElementStyleState.Active, ElementStyleState.Focus, ElementStyleState.Current];
|
|
12266
|
+
const ELEMENT_STYLES = SPEC_ELEMENT_STYLES;
|
|
12267
|
+
/** Legacy `Button.variant` → the element style it maps to (adopt, DS7). */
|
|
12268
|
+
const BUTTON_VARIANT_TO_STYLE = SPEC_BUTTON_VARIANT_TO_STYLE;
|
|
12269
|
+
/** Palette entries that are a Container wearing an element style (Card · Panel · Navigation bar). */
|
|
12270
|
+
const PALETTE_PRESETS = SPEC_PALETTE_PRESETS;
|
|
12271
|
+
const BY_ID = new Map(ELEMENT_STYLES.map(s => [s.id, s]));
|
|
12272
|
+
function elementStyleById(id) {
|
|
12273
|
+
return id ? BY_ID.get(id) : undefined;
|
|
12242
12274
|
}
|
|
12243
|
-
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
return [...new Set(Array.from(css.matchAll(REFERENCE$1), m => m[1]))];
|
|
12275
|
+
/** The styles a node of `type` may wear — the Style panel's select. */
|
|
12276
|
+
function elementStylesFor(type) {
|
|
12277
|
+
return ELEMENT_STYLES.filter(s => s.appliesTo.includes(type));
|
|
12247
12278
|
}
|
|
12248
|
-
|
|
12249
|
-
function
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12279
|
+
var OwnedTraitLink;
|
|
12280
|
+
(function (OwnedTraitLink) {
|
|
12281
|
+
/** The node still holds the style's value. */
|
|
12282
|
+
OwnedTraitLink["Linked"] = "linked";
|
|
12283
|
+
/** The author replaced it on this node. */
|
|
12284
|
+
OwnedTraitLink["Changed"] = "changed";
|
|
12285
|
+
})(OwnedTraitLink || (OwnedTraitLink = {}));
|
|
12286
|
+
const usesTraits = (t) => Array.isArray(t.styleTraits);
|
|
12287
|
+
function findTrait(target, name) {
|
|
12288
|
+
for (const group of target.styleTraits ?? []) {
|
|
12289
|
+
const hit = group.traits.find(tr => tr.name === name);
|
|
12290
|
+
if (hit)
|
|
12291
|
+
return hit;
|
|
12292
|
+
}
|
|
12293
|
+
return undefined;
|
|
12253
12294
|
}
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
const stripComments = (css) => String(css ?? '')
|
|
12257
|
-
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
12258
|
-
.replace(/(^|[^:\\])\/\/[^\n]*/g, '$1');
|
|
12259
|
-
/** A nested SCSS selector against its parent's: `&` is the parent; no `&` means a descendant. */
|
|
12260
|
-
function resolveNested(parent, selector) {
|
|
12261
|
-
if (!parent)
|
|
12262
|
-
return selector;
|
|
12263
|
-
return selector.split(',').map(part => {
|
|
12264
|
-
const own = part.trim();
|
|
12265
|
-
return own.includes('&') ? own.replace(/&/g, parent) : `${parent} ${own}`;
|
|
12266
|
-
}).join(', ');
|
|
12295
|
+
function readBase(target, name) {
|
|
12296
|
+
return usesTraits(target) ? findTrait(target, name)?.default : target.styleProps?.[name];
|
|
12267
12297
|
}
|
|
12268
|
-
/**
|
|
12269
|
-
|
|
12270
|
-
|
|
12271
|
-
|
|
12272
|
-
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12298
|
+
/** False when a builder node has no such trait — the value would be dropped. */
|
|
12299
|
+
function writeBase(target, name, value) {
|
|
12300
|
+
if (usesTraits(target)) {
|
|
12301
|
+
const trait = findTrait(target, name);
|
|
12302
|
+
if (!trait)
|
|
12303
|
+
return false;
|
|
12304
|
+
trait.default = value;
|
|
12305
|
+
return true;
|
|
12306
|
+
}
|
|
12307
|
+
target.styleProps = target.styleProps ?? {};
|
|
12308
|
+
if (value === undefined)
|
|
12309
|
+
delete target.styleProps[name];
|
|
12310
|
+
else
|
|
12311
|
+
target.styleProps[name] = value;
|
|
12312
|
+
return true;
|
|
12313
|
+
}
|
|
12314
|
+
function readState(target, state, name) {
|
|
12315
|
+
return target.stateStyles?.[state]?.[name];
|
|
12316
|
+
}
|
|
12317
|
+
function writeState(target, state, name, value) {
|
|
12318
|
+
target.stateStyles = target.stateStyles ?? {};
|
|
12319
|
+
target.stateStyles[state] = { ...(target.stateStyles[state] ?? {}), [name]: value };
|
|
12320
|
+
}
|
|
12321
|
+
function deleteState(target, state, name) {
|
|
12322
|
+
const map = target.stateStyles?.[state];
|
|
12323
|
+
if (!map)
|
|
12324
|
+
return;
|
|
12325
|
+
const { [name]: _drop, ...rest } = map;
|
|
12326
|
+
if (Object.keys(rest).length)
|
|
12327
|
+
target.stateStyles[state] = rest;
|
|
12328
|
+
else
|
|
12329
|
+
delete target.stateStyles[state];
|
|
12330
|
+
}
|
|
12331
|
+
/** Every (state, trait, value) a style owns, base first. */
|
|
12332
|
+
function ownedEntries(style) {
|
|
12278
12333
|
const out = [];
|
|
12279
|
-
const
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
if (tokens.length)
|
|
12285
|
-
out.push({ selector: frame.selector, tokens });
|
|
12286
|
-
};
|
|
12287
|
-
let buffer = '';
|
|
12288
|
-
for (const ch of text) {
|
|
12289
|
-
if (ch === '{') {
|
|
12290
|
-
const head = buffer.trim().replace(/\s+/g, ' ');
|
|
12291
|
-
buffer = '';
|
|
12292
|
-
// Declarations before a nested block belong to the parent (`color: x; &:hover {`).
|
|
12293
|
-
const cut = head.lastIndexOf(';');
|
|
12294
|
-
const prelude = cut >= 0 ? head.slice(cut + 1).trim() : head;
|
|
12295
|
-
const parent = stack[stack.length - 1];
|
|
12296
|
-
if (parent && cut >= 0)
|
|
12297
|
-
parent.body += head.slice(0, cut + 1);
|
|
12298
|
-
const inherited = parent?.selector ?? '';
|
|
12299
|
-
const selector = prelude.startsWith('@') ? inherited : resolveNested(inherited, prelude);
|
|
12300
|
-
stack.push({ selector, body: '' });
|
|
12301
|
-
}
|
|
12302
|
-
else if (ch === '}') {
|
|
12303
|
-
const frame = stack.pop();
|
|
12304
|
-
if (frame) {
|
|
12305
|
-
frame.body += buffer;
|
|
12306
|
-
report(frame);
|
|
12307
|
-
}
|
|
12308
|
-
buffer = '';
|
|
12309
|
-
}
|
|
12310
|
-
else if (ch === ';' && stack.length) {
|
|
12311
|
-
stack[stack.length - 1].body += buffer + ch;
|
|
12312
|
-
buffer = '';
|
|
12313
|
-
}
|
|
12314
|
-
else {
|
|
12315
|
-
buffer += ch;
|
|
12316
|
-
}
|
|
12334
|
+
for (const [trait, value] of Object.entries(style.base))
|
|
12335
|
+
out.push({ trait, value });
|
|
12336
|
+
for (const state of ELEMENT_STYLE_STATES) {
|
|
12337
|
+
for (const [trait, value] of Object.entries(style[state] ?? {}))
|
|
12338
|
+
out.push({ trait, state, value });
|
|
12317
12339
|
}
|
|
12318
12340
|
return out;
|
|
12319
12341
|
}
|
|
12320
|
-
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
/** What `prefers-reduced-transparency: reduce` makes solid — the contract's `a11y.reducedTransparency`. */
|
|
12324
|
-
const REDUCED_TRANSPARENCY_OVERRIDES = SPEC_A11Y.reducedTransparency;
|
|
12325
|
-
const ROOT = ':root';
|
|
12326
|
-
const DEFAULT_SCHEME$1 = 'default';
|
|
12327
|
-
const REFERENCE = 'var(';
|
|
12328
|
-
const MEDIA_DARK = '(prefers-color-scheme: dark)';
|
|
12329
|
-
const ACCESSIBILITY_MEDIA = [
|
|
12330
|
-
{ query: '(prefers-reduced-motion: reduce)', overrides: REDUCED_MOTION_OVERRIDES },
|
|
12331
|
-
{ query: '(prefers-reduced-transparency: reduce)', overrides: REDUCED_TRANSPARENCY_OVERRIDES },
|
|
12332
|
-
];
|
|
12333
|
-
const usable = (t) => !!t && typeof t.name === 'string' && t.name !== '' &&
|
|
12334
|
-
typeof t.value === 'string' && t.value !== '';
|
|
12335
|
-
const darkOf = (t) => {
|
|
12336
|
-
const dark = t.values?.dark;
|
|
12337
|
-
return typeof dark === 'string' && dark !== '' ? dark : null;
|
|
12338
|
-
};
|
|
12339
|
-
const usableTokens = (tokens) => (tokens ?? []).filter(usable);
|
|
12340
|
-
const declarations = (entries, indent) => entries.map(([name, value]) => `${indent}--iox-${name}: ${value};`).join('\n');
|
|
12341
|
-
const rule = (selector, entries, indent = '') => entries.length ? `${indent}${selector} {\n${declarations(entries, indent + ' ')}\n${indent}}` : '';
|
|
12342
|
-
const media = (query, rules) => {
|
|
12343
|
-
const body = rules.filter(Boolean);
|
|
12344
|
-
return body.length ? `@media ${query} {\n${body.join('\n')}\n}` : '';
|
|
12345
|
-
};
|
|
12346
|
-
const schemeSelector = (id, scope) => scope ? `${scope} .iox-scheme-${id}` : `.iox-scheme-${id}`;
|
|
12347
|
-
const nonDefaultSchemes = () => Object.entries(SPEC_SCHEMES)
|
|
12348
|
-
.filter(([id]) => id !== DEFAULT_SCHEME$1)
|
|
12349
|
-
.map(([id, scheme]) => [id, scheme.set]);
|
|
12350
|
-
/** `{ 'iox-brand': '#2f6f62', … }` — the builder registry's input shape for base values. */
|
|
12351
|
-
function tokensToVarMap(tokens) {
|
|
12352
|
-
const map = {};
|
|
12353
|
-
for (const t of usableTokens(tokens))
|
|
12354
|
-
map[`iox-${t.name}`] = t.value;
|
|
12355
|
-
return map;
|
|
12342
|
+
/** Every trait the style owns with the value it writes — base first, then hover/active/focus/current. */
|
|
12343
|
+
function ownedTraitsOf(style) {
|
|
12344
|
+
return ownedEntries(style);
|
|
12356
12345
|
}
|
|
12357
|
-
/**
|
|
12358
|
-
function
|
|
12359
|
-
|
|
12360
|
-
for (const t of usableTokens(tokens)) {
|
|
12361
|
-
const dark = darkOf(t);
|
|
12362
|
-
if (dark !== null)
|
|
12363
|
-
map[`iox-${t.name}`] = dark;
|
|
12364
|
-
}
|
|
12365
|
-
return map;
|
|
12346
|
+
/** The node's value of one owned trait (a base trait, or a trait inside a pseudo-state map). */
|
|
12347
|
+
function readOwnedTrait(target, owned) {
|
|
12348
|
+
return owned.state ? readState(target, owned.state, owned.trait) : readBase(target, owned.trait);
|
|
12366
12349
|
}
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
|
|
12373
|
-
* the rows unchanged. */
|
|
12374
|
-
function rowsForMode(rows, mode) {
|
|
12375
|
-
if (mode !== LIGHT && mode !== DARK)
|
|
12376
|
-
return [...rows];
|
|
12377
|
-
return rows.map(t => {
|
|
12378
|
-
const { values: _dropped, ...rest } = t;
|
|
12379
|
-
return { ...rest, value: modeValue(t, mode) };
|
|
12380
|
-
});
|
|
12350
|
+
/** Write one owned trait. False when a builder node has no slot for a base trait (dropped). */
|
|
12351
|
+
function writeOwnedTrait(target, owned, value) {
|
|
12352
|
+
if (!owned.state)
|
|
12353
|
+
return writeBase(target, owned.trait, value);
|
|
12354
|
+
writeState(target, owned.state, owned.trait, value);
|
|
12355
|
+
return true;
|
|
12381
12356
|
}
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
|
|
12387
|
-
|
|
12388
|
-
if (
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
return null;
|
|
12393
|
-
const next = new Set(trail).add(name);
|
|
12394
|
-
return value.replace(TOKEN_REF$1, (ref, inner, fallback) => resolve(inner, next) ?? (fallback !== undefined ? fallback.trim() : ref));
|
|
12395
|
-
};
|
|
12396
|
-
for (const name of raw.keys()) {
|
|
12397
|
-
const value = resolve(name, new Set());
|
|
12398
|
-
if (value !== null)
|
|
12399
|
-
out[name] = value;
|
|
12357
|
+
const sameOwned = (a, b) => a.trait === b.trait && a.state === b.state;
|
|
12358
|
+
function writeEntries(target, style, skip = []) {
|
|
12359
|
+
const unknown = [];
|
|
12360
|
+
for (const entry of ownedEntries(style)) {
|
|
12361
|
+
if (skip.some(s => sameOwned(s, entry)))
|
|
12362
|
+
continue;
|
|
12363
|
+
if (entry.state)
|
|
12364
|
+
writeState(target, entry.state, entry.trait, entry.value);
|
|
12365
|
+
else if (!writeBase(target, entry.trait, entry.value))
|
|
12366
|
+
unknown.push(entry.trait);
|
|
12400
12367
|
}
|
|
12401
|
-
|
|
12368
|
+
target.elementStyle = style.id;
|
|
12369
|
+
return unknown;
|
|
12402
12370
|
}
|
|
12403
|
-
/**
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
function resolveSchemeTokenValues(tokens, mode, schemeId) {
|
|
12410
|
-
const rows = usableTokens(tokens);
|
|
12411
|
-
const set = schemeId === DEFAULT_SCHEME$1 ? undefined : SPEC_SCHEMES[schemeId]?.set;
|
|
12412
|
-
if (!set)
|
|
12413
|
-
return resolveTokenValues(rows, mode);
|
|
12414
|
-
const root = resolveTokenValues(rows, mode);
|
|
12415
|
-
const other = resolveTokenValues(rows, mode === DARK ? LIGHT : DARK);
|
|
12416
|
-
const overrides = new Map(schemeEntries(set, root, other));
|
|
12417
|
-
return resolveTokenValues(rows.map(t => ({ name: t.name, value: overrides.get(t.name) ?? modeValue(t, mode) })), LIGHT);
|
|
12371
|
+
/** Write the style's exact base map and its hover/active/focus/current maps into the target. */
|
|
12372
|
+
function applyElementStyle(target, id) {
|
|
12373
|
+
const style = elementStyleById(id);
|
|
12374
|
+
if (!style)
|
|
12375
|
+
return { applied: false, unknownTraits: [] };
|
|
12376
|
+
return { applied: true, unknownTraits: writeEntries(target, style) };
|
|
12418
12377
|
}
|
|
12378
|
+
const RULE_KEY = /^(\w+)(?:\[(\w+)=([^\]]+)\])?$/;
|
|
12379
|
+
const RANGE = /^([a-z]*)(\d+)\.\.\1(\d+)$/;
|
|
12380
|
+
function expandValues(raw) {
|
|
12381
|
+
const range = RANGE.exec(raw);
|
|
12382
|
+
if (!range)
|
|
12383
|
+
return [raw];
|
|
12384
|
+
const [, prefix, from, to] = range;
|
|
12385
|
+
const out = [];
|
|
12386
|
+
for (let n = Number(from); n <= Number(to); n++)
|
|
12387
|
+
out.push(`${prefix}${n}`);
|
|
12388
|
+
return out;
|
|
12389
|
+
}
|
|
12390
|
+
const DEFAULT_RULES = Object.entries(SPEC_DEFAULT_ELEMENT_STYLE).map(([key, style]) => {
|
|
12391
|
+
const m = RULE_KEY.exec(key);
|
|
12392
|
+
if (!m)
|
|
12393
|
+
throw new Error(`defaultElementStyle: unreadable key "${key}"`);
|
|
12394
|
+
const [, type, prop, raw] = m;
|
|
12395
|
+
return prop ? { type, prop, values: expandValues(raw), style } : { type, style };
|
|
12396
|
+
});
|
|
12419
12397
|
/**
|
|
12420
|
-
*
|
|
12421
|
-
* the
|
|
12422
|
-
*
|
|
12398
|
+
* The element style a NEW node of `type` is born wearing (the spec's `defaultElementStyle`), or null
|
|
12399
|
+
* when the type has none. `traits` is the node's own trait values (props) — a Heading's default
|
|
12400
|
+
* follows its `level`; a Heading with no level matches no rule.
|
|
12423
12401
|
*/
|
|
12424
|
-
function
|
|
12425
|
-
const
|
|
12426
|
-
|
|
12402
|
+
function defaultElementStyleFor(type, traits = {}) {
|
|
12403
|
+
for (const rule of DEFAULT_RULES) {
|
|
12404
|
+
if (rule.type !== type)
|
|
12405
|
+
continue;
|
|
12406
|
+
if (!rule.prop)
|
|
12407
|
+
return rule.style;
|
|
12408
|
+
if (rule.values.includes(String(traits[rule.prop])))
|
|
12409
|
+
return rule.style;
|
|
12410
|
+
}
|
|
12411
|
+
return null;
|
|
12427
12412
|
}
|
|
12428
|
-
/**
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12413
|
+
/** Per owned trait: does the node still hold the style's value (linked) or the author's (changed)? */
|
|
12414
|
+
function ownedTraitStatus(target, id) {
|
|
12415
|
+
const style = elementStyleById(id);
|
|
12416
|
+
if (!style)
|
|
12417
|
+
return [];
|
|
12418
|
+
return ownedEntries(style).map(({ trait, state, value }) => {
|
|
12419
|
+
const actual = state ? readState(target, state, trait) : readBase(target, trait);
|
|
12420
|
+
return {
|
|
12421
|
+
trait, ...(state ? { state } : {}), expected: value, actual,
|
|
12422
|
+
status: actual === value ? OwnedTraitLink.Linked : OwnedTraitLink.Changed,
|
|
12423
|
+
};
|
|
12439
12424
|
});
|
|
12440
|
-
return missing ? null : value;
|
|
12441
12425
|
}
|
|
12442
|
-
const schemeEntries = (set, resolved, opposite) => Object.entries(set)
|
|
12443
|
-
.map(([name, template]) => [name, substitute(template, resolved, opposite)])
|
|
12444
|
-
.filter((e) => e[1] !== null);
|
|
12445
|
-
const hasPlaceholder = (value) => value.includes('{{');
|
|
12446
12426
|
/**
|
|
12447
|
-
*
|
|
12448
|
-
*
|
|
12449
|
-
*
|
|
12450
|
-
*
|
|
12451
|
-
*
|
|
12452
|
-
*
|
|
12453
|
-
* re-declared verbatim — re-resolving it in the section.
|
|
12454
|
-
* - ⚠️ A scheme that SWAPS two tokens (Brand: accent ⇄ accent-ink) cannot write them as `var()`:
|
|
12455
|
-
* on one element `accent: var(--iox-accent-ink)` + `accent-ink: var(--iox-accent)` is a cycle,
|
|
12456
|
-
* and CSS makes both invalid. The contract writes `{{accent}}` instead — the token's ROOT value,
|
|
12457
|
-
* resolved here at compile time (and again from dark values for the dark twin).
|
|
12427
|
+
* Move a node from one style to another, rewriting ONLY what the old style owned:
|
|
12428
|
+
* - an owned trait still holding the old style's value is released — a base trait goes back to
|
|
12429
|
+
* `baseline[trait]` (the type's unstyled value; deleted when the baseline has none), a state trait
|
|
12430
|
+
* is removed from its state map;
|
|
12431
|
+
* - an owned trait the author changed is KEPT, and the new style does not overwrite it.
|
|
12432
|
+
* Then the new style is written. Traits neither style owns are never touched.
|
|
12458
12433
|
*/
|
|
12459
|
-
function
|
|
12460
|
-
const
|
|
12461
|
-
if (!
|
|
12462
|
-
return
|
|
12463
|
-
const
|
|
12464
|
-
const
|
|
12465
|
-
|
|
12466
|
-
|
|
12467
|
-
|
|
12468
|
-
.
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
|
|
12472
|
-
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
return d !== null && (t.value.includes(REFERENCE) || d.includes(REFERENCE));
|
|
12479
|
-
});
|
|
12480
|
-
return nonDefaultSchemes().map(([id, set]) => {
|
|
12481
|
-
const swapped = Object.fromEntries(Object.entries(set).filter(([, v]) => hasPlaceholder(v)));
|
|
12482
|
-
const lightSwap = new Map(schemeEntries(swapped, light, dark));
|
|
12483
|
-
return rule(schemeSelector(id, scope), [
|
|
12484
|
-
...schemeEntries(swapped, dark, light).filter(([name, value]) => lightSwap.get(name) !== value),
|
|
12485
|
-
...redeclared.filter(t => !(t.name in set)).map((t) => [t.name, darkOf(t)]),
|
|
12486
|
-
], ' ');
|
|
12487
|
-
});
|
|
12488
|
-
}
|
|
12489
|
-
function presentOverrides(rows, overrides, onlyWithDark) {
|
|
12490
|
-
return Object.entries(overrides).filter(([name]) => rows.some(t => t.name === name && (!onlyWithDark || darkOf(t) !== null)));
|
|
12491
|
-
}
|
|
12492
|
-
/** The token CSS as the two halves a renderer places around its node rules. */
|
|
12493
|
-
function compileTokenCssBlocks(tokens, opts = {}) {
|
|
12494
|
-
const all = usableTokens(tokens);
|
|
12495
|
-
const rows = rowsForMode(all, opts.mode);
|
|
12496
|
-
const root = opts.scope ?? ROOT;
|
|
12497
|
-
// A forced mode flattens the rows to ONE mode; a `{{~token}}` still reads the other mode's value.
|
|
12498
|
-
const opposite = resolveTokenValues(all, opts.mode === DARK ? LIGHT : DARK);
|
|
12499
|
-
const present = new Set(rows.map(t => t.name));
|
|
12500
|
-
const unset = opts.isolate
|
|
12501
|
-
? [...specTokenNames()].filter(name => !present.has(name)).map((name) => [name, 'initial'])
|
|
12502
|
-
: [];
|
|
12503
|
-
const base = [
|
|
12504
|
-
rule(root, [...unset, ...rows.map((t) => [t.name, t.value])]),
|
|
12505
|
-
compileSchemeCss(rows, opts.scope, opposite),
|
|
12506
|
-
...ACCESSIBILITY_MEDIA.map(({ query, overrides }) => media(query, [rule(root, presentOverrides(rows, overrides, false), ' ')])),
|
|
12507
|
-
].filter(Boolean).join('\n');
|
|
12508
|
-
const darkRows = rows.map((t) => [t.name, darkOf(t)])
|
|
12509
|
-
.filter((e) => e[1] !== null);
|
|
12510
|
-
const dark = darkRows.length ? [
|
|
12511
|
-
media(MEDIA_DARK, [rule(root, darkRows, ' '), ...darkSchemeRules(rows, opts.scope)]),
|
|
12512
|
-
// Glass carries dark glass values; without this the dark block (LAST) would out-rank the
|
|
12513
|
-
// reduced-transparency swap and keep dark surfaces translucent.
|
|
12514
|
-
...ACCESSIBILITY_MEDIA.map(({ query, overrides }) => media(`${MEDIA_DARK} and ${query}`, [rule(root, presentOverrides(rows, overrides, true), ' ')])),
|
|
12515
|
-
].filter(Boolean).join('\n') : '';
|
|
12516
|
-
return { base, dark };
|
|
12517
|
-
}
|
|
12518
|
-
/** One stylesheet string: base → schemes → reduced motion → reduced transparency → dark LAST. */
|
|
12519
|
-
function compileTokenCss(tokens, opts = {}) {
|
|
12520
|
-
const { base, dark } = compileTokenCssBlocks(tokens, opts);
|
|
12521
|
-
return [base, dark].filter(Boolean).join('\n');
|
|
12522
|
-
}
|
|
12523
|
-
|
|
12524
|
-
/** A pack's own sanity: every token row names itself and carries a value. Returns errors. */
|
|
12525
|
-
function validateFlavorPack(pack) {
|
|
12526
|
-
const errors = [];
|
|
12527
|
-
for (const t of pack.tokens ?? []) {
|
|
12528
|
-
if (!t.name)
|
|
12529
|
-
errors.push(`${pack.id}: token with empty name`);
|
|
12530
|
-
if (!t.value)
|
|
12531
|
-
errors.push(`${pack.id}: token "${t.name}" has no value`);
|
|
12434
|
+
function switchElementStyle(target, fromId, toId, baseline = {}) {
|
|
12435
|
+
const to = elementStyleById(toId);
|
|
12436
|
+
if (!to)
|
|
12437
|
+
return { applied: false, kept: [] };
|
|
12438
|
+
const kept = [];
|
|
12439
|
+
const from = elementStyleById(fromId);
|
|
12440
|
+
if (from) {
|
|
12441
|
+
for (const status of ownedTraitStatus(target, from.id)) {
|
|
12442
|
+
const ref = status.state ? { trait: status.trait, state: status.state } : { trait: status.trait };
|
|
12443
|
+
if (status.status === OwnedTraitLink.Changed) {
|
|
12444
|
+
if (status.actual !== undefined)
|
|
12445
|
+
kept.push(ref);
|
|
12446
|
+
continue;
|
|
12447
|
+
}
|
|
12448
|
+
if (ref.state)
|
|
12449
|
+
deleteState(target, ref.state, ref.trait);
|
|
12450
|
+
else
|
|
12451
|
+
writeBase(target, ref.trait, baseline[ref.trait]);
|
|
12452
|
+
}
|
|
12532
12453
|
}
|
|
12533
|
-
|
|
12454
|
+
writeEntries(target, to, kept);
|
|
12455
|
+
return { applied: true, kept };
|
|
12534
12456
|
}
|
|
12535
12457
|
/**
|
|
12536
|
-
*
|
|
12537
|
-
*
|
|
12538
|
-
* `
|
|
12458
|
+
* The element-style MARKER (design-system §3b-bis, spec `elementStyleMarker`). A node that wears an
|
|
12459
|
+
* element style renders `iox-es iox-es-<id>` in BOTH renderers, through the one node-class helper
|
|
12460
|
+
* `nodeDesignClasses` (node-classes.ts); every piece of component CSS that carries the system look is
|
|
12461
|
+
* scoped to it, so a node saved before DS2 (no `elementStyle`) keeps its exact pre-DS2 component CSS
|
|
12462
|
+
* no matter which tokens the org holds.
|
|
12539
12463
|
*/
|
|
12540
|
-
const
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12548
|
-
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
|
|
12464
|
+
const ELEMENT_STYLE_MARKER_CLASS = 'iox-es';
|
|
12465
|
+
const MARKER_PREFIX$1 = `${ELEMENT_STYLE_MARKER_CLASS}-`;
|
|
12466
|
+
/** `iox-es-<id>` for a known style, else null — an unknown id never reaches a class attribute. */
|
|
12467
|
+
function elementStyleClass(id) {
|
|
12468
|
+
return elementStyleById(id) ? `${MARKER_PREFIX$1}${id}` : null;
|
|
12469
|
+
}
|
|
12470
|
+
/**
|
|
12471
|
+
* The spec's `headingLevelRule`: changing a Heading's level moves it to the new level's DEFAULT
|
|
12472
|
+
* style only when it still wears its old level's default (author changes kept, via
|
|
12473
|
+
* `switchElementStyle`); a Heading wearing any other style — or none — is left alone. Returns null
|
|
12474
|
+
* when nothing switched.
|
|
12475
|
+
*/
|
|
12476
|
+
function applyHeadingLevelRule(target, oldLevel, newLevel, baseline = {}) {
|
|
12477
|
+
if (target.type !== 'Heading' || oldLevel === newLevel)
|
|
12478
|
+
return null;
|
|
12479
|
+
const from = defaultElementStyleFor('Heading', { level: oldLevel });
|
|
12480
|
+
const to = defaultElementStyleFor('Heading', { level: newLevel });
|
|
12481
|
+
if (!from || !to || target.elementStyle !== from || from === to)
|
|
12482
|
+
return null;
|
|
12483
|
+
return switchElementStyle(target, from, to, baseline);
|
|
12484
|
+
}
|
|
12554
12485
|
|
|
12555
12486
|
/**
|
|
12556
|
-
*
|
|
12557
|
-
*
|
|
12558
|
-
*
|
|
12559
|
-
* reads `elementStyle`: it records which look a node wears, for the panel row, Reset, adopt and AI.
|
|
12487
|
+
* The design-system classes a node renders, in BOTH renderers (builder canvas, engine component
|
|
12488
|
+
* path, engine string path) — ONE helper, so the three can never disagree about which class a node
|
|
12489
|
+
* carries:
|
|
12560
12490
|
*
|
|
12561
|
-
*
|
|
12562
|
-
*
|
|
12563
|
-
*
|
|
12491
|
+
* - the element-style MARKER `iox-es iox-es-<id>` (design-system §3b-bis) — component CSS carrying
|
|
12492
|
+
* the system look is scoped to it, so a node saved before DS2 keeps its pre-DS2 look;
|
|
12493
|
+
* - the section colour scheme `iox-scheme-<id>` (§3c) for a non-default `colorScheme` — the class
|
|
12494
|
+
* `compileSchemeCss` re-declares tokens on, so everything inside re-resolves;
|
|
12495
|
+
* - the composite ROLE `iox-role-<role>` (`card.media` → `iox-role-card-media`; composite-components
|
|
12496
|
+
* plan §3, Card v2) — what the shared CSS keys a part's structural rules on (the badge's corner, the
|
|
12497
|
+
* card's stretched link), so a role is never a renderer's private knowledge.
|
|
12498
|
+
*
|
|
12499
|
+
* Renderers read `elementStyle`, `colorScheme` and `role` for exactly this and nothing else.
|
|
12564
12500
|
*/
|
|
12565
|
-
|
|
12566
|
-
|
|
12567
|
-
|
|
12568
|
-
|
|
12569
|
-
|
|
12570
|
-
|
|
12571
|
-
|
|
12572
|
-
})(
|
|
12573
|
-
|
|
12574
|
-
const
|
|
12575
|
-
/**
|
|
12576
|
-
const
|
|
12577
|
-
/**
|
|
12578
|
-
const
|
|
12579
|
-
const
|
|
12580
|
-
|
|
12581
|
-
|
|
12501
|
+
/** The section colour schemes — the contract's `schemes` keys. */
|
|
12502
|
+
var ColorScheme;
|
|
12503
|
+
(function (ColorScheme) {
|
|
12504
|
+
ColorScheme["Default"] = "default";
|
|
12505
|
+
ColorScheme["Subtle"] = "subtle";
|
|
12506
|
+
ColorScheme["Inverse"] = "inverse";
|
|
12507
|
+
ColorScheme["Accent"] = "accent";
|
|
12508
|
+
})(ColorScheme || (ColorScheme = {}));
|
|
12509
|
+
/** The content trait (stored in `props`, not a style prop) that picks a node's scheme. */
|
|
12510
|
+
const COLOR_SCHEME_TRAIT = 'colorScheme';
|
|
12511
|
+
/** The node types that offer a scheme (spec §3c: Section/Container; LinkedContainer is a Container that links). */
|
|
12512
|
+
const COLOR_SCHEME_TYPES = ['Section', 'Container', 'LinkedContainer'];
|
|
12513
|
+
/** Every scheme in contract order, with the contract's label (Default · Subtle · Inverse · Brand). */
|
|
12514
|
+
const COLOR_SCHEMES = Object.keys(SPEC_SCHEMES).map(id => ({ id, label: SPEC_SCHEMES[id].label }));
|
|
12515
|
+
const SCHEME_IDS$1 = new Set(Object.keys(SPEC_SCHEMES));
|
|
12516
|
+
const SCHEME_PREFIX = 'iox-scheme-';
|
|
12517
|
+
const ROLE_PREFIX = 'iox-role-';
|
|
12518
|
+
/** A role is dot-separated lowercase words (`card`, `card.title`) — anything else never reaches a class. */
|
|
12519
|
+
const ROLE_SHAPE = /^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)*$/;
|
|
12520
|
+
const MARKER_PREFIX = `${ELEMENT_STYLE_MARKER_CLASS}-`;
|
|
12521
|
+
/** `iox-scheme-<id>` for a known NON-default scheme, else null — an unknown id never reaches a class attribute. */
|
|
12522
|
+
function colorSchemeClass(id) {
|
|
12523
|
+
return typeof id === 'string' && id !== ColorScheme.Default && SCHEME_IDS$1.has(id) ? `${SCHEME_PREFIX}${id}` : null;
|
|
12582
12524
|
}
|
|
12583
|
-
/**
|
|
12584
|
-
function
|
|
12585
|
-
return
|
|
12525
|
+
/** `iox-role-<role>` for a well-formed composite role, else null. */
|
|
12526
|
+
function roleClass(role) {
|
|
12527
|
+
return typeof role === 'string' && ROLE_SHAPE.test(role) ? `${ROLE_PREFIX}${role.replace(/\./g, '-')}` : null;
|
|
12586
12528
|
}
|
|
12587
|
-
|
|
12588
|
-
|
|
12589
|
-
|
|
12590
|
-
|
|
12591
|
-
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
for (const group of
|
|
12597
|
-
const hit = group.traits
|
|
12529
|
+
/** The element style whose wearer is the phone's bottom navigation bar (CC1, R1). */
|
|
12530
|
+
const BOTTOM_BAR_STYLE = 'bottom-bar';
|
|
12531
|
+
/** The page reserves the bar's height wherever this class is on the page… */
|
|
12532
|
+
const BAR_RESERVE_CLASS = 'iox-bar-reserve';
|
|
12533
|
+
/** …the responsive Breakpoint ids that can hold an override, widest first (a spec pins it to BREAKPOINTS). */
|
|
12534
|
+
const BAR_RESERVE_BREAKPOINTS = ['laptop', 'tablet', 'mobile', 'small'];
|
|
12535
|
+
function baseDisplayOf(node) {
|
|
12536
|
+
if (node.styleProps && 'display' in node.styleProps)
|
|
12537
|
+
return node.styleProps['display'];
|
|
12538
|
+
for (const group of node.styleTraits ?? []) {
|
|
12539
|
+
const hit = group.traits?.find(t => t?.name === 'display');
|
|
12598
12540
|
if (hit)
|
|
12599
|
-
return hit;
|
|
12541
|
+
return hit.default;
|
|
12600
12542
|
}
|
|
12601
12543
|
return undefined;
|
|
12602
12544
|
}
|
|
12603
|
-
|
|
12604
|
-
|
|
12545
|
+
/**
|
|
12546
|
+
* The class that makes the page reserve a bottom bar's height (iox-design.css: `padding-bottom` and
|
|
12547
|
+
* `scroll-padding-bottom`, WCAG 2.4.11), only at the widths where the bar SHOWS: `iox-bar-reserve` when
|
|
12548
|
+
* it shows at every width, `iox-bar-reserve-<bp>` when it is hidden at base and shown from that
|
|
12549
|
+
* breakpoint down (the phone shape's own rule), null when it never shows or is not a bar.
|
|
12550
|
+
*/
|
|
12551
|
+
function barReserveClass(node) {
|
|
12552
|
+
if (!node || node.elementStyle !== BOTTOM_BAR_STYLE)
|
|
12553
|
+
return null;
|
|
12554
|
+
if (baseDisplayOf(node) !== 'none')
|
|
12555
|
+
return BAR_RESERVE_CLASS;
|
|
12556
|
+
for (const bp of BAR_RESERVE_BREAKPOINTS) {
|
|
12557
|
+
const display = node.responsive?.[bp]?.styleProps?.['display'];
|
|
12558
|
+
if (display !== undefined && display !== 'none')
|
|
12559
|
+
return `${BAR_RESERVE_CLASS}-${bp}`;
|
|
12560
|
+
}
|
|
12561
|
+
return null;
|
|
12605
12562
|
}
|
|
12606
|
-
/**
|
|
12607
|
-
function
|
|
12608
|
-
if (
|
|
12609
|
-
|
|
12563
|
+
/** A node's `colorScheme`, from `props` (serialized) or its trait (builder). */
|
|
12564
|
+
function colorSchemeOf(node) {
|
|
12565
|
+
if (!node)
|
|
12566
|
+
return null;
|
|
12567
|
+
const fromProps = node.props?.[COLOR_SCHEME_TRAIT];
|
|
12568
|
+
if (fromProps !== undefined)
|
|
12569
|
+
return typeof fromProps === 'string' ? fromProps : null;
|
|
12570
|
+
const trait = node.traits?.find(t => t?.name === COLOR_SCHEME_TRAIT)?.default;
|
|
12571
|
+
return typeof trait === 'string' ? trait : null;
|
|
12572
|
+
}
|
|
12573
|
+
/**
|
|
12574
|
+
* The ink a section colour scheme gives everything inside it (vectoriox/iox-ui#15). A scheme re-declares
|
|
12575
|
+
* tokens only, so without this a Container wearing one kept the colour it INHERITED from the section around
|
|
12576
|
+
* it: a Featured (Brand) card's body text stayed the page's dark ink on the Brand fill, 2.54:1. Two halves,
|
|
12577
|
+
* one rule: `compileSchemeCss` gives every `iox-scheme-*` element `color: var(--iox-text)` (the node rule,
|
|
12578
|
+
* emitted after it at the same specificity, still wins), and {@link withSchemeInk} reads a scheme'd node's
|
|
12579
|
+
* own `inherit` — what the card / box / panel element styles write for "no colour of my own" — as this ink.
|
|
12580
|
+
* The value is the contract's `schemeInk`.
|
|
12581
|
+
*/
|
|
12582
|
+
const SCHEME_INK = SPEC_SCHEME_INK;
|
|
12583
|
+
/** The values that mean "no colour of my own" — `color` is inherited, so these equal no declaration. */
|
|
12584
|
+
const INHERITED_INK = new Set(['inherit', 'unset']);
|
|
12585
|
+
/**
|
|
12586
|
+
* A node's style map as its renderer compiles it under a section colour scheme: a NON-default scheme turns
|
|
12587
|
+
* an inherited `color` into {@link SCHEME_INK}; anything else — no scheme, an author's own colour, a token —
|
|
12588
|
+
* is returned untouched (the same object). Every render path calls it on every rule it compiles for the
|
|
12589
|
+
* node (base, states, breakpoint layers): the builder's StyleRegistryService and both engine paths.
|
|
12590
|
+
*/
|
|
12591
|
+
function withSchemeInk(styles, scheme) {
|
|
12592
|
+
if (!styles || !colorSchemeClass(scheme))
|
|
12593
|
+
return styles;
|
|
12594
|
+
const color = styles['color'];
|
|
12595
|
+
if (typeof color !== 'string' || !INHERITED_INK.has(color.trim().toLowerCase()))
|
|
12596
|
+
return styles;
|
|
12597
|
+
return { ...styles, color: SCHEME_INK };
|
|
12598
|
+
}
|
|
12599
|
+
/**
|
|
12600
|
+
* Write a node's section colour scheme — THE one writer, so every control that offers Section colours (the
|
|
12601
|
+
* Style panel's Element style block, Card ▸ Card) edits the same setting: the `colorScheme` content trait on
|
|
12602
|
+
* a builder node, `props.colorScheme` on a saved one. False when nothing changed: an unknown id, the value it
|
|
12603
|
+
* already holds, or a builder node with no such trait (a type that offers no scheme).
|
|
12604
|
+
*/
|
|
12605
|
+
function setColorScheme(node, id) {
|
|
12606
|
+
if (!node || !SCHEME_IDS$1.has(id) || (colorSchemeOf(node) ?? ColorScheme.Default) === id)
|
|
12607
|
+
return false;
|
|
12608
|
+
if (Array.isArray(node.traits)) {
|
|
12609
|
+
const trait = node.traits.find(t => t?.name === COLOR_SCHEME_TRAIT);
|
|
12610
12610
|
if (!trait)
|
|
12611
12611
|
return false;
|
|
12612
|
-
trait.default =
|
|
12612
|
+
trait.default = id;
|
|
12613
12613
|
return true;
|
|
12614
12614
|
}
|
|
12615
|
-
|
|
12616
|
-
if (value === undefined)
|
|
12617
|
-
delete target.styleProps[name];
|
|
12618
|
-
else
|
|
12619
|
-
target.styleProps[name] = value;
|
|
12615
|
+
node.props = { ...(node.props ?? {}), [COLOR_SCHEME_TRAIT]: id };
|
|
12620
12616
|
return true;
|
|
12621
12617
|
}
|
|
12622
|
-
|
|
12623
|
-
|
|
12618
|
+
/** True when the node wears a known element style — the marker is on it. */
|
|
12619
|
+
function hasElementStyleMarker(node) {
|
|
12620
|
+
return elementStyleClass(node?.elementStyle) !== null;
|
|
12624
12621
|
}
|
|
12625
|
-
|
|
12626
|
-
|
|
12627
|
-
|
|
12622
|
+
/** The classes a node renders: `'iox-es iox-es-card iox-scheme-inverse'` (+ a bottom bar's reserve class), or `''` for none. */
|
|
12623
|
+
function nodeDesignClasses(node) {
|
|
12624
|
+
const marker = elementStyleClass(node?.elementStyle);
|
|
12625
|
+
return [marker ? `${ELEMENT_STYLE_MARKER_CLASS} ${marker}` : '', colorSchemeClass(colorSchemeOf(node)) ?? '', roleClass(node?.role) ?? '', barReserveClass(node) ?? '']
|
|
12626
|
+
.filter(Boolean).join(' ');
|
|
12628
12627
|
}
|
|
12629
|
-
|
|
12630
|
-
|
|
12631
|
-
|
|
12628
|
+
const isDesignClass = (c) => c === ELEMENT_STYLE_MARKER_CLASS || c.startsWith(MARKER_PREFIX) || c.startsWith(SCHEME_PREFIX) || c.startsWith(ROLE_PREFIX) || c.startsWith(BAR_RESERVE_CLASS);
|
|
12629
|
+
/** Make an element's design classes match the node — the live switch on the canvas and the
|
|
12630
|
+
* component path's one-time stamp. Removes stale ones; touches no other class. */
|
|
12631
|
+
function syncNodeDesignClasses(el, node) {
|
|
12632
|
+
if (!el?.classList)
|
|
12632
12633
|
return;
|
|
12633
|
-
const
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12634
|
+
for (const c of Array.from(el.classList).filter(isDesignClass))
|
|
12635
|
+
el.classList.remove(c);
|
|
12636
|
+
const classes = nodeDesignClasses(node);
|
|
12637
|
+
if (classes)
|
|
12638
|
+
el.classList.add(...classes.split(' '));
|
|
12639
|
+
}
|
|
12640
|
+
|
|
12641
|
+
/**
|
|
12642
|
+
* Which `--iox-<name>` a piece of COMPONENT CSS may reference (design-system §3b-bis: "component CSS
|
|
12643
|
+
* may reference ONLY tokens defined in this spec"). DS2 shipped seven names nobody defines
|
|
12644
|
+
* (`card-media-gap`, `gallery-overlay`, `dialog-close-bg`…): a token the contract does not define can
|
|
12645
|
+
* never be set by a flavor, so it is a literal wearing a costume. One guard, run over BOTH
|
|
12646
|
+
* renderers' component CSS (iox-ui's spec; the engine's `verify:token-names`).
|
|
12647
|
+
*/
|
|
12648
|
+
/** The 161 names of the contract's two tiers, plus its legacy aliases. */
|
|
12649
|
+
function specTokenNames() {
|
|
12650
|
+
return new Set([
|
|
12651
|
+
...SPEC_TIERS.semantic.map(t => t.name),
|
|
12652
|
+
...SPEC_TIERS.component.map(t => t.name),
|
|
12653
|
+
...Object.keys(SPEC_LEGACY_ALIASES),
|
|
12654
|
+
]);
|
|
12655
|
+
}
|
|
12656
|
+
const REFERENCE$1 = /var\(\s*--iox-([a-z0-9-]+)/gi;
|
|
12657
|
+
/** Every distinct token a stylesheet READS (`var(--iox-x…)`), in first-seen order. */
|
|
12658
|
+
function tokenReferences(css) {
|
|
12659
|
+
return [...new Set(Array.from(css.matchAll(REFERENCE$1), m => m[1]))];
|
|
12660
|
+
}
|
|
12661
|
+
/** The referenced names that are neither spec tokens nor in `alsoAllowed`. */
|
|
12662
|
+
function unknownTokenReferences(css, alsoAllowed = []) {
|
|
12663
|
+
const spec = specTokenNames();
|
|
12664
|
+
const extra = new Set(alsoAllowed);
|
|
12665
|
+
return tokenReferences(css).filter(name => !spec.has(name) && !extra.has(name));
|
|
12666
|
+
}
|
|
12667
|
+
const LEGACY_SCOPE = /:not\(\s*\.iox-es\s*\)/;
|
|
12668
|
+
/** Comments out: block comments, and SCSS `//` line comments (never the `//` of a `url(https://…)`). */
|
|
12669
|
+
const stripComments = (css) => String(css ?? '')
|
|
12670
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
12671
|
+
.replace(/(^|[^:\\])\/\/[^\n]*/g, '$1');
|
|
12672
|
+
/** A nested SCSS selector against its parent's: `&` is the parent; no `&` means a descendant. */
|
|
12673
|
+
function resolveNested(parent, selector) {
|
|
12674
|
+
if (!parent)
|
|
12675
|
+
return selector;
|
|
12676
|
+
return selector.split(',').map(part => {
|
|
12677
|
+
const own = part.trim();
|
|
12678
|
+
return own.includes('&') ? own.replace(/&/g, parent) : `${parent} ${own}`;
|
|
12679
|
+
}).join(', ');
|
|
12638
12680
|
}
|
|
12639
|
-
/**
|
|
12640
|
-
|
|
12681
|
+
/**
|
|
12682
|
+
* Tokens read by a LEGACY rule — any rule whose selector is scoped `:not(.iox-es)` (the pre-DS2 look
|
|
12683
|
+
* of a node that wears no element style, design-system §3b-bis). Such a rule must read NO token at
|
|
12684
|
+
* all: a token it reads repaints a pre-DS2 page the moment the org's rows are seeded or a flavor is
|
|
12685
|
+
* applied (D5). Returns `selector → names` for each offending rule; comments are ignored. SCSS
|
|
12686
|
+
* nesting is resolved (DS4.1): `.x:where(:not(.iox-es)) { &:hover { … } }` is the legacy rule
|
|
12687
|
+
* `.x:where(:not(.iox-es)):hover`, and an at-rule (`@media`) between them does not break the chain.
|
|
12688
|
+
*/
|
|
12689
|
+
function legacyRuleTokenReferences(css) {
|
|
12690
|
+
const text = stripComments(css);
|
|
12641
12691
|
const out = [];
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12692
|
+
const stack = [];
|
|
12693
|
+
const report = (frame) => {
|
|
12694
|
+
if (!LEGACY_SCOPE.test(frame.selector))
|
|
12695
|
+
return;
|
|
12696
|
+
const tokens = tokenReferences(frame.body);
|
|
12697
|
+
if (tokens.length)
|
|
12698
|
+
out.push({ selector: frame.selector, tokens });
|
|
12699
|
+
};
|
|
12700
|
+
let buffer = '';
|
|
12701
|
+
for (const ch of text) {
|
|
12702
|
+
if (ch === '{') {
|
|
12703
|
+
const head = buffer.trim().replace(/\s+/g, ' ');
|
|
12704
|
+
buffer = '';
|
|
12705
|
+
// Declarations before a nested block belong to the parent (`color: x; &:hover {`).
|
|
12706
|
+
const cut = head.lastIndexOf(';');
|
|
12707
|
+
const prelude = cut >= 0 ? head.slice(cut + 1).trim() : head;
|
|
12708
|
+
const parent = stack[stack.length - 1];
|
|
12709
|
+
if (parent && cut >= 0)
|
|
12710
|
+
parent.body += head.slice(0, cut + 1);
|
|
12711
|
+
const inherited = parent?.selector ?? '';
|
|
12712
|
+
const selector = prelude.startsWith('@') ? inherited : resolveNested(inherited, prelude);
|
|
12713
|
+
stack.push({ selector, body: '' });
|
|
12714
|
+
}
|
|
12715
|
+
else if (ch === '}') {
|
|
12716
|
+
const frame = stack.pop();
|
|
12717
|
+
if (frame) {
|
|
12718
|
+
frame.body += buffer;
|
|
12719
|
+
report(frame);
|
|
12720
|
+
}
|
|
12721
|
+
buffer = '';
|
|
12722
|
+
}
|
|
12723
|
+
else if (ch === ';' && stack.length) {
|
|
12724
|
+
stack[stack.length - 1].body += buffer + ch;
|
|
12725
|
+
buffer = '';
|
|
12726
|
+
}
|
|
12727
|
+
else {
|
|
12728
|
+
buffer += ch;
|
|
12729
|
+
}
|
|
12647
12730
|
}
|
|
12648
12731
|
return out;
|
|
12649
12732
|
}
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12733
|
+
|
|
12734
|
+
/** What `prefers-reduced-motion: reduce` collapses — the contract's complete list (`a11y.reducedMotion`). */
|
|
12735
|
+
const REDUCED_MOTION_OVERRIDES = SPEC_A11Y.reducedMotion;
|
|
12736
|
+
/** What `prefers-reduced-transparency: reduce` makes solid — the contract's `a11y.reducedTransparency`. */
|
|
12737
|
+
const REDUCED_TRANSPARENCY_OVERRIDES = SPEC_A11Y.reducedTransparency;
|
|
12738
|
+
const ROOT = ':root';
|
|
12739
|
+
const DEFAULT_SCHEME$1 = 'default';
|
|
12740
|
+
const REFERENCE = 'var(';
|
|
12741
|
+
const MEDIA_DARK = '(prefers-color-scheme: dark)';
|
|
12742
|
+
const ACCESSIBILITY_MEDIA = [
|
|
12743
|
+
{ query: '(prefers-reduced-motion: reduce)', overrides: REDUCED_MOTION_OVERRIDES },
|
|
12744
|
+
{ query: '(prefers-reduced-transparency: reduce)', overrides: REDUCED_TRANSPARENCY_OVERRIDES },
|
|
12745
|
+
];
|
|
12746
|
+
const usable = (t) => !!t && typeof t.name === 'string' && t.name !== '' &&
|
|
12747
|
+
typeof t.value === 'string' && t.value !== '';
|
|
12748
|
+
const darkOf = (t) => {
|
|
12749
|
+
const dark = t.values?.dark;
|
|
12750
|
+
return typeof dark === 'string' && dark !== '' ? dark : null;
|
|
12751
|
+
};
|
|
12752
|
+
const usableTokens = (tokens) => (tokens ?? []).filter(usable);
|
|
12753
|
+
const declarations = (entries, indent) => entries.map(([name, value]) => `${indent}--iox-${name}: ${value};`).join('\n');
|
|
12754
|
+
const rule = (selector, entries, indent = '') => entries.length ? `${indent}${selector} {\n${declarations(entries, indent + ' ')}\n${indent}}` : '';
|
|
12755
|
+
const media = (query, rules) => {
|
|
12756
|
+
const body = rules.filter(Boolean);
|
|
12757
|
+
return body.length ? `@media ${query} {\n${body.join('\n')}\n}` : '';
|
|
12758
|
+
};
|
|
12759
|
+
const schemeSelector = (id, scope) => scope ? `${scope} .iox-scheme-${id}` : `.iox-scheme-${id}`;
|
|
12760
|
+
const nonDefaultSchemes = () => Object.entries(SPEC_SCHEMES)
|
|
12761
|
+
.filter(([id]) => id !== DEFAULT_SCHEME$1)
|
|
12762
|
+
.map(([id, scheme]) => [id, scheme.set]);
|
|
12763
|
+
/** `{ 'iox-brand': '#2f6f62', … }` — the builder registry's input shape for base values. */
|
|
12764
|
+
function tokensToVarMap(tokens) {
|
|
12765
|
+
const map = {};
|
|
12766
|
+
for (const t of usableTokens(tokens))
|
|
12767
|
+
map[`iox-${t.name}`] = t.value;
|
|
12768
|
+
return map;
|
|
12664
12769
|
}
|
|
12665
|
-
|
|
12666
|
-
function
|
|
12667
|
-
const
|
|
12668
|
-
for (const
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
writeState(target, entry.state, entry.trait, entry.value);
|
|
12673
|
-
else if (!writeBase(target, entry.trait, entry.value))
|
|
12674
|
-
unknown.push(entry.trait);
|
|
12770
|
+
/** Only the tokens that carry a dark override, as `{ 'iox-name': darkValue }`. */
|
|
12771
|
+
function tokensToDarkVarMap(tokens) {
|
|
12772
|
+
const map = {};
|
|
12773
|
+
for (const t of usableTokens(tokens)) {
|
|
12774
|
+
const dark = darkOf(t);
|
|
12775
|
+
if (dark !== null)
|
|
12776
|
+
map[`iox-${t.name}`] = dark;
|
|
12675
12777
|
}
|
|
12676
|
-
|
|
12677
|
-
return unknown;
|
|
12778
|
+
return map;
|
|
12678
12779
|
}
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
|
|
12780
|
+
const TOKEN_REF$1 = /var\(\s*--iox-([\w-]+)\s*(?:,([^()]*))?\)/g;
|
|
12781
|
+
const PLACEHOLDER = /\{\{\s*(~?)([\w-]+)\s*\}\}/g;
|
|
12782
|
+
const LIGHT = 'light';
|
|
12783
|
+
const DARK = 'dark';
|
|
12784
|
+
const modeValue = (t, mode) => (mode === DARK ? darkOf(t) ?? t.value : t.value);
|
|
12785
|
+
/** The rows as ONE mode: each row's value in that mode, no dark override left. `auto` (or none) →
|
|
12786
|
+
* the rows unchanged. */
|
|
12787
|
+
function rowsForMode(rows, mode) {
|
|
12788
|
+
if (mode !== LIGHT && mode !== DARK)
|
|
12789
|
+
return [...rows];
|
|
12790
|
+
return rows.map(t => {
|
|
12791
|
+
const { values: _dropped, ...rest } = t;
|
|
12792
|
+
return { ...rest, value: modeValue(t, mode) };
|
|
12793
|
+
});
|
|
12685
12794
|
}
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
function
|
|
12689
|
-
const
|
|
12690
|
-
|
|
12691
|
-
|
|
12692
|
-
|
|
12693
|
-
|
|
12694
|
-
|
|
12695
|
-
|
|
12795
|
+
/** Every token's ROOT value in one mode, with `var(--iox-…)` references resolved against the same
|
|
12796
|
+
* set (recursively; a reference cycle or an unknown token is left as written). */
|
|
12797
|
+
function resolveTokenValues(tokens, mode = LIGHT) {
|
|
12798
|
+
const raw = new Map(usableTokens(tokens).map(t => [t.name, modeValue(t, mode)]));
|
|
12799
|
+
const out = {};
|
|
12800
|
+
const resolve = (name, trail) => {
|
|
12801
|
+
if (name in out)
|
|
12802
|
+
return out[name];
|
|
12803
|
+
const value = raw.get(name);
|
|
12804
|
+
if (value === undefined || trail.has(name))
|
|
12805
|
+
return null;
|
|
12806
|
+
const next = new Set(trail).add(name);
|
|
12807
|
+
return value.replace(TOKEN_REF$1, (ref, inner, fallback) => resolve(inner, next) ?? (fallback !== undefined ? fallback.trim() : ref));
|
|
12808
|
+
};
|
|
12809
|
+
for (const name of raw.keys()) {
|
|
12810
|
+
const value = resolve(name, new Set());
|
|
12811
|
+
if (value !== null)
|
|
12812
|
+
out[name] = value;
|
|
12813
|
+
}
|
|
12696
12814
|
return out;
|
|
12697
12815
|
}
|
|
12698
|
-
const DEFAULT_RULES = Object.entries(SPEC_DEFAULT_ELEMENT_STYLE).map(([key, style]) => {
|
|
12699
|
-
const m = RULE_KEY.exec(key);
|
|
12700
|
-
if (!m)
|
|
12701
|
-
throw new Error(`defaultElementStyle: unreadable key "${key}"`);
|
|
12702
|
-
const [, type, prop, raw] = m;
|
|
12703
|
-
return prop ? { type, prop, values: expandValues(raw), style } : { type, style };
|
|
12704
|
-
});
|
|
12705
12816
|
/**
|
|
12706
|
-
*
|
|
12707
|
-
*
|
|
12708
|
-
*
|
|
12817
|
+
* Every token's value INSIDE a section wearing `schemeId`, in one mode — what CSS computes there: the
|
|
12818
|
+
* scheme's overrides (`{{token}}` / `{{~token}}` placeholders substituted from the root), every other
|
|
12819
|
+
* row as declared, and `var()` references resolved within the section (the §3c re-declaration rule
|
|
12820
|
+
* makes that the section's own resolution). `default` (or an unknown id) is the root. A CHAIN
|
|
12821
|
+
* (`['inverse', 'accent']`, outermost first) is an element wearing the last scheme inside elements wearing
|
|
12822
|
+
* the ones before it: a token the inner scheme does not set is the outer one's (custom properties inherit).
|
|
12709
12823
|
*/
|
|
12710
|
-
function
|
|
12711
|
-
|
|
12712
|
-
|
|
12824
|
+
function resolveSchemeTokenValues(tokens, mode, schemeId) {
|
|
12825
|
+
const rows = usableTokens(tokens);
|
|
12826
|
+
const sets = (typeof schemeId === 'string' ? [schemeId] : schemeId)
|
|
12827
|
+
.map(id => (id === DEFAULT_SCHEME$1 ? undefined : SPEC_SCHEMES[id]?.set));
|
|
12828
|
+
if (!sets.some(Boolean))
|
|
12829
|
+
return resolveTokenValues(rows, mode);
|
|
12830
|
+
const root = resolveTokenValues(rows, mode);
|
|
12831
|
+
const other = resolveTokenValues(rows, mode === DARK ? LIGHT : DARK);
|
|
12832
|
+
// Nested (`[outer, inner]` — a Featured card in an Inverse section): each scheme block re-declares the
|
|
12833
|
+
// rows that reference a token, so at every level those are restored before the block's own set.
|
|
12834
|
+
const overrides = new Map();
|
|
12835
|
+
for (const set of sets) {
|
|
12836
|
+
if (!set)
|
|
12713
12837
|
continue;
|
|
12714
|
-
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12838
|
+
for (const t of rows)
|
|
12839
|
+
if (modeValue(t, mode).includes(REFERENCE))
|
|
12840
|
+
overrides.delete(t.name);
|
|
12841
|
+
for (const [name, value] of schemeEntries(set, root, other))
|
|
12842
|
+
overrides.set(name, value);
|
|
12718
12843
|
}
|
|
12719
|
-
return
|
|
12720
|
-
}
|
|
12721
|
-
/** Per owned trait: does the node still hold the style's value (linked) or the author's (changed)? */
|
|
12722
|
-
function ownedTraitStatus(target, id) {
|
|
12723
|
-
const style = elementStyleById(id);
|
|
12724
|
-
if (!style)
|
|
12725
|
-
return [];
|
|
12726
|
-
return ownedEntries(style).map(({ trait, state, value }) => {
|
|
12727
|
-
const actual = state ? readState(target, state, trait) : readBase(target, trait);
|
|
12728
|
-
return {
|
|
12729
|
-
trait, ...(state ? { state } : {}), expected: value, actual,
|
|
12730
|
-
status: actual === value ? OwnedTraitLink.Linked : OwnedTraitLink.Changed,
|
|
12731
|
-
};
|
|
12732
|
-
});
|
|
12844
|
+
return resolveTokenValues(rows.map(t => ({ name: t.name, value: overrides.get(t.name) ?? modeValue(t, mode) })), LIGHT);
|
|
12733
12845
|
}
|
|
12734
12846
|
/**
|
|
12735
|
-
*
|
|
12736
|
-
*
|
|
12737
|
-
*
|
|
12738
|
-
* is removed from its state map;
|
|
12739
|
-
* - an owned trait the author changed is KEPT, and the new style does not overwrite it.
|
|
12740
|
-
* Then the new style is written. Traits neither style owns are never touched.
|
|
12847
|
+
* `value` with every `var(--iox-…)` replaced by that token's resolved root value in `mode` — what
|
|
12848
|
+
* the Style panel's Detach writes, so the node keeps exactly what it showed as a literal. An unknown
|
|
12849
|
+
* token falls back to its declared fallback, else stays as written.
|
|
12741
12850
|
*/
|
|
12742
|
-
function
|
|
12743
|
-
const
|
|
12744
|
-
|
|
12745
|
-
|
|
12746
|
-
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
|
|
12754
|
-
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
writeBase(target, ref.trait, baseline[ref.trait]);
|
|
12760
|
-
}
|
|
12761
|
-
}
|
|
12762
|
-
writeEntries(target, to, kept);
|
|
12763
|
-
return { applied: true, kept };
|
|
12851
|
+
function resolveTokenReferences(value, tokens, mode = LIGHT) {
|
|
12852
|
+
const resolved = resolveTokenValues(tokens, mode);
|
|
12853
|
+
return value.replace(TOKEN_REF$1, (ref, name, fallback) => resolved[name] ?? (fallback !== undefined ? fallback.trim() : ref));
|
|
12854
|
+
}
|
|
12855
|
+
/** A scheme value with its placeholders replaced — `{{token}}` by the root's resolved value in this
|
|
12856
|
+
* mode, `{{~token}}` by its value in the OTHER mode (an inverse section is the other mode's ground,
|
|
12857
|
+
* DS9) — or null when a placeholder names a token the set does not have (the declaration is then
|
|
12858
|
+
* omitted). */
|
|
12859
|
+
function substitute(template, resolved, opposite) {
|
|
12860
|
+
let missing = false;
|
|
12861
|
+
const value = template.replace(PLACEHOLDER, (_, tilde, name) => {
|
|
12862
|
+
const from = tilde ? opposite : resolved;
|
|
12863
|
+
if (!(name in from))
|
|
12864
|
+
missing = true;
|
|
12865
|
+
return from[name] ?? '';
|
|
12866
|
+
});
|
|
12867
|
+
return missing ? null : value;
|
|
12764
12868
|
}
|
|
12869
|
+
const schemeEntries = (set, resolved, opposite) => Object.entries(set)
|
|
12870
|
+
.map(([name, template]) => [name, substitute(template, resolved, opposite)])
|
|
12871
|
+
.filter((e) => e[1] !== null);
|
|
12872
|
+
const hasPlaceholder = (value) => value.includes('{{');
|
|
12765
12873
|
/**
|
|
12766
|
-
*
|
|
12767
|
-
*
|
|
12768
|
-
*
|
|
12769
|
-
*
|
|
12770
|
-
*
|
|
12874
|
+
* Section colour schemes (design-system plan §3c). Two rules, both about WHERE a custom property
|
|
12875
|
+
* resolves:
|
|
12876
|
+
*
|
|
12877
|
+
* - ⚠️ Custom properties resolve where they are DECLARED: `--iox-card-bg: var(--iox-surface)`
|
|
12878
|
+
* declared on `:root` keeps `:root`'s surface inside `.iox-scheme-inverse`. So each scheme block
|
|
12879
|
+
* carries the spec's overrides PLUS every other token whose value references a token,
|
|
12880
|
+
* re-declared verbatim — re-resolving it in the section.
|
|
12881
|
+
* - ⚠️ A scheme that SWAPS two tokens (Brand: accent ⇄ accent-ink) cannot write them as `var()`:
|
|
12882
|
+
* on one element `accent: var(--iox-accent-ink)` + `accent-ink: var(--iox-accent)` is a cycle,
|
|
12883
|
+
* and CSS makes both invalid. The contract writes `{{accent}}` instead — the token's ROOT value,
|
|
12884
|
+
* resolved here at compile time (and again from dark values for the dark twin).
|
|
12771
12885
|
*/
|
|
12772
|
-
|
|
12773
|
-
const
|
|
12774
|
-
|
|
12775
|
-
|
|
12776
|
-
|
|
12886
|
+
function compileSchemeCss(tokens, scope, opposite) {
|
|
12887
|
+
const rows = usableTokens(tokens);
|
|
12888
|
+
if (!rows.length)
|
|
12889
|
+
return '';
|
|
12890
|
+
const resolved = resolveTokenValues(rows, LIGHT);
|
|
12891
|
+
const other = opposite ?? resolveTokenValues(rows, DARK);
|
|
12892
|
+
return [
|
|
12893
|
+
...nonDefaultSchemes().map(([id, set]) => rule(schemeSelector(id, scope), [
|
|
12894
|
+
...schemeEntries(set, resolved, other),
|
|
12895
|
+
...rows.filter(t => !(t.name in set) && t.value.includes(REFERENCE))
|
|
12896
|
+
.map((t) => [t.name, t.value]),
|
|
12897
|
+
])),
|
|
12898
|
+
schemeInkRule(scope),
|
|
12899
|
+
].filter(Boolean).join('\n');
|
|
12777
12900
|
}
|
|
12778
12901
|
/**
|
|
12779
|
-
*
|
|
12780
|
-
*
|
|
12781
|
-
*
|
|
12782
|
-
*
|
|
12902
|
+
* Every element wearing a scheme takes the scheme's ink (vectoriox/iox-ui#15): the tokens re-resolve inside
|
|
12903
|
+
* it, but `color` is inherited as a COMPUTED value, so without this a scheme'd Container's running text kept
|
|
12904
|
+
* the outer section's ink. One rule, specificity (0,1,0) in every renderer — a builder scope is wrapped in
|
|
12905
|
+
* `:where()` — emitted with the token CSS, BEFORE every node rule: a node's own colour (same specificity,
|
|
12906
|
+
* later) still wins. A node's `color: inherit` is read as this ink by `withSchemeInk`.
|
|
12783
12907
|
*/
|
|
12784
|
-
function
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12908
|
+
function schemeInkRule(scope) {
|
|
12909
|
+
const where = scope ? `:where(${scope}) ` : '';
|
|
12910
|
+
const selectors = nonDefaultSchemes().map(([id]) => `${where}.iox-scheme-${id}`);
|
|
12911
|
+
return selectors.length ? `${selectors.join(', ')} {\n color: ${SCHEME_INK};\n}` : '';
|
|
12912
|
+
}
|
|
12913
|
+
/** The dark twin of both scheme rules: a re-declared token with a dark value would otherwise pin
|
|
12914
|
+
* the LIGHT value inside the section, and a `{{token}}` swap was resolved from LIGHT values. */
|
|
12915
|
+
function darkSchemeRules(rows, scope) {
|
|
12916
|
+
const light = resolveTokenValues(rows, LIGHT);
|
|
12917
|
+
const dark = resolveTokenValues(rows, DARK);
|
|
12918
|
+
const redeclared = rows.filter(t => {
|
|
12919
|
+
const d = darkOf(t);
|
|
12920
|
+
return d !== null && (t.value.includes(REFERENCE) || d.includes(REFERENCE));
|
|
12921
|
+
});
|
|
12922
|
+
return nonDefaultSchemes().map(([id, set]) => {
|
|
12923
|
+
const swapped = Object.fromEntries(Object.entries(set).filter(([, v]) => hasPlaceholder(v)));
|
|
12924
|
+
const lightSwap = new Map(schemeEntries(swapped, light, dark));
|
|
12925
|
+
return rule(schemeSelector(id, scope), [
|
|
12926
|
+
...schemeEntries(swapped, dark, light).filter(([name, value]) => lightSwap.get(name) !== value),
|
|
12927
|
+
...redeclared.filter(t => !(t.name in set)).map((t) => [t.name, darkOf(t)]),
|
|
12928
|
+
], ' ');
|
|
12929
|
+
});
|
|
12930
|
+
}
|
|
12931
|
+
function presentOverrides(rows, overrides, onlyWithDark) {
|
|
12932
|
+
return Object.entries(overrides).filter(([name]) => rows.some(t => t.name === name && (!onlyWithDark || darkOf(t) !== null)));
|
|
12933
|
+
}
|
|
12934
|
+
/** The token CSS as the two halves a renderer places around its node rules. */
|
|
12935
|
+
function compileTokenCssBlocks(tokens, opts = {}) {
|
|
12936
|
+
const all = usableTokens(tokens);
|
|
12937
|
+
const rows = rowsForMode(all, opts.mode);
|
|
12938
|
+
const root = opts.scope ?? ROOT;
|
|
12939
|
+
// A forced mode flattens the rows to ONE mode; a `{{~token}}` still reads the other mode's value.
|
|
12940
|
+
const opposite = resolveTokenValues(all, opts.mode === DARK ? LIGHT : DARK);
|
|
12941
|
+
const present = new Set(rows.map(t => t.name));
|
|
12942
|
+
const unset = opts.isolate
|
|
12943
|
+
? [...specTokenNames()].filter(name => !present.has(name)).map((name) => [name, 'initial'])
|
|
12944
|
+
: [];
|
|
12945
|
+
const base = [
|
|
12946
|
+
rule(root, [...unset, ...rows.map((t) => [t.name, t.value])]),
|
|
12947
|
+
compileSchemeCss(rows, opts.scope, opposite),
|
|
12948
|
+
...ACCESSIBILITY_MEDIA.map(({ query, overrides }) => media(query, [rule(root, presentOverrides(rows, overrides, false), ' ')])),
|
|
12949
|
+
].filter(Boolean).join('\n');
|
|
12950
|
+
const darkRows = rows.map((t) => [t.name, darkOf(t)])
|
|
12951
|
+
.filter((e) => e[1] !== null);
|
|
12952
|
+
const dark = darkRows.length ? [
|
|
12953
|
+
media(MEDIA_DARK, [rule(root, darkRows, ' '), ...darkSchemeRules(rows, opts.scope)]),
|
|
12954
|
+
// Glass carries dark glass values; without this the dark block (LAST) would out-rank the
|
|
12955
|
+
// reduced-transparency swap and keep dark surfaces translucent.
|
|
12956
|
+
...ACCESSIBILITY_MEDIA.map(({ query, overrides }) => media(`${MEDIA_DARK} and ${query}`, [rule(root, presentOverrides(rows, overrides, true), ' ')])),
|
|
12957
|
+
].filter(Boolean).join('\n') : '';
|
|
12958
|
+
return { base, dark };
|
|
12959
|
+
}
|
|
12960
|
+
/** One stylesheet string: base → schemes → reduced motion → reduced transparency → dark LAST. */
|
|
12961
|
+
function compileTokenCss(tokens, opts = {}) {
|
|
12962
|
+
const { base, dark } = compileTokenCssBlocks(tokens, opts);
|
|
12963
|
+
return [base, dark].filter(Boolean).join('\n');
|
|
12964
|
+
}
|
|
12965
|
+
|
|
12966
|
+
/** A pack's own sanity: every token row names itself and carries a value. Returns errors. */
|
|
12967
|
+
function validateFlavorPack(pack) {
|
|
12968
|
+
const errors = [];
|
|
12969
|
+
for (const t of pack.tokens ?? []) {
|
|
12970
|
+
if (!t.name)
|
|
12971
|
+
errors.push(`${pack.id}: token with empty name`);
|
|
12972
|
+
if (!t.value)
|
|
12973
|
+
errors.push(`${pack.id}: token "${t.name}" has no value`);
|
|
12974
|
+
}
|
|
12975
|
+
return errors;
|
|
12792
12976
|
}
|
|
12977
|
+
/**
|
|
12978
|
+
* Swiss — the retired F1 pack: four tokens (control/surface radius, control/stack spacing) and the
|
|
12979
|
+
* hue opinion F2's brand step read. Three of its rows become the spec's `legacyAliases` on migration;
|
|
12980
|
+
* `space-control` is a v2 token in every pack and takes Crisp's value.
|
|
12981
|
+
*/
|
|
12982
|
+
const SWISS_FLAVOR = {
|
|
12983
|
+
id: 'swiss',
|
|
12984
|
+
version: 1,
|
|
12985
|
+
label: 'Swiss',
|
|
12986
|
+
blurb: 'Grid discipline, hairline rules, near-zero motion.',
|
|
12987
|
+
tokens: [
|
|
12988
|
+
{ name: 'radius-control', value: '4px', type: 'size', group: 'shape' },
|
|
12989
|
+
{ name: 'radius-surface', value: '4px', type: 'size', group: 'shape' },
|
|
12990
|
+
{ name: 'space-control', value: '10px 18px', type: 'spacing', group: 'space' },
|
|
12991
|
+
{ name: 'space-stack', value: '12px', type: 'spacing', group: 'space' },
|
|
12992
|
+
],
|
|
12993
|
+
// F2: Swiss turns the seed toward a cool counterpoint.
|
|
12994
|
+
accentHueDeg: 150,
|
|
12995
|
+
};
|
|
12793
12996
|
|
|
12794
12997
|
/**
|
|
12795
12998
|
* ADOPT (design-system DS7, decision D5): link the nodes of a page saved before element styles to
|
|
@@ -12987,116 +13190,6 @@ function previewElementStyleAdoption(tree, ctx) {
|
|
|
12987
13190
|
return adoptElementStyles(JSON.parse(JSON.stringify(tree ?? [])), ctx);
|
|
12988
13191
|
}
|
|
12989
13192
|
|
|
12990
|
-
/**
|
|
12991
|
-
* The design-system classes a node renders, in BOTH renderers (builder canvas, engine component
|
|
12992
|
-
* path, engine string path) — ONE helper, so the three can never disagree about which class a node
|
|
12993
|
-
* carries:
|
|
12994
|
-
*
|
|
12995
|
-
* - the element-style MARKER `iox-es iox-es-<id>` (design-system §3b-bis) — component CSS carrying
|
|
12996
|
-
* the system look is scoped to it, so a node saved before DS2 keeps its pre-DS2 look;
|
|
12997
|
-
* - the section colour scheme `iox-scheme-<id>` (§3c) for a non-default `colorScheme` — the class
|
|
12998
|
-
* `compileSchemeCss` re-declares tokens on, so everything inside re-resolves;
|
|
12999
|
-
* - the composite ROLE `iox-role-<role>` (`card.media` → `iox-role-card-media`; composite-components
|
|
13000
|
-
* plan §3, Card v2) — what the shared CSS keys a part's structural rules on (the badge's corner, the
|
|
13001
|
-
* card's stretched link), so a role is never a renderer's private knowledge.
|
|
13002
|
-
*
|
|
13003
|
-
* Renderers read `elementStyle`, `colorScheme` and `role` for exactly this and nothing else.
|
|
13004
|
-
*/
|
|
13005
|
-
/** The section colour schemes — the contract's `schemes` keys. */
|
|
13006
|
-
var ColorScheme;
|
|
13007
|
-
(function (ColorScheme) {
|
|
13008
|
-
ColorScheme["Default"] = "default";
|
|
13009
|
-
ColorScheme["Subtle"] = "subtle";
|
|
13010
|
-
ColorScheme["Inverse"] = "inverse";
|
|
13011
|
-
ColorScheme["Accent"] = "accent";
|
|
13012
|
-
})(ColorScheme || (ColorScheme = {}));
|
|
13013
|
-
/** The content trait (stored in `props`, not a style prop) that picks a node's scheme. */
|
|
13014
|
-
const COLOR_SCHEME_TRAIT = 'colorScheme';
|
|
13015
|
-
/** The node types that offer a scheme (spec §3c: Section/Container; LinkedContainer is a Container that links). */
|
|
13016
|
-
const COLOR_SCHEME_TYPES = ['Section', 'Container', 'LinkedContainer'];
|
|
13017
|
-
/** Every scheme in contract order, with the contract's label (Default · Subtle · Inverse · Brand). */
|
|
13018
|
-
const COLOR_SCHEMES = Object.keys(SPEC_SCHEMES).map(id => ({ id, label: SPEC_SCHEMES[id].label }));
|
|
13019
|
-
const SCHEME_IDS$1 = new Set(Object.keys(SPEC_SCHEMES));
|
|
13020
|
-
const SCHEME_PREFIX = 'iox-scheme-';
|
|
13021
|
-
const ROLE_PREFIX = 'iox-role-';
|
|
13022
|
-
/** A role is dot-separated lowercase words (`card`, `card.title`) — anything else never reaches a class. */
|
|
13023
|
-
const ROLE_SHAPE = /^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)*$/;
|
|
13024
|
-
const MARKER_PREFIX = `${ELEMENT_STYLE_MARKER_CLASS}-`;
|
|
13025
|
-
/** `iox-scheme-<id>` for a known NON-default scheme, else null — an unknown id never reaches a class attribute. */
|
|
13026
|
-
function colorSchemeClass(id) {
|
|
13027
|
-
return typeof id === 'string' && id !== ColorScheme.Default && SCHEME_IDS$1.has(id) ? `${SCHEME_PREFIX}${id}` : null;
|
|
13028
|
-
}
|
|
13029
|
-
/** `iox-role-<role>` for a well-formed composite role, else null. */
|
|
13030
|
-
function roleClass(role) {
|
|
13031
|
-
return typeof role === 'string' && ROLE_SHAPE.test(role) ? `${ROLE_PREFIX}${role.replace(/\./g, '-')}` : null;
|
|
13032
|
-
}
|
|
13033
|
-
/** The element style whose wearer is the phone's bottom navigation bar (CC1, R1). */
|
|
13034
|
-
const BOTTOM_BAR_STYLE = 'bottom-bar';
|
|
13035
|
-
/** The page reserves the bar's height wherever this class is on the page… */
|
|
13036
|
-
const BAR_RESERVE_CLASS = 'iox-bar-reserve';
|
|
13037
|
-
/** …the responsive Breakpoint ids that can hold an override, widest first (a spec pins it to BREAKPOINTS). */
|
|
13038
|
-
const BAR_RESERVE_BREAKPOINTS = ['laptop', 'tablet', 'mobile', 'small'];
|
|
13039
|
-
function baseDisplayOf(node) {
|
|
13040
|
-
if (node.styleProps && 'display' in node.styleProps)
|
|
13041
|
-
return node.styleProps['display'];
|
|
13042
|
-
for (const group of node.styleTraits ?? []) {
|
|
13043
|
-
const hit = group.traits?.find(t => t?.name === 'display');
|
|
13044
|
-
if (hit)
|
|
13045
|
-
return hit.default;
|
|
13046
|
-
}
|
|
13047
|
-
return undefined;
|
|
13048
|
-
}
|
|
13049
|
-
/**
|
|
13050
|
-
* The class that makes the page reserve a bottom bar's height (iox-design.css: `padding-bottom` and
|
|
13051
|
-
* `scroll-padding-bottom`, WCAG 2.4.11), only at the widths where the bar SHOWS: `iox-bar-reserve` when
|
|
13052
|
-
* it shows at every width, `iox-bar-reserve-<bp>` when it is hidden at base and shown from that
|
|
13053
|
-
* breakpoint down (the phone shape's own rule), null when it never shows or is not a bar.
|
|
13054
|
-
*/
|
|
13055
|
-
function barReserveClass(node) {
|
|
13056
|
-
if (!node || node.elementStyle !== BOTTOM_BAR_STYLE)
|
|
13057
|
-
return null;
|
|
13058
|
-
if (baseDisplayOf(node) !== 'none')
|
|
13059
|
-
return BAR_RESERVE_CLASS;
|
|
13060
|
-
for (const bp of BAR_RESERVE_BREAKPOINTS) {
|
|
13061
|
-
const display = node.responsive?.[bp]?.styleProps?.['display'];
|
|
13062
|
-
if (display !== undefined && display !== 'none')
|
|
13063
|
-
return `${BAR_RESERVE_CLASS}-${bp}`;
|
|
13064
|
-
}
|
|
13065
|
-
return null;
|
|
13066
|
-
}
|
|
13067
|
-
/** A node's `colorScheme`, from `props` (serialized) or its trait (builder). */
|
|
13068
|
-
function colorSchemeOf(node) {
|
|
13069
|
-
if (!node)
|
|
13070
|
-
return null;
|
|
13071
|
-
const fromProps = node.props?.[COLOR_SCHEME_TRAIT];
|
|
13072
|
-
if (fromProps !== undefined)
|
|
13073
|
-
return typeof fromProps === 'string' ? fromProps : null;
|
|
13074
|
-
const trait = node.traits?.find(t => t?.name === COLOR_SCHEME_TRAIT)?.default;
|
|
13075
|
-
return typeof trait === 'string' ? trait : null;
|
|
13076
|
-
}
|
|
13077
|
-
/** True when the node wears a known element style — the marker is on it. */
|
|
13078
|
-
function hasElementStyleMarker(node) {
|
|
13079
|
-
return elementStyleClass(node?.elementStyle) !== null;
|
|
13080
|
-
}
|
|
13081
|
-
/** The classes a node renders: `'iox-es iox-es-card iox-scheme-inverse'` (+ a bottom bar's reserve class), or `''` for none. */
|
|
13082
|
-
function nodeDesignClasses(node) {
|
|
13083
|
-
const marker = elementStyleClass(node?.elementStyle);
|
|
13084
|
-
return [marker ? `${ELEMENT_STYLE_MARKER_CLASS} ${marker}` : '', colorSchemeClass(colorSchemeOf(node)) ?? '', roleClass(node?.role) ?? '', barReserveClass(node) ?? '']
|
|
13085
|
-
.filter(Boolean).join(' ');
|
|
13086
|
-
}
|
|
13087
|
-
const isDesignClass = (c) => c === ELEMENT_STYLE_MARKER_CLASS || c.startsWith(MARKER_PREFIX) || c.startsWith(SCHEME_PREFIX) || c.startsWith(ROLE_PREFIX) || c.startsWith(BAR_RESERVE_CLASS);
|
|
13088
|
-
/** Make an element's design classes match the node — the live switch on the canvas and the
|
|
13089
|
-
* component path's one-time stamp. Removes stale ones; touches no other class. */
|
|
13090
|
-
function syncNodeDesignClasses(el, node) {
|
|
13091
|
-
if (!el?.classList)
|
|
13092
|
-
return;
|
|
13093
|
-
for (const c of Array.from(el.classList).filter(isDesignClass))
|
|
13094
|
-
el.classList.remove(c);
|
|
13095
|
-
const classes = nodeDesignClasses(node);
|
|
13096
|
-
if (classes)
|
|
13097
|
-
el.classList.add(...classes.split(' '));
|
|
13098
|
-
}
|
|
13099
|
-
|
|
13100
13193
|
/**
|
|
13101
13194
|
* Empty images (design-system DS3). A MARKED Image (`.iox-es-media`) with no source renders a box in
|
|
13102
13195
|
* the `surface-2` token with its aspect ratio kept — on the canvas with an "Add image" label, on the
|
|
@@ -13836,6 +13929,8 @@ const GLYPH_GROUP = 'Media';
|
|
|
13836
13929
|
const FORMS_GROUP = 'Forms';
|
|
13837
13930
|
const DEFAULT_SCHEME = 'default';
|
|
13838
13931
|
const SECTION = 'section';
|
|
13932
|
+
/** The element a scheme'd container's running text is reported as (iox-ui#15). */
|
|
13933
|
+
const INHERITED_TEXT = 'inherited text';
|
|
13839
13934
|
const FIELD = 'field';
|
|
13840
13935
|
const WHITE = { r: 1, g: 1, b: 1, a: 1 };
|
|
13841
13936
|
const SINGLE_REF = /^var\(--iox-([\w-]+)\)$/;
|
|
@@ -13948,10 +14043,51 @@ function auditDesignContrast(rows, mode) {
|
|
|
13948
14043
|
}
|
|
13949
14044
|
}
|
|
13950
14045
|
}
|
|
14046
|
+
findings.push(...schemedContainerFindings(rows, mode, section, containers.filter((c) => !!c)));
|
|
13951
14047
|
for (const scrim of SCRIMS)
|
|
13952
14048
|
findings.push(...scrimFindings(rows, mode, scrim, byId.get(scrim.style)));
|
|
13953
14049
|
return findings;
|
|
13954
14050
|
}
|
|
14051
|
+
/** What a section in `values` paints under its content: its own fill over the page, or the page. */
|
|
14052
|
+
function sectionGround(values) {
|
|
14053
|
+
const pageInk = parseCssColour(values['text']);
|
|
14054
|
+
const page = paintColours(values['page-bg'], pageInk);
|
|
14055
|
+
const sectionPaint = paintColours(values['section-bg'], pageInk);
|
|
14056
|
+
return opaque(sectionPaint) ? sectionPaint.map(c => (c.a < 1 ? compositeOver(c, page[0] ?? WHITE) : c)) : page;
|
|
14057
|
+
}
|
|
14058
|
+
/**
|
|
14059
|
+
* A container that wears a NON-default scheme, inside a section of every scheme (vectoriox/iox-ui#15 — the
|
|
14060
|
+
* Featured card is a Card in Brand on a Default page). Its tokens are its own scheme's laid over the outer
|
|
14061
|
+
* section's (what it does not set, it inherits); a translucent fill composites over the OUTER section; the running text it holds (`body`, `lead`, a label: `color: inherit`)
|
|
14062
|
+
* reads the scheme's ink, which is what the scheme-ink rule and `withSchemeInk` make CSS compute.
|
|
14063
|
+
*/
|
|
14064
|
+
function schemedContainerFindings(rows, mode, section, containers) {
|
|
14065
|
+
const out = [];
|
|
14066
|
+
for (const outer of SCHEME_IDS) {
|
|
14067
|
+
const ground = sectionGround(resolveSchemeTokenValues(rows, mode, outer));
|
|
14068
|
+
for (const inner of SCHEME_IDS.filter(id => id !== DEFAULT_SCHEME)) {
|
|
14069
|
+
const values = resolveSchemeTokenValues(rows, mode, [outer, inner]);
|
|
14070
|
+
const schemeInk = parseCssColour(resolveIn(values, SCHEME_INK), parseCssColour(resolveIn(values, section['color'])));
|
|
14071
|
+
for (const box of containers) {
|
|
14072
|
+
const style = ownStyle(box);
|
|
14073
|
+
const bgs = overAll(paintColours(resolveIn(values, style['backgroundColor']), schemeInk), ground);
|
|
14074
|
+
const ink = style['color'] && style['color'] !== 'inherit' ? parseCssColour(resolveIn(values, style['color']), schemeInk) : schemeInk;
|
|
14075
|
+
if (!ink)
|
|
14076
|
+
continue;
|
|
14077
|
+
for (const g of bgs) {
|
|
14078
|
+
const bg = quantizeRgb(g);
|
|
14079
|
+
const f = quantizeRgb(ink.a < 1 ? compositeOver(ink, bg) : ink);
|
|
14080
|
+
const ratio = wcagContrastRatio(f, bg);
|
|
14081
|
+
out.push({
|
|
14082
|
+
scheme: inner, container: `${box.id} in a ${outer} section`, element: INHERITED_TEXT, part: 'text',
|
|
14083
|
+
fg: toHexColor(f), bg: toHexColor(bg), ratio: Math.round(ratio * 100) / 100, min: WCAG_AA_TEXT, pass: ratio >= WCAG_AA_TEXT - 1e-9,
|
|
14084
|
+
});
|
|
14085
|
+
}
|
|
14086
|
+
}
|
|
14087
|
+
}
|
|
14088
|
+
}
|
|
14089
|
+
return out;
|
|
14090
|
+
}
|
|
13955
14091
|
/** Text over an image: the block's ink — and every token its ink scope pins to it — over the scrim
|
|
13956
14092
|
* composited on the WORST-CASE image, in the scheme the block wears. Never over the section: the image
|
|
13957
14093
|
* covers it. */
|
|
@@ -15245,5 +15381,5 @@ function planFontFamilyRemoval(existing, previous, family) {
|
|
|
15245
15381
|
* Generated bundle index. Do not edit.
|
|
15246
15382
|
*/
|
|
15247
15383
|
|
|
15248
|
-
export { ACCENT_TOKEN_NAMES, AdoptOutcome, AdoptSkipReason, BAR_RESERVE_BREAKPOINTS, BAR_RESERVE_CLASS, BOTTOM_BAR_STYLE, BUTTON_VARIANT_TO_STYLE, CANVAS_LINK_ATTRIBUTE, CARD_LINK_CLASS, COLOR_SCHEMES, COLOR_SCHEME_TRAIT, COLOR_SCHEME_TYPES, ColorScheme, ColourCheckId, DEFAULT_FLAVOR_ID, DESIGN_TOKEN_GROUPS, DESIGN_TOKEN_TIERS, DESIGN_TOKEN_TYPES, DesignConfigKey, ELEMENT_STYLES, ELEMENT_STYLE_MARKER_CLASS, ELEMENT_STYLE_STATES, EMPTY_IMAGE_ATTRIBUTE, EMPTY_IMAGE_SRC, ElementStyleState, FLAVOR_SPEC_VERSION, FONT_CATALOG, FONT_FAMILY_TOKENS, FONT_FILE_ACCEPT, FONT_FILE_EXTENSIONS, FONT_FILE_FORMATS, FONT_STYLES, FONT_WEIGHTS, FontUploadError, GOOGLE_FONTS_CSS_ORIGIN, GOOGLE_FONTS_FILE_ORIGIN, HELD_CONTRAST, LinkType, MAX_FONT_FILE_BYTES, NEW_NODE_STYLE_DEFAULTS, OwnedTraitLink, PALETTE_PRESETS, PRE_DS2_FLAVOR_DEFAULTS, PRE_TINT_DEFAULT, REDUCED_MOTION_OVERRIDES, REDUCED_TRANSPARENCY_OVERRIDES, REVERT_WINDOW_MS, SPEC_A11Y, SPEC_AXES, SPEC_BUTTON_VARIANT_TO_STYLE, SPEC_CONTRAST, SPEC_CONTRAST_AUDIT, SPEC_DEFAULT_ELEMENT_STYLE, SPEC_ELEMENT_STYLES, SPEC_FIELD_CLASS_BASELINE, SPEC_FLAVORS, SPEC_FLAVOR_PACKS, SPEC_FONTS, SPEC_FONT_ROLES, SPEC_INK_SCOPES, SPEC_LEGACY_ALIASES, SPEC_PALETTE_PRESETS, SPEC_SCHEMES, SPEC_SPRINGS, SPEC_TIERS, SPEC_TIER_IDS, SPEC_TOKEN_TYPES, SUPERSEDED_STYLE_VALUES, SWISS_FLAVOR, TINT_FULL_CHROMA, TINT_IDS, TINT_LEVELS, TINT_OWN_HUE_CHROMA, TINT_TURN_CHROMA, USER_TOKEN_SOURCE, WCAG_AA_TEXT, WCAG_AA_UI, adoptElementStyles, adoptionStyleFor, apcaLc, applyElementStyle, applyHeadingLevelRule, atLightness, atLightnessMaxChroma, auditDesignContrast, barReserveClass, buildFlavorTokens, buildFontFaceCss, buttonBlockHref, catalogFontId, checkFontWeight, choicesForPack, colorSchemeClass, colorSchemeOf, colourTabChecks, compareFontWeights, compileSchemeCss, compileTokenCss, compileTokenCssBlocks, compositeOver, cssString, defaultDesignChoices, defaultElementStyleFor, deriveAccentTokens, deriveBrandTokens, designBaseline, designConfigEntries, designModeOf, designTokenRepairs, designTokenRows, elementStyleById, elementStyleClass, elementStylesFor, emptyImageLabelSrc, emptyImagePlaceholder, emptyImageSrc, ensureAlpha, ensureContrast, flavorColours, flavorPackById, flavorSeedWrites, flavorSourceStamp, fontFamilyKey, fontFileName, fontFileStem, fontFormatOf, fontPreloads, fontRoleReferences, fontStackWithout, fontWeightCovers, fontWeightRange, fontWeightValue, fontsForTokens, formatFontFamilies, formatFontFamily, formatFontWeight, googleFontHref, groupFontFamilies, hasElementStyleMarker, headingHref, inSrgbGamut, isDesignTokenGroup, isDesignTokenTier, isDesignTokenType, isFontWeightRange, isRetiredFlavorId, legacyDesignTokenRows, legacyFlavorTokens, legacyRuleTokenReferences, matchFontWeight, missingDesignRows, missingFontRoles, nodeDesignClasses, normalizeFontStyle, normalizeFontWeight, normalizeFontWeightValue, oklabToRgb, ownedTraitStatus, ownedTraitsOf, packDesignChoices, paintColours, parseCssColour, parseFontFamilies, parseFontWeight, parseHexColor, planDesignApply, planDesignRevert, planFlavorRevert, planFlavorSeed, planFontFamilyRemoval, planSwissMigration, preTintAccentGrounds, previewElementStyleAdoption, previewFontWeight, quantizeRgb, readDesignConfig, readOwnedTrait, relativeLuminance, resolveDesignChoices, resolveSchemeTokenValues, resolveTokenReferences, resolveTokenValues, revertAvailable, rgbToOklab, ringColour, roleClass, sameDesignChoices, specTokenNames, splitTopLevel, springToLinear, stackNamesFamily, styleKeyToKebab, switchElementStyle, syncNodeDesignClasses, toHexColor, tokenReferences, tokensToDarkVarMap, tokensToVarMap, unknownTokenReferences, untouchedSeedRow, userFontStack, validateFlavorPack, wcagContrastRatio, writeOwnedTrait };
|
|
15384
|
+
export { ACCENT_TOKEN_NAMES, AdoptOutcome, AdoptSkipReason, BAR_RESERVE_BREAKPOINTS, BAR_RESERVE_CLASS, BOTTOM_BAR_STYLE, BUTTON_VARIANT_TO_STYLE, CANVAS_LINK_ATTRIBUTE, CARD_LINK_CLASS, COLOR_SCHEMES, COLOR_SCHEME_TRAIT, COLOR_SCHEME_TYPES, ColorScheme, ColourCheckId, DEFAULT_FLAVOR_ID, DESIGN_TOKEN_GROUPS, DESIGN_TOKEN_TIERS, DESIGN_TOKEN_TYPES, DesignConfigKey, ELEMENT_STYLES, ELEMENT_STYLE_MARKER_CLASS, ELEMENT_STYLE_STATES, EMPTY_IMAGE_ATTRIBUTE, EMPTY_IMAGE_SRC, ElementStyleState, FLAVOR_SPEC_VERSION, FONT_CATALOG, FONT_FAMILY_TOKENS, FONT_FILE_ACCEPT, FONT_FILE_EXTENSIONS, FONT_FILE_FORMATS, FONT_STYLES, FONT_WEIGHTS, FontUploadError, GOOGLE_FONTS_CSS_ORIGIN, GOOGLE_FONTS_FILE_ORIGIN, HELD_CONTRAST, INHERITED_TEXT, LinkType, MAX_FONT_FILE_BYTES, NEW_NODE_STYLE_DEFAULTS, OwnedTraitLink, PALETTE_PRESETS, PRE_DS2_FLAVOR_DEFAULTS, PRE_TINT_DEFAULT, REDUCED_MOTION_OVERRIDES, REDUCED_TRANSPARENCY_OVERRIDES, REVERT_WINDOW_MS, SCHEME_INK, SPEC_A11Y, SPEC_AXES, SPEC_BUTTON_VARIANT_TO_STYLE, SPEC_CONTRAST, SPEC_CONTRAST_AUDIT, SPEC_DEFAULT_ELEMENT_STYLE, SPEC_ELEMENT_STYLES, SPEC_FIELD_CLASS_BASELINE, SPEC_FLAVORS, SPEC_FLAVOR_PACKS, SPEC_FONTS, SPEC_FONT_ROLES, SPEC_INK_SCOPES, SPEC_LEGACY_ALIASES, SPEC_PALETTE_PRESETS, SPEC_SCHEMES, SPEC_SCHEME_INK, SPEC_SPRINGS, SPEC_TIERS, SPEC_TIER_IDS, SPEC_TOKEN_TYPES, SUPERSEDED_STYLE_VALUES, SWISS_FLAVOR, TINT_FULL_CHROMA, TINT_IDS, TINT_LEVELS, TINT_OWN_HUE_CHROMA, TINT_TURN_CHROMA, USER_TOKEN_SOURCE, WCAG_AA_TEXT, WCAG_AA_UI, adoptElementStyles, adoptionStyleFor, apcaLc, applyElementStyle, applyHeadingLevelRule, atLightness, atLightnessMaxChroma, auditDesignContrast, barReserveClass, buildFlavorTokens, buildFontFaceCss, buttonBlockHref, catalogFontId, checkFontWeight, choicesForPack, colorSchemeClass, colorSchemeOf, colourTabChecks, compareFontWeights, compileSchemeCss, compileTokenCss, compileTokenCssBlocks, compositeOver, cssString, defaultDesignChoices, defaultElementStyleFor, deriveAccentTokens, deriveBrandTokens, designBaseline, designConfigEntries, designModeOf, designTokenRepairs, designTokenRows, elementStyleById, elementStyleClass, elementStylesFor, emptyImageLabelSrc, emptyImagePlaceholder, emptyImageSrc, ensureAlpha, ensureContrast, flavorColours, flavorPackById, flavorSeedWrites, flavorSourceStamp, fontFamilyKey, fontFileName, fontFileStem, fontFormatOf, fontPreloads, fontRoleReferences, fontStackWithout, fontWeightCovers, fontWeightRange, fontWeightValue, fontsForTokens, formatFontFamilies, formatFontFamily, formatFontWeight, googleFontHref, groupFontFamilies, hasElementStyleMarker, headingHref, inSrgbGamut, isDesignTokenGroup, isDesignTokenTier, isDesignTokenType, isFontWeightRange, isRetiredFlavorId, legacyDesignTokenRows, legacyFlavorTokens, legacyRuleTokenReferences, matchFontWeight, missingDesignRows, missingFontRoles, nodeDesignClasses, normalizeFontStyle, normalizeFontWeight, normalizeFontWeightValue, oklabToRgb, ownedTraitStatus, ownedTraitsOf, packDesignChoices, paintColours, parseCssColour, parseFontFamilies, parseFontWeight, parseHexColor, planDesignApply, planDesignRevert, planFlavorRevert, planFlavorSeed, planFontFamilyRemoval, planSwissMigration, preTintAccentGrounds, previewElementStyleAdoption, previewFontWeight, quantizeRgb, readDesignConfig, readOwnedTrait, relativeLuminance, resolveDesignChoices, resolveSchemeTokenValues, resolveTokenReferences, resolveTokenValues, revertAvailable, rgbToOklab, ringColour, roleClass, sameDesignChoices, setColorScheme, specTokenNames, splitTopLevel, springToLinear, stackNamesFamily, styleKeyToKebab, switchElementStyle, syncNodeDesignClasses, toHexColor, tokenReferences, tokensToDarkVarMap, tokensToVarMap, unknownTokenReferences, untouchedSeedRow, userFontStack, validateFlavorPack, wcagContrastRatio, withSchemeInk, writeOwnedTrait };
|
|
15249
15385
|
//# sourceMappingURL=vectoriox-iox-ui-design-core.mjs.map
|