@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,11 +1,11 @@
1
- import { DesignChoices, LinkType, resolveDesignChoices } from '@vectoriox/iox-ui/design-core';
1
+ import { COLOR_SCHEMES, DesignChoices, LinkType, resolveDesignChoices, setColorScheme } from '@vectoriox/iox-ui/design-core';
2
2
  import { FormPresetDef, FormPresetField, formPresetById } from '@vectoriox/iox-ui/forms-core';
3
3
  import {
4
4
  ACCORDION_BIND_PROP, ACCORDION_CONTENT_LIMIT, ACCORDION_WORDS, accordionAnswerOf, accordionItems, accordionQuestionOf, AccordionRole,
5
5
  buildAccordionRecipe, buildCardRecipe, buildCarouselRecipe, buildLightboxRecipe, CardLayout, CardPart, CardRole, CARD_LAYOUTS, CARD_PARTS, CompositeNode,
6
6
  CompositeNodeSpec, findByRole, LIGHTBOX_LABEL, pickAccordionAutoBinds, pickTabsAutoBinds, SLIDE_TO_ROW, SLIDE_TYPE, buildTabsRecipe, tabLabelNodeOf,
7
7
  tabPanelImageOf, tabPanelTextOf, tabsListOf, tabsPanels, tabsPanelsOf, tabsTriggers, TABS_CONTENT_LIMIT, TABS_IMAGE_BIND_PROP, TABS_LABEL_BIND_PROP,
8
- TABS_TEXT_BIND_PROP, TABS_WORDS,
8
+ TABS_TEXT_BIND_PROP, TABS_WORDS, BadgeTone, BADGE_TONES, buildSegmentedRecipe, CardWords, ITEM_OPEN_STATE, segmentedOptions,
9
9
  } from '@vectoriox/iox-ui/composite-core';
10
10
 
11
11
  import { NODE_BASELINES } from './node-baselines.generated';
@@ -41,6 +41,18 @@ export enum PlaceholderKind {
41
41
  Image = 'image',
42
42
  /** CC3: a video slot with no clip — the studio uploads its own (the poster blank meanwhile). */
43
43
  Video = 'video',
44
+ /** CC4b (Q37): a price — a FACT the customer could be held to. Free text the studio types ("₪ 1,200", "From $40",
45
+ * "On request"); its label shows meanwhile ("Monthly price"), never a number. No currency model. */
46
+ Price = 'price',
47
+ }
48
+
49
+ /** The placeholders a page cannot be published with unfilled (W4's gate): a fact, a price, the studio's own video.
50
+ * Copy and an empty image are the author's to rewrite, never blocking. */
51
+ export const PUBLISH_BLOCKING_PLACEHOLDERS: ReadonlySet<PlaceholderKind> = new Set([PlaceholderKind.Fact, PlaceholderKind.Price, PlaceholderKind.Video]);
52
+
53
+ /** True when a placeholder of `kind` blocks publishing until the studio fills it. */
54
+ export function blocksPublish(kind: PlaceholderKind): boolean {
55
+ return PUBLISH_BLOCKING_PLACEHOLDERS.has(kind);
44
56
  }
45
57
 
46
58
  export interface ComposedPlaceholder {
@@ -241,6 +253,18 @@ interface Ctx {
241
253
  routes: ReadonlySet<string>;
242
254
  /** CC3: nodes whose click opens the pattern's lightbox (`opens`), wired once the pattern is stamped. */
243
255
  openers?: string[];
256
+ /** CC4b: nodes shown while an option is on (`shownWhen`), wired once the pattern is stamped. */
257
+ shownWhen?: ShownWhen[];
258
+ /** A section inserted from the palette (`composeSection`): a button to a page the studio lacks keeps its words,
259
+ * unlinked — the author links it — instead of being removed. */
260
+ keepButtons?: boolean;
261
+ }
262
+
263
+ interface ShownWhen {
264
+ id: string;
265
+ key: string;
266
+ /** The display the node shows with (its own layout's, else flex). */
267
+ display: string;
244
268
  }
245
269
 
246
270
  function nonEmpty(v: unknown): v is string {
@@ -273,6 +297,7 @@ function chooseText(pn: PatternNode, ctx: Ctx): TextChoice {
273
297
  }
274
298
  const own = pn.text === undefined ? undefined : fillVariables(pn.text, ctx);
275
299
  if (pn.ph === PatternPlaceholder.Copy) return { value: own, placeholder: { kind: PlaceholderKind.Copy } };
300
+ if (pn.ph === PatternPlaceholder.Price) return { value: own, placeholder: { kind: PlaceholderKind.Price } };
276
301
  return { value: own };
277
302
  }
278
303
 
@@ -364,7 +389,7 @@ enum DanglingFate {
364
389
  function danglingFate(pn: PatternNode, ctx: Ctx): DanglingFate | null {
365
390
  if (!pn.href || pn.href === PatternDirective.PageRoute || ctx.routes.has(pn.href)) return null;
366
391
  if (ctx.email) return DanglingFate.Email;
367
- return UNLINKED_TYPE[pn.t] ? DanglingFate.Unlink : DanglingFate.Remove;
392
+ return UNLINKED_TYPE[pn.t] || (ctx.keepButtons && pn.t === BUTTON_BLOCK) ? DanglingFate.Unlink : DanglingFate.Remove;
368
393
  }
369
394
 
370
395
  const DANGLING_ISSUE: Readonly<Record<DanglingFate, ComposeIssueCode>> = {
@@ -378,7 +403,9 @@ function reportDangling(fate: DanglingFate, pn: PatternNode, id: string, words:
378
403
  const outcome = {
379
404
  [DanglingFate.Email]: `it now opens an email to ${ctx.email}`,
380
405
  [DanglingFate.Remove]: 'with no email address to send to instead, it was removed',
381
- [DanglingFate.Unlink]: 'with no email address to send to instead, the box keeps its contents without the link',
406
+ [DanglingFate.Unlink]: pn.t === BUTTON_BLOCK
407
+ ? 'with no email address to send to instead, the button keeps its words without the link'
408
+ : 'with no email address to send to instead, the box keeps its contents without the link',
382
409
  }[fate];
383
410
  ctx.issues.push({
384
411
  code: DANGLING_ISSUE[fate], nodeId: id, owner: ctx.owner, route: pn.href,
@@ -459,7 +486,7 @@ function composeNode(pn: PatternNode, id: string, repeater: RepeaterScope | null
459
486
  reportDangling(fate, pn, id, words.value, ctx);
460
487
  return null;
461
488
  }
462
- const type = fate === DanglingFate.Unlink ? UNLINKED_TYPE[pn.t] : pn.t;
489
+ const type = fate === DanglingFate.Unlink ? UNLINKED_TYPE[pn.t] ?? pn.t : pn.t;
463
490
 
464
491
  const props: Record<string, unknown> = {};
465
492
  if (pn.level) props['level'] = pn.level;
@@ -501,6 +528,11 @@ function composeNode(pn: PatternNode, id: string, repeater: RepeaterScope | null
501
528
  ctx.placeholders.push({ nodeId: id, owner: ctx.owner, kind: PlaceholderKind.Video, text: '' });
502
529
  }
503
530
  if (pn.name) setProp(node, 'ariaLabel', pn.name);
531
+ if (pn.icon) {
532
+ if (type !== ICON) throw new ComposeError(`${id}: "icon" belongs on an Icon`);
533
+ setProp(node, 'iconClass', pn.icon);
534
+ }
535
+ if (pn.layer) node.label = pn.layer;
504
536
  if (pn.opens) {
505
537
  if (pn.opens !== PatternOpens.Lightbox) throw new ComposeError(`${id}: "opens" names the pattern's lightbox`);
506
538
  (ctx.openers ??= []).push(id);
@@ -542,11 +574,8 @@ function composeNode(pn: PatternNode, id: string, repeater: RepeaterScope | null
542
574
  }
543
575
 
544
576
  // Layout.
545
- if (pn.lay) setStyleProps(node, pn.lay);
546
- if (pn.resp) {
547
- for (const layer of Object.values(pn.resp)) assertStyleSlots(node.type, Object.keys(layer));
548
- node.responsive = Object.fromEntries(Object.entries(pn.resp).map(([bp, styleProps]) => [bp, { styleProps: { ...styleProps } }]));
549
- }
577
+ applyLayout(node, pn);
578
+ if (pn.shownWhen) hideUntilOn(node, pn, ctx);
550
579
 
551
580
  // A Repeater's rows.
552
581
  let rowScope = repeater;
@@ -573,6 +602,44 @@ function composeNode(pn: PatternNode, id: string, repeater: RepeaterScope | null
573
602
  return node;
574
603
  }
575
604
 
605
+ /** A pattern node's layout: its `lay` styleProps and its per-breakpoint `resp` layers. */
606
+ function applyLayout(node: SerializedNode, pn: PatternNode): void {
607
+ if (pn.lay) setStyleProps(node, pn.lay);
608
+ if (pn.resp) {
609
+ for (const layer of Object.values(pn.resp)) assertStyleSlots(node.type, Object.keys(layer));
610
+ node.responsive = Object.fromEntries(Object.entries(pn.resp).map(([bp, styleProps]) => [bp, { styleProps: { ...styleProps } }]));
611
+ }
612
+ }
613
+
614
+ /** CC4b (`shownWhen`, Q38): hidden at base and shown — with its own layout's display — while the pattern's Segmented
615
+ * option of that key is on. Wired once the pattern is stamped (the option's id is known then). */
616
+ function hideUntilOn(node: SerializedNode, pn: PatternNode, ctx: Ctx): void {
617
+ const display = String(node.styleProps['display'] ?? '') || SHOWN_DISPLAY;
618
+ setStyleProps(node, { display: HIDDEN_DISPLAY });
619
+ (ctx.shownWhen ??= []).push({ id: node.id, key: pn.shownWhen!, display });
620
+ }
621
+
622
+ /** CC4b: every `shownWhen` node of a stamped pattern follows its option — the targeted `trigger-on` ("when Yearly is
623
+ * on"), compiled by both renderers to ONE `:has()` rule on the nearest common ancestor. */
624
+ function wireShownWhen(root: SerializedNode, entries: ReadonlyArray<ShownWhen>): void {
625
+ if (!entries.length) return;
626
+ const nodes = new Map<string, SerializedNode>();
627
+ const options = new Map<string, string>();
628
+ const visit = (n: SerializedNode) => {
629
+ nodes.set(n.id, n);
630
+ for (const option of segmentedOptions(n as unknown as CompositeNode)) if (option.itemKey && !options.has(option.itemKey)) options.set(option.itemKey, option.id!);
631
+ (n.children ?? []).forEach(visit);
632
+ };
633
+ visit(root);
634
+ for (const entry of entries) {
635
+ const option = options.get(entry.key);
636
+ if (!option) throw new ComposeError(`${entry.id}: "shownWhen: ${entry.key}" names no option of a segmented in the pattern`);
637
+ const node = nodes.get(entry.id)!;
638
+ node.stateStyles = { ...(node.stateStyles ?? {}), [ITEM_OPEN_STATE]: { display: entry.display } };
639
+ node.stateTriggers = { ...(node.stateTriggers ?? {}), [ITEM_OPEN_STATE]: option };
640
+ }
641
+ }
642
+
576
643
  /** A Card v2 `binds` key → the part it binds and that part's bound prop. */
577
644
  const CARD_BINDS: Readonly<Record<CardBindTarget, { role: CardRole; prop: string }>> = {
578
645
  [CardBindTarget.Image]: { role: CardRole.Media, prop: 'src' },
@@ -591,6 +658,7 @@ function composeRecipe(pn: PatternNode, id: string, repeater: RepeaterScope | nu
591
658
  if (pn.recipe === PatternRecipe.Tabs) return composeTabs(pn, id, ctx);
592
659
  if (pn.recipe === PatternRecipe.Carousel) return composeCarousel(pn, id, ctx);
593
660
  if (pn.recipe === PatternRecipe.Lightbox) return composeLightbox(pn, id, repeater, ctx);
661
+ if (pn.recipe === PatternRecipe.Segmented) return composeSegmented(pn, id);
594
662
  if (pn.recipe !== PatternRecipe.Card) throw new ComposeError(`${id}: no recipe "${pn.recipe}" in composite-core`);
595
663
  const layout = (pn.layout ?? CardLayout.Top) as CardLayout;
596
664
  if (!CARD_LAYOUTS.includes(layout)) throw new ComposeError(`${id}: a card has no layout "${pn.layout}"`);
@@ -599,7 +667,22 @@ function composeRecipe(pn: PatternNode, id: string, repeater: RepeaterScope | nu
599
667
  }
600
668
  const factory = (spec: CompositeNodeSpec): CompositeNode =>
601
669
  create(spec.key === CardRole.Card ? id : `${id}-${spec.key}`, spec.type, { ...(spec.props ?? {}) }, spec.elementStyle ?? null) as CompositeNode;
602
- const card = buildCardRecipe(factory, { layout, parts: pn.parts as Partial<Record<CardPart, boolean>> }) as SerializedNode;
670
+ const tone = pn.badge as BadgeTone | undefined;
671
+ if (tone && !BADGE_TONES.includes(tone)) throw new ComposeError(`${id}: a badge has no tone "${pn.badge}"`);
672
+ for (const key of Object.keys(pn.words ?? {})) if (!CARD_WORD_KEYS.includes(key)) throw new ComposeError(`${id}: a card has no words "${key}"`);
673
+ const card = buildCardRecipe(factory, {
674
+ layout, parts: pn.parts as Partial<Record<CardPart, boolean>>, words: pn.words as Partial<CardWords> | undefined, badgeTone: tone,
675
+ ...(pn.icon ? { badgeIcon: pn.icon } : {}),
676
+ }) as SerializedNode;
677
+ if (pn.scheme) {
678
+ if (!COLOR_SCHEMES.some(c => c.id === pn.scheme)) throw new ComposeError(`${id}: no colour scheme "${pn.scheme}"`);
679
+ setColorScheme(card, pn.scheme);
680
+ }
681
+ if (pn.ph === PatternPlaceholder.Copy) copyPlaceholders(card, ctx);
682
+ if (pn.c?.length) {
683
+ const content = findByRole(card as CompositeNode, CardRole.Content) as SerializedNode;
684
+ content.children = [...(content.children ?? []), ...composeChildren(pn, id, repeater, ctx)];
685
+ }
603
686
 
604
687
  for (const [key, path] of Object.entries(pn.binds ?? {})) {
605
688
  const target = CARD_BINDS[key as CardBindTarget];
@@ -628,6 +711,31 @@ function composeRecipe(pn: PatternNode, id: string, repeater: RepeaterScope | nu
628
711
  }
629
712
 
630
713
  const REPEATER = 'Repeater';
714
+ const ICON = 'Icon';
715
+ const SHOWN_DISPLAY = 'flex';
716
+ const HIDDEN_DISPLAY = 'none';
717
+ /** The words a card recipe's `words` may set (composite-core `CardWords`). */
718
+ const CARD_WORD_KEYS: ReadonlyArray<string> = ['eyebrow', 'title', 'text', 'primary', 'secondary', 'badge'];
719
+ /** A card's words the studio rewrites (`ph: 'copy'`): its eyebrow, title, text and badge. */
720
+ const CARD_COPY_ROLES: ReadonlyArray<string> = [CardRole.Eyebrow, CardRole.Title, CardRole.Text];
721
+
722
+ /** A card's own words, as COPY placeholders (its badge's words too). */
723
+ function copyPlaceholders(card: SerializedNode, ctx: Ctx): void {
724
+ for (const role of CARD_COPY_ROLES) {
725
+ const part = findByRole(card as unknown as CompositeNode, role) as SerializedNode | undefined;
726
+ if (part) ctx.placeholders.push({ nodeId: part.id, owner: ctx.owner, kind: PlaceholderKind.Copy, text: String(part.props?.['content'] ?? '') });
727
+ }
728
+ const badge = findByRole(card as unknown as CompositeNode, CardRole.Badge) as SerializedNode | undefined;
729
+ const words = badge?.children?.find(c => c.type === TEXT);
730
+ if (words) ctx.placeholders.push({ nodeId: words.id, owner: ctx.owner, kind: PlaceholderKind.Copy, text: String(words.props?.['content'] ?? '') });
731
+ }
732
+
733
+ /** CC4b: the Segmented control — composite-core's recipe (Monthly · Yearly), named by the pattern, laid out by it. */
734
+ function composeSegmented(pn: PatternNode, id: string): SerializedNode {
735
+ const root = buildSegmentedRecipe(recipeFactory(id, 'segmented'), pn.name !== undefined ? { label: pn.name } : {}) as SerializedNode;
736
+ applyLayout(root, pn);
737
+ return root;
738
+ }
631
739
 
632
740
  /**
633
741
  * An Accordion (CC2) — the composite-core recipe stamped with this composer's factory. Manual (no section
@@ -784,10 +892,11 @@ function wireOpeners(root: SerializedNode, openers: ReadonlyArray<string>): void
784
892
 
785
893
  function composePattern(pattern: SitePattern, id: string, ctx: Ctx): SerializedNode {
786
894
  if (pattern.node.each) throw new ComposeError(`${id}: a pattern's root cannot be stamped per page`);
787
- const own: Ctx = { ...ctx, openers: [] };
895
+ const own: Ctx = { ...ctx, openers: [], shownWhen: [] };
788
896
  const node = composeNode(pattern.node, id, null, own);
789
897
  if (!node) throw new ComposeError(`${id}: a pattern's root cannot be optional or a link`);
790
898
  wireOpeners(node, own.openers ?? []);
899
+ wireShownWhen(node, own.shownWhen ?? []);
791
900
  node.label = pattern.label;
792
901
  return node;
793
902
  }
@@ -965,3 +1074,52 @@ export function composeNavHeader(input: NavHeaderInput, options: NavHeaderOption
965
1074
  const header = shape ? planNavShape([root], shape, { newId: options.newId }, root.id).globals[0] : root;
966
1075
  return { header, issues };
967
1076
  }
1077
+
1078
+ // ── One pattern on its own (CC4b) ───────────────────────────────────────────────────────────────
1079
+
1080
+ /** The pricing section (CC4b, board 10): plans with a Monthly / Yearly switch — the library and the palette, never a
1081
+ * Studio page (Q35). */
1082
+ export const PRICING_PATTERN = 'pricing.tiers';
1083
+
1084
+ /** What a section is composed from when there is no Site Plan: the studio's name, its pages (the routes a link may
1085
+ * reach) and its facts. */
1086
+ export interface SectionInput {
1087
+ readonly business?: SiteBusiness;
1088
+ readonly pages?: ReadonlyArray<SitePageRef>;
1089
+ }
1090
+
1091
+ export interface SectionOptions {
1092
+ /** The section's id; its parts' ids derive from it (`<id>-0-1-…`), so a fresh id gives fresh parts. */
1093
+ readonly id: string;
1094
+ }
1095
+
1096
+ export interface ComposedSection {
1097
+ section: SerializedNode;
1098
+ placeholders: ComposedPlaceholder[];
1099
+ issues: ComposeIssue[];
1100
+ }
1101
+
1102
+ /**
1103
+ * ONE library pattern composed on its own — the builder palette's ready-made sections (CC4b: "Pricing", the
1104
+ * `pricing.tiers` pattern). THE SAME pattern and composer as `composeSite`: its words, its placeholders (a price shows
1105
+ * its label, never a number) and the one dangling-link rule — except a button to a page the studio lacks keeps its
1106
+ * words, unlinked, for the author to link. Pure.
1107
+ */
1108
+ export function composeSection(patternId: string, input: SectionInput, options: SectionOptions): ComposedSection {
1109
+ if (!nonEmpty(options?.id)) throw new ComposeError('composeSection needs the section id');
1110
+ const pattern = patternById(patternId);
1111
+ if (!pattern) throw new ComposeError(`no pattern "${patternId}" in the library`);
1112
+ if (pattern.global) throw new ComposeError(`"${patternId}" is a header or footer — composeNavHeader / composeSite stamp those`);
1113
+ const business: SiteBusiness = input.business ?? { name: '' } as SiteBusiness;
1114
+ const pages = navPagePlans(input.pages ?? []);
1115
+ const plan = { business, pages, dataSources: [], contentTypes: [] } as unknown as SitePlan;
1116
+ const email = nonEmpty(business.facts?.email) ? business.facts!.email!.trim() : null;
1117
+ const placeholders: ComposedPlaceholder[] = [];
1118
+ const issues: ComposeIssue[] = [];
1119
+ const ctx: Ctx = {
1120
+ owner: options.id, page: null, section: null, plan, year: 0, email, navPage: null, nextAlias: null,
1121
+ placeholders, issues, routes: new Set(pages.map(p => p.route)), keepButtons: true,
1122
+ };
1123
+ const section = composePattern(pattern, options.id, ctx);
1124
+ return { section, placeholders, issues };
1125
+ }
@@ -55,6 +55,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
55
55
  "textAlign": "start",
56
56
  "fontStyle": "normal",
57
57
  "textDecoration": "none",
58
+ "fontVariantNumeric": "normal",
58
59
  "WebkitTextStrokeWidth": "0px",
59
60
  "WebkitTextStrokeColor": "transparent",
60
61
  "margin": "0px 0px 0px 0px",
@@ -144,6 +145,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
144
145
  "textAlign",
145
146
  "fontStyle",
146
147
  "textDecoration",
148
+ "fontVariantNumeric",
147
149
  "_sep_stroke",
148
150
  "WebkitTextStrokeWidth",
149
151
  "WebkitTextStrokeColor",
@@ -246,6 +248,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
246
248
  "textAlign": "start",
247
249
  "fontStyle": "normal",
248
250
  "textDecoration": "none",
251
+ "fontVariantNumeric": "normal",
249
252
  "WebkitTextStrokeWidth": "0px",
250
253
  "WebkitTextStrokeColor": "transparent",
251
254
  "margin": "0px 0px 0px 0px",
@@ -340,6 +343,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
340
343
  "textAlign",
341
344
  "fontStyle",
342
345
  "textDecoration",
346
+ "fontVariantNumeric",
343
347
  "_sep_stroke",
344
348
  "WebkitTextStrokeWidth",
345
349
  "WebkitTextStrokeColor",
@@ -438,6 +442,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
438
442
  "textAlign": "start",
439
443
  "fontStyle": "normal",
440
444
  "textDecoration": "none",
445
+ "fontVariantNumeric": "normal",
441
446
  "WebkitTextStrokeWidth": "0px",
442
447
  "WebkitTextStrokeColor": "transparent",
443
448
  "margin": "0px 0px 0px 0px",
@@ -527,6 +532,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
527
532
  "textAlign",
528
533
  "fontStyle",
529
534
  "textDecoration",
535
+ "fontVariantNumeric",
530
536
  "_sep_stroke",
531
537
  "WebkitTextStrokeWidth",
532
538
  "WebkitTextStrokeColor",
@@ -624,6 +630,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
624
630
  "textAlign": "start",
625
631
  "fontStyle": "normal",
626
632
  "textDecoration": "none",
633
+ "fontVariantNumeric": "normal",
627
634
  "WebkitTextStrokeWidth": "0px",
628
635
  "WebkitTextStrokeColor": "transparent",
629
636
  "margin": "0px 0px 0px 0px",
@@ -717,6 +724,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
717
724
  "textAlign",
718
725
  "fontStyle",
719
726
  "textDecoration",
727
+ "fontVariantNumeric",
720
728
  "_sep_stroke",
721
729
  "WebkitTextStrokeWidth",
722
730
  "WebkitTextStrokeColor",
@@ -818,6 +826,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
818
826
  "textAlign": "start",
819
827
  "fontStyle": "normal",
820
828
  "textDecoration": "none",
829
+ "fontVariantNumeric": "normal",
821
830
  "WebkitTextStrokeWidth": "0px",
822
831
  "WebkitTextStrokeColor": "transparent",
823
832
  "maxLines": "none",
@@ -911,6 +920,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
911
920
  "textAlign",
912
921
  "fontStyle",
913
922
  "textDecoration",
923
+ "fontVariantNumeric",
914
924
  "_sep_stroke",
915
925
  "WebkitTextStrokeWidth",
916
926
  "WebkitTextStrokeColor",
@@ -1009,6 +1019,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1009
1019
  "textAlign": "start",
1010
1020
  "fontStyle": "normal",
1011
1021
  "textDecoration": "none",
1022
+ "fontVariantNumeric": "normal",
1012
1023
  "WebkitTextStrokeWidth": "0px",
1013
1024
  "WebkitTextStrokeColor": "transparent",
1014
1025
  "maxLines": "none",
@@ -1098,6 +1109,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1098
1109
  "textAlign",
1099
1110
  "fontStyle",
1100
1111
  "textDecoration",
1112
+ "fontVariantNumeric",
1101
1113
  "_sep_stroke",
1102
1114
  "WebkitTextStrokeWidth",
1103
1115
  "WebkitTextStrokeColor",
@@ -1196,6 +1208,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1196
1208
  "textAlign": "start",
1197
1209
  "fontStyle": "normal",
1198
1210
  "textDecoration": "none",
1211
+ "fontVariantNumeric": "normal",
1199
1212
  "WebkitTextStrokeWidth": "0px",
1200
1213
  "WebkitTextStrokeColor": "transparent",
1201
1214
  "margin": "0px 0px 0px 0px",
@@ -1284,6 +1297,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1284
1297
  "textAlign",
1285
1298
  "fontStyle",
1286
1299
  "textDecoration",
1300
+ "fontVariantNumeric",
1287
1301
  "_sep_stroke",
1288
1302
  "WebkitTextStrokeWidth",
1289
1303
  "WebkitTextStrokeColor",
@@ -1385,6 +1399,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1385
1399
  "textAlign": "start",
1386
1400
  "fontStyle": "normal",
1387
1401
  "textDecoration": "none",
1402
+ "fontVariantNumeric": "normal",
1388
1403
  "WebkitTextStrokeWidth": "0px",
1389
1404
  "WebkitTextStrokeColor": "transparent",
1390
1405
  "margin": "0px 0px 0px 0px",
@@ -1478,6 +1493,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1478
1493
  "textAlign",
1479
1494
  "fontStyle",
1480
1495
  "textDecoration",
1496
+ "fontVariantNumeric",
1481
1497
  "_sep_stroke",
1482
1498
  "WebkitTextStrokeWidth",
1483
1499
  "WebkitTextStrokeColor",
@@ -1579,6 +1595,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1579
1595
  "textAlign": "start",
1580
1596
  "fontStyle": "normal",
1581
1597
  "textDecoration": "none",
1598
+ "fontVariantNumeric": "normal",
1582
1599
  "WebkitTextStrokeWidth": "0px",
1583
1600
  "WebkitTextStrokeColor": "transparent",
1584
1601
  "margin": "0px 0px 0px 0px",
@@ -1672,6 +1689,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1672
1689
  "textAlign",
1673
1690
  "fontStyle",
1674
1691
  "textDecoration",
1692
+ "fontVariantNumeric",
1675
1693
  "_sep_stroke",
1676
1694
  "WebkitTextStrokeWidth",
1677
1695
  "WebkitTextStrokeColor",
@@ -1768,6 +1786,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1768
1786
  "textAlign": "start",
1769
1787
  "fontStyle": "normal",
1770
1788
  "textDecoration": "none",
1789
+ "fontVariantNumeric": "normal",
1771
1790
  "WebkitTextStrokeWidth": "0px",
1772
1791
  "WebkitTextStrokeColor": "transparent",
1773
1792
  "margin": "0px 0px 0px 0px",
@@ -1855,6 +1874,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1855
1874
  "textAlign",
1856
1875
  "fontStyle",
1857
1876
  "textDecoration",
1877
+ "fontVariantNumeric",
1858
1878
  "_sep_stroke",
1859
1879
  "WebkitTextStrokeWidth",
1860
1880
  "WebkitTextStrokeColor",
@@ -1951,6 +1971,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
1951
1971
  "textAlign": "start",
1952
1972
  "fontStyle": "normal",
1953
1973
  "textDecoration": "none",
1974
+ "fontVariantNumeric": "normal",
1954
1975
  "WebkitTextStrokeWidth": "0px",
1955
1976
  "WebkitTextStrokeColor": "transparent",
1956
1977
  "margin": "0px 0px 0px 0px",
@@ -2038,6 +2059,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2038
2059
  "textAlign",
2039
2060
  "fontStyle",
2040
2061
  "textDecoration",
2062
+ "fontVariantNumeric",
2041
2063
  "_sep_stroke",
2042
2064
  "WebkitTextStrokeWidth",
2043
2065
  "WebkitTextStrokeColor",
@@ -2132,6 +2154,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2132
2154
  "textAlign": "start",
2133
2155
  "fontStyle": "normal",
2134
2156
  "textDecoration": "none",
2157
+ "fontVariantNumeric": "normal",
2135
2158
  "WebkitTextStrokeWidth": "0px",
2136
2159
  "WebkitTextStrokeColor": "transparent",
2137
2160
  "margin": "8px 0px 8px 0px",
@@ -2217,6 +2240,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2217
2240
  "textAlign",
2218
2241
  "fontStyle",
2219
2242
  "textDecoration",
2243
+ "fontVariantNumeric",
2220
2244
  "_sep_stroke",
2221
2245
  "WebkitTextStrokeWidth",
2222
2246
  "WebkitTextStrokeColor",
@@ -2311,6 +2335,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2311
2335
  "textAlign": "start",
2312
2336
  "fontStyle": "normal",
2313
2337
  "textDecoration": "none",
2338
+ "fontVariantNumeric": "normal",
2314
2339
  "WebkitTextStrokeWidth": "0px",
2315
2340
  "WebkitTextStrokeColor": "transparent",
2316
2341
  "margin": "0px 0px 0px 0px",
@@ -2396,6 +2421,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2396
2421
  "textAlign",
2397
2422
  "fontStyle",
2398
2423
  "textDecoration",
2424
+ "fontVariantNumeric",
2399
2425
  "_sep_stroke",
2400
2426
  "WebkitTextStrokeWidth",
2401
2427
  "WebkitTextStrokeColor",
@@ -2499,6 +2525,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2499
2525
  "textAlign": "start",
2500
2526
  "fontStyle": "normal",
2501
2527
  "textDecoration": "none",
2528
+ "fontVariantNumeric": "normal",
2502
2529
  "WebkitTextStrokeWidth": "0px",
2503
2530
  "WebkitTextStrokeColor": "transparent",
2504
2531
  "opacity": "1",
@@ -2587,6 +2614,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2587
2614
  "textAlign",
2588
2615
  "fontStyle",
2589
2616
  "textDecoration",
2617
+ "fontVariantNumeric",
2590
2618
  "_sep_stroke",
2591
2619
  "WebkitTextStrokeWidth",
2592
2620
  "WebkitTextStrokeColor",
@@ -2676,6 +2704,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2676
2704
  "textAlign": "start",
2677
2705
  "fontStyle": "normal",
2678
2706
  "textDecoration": "none",
2707
+ "fontVariantNumeric": "normal",
2679
2708
  "WebkitTextStrokeWidth": "0px",
2680
2709
  "WebkitTextStrokeColor": "transparent",
2681
2710
  "margin": "0px 0px 0px 0px",
@@ -2763,6 +2792,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2763
2792
  "textAlign",
2764
2793
  "fontStyle",
2765
2794
  "textDecoration",
2795
+ "fontVariantNumeric",
2766
2796
  "_sep_stroke",
2767
2797
  "WebkitTextStrokeWidth",
2768
2798
  "WebkitTextStrokeColor",
@@ -2860,6 +2890,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2860
2890
  "textAlign": "start",
2861
2891
  "fontStyle": "normal",
2862
2892
  "textDecoration": "none",
2893
+ "fontVariantNumeric": "normal",
2863
2894
  "WebkitTextStrokeWidth": "0px",
2864
2895
  "WebkitTextStrokeColor": "transparent",
2865
2896
  "margin": "0px 0px 0px 0px",
@@ -2953,6 +2984,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
2953
2984
  "textAlign",
2954
2985
  "fontStyle",
2955
2986
  "textDecoration",
2987
+ "fontVariantNumeric",
2956
2988
  "_sep_stroke",
2957
2989
  "WebkitTextStrokeWidth",
2958
2990
  "WebkitTextStrokeColor",
@@ -3270,6 +3302,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
3270
3302
  "textAlign": "start",
3271
3303
  "fontStyle": "normal",
3272
3304
  "textDecoration": "none",
3305
+ "fontVariantNumeric": "normal",
3273
3306
  "WebkitTextStrokeWidth": "0px",
3274
3307
  "WebkitTextStrokeColor": "transparent",
3275
3308
  "opacity": "1",
@@ -3347,6 +3380,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
3347
3380
  "textAlign",
3348
3381
  "fontStyle",
3349
3382
  "textDecoration",
3383
+ "fontVariantNumeric",
3350
3384
  "_sep_stroke",
3351
3385
  "WebkitTextStrokeWidth",
3352
3386
  "WebkitTextStrokeColor",
@@ -3580,6 +3614,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
3580
3614
  "textAlign": "start",
3581
3615
  "fontStyle": "normal",
3582
3616
  "textDecoration": "none",
3617
+ "fontVariantNumeric": "normal",
3583
3618
  "WebkitTextStrokeWidth": "0px",
3584
3619
  "WebkitTextStrokeColor": "transparent",
3585
3620
  "opacity": "1",
@@ -3673,6 +3708,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
3673
3708
  "textAlign",
3674
3709
  "fontStyle",
3675
3710
  "textDecoration",
3711
+ "fontVariantNumeric",
3676
3712
  "_sep_stroke",
3677
3713
  "WebkitTextStrokeWidth",
3678
3714
  "WebkitTextStrokeColor",
@@ -3775,6 +3811,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
3775
3811
  "textAlign": "start",
3776
3812
  "fontStyle": "normal",
3777
3813
  "textDecoration": "none",
3814
+ "fontVariantNumeric": "normal",
3778
3815
  "WebkitTextStrokeWidth": "0px",
3779
3816
  "WebkitTextStrokeColor": "transparent",
3780
3817
  "margin": "0px 0px 0px 0px",
@@ -3878,6 +3915,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
3878
3915
  "textAlign",
3879
3916
  "fontStyle",
3880
3917
  "textDecoration",
3918
+ "fontVariantNumeric",
3881
3919
  "_sep_stroke",
3882
3920
  "WebkitTextStrokeWidth",
3883
3921
  "WebkitTextStrokeColor",
@@ -3974,6 +4012,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
3974
4012
  "textAlign": "start",
3975
4013
  "fontStyle": "normal",
3976
4014
  "textDecoration": "none",
4015
+ "fontVariantNumeric": "normal",
3977
4016
  "WebkitTextStrokeWidth": "0px",
3978
4017
  "WebkitTextStrokeColor": "transparent",
3979
4018
  "margin": "0px 0px 0px 0px",
@@ -4061,6 +4100,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4061
4100
  "textAlign",
4062
4101
  "fontStyle",
4063
4102
  "textDecoration",
4103
+ "fontVariantNumeric",
4064
4104
  "_sep_stroke",
4065
4105
  "WebkitTextStrokeWidth",
4066
4106
  "WebkitTextStrokeColor",
@@ -4159,6 +4199,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4159
4199
  "textAlign": "start",
4160
4200
  "fontStyle": "normal",
4161
4201
  "textDecoration": "none",
4202
+ "fontVariantNumeric": "normal",
4162
4203
  "WebkitTextStrokeWidth": "0px",
4163
4204
  "WebkitTextStrokeColor": "transparent",
4164
4205
  "margin": "0px 0px 0px 0px",
@@ -4248,6 +4289,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4248
4289
  "textAlign",
4249
4290
  "fontStyle",
4250
4291
  "textDecoration",
4292
+ "fontVariantNumeric",
4251
4293
  "_sep_stroke",
4252
4294
  "WebkitTextStrokeWidth",
4253
4295
  "WebkitTextStrokeColor",
@@ -4344,6 +4386,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4344
4386
  "textAlign": "start",
4345
4387
  "fontStyle": "normal",
4346
4388
  "textDecoration": "none",
4389
+ "fontVariantNumeric": "normal",
4347
4390
  "WebkitTextStrokeWidth": "0px",
4348
4391
  "WebkitTextStrokeColor": "transparent",
4349
4392
  "margin": "0px 0px 0px 0px",
@@ -4431,6 +4474,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4431
4474
  "textAlign",
4432
4475
  "fontStyle",
4433
4476
  "textDecoration",
4477
+ "fontVariantNumeric",
4434
4478
  "_sep_stroke",
4435
4479
  "WebkitTextStrokeWidth",
4436
4480
  "WebkitTextStrokeColor",
@@ -4527,6 +4571,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4527
4571
  "textAlign": "start",
4528
4572
  "fontStyle": "normal",
4529
4573
  "textDecoration": "none",
4574
+ "fontVariantNumeric": "normal",
4530
4575
  "WebkitTextStrokeWidth": "0px",
4531
4576
  "WebkitTextStrokeColor": "transparent",
4532
4577
  "margin": "0px 0px 0px 0px",
@@ -4614,6 +4659,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4614
4659
  "textAlign",
4615
4660
  "fontStyle",
4616
4661
  "textDecoration",
4662
+ "fontVariantNumeric",
4617
4663
  "_sep_stroke",
4618
4664
  "WebkitTextStrokeWidth",
4619
4665
  "WebkitTextStrokeColor",
@@ -4716,6 +4762,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4716
4762
  "textAlign": "start",
4717
4763
  "fontStyle": "normal",
4718
4764
  "textDecoration": "none",
4765
+ "fontVariantNumeric": "normal",
4719
4766
  "WebkitTextStrokeWidth": "0px",
4720
4767
  "WebkitTextStrokeColor": "transparent",
4721
4768
  "margin": "0px 0px 0px 0px",
@@ -4811,6 +4858,7 @@ export const NODE_BASELINES: Readonly<Record<string, NodeBaseline>> = {
4811
4858
  "textAlign",
4812
4859
  "fontStyle",
4813
4860
  "textDecoration",
4861
+ "fontVariantNumeric",
4814
4862
  "_sep_stroke",
4815
4863
  "WebkitTextStrokeWidth",
4816
4864
  "WebkitTextStrokeColor",
@@ -5045,6 +5093,7 @@ export const NEUTRAL_STYLE_PROPS: Readonly<Record<string, unknown>> = {
5045
5093
  "textAlign": "start",
5046
5094
  "fontStyle": "normal",
5047
5095
  "textDecoration": "none",
5096
+ "fontVariantNumeric": "normal",
5048
5097
  "WebkitTextStrokeWidth": "0px",
5049
5098
  "WebkitTextStrokeColor": "transparent",
5050
5099
  "margin": "0px 0px 0px 0px",