@neatico/visual-core 0.14.64 → 0.14.66
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.
- package/dist/cjs/designSystem.js +6 -1
- package/dist/cjs/exploreCollection.js +181 -0
- package/dist/cjs/formalCompositions.js +3 -2
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/recipeParameters.js +79 -8
- package/dist/designSystem.js +6 -1
- package/dist/exploreCollection.d.ts +7 -0
- package/dist/exploreCollection.js +177 -0
- package/dist/formalCompositions.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/recipeParameters.js +80 -9
- package/package.json +1 -1
package/dist/cjs/designSystem.js
CHANGED
|
@@ -6,11 +6,13 @@ 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" },
|
|
@@ -188,7 +190,7 @@ function designTheme(id) {
|
|
|
188
190
|
plum: "electric",
|
|
189
191
|
};
|
|
190
192
|
return (exports.DESIGN_THEMES.find((theme) => theme.id === (alias[id] || id)) ||
|
|
191
|
-
exports.DESIGN_THEMES
|
|
193
|
+
exports.DESIGN_THEMES.find(theme => theme.id === "neatico"));
|
|
192
194
|
}
|
|
193
195
|
const family = (id, semantic) => {
|
|
194
196
|
if (/code|terminal/.test(id))
|
|
@@ -370,6 +372,7 @@ function canonicalRecipeId(id, kind) {
|
|
|
370
372
|
}
|
|
371
373
|
/** Existing authored catalogs remain first-class candidates, rather than being discarded. */
|
|
372
374
|
const ALL_DESIGN_RECIPES = [
|
|
375
|
+
...exploreCollection_js_1.EXPLORE_RECIPES,
|
|
373
376
|
...["cover", "closing"].flatMap((role) => ["editorial", "panel", "split"].map((style) => ({
|
|
374
377
|
id: `bookend-${role}-${style}`,
|
|
375
378
|
kind: "presentation",
|
|
@@ -508,6 +511,7 @@ function designCandidates(page, context) {
|
|
|
508
511
|
const available = page.blocks.some((b) => b.kind === "image" && b.status === "available");
|
|
509
512
|
const exclude = new Set(context.excluded || []);
|
|
510
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))) &&
|
|
511
515
|
r.automatic !== false &&
|
|
512
516
|
(!r.scenes || Boolean(page.scene && r.scenes.includes(page.scene))) &&
|
|
513
517
|
!(r.family.startsWith("hero") &&
|
|
@@ -535,6 +539,7 @@ function designCandidates(page, context) {
|
|
|
535
539
|
? r.family.startsWith("steps") || r.family.startsWith("code")
|
|
536
540
|
: true;
|
|
537
541
|
return ((r.id.startsWith("bookend-") ? 80 : 0) +
|
|
542
|
+
(r.id.startsWith("authored-explore-") ? 110 : 0) +
|
|
538
543
|
(page.scene === "brand-collection" && r.id === "brand-collection-grid"
|
|
539
544
|
? 80
|
|
540
545
|
: 0) +
|
|
@@ -0,0 +1,181 @@
|
|
|
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
|
+
/** Explore's editorial colorways, including light and solid-background variants. */
|
|
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
|
+
["olive-classic", "#E8EEDC", "#607447", "#4F6339", "#FFFFFF"],
|
|
19
|
+
["rose", "#9B3E61", "#F6E2EB", "#FFFAFC", "#402332"],
|
|
20
|
+
["wine", "#7A3048", "#EFDEE5", "#FCF8FA", "#39202C"],
|
|
21
|
+
["sunflower", "#8A5D12", "#F7EBC6", "#FFFDF5", "#392F1D"],
|
|
22
|
+
["seafoam", "#216C62", "#DDF0E8", "#F7FCFA", "#193D36"],
|
|
23
|
+
["graphite", "#D5B98C", "#30343A", "#1B1E23", "#F5F2EA"],
|
|
24
|
+
["midnight", "#91B7DE", "#22344C", "#132236", "#F3F6FA"],
|
|
25
|
+
["ice", "#27697B", "#DDEFF5", "#F8FCFE", "#193C49"],
|
|
26
|
+
["copper", "#9A563B", "#F1E2D7", "#FCF9F5", "#3F2C23"],
|
|
27
|
+
];
|
|
28
|
+
exports.EXPLORE_THEMES = colors.map(([id, accent, surface, background, ink]) => ({
|
|
29
|
+
id: `explore-${id}`,
|
|
30
|
+
palette: { accent, surface, background, ink, muted: ink, line: surface },
|
|
31
|
+
typography: {
|
|
32
|
+
heading: "Playfair Display",
|
|
33
|
+
body: "Inter",
|
|
34
|
+
code: "JetBrains Mono",
|
|
35
|
+
headingWeight: 600,
|
|
36
|
+
},
|
|
37
|
+
geometry: { radius: 4, spacing: 1.1, rule: "hairline" },
|
|
38
|
+
}));
|
|
39
|
+
exports.EXPLORE_LAYOUTS = [
|
|
40
|
+
[
|
|
41
|
+
"cover",
|
|
42
|
+
"paragraph",
|
|
43
|
+
0,
|
|
44
|
+
0,
|
|
45
|
+
"Open with a spacious editorial headline, a short premise and an optional real photograph.",
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
"overview",
|
|
49
|
+
"features",
|
|
50
|
+
2,
|
|
51
|
+
4,
|
|
52
|
+
"Orient readers with a numbered overview of parallel subjects.",
|
|
53
|
+
],
|
|
54
|
+
[
|
|
55
|
+
"section",
|
|
56
|
+
"paragraph",
|
|
57
|
+
0,
|
|
58
|
+
0,
|
|
59
|
+
"Introduce one new section or central principle in a strong color field.",
|
|
60
|
+
],
|
|
61
|
+
[
|
|
62
|
+
"pillars",
|
|
63
|
+
"features",
|
|
64
|
+
2,
|
|
65
|
+
3,
|
|
66
|
+
"Explain two or three equally important ideas in spacious editorial columns.",
|
|
67
|
+
],
|
|
68
|
+
[
|
|
69
|
+
"focus",
|
|
70
|
+
"paragraph",
|
|
71
|
+
0,
|
|
72
|
+
0,
|
|
73
|
+
"Develop one idea in an asymmetric reading composition.",
|
|
74
|
+
],
|
|
75
|
+
[
|
|
76
|
+
"workflow",
|
|
77
|
+
"steps",
|
|
78
|
+
2,
|
|
79
|
+
4,
|
|
80
|
+
"Show an ordered workflow with explicit actions and useful descriptions.",
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
"timeline",
|
|
84
|
+
"steps",
|
|
85
|
+
2,
|
|
86
|
+
4,
|
|
87
|
+
"Present a short chronological sequence on a horizontal reading axis.",
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
"comparison",
|
|
91
|
+
"comparison",
|
|
92
|
+
2,
|
|
93
|
+
2,
|
|
94
|
+
"Compare two supplied alternatives with corresponding points.",
|
|
95
|
+
],
|
|
96
|
+
[
|
|
97
|
+
"worksheet",
|
|
98
|
+
"parameters",
|
|
99
|
+
2,
|
|
100
|
+
4,
|
|
101
|
+
"Explain named fields with their concrete values and instructions.",
|
|
102
|
+
],
|
|
103
|
+
[
|
|
104
|
+
"photo-story",
|
|
105
|
+
"image",
|
|
106
|
+
0,
|
|
107
|
+
0,
|
|
108
|
+
"Use a real contextual photograph beside a concise explanation.",
|
|
109
|
+
],
|
|
110
|
+
[
|
|
111
|
+
"quote",
|
|
112
|
+
"quote",
|
|
113
|
+
0,
|
|
114
|
+
0,
|
|
115
|
+
"Give an exact source statement room to breathe, retaining supplied attribution.",
|
|
116
|
+
],
|
|
117
|
+
[
|
|
118
|
+
"chart",
|
|
119
|
+
"chart",
|
|
120
|
+
2,
|
|
121
|
+
6,
|
|
122
|
+
"Compare source-backed quantities in labeled bars with the original unit.",
|
|
123
|
+
],
|
|
124
|
+
[
|
|
125
|
+
"ledger",
|
|
126
|
+
"parameters",
|
|
127
|
+
2,
|
|
128
|
+
5,
|
|
129
|
+
"Arrange named facts and explanations in a flat editorial ledger.",
|
|
130
|
+
],
|
|
131
|
+
[
|
|
132
|
+
"faq",
|
|
133
|
+
"features",
|
|
134
|
+
2,
|
|
135
|
+
3,
|
|
136
|
+
"Answer a small set of meaningful questions with concise responses.",
|
|
137
|
+
],
|
|
138
|
+
[
|
|
139
|
+
"action-plan",
|
|
140
|
+
"steps",
|
|
141
|
+
2,
|
|
142
|
+
3,
|
|
143
|
+
"Make the next few actions prominent, with descriptions that explain the work.",
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
"closing",
|
|
147
|
+
"paragraph",
|
|
148
|
+
0,
|
|
149
|
+
0,
|
|
150
|
+
"Close with one clear takeaway and a concrete next action.",
|
|
151
|
+
],
|
|
152
|
+
];
|
|
153
|
+
exports.EXPLORE_RECIPES = exports.EXPLORE_LAYOUTS.map(([id, kind, min, max]) => ({
|
|
154
|
+
id: `authored-explore-${id}`,
|
|
155
|
+
kind: "presentation",
|
|
156
|
+
renderer: "semantic",
|
|
157
|
+
automatic: true,
|
|
158
|
+
family: kind === "paragraph" ? `hero-explore-${id}` : kind,
|
|
159
|
+
minEntries: min,
|
|
160
|
+
maxEntries: max,
|
|
161
|
+
accepts: (["cover", "photo-story"].includes(id)
|
|
162
|
+
? ["paragraph", "image"]
|
|
163
|
+
: [kind]),
|
|
164
|
+
requiresImage: id === "photo-story",
|
|
165
|
+
}));
|
|
166
|
+
function exploreCompositionFits(page, id) {
|
|
167
|
+
if (!id.startsWith("authored-explore-"))
|
|
168
|
+
return true;
|
|
169
|
+
const variant = id.slice("authored-explore-".length);
|
|
170
|
+
if (variant === "cover")
|
|
171
|
+
return page.purpose === "cover";
|
|
172
|
+
if (variant === "closing")
|
|
173
|
+
return page.purpose === "conclude";
|
|
174
|
+
if (["cover", "conclude"].includes(page.purpose))
|
|
175
|
+
return false;
|
|
176
|
+
if (variant === "section")
|
|
177
|
+
return (page.blocks.length === 1 &&
|
|
178
|
+
page.blocks[0].kind === "paragraph" &&
|
|
179
|
+
page.blocks[0].text.length <= 160);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FORMAL_COMPOSITIONS = exports.FORMAL_REFERENCE_COMPOSITIONS = void 0;
|
|
4
4
|
exports.applicableCompositions = applicableCompositions;
|
|
5
|
+
const exploreCollection_js_1 = require("./exploreCollection.js");
|
|
5
6
|
const compositionUseCases_js_1 = require("./compositionUseCases.js");
|
|
6
7
|
const nativeSocialParameters_js_1 = require("./nativeSocialParameters.js");
|
|
7
8
|
const designSystem_js_1 = require("./designSystem.js");
|
|
@@ -11,7 +12,7 @@ const compositionNumbers_js_1 = require("./compositionNumbers.js");
|
|
|
11
12
|
const both = ['presentation', 'social'];
|
|
12
13
|
const semantic = (id, accepts, minEntries = 0, maxEntries = 12, requiresImage = false) => ({ id, renderer: 'semantic', kind: 'social', family: id, accepts, minEntries, maxEntries, requiresImage });
|
|
13
14
|
function define(recipe, kinds, id, displayNumber, min = .25, max = 4) {
|
|
14
|
-
return { ...(0, recipeParameters_js_1.recipeParameterContract)(recipe, kinds), semanticDescription: (0, compositionUseCases_js_1.compositionUseCase)(recipe.id), id, displayNumber, aspectRatios: { min, max }, recipe };
|
|
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 };
|
|
15
16
|
}
|
|
16
17
|
/** Structural reference contracts shared with the product's existing renderers.
|
|
17
18
|
* Colorways and historical aliases remain outside active discovery.
|
|
@@ -104,7 +105,7 @@ exports.FORMAL_COMPOSITIONS = [
|
|
|
104
105
|
const recipe = designSystem_js_1.DESIGN_RECIPES.find(item => item.id === preset.id && item.kind === 'social');
|
|
105
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) };
|
|
106
107
|
}),
|
|
107
|
-
...uniqueSemantic.map(recipe => define(recipe, semanticRecipes.filter(other => other.id === recipe.id).map(other => other.kind), `semantic:${recipe.kind}:${recipe.id}`, compositionNumbers_js_1.SEMANTIC_DISPLAY_NUMBERS[`semantic:${recipe.kind}:${recipe.id}`])),
|
|
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)),
|
|
108
109
|
...founderDefinitions.map(([id, accepts, min, max], index) => define(semantic(id, accepts, min, max), ['social'], `semantic:social:${id}`, `F${index + 1}`, 1.3)),
|
|
109
110
|
...[0, 1, 2].flatMap(variant => [article(`article-cover-${variant}`, 'cover', variant), ...articleKinds.map(kind => article(`article-${kind}-${variant}`, kind, variant))]),
|
|
110
111
|
...[3, 4, 5, 6, 7, 8, 9, 10].map(variant => article(`article-features-${variant}`, 'features', variant)),
|
package/dist/cjs/index.js
CHANGED
|
@@ -42,3 +42,4 @@ Object.defineProperty(exports, "compositionParameterDefaults", { enumerable: tru
|
|
|
42
42
|
var compositionNumbers_js_1 = require("./compositionNumbers.js");
|
|
43
43
|
Object.defineProperty(exports, "SOCIAL_DISPLAY_NUMBERS", { enumerable: true, get: function () { return compositionNumbers_js_1.SOCIAL_DISPLAY_NUMBERS; } });
|
|
44
44
|
__exportStar(require("./textPresentation.js"), exports);
|
|
45
|
+
__exportStar(require("./exploreCollection.js"), exports);
|
|
@@ -109,7 +109,9 @@ function blockSchema(kind, maximum) {
|
|
|
109
109
|
function fixedBlocks(recipe) {
|
|
110
110
|
const id = recipe.id;
|
|
111
111
|
let kinds;
|
|
112
|
-
if (
|
|
112
|
+
if (["authored-explore-cover", "authored-explore-photo-story"].includes(id))
|
|
113
|
+
kinds = ["paragraph", "image"];
|
|
114
|
+
else if (id.endsWith("ledger-chart"))
|
|
113
115
|
kinds = ["parameters", "chart"];
|
|
114
116
|
else if (id.endsWith("detail-sidebar"))
|
|
115
117
|
kinds = ["paragraph", "parameters"];
|
|
@@ -151,8 +153,13 @@ function fixedBlocks(recipe) {
|
|
|
151
153
|
const fields = schema.properties;
|
|
152
154
|
const count = Math.max(recipe.minEntries || 1, Math.min(3, recipe.maxEntries || 3));
|
|
153
155
|
if (kind === "paragraph")
|
|
154
|
-
fields.text.maxLength =
|
|
155
|
-
|
|
156
|
+
fields.text.maxLength = [
|
|
157
|
+
"authored-reference-detail-sidebar",
|
|
158
|
+
"authored-reference-diagonal",
|
|
159
|
+
"authored-prose-inset",
|
|
160
|
+
].includes(id)
|
|
161
|
+
? 160
|
|
162
|
+
: 120;
|
|
156
163
|
if (kind === "features" || kind === "steps") {
|
|
157
164
|
const entries = fields.entries;
|
|
158
165
|
entries.minItems = id === "authored-reference-story" ? 2 : count;
|
|
@@ -164,7 +171,24 @@ function fixedBlocks(recipe) {
|
|
|
164
171
|
description: "Editable native illustration for the item. Choose the visual concept that explains its meaning. This field controls a graphic, not prose.",
|
|
165
172
|
};
|
|
166
173
|
entries.items.required.push("illustration");
|
|
167
|
-
entries.items.properties.icon = {
|
|
174
|
+
entries.items.properties.icon = {
|
|
175
|
+
type: "string",
|
|
176
|
+
enum: [
|
|
177
|
+
"BsJournalText",
|
|
178
|
+
"BsPersonCheck",
|
|
179
|
+
"BsShare",
|
|
180
|
+
"BsPeople",
|
|
181
|
+
"BsSearch",
|
|
182
|
+
"BsShieldCheck",
|
|
183
|
+
"BsBarChart",
|
|
184
|
+
"BsCodeSlash",
|
|
185
|
+
"BsSignpostSplit",
|
|
186
|
+
"BsCheck2Circle",
|
|
187
|
+
"BsFolder2Open",
|
|
188
|
+
"BsGrid1X2",
|
|
189
|
+
],
|
|
190
|
+
description: "Optional authored icon variant; illustration remains the primary visual concept.",
|
|
191
|
+
};
|
|
168
192
|
entries.items.properties.title.maxLength = 28;
|
|
169
193
|
entries.items.properties.description.maxLength =
|
|
170
194
|
id === "authored-feature-focus" ? 160 : 48;
|
|
@@ -177,7 +201,11 @@ function fixedBlocks(recipe) {
|
|
|
177
201
|
id.includes("speaker-")
|
|
178
202
|
? 2
|
|
179
203
|
: count;
|
|
180
|
-
fields.rows.minItems = id.endsWith("speaker-lineup")
|
|
204
|
+
fields.rows.minItems = id.endsWith("speaker-lineup")
|
|
205
|
+
? 1
|
|
206
|
+
: id === "pricing"
|
|
207
|
+
? 2
|
|
208
|
+
: rows;
|
|
181
209
|
fields.rows.maxItems = rows;
|
|
182
210
|
fields.rows.items.properties.name.maxLength = 20;
|
|
183
211
|
fields.rows.items.properties.value.maxLength = 24;
|
|
@@ -192,7 +220,8 @@ function fixedBlocks(recipe) {
|
|
|
192
220
|
column.title.maxLength = 20;
|
|
193
221
|
column.points.minItems = id === "authored-founder-comparison" ? 1 : 2;
|
|
194
222
|
column.points.maxItems = 3;
|
|
195
|
-
column.points.items.maxLength =
|
|
223
|
+
column.points.items.maxLength =
|
|
224
|
+
id === "authored-founder-comparison" ? 64 : 40;
|
|
196
225
|
column.values.maxItems = 3;
|
|
197
226
|
column.values.items.maxLength = 16;
|
|
198
227
|
column.values.minItems = 0;
|
|
@@ -229,19 +258,61 @@ function fixedBlocks(recipe) {
|
|
|
229
258
|
fields.chart = { const: "bar" };
|
|
230
259
|
if (/donut|reference-share|reference-metrics/.test(id)) {
|
|
231
260
|
fields.chart = { const: "bar" };
|
|
232
|
-
fields.unit = {
|
|
261
|
+
fields.unit = {
|
|
262
|
+
type: "string",
|
|
263
|
+
maxLength: 24,
|
|
264
|
+
pattern: "%",
|
|
265
|
+
description: "Percentage unit, optionally qualified as illustrative or simulated.",
|
|
266
|
+
};
|
|
233
267
|
fields.values.description =
|
|
234
268
|
"Nonnegative shares totaling exactly 100. Use labeled illustrative shares when the input has no comparable numbers.";
|
|
235
269
|
fields.values.items.properties.value.minimum = 0;
|
|
236
270
|
fields.values.items.properties.value.maximum = 100;
|
|
237
271
|
}
|
|
238
272
|
}
|
|
273
|
+
if (id.startsWith("authored-explore-")) {
|
|
274
|
+
if (kind === "paragraph") {
|
|
275
|
+
fields.text.maxLength = 220;
|
|
276
|
+
if (id !== "authored-explore-focus") {
|
|
277
|
+
delete fields.heading;
|
|
278
|
+
delete fields.level;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (kind === "features" || kind === "steps") {
|
|
282
|
+
fields.entries.minItems = Math.max(2, recipe.minEntries);
|
|
283
|
+
fields.entries.maxItems = recipe.maxEntries;
|
|
284
|
+
fields.entries.items.properties.title.maxLength = 44;
|
|
285
|
+
fields.entries.items.properties.description.maxLength = 120;
|
|
286
|
+
delete fields.entries.items.properties.illustration;
|
|
287
|
+
delete fields.entries.items.properties.icon;
|
|
288
|
+
fields.entries.items.required = fields.entries.items.required.filter((key) => !["illustration", "icon"].includes(key));
|
|
289
|
+
}
|
|
290
|
+
if (kind === "parameters") {
|
|
291
|
+
fields.rows.minItems = recipe.minEntries;
|
|
292
|
+
fields.rows.maxItems = recipe.maxEntries;
|
|
293
|
+
fields.rows.items.properties.name.maxLength = 36;
|
|
294
|
+
fields.rows.items.properties.value.maxLength = 120;
|
|
295
|
+
fields.rows.items.properties.description.maxLength = 60;
|
|
296
|
+
}
|
|
297
|
+
if (kind === "comparison") {
|
|
298
|
+
fields.columns.items.properties.points.maxItems = 3;
|
|
299
|
+
fields.columns.items.properties.points.items.maxLength = 100;
|
|
300
|
+
for (const key of ["price", "values", "statuses"])
|
|
301
|
+
delete fields.columns.items.properties[key];
|
|
302
|
+
}
|
|
303
|
+
if (kind === "chart") {
|
|
304
|
+
fields.chart = { const: "bar" };
|
|
305
|
+
fields.values.minItems = 2;
|
|
306
|
+
fields.values.maxItems = 6;
|
|
307
|
+
fields.values.items.properties.value.minimum = 0;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
239
310
|
return schema;
|
|
240
311
|
});
|
|
241
312
|
return {
|
|
242
313
|
type: "array",
|
|
243
314
|
items,
|
|
244
|
-
minItems: items.length,
|
|
315
|
+
minItems: id === "authored-explore-cover" ? 1 : items.length,
|
|
245
316
|
maxItems: items.length,
|
|
246
317
|
additionalItems: false,
|
|
247
318
|
description: "Fixed ordered parameters for this renderer. Return every block exactly once in this order; do not add explanatory blocks.",
|
package/dist/designSystem.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { EXPLORE_THEMES, EXPLORE_RECIPES, exploreCompositionFits } from './exploreCollection.js';
|
|
1
2
|
import { AUTHORED_COMPOSITIONS, sceneRecipePreference, } from "./compositionScenes.js";
|
|
2
3
|
import { SOCIAL_LAYOUT_CATALOG } from "./socialLayouts.js";
|
|
3
4
|
import { contentBlockText, } from "./content.js";
|
|
4
5
|
/** Complete, deterministic token sets; decorative geometry belongs to individual compositions. */
|
|
5
6
|
export const DESIGN_THEMES = [
|
|
7
|
+
...EXPLORE_THEMES,
|
|
6
8
|
{
|
|
7
9
|
id: "neatico",
|
|
8
10
|
palette: { background: "#FAF9F6", surface: "#FFFFFF", ink: "#202124", muted: "#62646B", accent: "#F4CE36", line: "#E4E1D9" },
|
|
@@ -180,7 +182,7 @@ export function designTheme(id) {
|
|
|
180
182
|
plum: "electric",
|
|
181
183
|
};
|
|
182
184
|
return (DESIGN_THEMES.find((theme) => theme.id === (alias[id] || id)) ||
|
|
183
|
-
DESIGN_THEMES
|
|
185
|
+
DESIGN_THEMES.find(theme => theme.id === "neatico"));
|
|
184
186
|
}
|
|
185
187
|
const family = (id, semantic) => {
|
|
186
188
|
if (/code|terminal/.test(id))
|
|
@@ -362,6 +364,7 @@ export function canonicalRecipeId(id, kind) {
|
|
|
362
364
|
}
|
|
363
365
|
/** Existing authored catalogs remain first-class candidates, rather than being discarded. */
|
|
364
366
|
const ALL_DESIGN_RECIPES = [
|
|
367
|
+
...EXPLORE_RECIPES,
|
|
365
368
|
...["cover", "closing"].flatMap((role) => ["editorial", "panel", "split"].map((style) => ({
|
|
366
369
|
id: `bookend-${role}-${style}`,
|
|
367
370
|
kind: "presentation",
|
|
@@ -500,6 +503,7 @@ export function designCandidates(page, context) {
|
|
|
500
503
|
const available = page.blocks.some((b) => b.kind === "image" && b.status === "available");
|
|
501
504
|
const exclude = new Set(context.excluded || []);
|
|
502
505
|
const candidates = DESIGN_RECIPES.filter((r) => r.kind === context.kind &&
|
|
506
|
+
(!r.id.startsWith("authored-explore-") || (context.ratio >= 1.4 && context.ratio <= 2 && exploreCompositionFits(page, r.id))) &&
|
|
503
507
|
r.automatic !== false &&
|
|
504
508
|
(!r.scenes || Boolean(page.scene && r.scenes.includes(page.scene))) &&
|
|
505
509
|
!(r.family.startsWith("hero") &&
|
|
@@ -527,6 +531,7 @@ export function designCandidates(page, context) {
|
|
|
527
531
|
? r.family.startsWith("steps") || r.family.startsWith("code")
|
|
528
532
|
: true;
|
|
529
533
|
return ((r.id.startsWith("bookend-") ? 80 : 0) +
|
|
534
|
+
(r.id.startsWith("authored-explore-") ? 110 : 0) +
|
|
530
535
|
(page.scene === "brand-collection" && r.id === "brand-collection-grid"
|
|
531
536
|
? 80
|
|
532
537
|
: 0) +
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DesignRecipe, DesignTheme } from "./designSystem.js";
|
|
2
|
+
import type { ContentPage } from "./content.js";
|
|
3
|
+
export declare const DEFAULT_PRESENTATION_THEME = "explore-teal";
|
|
4
|
+
export declare const EXPLORE_THEMES: readonly DesignTheme[];
|
|
5
|
+
export declare const EXPLORE_LAYOUTS: readonly [readonly ["cover", "paragraph", 0, 0, "Open with a spacious editorial headline, a short premise and an optional real photograph."], readonly ["overview", "features", 2, 4, "Orient readers with a numbered overview of parallel subjects."], readonly ["section", "paragraph", 0, 0, "Introduce one new section or central principle in a strong color field."], readonly ["pillars", "features", 2, 3, "Explain two or three equally important ideas in spacious editorial columns."], readonly ["focus", "paragraph", 0, 0, "Develop one idea in an asymmetric reading composition."], readonly ["workflow", "steps", 2, 4, "Show an ordered workflow with explicit actions and useful descriptions."], readonly ["timeline", "steps", 2, 4, "Present a short chronological sequence on a horizontal reading axis."], readonly ["comparison", "comparison", 2, 2, "Compare two supplied alternatives with corresponding points."], readonly ["worksheet", "parameters", 2, 4, "Explain named fields with their concrete values and instructions."], readonly ["photo-story", "image", 0, 0, "Use a real contextual photograph beside a concise explanation."], readonly ["quote", "quote", 0, 0, "Give an exact source statement room to breathe, retaining supplied attribution."], readonly ["chart", "chart", 2, 6, "Compare source-backed quantities in labeled bars with the original unit."], readonly ["ledger", "parameters", 2, 5, "Arrange named facts and explanations in a flat editorial ledger."], readonly ["faq", "features", 2, 3, "Answer a small set of meaningful questions with concise responses."], readonly ["action-plan", "steps", 2, 3, "Make the next few actions prominent, with descriptions that explain the work."], readonly ["closing", "paragraph", 0, 0, "Close with one clear takeaway and a concrete next action."]];
|
|
6
|
+
export declare const EXPLORE_RECIPES: readonly DesignRecipe[];
|
|
7
|
+
export declare function exploreCompositionFits(page: ContentPage, id: string): boolean;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
export const DEFAULT_PRESENTATION_THEME = "explore-teal";
|
|
2
|
+
/** Explore's editorial colorways, including light and solid-background variants. */
|
|
3
|
+
const colors = [
|
|
4
|
+
["teal", "#214B4A", "#E1EEEB", "#F7FAF9", "#1C3533"],
|
|
5
|
+
["slate", "#3F5477", "#E6EAF1", "#F9FAFC", "#1D283B"],
|
|
6
|
+
["cobalt", "#2847A9", "#E5EBFC", "#F8FAFF", "#19294E"],
|
|
7
|
+
["clay", "#9D4F32", "#F8E7DE", "#FFFAF6", "#3F2920"],
|
|
8
|
+
["terracotta", "#AC3F25", "#FBE5DC", "#FFFAF5", "#3E241B"],
|
|
9
|
+
["lavender", "#6A497B", "#EEE6F5", "#FCFAFD", "#34243D"],
|
|
10
|
+
["petrol", "#315664", "#E2EDF1", "#F8FBFC", "#223E48"],
|
|
11
|
+
["sand", "#6D5140", "#EFE4D8", "#FCFAF7", "#392C23"],
|
|
12
|
+
["indigo", "#43387D", "#EAE5F6", "#FAF9FD", "#292444"],
|
|
13
|
+
["olive", "#4F633A", "#E8EEDC", "#FBFCF8", "#2D3824"],
|
|
14
|
+
["olive-classic", "#E8EEDC", "#607447", "#4F6339", "#FFFFFF"],
|
|
15
|
+
["rose", "#9B3E61", "#F6E2EB", "#FFFAFC", "#402332"],
|
|
16
|
+
["wine", "#7A3048", "#EFDEE5", "#FCF8FA", "#39202C"],
|
|
17
|
+
["sunflower", "#8A5D12", "#F7EBC6", "#FFFDF5", "#392F1D"],
|
|
18
|
+
["seafoam", "#216C62", "#DDF0E8", "#F7FCFA", "#193D36"],
|
|
19
|
+
["graphite", "#D5B98C", "#30343A", "#1B1E23", "#F5F2EA"],
|
|
20
|
+
["midnight", "#91B7DE", "#22344C", "#132236", "#F3F6FA"],
|
|
21
|
+
["ice", "#27697B", "#DDEFF5", "#F8FCFE", "#193C49"],
|
|
22
|
+
["copper", "#9A563B", "#F1E2D7", "#FCF9F5", "#3F2C23"],
|
|
23
|
+
];
|
|
24
|
+
export const EXPLORE_THEMES = colors.map(([id, accent, surface, background, ink]) => ({
|
|
25
|
+
id: `explore-${id}`,
|
|
26
|
+
palette: { accent, surface, background, ink, muted: ink, line: surface },
|
|
27
|
+
typography: {
|
|
28
|
+
heading: "Playfair Display",
|
|
29
|
+
body: "Inter",
|
|
30
|
+
code: "JetBrains Mono",
|
|
31
|
+
headingWeight: 600,
|
|
32
|
+
},
|
|
33
|
+
geometry: { radius: 4, spacing: 1.1, rule: "hairline" },
|
|
34
|
+
}));
|
|
35
|
+
export const EXPLORE_LAYOUTS = [
|
|
36
|
+
[
|
|
37
|
+
"cover",
|
|
38
|
+
"paragraph",
|
|
39
|
+
0,
|
|
40
|
+
0,
|
|
41
|
+
"Open with a spacious editorial headline, a short premise and an optional real photograph.",
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
"overview",
|
|
45
|
+
"features",
|
|
46
|
+
2,
|
|
47
|
+
4,
|
|
48
|
+
"Orient readers with a numbered overview of parallel subjects.",
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
"section",
|
|
52
|
+
"paragraph",
|
|
53
|
+
0,
|
|
54
|
+
0,
|
|
55
|
+
"Introduce one new section or central principle in a strong color field.",
|
|
56
|
+
],
|
|
57
|
+
[
|
|
58
|
+
"pillars",
|
|
59
|
+
"features",
|
|
60
|
+
2,
|
|
61
|
+
3,
|
|
62
|
+
"Explain two or three equally important ideas in spacious editorial columns.",
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
"focus",
|
|
66
|
+
"paragraph",
|
|
67
|
+
0,
|
|
68
|
+
0,
|
|
69
|
+
"Develop one idea in an asymmetric reading composition.",
|
|
70
|
+
],
|
|
71
|
+
[
|
|
72
|
+
"workflow",
|
|
73
|
+
"steps",
|
|
74
|
+
2,
|
|
75
|
+
4,
|
|
76
|
+
"Show an ordered workflow with explicit actions and useful descriptions.",
|
|
77
|
+
],
|
|
78
|
+
[
|
|
79
|
+
"timeline",
|
|
80
|
+
"steps",
|
|
81
|
+
2,
|
|
82
|
+
4,
|
|
83
|
+
"Present a short chronological sequence on a horizontal reading axis.",
|
|
84
|
+
],
|
|
85
|
+
[
|
|
86
|
+
"comparison",
|
|
87
|
+
"comparison",
|
|
88
|
+
2,
|
|
89
|
+
2,
|
|
90
|
+
"Compare two supplied alternatives with corresponding points.",
|
|
91
|
+
],
|
|
92
|
+
[
|
|
93
|
+
"worksheet",
|
|
94
|
+
"parameters",
|
|
95
|
+
2,
|
|
96
|
+
4,
|
|
97
|
+
"Explain named fields with their concrete values and instructions.",
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
"photo-story",
|
|
101
|
+
"image",
|
|
102
|
+
0,
|
|
103
|
+
0,
|
|
104
|
+
"Use a real contextual photograph beside a concise explanation.",
|
|
105
|
+
],
|
|
106
|
+
[
|
|
107
|
+
"quote",
|
|
108
|
+
"quote",
|
|
109
|
+
0,
|
|
110
|
+
0,
|
|
111
|
+
"Give an exact source statement room to breathe, retaining supplied attribution.",
|
|
112
|
+
],
|
|
113
|
+
[
|
|
114
|
+
"chart",
|
|
115
|
+
"chart",
|
|
116
|
+
2,
|
|
117
|
+
6,
|
|
118
|
+
"Compare source-backed quantities in labeled bars with the original unit.",
|
|
119
|
+
],
|
|
120
|
+
[
|
|
121
|
+
"ledger",
|
|
122
|
+
"parameters",
|
|
123
|
+
2,
|
|
124
|
+
5,
|
|
125
|
+
"Arrange named facts and explanations in a flat editorial ledger.",
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
"faq",
|
|
129
|
+
"features",
|
|
130
|
+
2,
|
|
131
|
+
3,
|
|
132
|
+
"Answer a small set of meaningful questions with concise responses.",
|
|
133
|
+
],
|
|
134
|
+
[
|
|
135
|
+
"action-plan",
|
|
136
|
+
"steps",
|
|
137
|
+
2,
|
|
138
|
+
3,
|
|
139
|
+
"Make the next few actions prominent, with descriptions that explain the work.",
|
|
140
|
+
],
|
|
141
|
+
[
|
|
142
|
+
"closing",
|
|
143
|
+
"paragraph",
|
|
144
|
+
0,
|
|
145
|
+
0,
|
|
146
|
+
"Close with one clear takeaway and a concrete next action.",
|
|
147
|
+
],
|
|
148
|
+
];
|
|
149
|
+
export const EXPLORE_RECIPES = EXPLORE_LAYOUTS.map(([id, kind, min, max]) => ({
|
|
150
|
+
id: `authored-explore-${id}`,
|
|
151
|
+
kind: "presentation",
|
|
152
|
+
renderer: "semantic",
|
|
153
|
+
automatic: true,
|
|
154
|
+
family: kind === "paragraph" ? `hero-explore-${id}` : kind,
|
|
155
|
+
minEntries: min,
|
|
156
|
+
maxEntries: max,
|
|
157
|
+
accepts: (["cover", "photo-story"].includes(id)
|
|
158
|
+
? ["paragraph", "image"]
|
|
159
|
+
: [kind]),
|
|
160
|
+
requiresImage: id === "photo-story",
|
|
161
|
+
}));
|
|
162
|
+
export function exploreCompositionFits(page, id) {
|
|
163
|
+
if (!id.startsWith("authored-explore-"))
|
|
164
|
+
return true;
|
|
165
|
+
const variant = id.slice("authored-explore-".length);
|
|
166
|
+
if (variant === "cover")
|
|
167
|
+
return page.purpose === "cover";
|
|
168
|
+
if (variant === "closing")
|
|
169
|
+
return page.purpose === "conclude";
|
|
170
|
+
if (["cover", "conclude"].includes(page.purpose))
|
|
171
|
+
return false;
|
|
172
|
+
if (variant === "section")
|
|
173
|
+
return (page.blocks.length === 1 &&
|
|
174
|
+
page.blocks[0].kind === "paragraph" &&
|
|
175
|
+
page.blocks[0].text.length <= 160);
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EXPLORE_LAYOUTS } from './exploreCollection.js';
|
|
1
2
|
import { compositionUseCase } from './compositionUseCases.js';
|
|
2
3
|
import { nativeSocialParameterContract } from './nativeSocialParameters.js';
|
|
3
4
|
import { DESIGN_RECIPES } from './designSystem.js';
|
|
@@ -7,7 +8,7 @@ import { SEMANTIC_DISPLAY_NUMBERS, SOCIAL_DISPLAY_NUMBERS } from './compositionN
|
|
|
7
8
|
const both = ['presentation', 'social'];
|
|
8
9
|
const semantic = (id, accepts, minEntries = 0, maxEntries = 12, requiresImage = false) => ({ id, renderer: 'semantic', kind: 'social', family: id, accepts, minEntries, maxEntries, requiresImage });
|
|
9
10
|
function define(recipe, kinds, id, displayNumber, min = .25, max = 4) {
|
|
10
|
-
return { ...recipeParameterContract(recipe, kinds), semanticDescription: compositionUseCase(recipe.id), id, displayNumber, aspectRatios: { min, max }, recipe };
|
|
11
|
+
return { ...recipeParameterContract(recipe, kinds), semanticDescription: EXPLORE_LAYOUTS.find(item => recipe.id === `authored-explore-${item[0]}`)?.[4] || compositionUseCase(recipe.id), id, displayNumber, aspectRatios: { min, max }, recipe };
|
|
11
12
|
}
|
|
12
13
|
/** Structural reference contracts shared with the product's existing renderers.
|
|
13
14
|
* Colorways and historical aliases remain outside active discovery.
|
|
@@ -100,7 +101,7 @@ export const FORMAL_COMPOSITIONS = [
|
|
|
100
101
|
const recipe = DESIGN_RECIPES.find(item => item.id === preset.id && item.kind === 'social');
|
|
101
102
|
return { ...define({ ...recipe, renderer: 'catalog' }, ['social'], `social:${preset.id}`, SOCIAL_DISPLAY_NUMBERS[preset.id], .5, 2.4), ...nativeSocialParameterContract(preset.id) };
|
|
102
103
|
}),
|
|
103
|
-
...uniqueSemantic.map(recipe => define(recipe, semanticRecipes.filter(other => other.id === recipe.id).map(other => other.kind), `semantic:${recipe.kind}:${recipe.id}`, SEMANTIC_DISPLAY_NUMBERS[`semantic:${recipe.kind}:${recipe.id}`])),
|
|
104
|
+
...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(EXPLORE_LAYOUTS.findIndex(item => recipe.id === `authored-explore-${item[0]}`) + 1).padStart(2, "0")}` : SEMANTIC_DISPLAY_NUMBERS[`semantic:${recipe.kind}:${recipe.id}`], recipe.id.startsWith("authored-explore-") ? 1.4 : .25, recipe.id.startsWith("authored-explore-") ? 2 : 4)),
|
|
104
105
|
...founderDefinitions.map(([id, accepts, min, max], index) => define(semantic(id, accepts, min, max), ['social'], `semantic:social:${id}`, `F${index + 1}`, 1.3)),
|
|
105
106
|
...[0, 1, 2].flatMap(variant => [article(`article-cover-${variant}`, 'cover', variant), ...articleKinds.map(kind => article(`article-${kind}-${variant}`, kind, variant))]),
|
|
106
107
|
...[3, 4, 5, 6, 7, 8, 9, 10].map(variant => article(`article-features-${variant}`, 'features', variant)),
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/recipeParameters.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { COMPOSITION_ILLUSTRATIONS } from "./nativeSocialParameters.js";
|
|
2
|
-
import { textPresentationSchema } from
|
|
2
|
+
import { textPresentationSchema } from "./textPresentation.js";
|
|
3
3
|
import { DESIGN_RECIPES } from "./designSystem.js";
|
|
4
4
|
const text = (description, maxLength = 600) => ({
|
|
5
5
|
type: "string",
|
|
@@ -105,7 +105,9 @@ function blockSchema(kind, maximum) {
|
|
|
105
105
|
function fixedBlocks(recipe) {
|
|
106
106
|
const id = recipe.id;
|
|
107
107
|
let kinds;
|
|
108
|
-
if (
|
|
108
|
+
if (["authored-explore-cover", "authored-explore-photo-story"].includes(id))
|
|
109
|
+
kinds = ["paragraph", "image"];
|
|
110
|
+
else if (id.endsWith("ledger-chart"))
|
|
109
111
|
kinds = ["parameters", "chart"];
|
|
110
112
|
else if (id.endsWith("detail-sidebar"))
|
|
111
113
|
kinds = ["paragraph", "parameters"];
|
|
@@ -147,8 +149,13 @@ function fixedBlocks(recipe) {
|
|
|
147
149
|
const fields = schema.properties;
|
|
148
150
|
const count = Math.max(recipe.minEntries || 1, Math.min(3, recipe.maxEntries || 3));
|
|
149
151
|
if (kind === "paragraph")
|
|
150
|
-
fields.text.maxLength =
|
|
151
|
-
|
|
152
|
+
fields.text.maxLength = [
|
|
153
|
+
"authored-reference-detail-sidebar",
|
|
154
|
+
"authored-reference-diagonal",
|
|
155
|
+
"authored-prose-inset",
|
|
156
|
+
].includes(id)
|
|
157
|
+
? 160
|
|
158
|
+
: 120;
|
|
152
159
|
if (kind === "features" || kind === "steps") {
|
|
153
160
|
const entries = fields.entries;
|
|
154
161
|
entries.minItems = id === "authored-reference-story" ? 2 : count;
|
|
@@ -160,7 +167,24 @@ function fixedBlocks(recipe) {
|
|
|
160
167
|
description: "Editable native illustration for the item. Choose the visual concept that explains its meaning. This field controls a graphic, not prose.",
|
|
161
168
|
};
|
|
162
169
|
entries.items.required.push("illustration");
|
|
163
|
-
entries.items.properties.icon = {
|
|
170
|
+
entries.items.properties.icon = {
|
|
171
|
+
type: "string",
|
|
172
|
+
enum: [
|
|
173
|
+
"BsJournalText",
|
|
174
|
+
"BsPersonCheck",
|
|
175
|
+
"BsShare",
|
|
176
|
+
"BsPeople",
|
|
177
|
+
"BsSearch",
|
|
178
|
+
"BsShieldCheck",
|
|
179
|
+
"BsBarChart",
|
|
180
|
+
"BsCodeSlash",
|
|
181
|
+
"BsSignpostSplit",
|
|
182
|
+
"BsCheck2Circle",
|
|
183
|
+
"BsFolder2Open",
|
|
184
|
+
"BsGrid1X2",
|
|
185
|
+
],
|
|
186
|
+
description: "Optional authored icon variant; illustration remains the primary visual concept.",
|
|
187
|
+
};
|
|
164
188
|
entries.items.properties.title.maxLength = 28;
|
|
165
189
|
entries.items.properties.description.maxLength =
|
|
166
190
|
id === "authored-feature-focus" ? 160 : 48;
|
|
@@ -173,7 +197,11 @@ function fixedBlocks(recipe) {
|
|
|
173
197
|
id.includes("speaker-")
|
|
174
198
|
? 2
|
|
175
199
|
: count;
|
|
176
|
-
fields.rows.minItems = id.endsWith("speaker-lineup")
|
|
200
|
+
fields.rows.minItems = id.endsWith("speaker-lineup")
|
|
201
|
+
? 1
|
|
202
|
+
: id === "pricing"
|
|
203
|
+
? 2
|
|
204
|
+
: rows;
|
|
177
205
|
fields.rows.maxItems = rows;
|
|
178
206
|
fields.rows.items.properties.name.maxLength = 20;
|
|
179
207
|
fields.rows.items.properties.value.maxLength = 24;
|
|
@@ -188,7 +216,8 @@ function fixedBlocks(recipe) {
|
|
|
188
216
|
column.title.maxLength = 20;
|
|
189
217
|
column.points.minItems = id === "authored-founder-comparison" ? 1 : 2;
|
|
190
218
|
column.points.maxItems = 3;
|
|
191
|
-
column.points.items.maxLength =
|
|
219
|
+
column.points.items.maxLength =
|
|
220
|
+
id === "authored-founder-comparison" ? 64 : 40;
|
|
192
221
|
column.values.maxItems = 3;
|
|
193
222
|
column.values.items.maxLength = 16;
|
|
194
223
|
column.values.minItems = 0;
|
|
@@ -225,19 +254,61 @@ function fixedBlocks(recipe) {
|
|
|
225
254
|
fields.chart = { const: "bar" };
|
|
226
255
|
if (/donut|reference-share|reference-metrics/.test(id)) {
|
|
227
256
|
fields.chart = { const: "bar" };
|
|
228
|
-
fields.unit = {
|
|
257
|
+
fields.unit = {
|
|
258
|
+
type: "string",
|
|
259
|
+
maxLength: 24,
|
|
260
|
+
pattern: "%",
|
|
261
|
+
description: "Percentage unit, optionally qualified as illustrative or simulated.",
|
|
262
|
+
};
|
|
229
263
|
fields.values.description =
|
|
230
264
|
"Nonnegative shares totaling exactly 100. Use labeled illustrative shares when the input has no comparable numbers.";
|
|
231
265
|
fields.values.items.properties.value.minimum = 0;
|
|
232
266
|
fields.values.items.properties.value.maximum = 100;
|
|
233
267
|
}
|
|
234
268
|
}
|
|
269
|
+
if (id.startsWith("authored-explore-")) {
|
|
270
|
+
if (kind === "paragraph") {
|
|
271
|
+
fields.text.maxLength = 220;
|
|
272
|
+
if (id !== "authored-explore-focus") {
|
|
273
|
+
delete fields.heading;
|
|
274
|
+
delete fields.level;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (kind === "features" || kind === "steps") {
|
|
278
|
+
fields.entries.minItems = Math.max(2, recipe.minEntries);
|
|
279
|
+
fields.entries.maxItems = recipe.maxEntries;
|
|
280
|
+
fields.entries.items.properties.title.maxLength = 44;
|
|
281
|
+
fields.entries.items.properties.description.maxLength = 120;
|
|
282
|
+
delete fields.entries.items.properties.illustration;
|
|
283
|
+
delete fields.entries.items.properties.icon;
|
|
284
|
+
fields.entries.items.required = fields.entries.items.required.filter((key) => !["illustration", "icon"].includes(key));
|
|
285
|
+
}
|
|
286
|
+
if (kind === "parameters") {
|
|
287
|
+
fields.rows.minItems = recipe.minEntries;
|
|
288
|
+
fields.rows.maxItems = recipe.maxEntries;
|
|
289
|
+
fields.rows.items.properties.name.maxLength = 36;
|
|
290
|
+
fields.rows.items.properties.value.maxLength = 120;
|
|
291
|
+
fields.rows.items.properties.description.maxLength = 60;
|
|
292
|
+
}
|
|
293
|
+
if (kind === "comparison") {
|
|
294
|
+
fields.columns.items.properties.points.maxItems = 3;
|
|
295
|
+
fields.columns.items.properties.points.items.maxLength = 100;
|
|
296
|
+
for (const key of ["price", "values", "statuses"])
|
|
297
|
+
delete fields.columns.items.properties[key];
|
|
298
|
+
}
|
|
299
|
+
if (kind === "chart") {
|
|
300
|
+
fields.chart = { const: "bar" };
|
|
301
|
+
fields.values.minItems = 2;
|
|
302
|
+
fields.values.maxItems = 6;
|
|
303
|
+
fields.values.items.properties.value.minimum = 0;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
235
306
|
return schema;
|
|
236
307
|
});
|
|
237
308
|
return {
|
|
238
309
|
type: "array",
|
|
239
310
|
items,
|
|
240
|
-
minItems: items.length,
|
|
311
|
+
minItems: id === "authored-explore-cover" ? 1 : items.length,
|
|
241
312
|
maxItems: items.length,
|
|
242
313
|
additionalItems: false,
|
|
243
314
|
description: "Fixed ordered parameters for this renderer. Return every block exactly once in this order; do not add explanatory blocks.",
|
package/package.json
CHANGED