create-tanqory-theme 0.0.0-stage → 0.2.3
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 +21 -0
- package/README.md +55 -2
- package/bin/create-tanqory-theme.mjs +13 -0
- package/lib/agents.mjs +118 -0
- package/lib/create.mjs +245 -0
- package/package.json +39 -4
- package/templates/blank/README.md +13 -0
- package/templates/blank/config/settings.json +3 -0
- package/templates/blank/locales/en.json +22 -0
- package/templates/blank/locales/th.json +22 -0
- package/templates/blank/package.json +34 -0
- package/templates/blank/regions/footer.json +35 -0
- package/templates/blank/regions/header.json +13 -0
- package/templates/blank/scripts/build.mjs +193 -0
- package/templates/blank/scripts/probe.ts +4 -0
- package/templates/blank/src/bundle.ts +15 -0
- package/templates/blank/src/components/parts.tsx +32 -0
- package/templates/blank/src/entry.client.tsx +6 -0
- package/templates/blank/src/entry.server.tsx +13 -0
- package/templates/blank/src/sections/chrome.tsx +132 -0
- package/templates/blank/src/sections/commerce.tsx +242 -0
- package/templates/blank/src/sections/content.tsx +111 -0
- package/templates/blank/src/sections/editorial.tsx +107 -0
- package/templates/blank/src/settings.ts +15 -0
- package/templates/blank/src/styles/theme.css +195 -0
- package/templates/blank/src/templates.ts +14 -0
- package/templates/blank/src/theme.tsx +76 -0
- package/templates/blank/template.json +24 -0
- package/templates/blank/templates/404.json +14 -0
- package/templates/blank/templates/account.json +14 -0
- package/templates/blank/templates/article.json +14 -0
- package/templates/blank/templates/blog.json +14 -0
- package/templates/blank/templates/cart.json +14 -0
- package/templates/blank/templates/collection.json +14 -0
- package/templates/blank/templates/index.json +36 -0
- package/templates/blank/templates/page.contact.json +18 -0
- package/templates/blank/templates/page.json +14 -0
- package/templates/blank/templates/product.json +18 -0
- package/templates/blank/templates/search.json +14 -0
- package/templates/blank/tests/theme.test.ts +49 -0
- package/templates/blank/tsconfig.json +17 -0
- package/templates/blank/vite.client.config.ts +17 -0
- package/templates/blank/vite.probe.config.ts +16 -0
- package/templates/blank/vite.server.config.ts +32 -0
- package/templates/blank/vitest.config.ts +9 -0
- package/templates/common/.claude/settings.json +8 -0
- package/templates/common/.codex/config.toml +4 -0
- package/templates/common/.gemini/settings.json +12 -0
- package/templates/common/.github/workflows/theme-check.yml +44 -0
- package/templates/common/.mcp.json +12 -0
- package/templates/common/.vscode/mcp.json +9 -0
- package/templates/common/_gitignore +9 -0
- package/templates/common/scripts/check.mjs +44 -0
- package/templates/common/scripts/dev.mjs +30 -0
- package/templates/common/tanqory.config.json +6 -0
- package/templates/nova/.gitattributes +3 -0
- package/templates/nova/.tanqory/contracts/LOCK.json +66 -0
- package/templates/nova/.tanqory/contracts/nova-01.json +1092 -0
- package/templates/nova/.tanqory/contracts/nova-12A.json +2674 -0
- package/templates/nova/.tanqory/contracts/nova-12B.json +2285 -0
- package/templates/nova/.tanqory/contracts/nova-12C.json +2848 -0
- package/templates/nova/.tanqory/contracts/nova-12D.json +3039 -0
- package/templates/nova/.tanqory/contracts/nova-12E.json +1473 -0
- package/templates/nova/.tanqory/contracts/nova-12F.json +1670 -0
- package/templates/nova/.tanqory/contracts/nova-12G.json +1661 -0
- package/templates/nova/.tanqory/contracts/nova-13.json +301 -0
- package/templates/nova/.tanqory/contracts/nova-14.json +172 -0
- package/templates/nova/.tanqory/legacy-settings.json +1121 -0
- package/templates/nova/README.md +150 -0
- package/templates/nova/_gitignore +28 -0
- package/templates/nova/assets/ai-tokens.css +6 -0
- package/templates/nova/assets/starter/starter-art-1200x800-0b773ac4.svg +1 -0
- package/templates/nova/assets/starter/starter-art-1200x900-59600290.svg +1 -0
- package/templates/nova/assets/starter/starter-art-1200x900-c549d496.svg +1 -0
- package/templates/nova/assets/starter/starter-art-1600x900-8f979fcb.svg +1 -0
- package/templates/nova/assets/starter/starter-art-2100x900-cbb71bfd.svg +1 -0
- package/templates/nova/config/legacy-settings.json +438 -0
- package/templates/nova/config/promotion-popup.schema.ts +29 -0
- package/templates/nova/config/settings.json +23 -0
- package/templates/nova/config/settings.schema.ts +231 -0
- package/templates/nova/entry.abi.tsx +27 -0
- package/templates/nova/groups/footer.json +39 -0
- package/templates/nova/groups/header.json +11 -0
- package/templates/nova/lib/abi/abi.css +41 -0
- package/templates/nova/lib/bundle-core.ts +35 -0
- package/templates/nova/lib/bundle.client.ts +15 -0
- package/templates/nova/lib/bundle.ts +15 -0
- package/templates/nova/lib/legacy-settings.ts +104 -0
- package/templates/nova/locales/ar.json +590 -0
- package/templates/nova/locales/en.json +590 -0
- package/templates/nova/locales/th.json +590 -0
- package/templates/nova/main.abi.tsx +12 -0
- package/templates/nova/package.json +44 -0
- package/templates/nova/scripts/abi/build.mjs +145 -0
- package/templates/nova/scripts/abi/check-content.mjs +99 -0
- package/templates/nova/scripts/abi/jcs.mjs +27 -0
- package/templates/nova/scripts/abi/local-host.mjs +294 -0
- package/templates/nova/scripts/abi/manifest.mjs +392 -0
- package/templates/nova/scripts/abi/starter-assets.mjs +32 -0
- package/templates/nova/scripts/compiler/checks/check-a11y.mjs +88 -0
- package/templates/nova/scripts/compiler/checks/check-layout-sanity.mjs +169 -0
- package/templates/nova/scripts/compiler/checks/check-page-headings.mjs +67 -0
- package/templates/nova/scripts/compiler/checks/check-product-jsonld.mjs +80 -0
- package/templates/nova/scripts/compiler/checks/theme-spec/check.mjs +88 -0
- package/templates/nova/scripts/compiler/contracts/extract.mjs +188 -0
- package/templates/nova/scripts/compiler/contracts/index.ts +125 -0
- package/templates/nova/scripts/compiler/contracts/validate.ts +347 -0
- package/templates/nova/scripts/compiler/manifest/gen-manifest.mjs +156 -0
- package/templates/nova/scripts/compiler/manifest/manifest-entry.ts +386 -0
- package/templates/nova/scripts/compiler/manifest/manifest-sections.ts +247 -0
- package/templates/nova/scripts/compiler/migrate/migrate-content.mjs +171 -0
- package/templates/nova/scripts/compiler/migrate/migrate-groups.mjs +159 -0
- package/templates/nova/scripts/parity/case-shim.ts +14 -0
- package/templates/nova/scripts/parity/emit.ts +206 -0
- package/templates/nova/scripts/parity/index.html +12 -0
- package/templates/nova/scripts/parity/main.tsx +23 -0
- package/templates/nova/scripts/parity/pages.tsx +123 -0
- package/templates/nova/scripts/parity/vite.config.ts +29 -0
- package/templates/nova/src/components/base/Accordion.css +20 -0
- package/templates/nova/src/components/base/Accordion.tsx +50 -0
- package/templates/nova/src/components/base/Badge.css +17 -0
- package/templates/nova/src/components/base/Badge.tsx +26 -0
- package/templates/nova/src/components/base/Button.css +73 -0
- package/templates/nova/src/components/base/Button.tsx +64 -0
- package/templates/nova/src/components/base/Checkbox.tsx +18 -0
- package/templates/nova/src/components/base/Chip.css +20 -0
- package/templates/nova/src/components/base/Chip.tsx +33 -0
- package/templates/nova/src/components/base/Divider.css +6 -0
- package/templates/nova/src/components/base/Divider.tsx +28 -0
- package/templates/nova/src/components/base/IconButton.css +34 -0
- package/templates/nova/src/components/base/IconButton.tsx +41 -0
- package/templates/nova/src/components/base/Input.css +21 -0
- package/templates/nova/src/components/base/Input.tsx +24 -0
- package/templates/nova/src/components/base/Link.css +15 -0
- package/templates/nova/src/components/base/Link.tsx +23 -0
- package/templates/nova/src/components/base/Radio.tsx +13 -0
- package/templates/nova/src/components/base/Select.css +18 -0
- package/templates/nova/src/components/base/Select.tsx +34 -0
- package/templates/nova/src/components/base/Skeleton.css +17 -0
- package/templates/nova/src/components/base/Skeleton.tsx +23 -0
- package/templates/nova/src/components/base/Spinner.css +13 -0
- package/templates/nova/src/components/base/Spinner.tsx +8 -0
- package/templates/nova/src/components/base/Switch.tsx +16 -0
- package/templates/nova/src/components/base/Tabs.css +24 -0
- package/templates/nova/src/components/base/Tabs.tsx +61 -0
- package/templates/nova/src/components/base/Textarea.css +1 -0
- package/templates/nova/src/components/base/Textarea.tsx +8 -0
- package/templates/nova/src/components/base/choice-props.ts +9 -0
- package/templates/nova/src/components/base/choice.css +69 -0
- package/templates/nova/src/components/commerce/AddToCart.css +4 -0
- package/templates/nova/src/components/commerce/AddToCart.tsx +77 -0
- package/templates/nova/src/components/commerce/CartLine.css +26 -0
- package/templates/nova/src/components/commerce/CartLine.tsx +82 -0
- package/templates/nova/src/components/commerce/CartSummary.css +23 -0
- package/templates/nova/src/components/commerce/CartSummary.tsx +120 -0
- package/templates/nova/src/components/commerce/CollectionCard.css +66 -0
- package/templates/nova/src/components/commerce/CollectionCard.tsx +57 -0
- package/templates/nova/src/components/commerce/ComparisonTable.css +33 -0
- package/templates/nova/src/components/commerce/ComparisonTable.tsx +113 -0
- package/templates/nova/src/components/commerce/EarnHint.css +3 -0
- package/templates/nova/src/components/commerce/EarnHint.tsx +31 -0
- package/templates/nova/src/components/commerce/Hotspot.css +16 -0
- package/templates/nova/src/components/commerce/Hotspot.tsx +64 -0
- package/templates/nova/src/components/commerce/ListingParts.css +79 -0
- package/templates/nova/src/components/commerce/ListingParts.tsx +211 -0
- package/templates/nova/src/components/commerce/LookItem.css +19 -0
- package/templates/nova/src/components/commerce/LookItem.tsx +41 -0
- package/templates/nova/src/components/commerce/MiniCartLine.css +20 -0
- package/templates/nova/src/components/commerce/MiniCartLine.tsx +93 -0
- package/templates/nova/src/components/commerce/PaymentMark.css +2 -0
- package/templates/nova/src/components/commerce/PaymentMark.tsx +55 -0
- package/templates/nova/src/components/commerce/Price.css +27 -0
- package/templates/nova/src/components/commerce/Price.tsx +55 -0
- package/templates/nova/src/components/commerce/ProductCard.css +66 -0
- package/templates/nova/src/components/commerce/ProductCard.tsx +117 -0
- package/templates/nova/src/components/commerce/ProductGallery.css +72 -0
- package/templates/nova/src/components/commerce/ProductGallery.tsx +98 -0
- package/templates/nova/src/components/commerce/QuantitySelector.css +23 -0
- package/templates/nova/src/components/commerce/QuantitySelector.tsx +45 -0
- package/templates/nova/src/components/commerce/Reviews.css +34 -0
- package/templates/nova/src/components/commerce/Reviews.tsx +112 -0
- package/templates/nova/src/components/commerce/Stars.css +7 -0
- package/templates/nova/src/components/commerce/Stars.tsx +38 -0
- package/templates/nova/src/components/commerce/VariantPicker.css +31 -0
- package/templates/nova/src/components/commerce/VariantPicker.tsx +122 -0
- package/templates/nova/src/components/commerce/blocks/Badge.css +6 -0
- package/templates/nova/src/components/commerce/blocks/Badge.tsx +33 -0
- package/templates/nova/src/components/commerce/blocks/PaymentIcons.tsx +43 -0
- package/templates/nova/src/components/commerce/blocks/Swatches.tsx +17 -0
- package/templates/nova/src/components/commerce/blocks/payment.css +2 -0
- package/templates/nova/src/components/commerce/cart-limit.ts +11 -0
- package/templates/nova/src/components/commerce/money.ts +34 -0
- package/templates/nova/src/components/commerce/swatch.ts +54 -0
- package/templates/nova/src/components/content/ArticleCard.css +22 -0
- package/templates/nova/src/components/content/ArticleCard.tsx +53 -0
- package/templates/nova/src/components/content/BeforeAfterSlider.css +38 -0
- package/templates/nova/src/components/content/BeforeAfterSlider.tsx +87 -0
- package/templates/nova/src/components/content/CardRow.css +80 -0
- package/templates/nova/src/components/content/CardRow.tsx +140 -0
- package/templates/nova/src/components/content/CarouselControls.css +61 -0
- package/templates/nova/src/components/content/CarouselControls.tsx +90 -0
- package/templates/nova/src/components/content/ContentsNav.css +16 -0
- package/templates/nova/src/components/content/ContentsNav.tsx +55 -0
- package/templates/nova/src/components/content/Countdown.css +24 -0
- package/templates/nova/src/components/content/Countdown.tsx +115 -0
- package/templates/nova/src/components/content/HeroCopy.css +92 -0
- package/templates/nova/src/components/content/HeroCopy.tsx +148 -0
- package/templates/nova/src/components/content/HeroFrame.css +75 -0
- package/templates/nova/src/components/content/HeroFrame.tsx +49 -0
- package/templates/nova/src/components/content/HeroMedia.css +40 -0
- package/templates/nova/src/components/content/HeroMedia.tsx +170 -0
- package/templates/nova/src/components/content/LongForm.css +40 -0
- package/templates/nova/src/components/content/LongForm.tsx +56 -0
- package/templates/nova/src/components/content/MediaFrame.css +5 -0
- package/templates/nova/src/components/content/MediaFrame.tsx +52 -0
- package/templates/nova/src/components/content/RichText.tsx +30 -0
- package/templates/nova/src/components/content/SectionHead.css +8 -0
- package/templates/nova/src/components/content/SectionHead.tsx +34 -0
- package/templates/nova/src/components/content/ShareButtons.css +2 -0
- package/templates/nova/src/components/content/ShareButtons.tsx +40 -0
- package/templates/nova/src/components/content/StoreCard.css +14 -0
- package/templates/nova/src/components/content/StoreCard.tsx +60 -0
- package/templates/nova/src/components/content/TestimonialCard.css +36 -0
- package/templates/nova/src/components/content/TestimonialCard.tsx +102 -0
- package/templates/nova/src/components/content/UgcTile.css +8 -0
- package/templates/nova/src/components/content/UgcTile.tsx +33 -0
- package/templates/nova/src/components/content/blocks/Button.tsx +36 -0
- package/templates/nova/src/components/content/blocks/Column.tsx +30 -0
- package/templates/nova/src/components/content/blocks/Heading.tsx +31 -0
- package/templates/nova/src/components/content/blocks/Icon.tsx +25 -0
- package/templates/nova/src/components/content/blocks/Image.tsx +42 -0
- package/templates/nova/src/components/content/blocks/Text.tsx +26 -0
- package/templates/nova/src/components/content/blocks/Video.tsx +44 -0
- package/templates/nova/src/components/content/blocks/content.css +25 -0
- package/templates/nova/src/components/content/blocks/shared.ts +5 -0
- package/templates/nova/src/components/forms/ContactForm.css +19 -0
- package/templates/nova/src/components/forms/ContactForm.tsx +139 -0
- package/templates/nova/src/components/forms/FormField.css +15 -0
- package/templates/nova/src/components/forms/FormField.tsx +77 -0
- package/templates/nova/src/components/forms/GatewayFields.tsx +79 -0
- package/templates/nova/src/components/forms/NewsletterForm.css +9 -0
- package/templates/nova/src/components/forms/NewsletterForm.tsx +141 -0
- package/templates/nova/src/components/forms/SearchField.css +7 -0
- package/templates/nova/src/components/forms/SearchField.tsx +68 -0
- package/templates/nova/src/components/forms/blocks/Newsletter.css +5 -0
- package/templates/nova/src/components/forms/blocks/Newsletter.tsx +71 -0
- package/templates/nova/src/components/forms/validate.ts +4 -0
- package/templates/nova/src/components/listing/ProductListing.tsx +200 -0
- package/templates/nova/src/components/navigation/BrandLogo.tsx +35 -0
- package/templates/nova/src/components/navigation/Breadcrumb.css +16 -0
- package/templates/nova/src/components/navigation/Breadcrumb.tsx +59 -0
- package/templates/nova/src/components/navigation/LineAddFriend.css +5 -0
- package/templates/nova/src/components/navigation/LineAddFriend.tsx +42 -0
- package/templates/nova/src/components/navigation/LocaleSelector.css +33 -0
- package/templates/nova/src/components/navigation/LocaleSelector.tsx +64 -0
- package/templates/nova/src/components/navigation/Menu.tsx +26 -0
- package/templates/nova/src/components/navigation/Pagination.css +24 -0
- package/templates/nova/src/components/navigation/Pagination.tsx +74 -0
- package/templates/nova/src/components/navigation/RecoveryLinks.css +8 -0
- package/templates/nova/src/components/navigation/RecoveryLinks.tsx +23 -0
- package/templates/nova/src/components/navigation/SocialLinks.css +5 -0
- package/templates/nova/src/components/navigation/SocialLinks.tsx +51 -0
- package/templates/nova/src/components/navigation/blocks/SocialLinks.tsx +23 -0
- package/templates/nova/src/components/overlays/AccountMenu.css +11 -0
- package/templates/nova/src/components/overlays/AccountMenu.tsx +91 -0
- package/templates/nova/src/components/overlays/CartDrawer.css +17 -0
- package/templates/nova/src/components/overlays/CartDrawer.tsx +118 -0
- package/templates/nova/src/components/overlays/ConfirmationDialog.tsx +49 -0
- package/templates/nova/src/components/overlays/CookieConsent.css +56 -0
- package/templates/nova/src/components/overlays/CookieConsent.tsx +170 -0
- package/templates/nova/src/components/overlays/Drawer.css +38 -0
- package/templates/nova/src/components/overlays/Drawer.tsx +66 -0
- package/templates/nova/src/components/overlays/FriendOfferPanel.tsx +79 -0
- package/templates/nova/src/components/overlays/MarketSelector.css +111 -0
- package/templates/nova/src/components/overlays/MarketSelector.tsx +450 -0
- package/templates/nova/src/components/overlays/Menu.css +9 -0
- package/templates/nova/src/components/overlays/Menu.tsx +124 -0
- package/templates/nova/src/components/overlays/MobileNavDrawer.css +28 -0
- package/templates/nova/src/components/overlays/MobileNavDrawer.tsx +166 -0
- package/templates/nova/src/components/overlays/Modal.css +52 -0
- package/templates/nova/src/components/overlays/Modal.tsx +88 -0
- package/templates/nova/src/components/overlays/Popover.css +4 -0
- package/templates/nova/src/components/overlays/Popover.tsx +115 -0
- package/templates/nova/src/components/overlays/ProductLightbox.css +20 -0
- package/templates/nova/src/components/overlays/ProductLightbox.tsx +70 -0
- package/templates/nova/src/components/overlays/PromoPopup.css +32 -0
- package/templates/nova/src/components/overlays/PromoPopup.tsx +198 -0
- package/templates/nova/src/components/overlays/QuickView.css +31 -0
- package/templates/nova/src/components/overlays/QuickView.tsx +127 -0
- package/templates/nova/src/components/overlays/ReferralPanel.css +16 -0
- package/templates/nova/src/components/overlays/ReferralPanel.tsx +138 -0
- package/templates/nova/src/components/overlays/RewardsLauncher.css +22 -0
- package/templates/nova/src/components/overlays/RewardsLauncher.tsx +270 -0
- package/templates/nova/src/components/overlays/SearchModal.css +48 -0
- package/templates/nova/src/components/overlays/SearchModal.tsx +302 -0
- package/templates/nova/src/components/overlays/Sheet.css +16 -0
- package/templates/nova/src/components/overlays/Sheet.tsx +48 -0
- package/templates/nova/src/components/overlays/SizeGuide.css +8 -0
- package/templates/nova/src/components/overlays/SizeGuide.tsx +74 -0
- package/templates/nova/src/components/overlays/Toast.css +20 -0
- package/templates/nova/src/components/overlays/Toast.tsx +164 -0
- package/templates/nova/src/components/overlays/Tooltip.css +6 -0
- package/templates/nova/src/components/overlays/Tooltip.tsx +59 -0
- package/templates/nova/src/components/overlays/use-dialog.ts +74 -0
- package/templates/nova/src/components/section/shared.css +42 -0
- package/templates/nova/src/components/section/shared.ts +120 -0
- package/templates/nova/src/components/section/shell.tsx +29 -0
- package/templates/nova/src/components/states/Alert.css +10 -0
- package/templates/nova/src/components/states/Alert.tsx +50 -0
- package/templates/nova/src/components/states/EditorFrame.css +31 -0
- package/templates/nova/src/components/states/EditorFrame.tsx +43 -0
- package/templates/nova/src/components/states/MediaState.css +1 -0
- package/templates/nova/src/components/states/MediaState.tsx +49 -0
- package/templates/nova/src/components/states/OfflineNotice.css +4 -0
- package/templates/nova/src/components/states/OfflineNotice.tsx +24 -0
- package/templates/nova/src/components/states/SkeletonLayout.css +22 -0
- package/templates/nova/src/components/states/SkeletonLayout.tsx +104 -0
- package/templates/nova/src/components/states/StateBlock.css +22 -0
- package/templates/nova/src/components/states/StateBlock.tsx +39 -0
- package/templates/nova/src/components/states/media/MediaError.css +6 -0
- package/templates/nova/src/components/states/media/MediaError.tsx +49 -0
- package/templates/nova/src/components/states/media/MediaPlaceholder.css +24 -0
- package/templates/nova/src/components/states/media/MediaPlaceholder.tsx +101 -0
- package/templates/nova/src/components/states/media/placeholder-art.ts +142 -0
- package/templates/nova/src/layouts/Main.tsx +80 -0
- package/templates/nova/src/sections/Account/Account.tsx +109 -0
- package/templates/nova/src/sections/Account/index.ts +22 -0
- package/templates/nova/src/sections/Account/presets.ts +6 -0
- package/templates/nova/src/sections/Account/schema.ts +29 -0
- package/templates/nova/src/sections/AnnouncementBar/AnnouncementBar.css +37 -0
- package/templates/nova/src/sections/AnnouncementBar/AnnouncementBar.tsx +151 -0
- package/templates/nova/src/sections/AnnouncementBar/index.ts +20 -0
- package/templates/nova/src/sections/AnnouncementBar/presets.ts +10 -0
- package/templates/nova/src/sections/AnnouncementBar/schema.ts +26 -0
- package/templates/nova/src/sections/ArticleBody/ArticleBody.tsx +129 -0
- package/templates/nova/src/sections/ArticleBody/index.ts +21 -0
- package/templates/nova/src/sections/ArticleBody/presets.ts +10 -0
- package/templates/nova/src/sections/ArticleBody/schema.ts +40 -0
- package/templates/nova/src/sections/BeforeAfter/BeforeAfter.tsx +47 -0
- package/templates/nova/src/sections/BeforeAfter/blocks/Comparison.tsx +20 -0
- package/templates/nova/src/sections/BeforeAfter/index.ts +28 -0
- package/templates/nova/src/sections/BeforeAfter/presets.ts +10 -0
- package/templates/nova/src/sections/BeforeAfter/schema.ts +34 -0
- package/templates/nova/src/sections/BlogPosts/BlogPosts.tsx +106 -0
- package/templates/nova/src/sections/BlogPosts/index.ts +30 -0
- package/templates/nova/src/sections/BlogPosts/presets.ts +10 -0
- package/templates/nova/src/sections/BlogPosts/schema.ts +42 -0
- package/templates/nova/src/sections/Breadcrumbs/Breadcrumbs.css +10 -0
- package/templates/nova/src/sections/Breadcrumbs/Breadcrumbs.tsx +41 -0
- package/templates/nova/src/sections/Breadcrumbs/index.ts +20 -0
- package/templates/nova/src/sections/Breadcrumbs/presets.ts +6 -0
- package/templates/nova/src/sections/Breadcrumbs/schema.ts +24 -0
- package/templates/nova/src/sections/CartItems/CartItems.tsx +170 -0
- package/templates/nova/src/sections/CartItems/blocks/CartBadge.tsx +14 -0
- package/templates/nova/src/sections/CartItems/index.ts +37 -0
- package/templates/nova/src/sections/CartItems/presets.ts +8 -0
- package/templates/nova/src/sections/CartItems/schema.ts +34 -0
- package/templates/nova/src/sections/CollectionBanner/CollectionBanner.tsx +120 -0
- package/templates/nova/src/sections/CollectionBanner/index.ts +25 -0
- package/templates/nova/src/sections/CollectionBanner/presets.ts +10 -0
- package/templates/nova/src/sections/CollectionBanner/schema.ts +37 -0
- package/templates/nova/src/sections/CollectionLinks/CollectionLinks.tsx +47 -0
- package/templates/nova/src/sections/CollectionLinks/index.ts +20 -0
- package/templates/nova/src/sections/CollectionLinks/presets.ts +8 -0
- package/templates/nova/src/sections/CollectionLinks/schema.ts +33 -0
- package/templates/nova/src/sections/CollectionList/CollectionList.tsx +89 -0
- package/templates/nova/src/sections/CollectionList/blocks/CollectionItem.tsx +25 -0
- package/templates/nova/src/sections/CollectionList/index.ts +33 -0
- package/templates/nova/src/sections/CollectionList/presets.ts +10 -0
- package/templates/nova/src/sections/CollectionList/schema.ts +41 -0
- package/templates/nova/src/sections/ComparisonTable/ComparisonTable.tsx +52 -0
- package/templates/nova/src/sections/ComparisonTable/blocks/CompareItem.tsx +26 -0
- package/templates/nova/src/sections/ComparisonTable/index.ts +31 -0
- package/templates/nova/src/sections/ComparisonTable/presets.ts +8 -0
- package/templates/nova/src/sections/ComparisonTable/schema.ts +31 -0
- package/templates/nova/src/sections/ContactForm/ContactForm.tsx +83 -0
- package/templates/nova/src/sections/ContactForm/blocks/ContactDetail.tsx +13 -0
- package/templates/nova/src/sections/ContactForm/index.ts +29 -0
- package/templates/nova/src/sections/ContactForm/presets.ts +8 -0
- package/templates/nova/src/sections/ContactForm/schema.ts +34 -0
- package/templates/nova/src/sections/Divider/Divider.css +17 -0
- package/templates/nova/src/sections/Divider/Divider.tsx +21 -0
- package/templates/nova/src/sections/Divider/index.ts +20 -0
- package/templates/nova/src/sections/Divider/presets.ts +10 -0
- package/templates/nova/src/sections/Divider/schema.ts +24 -0
- package/templates/nova/src/sections/Faq/Faq.tsx +51 -0
- package/templates/nova/src/sections/Faq/blocks/FaqItem.tsx +13 -0
- package/templates/nova/src/sections/Faq/index.ts +28 -0
- package/templates/nova/src/sections/Faq/presets.ts +8 -0
- package/templates/nova/src/sections/Faq/schema.ts +32 -0
- package/templates/nova/src/sections/FeatureGridBlocks/FeatureGridBlocks.tsx +90 -0
- package/templates/nova/src/sections/FeatureGridBlocks/index.ts +35 -0
- package/templates/nova/src/sections/FeatureGridBlocks/presets.ts +8 -0
- package/templates/nova/src/sections/FeatureGridBlocks/schema.ts +35 -0
- package/templates/nova/src/sections/FeatureHighlights/FeatureHighlights.tsx +56 -0
- package/templates/nova/src/sections/FeatureHighlights/index.ts +20 -0
- package/templates/nova/src/sections/FeatureHighlights/presets.ts +6 -0
- package/templates/nova/src/sections/FeatureHighlights/schema.ts +27 -0
- package/templates/nova/src/sections/FeaturedCollection/FeaturedCollection.tsx +67 -0
- package/templates/nova/src/sections/FeaturedCollection/index.ts +21 -0
- package/templates/nova/src/sections/FeaturedCollection/presets.ts +10 -0
- package/templates/nova/src/sections/FeaturedCollection/schema.ts +39 -0
- package/templates/nova/src/sections/FeaturedProduct/FeaturedProduct.tsx +107 -0
- package/templates/nova/src/sections/FeaturedProduct/index.ts +23 -0
- package/templates/nova/src/sections/FeaturedProduct/presets.ts +8 -0
- package/templates/nova/src/sections/FeaturedProduct/schema.ts +35 -0
- package/templates/nova/src/sections/Footer/Footer.css +81 -0
- package/templates/nova/src/sections/Footer/Footer.tsx +256 -0
- package/templates/nova/src/sections/Footer/blocks/FooterBrand.tsx +40 -0
- package/templates/nova/src/sections/Footer/blocks/FooterLine.tsx +11 -0
- package/templates/nova/src/sections/Footer/blocks/FooterMenu.tsx +14 -0
- package/templates/nova/src/sections/Footer/blocks/FooterText.tsx +8 -0
- package/templates/nova/src/sections/Footer/blocks/footer.css +7 -0
- package/templates/nova/src/sections/Footer/index.ts +38 -0
- package/templates/nova/src/sections/Footer/presets.ts +10 -0
- package/templates/nova/src/sections/Footer/schema.ts +27 -0
- package/templates/nova/src/sections/Group/Group.css +59 -0
- package/templates/nova/src/sections/Group/Group.tsx +167 -0
- package/templates/nova/src/sections/Group/blocks/Accordion.tsx +26 -0
- package/templates/nova/src/sections/Group/blocks/JumboText.tsx +20 -0
- package/templates/nova/src/sections/Group/blocks/Spacer.tsx +16 -0
- package/templates/nova/src/sections/Group/index.ts +36 -0
- package/templates/nova/src/sections/Group/presets.ts +12 -0
- package/templates/nova/src/sections/Group/schema.ts +35 -0
- package/templates/nova/src/sections/Header/Header.css +185 -0
- package/templates/nova/src/sections/Header/Header.tsx +478 -0
- package/templates/nova/src/sections/Header/index.ts +32 -0
- package/templates/nova/src/sections/Header/presets.ts +10 -0
- package/templates/nova/src/sections/Header/schema.ts +32 -0
- package/templates/nova/src/sections/Hero/Hero.tsx +128 -0
- package/templates/nova/src/sections/Hero/index.ts +24 -0
- package/templates/nova/src/sections/Hero/presets.ts +16 -0
- package/templates/nova/src/sections/Hero/schema.ts +56 -0
- package/templates/nova/src/sections/ImageGallery/ImageGallery.tsx +86 -0
- package/templates/nova/src/sections/ImageGallery/index.ts +28 -0
- package/templates/nova/src/sections/ImageGallery/presets.ts +10 -0
- package/templates/nova/src/sections/ImageGallery/schema.ts +34 -0
- package/templates/nova/src/sections/ImageWithText/ImageWithText.tsx +62 -0
- package/templates/nova/src/sections/ImageWithText/index.ts +23 -0
- package/templates/nova/src/sections/ImageWithText/presets.ts +12 -0
- package/templates/nova/src/sections/ImageWithText/schema.ts +45 -0
- package/templates/nova/src/sections/LineAddFriend/LineAddFriend.tsx +25 -0
- package/templates/nova/src/sections/LineAddFriend/index.ts +20 -0
- package/templates/nova/src/sections/LineAddFriend/presets.ts +3 -0
- package/templates/nova/src/sections/LineAddFriend/schema.ts +25 -0
- package/templates/nova/src/sections/LogoList/LogoList.tsx +40 -0
- package/templates/nova/src/sections/LogoList/blocks/Logo.tsx +18 -0
- package/templates/nova/src/sections/LogoList/index.ts +29 -0
- package/templates/nova/src/sections/LogoList/presets.ts +8 -0
- package/templates/nova/src/sections/LogoList/schema.ts +29 -0
- package/templates/nova/src/sections/MainCollection/MainCollection.tsx +51 -0
- package/templates/nova/src/sections/MainCollection/index.ts +26 -0
- package/templates/nova/src/sections/MainCollection/presets.ts +10 -0
- package/templates/nova/src/sections/MainCollection/schema.ts +29 -0
- package/templates/nova/src/sections/Marquee/Marquee.tsx +114 -0
- package/templates/nova/src/sections/Marquee/index.ts +20 -0
- package/templates/nova/src/sections/Marquee/presets.ts +10 -0
- package/templates/nova/src/sections/Marquee/schema.ts +23 -0
- package/templates/nova/src/sections/Multicolumn/Multicolumn.tsx +56 -0
- package/templates/nova/src/sections/Multicolumn/index.ts +25 -0
- package/templates/nova/src/sections/Multicolumn/presets.ts +8 -0
- package/templates/nova/src/sections/Multicolumn/schema.ts +34 -0
- package/templates/nova/src/sections/Newsletter/Newsletter.tsx +64 -0
- package/templates/nova/src/sections/Newsletter/index.ts +20 -0
- package/templates/nova/src/sections/Newsletter/presets.ts +10 -0
- package/templates/nova/src/sections/Newsletter/schema.ts +36 -0
- package/templates/nova/src/sections/NotFound/NotFound.tsx +41 -0
- package/templates/nova/src/sections/NotFound/index.ts +20 -0
- package/templates/nova/src/sections/NotFound/presets.ts +6 -0
- package/templates/nova/src/sections/NotFound/schema.ts +30 -0
- package/templates/nova/src/sections/PageBody/PageBody.tsx +35 -0
- package/templates/nova/src/sections/PageBody/index.ts +21 -0
- package/templates/nova/src/sections/PageBody/presets.ts +6 -0
- package/templates/nova/src/sections/PageBody/schema.ts +29 -0
- package/templates/nova/src/sections/PolicyPage/PolicyPage.tsx +62 -0
- package/templates/nova/src/sections/PolicyPage/index.ts +23 -0
- package/templates/nova/src/sections/PolicyPage/presets.ts +6 -0
- package/templates/nova/src/sections/PolicyPage/schema.ts +27 -0
- package/templates/nova/src/sections/ProductDetails/ProductDetails.tsx +269 -0
- package/templates/nova/src/sections/ProductDetails/blocks/AddToCartBlock.tsx +15 -0
- package/templates/nova/src/sections/ProductDetails/blocks/ProductDescription.tsx +15 -0
- package/templates/nova/src/sections/ProductDetails/blocks/ProductInventory.tsx +38 -0
- package/templates/nova/src/sections/ProductDetails/blocks/ProductPrice.tsx +19 -0
- package/templates/nova/src/sections/ProductDetails/blocks/ProductSku.tsx +15 -0
- package/templates/nova/src/sections/ProductDetails/blocks/ProductTitle.tsx +17 -0
- package/templates/nova/src/sections/ProductDetails/blocks/Quantity.tsx +14 -0
- package/templates/nova/src/sections/ProductDetails/blocks/Tab.tsx +23 -0
- package/templates/nova/src/sections/ProductDetails/blocks/VariantPickerBlock.tsx +44 -0
- package/templates/nova/src/sections/ProductDetails/blocks/commerce-blocks.css +13 -0
- package/templates/nova/src/sections/ProductDetails/index.ts +44 -0
- package/templates/nova/src/sections/ProductDetails/presets.ts +10 -0
- package/templates/nova/src/sections/ProductDetails/schema.ts +44 -0
- package/templates/nova/src/sections/ProductGrid/ProductGrid.tsx +38 -0
- package/templates/nova/src/sections/ProductGrid/index.ts +25 -0
- package/templates/nova/src/sections/ProductGrid/presets.ts +6 -0
- package/templates/nova/src/sections/ProductGrid/schema.ts +37 -0
- package/templates/nova/src/sections/ProductRecommendations/ProductRecommendations.tsx +45 -0
- package/templates/nova/src/sections/ProductRecommendations/index.ts +20 -0
- package/templates/nova/src/sections/ProductRecommendations/presets.ts +8 -0
- package/templates/nova/src/sections/ProductRecommendations/schema.ts +28 -0
- package/templates/nova/src/sections/ProductReviews/ProductReviews.tsx +136 -0
- package/templates/nova/src/sections/ProductReviews/index.ts +22 -0
- package/templates/nova/src/sections/ProductReviews/presets.ts +6 -0
- package/templates/nova/src/sections/ProductReviews/schema.ts +31 -0
- package/templates/nova/src/sections/PromoBanner/PromoBanner.tsx +78 -0
- package/templates/nova/src/sections/PromoBanner/index.ts +20 -0
- package/templates/nova/src/sections/PromoBanner/presets.ts +10 -0
- package/templates/nova/src/sections/PromoBanner/schema.ts +38 -0
- package/templates/nova/src/sections/RecentlyViewed/RecentlyViewed.tsx +53 -0
- package/templates/nova/src/sections/RecentlyViewed/index.ts +20 -0
- package/templates/nova/src/sections/RecentlyViewed/presets.ts +6 -0
- package/templates/nova/src/sections/RecentlyViewed/schema.ts +26 -0
- package/templates/nova/src/sections/RichText/RichText.tsx +38 -0
- package/templates/nova/src/sections/RichText/index.ts +20 -0
- package/templates/nova/src/sections/RichText/presets.ts +10 -0
- package/templates/nova/src/sections/RichText/schema.ts +37 -0
- package/templates/nova/src/sections/SearchResults/SearchResults.tsx +112 -0
- package/templates/nova/src/sections/SearchResults/index.ts +26 -0
- package/templates/nova/src/sections/SearchResults/presets.ts +8 -0
- package/templates/nova/src/sections/SearchResults/schema.ts +30 -0
- package/templates/nova/src/sections/ShopTheLook/ShopTheLook.tsx +112 -0
- package/templates/nova/src/sections/ShopTheLook/blocks/Hotspot.tsx +22 -0
- package/templates/nova/src/sections/ShopTheLook/index.ts +33 -0
- package/templates/nova/src/sections/ShopTheLook/presets.ts +8 -0
- package/templates/nova/src/sections/ShopTheLook/schema.ts +31 -0
- package/templates/nova/src/sections/Slideshow/Slideshow.tsx +199 -0
- package/templates/nova/src/sections/Slideshow/blocks/Slide.tsx +93 -0
- package/templates/nova/src/sections/Slideshow/index.ts +30 -0
- package/templates/nova/src/sections/Slideshow/presets.ts +10 -0
- package/templates/nova/src/sections/Slideshow/schema.ts +36 -0
- package/templates/nova/src/sections/StoreLocator/StoreLocator.tsx +66 -0
- package/templates/nova/src/sections/StoreLocator/index.ts +20 -0
- package/templates/nova/src/sections/StoreLocator/presets.ts +6 -0
- package/templates/nova/src/sections/StoreLocator/schema.ts +34 -0
- package/templates/nova/src/sections/TeamFounders/TeamFounders.tsx +74 -0
- package/templates/nova/src/sections/TeamFounders/blocks/Person.tsx +28 -0
- package/templates/nova/src/sections/TeamFounders/index.ts +28 -0
- package/templates/nova/src/sections/TeamFounders/presets.ts +10 -0
- package/templates/nova/src/sections/TeamFounders/schema.ts +36 -0
- package/templates/nova/src/sections/Testimonials/Testimonials.tsx +83 -0
- package/templates/nova/src/sections/Testimonials/blocks/Testimonial.tsx +30 -0
- package/templates/nova/src/sections/Testimonials/index.ts +29 -0
- package/templates/nova/src/sections/Testimonials/presets.ts +10 -0
- package/templates/nova/src/sections/Testimonials/schema.ts +35 -0
- package/templates/nova/src/sections/Timeline/Timeline.tsx +43 -0
- package/templates/nova/src/sections/Timeline/blocks/Step.tsx +19 -0
- package/templates/nova/src/sections/Timeline/index.ts +28 -0
- package/templates/nova/src/sections/Timeline/presets.ts +8 -0
- package/templates/nova/src/sections/Timeline/schema.ts +31 -0
- package/templates/nova/src/sections/TrustBadges/TrustBadges.tsx +42 -0
- package/templates/nova/src/sections/TrustBadges/index.ts +29 -0
- package/templates/nova/src/sections/TrustBadges/presets.ts +8 -0
- package/templates/nova/src/sections/TrustBadges/schema.ts +29 -0
- package/templates/nova/src/sections/UgcGallery/UgcGallery.tsx +58 -0
- package/templates/nova/src/sections/UgcGallery/blocks/UgcImage.tsx +27 -0
- package/templates/nova/src/sections/UgcGallery/index.ts +31 -0
- package/templates/nova/src/sections/UgcGallery/presets.ts +8 -0
- package/templates/nova/src/sections/UgcGallery/schema.ts +35 -0
- package/templates/nova/src/sections/VideoHero/VideoHero.tsx +75 -0
- package/templates/nova/src/sections/VideoHero/index.ts +22 -0
- package/templates/nova/src/sections/VideoHero/presets.ts +8 -0
- package/templates/nova/src/sections/VideoHero/schema.ts +43 -0
- package/templates/nova/src/sections/data.ts +115 -0
- package/templates/nova/src/sections/shipped-copy.ts +25 -0
- package/templates/nova/src/sections/starter.ts +49 -0
- package/templates/nova/src/styles/Container.css +6 -0
- package/templates/nova/src/styles/Container.tsx +13 -0
- package/templates/nova/src/styles/Icon.css +2 -0
- package/templates/nova/src/styles/Icon.tsx +101 -0
- package/templates/nova/src/styles/NovaProvider.tsx +91 -0
- package/templates/nova/src/styles/base.css +142 -0
- package/templates/nova/src/styles/blocks.css +6 -0
- package/templates/nova/src/styles/fonts/OFL.txt +93 -0
- package/templates/nova/src/styles/fonts/geist-cyrillic-ext.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-cyrillic.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-latin-ext.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-latin.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-mono-cyrillic-ext.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-mono-cyrillic.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-mono-latin-ext.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-mono-latin.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-mono-vietnamese.woff2 +0 -0
- package/templates/nova/src/styles/fonts/geist-vietnamese.woff2 +0 -0
- package/templates/nova/src/styles/fonts.css +95 -0
- package/templates/nova/src/styles/global-settings.css +88 -0
- package/templates/nova/src/styles/index.css +6 -0
- package/templates/nova/src/styles/motion.ts +53 -0
- package/templates/nova/src/styles/scroll.ts +24 -0
- package/templates/nova/src/styles/sections/commerce.css +147 -0
- package/templates/nova/src/styles/sections/content.css +304 -0
- package/templates/nova/src/styles/sections/editorial.css +131 -0
- package/templates/nova/src/styles/sections/promotion.css +336 -0
- package/templates/nova/src/styles/sections/trust.css +117 -0
- package/templates/nova/src/styles/sections/utility.css +190 -0
- package/templates/nova/src/styles/strings.ts +492 -0
- package/templates/nova/src/styles/text.ts +4 -0
- package/templates/nova/src/styles/theme.ts +171 -0
- package/templates/nova/src/styles/tokens.css +600 -0
- package/templates/nova/src/styles/viewport.ts +23 -0
- package/templates/nova/template.json +94 -0
- package/templates/nova/templates/404.json +30 -0
- package/templates/nova/templates/account.json +15 -0
- package/templates/nova/templates/article.json +41 -0
- package/templates/nova/templates/article.longform.json +17 -0
- package/templates/nova/templates/blog.featured.json +22 -0
- package/templates/nova/templates/blog.json +29 -0
- package/templates/nova/templates/cart.json +67 -0
- package/templates/nova/templates/collection.featured.json +43 -0
- package/templates/nova/templates/collection.json +30 -0
- package/templates/nova/templates/contact.json +65 -0
- package/templates/nova/templates/index.json +167 -0
- package/templates/nova/templates/list-collections.json +19 -0
- package/templates/nova/templates/page.about.json +134 -0
- package/templates/nova/templates/page.contact.json +27 -0
- package/templates/nova/templates/page.json +27 -0
- package/templates/nova/templates/policy.json +23 -0
- package/templates/nova/templates/product.bundle.json +145 -0
- package/templates/nova/templates/product.json +119 -0
- package/templates/nova/templates/search.json +17 -0
- package/templates/nova/tests/abi-ai-contract.test.ts +99 -0
- package/templates/nova/tests/abi-forms.test.tsx +269 -0
- package/templates/nova/tests/abi-inventory.test.tsx +197 -0
- package/templates/nova/tests/abi-legacy-settings.test.tsx +105 -0
- package/templates/nova/tests/abi-opt-in.test.tsx +100 -0
- package/templates/nova/tests/abi-parity.test.tsx +95 -0
- package/templates/nova/tests/abi-r5-store-settings.test.tsx +337 -0
- package/templates/nova/tests/abi-render.test.tsx +178 -0
- package/templates/nova/tests/abi-shop-links.test.tsx +141 -0
- package/templates/nova/tests/abi-storefront-basics.test.tsx +233 -0
- package/templates/nova/tests/abi-variant-url.test.tsx +73 -0
- package/templates/nova/tests/add-refused-no-success.test.tsx +193 -0
- package/templates/nova/tests/architecture.test.ts +63 -0
- package/templates/nova/tests/architecture.ts +160 -0
- package/templates/nova/tests/audit-guards.test.ts +31 -0
- package/templates/nova/tests/bundle-split.test.ts +29 -0
- package/templates/nova/tests/cart-limit-message.test.tsx +212 -0
- package/templates/nova/tests/cart-link-message.test.tsx +98 -0
- package/templates/nova/tests/cases/components/Overview.cases.tsx +8 -0
- package/templates/nova/tests/cases/components/base/Accordion.cases.tsx +40 -0
- package/templates/nova/tests/cases/components/base/Badge.cases.tsx +30 -0
- package/templates/nova/tests/cases/components/base/Button.cases.tsx +73 -0
- package/templates/nova/tests/cases/components/base/Checkbox.cases.tsx +27 -0
- package/templates/nova/tests/cases/components/base/Chip.cases.tsx +37 -0
- package/templates/nova/tests/cases/components/base/Divider.cases.tsx +26 -0
- package/templates/nova/tests/cases/components/base/IconButton.cases.tsx +28 -0
- package/templates/nova/tests/cases/components/base/Input.cases.tsx +28 -0
- package/templates/nova/tests/cases/components/base/Link.cases.tsx +27 -0
- package/templates/nova/tests/cases/components/base/Radio.cases.tsx +27 -0
- package/templates/nova/tests/cases/components/base/Select.cases.tsx +26 -0
- package/templates/nova/tests/cases/components/base/Skeleton.cases.tsx +29 -0
- package/templates/nova/tests/cases/components/base/Spinner.cases.tsx +16 -0
- package/templates/nova/tests/cases/components/base/Switch.cases.tsx +26 -0
- package/templates/nova/tests/cases/components/base/Tabs.cases.tsx +39 -0
- package/templates/nova/tests/cases/components/base/Textarea.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/commerce/AddToCart.cases.tsx +36 -0
- package/templates/nova/tests/cases/components/commerce/CartLine.cases.tsx +20 -0
- package/templates/nova/tests/cases/components/commerce/CartSummary.cases.tsx +16 -0
- package/templates/nova/tests/cases/components/commerce/CollectionCard.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/commerce/ComparisonTable.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/commerce/Hotspot.cases.tsx +25 -0
- package/templates/nova/tests/cases/components/commerce/LookItem.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/commerce/PaymentMark.cases.tsx +16 -0
- package/templates/nova/tests/cases/components/commerce/Price.cases.tsx +27 -0
- package/templates/nova/tests/cases/components/commerce/ProductCard.cases.tsx +67 -0
- package/templates/nova/tests/cases/components/commerce/ProductGallery.cases.tsx +39 -0
- package/templates/nova/tests/cases/components/commerce/QuantitySelector.cases.tsx +31 -0
- package/templates/nova/tests/cases/components/commerce/Reviews.cases.tsx +35 -0
- package/templates/nova/tests/cases/components/commerce/Stars.cases.tsx +16 -0
- package/templates/nova/tests/cases/components/commerce/VariantPicker.cases.tsx +38 -0
- package/templates/nova/tests/cases/components/commerce/blocks/Badge.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/commerce/blocks/PaymentIcons.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/commerce/blocks/Swatches.cases.tsx +22 -0
- package/templates/nova/tests/cases/components/content/ArticleCard.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/content/BeforeAfterSlider.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/content/CardRow.cases.tsx +23 -0
- package/templates/nova/tests/cases/components/content/CarouselControls.cases.tsx +48 -0
- package/templates/nova/tests/cases/components/content/ContentsNav.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/content/Countdown.cases.tsx +28 -0
- package/templates/nova/tests/cases/components/content/HeroCopy.cases.tsx +42 -0
- package/templates/nova/tests/cases/components/content/HeroFrame.cases.tsx +22 -0
- package/templates/nova/tests/cases/components/content/HeroMedia.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/content/LongForm.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/content/MediaFrame.cases.tsx +32 -0
- package/templates/nova/tests/cases/components/content/RichText.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/content/SectionHead.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/content/ShareButtons.cases.tsx +24 -0
- package/templates/nova/tests/cases/components/content/StoreCard.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/content/TestimonialCard.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/content/UgcTile.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/content/blocks/Button.cases.tsx +20 -0
- package/templates/nova/tests/cases/components/content/blocks/Column.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/content/blocks/Heading.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/content/blocks/Icon.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/content/blocks/Image.cases.tsx +22 -0
- package/templates/nova/tests/cases/components/content/blocks/Text.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/content/blocks/Video.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/forms/ContactForm.cases.tsx +29 -0
- package/templates/nova/tests/cases/components/forms/FormField.cases.tsx +61 -0
- package/templates/nova/tests/cases/components/forms/NewsletterForm.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/forms/SearchField.cases.tsx +25 -0
- package/templates/nova/tests/cases/components/forms/blocks/Newsletter.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/navigation/BrandLogo.cases.tsx +29 -0
- package/templates/nova/tests/cases/components/navigation/Breadcrumb.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/navigation/LocaleSelector.cases.tsx +32 -0
- package/templates/nova/tests/cases/components/navigation/Menu.cases.tsx +27 -0
- package/templates/nova/tests/cases/components/navigation/Pagination.cases.tsx +25 -0
- package/templates/nova/tests/cases/components/navigation/RecoveryLinks.cases.tsx +16 -0
- package/templates/nova/tests/cases/components/navigation/SocialLinks.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/navigation/blocks/SocialLinks.cases.tsx +17 -0
- package/templates/nova/tests/cases/components/overlays/AccountMenu.cases.tsx +28 -0
- package/templates/nova/tests/cases/components/overlays/CartDrawer.cases.tsx +30 -0
- package/templates/nova/tests/cases/components/overlays/ConfirmationDialog.cases.tsx +16 -0
- package/templates/nova/tests/cases/components/overlays/CookieConsent.cases.tsx +23 -0
- package/templates/nova/tests/cases/components/overlays/CookiePreferences.cases.tsx +16 -0
- package/templates/nova/tests/cases/components/overlays/Drawer.cases.tsx +52 -0
- package/templates/nova/tests/cases/components/overlays/MarketSelector.cases.tsx +82 -0
- package/templates/nova/tests/cases/components/overlays/Menu.cases.tsx +27 -0
- package/templates/nova/tests/cases/components/overlays/MobileNavDrawer.cases.tsx +32 -0
- package/templates/nova/tests/cases/components/overlays/Modal.cases.tsx +71 -0
- package/templates/nova/tests/cases/components/overlays/Popover.cases.tsx +50 -0
- package/templates/nova/tests/cases/components/overlays/PromoPopup.cases.tsx +19 -0
- package/templates/nova/tests/cases/components/overlays/QuickView.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/overlays/SearchModal.cases.tsx +60 -0
- package/templates/nova/tests/cases/components/overlays/Sheet.cases.tsx +32 -0
- package/templates/nova/tests/cases/components/overlays/SizeGuide.cases.tsx +27 -0
- package/templates/nova/tests/cases/components/overlays/Toast.cases.tsx +48 -0
- package/templates/nova/tests/cases/components/overlays/Tooltip.cases.tsx +33 -0
- package/templates/nova/tests/cases/components/states/Alert.cases.tsx +27 -0
- package/templates/nova/tests/cases/components/states/EditorFrame.cases.tsx +36 -0
- package/templates/nova/tests/cases/components/states/Empty.cases.tsx +30 -0
- package/templates/nova/tests/cases/components/states/Error.cases.tsx +38 -0
- package/templates/nova/tests/cases/components/states/Loading.cases.tsx +15 -0
- package/templates/nova/tests/cases/components/states/MediaState.cases.tsx +29 -0
- package/templates/nova/tests/cases/components/states/SkeletonLayout.cases.tsx +20 -0
- package/templates/nova/tests/cases/components/states/Unavailable.cases.tsx +16 -0
- package/templates/nova/tests/cases/components/states/media/MediaError.cases.tsx +18 -0
- package/templates/nova/tests/cases/components/states/media/MediaPlaceholder.cases.tsx +87 -0
- package/templates/nova/tests/cases/sections/Overview.cases.tsx +8 -0
- package/templates/nova/tests/cases/sections/commerce/collection-list/CollectionList.cases.tsx +46 -0
- package/templates/nova/tests/cases/sections/commerce/collection-list/blocks/CollectionItem.cases.tsx +18 -0
- package/templates/nova/tests/cases/sections/commerce/featured-collection/FeaturedCollection.cases.tsx +46 -0
- package/templates/nova/tests/cases/sections/commerce/featured-product/FeaturedProduct.cases.tsx +40 -0
- package/templates/nova/tests/cases/sections/commerce/main-collection/MainCollection.cases.tsx +81 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/ProductDetails.cases.tsx +110 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/AddToCartBlock.cases.tsx +21 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/ProductDescription.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/ProductInventory.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/ProductPrice.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/ProductSku.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/ProductTitle.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/Quantity.cases.tsx +20 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/Tab.cases.tsx +29 -0
- package/templates/nova/tests/cases/sections/commerce/product-details/blocks/VariantPickerBlock.cases.tsx +32 -0
- package/templates/nova/tests/cases/sections/commerce/product-grid/ProductGrid.cases.tsx +48 -0
- package/templates/nova/tests/cases/sections/commerce/product-recommendations/ProductRecommendations.cases.tsx +27 -0
- package/templates/nova/tests/cases/sections/commerce/recently-viewed/RecentlyViewed.cases.tsx +36 -0
- package/templates/nova/tests/cases/sections/content/article-body/ArticleBody.cases.tsx +32 -0
- package/templates/nova/tests/cases/sections/content/before-after/BeforeAfter.cases.tsx +40 -0
- package/templates/nova/tests/cases/sections/content/before-after/blocks/Comparison.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/content/blog-posts/BlogPosts.cases.tsx +47 -0
- package/templates/nova/tests/cases/sections/content/collection-links/CollectionLinks.cases.tsx +36 -0
- package/templates/nova/tests/cases/sections/content/faq/Faq.cases.tsx +38 -0
- package/templates/nova/tests/cases/sections/content/faq/blocks/FaqItem.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/content/feature-grid-blocks/FeatureGridBlocks.cases.tsx +31 -0
- package/templates/nova/tests/cases/sections/content/feature-highlights/FeatureHighlights.cases.tsx +26 -0
- package/templates/nova/tests/cases/sections/content/image-gallery/ImageGallery.cases.tsx +31 -0
- package/templates/nova/tests/cases/sections/content/image-with-text/ImageWithText.cases.tsx +35 -0
- package/templates/nova/tests/cases/sections/content/multicolumn/Multicolumn.cases.tsx +32 -0
- package/templates/nova/tests/cases/sections/content/page-body/PageBody.cases.tsx +31 -0
- package/templates/nova/tests/cases/sections/content/rich-text/RichTextSection.cases.tsx +33 -0
- package/templates/nova/tests/cases/sections/content/team-founders/TeamFounders.cases.tsx +31 -0
- package/templates/nova/tests/cases/sections/content/team-founders/blocks/Person.cases.tsx +18 -0
- package/templates/nova/tests/cases/sections/content/timeline/Timeline.cases.tsx +27 -0
- package/templates/nova/tests/cases/sections/content/timeline/blocks/Step.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/layout/announcement-bar/AnnouncementBar.cases.tsx +119 -0
- package/templates/nova/tests/cases/sections/layout/breadcrumbs/Breadcrumbs.cases.tsx +73 -0
- package/templates/nova/tests/cases/sections/layout/divider/Divider.cases.tsx +81 -0
- package/templates/nova/tests/cases/sections/layout/footer/Footer.cases.tsx +116 -0
- package/templates/nova/tests/cases/sections/layout/footer/blocks/FooterBrand.cases.tsx +27 -0
- package/templates/nova/tests/cases/sections/layout/footer/blocks/FooterMenu.cases.tsx +22 -0
- package/templates/nova/tests/cases/sections/layout/footer/blocks/FooterText.cases.tsx +20 -0
- package/templates/nova/tests/cases/sections/layout/group/Group.cases.tsx +185 -0
- package/templates/nova/tests/cases/sections/layout/group/blocks/Accordion.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/layout/group/blocks/JumboText.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/layout/group/blocks/Spacer.cases.tsx +33 -0
- package/templates/nova/tests/cases/sections/layout/header/Header.cases.tsx +277 -0
- package/templates/nova/tests/cases/sections/marketing/collection-banner/CollectionBanner.cases.tsx +62 -0
- package/templates/nova/tests/cases/sections/marketing/hero/Hero.cases.tsx +138 -0
- package/templates/nova/tests/cases/sections/marketing/marquee/Marquee.cases.tsx +63 -0
- package/templates/nova/tests/cases/sections/marketing/promo-banner/PromoBanner.cases.tsx +87 -0
- package/templates/nova/tests/cases/sections/marketing/slideshow/Slideshow.cases.tsx +113 -0
- package/templates/nova/tests/cases/sections/marketing/slideshow/blocks/Slide.cases.tsx +26 -0
- package/templates/nova/tests/cases/sections/marketing/video-hero/VideoHero.cases.tsx +72 -0
- package/templates/nova/tests/cases/sections/trust/comparison-table/ComparisonTableSection.cases.tsx +42 -0
- package/templates/nova/tests/cases/sections/trust/comparison-table/blocks/CompareItem.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/trust/logo-list/LogoList.cases.tsx +29 -0
- package/templates/nova/tests/cases/sections/trust/logo-list/blocks/Logo.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/trust/product-reviews/ProductReviews.cases.tsx +51 -0
- package/templates/nova/tests/cases/sections/trust/shop-the-look/ShopTheLook.cases.tsx +51 -0
- package/templates/nova/tests/cases/sections/trust/shop-the-look/blocks/Hotspot.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/trust/testimonials/Testimonials.cases.tsx +61 -0
- package/templates/nova/tests/cases/sections/trust/testimonials/blocks/Testimonial.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/trust/trust-badges/TrustBadges.cases.tsx +30 -0
- package/templates/nova/tests/cases/sections/trust/ugc-gallery/UgcGallery.cases.tsx +32 -0
- package/templates/nova/tests/cases/sections/trust/ugc-gallery/blocks/UgcImage.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/utility/account/Account.cases.tsx +44 -0
- package/templates/nova/tests/cases/sections/utility/cart-items/CartItems.cases.tsx +43 -0
- package/templates/nova/tests/cases/sections/utility/cart-items/blocks/CartBadge.cases.tsx +16 -0
- package/templates/nova/tests/cases/sections/utility/contact-form/ContactFormSection.cases.tsx +52 -0
- package/templates/nova/tests/cases/sections/utility/contact-form/blocks/ContactDetail.cases.tsx +17 -0
- package/templates/nova/tests/cases/sections/utility/newsletter/NewsletterSection.cases.tsx +109 -0
- package/templates/nova/tests/cases/sections/utility/not-found/NotFound.cases.tsx +28 -0
- package/templates/nova/tests/cases/sections/utility/policy-page/PolicyPage.cases.tsx +29 -0
- package/templates/nova/tests/cases/sections/utility/search-results/SearchResultsSection.cases.tsx +39 -0
- package/templates/nova/tests/cases/sections/utility/store-locator/StoreLocator.cases.tsx +40 -0
- package/templates/nova/tests/cases/styles/Borders.cases.tsx +10 -0
- package/templates/nova/tests/cases/styles/Breakpoints.cases.tsx +10 -0
- package/templates/nova/tests/cases/styles/Colors.cases.tsx +10 -0
- package/templates/nova/tests/cases/styles/Elevation.cases.tsx +10 -0
- package/templates/nova/tests/cases/styles/Icon.cases.tsx +23 -0
- package/templates/nova/tests/cases/styles/Layout.cases.tsx +8 -0
- package/templates/nova/tests/cases/styles/Motion.cases.tsx +10 -0
- package/templates/nova/tests/cases/styles/Overview.cases.tsx +8 -0
- package/templates/nova/tests/cases/styles/Radius.cases.tsx +10 -0
- package/templates/nova/tests/cases/styles/SharedThemeSettings.cases.tsx +19 -0
- package/templates/nova/tests/cases/styles/Spacing.cases.tsx +10 -0
- package/templates/nova/tests/cases/styles/Typography.cases.tsx +10 -0
- package/templates/nova/tests/cases.test.tsx +38 -0
- package/templates/nova/tests/components/PromoPopup.test.ts +21 -0
- package/templates/nova/tests/components/RichText.test.tsx +65 -0
- package/templates/nova/tests/components/formatDate.test.ts +10 -0
- package/templates/nova/tests/contract-locks.test.ts +23 -0
- package/templates/nova/tests/contracts.test.ts +153 -0
- package/templates/nova/tests/cookie-consent-privacy.test.tsx +128 -0
- package/templates/nova/tests/empty-store.test.tsx +81 -0
- package/templates/nova/tests/fixtures/commerce.ts +128 -0
- package/templates/nova/tests/fixtures/content.ts +58 -0
- package/templates/nova/tests/fixtures/index.ts +8 -0
- package/templates/nova/tests/fixtures/merch.ts +161 -0
- package/templates/nova/tests/fixtures/navigation.ts +125 -0
- package/templates/nova/tests/fixtures/promotion.ts +43 -0
- package/templates/nova/tests/fixtures/sample-store.json +1674 -0
- package/templates/nova/tests/fixtures/shop.ts +88 -0
- package/templates/nova/tests/fixtures/stress.ts +21 -0
- package/templates/nova/tests/inert.test.tsx +285 -0
- package/templates/nova/tests/line-add-friend.test.tsx +108 -0
- package/templates/nova/tests/localized-copy.test.ts +330 -0
- package/templates/nova/tests/product-template-blocks.test.ts +28 -0
- package/templates/nova/tests/rewards-launcher.test.tsx +401 -0
- package/templates/nova/tests/schema.test.ts +65 -0
- package/templates/nova/tests/schema.typetest.ts +7 -0
- package/templates/nova/tests/section-groups.test.ts +189 -0
- package/templates/nova/tests/sections/Group.test.tsx +37 -0
- package/templates/nova/tests/setup.ts +30 -0
- package/templates/nova/tests/starter.test.ts +56 -0
- package/templates/nova/tests/storefront-click-path.test.tsx +157 -0
- package/templates/nova/tests/styles/button-brand.test.ts +24 -0
- package/templates/nova/tests/styles/theme.test.ts +43 -0
- package/templates/nova/tests/styles/tokens.test.ts +35 -0
- package/templates/nova/tests/support/abi-ctx.ts +136 -0
- package/templates/nova/tests/support/block-stories.tsx +13 -0
- package/templates/nova/tests/support/case.tsx +102 -0
- package/templates/nova/tests/support/contracts.ts +30 -0
- package/templates/nova/tests/support/foundation-pages.tsx +260 -0
- package/templates/nova/tests/support/ia-pages.tsx +154 -0
- package/templates/nova/tests/support/listing-demo.tsx +29 -0
- package/templates/nova/tests/support/presets.ts +14 -0
- package/templates/nova/tests/support/sections.ts +36 -0
- package/templates/nova/tests/support/story-content.ts +321 -0
- package/templates/nova/tests/support/story-helpers.tsx +37 -0
- package/templates/nova/tests/support/with-nova.tsx +26 -0
- package/templates/nova/tests/theme-config.test.ts +82 -0
- package/templates/nova/tests/theme-integrity.test.ts +315 -0
- package/templates/nova/theme.config.ts +134 -0
- package/templates/nova/theme.manifest.json +17495 -0
- package/templates/nova/tsconfig.json +19 -0
- package/templates/nova/vite.abi-ssr.config.ts +37 -0
- package/templates/nova/vite.abi.config.ts +26 -0
- package/templates/nova/vitest.config.ts +20 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import theme from '../theme.config'
|
|
5
|
+
import { BLOCK_SCHEMAS } from './support/sections'
|
|
6
|
+
import manifest from '../theme.manifest.json'
|
|
7
|
+
import Main from '../src/layouts/Main'
|
|
8
|
+
|
|
9
|
+
const SECTIONS_DIR = join(__dirname, '../src/sections')
|
|
10
|
+
|
|
11
|
+
/** Every src/sections/<Name>/schema.ts that declares a section: persisted id → folder. */
|
|
12
|
+
function declaredSections(): Map<string, string> {
|
|
13
|
+
const out = new Map<string, string>()
|
|
14
|
+
for (const dir of readdirSync(SECTIONS_DIR, { withFileTypes: true })) {
|
|
15
|
+
const file = join(SECTIONS_DIR, dir.name, 'schema.ts')
|
|
16
|
+
if (!dir.isDirectory() || !existsSync(file)) continue
|
|
17
|
+
const m = /defineSchema\(\s*\{\s*kind:\s*'section',\s*name:\s*'([^']+)'/.exec(readFileSync(file, 'utf8'))
|
|
18
|
+
if (m) out.set(m[1], dir.name)
|
|
19
|
+
}
|
|
20
|
+
return out
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('theme.config.ts lists every section, once', () => {
|
|
24
|
+
const declared = declaredSections()
|
|
25
|
+
|
|
26
|
+
it('lists every section folder the theme declares, once', () => {
|
|
27
|
+
expect(theme.sections.map((s) => s.id).sort()).toEqual([...declared.keys()].sort())
|
|
28
|
+
expect(new Set(theme.sections.map((s) => s.id)).size).toBe(theme.sections.length)
|
|
29
|
+
})
|
|
30
|
+
it('each section folder has the standard files', () => {
|
|
31
|
+
for (const folder of declared.values())
|
|
32
|
+
for (const f of [`${folder}.tsx`, 'schema.ts', 'presets.ts', 'index.ts']) expect(existsSync(join(SECTIONS_DIR, folder, f)), `${folder}/${f}`).toBe(true)
|
|
33
|
+
})
|
|
34
|
+
it('the id is the schema name', () => {
|
|
35
|
+
for (const s of theme.sections) {
|
|
36
|
+
expect(s.schema.name).toBe(s.id)
|
|
37
|
+
expect(s.schema.kind).toBe('section')
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
it('every section has an editor title and description', () => {
|
|
41
|
+
for (const s of theme.sections) {
|
|
42
|
+
expect(s.title, s.id).toBeTruthy()
|
|
43
|
+
expect(s.description, s.id).toBeTruthy()
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
it('each section declares the block schemas it accepts, and each names the section as a parent', () => {
|
|
47
|
+
for (const s of theme.sections) {
|
|
48
|
+
const accepted = [...new Set([...(s.schema.blocks ?? []), ...(s.schema.legacyBlocks ?? [])])].sort()
|
|
49
|
+
// A block's earlier names (legacyNames) are what its parents keep accepting for saved content.
|
|
50
|
+
expect([...new Set((s.blocks ?? []).flatMap((b) => [b.name, ...(b.legacyNames ?? [])]))].sort(), s.id).toEqual(accepted)
|
|
51
|
+
for (const b of s.blocks ?? []) {
|
|
52
|
+
expect(b.kind, `${s.id} → ${b.name}`).toBe('block')
|
|
53
|
+
expect(b.parents, `${b.name} lists ${s.id}`).toContain(s.id)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
it('there is no block no section accepts: the sections are the only block list', () => {
|
|
58
|
+
const declared = new Set(BLOCK_SCHEMAS)
|
|
59
|
+
const files = import.meta.glob<Record<string, unknown>>('../src/**/blocks/*.tsx', { eager: true })
|
|
60
|
+
const orphans = Object.entries(files).flatMap(([path, mod]) =>
|
|
61
|
+
Object.values(mod).filter((v) => (v as { kind?: string })?.kind === 'block' && !declared.has(v as never)).map((v) => `${path}: ${(v as { name: string }).name}`),
|
|
62
|
+
)
|
|
63
|
+
expect(orphans).toEqual([])
|
|
64
|
+
})
|
|
65
|
+
it('"Section" means the 50 merchant-placeable sections; blocks and the layout are counted apart', () => {
|
|
66
|
+
expect(theme.sections).toHaveLength(50)
|
|
67
|
+
expect(manifest.stats).toMatchObject({ sections: 50, headerFooterSections: 3, blocks: 39, blockSchemas: 41, units: 89, layouts: 0 })
|
|
68
|
+
// What the editor's Add section picker offers: every catalog unit that is not a block.
|
|
69
|
+
expect(manifest.sections.filter((u) => u.role !== 'block').map((u) => u.name).sort()).toEqual(theme.sections.map((s) => s.id).sort())
|
|
70
|
+
})
|
|
71
|
+
it('no block shares a section\'s name: the catalog has one entry per name, and a block that collapsed into a section could never be offered in "Add block"', () => {
|
|
72
|
+
const sectionIds = new Set(theme.sections.map((s) => s.id))
|
|
73
|
+
const blockNames = [...new Set(theme.sections.flatMap((s) => (s.blocks ?? []).map((b) => b.name)))]
|
|
74
|
+
expect(blockNames.filter((n) => sectionIds.has(n))).toEqual([])
|
|
75
|
+
})
|
|
76
|
+
it('only the header zone holds header + announcement bar, the footer zone the footer', () => {
|
|
77
|
+
expect(theme.sections.filter((s) => s.zone !== 'main').map((s) => `${s.zone}:${s.id}`).sort()).toEqual(['footer:footer', 'header:announcement-bar', 'header:header'])
|
|
78
|
+
})
|
|
79
|
+
it('the layout is never a section', () => {
|
|
80
|
+
expect(theme.sections.some((s) => s.component === (Main as unknown))).toBe(false)
|
|
81
|
+
})
|
|
82
|
+
})
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme content integrity: the templates the theme SHIPS must be renderable by
|
|
3
|
+
* the sections the theme SHIPS.
|
|
4
|
+
*
|
|
5
|
+
* `pnpm manifest:check` proves the manifest matches the code. This proves the
|
|
6
|
+
* templates match the manifest — the drift that reaches a merchant as a setting
|
|
7
|
+
* that silently does nothing, a not-found card on their home page, or a
|
|
8
|
+
* composition the editor would refuse to save.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync, readdirSync } from 'node:fs'
|
|
11
|
+
import { join } from 'node:path'
|
|
12
|
+
import { describe, expect, it } from 'vitest'
|
|
13
|
+
import manifest from '../theme.manifest.json'
|
|
14
|
+
import sampleStore from './fixtures/sample-store.json'
|
|
15
|
+
|
|
16
|
+
interface Node {
|
|
17
|
+
type?: string
|
|
18
|
+
settings?: Record<string, unknown>
|
|
19
|
+
blocks?: Node[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** What this test needs from a manifest section entry. `theme.manifest.json` is
|
|
23
|
+
* imported for its values; TypeScript infers `never[]` for a section whose
|
|
24
|
+
* `allowedBlocks` happens to be empty in the committed file, so the shape is
|
|
25
|
+
* stated explicitly here rather than inferred from one sample. */
|
|
26
|
+
interface ManifestSection {
|
|
27
|
+
name: string
|
|
28
|
+
attributes: Record<string, { default?: unknown }>
|
|
29
|
+
allowedBlocks: string[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const TEMPLATE_DIR = join(__dirname, '..', 'templates')
|
|
33
|
+
const templates = readdirSync(TEMPLATE_DIR)
|
|
34
|
+
.filter((f) => f.endsWith('.json'))
|
|
35
|
+
.map((f) => ({
|
|
36
|
+
name: f.replace(/\.json$/, ''),
|
|
37
|
+
doc: JSON.parse(readFileSync(join(TEMPLATE_DIR, f), 'utf8')) as { sections?: Node[] },
|
|
38
|
+
}))
|
|
39
|
+
|
|
40
|
+
const manifestSections = manifest.sections as unknown as ManifestSection[]
|
|
41
|
+
const sections = new Map<string, ManifestSection>(manifestSections.map((s) => [s.name, s]))
|
|
42
|
+
|
|
43
|
+
function walk(nodes: Node[] | undefined, visit: (node: Node, parent?: string) => void, parent?: string): void {
|
|
44
|
+
for (const node of nodes ?? []) {
|
|
45
|
+
visit(node, parent)
|
|
46
|
+
walk(node.blocks, visit, node.type)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
describe('templates reference only sections the theme ships', () => {
|
|
51
|
+
it.each(templates)('$name', ({ doc }) => {
|
|
52
|
+
const unknown: string[] = []
|
|
53
|
+
walk(doc.sections, (node) => {
|
|
54
|
+
if (node.type && !sections.has(node.type)) unknown.push(node.type)
|
|
55
|
+
})
|
|
56
|
+
expect(unknown).toEqual([])
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
describe('templates only set settings their section declares', () => {
|
|
61
|
+
it.each(templates)('$name', ({ doc }) => {
|
|
62
|
+
const undeclared: string[] = []
|
|
63
|
+
walk(doc.sections, (node) => {
|
|
64
|
+
const def = node.type ? sections.get(node.type) : undefined
|
|
65
|
+
if (!def) return
|
|
66
|
+
for (const key of Object.keys(node.settings ?? {})) {
|
|
67
|
+
if (!(key in def.attributes)) undeclared.push(`${node.type}.${key}`)
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
// A setting the section does not declare is dropped on render and invisible
|
|
71
|
+
// in the editor — the template appears to configure something it does not.
|
|
72
|
+
expect(undeclared).toEqual([])
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
describe('nested blocks are permitted by their parent', () => {
|
|
77
|
+
it.each(templates)('$name', ({ doc }) => {
|
|
78
|
+
const disallowed: string[] = []
|
|
79
|
+
walk(doc.sections, (node, parent) => {
|
|
80
|
+
if (!parent || !node.type) return
|
|
81
|
+
const parentDef = sections.get(parent)
|
|
82
|
+
if (parentDef && !parentDef.allowedBlocks.includes(node.type)) {
|
|
83
|
+
disallowed.push(`${parent} > ${node.type}`)
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
expect(disallowed).toEqual([])
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
describe('starter content makes no claims on the merchant’s behalf', () => {
|
|
91
|
+
const BANNED = [
|
|
92
|
+
/free shipping/i,
|
|
93
|
+
/\d+-day returns?/i,
|
|
94
|
+
// "Free returns within 30 days" came back in `announcement-bar` after P1-7
|
|
95
|
+
// removed "30-day returns" — the claim, not its wording, is what is banned.
|
|
96
|
+
/free returns?/i,
|
|
97
|
+
/returns? within \d+/i,
|
|
98
|
+
/organic cotton/i,
|
|
99
|
+
/ships in \d+ ?h/i,
|
|
100
|
+
// A discount is a promise the merchant has to honour; "no spam /
|
|
101
|
+
// unsubscribe anytime" is a policy statement. Both came back in newsletter.
|
|
102
|
+
/\d+ ?% off/i,
|
|
103
|
+
/no spam/i,
|
|
104
|
+
/unsubscribe anytime/i,
|
|
105
|
+
// Where the goods ship from is the merchant's fact to state.
|
|
106
|
+
/ships? from our/i,
|
|
107
|
+
// A reply time is a service promise: "we'll reply within one business day" shipped on the contact page.
|
|
108
|
+
/reply within/i,
|
|
109
|
+
/within (one|\d+) business days?/i,
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
it('no template ships a shipping/returns/materials claim', () => {
|
|
113
|
+
const hits: string[] = []
|
|
114
|
+
for (const { name, doc } of templates) {
|
|
115
|
+
const json = JSON.stringify(doc)
|
|
116
|
+
for (const re of BANNED) {
|
|
117
|
+
const m = json.match(re)
|
|
118
|
+
if (m) hits.push(`${name}: ${m[0]}`)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
expect(hits).toEqual([])
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('no section DEFAULT ships one either', () => {
|
|
125
|
+
// A default reaches a live storefront the moment the section is placed —
|
|
126
|
+
// `announcement-bar` defaulted to "Free shipping on orders over $50".
|
|
127
|
+
const hits: string[] = []
|
|
128
|
+
for (const s of manifestSections) {
|
|
129
|
+
for (const [key, spec] of Object.entries(s.attributes)) {
|
|
130
|
+
const value = spec?.default
|
|
131
|
+
if (typeof value !== 'string') continue
|
|
132
|
+
for (const re of BANNED) {
|
|
133
|
+
if (re.test(value)) hits.push(`${s.name}.${key}`)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
expect(hits).toEqual([])
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('no UI or runtime SOURCE ships one in a preset, a default string or a hardcoded fallback', () => {
|
|
141
|
+
// The two tests above read the manifest, which carries `attributes` but not
|
|
142
|
+
// the presets, built-in strings and fallbacks in code — `Multicolumn`'s
|
|
143
|
+
// DEFAULT_ITEMS once shipped "Free shipping — on orders over $50" after the
|
|
144
|
+
// templates were cleaned. Everything a storefront renders is scanned;
|
|
145
|
+
// fixtures and test cases are offline example data and are not.
|
|
146
|
+
const roots = ['src', 'sections', 'locales'].map((d) => join(__dirname, '..', d))
|
|
147
|
+
const files: string[] = []
|
|
148
|
+
const walk = (dir: string): void => {
|
|
149
|
+
let entries: import('node:fs').Dirent[]
|
|
150
|
+
try {
|
|
151
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
152
|
+
} catch {
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
for (const e of entries) {
|
|
156
|
+
const full = join(dir, e.name)
|
|
157
|
+
if (e.isDirectory()) {
|
|
158
|
+
if (e.name !== 'fixtures' && e.name !== 'test') walk(full)
|
|
159
|
+
} else if (/\.(tsx?|json)$/.test(e.name) && !/\.test\.tsx?$/.test(e.name)) files.push(full)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
roots.forEach(walk)
|
|
163
|
+
const hits: string[] = []
|
|
164
|
+
for (const file of files) {
|
|
165
|
+
const body = readFileSync(file, 'utf8')
|
|
166
|
+
// Strip comments so prose ABOUT the removed claims does not trip it.
|
|
167
|
+
const code = body.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '')
|
|
168
|
+
for (const re of BANNED) {
|
|
169
|
+
const m = code.match(re)
|
|
170
|
+
if (m) hits.push(`${file.slice(join(__dirname, '..').length + 1)}: ${m[0]}`)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
expect(files.length).toBeGreaterThan(100)
|
|
174
|
+
// The free-shipping progress line renders only when the platform supplies
|
|
175
|
+
// the merchant's own threshold (CartDrawer `freeShipping`), never by default.
|
|
176
|
+
const ALLOWED = [
|
|
177
|
+
'locales/en.json: free shipping',
|
|
178
|
+
// KNOWN, NOT ACCEPTED: the approved 12B contract's "slideshow-compact"
|
|
179
|
+
// preset carries this heading. It shipped before presets moved into
|
|
180
|
+
// source (the scan could not see the contract JSON). Changing it is a
|
|
181
|
+
// design decision, so it is pinned here until the contract changes.
|
|
182
|
+
'src/sections/Slideshow/presets.ts: Free shipping',
|
|
183
|
+
// KNOWN, NOT ACCEPTED: the approved contract's contact-form `subheading`
|
|
184
|
+
// default promises a reply time. Same reason as above — the contract
|
|
185
|
+
// locks it, so changing it is a design decision; pinned until it changes.
|
|
186
|
+
"src/sections/ContactForm/schema.ts: reply within",
|
|
187
|
+
'src/sections/ContactForm/schema.ts: within one business day',
|
|
188
|
+
// The same pinned default as its shipped-copy entry (copy.weReplyWithinOneBusinessDay), so a store that
|
|
189
|
+
// saved it reads it in its own language. It goes when the default goes.
|
|
190
|
+
'locales/en.json: reply within',
|
|
191
|
+
'locales/en.json: within one business day',
|
|
192
|
+
]
|
|
193
|
+
hits.splice(0, hits.length, ...hits.filter((h) => !ALLOWED.includes(h)))
|
|
194
|
+
expect(hits).toEqual([])
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
describe('theme settings schema', () => {
|
|
199
|
+
it('has no drift between schema and values', () => {
|
|
200
|
+
expect(manifest.warnings.settingsUndeclared).toEqual([])
|
|
201
|
+
expect(manifest.warnings.settingsMissingValue).toEqual([])
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('records no template drift', () => {
|
|
205
|
+
expect(manifest.warnings.danglingTemplateRefs).toEqual([])
|
|
206
|
+
expect(manifest.warnings.unknownTemplateSettings).toEqual([])
|
|
207
|
+
expect(manifest.warnings.disallowedTemplateBlocks).toEqual([])
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
describe('translations', () => {
|
|
212
|
+
const locales = readdirSync(join(__dirname, '..', 'locales')).filter((f) => f.endsWith('.json'))
|
|
213
|
+
const load = (f: string): Record<string, string> =>
|
|
214
|
+
JSON.parse(readFileSync(join(__dirname, '..', 'locales', f), 'utf8'))
|
|
215
|
+
const en = load('en.json')
|
|
216
|
+
|
|
217
|
+
it.each(locales.filter((f) => f !== 'en.json'))('%s covers every en key', (file) => {
|
|
218
|
+
const other = load(file)
|
|
219
|
+
// A missing key falls back to English silently; the shopper sees a mixed
|
|
220
|
+
// page and nothing reports it.
|
|
221
|
+
expect(Object.keys(en).filter((k) => !(k in other))).toEqual([])
|
|
222
|
+
})
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
describe('starter content resolves against the shipped fixtures', () => {
|
|
226
|
+
// A handle that is not in the v1 runtime's offline sample store (`tests/fixtures/sample-store.json`) renders as an empty row or a
|
|
227
|
+
// 404 CTA for every merchant who has not yet replaced the starter content,
|
|
228
|
+
// and for anyone developing offline. `test-collection` / `blazer` / `featured`
|
|
229
|
+
// were a dev store's handles and shipped in `index.json` for months.
|
|
230
|
+
const fixtures = new Set(
|
|
231
|
+
(sampleStore as unknown as { handle: string }[]).map((c) => c.handle),
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
/** Every collection handle a template references, wherever it appears. */
|
|
235
|
+
const handles = (doc: { sections?: Node[] }): string[] => {
|
|
236
|
+
const out: string[] = []
|
|
237
|
+
const walk = (n: Node): void => {
|
|
238
|
+
const s = n.settings ?? {}
|
|
239
|
+
for (const [key, value] of Object.entries(s)) {
|
|
240
|
+
if (typeof value !== 'string' || !value) continue
|
|
241
|
+
if (key === 'collection') out.push(value)
|
|
242
|
+
else if (key === 'collections') out.push(...value.split(',').map((h) => h.trim()))
|
|
243
|
+
else if (key.toLowerCase().endsWith('link')) {
|
|
244
|
+
const m = /^\/collections\/([^/?#]+)/.exec(value)
|
|
245
|
+
if (m?.[1]) out.push(m[1])
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
n.blocks?.forEach(walk)
|
|
249
|
+
}
|
|
250
|
+
doc.sections?.forEach(walk)
|
|
251
|
+
return out.filter(Boolean)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
it.each(templates)('$name references only collections that exist', ({ doc }) => {
|
|
255
|
+
expect(handles(doc).filter((h) => !fixtures.has(h))).toEqual([])
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Existing in the v1 runtime's offline sample store (`tests/fixtures/sample-store.json`) is NOT enough.
|
|
260
|
+
*
|
|
261
|
+
* Those fixtures are the theme's offline/editor data. A handle can be in
|
|
262
|
+
* them and absent from the shop the theme is installed on — `new-arrivals`
|
|
263
|
+
* passed the test above and still rendered "No products in this collection
|
|
264
|
+
* yet" against a live store, exactly as the dev store's `test-collection`
|
|
265
|
+
* did before it. `all` is the one handle every storefront has.
|
|
266
|
+
*/
|
|
267
|
+
it.each(templates)('$name starter content only references `all`', ({ doc }) => {
|
|
268
|
+
expect([...new Set(handles(doc))].filter((h) => h !== 'all')).toEqual([])
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* This repository is public. It must describe itself in its own words and never
|
|
274
|
+
* name another commerce platform, its themes, its template language or its
|
|
275
|
+
* documentation — a rule the team already applied once by hand and that then
|
|
276
|
+
* regressed. The list cannot know every name; it pins the ones that have
|
|
277
|
+
* actually appeared here, across every tracked text file.
|
|
278
|
+
*/
|
|
279
|
+
describe('no third-party platform references in a public repository', () => {
|
|
280
|
+
const ROOT_DIR = join(__dirname, '..')
|
|
281
|
+
const SKIP_DIRS = new Set(['node_modules', 'dist', 'dist-ssr', '.git', '.vite', 'qa', 'vendor'])
|
|
282
|
+
const TEXT = /\.(tsx?|mjs|cjs|js|json|css|md|html|ya?ml|txt)$/
|
|
283
|
+
// Built from parts so this file does not contain the names it forbids.
|
|
284
|
+
const FORBIDDEN = new RegExp(
|
|
285
|
+
[['shop', 'ify'], ['\\bliq', 'uid\\b'], ['\\.liq', 'uid\\b'], ['\\{', '%'], ['my', 'shop', 'ify'], ['woo', 'commerce'], ['big', 'commerce'], ['\\bmag', 'ento\\b']]
|
|
286
|
+
.map((p) => p.join(''))
|
|
287
|
+
.join('|'),
|
|
288
|
+
'i',
|
|
289
|
+
)
|
|
290
|
+
const files: string[] = []
|
|
291
|
+
const scan = (dir: string): void => {
|
|
292
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
293
|
+
if (SKIP_DIRS.has(entry.name)) continue
|
|
294
|
+
const full = join(dir, entry.name)
|
|
295
|
+
if (entry.isDirectory()) scan(full)
|
|
296
|
+
else if (TEXT.test(entry.name) && entry.name !== 'pnpm-lock.yaml') files.push(full)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
scan(ROOT_DIR)
|
|
300
|
+
|
|
301
|
+
it('scans the repository', () => {
|
|
302
|
+
expect(files.length).toBeGreaterThan(100)
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('names no other platform, theme or template language', () => {
|
|
306
|
+
const hits: string[] = []
|
|
307
|
+
for (const file of files) {
|
|
308
|
+
const lines = readFileSync(file, 'utf8').split('\n')
|
|
309
|
+
lines.forEach((line, i) => {
|
|
310
|
+
if (FORBIDDEN.test(line)) hits.push(`${file.slice(ROOT_DIR.length + 1)}:${i + 1}: ${line.trim().slice(0, 90)}`)
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
expect(hits).toEqual([])
|
|
314
|
+
})
|
|
315
|
+
})
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { STARTER_TEXT } from './src/sections/starter'
|
|
2
|
+
import { defineTheme } from '@tanqory/theme-kit'
|
|
3
|
+
import { ThemeRoot } from './src/styles/NovaProvider'
|
|
4
|
+
import { BUILTIN_STRINGS, STRINGS_EN } from './src/styles/strings'
|
|
5
|
+
import { Main } from './src/layouts/Main'
|
|
6
|
+
import english from './locales/en.json'
|
|
7
|
+
import { DERIVED_WHEN_UNSET, KEEP_SHIPPED_COPY } from './src/sections/shipped-copy'
|
|
8
|
+
import { SHARED_SETTINGS } from './src/components/section/shared'
|
|
9
|
+
import header from './src/sections/Header'
|
|
10
|
+
import announcementBar from './src/sections/AnnouncementBar'
|
|
11
|
+
import footer from './src/sections/Footer'
|
|
12
|
+
import group from './src/sections/Group'
|
|
13
|
+
import divider from './src/sections/Divider'
|
|
14
|
+
import breadcrumbs from './src/sections/Breadcrumbs'
|
|
15
|
+
import hero from './src/sections/Hero'
|
|
16
|
+
import slideshow from './src/sections/Slideshow'
|
|
17
|
+
import videoHero from './src/sections/VideoHero'
|
|
18
|
+
import promoBanner from './src/sections/PromoBanner'
|
|
19
|
+
import marquee from './src/sections/Marquee'
|
|
20
|
+
import collectionBanner from './src/sections/CollectionBanner'
|
|
21
|
+
import productDetails from './src/sections/ProductDetails'
|
|
22
|
+
import mainCollection from './src/sections/MainCollection'
|
|
23
|
+
import productGrid from './src/sections/ProductGrid'
|
|
24
|
+
import featuredCollection from './src/sections/FeaturedCollection'
|
|
25
|
+
import featuredProduct from './src/sections/FeaturedProduct'
|
|
26
|
+
import collectionList from './src/sections/CollectionList'
|
|
27
|
+
import productRecommendations from './src/sections/ProductRecommendations'
|
|
28
|
+
import recentlyViewed from './src/sections/RecentlyViewed'
|
|
29
|
+
import richText from './src/sections/RichText'
|
|
30
|
+
import imageWithText from './src/sections/ImageWithText'
|
|
31
|
+
import multicolumn from './src/sections/Multicolumn'
|
|
32
|
+
import featureGridBlocks from './src/sections/FeatureGridBlocks'
|
|
33
|
+
import featureHighlights from './src/sections/FeatureHighlights'
|
|
34
|
+
import faq from './src/sections/Faq'
|
|
35
|
+
import collectionLinks from './src/sections/CollectionLinks'
|
|
36
|
+
import imageGallery from './src/sections/ImageGallery'
|
|
37
|
+
import timeline from './src/sections/Timeline'
|
|
38
|
+
import pageBody from './src/sections/PageBody'
|
|
39
|
+
import articleBody from './src/sections/ArticleBody'
|
|
40
|
+
import blogPosts from './src/sections/BlogPosts'
|
|
41
|
+
import teamFounders from './src/sections/TeamFounders'
|
|
42
|
+
import beforeAfter from './src/sections/BeforeAfter'
|
|
43
|
+
import testimonials from './src/sections/Testimonials'
|
|
44
|
+
import logoList from './src/sections/LogoList'
|
|
45
|
+
import trustBadges from './src/sections/TrustBadges'
|
|
46
|
+
import productReviews from './src/sections/ProductReviews'
|
|
47
|
+
import ugcGallery from './src/sections/UgcGallery'
|
|
48
|
+
import shopTheLook from './src/sections/ShopTheLook'
|
|
49
|
+
import comparisonTable from './src/sections/ComparisonTable'
|
|
50
|
+
import cartItems from './src/sections/CartItems'
|
|
51
|
+
import searchResults from './src/sections/SearchResults'
|
|
52
|
+
import account from './src/sections/Account'
|
|
53
|
+
import policyPage from './src/sections/PolicyPage'
|
|
54
|
+
import storeLocator from './src/sections/StoreLocator'
|
|
55
|
+
import newsletter from './src/sections/Newsletter'
|
|
56
|
+
import lineAddFriend from './src/sections/LineAddFriend'
|
|
57
|
+
import contactForm from './src/sections/ContactForm'
|
|
58
|
+
import notFound from './src/sections/NotFound'
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Nova — what the platform needs to know about this theme: its sections (in the
|
|
62
|
+
* order "Add section" lists them), its root provider, its page layout and the
|
|
63
|
+
* words the breadcrumb trail uses.
|
|
64
|
+
*/
|
|
65
|
+
export default defineTheme({
|
|
66
|
+
name: 'nova',
|
|
67
|
+
sections: [
|
|
68
|
+
header,
|
|
69
|
+
announcementBar,
|
|
70
|
+
footer,
|
|
71
|
+
group,
|
|
72
|
+
divider,
|
|
73
|
+
breadcrumbs,
|
|
74
|
+
hero,
|
|
75
|
+
slideshow,
|
|
76
|
+
videoHero,
|
|
77
|
+
promoBanner,
|
|
78
|
+
marquee,
|
|
79
|
+
collectionBanner,
|
|
80
|
+
productDetails,
|
|
81
|
+
mainCollection,
|
|
82
|
+
productGrid,
|
|
83
|
+
featuredCollection,
|
|
84
|
+
featuredProduct,
|
|
85
|
+
collectionList,
|
|
86
|
+
productRecommendations,
|
|
87
|
+
recentlyViewed,
|
|
88
|
+
richText,
|
|
89
|
+
imageWithText,
|
|
90
|
+
multicolumn,
|
|
91
|
+
featureGridBlocks,
|
|
92
|
+
featureHighlights,
|
|
93
|
+
faq,
|
|
94
|
+
collectionLinks,
|
|
95
|
+
imageGallery,
|
|
96
|
+
timeline,
|
|
97
|
+
pageBody,
|
|
98
|
+
articleBody,
|
|
99
|
+
blogPosts,
|
|
100
|
+
teamFounders,
|
|
101
|
+
beforeAfter,
|
|
102
|
+
testimonials,
|
|
103
|
+
logoList,
|
|
104
|
+
trustBadges,
|
|
105
|
+
productReviews,
|
|
106
|
+
ugcGallery,
|
|
107
|
+
shopTheLook,
|
|
108
|
+
comparisonTable,
|
|
109
|
+
cartItems,
|
|
110
|
+
searchResults,
|
|
111
|
+
account,
|
|
112
|
+
policyPage,
|
|
113
|
+
storeLocator,
|
|
114
|
+
newsletter,
|
|
115
|
+
lineAddFriend,
|
|
116
|
+
contactForm,
|
|
117
|
+
notFound,
|
|
118
|
+
],
|
|
119
|
+
Provider: ThemeRoot,
|
|
120
|
+
sharedSettings: SHARED_SETTINGS,
|
|
121
|
+
// Geist for headings and body, Geist Mono for codes.
|
|
122
|
+
// Geist is self-hosted (styles/fonts.css): no font CDN in front of the first paint.
|
|
123
|
+
stylesheets: [],
|
|
124
|
+
// Instructions to the merchant in the starter content: editor only, never on the live store.
|
|
125
|
+
starterText: STARTER_TEXT,
|
|
126
|
+
// Words Nova ships in defaults, templates and presets: shown in the page's language until the merchant writes their own.
|
|
127
|
+
// Renderers that test a value against the shipped English, or derive an unset one from data, are left alone.
|
|
128
|
+
shippedCopy: { english, prefix: 'copy.', keep: KEEP_SHIPPED_COPY, derivedWhenUnset: DERIVED_WHEN_UNSET },
|
|
129
|
+
Layout: Main,
|
|
130
|
+
labels: (locale) => {
|
|
131
|
+
const s = BUILTIN_STRINGS[locale.split('-')[0]] ?? STRINGS_EN
|
|
132
|
+
return { home: s.home, collections: s.collections, search: s.search, cart: s.cart, account: s.account }
|
|
133
|
+
},
|
|
134
|
+
})
|