@scalebun/web 1.0.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 +21 -0
- package/README.md +59 -0
- package/dist/bootstrap/FeatureRegistry.d.ts +44 -0
- package/dist/bootstrap/FeatureRegistry.d.ts.map +1 -0
- package/dist/bootstrap/FeatureRegistry.js +85 -0
- package/dist/bootstrap/FeatureRegistry.js.map +1 -0
- package/dist/bootstrap/SDKBootstrapper.d.ts +37 -0
- package/dist/bootstrap/SDKBootstrapper.d.ts.map +1 -0
- package/dist/bootstrap/SDKBootstrapper.js +248 -0
- package/dist/bootstrap/SDKBootstrapper.js.map +1 -0
- package/dist/browser.d.ts +51 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +81 -0
- package/dist/browser.js.map +1 -0
- package/dist/config/schema.d.ts +108 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +95 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/breadcrumbs.d.ts +56 -0
- package/dist/core/breadcrumbs.d.ts.map +1 -0
- package/dist/core/breadcrumbs.js +141 -0
- package/dist/core/breadcrumbs.js.map +1 -0
- package/dist/core/capabilities.d.ts +38 -0
- package/dist/core/capabilities.d.ts.map +1 -0
- package/dist/core/capabilities.js +78 -0
- package/dist/core/capabilities.js.map +1 -0
- package/dist/core/consent.d.ts +17 -0
- package/dist/core/consent.d.ts.map +1 -0
- package/dist/core/consent.js +38 -0
- package/dist/core/consent.js.map +1 -0
- package/dist/core/csp.d.ts +31 -0
- package/dist/core/csp.d.ts.map +1 -0
- package/dist/core/csp.js +74 -0
- package/dist/core/csp.js.map +1 -0
- package/dist/core/evalContext.d.ts +7 -0
- package/dist/core/evalContext.d.ts.map +1 -0
- package/dist/core/evalContext.js +22 -0
- package/dist/core/evalContext.js.map +1 -0
- package/dist/core/ids.d.ts +6 -0
- package/dist/core/ids.d.ts.map +1 -0
- package/dist/core/ids.js +35 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/index.d.ts +15 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +15 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/lifecycle.d.ts +4 -0
- package/dist/core/lifecycle.d.ts.map +1 -0
- package/dist/core/lifecycle.js +24 -0
- package/dist/core/lifecycle.js.map +1 -0
- package/dist/core/logger.d.ts +12 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +14 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/observe.d.ts +3 -0
- package/dist/core/observe.d.ts.map +1 -0
- package/dist/core/observe.js +22 -0
- package/dist/core/observe.js.map +1 -0
- package/dist/core/pageContext.d.ts +13 -0
- package/dist/core/pageContext.d.ts.map +1 -0
- package/dist/core/pageContext.js +73 -0
- package/dist/core/pageContext.js.map +1 -0
- package/dist/core/prune.d.ts +7 -0
- package/dist/core/prune.d.ts.map +1 -0
- package/dist/core/prune.js +31 -0
- package/dist/core/prune.js.map +1 -0
- package/dist/core/redact.d.ts +15 -0
- package/dist/core/redact.d.ts.map +1 -0
- package/dist/core/redact.js +50 -0
- package/dist/core/redact.js.map +1 -0
- package/dist/core/replayCoord.d.ts +22 -0
- package/dist/core/replayCoord.d.ts.map +1 -0
- package/dist/core/replayCoord.js +20 -0
- package/dist/core/replayCoord.js.map +1 -0
- package/dist/core/retry.d.ts +25 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +44 -0
- package/dist/core/retry.js.map +1 -0
- package/dist/core/runtime.d.ts +28 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +67 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/scrollDepth.d.ts +48 -0
- package/dist/core/scrollDepth.d.ts.map +1 -0
- package/dist/core/scrollDepth.js +63 -0
- package/dist/core/scrollDepth.js.map +1 -0
- package/dist/debug/index.d.ts +6 -0
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/index.js +2 -0
- package/dist/debug/index.js.map +1 -0
- package/dist/features/analytics/AnalyticsFeature.d.ts +122 -0
- package/dist/features/analytics/AnalyticsFeature.d.ts.map +1 -0
- package/dist/features/analytics/AnalyticsFeature.js +757 -0
- package/dist/features/analytics/AnalyticsFeature.js.map +1 -0
- package/dist/features/analytics/autocapture.d.ts +13 -0
- package/dist/features/analytics/autocapture.d.ts.map +1 -0
- package/dist/features/analytics/autocapture.js +398 -0
- package/dist/features/analytics/autocapture.js.map +1 -0
- package/dist/features/analytics/governance.d.ts +15 -0
- package/dist/features/analytics/governance.d.ts.map +1 -0
- package/dist/features/analytics/governance.js +30 -0
- package/dist/features/analytics/governance.js.map +1 -0
- package/dist/features/analytics/revenue.d.ts +38 -0
- package/dist/features/analytics/revenue.d.ts.map +1 -0
- package/dist/features/analytics/revenue.js +26 -0
- package/dist/features/analytics/revenue.js.map +1 -0
- package/dist/features/analytics/sampler.d.ts +2 -0
- package/dist/features/analytics/sampler.d.ts.map +1 -0
- package/dist/features/analytics/sampler.js +24 -0
- package/dist/features/analytics/sampler.js.map +1 -0
- package/dist/features/analytics/subscription.d.ts +25 -0
- package/dist/features/analytics/subscription.d.ts.map +1 -0
- package/dist/features/analytics/subscription.js +51 -0
- package/dist/features/analytics/subscription.js.map +1 -0
- package/dist/features/attention/index.d.ts +29 -0
- package/dist/features/attention/index.d.ts.map +1 -0
- package/dist/features/attention/index.js +128 -0
- package/dist/features/attention/index.js.map +1 -0
- package/dist/features/bugreport/BugReportFeature.d.ts +36 -0
- package/dist/features/bugreport/BugReportFeature.d.ts.map +1 -0
- package/dist/features/bugreport/BugReportFeature.js +55 -0
- package/dist/features/bugreport/BugReportFeature.js.map +1 -0
- package/dist/features/bugreport/collect.d.ts +21 -0
- package/dist/features/bugreport/collect.d.ts.map +1 -0
- package/dist/features/bugreport/collect.js +27 -0
- package/dist/features/bugreport/collect.js.map +1 -0
- package/dist/features/bugreport/widget.d.ts +21 -0
- package/dist/features/bugreport/widget.d.ts.map +1 -0
- package/dist/features/bugreport/widget.js +111 -0
- package/dist/features/bugreport/widget.js.map +1 -0
- package/dist/features/coach/CoachmarkFeature.d.ts +78 -0
- package/dist/features/coach/CoachmarkFeature.d.ts.map +1 -0
- package/dist/features/coach/CoachmarkFeature.js +161 -0
- package/dist/features/coach/CoachmarkFeature.js.map +1 -0
- package/dist/features/coach/anchor.d.ts +32 -0
- package/dist/features/coach/anchor.d.ts.map +1 -0
- package/dist/features/coach/anchor.js +128 -0
- package/dist/features/coach/anchor.js.map +1 -0
- package/dist/features/coach/observers.d.ts +17 -0
- package/dist/features/coach/observers.d.ts.map +1 -0
- package/dist/features/coach/observers.js +49 -0
- package/dist/features/coach/observers.js.map +1 -0
- package/dist/features/coach/overlay.d.ts +15 -0
- package/dist/features/coach/overlay.d.ts.map +1 -0
- package/dist/features/coach/overlay.js +183 -0
- package/dist/features/coach/overlay.js.map +1 -0
- package/dist/features/coach/position.d.ts +9 -0
- package/dist/features/coach/position.d.ts.map +1 -0
- package/dist/features/coach/position.js +83 -0
- package/dist/features/coach/position.js.map +1 -0
- package/dist/features/coach/predicate.d.ts +10 -0
- package/dist/features/coach/predicate.d.ts.map +1 -0
- package/dist/features/coach/predicate.js +36 -0
- package/dist/features/coach/predicate.js.map +1 -0
- package/dist/features/coach/tour.d.ts +55 -0
- package/dist/features/coach/tour.d.ts.map +1 -0
- package/dist/features/coach/tour.js +181 -0
- package/dist/features/coach/tour.js.map +1 -0
- package/dist/features/coach/types.d.ts +161 -0
- package/dist/features/coach/types.d.ts.map +1 -0
- package/dist/features/coach/types.js +2 -0
- package/dist/features/coach/types.js.map +1 -0
- package/dist/features/coach/wait.d.ts +34 -0
- package/dist/features/coach/wait.d.ts.map +1 -0
- package/dist/features/coach/wait.js +107 -0
- package/dist/features/coach/wait.js.map +1 -0
- package/dist/features/config/ConfigFeature.d.ts +117 -0
- package/dist/features/config/ConfigFeature.d.ts.map +1 -0
- package/dist/features/config/ConfigFeature.js +437 -0
- package/dist/features/config/ConfigFeature.js.map +1 -0
- package/dist/features/config/bucketing.d.ts +20 -0
- package/dist/features/config/bucketing.d.ts.map +1 -0
- package/dist/features/config/bucketing.js +37 -0
- package/dist/features/config/bucketing.js.map +1 -0
- package/dist/features/config/configStore.d.ts +11 -0
- package/dist/features/config/configStore.d.ts.map +1 -0
- package/dist/features/config/configStore.js +66 -0
- package/dist/features/config/configStore.js.map +1 -0
- package/dist/features/config/targeting.d.ts +11 -0
- package/dist/features/config/targeting.d.ts.map +1 -0
- package/dist/features/config/targeting.js +57 -0
- package/dist/features/config/targeting.js.map +1 -0
- package/dist/features/config/types.d.ts +100 -0
- package/dist/features/config/types.d.ts.map +1 -0
- package/dist/features/config/types.js +9 -0
- package/dist/features/config/types.js.map +1 -0
- package/dist/features/console/ConsoleFeature.d.ts +31 -0
- package/dist/features/console/ConsoleFeature.d.ts.map +1 -0
- package/dist/features/console/ConsoleFeature.js +98 -0
- package/dist/features/console/ConsoleFeature.js.map +1 -0
- package/dist/features/console/normalize.d.ts +18 -0
- package/dist/features/console/normalize.d.ts.map +1 -0
- package/dist/features/console/normalize.js +64 -0
- package/dist/features/console/normalize.js.map +1 -0
- package/dist/features/console/serialize.d.ts +24 -0
- package/dist/features/console/serialize.d.ts.map +1 -0
- package/dist/features/console/serialize.js +99 -0
- package/dist/features/console/serialize.js.map +1 -0
- package/dist/features/console/throttle.d.ts +27 -0
- package/dist/features/console/throttle.d.ts.map +1 -0
- package/dist/features/console/throttle.js +37 -0
- package/dist/features/console/throttle.js.map +1 -0
- package/dist/features/crash/CrashFeature.d.ts +46 -0
- package/dist/features/crash/CrashFeature.d.ts.map +1 -0
- package/dist/features/crash/CrashFeature.js +173 -0
- package/dist/features/crash/CrashFeature.js.map +1 -0
- package/dist/features/crash/liveness.d.ts +30 -0
- package/dist/features/crash/liveness.d.ts.map +1 -0
- package/dist/features/crash/liveness.js +131 -0
- package/dist/features/crash/liveness.js.map +1 -0
- package/dist/features/engage/EngageFeature.d.ts +61 -0
- package/dist/features/engage/EngageFeature.d.ts.map +1 -0
- package/dist/features/engage/EngageFeature.js +221 -0
- package/dist/features/engage/EngageFeature.js.map +1 -0
- package/dist/features/engage/attachments.d.ts +24 -0
- package/dist/features/engage/attachments.d.ts.map +1 -0
- package/dist/features/engage/attachments.js +209 -0
- package/dist/features/engage/attachments.js.map +1 -0
- package/dist/features/engage/gameLogic.d.ts +60 -0
- package/dist/features/engage/gameLogic.d.ts.map +1 -0
- package/dist/features/engage/gameLogic.js +213 -0
- package/dist/features/engage/gameLogic.js.map +1 -0
- package/dist/features/engage/gameResolver.d.ts +35 -0
- package/dist/features/engage/gameResolver.d.ts.map +1 -0
- package/dist/features/engage/gameResolver.js +81 -0
- package/dist/features/engage/gameResolver.js.map +1 -0
- package/dist/features/engage/gameTypes.d.ts +76 -0
- package/dist/features/engage/gameTypes.d.ts.map +1 -0
- package/dist/features/engage/gameTypes.js +17 -0
- package/dist/features/engage/gameTypes.js.map +1 -0
- package/dist/features/engage/inappSlots.d.ts +39 -0
- package/dist/features/engage/inappSlots.d.ts.map +1 -0
- package/dist/features/engage/inappSlots.js +50 -0
- package/dist/features/engage/inappSlots.js.map +1 -0
- package/dist/features/engage/normalize.d.ts +11 -0
- package/dist/features/engage/normalize.d.ts.map +1 -0
- package/dist/features/engage/normalize.js +203 -0
- package/dist/features/engage/normalize.js.map +1 -0
- package/dist/features/engage/richInApp.d.ts +64 -0
- package/dist/features/engage/richInApp.d.ts.map +1 -0
- package/dist/features/engage/richInApp.js +1082 -0
- package/dist/features/engage/richInApp.js.map +1 -0
- package/dist/features/engage/runtime.d.ts +78 -0
- package/dist/features/engage/runtime.d.ts.map +1 -0
- package/dist/features/engage/runtime.js +349 -0
- package/dist/features/engage/runtime.js.map +1 -0
- package/dist/features/engage/shakeDetector.d.ts +6 -0
- package/dist/features/engage/shakeDetector.d.ts.map +1 -0
- package/dist/features/engage/shakeDetector.js +105 -0
- package/dist/features/engage/shakeDetector.js.map +1 -0
- package/dist/features/engage/theme.d.ts +129 -0
- package/dist/features/engage/theme.d.ts.map +1 -0
- package/dist/features/engage/theme.js +270 -0
- package/dist/features/engage/theme.js.map +1 -0
- package/dist/features/engage/throttle.d.ts +31 -0
- package/dist/features/engage/throttle.d.ts.map +1 -0
- package/dist/features/engage/throttle.js +130 -0
- package/dist/features/engage/throttle.js.map +1 -0
- package/dist/features/engage/transport.d.ts +62 -0
- package/dist/features/engage/transport.d.ts.map +1 -0
- package/dist/features/engage/transport.js +185 -0
- package/dist/features/engage/transport.js.map +1 -0
- package/dist/features/engage/triggerEngine.d.ts +39 -0
- package/dist/features/engage/triggerEngine.d.ts.map +1 -0
- package/dist/features/engage/triggerEngine.js +105 -0
- package/dist/features/engage/triggerEngine.js.map +1 -0
- package/dist/features/engage/types.d.ts +265 -0
- package/dist/features/engage/types.d.ts.map +1 -0
- package/dist/features/engage/types.js +3 -0
- package/dist/features/engage/types.js.map +1 -0
- package/dist/features/engage/widget/InAppWidget.d.ts +10 -0
- package/dist/features/engage/widget/InAppWidget.d.ts.map +1 -0
- package/dist/features/engage/widget/InAppWidget.js +136 -0
- package/dist/features/engage/widget/InAppWidget.js.map +1 -0
- package/dist/features/engage/widget/SurveyWidget.d.ts +11 -0
- package/dist/features/engage/widget/SurveyWidget.d.ts.map +1 -0
- package/dist/features/engage/widget/SurveyWidget.js +546 -0
- package/dist/features/engage/widget/SurveyWidget.js.map +1 -0
- package/dist/features/errors/ErrorsFeature.d.ts +62 -0
- package/dist/features/errors/ErrorsFeature.d.ts.map +1 -0
- package/dist/features/errors/ErrorsFeature.js +209 -0
- package/dist/features/errors/ErrorsFeature.js.map +1 -0
- package/dist/features/errors/causes.d.ts +15 -0
- package/dist/features/errors/causes.d.ts.map +1 -0
- package/dist/features/errors/causes.js +29 -0
- package/dist/features/errors/causes.js.map +1 -0
- package/dist/features/errors/dedup.d.ts +28 -0
- package/dist/features/errors/dedup.d.ts.map +1 -0
- package/dist/features/errors/dedup.js +42 -0
- package/dist/features/errors/dedup.js.map +1 -0
- package/dist/features/errors/group/fingerprint.d.ts +13 -0
- package/dist/features/errors/group/fingerprint.d.ts.map +1 -0
- package/dist/features/errors/group/fingerprint.js +45 -0
- package/dist/features/errors/group/fingerprint.js.map +1 -0
- package/dist/features/errors/lazy.d.ts +8 -0
- package/dist/features/errors/lazy.d.ts.map +1 -0
- package/dist/features/errors/lazy.js +8 -0
- package/dist/features/errors/lazy.js.map +1 -0
- package/dist/features/errors/normalize.d.ts +26 -0
- package/dist/features/errors/normalize.d.ts.map +1 -0
- package/dist/features/errors/normalize.js +58 -0
- package/dist/features/errors/normalize.js.map +1 -0
- package/dist/features/errors/parse/stacktrace.d.ts +13 -0
- package/dist/features/errors/parse/stacktrace.d.ts.map +1 -0
- package/dist/features/errors/parse/stacktrace.js +85 -0
- package/dist/features/errors/parse/stacktrace.js.map +1 -0
- package/dist/features/errors/redact.d.ts +7 -0
- package/dist/features/errors/redact.d.ts.map +1 -0
- package/dist/features/errors/redact.js +39 -0
- package/dist/features/errors/redact.js.map +1 -0
- package/dist/features/errors/sampling.d.ts +2 -0
- package/dist/features/errors/sampling.d.ts.map +1 -0
- package/dist/features/errors/sampling.js +24 -0
- package/dist/features/errors/sampling.js.map +1 -0
- package/dist/features/errors/scope.d.ts +26 -0
- package/dist/features/errors/scope.d.ts.map +1 -0
- package/dist/features/errors/scope.js +30 -0
- package/dist/features/errors/scope.js.map +1 -0
- package/dist/features/exit-intent/ExitIntentFeature.d.ts +16 -0
- package/dist/features/exit-intent/ExitIntentFeature.d.ts.map +1 -0
- package/dist/features/exit-intent/ExitIntentFeature.js +25 -0
- package/dist/features/exit-intent/ExitIntentFeature.js.map +1 -0
- package/dist/features/exit-intent/engine.d.ts +127 -0
- package/dist/features/exit-intent/engine.d.ts.map +1 -0
- package/dist/features/exit-intent/engine.js +227 -0
- package/dist/features/exit-intent/engine.js.map +1 -0
- package/dist/features/forms/index.d.ts +83 -0
- package/dist/features/forms/index.d.ts.map +1 -0
- package/dist/features/forms/index.js +405 -0
- package/dist/features/forms/index.js.map +1 -0
- package/dist/features/inapp/InApp2Feature.d.ts +24 -0
- package/dist/features/inapp/InApp2Feature.d.ts.map +1 -0
- package/dist/features/inapp/InApp2Feature.js +43 -0
- package/dist/features/inapp/InApp2Feature.js.map +1 -0
- package/dist/features/inapp/a11y/focus.d.ts +24 -0
- package/dist/features/inapp/a11y/focus.d.ts.map +1 -0
- package/dist/features/inapp/a11y/focus.js +112 -0
- package/dist/features/inapp/a11y/focus.js.map +1 -0
- package/dist/features/inapp/anchor/controller.d.ts +64 -0
- package/dist/features/inapp/anchor/controller.d.ts.map +1 -0
- package/dist/features/inapp/anchor/controller.js +155 -0
- package/dist/features/inapp/anchor/controller.js.map +1 -0
- package/dist/features/inapp/api.d.ts +28 -0
- package/dist/features/inapp/api.d.ts.map +1 -0
- package/dist/features/inapp/api.js +41 -0
- package/dist/features/inapp/api.js.map +1 -0
- package/dist/features/inapp/blocks/blocks.d.ts +65 -0
- package/dist/features/inapp/blocks/blocks.d.ts.map +1 -0
- package/dist/features/inapp/blocks/blocks.js +196 -0
- package/dist/features/inapp/blocks/blocks.js.map +1 -0
- package/dist/features/inapp/blocks/feedback.d.ts +13 -0
- package/dist/features/inapp/blocks/feedback.d.ts.map +1 -0
- package/dist/features/inapp/blocks/feedback.js +154 -0
- package/dist/features/inapp/blocks/feedback.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/carousel.d.ts +8 -0
- package/dist/features/inapp/blocks/heavy/carousel.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/carousel.js +67 -0
- package/dist/features/inapp/blocks/heavy/carousel.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/chart.d.ts +9 -0
- package/dist/features/inapp/blocks/heavy/chart.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/chart.js +83 -0
- package/dist/features/inapp/blocks/heavy/chart.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/code.d.ts +8 -0
- package/dist/features/inapp/blocks/heavy/code.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/code.js +47 -0
- package/dist/features/inapp/blocks/heavy/code.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/confetti.d.ts +9 -0
- package/dist/features/inapp/blocks/heavy/confetti.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/confetti.js +76 -0
- package/dist/features/inapp/blocks/heavy/confetti.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/countdown.d.ts +9 -0
- package/dist/features/inapp/blocks/heavy/countdown.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/countdown.js +59 -0
- package/dist/features/inapp/blocks/heavy/countdown.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/index.d.ts +11 -0
- package/dist/features/inapp/blocks/heavy/index.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/index.js +45 -0
- package/dist/features/inapp/blocks/heavy/index.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/markdown.d.ts +9 -0
- package/dist/features/inapp/blocks/heavy/markdown.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/markdown.js +76 -0
- package/dist/features/inapp/blocks/heavy/markdown.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/productgrid.d.ts +8 -0
- package/dist/features/inapp/blocks/heavy/productgrid.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/productgrid.js +46 -0
- package/dist/features/inapp/blocks/heavy/productgrid.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/qr.d.ts +10 -0
- package/dist/features/inapp/blocks/heavy/qr.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/qr.js +69 -0
- package/dist/features/inapp/blocks/heavy/qr.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/scratch.d.ts +8 -0
- package/dist/features/inapp/blocks/heavy/scratch.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/scratch.js +141 -0
- package/dist/features/inapp/blocks/heavy/scratch.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/slot.d.ts +8 -0
- package/dist/features/inapp/blocks/heavy/slot.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/slot.js +96 -0
- package/dist/features/inapp/blocks/heavy/slot.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/spinwheel.d.ts +9 -0
- package/dist/features/inapp/blocks/heavy/spinwheel.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/spinwheel.js +127 -0
- package/dist/features/inapp/blocks/heavy/spinwheel.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/steps.d.ts +27 -0
- package/dist/features/inapp/blocks/heavy/steps.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/steps.js +127 -0
- package/dist/features/inapp/blocks/heavy/steps.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/streak.d.ts +18 -0
- package/dist/features/inapp/blocks/heavy/streak.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/streak.js +52 -0
- package/dist/features/inapp/blocks/heavy/streak.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/table.d.ts +7 -0
- package/dist/features/inapp/blocks/heavy/table.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/table.js +30 -0
- package/dist/features/inapp/blocks/heavy/table.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/unavailable.d.ts +28 -0
- package/dist/features/inapp/blocks/heavy/unavailable.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/unavailable.js +33 -0
- package/dist/features/inapp/blocks/heavy/unavailable.js.map +1 -0
- package/dist/features/inapp/blocks/heavy/video.d.ts +7 -0
- package/dist/features/inapp/blocks/heavy/video.d.ts.map +1 -0
- package/dist/features/inapp/blocks/heavy/video.js +38 -0
- package/dist/features/inapp/blocks/heavy/video.js.map +1 -0
- package/dist/features/inapp/blocks/styles.d.ts +7 -0
- package/dist/features/inapp/blocks/styles.d.ts.map +1 -0
- package/dist/features/inapp/blocks/styles.js +198 -0
- package/dist/features/inapp/blocks/styles.js.map +1 -0
- package/dist/features/inapp/center/bridge.d.ts +12 -0
- package/dist/features/inapp/center/bridge.d.ts.map +1 -0
- package/dist/features/inapp/center/bridge.js +59 -0
- package/dist/features/inapp/center/bridge.js.map +1 -0
- package/dist/features/inapp/center/panel.d.ts +20 -0
- package/dist/features/inapp/center/panel.d.ts.map +1 -0
- package/dist/features/inapp/center/panel.js +194 -0
- package/dist/features/inapp/center/panel.js.map +1 -0
- package/dist/features/inapp/center/store.d.ts +50 -0
- package/dist/features/inapp/center/store.d.ts.map +1 -0
- package/dist/features/inapp/center/store.js +188 -0
- package/dist/features/inapp/center/store.js.map +1 -0
- package/dist/features/inapp/center/sync.d.ts +32 -0
- package/dist/features/inapp/center/sync.d.ts.map +1 -0
- package/dist/features/inapp/center/sync.js +60 -0
- package/dist/features/inapp/center/sync.js.map +1 -0
- package/dist/features/inapp/center/types.d.ts +46 -0
- package/dist/features/inapp/center/types.d.ts.map +1 -0
- package/dist/features/inapp/center/types.js +5 -0
- package/dist/features/inapp/center/types.js.map +1 -0
- package/dist/features/inapp/core/analytics.d.ts +35 -0
- package/dist/features/inapp/core/analytics.d.ts.map +1 -0
- package/dist/features/inapp/core/analytics.js +70 -0
- package/dist/features/inapp/core/analytics.js.map +1 -0
- package/dist/features/inapp/core/compat.d.ts +28 -0
- package/dist/features/inapp/core/compat.d.ts.map +1 -0
- package/dist/features/inapp/core/compat.js +104 -0
- package/dist/features/inapp/core/compat.js.map +1 -0
- package/dist/features/inapp/core/debugOverlay.d.ts +5 -0
- package/dist/features/inapp/core/debugOverlay.d.ts.map +1 -0
- package/dist/features/inapp/core/debugOverlay.js +79 -0
- package/dist/features/inapp/core/debugOverlay.js.map +1 -0
- package/dist/features/inapp/core/engine.d.ts +70 -0
- package/dist/features/inapp/core/engine.d.ts.map +1 -0
- package/dist/features/inapp/core/engine.js +248 -0
- package/dist/features/inapp/core/engine.js.map +1 -0
- package/dist/features/inapp/core/environment.d.ts +21 -0
- package/dist/features/inapp/core/environment.d.ts.map +1 -0
- package/dist/features/inapp/core/environment.js +57 -0
- package/dist/features/inapp/core/environment.js.map +1 -0
- package/dist/features/inapp/core/host.d.ts +53 -0
- package/dist/features/inapp/core/host.d.ts.map +1 -0
- package/dist/features/inapp/core/host.js +239 -0
- package/dist/features/inapp/core/host.js.map +1 -0
- package/dist/features/inapp/core/keyboard.d.ts +27 -0
- package/dist/features/inapp/core/keyboard.d.ts.map +1 -0
- package/dist/features/inapp/core/keyboard.js +69 -0
- package/dist/features/inapp/core/keyboard.js.map +1 -0
- package/dist/features/inapp/core/metrics.d.ts +73 -0
- package/dist/features/inapp/core/metrics.d.ts.map +1 -0
- package/dist/features/inapp/core/metrics.js +125 -0
- package/dist/features/inapp/core/metrics.js.map +1 -0
- package/dist/features/inapp/core/migration.d.ts +32 -0
- package/dist/features/inapp/core/migration.d.ts.map +1 -0
- package/dist/features/inapp/core/migration.js +28 -0
- package/dist/features/inapp/core/migration.js.map +1 -0
- package/dist/features/inapp/core/orchestrator.d.ts +77 -0
- package/dist/features/inapp/core/orchestrator.d.ts.map +1 -0
- package/dist/features/inapp/core/orchestrator.js +144 -0
- package/dist/features/inapp/core/orchestrator.js.map +1 -0
- package/dist/features/inapp/core/respect.d.ts +51 -0
- package/dist/features/inapp/core/respect.d.ts.map +1 -0
- package/dist/features/inapp/core/respect.js +78 -0
- package/dist/features/inapp/core/respect.js.map +1 -0
- package/dist/features/inapp/core/slots.d.ts +19 -0
- package/dist/features/inapp/core/slots.d.ts.map +1 -0
- package/dist/features/inapp/core/slots.js +53 -0
- package/dist/features/inapp/core/slots.js.map +1 -0
- package/dist/features/inapp/core/targeting.d.ts +58 -0
- package/dist/features/inapp/core/targeting.d.ts.map +1 -0
- package/dist/features/inapp/core/targeting.js +181 -0
- package/dist/features/inapp/core/targeting.js.map +1 -0
- package/dist/features/inapp/core/transport.d.ts +66 -0
- package/dist/features/inapp/core/transport.d.ts.map +1 -0
- package/dist/features/inapp/core/transport.js +154 -0
- package/dist/features/inapp/core/transport.js.map +1 -0
- package/dist/features/inapp/core/triggers.d.ts +94 -0
- package/dist/features/inapp/core/triggers.d.ts.map +1 -0
- package/dist/features/inapp/core/triggers.js +368 -0
- package/dist/features/inapp/core/triggers.js.map +1 -0
- package/dist/features/inapp/inappContract.web.d.ts +47 -0
- package/dist/features/inapp/inappContract.web.d.ts.map +1 -0
- package/dist/features/inapp/inappContract.web.js +219 -0
- package/dist/features/inapp/inappContract.web.js.map +1 -0
- package/dist/features/inapp/index.d.ts +23 -0
- package/dist/features/inapp/index.d.ts.map +1 -0
- package/dist/features/inapp/index.js +23 -0
- package/dist/features/inapp/index.js.map +1 -0
- package/dist/features/inapp/registry.canonical.hash.d.ts +7 -0
- package/dist/features/inapp/registry.canonical.hash.d.ts.map +1 -0
- package/dist/features/inapp/registry.canonical.hash.js +7 -0
- package/dist/features/inapp/registry.canonical.hash.js.map +1 -0
- package/dist/features/inapp/registry.web.canonical.d.ts +21 -0
- package/dist/features/inapp/registry.web.canonical.d.ts.map +1 -0
- package/dist/features/inapp/registry.web.canonical.js +136 -0
- package/dist/features/inapp/registry.web.canonical.js.map +1 -0
- package/dist/features/inapp/registry.web.catalog.d.ts +12 -0
- package/dist/features/inapp/registry.web.catalog.d.ts.map +1 -0
- package/dist/features/inapp/registry.web.catalog.js +208 -0
- package/dist/features/inapp/registry.web.catalog.js.map +1 -0
- package/dist/features/inapp/surfaces/banner.d.ts +7 -0
- package/dist/features/inapp/surfaces/banner.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/banner.js +30 -0
- package/dist/features/inapp/surfaces/banner.js.map +1 -0
- package/dist/features/inapp/surfaces/checklist.d.ts +13 -0
- package/dist/features/inapp/surfaces/checklist.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/checklist.js +127 -0
- package/dist/features/inapp/surfaces/checklist.js.map +1 -0
- package/dist/features/inapp/surfaces/coachmark.d.ts +10 -0
- package/dist/features/inapp/surfaces/coachmark.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/coachmark.js +92 -0
- package/dist/features/inapp/surfaces/coachmark.js.map +1 -0
- package/dist/features/inapp/surfaces/hotspot.d.ts +8 -0
- package/dist/features/inapp/surfaces/hotspot.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/hotspot.js +88 -0
- package/dist/features/inapp/surfaces/hotspot.js.map +1 -0
- package/dist/features/inapp/surfaces/inline.d.ts +13 -0
- package/dist/features/inapp/surfaces/inline.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/inline.js +72 -0
- package/dist/features/inapp/surfaces/inline.js.map +1 -0
- package/dist/features/inapp/surfaces/launcher.d.ts +9 -0
- package/dist/features/inapp/surfaces/launcher.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/launcher.js +54 -0
- package/dist/features/inapp/surfaces/launcher.js.map +1 -0
- package/dist/features/inapp/surfaces/modal.d.ts +8 -0
- package/dist/features/inapp/surfaces/modal.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/modal.js +70 -0
- package/dist/features/inapp/surfaces/modal.js.map +1 -0
- package/dist/features/inapp/surfaces/mount.d.ts +19 -0
- package/dist/features/inapp/surfaces/mount.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/mount.js +29 -0
- package/dist/features/inapp/surfaces/mount.js.map +1 -0
- package/dist/features/inapp/surfaces/palette.d.ts +9 -0
- package/dist/features/inapp/surfaces/palette.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/palette.js +127 -0
- package/dist/features/inapp/surfaces/palette.js.map +1 -0
- package/dist/features/inapp/surfaces/panel.d.ts +14 -0
- package/dist/features/inapp/surfaces/panel.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/panel.js +91 -0
- package/dist/features/inapp/surfaces/panel.js.map +1 -0
- package/dist/features/inapp/surfaces/popover.d.ts +10 -0
- package/dist/features/inapp/surfaces/popover.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/popover.js +66 -0
- package/dist/features/inapp/surfaces/popover.js.map +1 -0
- package/dist/features/inapp/surfaces/render.d.ts +34 -0
- package/dist/features/inapp/surfaces/render.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/render.js +52 -0
- package/dist/features/inapp/surfaces/render.js.map +1 -0
- package/dist/features/inapp/surfaces/slideover.d.ts +9 -0
- package/dist/features/inapp/surfaces/slideover.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/slideover.js +144 -0
- package/dist/features/inapp/surfaces/slideover.js.map +1 -0
- package/dist/features/inapp/surfaces/styles.d.ts +7 -0
- package/dist/features/inapp/surfaces/styles.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/styles.js +186 -0
- package/dist/features/inapp/surfaces/styles.js.map +1 -0
- package/dist/features/inapp/surfaces/surface.d.ts +69 -0
- package/dist/features/inapp/surfaces/surface.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/surface.js +80 -0
- package/dist/features/inapp/surfaces/surface.js.map +1 -0
- package/dist/features/inapp/surfaces/takeover.d.ts +9 -0
- package/dist/features/inapp/surfaces/takeover.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/takeover.js +60 -0
- package/dist/features/inapp/surfaces/takeover.js.map +1 -0
- package/dist/features/inapp/surfaces/toast.d.ts +7 -0
- package/dist/features/inapp/surfaces/toast.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/toast.js +48 -0
- package/dist/features/inapp/surfaces/toast.js.map +1 -0
- package/dist/features/inapp/surfaces/toolbar.d.ts +8 -0
- package/dist/features/inapp/surfaces/toolbar.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/toolbar.js +62 -0
- package/dist/features/inapp/surfaces/toolbar.js.map +1 -0
- package/dist/features/inapp/surfaces/tour.d.ts +14 -0
- package/dist/features/inapp/surfaces/tour.d.ts.map +1 -0
- package/dist/features/inapp/surfaces/tour.js +199 -0
- package/dist/features/inapp/surfaces/tour.js.map +1 -0
- package/dist/features/inapp/types.d.ts +163 -0
- package/dist/features/inapp/types.d.ts.map +1 -0
- package/dist/features/inapp/types.js +12 -0
- package/dist/features/inapp/types.js.map +1 -0
- package/dist/features/inbox/InboxFeature.d.ts +57 -0
- package/dist/features/inbox/InboxFeature.d.ts.map +1 -0
- package/dist/features/inbox/InboxFeature.js +225 -0
- package/dist/features/inbox/InboxFeature.js.map +1 -0
- package/dist/features/inbox/runtime.d.ts +67 -0
- package/dist/features/inbox/runtime.d.ts.map +1 -0
- package/dist/features/inbox/runtime.js +376 -0
- package/dist/features/inbox/runtime.js.map +1 -0
- package/dist/features/inbox/store.d.ts +37 -0
- package/dist/features/inbox/store.d.ts.map +1 -0
- package/dist/features/inbox/store.js +149 -0
- package/dist/features/inbox/store.js.map +1 -0
- package/dist/features/inbox/sync.d.ts +49 -0
- package/dist/features/inbox/sync.d.ts.map +1 -0
- package/dist/features/inbox/sync.js +131 -0
- package/dist/features/inbox/sync.js.map +1 -0
- package/dist/features/inbox/types.d.ts +275 -0
- package/dist/features/inbox/types.d.ts.map +1 -0
- package/dist/features/inbox/types.js +42 -0
- package/dist/features/inbox/types.js.map +1 -0
- package/dist/features/inbox/widget/InboxWidget.d.ts +16 -0
- package/dist/features/inbox/widget/InboxWidget.d.ts.map +1 -0
- package/dist/features/inbox/widget/InboxWidget.js +608 -0
- package/dist/features/inbox/widget/InboxWidget.js.map +1 -0
- package/dist/features/index.d.ts +21 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/index.js +2 -0
- package/dist/features/index.js.map +1 -0
- package/dist/features/journey/InteractionTracker.d.ts +34 -0
- package/dist/features/journey/InteractionTracker.d.ts.map +1 -0
- package/dist/features/journey/InteractionTracker.js +125 -0
- package/dist/features/journey/InteractionTracker.js.map +1 -0
- package/dist/features/journey/JourneyFeature.d.ts +18 -0
- package/dist/features/journey/JourneyFeature.d.ts.map +1 -0
- package/dist/features/journey/JourneyFeature.js +57 -0
- package/dist/features/journey/JourneyFeature.js.map +1 -0
- package/dist/features/journey/NavigationTracker.d.ts +16 -0
- package/dist/features/journey/NavigationTracker.d.ts.map +1 -0
- package/dist/features/journey/NavigationTracker.js +92 -0
- package/dist/features/journey/NavigationTracker.js.map +1 -0
- package/dist/features/journey/friction.d.ts +29 -0
- package/dist/features/journey/friction.d.ts.map +1 -0
- package/dist/features/journey/friction.js +65 -0
- package/dist/features/journey/friction.js.map +1 -0
- package/dist/features/manifest.d.ts +20 -0
- package/dist/features/manifest.d.ts.map +1 -0
- package/dist/features/manifest.js +76 -0
- package/dist/features/manifest.js.map +1 -0
- package/dist/features/network/NetworkFeature.d.ts +56 -0
- package/dist/features/network/NetworkFeature.d.ts.map +1 -0
- package/dist/features/network/NetworkFeature.js +235 -0
- package/dist/features/network/NetworkFeature.js.map +1 -0
- package/dist/features/network/capture/body.d.ts +31 -0
- package/dist/features/network/capture/body.d.ts.map +1 -0
- package/dist/features/network/capture/body.js +81 -0
- package/dist/features/network/capture/body.js.map +1 -0
- package/dist/features/network/classify.d.ts +21 -0
- package/dist/features/network/classify.d.ts.map +1 -0
- package/dist/features/network/classify.js +50 -0
- package/dist/features/network/classify.js.map +1 -0
- package/dist/features/network/dedup.d.ts +36 -0
- package/dist/features/network/dedup.d.ts.map +1 -0
- package/dist/features/network/dedup.js +68 -0
- package/dist/features/network/dedup.js.map +1 -0
- package/dist/features/network/fetchInterceptor.d.ts +20 -0
- package/dist/features/network/fetchInterceptor.d.ts.map +1 -0
- package/dist/features/network/fetchInterceptor.js +158 -0
- package/dist/features/network/fetchInterceptor.js.map +1 -0
- package/dist/features/network/intercept/beacon.d.ts +14 -0
- package/dist/features/network/intercept/beacon.d.ts.map +1 -0
- package/dist/features/network/intercept/beacon.js +56 -0
- package/dist/features/network/intercept/beacon.js.map +1 -0
- package/dist/features/network/intercept/sse.d.ts +16 -0
- package/dist/features/network/intercept/sse.d.ts.map +1 -0
- package/dist/features/network/intercept/sse.js +74 -0
- package/dist/features/network/intercept/sse.js.map +1 -0
- package/dist/features/network/intercept/streams.d.ts +23 -0
- package/dist/features/network/intercept/streams.d.ts.map +1 -0
- package/dist/features/network/intercept/streams.js +25 -0
- package/dist/features/network/intercept/streams.js.map +1 -0
- package/dist/features/network/intercept/websocket.d.ts +14 -0
- package/dist/features/network/intercept/websocket.d.ts.map +1 -0
- package/dist/features/network/intercept/websocket.js +97 -0
- package/dist/features/network/intercept/websocket.js.map +1 -0
- package/dist/features/network/lazy.d.ts +23 -0
- package/dist/features/network/lazy.d.ts.map +1 -0
- package/dist/features/network/lazy.js +65 -0
- package/dist/features/network/lazy.js.map +1 -0
- package/dist/features/network/normalize.d.ts +9 -0
- package/dist/features/network/normalize.d.ts.map +1 -0
- package/dist/features/network/normalize.js +49 -0
- package/dist/features/network/normalize.js.map +1 -0
- package/dist/features/network/parse/graphql.d.ts +17 -0
- package/dist/features/network/parse/graphql.d.ts.map +1 -0
- package/dist/features/network/parse/graphql.js +106 -0
- package/dist/features/network/parse/graphql.js.map +1 -0
- package/dist/features/network/parse/url.d.ts +12 -0
- package/dist/features/network/parse/url.d.ts.map +1 -0
- package/dist/features/network/parse/url.js +52 -0
- package/dist/features/network/parse/url.js.map +1 -0
- package/dist/features/network/sampler.d.ts +21 -0
- package/dist/features/network/sampler.d.ts.map +1 -0
- package/dist/features/network/sampler.js +25 -0
- package/dist/features/network/sampler.js.map +1 -0
- package/dist/features/network/size.d.ts +21 -0
- package/dist/features/network/size.d.ts.map +1 -0
- package/dist/features/network/size.js +63 -0
- package/dist/features/network/size.js.map +1 -0
- package/dist/features/network/timing.d.ts +41 -0
- package/dist/features/network/timing.d.ts.map +1 -0
- package/dist/features/network/timing.js +134 -0
- package/dist/features/network/timing.js.map +1 -0
- package/dist/features/network/tracing.d.ts +18 -0
- package/dist/features/network/tracing.d.ts.map +1 -0
- package/dist/features/network/tracing.js +46 -0
- package/dist/features/network/tracing.js.map +1 -0
- package/dist/features/network/types.d.ts +75 -0
- package/dist/features/network/types.d.ts.map +1 -0
- package/dist/features/network/types.js +2 -0
- package/dist/features/network/types.js.map +1 -0
- package/dist/features/network/xhrInterceptor.d.ts +12 -0
- package/dist/features/network/xhrInterceptor.d.ts.map +1 -0
- package/dist/features/network/xhrInterceptor.js +108 -0
- package/dist/features/network/xhrInterceptor.js.map +1 -0
- package/dist/features/performance/PerformanceFeature.d.ts +76 -0
- package/dist/features/performance/PerformanceFeature.d.ts.map +1 -0
- package/dist/features/performance/PerformanceFeature.js +265 -0
- package/dist/features/performance/PerformanceFeature.js.map +1 -0
- package/dist/features/performance/jankTap.d.ts +23 -0
- package/dist/features/performance/jankTap.d.ts.map +1 -0
- package/dist/features/performance/jankTap.js +20 -0
- package/dist/features/performance/jankTap.js.map +1 -0
- package/dist/features/performance/longTasks.d.ts +14 -0
- package/dist/features/performance/longTasks.d.ts.map +1 -0
- package/dist/features/performance/longTasks.js +55 -0
- package/dist/features/performance/longTasks.js.map +1 -0
- package/dist/features/performance/normalize.d.ts +15 -0
- package/dist/features/performance/normalize.d.ts.map +1 -0
- package/dist/features/performance/normalize.js +30 -0
- package/dist/features/performance/normalize.js.map +1 -0
- package/dist/features/performance/resources.d.ts +19 -0
- package/dist/features/performance/resources.d.ts.map +1 -0
- package/dist/features/performance/resources.js +78 -0
- package/dist/features/performance/resources.js.map +1 -0
- package/dist/features/performance/sampler.d.ts +10 -0
- package/dist/features/performance/sampler.d.ts.map +1 -0
- package/dist/features/performance/sampler.js +23 -0
- package/dist/features/performance/sampler.js.map +1 -0
- package/dist/features/performance/spa.d.ts +2 -0
- package/dist/features/performance/spa.d.ts.map +1 -0
- package/dist/features/performance/spa.js +40 -0
- package/dist/features/performance/spa.js.map +1 -0
- package/dist/features/performance/throttle.d.ts +21 -0
- package/dist/features/performance/throttle.d.ts.map +1 -0
- package/dist/features/performance/throttle.js +26 -0
- package/dist/features/performance/throttle.js.map +1 -0
- package/dist/features/performance/trace/context.d.ts +17 -0
- package/dist/features/performance/trace/context.d.ts.map +1 -0
- package/dist/features/performance/trace/context.js +33 -0
- package/dist/features/performance/trace/context.js.map +1 -0
- package/dist/features/performance/trace/index.d.ts +7 -0
- package/dist/features/performance/trace/index.d.ts.map +1 -0
- package/dist/features/performance/trace/index.js +6 -0
- package/dist/features/performance/trace/index.js.map +1 -0
- package/dist/features/performance/trace/pageload.d.ts +3 -0
- package/dist/features/performance/trace/pageload.d.ts.map +1 -0
- package/dist/features/performance/trace/pageload.js +34 -0
- package/dist/features/performance/trace/pageload.js.map +1 -0
- package/dist/features/performance/trace/transaction.d.ts +61 -0
- package/dist/features/performance/trace/transaction.d.ts.map +1 -0
- package/dist/features/performance/trace/transaction.js +90 -0
- package/dist/features/performance/trace/transaction.js.map +1 -0
- package/dist/features/performance/trace/types.d.ts +23 -0
- package/dist/features/performance/trace/types.d.ts.map +1 -0
- package/dist/features/performance/trace/types.js +10 -0
- package/dist/features/performance/trace/types.js.map +1 -0
- package/dist/features/performance/traces.d.ts +36 -0
- package/dist/features/performance/traces.d.ts.map +1 -0
- package/dist/features/performance/traces.js +50 -0
- package/dist/features/performance/traces.js.map +1 -0
- package/dist/features/profiler/ProfilerFeature.d.ts +28 -0
- package/dist/features/profiler/ProfilerFeature.d.ts.map +1 -0
- package/dist/features/profiler/ProfilerFeature.js +82 -0
- package/dist/features/profiler/ProfilerFeature.js.map +1 -0
- package/dist/features/profiler/capture.d.ts +8 -0
- package/dist/features/profiler/capture.d.ts.map +1 -0
- package/dist/features/profiler/capture.js +21 -0
- package/dist/features/profiler/capture.js.map +1 -0
- package/dist/features/push/PushFeature.d.ts +120 -0
- package/dist/features/push/PushFeature.d.ts.map +1 -0
- package/dist/features/push/PushFeature.js +319 -0
- package/dist/features/push/PushFeature.js.map +1 -0
- package/dist/features/push/diagnostics.d.ts +55 -0
- package/dist/features/push/diagnostics.d.ts.map +1 -0
- package/dist/features/push/diagnostics.js +383 -0
- package/dist/features/push/diagnostics.js.map +1 -0
- package/dist/features/push/pushState.d.ts +58 -0
- package/dist/features/push/pushState.d.ts.map +1 -0
- package/dist/features/push/pushState.js +75 -0
- package/dist/features/push/pushState.js.map +1 -0
- package/dist/features/push/softAsk.d.ts +68 -0
- package/dist/features/push/softAsk.d.ts.map +1 -0
- package/dist/features/push/softAsk.js +141 -0
- package/dist/features/push/softAsk.js.map +1 -0
- package/dist/features/replay/ReplayFeature.d.ts +32 -0
- package/dist/features/replay/ReplayFeature.d.ts.map +1 -0
- package/dist/features/replay/ReplayFeature.js +132 -0
- package/dist/features/replay/ReplayFeature.js.map +1 -0
- package/dist/features/replay/engine/canvas.d.ts +45 -0
- package/dist/features/replay/engine/canvas.d.ts.map +1 -0
- package/dist/features/replay/engine/canvas.js +122 -0
- package/dist/features/replay/engine/canvas.js.map +1 -0
- package/dist/features/replay/engine/crossOrigin.d.ts +23 -0
- package/dist/features/replay/engine/crossOrigin.d.ts.map +1 -0
- package/dist/features/replay/engine/crossOrigin.js +108 -0
- package/dist/features/replay/engine/crossOrigin.js.map +1 -0
- package/dist/features/replay/engine/cssom.d.ts +31 -0
- package/dist/features/replay/engine/cssom.d.ts.map +1 -0
- package/dist/features/replay/engine/cssom.js +128 -0
- package/dist/features/replay/engine/cssom.js.map +1 -0
- package/dist/features/replay/engine/iframe.d.ts +65 -0
- package/dist/features/replay/engine/iframe.d.ts.map +1 -0
- package/dist/features/replay/engine/iframe.js +186 -0
- package/dist/features/replay/engine/iframe.js.map +1 -0
- package/dist/features/replay/engine/interactions.d.ts +142 -0
- package/dist/features/replay/engine/interactions.d.ts.map +1 -0
- package/dist/features/replay/engine/interactions.js +371 -0
- package/dist/features/replay/engine/interactions.js.map +1 -0
- package/dist/features/replay/engine/mutations.d.ts +49 -0
- package/dist/features/replay/engine/mutations.d.ts.map +1 -0
- package/dist/features/replay/engine/mutations.js +261 -0
- package/dist/features/replay/engine/mutations.js.map +1 -0
- package/dist/features/replay/engine/nodeRegistry.d.ts +23 -0
- package/dist/features/replay/engine/nodeRegistry.d.ts.map +1 -0
- package/dist/features/replay/engine/nodeRegistry.js +51 -0
- package/dist/features/replay/engine/nodeRegistry.js.map +1 -0
- package/dist/features/replay/engine/player.d.ts +11 -0
- package/dist/features/replay/engine/player.d.ts.map +1 -0
- package/dist/features/replay/engine/player.js +284 -0
- package/dist/features/replay/engine/player.js.map +1 -0
- package/dist/features/replay/engine/rebuild.d.ts +8 -0
- package/dist/features/replay/engine/rebuild.d.ts.map +1 -0
- package/dist/features/replay/engine/rebuild.js +46 -0
- package/dist/features/replay/engine/rebuild.js.map +1 -0
- package/dist/features/replay/engine/replayWorker.d.ts +33 -0
- package/dist/features/replay/engine/replayWorker.d.ts.map +1 -0
- package/dist/features/replay/engine/replayWorker.js +175 -0
- package/dist/features/replay/engine/replayWorker.js.map +1 -0
- package/dist/features/replay/engine/resources.d.ts +52 -0
- package/dist/features/replay/engine/resources.d.ts.map +1 -0
- package/dist/features/replay/engine/resources.js +132 -0
- package/dist/features/replay/engine/resources.js.map +1 -0
- package/dist/features/replay/engine/snapshot.d.ts +103 -0
- package/dist/features/replay/engine/snapshot.d.ts.map +1 -0
- package/dist/features/replay/engine/snapshot.js +409 -0
- package/dist/features/replay/engine/snapshot.js.map +1 -0
- package/dist/features/replay/engine/traverse.d.ts +19 -0
- package/dist/features/replay/engine/traverse.d.ts.map +1 -0
- package/dist/features/replay/engine/traverse.js +39 -0
- package/dist/features/replay/engine/traverse.js.map +1 -0
- package/dist/features/replay/engine/types.d.ts +137 -0
- package/dist/features/replay/engine/types.d.ts.map +1 -0
- package/dist/features/replay/engine/types.js +6 -0
- package/dist/features/replay/engine/types.js.map +1 -0
- package/dist/features/replay/engine/webglPatch.d.ts +26 -0
- package/dist/features/replay/engine/webglPatch.d.ts.map +1 -0
- package/dist/features/replay/engine/webglPatch.js +83 -0
- package/dist/features/replay/engine/webglPatch.js.map +1 -0
- package/dist/features/replay/lifecycle/adaptive.d.ts +38 -0
- package/dist/features/replay/lifecycle/adaptive.d.ts.map +1 -0
- package/dist/features/replay/lifecycle/adaptive.js +90 -0
- package/dist/features/replay/lifecycle/adaptive.js.map +1 -0
- package/dist/features/replay/lifecycle/cadence.d.ts +20 -0
- package/dist/features/replay/lifecycle/cadence.d.ts.map +1 -0
- package/dist/features/replay/lifecycle/cadence.js +62 -0
- package/dist/features/replay/lifecycle/cadence.js.map +1 -0
- package/dist/features/replay/lifecycle/deviceSignals.d.ts +35 -0
- package/dist/features/replay/lifecycle/deviceSignals.d.ts.map +1 -0
- package/dist/features/replay/lifecycle/deviceSignals.js +61 -0
- package/dist/features/replay/lifecycle/deviceSignals.js.map +1 -0
- package/dist/features/replay/lifecycle/pii.d.ts +14 -0
- package/dist/features/replay/lifecycle/pii.d.ts.map +1 -0
- package/dist/features/replay/lifecycle/pii.js +52 -0
- package/dist/features/replay/lifecycle/pii.js.map +1 -0
- package/dist/features/replay/lifecycle/recorder.d.ts +129 -0
- package/dist/features/replay/lifecycle/recorder.d.ts.map +1 -0
- package/dist/features/replay/lifecycle/recorder.js +509 -0
- package/dist/features/replay/lifecycle/recorder.js.map +1 -0
- package/dist/features/replay/lifecycle/sampling.d.ts +28 -0
- package/dist/features/replay/lifecycle/sampling.d.ts.map +1 -0
- package/dist/features/replay/lifecycle/sampling.js +31 -0
- package/dist/features/replay/lifecycle/sampling.js.map +1 -0
- package/dist/features/replay/lifecycle/segmentBuffer.d.ts +75 -0
- package/dist/features/replay/lifecycle/segmentBuffer.d.ts.map +1 -0
- package/dist/features/replay/lifecycle/segmentBuffer.js +130 -0
- package/dist/features/replay/lifecycle/segmentBuffer.js.map +1 -0
- package/dist/features/replay/lifecycle/viewContext.d.ts +7 -0
- package/dist/features/replay/lifecycle/viewContext.d.ts.map +1 -0
- package/dist/features/replay/lifecycle/viewContext.js +51 -0
- package/dist/features/replay/lifecycle/viewContext.js.map +1 -0
- package/dist/features/scroll/index.d.ts +31 -0
- package/dist/features/scroll/index.d.ts.map +1 -0
- package/dist/features/scroll/index.js +102 -0
- package/dist/features/scroll/index.js.map +1 -0
- package/dist/features/session/sessionManager.d.ts +25 -0
- package/dist/features/session/sessionManager.d.ts.map +1 -0
- package/dist/features/session/sessionManager.js +36 -0
- package/dist/features/session/sessionManager.js.map +1 -0
- package/dist/features/session/sessionStore.d.ts +106 -0
- package/dist/features/session/sessionStore.d.ts.map +1 -0
- package/dist/features/session/sessionStore.js +265 -0
- package/dist/features/session/sessionStore.js.map +1 -0
- package/dist/features/watchdog/WatchdogFeature.d.ts +23 -0
- package/dist/features/watchdog/WatchdogFeature.d.ts.map +1 -0
- package/dist/features/watchdog/WatchdogFeature.js +29 -0
- package/dist/features/watchdog/WatchdogFeature.js.map +1 -0
- package/dist/features/watchdog/collectors.d.ts +18 -0
- package/dist/features/watchdog/collectors.d.ts.map +1 -0
- package/dist/features/watchdog/collectors.js +107 -0
- package/dist/features/watchdog/collectors.js.map +1 -0
- package/dist/features/watchdog/config.d.ts +51 -0
- package/dist/features/watchdog/config.d.ts.map +1 -0
- package/dist/features/watchdog/config.js +28 -0
- package/dist/features/watchdog/config.js.map +1 -0
- package/dist/features/watchdog/engine.d.ts +22 -0
- package/dist/features/watchdog/engine.d.ts.map +1 -0
- package/dist/features/watchdog/engine.js +123 -0
- package/dist/features/watchdog/engine.js.map +1 -0
- package/dist/features/watchdog/incidents.d.ts +79 -0
- package/dist/features/watchdog/incidents.d.ts.map +1 -0
- package/dist/features/watchdog/incidents.js +204 -0
- package/dist/features/watchdog/incidents.js.map +1 -0
- package/dist/features/watchdog/rollup.d.ts +41 -0
- package/dist/features/watchdog/rollup.d.ts.map +1 -0
- package/dist/features/watchdog/rollup.js +76 -0
- package/dist/features/watchdog/rollup.js.map +1 -0
- package/dist/features/webVitals/WebVitalsFeature.d.ts +46 -0
- package/dist/features/webVitals/WebVitalsFeature.d.ts.map +1 -0
- package/dist/features/webVitals/WebVitalsFeature.js +252 -0
- package/dist/features/webVitals/WebVitalsFeature.js.map +1 -0
- package/dist/features/webVitals/attribution.d.ts +50 -0
- package/dist/features/webVitals/attribution.d.ts.map +1 -0
- package/dist/features/webVitals/attribution.js +186 -0
- package/dist/features/webVitals/attribution.js.map +1 -0
- package/dist/features/webVitals/observe.d.ts +6 -0
- package/dist/features/webVitals/observe.d.ts.map +1 -0
- package/dist/features/webVitals/observe.js +6 -0
- package/dist/features/webVitals/observe.js.map +1 -0
- package/dist/features/webVitals/vitals.d.ts +99 -0
- package/dist/features/webVitals/vitals.d.ts.map +1 -0
- package/dist/features/webVitals/vitals.js +166 -0
- package/dist/features/webVitals/vitals.js.map +1 -0
- package/dist/features/webperf/WebPerfFeature.d.ts +19 -0
- package/dist/features/webperf/WebPerfFeature.d.ts.map +1 -0
- package/dist/features/webperf/WebPerfFeature.js +48 -0
- package/dist/features/webperf/WebPerfFeature.js.map +1 -0
- package/dist/features/webperf/collectors.d.ts +3 -0
- package/dist/features/webperf/collectors.d.ts.map +1 -0
- package/dist/features/webperf/collectors.js +118 -0
- package/dist/features/webperf/collectors.js.map +1 -0
- package/dist/features/webperf/math.d.ts +12 -0
- package/dist/features/webperf/math.d.ts.map +1 -0
- package/dist/features/webperf/math.js +26 -0
- package/dist/features/webperf/math.js.map +1 -0
- package/dist/inapp.d.ts +6 -0
- package/dist/inapp.d.ts.map +1 -0
- package/dist/inapp.js +6 -0
- package/dist/inapp.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/index.d.ts +7 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +2 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/pipeline/index.d.ts +3 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +3 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/pipeline.d.ts +84 -0
- package/dist/pipeline/pipeline.d.ts.map +1 -0
- package/dist/pipeline/pipeline.js +284 -0
- package/dist/pipeline/pipeline.js.map +1 -0
- package/dist/public/ScaleBunFacade.d.ts +382 -0
- package/dist/public/ScaleBunFacade.d.ts.map +1 -0
- package/dist/public/ScaleBunFacade.js +787 -0
- package/dist/public/ScaleBunFacade.js.map +1 -0
- package/dist/public/index.d.ts +5 -0
- package/dist/public/index.d.ts.map +1 -0
- package/dist/public/index.js +4 -0
- package/dist/public/index.js.map +1 -0
- package/dist/public/typedTracker.d.ts +91 -0
- package/dist/public/typedTracker.d.ts.map +1 -0
- package/dist/public/typedTracker.js +60 -0
- package/dist/public/typedTracker.js.map +1 -0
- package/dist/scalebun-push-sw.js +236 -0
- package/dist/scalebun.min.js +635 -0
- package/dist/scalebun.min.js.map +7 -0
- package/dist/storage/idb.d.ts +16 -0
- package/dist/storage/idb.d.ts.map +1 -0
- package/dist/storage/idb.js +76 -0
- package/dist/storage/idb.js.map +1 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +3 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/transport/gzip.d.ts +2 -0
- package/dist/transport/gzip.d.ts.map +1 -0
- package/dist/transport/gzip.js +20 -0
- package/dist/transport/gzip.js.map +1 -0
- package/dist/transport/httpClient.d.ts +60 -0
- package/dist/transport/httpClient.d.ts.map +1 -0
- package/dist/transport/httpClient.js +154 -0
- package/dist/transport/httpClient.js.map +1 -0
- package/dist/transport/index.d.ts +3 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +3 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/sign.d.ts +25 -0
- package/dist/transport/sign.d.ts.map +1 -0
- package/dist/transport/sign.js +58 -0
- package/dist/transport/sign.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,1082 @@
|
|
|
1
|
+
import { readableOn, sanitizeTheme } from './theme';
|
|
2
|
+
import { makeGameResolver } from './gameResolver';
|
|
3
|
+
import { engageSlots, hasInAppSlot, slotNameFor } from './inappSlots';
|
|
4
|
+
import { inAppGameActionFor } from './gameLogic';
|
|
5
|
+
const rec = (v) => (v && typeof v === 'object' && !Array.isArray(v) ? v : {});
|
|
6
|
+
const str = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
|
|
7
|
+
const num = (v, d) => (typeof v === 'number' && Number.isFinite(v) ? v : d);
|
|
8
|
+
/**
|
|
9
|
+
* The display text of an authored row, whatever the author called the field.
|
|
10
|
+
*
|
|
11
|
+
* This read `label` and only `label`, while the registry authors carousel slides and products as
|
|
12
|
+
* `{ title: 'Cloud Sneakers' }` — so every slide and every product card shipped with an empty
|
|
13
|
+
* caption. The authoring preview has always read `label ?? title ?? text ?? name`, so the two sides
|
|
14
|
+
* disagreed about the content while agreeing about the block, which is exactly the gap no parity
|
|
15
|
+
* check on block KINDS can see. Widened to match the preview.
|
|
16
|
+
*/
|
|
17
|
+
const labelOf = (x) => {
|
|
18
|
+
if (typeof x === 'string')
|
|
19
|
+
return x;
|
|
20
|
+
const o = rec(x);
|
|
21
|
+
return str(o.label) ?? str(o.title) ?? str(o.text) ?? str(o.name) ?? '';
|
|
22
|
+
};
|
|
23
|
+
const listOf = (ext, keys) => {
|
|
24
|
+
for (const k of keys)
|
|
25
|
+
if (Array.isArray(ext[k]))
|
|
26
|
+
return ext[k];
|
|
27
|
+
return [];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Archetypes this bridge can actually build a mechanic for. Anything else — including a served
|
|
31
|
+
* archetype from a newer registry than this SDK — degrades to the widget and is REPORTED.
|
|
32
|
+
* Kept as data so the check is one lookup rather than a switch that silently returns [].
|
|
33
|
+
*/
|
|
34
|
+
const RENDERABLE_ARCHETYPES = new Set([
|
|
35
|
+
'spinWheel', 'scratchReveal', 'slotReward', 'carouselDeck', 'countdown',
|
|
36
|
+
'questionFlow', 'checklistProgress', 'qrNfc', 'videoCommerce', 'celebration',
|
|
37
|
+
// R1 — additive layout archetypes. The legacy widget draws seven fixed layouts and has neither a
|
|
38
|
+
// side-docked panel nor a wizard, so both belong on the rich path even though they are containers
|
|
39
|
+
// rather than mechanics.
|
|
40
|
+
'multiStepSheet', 'sideSheet',
|
|
41
|
+
]);
|
|
42
|
+
/**
|
|
43
|
+
* Archetypes that dictate their own SURFACE, overriding the one derived from `m.layout`.
|
|
44
|
+
*
|
|
45
|
+
* Both come straight from the registry's own layout defaults: `sideSheet` is
|
|
46
|
+
* `position:'right', slide_in_right`, and multiStepSheet "keeps the bottom-sheet defaults … it IS a
|
|
47
|
+
* bottom sheet, just wizard-paged". Neither needed a new surface — `slideover` already docks to an
|
|
48
|
+
* edge; it simply had no bottom placement until R1 added one.
|
|
49
|
+
*/
|
|
50
|
+
const ARCHETYPE_SURFACE = {
|
|
51
|
+
sideSheet: { surface: 'slideover', surfaceOptions: { placement: 'right' } },
|
|
52
|
+
multiStepSheet: { surface: 'slideover', surfaceOptions: { placement: 'bottom' } },
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* LEGACY FALLBACK — superseded by the served `spec.ext.archetype`.
|
|
56
|
+
*
|
|
57
|
+
* This map covered 29 of the registry's 100 variants while the dashboard preview resolved
|
|
58
|
+
* `archetype` from the registry itself and covered all 100 — so the two had drifted by 71 keys and
|
|
59
|
+
* an author could preview a distinct mechanic while the SDK shipped a plain modal. The registry
|
|
60
|
+
* states the intended design outright: "`archetype` is DATA so the SDK resolves
|
|
61
|
+
* ARCHETYPES[def.archetype]". The SDK cannot ship the 55 KB registry against a ~570 B core budget,
|
|
62
|
+
* so the backend now resolves it and serves it on `ext`.
|
|
63
|
+
*
|
|
64
|
+
* Retained ONLY for payloads served before that shipped; it is not extended. Adding a key here
|
|
65
|
+
* would re-open the drift this exists to close — the fix for a missing mechanic is the registry,
|
|
66
|
+
* which the backend already reads.
|
|
67
|
+
*/
|
|
68
|
+
const KEY_TO_ARCHETYPE = {
|
|
69
|
+
spin_wheel: 'spinWheel',
|
|
70
|
+
scratch_card: 'scratchReveal', mystery_box: 'scratchReveal',
|
|
71
|
+
slot_reward: 'slotReward',
|
|
72
|
+
carousel_story: 'carouselDeck', swipe_deck: 'carouselDeck',
|
|
73
|
+
countdown_offer: 'countdown',
|
|
74
|
+
poll_card: 'questionFlow', survey_sheet: 'questionFlow', nps_prompt: 'questionFlow',
|
|
75
|
+
quiz_card: 'questionFlow', product_finder: 'questionFlow', preferences_picker: 'questionFlow',
|
|
76
|
+
feedback_capture: 'questionFlow', emoji_reaction_bar: 'questionFlow', rating_request: 'questionFlow',
|
|
77
|
+
progress_unlock: 'checklistProgress', streak_reward: 'checklistProgress', daily_check_in: 'checklistProgress',
|
|
78
|
+
goal_tracker: 'checklistProgress', interactive_checklist: 'checklistProgress', guided_setup_wizard: 'checklistProgress',
|
|
79
|
+
first_session_onboarding: 'checklistProgress', community_challenge: 'checklistProgress',
|
|
80
|
+
milestone_celebration: 'celebration', celebration_confetti_full_screen: 'celebration',
|
|
81
|
+
nfc_qr_prompt: 'qrNfc', wallet_pass_offer: 'qrNfc',
|
|
82
|
+
video_commerce_card: 'videoCommerce',
|
|
83
|
+
};
|
|
84
|
+
let onDegrade = null;
|
|
85
|
+
/**
|
|
86
|
+
* Observe rich-render fall-throughs.
|
|
87
|
+
*
|
|
88
|
+
* C4 requires that an unmapped variantKey "degrades to the widget AND reports it". Previously it
|
|
89
|
+
* degraded in total silence, which is indistinguishable from working — the same failure mode as a
|
|
90
|
+
* wheel that always lands on segment 0.
|
|
91
|
+
*/
|
|
92
|
+
export function onRichDegrade(fn) {
|
|
93
|
+
onDegrade = fn;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The host's gamified-outcome handler, supplied via `engageOptions.onInAppGameRequest`.
|
|
97
|
+
*
|
|
98
|
+
* Module-level rather than threaded through every call, mirroring `onRichDegrade` above: the
|
|
99
|
+
* bootstrap sets it once from config and the render path reads it. Absent handler → the eight game
|
|
100
|
+
* variants render their unavailable state, never a fabricated prize.
|
|
101
|
+
*/
|
|
102
|
+
let gameHandlerRef = null;
|
|
103
|
+
export function setInAppGameHandler(fn) {
|
|
104
|
+
gameHandlerRef = fn;
|
|
105
|
+
}
|
|
106
|
+
function report(d) {
|
|
107
|
+
try {
|
|
108
|
+
onDegrade?.(d);
|
|
109
|
+
}
|
|
110
|
+
catch { /* an observer must never break rendering */ }
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Resolve the render archetype for a message.
|
|
114
|
+
*
|
|
115
|
+
* Order is deliberate: the SERVED archetype wins, because the backend resolved it from the
|
|
116
|
+
* canonical registry — the single source the dashboard preview also reads. The local map is only
|
|
117
|
+
* consulted for payloads served before the backend started stamping it.
|
|
118
|
+
*/
|
|
119
|
+
export function richArchetype(variantKey, servedArchetype) {
|
|
120
|
+
const served = typeof servedArchetype === 'string' && servedArchetype ? servedArchetype : null;
|
|
121
|
+
if (served)
|
|
122
|
+
return RENDERABLE_ARCHETYPES.has(served) ? served : null;
|
|
123
|
+
return (variantKey && KEY_TO_ARCHETYPE[variantKey]) || null;
|
|
124
|
+
}
|
|
125
|
+
/** The archetype the config served for this message, if any. */
|
|
126
|
+
function servedArchetypeOf(spec) {
|
|
127
|
+
const v = spec?.ext?.['archetype'];
|
|
128
|
+
return typeof v === 'string' && v ? v : undefined;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Does this engage message use a rich mechanic variant the basic widget can't render?
|
|
132
|
+
*
|
|
133
|
+
* Reports the two distinct fall-through reasons instead of returning a bare false: a CONTAINER
|
|
134
|
+
* archetype (modal/banner/…) legitimately belongs to the widget, whereas a mechanic archetype this
|
|
135
|
+
* SDK doesn't know is a version gap the host should be able to see.
|
|
136
|
+
*/
|
|
137
|
+
export function isRichInApp(m, resolvedSpec) {
|
|
138
|
+
// Defaults to the base spec, but callers that have already run A/B resolution MUST pass the
|
|
139
|
+
// resolved one: variant B carries its own `ext`, so deciding from the base spec here and building
|
|
140
|
+
// from the resolved spec later can pick two different archetypes for the same render.
|
|
141
|
+
const served = servedArchetypeOf(resolvedSpec ?? m.spec);
|
|
142
|
+
const arch = richArchetype(m.variantKey, served);
|
|
143
|
+
if (arch)
|
|
144
|
+
return true;
|
|
145
|
+
if (served) {
|
|
146
|
+
// Only a MECHANIC archetype we can't build is worth reporting; containers are the widget's job.
|
|
147
|
+
if (!CONTAINER_ARCHETYPES.has(served)) {
|
|
148
|
+
report({ variantKey: m.variantKey, reason: 'unrenderable', archetype: served });
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
if (m.variantKey)
|
|
153
|
+
report({ variantKey: m.variantKey, reason: 'unmapped' });
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Archetypes the legacy widget renders correctly — a fall-through here is expected, not a gap.
|
|
158
|
+
* `multiStepSheet`/`sideSheet` are deliberately NOT listed: the widget has no wizard and no
|
|
159
|
+
* edge-docked panel, so they take the rich path (see ARCHETYPE_SURFACE).
|
|
160
|
+
*/
|
|
161
|
+
const CONTAINER_ARCHETYPES = new Set([
|
|
162
|
+
'modal', 'sheet', 'bannerToast', 'fullscreen', 'anchored', 'inline',
|
|
163
|
+
]);
|
|
164
|
+
/**
|
|
165
|
+
* MOUNT MODEL → surface. The registry's own answer to "where does this attach?", served on `ext`.
|
|
166
|
+
*
|
|
167
|
+
* `LAYOUT_SURFACE` below maps the LEGACY layout — a seven-value mobile enum with no way to say
|
|
168
|
+
* "anchored to an element" or "inline in the document", so those variants fell through to a modal or
|
|
169
|
+
* a corner toast. Measured across all 100: **10 mounted on the wrong surface**. An Inline Card meant
|
|
170
|
+
* for a feed opened as a centred modal with a backdrop; a tooltip anchored to a button appeared
|
|
171
|
+
* bottom-right. The authoring preview mounts by mount model, so author and visitor saw different
|
|
172
|
+
* placements while every block-level gate stayed green.
|
|
173
|
+
*
|
|
174
|
+
* `inline` is deliberately ABSENT — see `mountSurfaceFor`.
|
|
175
|
+
*/
|
|
176
|
+
const MOUNT_SURFACE = {
|
|
177
|
+
overlay: { surface: 'modal', surfaceOptions: { placement: 'center', size: 'md', backdrop: true } },
|
|
178
|
+
sheet: { surface: 'slideover', surfaceOptions: { placement: 'right', resizable: true } },
|
|
179
|
+
banner: { surface: 'banner', surfaceOptions: { placement: 'top' } },
|
|
180
|
+
fullscreen: { surface: 'takeover' },
|
|
181
|
+
toast: { surface: 'toast', surfaceOptions: { placement: 'bottom-right' } },
|
|
182
|
+
bubble: { surface: 'toast', surfaceOptions: { placement: 'bottom-right' } },
|
|
183
|
+
anchored: { surface: 'popover', surfaceOptions: { placement: 'bottom', maxWidth: 320 } },
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* Resolve a served mount model, or null to keep the legacy mapping.
|
|
187
|
+
*
|
|
188
|
+
* INLINE IS NOT MAPPED, on purpose. The inline surface renders into a host-registered slot and
|
|
189
|
+
* `renderVariant` returns `inert()` when no `SlotRegistry` is supplied — and this bridge does not
|
|
190
|
+
* supply one. Mapping it "correctly" would turn four variants (inline_card, embedded_panel,
|
|
191
|
+
* empty_state_prompt, smart_inbox_message) from a WRONG surface into NO surface, which is a worse
|
|
192
|
+
* failure: a modal in the wrong place is at least visible and reportable. Closing it properly means
|
|
193
|
+
* threading a slot registry through this path and having the host register a mount point, which
|
|
194
|
+
* changes what an existing campaign does — a product decision, not a mapping fix. Until then these
|
|
195
|
+
* four keep the legacy modal and the divergence is recorded in the surface-parity gate rather than
|
|
196
|
+
* being silently "fixed" into invisibility.
|
|
197
|
+
*/
|
|
198
|
+
function mountSurfaceFor(ext) {
|
|
199
|
+
const mount = str(ext.mountModel);
|
|
200
|
+
if (!mount)
|
|
201
|
+
return null;
|
|
202
|
+
/**
|
|
203
|
+
* `inline` is placement-conditional, not unconditional.
|
|
204
|
+
*
|
|
205
|
+
* The inline surface renders into a HOST-REGISTERED slot and goes inert without one, so mapping it
|
|
206
|
+
* blindly would turn four variants from a wrong surface into no surface — invisible rather than
|
|
207
|
+
* misplaced. It is chosen only when the page actually has the slot this campaign names; otherwise
|
|
208
|
+
* the legacy modal stands and the fall-through is reported, so "my inline card opens as a popup"
|
|
209
|
+
* has an answer instead of being a mystery.
|
|
210
|
+
*/
|
|
211
|
+
if (mount === 'inline') {
|
|
212
|
+
const name = slotNameFor(ext);
|
|
213
|
+
if (!name || !hasInAppSlot(ext)) {
|
|
214
|
+
report({ reason: 'unrenderable', archetype: 'inline' });
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
return { surface: 'inline', surfaceOptions: { slot: name } };
|
|
218
|
+
}
|
|
219
|
+
return MOUNT_SURFACE[mount] ?? null;
|
|
220
|
+
}
|
|
221
|
+
const LAYOUT_SURFACE = {
|
|
222
|
+
modal: { surface: 'modal', surfaceOptions: { placement: 'center', size: 'md', backdrop: true } },
|
|
223
|
+
fullscreen: { surface: 'takeover' },
|
|
224
|
+
bottom_sheet: { surface: 'slideover', surfaceOptions: { placement: 'bottom' } },
|
|
225
|
+
top_banner: { surface: 'banner', surfaceOptions: { placement: 'top' } },
|
|
226
|
+
bottom_banner: { surface: 'banner', surfaceOptions: { placement: 'bottom' } },
|
|
227
|
+
tooltip: { surface: 'toast', surfaceOptions: { placement: 'bottom-right' } },
|
|
228
|
+
toast: { surface: 'toast', surfaceOptions: { placement: 'bottom-right' } },
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* `variantKey` is passed alongside the archetype because the registry maps several DISTINCT
|
|
232
|
+
* variants onto one archetype (mystery_box and scratch_card both resolve to `scratchReveal`). The
|
|
233
|
+
* archetype picks the mechanic; the key selects the presentation within it.
|
|
234
|
+
*/
|
|
235
|
+
/**
|
|
236
|
+
* Progress as a PERCENTAGE, from authoring that writes a fraction.
|
|
237
|
+
*
|
|
238
|
+
* Every authored example in the registry writes `progress: 0.8` meaning 80%, and the progress block
|
|
239
|
+
* clamps to 0–100 — so 0.8 rendered a bar that was 0.8% full. Visually that is an empty bar, which
|
|
240
|
+
* is indistinguishable from "no data", so the bug read as a missing value rather than a wrong one.
|
|
241
|
+
*
|
|
242
|
+
* 0–1 is treated as a fraction. That makes a literal 1% unauthorable through this path, which is the
|
|
243
|
+
* right trade: no example authors 1%, every example authors fractions, and the alternative silently
|
|
244
|
+
* blanks the common case.
|
|
245
|
+
*/
|
|
246
|
+
const pctOf = (raw, fallback) => {
|
|
247
|
+
const n = Number(raw);
|
|
248
|
+
if (!Number.isFinite(n))
|
|
249
|
+
return fallback;
|
|
250
|
+
return n > 0 && n <= 1 ? n * 100 : n;
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* An absolute deadline from either an ISO timestamp or an authored DURATION.
|
|
254
|
+
*
|
|
255
|
+
* `countdown_offer` requires `expiryTime` and its example authors `'02:45:18'` — hours:minutes:seconds
|
|
256
|
+
* remaining, not a date. The countdown block takes an absolute instant, so a duration has to be
|
|
257
|
+
* resolved against now or the block ships with `to: undefined` and renders nothing.
|
|
258
|
+
*/
|
|
259
|
+
/**
|
|
260
|
+
* Which wheel segment the SERVER decided, resolved without a shred of client randomness.
|
|
261
|
+
*
|
|
262
|
+
* The outcome is server-authoritative everywhere in this system, and the bridge simply never read
|
|
263
|
+
* it — so a served result was discarded and the block's `|| 0` default meant every visitor won
|
|
264
|
+
* segment 0. Precedence mirrors the authoring preview's `resolveWheelPreviewWinner` exactly, so a
|
|
265
|
+
* campaign that previews a win on segment 3 ships a win on segment 3:
|
|
266
|
+
*
|
|
267
|
+
* numeric index → segment/outcome id → result label → segment 0
|
|
268
|
+
*
|
|
269
|
+
* Landing on 0 stays the final fallback rather than picking randomly: a client that chooses its own
|
|
270
|
+
* prize is a client that can be made to choose again.
|
|
271
|
+
*/
|
|
272
|
+
const resolveWinningIndex = (segments, ext) => {
|
|
273
|
+
if (!segments.length)
|
|
274
|
+
return 0;
|
|
275
|
+
for (const key of ['resultIndex', 'winningIndex']) {
|
|
276
|
+
const n = Number(ext[key]);
|
|
277
|
+
if (Number.isInteger(n) && n >= 0 && n < segments.length)
|
|
278
|
+
return n;
|
|
279
|
+
}
|
|
280
|
+
const idOf = (v) => {
|
|
281
|
+
const o = rec(v);
|
|
282
|
+
return str(o.id) ?? str(o.segmentId) ?? str(o.key) ?? str(o.value);
|
|
283
|
+
};
|
|
284
|
+
const wantedId = str(ext.segmentId ?? ext.winningId ?? ext.resultId ?? ext.outcomeId);
|
|
285
|
+
if (wantedId) {
|
|
286
|
+
const i = segments.findIndex((s) => idOf(s) === wantedId);
|
|
287
|
+
if (i >= 0)
|
|
288
|
+
return i;
|
|
289
|
+
}
|
|
290
|
+
const wantedLabel = str(ext.resultState ?? ext.rewardValue ?? ext.prize ?? ext.rewardResult ?? ext.resultReward);
|
|
291
|
+
if (wantedLabel) {
|
|
292
|
+
const target = wantedLabel.trim().toLowerCase();
|
|
293
|
+
const i = segments.findIndex((s) => labelOf(s).trim().toLowerCase() === target);
|
|
294
|
+
if (i >= 0)
|
|
295
|
+
return i;
|
|
296
|
+
}
|
|
297
|
+
return 0;
|
|
298
|
+
};
|
|
299
|
+
const countdownProps = (ext) => {
|
|
300
|
+
const target = deadlineFrom(ext);
|
|
301
|
+
if (target)
|
|
302
|
+
return { target };
|
|
303
|
+
const hrs = Number(ext.durationHours ?? ext.hours);
|
|
304
|
+
return { durationMs: (Number.isFinite(hrs) && hrs > 0 ? hrs : 24) * 3600000 };
|
|
305
|
+
};
|
|
306
|
+
const deadlineFrom = (ext) => {
|
|
307
|
+
const absolute = str(ext.endsAt) ?? str(ext.deadline) ?? str(ext.to) ?? str(ext.endAt);
|
|
308
|
+
if (absolute)
|
|
309
|
+
return absolute;
|
|
310
|
+
const raw = str(ext.expiryTime) ?? str(ext.expiresAt);
|
|
311
|
+
if (!raw)
|
|
312
|
+
return undefined;
|
|
313
|
+
// An ISO-ish string parses directly; only a bare hh:mm:ss / mm:ss falls through to the duration path.
|
|
314
|
+
const parsed = Date.parse(raw);
|
|
315
|
+
if (Number.isFinite(parsed))
|
|
316
|
+
return new Date(parsed).toISOString();
|
|
317
|
+
const parts = raw.split(':').map((p) => Number(p));
|
|
318
|
+
if (!parts.length || parts.some((p) => !Number.isFinite(p)))
|
|
319
|
+
return undefined;
|
|
320
|
+
const [h = 0, m = 0, s = 0] = parts.length === 3 ? parts : [0, ...parts];
|
|
321
|
+
const ms = ((h * 60 + m) * 60 + s) * 1000;
|
|
322
|
+
return ms > 0 ? new Date(Date.now() + ms).toISOString() : undefined;
|
|
323
|
+
};
|
|
324
|
+
function mechanicBlocks(arch, ext, title, variantKey, body) {
|
|
325
|
+
switch (arch) {
|
|
326
|
+
case 'spinWheel': {
|
|
327
|
+
const rawSegments = listOf(ext, ['segments', 'prizes', 'rewards']);
|
|
328
|
+
return [{
|
|
329
|
+
kind: 'spinwheel',
|
|
330
|
+
props: {
|
|
331
|
+
segments: rawSegments.map(labelOf).filter(Boolean),
|
|
332
|
+
// Honour a SERVED outcome. Without this the block's own `|| 0` default applied and every
|
|
333
|
+
// visitor landed on segment 0 even when the server had already decided otherwise.
|
|
334
|
+
resultIndex: resolveWinningIndex(rawSegments, ext),
|
|
335
|
+
},
|
|
336
|
+
}];
|
|
337
|
+
}
|
|
338
|
+
case 'scratchReveal':
|
|
339
|
+
/**
|
|
340
|
+
* `scratch_card` and `mystery_box` share this archetype but are NOT the same thing.
|
|
341
|
+
*
|
|
342
|
+
* The registry declares distinct renderers (ScratchCardRenderer / MysteryBoxRenderer) and then
|
|
343
|
+
* collapses both onto `scratchReveal`, so the SDK shipped a scratch card for both — a mystery
|
|
344
|
+
* box that you scratch. They share an outcome MODEL (reveal a server-provided prize), not a
|
|
345
|
+
* presentation, so the difference rides a prop rather than a second archetype (which would be
|
|
346
|
+
* a registry change, and the registry is the frozen contract).
|
|
347
|
+
*/
|
|
348
|
+
return [{
|
|
349
|
+
kind: 'scratch',
|
|
350
|
+
props: {
|
|
351
|
+
// The form names the prize differently per variant — scratch_card writes `rewardValue`
|
|
352
|
+
// or `rewardResult`, mystery_box writes `rewardResult`. Reading only `prize` meant the
|
|
353
|
+
// authored reward was replaced by the generic "You won!".
|
|
354
|
+
prize: str(ext.prize ?? ext.reward ?? ext.rewardValue ?? ext.rewardResult ?? ext.resultReward ?? ext.coupon)
|
|
355
|
+
?? 'You won!',
|
|
356
|
+
reveal: variantKey === 'mystery_box' ? 'box' : 'scratch',
|
|
357
|
+
},
|
|
358
|
+
}];
|
|
359
|
+
case 'slotReward': {
|
|
360
|
+
// `result` is the 3-symbol combo the server decided; the block spins to it. Unread, the reels
|
|
361
|
+
// fell back to their own default and the outcome the backend chose never showed.
|
|
362
|
+
const result = listOf(ext, ['resultSymbols', 'result', 'winningSymbols']).map(labelOf).filter(Boolean);
|
|
363
|
+
return [{
|
|
364
|
+
kind: 'slot',
|
|
365
|
+
props: {
|
|
366
|
+
symbols: listOf(ext, ['symbols', 'reels', 'slotItems']).map(labelOf).filter(Boolean),
|
|
367
|
+
...(result.length ? { result: result.slice(0, 3) } : {}),
|
|
368
|
+
},
|
|
369
|
+
}];
|
|
370
|
+
}
|
|
371
|
+
case 'countdown':
|
|
372
|
+
/**
|
|
373
|
+
* The block reads `target` (ISO or epoch ms) or `durationMs`. The bridge emitted `to`, which
|
|
374
|
+
* the renderer never reads — so every countdown campaign shipped a timer with no deadline. The
|
|
375
|
+
* kind was right, the prop name was not, and nothing in the type system or the parity gate
|
|
376
|
+
* could see it because both sides agreed on the KIND.
|
|
377
|
+
*
|
|
378
|
+
* `durationMs` is the honest fallback when no deadline was authored: a countdown with no end
|
|
379
|
+
* is not a countdown, and 24h is what the authoring preview has always shown.
|
|
380
|
+
*/
|
|
381
|
+
return [{ kind: 'countdown', props: countdownProps(ext) }];
|
|
382
|
+
case 'celebration':
|
|
383
|
+
return [{ kind: 'confetti', props: {} }];
|
|
384
|
+
case 'qrNfc':
|
|
385
|
+
return [{ kind: 'qr', props: { value: str(ext.url) ?? str(ext.link) ?? str(ext.qrValue) ?? str(ext.deepLink) ?? 'https://app.example.com' } }];
|
|
386
|
+
case 'carouselDeck': {
|
|
387
|
+
const rows = listOf(ext, ['slides', 'cards', 'items', 'steps']);
|
|
388
|
+
const slides = (rows.length ? rows : [{}, {}, {}]).map((r) => {
|
|
389
|
+
const o = rec(r);
|
|
390
|
+
return { image: str(o.image ?? o.imageUrl), title: labelOf(r), text: str(o.text ?? o.body ?? o.subtitle) };
|
|
391
|
+
});
|
|
392
|
+
return [{ kind: 'carousel', props: { slides } }];
|
|
393
|
+
}
|
|
394
|
+
case 'questionFlow': {
|
|
395
|
+
/**
|
|
396
|
+
* FIVE shapes, not one.
|
|
397
|
+
*
|
|
398
|
+
* Nine variants share this archetype and every one of them shipped a `poll` — an NPS prompt
|
|
399
|
+
* rendered as multiple choice, a rating request as multiple choice, an emoji bar as multiple
|
|
400
|
+
* choice. The SDK already had `nps`, `rating`, `emoji` and `quiz` renderers registered; the
|
|
401
|
+
* bridge simply never emitted them (0 uses each). Same collapse as mystery_box, four times
|
|
402
|
+
* over, and the fix is a mapping rather than new rendering code.
|
|
403
|
+
*
|
|
404
|
+
* The archetype still decides the FAMILY (ask the user something); the variantKey picks the
|
|
405
|
+
* instrument. Anything unrecognised keeps the poll, so a new question variant degrades to a
|
|
406
|
+
* working control rather than nothing.
|
|
407
|
+
*/
|
|
408
|
+
/**
|
|
409
|
+
* The question comes from the FORM's `question` field, not the campaign title.
|
|
410
|
+
*
|
|
411
|
+
* Every question variant authors its prompt in a dedicated field — `poll_card` writes
|
|
412
|
+
* `question`, `feedback_capture` writes `promptText`, `product_finder` writes a `questions`
|
|
413
|
+
* array — and the bridge used `spec.title` instead. A poll authored as "Which do you prefer?"
|
|
414
|
+
* asked whatever the campaign happened to be named.
|
|
415
|
+
*/
|
|
416
|
+
const questionRows = listOf(ext, ['questions', 'steps']);
|
|
417
|
+
const firstQuestion = rec(questionRows[0]);
|
|
418
|
+
const question = str(ext.question ?? ext.promptText ?? ext.prompt)
|
|
419
|
+
?? str(firstQuestion.prompt ?? firstQuestion.question ?? firstQuestion.label)
|
|
420
|
+
?? title ?? 'Tell us';
|
|
421
|
+
const rows = listOf(ext, ['options', 'preferenceOptions', 'pollOptions', 'answers', 'choices', 'reactions']);
|
|
422
|
+
// A multi-question flow degrades to its first question's options rather than to placeholders.
|
|
423
|
+
const optionRows = rows.length ? rows : listOf(firstQuestion, ['options', 'answers', 'choices']);
|
|
424
|
+
const options = (optionRows.length ? optionRows : [{ label: 'Option A' }, { label: 'Option B' }])
|
|
425
|
+
.map((r, i) => ({ id: String(i), label: labelOf(r) }));
|
|
426
|
+
switch (variantKey) {
|
|
427
|
+
case 'nps_prompt':
|
|
428
|
+
// 0–10 is the definition of NPS; it takes no options.
|
|
429
|
+
return [{ kind: 'nps', props: { question } }];
|
|
430
|
+
case 'rating_request':
|
|
431
|
+
// Authoring may hand back "5" as text; a string would fall through to the default and
|
|
432
|
+
// silently ignore a 10-star scale the author set.
|
|
433
|
+
return [{ kind: 'rating', props: { question, max: num(Number(ext.max ?? ext.scale), 5) } }];
|
|
434
|
+
case 'emoji_reaction_bar': {
|
|
435
|
+
const emojis = listOf(ext, ['emojis', 'reactions', 'options'])
|
|
436
|
+
.map((r) => (typeof r === 'string' ? r : str(rec(r).emoji) ?? labelOf(r)))
|
|
437
|
+
.filter(Boolean);
|
|
438
|
+
return [{ kind: 'emoji', props: { question, ...(emojis.length ? { emojis } : {}) } }];
|
|
439
|
+
}
|
|
440
|
+
case 'quiz_card': {
|
|
441
|
+
/**
|
|
442
|
+
* Correctness stays server-authoritative — no answer key is shipped. The block marks the
|
|
443
|
+
* right and wrong answers only once the server has graded the attempt, which it reports as
|
|
444
|
+
* `{ answeredId, correctId }`. Forwarded rather than invented.
|
|
445
|
+
*/
|
|
446
|
+
const graded = rec(ext.outcome ?? ext.quizOutcome);
|
|
447
|
+
const answeredId = str(graded.answeredId ?? ext.answeredId);
|
|
448
|
+
const correctId = str(graded.correctId ?? ext.correctId);
|
|
449
|
+
return [{
|
|
450
|
+
kind: 'quiz',
|
|
451
|
+
props: {
|
|
452
|
+
question,
|
|
453
|
+
options,
|
|
454
|
+
...(answeredId || correctId ? { outcome: { answeredId, correctId } } : {}),
|
|
455
|
+
},
|
|
456
|
+
}];
|
|
457
|
+
}
|
|
458
|
+
default:
|
|
459
|
+
return [{ kind: 'poll', props: { question, options } }];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
case 'checklistProgress': {
|
|
463
|
+
/**
|
|
464
|
+
* SIX shapes, not one.
|
|
465
|
+
*
|
|
466
|
+
* Eight variants share this archetype and every one shipped `progress + checklist` — a habit
|
|
467
|
+
* streak drew a to-do list, a daily check-in drew a to-do list, a setup wizard drew a to-do
|
|
468
|
+
* list. The archetype names the FAMILY (something is partly complete); the variantKey decides
|
|
469
|
+
* how completeness is shown, and for a streak the shape IS the message.
|
|
470
|
+
*
|
|
471
|
+
* Unrecognised keys keep progress + checklist, so a new variant degrades to a working control.
|
|
472
|
+
*/
|
|
473
|
+
const rows = listOf(ext, ['steps', 'items', 'tasks', 'checklist']);
|
|
474
|
+
const rawSteps = rows.length ? rows : ['Step one', 'Step two', 'Step three'];
|
|
475
|
+
const items = rawSteps.map((s, i) => {
|
|
476
|
+
const o = rec(s);
|
|
477
|
+
return {
|
|
478
|
+
id: String(i),
|
|
479
|
+
label: labelOf(s),
|
|
480
|
+
// Completion is server-decided, like every other outcome in this file.
|
|
481
|
+
done: o.done === true || o.checked === true || o.complete === true,
|
|
482
|
+
};
|
|
483
|
+
});
|
|
484
|
+
const pct = pctOf(ext.progress ?? ext.percent ?? ext.progressValue ?? ext.currentValue, 40);
|
|
485
|
+
const progressBlock = { kind: 'progress', props: { value: pct } };
|
|
486
|
+
const reward = str(ext.reward ?? ext.prize ?? ext.rewardValue);
|
|
487
|
+
switch (variantKey) {
|
|
488
|
+
case 'streak_reward':
|
|
489
|
+
case 'daily_check_in': {
|
|
490
|
+
// Both are day cells; a streak is a consecutive run, a check-in has a today cell to tap.
|
|
491
|
+
const checkin = variantKey === 'daily_check_in';
|
|
492
|
+
const rawDays = listOf(ext, ['calendarDays', 'dayLabels', 'days']);
|
|
493
|
+
const labels = rawDays.map(labelOf).filter(Boolean);
|
|
494
|
+
/**
|
|
495
|
+
* Two ways a day count arrives, and the form writes BOTH depending on variant:
|
|
496
|
+
* `streak_reward` authors a scalar (`streakValueSource: 7`), while `daily_check_in`
|
|
497
|
+
* authors the calendar itself (`[{label:'Mon',done:true}, …]`) and the count is however
|
|
498
|
+
* many carry `done`. Reading only the scalar left every check-in calendar at zero.
|
|
499
|
+
*/
|
|
500
|
+
const doneDays = rawDays.filter((d) => {
|
|
501
|
+
const o = rec(d);
|
|
502
|
+
return o.done === true || o.checked === true || o.complete === true;
|
|
503
|
+
}).length;
|
|
504
|
+
const filled = num(Number(ext.filled ?? ext.currentStreak ?? ext.streakValue ?? ext.streakValueSource), doneDays);
|
|
505
|
+
// The authored calendar can also name today, which is otherwise inferred as filled + 1.
|
|
506
|
+
const todayIndex = rawDays.findIndex((d) => rec(d).today === true);
|
|
507
|
+
const blocks = [{
|
|
508
|
+
kind: 'streak',
|
|
509
|
+
props: {
|
|
510
|
+
mode: checkin ? 'checkin' : 'streak',
|
|
511
|
+
filled,
|
|
512
|
+
...(todayIndex >= 0 ? { today: todayIndex + 1 } : {}),
|
|
513
|
+
...(labels.length ? { labels } : { days: num(Number(ext.days ?? ext.calendarLength), 7) }),
|
|
514
|
+
// An author who already checked in today has no today cell to offer.
|
|
515
|
+
...(checkin && ext.alreadyCheckedIn === true ? { today: -1 } : {}),
|
|
516
|
+
},
|
|
517
|
+
}];
|
|
518
|
+
if (reward)
|
|
519
|
+
blocks.push({ kind: 'callout', props: { icon: '🎁', text: reward } });
|
|
520
|
+
return blocks;
|
|
521
|
+
}
|
|
522
|
+
case 'progress_unlock': {
|
|
523
|
+
// A locked reward, not a task list: the bar is the lock and the callout is the prize.
|
|
524
|
+
const unlocked = pct >= 100;
|
|
525
|
+
const blocks = [progressBlock];
|
|
526
|
+
if (reward) {
|
|
527
|
+
blocks.push({
|
|
528
|
+
kind: 'callout',
|
|
529
|
+
props: { icon: unlocked ? '🎉' : '🔒', text: unlocked ? reward : `Unlock ${reward}` },
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
return blocks;
|
|
533
|
+
}
|
|
534
|
+
case 'goal_tracker': {
|
|
535
|
+
const current = Number(ext.currentValue ?? ext.progressValue ?? ext.current);
|
|
536
|
+
const target = Number(ext.target ?? ext.goal ?? ext.targetValue ?? ext.goalValue);
|
|
537
|
+
const blocks = [progressBlock];
|
|
538
|
+
/**
|
|
539
|
+
* The form's required fields are `goalSource`/`progressValue` with `targetValue` optional,
|
|
540
|
+
* but the shipped example authors only `progress` — so a variant whose whole point is a
|
|
541
|
+
* number showed a bar and no number. The percentage is a legitimate reading of the goal
|
|
542
|
+
* when no absolute pair was authored, rather than dropping the stat entirely.
|
|
543
|
+
*/
|
|
544
|
+
blocks.push({
|
|
545
|
+
kind: 'stat',
|
|
546
|
+
props: {
|
|
547
|
+
value: Number.isFinite(current)
|
|
548
|
+
? (Number.isFinite(target) ? `${current} / ${target}` : current)
|
|
549
|
+
: `${Math.round(pct)}%`,
|
|
550
|
+
label: str(ext.goalLabel ?? ext.unit ?? ext.goalSource) ?? 'Progress',
|
|
551
|
+
},
|
|
552
|
+
});
|
|
553
|
+
return blocks;
|
|
554
|
+
}
|
|
555
|
+
case 'community_challenge': {
|
|
556
|
+
const participants = Number(ext.participants ?? ext.members ?? ext.joined);
|
|
557
|
+
const blocks = [progressBlock];
|
|
558
|
+
if (Number.isFinite(participants)) {
|
|
559
|
+
blocks.push({ kind: 'stat', props: { value: participants, label: str(ext.participantsLabel) ?? 'taking part' } });
|
|
560
|
+
}
|
|
561
|
+
// Milestones are the shared goal's rungs — a list, not personal to-dos.
|
|
562
|
+
if (rows.length)
|
|
563
|
+
blocks.push({ kind: 'list', props: { items: items.map((i) => ({ label: i.label })) } });
|
|
564
|
+
return blocks;
|
|
565
|
+
}
|
|
566
|
+
case 'guided_setup_wizard':
|
|
567
|
+
case 'first_session_onboarding': {
|
|
568
|
+
// These are wizards. The registry calls them "guided flow" / "new user guide" and gives
|
|
569
|
+
// them a fullscreen surface — one step at a time, which is exactly the `steps` block that
|
|
570
|
+
// multiStepSheet already ships. Reused rather than re-implemented.
|
|
571
|
+
const steps = rawSteps.map((r) => {
|
|
572
|
+
const o = rec(r);
|
|
573
|
+
return { title: labelOf(r) || undefined, body: str(o.body ?? o.text ?? o.subtitle) };
|
|
574
|
+
});
|
|
575
|
+
return [{
|
|
576
|
+
kind: 'steps',
|
|
577
|
+
props: {
|
|
578
|
+
steps,
|
|
579
|
+
backLabel: str(ext.backLabel), skipLabel: str(ext.skipLabel),
|
|
580
|
+
nextLabel: str(ext.nextLabel), finalLabel: str(ext.finalLabel),
|
|
581
|
+
},
|
|
582
|
+
}];
|
|
583
|
+
}
|
|
584
|
+
default:
|
|
585
|
+
// interactive_checklist and any future key: the canonical progress + checklist.
|
|
586
|
+
return [progressBlock, { kind: 'checklist', props: { items } }];
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
case 'multiStepSheet': {
|
|
590
|
+
// Steps come from the same authored keys the checklist archetype accepts, so a payload that
|
|
591
|
+
// already lists steps renders as a wizard without re-authoring. Labels ride `ext` with the RN
|
|
592
|
+
// precedence (backLabel/skipLabel/nextLabel/finalLabel).
|
|
593
|
+
const rows = listOf(ext, ['steps', 'pages', 'items', 'screens']);
|
|
594
|
+
const steps = (rows.length ? rows : [{}]).map((r) => {
|
|
595
|
+
const o = rec(r);
|
|
596
|
+
return { title: labelOf(r) || undefined, body: str(o.body ?? o.text ?? o.subtitle) };
|
|
597
|
+
});
|
|
598
|
+
return [{
|
|
599
|
+
kind: 'steps',
|
|
600
|
+
props: {
|
|
601
|
+
steps,
|
|
602
|
+
backLabel: str(ext.backLabel), skipLabel: str(ext.skipLabel),
|
|
603
|
+
nextLabel: str(ext.nextLabel), finalLabel: str(ext.finalLabel),
|
|
604
|
+
},
|
|
605
|
+
}];
|
|
606
|
+
}
|
|
607
|
+
case 'sideSheet':
|
|
608
|
+
// Handled by the container path below — a side sheet earns the rich lane for its SURFACE,
|
|
609
|
+
// and its body is the same authored content any container renders.
|
|
610
|
+
return containerBlocks(ext, body);
|
|
611
|
+
case 'videoCommerce': {
|
|
612
|
+
const out = [];
|
|
613
|
+
const video = str(ext.video);
|
|
614
|
+
if (video)
|
|
615
|
+
out.push({ kind: 'video', props: { src: video } });
|
|
616
|
+
const products = listOf(ext, ['products', 'items']).map((p) => {
|
|
617
|
+
const o = rec(p);
|
|
618
|
+
return { id: String(o.id ?? ''), image: str(o.image ?? o.imageUrl), title: labelOf(p), price: o.price ?? o.amount };
|
|
619
|
+
});
|
|
620
|
+
/**
|
|
621
|
+
* A shoppable video is usually ONE product, and the form says so: `productTitle` is required
|
|
622
|
+
* while a `products` array is not offered at all. Reading only the array meant the shipped
|
|
623
|
+
* example rendered an empty grid under the video — the video played and there was nothing to
|
|
624
|
+
* buy, which is the entire mechanic missing.
|
|
625
|
+
*/
|
|
626
|
+
const single = str(ext.productTitle);
|
|
627
|
+
if (!products.length && single) {
|
|
628
|
+
products.push({
|
|
629
|
+
id: 'product',
|
|
630
|
+
image: str(ext.productImage ?? ext.image),
|
|
631
|
+
title: single,
|
|
632
|
+
price: ext.price ?? ext.amount,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
out.push({ kind: 'product-grid', props: { products } });
|
|
636
|
+
return out;
|
|
637
|
+
}
|
|
638
|
+
default:
|
|
639
|
+
// CONTAINER archetypes (modal / sheet / bannerToast / fullscreen / anchored / inline).
|
|
640
|
+
return containerBlocks(ext, body);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Content blocks for a CONTAINER archetype.
|
|
645
|
+
*
|
|
646
|
+
* Measured before this existed: 70 of the 100 canonical variants shipped `heading + text` and
|
|
647
|
+
* nothing else — a "Rich modal", a "Compare plans sheet" and a "Coupon wallet" all rendered as a
|
|
648
|
+
* title over a paragraph, differing only in the surface they arrived on. The authoring preview drew
|
|
649
|
+
* the bullets, plans and product grids from the same payload, so the author saw a rich card and the
|
|
650
|
+
* visitor got a plain one.
|
|
651
|
+
*
|
|
652
|
+
* The registry's design is that distinctness comes from "the shared block library, not a per-variant
|
|
653
|
+
* file" — that only holds if the container path actually reaches for the library. These are the same
|
|
654
|
+
* four content shapes the preview builds, from the same authored keys.
|
|
655
|
+
*/
|
|
656
|
+
/**
|
|
657
|
+
* Supporting content that belongs to EVERY archetype, not just containers.
|
|
658
|
+
*
|
|
659
|
+
* These reads first lived inside `containerBlocks`, which only runs for container archetypes — so a
|
|
660
|
+
* mystery box's `closedMessage`, a QR prompt's `instruction` and a community challenge's `goal` were
|
|
661
|
+
* still dropped, because those variants take the mechanic path. The prose, the price line and the
|
|
662
|
+
* item spotlight are orthogonal to which mechanic (if any) a variant renders, so they are resolved
|
|
663
|
+
* once, here, for all of them.
|
|
664
|
+
*
|
|
665
|
+
* Split in two: `lead` sits directly under the body, `trail` after the mechanic — a prize message
|
|
666
|
+
* reads before the scratch surface, a price line reads after it.
|
|
667
|
+
*/
|
|
668
|
+
function supportingBlocks(ext, body) {
|
|
669
|
+
const lead = [];
|
|
670
|
+
const trail = [];
|
|
671
|
+
/**
|
|
672
|
+
* Prose that a variant REQUIRES but does not call `body`.
|
|
673
|
+
*
|
|
674
|
+
* `vip_unlock` requires `benefitMessage`, `smart_segment_preview` requires `segmentExplanation`,
|
|
675
|
+
* `nfc_qr_prompt` requires `instruction` — each is the point of its variant, and the seed maps
|
|
676
|
+
* only `body`/`message` onto the body slot, so every other name was authored and dropped.
|
|
677
|
+
* Skipped when it merely repeats the body, which happens when a variant authors both.
|
|
678
|
+
*/
|
|
679
|
+
const copy = str(ext.benefitMessage ?? ext.segmentExplanation ?? ext.availabilityMessage ??
|
|
680
|
+
ext.rewardMessage ?? ext.offerMessage ?? ext.proofMessage ?? ext.valueMessage ??
|
|
681
|
+
ext.reviewMessage ?? ext.assistantMessage ?? ext.supportMessage ?? ext.arrivalMessage ??
|
|
682
|
+
ext.checkoutMessage ?? ext.instruction ?? ext.instructions ?? ext.closedMessage ??
|
|
683
|
+
ext.reasonText ?? ext.motivationalText ?? ext.urgencyNote ?? ext.subtitle);
|
|
684
|
+
if (copy && copy !== body)
|
|
685
|
+
lead.push({ kind: 'text', props: { text: copy } });
|
|
686
|
+
/**
|
|
687
|
+
* A decision hub IS its choices.
|
|
688
|
+
*
|
|
689
|
+
* `multi_cta_decision_hub` authors `actions: [{label:'Explore'},{label:'Upgrade'},…]` — the whole
|
|
690
|
+
* variant — and it rendered a heading and nothing else. These become real CTA buttons rather than
|
|
691
|
+
* a bulleted list, because that is what the author authored.
|
|
692
|
+
*/
|
|
693
|
+
const choices = listOf(ext, ['actions', 'ctas']).map((a) => {
|
|
694
|
+
const o = rec(a);
|
|
695
|
+
return { label: labelOf(a), action: str(o.action) ?? 'dismiss', deepLink: str(o.deepLink), variant: 'secondary' };
|
|
696
|
+
}).filter((a) => a.label);
|
|
697
|
+
if (choices.length)
|
|
698
|
+
trail.push({ kind: 'cta', props: { actions: choices } });
|
|
699
|
+
/**
|
|
700
|
+
* A short detail line: the price on a paywall, the time on an event, the goal on a challenge, the
|
|
701
|
+
* reward on a quiz. Each is a required field of its variant and none of them rendered — a paywall
|
|
702
|
+
* with no price.
|
|
703
|
+
*/
|
|
704
|
+
const detail = str(ext.price ?? ext.eventTime ?? ext.dateTime ?? ext.goal ?? ext.documentType ??
|
|
705
|
+
ext.lastOrderDate ?? ext.reward ?? ext.rewardTitle ?? ext.resultReward);
|
|
706
|
+
if (detail)
|
|
707
|
+
trail.push({ kind: 'badge', props: { text: detail } });
|
|
708
|
+
/**
|
|
709
|
+
* A SECOND title — `webinar_registration` and `wallet_pass_offer` author both `title` and an
|
|
710
|
+
* `eventTitle`/`passTitle` naming the thing itself. Only one can be the heading, so the other
|
|
711
|
+
* becomes a callout instead of being discarded.
|
|
712
|
+
*/
|
|
713
|
+
const named = str(ext.eventTitle ?? ext.passTitle);
|
|
714
|
+
if (named && named !== body)
|
|
715
|
+
lead.push({ kind: 'callout', props: { icon: '🎟️', text: named } });
|
|
716
|
+
// `social_proof_popup` authors an avatar for the person being quoted; it rendered nowhere.
|
|
717
|
+
const avatar = str(ext.avatar ?? ext.avatarUrl);
|
|
718
|
+
if (avatar)
|
|
719
|
+
lead.unshift({ kind: 'image', props: { src: avatar, alt: '' } });
|
|
720
|
+
/**
|
|
721
|
+
* The item a behavioural alert is ABOUT, with the numbers that give it meaning.
|
|
722
|
+
*
|
|
723
|
+
* `price_drop_alert` requires `itemName`, `oldPrice` and `newPrice`, and rendered none of them —
|
|
724
|
+
* a price-drop alert that showed no price. Same for back-in-stock and reorder reminders.
|
|
725
|
+
*/
|
|
726
|
+
const item = str(ext.itemName);
|
|
727
|
+
if (item) {
|
|
728
|
+
const oldPrice = str(ext.oldPrice);
|
|
729
|
+
const newPrice = str(ext.newPrice);
|
|
730
|
+
const prices = oldPrice && newPrice
|
|
731
|
+
? `${oldPrice} → ${newPrice}`
|
|
732
|
+
: newPrice ?? oldPrice ?? str(ext.stockStatus) ?? str(ext.quantity);
|
|
733
|
+
trail.push({ kind: 'callout', props: { icon: '🏷️', text: prices ? `${item} · ${prices}` : item } });
|
|
734
|
+
}
|
|
735
|
+
return { lead, trail };
|
|
736
|
+
}
|
|
737
|
+
function containerBlocks(ext, body) {
|
|
738
|
+
const out = [];
|
|
739
|
+
/**
|
|
740
|
+
* Prose that a variant REQUIRES but does not call `body`.
|
|
741
|
+
*
|
|
742
|
+
* `vip_unlock` requires `benefitMessage` and `smart_segment_preview` requires
|
|
743
|
+
* `segmentExplanation` — each is the entire point of its variant, and neither reached the render.
|
|
744
|
+
* The seed maps only `body`/`message` onto the body slot, so everything else was authored and
|
|
745
|
+
* dropped: a VIP unlock that never said what the benefit was.
|
|
746
|
+
*
|
|
747
|
+
* Skipped when it merely repeats the body, which happens when a variant authors both.
|
|
748
|
+
*/
|
|
749
|
+
/**
|
|
750
|
+
* The authored key names are per-VARIANT, not generic.
|
|
751
|
+
*
|
|
752
|
+
* This read `bullets`/`features`/`points` while the form for `rich_modal` writes `bulletList`, the
|
|
753
|
+
* one for `loyalty_tier_upgrade` writes `perks`, `personalized_digest` writes `digestItems` and
|
|
754
|
+
* `bundle_builder` writes `bundleItems`. Every one of those authored a list and rendered a plain
|
|
755
|
+
* modal — which is exactly the "this should be the rich modal with bullets" report.
|
|
756
|
+
*
|
|
757
|
+
* Listing the real field names is deliberate over pattern-matching anything list-shaped: a variant
|
|
758
|
+
* that happens to carry an unrelated array should not have it rendered as body copy.
|
|
759
|
+
*/
|
|
760
|
+
const bullets = listOf(ext, [
|
|
761
|
+
'bullets', 'bulletList', 'benefits', 'features', 'newFeatures', 'perks', 'perksList',
|
|
762
|
+
'reasonList', 'digestItems', 'contentSections', 'contentBlocks', 'suggestedActions',
|
|
763
|
+
'points', 'highlights', 'dateTimeOptions', 'tabs', 'slots',
|
|
764
|
+
])
|
|
765
|
+
.map(labelOf)
|
|
766
|
+
.filter(Boolean);
|
|
767
|
+
if (bullets.length)
|
|
768
|
+
out.push({ kind: 'list', props: { items: bullets } });
|
|
769
|
+
const plans = listOf(ext, ['plans', 'planCards', 'tiers', 'pricingTiers', 'packages']);
|
|
770
|
+
if (plans.length) {
|
|
771
|
+
out.push({
|
|
772
|
+
kind: 'table',
|
|
773
|
+
props: {
|
|
774
|
+
columns: ['Plan', 'Price'],
|
|
775
|
+
rows: plans.map((p) => {
|
|
776
|
+
const o = rec(p);
|
|
777
|
+
return [labelOf(p), String(o.price ?? o.amount ?? '')];
|
|
778
|
+
}),
|
|
779
|
+
},
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
// Classification MUST match the preview's PRODUCT_KEYS — `bundleItems` and `itemList` are products
|
|
783
|
+
// there, so listing them as bullets here would show an author a grid and ship them a list.
|
|
784
|
+
const products = listOf(ext, [
|
|
785
|
+
'products', 'productList', 'productCards', 'productImages', 'crossSellItems',
|
|
786
|
+
'recommendations', 'bundleItems', 'cartItems', 'itemList', 'relatedItems',
|
|
787
|
+
]);
|
|
788
|
+
if (products.length) {
|
|
789
|
+
out.push({
|
|
790
|
+
kind: 'product-grid',
|
|
791
|
+
props: {
|
|
792
|
+
products: products.map((p) => {
|
|
793
|
+
const o = rec(p);
|
|
794
|
+
return { id: String(o.id ?? ''), image: str(o.image ?? o.imageUrl), title: labelOf(p), price: o.price ?? o.amount };
|
|
795
|
+
}),
|
|
796
|
+
},
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
// Checklist LAST: it reads as the "what's next" tail of a container, after the pitch.
|
|
800
|
+
const steps = listOf(ext, ['steps', 'setupSteps', 'tasks', 'checklistItems', 'checklist']);
|
|
801
|
+
if (steps.length) {
|
|
802
|
+
out.push({
|
|
803
|
+
kind: 'checklist',
|
|
804
|
+
props: { items: steps.map((s, i) => ({ id: String(i), label: labelOf(s), done: rec(s).done === true })) },
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
return out;
|
|
808
|
+
}
|
|
809
|
+
/** Build an IAM 2.0 Variant from an engage rich-variant message + its (A/B-resolved) spec. */
|
|
810
|
+
export function engageMessageToVariant(m, spec) {
|
|
811
|
+
// Resolved off the A/B-resolved `spec` that is actually being rendered, not `m.spec` — variant B
|
|
812
|
+
// carries its own ext, so reading the base spec here would build variant A's mechanic.
|
|
813
|
+
const arch = richArchetype(m.variantKey, servedArchetypeOf(spec)) ?? '';
|
|
814
|
+
// An archetype that dictates its own surface wins over the layout-derived one: `sideSheet` must
|
|
815
|
+
// dock to an edge and `multiStepSheet` must be a bottom sheet regardless of the legacy layout the
|
|
816
|
+
// payload also carries for old clients.
|
|
817
|
+
const ext = rec(spec.ext);
|
|
818
|
+
/**
|
|
819
|
+
* Precedence: an archetype that dictates its own surface, then the SERVED mount model, then the
|
|
820
|
+
* legacy layout. The archetype still wins — `multiStepSheet` must be a bottom sheet and `sideSheet`
|
|
821
|
+
* must dock to an edge regardless of how either was authored — but everything else now honours the
|
|
822
|
+
* registry's mount model instead of a mobile layout enum that could not express it.
|
|
823
|
+
*/
|
|
824
|
+
const base = ARCHETYPE_SURFACE[arch] ?? mountSurfaceFor(ext) ?? LAYOUT_SURFACE[m.layout] ?? LAYOUT_SURFACE.modal;
|
|
825
|
+
/**
|
|
826
|
+
* `side_sheet` offers a `sidePosition` field and it was ignored — a sheet authored to dock LEFT
|
|
827
|
+
* always slid in from the right. The archetype default stands when nothing was authored.
|
|
828
|
+
*/
|
|
829
|
+
const side = str(ext.sidePosition ?? ext.position);
|
|
830
|
+
const map = arch === 'sideSheet' && (side === 'left' || side === 'right')
|
|
831
|
+
? { ...base, surfaceOptions: { ...base.surfaceOptions, placement: side } }
|
|
832
|
+
: base;
|
|
833
|
+
const blocks = [];
|
|
834
|
+
if (spec.imageUrl)
|
|
835
|
+
blocks.push({ kind: 'image', props: { src: spec.imageUrl, alt: spec.title ?? '' } });
|
|
836
|
+
/**
|
|
837
|
+
* The eyebrow — the small label ABOVE the title. `classic_modal` requires it and the bridge dropped
|
|
838
|
+
* it entirely, so the one piece of chrome that variant asks for never rendered. Placed here rather
|
|
839
|
+
* than with the container content because it belongs above the heading, and because a mechanic
|
|
840
|
+
* variant can author one too. Guards mirror the preview: an eyebrow that merely repeats the title,
|
|
841
|
+
* or that is long enough to be a sentence, is body copy wearing a badge.
|
|
842
|
+
*/
|
|
843
|
+
const eyebrow = str(ext.eyebrow ?? ext.badge);
|
|
844
|
+
if (eyebrow && eyebrow !== spec.title && eyebrow.length < 32) {
|
|
845
|
+
blocks.push({ kind: 'badge', props: { text: eyebrow } });
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Several variants name their headline something other than `title` — `live_event_banner` writes
|
|
849
|
+
* `eventTitle`, `wallet_pass_offer` writes `passTitle`, `peek_card` writes `expandedTitle` and no
|
|
850
|
+
* title at all, `smart_inbox_message` writes `subject`. Those campaigns rendered headless.
|
|
851
|
+
*/
|
|
852
|
+
// `str()` rather than `??` on both: the seed hands back an EMPTY STRING for an unauthored body,
|
|
853
|
+
// and `'' ?? fallback` keeps the empty string — so peek_card, which authors only `expandedBody`,
|
|
854
|
+
// rendered no body at all while the fallback sat right there.
|
|
855
|
+
const heading = str(spec.title)
|
|
856
|
+
?? str(ext.eventTitle ?? ext.passTitle ?? ext.expandedTitle ?? ext.subject ?? ext.vipTitle
|
|
857
|
+
?? ext.offerTitle ?? ext.bubbleLabel ?? ext.peekLabel);
|
|
858
|
+
const bodyText = str(spec.body) ?? str(ext.expandedBody);
|
|
859
|
+
if (heading)
|
|
860
|
+
blocks.push({ kind: 'heading', props: { text: heading } });
|
|
861
|
+
if (bodyText)
|
|
862
|
+
blocks.push({ kind: 'text', props: { text: bodyText } });
|
|
863
|
+
const support = supportingBlocks(ext, bodyText);
|
|
864
|
+
blocks.push(...support.lead);
|
|
865
|
+
// The RESOLVED heading/body are handed down, so a question falls back to the real headline and the
|
|
866
|
+
// prose dedupe compares against the text that was actually drawn.
|
|
867
|
+
blocks.push(...mechanicBlocks(arch, ext, heading, m.variantKey, bodyText));
|
|
868
|
+
blocks.push(...support.trail);
|
|
869
|
+
const actions = [];
|
|
870
|
+
if (spec.cta?.label)
|
|
871
|
+
actions.push({ label: spec.cta.label, action: spec.cta.action ?? 'dismiss', deepLink: spec.cta.deepLink, variant: 'primary' });
|
|
872
|
+
if (spec.secondaryCta?.label)
|
|
873
|
+
actions.push({ label: spec.secondaryCta.label, action: 'dismiss', variant: 'dismiss' });
|
|
874
|
+
if (actions.length)
|
|
875
|
+
blocks.push({ kind: 'cta', props: { actions } });
|
|
876
|
+
if (blocks.length === 0)
|
|
877
|
+
blocks.push({ kind: 'text', props: { text: spec.body } });
|
|
878
|
+
return {
|
|
879
|
+
id: m.id,
|
|
880
|
+
key: m.variantKey ?? m.id,
|
|
881
|
+
name: spec.title ?? m.id,
|
|
882
|
+
category: 'misc',
|
|
883
|
+
platforms: ['web'],
|
|
884
|
+
surface: map.surface,
|
|
885
|
+
surfaceOptions: map.surfaceOptions,
|
|
886
|
+
blocks,
|
|
887
|
+
priority: 'normal',
|
|
888
|
+
triggers: [{ type: 'manual' }],
|
|
889
|
+
dismiss: { xButton: true, escClose: true, backdropClose: true },
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Bridge the ENGAGE theme contract onto the IAM 2.0 variable namespace.
|
|
894
|
+
*
|
|
895
|
+
* Two namespaces exist for good reasons and neither should be renamed: engage's `--sb-*` names are
|
|
896
|
+
* copied byte-for-byte from the frozen mobile contract (`accent`/`cardBg`/`titleColor`/…), while
|
|
897
|
+
* IAM's `--scalebun-*` names are the block library's own vocabulary. This maps one onto the other so
|
|
898
|
+
* an author picks a colour once and both surfaces obey it.
|
|
899
|
+
*
|
|
900
|
+
* Before this, `richInApp` never read `spec.style` at all: a campaign's brand colours were authored
|
|
901
|
+
* in the dashboard, packed by `buildPayload`, served by the backend — and rendered by nobody. Every
|
|
902
|
+
* rich in-app message came out in ScaleBun's default indigo regardless of what the customer chose.
|
|
903
|
+
*
|
|
904
|
+
* Values arrive already validated by `resolveTheme` (strict colour grammar, unsafe values dropped to
|
|
905
|
+
* defaults), so nothing unvalidated is interpolated into a style property here.
|
|
906
|
+
*/
|
|
907
|
+
/**
|
|
908
|
+
* Authored entrance animation → a fixed CSS shorthand.
|
|
909
|
+
*
|
|
910
|
+
* A DICTIONARY, not interpolation. The value is author-controlled and ends up in a stylesheet, so
|
|
911
|
+
* the same rule as colours applies: an unknown name maps to nothing and the surface keeps its own
|
|
912
|
+
* default. Every keyframe referenced here already exists in the surface stylesheet — this maps the
|
|
913
|
+
* authored vocabulary onto them rather than adding new motion.
|
|
914
|
+
*
|
|
915
|
+
* `slide_out_right` is deliberately absent: it only ever appears as an EXIT animation, and applying
|
|
916
|
+
* an exit as an entrance would play the surface sliding away as it arrives.
|
|
917
|
+
*/
|
|
918
|
+
const ANIMATION_CSS = {
|
|
919
|
+
fade: 'scalebun-fade .18s ease',
|
|
920
|
+
fade_scale: 'scalebun-pop .16s ease',
|
|
921
|
+
slide_up: 'scalebun-slideup .2s ease',
|
|
922
|
+
slide_down: 'scalebun-slidedown .18s ease',
|
|
923
|
+
slide_in_right: 'scalebun-slide-in-r .2s ease',
|
|
924
|
+
};
|
|
925
|
+
/**
|
|
926
|
+
* Apply the authored entrance animation, if the SDK knows it.
|
|
927
|
+
*
|
|
928
|
+
* Reduced motion needs no handling here: the host's base stylesheet carries
|
|
929
|
+
* `@media (prefers-reduced-motion: reduce){ .layer *{ animation:none !important } }`, and an
|
|
930
|
+
* `!important` rule beats this custom property — so an authored animation cannot override a user's
|
|
931
|
+
* accessibility preference.
|
|
932
|
+
*/
|
|
933
|
+
function applyEngageAnimation(el, spec) {
|
|
934
|
+
const authored = spec.ext?.['animationIn'];
|
|
935
|
+
const css = typeof authored === 'string' ? ANIMATION_CSS[authored] : undefined;
|
|
936
|
+
if (css)
|
|
937
|
+
el.style.setProperty('--scalebun-anim-in', css);
|
|
938
|
+
}
|
|
939
|
+
function applyEngageTheme(el, spec) {
|
|
940
|
+
/**
|
|
941
|
+
* ONLY tokens the author actually set are applied.
|
|
942
|
+
*
|
|
943
|
+
* `resolveTheme` fills every unset token with the SURVEY widget's historical defaults — correct
|
|
944
|
+
* there, wrong here: IAM has its own defaults (accent `#4f46e5`, auto light/dark) and an unstyled
|
|
945
|
+
* in-app message must keep them. Applying the resolved record wholesale would silently repaint
|
|
946
|
+
* every un-themed campaign, which is the regression their module's rule 2 exists to prevent.
|
|
947
|
+
* Sanitizing gives the authored subset; the rest simply isn't set, so IAM's own vars stand.
|
|
948
|
+
*/
|
|
949
|
+
const authored = sanitizeTheme(spec.style);
|
|
950
|
+
const set = (name, v) => {
|
|
951
|
+
if (v)
|
|
952
|
+
el.style.setProperty(name, v);
|
|
953
|
+
};
|
|
954
|
+
set('--scalebun-accent', authored.accent);
|
|
955
|
+
set('--scalebun-bg', authored.cardBg);
|
|
956
|
+
// IAM carries ONE foreground; the contract names title and body separately. Body drives the
|
|
957
|
+
// general token because it covers more surface, and the heading reads its own var so an author who
|
|
958
|
+
// set them differently still gets both — without widening the frozen contract.
|
|
959
|
+
set('--scalebun-fg', authored.bodyColor);
|
|
960
|
+
set('--scalebun-title', authored.titleColor);
|
|
961
|
+
/**
|
|
962
|
+
* CTA text is COMPUTED, not just copied. A pale authored accent with IAM's default white
|
|
963
|
+
* `--scalebun-accent-fg` gives white-on-pale — legible in the authoring preview at full size,
|
|
964
|
+
* unreadable in the surface. `readableOn` honours an explicit `ctaText` and otherwise picks a
|
|
965
|
+
* readable foreground. Only when the accent was authored: otherwise IAM's own pairing is intact.
|
|
966
|
+
*/
|
|
967
|
+
if (authored.accent)
|
|
968
|
+
set('--scalebun-accent-fg', readableOn(authored.accent, authored.ctaText));
|
|
969
|
+
else
|
|
970
|
+
set('--scalebun-accent-fg', authored.ctaText);
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Render a rich variant through the IAM 2.0 renderer. The render system is dynamic-imported (kept
|
|
974
|
+
* out of the eager bundle), rendered into its own ShadowHost, and torn down on close. CTA/dismiss
|
|
975
|
+
* are wired back to the caller's beacons so analytics is identical to the widget path.
|
|
976
|
+
*/
|
|
977
|
+
export async function renderRichInApp(m, spec, cb) {
|
|
978
|
+
const [{ renderVariant }, { ShadowHost }] = await Promise.all([
|
|
979
|
+
import('../inapp/surfaces/render'),
|
|
980
|
+
import('../inapp/core/host'),
|
|
981
|
+
]);
|
|
982
|
+
const host = new ShadowHost();
|
|
983
|
+
host.ensure();
|
|
984
|
+
/**
|
|
985
|
+
* Mode first, then the author's colours on top — `setTheme` re-applies the whole default set, so
|
|
986
|
+
* the reverse order would wipe the overrides. A campaign that asked for dark gets IAM's dark
|
|
987
|
+
* defaults for everything it did NOT theme; one that didn't ask keeps 'auto' (the host's existing
|
|
988
|
+
* behaviour), because a page's colour scheme is not the campaign author's decision.
|
|
989
|
+
*/
|
|
990
|
+
if (spec.dark === true)
|
|
991
|
+
host.setTheme('dark');
|
|
992
|
+
// Brand BEFORE mounting: the surface and its blocks read these vars as they build, so applying
|
|
993
|
+
// afterwards would paint one frame in the default palette first.
|
|
994
|
+
const themed = host.element();
|
|
995
|
+
if (themed) {
|
|
996
|
+
applyEngageTheme(themed, spec);
|
|
997
|
+
applyEngageAnimation(themed, spec);
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* The gamified outcome lane.
|
|
1001
|
+
*
|
|
1002
|
+
* `load` variants (progress_unlock, streak_reward, daily_check_in) are resolved BEFORE the variant
|
|
1003
|
+
* is built, because "load" means the state is what the message is about — painting a 0% bar and
|
|
1004
|
+
* correcting it a moment later would show every visitor a wrong number first. `play` and
|
|
1005
|
+
* `submit_quiz` resolve on interaction instead, via the resolver handed to the surface below.
|
|
1006
|
+
*
|
|
1007
|
+
* A failed load is NOT fatal: the message still renders with its authored defaults, which is
|
|
1008
|
+
* strictly better than showing nothing because a rewards backend was briefly down.
|
|
1009
|
+
*/
|
|
1010
|
+
// Same object reference `engageMessageToVariant` will read, so a resolved `load` state merged
|
|
1011
|
+
// here is visible when the blocks are built below.
|
|
1012
|
+
const ext = rec(spec.ext);
|
|
1013
|
+
const resolver = makeGameResolver({
|
|
1014
|
+
campaignId: m.id,
|
|
1015
|
+
variantKey: m.variantKey ?? '',
|
|
1016
|
+
ext,
|
|
1017
|
+
preview: m.preview === true || m.isTest === true,
|
|
1018
|
+
...(gameHandlerRef ? { handler: gameHandlerRef } : {}),
|
|
1019
|
+
});
|
|
1020
|
+
if (resolver && inAppGameActionFor(m.variantKey) === 'load') {
|
|
1021
|
+
const loaded = await resolver(1);
|
|
1022
|
+
if (loaded.ok && loaded.state)
|
|
1023
|
+
Object.assign(ext, loaded.state);
|
|
1024
|
+
}
|
|
1025
|
+
const variant = engageMessageToVariant(m, spec);
|
|
1026
|
+
let done = false;
|
|
1027
|
+
/**
|
|
1028
|
+
* Detach the per-message host once the surface is gone.
|
|
1029
|
+
*
|
|
1030
|
+
* A user-driven dismiss (X / Esc / backdrop) resolves INSIDE the surface — requestClose tears the
|
|
1031
|
+
* surface down and fires onDismiss — so it never passes through the RichHandle.close() below. That
|
|
1032
|
+
* left this host (and its cached zones) attached to <body> for the page's lifetime, one per
|
|
1033
|
+
* campaign shown. Deferred a microtask because mountSurface calls hooks.onDismiss() BEFORE
|
|
1034
|
+
* inst.destroy(); destroying the host first would pull the DOM out from under that teardown.
|
|
1035
|
+
*/
|
|
1036
|
+
let hostGone = false;
|
|
1037
|
+
const dropHost = () => {
|
|
1038
|
+
if (hostGone)
|
|
1039
|
+
return;
|
|
1040
|
+
hostGone = true;
|
|
1041
|
+
queueMicrotask(() => {
|
|
1042
|
+
try {
|
|
1043
|
+
host.destroy();
|
|
1044
|
+
}
|
|
1045
|
+
catch { /* already detached */ }
|
|
1046
|
+
});
|
|
1047
|
+
};
|
|
1048
|
+
const rendered = await renderVariant(variant, {
|
|
1049
|
+
onImpression() { },
|
|
1050
|
+
onView() { },
|
|
1051
|
+
onCtaClick() { if (!done) {
|
|
1052
|
+
done = true;
|
|
1053
|
+
cb.onClick();
|
|
1054
|
+
} },
|
|
1055
|
+
onInteraction() { },
|
|
1056
|
+
onDismiss() {
|
|
1057
|
+
if (!done) {
|
|
1058
|
+
done = true;
|
|
1059
|
+
cb.onDismiss();
|
|
1060
|
+
}
|
|
1061
|
+
dropHost();
|
|
1062
|
+
},
|
|
1063
|
+
/**
|
|
1064
|
+
* Present ONLY for the eight gamified variants — its absence is how a block knows it is not
|
|
1065
|
+
* server-resolved. `load` variants were already resolved above, before paint; this serves the
|
|
1066
|
+
* `play` and `submit_quiz` blocks, which call it when the user actually plays.
|
|
1067
|
+
*/
|
|
1068
|
+
...(resolver ? { requestOutcome: resolver } : {}),
|
|
1069
|
+
},
|
|
1070
|
+
// The slot registry rides along so an inline surface can find its host-registered mount.
|
|
1071
|
+
{ host, slots: engageSlots });
|
|
1072
|
+
return {
|
|
1073
|
+
close: () => {
|
|
1074
|
+
try {
|
|
1075
|
+
rendered.close();
|
|
1076
|
+
}
|
|
1077
|
+
catch { /* already closed */ }
|
|
1078
|
+
dropHost();
|
|
1079
|
+
},
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
//# sourceMappingURL=richInApp.js.map
|