@omega.js/web 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +98 -0
- package/README.md +640 -0
- package/bin/omega +2 -0
- package/bin/omega-web +2 -0
- package/bin/omg +2 -0
- package/core/_includes/admin/sections/sidebar.json +100 -0
- package/core/_includes/admin/sections/topbar.json +11 -0
- package/core/_includes/backend/sections/sidebar.json +39 -0
- package/core/_includes/backend/sections/topbar.json +16 -0
- package/core/_includes/core/body.html +102 -0
- package/core/_includes/core/foot.html +536 -0
- package/core/_includes/core/head.html +423 -0
- package/core/_includes/core/pricing/price-per-unit.html +33 -0
- package/core/_includes/core/showcase/entry-body.html +94 -0
- package/core/_includes/core/showcase/index-body.html +43 -0
- package/core/_includes/core/showcase/nav.html +60 -0
- package/core/_includes/frontend/sections/footer.json +74 -0
- package/core/_includes/frontend/sections/nav.json +70 -0
- package/core/_includes/global/sections/account.json +31 -0
- package/core/_includes/modules/engagement/giscus.html +26 -0
- package/core/_layouts/blueprint/404.html +10 -0
- package/core/_layouts/blueprint/about.html +10 -0
- package/core/_layouts/blueprint/account/index.html +11 -0
- package/core/_layouts/blueprint/admin/calendar/index.html +590 -0
- package/core/_layouts/blueprint/admin/dashboard/index.html +301 -0
- package/core/_layouts/blueprint/admin/firebase/index.html +214 -0
- package/core/_layouts/blueprint/admin/posts/editor.html +157 -0
- package/core/_layouts/blueprint/admin/posts/index.html +126 -0
- package/core/_layouts/blueprint/admin/stackblitz/index.html +30 -0
- package/core/_layouts/blueprint/admin/studio/index.html +85 -0
- package/core/_layouts/blueprint/admin/users/index.html +272 -0
- package/core/_layouts/blueprint/admin/users/new.html +82 -0
- package/core/_layouts/blueprint/admin/verts/index.html +204 -0
- package/core/_layouts/blueprint/alternatives/alternative.html +15 -0
- package/core/_layouts/blueprint/alternatives/index.html +10 -0
- package/core/_layouts/blueprint/app.html +10 -0
- package/core/_layouts/blueprint/auth/reset.html +19 -0
- package/core/_layouts/blueprint/auth/signin.html +19 -0
- package/core/_layouts/blueprint/auth/signup.html +19 -0
- package/core/_layouts/blueprint/auth/token.html +19 -0
- package/core/_layouts/blueprint/blog/categories/category.html +8 -0
- package/core/_layouts/blueprint/blog/categories/index.html +11 -0
- package/core/_layouts/blueprint/blog/index.html +10 -0
- package/core/_layouts/blueprint/blog/post.html +5 -0
- package/core/_layouts/blueprint/blog/tags/index.html +11 -0
- package/core/_layouts/blueprint/blog/tags/tag.html +8 -0
- package/core/_layouts/blueprint/careers.md +13 -0
- package/core/_layouts/blueprint/collection/category.html +9 -0
- package/core/_layouts/blueprint/collection/document.html +9 -0
- package/core/_layouts/blueprint/collection/index.html +9 -0
- package/core/_layouts/blueprint/connections/callback.html +11 -0
- package/core/_layouts/blueprint/contact.html +14 -0
- package/core/_layouts/blueprint/dashboard/index.html +10 -0
- package/core/_layouts/blueprint/download.html +20 -0
- package/core/_layouts/blueprint/extension/index.html +14 -0
- package/core/_layouts/blueprint/extension/installed.html +11 -0
- package/core/_layouts/blueprint/feedback.html +10 -0
- package/core/_layouts/blueprint/index.html +16 -0
- package/core/_layouts/blueprint/legal/cookies.md +57 -0
- package/core/_layouts/blueprint/legal/privacy.md +109 -0
- package/core/_layouts/blueprint/legal/terms.md +155 -0
- package/core/_layouts/blueprint/payment/checkout.html +15 -0
- package/core/_layouts/blueprint/payment/confirmation.html +14 -0
- package/core/_layouts/blueprint/portal/email-preferences.html +15 -0
- package/core/_layouts/blueprint/pricing.html +20 -0
- package/core/_layouts/blueprint/status.html +10 -0
- package/core/_layouts/blueprint/team/index.html +10 -0
- package/core/_layouts/blueprint/team/member.html +5 -0
- package/core/_layouts/blueprint/updates/index.html +10 -0
- package/core/_layouts/blueprint/updates/update.html +10 -0
- package/core/_layouts/core/root.html +45 -0
- package/core/_layouts/modules/utilities/redirect.html +129 -0
- package/core/css/_studio.scss +237 -0
- package/core/css/components/_index.scss +146 -0
- package/core/css/core/_.scss +0 -0
- package/core/css/core/_alert.scss +87 -0
- package/core/css/core/_animations.scss +343 -0
- package/core/css/core/_bindings.scss +116 -0
- package/core/css/core/_blog-search.scss +57 -0
- package/core/css/core/_chatsy.scss +61 -0
- package/core/css/core/_consent.scss +424 -0
- package/core/css/core/_custom-font-awesome.scss +146 -0
- package/core/css/core/_exit-popup.scss +42 -0
- package/core/css/core/_generated-badge.scss +33 -0
- package/core/css/core/_initialize.scss +29 -0
- package/core/css/core/_lazy-loading.scss +104 -0
- package/core/css/core/_social-sharing.scss +41 -0
- package/core/css/core/_tones.scss +32 -0
- package/core/css/core/_utilities.scss +157 -0
- package/core/css/main.scss +54 -0
- package/core/css/motion/_index.scss +368 -0
- package/core/css/pages/404/index.scss +0 -0
- package/core/css/pages/admin/calendar/index.scss +692 -0
- package/core/css/pages/admin/firebase/index.scss +33 -0
- package/core/css/pages/admin/index.scss +9 -0
- package/core/css/pages/admin/users/index.scss +9 -0
- package/core/css/pages/admin/verts/index.scss +9 -0
- package/core/css/pages/alternatives/[alternative]/index.scss +0 -0
- package/core/css/pages/blog/[slug].scss +55 -0
- package/core/css/pages/dashboard/account/index.scss +242 -0
- package/core/css/pages/download/index.scss +480 -0
- package/core/css/pages/extension/installed/index.scss +317 -0
- package/core/css/pages/feedback/index.scss +31 -0
- package/core/css/pages/payment/confirmation/index.scss +14 -0
- package/core/css/pages/pricing/index.scss +0 -0
- package/core/css/pages/status/index.scss +162 -0
- package/core/css/pages/test/libraries/layers/index.scss +28 -0
- package/core/css/pages/updates/[update].scss +46 -0
- package/core/css/pages/updates/index.scss +13 -0
- package/core/css/shell/_index.scss +207 -0
- package/core/css/tokens/_index.scss +166 -0
- package/core/icons/flags/ar.svg +1 -0
- package/core/icons/flags/bd.svg +1 -0
- package/core/icons/flags/ca.svg +1 -0
- package/core/icons/flags/ch.svg +1 -0
- package/core/icons/flags/cn.svg +1 -0
- package/core/icons/flags/co.svg +1 -0
- package/core/icons/flags/cw.svg +1 -0
- package/core/icons/flags/cz.svg +1 -0
- package/core/icons/flags/de.svg +1 -0
- package/core/icons/flags/dk.svg +1 -0
- package/core/icons/flags/eg.svg +1 -0
- package/core/icons/flags/es.svg +1 -0
- package/core/icons/flags/fi.svg +1 -0
- package/core/icons/flags/fr.svg +1 -0
- package/core/icons/flags/gb.svg +1 -0
- package/core/icons/flags/gq.svg +1 -0
- package/core/icons/flags/gr.svg +1 -0
- package/core/icons/flags/gt.svg +1 -0
- package/core/icons/flags/hn.svg +1 -0
- package/core/icons/flags/id.svg +1 -0
- package/core/icons/flags/ie.svg +1 -0
- package/core/icons/flags/in.svg +1 -0
- package/core/icons/flags/ir.svg +1 -0
- package/core/icons/flags/it.svg +1 -0
- package/core/icons/flags/jp.svg +1 -0
- package/core/icons/flags/kp.svg +1 -0
- package/core/icons/flags/kr.svg +1 -0
- package/core/icons/flags/ly.svg +1 -0
- package/core/icons/flags/ma.svg +1 -0
- package/core/icons/flags/mu.svg +1 -0
- package/core/icons/flags/mx.svg +1 -0
- package/core/icons/flags/ng.svg +1 -0
- package/core/icons/flags/pa.svg +1 -0
- package/core/icons/flags/ph.svg +1 -0
- package/core/icons/flags/pk.svg +1 -0
- package/core/icons/flags/pt.svg +1 -0
- package/core/icons/flags/ru.svg +1 -0
- package/core/icons/flags/sa.svg +1 -0
- package/core/icons/flags/sd.svg +1 -0
- package/core/icons/flags/se.svg +1 -0
- package/core/icons/flags/th.svg +1 -0
- package/core/icons/flags/tm.svg +1 -0
- package/core/icons/flags/tr.svg +1 -0
- package/core/icons/flags/us.svg +1 -0
- package/core/icons/flags/uy.svg +1 -0
- package/core/icons/flags/vn.svg +1 -0
- package/core/icons/flags/za.svg +1 -0
- package/core/images/exit-popup/subscriber-1.jpg +0 -0
- package/core/images/exit-popup/subscriber-2.jpg +0 -0
- package/core/images/exit-popup/subscriber-3.jpg +0 -0
- package/core/images/exit-popup/subscriber-4.jpg +0 -0
- package/core/images/placeholder/photo-1.jpg +0 -0
- package/core/images/placeholder/photo-2.jpg +0 -0
- package/core/images/placeholder/photo-3.jpg +0 -0
- package/core/js/core/analytics-loader.js +253 -0
- package/core/js/core/app-shell.js +136 -0
- package/core/js/core/appearance.js +195 -0
- package/core/js/core/auth.js +457 -0
- package/core/js/core/complete.js +72 -0
- package/core/js/core/consent.js +384 -0
- package/core/js/core/dev-icon-audit.js +63 -0
- package/core/js/core/dev-palette.js +670 -0
- package/core/js/core/dev-sections.js +53 -0
- package/core/js/core/exit-popup.js +276 -0
- package/core/js/core/initialize.js +8 -0
- package/core/js/core/language-switcher.js +167 -0
- package/core/js/core/lazy-loading.js +479 -0
- package/core/js/core/motion.js +28 -0
- package/core/js/core/query-strings.js +146 -0
- package/core/js/core/service-worker.js +28 -0
- package/core/js/core/social-sharing.js +293 -0
- package/core/js/first-paint.js +35 -0
- package/core/js/layouts/modules/utilities/redirect.js +122 -0
- package/core/js/libs/admin-helpers.js +62 -0
- package/core/js/libs/alert-dismiss.js +35 -0
- package/core/js/libs/analytics.js +368 -0
- package/core/js/libs/auth/email.js +144 -0
- package/core/js/libs/auth/errors.js +119 -0
- package/core/js/libs/auth/forms.js +206 -0
- package/core/js/libs/auth/index.js +181 -0
- package/core/js/libs/auth/oauth.js +394 -0
- package/core/js/libs/auth/orphan.js +110 -0
- package/core/js/libs/auth/password-toggle.js +44 -0
- package/core/js/libs/auth/session-params.js +266 -0
- package/core/js/libs/auth/tracking.js +41 -0
- package/core/js/libs/charts.js +516 -0
- package/core/js/libs/consent-region.js +127 -0
- package/core/js/libs/dev.js +150 -0
- package/core/js/libs/graph.js +201 -0
- package/core/js/libs/initialize-tooltips.js +31 -0
- package/core/js/libs/logger.js +38 -0
- package/core/js/libs/omega-copy.js +89 -0
- package/core/js/libs/path-prefix.js +44 -0
- package/core/js/libs/payment-config.js +76 -0
- package/core/js/libs/recaptcha.js +94 -0
- package/core/js/libs/sale-name.js +295 -0
- package/core/js/libs/showcase-frames.js +37 -0
- package/core/js/libs/srcset.js +69 -0
- package/core/js/libs/tracking-consent.js +161 -0
- package/core/js/main.js +144 -0
- package/core/js/pages/404/index.js +57 -0
- package/core/js/pages/admin/calendar/calendar-core.js +701 -0
- package/core/js/pages/admin/calendar/calendar-events.js +853 -0
- package/core/js/pages/admin/calendar/calendar-renderer.js +807 -0
- package/core/js/pages/admin/calendar/campaign-preview.js +105 -0
- package/core/js/pages/admin/calendar/index.js +40 -0
- package/core/js/pages/admin/firebase/index.js +727 -0
- package/core/js/pages/admin/index.js +531 -0
- package/core/js/pages/admin/posts/editor/index.js +230 -0
- package/core/js/pages/admin/posts/index.js +237 -0
- package/core/js/pages/admin/studio/index.js +538 -0
- package/core/js/pages/admin/users/index.js +669 -0
- package/core/js/pages/admin/users/new/index.js +65 -0
- package/core/js/pages/admin/verts/index.js +407 -0
- package/core/js/pages/alternatives/[alternative]/index.js +17 -0
- package/core/js/pages/app/index.js +135 -0
- package/core/js/pages/blog/[slug].js +132 -0
- package/core/js/pages/blog/_search.mjs +108 -0
- package/core/js/pages/blog/index.js +193 -0
- package/core/js/pages/blog/page/[num]/index.js +7 -0
- package/core/js/pages/connections/callback/index.js +148 -0
- package/core/js/pages/contact/index.js +170 -0
- package/core/js/pages/cookies.js +2 -0
- package/core/js/pages/dashboard/account/index.js +366 -0
- package/core/js/pages/dashboard/account/modules/orders.js +82 -0
- package/core/js/pages/dashboard/account/sections/api-keys.js +149 -0
- package/core/js/pages/dashboard/account/sections/billing.js +1667 -0
- package/core/js/pages/dashboard/account/sections/connections.js +333 -0
- package/core/js/pages/dashboard/account/sections/data-request.js +225 -0
- package/core/js/pages/dashboard/account/sections/delete.js +80 -0
- package/core/js/pages/dashboard/account/sections/notifications.js +167 -0
- package/core/js/pages/dashboard/account/sections/orders.js +151 -0
- package/core/js/pages/dashboard/account/sections/profile.js +200 -0
- package/core/js/pages/dashboard/account/sections/referrals.js +217 -0
- package/core/js/pages/dashboard/account/sections/refund.js +253 -0
- package/core/js/pages/dashboard/account/sections/security.js +726 -0
- package/core/js/pages/dashboard/account/sections/team.js +247 -0
- package/core/js/pages/download/index.js +418 -0
- package/core/js/pages/extension/index.js +164 -0
- package/core/js/pages/extension/installed/index.js +135 -0
- package/core/js/pages/feedback/index.js +193 -0
- package/core/js/pages/legal/_document.js +91 -0
- package/core/js/pages/payment/checkout/index.js +420 -0
- package/core/js/pages/payment/checkout/modules/api.js +139 -0
- package/core/js/pages/payment/checkout/modules/dev-section.js +175 -0
- package/core/js/pages/payment/checkout/modules/discount.js +69 -0
- package/core/js/pages/payment/checkout/modules/pricing.js +73 -0
- package/core/js/pages/payment/checkout/modules/state.js +339 -0
- package/core/js/pages/payment/checkout/modules/tracking.js +54 -0
- package/core/js/pages/payment/confirmation/index.js +91 -0
- package/core/js/pages/payment/confirmation/modules/celebration.js +45 -0
- package/core/js/pages/payment/confirmation/modules/state.js +112 -0
- package/core/js/pages/payment/confirmation/modules/tracking.js +133 -0
- package/core/js/pages/payment/confirmation/modules/verify.js +142 -0
- package/core/js/pages/portal/email-preferences/index.js +183 -0
- package/core/js/pages/pricing/index.js +425 -0
- package/core/js/pages/privacy.js +2 -0
- package/core/js/pages/reset/index.js +12 -0
- package/core/js/pages/signin/index.js +22 -0
- package/core/js/pages/signup/index.js +23 -0
- package/core/js/pages/status/index.js +687 -0
- package/core/js/pages/terms.js +2 -0
- package/core/js/pages/test/components/[category]/[name]/index.js +26 -0
- package/core/js/pages/test/libraries/appearance/index.js +220 -0
- package/core/js/pages/test/libraries/form-manager/index.js +328 -0
- package/core/js/pages/test/libraries/layers/index.js +16 -0
- package/core/js/pages/test/libraries/verts/index.js +68 -0
- package/core/js/pages/test/sections/[category]/[name]/index.js +28 -0
- package/core/js/pages/test/styleguide/index.js +35 -0
- package/core/js/pages/token/index.js +203 -0
- package/core/logos/brandmarks/original/apple-app-store.svg +1 -0
- package/core/logos/brandmarks/original/apple.svg +6 -0
- package/core/logos/brandmarks/original/bitbucket.svg +14 -0
- package/core/logos/brandmarks/original/bitcoin.svg +1 -0
- package/core/logos/brandmarks/original/bluesky.svg +7 -0
- package/core/logos/brandmarks/original/bootstrap.svg +43 -0
- package/core/logos/brandmarks/original/brave.svg +1 -0
- package/core/logos/brandmarks/original/chrome.svg +1 -0
- package/core/logos/brandmarks/original/discord.svg +1 -0
- package/core/logos/brandmarks/original/dropbox.svg +10 -0
- package/core/logos/brandmarks/original/edge.svg +1 -0
- package/core/logos/brandmarks/original/facebook-f.svg +1 -0
- package/core/logos/brandmarks/original/facebook.svg +8 -0
- package/core/logos/brandmarks/original/figma.svg +10 -0
- package/core/logos/brandmarks/original/firefox.svg +1 -0
- package/core/logos/brandmarks/original/github.svg +6 -0
- package/core/logos/brandmarks/original/gitlab.svg +17 -0
- package/core/logos/brandmarks/original/google-a-s.svg +1 -0
- package/core/logos/brandmarks/original/google-chrome-webstore.svg +49 -0
- package/core/logos/brandmarks/original/google-play-store.svg +1 -0
- package/core/logos/brandmarks/original/google-web-search.svg +1 -0
- package/core/logos/brandmarks/original/google.svg +1 -0
- package/core/logos/brandmarks/original/gulp.svg +4 -0
- package/core/logos/brandmarks/original/html-5.svg +1 -0
- package/core/logos/brandmarks/original/instagram.svg +1 -0
- package/core/logos/brandmarks/original/javascript.svg +1 -0
- package/core/logos/brandmarks/original/jira.svg +18 -0
- package/core/logos/brandmarks/original/kick.svg +7 -0
- package/core/logos/brandmarks/original/linkedin.svg +1 -0
- package/core/logos/brandmarks/original/linux.svg +28 -0
- package/core/logos/brandmarks/original/messenger.svg +16 -0
- package/core/logos/brandmarks/original/microsoft.svg +1 -0
- package/core/logos/brandmarks/original/npm.svg +8 -0
- package/core/logos/brandmarks/original/opera.svg +1 -0
- package/core/logos/brandmarks/original/patreon.svg +6 -0
- package/core/logos/brandmarks/original/pinterest.svg +6 -0
- package/core/logos/brandmarks/original/reddit.svg +1 -0
- package/core/logos/brandmarks/original/safari.svg +31 -0
- package/core/logos/brandmarks/original/sass.svg +3 -0
- package/core/logos/brandmarks/original/signal.svg +6 -0
- package/core/logos/brandmarks/original/skype.svg +47 -0
- package/core/logos/brandmarks/original/slack.svg +33 -0
- package/core/logos/brandmarks/original/soundcloud.svg +1 -0
- package/core/logos/brandmarks/original/spotify.svg +5 -0
- package/core/logos/brandmarks/original/steam.svg +6 -0
- package/core/logos/brandmarks/original/telegram.svg +14 -0
- package/core/logos/brandmarks/original/tiktok.svg +1 -0
- package/core/logos/brandmarks/original/trello.svg +16 -0
- package/core/logos/brandmarks/original/tumblr.svg +1 -0
- package/core/logos/brandmarks/original/twitch.svg +6 -0
- package/core/logos/brandmarks/original/twitter.svg +6 -0
- package/core/logos/brandmarks/original/unity.svg +6 -0
- package/core/logos/brandmarks/original/x.svg +7 -0
- package/core/logos/brandmarks/original/yahoo-y.svg +1 -0
- package/core/logos/brandmarks/original/youtube-square.svg +1 -0
- package/core/logos/brandmarks/original/youtube.svg +1 -0
- package/core/logos/combomarks/dark/airbnb.svg +30 -0
- package/core/logos/combomarks/dark/slack.svg +38 -0
- package/core/logos/combomarks/dark/spotify.svg +35 -0
- package/core/logos/combomarks/dark/twilio.svg +26 -0
- package/core/logos/combomarks/dark/weebly.svg +35 -0
- package/core/logos/combomarks/gray/airbnb.svg +33 -0
- package/core/logos/combomarks/gray/alphabet.svg +23 -0
- package/core/logos/combomarks/gray/amazon.svg +38 -0
- package/core/logos/combomarks/gray/boring-company.svg +91 -0
- package/core/logos/combomarks/gray/burberry.svg +239 -0
- package/core/logos/combomarks/gray/embark.svg +21 -0
- package/core/logos/combomarks/gray/fitbit.svg +61 -0
- package/core/logos/combomarks/gray/fred-perry.svg +94 -0
- package/core/logos/combomarks/gray/google.svg +27 -0
- package/core/logos/combomarks/gray/hollister.svg +34 -0
- package/core/logos/combomarks/gray/hubspot.svg +27 -0
- package/core/logos/combomarks/gray/kaplan.svg +33 -0
- package/core/logos/combomarks/gray/lenovo.svg +27 -0
- package/core/logos/combomarks/gray/levis.svg +25 -0
- package/core/logos/combomarks/gray/mapbox.svg +37 -0
- package/core/logos/combomarks/gray/netflix.svg +15 -0
- package/core/logos/combomarks/gray/new-balance.svg +32 -0
- package/core/logos/combomarks/gray/nike.svg +17 -0
- package/core/logos/combomarks/gray/paypal.svg +41 -0
- package/core/logos/combomarks/gray/puma.svg +82 -0
- package/core/logos/combomarks/gray/samsung.svg +26 -0
- package/core/logos/combomarks/gray/shopify.svg +36 -0
- package/core/logos/combomarks/gray/slack.svg +42 -0
- package/core/logos/combomarks/gray/spotify.svg +38 -0
- package/core/logos/combomarks/gray/stripe.svg +24 -0
- package/core/logos/combomarks/gray/tnf.svg +30 -0
- package/core/logos/combomarks/gray/twilio.svg +29 -0
- package/core/logos/combomarks/gray/uber.svg +24 -0
- package/core/logos/combomarks/gray/weebly.svg +38 -0
- package/core/logos/combomarks/original/airbnb.svg +33 -0
- package/core/logos/combomarks/original/alphabet.svg +23 -0
- package/core/logos/combomarks/original/amazon.svg +38 -0
- package/core/logos/combomarks/original/asana.svg +8 -0
- package/core/logos/combomarks/original/boring-company.svg +91 -0
- package/core/logos/combomarks/original/discord.svg +6 -0
- package/core/logos/combomarks/original/embark.svg +24 -0
- package/core/logos/combomarks/original/fitbit.svg +60 -0
- package/core/logos/combomarks/original/github.svg +6 -0
- package/core/logos/combomarks/original/gitlab.svg +20 -0
- package/core/logos/combomarks/original/google.svg +28 -0
- package/core/logos/combomarks/original/hubspot.svg +29 -0
- package/core/logos/combomarks/original/instagram.svg +7 -0
- package/core/logos/combomarks/original/kickstarter.svg +6 -0
- package/core/logos/combomarks/original/lenovo.svg +24 -0
- package/core/logos/combomarks/original/linkedin.svg +6 -0
- package/core/logos/combomarks/original/mapbox.svg +39 -0
- package/core/logos/combomarks/original/mastodon.svg +7 -0
- package/core/logos/combomarks/original/medium.svg +6 -0
- package/core/logos/combomarks/original/meta.svg +22 -0
- package/core/logos/combomarks/original/microsoft.svg +13 -0
- package/core/logos/combomarks/original/monday.svg +12 -0
- package/core/logos/combomarks/original/netflix.svg +15 -0
- package/core/logos/combomarks/original/notion.svg +9 -0
- package/core/logos/combomarks/original/paypal.svg +41 -0
- package/core/logos/combomarks/original/reddit.svg +13 -0
- package/core/logos/combomarks/original/samsung.svg +25 -0
- package/core/logos/combomarks/original/shopify.svg +35 -0
- package/core/logos/combomarks/original/slack.svg +47 -0
- package/core/logos/combomarks/original/spotify.svg +37 -0
- package/core/logos/combomarks/original/stackoverflow.svg +28 -0
- package/core/logos/combomarks/original/stripe.svg +24 -0
- package/core/logos/combomarks/original/tiktok.svg +12 -0
- package/core/logos/combomarks/original/tumblr.svg +6 -0
- package/core/logos/combomarks/original/uber.svg +24 -0
- package/core/logos/combomarks/original/weebly.svg +34 -0
- package/core/logos/combomarks/original/whatsapp.svg +20 -0
- package/core/logos/combomarks/original/youtube.svg +10 -0
- package/core/logos/combomarks/original/zoom.svg +7 -0
- package/core/logos/combomarks/white/airbnb.svg +33 -0
- package/core/logos/combomarks/white/alphabet.svg +23 -0
- package/core/logos/combomarks/white/amazon.svg +38 -0
- package/core/logos/combomarks/white/boring-company.svg +91 -0
- package/core/logos/combomarks/white/embark.svg +21 -0
- package/core/logos/combomarks/white/fitbit.svg +61 -0
- package/core/logos/combomarks/white/google.svg +27 -0
- package/core/logos/combomarks/white/hubspot.svg +27 -0
- package/core/logos/combomarks/white/kaplan.svg +33 -0
- package/core/logos/combomarks/white/lenovo.svg +27 -0
- package/core/logos/combomarks/white/mapbox.svg +37 -0
- package/core/logos/combomarks/white/netflix.svg +15 -0
- package/core/logos/combomarks/white/paypal.svg +40 -0
- package/core/logos/combomarks/white/samsung.svg +26 -0
- package/core/logos/combomarks/white/shopify.svg +36 -0
- package/core/logos/combomarks/white/slack.svg +42 -0
- package/core/logos/combomarks/white/spotify.svg +38 -0
- package/core/logos/combomarks/white/stripe.svg +24 -0
- package/core/logos/combomarks/white/twilio.svg +29 -0
- package/core/logos/combomarks/white/uber.svg +24 -0
- package/core/logos/combomarks/white/weebly.svg +38 -0
- package/defaults/pages/404.md +4 -0
- package/defaults/pages/about.md +4 -0
- package/defaults/pages/admin/calendar/index.html +4 -0
- package/defaults/pages/admin/firebase/index.html +4 -0
- package/defaults/pages/admin/index.md +4 -0
- package/defaults/pages/admin/posts/editor.html +4 -0
- package/defaults/pages/admin/posts/index.html +4 -0
- package/defaults/pages/admin/stackblitz/index.html +4 -0
- package/defaults/pages/admin/studio/index.html +4 -0
- package/defaults/pages/admin/users/index.html +4 -0
- package/defaults/pages/admin/users/new.html +4 -0
- package/defaults/pages/admin/verts/index.html +4 -0
- package/defaults/pages/ads-txt.html +11 -0
- package/defaults/pages/alternatives/index.md +4 -0
- package/defaults/pages/app.md +4 -0
- package/defaults/pages/auth/reset.md +4 -0
- package/defaults/pages/auth/signin.md +4 -0
- package/defaults/pages/auth/signup.md +4 -0
- package/defaults/pages/auth/token.md +4 -0
- package/defaults/pages/blog/categories/category.html +21 -0
- package/defaults/pages/blog/categories.md +4 -0
- package/defaults/pages/blog/index-json.html +27 -0
- package/defaults/pages/blog/tags/tag.html +21 -0
- package/defaults/pages/blog/tags.md +4 -0
- package/defaults/pages/blog.md +22 -0
- package/defaults/pages/careers.md +4 -0
- package/defaults/pages/connections/callback.md +4 -0
- package/defaults/pages/contact.md +4 -0
- package/defaults/pages/dashboard/account.md +4 -0
- package/defaults/pages/dashboard/index.md +12 -0
- package/defaults/pages/download.md +4 -0
- package/defaults/pages/extension/index.html +4 -0
- package/defaults/pages/extension/installed.html +4 -0
- package/defaults/pages/feedback.md +4 -0
- package/defaults/pages/feeds/posts-json.html +40 -0
- package/defaults/pages/feeds/posts-xml.html +38 -0
- package/defaults/pages/humans.html +25 -0
- package/defaults/pages/index.md +4 -0
- package/defaults/pages/legal/cookies.md +4 -0
- package/defaults/pages/legal/privacy.md +4 -0
- package/defaults/pages/legal/terms.md +4 -0
- package/defaults/pages/llms-txt.html +46 -0
- package/defaults/pages/opensearch.html +16 -0
- package/defaults/pages/pages-json.html +42 -0
- package/defaults/pages/payment/checkout.md +4 -0
- package/defaults/pages/payment/confirmation.md +4 -0
- package/defaults/pages/portal/email-preferences.md +4 -0
- package/defaults/pages/pricing.md +4 -0
- package/defaults/pages/redirects/account.md +12 -0
- package/defaults/pages/redirects/admin/dashboard.md +11 -0
- package/defaults/pages/redirects/auth/change-password.md +9 -0
- package/defaults/pages/redirects/auth/forgot.md +9 -0
- package/defaults/pages/redirects/auth/join.md +9 -0
- package/defaults/pages/redirects/auth/login.md +9 -0
- package/defaults/pages/redirects/auth/recover.md +9 -0
- package/defaults/pages/redirects/auth/register.md +9 -0
- package/defaults/pages/redirects/auth/reset-password.md +9 -0
- package/defaults/pages/redirects/billing/cancel.md +9 -0
- package/defaults/pages/redirects/billing/refund.md +9 -0
- package/defaults/pages/robots.html +36 -0
- package/defaults/pages/security-txt.html +11 -0
- package/defaults/pages/sitemap.html +37 -0
- package/defaults/pages/status.md +4 -0
- package/defaults/pages/team/index.md +4 -0
- package/defaults/pages/test/account/dashboard.html +16 -0
- package/defaults/pages/test/index.md +12 -0
- package/defaults/pages/test/libraries/appearance.html +268 -0
- package/defaults/pages/test/libraries/cover.html +50 -0
- package/defaults/pages/test/libraries/error.html +30 -0
- package/defaults/pages/test/libraries/firestore.html +202 -0
- package/defaults/pages/test/libraries/form-manager.html +374 -0
- package/defaults/pages/test/libraries/layers.html +52 -0
- package/defaults/pages/test/libraries/lazy-loading.html +450 -0
- package/defaults/pages/test/libraries/verts.html +149 -0
- package/defaults/pages/test/redirect/external.md +13 -0
- package/defaults/pages/test/redirect/internal.md +13 -0
- package/defaults/pages/test/styleguide/index.html +588 -0
- package/defaults/pages/test/translation/index.md +50 -0
- package/defaults/pages/updates/index.md +4 -0
- package/defaults/sample-posts/2026-01-12-welcome-to-the-blog.md +26 -0
- package/defaults/sample-posts/2026-02-03-a-field-guide-to-good-defaults.md +50 -0
- package/defaults/sample-posts/2026-02-24-shipping-week-notes.md +37 -0
- package/defaults/sample-posts/2026-03-17-the-case-for-one-config.md +36 -0
- package/defaults/sample-posts/2026-04-09-write-release-notes-people-read.md +34 -0
- package/defaults/sample-posts/2026-05-21-dark-mode-done-properly.md +38 -0
- package/defaults/sample-posts/2026-06-02-the-boring-deploy-is-the-good-deploy.md +30 -0
- package/defaults/sample-posts/2026-06-11-naming-things-a-survival-guide.md +30 -0
- package/defaults/sample-posts/2026-06-19-your-pricing-page-is-a-product.md +28 -0
- package/defaults/sample-posts/2026-06-30-email-is-an-api-with-feelings.md +28 -0
- package/defaults/sample-posts/2026-07-08-ship-the-docs-with-the-diff.md +30 -0
- package/defaults/sample-team/avery-quinn.md +22 -0
- package/defaults/sample-team/jordan-reyes.md +25 -0
- package/defaults/sample-team/riley-nakamura.md +22 -0
- package/defaults/sample-team/sam-okafor.md +22 -0
- package/defaults/sample-updates/v1.0.0.md +28 -0
- package/defaults/sample-updates/v1.1.0.md +27 -0
- package/defaults/sample-updates/v1.2.0.md +27 -0
- package/defaults/sample-updates/v1.3.0.md +28 -0
- package/defaults/showcase/components.html +62 -0
- package/defaults/showcase/entry.html +76 -0
- package/defaults/showcase/frame.html +62 -0
- package/defaults/showcase/index.html +59 -0
- package/dist/assets.js +1349 -0
- package/dist/brand-tokens.js +195 -0
- package/dist/build.js +192 -0
- package/dist/cachebreak-html.js +71 -0
- package/dist/cli-run.js +25 -0
- package/dist/cli.js +47 -0
- package/dist/collections.js +183 -0
- package/dist/commands/audit.js +470 -0
- package/dist/commands/build.js +197 -0
- package/dist/commands/clean.js +18 -0
- package/dist/commands/customize.js +125 -0
- package/dist/commands/deploy.js +441 -0
- package/dist/commands/dev.js +1067 -0
- package/dist/commands/install.js +31 -0
- package/dist/commands/lib/deploy-precheck.js +43 -0
- package/dist/commands/lib/ensure-target.js +115 -0
- package/dist/commands/migrate.js +86 -0
- package/dist/commands/purge.js +31 -0
- package/dist/commands/test.js +237 -0
- package/dist/commands/translate.js +57 -0
- package/dist/commands/update.js +22 -0
- package/dist/commands/version.js +11 -0
- package/dist/config-sections.js +245 -0
- package/dist/consumer-scan.js +118 -0
- package/dist/consumer.js +49 -0
- package/dist/customize.js +328 -0
- package/dist/decisions.js +153 -0
- package/dist/dist-audit.js +417 -0
- package/dist/dynamic-pages.js +357 -0
- package/dist/engine.js +1402 -0
- package/dist/firebase-auth-helpers.js +198 -0
- package/dist/font-metrics.js +420 -0
- package/dist/frontmatter-liquid.js +253 -0
- package/dist/github-secrets.js +80 -0
- package/dist/hero-animations.js +170 -0
- package/dist/imagemin.js +261 -0
- package/dist/index.js +41 -0
- package/dist/inline-icons.js +65 -0
- package/dist/language-flags.js +55 -0
- package/dist/layers.js +80 -0
- package/dist/layouts.js +44 -0
- package/dist/limit-collections.js +199 -0
- package/dist/link-resolver.js +303 -0
- package/dist/markdown-images.js +85 -0
- package/dist/merge.js +20 -0
- package/dist/migrate/codemod.js +172 -0
- package/dist/migrate/config-convert.js +448 -0
- package/dist/migrate/consumer-assets.js +130 -0
- package/dist/migrate/index.js +223 -0
- package/dist/migrate/lint.js +108 -0
- package/dist/migrate/rules.js +1929 -0
- package/dist/minify-html.js +148 -0
- package/dist/mode-helpers.js +96 -0
- package/dist/omega-bin.js +7 -0
- package/dist/overrides.js +190 -0
- package/dist/path-prefix.js +167 -0
- package/dist/paths.js +37 -0
- package/dist/pricing.js +301 -0
- package/dist/purge.js +95 -0
- package/dist/redirect-page.js +45 -0
- package/dist/sample-content.js +210 -0
- package/dist/scaffold.js +123 -0
- package/dist/sections.js +810 -0
- package/dist/service-worker.js +200 -0
- package/dist/social-pages.js +142 -0
- package/dist/srcset.js +67 -0
- package/dist/static-assets.js +154 -0
- package/dist/target-shortlinks.js +123 -0
- package/dist/theme-vocabulary.js +76 -0
- package/dist/translate/collect-text-nodes.js +93 -0
- package/dist/translate/default-routes.js +152 -0
- package/dist/translate/generate-defaults.js +297 -0
- package/dist/translate/index.js +568 -0
- package/dist/translate/packaged-defaults.js +127 -0
- package/dist/translate/sitemap.js +108 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/actions-secrets.js +145 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/bare-requires.js +153 -0
- package/dist/vendor/devkit/bundle.js +292 -0
- package/dist/vendor/devkit/ci-workflows.js +520 -0
- package/dist/vendor/devkit/cli-router.js +156 -0
- package/dist/vendor/devkit/command-path.js +46 -0
- package/dist/vendor/devkit/defaults-engine.js +372 -0
- package/dist/vendor/devkit/deploy-precheck.js +54 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/deploy.js +286 -0
- package/dist/vendor/devkit/env-watch.js +132 -0
- package/dist/vendor/devkit/framework-deps.js +46 -0
- package/dist/vendor/devkit/icons.js +178 -0
- package/dist/vendor/devkit/license.js +155 -0
- package/dist/vendor/devkit/local-https.js +360 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/merge-line-files.js +296 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/reads.js +274 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/scaffold-guard.js +96 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/strip-dev-blocks-plugin.js +29 -0
- package/dist/vendor/devkit/strip-dev-blocks.js +32 -0
- package/dist/vendor/devkit/target-secrets.js +165 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/translate/cache.js +84 -0
- package/dist/vendor/devkit/translate/engine.js +243 -0
- package/dist/vendor/devkit/translate/index.js +49 -0
- package/dist/vendor/devkit/translate/languages.js +134 -0
- package/dist/vendor/devkit/translate/providers.js +188 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/dist/vendor/template-kit/data/language-flags.js +54 -0
- package/dist/vendor/template-kit/data/languages.js +195 -0
- package/dist/vendor/template-kit/data/social-urls.js +26 -0
- package/dist/vendor/template-kit/filters.js +227 -0
- package/dist/vendor/template-kit/index.js +28 -0
- package/dist/vendor/template-kit/jekyll-compat.js +268 -0
- package/dist/vendor/template-kit/register-liquid.js +0 -0
- package/dist/vendor/template-kit/tags/collections.js +191 -0
- package/dist/vendor/template-kit/tags/conditionals.js +101 -0
- package/dist/vendor/template-kit/tags/content.js +175 -0
- package/dist/vendor/template-kit/tags/index.js +33 -0
- package/dist/vendor/template-kit/tags/media.js +376 -0
- package/dist/vendor/template-kit/variable-resolver.js +163 -0
- package/docs/ads-system.md +109 -0
- package/docs/classy-v2/DIRECTION.md +92 -0
- package/docs/classy-v2/draft-1.html +1932 -0
- package/docs/classy-v2/draft-2.html +1956 -0
- package/docs/frontmatter.md +153 -0
- package/docs/index.md +254 -0
- package/docs/libs.md +298 -0
- package/docs/omega-sections-spec.md +159 -0
- package/docs/page-contract.md +112 -0
- package/docs/sections.md +845 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/template-kit.md +128 -0
- package/docs/test-framework.md +163 -0
- package/package.json +122 -0
- package/runtime/boot.js +149 -0
- package/runtime/icons.js +77 -0
- package/runtime/manager.js +36 -0
- package/scaffold/.github/workflows/build.yml +139 -0
- package/scaffold/.nvmrc +1 -0
- package/scaffold/AGENTS.md +55 -0
- package/scaffold/CLAUDE.md +1 -0
- package/scaffold/_.gitattributes +4 -0
- package/scaffold/_.gitignore +27 -0
- package/scaffold/config/omega.json5 +20 -0
- package/scaffold/src/assets/css/pages/.gitkeep +0 -0
- package/scaffold/src/assets/images/.gitkeep +0 -0
- package/scaffold/src/assets/js/pages/.gitkeep +0 -0
- package/scaffold/src/pages/.gitkeep +0 -0
- package/scaffold/src/pages/example.md.txt +94 -0
- package/scaffold/src/service-worker.js +16 -0
- package/sw/entry.js +19 -0
- package/sw/manager.js +281 -0
- package/themes/_template/README.md +115 -0
- package/themes/_template/_config.scss +60 -0
- package/themes/_template/_theme.js +14 -0
- package/themes/_template/_theme.scss +28 -0
- package/themes/_template/css/base/_root.scss +19 -0
- package/themes/_template/css/components/_components.scss +23 -0
- package/themes/base/README.md +5 -0
- package/themes/base/_components/data/org-chart/component.html +33 -0
- package/themes/base/_components/data/org-chart/component.json5 +33 -0
- package/themes/base/_components/data/org-chart/component.scss +183 -0
- package/themes/base/_components/heading/masthead/component.html +22 -0
- package/themes/base/_components/heading/masthead/component.json5 +30 -0
- package/themes/base/_components/heading/section-head/component.html +18 -0
- package/themes/base/_components/heading/section-head/component.json5 +27 -0
- package/themes/base/_components/pricing/features/component.html +29 -0
- package/themes/base/_components/pricing/features/component.json5 +30 -0
- package/themes/base/_hero/orbit/index.html +30 -0
- package/themes/base/_hero/orbit/script.js +33 -0
- package/themes/base/_hero/orbit/style.scss +133 -0
- package/themes/base/_includes/admin/sections/sidebar.html +3 -0
- package/themes/base/_includes/admin/sections/topbar.html +3 -0
- package/themes/base/_includes/backend/sections/sidebar.html +3 -0
- package/themes/base/_includes/backend/sections/topbar.html +3 -0
- package/themes/base/_includes/frontend/components/connection-card.html +49 -0
- package/themes/base/_includes/frontend/components/post-card.html +54 -0
- package/themes/base/_includes/frontend/sections/account-connections.html +42 -0
- package/themes/base/_includes/frontend/sections/account-section-header.html +11 -0
- package/themes/base/_includes/frontend/sections/footer.html +154 -0
- package/themes/base/_includes/frontend/sections/nav.html +276 -0
- package/themes/base/_includes/global/sections/account.html +72 -0
- package/themes/base/_includes/global/sections/app-sidebar.html +248 -0
- package/themes/base/_includes/global/sections/app-topbar.html +228 -0
- package/themes/base/_includes/global/sections/page-header.html +99 -0
- package/themes/base/_layouts/admin/core/minimal-viewport-locked.html +22 -0
- package/themes/base/_layouts/admin/core/minimal.html +23 -0
- package/themes/base/_layouts/backend/core/base.html +57 -0
- package/themes/base/_layouts/backend/core/minimal-viewport-locked.html +32 -0
- package/themes/base/_layouts/backend/core/minimal.html +32 -0
- package/themes/base/_layouts/backend/pages/dashboard/index.html +230 -0
- package/themes/base/_layouts/frontend/core/base.html +31 -0
- package/themes/base/_layouts/frontend/core/cover.html +40 -0
- package/themes/base/_layouts/frontend/core/minimal.html +47 -0
- package/themes/base/_layouts/frontend/pages/404.html +54 -0
- package/themes/base/_layouts/frontend/pages/about.html +144 -0
- package/themes/base/_layouts/frontend/pages/account/index.html +2104 -0
- package/themes/base/_layouts/frontend/pages/alternatives/alternative.html +319 -0
- package/themes/base/_layouts/frontend/pages/alternatives/index.html +186 -0
- package/themes/base/_layouts/frontend/pages/app.html +142 -0
- package/themes/base/_layouts/frontend/pages/auth/reset.html +53 -0
- package/themes/base/_layouts/frontend/pages/auth/signin.html +90 -0
- package/themes/base/_layouts/frontend/pages/auth/signup.html +141 -0
- package/themes/base/_layouts/frontend/pages/auth/token.html +44 -0
- package/themes/base/_layouts/frontend/pages/blog/categories/category.html +88 -0
- package/themes/base/_layouts/frontend/pages/blog/categories/index.html +88 -0
- package/themes/base/_layouts/frontend/pages/blog/index.html +255 -0
- package/themes/base/_layouts/frontend/pages/blog/post.html +261 -0
- package/themes/base/_layouts/frontend/pages/blog/tags/index.html +84 -0
- package/themes/base/_layouts/frontend/pages/blog/tags/tag.html +88 -0
- package/themes/base/_layouts/frontend/pages/collection/category.html +72 -0
- package/themes/base/_layouts/frontend/pages/collection/document.html +54 -0
- package/themes/base/_layouts/frontend/pages/collection/index.html +84 -0
- package/themes/base/_layouts/frontend/pages/connections/callback.html +55 -0
- package/themes/base/_layouts/frontend/pages/contact.html +214 -0
- package/themes/base/_layouts/frontend/pages/download.html +793 -0
- package/themes/base/_layouts/frontend/pages/extension/index.html +253 -0
- package/themes/base/_layouts/frontend/pages/extension/installed.html +198 -0
- package/themes/base/_layouts/frontend/pages/feedback.html +171 -0
- package/themes/base/_layouts/frontend/pages/index.html +66 -0
- package/themes/base/_layouts/frontend/pages/legal/document.html +78 -0
- package/themes/base/_layouts/frontend/pages/payment/checkout.html +459 -0
- package/themes/base/_layouts/frontend/pages/payment/confirmation.html +131 -0
- package/themes/base/_layouts/frontend/pages/portal/email-preferences.html +104 -0
- package/themes/base/_layouts/frontend/pages/pricing.html +596 -0
- package/themes/base/_layouts/frontend/pages/status.html +361 -0
- package/themes/base/_layouts/frontend/pages/team/index.html +210 -0
- package/themes/base/_layouts/frontend/pages/team/member.html +125 -0
- package/themes/base/_layouts/frontend/pages/updates/index.html +119 -0
- package/themes/base/_layouts/frontend/pages/updates/update.html +118 -0
- package/themes/base/_sections/about/hero/section.html +68 -0
- package/themes/base/_sections/about/hero/section.json5 +58 -0
- package/themes/base/_sections/about/letter/section.html +60 -0
- package/themes/base/_sections/about/letter/section.json5 +56 -0
- package/themes/base/_sections/about/photo-band/section.html +24 -0
- package/themes/base/_sections/about/photo-band/section.json5 +23 -0
- package/themes/base/_sections/about/principles/section.html +17 -0
- package/themes/base/_sections/about/principles/section.json5 +34 -0
- package/themes/base/_sections/about/timeline/section.html +20 -0
- package/themes/base/_sections/about/timeline/section.json5 +34 -0
- package/themes/base/_sections/marketing/bento/section.html +91 -0
- package/themes/base/_sections/marketing/bento/section.json5 +152 -0
- package/themes/base/_sections/marketing/cta/section.html +44 -0
- package/themes/base/_sections/marketing/cta/section.json5 +47 -0
- package/themes/base/_sections/marketing/faq/section.html +52 -0
- package/themes/base/_sections/marketing/faq/section.json5 +68 -0
- package/themes/base/_sections/marketing/hero/section.html +349 -0
- package/themes/base/_sections/marketing/hero/section.json5 +335 -0
- package/themes/base/_sections/marketing/newsletter-cta/section.html +38 -0
- package/themes/base/_sections/marketing/newsletter-cta/section.js +86 -0
- package/themes/base/_sections/marketing/newsletter-cta/section.json5 +29 -0
- package/themes/base/_sections/marketing/pricing-cards/section.html +115 -0
- package/themes/base/_sections/marketing/pricing-cards/section.json5 +72 -0
- package/themes/base/_sections/marketing/product-demo/section.html +62 -0
- package/themes/base/_sections/marketing/product-demo/section.js +44 -0
- package/themes/base/_sections/marketing/product-demo/section.json5 +52 -0
- package/themes/base/_sections/marketing/prose/section.html +22 -0
- package/themes/base/_sections/marketing/prose/section.json5 +41 -0
- package/themes/base/_sections/marketing/showcase/section.html +35 -0
- package/themes/base/_sections/marketing/showcase/section.json5 +52 -0
- package/themes/base/_sections/marketing/stats/section.html +32 -0
- package/themes/base/_sections/marketing/stats/section.json5 +44 -0
- package/themes/base/_sections/marketing/testimonials/section.html +54 -0
- package/themes/base/_sections/marketing/testimonials/section.json5 +70 -0
- package/themes/base/_sections/marketing/trusted-by/section.html +30 -0
- package/themes/base/_sections/marketing/trusted-by/section.json5 +38 -0
- package/themes/base/_sections/verts/unit/section.html +7 -0
- package/themes/base/_sections/verts/unit/section.js +22 -0
- package/themes/base/_sections/verts/unit/section.json5 +24 -0
- package/themes/base/_sections/verts/unit/section.scss +24 -0
- package/themes/base/_theme.js +13 -0
- package/themes/base/_theme.scss +4 -0
- package/themes/bootstrap/_theme.js +16 -0
- package/themes/bootstrap/_theme.scss +11 -0
- package/themes/bootstrap/js/index.esm.js +19 -0
- package/themes/bootstrap/js/index.umd.js +34 -0
- package/themes/bootstrap/js/src/alert.js +87 -0
- package/themes/bootstrap/js/src/base-component.js +86 -0
- package/themes/bootstrap/js/src/button.js +72 -0
- package/themes/bootstrap/js/src/carousel.js +474 -0
- package/themes/bootstrap/js/src/collapse.js +297 -0
- package/themes/bootstrap/js/src/dom/data.js +55 -0
- package/themes/bootstrap/js/src/dom/event-handler.js +317 -0
- package/themes/bootstrap/js/src/dom/manipulator.js +71 -0
- package/themes/bootstrap/js/src/dom/selector-engine.js +126 -0
- package/themes/bootstrap/js/src/dropdown.js +458 -0
- package/themes/bootstrap/js/src/modal.js +378 -0
- package/themes/bootstrap/js/src/offcanvas.js +282 -0
- package/themes/bootstrap/js/src/popover.js +97 -0
- package/themes/bootstrap/js/src/scrollspy.js +296 -0
- package/themes/bootstrap/js/src/tab.js +315 -0
- package/themes/bootstrap/js/src/toast.js +224 -0
- package/themes/bootstrap/js/src/tooltip.js +632 -0
- package/themes/bootstrap/js/src/util/backdrop.js +151 -0
- package/themes/bootstrap/js/src/util/component-functions.js +35 -0
- package/themes/bootstrap/js/src/util/config.js +65 -0
- package/themes/bootstrap/js/src/util/focustrap.js +115 -0
- package/themes/bootstrap/js/src/util/index.js +306 -0
- package/themes/bootstrap/js/src/util/sanitizer.js +117 -0
- package/themes/bootstrap/js/src/util/scrollbar.js +114 -0
- package/themes/bootstrap/js/src/util/swipe.js +146 -0
- package/themes/bootstrap/js/src/util/template-factory.js +160 -0
- package/themes/bootstrap/overrides/_accordion.scss +21 -0
- package/themes/bootstrap/overrides/_avatars.scss +51 -0
- package/themes/bootstrap/overrides/_blog-images.scss +45 -0
- package/themes/bootstrap/overrides/_buttons-adaptive.scss +141 -0
- package/themes/bootstrap/overrides/_color-shades.scss +25 -0
- package/themes/bootstrap/overrides/_cursor-utilities.scss +13 -0
- package/themes/bootstrap/overrides/_index.scss +30 -0
- package/themes/bootstrap/overrides/_links.scss +26 -0
- package/themes/bootstrap/overrides/_soft-colors.scss +99 -0
- package/themes/bootstrap/overrides/_spacing-extended.scss +74 -0
- package/themes/bootstrap/overrides/_spinners.scss +22 -0
- package/themes/bootstrap/overrides/_typography-utilities.scss +40 -0
- package/themes/bootstrap/scss/_accordion.scss +153 -0
- package/themes/bootstrap/scss/_alert.scss +68 -0
- package/themes/bootstrap/scss/_badge.scss +38 -0
- package/themes/bootstrap/scss/_breadcrumb.scss +40 -0
- package/themes/bootstrap/scss/_button-group.scss +147 -0
- package/themes/bootstrap/scss/_buttons.scss +216 -0
- package/themes/bootstrap/scss/_card.scss +238 -0
- package/themes/bootstrap/scss/_carousel.scss +226 -0
- package/themes/bootstrap/scss/_close.scss +66 -0
- package/themes/bootstrap/scss/_containers.scss +41 -0
- package/themes/bootstrap/scss/_dropdown.scss +250 -0
- package/themes/bootstrap/scss/_forms.scss +9 -0
- package/themes/bootstrap/scss/_functions.scss +302 -0
- package/themes/bootstrap/scss/_grid.scss +39 -0
- package/themes/bootstrap/scss/_helpers.scss +12 -0
- package/themes/bootstrap/scss/_images.scss +42 -0
- package/themes/bootstrap/scss/_list-group.scss +199 -0
- package/themes/bootstrap/scss/_maps.scss +174 -0
- package/themes/bootstrap/scss/_mixins.scss +42 -0
- package/themes/bootstrap/scss/_modal.scss +240 -0
- package/themes/bootstrap/scss/_nav.scss +197 -0
- package/themes/bootstrap/scss/_navbar.scss +289 -0
- package/themes/bootstrap/scss/_offcanvas.scss +147 -0
- package/themes/bootstrap/scss/_pagination.scss +109 -0
- package/themes/bootstrap/scss/_placeholders.scss +51 -0
- package/themes/bootstrap/scss/_popover.scss +196 -0
- package/themes/bootstrap/scss/_progress.scss +68 -0
- package/themes/bootstrap/scss/_reboot.scss +611 -0
- package/themes/bootstrap/scss/_root.scss +187 -0
- package/themes/bootstrap/scss/_spinners.scss +85 -0
- package/themes/bootstrap/scss/_tables.scss +171 -0
- package/themes/bootstrap/scss/_toasts.scss +73 -0
- package/themes/bootstrap/scss/_tooltip.scss +119 -0
- package/themes/bootstrap/scss/_transitions.scss +27 -0
- package/themes/bootstrap/scss/_type.scss +106 -0
- package/themes/bootstrap/scss/_utilities.scss +806 -0
- package/themes/bootstrap/scss/_variables-dark.scss +102 -0
- package/themes/bootstrap/scss/_variables.scss +1753 -0
- package/themes/bootstrap/scss/bootstrap-grid.scss +62 -0
- package/themes/bootstrap/scss/bootstrap-reboot.scss +10 -0
- package/themes/bootstrap/scss/bootstrap-utilities.scss +19 -0
- package/themes/bootstrap/scss/bootstrap.scss +52 -0
- package/themes/bootstrap/scss/forms/_floating-labels.scss +97 -0
- package/themes/bootstrap/scss/forms/_form-check.scss +189 -0
- package/themes/bootstrap/scss/forms/_form-control.scss +214 -0
- package/themes/bootstrap/scss/forms/_form-range.scss +91 -0
- package/themes/bootstrap/scss/forms/_form-select.scss +80 -0
- package/themes/bootstrap/scss/forms/_form-text.scss +11 -0
- package/themes/bootstrap/scss/forms/_input-group.scss +132 -0
- package/themes/bootstrap/scss/forms/_labels.scss +36 -0
- package/themes/bootstrap/scss/forms/_validation.scss +12 -0
- package/themes/bootstrap/scss/helpers/_clearfix.scss +3 -0
- package/themes/bootstrap/scss/helpers/_color-bg.scss +7 -0
- package/themes/bootstrap/scss/helpers/_colored-links.scss +30 -0
- package/themes/bootstrap/scss/helpers/_focus-ring.scss +5 -0
- package/themes/bootstrap/scss/helpers/_icon-link.scss +25 -0
- package/themes/bootstrap/scss/helpers/_position.scss +36 -0
- package/themes/bootstrap/scss/helpers/_ratio.scss +26 -0
- package/themes/bootstrap/scss/helpers/_stacks.scss +15 -0
- package/themes/bootstrap/scss/helpers/_stretched-link.scss +15 -0
- package/themes/bootstrap/scss/helpers/_text-truncation.scss +7 -0
- package/themes/bootstrap/scss/helpers/_visually-hidden.scss +8 -0
- package/themes/bootstrap/scss/helpers/_vr.scss +8 -0
- package/themes/bootstrap/scss/mixins/_alert.scss +18 -0
- package/themes/bootstrap/scss/mixins/_backdrop.scss +14 -0
- package/themes/bootstrap/scss/mixins/_banner.scss +7 -0
- package/themes/bootstrap/scss/mixins/_border-radius.scss +78 -0
- package/themes/bootstrap/scss/mixins/_box-shadow.scss +18 -0
- package/themes/bootstrap/scss/mixins/_breakpoints.scss +127 -0
- package/themes/bootstrap/scss/mixins/_buttons.scss +70 -0
- package/themes/bootstrap/scss/mixins/_caret.scss +69 -0
- package/themes/bootstrap/scss/mixins/_clearfix.scss +9 -0
- package/themes/bootstrap/scss/mixins/_color-mode.scss +21 -0
- package/themes/bootstrap/scss/mixins/_color-scheme.scss +7 -0
- package/themes/bootstrap/scss/mixins/_container.scss +11 -0
- package/themes/bootstrap/scss/mixins/_deprecate.scss +10 -0
- package/themes/bootstrap/scss/mixins/_forms.scss +163 -0
- package/themes/bootstrap/scss/mixins/_gradients.scss +47 -0
- package/themes/bootstrap/scss/mixins/_grid.scss +151 -0
- package/themes/bootstrap/scss/mixins/_image.scss +16 -0
- package/themes/bootstrap/scss/mixins/_list-group.scss +26 -0
- package/themes/bootstrap/scss/mixins/_lists.scss +7 -0
- package/themes/bootstrap/scss/mixins/_pagination.scss +10 -0
- package/themes/bootstrap/scss/mixins/_reset-text.scss +17 -0
- package/themes/bootstrap/scss/mixins/_resize.scss +6 -0
- package/themes/bootstrap/scss/mixins/_table-variants.scss +24 -0
- package/themes/bootstrap/scss/mixins/_text-truncate.scss +8 -0
- package/themes/bootstrap/scss/mixins/_transition.scss +26 -0
- package/themes/bootstrap/scss/mixins/_utilities.scss +97 -0
- package/themes/bootstrap/scss/mixins/_visually-hidden.scss +38 -0
- package/themes/bootstrap/scss/tests/jasmine.js +16 -0
- package/themes/bootstrap/scss/tests/mixins/_auto-import-of-variables-dark.test.scss +7 -0
- package/themes/bootstrap/scss/tests/mixins/_color-modes.test.scss +69 -0
- package/themes/bootstrap/scss/tests/mixins/_media-query-color-mode-full.test.scss +8 -0
- package/themes/bootstrap/scss/tests/mixins/_utilities.test.scss +393 -0
- package/themes/bootstrap/scss/tests/sass-true/register.js +14 -0
- package/themes/bootstrap/scss/tests/sass-true/runner.js +17 -0
- package/themes/bootstrap/scss/tests/utilities/_api.test.scss +75 -0
- package/themes/bootstrap/scss/utilities/_api.scss +47 -0
- package/themes/bootstrap/scss/vendor/_rfs.scss +348 -0
- package/themes/classy/README.md +89 -0
- package/themes/classy/_config.scss +245 -0
- package/themes/classy/_theme.js +31 -0
- package/themes/classy/_theme.scss +57 -0
- package/themes/classy/css/app/_panels.scss +183 -0
- package/themes/classy/css/base/_fonts.scss +79 -0
- package/themes/classy/css/base/_no-raise.scss +49 -0
- package/themes/classy/css/base/_root.scss +113 -0
- package/themes/classy/css/base/_typography.scss +154 -0
- package/themes/classy/css/base/_utilities.scss +284 -0
- package/themes/classy/css/components/_alerts.scss +51 -0
- package/themes/classy/css/components/_badges.scss +46 -0
- package/themes/classy/css/components/_buttons.scss +175 -0
- package/themes/classy/css/components/_cards.scss +41 -0
- package/themes/classy/css/components/_dropdowns.scss +48 -0
- package/themes/classy/css/components/_forms.scss +171 -0
- package/themes/classy/css/components/_receipt.scss +45 -0
- package/themes/classy/css/layout/_footer.scss +298 -0
- package/themes/classy/css/layout/_general.scss +209 -0
- package/themes/classy/css/layout/_nav.scss +154 -0
- package/themes/classy/css/layout/_shell.scss +458 -0
- package/themes/classy/css/marketing/_bento.scss +238 -0
- package/themes/classy/css/marketing/_content.scss +1328 -0
- package/themes/classy/css/marketing/_downloads.scss +246 -0
- package/themes/classy/css/marketing/_hero.scss +311 -0
- package/themes/classy/css/marketing/_sections.scss +649 -0
- package/themes/classy/css/pages/404/index.scss +67 -0
- package/themes/classy/css/pages/_auth.scss +235 -0
- package/themes/classy/css/pages/admin/firebase/index.scss +22 -0
- package/themes/classy/css/pages/blog/[slug].scss +56 -0
- package/themes/classy/css/pages/cookies.scss +2 -0
- package/themes/classy/css/pages/dashboard/account/index.scss +31 -0
- package/themes/classy/css/pages/feedback/index.scss +39 -0
- package/themes/classy/css/pages/legal/_document.scss +192 -0
- package/themes/classy/css/pages/payment/checkout/index.scss +585 -0
- package/themes/classy/css/pages/payment/confirmation/index.scss +9 -0
- package/themes/classy/css/pages/privacy.scss +2 -0
- package/themes/classy/css/pages/status/index.scss +164 -0
- package/themes/classy/css/pages/terms.scss +2 -0
- package/themes/classy/css/pages/updates/index.scss +128 -0
- package/themes/classy/fonts/inter-italic-latin-ext.woff2 +0 -0
- package/themes/classy/fonts/inter-italic-latin.woff2 +0 -0
- package/themes/classy/fonts/inter-normal-latin-ext.woff2 +0 -0
- package/themes/classy/fonts/inter-normal-latin.woff2 +0 -0
- package/themes/classy/fonts/newsreader-italic-latin-ext.woff2 +0 -0
- package/themes/classy/fonts/newsreader-italic-latin.woff2 +0 -0
- package/themes/classy/fonts/newsreader-normal-latin-ext.woff2 +0 -0
- package/themes/classy/fonts/newsreader-normal-latin.woff2 +0 -0
- package/themes/classy/js/hero-demo-form.js +56 -0
- package/themes/neobrutalism/README.md +118 -0
- package/themes/neobrutalism/_config.scss +139 -0
- package/themes/neobrutalism/_layouts/frontend/core/base.html +30 -0
- package/themes/neobrutalism/_layouts/frontend/pages/index.html +275 -0
- package/themes/neobrutalism/_theme.js +24 -0
- package/themes/neobrutalism/_theme.scss +61 -0
- package/themes/neobrutalism/css/base/_mixins.scss +46 -0
- package/themes/neobrutalism/css/base/_root.scss +169 -0
- package/themes/neobrutalism/css/base/_typography.scss +61 -0
- package/themes/neobrutalism/css/base/_utilities.scss +89 -0
- package/themes/neobrutalism/css/components/_billing-toggle.scss +74 -0
- package/themes/neobrutalism/css/components/_buttons.scss +148 -0
- package/themes/neobrutalism/css/components/_cards.scss +47 -0
- package/themes/neobrutalism/css/components/_forms.scss +88 -0
- package/themes/neobrutalism/css/components/_marketing.scss +244 -0
- package/themes/neobrutalism/css/layout/_general.scss +213 -0
- package/themes/neobrutalism/css/layout/_navigation.scss +171 -0
- package/themes/neobrutalism/css/pages/index.scss +203 -0
- package/themes/neobrutalism/css/pages/pricing/index.scss +58 -0
- package/themes/neobrutalism/css/pages/test/libraries/layers/index.scss +7 -0
- package/themes/neobrutalism/js/pages/test/libraries/layers/index.js +9 -0
- package/themes/newsflash/README.md +117 -0
- package/themes/newsflash/_components/heading/lede/component.html +14 -0
- package/themes/newsflash/_components/heading/lede/component.json5 +23 -0
- package/themes/newsflash/_components/heading/rule-head/component.html +17 -0
- package/themes/newsflash/_components/heading/rule-head/component.json5 +23 -0
- package/themes/newsflash/_components/news/byline/component.html +12 -0
- package/themes/newsflash/_components/news/byline/component.json5 +18 -0
- package/themes/newsflash/_components/news/story-card/component.html +25 -0
- package/themes/newsflash/_components/news/story-card/component.json5 +21 -0
- package/themes/newsflash/_config.scss +147 -0
- package/themes/newsflash/_layouts/frontend/core/base.html +51 -0
- package/themes/newsflash/_layouts/frontend/pages/blog/index.html +299 -0
- package/themes/newsflash/_layouts/frontend/pages/blog/post.html +235 -0
- package/themes/newsflash/_layouts/frontend/pages/index.html +328 -0
- package/themes/newsflash/_sections/marketing/desks/section.html +39 -0
- package/themes/newsflash/_sections/marketing/desks/section.json5 +49 -0
- package/themes/newsflash/_sections/marketing/newsletter-cta/section.html +103 -0
- package/themes/newsflash/_sections/marketing/newsletter-cta/section.json5 +50 -0
- package/themes/newsflash/_sections/marketing/rundown/section.html +28 -0
- package/themes/newsflash/_sections/marketing/rundown/section.json5 +40 -0
- package/themes/newsflash/_theme.js +24 -0
- package/themes/newsflash/_theme.scss +70 -0
- package/themes/newsflash/css/base/_fonts.scss +80 -0
- package/themes/newsflash/css/base/_mixins.scss +51 -0
- package/themes/newsflash/css/base/_root.scss +257 -0
- package/themes/newsflash/css/base/_typography.scss +49 -0
- package/themes/newsflash/css/base/_utilities.scss +122 -0
- package/themes/newsflash/css/components/_badges.scss +65 -0
- package/themes/newsflash/css/components/_billing-toggle.scss +61 -0
- package/themes/newsflash/css/components/_buttons.scss +139 -0
- package/themes/newsflash/css/components/_cards.scss +47 -0
- package/themes/newsflash/css/components/_editorial.scss +173 -0
- package/themes/newsflash/css/components/_forms.scss +75 -0
- package/themes/newsflash/css/components/_infinite-scroll.scss +102 -0
- package/themes/newsflash/css/components/_panels.scss +156 -0
- package/themes/newsflash/css/components/_ticker.scss +67 -0
- package/themes/newsflash/css/layout/_general.scss +330 -0
- package/themes/newsflash/css/layout/_navigation.scss +168 -0
- package/themes/newsflash/css/pages/404/index.scss +79 -0
- package/themes/newsflash/css/pages/blog/[slug].scss +186 -0
- package/themes/newsflash/css/pages/blog/index.scss +17 -0
- package/themes/newsflash/css/pages/index.scss +157 -0
- package/themes/newsflash/css/pages/pricing/index.scss +55 -0
- package/themes/newsflash/css/pages/test/libraries/layers/index.scss +7 -0
- package/themes/newsflash/fonts/fraunces-italic-latin-ext.woff2 +0 -0
- package/themes/newsflash/fonts/fraunces-italic-latin.woff2 +0 -0
- package/themes/newsflash/fonts/fraunces-normal-latin-ext.woff2 +0 -0
- package/themes/newsflash/fonts/fraunces-normal-latin.woff2 +0 -0
- package/themes/newsflash/fonts/schibsted-grotesk-italic-latin-ext.woff2 +0 -0
- package/themes/newsflash/fonts/schibsted-grotesk-italic-latin.woff2 +0 -0
- package/themes/newsflash/fonts/schibsted-grotesk-normal-latin-ext.woff2 +0 -0
- package/themes/newsflash/fonts/schibsted-grotesk-normal-latin.woff2 +0 -0
- package/themes/newsflash/js/pages/blog/[slug].js +29 -0
- package/themes/newsflash/js/pages/test/libraries/layers/index.js +9 -0
- package/translations/es/pages/404.json +86 -0
- package/translations/es/pages/account.json +36 -0
- package/translations/es/pages/app.json +44 -0
- package/translations/es/pages/cancel.json +36 -0
- package/translations/es/pages/change-password.json +36 -0
- package/translations/es/pages/connections/callback.json +41 -0
- package/translations/es/pages/dashboard/account.json +475 -0
- package/translations/es/pages/dashboard.json +36 -0
- package/translations/es/pages/forgot.json +36 -0
- package/translations/es/pages/join.json +36 -0
- package/translations/es/pages/login.json +36 -0
- package/translations/es/pages/payment/checkout.json +83 -0
- package/translations/es/pages/payment/confirmation.json +62 -0
- package/translations/es/pages/portal/email-preferences.json +46 -0
- package/translations/es/pages/recover.json +36 -0
- package/translations/es/pages/refund.json +36 -0
- package/translations/es/pages/register.json +36 -0
- package/translations/es/pages/reset-password.json +36 -0
- package/translations/es/pages/reset.json +42 -0
- package/translations/es/pages/signin.json +45 -0
- package/translations/es/pages/signup.json +60 -0
- package/translations/es/pages/token.json +39 -0
- package/translations/fa/pages/404.json +86 -0
- package/translations/fa/pages/account.json +36 -0
- package/translations/fa/pages/app.json +44 -0
- package/translations/fa/pages/cancel.json +36 -0
- package/translations/fa/pages/change-password.json +36 -0
- package/translations/fa/pages/connections/callback.json +41 -0
- package/translations/fa/pages/dashboard/account.json +475 -0
- package/translations/fa/pages/dashboard.json +36 -0
- package/translations/fa/pages/forgot.json +36 -0
- package/translations/fa/pages/join.json +36 -0
- package/translations/fa/pages/login.json +36 -0
- package/translations/fa/pages/payment/checkout.json +83 -0
- package/translations/fa/pages/payment/confirmation.json +62 -0
- package/translations/fa/pages/portal/email-preferences.json +46 -0
- package/translations/fa/pages/recover.json +36 -0
- package/translations/fa/pages/refund.json +36 -0
- package/translations/fa/pages/register.json +36 -0
- package/translations/fa/pages/reset-password.json +36 -0
- package/translations/fa/pages/reset.json +42 -0
- package/translations/fa/pages/signin.json +45 -0
- package/translations/fa/pages/signup.json +60 -0
- package/translations/fa/pages/token.json +39 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Analytics tracking for the checkout page — one canonical fire per step; the
|
|
2
|
+
// catalog decides which provider hears it, under which name, in which dialect
|
|
3
|
+
// (#328), and the transport under it is guarded per provider (#306)
|
|
4
|
+
import { event } from '__main_assets__/js/libs/analytics.js';
|
|
5
|
+
import { calculatePrices } from './pricing.js';
|
|
6
|
+
|
|
7
|
+
// What the funnel reports this checkout is worth: the LIST price of what is
|
|
8
|
+
// being bought, before any code comes off it.
|
|
9
|
+
//
|
|
10
|
+
// calculatePrices() is the one place that knows every price shape a catalog can
|
|
11
|
+
// carry — the cadence keys, the one-time `once` key, and the legacy
|
|
12
|
+
// `amount`/`monthly` fallbacks — and its `subtotal` IS that list price. The
|
|
13
|
+
// hand-rolled read this replaced never looked at `once`, so a product priced
|
|
14
|
+
// `{ once: 49.99 }` sent `begin_checkout` and `add_payment_info` a value of 0
|
|
15
|
+
// while `purchase` reported $49.99
|
|
16
|
+
// ([#668](https://github.com/Omega-JS-Stack/omega/issues/668)).
|
|
17
|
+
function getBasePrice(state) {
|
|
18
|
+
return calculatePrices(state).subtotal;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Build common item array for tracking
|
|
22
|
+
function buildItems(state, price) {
|
|
23
|
+
return [{
|
|
24
|
+
item_id: state.product.id,
|
|
25
|
+
item_name: state.product.name,
|
|
26
|
+
item_category: state.product.type === 'subscription' ? 'subscription' : 'one-time',
|
|
27
|
+
item_variant: state.frequency,
|
|
28
|
+
price: price,
|
|
29
|
+
quantity: 1,
|
|
30
|
+
}];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function trackBeginCheckout(state) {
|
|
34
|
+
const price = getBasePrice(state);
|
|
35
|
+
const items = buildItems(state, price);
|
|
36
|
+
|
|
37
|
+
event('begin_checkout', {
|
|
38
|
+
currency: 'USD',
|
|
39
|
+
value: price,
|
|
40
|
+
items: items,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function trackAddPaymentInfo(state, paymentMethod) {
|
|
45
|
+
const price = getBasePrice(state);
|
|
46
|
+
const items = buildItems(state, price);
|
|
47
|
+
|
|
48
|
+
event('add_payment_info', {
|
|
49
|
+
currency: 'USD',
|
|
50
|
+
value: price,
|
|
51
|
+
payment_type: paymentMethod,
|
|
52
|
+
items: items,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Payment Confirmation Page
|
|
2
|
+
import { state, buildBindingsState } from './modules/state.js';
|
|
3
|
+
import { trackPurchaseIfNeeded } from './modules/tracking.js';
|
|
4
|
+
import { triggerCelebration } from './modules/celebration.js';
|
|
5
|
+
import { verifyPurchase, initialStatus } from './modules/verify.js';
|
|
6
|
+
import omega from '@omega.js/client';
|
|
7
|
+
import { createLogger } from '__main_assets__/js/libs/logger.js';
|
|
8
|
+
|
|
9
|
+
const logger = createLogger('confirmation');
|
|
10
|
+
|
|
11
|
+
/* Test URL
|
|
12
|
+
https://localhost:3000/payment/confirmation?orderId=ORD-TRIAL-123&productId=pro&productName=Pro%20Plan&amount=0¤cy=USD&frequency=annually&paymentMethod=stripe&trial=true&track=true
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// Module export
|
|
16
|
+
export default () => {
|
|
17
|
+
return new Promise(async function (resolve) {
|
|
18
|
+
await omega.dom().ready();
|
|
19
|
+
await initializeConfirmation();
|
|
20
|
+
return resolve();
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Update UI via bindings (single source of truth)
|
|
25
|
+
function updateUI() {
|
|
26
|
+
omega.bindings().update(buildBindingsState());
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Initialize confirmation page
|
|
30
|
+
async function initializeConfirmation() {
|
|
31
|
+
// Parse URL params into state
|
|
32
|
+
parseUrlParams();
|
|
33
|
+
|
|
34
|
+
// Update UI with loaded data
|
|
35
|
+
updateUI();
|
|
36
|
+
|
|
37
|
+
// The browser half of the purchase (if the track=true param is present) —
|
|
38
|
+
// Meta's and TikTok's retargeting signal, deduped against the webhook's own
|
|
39
|
+
// fire (#386). The revenue TRUTH is the webhook's, always.
|
|
40
|
+
trackPurchaseIfNeeded(state);
|
|
41
|
+
|
|
42
|
+
// Subscribe to push notifications on CTA click (requires user gesture).
|
|
43
|
+
// Wired before the verification wait so the CTAs are live immediately.
|
|
44
|
+
document.querySelectorAll('.btn').forEach(($btn) => {
|
|
45
|
+
$btn.addEventListener('click', () => {
|
|
46
|
+
omega.notifications().subscribe().catch((e) => {
|
|
47
|
+
logger.warn('Notification subscribe failed:', e.message);
|
|
48
|
+
});
|
|
49
|
+
}, { once: true });
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// The redirect is the provider's CLAIM; entitlement is granted by the
|
|
53
|
+
// webhook, which lands after the browser does — or never (#232). Hold the
|
|
54
|
+
// page in `processing` until the account itself carries the purchase. A
|
|
55
|
+
// purchase that opened already answered has no poll to wait on and nothing to
|
|
56
|
+
// wait for auth for — it rendered its receipt in the update above.
|
|
57
|
+
if (state.status === 'processing') {
|
|
58
|
+
await new Promise((resolve) => omega.auth().listen({ once: true }, resolve));
|
|
59
|
+
|
|
60
|
+
// ONE reveal: the update that answers the page is the update that brings
|
|
61
|
+
// the order details with it, and the celebration rides that same flip —
|
|
62
|
+
// numbers arriving seconds before the confetti read as broken (Ian's QA).
|
|
63
|
+
state.status = await verifyPurchase(state);
|
|
64
|
+
updateUI();
|
|
65
|
+
|
|
66
|
+
if (state.status !== 'confirmed') {
|
|
67
|
+
logger.warn(`Purchase not confirmed against the account state: orderId=${state.orderId}, product=${state.productId}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Trigger celebration animation — only for a purchase that really landed
|
|
73
|
+
await triggerCelebration();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Parse URL parameters into minimal state
|
|
77
|
+
function parseUrlParams() {
|
|
78
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
79
|
+
|
|
80
|
+
state.orderId = urlParams.get('orderId') || '';
|
|
81
|
+
state.productId = urlParams.get('productId') || '';
|
|
82
|
+
state.productName = urlParams.get('productName') || '';
|
|
83
|
+
state.amount = parseFloat(urlParams.get('amount') || 0);
|
|
84
|
+
state.currency = urlParams.get('currency') || 'USD';
|
|
85
|
+
state.type = urlParams.get('type') || '';
|
|
86
|
+
state.frequency = urlParams.get('frequency') || '';
|
|
87
|
+
state.paymentMethod = urlParams.get('paymentMethod') || '';
|
|
88
|
+
state.hasFreeTrial = urlParams.get('trial') === 'true';
|
|
89
|
+
state.status = initialStatus(state);
|
|
90
|
+
state.loaded = true;
|
|
91
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Celebration animation for confirmation page
|
|
2
|
+
import omega from '@omega.js/client';
|
|
3
|
+
|
|
4
|
+
// Trigger confetti celebration
|
|
5
|
+
export async function triggerCelebration() {
|
|
6
|
+
try {
|
|
7
|
+
await omega.dom().loadScript({
|
|
8
|
+
src: 'https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.2/dist/confetti.browser.min.js'
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// Center burst
|
|
12
|
+
window.confetti({
|
|
13
|
+
particleCount: 100,
|
|
14
|
+
spread: 70,
|
|
15
|
+
origin: { y: 0.6 },
|
|
16
|
+
// Brand confetti: ocean accent + a festive hand-mixed set (legacy
|
|
17
|
+
// purple-era palette retired, Ian 2026-07-16)
|
|
18
|
+
colors: ['#2563eb', '#18b7cf', '#21c07c', '#efa312', '#e4572e'],
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Left side burst
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
window.confetti({
|
|
24
|
+
particleCount: 50,
|
|
25
|
+
angle: 60,
|
|
26
|
+
spread: 55,
|
|
27
|
+
origin: { x: 0 },
|
|
28
|
+
colors: ['#2563eb', '#18b7cf', '#21c07c'],
|
|
29
|
+
});
|
|
30
|
+
}, 250);
|
|
31
|
+
|
|
32
|
+
// Right side burst
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
window.confetti({
|
|
35
|
+
particleCount: 50,
|
|
36
|
+
angle: 120,
|
|
37
|
+
spread: 55,
|
|
38
|
+
origin: { x: 1 },
|
|
39
|
+
colors: ['#21c07c', '#efa312', '#e4572e'],
|
|
40
|
+
});
|
|
41
|
+
}, 400);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.log('Confetti library failed to load:', error);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// State management for confirmation page
|
|
2
|
+
// Minimal mutable state -- everything else is derived by buildBindingsState()
|
|
3
|
+
|
|
4
|
+
import { FREQUENCIES, ONE_TIME_FREQUENCY } from '../../checkout/modules/state.js';
|
|
5
|
+
|
|
6
|
+
// Minimal mutable state
|
|
7
|
+
export const state = {
|
|
8
|
+
// Raw values from URL params (never formatted)
|
|
9
|
+
orderId: '',
|
|
10
|
+
productId: '',
|
|
11
|
+
productName: '',
|
|
12
|
+
amount: 0,
|
|
13
|
+
currency: 'USD',
|
|
14
|
+
// What was bought, straight off the redirect the intent route builds
|
|
15
|
+
// ('subscription' | 'one-time'): the one thing here that does not have to be
|
|
16
|
+
// inferred from the cadence beside it (#668)
|
|
17
|
+
type: '',
|
|
18
|
+
frequency: '',
|
|
19
|
+
paymentMethod: '',
|
|
20
|
+
hasFreeTrial: false,
|
|
21
|
+
|
|
22
|
+
// Whether the purchase has actually landed in the account yet (#232). The
|
|
23
|
+
// page opens UNSURE — the redirect is the provider's claim, and the webhook
|
|
24
|
+
// that grants entitlement arrives after the browser does.
|
|
25
|
+
// 'processing' | 'confirmed' | 'timeout'
|
|
26
|
+
status: 'processing',
|
|
27
|
+
|
|
28
|
+
// UI state
|
|
29
|
+
loaded: false,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Build the complete bindings state from minimal state
|
|
33
|
+
// Returns a fresh object every time -- no mutation of shared references
|
|
34
|
+
export function buildBindingsState() {
|
|
35
|
+
// Only the cadences checkout SELLS renew (#282). A one-time buy arrives as
|
|
36
|
+
// `frequency=once`, which reading `!!state.frequency` called a subscription:
|
|
37
|
+
// every one-time receipt got the subscription sentence with its cycle slots
|
|
38
|
+
// empty, because `once` is not a cadence and the map below has no row for it.
|
|
39
|
+
// The same list decides what verify.js can poll the account for (#232).
|
|
40
|
+
const isSubscription = FREQUENCIES.includes(state.frequency);
|
|
41
|
+
const isOneTime = state.frequency === ONE_TIME_FREQUENCY;
|
|
42
|
+
|
|
43
|
+
const FREQUENCY_MAP = {
|
|
44
|
+
// `cycle` is the adverb ("charged annually"); `adjective` is the noun
|
|
45
|
+
// modifier ("annual subscription") — "annually subscription" was the tell.
|
|
46
|
+
daily: { cycle: 'daily', adjective: 'daily', period: 'day' },
|
|
47
|
+
weekly: { cycle: 'weekly', adjective: 'weekly', period: 'week' },
|
|
48
|
+
monthly: { cycle: 'monthly', adjective: 'monthly', period: 'month' },
|
|
49
|
+
annually: { cycle: 'annually', adjective: 'annual', period: 'year' },
|
|
50
|
+
};
|
|
51
|
+
const freq = FREQUENCY_MAP[state.frequency] || { cycle: '', adjective: '', period: '' };
|
|
52
|
+
const billingCycleText = freq.cycle;
|
|
53
|
+
const billingAdjectiveText = freq.adjective;
|
|
54
|
+
const billingPeriodText = freq.period;
|
|
55
|
+
|
|
56
|
+
// Build subscription info text
|
|
57
|
+
let subscriptionInfoText = '';
|
|
58
|
+
if (isSubscription) {
|
|
59
|
+
if (state.hasFreeTrial) {
|
|
60
|
+
subscriptionInfoText = `Free Trial Active! Your trial period has begun. You'll be charged ${billingCycleText} after the trial ends.`;
|
|
61
|
+
} else {
|
|
62
|
+
subscriptionInfoText = `Your ${billingAdjectiveText} subscription is now active. You'll be charged automatically each ${billingPeriodText}.`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// The one-time buy's own note: what it needs to hear is that nothing else is
|
|
67
|
+
// coming, which is the opposite of everything the subscription copy says.
|
|
68
|
+
const purchaseInfoText = isOneTime
|
|
69
|
+
? 'This is a one-time purchase. There is nothing to renew and nothing to cancel.'
|
|
70
|
+
: '';
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
confirmation: {
|
|
74
|
+
order: {
|
|
75
|
+
id: state.orderId || 'Loading...',
|
|
76
|
+
// "Plan" is subscription language on a one-time buy (#282)
|
|
77
|
+
itemLabel: isOneTime ? 'Item' : 'Plan',
|
|
78
|
+
productName: state.productName || state.productId || 'Product',
|
|
79
|
+
total: formatCurrency(state.amount),
|
|
80
|
+
currency: state.currency,
|
|
81
|
+
},
|
|
82
|
+
subscription: {
|
|
83
|
+
// "Your subscription is now active" is a claim about the account, so it
|
|
84
|
+
// waits for the account to say so (#232)
|
|
85
|
+
show: isSubscription && state.status === 'confirmed',
|
|
86
|
+
hasFreeTrial: state.hasFreeTrial,
|
|
87
|
+
billingCycle: billingCycleText,
|
|
88
|
+
infoText: subscriptionInfoText,
|
|
89
|
+
},
|
|
90
|
+
purchase: {
|
|
91
|
+
// The same gate the subscription note sits behind: a note about what
|
|
92
|
+
// was bought waits until the purchase is known to have landed (#232)
|
|
93
|
+
show: isOneTime && state.status === 'confirmed',
|
|
94
|
+
infoText: purchaseInfoText,
|
|
95
|
+
},
|
|
96
|
+
// Which of the three moments the page is rendering (#232). Only
|
|
97
|
+
// `confirmed` may say the words "payment received".
|
|
98
|
+
verification: {
|
|
99
|
+
processing: state.status === 'processing',
|
|
100
|
+
confirmed: state.status === 'confirmed',
|
|
101
|
+
timedOut: state.status === 'timeout',
|
|
102
|
+
},
|
|
103
|
+
loaded: state.loaded,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Format a number as currency, or return placeholder
|
|
109
|
+
function formatCurrency(amount) {
|
|
110
|
+
if (amount == null || isNaN(amount)) return '$--';
|
|
111
|
+
return `$${Number(amount).toFixed(2)}`;
|
|
112
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// The confirmation page's conversion PIXEL — the browser half of the checkout
|
|
2
|
+
// ([#386](https://github.com/Omega-JS-Stack/omega/issues/386)).
|
|
3
|
+
//
|
|
4
|
+
// The backend's payment webhook is the TRUTH: it sees what the provider actually
|
|
5
|
+
// charged. What only a browser can give is the RETARGETING signal — Meta's and
|
|
6
|
+
// TikTok's pixels tie the conversion to the ad click sitting in this page's
|
|
7
|
+
// cookies — and, for GA4, the session, the campaign and the client id a webhook
|
|
8
|
+
// has none of.
|
|
9
|
+
//
|
|
10
|
+
// TWO THINGS THIS HALF GETS RIGHT, both found on 2026-08-27:
|
|
11
|
+
//
|
|
12
|
+
// 1. A TRIAL CHECKOUT IS NOT A PURCHASE
|
|
13
|
+
// ([#654](https://github.com/Omega-JS-Stack/omega/issues/654)). The intent
|
|
14
|
+
// route sets `?track=true` for EVERY checkout, trials included, so a $0 trial
|
|
15
|
+
// used to fire a browser `purchase` while the webhook fired `trial_start`.
|
|
16
|
+
// The AMOUNT was never the defect — the intent route already puts `amount=0`
|
|
17
|
+
// on a trial confirmation URL (`routes/payments/intent/post.js`) — the NAME
|
|
18
|
+
// was: two different event names never deduplicate, so each platform counted
|
|
19
|
+
// the browser half as a second conversion beside the server's trial. A trial
|
|
20
|
+
// order fires `trial_start` with value 0; everything else fires `purchase`.
|
|
21
|
+
// 2. GA4 BELONGS ON THE PURCHASE HALF
|
|
22
|
+
// ([#656](https://github.com/Omega-JS-Stack/omega/issues/656)). GA4
|
|
23
|
+
// deduplicates `purchase` on `transaction_id`
|
|
24
|
+
// (https://support.google.com/analytics/answer/12313109), and both halves
|
|
25
|
+
// send the ORDER id — so the browser adds its attribution and GA4 still
|
|
26
|
+
// counts one purchase. `trial_start` is a GA4 CUSTOM event with no such
|
|
27
|
+
// dedupe, so its browser half names the ad platforms only and the server
|
|
28
|
+
// keeps GA4 to itself.
|
|
29
|
+
//
|
|
30
|
+
// Both halves carry the SAME dedupe id, or each platform counts two conversions:
|
|
31
|
+
//
|
|
32
|
+
// THE DEDUPE ID IS `<canonical>.<order id>`
|
|
33
|
+
//
|
|
34
|
+
// which is the ORDER-ID branch of the backend's own derivation
|
|
35
|
+
// (`events/firestore/payments-webhooks/analytics.js` resolveEventId keys the two
|
|
36
|
+
// browser-twinned events, `purchase` and `trial_start`, on the order — the only
|
|
37
|
+
// id a browser can compute).
|
|
38
|
+
import omega from '@omega.js/client';
|
|
39
|
+
import { event } from '__main_assets__/js/libs/analytics.js';
|
|
40
|
+
import { FREQUENCIES, ONE_TIME_FREQUENCY } from '../../checkout/modules/state.js';
|
|
41
|
+
|
|
42
|
+
// Build the canonical items array for the purchase.
|
|
43
|
+
//
|
|
44
|
+
// The category comes from WHAT WAS BOUGHT, and the redirect the intent route
|
|
45
|
+
// builds now says so outright — `type=subscription|one-time`, the one field here
|
|
46
|
+
// that needs no inferring ([#668](https://github.com/Omega-JS-Stack/omega/issues/668)).
|
|
47
|
+
// The cadence is the FALLBACK, for a confirmation URL minted before the type was
|
|
48
|
+
// sent: reading the truthiness of the frequency string called every one-time buy a
|
|
49
|
+
// subscription, because checkout sends `frequency=once` for one (#282 is the same
|
|
50
|
+
// bug in the receipt copy), so the fallback reads FREQUENCIES — the cadences
|
|
51
|
+
// checkout actually SELLS, the same list the bindings and the verification poll
|
|
52
|
+
// read. A stale link that carries a cadence for a one-time product (the live buy
|
|
53
|
+
// reached this file as `frequency=annually`) is classified by the type regardless.
|
|
54
|
+
//
|
|
55
|
+
// `price` is the conversion's own amount, passed in rather than read off the
|
|
56
|
+
// state: the intent route already sends `amount=0` on a trial checkout, so this
|
|
57
|
+
// default and the trial's explicit 0 agree today. DEFENSIVE — the conversion's
|
|
58
|
+
// value has ONE source in this file, so a confirmation URL that ever carried the
|
|
59
|
+
// plan's price on a trial could not put it on the item either ([#654]).
|
|
60
|
+
export function buildItems(state, price = state.amount) {
|
|
61
|
+
const isSubscription = state.type
|
|
62
|
+
? state.type === 'subscription'
|
|
63
|
+
: FREQUENCIES.includes(state.frequency);
|
|
64
|
+
|
|
65
|
+
return [{
|
|
66
|
+
item_id: state.productId,
|
|
67
|
+
item_name: state.productName || state.productId,
|
|
68
|
+
item_category: isSubscription ? 'subscription' : 'one-time',
|
|
69
|
+
item_variant: isSubscription ? state.frequency : ONE_TIME_FREQUENCY,
|
|
70
|
+
price: price,
|
|
71
|
+
quantity: 1,
|
|
72
|
+
}];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Fire the canonical conversion for this order — see the header for which.
|
|
76
|
+
function trackPurchase(state) {
|
|
77
|
+
const canonical = state.hasFreeTrial ? 'trial_start' : 'purchase';
|
|
78
|
+
// A trial charges nothing. The intent route already sends `amount=0` for one,
|
|
79
|
+
// so this is DEFENSIVE: the value a trial reports is 0 here whatever the
|
|
80
|
+
// confirmation URL says ([#654]).
|
|
81
|
+
const value = state.hasFreeTrial ? 0 : state.amount;
|
|
82
|
+
|
|
83
|
+
event(canonical, {
|
|
84
|
+
// The same id the webhook sends, and the key GA4 collapses the two halves on.
|
|
85
|
+
transaction_id: state.orderId,
|
|
86
|
+
value: value,
|
|
87
|
+
currency: state.currency,
|
|
88
|
+
items: buildItems(state, value),
|
|
89
|
+
payment_provider: state.paymentMethod,
|
|
90
|
+
payment_frequency: state.frequency,
|
|
91
|
+
is_trial: state.hasFreeTrial,
|
|
92
|
+
}, {
|
|
93
|
+
// GA4 rides the purchase half (it dedupes on transaction_id) but never the
|
|
94
|
+
// trial half, where its event is custom and the server owns it outright.
|
|
95
|
+
providers: state.hasFreeTrial ? ['meta', 'tiktok'] : ['ga4', 'meta', 'tiktok'],
|
|
96
|
+
eventId: `${canonical}.${state.orderId}`,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Track purchase only if the track=true URL param is present
|
|
101
|
+
// Removes the param after tracking to prevent duplicates on refresh
|
|
102
|
+
// Also stores orderId in omega storage as a backup guard
|
|
103
|
+
export function trackPurchaseIfNeeded(state) {
|
|
104
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
105
|
+
const shouldTrack = urlParams.get('track') === 'true';
|
|
106
|
+
|
|
107
|
+
if (!shouldTrack) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Track the purchase
|
|
112
|
+
trackPurchase(state);
|
|
113
|
+
|
|
114
|
+
// Remove 'track' param from URL to prevent re-tracking on refresh
|
|
115
|
+
urlParams.delete('track');
|
|
116
|
+
const newUrl = urlParams.toString()
|
|
117
|
+
? `${window.location.pathname}?${urlParams.toString()}`
|
|
118
|
+
: window.location.pathname;
|
|
119
|
+
window.history.replaceState({}, document.title, newUrl);
|
|
120
|
+
|
|
121
|
+
// Backup: store orderId in storage
|
|
122
|
+
const trackedOrders = omega.storage().get('trackedPurchases', []);
|
|
123
|
+
if (!trackedOrders.includes(state.orderId)) {
|
|
124
|
+
trackedOrders.push(state.orderId);
|
|
125
|
+
|
|
126
|
+
// Keep only last 50 orders
|
|
127
|
+
if (trackedOrders.length > 50) {
|
|
128
|
+
trackedOrders.shift();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
omega.storage().set('trackedPurchases', trackedOrders);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Has the purchase the redirect claims actually LANDED? (#232)
|
|
2
|
+
//
|
|
3
|
+
// Entitlement is granted by the payment webhook, which arrives AFTER the
|
|
4
|
+
// provider has redirected the browser here — usually a second or two later,
|
|
5
|
+
// sometimes never (a declined charge, an undelivered webhook in local dev). The
|
|
6
|
+
// redirect's URL params are the provider's claim, not proof, so the page asks
|
|
7
|
+
// the account itself before it congratulates anyone.
|
|
8
|
+
import omega from '@omega.js/client';
|
|
9
|
+
import { createLogger } from '__main_assets__/js/libs/logger.js';
|
|
10
|
+
import { FREQUENCIES } from '../../checkout/modules/state.js';
|
|
11
|
+
|
|
12
|
+
const logger = createLogger('confirmation');
|
|
13
|
+
|
|
14
|
+
// How often to ask, and how long before pointing the customer at support.
|
|
15
|
+
export const POLL_INTERVAL_MS = 2000;
|
|
16
|
+
export const POLL_TIMEOUT_MS = 30000;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Is this a purchase whose landing the account doc can actually prove?
|
|
20
|
+
*
|
|
21
|
+
* Only the billing cadences checkout sells (`FREQUENCIES`) write account
|
|
22
|
+
* state to wait for. A one-time purchase arrives as `frequency=once` and
|
|
23
|
+
* writes nothing to the account doc — the receipt is the whole answer there.
|
|
24
|
+
*
|
|
25
|
+
* The product TYPE the redirect carries is the second guard, and it outranks
|
|
26
|
+
* the cadence: a checkout that sent the wrong frequency (`type=one-time,
|
|
27
|
+
* frequency=annually`, [#668](https://github.com/Omega-JS-Stack/omega/issues/668))
|
|
28
|
+
* had this page polling for a plan the purchase never writes, all the way to
|
|
29
|
+
* the timeout, on a payment that had completed cleanly. A redirect old enough
|
|
30
|
+
* to carry no type at all still answers on the cadence alone.
|
|
31
|
+
*/
|
|
32
|
+
export function isVerifiable(state) {
|
|
33
|
+
if (state?.type && state.type !== 'subscription') {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return FREQUENCIES.includes(state?.frequency);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The moment the page OPENS in.
|
|
42
|
+
*
|
|
43
|
+
* A purchase with a poll behind it opens UNSURE — nothing about the order may
|
|
44
|
+
* render until the account answers, or the receipt sits on screen beside a
|
|
45
|
+
* spinner and reads as broken (Ian's QA). One with no poll — a one-time buy the
|
|
46
|
+
* account doc never records — is already answered, so it renders at once.
|
|
47
|
+
*
|
|
48
|
+
* @param {object} state - the confirmation page state (frequency)
|
|
49
|
+
* @returns {'processing'|'confirmed'}
|
|
50
|
+
*/
|
|
51
|
+
export function initialStatus(state) {
|
|
52
|
+
return isVerifiable(state) ? 'processing' : 'confirmed';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Does this account carry the purchase that was just made?
|
|
57
|
+
*
|
|
58
|
+
* The account doc is the only purchase state a browser may read — `payments-orders`
|
|
59
|
+
* is admin-only by security rule — and it is exactly what the subscription
|
|
60
|
+
* webhook writes. The plan has to MATCH: a user who already held one plan while
|
|
61
|
+
* buying another must not be confirmed by the plan they walked in with.
|
|
62
|
+
*
|
|
63
|
+
* @param {object|null} account - the user doc, or null when there is none
|
|
64
|
+
* @param {string} productId - the plan the redirect says was bought
|
|
65
|
+
*/
|
|
66
|
+
export function purchaseLanded(account, productId) {
|
|
67
|
+
// No account doc is no ANSWER, never a yes — and it must not be asked about
|
|
68
|
+
// either: the client's `resolveSubscription(account)` falls back to the STORED
|
|
69
|
+
// auth state when it is handed nothing, so a null read would be answered out
|
|
70
|
+
// of localStorage with the plan the shopper walked in with.
|
|
71
|
+
if (!account) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const resolved = omega.auth().resolveSubscription(account);
|
|
76
|
+
|
|
77
|
+
if (!resolved.active) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return !productId || resolved.plan === productId;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Read the buyer's own account doc.
|
|
85
|
+
async function readAccount() {
|
|
86
|
+
const user = omega.auth().getUser();
|
|
87
|
+
|
|
88
|
+
if (!user) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const snapshot = await omega.firestore().doc(`users/${user.uid}`).get();
|
|
93
|
+
|
|
94
|
+
return snapshot.exists() ? snapshot.data() : null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Ask until the purchase is real, or the budget runs out.
|
|
101
|
+
*
|
|
102
|
+
* Every I/O seam is injected so the loop itself is unit-testable at full speed.
|
|
103
|
+
*
|
|
104
|
+
* @param {object} state - the confirmation page state (productId, frequency)
|
|
105
|
+
* @param {object} [seams] - read/sleep/now/interval/timeout overrides
|
|
106
|
+
* @returns {Promise<'confirmed'|'timeout'>}
|
|
107
|
+
*/
|
|
108
|
+
export async function verifyPurchase(state, {
|
|
109
|
+
read = readAccount,
|
|
110
|
+
sleep = wait,
|
|
111
|
+
now = () => Date.now(),
|
|
112
|
+
intervalMs = POLL_INTERVAL_MS,
|
|
113
|
+
timeoutMs = POLL_TIMEOUT_MS,
|
|
114
|
+
} = {}) {
|
|
115
|
+
if (!isVerifiable(state)) {
|
|
116
|
+
return 'confirmed';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const deadline = now() + timeoutMs;
|
|
120
|
+
|
|
121
|
+
while (true) {
|
|
122
|
+
let account = null;
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
account = await read();
|
|
126
|
+
} catch (e) {
|
|
127
|
+
// A read that FAILED is no answer, not a NO — the webhook may still be in
|
|
128
|
+
// flight behind a network blip. Keep asking; the budget decides.
|
|
129
|
+
logger.warn(`Could not read the account while confirming the purchase: ${e.message}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (purchaseLanded(account, state.productId)) {
|
|
133
|
+
return 'confirmed';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (now() >= deadline) {
|
|
137
|
+
return 'timeout';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
await sleep(intervalMs);
|
|
141
|
+
}
|
|
142
|
+
}
|