@brandlab-digital/site-next 3.13.0 → 3.15.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.
- package/README.md +79 -0
- package/dist/analytics.d.ts +1 -1
- package/dist/analytics.d.ts.map +1 -1
- package/dist/analytics.js +2 -0
- package/dist/analytics.js.map +1 -1
- package/dist/contact/delivery.d.ts +81 -0
- package/dist/contact/delivery.d.ts.map +1 -0
- package/dist/contact/delivery.js +138 -0
- package/dist/contact/delivery.js.map +1 -0
- package/dist/contact/resend-webhook.d.ts +72 -0
- package/dist/contact/resend-webhook.d.ts.map +1 -0
- package/dist/contact/resend-webhook.js +300 -0
- package/dist/contact/resend-webhook.js.map +1 -0
- package/dist/contact/route-handler.d.ts +16 -0
- package/dist/contact/route-handler.d.ts.map +1 -1
- package/dist/contact/route-handler.js +8 -0
- package/dist/contact/route-handler.js.map +1 -1
- package/dist/contact/server-entry.d.ts +2 -0
- package/dist/contact/server-entry.d.ts.map +1 -1
- package/dist/contact/server-entry.js +2 -0
- package/dist/contact/server-entry.js.map +1 -1
- package/dist/contact/server.d.ts +26 -0
- package/dist/contact/server.d.ts.map +1 -1
- package/dist/contact/server.js +48 -3
- package/dist/contact/server.js.map +1 -1
- package/dist/navigation/constants.d.ts +11 -2
- package/dist/navigation/constants.d.ts.map +1 -1
- package/dist/navigation/constants.js +11 -2
- package/dist/navigation/constants.js.map +1 -1
- package/dist/navigation/index.d.ts +1 -1
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +1 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/navigation/use-back-to-top.d.ts.map +1 -1
- package/dist/navigation/use-back-to-top.js +12 -4
- package/dist/navigation/use-back-to-top.js.map +1 -1
- package/dist/navigation/use-header-metrics.d.ts +1 -1
- package/dist/navigation/use-header-metrics.js +1 -1
- package/dist/navigation/use-header-metrics.js.map +1 -1
- package/dist/navigation/use-sticky-call-bar.d.ts +2 -1
- package/dist/navigation/use-sticky-call-bar.d.ts.map +1 -1
- package/dist/navigation/use-sticky-call-bar.js +11 -2
- package/dist/navigation/use-sticky-call-bar.js.map +1 -1
- package/dist/next-config.d.ts +17 -1
- package/dist/next-config.d.ts.map +1 -1
- package/dist/next-config.js +36 -2
- package/dist/next-config.js.map +1 -1
- package/dist/ui-kit/brandlab-skin.d.ts +50 -1
- package/dist/ui-kit/brandlab-skin.d.ts.map +1 -1
- package/dist/ui-kit/brandlab-skin.js.map +1 -1
- package/dist/ui-kit/form/photo-upload.d.ts +4 -1
- package/dist/ui-kit/form/photo-upload.d.ts.map +1 -1
- package/dist/ui-kit/form/photo-upload.js +4 -4
- package/dist/ui-kit/form/photo-upload.js.map +1 -1
- package/dist/ui-kit/form/quote-form.d.ts +4 -1
- package/dist/ui-kit/form/quote-form.d.ts.map +1 -1
- package/dist/ui-kit/form/quote-form.js.map +1 -1
- package/dist/ui-kit/form/thank-you.d.ts +4 -1
- package/dist/ui-kit/form/thank-you.d.ts.map +1 -1
- package/dist/ui-kit/form/thank-you.js +2 -2
- package/dist/ui-kit/form/thank-you.js.map +1 -1
- package/dist/ui-kit/icon-glyphs.d.ts +41 -0
- package/dist/ui-kit/icon-glyphs.d.ts.map +1 -0
- package/dist/ui-kit/icon-glyphs.js +138 -0
- package/dist/ui-kit/icon-glyphs.js.map +1 -0
- package/dist/ui-kit/icon-sprite.d.ts +19 -0
- package/dist/ui-kit/icon-sprite.d.ts.map +1 -0
- package/dist/ui-kit/icon-sprite.js +44 -0
- package/dist/ui-kit/icon-sprite.js.map +1 -0
- package/dist/ui-kit/icons.d.ts +38 -3
- package/dist/ui-kit/icons.d.ts.map +1 -1
- package/dist/ui-kit/icons.js +47 -64
- package/dist/ui-kit/icons.js.map +1 -1
- package/dist/ui-kit/prefetch.d.ts +19 -10
- package/dist/ui-kit/prefetch.d.ts.map +1 -1
- package/dist/ui-kit/prefetch.js +23 -10
- package/dist/ui-kit/prefetch.js.map +1 -1
- package/dist/ui-kit/primitives/badge.d.ts +25 -0
- package/dist/ui-kit/primitives/badge.d.ts.map +1 -0
- package/dist/ui-kit/primitives/badge.js +21 -0
- package/dist/ui-kit/primitives/badge.js.map +1 -0
- package/dist/ui-kit/primitives/breadcrumbs.d.ts +27 -0
- package/dist/ui-kit/primitives/breadcrumbs.d.ts.map +1 -0
- package/dist/ui-kit/primitives/breadcrumbs.js +40 -0
- package/dist/ui-kit/primitives/breadcrumbs.js.map +1 -0
- package/dist/ui-kit/primitives/button.d.ts +32 -0
- package/dist/ui-kit/primitives/button.d.ts.map +1 -0
- package/dist/ui-kit/primitives/button.js +8 -0
- package/dist/ui-kit/primitives/button.js.map +1 -0
- package/dist/ui-kit/primitives/card.d.ts +40 -0
- package/dist/ui-kit/primitives/card.d.ts.map +1 -0
- package/dist/ui-kit/primitives/card.js +8 -0
- package/dist/ui-kit/primitives/card.js.map +1 -0
- package/dist/ui-kit/primitives/index.d.ts +11 -2
- package/dist/ui-kit/primitives/index.d.ts.map +1 -1
- package/dist/ui-kit/primitives/index.js +11 -2
- package/dist/ui-kit/primitives/index.js.map +1 -1
- package/dist/ui-kit/primitives/layout.d.ts +12 -0
- package/dist/ui-kit/primitives/layout.d.ts.map +1 -1
- package/dist/ui-kit/primitives/layout.js +20 -2
- package/dist/ui-kit/primitives/layout.js.map +1 -1
- package/dist/ui-kit/primitives/links.d.ts +15 -0
- package/dist/ui-kit/primitives/links.d.ts.map +1 -1
- package/dist/ui-kit/primitives/links.js +6 -2
- package/dist/ui-kit/primitives/links.js.map +1 -1
- package/dist/ui-kit/primitives/lists.d.ts +51 -0
- package/dist/ui-kit/primitives/lists.d.ts.map +1 -0
- package/dist/ui-kit/primitives/lists.js +34 -0
- package/dist/ui-kit/primitives/lists.js.map +1 -0
- package/dist/ui-kit/primitives/media-frame.d.ts +28 -0
- package/dist/ui-kit/primitives/media-frame.d.ts.map +1 -0
- package/dist/ui-kit/primitives/media-frame.js +58 -0
- package/dist/ui-kit/primitives/media-frame.js.map +1 -0
- package/dist/ui-kit/primitives/media.d.ts +38 -0
- package/dist/ui-kit/primitives/media.d.ts.map +1 -0
- package/dist/ui-kit/primitives/media.js +9 -0
- package/dist/ui-kit/primitives/media.js.map +1 -0
- package/dist/ui-kit/primitives/quote-button.d.ts +25 -2
- package/dist/ui-kit/primitives/quote-button.d.ts.map +1 -1
- package/dist/ui-kit/primitives/quote-button.js +25 -3
- package/dist/ui-kit/primitives/quote-button.js.map +1 -1
- package/dist/ui-kit/primitives/stat.d.ts +25 -0
- package/dist/ui-kit/primitives/stat.d.ts.map +1 -0
- package/dist/ui-kit/primitives/stat.js +7 -0
- package/dist/ui-kit/primitives/stat.js.map +1 -0
- package/dist/ui-kit/repeated-slots.d.ts +153 -0
- package/dist/ui-kit/repeated-slots.d.ts.map +1 -0
- package/dist/ui-kit/repeated-slots.js +97 -0
- package/dist/ui-kit/repeated-slots.js.map +1 -0
- package/dist/ui-kit/sections/accordion.d.ts +4 -1
- package/dist/ui-kit/sections/accordion.d.ts.map +1 -1
- package/dist/ui-kit/sections/accordion.js +2 -2
- package/dist/ui-kit/sections/accordion.js.map +1 -1
- package/dist/ui-kit/sections/area-map.d.ts +64 -0
- package/dist/ui-kit/sections/area-map.d.ts.map +1 -0
- package/dist/ui-kit/sections/area-map.js +142 -0
- package/dist/ui-kit/sections/area-map.js.map +1 -0
- package/dist/ui-kit/sections/before-after.d.ts +59 -0
- package/dist/ui-kit/sections/before-after.d.ts.map +1 -0
- package/dist/ui-kit/sections/before-after.js +42 -0
- package/dist/ui-kit/sections/before-after.js.map +1 -0
- package/dist/ui-kit/sections/contact-block.d.ts +4 -1
- package/dist/ui-kit/sections/contact-block.d.ts.map +1 -1
- package/dist/ui-kit/sections/contact-block.js +3 -3
- package/dist/ui-kit/sections/contact-block.js.map +1 -1
- package/dist/ui-kit/sections/council-rules.d.ts +64 -0
- package/dist/ui-kit/sections/council-rules.d.ts.map +1 -0
- package/dist/ui-kit/sections/council-rules.js +46 -0
- package/dist/ui-kit/sections/council-rules.js.map +1 -0
- package/dist/ui-kit/sections/coverage.d.ts +53 -0
- package/dist/ui-kit/sections/coverage.d.ts.map +1 -0
- package/dist/ui-kit/sections/coverage.js +57 -0
- package/dist/ui-kit/sections/coverage.js.map +1 -0
- package/dist/ui-kit/sections/emergency-band.d.ts +60 -0
- package/dist/ui-kit/sections/emergency-band.d.ts.map +1 -0
- package/dist/ui-kit/sections/emergency-band.js +43 -0
- package/dist/ui-kit/sections/emergency-band.js.map +1 -0
- package/dist/ui-kit/sections/faqs.d.ts +4 -1
- package/dist/ui-kit/sections/faqs.d.ts.map +1 -1
- package/dist/ui-kit/sections/faqs.js +4 -5
- package/dist/ui-kit/sections/faqs.js.map +1 -1
- package/dist/ui-kit/sections/gallery.d.ts +60 -0
- package/dist/ui-kit/sections/gallery.d.ts.map +1 -0
- package/dist/ui-kit/sections/gallery.js +39 -0
- package/dist/ui-kit/sections/gallery.js.map +1 -0
- package/dist/ui-kit/sections/hero.d.ts +118 -0
- package/dist/ui-kit/sections/hero.d.ts.map +1 -0
- package/dist/ui-kit/sections/hero.js +58 -0
- package/dist/ui-kit/sections/hero.js.map +1 -0
- package/dist/ui-kit/sections/index.d.ts +16 -1
- package/dist/ui-kit/sections/index.d.ts.map +1 -1
- package/dist/ui-kit/sections/index.js +16 -1
- package/dist/ui-kit/sections/index.js.map +1 -1
- package/dist/ui-kit/sections/licences.d.ts +72 -0
- package/dist/ui-kit/sections/licences.d.ts.map +1 -0
- package/dist/ui-kit/sections/licences.js +46 -0
- package/dist/ui-kit/sections/licences.js.map +1 -0
- package/dist/ui-kit/sections/local-facts.d.ts +78 -0
- package/dist/ui-kit/sections/local-facts.d.ts.map +1 -0
- package/dist/ui-kit/sections/local-facts.js +32 -0
- package/dist/ui-kit/sections/local-facts.js.map +1 -0
- package/dist/ui-kit/sections/nearby-areas.d.ts +50 -0
- package/dist/ui-kit/sections/nearby-areas.d.ts.map +1 -0
- package/dist/ui-kit/sections/nearby-areas.js +49 -0
- package/dist/ui-kit/sections/nearby-areas.js.map +1 -0
- package/dist/ui-kit/sections/nearby-jobs.d.ts +66 -0
- package/dist/ui-kit/sections/nearby-jobs.d.ts.map +1 -0
- package/dist/ui-kit/sections/nearby-jobs.js +49 -0
- package/dist/ui-kit/sections/nearby-jobs.js.map +1 -0
- package/dist/ui-kit/sections/price-guide.d.ts +4 -1
- package/dist/ui-kit/sections/price-guide.d.ts.map +1 -1
- package/dist/ui-kit/sections/price-guide.js +3 -3
- package/dist/ui-kit/sections/price-guide.js.map +1 -1
- package/dist/ui-kit/sections/price-table.d.ts +7 -9
- package/dist/ui-kit/sections/price-table.d.ts.map +1 -1
- package/dist/ui-kit/sections/price-table.js +8 -8
- package/dist/ui-kit/sections/price-table.js.map +1 -1
- package/dist/ui-kit/sections/projects.d.ts +79 -0
- package/dist/ui-kit/sections/projects.d.ts.map +1 -0
- package/dist/ui-kit/sections/projects.js +69 -0
- package/dist/ui-kit/sections/projects.js.map +1 -0
- package/dist/ui-kit/sections/proof-strip.d.ts +4 -1
- package/dist/ui-kit/sections/proof-strip.d.ts.map +1 -1
- package/dist/ui-kit/sections/proof-strip.js +2 -2
- package/dist/ui-kit/sections/proof-strip.js.map +1 -1
- package/dist/ui-kit/sections/quote-checklist.d.ts +43 -0
- package/dist/ui-kit/sections/quote-checklist.d.ts.map +1 -0
- package/dist/ui-kit/sections/quote-checklist.js +19 -0
- package/dist/ui-kit/sections/quote-checklist.js.map +1 -0
- package/dist/ui-kit/sections/related-services.d.ts +41 -0
- package/dist/ui-kit/sections/related-services.d.ts.map +1 -0
- package/dist/ui-kit/sections/related-services.js +52 -0
- package/dist/ui-kit/sections/related-services.js.map +1 -0
- package/dist/ui-kit/sections/reviews-band.d.ts +16 -2
- package/dist/ui-kit/sections/reviews-band.d.ts.map +1 -1
- package/dist/ui-kit/sections/reviews-band.js +13 -2
- package/dist/ui-kit/sections/reviews-band.js.map +1 -1
- package/dist/ui-kit/sections/services-grid.d.ts +82 -0
- package/dist/ui-kit/sections/services-grid.d.ts.map +1 -0
- package/dist/ui-kit/sections/services-grid.js +90 -0
- package/dist/ui-kit/sections/services-grid.js.map +1 -0
- package/dist/ui-kit/sections/site-footer.d.ts +4 -1
- package/dist/ui-kit/sections/site-footer.d.ts.map +1 -1
- package/dist/ui-kit/sections/site-footer.js +6 -6
- package/dist/ui-kit/sections/site-footer.js.map +1 -1
- package/dist/ui-kit/sections/work-photos.d.ts +15 -0
- package/dist/ui-kit/sections/work-photos.d.ts.map +1 -0
- package/dist/ui-kit/sections/work-photos.js +24 -0
- package/dist/ui-kit/sections/work-photos.js.map +1 -0
- package/dist/ui-kit/shell/back-to-top.js +1 -1
- package/dist/ui-kit/shell/back-to-top.js.map +1 -1
- package/dist/ui-kit/shell/current-link.d.ts +21 -5
- package/dist/ui-kit/shell/current-link.d.ts.map +1 -1
- package/dist/ui-kit/shell/current-link.js +16 -5
- package/dist/ui-kit/shell/current-link.js.map +1 -1
- package/dist/ui-kit/shell/drawer-client.js +1 -1
- package/dist/ui-kit/shell/drawer-client.js.map +1 -1
- package/dist/ui-kit/shell/intent-prefetch.d.ts.map +1 -1
- package/dist/ui-kit/shell/intent-prefetch.js +3 -2
- package/dist/ui-kit/shell/intent-prefetch.js.map +1 -1
- package/dist/ui-kit/shell/mobile-call-bar.d.ts +6 -1
- package/dist/ui-kit/shell/mobile-call-bar.d.ts.map +1 -1
- package/dist/ui-kit/shell/mobile-call-bar.js +6 -3
- package/dist/ui-kit/shell/mobile-call-bar.js.map +1 -1
- package/dist/ui-kit/shell/mobile-drawer.d.ts +7 -3
- package/dist/ui-kit/shell/mobile-drawer.d.ts.map +1 -1
- package/dist/ui-kit/shell/mobile-drawer.js +21 -5
- package/dist/ui-kit/shell/mobile-drawer.js.map +1 -1
- package/dist/ui-kit/shell/shell-quote.d.ts +10 -0
- package/dist/ui-kit/shell/shell-quote.d.ts.map +1 -0
- package/dist/ui-kit/shell/shell-quote.js +13 -0
- package/dist/ui-kit/shell/shell-quote.js.map +1 -0
- package/dist/ui-kit/shell/site-header.d.ts +5 -2
- package/dist/ui-kit/shell/site-header.d.ts.map +1 -1
- package/dist/ui-kit/shell/site-header.js +9 -9
- package/dist/ui-kit/shell/site-header.js.map +1 -1
- package/dist/ui-kit/shell/social-links.d.ts +1 -2
- package/dist/ui-kit/shell/social-links.d.ts.map +1 -1
- package/dist/ui-kit/shell/social-links.js +6 -3
- package/dist/ui-kit/shell/social-links.js.map +1 -1
- package/dist/ui-kit/shell/utility-bar.d.ts +4 -1
- package/dist/ui-kit/shell/utility-bar.d.ts.map +1 -1
- package/dist/ui-kit/shell/utility-bar.js +2 -2
- package/dist/ui-kit/shell/utility-bar.js.map +1 -1
- package/dist/ui-kit/skin-index.d.ts +2 -1
- package/dist/ui-kit/skin-index.d.ts.map +1 -1
- package/dist/ui-kit/skin-index.js +2 -1
- package/dist/ui-kit/skin-index.js.map +1 -1
- package/dist/ui-kit/skin.d.ts +21 -4
- package/dist/ui-kit/skin.d.ts.map +1 -1
- package/dist/ui-kit/skin.js +14 -1
- package/dist/ui-kit/skin.js.map +1 -1
- package/dist/ui-kit/structure.css +793 -10
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/button.tsx"],"names":[],"mappings":";AAQA,OAAO,EAAE,IAAI,EAAmB,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAA;AAsBjD,MAAM,UAAU,MAAM,CAAC,EACrB,QAAQ,EACR,IAAI,GAAG,QAAQ,EACf,IAAI,EACJ,YAAY,GAAG,KAAK,EACpB,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,MAAM,EACN,OAAO,GAAG,SAAS,EACnB,MAAM,EACN,OAAO,GACK;IACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,kBAAU,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,YAAE,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,GAAI,GAAO,CAAC,CAAC,CAAC,IAAI,CAAA;IAC3F,OAAO,CACL,kBACE,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,aACV,QAAQ,kBACF,OAAO,eACV,MAAM,EAAE,IAAI,IAAI,SAAS,oBACpB,MAAM,EACtB,SAAS,EAAE,OAAO,EAAE,IAAI,aAEvB,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAC3C,kBAAU,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,YAAG,QAAQ,GAAQ,EAClD,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAClC,CACV,CAAA;AACH,CAAC","sourcesContent":["/**\n * `Button` (3.14.0): an action on the page, as distinct from `ButtonLink`, which goes somewhere. A real `<button>`\n * (default `type=\"button\"`) with the same `data-bl=\"button\"` hook, variants and sizes as `ButtonLink`, so one skin\n * stylesheet rule and the shared 44 px minimum cover both; `button[data-bl='button']` tells them apart. Server\n * component. It takes no event props: a form submits it, or a client island finds it by its `action` hook\n * (`data-bl-action`) and listens there. `disabled` is the native attribute, so it is announced.\n */\nimport type { ReactNode } from 'react'\nimport { Icon, type UiIconName } from '../icons.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport type { ButtonVariant } from './links.js'\n\nexport type ButtonSlot = 'root' | 'label' | 'icon'\nexport type ButtonSkin = SkinEntry<ButtonSlot, ButtonVariant, { size?: 'regular' | 'large' }>\n\nexport interface ButtonProps extends ButtonSkin {\n readonly children: ReactNode\n /** `button` by default; `submit` inside a form. */\n readonly type?: 'button' | 'submit' | 'reset'\n /** An icon after the label (`arrow`) or before it (`phone`). */\n readonly icon?: UiIconName\n readonly iconPosition?: 'start' | 'end'\n readonly disabled?: boolean\n /** The form field name and value it submits, and the id of a form outside it that it submits. */\n readonly name?: string\n readonly value?: string\n readonly form?: string\n /** A stable name a client island listens for, rendered as `data-bl-action` (for example `show-more`). */\n readonly action?: string\n}\n\nexport function Button({\n children,\n type = 'button',\n icon,\n iconPosition = 'end',\n disabled,\n name,\n value,\n form,\n action,\n variant = 'primary',\n layout,\n classes,\n}: ButtonProps) {\n const iconNode = icon ? <span {...slot(classes, 'icon')}><Icon name={icon} /></span> : null\n return (\n <button\n type={type}\n name={name}\n value={value}\n form={form}\n disabled={disabled}\n data-bl=\"button\"\n data-variant={variant}\n data-size={layout?.size ?? 'regular'}\n data-bl-action={action}\n className={classes?.root}\n >\n {iconPosition === 'start' ? iconNode : null}\n <span {...slot(classes, 'label')}>{children}</span>\n {iconPosition === 'end' ? iconNode : null}\n </button>\n )\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Card` (3.14.0): one entry of a grid or list (a service, a project, a guide). Server component. A heading inside
|
|
3
|
+
* every card; with `href` the whole card is one link, made by the title's own link and a stretched hit area
|
|
4
|
+
* (structure.css), so there are never nested links and the link's name is the title.
|
|
5
|
+
*
|
|
6
|
+
* A card is always rendered once per entry of a list, so none of its parts take a class (3.14.0 repeated slots): the
|
|
7
|
+
* site styles `[data-bl="card"]` and its `[data-slot]` parts once in `src/site/skin.css`. Its skin entry holds the
|
|
8
|
+
* media position only.
|
|
9
|
+
*/
|
|
10
|
+
import type { ReactNode } from 'react';
|
|
11
|
+
import type { LinkPrefetch } from '../prefetch.js';
|
|
12
|
+
import type { RepeatedSlotOf } from '../repeated-slots.js';
|
|
13
|
+
import { type SkinEntry } from '../skin.js';
|
|
14
|
+
/** Every part of a card is repeated: styled from the skin stylesheet through `[data-bl="card"] [data-slot]`. */
|
|
15
|
+
export type CardSlot = RepeatedSlotOf<'card'>;
|
|
16
|
+
export interface CardLayout {
|
|
17
|
+
/** Where the media sits beside the body at wider widths (default `top`). */
|
|
18
|
+
readonly media?: 'top' | 'start';
|
|
19
|
+
}
|
|
20
|
+
export type CardSkin = SkinEntry<CardSlot, never, CardLayout, CardSlot>;
|
|
21
|
+
export interface CardProps extends CardSkin {
|
|
22
|
+
/** The card's heading text; with `href` it is the link's whole name. */
|
|
23
|
+
readonly title: string;
|
|
24
|
+
/** The heading level from the page outline: 3 under a section's H2 (the default), 2 when the cards are the section. */
|
|
25
|
+
readonly headingLevel?: 2 | 3 | 4;
|
|
26
|
+
/** The root element: `article` (default), `li` inside a list the caller renders, or `div`. */
|
|
27
|
+
readonly as?: 'article' | 'li' | 'div';
|
|
28
|
+
/** Makes the whole card one link to this page. */
|
|
29
|
+
readonly href?: string;
|
|
30
|
+
/** Cards prefetch on intent by default (`LINK_PREFETCH_POLICY.contentCard`). */
|
|
31
|
+
readonly prefetch?: LinkPrefetch;
|
|
32
|
+
/** The card's image (a `MediaFrame` with a fixed or `vw` size), rendered before the body. */
|
|
33
|
+
readonly media?: ReactNode;
|
|
34
|
+
/** The card's text: a short summary. */
|
|
35
|
+
readonly children?: ReactNode;
|
|
36
|
+
/** A line under the text, for example the suburb and month of a project, or a price band. */
|
|
37
|
+
readonly meta?: ReactNode;
|
|
38
|
+
}
|
|
39
|
+
export declare function Card({ title, headingLevel, as: Root, href, prefetch, media, children, meta, layout }: CardProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/card.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAGzD,gHAAgH;AAChH,MAAM,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;AAC7C,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAAA;CACjC;AACD,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAA;AAEvE,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,uHAAuH;IACvH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACjC,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,KAAK,CAAA;IACtC,kDAAkD;IAClD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;IAChC,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAA;IAC1B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;IAC7B,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAC1B;AAED,wBAAgB,IAAI,CAAC,EAAE,KAAK,EAAE,YAAgB,EAAE,EAAE,EAAE,IAAgB,EAAE,IAAI,EAAE,QAAmB,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,2CAoB1I"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { repeatedSlot } from '../skin.js';
|
|
3
|
+
import { Anchor } from './links.js';
|
|
4
|
+
export function Card({ title, headingLevel = 3, as: Root = 'article', href, prefetch = 'intent', media, children, meta, layout }) {
|
|
5
|
+
const Heading = `h${headingLevel}`;
|
|
6
|
+
return (_jsxs(Root, { "data-bl": "card", "data-media": media ? (layout?.media ?? 'top') : undefined, "data-linked": href ? '' : undefined, children: [media ? _jsx("div", { ...repeatedSlot('media'), children: media }) : null, _jsxs("div", { ...repeatedSlot('body'), children: [_jsx(Heading, { ...repeatedSlot('title'), children: href ? (_jsx(Anchor, { href: href, prefetch: prefetch, hooks: { 'data-slot': 'link' }, children: title })) : (title) }), children ? _jsx("div", { ...repeatedSlot('text'), children: children }) : null, meta ? _jsx("div", { ...repeatedSlot('meta'), children: meta }) : null] })] }));
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/card.tsx"],"names":[],"mappings":";AAYA,OAAO,EAAE,YAAY,EAAkB,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AA6BnC,MAAM,UAAU,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAa;IACzI,MAAM,OAAO,GAAG,IAAI,YAAY,EAAW,CAAA;IAC3C,OAAO,CACL,MAAC,IAAI,eAAS,MAAM,gBAAa,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,iBAAe,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,aAC9G,KAAK,CAAC,CAAC,CAAC,iBAAS,YAAY,CAAC,OAAO,CAAC,YAAG,KAAK,GAAO,CAAC,CAAC,CAAC,IAAI,EAC7D,kBAAS,YAAY,CAAC,MAAM,CAAC,aAC3B,KAAC,OAAO,OAAK,YAAY,CAAC,OAAO,CAAC,YAC/B,IAAI,CAAC,CAAC,CAAC,CACN,KAAC,MAAM,IAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,YACnE,KAAK,GACC,CACV,CAAC,CAAC,CAAC,CACF,KAAK,CACN,GACO,EACT,QAAQ,CAAC,CAAC,CAAC,iBAAS,YAAY,CAAC,MAAM,CAAC,YAAG,QAAQ,GAAO,CAAC,CAAC,CAAC,IAAI,EACjE,IAAI,CAAC,CAAC,CAAC,iBAAS,YAAY,CAAC,MAAM,CAAC,YAAG,IAAI,GAAO,CAAC,CAAC,CAAC,IAAI,IACtD,IACD,CACR,CAAA;AACH,CAAC","sourcesContent":["/**\n * `Card` (3.14.0): one entry of a grid or list (a service, a project, a guide). Server component. A heading inside\n * every card; with `href` the whole card is one link, made by the title's own link and a stretched hit area\n * (structure.css), so there are never nested links and the link's name is the title.\n *\n * A card is always rendered once per entry of a list, so none of its parts take a class (3.14.0 repeated slots): the\n * site styles `[data-bl=\"card\"]` and its `[data-slot]` parts once in `src/site/skin.css`. Its skin entry holds the\n * media position only.\n */\nimport type { ReactNode } from 'react'\nimport type { LinkPrefetch } from '../prefetch.js'\nimport type { RepeatedSlotOf } from '../repeated-slots.js'\nimport { repeatedSlot, type SkinEntry } from '../skin.js'\nimport { Anchor } from './links.js'\n\n/** Every part of a card is repeated: styled from the skin stylesheet through `[data-bl=\"card\"] [data-slot]`. */\nexport type CardSlot = RepeatedSlotOf<'card'>\nexport interface CardLayout {\n /** Where the media sits beside the body at wider widths (default `top`). */\n readonly media?: 'top' | 'start'\n}\nexport type CardSkin = SkinEntry<CardSlot, never, CardLayout, CardSlot>\n\nexport interface CardProps extends CardSkin {\n /** The card's heading text; with `href` it is the link's whole name. */\n readonly title: string\n /** The heading level from the page outline: 3 under a section's H2 (the default), 2 when the cards are the section. */\n readonly headingLevel?: 2 | 3 | 4\n /** The root element: `article` (default), `li` inside a list the caller renders, or `div`. */\n readonly as?: 'article' | 'li' | 'div'\n /** Makes the whole card one link to this page. */\n readonly href?: string\n /** Cards prefetch on intent by default (`LINK_PREFETCH_POLICY.contentCard`). */\n readonly prefetch?: LinkPrefetch\n /** The card's image (a `MediaFrame` with a fixed or `vw` size), rendered before the body. */\n readonly media?: ReactNode\n /** The card's text: a short summary. */\n readonly children?: ReactNode\n /** A line under the text, for example the suburb and month of a project, or a price band. */\n readonly meta?: ReactNode\n}\n\nexport function Card({ title, headingLevel = 3, as: Root = 'article', href, prefetch = 'intent', media, children, meta, layout }: CardProps) {\n const Heading = `h${headingLevel}` as const\n return (\n <Root data-bl=\"card\" data-media={media ? (layout?.media ?? 'top') : undefined} data-linked={href ? '' : undefined}>\n {media ? <div {...repeatedSlot('media')}>{media}</div> : null}\n <div {...repeatedSlot('body')}>\n <Heading {...repeatedSlot('title')}>\n {href ? (\n <Anchor href={href} prefetch={prefetch} hooks={{ 'data-slot': 'link' }}>\n {title}\n </Anchor>\n ) : (\n title\n )}\n </Heading>\n {children ? <div {...repeatedSlot('text')}>{children}</div> : null}\n {meta ? <div {...repeatedSlot('meta')}>{meta}</div> : null}\n </div>\n </Root>\n )\n}\n"]}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
export { BUTTON_VARIANTS, ButtonLink, PhoneLink, TextLink, type ButtonLinkProps, type ButtonLinkSkin, type ButtonLinkSlot, type ButtonVariant, type PhoneLinkProps, type PhoneLinkSkin, type PhoneLinkSlot, type TextLinkProps, type TextLinkSkin, type TextLinkSlot, } from './links.js';
|
|
2
|
-
export { CONTAINER_WIDTHS, Container, RatingStars, SECTION_TONES, Section, SectionHeading, VisuallyHidden, type ContainerSkin, type ContainerWidth, type SectionHeadingProps, type SectionHeadingSkin, type SectionHeadingSlot, type SectionProps, type SectionSlot, type SectionTone, } from './layout.js';
|
|
2
|
+
export { CONTAINER_WIDTHS, Container, Eyebrow, RatingStars, SECTION_TONES, Section, SectionHeading, VisuallyHidden, type ContainerSkin, type ContainerWidth, type EyebrowSkin, type EyebrowSlot, type SectionHeadingProps, type SectionHeadingSkin, type SectionHeadingSlot, type SectionProps, type SectionSlot, type SectionTone, } from './layout.js';
|
|
3
|
+
export { Button, type ButtonProps, type ButtonSkin, type ButtonSlot } from './button.js';
|
|
4
|
+
export { Card, type CardLayout, type CardProps, type CardSkin, type CardSlot } from './card.js';
|
|
5
|
+
export { Badge, Chip, type BadgeProps, type BadgeSkin, type BadgeSlot, type ChipProps, type ChipSkin, type ChipSlot } from './badge.js';
|
|
6
|
+
export { Stat, type StatProps, type StatSkin, type StatSlot } from './stat.js';
|
|
7
|
+
export { LINK_LIST_KINDS, LinkList, TickList, type LinkListKind, type LinkListLayout, type LinkListEntry, type LinkListProps, type LinkListSkin, type LinkListSlot, type TickItem, type TickListLayout, type TickListProps, type TickListRepeatedSlot, type TickListSkin, type TickListSlot, } from './lists.js';
|
|
8
|
+
export { ILLUSTRATION_LABEL, MediaFrame, type MediaFrameProps, type MediaFrameSizing, type MediaFrameSkin, type MediaFrameSlot, type UiMedia, } from './media-frame.js';
|
|
9
|
+
export { MEDIA_ILLUSTRATION_LABEL, Media, type MediaLayout, type MediaProps, type MediaSkin, type MediaSlot } from './media.js';
|
|
10
|
+
export { BREADCRUMBS_LABEL, Breadcrumbs, breadcrumbsSchema, type BreadcrumbTrail, type BreadcrumbsProps, type BreadcrumbsRepeatedSlot, type BreadcrumbsSkin, type BreadcrumbsSlot, } from './breadcrumbs.js';
|
|
3
11
|
export { QuoteButton, type QuoteButtonProps, type QuoteButtonSkin, type QuoteButtonSlot } from './quote-button.js';
|
|
4
|
-
export { Icon, SocialIcon, UI_ICON_NAMES, type IconProps, type UiIconName } from '../icons.js';
|
|
12
|
+
export { Icon, SocialIcon, UI_ICON_NAMES, createSiteIcon, iconSpriteHref, type IconProps, type UiIconName } from '../icons.js';
|
|
13
|
+
export { defineSiteIcons, type IconGlyph, type SiteIconSet } from '../icon-glyphs.js';
|
|
5
14
|
export { UI_SOCIAL_KINDS, type UiLink, type UiPhone, type UiSocial, type UiSocialKind } from '../types.js';
|
|
6
15
|
export { INTENT_PREFETCH_SELECTOR, LINK_PREFETCH_LIMITS, LINK_PREFETCH_POLICY, linkPrefetchProps, type LinkPrefetch, type LinkPrefetchRole, } from '../prefetch.js';
|
|
7
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,UAAU,EACV,SAAS,EACT,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,aAAa,EACb,OAAO,EACP,cAAc,EACd,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAClH,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
export { BUTTON_VARIANTS, ButtonLink, PhoneLink, TextLink, } from './links.js';
|
|
2
|
-
export { CONTAINER_WIDTHS, Container, RatingStars, SECTION_TONES, Section, SectionHeading, VisuallyHidden, } from './layout.js';
|
|
2
|
+
export { CONTAINER_WIDTHS, Container, Eyebrow, RatingStars, SECTION_TONES, Section, SectionHeading, VisuallyHidden, } from './layout.js';
|
|
3
|
+
export { Button } from './button.js';
|
|
4
|
+
export { Card } from './card.js';
|
|
5
|
+
export { Badge, Chip } from './badge.js';
|
|
6
|
+
export { Stat } from './stat.js';
|
|
7
|
+
export { LINK_LIST_KINDS, LinkList, TickList, } from './lists.js';
|
|
8
|
+
export { ILLUSTRATION_LABEL, MediaFrame, } from './media-frame.js';
|
|
9
|
+
export { MEDIA_ILLUSTRATION_LABEL, Media } from './media.js';
|
|
10
|
+
export { BREADCRUMBS_LABEL, Breadcrumbs, breadcrumbsSchema, } from './breadcrumbs.js';
|
|
3
11
|
export { QuoteButton } from './quote-button.js';
|
|
4
|
-
export { Icon, SocialIcon, UI_ICON_NAMES } from '../icons.js';
|
|
12
|
+
export { Icon, SocialIcon, UI_ICON_NAMES, createSiteIcon, iconSpriteHref } from '../icons.js';
|
|
13
|
+
export { defineSiteIcons } from '../icon-glyphs.js';
|
|
5
14
|
export { UI_SOCIAL_KINDS } from '../types.js';
|
|
6
15
|
export { INTENT_PREFETCH_SELECTOR, LINK_PREFETCH_LIMITS, LINK_PREFETCH_POLICY, linkPrefetchProps, } from '../prefetch.js';
|
|
7
16
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,UAAU,EACV,SAAS,EACT,QAAQ,GAWT,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,aAAa,EACb,OAAO,EACP,cAAc,EACd,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,UAAU,EACV,SAAS,EACT,QAAQ,GAWT,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,OAAO,EACP,WAAW,EACX,aAAa,EACb,OAAO,EACP,cAAc,EACd,cAAc,GAWf,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,MAAM,EAAsD,MAAM,aAAa,CAAA;AACxF,OAAO,EAAE,IAAI,EAAiE,MAAM,WAAW,CAAA;AAC/F,OAAO,EAAE,KAAK,EAAE,IAAI,EAAiG,MAAM,YAAY,CAAA;AACvI,OAAO,EAAE,IAAI,EAAgD,MAAM,WAAW,CAAA;AAC9E,OAAO,EACL,eAAe,EACf,QAAQ,EACR,QAAQ,GAaT,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,kBAAkB,EAClB,UAAU,GAMX,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,wBAAwB,EAAE,KAAK,EAAqE,MAAM,YAAY,CAAA;AAC/H,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAMlB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,WAAW,EAAqE,MAAM,mBAAmB,CAAA;AAClH,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAmC,MAAM,aAAa,CAAA;AAC9H,OAAO,EAAE,eAAe,EAAoC,MAAM,mBAAmB,CAAA;AACrF,OAAO,EAAE,eAAe,EAA+D,MAAM,aAAa,CAAA;AAC1G,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,GAGlB,MAAM,gBAAgB,CAAA","sourcesContent":["export {\n BUTTON_VARIANTS,\n ButtonLink,\n PhoneLink,\n TextLink,\n type ButtonLinkProps,\n type ButtonLinkSkin,\n type ButtonLinkSlot,\n type ButtonVariant,\n type PhoneLinkProps,\n type PhoneLinkSkin,\n type PhoneLinkSlot,\n type TextLinkProps,\n type TextLinkSkin,\n type TextLinkSlot,\n} from './links.js'\nexport {\n CONTAINER_WIDTHS,\n Container,\n Eyebrow,\n RatingStars,\n SECTION_TONES,\n Section,\n SectionHeading,\n VisuallyHidden,\n type ContainerSkin,\n type ContainerWidth,\n type EyebrowSkin,\n type EyebrowSlot,\n type SectionHeadingProps,\n type SectionHeadingSkin,\n type SectionHeadingSlot,\n type SectionProps,\n type SectionSlot,\n type SectionTone,\n} from './layout.js'\nexport { Button, type ButtonProps, type ButtonSkin, type ButtonSlot } from './button.js'\nexport { Card, type CardLayout, type CardProps, type CardSkin, type CardSlot } from './card.js'\nexport { Badge, Chip, type BadgeProps, type BadgeSkin, type BadgeSlot, type ChipProps, type ChipSkin, type ChipSlot } from './badge.js'\nexport { Stat, type StatProps, type StatSkin, type StatSlot } from './stat.js'\nexport {\n LINK_LIST_KINDS,\n LinkList,\n TickList,\n type LinkListKind,\n type LinkListLayout,\n type LinkListEntry,\n type LinkListProps,\n type LinkListSkin,\n type LinkListSlot,\n type TickItem,\n type TickListLayout,\n type TickListProps,\n type TickListRepeatedSlot,\n type TickListSkin,\n type TickListSlot,\n} from './lists.js'\nexport {\n ILLUSTRATION_LABEL,\n MediaFrame,\n type MediaFrameProps,\n type MediaFrameSizing,\n type MediaFrameSkin,\n type MediaFrameSlot,\n type UiMedia,\n} from './media-frame.js'\nexport { MEDIA_ILLUSTRATION_LABEL, Media, type MediaLayout, type MediaProps, type MediaSkin, type MediaSlot } from './media.js'\nexport {\n BREADCRUMBS_LABEL,\n Breadcrumbs,\n breadcrumbsSchema,\n type BreadcrumbTrail,\n type BreadcrumbsProps,\n type BreadcrumbsRepeatedSlot,\n type BreadcrumbsSkin,\n type BreadcrumbsSlot,\n} from './breadcrumbs.js'\nexport { QuoteButton, type QuoteButtonProps, type QuoteButtonSkin, type QuoteButtonSlot } from './quote-button.js'\nexport { Icon, SocialIcon, UI_ICON_NAMES, createSiteIcon, iconSpriteHref, type IconProps, type UiIconName } from '../icons.js'\nexport { defineSiteIcons, type IconGlyph, type SiteIconSet } from '../icon-glyphs.js'\nexport { UI_SOCIAL_KINDS, type UiLink, type UiPhone, type UiSocial, type UiSocialKind } from '../types.js'\nexport {\n INTENT_PREFETCH_SELECTOR,\n LINK_PREFETCH_LIMITS,\n LINK_PREFETCH_POLICY,\n linkPrefetchProps,\n type LinkPrefetch,\n type LinkPrefetchRole,\n} from '../prefetch.js'\n"]}
|
|
@@ -57,9 +57,21 @@ export interface SectionHeadingProps extends SectionHeadingSkin {
|
|
|
57
57
|
}
|
|
58
58
|
/** A section's heading block: an optional eyebrow, the H2 and an optional lead paragraph. */
|
|
59
59
|
export declare function SectionHeading({ id, title, eyebrow, lead, layout, classes }: SectionHeadingProps): import("react/jsx-runtime").JSX.Element;
|
|
60
|
+
export type EyebrowSlot = 'root';
|
|
61
|
+
export type EyebrowSkin = SkinEntry<EyebrowSlot>;
|
|
62
|
+
/**
|
|
63
|
+
* A short label above a site's own heading (3.14.0), for signature sections that don't use `SectionHeading`. At
|
|
64
|
+
* least 13 px; never the only label for a section. `SectionHeading` and the hero keep their own `eyebrow` slot.
|
|
65
|
+
*/
|
|
66
|
+
export declare function Eyebrow({ children, classes }: EyebrowSkin & {
|
|
67
|
+
readonly children: ReactNode;
|
|
68
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
60
69
|
/**
|
|
61
70
|
* Five stars with one text alternative ("Rated 4.9 out of 5"). The stars use `--bl-color-star`; whole stars only,
|
|
62
71
|
* rounded to the nearest. The rating always comes from the feed, never typed by hand (T4).
|
|
72
|
+
*
|
|
73
|
+
* From 3.14.0 the row is one `<svg>` holding five `<use>` references to the sprite's star (`data-slot="star"`,
|
|
74
|
+
* `data-state="on" | "off"`), not five icons; without the sprite each star is a `<g>` with the glyph inline.
|
|
63
75
|
*/
|
|
64
76
|
export declare function RatingStars({ rating, label, className }: {
|
|
65
77
|
readonly rating: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/layout.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE5D,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAEjD,eAAO,MAAM,gBAAgB,wCAAyC,CAAA;AACtE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAC9D,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE;IAAE,KAAK,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC,CAAA;AAEhF,2GAA2G;AAC3G,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,aAAa,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAMxG;AAED,sHAAsH;AACtH,eAAO,MAAM,aAAa,iDAAkD,CAAA;AAC5E,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,CAAA;AAE1C,MAAM,WAAW,YAAY;IAC3B,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,sFAAsF;IACtF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;IAC7E,6CAA6C;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAA;IAC/B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;IACvE,0FAA0F;IAC1F,QAAQ,CAAC,cAAc,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACxD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,YAAY,2CAmB5H;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAA;AACxE,MAAM,MAAM,kBAAkB,GAAG,SAAS,CAAC,kBAAkB,EAAE,KAAK,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;CAAE,CAAC,CAAA;AAErG,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,oEAAoE;IACpE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;IACzB,yFAAyF;IACzF,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAC1B;AAED,6FAA6F;AAC7F,wBAAgB,cAAc,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,mBAAmB,2CAUhG;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/layout.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { starGlyph } from '../icons.js';
|
|
3
3
|
import { slot } from '../skin.js';
|
|
4
4
|
export const CONTAINER_WIDTHS = ['default', 'narrow', 'wide'];
|
|
5
5
|
/** One container width shared by the header, the page and the footer (`--bl-container`, `--bl-gutter`). */
|
|
@@ -19,13 +19,31 @@ export function Section({ id, labelledBy, tone, variant, classes, decoration, ho
|
|
|
19
19
|
export function SectionHeading({ id, title, eyebrow, lead, layout, classes }) {
|
|
20
20
|
return (_jsxs("div", { ...slot(classes, 'head'), "data-align": layout?.align ?? 'start', children: [eyebrow ? _jsx("p", { ...slot(classes, 'eyebrow'), children: eyebrow }) : null, _jsx("h2", { id: id, ...slot(classes, 'heading'), children: title }), lead ? _jsx("p", { ...slot(classes, 'lead'), children: lead }) : null] }));
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* A short label above a site's own heading (3.14.0), for signature sections that don't use `SectionHeading`. At
|
|
24
|
+
* least 13 px; never the only label for a section. `SectionHeading` and the hero keep their own `eyebrow` slot.
|
|
25
|
+
*/
|
|
26
|
+
export function Eyebrow({ children, classes }) {
|
|
27
|
+
return (_jsx("p", { "data-bl": "eyebrow", className: classes?.root, children: children }));
|
|
28
|
+
}
|
|
29
|
+
/** The rating row's geometry: five 20-unit stars, 2 units apart, in one `viewBox`. */
|
|
30
|
+
const STAR_SIZE = 20;
|
|
31
|
+
const STAR_STRIDE = 22;
|
|
32
|
+
const STARS_VIEW_BOX = `0 0 ${STAR_STRIDE * 4 + STAR_SIZE} ${STAR_SIZE}`;
|
|
22
33
|
/**
|
|
23
34
|
* Five stars with one text alternative ("Rated 4.9 out of 5"). The stars use `--bl-color-star`; whole stars only,
|
|
24
35
|
* rounded to the nearest. The rating always comes from the feed, never typed by hand (T4).
|
|
36
|
+
*
|
|
37
|
+
* From 3.14.0 the row is one `<svg>` holding five `<use>` references to the sprite's star (`data-slot="star"`,
|
|
38
|
+
* `data-state="on" | "off"`), not five icons; without the sprite each star is a `<g>` with the glyph inline.
|
|
25
39
|
*/
|
|
26
40
|
export function RatingStars({ rating, label, className }) {
|
|
27
41
|
const filled = Math.max(0, Math.min(5, Math.round(rating)));
|
|
28
|
-
|
|
42
|
+
const star = starGlyph();
|
|
43
|
+
return (_jsx("span", { "data-bl": "stars", role: "img", "aria-label": label ?? `Rated ${rating.toFixed(1)} out of 5`, className: className, children: _jsx("svg", { "aria-hidden": "true", viewBox: STARS_VIEW_BOX, children: Array.from({ length: 5 }, (_, index) => {
|
|
44
|
+
const state = index < filled ? 'on' : 'off';
|
|
45
|
+
return star.href ? (_jsx("use", { href: star.href, x: index * STAR_STRIDE, width: STAR_SIZE, height: STAR_SIZE, "data-slot": "star", "data-state": state }, index)) : (_jsx("g", { transform: index === 0 ? undefined : `translate(${index * STAR_STRIDE})`, "data-slot": "star", "data-state": state, dangerouslySetInnerHTML: { __html: star.glyph.body } }, index));
|
|
46
|
+
}) }) }));
|
|
29
47
|
}
|
|
30
48
|
/** Text for assistive technology only. */
|
|
31
49
|
export function VisuallyHidden({ children }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/layout.tsx"],"names":[],"mappings":";AAOA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/layout.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Layout primitives: `Container`, `Section`, `SectionHeading`, `Eyebrow`, `RatingStars` and `VisuallyHidden`.\n * Server components. Heading levels come from the page outline (one H1 in the hero or page header, an H2 per\n * section), never from a look.\n */\nimport type { ReactNode } from 'react'\nimport type { PhoneCallPlacement } from '../../analytics.js'\nimport { starGlyph } from '../icons.js'\nimport { slot, type SkinEntry } from '../skin.js'\n\nexport const CONTAINER_WIDTHS = ['default', 'narrow', 'wide'] as const\nexport type ContainerWidth = (typeof CONTAINER_WIDTHS)[number]\nexport type ContainerSkin = SkinEntry<'root', never, { width?: ContainerWidth }>\n\n/** One container width shared by the header, the page and the footer (`--bl-container`, `--bl-gutter`). */\nexport function Container({ children, layout, classes }: ContainerSkin & { readonly children: ReactNode }) {\n return (\n <div data-bl=\"container\" data-width={layout?.width ?? 'default'} className={classes?.root}>\n {children}\n </div>\n )\n}\n\n/** The four section tones `SectionSequence` assigns: two alternating grounds, one optional band, one photo ground. */\nexport const SECTION_TONES = ['canvas', 'surface', 'band', 'photo'] as const\nexport type SectionTone = (typeof SECTION_TONES)[number]\n\nexport type SectionSlot = 'root' | 'inner'\n\nexport interface SectionProps {\n /** The matrix id, rendered as `data-bl-section` (for example `reviews`, `cta`, `faqs`). */\n readonly id: string\n /** The id of the section's H2. A section is a `<section>` labelled by its heading. */\n readonly labelledBy: string\n readonly tone?: SectionTone | undefined\n readonly variant?: string | undefined\n readonly classes?: Readonly<Partial<Record<SectionSlot, string>>> | undefined\n /** Signature art, rendered `aria-hidden`. */\n readonly decoration?: ReactNode\n /**\n * Extra layout hooks on the root, for example `{ 'data-columns': '3' }`. They cannot override `data-bl-section`,\n * `data-variant`, `data-tone` or `data-phone-location`.\n */\n readonly hooks?: Readonly<Record<`data-${string}`, string | undefined>>\n /** The placement a `tel:` link inside the section reports when it has none of its own. */\n readonly phonePlacement?: PhoneCallPlacement | undefined\n readonly children: ReactNode\n}\n\n/**\n * The root every section component renders: `<section data-bl-section aria-labelledby>`, its tone and variant, an\n * optional `aria-hidden` decoration and the inner container slot.\n */\nexport function Section({ id, labelledBy, tone, variant, classes, decoration, hooks, phonePlacement, children }: SectionProps) {\n return (\n <section\n {...hooks}\n data-bl-section={id}\n data-variant={variant}\n data-tone={tone}\n data-phone-location={phonePlacement}\n aria-labelledby={labelledBy}\n className={classes?.root}\n >\n {decoration ? (\n <div data-slot=\"decoration\" aria-hidden=\"true\">\n {decoration}\n </div>\n ) : null}\n <div {...slot(classes, 'inner')}>{children}</div>\n </section>\n )\n}\n\nexport type SectionHeadingSlot = 'head' | 'eyebrow' | 'heading' | 'lead'\nexport type SectionHeadingSkin = SkinEntry<SectionHeadingSlot, never, { align?: 'start' | 'center' }>\n\nexport interface SectionHeadingProps extends SectionHeadingSkin {\n /** The H2's id, which the section's `aria-labelledby` points at. */\n readonly id: string\n readonly title: ReactNode\n /** A short label above the H2 (at least 13 px; never the only label for the section). */\n readonly eyebrow?: ReactNode\n readonly lead?: ReactNode\n}\n\n/** A section's heading block: an optional eyebrow, the H2 and an optional lead paragraph. */\nexport function SectionHeading({ id, title, eyebrow, lead, layout, classes }: SectionHeadingProps) {\n return (\n <div {...slot(classes, 'head')} data-align={layout?.align ?? 'start'}>\n {eyebrow ? <p {...slot(classes, 'eyebrow')}>{eyebrow}</p> : null}\n <h2 id={id} {...slot(classes, 'heading')}>\n {title}\n </h2>\n {lead ? <p {...slot(classes, 'lead')}>{lead}</p> : null}\n </div>\n )\n}\n\nexport type EyebrowSlot = 'root'\nexport type EyebrowSkin = SkinEntry<EyebrowSlot>\n\n/**\n * A short label above a site's own heading (3.14.0), for signature sections that don't use `SectionHeading`. At\n * least 13 px; never the only label for a section. `SectionHeading` and the hero keep their own `eyebrow` slot.\n */\nexport function Eyebrow({ children, classes }: EyebrowSkin & { readonly children: ReactNode }) {\n return (\n <p data-bl=\"eyebrow\" className={classes?.root}>\n {children}\n </p>\n )\n}\n\n/** The rating row's geometry: five 20-unit stars, 2 units apart, in one `viewBox`. */\nconst STAR_SIZE = 20\nconst STAR_STRIDE = 22\nconst STARS_VIEW_BOX = `0 0 ${STAR_STRIDE * 4 + STAR_SIZE} ${STAR_SIZE}`\n\n/**\n * Five stars with one text alternative (\"Rated 4.9 out of 5\"). The stars use `--bl-color-star`; whole stars only,\n * rounded to the nearest. The rating always comes from the feed, never typed by hand (T4).\n *\n * From 3.14.0 the row is one `<svg>` holding five `<use>` references to the sprite's star (`data-slot=\"star\"`,\n * `data-state=\"on\" | \"off\"`), not five icons; without the sprite each star is a `<g>` with the glyph inline.\n */\nexport function RatingStars({ rating, label, className }: { readonly rating: number; readonly label?: string; readonly className?: string }) {\n const filled = Math.max(0, Math.min(5, Math.round(rating)))\n const star = starGlyph()\n return (\n <span data-bl=\"stars\" role=\"img\" aria-label={label ?? `Rated ${rating.toFixed(1)} out of 5`} className={className}>\n <svg aria-hidden=\"true\" viewBox={STARS_VIEW_BOX}>\n {Array.from({ length: 5 }, (_, index) => {\n const state = index < filled ? 'on' : 'off'\n return star.href ? (\n <use key={index} href={star.href} x={index * STAR_STRIDE} width={STAR_SIZE} height={STAR_SIZE} data-slot=\"star\" data-state={state} />\n ) : (\n <g\n key={index}\n transform={index === 0 ? undefined : `translate(${index * STAR_STRIDE})`}\n data-slot=\"star\"\n data-state={state}\n dangerouslySetInnerHTML={{ __html: star.glyph.body }}\n />\n )\n })}\n </svg>\n </span>\n )\n}\n\n/** Text for assistive technology only. */\nexport function VisuallyHidden({ children }: { readonly children: ReactNode }) {\n return <span data-bl-visually-hidden=\"\">{children}</span>\n}\n"]}
|
|
@@ -4,6 +4,21 @@ import { type UiIconName } from '../icons.js';
|
|
|
4
4
|
import { type LinkPrefetch } from '../prefetch.js';
|
|
5
5
|
import { type SkinEntry } from '../skin.js';
|
|
6
6
|
import type { UiPhone } from '../types.js';
|
|
7
|
+
/** Data hooks and the skin class for an anchor's root. */
|
|
8
|
+
export type AnchorHooks = {
|
|
9
|
+
readonly className?: string | undefined;
|
|
10
|
+
} & Readonly<Record<`data-${string}`, string | undefined>>;
|
|
11
|
+
/**
|
|
12
|
+
* The one anchor every ui-kit link renders (internal; not exported from the subpath): `next/link` with the prefetch
|
|
13
|
+
* role for internal links, a plain `<a target="_blank" rel="noopener noreferrer">` for external ones.
|
|
14
|
+
*/
|
|
15
|
+
export declare function Anchor({ href, external, prefetch, hooks, children, }: {
|
|
16
|
+
href: string;
|
|
17
|
+
external?: boolean | undefined;
|
|
18
|
+
prefetch?: LinkPrefetch | undefined;
|
|
19
|
+
hooks: AnchorHooks;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
7
22
|
export type ButtonLinkSlot = 'root' | 'label' | 'icon';
|
|
8
23
|
export declare const BUTTON_VARIANTS: readonly ["primary", "secondary", "quiet"];
|
|
9
24
|
export type ButtonVariant = (typeof BUTTON_VARIANTS)[number];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/links.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/links.tsx"],"names":[],"mappings":"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"}
|
|
@@ -11,11 +11,15 @@ import { slot } from '../skin.js';
|
|
|
11
11
|
function isExternal(href) {
|
|
12
12
|
return /^https?:\/\//i.test(href);
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The one anchor every ui-kit link renders (internal; not exported from the subpath): `next/link` with the prefetch
|
|
16
|
+
* role for internal links, a plain `<a target="_blank" rel="noopener noreferrer">` for external ones.
|
|
17
|
+
*/
|
|
18
|
+
export function Anchor({ href, external, prefetch, hooks, children, }) {
|
|
15
19
|
if (external ?? isExternal(href)) {
|
|
16
20
|
return (_jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", ...hooks, children: children }));
|
|
17
21
|
}
|
|
18
|
-
return (_jsx(Link, { href: href, ...linkPrefetchProps(prefetch), ...hooks, children: children }));
|
|
22
|
+
return (_jsx(Link, { href: href, ...linkPrefetchProps(prefetch, href), ...hooks, children: children }));
|
|
19
23
|
}
|
|
20
24
|
export const BUTTON_VARIANTS = ['primary', 'secondary', 'quiet'];
|
|
21
25
|
/** A link styled as a button. A primary action is at least 44 px tall (structure.css). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/links.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AACH,OAAO,IAAI,MAAM,WAAW,CAAA;AAG5B,OAAO,EAAE,IAAI,EAAmB,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAqB,MAAM,gBAAgB,CAAA;AACrE,OAAO,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAA;AAGjD,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACnC,CAAC;AAKD,
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/links.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Link primitives: `ButtonLink`, `TextLink` and `PhoneLink`. Server components; every link is a real `<a href>`.\n * External links open in a new tab with `rel=\"noopener noreferrer\"`. `PhoneLink` requires a typed placement, which the\n * shared instrumentation reads to send one `phone_link_click` per tap; nothing here emits events itself.\n */\nimport Link from 'next/link'\nimport type { ReactNode } from 'react'\nimport type { PhoneCallPlacement } from '../../analytics.js'\nimport { Icon, type UiIconName } from '../icons.js'\nimport { linkPrefetchProps, type LinkPrefetch } from '../prefetch.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport type { UiPhone } from '../types.js'\n\nfunction isExternal(href: string) {\n return /^https?:\\/\\//i.test(href)\n}\n\n/** Data hooks and the skin class for an anchor's root. */\nexport type AnchorHooks = { readonly className?: string | undefined } & Readonly<Record<`data-${string}`, string | undefined>>\n\n/**\n * The one anchor every ui-kit link renders (internal; not exported from the subpath): `next/link` with the prefetch\n * role for internal links, a plain `<a target=\"_blank\" rel=\"noopener noreferrer\">` for external ones.\n */\nexport function Anchor({\n href,\n external,\n prefetch,\n hooks,\n children,\n}: {\n href: string\n external?: boolean | undefined\n prefetch?: LinkPrefetch | undefined\n hooks: AnchorHooks\n children: ReactNode\n}) {\n if (external ?? isExternal(href)) {\n return (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" {...hooks}>\n {children}\n </a>\n )\n }\n return (\n <Link href={href} {...linkPrefetchProps(prefetch, href)} {...hooks}>\n {children}\n </Link>\n )\n}\n\nexport type ButtonLinkSlot = 'root' | 'label' | 'icon'\nexport const BUTTON_VARIANTS = ['primary', 'secondary', 'quiet'] as const\nexport type ButtonVariant = (typeof BUTTON_VARIANTS)[number]\nexport type ButtonLinkSkin = SkinEntry<ButtonLinkSlot, ButtonVariant, { size?: 'regular' | 'large' }>\n\nexport interface ButtonLinkProps extends ButtonLinkSkin {\n readonly href: string\n readonly children: ReactNode\n /** An icon after the label (`arrow`) or before it (`phone`). */\n readonly icon?: UiIconName\n readonly iconPosition?: 'start' | 'end'\n /** Force external handling; by default `http(s)://` links are external. */\n readonly external?: boolean\n /**\n * Prefetch by link role (`LINK_PREFETCH_POLICY`): `auto` (the default, Next's prefetch in view) for a main action,\n * `intent` for an in-content card link, `false` for footer, area, nearby, map and finder links.\n */\n readonly prefetch?: LinkPrefetch\n}\n\n/** A link styled as a button. A primary action is at least 44 px tall (structure.css). */\nexport function ButtonLink({ href, children, icon, iconPosition = 'end', external, prefetch, variant = 'primary', layout, classes }: ButtonLinkProps) {\n const iconNode = icon ? <span {...slot(classes, 'icon')}><Icon name={icon} /></span> : null\n return (\n <Anchor\n href={href}\n external={external}\n prefetch={prefetch}\n hooks={{ 'data-bl': 'button', 'data-variant': variant, 'data-size': layout?.size ?? 'regular', className: classes?.root }}\n >\n {iconPosition === 'start' ? iconNode : null}\n <span {...slot(classes, 'label')}>{children}</span>\n {iconPosition === 'end' ? iconNode : null}\n </Anchor>\n )\n}\n\nexport type TextLinkSlot = 'root'\nexport type TextLinkSkin = SkinEntry<TextLinkSlot, 'inline' | 'standalone'>\n\nexport interface TextLinkProps extends TextLinkSkin {\n readonly href: string\n readonly children: ReactNode\n readonly external?: boolean\n /**\n * Prefetch by link role (`LINK_PREFETCH_POLICY`): `auto` (the default, Next's prefetch in view) for a main action,\n * `intent` for an in-content card link, `false` for footer, area, nearby, map and finder links.\n */\n readonly prefetch?: LinkPrefetch\n}\n\n/** An inline or standalone text link. */\nexport function TextLink({ href, children, external, prefetch, variant = 'inline', classes }: TextLinkProps) {\n return (\n <Anchor href={href} external={external} prefetch={prefetch} hooks={{ 'data-bl': 'text-link', 'data-variant': variant, className: classes?.root }}>\n {children}\n </Anchor>\n )\n}\n\nexport type PhoneLinkSlot = 'root' | 'icon' | 'label' | 'number'\nexport type PhoneLinkSkin = SkinEntry<PhoneLinkSlot, 'text' | 'button'>\n\nexport interface PhoneLinkProps extends PhoneLinkSkin {\n readonly phone: UiPhone\n /** Where the link sits, for `phone_link_click`. Required: a section sets its own. */\n readonly placement: PhoneCallPlacement\n /** Optional words before the number, for example \"Call\". The accessible name is always the visible text. */\n readonly label?: string\n /** The phone icon on the left (header and hero). */\n readonly showIcon?: boolean\n}\n\n/**\n * A `tel:` link. Its accessible name is its visible text, which always includes the number (WCAG 2.5.3). Use it for\n * every call link: a literal `tel:` anywhere else fails lint (K1) and C10 checks the href against the evidence file.\n */\nexport function PhoneLink({ phone, placement, label, showIcon = false, variant = 'text', classes }: PhoneLinkProps) {\n return (\n <a href={phone.telHref} data-bl=\"phone-link\" data-variant={variant} data-phone-location={placement} className={classes?.root}>\n {showIcon ? (\n <span {...slot(classes, 'icon')}>\n <Icon name=\"phone\" />\n </span>\n ) : null}\n {label ? (\n <>\n <span {...slot(classes, 'label')}>{label}</span>{' '}\n </>\n ) : null}\n <span {...slot(classes, 'number')}>{phone.display}</span>\n </a>\n )\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { LinkPrefetch } from '../prefetch.js';
|
|
2
|
+
import type { RepeatedSlotOf } from '../repeated-slots.js';
|
|
3
|
+
import { type SkinEntry } from '../skin.js';
|
|
4
|
+
import type { UiLink } from '../types.js';
|
|
5
|
+
/** One checklist entry: the fact, and optionally where to check it. */
|
|
6
|
+
export type TickItem = string | {
|
|
7
|
+
readonly text: string;
|
|
8
|
+
readonly link?: UiLink;
|
|
9
|
+
};
|
|
10
|
+
export type TickListSlot = 'root' | RepeatedSlotOf<'tickList'>;
|
|
11
|
+
export type TickListRepeatedSlot = RepeatedSlotOf<'tickList'>;
|
|
12
|
+
export interface TickListLayout {
|
|
13
|
+
/** One column (the default) or two, from the phone breakpoint up. */
|
|
14
|
+
readonly columns?: 1 | 2;
|
|
15
|
+
/**
|
|
16
|
+
* The tick: `icon` (the default) is the sprite's check; `rule` ships no svg, only an empty decorative element the
|
|
17
|
+
* stylesheet draws as a short rule (`data-tick="rule"` on the list), about 120 bytes less a fact.
|
|
18
|
+
*/
|
|
19
|
+
readonly tick?: 'icon' | 'rule';
|
|
20
|
+
}
|
|
21
|
+
export type TickListSkin = SkinEntry<TickListSlot, never, TickListLayout, TickListRepeatedSlot>;
|
|
22
|
+
export interface TickListProps extends TickListSkin {
|
|
23
|
+
readonly items: readonly TickItem[];
|
|
24
|
+
}
|
|
25
|
+
export declare function TickList({ items, layout, classes }: TickListProps): import("react/jsx-runtime").JSX.Element | null;
|
|
26
|
+
/** The `data-bl-links` roles W2 reads: links in these lists never prefetch. */
|
|
27
|
+
export declare const LINK_LIST_KINDS: readonly ["area", "nearby", "map", "finder", "other-services"];
|
|
28
|
+
export type LinkListKind = (typeof LINK_LIST_KINDS)[number];
|
|
29
|
+
export type LinkListSlot = 'root';
|
|
30
|
+
export interface LinkListLayout {
|
|
31
|
+
/** Columns at the widest width (default 3); phones show one, then two. */
|
|
32
|
+
readonly columns?: 1 | 2 | 3 | 4;
|
|
33
|
+
}
|
|
34
|
+
export type LinkListSkin = SkinEntry<LinkListSlot, never, LinkListLayout>;
|
|
35
|
+
/**
|
|
36
|
+
* One entry: a link, or (3.15.0) a name with no `href`, rendered as plain text in the same list (`<li>Putney</li>`, no
|
|
37
|
+
* anchor), for an area whose page is still noindex while it waits for its return wave.
|
|
38
|
+
*/
|
|
39
|
+
export type LinkListEntry = UiLink | {
|
|
40
|
+
readonly label: string;
|
|
41
|
+
readonly href?: undefined;
|
|
42
|
+
};
|
|
43
|
+
export interface LinkListProps extends LinkListSkin {
|
|
44
|
+
readonly links: readonly LinkListEntry[];
|
|
45
|
+
/** What the list holds, rendered as `data-bl-links` for W2. Leave it out for a list of other destinations. */
|
|
46
|
+
readonly kind?: LinkListKind;
|
|
47
|
+
/** Off by default; `intent` only for a short list of in-content destinations. */
|
|
48
|
+
readonly prefetch?: Exclude<LinkPrefetch, 'auto'>;
|
|
49
|
+
}
|
|
50
|
+
export declare function LinkList({ links, kind, prefetch, layout, classes }: LinkListProps): import("react/jsx-runtime").JSX.Element | null;
|
|
51
|
+
//# sourceMappingURL=lists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lists.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/lists.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGzC,uEAAuE;AACvE,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAA;AAC9D,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,UAAU,CAAC,CAAA;AAC7D,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACxB;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAChC;AACD,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,oBAAoB,CAAC,CAAA;AAE/F,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;CACpC;AAID,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,aAAa,kDAkCjE;AAED,+EAA+E;AAC/E,eAAO,MAAM,eAAe,gEAAiE,CAAA;AAC7F,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3D,MAAM,MAAM,YAAY,GAAG,MAAM,CAAA;AACjC,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;CACjC;AACD,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,EAAE,KAAK,EAAE,cAAc,CAAC,CAAA;AAEzE;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,CAAA;AAE1F,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IACxC,8GAA8G;IAC9G,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;CAClD;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,aAAa,kDAiBzF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `TickList` and `LinkList` (3.14.0). Server components; both are a real `<ul>`.
|
|
4
|
+
*
|
|
5
|
+
* `TickList`: verified facts or the scope of a service, each after a decorative tick (the check icon, or a ruled mark
|
|
6
|
+
* with `layout.tick: 'rule'`). One or two columns; the hero's trust checklist uses two (Romie, Prestige and Sydney
|
|
7
|
+
* Waterproofing). An item may end with a link to where the fact can be checked, for example the licence register.
|
|
8
|
+
*
|
|
9
|
+
* `LinkList`: a ruled list of destinations (AA's `RuledLinkList`): service areas, nearby suburbs, other services. Lean
|
|
10
|
+
* by design (cost item 1f): each entry is a plain `<li><a>` with no class, hook or icon, so a 120-suburb hub stays near
|
|
11
|
+
* 120 bytes a link; a skin draws rules and arrows from `src/site/skin.css`. Its links never prefetch (area and nearby
|
|
12
|
+
* lists are `false` in `LINK_PREFETCH_POLICY`), and `kind` marks the list for W2 (`data-bl-links`).
|
|
13
|
+
*/
|
|
14
|
+
import { Icon } from '../icons.js';
|
|
15
|
+
import { repeatedSlot } from '../skin.js';
|
|
16
|
+
import { Anchor } from './links.js';
|
|
17
|
+
const itemText = (item) => (typeof item === 'string' ? item : item.text);
|
|
18
|
+
export function TickList({ items, layout, classes }) {
|
|
19
|
+
if (items.length === 0)
|
|
20
|
+
return null;
|
|
21
|
+
const rule = layout?.tick === 'rule';
|
|
22
|
+
return (_jsx("ul", { role: "list", "data-bl": "tick-list", "data-columns": String(layout?.columns ?? 1), "data-tick": rule ? 'rule' : undefined, className: classes?.root, children: items.map((item) => {
|
|
23
|
+
const link = typeof item === 'string' ? undefined : item.link;
|
|
24
|
+
return (_jsxs("li", { ...repeatedSlot('item'), children: [_jsx("span", { ...repeatedSlot('tick'), "aria-hidden": "true", children: rule ? null : _jsx(Icon, { name: "check" }) }), _jsxs("span", { ...repeatedSlot('text'), children: [itemText(item), link ? (_jsxs(_Fragment, { children: [' ', _jsx(Anchor, { href: link.href, prefetch: false, hooks: { 'data-slot': 'link' }, children: link.label })] })) : null] })] }, itemText(item)));
|
|
25
|
+
}) }));
|
|
26
|
+
}
|
|
27
|
+
/** The `data-bl-links` roles W2 reads: links in these lists never prefetch. */
|
|
28
|
+
export const LINK_LIST_KINDS = ['area', 'nearby', 'map', 'finder', 'other-services'];
|
|
29
|
+
export function LinkList({ links, kind, prefetch = false, layout, classes }) {
|
|
30
|
+
if (links.length === 0)
|
|
31
|
+
return null;
|
|
32
|
+
return (_jsx("ul", { role: "list", "data-bl": "link-list", "data-columns": String(layout?.columns ?? 3), "data-bl-links": kind, className: classes?.root, children: links.map((link) => link.href === undefined ? (_jsx("li", { children: link.label }, `text:${link.label}`)) : (_jsx("li", { children: _jsx(Anchor, { href: link.href, prefetch: prefetch, hooks: {}, children: link.label }) }, link.href))) }));
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=lists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lists.js","sourceRoot":"","sources":["../../../src/ui-kit/primitives/lists.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * `TickList` and `LinkList` (3.14.0). Server components; both are a real `<ul>`.\n *\n * `TickList`: verified facts or the scope of a service, each after a decorative tick (the check icon, or a ruled mark\n * with `layout.tick: 'rule'`). One or two columns; the hero's trust checklist uses two (Romie, Prestige and Sydney\n * Waterproofing). An item may end with a link to where the fact can be checked, for example the licence register.\n *\n * `LinkList`: a ruled list of destinations (AA's `RuledLinkList`): service areas, nearby suburbs, other services. Lean\n * by design (cost item 1f): each entry is a plain `<li><a>` with no class, hook or icon, so a 120-suburb hub stays near\n * 120 bytes a link; a skin draws rules and arrows from `src/site/skin.css`. Its links never prefetch (area and nearby\n * lists are `false` in `LINK_PREFETCH_POLICY`), and `kind` marks the list for W2 (`data-bl-links`).\n */\nimport { Icon } from '../icons.js'\nimport type { LinkPrefetch } from '../prefetch.js'\nimport type { RepeatedSlotOf } from '../repeated-slots.js'\nimport { repeatedSlot, type SkinEntry } from '../skin.js'\nimport type { UiLink } from '../types.js'\nimport { Anchor } from './links.js'\n\n/** One checklist entry: the fact, and optionally where to check it. */\nexport type TickItem = string | { readonly text: string; readonly link?: UiLink }\n\nexport type TickListSlot = 'root' | RepeatedSlotOf<'tickList'>\nexport type TickListRepeatedSlot = RepeatedSlotOf<'tickList'>\nexport interface TickListLayout {\n /** One column (the default) or two, from the phone breakpoint up. */\n readonly columns?: 1 | 2\n /**\n * The tick: `icon` (the default) is the sprite's check; `rule` ships no svg, only an empty decorative element the\n * stylesheet draws as a short rule (`data-tick=\"rule\"` on the list), about 120 bytes less a fact.\n */\n readonly tick?: 'icon' | 'rule'\n}\nexport type TickListSkin = SkinEntry<TickListSlot, never, TickListLayout, TickListRepeatedSlot>\n\nexport interface TickListProps extends TickListSkin {\n readonly items: readonly TickItem[]\n}\n\nconst itemText = (item: TickItem) => (typeof item === 'string' ? item : item.text)\n\nexport function TickList({ items, layout, classes }: TickListProps) {\n if (items.length === 0) return null\n const rule = layout?.tick === 'rule'\n return (\n <ul\n role=\"list\"\n data-bl=\"tick-list\"\n data-columns={String(layout?.columns ?? 1)}\n data-tick={rule ? 'rule' : undefined}\n className={classes?.root}\n >\n {items.map((item) => {\n const link = typeof item === 'string' ? undefined : item.link\n return (\n <li key={itemText(item)} {...repeatedSlot('item')}>\n <span {...repeatedSlot('tick')} aria-hidden=\"true\">\n {rule ? null : <Icon name=\"check\" />}\n </span>\n <span {...repeatedSlot('text')}>\n {itemText(item)}\n {link ? (\n <>\n {' '}\n <Anchor href={link.href} prefetch={false} hooks={{ 'data-slot': 'link' }}>\n {link.label}\n </Anchor>\n </>\n ) : null}\n </span>\n </li>\n )\n })}\n </ul>\n )\n}\n\n/** The `data-bl-links` roles W2 reads: links in these lists never prefetch. */\nexport const LINK_LIST_KINDS = ['area', 'nearby', 'map', 'finder', 'other-services'] as const\nexport type LinkListKind = (typeof LINK_LIST_KINDS)[number]\n\nexport type LinkListSlot = 'root'\nexport interface LinkListLayout {\n /** Columns at the widest width (default 3); phones show one, then two. */\n readonly columns?: 1 | 2 | 3 | 4\n}\nexport type LinkListSkin = SkinEntry<LinkListSlot, never, LinkListLayout>\n\n/**\n * One entry: a link, or (3.15.0) a name with no `href`, rendered as plain text in the same list (`<li>Putney</li>`, no\n * anchor), for an area whose page is still noindex while it waits for its return wave.\n */\nexport type LinkListEntry = UiLink | { readonly label: string; readonly href?: undefined }\n\nexport interface LinkListProps extends LinkListSkin {\n readonly links: readonly LinkListEntry[]\n /** What the list holds, rendered as `data-bl-links` for W2. Leave it out for a list of other destinations. */\n readonly kind?: LinkListKind\n /** Off by default; `intent` only for a short list of in-content destinations. */\n readonly prefetch?: Exclude<LinkPrefetch, 'auto'>\n}\n\nexport function LinkList({ links, kind, prefetch = false, layout, classes }: LinkListProps) {\n if (links.length === 0) return null\n return (\n <ul role=\"list\" data-bl=\"link-list\" data-columns={String(layout?.columns ?? 3)} data-bl-links={kind} className={classes?.root}>\n {links.map((link) =>\n link.href === undefined ? (\n <li key={`text:${link.label}`}>{link.label}</li>\n ) : (\n <li key={link.href}>\n <Anchor href={link.href} prefetch={prefetch} hooks={{}}>\n {link.label}\n </Anchor>\n </li>\n ),\n )}\n </ul>\n )\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type BrandlabMediaEntry, type BrandlabMediaRatio } from '@brandlab-digital/site-core/media';
|
|
3
|
+
import { type SkinEntry } from '../skin.js';
|
|
4
|
+
/** What a frame needs from a `media.ts` entry; a whole `BrandlabMediaEntry` fits. */
|
|
5
|
+
export type UiMedia = Pick<BrandlabMediaEntry, 'src' | 'width' | 'height' | 'alt' | 'provenance'> & Partial<Pick<BrandlabMediaEntry, 'decorative' | 'focalPoint'>>;
|
|
6
|
+
export type MediaFrameSlot = 'root' | 'img' | 'caption' | 'label';
|
|
7
|
+
export type MediaFrameSkin = SkinEntry<MediaFrameSlot>;
|
|
8
|
+
/** The locked visible label on an AI image (F13; truth wording, not site copy). */
|
|
9
|
+
export declare const ILLUSTRATION_LABEL = "Illustration";
|
|
10
|
+
/** Exactly one sizing: `sizes` with a `vw` part for a fluid image, or `displayWidth` for a fixed-size one. */
|
|
11
|
+
export type MediaFrameSizing = {
|
|
12
|
+
readonly sizes: string;
|
|
13
|
+
readonly displayWidth?: never;
|
|
14
|
+
} | {
|
|
15
|
+
readonly displayWidth: number;
|
|
16
|
+
readonly sizes?: never;
|
|
17
|
+
};
|
|
18
|
+
export type MediaFrameProps = MediaFrameSkin & MediaFrameSizing & {
|
|
19
|
+
readonly media: UiMedia;
|
|
20
|
+
/** Crop to an allowed ratio; by default the frame keeps the image's own shape. */
|
|
21
|
+
readonly ratio?: BrandlabMediaRatio;
|
|
22
|
+
/** "{what}, {suburb}, {month year}", only when the photo really shows that job. */
|
|
23
|
+
readonly caption?: ReactNode;
|
|
24
|
+
/** The page's largest image: preloaded, high fetch priority, never lazy. */
|
|
25
|
+
readonly priority?: boolean;
|
|
26
|
+
};
|
|
27
|
+
export declare function MediaFrame(props: MediaFrameProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
//# sourceMappingURL=media-frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-frame.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/primitives/media-frame.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAyB,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAC3H,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAEjD,qFAAqF;AACrF,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,YAAY,CAAC,GAC/F,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,YAAY,CAAC,CAAC,CAAA;AAEhE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,CAAA;AACjE,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC,cAAc,CAAC,CAAA;AAEtD,mFAAmF;AACnF,eAAO,MAAM,kBAAkB,iBAAiB,CAAA;AAEhD,8GAA8G;AAC9G,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAA;AAE7D,MAAM,MAAM,eAAe,GAAG,cAAc,GAC1C,gBAAgB,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,CAAA;IACnC,mFAAmF;IACnF,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAC5B,CAAA;AAUH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAqDhD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `MediaFrame` (3.14.0, F13): one image from the site's media manifest in a frame of an allowed ratio. Server
|
|
4
|
+
* component over `next/image`, and the library's one image path: `Media` and the hero render through it, so the
|
|
5
|
+
* "Illustration" label and the sizing rule below live here only. It is provenance-aware: the root carries
|
|
6
|
+
* `data-provenance`, and an AI image shows the locked visible label "Illustration" inside the `<figcaption>`, so the
|
|
7
|
+
* figure's accessible caption names it an illustration too. A caption ("{what}, {suburb}, {month year}") or the label
|
|
8
|
+
* makes the root a `<figure>`; otherwise it is a `<div>`.
|
|
9
|
+
*
|
|
10
|
+
* Sizing (cost item 1g) is one of two kinds, and the type takes exactly one:
|
|
11
|
+
* - **fluid** (`sizes`, which must have a `vw` part, for example `(min-width: 1024px) 50vw, 100vw`): Next keeps only the
|
|
12
|
+
* widths the layout can use.
|
|
13
|
+
* - **fixed** (`displayWidth`, the CSS width in pixels): no `sizes` at all, so Next emits a 1x and a 2x candidate only.
|
|
14
|
+
* A `sizes` without `vw` (for example `sizes="148px"`) makes Next list all 16 widths, which was 28–30% of some pages'
|
|
15
|
+
* HTML; it is refused here.
|
|
16
|
+
*
|
|
17
|
+
* `priority` is for the page's largest image (the hero): preloaded and fetched with high priority, never lazy. Every
|
|
18
|
+
* other image loads lazily.
|
|
19
|
+
*/
|
|
20
|
+
import Image from 'next/image';
|
|
21
|
+
import { BRANDLAB_MEDIA_RATIOS } from '@brandlab-digital/site-core/media';
|
|
22
|
+
import { slot } from '../skin.js';
|
|
23
|
+
/** The locked visible label on an AI image (F13; truth wording, not site copy). */
|
|
24
|
+
export const ILLUSTRATION_LABEL = 'Illustration';
|
|
25
|
+
/** Next's own test for a `vw` part in `sizes` (shared/lib/get-img-props). */
|
|
26
|
+
const VIEWPORT_WIDTH = /(^|\s)(1?\d?\d)vw/;
|
|
27
|
+
function ratioOf(ratio) {
|
|
28
|
+
const [width, height] = ratio.split(':').map(Number);
|
|
29
|
+
return height / width;
|
|
30
|
+
}
|
|
31
|
+
export function MediaFrame(props) {
|
|
32
|
+
const { media, ratio, caption, priority = false, classes } = props;
|
|
33
|
+
if (ratio !== undefined && !BRANDLAB_MEDIA_RATIOS.includes(ratio)) {
|
|
34
|
+
throw new Error(`MediaFrame ${media.src}: ratio "${ratio}" is not one of ${BRANDLAB_MEDIA_RATIOS.join(', ')}.`);
|
|
35
|
+
}
|
|
36
|
+
let width = media.width;
|
|
37
|
+
let height = media.height;
|
|
38
|
+
let sizes;
|
|
39
|
+
if (props.sizes !== undefined) {
|
|
40
|
+
if (!VIEWPORT_WIDTH.test(props.sizes)) {
|
|
41
|
+
throw new Error(`MediaFrame ${media.src}: sizes "${props.sizes}" has no vw part, so Next would list every width. Give a fluid image a vw size, or a fixed-size image its displayWidth instead.`);
|
|
42
|
+
}
|
|
43
|
+
sizes = props.sizes;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
if (!Number.isInteger(props.displayWidth) || props.displayWidth <= 0) {
|
|
47
|
+
throw new Error(`MediaFrame ${media.src}: displayWidth must be the image's CSS width in whole pixels.`);
|
|
48
|
+
}
|
|
49
|
+
width = props.displayWidth;
|
|
50
|
+
height = Math.round(props.displayWidth * (ratio ? ratioOf(ratio) : media.height / media.width));
|
|
51
|
+
}
|
|
52
|
+
const illustration = media.provenance === 'illustrative-ai';
|
|
53
|
+
const hasCaption = caption !== undefined && caption !== null && caption !== '';
|
|
54
|
+
const Root = illustration || hasCaption ? 'figure' : 'div';
|
|
55
|
+
const focal = media.focalPoint ? { objectPosition: `${media.focalPoint.x}% ${media.focalPoint.y}%` } : undefined;
|
|
56
|
+
return (_jsxs(Root, { "data-bl": "media", "data-ratio": ratio, "data-fit": sizes ? 'fluid' : 'fixed', "data-provenance": media.provenance, className: classes?.root, children: [_jsx(Image, { src: media.src, alt: media.decorative ? '' : media.alt, width: width, height: height, sizes: sizes, style: focal, ...(priority ? { preload: true, fetchPriority: 'high' } : { loading: 'lazy' }), ...slot(classes, 'img') }), illustration || hasCaption ? (_jsxs("figcaption", { ...slot(classes, 'caption'), children: [illustration ? _jsx("span", { ...slot(classes, 'label'), children: ILLUSTRATION_LABEL }) : null, illustration && hasCaption ? ' ' : null, hasCaption ? caption : null] })) : null] }));
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=media-frame.js.map
|