@wildo-ai/saas-website 1.1.1
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/LICENSE +34 -0
- package/dist/esm/.builder.pid +9 -0
- package/dist/esm/astro/blog-post-bridge.d.ts +324 -0
- package/dist/esm/astro/blog-post-bridge.d.ts.map +1 -0
- package/dist/esm/astro/blog-post-bridge.js +57 -0
- package/dist/esm/astro/blog-post-bridge.js.map +1 -0
- package/dist/esm/astro/blog-post-head.renderer.d.ts +129 -0
- package/dist/esm/astro/blog-post-head.renderer.d.ts.map +1 -0
- package/dist/esm/astro/blog-post-head.renderer.js +139 -0
- package/dist/esm/astro/blog-post-head.renderer.js.map +1 -0
- package/dist/esm/astro/bridge-runtime.d.ts +224 -0
- package/dist/esm/astro/bridge-runtime.d.ts.map +1 -0
- package/dist/esm/astro/bridge-runtime.js +30 -0
- package/dist/esm/astro/bridge-runtime.js.map +1 -0
- package/dist/esm/astro/collect-expected-label-keys.d.ts +65 -0
- package/dist/esm/astro/collect-expected-label-keys.d.ts.map +1 -0
- package/dist/esm/astro/collect-expected-label-keys.js +101 -0
- package/dist/esm/astro/collect-expected-label-keys.js.map +1 -0
- package/dist/esm/astro/headers-renderer.d.ts +32 -0
- package/dist/esm/astro/headers-renderer.d.ts.map +1 -0
- package/dist/esm/astro/headers-renderer.js +64 -0
- package/dist/esm/astro/headers-renderer.js.map +1 -0
- package/dist/esm/astro/i18n-routing.helper.d.ts +91 -0
- package/dist/esm/astro/i18n-routing.helper.d.ts.map +1 -0
- package/dist/esm/astro/i18n-routing.helper.js +23 -0
- package/dist/esm/astro/i18n-routing.helper.js.map +1 -0
- package/dist/esm/astro/internal/html-escape.d.ts +31 -0
- package/dist/esm/astro/internal/html-escape.d.ts.map +1 -0
- package/dist/esm/astro/internal/html-escape.js +40 -0
- package/dist/esm/astro/internal/html-escape.js.map +1 -0
- package/dist/esm/astro/label-pack-loader.d.ts +134 -0
- package/dist/esm/astro/label-pack-loader.d.ts.map +1 -0
- package/dist/esm/astro/label-pack-loader.js +298 -0
- package/dist/esm/astro/label-pack-loader.js.map +1 -0
- package/dist/esm/astro/llms-txt-server.d.ts +28 -0
- package/dist/esm/astro/llms-txt-server.d.ts.map +1 -0
- package/dist/esm/astro/llms-txt-server.js +33 -0
- package/dist/esm/astro/llms-txt-server.js.map +1 -0
- package/dist/esm/astro/pick-labels-for-page.d.ts +63 -0
- package/dist/esm/astro/pick-labels-for-page.d.ts.map +1 -0
- package/dist/esm/astro/pick-labels-for-page.js +73 -0
- package/dist/esm/astro/pick-labels-for-page.js.map +1 -0
- package/dist/esm/astro/robots-renderer.d.ts +85 -0
- package/dist/esm/astro/robots-renderer.d.ts.map +1 -0
- package/dist/esm/astro/robots-renderer.js +157 -0
- package/dist/esm/astro/robots-renderer.js.map +1 -0
- package/dist/esm/astro/sitemap-coverage.d.ts +101 -0
- package/dist/esm/astro/sitemap-coverage.d.ts.map +1 -0
- package/dist/esm/astro/sitemap-coverage.js +67 -0
- package/dist/esm/astro/sitemap-coverage.js.map +1 -0
- package/dist/esm/astro/structured-data.renderer.d.ts +21 -0
- package/dist/esm/astro/structured-data.renderer.d.ts.map +1 -0
- package/dist/esm/astro/structured-data.renderer.js +142 -0
- package/dist/esm/astro/structured-data.renderer.js.map +1 -0
- package/dist/esm/astro/website-page-head.renderer.d.ts +93 -0
- package/dist/esm/astro/website-page-head.renderer.d.ts.map +1 -0
- package/dist/esm/astro/website-page-head.renderer.js +184 -0
- package/dist/esm/astro/website-page-head.renderer.js.map +1 -0
- package/dist/esm/astro/website-page-runtime.helper.d.ts +112 -0
- package/dist/esm/astro/website-page-runtime.helper.d.ts.map +1 -0
- package/dist/esm/astro/website-page-runtime.helper.js +60 -0
- package/dist/esm/astro/website-page-runtime.helper.js.map +1 -0
- package/dist/esm/astro/website-site-context.d.ts +126 -0
- package/dist/esm/astro/website-site-context.d.ts.map +1 -0
- package/dist/esm/astro/website-site-context.js +37 -0
- package/dist/esm/astro/website-site-context.js.map +1 -0
- package/dist/esm/astro-island.d.ts +56 -0
- package/dist/esm/astro-island.d.ts.map +1 -0
- package/dist/esm/astro-island.js +61 -0
- package/dist/esm/astro-island.js.map +1 -0
- package/dist/esm/astro.d.ts +151 -0
- package/dist/esm/astro.d.ts.map +1 -0
- package/dist/esm/astro.js +151 -0
- package/dist/esm/astro.js.map +1 -0
- package/dist/esm/companion-exports.d.ts +38 -0
- package/dist/esm/companion-exports.d.ts.map +1 -0
- package/dist/esm/companion-exports.js +38 -0
- package/dist/esm/companion-exports.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteButton.d.ts +73 -0
- package/dist/esm/components/low-level/WebsiteButton.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteButton.js +68 -0
- package/dist/esm/components/low-level/WebsiteButton.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteHeading.d.ts +78 -0
- package/dist/esm/components/low-level/WebsiteHeading.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteHeading.js +41 -0
- package/dist/esm/components/low-level/WebsiteHeading.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteImage.d.ts +73 -0
- package/dist/esm/components/low-level/WebsiteImage.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteImage.js +21 -0
- package/dist/esm/components/low-level/WebsiteImage.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.d.ts +90 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.js +47 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.d.ts +99 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.js +68 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteLink.d.ts +50 -0
- package/dist/esm/components/low-level/WebsiteLink.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteLink.js +22 -0
- package/dist/esm/components/low-level/WebsiteLink.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteText.d.ts +57 -0
- package/dist/esm/components/low-level/WebsiteText.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteText.js +57 -0
- package/dist/esm/components/low-level/WebsiteText.js.map +1 -0
- package/dist/esm/config/define-website-config.d.ts +83 -0
- package/dist/esm/config/define-website-config.d.ts.map +1 -0
- package/dist/esm/config/define-website-config.js +126 -0
- package/dist/esm/config/define-website-config.js.map +1 -0
- package/dist/esm/config/index.d.ts +38 -0
- package/dist/esm/config/index.d.ts.map +1 -0
- package/dist/esm/config/index.js +38 -0
- package/dist/esm/config/index.js.map +1 -0
- package/dist/esm/config/load-website-config.d.ts +136 -0
- package/dist/esm/config/load-website-config.d.ts.map +1 -0
- package/dist/esm/config/load-website-config.js +177 -0
- package/dist/esm/config/load-website-config.js.map +1 -0
- package/dist/esm/config/wildo-website-config.schemas.d.ts +251 -0
- package/dist/esm/config/wildo-website-config.schemas.d.ts.map +1 -0
- package/dist/esm/config/wildo-website-config.schemas.js +302 -0
- package/dist/esm/config/wildo-website-config.schemas.js.map +1 -0
- package/dist/esm/config-loader.d.ts +35 -0
- package/dist/esm/config-loader.d.ts.map +1 -0
- package/dist/esm/config-loader.js +35 -0
- package/dist/esm/config-loader.js.map +1 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.d.ts +38 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.js +77 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.js.map +1 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts +41 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js +58 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js.map +1 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts +81 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.js +177 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.js.map +1 -0
- package/dist/esm/core/contexts/WebsitePageContext.d.ts +40 -0
- package/dist/esm/core/contexts/WebsitePageContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsitePageContext.js +8 -0
- package/dist/esm/core/contexts/WebsitePageContext.js.map +1 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts +162 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.js +22 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.js.map +1 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.d.ts +47 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.js +8 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.js.map +1 -0
- package/dist/esm/core/contexts/useWebsitePage.d.ts +13 -0
- package/dist/esm/core/contexts/useWebsitePage.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsitePage.js +22 -0
- package/dist/esm/core/contexts/useWebsitePage.js.map +1 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.d.ts +19 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.js +28 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.js.map +1 -0
- package/dist/esm/core/contexts/useWebsiteSection.d.ts +12 -0
- package/dist/esm/core/contexts/useWebsiteSection.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsiteSection.js +22 -0
- package/dist/esm/core/contexts/useWebsiteSection.js.map +1 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts +17 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts.map +1 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.js +23 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.js.map +1 -0
- package/dist/esm/core/factories/define-website-page-manifest.d.ts +70 -0
- package/dist/esm/core/factories/define-website-page-manifest.d.ts.map +1 -0
- package/dist/esm/core/factories/define-website-page-manifest.js +51 -0
- package/dist/esm/core/factories/define-website-page-manifest.js.map +1 -0
- package/dist/esm/core/factories/define-website-section.d.ts +101 -0
- package/dist/esm/core/factories/define-website-section.d.ts.map +1 -0
- package/dist/esm/core/factories/define-website-section.js +71 -0
- package/dist/esm/core/factories/define-website-section.js.map +1 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts +23 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts.map +1 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.js +25 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.js.map +1 -0
- package/dist/esm/core/hooks/useWebsiteLabel.d.ts +68 -0
- package/dist/esm/core/hooks/useWebsiteLabel.d.ts.map +1 -0
- package/dist/esm/core/hooks/useWebsiteLabel.js +103 -0
- package/dist/esm/core/hooks/useWebsiteLabel.js.map +1 -0
- package/dist/esm/core/layouts/WebsitePageLayout.d.ts +87 -0
- package/dist/esm/core/layouts/WebsitePageLayout.d.ts.map +1 -0
- package/dist/esm/core/layouts/WebsitePageLayout.js +170 -0
- package/dist/esm/core/layouts/WebsitePageLayout.js.map +1 -0
- package/dist/esm/core/layouts/WebsiteSection.d.ts +91 -0
- package/dist/esm/core/layouts/WebsiteSection.d.ts.map +1 -0
- package/dist/esm/core/layouts/WebsiteSection.js +26 -0
- package/dist/esm/core/layouts/WebsiteSection.js.map +1 -0
- package/dist/esm/core/routing/internal-routing.utils.d.ts +65 -0
- package/dist/esm/core/routing/internal-routing.utils.d.ts.map +1 -0
- package/dist/esm/core/routing/internal-routing.utils.js +14 -0
- package/dist/esm/core/routing/internal-routing.utils.js.map +1 -0
- package/dist/esm/index.d.ts +129 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +129 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mdx/BlogPost.d.ts +193 -0
- package/dist/esm/mdx/BlogPost.d.ts.map +1 -0
- package/dist/esm/mdx/BlogPost.js +161 -0
- package/dist/esm/mdx/BlogPost.js.map +1 -0
- package/dist/esm/mdx/blog-post-collection.config.d.ts +139 -0
- package/dist/esm/mdx/blog-post-collection.config.d.ts.map +1 -0
- package/dist/esm/mdx/blog-post-collection.config.js +27 -0
- package/dist/esm/mdx/blog-post-collection.config.js.map +1 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.d.ts +12 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.d.ts.map +1 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.js +13 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.js.map +1 -0
- package/dist/esm/mdx/index.d.ts +22 -0
- package/dist/esm/mdx/index.d.ts.map +1 -0
- package/dist/esm/mdx/index.js +22 -0
- package/dist/esm/mdx/index.js.map +1 -0
- package/dist/esm/mdx/website-mdx-provider.d.ts +90 -0
- package/dist/esm/mdx/website-mdx-provider.d.ts.map +1 -0
- package/dist/esm/mdx/website-mdx-provider.js +8 -0
- package/dist/esm/mdx/website-mdx-provider.js.map +1 -0
- package/dist/esm/mdx.d.ts +38 -0
- package/dist/esm/mdx.d.ts.map +1 -0
- package/dist/esm/mdx.js +38 -0
- package/dist/esm/mdx.js.map +1 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts +75 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js +85 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts +120 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js +152 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts +73 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.js +76 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.js.map +1 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts +209 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js +218 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts +431 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js +438 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/refs/page-ref.schemas.d.ts +40 -0
- package/dist/esm/schemas/refs/page-ref.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/refs/page-ref.schemas.js +43 -0
- package/dist/esm/schemas/refs/page-ref.schemas.js.map +1 -0
- package/dist/esm/schemas/refs/section-ref.schemas.d.ts +41 -0
- package/dist/esm/schemas/refs/section-ref.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/refs/section-ref.schemas.js +44 -0
- package/dist/esm/schemas/refs/section-ref.schemas.js.map +1 -0
- package/dist/esm/schemas/sections/website-section-category.shared.d.ts +63 -0
- package/dist/esm/schemas/sections/website-section-category.shared.d.ts.map +1 -0
- package/dist/esm/schemas/sections/website-section-category.shared.js +64 -0
- package/dist/esm/schemas/sections/website-section-category.shared.js.map +1 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts +114 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js +69 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts +100 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts.map +1 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js +355 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js.map +1 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts +58 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js +2 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/validators/label-pack.validator.d.ts +144 -0
- package/dist/esm/schemas/validators/label-pack.validator.d.ts.map +1 -0
- package/dist/esm/schemas/validators/label-pack.validator.js +100 -0
- package/dist/esm/schemas/validators/label-pack.validator.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +143 -0
- package/src/__tests__/bundle-isolation.test.ts +607 -0
- package/src/astro/__tests__/blog-post-bridge.test.tsx +288 -0
- package/src/astro/__tests__/blog-post-head.renderer.test.ts +249 -0
- package/src/astro/__tests__/bridge-runtime.test.tsx +198 -0
- package/src/astro/__tests__/collect-expected-label-keys.test.ts +69 -0
- package/src/astro/__tests__/headers-renderer.test.ts +143 -0
- package/src/astro/__tests__/i18n-routing.helper.test.ts +116 -0
- package/src/astro/__tests__/label-pack-loader.test.ts +305 -0
- package/src/astro/__tests__/llms-txt-server.test.ts +127 -0
- package/src/astro/__tests__/pick-labels-for-page.test.ts +60 -0
- package/src/astro/__tests__/robots-renderer.test.ts +228 -0
- package/src/astro/__tests__/sitemap-coverage.test.ts +230 -0
- package/src/astro/__tests__/structured-data.renderer.test.ts +172 -0
- package/src/astro/__tests__/website-page-head.renderer.test.ts +424 -0
- package/src/astro/__tests__/website-page-runtime.helper.test.ts +157 -0
- package/src/astro/__tests__/website-site-context.test.ts +121 -0
- package/src/astro/blog-post-bridge.tsx +404 -0
- package/src/astro/blog-post-head.renderer.ts +293 -0
- package/src/astro/bridge-runtime.tsx +270 -0
- package/src/astro/collect-expected-label-keys.ts +113 -0
- package/src/astro/headers-renderer.ts +82 -0
- package/src/astro/i18n-routing.helper.ts +116 -0
- package/src/astro/internal/html-escape.ts +41 -0
- package/src/astro/label-pack-loader.ts +385 -0
- package/src/astro/llms-txt-server.ts +56 -0
- package/src/astro/pick-labels-for-page.ts +85 -0
- package/src/astro/robots-renderer.ts +171 -0
- package/src/astro/sitemap-coverage.ts +186 -0
- package/src/astro/structured-data.renderer.ts +171 -0
- package/src/astro/website-page-head.renderer.ts +279 -0
- package/src/astro/website-page-runtime.helper.ts +188 -0
- package/src/astro/website-site-context.ts +136 -0
- package/src/astro-island.ts +61 -0
- package/src/astro.ts +151 -0
- package/src/companion-exports.ts +38 -0
- package/src/components/low-level/WebsiteButton.tsx +118 -0
- package/src/components/low-level/WebsiteHeading.tsx +96 -0
- package/src/components/low-level/WebsiteImage.tsx +96 -0
- package/src/components/low-level/WebsiteInternalButton.tsx +172 -0
- package/src/components/low-level/WebsiteInternalLink.tsx +193 -0
- package/src/components/low-level/WebsiteLink.tsx +71 -0
- package/src/components/low-level/WebsiteText.tsx +75 -0
- package/src/components/low-level/__tests__/WebsiteInternalButton.test.tsx +169 -0
- package/src/components/low-level/__tests__/WebsiteInternalLink.test.tsx +202 -0
- package/src/components/low-level/__tests__/primitives.test.tsx +141 -0
- package/src/config/__tests__/define-website-config.test.ts +231 -0
- package/src/config/__tests__/load-website-config.test.ts +215 -0
- package/src/config/define-website-config.ts +134 -0
- package/src/config/index.ts +38 -0
- package/src/config/load-website-config.ts +229 -0
- package/src/config/wildo-website-config.schemas.ts +322 -0
- package/src/config-loader.ts +35 -0
- package/src/core/__tests__/WebsitePageLayout.test.tsx +184 -0
- package/src/core/__tests__/WebsiteSection.test.tsx +85 -0
- package/src/core/__tests__/contexts.test.tsx +133 -0
- package/src/core/__tests__/core-boundary.test.ts +85 -0
- package/src/core/__tests__/define-website-page-manifest.test.tsx +111 -0
- package/src/core/__tests__/define-website-section.test.tsx +89 -0
- package/src/core/__tests__/useWebsiteDesignTokens.test.tsx +41 -0
- package/src/core/__tests__/useWebsiteLabel.test.tsx +117 -0
- package/src/core/anonymous-session/InboundContactForm.tsx +157 -0
- package/src/core/anonymous-session/__tests__/inbound-contact-form.schema.test.ts +44 -0
- package/src/core/anonymous-session/inbound-contact-form.schema.ts +62 -0
- package/src/core/anonymous-session/website-anonymous-session-client.ts +194 -0
- package/src/core/contexts/WebsitePageContext.tsx +52 -0
- package/src/core/contexts/WebsiteRuntimeContext.tsx +175 -0
- package/src/core/contexts/WebsiteSectionContext.tsx +59 -0
- package/src/core/contexts/useWebsitePage.ts +28 -0
- package/src/core/contexts/useWebsiteRuntime.ts +34 -0
- package/src/core/contexts/useWebsiteSection.ts +28 -0
- package/src/core/external-providers/frontend-provider-registry.website.ts +62 -0
- package/src/core/factories/define-website-page-manifest.ts +102 -0
- package/src/core/factories/define-website-section.ts +128 -0
- package/src/core/hooks/useWebsiteDesignTokens.ts +26 -0
- package/src/core/hooks/useWebsiteLabel.ts +121 -0
- package/src/core/layouts/WebsitePageLayout.tsx +311 -0
- package/src/core/layouts/WebsiteSection.tsx +139 -0
- package/src/core/routing/__tests__/internal-routing.utils.test.ts +134 -0
- package/src/core/routing/internal-routing.utils.ts +77 -0
- package/src/index.ts +132 -0
- package/src/mdx/BlogPost.tsx +296 -0
- package/src/mdx/__tests__/BlogPost.test.tsx +218 -0
- package/src/mdx/__tests__/blog-post-collection.config.test.ts +127 -0
- package/src/mdx/__tests__/website-mdx-provider.test.tsx +82 -0
- package/src/mdx/blog-post-collection.config.ts +177 -0
- package/src/mdx/blog-post-frontmatter-source.ts +31 -0
- package/src/mdx/index.ts +39 -0
- package/src/mdx/website-mdx-provider.tsx +95 -0
- package/src/mdx.ts +38 -0
- package/src/schemas/__tests__/blog-frontmatter.test.ts +50 -0
- package/src/schemas/__tests__/companion-exports-react-free.test.ts +51 -0
- package/src/schemas/__tests__/design-tokens.test.ts +163 -0
- package/src/schemas/__tests__/label-key.test.ts +46 -0
- package/src/schemas/__tests__/label-pack-validator.test.ts +146 -0
- package/src/schemas/__tests__/page-manifest.test.ts +66 -0
- package/src/schemas/__tests__/refs.test.ts +37 -0
- package/src/schemas/__tests__/root-config.test.ts +292 -0
- package/src/schemas/__tests__/section-definition.test.ts +47 -0
- package/src/schemas/__tests__/structured-data-reconciliation.test.ts +543 -0
- package/src/schemas/blog/blog-post-frontmatter.shared.schemas.ts +111 -0
- package/src/schemas/design-tokens/website-design-tokens.shared.schemas.ts +166 -0
- package/src/schemas/label-keys/website-label-key.schemas.ts +88 -0
- package/src/schemas/manifests/website-page-manifest.shared.schemas.ts +266 -0
- package/src/schemas/manifests/website-root-config.shared.schemas.ts +504 -0
- package/src/schemas/refs/page-ref.schemas.ts +49 -0
- package/src/schemas/refs/section-ref.schemas.ts +50 -0
- package/src/schemas/sections/website-section-category.shared.ts +65 -0
- package/src/schemas/sections/website-section-definition.shared.schemas.ts +120 -0
- package/src/schemas/structured-data/structured-data-reconciliation.shared.ts +579 -0
- package/src/schemas/structured-data/website-structured-data.shared.schemas.ts +62 -0
- package/src/schemas/validators/label-pack.validator.ts +201 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @wildo-package @wildo-ai/saas-website (companion entry)
|
|
3
|
+
*
|
|
4
|
+
* Narrow, React-free entry point for non-React consumers:
|
|
5
|
+
* - the `wildo-cli`'s page/sitemap/structured-data audit commands
|
|
6
|
+
* - companion subprocesses (e.g. introspection of authored pages)
|
|
7
|
+
* - CI scripts that validate label-pack coverage
|
|
8
|
+
* - anything Astro-build-time that cannot pull React into the
|
|
9
|
+
* evaluation graph
|
|
10
|
+
*
|
|
11
|
+
* Per `saas-website-slice.md` §"Note on `companion-exports.ts` scope
|
|
12
|
+
* expansion": the SEO builder library lives here too (it's pure
|
|
13
|
+
* string + JSON-LD generation, React-free by design).
|
|
14
|
+
*
|
|
15
|
+
* @wildo-boundary
|
|
16
|
+
* This file MUST re-export ONLY from `schemas/**` and `seo/**`.
|
|
17
|
+
* It MUST NOT import or re-export anything from:
|
|
18
|
+
* - `core/**` (React runtime contexts/hooks)
|
|
19
|
+
* - `astro/**` (Astro-only adapter)
|
|
20
|
+
* - `mdx/**` (MDX-only adapter)
|
|
21
|
+
* - `integration/**` (React-bearing integration code)
|
|
22
|
+
* It MUST NOT import React, Astro, or `@mdx-js/*`.
|
|
23
|
+
*
|
|
24
|
+
* Enforced by review until Phase 8 boundary lint design (see plan).
|
|
25
|
+
*
|
|
26
|
+
* Phase 1 status: schemas exposed; SEO builders land in Phase 2.5.
|
|
27
|
+
*/
|
|
28
|
+
export * from './schemas/refs/page-ref.schemas';
|
|
29
|
+
export * from './schemas/refs/section-ref.schemas';
|
|
30
|
+
export * from './schemas/label-keys/website-label-key.schemas';
|
|
31
|
+
export * from './schemas/sections/website-section-category.shared';
|
|
32
|
+
export * from './schemas/sections/website-section-definition.shared.schemas';
|
|
33
|
+
export * from './schemas/design-tokens/website-design-tokens.shared.schemas';
|
|
34
|
+
export * from './schemas/manifests/website-page-manifest.shared.schemas';
|
|
35
|
+
export * from './schemas/manifests/website-root-config.shared.schemas';
|
|
36
|
+
export * from './schemas/blog/blog-post-frontmatter.shared.schemas';
|
|
37
|
+
export * from './schemas/validators/label-pack.validator';
|
|
38
|
+
//# sourceMappingURL=companion-exports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"companion-exports.d.ts","sourceRoot":"","sources":["../../../src/companion-exports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AACnE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0DAA0D,CAAC;AACzE,cAAc,wDAAwD,CAAC;AACvE,cAAc,qDAAqD,CAAC;AACpE,cAAc,2CAA2C,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @wildo-package @wildo-ai/saas-website (companion entry)
|
|
3
|
+
*
|
|
4
|
+
* Narrow, React-free entry point for non-React consumers:
|
|
5
|
+
* - the `wildo-cli`'s page/sitemap/structured-data audit commands
|
|
6
|
+
* - companion subprocesses (e.g. introspection of authored pages)
|
|
7
|
+
* - CI scripts that validate label-pack coverage
|
|
8
|
+
* - anything Astro-build-time that cannot pull React into the
|
|
9
|
+
* evaluation graph
|
|
10
|
+
*
|
|
11
|
+
* Per `saas-website-slice.md` §"Note on `companion-exports.ts` scope
|
|
12
|
+
* expansion": the SEO builder library lives here too (it's pure
|
|
13
|
+
* string + JSON-LD generation, React-free by design).
|
|
14
|
+
*
|
|
15
|
+
* @wildo-boundary
|
|
16
|
+
* This file MUST re-export ONLY from `schemas/**` and `seo/**`.
|
|
17
|
+
* It MUST NOT import or re-export anything from:
|
|
18
|
+
* - `core/**` (React runtime contexts/hooks)
|
|
19
|
+
* - `astro/**` (Astro-only adapter)
|
|
20
|
+
* - `mdx/**` (MDX-only adapter)
|
|
21
|
+
* - `integration/**` (React-bearing integration code)
|
|
22
|
+
* It MUST NOT import React, Astro, or `@mdx-js/*`.
|
|
23
|
+
*
|
|
24
|
+
* Enforced by review until Phase 8 boundary lint design (see plan).
|
|
25
|
+
*
|
|
26
|
+
* Phase 1 status: schemas exposed; SEO builders land in Phase 2.5.
|
|
27
|
+
*/
|
|
28
|
+
export * from './schemas/refs/page-ref.schemas.js';
|
|
29
|
+
export * from './schemas/refs/section-ref.schemas.js';
|
|
30
|
+
export * from './schemas/label-keys/website-label-key.schemas.js';
|
|
31
|
+
export * from './schemas/sections/website-section-category.shared.js';
|
|
32
|
+
export * from './schemas/sections/website-section-definition.shared.schemas.js';
|
|
33
|
+
export * from './schemas/design-tokens/website-design-tokens.shared.schemas.js';
|
|
34
|
+
export * from './schemas/manifests/website-page-manifest.shared.schemas.js';
|
|
35
|
+
export * from './schemas/manifests/website-root-config.shared.schemas.js';
|
|
36
|
+
export * from './schemas/blog/blog-post-frontmatter.shared.schemas.js';
|
|
37
|
+
export * from './schemas/validators/label-pack.validator.js';
|
|
38
|
+
//# sourceMappingURL=companion-exports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"companion-exports.js","sourceRoot":"","sources":["../../../src/companion-exports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AACnE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0DAA0D,CAAC;AACzE,cAAc,wDAAwD,CAAC;AACvE,cAAc,qDAAqD,CAAC;AACpE,cAAc,2CAA2C,CAAC","sourcesContent":["/**\n * @wildo-package @wildo-ai/saas-website (companion entry)\n *\n * Narrow, React-free entry point for non-React consumers:\n * - the `wildo-cli`'s page/sitemap/structured-data audit commands\n * - companion subprocesses (e.g. introspection of authored pages)\n * - CI scripts that validate label-pack coverage\n * - anything Astro-build-time that cannot pull React into the\n * evaluation graph\n *\n * Per `saas-website-slice.md` §\"Note on `companion-exports.ts` scope\n * expansion\": the SEO builder library lives here too (it's pure\n * string + JSON-LD generation, React-free by design).\n *\n * @wildo-boundary\n * This file MUST re-export ONLY from `schemas/**` and `seo/**`.\n * It MUST NOT import or re-export anything from:\n * - `core/**` (React runtime contexts/hooks)\n * - `astro/**` (Astro-only adapter)\n * - `mdx/**` (MDX-only adapter)\n * - `integration/**` (React-bearing integration code)\n * It MUST NOT import React, Astro, or `@mdx-js/*`.\n *\n * Enforced by review until Phase 8 boundary lint design (see plan).\n *\n * Phase 1 status: schemas exposed; SEO builders land in Phase 2.5.\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/sections/website-section-category.shared';\nexport * from './schemas/sections/website-section-definition.shared.schemas';\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"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @wildo_source:part:start saas.website.primitives.button facet:layer:components facet:family:website
|
|
4
|
+
*
|
|
5
|
+
* `WebsiteButton` — L1 marketing-site CTA / button primitive.
|
|
6
|
+
*
|
|
7
|
+
* **Two render modes** (selected by the presence of `href`):
|
|
8
|
+
* - `href` supplied => renders as a `<WebsiteLink>` (anchor)
|
|
9
|
+
* with button styling. This is the dominant marketing-site
|
|
10
|
+
* case (CTAs link to `/signup`, `/contact`, `#pricing`).
|
|
11
|
+
* - `href` omitted => renders a real `<button type="…">` for
|
|
12
|
+
* interactive sections (eg. a "Subscribe" form button on the
|
|
13
|
+
* contact page that opens an inbound-contact dialog).
|
|
14
|
+
*
|
|
15
|
+
* **Why a single primitive** (vs. separate `<WebsiteCta>` +
|
|
16
|
+
* `<WebsiteButton>`): the visual identity is the same, and the
|
|
17
|
+
* rendered tag is a low-level concern decided per call site. A
|
|
18
|
+
* single primitive with two modes keeps the section-author API
|
|
19
|
+
* narrow (one import, one prop set) while preserving correct
|
|
20
|
+
* semantic HTML at each call site.
|
|
21
|
+
*
|
|
22
|
+
* **Variant vocabulary**: kept minimal at the placeholder level
|
|
23
|
+
* (`primary` / `secondary`). The override implementation typically
|
|
24
|
+
* extends with `tertiary`, `ghost`, `destructive`, etc. — adding
|
|
25
|
+
* variants here would lock the placeholder vocabulary against the
|
|
26
|
+
* override's richer set.
|
|
27
|
+
*/
|
|
28
|
+
export declare enum WebsiteButtonVariant {
|
|
29
|
+
PRIMARY = "primary",
|
|
30
|
+
SECONDARY = "secondary"
|
|
31
|
+
}
|
|
32
|
+
export declare enum WebsiteButtonSize {
|
|
33
|
+
SM = "sm",
|
|
34
|
+
MD = "md",
|
|
35
|
+
LG = "lg"
|
|
36
|
+
}
|
|
37
|
+
interface WebsiteButtonCommonProps {
|
|
38
|
+
variant?: WebsiteButtonVariant;
|
|
39
|
+
size?: WebsiteButtonSize;
|
|
40
|
+
className?: string;
|
|
41
|
+
style?: CSSProperties;
|
|
42
|
+
id?: string;
|
|
43
|
+
ariaLabel?: string;
|
|
44
|
+
children: ReactNode;
|
|
45
|
+
}
|
|
46
|
+
interface WebsiteButtonAsLinkProps extends WebsiteButtonCommonProps {
|
|
47
|
+
href: string;
|
|
48
|
+
external?: boolean;
|
|
49
|
+
type?: never;
|
|
50
|
+
onClick?: never;
|
|
51
|
+
disabled?: never;
|
|
52
|
+
}
|
|
53
|
+
interface WebsiteButtonAsButtonProps extends WebsiteButtonCommonProps {
|
|
54
|
+
href?: never;
|
|
55
|
+
external?: never;
|
|
56
|
+
type?: 'button' | 'submit' | 'reset';
|
|
57
|
+
onClick?: () => void;
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Discriminated union of "anchor-shaped" vs. "button-shaped" props.
|
|
62
|
+
* Either supply `href` (renders an anchor with link semantics) OR
|
|
63
|
+
* supply `type` / `onClick` / `disabled` (renders a real button) —
|
|
64
|
+
* mixing the two is rejected at compile time.
|
|
65
|
+
*/
|
|
66
|
+
export type WebsiteButtonProps = WebsiteButtonAsLinkProps | WebsiteButtonAsButtonProps;
|
|
67
|
+
export declare function WebsiteButton(props: WebsiteButtonProps): ReactNode;
|
|
68
|
+
export declare namespace WebsiteButton {
|
|
69
|
+
var displayName: string;
|
|
70
|
+
}
|
|
71
|
+
export {};
|
|
72
|
+
/** @wildo_source:part:end saas.website.primitives.button */
|
|
73
|
+
//# sourceMappingURL=WebsiteButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsiteButton.d.ts","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteButton.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,oBAAY,oBAAoB;IAC9B,OAAO,YAAY;IACnB,SAAS,cAAc;CACxB;AAED,oBAAY,iBAAiB;IAC3B,EAAE,OAAO;IACT,EAAE,OAAO;IACT,EAAE,OAAO;CACV;AAED,UAAU,wBAAwB;IAChC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,wBAAyB,SAAQ,wBAAwB;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,UAAU,0BAA2B,SAAQ,wBAAwB;IACnE,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,GAAG,0BAA0B,CAAC;AAEvF,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,CAwClE;yBAxCe,aAAa;;;;AA0C7B,4DAA4D"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { WebsiteLink } from './WebsiteLink.js';
|
|
3
|
+
/**
|
|
4
|
+
* @wildo_source:part:start saas.website.primitives.button facet:layer:components facet:family:website
|
|
5
|
+
*
|
|
6
|
+
* `WebsiteButton` — L1 marketing-site CTA / button primitive.
|
|
7
|
+
*
|
|
8
|
+
* **Two render modes** (selected by the presence of `href`):
|
|
9
|
+
* - `href` supplied => renders as a `<WebsiteLink>` (anchor)
|
|
10
|
+
* with button styling. This is the dominant marketing-site
|
|
11
|
+
* case (CTAs link to `/signup`, `/contact`, `#pricing`).
|
|
12
|
+
* - `href` omitted => renders a real `<button type="…">` for
|
|
13
|
+
* interactive sections (eg. a "Subscribe" form button on the
|
|
14
|
+
* contact page that opens an inbound-contact dialog).
|
|
15
|
+
*
|
|
16
|
+
* **Why a single primitive** (vs. separate `<WebsiteCta>` +
|
|
17
|
+
* `<WebsiteButton>`): the visual identity is the same, and the
|
|
18
|
+
* rendered tag is a low-level concern decided per call site. A
|
|
19
|
+
* single primitive with two modes keeps the section-author API
|
|
20
|
+
* narrow (one import, one prop set) while preserving correct
|
|
21
|
+
* semantic HTML at each call site.
|
|
22
|
+
*
|
|
23
|
+
* **Variant vocabulary**: kept minimal at the placeholder level
|
|
24
|
+
* (`primary` / `secondary`). The override implementation typically
|
|
25
|
+
* extends with `tertiary`, `ghost`, `destructive`, etc. — adding
|
|
26
|
+
* variants here would lock the placeholder vocabulary against the
|
|
27
|
+
* override's richer set.
|
|
28
|
+
*/
|
|
29
|
+
export var WebsiteButtonVariant;
|
|
30
|
+
(function (WebsiteButtonVariant) {
|
|
31
|
+
WebsiteButtonVariant["PRIMARY"] = "primary";
|
|
32
|
+
WebsiteButtonVariant["SECONDARY"] = "secondary";
|
|
33
|
+
})(WebsiteButtonVariant || (WebsiteButtonVariant = {}));
|
|
34
|
+
export var WebsiteButtonSize;
|
|
35
|
+
(function (WebsiteButtonSize) {
|
|
36
|
+
WebsiteButtonSize["SM"] = "sm";
|
|
37
|
+
WebsiteButtonSize["MD"] = "md";
|
|
38
|
+
WebsiteButtonSize["LG"] = "lg";
|
|
39
|
+
})(WebsiteButtonSize || (WebsiteButtonSize = {}));
|
|
40
|
+
export function WebsiteButton(props) {
|
|
41
|
+
const variant = props.variant ?? WebsiteButtonVariant.PRIMARY;
|
|
42
|
+
const size = props.size ?? WebsiteButtonSize.MD;
|
|
43
|
+
if ('href' in props && props.href !== undefined) {
|
|
44
|
+
return (_jsx(WebsiteLink, { href: props.href, external: props.external, className: props.className, style: props.style, id: props.id, ariaLabel: props.ariaLabel, children: _jsx("span", { "data-website-primitive": "button", "data-website-button-variant": variant, "data-website-button-size": size, "data-website-button-mode": "link", children: props.children }) }));
|
|
45
|
+
}
|
|
46
|
+
const attrs = {
|
|
47
|
+
'data-website-primitive': 'button',
|
|
48
|
+
'data-website-button-variant': variant,
|
|
49
|
+
'data-website-button-size': size,
|
|
50
|
+
'data-website-button-mode': 'button',
|
|
51
|
+
type: props.type ?? 'button',
|
|
52
|
+
};
|
|
53
|
+
if (props.className !== undefined)
|
|
54
|
+
attrs.className = props.className;
|
|
55
|
+
if (props.style !== undefined)
|
|
56
|
+
attrs.style = props.style;
|
|
57
|
+
if (props.id !== undefined)
|
|
58
|
+
attrs.id = props.id;
|
|
59
|
+
if (props.ariaLabel !== undefined)
|
|
60
|
+
attrs['aria-label'] = props.ariaLabel;
|
|
61
|
+
if (props.disabled !== undefined)
|
|
62
|
+
attrs.disabled = props.disabled;
|
|
63
|
+
if (props.onClick !== undefined)
|
|
64
|
+
attrs.onClick = props.onClick;
|
|
65
|
+
return _jsx("button", { ...attrs, children: props.children });
|
|
66
|
+
}
|
|
67
|
+
WebsiteButton.displayName = 'WebsiteButton';
|
|
68
|
+
//# sourceMappingURL=WebsiteButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsiteButton.js","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteButton.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAN,IAAY,oBAGX;AAHD,WAAY,oBAAoB;IAC9B,2CAAmB,CAAA;IACnB,+CAAuB,CAAA;AACzB,CAAC,EAHW,oBAAoB,KAApB,oBAAoB,QAG/B;AAED,MAAM,CAAN,IAAY,iBAIX;AAJD,WAAY,iBAAiB;IAC3B,8BAAS,CAAA;IACT,8BAAS,CAAA;IACT,8BAAS,CAAA;AACX,CAAC,EAJW,iBAAiB,KAAjB,iBAAiB,QAI5B;AAoCD,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,oBAAoB,CAAC,OAAO,CAAC;IAC9D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,iBAAiB,CAAC,EAAE,CAAC;IAEhD,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAChD,OAAO,CACL,KAAC,WAAW,IACV,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,EAAE,EAAE,KAAK,CAAC,EAAE,EACZ,SAAS,EAAE,KAAK,CAAC,SAAS,YAE1B,yCACyB,QAAQ,iCACF,OAAO,8BACV,IAAI,8BACL,MAAM,YAE9B,KAAK,CAAC,QAAQ,GACV,GACK,CACf,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAA4B;QACrC,wBAAwB,EAAE,QAAQ;QAClC,6BAA6B,EAAE,OAAO;QACtC,0BAA0B,EAAE,IAAI;QAChC,0BAA0B,EAAE,QAAQ;QACpC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,QAAQ;KAC7B,CAAC;IACF,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IACrE,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACzD,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS;QAAE,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;IAChD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;IACzE,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAClE,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC/D,OAAO,oBAAY,KAAK,YAAG,KAAK,CAAC,QAAQ,GAAU,CAAC;AACtD,CAAC;AACD,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC","sourcesContent":["import React, { type CSSProperties, type ReactNode } from 'react';\n\nimport { WebsiteLink } from './WebsiteLink';\n\n/**\n * @wildo_source:part:start saas.website.primitives.button facet:layer:components facet:family:website\n *\n * `WebsiteButton` — L1 marketing-site CTA / button primitive.\n *\n * **Two render modes** (selected by the presence of `href`):\n * - `href` supplied => renders as a `<WebsiteLink>` (anchor)\n * with button styling. This is the dominant marketing-site\n * case (CTAs link to `/signup`, `/contact`, `#pricing`).\n * - `href` omitted => renders a real `<button type=\"…\">` for\n * interactive sections (eg. a \"Subscribe\" form button on the\n * contact page that opens an inbound-contact dialog).\n *\n * **Why a single primitive** (vs. separate `<WebsiteCta>` +\n * `<WebsiteButton>`): the visual identity is the same, and the\n * rendered tag is a low-level concern decided per call site. A\n * single primitive with two modes keeps the section-author API\n * narrow (one import, one prop set) while preserving correct\n * semantic HTML at each call site.\n *\n * **Variant vocabulary**: kept minimal at the placeholder level\n * (`primary` / `secondary`). The override implementation typically\n * extends with `tertiary`, `ghost`, `destructive`, etc. — adding\n * variants here would lock the placeholder vocabulary against the\n * override's richer set.\n */\nexport enum WebsiteButtonVariant {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n}\n\nexport enum WebsiteButtonSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n}\n\ninterface WebsiteButtonCommonProps {\n variant?: WebsiteButtonVariant;\n size?: WebsiteButtonSize;\n className?: string;\n style?: CSSProperties;\n id?: string;\n ariaLabel?: string;\n children: ReactNode;\n}\n\ninterface WebsiteButtonAsLinkProps extends WebsiteButtonCommonProps {\n href: string;\n external?: boolean;\n type?: never;\n onClick?: never;\n disabled?: never;\n}\n\ninterface WebsiteButtonAsButtonProps extends WebsiteButtonCommonProps {\n href?: never;\n external?: never;\n type?: 'button' | 'submit' | 'reset';\n onClick?: () => void;\n disabled?: boolean;\n}\n\n/**\n * Discriminated union of \"anchor-shaped\" vs. \"button-shaped\" props.\n * Either supply `href` (renders an anchor with link semantics) OR\n * supply `type` / `onClick` / `disabled` (renders a real button) —\n * mixing the two is rejected at compile time.\n */\nexport type WebsiteButtonProps = WebsiteButtonAsLinkProps | WebsiteButtonAsButtonProps;\n\nexport function WebsiteButton(props: WebsiteButtonProps): ReactNode {\n const variant = props.variant ?? WebsiteButtonVariant.PRIMARY;\n const size = props.size ?? WebsiteButtonSize.MD;\n\n if ('href' in props && props.href !== undefined) {\n return (\n <WebsiteLink\n href={props.href}\n external={props.external}\n className={props.className}\n style={props.style}\n id={props.id}\n ariaLabel={props.ariaLabel}\n >\n <span\n data-website-primitive=\"button\"\n data-website-button-variant={variant}\n data-website-button-size={size}\n data-website-button-mode=\"link\"\n >\n {props.children}\n </span>\n </WebsiteLink>\n );\n }\n\n const attrs: Record<string, unknown> = {\n 'data-website-primitive': 'button',\n 'data-website-button-variant': variant,\n 'data-website-button-size': size,\n 'data-website-button-mode': 'button',\n type: props.type ?? 'button',\n };\n if (props.className !== undefined) attrs.className = props.className;\n if (props.style !== undefined) attrs.style = props.style;\n if (props.id !== undefined) attrs.id = props.id;\n if (props.ariaLabel !== undefined) attrs['aria-label'] = props.ariaLabel;\n if (props.disabled !== undefined) attrs.disabled = props.disabled;\n if (props.onClick !== undefined) attrs.onClick = props.onClick;\n return <button {...attrs}>{props.children}</button>;\n}\nWebsiteButton.displayName = 'WebsiteButton';\n/** @wildo_source:part:end saas.website.primitives.button */\n"]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @wildo_source:part:start saas.website.primitives.heading facet:layer:components facet:family:website
|
|
4
|
+
*
|
|
5
|
+
* `WebsiteHeading` — L1 marketing-site heading primitive.
|
|
6
|
+
*
|
|
7
|
+
* **Status (Phase 2 / D18 — option D)**: minimal, self-contained
|
|
8
|
+
* placeholder. The framework defaults are intentionally bare so
|
|
9
|
+
* consumers MUST override at the L1 boundary by barrel-re-exporting
|
|
10
|
+
* a styled variant from their app's
|
|
11
|
+
* `app/website/primitives/WebsiteHeading.tsx`. The Phase 6
|
|
12
|
+
* dogfood will validate the override workflow and (deferred to
|
|
13
|
+
* Phase 6) decide whether to promote these to the
|
|
14
|
+
* `ComponentRegistryService` registry shared with `saas-frontend-lib`.
|
|
15
|
+
*
|
|
16
|
+
* **Why these primitives ship at all** (vs. asking consumers to
|
|
17
|
+
* author every primitive themselves): consistency of the section
|
|
18
|
+
* authoring surface. Section authors call `<WebsiteHeading
|
|
19
|
+
* level={1}>` from `defineWebsiteSection`'d components without
|
|
20
|
+
* having to know which app they're rendering in — the override
|
|
21
|
+
* happens at the consumer barrel level transparently.
|
|
22
|
+
*
|
|
23
|
+
* **Why `level` is a discrete prop (1–6)**: heading hierarchy is
|
|
24
|
+
* critical for SEO and accessibility, and a free-string `as` prop
|
|
25
|
+
* makes it trivial for a copy-paste section to render `<h2>`s where
|
|
26
|
+
* the page outline expects `<h1>`. Constraining `level` to a numeric
|
|
27
|
+
* union keeps the section author honest about the document outline.
|
|
28
|
+
*
|
|
29
|
+
* **Why `variant` (display vs. headline) is shipped here**:
|
|
30
|
+
* marketing-site headings need a visual scale that's distinct from
|
|
31
|
+
* the in-app heading scale (display sizes for hero, headline sizes
|
|
32
|
+
* for section titles). Even as a placeholder, the variant slot
|
|
33
|
+
* exists so section authors don't have to invent the prop ad-hoc;
|
|
34
|
+
* the override implementation can deliver the actual visual scale.
|
|
35
|
+
*/
|
|
36
|
+
export type WebsiteHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
37
|
+
export declare enum WebsiteHeadingVariant {
|
|
38
|
+
/**
|
|
39
|
+
* Hero / above-the-fold sizes. Maps to the largest type scale in
|
|
40
|
+
* the consumer's design system. Use for one-per-page copy.
|
|
41
|
+
*/
|
|
42
|
+
DISPLAY = "display",
|
|
43
|
+
/**
|
|
44
|
+
* Section / sub-section titles. The default — most marketing-site
|
|
45
|
+
* headings are headline-scale, not display-scale.
|
|
46
|
+
*/
|
|
47
|
+
HEADLINE = "headline",
|
|
48
|
+
/**
|
|
49
|
+
* In-section group titles (eg. pricing tier names, FAQ question
|
|
50
|
+
* cards). Smaller than headline, structurally a heading.
|
|
51
|
+
*/
|
|
52
|
+
TITLE = "title"
|
|
53
|
+
}
|
|
54
|
+
export interface WebsiteHeadingProps {
|
|
55
|
+
/** Required heading level (1–6). Drives the rendered tag. */
|
|
56
|
+
level: WebsiteHeadingLevel;
|
|
57
|
+
/** Visual variant. Defaults to `HEADLINE` (the most common case). */
|
|
58
|
+
variant?: WebsiteHeadingVariant;
|
|
59
|
+
/** Forwarded to the heading element. */
|
|
60
|
+
className?: string;
|
|
61
|
+
/** Forwarded to the heading element for one-off inline tweaks. */
|
|
62
|
+
style?: CSSProperties;
|
|
63
|
+
/** Forwarded id (for anchor links to specific headings). */
|
|
64
|
+
id?: string;
|
|
65
|
+
children: ReactNode;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Minimal placeholder. Renders the correct semantic tag with no
|
|
69
|
+
* visual styling beyond a `data-website-primitive="heading"`
|
|
70
|
+
* attribute that the consumer's tailwind config / global CSS / the
|
|
71
|
+
* override implementation can hook into.
|
|
72
|
+
*/
|
|
73
|
+
export declare function WebsiteHeading({ level, variant, className, style, id, children, }: WebsiteHeadingProps): ReactNode;
|
|
74
|
+
export declare namespace WebsiteHeading {
|
|
75
|
+
var displayName: string;
|
|
76
|
+
}
|
|
77
|
+
/** @wildo_source:part:end saas.website.primitives.heading */
|
|
78
|
+
//# sourceMappingURL=WebsiteHeading.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsiteHeading.d.ts","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteHeading.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAExD,oBAAY,qBAAqB;IAC/B;;;OAGG;IACH,OAAO,YAAY;IACnB;;;OAGG;IACH,QAAQ,aAAa;IACrB;;;OAGG;IACH,KAAK,UAAU;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,KAAK,EAAE,mBAAmB,CAAC;IAC3B,qEAAqE;IACrE,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,4DAA4D;IAC5D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,OAAwC,EACxC,SAAS,EACT,KAAK,EACL,EAAE,EACF,QAAQ,GACT,EAAE,mBAAmB,GAAG,SAAS,CAUjC;yBAjBe,cAAc;;;AAmB9B,6DAA6D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export var WebsiteHeadingVariant;
|
|
3
|
+
(function (WebsiteHeadingVariant) {
|
|
4
|
+
/**
|
|
5
|
+
* Hero / above-the-fold sizes. Maps to the largest type scale in
|
|
6
|
+
* the consumer's design system. Use for one-per-page copy.
|
|
7
|
+
*/
|
|
8
|
+
WebsiteHeadingVariant["DISPLAY"] = "display";
|
|
9
|
+
/**
|
|
10
|
+
* Section / sub-section titles. The default — most marketing-site
|
|
11
|
+
* headings are headline-scale, not display-scale.
|
|
12
|
+
*/
|
|
13
|
+
WebsiteHeadingVariant["HEADLINE"] = "headline";
|
|
14
|
+
/**
|
|
15
|
+
* In-section group titles (eg. pricing tier names, FAQ question
|
|
16
|
+
* cards). Smaller than headline, structurally a heading.
|
|
17
|
+
*/
|
|
18
|
+
WebsiteHeadingVariant["TITLE"] = "title";
|
|
19
|
+
})(WebsiteHeadingVariant || (WebsiteHeadingVariant = {}));
|
|
20
|
+
/**
|
|
21
|
+
* Minimal placeholder. Renders the correct semantic tag with no
|
|
22
|
+
* visual styling beyond a `data-website-primitive="heading"`
|
|
23
|
+
* attribute that the consumer's tailwind config / global CSS / the
|
|
24
|
+
* override implementation can hook into.
|
|
25
|
+
*/
|
|
26
|
+
export function WebsiteHeading({ level, variant = WebsiteHeadingVariant.HEADLINE, className, style, id, children, }) {
|
|
27
|
+
const Tag = `h${level}`;
|
|
28
|
+
const attrs = {
|
|
29
|
+
'data-website-primitive': 'heading',
|
|
30
|
+
'data-website-heading-variant': variant,
|
|
31
|
+
};
|
|
32
|
+
if (className !== undefined)
|
|
33
|
+
attrs.className = className;
|
|
34
|
+
if (style !== undefined)
|
|
35
|
+
attrs.style = style;
|
|
36
|
+
if (id !== undefined)
|
|
37
|
+
attrs.id = id;
|
|
38
|
+
return _jsx(Tag, { ...attrs, children: children });
|
|
39
|
+
}
|
|
40
|
+
WebsiteHeading.displayName = 'WebsiteHeading';
|
|
41
|
+
//# sourceMappingURL=WebsiteHeading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsiteHeading.js","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteHeading.tsx"],"names":[],"mappings":";AAsCA,MAAM,CAAN,IAAY,qBAgBX;AAhBD,WAAY,qBAAqB;IAC/B;;;OAGG;IACH,4CAAmB,CAAA;IACnB;;;OAGG;IACH,8CAAqB,CAAA;IACrB;;;OAGG;IACH,wCAAe,CAAA;AACjB,CAAC,EAhBW,qBAAqB,KAArB,qBAAqB,QAgBhC;AAgBD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,KAAK,EACL,OAAO,GAAG,qBAAqB,CAAC,QAAQ,EACxC,SAAS,EACT,KAAK,EACL,EAAE,EACF,QAAQ,GACY;IACpB,MAAM,GAAG,GAAG,IAAI,KAAK,EAA6C,CAAC;IACnE,MAAM,KAAK,GAA4B;QACrC,wBAAwB,EAAE,SAAS;QACnC,8BAA8B,EAAE,OAAO;KACxC,CAAC;IACF,IAAI,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACzD,IAAI,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC7C,IAAI,EAAE,KAAK,SAAS;QAAE,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;IACpC,OAAO,KAAC,GAAG,OAAK,KAAK,YAAG,QAAQ,GAAO,CAAC;AAC1C,CAAC;AACD,cAAc,CAAC,WAAW,GAAG,gBAAgB,CAAC","sourcesContent":["import React, { type CSSProperties, type ReactNode } from 'react';\n\n/**\n * @wildo_source:part:start saas.website.primitives.heading facet:layer:components facet:family:website\n *\n * `WebsiteHeading` — L1 marketing-site heading primitive.\n *\n * **Status (Phase 2 / D18 — option D)**: minimal, self-contained\n * placeholder. The framework defaults are intentionally bare so\n * consumers MUST override at the L1 boundary by barrel-re-exporting\n * a styled variant from their app's\n * `app/website/primitives/WebsiteHeading.tsx`. The Phase 6\n * dogfood will validate the override workflow and (deferred to\n * Phase 6) decide whether to promote these to the\n * `ComponentRegistryService` registry shared with `saas-frontend-lib`.\n *\n * **Why these primitives ship at all** (vs. asking consumers to\n * author every primitive themselves): consistency of the section\n * authoring surface. Section authors call `<WebsiteHeading\n * level={1}>` from `defineWebsiteSection`'d components without\n * having to know which app they're rendering in — the override\n * happens at the consumer barrel level transparently.\n *\n * **Why `level` is a discrete prop (1–6)**: heading hierarchy is\n * critical for SEO and accessibility, and a free-string `as` prop\n * makes it trivial for a copy-paste section to render `<h2>`s where\n * the page outline expects `<h1>`. Constraining `level` to a numeric\n * union keeps the section author honest about the document outline.\n *\n * **Why `variant` (display vs. headline) is shipped here**:\n * marketing-site headings need a visual scale that's distinct from\n * the in-app heading scale (display sizes for hero, headline sizes\n * for section titles). Even as a placeholder, the variant slot\n * exists so section authors don't have to invent the prop ad-hoc;\n * the override implementation can deliver the actual visual scale.\n */\nexport type WebsiteHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\nexport enum WebsiteHeadingVariant {\n /**\n * Hero / above-the-fold sizes. Maps to the largest type scale in\n * the consumer's design system. Use for one-per-page copy.\n */\n DISPLAY = 'display',\n /**\n * Section / sub-section titles. The default — most marketing-site\n * headings are headline-scale, not display-scale.\n */\n HEADLINE = 'headline',\n /**\n * In-section group titles (eg. pricing tier names, FAQ question\n * cards). Smaller than headline, structurally a heading.\n */\n TITLE = 'title',\n}\n\nexport interface WebsiteHeadingProps {\n /** Required heading level (1–6). Drives the rendered tag. */\n level: WebsiteHeadingLevel;\n /** Visual variant. Defaults to `HEADLINE` (the most common case). */\n variant?: WebsiteHeadingVariant;\n /** Forwarded to the heading element. */\n className?: string;\n /** Forwarded to the heading element for one-off inline tweaks. */\n style?: CSSProperties;\n /** Forwarded id (for anchor links to specific headings). */\n id?: string;\n children: ReactNode;\n}\n\n/**\n * Minimal placeholder. Renders the correct semantic tag with no\n * visual styling beyond a `data-website-primitive=\"heading\"`\n * attribute that the consumer's tailwind config / global CSS / the\n * override implementation can hook into.\n */\nexport function WebsiteHeading({\n level,\n variant = WebsiteHeadingVariant.HEADLINE,\n className,\n style,\n id,\n children,\n}: WebsiteHeadingProps): ReactNode {\n const Tag = `h${level}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n const attrs: Record<string, unknown> = {\n 'data-website-primitive': 'heading',\n 'data-website-heading-variant': variant,\n };\n if (className !== undefined) attrs.className = className;\n if (style !== undefined) attrs.style = style;\n if (id !== undefined) attrs.id = id;\n return <Tag {...attrs}>{children}</Tag>;\n}\nWebsiteHeading.displayName = 'WebsiteHeading';\n/** @wildo_source:part:end saas.website.primitives.heading */\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @wildo_source:part:start saas.website.primitives.image facet:layer:components facet:family:website
|
|
4
|
+
*
|
|
5
|
+
* `WebsiteImage` — L1 marketing-site image primitive.
|
|
6
|
+
*
|
|
7
|
+
* **Status (Phase 2 / D18)**: minimal placeholder around a plain
|
|
8
|
+
* `<img>` with sensible accessibility / performance defaults
|
|
9
|
+
* (`alt` is REQUIRED, `loading` defaults to `'lazy'`, `decoding`
|
|
10
|
+
* defaults to `'async'`). Production sites override at the L1
|
|
11
|
+
* boundary to wire in Astro's `<Image>` component (or a Next/CDN
|
|
12
|
+
* variant) for automatic format / width / DPR handling.
|
|
13
|
+
*
|
|
14
|
+
* **Why `alt` is REQUIRED at the type level**: marketing imagery
|
|
15
|
+
* is a public-facing surface where missing alt text directly hurts
|
|
16
|
+
* SEO scoring AND blocks screen-reader access. Forcing the section
|
|
17
|
+
* author to author an `alt` (even an empty `''` for purely
|
|
18
|
+
* decorative images) makes the accessibility decision explicit at
|
|
19
|
+
* the call site.
|
|
20
|
+
*
|
|
21
|
+
* **Why `width` / `height` are REQUIRED**: cumulative-layout-shift
|
|
22
|
+
* is a Core Web Vital that marketing pages are routinely scored
|
|
23
|
+
* against. Without intrinsic dimensions, every image on the page
|
|
24
|
+
* triggers layout shift on load. Forcing the dimensions at the call
|
|
25
|
+
* site keeps CLS near zero by default — the override implementation
|
|
26
|
+
* can swap to Astro's `<Image>` (which encodes the same dimensions
|
|
27
|
+
* differently) without changing the section-author API.
|
|
28
|
+
*
|
|
29
|
+
* **Why no `priority` / `fetchpriority` prop here**: Astro's
|
|
30
|
+
* `<Image>` exposes its own `loading="eager"` / `priority` props
|
|
31
|
+
* with implementation-specific semantics, and a placeholder-level
|
|
32
|
+
* `priority` would be either a lie (does nothing without the Astro
|
|
33
|
+
* adapter) or a footgun (forces the override to honor a contract
|
|
34
|
+
* it can't always meet). The override implementation is the right
|
|
35
|
+
* place to expose this.
|
|
36
|
+
*/
|
|
37
|
+
export interface WebsiteImageProps {
|
|
38
|
+
src: string;
|
|
39
|
+
/**
|
|
40
|
+
* REQUIRED. Use `alt=""` (empty string) for purely decorative
|
|
41
|
+
* images — `null` / `undefined` is rejected at compile time so
|
|
42
|
+
* the accessibility decision is always explicit.
|
|
43
|
+
*/
|
|
44
|
+
alt: string;
|
|
45
|
+
/**
|
|
46
|
+
* REQUIRED. Intrinsic image width in CSS pixels (eg. `1200`).
|
|
47
|
+
*/
|
|
48
|
+
width: number;
|
|
49
|
+
/**
|
|
50
|
+
* REQUIRED. Intrinsic image height in CSS pixels (eg. `630`).
|
|
51
|
+
*/
|
|
52
|
+
height: number;
|
|
53
|
+
/**
|
|
54
|
+
* `'lazy'` (default) defers loading until the image is near the
|
|
55
|
+
* viewport. Set to `'eager'` for above-the-fold hero images.
|
|
56
|
+
*/
|
|
57
|
+
loading?: 'lazy' | 'eager';
|
|
58
|
+
/**
|
|
59
|
+
* `'async'` (default) lets the browser decode the image off the
|
|
60
|
+
* main thread. Set to `'sync'` only for above-the-fold hero
|
|
61
|
+
* images that need to paint immediately.
|
|
62
|
+
*/
|
|
63
|
+
decoding?: 'async' | 'sync' | 'auto';
|
|
64
|
+
className?: string;
|
|
65
|
+
style?: CSSProperties;
|
|
66
|
+
id?: string;
|
|
67
|
+
}
|
|
68
|
+
export declare function WebsiteImage({ src, alt, width, height, loading, decoding, className, style, id, }: WebsiteImageProps): ReactNode;
|
|
69
|
+
export declare namespace WebsiteImage {
|
|
70
|
+
var displayName: string;
|
|
71
|
+
}
|
|
72
|
+
/** @wildo_source:part:end saas.website.primitives.image */
|
|
73
|
+
//# sourceMappingURL=WebsiteImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsiteImage.d.ts","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteImage.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,GAAG,EACH,KAAK,EACL,MAAM,EACN,OAAgB,EAChB,QAAkB,EAClB,SAAS,EACT,KAAK,EACL,EAAE,GACH,EAAE,iBAAiB,GAAG,SAAS,CAc/B;yBAxBe,YAAY;;;AA0B5B,2DAA2D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export function WebsiteImage({ src, alt, width, height, loading = 'lazy', decoding = 'async', className, style, id, }) {
|
|
3
|
+
const attrs = {
|
|
4
|
+
'data-website-primitive': 'image',
|
|
5
|
+
src,
|
|
6
|
+
alt,
|
|
7
|
+
width,
|
|
8
|
+
height,
|
|
9
|
+
loading,
|
|
10
|
+
decoding,
|
|
11
|
+
};
|
|
12
|
+
if (className !== undefined)
|
|
13
|
+
attrs.className = className;
|
|
14
|
+
if (style !== undefined)
|
|
15
|
+
attrs.style = style;
|
|
16
|
+
if (id !== undefined)
|
|
17
|
+
attrs.id = id;
|
|
18
|
+
return _jsx("img", { ...attrs });
|
|
19
|
+
}
|
|
20
|
+
WebsiteImage.displayName = 'WebsiteImage';
|
|
21
|
+
//# sourceMappingURL=WebsiteImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsiteImage.js","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteImage.tsx"],"names":[],"mappings":";AAqEA,MAAM,UAAU,YAAY,CAAC,EAC3B,GAAG,EACH,GAAG,EACH,KAAK,EACL,MAAM,EACN,OAAO,GAAG,MAAM,EAChB,QAAQ,GAAG,OAAO,EAClB,SAAS,EACT,KAAK,EACL,EAAE,GACgB;IAClB,MAAM,KAAK,GAA4B;QACrC,wBAAwB,EAAE,OAAO;QACjC,GAAG;QACH,GAAG;QACH,KAAK;QACL,MAAM;QACN,OAAO;QACP,QAAQ;KACT,CAAC;IACF,IAAI,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACzD,IAAI,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC7C,IAAI,EAAE,KAAK,SAAS;QAAE,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;IACpC,OAAO,iBAAS,KAAK,GAAI,CAAC;AAC5B,CAAC;AACD,YAAY,CAAC,WAAW,GAAG,cAAc,CAAC","sourcesContent":["import React, { type CSSProperties, type ReactNode } from 'react';\n\n/**\n * @wildo_source:part:start saas.website.primitives.image facet:layer:components facet:family:website\n *\n * `WebsiteImage` — L1 marketing-site image primitive.\n *\n * **Status (Phase 2 / D18)**: minimal placeholder around a plain\n * `<img>` with sensible accessibility / performance defaults\n * (`alt` is REQUIRED, `loading` defaults to `'lazy'`, `decoding`\n * defaults to `'async'`). Production sites override at the L1\n * boundary to wire in Astro's `<Image>` component (or a Next/CDN\n * variant) for automatic format / width / DPR handling.\n *\n * **Why `alt` is REQUIRED at the type level**: marketing imagery\n * is a public-facing surface where missing alt text directly hurts\n * SEO scoring AND blocks screen-reader access. Forcing the section\n * author to author an `alt` (even an empty `''` for purely\n * decorative images) makes the accessibility decision explicit at\n * the call site.\n *\n * **Why `width` / `height` are REQUIRED**: cumulative-layout-shift\n * is a Core Web Vital that marketing pages are routinely scored\n * against. Without intrinsic dimensions, every image on the page\n * triggers layout shift on load. Forcing the dimensions at the call\n * site keeps CLS near zero by default — the override implementation\n * can swap to Astro's `<Image>` (which encodes the same dimensions\n * differently) without changing the section-author API.\n *\n * **Why no `priority` / `fetchpriority` prop here**: Astro's\n * `<Image>` exposes its own `loading=\"eager\"` / `priority` props\n * with implementation-specific semantics, and a placeholder-level\n * `priority` would be either a lie (does nothing without the Astro\n * adapter) or a footgun (forces the override to honor a contract\n * it can't always meet). The override implementation is the right\n * place to expose this.\n */\nexport interface WebsiteImageProps {\n src: string;\n /**\n * REQUIRED. Use `alt=\"\"` (empty string) for purely decorative\n * images — `null` / `undefined` is rejected at compile time so\n * the accessibility decision is always explicit.\n */\n alt: string;\n /**\n * REQUIRED. Intrinsic image width in CSS pixels (eg. `1200`).\n */\n width: number;\n /**\n * REQUIRED. Intrinsic image height in CSS pixels (eg. `630`).\n */\n height: number;\n /**\n * `'lazy'` (default) defers loading until the image is near the\n * viewport. Set to `'eager'` for above-the-fold hero images.\n */\n loading?: 'lazy' | 'eager';\n /**\n * `'async'` (default) lets the browser decode the image off the\n * main thread. Set to `'sync'` only for above-the-fold hero\n * images that need to paint immediately.\n */\n decoding?: 'async' | 'sync' | 'auto';\n className?: string;\n style?: CSSProperties;\n id?: string;\n}\n\nexport function WebsiteImage({\n src,\n alt,\n width,\n height,\n loading = 'lazy',\n decoding = 'async',\n className,\n style,\n id,\n}: WebsiteImageProps): ReactNode {\n const attrs: Record<string, unknown> = {\n 'data-website-primitive': 'image',\n src,\n alt,\n width,\n height,\n loading,\n decoding,\n };\n if (className !== undefined) attrs.className = className;\n if (style !== undefined) attrs.style = style;\n if (id !== undefined) attrs.id = id;\n return <img {...attrs} />;\n}\nWebsiteImage.displayName = 'WebsiteImage';\n/** @wildo_source:part:end saas.website.primitives.image */\n"]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
import { type WebsiteButtonSize, type WebsiteButtonVariant } from './WebsiteButton';
|
|
3
|
+
/**
|
|
4
|
+
* @wildo_source:part:start saas.website.primitives.internal-button facet:layer:components facet:family:website
|
|
5
|
+
*
|
|
6
|
+
* `WebsiteInternalButton` — L1 marketing-site CTA primitive for
|
|
7
|
+
* INTERNAL anchor-mode buttons (CTAs that navigate to another route
|
|
8
|
+
* served by the same Astro build, e.g. "Get in touch" → `/contact`).
|
|
9
|
+
*
|
|
10
|
+
* **The architectural problem this solves** (Phase 6 fourth audit fix
|
|
11
|
+
* H-Φ): the H-β fix shipped `WebsiteInternalLink` for header/footer
|
|
12
|
+
* navigation links but `WebsiteButton` consumers in section bodies
|
|
13
|
+
* (hero / features / pricing / contact) continued to write
|
|
14
|
+
* `<WebsiteButton href="/contact">` with raw locale-neutral paths. On
|
|
15
|
+
* `/fr/…` pages those CTAs navigated to the EN-default `/contact`
|
|
16
|
+
* URL — exactly the cross-locale leak H-β was meant to kill, just on
|
|
17
|
+
* the page body instead of the chrome. Authors had to know the
|
|
18
|
+
* routing rule and call `buildLocalizedRoutePath` manually on every
|
|
19
|
+
* CTA they shipped, and the audit confirmed they did not.
|
|
20
|
+
*
|
|
21
|
+
* **Why a parallel primitive** (mirrors the H-β reasoning, NOT a
|
|
22
|
+
* `routePath` flag on `WebsiteButton`):
|
|
23
|
+
* 1. The two primitives have different authoring contracts —
|
|
24
|
+
* `WebsiteButton`'s `href` is a fully-qualified URL the author
|
|
25
|
+
* already commits to (or an anchor `#section`, or external);
|
|
26
|
+
* this primitive's `routePath` is a raw locale-neutral path that
|
|
27
|
+
* the framework prefixes. Mixing both shapes behind one prop
|
|
28
|
+
* forces the author to think about a routing rule on every CTA
|
|
29
|
+
* they place; mixing them without a type-system signal invites
|
|
30
|
+
* the wrong shape on the wrong branch.
|
|
31
|
+
* 2. Internal CTAs REQUIRE the runtime context; external/anchor
|
|
32
|
+
* CTAs do not. Forcing every external-link `WebsiteButton`
|
|
33
|
+
* consumer to wrap in `<WebsiteRuntimeContextProvider>` is wrong.
|
|
34
|
+
* Two primitives keep the dependency surface honest.
|
|
35
|
+
* 3. Symmetric with `WebsiteInternalLink` — section authors learn
|
|
36
|
+
* one rule ("use the `Internal` variant for app-served paths,
|
|
37
|
+
* the bare variant for external/scheme/anchor URLs") and apply
|
|
38
|
+
* it identically to both link and button shapes.
|
|
39
|
+
*
|
|
40
|
+
* **Button-only render mode**: this primitive is anchor-mode-only by
|
|
41
|
+
* construction (every internal target is a route → an anchor element
|
|
42
|
+
* with appropriate href). Consumers who need a real `<button>` (no
|
|
43
|
+
* navigation, just an `onClick` handler) keep using `<WebsiteButton>`
|
|
44
|
+
* directly — there is no `routePath`-based real-button concept.
|
|
45
|
+
*
|
|
46
|
+
* **Anchor-only links** (`routePath="#features"`) and URL schemes
|
|
47
|
+
* (`mailto:`/`tel:`) are rejected at runtime: those targets do NOT
|
|
48
|
+
* benefit from locale prefixing, and surfacing them through this
|
|
49
|
+
* primitive would invite the SAME confusion that motivated splitting
|
|
50
|
+
* `WebsiteInternalLink` from `WebsiteLink` in the first place. Use
|
|
51
|
+
* `<WebsiteButton href="..." external={true}>` for those cases.
|
|
52
|
+
*
|
|
53
|
+
* **Boundary**: this component MUST stay in the React-island bundle
|
|
54
|
+
* tier (`components/low-level/`). It depends on `useWebsiteRuntime`
|
|
55
|
+
* (which throws when called outside a `<WebsiteRuntimeContextProvider>`)
|
|
56
|
+
* — the throw is the contract that prevents body CTAs from being
|
|
57
|
+
* rendered outside a bridged page accidentally.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* // Hero CTA — auto-prefixes the active locale
|
|
62
|
+
* // (`/contact` on EN pages, `/fr/contact` on FR pages):
|
|
63
|
+
* <WebsiteInternalButton routePath="/contact" variant={WebsiteButtonVariant.PRIMARY}>
|
|
64
|
+
* {useWebsiteLabel('cta.primary')}
|
|
65
|
+
* </WebsiteInternalButton>
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export interface WebsiteInternalButtonProps {
|
|
69
|
+
/**
|
|
70
|
+
* The locale-NEUTRAL route path. Must match a value the consumer's
|
|
71
|
+
* Astro build serves (typically a `WebsitePageManifest.routePath`).
|
|
72
|
+
* MUST start with `/` — anchor-only `#section` and URL schemes
|
|
73
|
+
* (`mailto:` / `tel:`) are rejected (use `<WebsiteButton href={...}>`
|
|
74
|
+
* for those cases).
|
|
75
|
+
*/
|
|
76
|
+
routePath: string;
|
|
77
|
+
variant?: WebsiteButtonVariant;
|
|
78
|
+
size?: WebsiteButtonSize;
|
|
79
|
+
className?: string;
|
|
80
|
+
style?: CSSProperties;
|
|
81
|
+
id?: string;
|
|
82
|
+
ariaLabel?: string;
|
|
83
|
+
children: ReactNode;
|
|
84
|
+
}
|
|
85
|
+
export declare function WebsiteInternalButton({ routePath, variant, size, className, style, id, ariaLabel, children, }: WebsiteInternalButtonProps): ReactNode;
|
|
86
|
+
export declare namespace WebsiteInternalButton {
|
|
87
|
+
var displayName: string;
|
|
88
|
+
}
|
|
89
|
+
/** @wildo_source:part:end saas.website.primitives.internal-button */
|
|
90
|
+
//# sourceMappingURL=WebsiteInternalButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebsiteInternalButton.d.ts","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteInternalButton.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOlE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,iBAAiB,CAAC;AAmBzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,OAAO,EACP,IAAI,EACJ,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,EACT,QAAQ,GACT,EAAE,0BAA0B,GAAG,SAAS,CA+CxC;yBAxDe,qBAAqB;;;AA0DrC,qEAAqE"}
|