@brandlab-digital/site-next 3.12.1 → 3.14.0

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 (208) hide show
  1. package/README.md +132 -0
  2. package/dist/contact/delivery.d.ts +81 -0
  3. package/dist/contact/delivery.d.ts.map +1 -0
  4. package/dist/contact/delivery.js +138 -0
  5. package/dist/contact/delivery.js.map +1 -0
  6. package/dist/contact/resend-webhook.d.ts +72 -0
  7. package/dist/contact/resend-webhook.d.ts.map +1 -0
  8. package/dist/contact/resend-webhook.js +300 -0
  9. package/dist/contact/resend-webhook.js.map +1 -0
  10. package/dist/contact/route-handler.d.ts +16 -0
  11. package/dist/contact/route-handler.d.ts.map +1 -1
  12. package/dist/contact/route-handler.js +8 -0
  13. package/dist/contact/route-handler.js.map +1 -1
  14. package/dist/contact/server-entry.d.ts +2 -0
  15. package/dist/contact/server-entry.d.ts.map +1 -1
  16. package/dist/contact/server-entry.js +2 -0
  17. package/dist/contact/server-entry.js.map +1 -1
  18. package/dist/contact/server.d.ts +26 -0
  19. package/dist/contact/server.d.ts.map +1 -1
  20. package/dist/contact/server.js +48 -3
  21. package/dist/contact/server.js.map +1 -1
  22. package/dist/estate-segment.d.ts +48 -0
  23. package/dist/estate-segment.d.ts.map +1 -0
  24. package/dist/estate-segment.js +54 -0
  25. package/dist/estate-segment.js.map +1 -0
  26. package/dist/google-business-reviews-revalidate.d.ts +61 -0
  27. package/dist/google-business-reviews-revalidate.d.ts.map +1 -0
  28. package/dist/google-business-reviews-revalidate.js +151 -0
  29. package/dist/google-business-reviews-revalidate.js.map +1 -0
  30. package/dist/google-business-reviews-server.d.ts +21 -2
  31. package/dist/google-business-reviews-server.d.ts.map +1 -1
  32. package/dist/google-business-reviews-server.js +21 -4
  33. package/dist/google-business-reviews-server.js.map +1 -1
  34. package/dist/headers.d.ts.map +1 -1
  35. package/dist/headers.js +6 -0
  36. package/dist/headers.js.map +1 -1
  37. package/dist/next-config.d.ts +17 -1
  38. package/dist/next-config.d.ts.map +1 -1
  39. package/dist/next-config.js +36 -2
  40. package/dist/next-config.js.map +1 -1
  41. package/dist/robots.d.ts +26 -4
  42. package/dist/robots.d.ts.map +1 -1
  43. package/dist/robots.js +49 -2
  44. package/dist/robots.js.map +1 -1
  45. package/dist/ui-kit/brandlab-skin.d.ts +24 -1
  46. package/dist/ui-kit/brandlab-skin.d.ts.map +1 -1
  47. package/dist/ui-kit/brandlab-skin.js.map +1 -1
  48. package/dist/ui-kit/form/photo-upload.d.ts +4 -1
  49. package/dist/ui-kit/form/photo-upload.d.ts.map +1 -1
  50. package/dist/ui-kit/form/photo-upload.js +4 -4
  51. package/dist/ui-kit/form/photo-upload.js.map +1 -1
  52. package/dist/ui-kit/form/quote-form.d.ts +4 -1
  53. package/dist/ui-kit/form/quote-form.d.ts.map +1 -1
  54. package/dist/ui-kit/form/quote-form.js.map +1 -1
  55. package/dist/ui-kit/form/thank-you.d.ts +4 -1
  56. package/dist/ui-kit/form/thank-you.d.ts.map +1 -1
  57. package/dist/ui-kit/form/thank-you.js +2 -2
  58. package/dist/ui-kit/form/thank-you.js.map +1 -1
  59. package/dist/ui-kit/icon-glyphs.d.ts +41 -0
  60. package/dist/ui-kit/icon-glyphs.d.ts.map +1 -0
  61. package/dist/ui-kit/icon-glyphs.js +138 -0
  62. package/dist/ui-kit/icon-glyphs.js.map +1 -0
  63. package/dist/ui-kit/icon-sprite.d.ts +19 -0
  64. package/dist/ui-kit/icon-sprite.d.ts.map +1 -0
  65. package/dist/ui-kit/icon-sprite.js +44 -0
  66. package/dist/ui-kit/icon-sprite.js.map +1 -0
  67. package/dist/ui-kit/icons.d.ts +38 -3
  68. package/dist/ui-kit/icons.d.ts.map +1 -1
  69. package/dist/ui-kit/icons.js +47 -64
  70. package/dist/ui-kit/icons.js.map +1 -1
  71. package/dist/ui-kit/prefetch.d.ts +50 -0
  72. package/dist/ui-kit/prefetch.d.ts.map +1 -0
  73. package/dist/ui-kit/prefetch.js +50 -0
  74. package/dist/ui-kit/prefetch.js.map +1 -0
  75. package/dist/ui-kit/primitives/badge.d.ts +25 -0
  76. package/dist/ui-kit/primitives/badge.d.ts.map +1 -0
  77. package/dist/ui-kit/primitives/badge.js +21 -0
  78. package/dist/ui-kit/primitives/badge.js.map +1 -0
  79. package/dist/ui-kit/primitives/breadcrumbs.d.ts +27 -0
  80. package/dist/ui-kit/primitives/breadcrumbs.d.ts.map +1 -0
  81. package/dist/ui-kit/primitives/breadcrumbs.js +40 -0
  82. package/dist/ui-kit/primitives/breadcrumbs.js.map +1 -0
  83. package/dist/ui-kit/primitives/button.d.ts +32 -0
  84. package/dist/ui-kit/primitives/button.d.ts.map +1 -0
  85. package/dist/ui-kit/primitives/button.js +8 -0
  86. package/dist/ui-kit/primitives/button.js.map +1 -0
  87. package/dist/ui-kit/primitives/card.d.ts +40 -0
  88. package/dist/ui-kit/primitives/card.d.ts.map +1 -0
  89. package/dist/ui-kit/primitives/card.js +8 -0
  90. package/dist/ui-kit/primitives/card.js.map +1 -0
  91. package/dist/ui-kit/primitives/index.d.ts +12 -2
  92. package/dist/ui-kit/primitives/index.d.ts.map +1 -1
  93. package/dist/ui-kit/primitives/index.js +12 -2
  94. package/dist/ui-kit/primitives/index.js.map +1 -1
  95. package/dist/ui-kit/primitives/layout.d.ts +12 -0
  96. package/dist/ui-kit/primitives/layout.d.ts.map +1 -1
  97. package/dist/ui-kit/primitives/layout.js +20 -2
  98. package/dist/ui-kit/primitives/layout.js.map +1 -1
  99. package/dist/ui-kit/primitives/links.d.ts +28 -2
  100. package/dist/ui-kit/primitives/links.d.ts.map +1 -1
  101. package/dist/ui-kit/primitives/links.js +11 -6
  102. package/dist/ui-kit/primitives/links.js.map +1 -1
  103. package/dist/ui-kit/primitives/lists.d.ts +43 -0
  104. package/dist/ui-kit/primitives/lists.d.ts.map +1 -0
  105. package/dist/ui-kit/primitives/lists.js +34 -0
  106. package/dist/ui-kit/primitives/lists.js.map +1 -0
  107. package/dist/ui-kit/primitives/media-frame.d.ts +28 -0
  108. package/dist/ui-kit/primitives/media-frame.d.ts.map +1 -0
  109. package/dist/ui-kit/primitives/media-frame.js +58 -0
  110. package/dist/ui-kit/primitives/media-frame.js.map +1 -0
  111. package/dist/ui-kit/primitives/media.d.ts +38 -0
  112. package/dist/ui-kit/primitives/media.d.ts.map +1 -0
  113. package/dist/ui-kit/primitives/media.js +9 -0
  114. package/dist/ui-kit/primitives/media.js.map +1 -0
  115. package/dist/ui-kit/primitives/quote-button.d.ts +4 -1
  116. package/dist/ui-kit/primitives/quote-button.d.ts.map +1 -1
  117. package/dist/ui-kit/primitives/quote-button.js +3 -2
  118. package/dist/ui-kit/primitives/quote-button.js.map +1 -1
  119. package/dist/ui-kit/primitives/stat.d.ts +25 -0
  120. package/dist/ui-kit/primitives/stat.d.ts.map +1 -0
  121. package/dist/ui-kit/primitives/stat.js +7 -0
  122. package/dist/ui-kit/primitives/stat.js.map +1 -0
  123. package/dist/ui-kit/repeated-slots.d.ts +121 -0
  124. package/dist/ui-kit/repeated-slots.d.ts.map +1 -0
  125. package/dist/ui-kit/repeated-slots.js +81 -0
  126. package/dist/ui-kit/repeated-slots.js.map +1 -0
  127. package/dist/ui-kit/sections/accordion.d.ts +4 -1
  128. package/dist/ui-kit/sections/accordion.d.ts.map +1 -1
  129. package/dist/ui-kit/sections/accordion.js +2 -2
  130. package/dist/ui-kit/sections/accordion.js.map +1 -1
  131. package/dist/ui-kit/sections/contact-block.d.ts +4 -1
  132. package/dist/ui-kit/sections/contact-block.d.ts.map +1 -1
  133. package/dist/ui-kit/sections/contact-block.js +3 -3
  134. package/dist/ui-kit/sections/contact-block.js.map +1 -1
  135. package/dist/ui-kit/sections/faqs.d.ts +4 -1
  136. package/dist/ui-kit/sections/faqs.d.ts.map +1 -1
  137. package/dist/ui-kit/sections/faqs.js +4 -5
  138. package/dist/ui-kit/sections/faqs.js.map +1 -1
  139. package/dist/ui-kit/sections/hero.d.ts +113 -0
  140. package/dist/ui-kit/sections/hero.d.ts.map +1 -0
  141. package/dist/ui-kit/sections/hero.js +58 -0
  142. package/dist/ui-kit/sections/hero.js.map +1 -0
  143. package/dist/ui-kit/sections/index.d.ts +2 -0
  144. package/dist/ui-kit/sections/index.d.ts.map +1 -1
  145. package/dist/ui-kit/sections/index.js +2 -0
  146. package/dist/ui-kit/sections/index.js.map +1 -1
  147. package/dist/ui-kit/sections/price-guide.d.ts +4 -1
  148. package/dist/ui-kit/sections/price-guide.d.ts.map +1 -1
  149. package/dist/ui-kit/sections/price-guide.js +3 -3
  150. package/dist/ui-kit/sections/price-guide.js.map +1 -1
  151. package/dist/ui-kit/sections/price-table.d.ts +7 -9
  152. package/dist/ui-kit/sections/price-table.d.ts.map +1 -1
  153. package/dist/ui-kit/sections/price-table.js +8 -8
  154. package/dist/ui-kit/sections/price-table.js.map +1 -1
  155. package/dist/ui-kit/sections/proof-strip.d.ts +4 -1
  156. package/dist/ui-kit/sections/proof-strip.d.ts.map +1 -1
  157. package/dist/ui-kit/sections/proof-strip.js +2 -2
  158. package/dist/ui-kit/sections/proof-strip.js.map +1 -1
  159. package/dist/ui-kit/sections/reviews-band.d.ts +5 -2
  160. package/dist/ui-kit/sections/reviews-band.d.ts.map +1 -1
  161. package/dist/ui-kit/sections/reviews-band.js +2 -2
  162. package/dist/ui-kit/sections/reviews-band.js.map +1 -1
  163. package/dist/ui-kit/sections/services-grid.d.ts +82 -0
  164. package/dist/ui-kit/sections/services-grid.d.ts.map +1 -0
  165. package/dist/ui-kit/sections/services-grid.js +90 -0
  166. package/dist/ui-kit/sections/services-grid.js.map +1 -0
  167. package/dist/ui-kit/sections/site-footer.d.ts +4 -1
  168. package/dist/ui-kit/sections/site-footer.d.ts.map +1 -1
  169. package/dist/ui-kit/sections/site-footer.js +9 -6
  170. package/dist/ui-kit/sections/site-footer.js.map +1 -1
  171. package/dist/ui-kit/shell/current-link.d.ts +15 -1
  172. package/dist/ui-kit/shell/current-link.d.ts.map +1 -1
  173. package/dist/ui-kit/shell/current-link.js +10 -1
  174. package/dist/ui-kit/shell/current-link.js.map +1 -1
  175. package/dist/ui-kit/shell/index.d.ts +1 -0
  176. package/dist/ui-kit/shell/index.d.ts.map +1 -1
  177. package/dist/ui-kit/shell/index.js +1 -0
  178. package/dist/ui-kit/shell/index.js.map +1 -1
  179. package/dist/ui-kit/shell/intent-prefetch.d.ts +4 -0
  180. package/dist/ui-kit/shell/intent-prefetch.d.ts.map +1 -0
  181. package/dist/ui-kit/shell/intent-prefetch.js +61 -0
  182. package/dist/ui-kit/shell/intent-prefetch.js.map +1 -0
  183. package/dist/ui-kit/shell/mobile-drawer.d.ts +7 -3
  184. package/dist/ui-kit/shell/mobile-drawer.d.ts.map +1 -1
  185. package/dist/ui-kit/shell/mobile-drawer.js +20 -4
  186. package/dist/ui-kit/shell/mobile-drawer.js.map +1 -1
  187. package/dist/ui-kit/shell/site-header.d.ts +4 -1
  188. package/dist/ui-kit/shell/site-header.d.ts.map +1 -1
  189. package/dist/ui-kit/shell/site-header.js +9 -10
  190. package/dist/ui-kit/shell/site-header.js.map +1 -1
  191. package/dist/ui-kit/shell/social-links.d.ts +1 -2
  192. package/dist/ui-kit/shell/social-links.d.ts.map +1 -1
  193. package/dist/ui-kit/shell/social-links.js +6 -3
  194. package/dist/ui-kit/shell/social-links.js.map +1 -1
  195. package/dist/ui-kit/shell/utility-bar.d.ts +4 -1
  196. package/dist/ui-kit/shell/utility-bar.d.ts.map +1 -1
  197. package/dist/ui-kit/shell/utility-bar.js +2 -2
  198. package/dist/ui-kit/shell/utility-bar.js.map +1 -1
  199. package/dist/ui-kit/skin-index.d.ts +2 -1
  200. package/dist/ui-kit/skin-index.d.ts.map +1 -1
  201. package/dist/ui-kit/skin-index.js +2 -1
  202. package/dist/ui-kit/skin-index.js.map +1 -1
  203. package/dist/ui-kit/skin.d.ts +21 -4
  204. package/dist/ui-kit/skin.d.ts.map +1 -1
  205. package/dist/ui-kit/skin.js +14 -1
  206. package/dist/ui-kit/skin.js.map +1 -1
  207. package/dist/ui-kit/structure.css +383 -3
  208. package/package.json +10 -2
@@ -1 +1 @@
1
- {"version":3,"file":"photo-upload.js","sourceRoot":"","sources":["../../../src/ui-kit/form/photo-upload.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\n/**\n * `PhotoUpload`: the \"Add photos\" drop box over the shared photo preparation (`useBrandlabContactAttachments`). A\n * real file input, visually hidden but focusable, so the keyboard opens the picker with Enter or Space; the whole\n * box is its label and a drop target. `accept=\"image/*\"` and never a `capture` attribute, so phones offer the\n * library as well as the camera. The \"0 of 5\" counter is a `HeadlessStatus`, so each change is announced. Chosen\n * photos show as thumbnails with a remove button each.\n */\nimport type {\n BrandlabContactAttachmentErrorReason,\n UseBrandlabContactAttachmentsResult,\n} from '../../contact/attachments-client.js'\nimport { HeadlessStatus } from '../../ui.js'\nimport { Icon } from '../icons.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport { fillCopy } from './copy.js'\n\nexport type PhotoUploadSlot =\n | 'field'\n | 'label'\n | 'drop'\n | 'dropIcon'\n | 'counter'\n | 'photos'\n | 'photo'\n | 'thumb'\n | 'remove'\n | 'error'\nexport type PhotoUploadSkin = SkinEntry<PhotoUploadSlot>\n\nexport interface PhotoUploadProps extends PhotoUploadSkin {\n /** The file input's id. */\n readonly id: string\n /** The drop box's label, for example \"Add photos\". */\n readonly label: string\n /** The prepared photos, from `useBrandlabContactForm().attachments` or `useBrandlabContactAttachments()`. */\n readonly attachments: UseBrandlabContactAttachmentsResult\n /** The counter, with `{count}` and `{max}`, for example \"{count} of {max}\". */\n readonly counter: string\n /** Each remove button's name, with `{number}`, for example \"Remove photo {number}\". */\n readonly removeLabel: string\n /** `image/*` by default; `image/*,application/pdf` where the contract takes PDFs. */\n readonly accept?: string\n /**\n * The site's message for each reason a photo is refused (`count` may use `{max}`). Without them the shared photo\n * preparation's own wording shows.\n */\n readonly errorMessages?: Readonly<Record<BrandlabContactAttachmentErrorReason, string>> | undefined\n /** A form-level message, for example when photos are required. A refused photo's message wins. */\n readonly error?: string | undefined\n readonly required?: boolean\n /** Locks the box while an enquiry is sending. */\n readonly disabled?: boolean\n}\n\nexport function PhotoUpload({\n id,\n label,\n attachments,\n counter,\n removeLabel,\n accept = 'image/*',\n errorMessages,\n error,\n required = false,\n disabled = false,\n classes,\n}: PhotoUploadProps) {\n const counterId = `${id}-count`\n const errorId = `${id}-error`\n const reason = attachments.errorReason\n const refused = reason && errorMessages ? fillCopy(errorMessages[reason], { max: attachments.maxImages }) : attachments.errorMessage\n const message = refused ?? error\n const state = attachments.isProcessing ? 'busy' : attachments.isDragging ? 'dragging' : 'idle'\n return (\n <div data-bl=\"photo-upload\" {...slot(classes, 'field')}>\n <div\n {...slot(classes, 'drop')}\n data-state={state}\n data-disabled={disabled ? 'true' : undefined}\n onDragOver={disabled ? undefined : attachments.handleDragOver}\n onDragLeave={disabled ? undefined : attachments.handleDragLeave}\n onDrop={disabled ? undefined : (event) => void attachments.handleDrop(event)}\n >\n <input\n id={id}\n type=\"file\"\n accept={accept}\n multiple\n disabled={disabled}\n aria-required={required ? true : undefined}\n aria-invalid={message ? true : undefined}\n aria-describedby={[counterId, message ? errorId : undefined].filter(Boolean).join(' ')}\n data-bl-visually-hidden=\"\"\n onChange={(event) => void attachments.handleImageChange(event)}\n />\n <label {...slot(classes, 'label')} htmlFor={id}>\n <span {...slot(classes, 'dropIcon')}>\n <Icon name=\"camera\" />\n </span>\n <span>{label}</span>\n </label>\n <HeadlessStatus {...slot(classes, 'counter')} id={counterId}>\n {fillCopy(counter, { count: attachments.images.length, max: attachments.maxImages })}\n </HeadlessStatus>\n </div>\n {attachments.images.length > 0 ? (\n <ul {...slot(classes, 'photos')}>\n {attachments.images.map((image, index) => (\n <li {...slot(classes, 'photo')} key={image.preview}>\n <img {...slot(classes, 'thumb')} src={image.preview} alt=\"\" width={64} height={64} />\n <button\n {...slot(classes, 'remove')}\n type=\"button\"\n disabled={disabled}\n onClick={() => attachments.removeImage(index)}\n >\n <Icon name=\"close\" />\n <span data-bl-visually-hidden=\"\">{fillCopy(removeLabel, { number: index + 1 })}</span>\n </button>\n </li>\n ))}\n </ul>\n ) : null}\n {message ? (\n <div {...slot(classes, 'error')} id={errorId} role=\"alert\">\n {message}\n </div>\n ) : null}\n </div>\n )\n}\n"]}
1
+ {"version":3,"file":"photo-upload.js","sourceRoot":"","sources":["../../../src/ui-kit/form/photo-upload.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\n/**\n * `PhotoUpload`: the \"Add photos\" drop box over the shared photo preparation (`useBrandlabContactAttachments`). A\n * real file input, visually hidden but focusable, so the keyboard opens the picker with Enter or Space; the whole\n * box is its label and a drop target. `accept=\"image/*\"` and never a `capture` attribute, so phones offer the\n * library as well as the camera. The \"0 of 5\" counter is a `HeadlessStatus`, so each change is announced. Chosen\n * photos show as thumbnails with a remove button each.\n */\nimport type {\n BrandlabContactAttachmentErrorReason,\n UseBrandlabContactAttachmentsResult,\n} from '../../contact/attachments-client.js'\nimport { HeadlessStatus } from '../../ui.js'\nimport { Icon } from '../icons.js'\nimport type { RepeatedSlotOf } from '../repeated-slots.js'\nimport { repeatedSlot, slot, type SkinEntry } from '../skin.js'\nimport { fillCopy } from './copy.js'\n\nexport type PhotoUploadSlot =\n | 'field'\n | 'label'\n | 'drop'\n | 'dropIcon'\n | 'counter'\n | 'photos'\n | 'photo'\n | 'thumb'\n | 'remove'\n | 'error'\n/** Rendered once per chosen photo: styled from the skin stylesheet, never by class (3.14.0). */\nexport type PhotoUploadRepeatedSlot = RepeatedSlotOf<'photoUpload'>\nexport type PhotoUploadSkin = SkinEntry<PhotoUploadSlot, never, Record<never, never>, PhotoUploadRepeatedSlot>\n\nexport interface PhotoUploadProps extends PhotoUploadSkin {\n /** The file input's id. */\n readonly id: string\n /** The drop box's label, for example \"Add photos\". */\n readonly label: string\n /** The prepared photos, from `useBrandlabContactForm().attachments` or `useBrandlabContactAttachments()`. */\n readonly attachments: UseBrandlabContactAttachmentsResult\n /** The counter, with `{count}` and `{max}`, for example \"{count} of {max}\". */\n readonly counter: string\n /** Each remove button's name, with `{number}`, for example \"Remove photo {number}\". */\n readonly removeLabel: string\n /** `image/*` by default; `image/*,application/pdf` where the contract takes PDFs. */\n readonly accept?: string\n /**\n * The site's message for each reason a photo is refused (`count` may use `{max}`). Without them the shared photo\n * preparation's own wording shows.\n */\n readonly errorMessages?: Readonly<Record<BrandlabContactAttachmentErrorReason, string>> | undefined\n /** A form-level message, for example when photos are required. A refused photo's message wins. */\n readonly error?: string | undefined\n readonly required?: boolean\n /** Locks the box while an enquiry is sending. */\n readonly disabled?: boolean\n}\n\nexport function PhotoUpload({\n id,\n label,\n attachments,\n counter,\n removeLabel,\n accept = 'image/*',\n errorMessages,\n error,\n required = false,\n disabled = false,\n classes,\n}: PhotoUploadProps) {\n const counterId = `${id}-count`\n const errorId = `${id}-error`\n const reason = attachments.errorReason\n const refused = reason && errorMessages ? fillCopy(errorMessages[reason], { max: attachments.maxImages }) : attachments.errorMessage\n const message = refused ?? error\n const state = attachments.isProcessing ? 'busy' : attachments.isDragging ? 'dragging' : 'idle'\n return (\n <div data-bl=\"photo-upload\" {...slot(classes, 'field')}>\n <div\n {...slot(classes, 'drop')}\n data-state={state}\n data-disabled={disabled ? 'true' : undefined}\n onDragOver={disabled ? undefined : attachments.handleDragOver}\n onDragLeave={disabled ? undefined : attachments.handleDragLeave}\n onDrop={disabled ? undefined : (event) => void attachments.handleDrop(event)}\n >\n <input\n id={id}\n type=\"file\"\n accept={accept}\n multiple\n disabled={disabled}\n aria-required={required ? true : undefined}\n aria-invalid={message ? true : undefined}\n aria-describedby={[counterId, message ? errorId : undefined].filter(Boolean).join(' ')}\n data-bl-visually-hidden=\"\"\n onChange={(event) => void attachments.handleImageChange(event)}\n />\n <label {...slot(classes, 'label')} htmlFor={id}>\n <span {...slot(classes, 'dropIcon')}>\n <Icon name=\"camera\" />\n </span>\n <span>{label}</span>\n </label>\n <HeadlessStatus {...slot(classes, 'counter')} id={counterId}>\n {fillCopy(counter, { count: attachments.images.length, max: attachments.maxImages })}\n </HeadlessStatus>\n </div>\n {attachments.images.length > 0 ? (\n <ul {...slot(classes, 'photos')}>\n {attachments.images.map((image, index) => (\n <li {...repeatedSlot('photo')} key={image.preview}>\n <img {...repeatedSlot('thumb')} src={image.preview} alt=\"\" width={64} height={64} />\n <button\n {...repeatedSlot('remove')}\n type=\"button\"\n disabled={disabled}\n onClick={() => attachments.removeImage(index)}\n >\n <Icon name=\"close\" />\n <span data-bl-visually-hidden=\"\">{fillCopy(removeLabel, { number: index + 1 })}</span>\n </button>\n </li>\n ))}\n </ul>\n ) : null}\n {message ? (\n <div {...slot(classes, 'error')} id={errorId} role=\"alert\">\n {message}\n </div>\n ) : null}\n </div>\n )\n}\n"]}
@@ -17,6 +17,7 @@ import { type BrandlabContactContract, type ContactAttachmentPolicy } from '@bra
17
17
  import { type JSX } from 'react';
18
18
  import type { BrandlabAnalytics } from '../../analytics.js';
19
19
  import type { BrandlabContactAttachmentErrorReason, UseBrandlabContactAttachmentsOptions } from '../../contact/attachments-client.js';
20
+ import type { RepeatedSlotOf } from '../repeated-slots.js';
20
21
  import { type SkinEntry } from '../skin.js';
21
22
  import { type QuoteDialogSkin } from './quote-dialog.js';
22
23
  export declare const QUOTE_FORM_VARIANTS: readonly ["card", "plain", "inline"];
@@ -31,7 +32,9 @@ export type QuoteFormSlot = 'root' | 'row' | 'field' | 'label' | 'input' | 'text
31
32
  export interface QuoteFormLayout {
32
33
  readonly density?: 'comfortable' | 'compact';
33
34
  }
34
- export type QuoteFormSkin = SkinEntry<QuoteFormSlot, QuoteFormVariant, QuoteFormLayout>;
35
+ /** The photo boxes, rendered once per chosen photo: styled from the skin stylesheet, never by class (3.14.0). */
36
+ export type QuoteFormRepeatedSlot = RepeatedSlotOf<'quoteForm'>;
37
+ export type QuoteFormSkin = SkinEntry<QuoteFormSlot, QuoteFormVariant, QuoteFormLayout, QuoteFormRepeatedSlot>;
35
38
  /** Every visible phrase of the form, in the site's Australian English. */
36
39
  export interface QuoteFormCopy {
37
40
  readonly labels: {
@@ -1 +1 @@
1
- {"version":3,"file":"quote-form.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/form/quote-form.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"quote-form.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/form/quote-form.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"quote-form.js","sourceRoot":"","sources":["../../../src/ui-kit/form/quote-form.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\n/**\n * `QuoteForm`: the one enquiry form for the hero, the quote dialog, the contact page and cost guides, on the shared\n * contact runtime (`useBrandlabContactForm`, `POST /api/contact`, photo preparation, idempotent retries).\n *\n * Locked layout (F8): Name · Suburb; Phone · Email, both required; the message (\"How can we help?\"), 5 rows; the\n * \"Add photos\" drop box with its \"0 of 5\" counter; the button; then one consent line linking the privacy policy. One\n * column below 640 px. No job select, no \"(required)\", no helper or reassurance lines: every label and message is\n * the site's copy. Errors appear only after a submit attempt, as a summary plus a message under each field; every\n * typed value and chosen photo is kept on any error. The button stays disabled until the page has hydrated and is\n * locked with a busy label while photos are prepared or the enquiry sends. An accepted enquiry sends one\n * `contact_form` (with `has_photos`) and opens the thank-you page.\n *\n * `contract` and `analytics` can't cross from a server component, so a site binds them once with `createQuoteForm`\n * in its own `'use client'` file and renders the bound `QuoteForm` and `QuoteDialog` from its pages.\n */\nimport {\n defineContactContract,\n isValidAustralianPhoneNumber,\n type BrandlabContactContract,\n type ContactAttachmentPolicy,\n} from '@brandlab-digital/site-core/contact'\nimport { usePathname } from 'next/navigation'\nimport { useMemo, useRef, useState, type JSX, type RefObject } from 'react'\nimport type { BrandlabAnalytics } from '../../analytics.js'\nimport type {\n BrandlabContactAttachmentErrorReason,\n UseBrandlabContactAttachmentsOptions,\n} from '../../contact/attachments-client.js'\nimport { contactFieldProps, useBrandlabContactForm } from '../../contact/form-client.js'\nimport { CONTACT_FORM_FIELDS, CONTACT_PHONE_CHARACTERS } from '../../contact/shared.js'\nimport { HeadlessErrorSummary } from '../../ui.js'\nimport { HeadlessErrorFocus } from '../../ui-client.js'\nimport { TextLink } from '../primitives/links.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport { Field } from './field.js'\nimport { PhotoUpload } from './photo-upload.js'\nimport { QuoteDialog, type QuoteDialogSkin } from './quote-dialog.js'\n\nexport const QUOTE_FORM_VARIANTS = ['card', 'plain', 'inline'] as const\nexport type QuoteFormVariant = (typeof QUOTE_FORM_VARIANTS)[number]\n\n/** The form's id and its lead diagnostics' `form_id`, one per placement. */\nexport const QUOTE_FORM_PLACEMENTS = ['quote-hero', 'quote-dialog', 'contact', 'guide'] as const\nexport type QuoteFormPlacement = (typeof QUOTE_FORM_PLACEMENTS)[number]\n\n/** The variant each placement takes unless the skin names one: the hero aside, the dialog and contact page, a guide. */\nexport const QUOTE_FORM_PLACEMENT_VARIANTS: Readonly<Record<QuoteFormPlacement, QuoteFormVariant>> = {\n 'quote-hero': 'card',\n 'quote-dialog': 'plain',\n contact: 'plain',\n guide: 'inline',\n}\n\nexport type QuoteFormSlot =\n | 'root'\n | 'row'\n | 'field'\n | 'label'\n | 'input'\n | 'textarea'\n | 'drop'\n | 'dropIcon'\n | 'counter'\n | 'photos'\n | 'photo'\n | 'thumb'\n | 'remove'\n | 'submit'\n | 'consent'\n | 'errorSummary'\n | 'error'\n | 'status'\n/** Labels always sit above their fields; density sets the spacing. */\nexport interface QuoteFormLayout {\n readonly density?: 'comfortable' | 'compact'\n}\nexport type QuoteFormSkin = SkinEntry<QuoteFormSlot, QuoteFormVariant, QuoteFormLayout>\n\n/** Every visible phrase of the form, in the site's Australian English. */\nexport interface QuoteFormCopy {\n readonly labels: {\n readonly name: string\n readonly suburb: string\n readonly phone: string\n readonly email: string\n /** For example \"How can we help?\". */\n readonly message: string\n /** For example \"Add photos\". */\n readonly photos: string\n }\n /** The message placeholder, for example \"Tell us about your project\". */\n readonly messagePlaceholder: string\n /** The site's recorded button label, for example \"Get my free quote\". */\n readonly submit: string\n /** Busy labels: \"Sending…\", \"Sending photos…\" and \"Preparing photos…\". */\n readonly sending: string\n readonly sendingPhotos: string\n readonly preparingPhotos: string\n /** The photo counter with `{count}` and `{max}`, for example \"{count} of {max}\". */\n readonly photoCount: string\n /** Each remove button's name with `{number}`, for example \"Remove photo {number}\". */\n readonly removePhoto: string\n /** The one consent line: the sentence, the words in it that link, and the privacy policy's path. */\n readonly consent: { readonly sentence: string; readonly linkText: string; readonly href: string }\n /** The error summary's heading, for example \"Please check these details\". */\n readonly errorSummary: string\n /** A message under each field after a submit attempt. `photos` is needed only when photos are required. */\n readonly errors: {\n readonly name: string\n readonly suburb: string\n readonly phone: string\n readonly phoneFormat: string\n readonly email: string\n readonly emailFormat: string\n readonly message: string\n readonly photos?: string\n }\n /**\n * Why a chosen photo was refused: not an image type, too large, all photos together too large, more than the\n * limit (`{max}` allowed), or it couldn't be prepared (an iPhone photo that wouldn't convert). Needed when the\n * contract takes photos.\n */\n readonly photoErrors?: Readonly<Record<BrandlabContactAttachmentErrorReason, string>>\n /** Shown when sending fails: the photos were refused, or anything else (say how to call instead). */\n readonly failed: { readonly attachment: string; readonly general: string }\n}\n\nexport interface QuoteFormProps extends QuoteFormSkin {\n readonly formId: QuoteFormPlacement\n /** The contact contract from src/config/contact.ts. */\n readonly contract: BrandlabContactContract\n /** The site's defineBrandlabAnalytics binding. */\n readonly analytics?: BrandlabAnalytics | undefined\n /** Photo limits; the contract's attachment mode decides the default. */\n readonly attachmentPolicy?: ContactAttachmentPolicy | undefined\n /** The thank-you page opened after an accepted enquiry, for example `/thank-you`. */\n readonly redirectTo: string\n readonly copy: QuoteFormCopy\n /** The enquiry email's page row, for example \"Contact\". */\n readonly pageLabel?: string | undefined\n /** The runtime's honeypot field (default `website`). */\n readonly honeypotField?: string | undefined\n /** The contact endpoint (default `/api/contact`). */\n readonly contactEndpoint?: string | undefined\n /** Client navigation to the thank-you page, for example `router.push`; a full page load by default. */\n readonly navigate?: ((href: string) => void) | undefined\n /** Test seams: a fetch implementation and the photo preparation's options. */\n readonly fetcher?: typeof fetch | undefined\n readonly attachmentOptions?: Omit<UseBrandlabContactAttachmentsOptions, 'policy'> | undefined\n}\n\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\nconst PHOTOS = 'photos'\n\ninterface QuoteFields {\n readonly name: string\n /** The suburb: always required when the contract has one, as the server requires every location field. */\n readonly location: string | undefined\n readonly phone: string\n readonly email: string\n readonly message: string\n readonly maxLength: Readonly<Record<string, number | undefined>>\n}\n\n/**\n * The contract's keys for the locked layout. A required field the form can't render would make every enquiry fail,\n * so it throws instead, when the site binds the form (at build).\n */\nfunction quoteFields(contract: BrandlabContactContract): QuoteFields {\n defineContactContract(contract)\n const role = (name: string) => contract.fields.find((field) => field.role === name)\n const location = role('location')\n if (location && location.kind !== 'text') {\n throw new Error(`QuoteForm renders the suburb as a text field; the contract's \"${location.key}\" is a ${location.kind}.`)\n }\n const unrendered = contract.fields.find((field) => field.role === 'custom' && field.required)\n if (unrendered) {\n throw new Error(`QuoteForm has no place for the required field \"${unrendered.key}\"; make it optional or drop it.`)\n }\n return {\n name: role('name')!.key,\n location: location?.key,\n phone: role('phone')!.key,\n email: role('email')!.key,\n message: role('message')!.key,\n maxLength: Object.fromEntries(contract.fields.map((field) => [field.key, field.maxLength])),\n }\n}\n\nconst PHOTO_ERROR_REASONS = ['type', 'size', 'total', 'count', 'prepare'] as const\n\nfunction assertCopy(copy: QuoteFormCopy, photos: 'none' | 'optional' | 'required') {\n const text = [\n ...Object.values(copy.labels),\n copy.messagePlaceholder,\n copy.submit,\n copy.sending,\n copy.sendingPhotos,\n copy.preparingPhotos,\n copy.photoCount,\n copy.removePhoto,\n copy.consent.sentence,\n copy.consent.linkText,\n copy.consent.href,\n copy.errorSummary,\n copy.errors.name,\n copy.errors.suburb,\n copy.errors.phone,\n copy.errors.phoneFormat,\n copy.errors.email,\n copy.errors.emailFormat,\n copy.errors.message,\n copy.failed.attachment,\n copy.failed.general,\n ...(photos === 'none' ? [] : PHOTO_ERROR_REASONS.map((reason) => copy.photoErrors?.[reason])),\n ...(photos === 'required' ? [copy.errors.photos] : []),\n ]\n if (text.some((value) => typeof value !== 'string' || !value.trim())) {\n throw new Error('QuoteForm copy is incomplete: every label, message and the consent line is the site\\'s own text.')\n }\n}\n\n/** The checks the server makes, run before sending: never stricter than the server, so no real enquiry is blocked. */\nfunction validate(\n form: HTMLFormElement,\n fields: QuoteFields,\n copy: QuoteFormCopy,\n photos: { required: boolean; count: number },\n): Record<string, string> {\n const value = (name: string) => {\n const element = form.elements.namedItem(name)\n return element && 'value' in element ? String(element.value).trim() : ''\n }\n const errors: Record<string, string> = {}\n if (!value(fields.name)) errors[fields.name] = copy.errors.name\n if (fields.location && !value(fields.location)) errors[fields.location] = copy.errors.suburb\n const phone = value(fields.phone)\n if (!phone) errors[fields.phone] = copy.errors.phone\n else if (!CONTACT_PHONE_CHARACTERS.test(phone) || !isValidAustralianPhoneNumber(phone)) {\n errors[fields.phone] = copy.errors.phoneFormat\n }\n const email = value(fields.email).toLowerCase()\n if (!email) errors[fields.email] = copy.errors.email\n else if (!EMAIL_PATTERN.test(email)) errors[fields.email] = copy.errors.emailFormat\n if (!value(fields.message)) errors[fields.message] = copy.errors.message\n if (photos.required && photos.count === 0 && copy.errors.photos) errors[PHOTOS] = copy.errors.photos\n return errors\n}\n\n/**\n * The site's message for a field the server refused: the runtime's own wording never shows. An empty field gets its\n * \"enter\" message; a filled phone or email its format message.\n */\nfunction serverFieldMessage(form: HTMLFormElement | null, key: string, fields: QuoteFields, copy: QuoteFormCopy) {\n const element = form?.elements.namedItem(key)\n const filled = Boolean(element && 'value' in element && String(element.value).trim())\n if (key === fields.phone) return filled ? copy.errors.phoneFormat : copy.errors.phone\n if (key === fields.email) return filled ? copy.errors.emailFormat : copy.errors.email\n if (key === fields.name) return copy.errors.name\n if (key === fields.location) return copy.errors.suburb\n return copy.errors.message\n}\n\nfunction ConsentLine({ consent, hooks }: { consent: QuoteFormCopy['consent']; hooks: ReturnType<typeof slot> }) {\n const at = consent.sentence.indexOf(consent.linkText)\n const link = <TextLink href={consent.href}>{at < 0 ? consent.sentence : consent.linkText}</TextLink>\n return (\n <p {...hooks}>\n {at < 0 ? link : (\n <>\n {consent.sentence.slice(0, at)}\n {link}\n {consent.sentence.slice(at + consent.linkText.length)}\n </>\n )}\n </p>\n )\n}\n\nexport function QuoteForm({\n formId,\n contract,\n analytics,\n attachmentPolicy,\n redirectTo,\n copy,\n pageLabel,\n honeypotField = CONTACT_FORM_FIELDS.honeypot,\n contactEndpoint,\n navigate,\n fetcher,\n attachmentOptions,\n variant,\n layout,\n classes,\n}: QuoteFormProps) {\n const fields = useMemo(() => quoteFields(contract), [contract])\n const mode = contract.attachments.mode\n const photosEnabled = mode !== 'none'\n const photosRequired = mode === 'images-required'\n assertCopy(copy, photosRequired ? 'required' : photosEnabled ? 'optional' : 'none')\n const pagePath = usePathname() || '/'\n const [clientErrors, setClientErrors] = useState<Record<string, string> | null>(null)\n const [attempt, setAttempt] = useState(0)\n const [withPhotos, setWithPhotos] = useState(false)\n const photoCount = useRef(0)\n\n const form = useBrandlabContactForm({\n contract,\n ...(analytics ? { analytics } : {}),\n pagePath,\n ...(pageLabel ? { pageLabel } : {}),\n formId,\n redirectTo,\n redirectDelayMs: 0,\n ...(navigate ? { navigate } : {}),\n ...(contactEndpoint ? { contactEndpoint } : {}),\n ...(fetcher ? { fetcher } : {}),\n attachments: { ...attachmentOptions, ...(attachmentPolicy ? { policy: attachmentPolicy } : {}) },\n onSubmitStart: ({ form: element }) => {\n const errors = validate(element, fields, copy, { required: photosRequired, count: photoCount.current })\n setAttempt((count) => count + 1)\n if (Object.keys(errors).length > 0) {\n setClientErrors(errors)\n return false\n }\n setClientErrors(null)\n setWithPhotos(photoCount.current > 0)\n return undefined\n },\n })\n photoCount.current = form.attachments.images.length\n\n const fieldId = (key: string) => `${formId}-${key}`\n const order = [fields.name, fields.location, fields.phone, fields.email, fields.message, photosEnabled ? PHOTOS : undefined]\n .filter((key): key is string => Boolean(key))\n const errors: Record<string, string> = clientErrors ?? Object.fromEntries(\n order.flatMap((key) =>\n key !== PHOTOS && form.fieldError(key) ? [[key, serverFieldMessage(form.formProps.ref.current, key, fields, copy)]] : []),\n )\n const summary = order.flatMap((key) => (errors[key] ? [{ fieldId: fieldId(key), message: errors[key] }] : []))\n\n const leaving = form.succeeded\n const busyLabel = form.attachments.isProcessing\n ? copy.preparingPhotos\n : form.pending || leaving\n ? withPhotos ? copy.sendingPhotos : copy.sending\n : undefined\n const result = form.result\n const failure = !busyLabel && clientErrors === null && result && !result.ok && summary.length === 0\n ? result.code === 'attachment_rejected' ? copy.failed.attachment : copy.failed.general\n : undefined\n\n const fieldClasses = { field: classes?.field, label: classes?.label, error: classes?.error }\n const max = (key: string) => fields.maxLength[key]\n const textField = (key: string, label: string, props: { type: 'text' | 'tel' | 'email'; autoComplete: string }) => (\n <Field id={fieldId(key)} label={label} error={errors[key]} required classes={fieldClasses}>\n {(control) => (\n <input\n {...contactFieldProps(form, key)}\n {...control}\n {...slot(classes, 'input')}\n type={props.type}\n autoComplete={props.autoComplete}\n {...(props.type === 'tel' ? { inputMode: 'tel' as const } : { maxLength: max(key) })}\n {...(props.type === 'email' ? { autoCapitalize: 'none', spellCheck: false } : {})}\n />\n )}\n </Field>\n )\n\n return (\n <form\n {...form.formProps}\n noValidate\n data-bl=\"quote-form\"\n data-variant={variant ?? QUOTE_FORM_PLACEMENT_VARIANTS[formId]}\n data-density={layout?.density ?? 'comfortable'}\n className={classes?.root}\n >\n <HeadlessErrorSummary\n {...slot(classes, 'errorSummary')}\n id={`${formId}-errors`}\n headingId={`${formId}-errors-heading`}\n heading={copy.errorSummary}\n errors={summary}\n />\n <HeadlessErrorFocus key={attempt} active={summary.length > 0} formId={formId} summaryId={`${formId}-errors`} />\n <div data-bl-honeypot=\"\" data-bl-visually-hidden=\"\" aria-hidden=\"true\" inert>\n <input type=\"text\" name={honeypotField} tabIndex={-1} autoComplete=\"off\" />\n </div>\n\n <div {...slot(classes, 'row')}>\n {textField(fields.name, copy.labels.name, { type: 'text', autoComplete: 'name' })}\n {fields.location ? (\n <Field id={fieldId(fields.location)} label={copy.labels.suburb} error={errors[fields.location]} required classes={fieldClasses}>\n {(control) => (\n <input\n {...contactFieldProps(form, fields.location!)}\n {...control}\n {...slot(classes, 'input')}\n type=\"text\"\n autoComplete=\"address-level2\"\n maxLength={max(fields.location!)}\n />\n )}\n </Field>\n ) : null}\n </div>\n <div {...slot(classes, 'row')}>\n {textField(fields.phone, copy.labels.phone, { type: 'tel', autoComplete: 'tel' })}\n {textField(fields.email, copy.labels.email, { type: 'email', autoComplete: 'email' })}\n </div>\n <Field id={fieldId(fields.message)} label={copy.labels.message} error={errors[fields.message]} required classes={fieldClasses}>\n {(control) => (\n <textarea\n {...contactFieldProps(form, fields.message)}\n {...control}\n {...slot(classes, 'textarea')}\n rows={5}\n placeholder={copy.messagePlaceholder}\n maxLength={max(fields.message)}\n />\n )}\n </Field>\n {photosEnabled ? (\n <PhotoUpload\n id={fieldId(PHOTOS)}\n label={copy.labels.photos}\n attachments={form.attachments}\n counter={copy.photoCount}\n removeLabel={copy.removePhoto}\n errorMessages={copy.photoErrors}\n accept={mode === 'images-and-pdfs-optional' ? 'image/*,application/pdf' : 'image/*'}\n error={errors[PHOTOS]}\n required={photosRequired}\n disabled={form.pending || leaving}\n classes={classes}\n />\n ) : null}\n\n <button\n {...form.submitProps}\n {...slot(classes, 'submit')}\n disabled={form.submitDisabled || leaving}\n data-state={busyLabel ? 'busy' : 'idle'}\n >\n {busyLabel ?? copy.submit}\n </button>\n <ConsentLine consent={copy.consent} hooks={slot(classes, 'consent')} />\n <div\n {...slot(classes, 'status')}\n ref={form.statusRef as RefObject<HTMLDivElement>}\n role=\"status\"\n aria-live=\"polite\"\n tabIndex={-1}\n data-state={failure ? 'error' : busyLabel ? 'busy' : 'idle'}\n >\n {failure ?? (busyLabel ? <span data-bl-visually-hidden=\"\">{busyLabel}</span> : null)}\n </div>\n </form>\n )\n}\n\nexport interface CreateQuoteFormOptions {\n readonly contract: BrandlabContactContract\n readonly analytics?: BrandlabAnalytics | undefined\n readonly attachmentPolicy?: ContactAttachmentPolicy | undefined\n /** The thank-you page, for example `/thank-you`. */\n readonly redirectTo: string\n readonly copy: QuoteFormCopy\n /** The site's quote form skin; leave `variant` unset so each placement takes its own. */\n readonly skin?: QuoteFormSkin | undefined\n /** The quote dialog's skin. */\n readonly dialogSkin?: QuoteDialogSkin | undefined\n readonly honeypotField?: string | undefined\n readonly contactEndpoint?: string | undefined\n readonly navigate?: ((href: string) => void) | undefined\n readonly fetcher?: typeof fetch | undefined\n readonly attachmentOptions?: Omit<UseBrandlabContactAttachmentsOptions, 'policy'> | undefined\n}\n\n/** What a page passes to the bound form: plain data, so a server component can render it. */\nexport interface BoundQuoteFormProps {\n readonly formId: QuoteFormPlacement\n readonly pageLabel?: string\n /** This placement's own placeholder, for example on a cost guide. */\n readonly messagePlaceholder?: string\n readonly layout?: QuoteFormLayout\n}\n\nexport interface BoundQuoteDialogProps {\n /** The dialog's H2, for example \"Get a free quote\". */\n readonly title: string\n /** The close button's accessible name, for example \"Close\". */\n readonly closeLabel: string\n readonly pageLabel?: string\n readonly messagePlaceholder?: string\n}\n\nexport interface BoundQuoteForm {\n readonly QuoteForm: (props: BoundQuoteFormProps) => JSX.Element\n readonly QuoteDialog: (props: BoundQuoteDialogProps) => JSX.Element\n}\n\n/**\n * Binds the form to the site's contract, analytics, photo policy, thank-you page, copy and skin. Call it once in the\n * site's own `'use client'` file (`src/site/quote-form.tsx`) and export the two components:\n *\n * ```tsx\n * 'use client'\n * const quote = createQuoteForm({ contract: contactContract, analytics, redirectTo: '/thank-you', copy, skin: skin.quoteForm })\n * export const QuoteForm = quote.QuoteForm\n * export const QuoteDialog = quote.QuoteDialog\n * ```\n *\n * It checks the contract and copy when the module loads, so a form that couldn't send fails the build instead.\n */\nexport function createQuoteForm(options: CreateQuoteFormOptions): BoundQuoteForm {\n if (!options || typeof options !== 'object') throw new TypeError('createQuoteForm needs the contract, copy and thank-you page.')\n if (typeof options.redirectTo !== 'string' || !/^\\/(?!\\/)[^\\s]*$/.test(options.redirectTo)) {\n throw new TypeError('redirectTo must be a root-relative path such as /thank-you.')\n }\n quoteFields(options.contract)\n const mode = options.contract.attachments.mode\n assertCopy(options.copy, mode === 'images-required' ? 'required' : mode === 'none' ? 'none' : 'optional')\n const { skin, dialogSkin, ...shared } = options\n\n function BoundQuoteForm({ formId, pageLabel, messagePlaceholder, layout }: BoundQuoteFormProps) {\n const merged = skin?.layout || layout ? { ...skin?.layout, ...layout } : undefined\n return (\n <QuoteForm\n {...shared}\n formId={formId}\n pageLabel={pageLabel}\n copy={messagePlaceholder ? { ...shared.copy, messagePlaceholder } : shared.copy}\n variant={skin?.variant}\n layout={merged}\n classes={skin?.classes}\n />\n )\n }\n\n function BoundQuoteDialog({ title, closeLabel, pageLabel, messagePlaceholder }: BoundQuoteDialogProps) {\n return (\n <QuoteDialog title={title} closeLabel={closeLabel} classes={dialogSkin?.classes}>\n <BoundQuoteForm\n formId=\"quote-dialog\"\n {...(pageLabel ? { pageLabel } : {})}\n {...(messagePlaceholder ? { messagePlaceholder } : {})}\n />\n </QuoteDialog>\n )\n }\n\n return Object.freeze({ QuoteForm: BoundQuoteForm, QuoteDialog: BoundQuoteDialog })\n}\n"]}
1
+ {"version":3,"file":"quote-form.js","sourceRoot":"","sources":["../../../src/ui-kit/form/quote-form.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\n/**\n * `QuoteForm`: the one enquiry form for the hero, the quote dialog, the contact page and cost guides, on the shared\n * contact runtime (`useBrandlabContactForm`, `POST /api/contact`, photo preparation, idempotent retries).\n *\n * Locked layout (F8): Name · Suburb; Phone · Email, both required; the message (\"How can we help?\"), 5 rows; the\n * \"Add photos\" drop box with its \"0 of 5\" counter; the button; then one consent line linking the privacy policy. One\n * column below 640 px. No job select, no \"(required)\", no helper or reassurance lines: every label and message is\n * the site's copy. Errors appear only after a submit attempt, as a summary plus a message under each field; every\n * typed value and chosen photo is kept on any error. The button stays disabled until the page has hydrated and is\n * locked with a busy label while photos are prepared or the enquiry sends. An accepted enquiry sends one\n * `contact_form` (with `has_photos`) and opens the thank-you page.\n *\n * `contract` and `analytics` can't cross from a server component, so a site binds them once with `createQuoteForm`\n * in its own `'use client'` file and renders the bound `QuoteForm` and `QuoteDialog` from its pages.\n */\nimport {\n defineContactContract,\n isValidAustralianPhoneNumber,\n type BrandlabContactContract,\n type ContactAttachmentPolicy,\n} from '@brandlab-digital/site-core/contact'\nimport { usePathname } from 'next/navigation'\nimport { useMemo, useRef, useState, type JSX, type RefObject } from 'react'\nimport type { BrandlabAnalytics } from '../../analytics.js'\nimport type {\n BrandlabContactAttachmentErrorReason,\n UseBrandlabContactAttachmentsOptions,\n} from '../../contact/attachments-client.js'\nimport { contactFieldProps, useBrandlabContactForm } from '../../contact/form-client.js'\nimport { CONTACT_FORM_FIELDS, CONTACT_PHONE_CHARACTERS } from '../../contact/shared.js'\nimport { HeadlessErrorSummary } from '../../ui.js'\nimport { HeadlessErrorFocus } from '../../ui-client.js'\nimport { TextLink } from '../primitives/links.js'\nimport type { RepeatedSlotOf } from '../repeated-slots.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport { Field } from './field.js'\nimport { PhotoUpload } from './photo-upload.js'\nimport { QuoteDialog, type QuoteDialogSkin } from './quote-dialog.js'\n\nexport const QUOTE_FORM_VARIANTS = ['card', 'plain', 'inline'] as const\nexport type QuoteFormVariant = (typeof QUOTE_FORM_VARIANTS)[number]\n\n/** The form's id and its lead diagnostics' `form_id`, one per placement. */\nexport const QUOTE_FORM_PLACEMENTS = ['quote-hero', 'quote-dialog', 'contact', 'guide'] as const\nexport type QuoteFormPlacement = (typeof QUOTE_FORM_PLACEMENTS)[number]\n\n/** The variant each placement takes unless the skin names one: the hero aside, the dialog and contact page, a guide. */\nexport const QUOTE_FORM_PLACEMENT_VARIANTS: Readonly<Record<QuoteFormPlacement, QuoteFormVariant>> = {\n 'quote-hero': 'card',\n 'quote-dialog': 'plain',\n contact: 'plain',\n guide: 'inline',\n}\n\nexport type QuoteFormSlot =\n | 'root'\n | 'row'\n | 'field'\n | 'label'\n | 'input'\n | 'textarea'\n | 'drop'\n | 'dropIcon'\n | 'counter'\n | 'photos'\n | 'photo'\n | 'thumb'\n | 'remove'\n | 'submit'\n | 'consent'\n | 'errorSummary'\n | 'error'\n | 'status'\n/** Labels always sit above their fields; density sets the spacing. */\nexport interface QuoteFormLayout {\n readonly density?: 'comfortable' | 'compact'\n}\n/** The photo boxes, rendered once per chosen photo: styled from the skin stylesheet, never by class (3.14.0). */\nexport type QuoteFormRepeatedSlot = RepeatedSlotOf<'quoteForm'>\nexport type QuoteFormSkin = SkinEntry<QuoteFormSlot, QuoteFormVariant, QuoteFormLayout, QuoteFormRepeatedSlot>\n\n/** Every visible phrase of the form, in the site's Australian English. */\nexport interface QuoteFormCopy {\n readonly labels: {\n readonly name: string\n readonly suburb: string\n readonly phone: string\n readonly email: string\n /** For example \"How can we help?\". */\n readonly message: string\n /** For example \"Add photos\". */\n readonly photos: string\n }\n /** The message placeholder, for example \"Tell us about your project\". */\n readonly messagePlaceholder: string\n /** The site's recorded button label, for example \"Get my free quote\". */\n readonly submit: string\n /** Busy labels: \"Sending…\", \"Sending photos…\" and \"Preparing photos…\". */\n readonly sending: string\n readonly sendingPhotos: string\n readonly preparingPhotos: string\n /** The photo counter with `{count}` and `{max}`, for example \"{count} of {max}\". */\n readonly photoCount: string\n /** Each remove button's name with `{number}`, for example \"Remove photo {number}\". */\n readonly removePhoto: string\n /** The one consent line: the sentence, the words in it that link, and the privacy policy's path. */\n readonly consent: { readonly sentence: string; readonly linkText: string; readonly href: string }\n /** The error summary's heading, for example \"Please check these details\". */\n readonly errorSummary: string\n /** A message under each field after a submit attempt. `photos` is needed only when photos are required. */\n readonly errors: {\n readonly name: string\n readonly suburb: string\n readonly phone: string\n readonly phoneFormat: string\n readonly email: string\n readonly emailFormat: string\n readonly message: string\n readonly photos?: string\n }\n /**\n * Why a chosen photo was refused: not an image type, too large, all photos together too large, more than the\n * limit (`{max}` allowed), or it couldn't be prepared (an iPhone photo that wouldn't convert). Needed when the\n * contract takes photos.\n */\n readonly photoErrors?: Readonly<Record<BrandlabContactAttachmentErrorReason, string>>\n /** Shown when sending fails: the photos were refused, or anything else (say how to call instead). */\n readonly failed: { readonly attachment: string; readonly general: string }\n}\n\nexport interface QuoteFormProps extends QuoteFormSkin {\n readonly formId: QuoteFormPlacement\n /** The contact contract from src/config/contact.ts. */\n readonly contract: BrandlabContactContract\n /** The site's defineBrandlabAnalytics binding. */\n readonly analytics?: BrandlabAnalytics | undefined\n /** Photo limits; the contract's attachment mode decides the default. */\n readonly attachmentPolicy?: ContactAttachmentPolicy | undefined\n /** The thank-you page opened after an accepted enquiry, for example `/thank-you`. */\n readonly redirectTo: string\n readonly copy: QuoteFormCopy\n /** The enquiry email's page row, for example \"Contact\". */\n readonly pageLabel?: string | undefined\n /** The runtime's honeypot field (default `website`). */\n readonly honeypotField?: string | undefined\n /** The contact endpoint (default `/api/contact`). */\n readonly contactEndpoint?: string | undefined\n /** Client navigation to the thank-you page, for example `router.push`; a full page load by default. */\n readonly navigate?: ((href: string) => void) | undefined\n /** Test seams: a fetch implementation and the photo preparation's options. */\n readonly fetcher?: typeof fetch | undefined\n readonly attachmentOptions?: Omit<UseBrandlabContactAttachmentsOptions, 'policy'> | undefined\n}\n\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\nconst PHOTOS = 'photos'\n\ninterface QuoteFields {\n readonly name: string\n /** The suburb: always required when the contract has one, as the server requires every location field. */\n readonly location: string | undefined\n readonly phone: string\n readonly email: string\n readonly message: string\n readonly maxLength: Readonly<Record<string, number | undefined>>\n}\n\n/**\n * The contract's keys for the locked layout. A required field the form can't render would make every enquiry fail,\n * so it throws instead, when the site binds the form (at build).\n */\nfunction quoteFields(contract: BrandlabContactContract): QuoteFields {\n defineContactContract(contract)\n const role = (name: string) => contract.fields.find((field) => field.role === name)\n const location = role('location')\n if (location && location.kind !== 'text') {\n throw new Error(`QuoteForm renders the suburb as a text field; the contract's \"${location.key}\" is a ${location.kind}.`)\n }\n const unrendered = contract.fields.find((field) => field.role === 'custom' && field.required)\n if (unrendered) {\n throw new Error(`QuoteForm has no place for the required field \"${unrendered.key}\"; make it optional or drop it.`)\n }\n return {\n name: role('name')!.key,\n location: location?.key,\n phone: role('phone')!.key,\n email: role('email')!.key,\n message: role('message')!.key,\n maxLength: Object.fromEntries(contract.fields.map((field) => [field.key, field.maxLength])),\n }\n}\n\nconst PHOTO_ERROR_REASONS = ['type', 'size', 'total', 'count', 'prepare'] as const\n\nfunction assertCopy(copy: QuoteFormCopy, photos: 'none' | 'optional' | 'required') {\n const text = [\n ...Object.values(copy.labels),\n copy.messagePlaceholder,\n copy.submit,\n copy.sending,\n copy.sendingPhotos,\n copy.preparingPhotos,\n copy.photoCount,\n copy.removePhoto,\n copy.consent.sentence,\n copy.consent.linkText,\n copy.consent.href,\n copy.errorSummary,\n copy.errors.name,\n copy.errors.suburb,\n copy.errors.phone,\n copy.errors.phoneFormat,\n copy.errors.email,\n copy.errors.emailFormat,\n copy.errors.message,\n copy.failed.attachment,\n copy.failed.general,\n ...(photos === 'none' ? [] : PHOTO_ERROR_REASONS.map((reason) => copy.photoErrors?.[reason])),\n ...(photos === 'required' ? [copy.errors.photos] : []),\n ]\n if (text.some((value) => typeof value !== 'string' || !value.trim())) {\n throw new Error('QuoteForm copy is incomplete: every label, message and the consent line is the site\\'s own text.')\n }\n}\n\n/** The checks the server makes, run before sending: never stricter than the server, so no real enquiry is blocked. */\nfunction validate(\n form: HTMLFormElement,\n fields: QuoteFields,\n copy: QuoteFormCopy,\n photos: { required: boolean; count: number },\n): Record<string, string> {\n const value = (name: string) => {\n const element = form.elements.namedItem(name)\n return element && 'value' in element ? String(element.value).trim() : ''\n }\n const errors: Record<string, string> = {}\n if (!value(fields.name)) errors[fields.name] = copy.errors.name\n if (fields.location && !value(fields.location)) errors[fields.location] = copy.errors.suburb\n const phone = value(fields.phone)\n if (!phone) errors[fields.phone] = copy.errors.phone\n else if (!CONTACT_PHONE_CHARACTERS.test(phone) || !isValidAustralianPhoneNumber(phone)) {\n errors[fields.phone] = copy.errors.phoneFormat\n }\n const email = value(fields.email).toLowerCase()\n if (!email) errors[fields.email] = copy.errors.email\n else if (!EMAIL_PATTERN.test(email)) errors[fields.email] = copy.errors.emailFormat\n if (!value(fields.message)) errors[fields.message] = copy.errors.message\n if (photos.required && photos.count === 0 && copy.errors.photos) errors[PHOTOS] = copy.errors.photos\n return errors\n}\n\n/**\n * The site's message for a field the server refused: the runtime's own wording never shows. An empty field gets its\n * \"enter\" message; a filled phone or email its format message.\n */\nfunction serverFieldMessage(form: HTMLFormElement | null, key: string, fields: QuoteFields, copy: QuoteFormCopy) {\n const element = form?.elements.namedItem(key)\n const filled = Boolean(element && 'value' in element && String(element.value).trim())\n if (key === fields.phone) return filled ? copy.errors.phoneFormat : copy.errors.phone\n if (key === fields.email) return filled ? copy.errors.emailFormat : copy.errors.email\n if (key === fields.name) return copy.errors.name\n if (key === fields.location) return copy.errors.suburb\n return copy.errors.message\n}\n\nfunction ConsentLine({ consent, hooks }: { consent: QuoteFormCopy['consent']; hooks: ReturnType<typeof slot> }) {\n const at = consent.sentence.indexOf(consent.linkText)\n const link = <TextLink href={consent.href}>{at < 0 ? consent.sentence : consent.linkText}</TextLink>\n return (\n <p {...hooks}>\n {at < 0 ? link : (\n <>\n {consent.sentence.slice(0, at)}\n {link}\n {consent.sentence.slice(at + consent.linkText.length)}\n </>\n )}\n </p>\n )\n}\n\nexport function QuoteForm({\n formId,\n contract,\n analytics,\n attachmentPolicy,\n redirectTo,\n copy,\n pageLabel,\n honeypotField = CONTACT_FORM_FIELDS.honeypot,\n contactEndpoint,\n navigate,\n fetcher,\n attachmentOptions,\n variant,\n layout,\n classes,\n}: QuoteFormProps) {\n const fields = useMemo(() => quoteFields(contract), [contract])\n const mode = contract.attachments.mode\n const photosEnabled = mode !== 'none'\n const photosRequired = mode === 'images-required'\n assertCopy(copy, photosRequired ? 'required' : photosEnabled ? 'optional' : 'none')\n const pagePath = usePathname() || '/'\n const [clientErrors, setClientErrors] = useState<Record<string, string> | null>(null)\n const [attempt, setAttempt] = useState(0)\n const [withPhotos, setWithPhotos] = useState(false)\n const photoCount = useRef(0)\n\n const form = useBrandlabContactForm({\n contract,\n ...(analytics ? { analytics } : {}),\n pagePath,\n ...(pageLabel ? { pageLabel } : {}),\n formId,\n redirectTo,\n redirectDelayMs: 0,\n ...(navigate ? { navigate } : {}),\n ...(contactEndpoint ? { contactEndpoint } : {}),\n ...(fetcher ? { fetcher } : {}),\n attachments: { ...attachmentOptions, ...(attachmentPolicy ? { policy: attachmentPolicy } : {}) },\n onSubmitStart: ({ form: element }) => {\n const errors = validate(element, fields, copy, { required: photosRequired, count: photoCount.current })\n setAttempt((count) => count + 1)\n if (Object.keys(errors).length > 0) {\n setClientErrors(errors)\n return false\n }\n setClientErrors(null)\n setWithPhotos(photoCount.current > 0)\n return undefined\n },\n })\n photoCount.current = form.attachments.images.length\n\n const fieldId = (key: string) => `${formId}-${key}`\n const order = [fields.name, fields.location, fields.phone, fields.email, fields.message, photosEnabled ? PHOTOS : undefined]\n .filter((key): key is string => Boolean(key))\n const errors: Record<string, string> = clientErrors ?? Object.fromEntries(\n order.flatMap((key) =>\n key !== PHOTOS && form.fieldError(key) ? [[key, serverFieldMessage(form.formProps.ref.current, key, fields, copy)]] : []),\n )\n const summary = order.flatMap((key) => (errors[key] ? [{ fieldId: fieldId(key), message: errors[key] }] : []))\n\n const leaving = form.succeeded\n const busyLabel = form.attachments.isProcessing\n ? copy.preparingPhotos\n : form.pending || leaving\n ? withPhotos ? copy.sendingPhotos : copy.sending\n : undefined\n const result = form.result\n const failure = !busyLabel && clientErrors === null && result && !result.ok && summary.length === 0\n ? result.code === 'attachment_rejected' ? copy.failed.attachment : copy.failed.general\n : undefined\n\n const fieldClasses = { field: classes?.field, label: classes?.label, error: classes?.error }\n const max = (key: string) => fields.maxLength[key]\n const textField = (key: string, label: string, props: { type: 'text' | 'tel' | 'email'; autoComplete: string }) => (\n <Field id={fieldId(key)} label={label} error={errors[key]} required classes={fieldClasses}>\n {(control) => (\n <input\n {...contactFieldProps(form, key)}\n {...control}\n {...slot(classes, 'input')}\n type={props.type}\n autoComplete={props.autoComplete}\n {...(props.type === 'tel' ? { inputMode: 'tel' as const } : { maxLength: max(key) })}\n {...(props.type === 'email' ? { autoCapitalize: 'none', spellCheck: false } : {})}\n />\n )}\n </Field>\n )\n\n return (\n <form\n {...form.formProps}\n noValidate\n data-bl=\"quote-form\"\n data-variant={variant ?? QUOTE_FORM_PLACEMENT_VARIANTS[formId]}\n data-density={layout?.density ?? 'comfortable'}\n className={classes?.root}\n >\n <HeadlessErrorSummary\n {...slot(classes, 'errorSummary')}\n id={`${formId}-errors`}\n headingId={`${formId}-errors-heading`}\n heading={copy.errorSummary}\n errors={summary}\n />\n <HeadlessErrorFocus key={attempt} active={summary.length > 0} formId={formId} summaryId={`${formId}-errors`} />\n <div data-bl-honeypot=\"\" data-bl-visually-hidden=\"\" aria-hidden=\"true\" inert>\n <input type=\"text\" name={honeypotField} tabIndex={-1} autoComplete=\"off\" />\n </div>\n\n <div {...slot(classes, 'row')}>\n {textField(fields.name, copy.labels.name, { type: 'text', autoComplete: 'name' })}\n {fields.location ? (\n <Field id={fieldId(fields.location)} label={copy.labels.suburb} error={errors[fields.location]} required classes={fieldClasses}>\n {(control) => (\n <input\n {...contactFieldProps(form, fields.location!)}\n {...control}\n {...slot(classes, 'input')}\n type=\"text\"\n autoComplete=\"address-level2\"\n maxLength={max(fields.location!)}\n />\n )}\n </Field>\n ) : null}\n </div>\n <div {...slot(classes, 'row')}>\n {textField(fields.phone, copy.labels.phone, { type: 'tel', autoComplete: 'tel' })}\n {textField(fields.email, copy.labels.email, { type: 'email', autoComplete: 'email' })}\n </div>\n <Field id={fieldId(fields.message)} label={copy.labels.message} error={errors[fields.message]} required classes={fieldClasses}>\n {(control) => (\n <textarea\n {...contactFieldProps(form, fields.message)}\n {...control}\n {...slot(classes, 'textarea')}\n rows={5}\n placeholder={copy.messagePlaceholder}\n maxLength={max(fields.message)}\n />\n )}\n </Field>\n {photosEnabled ? (\n <PhotoUpload\n id={fieldId(PHOTOS)}\n label={copy.labels.photos}\n attachments={form.attachments}\n counter={copy.photoCount}\n removeLabel={copy.removePhoto}\n errorMessages={copy.photoErrors}\n accept={mode === 'images-and-pdfs-optional' ? 'image/*,application/pdf' : 'image/*'}\n error={errors[PHOTOS]}\n required={photosRequired}\n disabled={form.pending || leaving}\n classes={classes}\n />\n ) : null}\n\n <button\n {...form.submitProps}\n {...slot(classes, 'submit')}\n disabled={form.submitDisabled || leaving}\n data-state={busyLabel ? 'busy' : 'idle'}\n >\n {busyLabel ?? copy.submit}\n </button>\n <ConsentLine consent={copy.consent} hooks={slot(classes, 'consent')} />\n <div\n {...slot(classes, 'status')}\n ref={form.statusRef as RefObject<HTMLDivElement>}\n role=\"status\"\n aria-live=\"polite\"\n tabIndex={-1}\n data-state={failure ? 'error' : busyLabel ? 'busy' : 'idle'}\n >\n {failure ?? (busyLabel ? <span data-bl-visually-hidden=\"\">{busyLabel}</span> : null)}\n </div>\n </form>\n )\n}\n\nexport interface CreateQuoteFormOptions {\n readonly contract: BrandlabContactContract\n readonly analytics?: BrandlabAnalytics | undefined\n readonly attachmentPolicy?: ContactAttachmentPolicy | undefined\n /** The thank-you page, for example `/thank-you`. */\n readonly redirectTo: string\n readonly copy: QuoteFormCopy\n /** The site's quote form skin; leave `variant` unset so each placement takes its own. */\n readonly skin?: QuoteFormSkin | undefined\n /** The quote dialog's skin. */\n readonly dialogSkin?: QuoteDialogSkin | undefined\n readonly honeypotField?: string | undefined\n readonly contactEndpoint?: string | undefined\n readonly navigate?: ((href: string) => void) | undefined\n readonly fetcher?: typeof fetch | undefined\n readonly attachmentOptions?: Omit<UseBrandlabContactAttachmentsOptions, 'policy'> | undefined\n}\n\n/** What a page passes to the bound form: plain data, so a server component can render it. */\nexport interface BoundQuoteFormProps {\n readonly formId: QuoteFormPlacement\n readonly pageLabel?: string\n /** This placement's own placeholder, for example on a cost guide. */\n readonly messagePlaceholder?: string\n readonly layout?: QuoteFormLayout\n}\n\nexport interface BoundQuoteDialogProps {\n /** The dialog's H2, for example \"Get a free quote\". */\n readonly title: string\n /** The close button's accessible name, for example \"Close\". */\n readonly closeLabel: string\n readonly pageLabel?: string\n readonly messagePlaceholder?: string\n}\n\nexport interface BoundQuoteForm {\n readonly QuoteForm: (props: BoundQuoteFormProps) => JSX.Element\n readonly QuoteDialog: (props: BoundQuoteDialogProps) => JSX.Element\n}\n\n/**\n * Binds the form to the site's contract, analytics, photo policy, thank-you page, copy and skin. Call it once in the\n * site's own `'use client'` file (`src/site/quote-form.tsx`) and export the two components:\n *\n * ```tsx\n * 'use client'\n * const quote = createQuoteForm({ contract: contactContract, analytics, redirectTo: '/thank-you', copy, skin: skin.quoteForm })\n * export const QuoteForm = quote.QuoteForm\n * export const QuoteDialog = quote.QuoteDialog\n * ```\n *\n * It checks the contract and copy when the module loads, so a form that couldn't send fails the build instead.\n */\nexport function createQuoteForm(options: CreateQuoteFormOptions): BoundQuoteForm {\n if (!options || typeof options !== 'object') throw new TypeError('createQuoteForm needs the contract, copy and thank-you page.')\n if (typeof options.redirectTo !== 'string' || !/^\\/(?!\\/)[^\\s]*$/.test(options.redirectTo)) {\n throw new TypeError('redirectTo must be a root-relative path such as /thank-you.')\n }\n quoteFields(options.contract)\n const mode = options.contract.attachments.mode\n assertCopy(options.copy, mode === 'images-required' ? 'required' : mode === 'none' ? 'none' : 'optional')\n const { skin, dialogSkin, ...shared } = options\n\n function BoundQuoteForm({ formId, pageLabel, messagePlaceholder, layout }: BoundQuoteFormProps) {\n const merged = skin?.layout || layout ? { ...skin?.layout, ...layout } : undefined\n return (\n <QuoteForm\n {...shared}\n formId={formId}\n pageLabel={pageLabel}\n copy={messagePlaceholder ? { ...shared.copy, messagePlaceholder } : shared.copy}\n variant={skin?.variant}\n layout={merged}\n classes={skin?.classes}\n />\n )\n }\n\n function BoundQuoteDialog({ title, closeLabel, pageLabel, messagePlaceholder }: BoundQuoteDialogProps) {\n return (\n <QuoteDialog title={title} closeLabel={closeLabel} classes={dialogSkin?.classes}>\n <BoundQuoteForm\n formId=\"quote-dialog\"\n {...(pageLabel ? { pageLabel } : {})}\n {...(messagePlaceholder ? { messagePlaceholder } : {})}\n />\n </QuoteDialog>\n )\n }\n\n return Object.freeze({ QuoteForm: BoundQuoteForm, QuoteDialog: BoundQuoteDialog })\n}\n"]}
@@ -1,9 +1,12 @@
1
+ import type { RepeatedSlotOf } from '../repeated-slots.js';
1
2
  import { type SkinEntry } from '../skin.js';
2
3
  import type { UiPhone } from '../types.js';
3
4
  /** The reply time when the owner hasn't confirmed one (Abloom's live wording). */
4
5
  export declare const THANK_YOU_DEFAULT_REPLY_TIME = "within one business day";
5
6
  export type ThankYouSlot = 'root' | 'heading' | 'reply' | 'steps' | 'step' | 'call' | 'phone';
6
- export type ThankYouSkin = SkinEntry<ThankYouSlot>;
7
+ /** Rendered once per next step: styled from the skin stylesheet, never by class (3.14.0). */
8
+ export type ThankYouRepeatedSlot = RepeatedSlotOf<'thankYou'>;
9
+ export type ThankYouSkin = SkinEntry<ThankYouSlot, never, Record<never, never>, ThankYouRepeatedSlot>;
7
10
  export interface ThankYouProps extends ThankYouSkin {
8
11
  /** The H1, for example "Thanks. We've got your request." */
9
12
  readonly heading: string;
@@ -1 +1 @@
1
- {"version":3,"file":"thank-you.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/form/thank-you.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAG1C,kFAAkF;AAClF,eAAO,MAAM,4BAA4B,4BAA4B,CAAA;AAErE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAC7F,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,CAAA;AAElD,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,6FAA6F;IAC7F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,aAAa,2CA+B9G;AAED;;;GAGG;AACH,wBAAgB,gBAAgB;;;;;;;;;EAQ/B"}
1
+ {"version":3,"file":"thank-you.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/form/thank-you.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAG1C,kFAAkF;AAClF,eAAO,MAAM,4BAA4B,4BAA4B,CAAA;AAErE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAC7F,6FAA6F;AAC7F,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,UAAU,CAAC,CAAA;AAC7D,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,oBAAoB,CAAC,CAAA;AAErG,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,6FAA6F;IAC7F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,aAAa,2CA+B9G;AAED;;;GAGG;AACH,wBAAgB,gBAAgB;;;;;;;;;EAQ/B"}
@@ -7,7 +7,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
7
  * page is `noindex, follow`: export `thankYouMetadata()` from it.
8
8
  */
9
9
  import { PhoneLink } from '../primitives/links.js';
10
- import { slot } from '../skin.js';
10
+ import { repeatedSlot, slot } from '../skin.js';
11
11
  import { fillCopy } from './copy.js';
12
12
  /** The reply time when the owner hasn't confirmed one (Abloom's live wording). */
13
13
  export const THANK_YOU_DEFAULT_REPLY_TIME = 'within one business day';
@@ -18,7 +18,7 @@ export function ThankYou({ heading, reply, replyTime, steps, urgent, phone, call
18
18
  if (steps.length < 2 || steps.length > 3) {
19
19
  throw new Error('ThankYou takes two or three next steps.');
20
20
  }
21
- return (_jsxs("div", { "data-bl": "thank-you", className: classes?.root, children: [_jsx("h1", { ...slot(classes, 'heading'), children: heading }), _jsx("p", { ...slot(classes, 'reply'), children: fillCopy(reply, { replyTime: replyTime?.trim() || THANK_YOU_DEFAULT_REPLY_TIME }) }), _jsx("ol", { ...slot(classes, 'steps'), children: steps.map((step) => (_createElement("li", { ...slot(classes, 'step'), key: step }, step))) }), _jsxs("p", { ...slot(classes, 'call'), children: [_jsx("span", { children: urgent }), ' ', _jsx(PhoneLink, { phone: phone, placement: "contact", variant: "button", showIcon: true, ...(callLabel ? { label: callLabel } : {}), ...(classes?.phone ? { classes: { root: classes.phone } } : {}) })] })] }));
21
+ return (_jsxs("div", { "data-bl": "thank-you", className: classes?.root, children: [_jsx("h1", { ...slot(classes, 'heading'), children: heading }), _jsx("p", { ...slot(classes, 'reply'), children: fillCopy(reply, { replyTime: replyTime?.trim() || THANK_YOU_DEFAULT_REPLY_TIME }) }), _jsx("ol", { ...slot(classes, 'steps'), children: steps.map((step) => (_createElement("li", { ...repeatedSlot('step'), key: step }, step))) }), _jsxs("p", { ...slot(classes, 'call'), children: [_jsx("span", { children: urgent }), ' ', _jsx(PhoneLink, { phone: phone, placement: "contact", variant: "button", showIcon: true, ...(callLabel ? { label: callLabel } : {}), ...(classes?.phone ? { classes: { root: classes.phone } } : {}) })] })] }));
22
22
  }
23
23
  /**
24
24
  * The thank-you page's robots: `noindex, follow` (Google and every other crawler). Spread it into the page's metadata:
@@ -1 +1 @@
1
- {"version":3,"file":"thank-you.js","sourceRoot":"","sources":["../../../src/ui-kit/form/thank-you.tsx"],"names":[],"mappings":";;AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAA;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,kFAAkF;AAClF,MAAM,CAAC,MAAM,4BAA4B,GAAG,yBAAyB,CAAA;AAqBrE,MAAM,UAAU,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAiB;IAC7G,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAA;IAC7F,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,CACL,0BAAa,WAAW,EAAC,SAAS,EAAE,OAAO,EAAE,IAAI,aAC/C,gBAAQ,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,YAAG,OAAO,GAAM,EAChD,eAAO,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,YAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,4BAA4B,EAAE,CAAC,GAAK,EACtH,gBAAQ,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,YAC3B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,0BAAQ,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,IACrC,IAAI,CACF,CACN,CAAC,GACC,EACL,gBAAO,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,aAC1B,yBAAO,MAAM,GAAQ,EAAC,GAAG,EACzB,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,SAAS,EAAC,SAAS,EACnB,OAAO,EAAC,QAAQ,EAChB,QAAQ,WACJ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACvC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAChE,IACA,IACA,CACP,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,MAAM,EAAE;YACN,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;SAC1C;KACO,CAAA;AACZ,CAAC","sourcesContent":["/**\n * `ThankYou`: the block on the thank-you page an accepted enquiry opens. Server component, all text in the server\n * HTML (nothing waits for a script): the H1, the reply time (\"within one business day\" unless the owner confirmed\n * another), two or three plain next steps and a large call button for anything urgent (placement `contact`). The\n * page is `noindex, follow`: export `thankYouMetadata()` from it.\n */\nimport { PhoneLink } from '../primitives/links.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport type { UiPhone } from '../types.js'\nimport { fillCopy } from './copy.js'\n\n/** The reply time when the owner hasn't confirmed one (Abloom's live wording). */\nexport const THANK_YOU_DEFAULT_REPLY_TIME = 'within one business day'\n\nexport type ThankYouSlot = 'root' | 'heading' | 'reply' | 'steps' | 'step' | 'call' | 'phone'\nexport type ThankYouSkin = SkinEntry<ThankYouSlot>\n\nexport interface ThankYouProps extends ThankYouSkin {\n /** The H1, for example \"Thanks. We've got your request.\" */\n readonly heading: string\n /** The reply sentence with `{replyTime}`, for example \"We'll get back to you {replyTime}.\" */\n readonly reply: string\n /** The owner-confirmed reply time, for example \"within two hours\"; the default otherwise. */\n readonly replyTime?: string | undefined\n /** Two or three plain next steps. */\n readonly steps: readonly string[]\n /** The words before the call button, for example \"Anything urgent? Call us now.\" */\n readonly urgent: string\n readonly phone: UiPhone\n /** Optional words in the button before the number, for example \"Call\". */\n readonly callLabel?: string | undefined\n}\n\nexport function ThankYou({ heading, reply, replyTime, steps, urgent, phone, callLabel, classes }: ThankYouProps) {\n if (!reply.includes('{replyTime}')) {\n throw new Error('ThankYou reply must include {replyTime}, so the reply time always shows.')\n }\n if (steps.length < 2 || steps.length > 3) {\n throw new Error('ThankYou takes two or three next steps.')\n }\n return (\n <div data-bl=\"thank-you\" className={classes?.root}>\n <h1 {...slot(classes, 'heading')}>{heading}</h1>\n <p {...slot(classes, 'reply')}>{fillCopy(reply, { replyTime: replyTime?.trim() || THANK_YOU_DEFAULT_REPLY_TIME })}</p>\n <ol {...slot(classes, 'steps')}>\n {steps.map((step) => (\n <li {...slot(classes, 'step')} key={step}>\n {step}\n </li>\n ))}\n </ol>\n <p {...slot(classes, 'call')}>\n <span>{urgent}</span>{' '}\n <PhoneLink\n phone={phone}\n placement=\"contact\"\n variant=\"button\"\n showIcon\n {...(callLabel ? { label: callLabel } : {})}\n {...(classes?.phone ? { classes: { root: classes.phone } } : {})}\n />\n </p>\n </div>\n )\n}\n\n/**\n * The thank-you page's robots: `noindex, follow` (Google and every other crawler). Spread it into the page's metadata:\n * `export const metadata = { ...pageMetadata('thank-you'), ...thankYouMetadata() }`.\n */\nexport function thankYouMetadata() {\n return {\n robots: {\n index: false,\n follow: true,\n googleBot: { index: false, follow: true },\n },\n } as const\n}\n"]}
1
+ {"version":3,"file":"thank-you.js","sourceRoot":"","sources":["../../../src/ui-kit/form/thank-you.tsx"],"names":[],"mappings":";;AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAElD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAA;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,kFAAkF;AAClF,MAAM,CAAC,MAAM,4BAA4B,GAAG,yBAAyB,CAAA;AAuBrE,MAAM,UAAU,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAiB;IAC7G,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAA;IAC7F,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,CACL,0BAAa,WAAW,EAAC,SAAS,EAAE,OAAO,EAAE,IAAI,aAC/C,gBAAQ,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,YAAG,OAAO,GAAM,EAChD,eAAO,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,YAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,4BAA4B,EAAE,CAAC,GAAK,EACtH,gBAAQ,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,YAC3B,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,0BAAQ,YAAY,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,IACpC,IAAI,CACF,CACN,CAAC,GACC,EACL,gBAAO,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,aAC1B,yBAAO,MAAM,GAAQ,EAAC,GAAG,EACzB,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,SAAS,EAAC,SAAS,EACnB,OAAO,EAAC,QAAQ,EAChB,QAAQ,WACJ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACvC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAChE,IACA,IACA,CACP,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,MAAM,EAAE;YACN,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;SAC1C;KACO,CAAA;AACZ,CAAC","sourcesContent":["/**\n * `ThankYou`: the block on the thank-you page an accepted enquiry opens. Server component, all text in the server\n * HTML (nothing waits for a script): the H1, the reply time (\"within one business day\" unless the owner confirmed\n * another), two or three plain next steps and a large call button for anything urgent (placement `contact`). The\n * page is `noindex, follow`: export `thankYouMetadata()` from it.\n */\nimport { PhoneLink } from '../primitives/links.js'\nimport type { RepeatedSlotOf } from '../repeated-slots.js'\nimport { repeatedSlot, slot, type SkinEntry } from '../skin.js'\nimport type { UiPhone } from '../types.js'\nimport { fillCopy } from './copy.js'\n\n/** The reply time when the owner hasn't confirmed one (Abloom's live wording). */\nexport const THANK_YOU_DEFAULT_REPLY_TIME = 'within one business day'\n\nexport type ThankYouSlot = 'root' | 'heading' | 'reply' | 'steps' | 'step' | 'call' | 'phone'\n/** Rendered once per next step: styled from the skin stylesheet, never by class (3.14.0). */\nexport type ThankYouRepeatedSlot = RepeatedSlotOf<'thankYou'>\nexport type ThankYouSkin = SkinEntry<ThankYouSlot, never, Record<never, never>, ThankYouRepeatedSlot>\n\nexport interface ThankYouProps extends ThankYouSkin {\n /** The H1, for example \"Thanks. We've got your request.\" */\n readonly heading: string\n /** The reply sentence with `{replyTime}`, for example \"We'll get back to you {replyTime}.\" */\n readonly reply: string\n /** The owner-confirmed reply time, for example \"within two hours\"; the default otherwise. */\n readonly replyTime?: string | undefined\n /** Two or three plain next steps. */\n readonly steps: readonly string[]\n /** The words before the call button, for example \"Anything urgent? Call us now.\" */\n readonly urgent: string\n readonly phone: UiPhone\n /** Optional words in the button before the number, for example \"Call\". */\n readonly callLabel?: string | undefined\n}\n\nexport function ThankYou({ heading, reply, replyTime, steps, urgent, phone, callLabel, classes }: ThankYouProps) {\n if (!reply.includes('{replyTime}')) {\n throw new Error('ThankYou reply must include {replyTime}, so the reply time always shows.')\n }\n if (steps.length < 2 || steps.length > 3) {\n throw new Error('ThankYou takes two or three next steps.')\n }\n return (\n <div data-bl=\"thank-you\" className={classes?.root}>\n <h1 {...slot(classes, 'heading')}>{heading}</h1>\n <p {...slot(classes, 'reply')}>{fillCopy(reply, { replyTime: replyTime?.trim() || THANK_YOU_DEFAULT_REPLY_TIME })}</p>\n <ol {...slot(classes, 'steps')}>\n {steps.map((step) => (\n <li {...repeatedSlot('step')} key={step}>\n {step}\n </li>\n ))}\n </ol>\n <p {...slot(classes, 'call')}>\n <span>{urgent}</span>{' '}\n <PhoneLink\n phone={phone}\n placement=\"contact\"\n variant=\"button\"\n showIcon\n {...(callLabel ? { label: callLabel } : {})}\n {...(classes?.phone ? { classes: { root: classes.phone } } : {})}\n />\n </p>\n </div>\n )\n}\n\n/**\n * The thank-you page's robots: `noindex, follow` (Google and every other crawler). Spread it into the page's metadata:\n * `export const metadata = { ...pageMetadata('thank-you'), ...thankYouMetadata() }`.\n */\nexport function thankYouMetadata() {\n return {\n robots: {\n index: false,\n follow: true,\n googleBot: { index: false, follow: true },\n },\n } as const\n}\n"]}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The ui-kit's icon glyphs as SVG markup, and the typed API a site registers its own icons through. Pure data with no
3
+ * React and no Node APIs, so `next.config.ts` (which builds the sprite) and the browser bundle (which renders the
4
+ * fallback) can both import it.
5
+ *
6
+ * From 3.14.0 every icon renders as `<svg aria-hidden="true" viewBox><use href="/_bl/icons.<hash>.svg#name"/></svg>`
7
+ * once `defineBrandlabNextConfig({ icons })` has built the sprite; without it (tests, a site that has not opted in) the
8
+ * same `<svg>` carries the glyph inline.
9
+ */
10
+ /** One glyph: the symbol's `viewBox` (default `0 0 24 24`) and its SVG child markup (paths, circles, groups). */
11
+ export interface IconGlyph {
12
+ readonly viewBox?: string;
13
+ readonly body: string;
14
+ }
15
+ export declare const UI_ICON_NAMES: readonly ["phone", "chevron", "arrow", "arrow-up", "menu", "close", "star", "check", "camera", "mail", "facebook", "instagram", "google", "linkedin", "youtube", "tiktok"];
16
+ export type UiIconName = (typeof UI_ICON_NAMES)[number];
17
+ export declare const DEFAULT_ICON_VIEW_BOX = "0 0 24 24";
18
+ /** The environment variable `defineBrandlabNextConfig({ icons })` sets to the sprite's path. */
19
+ export declare const ICON_SPRITE_ENV = "NEXT_PUBLIC_BL_ICON_SPRITE";
20
+ export declare const UI_ICON_GLYPHS: Readonly<Record<UiIconName, IconGlyph>>;
21
+ /** A site's own icons, from `defineSiteIcons`. They join the library icons in the one sprite. */
22
+ export interface SiteIconSet<Name extends string = string> {
23
+ readonly names: readonly Name[];
24
+ readonly glyphs: Readonly<Record<Name, IconGlyph>>;
25
+ }
26
+ /**
27
+ * Register a site's own icons (signature art, trade marks the site draws itself) for the sprite. Names are lower-case
28
+ * words joined by hyphens and may not reuse a library icon's name; each glyph is plain SVG shapes using
29
+ * `currentColor` (no ids, links, styles or scripts), checked when the module loads.
30
+ *
31
+ * ```ts
32
+ * // src/site/icons.ts
33
+ * export const siteIcons = defineSiteIcons({ leaf: { body: '<path fill="currentColor" d="…"/>' } })
34
+ * // next.config.ts: defineBrandlabNextConfig({ …, icons: { site: siteIcons } })
35
+ * // src/site/ui.tsx: export const SiteIcon = createSiteIcon(siteIcons)
36
+ * ```
37
+ */
38
+ export declare function defineSiteIcons<const Name extends string>(icons: Readonly<Record<Name, IconGlyph>>): SiteIconSet<Name>;
39
+ /** The sprite's markup: one `<symbol id="name" viewBox>` per library icon, then the site's icons. */
40
+ export declare function iconSpriteMarkup(site?: SiteIconSet): string;
41
+ //# sourceMappingURL=icon-glyphs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-glyphs.d.ts","sourceRoot":"","sources":["../../src/ui-kit/icon-glyphs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iHAAiH;AACjH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,eAAO,MAAM,aAAa,4KAiBhB,CAAA;AACV,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvD,eAAO,MAAM,qBAAqB,cAAc,CAAA;AAEhD,gGAAgG;AAChG,eAAO,MAAM,eAAe,+BAA+B,CAAA;AAM3D,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,CAqDjE,CAAA;AAEF,iGAAiG;AACjG,MAAM,WAAW,WAAW,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACvD,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;CACnD;AAuBD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAetH;AAED,qGAAqG;AACrG,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAM3D"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * The ui-kit's icon glyphs as SVG markup, and the typed API a site registers its own icons through. Pure data with no
3
+ * React and no Node APIs, so `next.config.ts` (which builds the sprite) and the browser bundle (which renders the
4
+ * fallback) can both import it.
5
+ *
6
+ * From 3.14.0 every icon renders as `<svg aria-hidden="true" viewBox><use href="/_bl/icons.<hash>.svg#name"/></svg>`
7
+ * once `defineBrandlabNextConfig({ icons })` has built the sprite; without it (tests, a site that has not opted in) the
8
+ * same `<svg>` carries the glyph inline.
9
+ */
10
+ export const UI_ICON_NAMES = [
11
+ 'phone',
12
+ 'chevron',
13
+ 'arrow',
14
+ 'arrow-up',
15
+ 'menu',
16
+ 'close',
17
+ 'star',
18
+ 'check',
19
+ 'camera',
20
+ 'mail',
21
+ 'facebook',
22
+ 'instagram',
23
+ 'google',
24
+ 'linkedin',
25
+ 'youtube',
26
+ 'tiktok',
27
+ ];
28
+ export const DEFAULT_ICON_VIEW_BOX = '0 0 24 24';
29
+ /** The environment variable `defineBrandlabNextConfig({ icons })` sets to the sprite's path. */
30
+ export const ICON_SPRITE_ENV = 'NEXT_PUBLIC_BL_ICON_SPRITE';
31
+ const stroke = (width, d) => `<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="${width}" d="${d}"/>`;
32
+ const fill = (d) => `<path fill="currentColor" d="${d}"/>`;
33
+ export const UI_ICON_GLYPHS = Object.freeze({
34
+ phone: {
35
+ body: stroke('1.6', 'M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106a1.125 1.125 0 0 0-1.173.417l-.97 1.293a1.125 1.125 0 0 1-1.21.38 12.035 12.035 0 0 1-7.143-7.143 1.125 1.125 0 0 1 .38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z'),
36
+ },
37
+ chevron: { body: stroke('1.8', 'm6 9 6 6 6-6') },
38
+ arrow: { body: stroke('1.6', 'M13.5 4.5 21 12l-7.5 7.5M3 12h17.25') },
39
+ 'arrow-up': { body: stroke('1.8', 'M12 20V4m0 0-7 7m7-7 7 7') },
40
+ menu: { body: stroke('1.7', 'M4 7h16M4 12h16M4 17h16') },
41
+ close: { body: stroke('1.7', 'M6 18 18 6M6 6l12 12') },
42
+ star: { viewBox: '0 0 20 20', body: fill('M10 1.6 12.6 7l5.9.7-4.4 4 1.2 5.8L10 14.6l-5.3 2.9L5.9 11.7l-4.4-4L7.4 7 10 1.6Z') },
43
+ check: { body: stroke('2', 'm4.5 12.75 6 6 9-13.5') },
44
+ camera: {
45
+ body: stroke('1.6', 'M3 8.25A2.25 2.25 0 0 1 5.25 6h1.372c.516 0 .966-.351 1.091-.852l.38-1.52A1.125 1.125 0 0 1 9.184 2.7h5.632c.516 0 .966.351 1.091.852l.38 1.52c.125.5.575.852 1.091.852h1.372A2.25 2.25 0 0 1 21 8.25v9.75a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 18V8.25Z') +
46
+ '<circle fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.6" cx="12" cy="12.75" r="3.75"/>',
47
+ },
48
+ mail: {
49
+ body: stroke('1.6', 'M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0-8.69 5.6a2.25 2.25 0 0 1-2.12 0l-8.69-5.6'),
50
+ },
51
+ facebook: { body: fill('M9 8H6v4h3v12h5V12h3.642L18 8h-4V6.333C14 5.378 14.192 5 15.115 5H18V0h-3.808C10.596 0 9 1.583 9 4.615V8Z') },
52
+ instagram: {
53
+ body: '<rect x="3" y="3" width="18" height="18" rx="5" fill="none" stroke="currentColor" stroke-width="2"/>' +
54
+ '<circle cx="12" cy="12" r="4.2" fill="none" stroke="currentColor" stroke-width="2"/>' +
55
+ '<circle cx="17.4" cy="6.6" r="1.3" fill="currentColor"/>',
56
+ },
57
+ google: {
58
+ body: fill('M21.6 12.23c0-.68-.06-1.33-.17-1.96H12v3.7h5.39a4.6 4.6 0 0 1-2 3.02v2.5h3.24c1.9-1.75 2.97-4.32 2.97-7.26ZM12 22c2.7 0 4.96-.9 6.62-2.43l-3.24-2.5c-.9.6-2.04.95-3.38.95-2.6 0-4.8-1.75-5.59-4.11H3.07v2.59A10 10 0 0 0 12 22Zm-5.59-8.09A6 6 0 0 1 6.1 12c0-.66.11-1.31.31-1.91V7.5H3.07A10 10 0 0 0 2 12c0 1.61.39 3.14 1.07 4.5l3.34-2.59ZM12 5.98c1.47 0 2.79.5 3.83 1.5l2.87-2.87A9.6 9.6 0 0 0 12 2a10 10 0 0 0-8.93 5.5l3.34 2.59C7.2 7.73 9.4 5.98 12 5.98Z'),
59
+ },
60
+ linkedin: {
61
+ body: fill('M4.98 3.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5ZM3 9.75h4v11.5H3V9.75Zm6.5 0h3.83v1.57h.06c.53-1 1.84-2.07 3.79-2.07 4.05 0 4.8 2.67 4.8 6.13v5.87h-4v-5.2c0-1.24-.02-2.84-1.73-2.84-1.73 0-2 1.35-2 2.75v5.29h-4V9.75Z'),
62
+ },
63
+ youtube: {
64
+ body: fill('M23 7.2a3 3 0 0 0-2.1-2.1C19 4.6 12 4.6 12 4.6s-7 0-8.9.5A3 3 0 0 0 1 7.2 31 31 0 0 0 .5 12a31 31 0 0 0 .5 4.8 3 3 0 0 0 2.1 2.1c1.9.5 8.9.5 8.9.5s7 0 8.9-.5a3 3 0 0 0 2.1-2.1 31 31 0 0 0 .5-4.8 31 31 0 0 0-.5-4.8ZM9.75 15.02V8.98L15.5 12l-5.75 3.02Z'),
65
+ },
66
+ tiktok: {
67
+ body: fill('M16.6 2h-3.4v13.4a2.9 2.9 0 1 1-2.9-2.9c.3 0 .6 0 .9.1V9.1a6.3 6.3 0 1 0 5.4 6.3V8.6a8.1 8.1 0 0 0 4.4 1.3V6.5a4.5 4.5 0 0 1-4.4-4.5Z'),
68
+ },
69
+ });
70
+ const ICON_NAME = /^[a-z][a-z0-9-]{0,39}$/;
71
+ const VIEW_BOX = /^-?\d+(?:\.\d+)?(?: -?\d+(?:\.\d+)?){3}$/;
72
+ const GLYPH_ELEMENTS = new Set([
73
+ 'path', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'rect', 'g', 'title', 'desc',
74
+ 'lineargradient', 'radialgradient', 'stop', 'defs', 'clippath', 'mask',
75
+ ]);
76
+ /** Why a glyph's markup is refused, or null when it is plain shapes. */
77
+ function glyphProblem(body) {
78
+ if (body.trim() === '')
79
+ return 'is empty';
80
+ for (const [, tag] of body.matchAll(/<\/?\s*([a-zA-Z][\w:-]*)/g)) {
81
+ if (!GLYPH_ELEMENTS.has(tag.toLowerCase()))
82
+ return `uses <${tag}>; a glyph holds shapes only (path, circle, rect, g and the like)`;
83
+ }
84
+ if (/<!|<\?/.test(body))
85
+ return 'holds a comment, CDATA or processing instruction';
86
+ if (/\son[a-z]+\s*=/i.test(body))
87
+ return 'carries an event handler attribute';
88
+ if (/(?:^|\s)(?:xlink:)?href\s*=/i.test(body))
89
+ return 'links to another resource';
90
+ if (/\sstyle\s*=|url\s*\(|javascript:/i.test(body))
91
+ return 'carries a style or url() value';
92
+ if (/\sid\s*=/i.test(body))
93
+ return 'sets an id, which would clash once the sprite holds every icon';
94
+ return null;
95
+ }
96
+ /**
97
+ * Register a site's own icons (signature art, trade marks the site draws itself) for the sprite. Names are lower-case
98
+ * words joined by hyphens and may not reuse a library icon's name; each glyph is plain SVG shapes using
99
+ * `currentColor` (no ids, links, styles or scripts), checked when the module loads.
100
+ *
101
+ * ```ts
102
+ * // src/site/icons.ts
103
+ * export const siteIcons = defineSiteIcons({ leaf: { body: '<path fill="currentColor" d="…"/>' } })
104
+ * // next.config.ts: defineBrandlabNextConfig({ …, icons: { site: siteIcons } })
105
+ * // src/site/ui.tsx: export const SiteIcon = createSiteIcon(siteIcons)
106
+ * ```
107
+ */
108
+ export function defineSiteIcons(icons) {
109
+ if (!icons || typeof icons !== 'object' || Array.isArray(icons))
110
+ throw new TypeError('defineSiteIcons takes an object of { name: { viewBox?, body } }.');
111
+ const names = Object.keys(icons);
112
+ const library = new Set(UI_ICON_NAMES);
113
+ for (const name of names) {
114
+ if (!ICON_NAME.test(name))
115
+ throw new Error(`Site icon "${name}": names are lower-case words joined by hyphens, at most 40 characters.`);
116
+ if (library.has(name))
117
+ throw new Error(`Site icon "${name}" reuses a library icon's name; choose another name.`);
118
+ const glyph = icons[name];
119
+ if (!glyph || typeof glyph.body !== 'string')
120
+ throw new Error(`Site icon "${name}" needs a body of SVG markup.`);
121
+ if (glyph.viewBox !== undefined && !VIEW_BOX.test(glyph.viewBox))
122
+ throw new Error(`Site icon "${name}": viewBox must be four numbers, for example "0 0 24 24".`);
123
+ const problem = glyphProblem(glyph.body);
124
+ if (problem)
125
+ throw new Error(`Site icon "${name}" ${problem}.`);
126
+ }
127
+ const glyphs = Object.freeze(Object.fromEntries(names.map((name) => [name, Object.freeze({ ...icons[name] })])));
128
+ return Object.freeze({ names: Object.freeze([...names]), glyphs });
129
+ }
130
+ /** The sprite's markup: one `<symbol id="name" viewBox>` per library icon, then the site's icons. */
131
+ export function iconSpriteMarkup(site) {
132
+ const symbols = [
133
+ ...UI_ICON_NAMES.map((name) => [name, UI_ICON_GLYPHS[name]]),
134
+ ...(site?.names ?? []).map((name) => [name, site.glyphs[name]]),
135
+ ].map(([name, glyph]) => `<symbol id="${name}" viewBox="${glyph.viewBox ?? DEFAULT_ICON_VIEW_BOX}">${glyph.body}</symbol>`);
136
+ return `<svg xmlns="http://www.w3.org/2000/svg">${symbols.join('')}</svg>\n`;
137
+ }
138
+ //# sourceMappingURL=icon-glyphs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-glyphs.js","sourceRoot":"","sources":["../../src/ui-kit/icon-glyphs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The ui-kit's icon glyphs as SVG markup, and the typed API a site registers its own icons through. Pure data with no\n * React and no Node APIs, so `next.config.ts` (which builds the sprite) and the browser bundle (which renders the\n * fallback) can both import it.\n *\n * From 3.14.0 every icon renders as `<svg aria-hidden=\"true\" viewBox><use href=\"/_bl/icons.<hash>.svg#name\"/></svg>`\n * once `defineBrandlabNextConfig({ icons })` has built the sprite; without it (tests, a site that has not opted in) the\n * same `<svg>` carries the glyph inline.\n */\n\n/** One glyph: the symbol's `viewBox` (default `0 0 24 24`) and its SVG child markup (paths, circles, groups). */\nexport interface IconGlyph {\n readonly viewBox?: string\n readonly body: string\n}\n\nexport const UI_ICON_NAMES = [\n 'phone',\n 'chevron',\n 'arrow',\n 'arrow-up',\n 'menu',\n 'close',\n 'star',\n 'check',\n 'camera',\n 'mail',\n 'facebook',\n 'instagram',\n 'google',\n 'linkedin',\n 'youtube',\n 'tiktok',\n] as const\nexport type UiIconName = (typeof UI_ICON_NAMES)[number]\n\nexport const DEFAULT_ICON_VIEW_BOX = '0 0 24 24'\n\n/** The environment variable `defineBrandlabNextConfig({ icons })` sets to the sprite's path. */\nexport const ICON_SPRITE_ENV = 'NEXT_PUBLIC_BL_ICON_SPRITE'\n\nconst stroke = (width: string, d: string) =>\n `<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"${width}\" d=\"${d}\"/>`\nconst fill = (d: string) => `<path fill=\"currentColor\" d=\"${d}\"/>`\n\nexport const UI_ICON_GLYPHS: Readonly<Record<UiIconName, IconGlyph>> = Object.freeze({\n phone: {\n body: stroke(\n '1.6',\n 'M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106a1.125 1.125 0 0 0-1.173.417l-.97 1.293a1.125 1.125 0 0 1-1.21.38 12.035 12.035 0 0 1-7.143-7.143 1.125 1.125 0 0 1 .38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z',\n ),\n },\n chevron: { body: stroke('1.8', 'm6 9 6 6 6-6') },\n arrow: { body: stroke('1.6', 'M13.5 4.5 21 12l-7.5 7.5M3 12h17.25') },\n 'arrow-up': { body: stroke('1.8', 'M12 20V4m0 0-7 7m7-7 7 7') },\n menu: { body: stroke('1.7', 'M4 7h16M4 12h16M4 17h16') },\n close: { body: stroke('1.7', 'M6 18 18 6M6 6l12 12') },\n star: { viewBox: '0 0 20 20', body: fill('M10 1.6 12.6 7l5.9.7-4.4 4 1.2 5.8L10 14.6l-5.3 2.9L5.9 11.7l-4.4-4L7.4 7 10 1.6Z') },\n check: { body: stroke('2', 'm4.5 12.75 6 6 9-13.5') },\n camera: {\n body:\n stroke(\n '1.6',\n 'M3 8.25A2.25 2.25 0 0 1 5.25 6h1.372c.516 0 .966-.351 1.091-.852l.38-1.52A1.125 1.125 0 0 1 9.184 2.7h5.632c.516 0 .966.351 1.091.852l.38 1.52c.125.5.575.852 1.091.852h1.372A2.25 2.25 0 0 1 21 8.25v9.75a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 18V8.25Z',\n ) +\n '<circle fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.6\" cx=\"12\" cy=\"12.75\" r=\"3.75\"/>',\n },\n mail: {\n body: stroke(\n '1.6',\n 'M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0-8.69 5.6a2.25 2.25 0 0 1-2.12 0l-8.69-5.6',\n ),\n },\n facebook: { body: fill('M9 8H6v4h3v12h5V12h3.642L18 8h-4V6.333C14 5.378 14.192 5 15.115 5H18V0h-3.808C10.596 0 9 1.583 9 4.615V8Z') },\n instagram: {\n body:\n '<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"/>' +\n '<circle cx=\"12\" cy=\"12\" r=\"4.2\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"/>' +\n '<circle cx=\"17.4\" cy=\"6.6\" r=\"1.3\" fill=\"currentColor\"/>',\n },\n google: {\n body: fill(\n 'M21.6 12.23c0-.68-.06-1.33-.17-1.96H12v3.7h5.39a4.6 4.6 0 0 1-2 3.02v2.5h3.24c1.9-1.75 2.97-4.32 2.97-7.26ZM12 22c2.7 0 4.96-.9 6.62-2.43l-3.24-2.5c-.9.6-2.04.95-3.38.95-2.6 0-4.8-1.75-5.59-4.11H3.07v2.59A10 10 0 0 0 12 22Zm-5.59-8.09A6 6 0 0 1 6.1 12c0-.66.11-1.31.31-1.91V7.5H3.07A10 10 0 0 0 2 12c0 1.61.39 3.14 1.07 4.5l3.34-2.59ZM12 5.98c1.47 0 2.79.5 3.83 1.5l2.87-2.87A9.6 9.6 0 0 0 12 2a10 10 0 0 0-8.93 5.5l3.34 2.59C7.2 7.73 9.4 5.98 12 5.98Z',\n ),\n },\n linkedin: {\n body: fill(\n 'M4.98 3.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5ZM3 9.75h4v11.5H3V9.75Zm6.5 0h3.83v1.57h.06c.53-1 1.84-2.07 3.79-2.07 4.05 0 4.8 2.67 4.8 6.13v5.87h-4v-5.2c0-1.24-.02-2.84-1.73-2.84-1.73 0-2 1.35-2 2.75v5.29h-4V9.75Z',\n ),\n },\n youtube: {\n body: fill(\n 'M23 7.2a3 3 0 0 0-2.1-2.1C19 4.6 12 4.6 12 4.6s-7 0-8.9.5A3 3 0 0 0 1 7.2 31 31 0 0 0 .5 12a31 31 0 0 0 .5 4.8 3 3 0 0 0 2.1 2.1c1.9.5 8.9.5 8.9.5s7 0 8.9-.5a3 3 0 0 0 2.1-2.1 31 31 0 0 0 .5-4.8 31 31 0 0 0-.5-4.8ZM9.75 15.02V8.98L15.5 12l-5.75 3.02Z',\n ),\n },\n tiktok: {\n body: fill('M16.6 2h-3.4v13.4a2.9 2.9 0 1 1-2.9-2.9c.3 0 .6 0 .9.1V9.1a6.3 6.3 0 1 0 5.4 6.3V8.6a8.1 8.1 0 0 0 4.4 1.3V6.5a4.5 4.5 0 0 1-4.4-4.5Z'),\n },\n})\n\n/** A site's own icons, from `defineSiteIcons`. They join the library icons in the one sprite. */\nexport interface SiteIconSet<Name extends string = string> {\n readonly names: readonly Name[]\n readonly glyphs: Readonly<Record<Name, IconGlyph>>\n}\n\nconst ICON_NAME = /^[a-z][a-z0-9-]{0,39}$/\nconst VIEW_BOX = /^-?\\d+(?:\\.\\d+)?(?: -?\\d+(?:\\.\\d+)?){3}$/\nconst GLYPH_ELEMENTS = new Set([\n 'path', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'rect', 'g', 'title', 'desc',\n 'lineargradient', 'radialgradient', 'stop', 'defs', 'clippath', 'mask',\n])\n\n/** Why a glyph's markup is refused, or null when it is plain shapes. */\nfunction glyphProblem(body: string): string | null {\n if (body.trim() === '') return 'is empty'\n for (const [, tag] of body.matchAll(/<\\/?\\s*([a-zA-Z][\\w:-]*)/g)) {\n if (!GLYPH_ELEMENTS.has(tag!.toLowerCase())) return `uses <${tag}>; a glyph holds shapes only (path, circle, rect, g and the like)`\n }\n if (/<!|<\\?/.test(body)) return 'holds a comment, CDATA or processing instruction'\n if (/\\son[a-z]+\\s*=/i.test(body)) return 'carries an event handler attribute'\n if (/(?:^|\\s)(?:xlink:)?href\\s*=/i.test(body)) return 'links to another resource'\n if (/\\sstyle\\s*=|url\\s*\\(|javascript:/i.test(body)) return 'carries a style or url() value'\n if (/\\sid\\s*=/i.test(body)) return 'sets an id, which would clash once the sprite holds every icon'\n return null\n}\n\n/**\n * Register a site's own icons (signature art, trade marks the site draws itself) for the sprite. Names are lower-case\n * words joined by hyphens and may not reuse a library icon's name; each glyph is plain SVG shapes using\n * `currentColor` (no ids, links, styles or scripts), checked when the module loads.\n *\n * ```ts\n * // src/site/icons.ts\n * export const siteIcons = defineSiteIcons({ leaf: { body: '<path fill=\"currentColor\" d=\"…\"/>' } })\n * // next.config.ts: defineBrandlabNextConfig({ …, icons: { site: siteIcons } })\n * // src/site/ui.tsx: export const SiteIcon = createSiteIcon(siteIcons)\n * ```\n */\nexport function defineSiteIcons<const Name extends string>(icons: Readonly<Record<Name, IconGlyph>>): SiteIconSet<Name> {\n if (!icons || typeof icons !== 'object' || Array.isArray(icons)) throw new TypeError('defineSiteIcons takes an object of { name: { viewBox?, body } }.')\n const names = Object.keys(icons) as Name[]\n const library = new Set<string>(UI_ICON_NAMES)\n for (const name of names) {\n if (!ICON_NAME.test(name)) throw new Error(`Site icon \"${name}\": names are lower-case words joined by hyphens, at most 40 characters.`)\n if (library.has(name)) throw new Error(`Site icon \"${name}\" reuses a library icon's name; choose another name.`)\n const glyph = icons[name] as IconGlyph | undefined\n if (!glyph || typeof glyph.body !== 'string') throw new Error(`Site icon \"${name}\" needs a body of SVG markup.`)\n if (glyph.viewBox !== undefined && !VIEW_BOX.test(glyph.viewBox)) throw new Error(`Site icon \"${name}\": viewBox must be four numbers, for example \"0 0 24 24\".`)\n const problem = glyphProblem(glyph.body)\n if (problem) throw new Error(`Site icon \"${name}\" ${problem}.`)\n }\n const glyphs = Object.freeze(Object.fromEntries(names.map((name) => [name, Object.freeze({ ...icons[name] })]))) as Record<Name, IconGlyph>\n return Object.freeze({ names: Object.freeze([...names]), glyphs })\n}\n\n/** The sprite's markup: one `<symbol id=\"name\" viewBox>` per library icon, then the site's icons. */\nexport function iconSpriteMarkup(site?: SiteIconSet): string {\n const symbols = [\n ...UI_ICON_NAMES.map((name) => [name, UI_ICON_GLYPHS[name]] as const),\n ...(site?.names ?? []).map((name) => [name, site!.glyphs[name]!] as const),\n ].map(([name, glyph]) => `<symbol id=\"${name}\" viewBox=\"${glyph.viewBox ?? DEFAULT_ICON_VIEW_BOX}\">${glyph.body}</symbol>`)\n return `<svg xmlns=\"http://www.w3.org/2000/svg\">${symbols.join('')}</svg>\\n`\n}\n"]}