@qualified-salesforce/web 0.0.1-oidc-bootstrap
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/41842993ec71d6628e4949e9a22b146b.svg +3 -0
- package/7271f3433ed82fc7f56adcd9e30275f4.svg +17 -0
- package/LICENSE.txt +82 -0
- package/components/helpers/entriesStringValidations.js +69 -0
- package/components/helpers/languages.js +32 -0
- package/components/shared/assertUnreachable.js +5 -0
- package/components/shared/controls/imageCropperHelpers.js +43 -0
- package/components/shared/meetingLoadingProgressSpec.js +116 -0
- package/constants.generated.js +9883 -0
- package/css/widget/multimodal_v2/host.split-css.css +162 -0
- package/css/widget/multimodal_v2/index.split-css.panda.css +5240 -0
- package/css/widget/widget.split-css.css +100 -0
- package/fonts/inter/Inter-Black.woff +0 -0
- package/fonts/inter/Inter-Black.woff2 +0 -0
- package/fonts/inter/Inter-BlackItalic.woff +0 -0
- package/fonts/inter/Inter-BlackItalic.woff2 +0 -0
- package/fonts/inter/Inter-Bold.woff +0 -0
- package/fonts/inter/Inter-Bold.woff2 +0 -0
- package/fonts/inter/Inter-BoldItalic.woff +0 -0
- package/fonts/inter/Inter-BoldItalic.woff2 +0 -0
- package/fonts/inter/Inter-ExtraBold.woff +0 -0
- package/fonts/inter/Inter-ExtraBold.woff2 +0 -0
- package/fonts/inter/Inter-ExtraBoldItalic.woff +0 -0
- package/fonts/inter/Inter-ExtraBoldItalic.woff2 +0 -0
- package/fonts/inter/Inter-ExtraLight.woff +0 -0
- package/fonts/inter/Inter-ExtraLight.woff2 +0 -0
- package/fonts/inter/Inter-ExtraLightItalic.woff +0 -0
- package/fonts/inter/Inter-ExtraLightItalic.woff2 +0 -0
- package/fonts/inter/Inter-Italic.woff +0 -0
- package/fonts/inter/Inter-Italic.woff2 +0 -0
- package/fonts/inter/Inter-Light.woff +0 -0
- package/fonts/inter/Inter-Light.woff2 +0 -0
- package/fonts/inter/Inter-LightItalic.woff +0 -0
- package/fonts/inter/Inter-LightItalic.woff2 +0 -0
- package/fonts/inter/Inter-Medium.woff +0 -0
- package/fonts/inter/Inter-Medium.woff2 +0 -0
- package/fonts/inter/Inter-MediumItalic.woff +0 -0
- package/fonts/inter/Inter-MediumItalic.woff2 +0 -0
- package/fonts/inter/Inter-Regular.woff +0 -0
- package/fonts/inter/Inter-Regular.woff2 +0 -0
- package/fonts/inter/Inter-SemiBold.woff +0 -0
- package/fonts/inter/Inter-SemiBold.woff2 +0 -0
- package/fonts/inter/Inter-SemiBoldItalic.woff +0 -0
- package/fonts/inter/Inter-SemiBoldItalic.woff2 +0 -0
- package/fonts/inter/Inter-Thin.woff +0 -0
- package/fonts/inter/Inter-Thin.woff2 +0 -0
- package/fonts/inter/Inter-ThinItalic.woff +0 -0
- package/fonts/inter/Inter-ThinItalic.woff2 +0 -0
- package/fonts/inter/Inter-italic.var.woff2 +0 -0
- package/fonts/inter/Inter-roman.var.woff2 +0 -0
- package/images/close.js +63 -0
- package/images/logo.js +22 -0
- package/js/4101.js +19721 -0
- package/js/daily-esm.js +9948 -0
- package/js/date-fns.js +427 -0
- package/js/multimodal_v2.js +1653 -0
- package/js/runtime.js +109 -0
- package/media/Inter-Black.796be8d8bf.woff2 +0 -0
- package/media/Inter-Black.b254104c56.woff +0 -0
- package/media/Inter-BlackItalic.70306b0eae.woff +0 -0
- package/media/Inter-BlackItalic.752f1e0aaa.woff2 +0 -0
- package/media/Inter-Bold.579e0f95ca.woff2 +0 -0
- package/media/Inter-Bold.b1234477a5.woff +0 -0
- package/media/Inter-BoldItalic.3d0d804323.woff +0 -0
- package/media/Inter-BoldItalic.828a494e04.woff2 +0 -0
- package/media/Inter-ExtraBold.208a9e6c99.woff +0 -0
- package/media/Inter-ExtraBold.d65f028165.woff2 +0 -0
- package/media/Inter-ExtraBoldItalic.30429962ec.woff +0 -0
- package/media/Inter-ExtraBoldItalic.8c7eac5ce3.woff2 +0 -0
- package/media/Inter-ExtraLight.15c082a57d.woff +0 -0
- package/media/Inter-ExtraLight.6824177d1e.woff2 +0 -0
- package/media/Inter-ExtraLightItalic.05138dddf3.woff2 +0 -0
- package/media/Inter-ExtraLightItalic.3beee54f59.woff +0 -0
- package/media/Inter-Italic.9beab78452.woff +0 -0
- package/media/Inter-Italic.d593a8df79.woff2 +0 -0
- package/media/Inter-Light.27083fa637.woff2 +0 -0
- package/media/Inter-Light.91dfddd842.woff +0 -0
- package/media/Inter-LightItalic.0a783b89b3.woff2 +0 -0
- package/media/Inter-LightItalic.f8ccf2813f.woff +0 -0
- package/media/Inter-Medium.dc792b508e.woff2 +0 -0
- package/media/Inter-Medium.ec7dd2d9d8.woff +0 -0
- package/media/Inter-MediumItalic.17301e5b40.woff +0 -0
- package/media/Inter-MediumItalic.84d3493a9f.woff2 +0 -0
- package/media/Inter-Regular.f1f0c35b32.woff2 +0 -0
- package/media/Inter-Regular.f356e84aa0.woff +0 -0
- package/media/Inter-SemiBold.55027e4724.woff +0 -0
- package/media/Inter-SemiBold.fcb100c760.woff2 +0 -0
- package/media/Inter-SemiBoldItalic.ab9105ed3b.woff +0 -0
- package/media/Inter-SemiBoldItalic.d90f295d0c.woff2 +0 -0
- package/media/Inter-Thin.16325d9b0f.woff +0 -0
- package/media/Inter-Thin.dafaa44d99.woff2 +0 -0
- package/media/Inter-ThinItalic.4fc662b3cf.woff2 +0 -0
- package/media/Inter-ThinItalic.d3d8994788.woff +0 -0
- package/media/Inter-italic.var.958a0b9742.woff2 +0 -0
- package/media/Inter-roman.var.b2129c009c.woff2 +0 -0
- package/package.json +20 -0
- package/packs/widget/api/docking/docking_host.js +97 -0
- package/packs/widget/api/docking/index.js +294 -0
- package/packs/widget/api/docking/shared.js +164 -0
- package/packs/widget/api/docking/viewport_lock.js +488 -0
- package/packs/widget/api/docking/viewport_resize.js +1203 -0
- package/packs/widget/esm/fonts/Inter-Black.796be8d8bf.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Black.b254104c56.woff +0 -0
- package/packs/widget/esm/fonts/Inter-BlackItalic.70306b0eae.woff +0 -0
- package/packs/widget/esm/fonts/Inter-BlackItalic.752f1e0aaa.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Bold.579e0f95ca.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Bold.b1234477a5.woff +0 -0
- package/packs/widget/esm/fonts/Inter-BoldItalic.3d0d804323.woff +0 -0
- package/packs/widget/esm/fonts/Inter-BoldItalic.828a494e04.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-ExtraBold.208a9e6c99.woff +0 -0
- package/packs/widget/esm/fonts/Inter-ExtraBold.d65f028165.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-ExtraBoldItalic.30429962ec.woff +0 -0
- package/packs/widget/esm/fonts/Inter-ExtraBoldItalic.8c7eac5ce3.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-ExtraLight.15c082a57d.woff +0 -0
- package/packs/widget/esm/fonts/Inter-ExtraLight.6824177d1e.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-ExtraLightItalic.05138dddf3.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-ExtraLightItalic.3beee54f59.woff +0 -0
- package/packs/widget/esm/fonts/Inter-Italic.9beab78452.woff +0 -0
- package/packs/widget/esm/fonts/Inter-Italic.d593a8df79.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Light.27083fa637.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Light.91dfddd842.woff +0 -0
- package/packs/widget/esm/fonts/Inter-LightItalic.0a783b89b3.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-LightItalic.f8ccf2813f.woff +0 -0
- package/packs/widget/esm/fonts/Inter-Medium.dc792b508e.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Medium.ec7dd2d9d8.woff +0 -0
- package/packs/widget/esm/fonts/Inter-MediumItalic.17301e5b40.woff +0 -0
- package/packs/widget/esm/fonts/Inter-MediumItalic.84d3493a9f.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Regular.f1f0c35b32.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Regular.f356e84aa0.woff +0 -0
- package/packs/widget/esm/fonts/Inter-SemiBold.55027e4724.woff +0 -0
- package/packs/widget/esm/fonts/Inter-SemiBold.fcb100c760.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-SemiBoldItalic.ab9105ed3b.woff +0 -0
- package/packs/widget/esm/fonts/Inter-SemiBoldItalic.d90f295d0c.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-Thin.16325d9b0f.woff +0 -0
- package/packs/widget/esm/fonts/Inter-Thin.dafaa44d99.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-ThinItalic.4fc662b3cf.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-ThinItalic.d3d8994788.woff +0 -0
- package/packs/widget/esm/fonts/Inter-italic.var.958a0b9742.woff2 +0 -0
- package/packs/widget/esm/fonts/Inter-roman.var.b2129c009c.woff2 +0 -0
- package/packs/widget/esm/index.js +183 -0
- package/packs/widget/esm/qualified.css +5502 -0
- package/routes/app/offers/scripts/OfferMainScript.js +154 -0
- package/routes/app/offers/scripts/constants.js +71 -0
- package/routes/app/offers/scripts/main/ButtonManager.js +65 -0
- package/routes/app/offers/scripts/main/FormManager.js +325 -0
- package/routes/app/offers/scripts/main/MainContext.js +19 -0
- package/routes/app/offers/scripts/main/OfferManager.js +91 -0
- package/routes/app/offers/scripts/main/TriggerManager.js +125 -0
- package/routes/app/offers/scripts/rendering/ContentManager.js +53 -0
- package/routes/app/offers/scripts/rendering/LocationManager.js +83 -0
- package/routes/app/offers/scripts/rendering/RenderedOffer.js +188 -0
- package/routes/app/offers/scripts/rendering/Renderer.js +69 -0
- package/routes/app/offers/scripts/rendering/RenderingInitializer.js +62 -0
- package/routes/app/offers/scripts/rendering/animations/AnimationManager.js +31 -0
- package/routes/app/offers/scripts/rendering/animations/AnimationManagerFooter.js +81 -0
- package/routes/app/offers/scripts/rendering/animations/AnimationManagerHeader.js +81 -0
- package/routes/app/offers/scripts/rendering/animations/AnimationManagerModal.js +117 -0
- package/routes/app/offers/scripts/rendering/animations/AnimationManagerSidebar.js +75 -0
- package/routes/app/offers/scripts/rendering/animations/AnimationResult.js +43 -0
- package/routes/app/offers/scripts/rendering/animations/Animator.js +78 -0
- package/routes/app/offers/scripts/rendering/animations/BaseAnimationManager.js +25 -0
- package/routes/app/offers/scripts/rendering/lib/BaseComponent.js +106 -0
- package/routes/app/offers/scripts/rendering/lib/FormComponent.js +134 -0
- package/routes/app/offers/scripts/rendering/lib/OfferComponent.js +144 -0
- package/routes/app/offers/scripts/rendering/lib/ScrollbarWidth.js +27 -0
- package/routes/app/offers/scripts/rendering/lib/decorators.js +20 -0
- package/routes/app/offers/scripts/rendering/locations/CSSVarsManager.js +66 -0
- package/routes/app/offers/scripts/rendering/locations/ElementResizeObserver.js +49 -0
- package/routes/app/offers/scripts/rendering/locations/footer.js +53 -0
- package/routes/app/offers/scripts/rendering/locations/header/AsyncBatchProcessor.js +70 -0
- package/routes/app/offers/scripts/rendering/locations/header/CSSTransitionObserver.js +182 -0
- package/routes/app/offers/scripts/rendering/locations/header/ElementStyleChangeObserver.js +138 -0
- package/routes/app/offers/scripts/rendering/locations/header/ExternalStyleManager.js +110 -0
- package/routes/app/offers/scripts/rendering/locations/header/Header.js +353 -0
- package/routes/app/offers/scripts/rendering/locations/header/InlineStyleManager.js +105 -0
- package/routes/app/offers/scripts/rendering/locations/header/MatchingElementsObserver.js +107 -0
- package/routes/app/offers/scripts/rendering/locations/header/NewElementsObserver.js +129 -0
- package/routes/app/offers/scripts/rendering/locations/header/RuleWrapper.js +46 -0
- package/routes/app/offers/scripts/rendering/locations/header/SelectorObservable.js +23 -0
- package/routes/app/offers/scripts/rendering/locations/header/SelectorObserver.js +61 -0
- package/routes/app/offers/scripts/rendering/locations/header/ShiftedElementsManager.js +45 -0
- package/routes/app/offers/scripts/rendering/locations/header/StyleElementManager.js +37 -0
- package/routes/app/offers/scripts/rendering/locations/header/StyleElementWrapper.js +62 -0
- package/routes/app/offers/scripts/rendering/locations/header/StyleSelectorObserver/ObservedSelectorValue.js +45 -0
- package/routes/app/offers/scripts/rendering/locations/header/StyleSelectorObserver/ObservedSelectors.js +62 -0
- package/routes/app/offers/scripts/rendering/locations/header/StyleSelectorObserver/StyleSelectorObserver.js +294 -0
- package/routes/app/offers/scripts/rendering/locations/header/StyleSelectorObserver/constants.js +21 -0
- package/routes/app/offers/scripts/rendering/locations/header/WindowResizeObserver.js +43 -0
- package/routes/app/offers/scripts/rendering/locations/header/utils.js +25 -0
- package/routes/app/offers/scripts/rendering/locations/popup.js +66 -0
- package/routes/app/offers/scripts/rendering/locations/sidebar.js +21 -0
- package/routes/app/offers/scripts/rendering/variations/ButtonBanner.js +105 -0
- package/routes/app/offers/scripts/rendering/variations/ButtonModal.js +114 -0
- package/routes/app/offers/scripts/rendering/variations/FormBanner.js +214 -0
- package/routes/app/offers/scripts/rendering/variations/FormModal.js +325 -0
- package/routes/app/offers/scripts/rendering/variations/LinkBanner.js +105 -0
- package/routes/app/offers/scripts/rendering/variations/components/Body.js +29 -0
- package/routes/app/offers/scripts/rendering/variations/components/Button.js +128 -0
- package/routes/app/offers/scripts/rendering/variations/components/DismissButton.js +39 -0
- package/routes/app/offers/scripts/rendering/variations/components/ForegroundImageBanner.js +110 -0
- package/routes/app/offers/scripts/rendering/variations/components/ForegroundImageModal.js +128 -0
- package/routes/app/offers/scripts/rendering/variations/components/Headline.js +94 -0
- package/routes/app/offers/scripts/rendering/variations/components/MultiFieldForm.js +302 -0
- package/routes/app/offers/scripts/rendering/variations/components/Tooltip.js +74 -0
- package/routes/app/offers/scripts/rendering/variations/icons.js +15 -0
- package/routes/app/offers/scripts/utils.js +115 -0
- package/routes/app/offers/utils/HTMLUtils.js +10 -0
- package/routes/app/offers/utils/createTypeGuard.js +32 -0
- package/routes/app/offers/utils/promise-utils.js +22 -0
- package/routes/app/websiteBuilder/stores/storeHelpers.js +18 -0
- package/sounds/message-initial.mp3 +0 -0
- package/sounds/message-received.mp3 +0 -0
- package/sounds/message-sent.mp3 +0 -0
- package/src/arrays.js +15 -0
- package/src/audio.js +106 -0
- package/src/bounded-set.js +16 -0
- package/src/bounding_box_observer.js +129 -0
- package/src/decorators.js +29 -0
- package/src/dom.js +128 -0
- package/src/dom_roots.js +26 -0
- package/src/embedded_forms/EmbeddedForm.js +638 -0
- package/src/embedded_forms/QualifiedEmbeddedForm.js +51 -0
- package/src/embedded_forms/QualifiedFormField.js +137 -0
- package/src/embedded_forms/utils.js +17 -0
- package/src/graphql-types.js +1686 -0
- package/src/iframes.js +86 -0
- package/src/localstorage.js +43 -0
- package/src/mirror/Shipper.js +133 -0
- package/src/mirror/constants.generated.js +13 -0
- package/src/mirror/constants.js +238 -0
- package/src/mirror/shipper/ChangeQueue.js +155 -0
- package/src/mirror/shipper/DOMSerializer.js +392 -0
- package/src/mirror/shipper/observers.js +441 -0
- package/src/mirror/shipper/utils.js +98 -0
- package/src/mixins/disposable.js +125 -0
- package/src/mixins/injectable.js +37 -0
- package/src/personalizations/personalization-manager.js +110 -0
- package/src/personalizations/strategies/node-freezing-strategy.js +174 -0
- package/src/personalizations/utils.js +187 -0
- package/src/promises.js +107 -0
- package/src/proxy.js +144 -0
- package/src/qualified_root.js +35 -0
- package/src/query_params.js +55 -0
- package/src/shadow-dom-helper.js +63 -0
- package/src/singleton_host.js +39 -0
- package/src/smart_website/trigger.js +49 -0
- package/src/smart_website/utils.js +149 -0
- package/src/string.js +53 -0
- package/src/timezone.js +57 -0
- package/src/timing.js +49 -0
- package/src/type-utils.js +76 -0
- package/src/url-utils.js +102 -0
- package/src/url.js +50 -0
- package/src/utils.js +72 -0
- package/src/validation.js.js +29 -0
- package/src/validation_ts.js +6 -0
- package/vendor/actioncable/adapters.js +6 -0
- package/vendor/actioncable/connection.js +204 -0
- package/vendor/actioncable/connection_monitor.js +129 -0
- package/vendor/actioncable/consumer.js +91 -0
- package/vendor/actioncable/index.js +34 -0
- package/vendor/actioncable/internal.js +22 -0
- package/vendor/actioncable/logger.js +28 -0
- package/vendor/actioncable/subscription.js +93 -0
- package/vendor/actioncable/subscriptions.js +89 -0
- package/vendor/open-telemetry-idgenerator.js +43 -0
- package/widget/analytics/facebook_tracker.js +8 -0
- package/widget/analytics/google_analytics_tracker.js +83 -0
- package/widget/analytics/google_tag_manager_tracker.js +22 -0
- package/widget/analytics.js +58 -0
- package/widget/api_handler/api_handler.js +730 -0
- package/widget/api_handler/base_api_handler.js +249 -0
- package/widget/booker_intent_tracker.js +391 -0
- package/widget/booker_outcome_tracker.js +329 -0
- package/widget/capture_widget_exceptions.js +150 -0
- package/widget/channel.js +282 -0
- package/widget/composite_experience_adapter.js +101 -0
- package/widget/constants.generated.js +350 -0
- package/widget/constants.js +21 -0
- package/widget/container.js +193 -0
- package/widget/content_activity_emitter.js +36 -0
- package/widget/data360_visitor.js +67 -0
- package/widget/date_provider.js +11 -0
- package/widget/debug_mode_state.js +175 -0
- package/widget/dummy_module.js +9 -0
- package/widget/eloqua_visitor.js +17 -0
- package/widget/form_cta_booker_intent.js +246 -0
- package/widget/hubspot_visitor.js +39 -0
- package/widget/inline_meeting_booker_page.js +90 -0
- package/widget/local_state/abstract_local_state.js +38 -0
- package/widget/local_state/debug_state/abstract_debug_flow.js +29 -0
- package/widget/local_state/debug_state/custom_form_flow.js +14 -0
- package/widget/local_state/debug_state/hubspot_form_flow.js +19 -0
- package/widget/local_state/debug_state/hubspot_v4_form_flow.js +19 -0
- package/widget/local_state/debug_state/marketo_form_flow.js +20 -0
- package/widget/local_state/debug_state/pardot_form_flow.js +18 -0
- package/widget/local_state/debug_state.js +362 -0
- package/widget/local_state/trace_state.js +20 -0
- package/widget/location_provider.js +9 -0
- package/widget/marketo_visitor.js +39 -0
- package/widget/meetings/tracing/buttons_forms_triggering_tracer.js +124 -0
- package/widget/meetings/tracing/spans/button_spans.js +18 -0
- package/widget/meetings/tracing/spans/form_spans.js +11 -0
- package/widget/multimodal_v2/assets_preloader.js +97 -0
- package/widget/multimodal_v2/components/AppLayout.js +93 -0
- package/widget/multimodal_v2/components/CursorOverlay.js +93 -0
- package/widget/multimodal_v2/components/PointerRectOverlay.js +74 -0
- package/widget/multimodal_v2/components/app/Artifact.js +109 -0
- package/widget/multimodal_v2/components/app/Background.js +27 -0
- package/widget/multimodal_v2/components/app/CalendarLoadingContent.js +255 -0
- package/widget/multimodal_v2/components/app/Chat.js +39 -0
- package/widget/multimodal_v2/components/app/CookieConsentModal.js +149 -0
- package/widget/multimodal_v2/components/app/Foreground.js +48 -0
- package/widget/multimodal_v2/components/app/HiddenInput.js +41 -0
- package/widget/multimodal_v2/components/app/Input.js +72 -0
- package/widget/multimodal_v2/components/app/LightboxExperience.js +769 -0
- package/widget/multimodal_v2/components/app/LoadingOverlay.js +97 -0
- package/widget/multimodal_v2/components/app/Main.js +985 -0
- package/widget/multimodal_v2/components/app/MessengerButton.js +160 -0
- package/widget/multimodal_v2/components/app/Multimodal.js +17 -0
- package/widget/multimodal_v2/components/app/OverlayControls.js +79 -0
- package/widget/multimodal_v2/components/app/Preview.js +32 -0
- package/widget/multimodal_v2/components/app/PrivacyDisclosure.js +57 -0
- package/widget/multimodal_v2/components/app/RotateDeviceOverlay.js +70 -0
- package/widget/multimodal_v2/components/app/Toolbar.js +156 -0
- package/widget/multimodal_v2/components/chat/ChatComposer.js +129 -0
- package/widget/multimodal_v2/components/chat/ChatInputForm.js +398 -0
- package/widget/multimodal_v2/components/chat/ColdStartQuestions.js +354 -0
- package/widget/multimodal_v2/components/chat/ComposerErrorBanner.js +62 -0
- package/widget/multimodal_v2/components/chat/PostCallSurvey.js +359 -0
- package/widget/multimodal_v2/components/chat/preview/FieldRequestRenderer.js +41 -0
- package/widget/multimodal_v2/components/chat/preview/PreviewMessageRenderer.js +60 -0
- package/widget/multimodal_v2/components/chat/preview/SharedOfferRenderer.js +143 -0
- package/widget/multimodal_v2/components/chat/preview/TextRenderer.js +27 -0
- package/widget/multimodal_v2/components/chat/preview/TimelinePreview.js +254 -0
- package/widget/multimodal_v2/components/chat/timeline/CalendarEventOfferRenderer.js +103 -0
- package/widget/multimodal_v2/components/chat/timeline/CalendarEventPickRenderer.js +148 -0
- package/widget/multimodal_v2/components/chat/timeline/FieldEntryRenderer.js +84 -0
- package/widget/multimodal_v2/components/chat/timeline/FieldRequestRenderer.js +56 -0
- package/widget/multimodal_v2/components/chat/timeline/InlinePrivacyDisclosure.js +66 -0
- package/widget/multimodal_v2/components/chat/timeline/LinkPreviewCard.js +70 -0
- package/widget/multimodal_v2/components/chat/timeline/MessageEntry.js +88 -0
- package/widget/multimodal_v2/components/chat/timeline/PresentContentRenderer.js +30 -0
- package/widget/multimodal_v2/components/chat/timeline/PresentDeckRenderer.js +279 -0
- package/widget/multimodal_v2/components/chat/timeline/PresentVideoRenderer.js +131 -0
- package/widget/multimodal_v2/components/chat/timeline/ShareContentRenderer.js +59 -0
- package/widget/multimodal_v2/components/chat/timeline/SharedOfferRenderer.js +131 -0
- package/widget/multimodal_v2/components/chat/timeline/SystemRenderer.js +82 -0
- package/widget/multimodal_v2/components/chat/timeline/TextRenderer.js +66 -0
- package/widget/multimodal_v2/components/chat/timeline/Timeline.js +158 -0
- package/widget/multimodal_v2/components/debug/DebugMultimodalPanel.js +327 -0
- package/widget/multimodal_v2/components/decks/index.js +160 -0
- package/widget/multimodal_v2/components/field_request/BooleanField.js +77 -0
- package/widget/multimodal_v2/components/field_request/FieldComponents.js +69 -0
- package/widget/multimodal_v2/components/field_request/Form.js +87 -0
- package/widget/multimodal_v2/components/field_request/MultiPicklistField.js +240 -0
- package/widget/multimodal_v2/components/field_request/PicklistField.js +166 -0
- package/widget/multimodal_v2/components/field_request/SingleLineInputField.js +69 -0
- package/widget/multimodal_v2/components/field_request/TextField.js +37 -0
- package/widget/multimodal_v2/components/field_request/index.js +170 -0
- package/widget/multimodal_v2/components/helpers/AutoScroll.js +37 -0
- package/widget/multimodal_v2/components/helpers/ErrorBoundary.js +53 -0
- package/widget/multimodal_v2/components/helpers/FocusTrapDialog.js +26 -0
- package/widget/multimodal_v2/components/helpers/ImpressionTracker.js +94 -0
- package/widget/multimodal_v2/components/helpers/ListRenderer.js +37 -0
- package/widget/multimodal_v2/components/helpers/Localization.js +76 -0
- package/widget/multimodal_v2/components/helpers/Persisted.js +166 -0
- package/widget/multimodal_v2/components/helpers/RichText.js +358 -0
- package/widget/multimodal_v2/components/helpers/ScreenReaderHeading.js +17 -0
- package/widget/multimodal_v2/components/helpers/Thumbnail.js +190 -0
- package/widget/multimodal_v2/components/helpers/VisuallyHidden.js +41 -0
- package/widget/multimodal_v2/components/helpers/content_click_payloads.js +58 -0
- package/widget/multimodal_v2/components/helpers/useDraggable.js +103 -0
- package/widget/multimodal_v2/components/helpers/useTextOverflow.js +44 -0
- package/widget/multimodal_v2/components/lightbox_gather/index.js +741 -0
- package/widget/multimodal_v2/components/meetings/ArtifactEntryPoint.js +252 -0
- package/widget/multimodal_v2/components/meetings/MeetingAdditionalAttendees.js +325 -0
- package/widget/multimodal_v2/components/meetings/MeetingBookerEntry.js +100 -0
- package/widget/multimodal_v2/components/meetings/MeetingDetailsCard.js +99 -0
- package/widget/multimodal_v2/components/meetings/MeetingErrorBanner.js +62 -0
- package/widget/multimodal_v2/components/meetings/MeetingOfferEmailStep.js +239 -0
- package/widget/multimodal_v2/components/meetings/MeetingOfferFooter.js +104 -0
- package/widget/multimodal_v2/components/meetings/MeetingOfferSelectionStep.js +60 -0
- package/widget/multimodal_v2/components/meetings/MeetingRepHeader.js +222 -0
- package/widget/multimodal_v2/components/meetings/MeetingStepShell.js +92 -0
- package/widget/multimodal_v2/components/meetings/MeetingSummaryRail.js +515 -0
- package/widget/multimodal_v2/components/meetings/MeetingTimeSelector.js +603 -0
- package/widget/multimodal_v2/components/meetings/MonthDatePicker.js +422 -0
- package/widget/multimodal_v2/components/meetings/NavigationButtons.js +76 -0
- package/widget/multimodal_v2/components/meetings/TimeSlotHeader.js +357 -0
- package/widget/multimodal_v2/components/meetings/WeekViewHeader.js +20 -0
- package/widget/multimodal_v2/components/meetings/constants.js +7 -0
- package/widget/multimodal_v2/components/meetings/index.js +47 -0
- package/widget/multimodal_v2/components/meetings/utils.js +328 -0
- package/widget/multimodal_v2/components/multimodal/Audio.js +28 -0
- package/widget/multimodal_v2/components/multimodal/Controls.js +188 -0
- package/widget/multimodal_v2/components/multimodal/LiveVideo.js +63 -0
- package/widget/multimodal_v2/components/multimodal/MultiModalComponent.js +424 -0
- package/widget/multimodal_v2/components/multimodal/MultimodalAvatar.js +36 -0
- package/widget/multimodal_v2/components/multimodal/OrbAvatar.js +326 -0
- package/widget/multimodal_v2/components/multimodal/Status.js +220 -0
- package/widget/multimodal_v2/components/multimodal/VideoAvatar.js +24 -0
- package/widget/multimodal_v2/components/multimodal/VideoPreview.js +114 -0
- package/widget/multimodal_v2/components/multimodal/useAudioLevelMonitoring.js +96 -0
- package/widget/multimodal_v2/components/multimodal/useMultimodal.js +434 -0
- package/widget/multimodal_v2/components/presentations/index.js +372 -0
- package/widget/multimodal_v2/components/shared/Avatar.js +92 -0
- package/widget/multimodal_v2/components/shared/AvatarGroup.js +135 -0
- package/widget/multimodal_v2/components/shared/Button.js +245 -0
- package/widget/multimodal_v2/components/shared/ButtonGroup.js +133 -0
- package/widget/multimodal_v2/components/shared/ComposerForm.js +98 -0
- package/widget/multimodal_v2/components/shared/SpeakingIndicator.js +239 -0
- package/widget/multimodal_v2/components/shared/ThinkingAnimation.js +165 -0
- package/widget/multimodal_v2/components/shared/Tooltip.js +266 -0
- package/widget/multimodal_v2/components/shared/controls/Dropdown.js +79 -0
- package/widget/multimodal_v2/components/shared/controls/PillToggle.js +142 -0
- package/widget/multimodal_v2/components/shared/controls/TextArea.js +114 -0
- package/widget/multimodal_v2/components/shared/toolCallLabels.js +12 -0
- package/widget/multimodal_v2/components/slides/SlidesThumbnail.js +47 -0
- package/widget/multimodal_v2/components/slides/index.js +61 -0
- package/widget/multimodal_v2/constants.js +88 -0
- package/widget/multimodal_v2/host.split-css.js +2 -0
- package/widget/multimodal_v2/host.string.js +96 -0
- package/widget/multimodal_v2/images/icons.js +582 -0
- package/widget/multimodal_v2/images/posters/piper_low_res.jpg +0 -0
- package/widget/multimodal_v2/index.js +23 -0
- package/widget/multimodal_v2/index.panda.js +28 -0
- package/widget/multimodal_v2/index.split-css.panda.js +2 -0
- package/widget/multimodal_v2/inline_meeting_booker.js +182 -0
- package/widget/multimodal_v2/locales/cs.js +196 -0
- package/widget/multimodal_v2/locales/da.js +196 -0
- package/widget/multimodal_v2/locales/de.js +196 -0
- package/widget/multimodal_v2/locales/en.js +196 -0
- package/widget/multimodal_v2/locales/en_AU.js +197 -0
- package/widget/multimodal_v2/locales/en_GB.js +197 -0
- package/widget/multimodal_v2/locales/es.js +197 -0
- package/widget/multimodal_v2/locales/es_LA.js +196 -0
- package/widget/multimodal_v2/locales/fi.js +196 -0
- package/widget/multimodal_v2/locales/fr.js +197 -0
- package/widget/multimodal_v2/locales/fr_CA.js +196 -0
- package/widget/multimodal_v2/locales/id.js +196 -0
- package/widget/multimodal_v2/locales/index.js +48 -0
- package/widget/multimodal_v2/locales/it.js +196 -0
- package/widget/multimodal_v2/locales/ja.js +196 -0
- package/widget/multimodal_v2/locales/ko.js +196 -0
- package/widget/multimodal_v2/locales/nb.js +196 -0
- package/widget/multimodal_v2/locales/nl.js +196 -0
- package/widget/multimodal_v2/locales/pl.js +196 -0
- package/widget/multimodal_v2/locales/pt_BR.js +196 -0
- package/widget/multimodal_v2/locales/ru.js +196 -0
- package/widget/multimodal_v2/locales/sv.js +196 -0
- package/widget/multimodal_v2/locales/th.js +196 -0
- package/widget/multimodal_v2/locales/tr.js +196 -0
- package/widget/multimodal_v2/locales/vi.js +196 -0
- package/widget/multimodal_v2/locales/zh_CN.js +196 -0
- package/widget/multimodal_v2/locales/zh_TW.js +196 -0
- package/widget/multimodal_v2/multimodal.js +633 -0
- package/widget/multimodal_v2/multimodal_channel.js +195 -0
- package/widget/multimodal_v2/signals/active_conversation_signal.js +33 -0
- package/widget/multimodal_v2/signals/allowed_conversation_mode_signal.js +38 -0
- package/widget/multimodal_v2/signals/artifact_signal.js +22 -0
- package/widget/multimodal_v2/signals/layout_signal.js +98 -0
- package/widget/multimodal_v2/signals/messages_signal.js +207 -0
- package/widget/multimodal_v2/signals/ui_state_signal.js +128 -0
- package/widget/multimodal_v2/stable_bundle_src.js +44 -0
- package/widget/multimodal_v2/stores/ai_conversation_store.js +221 -0
- package/widget/multimodal_v2/stores/artifact_store.js +205 -0
- package/widget/multimodal_v2/stores/base_store.js +16 -0
- package/widget/multimodal_v2/stores/call_store.js +770 -0
- package/widget/multimodal_v2/stores/call_ui_adapter.js +225 -0
- package/widget/multimodal_v2/stores/debug_multimodal_scenario_store.js +471 -0
- package/widget/multimodal_v2/stores/decks_store.js +285 -0
- package/widget/multimodal_v2/stores/device_store.js +63 -0
- package/widget/multimodal_v2/stores/docking_store.js +62 -0
- package/widget/multimodal_v2/stores/field_request_store.js +326 -0
- package/widget/multimodal_v2/stores/meeting_store.js +477 -0
- package/widget/multimodal_v2/stores/participant_store.js +73 -0
- package/widget/multimodal_v2/stores/post_call_survey_store.js +160 -0
- package/widget/multimodal_v2/stores/pounce_tracking_store.js +163 -0
- package/widget/multimodal_v2/stores/pounce_tracking_store_v2.js +511 -0
- package/widget/multimodal_v2/stores/presentations_store.js +111 -0
- package/widget/multimodal_v2/stores/root_store.js +1919 -0
- package/widget/multimodal_v2/stores/screen_share_store.js +217 -0
- package/widget/multimodal_v2/stores/slides_store.js +21 -0
- package/widget/multimodal_v2/stores/translation_store.js +185 -0
- package/widget/multimodal_v2/stores/ui_store.js +496 -0
- package/widget/multimodal_v2/stores/waiting_store.js +159 -0
- package/widget/multimodal_v2/stores/website_navigation_store.js +767 -0
- package/widget/multimodal_v2/styled-system/css/conditions.js +34 -0
- package/widget/multimodal_v2/styled-system/css/css.js +48 -0
- package/widget/multimodal_v2/styled-system/css/cva.js +96 -0
- package/widget/multimodal_v2/styled-system/css/cx.js +13 -0
- package/widget/multimodal_v2/styled-system/css/index.js +15 -0
- package/widget/multimodal_v2/styled-system/css/sva.js +69 -0
- package/widget/multimodal_v2/styled-system/helpers.js +384 -0
- package/widget/multimodal_v2/styled-system/jsx/create-style-context.js +96 -0
- package/widget/multimodal_v2/styled-system/jsx/factory-helper.js +19 -0
- package/widget/multimodal_v2/styled-system/jsx/factory.js +111 -0
- package/widget/multimodal_v2/styled-system/jsx/index.js +12 -0
- package/widget/multimodal_v2/styled-system/jsx/is-valid-prop.js +22 -0
- package/widget/multimodal_v2/types.js +105 -0
- package/widget/multimodal_v2/utils/auto_scroller.js +157 -0
- package/widget/multimodal_v2/utils/flip_animation.js +124 -0
- package/widget/multimodal_v2/utils/focus_gate.js +237 -0
- package/widget/multimodal_v2/utils/locale.js +16 -0
- package/widget/multimodal_v2/utils/media_queries.js +30 -0
- package/widget/multimodal_v2/utils/multimodal_cache.js +19 -0
- package/widget/multimodal_v2/utils/mutation_effect.js +14 -0
- package/widget/multimodal_v2/utils/navigation_interceptor.js +205 -0
- package/widget/multimodal_v2/utils/navigation_strategies/dom_swap.js +393 -0
- package/widget/multimodal_v2/utils/navigation_strategies/index.js +12 -0
- package/widget/multimodal_v2/utils/navigation_strategies/lwr.js +61 -0
- package/widget/multimodal_v2/utils/navigation_strategies/navigation_utils.js +46 -0
- package/widget/multimodal_v2/utils/navigation_strategies/next_js.js +24 -0
- package/widget/multimodal_v2/utils/navigation_strategies/wouter_v3.js +15 -0
- package/widget/multimodal_v2/utils/objects_map.js +38 -0
- package/widget/multimodal_v2/utils/perceived_voice_turn_tracker.js +345 -0
- package/widget/multimodal_v2/utils/sanitize_html.js +132 -0
- package/widget/multimodal_v2/utils/signals.js +97 -0
- package/widget/multimodal_v2/utils/slide_zoom.js +114 -0
- package/widget/multimodal_v2/utils/theme_styles.js +137 -0
- package/widget/multimodal_v2/utils/url_observer.js +52 -0
- package/widget/multimodal_v2/utils/voice_onset_detector.js +127 -0
- package/widget/page_mirror.js +89 -0
- package/widget/page_view_activity_emitter.js +71 -0
- package/widget/pardot_visitor.js +137 -0
- package/widget/personalization_observer.js +96 -0
- package/widget/personalizations_config.js +160 -0
- package/widget/qualified_form/constants.js +23 -0
- package/widget/qualified_form/phone_utils.js +38 -0
- package/widget/qualified_form/qualified_form_action.js +91 -0
- package/widget/qualified_form/qualified_form_action_orchestrator.js +21 -0
- package/widget/qualified_form/qualified_form_api.js +471 -0
- package/widget/scroll_disabler.js +109 -0
- package/widget/server-logger.js +156 -0
- package/widget/smart_website_config.js +112 -0
- package/widget/telemetry/context.js +75 -0
- package/widget/telemetry/index.js +16 -0
- package/widget/telemetry/messenger_uptime.js +80 -0
- package/widget/telemetry/metrics.js +120 -0
- package/widget/telemetry/span.js +82 -0
- package/widget/telemetry/telemetry.js +180 -0
- package/widget/telemetry/tracer.js +41 -0
- package/widget/telemetry/tracing_store.js +310 -0
- package/widget/tracker.js +916 -0
- package/widget/utils/native_globals.js +129 -0
- package/widget/v1_adapter.js +50 -0
- package/widget/v2_adapter.js +368 -0
- package/widget/visitor/base_visitor_state.js +11 -0
- package/widget/visitor/cookie_visitor_state.js +128 -0
- package/widget/visitor/in_memory_visitor_state.js +29 -0
- package/widget/visitor/visitor_state.js +384 -0
- package/widget/visitor.js +356 -0
- package/widget/widget/linked_widget_v2.js +227 -0
- package/widget/widget/page_mirror_factory.js +22 -0
- package/widget/widget/sentry.js +130 -0
- package/widget/widget/widget.js +1698 -0
- package/widget/widget.split-css.js +2 -0
- package/widget/widget_bootstrap.js +97 -0
- package/widget/widget_object.js +73 -0
|
@@ -0,0 +1,767 @@
|
|
|
1
|
+
import { __webpack_require__ } from "../../../js/runtime.js";
|
|
2
|
+
import { signals_core_module_d } from "../../../js/multimodal_v2.js";
|
|
3
|
+
import { normalizeToBaseUrl } from "../../../src/url-utils.js";
|
|
4
|
+
import { MULTIMODAL_HOST_ID } from "../constants.js";
|
|
5
|
+
import { isMobile } from "../utils/media_queries.js";
|
|
6
|
+
import { NavigationInterceptor } from "../utils/navigation_interceptor.js";
|
|
7
|
+
import "../utils/navigation_strategies/index.js";
|
|
8
|
+
import { unzoomRect, slideZoomPoint, zoomScaleForBox, slideZoomFocus } from "../utils/slide_zoom.js";
|
|
9
|
+
import { DisplayMode as types_DisplayMode } from "../types.js";
|
|
10
|
+
import "../../utils/native_globals.js";
|
|
11
|
+
import { hexToRgba } from "../utils/theme_styles.js";
|
|
12
|
+
import { isSameOrigin, findElementWithText } from "../utils/navigation_strategies/navigation_utils.js";
|
|
13
|
+
import { wouterV3Strategy as wouter_v3 } from "../utils/navigation_strategies/wouter_v3.js";
|
|
14
|
+
import { lwrStrategy as lwr } from "../utils/navigation_strategies/lwr.js";
|
|
15
|
+
import { nextJsStrategy as next_js } from "../utils/navigation_strategies/next_js.js";
|
|
16
|
+
import { default as dom_swap } from "../utils/navigation_strategies/dom_swap.js";
|
|
17
|
+
|
|
18
|
+
/* provided dependency */ var website_navigation_store_setTimeout = __webpack_require__(68034).pS;
|
|
19
|
+
/* provided dependency */ var website_navigation_store_clearTimeout = __webpack_require__(68034).Kj;
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// Layout constants
|
|
30
|
+
const CURSOR_OFFSET_PX = 14;
|
|
31
|
+
const CURSOR_ELEMENT_OFFSET_PX = 15;
|
|
32
|
+
// Animation timing constants (in milliseconds)
|
|
33
|
+
const HIGHLIGHT_DELAY_MS = 3000;
|
|
34
|
+
// Upper bound for waiting on the smooth scroll to settle. Smooth scrolls
|
|
35
|
+
// can run ~800-1500ms on long pages, and we then need several consecutive
|
|
36
|
+
// stable samples on top of that, so this needs headroom over the raw scroll
|
|
37
|
+
// duration. The cap keeps us from hanging if the page keeps animating
|
|
38
|
+
// (carousels, sticky headers re-laying out, etc.).
|
|
39
|
+
const SCROLL_STABILITY_TIMEOUT_MS = 3500;
|
|
40
|
+
const RECT_STABILITY_POLL_INTERVAL_MS = 100;
|
|
41
|
+
// Five consecutive identical samples (~500ms of stillness) is enough to
|
|
42
|
+
// declare a smooth scroll done without being so eager that mid-scroll
|
|
43
|
+
// pauses get mistaken for the final position.
|
|
44
|
+
const RECT_STABILITY_REQUIRED_SAMPLES = 5;
|
|
45
|
+
const CURSOR_POSITION_DELAY_MS = 500;
|
|
46
|
+
const CURSOR_HIDE_DELAY_MS = 1500;
|
|
47
|
+
// How long the cursor's glide to the target takes — must match the CursorContainer CSS transition
|
|
48
|
+
// (transform 0.8s) so we wait for the cursor to actually arrive before zooming the video in, and so
|
|
49
|
+
// each traced side is drawn in lockstep with the cursor. Kept unhurried so the trace reads calmly.
|
|
50
|
+
const CURSOR_MOVE_DURATION_MS = 800;
|
|
51
|
+
// Per-side duration while the cursor traces (draws) the bounding box — 40% faster than the glide so
|
|
52
|
+
// the box draws snappily. Drives both the cursor's per-leg glide and the border reveal, kept in sync.
|
|
53
|
+
const RECT_TRACE_LEG_MS = Math.round(CURSOR_MOVE_DURATION_MS * 0.6);
|
|
54
|
+
// How long the video stays zoomed in on the target before zooming back out. Comfortably longer than
|
|
55
|
+
// the full trace (5 glides x CURSOR_MOVE_DURATION_MS) so the finished box rests a beat before closing.
|
|
56
|
+
const SLIDE_ZOOM_HOLD_MS = 6500;
|
|
57
|
+
// Padding (viewport px) added around the model's bounding box so the drawn rectangle frames the
|
|
58
|
+
// element with a little breathing room instead of hugging its exact edges.
|
|
59
|
+
const RECT_PADDING_PX = 12;
|
|
60
|
+
// How far off the bottom-right corner the cursor rests once the box is drawn, so it sits beside the
|
|
61
|
+
// finished rectangle rather than on the corner.
|
|
62
|
+
const RECT_REST_OFFSET_PX = 12;
|
|
63
|
+
// Brief pause after showing the cursor at its start position so the browser paints that frame before
|
|
64
|
+
// we move it — otherwise the CSS transform transition has nothing to animate from and it just pops in.
|
|
65
|
+
const CURSOR_GLIDE_START_DELAY_MS = 60;
|
|
66
|
+
const TRANSITION_DURATION_MS = 300;
|
|
67
|
+
// Highlight styling
|
|
68
|
+
const HIGHLIGHT_OPACITY = 0.2;
|
|
69
|
+
const DARK_SURFACE_HIGHLIGHT_OPACITY = 0.25;
|
|
70
|
+
const DARK_SURFACE_LUMINANCE_THRESHOLD = 0.4;
|
|
71
|
+
const DEFAULT_PRIMARY_COLOR = "#1e79ff";
|
|
72
|
+
// Text search retry config
|
|
73
|
+
const FIND_TEXT_MAX_ATTEMPTS = 3;
|
|
74
|
+
const FIND_TEXT_DELAY_MS = 500;
|
|
75
|
+
class WebsiteNavigationStore {
|
|
76
|
+
/**
|
|
77
|
+
* Navigate to a URL and optionally highlight a text snippet.
|
|
78
|
+
* Switches to docked mode to push content left for co-browsing.
|
|
79
|
+
*/ async navigateToContent(message) {
|
|
80
|
+
const wasNavigationInterceptorInitialized = this.navigationInterceptor.initialized;
|
|
81
|
+
try {
|
|
82
|
+
this.navigationInterceptor.dispose();
|
|
83
|
+
if (this.rootStore.displayMode.peek() !== types_DisplayMode.CLOSED) {
|
|
84
|
+
this.rootStore.setDisplayMode(isMobile.value ? types_DisplayMode.CLOSED : types_DisplayMode.DOCKED);
|
|
85
|
+
}
|
|
86
|
+
// Minimize video if maximized so user can see the navigated content,
|
|
87
|
+
// this will also clear the slide if it is maximized with an artifact
|
|
88
|
+
this.rootStore.clearMaximizedState();
|
|
89
|
+
const promises = [];
|
|
90
|
+
// Perform soft navigation if URL is provided
|
|
91
|
+
if (message.url) {
|
|
92
|
+
const postNavigate = await this.navigate(message.url);
|
|
93
|
+
promises.push(postNavigate());
|
|
94
|
+
}
|
|
95
|
+
// Highlight text snippet if provided
|
|
96
|
+
if (message.textSnippet) {
|
|
97
|
+
promises.push(this.highlightText(message.textSnippet));
|
|
98
|
+
}
|
|
99
|
+
await Promise.all(promises);
|
|
100
|
+
} finally{
|
|
101
|
+
if (wasNavigationInterceptorInitialized) {
|
|
102
|
+
this.navigationInterceptor.init();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Highlight a text snippet on the page with a cursor animation.
|
|
108
|
+
* Shows cursor at center, moves to element, then highlights it.
|
|
109
|
+
*/ async highlightText(text) {
|
|
110
|
+
// Give the user a few seconds before highlighting the text snippet
|
|
111
|
+
await this.delay(HIGHLIGHT_DELAY_MS);
|
|
112
|
+
// Show initial cursor in center of the page content (accounting for sidebar)
|
|
113
|
+
this.setCursorPosition({
|
|
114
|
+
x: window.innerWidth / 2 - CURSOR_OFFSET_PX,
|
|
115
|
+
y: window.innerHeight / 2 - CURSOR_OFFSET_PX,
|
|
116
|
+
visible: true
|
|
117
|
+
});
|
|
118
|
+
const foundElement = await findElementWithText(text, {
|
|
119
|
+
maxAttempts: FIND_TEXT_MAX_ATTEMPTS,
|
|
120
|
+
delayMs: FIND_TEXT_DELAY_MS
|
|
121
|
+
});
|
|
122
|
+
if (!foundElement) {
|
|
123
|
+
this.setCursorPosition({
|
|
124
|
+
x: 0,
|
|
125
|
+
y: 0,
|
|
126
|
+
visible: false
|
|
127
|
+
});
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
await this.pointCursorAtElement(foundElement);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Point Piper's cursor at a specific element on the live page (and highlight it), identified by
|
|
134
|
+
* its co-browse node-id. Driven by the point_at_page tool / PointCursor message. Resolves the
|
|
135
|
+
* node-id to the live host element via the Shipper reverse lookup (falls back to text search).
|
|
136
|
+
* Reuses the same cursor + highlight as the share_website flow.
|
|
137
|
+
*/ async pointAtNode(nodeId, text) {
|
|
138
|
+
// A previous point gesture may still have a hide timer pending; cancel it so it can't
|
|
139
|
+
// yank the cursor back to the old spot mid-gesture.
|
|
140
|
+
this.cancelCursorSequenceTimers();
|
|
141
|
+
let element = this.elementForNodeId(nodeId);
|
|
142
|
+
if (!element && text) {
|
|
143
|
+
element = await findElementWithText(text, {
|
|
144
|
+
maxAttempts: FIND_TEXT_MAX_ATTEMPTS,
|
|
145
|
+
delayMs: FIND_TEXT_DELAY_MS
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (!element) {
|
|
149
|
+
this.setCursorPosition({
|
|
150
|
+
x: 0,
|
|
151
|
+
y: 0,
|
|
152
|
+
visible: false
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// Show the cursor near center first so it visibly glides to the target.
|
|
157
|
+
this.setCursorPosition({
|
|
158
|
+
x: window.innerWidth / 2 - CURSOR_OFFSET_PX,
|
|
159
|
+
y: window.innerHeight / 2 - CURSOR_OFFSET_PX,
|
|
160
|
+
visible: true
|
|
161
|
+
});
|
|
162
|
+
// Let the browser paint that start frame before moving. A resolved node-id needs no lookup, so
|
|
163
|
+
// without this pause both positions land in one task and the cursor pops onto the target instead
|
|
164
|
+
// of gliding. Routed through the cursor-sequence set so a newer gesture drops this continuation.
|
|
165
|
+
await this.cursorSequenceDelay(CURSOR_GLIDE_START_DELAY_MS);
|
|
166
|
+
// Don't scroll the visitor's page: marks are only placed on elements already in view, so the
|
|
167
|
+
// target is on-screen and yanking the page would be jarring mid-call.
|
|
168
|
+
await this.pointCursorAtElement(element, {
|
|
169
|
+
scroll: false
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Point Piper's cursor at a spot on the slide image she's currently showing. A slide is an image
|
|
174
|
+
* with no DOM to anchor to, so the model gives normalized [0,1] coordinates and we map them onto
|
|
175
|
+
* the on-screen slide image's rect. Reuses the same cursor overlay as the page/share_website flow.
|
|
176
|
+
*/ async pointAtSlide(normalizedX, normalizedY, box) {
|
|
177
|
+
if (box === void 0) box = null;
|
|
178
|
+
// Cancel any pending hide (and glide continuation) from a previous point gesture: its
|
|
179
|
+
// callback captured the *old* x/y, so letting it fire would jump the cursor back there
|
|
180
|
+
// and hide it while this gesture is still showing.
|
|
181
|
+
this.cancelCursorSequenceTimers();
|
|
182
|
+
const nx = Math.min(1, Math.max(0, normalizedX));
|
|
183
|
+
const ny = Math.min(1, Math.max(0, normalizedY));
|
|
184
|
+
const slide = this.currentSlideElement();
|
|
185
|
+
const measured = slide == null ? void 0 : slide.getBoundingClientRect();
|
|
186
|
+
if (!slide || !measured || measured.width < 1 || measured.height < 1) {
|
|
187
|
+
this.slideZoom.value = null;
|
|
188
|
+
this.pointerTrace.value = null;
|
|
189
|
+
this.setCursorPosition({
|
|
190
|
+
x: 0,
|
|
191
|
+
y: 0,
|
|
192
|
+
visible: false
|
|
193
|
+
});
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
// A previous gesture's zoom may still be applied to the media — its hold hasn't elapsed, or its
|
|
197
|
+
// unzoom transition is still animating — so getBoundingClientRect reports the *zoomed* geometry.
|
|
198
|
+
// Recover the natural rect by inverting that known zoom before mapping the model's fraction onto
|
|
199
|
+
// it (measuring through the live transform would land the point in the wrong place).
|
|
200
|
+
const activeZoom = this.slideZoom.peek();
|
|
201
|
+
const rect = activeZoom ? unzoomRect(measured, activeZoom) : measured;
|
|
202
|
+
// The model's coordinates are fractions of the FRAME it perceives, which is the raw
|
|
203
|
+
// slide/video content (no letterbox). The element renders that content with object-fit:
|
|
204
|
+
// contain, so when the element box isn't the content's aspect ratio the picture is
|
|
205
|
+
// letterboxed inside it. Map onto the actual displayed content box (not the padded element
|
|
206
|
+
// rect) so the cursor lands where the model means — otherwise a non-matching aspect (common
|
|
207
|
+
// for videos) offsets the pointer.
|
|
208
|
+
const content = contentBox(slide, rect);
|
|
209
|
+
const x = content.left + nx * content.width;
|
|
210
|
+
const y = content.top + ny * content.height;
|
|
211
|
+
// Make the cursor glide to the spot rather than pop in. The CSS transform transition only
|
|
212
|
+
// animates if the cursor is already on-screen at a prior position, so if it's hidden we first
|
|
213
|
+
// show it at the viewport center, let the browser paint that frame, then move it to the target.
|
|
214
|
+
if (!this.cursorPosition.peek().visible) {
|
|
215
|
+
this.setCursorPosition({
|
|
216
|
+
x: window.innerWidth / 2 - CURSOR_OFFSET_PX,
|
|
217
|
+
y: window.innerHeight / 2 - CURSOR_OFFSET_PX,
|
|
218
|
+
visible: true
|
|
219
|
+
});
|
|
220
|
+
// Routed through the cursor-sequence set: if another point gesture starts during the
|
|
221
|
+
// glide pause, the promise is dropped and this gesture's continuation never runs.
|
|
222
|
+
await this.cursorSequenceDelay(CURSOR_GLIDE_START_DELAY_MS);
|
|
223
|
+
}
|
|
224
|
+
// Phase 1: glide the cursor to the (un-zoomed) target spot, with no zoom yet.
|
|
225
|
+
this.slideZoom.value = null;
|
|
226
|
+
this.setCursorPosition({
|
|
227
|
+
x,
|
|
228
|
+
y,
|
|
229
|
+
visible: true
|
|
230
|
+
});
|
|
231
|
+
// Size the magnification to the target box: a small box zooms in hard, a wide/tall one stays
|
|
232
|
+
// gentle so it isn't cropped by the zoom window. With no box, fall back to the default scale.
|
|
233
|
+
const scale = box ? zoomScaleForBox(box) : (/* inlined export .SLIDE_ZOOM_SCALE */1.3);
|
|
234
|
+
// Phase 2: once the cursor has reached the spot, zoom the media (slide image OR demo video) in
|
|
235
|
+
// toward it. Both apply slideZoomStyle from `slideZoom` (see components/decks + presentations).
|
|
236
|
+
// Routed through the cursor-sequence delay so a new point gesture starting mid-move drops this.
|
|
237
|
+
await this.cursorSequenceDelay(CURSOR_MOVE_DURATION_MS);
|
|
238
|
+
this.slideZoom.value = {
|
|
239
|
+
x: nx,
|
|
240
|
+
y: ny,
|
|
241
|
+
scale
|
|
242
|
+
};
|
|
243
|
+
// Phase 3: hold the zoom for SLIDE_ZOOM_HOLD_MS, then zoom back out (the cursor returns to the
|
|
244
|
+
// un-zoomed spot as the media unzooms) and hide the cursor + box. Scheduled from zoom-in time,
|
|
245
|
+
// independent of the trace below, so the zoom always lasts the full hold.
|
|
246
|
+
this.scheduleCursorSequenceTimer(()=>{
|
|
247
|
+
this.slideZoom.value = null;
|
|
248
|
+
this.pointerTrace.value = null;
|
|
249
|
+
this.setCursorPosition({
|
|
250
|
+
x,
|
|
251
|
+
y,
|
|
252
|
+
visible: false
|
|
253
|
+
});
|
|
254
|
+
}, SLIDE_ZOOM_HOLD_MS);
|
|
255
|
+
if (box) {
|
|
256
|
+
// Trace the bounding box with the cursor, drawing the border as it goes.
|
|
257
|
+
await this.traceRect(box, {
|
|
258
|
+
x: nx,
|
|
259
|
+
y: ny
|
|
260
|
+
}, content, scale);
|
|
261
|
+
} else {
|
|
262
|
+
// No box: the magnification pans the point toward center, so move the cursor to where it lands
|
|
263
|
+
// (slideZoomFocus) so it stays glued to the target as the media zooms.
|
|
264
|
+
const focus = slideZoomFocus({
|
|
265
|
+
x: nx,
|
|
266
|
+
y: ny
|
|
267
|
+
}, scale);
|
|
268
|
+
this.setCursorPosition({
|
|
269
|
+
x: content.left + focus.x * content.width,
|
|
270
|
+
y: content.top + focus.y * content.height,
|
|
271
|
+
visible: true
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Trace the target's bounding box with the cursor on the zoomed video, drawing the border in the
|
|
277
|
+
* cursor's color as it goes. Each corner is mapped through the same zoom the media applies (so the
|
|
278
|
+
* box frames the zoomed content) and padded outward a little so the box sits just outside the
|
|
279
|
+
* element rather than hugging it. The cursor starts at the bottom-right corner and glides clockwise
|
|
280
|
+
* (BR -> BL -> TL -> TR -> BR) while PointerRectOverlay reveals the border for each side over the
|
|
281
|
+
* same per-side duration, so the line follows the cursor; it then rests just off the bottom-right
|
|
282
|
+
* corner. Every step is a cursor-sequence delay, so a new point gesture cancels the trace cleanly.
|
|
283
|
+
*/ async traceRect(box, focal, content, scale) {
|
|
284
|
+
// Map a normalized content point through the zoom, then to viewport pixels — clamped to the
|
|
285
|
+
// content box so a box larger than the zoom window still traces along the media's edges.
|
|
286
|
+
const toScreen = (px, py)=>{
|
|
287
|
+
const z = slideZoomPoint(focal, {
|
|
288
|
+
x: px,
|
|
289
|
+
y: py
|
|
290
|
+
}, scale);
|
|
291
|
+
return {
|
|
292
|
+
x: content.left + Math.min(1, Math.max(0, z.x)) * content.width,
|
|
293
|
+
y: content.top + Math.min(1, Math.max(0, z.y)) * content.height
|
|
294
|
+
};
|
|
295
|
+
};
|
|
296
|
+
const tlPoint = toScreen(box.x1, box.y1);
|
|
297
|
+
const brPoint = toScreen(box.x2, box.y2);
|
|
298
|
+
// Pad the box outward so the drawn rectangle frames the element with a little breathing room
|
|
299
|
+
// instead of hugging its exact edges (the model's box is very tight).
|
|
300
|
+
const left = tlPoint.x - RECT_PADDING_PX;
|
|
301
|
+
const top = tlPoint.y - RECT_PADDING_PX;
|
|
302
|
+
const width = Math.max(0, brPoint.x - tlPoint.x) + 2 * RECT_PADDING_PX;
|
|
303
|
+
const height = Math.max(0, brPoint.y - tlPoint.y) + 2 * RECT_PADDING_PX;
|
|
304
|
+
// Padded corners the cursor visits.
|
|
305
|
+
const br = {
|
|
306
|
+
x: left + width,
|
|
307
|
+
y: top + height
|
|
308
|
+
};
|
|
309
|
+
const bl = {
|
|
310
|
+
x: left,
|
|
311
|
+
y: top + height
|
|
312
|
+
};
|
|
313
|
+
const tl = {
|
|
314
|
+
x: left,
|
|
315
|
+
y: top
|
|
316
|
+
};
|
|
317
|
+
const tr = {
|
|
318
|
+
x: left + width,
|
|
319
|
+
y: top
|
|
320
|
+
};
|
|
321
|
+
const perimeter = 2 * (width + height) || 1;
|
|
322
|
+
// Cumulative perimeter fraction revealed after each side is drawn, clockwise from the bottom-right:
|
|
323
|
+
// bottom (BR->BL), left (BL->TL), top (TL->TR), right (TR->BR).
|
|
324
|
+
const legs = [
|
|
325
|
+
{
|
|
326
|
+
corner: bl,
|
|
327
|
+
reveal: width / perimeter
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
corner: tl,
|
|
331
|
+
reveal: (width + height) / perimeter
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
corner: tr,
|
|
335
|
+
reveal: (2 * width + height) / perimeter
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
corner: br,
|
|
339
|
+
reveal: 1
|
|
340
|
+
}
|
|
341
|
+
];
|
|
342
|
+
// Show the (undrawn) box and glide the cursor to the bottom-right corner to start the trace.
|
|
343
|
+
this.pointerTrace.value = {
|
|
344
|
+
left,
|
|
345
|
+
top,
|
|
346
|
+
width,
|
|
347
|
+
height,
|
|
348
|
+
reveal: 0,
|
|
349
|
+
transitionMs: 0
|
|
350
|
+
};
|
|
351
|
+
this.setCursorPosition({
|
|
352
|
+
x: br.x,
|
|
353
|
+
y: br.y,
|
|
354
|
+
visible: true
|
|
355
|
+
});
|
|
356
|
+
await this.cursorSequenceDelay(CURSOR_MOVE_DURATION_MS);
|
|
357
|
+
for (const leg of legs){
|
|
358
|
+
this.pointerTrace.value = {
|
|
359
|
+
left,
|
|
360
|
+
top,
|
|
361
|
+
width,
|
|
362
|
+
height,
|
|
363
|
+
reveal: leg.reveal,
|
|
364
|
+
transitionMs: RECT_TRACE_LEG_MS
|
|
365
|
+
};
|
|
366
|
+
// Speed the cursor's glide to match the faster border reveal so the two stay in lockstep.
|
|
367
|
+
this.setCursorPosition({
|
|
368
|
+
x: leg.corner.x,
|
|
369
|
+
y: leg.corner.y,
|
|
370
|
+
visible: true,
|
|
371
|
+
transitionMs: RECT_TRACE_LEG_MS
|
|
372
|
+
});
|
|
373
|
+
// Sequential by design: each side is drawn only after the cursor finishes the previous one.
|
|
374
|
+
// eslint-disable-next-line no-await-in-loop
|
|
375
|
+
await this.cursorSequenceDelay(RECT_TRACE_LEG_MS);
|
|
376
|
+
}
|
|
377
|
+
// Rest the cursor just off the bottom-right corner so it sits beside the finished box, not on it.
|
|
378
|
+
this.setCursorPosition({
|
|
379
|
+
x: br.x + RECT_REST_OFFSET_PX,
|
|
380
|
+
y: br.y + RECT_REST_OFFSET_PX,
|
|
381
|
+
visible: true
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* The on-screen element the agent is pointing at — a slide image (deck or single slide) or the
|
|
386
|
+
* demo video currently playing — looked up inside the multimodal widget's shadow root. Its
|
|
387
|
+
* viewport rect is what we map the normalized [0,1] point coordinates onto. Only one of these is
|
|
388
|
+
* ever mounted at a time (the artifact overlay shows a single thing), so first-match is correct.
|
|
389
|
+
*/ currentSlideElement() {
|
|
390
|
+
const host = document.getElementById(MULTIMODAL_HOST_ID);
|
|
391
|
+
const root = host == null ? void 0 : host.shadowRoot;
|
|
392
|
+
if (!root) return null;
|
|
393
|
+
// Slides are plain styled elements, so we match their data-component-name. The demo video is a
|
|
394
|
+
// <Persisted> element, which applies attributes as JS properties (not DOM attributes) — so
|
|
395
|
+
// data-component-name isn't queryable on it. Its id ("presentation-video") IS a reflected DOM
|
|
396
|
+
// attribute, so we target the video by id instead.
|
|
397
|
+
return root.querySelector('[data-component-name="Deck.SlideImage"], [data-component-name="Slide.SlideImage"], #presentation-video');
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Resolve a co-browse node-id to the live host-page element. The Shipper (running because a call
|
|
401
|
+
* with page perception is active) exposes the reverse lookup on the host window. Returns null when
|
|
402
|
+
* unavailable or when the node isn't an element.
|
|
403
|
+
*/ elementForNodeId(nodeId) {
|
|
404
|
+
var _ref;
|
|
405
|
+
if (nodeId == null) return null;
|
|
406
|
+
const lookup = window.__qlfdNodeForId;
|
|
407
|
+
const node = (_ref = lookup == null ? void 0 : lookup(nodeId)) != null ? _ref : null;
|
|
408
|
+
if (!node) return null;
|
|
409
|
+
const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
410
|
+
return el != null ? el : null;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Scroll an element into view, land the cursor on it, and highlight it. Shared by the
|
|
414
|
+
* share_website text flow (highlightText) and the point_at_page node-id flow (pointAtNode).
|
|
415
|
+
*/ async pointCursorAtElement(element, param) {
|
|
416
|
+
let { scroll = true } = param === void 0 ? {} : param;
|
|
417
|
+
// Cancel any highlight/hide cascade still pending from a previous point gesture so its
|
|
418
|
+
// stale hide (captured at the old coordinates) can't fire during this one.
|
|
419
|
+
this.cancelCursorSequenceTimers();
|
|
420
|
+
// Detect surface darkness up front so the cursor can pick a contrasting color before it lands.
|
|
421
|
+
const onDarkSurface = this.isOnDarkSurface(element);
|
|
422
|
+
let rect;
|
|
423
|
+
if (scroll) {
|
|
424
|
+
element.scrollIntoView({
|
|
425
|
+
behavior: "smooth",
|
|
426
|
+
block: "center",
|
|
427
|
+
inline: "nearest"
|
|
428
|
+
});
|
|
429
|
+
// Wait for the smooth scroll to settle before measuring, so the cursor lands accurately.
|
|
430
|
+
rect = await this.waitForStableRect(element);
|
|
431
|
+
} else {
|
|
432
|
+
// No scroll: the element is already in view, so measure it where it is.
|
|
433
|
+
rect = element.getBoundingClientRect();
|
|
434
|
+
}
|
|
435
|
+
// Move cursor to bottom right of the element.
|
|
436
|
+
this.setCursorPosition({
|
|
437
|
+
x: rect.right - CURSOR_ELEMENT_OFFSET_PX,
|
|
438
|
+
y: rect.bottom - CURSOR_ELEMENT_OFFSET_PX,
|
|
439
|
+
visible: true,
|
|
440
|
+
onDarkSurface
|
|
441
|
+
});
|
|
442
|
+
// After cursor arrives, highlight the element, then hide the cursor shortly after.
|
|
443
|
+
this.scheduleCursorSequenceTimer(()=>{
|
|
444
|
+
this.applyHighlight(element);
|
|
445
|
+
this.scheduleCursorSequenceTimer(()=>{
|
|
446
|
+
this.setCursorPosition({
|
|
447
|
+
x: rect.right - CURSOR_ELEMENT_OFFSET_PX,
|
|
448
|
+
y: rect.bottom - CURSOR_ELEMENT_OFFSET_PX,
|
|
449
|
+
visible: false,
|
|
450
|
+
onDarkSurface
|
|
451
|
+
});
|
|
452
|
+
}, CURSOR_HIDE_DELAY_MS);
|
|
453
|
+
}, CURSOR_POSITION_DELAY_MS);
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Set the cursor position for the co-browsing overlay.
|
|
457
|
+
*/ setCursorPosition(position) {
|
|
458
|
+
this.cursorPosition.value = position;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Initialize navigation interception to handle user-initiated link clicks.
|
|
462
|
+
* Uses the Navigation API on Chromium browsers, falls back to click capture
|
|
463
|
+
* on Firefox/Safari until they implement the Navigation API.
|
|
464
|
+
*
|
|
465
|
+
* Should be called when entering voice/video mode.
|
|
466
|
+
*/ initNavigationInterceptor() {
|
|
467
|
+
const strategy = this.navigationStrategies.find((s)=>s.isApplicable());
|
|
468
|
+
if (!strategy || strategy.needsInterceptor) {
|
|
469
|
+
this.navigationInterceptor.init();
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Dispose of the navigation interceptor and remove event listeners.
|
|
474
|
+
* Should be called when leaving voice/video mode.
|
|
475
|
+
*/ disposeNavigationInterceptor() {
|
|
476
|
+
this.navigationInterceptor.dispose();
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Dispose of the store by clearing all active timers and removing event listeners.
|
|
480
|
+
* Should be called when the store is no longer needed.
|
|
481
|
+
*/ dispose() {
|
|
482
|
+
this.clearAllTimers();
|
|
483
|
+
this.slideZoom.value = null;
|
|
484
|
+
this.pointerTrace.value = null;
|
|
485
|
+
this.navigationInterceptor.dispose();
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Navigate to a URL using the best available strategy.
|
|
489
|
+
* @returns Post-navigation callback if any cleanup is needed (e.g., run scripts)
|
|
490
|
+
* @throws If no strategy can handle it (e.g., cross-origin URL)
|
|
491
|
+
*/ async navigate(url) {
|
|
492
|
+
const target = new URL(url, window.location.origin);
|
|
493
|
+
const strategy = this.navigationStrategies.find((s)=>s.isApplicable());
|
|
494
|
+
if (!strategy || !isSameOrigin(target)) {
|
|
495
|
+
throw new Error("No navigation strategy can handle URL: " + url);
|
|
496
|
+
}
|
|
497
|
+
const postNavigate = await strategy.navigate(target);
|
|
498
|
+
return async ()=>{
|
|
499
|
+
await (postNavigate == null ? void 0 : postNavigate());
|
|
500
|
+
this.rootStore.dockingStore.reEvaluate();
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Schedule a timer and track it for cleanup.
|
|
505
|
+
*/ scheduleTimer(callback, delay) {
|
|
506
|
+
const timerId = website_navigation_store_setTimeout(callback, delay);
|
|
507
|
+
this.activeTimerIds.add(timerId);
|
|
508
|
+
return timerId;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Schedule a timer belonging to the current cursor point/highlight/hide gesture.
|
|
512
|
+
* Cancelled wholesale by `cancelCursorSequenceTimers()` when a new gesture starts,
|
|
513
|
+
* and by `clearAllTimers()` on dispose.
|
|
514
|
+
*/ scheduleCursorSequenceTimer(callback, delay) {
|
|
515
|
+
const timerId = this.scheduleTimer(()=>{
|
|
516
|
+
this.activeTimerIds.delete(timerId);
|
|
517
|
+
this.cursorSequenceTimerIds.delete(timerId);
|
|
518
|
+
callback();
|
|
519
|
+
}, delay);
|
|
520
|
+
this.cursorSequenceTimerIds.add(timerId);
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Like `delay()`, but the timer is part of the current cursor gesture: if a new
|
|
524
|
+
* gesture starts (or the store is disposed) before it elapses, the promise is left
|
|
525
|
+
* unresolved and the awaiting continuation is dropped along with the stale gesture.
|
|
526
|
+
*/ cursorSequenceDelay(ms) {
|
|
527
|
+
return new Promise((resolve)=>{
|
|
528
|
+
this.scheduleCursorSequenceTimer(resolve, ms);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Cancel all timers belonging to the previous cursor gesture (see
|
|
533
|
+
* `cursorSequenceTimerIds`).
|
|
534
|
+
*/ cancelCursorSequenceTimers() {
|
|
535
|
+
for (const timerId of this.cursorSequenceTimerIds){
|
|
536
|
+
website_navigation_store_clearTimeout(timerId);
|
|
537
|
+
this.activeTimerIds.delete(timerId);
|
|
538
|
+
}
|
|
539
|
+
this.cursorSequenceTimerIds.clear();
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Clear all active timers.
|
|
543
|
+
*/ clearAllTimers() {
|
|
544
|
+
for (const timerId of this.activeTimerIds){
|
|
545
|
+
website_navigation_store_clearTimeout(timerId);
|
|
546
|
+
}
|
|
547
|
+
this.activeTimerIds.clear();
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Create a delay promise that can be used with async/await.
|
|
551
|
+
*/ delay(ms) {
|
|
552
|
+
return new Promise((resolve)=>{
|
|
553
|
+
const timerId = this.scheduleTimer(()=>{
|
|
554
|
+
this.activeTimerIds.delete(timerId);
|
|
555
|
+
resolve();
|
|
556
|
+
}, ms);
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
applyHighlight(element) {
|
|
560
|
+
const isDark = this.isOnDarkSurface(element);
|
|
561
|
+
const baseColor = isDark ? this.getThemeVar("--q-lighter-primary-color") : this.getThemeVar("--q-primary-color");
|
|
562
|
+
const alpha = isDark ? DARK_SURFACE_HIGHLIGHT_OPACITY : HIGHLIGHT_OPACITY;
|
|
563
|
+
element.style.backgroundColor = hexToRgba(baseColor, alpha);
|
|
564
|
+
element.style.transition = "background-color " + TRANSITION_DURATION_MS + "ms ease-in-out";
|
|
565
|
+
}
|
|
566
|
+
getThemeVar(name, fallback) {
|
|
567
|
+
if (fallback === void 0) fallback = DEFAULT_PRIMARY_COLOR;
|
|
568
|
+
const host = document.getElementById(MULTIMODAL_HOST_ID);
|
|
569
|
+
return ((host == null ? void 0 : host.style.getPropertyValue(name)) || getComputedStyle(host || document.documentElement).getPropertyValue(name) || fallback).trim();
|
|
570
|
+
}
|
|
571
|
+
// Light text (high luminance) implies a dark background.
|
|
572
|
+
isOnDarkSurface(element) {
|
|
573
|
+
const textColor = this.extractTextColor(element);
|
|
574
|
+
if (textColor) return this.relativeLuminance(textColor) > 1 - DARK_SURFACE_LUMINANCE_THRESHOLD;
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
extractTextColor(element) {
|
|
578
|
+
const { color } = getComputedStyle(element);
|
|
579
|
+
if (!color) return null;
|
|
580
|
+
const match = color.match(/rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)/);
|
|
581
|
+
if (!match) return null;
|
|
582
|
+
return [
|
|
583
|
+
parseInt(match[1], 10),
|
|
584
|
+
parseInt(match[2], 10),
|
|
585
|
+
parseInt(match[3], 10)
|
|
586
|
+
];
|
|
587
|
+
}
|
|
588
|
+
relativeLuminance(param) {
|
|
589
|
+
let [r, g, b] = param;
|
|
590
|
+
const toLinear = (c)=>{
|
|
591
|
+
const s = c / 255;
|
|
592
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
593
|
+
};
|
|
594
|
+
return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Perform soft navigation to a URL.
|
|
598
|
+
* Updates history, fetches the page, and swaps the DOM.
|
|
599
|
+
* This is passed to NavigationInterceptor for user-initiated navigation.
|
|
600
|
+
*/ async navigateSoftly(url, options) {
|
|
601
|
+
if (options === void 0) options = {};
|
|
602
|
+
const { history = "push", scroll = "top" } = options;
|
|
603
|
+
try {
|
|
604
|
+
const postNavigate = await this.navigate(url);
|
|
605
|
+
// Update history if needed (for fallback mode where we manage history ourselves)
|
|
606
|
+
if (history === "push") {
|
|
607
|
+
window.history.pushState({
|
|
608
|
+
__live: true
|
|
609
|
+
}, "", url);
|
|
610
|
+
} else if (history === "replace") {
|
|
611
|
+
window.history.replaceState({
|
|
612
|
+
__live: true
|
|
613
|
+
}, "", url);
|
|
614
|
+
}
|
|
615
|
+
// Run post-navigation
|
|
616
|
+
await postNavigate();
|
|
617
|
+
// Notify the backend so the multimodal agent knows the visitor navigated.
|
|
618
|
+
// Use window.location.href (not the original url) to capture the final URL after any redirects.
|
|
619
|
+
this.notifyPageNavigation(window.location.href);
|
|
620
|
+
// Scroll to top if requested
|
|
621
|
+
if (scroll === "top") {
|
|
622
|
+
window.scrollTo(0, 0);
|
|
623
|
+
}
|
|
624
|
+
} catch (unused) {
|
|
625
|
+
// If soft navigation fails, fall back to hard navigation
|
|
626
|
+
window.location.href = url;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Notify the backend that the visitor navigated to a new page.
|
|
631
|
+
* Deduplicates by comparing against the last notified URL.
|
|
632
|
+
*/ notifyPageNavigation(url) {
|
|
633
|
+
const normalizedUrl = normalizeToBaseUrl(url);
|
|
634
|
+
// Skip if this URL was already reported
|
|
635
|
+
if (normalizedUrl === this.lastNotifiedUrl) return;
|
|
636
|
+
this.lastNotifiedUrl = normalizedUrl;
|
|
637
|
+
this.rootStore.channel.perform("notify_page_navigation", {
|
|
638
|
+
url: normalizedUrl
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Resolve once the element's rect has been unchanged for ~500ms,
|
|
643
|
+
* or with the latest rect after `timeoutMs` so callers never hang.
|
|
644
|
+
*
|
|
645
|
+
* The polling timers are routed through `scheduleTimer` so `dispose()` /
|
|
646
|
+
* `clearAllTimers()` can cancel them. If the store is disposed before the
|
|
647
|
+
* watcher settles, no further DOM reads happen and the promise is left
|
|
648
|
+
* unresolved (matching `delay()`'s existing semantics) — the awaiting
|
|
649
|
+
* caller's continuation is dropped along with the rest of the store.
|
|
650
|
+
*/ waitForStableRect(element, timeoutMs) {
|
|
651
|
+
if (timeoutMs === void 0) timeoutMs = SCROLL_STABILITY_TIMEOUT_MS;
|
|
652
|
+
return new Promise((resolve)=>{
|
|
653
|
+
const startTime = performance.now();
|
|
654
|
+
let stableCount = 0;
|
|
655
|
+
let prevRect = element.getBoundingClientRect();
|
|
656
|
+
const scheduleTick = ()=>{
|
|
657
|
+
const timerId = this.scheduleTimer(()=>{
|
|
658
|
+
this.activeTimerIds.delete(timerId);
|
|
659
|
+
tick();
|
|
660
|
+
}, RECT_STABILITY_POLL_INTERVAL_MS);
|
|
661
|
+
};
|
|
662
|
+
const tick = ()=>{
|
|
663
|
+
const newRect = element.getBoundingClientRect();
|
|
664
|
+
const isStable = newRect.top === prevRect.top && newRect.left === prevRect.left && newRect.right === prevRect.right && newRect.bottom === prevRect.bottom;
|
|
665
|
+
if (isStable) {
|
|
666
|
+
stableCount += 1;
|
|
667
|
+
if (stableCount >= RECT_STABILITY_REQUIRED_SAMPLES) {
|
|
668
|
+
resolve(newRect);
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
} else {
|
|
672
|
+
// A single moving sample resets the streak so we only resolve on
|
|
673
|
+
// truly consecutive stable frames (smooth scrolls can briefly
|
|
674
|
+
// pause mid-motion and we don't want to call those "settled").
|
|
675
|
+
stableCount = 0;
|
|
676
|
+
}
|
|
677
|
+
if (performance.now() - startTime >= timeoutMs) {
|
|
678
|
+
// Timed out — fall through with the latest rect rather than hang
|
|
679
|
+
// forever on a page that never stops animating.
|
|
680
|
+
resolve(newRect);
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
prevRect = newRect;
|
|
684
|
+
scheduleTick();
|
|
685
|
+
};
|
|
686
|
+
scheduleTick();
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
// eslint-disable-next-line no-useless-constructor
|
|
690
|
+
constructor(rootStore){
|
|
691
|
+
this.rootStore = rootStore;
|
|
692
|
+
this.cursorPosition = signals_core_module_d({
|
|
693
|
+
x: 0,
|
|
694
|
+
y: 0,
|
|
695
|
+
visible: false
|
|
696
|
+
});
|
|
697
|
+
// Focal point (normalized [0,1] within the media element) the on-screen slide/video should zoom
|
|
698
|
+
// toward while the cursor points, or null for no zoom, plus the magnification to apply (chosen from
|
|
699
|
+
// the target box so a small target zooms in hard and a wide one stays gentle — see zoomScaleForBox).
|
|
700
|
+
// The media components read this and apply slideZoomStyle so the media zooms in place.
|
|
701
|
+
this.slideZoom = signals_core_module_d(null);
|
|
702
|
+
// Bounding box (viewport pixels) the cursor is tracing on the zoomed video, or null when not
|
|
703
|
+
// tracing. `reveal` is the fraction of the perimeter drawn so far and `transitionMs` how long to
|
|
704
|
+
// animate to it; the PointerRectOverlay draws the border in sync with the cursor's glide. See
|
|
705
|
+
// pointAtSlide -> traceRect.
|
|
706
|
+
this.pointerTrace = signals_core_module_d(null);
|
|
707
|
+
// Navigation interceptor for handling user-initiated link clicks
|
|
708
|
+
this.navigationInterceptor = new NavigationInterceptor(this.navigateSoftly.bind(this));
|
|
709
|
+
// Tracks the last URL sent to the backend to avoid duplicate notifications
|
|
710
|
+
this.lastNotifiedUrl = null;
|
|
711
|
+
// Order matters - first match wins. SPA-router strategies come before
|
|
712
|
+
// dom_swap since dom_swap is a brute-force fallback that re-executes the
|
|
713
|
+
// page's bootstrap scripts and breaks on frameworks that freeze globals.
|
|
714
|
+
this.navigationStrategies = [
|
|
715
|
+
wouter_v3,
|
|
716
|
+
lwr,
|
|
717
|
+
next_js,
|
|
718
|
+
// Always last as a fallback
|
|
719
|
+
dom_swap
|
|
720
|
+
];
|
|
721
|
+
this.activeTimerIds = new Set();
|
|
722
|
+
/**
|
|
723
|
+
* Timers driving the *current* point/highlight/hide cursor gesture (a subset of
|
|
724
|
+
* `activeTimerIds`). Each new point gesture cancels these so a stale hide timer —
|
|
725
|
+
* whose callback captured the previous gesture's coordinates — can't jump the
|
|
726
|
+
* cursor back and hide it mid-gesture.
|
|
727
|
+
*/ this.cursorSequenceTimerIds = new Set();
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* The rect of the actual displayed content inside an element that renders intrinsic media with
|
|
733
|
+
* `object-fit: contain` — accounting for letterbox bars when the element box and the content have
|
|
734
|
+
* different aspect ratios (e.g. a 16:9 video in a taller box). Falls back to the full element rect
|
|
735
|
+
* when the intrinsic size is unknown (metadata not loaded yet) or the element isn't a video/image,
|
|
736
|
+
* so a slide image that fills its box is unaffected.
|
|
737
|
+
*/ function contentBox(el, rect) {
|
|
738
|
+
let intrinsicW = 0;
|
|
739
|
+
let intrinsicH = 0;
|
|
740
|
+
if (el instanceof HTMLVideoElement) {
|
|
741
|
+
intrinsicW = el.videoWidth;
|
|
742
|
+
intrinsicH = el.videoHeight;
|
|
743
|
+
} else if (el instanceof HTMLImageElement) {
|
|
744
|
+
intrinsicW = el.naturalWidth;
|
|
745
|
+
intrinsicH = el.naturalHeight;
|
|
746
|
+
}
|
|
747
|
+
if (intrinsicW < 1 || intrinsicH < 1) {
|
|
748
|
+
return {
|
|
749
|
+
left: rect.left,
|
|
750
|
+
top: rect.top,
|
|
751
|
+
width: rect.width,
|
|
752
|
+
height: rect.height
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
const scale = Math.min(rect.width / intrinsicW, rect.height / intrinsicH);
|
|
756
|
+
const width = intrinsicW * scale;
|
|
757
|
+
const height = intrinsicH * scale;
|
|
758
|
+
return {
|
|
759
|
+
left: rect.left + (rect.width - width) / 2,
|
|
760
|
+
top: rect.top + (rect.height - height) / 2,
|
|
761
|
+
width,
|
|
762
|
+
height
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
export { CURSOR_MOVE_DURATION_MS, RECT_TRACE_LEG_MS, SLIDE_ZOOM_HOLD_MS };
|
|
767
|
+
export default WebsiteNavigationStore;
|