@neatico/visual-core 0.14.3 → 0.14.64

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 (68) 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/composition.js +62 -36
  5. package/dist/cjs/compositionNumbers.js +111 -0
  6. package/dist/cjs/compositionScenes.js +91 -38
  7. package/dist/cjs/compositionUseCases.js +145 -0
  8. package/dist/cjs/content.js +574 -120
  9. package/dist/cjs/contentBrief.js +82 -0
  10. package/dist/cjs/designBlueprint.js +94 -19
  11. package/dist/cjs/designSystem.js +536 -77
  12. package/dist/cjs/editorial.js +76 -20
  13. package/dist/cjs/fontCatalog.js +81 -23
  14. package/dist/cjs/formalCompositions.js +120 -0
  15. package/dist/cjs/index.js +13 -0
  16. package/dist/cjs/layoutContracts.js +57 -11
  17. package/dist/cjs/layouts.js +5 -92
  18. package/dist/cjs/nativeSocialParameters.js +145 -0
  19. package/dist/cjs/pagination.js +27 -7
  20. package/dist/cjs/parameterDefaults.js +20 -0
  21. package/dist/cjs/recipeParameters.js +304 -0
  22. package/dist/cjs/socialLayouts.js +127 -387
  23. package/dist/cjs/styleManifest.js +107 -0
  24. package/dist/cjs/text.js +12 -2
  25. package/dist/cjs/textPresentation.js +68 -0
  26. package/dist/composition.d.ts +4 -4
  27. package/dist/composition.js +62 -36
  28. package/dist/compositionNumbers.d.ts +4 -0
  29. package/dist/compositionNumbers.js +108 -0
  30. package/dist/compositionScenes.d.ts +2 -2
  31. package/dist/compositionScenes.js +91 -38
  32. package/dist/compositionUseCases.d.ts +1 -0
  33. package/dist/compositionUseCases.js +142 -0
  34. package/dist/content.d.ts +65 -20
  35. package/dist/content.js +575 -121
  36. package/dist/contentBrief.d.ts +16 -0
  37. package/dist/contentBrief.js +78 -0
  38. package/dist/designBlueprint.d.ts +4 -4
  39. package/dist/designBlueprint.js +95 -20
  40. package/dist/designSystem.d.ts +11 -7
  41. package/dist/designSystem.js +537 -79
  42. package/dist/editorial.d.ts +1 -1
  43. package/dist/editorial.js +77 -21
  44. package/dist/fontCatalog.d.ts +1 -1
  45. package/dist/fontCatalog.js +81 -23
  46. package/dist/formalCompositions.d.ts +26 -0
  47. package/dist/formalCompositions.js +116 -0
  48. package/dist/index.d.ts +10 -0
  49. package/dist/index.js +10 -0
  50. package/dist/layoutContracts.d.ts +3 -3
  51. package/dist/layoutContracts.js +58 -12
  52. package/dist/layouts.d.ts +2 -2
  53. package/dist/layouts.js +5 -92
  54. package/dist/nativeSocialParameters.d.ts +38 -0
  55. package/dist/nativeSocialParameters.js +139 -0
  56. package/dist/pagination.js +27 -7
  57. package/dist/parameterDefaults.d.ts +2 -0
  58. package/dist/parameterDefaults.js +17 -0
  59. package/dist/recipeParameters.d.ts +34 -0
  60. package/dist/recipeParameters.js +300 -0
  61. package/dist/socialLayouts.d.ts +40 -232
  62. package/dist/socialLayouts.js +127 -387
  63. package/dist/styleManifest.d.ts +20 -0
  64. package/dist/styleManifest.js +103 -0
  65. package/dist/text.js +12 -2
  66. package/dist/textPresentation.d.ts +29 -0
  67. package/dist/textPresentation.js +64 -0
  68. package/package.json +1 -1
@@ -0,0 +1,31 @@
1
+ /** Versioned scoring shared by generation, recommendation previews, and exports. */
2
+ export declare const CANDIDATE_RANKING_VERSION: 1;
3
+ export type CandidateState = "pending" | "ready" | "degraded" | "failed";
4
+ export type ParameterSource = "user-fact" | "derived" | "creative" | "simulated";
5
+ export interface ParameterAssessment {
6
+ field: string;
7
+ score: number;
8
+ sourceType: ParameterSource;
9
+ evidenceRef?: string[];
10
+ requiresExampleLabel?: boolean;
11
+ }
12
+ export interface CandidateScores {
13
+ semantic: number;
14
+ layout: number;
15
+ fidelity: number;
16
+ }
17
+ export interface RankedCandidate {
18
+ compositionId: string;
19
+ slotId: string;
20
+ state: CandidateState;
21
+ scores: CandidateScores;
22
+ }
23
+ /** Registry importance is normalized: adding fields never adds points by itself.
24
+ * Optional omitted fields must be excluded by the caller; missing required fields
25
+ * fail schema validation before ranking and cannot be repaired with a low score.
26
+ */
27
+ export declare function weightedParameterScore(assessments: readonly ParameterAssessment[], importance: Readonly<Record<string, number>>): number;
28
+ /** Initial experimental weights; only measured, usable candidates are ranked. */
29
+ export declare function candidateScore(scores: CandidateScores): number;
30
+ /** Stable ties do not depend on arrival order, locale, or batch registration order. */
31
+ export declare function rankCandidates<T extends RankedCandidate>(candidates: readonly T[]): T[];
@@ -0,0 +1,55 @@
1
+ /** Versioned scoring shared by generation, recommendation previews, and exports. */
2
+ export const CANDIDATE_RANKING_VERSION = 1;
3
+ const score = (value) => {
4
+ if (!Number.isFinite(value) || value < 0 || value > 100)
5
+ throw new Error("CANDIDATE_INVALID_SCORE");
6
+ return value;
7
+ };
8
+ /** Registry importance is normalized: adding fields never adds points by itself.
9
+ * Optional omitted fields must be excluded by the caller; missing required fields
10
+ * fail schema validation before ranking and cannot be repaired with a low score.
11
+ */
12
+ export function weightedParameterScore(assessments, importance) {
13
+ let weighted = 0, total = 0;
14
+ const seen = new Set();
15
+ for (const assessment of assessments) {
16
+ const weight = Object.prototype.hasOwnProperty.call(importance, assessment.field)
17
+ ? importance[assessment.field]
18
+ : undefined;
19
+ if (seen.has(assessment.field) ||
20
+ weight === undefined ||
21
+ !Number.isFinite(weight) ||
22
+ weight <= 0)
23
+ throw new Error("CANDIDATE_INVALID_ASSESSMENT");
24
+ seen.add(assessment.field);
25
+ weighted += score(assessment.score) * weight;
26
+ total += weight;
27
+ }
28
+ if (!total)
29
+ throw new Error("CANDIDATE_MISSING_ASSESSMENT");
30
+ return weighted / total;
31
+ }
32
+ /** Initial experimental weights; only measured, usable candidates are ranked. */
33
+ export function candidateScore(scores) {
34
+ return (Math.round((0.5 * score(scores.semantic) +
35
+ 0.3 * score(scores.layout) +
36
+ 0.2 * score(scores.fidelity)) *
37
+ 1000) / 1000);
38
+ }
39
+ /** Stable ties do not depend on arrival order, locale, or batch registration order. */
40
+ export function rankCandidates(candidates) {
41
+ const identities = new Set();
42
+ for (const candidate of candidates) {
43
+ const key = JSON.stringify([candidate.slotId, candidate.compositionId]);
44
+ if (!candidate.slotId || !candidate.compositionId || identities.has(key))
45
+ throw new Error("CANDIDATE_DUPLICATE_ID");
46
+ identities.add(key);
47
+ }
48
+ const compare = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
49
+ return candidates
50
+ .filter((candidate) => candidate.state === "ready" || candidate.state === "degraded")
51
+ .slice()
52
+ .sort((a, b) => candidateScore(b.scores) - candidateScore(a.scores) ||
53
+ compare(a.slotId, b.slotId) ||
54
+ compare(a.compositionId, b.compositionId));
55
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CANDIDATE_RANKING_VERSION = void 0;
4
+ exports.weightedParameterScore = weightedParameterScore;
5
+ exports.candidateScore = candidateScore;
6
+ exports.rankCandidates = rankCandidates;
7
+ /** Versioned scoring shared by generation, recommendation previews, and exports. */
8
+ exports.CANDIDATE_RANKING_VERSION = 1;
9
+ const score = (value) => {
10
+ if (!Number.isFinite(value) || value < 0 || value > 100)
11
+ throw new Error("CANDIDATE_INVALID_SCORE");
12
+ return value;
13
+ };
14
+ /** Registry importance is normalized: adding fields never adds points by itself.
15
+ * Optional omitted fields must be excluded by the caller; missing required fields
16
+ * fail schema validation before ranking and cannot be repaired with a low score.
17
+ */
18
+ function weightedParameterScore(assessments, importance) {
19
+ let weighted = 0, total = 0;
20
+ const seen = new Set();
21
+ for (const assessment of assessments) {
22
+ const weight = Object.prototype.hasOwnProperty.call(importance, assessment.field)
23
+ ? importance[assessment.field]
24
+ : undefined;
25
+ if (seen.has(assessment.field) ||
26
+ weight === undefined ||
27
+ !Number.isFinite(weight) ||
28
+ weight <= 0)
29
+ throw new Error("CANDIDATE_INVALID_ASSESSMENT");
30
+ seen.add(assessment.field);
31
+ weighted += score(assessment.score) * weight;
32
+ total += weight;
33
+ }
34
+ if (!total)
35
+ throw new Error("CANDIDATE_MISSING_ASSESSMENT");
36
+ return weighted / total;
37
+ }
38
+ /** Initial experimental weights; only measured, usable candidates are ranked. */
39
+ function candidateScore(scores) {
40
+ return (Math.round((0.5 * score(scores.semantic) +
41
+ 0.3 * score(scores.layout) +
42
+ 0.2 * score(scores.fidelity)) *
43
+ 1000) / 1000);
44
+ }
45
+ /** Stable ties do not depend on arrival order, locale, or batch registration order. */
46
+ function rankCandidates(candidates) {
47
+ const identities = new Set();
48
+ for (const candidate of candidates) {
49
+ const key = JSON.stringify([candidate.slotId, candidate.compositionId]);
50
+ if (!candidate.slotId || !candidate.compositionId || identities.has(key))
51
+ throw new Error("CANDIDATE_DUPLICATE_ID");
52
+ identities.add(key);
53
+ }
54
+ const compare = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
55
+ return candidates
56
+ .filter((candidate) => candidate.state === "ready" || candidate.state === "degraded")
57
+ .slice()
58
+ .sort((a, b) => candidateScore(b.scores) - candidateScore(a.scores) ||
59
+ compare(a.slotId, b.slotId) ||
60
+ compare(a.compositionId, b.compositionId));
61
+ }
@@ -6,18 +6,29 @@ exports.validateComposition = validateComposition;
6
6
  exports.COMPOSITION_PROMPT = `Also return composition:{version:1,root:node}. Design a hierarchy from the content, not a fixed template. A node is {type,weight?,tone?,role?,bind?,icon?,children?}. row and column contain 2-4 children; nest up to 5 levels, at most 40 nodes. Weight is relative space 0.5-4. Tone plain/card/contrast applies to groups. Text binds exactly one existing nonempty content field (title or headline, body, eyebrow, cta, value, attribution, items.0.title, items.0.description, etc); never bind notes. Include EVERY nonempty content field exactly once. Text role hero/heading/body/caption controls typography. Image is an optional original conceptual illustration, not invented evidence or a photo. Icon optionally uses idea/check/chart/people/shield/arrow. Divider separates related content. No coordinates, CSS, HTML, URLs or text in the tree. Use one strong hero, purposeful contrast, asymmetric columns, grouped evidence, and breathing room. Rows reflow for narrow formats. Different stories should have different trees, not just different colors.`;
7
7
  function compositionFields(value) {
8
8
  const fields = {};
9
- for (const key of ['title', 'headline', 'body', 'eyebrow', 'cta', 'value', 'attribution'])
10
- if (typeof value[key] === 'string' && value[key].trim())
9
+ for (const key of [
10
+ "title",
11
+ "headline",
12
+ "body",
13
+ "eyebrow",
14
+ "cta",
15
+ "value",
16
+ "attribution",
17
+ ])
18
+ if (typeof value[key] === "string" && value[key].trim())
11
19
  fields[key] = value[key];
12
20
  if (Array.isArray(value.items))
13
- value.items.forEach((item, i) => { if (!item || typeof item !== 'object')
14
- return; for (const key of ['title', 'description']) {
15
- if (!Object.prototype.hasOwnProperty.call(item, key))
16
- continue;
17
- const v = item[key];
18
- if (typeof v === 'string' && v.trim())
19
- fields[`items.${i}.${key}`] = v;
20
- } });
21
+ value.items.forEach((item, i) => {
22
+ if (!item || typeof item !== "object")
23
+ return;
24
+ for (const key of ["title", "description"]) {
25
+ if (!Object.prototype.hasOwnProperty.call(item, key))
26
+ continue;
27
+ const v = item[key];
28
+ if (typeof v === "string" && v.trim())
29
+ fields[`items.${i}.${key}`] = v;
30
+ }
31
+ });
21
32
  return fields;
22
33
  }
23
34
  function validateComposition(raw, fields) {
@@ -25,44 +36,59 @@ function validateComposition(raw, fields) {
25
36
  let count = 0, images = 0;
26
37
  const seen = new Set();
27
38
  if (!value || value.version !== 1)
28
- throw new Error('Unsupported composition');
39
+ throw new Error("Unsupported composition");
29
40
  function visit(n, depth) {
30
- if (!n || typeof n !== 'object' || ++count > 40 || depth > 5 || !['row', 'column', 'text', 'image', 'divider', 'icon'].includes(n.type))
31
- throw new Error('Invalid composition node');
32
- if (n.weight !== undefined && (!Number.isFinite(n.weight) || n.weight < .5 || n.weight > 4))
33
- throw new Error('Invalid composition weight');
34
- if (n.tone !== undefined && !['plain', 'card', 'contrast'].includes(n.tone))
35
- throw new Error('Invalid composition tone');
36
- const out = { type: n.type, weight: n.weight, tone: n.tone };
37
- if (n.type === 'row' || n.type === 'column') {
38
- if (!Array.isArray(n.children) || n.children.length < 2 || n.children.length > 4)
39
- throw new Error('Invalid composition group');
40
- out.children = n.children.map(c => visit(c, depth + 1));
41
+ if (!n ||
42
+ typeof n !== "object" ||
43
+ ++count > 40 ||
44
+ depth > 5 ||
45
+ !["row", "column", "text", "image", "divider", "icon"].includes(n.type))
46
+ throw new Error("Invalid composition node");
47
+ if (n.weight !== undefined &&
48
+ (!Number.isFinite(n.weight) || n.weight < 0.5 || n.weight > 4))
49
+ throw new Error("Invalid composition weight");
50
+ if (n.tone !== undefined && !["plain", "card", "contrast"].includes(n.tone))
51
+ throw new Error("Invalid composition tone");
52
+ const out = {
53
+ type: n.type,
54
+ weight: n.weight,
55
+ tone: n.tone,
56
+ };
57
+ if (n.type === "row" || n.type === "column") {
58
+ if (!Array.isArray(n.children) ||
59
+ n.children.length < 2 ||
60
+ n.children.length > 4)
61
+ throw new Error("Invalid composition group");
62
+ out.children = n.children.map((c) => visit(c, depth + 1));
41
63
  }
42
64
  else {
43
65
  if (n.children !== undefined)
44
- throw new Error('Leaf cannot have children');
45
- if (n.type === 'text') {
46
- if (!n.bind || !Object.prototype.hasOwnProperty.call(fields, n.bind) || seen.has(n.bind))
47
- throw new Error('Invalid or duplicated binding');
48
- if (n.role !== undefined && !['hero', 'heading', 'body', 'caption'].includes(n.role))
49
- throw new Error('Invalid text role');
66
+ throw new Error("Leaf cannot have children");
67
+ if (n.type === "text") {
68
+ if (!n.bind ||
69
+ !Object.prototype.hasOwnProperty.call(fields, n.bind) ||
70
+ seen.has(n.bind))
71
+ throw new Error("Invalid or duplicated binding");
72
+ if (n.role !== undefined &&
73
+ !["hero", "heading", "body", "caption"].includes(n.role))
74
+ throw new Error("Invalid text role");
50
75
  seen.add(n.bind);
51
76
  out.bind = n.bind;
52
- out.role = n.role || 'body';
77
+ out.role = n.role || "body";
53
78
  }
54
- if (n.type === 'image' && ++images > 1)
55
- throw new Error('Only one illustration per composition');
56
- if (n.type === 'icon') {
57
- if (!n.icon || !['idea', 'check', 'chart', 'people', 'shield', 'arrow'].includes(n.icon))
58
- throw new Error('Invalid icon');
79
+ if (n.type === "image" && ++images > 1)
80
+ throw new Error("Only one illustration per composition");
81
+ if (n.type === "icon") {
82
+ if (!n.icon ||
83
+ !["idea", "check", "chart", "people", "shield", "arrow"].includes(n.icon))
84
+ throw new Error("Invalid icon");
59
85
  out.icon = n.icon;
60
86
  }
61
87
  }
62
88
  return out;
63
89
  }
64
90
  const root = visit(value.root, 0);
65
- if (Object.keys(fields).some(key => !seen.has(key)))
66
- throw new Error('Composition omits content');
91
+ if (Object.keys(fields).some((key) => !seen.has(key)))
92
+ throw new Error("Composition omits content");
67
93
  return { version: 1, root };
68
94
  }
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SOCIAL_DISPLAY_NUMBERS = exports.SEMANTIC_DISPLAY_NUMBERS = void 0;
4
+ /** Stable public display numbers, independent of runtime registration order. */
5
+ exports.SEMANTIC_DISPLAY_NUMBERS = {
6
+ "semantic:presentation:bookend-cover-editorial": "M001",
7
+ "semantic:presentation:bookend-cover-panel": "M002",
8
+ "semantic:presentation:bookend-cover-split": "M003",
9
+ "semantic:presentation:bookend-closing-editorial": "M004",
10
+ "semantic:presentation:bookend-closing-panel": "M005",
11
+ "semantic:presentation:bookend-closing-split": "M006",
12
+ "semantic:presentation:brand-collection-grid": "M007",
13
+ "semantic:social:time-notice": "M099",
14
+ "semantic:social:ticket": "M100",
15
+ "semantic:social:webinar": "M101",
16
+ "semantic:social:pricing": "M102",
17
+ "semantic:social:offer": "M103",
18
+ "semantic:social:hiring": "M104",
19
+ "semantic:social:community": "M105",
20
+ "semantic:social:menu": "M106",
21
+ "semantic:social:itinerary": "M107",
22
+ "semantic:social:schedule": "M108",
23
+ "semantic:presentation:authored-plan-cards": "M109",
24
+ "semantic:presentation:authored-image-banner": "M009",
25
+ "semantic:presentation:authored-image-split": "M010",
26
+ "semantic:presentation:authored-image-editorial": "M011",
27
+ "semantic:presentation:authored-image-campaign": "M012",
28
+ "semantic:presentation:authored-image-inset": "M013",
29
+ "semantic:presentation:authored-prose-inset": "M014",
30
+ "semantic:presentation:authored-feature-focus": "M015",
31
+ "semantic:presentation:authored-feature-bento": "M016",
32
+ "semantic:presentation:authored-feature-index": "M017",
33
+ "semantic:presentation:authored-steps-journey": "M018",
34
+ "semantic:presentation:authored-steps-ribbon": "M019",
35
+ "semantic:presentation:authored-comparison-panels": "M020",
36
+ "semantic:presentation:authored-quote-editorial": "M021",
37
+ "semantic:presentation:authored-quote-poster": "M022",
38
+ "semantic:presentation:authored-code-editorial": "M023",
39
+ "semantic:presentation:authored-parameter-ledger": "M024",
40
+ "semantic:presentation:authored-parameter-cards": "M025",
41
+ "semantic:presentation:semantic-code-split": "M026",
42
+ "semantic:presentation:semantic-parameters-split": "M029",
43
+ "semantic:presentation:semantic-parameters-stack": "M030",
44
+ "semantic:presentation:semantic-steps-split": "M032",
45
+ "semantic:presentation:semantic-steps-stack": "M033",
46
+ "semantic:presentation:semantic-steps-editorial": "M034",
47
+ "semantic:presentation:semantic-comparison-split": "M035",
48
+ "semantic:presentation:semantic-features-split": "M038",
49
+ "semantic:presentation:semantic-features-stack": "M039",
50
+ "semantic:presentation:semantic-features-editorial": "M040",
51
+ "semantic:presentation:semantic-quote-split": "M041",
52
+ "semantic:presentation:semantic-chart-split": "M044",
53
+ "semantic:presentation:semantic-chart-stack": "M045",
54
+ "semantic:presentation:semantic-prose-split": "M050",
55
+ "semantic:presentation:semantic-prose-stack": "M051",
56
+ "semantic:presentation:semantic-prose-editorial": "M052",
57
+ "semantic:presentation:semantic-mixed-stack": "M053",
58
+ "semantic:social:semantic-hero-editorial": "M094"
59
+ };
60
+ /** Social numbers follow the established formal gallery, not registration order. */
61
+ exports.SOCIAL_DISPLAY_NUMBERS = {
62
+ "note-question": "S001",
63
+ "note-marker": "S002",
64
+ "note-editorial": "S003",
65
+ "note-checklist": "S004",
66
+ "note-photo": "S005",
67
+ "note-news": "S006",
68
+ "chat-messenger": "S007",
69
+ "chat-imessage": "S008",
70
+ "chat-telegram": "S009",
71
+ "chat-workplace": "S010",
72
+ "time-notice": "S011",
73
+ "news-focus": "S012",
74
+ "usage-breakdown": "S013",
75
+ "organization": "S014",
76
+ "editorial-quote": "S015",
77
+ "research-highlight": "S016",
78
+ "product-showcase": "S017",
79
+ "manifesto": "S018",
80
+ "launch": "S019",
81
+ "bento": "S020",
82
+ "spotlight": "S021",
83
+ "ticket": "S022",
84
+ "webinar": "S023",
85
+ "quote": "S024",
86
+ "testimonial": "S025",
87
+ "metric": "S026",
88
+ "report": "S027",
89
+ "checklist": "S028",
90
+ "steps": "S029",
91
+ "comparison": "S030",
92
+ "myth": "S031",
93
+ "pricing": "S032",
94
+ "offer": "S033",
95
+ "editorial": "S034",
96
+ "story": "S035",
97
+ "hiring": "S036",
98
+ "team": "S037",
99
+ "course": "S038",
100
+ "case-study": "S039",
101
+ "notice": "S040",
102
+ "community": "S041",
103
+ "menu": "S042",
104
+ "specification": "S043",
105
+ "itinerary": "S044",
106
+ "schedule": "S045",
107
+ "safety": "S046",
108
+ "faq": "S047",
109
+ "split-bar-compare": "S048",
110
+ "benchmark-bars": "S049"
111
+ };
@@ -2,50 +2,103 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AUTHORED_COMPOSITIONS = exports.COMPOSITION_SCENES = void 0;
4
4
  exports.sceneRecipePreference = sceneRecipePreference;
5
- const both = ['presentation', 'social'];
5
+ const both = ["presentation", "social"];
6
6
  exports.COMPOSITION_SCENES = [
7
- { id: 'brand-collection', kinds: ['features'], outputs: both },
8
- { id: 'hero', kinds: ['paragraph'], outputs: both }, { id: 'chapter', kinds: ['paragraph'], outputs: ['presentation'] },
9
- { id: 'statement', kinds: ['paragraph'], outputs: both }, { id: 'closing', kinds: ['paragraph'], outputs: both },
10
- { id: 'product-launch', kinds: ['features'], outputs: both }, { id: 'feature-spotlight', kinds: ['features'], outputs: both },
11
- { id: 'feature-overview', kinds: ['features'], outputs: both }, { id: 'benefits', kinds: ['features'], outputs: both },
12
- { id: 'comparison', kinds: ['comparison'], outputs: both }, { id: 'before-after', kinds: ['comparison'], outputs: both },
13
- { id: 'plan-options', kinds: ['comparison'], outputs: both }, { id: 'process', kinds: ['steps'], outputs: both },
14
- { id: 'roadmap', kinds: ['steps'], outputs: both }, { id: 'tutorial', kinds: ['steps'], outputs: both },
15
- { id: 'checklist', kinds: ['features'], outputs: both }, { id: 'metrics', kinds: ['chart'], outputs: both },
16
- { id: 'trend', kinds: ['chart'], outputs: both }, { id: 'results', kinds: ['chart'], outputs: both },
17
- { id: 'quotation', kinds: ['quote'], outputs: both }, { id: 'testimonial', kinds: ['quote'], outputs: both },
18
- { id: 'code-example', kinds: ['code'], outputs: both }, { id: 'specifications', kinds: ['parameters'], outputs: both },
19
- { id: 'pricing-details', kinds: ['parameters'], outputs: both }, { id: 'event-details', kinds: ['parameters'], outputs: both },
20
- { id: 'recruitment-details', kinds: ['parameters'], outputs: both },
21
- { id: 'product-demonstration', kinds: ['image'], outputs: both, requiresAsset: true },
22
- { id: 'photograph', kinds: ['image'], outputs: both, requiresAsset: true },
23
- ...['banner-hero', 'product-showcase', 'editorial-cover', 'image-campaign'].map(id => ({ id, kinds: ['image'], outputs: both, requiresAsset: true })),
7
+ { id: "menu-details", kinds: ["parameters"], outputs: both },
8
+ { id: "travel-details", kinds: ["parameters"], outputs: both },
9
+ { id: "offer-details", kinds: ["parameters"], outputs: both },
10
+ { id: "questions", kinds: ["features"], outputs: both },
11
+ { id: "case-study", kinds: ["features"], outputs: both },
12
+ { id: "brand-collection", kinds: ["features"], outputs: both },
13
+ { id: "hero", kinds: ["paragraph"], outputs: both },
14
+ { id: "chapter", kinds: ["paragraph"], outputs: ["presentation"] },
15
+ { id: "statement", kinds: ["paragraph"], outputs: both },
16
+ { id: "closing", kinds: ["paragraph"], outputs: both },
17
+ { id: "product-launch", kinds: ["features"], outputs: both },
18
+ { id: "feature-spotlight", kinds: ["features"], outputs: both },
19
+ { id: "feature-overview", kinds: ["features"], outputs: both },
20
+ { id: "benefits", kinds: ["features"], outputs: both },
21
+ { id: "comparison", kinds: ["comparison"], outputs: both },
22
+ { id: "before-after", kinds: ["comparison"], outputs: both },
23
+ { id: "plan-options", kinds: ["comparison"], outputs: both },
24
+ { id: "process", kinds: ["steps"], outputs: both },
25
+ { id: "roadmap", kinds: ["steps"], outputs: both },
26
+ { id: "tutorial", kinds: ["steps"], outputs: both },
27
+ { id: "checklist", kinds: ["features"], outputs: both },
28
+ { id: "metrics", kinds: ["chart"], outputs: both },
29
+ { id: "trend", kinds: ["chart"], outputs: both },
30
+ { id: "results", kinds: ["chart"], outputs: both },
31
+ { id: "quotation", kinds: ["quote"], outputs: both },
32
+ { id: "testimonial", kinds: ["quote"], outputs: both },
33
+ { id: "code-example", kinds: ["code"], outputs: both },
34
+ { id: "specifications", kinds: ["parameters"], outputs: both },
35
+ { id: "pricing-details", kinds: ["parameters"], outputs: both },
36
+ { id: "event-details", kinds: ["parameters"], outputs: both },
37
+ { id: "recruitment-details", kinds: ["parameters"], outputs: both },
38
+ {
39
+ id: "product-demonstration",
40
+ kinds: ["image"],
41
+ outputs: both,
42
+ requiresAsset: true,
43
+ },
44
+ { id: "photograph", kinds: ["image"], outputs: both, requiresAsset: true },
45
+ ...[
46
+ "banner-hero",
47
+ "product-showcase",
48
+ "editorial-cover",
49
+ "image-campaign",
50
+ ].map((id) => ({
51
+ id,
52
+ kinds: ["image"],
53
+ outputs: both,
54
+ requiresAsset: true,
55
+ })),
24
56
  ];
25
57
  exports.AUTHORED_COMPOSITIONS = [
26
- { id: 'feature-focus', kind: 'features', min: 1, max: 1 },
27
- { id: 'feature-bento', kind: 'features', min: 2, max: 6 },
28
- { id: 'feature-index', kind: 'features', min: 2, max: 6 },
29
- { id: 'steps-journey', kind: 'steps', min: 2, max: 6 },
30
- { id: 'steps-ribbon', kind: 'steps', min: 2, max: 4 },
31
- { id: 'comparison-panels', kind: 'comparison', min: 2, max: 3 },
32
- { id: 'quote-editorial', kind: 'quote', min: 0, max: 0 },
33
- { id: 'quote-poster', kind: 'quote', min: 0, max: 0 },
34
- { id: 'code-editorial', kind: 'code', min: 0, max: 0 },
35
- { id: 'parameter-ledger', kind: 'parameters', min: 1, max: 8 },
36
- { id: 'parameter-cards', kind: 'parameters', min: 1, max: 4 },
58
+ { id: "feature-focus", kind: "features", min: 1, max: 1 },
59
+ { id: "feature-bento", kind: "features", min: 2, max: 6 },
60
+ { id: "feature-index", kind: "features", min: 2, max: 6 },
61
+ { id: "steps-journey", kind: "steps", min: 2, max: 6 },
62
+ { id: "steps-ribbon", kind: "steps", min: 2, max: 4 },
63
+ { id: "comparison-panels", kind: "comparison", min: 2, max: 3 },
64
+ { id: "quote-editorial", kind: "quote", min: 0, max: 0 },
65
+ { id: "quote-poster", kind: "quote", min: 0, max: 0 },
66
+ { id: "code-editorial", kind: "code", min: 0, max: 0 },
67
+ { id: "parameter-ledger", kind: "parameters", min: 1, max: 8 },
68
+ { id: "parameter-cards", kind: "parameters", min: 1, max: 4 },
37
69
  ];
38
70
  /** Soft art-direction preferences; capacity and measured quality always remain mandatory. */
39
71
  function sceneRecipePreference(scene, recipeId) {
40
72
  const preferred = {
41
- 'banner-hero': ['authored-image-banner'], 'product-showcase': ['authored-image-split'], 'editorial-cover': ['authored-image-editorial'], 'image-campaign': ['authored-image-campaign'],
42
- hero: ['cover', 'semantic-hero-split'], chapter: ['section', 'semantic-hero-editorial'], statement: ['statement', 'semantic-hero-stack'], closing: ['closing'],
43
- 'product-launch': ['authored-feature-bento'], 'feature-spotlight': ['authored-feature-focus'], 'feature-overview': ['authored-feature-bento', 'three-column'], benefits: ['authored-feature-index'],
44
- comparison: ['authored-comparison-panels'], 'before-after': ['before-after', 'semantic-comparison-split'], 'plan-options': ['authored-comparison-panels'],
45
- process: ['authored-steps-ribbon'], roadmap: ['authored-steps-ribbon', 'roadmap'], tutorial: ['authored-steps-journey'], checklist: ['authored-feature-index', 'checklist'],
46
- quotation: ['authored-quote-editorial'], testimonial: ['authored-quote-poster'],
47
- 'code-example': ['authored-code-editorial'], specifications: ['authored-parameter-ledger'],
48
- 'pricing-details': ['authored-parameter-cards'], 'event-details': ['authored-parameter-cards'], 'recruitment-details': ['authored-parameter-ledger'],
73
+ "banner-hero": ["authored-image-banner"],
74
+ "product-showcase": ["authored-image-split"],
75
+ "editorial-cover": ["authored-image-editorial"],
76
+ "image-campaign": ["authored-image-campaign"],
77
+ hero: ["cover", "semantic-hero-split"],
78
+ chapter: ["section", "semantic-hero-editorial"],
79
+ statement: ["statement", "semantic-hero-stack"],
80
+ closing: ["closing"],
81
+ "product-launch": ["authored-feature-bento"],
82
+ "feature-spotlight": ["authored-feature-focus"],
83
+ "feature-overview": ["authored-feature-bento", "three-column"],
84
+ benefits: ["authored-feature-index"],
85
+ comparison: ["authored-comparison-panels"],
86
+ "before-after": ["before-after", "semantic-comparison-split"],
87
+ "plan-options": ["authored-comparison-panels"],
88
+ process: ["authored-steps-ribbon"],
89
+ roadmap: ["authored-steps-ribbon", "roadmap"],
90
+ tutorial: ["authored-steps-journey"],
91
+ checklist: ["authored-feature-index", "checklist"],
92
+ quotation: ["authored-quote-editorial"],
93
+ testimonial: ["authored-quote-poster"],
94
+ "code-example": ["authored-code-editorial"],
95
+ specifications: ["authored-parameter-ledger"],
96
+ "pricing-details": ["authored-parameter-cards"],
97
+ "event-details": ["authored-parameter-cards"],
98
+ "recruitment-details": ["authored-parameter-ledger"],
49
99
  };
50
- return scene && preferred[scene]?.some(id => recipeId === id || recipeId.startsWith(`${id}--`)) ? 6 : 0;
100
+ return scene &&
101
+ preferred[scene]?.some((id) => recipeId === id || recipeId.startsWith(`${id}--`))
102
+ ? 6
103
+ : 0;
51
104
  }