@aglyn/plugins-ai 1.0.0-beta.291 → 1.0.0-beta.293

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 (149) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-site-import-job.component.js +5 -4
  3. package/src/lib/components/ai-site-import-job.component.js.map +1 -1
  4. package/src/lib/components/ai-site-import-start.component.js +3 -3
  5. package/src/lib/components/ai-site-import-start.component.js.map +1 -1
  6. package/src/lib/components/ai-site-start-card.component.d.ts +1 -1
  7. package/src/lib/components/ai-site-start-card.component.js +129 -29
  8. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  9. package/src/lib/components/ai-site-start-steps.component.d.ts +15 -3
  10. package/src/lib/components/ai-site-start-steps.component.js +42 -25
  11. package/src/lib/components/ai-site-start-steps.component.js.map +1 -1
  12. package/src/lib/components/ai-site-style-previews.d.ts +17 -0
  13. package/src/lib/components/ai-site-style-previews.js +26 -95
  14. package/src/lib/components/ai-site-style-previews.js.map +1 -1
  15. package/src/lib/declarations.server.js +22 -0
  16. package/src/lib/declarations.server.js.map +1 -1
  17. package/src/lib/jobs/ai-job-import-step.d.ts +21 -2
  18. package/src/lib/jobs/ai-job-import-step.js +179 -49
  19. package/src/lib/jobs/ai-job-import-step.js.map +1 -1
  20. package/src/lib/jobs/ai-job-layout-language.d.ts +27 -3
  21. package/src/lib/jobs/ai-job-layout-language.js +156 -113
  22. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  23. package/src/lib/jobs/ai-job-layout-step.js +56 -17
  24. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  25. package/src/lib/jobs/ai-job-page-language.d.ts +25 -15
  26. package/src/lib/jobs/ai-job-page-language.js +120 -66
  27. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  28. package/src/lib/jobs/ai-job-page-step.js +27 -7
  29. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  30. package/src/lib/jobs/ai-job-site-datasets.d.ts +12 -4
  31. package/src/lib/jobs/ai-job-site-datasets.js +36 -16
  32. package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
  33. package/src/lib/jobs/ai-jobs.js +6 -2
  34. package/src/lib/jobs/ai-jobs.js.map +1 -1
  35. package/src/lib/jobs/ai-layout-stock-photos.d.ts +50 -1
  36. package/src/lib/jobs/ai-layout-stock-photos.js +586 -35
  37. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
  38. package/src/lib/jobs/ai-site-import-compile.d.ts +147 -0
  39. package/src/lib/jobs/ai-site-import-compile.js +1143 -0
  40. package/src/lib/jobs/ai-site-import-compile.js.map +1 -0
  41. package/src/lib/jobs/ai-site-import-document.d.ts +9 -36
  42. package/src/lib/jobs/ai-site-import-document.js +23 -489
  43. package/src/lib/jobs/ai-site-import-document.js.map +1 -1
  44. package/src/lib/jobs/ai-site-import-look.d.ts +54 -7
  45. package/src/lib/jobs/ai-site-import-look.js +163 -52
  46. package/src/lib/jobs/ai-site-import-look.js.map +1 -1
  47. package/src/lib/jobs/ai-site-import-publish.d.ts +7 -1
  48. package/src/lib/jobs/ai-site-import-publish.js +19 -5
  49. package/src/lib/jobs/ai-site-import-publish.js.map +1 -1
  50. package/src/lib/jobs/ai-site-late-photos.js +4 -2
  51. package/src/lib/jobs/ai-site-late-photos.js.map +1 -1
  52. package/src/lib/jobs/ai-site-publish.d.ts +10 -1
  53. package/src/lib/jobs/ai-site-publish.js +8 -3
  54. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  55. package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.d.ts +23 -0
  56. package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.js +677 -0
  57. package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.js.map +1 -0
  58. package/src/lib/layout-language/ai-layout-compiler.d.ts +26 -0
  59. package/src/lib/layout-language/ai-layout-compiler.js +677 -33
  60. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  61. package/src/lib/layout-language/ai-layout-frame-hollows.js +5 -1
  62. package/src/lib/layout-language/ai-layout-frame-hollows.js.map +1 -1
  63. package/src/lib/layout-language/ai-layout-frame-source.d.ts +196 -0
  64. package/src/lib/layout-language/ai-layout-frame-source.js +726 -0
  65. package/src/lib/layout-language/ai-layout-frame-source.js.map +1 -0
  66. package/src/lib/layout-language/ai-layout-frame.d.ts +22 -0
  67. package/src/lib/layout-language/ai-layout-frame.js +121 -29
  68. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  69. package/src/lib/layout-language/ai-layout-language.d.ts +103 -37
  70. package/src/lib/layout-language/ai-layout-language.js +85 -120
  71. package/src/lib/layout-language/ai-layout-language.js.map +1 -1
  72. package/src/lib/model/ai-credit-estimate.d.ts +11 -7
  73. package/src/lib/model/ai-credit-estimate.js +11 -7
  74. package/src/lib/model/ai-credit-estimate.js.map +1 -1
  75. package/src/lib/model/ai-site-import.d.ts +307 -13
  76. package/src/lib/model/ai-site-import.js +227 -19
  77. package/src/lib/model/ai-site-import.js.map +1 -1
  78. package/src/lib/model/ai-site-look.d.ts +65 -1
  79. package/src/lib/model/ai-site-look.js +141 -23
  80. package/src/lib/model/ai-site-look.js.map +1 -1
  81. package/src/lib/model/ai-site-photos.d.ts +2 -0
  82. package/src/lib/model/ai-site-photos.js.map +1 -1
  83. package/src/lib/model/ai-site-start-steps.d.ts +4 -3
  84. package/src/lib/model/ai-site-start-steps.js +11 -3
  85. package/src/lib/model/ai-site-start-steps.js.map +1 -1
  86. package/src/lib/model/ai-site-start.d.ts +23 -2
  87. package/src/lib/model/ai-site-start.js +25 -3
  88. package/src/lib/model/ai-site-start.js.map +1 -1
  89. package/src/lib/providers/routing.d.ts +11 -0
  90. package/src/lib/providers/routing.js +23 -0
  91. package/src/lib/providers/routing.js.map +1 -1
  92. package/src/lib/runtime/ai-doctrine-validators.d.ts +4 -2
  93. package/src/lib/runtime/ai-doctrine-validators.js +7 -2
  94. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  95. package/src/lib/runtime/ai-icon-library.d.ts +4 -0
  96. package/src/lib/runtime/ai-icon-library.js +4 -0
  97. package/src/lib/runtime/ai-icon-library.js.map +1 -1
  98. package/src/lib/runtime/ai-node-tree.js +5 -1
  99. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  100. package/src/lib/runtime/ai-palette.d.ts +2 -0
  101. package/src/lib/runtime/ai-palette.generated.js +19 -3
  102. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  103. package/src/lib/runtime/ai-palette.js +2 -1
  104. package/src/lib/runtime/ai-palette.js.map +1 -1
  105. package/src/lib/site-import/fixtures/site-layout-recordings.d.ts +50 -0
  106. package/src/lib/site-import/fixtures/site-layout-recordings.js +86 -0
  107. package/src/lib/site-import/fixtures/site-layout-recordings.js.map +1 -0
  108. package/src/lib/site-import/site-import-crawl.d.ts +18 -1
  109. package/src/lib/site-import/site-import-crawl.js +70 -10
  110. package/src/lib/site-import/site-import-crawl.js.map +1 -1
  111. package/src/lib/site-import/site-import-css.d.ts +110 -0
  112. package/src/lib/site-import/site-import-css.js +826 -0
  113. package/src/lib/site-import/site-import-css.js.map +1 -0
  114. package/src/lib/site-import/site-import-html.d.ts +116 -1
  115. package/src/lib/site-import/site-import-html.js +538 -46
  116. package/src/lib/site-import/site-import-html.js.map +1 -1
  117. package/src/lib/site-import/site-import-layout.d.ts +79 -0
  118. package/src/lib/site-import/site-import-layout.js +1608 -0
  119. package/src/lib/site-import/site-import-layout.js.map +1 -0
  120. package/src/lib/site-import/site-import-nav.d.ts +40 -0
  121. package/src/lib/site-import/site-import-nav.js +437 -0
  122. package/src/lib/site-import/site-import-nav.js.map +1 -0
  123. package/src/lib/site-import/site-import-page.d.ts +8 -1
  124. package/src/lib/site-import/site-import-page.js +24 -2
  125. package/src/lib/site-import/site-import-page.js.map +1 -1
  126. package/src/lib/assets/site-styles/beauty.webp +0 -0
  127. package/src/lib/assets/site-styles/blog.webp +0 -0
  128. package/src/lib/assets/site-styles/business.webp +0 -0
  129. package/src/lib/assets/site-styles/coming-soon.webp +0 -0
  130. package/src/lib/assets/site-styles/education.webp +0 -0
  131. package/src/lib/assets/site-styles/events.webp +0 -0
  132. package/src/lib/assets/site-styles/fitness.webp +0 -0
  133. package/src/lib/assets/site-styles/landing.webp +0 -0
  134. package/src/lib/assets/site-styles/music.webp +0 -0
  135. package/src/lib/assets/site-styles/nonprofit.webp +0 -0
  136. package/src/lib/assets/site-styles/personal.webp +0 -0
  137. package/src/lib/assets/site-styles/photography.webp +0 -0
  138. package/src/lib/assets/site-styles/portfolio.webp +0 -0
  139. package/src/lib/assets/site-styles/professional.webp +0 -0
  140. package/src/lib/assets/site-styles/realestate.webp +0 -0
  141. package/src/lib/assets/site-styles/restaurant.webp +0 -0
  142. package/src/lib/assets/site-styles/store.webp +0 -0
  143. package/src/lib/assets/site-styles/studio.webp +0 -0
  144. package/src/lib/assets/site-styles/trades.webp +0 -0
  145. package/src/lib/assets/site-styles/wellness.webp +0 -0
  146. package/src/lib/assets/site-styles/yoga.webp +0 -0
  147. package/src/lib/site-import/site-import-review.d.ts +0 -40
  148. package/src/lib/site-import/site-import-review.js +0 -149
  149. package/src/lib/site-import/site-import-review.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-site-start-steps.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport {\n mdiBookOpenPageVariant,\n mdiBriefcaseOutline,\n mdiCalendarHeart,\n mdiCheck,\n mdiChevronDown,\n mdiCreation,\n mdiHandHeart,\n mdiScaleBalance,\n mdiShopping,\n mdiSilverwareForkKnife,\n mdiViewGridOutline,\n mdiWrench,\n} from '@aglyn/shared-data-mdi'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { OptionCardGrid } from '@aglyn/shared-ui-jsx/components/option-card-grid.component'\nimport { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport { OpeningHoursPicker } from '@aglyn/shared-ui-jsx/components/weekly-hours-picker.component'\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Box,\n Divider,\n LinearProgress,\n List,\n ListItemButton,\n MenuItem,\n Stack,\n Step,\n StepButton,\n StepLabel,\n Stepper,\n TextField,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { Fragment, useId, useState, type ReactNode, type Ref } from 'react'\nimport { aiSiteHoursSentence, aiSiteServiceAreas, aiSiteSocialLinks } from '../model/ai-site-details'\nimport { AI_SITE_FREE_PAGES_NOTE, AI_SITE_SUBMISSION_CHOICES, type AiSiteSubmissions } from '../model/ai-site-job'\nimport { AI_SITE_KINDS } from '../model/ai-site-kinds'\nimport {\n AI_SITE_INSPIRATION_LIMITS,\n AI_SITE_INSPIRATION_MAX,\n AI_SITE_INSPIRATION_PAID_NOTE,\n aiSiteInspirationHost,\n} from '../model/ai-site-inspiration'\nimport {\n AI_SITE_START_TYPES,\n aiSiteStartInspirationTyped,\n aiSiteStartKind,\n type AiSiteStartAnswers,\n type AiSiteStartExtraKey,\n} from '../model/ai-site-start'\nimport {\n AI_SITE_START_MORE_FIELDS,\n AI_SITE_START_STEP_LABELS,\n AI_SITE_START_STEPS,\n aiSiteStartStepIndex,\n type AiSiteStartField,\n type AiSiteStartFieldError,\n type AiSiteStartStep,\n} from '../model/ai-site-start-steps'\nimport type { AiSiteStartTracker } from './ai-site-start-tracking'\nimport { aiSiteStylePreview } from './ai-site-style-previews'\n\n/**\n * The guided start's question steps (AGL-3898), one decision each. Each step\n * draws its own answers and writes them through `answer`, exactly the patch\n * the single form wrote, so the answers object is the same whichever way it\n * was filled in. The dialog around them (`ai-site-start-card.component.tsx`)\n * owns the step, Back and Next, validation and the job.\n */\n\n/** Each part of the guided start links its own section of the Start with AI guide (AGL-3660). */\nexport const START_STEP_HELP = {\n kind: pluginDocsHelp('aiStart', {\n anchor: '#your-business',\n excerpt:\n 'What kind of site it is picks its style and pages; who it is for is who every page and the contact form are written for.',\n }),\n audience: pluginDocsHelp('aiStart', {\n anchor: '#audience',\n excerpt: 'Who the site is for is who every page, every search listing and the contact form are written for. Optional.',\n }),\n review: pluginDocsHelp('aiStart', {\n anchor: '#review',\n excerpt: 'Every answer, each with Edit to change it. Plan my site creates the site, plans it, writes the pages and publishes it.',\n }),\n style: pluginDocsHelp('aiSiteLooks', {\n anchor: '#choose-a-style',\n excerpt:\n 'The style decides the look — theme, colors, fonts, buttons — and which pages the site usually has. Every site gets its own variation.',\n }),\n details: pluginDocsHelp('aiStart', {\n anchor: '#details',\n excerpt:\n 'Your phone number and email, which your pages show, where contact form messages go, how many pages to write, and on paid plans whether to draft a welcome email. All can be changed later.',\n }),\n}\n\n/** The icon on each kind-of-site card: the icon of the style that answer picks. */\nconst START_TYPE_ICONS: Readonly<Record<string, string>> = {\n 'a local service business': mdiBriefcaseOutline.path,\n 'a restaurant or cafe': mdiSilverwareForkKnife.path,\n 'a professional practice': mdiScaleBalance.path,\n 'a trades business': mdiWrench.path,\n 'a shop': mdiShopping.path,\n 'a nonprofit': mdiHandHeart.path,\n 'a personal portfolio': mdiViewGridOutline.path,\n 'an event': mdiCalendarHeart.path,\n}\n\n/** \"a restaurant or cafe\" as a card title: \"Restaurant or cafe\". The answer itself keeps its words. */\nexport function startTypeTitle(type: string): string {\n const words = type.replace(/^(a|an)\\s+/i, '')\n return words.charAt(0).toUpperCase() + words.slice(1)\n}\n\n/** The id the style grid gives \"Pick for me\", which is no kind: the answers' `kind: null`. */\nexport const AI_SITE_STYLE_AUTO = 'auto'\n\n/**\n * The progress through the steps: labeled steps on a wide screen, a bar and\n * \"Step 3 of 6\" on a phone. On a wide screen a step already answered is a\n * button back to it (`onStep`), because a checked step reads as a link: the\n * guided start's dead clicks were people clicking it to go back.\n */\nexport function StartProgress({\n step,\n compact,\n onStep,\n}: {\n step: AiSiteStartStep\n compact: boolean\n onStep?: (step: AiSiteStartStep) => void\n}) {\n const index = aiSiteStartStepIndex(step)\n const count = AI_SITE_START_STEPS.length\n const name = `Step ${index + 1} of ${count}`\n if (compact) {\n return (\n <Stack spacing={1} data-start-area=\"progress\" role=\"group\" aria-label={name}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${name}: ${AI_SITE_START_STEP_LABELS[step]}`}\n </Typography>\n <LinearProgress variant=\"determinate\" value={((index + 1) / count) * 100} aria-hidden />\n </Stack>\n )\n }\n return (\n <Stepper activeStep={index} alternativeLabel aria-label={name} data-start-area=\"progress\">\n {AI_SITE_START_STEPS.map((id, at) => (\n <Step key={id}>\n {onStep && at < index ? (\n <StepButton onClick={() => onStep(id)} aria-label={`Back to ${AI_SITE_START_STEP_LABELS[id].toLowerCase()}`}>\n {AI_SITE_START_STEP_LABELS[id]}\n </StepButton>\n ) : (\n <StepLabel>{AI_SITE_START_STEP_LABELS[id]}</StepLabel>\n )}\n </Step>\n ))}\n </Stepper>\n )\n}\n\ninterface StepProps {\n answers: AiSiteStartAnswers\n answer: (patch: Partial<AiSiteStartAnswers>) => void\n tracker: AiSiteStartTracker\n /** Each field's reason not to go forward, once the person has tried to. */\n errors: Partial<Record<AiSiteStartField, AiSiteStartFieldError>>\n /** Where each field's input is, so a refused Next can put the cursor in it. */\n fieldRef: (field: AiSiteStartField) => Ref<HTMLInputElement>\n}\n\n/** A text answer's tracking: each change, and leaving the field, which ends one edit. */\nconst typed = (tracker: AiSiteStartTracker, field: AiSiteStartField) => ({\n onBlur: () => tracker.fieldLeft(field),\n})\n\n/** Step: what kind of site it is — the one required answer — typed, or picked from cards. */\nexport function KindStep({ answers, answer, tracker, errors, fieldRef }: StepProps) {\n const picked = AI_SITE_START_TYPES.includes(answers.siteType) ? answers.siteType : null\n return (\n <Stack spacing={3}>\n <Box data-start-area=\"field-siteType\">\n <TextField\n fullWidth\n required\n inputRef={fieldRef('siteType')}\n label=\"What kind of site are you creating?\"\n placeholder=\"a neighborhood dog groomer that takes bookings\"\n value={answers.siteType}\n onChange={(event) => {\n answer({ siteType: event.target.value })\n tracker.fieldChanged('siteType')\n }}\n {...typed(tracker, 'siteType')}\n error={Boolean(errors.siteType)}\n helperText={errors.siteType?.message ?? 'A few words is enough, or pick one below.'}\n />\n </Box>\n <Stack spacing={1.5}>\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"h2\">\n {'Or pick the closest'}\n </Typography>\n <OptionCardGrid\n label=\"Kind of site\"\n data-start-area=\"kind-cards\"\n columns={{ xs: 2, sm: 2, md: 4 }}\n options={AI_SITE_START_TYPES.map((type) => ({\n id: type,\n title: startTypeTitle(type),\n icon: START_TYPE_ICONS[type] ?? mdiBookOpenPageVariant.path,\n }))}\n value={picked}\n onChange={(type) => {\n answer({ siteType: type })\n tracker.fieldPicked('siteType')\n }}\n />\n </Stack>\n </Stack>\n )\n}\n\n/** Step: who the site is for. Optional. */\nexport function AudienceStep({ answers, answer, tracker, errors, fieldRef }: StepProps) {\n return (\n <Box data-start-area=\"field-audience\">\n <TextField\n fullWidth\n inputRef={fieldRef('audience')}\n label=\"Who is it for?\"\n placeholder=\"local dog owners who want a regular groom booked online\"\n value={answers.audience}\n onChange={(event) => {\n answer({ audience: event.target.value })\n tracker.fieldChanged('audience')\n }}\n {...typed(tracker, 'audience')}\n error={Boolean(errors.audience)}\n helperText={errors.audience?.message ?? 'Optional. It narrows who the pages are written for.'}\n />\n </Box>\n )\n}\n\n/**\n * Step: the style, from cards that show it. \"Pick for me\" leaves the kind\n * unset, which is what the single form's unpicked state was: the kind the\n * first answer suggests is the one used, and the card says which.\n */\nexport function StyleStep({\n answers,\n answer,\n tracker,\n errors,\n fieldRef,\n inspiration,\n}: StepProps & { inspiration?: AiSiteStartInspirationOffer | null }) {\n const suggested = aiSiteStartKind({ ...answers, kind: null })\n const cards = (\n <OptionCardGrid\n label=\"Style of site\"\n data-start-area=\"style-cards\"\n columns={{ xs: 2, sm: 2, md: 3 }}\n options={[\n {\n id: AI_SITE_STYLE_AUTO,\n title: 'Pick for me',\n description: `From your answer: ${suggested.label}`,\n icon: mdiCreation.path,\n },\n ...AI_SITE_KINDS.map((kind) => {\n const image = aiSiteStylePreview(kind.id)\n return { id: kind.id, title: kind.label, description: kind.blurb, ...(image ? { image } : {}) }\n }),\n ]}\n value={answers.kind ?? AI_SITE_STYLE_AUTO}\n onChange={(id) => {\n answer({ kind: id === AI_SITE_STYLE_AUTO ? null : id })\n tracker.fieldPicked('kind')\n }}\n />\n )\n if (!inspiration) return cards\n return (\n <Stack spacing={4}>\n {cards}\n <InspirationFields answers={answers} answer={answer} tracker={tracker} errors={errors} fieldRef={fieldRef} offer={inspiration} />\n </Stack>\n )\n}\n\n/**\n * What the guided start offers of Sites I like (AGL-3975), while\n * `release_ai_site_inspiration` is on: how many sites the workspace may name,\n * and where it upgrades for more.\n */\nexport interface AiSiteStartInspirationOffer {\n limit: number\n upgradeHref: string | null\n}\n\n/** Why a Free workspace's second and third site fields are locked. */\nexport const AI_SITE_INSPIRATION_LOCKED_REASON = `A Free workspace names ${AI_SITE_INSPIRATION_LIMITS.free} site you like. Paid plans name up to ${AI_SITE_INSPIRATION_MAX}.`\n\n/**\n * Sites I like (AGL-3975): up to three addresses under the style cards. A\n * Free workspace's fields past its one are shown disabled with the reason\n * and an upgrade link, never hidden, so the person sees what a paid plan adds.\n */\nfunction InspirationFields({\n answers,\n answer,\n tracker,\n errors,\n fieldRef,\n offer,\n}: StepProps & { offer: AiSiteStartInspirationOffer }) {\n const values = answers.inspiration ?? []\n const change = (index: number, value: string) => {\n const next = Array.from({ length: offer.limit }, (_, at) => values[at] ?? '')\n next[index] = value\n answer({ inspiration: next })\n tracker.fieldChanged('inspiration')\n }\n return (\n <Stack spacing={1.5} data-start-area=\"field-inspiration\">\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"h2\">\n {'Sites you like (optional)'}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {\n 'We take only how they are laid out and styled: the order of sections, colors, type, buttons and motion. Never their words, photos or logos, so your site stays your own.'\n }\n </Typography>\n {Array.from({ length: AI_SITE_INSPIRATION_MAX }, (_, index) => {\n const locked = index >= offer.limit\n const field = (\n <TextField\n fullWidth\n type=\"url\"\n inputMode=\"url\"\n label={`Site ${index + 1}`}\n placeholder=\"https://example.com\"\n value={locked ? '' : (values[index] ?? '')}\n onChange={(event) => change(index, event.target.value)}\n onBlur={() => tracker.fieldLeft('inspiration')}\n {...(index === 0 ? { inputRef: fieldRef('inspiration') } : {})}\n error={index === 0 && Boolean(errors.inspiration)}\n {...(index === 0 && errors.inspiration ? { helperText: errors.inspiration.message } : {})}\n />\n )\n return locked ? (\n <BlockedControl key={index} blocked reason={AI_SITE_INSPIRATION_LOCKED_REASON} fullWidth>\n {field}\n </BlockedControl>\n ) : (\n <Box key={index}>{field}</Box>\n )\n })}\n {offer.limit < AI_SITE_INSPIRATION_MAX && (\n <PrerequisiteNotice {...(offer.upgradeHref ? { href: offer.upgradeHref } : {})} actionLabel=\"Upgrade\">\n {AI_SITE_INSPIRATION_PAID_NOTE}\n </PrerequisiteNotice>\n )}\n </Stack>\n )\n}\n\n/** Step: where leads go, how many pages, and on a paid plan the welcome email. */\nexport function DetailsStep({\n answers,\n answer,\n tracker,\n errors,\n fieldRef,\n freeTaste,\n band,\n}: StepProps & { freeTaste: boolean; band: { min: number; max: number } }) {\n return (\n <Stack spacing={3}>\n {/*\n How a customer reaches the business (AGL-3979), first: given, the\n pages show them as links — the contact page, the footer, the buttons\n that ask a visitor to call or write — and the site's search listing\n and AI-agent details carry them. Optional, and never a placeholder.\n */}\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <Box data-start-area=\"field-phone\" sx={{ flex: 1 }}>\n <TextField\n fullWidth\n type=\"tel\"\n inputRef={fieldRef('phone')}\n label=\"Business phone\"\n placeholder=\"(512) 555-0142\"\n autoComplete=\"tel\"\n value={answers.phone}\n onChange={(event) => {\n answer({ phone: event.target.value })\n tracker.fieldChanged('phone')\n }}\n {...typed(tracker, 'phone')}\n error={Boolean(errors.phone)}\n helperText={errors.phone?.message ?? 'Optional. Shown on your site so customers can call.'}\n slotProps={{ htmlInput: { inputMode: 'tel' } }}\n />\n </Box>\n <Box data-start-area=\"field-email\" sx={{ flex: 1 }}>\n <TextField\n fullWidth\n type=\"email\"\n inputRef={fieldRef('email')}\n label=\"Business email\"\n placeholder=\"hello@yourbusiness.com\"\n autoComplete=\"email\"\n value={answers.email}\n onChange={(event) => {\n answer({ email: event.target.value })\n tracker.fieldChanged('email')\n }}\n {...typed(tracker, 'email')}\n error={Boolean(errors.email)}\n helperText={errors.email?.message ?? 'Optional. Shown on your site so customers can write.'}\n />\n </Box>\n </Stack>\n {/*\n The one setting a new site owner has to make, asked where they are\n already answering: a contact form nobody routed files its messages\n somewhere the person has not looked.\n */}\n <Box data-start-area=\"field-submissions\">\n <TextField\n select\n fullWidth\n inputRef={fieldRef('submissions')}\n label=\"Where do form submissions go?\"\n value={answers.submissions}\n onChange={(event) => {\n answer({ submissions: event.target.value as AiSiteSubmissions })\n tracker.fieldPicked('submissions')\n }}\n error={Boolean(errors.submissions)}\n helperText={errors.submissions?.message ?? 'You can change this on the form itself afterwards.'}\n >\n {AI_SITE_SUBMISSION_CHOICES.map((option) => (\n <MenuItem key={option.id} value={option.id}>\n {`${option.label} — ${option.blurb}`}\n </MenuItem>\n ))}\n </TextField>\n </Box>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <Box data-start-area=\"field-pages\" sx={{ flex: 1 }}>\n <TextField\n select\n fullWidth\n inputRef={fieldRef('pages')}\n label=\"Pages\"\n value={answers.pages}\n onChange={(event) => {\n answer({ pages: Number(event.target.value) })\n tracker.fieldPicked('pages')\n }}\n error={Boolean(errors.pages)}\n helperText={errors.pages?.message ?? (freeTaste ? AI_SITE_FREE_PAGES_NOTE : undefined)}\n >\n {Array.from({ length: band.max - band.min + 1 }, (_, index) => band.min + index).map((count) => (\n <MenuItem key={count} value={count}>\n {count}\n </MenuItem>\n ))}\n </TextField>\n </Box>\n {!freeTaste && (\n <Box data-start-area=\"field-welcomeEmail\" sx={{ flex: 1 }}>\n <TextField\n select\n fullWidth\n label=\"Welcome email\"\n value={answers.welcomeEmail ? 'yes' : 'no'}\n onChange={(event) => {\n answer({ welcomeEmail: event.target.value === 'yes' })\n tracker.fieldPicked('welcomeEmail')\n }}\n >\n <MenuItem value=\"yes\">{'Draft one'}</MenuItem>\n <MenuItem value=\"no\">{'No'}</MenuItem>\n </TextField>\n </Box>\n )}\n </Stack>\n </Stack>\n )\n}\n\n/**\n * The brand colors \"More details\" offers on the Style step (AGL-3979), by\n * name: picking one makes it the site's primary color, held to contrast by\n * the look like any brand color; none leaves the style to choose. Picked,\n * never typed: a color code is not something a site owner should need.\n */\nexport const AI_SITE_START_BRAND_COLORS: ReadonlyArray<{ label: string; hex: string }> = [\n { label: 'Red', hex: '#c62828' },\n { label: 'Orange', hex: '#e65100' },\n { label: 'Gold', hex: '#b28704' },\n { label: 'Green', hex: '#2e7d32' },\n { label: 'Teal', hex: '#00796b' },\n { label: 'Blue', hex: '#1565c0' },\n { label: 'Navy', hex: '#1a237e' },\n { label: 'Purple', hex: '#6a1b9a' },\n { label: 'Pink', hex: '#ad1457' },\n { label: 'Brown', hex: '#5d4037' },\n { label: 'Charcoal', hex: '#37474f' },\n]\n\n/** The price ranges offered, as a search listing writes them. */\nconst PRICE_RANGES: ReadonlyArray<{ value: string; label: string }> = [\n { value: '$', label: '$ — budget' },\n { value: '$$', label: '$$ — moderate' },\n { value: '$$$', label: '$$$ — premium' },\n { value: '$$$$', label: '$$$$ — luxury' },\n]\n\n/** What each step's \"More details\" says it holds, under its title. */\nconst MORE_SUMMARY: Readonly<Partial<Record<AiSiteStartStep, string>>> = {\n kind: 'Optional: a tagline and the year you started',\n audience: 'Optional: areas you serve, price range and languages',\n style: 'Optional: your brand color',\n details: 'Optional: address, opening hours and social profiles',\n}\n\n/** A typed extra's field. */\nfunction ExtraText({\n field,\n answers,\n answer,\n tracker,\n errors,\n fieldRef,\n label,\n placeholder,\n helper,\n autoComplete = 'off',\n multiline = false,\n inputMode,\n}: StepProps & {\n field: AiSiteStartExtraKey\n label: string\n placeholder?: string\n helper?: string\n autoComplete?: string\n multiline?: boolean\n inputMode?: 'numeric' | 'url'\n}) {\n const error = errors[field]\n return (\n <Box data-start-area={`field-${field}`} sx={{ flex: 1, minWidth: 0 }}>\n <TextField\n fullWidth\n inputRef={fieldRef(field)}\n label={label}\n placeholder={placeholder}\n autoComplete={autoComplete}\n multiline={multiline}\n minRows={multiline ? 2 : undefined}\n value={answers[field]}\n onChange={(event) => {\n answer({ [field]: event.target.value })\n tracker.fieldChanged(field)\n }}\n {...typed(tracker, field)}\n error={Boolean(error)}\n helperText={error?.message ?? helper}\n slotProps={inputMode ? { htmlInput: { inputMode } } : undefined}\n />\n </Box>\n )\n}\n\n/** The price range, picked from how search results show one. */\nfunction PriceRangeField({ answers, answer, tracker, errors, fieldRef }: StepProps) {\n const own = answers.priceRange && !PRICE_RANGES.some((option) => option.value === answers.priceRange)\n const options = own ? [...PRICE_RANGES, { value: answers.priceRange, label: answers.priceRange }] : PRICE_RANGES\n return (\n <Box data-start-area=\"field-priceRange\" sx={{ flex: 1, minWidth: 0 }}>\n <TextField\n select\n fullWidth\n inputRef={fieldRef('priceRange')}\n label=\"Price range\"\n value={answers.priceRange}\n onChange={(event) => {\n answer({ priceRange: event.target.value })\n tracker.fieldPicked('priceRange')\n }}\n error={Boolean(errors.priceRange)}\n helperText={errors.priceRange?.message ?? 'How your prices compare, as search results show it.'}\n >\n <MenuItem value=\"\">{'Not said'}</MenuItem>\n {options.map((option) => (\n <MenuItem key={option.value} value={option.value}>\n {option.label}\n </MenuItem>\n ))}\n </TextField>\n </Box>\n )\n}\n\n/** The brand color, picked from named swatches. */\nfunction BrandField({ answers, answer, tracker }: StepProps) {\n const labelId = useId()\n return (\n <Stack spacing={1} data-start-area=\"field-brand\">\n <Typography variant=\"body2\" color=\"text.secondary\" id={labelId}>\n {'Brand color'}\n </Typography>\n <Stack direction=\"row\" role=\"radiogroup\" aria-labelledby={labelId} sx={{ flexWrap: 'wrap', gap: 1 }}>\n {[{ label: 'Let the style choose', hex: '' }, ...AI_SITE_START_BRAND_COLORS].map((color) => {\n const picked = (answers.brand || '') === color.hex\n return (\n <Tooltip key={color.label} title={color.label}>\n <Box\n component=\"button\"\n type=\"button\"\n role=\"radio\"\n aria-checked={picked}\n aria-label={color.label}\n onClick={() => {\n answer({ brand: color.hex })\n tracker.fieldPicked('brand')\n }}\n sx={{\n width: 36,\n height: 36,\n p: 0,\n borderRadius: '50%',\n border: 2,\n borderColor: picked ? 'text.primary' : 'divider',\n bgcolor: color.hex || 'background.paper',\n color: color.hex ? 'common.white' : 'text.secondary',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n }}\n >\n {picked ? <MdiIcon path={mdiCheck.path} fontSize=\"small\" /> : null}\n </Box>\n </Tooltip>\n )\n })}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Picked, it is your site’s main color, kept readable everywhere it is used.'}\n </Typography>\n </Stack>\n )\n}\n\n/** The opening hours, picked a day at a time: the same editor as Setup → SEO. */\nfunction HoursField({ answers, answer, tracker, errors }: StepProps) {\n return (\n <Box data-start-area=\"field-hours\">\n <OpeningHoursPicker\n label=\"Opening hours\"\n value={answers.hours}\n onChange={(hours) => {\n answer({ hours })\n tracker.fieldPicked('hours')\n }}\n helperText={errors.hours?.message ?? 'Leave every day closed if you work by appointment.'}\n />\n </Box>\n )\n}\n\n/** One extra's field, as \"More details\" draws it. */\nfunction ExtraField({ field, ...props }: StepProps & { field: AiSiteStartExtraKey }) {\n switch (field) {\n case 'tagline':\n return <ExtraText {...props} field={field} label=\"Tagline\" placeholder=\"Calm, gentle grooming your dog will love\" helper=\"A short line about the business, in your words.\" />\n case 'founded':\n return <ExtraText {...props} field={field} label=\"Year founded\" placeholder=\"2015\" inputMode=\"numeric\" />\n case 'serviceArea':\n return <ExtraText {...props} field={field} label=\"Areas you serve\" placeholder={'Austin\\nRound Rock'} helper=\"Cities, towns or neighborhoods, one a line.\" multiline />\n case 'priceRange':\n return <PriceRangeField {...props} />\n case 'languages':\n return <ExtraText {...props} field={field} label=\"Languages you serve customers in\" placeholder=\"English, Spanish\" />\n case 'brand':\n return <BrandField {...props} />\n case 'street':\n return <ExtraText {...props} field={field} label=\"Street address\" placeholder=\"214 Main Street\" autoComplete=\"street-address\" />\n case 'city':\n return <ExtraText {...props} field={field} label=\"City or town\" placeholder=\"Austin\" autoComplete=\"address-level2\" />\n case 'region':\n return <ExtraText {...props} field={field} label=\"State or region\" placeholder=\"TX\" autoComplete=\"address-level1\" />\n case 'postalCode':\n return <ExtraText {...props} field={field} label=\"ZIP or postal code\" placeholder=\"78701\" autoComplete=\"postal-code\" />\n case 'country':\n return <ExtraText {...props} field={field} label=\"Country\" placeholder=\"United States\" autoComplete=\"country-name\" />\n case 'hours':\n return <HoursField {...props} />\n case 'social':\n return (\n <ExtraText\n {...props}\n field={field}\n label=\"Social profiles\"\n placeholder=\"instagram.com/yourbusiness\"\n helper=\"One link a line. Your site links them, and its search listing names them as yours.\"\n multiline\n inputMode=\"url\"\n />\n )\n default:\n return null\n }\n}\n\n/** Fields \"More details\" draws side by side. */\nconst PAIRS: ReadonlyArray<readonly [AiSiteStartExtraKey, AiSiteStartExtraKey]> = [\n ['tagline', 'founded'],\n ['priceRange', 'languages'],\n ['city', 'region'],\n ['postalCode', 'country'],\n]\n\n/**\n * A step's \"More details\" (AGL-3979): a collapsed section of optional extras\n * that fit the step, so a person who wants the site to say more can, and one\n * who does not never has to open it. Open from the start where something in\n * it is already filled in (a start reopened on its answers), and opened by a\n * Next refused on one of its fields.\n */\nexport function MoreDetails({ step, ...props }: StepProps & { step: AiSiteStartStep }) {\n const fields = AI_SITE_START_MORE_FIELDS[step]\n const { answers, errors, tracker } = props\n const [open, setOpen] = useState(() => fields.some((field) => (answers[field] ?? '').trim() !== ''))\n if (!fields.length) return null\n const expanded = open || fields.some((field) => errors[field])\n const rows: Array<readonly AiSiteStartExtraKey[]> = []\n for (const field of fields) {\n if (rows.some((row) => row.includes(field))) continue\n const pair = PAIRS.find((entry) => entry[0] === field && fields.includes(entry[1]))\n rows.push(pair ?? [field])\n }\n return (\n <Accordion\n disableGutters\n variant=\"outlined\"\n // The same outlined, rounded section as the build page's plan.\n sx={{ borderRadius: 2, '&::before': { display: 'none' } }}\n expanded={expanded}\n onChange={(_, next) => {\n setOpen(next)\n if (next) tracker.moreDetails()\n }}\n data-start-area=\"more-details\"\n >\n <AccordionSummary expandIcon={<MdiIcon path={mdiChevronDown.path} />}>\n <Stack spacing={0.25}>\n <Typography variant=\"subtitle2\" component=\"span\">\n {'More details'}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\" component=\"span\">\n {MORE_SUMMARY[step]}\n </Typography>\n </Stack>\n </AccordionSummary>\n <AccordionDetails>\n <Stack spacing={2.5}>\n {rows.map((row) =>\n row.length > 1 ? (\n <Stack key={row.join('-')} direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n {row.map((field) => (\n <ExtraField key={field} field={field} {...props} />\n ))}\n </Stack>\n ) : (\n <ExtraField key={row[0]} field={row[0]} {...props} />\n ),\n )}\n </Stack>\n </AccordionDetails>\n </Accordion>\n )\n}\n\n/** The extras on the review, each as a person reads it, with the step that asks it. */\nexport function aiSiteStartExtraRows(answers: AiSiteStartAnswers): Array<{ label: string; value: string; step: AiSiteStartStep }> {\n const rows: Array<{ label: string; value: string; step: AiSiteStartStep }> = []\n const add = (label: string, value: string, step: AiSiteStartStep) => {\n if (value.trim()) rows.push({ label, value: value.trim(), step })\n }\n add('Phone', answers.phone, 'details')\n add('Email', answers.email, 'details')\n add('Tagline', answers.tagline, 'kind')\n add('Year founded', answers.founded, 'kind')\n add('Areas you serve', aiSiteServiceAreas(answers.serviceArea).join(', '), 'audience')\n add('Price range', answers.priceRange, 'audience')\n add('Languages', answers.languages, 'audience')\n const brand = AI_SITE_START_BRAND_COLORS.find((color) => color.hex === answers.brand)\n add('Brand color', brand?.label ?? answers.brand, 'style')\n const regional = [answers.region, answers.postalCode].map((part) => part.trim()).filter(Boolean).join(' ')\n const address = [answers.street, answers.city, regional, answers.country]\n .map((part) => part.trim())\n .filter(Boolean)\n .join(', ')\n add('Address', address, 'details')\n add('Opening hours', aiSiteHoursSentence(answers.hours), 'details')\n const links = aiSiteSocialLinks(answers.social) ?? []\n add('Social profiles', links.map((link) => link.replace(/^https:\\/\\//, '')).join(', '), 'details')\n return rows\n}\n\n/**\n * One answer on the review, as one button back to the step that asks it. The\n * whole row is the target, not only \"Edit\" at its end: people clicked the\n * answer itself to change it, and nothing happened.\n */\nfunction ReviewRow({ label, value, step, onEdit }: { label: string; value: ReactNode; step: AiSiteStartStep; onEdit: (step: AiSiteStartStep) => void }) {\n const valueId = useId()\n return (\n <ListItemButton\n onClick={() => onEdit(step)}\n aria-label={`Edit ${label.toLowerCase()}`}\n aria-describedby={valueId}\n sx={{ alignItems: 'flex-start', gap: 2, py: 1.5, px: 1, mx: -1, borderRadius: 1 }}\n >\n <Box sx={{ flex: 1, minWidth: 0 }}>\n <Typography variant=\"body2\" color=\"text.secondary\" component=\"span\" sx={{ display: 'block' }}>\n {label}\n </Typography>\n <Typography id={valueId} variant=\"body1\" component=\"span\" sx={{ display: 'block', overflowWrap: 'anywhere' }}>\n {value}\n </Typography>\n </Box>\n <Typography variant=\"button\" color=\"primary\" component=\"span\" aria-hidden sx={{ fontSize: '0.8125rem', pt: 0.25 }}>\n {'Edit'}\n </Typography>\n </ListItemButton>\n )\n}\n\n/** Step: every answer, each with Edit, before \"Plan my site\". */\nexport function ReviewStep({\n answers,\n freeTaste,\n onEdit,\n children,\n inspiration = false,\n}: {\n answers: AiSiteStartAnswers\n freeTaste: boolean\n onEdit: (step: AiSiteStartStep) => void\n children?: ReactNode\n /** Whether the start asks for the sites the person likes (AGL-3975). */\n inspiration?: boolean\n}) {\n const liked = aiSiteStartInspirationTyped(answers)\n const kind = aiSiteStartKind(answers)\n const submissions = AI_SITE_SUBMISSION_CHOICES.find((option) => option.id === answers.submissions)\n const rows: Array<{ label: string; value: ReactNode; step: AiSiteStartStep }> = [\n { label: 'Kind of site', value: answers.siteType.trim(), step: 'kind' },\n { label: 'Who it is for', value: answers.audience.trim() || 'Anyone (not said)', step: 'audience' },\n { label: 'Style', value: answers.kind ? kind.label : `${kind.label}, picked for you`, step: 'style' },\n ...(inspiration\n ? [{ label: 'Sites you like', value: liked.length ? liked.map(aiSiteInspirationHost).join(', ') : 'None', step: 'style' as const }]\n : []),\n { label: 'Form submissions', value: submissions?.label ?? answers.submissions, step: 'details' },\n { label: 'Pages', value: String(answers.pages), step: 'details' },\n ...(freeTaste ? [] : [{ label: 'Welcome email', value: answers.welcomeEmail ? 'Draft one' : 'No', step: 'details' as const }]),\n // Everything \"More details\" and the contact fields were given (AGL-3979), each with Edit.\n ...aiSiteStartExtraRows(answers),\n ]\n return (\n <Stack spacing={3}>\n <List disablePadding data-start-area=\"review\" aria-label=\"Your answers\">\n {rows.map((row, index) => (\n <Fragment key={row.label}>\n {index > 0 && <Divider component=\"li\" aria-hidden />}\n <li>\n <ReviewRow {...row} onEdit={onEdit} />\n </li>\n </Fragment>\n ))}\n </List>\n {children}\n </Stack>\n )\n}\n\n/** A step's help beside its heading. */\nexport function StepHelp({ step }: { step: AiSiteStartStep }) {\n const help = step === 'choose' ? null : START_STEP_HELP[step]\n return help ? <HelpTip sx={{ float: 'right' }} {...help} /> : null\n}\n"],"names":["pluginDocsHelp","mdiBookOpenPageVariant","mdiBriefcaseOutline","mdiCalendarHeart","mdiCheck","mdiChevronDown","mdiCreation","mdiHandHeart","mdiScaleBalance","mdiShopping","mdiSilverwareForkKnife","mdiViewGridOutline","mdiWrench","HelpTip","MdiIcon","OptionCardGrid","BlockedControl","PrerequisiteNotice","OpeningHoursPicker","Accordion","AccordionDetails","AccordionSummary","Box","Divider","LinearProgress","List","ListItemButton","MenuItem","Stack","Step","StepButton","StepLabel","Stepper","TextField","Tooltip","Typography","Fragment","useId","useState","aiSiteHoursSentence","aiSiteServiceAreas","aiSiteSocialLinks","AI_SITE_FREE_PAGES_NOTE","AI_SITE_SUBMISSION_CHOICES","AI_SITE_KINDS","AI_SITE_INSPIRATION_LIMITS","AI_SITE_INSPIRATION_MAX","AI_SITE_INSPIRATION_PAID_NOTE","aiSiteInspirationHost","AI_SITE_START_TYPES","aiSiteStartInspirationTyped","aiSiteStartKind","AI_SITE_START_MORE_FIELDS","AI_SITE_START_STEP_LABELS","AI_SITE_START_STEPS","aiSiteStartStepIndex","aiSiteStylePreview","START_STEP_HELP","kind","anchor","excerpt","audience","review","style","details","START_TYPE_ICONS","path","startTypeTitle","type","words","replace","charAt","toUpperCase","slice","AI_SITE_STYLE_AUTO","StartProgress","step","compact","onStep","index","count","length","name","spacing","data-start-area","role","aria-label","variant","color","value","aria-hidden","activeStep","alternativeLabel","map","id","at","onClick","toLowerCase","typed","tracker","field","onBlur","fieldLeft","KindStep","answers","answer","errors","fieldRef","picked","includes","siteType","fullWidth","required","inputRef","label","placeholder","onChange","event","target","fieldChanged","error","Boolean","helperText","message","component","columns","xs","sm","md","options","title","icon","fieldPicked","AudienceStep","StyleStep","inspiration","suggested","cards","description","image","blurb","InspirationFields","offer","AI_SITE_INSPIRATION_LOCKED_REASON","free","values","change","next","Array","from","limit","_","locked","inputMode","blocked","reason","upgradeHref","href","actionLabel","DetailsStep","freeTaste","band","direction","sx","flex","autoComplete","phone","slotProps","htmlInput","email","select","submissions","option","pages","Number","undefined","max","min","welcomeEmail","AI_SITE_START_BRAND_COLORS","hex","PRICE_RANGES","MORE_SUMMARY","ExtraText","helper","multiline","minWidth","minRows","PriceRangeField","own","priceRange","some","BrandField","labelId","aria-labelledby","flexWrap","gap","brand","aria-checked","width","height","p","borderRadius","border","borderColor","bgcolor","display","alignItems","justifyContent","cursor","fontSize","HoursField","hours","ExtraField","props","PAIRS","MoreDetails","fields","open","setOpen","trim","expanded","rows","row","pair","find","entry","push","disableGutters","moreDetails","expandIcon","join","aiSiteStartExtraRows","add","tagline","founded","serviceArea","languages","regional","region","postalCode","part","filter","address","street","city","country","links","social","link","ReviewRow","onEdit","valueId","aria-describedby","py","px","mx","overflowWrap","pt","ReviewStep","children","liked","String","disablePadding","li","StepHelp","help","float"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-site-start-steps.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport {\n mdiBookOpenPageVariant,\n mdiBriefcaseOutline,\n mdiCalendarHeart,\n mdiCheck,\n mdiChevronDown,\n mdiCreation,\n mdiHandHeart,\n mdiScaleBalance,\n mdiShopping,\n mdiSilverwareForkKnife,\n mdiViewGridOutline,\n mdiWrench,\n} from '@aglyn/shared-data-mdi'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { OptionCardGrid } from '@aglyn/shared-ui-jsx/components/option-card-grid.component'\nimport { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport { OpeningHoursPicker } from '@aglyn/shared-ui-jsx/components/weekly-hours-picker.component'\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Box,\n Divider,\n FormHelperText,\n LinearProgress,\n List,\n ListItemButton,\n MenuItem,\n Stack,\n Step,\n StepButton,\n StepLabel,\n Stepper,\n TextField,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { Fragment, useId, useState, type ReactNode, type Ref } from 'react'\nimport { aiSiteHoursSentence, aiSiteServiceAreas, aiSiteSocialLinks } from '../model/ai-site-details'\nimport { AI_SITE_FREE_PAGES_NOTE, AI_SITE_SUBMISSION_CHOICES, type AiSiteSubmissions } from '../model/ai-site-job'\nimport { AI_SITE_KINDS } from '../model/ai-site-kinds'\nimport {\n AI_SITE_INSPIRATION_LIMITS,\n AI_SITE_INSPIRATION_MAX,\n AI_SITE_INSPIRATION_PAID_NOTE,\n aiSiteInspirationHost,\n} from '../model/ai-site-inspiration'\nimport { SITE_STYLE_AUTO } from '@aglyn/aglyn/app-utils/site-styles'\nimport {\n AI_SITE_START_TYPES,\n aiSiteStartInspirationTyped,\n aiSiteStartKind,\n aiSiteStartStyleAnswer,\n type AiSiteStartAnswers,\n type AiSiteStartExtraKey,\n} from '../model/ai-site-start'\nimport {\n AI_SITE_START_MORE_FIELDS,\n AI_SITE_START_STEP_LABELS,\n AI_SITE_START_STEPS,\n aiSiteStartStepIndex,\n type AiSiteStartField,\n type AiSiteStartFieldError,\n type AiSiteStartStep,\n} from '../model/ai-site-start-steps'\nimport type { AiSiteStartTracker } from './ai-site-start-tracking'\nimport { aiSiteStylePreview } from './ai-site-style-previews'\n\n/**\n * The guided start's question steps (AGL-3898), one decision each. Each step\n * draws its own answers and writes them through `answer`, exactly the patch\n * the single form wrote, so the answers object is the same whichever way it\n * was filled in. The dialog around them (`ai-site-start-card.component.tsx`)\n * owns the step, Back and Next, validation and the job.\n */\n\n/** Each part of the guided start links its own section of the Start with AI guide (AGL-3660). */\nexport const START_STEP_HELP = {\n kind: pluginDocsHelp('aiStart', {\n anchor: '#your-business',\n excerpt:\n 'What kind of site it is picks its style and pages; who it is for is who every page and the contact form are written for.',\n }),\n audience: pluginDocsHelp('aiStart', {\n anchor: '#audience',\n excerpt: 'Who the site is for is who every page, every search listing and the contact form are written for. Optional.',\n }),\n review: pluginDocsHelp('aiStart', {\n anchor: '#review',\n excerpt: 'Every answer, each with Edit to change it. Plan my site creates the site, plans it, writes the pages and publishes it.',\n }),\n style: pluginDocsHelp('aiSiteLooks', {\n anchor: '#choose-a-style',\n excerpt:\n 'The style decides the look — theme, colors, fonts, buttons — and which pages the site usually has. Every site gets its own variation.',\n }),\n details: pluginDocsHelp('aiStart', {\n anchor: '#details',\n excerpt:\n 'Your phone number and email, which your pages show, where contact form messages go, how many pages to write, and on paid plans whether to draft a welcome email. All can be changed later.',\n }),\n}\n\n/** The icon on each kind-of-site card: the icon of the style that answer picks. */\nconst START_TYPE_ICONS: Readonly<Record<string, string>> = {\n 'a local service business': mdiBriefcaseOutline.path,\n 'a restaurant or cafe': mdiSilverwareForkKnife.path,\n 'a professional practice': mdiScaleBalance.path,\n 'a trades business': mdiWrench.path,\n 'a shop': mdiShopping.path,\n 'a nonprofit': mdiHandHeart.path,\n 'a personal portfolio': mdiViewGridOutline.path,\n 'an event': mdiCalendarHeart.path,\n}\n\n/** \"a restaurant or cafe\" as a card title: \"Restaurant or cafe\". The answer itself keeps its words. */\nexport function startTypeTitle(type: string): string {\n const words = type.replace(/^(a|an)\\s+/i, '')\n return words.charAt(0).toUpperCase() + words.slice(1)\n}\n\n/** The id the style grid gives \"Pick for me\", which is no kind: the answers' `kind: null`. */\nexport const AI_SITE_STYLE_AUTO = SITE_STYLE_AUTO\n\n/**\n * The 21 style cards, each with its example home page (AGL-3898), as the\n * Style step and the starter site's style choice (AGL-4049) both draw them.\n */\nexport function aiSiteStyleCards(): Array<{\n id: string\n title: string\n description: string\n image?: NonNullable<ReturnType<typeof aiSiteStylePreview>>\n}> {\n return AI_SITE_KINDS.map((kind) => {\n const image = aiSiteStylePreview(kind.id)\n return { id: kind.id, title: kind.label, description: kind.blurb, ...(image ? { image } : {}) }\n })\n}\n\n/**\n * The progress through the steps: labeled steps on a wide screen, a bar and\n * \"Step 3 of 6\" on a phone. On a wide screen a step already answered is a\n * button back to it (`onStep`), because a checked step reads as a link: the\n * guided start's dead clicks were people clicking it to go back.\n */\nexport function StartProgress({\n step,\n compact,\n onStep,\n}: {\n step: AiSiteStartStep\n compact: boolean\n onStep?: (step: AiSiteStartStep) => void\n}) {\n const index = aiSiteStartStepIndex(step)\n const count = AI_SITE_START_STEPS.length\n const name = `Step ${index + 1} of ${count}`\n if (compact) {\n return (\n <Stack spacing={1} data-start-area=\"progress\" role=\"group\" aria-label={name}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${name}: ${AI_SITE_START_STEP_LABELS[step]}`}\n </Typography>\n <LinearProgress variant=\"determinate\" value={((index + 1) / count) * 100} aria-hidden />\n </Stack>\n )\n }\n return (\n <Stepper activeStep={index} alternativeLabel aria-label={name} data-start-area=\"progress\">\n {AI_SITE_START_STEPS.map((id, at) => (\n <Step key={id}>\n {onStep && at < index ? (\n <StepButton onClick={() => onStep(id)} aria-label={`Back to ${AI_SITE_START_STEP_LABELS[id].toLowerCase()}`}>\n {AI_SITE_START_STEP_LABELS[id]}\n </StepButton>\n ) : (\n <StepLabel>{AI_SITE_START_STEP_LABELS[id]}</StepLabel>\n )}\n </Step>\n ))}\n </Stepper>\n )\n}\n\ninterface StepProps {\n answers: AiSiteStartAnswers\n answer: (patch: Partial<AiSiteStartAnswers>) => void\n tracker: AiSiteStartTracker\n /** Each field's reason not to go forward, once the person has tried to. */\n errors: Partial<Record<AiSiteStartField, AiSiteStartFieldError>>\n /** Where each field's input is, so a refused Next can put the cursor in it. */\n fieldRef: (field: AiSiteStartField) => Ref<HTMLInputElement>\n}\n\n/** A text answer's tracking: each change, and leaving the field, which ends one edit. */\nconst typed = (tracker: AiSiteStartTracker, field: AiSiteStartField) => ({\n onBlur: () => tracker.fieldLeft(field),\n})\n\n/** Step: what kind of site it is — the one required answer — typed, or picked from cards. */\nexport function KindStep({ answers, answer, tracker, errors, fieldRef }: StepProps) {\n const picked = AI_SITE_START_TYPES.includes(answers.siteType) ? answers.siteType : null\n return (\n <Stack spacing={3}>\n <Box data-start-area=\"field-siteType\">\n <TextField\n fullWidth\n required\n inputRef={fieldRef('siteType')}\n label=\"What kind of site are you creating?\"\n placeholder=\"a neighborhood dog groomer that takes bookings\"\n value={answers.siteType}\n onChange={(event) => {\n answer({ siteType: event.target.value })\n tracker.fieldChanged('siteType')\n }}\n {...typed(tracker, 'siteType')}\n error={Boolean(errors.siteType)}\n helperText={errors.siteType?.message ?? 'A few words is enough, or pick one below.'}\n />\n </Box>\n <Stack spacing={1.5}>\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"h2\">\n {'Or pick the closest'}\n </Typography>\n <OptionCardGrid\n label=\"Kind of site\"\n data-start-area=\"kind-cards\"\n columns={{ xs: 2, sm: 2, md: 4 }}\n options={AI_SITE_START_TYPES.map((type) => ({\n id: type,\n title: startTypeTitle(type),\n icon: START_TYPE_ICONS[type] ?? mdiBookOpenPageVariant.path,\n }))}\n value={picked}\n onChange={(type) => {\n answer({ siteType: type })\n tracker.fieldPicked('siteType')\n }}\n />\n </Stack>\n </Stack>\n )\n}\n\n/** Step: who the site is for. Optional. */\nexport function AudienceStep({ answers, answer, tracker, errors, fieldRef }: StepProps) {\n return (\n <Box data-start-area=\"field-audience\">\n <TextField\n fullWidth\n inputRef={fieldRef('audience')}\n label=\"Who is it for?\"\n placeholder=\"local dog owners who want a regular groom booked online\"\n value={answers.audience}\n onChange={(event) => {\n answer({ audience: event.target.value })\n tracker.fieldChanged('audience')\n }}\n {...typed(tracker, 'audience')}\n error={Boolean(errors.audience)}\n helperText={errors.audience?.message ?? 'Optional. It narrows who the pages are written for.'}\n />\n </Box>\n )\n}\n\n/**\n * Step: the style, from cards that show it. Nothing is chosen until a card is\n * clicked (AGL-4049), and the step does not go forward before one is. \"Pick\n * for me\" is a card too: it leaves the kind unset, so the kind the first\n * answer suggests is the one used, and the card says which.\n */\nexport function StyleStep({\n answers,\n answer,\n tracker,\n errors,\n fieldRef,\n inspiration,\n}: StepProps & { inspiration?: AiSiteStartInspirationOffer | null }) {\n const suggested = aiSiteStartKind({ ...answers, kind: null })\n const cards = (\n <OptionCardGrid\n label=\"Style of site\"\n data-start-area=\"style-cards\"\n columns={{ xs: 2, sm: 2, md: 3 }}\n options={[\n {\n id: AI_SITE_STYLE_AUTO,\n title: 'Pick for me',\n description: `From your answer: ${suggested.label}`,\n icon: mdiCreation.path,\n },\n ...aiSiteStyleCards(),\n ]}\n value={answers.style}\n onChange={(id) => {\n answer(aiSiteStartStyleAnswer(id))\n tracker.fieldPicked('style')\n }}\n />\n )\n const chosen = (\n <Stack spacing={1} data-start-area=\"field-style\">\n {cards}\n {errors.style ? (\n <FormHelperText error role=\"alert\">\n {errors.style.message}\n </FormHelperText>\n ) : null}\n </Stack>\n )\n if (!inspiration) return chosen\n return (\n <Stack spacing={4}>\n {chosen}\n <InspirationFields answers={answers} answer={answer} tracker={tracker} errors={errors} fieldRef={fieldRef} offer={inspiration} />\n </Stack>\n )\n}\n\n/**\n * What the guided start offers of Sites I like (AGL-3975), while\n * `release_ai_site_inspiration` is on: how many sites the workspace may name,\n * and where it upgrades for more.\n */\nexport interface AiSiteStartInspirationOffer {\n limit: number\n upgradeHref: string | null\n}\n\n/** Why a Free workspace's second and third site fields are locked. */\nexport const AI_SITE_INSPIRATION_LOCKED_REASON = `A Free workspace names ${AI_SITE_INSPIRATION_LIMITS.free} site you like. Paid plans name up to ${AI_SITE_INSPIRATION_MAX}.`\n\n/**\n * Sites I like (AGL-3975): up to three addresses under the style cards. A\n * Free workspace's fields past its one are shown disabled with the reason\n * and an upgrade link, never hidden, so the person sees what a paid plan adds.\n */\nfunction InspirationFields({\n answers,\n answer,\n tracker,\n errors,\n fieldRef,\n offer,\n}: StepProps & { offer: AiSiteStartInspirationOffer }) {\n const values = answers.inspiration ?? []\n const change = (index: number, value: string) => {\n const next = Array.from({ length: offer.limit }, (_, at) => values[at] ?? '')\n next[index] = value\n answer({ inspiration: next })\n tracker.fieldChanged('inspiration')\n }\n return (\n <Stack spacing={1.5} data-start-area=\"field-inspiration\">\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"h2\">\n {'Sites you like (optional)'}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {\n 'We take only how they are laid out and styled: the order of sections, colors, type, buttons and motion. Never their words, photos or logos, so your site stays your own.'\n }\n </Typography>\n {Array.from({ length: AI_SITE_INSPIRATION_MAX }, (_, index) => {\n const locked = index >= offer.limit\n const field = (\n <TextField\n fullWidth\n type=\"url\"\n inputMode=\"url\"\n label={`Site ${index + 1}`}\n placeholder=\"https://example.com\"\n value={locked ? '' : (values[index] ?? '')}\n onChange={(event) => change(index, event.target.value)}\n onBlur={() => tracker.fieldLeft('inspiration')}\n {...(index === 0 ? { inputRef: fieldRef('inspiration') } : {})}\n error={index === 0 && Boolean(errors.inspiration)}\n {...(index === 0 && errors.inspiration ? { helperText: errors.inspiration.message } : {})}\n />\n )\n return locked ? (\n <BlockedControl key={index} blocked reason={AI_SITE_INSPIRATION_LOCKED_REASON} fullWidth>\n {field}\n </BlockedControl>\n ) : (\n <Box key={index}>{field}</Box>\n )\n })}\n {offer.limit < AI_SITE_INSPIRATION_MAX && (\n <PrerequisiteNotice {...(offer.upgradeHref ? { href: offer.upgradeHref } : {})} actionLabel=\"Upgrade\">\n {AI_SITE_INSPIRATION_PAID_NOTE}\n </PrerequisiteNotice>\n )}\n </Stack>\n )\n}\n\n/** Step: where leads go, how many pages, and on a paid plan the welcome email. */\nexport function DetailsStep({\n answers,\n answer,\n tracker,\n errors,\n fieldRef,\n freeTaste,\n band,\n}: StepProps & { freeTaste: boolean; band: { min: number; max: number } }) {\n return (\n <Stack spacing={3}>\n {/*\n How a customer reaches the business (AGL-3979), first: given, the\n pages show them as links — the contact page, the footer, the buttons\n that ask a visitor to call or write — and the site's search listing\n and AI-agent details carry them. Optional, and never a placeholder.\n */}\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <Box data-start-area=\"field-phone\" sx={{ flex: 1 }}>\n <TextField\n fullWidth\n type=\"tel\"\n inputRef={fieldRef('phone')}\n label=\"Business phone\"\n placeholder=\"(512) 555-0142\"\n autoComplete=\"tel\"\n value={answers.phone}\n onChange={(event) => {\n answer({ phone: event.target.value })\n tracker.fieldChanged('phone')\n }}\n {...typed(tracker, 'phone')}\n error={Boolean(errors.phone)}\n helperText={errors.phone?.message ?? 'Optional. Shown on your site so customers can call.'}\n slotProps={{ htmlInput: { inputMode: 'tel' } }}\n />\n </Box>\n <Box data-start-area=\"field-email\" sx={{ flex: 1 }}>\n <TextField\n fullWidth\n type=\"email\"\n inputRef={fieldRef('email')}\n label=\"Business email\"\n placeholder=\"hello@yourbusiness.com\"\n autoComplete=\"email\"\n value={answers.email}\n onChange={(event) => {\n answer({ email: event.target.value })\n tracker.fieldChanged('email')\n }}\n {...typed(tracker, 'email')}\n error={Boolean(errors.email)}\n helperText={errors.email?.message ?? 'Optional. Shown on your site so customers can write.'}\n />\n </Box>\n </Stack>\n {/*\n The one setting a new site owner has to make, asked where they are\n already answering: a contact form nobody routed files its messages\n somewhere the person has not looked.\n */}\n <Box data-start-area=\"field-submissions\">\n <TextField\n select\n fullWidth\n inputRef={fieldRef('submissions')}\n label=\"Where do form submissions go?\"\n value={answers.submissions}\n onChange={(event) => {\n answer({ submissions: event.target.value as AiSiteSubmissions })\n tracker.fieldPicked('submissions')\n }}\n error={Boolean(errors.submissions)}\n helperText={errors.submissions?.message ?? 'You can change this on the form itself afterwards.'}\n >\n {AI_SITE_SUBMISSION_CHOICES.map((option) => (\n <MenuItem key={option.id} value={option.id}>\n {`${option.label} — ${option.blurb}`}\n </MenuItem>\n ))}\n </TextField>\n </Box>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <Box data-start-area=\"field-pages\" sx={{ flex: 1 }}>\n <TextField\n select\n fullWidth\n inputRef={fieldRef('pages')}\n label=\"Pages\"\n value={answers.pages}\n onChange={(event) => {\n answer({ pages: Number(event.target.value) })\n tracker.fieldPicked('pages')\n }}\n error={Boolean(errors.pages)}\n helperText={errors.pages?.message ?? (freeTaste ? AI_SITE_FREE_PAGES_NOTE : undefined)}\n >\n {Array.from({ length: band.max - band.min + 1 }, (_, index) => band.min + index).map((count) => (\n <MenuItem key={count} value={count}>\n {count}\n </MenuItem>\n ))}\n </TextField>\n </Box>\n {!freeTaste && (\n <Box data-start-area=\"field-welcomeEmail\" sx={{ flex: 1 }}>\n <TextField\n select\n fullWidth\n label=\"Welcome email\"\n value={answers.welcomeEmail ? 'yes' : 'no'}\n onChange={(event) => {\n answer({ welcomeEmail: event.target.value === 'yes' })\n tracker.fieldPicked('welcomeEmail')\n }}\n >\n <MenuItem value=\"yes\">{'Draft one'}</MenuItem>\n <MenuItem value=\"no\">{'No'}</MenuItem>\n </TextField>\n </Box>\n )}\n </Stack>\n </Stack>\n )\n}\n\n/**\n * The brand colors \"More details\" offers on the Style step (AGL-3979), by\n * name: picking one makes it the site's primary color, held to contrast by\n * the look like any brand color; none leaves the style to choose. Picked,\n * never typed: a color code is not something a site owner should need.\n */\nexport const AI_SITE_START_BRAND_COLORS: ReadonlyArray<{ label: string; hex: string }> = [\n { label: 'Red', hex: '#c62828' },\n { label: 'Orange', hex: '#e65100' },\n { label: 'Gold', hex: '#b28704' },\n { label: 'Green', hex: '#2e7d32' },\n { label: 'Teal', hex: '#00796b' },\n { label: 'Blue', hex: '#1565c0' },\n { label: 'Navy', hex: '#1a237e' },\n { label: 'Purple', hex: '#6a1b9a' },\n { label: 'Pink', hex: '#ad1457' },\n { label: 'Brown', hex: '#5d4037' },\n { label: 'Charcoal', hex: '#37474f' },\n]\n\n/** The price ranges offered, as a search listing writes them. */\nconst PRICE_RANGES: ReadonlyArray<{ value: string; label: string }> = [\n { value: '$', label: '$ — budget' },\n { value: '$$', label: '$$ — moderate' },\n { value: '$$$', label: '$$$ — premium' },\n { value: '$$$$', label: '$$$$ — luxury' },\n]\n\n/** What each step's \"More details\" says it holds, under its title. */\nconst MORE_SUMMARY: Readonly<Partial<Record<AiSiteStartStep, string>>> = {\n kind: 'Optional: a tagline and the year you started',\n audience: 'Optional: areas you serve, price range and languages',\n style: 'Optional: your brand color',\n details: 'Optional: address, opening hours and social profiles',\n}\n\n/** A typed extra's field. */\nfunction ExtraText({\n field,\n answers,\n answer,\n tracker,\n errors,\n fieldRef,\n label,\n placeholder,\n helper,\n autoComplete = 'off',\n multiline = false,\n inputMode,\n}: StepProps & {\n field: AiSiteStartExtraKey\n label: string\n placeholder?: string\n helper?: string\n autoComplete?: string\n multiline?: boolean\n inputMode?: 'numeric' | 'url'\n}) {\n const error = errors[field]\n return (\n <Box data-start-area={`field-${field}`} sx={{ flex: 1, minWidth: 0 }}>\n <TextField\n fullWidth\n inputRef={fieldRef(field)}\n label={label}\n placeholder={placeholder}\n autoComplete={autoComplete}\n multiline={multiline}\n minRows={multiline ? 2 : undefined}\n value={answers[field]}\n onChange={(event) => {\n answer({ [field]: event.target.value })\n tracker.fieldChanged(field)\n }}\n {...typed(tracker, field)}\n error={Boolean(error)}\n helperText={error?.message ?? helper}\n slotProps={inputMode ? { htmlInput: { inputMode } } : undefined}\n />\n </Box>\n )\n}\n\n/** The price range, picked from how search results show one. */\nfunction PriceRangeField({ answers, answer, tracker, errors, fieldRef }: StepProps) {\n const own = answers.priceRange && !PRICE_RANGES.some((option) => option.value === answers.priceRange)\n const options = own ? [...PRICE_RANGES, { value: answers.priceRange, label: answers.priceRange }] : PRICE_RANGES\n return (\n <Box data-start-area=\"field-priceRange\" sx={{ flex: 1, minWidth: 0 }}>\n <TextField\n select\n fullWidth\n inputRef={fieldRef('priceRange')}\n label=\"Price range\"\n value={answers.priceRange}\n onChange={(event) => {\n answer({ priceRange: event.target.value })\n tracker.fieldPicked('priceRange')\n }}\n error={Boolean(errors.priceRange)}\n helperText={errors.priceRange?.message ?? 'How your prices compare, as search results show it.'}\n >\n <MenuItem value=\"\">{'Not said'}</MenuItem>\n {options.map((option) => (\n <MenuItem key={option.value} value={option.value}>\n {option.label}\n </MenuItem>\n ))}\n </TextField>\n </Box>\n )\n}\n\n/** The brand color, picked from named swatches. */\nfunction BrandField({ answers, answer, tracker }: StepProps) {\n const labelId = useId()\n return (\n <Stack spacing={1} data-start-area=\"field-brand\">\n <Typography variant=\"body2\" color=\"text.secondary\" id={labelId}>\n {'Brand color'}\n </Typography>\n <Stack direction=\"row\" role=\"radiogroup\" aria-labelledby={labelId} sx={{ flexWrap: 'wrap', gap: 1 }}>\n {[{ label: 'Let the style choose', hex: '' }, ...AI_SITE_START_BRAND_COLORS].map((color) => {\n const picked = (answers.brand || '') === color.hex\n return (\n <Tooltip key={color.label} title={color.label}>\n <Box\n component=\"button\"\n type=\"button\"\n role=\"radio\"\n aria-checked={picked}\n aria-label={color.label}\n onClick={() => {\n answer({ brand: color.hex })\n tracker.fieldPicked('brand')\n }}\n sx={{\n width: 36,\n height: 36,\n p: 0,\n borderRadius: '50%',\n border: 2,\n borderColor: picked ? 'text.primary' : 'divider',\n bgcolor: color.hex || 'background.paper',\n color: color.hex ? 'common.white' : 'text.secondary',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n }}\n >\n {picked ? <MdiIcon path={mdiCheck.path} fontSize=\"small\" /> : null}\n </Box>\n </Tooltip>\n )\n })}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Picked, it is your site’s main color, kept readable everywhere it is used.'}\n </Typography>\n </Stack>\n )\n}\n\n/** The opening hours, picked a day at a time: the same editor as Setup → SEO. */\nfunction HoursField({ answers, answer, tracker, errors }: StepProps) {\n return (\n <Box data-start-area=\"field-hours\">\n <OpeningHoursPicker\n label=\"Opening hours\"\n value={answers.hours}\n onChange={(hours) => {\n answer({ hours })\n tracker.fieldPicked('hours')\n }}\n helperText={errors.hours?.message ?? 'Leave every day closed if you work by appointment.'}\n />\n </Box>\n )\n}\n\n/** One extra's field, as \"More details\" draws it. */\nfunction ExtraField({ field, ...props }: StepProps & { field: AiSiteStartExtraKey }) {\n switch (field) {\n case 'tagline':\n return <ExtraText {...props} field={field} label=\"Tagline\" placeholder=\"Calm, gentle grooming your dog will love\" helper=\"A short line about the business, in your words.\" />\n case 'founded':\n return <ExtraText {...props} field={field} label=\"Year founded\" placeholder=\"2015\" inputMode=\"numeric\" />\n case 'serviceArea':\n return <ExtraText {...props} field={field} label=\"Areas you serve\" placeholder={'Austin\\nRound Rock'} helper=\"Cities, towns or neighborhoods, one a line.\" multiline />\n case 'priceRange':\n return <PriceRangeField {...props} />\n case 'languages':\n return <ExtraText {...props} field={field} label=\"Languages you serve customers in\" placeholder=\"English, Spanish\" />\n case 'brand':\n return <BrandField {...props} />\n case 'street':\n return <ExtraText {...props} field={field} label=\"Street address\" placeholder=\"214 Main Street\" autoComplete=\"street-address\" />\n case 'city':\n return <ExtraText {...props} field={field} label=\"City or town\" placeholder=\"Austin\" autoComplete=\"address-level2\" />\n case 'region':\n return <ExtraText {...props} field={field} label=\"State or region\" placeholder=\"TX\" autoComplete=\"address-level1\" />\n case 'postalCode':\n return <ExtraText {...props} field={field} label=\"ZIP or postal code\" placeholder=\"78701\" autoComplete=\"postal-code\" />\n case 'country':\n return <ExtraText {...props} field={field} label=\"Country\" placeholder=\"United States\" autoComplete=\"country-name\" />\n case 'hours':\n return <HoursField {...props} />\n case 'social':\n return (\n <ExtraText\n {...props}\n field={field}\n label=\"Social profiles\"\n placeholder=\"instagram.com/yourbusiness\"\n helper=\"One link a line. Your site links them, and its search listing names them as yours.\"\n multiline\n inputMode=\"url\"\n />\n )\n default:\n return null\n }\n}\n\n/** Fields \"More details\" draws side by side. */\nconst PAIRS: ReadonlyArray<readonly [AiSiteStartExtraKey, AiSiteStartExtraKey]> = [\n ['tagline', 'founded'],\n ['priceRange', 'languages'],\n ['city', 'region'],\n ['postalCode', 'country'],\n]\n\n/**\n * A step's \"More details\" (AGL-3979): a collapsed section of optional extras\n * that fit the step, so a person who wants the site to say more can, and one\n * who does not never has to open it. Open from the start where something in\n * it is already filled in (a start reopened on its answers), and opened by a\n * Next refused on one of its fields.\n */\nexport function MoreDetails({ step, ...props }: StepProps & { step: AiSiteStartStep }) {\n const fields = AI_SITE_START_MORE_FIELDS[step]\n const { answers, errors, tracker } = props\n const [open, setOpen] = useState(() => fields.some((field) => (answers[field] ?? '').trim() !== ''))\n if (!fields.length) return null\n const expanded = open || fields.some((field) => errors[field])\n const rows: Array<readonly AiSiteStartExtraKey[]> = []\n for (const field of fields) {\n if (rows.some((row) => row.includes(field))) continue\n const pair = PAIRS.find((entry) => entry[0] === field && fields.includes(entry[1]))\n rows.push(pair ?? [field])\n }\n return (\n <Accordion\n disableGutters\n variant=\"outlined\"\n // The same outlined, rounded section as the build page's plan.\n sx={{ borderRadius: 2, '&::before': { display: 'none' } }}\n expanded={expanded}\n onChange={(_, next) => {\n setOpen(next)\n if (next) tracker.moreDetails()\n }}\n data-start-area=\"more-details\"\n >\n <AccordionSummary expandIcon={<MdiIcon path={mdiChevronDown.path} />}>\n <Stack spacing={0.25}>\n <Typography variant=\"subtitle2\" component=\"span\">\n {'More details'}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\" component=\"span\">\n {MORE_SUMMARY[step]}\n </Typography>\n </Stack>\n </AccordionSummary>\n <AccordionDetails>\n <Stack spacing={2.5}>\n {rows.map((row) =>\n row.length > 1 ? (\n <Stack key={row.join('-')} direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n {row.map((field) => (\n <ExtraField key={field} field={field} {...props} />\n ))}\n </Stack>\n ) : (\n <ExtraField key={row[0]} field={row[0]} {...props} />\n ),\n )}\n </Stack>\n </AccordionDetails>\n </Accordion>\n )\n}\n\n/** The extras on the review, each as a person reads it, with the step that asks it. */\nexport function aiSiteStartExtraRows(answers: AiSiteStartAnswers): Array<{ label: string; value: string; step: AiSiteStartStep }> {\n const rows: Array<{ label: string; value: string; step: AiSiteStartStep }> = []\n const add = (label: string, value: string, step: AiSiteStartStep) => {\n if (value.trim()) rows.push({ label, value: value.trim(), step })\n }\n add('Phone', answers.phone, 'details')\n add('Email', answers.email, 'details')\n add('Tagline', answers.tagline, 'kind')\n add('Year founded', answers.founded, 'kind')\n add('Areas you serve', aiSiteServiceAreas(answers.serviceArea).join(', '), 'audience')\n add('Price range', answers.priceRange, 'audience')\n add('Languages', answers.languages, 'audience')\n const brand = AI_SITE_START_BRAND_COLORS.find((color) => color.hex === answers.brand)\n add('Brand color', brand?.label ?? answers.brand, 'style')\n const regional = [answers.region, answers.postalCode].map((part) => part.trim()).filter(Boolean).join(' ')\n const address = [answers.street, answers.city, regional, answers.country]\n .map((part) => part.trim())\n .filter(Boolean)\n .join(', ')\n add('Address', address, 'details')\n add('Opening hours', aiSiteHoursSentence(answers.hours), 'details')\n const links = aiSiteSocialLinks(answers.social) ?? []\n add('Social profiles', links.map((link) => link.replace(/^https:\\/\\//, '')).join(', '), 'details')\n return rows\n}\n\n/**\n * One answer on the review, as one button back to the step that asks it. The\n * whole row is the target, not only \"Edit\" at its end: people clicked the\n * answer itself to change it, and nothing happened.\n */\nfunction ReviewRow({ label, value, step, onEdit }: { label: string; value: ReactNode; step: AiSiteStartStep; onEdit: (step: AiSiteStartStep) => void }) {\n const valueId = useId()\n return (\n <ListItemButton\n onClick={() => onEdit(step)}\n aria-label={`Edit ${label.toLowerCase()}`}\n aria-describedby={valueId}\n sx={{ alignItems: 'flex-start', gap: 2, py: 1.5, px: 1, mx: -1, borderRadius: 1 }}\n >\n <Box sx={{ flex: 1, minWidth: 0 }}>\n <Typography variant=\"body2\" color=\"text.secondary\" component=\"span\" sx={{ display: 'block' }}>\n {label}\n </Typography>\n <Typography id={valueId} variant=\"body1\" component=\"span\" sx={{ display: 'block', overflowWrap: 'anywhere' }}>\n {value}\n </Typography>\n </Box>\n <Typography variant=\"button\" color=\"primary\" component=\"span\" aria-hidden sx={{ fontSize: '0.8125rem', pt: 0.25 }}>\n {'Edit'}\n </Typography>\n </ListItemButton>\n )\n}\n\n/** Step: every answer, each with Edit, before \"Plan my site\". */\nexport function ReviewStep({\n answers,\n freeTaste,\n onEdit,\n children,\n inspiration = false,\n}: {\n answers: AiSiteStartAnswers\n freeTaste: boolean\n onEdit: (step: AiSiteStartStep) => void\n children?: ReactNode\n /** Whether the start asks for the sites the person likes (AGL-3975). */\n inspiration?: boolean\n}) {\n const liked = aiSiteStartInspirationTyped(answers)\n const kind = aiSiteStartKind(answers)\n const submissions = AI_SITE_SUBMISSION_CHOICES.find((option) => option.id === answers.submissions)\n const rows: Array<{ label: string; value: ReactNode; step: AiSiteStartStep }> = [\n { label: 'Kind of site', value: answers.siteType.trim(), step: 'kind' },\n { label: 'Who it is for', value: answers.audience.trim() || 'Anyone (not said)', step: 'audience' },\n {\n label: 'Style',\n value: answers.style === null ? 'Not chosen yet' : answers.kind ? kind.label : `${kind.label}, picked for you`,\n step: 'style',\n },\n ...(inspiration\n ? [{ label: 'Sites you like', value: liked.length ? liked.map(aiSiteInspirationHost).join(', ') : 'None', step: 'style' as const }]\n : []),\n { label: 'Form submissions', value: submissions?.label ?? answers.submissions, step: 'details' },\n { label: 'Pages', value: String(answers.pages), step: 'details' },\n ...(freeTaste ? [] : [{ label: 'Welcome email', value: answers.welcomeEmail ? 'Draft one' : 'No', step: 'details' as const }]),\n // Everything \"More details\" and the contact fields were given (AGL-3979), each with Edit.\n ...aiSiteStartExtraRows(answers),\n ]\n return (\n <Stack spacing={3}>\n <List disablePadding data-start-area=\"review\" aria-label=\"Your answers\">\n {rows.map((row, index) => (\n <Fragment key={row.label}>\n {index > 0 && <Divider component=\"li\" aria-hidden />}\n <li>\n <ReviewRow {...row} onEdit={onEdit} />\n </li>\n </Fragment>\n ))}\n </List>\n {children}\n </Stack>\n )\n}\n\n/** A step's help beside its heading. */\nexport function StepHelp({ step }: { step: AiSiteStartStep }) {\n const help = step === 'choose' ? null : START_STEP_HELP[step]\n return help ? <HelpTip sx={{ float: 'right' }} {...help} /> : null\n}\n"],"names":["pluginDocsHelp","mdiBookOpenPageVariant","mdiBriefcaseOutline","mdiCalendarHeart","mdiCheck","mdiChevronDown","mdiCreation","mdiHandHeart","mdiScaleBalance","mdiShopping","mdiSilverwareForkKnife","mdiViewGridOutline","mdiWrench","HelpTip","MdiIcon","OptionCardGrid","BlockedControl","PrerequisiteNotice","OpeningHoursPicker","Accordion","AccordionDetails","AccordionSummary","Box","Divider","FormHelperText","LinearProgress","List","ListItemButton","MenuItem","Stack","Step","StepButton","StepLabel","Stepper","TextField","Tooltip","Typography","Fragment","useId","useState","aiSiteHoursSentence","aiSiteServiceAreas","aiSiteSocialLinks","AI_SITE_FREE_PAGES_NOTE","AI_SITE_SUBMISSION_CHOICES","AI_SITE_KINDS","AI_SITE_INSPIRATION_LIMITS","AI_SITE_INSPIRATION_MAX","AI_SITE_INSPIRATION_PAID_NOTE","aiSiteInspirationHost","SITE_STYLE_AUTO","AI_SITE_START_TYPES","aiSiteStartInspirationTyped","aiSiteStartKind","aiSiteStartStyleAnswer","AI_SITE_START_MORE_FIELDS","AI_SITE_START_STEP_LABELS","AI_SITE_START_STEPS","aiSiteStartStepIndex","aiSiteStylePreview","START_STEP_HELP","kind","anchor","excerpt","audience","review","style","details","START_TYPE_ICONS","path","startTypeTitle","type","words","replace","charAt","toUpperCase","slice","AI_SITE_STYLE_AUTO","aiSiteStyleCards","map","image","id","title","label","description","blurb","StartProgress","step","compact","onStep","index","count","length","name","spacing","data-start-area","role","aria-label","variant","color","value","aria-hidden","activeStep","alternativeLabel","at","onClick","toLowerCase","typed","tracker","field","onBlur","fieldLeft","KindStep","answers","answer","errors","fieldRef","picked","includes","siteType","fullWidth","required","inputRef","placeholder","onChange","event","target","fieldChanged","error","Boolean","helperText","message","component","columns","xs","sm","md","options","icon","fieldPicked","AudienceStep","StyleStep","inspiration","suggested","cards","chosen","InspirationFields","offer","AI_SITE_INSPIRATION_LOCKED_REASON","free","values","change","next","Array","from","limit","_","locked","inputMode","blocked","reason","upgradeHref","href","actionLabel","DetailsStep","freeTaste","band","direction","sx","flex","autoComplete","phone","slotProps","htmlInput","email","select","submissions","option","pages","Number","undefined","max","min","welcomeEmail","AI_SITE_START_BRAND_COLORS","hex","PRICE_RANGES","MORE_SUMMARY","ExtraText","helper","multiline","minWidth","minRows","PriceRangeField","own","priceRange","some","BrandField","labelId","aria-labelledby","flexWrap","gap","brand","aria-checked","width","height","p","borderRadius","border","borderColor","bgcolor","display","alignItems","justifyContent","cursor","fontSize","HoursField","hours","ExtraField","props","PAIRS","MoreDetails","fields","open","setOpen","trim","expanded","rows","row","pair","find","entry","push","disableGutters","moreDetails","expandIcon","join","aiSiteStartExtraRows","add","tagline","founded","serviceArea","languages","regional","region","postalCode","part","filter","address","street","city","country","links","social","link","ReviewRow","onEdit","valueId","aria-describedby","py","px","mx","overflowWrap","pt","ReviewStep","children","liked","String","disablePadding","li","StepHelp","help","float"],"mappings":"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"}
@@ -15,6 +15,23 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  import type { OptionCardImage } from '@aglyn/shared-ui-jsx/components/option-card-grid.component';
18
+ /**
19
+ * The picture on each style card (AGL-3898): an example home page of that
20
+ * kind of site, in its own shape — a café's menu, a store's products, a
21
+ * photographer's gallery, a band's tour dates — drawn in the kind's look by
22
+ * `libs/plugins/ai/scripts/render-site-style-previews.mts` from the stand-in
23
+ * pages in `site-style-previews.json`, with the real compiler and node
24
+ * renderer, the starter photos and the previews' own credited photos
25
+ * (`scripts/style-preview-photos/`). Each opens on its kind's signature hero
26
+ * (`aiLayoutKindSignature`, AGL-3985) with a photo of its own kind of
27
+ * business.
28
+ *
29
+ * The pictures are the console's (`apps/console/public/_static/starter/styles/`,
30
+ * AGL-4049): the starter site's style choice draws the same ones without this
31
+ * plugin, so they are served from one place and named by core's
32
+ * `SITE_STYLES`. Each is 800 × 800; regenerate them all with that script when
33
+ * a kind's look or layout changes.
34
+ */
18
35
  /** What each picture shows, as its alt text: the example page and what leads it. */
19
36
  export declare const AI_SITE_STYLE_PREVIEW_ALTS: Readonly<Record<string, string>>;
20
37
  /** The width and height every preview is drawn at. */
@@ -14,106 +14,37 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
+ import { SITE_STYLE_PREVIEW_SIZE, SITE_STYLES, siteStyleOf } from "@aglyn/aglyn/app-utils/site-styles";
17
18
  import { AI_SITE_KINDS } from "../model/ai-site-kinds.js";
18
- import businessPreview from "../assets/site-styles/business.webp";
19
- import tradesPreview from "../assets/site-styles/trades.webp";
20
- import professionalPreview from "../assets/site-styles/professional.webp";
21
- import wellnessPreview from "../assets/site-styles/wellness.webp";
22
- import restaurantPreview from "../assets/site-styles/restaurant.webp";
23
- import storePreview from "../assets/site-styles/store.webp";
24
- import portfolioPreview from "../assets/site-styles/portfolio.webp";
25
- import studioPreview from "../assets/site-styles/studio.webp";
26
- import photographyPreview from "../assets/site-styles/photography.webp";
27
- import blogPreview from "../assets/site-styles/blog.webp";
28
- import eventsPreview from "../assets/site-styles/events.webp";
29
- import fitnessPreview from "../assets/site-styles/fitness.webp";
30
- import yogaPreview from "../assets/site-styles/yoga.webp";
31
- import beautyPreview from "../assets/site-styles/beauty.webp";
32
- import realestatePreview from "../assets/site-styles/realestate.webp";
33
- import educationPreview from "../assets/site-styles/education.webp";
34
- import nonprofitPreview from "../assets/site-styles/nonprofit.webp";
35
- import musicPreview from "../assets/site-styles/music.webp";
36
- import personalPreview from "../assets/site-styles/personal.webp";
37
- import landingPreview from "../assets/site-styles/landing.webp";
38
- import comingSoonPreview from "../assets/site-styles/coming-soon.webp";
39
19
  /**
40
- * The picture on each style card of the guided start (AGL-3898): an example
41
- * home page of that kind of site, in its own shape — a café's menu, a
42
- * store's products, a photographer's gallery, a band's tour dates — drawn in
43
- * the kind's look by `libs/plugins/ai/scripts/render-site-style-previews.mts`
44
- * from the stand-in pages in `site-style-previews.json`, with the real
45
- * compiler and node renderer, the starter photos and the previews' own
46
- * credited photos (`scripts/style-preview-photos/`). Each opens on its kind's
47
- * signature hero (`aiLayoutKindSignature`, AGL-3985) with a photo of its own
48
- * kind of business.
49
- * Each is 800 × 800; regenerate them all with that script when a kind's look
50
- * or layout changes.
51
- */ const PREVIEWS = {
52
- business: businessPreview,
53
- trades: tradesPreview,
54
- professional: professionalPreview,
55
- wellness: wellnessPreview,
56
- restaurant: restaurantPreview,
57
- store: storePreview,
58
- portfolio: portfolioPreview,
59
- studio: studioPreview,
60
- photography: photographyPreview,
61
- blog: blogPreview,
62
- events: eventsPreview,
63
- fitness: fitnessPreview,
64
- yoga: yogaPreview,
65
- beauty: beautyPreview,
66
- realestate: realestatePreview,
67
- education: educationPreview,
68
- nonprofit: nonprofitPreview,
69
- music: musicPreview,
70
- personal: personalPreview,
71
- landing: landingPreview,
72
- 'coming-soon': comingSoonPreview
73
- };
74
- /** What each picture shows, as its alt text: the example page and what leads it. */ export const AI_SITE_STYLE_PREVIEW_ALTS = {
75
- business: "A cleaning company's home page: its heading beside a photo of gloved hands wiping a desk, then its services as cards",
76
- trades: "A roofer's home page: a bold heading over a full-width photo of a roofer carrying shingles, then roofing services",
77
- professional: "A consulting firm's home page: its heading on a white card over a full-width photo of a team at a planning board",
78
- wellness: "A therapy practice's home page: half the page a photo of a calm, sunlit room, its heading in the other half, then its sessions",
79
- restaurant: "A café's home page: its heading centered over a photo of the owner at the counter, then menu highlights",
80
- store: "A handmade goods shop's home page: its heading beside two overlapping photos of wax seals, then featured products",
81
- portfolio: "A prop stylist's home page: a large heading over a grid of three styled sets",
82
- studio: "A design studio's home page: an oversized heading on black over a wide photo of the team at a brand board",
83
- photography: "A photographer's home page: its heading on black over a gallery of a wedding, a portrait and a maker",
84
- blog: "A food journal's home page: its heading centered in a narrow column over a wide photo of vegetables on a cutting board",
85
- events: "A festival's home page: two overlapping photos of a lantern-lit night market beside its dates, then the program",
86
- fitness: "A gym's home page: a bold heading on black beside a photo of rows of dumbbells, then this week's classes",
87
- yoga: "A yoga studio's home page: a quiet centered heading over a wide photo of a class stretching on mats",
88
- beauty: "A hair salon's home page: its heading beside two overlapping photos of a stylist at work and the salon's chairs",
89
- realestate: "A real estate agent's home page: its heading on a white card over a photo of a white house, then new listings",
90
- education: "A tutoring center's home page: a photo of a tutor at the whiteboard beside its heading, then its courses",
91
- nonprofit: "A food bank's home page: its heading over a full-width photo of volunteers sorting donations, then the ways to help",
92
- music: "A band's home page: its name in large type over a photo of a band under stage lights, then its tour dates",
93
- personal: "A product manager's personal page: a round portrait over her centered introduction, then her experience",
94
- landing: "A budgeting app's landing page: its pitch centered on a colored band over a photo of a couple planning on a phone",
95
- 'coming-soon': "A café's coming soon page: its heading and notify button centered over a photo of the café's coffee shelves"
96
- };
97
- /** The width and height every preview is drawn at. */ export const AI_SITE_STYLE_PREVIEW_SIZE = {
98
- width: 800,
99
- height: 800
100
- };
101
- /** A bundler hands an imported picture over as its URL, or as an object carrying it. */ function urlOf(imported) {
102
- if (typeof imported === 'string') return imported;
103
- if (imported && typeof imported === 'object' && typeof imported.src === 'string') {
104
- return imported.src;
105
- }
106
- return null;
107
- }
20
+ * The picture on each style card (AGL-3898): an example home page of that
21
+ * kind of site, in its own shape — a café's menu, a store's products, a
22
+ * photographer's gallery, a band's tour dates — drawn in the kind's look by
23
+ * `libs/plugins/ai/scripts/render-site-style-previews.mts` from the stand-in
24
+ * pages in `site-style-previews.json`, with the real compiler and node
25
+ * renderer, the starter photos and the previews' own credited photos
26
+ * (`scripts/style-preview-photos/`). Each opens on its kind's signature hero
27
+ * (`aiLayoutKindSignature`, AGL-3985) with a photo of its own kind of
28
+ * business.
29
+ *
30
+ * The pictures are the console's (`apps/console/public/_static/starter/styles/`,
31
+ * AGL-4049): the starter site's style choice draws the same ones without this
32
+ * plugin, so they are served from one place and named by core's
33
+ * `SITE_STYLES`. Each is 800 × 800; regenerate them all with that script when
34
+ * a kind's look or layout changes.
35
+ */ /** What each picture shows, as its alt text: the example page and what leads it. */ export const AI_SITE_STYLE_PREVIEW_ALTS = Object.fromEntries(SITE_STYLES.map((style)=>[
36
+ style.id,
37
+ style.alt
38
+ ]));
39
+ /** The width and height every preview is drawn at. */ export const AI_SITE_STYLE_PREVIEW_SIZE = SITE_STYLE_PREVIEW_SIZE;
108
40
  /** The style card picture for a kind of site, by its `AI_SITE_KINDS` id; `null` for a kind with none. */ export function aiSiteStylePreview(kindId) {
109
- var _AI_SITE_STYLE_PREVIEW_ALTS_kindId;
110
- const src = urlOf(PREVIEWS[kindId]);
41
+ const style = siteStyleOf(kindId);
111
42
  const kind = AI_SITE_KINDS.find((entry)=>entry.id === kindId);
112
- if (!src || !kind) return null;
43
+ if (!style || !kind) return null;
113
44
  return _extends({
114
- src,
115
- alt: (_AI_SITE_STYLE_PREVIEW_ALTS_kindId = AI_SITE_STYLE_PREVIEW_ALTS[kindId]) != null ? _AI_SITE_STYLE_PREVIEW_ALTS_kindId : `An example home page in the ${kind.label} style`
116
- }, AI_SITE_STYLE_PREVIEW_SIZE);
45
+ src: style.preview,
46
+ alt: style.alt || `An example home page in the ${kind.label} style`
47
+ }, SITE_STYLE_PREVIEW_SIZE);
117
48
  }
118
49
 
119
50
  //# sourceMappingURL=ai-site-style-previews.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-site-style-previews.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { OptionCardImage } from '@aglyn/shared-ui-jsx/components/option-card-grid.component'\nimport { AI_SITE_KINDS } from '../model/ai-site-kinds'\nimport businessPreview from '../assets/site-styles/business.webp'\nimport tradesPreview from '../assets/site-styles/trades.webp'\nimport professionalPreview from '../assets/site-styles/professional.webp'\nimport wellnessPreview from '../assets/site-styles/wellness.webp'\nimport restaurantPreview from '../assets/site-styles/restaurant.webp'\nimport storePreview from '../assets/site-styles/store.webp'\nimport portfolioPreview from '../assets/site-styles/portfolio.webp'\nimport studioPreview from '../assets/site-styles/studio.webp'\nimport photographyPreview from '../assets/site-styles/photography.webp'\nimport blogPreview from '../assets/site-styles/blog.webp'\nimport eventsPreview from '../assets/site-styles/events.webp'\nimport fitnessPreview from '../assets/site-styles/fitness.webp'\nimport yogaPreview from '../assets/site-styles/yoga.webp'\nimport beautyPreview from '../assets/site-styles/beauty.webp'\nimport realestatePreview from '../assets/site-styles/realestate.webp'\nimport educationPreview from '../assets/site-styles/education.webp'\nimport nonprofitPreview from '../assets/site-styles/nonprofit.webp'\nimport musicPreview from '../assets/site-styles/music.webp'\nimport personalPreview from '../assets/site-styles/personal.webp'\nimport landingPreview from '../assets/site-styles/landing.webp'\nimport comingSoonPreview from '../assets/site-styles/coming-soon.webp'\n\n/**\n * The picture on each style card of the guided start (AGL-3898): an example\n * home page of that kind of site, in its own shape — a café's menu, a\n * store's products, a photographer's gallery, a band's tour dates — drawn in\n * the kind's look by `libs/plugins/ai/scripts/render-site-style-previews.mts`\n * from the stand-in pages in `site-style-previews.json`, with the real\n * compiler and node renderer, the starter photos and the previews' own\n * credited photos (`scripts/style-preview-photos/`). Each opens on its kind's\n * signature hero (`aiLayoutKindSignature`, AGL-3985) with a photo of its own\n * kind of business.\n * Each is 800 × 800; regenerate them all with that script when a kind's look\n * or layout changes.\n */\nconst PREVIEWS: Readonly<Record<string, unknown>> = {\n business: businessPreview,\n trades: tradesPreview,\n professional: professionalPreview,\n wellness: wellnessPreview,\n restaurant: restaurantPreview,\n store: storePreview,\n portfolio: portfolioPreview,\n studio: studioPreview,\n photography: photographyPreview,\n blog: blogPreview,\n events: eventsPreview,\n fitness: fitnessPreview,\n yoga: yogaPreview,\n beauty: beautyPreview,\n realestate: realestatePreview,\n education: educationPreview,\n nonprofit: nonprofitPreview,\n music: musicPreview,\n personal: personalPreview,\n landing: landingPreview,\n 'coming-soon': comingSoonPreview,\n}\n\n/** What each picture shows, as its alt text: the example page and what leads it. */\nexport const AI_SITE_STYLE_PREVIEW_ALTS: Readonly<Record<string, string>> = {\n business: \"A cleaning company's home page: its heading beside a photo of gloved hands wiping a desk, then its services as cards\",\n trades: \"A roofer's home page: a bold heading over a full-width photo of a roofer carrying shingles, then roofing services\",\n professional: \"A consulting firm's home page: its heading on a white card over a full-width photo of a team at a planning board\",\n wellness: \"A therapy practice's home page: half the page a photo of a calm, sunlit room, its heading in the other half, then its sessions\",\n restaurant: \"A café's home page: its heading centered over a photo of the owner at the counter, then menu highlights\",\n store: \"A handmade goods shop's home page: its heading beside two overlapping photos of wax seals, then featured products\",\n portfolio: \"A prop stylist's home page: a large heading over a grid of three styled sets\",\n studio: \"A design studio's home page: an oversized heading on black over a wide photo of the team at a brand board\",\n photography: \"A photographer's home page: its heading on black over a gallery of a wedding, a portrait and a maker\",\n blog: \"A food journal's home page: its heading centered in a narrow column over a wide photo of vegetables on a cutting board\",\n events: \"A festival's home page: two overlapping photos of a lantern-lit night market beside its dates, then the program\",\n fitness: \"A gym's home page: a bold heading on black beside a photo of rows of dumbbells, then this week's classes\",\n yoga: \"A yoga studio's home page: a quiet centered heading over a wide photo of a class stretching on mats\",\n beauty: \"A hair salon's home page: its heading beside two overlapping photos of a stylist at work and the salon's chairs\",\n realestate: \"A real estate agent's home page: its heading on a white card over a photo of a white house, then new listings\",\n education: \"A tutoring center's home page: a photo of a tutor at the whiteboard beside its heading, then its courses\",\n nonprofit: \"A food bank's home page: its heading over a full-width photo of volunteers sorting donations, then the ways to help\",\n music: \"A band's home page: its name in large type over a photo of a band under stage lights, then its tour dates\",\n personal: \"A product manager's personal page: a round portrait over her centered introduction, then her experience\",\n landing: \"A budgeting app's landing page: its pitch centered on a colored band over a photo of a couple planning on a phone\",\n 'coming-soon': \"A café's coming soon page: its heading and notify button centered over a photo of the café's coffee shelves\",\n}\n\n/** The width and height every preview is drawn at. */\nexport const AI_SITE_STYLE_PREVIEW_SIZE = { width: 800, height: 800 } as const\n\n/** A bundler hands an imported picture over as its URL, or as an object carrying it. */\nfunction urlOf(imported: unknown): string | null {\n if (typeof imported === 'string') return imported\n if (imported && typeof imported === 'object' && typeof (imported as { src?: unknown }).src === 'string') {\n return (imported as { src: string }).src\n }\n return null\n}\n\n/** The style card picture for a kind of site, by its `AI_SITE_KINDS` id; `null` for a kind with none. */\nexport function aiSiteStylePreview(kindId: string): OptionCardImage | null {\n const src = urlOf(PREVIEWS[kindId])\n const kind = AI_SITE_KINDS.find((entry) => entry.id === kindId)\n if (!src || !kind) return null\n return {\n src,\n alt: AI_SITE_STYLE_PREVIEW_ALTS[kindId] ?? `An example home page in the ${kind.label} style`,\n ...AI_SITE_STYLE_PREVIEW_SIZE,\n }\n}\n"],"names":["AI_SITE_KINDS","businessPreview","tradesPreview","professionalPreview","wellnessPreview","restaurantPreview","storePreview","portfolioPreview","studioPreview","photographyPreview","blogPreview","eventsPreview","fitnessPreview","yogaPreview","beautyPreview","realestatePreview","educationPreview","nonprofitPreview","musicPreview","personalPreview","landingPreview","comingSoonPreview","PREVIEWS","business","trades","professional","wellness","restaurant","store","portfolio","studio","photography","blog","events","fitness","yoga","beauty","realestate","education","nonprofit","music","personal","landing","AI_SITE_STYLE_PREVIEW_ALTS","AI_SITE_STYLE_PREVIEW_SIZE","width","height","urlOf","imported","src","aiSiteStylePreview","kindId","kind","find","entry","id","alt","label"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SAASA,aAAa,QAAQ,4BAAwB;AACtD,OAAOC,qBAAqB,sCAAqC;AACjE,OAAOC,mBAAmB,oCAAmC;AAC7D,OAAOC,yBAAyB,0CAAyC;AACzE,OAAOC,qBAAqB,sCAAqC;AACjE,OAAOC,uBAAuB,wCAAuC;AACrE,OAAOC,kBAAkB,mCAAkC;AAC3D,OAAOC,sBAAsB,uCAAsC;AACnE,OAAOC,mBAAmB,oCAAmC;AAC7D,OAAOC,wBAAwB,yCAAwC;AACvE,OAAOC,iBAAiB,kCAAiC;AACzD,OAAOC,mBAAmB,oCAAmC;AAC7D,OAAOC,oBAAoB,qCAAoC;AAC/D,OAAOC,iBAAiB,kCAAiC;AACzD,OAAOC,mBAAmB,oCAAmC;AAC7D,OAAOC,uBAAuB,wCAAuC;AACrE,OAAOC,sBAAsB,uCAAsC;AACnE,OAAOC,sBAAsB,uCAAsC;AACnE,OAAOC,kBAAkB,mCAAkC;AAC3D,OAAOC,qBAAqB,sCAAqC;AACjE,OAAOC,oBAAoB,qCAAoC;AAC/D,OAAOC,uBAAuB,yCAAwC;AAEtE;;;;;;;;;;;;CAYC,GACD,MAAMC,WAA8C;IAClDC,UAAUtB;IACVuB,QAAQtB;IACRuB,cAActB;IACduB,UAAUtB;IACVuB,YAAYtB;IACZuB,OAAOtB;IACPuB,WAAWtB;IACXuB,QAAQtB;IACRuB,aAAatB;IACbuB,MAAMtB;IACNuB,QAAQtB;IACRuB,SAAStB;IACTuB,MAAMtB;IACNuB,QAAQtB;IACRuB,YAAYtB;IACZuB,WAAWtB;IACXuB,WAAWtB;IACXuB,OAAOtB;IACPuB,UAAUtB;IACVuB,SAAStB;IACT,eAAeC;AACjB;AAEA,kFAAkF,GAClF,OAAO,MAAMsB,6BAA+D;IAC1EpB,UAAU;IACVC,QAAQ;IACRC,cAAc;IACdC,UAAU;IACVC,YAAY;IACZC,OAAO;IACPC,WAAW;IACXC,QAAQ;IACRC,aAAa;IACbC,MAAM;IACNC,QAAQ;IACRC,SAAS;IACTC,MAAM;IACNC,QAAQ;IACRC,YAAY;IACZC,WAAW;IACXC,WAAW;IACXC,OAAO;IACPC,UAAU;IACVC,SAAS;IACT,eAAe;AACjB,EAAC;AAED,oDAAoD,GACpD,OAAO,MAAME,6BAA6B;IAAEC,OAAO;IAAKC,QAAQ;AAAI,EAAU;AAE9E,sFAAsF,GACtF,SAASC,MAAMC,QAAiB;IAC9B,IAAI,OAAOA,aAAa,UAAU,OAAOA;IACzC,IAAIA,YAAY,OAAOA,aAAa,YAAY,OAAO,AAACA,SAA+BC,GAAG,KAAK,UAAU;QACvG,OAAO,AAACD,SAA6BC,GAAG;IAC1C;IACA,OAAO;AACT;AAEA,uGAAuG,GACvG,OAAO,SAASC,mBAAmBC,MAAc;QAMxCR;IALP,MAAMM,MAAMF,MAAMzB,QAAQ,CAAC6B,OAAO;IAClC,MAAMC,OAAOpD,cAAcqD,IAAI,CAAC,CAACC,QAAUA,MAAMC,EAAE,KAAKJ;IACxD,IAAI,CAACF,OAAO,CAACG,MAAM,OAAO;IAC1B,OAAO;QACLH;QACAO,GAAG,GAAEb,qCAAAA,0BAA0B,CAACQ,OAAO,YAAlCR,qCAAsC,CAAC,4BAA4B,EAAES,KAAKK,KAAK,CAAC,MAAM,CAAC;OACzFb;AAEP"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-site-style-previews.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { OptionCardImage } from '@aglyn/shared-ui-jsx/components/option-card-grid.component'\nimport {\n SITE_STYLE_PREVIEW_SIZE,\n SITE_STYLES,\n siteStyleOf,\n} from '@aglyn/aglyn/app-utils/site-styles'\nimport { AI_SITE_KINDS } from '../model/ai-site-kinds'\n\n/**\n * The picture on each style card (AGL-3898): an example home page of that\n * kind of site, in its own shape — a café's menu, a store's products, a\n * photographer's gallery, a band's tour dates — drawn in the kind's look by\n * `libs/plugins/ai/scripts/render-site-style-previews.mts` from the stand-in\n * pages in `site-style-previews.json`, with the real compiler and node\n * renderer, the starter photos and the previews' own credited photos\n * (`scripts/style-preview-photos/`). Each opens on its kind's signature hero\n * (`aiLayoutKindSignature`, AGL-3985) with a photo of its own kind of\n * business.\n *\n * The pictures are the console's (`apps/console/public/_static/starter/styles/`,\n * AGL-4049): the starter site's style choice draws the same ones without this\n * plugin, so they are served from one place and named by core's\n * `SITE_STYLES`. Each is 800 × 800; regenerate them all with that script when\n * a kind's look or layout changes.\n */\n\n/** What each picture shows, as its alt text: the example page and what leads it. */\nexport const AI_SITE_STYLE_PREVIEW_ALTS: Readonly<Record<string, string>> = Object.fromEntries(\n SITE_STYLES.map((style) => [style.id, style.alt]),\n)\n\n/** The width and height every preview is drawn at. */\nexport const AI_SITE_STYLE_PREVIEW_SIZE = SITE_STYLE_PREVIEW_SIZE\n\n/** The style card picture for a kind of site, by its `AI_SITE_KINDS` id; `null` for a kind with none. */\nexport function aiSiteStylePreview(kindId: string): OptionCardImage | null {\n const style = siteStyleOf(kindId)\n const kind = AI_SITE_KINDS.find((entry) => entry.id === kindId)\n if (!style || !kind) return null\n return {\n src: style.preview,\n alt: style.alt || `An example home page in the ${kind.label} style`,\n ...SITE_STYLE_PREVIEW_SIZE,\n }\n}\n"],"names":["SITE_STYLE_PREVIEW_SIZE","SITE_STYLES","siteStyleOf","AI_SITE_KINDS","AI_SITE_STYLE_PREVIEW_ALTS","Object","fromEntries","map","style","id","alt","AI_SITE_STYLE_PREVIEW_SIZE","aiSiteStylePreview","kindId","kind","find","entry","src","preview","label"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAED,SACEA,uBAAuB,EACvBC,WAAW,EACXC,WAAW,QACN,qCAAoC;AAC3C,SAASC,aAAa,QAAQ,4BAAwB;AAEtD;;;;;;;;;;;;;;;;CAgBC,GAED,kFAAkF,GAClF,OAAO,MAAMC,6BAA+DC,OAAOC,WAAW,CAC5FL,YAAYM,GAAG,CAAC,CAACC,QAAU;QAACA,MAAMC,EAAE;QAAED,MAAME,GAAG;KAAC,GACjD;AAED,oDAAoD,GACpD,OAAO,MAAMC,6BAA6BX,wBAAuB;AAEjE,uGAAuG,GACvG,OAAO,SAASY,mBAAmBC,MAAc;IAC/C,MAAML,QAAQN,YAAYW;IAC1B,MAAMC,OAAOX,cAAcY,IAAI,CAAC,CAACC,QAAUA,MAAMP,EAAE,KAAKI;IACxD,IAAI,CAACL,SAAS,CAACM,MAAM,OAAO;IAC5B,OAAO;QACLG,KAAKT,MAAMU,OAAO;QAClBR,KAAKF,MAAME,GAAG,IAAI,CAAC,4BAA4B,EAAEI,KAAKK,KAAK,CAAC,MAAM,CAAC;OAChEnB;AAEP"}
@@ -23,6 +23,8 @@ import { listUsageAlertContributors, registerUsageAlertContributor } from "@agly
23
23
  import { registerPluginUsageMeter } from "@aglyn/aglyn/plugin-manager/plugin-usage-meters";
24
24
  import { registerOperatorAlerts } from "@aglyn/aglyn/plugin-manager/operator-alerts";
25
25
  import { registerStockPhotoPicker } from "@aglyn/aglyn/plugin-manager/stock-photo-provider";
26
+ import { registerPluginSiteStyleLooks } from "@aglyn/aglyn/plugin-manager/plugin-site-style-looks";
27
+ import { listServerThemePresets } from "@aglyn/aglyn/plugin-manager/plugin-theme-presets";
26
28
  import { AI_PLUGIN_ID, AI_USAGE_METER_ID } from "./constants.js";
27
29
  import { AI_BUILD_PARTLY_FAILED, AI_JOB_FAILED, AI_PROVIDER_UNAVAILABLE } from "./operator-alerts.js";
28
30
  import { registerAiDeclarations } from "./declarations.js";
@@ -168,6 +170,26 @@ import { registerAiDeclarations } from "./declarations.js";
168
170
  }, {
169
171
  pluginId: AI_PLUGIN_ID
170
172
  });
173
+ // The look each style starts a new site in (AGL-4049): Create site asks a
174
+ // style before it creates anything, and the 21 styles are this plugin's
175
+ // kinds of site. Asked on the create, so the look module loads then; the
176
+ // built-in themes this deployment has are read at that moment too.
177
+ registerPluginSiteStyleLooks({
178
+ look: async (styleId)=>{
179
+ const [{ aiSiteKind }, { aiSiteKindDefaultLook }] = await Promise.all([
180
+ import("./model/ai-site-kinds.js"),
181
+ import("./model/ai-site-look.js")
182
+ ]);
183
+ const kind = aiSiteKind(styleId);
184
+ if (!kind) return null;
185
+ const presetIds = new Set(listServerThemePresets().map((preset)=>preset.id));
186
+ return aiSiteKindDefaultLook(kind, {
187
+ presetIds
188
+ }).theme;
189
+ }
190
+ }, {
191
+ pluginId: AI_PLUGIN_ID
192
+ });
171
193
  if (!listUsageAlertContributors().some((contributor)=>contributor.pluginId === AI_PLUGIN_ID && contributor.id === AI_USAGE_ALERTS_ID)) {
172
194
  registerUsageAlertContributor({
173
195
  pluginId: AI_PLUGIN_ID,