@vectoriox/iox-ui 5.68.0 → 5.70.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 +9 -1
- package/fesm2022/vectoriox-iox-ui-composite-core.mjs +13 -1
- package/fesm2022/vectoriox-iox-ui-composite-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs +39 -7
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-scene-core.mjs +471 -0
- package/fesm2022/vectoriox-iox-ui-scene-core.mjs.map +1 -0
- package/fesm2022/vectoriox-iox-ui.mjs +2 -2
- package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
- package/generation-core/index.d.ts +3 -0
- package/package.json +5 -1
- package/scene-core/index.d.ts +193 -0
- package/scene-core/package.json +3 -0
- package/src/composite-core/composite-kinds.ts +9 -0
- package/src/composite-core/structure.ts +4 -1
- package/src/generation-core/compose-site.ts +2 -1
- package/src/generation-core/plan-wire.ts +14 -5
- package/src/generation-core/plan-words.ts +3 -1
- package/src/generation-core/site-plan.model.ts +2 -0
- package/src/generation-core/site-spec.generated.ts +1 -0
- package/src/generation-core/validate-site-plan.ts +11 -0
- package/src/scene-core/public-api.ts +9 -0
- package/src/scene-core/scene-recipe.ts +100 -0
- package/src/scene-core/scene.ts +232 -0
- package/src/scene-core/scroll-driver.ts +220 -0
- package/styles/iox-design.css +7 -0
|
@@ -75,6 +75,7 @@ const SPEC_SITE_PLAN_SHAPE = {
|
|
|
75
75
|
"count": "integer ≥ 0",
|
|
76
76
|
"sample": "boolean — items are flagged isSample",
|
|
77
77
|
"isPublished": "boolean",
|
|
78
|
+
"perItem?": "per field, one string per sample: real content that wins over the template",
|
|
78
79
|
"[field]?": "the field's value — strings are templates: {n} = the item's 1-based number, {sampleImage:n} / {sampleImage:n+k} = a bundled sample image"
|
|
79
80
|
},
|
|
80
81
|
"cmsDataSource": {
|
|
@@ -10887,6 +10888,7 @@ const ROLE_KEYS$1 = shapeKeys(SHAPE['roles']);
|
|
|
10887
10888
|
const PAGE_SEO_KEYS = shapeKeys(SHAPE['pageSeo']);
|
|
10888
10889
|
const ARRAY_TYPE = 'array';
|
|
10889
10890
|
const FIELD_KEYS = shapeKeys(SHAPE['field']);
|
|
10891
|
+
const SLUG_FIELD = 'slug';
|
|
10890
10892
|
const SEED_FIXED_KEYS = shapeKeys(SHAPE['seed']);
|
|
10891
10893
|
const CMS_SOURCE_KEYS = shapeKeys(SHAPE['cmsDataSource']);
|
|
10892
10894
|
const RELATIVE_SOURCE_KEYS = shapeKeys(SHAPE['relativeDataSource']);
|
|
@@ -11025,6 +11027,21 @@ function validateContentTypes(c, list) {
|
|
|
11025
11027
|
for (const key of ['sample', 'isPublished'])
|
|
11026
11028
|
if (typeof seed[key] !== 'boolean')
|
|
11027
11029
|
c.add(SitePlanIssueCode.Shape, `${path}.seed.${key}`, 'must be a boolean');
|
|
11030
|
+
const perItem = seed['perItem'];
|
|
11031
|
+
if (perItem !== undefined) {
|
|
11032
|
+
if (!isPlainObject(perItem))
|
|
11033
|
+
c.add(SitePlanIssueCode.Shape, `${path}.seed.perItem`, 'must be an object');
|
|
11034
|
+
else
|
|
11035
|
+
for (const [field, list] of Object.entries(perItem)) {
|
|
11036
|
+
const at = `${path}.seed.perItem.${field}`;
|
|
11037
|
+
if (!fieldSet.has(field))
|
|
11038
|
+
c.add(SitePlanIssueCode.UnknownField, at, `"${field}" is not a field of ${name}`);
|
|
11039
|
+
else if (!Array.isArray(list) || list.length !== seed['count'] || list.some(v => typeof v !== 'string'))
|
|
11040
|
+
c.add(SitePlanIssueCode.Shape, at, `must be ${String(seed['count'])} strings, one per sample`);
|
|
11041
|
+
else if (field === SLUG_FIELD && new Set(list).size !== list.length)
|
|
11042
|
+
c.add(SitePlanIssueCode.Shape, at, 'each sample needs its own slug');
|
|
11043
|
+
}
|
|
11044
|
+
}
|
|
11028
11045
|
for (const key of Object.keys(seed)) {
|
|
11029
11046
|
if (!SEED_FIXED_KEYS.includes(key) && !fieldSet.has(key))
|
|
11030
11047
|
c.add(SitePlanIssueCode.UnknownField, `${path}.seed.${key}`, `"${key}" is not a field of ${name}`);
|
|
@@ -13061,7 +13078,8 @@ function composeItems(type, fillEmpty) {
|
|
|
13061
13078
|
for (const field of type.fields) {
|
|
13062
13079
|
const given = seed[field.name];
|
|
13063
13080
|
const empty = !(field.name in seed) || given === '' || (Array.isArray(given) && !given.length);
|
|
13064
|
-
const
|
|
13081
|
+
const own = seed.perItem?.[field.name]?.[n - 1];
|
|
13082
|
+
const value = own || (empty && fillEmpty ? defaultSeed(type, field) : given);
|
|
13065
13083
|
if (value !== undefined)
|
|
13066
13084
|
item[field.name] = expandSeedValue(value, n);
|
|
13067
13085
|
}
|
|
@@ -13669,6 +13687,7 @@ const WIRE_KEYS = {
|
|
|
13669
13687
|
seedValue: {
|
|
13670
13688
|
field: { refs: ['seed.[field]'], text: 'string — a field of the type' },
|
|
13671
13689
|
value: { refs: ['seed.[field]'], text: `string | string[] — ${describeShapeKey(PLAN_SHAPE['seed'], '[field]')} (a list for an array field)` },
|
|
13690
|
+
each: { refs: ['seed.perItem'], text: 'string[] — one value per sample, in order, when each sample has its own content', none: '[]' },
|
|
13672
13691
|
},
|
|
13673
13692
|
dataSource: {
|
|
13674
13693
|
alias: { refs: ['cmsDataSource.alias', 'relativeDataSource.alias'] },
|
|
@@ -13798,7 +13817,7 @@ const shapedAs = (entry, options, properties) => {
|
|
|
13798
13817
|
return jsonShapedObject(wireEntryShape(entry, options), Object.fromEntries(Object.entries(properties).filter(([k]) => !left.includes(k))), `wire ${entry}`);
|
|
13799
13818
|
};
|
|
13800
13819
|
function wireContentTypeJsonSchema(options = {}) {
|
|
13801
|
-
const value = shaped(PlanWireEntry.SeedValue, { field: jsonText(), value: jsonAnyOf([jsonText(), jsonListOf(jsonText())]) });
|
|
13820
|
+
const value = shaped(PlanWireEntry.SeedValue, { field: jsonText(), value: jsonAnyOf([jsonText(), jsonListOf(jsonText())]), each: jsonListOf(jsonText()) });
|
|
13802
13821
|
return shapedAs(PlanWireEntry.ContentType, options, {
|
|
13803
13822
|
name: jsonText(),
|
|
13804
13823
|
label: jsonText(),
|
|
@@ -13910,8 +13929,18 @@ function expandWireContentType(wire, options = {}) {
|
|
|
13910
13929
|
const { values, ...fixed } = seed;
|
|
13911
13930
|
if (fixed['count'] === 0 && emptyList(values))
|
|
13912
13931
|
return out;
|
|
13913
|
-
const
|
|
13914
|
-
|
|
13932
|
+
const perItem = {};
|
|
13933
|
+
const plain = Array.isArray(values) ? values.map(row => {
|
|
13934
|
+
if (!isPlainObject(row))
|
|
13935
|
+
return row;
|
|
13936
|
+
const { each, ...rest } = row;
|
|
13937
|
+
if (Array.isArray(each) && each.length)
|
|
13938
|
+
perItem[String(rest['field'])] = each;
|
|
13939
|
+
return rest;
|
|
13940
|
+
}) : values;
|
|
13941
|
+
const map = listToMap(plain ?? [], 'field', 'value');
|
|
13942
|
+
const items = Object.keys(perItem).length ? { perItem } : {};
|
|
13943
|
+
return { ...out, seed: isPlainObject(map) ? { ...fixed, ...items, ...map } : { ...fixed, values } };
|
|
13915
13944
|
}
|
|
13916
13945
|
function expandWireDataSource(wire) {
|
|
13917
13946
|
if (!isPlainObject(wire))
|
|
@@ -13994,10 +14023,10 @@ function fieldToWire(field) {
|
|
|
13994
14023
|
function contentTypeToWire(type, options = {}) {
|
|
13995
14024
|
const played = type.roles;
|
|
13996
14025
|
const roles = ROLE_KEYS.filter(role => played[role]).map(role => ({ role, field: played[role] }));
|
|
13997
|
-
const { count = 0, sample = false, isPublished = false, ...values } = type.seed ?? {};
|
|
14026
|
+
const { count = 0, sample = false, isPublished = false, perItem = {}, ...values } = type.seed ?? {};
|
|
13998
14027
|
return {
|
|
13999
14028
|
name: type.name, label: type.label, roles, ...(options.children === false ? {} : { fields: type.fields.map(fieldToWire) }),
|
|
14000
|
-
seed: { count, sample, isPublished, values: mapToList(values, 'field', 'value') },
|
|
14029
|
+
seed: { count, sample, isPublished, values: mapToList(values, 'field', 'value').map(row => ({ ...row, each: perItem[String(row['field'])] ?? [] })) },
|
|
14001
14030
|
};
|
|
14002
14031
|
}
|
|
14003
14032
|
function dataSourceToWire(source) {
|
|
@@ -14949,7 +14978,10 @@ function writtenTexts(plan) {
|
|
|
14949
14978
|
});
|
|
14950
14979
|
plan.contentTypes?.forEach((type, t) => {
|
|
14951
14980
|
add(`contentTypes[${t}].label`, type.label);
|
|
14952
|
-
|
|
14981
|
+
const { perItem, ...seed } = type.seed ?? {};
|
|
14982
|
+
for (const [field, list] of Object.entries(perItem ?? {}))
|
|
14983
|
+
list.forEach((v, k) => add(`contentTypes[${t}].seed.perItem.${field}[${k}]`, v));
|
|
14984
|
+
for (const [field, value] of Object.entries(seed)) {
|
|
14953
14985
|
const values = Array.isArray(value) ? value : [value];
|
|
14954
14986
|
values.forEach((v, k) => add(`contentTypes[${t}].seed.${field}${Array.isArray(value) ? `[${k}]` : ''}`, v));
|
|
14955
14987
|
}
|