@vectoriox/iox-ui 5.35.0 → 5.37.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.
Files changed (36) hide show
  1. package/actions-core/index.d.ts +12 -3
  2. package/composite-core/index.d.ts +500 -2
  3. package/design-core/index.d.ts +417 -0
  4. package/fesm2022/vectoriox-iox-ui-actions-core.mjs +26 -2
  5. package/fesm2022/vectoriox-iox-ui-actions-core.mjs.map +1 -1
  6. package/fesm2022/vectoriox-iox-ui-composite-core.mjs +1205 -2
  7. package/fesm2022/vectoriox-iox-ui-composite-core.mjs.map +1 -1
  8. package/fesm2022/vectoriox-iox-ui-design-core.mjs +489 -0
  9. package/fesm2022/vectoriox-iox-ui-design-core.mjs.map +1 -1
  10. package/fesm2022/vectoriox-iox-ui-forms-core.mjs +2 -1
  11. package/fesm2022/vectoriox-iox-ui-forms-core.mjs.map +1 -1
  12. package/fesm2022/vectoriox-iox-ui-generation-core.mjs +113 -8
  13. package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
  14. package/fesm2022/vectoriox-iox-ui.mjs +94 -19
  15. package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
  16. package/generation-core/index.d.ts +53 -3
  17. package/index.d.ts +60 -10
  18. package/package.json +1 -1
  19. package/src/actions-core/action.model.ts +4 -2
  20. package/src/actions-core/element-actions.ts +29 -1
  21. package/src/composite-core/accordion-runtime.ts +443 -0
  22. package/src/composite-core/accordion.ts +694 -0
  23. package/src/composite-core/composite-kinds.ts +110 -0
  24. package/src/composite-core/composite-node.ts +16 -0
  25. package/src/composite-core/disclosure.ts +125 -0
  26. package/src/composite-core/public-api.ts +7 -1
  27. package/src/composite-core/structure.ts +14 -0
  28. package/src/design-core/flavor-spec.generated.ts +489 -0
  29. package/src/forms-core/nesting.ts +2 -1
  30. package/src/generation-core/compose-site.ts +49 -1
  31. package/src/generation-core/node-baselines.generated.ts +6 -2
  32. package/src/generation-core/patterns.ts +10 -0
  33. package/src/generation-core/serialized-node.ts +4 -0
  34. package/src/generation-core/site-spec.generated.ts +46 -1
  35. package/src/generation-core/validate-site-plan.ts +5 -4
  36. package/styles/iox-design.css +30 -0
@@ -1,6 +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
+ import { CardRole, CardLayout, CARD_LAYOUTS, CARD_PARTS, buildCardRecipe, findByRole, AccordionRole, buildAccordionRecipe, ACCORDION_WORDS, accordionItems, accordionQuestionOf, accordionAnswerOf, ACCORDION_BIND_PROP, pickAccordionAutoBinds, ACCORDION_CONTENT_LIMIT } from '@vectoriox/iox-ui/composite-core';
4
4
 
5
5
  // GENERATED from iox-ai-guidance flavor-spec.v1.json — do not edit; re-run scripts/gen-flavor-spec.mjs
6
6
  // (npm run gen:flavor-spec). The JSON is itself generated by iox-ai-guidance
@@ -93,7 +93,7 @@ const SPEC_SITE_PLAN_SHAPE = {
93
93
  "section": {
94
94
  "pattern": "string — a non-global pattern id",
95
95
  "slots?": "{ [slot]: string } — the pattern's declared slots",
96
- "binding?": "string — the list source a pattern's $binding repeater iterates (exactly when it has one)",
96
+ "binding?": "string — the list source a pattern's $binding repeater iterates (exactly when it has one); a $binding? pattern (faq.accordion) MAY take one — then its items come from that content",
97
97
  "without?": "string[] — the pattern's optional parts to leave out"
98
98
  },
99
99
  "globals": {
@@ -935,6 +935,51 @@ const SPEC_SITE_PATTERNS = {
935
935
  }
936
936
  ]
937
937
  }
938
+ },
939
+ "faq.accordion": {
940
+ "family": "faq",
941
+ "label": "FAQ — questions that open",
942
+ "node": {
943
+ "t": "Section",
944
+ "es": "section",
945
+ "c": [
946
+ {
947
+ "t": "Container",
948
+ "es": "box",
949
+ "lay": {
950
+ "display": "flex",
951
+ "flexDirection": "column",
952
+ "gap": "14px",
953
+ "maxWidth": "860px",
954
+ "width": "100%",
955
+ "margin": "0px auto 0px auto"
956
+ },
957
+ "c": [
958
+ {
959
+ "t": "Text",
960
+ "es": "eyebrow",
961
+ "slot": "eyebrow",
962
+ "ph": "copy",
963
+ "text": "FAQ"
964
+ },
965
+ {
966
+ "t": "Heading",
967
+ "es": "h2",
968
+ "level": "h2",
969
+ "slot": "title",
970
+ "ph": "copy",
971
+ "text": "Questions people ask"
972
+ },
973
+ {
974
+ "t": "Container",
975
+ "recipe": "accordion",
976
+ "src": "$binding?",
977
+ "ph": "copy"
978
+ }
979
+ ]
980
+ }
981
+ ]
982
+ }
938
983
  }
939
984
  };
940
985
  const SPEC_SITE_TEMPLATES = {
@@ -1818,7 +1863,9 @@ const NODE_BASELINES = {
1818
1863
  },
1819
1864
  "traits": [
1820
1865
  "htmlTag",
1821
- "colorScheme"
1866
+ "colorScheme",
1867
+ "multiple",
1868
+ "defaultOn"
1822
1869
  ],
1823
1870
  "styleTraits": [
1824
1871
  "position",
@@ -4049,7 +4096,9 @@ const NODE_BASELINES = {
4049
4096
  },
4050
4097
  "traits": [
4051
4098
  "source",
4052
- "limit"
4099
+ "limit",
4100
+ "multiple",
4101
+ "defaultOn"
4053
4102
  ],
4054
4103
  "styleTraits": [
4055
4104
  "position",
@@ -6197,6 +6246,9 @@ var GlobalSlot;
6197
6246
  var PatternRecipe;
6198
6247
  (function (PatternRecipe) {
6199
6248
  PatternRecipe["Card"] = "card";
6249
+ /** CC2: the Accordion — Manual (three placeholder items), or From content when the section names a list
6250
+ * `binding` (`src: '$binding?'`): one template item bound to the type's question / answer fields. */
6251
+ PatternRecipe["Accordion"] = "accordion";
6200
6252
  })(PatternRecipe || (PatternRecipe = {}));
6201
6253
  /** A recipe node's `binds` keys → the part each binds (Card v2). */
6202
6254
  var CardBindTarget;
@@ -6227,6 +6279,8 @@ var PatternDirective;
6227
6279
  (function (PatternDirective) {
6228
6280
  /** A Repeater's source: the section's `binding`. */
6229
6281
  PatternDirective["Binding"] = "$binding";
6282
+ /** The section MAY name a list `binding` (faq.accordion): with one, the recipe's items come from it. */
6283
+ PatternDirective["OptionalBinding"] = "$binding?";
6230
6284
  /** `each`: one plain node per page of the plan that is in the navigation (`inNav`), in plan order —
6231
6285
  * words and routes written in, editable on the canvas (W1.1). */
6232
6286
  PatternDirective["NavPages"] = "$navPages";
@@ -6271,6 +6325,10 @@ function patternOptionalParts(pattern) {
6271
6325
  function patternNeedsBinding(pattern) {
6272
6326
  return patternNodes(pattern).some(n => n.src === PatternDirective.Binding);
6273
6327
  }
6328
+ /** True when the pattern may take a section `binding` — it needs one, or names `$binding?` (CC2). */
6329
+ function patternTakesBinding(pattern) {
6330
+ return patternNeedsBinding(pattern) || patternNodes(pattern).some(n => n.src === PatternDirective.OptionalBinding);
6331
+ }
6274
6332
  const IMAGE_TYPE = 'Image';
6275
6333
  /** The scopes whose ITEM a pattern's bound Images take their alt text from (an Image that names no `alt`
6276
6334
  * of its own): `item` (the row of a `$binding` Repeater — the section's list), `route` or `next`. Each
@@ -6803,9 +6861,11 @@ function validatePages(c, list, types, sources) {
6803
6861
  });
6804
6862
  }
6805
6863
  const binding = c.string(s, 'binding', sp, false);
6806
- if (patternNeedsBinding(pattern)) {
6807
- if (!binding)
6808
- c.add(SitePlanIssueCode.Binding, `${sp}.binding`, `"${patternId}" repeats the section's binding — name a list source`);
6864
+ if (patternTakesBinding(pattern)) {
6865
+ if (!binding) {
6866
+ if (patternNeedsBinding(pattern))
6867
+ c.add(SitePlanIssueCode.Binding, `${sp}.binding`, `"${patternId}" repeats the section's binding — name a list source`);
6868
+ }
6809
6869
  else {
6810
6870
  const src = sources.get(binding);
6811
6871
  if (!src)
@@ -7859,6 +7919,8 @@ const CARD_BINDS = {
7859
7919
  * through its title (`href` + `param`, the stretched link). Ids derive from the recipe's keys.
7860
7920
  */
7861
7921
  function composeRecipe(pn, id, repeater, ctx) {
7922
+ if (pn.recipe === PatternRecipe.Accordion)
7923
+ return composeAccordion(pn, id, ctx);
7862
7924
  if (pn.recipe !== PatternRecipe.Card)
7863
7925
  throw new ComposeError(`${id}: no recipe "${pn.recipe}" in composite-core`);
7864
7926
  const layout = (pn.layout ?? CardLayout.Top);
@@ -7901,6 +7963,49 @@ function composeRecipe(pn, id, repeater, ctx) {
7901
7963
  }
7902
7964
  return card;
7903
7965
  }
7966
+ const REPEATER = 'Repeater';
7967
+ /**
7968
+ * An Accordion (CC2) — the composite-core recipe stamped with this composer's factory. Manual (no section
7969
+ * binding): three items whose questions and answers are placeholders the studio rewrites (`ph: 'copy'`), never
7970
+ * invented answers. From content (the section names a list `binding` — R3's AI path): the root is a Repeater
7971
+ * over that list holding ONE template item, its question and answer bound to the content type's first
7972
+ * short-text and first long-text fields (`pickAccordionAutoBinds`, the builder switch's rule), limit 20.
7973
+ */
7974
+ function composeAccordion(pn, id, ctx) {
7975
+ const binding = pn.src === PatternDirective.OptionalBinding || pn.src === PatternDirective.Binding ? ctx.section?.binding ?? null : null;
7976
+ if (pn.src === PatternDirective.Binding && !binding)
7977
+ throw new ComposeError(`${id}: "$binding" with no section binding`);
7978
+ const factory = (spec) => {
7979
+ const isRoot = spec.key === AccordionRole.Accordion;
7980
+ const type = isRoot && binding ? REPEATER : spec.type;
7981
+ return create(isRoot ? id : `${id}-${spec.key}`, type, { ...(spec.props ?? {}) }, spec.elementStyle ?? null);
7982
+ };
7983
+ const root = buildAccordionRecipe(factory, binding ? { items: ACCORDION_WORDS.slice(0, 1) } : {});
7984
+ if (!binding) {
7985
+ if (pn.ph === PatternPlaceholder.Copy) {
7986
+ for (const item of accordionItems(root)) {
7987
+ for (const part of [accordionQuestionOf(item), accordionAnswerOf(item)]) {
7988
+ if (part)
7989
+ ctx.placeholders.push({ nodeId: part.id, owner: ctx.owner, kind: PlaceholderKind.Copy, text: String(part.props?.[ACCORDION_BIND_PROP] ?? '') });
7990
+ }
7991
+ }
7992
+ }
7993
+ return root;
7994
+ }
7995
+ const source = ctx.plan.dataSources.find(d => d.alias === binding);
7996
+ const type = source && 'contentType' in source ? ctx.plan.contentTypes.find(t => t.name === source.contentType) : undefined;
7997
+ const picks = pickAccordionAutoBinds((type?.fields ?? []).map(f => ({ name: f.name, type: f.type, controller: f.controller })));
7998
+ if (!picks.question || !picks.answer) {
7999
+ throw new ComposeError(`${id}: "${binding}" has no short-text field for the question and long-text field for the answer`);
8000
+ }
8001
+ addBinding(root, { prop: 'source', source: binding, path: '' });
8002
+ setProp(root, 'limit', ACCORDION_CONTENT_LIMIT);
8003
+ const [template] = accordionItems(root);
8004
+ delete template.itemKey;
8005
+ addBinding(accordionQuestionOf(template), { prop: ACCORDION_BIND_PROP, source: binding, path: picks.question });
8006
+ addBinding(accordionAnswerOf(template), { prop: ACCORDION_BIND_PROP, source: binding, path: picks.answer });
8007
+ return root;
8008
+ }
7904
8009
  function composePattern(pattern, id, ctx) {
7905
8010
  if (pattern.node.each)
7906
8011
  throw new ComposeError(`${id}: a pattern's root cannot be stamped per page`);
@@ -8024,5 +8129,5 @@ function composeSite(plan, context) {
8024
8129
  * Generated bundle index. Do not edit.
8025
8130
  */
8026
8131
 
8027
- export { BAR_ITEMS_MAX, BAR_ITEMS_MIN, BASELINE_ROLES, BaselineRole, BindScope, CardBindTarget, ComposeError, ComposeIssueCode, DANGLING_LINK_CODES, DEFAULT_PHONE_MENU_BREAKPOINT, FACT_KEYS, GlobalSlot, NAV_PART_LABELS, NAV_SHAPE_COPY, NEUTRAL_STYLE_PROPS, NODE_BASELINES, NavRole, NavShape, NavShapeError, PatternDirective, PatternGlobalPosition, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, 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, addBarItem, altSourceScopes, assertStyleSlots, assertValidSitePlan, barIconForRoute, composeSite, createSerializedNode, findNavRoot, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, parseSampleImageRef, patternById, patternNeedsBinding, patternNodes, patternOptionalParts, patternScopes, patternSlots, planFromTemplate, planNavShape, releasedLayoutDefaults, requiredShapeKeys, routeParams, sampleImageRef, setStyleProps, shapeKeys, validateSitePlan, walkSerialized };
8132
+ export { BAR_ITEMS_MAX, BAR_ITEMS_MIN, BASELINE_ROLES, BaselineRole, BindScope, CardBindTarget, ComposeError, ComposeIssueCode, DANGLING_LINK_CODES, DEFAULT_PHONE_MENU_BREAKPOINT, FACT_KEYS, GlobalSlot, NAV_PART_LABELS, NAV_SHAPE_COPY, NEUTRAL_STYLE_PROPS, NODE_BASELINES, NavRole, NavShape, NavShapeError, PatternDirective, PatternGlobalPosition, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, 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, addBarItem, altSourceScopes, assertStyleSlots, assertValidSitePlan, barIconForRoute, composeSite, createSerializedNode, findNavRoot, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, parseSampleImageRef, patternById, patternNeedsBinding, patternNodes, patternOptionalParts, patternScopes, patternSlots, patternTakesBinding, planFromTemplate, planNavShape, releasedLayoutDefaults, requiredShapeKeys, routeParams, sampleImageRef, setStyleProps, shapeKeys, validateSitePlan, walkSerialized };
8028
8133
  //# sourceMappingURL=vectoriox-iox-ui-generation-core.mjs.map