@vectoriox/iox-ui 5.40.0 → 5.41.1

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 (32) hide show
  1. package/composite-core/index.d.ts +212 -12
  2. package/design-core/index.d.ts +694 -17
  3. package/fesm2022/vectoriox-iox-ui-actions-core.mjs +4 -3
  4. package/fesm2022/vectoriox-iox-ui-actions-core.mjs.map +1 -1
  5. package/fesm2022/vectoriox-iox-ui-composite-core.mjs +540 -124
  6. package/fesm2022/vectoriox-iox-ui-composite-core.mjs.map +1 -1
  7. package/fesm2022/vectoriox-iox-ui-design-core.mjs +843 -45
  8. package/fesm2022/vectoriox-iox-ui-design-core.mjs.map +1 -1
  9. package/fesm2022/vectoriox-iox-ui-generation-core.mjs +846 -17
  10. package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
  11. package/fesm2022/vectoriox-iox-ui.mjs +3945 -3914
  12. package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
  13. package/generation-core/index.d.ts +608 -4
  14. package/index.d.ts +22 -1
  15. package/package.json +1 -1
  16. package/src/actions-core/element-actions.ts +4 -3
  17. package/src/composite-core/accordion.ts +1 -0
  18. package/src/composite-core/card.ts +6 -4
  19. package/src/composite-core/composite-kinds.ts +42 -6
  20. package/src/composite-core/exclusive-runtime.ts +60 -10
  21. package/src/composite-core/exclusive.ts +64 -0
  22. package/src/composite-core/public-api.ts +5 -2
  23. package/src/composite-core/segmented.ts +351 -0
  24. package/src/composite-core/structure.ts +6 -1
  25. package/src/composite-core/tabs.ts +6 -3
  26. package/src/design-core/contrast-audit.ts +8 -3
  27. package/src/design-core/flavor-spec.generated.ts +832 -41
  28. package/src/generation-core/compose-site.ts +170 -12
  29. package/src/generation-core/node-baselines.generated.ts +49 -0
  30. package/src/generation-core/patterns.ts +21 -0
  31. package/src/generation-core/site-spec.generated.ts +639 -0
  32. package/styles/iox-design.css +19 -0
@@ -1,6 +1,6 @@
1
- import { NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, elementStyleById, ownedTraitsOf, applyElementStyle, flavorPackById, parseHexColor, SPEC_AXES, LinkType, resolveDesignChoices } from '@vectoriox/iox-ui/design-core';
1
+ import { NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, elementStyleById, ownedTraitsOf, applyElementStyle, flavorPackById, parseHexColor, SPEC_AXES, LinkType, COLOR_SCHEMES, setColorScheme, 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, AccordionRole, buildAccordionRecipe, ACCORDION_WORDS, accordionItems, accordionQuestionOf, accordionAnswerOf, ACCORDION_BIND_PROP, pickAccordionAutoBinds, ACCORDION_CONTENT_LIMIT, buildTabsRecipe, TABS_WORDS, tabsTriggers, tabLabelNodeOf, TABS_LABEL_BIND_PROP, tabsPanels, tabPanelTextOf, TABS_TEXT_BIND_PROP, tabPanelImageOf, pickTabsAutoBinds, tabsListOf, tabsPanelsOf, TABS_CONTENT_LIMIT, TABS_IMAGE_BIND_PROP, buildCarouselRecipe, SLIDE_TYPE, buildLightboxRecipe, LIGHTBOX_LABEL, SLIDE_TO_ROW } from '@vectoriox/iox-ui/composite-core';
3
+ import { segmentedOptions, ITEM_OPEN_STATE, CardRole, CardLayout, CARD_LAYOUTS, CARD_PARTS, BADGE_TONES, buildCardRecipe, findByRole, buildSegmentedRecipe, AccordionRole, buildAccordionRecipe, ACCORDION_WORDS, accordionItems, accordionQuestionOf, accordionAnswerOf, ACCORDION_BIND_PROP, pickAccordionAutoBinds, ACCORDION_CONTENT_LIMIT, buildTabsRecipe, TABS_WORDS, tabsTriggers, tabLabelNodeOf, TABS_LABEL_BIND_PROP, tabsPanels, tabPanelTextOf, TABS_TEXT_BIND_PROP, tabPanelImageOf, pickTabsAutoBinds, tabsListOf, tabsPanelsOf, TABS_CONTENT_LIMIT, TABS_IMAGE_BIND_PROP, buildCarouselRecipe, SLIDE_TYPE, buildLightboxRecipe, LIGHTBOX_LABEL, SLIDE_TO_ROW } 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
@@ -1027,6 +1027,645 @@ const SPEC_SITE_PATTERNS = {
1027
1027
  ]
1028
1028
  }
1029
1029
  },
1030
+ "pricing.tiers": {
1031
+ "family": "pricing",
1032
+ "label": "Pricing — plans with a monthly / yearly switch",
1033
+ "node": {
1034
+ "t": "Section",
1035
+ "es": "section",
1036
+ "c": [
1037
+ {
1038
+ "t": "Container",
1039
+ "es": "box",
1040
+ "lay": {
1041
+ "display": "flex",
1042
+ "flexDirection": "column",
1043
+ "gap": "8px",
1044
+ "alignItems": "center",
1045
+ "textAlign": "center"
1046
+ },
1047
+ "c": [
1048
+ {
1049
+ "t": "Text",
1050
+ "es": "eyebrow",
1051
+ "slot": "eyebrow",
1052
+ "ph": "copy",
1053
+ "text": "Pricing",
1054
+ "lay": {
1055
+ "textAlign": "center"
1056
+ }
1057
+ },
1058
+ {
1059
+ "t": "Heading",
1060
+ "es": "h2",
1061
+ "level": "h2",
1062
+ "slot": "title",
1063
+ "ph": "copy",
1064
+ "text": "Plans",
1065
+ "lay": {
1066
+ "textAlign": "center"
1067
+ }
1068
+ }
1069
+ ]
1070
+ },
1071
+ {
1072
+ "t": "Container",
1073
+ "recipe": "segmented",
1074
+ "name": "Billing period",
1075
+ "lay": {
1076
+ "alignSelf": "center"
1077
+ },
1078
+ "resp": {
1079
+ "mobile": {
1080
+ "position": "sticky",
1081
+ "top": "calc(12px + env(safe-area-inset-top, 0px))",
1082
+ "zIndex": "2",
1083
+ "width": "100%"
1084
+ }
1085
+ }
1086
+ },
1087
+ {
1088
+ "t": "Container",
1089
+ "es": "box",
1090
+ "layer": "Plans",
1091
+ "lay": {
1092
+ "display": "grid",
1093
+ "gridTemplateColumns": "repeat(3, minmax(0, 1fr))",
1094
+ "gap": "var(--iox-space-gap)",
1095
+ "alignItems": "stretch"
1096
+ },
1097
+ "resp": {
1098
+ "mobile": {
1099
+ "gridTemplateColumns": "minmax(0, 1fr)"
1100
+ }
1101
+ },
1102
+ "c": [
1103
+ {
1104
+ "t": "Container",
1105
+ "recipe": "card",
1106
+ "layout": "top",
1107
+ "ph": "copy",
1108
+ "parts": {
1109
+ "media": false,
1110
+ "eyebrow": false,
1111
+ "badge": false,
1112
+ "actions": false
1113
+ },
1114
+ "words": {
1115
+ "title": "First plan",
1116
+ "text": "Who this plan is for, in one sentence."
1117
+ },
1118
+ "c": [
1119
+ {
1120
+ "t": "Container",
1121
+ "es": "box",
1122
+ "layer": "Price · Monthly",
1123
+ "shownWhen": "monthly",
1124
+ "lay": {
1125
+ "display": "flex",
1126
+ "alignItems": "baseline",
1127
+ "flexWrap": "wrap",
1128
+ "gap": "6px"
1129
+ },
1130
+ "c": [
1131
+ {
1132
+ "t": "Text",
1133
+ "es": "price",
1134
+ "ph": "price",
1135
+ "text": "Monthly price",
1136
+ "lay": {
1137
+ "width": "auto"
1138
+ }
1139
+ },
1140
+ {
1141
+ "t": "Text",
1142
+ "es": "small",
1143
+ "text": "per month",
1144
+ "lay": {
1145
+ "width": "auto"
1146
+ }
1147
+ }
1148
+ ]
1149
+ },
1150
+ {
1151
+ "t": "Container",
1152
+ "es": "box",
1153
+ "layer": "Price · Yearly",
1154
+ "shownWhen": "yearly",
1155
+ "lay": {
1156
+ "display": "flex",
1157
+ "alignItems": "baseline",
1158
+ "flexWrap": "wrap",
1159
+ "gap": "6px"
1160
+ },
1161
+ "c": [
1162
+ {
1163
+ "t": "Text",
1164
+ "es": "price",
1165
+ "ph": "price",
1166
+ "text": "Yearly price",
1167
+ "lay": {
1168
+ "width": "auto"
1169
+ }
1170
+ },
1171
+ {
1172
+ "t": "Text",
1173
+ "es": "small",
1174
+ "text": "per year",
1175
+ "lay": {
1176
+ "width": "auto"
1177
+ }
1178
+ }
1179
+ ]
1180
+ },
1181
+ {
1182
+ "t": "Container",
1183
+ "es": "box",
1184
+ "layer": "Includes",
1185
+ "lay": {
1186
+ "display": "flex",
1187
+ "flexDirection": "column",
1188
+ "gap": "8px"
1189
+ },
1190
+ "c": [
1191
+ {
1192
+ "t": "Container",
1193
+ "es": "box",
1194
+ "lay": {
1195
+ "display": "flex",
1196
+ "flexWrap": "nowrap",
1197
+ "gap": "8px",
1198
+ "alignItems": "center"
1199
+ },
1200
+ "c": [
1201
+ {
1202
+ "t": "Icon",
1203
+ "es": "icon",
1204
+ "icon": "ph ph-check"
1205
+ },
1206
+ {
1207
+ "t": "Text",
1208
+ "es": "body",
1209
+ "ph": "copy",
1210
+ "text": "What this plan includes"
1211
+ }
1212
+ ]
1213
+ },
1214
+ {
1215
+ "t": "Container",
1216
+ "es": "box",
1217
+ "lay": {
1218
+ "display": "flex",
1219
+ "flexWrap": "nowrap",
1220
+ "gap": "8px",
1221
+ "alignItems": "center"
1222
+ },
1223
+ "c": [
1224
+ {
1225
+ "t": "Icon",
1226
+ "es": "icon",
1227
+ "icon": "ph ph-check"
1228
+ },
1229
+ {
1230
+ "t": "Text",
1231
+ "es": "body",
1232
+ "ph": "copy",
1233
+ "text": "What this plan includes"
1234
+ }
1235
+ ]
1236
+ },
1237
+ {
1238
+ "t": "Container",
1239
+ "es": "box",
1240
+ "lay": {
1241
+ "display": "flex",
1242
+ "flexWrap": "nowrap",
1243
+ "gap": "8px",
1244
+ "alignItems": "center"
1245
+ },
1246
+ "c": [
1247
+ {
1248
+ "t": "Icon",
1249
+ "es": "icon",
1250
+ "icon": "ph ph-check"
1251
+ },
1252
+ {
1253
+ "t": "Text",
1254
+ "es": "body",
1255
+ "ph": "copy",
1256
+ "text": "What this plan includes"
1257
+ }
1258
+ ]
1259
+ }
1260
+ ]
1261
+ },
1262
+ {
1263
+ "t": "Container",
1264
+ "es": "box",
1265
+ "role": "card.actions",
1266
+ "layer": "Buttons",
1267
+ "lay": {
1268
+ "display": "flex",
1269
+ "flexWrap": "wrap",
1270
+ "gap": "8px",
1271
+ "alignItems": "center",
1272
+ "width": "100%",
1273
+ "margin": "auto 0px 0px 0px",
1274
+ "padding": "6px 0px 0px 0px"
1275
+ },
1276
+ "c": [
1277
+ {
1278
+ "t": "ButtonBlock",
1279
+ "es": "button-primary",
1280
+ "href": "/contact",
1281
+ "text": "Choose this plan"
1282
+ }
1283
+ ]
1284
+ }
1285
+ ]
1286
+ },
1287
+ {
1288
+ "t": "Container",
1289
+ "recipe": "card",
1290
+ "layout": "top",
1291
+ "ph": "copy",
1292
+ "scheme": "accent",
1293
+ "badge": "neutral",
1294
+ "icon": "ph ph-sparkle",
1295
+ "parts": {
1296
+ "media": false,
1297
+ "eyebrow": false,
1298
+ "badge": true,
1299
+ "actions": false
1300
+ },
1301
+ "words": {
1302
+ "title": "Second plan",
1303
+ "text": "Who this plan is for, in one sentence.",
1304
+ "badge": "Most popular"
1305
+ },
1306
+ "c": [
1307
+ {
1308
+ "t": "Container",
1309
+ "es": "box",
1310
+ "layer": "Price · Monthly",
1311
+ "shownWhen": "monthly",
1312
+ "lay": {
1313
+ "display": "flex",
1314
+ "alignItems": "baseline",
1315
+ "flexWrap": "wrap",
1316
+ "gap": "6px"
1317
+ },
1318
+ "c": [
1319
+ {
1320
+ "t": "Text",
1321
+ "es": "price",
1322
+ "ph": "price",
1323
+ "text": "Monthly price",
1324
+ "lay": {
1325
+ "width": "auto"
1326
+ }
1327
+ },
1328
+ {
1329
+ "t": "Text",
1330
+ "es": "small",
1331
+ "text": "per month",
1332
+ "lay": {
1333
+ "width": "auto"
1334
+ }
1335
+ }
1336
+ ]
1337
+ },
1338
+ {
1339
+ "t": "Container",
1340
+ "es": "box",
1341
+ "layer": "Price · Yearly",
1342
+ "shownWhen": "yearly",
1343
+ "lay": {
1344
+ "display": "flex",
1345
+ "alignItems": "baseline",
1346
+ "flexWrap": "wrap",
1347
+ "gap": "6px"
1348
+ },
1349
+ "c": [
1350
+ {
1351
+ "t": "Text",
1352
+ "es": "price",
1353
+ "ph": "price",
1354
+ "text": "Yearly price",
1355
+ "lay": {
1356
+ "width": "auto"
1357
+ }
1358
+ },
1359
+ {
1360
+ "t": "Text",
1361
+ "es": "small",
1362
+ "text": "per year",
1363
+ "lay": {
1364
+ "width": "auto"
1365
+ }
1366
+ }
1367
+ ]
1368
+ },
1369
+ {
1370
+ "t": "Container",
1371
+ "es": "box",
1372
+ "layer": "Includes",
1373
+ "lay": {
1374
+ "display": "flex",
1375
+ "flexDirection": "column",
1376
+ "gap": "8px"
1377
+ },
1378
+ "c": [
1379
+ {
1380
+ "t": "Container",
1381
+ "es": "box",
1382
+ "lay": {
1383
+ "display": "flex",
1384
+ "flexWrap": "nowrap",
1385
+ "gap": "8px",
1386
+ "alignItems": "center"
1387
+ },
1388
+ "c": [
1389
+ {
1390
+ "t": "Icon",
1391
+ "es": "icon",
1392
+ "icon": "ph ph-check"
1393
+ },
1394
+ {
1395
+ "t": "Text",
1396
+ "es": "body",
1397
+ "ph": "copy",
1398
+ "text": "What this plan includes"
1399
+ }
1400
+ ]
1401
+ },
1402
+ {
1403
+ "t": "Container",
1404
+ "es": "box",
1405
+ "lay": {
1406
+ "display": "flex",
1407
+ "flexWrap": "nowrap",
1408
+ "gap": "8px",
1409
+ "alignItems": "center"
1410
+ },
1411
+ "c": [
1412
+ {
1413
+ "t": "Icon",
1414
+ "es": "icon",
1415
+ "icon": "ph ph-check"
1416
+ },
1417
+ {
1418
+ "t": "Text",
1419
+ "es": "body",
1420
+ "ph": "copy",
1421
+ "text": "What this plan includes"
1422
+ }
1423
+ ]
1424
+ },
1425
+ {
1426
+ "t": "Container",
1427
+ "es": "box",
1428
+ "lay": {
1429
+ "display": "flex",
1430
+ "flexWrap": "nowrap",
1431
+ "gap": "8px",
1432
+ "alignItems": "center"
1433
+ },
1434
+ "c": [
1435
+ {
1436
+ "t": "Icon",
1437
+ "es": "icon",
1438
+ "icon": "ph ph-check"
1439
+ },
1440
+ {
1441
+ "t": "Text",
1442
+ "es": "body",
1443
+ "ph": "copy",
1444
+ "text": "What this plan includes"
1445
+ }
1446
+ ]
1447
+ }
1448
+ ]
1449
+ },
1450
+ {
1451
+ "t": "Container",
1452
+ "es": "box",
1453
+ "role": "card.actions",
1454
+ "layer": "Buttons",
1455
+ "lay": {
1456
+ "display": "flex",
1457
+ "flexWrap": "wrap",
1458
+ "gap": "8px",
1459
+ "alignItems": "center",
1460
+ "width": "100%",
1461
+ "margin": "auto 0px 0px 0px",
1462
+ "padding": "6px 0px 0px 0px"
1463
+ },
1464
+ "c": [
1465
+ {
1466
+ "t": "ButtonBlock",
1467
+ "es": "button-primary",
1468
+ "href": "/contact",
1469
+ "text": "Choose this plan"
1470
+ }
1471
+ ]
1472
+ }
1473
+ ]
1474
+ },
1475
+ {
1476
+ "t": "Container",
1477
+ "recipe": "card",
1478
+ "layout": "top",
1479
+ "ph": "copy",
1480
+ "parts": {
1481
+ "media": false,
1482
+ "eyebrow": false,
1483
+ "badge": false,
1484
+ "actions": false
1485
+ },
1486
+ "words": {
1487
+ "title": "Third plan",
1488
+ "text": "Who this plan is for, in one sentence."
1489
+ },
1490
+ "c": [
1491
+ {
1492
+ "t": "Container",
1493
+ "es": "box",
1494
+ "layer": "Price · Monthly",
1495
+ "shownWhen": "monthly",
1496
+ "lay": {
1497
+ "display": "flex",
1498
+ "alignItems": "baseline",
1499
+ "flexWrap": "wrap",
1500
+ "gap": "6px"
1501
+ },
1502
+ "c": [
1503
+ {
1504
+ "t": "Text",
1505
+ "es": "price",
1506
+ "ph": "price",
1507
+ "text": "Monthly price",
1508
+ "lay": {
1509
+ "width": "auto"
1510
+ }
1511
+ },
1512
+ {
1513
+ "t": "Text",
1514
+ "es": "small",
1515
+ "text": "per month",
1516
+ "lay": {
1517
+ "width": "auto"
1518
+ }
1519
+ }
1520
+ ]
1521
+ },
1522
+ {
1523
+ "t": "Container",
1524
+ "es": "box",
1525
+ "layer": "Price · Yearly",
1526
+ "shownWhen": "yearly",
1527
+ "lay": {
1528
+ "display": "flex",
1529
+ "alignItems": "baseline",
1530
+ "flexWrap": "wrap",
1531
+ "gap": "6px"
1532
+ },
1533
+ "c": [
1534
+ {
1535
+ "t": "Text",
1536
+ "es": "price",
1537
+ "ph": "price",
1538
+ "text": "Yearly price",
1539
+ "lay": {
1540
+ "width": "auto"
1541
+ }
1542
+ },
1543
+ {
1544
+ "t": "Text",
1545
+ "es": "small",
1546
+ "text": "per year",
1547
+ "lay": {
1548
+ "width": "auto"
1549
+ }
1550
+ }
1551
+ ]
1552
+ },
1553
+ {
1554
+ "t": "Container",
1555
+ "es": "box",
1556
+ "layer": "Includes",
1557
+ "lay": {
1558
+ "display": "flex",
1559
+ "flexDirection": "column",
1560
+ "gap": "8px"
1561
+ },
1562
+ "c": [
1563
+ {
1564
+ "t": "Container",
1565
+ "es": "box",
1566
+ "lay": {
1567
+ "display": "flex",
1568
+ "flexWrap": "nowrap",
1569
+ "gap": "8px",
1570
+ "alignItems": "center"
1571
+ },
1572
+ "c": [
1573
+ {
1574
+ "t": "Icon",
1575
+ "es": "icon",
1576
+ "icon": "ph ph-check"
1577
+ },
1578
+ {
1579
+ "t": "Text",
1580
+ "es": "body",
1581
+ "ph": "copy",
1582
+ "text": "What this plan includes"
1583
+ }
1584
+ ]
1585
+ },
1586
+ {
1587
+ "t": "Container",
1588
+ "es": "box",
1589
+ "lay": {
1590
+ "display": "flex",
1591
+ "flexWrap": "nowrap",
1592
+ "gap": "8px",
1593
+ "alignItems": "center"
1594
+ },
1595
+ "c": [
1596
+ {
1597
+ "t": "Icon",
1598
+ "es": "icon",
1599
+ "icon": "ph ph-check"
1600
+ },
1601
+ {
1602
+ "t": "Text",
1603
+ "es": "body",
1604
+ "ph": "copy",
1605
+ "text": "What this plan includes"
1606
+ }
1607
+ ]
1608
+ },
1609
+ {
1610
+ "t": "Container",
1611
+ "es": "box",
1612
+ "lay": {
1613
+ "display": "flex",
1614
+ "flexWrap": "nowrap",
1615
+ "gap": "8px",
1616
+ "alignItems": "center"
1617
+ },
1618
+ "c": [
1619
+ {
1620
+ "t": "Icon",
1621
+ "es": "icon",
1622
+ "icon": "ph ph-check"
1623
+ },
1624
+ {
1625
+ "t": "Text",
1626
+ "es": "body",
1627
+ "ph": "copy",
1628
+ "text": "What this plan includes"
1629
+ }
1630
+ ]
1631
+ }
1632
+ ]
1633
+ },
1634
+ {
1635
+ "t": "Container",
1636
+ "es": "box",
1637
+ "role": "card.actions",
1638
+ "layer": "Buttons",
1639
+ "lay": {
1640
+ "display": "flex",
1641
+ "flexWrap": "wrap",
1642
+ "gap": "8px",
1643
+ "alignItems": "center",
1644
+ "width": "100%",
1645
+ "margin": "auto 0px 0px 0px",
1646
+ "padding": "6px 0px 0px 0px"
1647
+ },
1648
+ "c": [
1649
+ {
1650
+ "t": "ButtonBlock",
1651
+ "es": "button-primary",
1652
+ "href": "/contact",
1653
+ "text": "Choose this plan"
1654
+ }
1655
+ ]
1656
+ }
1657
+ ]
1658
+ }
1659
+ ]
1660
+ }
1661
+ ],
1662
+ "lay": {
1663
+ "display": "flex",
1664
+ "flexDirection": "column",
1665
+ "gap": "32px"
1666
+ }
1667
+ }
1668
+ },
1030
1669
  "hero.full-bleed-media": {
1031
1670
  "family": "hero",
1032
1671
  "label": "Hero — words over a background video",
@@ -1463,6 +2102,7 @@ const NODE_BASELINES = {
1463
2102
  "textAlign": "start",
1464
2103
  "fontStyle": "normal",
1465
2104
  "textDecoration": "none",
2105
+ "fontVariantNumeric": "normal",
1466
2106
  "WebkitTextStrokeWidth": "0px",
1467
2107
  "WebkitTextStrokeColor": "transparent",
1468
2108
  "margin": "0px 0px 0px 0px",
@@ -1552,6 +2192,7 @@ const NODE_BASELINES = {
1552
2192
  "textAlign",
1553
2193
  "fontStyle",
1554
2194
  "textDecoration",
2195
+ "fontVariantNumeric",
1555
2196
  "_sep_stroke",
1556
2197
  "WebkitTextStrokeWidth",
1557
2198
  "WebkitTextStrokeColor",
@@ -1654,6 +2295,7 @@ const NODE_BASELINES = {
1654
2295
  "textAlign": "start",
1655
2296
  "fontStyle": "normal",
1656
2297
  "textDecoration": "none",
2298
+ "fontVariantNumeric": "normal",
1657
2299
  "WebkitTextStrokeWidth": "0px",
1658
2300
  "WebkitTextStrokeColor": "transparent",
1659
2301
  "margin": "0px 0px 0px 0px",
@@ -1748,6 +2390,7 @@ const NODE_BASELINES = {
1748
2390
  "textAlign",
1749
2391
  "fontStyle",
1750
2392
  "textDecoration",
2393
+ "fontVariantNumeric",
1751
2394
  "_sep_stroke",
1752
2395
  "WebkitTextStrokeWidth",
1753
2396
  "WebkitTextStrokeColor",
@@ -1846,6 +2489,7 @@ const NODE_BASELINES = {
1846
2489
  "textAlign": "start",
1847
2490
  "fontStyle": "normal",
1848
2491
  "textDecoration": "none",
2492
+ "fontVariantNumeric": "normal",
1849
2493
  "WebkitTextStrokeWidth": "0px",
1850
2494
  "WebkitTextStrokeColor": "transparent",
1851
2495
  "margin": "0px 0px 0px 0px",
@@ -1935,6 +2579,7 @@ const NODE_BASELINES = {
1935
2579
  "textAlign",
1936
2580
  "fontStyle",
1937
2581
  "textDecoration",
2582
+ "fontVariantNumeric",
1938
2583
  "_sep_stroke",
1939
2584
  "WebkitTextStrokeWidth",
1940
2585
  "WebkitTextStrokeColor",
@@ -2032,6 +2677,7 @@ const NODE_BASELINES = {
2032
2677
  "textAlign": "start",
2033
2678
  "fontStyle": "normal",
2034
2679
  "textDecoration": "none",
2680
+ "fontVariantNumeric": "normal",
2035
2681
  "WebkitTextStrokeWidth": "0px",
2036
2682
  "WebkitTextStrokeColor": "transparent",
2037
2683
  "margin": "0px 0px 0px 0px",
@@ -2125,6 +2771,7 @@ const NODE_BASELINES = {
2125
2771
  "textAlign",
2126
2772
  "fontStyle",
2127
2773
  "textDecoration",
2774
+ "fontVariantNumeric",
2128
2775
  "_sep_stroke",
2129
2776
  "WebkitTextStrokeWidth",
2130
2777
  "WebkitTextStrokeColor",
@@ -2226,6 +2873,7 @@ const NODE_BASELINES = {
2226
2873
  "textAlign": "start",
2227
2874
  "fontStyle": "normal",
2228
2875
  "textDecoration": "none",
2876
+ "fontVariantNumeric": "normal",
2229
2877
  "WebkitTextStrokeWidth": "0px",
2230
2878
  "WebkitTextStrokeColor": "transparent",
2231
2879
  "maxLines": "none",
@@ -2319,6 +2967,7 @@ const NODE_BASELINES = {
2319
2967
  "textAlign",
2320
2968
  "fontStyle",
2321
2969
  "textDecoration",
2970
+ "fontVariantNumeric",
2322
2971
  "_sep_stroke",
2323
2972
  "WebkitTextStrokeWidth",
2324
2973
  "WebkitTextStrokeColor",
@@ -2417,6 +3066,7 @@ const NODE_BASELINES = {
2417
3066
  "textAlign": "start",
2418
3067
  "fontStyle": "normal",
2419
3068
  "textDecoration": "none",
3069
+ "fontVariantNumeric": "normal",
2420
3070
  "WebkitTextStrokeWidth": "0px",
2421
3071
  "WebkitTextStrokeColor": "transparent",
2422
3072
  "maxLines": "none",
@@ -2506,6 +3156,7 @@ const NODE_BASELINES = {
2506
3156
  "textAlign",
2507
3157
  "fontStyle",
2508
3158
  "textDecoration",
3159
+ "fontVariantNumeric",
2509
3160
  "_sep_stroke",
2510
3161
  "WebkitTextStrokeWidth",
2511
3162
  "WebkitTextStrokeColor",
@@ -2604,6 +3255,7 @@ const NODE_BASELINES = {
2604
3255
  "textAlign": "start",
2605
3256
  "fontStyle": "normal",
2606
3257
  "textDecoration": "none",
3258
+ "fontVariantNumeric": "normal",
2607
3259
  "WebkitTextStrokeWidth": "0px",
2608
3260
  "WebkitTextStrokeColor": "transparent",
2609
3261
  "margin": "0px 0px 0px 0px",
@@ -2692,6 +3344,7 @@ const NODE_BASELINES = {
2692
3344
  "textAlign",
2693
3345
  "fontStyle",
2694
3346
  "textDecoration",
3347
+ "fontVariantNumeric",
2695
3348
  "_sep_stroke",
2696
3349
  "WebkitTextStrokeWidth",
2697
3350
  "WebkitTextStrokeColor",
@@ -2793,6 +3446,7 @@ const NODE_BASELINES = {
2793
3446
  "textAlign": "start",
2794
3447
  "fontStyle": "normal",
2795
3448
  "textDecoration": "none",
3449
+ "fontVariantNumeric": "normal",
2796
3450
  "WebkitTextStrokeWidth": "0px",
2797
3451
  "WebkitTextStrokeColor": "transparent",
2798
3452
  "margin": "0px 0px 0px 0px",
@@ -2886,6 +3540,7 @@ const NODE_BASELINES = {
2886
3540
  "textAlign",
2887
3541
  "fontStyle",
2888
3542
  "textDecoration",
3543
+ "fontVariantNumeric",
2889
3544
  "_sep_stroke",
2890
3545
  "WebkitTextStrokeWidth",
2891
3546
  "WebkitTextStrokeColor",
@@ -2987,6 +3642,7 @@ const NODE_BASELINES = {
2987
3642
  "textAlign": "start",
2988
3643
  "fontStyle": "normal",
2989
3644
  "textDecoration": "none",
3645
+ "fontVariantNumeric": "normal",
2990
3646
  "WebkitTextStrokeWidth": "0px",
2991
3647
  "WebkitTextStrokeColor": "transparent",
2992
3648
  "margin": "0px 0px 0px 0px",
@@ -3080,6 +3736,7 @@ const NODE_BASELINES = {
3080
3736
  "textAlign",
3081
3737
  "fontStyle",
3082
3738
  "textDecoration",
3739
+ "fontVariantNumeric",
3083
3740
  "_sep_stroke",
3084
3741
  "WebkitTextStrokeWidth",
3085
3742
  "WebkitTextStrokeColor",
@@ -3176,6 +3833,7 @@ const NODE_BASELINES = {
3176
3833
  "textAlign": "start",
3177
3834
  "fontStyle": "normal",
3178
3835
  "textDecoration": "none",
3836
+ "fontVariantNumeric": "normal",
3179
3837
  "WebkitTextStrokeWidth": "0px",
3180
3838
  "WebkitTextStrokeColor": "transparent",
3181
3839
  "margin": "0px 0px 0px 0px",
@@ -3263,6 +3921,7 @@ const NODE_BASELINES = {
3263
3921
  "textAlign",
3264
3922
  "fontStyle",
3265
3923
  "textDecoration",
3924
+ "fontVariantNumeric",
3266
3925
  "_sep_stroke",
3267
3926
  "WebkitTextStrokeWidth",
3268
3927
  "WebkitTextStrokeColor",
@@ -3359,6 +4018,7 @@ const NODE_BASELINES = {
3359
4018
  "textAlign": "start",
3360
4019
  "fontStyle": "normal",
3361
4020
  "textDecoration": "none",
4021
+ "fontVariantNumeric": "normal",
3362
4022
  "WebkitTextStrokeWidth": "0px",
3363
4023
  "WebkitTextStrokeColor": "transparent",
3364
4024
  "margin": "0px 0px 0px 0px",
@@ -3446,6 +4106,7 @@ const NODE_BASELINES = {
3446
4106
  "textAlign",
3447
4107
  "fontStyle",
3448
4108
  "textDecoration",
4109
+ "fontVariantNumeric",
3449
4110
  "_sep_stroke",
3450
4111
  "WebkitTextStrokeWidth",
3451
4112
  "WebkitTextStrokeColor",
@@ -3540,6 +4201,7 @@ const NODE_BASELINES = {
3540
4201
  "textAlign": "start",
3541
4202
  "fontStyle": "normal",
3542
4203
  "textDecoration": "none",
4204
+ "fontVariantNumeric": "normal",
3543
4205
  "WebkitTextStrokeWidth": "0px",
3544
4206
  "WebkitTextStrokeColor": "transparent",
3545
4207
  "margin": "8px 0px 8px 0px",
@@ -3625,6 +4287,7 @@ const NODE_BASELINES = {
3625
4287
  "textAlign",
3626
4288
  "fontStyle",
3627
4289
  "textDecoration",
4290
+ "fontVariantNumeric",
3628
4291
  "_sep_stroke",
3629
4292
  "WebkitTextStrokeWidth",
3630
4293
  "WebkitTextStrokeColor",
@@ -3719,6 +4382,7 @@ const NODE_BASELINES = {
3719
4382
  "textAlign": "start",
3720
4383
  "fontStyle": "normal",
3721
4384
  "textDecoration": "none",
4385
+ "fontVariantNumeric": "normal",
3722
4386
  "WebkitTextStrokeWidth": "0px",
3723
4387
  "WebkitTextStrokeColor": "transparent",
3724
4388
  "margin": "0px 0px 0px 0px",
@@ -3804,6 +4468,7 @@ const NODE_BASELINES = {
3804
4468
  "textAlign",
3805
4469
  "fontStyle",
3806
4470
  "textDecoration",
4471
+ "fontVariantNumeric",
3807
4472
  "_sep_stroke",
3808
4473
  "WebkitTextStrokeWidth",
3809
4474
  "WebkitTextStrokeColor",
@@ -3907,6 +4572,7 @@ const NODE_BASELINES = {
3907
4572
  "textAlign": "start",
3908
4573
  "fontStyle": "normal",
3909
4574
  "textDecoration": "none",
4575
+ "fontVariantNumeric": "normal",
3910
4576
  "WebkitTextStrokeWidth": "0px",
3911
4577
  "WebkitTextStrokeColor": "transparent",
3912
4578
  "opacity": "1",
@@ -3995,6 +4661,7 @@ const NODE_BASELINES = {
3995
4661
  "textAlign",
3996
4662
  "fontStyle",
3997
4663
  "textDecoration",
4664
+ "fontVariantNumeric",
3998
4665
  "_sep_stroke",
3999
4666
  "WebkitTextStrokeWidth",
4000
4667
  "WebkitTextStrokeColor",
@@ -4084,6 +4751,7 @@ const NODE_BASELINES = {
4084
4751
  "textAlign": "start",
4085
4752
  "fontStyle": "normal",
4086
4753
  "textDecoration": "none",
4754
+ "fontVariantNumeric": "normal",
4087
4755
  "WebkitTextStrokeWidth": "0px",
4088
4756
  "WebkitTextStrokeColor": "transparent",
4089
4757
  "margin": "0px 0px 0px 0px",
@@ -4171,6 +4839,7 @@ const NODE_BASELINES = {
4171
4839
  "textAlign",
4172
4840
  "fontStyle",
4173
4841
  "textDecoration",
4842
+ "fontVariantNumeric",
4174
4843
  "_sep_stroke",
4175
4844
  "WebkitTextStrokeWidth",
4176
4845
  "WebkitTextStrokeColor",
@@ -4268,6 +4937,7 @@ const NODE_BASELINES = {
4268
4937
  "textAlign": "start",
4269
4938
  "fontStyle": "normal",
4270
4939
  "textDecoration": "none",
4940
+ "fontVariantNumeric": "normal",
4271
4941
  "WebkitTextStrokeWidth": "0px",
4272
4942
  "WebkitTextStrokeColor": "transparent",
4273
4943
  "margin": "0px 0px 0px 0px",
@@ -4361,6 +5031,7 @@ const NODE_BASELINES = {
4361
5031
  "textAlign",
4362
5032
  "fontStyle",
4363
5033
  "textDecoration",
5034
+ "fontVariantNumeric",
4364
5035
  "_sep_stroke",
4365
5036
  "WebkitTextStrokeWidth",
4366
5037
  "WebkitTextStrokeColor",
@@ -4678,6 +5349,7 @@ const NODE_BASELINES = {
4678
5349
  "textAlign": "start",
4679
5350
  "fontStyle": "normal",
4680
5351
  "textDecoration": "none",
5352
+ "fontVariantNumeric": "normal",
4681
5353
  "WebkitTextStrokeWidth": "0px",
4682
5354
  "WebkitTextStrokeColor": "transparent",
4683
5355
  "opacity": "1",
@@ -4755,6 +5427,7 @@ const NODE_BASELINES = {
4755
5427
  "textAlign",
4756
5428
  "fontStyle",
4757
5429
  "textDecoration",
5430
+ "fontVariantNumeric",
4758
5431
  "_sep_stroke",
4759
5432
  "WebkitTextStrokeWidth",
4760
5433
  "WebkitTextStrokeColor",
@@ -4988,6 +5661,7 @@ const NODE_BASELINES = {
4988
5661
  "textAlign": "start",
4989
5662
  "fontStyle": "normal",
4990
5663
  "textDecoration": "none",
5664
+ "fontVariantNumeric": "normal",
4991
5665
  "WebkitTextStrokeWidth": "0px",
4992
5666
  "WebkitTextStrokeColor": "transparent",
4993
5667
  "opacity": "1",
@@ -5081,6 +5755,7 @@ const NODE_BASELINES = {
5081
5755
  "textAlign",
5082
5756
  "fontStyle",
5083
5757
  "textDecoration",
5758
+ "fontVariantNumeric",
5084
5759
  "_sep_stroke",
5085
5760
  "WebkitTextStrokeWidth",
5086
5761
  "WebkitTextStrokeColor",
@@ -5183,6 +5858,7 @@ const NODE_BASELINES = {
5183
5858
  "textAlign": "start",
5184
5859
  "fontStyle": "normal",
5185
5860
  "textDecoration": "none",
5861
+ "fontVariantNumeric": "normal",
5186
5862
  "WebkitTextStrokeWidth": "0px",
5187
5863
  "WebkitTextStrokeColor": "transparent",
5188
5864
  "margin": "0px 0px 0px 0px",
@@ -5286,6 +5962,7 @@ const NODE_BASELINES = {
5286
5962
  "textAlign",
5287
5963
  "fontStyle",
5288
5964
  "textDecoration",
5965
+ "fontVariantNumeric",
5289
5966
  "_sep_stroke",
5290
5967
  "WebkitTextStrokeWidth",
5291
5968
  "WebkitTextStrokeColor",
@@ -5382,6 +6059,7 @@ const NODE_BASELINES = {
5382
6059
  "textAlign": "start",
5383
6060
  "fontStyle": "normal",
5384
6061
  "textDecoration": "none",
6062
+ "fontVariantNumeric": "normal",
5385
6063
  "WebkitTextStrokeWidth": "0px",
5386
6064
  "WebkitTextStrokeColor": "transparent",
5387
6065
  "margin": "0px 0px 0px 0px",
@@ -5469,6 +6147,7 @@ const NODE_BASELINES = {
5469
6147
  "textAlign",
5470
6148
  "fontStyle",
5471
6149
  "textDecoration",
6150
+ "fontVariantNumeric",
5472
6151
  "_sep_stroke",
5473
6152
  "WebkitTextStrokeWidth",
5474
6153
  "WebkitTextStrokeColor",
@@ -5567,6 +6246,7 @@ const NODE_BASELINES = {
5567
6246
  "textAlign": "start",
5568
6247
  "fontStyle": "normal",
5569
6248
  "textDecoration": "none",
6249
+ "fontVariantNumeric": "normal",
5570
6250
  "WebkitTextStrokeWidth": "0px",
5571
6251
  "WebkitTextStrokeColor": "transparent",
5572
6252
  "margin": "0px 0px 0px 0px",
@@ -5656,6 +6336,7 @@ const NODE_BASELINES = {
5656
6336
  "textAlign",
5657
6337
  "fontStyle",
5658
6338
  "textDecoration",
6339
+ "fontVariantNumeric",
5659
6340
  "_sep_stroke",
5660
6341
  "WebkitTextStrokeWidth",
5661
6342
  "WebkitTextStrokeColor",
@@ -5752,6 +6433,7 @@ const NODE_BASELINES = {
5752
6433
  "textAlign": "start",
5753
6434
  "fontStyle": "normal",
5754
6435
  "textDecoration": "none",
6436
+ "fontVariantNumeric": "normal",
5755
6437
  "WebkitTextStrokeWidth": "0px",
5756
6438
  "WebkitTextStrokeColor": "transparent",
5757
6439
  "margin": "0px 0px 0px 0px",
@@ -5839,6 +6521,7 @@ const NODE_BASELINES = {
5839
6521
  "textAlign",
5840
6522
  "fontStyle",
5841
6523
  "textDecoration",
6524
+ "fontVariantNumeric",
5842
6525
  "_sep_stroke",
5843
6526
  "WebkitTextStrokeWidth",
5844
6527
  "WebkitTextStrokeColor",
@@ -5935,6 +6618,7 @@ const NODE_BASELINES = {
5935
6618
  "textAlign": "start",
5936
6619
  "fontStyle": "normal",
5937
6620
  "textDecoration": "none",
6621
+ "fontVariantNumeric": "normal",
5938
6622
  "WebkitTextStrokeWidth": "0px",
5939
6623
  "WebkitTextStrokeColor": "transparent",
5940
6624
  "margin": "0px 0px 0px 0px",
@@ -6022,6 +6706,7 @@ const NODE_BASELINES = {
6022
6706
  "textAlign",
6023
6707
  "fontStyle",
6024
6708
  "textDecoration",
6709
+ "fontVariantNumeric",
6025
6710
  "_sep_stroke",
6026
6711
  "WebkitTextStrokeWidth",
6027
6712
  "WebkitTextStrokeColor",
@@ -6124,6 +6809,7 @@ const NODE_BASELINES = {
6124
6809
  "textAlign": "start",
6125
6810
  "fontStyle": "normal",
6126
6811
  "textDecoration": "none",
6812
+ "fontVariantNumeric": "normal",
6127
6813
  "WebkitTextStrokeWidth": "0px",
6128
6814
  "WebkitTextStrokeColor": "transparent",
6129
6815
  "margin": "0px 0px 0px 0px",
@@ -6219,6 +6905,7 @@ const NODE_BASELINES = {
6219
6905
  "textAlign",
6220
6906
  "fontStyle",
6221
6907
  "textDecoration",
6908
+ "fontVariantNumeric",
6222
6909
  "_sep_stroke",
6223
6910
  "WebkitTextStrokeWidth",
6224
6911
  "WebkitTextStrokeColor",
@@ -6452,6 +7139,7 @@ const NEUTRAL_STYLE_PROPS = {
6452
7139
  "textAlign": "start",
6453
7140
  "fontStyle": "normal",
6454
7141
  "textDecoration": "none",
7142
+ "fontVariantNumeric": "normal",
6455
7143
  "WebkitTextStrokeWidth": "0px",
6456
7144
  "WebkitTextStrokeColor": "transparent",
6457
7145
  "margin": "0px 0px 0px 0px",
@@ -6614,6 +7302,8 @@ var PatternRecipe;
6614
7302
  /** CC4a: Tabs — Manual (three placeholder tabs), or From content when the section names a list `binding`: the tab
6615
7303
  * list and the panels are both Repeaters over it, one row giving its tab AND its panel. */
6616
7304
  PatternRecipe["Tabs"] = "tabs";
7305
+ /** CC4b: the Segmented control — Monthly · Yearly, named by the pattern (`name`). */
7306
+ PatternRecipe["Segmented"] = "segmented";
6617
7307
  /** CC3: the accessible carousel — a named Slider whose controls are parts, one quote per slide (placeholders). */
6618
7308
  PatternRecipe["Carousel"] = "carousel";
6619
7309
  /** CC3: the Lightbox — a Dialog holding a Slider over the node's `src` (the gallery's own source). */
@@ -6644,6 +7334,8 @@ var PatternPlaceholder;
6644
7334
  PatternPlaceholder["Image"] = "image";
6645
7335
  /** CC3: a clip the studio uploads (a Video's file): the poster blank until then, publish-blocking. */
6646
7336
  PatternPlaceholder["Video"] = "video";
7337
+ /** CC4b (Q37): a price the studio types — free text, publish-blocking, its label shown meanwhile, never a number. */
7338
+ PatternPlaceholder["Price"] = "price";
6647
7339
  })(PatternPlaceholder || (PatternPlaceholder = {}));
6648
7340
  /** CC3: what an `opens` node opens. */
6649
7341
  var PatternOpens;
@@ -7384,7 +8076,7 @@ const DIALOG$1 = 'Dialog';
7384
8076
  const LINK = 'Link';
7385
8077
  const LINKED = 'LinkedContainer';
7386
8078
  const BUTTON = 'ButtonBlock';
7387
- const ICON = 'Icon';
8079
+ const ICON$1 = 'Icon';
7388
8080
  const TEXT$1 = 'Text';
7389
8081
  const HEADING = 'Heading';
7390
8082
  const NAV_STYLE = 'nav';
@@ -7575,7 +8267,7 @@ function moveDisplayOverride(node, to) {
7575
8267
  }
7576
8268
  }
7577
8269
  function iconNode(kit, suffix, iconClass) {
7578
- return part(kit, suffix, ICON, { iconClass }, null);
8270
+ return part(kit, suffix, ICON$1, { iconClass }, null);
7579
8271
  }
7580
8272
  function labelText(kit, suffix, words) {
7581
8273
  return part(kit, suffix, TEXT$1, { content: words, tag: 'span' }, 'button-label');
@@ -7903,7 +8595,17 @@ var PlaceholderKind;
7903
8595
  PlaceholderKind["Image"] = "image";
7904
8596
  /** CC3: a video slot with no clip — the studio uploads its own (the poster blank meanwhile). */
7905
8597
  PlaceholderKind["Video"] = "video";
8598
+ /** CC4b (Q37): a price — a FACT the customer could be held to. Free text the studio types ("₪ 1,200", "From $40",
8599
+ * "On request"); its label shows meanwhile ("Monthly price"), never a number. No currency model. */
8600
+ PlaceholderKind["Price"] = "price";
7906
8601
  })(PlaceholderKind || (PlaceholderKind = {}));
8602
+ /** The placeholders a page cannot be published with unfilled (W4's gate): a fact, a price, the studio's own video.
8603
+ * Copy and an empty image are the author's to rewrite, never blocking. */
8604
+ const PUBLISH_BLOCKING_PLACEHOLDERS = new Set([PlaceholderKind.Fact, PlaceholderKind.Price, PlaceholderKind.Video]);
8605
+ /** True when a placeholder of `kind` blocks publishing until the studio fills it. */
8606
+ function blocksPublish(kind) {
8607
+ return PUBLISH_BLOCKING_PLACEHOLDERS.has(kind);
8608
+ }
7907
8609
  var ComposeIssueCode;
7908
8610
  (function (ComposeIssueCode) {
7909
8611
  /** A slot the plan and the business left empty and the pattern gives no words for — the node keeps
@@ -8022,6 +8724,8 @@ function chooseText(pn, ctx) {
8022
8724
  const own = pn.text === undefined ? undefined : fillVariables(pn.text, ctx);
8023
8725
  if (pn.ph === PatternPlaceholder.Copy)
8024
8726
  return { value: own, placeholder: { kind: PlaceholderKind.Copy } };
8727
+ if (pn.ph === PatternPlaceholder.Price)
8728
+ return { value: own, placeholder: { kind: PlaceholderKind.Price } };
8025
8729
  return { value: own };
8026
8730
  }
8027
8731
  /** A `bind` / `alt` / `param` / `src` path → the binding source + path, in this node's scope. */
@@ -8116,7 +8820,7 @@ function danglingFate(pn, ctx) {
8116
8820
  return null;
8117
8821
  if (ctx.email)
8118
8822
  return DanglingFate.Email;
8119
- return UNLINKED_TYPE[pn.t] ? DanglingFate.Unlink : DanglingFate.Remove;
8823
+ return UNLINKED_TYPE[pn.t] || (ctx.keepButtons && pn.t === BUTTON_BLOCK) ? DanglingFate.Unlink : DanglingFate.Remove;
8120
8824
  }
8121
8825
  const DANGLING_ISSUE = {
8122
8826
  [DanglingFate.Email]: ComposeIssueCode.LinkToEmail,
@@ -8128,7 +8832,9 @@ function reportDangling(fate, pn, id, words, ctx) {
8128
8832
  const outcome = {
8129
8833
  [DanglingFate.Email]: `it now opens an email to ${ctx.email}`,
8130
8834
  [DanglingFate.Remove]: 'with no email address to send to instead, it was removed',
8131
- [DanglingFate.Unlink]: 'with no email address to send to instead, the box keeps its contents without the link',
8835
+ [DanglingFate.Unlink]: pn.t === BUTTON_BLOCK
8836
+ ? 'with no email address to send to instead, the button keeps its words without the link'
8837
+ : 'with no email address to send to instead, the box keeps its contents without the link',
8132
8838
  }[fate];
8133
8839
  ctx.issues.push({
8134
8840
  code: DANGLING_ISSUE[fate], nodeId: id, owner: ctx.owner, route: pn.href,
@@ -8212,7 +8918,7 @@ function composeNode(pn, id, repeater, ctx) {
8212
8918
  reportDangling(fate, pn, id, words.value, ctx);
8213
8919
  return null;
8214
8920
  }
8215
- const type = fate === DanglingFate.Unlink ? UNLINKED_TYPE[pn.t] : pn.t;
8921
+ const type = fate === DanglingFate.Unlink ? UNLINKED_TYPE[pn.t] ?? pn.t : pn.t;
8216
8922
  const props = {};
8217
8923
  if (pn.level)
8218
8924
  props['level'] = pn.level;
@@ -8263,6 +8969,13 @@ function composeNode(pn, id, repeater, ctx) {
8263
8969
  }
8264
8970
  if (pn.name)
8265
8971
  setProp(node, 'ariaLabel', pn.name);
8972
+ if (pn.icon) {
8973
+ if (type !== ICON)
8974
+ throw new ComposeError(`${id}: "icon" belongs on an Icon`);
8975
+ setProp(node, 'iconClass', pn.icon);
8976
+ }
8977
+ if (pn.layer)
8978
+ node.label = pn.layer;
8266
8979
  if (pn.opens) {
8267
8980
  if (pn.opens !== PatternOpens.Lightbox)
8268
8981
  throw new ComposeError(`${id}: "opens" names the pattern's lightbox`);
@@ -8313,13 +9026,9 @@ function composeNode(pn, id, repeater, ctx) {
8313
9026
  throw new ComposeError(`${id}: "alt" belongs on a bound Image`);
8314
9027
  }
8315
9028
  // Layout.
8316
- if (pn.lay)
8317
- setStyleProps(node, pn.lay);
8318
- if (pn.resp) {
8319
- for (const layer of Object.values(pn.resp))
8320
- assertStyleSlots(node.type, Object.keys(layer));
8321
- node.responsive = Object.fromEntries(Object.entries(pn.resp).map(([bp, styleProps]) => [bp, { styleProps: { ...styleProps } }]));
8322
- }
9029
+ applyLayout(node, pn);
9030
+ if (pn.shownWhen)
9031
+ hideUntilOn(node, pn, ctx);
8323
9032
  // A Repeater's rows.
8324
9033
  let rowScope = repeater;
8325
9034
  if (pn.src) {
@@ -8347,6 +9056,47 @@ function composeNode(pn, id, repeater, ctx) {
8347
9056
  composeForm(node, pn, id, ctx);
8348
9057
  return node;
8349
9058
  }
9059
+ /** A pattern node's layout: its `lay` styleProps and its per-breakpoint `resp` layers. */
9060
+ function applyLayout(node, pn) {
9061
+ if (pn.lay)
9062
+ setStyleProps(node, pn.lay);
9063
+ if (pn.resp) {
9064
+ for (const layer of Object.values(pn.resp))
9065
+ assertStyleSlots(node.type, Object.keys(layer));
9066
+ node.responsive = Object.fromEntries(Object.entries(pn.resp).map(([bp, styleProps]) => [bp, { styleProps: { ...styleProps } }]));
9067
+ }
9068
+ }
9069
+ /** CC4b (`shownWhen`, Q38): hidden at base and shown — with its own layout's display — while the pattern's Segmented
9070
+ * option of that key is on. Wired once the pattern is stamped (the option's id is known then). */
9071
+ function hideUntilOn(node, pn, ctx) {
9072
+ const display = String(node.styleProps['display'] ?? '') || SHOWN_DISPLAY;
9073
+ setStyleProps(node, { display: HIDDEN_DISPLAY });
9074
+ (ctx.shownWhen ??= []).push({ id: node.id, key: pn.shownWhen, display });
9075
+ }
9076
+ /** CC4b: every `shownWhen` node of a stamped pattern follows its option — the targeted `trigger-on` ("when Yearly is
9077
+ * on"), compiled by both renderers to ONE `:has()` rule on the nearest common ancestor. */
9078
+ function wireShownWhen(root, entries) {
9079
+ if (!entries.length)
9080
+ return;
9081
+ const nodes = new Map();
9082
+ const options = new Map();
9083
+ const visit = (n) => {
9084
+ nodes.set(n.id, n);
9085
+ for (const option of segmentedOptions(n))
9086
+ if (option.itemKey && !options.has(option.itemKey))
9087
+ options.set(option.itemKey, option.id);
9088
+ (n.children ?? []).forEach(visit);
9089
+ };
9090
+ visit(root);
9091
+ for (const entry of entries) {
9092
+ const option = options.get(entry.key);
9093
+ if (!option)
9094
+ throw new ComposeError(`${entry.id}: "shownWhen: ${entry.key}" names no option of a segmented in the pattern`);
9095
+ const node = nodes.get(entry.id);
9096
+ node.stateStyles = { ...(node.stateStyles ?? {}), [ITEM_OPEN_STATE]: { display: entry.display } };
9097
+ node.stateTriggers = { ...(node.stateTriggers ?? {}), [ITEM_OPEN_STATE]: option };
9098
+ }
9099
+ }
8350
9100
  /** A Card v2 `binds` key → the part it binds and that part's bound prop. */
8351
9101
  const CARD_BINDS = {
8352
9102
  [CardBindTarget.Image]: { role: CardRole.Media, prop: 'src' },
@@ -8368,6 +9118,8 @@ function composeRecipe(pn, id, repeater, ctx) {
8368
9118
  return composeCarousel(pn, id, ctx);
8369
9119
  if (pn.recipe === PatternRecipe.Lightbox)
8370
9120
  return composeLightbox(pn, id, repeater, ctx);
9121
+ if (pn.recipe === PatternRecipe.Segmented)
9122
+ return composeSegmented(pn, id);
8371
9123
  if (pn.recipe !== PatternRecipe.Card)
8372
9124
  throw new ComposeError(`${id}: no recipe "${pn.recipe}" in composite-core`);
8373
9125
  const layout = (pn.layout ?? CardLayout.Top);
@@ -8378,7 +9130,27 @@ function composeRecipe(pn, id, repeater, ctx) {
8378
9130
  throw new ComposeError(`${id}: a card has no part "${part}"`);
8379
9131
  }
8380
9132
  const factory = (spec) => create(spec.key === CardRole.Card ? id : `${id}-${spec.key}`, spec.type, { ...(spec.props ?? {}) }, spec.elementStyle ?? null);
8381
- const card = buildCardRecipe(factory, { layout, parts: pn.parts });
9133
+ const tone = pn.badge;
9134
+ if (tone && !BADGE_TONES.includes(tone))
9135
+ throw new ComposeError(`${id}: a badge has no tone "${pn.badge}"`);
9136
+ for (const key of Object.keys(pn.words ?? {}))
9137
+ if (!CARD_WORD_KEYS.includes(key))
9138
+ throw new ComposeError(`${id}: a card has no words "${key}"`);
9139
+ const card = buildCardRecipe(factory, {
9140
+ layout, parts: pn.parts, words: pn.words, badgeTone: tone,
9141
+ ...(pn.icon ? { badgeIcon: pn.icon } : {}),
9142
+ });
9143
+ if (pn.scheme) {
9144
+ if (!COLOR_SCHEMES.some(c => c.id === pn.scheme))
9145
+ throw new ComposeError(`${id}: no colour scheme "${pn.scheme}"`);
9146
+ setColorScheme(card, pn.scheme);
9147
+ }
9148
+ if (pn.ph === PatternPlaceholder.Copy)
9149
+ copyPlaceholders(card, ctx);
9150
+ if (pn.c?.length) {
9151
+ const content = findByRole(card, CardRole.Content);
9152
+ content.children = [...(content.children ?? []), ...composeChildren(pn, id, repeater, ctx)];
9153
+ }
8382
9154
  for (const [key, path] of Object.entries(pn.binds ?? {})) {
8383
9155
  const target = CARD_BINDS[key];
8384
9156
  if (!target)
@@ -8411,6 +9183,31 @@ function composeRecipe(pn, id, repeater, ctx) {
8411
9183
  return card;
8412
9184
  }
8413
9185
  const REPEATER = 'Repeater';
9186
+ const ICON = 'Icon';
9187
+ const SHOWN_DISPLAY = 'flex';
9188
+ const HIDDEN_DISPLAY = 'none';
9189
+ /** The words a card recipe's `words` may set (composite-core `CardWords`). */
9190
+ const CARD_WORD_KEYS = ['eyebrow', 'title', 'text', 'primary', 'secondary', 'badge'];
9191
+ /** A card's words the studio rewrites (`ph: 'copy'`): its eyebrow, title, text and badge. */
9192
+ const CARD_COPY_ROLES = [CardRole.Eyebrow, CardRole.Title, CardRole.Text];
9193
+ /** A card's own words, as COPY placeholders (its badge's words too). */
9194
+ function copyPlaceholders(card, ctx) {
9195
+ for (const role of CARD_COPY_ROLES) {
9196
+ const part = findByRole(card, role);
9197
+ if (part)
9198
+ ctx.placeholders.push({ nodeId: part.id, owner: ctx.owner, kind: PlaceholderKind.Copy, text: String(part.props?.['content'] ?? '') });
9199
+ }
9200
+ const badge = findByRole(card, CardRole.Badge);
9201
+ const words = badge?.children?.find(c => c.type === TEXT);
9202
+ if (words)
9203
+ ctx.placeholders.push({ nodeId: words.id, owner: ctx.owner, kind: PlaceholderKind.Copy, text: String(words.props?.['content'] ?? '') });
9204
+ }
9205
+ /** CC4b: the Segmented control — composite-core's recipe (Monthly · Yearly), named by the pattern, laid out by it. */
9206
+ function composeSegmented(pn, id) {
9207
+ const root = buildSegmentedRecipe(recipeFactory(id, 'segmented'), pn.name !== undefined ? { label: pn.name } : {});
9208
+ applyLayout(root, pn);
9209
+ return root;
9210
+ }
8414
9211
  /**
8415
9212
  * An Accordion (CC2) — the composite-core recipe stamped with this composer's factory. Manual (no section
8416
9213
  * binding): three items whose questions and answers are placeholders the studio rewrites (`ph: 'copy'`), never
@@ -8570,11 +9367,12 @@ function wireOpeners(root, openers) {
8570
9367
  function composePattern(pattern, id, ctx) {
8571
9368
  if (pattern.node.each)
8572
9369
  throw new ComposeError(`${id}: a pattern's root cannot be stamped per page`);
8573
- const own = { ...ctx, openers: [] };
9370
+ const own = { ...ctx, openers: [], shownWhen: [] };
8574
9371
  const node = composeNode(pattern.node, id, null, own);
8575
9372
  if (!node)
8576
9373
  throw new ComposeError(`${id}: a pattern's root cannot be optional or a link`);
8577
9374
  wireOpeners(node, own.openers ?? []);
9375
+ wireShownWhen(node, own.shownWhen ?? []);
8578
9376
  node.label = pattern.label;
8579
9377
  return node;
8580
9378
  }
@@ -8723,6 +9521,37 @@ function composeNavHeader(input, options) {
8723
9521
  const header = shape ? planNavShape([root], shape, { newId: options.newId }, root.id).globals[0] : root;
8724
9522
  return { header, issues };
8725
9523
  }
9524
+ // ── One pattern on its own (CC4b) ───────────────────────────────────────────────────────────────
9525
+ /** The pricing section (CC4b, board 10): plans with a Monthly / Yearly switch — the library and the palette, never a
9526
+ * Studio page (Q35). */
9527
+ const PRICING_PATTERN = 'pricing.tiers';
9528
+ /**
9529
+ * ONE library pattern composed on its own — the builder palette's ready-made sections (CC4b: "Pricing", the
9530
+ * `pricing.tiers` pattern). THE SAME pattern and composer as `composeSite`: its words, its placeholders (a price shows
9531
+ * its label, never a number) and the one dangling-link rule — except a button to a page the studio lacks keeps its
9532
+ * words, unlinked, for the author to link. Pure.
9533
+ */
9534
+ function composeSection(patternId, input, options) {
9535
+ if (!nonEmpty(options?.id))
9536
+ throw new ComposeError('composeSection needs the section id');
9537
+ const pattern = patternById(patternId);
9538
+ if (!pattern)
9539
+ throw new ComposeError(`no pattern "${patternId}" in the library`);
9540
+ if (pattern.global)
9541
+ throw new ComposeError(`"${patternId}" is a header or footer — composeNavHeader / composeSite stamp those`);
9542
+ const business = input.business ?? { name: '' };
9543
+ const pages = navPagePlans(input.pages ?? []);
9544
+ const plan = { business, pages, dataSources: [], contentTypes: [] };
9545
+ const email = nonEmpty(business.facts?.email) ? business.facts.email.trim() : null;
9546
+ const placeholders = [];
9547
+ const issues = [];
9548
+ const ctx = {
9549
+ owner: options.id, page: null, section: null, plan, year: 0, email, navPage: null, nextAlias: null,
9550
+ placeholders, issues, routes: new Set(pages.map(p => p.route)), keepButtons: true,
9551
+ };
9552
+ const section = composePattern(pattern, options.id, ctx);
9553
+ return { section, placeholders, issues };
9554
+ }
8726
9555
 
8727
9556
  /**
8728
9557
  * @vectoriox/iox-ui/generation-core — the shared, FRAMEWORK-FREE site-plan core (design-system plan
@@ -8740,5 +9569,5 @@ function composeNavHeader(input, options) {
8740
9569
  * Generated bundle index. Do not edit.
8741
9570
  */
8742
9571
 
8743
- 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, NavPagesSource, NavRole, NavShape, NavShapeError, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanDataSourceMode, PlanDataSourceType, RelativeOp, SAMPLE_IMAGE_REF, SITE_FACT_LABELS, SITE_HEADER_PATTERN, 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, composeNavHeader, composeSite, createSerializedNode, findNavRoot, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, parseSampleImageRef, patternById, patternNeedsBinding, patternNodes, patternOptionalParts, patternScopes, patternSlots, patternTakesBinding, phoneMenuPages, planFromTemplate, planNavShape, releasedLayoutDefaults, removeBarItem, requiredShapeKeys, routeParams, sampleImageRef, setStyleProps, shapeKeys, siteNavPages, validateSitePlan, walkSerialized };
9572
+ 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, NavPagesSource, NavRole, NavShape, NavShapeError, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanDataSourceMode, PlanDataSourceType, RelativeOp, SAMPLE_IMAGE_REF, SITE_FACT_LABELS, SITE_HEADER_PATTERN, 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, blocksPublish, composeNavHeader, composeSection, composeSite, createSerializedNode, findNavRoot, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, parseSampleImageRef, patternById, patternNeedsBinding, patternNodes, patternOptionalParts, patternScopes, patternSlots, patternTakesBinding, phoneMenuPages, planFromTemplate, planNavShape, releasedLayoutDefaults, removeBarItem, requiredShapeKeys, routeParams, sampleImageRef, setStyleProps, shapeKeys, siteNavPages, validateSitePlan, walkSerialized };
8744
9573
  //# sourceMappingURL=vectoriox-iox-ui-generation-core.mjs.map