@syntrologie/runtime-sdk 2.14.0 → 2.16.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.
Files changed (74) hide show
  1. package/README.md +1 -0
  2. package/dist/SmartCanvasApp.d.ts +4 -1
  3. package/dist/SmartCanvasElementLit.d.ts +166 -0
  4. package/dist/actions/schema.js +4 -3
  5. package/dist/actions/types.d.ts +8 -2
  6. package/dist/anchor/AnchorResolver.d.ts +1 -0
  7. package/dist/api-lit.d.ts +84 -0
  8. package/dist/api.d.ts +3 -0
  9. package/dist/apps/builtinRuntimeModules-lit.d.ts +20 -0
  10. package/dist/bootstrap-init.d.ts +2 -0
  11. package/dist/bootstrap-types.d.ts +10 -0
  12. package/dist/chunk-2IQ2PTLJ.js +871 -0
  13. package/dist/chunk-2IQ2PTLJ.js.map +7 -0
  14. package/dist/{chunk-YLLWLUQX.js → chunk-4HXPGXUC.js} +1 -16
  15. package/dist/{chunk-YLLWLUQX.js.map → chunk-4HXPGXUC.js.map} +1 -1
  16. package/dist/{chunk-IR6UOR63.js → chunk-GX7BBYX6.js} +2 -2
  17. package/dist/chunk-JMHRHAEL.js +18 -0
  18. package/dist/chunk-JMHRHAEL.js.map +7 -0
  19. package/dist/{chunk-JCDCANR7.js → chunk-NVV7IWJC.js} +1301 -1084
  20. package/dist/chunk-NVV7IWJC.js.map +7 -0
  21. package/dist/{chunk-77TNZ66J.js → chunk-XVRDKBYF.js} +3 -3
  22. package/dist/components/SyntroCanvasOverlay.d.ts +100 -0
  23. package/dist/components/SyntroDrawer.d.ts +110 -0
  24. package/dist/components/SyntroLauncher.d.ts +105 -0
  25. package/dist/components/SyntroTileCard.d.ts +74 -0
  26. package/dist/components/SyntroTileWheel.d.ts +51 -0
  27. package/dist/config/schema.js +3 -2
  28. package/dist/controllers/DecisionController.d.ts +48 -0
  29. package/dist/controllers/NotificationsController.d.ts +59 -0
  30. package/dist/controllers/RuntimeController.d.ts +52 -0
  31. package/dist/controllers/RuntimeEventsController.d.ts +42 -0
  32. package/dist/controllers/ThemeController.d.ts +110 -0
  33. package/dist/controllers/index.d.ts +13 -0
  34. package/dist/decisions/schema.js +2 -1
  35. package/dist/decisions/types.d.ts +4 -0
  36. package/dist/editorLoader.d.ts +5 -0
  37. package/dist/index-lit.d.ts +40 -0
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.js +1338 -19
  40. package/dist/index.js.map +4 -4
  41. package/dist/interop/LitInReact.d.ts +27 -0
  42. package/dist/interop/ReactInLit.d.ts +42 -0
  43. package/dist/interop/index.d.ts +7 -0
  44. package/dist/metrics/sessionMetrics.d.ts +4 -0
  45. package/dist/notifications/SyntroToastStack.d.ts +43 -0
  46. package/dist/platform/PlatformAdapter.d.ts +46 -0
  47. package/dist/platform/ShopifyAdapter.d.ts +36 -0
  48. package/dist/platform/ShopifyAnchorResolver.d.ts +31 -0
  49. package/dist/platform/ShopifyAntiFlicker.d.ts +21 -0
  50. package/dist/platform/ShopifyPixelBridge.d.ts +37 -0
  51. package/dist/platform/detect.d.ts +9 -0
  52. package/dist/platform/index.d.ts +10 -0
  53. package/dist/platform/shopify-cookie-contract.d.ts +39 -0
  54. package/dist/react-compat.d.ts +114 -0
  55. package/dist/react.js +6 -4
  56. package/dist/react.js.map +1 -1
  57. package/dist/shopify-pixel-entry.d.ts +68 -0
  58. package/dist/shopify-pixel.js +77 -0
  59. package/dist/shopify-pixel.js.map +7 -0
  60. package/dist/shopify-pixel.min.js +2 -0
  61. package/dist/shopify-pixel.min.js.map +7 -0
  62. package/dist/smart-canvas.esm.js +856 -240
  63. package/dist/smart-canvas.esm.js.map +4 -4
  64. package/dist/smart-canvas.js +28769 -37080
  65. package/dist/smart-canvas.js.map +4 -4
  66. package/dist/smart-canvas.min.js +855 -240
  67. package/dist/smart-canvas.min.js.map +4 -4
  68. package/dist/theme/index.js +30 -0
  69. package/dist/theme/index.js.map +7 -0
  70. package/dist/version.d.ts +1 -1
  71. package/package.json +10 -1
  72. package/dist/chunk-JCDCANR7.js.map +0 -7
  73. /package/dist/{chunk-IR6UOR63.js.map → chunk-GX7BBYX6.js.map} +0 -0
  74. /package/dist/{chunk-77TNZ66J.js.map → chunk-XVRDKBYF.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  ANIMATION_KEYFRAMES,
3
3
  AppRegistry,
4
+ COOKIE_NAME,
4
5
  CanvasEvents,
5
6
  ContextManager,
6
7
  DEFAULT_COOLDOWN,
@@ -21,6 +22,9 @@ import {
21
22
  SessionMetricTracker,
22
23
  ShadowCanvasOverlay,
23
24
  ShadowRootProvider,
25
+ ShopifyAdapter,
26
+ ShopifyAntiFlicker,
27
+ ShopifyPixelBridge,
24
28
  SmartCanvasApp,
25
29
  SmartCanvasController,
26
30
  SmartCanvasElement,
@@ -31,7 +35,6 @@ import {
31
35
  WidgetRegistry,
32
36
  appRegistry,
33
37
  applyStaticSlotStyles,
34
- base,
35
38
  cleanupAppContext,
36
39
  createActionEngine,
37
40
  createAnchorResolver,
@@ -54,6 +57,7 @@ import {
54
57
  createSurfaceContainer,
55
58
  createSurfaces,
56
59
  decodeToken,
60
+ detectPlatform,
57
61
  encodeToken,
58
62
  evaluate,
59
63
  evaluateCondition,
@@ -76,8 +80,6 @@ import {
76
80
  normalizePostHogEvent,
77
81
  playEnterAnimation,
78
82
  playExitAnimation,
79
- purple,
80
- red,
81
83
  registerConfigPredicates,
82
84
  registerSmartCanvasElement,
83
85
  resolveConfigUri,
@@ -86,7 +88,6 @@ import {
86
88
  setupAdjacentPositioning,
87
89
  setupInlinePositioning,
88
90
  shouldNormalizeEvent,
89
- slateGrey,
90
91
  useDecision,
91
92
  useNotifications,
92
93
  useNotifyWatcher,
@@ -104,7 +105,13 @@ import {
104
105
  validateEventName,
105
106
  validateProps,
106
107
  widgetRegistry
107
- } from "./chunk-JCDCANR7.js";
108
+ } from "./chunk-NVV7IWJC.js";
109
+ import {
110
+ base,
111
+ purple,
112
+ red,
113
+ slateGrey
114
+ } from "./chunk-2IQ2PTLJ.js";
108
115
  import {
109
116
  AddClassZ,
110
117
  AnchorIdZ,
@@ -138,8 +145,8 @@ import {
138
145
  WaitZ,
139
146
  WidgetConfigZ,
140
147
  coreActionStepSchemas
141
- } from "./chunk-77TNZ66J.js";
142
- import "./chunk-IR6UOR63.js";
148
+ } from "./chunk-XVRDKBYF.js";
149
+ import "./chunk-GX7BBYX6.js";
143
150
  import {
144
151
  ActivationConfigZ,
145
152
  AnchorVisibleConditionZ,
@@ -164,12 +171,14 @@ import {
164
171
  StateEqualsConditionZ,
165
172
  TriggerWhenZ,
166
173
  ViewportConditionZ,
167
- __publicField,
168
174
  decisionSchemas,
169
175
  validateActivationConfig,
170
176
  validateCondition,
171
177
  validateStrategy
172
- } from "./chunk-YLLWLUQX.js";
178
+ } from "./chunk-4HXPGXUC.js";
179
+ import {
180
+ __publicField
181
+ } from "./chunk-JMHRHAEL.js";
173
182
 
174
183
  // src/index.ts
175
184
  import React4 from "react";
@@ -506,6 +515,342 @@ var ChatAssistantMountableWidget = {
506
515
  }
507
516
  };
508
517
 
518
+ // ../adaptives/adaptive-chatbot/dist/ChatAssistantLit.js
519
+ import { html, LitElement, nothing } from "lit";
520
+ import { styleMap } from "lit/directives/style-map.js";
521
+ var __classPrivateFieldGet = function(receiver, state, kind, f) {
522
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
523
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
524
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
525
+ };
526
+ var __classPrivateFieldSet = function(receiver, state, value, kind, f) {
527
+ if (kind === "m") throw new TypeError("Private method is not writable");
528
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
529
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
530
+ return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
531
+ };
532
+ var _ChatAssistantElement_instances;
533
+ var _ChatAssistantElement_batchHandle;
534
+ var _ChatAssistantElement_inputEl;
535
+ var _ChatAssistantElement_messageListEl;
536
+ var _ChatAssistantElement_renderBubble;
537
+ var _ChatAssistantElement_handleSubmit;
538
+ var _ChatAssistantElement_sendMessage;
539
+ var TOKEN_PURPLE_4 = "#6a59ce";
540
+ var TOKEN_WHITE = "#ffffff";
541
+ var TOKEN_SLATE_10 = "#cbd0d7";
542
+ var TOKEN_SLATE_12 = "#f6f7f9";
543
+ var TOKEN_SLATE_8 = "#87919f";
544
+ var TOKEN_RED_4 = "#ff2524";
545
+ var _nextId = 0;
546
+ function generateId2() {
547
+ return `msg-${Date.now()}-${++_nextId}`;
548
+ }
549
+ var containerStyle = {
550
+ display: "flex",
551
+ flexDirection: "column",
552
+ height: "100%",
553
+ fontFamily: "system-ui, -apple-system, sans-serif",
554
+ fontSize: "14px",
555
+ touchAction: "none"
556
+ };
557
+ var messageListStyle = {
558
+ flex: "1",
559
+ overflowY: "auto",
560
+ padding: "12px",
561
+ display: "flex",
562
+ flexDirection: "column",
563
+ gap: "8px"
564
+ };
565
+ var bubbleBaseStyle = {
566
+ maxWidth: "85%",
567
+ padding: "8px 12px",
568
+ borderRadius: "12px",
569
+ lineHeight: "1.5",
570
+ wordBreak: "break-word"
571
+ };
572
+ var userBubbleExtra = {
573
+ alignSelf: "flex-end",
574
+ backgroundColor: `var(--sc-color-primary, ${TOKEN_PURPLE_4})`,
575
+ color: `var(--sc-color-primary-text, ${TOKEN_WHITE})`,
576
+ borderBottomRightRadius: "4px"
577
+ };
578
+ var assistantBubbleExtra = {
579
+ alignSelf: "flex-start",
580
+ backgroundColor: "var(--sc-chat-assistant-bubble-bg, rgba(255, 255, 255, 0.08))",
581
+ color: `var(--sc-content-text-color, ${TOKEN_SLATE_10})`,
582
+ borderBottomLeftRadius: "4px"
583
+ };
584
+ var loadingDotsStyle = {
585
+ alignSelf: "flex-start",
586
+ padding: "8px 16px",
587
+ backgroundColor: "var(--sc-chat-loading-bg, rgba(255, 255, 255, 0.05))",
588
+ borderRadius: "12px",
589
+ color: `var(--sc-content-text-secondary-color, ${TOKEN_SLATE_8})`,
590
+ fontSize: "13px"
591
+ };
592
+ var errorBannerStyle = {
593
+ padding: "8px 12px",
594
+ backgroundColor: "var(--sc-color-error-bg, rgba(239, 68, 68, 0.1))",
595
+ color: `var(--sc-color-error, ${TOKEN_RED_4})`,
596
+ fontSize: "13px",
597
+ borderRadius: "8px",
598
+ margin: "0 12px"
599
+ };
600
+ var inputFormStyle = {
601
+ display: "flex",
602
+ gap: "8px",
603
+ padding: "12px",
604
+ borderTop: "1px solid var(--sc-content-border-color, rgba(255, 255, 255, 0.06))"
605
+ };
606
+ var inputStyle = {
607
+ flex: "1",
608
+ padding: "8px 12px",
609
+ borderRadius: "8px",
610
+ border: "1px solid var(--sc-content-border-color, rgba(255, 255, 255, 0.1))",
611
+ backgroundColor: "var(--sc-chat-input-bg, rgba(0, 0, 0, 0.2))",
612
+ color: `var(--sc-content-heading-color, ${TOKEN_SLATE_12})`,
613
+ fontSize: "14px",
614
+ outline: "none",
615
+ fontFamily: "inherit"
616
+ };
617
+ var sendButtonStyle = {
618
+ padding: "8px 16px",
619
+ borderRadius: "8px",
620
+ border: "none",
621
+ backgroundColor: `var(--sc-color-primary, ${TOKEN_PURPLE_4})`,
622
+ color: `var(--sc-color-primary-text, ${TOKEN_WHITE})`,
623
+ fontWeight: "600",
624
+ fontSize: "13px",
625
+ cursor: "pointer",
626
+ whiteSpace: "nowrap"
627
+ };
628
+ var sendButtonDisabledExtra = {
629
+ opacity: "0.5",
630
+ cursor: "not-allowed"
631
+ };
632
+ var ChatAssistantElement = class extends LitElement {
633
+ constructor() {
634
+ super(...arguments);
635
+ _ChatAssistantElement_instances.add(this);
636
+ this.config = void 0;
637
+ this.runtime = void 0;
638
+ this.tileId = "chatbot-widget";
639
+ this._messages = [];
640
+ this._isLoading = false;
641
+ this._error = null;
642
+ _ChatAssistantElement_batchHandle.set(this, null);
643
+ _ChatAssistantElement_inputEl.set(this, null);
644
+ _ChatAssistantElement_messageListEl.set(this, null);
645
+ _ChatAssistantElement_handleSubmit.set(this, (e) => {
646
+ var _a2;
647
+ e.preventDefault();
648
+ const input = (_a2 = __classPrivateFieldGet(this, _ChatAssistantElement_inputEl, "f")) != null ? _a2 : this.querySelector("[data-chat-input]");
649
+ if (!input || !input.value.trim() || this._isLoading)
650
+ return;
651
+ const text = input.value;
652
+ input.value = "";
653
+ __classPrivateFieldGet(this, _ChatAssistantElement_instances, "m", _ChatAssistantElement_sendMessage).call(this, text);
654
+ });
655
+ }
656
+ createRenderRoot() {
657
+ return this;
658
+ }
659
+ // ---------- Lifecycle: connectedCallback --------------------------------
660
+ connectedCallback() {
661
+ super.connectedCallback();
662
+ }
663
+ // ---------- Lifecycle: disconnectedCallback -----------------------------
664
+ disconnectedCallback() {
665
+ var _a2;
666
+ super.disconnectedCallback();
667
+ if ((_a2 = __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f")) == null ? void 0 : _a2.isApplied()) {
668
+ __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f").revertAll().catch((err) => {
669
+ console.error("[ChatAssistantElement] Failed to revert actions on disconnect:", err);
670
+ });
671
+ __classPrivateFieldSet(this, _ChatAssistantElement_batchHandle, null, "f");
672
+ }
673
+ }
674
+ // ---------- Lifecycle: firstUpdated -------------------------------------
675
+ firstUpdated() {
676
+ __classPrivateFieldSet(this, _ChatAssistantElement_inputEl, this.querySelector("[data-chat-input]"), "f");
677
+ __classPrivateFieldSet(this, _ChatAssistantElement_messageListEl, this.querySelector("[data-message-list]"), "f");
678
+ }
679
+ // ---------- Lifecycle: updated ------------------------------------------
680
+ updated(changed) {
681
+ var _a2;
682
+ if (changed.has("_messages") || changed.has("_isLoading")) {
683
+ if (__classPrivateFieldGet(this, _ChatAssistantElement_messageListEl, "f")) {
684
+ __classPrivateFieldGet(this, _ChatAssistantElement_messageListEl, "f").scrollTop = __classPrivateFieldGet(this, _ChatAssistantElement_messageListEl, "f").scrollHeight;
685
+ }
686
+ }
687
+ if (changed.has("config") && ((_a2 = this.config) == null ? void 0 : _a2.greeting) && this._messages.length === 0) {
688
+ this._messages = [
689
+ {
690
+ id: generateId2(),
691
+ role: "assistant",
692
+ text: this.config.greeting,
693
+ timestamp: Date.now()
694
+ }
695
+ ];
696
+ }
697
+ }
698
+ // ---------- Render -------------------------------------------------------
699
+ render() {
700
+ return html`
701
+ <div style=${styleMap(containerStyle)} data-testid="chat-assistant">
702
+ <!-- Message list -->
703
+ <div style=${styleMap(messageListStyle)} data-message-list>
704
+ ${this._messages.map((msg) => __classPrivateFieldGet(this, _ChatAssistantElement_instances, "m", _ChatAssistantElement_renderBubble).call(this, msg))}
705
+ ${this._isLoading ? html`<div style=${styleMap(loadingDotsStyle)}>Thinking...</div>` : nothing}
706
+ </div>
707
+
708
+ <!-- Error banner -->
709
+ ${this._error ? html`<div style=${styleMap(errorBannerStyle)}>${this._error}</div>` : nothing}
710
+
711
+ <!-- Composer -->
712
+ <form
713
+ style=${styleMap(inputFormStyle)}
714
+ @submit=${__classPrivateFieldGet(this, _ChatAssistantElement_handleSubmit, "f")}
715
+ >
716
+ <input
717
+ data-chat-input
718
+ style=${styleMap(inputStyle)}
719
+ placeholder="Ask anything..."
720
+ ?disabled=${this._isLoading}
721
+ data-testid="chat-input"
722
+ />
723
+ <button
724
+ type="submit"
725
+ ?disabled=${this._isLoading}
726
+ style=${styleMap(this._isLoading ? { ...sendButtonStyle, ...sendButtonDisabledExtra } : sendButtonStyle)}
727
+ data-testid="chat-send"
728
+ >
729
+ Send
730
+ </button>
731
+ </form>
732
+ </div>
733
+ `;
734
+ }
735
+ // ---------- Public API --------------------------------------------------
736
+ /** Programmatically clear the conversation (mirrors useChat.clearMessages) */
737
+ clearMessages() {
738
+ var _a2;
739
+ this._messages = [];
740
+ this._error = null;
741
+ if ((_a2 = __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f")) == null ? void 0 : _a2.isApplied()) {
742
+ __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f").revertAll().catch((err) => {
743
+ console.error("[ChatAssistantElement] Failed to revert actions on clear:", err);
744
+ });
745
+ __classPrivateFieldSet(this, _ChatAssistantElement_batchHandle, null, "f");
746
+ }
747
+ sessionStorage.removeItem(`syntro:chatbot:history:${this.tileId}`);
748
+ }
749
+ };
750
+ _ChatAssistantElement_batchHandle = /* @__PURE__ */ new WeakMap(), _ChatAssistantElement_inputEl = /* @__PURE__ */ new WeakMap(), _ChatAssistantElement_messageListEl = /* @__PURE__ */ new WeakMap(), _ChatAssistantElement_handleSubmit = /* @__PURE__ */ new WeakMap(), _ChatAssistantElement_instances = /* @__PURE__ */ new WeakSet(), _ChatAssistantElement_renderBubble = function _ChatAssistantElement_renderBubble2(msg) {
751
+ const isUser = msg.role === "user";
752
+ const bubbleStyle = isUser ? { ...bubbleBaseStyle, ...userBubbleExtra } : { ...bubbleBaseStyle, ...assistantBubbleExtra };
753
+ return html`<div style=${styleMap(bubbleStyle)}>${msg.text}</div>`;
754
+ }, _ChatAssistantElement_sendMessage = // ---------- Message sending logic (replaces useChat) --------------------
755
+ async function _ChatAssistantElement_sendMessage2(text) {
756
+ var _a2, _b;
757
+ const trimmed = text.trim();
758
+ if (!trimmed || !this.config || !this.runtime)
759
+ return;
760
+ this._error = null;
761
+ const userMessage = {
762
+ id: generateId2(),
763
+ role: "user",
764
+ text: trimmed,
765
+ timestamp: Date.now()
766
+ };
767
+ this._messages = [...this._messages, userMessage];
768
+ this._isLoading = true;
769
+ this.dispatchEvent(new CustomEvent("chat-message-sent", {
770
+ detail: { text: trimmed },
771
+ bubbles: true
772
+ }));
773
+ try {
774
+ const maxHistory = (_a2 = this.config.maxHistory) != null ? _a2 : 20;
775
+ const historySlice = [...this._messages].slice(-maxHistory).map((m2) => ({
776
+ role: m2.role,
777
+ content: m2.text
778
+ }));
779
+ const response = await sendMessage(this.config.backendUrl, {
780
+ message: trimmed,
781
+ history: historySlice,
782
+ mlflow_run_id: this.config.mlflowRunId
783
+ });
784
+ const { displayText, actions } = parseActions(response.response);
785
+ const assistantMessage = {
786
+ id: generateId2(),
787
+ role: "assistant",
788
+ text: displayText,
789
+ timestamp: Date.now()
790
+ };
791
+ this._messages = [...this._messages, assistantMessage];
792
+ if (actions.length > 0) {
793
+ if ((_b = __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f")) == null ? void 0 : _b.isApplied()) {
794
+ await __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f").revertAll();
795
+ }
796
+ __classPrivateFieldSet(this, _ChatAssistantElement_batchHandle, await this.runtime.actions.applyBatch(actions), "f");
797
+ this.runtime.events.publish("chatbot.actions_applied", {
798
+ count: actions.length,
799
+ kinds: actions.map((a) => a.kind),
800
+ tileId: this.tileId
801
+ });
802
+ }
803
+ this.dispatchEvent(new CustomEvent("chat-response-received", {
804
+ detail: { text: displayText, actions },
805
+ bubbles: true
806
+ }));
807
+ } catch (err) {
808
+ const message = err instanceof Error ? err.message : "An unexpected error occurred";
809
+ this._error = message;
810
+ } finally {
811
+ this._isLoading = false;
812
+ }
813
+ };
814
+ ChatAssistantElement.properties = {
815
+ // Public inputs
816
+ config: { attribute: false },
817
+ runtime: { attribute: false },
818
+ tileId: { type: String },
819
+ // Internal reactive state
820
+ _messages: { state: true },
821
+ _isLoading: { state: true },
822
+ _error: { state: true }
823
+ };
824
+ var TAG_NAME = "syntro-chat-assistant";
825
+ var registerChatAssistantElement = () => {
826
+ if (typeof window === "undefined")
827
+ return;
828
+ if (!customElements.get(TAG_NAME)) {
829
+ customElements.define(TAG_NAME, ChatAssistantElement);
830
+ }
831
+ };
832
+ var ChatAssistantLitMountable = {
833
+ mount(container, mountConfig) {
834
+ const { config, runtime: runtime7, tileId = "chatbot-widget" } = mountConfig != null ? mountConfig : {};
835
+ if (!config || !runtime7) {
836
+ container.innerHTML = `<div style="padding: 16px; color: var(--sc-content-text-secondary-color, ${TOKEN_SLATE_8});">Chat widget requires config and runtime.</div>`;
837
+ return () => {
838
+ container.innerHTML = "";
839
+ };
840
+ }
841
+ registerChatAssistantElement();
842
+ const el = document.createElement("syntro-chat-assistant");
843
+ el.config = config;
844
+ el.runtime = runtime7;
845
+ el.tileId = tileId;
846
+ el.style.cssText = "display:flex;flex-direction:column;height:100%;width:100%;";
847
+ container.appendChild(el);
848
+ return () => {
849
+ el.remove();
850
+ };
851
+ }
852
+ };
853
+
509
854
  // ../adaptives/adaptive-chatbot/dist/runtime.js
510
855
  var runtime3 = {
511
856
  id: "adaptive-chatbot",
@@ -524,6 +869,15 @@ var runtime3 = {
524
869
  description: "AI-powered chat assistant that can execute DOM actions",
525
870
  icon: "\u{1F4AC}"
526
871
  }
872
+ },
873
+ {
874
+ id: "adaptive-chatbot:assistant-lit",
875
+ component: ChatAssistantLitMountable,
876
+ metadata: {
877
+ name: "Chat Assistant (Lit)",
878
+ description: "Lit web component chat assistant \u2014 no React dependency",
879
+ icon: "\u{1F4AC}"
880
+ }
527
881
  }
528
882
  ]
529
883
  };
@@ -2057,19 +2411,19 @@ function getAnswerText(answer) {
2057
2411
  }
2058
2412
  function renderAnswer(answer) {
2059
2413
  if (typeof answer === "string") {
2060
- const html2 = marked.parse(answer);
2414
+ const html5 = marked.parse(answer);
2061
2415
  return (
2062
2416
  // biome-ignore lint/security/noDangerouslySetInnerHtml: content is CMS/config content, not user-controlled input
2063
- _jsx2("div", { style: { margin: 0 }, "data-faq-markdown": "", dangerouslySetInnerHTML: { __html: html2 } })
2417
+ _jsx2("div", { style: { margin: 0 }, "data-faq-markdown": "", dangerouslySetInnerHTML: { __html: html5 } })
2064
2418
  );
2065
2419
  }
2066
2420
  if (answer.type === "rich") {
2067
2421
  return _jsx2("div", { style: { margin: 0 }, dangerouslySetInnerHTML: { __html: answer.html } });
2068
2422
  }
2069
- const html = marked.parse(answer.content);
2423
+ const html4 = marked.parse(answer.content);
2070
2424
  return (
2071
2425
  // biome-ignore lint/security/noDangerouslySetInnerHtml: markdown content is CMS/config content, not user-controlled input
2072
- _jsx2("div", { style: { margin: 0 }, "data-faq-markdown": "", dangerouslySetInnerHTML: { __html: html } })
2426
+ _jsx2("div", { style: { margin: 0 }, "data-faq-markdown": "", dangerouslySetInnerHTML: { __html: html4 } })
2073
2427
  );
2074
2428
  }
2075
2429
  function resolveFeedbackConfig(feedback) {
@@ -2299,7 +2653,7 @@ function FAQWidget({ config, runtime: runtime7, instanceId }) {
2299
2653
  value
2300
2654
  });
2301
2655
  }, [runtime7.events]);
2302
- const containerStyle = {
2656
+ const containerStyle2 = {
2303
2657
  ...baseStyles.container,
2304
2658
  ...themeStyles[resolvedTheme].container
2305
2659
  };
@@ -2317,9 +2671,9 @@ function FAQWidget({ config, runtime: runtime7, instanceId }) {
2317
2671
  };
2318
2672
  const renderItems = (items) => items.map((q2, index) => _jsx2(FAQItem, { item: q2, isExpanded: expandedIds.has(q2.config.id), isHighlighted: highlightId === q2.config.id, isLast: index === items.length - 1, onToggle: () => handleToggle(q2.config.id), theme: resolvedTheme, feedbackConfig, feedbackValue: feedbackState.get(q2.config.id), onFeedback: handleFeedback }, q2.config.id));
2319
2673
  if (visibleQuestions.length === 0) {
2320
- return _jsx2("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-faq", children: _jsx2("div", { style: emptyStateStyle, children: "You're all set for now! We'll surface answers here when they're relevant to what you're doing." }) });
2674
+ return _jsx2("div", { style: containerStyle2, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-faq", children: _jsx2("div", { style: emptyStateStyle, children: "You're all set for now! We'll surface answers here when they're relevant to what you're doing." }) });
2321
2675
  }
2322
- return _jsxs2("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-faq", children: [config.searchable && _jsxs2("div", { style: baseStyles.searchWrapper, children: [_jsx2("style", { children: `[data-adaptive-id="${instanceId}"] input::placeholder { color: var(--sc-content-search-color, inherit); opacity: 0.7; }` }), _jsx2("input", { type: "text", placeholder: "Search questions...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), style: searchInputStyle })] }), _jsx2("div", { style: baseStyles.accordion, children: hasCategories ? Array.from(categoryGroups.entries()).map(([category, items]) => _jsxs2(React2.Fragment, { children: [category && _jsx2("div", { style: categoryHeaderStyle, "data-category-header": category, children: category }), renderItems(items)] }, category != null ? category : "__ungrouped")) : renderItems(filteredQuestions) }), config.searchable && filteredQuestions.length === 0 && searchQuery && _jsxs2("div", { style: { ...baseStyles.noResults, ...themeStyles[resolvedTheme].emptyState }, children: ['No questions found matching "', searchQuery, '"'] })] });
2676
+ return _jsxs2("div", { style: containerStyle2, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-faq", children: [config.searchable && _jsxs2("div", { style: baseStyles.searchWrapper, children: [_jsx2("style", { children: `[data-adaptive-id="${instanceId}"] input::placeholder { color: var(--sc-content-search-color, inherit); opacity: 0.7; }` }), _jsx2("input", { type: "text", placeholder: "Search questions...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), style: searchInputStyle })] }), _jsx2("div", { style: baseStyles.accordion, children: hasCategories ? Array.from(categoryGroups.entries()).map(([category, items]) => _jsxs2(React2.Fragment, { children: [category && _jsx2("div", { style: categoryHeaderStyle, "data-category-header": category, children: category }), renderItems(items)] }, category != null ? category : "__ungrouped")) : renderItems(filteredQuestions) }), config.searchable && filteredQuestions.length === 0 && searchQuery && _jsxs2("div", { style: { ...baseStyles.noResults, ...themeStyles[resolvedTheme].emptyState }, children: ['No questions found matching "', searchQuery, '"'] })] });
2323
2677
  }
2324
2678
  var FAQMountableWidget = {
2325
2679
  mount(container, config) {
@@ -2343,6 +2697,485 @@ var FAQMountableWidget = {
2343
2697
  }
2344
2698
  };
2345
2699
 
2700
+ // ../adaptives/adaptive-faq/dist/FAQWidgetLit.js
2701
+ import { html as html2, LitElement as LitElement2, nothing as nothing2 } from "lit";
2702
+ import { styleMap as styleMap2 } from "lit/directives/style-map.js";
2703
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
2704
+ function sm(styles2) {
2705
+ return styles2;
2706
+ }
2707
+ var marked2 = new B({ async: false, gfm: true, breaks: true });
2708
+ function getAnswerText2(answer) {
2709
+ if (typeof answer === "string")
2710
+ return answer;
2711
+ if (answer.type === "rich")
2712
+ return answer.html;
2713
+ return answer.content;
2714
+ }
2715
+ function renderAnswerHtml(answer) {
2716
+ if (typeof answer === "string") {
2717
+ return marked2.parse(answer);
2718
+ }
2719
+ if (answer.type === "rich") {
2720
+ return answer.html;
2721
+ }
2722
+ return marked2.parse(answer.content);
2723
+ }
2724
+ function resolveFeedbackConfig2(feedback) {
2725
+ if (!feedback)
2726
+ return null;
2727
+ if (feedback === true)
2728
+ return { style: "thumbs" };
2729
+ return feedback;
2730
+ }
2731
+ function getFeedbackPrompt2(feedbackConfig) {
2732
+ var _a2;
2733
+ return (_a2 = feedbackConfig.prompt) != null ? _a2 : "Was this helpful?";
2734
+ }
2735
+ function resolveTheme(theme) {
2736
+ var _a2;
2737
+ if (theme && theme !== "auto")
2738
+ return theme;
2739
+ if (typeof window !== "undefined") {
2740
+ return ((_a2 = window.matchMedia) == null ? void 0 : _a2.call(window, "(prefers-color-scheme: dark)").matches) ? "dark" : "light";
2741
+ }
2742
+ return "light";
2743
+ }
2744
+ var FAQAccordionElement = class extends LitElement2 {
2745
+ constructor() {
2746
+ super(...arguments);
2747
+ this.faqConfig = {
2748
+ expandBehavior: "single",
2749
+ searchable: false,
2750
+ theme: "auto",
2751
+ actions: []
2752
+ };
2753
+ this.runtime = null;
2754
+ this.instanceId = "faq-widget";
2755
+ this._expandedIds = /* @__PURE__ */ new Set();
2756
+ this._highlightId = null;
2757
+ this._searchQuery = "";
2758
+ this._feedbackState = /* @__PURE__ */ new Map();
2759
+ this._hoveredId = null;
2760
+ this._unsubContext = null;
2761
+ this._unsubAccumulator = null;
2762
+ this._unsubCta = null;
2763
+ this._unsubDeepLink = null;
2764
+ this._unsubSessionMetrics = null;
2765
+ this._highlightTimer = null;
2766
+ }
2767
+ // -----------------------------------------------------------------------
2768
+ // Light DOM — no Shadow DOM so CSS variables from the host page apply
2769
+ // -----------------------------------------------------------------------
2770
+ createRenderRoot() {
2771
+ return this;
2772
+ }
2773
+ // -----------------------------------------------------------------------
2774
+ // Lifecycle
2775
+ // -----------------------------------------------------------------------
2776
+ connectedCallback() {
2777
+ super.connectedCallback();
2778
+ this._subscribeAll();
2779
+ }
2780
+ disconnectedCallback() {
2781
+ super.disconnectedCallback();
2782
+ this._unsubscribeAll();
2783
+ if (this._highlightTimer !== null) {
2784
+ clearTimeout(this._highlightTimer);
2785
+ this._highlightTimer = null;
2786
+ }
2787
+ }
2788
+ // Re-subscribe when runtime changes (property may be set after connectedCallback)
2789
+ updated(changedProps) {
2790
+ if (changedProps.has("runtime")) {
2791
+ this._unsubscribeAll();
2792
+ this._subscribeAll();
2793
+ }
2794
+ }
2795
+ // -----------------------------------------------------------------------
2796
+ // Subscription management
2797
+ // -----------------------------------------------------------------------
2798
+ _subscribeAll() {
2799
+ var _a2, _b;
2800
+ if (!this.runtime)
2801
+ return;
2802
+ this._unsubContext = this.runtime.context.subscribe(() => {
2803
+ this.requestUpdate();
2804
+ });
2805
+ if ((_a2 = this.runtime.accumulator) == null ? void 0 : _a2.subscribe) {
2806
+ this._unsubAccumulator = this.runtime.accumulator.subscribe(() => {
2807
+ this.requestUpdate();
2808
+ });
2809
+ }
2810
+ if ((_b = this.runtime.sessionMetrics) == null ? void 0 : _b.subscribe) {
2811
+ this._unsubSessionMetrics = this.runtime.sessionMetrics.subscribe(() => {
2812
+ this.requestUpdate();
2813
+ });
2814
+ }
2815
+ if (this.runtime.events.subscribe) {
2816
+ if (this.runtime.events.getRecent) {
2817
+ const recentEvents = this.runtime.events.getRecent({ patterns: ["^action\\.tooltip_cta_clicked$", "^action\\.modal_cta_clicked$"] }, 10);
2818
+ const pendingEvent = recentEvents.filter((e) => {
2819
+ var _a3;
2820
+ const actionId = (_a3 = e.props) == null ? void 0 : _a3.actionId;
2821
+ return typeof actionId === "string" && actionId.startsWith("faq:open:");
2822
+ }).pop();
2823
+ if (pendingEvent && Date.now() - pendingEvent.ts < 1e4) {
2824
+ const questionId = pendingEvent.props.actionId.replace("faq:open:", "");
2825
+ this._expandedIds = /* @__PURE__ */ new Set([questionId]);
2826
+ requestAnimationFrame(() => {
2827
+ const el = document.querySelector(`[data-faq-item-id="${questionId}"]`);
2828
+ if (el)
2829
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
2830
+ });
2831
+ }
2832
+ }
2833
+ this._unsubCta = this.runtime.events.subscribe({ patterns: ["^action\\.tooltip_cta_clicked$", "^action\\.modal_cta_clicked$"] }, (event) => {
2834
+ var _a3, _b2;
2835
+ const actionId = (_a3 = event.props) == null ? void 0 : _a3.actionId;
2836
+ if (typeof actionId !== "string" || !actionId.startsWith("faq:open:"))
2837
+ return;
2838
+ const questionId = actionId.replace("faq:open:", "");
2839
+ this._expandedIds = /* @__PURE__ */ new Set([questionId]);
2840
+ requestAnimationFrame(() => {
2841
+ const el = document.querySelector(`[data-faq-item-id="${questionId}"]`);
2842
+ if (el)
2843
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
2844
+ });
2845
+ (_b2 = this.runtime) == null ? void 0 : _b2.events.publish("canvas.requestOpen");
2846
+ });
2847
+ }
2848
+ if (this.runtime.events.subscribe) {
2849
+ const handleDeepLink = (event) => {
2850
+ var _a3, _b2;
2851
+ const tileId = (_a3 = event.props) == null ? void 0 : _a3.tileId;
2852
+ const itemId = (_b2 = event.props) == null ? void 0 : _b2.itemId;
2853
+ if (tileId !== this.instanceId)
2854
+ return;
2855
+ if (!itemId)
2856
+ return;
2857
+ this._expandedIds = /* @__PURE__ */ new Set([itemId]);
2858
+ this._highlightId = itemId;
2859
+ if (this._highlightTimer !== null)
2860
+ clearTimeout(this._highlightTimer);
2861
+ this._highlightTimer = setTimeout(() => {
2862
+ this._highlightId = null;
2863
+ this._highlightTimer = null;
2864
+ }, 1500);
2865
+ requestAnimationFrame(() => {
2866
+ const el = document.querySelector(`[data-faq-item-id="${itemId}"]`);
2867
+ if (el)
2868
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
2869
+ });
2870
+ };
2871
+ if (this.runtime.events.getRecent) {
2872
+ const recent = this.runtime.events.getRecent({ names: ["notification.deep_link"] }, 5);
2873
+ const pending = recent.filter((e) => {
2874
+ var _a3, _b2;
2875
+ return ((_a3 = e.props) == null ? void 0 : _a3.tileId) === this.instanceId && ((_b2 = e.props) == null ? void 0 : _b2.itemId);
2876
+ }).pop();
2877
+ if (pending && Date.now() - pending.ts < 1e4) {
2878
+ handleDeepLink(pending);
2879
+ }
2880
+ }
2881
+ this._unsubDeepLink = this.runtime.events.subscribe({ names: ["notification.deep_link"] }, handleDeepLink);
2882
+ }
2883
+ }
2884
+ _unsubscribeAll() {
2885
+ var _a2, _b, _c, _d, _e2;
2886
+ (_a2 = this._unsubContext) == null ? void 0 : _a2.call(this);
2887
+ (_b = this._unsubAccumulator) == null ? void 0 : _b.call(this);
2888
+ (_c = this._unsubSessionMetrics) == null ? void 0 : _c.call(this);
2889
+ (_d = this._unsubCta) == null ? void 0 : _d.call(this);
2890
+ (_e2 = this._unsubDeepLink) == null ? void 0 : _e2.call(this);
2891
+ this._unsubContext = null;
2892
+ this._unsubAccumulator = null;
2893
+ this._unsubSessionMetrics = null;
2894
+ this._unsubCta = null;
2895
+ this._unsubDeepLink = null;
2896
+ }
2897
+ // -----------------------------------------------------------------------
2898
+ // Handlers
2899
+ // -----------------------------------------------------------------------
2900
+ _handleToggle(id) {
2901
+ var _a2;
2902
+ const prev = this._expandedIds;
2903
+ let next;
2904
+ if (this.faqConfig.expandBehavior === "single") {
2905
+ next = prev.has(id) ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([id]);
2906
+ } else {
2907
+ next = new Set(prev);
2908
+ if (prev.has(id)) {
2909
+ next.delete(id);
2910
+ } else {
2911
+ next.add(id);
2912
+ }
2913
+ }
2914
+ const willBeExpanded = !prev.has(id);
2915
+ this._expandedIds = next;
2916
+ (_a2 = this.runtime) == null ? void 0 : _a2.events.publish("faq:toggled", {
2917
+ instanceId: this.instanceId,
2918
+ questionId: id,
2919
+ expanded: willBeExpanded,
2920
+ timestamp: Date.now()
2921
+ });
2922
+ }
2923
+ _handleFeedback(itemId, question, value) {
2924
+ var _a2;
2925
+ const next = new Map(this._feedbackState);
2926
+ next.set(itemId, value);
2927
+ this._feedbackState = next;
2928
+ (_a2 = this.runtime) == null ? void 0 : _a2.events.publish("faq:feedback", { itemId, question, value });
2929
+ }
2930
+ // -----------------------------------------------------------------------
2931
+ // Computed helpers
2932
+ // -----------------------------------------------------------------------
2933
+ _visibleQuestions() {
2934
+ var _a2;
2935
+ return ((_a2 = this.faqConfig.actions) != null ? _a2 : []).filter((q2) => {
2936
+ if (!q2.triggerWhen)
2937
+ return true;
2938
+ if (!this.runtime)
2939
+ return true;
2940
+ const result = this.runtime.evaluateSync(q2.triggerWhen);
2941
+ return result.value;
2942
+ });
2943
+ }
2944
+ _orderedQuestions(visible) {
2945
+ if (this.faqConfig.ordering === "priority") {
2946
+ return [...visible].sort((a, b2) => {
2947
+ var _a2, _b;
2948
+ return ((_a2 = b2.config.priority) != null ? _a2 : 0) - ((_b = a.config.priority) != null ? _b : 0);
2949
+ });
2950
+ }
2951
+ return visible;
2952
+ }
2953
+ _filteredQuestions(ordered) {
2954
+ const q2 = this._searchQuery.trim().toLowerCase();
2955
+ if (!this.faqConfig.searchable || !q2)
2956
+ return ordered;
2957
+ return ordered.filter((item) => {
2958
+ var _a2;
2959
+ return item.config.question.toLowerCase().includes(q2) || getAnswerText2(item.config.answer).toLowerCase().includes(q2) || ((_a2 = item.config.category) == null ? void 0 : _a2.toLowerCase().includes(q2));
2960
+ });
2961
+ }
2962
+ _categoryGroups(filtered) {
2963
+ const groups = /* @__PURE__ */ new Map();
2964
+ for (const item of filtered) {
2965
+ const cat = item.config.category;
2966
+ if (!groups.has(cat))
2967
+ groups.set(cat, []);
2968
+ groups.get(cat).push(item);
2969
+ }
2970
+ return groups;
2971
+ }
2972
+ // -----------------------------------------------------------------------
2973
+ // Render helpers
2974
+ // -----------------------------------------------------------------------
2975
+ _renderAnswer(answer) {
2976
+ const html_str = renderAnswerHtml(answer);
2977
+ return html2`<div style="margin:0" data-faq-markdown="">${unsafeHTML(html_str)}</div>`;
2978
+ }
2979
+ _renderFeedback(item, feedbackConfig, feedbackValue, theme) {
2980
+ const colors = themeStyles[theme];
2981
+ const feedbackStyle = { ...baseStyles.feedback, ...colors.feedbackPrompt };
2982
+ return html2`
2983
+ <div style=${styleMap2(sm(feedbackStyle))}>
2984
+ <span>${getFeedbackPrompt2(feedbackConfig)}</span>
2985
+ <button
2986
+ type="button"
2987
+ style=${styleMap2(sm({
2988
+ ...baseStyles.feedbackButton,
2989
+ ...feedbackValue === "up" ? baseStyles.feedbackButtonSelected : {}
2990
+ }))}
2991
+ aria-label="Thumbs up"
2992
+ @click=${() => this._handleFeedback(item.config.id, item.config.question, "up")}
2993
+ >\uD83D\uDC4D</button>
2994
+ <button
2995
+ type="button"
2996
+ style=${styleMap2(sm({
2997
+ ...baseStyles.feedbackButton,
2998
+ ...feedbackValue === "down" ? baseStyles.feedbackButtonSelected : {}
2999
+ }))}
3000
+ aria-label="Thumbs down"
3001
+ @click=${() => this._handleFeedback(item.config.id, item.config.question, "down")}
3002
+ >\uD83D\uDC4E</button>
3003
+ </div>
3004
+ `;
3005
+ }
3006
+ _renderItem(item, isLast, theme, feedbackConfig) {
3007
+ const colors = themeStyles[theme];
3008
+ const isExpanded = this._expandedIds.has(item.config.id);
3009
+ const isHighlighted = this._highlightId === item.config.id;
3010
+ const isHovered = this._hoveredId === item.config.id;
3011
+ const itemStyle = {
3012
+ ...baseStyles.item,
3013
+ ...colors.item,
3014
+ ...isExpanded ? colors.itemExpanded : {},
3015
+ ...isHighlighted ? {
3016
+ boxShadow: `0 0 0 2px ${purple[4]}, 0 0 12px rgba(106, 89, 206, 0.4)`,
3017
+ transition: "box-shadow 0.3s ease"
3018
+ } : {},
3019
+ ...!isLast ? { borderBottom: "var(--sc-content-item-divider, none)" } : {}
3020
+ };
3021
+ const questionStyle = {
3022
+ ...baseStyles.question,
3023
+ ...colors.question,
3024
+ ...isHovered ? colors.questionHover : {}
3025
+ };
3026
+ const chevronStyle = {
3027
+ ...baseStyles.chevron,
3028
+ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)"
3029
+ };
3030
+ const answerStyle = {
3031
+ ...baseStyles.answer,
3032
+ ...colors.answer,
3033
+ maxHeight: isExpanded ? "500px" : "0",
3034
+ paddingBottom: isExpanded ? "16px" : "0"
3035
+ };
3036
+ return html2`
3037
+ <div
3038
+ style=${styleMap2(sm(itemStyle))}
3039
+ data-faq-item-id=${item.config.id}
3040
+ >
3041
+ <button
3042
+ type="button"
3043
+ style=${styleMap2(sm(questionStyle))}
3044
+ aria-expanded=${isExpanded}
3045
+ @click=${() => this._handleToggle(item.config.id)}
3046
+ @mouseenter=${() => {
3047
+ this._hoveredId = item.config.id;
3048
+ }}
3049
+ @mouseleave=${() => {
3050
+ this._hoveredId = null;
3051
+ }}
3052
+ >
3053
+ <span>${item.config.question}</span>
3054
+ <span style=${styleMap2(sm(chevronStyle))}>\u203A</span>
3055
+ </button>
3056
+
3057
+ <div
3058
+ style=${styleMap2(sm(answerStyle))}
3059
+ aria-hidden=${!isExpanded}
3060
+ >
3061
+ ${this._renderAnswer(item.config.answer)}
3062
+ ${isExpanded && feedbackConfig ? this._renderFeedback(item, feedbackConfig, this._feedbackState.get(item.config.id), theme) : nothing2}
3063
+ </div>
3064
+ </div>
3065
+ `;
3066
+ }
3067
+ _renderItems(items, theme, feedbackConfig) {
3068
+ return items.map((item, index) => this._renderItem(item, index === items.length - 1, theme, feedbackConfig));
3069
+ }
3070
+ // -----------------------------------------------------------------------
3071
+ // Render
3072
+ // -----------------------------------------------------------------------
3073
+ render() {
3074
+ const theme = resolveTheme(this.faqConfig.theme);
3075
+ const colors = themeStyles[theme];
3076
+ const feedbackConfig = resolveFeedbackConfig2(this.faqConfig.feedback);
3077
+ const visible = this._visibleQuestions();
3078
+ const ordered = this._orderedQuestions(visible);
3079
+ const filtered = this._filteredQuestions(ordered);
3080
+ const hasCategories = filtered.some((q2) => q2.config.category);
3081
+ const groups = hasCategories ? this._categoryGroups(filtered) : null;
3082
+ const containerStyle2 = {
3083
+ ...baseStyles.container,
3084
+ ...colors.container
3085
+ };
3086
+ const emptyStateStyle = {
3087
+ ...baseStyles.emptyState,
3088
+ ...colors.emptyState
3089
+ };
3090
+ const categoryHeaderStyle = {
3091
+ ...baseStyles.categoryHeader,
3092
+ ...colors.categoryHeader
3093
+ };
3094
+ const searchInputStyle = {
3095
+ ...baseStyles.searchInput,
3096
+ ...colors.searchInput
3097
+ };
3098
+ if (visible.length === 0) {
3099
+ return html2`
3100
+ <div
3101
+ style=${styleMap2(sm(containerStyle2))}
3102
+ data-adaptive-id=${this.instanceId}
3103
+ data-adaptive-type="adaptive-faq"
3104
+ >
3105
+ <div style=${styleMap2(sm(emptyStateStyle))}>
3106
+ You're all set for now! We'll surface answers here when they're relevant to what
3107
+ you're doing.
3108
+ </div>
3109
+ </div>
3110
+ `;
3111
+ }
3112
+ return html2`
3113
+ <div
3114
+ style=${styleMap2(sm(containerStyle2))}
3115
+ data-adaptive-id=${this.instanceId}
3116
+ data-adaptive-type="adaptive-faq"
3117
+ >
3118
+ ${this.faqConfig.searchable ? html2`
3119
+ <div style=${styleMap2(sm(baseStyles.searchWrapper))}>
3120
+ <style>
3121
+ [data-adaptive-id="${this.instanceId}"] input::placeholder {
3122
+ color: var(--sc-content-search-color, inherit);
3123
+ opacity: 0.7;
3124
+ }
3125
+ </style>
3126
+ <input
3127
+ type="text"
3128
+ placeholder="Search questions..."
3129
+ .value=${this._searchQuery}
3130
+ style=${styleMap2(sm(searchInputStyle))}
3131
+ @input=${(e) => {
3132
+ this._searchQuery = e.target.value;
3133
+ }}
3134
+ />
3135
+ </div>
3136
+ ` : nothing2}
3137
+
3138
+ <div style=${styleMap2(sm(baseStyles.accordion))}>
3139
+ ${groups ? Array.from(groups.entries()).map(([category, items]) => html2`
3140
+ ${category ? html2`
3141
+ <div
3142
+ style=${styleMap2(sm(categoryHeaderStyle))}
3143
+ data-category-header=${category}
3144
+ >
3145
+ ${category}
3146
+ </div>
3147
+ ` : nothing2}
3148
+ ${this._renderItems(items, theme, feedbackConfig)}
3149
+ `) : this._renderItems(filtered, theme, feedbackConfig)}
3150
+ </div>
3151
+
3152
+ ${this.faqConfig.searchable && filtered.length === 0 && this._searchQuery ? html2`
3153
+ <div
3154
+ style=${styleMap2(sm({ ...baseStyles.noResults, ...colors.emptyState }))}
3155
+ >
3156
+ No questions found matching &quot;${this._searchQuery}&quot;
3157
+ </div>
3158
+ ` : nothing2}
3159
+ </div>
3160
+ `;
3161
+ }
3162
+ };
3163
+ FAQAccordionElement.properties = {
3164
+ // Public API — set from the outside
3165
+ faqConfig: { attribute: false },
3166
+ runtime: { attribute: false },
3167
+ instanceId: { type: String },
3168
+ // Internal reactive state (prefixed with _ to signal "private")
3169
+ _expandedIds: { state: true },
3170
+ _highlightId: { state: true },
3171
+ _searchQuery: { state: true },
3172
+ _feedbackState: { state: true },
3173
+ _hoveredId: { state: true }
3174
+ };
3175
+ if (!customElements.get("syntro-faq-accordion")) {
3176
+ customElements.define("syntro-faq-accordion", FAQAccordionElement);
3177
+ }
3178
+
2346
3179
  // ../adaptives/adaptive-faq/dist/runtime.js
2347
3180
  var runtime4 = {
2348
3181
  id: "adaptive-faq",
@@ -2784,7 +3617,7 @@ function NavWidget({ config, runtime: runtime7, instanceId }) {
2784
3617
  pulseElement(el);
2785
3618
  setTimeout(() => el.focus(), 400);
2786
3619
  }, [runtime7.events, instanceId]);
2787
- const containerStyle = {
3620
+ const containerStyle2 = {
2788
3621
  ...baseStyles2.container,
2789
3622
  ...themeStyles2[resolvedTheme].container
2790
3623
  };
@@ -2798,9 +3631,9 @@ function NavWidget({ config, runtime: runtime7, instanceId }) {
2798
3631
  };
2799
3632
  const renderItems = (items) => items.map((tip, index) => _jsx3(NavTipItem, { item: tip, isExpanded: expandedIds.has(tip.config.id), isLast: index === items.length - 1, onToggle: () => handleToggle(tip.config.id), onNavigate: handleNavigate, onFocusAnchor: handleFocusAnchor, theme: resolvedTheme }, tip.config.id));
2800
3633
  if (visibleTips.length === 0) {
2801
- return _jsx3("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-nav", children: _jsx3("div", { style: emptyStateStyle, children: "You're all set for now! We'll share helpful tips here when they're relevant to what you're doing." }) });
3634
+ return _jsx3("div", { style: containerStyle2, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-nav", children: _jsx3("div", { style: emptyStateStyle, children: "You're all set for now! We'll share helpful tips here when they're relevant to what you're doing." }) });
2802
3635
  }
2803
- return _jsx3("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-nav", children: _jsx3("div", { style: baseStyles2.accordion, children: hasCategories ? Array.from(categoryGroups.entries()).map(([category, items]) => _jsxs3(React3.Fragment, { children: [category && _jsx3("div", { style: categoryHeaderStyle, "data-category-header": category, children: category }), renderItems(items)] }, category != null ? category : "__ungrouped")) : renderItems(visibleTips) }) });
3636
+ return _jsx3("div", { style: containerStyle2, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-nav", children: _jsx3("div", { style: baseStyles2.accordion, children: hasCategories ? Array.from(categoryGroups.entries()).map(([category, items]) => _jsxs3(React3.Fragment, { children: [category && _jsx3("div", { style: categoryHeaderStyle, "data-category-header": category, children: category }), renderItems(items)] }, category != null ? category : "__ungrouped")) : renderItems(visibleTips) }) });
2804
3637
  }
2805
3638
  var NavMountableWidget = {
2806
3639
  mount(container, config) {
@@ -2823,6 +3656,423 @@ var NavMountableWidget = {
2823
3656
  }
2824
3657
  };
2825
3658
 
3659
+ // ../adaptives/adaptive-nav/dist/NavWidgetLit.js
3660
+ import { html as html3, LitElement as LitElement3, nothing as nothing3 } from "lit";
3661
+ import { styleMap as styleMap3 } from "lit/directives/style-map.js";
3662
+ import { unsafeHTML as unsafeHTML2 } from "lit/directives/unsafe-html.js";
3663
+ var __classPrivateFieldGet2 = function(receiver, state, kind, f) {
3664
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3665
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
3666
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
3667
+ };
3668
+ var __classPrivateFieldSet2 = function(receiver, state, value, kind, f) {
3669
+ if (kind === "m") throw new TypeError("Private method is not writable");
3670
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
3671
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
3672
+ return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
3673
+ };
3674
+ var _NavWidgetLit_instances;
3675
+ var _NavWidgetLit_contextUnsub;
3676
+ var _NavWidgetLit_accumulatorUnsub;
3677
+ var _NavWidgetLit_subscribeRuntime;
3678
+ var _NavWidgetLit_unsubscribeRuntime;
3679
+ var _NavWidgetLit_getVisibleTips;
3680
+ var _NavWidgetLit_getResolvedTheme;
3681
+ var _NavWidgetLit_handleToggle;
3682
+ var _NavWidgetLit_handleNavigate;
3683
+ var _NavWidgetLit_handleFocusAnchor;
3684
+ var _NavWidgetLit_publishEvent;
3685
+ var _NavWidgetLit_renderTipItem;
3686
+ var TOKEN_PURPLE_42 = "#6a59ce";
3687
+ var TOKEN_SLATE_GREY_7 = "#677384";
3688
+ var TOKEN_SLATE_GREY_8 = "#87919f";
3689
+ var EMOJI_SVG_MAP2 = {
3690
+ "\u{1F4B5}": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="12" x="2" y="6" rx="2"/><circle cx="12" cy="12" r="2"/><path d="M6 12h.01M18 12h.01"/></svg>',
3691
+ "\u{1F3DB}\uFE0F": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" x2="21" y1="22" y2="22"/><line x1="6" x2="6" y1="18" y2="11"/><line x1="10" x2="10" y1="18" y2="11"/><line x1="14" x2="14" y1="18" y2="11"/><line x1="18" x2="18" y1="18" y2="11"/><polygon points="12 2 20 7 4 7"/></svg>',
3692
+ "\u23ED\uFE0F": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 4 15 12 5 20 5 4"/><line x1="19" x2="19" y1="5" y2="19"/></svg>',
3693
+ "\u27A1\uFE0F": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>',
3694
+ "\u{1F4A1}": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg>',
3695
+ "\u{1F4B0}": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="12" x="2" y="6" rx="2"/><circle cx="12" cy="12" r="2"/><path d="M6 12h.01M18 12h.01"/></svg>',
3696
+ "\u{1F4CB}": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="M12 11h4"/><path d="M12 16h4"/><path d="M8 11h.01"/><path d="M8 16h.01"/></svg>',
3697
+ "\u2705": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/></svg>',
3698
+ "\u26A0\uFE0F": '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>'
3699
+ };
3700
+ function escapeHtml2(str) {
3701
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3702
+ }
3703
+ function renderIcon2(emoji) {
3704
+ var _a2;
3705
+ return (_a2 = EMOJI_SVG_MAP2[emoji]) != null ? _a2 : escapeHtml2(emoji);
3706
+ }
3707
+ function routeMatchesCurrent2(routes) {
3708
+ if (typeof window === "undefined")
3709
+ return false;
3710
+ const current = window.location.pathname;
3711
+ return routes.some((route) => {
3712
+ const routePath = route.split("?")[0].split("#")[0];
3713
+ if (routePath.endsWith("/**")) {
3714
+ return current.startsWith(routePath.slice(0, -3));
3715
+ }
3716
+ return current === routePath;
3717
+ });
3718
+ }
3719
+ function pulseElement2(el) {
3720
+ const keyframes = [
3721
+ { boxShadow: "0 0 0 0 rgba(13, 148, 136, 0.5)" },
3722
+ { boxShadow: "0 0 0 8px rgba(13, 148, 136, 0)" }
3723
+ ];
3724
+ el.animate(keyframes, { duration: 600, iterations: 3, easing: "ease-out" });
3725
+ }
3726
+ function resolveTheme2(theme) {
3727
+ var _a2;
3728
+ if (theme === "dark")
3729
+ return "dark";
3730
+ if (theme === "light")
3731
+ return "light";
3732
+ if (typeof window !== "undefined") {
3733
+ return ((_a2 = window.matchMedia) == null ? void 0 : _a2.call(window, "(prefers-color-scheme: dark)").matches) ? "dark" : "light";
3734
+ }
3735
+ return "light";
3736
+ }
3737
+ var NavWidgetLit = class extends LitElement3 {
3738
+ constructor() {
3739
+ super(...arguments);
3740
+ _NavWidgetLit_instances.add(this);
3741
+ this.config = { expandBehavior: "single", theme: "auto", actions: [] };
3742
+ this.runtime = void 0;
3743
+ this.instanceId = "nav-widget";
3744
+ this._expandedIds = /* @__PURE__ */ new Set();
3745
+ this._renderTick = 0;
3746
+ this._hoveredId = null;
3747
+ _NavWidgetLit_contextUnsub.set(this, null);
3748
+ _NavWidgetLit_accumulatorUnsub.set(this, null);
3749
+ }
3750
+ createRenderRoot() {
3751
+ return this;
3752
+ }
3753
+ // ---------- Lifecycle: connectedCallback ---------------------------------
3754
+ connectedCallback() {
3755
+ super.connectedCallback();
3756
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_subscribeRuntime).call(this);
3757
+ }
3758
+ // ---------- Lifecycle: disconnectedCallback ------------------------------
3759
+ disconnectedCallback() {
3760
+ super.disconnectedCallback();
3761
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_unsubscribeRuntime).call(this);
3762
+ }
3763
+ // ---------- Lifecycle: updated -------------------------------------------
3764
+ updated(changed) {
3765
+ if (changed.has("runtime")) {
3766
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_unsubscribeRuntime).call(this);
3767
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_subscribeRuntime).call(this);
3768
+ }
3769
+ }
3770
+ // ---------- Render --------------------------------------------------------
3771
+ render() {
3772
+ const visibleTips = __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_getVisibleTips).call(this);
3773
+ const theme = __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_getResolvedTheme).call(this);
3774
+ const containerStyle2 = styleMap3({
3775
+ fontFamily: "var(--sc-font-family, system-ui, -apple-system, sans-serif)",
3776
+ maxWidth: "100%",
3777
+ overflow: "hidden",
3778
+ backgroundColor: "transparent",
3779
+ color: "inherit"
3780
+ });
3781
+ const accordionStyle = styleMap3({
3782
+ display: "flex",
3783
+ flexDirection: "column",
3784
+ gap: "var(--sc-content-item-gap, 6px)"
3785
+ });
3786
+ const categoryHeaderStyle = styleMap3({
3787
+ fontSize: "var(--sc-content-category-font-size, 12px)",
3788
+ fontWeight: "600",
3789
+ textTransform: "uppercase",
3790
+ letterSpacing: "0.05em",
3791
+ padding: "var(--sc-content-category-padding, 8px 4px 4px 4px)",
3792
+ color: theme === "dark" ? TOKEN_SLATE_GREY_8 : TOKEN_SLATE_GREY_7
3793
+ });
3794
+ const emptyStateStyle = styleMap3({
3795
+ fontSize: "13px",
3796
+ padding: "16px",
3797
+ textAlign: "center",
3798
+ color: theme === "dark" ? TOKEN_SLATE_GREY_7 : TOKEN_SLATE_GREY_8
3799
+ });
3800
+ if (visibleTips.length === 0) {
3801
+ return html3`
3802
+ <div
3803
+ style=${containerStyle2}
3804
+ data-adaptive-id=${this.instanceId}
3805
+ data-adaptive-type="adaptive-nav"
3806
+ >
3807
+ <div style=${emptyStateStyle}>
3808
+ You're all set for now! We'll share helpful tips here when they're relevant to what
3809
+ you're doing.
3810
+ </div>
3811
+ </div>
3812
+ `;
3813
+ }
3814
+ const categoryGroups = /* @__PURE__ */ new Map();
3815
+ for (const tip of visibleTips) {
3816
+ const cat = tip.config.category;
3817
+ if (!categoryGroups.has(cat)) {
3818
+ categoryGroups.set(cat, []);
3819
+ }
3820
+ categoryGroups.get(cat).push(tip);
3821
+ }
3822
+ const hasCategories = visibleTips.some((t) => t.config.category);
3823
+ return html3`
3824
+ <div
3825
+ style=${containerStyle2}
3826
+ data-adaptive-id=${this.instanceId}
3827
+ data-adaptive-type="adaptive-nav"
3828
+ >
3829
+ <div style=${accordionStyle}>
3830
+ ${hasCategories ? Array.from(categoryGroups.entries()).map(([category, items]) => html3`
3831
+ ${category ? html3`<div style=${categoryHeaderStyle} data-category-header=${category}>${category}</div>` : nothing3}
3832
+ ${items.map((tip, idx) => __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_renderTipItem).call(this, tip, idx, items.length))}
3833
+ `) : visibleTips.map((tip, idx) => __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_renderTipItem).call(this, tip, idx, visibleTips.length))}
3834
+ </div>
3835
+ </div>
3836
+ `;
3837
+ }
3838
+ };
3839
+ _NavWidgetLit_contextUnsub = /* @__PURE__ */ new WeakMap(), _NavWidgetLit_accumulatorUnsub = /* @__PURE__ */ new WeakMap(), _NavWidgetLit_instances = /* @__PURE__ */ new WeakSet(), _NavWidgetLit_subscribeRuntime = function _NavWidgetLit_subscribeRuntime2() {
3840
+ var _a2;
3841
+ if (!this.runtime)
3842
+ return;
3843
+ __classPrivateFieldSet2(this, _NavWidgetLit_contextUnsub, this.runtime.context.subscribe(() => {
3844
+ this._renderTick += 1;
3845
+ }), "f");
3846
+ if ((_a2 = this.runtime.accumulator) == null ? void 0 : _a2.subscribe) {
3847
+ __classPrivateFieldSet2(this, _NavWidgetLit_accumulatorUnsub, this.runtime.accumulator.subscribe(() => {
3848
+ this._renderTick += 1;
3849
+ }), "f");
3850
+ }
3851
+ }, _NavWidgetLit_unsubscribeRuntime = function _NavWidgetLit_unsubscribeRuntime2() {
3852
+ var _a2, _b;
3853
+ (_a2 = __classPrivateFieldGet2(this, _NavWidgetLit_contextUnsub, "f")) == null ? void 0 : _a2.call(this);
3854
+ __classPrivateFieldSet2(this, _NavWidgetLit_contextUnsub, null, "f");
3855
+ (_b = __classPrivateFieldGet2(this, _NavWidgetLit_accumulatorUnsub, "f")) == null ? void 0 : _b.call(this);
3856
+ __classPrivateFieldSet2(this, _NavWidgetLit_accumulatorUnsub, null, "f");
3857
+ }, _NavWidgetLit_getVisibleTips = function _NavWidgetLit_getVisibleTips2() {
3858
+ void this._renderTick;
3859
+ if (!this.runtime)
3860
+ return this.config.actions;
3861
+ return this.config.actions.filter((tip) => {
3862
+ if (!tip.triggerWhen)
3863
+ return true;
3864
+ try {
3865
+ const result = this.runtime.evaluateSync(tip.triggerWhen);
3866
+ return result.value;
3867
+ } catch {
3868
+ return false;
3869
+ }
3870
+ });
3871
+ }, _NavWidgetLit_getResolvedTheme = function _NavWidgetLit_getResolvedTheme2() {
3872
+ return resolveTheme2(this.config.theme);
3873
+ }, _NavWidgetLit_handleToggle = function _NavWidgetLit_handleToggle2(id) {
3874
+ const wasExpanded = this._expandedIds.has(id);
3875
+ let next;
3876
+ if (this.config.expandBehavior === "single") {
3877
+ for (const prevId of this._expandedIds) {
3878
+ if (prevId !== id) {
3879
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_publishEvent).call(this, "nav:toggled", {
3880
+ tipId: prevId,
3881
+ expanded: false
3882
+ });
3883
+ }
3884
+ }
3885
+ next = wasExpanded ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([id]);
3886
+ } else {
3887
+ next = new Set(this._expandedIds);
3888
+ if (wasExpanded) {
3889
+ next.delete(id);
3890
+ } else {
3891
+ next.add(id);
3892
+ }
3893
+ }
3894
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_publishEvent).call(this, "nav:toggled", {
3895
+ tipId: id,
3896
+ expanded: !wasExpanded
3897
+ });
3898
+ this._expandedIds = next;
3899
+ }, _NavWidgetLit_handleNavigate = function _NavWidgetLit_handleNavigate2(href, external) {
3900
+ const normalized = href.trim().toLowerCase();
3901
+ if (normalized.startsWith("javascript:") || normalized.startsWith("data:"))
3902
+ return;
3903
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_publishEvent).call(this, "nav:tip_clicked", { href, external });
3904
+ this.dispatchEvent(new CustomEvent("nav-tip-clicked", {
3905
+ bubbles: true,
3906
+ detail: { href, external, instanceId: this.instanceId }
3907
+ }));
3908
+ if (external) {
3909
+ window.open(href, "_blank", "noopener,noreferrer");
3910
+ } else {
3911
+ const url = new URL(href, window.location.origin);
3912
+ url.search = window.location.search;
3913
+ if (!navigateWithFrameworkRouter(url.toString())) {
3914
+ window.history.pushState(null, "", url.toString());
3915
+ window.dispatchEvent(new PopStateEvent("popstate"));
3916
+ }
3917
+ }
3918
+ }, _NavWidgetLit_handleFocusAnchor = function _NavWidgetLit_handleFocusAnchor2(anchor) {
3919
+ const el = document.querySelector(anchor.selector);
3920
+ if (!(el instanceof HTMLElement))
3921
+ return;
3922
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_publishEvent).call(this, "nav:tip_focused", {
3923
+ selector: anchor.selector,
3924
+ route: anchor.route
3925
+ });
3926
+ this.dispatchEvent(new CustomEvent("nav-tip-focused", {
3927
+ bubbles: true,
3928
+ detail: { selector: anchor.selector, instanceId: this.instanceId }
3929
+ }));
3930
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
3931
+ pulseElement2(el);
3932
+ setTimeout(() => el.focus(), 400);
3933
+ }, _NavWidgetLit_publishEvent = function _NavWidgetLit_publishEvent2(name, props) {
3934
+ var _a2;
3935
+ (_a2 = this.runtime) == null ? void 0 : _a2.events.publish(name, {
3936
+ instanceId: this.instanceId,
3937
+ timestamp: Date.now(),
3938
+ ...props
3939
+ });
3940
+ }, _NavWidgetLit_renderTipItem = function _NavWidgetLit_renderTipItem2(tip, index, total) {
3941
+ const { id, title, description, href, icon, external, anchor, category: _cat } = tip.config;
3942
+ const isExpanded = this._expandedIds.has(id);
3943
+ const isLast = index === total - 1;
3944
+ const isHovered = this._hoveredId === id;
3945
+ const theme = __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_getResolvedTheme).call(this);
3946
+ const effectiveHref = anchor ? Array.isArray(anchor.route) ? anchor.route[0] : anchor.route : href;
3947
+ const isSamePage = anchor ? routeMatchesCurrent2(Array.isArray(anchor.route) ? anchor.route : [anchor.route]) : effectiveHref ? routeMatchesCurrent2([effectiveHref]) : false;
3948
+ const hasSelector = (anchor == null ? void 0 : anchor.selector) && anchor.selector !== "*";
3949
+ const isFocusAction = isSamePage && hasSelector;
3950
+ const hasAction = !!effectiveHref || isFocusAction;
3951
+ const ctaLabel = isFocusAction ? "Focus \u2192" : external ? "Go \u2197" : "Go \u2192";
3952
+ const itemStyle = styleMap3({
3953
+ borderRadius: "var(--sc-content-border-radius, 8px)",
3954
+ overflow: "hidden",
3955
+ transition: "box-shadow 0.2s ease",
3956
+ backgroundColor: "var(--sc-content-background)",
3957
+ border: "var(--sc-content-border)",
3958
+ ...isExpanded ? {
3959
+ boxShadow: theme === "dark" ? "0 4px 12px rgba(0, 0, 0, 0.15)" : "0 4px 12px rgba(0, 0, 0, 0.08)"
3960
+ } : {},
3961
+ ...!isLast ? { borderBottom: "var(--sc-content-item-divider, none)" } : {}
3962
+ });
3963
+ const headerStyle = styleMap3({
3964
+ display: "flex",
3965
+ alignItems: "center",
3966
+ gap: "8px",
3967
+ width: "100%",
3968
+ padding: "var(--sc-content-item-padding, 12px 16px)",
3969
+ border: "none",
3970
+ cursor: "pointer",
3971
+ fontSize: "var(--sc-content-item-font-size, 15px)",
3972
+ fontWeight: "500",
3973
+ fontFamily: "inherit",
3974
+ textAlign: "left",
3975
+ transition: "background-color 0.15s ease",
3976
+ backgroundColor: isHovered ? "var(--sc-content-background-hover)" : "transparent",
3977
+ color: "var(--sc-content-text-color)"
3978
+ });
3979
+ const chevronStyle = styleMap3({
3980
+ fontSize: "20px",
3981
+ transition: "transform 0.2s ease",
3982
+ marginLeft: "auto",
3983
+ flexShrink: "0",
3984
+ color: "var(--sc-content-chevron-color, currentColor)",
3985
+ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)"
3986
+ });
3987
+ const bodyStyle = styleMap3({
3988
+ overflow: "hidden",
3989
+ transition: "max-height 0.25s ease, padding-bottom 0.25s ease",
3990
+ padding: "var(--sc-content-body-padding, 0 16px 12px 16px)",
3991
+ color: "var(--sc-content-text-secondary-color)",
3992
+ maxHeight: isExpanded ? "500px" : "0",
3993
+ paddingBottom: isExpanded ? "16px" : "0"
3994
+ });
3995
+ const descriptionStyle = styleMap3({
3996
+ fontSize: "var(--sc-content-body-font-size, 14px)",
3997
+ lineHeight: "1.5",
3998
+ margin: "0"
3999
+ });
4000
+ const linkButtonStyle = styleMap3({
4001
+ display: "inline-flex",
4002
+ alignItems: "center",
4003
+ gap: "4px",
4004
+ marginTop: "10px",
4005
+ padding: "6px 12px",
4006
+ borderRadius: "6px",
4007
+ textDecoration: "none",
4008
+ fontSize: "13px",
4009
+ fontWeight: "500",
4010
+ cursor: "pointer",
4011
+ border: "none",
4012
+ transition: "background-color 0.15s ease",
4013
+ backgroundColor: `var(--sc-color-primary, ${TOKEN_PURPLE_42})`,
4014
+ color: "#ffffff"
4015
+ });
4016
+ const iconStyle = styleMap3({
4017
+ fontSize: "16px",
4018
+ flexShrink: "0"
4019
+ });
4020
+ const onLinkClick = (e) => {
4021
+ e.preventDefault();
4022
+ e.stopPropagation();
4023
+ if (isFocusAction && anchor) {
4024
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_handleFocusAnchor).call(this, anchor);
4025
+ } else if (effectiveHref) {
4026
+ __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_handleNavigate).call(this, effectiveHref, external != null ? external : false);
4027
+ }
4028
+ };
4029
+ return html3`
4030
+ <div
4031
+ style=${itemStyle}
4032
+ data-nav-tip-id=${id}
4033
+ >
4034
+ <button
4035
+ type="button"
4036
+ style=${headerStyle}
4037
+ aria-expanded=${isExpanded}
4038
+ @click=${() => __classPrivateFieldGet2(this, _NavWidgetLit_instances, "m", _NavWidgetLit_handleToggle).call(this, id)}
4039
+ @mouseenter=${() => {
4040
+ this._hoveredId = id;
4041
+ }}
4042
+ @mouseleave=${() => {
4043
+ this._hoveredId = null;
4044
+ }}
4045
+ >
4046
+ ${icon ? html3`<span style=${iconStyle}>${unsafeHTML2(renderIcon2(icon))}</span>` : nothing3}
4047
+ <span>${title}</span>
4048
+ <span style=${chevronStyle}>${"\u203A"}</span>
4049
+ </button>
4050
+ <div style=${bodyStyle} aria-hidden=${!isExpanded}>
4051
+ <p style=${descriptionStyle}>${description}</p>
4052
+ ${hasAction ? html3`
4053
+ <a
4054
+ href=${effectiveHref || "#"}
4055
+ style=${linkButtonStyle}
4056
+ target=${external ? "_blank" : nothing3}
4057
+ rel=${external ? "noopener noreferrer" : nothing3}
4058
+ @click=${onLinkClick}
4059
+ >${ctaLabel}</a>
4060
+ ` : nothing3}
4061
+ </div>
4062
+ </div>
4063
+ `;
4064
+ };
4065
+ NavWidgetLit.properties = {
4066
+ // Public inputs
4067
+ config: { attribute: false },
4068
+ runtime: { attribute: false },
4069
+ instanceId: { type: String },
4070
+ // Internal reactive state
4071
+ _expandedIds: { state: true },
4072
+ _renderTick: { state: true },
4073
+ _hoveredId: { state: true }
4074
+ };
4075
+
2826
4076
  // ../adaptives/adaptive-nav/dist/runtime.js
2827
4077
  var executeScrollTo = async (action, context) => {
2828
4078
  var _a2, _b, _c, _d;
@@ -3325,6 +4575,68 @@ function validateEventFilter(data) {
3325
4575
  return EventFilterZ.safeParse(data);
3326
4576
  }
3327
4577
 
4578
+ // src/platform/ShopifyAnchorResolver.ts
4579
+ var DAWN_FAMILY = ["dawn", "sense", "craft", "ride", "refresh", "colorblock", "taste", "studio"];
4580
+ var PRESTIGE_FAMILY = ["prestige", "impact", "stretch"];
4581
+ var LEGACY_FAMILY = [
4582
+ "debut",
4583
+ "brooklyn",
4584
+ "supply",
4585
+ "minimal",
4586
+ "narrative",
4587
+ "simple",
4588
+ "boundless"
4589
+ ];
4590
+ var IMPULSE_FAMILY = ["impulse"];
4591
+ var TURBO_FAMILY = ["turbo"];
4592
+ var TRADEMARK_FAMILY = ["trademark", "clean canvas"];
4593
+ function detectThemeFamily() {
4594
+ var _a2, _b;
4595
+ const themeName = (_b = (_a2 = window == null ? void 0 : window.Shopify) == null ? void 0 : _a2.theme) == null ? void 0 : _b.name;
4596
+ if (!themeName) return "unknown";
4597
+ const lower = themeName.toLowerCase();
4598
+ if (DAWN_FAMILY.includes(lower)) return "dawn";
4599
+ if (PRESTIGE_FAMILY.includes(lower)) return "prestige";
4600
+ if (IMPULSE_FAMILY.includes(lower)) return "impulse";
4601
+ if (TURBO_FAMILY.includes(lower)) return "turbo";
4602
+ if (TRADEMARK_FAMILY.includes(lower)) return "trademark";
4603
+ if (LEGACY_FAMILY.includes(lower)) return "legacy";
4604
+ return "unknown";
4605
+ }
4606
+ var ShopifyAnchorResolver = class {
4607
+ /**
4608
+ * Scope a CSS selector to its containing .shopify-section wrapper.
4609
+ */
4610
+ scopeSelector(selector, element) {
4611
+ const section = element.closest(".shopify-section");
4612
+ if (section == null ? void 0 : section.id) {
4613
+ const escaped = typeof CSS !== "undefined" ? CSS.escape(section.id) : section.id;
4614
+ return `#${escaped} ${selector}`;
4615
+ }
4616
+ return selector;
4617
+ }
4618
+ /**
4619
+ * Validate that a selector matches exactly one element in the document.
4620
+ */
4621
+ validateUniqueness(selector) {
4622
+ try {
4623
+ const matches = document.querySelectorAll(selector);
4624
+ return {
4625
+ unique: matches.length === 1,
4626
+ matchCount: matches.length
4627
+ };
4628
+ } catch {
4629
+ return { unique: false, matchCount: 0 };
4630
+ }
4631
+ }
4632
+ /**
4633
+ * Get the current theme family for diagnostic/logging purposes.
4634
+ */
4635
+ getThemeFamily() {
4636
+ return detectThemeFamily();
4637
+ }
4638
+ };
4639
+
3328
4640
  // src/state/schema.ts
3329
4641
  import { z as z5 } from "zod";
3330
4642
  var StoredValueZ = z5.object({
@@ -3424,6 +4736,7 @@ export {
3424
4736
  RuntimeProvider,
3425
4737
  SDK_SCHEMA_VERSION,
3426
4738
  SDK_VERSION,
4739
+ COOKIE_NAME as SHOPIFY_COOKIE_NAME,
3427
4740
  STATIC_SLOT_STYLES,
3428
4741
  ScoreStrategyZ,
3429
4742
  ScrollBehaviorZ,
@@ -3439,6 +4752,10 @@ export {
3439
4752
  SetTextZ,
3440
4753
  ShadowCanvasOverlay,
3441
4754
  ShadowRootProvider,
4755
+ ShopifyAdapter,
4756
+ ShopifyAnchorResolver,
4757
+ ShopifyAntiFlicker,
4758
+ ShopifyPixelBridge,
3442
4759
  SmartCanvasApp,
3443
4760
  SmartCanvasController,
3444
4761
  SmartCanvasElement,
@@ -3490,6 +4807,8 @@ export {
3490
4807
  createSurfaces,
3491
4808
  decisionSchemas,
3492
4809
  decodeToken,
4810
+ detectPlatform,
4811
+ detectThemeFamily,
3493
4812
  encodeToken,
3494
4813
  evaluate,
3495
4814
  evaluateCondition,