@vectoriox/iox-ui 5.30.0 → 5.31.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 +270 -0
- package/composite-core/package.json +3 -0
- package/design-core/index.d.ts +870 -41
- package/fesm2022/vectoriox-iox-ui-composite-core.mjs +698 -0
- package/fesm2022/vectoriox-iox-ui-composite-core.mjs.map +1 -0
- package/fesm2022/vectoriox-iox-ui-design-core.mjs +1090 -82
- package/fesm2022/vectoriox-iox-ui-design-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs +110 -30
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui.mjs +134 -31
- package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
- package/generation-core/index.d.ts +35 -23
- package/index.d.ts +41 -15
- package/package.json +5 -1
- package/src/composite-core/badge.ts +103 -0
- package/src/composite-core/card.ts +524 -0
- package/src/composite-core/composite-node.ts +143 -0
- package/src/composite-core/public-api.ts +11 -0
- package/src/composite-core/structure.ts +58 -0
- package/src/design-core/contrast-audit.ts +38 -5
- package/src/design-core/flavor-fixtures.generated.ts +144 -144
- package/src/design-core/flavor-spec.generated.ts +970 -26
- package/src/design-core/node-classes.ts +16 -4
- package/src/design-core/node-links.ts +29 -0
- package/src/generation-core/compose-site.ts +55 -1
- package/src/generation-core/node-baselines.generated.ts +14 -2
- package/src/generation-core/patterns.ts +29 -2
- package/src/generation-core/serialized-node.ts +2 -0
- package/src/generation-core/site-spec.generated.ts +13 -26
- package/styles/iox-design.css +62 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, elementStyleById, ownedTraitsOf, applyElementStyle, flavorPackById, parseHexColor, SPEC_AXES, LinkType, resolveDesignChoices } from '@vectoriox/iox-ui/design-core';
|
|
2
2
|
import { formPresetById } from '@vectoriox/iox-ui/forms-core';
|
|
3
|
+
import { CardRole, CardLayout, CARD_LAYOUTS, CARD_PARTS, buildCardRecipe, findByRole } from '@vectoriox/iox-ui/composite-core';
|
|
3
4
|
|
|
4
5
|
// GENERATED from iox-ai-guidance flavor-spec.v1.json — do not edit; re-run scripts/gen-flavor-spec.mjs
|
|
5
6
|
// (npm run gen:flavor-spec). The JSON is itself generated by iox-ai-guidance
|
|
@@ -429,34 +430,21 @@ const SPEC_SITE_PATTERNS = {
|
|
|
429
430
|
},
|
|
430
431
|
"c": [
|
|
431
432
|
{
|
|
432
|
-
"t": "
|
|
433
|
-
"
|
|
433
|
+
"t": "Container",
|
|
434
|
+
"recipe": "card",
|
|
435
|
+
"layout": "top",
|
|
436
|
+
"parts": {
|
|
437
|
+
"badge": false,
|
|
438
|
+
"actions": false
|
|
439
|
+
},
|
|
434
440
|
"href": "/work/:slug",
|
|
435
441
|
"param": "item.slug",
|
|
436
|
-
"
|
|
437
|
-
"
|
|
438
|
-
"
|
|
439
|
-
"
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
{
|
|
443
|
-
"t": "Image",
|
|
444
|
-
"es": "media",
|
|
445
|
-
"bind": "item.cover",
|
|
446
|
-
"aspect": "4 / 3"
|
|
447
|
-
},
|
|
448
|
-
{
|
|
449
|
-
"t": "Heading",
|
|
450
|
-
"es": "h3",
|
|
451
|
-
"level": "h3",
|
|
452
|
-
"bind": "item.title"
|
|
453
|
-
},
|
|
454
|
-
{
|
|
455
|
-
"t": "Text",
|
|
456
|
-
"es": "small",
|
|
457
|
-
"bind": "item.summary"
|
|
458
|
-
}
|
|
459
|
-
]
|
|
442
|
+
"binds": {
|
|
443
|
+
"image": "item.cover",
|
|
444
|
+
"eyebrow": "item.year",
|
|
445
|
+
"title": "item.title",
|
|
446
|
+
"text": "item.summary"
|
|
447
|
+
}
|
|
460
448
|
}
|
|
461
449
|
]
|
|
462
450
|
}
|
|
@@ -1923,7 +1911,11 @@ const NODE_BASELINES = {
|
|
|
1923
1911
|
"Heading": {
|
|
1924
1912
|
"props": {
|
|
1925
1913
|
"content": "Heading",
|
|
1926
|
-
"level": "h2"
|
|
1914
|
+
"level": "h2",
|
|
1915
|
+
"linkType": "none",
|
|
1916
|
+
"url": "",
|
|
1917
|
+
"pageRoute": "",
|
|
1918
|
+
"target": "_self"
|
|
1927
1919
|
},
|
|
1928
1920
|
"styleProps": {
|
|
1929
1921
|
"position": "static",
|
|
@@ -1972,6 +1964,7 @@ const NODE_BASELINES = {
|
|
|
1972
1964
|
"textDecoration": "none",
|
|
1973
1965
|
"WebkitTextStrokeWidth": "0px",
|
|
1974
1966
|
"WebkitTextStrokeColor": "transparent",
|
|
1967
|
+
"maxLines": "none",
|
|
1975
1968
|
"margin": "0px 0px 0px 0px",
|
|
1976
1969
|
"padding": "0px 0px 0px 0px",
|
|
1977
1970
|
"borderWidth": "0px",
|
|
@@ -2011,7 +2004,11 @@ const NODE_BASELINES = {
|
|
|
2011
2004
|
},
|
|
2012
2005
|
"traits": [
|
|
2013
2006
|
"content",
|
|
2014
|
-
"level"
|
|
2007
|
+
"level",
|
|
2008
|
+
"linkType",
|
|
2009
|
+
"url",
|
|
2010
|
+
"pageRoute",
|
|
2011
|
+
"target"
|
|
2015
2012
|
],
|
|
2016
2013
|
"styleTraits": [
|
|
2017
2014
|
"position",
|
|
@@ -2061,6 +2058,7 @@ const NODE_BASELINES = {
|
|
|
2061
2058
|
"_sep_stroke",
|
|
2062
2059
|
"WebkitTextStrokeWidth",
|
|
2063
2060
|
"WebkitTextStrokeColor",
|
|
2061
|
+
"maxLines",
|
|
2064
2062
|
"margin",
|
|
2065
2063
|
"padding",
|
|
2066
2064
|
"borderWidth",
|
|
@@ -2158,6 +2156,7 @@ const NODE_BASELINES = {
|
|
|
2158
2156
|
"textDecoration": "none",
|
|
2159
2157
|
"WebkitTextStrokeWidth": "0px",
|
|
2160
2158
|
"WebkitTextStrokeColor": "transparent",
|
|
2159
|
+
"maxLines": "none",
|
|
2161
2160
|
"margin": "0px 0px 0px 0px",
|
|
2162
2161
|
"padding": "10px",
|
|
2163
2162
|
"borderWidth": "0px",
|
|
@@ -2247,6 +2246,7 @@ const NODE_BASELINES = {
|
|
|
2247
2246
|
"_sep_stroke",
|
|
2248
2247
|
"WebkitTextStrokeWidth",
|
|
2249
2248
|
"WebkitTextStrokeColor",
|
|
2249
|
+
"maxLines",
|
|
2250
2250
|
"margin",
|
|
2251
2251
|
"padding",
|
|
2252
2252
|
"borderWidth",
|
|
@@ -6198,6 +6198,23 @@ var GlobalSlot;
|
|
|
6198
6198
|
GlobalSlot["Footer"] = "footer";
|
|
6199
6199
|
})(GlobalSlot || (GlobalSlot = {}));
|
|
6200
6200
|
|
|
6201
|
+
/** The composite-core recipes a pattern may stamp (`recipe`). */
|
|
6202
|
+
var PatternRecipe;
|
|
6203
|
+
(function (PatternRecipe) {
|
|
6204
|
+
PatternRecipe["Card"] = "card";
|
|
6205
|
+
})(PatternRecipe || (PatternRecipe = {}));
|
|
6206
|
+
/** A recipe node's `binds` keys → the part each binds (Card v2). */
|
|
6207
|
+
var CardBindTarget;
|
|
6208
|
+
(function (CardBindTarget) {
|
|
6209
|
+
CardBindTarget["Image"] = "image";
|
|
6210
|
+
CardBindTarget["Eyebrow"] = "eyebrow";
|
|
6211
|
+
CardBindTarget["Title"] = "title";
|
|
6212
|
+
CardBindTarget["Text"] = "text";
|
|
6213
|
+
})(CardBindTarget || (CardBindTarget = {}));
|
|
6214
|
+
/** Every binding path a node reads: its own `bind`, and a recipe's `binds`. */
|
|
6215
|
+
function nodeBindPaths(node) {
|
|
6216
|
+
return [node.bind, ...Object.values(node.binds ?? {})].filter((p) => !!p);
|
|
6217
|
+
}
|
|
6201
6218
|
var PatternGlobalPosition;
|
|
6202
6219
|
(function (PatternGlobalPosition) {
|
|
6203
6220
|
PatternGlobalPosition["Before"] = "before";
|
|
@@ -6268,6 +6285,10 @@ function altSourceScopes(pattern) {
|
|
|
6268
6285
|
const visit = (n) => {
|
|
6269
6286
|
if (n.t === IMAGE_TYPE && n.bind && n.alt === undefined)
|
|
6270
6287
|
scopes.add(n.bind.split('.')[0]);
|
|
6288
|
+
// A Card v2's bound image takes its alt from the same item.
|
|
6289
|
+
const cardImage = n.recipe === PatternRecipe.Card ? n.binds?.[CardBindTarget.Image] : undefined;
|
|
6290
|
+
if (cardImage)
|
|
6291
|
+
scopes.add(cardImage.split('.')[0]);
|
|
6271
6292
|
for (const child of n.c ?? [])
|
|
6272
6293
|
visit(child);
|
|
6273
6294
|
};
|
|
@@ -6278,7 +6299,7 @@ function altSourceScopes(pattern) {
|
|
|
6278
6299
|
function patternScopes(pattern) {
|
|
6279
6300
|
const scopes = new Set();
|
|
6280
6301
|
for (const n of patternNodes(pattern)) {
|
|
6281
|
-
for (const path of [n
|
|
6302
|
+
for (const path of [...nodeBindPaths(n), n.alt, n.param, n.src]) {
|
|
6282
6303
|
if (path && !path.startsWith('$'))
|
|
6283
6304
|
scopes.add(path.split('.')[0]);
|
|
6284
6305
|
}
|
|
@@ -6940,6 +6961,8 @@ const LINK_SLOTS = {
|
|
|
6940
6961
|
Link: { url: 'url' },
|
|
6941
6962
|
LinkedContainer: { url: 'url' },
|
|
6942
6963
|
ButtonBlock: { url: 'href', fixed: { tag: 'a' } },
|
|
6964
|
+
// A Card v2 links as a whole through its TITLE (the stretched link): the Heading carries the link.
|
|
6965
|
+
Heading: { url: 'url' },
|
|
6943
6966
|
};
|
|
6944
6967
|
/** What a linked box becomes when its link has nowhere to go: the same box, unlinked. */
|
|
6945
6968
|
const UNLINKED_TYPE = { LinkedContainer: 'Container' };
|
|
@@ -7187,6 +7210,8 @@ function composeChildren(pn, id, repeater, ctx) {
|
|
|
7187
7210
|
function composeNode(pn, id, repeater, ctx) {
|
|
7188
7211
|
if (pn.optional && ctx.section?.without?.includes(pn.optional))
|
|
7189
7212
|
return null;
|
|
7213
|
+
if (pn.recipe)
|
|
7214
|
+
return composeRecipe(pn, id, repeater, ctx);
|
|
7190
7215
|
const words = chooseText(pn, ctx);
|
|
7191
7216
|
const fate = danglingFate(pn, ctx);
|
|
7192
7217
|
if (fate === DanglingFate.Remove) {
|
|
@@ -7308,6 +7333,61 @@ function composeNode(pn, id, repeater, ctx) {
|
|
|
7308
7333
|
composeForm(node, pn, id, ctx);
|
|
7309
7334
|
return node;
|
|
7310
7335
|
}
|
|
7336
|
+
/** A Card v2 `binds` key → the part it binds and that part's bound prop. */
|
|
7337
|
+
const CARD_BINDS = {
|
|
7338
|
+
[CardBindTarget.Image]: { role: CardRole.Media, prop: 'src' },
|
|
7339
|
+
[CardBindTarget.Eyebrow]: { role: CardRole.Eyebrow, prop: 'content' },
|
|
7340
|
+
[CardBindTarget.Title]: { role: CardRole.Title, prop: 'content' },
|
|
7341
|
+
[CardBindTarget.Text]: { role: CardRole.Text, prop: 'content' },
|
|
7342
|
+
};
|
|
7343
|
+
/**
|
|
7344
|
+
* A `recipe` node: the composite-core recipe, stamped whole with THIS composer's node factory — the same
|
|
7345
|
+
* recipe the builder's palette stamps with its own — then bound part by part, and linked as a whole card
|
|
7346
|
+
* through its title (`href` + `param`, the stretched link). Ids derive from the recipe's keys.
|
|
7347
|
+
*/
|
|
7348
|
+
function composeRecipe(pn, id, repeater, ctx) {
|
|
7349
|
+
if (pn.recipe !== PatternRecipe.Card)
|
|
7350
|
+
throw new ComposeError(`${id}: no recipe "${pn.recipe}" in composite-core`);
|
|
7351
|
+
const layout = (pn.layout ?? CardLayout.Top);
|
|
7352
|
+
if (!CARD_LAYOUTS.includes(layout))
|
|
7353
|
+
throw new ComposeError(`${id}: a card has no layout "${pn.layout}"`);
|
|
7354
|
+
for (const part of Object.keys(pn.parts ?? {})) {
|
|
7355
|
+
if (!CARD_PARTS.includes(part))
|
|
7356
|
+
throw new ComposeError(`${id}: a card has no part "${part}"`);
|
|
7357
|
+
}
|
|
7358
|
+
const factory = (spec) => create(spec.key === CardRole.Card ? id : `${id}-${spec.key}`, spec.type, { ...(spec.props ?? {}) }, spec.elementStyle ?? null);
|
|
7359
|
+
const card = buildCardRecipe(factory, { layout, parts: pn.parts });
|
|
7360
|
+
for (const [key, path] of Object.entries(pn.binds ?? {})) {
|
|
7361
|
+
const target = CARD_BINDS[key];
|
|
7362
|
+
if (!target)
|
|
7363
|
+
throw new ComposeError(`${id}: a card cannot bind "${key}"`);
|
|
7364
|
+
const part = findByRole(card, target.role);
|
|
7365
|
+
if (!part)
|
|
7366
|
+
throw new ComposeError(`${id}: "${key}" binds a part the card leaves out`);
|
|
7367
|
+
const node = target.role === CardRole.Media ? part.children?.find(c => c.type === IMAGE) : part;
|
|
7368
|
+
if (!node)
|
|
7369
|
+
throw new ComposeError(`${id}: the card's media holds no image`);
|
|
7370
|
+
addBinding(node, { prop: target.prop, ...resolveScoped(path, repeater, ctx, id) });
|
|
7371
|
+
if (node.type === IMAGE)
|
|
7372
|
+
addBinding(node, { prop: 'alt', ...altBinding({ ...pn, t: IMAGE, bind: path, alt: undefined }, repeater, ctx, id) });
|
|
7373
|
+
}
|
|
7374
|
+
const fate = danglingFate({ ...pn, t: 'Heading' }, ctx);
|
|
7375
|
+
const title = findByRole(card, CardRole.Title);
|
|
7376
|
+
if (pn.href && !fate)
|
|
7377
|
+
writePageLink(title, pn.href);
|
|
7378
|
+
else if (fate) {
|
|
7379
|
+
if (fate === DanglingFate.Email)
|
|
7380
|
+
writeExternalLink(title, `${MAILTO}${ctx.email}`);
|
|
7381
|
+
reportDangling(fate === DanglingFate.Remove ? DanglingFate.Unlink : fate, pn, id, undefined, ctx);
|
|
7382
|
+
}
|
|
7383
|
+
if (pn.param && !fate) {
|
|
7384
|
+
const names = pn.href ? routeParams(pn.href) : [];
|
|
7385
|
+
if (names.length !== 1)
|
|
7386
|
+
throw new ComposeError(`${id}: "param" needs an href with one :param`);
|
|
7387
|
+
addBinding(title, { prop: `routeParam:${names[0]}`, ...resolveScoped(pn.param, repeater, ctx, id) });
|
|
7388
|
+
}
|
|
7389
|
+
return card;
|
|
7390
|
+
}
|
|
7311
7391
|
function composePattern(pattern, id, ctx) {
|
|
7312
7392
|
if (pattern.node.each)
|
|
7313
7393
|
throw new ComposeError(`${id}: a pattern's root cannot be stamped per page`);
|
|
@@ -7424,5 +7504,5 @@ function composeSite(plan, context) {
|
|
|
7424
7504
|
* Generated bundle index. Do not edit.
|
|
7425
7505
|
*/
|
|
7426
7506
|
|
|
7427
|
-
export { BASELINE_ROLES, BaselineRole, BindScope, ComposeError, ComposeIssueCode, DANGLING_LINK_CODES, FACT_KEYS, GlobalSlot, NEUTRAL_STYLE_PROPS, NODE_BASELINES, PatternDirective, PatternGlobalPosition, PatternPlaceholder, PlaceholderKind, PlanDataSourceMode, PlanDataSourceType, RelativeOp, SAMPLE_IMAGE_REF, SITE_FACT_LABELS, SITE_PATTERNS, SITE_PLAN_VERSION, SITE_TEMPLATES, SPEC_SITE_FACTS, SPEC_SITE_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_TEMPLATES, STUDIO_TEMPLATE, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SiteTemplateError, SiteTemplateId, altSourceScopes, assertStyleSlots, assertValidSitePlan, composeSite, createSerializedNode, nextSourceOf, parseSampleImageRef, patternById, patternNeedsBinding, patternNodes, patternOptionalParts, patternScopes, patternSlots, planFromTemplate, releasedLayoutDefaults, requiredShapeKeys, routeParams, sampleImageRef, setStyleProps, shapeKeys, validateSitePlan, walkSerialized };
|
|
7507
|
+
export { BASELINE_ROLES, BaselineRole, BindScope, CardBindTarget, ComposeError, ComposeIssueCode, DANGLING_LINK_CODES, FACT_KEYS, GlobalSlot, NEUTRAL_STYLE_PROPS, NODE_BASELINES, PatternDirective, PatternGlobalPosition, PatternPlaceholder, PatternRecipe, PlaceholderKind, PlanDataSourceMode, PlanDataSourceType, RelativeOp, SAMPLE_IMAGE_REF, SITE_FACT_LABELS, SITE_PATTERNS, SITE_PLAN_VERSION, SITE_TEMPLATES, SPEC_SITE_FACTS, SPEC_SITE_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_TEMPLATES, STUDIO_TEMPLATE, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SiteTemplateError, SiteTemplateId, altSourceScopes, assertStyleSlots, assertValidSitePlan, composeSite, createSerializedNode, nextSourceOf, nodeBindPaths, parseSampleImageRef, patternById, patternNeedsBinding, patternNodes, patternOptionalParts, patternScopes, patternSlots, planFromTemplate, releasedLayoutDefaults, requiredShapeKeys, routeParams, sampleImageRef, setStyleProps, shapeKeys, validateSitePlan, walkSerialized };
|
|
7428
7508
|
//# sourceMappingURL=vectoriox-iox-ui-generation-core.mjs.map
|