@aglyn/plugins-ai 1.0.0-beta.233 → 1.0.0-beta.235
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/activity/ai-activity-actions.d.ts +25 -0
- package/src/lib/activity/ai-activity-actions.js +85 -4
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- package/src/lib/components/ai-brief-dialog.component.js +46 -2
- package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
- package/src/lib/components/ai-campaign-create.component.js +1 -1
- package/src/lib/components/ai-campaign-create.component.js.map +1 -1
- package/src/lib/components/ai-credits-card.component.js +3 -3
- package/src/lib/components/ai-credits-card.component.js.map +1 -1
- package/src/lib/components/ai-crm-email-draft.component.js +1 -1
- package/src/lib/components/ai-crm-email-draft.component.js.map +1 -1
- package/src/lib/components/ai-crm-import-mapping.component.js +1 -1
- package/src/lib/components/ai-crm-import-mapping.component.js.map +1 -1
- package/src/lib/components/ai-crm-record-card.component.js +1 -1
- package/src/lib/components/ai-crm-record-card.component.js.map +1 -1
- package/src/lib/components/ai-describe-automation.component.js +4 -2
- package/src/lib/components/ai-describe-automation.component.js.map +1 -1
- package/src/lib/components/ai-describe-org-automation.component.js +1 -1
- package/src/lib/components/ai-describe-org-automation.component.js.map +1 -1
- package/src/lib/components/ai-experiment-cards.component.js +2 -2
- package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
- package/src/lib/components/ai-explain-automation.component.js +1 -1
- package/src/lib/components/ai-explain-automation.component.js.map +1 -1
- package/src/lib/components/ai-insight-card.component.js +3 -1
- package/src/lib/components/ai-insight-card.component.js.map +1 -1
- 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-jobs-list-page.component.d.ts +6 -1
- package/src/lib/components/ai-jobs-list-page.component.js +15 -2
- package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
- package/src/lib/components/ai-logic.component.js +5 -3
- package/src/lib/components/ai-logic.component.js.map +1 -1
- package/src/lib/components/ai-media-create.component.js +88 -16
- package/src/lib/components/ai-media-create.component.js.map +1 -1
- package/src/lib/components/ai-model-selector.component.js +8 -0
- package/src/lib/components/ai-model-selector.component.js.map +1 -1
- package/src/lib/components/ai-overlay-cards.component.js +2 -2
- package/src/lib/components/ai-overlay-cards.component.js.map +1 -1
- package/src/lib/components/ai-product-copy-card.component.js +2 -1
- package/src/lib/components/ai-product-copy-card.component.js.map +1 -1
- package/src/lib/components/ai-products-hub-card.component.js +2 -1
- package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
- package/src/lib/components/ai-revise-automation.component.js +1 -1
- package/src/lib/components/ai-revise-automation.component.js.map +1 -1
- package/src/lib/components/ai-seo-fields-card.component.js +7 -3
- package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
- package/src/lib/components/ai-site-batch-card.component.js +7 -4
- package/src/lib/components/ai-site-batch-card.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +48 -6
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-seo-start-card.component.js +7 -4
- package/src/lib/components/ai-site-seo-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.js +152 -36
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-theme-proposal-card.component.js +1 -0
- package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
- package/src/lib/components/ai-upsell-dialog.component.js +17 -3
- package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
- package/src/lib/components/ai-usage-strip.component.js +13 -2
- package/src/lib/components/ai-usage-strip.component.js.map +1 -1
- package/src/lib/components/assist-build-card.component.js +20 -3
- package/src/lib/components/assist-build-card.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.js +7 -1
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/billing-ai-allotments.component.js +2 -2
- package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
- package/src/lib/components/billing-ai-top-users.component.js +1 -0
- package/src/lib/components/billing-ai-top-users.component.js.map +1 -1
- package/src/lib/components/billing-assist-overage-card.component.js +2 -2
- package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
- package/src/lib/components/host-ai-allotments.component.js +2 -2
- package/src/lib/components/host-ai-allotments.component.js.map +1 -1
- package/src/lib/components/member-ai-allotment-card.component.js +2 -2
- package/src/lib/components/member-ai-allotment-card.component.js.map +1 -1
- package/src/lib/components/staff-org-ai-card.component.js +1 -0
- package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
- package/src/lib/components/staff-org-ai-conversations.component.d.ts +9 -3
- package/src/lib/components/staff-org-ai-conversations.component.js +174 -83
- package/src/lib/components/staff-org-ai-conversations.component.js.map +1 -1
- package/src/lib/components/staff-user-ai-usage-card.component.js +2 -1
- package/src/lib/components/staff-user-ai-usage-card.component.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 +6 -1
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-site-pages.d.ts +14 -0
- package/src/lib/jobs/ai-job-layout-site-pages.js +43 -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 +26 -1
- package/src/lib/jobs/ai-job-page-language.js +75 -13
- 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 +32 -7
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +34 -0
- package/src/lib/jobs/ai-job-plan-step.js +106 -14
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-content.d.ts +81 -13
- package/src/lib/jobs/ai-job-site-content.js +210 -43
- package/src/lib/jobs/ai-job-site-content.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +19 -0
- package/src/lib/jobs/ai-job-site-step.js +152 -51
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +8 -4
- package/src/lib/jobs/ai-jobs.js +19 -2
- 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 +37 -0
- package/src/lib/layout-language/ai-layout-compiler.js +1003 -19
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +114 -0
- package/src/lib/layout-language/ai-layout-design.js +209 -0
- package/src/lib/layout-language/ai-layout-design.js.map +1 -0
- package/src/lib/layout-language/ai-layout-frame.d.ts +12 -0
- package/src/lib/layout-language/ai-layout-frame.js +33 -8
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-gaps.js +18 -2
- package/src/lib/layout-language/ai-layout-gaps.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 +36 -0
- package/src/lib/layout-language/ai-layout-links.js +26 -2
- package/src/lib/layout-language/ai-layout-links.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +125 -0
- package/src/lib/layout-language/ai-layout-listings.js +187 -0
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -0
- 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 +7 -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 +104 -15
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +236 -24
- package/src/lib/model/ai-site-job.js +269 -22
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.d.ts +30 -8
- package/src/lib/model/ai-site-kinds.js +735 -116
- 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/model/ai-site-start-seo.d.ts +30 -0
- package/src/lib/model/ai-site-start-seo.js +132 -11
- package/src/lib/model/ai-site-start-seo.js.map +1 -1
- package/src/lib/model/ai-site-start.d.ts +2 -2
- package/src/lib/model/ai-site-start.js +3 -3
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/plugin.js +15 -3
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +32 -1
- package/src/lib/runtime/ai-doctrine-validators.js +227 -4
- 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 +31 -5
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/server/ai-admin-conversations.d.ts +9 -0
- package/src/lib/server/ai-admin-conversations.js +151 -9
- package/src/lib/server/ai-admin-conversations.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
- package/src/lib/usage/staff-org-ai-conversations.d.ts +23 -0
- package/src/lib/usage/staff-org-ai-conversations.js +45 -0
- package/src/lib/usage/staff-org-ai-conversations.js.map +1 -1
|
@@ -22,8 +22,18 @@ 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 {
|
|
25
|
+
import { aiLayoutDesignChoices, aiLayoutGroupVariant } from "./ai-layout-design.js";
|
|
26
|
+
import { AI_LAYOUT_FEATURED_RECORDS, AI_LAYOUT_LISTING_ELEMENTS, aiLayoutListingAt } from "./ai-layout-listings.js";
|
|
27
|
+
import { aiLayoutRenamedLabel, aiLayoutResolveLink } from "./ai-layout-links.js";
|
|
26
28
|
import { AI_LAYOUT_FRAMES, AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
29
|
+
/**
|
|
30
|
+
* What a section is called to a screen reader: its plan name, with any note
|
|
31
|
+
* the plan left in brackets taken out. A live blog plan (2026-10-09) named a
|
|
32
|
+
* section "reader notes and kind words [to be added by owner]"; carried into
|
|
33
|
+
* the label it read as a gap, and the page's gap pass took the section out.
|
|
34
|
+
*/ function sectionLabel(name, index) {
|
|
35
|
+
return aiLayoutFitText(name.replace(/\[[^\]]*\]/g, ' ').replace(/\s+/g, ' ').trim(), 'note') || `Section ${index + 1}`;
|
|
36
|
+
}
|
|
27
37
|
/** A section root's id where the caller gives none. */ function sectionIdOf(index) {
|
|
28
38
|
return `section-${index + 1}`;
|
|
29
39
|
}
|
|
@@ -69,7 +79,15 @@ const componentOf = (targets, id)=>{
|
|
|
69
79
|
formSection: formSectionOf(sections, plan, targets),
|
|
70
80
|
pageIcon: pageIconOf(sections),
|
|
71
81
|
formsPlaced: new Set(),
|
|
72
|
-
itemIds: plan.sections.map(()=>[])
|
|
82
|
+
itemIds: plan.sections.map(()=>[]),
|
|
83
|
+
design: options.design ? {
|
|
84
|
+
input: options.design,
|
|
85
|
+
choices: aiLayoutDesignChoices(options.design)
|
|
86
|
+
} : null,
|
|
87
|
+
pictures: 0,
|
|
88
|
+
features: 0,
|
|
89
|
+
splitAt: -2,
|
|
90
|
+
quotesOnly: []
|
|
73
91
|
};
|
|
74
92
|
const roots = plan.sections.map((_, index)=>{
|
|
75
93
|
var _sections_index;
|
|
@@ -87,7 +105,8 @@ const componentOf = (targets, id)=>{
|
|
|
87
105
|
sectionRoots: roots,
|
|
88
106
|
scrollTo: page.scrollTo,
|
|
89
107
|
settled: page.settled,
|
|
90
|
-
itemIds: page.itemIds
|
|
108
|
+
itemIds: page.itemIds,
|
|
109
|
+
quotesOnly: page.quotesOnly
|
|
91
110
|
};
|
|
92
111
|
}
|
|
93
112
|
/** The first icon the design names anywhere, else a sparkle: what an empty picture shows. */ function pageIconOf(sections) {
|
|
@@ -106,8 +125,8 @@ const componentOf = (targets, id)=>{
|
|
|
106
125
|
}
|
|
107
126
|
// ── A section ─────────────────────────────────────────────────────────────
|
|
108
127
|
function compileSection(page, raw, index) {
|
|
109
|
-
var _raw_band, _ref;
|
|
110
|
-
var _placedHere_, _page_plan_sections_index_name,
|
|
128
|
+
var _raw_band, _ref, _page_targets_listings, _ref1;
|
|
129
|
+
var _raw_blocks_find, _page_plan_sections_index, _placedHere_, _page_plan_sections_index_name, _page_plan_sections_index1, _page_options_sectionIds;
|
|
111
130
|
const at = `sections[${index}]`;
|
|
112
131
|
const band = settleBand(page, (_raw_band = raw.band) != null ? _raw_band : 'plain', at);
|
|
113
132
|
const scope = {
|
|
@@ -123,7 +142,15 @@ function compileSection(page, raw, index) {
|
|
|
123
142
|
sections: page.plan.sections.map((section)=>section.name),
|
|
124
143
|
from: index,
|
|
125
144
|
formSection: page.formSection
|
|
126
|
-
}
|
|
145
|
+
},
|
|
146
|
+
heading: (_raw_blocks_find = raw.blocks.find((block)=>block.kind === 'heading')) == null ? void 0 : _raw_blocks_find.text,
|
|
147
|
+
words: [
|
|
148
|
+
(_ref = (_page_plan_sections_index = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index.name) != null ? _ref : '',
|
|
149
|
+
...raw.blocks.filter((block)=>block.kind === 'heading' || block.kind === 'eyebrow').map((block)=>{
|
|
150
|
+
var _block_text;
|
|
151
|
+
return (_block_text = block.text) != null ? _block_text : '';
|
|
152
|
+
})
|
|
153
|
+
].join(' ')
|
|
127
154
|
};
|
|
128
155
|
// A quote is a gap the owner fills, and a published page shows no gap (AGL-3660).
|
|
129
156
|
const blocks = placePlanned(scope, raw).filter((block)=>{
|
|
@@ -134,6 +161,20 @@ function compileSection(page, raw, index) {
|
|
|
134
161
|
});
|
|
135
162
|
return false;
|
|
136
163
|
});
|
|
164
|
+
// A section whose only items were those quotes has none left to show, and is
|
|
165
|
+
// not asked for them again: no answer can give words the brief did not (AGL-3676).
|
|
166
|
+
if (raw.blocks.some((block)=>block.kind === 'quotes') && !blocks.some((block)=>AI_LAYOUT_GROUP_KINDS.has(block.kind) || block.kind === 'component')) {
|
|
167
|
+
page.quotesOnly.push(index);
|
|
168
|
+
}
|
|
169
|
+
// A section the site's records fill — its catalog, its blog — shows them
|
|
170
|
+
// through the element that keeps them, around the words the design gave it (AGL-3676).
|
|
171
|
+
const listed = aiLayoutListingAt((_page_targets_listings = page.targets.listings) != null ? _page_targets_listings : [], page.targets.pageId, index);
|
|
172
|
+
if (listed) return listingSection(scope, blocks, listed);
|
|
173
|
+
// The site's design draws the sections it has an arrangement for (AGL-3660).
|
|
174
|
+
if (page.design) {
|
|
175
|
+
const designed = designSection(scope, raw, blocks);
|
|
176
|
+
if (designed) return designed;
|
|
177
|
+
}
|
|
137
178
|
const cols = raw.cols && raw.cols.length >= 2 ? raw.cols : null;
|
|
138
179
|
// Above the row, the row's columns, and below it.
|
|
139
180
|
const head = [];
|
|
@@ -280,13 +321,13 @@ function compileSection(page, raw, index) {
|
|
|
280
321
|
}
|
|
281
322
|
}
|
|
282
323
|
if (!parts.length) {
|
|
283
|
-
var
|
|
324
|
+
var _page_plan_sections_index2;
|
|
284
325
|
// Nothing the design gave this section could be shown: it keeps its
|
|
285
326
|
// place on the page under the name its plan gives it.
|
|
286
327
|
const fallback = compileFlow(scope, [
|
|
287
328
|
{
|
|
288
329
|
kind: 'heading',
|
|
289
|
-
text: ((
|
|
330
|
+
text: ((_page_plan_sections_index2 = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index2.name) || page.plan.title
|
|
290
331
|
}
|
|
291
332
|
], 'full');
|
|
292
333
|
if (fallback) parts.push(fallback);
|
|
@@ -308,15 +349,15 @@ function compileSection(page, raw, index) {
|
|
|
308
349
|
}, [
|
|
309
350
|
content
|
|
310
351
|
], 'container');
|
|
311
|
-
const name = ((
|
|
352
|
+
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
353
|
return tree.add('section', _extends({
|
|
313
354
|
element: 'section',
|
|
314
|
-
ariaLabel:
|
|
355
|
+
ariaLabel: sectionLabel(name, index)
|
|
315
356
|
}, band === 'dark' ? {
|
|
316
357
|
colorScheme: 'dark'
|
|
317
358
|
} : {}), bandSx(band), [
|
|
318
359
|
container
|
|
319
|
-
], 'section', (
|
|
360
|
+
], 'section', (_ref1 = (_page_options_sectionIds = page.options.sectionIds) == null ? void 0 : _page_options_sectionIds[index]) != null ? _ref1 : sectionIdOf(index));
|
|
320
361
|
}
|
|
321
362
|
/**
|
|
322
363
|
* A component block's prop values as a card item: its title-like prop as the
|
|
@@ -650,12 +691,12 @@ function compileBlock(scope, block, room) {
|
|
|
650
691
|
}
|
|
651
692
|
}
|
|
652
693
|
/** Secondary words' color: muted text, or the band's own on a brand band. */ function muted(scope) {
|
|
653
|
-
return scope.band === 'brand' ? null : {
|
|
694
|
+
return scope.band === 'brand' || scope.overPhoto ? null : {
|
|
654
695
|
color: 'text.secondary'
|
|
655
696
|
};
|
|
656
697
|
}
|
|
657
698
|
/** 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 : {
|
|
699
|
+
return scope.band === 'brand' || scope.overPhoto ? null : {
|
|
659
700
|
color: 'primary.main'
|
|
660
701
|
};
|
|
661
702
|
}
|
|
@@ -702,18 +743,25 @@ function words(scope, block, place, variant, props, sx) {
|
|
|
702
743
|
}
|
|
703
744
|
function compileButton(scope, block) {
|
|
704
745
|
var _block_style;
|
|
705
|
-
const
|
|
706
|
-
if (!
|
|
707
|
-
const destination = aiLayoutResolveLink(block.to,
|
|
746
|
+
const asked = aiLayoutFitText(block.text, 'label');
|
|
747
|
+
if (!asked) return null;
|
|
748
|
+
const destination = aiLayoutResolveLink(block.to, asked, scope.link, scope.page.targets);
|
|
708
749
|
if (!destination) {
|
|
709
750
|
scope.page.settled.push({
|
|
710
751
|
at: scope.at,
|
|
711
|
-
what: `the button "${
|
|
752
|
+
what: `the button "${asked}" has nowhere to go; left out`
|
|
712
753
|
});
|
|
713
754
|
return null;
|
|
714
755
|
}
|
|
756
|
+
// A button to a page merged into the blog names the blog (AGL-3676).
|
|
757
|
+
const label = aiLayoutRenamedLabel(asked, destination);
|
|
758
|
+
if (label !== asked) scope.page.settled.push({
|
|
759
|
+
at: scope.at,
|
|
760
|
+
what: `the button "${asked}" named for the blog: "${label}"`
|
|
761
|
+
});
|
|
715
762
|
const style = (_block_style = block.style) != null ? _block_style : 'primary';
|
|
716
|
-
|
|
763
|
+
// Over a photo, a quiet or outlined button takes the words' own color, as on a brand band.
|
|
764
|
+
const onBrand = scope.band === 'brand' || !!scope.overPhoto && style !== 'primary';
|
|
717
765
|
const look = style === 'quiet' ? {
|
|
718
766
|
variant: 'text',
|
|
719
767
|
color: onBrand ? 'inherit' : 'primary'
|
|
@@ -760,6 +808,9 @@ export function destinationProps(destination) {
|
|
|
760
808
|
href: destination.href,
|
|
761
809
|
target: '_blank'
|
|
762
810
|
};
|
|
811
|
+
if (destination.kind === 'path') return {
|
|
812
|
+
href: destination.href
|
|
813
|
+
};
|
|
763
814
|
return {};
|
|
764
815
|
}
|
|
765
816
|
/**
|
|
@@ -968,7 +1019,24 @@ function group(scope, block, room) {
|
|
|
968
1019
|
const perRow = across(items.length, room, block.kind);
|
|
969
1020
|
const placed = componentOf(scope.page.targets, block.to);
|
|
970
1021
|
if (placed) return instances(scope, placed, items, perRow);
|
|
971
|
-
|
|
1022
|
+
const design = scope.page.design;
|
|
1023
|
+
if (rule1(scope)) {
|
|
1024
|
+
var _scope_words;
|
|
1025
|
+
// Picture cards the design draws are the compiler's, not a block typed out
|
|
1026
|
+
// by hand (`repeatsCompiled`, AGL-3660); every other repeat stays compact.
|
|
1027
|
+
const variant = design && block.kind === 'cards' && block.style !== 'quiet' ? aiLayoutGroupVariant(design.input, design.choices, (_scope_words = scope.words) != null ? _scope_words : '') : null;
|
|
1028
|
+
const pictured = (variant === 'pictures' || variant === 'articles') && room === 'full' && picturesLeft(scope.page) >= items.length;
|
|
1029
|
+
return pictured && designedGroup(scope, variant, items, room) || compactGroup(scope, block, items, perRow);
|
|
1030
|
+
}
|
|
1031
|
+
if (design && block.kind === 'steps' && (design.choices.steps === 'timeline' || room !== 'full')) {
|
|
1032
|
+
return timeline(scope, items);
|
|
1033
|
+
}
|
|
1034
|
+
if (design && block.kind === 'cards' && block.style !== 'quiet') {
|
|
1035
|
+
var _scope_groupStyle, _scope_words1;
|
|
1036
|
+
const variant = (_scope_groupStyle = scope.groupStyle) != null ? _scope_groupStyle : aiLayoutGroupVariant(design.input, design.choices, (_scope_words1 = scope.words) != null ? _scope_words1 : '');
|
|
1037
|
+
const drawn = designedGroup(scope, variant, items, room);
|
|
1038
|
+
if (drawn) return drawn;
|
|
1039
|
+
}
|
|
972
1040
|
switch(block.kind){
|
|
973
1041
|
case 'steps':
|
|
974
1042
|
return layOut(scope, noted(scope, items.map((item, position)=>step(scope, item, position))), perRow, '4', 'steps');
|
|
@@ -1230,6 +1298,922 @@ function instances(scope, placed, items, perRow) {
|
|
|
1230
1298
|
spacing: '1.5'
|
|
1231
1299
|
}, null, noted(scope, panels), 'faq');
|
|
1232
1300
|
}
|
|
1301
|
+
// ── The designer layer (AGL-3660) ─────────────────────────────────────────
|
|
1302
|
+
//
|
|
1303
|
+
// What `ai-layout-design.ts` chose for the site, drawn: the hero, a section
|
|
1304
|
+
// of words beside a picture, a closing band over a photo, a heading beside
|
|
1305
|
+
// its items, and groups drawn as pictures, articles, a menu or open ruled
|
|
1306
|
+
// columns. Every variant is built from the same palette elements and theme
|
|
1307
|
+
// tokens as the rest of the compiler, so the doctrine holds by construction.
|
|
1308
|
+
/** The most pictures a designed page carries, the model's and the stand-ins together. */ export const AI_LAYOUT_MAX_DESIGN_PICTURES = 8;
|
|
1309
|
+
/** The block kinds a section of words holds. */ const WORD_KINDS = new Set([
|
|
1310
|
+
'eyebrow',
|
|
1311
|
+
'heading',
|
|
1312
|
+
'lede',
|
|
1313
|
+
'text',
|
|
1314
|
+
'note',
|
|
1315
|
+
'button'
|
|
1316
|
+
]);
|
|
1317
|
+
/** How many more pictures the page has room for. */ function picturesLeft(page) {
|
|
1318
|
+
return AI_LAYOUT_MAX_DESIGN_PICTURES - page.images - page.pictures;
|
|
1319
|
+
}
|
|
1320
|
+
/** Whether a heading block has words left once fitted: one with none is no heading. */ function speaksHeading(scope, block) {
|
|
1321
|
+
return block.kind === 'heading' && !!aiLayoutWords(block.text, 'heading', scope.page.targets.facts);
|
|
1322
|
+
}
|
|
1323
|
+
/** The section root every designed section is written under, as `compileSection` writes its own. */ function designedRoot(scope, children, sx, dark) {
|
|
1324
|
+
var _ref;
|
|
1325
|
+
var _page_plan_sections_index_name, _page_plan_sections_index, _page_options_sectionIds;
|
|
1326
|
+
const { page, index } = scope;
|
|
1327
|
+
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}`;
|
|
1328
|
+
return page.tree.add('section', _extends({
|
|
1329
|
+
element: 'section',
|
|
1330
|
+
ariaLabel: sectionLabel(name, index)
|
|
1331
|
+
}, dark ? {
|
|
1332
|
+
colorScheme: 'dark'
|
|
1333
|
+
} : {}, index === 0 && scope.overPhoto ? {
|
|
1334
|
+
underHeader: true
|
|
1335
|
+
} : {}), sx, children, 'section', (_ref = (_page_options_sectionIds = page.options.sectionIds) == null ? void 0 : _page_options_sectionIds[index]) != null ? _ref : sectionIdOf(index));
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* A picture the design places: the model's own where it described one, else
|
|
1339
|
+
* a stand-in — marked decorative, since no one described it, with the
|
|
1340
|
+
* section's words as what a stock search looks for. Either is filled by
|
|
1341
|
+
* `ai-layout-pictures.ts` after the page is checked, as any slot is.
|
|
1342
|
+
*/ function designPicture(scope, picture, frameSx, role = 'designFrame', imageSx = {}) {
|
|
1343
|
+
const tree = scope.page.tree;
|
|
1344
|
+
// The picture fills its frame by its own size props, so the frame alone
|
|
1345
|
+
// carries a style: a page of many pictures repeats no inline style (rule 16).
|
|
1346
|
+
const image = designImage(scope, picture, {
|
|
1347
|
+
width: '100%',
|
|
1348
|
+
height: '100%'
|
|
1349
|
+
}, Object.keys(imageSx).length ? imageSx : null);
|
|
1350
|
+
return tree.add('muiBox', null, _extends({
|
|
1351
|
+
position: 'relative',
|
|
1352
|
+
overflow: 'hidden',
|
|
1353
|
+
bgcolor: 'action.hover'
|
|
1354
|
+
}, frameSx), [
|
|
1355
|
+
image
|
|
1356
|
+
], role);
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* The `image` a designed picture is: its alt, its fit and, for a stand-in,
|
|
1360
|
+
* decorative. Its slot is filled after the page is checked.
|
|
1361
|
+
*/ function designImage(scope, picture, props, sx) {
|
|
1362
|
+
const { page } = scope;
|
|
1363
|
+
if (picture.given) page.images += 1;
|
|
1364
|
+
else page.pictures += 1;
|
|
1365
|
+
return page.tree.add('image', _extends({
|
|
1366
|
+
alt: picture.alt,
|
|
1367
|
+
objectFit: 'cover'
|
|
1368
|
+
}, picture.given ? {} : {
|
|
1369
|
+
decorative: true
|
|
1370
|
+
}, props), sx, null, 'image');
|
|
1371
|
+
}
|
|
1372
|
+
/** What a stand-in picture is of, for a stock search: the section's subject, else the site's. */ function standInAlt(scope, words) {
|
|
1373
|
+
var _scope_page_plan_sections_scope_index;
|
|
1374
|
+
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';
|
|
1375
|
+
}
|
|
1376
|
+
/** A grid row of sized cells, as `compileRow` writes one, from ids already compiled. */ function designRow(scope, cells, spacing, alignItems = 'center') {
|
|
1377
|
+
const tree = scope.page.tree;
|
|
1378
|
+
return tree.add('muiGrid', {
|
|
1379
|
+
container: true,
|
|
1380
|
+
spacing
|
|
1381
|
+
}, {
|
|
1382
|
+
alignItems
|
|
1383
|
+
}, cells.map((cell)=>{
|
|
1384
|
+
var _cell_sx;
|
|
1385
|
+
return tree.add('muiGrid', {
|
|
1386
|
+
size: cell.size
|
|
1387
|
+
}, (_cell_sx = cell.sx) != null ? _cell_sx : null, [
|
|
1388
|
+
cell.id
|
|
1389
|
+
], 'column');
|
|
1390
|
+
}), 'row');
|
|
1391
|
+
}
|
|
1392
|
+
/** A section's own arrangement where the design has one; `null` to draw it the compiler's first way. */ function designSection(scope, raw, blocks) {
|
|
1393
|
+
var _scope_words, _ref, _ref1;
|
|
1394
|
+
var _group_items, _group_items1;
|
|
1395
|
+
const { page, index } = scope;
|
|
1396
|
+
const design = page.design;
|
|
1397
|
+
if (!design) return null;
|
|
1398
|
+
const images = blocks.filter((block)=>block.kind === 'image');
|
|
1399
|
+
const words = blocks.filter((block)=>block.kind !== 'image');
|
|
1400
|
+
const ofWords = words.length > 0 && words.every((block)=>WORD_KINDS.has(block.kind));
|
|
1401
|
+
if (index === 0) {
|
|
1402
|
+
var _words_find;
|
|
1403
|
+
if (!ofWords || images.length > 1 || picturesLeft(page) < 1) return null;
|
|
1404
|
+
const flow = [
|
|
1405
|
+
...words
|
|
1406
|
+
];
|
|
1407
|
+
if (!flow.some((block)=>speaksHeading(scope, block))) {
|
|
1408
|
+
flow.unshift({
|
|
1409
|
+
kind: 'heading',
|
|
1410
|
+
text: page.plan.title
|
|
1411
|
+
});
|
|
1412
|
+
page.settled.push({
|
|
1413
|
+
at: scope.at,
|
|
1414
|
+
what: "no heading; the page's title written as its h1"
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1417
|
+
// A designed hero's title is display-sized; beside a photo, in half the
|
|
1418
|
+
// page, it is the page's title size, so a long one still reads in a few lines.
|
|
1419
|
+
const lead = flow.findIndex((block)=>speaksHeading(scope, block));
|
|
1420
|
+
const _flow_lead = flow[lead], { style: _style } = _flow_lead, title = _object_without_properties_loose(_flow_lead, [
|
|
1421
|
+
"style"
|
|
1422
|
+
]);
|
|
1423
|
+
flow[lead] = design.choices.hero === 'split' ? title : _extends({}, title, {
|
|
1424
|
+
style: 'large'
|
|
1425
|
+
});
|
|
1426
|
+
const given = images[0] ? aiLayoutFitText(images[0].text, 'alt') : '';
|
|
1427
|
+
return hero(scope, raw, flow, given ? {
|
|
1428
|
+
alt: given,
|
|
1429
|
+
given: true
|
|
1430
|
+
} : {
|
|
1431
|
+
alt: standInAlt(scope, (_words_find = words.find((block)=>speaksHeading(scope, block))) == null ? void 0 : _words_find.text),
|
|
1432
|
+
given: false
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
if (ofWords && !images.length && words.some((block)=>speaksHeading(scope, block))) {
|
|
1436
|
+
const last = index === page.plan.sections.length - 1;
|
|
1437
|
+
const asks = words.some((block)=>block.kind === 'button');
|
|
1438
|
+
const strong = scope.band === 'brand' || scope.band === 'dark';
|
|
1439
|
+
const told = words.some((block)=>block.kind === 'text' || block.kind === 'lede');
|
|
1440
|
+
if (last && asks && (strong || scope.centered) && design.choices.coverClose && picturesLeft(page) >= 1) {
|
|
1441
|
+
return coverBand(scope, words);
|
|
1442
|
+
}
|
|
1443
|
+
if (design.choices.features && told && page.features < 2 && picturesLeft(page) >= 1 && !(last && asks && strong)) {
|
|
1444
|
+
return feature(scope, words);
|
|
1445
|
+
}
|
|
1446
|
+
return null;
|
|
1447
|
+
}
|
|
1448
|
+
// A heading over one group of items: the heading beside them.
|
|
1449
|
+
if (!design.choices.splitHeads || images.length || page.splitAt === index - 1) return null;
|
|
1450
|
+
const at = words.findIndex((block)=>block.kind === 'cards' || block.kind === 'steps');
|
|
1451
|
+
if (at <= 0) return null;
|
|
1452
|
+
const head = words.slice(0, at);
|
|
1453
|
+
const group = words[at];
|
|
1454
|
+
const tail = words.slice(at + 1);
|
|
1455
|
+
const variant = aiLayoutGroupVariant(design.input, design.choices, (_scope_words = scope.words) != null ? _scope_words : '');
|
|
1456
|
+
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') {
|
|
1457
|
+
return null;
|
|
1458
|
+
}
|
|
1459
|
+
return splitSection(scope, head, group, tail);
|
|
1460
|
+
}
|
|
1461
|
+
/** The first section, in the site's hero arrangement. */ function hero(scope, raw, flow, picture) {
|
|
1462
|
+
const { page } = scope;
|
|
1463
|
+
const tree = page.tree;
|
|
1464
|
+
const design = page.design;
|
|
1465
|
+
const home = design.input.home;
|
|
1466
|
+
const variant = design.choices.hero;
|
|
1467
|
+
page.settled.push({
|
|
1468
|
+
at: scope.at,
|
|
1469
|
+
what: `drawn as a ${variant} hero`
|
|
1470
|
+
});
|
|
1471
|
+
if (variant === 'cover') {
|
|
1472
|
+
scope.band = 'dark';
|
|
1473
|
+
scope.centered = raw.align === 'center';
|
|
1474
|
+
return cover(scope, flow, picture, home ? {
|
|
1475
|
+
xs: '78vh',
|
|
1476
|
+
md: '86vh'
|
|
1477
|
+
} : {
|
|
1478
|
+
xs: '46vh',
|
|
1479
|
+
md: '54vh'
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
const band = scope.band;
|
|
1483
|
+
scope.centered = false;
|
|
1484
|
+
if (variant === 'split') {
|
|
1485
|
+
const words = compileFlow(scope, flow, 'half');
|
|
1486
|
+
const photo = designPicture(scope, picture, {
|
|
1487
|
+
aspectRatio: home ? {
|
|
1488
|
+
xs: '4 / 3',
|
|
1489
|
+
md: '4 / 5'
|
|
1490
|
+
} : {
|
|
1491
|
+
xs: '4 / 3',
|
|
1492
|
+
md: '1 / 1'
|
|
1493
|
+
},
|
|
1494
|
+
borderRadius: 2
|
|
1495
|
+
});
|
|
1496
|
+
const right = design.choices.featureLeft;
|
|
1497
|
+
const row = designRow(scope, [
|
|
1498
|
+
_extends({
|
|
1499
|
+
id: words,
|
|
1500
|
+
size: 'xs:12 md:6'
|
|
1501
|
+
}, right ? {
|
|
1502
|
+
sx: {
|
|
1503
|
+
order: {
|
|
1504
|
+
xs: 0,
|
|
1505
|
+
md: 1
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
} : {}),
|
|
1509
|
+
{
|
|
1510
|
+
id: photo,
|
|
1511
|
+
size: 'xs:12 md:6'
|
|
1512
|
+
}
|
|
1513
|
+
], '8');
|
|
1514
|
+
const container = tree.add('muiContainer', {
|
|
1515
|
+
maxWidth: 'lg'
|
|
1516
|
+
}, {
|
|
1517
|
+
py: {
|
|
1518
|
+
xs: 6,
|
|
1519
|
+
md: 10
|
|
1520
|
+
}
|
|
1521
|
+
}, [
|
|
1522
|
+
row
|
|
1523
|
+
], 'container');
|
|
1524
|
+
return designedRoot(scope, [
|
|
1525
|
+
container
|
|
1526
|
+
], bandSx(band), band === 'dark');
|
|
1527
|
+
}
|
|
1528
|
+
// Editorial: display type across the page, the rest in a row under it, a wide photo below.
|
|
1529
|
+
const top = flow.filter((block)=>block.kind === 'eyebrow' || block.kind === 'heading');
|
|
1530
|
+
const rest = flow.filter((block)=>block.kind !== 'eyebrow' && block.kind !== 'heading');
|
|
1531
|
+
const lede = rest.filter((block)=>block.kind !== 'button');
|
|
1532
|
+
const actions = rest.filter((block)=>block.kind === 'button');
|
|
1533
|
+
const headId = compileFlow(scope, top, 'full');
|
|
1534
|
+
const ledeId = compileFlow(scope, lede, 'half');
|
|
1535
|
+
const actionsId = compileFlow(scope, actions, 'half');
|
|
1536
|
+
const under = ledeId && actionsId ? designRow(scope, [
|
|
1537
|
+
{
|
|
1538
|
+
id: ledeId,
|
|
1539
|
+
size: 'xs:12 md:7'
|
|
1540
|
+
},
|
|
1541
|
+
{
|
|
1542
|
+
id: actionsId,
|
|
1543
|
+
size: 'xs:12 md:5',
|
|
1544
|
+
sx: {
|
|
1545
|
+
display: 'flex',
|
|
1546
|
+
justifyContent: {
|
|
1547
|
+
xs: 'flex-start',
|
|
1548
|
+
md: 'flex-end'
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
], '4', 'flex-end') : ledeId != null ? ledeId : actionsId;
|
|
1553
|
+
const photo = designPicture(scope, picture, {
|
|
1554
|
+
aspectRatio: home ? {
|
|
1555
|
+
xs: '4 / 3',
|
|
1556
|
+
md: '21 / 9'
|
|
1557
|
+
} : {
|
|
1558
|
+
xs: '16 / 9',
|
|
1559
|
+
md: '3 / 1'
|
|
1560
|
+
},
|
|
1561
|
+
borderRadius: 2
|
|
1562
|
+
});
|
|
1563
|
+
const stack = tree.add('muiStack', {
|
|
1564
|
+
spacing: '6',
|
|
1565
|
+
useFlexGap: true
|
|
1566
|
+
}, null, [
|
|
1567
|
+
headId,
|
|
1568
|
+
under,
|
|
1569
|
+
photo
|
|
1570
|
+
], 'content');
|
|
1571
|
+
const container = tree.add('muiContainer', {
|
|
1572
|
+
maxWidth: 'lg'
|
|
1573
|
+
}, {
|
|
1574
|
+
pt: {
|
|
1575
|
+
xs: 8,
|
|
1576
|
+
md: 12
|
|
1577
|
+
},
|
|
1578
|
+
pb: {
|
|
1579
|
+
xs: 6,
|
|
1580
|
+
md: 10
|
|
1581
|
+
}
|
|
1582
|
+
}, [
|
|
1583
|
+
stack
|
|
1584
|
+
], 'container');
|
|
1585
|
+
return designedRoot(scope, [
|
|
1586
|
+
container
|
|
1587
|
+
], bandSx(band), band === 'dark');
|
|
1588
|
+
}
|
|
1589
|
+
/** 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) {
|
|
1590
|
+
const tree = scope.page.tree;
|
|
1591
|
+
// The photo dimmed over black: the scrim that keeps the words over it readable.
|
|
1592
|
+
const photo = designPicture(scope, picture, {
|
|
1593
|
+
position: 'absolute',
|
|
1594
|
+
top: 0,
|
|
1595
|
+
left: 0,
|
|
1596
|
+
width: '100%',
|
|
1597
|
+
height: '100%',
|
|
1598
|
+
bgcolor: 'common.black'
|
|
1599
|
+
}, 'coverPhoto', {
|
|
1600
|
+
opacity: 0.42
|
|
1601
|
+
});
|
|
1602
|
+
scope.overPhoto = true;
|
|
1603
|
+
const words = compileFlow(scope, flow, 'full');
|
|
1604
|
+
const measure = tree.add('muiBox', null, scope.centered ? {
|
|
1605
|
+
maxWidth: {
|
|
1606
|
+
xs: '100%',
|
|
1607
|
+
md: '75%'
|
|
1608
|
+
},
|
|
1609
|
+
mx: 'auto'
|
|
1610
|
+
} : {
|
|
1611
|
+
maxWidth: {
|
|
1612
|
+
xs: '100%',
|
|
1613
|
+
md: '62%'
|
|
1614
|
+
}
|
|
1615
|
+
}, [
|
|
1616
|
+
words
|
|
1617
|
+
], 'measure');
|
|
1618
|
+
const container = tree.add('muiContainer', {
|
|
1619
|
+
maxWidth: 'lg'
|
|
1620
|
+
}, {
|
|
1621
|
+
position: 'relative',
|
|
1622
|
+
zIndex: 1,
|
|
1623
|
+
py: {
|
|
1624
|
+
xs: 10,
|
|
1625
|
+
md: 14
|
|
1626
|
+
}
|
|
1627
|
+
}, [
|
|
1628
|
+
measure
|
|
1629
|
+
], 'container');
|
|
1630
|
+
return designedRoot(scope, [
|
|
1631
|
+
photo,
|
|
1632
|
+
container
|
|
1633
|
+
], {
|
|
1634
|
+
position: 'relative',
|
|
1635
|
+
overflow: 'hidden',
|
|
1636
|
+
display: 'flex',
|
|
1637
|
+
alignItems: {
|
|
1638
|
+
xs: 'flex-end',
|
|
1639
|
+
md: 'center'
|
|
1640
|
+
},
|
|
1641
|
+
minHeight
|
|
1642
|
+
}, true);
|
|
1643
|
+
}
|
|
1644
|
+
/** A closing section of words over a photo. */ function coverBand(scope, words) {
|
|
1645
|
+
scope.band = 'dark';
|
|
1646
|
+
scope.centered = true;
|
|
1647
|
+
scope.page.settled.push({
|
|
1648
|
+
at: scope.at,
|
|
1649
|
+
what: 'drawn over a photo'
|
|
1650
|
+
});
|
|
1651
|
+
return cover(scope, words, {
|
|
1652
|
+
alt: standInAlt(scope),
|
|
1653
|
+
given: false
|
|
1654
|
+
}, {
|
|
1655
|
+
xs: '56vh',
|
|
1656
|
+
md: '64vh'
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
/** A section of words beside a picture, the side turning section by section. */ function feature(scope, words) {
|
|
1660
|
+
const { page } = scope;
|
|
1661
|
+
const design = page.design;
|
|
1662
|
+
const left = design.choices.featureLeft !== (page.features % 2 === 1);
|
|
1663
|
+
page.features += 1;
|
|
1664
|
+
page.settled.push({
|
|
1665
|
+
at: scope.at,
|
|
1666
|
+
what: `set beside a picture on the ${left ? 'left' : 'right'}`
|
|
1667
|
+
});
|
|
1668
|
+
scope.centered = false;
|
|
1669
|
+
const flow = compileFlow(scope, words, 'half');
|
|
1670
|
+
const photo = designPicture(scope, {
|
|
1671
|
+
alt: standInAlt(scope),
|
|
1672
|
+
given: false
|
|
1673
|
+
}, {
|
|
1674
|
+
aspectRatio: {
|
|
1675
|
+
xs: '4 / 3',
|
|
1676
|
+
md: page.features === 1 ? '4 / 5' : '1 / 1'
|
|
1677
|
+
},
|
|
1678
|
+
borderRadius: 2
|
|
1679
|
+
});
|
|
1680
|
+
const row = designRow(scope, left ? [
|
|
1681
|
+
{
|
|
1682
|
+
id: photo,
|
|
1683
|
+
size: 'xs:12 md:6'
|
|
1684
|
+
},
|
|
1685
|
+
{
|
|
1686
|
+
id: flow,
|
|
1687
|
+
size: 'xs:12 md:6'
|
|
1688
|
+
}
|
|
1689
|
+
] : [
|
|
1690
|
+
{
|
|
1691
|
+
id: flow,
|
|
1692
|
+
size: 'xs:12 md:6'
|
|
1693
|
+
},
|
|
1694
|
+
{
|
|
1695
|
+
id: photo,
|
|
1696
|
+
size: 'xs:12 md:6'
|
|
1697
|
+
}
|
|
1698
|
+
], '8');
|
|
1699
|
+
const container = page.tree.add('muiContainer', {
|
|
1700
|
+
maxWidth: 'lg'
|
|
1701
|
+
}, {
|
|
1702
|
+
py: _extends({}, SECTION_PADDING)
|
|
1703
|
+
}, [
|
|
1704
|
+
row
|
|
1705
|
+
], 'container');
|
|
1706
|
+
return designedRoot(scope, [
|
|
1707
|
+
container
|
|
1708
|
+
], bandSx(scope.band), scope.band === 'dark');
|
|
1709
|
+
}
|
|
1710
|
+
/** A heading beside its items: the words in a narrow column, the items ruled in the wide one. */ function splitSection(scope, head, group, tail) {
|
|
1711
|
+
const { page } = scope;
|
|
1712
|
+
scope.centered = false;
|
|
1713
|
+
scope.groupStyle = 'ruled';
|
|
1714
|
+
page.splitAt = scope.index;
|
|
1715
|
+
page.settled.push({
|
|
1716
|
+
at: scope.at,
|
|
1717
|
+
what: 'the heading set beside its items'
|
|
1718
|
+
});
|
|
1719
|
+
const words = compileFlow(scope, [
|
|
1720
|
+
...head,
|
|
1721
|
+
...tail
|
|
1722
|
+
], 'half');
|
|
1723
|
+
const items = compileFlow(scope, [
|
|
1724
|
+
group
|
|
1725
|
+
], 'half');
|
|
1726
|
+
if (!words || !items) {
|
|
1727
|
+
const flow = [
|
|
1728
|
+
words,
|
|
1729
|
+
items
|
|
1730
|
+
].filter((id)=>!!id);
|
|
1731
|
+
const container = page.tree.add('muiContainer', {
|
|
1732
|
+
maxWidth: 'lg'
|
|
1733
|
+
}, {
|
|
1734
|
+
py: _extends({}, SECTION_PADDING)
|
|
1735
|
+
}, flow, 'container');
|
|
1736
|
+
return designedRoot(scope, [
|
|
1737
|
+
container
|
|
1738
|
+
], bandSx(scope.band), scope.band === 'dark');
|
|
1739
|
+
}
|
|
1740
|
+
const row = designRow(scope, [
|
|
1741
|
+
{
|
|
1742
|
+
id: words,
|
|
1743
|
+
size: 'xs:12 md:5'
|
|
1744
|
+
},
|
|
1745
|
+
{
|
|
1746
|
+
id: items,
|
|
1747
|
+
size: 'xs:12 md:7'
|
|
1748
|
+
}
|
|
1749
|
+
], '8', 'flex-start');
|
|
1750
|
+
const container = page.tree.add('muiContainer', {
|
|
1751
|
+
maxWidth: 'lg'
|
|
1752
|
+
}, {
|
|
1753
|
+
py: _extends({}, SECTION_PADDING)
|
|
1754
|
+
}, [
|
|
1755
|
+
row
|
|
1756
|
+
], 'container');
|
|
1757
|
+
return designedRoot(scope, [
|
|
1758
|
+
container
|
|
1759
|
+
], bandSx(scope.band), scope.band === 'dark');
|
|
1760
|
+
}
|
|
1761
|
+
/**
|
|
1762
|
+
* Items under rules, one a line, each opening under a thin rule in the
|
|
1763
|
+
* text's own color. One style key an element, so a long list repeats no
|
|
1764
|
+
* multi-key inline style (rule 16); and no Stack `divider`, which a
|
|
1765
|
+
* published page's renderer hands a Stack as one child and so never draws.
|
|
1766
|
+
*/ function ruledList(scope, ids, role) {
|
|
1767
|
+
const tree = scope.page.tree;
|
|
1768
|
+
return tree.add('muiStack', {
|
|
1769
|
+
spacing: '2'
|
|
1770
|
+
}, null, ids.map((id)=>tree.add('muiBox', null, {
|
|
1771
|
+
borderTop: 1
|
|
1772
|
+
}, [
|
|
1773
|
+
tree.add('muiBox', null, {
|
|
1774
|
+
pt: 2
|
|
1775
|
+
}, [
|
|
1776
|
+
id
|
|
1777
|
+
], 'ruledWords')
|
|
1778
|
+
], 'ruledLine')), role);
|
|
1779
|
+
}
|
|
1780
|
+
/** Numbered items as a ruled list: each number beside its title and words. */ function timeline(scope, items) {
|
|
1781
|
+
const tree = scope.page.tree;
|
|
1782
|
+
const facts = scope.page.targets.facts;
|
|
1783
|
+
const rows = items.map((item, position)=>tree.add('muiStack', {
|
|
1784
|
+
direction: 'row',
|
|
1785
|
+
spacing: '3',
|
|
1786
|
+
alignItems: 'baseline'
|
|
1787
|
+
}, null, [
|
|
1788
|
+
// The numbers keep one column, so every title starts at the same line.
|
|
1789
|
+
tree.add('muiBox', null, {
|
|
1790
|
+
flex: '0 0 3.5rem'
|
|
1791
|
+
}, [
|
|
1792
|
+
tree.add('muiTypography', {
|
|
1793
|
+
children: String(position + 1).padStart(2, '0'),
|
|
1794
|
+
variant: 'h4',
|
|
1795
|
+
component: 'p'
|
|
1796
|
+
}, accent(scope), null, 'number')
|
|
1797
|
+
], 'numberColumn'),
|
|
1798
|
+
tree.add('muiStack', {
|
|
1799
|
+
spacing: '1'
|
|
1800
|
+
}, null, [
|
|
1801
|
+
item.title.trim() ? tree.add('muiTypography', {
|
|
1802
|
+
children: aiLayoutWords(item.title, 'itemTitle', facts),
|
|
1803
|
+
variant: 'h5',
|
|
1804
|
+
component: itemElement(scope)
|
|
1805
|
+
}, null, null, 'title') : null,
|
|
1806
|
+
item.text.trim() ? tree.add('muiTypography', {
|
|
1807
|
+
children: aiLayoutWords(item.text, 'itemText', facts),
|
|
1808
|
+
variant: 'body1'
|
|
1809
|
+
}, muted(scope), null, 'text') : null
|
|
1810
|
+
], 'stepWords')
|
|
1811
|
+
], 'step'));
|
|
1812
|
+
return ruledList(scope, noted(scope, rows), 'timeline');
|
|
1813
|
+
}
|
|
1814
|
+
/** A group drawn the design's way; `null` to draw it as the theme's cards. */ function designedGroup(scope, variant, items, room) {
|
|
1815
|
+
const { page } = scope;
|
|
1816
|
+
const tree = page.tree;
|
|
1817
|
+
const facts = page.targets.facts;
|
|
1818
|
+
const title = (item, type = 'h5')=>item.title.trim() ? tree.add('muiTypography', {
|
|
1819
|
+
children: aiLayoutWords(item.title, 'itemTitle', facts),
|
|
1820
|
+
variant: type,
|
|
1821
|
+
component: itemElement(scope)
|
|
1822
|
+
}, null, null, 'title') : null;
|
|
1823
|
+
const words = (item, type = 'body1')=>item.text.trim() ? tree.add('muiTypography', {
|
|
1824
|
+
children: aiLayoutWords(item.text, 'itemText', facts),
|
|
1825
|
+
variant: type
|
|
1826
|
+
}, muted(scope), null, 'text') : null;
|
|
1827
|
+
if (variant === 'cards') return null;
|
|
1828
|
+
const pictured = variant === 'pictures' || variant === 'articles';
|
|
1829
|
+
if (variant === 'ruled' || pictured && (room !== 'full' || picturesLeft(page) < items.length)) {
|
|
1830
|
+
const perRow = across(items.length, room, 'cards');
|
|
1831
|
+
if (perRow <= 1) {
|
|
1832
|
+
// Stacked, the rules run between the items.
|
|
1833
|
+
const ids = items.map((item)=>tree.add('muiStack', {
|
|
1834
|
+
spacing: '1'
|
|
1835
|
+
}, null, [
|
|
1836
|
+
title(item),
|
|
1837
|
+
words(item)
|
|
1838
|
+
], 'ruled'));
|
|
1839
|
+
return ruledList(scope, noted(scope, ids), 'ruledItems');
|
|
1840
|
+
}
|
|
1841
|
+
// Side by side, each column opens under a rule in the text's own color.
|
|
1842
|
+
const ids = items.map((item)=>tree.add('muiBox', null, {
|
|
1843
|
+
borderTop: 1
|
|
1844
|
+
}, [
|
|
1845
|
+
tree.add('muiStack', {
|
|
1846
|
+
spacing: '1'
|
|
1847
|
+
}, {
|
|
1848
|
+
pt: 2.5
|
|
1849
|
+
}, [
|
|
1850
|
+
title(item),
|
|
1851
|
+
words(item)
|
|
1852
|
+
], 'ruledWords')
|
|
1853
|
+
], 'ruled'));
|
|
1854
|
+
return layOut(scope, noted(scope, ids), perRow, '5', 'ruledItems');
|
|
1855
|
+
}
|
|
1856
|
+
if (variant === 'menu') {
|
|
1857
|
+
const ids = items.map((item)=>tree.add('muiStack', {
|
|
1858
|
+
spacing: '0.5'
|
|
1859
|
+
}, null, [
|
|
1860
|
+
title(item, 'h6'),
|
|
1861
|
+
words(item, 'body2')
|
|
1862
|
+
], 'dish'));
|
|
1863
|
+
noted(scope, ids);
|
|
1864
|
+
// Two columns of lines under rules, the first half and the second.
|
|
1865
|
+
const half = room === 'full' && ids.length >= 4 ? Math.ceil(ids.length / 2) : ids.length;
|
|
1866
|
+
const lists = [
|
|
1867
|
+
ids.slice(0, half),
|
|
1868
|
+
ids.slice(half)
|
|
1869
|
+
].filter((list)=>list.length).map((list)=>ruledList(scope, list, 'menu'));
|
|
1870
|
+
if (lists.length === 1) return lists[0];
|
|
1871
|
+
// On a phone the two columns read as one list, the second opening under
|
|
1872
|
+
// its own rule a line's gap below the first; side by side, a gutter.
|
|
1873
|
+
const [first, second] = lists;
|
|
1874
|
+
return tree.add('muiGrid', {
|
|
1875
|
+
container: true,
|
|
1876
|
+
rowSpacing: '2',
|
|
1877
|
+
columnSpacing: '8'
|
|
1878
|
+
}, {
|
|
1879
|
+
alignItems: 'flex-start'
|
|
1880
|
+
}, [
|
|
1881
|
+
tree.add('muiGrid', {
|
|
1882
|
+
size: 'xs:12 md:6'
|
|
1883
|
+
}, null, [
|
|
1884
|
+
first
|
|
1885
|
+
], 'column'),
|
|
1886
|
+
tree.add('muiGrid', {
|
|
1887
|
+
size: 'xs:12 md:6'
|
|
1888
|
+
}, null, [
|
|
1889
|
+
second
|
|
1890
|
+
], 'column')
|
|
1891
|
+
], 'menuRow');
|
|
1892
|
+
}
|
|
1893
|
+
// Pictures over each item's title and words.
|
|
1894
|
+
const design = page.design;
|
|
1895
|
+
const mosaic = variant === 'pictures' && design.choices.pictures === 'mosaic' && items.length >= 2;
|
|
1896
|
+
const portrait = design.input.kind === 'photography';
|
|
1897
|
+
const perRow = items.length === 4 || items.length === 2 ? 2 : Math.min(3, items.length);
|
|
1898
|
+
page.settled.push({
|
|
1899
|
+
at: scope.at,
|
|
1900
|
+
what: `${items.length} items drawn as ${mosaic ? 'a mosaic of pictures' : variant}`
|
|
1901
|
+
});
|
|
1902
|
+
const cells = items.map((item, position)=>{
|
|
1903
|
+
// A mosaic's rows turn wide-narrow, narrow-wide; an odd one out spans the row.
|
|
1904
|
+
const row = Math.floor(position / 2);
|
|
1905
|
+
const lone = mosaic && position === items.length - 1 && items.length % 2 === 1;
|
|
1906
|
+
const wide = mosaic && !lone && position % 2 === row % 2;
|
|
1907
|
+
const span = !mosaic ? 12 / perRow : lone ? 12 : wide ? 7 : 5;
|
|
1908
|
+
const aspect = !mosaic ? variant === 'articles' ? '3 / 2' : portrait ? '4 / 5' : '4 / 3' : lone ? '21 / 9' : wide ? '4 / 3' : '4 / 5';
|
|
1909
|
+
// The picture is its own frame: its shape its one style, so a grid of them repeats no inline style.
|
|
1910
|
+
const photo = designImage(scope, {
|
|
1911
|
+
alt: standInAlt(scope, item.title || item.text),
|
|
1912
|
+
given: false
|
|
1913
|
+
}, {
|
|
1914
|
+
width: '100%'
|
|
1915
|
+
}, {
|
|
1916
|
+
aspectRatio: {
|
|
1917
|
+
xs: '4 / 3',
|
|
1918
|
+
md: aspect
|
|
1919
|
+
}
|
|
1920
|
+
});
|
|
1921
|
+
const id = tree.add('muiStack', {
|
|
1922
|
+
spacing: '1.5'
|
|
1923
|
+
}, null, [
|
|
1924
|
+
photo,
|
|
1925
|
+
title(item, variant === 'articles' ? 'h5' : 'h6'),
|
|
1926
|
+
words(item, 'body2')
|
|
1927
|
+
], variant === 'articles' ? 'article' : 'work');
|
|
1928
|
+
return {
|
|
1929
|
+
id,
|
|
1930
|
+
size: span === 12 ? 'xs:12 sm:12' : `xs:12 ${span === 6 ? 'sm' : 'md'}:${span}`
|
|
1931
|
+
};
|
|
1932
|
+
});
|
|
1933
|
+
noted(scope, cells.map((cell)=>cell.id));
|
|
1934
|
+
return tree.add('muiGrid', {
|
|
1935
|
+
container: true,
|
|
1936
|
+
spacing: mosaic ? '5' : '4'
|
|
1937
|
+
}, {
|
|
1938
|
+
alignItems: 'flex-start'
|
|
1939
|
+
}, cells.map((cell)=>tree.add('muiGrid', {
|
|
1940
|
+
size: cell.size
|
|
1941
|
+
}, null, [
|
|
1942
|
+
cell.id
|
|
1943
|
+
], 'cell')), variant);
|
|
1944
|
+
}
|
|
1945
|
+
// ── A section the site's records fill (AGL-3676) ──────────────────────────
|
|
1946
|
+
//
|
|
1947
|
+
// The section's words — its eyebrow, heading and lede — are the design's;
|
|
1948
|
+
// what it lists is the site's: its products through the commerce plugin's
|
|
1949
|
+
// Product grid, its posts through the content plugin's Collection Entries.
|
|
1950
|
+
// Any group the design drew for those records (cards naming products, a list
|
|
1951
|
+
// of post titles) stands in for them, and is left out.
|
|
1952
|
+
/** The block kinds a listing stands in for: the records the design described in words. */ const LISTING_REPLACES = new Set([
|
|
1953
|
+
'cards',
|
|
1954
|
+
'steps',
|
|
1955
|
+
'stats',
|
|
1956
|
+
'quotes',
|
|
1957
|
+
'list',
|
|
1958
|
+
'image',
|
|
1959
|
+
'component'
|
|
1960
|
+
]);
|
|
1961
|
+
/** The tokens a post's card binds, filled per post when the page renders. */ export const AI_LAYOUT_POST_CARD_TOKENS = [
|
|
1962
|
+
'{{entry.title}}',
|
|
1963
|
+
'{{entry.excerpt}}',
|
|
1964
|
+
'{{entry.date}}',
|
|
1965
|
+
'{{entry.author}}',
|
|
1966
|
+
'{{entry.url}}',
|
|
1967
|
+
'{{entry.coverImage}}'
|
|
1968
|
+
];
|
|
1969
|
+
/** The tokens a post's card puts in a link or a picture, which the page's store admits whole. */ export const AI_LAYOUT_POST_ADDRESS_TOKENS = [
|
|
1970
|
+
'{{entry.url}}',
|
|
1971
|
+
'{{entry.coverImage}}'
|
|
1972
|
+
];
|
|
1973
|
+
/** The button under a featured band that opens the whole list, where the site has one and the design gave none. */ function listingAllButton(page, listing) {
|
|
1974
|
+
if (listing.kind === 'posts') return listing.href ? {
|
|
1975
|
+
kind: 'button',
|
|
1976
|
+
text: 'All posts',
|
|
1977
|
+
to: listing.href,
|
|
1978
|
+
style: 'secondary'
|
|
1979
|
+
} : null;
|
|
1980
|
+
const index = listing.placements.find((placement)=>placement.role === 'index' && placement.screenId !== page.targets.pageId);
|
|
1981
|
+
return index ? {
|
|
1982
|
+
kind: 'button',
|
|
1983
|
+
text: 'Shop all',
|
|
1984
|
+
to: `page:${index.screenId}`,
|
|
1985
|
+
style: 'secondary'
|
|
1986
|
+
} : null;
|
|
1987
|
+
}
|
|
1988
|
+
function listingSection(scope, blocks, placed) {
|
|
1989
|
+
var _ref;
|
|
1990
|
+
var _page_plan_sections_index_name, _page_plan_sections_index, _page_options_sectionIds;
|
|
1991
|
+
const { page, index, at } = scope;
|
|
1992
|
+
const { listing, role } = placed;
|
|
1993
|
+
const left = blocks.filter((block)=>LISTING_REPLACES.has(block.kind));
|
|
1994
|
+
if (left.length) {
|
|
1995
|
+
page.settled.push({
|
|
1996
|
+
at,
|
|
1997
|
+
what: `${left.map((block)=>block.kind).join(', ')} left out: the section lists the site's own ${listing.kind}`
|
|
1998
|
+
});
|
|
1999
|
+
}
|
|
2000
|
+
const kept = blocks.filter((block)=>!LISTING_REPLACES.has(block.kind)).map((_0)=>{
|
|
2001
|
+
let { col: _col } = _0, block = _object_without_properties_loose(_0, [
|
|
2002
|
+
"col"
|
|
2003
|
+
]);
|
|
2004
|
+
return block;
|
|
2005
|
+
});
|
|
2006
|
+
const words = kept.filter((block)=>block.kind !== 'button' && block.kind !== 'form');
|
|
2007
|
+
let actions = kept.filter((block)=>block.kind === 'button');
|
|
2008
|
+
if (!actions.length && role === 'featured') {
|
|
2009
|
+
const all = listingAllButton(page, listing);
|
|
2010
|
+
if (all) actions = [
|
|
2011
|
+
all
|
|
2012
|
+
];
|
|
2013
|
+
}
|
|
2014
|
+
if (!words.some((block)=>speaksHeading(scope, block))) {
|
|
2015
|
+
var _page_plan_sections_index1;
|
|
2016
|
+
// Every band of records is headed: the plan's name for it, or on a first section the page's title.
|
|
2017
|
+
words.unshift({
|
|
2018
|
+
kind: 'heading',
|
|
2019
|
+
text: index === 0 ? page.plan.title : ((_page_plan_sections_index1 = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index1.name) || page.plan.title
|
|
2020
|
+
});
|
|
2021
|
+
}
|
|
2022
|
+
page.settled.push({
|
|
2023
|
+
at,
|
|
2024
|
+
what: `lists the site's ${listing.kind} (${role})`
|
|
2025
|
+
});
|
|
2026
|
+
const tree = page.tree;
|
|
2027
|
+
const centered = scope.centered;
|
|
2028
|
+
const head = compileFlow(scope, words, centered ? 'full' : 'half');
|
|
2029
|
+
const link = compileFlow(scope, actions, 'half');
|
|
2030
|
+
// An editorial band's head: the words on the left, the way to the whole list on the right.
|
|
2031
|
+
const top = head && link && !centered ? designRow(scope, [
|
|
2032
|
+
{
|
|
2033
|
+
id: head,
|
|
2034
|
+
size: 'xs:12 md:8'
|
|
2035
|
+
},
|
|
2036
|
+
{
|
|
2037
|
+
id: link,
|
|
2038
|
+
size: 'xs:12 md:4',
|
|
2039
|
+
sx: {
|
|
2040
|
+
display: 'flex',
|
|
2041
|
+
justifyContent: {
|
|
2042
|
+
xs: 'flex-start',
|
|
2043
|
+
md: 'flex-end'
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
], '3', 'flex-end') : head;
|
|
2048
|
+
const records = listingElement(scope, listing, role);
|
|
2049
|
+
const parts = [
|
|
2050
|
+
top ? centered ? tree.add('muiContainer', {
|
|
2051
|
+
maxWidth: 'md',
|
|
2052
|
+
disableGutters: true
|
|
2053
|
+
}, null, [
|
|
2054
|
+
top
|
|
2055
|
+
], 'measure') : top : null,
|
|
2056
|
+
records,
|
|
2057
|
+
centered || !head ? link : null
|
|
2058
|
+
].filter((id)=>!!id);
|
|
2059
|
+
const content = tree.add('muiStack', _extends({
|
|
2060
|
+
spacing: '6',
|
|
2061
|
+
useFlexGap: true
|
|
2062
|
+
}, centered ? {
|
|
2063
|
+
alignItems: 'center'
|
|
2064
|
+
} : {}), null, parts, 'content');
|
|
2065
|
+
const container = tree.add('muiContainer', {
|
|
2066
|
+
maxWidth: 'lg'
|
|
2067
|
+
}, {
|
|
2068
|
+
py: index === 0 ? _extends({}, HERO_PADDING) : _extends({}, SECTION_PADDING)
|
|
2069
|
+
}, [
|
|
2070
|
+
content
|
|
2071
|
+
], 'container');
|
|
2072
|
+
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}`;
|
|
2073
|
+
return tree.add('section', _extends({
|
|
2074
|
+
element: 'section',
|
|
2075
|
+
ariaLabel: sectionLabel(name, index)
|
|
2076
|
+
}, scope.band === 'dark' ? {
|
|
2077
|
+
colorScheme: 'dark'
|
|
2078
|
+
} : {}), bandSx(scope.band), [
|
|
2079
|
+
container
|
|
2080
|
+
], 'section', (_ref = (_page_options_sectionIds = page.options.sectionIds) == null ? void 0 : _page_options_sectionIds[index]) != null ? _ref : sectionIdOf(index));
|
|
2081
|
+
}
|
|
2082
|
+
/**
|
|
2083
|
+
* The element that lists the records, bound to them: the Product grid over
|
|
2084
|
+
* the site's catalog, or Collection Entries over its blog with one post's
|
|
2085
|
+
* card as the template it repeats. Its records count as the section's items.
|
|
2086
|
+
*/ function listingElement(scope, listing, role) {
|
|
2087
|
+
const { page } = scope;
|
|
2088
|
+
const tree = page.tree;
|
|
2089
|
+
const featured = role === 'featured';
|
|
2090
|
+
const shown = featured ? AI_LAYOUT_FEATURED_RECORDS[listing.kind] : 12;
|
|
2091
|
+
const element = AI_LAYOUT_LISTING_ELEMENTS[listing.kind];
|
|
2092
|
+
let id;
|
|
2093
|
+
if (listing.kind === 'products') {
|
|
2094
|
+
id = tree.add(element, _extends({
|
|
2095
|
+
source: 'all',
|
|
2096
|
+
sort: 'newest',
|
|
2097
|
+
columns: String(featured ? Math.min(AI_LAYOUT_FEATURED_RECORDS.products, Math.max(3, listing.records.length)) : 3)
|
|
2098
|
+
}, featured ? {
|
|
2099
|
+
maxItems: String(shown)
|
|
2100
|
+
} : {
|
|
2101
|
+
pageSize: String(shown)
|
|
2102
|
+
}, {
|
|
2103
|
+
cardStyle: 'photo',
|
|
2104
|
+
emptyText: 'New products are on their way.'
|
|
2105
|
+
}), null, null, 'products');
|
|
2106
|
+
} else {
|
|
2107
|
+
id = postsElement(scope, listing, featured ? shown : COLLECTION_INDEX_POSTS);
|
|
2108
|
+
}
|
|
2109
|
+
// What a visitor sees here is the site's records, however many it keeps:
|
|
2110
|
+
// the section shows its planned items when it has any to show.
|
|
2111
|
+
noted(scope, Array.from({
|
|
2112
|
+
length: Math.max(2, Math.min(shown, listing.records.length))
|
|
2113
|
+
}, ()=>id));
|
|
2114
|
+
return id;
|
|
2115
|
+
}
|
|
2116
|
+
/** The most posts a page of the site lists where it is the writing's own page. */ const COLLECTION_INDEX_POSTS = 9;
|
|
2117
|
+
/** The blog's posts as the site's design lists them: a grid of covers, or a ruled list with the dates. */ function postsElement(scope, listing, limit) {
|
|
2118
|
+
var _page_design;
|
|
2119
|
+
const { page } = scope;
|
|
2120
|
+
const tree = page.tree;
|
|
2121
|
+
const ruled = ((_page_design = page.design) == null ? void 0 : _page_design.choices.writing) === 'ruled';
|
|
2122
|
+
const titleElement = itemElement(scope);
|
|
2123
|
+
const cover = (sx)=>tree.add('image', {
|
|
2124
|
+
src: '{{entry.coverImage}}',
|
|
2125
|
+
alt: '{{entry.title}}',
|
|
2126
|
+
href: '{{entry.url}}',
|
|
2127
|
+
objectFit: 'cover',
|
|
2128
|
+
width: '100%',
|
|
2129
|
+
loading: 'lazy'
|
|
2130
|
+
}, sx, null, 'postCover');
|
|
2131
|
+
const meta = tree.add('muiTypography', {
|
|
2132
|
+
children: '{{entry.date}} · {{entry.author}}',
|
|
2133
|
+
variant: 'caption',
|
|
2134
|
+
component: 'p'
|
|
2135
|
+
}, muted(scope), null, 'postMeta');
|
|
2136
|
+
const title = tree.add('muiTypography', {
|
|
2137
|
+
children: '{{entry.title}}',
|
|
2138
|
+
variant: ruled ? 'h5' : 'h6',
|
|
2139
|
+
component: titleElement
|
|
2140
|
+
}, null, null, 'postTitle');
|
|
2141
|
+
const excerpt = tree.add('muiTypography', {
|
|
2142
|
+
children: '{{entry.excerpt}}',
|
|
2143
|
+
variant: 'body2'
|
|
2144
|
+
}, muted(scope), null, 'postExcerpt');
|
|
2145
|
+
const more = tree.add('muiScreenLink', {
|
|
2146
|
+
children: 'Read the post',
|
|
2147
|
+
href: '{{entry.url}}',
|
|
2148
|
+
renderAs: 'link',
|
|
2149
|
+
color: 'inherit'
|
|
2150
|
+
}, {
|
|
2151
|
+
alignSelf: 'flex-start'
|
|
2152
|
+
}, null, 'postLink');
|
|
2153
|
+
page.settled.push({
|
|
2154
|
+
at: scope.at,
|
|
2155
|
+
what: `posts listed as ${ruled ? 'a ruled list' : 'a grid of covers'}`
|
|
2156
|
+
});
|
|
2157
|
+
const card = ruled ? tree.add('muiBox', null, {
|
|
2158
|
+
borderTop: 1,
|
|
2159
|
+
pt: 3
|
|
2160
|
+
}, [
|
|
2161
|
+
tree.add('muiStack', {
|
|
2162
|
+
direction: 'row',
|
|
2163
|
+
spacing: '3',
|
|
2164
|
+
alignItems: 'flex-start'
|
|
2165
|
+
}, null, [
|
|
2166
|
+
tree.add('muiStack', {
|
|
2167
|
+
spacing: '1'
|
|
2168
|
+
}, {
|
|
2169
|
+
flex: '1 1 auto',
|
|
2170
|
+
minWidth: 0
|
|
2171
|
+
}, [
|
|
2172
|
+
meta,
|
|
2173
|
+
title,
|
|
2174
|
+
excerpt,
|
|
2175
|
+
more
|
|
2176
|
+
], 'postWords'),
|
|
2177
|
+
tree.add('muiBox', null, {
|
|
2178
|
+
flex: '0 0 auto',
|
|
2179
|
+
width: {
|
|
2180
|
+
xs: '30%',
|
|
2181
|
+
md: '24%'
|
|
2182
|
+
}
|
|
2183
|
+
}, [
|
|
2184
|
+
cover({
|
|
2185
|
+
aspectRatio: '4 / 3',
|
|
2186
|
+
borderRadius: 2
|
|
2187
|
+
})
|
|
2188
|
+
], 'postThumb')
|
|
2189
|
+
], 'postRow')
|
|
2190
|
+
], 'post') : tree.add('muiStack', {
|
|
2191
|
+
spacing: '1.5'
|
|
2192
|
+
}, null, [
|
|
2193
|
+
cover({
|
|
2194
|
+
aspectRatio: '3 / 2',
|
|
2195
|
+
borderRadius: 2
|
|
2196
|
+
}),
|
|
2197
|
+
meta,
|
|
2198
|
+
title,
|
|
2199
|
+
excerpt,
|
|
2200
|
+
more
|
|
2201
|
+
], 'post');
|
|
2202
|
+
return tree.add(AI_LAYOUT_LISTING_ELEMENTS.posts, {
|
|
2203
|
+
collectionSlug: listing.collectionSlug,
|
|
2204
|
+
entriesLimit: String(limit),
|
|
2205
|
+
spacing: ruled ? '3' : '0'
|
|
2206
|
+
}, ruled ? null : {
|
|
2207
|
+
display: 'grid',
|
|
2208
|
+
gridTemplateColumns: {
|
|
2209
|
+
xs: '1fr',
|
|
2210
|
+
md: 'repeat(3, 1fr)'
|
|
2211
|
+
},
|
|
2212
|
+
gap: 5
|
|
2213
|
+
}, [
|
|
2214
|
+
card
|
|
2215
|
+
], 'posts');
|
|
2216
|
+
}
|
|
1233
2217
|
/** The id the compiled page's root is stored under. */ export const AI_LAYOUT_PAGE_ROOT_ID = CANVAS_ROOT_ELEMENT_ID;
|
|
1234
2218
|
|
|
1235
2219
|
//# sourceMappingURL=ai-layout-compiler.js.map
|