@vectoriox/iox-ui 5.40.0 → 5.41.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 (31) hide show
  1. package/composite-core/index.d.ts +210 -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 +535 -121
  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 +801 -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 +563 -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/composite-kinds.ts +42 -6
  19. package/src/composite-core/exclusive-runtime.ts +60 -10
  20. package/src/composite-core/exclusive.ts +64 -0
  21. package/src/composite-core/public-api.ts +5 -2
  22. package/src/composite-core/segmented.ts +349 -0
  23. package/src/composite-core/structure.ts +6 -1
  24. package/src/composite-core/tabs.ts +6 -3
  25. package/src/design-core/contrast-audit.ts +8 -3
  26. package/src/design-core/flavor-spec.generated.ts +832 -41
  27. package/src/generation-core/compose-site.ts +169 -12
  28. package/src/generation-core/node-baselines.generated.ts +49 -0
  29. package/src/generation-core/patterns.ts +20 -0
  30. package/src/generation-core/site-spec.generated.ts +595 -0
  31. 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,601 @@ 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
+ },
1055
+ {
1056
+ "t": "Heading",
1057
+ "es": "h2",
1058
+ "level": "h2",
1059
+ "slot": "title",
1060
+ "ph": "copy",
1061
+ "text": "Plans"
1062
+ }
1063
+ ]
1064
+ },
1065
+ {
1066
+ "t": "Container",
1067
+ "recipe": "segmented",
1068
+ "name": "Billing period",
1069
+ "lay": {
1070
+ "alignSelf": "center"
1071
+ },
1072
+ "resp": {
1073
+ "mobile": {
1074
+ "position": "sticky",
1075
+ "top": "calc(12px + env(safe-area-inset-top, 0px))",
1076
+ "zIndex": "2"
1077
+ }
1078
+ }
1079
+ },
1080
+ {
1081
+ "t": "Container",
1082
+ "es": "box",
1083
+ "layer": "Plans",
1084
+ "lay": {
1085
+ "display": "grid",
1086
+ "gridTemplateColumns": "repeat(3, minmax(0, 1fr))",
1087
+ "gap": "var(--iox-space-gap)",
1088
+ "alignItems": "stretch"
1089
+ },
1090
+ "resp": {
1091
+ "mobile": {
1092
+ "gridTemplateColumns": "minmax(0, 1fr)"
1093
+ }
1094
+ },
1095
+ "c": [
1096
+ {
1097
+ "t": "Container",
1098
+ "recipe": "card",
1099
+ "layout": "top",
1100
+ "ph": "copy",
1101
+ "parts": {
1102
+ "media": false,
1103
+ "eyebrow": false,
1104
+ "badge": false,
1105
+ "actions": false
1106
+ },
1107
+ "words": {
1108
+ "title": "First plan",
1109
+ "text": "Who this plan is for, in one sentence."
1110
+ },
1111
+ "c": [
1112
+ {
1113
+ "t": "Container",
1114
+ "es": "box",
1115
+ "layer": "Price · Monthly",
1116
+ "shownWhen": "monthly",
1117
+ "lay": {
1118
+ "display": "flex",
1119
+ "alignItems": "baseline",
1120
+ "flexWrap": "wrap",
1121
+ "gap": "6px"
1122
+ },
1123
+ "c": [
1124
+ {
1125
+ "t": "Text",
1126
+ "es": "price",
1127
+ "ph": "price",
1128
+ "text": "Monthly price"
1129
+ },
1130
+ {
1131
+ "t": "Text",
1132
+ "es": "small",
1133
+ "text": "per month"
1134
+ }
1135
+ ]
1136
+ },
1137
+ {
1138
+ "t": "Container",
1139
+ "es": "box",
1140
+ "layer": "Price · Yearly",
1141
+ "shownWhen": "yearly",
1142
+ "lay": {
1143
+ "display": "flex",
1144
+ "alignItems": "baseline",
1145
+ "flexWrap": "wrap",
1146
+ "gap": "6px"
1147
+ },
1148
+ "c": [
1149
+ {
1150
+ "t": "Text",
1151
+ "es": "price",
1152
+ "ph": "price",
1153
+ "text": "Yearly price"
1154
+ },
1155
+ {
1156
+ "t": "Text",
1157
+ "es": "small",
1158
+ "text": "per year"
1159
+ }
1160
+ ]
1161
+ },
1162
+ {
1163
+ "t": "Container",
1164
+ "es": "box",
1165
+ "layer": "Includes",
1166
+ "lay": {
1167
+ "display": "flex",
1168
+ "flexDirection": "column",
1169
+ "gap": "8px"
1170
+ },
1171
+ "c": [
1172
+ {
1173
+ "t": "Container",
1174
+ "es": "box",
1175
+ "lay": {
1176
+ "display": "flex",
1177
+ "flexWrap": "nowrap",
1178
+ "gap": "8px",
1179
+ "alignItems": "flex-start"
1180
+ },
1181
+ "c": [
1182
+ {
1183
+ "t": "Icon",
1184
+ "es": "icon",
1185
+ "icon": "ph ph-check"
1186
+ },
1187
+ {
1188
+ "t": "Text",
1189
+ "es": "body",
1190
+ "ph": "copy",
1191
+ "text": "What this plan includes"
1192
+ }
1193
+ ]
1194
+ },
1195
+ {
1196
+ "t": "Container",
1197
+ "es": "box",
1198
+ "lay": {
1199
+ "display": "flex",
1200
+ "flexWrap": "nowrap",
1201
+ "gap": "8px",
1202
+ "alignItems": "flex-start"
1203
+ },
1204
+ "c": [
1205
+ {
1206
+ "t": "Icon",
1207
+ "es": "icon",
1208
+ "icon": "ph ph-check"
1209
+ },
1210
+ {
1211
+ "t": "Text",
1212
+ "es": "body",
1213
+ "ph": "copy",
1214
+ "text": "What this plan includes"
1215
+ }
1216
+ ]
1217
+ },
1218
+ {
1219
+ "t": "Container",
1220
+ "es": "box",
1221
+ "lay": {
1222
+ "display": "flex",
1223
+ "flexWrap": "nowrap",
1224
+ "gap": "8px",
1225
+ "alignItems": "flex-start"
1226
+ },
1227
+ "c": [
1228
+ {
1229
+ "t": "Icon",
1230
+ "es": "icon",
1231
+ "icon": "ph ph-check"
1232
+ },
1233
+ {
1234
+ "t": "Text",
1235
+ "es": "body",
1236
+ "ph": "copy",
1237
+ "text": "What this plan includes"
1238
+ }
1239
+ ]
1240
+ }
1241
+ ]
1242
+ },
1243
+ {
1244
+ "t": "Container",
1245
+ "es": "box",
1246
+ "role": "card.actions",
1247
+ "layer": "Buttons",
1248
+ "lay": {
1249
+ "display": "flex",
1250
+ "flexWrap": "wrap",
1251
+ "gap": "8px",
1252
+ "alignItems": "center",
1253
+ "width": "100%",
1254
+ "margin": "auto 0px 0px 0px",
1255
+ "padding": "6px 0px 0px 0px"
1256
+ },
1257
+ "c": [
1258
+ {
1259
+ "t": "ButtonBlock",
1260
+ "es": "button-primary",
1261
+ "href": "/contact",
1262
+ "text": "Choose this plan"
1263
+ }
1264
+ ]
1265
+ }
1266
+ ]
1267
+ },
1268
+ {
1269
+ "t": "Container",
1270
+ "recipe": "card",
1271
+ "layout": "top",
1272
+ "ph": "copy",
1273
+ "scheme": "accent",
1274
+ "badge": "neutral",
1275
+ "parts": {
1276
+ "media": false,
1277
+ "eyebrow": false,
1278
+ "badge": true,
1279
+ "actions": false
1280
+ },
1281
+ "words": {
1282
+ "title": "Second plan",
1283
+ "text": "Who this plan is for, in one sentence.",
1284
+ "badge": "Most popular"
1285
+ },
1286
+ "c": [
1287
+ {
1288
+ "t": "Container",
1289
+ "es": "box",
1290
+ "layer": "Price · Monthly",
1291
+ "shownWhen": "monthly",
1292
+ "lay": {
1293
+ "display": "flex",
1294
+ "alignItems": "baseline",
1295
+ "flexWrap": "wrap",
1296
+ "gap": "6px"
1297
+ },
1298
+ "c": [
1299
+ {
1300
+ "t": "Text",
1301
+ "es": "price",
1302
+ "ph": "price",
1303
+ "text": "Monthly price"
1304
+ },
1305
+ {
1306
+ "t": "Text",
1307
+ "es": "small",
1308
+ "text": "per month"
1309
+ }
1310
+ ]
1311
+ },
1312
+ {
1313
+ "t": "Container",
1314
+ "es": "box",
1315
+ "layer": "Price · Yearly",
1316
+ "shownWhen": "yearly",
1317
+ "lay": {
1318
+ "display": "flex",
1319
+ "alignItems": "baseline",
1320
+ "flexWrap": "wrap",
1321
+ "gap": "6px"
1322
+ },
1323
+ "c": [
1324
+ {
1325
+ "t": "Text",
1326
+ "es": "price",
1327
+ "ph": "price",
1328
+ "text": "Yearly price"
1329
+ },
1330
+ {
1331
+ "t": "Text",
1332
+ "es": "small",
1333
+ "text": "per year"
1334
+ }
1335
+ ]
1336
+ },
1337
+ {
1338
+ "t": "Container",
1339
+ "es": "box",
1340
+ "layer": "Includes",
1341
+ "lay": {
1342
+ "display": "flex",
1343
+ "flexDirection": "column",
1344
+ "gap": "8px"
1345
+ },
1346
+ "c": [
1347
+ {
1348
+ "t": "Container",
1349
+ "es": "box",
1350
+ "lay": {
1351
+ "display": "flex",
1352
+ "flexWrap": "nowrap",
1353
+ "gap": "8px",
1354
+ "alignItems": "flex-start"
1355
+ },
1356
+ "c": [
1357
+ {
1358
+ "t": "Icon",
1359
+ "es": "icon",
1360
+ "icon": "ph ph-check"
1361
+ },
1362
+ {
1363
+ "t": "Text",
1364
+ "es": "body",
1365
+ "ph": "copy",
1366
+ "text": "What this plan includes"
1367
+ }
1368
+ ]
1369
+ },
1370
+ {
1371
+ "t": "Container",
1372
+ "es": "box",
1373
+ "lay": {
1374
+ "display": "flex",
1375
+ "flexWrap": "nowrap",
1376
+ "gap": "8px",
1377
+ "alignItems": "flex-start"
1378
+ },
1379
+ "c": [
1380
+ {
1381
+ "t": "Icon",
1382
+ "es": "icon",
1383
+ "icon": "ph ph-check"
1384
+ },
1385
+ {
1386
+ "t": "Text",
1387
+ "es": "body",
1388
+ "ph": "copy",
1389
+ "text": "What this plan includes"
1390
+ }
1391
+ ]
1392
+ },
1393
+ {
1394
+ "t": "Container",
1395
+ "es": "box",
1396
+ "lay": {
1397
+ "display": "flex",
1398
+ "flexWrap": "nowrap",
1399
+ "gap": "8px",
1400
+ "alignItems": "flex-start"
1401
+ },
1402
+ "c": [
1403
+ {
1404
+ "t": "Icon",
1405
+ "es": "icon",
1406
+ "icon": "ph ph-check"
1407
+ },
1408
+ {
1409
+ "t": "Text",
1410
+ "es": "body",
1411
+ "ph": "copy",
1412
+ "text": "What this plan includes"
1413
+ }
1414
+ ]
1415
+ }
1416
+ ]
1417
+ },
1418
+ {
1419
+ "t": "Container",
1420
+ "es": "box",
1421
+ "role": "card.actions",
1422
+ "layer": "Buttons",
1423
+ "lay": {
1424
+ "display": "flex",
1425
+ "flexWrap": "wrap",
1426
+ "gap": "8px",
1427
+ "alignItems": "center",
1428
+ "width": "100%",
1429
+ "margin": "auto 0px 0px 0px",
1430
+ "padding": "6px 0px 0px 0px"
1431
+ },
1432
+ "c": [
1433
+ {
1434
+ "t": "ButtonBlock",
1435
+ "es": "button-primary",
1436
+ "href": "/contact",
1437
+ "text": "Choose this plan"
1438
+ }
1439
+ ]
1440
+ }
1441
+ ]
1442
+ },
1443
+ {
1444
+ "t": "Container",
1445
+ "recipe": "card",
1446
+ "layout": "top",
1447
+ "ph": "copy",
1448
+ "parts": {
1449
+ "media": false,
1450
+ "eyebrow": false,
1451
+ "badge": false,
1452
+ "actions": false
1453
+ },
1454
+ "words": {
1455
+ "title": "Third plan",
1456
+ "text": "Who this plan is for, in one sentence."
1457
+ },
1458
+ "c": [
1459
+ {
1460
+ "t": "Container",
1461
+ "es": "box",
1462
+ "layer": "Price · Monthly",
1463
+ "shownWhen": "monthly",
1464
+ "lay": {
1465
+ "display": "flex",
1466
+ "alignItems": "baseline",
1467
+ "flexWrap": "wrap",
1468
+ "gap": "6px"
1469
+ },
1470
+ "c": [
1471
+ {
1472
+ "t": "Text",
1473
+ "es": "price",
1474
+ "ph": "price",
1475
+ "text": "Monthly price"
1476
+ },
1477
+ {
1478
+ "t": "Text",
1479
+ "es": "small",
1480
+ "text": "per month"
1481
+ }
1482
+ ]
1483
+ },
1484
+ {
1485
+ "t": "Container",
1486
+ "es": "box",
1487
+ "layer": "Price · Yearly",
1488
+ "shownWhen": "yearly",
1489
+ "lay": {
1490
+ "display": "flex",
1491
+ "alignItems": "baseline",
1492
+ "flexWrap": "wrap",
1493
+ "gap": "6px"
1494
+ },
1495
+ "c": [
1496
+ {
1497
+ "t": "Text",
1498
+ "es": "price",
1499
+ "ph": "price",
1500
+ "text": "Yearly price"
1501
+ },
1502
+ {
1503
+ "t": "Text",
1504
+ "es": "small",
1505
+ "text": "per year"
1506
+ }
1507
+ ]
1508
+ },
1509
+ {
1510
+ "t": "Container",
1511
+ "es": "box",
1512
+ "layer": "Includes",
1513
+ "lay": {
1514
+ "display": "flex",
1515
+ "flexDirection": "column",
1516
+ "gap": "8px"
1517
+ },
1518
+ "c": [
1519
+ {
1520
+ "t": "Container",
1521
+ "es": "box",
1522
+ "lay": {
1523
+ "display": "flex",
1524
+ "flexWrap": "nowrap",
1525
+ "gap": "8px",
1526
+ "alignItems": "flex-start"
1527
+ },
1528
+ "c": [
1529
+ {
1530
+ "t": "Icon",
1531
+ "es": "icon",
1532
+ "icon": "ph ph-check"
1533
+ },
1534
+ {
1535
+ "t": "Text",
1536
+ "es": "body",
1537
+ "ph": "copy",
1538
+ "text": "What this plan includes"
1539
+ }
1540
+ ]
1541
+ },
1542
+ {
1543
+ "t": "Container",
1544
+ "es": "box",
1545
+ "lay": {
1546
+ "display": "flex",
1547
+ "flexWrap": "nowrap",
1548
+ "gap": "8px",
1549
+ "alignItems": "flex-start"
1550
+ },
1551
+ "c": [
1552
+ {
1553
+ "t": "Icon",
1554
+ "es": "icon",
1555
+ "icon": "ph ph-check"
1556
+ },
1557
+ {
1558
+ "t": "Text",
1559
+ "es": "body",
1560
+ "ph": "copy",
1561
+ "text": "What this plan includes"
1562
+ }
1563
+ ]
1564
+ },
1565
+ {
1566
+ "t": "Container",
1567
+ "es": "box",
1568
+ "lay": {
1569
+ "display": "flex",
1570
+ "flexWrap": "nowrap",
1571
+ "gap": "8px",
1572
+ "alignItems": "flex-start"
1573
+ },
1574
+ "c": [
1575
+ {
1576
+ "t": "Icon",
1577
+ "es": "icon",
1578
+ "icon": "ph ph-check"
1579
+ },
1580
+ {
1581
+ "t": "Text",
1582
+ "es": "body",
1583
+ "ph": "copy",
1584
+ "text": "What this plan includes"
1585
+ }
1586
+ ]
1587
+ }
1588
+ ]
1589
+ },
1590
+ {
1591
+ "t": "Container",
1592
+ "es": "box",
1593
+ "role": "card.actions",
1594
+ "layer": "Buttons",
1595
+ "lay": {
1596
+ "display": "flex",
1597
+ "flexWrap": "wrap",
1598
+ "gap": "8px",
1599
+ "alignItems": "center",
1600
+ "width": "100%",
1601
+ "margin": "auto 0px 0px 0px",
1602
+ "padding": "6px 0px 0px 0px"
1603
+ },
1604
+ "c": [
1605
+ {
1606
+ "t": "ButtonBlock",
1607
+ "es": "button-primary",
1608
+ "href": "/contact",
1609
+ "text": "Choose this plan"
1610
+ }
1611
+ ]
1612
+ }
1613
+ ]
1614
+ }
1615
+ ]
1616
+ }
1617
+ ],
1618
+ "lay": {
1619
+ "display": "flex",
1620
+ "flexDirection": "column",
1621
+ "gap": "32px"
1622
+ }
1623
+ }
1624
+ },
1030
1625
  "hero.full-bleed-media": {
1031
1626
  "family": "hero",
1032
1627
  "label": "Hero — words over a background video",
@@ -1463,6 +2058,7 @@ const NODE_BASELINES = {
1463
2058
  "textAlign": "start",
1464
2059
  "fontStyle": "normal",
1465
2060
  "textDecoration": "none",
2061
+ "fontVariantNumeric": "normal",
1466
2062
  "WebkitTextStrokeWidth": "0px",
1467
2063
  "WebkitTextStrokeColor": "transparent",
1468
2064
  "margin": "0px 0px 0px 0px",
@@ -1552,6 +2148,7 @@ const NODE_BASELINES = {
1552
2148
  "textAlign",
1553
2149
  "fontStyle",
1554
2150
  "textDecoration",
2151
+ "fontVariantNumeric",
1555
2152
  "_sep_stroke",
1556
2153
  "WebkitTextStrokeWidth",
1557
2154
  "WebkitTextStrokeColor",
@@ -1654,6 +2251,7 @@ const NODE_BASELINES = {
1654
2251
  "textAlign": "start",
1655
2252
  "fontStyle": "normal",
1656
2253
  "textDecoration": "none",
2254
+ "fontVariantNumeric": "normal",
1657
2255
  "WebkitTextStrokeWidth": "0px",
1658
2256
  "WebkitTextStrokeColor": "transparent",
1659
2257
  "margin": "0px 0px 0px 0px",
@@ -1748,6 +2346,7 @@ const NODE_BASELINES = {
1748
2346
  "textAlign",
1749
2347
  "fontStyle",
1750
2348
  "textDecoration",
2349
+ "fontVariantNumeric",
1751
2350
  "_sep_stroke",
1752
2351
  "WebkitTextStrokeWidth",
1753
2352
  "WebkitTextStrokeColor",
@@ -1846,6 +2445,7 @@ const NODE_BASELINES = {
1846
2445
  "textAlign": "start",
1847
2446
  "fontStyle": "normal",
1848
2447
  "textDecoration": "none",
2448
+ "fontVariantNumeric": "normal",
1849
2449
  "WebkitTextStrokeWidth": "0px",
1850
2450
  "WebkitTextStrokeColor": "transparent",
1851
2451
  "margin": "0px 0px 0px 0px",
@@ -1935,6 +2535,7 @@ const NODE_BASELINES = {
1935
2535
  "textAlign",
1936
2536
  "fontStyle",
1937
2537
  "textDecoration",
2538
+ "fontVariantNumeric",
1938
2539
  "_sep_stroke",
1939
2540
  "WebkitTextStrokeWidth",
1940
2541
  "WebkitTextStrokeColor",
@@ -2032,6 +2633,7 @@ const NODE_BASELINES = {
2032
2633
  "textAlign": "start",
2033
2634
  "fontStyle": "normal",
2034
2635
  "textDecoration": "none",
2636
+ "fontVariantNumeric": "normal",
2035
2637
  "WebkitTextStrokeWidth": "0px",
2036
2638
  "WebkitTextStrokeColor": "transparent",
2037
2639
  "margin": "0px 0px 0px 0px",
@@ -2125,6 +2727,7 @@ const NODE_BASELINES = {
2125
2727
  "textAlign",
2126
2728
  "fontStyle",
2127
2729
  "textDecoration",
2730
+ "fontVariantNumeric",
2128
2731
  "_sep_stroke",
2129
2732
  "WebkitTextStrokeWidth",
2130
2733
  "WebkitTextStrokeColor",
@@ -2226,6 +2829,7 @@ const NODE_BASELINES = {
2226
2829
  "textAlign": "start",
2227
2830
  "fontStyle": "normal",
2228
2831
  "textDecoration": "none",
2832
+ "fontVariantNumeric": "normal",
2229
2833
  "WebkitTextStrokeWidth": "0px",
2230
2834
  "WebkitTextStrokeColor": "transparent",
2231
2835
  "maxLines": "none",
@@ -2319,6 +2923,7 @@ const NODE_BASELINES = {
2319
2923
  "textAlign",
2320
2924
  "fontStyle",
2321
2925
  "textDecoration",
2926
+ "fontVariantNumeric",
2322
2927
  "_sep_stroke",
2323
2928
  "WebkitTextStrokeWidth",
2324
2929
  "WebkitTextStrokeColor",
@@ -2417,6 +3022,7 @@ const NODE_BASELINES = {
2417
3022
  "textAlign": "start",
2418
3023
  "fontStyle": "normal",
2419
3024
  "textDecoration": "none",
3025
+ "fontVariantNumeric": "normal",
2420
3026
  "WebkitTextStrokeWidth": "0px",
2421
3027
  "WebkitTextStrokeColor": "transparent",
2422
3028
  "maxLines": "none",
@@ -2506,6 +3112,7 @@ const NODE_BASELINES = {
2506
3112
  "textAlign",
2507
3113
  "fontStyle",
2508
3114
  "textDecoration",
3115
+ "fontVariantNumeric",
2509
3116
  "_sep_stroke",
2510
3117
  "WebkitTextStrokeWidth",
2511
3118
  "WebkitTextStrokeColor",
@@ -2604,6 +3211,7 @@ const NODE_BASELINES = {
2604
3211
  "textAlign": "start",
2605
3212
  "fontStyle": "normal",
2606
3213
  "textDecoration": "none",
3214
+ "fontVariantNumeric": "normal",
2607
3215
  "WebkitTextStrokeWidth": "0px",
2608
3216
  "WebkitTextStrokeColor": "transparent",
2609
3217
  "margin": "0px 0px 0px 0px",
@@ -2692,6 +3300,7 @@ const NODE_BASELINES = {
2692
3300
  "textAlign",
2693
3301
  "fontStyle",
2694
3302
  "textDecoration",
3303
+ "fontVariantNumeric",
2695
3304
  "_sep_stroke",
2696
3305
  "WebkitTextStrokeWidth",
2697
3306
  "WebkitTextStrokeColor",
@@ -2793,6 +3402,7 @@ const NODE_BASELINES = {
2793
3402
  "textAlign": "start",
2794
3403
  "fontStyle": "normal",
2795
3404
  "textDecoration": "none",
3405
+ "fontVariantNumeric": "normal",
2796
3406
  "WebkitTextStrokeWidth": "0px",
2797
3407
  "WebkitTextStrokeColor": "transparent",
2798
3408
  "margin": "0px 0px 0px 0px",
@@ -2886,6 +3496,7 @@ const NODE_BASELINES = {
2886
3496
  "textAlign",
2887
3497
  "fontStyle",
2888
3498
  "textDecoration",
3499
+ "fontVariantNumeric",
2889
3500
  "_sep_stroke",
2890
3501
  "WebkitTextStrokeWidth",
2891
3502
  "WebkitTextStrokeColor",
@@ -2987,6 +3598,7 @@ const NODE_BASELINES = {
2987
3598
  "textAlign": "start",
2988
3599
  "fontStyle": "normal",
2989
3600
  "textDecoration": "none",
3601
+ "fontVariantNumeric": "normal",
2990
3602
  "WebkitTextStrokeWidth": "0px",
2991
3603
  "WebkitTextStrokeColor": "transparent",
2992
3604
  "margin": "0px 0px 0px 0px",
@@ -3080,6 +3692,7 @@ const NODE_BASELINES = {
3080
3692
  "textAlign",
3081
3693
  "fontStyle",
3082
3694
  "textDecoration",
3695
+ "fontVariantNumeric",
3083
3696
  "_sep_stroke",
3084
3697
  "WebkitTextStrokeWidth",
3085
3698
  "WebkitTextStrokeColor",
@@ -3176,6 +3789,7 @@ const NODE_BASELINES = {
3176
3789
  "textAlign": "start",
3177
3790
  "fontStyle": "normal",
3178
3791
  "textDecoration": "none",
3792
+ "fontVariantNumeric": "normal",
3179
3793
  "WebkitTextStrokeWidth": "0px",
3180
3794
  "WebkitTextStrokeColor": "transparent",
3181
3795
  "margin": "0px 0px 0px 0px",
@@ -3263,6 +3877,7 @@ const NODE_BASELINES = {
3263
3877
  "textAlign",
3264
3878
  "fontStyle",
3265
3879
  "textDecoration",
3880
+ "fontVariantNumeric",
3266
3881
  "_sep_stroke",
3267
3882
  "WebkitTextStrokeWidth",
3268
3883
  "WebkitTextStrokeColor",
@@ -3359,6 +3974,7 @@ const NODE_BASELINES = {
3359
3974
  "textAlign": "start",
3360
3975
  "fontStyle": "normal",
3361
3976
  "textDecoration": "none",
3977
+ "fontVariantNumeric": "normal",
3362
3978
  "WebkitTextStrokeWidth": "0px",
3363
3979
  "WebkitTextStrokeColor": "transparent",
3364
3980
  "margin": "0px 0px 0px 0px",
@@ -3446,6 +4062,7 @@ const NODE_BASELINES = {
3446
4062
  "textAlign",
3447
4063
  "fontStyle",
3448
4064
  "textDecoration",
4065
+ "fontVariantNumeric",
3449
4066
  "_sep_stroke",
3450
4067
  "WebkitTextStrokeWidth",
3451
4068
  "WebkitTextStrokeColor",
@@ -3540,6 +4157,7 @@ const NODE_BASELINES = {
3540
4157
  "textAlign": "start",
3541
4158
  "fontStyle": "normal",
3542
4159
  "textDecoration": "none",
4160
+ "fontVariantNumeric": "normal",
3543
4161
  "WebkitTextStrokeWidth": "0px",
3544
4162
  "WebkitTextStrokeColor": "transparent",
3545
4163
  "margin": "8px 0px 8px 0px",
@@ -3625,6 +4243,7 @@ const NODE_BASELINES = {
3625
4243
  "textAlign",
3626
4244
  "fontStyle",
3627
4245
  "textDecoration",
4246
+ "fontVariantNumeric",
3628
4247
  "_sep_stroke",
3629
4248
  "WebkitTextStrokeWidth",
3630
4249
  "WebkitTextStrokeColor",
@@ -3719,6 +4338,7 @@ const NODE_BASELINES = {
3719
4338
  "textAlign": "start",
3720
4339
  "fontStyle": "normal",
3721
4340
  "textDecoration": "none",
4341
+ "fontVariantNumeric": "normal",
3722
4342
  "WebkitTextStrokeWidth": "0px",
3723
4343
  "WebkitTextStrokeColor": "transparent",
3724
4344
  "margin": "0px 0px 0px 0px",
@@ -3804,6 +4424,7 @@ const NODE_BASELINES = {
3804
4424
  "textAlign",
3805
4425
  "fontStyle",
3806
4426
  "textDecoration",
4427
+ "fontVariantNumeric",
3807
4428
  "_sep_stroke",
3808
4429
  "WebkitTextStrokeWidth",
3809
4430
  "WebkitTextStrokeColor",
@@ -3907,6 +4528,7 @@ const NODE_BASELINES = {
3907
4528
  "textAlign": "start",
3908
4529
  "fontStyle": "normal",
3909
4530
  "textDecoration": "none",
4531
+ "fontVariantNumeric": "normal",
3910
4532
  "WebkitTextStrokeWidth": "0px",
3911
4533
  "WebkitTextStrokeColor": "transparent",
3912
4534
  "opacity": "1",
@@ -3995,6 +4617,7 @@ const NODE_BASELINES = {
3995
4617
  "textAlign",
3996
4618
  "fontStyle",
3997
4619
  "textDecoration",
4620
+ "fontVariantNumeric",
3998
4621
  "_sep_stroke",
3999
4622
  "WebkitTextStrokeWidth",
4000
4623
  "WebkitTextStrokeColor",
@@ -4084,6 +4707,7 @@ const NODE_BASELINES = {
4084
4707
  "textAlign": "start",
4085
4708
  "fontStyle": "normal",
4086
4709
  "textDecoration": "none",
4710
+ "fontVariantNumeric": "normal",
4087
4711
  "WebkitTextStrokeWidth": "0px",
4088
4712
  "WebkitTextStrokeColor": "transparent",
4089
4713
  "margin": "0px 0px 0px 0px",
@@ -4171,6 +4795,7 @@ const NODE_BASELINES = {
4171
4795
  "textAlign",
4172
4796
  "fontStyle",
4173
4797
  "textDecoration",
4798
+ "fontVariantNumeric",
4174
4799
  "_sep_stroke",
4175
4800
  "WebkitTextStrokeWidth",
4176
4801
  "WebkitTextStrokeColor",
@@ -4268,6 +4893,7 @@ const NODE_BASELINES = {
4268
4893
  "textAlign": "start",
4269
4894
  "fontStyle": "normal",
4270
4895
  "textDecoration": "none",
4896
+ "fontVariantNumeric": "normal",
4271
4897
  "WebkitTextStrokeWidth": "0px",
4272
4898
  "WebkitTextStrokeColor": "transparent",
4273
4899
  "margin": "0px 0px 0px 0px",
@@ -4361,6 +4987,7 @@ const NODE_BASELINES = {
4361
4987
  "textAlign",
4362
4988
  "fontStyle",
4363
4989
  "textDecoration",
4990
+ "fontVariantNumeric",
4364
4991
  "_sep_stroke",
4365
4992
  "WebkitTextStrokeWidth",
4366
4993
  "WebkitTextStrokeColor",
@@ -4678,6 +5305,7 @@ const NODE_BASELINES = {
4678
5305
  "textAlign": "start",
4679
5306
  "fontStyle": "normal",
4680
5307
  "textDecoration": "none",
5308
+ "fontVariantNumeric": "normal",
4681
5309
  "WebkitTextStrokeWidth": "0px",
4682
5310
  "WebkitTextStrokeColor": "transparent",
4683
5311
  "opacity": "1",
@@ -4755,6 +5383,7 @@ const NODE_BASELINES = {
4755
5383
  "textAlign",
4756
5384
  "fontStyle",
4757
5385
  "textDecoration",
5386
+ "fontVariantNumeric",
4758
5387
  "_sep_stroke",
4759
5388
  "WebkitTextStrokeWidth",
4760
5389
  "WebkitTextStrokeColor",
@@ -4988,6 +5617,7 @@ const NODE_BASELINES = {
4988
5617
  "textAlign": "start",
4989
5618
  "fontStyle": "normal",
4990
5619
  "textDecoration": "none",
5620
+ "fontVariantNumeric": "normal",
4991
5621
  "WebkitTextStrokeWidth": "0px",
4992
5622
  "WebkitTextStrokeColor": "transparent",
4993
5623
  "opacity": "1",
@@ -5081,6 +5711,7 @@ const NODE_BASELINES = {
5081
5711
  "textAlign",
5082
5712
  "fontStyle",
5083
5713
  "textDecoration",
5714
+ "fontVariantNumeric",
5084
5715
  "_sep_stroke",
5085
5716
  "WebkitTextStrokeWidth",
5086
5717
  "WebkitTextStrokeColor",
@@ -5183,6 +5814,7 @@ const NODE_BASELINES = {
5183
5814
  "textAlign": "start",
5184
5815
  "fontStyle": "normal",
5185
5816
  "textDecoration": "none",
5817
+ "fontVariantNumeric": "normal",
5186
5818
  "WebkitTextStrokeWidth": "0px",
5187
5819
  "WebkitTextStrokeColor": "transparent",
5188
5820
  "margin": "0px 0px 0px 0px",
@@ -5286,6 +5918,7 @@ const NODE_BASELINES = {
5286
5918
  "textAlign",
5287
5919
  "fontStyle",
5288
5920
  "textDecoration",
5921
+ "fontVariantNumeric",
5289
5922
  "_sep_stroke",
5290
5923
  "WebkitTextStrokeWidth",
5291
5924
  "WebkitTextStrokeColor",
@@ -5382,6 +6015,7 @@ const NODE_BASELINES = {
5382
6015
  "textAlign": "start",
5383
6016
  "fontStyle": "normal",
5384
6017
  "textDecoration": "none",
6018
+ "fontVariantNumeric": "normal",
5385
6019
  "WebkitTextStrokeWidth": "0px",
5386
6020
  "WebkitTextStrokeColor": "transparent",
5387
6021
  "margin": "0px 0px 0px 0px",
@@ -5469,6 +6103,7 @@ const NODE_BASELINES = {
5469
6103
  "textAlign",
5470
6104
  "fontStyle",
5471
6105
  "textDecoration",
6106
+ "fontVariantNumeric",
5472
6107
  "_sep_stroke",
5473
6108
  "WebkitTextStrokeWidth",
5474
6109
  "WebkitTextStrokeColor",
@@ -5567,6 +6202,7 @@ const NODE_BASELINES = {
5567
6202
  "textAlign": "start",
5568
6203
  "fontStyle": "normal",
5569
6204
  "textDecoration": "none",
6205
+ "fontVariantNumeric": "normal",
5570
6206
  "WebkitTextStrokeWidth": "0px",
5571
6207
  "WebkitTextStrokeColor": "transparent",
5572
6208
  "margin": "0px 0px 0px 0px",
@@ -5656,6 +6292,7 @@ const NODE_BASELINES = {
5656
6292
  "textAlign",
5657
6293
  "fontStyle",
5658
6294
  "textDecoration",
6295
+ "fontVariantNumeric",
5659
6296
  "_sep_stroke",
5660
6297
  "WebkitTextStrokeWidth",
5661
6298
  "WebkitTextStrokeColor",
@@ -5752,6 +6389,7 @@ const NODE_BASELINES = {
5752
6389
  "textAlign": "start",
5753
6390
  "fontStyle": "normal",
5754
6391
  "textDecoration": "none",
6392
+ "fontVariantNumeric": "normal",
5755
6393
  "WebkitTextStrokeWidth": "0px",
5756
6394
  "WebkitTextStrokeColor": "transparent",
5757
6395
  "margin": "0px 0px 0px 0px",
@@ -5839,6 +6477,7 @@ const NODE_BASELINES = {
5839
6477
  "textAlign",
5840
6478
  "fontStyle",
5841
6479
  "textDecoration",
6480
+ "fontVariantNumeric",
5842
6481
  "_sep_stroke",
5843
6482
  "WebkitTextStrokeWidth",
5844
6483
  "WebkitTextStrokeColor",
@@ -5935,6 +6574,7 @@ const NODE_BASELINES = {
5935
6574
  "textAlign": "start",
5936
6575
  "fontStyle": "normal",
5937
6576
  "textDecoration": "none",
6577
+ "fontVariantNumeric": "normal",
5938
6578
  "WebkitTextStrokeWidth": "0px",
5939
6579
  "WebkitTextStrokeColor": "transparent",
5940
6580
  "margin": "0px 0px 0px 0px",
@@ -6022,6 +6662,7 @@ const NODE_BASELINES = {
6022
6662
  "textAlign",
6023
6663
  "fontStyle",
6024
6664
  "textDecoration",
6665
+ "fontVariantNumeric",
6025
6666
  "_sep_stroke",
6026
6667
  "WebkitTextStrokeWidth",
6027
6668
  "WebkitTextStrokeColor",
@@ -6124,6 +6765,7 @@ const NODE_BASELINES = {
6124
6765
  "textAlign": "start",
6125
6766
  "fontStyle": "normal",
6126
6767
  "textDecoration": "none",
6768
+ "fontVariantNumeric": "normal",
6127
6769
  "WebkitTextStrokeWidth": "0px",
6128
6770
  "WebkitTextStrokeColor": "transparent",
6129
6771
  "margin": "0px 0px 0px 0px",
@@ -6219,6 +6861,7 @@ const NODE_BASELINES = {
6219
6861
  "textAlign",
6220
6862
  "fontStyle",
6221
6863
  "textDecoration",
6864
+ "fontVariantNumeric",
6222
6865
  "_sep_stroke",
6223
6866
  "WebkitTextStrokeWidth",
6224
6867
  "WebkitTextStrokeColor",
@@ -6452,6 +7095,7 @@ const NEUTRAL_STYLE_PROPS = {
6452
7095
  "textAlign": "start",
6453
7096
  "fontStyle": "normal",
6454
7097
  "textDecoration": "none",
7098
+ "fontVariantNumeric": "normal",
6455
7099
  "WebkitTextStrokeWidth": "0px",
6456
7100
  "WebkitTextStrokeColor": "transparent",
6457
7101
  "margin": "0px 0px 0px 0px",
@@ -6614,6 +7258,8 @@ var PatternRecipe;
6614
7258
  /** CC4a: Tabs — Manual (three placeholder tabs), or From content when the section names a list `binding`: the tab
6615
7259
  * list and the panels are both Repeaters over it, one row giving its tab AND its panel. */
6616
7260
  PatternRecipe["Tabs"] = "tabs";
7261
+ /** CC4b: the Segmented control — Monthly · Yearly, named by the pattern (`name`). */
7262
+ PatternRecipe["Segmented"] = "segmented";
6617
7263
  /** CC3: the accessible carousel — a named Slider whose controls are parts, one quote per slide (placeholders). */
6618
7264
  PatternRecipe["Carousel"] = "carousel";
6619
7265
  /** CC3: the Lightbox — a Dialog holding a Slider over the node's `src` (the gallery's own source). */
@@ -6644,6 +7290,8 @@ var PatternPlaceholder;
6644
7290
  PatternPlaceholder["Image"] = "image";
6645
7291
  /** CC3: a clip the studio uploads (a Video's file): the poster blank until then, publish-blocking. */
6646
7292
  PatternPlaceholder["Video"] = "video";
7293
+ /** CC4b (Q37): a price the studio types — free text, publish-blocking, its label shown meanwhile, never a number. */
7294
+ PatternPlaceholder["Price"] = "price";
6647
7295
  })(PatternPlaceholder || (PatternPlaceholder = {}));
6648
7296
  /** CC3: what an `opens` node opens. */
6649
7297
  var PatternOpens;
@@ -7384,7 +8032,7 @@ const DIALOG$1 = 'Dialog';
7384
8032
  const LINK = 'Link';
7385
8033
  const LINKED = 'LinkedContainer';
7386
8034
  const BUTTON = 'ButtonBlock';
7387
- const ICON = 'Icon';
8035
+ const ICON$1 = 'Icon';
7388
8036
  const TEXT$1 = 'Text';
7389
8037
  const HEADING = 'Heading';
7390
8038
  const NAV_STYLE = 'nav';
@@ -7575,7 +8223,7 @@ function moveDisplayOverride(node, to) {
7575
8223
  }
7576
8224
  }
7577
8225
  function iconNode(kit, suffix, iconClass) {
7578
- return part(kit, suffix, ICON, { iconClass }, null);
8226
+ return part(kit, suffix, ICON$1, { iconClass }, null);
7579
8227
  }
7580
8228
  function labelText(kit, suffix, words) {
7581
8229
  return part(kit, suffix, TEXT$1, { content: words, tag: 'span' }, 'button-label');
@@ -7903,7 +8551,17 @@ var PlaceholderKind;
7903
8551
  PlaceholderKind["Image"] = "image";
7904
8552
  /** CC3: a video slot with no clip — the studio uploads its own (the poster blank meanwhile). */
7905
8553
  PlaceholderKind["Video"] = "video";
8554
+ /** CC4b (Q37): a price — a FACT the customer could be held to. Free text the studio types ("₪ 1,200", "From $40",
8555
+ * "On request"); its label shows meanwhile ("Monthly price"), never a number. No currency model. */
8556
+ PlaceholderKind["Price"] = "price";
7906
8557
  })(PlaceholderKind || (PlaceholderKind = {}));
8558
+ /** The placeholders a page cannot be published with unfilled (W4's gate): a fact, a price, the studio's own video.
8559
+ * Copy and an empty image are the author's to rewrite, never blocking. */
8560
+ const PUBLISH_BLOCKING_PLACEHOLDERS = new Set([PlaceholderKind.Fact, PlaceholderKind.Price, PlaceholderKind.Video]);
8561
+ /** True when a placeholder of `kind` blocks publishing until the studio fills it. */
8562
+ function blocksPublish(kind) {
8563
+ return PUBLISH_BLOCKING_PLACEHOLDERS.has(kind);
8564
+ }
7907
8565
  var ComposeIssueCode;
7908
8566
  (function (ComposeIssueCode) {
7909
8567
  /** A slot the plan and the business left empty and the pattern gives no words for — the node keeps
@@ -8022,6 +8680,8 @@ function chooseText(pn, ctx) {
8022
8680
  const own = pn.text === undefined ? undefined : fillVariables(pn.text, ctx);
8023
8681
  if (pn.ph === PatternPlaceholder.Copy)
8024
8682
  return { value: own, placeholder: { kind: PlaceholderKind.Copy } };
8683
+ if (pn.ph === PatternPlaceholder.Price)
8684
+ return { value: own, placeholder: { kind: PlaceholderKind.Price } };
8025
8685
  return { value: own };
8026
8686
  }
8027
8687
  /** A `bind` / `alt` / `param` / `src` path → the binding source + path, in this node's scope. */
@@ -8116,7 +8776,7 @@ function danglingFate(pn, ctx) {
8116
8776
  return null;
8117
8777
  if (ctx.email)
8118
8778
  return DanglingFate.Email;
8119
- return UNLINKED_TYPE[pn.t] ? DanglingFate.Unlink : DanglingFate.Remove;
8779
+ return UNLINKED_TYPE[pn.t] || (ctx.keepButtons && pn.t === BUTTON_BLOCK) ? DanglingFate.Unlink : DanglingFate.Remove;
8120
8780
  }
8121
8781
  const DANGLING_ISSUE = {
8122
8782
  [DanglingFate.Email]: ComposeIssueCode.LinkToEmail,
@@ -8128,7 +8788,9 @@ function reportDangling(fate, pn, id, words, ctx) {
8128
8788
  const outcome = {
8129
8789
  [DanglingFate.Email]: `it now opens an email to ${ctx.email}`,
8130
8790
  [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',
8791
+ [DanglingFate.Unlink]: pn.t === BUTTON_BLOCK
8792
+ ? 'with no email address to send to instead, the button keeps its words without the link'
8793
+ : 'with no email address to send to instead, the box keeps its contents without the link',
8132
8794
  }[fate];
8133
8795
  ctx.issues.push({
8134
8796
  code: DANGLING_ISSUE[fate], nodeId: id, owner: ctx.owner, route: pn.href,
@@ -8212,7 +8874,7 @@ function composeNode(pn, id, repeater, ctx) {
8212
8874
  reportDangling(fate, pn, id, words.value, ctx);
8213
8875
  return null;
8214
8876
  }
8215
- const type = fate === DanglingFate.Unlink ? UNLINKED_TYPE[pn.t] : pn.t;
8877
+ const type = fate === DanglingFate.Unlink ? UNLINKED_TYPE[pn.t] ?? pn.t : pn.t;
8216
8878
  const props = {};
8217
8879
  if (pn.level)
8218
8880
  props['level'] = pn.level;
@@ -8263,6 +8925,13 @@ function composeNode(pn, id, repeater, ctx) {
8263
8925
  }
8264
8926
  if (pn.name)
8265
8927
  setProp(node, 'ariaLabel', pn.name);
8928
+ if (pn.icon) {
8929
+ if (type !== ICON)
8930
+ throw new ComposeError(`${id}: "icon" belongs on an Icon`);
8931
+ setProp(node, 'iconClass', pn.icon);
8932
+ }
8933
+ if (pn.layer)
8934
+ node.label = pn.layer;
8266
8935
  if (pn.opens) {
8267
8936
  if (pn.opens !== PatternOpens.Lightbox)
8268
8937
  throw new ComposeError(`${id}: "opens" names the pattern's lightbox`);
@@ -8313,13 +8982,9 @@ function composeNode(pn, id, repeater, ctx) {
8313
8982
  throw new ComposeError(`${id}: "alt" belongs on a bound Image`);
8314
8983
  }
8315
8984
  // 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
- }
8985
+ applyLayout(node, pn);
8986
+ if (pn.shownWhen)
8987
+ hideUntilOn(node, pn, ctx);
8323
8988
  // A Repeater's rows.
8324
8989
  let rowScope = repeater;
8325
8990
  if (pn.src) {
@@ -8347,6 +9012,47 @@ function composeNode(pn, id, repeater, ctx) {
8347
9012
  composeForm(node, pn, id, ctx);
8348
9013
  return node;
8349
9014
  }
9015
+ /** A pattern node's layout: its `lay` styleProps and its per-breakpoint `resp` layers. */
9016
+ function applyLayout(node, pn) {
9017
+ if (pn.lay)
9018
+ setStyleProps(node, pn.lay);
9019
+ if (pn.resp) {
9020
+ for (const layer of Object.values(pn.resp))
9021
+ assertStyleSlots(node.type, Object.keys(layer));
9022
+ node.responsive = Object.fromEntries(Object.entries(pn.resp).map(([bp, styleProps]) => [bp, { styleProps: { ...styleProps } }]));
9023
+ }
9024
+ }
9025
+ /** CC4b (`shownWhen`, Q38): hidden at base and shown — with its own layout's display — while the pattern's Segmented
9026
+ * option of that key is on. Wired once the pattern is stamped (the option's id is known then). */
9027
+ function hideUntilOn(node, pn, ctx) {
9028
+ const display = String(node.styleProps['display'] ?? '') || SHOWN_DISPLAY;
9029
+ setStyleProps(node, { display: HIDDEN_DISPLAY });
9030
+ (ctx.shownWhen ??= []).push({ id: node.id, key: pn.shownWhen, display });
9031
+ }
9032
+ /** CC4b: every `shownWhen` node of a stamped pattern follows its option — the targeted `trigger-on` ("when Yearly is
9033
+ * on"), compiled by both renderers to ONE `:has()` rule on the nearest common ancestor. */
9034
+ function wireShownWhen(root, entries) {
9035
+ if (!entries.length)
9036
+ return;
9037
+ const nodes = new Map();
9038
+ const options = new Map();
9039
+ const visit = (n) => {
9040
+ nodes.set(n.id, n);
9041
+ for (const option of segmentedOptions(n))
9042
+ if (option.itemKey && !options.has(option.itemKey))
9043
+ options.set(option.itemKey, option.id);
9044
+ (n.children ?? []).forEach(visit);
9045
+ };
9046
+ visit(root);
9047
+ for (const entry of entries) {
9048
+ const option = options.get(entry.key);
9049
+ if (!option)
9050
+ throw new ComposeError(`${entry.id}: "shownWhen: ${entry.key}" names no option of a segmented in the pattern`);
9051
+ const node = nodes.get(entry.id);
9052
+ node.stateStyles = { ...(node.stateStyles ?? {}), [ITEM_OPEN_STATE]: { display: entry.display } };
9053
+ node.stateTriggers = { ...(node.stateTriggers ?? {}), [ITEM_OPEN_STATE]: option };
9054
+ }
9055
+ }
8350
9056
  /** A Card v2 `binds` key → the part it binds and that part's bound prop. */
8351
9057
  const CARD_BINDS = {
8352
9058
  [CardBindTarget.Image]: { role: CardRole.Media, prop: 'src' },
@@ -8368,6 +9074,8 @@ function composeRecipe(pn, id, repeater, ctx) {
8368
9074
  return composeCarousel(pn, id, ctx);
8369
9075
  if (pn.recipe === PatternRecipe.Lightbox)
8370
9076
  return composeLightbox(pn, id, repeater, ctx);
9077
+ if (pn.recipe === PatternRecipe.Segmented)
9078
+ return composeSegmented(pn, id);
8371
9079
  if (pn.recipe !== PatternRecipe.Card)
8372
9080
  throw new ComposeError(`${id}: no recipe "${pn.recipe}" in composite-core`);
8373
9081
  const layout = (pn.layout ?? CardLayout.Top);
@@ -8378,7 +9086,26 @@ function composeRecipe(pn, id, repeater, ctx) {
8378
9086
  throw new ComposeError(`${id}: a card has no part "${part}"`);
8379
9087
  }
8380
9088
  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 });
9089
+ const tone = pn.badge;
9090
+ if (tone && !BADGE_TONES.includes(tone))
9091
+ throw new ComposeError(`${id}: a badge has no tone "${pn.badge}"`);
9092
+ for (const key of Object.keys(pn.words ?? {}))
9093
+ if (!CARD_WORD_KEYS.includes(key))
9094
+ throw new ComposeError(`${id}: a card has no words "${key}"`);
9095
+ const card = buildCardRecipe(factory, {
9096
+ layout, parts: pn.parts, words: pn.words, badgeTone: tone,
9097
+ });
9098
+ if (pn.scheme) {
9099
+ if (!COLOR_SCHEMES.some(c => c.id === pn.scheme))
9100
+ throw new ComposeError(`${id}: no colour scheme "${pn.scheme}"`);
9101
+ setColorScheme(card, pn.scheme);
9102
+ }
9103
+ if (pn.ph === PatternPlaceholder.Copy)
9104
+ copyPlaceholders(card, ctx);
9105
+ if (pn.c?.length) {
9106
+ const content = findByRole(card, CardRole.Content);
9107
+ content.children = [...(content.children ?? []), ...composeChildren(pn, id, repeater, ctx)];
9108
+ }
8382
9109
  for (const [key, path] of Object.entries(pn.binds ?? {})) {
8383
9110
  const target = CARD_BINDS[key];
8384
9111
  if (!target)
@@ -8411,6 +9138,31 @@ function composeRecipe(pn, id, repeater, ctx) {
8411
9138
  return card;
8412
9139
  }
8413
9140
  const REPEATER = 'Repeater';
9141
+ const ICON = 'Icon';
9142
+ const SHOWN_DISPLAY = 'flex';
9143
+ const HIDDEN_DISPLAY = 'none';
9144
+ /** The words a card recipe's `words` may set (composite-core `CardWords`). */
9145
+ const CARD_WORD_KEYS = ['eyebrow', 'title', 'text', 'primary', 'secondary', 'badge'];
9146
+ /** A card's words the studio rewrites (`ph: 'copy'`): its eyebrow, title, text and badge. */
9147
+ const CARD_COPY_ROLES = [CardRole.Eyebrow, CardRole.Title, CardRole.Text];
9148
+ /** A card's own words, as COPY placeholders (its badge's words too). */
9149
+ function copyPlaceholders(card, ctx) {
9150
+ for (const role of CARD_COPY_ROLES) {
9151
+ const part = findByRole(card, role);
9152
+ if (part)
9153
+ ctx.placeholders.push({ nodeId: part.id, owner: ctx.owner, kind: PlaceholderKind.Copy, text: String(part.props?.['content'] ?? '') });
9154
+ }
9155
+ const badge = findByRole(card, CardRole.Badge);
9156
+ const words = badge?.children?.find(c => c.type === TEXT);
9157
+ if (words)
9158
+ ctx.placeholders.push({ nodeId: words.id, owner: ctx.owner, kind: PlaceholderKind.Copy, text: String(words.props?.['content'] ?? '') });
9159
+ }
9160
+ /** CC4b: the Segmented control — composite-core's recipe (Monthly · Yearly), named by the pattern, laid out by it. */
9161
+ function composeSegmented(pn, id) {
9162
+ const root = buildSegmentedRecipe(recipeFactory(id, 'segmented'), pn.name !== undefined ? { label: pn.name } : {});
9163
+ applyLayout(root, pn);
9164
+ return root;
9165
+ }
8414
9166
  /**
8415
9167
  * An Accordion (CC2) — the composite-core recipe stamped with this composer's factory. Manual (no section
8416
9168
  * binding): three items whose questions and answers are placeholders the studio rewrites (`ph: 'copy'`), never
@@ -8570,11 +9322,12 @@ function wireOpeners(root, openers) {
8570
9322
  function composePattern(pattern, id, ctx) {
8571
9323
  if (pattern.node.each)
8572
9324
  throw new ComposeError(`${id}: a pattern's root cannot be stamped per page`);
8573
- const own = { ...ctx, openers: [] };
9325
+ const own = { ...ctx, openers: [], shownWhen: [] };
8574
9326
  const node = composeNode(pattern.node, id, null, own);
8575
9327
  if (!node)
8576
9328
  throw new ComposeError(`${id}: a pattern's root cannot be optional or a link`);
8577
9329
  wireOpeners(node, own.openers ?? []);
9330
+ wireShownWhen(node, own.shownWhen ?? []);
8578
9331
  node.label = pattern.label;
8579
9332
  return node;
8580
9333
  }
@@ -8723,6 +9476,37 @@ function composeNavHeader(input, options) {
8723
9476
  const header = shape ? planNavShape([root], shape, { newId: options.newId }, root.id).globals[0] : root;
8724
9477
  return { header, issues };
8725
9478
  }
9479
+ // ── One pattern on its own (CC4b) ───────────────────────────────────────────────────────────────
9480
+ /** The pricing section (CC4b, board 10): plans with a Monthly / Yearly switch — the library and the palette, never a
9481
+ * Studio page (Q35). */
9482
+ const PRICING_PATTERN = 'pricing.tiers';
9483
+ /**
9484
+ * ONE library pattern composed on its own — the builder palette's ready-made sections (CC4b: "Pricing", the
9485
+ * `pricing.tiers` pattern). THE SAME pattern and composer as `composeSite`: its words, its placeholders (a price shows
9486
+ * its label, never a number) and the one dangling-link rule — except a button to a page the studio lacks keeps its
9487
+ * words, unlinked, for the author to link. Pure.
9488
+ */
9489
+ function composeSection(patternId, input, options) {
9490
+ if (!nonEmpty(options?.id))
9491
+ throw new ComposeError('composeSection needs the section id');
9492
+ const pattern = patternById(patternId);
9493
+ if (!pattern)
9494
+ throw new ComposeError(`no pattern "${patternId}" in the library`);
9495
+ if (pattern.global)
9496
+ throw new ComposeError(`"${patternId}" is a header or footer — composeNavHeader / composeSite stamp those`);
9497
+ const business = input.business ?? { name: '' };
9498
+ const pages = navPagePlans(input.pages ?? []);
9499
+ const plan = { business, pages, dataSources: [], contentTypes: [] };
9500
+ const email = nonEmpty(business.facts?.email) ? business.facts.email.trim() : null;
9501
+ const placeholders = [];
9502
+ const issues = [];
9503
+ const ctx = {
9504
+ owner: options.id, page: null, section: null, plan, year: 0, email, navPage: null, nextAlias: null,
9505
+ placeholders, issues, routes: new Set(pages.map(p => p.route)), keepButtons: true,
9506
+ };
9507
+ const section = composePattern(pattern, options.id, ctx);
9508
+ return { section, placeholders, issues };
9509
+ }
8726
9510
 
8727
9511
  /**
8728
9512
  * @vectoriox/iox-ui/generation-core — the shared, FRAMEWORK-FREE site-plan core (design-system plan
@@ -8740,5 +9524,5 @@ function composeNavHeader(input, options) {
8740
9524
  * Generated bundle index. Do not edit.
8741
9525
  */
8742
9526
 
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 };
9527
+ 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
9528
  //# sourceMappingURL=vectoriox-iox-ui-generation-core.mjs.map