@aglyn/plugins-ai 1.0.0-beta.234 → 1.0.0-beta.236

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.d.ts +25 -0
  3. package/src/lib/activity/ai-activity-actions.js +85 -4
  4. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  5. package/src/lib/components/ai-brief-dialog.component.js +46 -2
  6. package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
  7. package/src/lib/components/ai-campaign-create.component.js +1 -1
  8. package/src/lib/components/ai-campaign-create.component.js.map +1 -1
  9. package/src/lib/components/ai-credits-card.component.js +3 -3
  10. package/src/lib/components/ai-credits-card.component.js.map +1 -1
  11. package/src/lib/components/ai-crm-email-draft.component.js +1 -1
  12. package/src/lib/components/ai-crm-email-draft.component.js.map +1 -1
  13. package/src/lib/components/ai-crm-import-mapping.component.js +1 -1
  14. package/src/lib/components/ai-crm-import-mapping.component.js.map +1 -1
  15. package/src/lib/components/ai-crm-record-card.component.js +1 -1
  16. package/src/lib/components/ai-crm-record-card.component.js.map +1 -1
  17. package/src/lib/components/ai-describe-automation.component.js +4 -2
  18. package/src/lib/components/ai-describe-automation.component.js.map +1 -1
  19. package/src/lib/components/ai-describe-org-automation.component.js +1 -1
  20. package/src/lib/components/ai-describe-org-automation.component.js.map +1 -1
  21. package/src/lib/components/ai-experiment-cards.component.js +2 -2
  22. package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
  23. package/src/lib/components/ai-explain-automation.component.js +1 -1
  24. package/src/lib/components/ai-explain-automation.component.js.map +1 -1
  25. package/src/lib/components/ai-insight-card.component.js +3 -1
  26. package/src/lib/components/ai-insight-card.component.js.map +1 -1
  27. package/src/lib/components/ai-jobs-list-page.component.d.ts +6 -1
  28. package/src/lib/components/ai-jobs-list-page.component.js +15 -2
  29. package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
  30. package/src/lib/components/ai-logic.component.js +5 -3
  31. package/src/lib/components/ai-logic.component.js.map +1 -1
  32. package/src/lib/components/ai-media-create.component.js +88 -16
  33. package/src/lib/components/ai-media-create.component.js.map +1 -1
  34. package/src/lib/components/ai-model-selector.component.js +8 -0
  35. package/src/lib/components/ai-model-selector.component.js.map +1 -1
  36. package/src/lib/components/ai-overlay-cards.component.js +2 -2
  37. package/src/lib/components/ai-overlay-cards.component.js.map +1 -1
  38. package/src/lib/components/ai-product-copy-card.component.js +2 -1
  39. package/src/lib/components/ai-product-copy-card.component.js.map +1 -1
  40. package/src/lib/components/ai-products-hub-card.component.js +2 -1
  41. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  42. package/src/lib/components/ai-revise-automation.component.js +1 -1
  43. package/src/lib/components/ai-revise-automation.component.js.map +1 -1
  44. package/src/lib/components/ai-seo-fields-card.component.js +7 -3
  45. package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
  46. package/src/lib/components/ai-site-batch-card.component.js +7 -4
  47. package/src/lib/components/ai-site-batch-card.component.js.map +1 -1
  48. package/src/lib/components/ai-site-build-page.component.js +7 -3
  49. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  50. package/src/lib/components/ai-site-seo-start-card.component.js +7 -4
  51. package/src/lib/components/ai-site-seo-start-card.component.js.map +1 -1
  52. package/src/lib/components/ai-site-start-card.component.js +62 -29
  53. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  54. package/src/lib/components/ai-theme-proposal-card.component.js +1 -0
  55. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
  56. package/src/lib/components/ai-upsell-dialog.component.js +17 -3
  57. package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
  58. package/src/lib/components/ai-usage-strip.component.js +13 -2
  59. package/src/lib/components/ai-usage-strip.component.js.map +1 -1
  60. package/src/lib/components/assist-build-card.component.js +20 -3
  61. package/src/lib/components/assist-build-card.component.js.map +1 -1
  62. package/src/lib/components/assist-jobs-drawer.component.js +7 -1
  63. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  64. package/src/lib/components/billing-ai-allotments.component.js +2 -2
  65. package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
  66. package/src/lib/components/billing-ai-top-users.component.js +1 -0
  67. package/src/lib/components/billing-ai-top-users.component.js.map +1 -1
  68. package/src/lib/components/billing-assist-overage-card.component.js +2 -2
  69. package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
  70. package/src/lib/components/host-ai-allotments.component.js +2 -2
  71. package/src/lib/components/host-ai-allotments.component.js.map +1 -1
  72. package/src/lib/components/member-ai-allotment-card.component.js +2 -2
  73. package/src/lib/components/member-ai-allotment-card.component.js.map +1 -1
  74. package/src/lib/components/staff-org-ai-card.component.js +1 -0
  75. package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
  76. package/src/lib/components/staff-org-ai-conversations.component.d.ts +9 -3
  77. package/src/lib/components/staff-org-ai-conversations.component.js +174 -83
  78. package/src/lib/components/staff-org-ai-conversations.component.js.map +1 -1
  79. package/src/lib/components/staff-user-ai-usage-card.component.js +2 -1
  80. package/src/lib/components/staff-user-ai-usage-card.component.js.map +1 -1
  81. package/src/lib/jobs/ai-job-layout-language.js +4 -1
  82. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  83. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +12 -0
  84. package/src/lib/jobs/ai-job-layout-site-pages.js +20 -0
  85. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  86. package/src/lib/jobs/ai-job-page-language.d.ts +10 -1
  87. package/src/lib/jobs/ai-job-page-language.js +41 -8
  88. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  89. package/src/lib/jobs/ai-job-page-step.js +14 -3
  90. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  91. package/src/lib/jobs/ai-job-site-content.d.ts +75 -7
  92. package/src/lib/jobs/ai-job-site-content.js +205 -32
  93. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  94. package/src/lib/jobs/ai-job-site-step.d.ts +8 -0
  95. package/src/lib/jobs/ai-job-site-step.js +61 -12
  96. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  97. package/src/lib/layout-language/ai-layout-compiler.d.ts +8 -0
  98. package/src/lib/layout-language/ai-layout-compiler.js +308 -10
  99. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  100. package/src/lib/layout-language/ai-layout-design.d.ts +7 -0
  101. package/src/lib/layout-language/ai-layout-design.js +23 -11
  102. package/src/lib/layout-language/ai-layout-design.js.map +1 -1
  103. package/src/lib/layout-language/ai-layout-frame.d.ts +6 -0
  104. package/src/lib/layout-language/ai-layout-frame.js +12 -3
  105. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  106. package/src/lib/layout-language/ai-layout-gaps.js +18 -2
  107. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
  108. package/src/lib/layout-language/ai-layout-links.d.ts +26 -1
  109. package/src/lib/layout-language/ai-layout-links.js +24 -4
  110. package/src/lib/layout-language/ai-layout-links.js.map +1 -1
  111. package/src/lib/layout-language/ai-layout-listings.d.ts +125 -0
  112. package/src/lib/layout-language/ai-layout-listings.js +187 -0
  113. package/src/lib/layout-language/ai-layout-listings.js.map +1 -0
  114. package/src/lib/model/ai-site-build-progress.js +27 -12
  115. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  116. package/src/lib/model/ai-site-job.d.ts +33 -8
  117. package/src/lib/model/ai-site-job.js +38 -18
  118. package/src/lib/model/ai-site-job.js.map +1 -1
  119. package/src/lib/model/ai-site-kinds.d.ts +30 -8
  120. package/src/lib/model/ai-site-kinds.js +731 -117
  121. package/src/lib/model/ai-site-kinds.js.map +1 -1
  122. package/src/lib/model/ai-site-start-seo.d.ts +30 -0
  123. package/src/lib/model/ai-site-start-seo.js +132 -11
  124. package/src/lib/model/ai-site-start-seo.js.map +1 -1
  125. package/src/lib/model/ai-site-start.d.ts +2 -2
  126. package/src/lib/model/ai-site-start.js +3 -3
  127. package/src/lib/model/ai-site-start.js.map +1 -1
  128. package/src/lib/plugin.js +15 -3
  129. package/src/lib/plugin.js.map +1 -1
  130. package/src/lib/runtime/ai-palette.generated.js +13 -3
  131. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  132. package/src/lib/server/ai-admin-conversations.d.ts +9 -0
  133. package/src/lib/server/ai-admin-conversations.js +151 -9
  134. package/src/lib/server/ai-admin-conversations.js.map +1 -1
  135. package/src/lib/usage/staff-org-ai-conversations.d.ts +23 -0
  136. package/src/lib/usage/staff-org-ai-conversations.js +45 -0
  137. package/src/lib/usage/staff-org-ai-conversations.js.map +1 -1
@@ -23,8 +23,17 @@ 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
25
  import { aiLayoutDesignChoices, aiLayoutGroupVariant } from "./ai-layout-design.js";
26
- import { aiLayoutResolveLink } from "./ai-layout-links.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";
27
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
+ }
28
37
  /** A section root's id where the caller gives none. */ function sectionIdOf(index) {
29
38
  return `section-${index + 1}`;
30
39
  }
@@ -77,7 +86,8 @@ const componentOf = (targets, id)=>{
77
86
  } : null,
78
87
  pictures: 0,
79
88
  features: 0,
80
- splitAt: -2
89
+ splitAt: -2,
90
+ quotesOnly: []
81
91
  };
82
92
  const roots = plan.sections.map((_, index)=>{
83
93
  var _sections_index;
@@ -95,7 +105,8 @@ const componentOf = (targets, id)=>{
95
105
  sectionRoots: roots,
96
106
  scrollTo: page.scrollTo,
97
107
  settled: page.settled,
98
- itemIds: page.itemIds
108
+ itemIds: page.itemIds,
109
+ quotesOnly: page.quotesOnly
99
110
  };
100
111
  }
101
112
  /** The first icon the design names anywhere, else a sparkle: what an empty picture shows. */ function pageIconOf(sections) {
@@ -114,7 +125,7 @@ const componentOf = (targets, id)=>{
114
125
  }
115
126
  // ── A section ─────────────────────────────────────────────────────────────
116
127
  function compileSection(page, raw, index) {
117
- var _raw_band, _ref, _ref1;
128
+ var _raw_band, _ref, _page_targets_listings, _ref1;
118
129
  var _raw_blocks_find, _page_plan_sections_index, _placedHere_, _page_plan_sections_index_name, _page_plan_sections_index1, _page_options_sectionIds;
119
130
  const at = `sections[${index}]`;
120
131
  const band = settleBand(page, (_raw_band = raw.band) != null ? _raw_band : 'plain', at);
@@ -150,6 +161,15 @@ function compileSection(page, raw, index) {
150
161
  });
151
162
  return false;
152
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);
153
173
  // The site's design draws the sections it has an arrangement for (AGL-3660).
154
174
  if (page.design) {
155
175
  const designed = designSection(scope, raw, blocks);
@@ -332,7 +352,7 @@ function compileSection(page, raw, index) {
332
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}`;
333
353
  return tree.add('section', _extends({
334
354
  element: 'section',
335
- ariaLabel: aiLayoutFitText(name, 'note') || `Section ${index + 1}`
355
+ ariaLabel: sectionLabel(name, index)
336
356
  }, band === 'dark' ? {
337
357
  colorScheme: 'dark'
338
358
  } : {}), bandSx(band), [
@@ -723,16 +743,22 @@ function words(scope, block, place, variant, props, sx) {
723
743
  }
724
744
  function compileButton(scope, block) {
725
745
  var _block_style;
726
- const label = aiLayoutFitText(block.text, 'label');
727
- if (!label) return null;
728
- const destination = aiLayoutResolveLink(block.to, label, scope.link, scope.page.targets);
746
+ const asked = aiLayoutFitText(block.text, 'label');
747
+ if (!asked) return null;
748
+ const destination = aiLayoutResolveLink(block.to, asked, scope.link, scope.page.targets);
729
749
  if (!destination) {
730
750
  scope.page.settled.push({
731
751
  at: scope.at,
732
- what: `the button "${label}" has nowhere to go; left out`
752
+ what: `the button "${asked}" has nowhere to go; left out`
733
753
  });
734
754
  return null;
735
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
+ });
736
762
  const style = (_block_style = block.style) != null ? _block_style : 'primary';
737
763
  // Over a photo, a quiet or outlined button takes the words' own color, as on a brand band.
738
764
  const onBrand = scope.band === 'brand' || !!scope.overPhoto && style !== 'primary';
@@ -1301,7 +1327,7 @@ function instances(scope, placed, items, perRow) {
1301
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}`;
1302
1328
  return page.tree.add('section', _extends({
1303
1329
  element: 'section',
1304
- ariaLabel: aiLayoutFitText(name, 'note') || `Section ${index + 1}`
1330
+ ariaLabel: sectionLabel(name, index)
1305
1331
  }, dark ? {
1306
1332
  colorScheme: 'dark'
1307
1333
  } : {}, index === 0 && scope.overPhoto ? {
@@ -1916,6 +1942,278 @@ function instances(scope, placed, items, perRow) {
1916
1942
  cell.id
1917
1943
  ], 'cell')), variant);
1918
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
+ }
1919
2217
  /** The id the compiled page's root is stored under. */ export const AI_LAYOUT_PAGE_ROOT_ID = CANVAS_ROOT_ELEMENT_ID;
1920
2218
 
1921
2219
  //# sourceMappingURL=ai-layout-compiler.js.map