@aglyn/plugins-ai 1.0.0-beta.237 → 1.0.0-beta.238
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-credits-prompt.component.d.ts +11 -4
- package/src/lib/components/ai-credits-prompt.component.js +84 -34
- package/src/lib/components/ai-credits-prompt.component.js.map +1 -1
- package/src/lib/components/ai-job-cancel.component.d.ts +38 -0
- package/src/lib/components/ai-job-cancel.component.js +156 -0
- package/src/lib/components/ai-job-cancel.component.js.map +1 -0
- package/src/lib/components/ai-job-plan.component.js +12 -1
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-jobs-list-page.component.js +141 -72
- package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +22 -2
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-usage-strip.component.d.ts +19 -2
- package/src/lib/components/ai-usage-strip.component.js +40 -9
- package/src/lib/components/ai-usage-strip.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.js +12 -16
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +87 -51
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.js +4 -1
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-cancel.d.ts +71 -0
- package/src/lib/jobs/ai-job-cancel.js +102 -0
- package/src/lib/jobs/ai-job-cancel.js.map +1 -0
- package/src/lib/jobs/ai-job-component-step.js +4 -1
- package/src/lib/jobs/ai-job-component-step.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.js +2 -0
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-form-step.js +4 -1
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +2 -0
- package/src/lib/jobs/ai-job-layout-language.js +13 -1
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.js +6 -1
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.js +8 -0
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.js +12 -1
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +20 -1
- package/src/lib/jobs/ai-job-plan-step.js +49 -9
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-content.d.ts +15 -0
- package/src/lib/jobs/ai-job-site-content.js +66 -7
- package/src/lib/jobs/ai-job-site-content.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.js +4 -1
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-template-step.js +4 -1
- package/src/lib/jobs/ai-job-template-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +37 -12
- package/src/lib/jobs/ai-jobs.js +184 -28
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +143 -70
- package/src/lib/jobs/ai-layout-stock-photos.js +649 -176
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.d.ts +30 -0
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js +220 -0
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.d.ts +27 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js +151 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +6 -0
- package/src/lib/layout-language/ai-layout-compiler.js +304 -8
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +6 -3
- package/src/lib/layout-language/ai-layout-design.js +5 -3
- package/src/lib/layout-language/ai-layout-design.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame.d.ts +12 -0
- package/src/lib/layout-language/ai-layout-frame.js +58 -3
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +13 -1
- package/src/lib/layout-language/ai-layout-listings.js +61 -46
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +8 -0
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/layout-language/ai-layout-storefront.d.ts +82 -0
- package/src/lib/layout-language/ai-layout-storefront.js +223 -0
- package/src/lib/layout-language/ai-layout-storefront.js.map +1 -0
- package/src/lib/model/ai-build-job.d.ts +9 -1
- package/src/lib/model/ai-build-job.js +19 -5
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-build-progress.d.ts +2 -2
- package/src/lib/model/ai-build-progress.js +6 -4
- package/src/lib/model/ai-build-progress.js.map +1 -1
- package/src/lib/model/ai-credit-estimate.d.ts +69 -2
- package/src/lib/model/ai-credit-estimate.js +91 -3
- package/src/lib/model/ai-credit-estimate.js.map +1 -1
- package/src/lib/model/ai-job-cancel-copy.d.ts +44 -0
- package/src/lib/model/ai-job-cancel-copy.js +53 -0
- package/src/lib/model/ai-job-cancel-copy.js.map +1 -0
- package/src/lib/model/ai-job-failure-copy.d.ts +4 -1
- package/src/lib/model/ai-job-failure-copy.js +8 -3
- package/src/lib/model/ai-job-failure-copy.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +20 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-build-progress.js +7 -4
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +19 -2
- package/src/lib/model/ai-site-job.js +29 -8
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.d.ts +4 -1
- package/src/lib/model/ai-site-kinds.js +34 -6
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +37 -1
- package/src/lib/runtime/ai-doctrine-validators.js +151 -6
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +4 -3
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +53 -7
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/server/ai-jobs-cancel.d.ts +13 -5
- package/src/lib/server/ai-jobs-cancel.js +27 -9
- package/src/lib/server/ai-jobs-cancel.js.map +1 -1
- package/src/lib/server/ai-jobs-gate.d.ts +12 -2
- package/src/lib/server/ai-jobs-gate.js +20 -9
- package/src/lib/server/ai-jobs-gate.js.map +1 -1
- package/src/lib/usage/ai-usage-meter.d.ts +2 -1
- package/src/lib/usage/ai-usage-meter.js +17 -1
- package/src/lib/usage/ai-usage-meter.js.map +1 -1
- package/src/lib/usage/ai-usage-wire.d.ts +6 -0
- package/src/lib/usage/ai-usage-wire.js.map +1 -1
- package/src/lib/usage/assist-usage.d.ts +7 -0
- package/src/lib/usage/assist-usage.js +14 -4
- package/src/lib/usage/assist-usage.js.map +1 -1
- package/src/lib/usage/free-ai-credits-left.d.ts +7 -0
- package/src/lib/usage/free-ai-credits-left.js +4 -2
- package/src/lib/usage/free-ai-credits-left.js.map +1 -1
|
@@ -22,8 +22,9 @@ 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
|
+
import { aiLayoutDesignChoices, aiLayoutFamily, aiLayoutGroupVariant } from "./ai-layout-design.js";
|
|
26
26
|
import { AI_LAYOUT_FEATURED_RECORDS, AI_LAYOUT_LISTING_ELEMENTS, aiLayoutListingAt } from "./ai-layout-listings.js";
|
|
27
|
+
import { aiStorefrontItemIcons } from "./ai-layout-storefront.js";
|
|
27
28
|
import { aiLayoutRenamedLabel, aiLayoutResolveLink } from "./ai-layout-links.js";
|
|
28
29
|
import { AI_LAYOUT_FRAMES, AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
29
30
|
/**
|
|
@@ -166,6 +167,9 @@ function compileSection(page, raw, index) {
|
|
|
166
167
|
if (raw.blocks.some((block)=>block.kind === 'quotes') && !blocks.some((block)=>AI_LAYOUT_GROUP_KINDS.has(block.kind) || block.kind === 'component')) {
|
|
167
168
|
page.quotesOnly.push(index);
|
|
168
169
|
}
|
|
170
|
+
// A store's Shop page opens on its grid (AGL-3676): its first section is a
|
|
171
|
+
// short title bar, never a hero, so the products start above the fold.
|
|
172
|
+
if (index === 0 && shopGridAt(page) > 0) return shopTitle(scope, blocks);
|
|
169
173
|
// A section the site's records fill — its catalog, its blog — shows them
|
|
170
174
|
// through the element that keeps them, around the words the design gave it (AGL-3676).
|
|
171
175
|
const listed = aiLayoutListingAt((_page_targets_listings = page.targets.listings) != null ? _page_targets_listings : [], page.targets.pageId, index);
|
|
@@ -385,7 +389,11 @@ function compileSection(page, raw, index) {
|
|
|
385
389
|
}
|
|
386
390
|
/** A band the page has room for: past two brand or two dark bands, a soft one instead. */ function settleBand(page, band, at) {
|
|
387
391
|
if (band !== 'brand' && band !== 'dark') return band;
|
|
388
|
-
|
|
392
|
+
// A storefront keeps one dark band at most (AGL-3676): the beta.237 Willow
|
|
393
|
+
// Wick home ran its text bands dark, and read as big empty dark slabs
|
|
394
|
+
// between the products.
|
|
395
|
+
const most = band === 'dark' && page.design && aiLayoutFamily(page.design.input.kind) === 'retail' ? 1 : AI_LAYOUT_MAX_STRONG_BANDS;
|
|
396
|
+
if (page.strong[band] >= most) {
|
|
389
397
|
page.settled.push({
|
|
390
398
|
at: `${at}.band`,
|
|
391
399
|
what: `a third ${band} band drawn soft`
|
|
@@ -1054,11 +1062,21 @@ function group(scope, block, room) {
|
|
|
1054
1062
|
const placed = componentOf(scope.page.targets, block.to);
|
|
1055
1063
|
if (placed) return instances(scope, placed, items, perRow);
|
|
1056
1064
|
const design = scope.page.design;
|
|
1065
|
+
const retail = !!design && aiLayoutFamily(design.input.kind) === 'retail';
|
|
1066
|
+
// A store's making, shown: its steps as pictures over their words (AGL-3676),
|
|
1067
|
+
// where the page has the pictures for them.
|
|
1068
|
+
if (retail && block.kind === 'steps' && room === 'full' && items.length >= 2 && items.length <= 4 && picturesLeft(scope.page) >= items.length) {
|
|
1069
|
+
const drawn = designedGroup(scope, 'articles', items, room);
|
|
1070
|
+
if (drawn) return drawn;
|
|
1071
|
+
}
|
|
1057
1072
|
if (rule1(scope)) {
|
|
1058
1073
|
var _scope_words;
|
|
1059
1074
|
// Picture cards the design draws are the compiler's, not a block typed out
|
|
1060
|
-
// by hand (`repeatsCompiled`, AGL-3660)
|
|
1075
|
+
// by hand (`repeatsCompiled`, AGL-3660), and so are a storefront's icon
|
|
1076
|
+
// columns (AGL-3676): the beta.237 Willow Wick home, on a paid plan, drew
|
|
1077
|
+
// every other group compact — four bands of a title and a sentence.
|
|
1061
1078
|
const variant = design && block.kind === 'cards' && block.style !== 'quiet' ? aiLayoutGroupVariant(design.input, design.choices, (_scope_words = scope.words) != null ? _scope_words : '') : null;
|
|
1079
|
+
if (variant === 'icons') return iconColumns(scope, items, room);
|
|
1062
1080
|
const pictured = (variant === 'pictures' || variant === 'articles') && room === 'full' && picturesLeft(scope.page) >= items.length;
|
|
1063
1081
|
return pictured && designedGroup(scope, variant, items, room) || compactGroup(scope, block, items, perRow);
|
|
1064
1082
|
}
|
|
@@ -1457,6 +1475,7 @@ function instances(scope, placed, items, perRow) {
|
|
|
1457
1475
|
flow[lead] = design.choices.hero === 'split' ? title : _extends({}, title, {
|
|
1458
1476
|
style: 'large'
|
|
1459
1477
|
});
|
|
1478
|
+
sellingHero(scope, flow);
|
|
1460
1479
|
const given = images[0] ? aiLayoutFitText(images[0].text, 'alt') : '';
|
|
1461
1480
|
return hero(scope, raw, flow, given ? {
|
|
1462
1481
|
alt: given,
|
|
@@ -1859,6 +1878,7 @@ function instances(scope, placed, items, perRow) {
|
|
|
1859
1878
|
variant: type
|
|
1860
1879
|
}, muted(scope), null, 'text') : null;
|
|
1861
1880
|
if (variant === 'cards') return null;
|
|
1881
|
+
if (variant === 'icons') return iconColumns(scope, items, room);
|
|
1862
1882
|
const pictured = variant === 'pictures' || variant === 'articles';
|
|
1863
1883
|
if (variant === 'ruled' || pictured && (room !== 'full' || picturesLeft(page) < items.length)) {
|
|
1864
1884
|
const perRow = across(items.length, room, 'cards');
|
|
@@ -1944,12 +1964,16 @@ function instances(scope, placed, items, perRow) {
|
|
|
1944
1964
|
// A portfolio's or a photographer's gallery opens in a lightbox, its
|
|
1945
1965
|
// pictures one gallery with the item's title as each caption (AGL-3717).
|
|
1946
1966
|
const opens = variant === 'pictures' && aiOpensGalleriesInLightbox(page);
|
|
1967
|
+
// A store's collection tiles open its Shop page (AGL-3676).
|
|
1968
|
+
const shop = variant === 'pictures' && !opens && aiLayoutFamily(design.input.kind) === 'retail' ? shopPageOf(page) : null;
|
|
1947
1969
|
const photo = designImage(scope, {
|
|
1948
1970
|
alt: standInAlt(scope, item.title || item.text),
|
|
1949
1971
|
given: false
|
|
1950
1972
|
}, _extends({
|
|
1951
1973
|
width: '100%'
|
|
1952
|
-
}, opens ? lightboxProps(scope, item.title) : {}
|
|
1974
|
+
}, opens ? lightboxProps(scope, item.title) : {}, shop ? {
|
|
1975
|
+
screenId: shop
|
|
1976
|
+
} : {}), {
|
|
1953
1977
|
aspectRatio: {
|
|
1954
1978
|
xs: '4 / 3',
|
|
1955
1979
|
md: aspect
|
|
@@ -2028,6 +2052,11 @@ function listingSection(scope, blocks, placed) {
|
|
|
2028
2052
|
var _page_plan_sections_index_name, _page_plan_sections_index, _page_options_sectionIds;
|
|
2029
2053
|
const { page, index, at } = scope;
|
|
2030
2054
|
const { listing, role } = placed;
|
|
2055
|
+
if (listing.kind === 'reviews') return reviewsSection(scope, blocks);
|
|
2056
|
+
if (listing.kind === 'signup') return signupSection(scope, blocks);
|
|
2057
|
+
// The grid straight under a Shop page's title bar opens on the products:
|
|
2058
|
+
// the title bar already heads the page (AGL-3676).
|
|
2059
|
+
const underTitle = listing.kind === 'products' && role === 'index' && index === 1 && shopGridAt(page) === 1;
|
|
2031
2060
|
const left = blocks.filter((block)=>LISTING_REPLACES.has(block.kind));
|
|
2032
2061
|
if (left.length) {
|
|
2033
2062
|
page.settled.push({
|
|
@@ -2035,7 +2064,7 @@ function listingSection(scope, blocks, placed) {
|
|
|
2035
2064
|
what: `${left.map((block)=>block.kind).join(', ')} left out: the section lists the site's own ${listing.kind}`
|
|
2036
2065
|
});
|
|
2037
2066
|
}
|
|
2038
|
-
const kept = blocks.filter((block)=>!LISTING_REPLACES.has(block.kind)).map((_0)=>{
|
|
2067
|
+
const kept = underTitle ? [] : blocks.filter((block)=>!LISTING_REPLACES.has(block.kind)).map((_0)=>{
|
|
2039
2068
|
let { col: _col } = _0, block = _object_without_properties_loose(_0, [
|
|
2040
2069
|
"col"
|
|
2041
2070
|
]);
|
|
@@ -2049,7 +2078,7 @@ function listingSection(scope, blocks, placed) {
|
|
|
2049
2078
|
all
|
|
2050
2079
|
];
|
|
2051
2080
|
}
|
|
2052
|
-
if (!words.some((block)=>speaksHeading(scope, block))) {
|
|
2081
|
+
if (!underTitle && !words.some((block)=>speaksHeading(scope, block))) {
|
|
2053
2082
|
var _page_plan_sections_index1;
|
|
2054
2083
|
// Every band of records is headed: the plan's name for it, or on a first section the page's title.
|
|
2055
2084
|
words.unshift({
|
|
@@ -2102,7 +2131,13 @@ function listingSection(scope, blocks, placed) {
|
|
|
2102
2131
|
} : {}), null, parts, 'content');
|
|
2103
2132
|
const container = tree.add('muiContainer', {
|
|
2104
2133
|
maxWidth: 'lg'
|
|
2105
|
-
}, {
|
|
2134
|
+
}, underTitle ? {
|
|
2135
|
+
pt: {
|
|
2136
|
+
xs: 2,
|
|
2137
|
+
md: 3
|
|
2138
|
+
},
|
|
2139
|
+
pb: _extends({}, SECTION_PADDING)
|
|
2140
|
+
} : {
|
|
2106
2141
|
py: index === 0 ? _extends({}, HERO_PADDING) : _extends({}, SECTION_PADDING)
|
|
2107
2142
|
}, [
|
|
2108
2143
|
content
|
|
@@ -2113,10 +2148,268 @@ function listingSection(scope, blocks, placed) {
|
|
|
2113
2148
|
ariaLabel: sectionLabel(name, index)
|
|
2114
2149
|
}, scope.band === 'dark' ? {
|
|
2115
2150
|
colorScheme: 'dark'
|
|
2116
|
-
} : {}), bandSx(scope.band), [
|
|
2151
|
+
} : {}), underTitle ? null : bandSx(scope.band), [
|
|
2117
2152
|
container
|
|
2118
2153
|
], 'section', (_ref = (_page_options_sectionIds = page.options.sectionIds) == null ? void 0 : _page_options_sectionIds[index]) != null ? _ref : sectionIdOf(index));
|
|
2119
2154
|
}
|
|
2155
|
+
/** What a store's reviews are headed with where neither the design nor the plan says. */ export const AI_LAYOUT_REVIEWS_HEADING = 'What our customers say';
|
|
2156
|
+
/**
|
|
2157
|
+
* A store's own customer reviews (AGL-3676): the commerce plugin's Product
|
|
2158
|
+
* reviews in its store-wide scope, carrying the section's heading itself.
|
|
2159
|
+
* It lists approved reviews with their star ratings, and on a published page
|
|
2160
|
+
* with none — every store that just opened — it shows nothing, heading and
|
|
2161
|
+
* all, so the band takes no room until a shopper has written one. No review
|
|
2162
|
+
* is ever written here: the design's quotes, if it gave any, were left out.
|
|
2163
|
+
*/ function reviewsSection(scope, blocks) {
|
|
2164
|
+
var _page_plan_sections_index;
|
|
2165
|
+
const { page, index, at } = scope;
|
|
2166
|
+
const tree = page.tree;
|
|
2167
|
+
const given = blocks.find((block)=>speaksHeading(scope, block));
|
|
2168
|
+
const heading = aiLayoutWords(given == null ? void 0 : given.text, 'heading', page.targets.facts) || aiLayoutFitText((_page_plan_sections_index = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index.name, 'heading') || AI_LAYOUT_REVIEWS_HEADING;
|
|
2169
|
+
page.settled.push({
|
|
2170
|
+
at,
|
|
2171
|
+
what: "the store's own reviews placed: shown once shoppers leave them, never written for them"
|
|
2172
|
+
});
|
|
2173
|
+
const id = tree.add(AI_LAYOUT_LISTING_ELEMENTS.reviews, {
|
|
2174
|
+
scope: 'store',
|
|
2175
|
+
heading,
|
|
2176
|
+
maxItems: String(AI_LAYOUT_FEATURED_RECORDS.reviews)
|
|
2177
|
+
}, // The padding is the element's, so a store with no reviews yet keeps no empty band.
|
|
2178
|
+
{
|
|
2179
|
+
py: _extends({}, SECTION_PADDING)
|
|
2180
|
+
}, null, 'reviews');
|
|
2181
|
+
// The reviews are what the section shows: its shoppers' to write.
|
|
2182
|
+
noted(scope, [
|
|
2183
|
+
id,
|
|
2184
|
+
id
|
|
2185
|
+
]);
|
|
2186
|
+
const container = tree.add('muiContainer', {
|
|
2187
|
+
maxWidth: 'lg'
|
|
2188
|
+
}, null, [
|
|
2189
|
+
id
|
|
2190
|
+
], 'container');
|
|
2191
|
+
return designedRoot(scope, [
|
|
2192
|
+
container
|
|
2193
|
+
], bandSx(scope.band), scope.band === 'dark');
|
|
2194
|
+
}
|
|
2195
|
+
/** What a store's sign-up is headed with where neither the design nor the plan says. */ export const AI_LAYOUT_SIGNUP_HEADING = 'Join our newsletter';
|
|
2196
|
+
/**
|
|
2197
|
+
* A store's newsletter sign-up (AGL-3676): the design's heading and words
|
|
2198
|
+
* beside the commerce plugin's Newsletter signup field, or over it on a
|
|
2199
|
+
* centered band. Any form or button the design drew for it is the field's.
|
|
2200
|
+
*/ function signupSection(scope, blocks) {
|
|
2201
|
+
const { page, index, at } = scope;
|
|
2202
|
+
const tree = page.tree;
|
|
2203
|
+
const flow = blocks.filter((block)=>WORD_KINDS.has(block.kind) && block.kind !== 'button').map((_0)=>{
|
|
2204
|
+
let { col: _col } = _0, block = _object_without_properties_loose(_0, [
|
|
2205
|
+
"col"
|
|
2206
|
+
]);
|
|
2207
|
+
return block;
|
|
2208
|
+
});
|
|
2209
|
+
if (!flow.some((block)=>speaksHeading(scope, block))) {
|
|
2210
|
+
var _page_plan_sections_index;
|
|
2211
|
+
flow.unshift({
|
|
2212
|
+
kind: 'heading',
|
|
2213
|
+
text: ((_page_plan_sections_index = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index.name) || AI_LAYOUT_SIGNUP_HEADING
|
|
2214
|
+
});
|
|
2215
|
+
}
|
|
2216
|
+
page.settled.push({
|
|
2217
|
+
at,
|
|
2218
|
+
what: "the store's newsletter sign-up placed"
|
|
2219
|
+
});
|
|
2220
|
+
const field = tree.add(AI_LAYOUT_LISTING_ELEMENTS.signup, {
|
|
2221
|
+
buttonLabel: 'Subscribe'
|
|
2222
|
+
}, null, null, 'signup');
|
|
2223
|
+
noted(scope, [
|
|
2224
|
+
field,
|
|
2225
|
+
field
|
|
2226
|
+
]);
|
|
2227
|
+
const words = compileFlow(scope, flow, scope.centered ? 'full' : 'half');
|
|
2228
|
+
const body = scope.centered ? tree.add('muiStack', {
|
|
2229
|
+
spacing: '4',
|
|
2230
|
+
alignItems: 'center'
|
|
2231
|
+
}, null, [
|
|
2232
|
+
words,
|
|
2233
|
+
tree.add('muiContainer', {
|
|
2234
|
+
maxWidth: 'sm',
|
|
2235
|
+
disableGutters: true
|
|
2236
|
+
}, null, [
|
|
2237
|
+
field
|
|
2238
|
+
], 'measure')
|
|
2239
|
+
], 'content') : designRow(scope, [
|
|
2240
|
+
...words ? [
|
|
2241
|
+
{
|
|
2242
|
+
id: words,
|
|
2243
|
+
size: 'xs:12 md:6'
|
|
2244
|
+
}
|
|
2245
|
+
] : [],
|
|
2246
|
+
{
|
|
2247
|
+
id: field,
|
|
2248
|
+
size: 'xs:12 md:6'
|
|
2249
|
+
}
|
|
2250
|
+
], '6');
|
|
2251
|
+
const container = tree.add('muiContainer', {
|
|
2252
|
+
maxWidth: 'lg'
|
|
2253
|
+
}, {
|
|
2254
|
+
py: _extends({}, SECTION_PADDING)
|
|
2255
|
+
}, [
|
|
2256
|
+
body
|
|
2257
|
+
], 'container');
|
|
2258
|
+
return designedRoot(scope, [
|
|
2259
|
+
container
|
|
2260
|
+
], bandSx(scope.band), scope.band === 'dark');
|
|
2261
|
+
}
|
|
2262
|
+
/** A store's Shop page's grid section on this page, by plan index; -1 where this page is not its Shop page. */ function shopGridAt(page) {
|
|
2263
|
+
var _page_targets_listings, _ref;
|
|
2264
|
+
var _products_placements_find;
|
|
2265
|
+
const products = ((_page_targets_listings = page.targets.listings) != null ? _page_targets_listings : []).find((listing)=>listing.kind === 'products');
|
|
2266
|
+
return (_ref = products == null ? void 0 : (_products_placements_find = products.placements.find((placement)=>placement.role === 'index' && placement.screenId === page.targets.pageId)) == null ? void 0 : _products_placements_find.section) != null ? _ref : -1;
|
|
2267
|
+
}
|
|
2268
|
+
/** A store's Shop page, by its id, where this page is another page of the store; `null` otherwise. */ function shopPageOf(page) {
|
|
2269
|
+
var _page_targets_listings;
|
|
2270
|
+
var _products_placements_find;
|
|
2271
|
+
const products = ((_page_targets_listings = page.targets.listings) != null ? _page_targets_listings : []).find((listing)=>listing.kind === 'products');
|
|
2272
|
+
const shop = products == null ? void 0 : (_products_placements_find = products.placements.find((placement)=>placement.role === 'index')) == null ? void 0 : _products_placements_find.screenId;
|
|
2273
|
+
return shop && shop !== page.targets.pageId && page.targets.pages.some((entry)=>entry.id === shop) ? shop : null;
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2276
|
+
* A Shop page's opening, as a storefront's collection page opens (AGL-3676):
|
|
2277
|
+
* the page's title and one line under it, on the page's own ground, with
|
|
2278
|
+
* little room around them — no photo and no buttons — so the grid that
|
|
2279
|
+
* follows starts above the fold. The beta.237 Willow Wick /shop opened on a
|
|
2280
|
+
* tall candle photo and its words, the products below the fold.
|
|
2281
|
+
*/ function shopTitle(scope, blocks) {
|
|
2282
|
+
var _ref;
|
|
2283
|
+
const { page, at } = scope;
|
|
2284
|
+
const left = blocks.filter((block)=>![
|
|
2285
|
+
'eyebrow',
|
|
2286
|
+
'heading',
|
|
2287
|
+
'lede',
|
|
2288
|
+
'text'
|
|
2289
|
+
].includes(block.kind));
|
|
2290
|
+
if (left.length) {
|
|
2291
|
+
page.settled.push({
|
|
2292
|
+
at,
|
|
2293
|
+
what: `${left.map((block)=>block.kind).join(', ')} left out: a Shop page opens on its title and its grid`
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
const heading = blocks.find((block)=>speaksHeading(scope, block));
|
|
2297
|
+
const line = blocks.find((block)=>block.kind === 'lede' || block.kind === 'text');
|
|
2298
|
+
const eyebrow = blocks.find((block)=>block.kind === 'eyebrow');
|
|
2299
|
+
const flow = [
|
|
2300
|
+
...eyebrow ? [
|
|
2301
|
+
eyebrow
|
|
2302
|
+
] : [],
|
|
2303
|
+
{
|
|
2304
|
+
kind: 'heading',
|
|
2305
|
+
text: (_ref = heading == null ? void 0 : heading.text) != null ? _ref : page.plan.title
|
|
2306
|
+
},
|
|
2307
|
+
...line ? [
|
|
2308
|
+
{
|
|
2309
|
+
kind: 'lede',
|
|
2310
|
+
text: line.text
|
|
2311
|
+
}
|
|
2312
|
+
] : []
|
|
2313
|
+
];
|
|
2314
|
+
scope.band = 'plain';
|
|
2315
|
+
scope.centered = false;
|
|
2316
|
+
page.settled.push({
|
|
2317
|
+
at,
|
|
2318
|
+
what: "drawn as the Shop page's title bar, the grid under it"
|
|
2319
|
+
});
|
|
2320
|
+
const words = compileFlow(scope, flow, 'half');
|
|
2321
|
+
const container = page.tree.add('muiContainer', {
|
|
2322
|
+
maxWidth: 'lg'
|
|
2323
|
+
}, {
|
|
2324
|
+
pt: {
|
|
2325
|
+
xs: 5,
|
|
2326
|
+
md: 7
|
|
2327
|
+
},
|
|
2328
|
+
pb: {
|
|
2329
|
+
xs: 1,
|
|
2330
|
+
md: 2
|
|
2331
|
+
}
|
|
2332
|
+
}, [
|
|
2333
|
+
words
|
|
2334
|
+
], 'container');
|
|
2335
|
+
return designedRoot(scope, [
|
|
2336
|
+
container
|
|
2337
|
+
], null, false);
|
|
2338
|
+
}
|
|
2339
|
+
/**
|
|
2340
|
+
* A storefront's home hero sells (AGL-3676): it opens the shop. Where the
|
|
2341
|
+
* design gave it no button to the Shop page, "Shop all" leads its buttons,
|
|
2342
|
+
* and any other primary button steps back to secondary beside it.
|
|
2343
|
+
*/ function sellingHero(scope, flow) {
|
|
2344
|
+
const design = scope.page.design;
|
|
2345
|
+
if (!(design == null ? void 0 : design.input.home) || aiLayoutFamily(design.input.kind) !== 'retail') return;
|
|
2346
|
+
const shop = shopPageOf(scope.page);
|
|
2347
|
+
if (!shop || flow.some((block)=>block.kind === 'button' && block.to === `page:${shop}`)) return;
|
|
2348
|
+
const firstButton = flow.findIndex((block)=>block.kind === 'button');
|
|
2349
|
+
for (const [at, block] of flow.entries()){
|
|
2350
|
+
var _block_style;
|
|
2351
|
+
if (block.kind === 'button' && ((_block_style = block.style) != null ? _block_style : 'primary') === 'primary') flow[at] = _extends({}, block, {
|
|
2352
|
+
style: 'secondary'
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
const shopAll = {
|
|
2356
|
+
kind: 'button',
|
|
2357
|
+
text: AI_LAYOUT_SHOP_ALL,
|
|
2358
|
+
to: `page:${shop}`,
|
|
2359
|
+
style: 'primary'
|
|
2360
|
+
};
|
|
2361
|
+
if (firstButton === -1) flow.push(shopAll);
|
|
2362
|
+
else flow.splice(firstButton, 0, shopAll);
|
|
2363
|
+
scope.page.settled.push({
|
|
2364
|
+
at: scope.at,
|
|
2365
|
+
what: `the hero opens the shop: "${AI_LAYOUT_SHOP_ALL}" leads its buttons`
|
|
2366
|
+
});
|
|
2367
|
+
}
|
|
2368
|
+
/** The button a storefront's hero opens its shop with. */ export const AI_LAYOUT_SHOP_ALL = 'Shop all';
|
|
2369
|
+
/**
|
|
2370
|
+
* A storefront's reasons to buy as open columns, each led by an icon over its
|
|
2371
|
+
* title and words (AGL-3676): the icon the design named for it, else one its
|
|
2372
|
+
* words suggest (shipping a truck, returns the arrows, small batch the hand),
|
|
2373
|
+
* never the same twice in a row. One style key an element, so a row repeats
|
|
2374
|
+
* no multi-key inline style (rule 16).
|
|
2375
|
+
*/ function iconColumns(scope, items, room) {
|
|
2376
|
+
const { page } = scope;
|
|
2377
|
+
const tree = page.tree;
|
|
2378
|
+
const facts = page.targets.facts;
|
|
2379
|
+
const iconWords = aiStorefrontItemIcons(items, (word)=>!!aiIconOfWord(word));
|
|
2380
|
+
const perRow = across(items.length, room, 'cards');
|
|
2381
|
+
const textAlign = scope.centered ? {
|
|
2382
|
+
align: 'center'
|
|
2383
|
+
} : {};
|
|
2384
|
+
page.settled.push({
|
|
2385
|
+
at: scope.at,
|
|
2386
|
+
what: `${items.length} items drawn as icon columns`
|
|
2387
|
+
});
|
|
2388
|
+
const ids = items.map((item, position)=>{
|
|
2389
|
+
var _aiIconOfWord;
|
|
2390
|
+
const icon = (_aiIconOfWord = aiIconOfWord(iconWords[position])) != null ? _aiIconOfWord : AI_ICON_LIBRARY.star;
|
|
2391
|
+
return tree.add('muiStack', _extends({
|
|
2392
|
+
spacing: '1.5'
|
|
2393
|
+
}, scope.centered ? {
|
|
2394
|
+
alignItems: 'center'
|
|
2395
|
+
} : {}), null, [
|
|
2396
|
+
tree.add(AI_ICON_COMPONENT_ID, {
|
|
2397
|
+
iconId: icon.id,
|
|
2398
|
+
size: '32'
|
|
2399
|
+
}, accent(scope), null, 'icon'),
|
|
2400
|
+
item.title.trim() ? tree.add('muiTypography', _extends({
|
|
2401
|
+
children: aiLayoutWords(item.title, 'itemTitle', facts),
|
|
2402
|
+
variant: 'h6',
|
|
2403
|
+
component: itemElement(scope)
|
|
2404
|
+
}, textAlign), null, null, 'title') : null,
|
|
2405
|
+
item.text.trim() ? tree.add('muiTypography', _extends({
|
|
2406
|
+
children: aiLayoutWords(item.text, 'itemText', facts),
|
|
2407
|
+
variant: 'body2'
|
|
2408
|
+
}, textAlign), muted(scope), null, 'text') : null
|
|
2409
|
+
], 'iconItem');
|
|
2410
|
+
});
|
|
2411
|
+
return layOut(scope, noted(scope, ids), perRow, '5', 'icons');
|
|
2412
|
+
}
|
|
2120
2413
|
/**
|
|
2121
2414
|
* The element that lists the records, bound to them: the Product grid over
|
|
2122
2415
|
* the site's catalog, or Collection Entries over its blog with one post's
|
|
@@ -2157,6 +2450,9 @@ function listingSection(scope, blocks, placed) {
|
|
|
2157
2450
|
showCategories: true
|
|
2158
2451
|
}, {
|
|
2159
2452
|
cardStyle: 'photo',
|
|
2453
|
+
// A storefront's cards sell from the grid (AGL-3676): Add to cart on a
|
|
2454
|
+
// product with one variant, Choose options on one with several.
|
|
2455
|
+
quickAdd: true,
|
|
2160
2456
|
// A store that opens before its first products are in says so, with a
|
|
2161
2457
|
// way to hear when they land (AGL-3676): never placeholder products.
|
|
2162
2458
|
emptyTitle: AI_LAYOUT_STORE_EMPTY.title,
|