@wildo-ai/saas-website 1.1.7 → 1.1.9
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/dist/esm/astro/assert-website-pages-have-sections.d.ts +28 -0
- package/dist/esm/astro/assert-website-pages-have-sections.d.ts.map +1 -0
- package/dist/esm/astro/assert-website-pages-have-sections.js +38 -0
- package/dist/esm/astro/assert-website-pages-have-sections.js.map +1 -0
- package/dist/esm/astro/blog-post-bridge.d.ts.map +1 -1
- package/dist/esm/astro/blog-post-bridge.js.map +1 -1
- package/dist/esm/astro/blog-post-head.renderer.d.ts.map +1 -1
- package/dist/esm/astro/bridge-runtime.d.ts.map +1 -1
- package/dist/esm/astro/bridge-runtime.js.map +1 -1
- package/dist/esm/astro/collect-expected-label-keys.d.ts.map +1 -1
- package/dist/esm/astro/headers-renderer.d.ts.map +1 -1
- package/dist/esm/astro/i18n-routing.helper.d.ts.map +1 -1
- package/dist/esm/astro/label-pack-loader.d.ts +6 -0
- package/dist/esm/astro/label-pack-loader.d.ts.map +1 -1
- package/dist/esm/astro/label-pack-loader.js +10 -0
- package/dist/esm/astro/label-pack-loader.js.map +1 -1
- package/dist/esm/astro/llms-txt-server.d.ts.map +1 -1
- package/dist/esm/astro/pick-labels-for-page.d.ts.map +1 -1
- package/dist/esm/astro/robots-renderer.d.ts.map +1 -1
- package/dist/esm/astro/robots-renderer.js.map +1 -1
- package/dist/esm/astro/sitemap-coverage.d.ts.map +1 -1
- package/dist/esm/astro/structured-data.renderer.d.ts.map +1 -1
- package/dist/esm/astro/website-page-head.renderer.d.ts.map +1 -1
- package/dist/esm/astro/website-page-head.renderer.js.map +1 -1
- package/dist/esm/astro/website-page-runtime.helper.d.ts.map +1 -1
- package/dist/esm/astro/website-site-context.d.ts.map +1 -1
- package/dist/esm/astro/website-site-context.js.map +1 -1
- package/dist/esm/astro-island.d.ts.map +1 -1
- package/dist/esm/astro.d.ts +1 -0
- package/dist/esm/astro.d.ts.map +1 -1
- package/dist/esm/astro.js +1 -0
- package/dist/esm/astro.js.map +1 -1
- package/dist/esm/companion-exports.d.ts.map +1 -1
- package/dist/esm/companion-exports.js.map +1 -1
- package/dist/esm/components/low-level/WebsiteInternalButton.d.ts.map +1 -1
- package/dist/esm/components/low-level/WebsiteInternalLink.d.ts.map +1 -1
- package/dist/esm/config/define-website-config.d.ts.map +1 -1
- package/dist/esm/config/define-website-config.js.map +1 -1
- package/dist/esm/config/index.d.ts.map +1 -1
- package/dist/esm/config/load-website-config.d.ts.map +1 -1
- package/dist/esm/config/load-website-config.js.map +1 -1
- package/dist/esm/config/load-website-pricing-catalog.d.ts.map +1 -1
- package/dist/esm/config/load-website-pricing-catalog.js.map +1 -1
- package/dist/esm/config/load-website-site-context.d.ts.map +1 -1
- package/dist/esm/config/load-website-site-context.js.map +1 -1
- package/dist/esm/config/wildo-website-config.schemas.d.ts.map +1 -1
- package/dist/esm/config-loader.d.ts.map +1 -1
- package/dist/esm/config-loader.js.map +1 -1
- package/dist/esm/core/anonymous-session/InboundContactForm.d.ts.map +1 -1
- package/dist/esm/core/anonymous-session/InboundContactForm.js.map +1 -1
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts.map +1 -1
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js.map +1 -1
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts.map +1 -1
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.js.map +1 -1
- package/dist/esm/core/anonymous-session/website-submission-challenge.d.ts.map +1 -1
- package/dist/esm/core/anonymous-session/website-submission-challenge.js.map +1 -1
- package/dist/esm/core/consent/WebsiteConsentBanner.d.ts.map +1 -1
- package/dist/esm/core/consent/WebsiteConsentBanner.js.map +1 -1
- package/dist/esm/core/consent/WebsiteConsentContext.d.ts.map +1 -1
- package/dist/esm/core/consent/WebsiteConsentGate.d.ts.map +1 -1
- package/dist/esm/core/consent/useWebsiteConsent.d.ts.map +1 -1
- package/dist/esm/core/consent/website-consent-storage.d.ts.map +1 -1
- package/dist/esm/core/contexts/WebsitePageContext.d.ts.map +1 -1
- package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts.map +1 -1
- package/dist/esm/core/contexts/WebsiteRuntimeContext.js.map +1 -1
- package/dist/esm/core/contexts/WebsiteSectionContext.d.ts.map +1 -1
- package/dist/esm/core/contexts/useWebsitePage.d.ts.map +1 -1
- package/dist/esm/core/contexts/useWebsiteRuntime.d.ts.map +1 -1
- package/dist/esm/core/contexts/useWebsiteRuntime.js.map +1 -1
- package/dist/esm/core/contexts/useWebsiteSection.d.ts.map +1 -1
- package/dist/esm/core/external-providers/WebsiteProviderComponent.d.ts.map +1 -1
- package/dist/esm/core/external-providers/WebsiteProviderComponent.js.map +1 -1
- package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts.map +1 -1
- package/dist/esm/core/external-providers/provider-component-registry.website.d.ts.map +1 -1
- package/dist/esm/core/external-providers/provider-component-registry.website.js.map +1 -1
- package/dist/esm/core/external-providers/useWebsiteProviderComponent.d.ts.map +1 -1
- package/dist/esm/core/external-providers/useWebsiteProviderComponent.js.map +1 -1
- package/dist/esm/core/external-providers/useWebsiteProviderScripts.d.ts.map +1 -1
- package/dist/esm/core/external-providers/useWebsiteProviderScripts.js.map +1 -1
- package/dist/esm/core/external-providers/website-provider-sdk-activations.d.ts.map +1 -1
- package/dist/esm/core/external-providers/website-provider-sdk-activations.js.map +1 -1
- package/dist/esm/core/factories/define-website-page-manifest.d.ts.map +1 -1
- package/dist/esm/core/factories/define-website-section.d.ts +2 -0
- package/dist/esm/core/factories/define-website-section.d.ts.map +1 -1
- package/dist/esm/core/factories/define-website-section.js +2 -0
- package/dist/esm/core/factories/define-website-section.js.map +1 -1
- package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts.map +1 -1
- package/dist/esm/core/hooks/useWebsiteLabel.d.ts.map +1 -1
- package/dist/esm/core/layouts/WebsitePageLayout.d.ts.map +1 -1
- package/dist/esm/core/layouts/WebsitePageLayout.js.map +1 -1
- package/dist/esm/core/layouts/WebsitePageSections.d.ts +43 -0
- package/dist/esm/core/layouts/WebsitePageSections.d.ts.map +1 -0
- package/dist/esm/core/layouts/WebsitePageSections.js +13 -0
- package/dist/esm/core/layouts/WebsitePageSections.js.map +1 -0
- package/dist/esm/core/layouts/WebsiteSection.d.ts.map +1 -1
- package/dist/esm/core/routing/internal-routing.utils.d.ts.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mdx/BlogPost.d.ts.map +1 -1
- package/dist/esm/mdx/blog-post-collection.config.d.ts.map +1 -1
- package/dist/esm/mdx/blog-post-frontmatter-source.d.ts.map +1 -1
- package/dist/esm/mdx/index.d.ts.map +1 -1
- package/dist/esm/mdx.d.ts.map +1 -1
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js.map +1 -1
- package/dist/esm/schemas/label-keys/website-consent-label-keys.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/label-keys/website-provider-component-label-keys.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/label-keys/website-provider-component-label-keys.schemas.js.map +1 -1
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts +2 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js +12 -3
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js.map +1 -1
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts +3 -3
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js.map +1 -1
- package/dist/esm/schemas/refs/page-ref.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/refs/section-ref.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/sections/website-section-category.shared.d.ts.map +1 -1
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts +9 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js +11 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js.map +1 -1
- package/dist/esm/schemas/structured-data/pricing-offer-structured-data.shared.d.ts.map +1 -1
- package/dist/esm/schemas/structured-data/pricing-offer-structured-data.shared.js.map +1 -1
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts.map +1 -1
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js.map +1 -1
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts.map +1 -1
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js.map +1 -1
- package/dist/esm/schemas/validators/label-pack.validator.d.ts.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/astro/__tests__/assert-website-pages-have-sections.test.ts +75 -0
- package/src/astro/assert-website-pages-have-sections.ts +41 -0
- package/src/astro/label-pack-loader.ts +10 -0
- package/src/astro.ts +1 -0
- package/src/core/__tests__/WebsitePageSections.test.tsx +57 -0
- package/src/core/factories/define-website-section.ts +4 -0
- package/src/core/layouts/WebsitePageSections.tsx +68 -0
- package/src/index.ts +1 -0
- package/src/schemas/__tests__/page-manifest.test.ts +4 -7
- package/src/schemas/manifests/website-page-manifest.shared.schemas.ts +12 -3
- package/src/schemas/sections/website-section-definition.shared.schemas.ts +11 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend-provider-registry.website.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"frontend-provider-registry.website.d.ts","sourceRoot":"","sources":["../../../../../src/core/external-providers/frontend-provider-registry.website.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,8CAA8C,CAAC;AAExG,YAAY,EACV,6BAA6B,EAC7B,0BAA0B,EAC1B,+BAA+B,EAC/B,+BAA+B,GAChC,MAAM,8CAA8C,CAAC;AAEtD,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,8CAA8C,CAAC;AAEpG,MAAM,WAAW,0CAA0C;IACzD,yEAAyE;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAC1C;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,+BAA+B,CAAC;IACnD,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,mCAAmC,KAAK,IAAI,CAAC;CACnF;AAED;;GAEG;AACH,wBAAgB,qCAAqC,CACnD,KAAK,CAAC,EAAE,0CAA0C,GACjD,+BAA+B,CAMjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-component-registry.website.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"provider-component-registry.website.d.ts","sourceRoot":"","sources":["../../../../../src/core/external-providers/provider-component-registry.website.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAW,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAIL,KAAK,2BAA2B,EAChC,KAAK,mCAAmC,EACxC,KAAK,yBAAyB,EAC/B,MAAM,8CAA8C,CAAC;AAEtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAEnF,OAAO,EAEL,KAAK,+BAA+B,EACpC,KAAK,+BAA+B,EACrC,MAAM,sCAAsC,CAAC;AAE9C,sEAAsE;AACtE,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;AAEhE,gGAAgG;AAChG,MAAM,MAAM,gCAAgC,GAAG,yBAAyB,CAAC,4BAA4B,CAAC,CAAC;AAEvG,MAAM,WAAW,2CAA2C;IAC1D,kFAAkF;IAClF,QAAQ,CAAC,gBAAgB,EAAE,+BAA+B,GAAG,SAAS,CAAC;IACvE,mFAAmF;IACnF,QAAQ,CAAC,wBAAwB,CAAC,EAAE,QAAQ,CAAC,mCAAmC,CAAC,CAAC;IAClF;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC3E;AAWD,uFAAuF;AACvF,wBAAgB,sCAAsC,CACpD,KAAK,EAAE,2CAA2C,GACjD,gCAAgC,CAOlC;AAED,4GAA4G;AAC5G,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,wBAAwB,EAAE,+BAA+B,CAAC;IACnE,QAAQ,CAAC,yBAAyB,EAAE,gCAAgC,CAAC;CACtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,QAAQ,CAAC,iBAAiB,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC/D,QAAQ,CAAC,uBAAuB,EAAE,+BAA+B,GAAG,SAAS,CAAC;IAC9E,QAAQ,CAAC,wBAAwB,EAAE,QAAQ,CAAC,mCAAmC,CAAC,GAAG,SAAS,CAAC;CAC9F,GAAG,yBAAyB,CAe5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-component-registry.website.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"provider-component-registry.website.js","sourceRoot":"","sources":["../../../../../src/core/external-providers/provider-component-registry.website.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,OAAO,EAAsB,MAAM,OAAO,CAAC;AACpD,OAAO,EACL,qCAAqC,EACrC,+BAA+B,EAC/B,yCAAyC,GAI1C,MAAM,8CAA8C,CAAC;AAItD,OAAO,EACL,qCAAqC,GAGtC,MAAM,sCAAsC,CAAC;AAqB9C,SAAS,+BAA+B,CAAC,UAAuC;IAC9E,0GAA0G;IAC1G,wGAAwG;IACxG,iGAAiG;IACjG,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO;IAC5C,sCAAsC;IACtC,OAAO,CAAC,IAAI,CAAC,8BAA8B,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;AACvF,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,sCAAsC,CACpD,KAAkD;IAElD,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,+BAA+B,CAAC;IAC3E,MAAM,aAAa,GAAG,qCAAqC,CAAC,KAAK,CAAC,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;QAC1G,kBAAkB,EAAE,yCAAyC,CAAC,KAAK,CAAC,wBAAwB,CAAC;QAC7F,YAAY;KACb,CAAC,CAAC;IACH,OAAO,+BAA+B,CAA+B,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC;AACxG,CAAC;AAQD;;;;;;;;GAQG;AACH,MAAM,UAAU,4BAA4B,CAAC,KAI5C;IACC,MAAM,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,GAAG,KAAK,CAAC;IACvF,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,wBAAwB,GAAG,qCAAqC,CAAC;YACrE,OAAO,EAAE,iBAAiB;YAC1B,OAAO,EAAE,uBAAuB;SACjC,CAAC,CAAC;QACH,OAAO;YACL,wBAAwB;YACxB,yBAAyB,EAAE,sCAAsC,CAAC;gBAChE,gBAAgB,EAAE,wBAAwB;gBAC1C,GAAG,CAAC,wBAAwB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,wBAAwB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChF,CAAC;SACH,CAAC;IACJ,CAAC,EAAE,CAAC,iBAAiB,EAAE,uBAAuB,EAAE,wBAAwB,CAAC,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["/**\n * The website's provider-component registry (#1703): the SAME registry the application builds, from\n * the SAME `components` declaration, over the website's live provider modules.\n *\n * A provider declares its components once, on its frontend module. Before this, the website facet\n * type accepted `components` and nothing on the website read it, so a contact form could not host an\n * address lookup (#561) and a marketing page could not host any provider component at all. The\n * registry is `createProviderComponentRegistry` from `@wildo-ai/external-connectors-public/website`\n * — keyed `capability:providerRef`, consent-gated, script-before-component and browser-only — and\n * this file only feeds it the website's two inputs:\n *\n * - the HYDRATED website provider registry (both channels joined, so a provider not live for this\n * website service contributes no component);\n * - the loaders the site's facet library contributes for components an engine provider module\n * declares but cannot import (the module lives in a renderer-free package), handed in through the\n * page bridge's `providerComponentLoaders` rather than through module-level state, because the\n * bridge is the website's one construction site and can carry it explicitly.\n *\n * Nothing is loaded here. A component loads when a `WebsiteProviderComponent` slot asks for it, from\n * an effect — never during the Astro server render.\n */\n\nimport { useMemo, type ComponentType } from 'react';\nimport {\n collectProviderComponentRegistrations,\n createProviderComponentRegistry,\n indexProviderComponentLoaderContributions,\n type ProviderComponentDiagnostic,\n type ProviderComponentLoaderContribution,\n type ProviderComponentRegistry,\n} from '@wildo-ai/external-connectors-public/website';\n\nimport type { FrontendProvidersBlock } from '@wildo-ai/saas-models/public-runtime';\n\nimport {\n createFrontendWebsiteProviderRegistry,\n type FrontendWebsiteProviderRegistry,\n type GeneratedWebsiteProviderModules,\n} from './frontend-provider-registry.website';\n\n/** A component type the website's registry hands back once loaded. */\nexport type WebsiteProviderComponentType = ComponentType<never>;\n\n/** The website's provider-component registry: the shared registry, holding React components. */\nexport type WebsiteProviderComponentRegistry = ProviderComponentRegistry<WebsiteProviderComponentType>;\n\nexport interface CreateWebsiteProviderComponentRegistryInput {\n /** The hydrated website provider registry; absent on a site with no providers. */\n readonly providerRegistry: FrontendWebsiteProviderRegistry | undefined;\n /** Loaders the site's facet library contributes for engine-declared components. */\n readonly providerComponentLoaders?: Iterable<ProviderComponentLoaderContribution>;\n /**\n * Where a registration or load problem is reported. Defaults to `console.warn`: the website runtime\n * has no logger service, and a provider component that cannot be offered is a developer-facing fact\n * that must not be silent.\n */\n readonly onDiagnostic?: (diagnostic: ProviderComponentDiagnostic) => void;\n}\n\nfunction warnProviderComponentDiagnostic(diagnostic: ProviderComponentDiagnostic): void {\n // Reported in the BROWSER only. The registry is built during the server render or prerender too, once per\n // page, and a declaration nothing can load would otherwise fill the build log with one warning per page\n // for a fact the first page already stated. The browser is where somebody can see and act on it.\n if (typeof document === 'undefined') return;\n // eslint-disable-next-line no-console\n console.warn(`[wildo-provider-component] ${diagnostic.kind}: ${diagnostic.message}`);\n}\n\n/** Builds the website's provider-component registry from its live provider modules. */\nexport function createWebsiteProviderComponentRegistry(\n input: CreateWebsiteProviderComponentRegistryInput,\n): WebsiteProviderComponentRegistry {\n const onDiagnostic = input.onDiagnostic ?? warnProviderComponentDiagnostic;\n const registrations = collectProviderComponentRegistrations(input.providerRegistry?.modules.values() ?? [], {\n contributedLoaders: indexProviderComponentLoaderContributions(input.providerComponentLoaders),\n onDiagnostic,\n });\n return createProviderComponentRegistry<WebsiteProviderComponentType>({ registrations, onDiagnostic });\n}\n\n/** What a page bridge builds once per island: the hydrated provider registry and its component registry. */\nexport interface WebsiteProviderRegistries {\n readonly frontendProviderRegistry: FrontendWebsiteProviderRegistry;\n readonly providerComponentRegistry: WebsiteProviderComponentRegistry;\n}\n\n/**\n * Builds both registries for a page bridge, MEMOISED on their inputs.\n *\n * Memoised because the component registry caches each loaded component: a registry rebuilt on every\n * render would forget what it loaded, hand every slot a new registry identity, and make each slot's\n * load effect run again — a download loop. The inputs are an island prop (`frontendProviders`, fixed\n * for the island's life) and two module-load-time bridge dependencies, so in practice this builds\n * once per island.\n */\nexport function useWebsiteProviderRegistries(input: {\n readonly frontendProviders: FrontendProvidersBlock | undefined;\n readonly frontendProviderModules: GeneratedWebsiteProviderModules | undefined;\n readonly providerComponentLoaders: Iterable<ProviderComponentLoaderContribution> | undefined;\n}): WebsiteProviderRegistries {\n const { frontendProviders, frontendProviderModules, providerComponentLoaders } = input;\n return useMemo(() => {\n const frontendProviderRegistry = createFrontendWebsiteProviderRegistry({\n entries: frontendProviders,\n modules: frontendProviderModules,\n });\n return {\n frontendProviderRegistry,\n providerComponentRegistry: createWebsiteProviderComponentRegistry({\n providerRegistry: frontendProviderRegistry,\n ...(providerComponentLoaders !== undefined ? { providerComponentLoaders } : {}),\n }),\n };\n }, [frontendProviders, frontendProviderModules, providerComponentLoaders]);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebsiteProviderComponent.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"useWebsiteProviderComponent.d.ts","sourceRoot":"","sources":["../../../../../src/core/external-providers/useWebsiteProviderComponent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAI/E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AAE1F,oGAAoG;AACpG,MAAM,MAAM,6BAA6B,GAAG,0BAA0B,CAAC,4BAA4B,CAAC,CAAC;AAErG;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,UAAU,EAAE,kBAAkB,GAAG,aAAa,CAAC,MAAM,CAAC,CAGxG;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,kBAAkB,EAC9B,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,6BAA6B,CAuB/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebsiteProviderComponent.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"useWebsiteProviderComponent.js","sourceRoot":"","sources":["../../../../../src/core/external-providers/useWebsiteProviderComponent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EACL,8BAA8B,EAC9B,0BAA0B,GAE3B,MAAM,8CAA8C,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAMlE;;;;GAIG;AACH,MAAM,UAAU,kCAAkC,CAAC,UAA8B;IAC/E,MAAM,EAAE,yBAAyB,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAC1D,OAAO,yBAAyB,EAAE,aAAa,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;AACpE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CACzC,UAA8B,EAC9B,WAA+B;IAE/B,MAAM,EAAE,yBAAyB,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAC1D,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgC,GAAG,EAAE,CAAC,8BAA8B,EAAgC,CAAC,CAAC;IAExI,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,QAAQ,CAAC,8BAA8B,EAAgC,CAAC,CAAC;YACzE,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,0BAA0B,CAAC;YAChC,QAAQ,EAAE,yBAAyB;YACnC,UAAU;YACV,WAAW;YACX,sBAAsB,EAAE,OAAO,CAAC,eAAe;YAC/C,OAAO,EAAE,QAAQ;SAClB,CAAC,CAAC;QACH,sGAAsG;QACtG,uDAAuD;IACzD,CAAC,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,yBAAyB,EAAE,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IAEzF,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/**\n * Reading provider-contributed components on the website (#1703) — the website's counterpart of the\n * application's `useProviderComponentChoices` / `useProviderComponent`, over the same registry and\n * the same status vocabulary (`ProviderComponentStatus`).\n *\n * Two differences from the application, both about WHO answers:\n *\n * - the consent grant is the VISITOR's decision from `WebsiteConsentContext`, not a signed-in\n * person's stored preference;\n * - nothing starts before that decision has been read from storage (`isResolved`). The server render\n * and the first client render read no storage, and asking the registry then would report a\n * consent-required state to a visitor who already agreed, flashing the refusal on every page.\n *\n * Neither hook picks a provider: when several providers offer a component for one capability,\n * choosing is the page's job.\n */\n\nimport { useEffect, useState } from 'react';\nimport {\n idleProviderComponentLoadState,\n startProviderComponentLoad,\n type ProviderComponentLoadState,\n} from '@wildo-ai/external-connectors-public/website';\nimport type { ProviderCapability } from '@wildo-ai/saas-models/public-runtime';\n\nimport { useWebsiteConsent } from '../consent/useWebsiteConsent';\nimport { useWebsiteRuntime } from '../contexts/useWebsiteRuntime';\nimport type { WebsiteProviderComponentType } from './provider-component-registry.website';\n\n/** What `useWebsiteProviderComponent` returns: the shared load state, holding a React component. */\nexport type WebsiteProviderComponentState = ProviderComponentLoadState<WebsiteProviderComponentType>;\n\n/**\n * The providers that are BOTH live for this website service and carry a component for this\n * capability, in the order the service declared them. Synchronous, so a page can render its choice\n * on the first frame.\n */\nexport function useWebsiteProviderComponentChoices(capability: ProviderCapability): ReadonlyArray<string> {\n const { providerComponentRegistry } = useWebsiteRuntime();\n return providerComponentRegistry?.listProviders(capability) ?? [];\n}\n\n/**\n * Loads one provider's component for a capability, once the visitor's consent decision is known.\n *\n * Pass `undefined` for the ref while nothing is chosen. The load runs in an effect, so it never runs\n * during the Astro server render; `CONSENT_REQUIRED` means nothing of the provider was downloaded,\n * and granting the missing purposes through the consent panel loads it without a re-mount.\n */\nexport function useWebsiteProviderComponent(\n capability: ProviderCapability,\n providerRef: string | undefined,\n): WebsiteProviderComponentState {\n const { providerComponentRegistry } = useWebsiteRuntime();\n const consent = useWebsiteConsent();\n const grantedKey = [...consent.grantedPurposes].sort().join(',');\n const [state, setState] = useState<WebsiteProviderComponentState>(() => idleProviderComponentLoadState<WebsiteProviderComponentType>());\n\n useEffect(() => {\n if (!consent.isResolved) {\n setState(idleProviderComponentLoadState<WebsiteProviderComponentType>());\n return undefined;\n }\n return startProviderComponentLoad({\n registry: providerComponentRegistry,\n capability,\n providerRef,\n grantedConsentPurposes: consent.grantedPurposes,\n onState: setState,\n });\n // `grantedPurposes` is read through `grantedKey`: keyed by the granted SET, not the array's identity.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [capability, providerRef, providerComponentRegistry, consent.isResolved, grantedKey]);\n\n return state;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebsiteProviderScripts.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"useWebsiteProviderScripts.d.ts","sourceRoot":"","sources":["../../../../../src/core/external-providers/useWebsiteProviderScripts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAUH,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAUvF;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,+BAA+B,GAAG,SAAS;AACrD;;;;GAIG;AACH,iBAAiB,CAAC,EAAE,gCAAgC,GACnD,IAAI,CAcN;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,+BAA+B,GAAG,SAAS;AACrD;;;;;GAKG;AACH,sBAAsB,EAAE,SAAS,cAAc,EAAE,GAChD,aAAa,CAAC,4BAA4B,CAAC,CAM7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebsiteProviderScripts.js","sourceRoot":"","sources":["../../../../src/core/external-providers/useWebsiteProviderScripts.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The website's executable-surface hooks: load what the live providers declared.\n *\n * Two mechanisms, one per kind of vendor. `useWebsiteProviderScripts` adds the\n * `<script>` tags a provider declared — the case a dynamic `import()` cannot\n * serve, and the dominant one on a marketing site. `useWebsiteProviderSdks`\n * activates the npm SDK of any provider that ships one, which reaches this\n * bundle through the CODE channel.\n *\n * Both are effect-only, and that is not incidental: this is an Astro site, so\n * page modules execute in Node at build time. Injecting into a document that\n * does not exist would throw, and starting a vendor SDK there would run a live\n * analytics client inside a build.\n *\n * Both come from `@wildo-ai/external-connectors-public/website`. The script\n * injector lives there rather than here so the SaaS application, the technical\n * doc and this site run ONE copy of it: a second copy of a DOM mutation\n * eventually disagrees about idempotence, which is how a vendor tag gets loaded\n * twice. It first shipped here alone, and that is how the application came to\n * declare its Drive Picker's Google API script and never inject it.\n *\n * ## Client-side injection, and the alternative that was rejected\n *\n * This is an Astro static site, so the \"obvious\" home for a third-party tag is\n * the built HTML `<head>`. That was rejected for now: the set of live providers\n * is per SERVICE and per ENVIRONMENT, resolved from the materialized artifact,\n * while the built HTML is one artifact shared across deploys of the same build.\n * Baking the tags in would make the build environment-specific — the same class\n * of coupling the DATA channel exists to avoid. Injecting from the client keeps\n * one build correct everywhere, at the cost of the tag arriving after hydration.\n * Revisit if a provider ever needs to run before first paint.\n */\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n activateFrontendProviderSdks,\n collectProviderScriptsWithoutComponents,\n consentPurposesRequiredByProvider,\n createFrontendProviderSdkActivationLane,\n injectProviderScripts,\n} from '@wildo-ai/external-connectors-public/website';\nimport { AppFrontendType, type ConsentPurpose } from '@wildo-ai/saas-models/public-runtime';\nimport type { FrontendWebsiteProviderRegistry } from './frontend-provider-registry.website';\nimport type { WebsiteProviderComponentRegistry } from './provider-component-registry.website';\nimport type { WebsiteProviderSdkActivation } from './website-provider-sdk-activations';\n\n/**\n * A stable key for a granted-purpose set, so an effect re-runs when the SET changes and not when a new\n * array with the same members is handed in.\n */\nfunction grantedKey(grantedConsentPurposes: readonly ConsentPurpose[]): string {\n return [...grantedConsentPurposes].sort().join(',');\n}\n\n/**\n * Injects the `<script>` tags of the live providers that rest on NO consent purpose and render no component.\n *\n * No consent input, deliberately (#1704): an executed `<script>` cannot be stopped, so a provider that rests on a\n * purpose must ship as a stoppable SDK (started on the grant and stopped on withdrawal by\n * {@link useWebsiteProviderSdks}); a consent-based module declaring `scripts` is refused at projection and skipped by\n * the collector. No grant could change what this injects.\n */\nexport function useWebsiteProviderScripts(\n registry: FrontendWebsiteProviderRegistry | undefined,\n /**\n * The website's provider-component registry (#1703). A provider with a registered component loads its\n * scripts WITH that component, when a page first shows it — so an address lookup's vendor loader is\n * not downloaded on every page of the site, only on the one with the form. This hook injects the rest.\n */\n componentRegistry?: WebsiteProviderComponentRegistry,\n): void {\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n const withComponents = [...(componentRegistry?.providersWithComponents() ?? [])].map((providerRef) => ({ providerRef }));\n const scripts = collectProviderScriptsWithoutComponents(registry?.modules.values() ?? [], withComponents);\n if (scripts.length === 0) return;\n\n injectProviderScripts(scripts, document);\n // Deliberately no teardown. A vendor tag installs a global and often starts\n // work immediately; removing the element undoes neither, so a cleanup that\n // removed it would only make the next mount inject a SECOND copy of an\n // already-running script. Idempotence by `src` is the real guard.\n }, [registry, componentRegistry]);\n}\n\n/**\n * Loads and starts the npm SDK of every live provider that declares one.\n *\n * Unlike a script tag, an SDK activation IS undone on unmount where the vendor\n * offers a teardown — an analytics client that cannot be stopped cannot honour\n * a consent withdrawal, and accumulates one instance per view transition.\n */\nexport function useWebsiteProviderSdks(\n registry: FrontendWebsiteProviderRegistry | undefined,\n /**\n * The purposes the visitor granted (#534). Providers are activated in TWO groups on purpose: those that\n * rest on no purpose (error monitoring, captcha) are started once and never restarted by a consent\n * change, while the consent-based ones start when their purpose is granted and are DEACTIVATED when it\n * is withdrawn — which is the only way a withdrawal stops a running analytics client.\n */\n grantedConsentPurposes: readonly ConsentPurpose[],\n): ReadonlyArray<WebsiteProviderSdkActivation> {\n const consentFree = useProviderSdkGroup(registry, false, []);\n const consentBased = useProviderSdkGroup(registry, true, grantedConsentPurposes);\n // The providers RUNNING on this page, both groups, published by the page layout (#1735): a form reads the captcha\n // vendor's handle from here. Emptied the moment a group stops, so nothing holds a handle past a withdrawal.\n return useMemo(() => [...consentFree, ...consentBased], [consentFree, consentBased]);\n}\n\nfunction useProviderSdkGroup(\n registry: FrontendWebsiteProviderRegistry | undefined,\n consentBased: boolean,\n grantedConsentPurposes: readonly ConsentPurpose[],\n): ReadonlyArray<WebsiteProviderSdkActivation> {\n const [running, setRunning] = useState<ReadonlyArray<WebsiteProviderSdkActivation>>([]);\n // Keyed by the grants this group's providers actually rest on, so changing an unrelated purpose does\n // not stop and restart a running analytics client.\n const relevant = registry === undefined\n ? []\n : [...registry.modules.values()]\n .filter((module) => (consentPurposesRequiredByProvider(module).length > 0) === consentBased)\n .flatMap((module) => consentPurposesRequiredByProvider(module))\n .filter((purpose) => grantedConsentPurposes.includes(purpose));\n const key = grantedKey(relevant);\n // One lane per group for the page's lifetime: a start waits for the previous stop.\n const lane = useRef(createFrontendProviderSdkActivationLane());\n useEffect(() => {\n if (registry === undefined) return;\n const modules = [...registry.modules.values()].filter(\n (module) => (consentPurposesRequiredByProvider(module).length > 0) === consentBased,\n );\n if (modules.length === 0) return;\n\n // Through the group's lane, so a start never overlaps the previous stop of the same page-global vendor (#1704): a\n // visitor who grants, withdraws and grants again while the bundle downloads must not have the first run's stop\n // switch off the second run's client. The stop also covers an unmount mid-download.\n const stop = lane.current.start(\n () => activateFrontendProviderSdks({\n surface: AppFrontendType.STATIC_WEBSITE,\n modules,\n grantedConsentPurposes,\n onDiagnostic: (diagnostic) => {\n // The website runtime has no logger service, and a provider that cannot\n // start is a developer-facing fact that must not be silent.\n // eslint-disable-next-line no-console\n console.warn(`[wildo-provider-sdk] ${diagnostic.kind}: ${diagnostic.message}`);\n },\n }),\n (result) => {\n setRunning(modules.flatMap((module) => {\n const activation = result.activations.get(module.metadata.ref);\n return activation === undefined\n ? []\n : [{ providerRef: module.metadata.ref, providerCapabilities: [...module.providerCapabilities], activation }];\n }));\n },\n );\n return () => {\n setRunning([]);\n stop();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed by the granted SET, see grantedKey.\n }, [registry, consentBased, key]);\n return running;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"useWebsiteProviderScripts.js","sourceRoot":"","sources":["../../../../../src/core/external-providers/useWebsiteProviderScripts.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The website's executable-surface hooks: load what the live providers declared.\n *\n * Two mechanisms, one per kind of vendor. `useWebsiteProviderScripts` adds the\n * `<script>` tags a provider declared — the case a dynamic `import()` cannot\n * serve, and the dominant one on a marketing site. `useWebsiteProviderSdks`\n * activates the npm SDK of any provider that ships one, which reaches this\n * bundle through the CODE channel.\n *\n * Both are effect-only, and that is not incidental: this is an Astro site, so\n * page modules execute in Node at build time. Injecting into a document that\n * does not exist would throw, and starting a vendor SDK there would run a live\n * analytics client inside a build.\n *\n * Both come from `@wildo-ai/external-connectors-public/website`. The script\n * injector lives there rather than here so the SaaS application, the technical\n * doc and this site run ONE copy of it: a second copy of a DOM mutation\n * eventually disagrees about idempotence, which is how a vendor tag gets loaded\n * twice. It first shipped here alone, and that is how the application came to\n * declare its Drive Picker's Google API script and never inject it.\n *\n * ## Client-side injection, and the alternative that was rejected\n *\n * This is an Astro static site, so the \"obvious\" home for a third-party tag is\n * the built HTML `<head>`. That was rejected for now: the set of live providers\n * is per SERVICE and per ENVIRONMENT, resolved from the materialized artifact,\n * while the built HTML is one artifact shared across deploys of the same build.\n * Baking the tags in would make the build environment-specific — the same class\n * of coupling the DATA channel exists to avoid. Injecting from the client keeps\n * one build correct everywhere, at the cost of the tag arriving after hydration.\n * Revisit if a provider ever needs to run before first paint.\n */\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n activateFrontendProviderSdks,\n collectProviderScriptsWithoutComponents,\n consentPurposesRequiredByProvider,\n createFrontendProviderSdkActivationLane,\n injectProviderScripts,\n} from '@wildo-ai/external-connectors-public/website';\nimport { AppFrontendType, type ConsentPurpose } from '@wildo-ai/saas-models/public-runtime';\nimport type { FrontendWebsiteProviderRegistry } from './frontend-provider-registry.website';\nimport type { WebsiteProviderComponentRegistry } from './provider-component-registry.website';\nimport type { WebsiteProviderSdkActivation } from './website-provider-sdk-activations';\n\n/**\n * A stable key for a granted-purpose set, so an effect re-runs when the SET changes and not when a new\n * array with the same members is handed in.\n */\nfunction grantedKey(grantedConsentPurposes: readonly ConsentPurpose[]): string {\n return [...grantedConsentPurposes].sort().join(',');\n}\n\n/**\n * Injects the `<script>` tags of the live providers that rest on NO consent purpose and render no component.\n *\n * No consent input, deliberately (#1704): an executed `<script>` cannot be stopped, so a provider that rests on a\n * purpose must ship as a stoppable SDK (started on the grant and stopped on withdrawal by\n * {@link useWebsiteProviderSdks}); a consent-based module declaring `scripts` is refused at projection and skipped by\n * the collector. No grant could change what this injects.\n */\nexport function useWebsiteProviderScripts(\n registry: FrontendWebsiteProviderRegistry | undefined,\n /**\n * The website's provider-component registry (#1703). A provider with a registered component loads its\n * scripts WITH that component, when a page first shows it — so an address lookup's vendor loader is\n * not downloaded on every page of the site, only on the one with the form. This hook injects the rest.\n */\n componentRegistry?: WebsiteProviderComponentRegistry,\n): void {\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n const withComponents = [...(componentRegistry?.providersWithComponents() ?? [])].map((providerRef) => ({ providerRef }));\n const scripts = collectProviderScriptsWithoutComponents(registry?.modules.values() ?? [], withComponents);\n if (scripts.length === 0) return;\n\n injectProviderScripts(scripts, document);\n // Deliberately no teardown. A vendor tag installs a global and often starts\n // work immediately; removing the element undoes neither, so a cleanup that\n // removed it would only make the next mount inject a SECOND copy of an\n // already-running script. Idempotence by `src` is the real guard.\n }, [registry, componentRegistry]);\n}\n\n/**\n * Loads and starts the npm SDK of every live provider that declares one.\n *\n * Unlike a script tag, an SDK activation IS undone on unmount where the vendor\n * offers a teardown — an analytics client that cannot be stopped cannot honour\n * a consent withdrawal, and accumulates one instance per view transition.\n */\nexport function useWebsiteProviderSdks(\n registry: FrontendWebsiteProviderRegistry | undefined,\n /**\n * The purposes the visitor granted (#534). Providers are activated in TWO groups on purpose: those that\n * rest on no purpose (error monitoring, captcha) are started once and never restarted by a consent\n * change, while the consent-based ones start when their purpose is granted and are DEACTIVATED when it\n * is withdrawn — which is the only way a withdrawal stops a running analytics client.\n */\n grantedConsentPurposes: readonly ConsentPurpose[],\n): ReadonlyArray<WebsiteProviderSdkActivation> {\n const consentFree = useProviderSdkGroup(registry, false, []);\n const consentBased = useProviderSdkGroup(registry, true, grantedConsentPurposes);\n // The providers RUNNING on this page, both groups, published by the page layout (#1735): a form reads the captcha\n // vendor's handle from here. Emptied the moment a group stops, so nothing holds a handle past a withdrawal.\n return useMemo(() => [...consentFree, ...consentBased], [consentFree, consentBased]);\n}\n\nfunction useProviderSdkGroup(\n registry: FrontendWebsiteProviderRegistry | undefined,\n consentBased: boolean,\n grantedConsentPurposes: readonly ConsentPurpose[],\n): ReadonlyArray<WebsiteProviderSdkActivation> {\n const [running, setRunning] = useState<ReadonlyArray<WebsiteProviderSdkActivation>>([]);\n // Keyed by the grants this group's providers actually rest on, so changing an unrelated purpose does\n // not stop and restart a running analytics client.\n const relevant = registry === undefined\n ? []\n : [...registry.modules.values()]\n .filter((module) => (consentPurposesRequiredByProvider(module).length > 0) === consentBased)\n .flatMap((module) => consentPurposesRequiredByProvider(module))\n .filter((purpose) => grantedConsentPurposes.includes(purpose));\n const key = grantedKey(relevant);\n // One lane per group for the page's lifetime: a start waits for the previous stop.\n const lane = useRef(createFrontendProviderSdkActivationLane());\n useEffect(() => {\n if (registry === undefined) return;\n const modules = [...registry.modules.values()].filter(\n (module) => (consentPurposesRequiredByProvider(module).length > 0) === consentBased,\n );\n if (modules.length === 0) return;\n\n // Through the group's lane, so a start never overlaps the previous stop of the same page-global vendor (#1704): a\n // visitor who grants, withdraws and grants again while the bundle downloads must not have the first run's stop\n // switch off the second run's client. The stop also covers an unmount mid-download.\n const stop = lane.current.start(\n () => activateFrontendProviderSdks({\n surface: AppFrontendType.STATIC_WEBSITE,\n modules,\n grantedConsentPurposes,\n onDiagnostic: (diagnostic) => {\n // The website runtime has no logger service, and a provider that cannot\n // start is a developer-facing fact that must not be silent.\n // eslint-disable-next-line no-console\n console.warn(`[wildo-provider-sdk] ${diagnostic.kind}: ${diagnostic.message}`);\n },\n }),\n (result) => {\n setRunning(modules.flatMap((module) => {\n const activation = result.activations.get(module.metadata.ref);\n return activation === undefined\n ? []\n : [{ providerRef: module.metadata.ref, providerCapabilities: [...module.providerCapabilities], activation }];\n }));\n },\n );\n return () => {\n setRunning([]);\n stop();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed by the granted SET, see grantedKey.\n }, [registry, consentBased, key]);\n return running;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"website-provider-sdk-activations.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"website-provider-sdk-activations.d.ts","sourceRoot":"","sources":["../../../../../src/core/external-providers/website-provider-sdk-activations.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAC;AAElG,6HAA6H;AAC7H,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,CAAC,UAAU,EAAE,6BAA6B,CAAC;CACpD;AAED,eAAO,MAAM,oCAAoC,kEAAiE,CAAC;AAEnH,sHAAsH;AACtH,wBAAgB,gCAAgC,IAAI,aAAa,CAAC,4BAA4B,CAAC,CAE9F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"website-provider-sdk-activations.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"website-provider-sdk-activations.js","sourceRoot":"","sources":["../../../../../src/core/external-providers/website-provider-sdk-activations.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAUlD,MAAM,CAAC,MAAM,oCAAoC,GAAG,aAAa,CAA8C,EAAE,CAAC,CAAC;AAEnH,sHAAsH;AACtH,MAAM,UAAU,gCAAgC;IAC9C,OAAO,UAAU,CAAC,oCAAoC,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["/**\n * The provider SDKs RUNNING on this website page (#1735), published by the page layout.\n *\n * A section reaches a running vendor through here rather than through a global — the contact form asks the consented\n * captcha vendor for a token this way. The list is emptied the moment a provider is stopped (a consent withdrawal, a\n * navigation), so a consumer that reads it at the moment it needs a handle never holds one past a withdrawal.\n */\nimport { createContext, useContext } from 'react';\nimport type { ProviderFrontendSdkActivation } from '@wildo-ai/external-connectors-public/website';\n\n/** One running provider: its ref, the capabilities it serves, and its activation (whose `handle` is the vendor's client). */\nexport interface WebsiteProviderSdkActivation {\n readonly providerRef: string;\n readonly providerCapabilities: ReadonlyArray<string>;\n readonly activation: ProviderFrontendSdkActivation;\n}\n\nexport const WebsiteProviderSdkActivationsContext = createContext<ReadonlyArray<WebsiteProviderSdkActivation>>([]);\n\n/** The provider SDKs running on this page, in declaration order. Empty outside a page layout and before any start. */\nexport function useWebsiteProviderSdkActivations(): ReadonlyArray<WebsiteProviderSdkActivation> {\n return useContext(WebsiteProviderSdkActivationsContext);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-website-page-manifest.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"define-website-page-manifest.d.ts","sourceRoot":"","sources":["../../../../../src/core/factories/define-website-page-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,4BAA4B,EAC7B,MAAM,8DAA8D,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAEhF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,8BAA8B,CAAC,MAAM;IACpD,GAAG,EAAE,cAAc,GAAG,MAAM,CAAC;IAC7B,SAAS,EAAE,oBAAoB,GAAG,MAAM,CAAC;IACzC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,WAAW,EAAE,SAAS,CAAC,iBAAiB,GAAG,MAAM,CAAC,EAAE,CAAC;IACrD,aAAa,EAAE,wBAAwB,CAAC;IACxC,SAAS,CAAC,EAAE,4BAA4B,CAAC;IACzC,GAAG,CAAC,EAAE,oBAAoB,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB,CAAC,MAAM,CAC9C,SAAQ,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC;IAClD,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACtE,KAAK,EAAE,8BAA8B,CAAC,MAAM,CAAC,GAC5C,wBAAwB,CAAC,MAAM,CAAC,CAmBlC;AACD,yEAAyE"}
|
|
@@ -24,6 +24,8 @@ export interface DefineWebsiteSectionInput<TProps> {
|
|
|
24
24
|
sectionRef: WebsiteSectionRef | string;
|
|
25
25
|
category: WebsiteSectionCategory;
|
|
26
26
|
expectedLabelKeys: readonly (WebsiteLabelKey | string)[];
|
|
27
|
+
/** The section's DOM id, so a link can target it (`<a href="#tiers">`). See `WebsiteSectionDefinition.anchorId`. */
|
|
28
|
+
anchorId?: string;
|
|
27
29
|
Component: ComponentType<TProps>;
|
|
28
30
|
/**
|
|
29
31
|
* See `WebsiteSectionDefinition.getStructuredData?` JSDoc for the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-website-section.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"define-website-section.d.ts","sourceRoot":"","sources":["../../../../../src/core/factories/define-website-section.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kEAAkE,CAAC;AACjH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wDAAwD,CAAC;AACrG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oDAAoD,CAAC;AAC1F,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,sEAAsE,CAAC;AAExH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,yBAAyB,CAAC,MAAM;IAC/C,UAAU,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACvC,QAAQ,EAAE,sBAAsB,CAAC;IACjC,iBAAiB,EAAE,SAAS,CAAC,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC;IACzD,oHAAoH;IACpH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACjC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,2BAA2B,CAAC;CACvD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,6BAA6B,CAAC,MAAM,CACnD,SAAQ,IAAI,CAAC,wBAAwB,EAAE,WAAW,GAAG,mBAAmB,CAAC;IACzE,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,2BAA2B,CAAC;CACvD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EACzC,KAAK,EAAE,yBAAyB,CAAC,MAAM,CAAC,GACvC,6BAA6B,CAAC,MAAM,CAAC,CAsBvC;AACD,mEAAmE"}
|
|
@@ -51,6 +51,7 @@ export function defineWebsiteSection(input) {
|
|
|
51
51
|
sectionRef: input.sectionRef,
|
|
52
52
|
category: input.category,
|
|
53
53
|
expectedLabelKeys: input.expectedLabelKeys,
|
|
54
|
+
anchorId: input.anchorId,
|
|
54
55
|
Component: input.Component,
|
|
55
56
|
getStructuredData: input.getStructuredData,
|
|
56
57
|
});
|
|
@@ -63,6 +64,7 @@ export function defineWebsiteSection(input) {
|
|
|
63
64
|
sectionRef: parsed.sectionRef,
|
|
64
65
|
category: parsed.category,
|
|
65
66
|
expectedLabelKeys: parsed.expectedLabelKeys,
|
|
67
|
+
...(parsed.anchorId !== undefined ? { anchorId: parsed.anchorId } : {}),
|
|
66
68
|
Component: input.Component,
|
|
67
69
|
...(input.getStructuredData ? { getStructuredData: input.getStructuredData } : {}),
|
|
68
70
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-website-section.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"define-website-section.js","sourceRoot":"","sources":["../../../../../src/core/factories/define-website-section.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,8BAA8B,EAAE,MAAM,kEAAkE,CAAC;AAyDlH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAwC;IAExC,MAAM,MAAM,GAAG,8BAA8B,CAAC,KAAK,CAAC;QAClD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;KAC3C,CAAC,CAAC;IACH;;;;OAIG;IACH,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnF,CAAC;AACJ,CAAC;AACD,mEAAmE","sourcesContent":["import type { ComponentType } from 'react';\n\nimport { WebsiteSectionDefinitionSchema } from '../../schemas/sections/website-section-definition.shared.schemas';\nimport type { WebsiteSectionDefinition } from '../../schemas/sections/website-section-definition.shared.schemas';\nimport type { WebsiteSectionCategory } from '../../schemas/sections/website-section-category.shared';\nimport type { WebsiteSectionRef } from '../../schemas/refs/section-ref.schemas';\nimport type { WebsiteLabelKey } from '../../schemas/label-keys/website-label-key.schemas';\nimport type { WebsiteStructuredDataReturn } from '../../schemas/structured-data/website-structured-data.shared.schemas';\n\n/**\n * @wildo_source:part:start saas.website.factories.define-section facet:layer:core facet:family:website\n *\n * Input shape consumed by `defineWebsiteSection<TProps>`. Mirrors\n * `WebsiteSectionDefinition` but keeps `Component` typed against the\n * caller-supplied generic so the precise prop shape survives end-to-end\n * (the consumer's `<HeroSection />` JSX can keep its strongly-typed\n * props after going through the factory).\n *\n * **String inputs vs. branded inputs**: `sectionRef` and\n * `expectedLabelKeys` accept raw strings as well as already-branded\n * values. The factory parses them through the underlying schemas, so\n * either path is safe — accepting strings directly removes the\n * ergonomic drag of forcing every section author to remember to call\n * `WebsiteSectionRefSchema.parse(...)` in their definition.\n */\nexport interface DefineWebsiteSectionInput<TProps> {\n sectionRef: WebsiteSectionRef | string;\n category: WebsiteSectionCategory;\n expectedLabelKeys: readonly (WebsiteLabelKey | string)[];\n /** The section's DOM id, so a link can target it (`<a href=\"#tiers\">`). See `WebsiteSectionDefinition.anchorId`. */\n anchorId?: string;\n Component: ComponentType<TProps>;\n /**\n * See `WebsiteSectionDefinition.getStructuredData?` JSDoc for the\n * full authoring contract. The factory passes the function through\n * unchanged; the framework invokes it at static-build time and\n * forwards the return value to `renderPageStructuredData()`.\n */\n getStructuredData?: () => WebsiteStructuredDataReturn;\n}\n\n/**\n * Return shape of `defineWebsiteSection<TProps>`. Identical to\n * `WebsiteSectionDefinition` except `Component` retains the\n * caller-supplied generic prop shape rather than the schema's\n * lowest-common-denominator `ComponentType<unknown>`.\n *\n * **Why this matters**: a consumer's `pageComponent` JSX composes\n * sections like `<HERO_SECTION.Component {...heroProps} />`. Without\n * preserving `TProps`, the spread would be untyped and a renamed prop\n * would silently miss the type system. With `TProps` preserved, the\n * call site fails to compile the moment the prop contract drifts.\n */\nexport interface TypedWebsiteSectionDefinition<TProps>\n extends Omit<WebsiteSectionDefinition, 'Component' | 'getStructuredData'> {\n Component: ComponentType<TProps>;\n getStructuredData?: () => WebsiteStructuredDataReturn;\n}\n\n/**\n * `defineWebsiteSection<TProps>` — factory that materializes a\n * `WebsiteSectionDefinition` from authored input.\n *\n * **Two responsibilities**, one entry point:\n * 1. Runtime validation — parses the input through\n * `WebsiteSectionDefinitionSchema` so brand checks, regex\n * validations, and array refinements run at module load time\n * (not at render time, not at build-output time).\n * 2. Type preservation — returns an object whose `Component` field\n * keeps the caller-supplied `TProps`, so JSX usage of the\n * returned section retains compile-time prop checking.\n *\n * **Why a factory instead of constructing the literal directly**:\n * - Consumers don't have to remember to parse refs / keys\n * themselves before assembling the literal.\n * - The schema parse provides a single audited validation chokepoint,\n * and the parsed `expectedLabelKeys` are what `wildo website audit`\n * checks every locale pack against, without re-entering the React graph.\n * - The factory is the documented authoring API the\n * `website_factory_authoring` skill targets — keeping the\n * authoring surface narrow lets the framework evolve the\n * internal schema (add fields, refinements) without churning\n * every section definition in every consumer app.\n *\n * @param input section authoring input (see `DefineWebsiteSectionInput`).\n * @returns a `TypedWebsiteSectionDefinition<TProps>` with `Component`\n * preserved at the precise prop type.\n *\n * @example\n * interface HeroProps {\n * headlineKey: WebsiteLabelKey;\n * subheadlineKey: WebsiteLabelKey;\n * }\n * function HeroSection({ headlineKey, subheadlineKey }: HeroProps) {\n * // …\n * }\n * export const HERO_SECTION = defineWebsiteSection<HeroProps>({\n * sectionRef: 'hero',\n * category: WebsiteSectionCategory.HERO,\n * expectedLabelKeys: [\n * 'website.landing.hero.headline',\n * 'website.landing.hero.subheadline',\n * ],\n * Component: HeroSection,\n * });\n */\nexport function defineWebsiteSection<TProps>(\n input: DefineWebsiteSectionInput<TProps>,\n): TypedWebsiteSectionDefinition<TProps> {\n const parsed = WebsiteSectionDefinitionSchema.parse({\n sectionRef: input.sectionRef,\n category: input.category,\n expectedLabelKeys: input.expectedLabelKeys,\n anchorId: input.anchorId,\n Component: input.Component,\n getStructuredData: input.getStructuredData,\n });\n /**\n * Re-attach `Component` and `getStructuredData` from the original\n * input so the precise generic types survive — `parsed.Component`\n * is `unknown` per the schema's `z.unknown()` contract.\n */\n return {\n sectionRef: parsed.sectionRef,\n category: parsed.category,\n expectedLabelKeys: parsed.expectedLabelKeys,\n ...(parsed.anchorId !== undefined ? { anchorId: parsed.anchorId } : {}),\n Component: input.Component,\n ...(input.getStructuredData ? { getStructuredData: input.getStructuredData } : {}),\n };\n}\n/** @wildo_source:part:end saas.website.factories.define-section */\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebsiteDesignTokens.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"useWebsiteDesignTokens.d.ts","sourceRoot":"","sources":["../../../../../src/core/hooks/useWebsiteDesignTokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kEAAkE,CAAC;AAE5G;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,IAAI,mBAAmB,CAE5D;AACD,0DAA0D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebsiteLabel.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"useWebsiteLabel.d.ts","sourceRoot":"","sources":["../../../../../src/core/hooks/useWebsiteLabel.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,oDAAoD,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA8BxD;AACD,yDAAyD;AAEzD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAajE;AACD,gEAAgE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebsitePageLayout.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"WebsitePageLayout.d.ts","sourceRoot":"","sources":["../../../../../src/core/layouts/WebsitePageLayout.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAcvD,OAAO,EAAgD,KAAK,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAG7H,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,qCAAqC,CAAC;AA6F7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;;OAOG;IACH,OAAO,EAAE,cAAc,GAAG,MAAM,CAAC;IACjC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACzC;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,SAAS,CAY1E;yBAZe,iBAAiB;;;AAiLjC,gEAAgE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebsitePageLayout.js","sourceRoot":"","sources":["../../../../src/core/layouts/WebsitePageLayout.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useMemo, type ReactNode } from 'react';\nimport { BUILTIN_PROVIDER_CAPABILITY } from '@wildo-ai/saas-models/public-runtime';\nimport { consentPurposesInUseByProviders } from '@wildo-ai/external-connectors-public/website';\n\nimport { WebsitePageContextProvider } from '../contexts/WebsitePageContext';\nimport {\n useWebsiteProviderScripts,\n useWebsiteProviderSdks,\n} from '../external-providers/useWebsiteProviderScripts';\nimport { WebsiteProviderSdkActivationsContext } from '../external-providers/website-provider-sdk-activations';\nimport type { WebsitePageContextValue } from '../contexts/WebsitePageContext';\nimport { useWebsiteRuntime } from '../contexts/useWebsiteRuntime';\nimport { websiteDesignTokenCssVar } from '../../schemas/design-tokens/website-design-tokens.shared.schemas';\nimport { useWebsiteLabelByKey } from '../hooks/useWebsiteLabel';\nimport { WebsiteConsentProvider, WebsiteConsentStatus, type WebsiteConsentRecorder } from '../consent/WebsiteConsentContext';\nimport { useWebsiteConsent } from '../consent/useWebsiteConsent';\nimport { WebsiteConsentBanner, WebsiteConsentSettingsButton } from '../consent/WebsiteConsentBanner';\nimport {\n WebsitePageRefSchema,\n type WebsitePageRef,\n} from '../../schemas/refs/page-ref.schemas';\n\n/**\n * Stable DOM id stamped on the `<main>` element so the framework's\n * skip-link `<a href=\"#main-content\">` can move keyboard focus past\n * the chrome on every page (Phase 6 audit fix M-α). Co-located here\n * (rather than exposed as a prop) because:\n * - The skip-link target is a framework concern — exposing it as a\n * consumer-tunable id would invite drift between the link's href\n * and the main element's id.\n * - Screen readers announce the heading inside `<main id=\"...\">` on\n * focus; a stable, framework-owned id keeps that affordance\n * deterministic across every page on every site.\n */\nconst MAIN_CONTENT_DOM_ID = 'main-content';\n\n/**\n * Inline style for the skip link's \"visually hidden by default,\n * visible on focus\" pattern. Inlined (NOT shipped as a CSS class)\n * because:\n * - The framework intentionally avoids shipping any CSS file the\n * consumer must opt in to — the only stylesheet emitted is the\n * `:root { --website-*: … }` design-token block, and the rest of\n * the styling surface lives in consumer code (see Phase 5\n * `renderWebsiteDesignTokensCss`). Inlining keeps the skip link\n * self-sufficient and side-effect-free.\n * - The \"skip-link\" pattern is a small, well-known a11y idiom; the\n * handful of style declarations here do not benefit from being\n * reorganized into a class with a custom-property hook.\n *\n * The \"focused\" variant uses BOTH `:focus` AND `:focus-visible`\n * pseudo-classes via a scoped `<style>` tag inside the layout output.\n * We cannot apply pseudo-class styles via a `style` attribute, but\n * emitting a tiny scoped block once at the layout root is safe (one\n * block per page render, ~120 bytes) and avoids importing a CSS-in-JS\n * runtime.\n *\n * **Why both selectors and not just `:focus-visible`** (Phase 6 fourth\n * audit fix M-Η): `:focus-visible` is the modern UA-heuristic-driven\n * selector that hides focus rings on mouse clicks, and it is the\n * RIGHT default for buttons / links. For a skip link though we WANT\n * the affordance to appear on EVERY focus event — the link is\n * invisible by default and a keyboard-only user (the only intended\n * audience) is the only one who can reach it. Older browsers that\n * predate `:focus-visible` (and Safari < 15.4 with the feature\n * disabled) would skip the rule entirely with a `:focus-visible`-only\n * declaration, leaving the keyboard user looking at an apparently\n * empty page when they pressed Tab. Pairing `:focus, :focus-visible`\n * is the documented WCAG 2.1 fallback pattern.\n */\nconst SKIP_LINK_HIDDEN_STYLE: React.CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '1px',\n height: '1px',\n padding: 0,\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n\n/**\n * Single scoped style block for the skip link's `:focus-visible`\n * affordance. Targets the `data-website-skip-link` attribute (NOT a\n * class) so consumer Tailwind / utility classes cannot accidentally\n * shadow it. Stays trivially small to keep payload under the\n * \"framework rendering\" implicit budget.\n */\nconst SKIP_LINK_FOCUS_CSS = `\n[data-website-skip-link]:focus,\n[data-website-skip-link]:focus-visible {\n position: fixed !important;\n top: 0.5rem !important;\n left: 0.5rem !important;\n width: auto !important;\n height: auto !important;\n padding: 0.75rem 1rem !important;\n margin: 0 !important;\n overflow: visible !important;\n clip: auto !important;\n white-space: normal !important;\n background: ${websiteDesignTokenCssVar('colors', 'background', '#fff')} !important;\n color: ${websiteDesignTokenCssVar('colors', 'foreground', '#000')} !important;\n border: 2px solid ${websiteDesignTokenCssVar('colors', 'primary', '#000')} !important;\n border-radius: ${websiteDesignTokenCssVar('radii', 'md', '0.375rem')} !important;\n z-index: 9999 !important;\n text-decoration: none !important;\n}\n`.trim();\n\n/**\n * @wildo_source:part:start saas.website.page-layout.component facet:layer:core facet:family:website\n *\n * `WebsitePageLayout` — the per-page structural primitive.\n *\n * **Three responsibilities** (each carrying its own semantic weight):\n *\n * 1. **Provides `WebsitePageContext`** — registers the active page\n * ref so child sections (`<WebsiteSection>`) and label hooks\n * (`useWebsiteLabel`) can derive label keys without re-typing\n * the page ref at every leaf.\n * 2. **Renders the site-wide chrome** — pulls\n * `headerComponent` and `footerComponent` from the runtime\n * navigation config and wraps the page's main content in the\n * site's standard header/main/footer scaffold. Per-page\n * overrides (`header={…}` / `footer={…}` props) take precedence\n * over the runtime defaults so individual pages can opt into a\n * custom chrome (eg. a campaign landing page running with\n * header-only minimal chrome).\n * 3. **Stamps DOM landmarks** — emits `data-website-page-ref` on\n * the layout root for analytics / SEO crawlers / overlay\n * tooling that needs to identify the active page from the DOM\n * without booting React. When the website facet hydrates\n * frontend-provider bootstraps, the same root also carries the\n * active public provider refs for analytics / browser-monitoring /\n * captcha so non-React tooling can detect the configured vendor\n * without reverse-engineering app code.\n *\n * 4. **Provides the visitor's consent state and enforces it** (#534) —\n * mounts `WebsiteConsentProvider`, starts a provider SDK or script only\n * once the purpose it rests on is granted (and stops the SDK when it is\n * withdrawn), and renders the consent panel when the site runs a\n * consent-based provider and the visitor has not decided. Here rather\n * than in each bridge because every page — including every blog post —\n * renders through this layout, so no page can be mounted without it.\n *\n * **Why semantic `<header>` / `<main>` / `<footer>` elements**:\n * marketing-site SEO scoring penalizes pages that ship a single\n * unstructured `<div>` tree. Using semantic landmarks costs nothing\n * and improves crawler accessibility AND screen-reader\n * navigability — both are first-class concerns for a public\n * marketing surface.\n *\n * **Why this lives in `core/`** (not `components/`): the layout is\n * structural framework machinery (it owns the page-context\n * provisioning + the navigation slot resolution), not a styled\n * primitive. Designers override `header` / `footer` via runtime\n * config or per-page props, NOT by replacing this component.\n */\nexport interface WebsitePageLayoutProps {\n /**\n * The active page's ref. Accepts either an already-branded\n * `WebsitePageRef` or a raw string — the layout parses through\n * `WebsitePageRefSchema` so a malformed ref fails loud at render.\n *\n * Typically sourced from the page's `WebsitePageManifest.ref`\n * (eg. `<WebsitePageLayout pageRef={LANDING_PAGE_MANIFEST.ref}>`).\n */\n pageRef: WebsitePageRef | string;\n /**\n * Per-page header override. When supplied, takes precedence over\n * `WebsiteRuntimeContext.designTokens` navigation config's\n * `headerComponent`. Pass `null` explicitly to suppress the header\n * entirely (campaign landing pages without site-wide nav).\n */\n header?: ReactNode | null;\n /**\n * Per-page footer override. Same semantics as `header`.\n */\n footer?: ReactNode | null;\n /**\n * Optional className applied to the root `<div data-website-page-ref=\"…\">`\n * wrapper. Use for page-level layout tweaks (eg. `min-h-screen` on\n * landing pages).\n */\n className?: string;\n /**\n * Optional className applied to the inner `<main>` element. Use for\n * vertical-rhythm overrides on long-scroll landing pages.\n */\n mainClassName?: string;\n /**\n * OPTIONAL anonymous-session client. When supplied, a visitor's consent decision is ALSO recorded\n * server-side against their session, which is what lets it follow them into the account they go on\n * to create (#1258). Pass the SAME instance the page's capture sections use, so one `uuidRef`\n * carries the decision, the lead and the draft note together.\n *\n * Absent keeps today's behaviour exactly: the decision lives in this browser and nowhere else.\n * The engine cannot construct the client here — it needs the application's own\n * `frontendServiceName` — which is why it arrives as a prop rather than off the runtime context.\n */\n consentRecorder?: WebsiteConsentRecorder;\n /**\n * The page's section composition. Typically a sequence of\n * `<WebsiteSection>` wrappers around concrete section components.\n */\n children: ReactNode;\n}\n\nexport function WebsitePageLayout(props: WebsitePageLayoutProps): ReactNode {\n const runtime = useWebsiteRuntime();\n // Derived from the LIVE providers, so the panel asks about exactly what this site processes.\n const purposesInUse = useMemo(\n () => consentPurposesInUseByProviders(runtime.frontendProviderRegistry?.modules.values()),\n [runtime.frontendProviderRegistry],\n );\n return (\n <WebsiteConsentProvider purposesInUse={purposesInUse} recorder={props.consentRecorder}>\n <WebsitePageLayoutContent {...props} />\n </WebsiteConsentProvider>\n );\n}\n\nfunction WebsitePageLayoutContent({\n pageRef,\n header,\n footer,\n className,\n mainClassName,\n children,\n}: WebsitePageLayoutProps): ReactNode {\n const runtime = useWebsiteRuntime();\n const consent = useWebsiteConsent();\n\n /**\n * Defensive parse: callers should pass a `WebsitePageManifest.ref`\n * (already branded), but accepting raw strings + parsing here means\n * a hand-typed call site can't smuggle a malformed ref into the\n * label-key derivation chain.\n */\n const safePageRef = useMemo<WebsitePageRef>(\n () => WebsitePageRefSchema.parse(pageRef),\n [pageRef],\n );\n\n const pageContextValue = useMemo<WebsitePageContextValue>(\n () => ({ pageRef: safePageRef }),\n [safePageRef],\n );\n\n /**\n * Header resolution rules:\n * - `header === null` => explicit suppression\n * - `header !== undefined` => per-page override (any ReactNode)\n * - `header === undefined` => fall back to the runtime navigation\n * config's `headerComponent`\n *\n * The fallback is the common path: every page renders the same\n * site-wide chrome. The override path is the escape hatch (campaign\n * landing pages with custom header layouts).\n */\n const resolvedHeader = useMemo<ReactNode>(() => {\n if (header === null) return null;\n if (header !== undefined) return header;\n const HeaderComponent = runtime.navigation.headerComponent;\n return <HeaderComponent />;\n }, [header, runtime.navigation.headerComponent]);\n\n const resolvedFooter = useMemo<ReactNode>(() => {\n if (footer === null) return null;\n if (footer !== undefined) return footer;\n const FooterComponent = runtime.navigation.footerComponent;\n return <FooterComponent />;\n }, [footer, runtime.navigation.footerComponent]);\n\n // Load whatever the live providers declared. Until this landed, the surface\n // resolved provider refs and stamped them into the attributes below and\n // stopped there — a provider could be declared, enabled and hydrated without\n // anything of it ever running.\n //\n // Consent-based providers start only once their purpose is granted (#534). Before the stored decision is\n // read, nothing is granted — the static HTML and the first render start nothing optional.\n useWebsiteProviderScripts(runtime.frontendProviderRegistry, runtime.providerComponentRegistry);\n // The running SDKs are published to the page (#1735): the contact form asks the consented captcha vendor for a token.\n const runningProviderSdks = useWebsiteProviderSdks(runtime.frontendProviderRegistry, consent.grantedPurposes);\n\n const providerRootAttributes = useMemo<Record<string, string>>(() => {\n const attrs: Record<string, string> = {};\n const productAnalyticsProviderRef = runtime.frontendProviderRegistry\n ?.findProviderByProviderCapability(\n BUILTIN_PROVIDER_CAPABILITY.FRONTEND_PRODUCT_ANALYTICS,\n )\n ?.metadata.ref;\n const errorMonitoringProviderRef = runtime.frontendProviderRegistry\n ?.findProviderByProviderCapability(\n BUILTIN_PROVIDER_CAPABILITY.FRONTEND_ERROR_MONITORING,\n )\n ?.metadata.ref;\n const captchaProviderRef = runtime.frontendProviderRegistry\n ?.findProviderByProviderCapability(\n BUILTIN_PROVIDER_CAPABILITY.FRONTEND_CAPTCHA,\n )\n ?.metadata.ref;\n\n if (productAnalyticsProviderRef) {\n attrs['data-website-product-analytics-provider-ref'] = productAnalyticsProviderRef;\n }\n if (errorMonitoringProviderRef) {\n attrs['data-website-error-monitoring-provider-ref'] = errorMonitoringProviderRef;\n }\n if (captchaProviderRef) {\n attrs['data-website-captcha-provider-ref'] = captchaProviderRef;\n }\n\n return attrs;\n }, [runtime.frontendProviderRegistry]);\n\n /**\n * Resolved skip-link label. Reads through the runtime label pack\n * via the standard `useWebsiteLabelByKey` hook so a missing\n * translation surfaces the same diagnostic shape as any other\n * missing chrome label. The framework guarantees the key reaches\n * the bridge (see `pickLabelsForPage`) and the consumer's\n * label-pack validator (see `composeEffectiveChromeLabelKeys` in\n * `label-pack-loader.ts`) ensures it is present in every locale\n * pack — there is therefore no silent-fallback path that would\n * ship an English skip link to a non-EN visitor.\n */\n const skipLinkLabel = useWebsiteLabelByKey(runtime.skipToMainContentLabelKey);\n\n return (\n <WebsitePageContextProvider value={pageContextValue}>\n <WebsiteProviderSdkActivationsContext.Provider value={runningProviderSdks}>\n <div\n data-website-page-ref={safePageRef as unknown as string}\n className={className}\n {...providerRootAttributes}\n >\n {/*\n * Skip link rendered as the FIRST focusable element on the\n * page so a keyboard / AT user can bypass the chrome on every\n * navigation (WCAG 2.1 §2.4.1 \"Bypass Blocks\", Level A).\n * Visually hidden by default; revealed on focus via the\n * scoped `<style>` block below.\n */}\n <style>{SKIP_LINK_FOCUS_CSS}</style>\n <a\n href={`#${MAIN_CONTENT_DOM_ID}`}\n data-website-skip-link=\"\"\n style={SKIP_LINK_HIDDEN_STYLE}\n >\n {skipLinkLabel}\n </a>\n {resolvedHeader !== null ? <header>{resolvedHeader}</header> : null}\n <main id={MAIN_CONTENT_DOM_ID} className={mainClassName} tabIndex={-1}>\n {children}\n </main>\n {resolvedFooter !== null ? <footer>{resolvedFooter}</footer> : null}\n {renderConsentSurface(consent, runtime.consentBannerComponent)}\n </div>\n </WebsiteProviderSdkActivationsContext.Provider>\n </WebsitePageContextProvider>\n );\n}\nWebsitePageLayout.displayName = 'WebsitePageLayout';\n\n/**\n * The panel while a decision is owed (or re-opened), the reopen button once one is made, and nothing at\n * all on a site whose live providers rest on no consent. Nothing renders before the stored decision is\n * read, so a visitor who already decided never sees the panel flash.\n */\nfunction renderConsentSurface(\n consent: ReturnType<typeof useWebsiteConsent>,\n BannerOverride: React.ComponentType | undefined,\n): ReactNode {\n if (!consent.isResolved || consent.purposesInUse.length === 0) return null;\n if (consent.status === WebsiteConsentStatus.UNDECIDED || consent.isSettingsOpen) {\n const Banner = BannerOverride ?? WebsiteConsentBanner;\n return <Banner />;\n }\n return (\n <div data-website-consent-settings=\"\">\n <WebsiteConsentSettingsButton />\n </div>\n );\n}\n/** @wildo_source:part:end saas.website.page-layout.component */\n"]}
|
|
1
|
+
{"version":3,"file":"WebsitePageLayout.js","sourceRoot":"","sources":["../../../../../src/core/layouts/WebsitePageLayout.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useMemo, type ReactNode } from 'react';\nimport { BUILTIN_PROVIDER_CAPABILITY } from '@wildo-ai/saas-models/public-runtime';\nimport { consentPurposesInUseByProviders } from '@wildo-ai/external-connectors-public/website';\n\nimport { WebsitePageContextProvider } from '../contexts/WebsitePageContext';\nimport {\n useWebsiteProviderScripts,\n useWebsiteProviderSdks,\n} from '../external-providers/useWebsiteProviderScripts';\nimport { WebsiteProviderSdkActivationsContext } from '../external-providers/website-provider-sdk-activations';\nimport type { WebsitePageContextValue } from '../contexts/WebsitePageContext';\nimport { useWebsiteRuntime } from '../contexts/useWebsiteRuntime';\nimport { websiteDesignTokenCssVar } from '../../schemas/design-tokens/website-design-tokens.shared.schemas';\nimport { useWebsiteLabelByKey } from '../hooks/useWebsiteLabel';\nimport { WebsiteConsentProvider, WebsiteConsentStatus, type WebsiteConsentRecorder } from '../consent/WebsiteConsentContext';\nimport { useWebsiteConsent } from '../consent/useWebsiteConsent';\nimport { WebsiteConsentBanner, WebsiteConsentSettingsButton } from '../consent/WebsiteConsentBanner';\nimport {\n WebsitePageRefSchema,\n type WebsitePageRef,\n} from '../../schemas/refs/page-ref.schemas';\n\n/**\n * Stable DOM id stamped on the `<main>` element so the framework's\n * skip-link `<a href=\"#main-content\">` can move keyboard focus past\n * the chrome on every page (Phase 6 audit fix M-α). Co-located here\n * (rather than exposed as a prop) because:\n * - The skip-link target is a framework concern — exposing it as a\n * consumer-tunable id would invite drift between the link's href\n * and the main element's id.\n * - Screen readers announce the heading inside `<main id=\"...\">` on\n * focus; a stable, framework-owned id keeps that affordance\n * deterministic across every page on every site.\n */\nconst MAIN_CONTENT_DOM_ID = 'main-content';\n\n/**\n * Inline style for the skip link's \"visually hidden by default,\n * visible on focus\" pattern. Inlined (NOT shipped as a CSS class)\n * because:\n * - The framework intentionally avoids shipping any CSS file the\n * consumer must opt in to — the only stylesheet emitted is the\n * `:root { --website-*: … }` design-token block, and the rest of\n * the styling surface lives in consumer code (see Phase 5\n * `renderWebsiteDesignTokensCss`). Inlining keeps the skip link\n * self-sufficient and side-effect-free.\n * - The \"skip-link\" pattern is a small, well-known a11y idiom; the\n * handful of style declarations here do not benefit from being\n * reorganized into a class with a custom-property hook.\n *\n * The \"focused\" variant uses BOTH `:focus` AND `:focus-visible`\n * pseudo-classes via a scoped `<style>` tag inside the layout output.\n * We cannot apply pseudo-class styles via a `style` attribute, but\n * emitting a tiny scoped block once at the layout root is safe (one\n * block per page render, ~120 bytes) and avoids importing a CSS-in-JS\n * runtime.\n *\n * **Why both selectors and not just `:focus-visible`** (Phase 6 fourth\n * audit fix M-Η): `:focus-visible` is the modern UA-heuristic-driven\n * selector that hides focus rings on mouse clicks, and it is the\n * RIGHT default for buttons / links. For a skip link though we WANT\n * the affordance to appear on EVERY focus event — the link is\n * invisible by default and a keyboard-only user (the only intended\n * audience) is the only one who can reach it. Older browsers that\n * predate `:focus-visible` (and Safari < 15.4 with the feature\n * disabled) would skip the rule entirely with a `:focus-visible`-only\n * declaration, leaving the keyboard user looking at an apparently\n * empty page when they pressed Tab. Pairing `:focus, :focus-visible`\n * is the documented WCAG 2.1 fallback pattern.\n */\nconst SKIP_LINK_HIDDEN_STYLE: React.CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '1px',\n height: '1px',\n padding: 0,\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n\n/**\n * Single scoped style block for the skip link's `:focus-visible`\n * affordance. Targets the `data-website-skip-link` attribute (NOT a\n * class) so consumer Tailwind / utility classes cannot accidentally\n * shadow it. Stays trivially small to keep payload under the\n * \"framework rendering\" implicit budget.\n */\nconst SKIP_LINK_FOCUS_CSS = `\n[data-website-skip-link]:focus,\n[data-website-skip-link]:focus-visible {\n position: fixed !important;\n top: 0.5rem !important;\n left: 0.5rem !important;\n width: auto !important;\n height: auto !important;\n padding: 0.75rem 1rem !important;\n margin: 0 !important;\n overflow: visible !important;\n clip: auto !important;\n white-space: normal !important;\n background: ${websiteDesignTokenCssVar('colors', 'background', '#fff')} !important;\n color: ${websiteDesignTokenCssVar('colors', 'foreground', '#000')} !important;\n border: 2px solid ${websiteDesignTokenCssVar('colors', 'primary', '#000')} !important;\n border-radius: ${websiteDesignTokenCssVar('radii', 'md', '0.375rem')} !important;\n z-index: 9999 !important;\n text-decoration: none !important;\n}\n`.trim();\n\n/**\n * @wildo_source:part:start saas.website.page-layout.component facet:layer:core facet:family:website\n *\n * `WebsitePageLayout` — the per-page structural primitive.\n *\n * **Three responsibilities** (each carrying its own semantic weight):\n *\n * 1. **Provides `WebsitePageContext`** — registers the active page\n * ref so child sections (`<WebsiteSection>`) and label hooks\n * (`useWebsiteLabel`) can derive label keys without re-typing\n * the page ref at every leaf.\n * 2. **Renders the site-wide chrome** — pulls\n * `headerComponent` and `footerComponent` from the runtime\n * navigation config and wraps the page's main content in the\n * site's standard header/main/footer scaffold. Per-page\n * overrides (`header={…}` / `footer={…}` props) take precedence\n * over the runtime defaults so individual pages can opt into a\n * custom chrome (eg. a campaign landing page running with\n * header-only minimal chrome).\n * 3. **Stamps DOM landmarks** — emits `data-website-page-ref` on\n * the layout root for analytics / SEO crawlers / overlay\n * tooling that needs to identify the active page from the DOM\n * without booting React. When the website facet hydrates\n * frontend-provider bootstraps, the same root also carries the\n * active public provider refs for analytics / browser-monitoring /\n * captcha so non-React tooling can detect the configured vendor\n * without reverse-engineering app code.\n *\n * 4. **Provides the visitor's consent state and enforces it** (#534) —\n * mounts `WebsiteConsentProvider`, starts a provider SDK or script only\n * once the purpose it rests on is granted (and stops the SDK when it is\n * withdrawn), and renders the consent panel when the site runs a\n * consent-based provider and the visitor has not decided. Here rather\n * than in each bridge because every page — including every blog post —\n * renders through this layout, so no page can be mounted without it.\n *\n * **Why semantic `<header>` / `<main>` / `<footer>` elements**:\n * marketing-site SEO scoring penalizes pages that ship a single\n * unstructured `<div>` tree. Using semantic landmarks costs nothing\n * and improves crawler accessibility AND screen-reader\n * navigability — both are first-class concerns for a public\n * marketing surface.\n *\n * **Why this lives in `core/`** (not `components/`): the layout is\n * structural framework machinery (it owns the page-context\n * provisioning + the navigation slot resolution), not a styled\n * primitive. Designers override `header` / `footer` via runtime\n * config or per-page props, NOT by replacing this component.\n */\nexport interface WebsitePageLayoutProps {\n /**\n * The active page's ref. Accepts either an already-branded\n * `WebsitePageRef` or a raw string — the layout parses through\n * `WebsitePageRefSchema` so a malformed ref fails loud at render.\n *\n * Typically sourced from the page's `WebsitePageManifest.ref`\n * (eg. `<WebsitePageLayout pageRef={LANDING_PAGE_MANIFEST.ref}>`).\n */\n pageRef: WebsitePageRef | string;\n /**\n * Per-page header override. When supplied, takes precedence over\n * `WebsiteRuntimeContext.designTokens` navigation config's\n * `headerComponent`. Pass `null` explicitly to suppress the header\n * entirely (campaign landing pages without site-wide nav).\n */\n header?: ReactNode | null;\n /**\n * Per-page footer override. Same semantics as `header`.\n */\n footer?: ReactNode | null;\n /**\n * Optional className applied to the root `<div data-website-page-ref=\"…\">`\n * wrapper. Use for page-level layout tweaks (eg. `min-h-screen` on\n * landing pages).\n */\n className?: string;\n /**\n * Optional className applied to the inner `<main>` element. Use for\n * vertical-rhythm overrides on long-scroll landing pages.\n */\n mainClassName?: string;\n /**\n * OPTIONAL anonymous-session client. When supplied, a visitor's consent decision is ALSO recorded\n * server-side against their session, which is what lets it follow them into the account they go on\n * to create (#1258). Pass the SAME instance the page's capture sections use, so one `uuidRef`\n * carries the decision, the lead and the draft note together.\n *\n * Absent keeps today's behaviour exactly: the decision lives in this browser and nowhere else.\n * The engine cannot construct the client here — it needs the application's own\n * `frontendServiceName` — which is why it arrives as a prop rather than off the runtime context.\n */\n consentRecorder?: WebsiteConsentRecorder;\n /**\n * The page's section composition. Typically a sequence of\n * `<WebsiteSection>` wrappers around concrete section components.\n */\n children: ReactNode;\n}\n\nexport function WebsitePageLayout(props: WebsitePageLayoutProps): ReactNode {\n const runtime = useWebsiteRuntime();\n // Derived from the LIVE providers, so the panel asks about exactly what this site processes.\n const purposesInUse = useMemo(\n () => consentPurposesInUseByProviders(runtime.frontendProviderRegistry?.modules.values()),\n [runtime.frontendProviderRegistry],\n );\n return (\n <WebsiteConsentProvider purposesInUse={purposesInUse} recorder={props.consentRecorder}>\n <WebsitePageLayoutContent {...props} />\n </WebsiteConsentProvider>\n );\n}\n\nfunction WebsitePageLayoutContent({\n pageRef,\n header,\n footer,\n className,\n mainClassName,\n children,\n}: WebsitePageLayoutProps): ReactNode {\n const runtime = useWebsiteRuntime();\n const consent = useWebsiteConsent();\n\n /**\n * Defensive parse: callers should pass a `WebsitePageManifest.ref`\n * (already branded), but accepting raw strings + parsing here means\n * a hand-typed call site can't smuggle a malformed ref into the\n * label-key derivation chain.\n */\n const safePageRef = useMemo<WebsitePageRef>(\n () => WebsitePageRefSchema.parse(pageRef),\n [pageRef],\n );\n\n const pageContextValue = useMemo<WebsitePageContextValue>(\n () => ({ pageRef: safePageRef }),\n [safePageRef],\n );\n\n /**\n * Header resolution rules:\n * - `header === null` => explicit suppression\n * - `header !== undefined` => per-page override (any ReactNode)\n * - `header === undefined` => fall back to the runtime navigation\n * config's `headerComponent`\n *\n * The fallback is the common path: every page renders the same\n * site-wide chrome. The override path is the escape hatch (campaign\n * landing pages with custom header layouts).\n */\n const resolvedHeader = useMemo<ReactNode>(() => {\n if (header === null) return null;\n if (header !== undefined) return header;\n const HeaderComponent = runtime.navigation.headerComponent;\n return <HeaderComponent />;\n }, [header, runtime.navigation.headerComponent]);\n\n const resolvedFooter = useMemo<ReactNode>(() => {\n if (footer === null) return null;\n if (footer !== undefined) return footer;\n const FooterComponent = runtime.navigation.footerComponent;\n return <FooterComponent />;\n }, [footer, runtime.navigation.footerComponent]);\n\n // Load whatever the live providers declared. Until this landed, the surface\n // resolved provider refs and stamped them into the attributes below and\n // stopped there — a provider could be declared, enabled and hydrated without\n // anything of it ever running.\n //\n // Consent-based providers start only once their purpose is granted (#534). Before the stored decision is\n // read, nothing is granted — the static HTML and the first render start nothing optional.\n useWebsiteProviderScripts(runtime.frontendProviderRegistry, runtime.providerComponentRegistry);\n // The running SDKs are published to the page (#1735): the contact form asks the consented captcha vendor for a token.\n const runningProviderSdks = useWebsiteProviderSdks(runtime.frontendProviderRegistry, consent.grantedPurposes);\n\n const providerRootAttributes = useMemo<Record<string, string>>(() => {\n const attrs: Record<string, string> = {};\n const productAnalyticsProviderRef = runtime.frontendProviderRegistry\n ?.findProviderByProviderCapability(\n BUILTIN_PROVIDER_CAPABILITY.FRONTEND_PRODUCT_ANALYTICS,\n )\n ?.metadata.ref;\n const errorMonitoringProviderRef = runtime.frontendProviderRegistry\n ?.findProviderByProviderCapability(\n BUILTIN_PROVIDER_CAPABILITY.FRONTEND_ERROR_MONITORING,\n )\n ?.metadata.ref;\n const captchaProviderRef = runtime.frontendProviderRegistry\n ?.findProviderByProviderCapability(\n BUILTIN_PROVIDER_CAPABILITY.FRONTEND_CAPTCHA,\n )\n ?.metadata.ref;\n\n if (productAnalyticsProviderRef) {\n attrs['data-website-product-analytics-provider-ref'] = productAnalyticsProviderRef;\n }\n if (errorMonitoringProviderRef) {\n attrs['data-website-error-monitoring-provider-ref'] = errorMonitoringProviderRef;\n }\n if (captchaProviderRef) {\n attrs['data-website-captcha-provider-ref'] = captchaProviderRef;\n }\n\n return attrs;\n }, [runtime.frontendProviderRegistry]);\n\n /**\n * Resolved skip-link label. Reads through the runtime label pack\n * via the standard `useWebsiteLabelByKey` hook so a missing\n * translation surfaces the same diagnostic shape as any other\n * missing chrome label. The framework guarantees the key reaches\n * the bridge (see `pickLabelsForPage`) and the consumer's\n * label-pack validator (see `composeEffectiveChromeLabelKeys` in\n * `label-pack-loader.ts`) ensures it is present in every locale\n * pack — there is therefore no silent-fallback path that would\n * ship an English skip link to a non-EN visitor.\n */\n const skipLinkLabel = useWebsiteLabelByKey(runtime.skipToMainContentLabelKey);\n\n return (\n <WebsitePageContextProvider value={pageContextValue}>\n <WebsiteProviderSdkActivationsContext.Provider value={runningProviderSdks}>\n <div\n data-website-page-ref={safePageRef as unknown as string}\n className={className}\n {...providerRootAttributes}\n >\n {/*\n * Skip link rendered as the FIRST focusable element on the\n * page so a keyboard / AT user can bypass the chrome on every\n * navigation (WCAG 2.1 §2.4.1 \"Bypass Blocks\", Level A).\n * Visually hidden by default; revealed on focus via the\n * scoped `<style>` block below.\n */}\n <style>{SKIP_LINK_FOCUS_CSS}</style>\n <a\n href={`#${MAIN_CONTENT_DOM_ID}`}\n data-website-skip-link=\"\"\n style={SKIP_LINK_HIDDEN_STYLE}\n >\n {skipLinkLabel}\n </a>\n {resolvedHeader !== null ? <header>{resolvedHeader}</header> : null}\n <main id={MAIN_CONTENT_DOM_ID} className={mainClassName} tabIndex={-1}>\n {children}\n </main>\n {resolvedFooter !== null ? <footer>{resolvedFooter}</footer> : null}\n {renderConsentSurface(consent, runtime.consentBannerComponent)}\n </div>\n </WebsiteProviderSdkActivationsContext.Provider>\n </WebsitePageContextProvider>\n );\n}\nWebsitePageLayout.displayName = 'WebsitePageLayout';\n\n/**\n * The panel while a decision is owed (or re-opened), the reopen button once one is made, and nothing at\n * all on a site whose live providers rest on no consent. Nothing renders before the stored decision is\n * read, so a visitor who already decided never sees the panel flash.\n */\nfunction renderConsentSurface(\n consent: ReturnType<typeof useWebsiteConsent>,\n BannerOverride: React.ComponentType | undefined,\n): ReactNode {\n if (!consent.isResolved || consent.purposesInUse.length === 0) return null;\n if (consent.status === WebsiteConsentStatus.UNDECIDED || consent.isSettingsOpen) {\n const Banner = BannerOverride ?? WebsiteConsentBanner;\n return <Banner />;\n }\n return (\n <div data-website-consent-settings=\"\">\n <WebsiteConsentSettingsButton />\n </div>\n );\n}\n/** @wildo_source:part:end saas.website.page-layout.component */\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { WebsiteSectionDefinition } from '../../schemas/sections/website-section-definition.shared.schemas';
|
|
3
|
+
/**
|
|
4
|
+
* @wildo_source:part:start saas.website.page-sections.component facet:layer:core facet:family:website
|
|
5
|
+
*
|
|
6
|
+
* `WebsitePageSections` — renders a page's ordered sections list, each inside its `WebsiteSection`
|
|
7
|
+
* wrapper, and a visible PENDING marker while the list is still empty.
|
|
8
|
+
*
|
|
9
|
+
* A page component should render its sections through this rather than mapping the list by hand:
|
|
10
|
+
*
|
|
11
|
+
* ```tsx
|
|
12
|
+
* export function PricingPage(): ReactNode {
|
|
13
|
+
* return <WebsitePageSections pageRef="pricing" sections={PRICING_SECTIONS} />;
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* **Why the empty state is the point.** A page's sections list starts EMPTY when its page
|
|
18
|
+
* is authored before its sections — the application-creation build lane does exactly that, one task
|
|
19
|
+
* per page and one per section. An empty page is a valid manifest and a dev server serves it; the
|
|
20
|
+
* production build refuses it (`assertWebsitePagesHaveSections`). Mapped by hand, an empty list
|
|
21
|
+
* renders nothing at all, which is indistinguishable from a page that failed. This renders a
|
|
22
|
+
* marked block instead, so the page visibly says its sections are still to come.
|
|
23
|
+
*
|
|
24
|
+
* A section's `anchorId`, declared on its definition, becomes the wrapper's DOM `id`, so in-page links
|
|
25
|
+
* still have a target when no page places its sections by hand.
|
|
26
|
+
*
|
|
27
|
+
* **The marker carries identifiers, not prose.** It shows the page ref and the empty list as code,
|
|
28
|
+
* deliberately: words a person reads come from the label packs, and a label for a state no built
|
|
29
|
+
* page can ever reach (the build refuses an empty page) would be a key every locale must carry for
|
|
30
|
+
* nothing. A missing section must LOOK missing, which a raw identifier does.
|
|
31
|
+
*/
|
|
32
|
+
export interface WebsitePageSectionsProps {
|
|
33
|
+
/** The page's ref, as its manifest declares it. Shown in the pending marker. */
|
|
34
|
+
pageRef: string;
|
|
35
|
+
/** The page's ordered sections list — the same array its manifest's `sectionRefs` derive from. */
|
|
36
|
+
sections: readonly WebsiteSectionDefinition[];
|
|
37
|
+
}
|
|
38
|
+
export declare function WebsitePageSections({ pageRef, sections }: WebsitePageSectionsProps): ReactNode;
|
|
39
|
+
export declare namespace WebsitePageSections {
|
|
40
|
+
var displayName: string;
|
|
41
|
+
}
|
|
42
|
+
/** @wildo_source:part:end saas.website.page-sections.component */
|
|
43
|
+
//# sourceMappingURL=WebsitePageSections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsitePageSections.d.ts","sourceRoot":"","sources":["../../../../../src/core/layouts/WebsitePageSections.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kEAAkE,CAAC;AAGjH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,wBAAwB;IACvC,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,QAAQ,EAAE,SAAS,wBAAwB,EAAE,CAAC;CAC/C;AAED,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,wBAAwB,GAAG,SAAS,CAwB9F;yBAxBe,mBAAmB;;;AA0BnC,kEAAkE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { WebsiteSection } from './WebsiteSection.js';
|
|
3
|
+
export function WebsitePageSections({ pageRef, sections }) {
|
|
4
|
+
if (sections.length === 0) {
|
|
5
|
+
return (_jsx("section", { "data-website-pending-page": pageRef, "aria-busy": "true", style: { margin: '2rem auto', maxWidth: '48rem', padding: '2rem', border: '2px dashed currentColor', opacity: 0.6, textAlign: 'center' }, children: _jsx("code", { children: `${pageRef}: sections = []` }) }));
|
|
6
|
+
}
|
|
7
|
+
return (_jsx(_Fragment, { children: sections.map((section) => {
|
|
8
|
+
const SectionComponent = section.Component;
|
|
9
|
+
return (_jsx(WebsiteSection, { sectionRef: section.sectionRef, category: section.category, id: section.anchorId, children: _jsx(SectionComponent, {}) }, String(section.sectionRef)));
|
|
10
|
+
}) }));
|
|
11
|
+
}
|
|
12
|
+
WebsitePageSections.displayName = 'WebsitePageSections';
|
|
13
|
+
//# sourceMappingURL=WebsitePageSections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsitePageSections.js","sourceRoot":"","sources":["../../../../../src/core/layouts/WebsitePageSections.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAsClD,MAAM,UAAU,mBAAmB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAA4B;IACjF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CACL,+CAC6B,OAAO,eACxB,MAAM,EAChB,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,YAExI,yBAAO,GAAG,OAAO,iBAAiB,GAAQ,GAClC,CACX,CAAC;IACJ,CAAC;IACD,OAAO,CACL,4BACG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YACxB,MAAM,gBAAgB,GAAG,OAAO,CAAC,SAAgC,CAAC;YAClE,OAAO,CACL,KAAC,cAAc,IAAkC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,QAAQ,YAC/H,KAAC,gBAAgB,KAAG,IADD,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAE9B,CAClB,CAAC;QACJ,CAAC,CAAC,GACD,CACJ,CAAC;AACJ,CAAC;AACD,mBAAmB,CAAC,WAAW,GAAG,qBAAqB,CAAC","sourcesContent":["import React, { type ReactNode } from 'react';\n\nimport type { WebsiteSectionDefinition } from '../../schemas/sections/website-section-definition.shared.schemas';\nimport { WebsiteSection } from './WebsiteSection';\n\n/**\n * @wildo_source:part:start saas.website.page-sections.component facet:layer:core facet:family:website\n *\n * `WebsitePageSections` — renders a page's ordered sections list, each inside its `WebsiteSection`\n * wrapper, and a visible PENDING marker while the list is still empty.\n *\n * A page component should render its sections through this rather than mapping the list by hand:\n *\n * ```tsx\n * export function PricingPage(): ReactNode {\n * return <WebsitePageSections pageRef=\"pricing\" sections={PRICING_SECTIONS} />;\n * }\n * ```\n *\n * **Why the empty state is the point.** A page's sections list starts EMPTY when its page\n * is authored before its sections — the application-creation build lane does exactly that, one task\n * per page and one per section. An empty page is a valid manifest and a dev server serves it; the\n * production build refuses it (`assertWebsitePagesHaveSections`). Mapped by hand, an empty list\n * renders nothing at all, which is indistinguishable from a page that failed. This renders a\n * marked block instead, so the page visibly says its sections are still to come.\n *\n * A section's `anchorId`, declared on its definition, becomes the wrapper's DOM `id`, so in-page links\n * still have a target when no page places its sections by hand.\n *\n * **The marker carries identifiers, not prose.** It shows the page ref and the empty list as code,\n * deliberately: words a person reads come from the label packs, and a label for a state no built\n * page can ever reach (the build refuses an empty page) would be a key every locale must carry for\n * nothing. A missing section must LOOK missing, which a raw identifier does.\n */\nexport interface WebsitePageSectionsProps {\n /** The page's ref, as its manifest declares it. Shown in the pending marker. */\n pageRef: string;\n /** The page's ordered sections list — the same array its manifest's `sectionRefs` derive from. */\n sections: readonly WebsiteSectionDefinition[];\n}\n\nexport function WebsitePageSections({ pageRef, sections }: WebsitePageSectionsProps): ReactNode {\n if (sections.length === 0) {\n return (\n <section\n data-website-pending-page={pageRef}\n aria-busy=\"true\"\n style={{ margin: '2rem auto', maxWidth: '48rem', padding: '2rem', border: '2px dashed currentColor', opacity: 0.6, textAlign: 'center' }}\n >\n <code>{`${pageRef}: sections = []`}</code>\n </section>\n );\n }\n return (\n <>\n {sections.map((section) => {\n const SectionComponent = section.Component as React.ComponentType;\n return (\n <WebsiteSection key={String(section.sectionRef)} sectionRef={section.sectionRef} category={section.category} id={section.anchorId}>\n <SectionComponent />\n </WebsiteSection>\n );\n })}\n </>\n );\n}\nWebsitePageSections.displayName = 'WebsitePageSections';\n/** @wildo_source:part:end saas.website.page-sections.component */\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebsiteSection.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"WebsiteSection.d.ts","sourceRoot":"","sources":["../../../../../src/core/layouts/WebsiteSection.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,wDAAwD,CAAC;AAChG,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,wCAAwC,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,UAAU,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACvC;;;;;;;OAOG;IACH,QAAQ,EAAE,sBAAsB,CAAC;IACjC;;;;OAIG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,QAAQ,EACR,EAAE,EACF,SAAS,EACT,QAAQ,EACR,SAAS,EACT,cAAc,GACf,EAAE,mBAAmB,GAAG,SAAS,CAmCjC;yBA3Ce,cAAc;;;AA6C9B,4DAA4D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal-routing.utils.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"internal-routing.utils.d.ts","sourceRoot":"","sources":["../../../../../src/core/routing/internal-routing.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,MAAM,WAAW,8BAA8B;IAC7C,iFAAiF;IACjF,MAAM,EAAE,iBAAiB,CAAC;IAC1B,sFAAsF;IACtF,aAAa,EAAE,iBAAiB,CAAC;IACjC;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,8BAA8B,GAAG,MAAM,CAWpF;AACD,iEAAiE"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -76,6 +76,7 @@ export * from './core/factories/define-website-section';
|
|
|
76
76
|
export * from './core/factories/define-website-page-manifest';
|
|
77
77
|
export * from './core/layouts/WebsitePageLayout';
|
|
78
78
|
export * from './core/layouts/WebsiteSection';
|
|
79
|
+
export * from './core/layouts/WebsitePageSections';
|
|
79
80
|
export * from './core/consent/website-consent-storage';
|
|
80
81
|
export * from './core/consent/WebsiteConsentContext';
|
|
81
82
|
export * from './core/consent/useWebsiteConsent';
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,yDAAyD,CAAC;AACxE,cAAc,oEAAoE,CAAC;AACnF,cAAc,oDAAoD,CAAC;AACnE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,kEAAkE,CAAC;AACjF,cAAc,iEAAiE,CAAC;AAChF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0DAA0D,CAAC;AACzE,cAAc,wDAAwD,CAAC;AACvE,cAAc,qDAAqD,CAAC;AACpE,cAAc,2CAA2C,CAAC;AAE1D,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AAEnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AAEpD,cAAc,+DAA+D,CAAC;AAC9E,cAAc,uDAAuD,CAAC;AACtE,cAAc,oDAAoD,CAAC;AACnE,cAAc,4DAA4D,CAAC;AAE3E,cAAc,2DAA2D,CAAC;AAC1E,cAAc,sDAAsD,CAAC;AACrE,cAAc,6CAA6C,CAAC;AAC5D,cAAc,uDAAuD,CAAC;AAEtE,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AACrD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,qCAAqC,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -76,6 +76,7 @@ export * from './core/factories/define-website-section.js';
|
|
|
76
76
|
export * from './core/factories/define-website-page-manifest.js';
|
|
77
77
|
export * from './core/layouts/WebsitePageLayout.js';
|
|
78
78
|
export * from './core/layouts/WebsiteSection.js';
|
|
79
|
+
export * from './core/layouts/WebsitePageSections.js';
|
|
79
80
|
export * from './core/consent/website-consent-storage.js';
|
|
80
81
|
export * from './core/consent/WebsiteConsentContext.js';
|
|
81
82
|
export * from './core/consent/useWebsiteConsent.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,yDAAyD,CAAC;AACxE,cAAc,oEAAoE,CAAC;AACnF,cAAc,oDAAoD,CAAC;AACnE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,kEAAkE,CAAC;AACjF,cAAc,iEAAiE,CAAC;AAChF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0DAA0D,CAAC;AACzE,cAAc,wDAAwD,CAAC;AACvE,cAAc,qDAAqD,CAAC;AACpE,cAAc,2CAA2C,CAAC;AAE1D,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AAEnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AAEpD,cAAc,+DAA+D,CAAC;AAC9E,cAAc,uDAAuD,CAAC;AACtE,cAAc,oDAAoD,CAAC;AACnE,cAAc,4DAA4D,CAAC;AAE3E,cAAc,2DAA2D,CAAC;AAC1E,cAAc,sDAAsD,CAAC;AACrE,cAAc,6CAA6C,CAAC;AAC5D,cAAc,uDAAuD,CAAC;AAEtE,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AACrD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,qCAAqC,CAAC","sourcesContent":["/**\n * @wildo-package @wildo-ai/saas-website\n *\n * SaaS marketing/landing website engine — schemas + helpers + layout\n * placeholders + Astro/MDX adapters + SEO/AEO/GEO builder library.\n *\n * Per `saas-website-slice.md` D6/D15: this engine ships **NO concrete\n * business sections** (no Hero, no CTA, no Pricing). It ships the\n * structural and helper machinery; consumers author every business\n * section themselves via the `defineWebsiteSection` factory and the\n * accompanying SKILLs in `framework-knowledge`.\n *\n * @wildo-boundary\n * This barrel re-exports the React-side surface: `schemas/`, `core/`,\n * `components/`. The other entries are separate subpaths with their own\n * audiences — `/astro` (Node, Astro frontmatter), `/astro-island` (the\n * bridge factory), `/config` and `/config-loader` (Node), `/mdx`,\n * `/companion` (React-free). Per directory:\n * - `schemas/` : NO React, NO Astro, NO `~wildo-frontend-lib/**`\n * - `core/`, `components/`: MAY use React; NO `~wildo-frontend-lib/**` (Q17=B)\n * - `astro/` : MAY use Astro and Node; NO React component runtime imports\n * - `config/` : Node-side loaders; never reachable from a React-island entry\n * - `mdx/` : MAY use `@mdx-js/*`\n *\n * D12 (client-bundle import discipline): everything reachable from a\n * React-island entry ships to the browser, so every shared model atom\n * comes from a side-effect-free `/public-runtime` subpath —\n * `@wildo-ai/saas-models/public-runtime` first,\n * `@wildo-ai/presets-components-models/public-runtime` for symbols it does\n * not re-export yet — and `@wildo-ai/zod-decorators` is allowed because\n * only an explicit `initZodDecorators()` mutates Zod's prototype.\n *\n * The ROOT barrels of `@wildo-ai/saas-models` and\n * `@wildo-ai/presets-components-models` are forbidden everywhere in this\n * package (they boot the decorator framework and pull the full schema\n * graph), as are the saas-app DI runtime (`inversify`,\n * `@wildo-ai/saas-frontend-lib`, `@wildo-ai/saas-backend-lib`) and\n * pure-backend libs (`mongoose`, `express`, `pino`, `helmet`, `argon2`,\n * `bcrypt`). Enforced by `src/__tests__/bundle-isolation.test.ts`, which\n * walks every entry's import graph against an allow-list.\n *\n * D18 (L1 boundary, Phase 2): the L1 primitives (`WebsiteHeading`,\n * `WebsiteText`, `WebsiteButton`, `WebsiteLink`, `WebsiteImage`) are\n * self-contained placeholders — they do NOT consume\n * `ComponentRegistryService` from `saas-frontend-lib` and do NOT\n * re-export `saas-frontend-lib` primitives. Consumers override at the\n * L1 boundary by barrel-re-exporting their preferred styled variant\n * from their app's `app/website/primitives/<Primitive>.tsx`. Phase 6\n * dogfood will revisit and decide whether to promote a registry-based\n * override mechanism.\n */\n\nexport * from './schemas/refs/page-ref.schemas';\nexport * from './schemas/refs/section-ref.schemas';\nexport * from './schemas/label-keys/website-label-key.schemas';\nexport * from './schemas/label-keys/website-consent-label-keys.schemas';\nexport * from './schemas/label-keys/website-provider-component-label-keys.schemas';\nexport * from './schemas/sections/website-section-category.shared';\nexport * from './schemas/sections/website-section-definition.shared.schemas';\nexport * from './schemas/structured-data/website-structured-data.shared.schemas';\nexport * from './schemas/structured-data/structured-data-reconciliation.shared';\nexport * from './schemas/structured-data/pricing-offer-structured-data.shared';\nexport * from './schemas/design-tokens/website-design-tokens.shared.schemas';\nexport * from './schemas/manifests/website-page-manifest.shared.schemas';\nexport * from './schemas/manifests/website-root-config.shared.schemas';\nexport * from './schemas/blog/blog-post-frontmatter.shared.schemas';\nexport * from './schemas/validators/label-pack.validator';\n\nexport * from './core/contexts/WebsiteRuntimeContext';\nexport * from './core/contexts/useWebsiteRuntime';\nexport * from './core/contexts/WebsitePageContext';\nexport * from './core/contexts/useWebsitePage';\nexport * from './core/contexts/WebsiteSectionContext';\nexport * from './core/contexts/useWebsiteSection';\nexport * from './core/hooks/useWebsiteLabel';\nexport * from './core/hooks/useWebsiteDesignTokens';\nexport * from './core/factories/define-website-section';\nexport * from './core/factories/define-website-page-manifest';\nexport * from './core/layouts/WebsitePageLayout';\nexport * from './core/layouts/WebsiteSection';\nexport * from './core/layouts/WebsitePageSections';\n\nexport * from './core/consent/website-consent-storage';\nexport * from './core/consent/WebsiteConsentContext';\nexport * from './core/consent/useWebsiteConsent';\nexport * from './core/consent/WebsiteConsentGate';\nexport * from './core/consent/WebsiteConsentBanner';\n\nexport * from './core/external-providers/provider-component-registry.website';\nexport * from './core/external-providers/useWebsiteProviderComponent';\nexport * from './core/external-providers/WebsiteProviderComponent';\nexport * from './core/external-providers/website-provider-sdk-activations';\n\nexport * from './core/anonymous-session/website-anonymous-session-client';\nexport * from './core/anonymous-session/inbound-contact-form.schema';\nexport * from './core/anonymous-session/InboundContactForm';\nexport * from './core/anonymous-session/website-submission-challenge';\n\nexport * from './components/low-level/WebsiteHeading';\nexport * from './components/low-level/WebsiteText';\nexport * from './components/low-level/WebsiteLink';\nexport * from './components/low-level/WebsiteInternalLink';\nexport * from './core/routing/internal-routing.utils';\nexport * from './components/low-level/WebsiteButton';\nexport * from './components/low-level/WebsiteInternalButton';\nexport * from './components/low-level/WebsiteImage';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlogPost.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"BlogPost.d.ts","sourceRoot":"","sources":["../../../../src/mdx/BlogPost.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAMvE,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,wBAAwB,CAAC;AAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4GG;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,EAAE,cAAyD,CAAC;AAE3F,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAWD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CAiFxD;yBAjFe,QAAQ;;;AAoFxB;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;AACtD,6DAA6D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blog-post-collection.config.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"blog-post-collection.config.d.ts","sourceRoot":"","sources":["../../../../src/mdx/blog-post-collection.config.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,sDAAsD,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK;QACxC,WAAW,EAAE,MAAM,OAAO,CAAC;KAC5B,CAAC;CACH;AAED,MAAM,WAAW,oCAAoC;IACnD;;;;;;OAMG;IACH,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,6BAA6B;IAC5C;;;;;;OAMG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,oCAAoC,GACzC,6BAA6B,CAK/B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,+BAA+B;IAC9C;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,OAAO,EACZ,GAAG,GAAE,+BAAoC,GACxC,mBAAmB,CAkBrB;AACD,iEAAiE"}
|