@vectoriox/iox-ui 5.34.0 → 5.36.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.
@@ -1,3 +1,4 @@
1
+ import { AccordionRole } from './accordion';
1
2
  import { CardPart, CardRole } from './card';
2
3
 
3
4
  /**
@@ -22,6 +23,12 @@ export const COMPOSITE_ROLE_SPECS: Readonly<Record<string, CompositeRoleSpec>> =
22
23
  [CardRole.Title]: { parent: CardRole.Content, locked: true },
23
24
  [CardRole.Text]: { parent: CardRole.Content, part: CardPart.Text },
24
25
  [CardRole.Actions]: { parent: CardRole.Content, part: CardPart.Actions },
26
+ // CC2 — an item always keeps its header and its panel; the icon is Behaviour ▸ Icon's.
27
+ [AccordionRole.Accordion]: { parent: null },
28
+ [AccordionRole.Item]: { parent: AccordionRole.Accordion },
29
+ [AccordionRole.Trigger]: { parent: AccordionRole.Item, locked: true },
30
+ [AccordionRole.Panel]: { parent: AccordionRole.Item, locked: true },
31
+ [AccordionRole.Icon]: { parent: AccordionRole.Trigger },
25
32
  };
26
33
 
27
34
  export enum StructureEdit {
@@ -974,6 +974,51 @@ export const SPEC_TIERS = {
974
974
  "type": "size",
975
975
  "default": "var(--iox-size-label)"
976
976
  },
977
+ {
978
+ "name": "accordion-gap",
979
+ "type": "spacing",
980
+ "default": "0px"
981
+ },
982
+ {
983
+ "name": "accordion-item-bg",
984
+ "type": "color",
985
+ "default": "var(--iox-section-bg)"
986
+ },
987
+ {
988
+ "name": "accordion-item-border",
989
+ "type": "color",
990
+ "default": "var(--iox-line)"
991
+ },
992
+ {
993
+ "name": "accordion-item-border-width",
994
+ "type": "size",
995
+ "default": "0px 0px var(--iox-border-width) 0px"
996
+ },
997
+ {
998
+ "name": "accordion-item-radius",
999
+ "type": "radius",
1000
+ "default": "0px"
1001
+ },
1002
+ {
1003
+ "name": "accordion-item-pad",
1004
+ "type": "spacing",
1005
+ "default": "0px"
1006
+ },
1007
+ {
1008
+ "name": "accordion-trigger-pad",
1009
+ "type": "spacing",
1010
+ "default": "20px 0px"
1011
+ },
1012
+ {
1013
+ "name": "accordion-trigger-hover-ink",
1014
+ "type": "color",
1015
+ "default": "var(--iox-accent-text)"
1016
+ },
1017
+ {
1018
+ "name": "accordion-panel-pad",
1019
+ "type": "spacing",
1020
+ "default": "0px 0px 20px 0px"
1021
+ },
977
1022
  {
978
1023
  "name": "heading-color",
979
1024
  "type": "color",
@@ -1839,6 +1884,55 @@ export const SPEC_ELEMENT_STYLES = [
1839
1884
  "boxShadow": "var(--iox-focus-ring)"
1840
1885
  }
1841
1886
  },
1887
+ {
1888
+ "id": "accordion-item",
1889
+ "label": "Accordion item",
1890
+ "group": "Layout",
1891
+ "appliesTo": [
1892
+ "Container"
1893
+ ],
1894
+ "base": {
1895
+ "color": "inherit",
1896
+ "backgroundColor": "var(--iox-accordion-item-bg)",
1897
+ "borderStyle": "solid",
1898
+ "borderWidth": "var(--iox-accordion-item-border-width)",
1899
+ "borderColor": "var(--iox-accordion-item-border)",
1900
+ "borderRadius": "var(--iox-accordion-item-radius)",
1901
+ "padding": "var(--iox-accordion-item-pad)"
1902
+ }
1903
+ },
1904
+ {
1905
+ "id": "accordion-trigger",
1906
+ "label": "Accordion header",
1907
+ "group": "Layout",
1908
+ "appliesTo": [
1909
+ "LinkedContainer"
1910
+ ],
1911
+ "base": {
1912
+ "color": "var(--iox-heading-color)",
1913
+ "padding": "var(--iox-accordion-trigger-pad)",
1914
+ "transitionDuration": "var(--iox-dur-fast)",
1915
+ "transitionTimingFunction": "var(--iox-ease-standard)"
1916
+ },
1917
+ "hover": {
1918
+ "color": "var(--iox-accordion-trigger-hover-ink)"
1919
+ },
1920
+ "focus": {
1921
+ "boxShadow": "var(--iox-focus-ring)"
1922
+ }
1923
+ },
1924
+ {
1925
+ "id": "accordion-panel",
1926
+ "label": "Accordion panel",
1927
+ "group": "Layout",
1928
+ "appliesTo": [
1929
+ "Container"
1930
+ ],
1931
+ "base": {
1932
+ "padding": "var(--iox-accordion-panel-pad)",
1933
+ "color": "var(--iox-text-muted)"
1934
+ }
1935
+ },
1842
1936
  {
1843
1937
  "id": "media",
1844
1938
  "label": "Image",
@@ -4006,6 +4100,69 @@ export const SPEC_FLAVOR_PACKS = [
4006
4100
  "group": "components",
4007
4101
  "value": "var(--iox-size-label)"
4008
4102
  },
4103
+ {
4104
+ "name": "accordion-gap",
4105
+ "tier": "component",
4106
+ "type": "spacing",
4107
+ "group": "components",
4108
+ "value": "0px"
4109
+ },
4110
+ {
4111
+ "name": "accordion-item-bg",
4112
+ "tier": "component",
4113
+ "type": "color",
4114
+ "group": "components",
4115
+ "value": "var(--iox-section-bg)"
4116
+ },
4117
+ {
4118
+ "name": "accordion-item-border",
4119
+ "tier": "component",
4120
+ "type": "color",
4121
+ "group": "components",
4122
+ "value": "var(--iox-line)"
4123
+ },
4124
+ {
4125
+ "name": "accordion-item-border-width",
4126
+ "tier": "component",
4127
+ "type": "size",
4128
+ "group": "components",
4129
+ "value": "0px 0px var(--iox-border-width) 0px"
4130
+ },
4131
+ {
4132
+ "name": "accordion-item-radius",
4133
+ "tier": "component",
4134
+ "type": "radius",
4135
+ "group": "components",
4136
+ "value": "0px"
4137
+ },
4138
+ {
4139
+ "name": "accordion-item-pad",
4140
+ "tier": "component",
4141
+ "type": "spacing",
4142
+ "group": "components",
4143
+ "value": "0px"
4144
+ },
4145
+ {
4146
+ "name": "accordion-trigger-pad",
4147
+ "tier": "component",
4148
+ "type": "spacing",
4149
+ "group": "components",
4150
+ "value": "20px 0px"
4151
+ },
4152
+ {
4153
+ "name": "accordion-trigger-hover-ink",
4154
+ "tier": "component",
4155
+ "type": "color",
4156
+ "group": "components",
4157
+ "value": "var(--iox-accent-text)"
4158
+ },
4159
+ {
4160
+ "name": "accordion-panel-pad",
4161
+ "tier": "component",
4162
+ "type": "spacing",
4163
+ "group": "components",
4164
+ "value": "0px 0px 20px 0px"
4165
+ },
4009
4166
  {
4010
4167
  "name": "heading-color",
4011
4168
  "tier": "component",
@@ -5564,6 +5721,69 @@ export const SPEC_FLAVOR_PACKS = [
5564
5721
  "group": "components",
5565
5722
  "value": "var(--iox-size-label)"
5566
5723
  },
5724
+ {
5725
+ "name": "accordion-gap",
5726
+ "tier": "component",
5727
+ "type": "spacing",
5728
+ "group": "components",
5729
+ "value": "0px"
5730
+ },
5731
+ {
5732
+ "name": "accordion-item-bg",
5733
+ "tier": "component",
5734
+ "type": "color",
5735
+ "group": "components",
5736
+ "value": "var(--iox-section-bg)"
5737
+ },
5738
+ {
5739
+ "name": "accordion-item-border",
5740
+ "tier": "component",
5741
+ "type": "color",
5742
+ "group": "components",
5743
+ "value": "var(--iox-line)"
5744
+ },
5745
+ {
5746
+ "name": "accordion-item-border-width",
5747
+ "tier": "component",
5748
+ "type": "size",
5749
+ "group": "components",
5750
+ "value": "0px 0px var(--iox-border-width) 0px"
5751
+ },
5752
+ {
5753
+ "name": "accordion-item-radius",
5754
+ "tier": "component",
5755
+ "type": "radius",
5756
+ "group": "components",
5757
+ "value": "0px"
5758
+ },
5759
+ {
5760
+ "name": "accordion-item-pad",
5761
+ "tier": "component",
5762
+ "type": "spacing",
5763
+ "group": "components",
5764
+ "value": "0px"
5765
+ },
5766
+ {
5767
+ "name": "accordion-trigger-pad",
5768
+ "tier": "component",
5769
+ "type": "spacing",
5770
+ "group": "components",
5771
+ "value": "20px 0px"
5772
+ },
5773
+ {
5774
+ "name": "accordion-trigger-hover-ink",
5775
+ "tier": "component",
5776
+ "type": "color",
5777
+ "group": "components",
5778
+ "value": "var(--iox-accent-text)"
5779
+ },
5780
+ {
5781
+ "name": "accordion-panel-pad",
5782
+ "tier": "component",
5783
+ "type": "spacing",
5784
+ "group": "components",
5785
+ "value": "0px 0px 20px 0px"
5786
+ },
5567
5787
  {
5568
5788
  "name": "heading-color",
5569
5789
  "tier": "component",
@@ -7116,6 +7336,69 @@ export const SPEC_FLAVOR_PACKS = [
7116
7336
  "group": "components",
7117
7337
  "value": "var(--iox-size-label)"
7118
7338
  },
7339
+ {
7340
+ "name": "accordion-gap",
7341
+ "tier": "component",
7342
+ "type": "spacing",
7343
+ "group": "components",
7344
+ "value": "0px"
7345
+ },
7346
+ {
7347
+ "name": "accordion-item-bg",
7348
+ "tier": "component",
7349
+ "type": "color",
7350
+ "group": "components",
7351
+ "value": "var(--iox-section-bg)"
7352
+ },
7353
+ {
7354
+ "name": "accordion-item-border",
7355
+ "tier": "component",
7356
+ "type": "color",
7357
+ "group": "components",
7358
+ "value": "var(--iox-line)"
7359
+ },
7360
+ {
7361
+ "name": "accordion-item-border-width",
7362
+ "tier": "component",
7363
+ "type": "size",
7364
+ "group": "components",
7365
+ "value": "0px 0px var(--iox-border-width) 0px"
7366
+ },
7367
+ {
7368
+ "name": "accordion-item-radius",
7369
+ "tier": "component",
7370
+ "type": "radius",
7371
+ "group": "components",
7372
+ "value": "0px"
7373
+ },
7374
+ {
7375
+ "name": "accordion-item-pad",
7376
+ "tier": "component",
7377
+ "type": "spacing",
7378
+ "group": "components",
7379
+ "value": "0px"
7380
+ },
7381
+ {
7382
+ "name": "accordion-trigger-pad",
7383
+ "tier": "component",
7384
+ "type": "spacing",
7385
+ "group": "components",
7386
+ "value": "20px 0px"
7387
+ },
7388
+ {
7389
+ "name": "accordion-trigger-hover-ink",
7390
+ "tier": "component",
7391
+ "type": "color",
7392
+ "group": "components",
7393
+ "value": "var(--iox-accent-text)"
7394
+ },
7395
+ {
7396
+ "name": "accordion-panel-pad",
7397
+ "tier": "component",
7398
+ "type": "spacing",
7399
+ "group": "components",
7400
+ "value": "0px 0px 20px 0px"
7401
+ },
7119
7402
  {
7120
7403
  "name": "heading-color",
7121
7404
  "tier": "component",
@@ -8703,6 +8986,75 @@ export const SPEC_FLAVOR_PACKS = [
8703
8986
  "group": "components",
8704
8987
  "value": "var(--iox-size-label)"
8705
8988
  },
8989
+ {
8990
+ "name": "accordion-gap",
8991
+ "tier": "component",
8992
+ "type": "spacing",
8993
+ "group": "components",
8994
+ "value": "12px",
8995
+ "overridden": true
8996
+ },
8997
+ {
8998
+ "name": "accordion-item-bg",
8999
+ "tier": "component",
9000
+ "type": "color",
9001
+ "group": "components",
9002
+ "value": "var(--iox-surface-glass)",
9003
+ "overridden": true
9004
+ },
9005
+ {
9006
+ "name": "accordion-item-border",
9007
+ "tier": "component",
9008
+ "type": "color",
9009
+ "group": "components",
9010
+ "value": "var(--iox-glass-border)",
9011
+ "overridden": true
9012
+ },
9013
+ {
9014
+ "name": "accordion-item-border-width",
9015
+ "tier": "component",
9016
+ "type": "size",
9017
+ "group": "components",
9018
+ "value": "var(--iox-border-width)",
9019
+ "overridden": true
9020
+ },
9021
+ {
9022
+ "name": "accordion-item-radius",
9023
+ "tier": "component",
9024
+ "type": "radius",
9025
+ "group": "components",
9026
+ "value": "var(--iox-radius-md)",
9027
+ "overridden": true
9028
+ },
9029
+ {
9030
+ "name": "accordion-item-pad",
9031
+ "tier": "component",
9032
+ "type": "spacing",
9033
+ "group": "components",
9034
+ "value": "0px var(--iox-space-pad)",
9035
+ "overridden": true
9036
+ },
9037
+ {
9038
+ "name": "accordion-trigger-pad",
9039
+ "tier": "component",
9040
+ "type": "spacing",
9041
+ "group": "components",
9042
+ "value": "20px 0px"
9043
+ },
9044
+ {
9045
+ "name": "accordion-trigger-hover-ink",
9046
+ "tier": "component",
9047
+ "type": "color",
9048
+ "group": "components",
9049
+ "value": "var(--iox-accent-text)"
9050
+ },
9051
+ {
9052
+ "name": "accordion-panel-pad",
9053
+ "tier": "component",
9054
+ "type": "spacing",
9055
+ "group": "components",
9056
+ "value": "0px 0px 20px 0px"
9057
+ },
8706
9058
  {
8707
9059
  "name": "heading-color",
8708
9060
  "tier": "component",
@@ -10253,6 +10605,74 @@ export const SPEC_FLAVOR_PACKS = [
10253
10605
  "group": "components",
10254
10606
  "value": "var(--iox-size-label)"
10255
10607
  },
10608
+ {
10609
+ "name": "accordion-gap",
10610
+ "tier": "component",
10611
+ "type": "spacing",
10612
+ "group": "components",
10613
+ "value": "12px",
10614
+ "overridden": true
10615
+ },
10616
+ {
10617
+ "name": "accordion-item-bg",
10618
+ "tier": "component",
10619
+ "type": "color",
10620
+ "group": "components",
10621
+ "value": "var(--iox-surface-2)",
10622
+ "overridden": true
10623
+ },
10624
+ {
10625
+ "name": "accordion-item-border",
10626
+ "tier": "component",
10627
+ "type": "color",
10628
+ "group": "components",
10629
+ "value": "var(--iox-line)"
10630
+ },
10631
+ {
10632
+ "name": "accordion-item-border-width",
10633
+ "tier": "component",
10634
+ "type": "size",
10635
+ "group": "components",
10636
+ "value": "0px",
10637
+ "overridden": true
10638
+ },
10639
+ {
10640
+ "name": "accordion-item-radius",
10641
+ "tier": "component",
10642
+ "type": "radius",
10643
+ "group": "components",
10644
+ "value": "var(--iox-radius-md)",
10645
+ "overridden": true
10646
+ },
10647
+ {
10648
+ "name": "accordion-item-pad",
10649
+ "tier": "component",
10650
+ "type": "spacing",
10651
+ "group": "components",
10652
+ "value": "0px var(--iox-space-pad)",
10653
+ "overridden": true
10654
+ },
10655
+ {
10656
+ "name": "accordion-trigger-pad",
10657
+ "tier": "component",
10658
+ "type": "spacing",
10659
+ "group": "components",
10660
+ "value": "20px 0px"
10661
+ },
10662
+ {
10663
+ "name": "accordion-trigger-hover-ink",
10664
+ "tier": "component",
10665
+ "type": "color",
10666
+ "group": "components",
10667
+ "value": "var(--iox-accent-text)"
10668
+ },
10669
+ {
10670
+ "name": "accordion-panel-pad",
10671
+ "tier": "component",
10672
+ "type": "spacing",
10673
+ "group": "components",
10674
+ "value": "0px 0px 20px 0px"
10675
+ },
10256
10676
  {
10257
10677
  "name": "heading-color",
10258
10678
  "tier": "component",
@@ -11808,6 +12228,75 @@ export const SPEC_FLAVOR_PACKS = [
11808
12228
  "group": "components",
11809
12229
  "value": "var(--iox-size-label)"
11810
12230
  },
12231
+ {
12232
+ "name": "accordion-gap",
12233
+ "tier": "component",
12234
+ "type": "spacing",
12235
+ "group": "components",
12236
+ "value": "12px",
12237
+ "overridden": true
12238
+ },
12239
+ {
12240
+ "name": "accordion-item-bg",
12241
+ "tier": "component",
12242
+ "type": "color",
12243
+ "group": "components",
12244
+ "value": "var(--iox-surface)",
12245
+ "overridden": true
12246
+ },
12247
+ {
12248
+ "name": "accordion-item-border",
12249
+ "tier": "component",
12250
+ "type": "color",
12251
+ "group": "components",
12252
+ "value": "var(--iox-line-strong)",
12253
+ "overridden": true
12254
+ },
12255
+ {
12256
+ "name": "accordion-item-border-width",
12257
+ "tier": "component",
12258
+ "type": "size",
12259
+ "group": "components",
12260
+ "value": "var(--iox-border-width)",
12261
+ "overridden": true
12262
+ },
12263
+ {
12264
+ "name": "accordion-item-radius",
12265
+ "tier": "component",
12266
+ "type": "radius",
12267
+ "group": "components",
12268
+ "value": "var(--iox-radius-sm)",
12269
+ "overridden": true
12270
+ },
12271
+ {
12272
+ "name": "accordion-item-pad",
12273
+ "tier": "component",
12274
+ "type": "spacing",
12275
+ "group": "components",
12276
+ "value": "0px var(--iox-space-pad)",
12277
+ "overridden": true
12278
+ },
12279
+ {
12280
+ "name": "accordion-trigger-pad",
12281
+ "tier": "component",
12282
+ "type": "spacing",
12283
+ "group": "components",
12284
+ "value": "20px 0px"
12285
+ },
12286
+ {
12287
+ "name": "accordion-trigger-hover-ink",
12288
+ "tier": "component",
12289
+ "type": "color",
12290
+ "group": "components",
12291
+ "value": "var(--iox-accent-text)"
12292
+ },
12293
+ {
12294
+ "name": "accordion-panel-pad",
12295
+ "tier": "component",
12296
+ "type": "spacing",
12297
+ "group": "components",
12298
+ "value": "0px 0px 20px 0px"
12299
+ },
11811
12300
  {
11812
12301
  "name": "heading-color",
11813
12302
  "tier": "component",
@@ -17,7 +17,8 @@ export enum InteractiveTag {
17
17
  * rule. Pinned to the engine components' selectors by `interactive-hosts.spec.ts`.
18
18
  */
19
19
  export const INTERACTIVE_HOST_TAGS: Readonly<Record<string, readonly InteractiveTag[]>> = Object.freeze({
20
- LinkedContainer: [InteractiveTag.Anchor],
20
+ // A LinkedContainer is an <a>, or — as an Accordion's header (CC2) — a <button>.
21
+ LinkedContainer: [InteractiveTag.Anchor, InteractiveTag.Button],
21
22
  Link: [InteractiveTag.Anchor],
22
23
  Button: [InteractiveTag.Anchor],
23
24
  ButtonBlock: [InteractiveTag.Anchor, InteractiveTag.Button],
@@ -1,6 +1,10 @@
1
1
  import { DesignChoices, LinkType, resolveDesignChoices } from '@vectoriox/iox-ui/design-core';
2
2
  import { FormPresetDef, FormPresetField, formPresetById } from '@vectoriox/iox-ui/forms-core';
3
- import { buildCardRecipe, CardLayout, CardPart, CardRole, CARD_LAYOUTS, CARD_PARTS, CompositeNode, CompositeNodeSpec, findByRole } from '@vectoriox/iox-ui/composite-core';
3
+ import {
4
+ ACCORDION_BIND_PROP, ACCORDION_CONTENT_LIMIT, ACCORDION_WORDS, accordionAnswerOf, accordionItems, accordionQuestionOf, AccordionRole,
5
+ buildAccordionRecipe, buildCardRecipe, CardLayout, CardPart, CardRole, CARD_LAYOUTS, CARD_PARTS, CompositeNode, CompositeNodeSpec, findByRole,
6
+ pickAccordionAutoBinds,
7
+ } from '@vectoriox/iox-ui/composite-core';
4
8
 
5
9
  import { NODE_BASELINES } from './node-baselines.generated';
6
10
  import { BindScope, CardBindTarget, PatternDirective, PatternNode, PatternPlaceholder, PatternRecipe, SitePattern, patternById } from './patterns';
@@ -557,6 +561,7 @@ const CARD_BINDS: Readonly<Record<CardBindTarget, { role: CardRole; prop: string
557
561
  * through its title (`href` + `param`, the stretched link). Ids derive from the recipe's keys.
558
562
  */
559
563
  function composeRecipe(pn: PatternNode, id: string, repeater: RepeaterScope | null, ctx: Ctx): SerializedNode {
564
+ if (pn.recipe === PatternRecipe.Accordion) return composeAccordion(pn, id, ctx);
560
565
  if (pn.recipe !== PatternRecipe.Card) throw new ComposeError(`${id}: no recipe "${pn.recipe}" in composite-core`);
561
566
  const layout = (pn.layout ?? CardLayout.Top) as CardLayout;
562
567
  if (!CARD_LAYOUTS.includes(layout)) throw new ComposeError(`${id}: a card has no layout "${pn.layout}"`);
@@ -593,6 +598,49 @@ function composeRecipe(pn: PatternNode, id: string, repeater: RepeaterScope | nu
593
598
  return card;
594
599
  }
595
600
 
601
+ const REPEATER = 'Repeater';
602
+
603
+ /**
604
+ * An Accordion (CC2) — the composite-core recipe stamped with this composer's factory. Manual (no section
605
+ * binding): three items whose questions and answers are placeholders the studio rewrites (`ph: 'copy'`), never
606
+ * invented answers. From content (the section names a list `binding` — R3's AI path): the root is a Repeater
607
+ * over that list holding ONE template item, its question and answer bound to the content type's first
608
+ * short-text and first long-text fields (`pickAccordionAutoBinds`, the builder switch's rule), limit 20.
609
+ */
610
+ function composeAccordion(pn: PatternNode, id: string, ctx: Ctx): SerializedNode {
611
+ const binding = pn.src === PatternDirective.OptionalBinding || pn.src === PatternDirective.Binding ? ctx.section?.binding ?? null : null;
612
+ if (pn.src === PatternDirective.Binding && !binding) throw new ComposeError(`${id}: "$binding" with no section binding`);
613
+ const factory = (spec: CompositeNodeSpec): CompositeNode => {
614
+ const isRoot = spec.key === AccordionRole.Accordion;
615
+ const type = isRoot && binding ? REPEATER : spec.type;
616
+ return create(isRoot ? id : `${id}-${spec.key}`, type, { ...(spec.props ?? {}) }, spec.elementStyle ?? null) as CompositeNode;
617
+ };
618
+ const root = buildAccordionRecipe(factory, binding ? { items: ACCORDION_WORDS.slice(0, 1) } : {}) as SerializedNode;
619
+ if (!binding) {
620
+ if (pn.ph === PatternPlaceholder.Copy) {
621
+ for (const item of accordionItems(root as CompositeNode)) {
622
+ for (const part of [accordionQuestionOf(item), accordionAnswerOf(item)]) {
623
+ if (part) ctx.placeholders.push({ nodeId: part.id!, owner: ctx.owner, kind: PlaceholderKind.Copy, text: String(part.props?.[ACCORDION_BIND_PROP] ?? '') });
624
+ }
625
+ }
626
+ }
627
+ return root;
628
+ }
629
+ const source = ctx.plan.dataSources.find(d => d.alias === binding);
630
+ const type = source && 'contentType' in source ? ctx.plan.contentTypes.find(t => t.name === source.contentType) : undefined;
631
+ const picks = pickAccordionAutoBinds((type?.fields ?? []).map(f => ({ name: f.name, type: f.type, controller: f.controller })));
632
+ if (!picks.question || !picks.answer) {
633
+ throw new ComposeError(`${id}: "${binding}" has no short-text field for the question and long-text field for the answer`);
634
+ }
635
+ addBinding(root, { prop: 'source', source: binding, path: '' });
636
+ setProp(root, 'limit', ACCORDION_CONTENT_LIMIT);
637
+ const [template] = accordionItems(root as CompositeNode);
638
+ delete template.itemKey;
639
+ addBinding(accordionQuestionOf(template) as SerializedNode, { prop: ACCORDION_BIND_PROP, source: binding, path: picks.question });
640
+ addBinding(accordionAnswerOf(template) as SerializedNode, { prop: ACCORDION_BIND_PROP, source: binding, path: picks.answer });
641
+ return root;
642
+ }
643
+
596
644
  function composePattern(pattern: SitePattern, id: string, ctx: Ctx): SerializedNode {
597
645
  if (pattern.node.each) throw new ComposeError(`${id}: a pattern's root cannot be stamped per page`);
598
646
  const node = composeNode(pattern.node, id, null, ctx);