@aglyn/plugins-ai 1.0.0-beta.232 → 1.0.0-beta.234
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/package.json +17 -17
- package/src/lib/components/ai-job-links.d.ts +6 -0
- package/src/lib/components/ai-job-links.js +9 -0
- package/src/lib/components/ai-job-links.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +41 -3
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.js +91 -8
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/declarations.server.js +7 -4
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/jobs/ai-build-capabilities.js +8 -2
- package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
- package/src/lib/jobs/ai-job-admission.d.ts +2 -1
- package/src/lib/jobs/ai-job-admission.js.map +1 -1
- package/src/lib/jobs/ai-job-email-step.d.ts +39 -0
- package/src/lib/jobs/ai-job-email-step.js +116 -5
- package/src/lib/jobs/ai-job-email-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +3 -0
- package/src/lib/jobs/ai-job-layout-language.js +3 -1
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-site-pages.d.ts +2 -0
- package/src/lib/jobs/ai-job-layout-site-pages.js +23 -11
- package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.js +3 -2
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +16 -0
- package/src/lib/jobs/ai-job-page-language.js +35 -6
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +3 -0
- package/src/lib/jobs/ai-job-page-step.js +18 -4
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +40 -1
- package/src/lib/jobs/ai-job-plan-step.js +121 -16
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-content.d.ts +6 -6
- package/src/lib/jobs/ai-job-site-content.js +6 -12
- package/src/lib/jobs/ai-job-site-content.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +11 -0
- package/src/lib/jobs/ai-job-site-step.js +96 -44
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs-notify.d.ts +14 -4
- package/src/lib/jobs/ai-jobs-notify.js +70 -4
- package/src/lib/jobs/ai-jobs-notify.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +22 -4
- package/src/lib/jobs/ai-jobs.js +47 -12
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +98 -0
- package/src/lib/jobs/ai-layout-stock-photos.js +248 -0
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -0
- package/src/lib/jobs/ai-site-publish.d.ts +11 -0
- package/src/lib/jobs/ai-site-publish.js +31 -1
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.d.ts +151 -0
- package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.js +183 -0
- package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.d.ts +27 -0
- package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.js +192 -0
- package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.d.ts +27 -0
- package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.js +222 -0
- package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +29 -0
- package/src/lib/layout-language/ai-layout-compiler.js +698 -12
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +107 -0
- package/src/lib/layout-language/ai-layout-design.js +197 -0
- package/src/lib/layout-language/ai-layout-design.js.map +1 -0
- package/src/lib/layout-language/ai-layout-frame.d.ts +6 -0
- package/src/lib/layout-language/ai-layout-frame.js +22 -6
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-language.d.ts +2 -0
- package/src/lib/layout-language/ai-layout-language.js +15 -1
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/layout-language/ai-layout-links.d.ts +11 -0
- package/src/lib/layout-language/ai-layout-links.js +4 -0
- package/src/lib/layout-language/ai-layout-links.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +11 -5
- package/src/lib/layout-language/ai-layout-pictures.js +80 -17
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-job-notice.d.ts +9 -1
- package/src/lib/model/ai-job-notice.js +23 -0
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-plan-capabilities.d.ts +23 -0
- package/src/lib/model/ai-plan-capabilities.js +5 -0
- package/src/lib/model/ai-plan-capabilities.js.map +1 -1
- package/src/lib/model/ai-site-build-progress.d.ts +12 -2
- package/src/lib/model/ai-site-build-progress.js +78 -4
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +209 -22
- package/src/lib/model/ai-site-job.js +247 -20
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.js +6 -1
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/model/ai-site-look.d.ts +21 -0
- package/src/lib/model/ai-site-look.js +63 -14
- package/src/lib/model/ai-site-look.js.map +1 -1
- package/src/lib/operator-alerts.d.ts +18 -0
- package/src/lib/operator-alerts.js +42 -0
- package/src/lib/operator-alerts.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +39 -1
- package/src/lib/runtime/ai-doctrine-validators.js +236 -6
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +5 -3
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.d.ts +2 -0
- package/src/lib/runtime/ai-palette.generated.js +18 -2
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/server/ai-jobs-resume.js.map +1 -1
- package/src/lib/server/ai-jobs-route.js +15 -3
- package/src/lib/server/ai-jobs-route.js.map +1 -1
- package/src/lib/server/assist-edit.js +5 -2
- package/src/lib/server/assist-edit.js.map +1 -1
- package/src/lib/usage/free-ai-credits-left.d.ts +54 -0
- package/src/lib/usage/free-ai-credits-left.js +62 -0
- package/src/lib/usage/free-ai-credits-left.js.map +1 -0
|
@@ -22,6 +22,7 @@ import { AI_INSTANCE_REF_PROP } from "../runtime/ai-node-tree.js";
|
|
|
22
22
|
import { aiPageScrollInteraction } from "../runtime/ai-page-links.js";
|
|
23
23
|
import { aiLayoutFitText, aiLayoutQuoteGap, aiLayoutWords } from "./ai-layout-copy.js";
|
|
24
24
|
import { AI_LAYOUT_GROUP_KINDS, AI_LAYOUT_MAX_ITEMS } from "./ai-layout-language.js";
|
|
25
|
+
import { aiLayoutDesignChoices, aiLayoutGroupVariant } from "./ai-layout-design.js";
|
|
25
26
|
import { aiLayoutResolveLink } from "./ai-layout-links.js";
|
|
26
27
|
import { AI_LAYOUT_FRAMES, AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
27
28
|
/** A section root's id where the caller gives none. */ function sectionIdOf(index) {
|
|
@@ -69,7 +70,14 @@ const componentOf = (targets, id)=>{
|
|
|
69
70
|
formSection: formSectionOf(sections, plan, targets),
|
|
70
71
|
pageIcon: pageIconOf(sections),
|
|
71
72
|
formsPlaced: new Set(),
|
|
72
|
-
itemIds: plan.sections.map(()=>[])
|
|
73
|
+
itemIds: plan.sections.map(()=>[]),
|
|
74
|
+
design: options.design ? {
|
|
75
|
+
input: options.design,
|
|
76
|
+
choices: aiLayoutDesignChoices(options.design)
|
|
77
|
+
} : null,
|
|
78
|
+
pictures: 0,
|
|
79
|
+
features: 0,
|
|
80
|
+
splitAt: -2
|
|
73
81
|
};
|
|
74
82
|
const roots = plan.sections.map((_, index)=>{
|
|
75
83
|
var _sections_index;
|
|
@@ -106,8 +114,8 @@ const componentOf = (targets, id)=>{
|
|
|
106
114
|
}
|
|
107
115
|
// ── A section ─────────────────────────────────────────────────────────────
|
|
108
116
|
function compileSection(page, raw, index) {
|
|
109
|
-
var _raw_band, _ref;
|
|
110
|
-
var _placedHere_, _page_plan_sections_index_name,
|
|
117
|
+
var _raw_band, _ref, _ref1;
|
|
118
|
+
var _raw_blocks_find, _page_plan_sections_index, _placedHere_, _page_plan_sections_index_name, _page_plan_sections_index1, _page_options_sectionIds;
|
|
111
119
|
const at = `sections[${index}]`;
|
|
112
120
|
const band = settleBand(page, (_raw_band = raw.band) != null ? _raw_band : 'plain', at);
|
|
113
121
|
const scope = {
|
|
@@ -123,7 +131,15 @@ function compileSection(page, raw, index) {
|
|
|
123
131
|
sections: page.plan.sections.map((section)=>section.name),
|
|
124
132
|
from: index,
|
|
125
133
|
formSection: page.formSection
|
|
126
|
-
}
|
|
134
|
+
},
|
|
135
|
+
heading: (_raw_blocks_find = raw.blocks.find((block)=>block.kind === 'heading')) == null ? void 0 : _raw_blocks_find.text,
|
|
136
|
+
words: [
|
|
137
|
+
(_ref = (_page_plan_sections_index = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index.name) != null ? _ref : '',
|
|
138
|
+
...raw.blocks.filter((block)=>block.kind === 'heading' || block.kind === 'eyebrow').map((block)=>{
|
|
139
|
+
var _block_text;
|
|
140
|
+
return (_block_text = block.text) != null ? _block_text : '';
|
|
141
|
+
})
|
|
142
|
+
].join(' ')
|
|
127
143
|
};
|
|
128
144
|
// A quote is a gap the owner fills, and a published page shows no gap (AGL-3660).
|
|
129
145
|
const blocks = placePlanned(scope, raw).filter((block)=>{
|
|
@@ -134,6 +150,11 @@ function compileSection(page, raw, index) {
|
|
|
134
150
|
});
|
|
135
151
|
return false;
|
|
136
152
|
});
|
|
153
|
+
// The site's design draws the sections it has an arrangement for (AGL-3660).
|
|
154
|
+
if (page.design) {
|
|
155
|
+
const designed = designSection(scope, raw, blocks);
|
|
156
|
+
if (designed) return designed;
|
|
157
|
+
}
|
|
137
158
|
const cols = raw.cols && raw.cols.length >= 2 ? raw.cols : null;
|
|
138
159
|
// Above the row, the row's columns, and below it.
|
|
139
160
|
const head = [];
|
|
@@ -280,13 +301,13 @@ function compileSection(page, raw, index) {
|
|
|
280
301
|
}
|
|
281
302
|
}
|
|
282
303
|
if (!parts.length) {
|
|
283
|
-
var
|
|
304
|
+
var _page_plan_sections_index2;
|
|
284
305
|
// Nothing the design gave this section could be shown: it keeps its
|
|
285
306
|
// place on the page under the name its plan gives it.
|
|
286
307
|
const fallback = compileFlow(scope, [
|
|
287
308
|
{
|
|
288
309
|
kind: 'heading',
|
|
289
|
-
text: ((
|
|
310
|
+
text: ((_page_plan_sections_index2 = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index2.name) || page.plan.title
|
|
290
311
|
}
|
|
291
312
|
], 'full');
|
|
292
313
|
if (fallback) parts.push(fallback);
|
|
@@ -308,7 +329,7 @@ function compileSection(page, raw, index) {
|
|
|
308
329
|
}, [
|
|
309
330
|
content
|
|
310
331
|
], 'container');
|
|
311
|
-
const name = ((
|
|
332
|
+
const name = ((_page_plan_sections_index1 = page.plan.sections[index]) == null ? void 0 : (_page_plan_sections_index_name = _page_plan_sections_index1.name) == null ? void 0 : _page_plan_sections_index_name.trim()) || `Section ${index + 1}`;
|
|
312
333
|
return tree.add('section', _extends({
|
|
313
334
|
element: 'section',
|
|
314
335
|
ariaLabel: aiLayoutFitText(name, 'note') || `Section ${index + 1}`
|
|
@@ -316,7 +337,7 @@ function compileSection(page, raw, index) {
|
|
|
316
337
|
colorScheme: 'dark'
|
|
317
338
|
} : {}), bandSx(band), [
|
|
318
339
|
container
|
|
319
|
-
], 'section', (
|
|
340
|
+
], 'section', (_ref1 = (_page_options_sectionIds = page.options.sectionIds) == null ? void 0 : _page_options_sectionIds[index]) != null ? _ref1 : sectionIdOf(index));
|
|
320
341
|
}
|
|
321
342
|
/**
|
|
322
343
|
* A component block's prop values as a card item: its title-like prop as the
|
|
@@ -650,12 +671,12 @@ function compileBlock(scope, block, room) {
|
|
|
650
671
|
}
|
|
651
672
|
}
|
|
652
673
|
/** Secondary words' color: muted text, or the band's own on a brand band. */ function muted(scope) {
|
|
653
|
-
return scope.band === 'brand' ? null : {
|
|
674
|
+
return scope.band === 'brand' || scope.overPhoto ? null : {
|
|
654
675
|
color: 'text.secondary'
|
|
655
676
|
};
|
|
656
677
|
}
|
|
657
678
|
/** An accent's color: the brand's, or the band's own on a brand band. */ function accent(scope) {
|
|
658
|
-
return scope.band === 'brand' ? null : {
|
|
679
|
+
return scope.band === 'brand' || scope.overPhoto ? null : {
|
|
659
680
|
color: 'primary.main'
|
|
660
681
|
};
|
|
661
682
|
}
|
|
@@ -713,7 +734,8 @@ function compileButton(scope, block) {
|
|
|
713
734
|
return null;
|
|
714
735
|
}
|
|
715
736
|
const style = (_block_style = block.style) != null ? _block_style : 'primary';
|
|
716
|
-
|
|
737
|
+
// Over a photo, a quiet or outlined button takes the words' own color, as on a brand band.
|
|
738
|
+
const onBrand = scope.band === 'brand' || !!scope.overPhoto && style !== 'primary';
|
|
717
739
|
const look = style === 'quiet' ? {
|
|
718
740
|
variant: 'text',
|
|
719
741
|
color: onBrand ? 'inherit' : 'primary'
|
|
@@ -760,6 +782,9 @@ export function destinationProps(destination) {
|
|
|
760
782
|
href: destination.href,
|
|
761
783
|
target: '_blank'
|
|
762
784
|
};
|
|
785
|
+
if (destination.kind === 'path') return {
|
|
786
|
+
href: destination.href
|
|
787
|
+
};
|
|
763
788
|
return {};
|
|
764
789
|
}
|
|
765
790
|
/**
|
|
@@ -968,7 +993,24 @@ function group(scope, block, room) {
|
|
|
968
993
|
const perRow = across(items.length, room, block.kind);
|
|
969
994
|
const placed = componentOf(scope.page.targets, block.to);
|
|
970
995
|
if (placed) return instances(scope, placed, items, perRow);
|
|
971
|
-
|
|
996
|
+
const design = scope.page.design;
|
|
997
|
+
if (rule1(scope)) {
|
|
998
|
+
var _scope_words;
|
|
999
|
+
// Picture cards the design draws are the compiler's, not a block typed out
|
|
1000
|
+
// by hand (`repeatsCompiled`, AGL-3660); every other repeat stays compact.
|
|
1001
|
+
const variant = design && block.kind === 'cards' && block.style !== 'quiet' ? aiLayoutGroupVariant(design.input, design.choices, (_scope_words = scope.words) != null ? _scope_words : '') : null;
|
|
1002
|
+
const pictured = (variant === 'pictures' || variant === 'articles') && room === 'full' && picturesLeft(scope.page) >= items.length;
|
|
1003
|
+
return pictured && designedGroup(scope, variant, items, room) || compactGroup(scope, block, items, perRow);
|
|
1004
|
+
}
|
|
1005
|
+
if (design && block.kind === 'steps' && (design.choices.steps === 'timeline' || room !== 'full')) {
|
|
1006
|
+
return timeline(scope, items);
|
|
1007
|
+
}
|
|
1008
|
+
if (design && block.kind === 'cards' && block.style !== 'quiet') {
|
|
1009
|
+
var _scope_groupStyle, _scope_words1;
|
|
1010
|
+
const variant = (_scope_groupStyle = scope.groupStyle) != null ? _scope_groupStyle : aiLayoutGroupVariant(design.input, design.choices, (_scope_words1 = scope.words) != null ? _scope_words1 : '');
|
|
1011
|
+
const drawn = designedGroup(scope, variant, items, room);
|
|
1012
|
+
if (drawn) return drawn;
|
|
1013
|
+
}
|
|
972
1014
|
switch(block.kind){
|
|
973
1015
|
case 'steps':
|
|
974
1016
|
return layOut(scope, noted(scope, items.map((item, position)=>step(scope, item, position))), perRow, '4', 'steps');
|
|
@@ -1230,6 +1272,650 @@ function instances(scope, placed, items, perRow) {
|
|
|
1230
1272
|
spacing: '1.5'
|
|
1231
1273
|
}, null, noted(scope, panels), 'faq');
|
|
1232
1274
|
}
|
|
1275
|
+
// ── The designer layer (AGL-3660) ─────────────────────────────────────────
|
|
1276
|
+
//
|
|
1277
|
+
// What `ai-layout-design.ts` chose for the site, drawn: the hero, a section
|
|
1278
|
+
// of words beside a picture, a closing band over a photo, a heading beside
|
|
1279
|
+
// its items, and groups drawn as pictures, articles, a menu or open ruled
|
|
1280
|
+
// columns. Every variant is built from the same palette elements and theme
|
|
1281
|
+
// tokens as the rest of the compiler, so the doctrine holds by construction.
|
|
1282
|
+
/** The most pictures a designed page carries, the model's and the stand-ins together. */ export const AI_LAYOUT_MAX_DESIGN_PICTURES = 8;
|
|
1283
|
+
/** The block kinds a section of words holds. */ const WORD_KINDS = new Set([
|
|
1284
|
+
'eyebrow',
|
|
1285
|
+
'heading',
|
|
1286
|
+
'lede',
|
|
1287
|
+
'text',
|
|
1288
|
+
'note',
|
|
1289
|
+
'button'
|
|
1290
|
+
]);
|
|
1291
|
+
/** How many more pictures the page has room for. */ function picturesLeft(page) {
|
|
1292
|
+
return AI_LAYOUT_MAX_DESIGN_PICTURES - page.images - page.pictures;
|
|
1293
|
+
}
|
|
1294
|
+
/** Whether a heading block has words left once fitted: one with none is no heading. */ function speaksHeading(scope, block) {
|
|
1295
|
+
return block.kind === 'heading' && !!aiLayoutWords(block.text, 'heading', scope.page.targets.facts);
|
|
1296
|
+
}
|
|
1297
|
+
/** The section root every designed section is written under, as `compileSection` writes its own. */ function designedRoot(scope, children, sx, dark) {
|
|
1298
|
+
var _ref;
|
|
1299
|
+
var _page_plan_sections_index_name, _page_plan_sections_index, _page_options_sectionIds;
|
|
1300
|
+
const { page, index } = scope;
|
|
1301
|
+
const name = ((_page_plan_sections_index = page.plan.sections[index]) == null ? void 0 : (_page_plan_sections_index_name = _page_plan_sections_index.name) == null ? void 0 : _page_plan_sections_index_name.trim()) || `Section ${index + 1}`;
|
|
1302
|
+
return page.tree.add('section', _extends({
|
|
1303
|
+
element: 'section',
|
|
1304
|
+
ariaLabel: aiLayoutFitText(name, 'note') || `Section ${index + 1}`
|
|
1305
|
+
}, dark ? {
|
|
1306
|
+
colorScheme: 'dark'
|
|
1307
|
+
} : {}, index === 0 && scope.overPhoto ? {
|
|
1308
|
+
underHeader: true
|
|
1309
|
+
} : {}), sx, children, 'section', (_ref = (_page_options_sectionIds = page.options.sectionIds) == null ? void 0 : _page_options_sectionIds[index]) != null ? _ref : sectionIdOf(index));
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* A picture the design places: the model's own where it described one, else
|
|
1313
|
+
* a stand-in — marked decorative, since no one described it, with the
|
|
1314
|
+
* section's words as what a stock search looks for. Either is filled by
|
|
1315
|
+
* `ai-layout-pictures.ts` after the page is checked, as any slot is.
|
|
1316
|
+
*/ function designPicture(scope, picture, frameSx, role = 'designFrame', imageSx = {}) {
|
|
1317
|
+
const tree = scope.page.tree;
|
|
1318
|
+
// The picture fills its frame by its own size props, so the frame alone
|
|
1319
|
+
// carries a style: a page of many pictures repeats no inline style (rule 16).
|
|
1320
|
+
const image = designImage(scope, picture, {
|
|
1321
|
+
width: '100%',
|
|
1322
|
+
height: '100%'
|
|
1323
|
+
}, Object.keys(imageSx).length ? imageSx : null);
|
|
1324
|
+
return tree.add('muiBox', null, _extends({
|
|
1325
|
+
position: 'relative',
|
|
1326
|
+
overflow: 'hidden',
|
|
1327
|
+
bgcolor: 'action.hover'
|
|
1328
|
+
}, frameSx), [
|
|
1329
|
+
image
|
|
1330
|
+
], role);
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* The `image` a designed picture is: its alt, its fit and, for a stand-in,
|
|
1334
|
+
* decorative. Its slot is filled after the page is checked.
|
|
1335
|
+
*/ function designImage(scope, picture, props, sx) {
|
|
1336
|
+
const { page } = scope;
|
|
1337
|
+
if (picture.given) page.images += 1;
|
|
1338
|
+
else page.pictures += 1;
|
|
1339
|
+
return page.tree.add('image', _extends({
|
|
1340
|
+
alt: picture.alt,
|
|
1341
|
+
objectFit: 'cover'
|
|
1342
|
+
}, picture.given ? {} : {
|
|
1343
|
+
decorative: true
|
|
1344
|
+
}, props), sx, null, 'image');
|
|
1345
|
+
}
|
|
1346
|
+
/** What a stand-in picture is of, for a stock search: the section's subject, else the site's. */ function standInAlt(scope, words) {
|
|
1347
|
+
var _scope_page_plan_sections_scope_index;
|
|
1348
|
+
return aiLayoutFitText(words, 'alt') || aiLayoutFitText(scope.heading, 'alt') || aiLayoutFitText((_scope_page_plan_sections_scope_index = scope.page.plan.sections[scope.index]) == null ? void 0 : _scope_page_plan_sections_scope_index.name, 'alt') || aiLayoutFitText(scope.page.plan.title, 'alt') || 'A photo';
|
|
1349
|
+
}
|
|
1350
|
+
/** A grid row of sized cells, as `compileRow` writes one, from ids already compiled. */ function designRow(scope, cells, spacing, alignItems = 'center') {
|
|
1351
|
+
const tree = scope.page.tree;
|
|
1352
|
+
return tree.add('muiGrid', {
|
|
1353
|
+
container: true,
|
|
1354
|
+
spacing
|
|
1355
|
+
}, {
|
|
1356
|
+
alignItems
|
|
1357
|
+
}, cells.map((cell)=>{
|
|
1358
|
+
var _cell_sx;
|
|
1359
|
+
return tree.add('muiGrid', {
|
|
1360
|
+
size: cell.size
|
|
1361
|
+
}, (_cell_sx = cell.sx) != null ? _cell_sx : null, [
|
|
1362
|
+
cell.id
|
|
1363
|
+
], 'column');
|
|
1364
|
+
}), 'row');
|
|
1365
|
+
}
|
|
1366
|
+
/** A section's own arrangement where the design has one; `null` to draw it the compiler's first way. */ function designSection(scope, raw, blocks) {
|
|
1367
|
+
var _scope_words, _ref, _ref1;
|
|
1368
|
+
var _group_items, _group_items1;
|
|
1369
|
+
const { page, index } = scope;
|
|
1370
|
+
const design = page.design;
|
|
1371
|
+
if (!design) return null;
|
|
1372
|
+
const images = blocks.filter((block)=>block.kind === 'image');
|
|
1373
|
+
const words = blocks.filter((block)=>block.kind !== 'image');
|
|
1374
|
+
const ofWords = words.length > 0 && words.every((block)=>WORD_KINDS.has(block.kind));
|
|
1375
|
+
if (index === 0) {
|
|
1376
|
+
var _words_find;
|
|
1377
|
+
if (!ofWords || images.length > 1 || picturesLeft(page) < 1) return null;
|
|
1378
|
+
const flow = [
|
|
1379
|
+
...words
|
|
1380
|
+
];
|
|
1381
|
+
if (!flow.some((block)=>speaksHeading(scope, block))) {
|
|
1382
|
+
flow.unshift({
|
|
1383
|
+
kind: 'heading',
|
|
1384
|
+
text: page.plan.title
|
|
1385
|
+
});
|
|
1386
|
+
page.settled.push({
|
|
1387
|
+
at: scope.at,
|
|
1388
|
+
what: "no heading; the page's title written as its h1"
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
// A designed hero's title is display-sized; beside a photo, in half the
|
|
1392
|
+
// page, it is the page's title size, so a long one still reads in a few lines.
|
|
1393
|
+
const lead = flow.findIndex((block)=>speaksHeading(scope, block));
|
|
1394
|
+
const _flow_lead = flow[lead], { style: _style } = _flow_lead, title = _object_without_properties_loose(_flow_lead, [
|
|
1395
|
+
"style"
|
|
1396
|
+
]);
|
|
1397
|
+
flow[lead] = design.choices.hero === 'split' ? title : _extends({}, title, {
|
|
1398
|
+
style: 'large'
|
|
1399
|
+
});
|
|
1400
|
+
const given = images[0] ? aiLayoutFitText(images[0].text, 'alt') : '';
|
|
1401
|
+
return hero(scope, raw, flow, given ? {
|
|
1402
|
+
alt: given,
|
|
1403
|
+
given: true
|
|
1404
|
+
} : {
|
|
1405
|
+
alt: standInAlt(scope, (_words_find = words.find((block)=>speaksHeading(scope, block))) == null ? void 0 : _words_find.text),
|
|
1406
|
+
given: false
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
if (ofWords && !images.length && words.some((block)=>speaksHeading(scope, block))) {
|
|
1410
|
+
const last = index === page.plan.sections.length - 1;
|
|
1411
|
+
const asks = words.some((block)=>block.kind === 'button');
|
|
1412
|
+
const strong = scope.band === 'brand' || scope.band === 'dark';
|
|
1413
|
+
const told = words.some((block)=>block.kind === 'text' || block.kind === 'lede');
|
|
1414
|
+
if (last && asks && (strong || scope.centered) && design.choices.coverClose && picturesLeft(page) >= 1) {
|
|
1415
|
+
return coverBand(scope, words);
|
|
1416
|
+
}
|
|
1417
|
+
if (design.choices.features && told && page.features < 2 && picturesLeft(page) >= 1 && !(last && asks && strong)) {
|
|
1418
|
+
return feature(scope, words);
|
|
1419
|
+
}
|
|
1420
|
+
return null;
|
|
1421
|
+
}
|
|
1422
|
+
// A heading over one group of items: the heading beside them.
|
|
1423
|
+
if (!design.choices.splitHeads || images.length || page.splitAt === index - 1) return null;
|
|
1424
|
+
const at = words.findIndex((block)=>block.kind === 'cards' || block.kind === 'steps');
|
|
1425
|
+
if (at <= 0) return null;
|
|
1426
|
+
const head = words.slice(0, at);
|
|
1427
|
+
const group = words[at];
|
|
1428
|
+
const tail = words.slice(at + 1);
|
|
1429
|
+
const variant = aiLayoutGroupVariant(design.input, design.choices, (_scope_words = scope.words) != null ? _scope_words : '');
|
|
1430
|
+
if (!head.every((block)=>WORD_KINDS.has(block.kind) && block.kind !== 'button') || !head.some((block)=>speaksHeading(scope, block)) || !tail.every((block)=>WORD_KINDS.has(block.kind)) || ((_ref = (_group_items = group.items) == null ? void 0 : _group_items.length) != null ? _ref : 0) < 2 || ((_ref1 = (_group_items1 = group.items) == null ? void 0 : _group_items1.length) != null ? _ref1 : 0) > 6 || group.to || group.kind === 'cards' && variant !== 'cards' && variant !== 'ruled') {
|
|
1431
|
+
return null;
|
|
1432
|
+
}
|
|
1433
|
+
return splitSection(scope, head, group, tail);
|
|
1434
|
+
}
|
|
1435
|
+
/** The first section, in the site's hero arrangement. */ function hero(scope, raw, flow, picture) {
|
|
1436
|
+
const { page } = scope;
|
|
1437
|
+
const tree = page.tree;
|
|
1438
|
+
const design = page.design;
|
|
1439
|
+
const home = design.input.home;
|
|
1440
|
+
const variant = design.choices.hero;
|
|
1441
|
+
page.settled.push({
|
|
1442
|
+
at: scope.at,
|
|
1443
|
+
what: `drawn as a ${variant} hero`
|
|
1444
|
+
});
|
|
1445
|
+
if (variant === 'cover') {
|
|
1446
|
+
scope.band = 'dark';
|
|
1447
|
+
scope.centered = raw.align === 'center';
|
|
1448
|
+
return cover(scope, flow, picture, home ? {
|
|
1449
|
+
xs: '78vh',
|
|
1450
|
+
md: '86vh'
|
|
1451
|
+
} : {
|
|
1452
|
+
xs: '46vh',
|
|
1453
|
+
md: '54vh'
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
const band = scope.band;
|
|
1457
|
+
scope.centered = false;
|
|
1458
|
+
if (variant === 'split') {
|
|
1459
|
+
const words = compileFlow(scope, flow, 'half');
|
|
1460
|
+
const photo = designPicture(scope, picture, {
|
|
1461
|
+
aspectRatio: home ? {
|
|
1462
|
+
xs: '4 / 3',
|
|
1463
|
+
md: '4 / 5'
|
|
1464
|
+
} : {
|
|
1465
|
+
xs: '4 / 3',
|
|
1466
|
+
md: '1 / 1'
|
|
1467
|
+
},
|
|
1468
|
+
borderRadius: 2
|
|
1469
|
+
});
|
|
1470
|
+
const right = design.choices.featureLeft;
|
|
1471
|
+
const row = designRow(scope, [
|
|
1472
|
+
_extends({
|
|
1473
|
+
id: words,
|
|
1474
|
+
size: 'xs:12 md:6'
|
|
1475
|
+
}, right ? {
|
|
1476
|
+
sx: {
|
|
1477
|
+
order: {
|
|
1478
|
+
xs: 0,
|
|
1479
|
+
md: 1
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
} : {}),
|
|
1483
|
+
{
|
|
1484
|
+
id: photo,
|
|
1485
|
+
size: 'xs:12 md:6'
|
|
1486
|
+
}
|
|
1487
|
+
], '8');
|
|
1488
|
+
const container = tree.add('muiContainer', {
|
|
1489
|
+
maxWidth: 'lg'
|
|
1490
|
+
}, {
|
|
1491
|
+
py: {
|
|
1492
|
+
xs: 6,
|
|
1493
|
+
md: 10
|
|
1494
|
+
}
|
|
1495
|
+
}, [
|
|
1496
|
+
row
|
|
1497
|
+
], 'container');
|
|
1498
|
+
return designedRoot(scope, [
|
|
1499
|
+
container
|
|
1500
|
+
], bandSx(band), band === 'dark');
|
|
1501
|
+
}
|
|
1502
|
+
// Editorial: display type across the page, the rest in a row under it, a wide photo below.
|
|
1503
|
+
const top = flow.filter((block)=>block.kind === 'eyebrow' || block.kind === 'heading');
|
|
1504
|
+
const rest = flow.filter((block)=>block.kind !== 'eyebrow' && block.kind !== 'heading');
|
|
1505
|
+
const lede = rest.filter((block)=>block.kind !== 'button');
|
|
1506
|
+
const actions = rest.filter((block)=>block.kind === 'button');
|
|
1507
|
+
const headId = compileFlow(scope, top, 'full');
|
|
1508
|
+
const ledeId = compileFlow(scope, lede, 'half');
|
|
1509
|
+
const actionsId = compileFlow(scope, actions, 'half');
|
|
1510
|
+
const under = ledeId && actionsId ? designRow(scope, [
|
|
1511
|
+
{
|
|
1512
|
+
id: ledeId,
|
|
1513
|
+
size: 'xs:12 md:7'
|
|
1514
|
+
},
|
|
1515
|
+
{
|
|
1516
|
+
id: actionsId,
|
|
1517
|
+
size: 'xs:12 md:5',
|
|
1518
|
+
sx: {
|
|
1519
|
+
display: 'flex',
|
|
1520
|
+
justifyContent: {
|
|
1521
|
+
xs: 'flex-start',
|
|
1522
|
+
md: 'flex-end'
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
], '4', 'flex-end') : ledeId != null ? ledeId : actionsId;
|
|
1527
|
+
const photo = designPicture(scope, picture, {
|
|
1528
|
+
aspectRatio: home ? {
|
|
1529
|
+
xs: '4 / 3',
|
|
1530
|
+
md: '21 / 9'
|
|
1531
|
+
} : {
|
|
1532
|
+
xs: '16 / 9',
|
|
1533
|
+
md: '3 / 1'
|
|
1534
|
+
},
|
|
1535
|
+
borderRadius: 2
|
|
1536
|
+
});
|
|
1537
|
+
const stack = tree.add('muiStack', {
|
|
1538
|
+
spacing: '6',
|
|
1539
|
+
useFlexGap: true
|
|
1540
|
+
}, null, [
|
|
1541
|
+
headId,
|
|
1542
|
+
under,
|
|
1543
|
+
photo
|
|
1544
|
+
], 'content');
|
|
1545
|
+
const container = tree.add('muiContainer', {
|
|
1546
|
+
maxWidth: 'lg'
|
|
1547
|
+
}, {
|
|
1548
|
+
pt: {
|
|
1549
|
+
xs: 8,
|
|
1550
|
+
md: 12
|
|
1551
|
+
},
|
|
1552
|
+
pb: {
|
|
1553
|
+
xs: 6,
|
|
1554
|
+
md: 10
|
|
1555
|
+
}
|
|
1556
|
+
}, [
|
|
1557
|
+
stack
|
|
1558
|
+
], 'container');
|
|
1559
|
+
return designedRoot(scope, [
|
|
1560
|
+
container
|
|
1561
|
+
], bandSx(band), band === 'dark');
|
|
1562
|
+
}
|
|
1563
|
+
/** Words over a full-bleed photo, on a scrim that keeps them readable, in the site's dark scheme. */ function cover(scope, flow, picture, minHeight) {
|
|
1564
|
+
const tree = scope.page.tree;
|
|
1565
|
+
// The photo dimmed over black: the scrim that keeps the words over it readable.
|
|
1566
|
+
const photo = designPicture(scope, picture, {
|
|
1567
|
+
position: 'absolute',
|
|
1568
|
+
top: 0,
|
|
1569
|
+
left: 0,
|
|
1570
|
+
width: '100%',
|
|
1571
|
+
height: '100%',
|
|
1572
|
+
bgcolor: 'common.black'
|
|
1573
|
+
}, 'coverPhoto', {
|
|
1574
|
+
opacity: 0.42
|
|
1575
|
+
});
|
|
1576
|
+
scope.overPhoto = true;
|
|
1577
|
+
const words = compileFlow(scope, flow, 'full');
|
|
1578
|
+
const measure = tree.add('muiBox', null, scope.centered ? {
|
|
1579
|
+
maxWidth: {
|
|
1580
|
+
xs: '100%',
|
|
1581
|
+
md: '75%'
|
|
1582
|
+
},
|
|
1583
|
+
mx: 'auto'
|
|
1584
|
+
} : {
|
|
1585
|
+
maxWidth: {
|
|
1586
|
+
xs: '100%',
|
|
1587
|
+
md: '62%'
|
|
1588
|
+
}
|
|
1589
|
+
}, [
|
|
1590
|
+
words
|
|
1591
|
+
], 'measure');
|
|
1592
|
+
const container = tree.add('muiContainer', {
|
|
1593
|
+
maxWidth: 'lg'
|
|
1594
|
+
}, {
|
|
1595
|
+
position: 'relative',
|
|
1596
|
+
zIndex: 1,
|
|
1597
|
+
py: {
|
|
1598
|
+
xs: 10,
|
|
1599
|
+
md: 14
|
|
1600
|
+
}
|
|
1601
|
+
}, [
|
|
1602
|
+
measure
|
|
1603
|
+
], 'container');
|
|
1604
|
+
return designedRoot(scope, [
|
|
1605
|
+
photo,
|
|
1606
|
+
container
|
|
1607
|
+
], {
|
|
1608
|
+
position: 'relative',
|
|
1609
|
+
overflow: 'hidden',
|
|
1610
|
+
display: 'flex',
|
|
1611
|
+
alignItems: {
|
|
1612
|
+
xs: 'flex-end',
|
|
1613
|
+
md: 'center'
|
|
1614
|
+
},
|
|
1615
|
+
minHeight
|
|
1616
|
+
}, true);
|
|
1617
|
+
}
|
|
1618
|
+
/** A closing section of words over a photo. */ function coverBand(scope, words) {
|
|
1619
|
+
scope.band = 'dark';
|
|
1620
|
+
scope.centered = true;
|
|
1621
|
+
scope.page.settled.push({
|
|
1622
|
+
at: scope.at,
|
|
1623
|
+
what: 'drawn over a photo'
|
|
1624
|
+
});
|
|
1625
|
+
return cover(scope, words, {
|
|
1626
|
+
alt: standInAlt(scope),
|
|
1627
|
+
given: false
|
|
1628
|
+
}, {
|
|
1629
|
+
xs: '56vh',
|
|
1630
|
+
md: '64vh'
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
/** A section of words beside a picture, the side turning section by section. */ function feature(scope, words) {
|
|
1634
|
+
const { page } = scope;
|
|
1635
|
+
const design = page.design;
|
|
1636
|
+
const left = design.choices.featureLeft !== (page.features % 2 === 1);
|
|
1637
|
+
page.features += 1;
|
|
1638
|
+
page.settled.push({
|
|
1639
|
+
at: scope.at,
|
|
1640
|
+
what: `set beside a picture on the ${left ? 'left' : 'right'}`
|
|
1641
|
+
});
|
|
1642
|
+
scope.centered = false;
|
|
1643
|
+
const flow = compileFlow(scope, words, 'half');
|
|
1644
|
+
const photo = designPicture(scope, {
|
|
1645
|
+
alt: standInAlt(scope),
|
|
1646
|
+
given: false
|
|
1647
|
+
}, {
|
|
1648
|
+
aspectRatio: {
|
|
1649
|
+
xs: '4 / 3',
|
|
1650
|
+
md: page.features === 1 ? '4 / 5' : '1 / 1'
|
|
1651
|
+
},
|
|
1652
|
+
borderRadius: 2
|
|
1653
|
+
});
|
|
1654
|
+
const row = designRow(scope, left ? [
|
|
1655
|
+
{
|
|
1656
|
+
id: photo,
|
|
1657
|
+
size: 'xs:12 md:6'
|
|
1658
|
+
},
|
|
1659
|
+
{
|
|
1660
|
+
id: flow,
|
|
1661
|
+
size: 'xs:12 md:6'
|
|
1662
|
+
}
|
|
1663
|
+
] : [
|
|
1664
|
+
{
|
|
1665
|
+
id: flow,
|
|
1666
|
+
size: 'xs:12 md:6'
|
|
1667
|
+
},
|
|
1668
|
+
{
|
|
1669
|
+
id: photo,
|
|
1670
|
+
size: 'xs:12 md:6'
|
|
1671
|
+
}
|
|
1672
|
+
], '8');
|
|
1673
|
+
const container = page.tree.add('muiContainer', {
|
|
1674
|
+
maxWidth: 'lg'
|
|
1675
|
+
}, {
|
|
1676
|
+
py: _extends({}, SECTION_PADDING)
|
|
1677
|
+
}, [
|
|
1678
|
+
row
|
|
1679
|
+
], 'container');
|
|
1680
|
+
return designedRoot(scope, [
|
|
1681
|
+
container
|
|
1682
|
+
], bandSx(scope.band), scope.band === 'dark');
|
|
1683
|
+
}
|
|
1684
|
+
/** A heading beside its items: the words in a narrow column, the items ruled in the wide one. */ function splitSection(scope, head, group, tail) {
|
|
1685
|
+
const { page } = scope;
|
|
1686
|
+
scope.centered = false;
|
|
1687
|
+
scope.groupStyle = 'ruled';
|
|
1688
|
+
page.splitAt = scope.index;
|
|
1689
|
+
page.settled.push({
|
|
1690
|
+
at: scope.at,
|
|
1691
|
+
what: 'the heading set beside its items'
|
|
1692
|
+
});
|
|
1693
|
+
const words = compileFlow(scope, [
|
|
1694
|
+
...head,
|
|
1695
|
+
...tail
|
|
1696
|
+
], 'half');
|
|
1697
|
+
const items = compileFlow(scope, [
|
|
1698
|
+
group
|
|
1699
|
+
], 'half');
|
|
1700
|
+
if (!words || !items) {
|
|
1701
|
+
const flow = [
|
|
1702
|
+
words,
|
|
1703
|
+
items
|
|
1704
|
+
].filter((id)=>!!id);
|
|
1705
|
+
const container = page.tree.add('muiContainer', {
|
|
1706
|
+
maxWidth: 'lg'
|
|
1707
|
+
}, {
|
|
1708
|
+
py: _extends({}, SECTION_PADDING)
|
|
1709
|
+
}, flow, 'container');
|
|
1710
|
+
return designedRoot(scope, [
|
|
1711
|
+
container
|
|
1712
|
+
], bandSx(scope.band), scope.band === 'dark');
|
|
1713
|
+
}
|
|
1714
|
+
const row = designRow(scope, [
|
|
1715
|
+
{
|
|
1716
|
+
id: words,
|
|
1717
|
+
size: 'xs:12 md:5'
|
|
1718
|
+
},
|
|
1719
|
+
{
|
|
1720
|
+
id: items,
|
|
1721
|
+
size: 'xs:12 md:7'
|
|
1722
|
+
}
|
|
1723
|
+
], '8', 'flex-start');
|
|
1724
|
+
const container = page.tree.add('muiContainer', {
|
|
1725
|
+
maxWidth: 'lg'
|
|
1726
|
+
}, {
|
|
1727
|
+
py: _extends({}, SECTION_PADDING)
|
|
1728
|
+
}, [
|
|
1729
|
+
row
|
|
1730
|
+
], 'container');
|
|
1731
|
+
return designedRoot(scope, [
|
|
1732
|
+
container
|
|
1733
|
+
], bandSx(scope.band), scope.band === 'dark');
|
|
1734
|
+
}
|
|
1735
|
+
/**
|
|
1736
|
+
* Items under rules, one a line, each opening under a thin rule in the
|
|
1737
|
+
* text's own color. One style key an element, so a long list repeats no
|
|
1738
|
+
* multi-key inline style (rule 16); and no Stack `divider`, which a
|
|
1739
|
+
* published page's renderer hands a Stack as one child and so never draws.
|
|
1740
|
+
*/ function ruledList(scope, ids, role) {
|
|
1741
|
+
const tree = scope.page.tree;
|
|
1742
|
+
return tree.add('muiStack', {
|
|
1743
|
+
spacing: '2'
|
|
1744
|
+
}, null, ids.map((id)=>tree.add('muiBox', null, {
|
|
1745
|
+
borderTop: 1
|
|
1746
|
+
}, [
|
|
1747
|
+
tree.add('muiBox', null, {
|
|
1748
|
+
pt: 2
|
|
1749
|
+
}, [
|
|
1750
|
+
id
|
|
1751
|
+
], 'ruledWords')
|
|
1752
|
+
], 'ruledLine')), role);
|
|
1753
|
+
}
|
|
1754
|
+
/** Numbered items as a ruled list: each number beside its title and words. */ function timeline(scope, items) {
|
|
1755
|
+
const tree = scope.page.tree;
|
|
1756
|
+
const facts = scope.page.targets.facts;
|
|
1757
|
+
const rows = items.map((item, position)=>tree.add('muiStack', {
|
|
1758
|
+
direction: 'row',
|
|
1759
|
+
spacing: '3',
|
|
1760
|
+
alignItems: 'baseline'
|
|
1761
|
+
}, null, [
|
|
1762
|
+
// The numbers keep one column, so every title starts at the same line.
|
|
1763
|
+
tree.add('muiBox', null, {
|
|
1764
|
+
flex: '0 0 3.5rem'
|
|
1765
|
+
}, [
|
|
1766
|
+
tree.add('muiTypography', {
|
|
1767
|
+
children: String(position + 1).padStart(2, '0'),
|
|
1768
|
+
variant: 'h4',
|
|
1769
|
+
component: 'p'
|
|
1770
|
+
}, accent(scope), null, 'number')
|
|
1771
|
+
], 'numberColumn'),
|
|
1772
|
+
tree.add('muiStack', {
|
|
1773
|
+
spacing: '1'
|
|
1774
|
+
}, null, [
|
|
1775
|
+
item.title.trim() ? tree.add('muiTypography', {
|
|
1776
|
+
children: aiLayoutWords(item.title, 'itemTitle', facts),
|
|
1777
|
+
variant: 'h5',
|
|
1778
|
+
component: itemElement(scope)
|
|
1779
|
+
}, null, null, 'title') : null,
|
|
1780
|
+
item.text.trim() ? tree.add('muiTypography', {
|
|
1781
|
+
children: aiLayoutWords(item.text, 'itemText', facts),
|
|
1782
|
+
variant: 'body1'
|
|
1783
|
+
}, muted(scope), null, 'text') : null
|
|
1784
|
+
], 'stepWords')
|
|
1785
|
+
], 'step'));
|
|
1786
|
+
return ruledList(scope, noted(scope, rows), 'timeline');
|
|
1787
|
+
}
|
|
1788
|
+
/** A group drawn the design's way; `null` to draw it as the theme's cards. */ function designedGroup(scope, variant, items, room) {
|
|
1789
|
+
const { page } = scope;
|
|
1790
|
+
const tree = page.tree;
|
|
1791
|
+
const facts = page.targets.facts;
|
|
1792
|
+
const title = (item, type = 'h5')=>item.title.trim() ? tree.add('muiTypography', {
|
|
1793
|
+
children: aiLayoutWords(item.title, 'itemTitle', facts),
|
|
1794
|
+
variant: type,
|
|
1795
|
+
component: itemElement(scope)
|
|
1796
|
+
}, null, null, 'title') : null;
|
|
1797
|
+
const words = (item, type = 'body1')=>item.text.trim() ? tree.add('muiTypography', {
|
|
1798
|
+
children: aiLayoutWords(item.text, 'itemText', facts),
|
|
1799
|
+
variant: type
|
|
1800
|
+
}, muted(scope), null, 'text') : null;
|
|
1801
|
+
if (variant === 'cards') return null;
|
|
1802
|
+
const pictured = variant === 'pictures' || variant === 'articles';
|
|
1803
|
+
if (variant === 'ruled' || pictured && (room !== 'full' || picturesLeft(page) < items.length)) {
|
|
1804
|
+
const perRow = across(items.length, room, 'cards');
|
|
1805
|
+
if (perRow <= 1) {
|
|
1806
|
+
// Stacked, the rules run between the items.
|
|
1807
|
+
const ids = items.map((item)=>tree.add('muiStack', {
|
|
1808
|
+
spacing: '1'
|
|
1809
|
+
}, null, [
|
|
1810
|
+
title(item),
|
|
1811
|
+
words(item)
|
|
1812
|
+
], 'ruled'));
|
|
1813
|
+
return ruledList(scope, noted(scope, ids), 'ruledItems');
|
|
1814
|
+
}
|
|
1815
|
+
// Side by side, each column opens under a rule in the text's own color.
|
|
1816
|
+
const ids = items.map((item)=>tree.add('muiBox', null, {
|
|
1817
|
+
borderTop: 1
|
|
1818
|
+
}, [
|
|
1819
|
+
tree.add('muiStack', {
|
|
1820
|
+
spacing: '1'
|
|
1821
|
+
}, {
|
|
1822
|
+
pt: 2.5
|
|
1823
|
+
}, [
|
|
1824
|
+
title(item),
|
|
1825
|
+
words(item)
|
|
1826
|
+
], 'ruledWords')
|
|
1827
|
+
], 'ruled'));
|
|
1828
|
+
return layOut(scope, noted(scope, ids), perRow, '5', 'ruledItems');
|
|
1829
|
+
}
|
|
1830
|
+
if (variant === 'menu') {
|
|
1831
|
+
const ids = items.map((item)=>tree.add('muiStack', {
|
|
1832
|
+
spacing: '0.5'
|
|
1833
|
+
}, null, [
|
|
1834
|
+
title(item, 'h6'),
|
|
1835
|
+
words(item, 'body2')
|
|
1836
|
+
], 'dish'));
|
|
1837
|
+
noted(scope, ids);
|
|
1838
|
+
// Two columns of lines under rules, the first half and the second.
|
|
1839
|
+
const half = room === 'full' && ids.length >= 4 ? Math.ceil(ids.length / 2) : ids.length;
|
|
1840
|
+
const lists = [
|
|
1841
|
+
ids.slice(0, half),
|
|
1842
|
+
ids.slice(half)
|
|
1843
|
+
].filter((list)=>list.length).map((list)=>ruledList(scope, list, 'menu'));
|
|
1844
|
+
if (lists.length === 1) return lists[0];
|
|
1845
|
+
// On a phone the two columns read as one list, the second opening under
|
|
1846
|
+
// its own rule a line's gap below the first; side by side, a gutter.
|
|
1847
|
+
const [first, second] = lists;
|
|
1848
|
+
return tree.add('muiGrid', {
|
|
1849
|
+
container: true,
|
|
1850
|
+
rowSpacing: '2',
|
|
1851
|
+
columnSpacing: '8'
|
|
1852
|
+
}, {
|
|
1853
|
+
alignItems: 'flex-start'
|
|
1854
|
+
}, [
|
|
1855
|
+
tree.add('muiGrid', {
|
|
1856
|
+
size: 'xs:12 md:6'
|
|
1857
|
+
}, null, [
|
|
1858
|
+
first
|
|
1859
|
+
], 'column'),
|
|
1860
|
+
tree.add('muiGrid', {
|
|
1861
|
+
size: 'xs:12 md:6'
|
|
1862
|
+
}, null, [
|
|
1863
|
+
second
|
|
1864
|
+
], 'column')
|
|
1865
|
+
], 'menuRow');
|
|
1866
|
+
}
|
|
1867
|
+
// Pictures over each item's title and words.
|
|
1868
|
+
const design = page.design;
|
|
1869
|
+
const mosaic = variant === 'pictures' && design.choices.pictures === 'mosaic' && items.length >= 2;
|
|
1870
|
+
const portrait = design.input.kind === 'photography';
|
|
1871
|
+
const perRow = items.length === 4 || items.length === 2 ? 2 : Math.min(3, items.length);
|
|
1872
|
+
page.settled.push({
|
|
1873
|
+
at: scope.at,
|
|
1874
|
+
what: `${items.length} items drawn as ${mosaic ? 'a mosaic of pictures' : variant}`
|
|
1875
|
+
});
|
|
1876
|
+
const cells = items.map((item, position)=>{
|
|
1877
|
+
// A mosaic's rows turn wide-narrow, narrow-wide; an odd one out spans the row.
|
|
1878
|
+
const row = Math.floor(position / 2);
|
|
1879
|
+
const lone = mosaic && position === items.length - 1 && items.length % 2 === 1;
|
|
1880
|
+
const wide = mosaic && !lone && position % 2 === row % 2;
|
|
1881
|
+
const span = !mosaic ? 12 / perRow : lone ? 12 : wide ? 7 : 5;
|
|
1882
|
+
const aspect = !mosaic ? variant === 'articles' ? '3 / 2' : portrait ? '4 / 5' : '4 / 3' : lone ? '21 / 9' : wide ? '4 / 3' : '4 / 5';
|
|
1883
|
+
// The picture is its own frame: its shape its one style, so a grid of them repeats no inline style.
|
|
1884
|
+
const photo = designImage(scope, {
|
|
1885
|
+
alt: standInAlt(scope, item.title || item.text),
|
|
1886
|
+
given: false
|
|
1887
|
+
}, {
|
|
1888
|
+
width: '100%'
|
|
1889
|
+
}, {
|
|
1890
|
+
aspectRatio: {
|
|
1891
|
+
xs: '4 / 3',
|
|
1892
|
+
md: aspect
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
const id = tree.add('muiStack', {
|
|
1896
|
+
spacing: '1.5'
|
|
1897
|
+
}, null, [
|
|
1898
|
+
photo,
|
|
1899
|
+
title(item, variant === 'articles' ? 'h5' : 'h6'),
|
|
1900
|
+
words(item, 'body2')
|
|
1901
|
+
], variant === 'articles' ? 'article' : 'work');
|
|
1902
|
+
return {
|
|
1903
|
+
id,
|
|
1904
|
+
size: span === 12 ? 'xs:12 sm:12' : `xs:12 ${span === 6 ? 'sm' : 'md'}:${span}`
|
|
1905
|
+
};
|
|
1906
|
+
});
|
|
1907
|
+
noted(scope, cells.map((cell)=>cell.id));
|
|
1908
|
+
return tree.add('muiGrid', {
|
|
1909
|
+
container: true,
|
|
1910
|
+
spacing: mosaic ? '5' : '4'
|
|
1911
|
+
}, {
|
|
1912
|
+
alignItems: 'flex-start'
|
|
1913
|
+
}, cells.map((cell)=>tree.add('muiGrid', {
|
|
1914
|
+
size: cell.size
|
|
1915
|
+
}, null, [
|
|
1916
|
+
cell.id
|
|
1917
|
+
], 'cell')), variant);
|
|
1918
|
+
}
|
|
1233
1919
|
/** The id the compiled page's root is stored under. */ export const AI_LAYOUT_PAGE_ROOT_ID = CANVAS_ROOT_ELEMENT_ID;
|
|
1234
1920
|
|
|
1235
1921
|
//# sourceMappingURL=ai-layout-compiler.js.map
|