@neatico/visual-core 0.14.26 → 0.14.65

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 (46) hide show
  1. package/dist/candidateRanking.d.ts +31 -0
  2. package/dist/candidateRanking.js +55 -0
  3. package/dist/cjs/candidateRanking.js +61 -0
  4. package/dist/cjs/compositionNumbers.js +111 -0
  5. package/dist/cjs/compositionUseCases.js +145 -0
  6. package/dist/cjs/content.js +46 -10
  7. package/dist/cjs/contentBrief.js +82 -0
  8. package/dist/cjs/designSystem.js +86 -9
  9. package/dist/cjs/exploreCollection.js +180 -0
  10. package/dist/cjs/fontCatalog.js +7 -1
  11. package/dist/cjs/formalCompositions.js +121 -0
  12. package/dist/cjs/index.js +14 -0
  13. package/dist/cjs/nativeSocialParameters.js +145 -0
  14. package/dist/cjs/pagination.js +14 -5
  15. package/dist/cjs/parameterDefaults.js +20 -0
  16. package/dist/cjs/recipeParameters.js +375 -0
  17. package/dist/cjs/styleManifest.js +107 -0
  18. package/dist/cjs/textPresentation.js +68 -0
  19. package/dist/compositionNumbers.d.ts +4 -0
  20. package/dist/compositionNumbers.js +108 -0
  21. package/dist/compositionUseCases.d.ts +1 -0
  22. package/dist/compositionUseCases.js +142 -0
  23. package/dist/content.d.ts +10 -0
  24. package/dist/content.js +46 -10
  25. package/dist/contentBrief.d.ts +16 -0
  26. package/dist/contentBrief.js +78 -0
  27. package/dist/designSystem.js +86 -9
  28. package/dist/exploreCollection.d.ts +7 -0
  29. package/dist/exploreCollection.js +176 -0
  30. package/dist/fontCatalog.js +7 -1
  31. package/dist/formalCompositions.d.ts +26 -0
  32. package/dist/formalCompositions.js +117 -0
  33. package/dist/index.d.ts +11 -0
  34. package/dist/index.js +11 -0
  35. package/dist/nativeSocialParameters.d.ts +38 -0
  36. package/dist/nativeSocialParameters.js +139 -0
  37. package/dist/pagination.js +14 -5
  38. package/dist/parameterDefaults.d.ts +2 -0
  39. package/dist/parameterDefaults.js +17 -0
  40. package/dist/recipeParameters.d.ts +34 -0
  41. package/dist/recipeParameters.js +371 -0
  42. package/dist/styleManifest.d.ts +20 -0
  43. package/dist/styleManifest.js +103 -0
  44. package/dist/textPresentation.d.ts +29 -0
  45. package/dist/textPresentation.js +64 -0
  46. package/package.json +1 -1
@@ -6,17 +6,91 @@ exports.canonicalRecipeId = canonicalRecipeId;
6
6
  exports.pageEntryCount = pageEntryCount;
7
7
  exports.designCandidates = designCandidates;
8
8
  exports.structureFingerprint = structureFingerprint;
9
+ const exploreCollection_js_1 = require("./exploreCollection.js");
9
10
  const compositionScenes_js_1 = require("./compositionScenes.js");
10
11
  const socialLayouts_js_1 = require("./socialLayouts.js");
11
12
  const content_js_1 = require("./content.js");
12
13
  /** Complete, deterministic token sets; decorative geometry belongs to individual compositions. */
13
14
  exports.DESIGN_THEMES = [
15
+ ...exploreCollection_js_1.EXPLORE_THEMES,
14
16
  {
15
17
  id: "neatico",
16
18
  palette: { background: "#FAF9F6", surface: "#FFFFFF", ink: "#202124", muted: "#62646B", accent: "#F4CE36", line: "#E4E1D9" },
17
- typography: { heading: "Inter", body: "Inter", code: "monospace", headingWeight: 700 },
19
+ typography: { heading: "Manrope", body: "Inter", code: "monospace", headingWeight: 700 },
18
20
  geometry: { radius: 12, spacing: 1, rule: "accent" },
19
21
  },
22
+ {
23
+ id: "archive",
24
+ palette: { background: "#F6F1E7", surface: "#FFFCF5", ink: "#19382E", muted: "#59665B", accent: "#C17A35", line: "#D7CEBC" },
25
+ typography: { heading: "Instrument Serif", body: "DM Sans", code: "JetBrains Mono", headingWeight: 400 },
26
+ geometry: { radius: 4, spacing: 1.1, rule: "hairline" },
27
+ },
28
+ {
29
+ "id": "bloom",
30
+ "palette": {
31
+ "background": "#FFF1F6",
32
+ "surface": "#FFFFFF",
33
+ "ink": "#341838",
34
+ "muted": "#70536D",
35
+ "accent": "#CC1D61",
36
+ "line": "#F3BED5"
37
+ },
38
+ "typography": {
39
+ "heading": "Montserrat",
40
+ "body": "Nunito Sans",
41
+ "code": "JetBrains Mono",
42
+ "headingWeight": 800
43
+ },
44
+ "geometry": {
45
+ "radius": 20,
46
+ "spacing": 1,
47
+ "rule": "accent"
48
+ }
49
+ },
50
+ {
51
+ "id": "splash",
52
+ "palette": {
53
+ "background": "#E9FAFF",
54
+ "surface": "#FFFFFF",
55
+ "ink": "#162E60",
56
+ "muted": "#4D637E",
57
+ "accent": "#2454E6",
58
+ "line": "#B8DEFA"
59
+ },
60
+ "typography": {
61
+ "heading": "Space Grotesk",
62
+ "body": "DM Sans",
63
+ "code": "JetBrains Mono",
64
+ "headingWeight": 700
65
+ },
66
+ "geometry": {
67
+ "radius": 20,
68
+ "spacing": 1,
69
+ "rule": "accent"
70
+ }
71
+ },
72
+ {
73
+ "id": "candy",
74
+ "palette": {
75
+ "background": "#F3EDFF",
76
+ "surface": "#FFFFFF",
77
+ "ink": "#35205C",
78
+ "muted": "#69557F",
79
+ "accent": "#7841D5",
80
+ "line": "#DCCAF6"
81
+ },
82
+ "typography": {
83
+ "heading": "Manrope",
84
+ "body": "Nunito Sans",
85
+ "code": "JetBrains Mono",
86
+ "headingWeight": 800
87
+ },
88
+ "geometry": {
89
+ "radius": 20,
90
+ "spacing": 1,
91
+ "rule": "accent"
92
+ }
93
+ },
20
94
  {
21
95
  id: "studio",
22
96
  palette: {
@@ -28,8 +102,8 @@ exports.DESIGN_THEMES = [
28
102
  line: "#D7DED3",
29
103
  },
30
104
  typography: {
31
- heading: "Inter",
32
- body: "Inter",
105
+ heading: "DM Sans",
106
+ body: "Source Sans 3",
33
107
  code: "monospace",
34
108
  headingWeight: 700,
35
109
  },
@@ -46,7 +120,7 @@ exports.DESIGN_THEMES = [
46
120
  line: "#3D526C",
47
121
  },
48
122
  typography: {
49
- heading: "Inter",
123
+ heading: "Space Grotesk",
50
124
  body: "Inter",
51
125
  code: "monospace",
52
126
  headingWeight: 700,
@@ -65,7 +139,7 @@ exports.DESIGN_THEMES = [
65
139
  },
66
140
  typography: {
67
141
  heading: "Lora",
68
- body: "Inter",
142
+ body: "Source Sans 3",
69
143
  code: "monospace",
70
144
  headingWeight: 700,
71
145
  },
@@ -82,8 +156,8 @@ exports.DESIGN_THEMES = [
82
156
  line: "#DAD5F2",
83
157
  },
84
158
  typography: {
85
- heading: "Inter",
86
- body: "Inter",
159
+ heading: "Space Grotesk",
160
+ body: "DM Sans",
87
161
  code: "monospace",
88
162
  headingWeight: 800,
89
163
  },
@@ -100,7 +174,7 @@ exports.DESIGN_THEMES = [
100
174
  line: "#B8A233",
101
175
  },
102
176
  typography: {
103
- heading: "Inter",
177
+ heading: "Oswald",
104
178
  body: "Inter",
105
179
  code: "monospace",
106
180
  headingWeight: 800,
@@ -116,7 +190,7 @@ function designTheme(id) {
116
190
  plum: "electric",
117
191
  };
118
192
  return (exports.DESIGN_THEMES.find((theme) => theme.id === (alias[id] || id)) ||
119
- exports.DESIGN_THEMES[0]);
193
+ exports.DESIGN_THEMES.find(theme => theme.id === "neatico"));
120
194
  }
121
195
  const family = (id, semantic) => {
122
196
  if (/code|terminal/.test(id))
@@ -298,6 +372,7 @@ function canonicalRecipeId(id, kind) {
298
372
  }
299
373
  /** Existing authored catalogs remain first-class candidates, rather than being discarded. */
300
374
  const ALL_DESIGN_RECIPES = [
375
+ ...exploreCollection_js_1.EXPLORE_RECIPES,
301
376
  ...["cover", "closing"].flatMap((role) => ["editorial", "panel", "split"].map((style) => ({
302
377
  id: `bookend-${role}-${style}`,
303
378
  kind: "presentation",
@@ -436,6 +511,7 @@ function designCandidates(page, context) {
436
511
  const available = page.blocks.some((b) => b.kind === "image" && b.status === "available");
437
512
  const exclude = new Set(context.excluded || []);
438
513
  const candidates = exports.DESIGN_RECIPES.filter((r) => r.kind === context.kind &&
514
+ (!r.id.startsWith("authored-explore-") || (context.ratio >= 1.4 && context.ratio <= 2 && (0, exploreCollection_js_1.exploreCompositionFits)(page, r.id))) &&
439
515
  r.automatic !== false &&
440
516
  (!r.scenes || Boolean(page.scene && r.scenes.includes(page.scene))) &&
441
517
  !(r.family.startsWith("hero") &&
@@ -463,6 +539,7 @@ function designCandidates(page, context) {
463
539
  ? r.family.startsWith("steps") || r.family.startsWith("code")
464
540
  : true;
465
541
  return ((r.id.startsWith("bookend-") ? 80 : 0) +
542
+ (r.id.startsWith("authored-explore-") ? 110 : 0) +
466
543
  (page.scene === "brand-collection" && r.id === "brand-collection-grid"
467
544
  ? 80
468
545
  : 0) +
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EXPLORE_RECIPES = exports.EXPLORE_LAYOUTS = exports.EXPLORE_THEMES = exports.DEFAULT_PRESENTATION_THEME = void 0;
4
+ exports.exploreCompositionFits = exploreCompositionFits;
5
+ exports.DEFAULT_PRESENTATION_THEME = "explore-teal";
6
+ /** The proven Explore editorial colorways, plus eight complementary directions. */
7
+ const colors = [
8
+ ["teal", "#214B4A", "#E1EEEB", "#F7FAF9", "#1C3533"],
9
+ ["slate", "#3F5477", "#E6EAF1", "#F9FAFC", "#1D283B"],
10
+ ["cobalt", "#2847A9", "#E5EBFC", "#F8FAFF", "#19294E"],
11
+ ["clay", "#9D4F32", "#F8E7DE", "#FFFAF6", "#3F2920"],
12
+ ["terracotta", "#AC3F25", "#FBE5DC", "#FFFAF5", "#3E241B"],
13
+ ["lavender", "#6A497B", "#EEE6F5", "#FCFAFD", "#34243D"],
14
+ ["petrol", "#315664", "#E2EDF1", "#F8FBFC", "#223E48"],
15
+ ["sand", "#6D5140", "#EFE4D8", "#FCFAF7", "#392C23"],
16
+ ["indigo", "#43387D", "#EAE5F6", "#FAF9FD", "#292444"],
17
+ ["olive", "#4F633A", "#E8EEDC", "#FBFCF8", "#2D3824"],
18
+ ["rose", "#9B3E61", "#F6E2EB", "#FFFAFC", "#402332"],
19
+ ["wine", "#7A3048", "#EFDEE5", "#FCF8FA", "#39202C"],
20
+ ["sunflower", "#8A5D12", "#F7EBC6", "#FFFDF5", "#392F1D"],
21
+ ["seafoam", "#216C62", "#DDF0E8", "#F7FCFA", "#193D36"],
22
+ ["graphite", "#D5B98C", "#30343A", "#1B1E23", "#F5F2EA"],
23
+ ["midnight", "#91B7DE", "#22344C", "#132236", "#F3F6FA"],
24
+ ["ice", "#27697B", "#DDEFF5", "#F8FCFE", "#193C49"],
25
+ ["copper", "#9A563B", "#F1E2D7", "#FCF9F5", "#3F2C23"],
26
+ ];
27
+ exports.EXPLORE_THEMES = colors.map(([id, accent, surface, background, ink]) => ({
28
+ id: `explore-${id}`,
29
+ palette: { accent, surface, background, ink, muted: ink, line: surface },
30
+ typography: {
31
+ heading: "Playfair Display",
32
+ body: "Inter",
33
+ code: "JetBrains Mono",
34
+ headingWeight: 600,
35
+ },
36
+ geometry: { radius: 4, spacing: 1.1, rule: "hairline" },
37
+ }));
38
+ exports.EXPLORE_LAYOUTS = [
39
+ [
40
+ "cover",
41
+ "paragraph",
42
+ 0,
43
+ 0,
44
+ "Open with a spacious editorial headline, a short premise and an optional real photograph.",
45
+ ],
46
+ [
47
+ "overview",
48
+ "features",
49
+ 2,
50
+ 4,
51
+ "Orient readers with a numbered overview of parallel subjects.",
52
+ ],
53
+ [
54
+ "section",
55
+ "paragraph",
56
+ 0,
57
+ 0,
58
+ "Introduce one new section or central principle in a strong color field.",
59
+ ],
60
+ [
61
+ "pillars",
62
+ "features",
63
+ 2,
64
+ 3,
65
+ "Explain two or three equally important ideas in spacious editorial columns.",
66
+ ],
67
+ [
68
+ "focus",
69
+ "paragraph",
70
+ 0,
71
+ 0,
72
+ "Develop one idea in an asymmetric reading composition.",
73
+ ],
74
+ [
75
+ "workflow",
76
+ "steps",
77
+ 2,
78
+ 4,
79
+ "Show an ordered workflow with explicit actions and useful descriptions.",
80
+ ],
81
+ [
82
+ "timeline",
83
+ "steps",
84
+ 2,
85
+ 4,
86
+ "Present a short chronological sequence on a horizontal reading axis.",
87
+ ],
88
+ [
89
+ "comparison",
90
+ "comparison",
91
+ 2,
92
+ 2,
93
+ "Compare two supplied alternatives with corresponding points.",
94
+ ],
95
+ [
96
+ "worksheet",
97
+ "parameters",
98
+ 2,
99
+ 4,
100
+ "Explain named fields with their concrete values and instructions.",
101
+ ],
102
+ [
103
+ "photo-story",
104
+ "image",
105
+ 0,
106
+ 0,
107
+ "Use a real contextual photograph beside a concise explanation.",
108
+ ],
109
+ [
110
+ "quote",
111
+ "quote",
112
+ 0,
113
+ 0,
114
+ "Give an exact source statement room to breathe, retaining supplied attribution.",
115
+ ],
116
+ [
117
+ "chart",
118
+ "chart",
119
+ 2,
120
+ 6,
121
+ "Compare source-backed quantities in labeled bars with the original unit.",
122
+ ],
123
+ [
124
+ "ledger",
125
+ "parameters",
126
+ 2,
127
+ 5,
128
+ "Arrange named facts and explanations in a flat editorial ledger.",
129
+ ],
130
+ [
131
+ "faq",
132
+ "features",
133
+ 2,
134
+ 3,
135
+ "Answer a small set of meaningful questions with concise responses.",
136
+ ],
137
+ [
138
+ "action-plan",
139
+ "steps",
140
+ 2,
141
+ 3,
142
+ "Make the next few actions prominent, with descriptions that explain the work.",
143
+ ],
144
+ [
145
+ "closing",
146
+ "paragraph",
147
+ 0,
148
+ 0,
149
+ "Close with one clear takeaway and a concrete next action.",
150
+ ],
151
+ ];
152
+ exports.EXPLORE_RECIPES = exports.EXPLORE_LAYOUTS.map(([id, kind, min, max]) => ({
153
+ id: `authored-explore-${id}`,
154
+ kind: "presentation",
155
+ renderer: "semantic",
156
+ automatic: true,
157
+ family: kind === "paragraph" ? `hero-explore-${id}` : kind,
158
+ minEntries: min,
159
+ maxEntries: max,
160
+ accepts: (["cover", "photo-story"].includes(id)
161
+ ? ["paragraph", "image"]
162
+ : [kind]),
163
+ requiresImage: id === "photo-story",
164
+ }));
165
+ function exploreCompositionFits(page, id) {
166
+ if (!id.startsWith("authored-explore-"))
167
+ return true;
168
+ const variant = id.slice("authored-explore-".length);
169
+ if (variant === "cover")
170
+ return page.purpose === "cover";
171
+ if (variant === "closing")
172
+ return page.purpose === "conclude";
173
+ if (["cover", "conclude"].includes(page.purpose))
174
+ return false;
175
+ if (variant === "section")
176
+ return (page.blocks.length === 1 &&
177
+ page.blocks[0].kind === "paragraph" &&
178
+ page.blocks[0].text.length <= 160);
179
+ return true;
180
+ }
@@ -28,6 +28,7 @@ exports.GOOGLE_FONT_CATALOG = [
28
28
  "Playfair Display",
29
29
  "PT Serif",
30
30
  ].map((f) => entry(f, "serif")),
31
+ entry("Instrument Serif", "serif", ["latin"], [400]),
31
32
  ...["Space Grotesk", "Oswald", "Bebas Neue"].map((f) => entry(f, "display", ["latin"], f === "Bebas Neue" ? [400] : [400, 700])),
32
33
  ...["JetBrains Mono", "IBM Plex Mono", "Fira Code", "Source Code Pro"].map((f) => entry(f, "mono")),
33
34
  entry("Noto Sans SC", "sans", ["zh"]),
@@ -43,6 +44,9 @@ exports.GOOGLE_FONT_CATALOG = [
43
44
  entry("Noto Serif KR", "serif", ["ko"]),
44
45
  entry("Noto Sans Arabic", "sans", ["ar"]),
45
46
  entry("Noto Sans Devanagari", "sans", ["hi"]),
47
+ entry("Noto Serif Devanagari", "serif", ["hi"]),
48
+ entry("Noto Sans Thai", "sans", ["th"]),
49
+ entry("Noto Serif Thai", "serif", ["th"]),
46
50
  ];
47
51
  function contentScript(text, locale = "en") {
48
52
  if (/[\u3040-\u30ff]/u.test(text))
@@ -53,6 +57,8 @@ function contentScript(text, locale = "en") {
53
57
  return "ar";
54
58
  if (/[\u0900-\u097f]/u.test(text))
55
59
  return "hi";
60
+ if (/[\u0e00-\u0e7f]/u.test(text))
61
+ return "th";
56
62
  if (/[\u3400-\u9fff]/u.test(text))
57
63
  return /^ja/i.test(locale)
58
64
  ? "ja"
@@ -63,7 +69,7 @@ function contentScript(text, locale = "en") {
63
69
  : "zh";
64
70
  if (/^zh/i.test(locale))
65
71
  return /TW|HK|Hant/i.test(locale) ? "zh-Hant" : "zh";
66
- return /^(ja|ko|ar|hi)/.exec(locale)?.[1] || "latin";
72
+ return /^(ja|ko|ar|hi|th)/.exec(locale)?.[1] || "latin";
67
73
  }
68
74
  function recommendedFonts(locale, text = "") {
69
75
  const script = contentScript(text, locale);
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FORMAL_COMPOSITIONS = exports.FORMAL_REFERENCE_COMPOSITIONS = void 0;
4
+ exports.applicableCompositions = applicableCompositions;
5
+ const exploreCollection_js_1 = require("./exploreCollection.js");
6
+ const compositionUseCases_js_1 = require("./compositionUseCases.js");
7
+ const nativeSocialParameters_js_1 = require("./nativeSocialParameters.js");
8
+ const designSystem_js_1 = require("./designSystem.js");
9
+ const socialLayouts_js_1 = require("./socialLayouts.js");
10
+ const recipeParameters_js_1 = require("./recipeParameters.js");
11
+ const compositionNumbers_js_1 = require("./compositionNumbers.js");
12
+ const both = ['presentation', 'social'];
13
+ const semantic = (id, accepts, minEntries = 0, maxEntries = 12, requiresImage = false) => ({ id, renderer: 'semantic', kind: 'social', family: id, accepts, minEntries, maxEntries, requiresImage });
14
+ function define(recipe, kinds, id, displayNumber, min = .25, max = 4) {
15
+ return { ...(0, recipeParameters_js_1.recipeParameterContract)(recipe, kinds), semanticDescription: exploreCollection_js_1.EXPLORE_LAYOUTS.find(item => recipe.id === `authored-explore-${item[0]}`)?.[4] || (0, compositionUseCases_js_1.compositionUseCase)(recipe.id), id, displayNumber, aspectRatios: { min, max }, recipe };
16
+ }
17
+ /** Structural reference contracts shared with the product's existing renderers.
18
+ * Colorways and historical aliases remain outside active discovery.
19
+ */
20
+ exports.FORMAL_REFERENCE_COMPOSITIONS = [
21
+ { id: 'authored-reference-photo', reference: 1, layout: 'authored-photo-editorial', accepts: ['image', 'paragraph'] },
22
+ { id: 'authored-reference-manifesto', reference: 2, layout: 'authored-type-manifesto', accepts: ['paragraph'] },
23
+ { id: 'authored-reference-journey', reference: 3, layout: 'authored-editorial-flow', accepts: ['steps'] },
24
+ { id: 'authored-reference-vision', reference: 4, layout: 'authored-editorial-features', accepts: ['features'] },
25
+ { id: 'authored-reference-matrix', reference: 5, layout: 'authored-editorial-matrix', accepts: ['comparison', 'paragraph'] },
26
+ { id: 'authored-reference-diagonal', reference: 6, layout: 'authored-diagonal-cover', accepts: ['paragraph'] },
27
+ { id: 'authored-reference-list', reference: 8, layout: 'authored-editorial-index', accepts: ['features'] },
28
+ { id: 'authored-reference-story', reference: 11, layout: 'authored-visual-poster', accepts: ['image', 'paragraph', 'features'] },
29
+ { id: 'authored-reference-sustainable', reference: 13, layout: 'authored-editorial-metrics', accepts: ['parameters'] },
30
+ { id: 'authored-reference-code', reference: 14, layout: 'authored-code-panel', accepts: ['code'] },
31
+ { id: 'authored-reference-bars', reference: 18, layout: 'authored-editorial-bars', accepts: ['chart'] },
32
+ { id: 'authored-reference-share', reference: 19, layout: 'authored-editorial-donut', accepts: ['chart'] },
33
+ { id: 'authored-reference-opinion', reference: 20, layout: 'authored-editorial-quote', accepts: ['quote'] },
34
+ { id: 'authored-reference-comparison', reference: 22, layout: 'authored-editorial-comparison', accepts: ['comparison'] },
35
+ { id: 'authored-reference-faq', reference: 23, layout: 'authored-editorial-faq', accepts: ['features'] },
36
+ { id: 'authored-reference-trend', reference: 25, layout: 'authored-editorial-trend', accepts: ['chart'] },
37
+ ];
38
+ const semanticRecipes = designSystem_js_1.DESIGN_RECIPES.filter(recipe => recipe.renderer === 'semantic');
39
+ const uniqueSemantic = semanticRecipes.filter((recipe, index) => semanticRecipes.findIndex(other => other.id === recipe.id) === index);
40
+ const campaignDefinitions = [
41
+ ['ledger-chart', ['parameters', 'chart'], 2, 6, false, true],
42
+ ['detail-sidebar', ['paragraph', 'parameters'], 1, 3, false, true],
43
+ ['technical-log', ['code', 'paragraph'], 0, 12, false, false],
44
+ ['architecture-stack', ['steps', 'paragraph'], 2, 4, false, false],
45
+ ['speaker-spotlight', ['quote', 'parameters'], 1, 6, true, false],
46
+ ['speaker-lineup', ['quote', 'parameters'], 1, 6, true, false],
47
+ ];
48
+ const founderDefinitions = [
49
+ ['authored-mechanism-flow', ['features', 'steps', 'paragraph'], 2, 4],
50
+ ['authored-reference-capability-map', ['features', 'paragraph'], 2, 4],
51
+ ['authored-founder-timeline', ['steps', 'paragraph'], 2, 4],
52
+ ['authored-founder-comparison', ['comparison', 'paragraph'], 2, 2],
53
+ ];
54
+ const articleKinds = ['features', 'process', 'comparison', 'summary', 'checklist', 'faq', 'chart'];
55
+ const articleAccepts = { features: ['features', 'paragraph'], process: ['steps', 'paragraph'], comparison: ['comparison', 'paragraph'], summary: ['paragraph', 'features'], checklist: ['features', 'paragraph'], faq: ['features', 'paragraph'], chart: ['chart', 'paragraph'] };
56
+ function article(id, kind, variant) {
57
+ const cover = kind === 'cover';
58
+ const recipe = semantic(id, cover ? ['paragraph', 'features', 'image'] : articleAccepts[kind], 0, kind === 'chart' ? 12 : 3);
59
+ const number = cover ? variant + 1 : kind === 'features' && variant >= 3 ? 22 + variant : kind === 'process' && variant === 3 ? 33 : 4 + articleKinds.indexOf(kind) * 3 + variant;
60
+ const definition = define(recipe, [cover ? 'article-cover' : 'article-illustration'], id, `A${String(number).padStart(3, '0')}`, .5, 2.4);
61
+ // A cover is a headline, a short deck and its authored hero. It is not a
62
+ // miniature article: the original source remains in the candidate pool.
63
+ const coverSchema = { type: 'object', additionalProperties: false, required: ['title', 'blocks'], properties: {
64
+ title: { type: 'string', minLength: 1, maxLength: 72, description: 'A concise editorial headline, preferably four to eight words.' },
65
+ blocks: { type: 'array', minItems: 1, maxItems: 1, items: { type: 'object', additionalProperties: false, required: ['id', 'kind', 'text', 'evidence'], properties: {
66
+ id: { type: 'string', minLength: 1, maxLength: 80 }, kind: { const: 'paragraph' }, text: { type: 'string', minLength: 1, maxLength: 140, description: 'One concise supporting sentence. Summarize the topic; do not repeat the full article or enumerate every feature.' },
67
+ evidence: { type: 'array', minItems: 1, maxItems: 32, items: { type: 'object', additionalProperties: false, required: ['sourceId'], properties: { sourceId: { type: 'string', maxLength: 160 }, quote: { type: 'string', maxLength: 2000 } } } },
68
+ } } },
69
+ } };
70
+ // The optional hero preserves compatibility with saved paragraph-only pools.
71
+ // New requests can reference a real asset; missing assets retain native artwork.
72
+ const coverWithHero = { ...coverSchema, properties: { ...coverSchema.properties, blocks: { ...coverSchema.properties.blocks, maxItems: 2,
73
+ description: 'One supporting paragraph and, when imagery helps explain the topic, one image hero. Use an available asset ID or a missing image request; never invent a photo URL.',
74
+ items: [coverSchema.properties.blocks.items, { type: 'object', additionalProperties: false, required: ['id', 'kind', 'sourceId', 'alt', 'treatment', 'status', 'evidence'], properties: {
75
+ id: { type: 'string', minLength: 1, maxLength: 80 }, kind: { const: 'image' }, sourceId: { type: 'string', maxLength: 160 },
76
+ alt: { type: 'string', minLength: 1, maxLength: 300, description: 'A concise description of the image subject, grounded in the article topic.' },
77
+ treatment: { enum: ['photograph', 'diagram', 'screenshot'] }, status: { enum: ['available', 'missing'] }, assetId: { type: 'string', maxLength: 200 },
78
+ evidence: coverSchema.properties.blocks.items.properties.evidence,
79
+ } }],
80
+ } } };
81
+ const illustrationSchema = JSON.parse(JSON.stringify(definition.parameterSchema));
82
+ if (!cover) {
83
+ const primaryKind = kind === 'summary' ? 'features' : articleAccepts[kind][0];
84
+ const blocks = illustrationSchema.properties.blocks;
85
+ const primary = blocks.items.find((block) => block.properties.kind.const === primaryKind);
86
+ blocks.items = [primary];
87
+ blocks.minItems = 1;
88
+ blocks.maxItems = 1;
89
+ if (kind === 'faq')
90
+ primary.properties.entries.items.properties.title.pattern = '^.+[??]$';
91
+ }
92
+ const coverDirections = ['An editorial document sculpture with layered planes and a strong headline.', 'A connected constellation with a single focal object and an editorial headline.', 'An architectural archive silhouette balanced against expressive editorial typography.'];
93
+ return { ...definition, ...(cover ? { parameterSchema: coverWithHero, capacity: { minEntries: 0, maxEntries: 0, requiresImage: false }, semanticDescription: coverDirections[variant] } : { parameterSchema: illustrationSchema }), recipe: undefined, rendererKey: `article-${kind}:${variant}`,
94
+ semanticDescription: (0, compositionUseCases_js_1.compositionUseCase)(id) + (cover ? ' ' + coverDirections[variant] : '') };
95
+ }
96
+ /** Matches /dev/compositions/all: 161 default previews plus two landscape-only
97
+ * reference entries. Output capabilities overlap and must never be summed.
98
+ */
99
+ exports.FORMAL_COMPOSITIONS = [
100
+ ...campaignDefinitions.map(([id, accepts, min, max, image, landscape], index) => define(semantic(`authored-reference-${id}`, accepts, min, max, image), landscape ? ['presentation'] : both, `new-reference:${id}`, `N${index + 1}`, landscape ? 1.4 : .25)),
101
+ define(semantic('authored-event-poster', ['parameters', 'paragraph'], 1, 6), ['social'], 'event:provider', 'E1'),
102
+ define(semantic('authored-image-triptych', ['paragraph', 'features', 'image'], 3, 3, true), ['social'], 'campaign:triptych', 'C1', .5, 2),
103
+ ...exports.FORMAL_REFERENCE_COMPOSITIONS.map(spec => define(semantic(spec.id, spec.accepts, 0, 12, spec.accepts.includes('image')), both, `reference:${spec.id}`, `R${String(spec.reference).padStart(2, '0')}`)),
104
+ ...socialLayouts_js_1.SOCIAL_LAYOUT_CATALOG.map(preset => {
105
+ const recipe = designSystem_js_1.DESIGN_RECIPES.find(item => item.id === preset.id && item.kind === 'social');
106
+ return { ...define({ ...recipe, renderer: 'catalog' }, ['social'], `social:${preset.id}`, compositionNumbers_js_1.SOCIAL_DISPLAY_NUMBERS[preset.id], .5, 2.4), ...(0, nativeSocialParameters_js_1.nativeSocialParameterContract)(preset.id) };
107
+ }),
108
+ ...uniqueSemantic.map(recipe => define(recipe, semanticRecipes.filter(other => other.id === recipe.id).map(other => other.kind), `semantic:${recipe.kind}:${recipe.id}`, recipe.id.startsWith("authored-explore-") ? `X${String(exploreCollection_js_1.EXPLORE_LAYOUTS.findIndex(item => recipe.id === `authored-explore-${item[0]}`) + 1).padStart(2, "0")}` : compositionNumbers_js_1.SEMANTIC_DISPLAY_NUMBERS[`semantic:${recipe.kind}:${recipe.id}`], recipe.id.startsWith("authored-explore-") ? 1.4 : .25, recipe.id.startsWith("authored-explore-") ? 2 : 4)),
109
+ ...founderDefinitions.map(([id, accepts, min, max], index) => define(semantic(id, accepts, min, max), ['social'], `semantic:social:${id}`, `F${index + 1}`, 1.3)),
110
+ ...[0, 1, 2].flatMap(variant => [article(`article-cover-${variant}`, 'cover', variant), ...articleKinds.map(kind => article(`article-${kind}-${variant}`, kind, variant))]),
111
+ ...[3, 4, 5, 6, 7, 8, 9, 10].map(variant => article(`article-features-${variant}`, 'features', variant)),
112
+ article('article-process-3', 'process', 3),
113
+ ];
114
+ /** Only output, ratio, and explicit IDs are hard gates; semantic fit is scored. */
115
+ function applicableCompositions(kind, ratio, id) {
116
+ if (!Number.isFinite(ratio) || ratio <= 0)
117
+ throw new Error('COMPOSITION_INVALID_RATIO');
118
+ if (id && !exports.FORMAL_COMPOSITIONS.some(item => item.id === id))
119
+ throw new Error('COMPOSITION_UNKNOWN_ID');
120
+ return exports.FORMAL_COMPOSITIONS.filter(item => item.supportedKinds.includes(kind) && ratio >= item.aspectRatios.min && ratio <= item.aspectRatios.max && (!id || item.id === id));
121
+ }
package/dist/cjs/index.js CHANGED
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.SOCIAL_DISPLAY_NUMBERS = exports.compositionParameterDefaults = void 0;
17
18
  __exportStar(require("./geometry.js"), exports);
18
19
  __exportStar(require("./text.js"), exports);
19
20
  __exportStar(require("./scenes.js"), exports);
@@ -29,3 +30,16 @@ __exportStar(require("./designBlueprint.js"), exports);
29
30
  __exportStar(require("./compositionScenes.js"), exports);
30
31
  __exportStar(require("./editorial.js"), exports);
31
32
  __exportStar(require("./fontCatalog.js"), exports);
33
+ __exportStar(require("./candidateRanking.js"), exports);
34
+ __exportStar(require("./styleManifest.js"), exports);
35
+ __exportStar(require("./recipeParameters.js"), exports);
36
+ __exportStar(require("./formalCompositions.js"), exports);
37
+ __exportStar(require("./contentBrief.js"), exports);
38
+ __exportStar(require("./nativeSocialParameters.js"), exports);
39
+ __exportStar(require("./compositionUseCases.js"), exports);
40
+ var parameterDefaults_js_1 = require("./parameterDefaults.js");
41
+ Object.defineProperty(exports, "compositionParameterDefaults", { enumerable: true, get: function () { return parameterDefaults_js_1.compositionParameterDefaults; } });
42
+ var compositionNumbers_js_1 = require("./compositionNumbers.js");
43
+ Object.defineProperty(exports, "SOCIAL_DISPLAY_NUMBERS", { enumerable: true, get: function () { return compositionNumbers_js_1.SOCIAL_DISPLAY_NUMBERS; } });
44
+ __exportStar(require("./textPresentation.js"), exports);
45
+ __exportStar(require("./exploreCollection.js"), exports);