@syntrologie/adapt-faq 2.8.0-canary.354 → 2.8.0-canary.355
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/dist/FAQWidgetLit.d.ts +26 -3
- package/dist/FAQWidgetLit.d.ts.map +1 -1
- package/dist/faq-styles.d.ts +31 -0
- package/dist/faq-styles.d.ts.map +1 -1
- package/dist/runtime.js +135 -57
- package/dist/runtime.js.map +2 -2
- package/dist/schema.d.ts +6 -6
- package/package.json +1 -1
package/dist/FAQWidgetLit.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare class FAQAccordionElement extends LitElement {
|
|
|
33
33
|
instanceId: {
|
|
34
34
|
type: StringConstructor;
|
|
35
35
|
};
|
|
36
|
-
|
|
36
|
+
_openId: {
|
|
37
37
|
state: boolean;
|
|
38
38
|
};
|
|
39
39
|
_highlightId: {
|
|
@@ -52,7 +52,7 @@ export declare class FAQAccordionElement extends LitElement {
|
|
|
52
52
|
faqConfig: FAQConfig;
|
|
53
53
|
runtime: FAQWidgetRuntime | null;
|
|
54
54
|
instanceId: string;
|
|
55
|
-
|
|
55
|
+
_openId: string | null;
|
|
56
56
|
_highlightId: string | null;
|
|
57
57
|
_searchQuery: string;
|
|
58
58
|
_feedbackState: Map<string, FeedbackValue>;
|
|
@@ -92,7 +92,15 @@ export declare class FAQAccordionElement extends LitElement {
|
|
|
92
92
|
/** Remove a question by instance id. */
|
|
93
93
|
private _removeItem;
|
|
94
94
|
private _unsubscribeAll;
|
|
95
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Master→detail takeover: tapping a list row opens its single-Q&A detail
|
|
97
|
+
* view (the whole widget swaps), so a long answer fills — and never
|
|
98
|
+
* overflows — the bounded velvet tile. There is no simultaneous multi-expand;
|
|
99
|
+
* one question owns the tile at a time.
|
|
100
|
+
*/
|
|
101
|
+
private _handleOpen;
|
|
102
|
+
/** Back affordance: return from the detail view to the full list. */
|
|
103
|
+
private _handleBack;
|
|
96
104
|
private _handleFeedback;
|
|
97
105
|
/**
|
|
98
106
|
* Unified render list. Merges compositionally-appended rows
|
|
@@ -108,8 +116,23 @@ export declare class FAQAccordionElement extends LitElement {
|
|
|
108
116
|
private _categoryGroups;
|
|
109
117
|
private _renderAnswer;
|
|
110
118
|
private _renderFeedback;
|
|
119
|
+
/**
|
|
120
|
+
* LIST-view row. A tappable question with its chevron \u2014 but NO inline answer
|
|
121
|
+
* body. Tapping it takes over the tile with the question's detail view (see
|
|
122
|
+
* {@link _renderDetail}). Keeps the per-row look/markers/highlight from the
|
|
123
|
+
* old accordion minus the inline-expanded answer that overflowed the tile.
|
|
124
|
+
*/
|
|
111
125
|
private _renderItem;
|
|
112
126
|
private _renderItems;
|
|
127
|
+
/**
|
|
128
|
+
* DETAIL view \u2014 the master\u2192detail takeover. Renders ONLY the open question:
|
|
129
|
+
* a back affordance, the question prominently, and its full answer via the
|
|
130
|
+
* SAME {@link _renderAnswer}/`renderAnswerHtml` path (all answer formats still
|
|
131
|
+
* work). The answer area scrolls if extremely long, so a single answer fills
|
|
132
|
+
* the bounded velvet tile and never pushes content past the `overflow:hidden`
|
|
133
|
+
* clip.
|
|
134
|
+
*/
|
|
135
|
+
private _renderDetail;
|
|
113
136
|
render(): import("lit-html").TemplateResult<1> | typeof nothing;
|
|
114
137
|
}
|
|
115
138
|
export default FAQAccordionElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FAQWidgetLit.d.ts","sourceRoot":"","sources":["../src/FAQWidgetLit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAQ,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAKhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAEV,SAAS,EAGT,aAAa,EACd,MAAM,SAAS,CAAC;AAkDjB;;;;;;;GAOG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IAKjD,OAAgB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"FAQWidgetLit.d.ts","sourceRoot":"","sources":["../src/FAQWidgetLit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAQ,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAKhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAEV,SAAS,EAGT,aAAa,EACd,MAAM,SAAS,CAAC;AAkDjB;;;;;;;GAOG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IAKjD,OAAgB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;MAcxB;IAMF,SAAS,EAAE,SAAS,CAKlB;IAEF,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAExC,UAAU,EAAE,MAAM,CAAgB;IAMlC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnC,YAAY,EAAE,MAAM,CAAM;IAC1B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAa;IACvD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAGjC,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,eAAe,CAA8C;IAMrE,OAAO,CAAC,mBAAmB,CAA6B;IACxD,OAAO,CAAC,OAAO,CAAuB;IACtC;gFAC4E;IAC5E,OAAO,CAAC,eAAe,CAA0B;IAMxC,gBAAgB;IAQhB,iBAAiB;IAKjB,oBAAoB;IAUpB,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAWnD,OAAO,CAAC,aAAa;IAqGrB;;;;;OAKG;IACH,OAAO,CAAC,uBAAuB;IAyB/B;;6DAEyD;IACzD,OAAO,CAAC,cAAc;IAOtB;2EACuE;IACvE,OAAO,CAAC,WAAW;IAcnB,iEAAiE;IACjE,OAAO,CAAC,UAAU;IAUlB,wCAAwC;IACxC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,eAAe;IAmBvB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAWnB,qEAAqE;IACrE,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,eAAe;IAYvB;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,eAAe;IAsCvB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAoDnB,OAAO,CAAC,YAAY;IAIpB;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAuDZ,MAAM;CAiJhB;AAUD,eAAe,mBAAmB,CAAC"}
|
package/dist/faq-styles.d.ts
CHANGED
|
@@ -100,6 +100,37 @@ export declare const baseStyles: {
|
|
|
100
100
|
readonly borderColor: "rgba(0, 0, 0, 0.2)";
|
|
101
101
|
readonly backgroundColor: "rgba(0, 0, 0, 0.04)";
|
|
102
102
|
};
|
|
103
|
+
readonly detail: {
|
|
104
|
+
readonly display: "flex";
|
|
105
|
+
readonly flexDirection: "column";
|
|
106
|
+
readonly gap: "12px";
|
|
107
|
+
readonly minHeight: "0";
|
|
108
|
+
};
|
|
109
|
+
readonly detailBack: {
|
|
110
|
+
readonly display: "inline-flex";
|
|
111
|
+
readonly alignItems: "center";
|
|
112
|
+
readonly gap: "4px";
|
|
113
|
+
readonly alignSelf: "flex-start";
|
|
114
|
+
readonly background: "none";
|
|
115
|
+
readonly border: "none";
|
|
116
|
+
readonly padding: "4px 0";
|
|
117
|
+
readonly cursor: "pointer";
|
|
118
|
+
readonly fontSize: "13px";
|
|
119
|
+
readonly fontWeight: 600;
|
|
120
|
+
readonly opacity: 0.85;
|
|
121
|
+
};
|
|
122
|
+
readonly detailQuestion: {
|
|
123
|
+
readonly fontSize: "var(--sc-content-item-font-size, 16px)";
|
|
124
|
+
readonly fontWeight: 600;
|
|
125
|
+
readonly lineHeight: 1.4;
|
|
126
|
+
};
|
|
127
|
+
readonly detailAnswer: {
|
|
128
|
+
readonly fontSize: "var(--sc-content-body-font-size, 14px)";
|
|
129
|
+
readonly lineHeight: 1.6;
|
|
130
|
+
readonly overflowY: "auto";
|
|
131
|
+
readonly flex: "1 1 auto";
|
|
132
|
+
readonly minHeight: "0";
|
|
133
|
+
};
|
|
103
134
|
readonly emptyState: {
|
|
104
135
|
readonly textAlign: "center";
|
|
105
136
|
readonly padding: "48px 24px";
|
package/dist/faq-styles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"faq-styles.d.ts","sourceRoot":"","sources":["../src/faq-styles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,eAAO,MAAM,UAAU
|
|
1
|
+
{"version":3,"file":"faq-styles.d.ts","sourceRoot":"","sources":["../src/faq-styles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4Ib,CAAC;AAMX,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqFvB,CAAC"}
|
package/dist/runtime.js
CHANGED
|
@@ -210,6 +210,40 @@ var baseStyles = {
|
|
|
210
210
|
borderColor: "rgba(0, 0, 0, 0.2)",
|
|
211
211
|
backgroundColor: "rgba(0, 0, 0, 0.04)"
|
|
212
212
|
},
|
|
213
|
+
// ── Master→detail takeover ──────────────────────────────────────────────
|
|
214
|
+
// The detail view fills the tile; the answer area scrolls if extremely long
|
|
215
|
+
// so a single answer never pushes content past the tile's overflow clip.
|
|
216
|
+
detail: {
|
|
217
|
+
display: "flex",
|
|
218
|
+
flexDirection: "column",
|
|
219
|
+
gap: "12px",
|
|
220
|
+
minHeight: "0"
|
|
221
|
+
},
|
|
222
|
+
detailBack: {
|
|
223
|
+
display: "inline-flex",
|
|
224
|
+
alignItems: "center",
|
|
225
|
+
gap: "4px",
|
|
226
|
+
alignSelf: "flex-start",
|
|
227
|
+
background: "none",
|
|
228
|
+
border: "none",
|
|
229
|
+
padding: "4px 0",
|
|
230
|
+
cursor: "pointer",
|
|
231
|
+
fontSize: "13px",
|
|
232
|
+
fontWeight: 600,
|
|
233
|
+
opacity: 0.85
|
|
234
|
+
},
|
|
235
|
+
detailQuestion: {
|
|
236
|
+
fontSize: "var(--sc-content-item-font-size, 16px)",
|
|
237
|
+
fontWeight: 600,
|
|
238
|
+
lineHeight: 1.4
|
|
239
|
+
},
|
|
240
|
+
detailAnswer: {
|
|
241
|
+
fontSize: "var(--sc-content-body-font-size, 14px)",
|
|
242
|
+
lineHeight: 1.6,
|
|
243
|
+
overflowY: "auto",
|
|
244
|
+
flex: "1 1 auto",
|
|
245
|
+
minHeight: "0"
|
|
246
|
+
},
|
|
213
247
|
emptyState: {
|
|
214
248
|
textAlign: "center",
|
|
215
249
|
padding: "48px 24px",
|
|
@@ -349,7 +383,10 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
349
383
|
this.runtime = null;
|
|
350
384
|
this.instanceId = "faq-widget";
|
|
351
385
|
// Internal state
|
|
352
|
-
|
|
386
|
+
// The currently-open question id (null = list view, value = detail view).
|
|
387
|
+
// The master→detail takeover swaps the whole widget to a single Q&A so a
|
|
388
|
+
// long answer never overflows the bounded velvet tile.
|
|
389
|
+
this._openId = null;
|
|
353
390
|
this._highlightId = null;
|
|
354
391
|
this._searchQuery = "";
|
|
355
392
|
this._feedbackState = /* @__PURE__ */ new Map();
|
|
@@ -429,11 +466,7 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
429
466
|
}).pop();
|
|
430
467
|
if (pendingEvent && Date.now() - pendingEvent.ts < 1e4) {
|
|
431
468
|
const questionId = pendingEvent.props.actionId.replace("faq:open:", "");
|
|
432
|
-
this.
|
|
433
|
-
requestAnimationFrame(() => {
|
|
434
|
-
const el = document.querySelector(`[data-faq-item-id="${questionId}"]`);
|
|
435
|
-
if (el) el.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
436
|
-
});
|
|
469
|
+
this._openId = questionId;
|
|
437
470
|
}
|
|
438
471
|
}
|
|
439
472
|
this._unsubCta = this.runtime.events.subscribe(
|
|
@@ -442,11 +475,7 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
442
475
|
const actionId = event.props?.actionId;
|
|
443
476
|
if (typeof actionId !== "string" || !actionId.startsWith("faq:open:")) return;
|
|
444
477
|
const questionId = actionId.replace("faq:open:", "");
|
|
445
|
-
this.
|
|
446
|
-
requestAnimationFrame(() => {
|
|
447
|
-
const el = document.querySelector(`[data-faq-item-id="${questionId}"]`);
|
|
448
|
-
if (el) el.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
449
|
-
});
|
|
478
|
+
this._openId = questionId;
|
|
450
479
|
this.runtime?.events.publish("canvas.requestOpen");
|
|
451
480
|
}
|
|
452
481
|
);
|
|
@@ -457,17 +486,13 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
457
486
|
const itemId = event.props?.itemId;
|
|
458
487
|
if (tileId !== this.instanceId) return;
|
|
459
488
|
if (!itemId) return;
|
|
460
|
-
this.
|
|
489
|
+
this._openId = itemId;
|
|
461
490
|
this._highlightId = itemId;
|
|
462
491
|
if (this._highlightTimer !== null) clearTimeout(this._highlightTimer);
|
|
463
492
|
this._highlightTimer = setTimeout(() => {
|
|
464
493
|
this._highlightId = null;
|
|
465
494
|
this._highlightTimer = null;
|
|
466
495
|
}, 1500);
|
|
467
|
-
requestAnimationFrame(() => {
|
|
468
|
-
const el = document.querySelector(`[data-faq-item-id="${itemId}"]`);
|
|
469
|
-
if (el) el.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
470
|
-
});
|
|
471
496
|
};
|
|
472
497
|
if (this.runtime.events.getRecent) {
|
|
473
498
|
const recent = this.runtime.events.getRecent({ names: ["notification.deep_link"] }, 5);
|
|
@@ -568,28 +593,34 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
568
593
|
// -----------------------------------------------------------------------
|
|
569
594
|
// Handlers
|
|
570
595
|
// -----------------------------------------------------------------------
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
next.delete(id);
|
|
580
|
-
} else {
|
|
581
|
-
next.add(id);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
const willBeExpanded = !prev.has(id);
|
|
585
|
-
this._expandedIds = next;
|
|
596
|
+
/**
|
|
597
|
+
* Master→detail takeover: tapping a list row opens its single-Q&A detail
|
|
598
|
+
* view (the whole widget swaps), so a long answer fills — and never
|
|
599
|
+
* overflows — the bounded velvet tile. There is no simultaneous multi-expand;
|
|
600
|
+
* one question owns the tile at a time.
|
|
601
|
+
*/
|
|
602
|
+
_handleOpen(id) {
|
|
603
|
+
this._openId = id;
|
|
586
604
|
this.runtime?.events.publish("faq:toggled", {
|
|
587
605
|
instanceId: this.instanceId,
|
|
588
606
|
questionId: id,
|
|
589
|
-
expanded:
|
|
607
|
+
expanded: true,
|
|
590
608
|
timestamp: Date.now()
|
|
591
609
|
});
|
|
592
610
|
}
|
|
611
|
+
/** Back affordance: return from the detail view to the full list. */
|
|
612
|
+
_handleBack() {
|
|
613
|
+
const id = this._openId;
|
|
614
|
+
this._openId = null;
|
|
615
|
+
if (id !== null) {
|
|
616
|
+
this.runtime?.events.publish("faq:toggled", {
|
|
617
|
+
instanceId: this.instanceId,
|
|
618
|
+
questionId: id,
|
|
619
|
+
expanded: false,
|
|
620
|
+
timestamp: Date.now()
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
593
624
|
_handleFeedback(itemId, question, value) {
|
|
594
625
|
const next = new Map(this._feedbackState);
|
|
595
626
|
next.set(itemId, value);
|
|
@@ -694,15 +725,19 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
694
725
|
</div>
|
|
695
726
|
`;
|
|
696
727
|
}
|
|
697
|
-
|
|
728
|
+
/**
|
|
729
|
+
* LIST-view row. A tappable question with its chevron \u2014 but NO inline answer
|
|
730
|
+
* body. Tapping it takes over the tile with the question's detail view (see
|
|
731
|
+
* {@link _renderDetail}). Keeps the per-row look/markers/highlight from the
|
|
732
|
+
* old accordion minus the inline-expanded answer that overflowed the tile.
|
|
733
|
+
*/
|
|
734
|
+
_renderItem(item, isLast, theme) {
|
|
698
735
|
const colors = themeStyles[theme];
|
|
699
|
-
const isExpanded = this._expandedIds.has(item.config.id);
|
|
700
736
|
const isHighlighted = this._highlightId === item.config.id;
|
|
701
737
|
const isHovered = this._hoveredId === item.config.id;
|
|
702
738
|
const itemStyle = {
|
|
703
739
|
...baseStyles.item,
|
|
704
740
|
...colors.item,
|
|
705
|
-
...isExpanded ? colors.itemExpanded : {},
|
|
706
741
|
...isHighlighted ? {
|
|
707
742
|
boxShadow: `0 0 0 2px ${purple[4]}, 0 0 12px rgba(106, 89, 206, 0.4)`,
|
|
708
743
|
transition: "box-shadow 0.3s ease"
|
|
@@ -716,13 +751,7 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
716
751
|
};
|
|
717
752
|
const chevronStyle = {
|
|
718
753
|
...baseStyles.chevron,
|
|
719
|
-
transform:
|
|
720
|
-
};
|
|
721
|
-
const answerStyle = {
|
|
722
|
-
...baseStyles.answer,
|
|
723
|
-
...colors.answer,
|
|
724
|
-
maxHeight: isExpanded ? "500px" : "0",
|
|
725
|
-
paddingBottom: isExpanded ? "16px" : "0"
|
|
754
|
+
transform: "rotate(0deg)"
|
|
726
755
|
};
|
|
727
756
|
return html`
|
|
728
757
|
<div
|
|
@@ -732,8 +761,8 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
732
761
|
<button
|
|
733
762
|
type="button"
|
|
734
763
|
style=${styleMap(sm(questionStyle))}
|
|
735
|
-
aria-expanded=${
|
|
736
|
-
@click=${() => this.
|
|
764
|
+
aria-expanded=${false}
|
|
765
|
+
@click=${() => this._handleOpen(item.config.id)}
|
|
737
766
|
@mouseenter=${() => {
|
|
738
767
|
this._hoveredId = item.config.id;
|
|
739
768
|
}}
|
|
@@ -744,13 +773,51 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
744
773
|
<span>${item.config.question}</span>
|
|
745
774
|
<span style=${styleMap(sm(chevronStyle))}>\u203A</span>
|
|
746
775
|
</button>
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
776
|
+
</div>
|
|
777
|
+
`;
|
|
778
|
+
}
|
|
779
|
+
_renderItems(items, theme) {
|
|
780
|
+
return items.map((item, index) => this._renderItem(item, index === items.length - 1, theme));
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* DETAIL view \u2014 the master\u2192detail takeover. Renders ONLY the open question:
|
|
784
|
+
* a back affordance, the question prominently, and its full answer via the
|
|
785
|
+
* SAME {@link _renderAnswer}/`renderAnswerHtml` path (all answer formats still
|
|
786
|
+
* work). The answer area scrolls if extremely long, so a single answer fills
|
|
787
|
+
* the bounded velvet tile and never pushes content past the `overflow:hidden`
|
|
788
|
+
* clip.
|
|
789
|
+
*/
|
|
790
|
+
_renderDetail(item, theme, feedbackConfig) {
|
|
791
|
+
const colors = themeStyles[theme];
|
|
792
|
+
const backStyle = {
|
|
793
|
+
...baseStyles.detailBack,
|
|
794
|
+
...colors.question
|
|
795
|
+
};
|
|
796
|
+
const detailQuestionStyle = {
|
|
797
|
+
...baseStyles.detailQuestion,
|
|
798
|
+
...colors.question
|
|
799
|
+
};
|
|
800
|
+
const detailAnswerStyle = {
|
|
801
|
+
...baseStyles.detailAnswer,
|
|
802
|
+
...colors.answer
|
|
803
|
+
};
|
|
804
|
+
return html`
|
|
805
|
+
<div style=${styleMap(sm(baseStyles.detail))} data-faq-detail=${item.config.id}>
|
|
806
|
+
<button
|
|
807
|
+
type="button"
|
|
808
|
+
style=${styleMap(sm(backStyle))}
|
|
809
|
+
data-faq-back=""
|
|
810
|
+
aria-label="Back to questions"
|
|
811
|
+
@click=${() => this._handleBack()}
|
|
751
812
|
>
|
|
813
|
+
\u2039 Back to questions
|
|
814
|
+
</button>
|
|
815
|
+
|
|
816
|
+
<div style=${styleMap(sm(detailQuestionStyle))}>${item.config.question}</div>
|
|
817
|
+
|
|
818
|
+
<div style=${styleMap(sm(detailAnswerStyle))} aria-hidden=${false}>
|
|
752
819
|
${this._renderAnswer(item.config.answer)}
|
|
753
|
-
${
|
|
820
|
+
${feedbackConfig ? this._renderFeedback(
|
|
754
821
|
item,
|
|
755
822
|
feedbackConfig,
|
|
756
823
|
this._feedbackState.get(item.config.id),
|
|
@@ -760,11 +827,6 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
760
827
|
</div>
|
|
761
828
|
`;
|
|
762
829
|
}
|
|
763
|
-
_renderItems(items, theme, feedbackConfig) {
|
|
764
|
-
return items.map(
|
|
765
|
-
(item, index) => this._renderItem(item, index === items.length - 1, theme, feedbackConfig)
|
|
766
|
-
);
|
|
767
|
-
}
|
|
768
830
|
// -----------------------------------------------------------------------
|
|
769
831
|
// Render
|
|
770
832
|
// -----------------------------------------------------------------------
|
|
@@ -808,6 +870,20 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
808
870
|
</div>
|
|
809
871
|
`;
|
|
810
872
|
}
|
|
873
|
+
if (this._openId !== null) {
|
|
874
|
+
const openItem = filtered.find((q) => q.config.id === this._openId);
|
|
875
|
+
if (openItem) {
|
|
876
|
+
return html`
|
|
877
|
+
<div
|
|
878
|
+
style=${styleMap(sm(containerStyle))}
|
|
879
|
+
data-adaptive-id=${this.instanceId}
|
|
880
|
+
data-adaptive-type="adaptive-faq"
|
|
881
|
+
>
|
|
882
|
+
${this._renderDetail(openItem, theme, feedbackConfig)}
|
|
883
|
+
</div>
|
|
884
|
+
`;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
811
887
|
return html`
|
|
812
888
|
<div
|
|
813
889
|
style=${styleMap(sm(containerStyle))}
|
|
@@ -845,9 +921,9 @@ var FAQAccordionElement = class extends LitElement {
|
|
|
845
921
|
${category}
|
|
846
922
|
</div>
|
|
847
923
|
` : nothing}
|
|
848
|
-
${this._renderItems(items, theme
|
|
924
|
+
${this._renderItems(items, theme)}
|
|
849
925
|
`
|
|
850
|
-
) : this._renderItems(filtered, theme
|
|
926
|
+
) : this._renderItems(filtered, theme)}
|
|
851
927
|
</div>
|
|
852
928
|
|
|
853
929
|
${this.faqConfig.searchable && filtered.length === 0 && this._searchQuery ? html`
|
|
@@ -870,7 +946,9 @@ FAQAccordionElement.properties = {
|
|
|
870
946
|
runtime: { attribute: false },
|
|
871
947
|
instanceId: { type: String },
|
|
872
948
|
// Internal reactive state (prefixed with _ to signal "private")
|
|
873
|
-
|
|
949
|
+
// _openId: currently-open question id for the master→detail takeover.
|
|
950
|
+
// null = LIST view; a value = DETAIL view showing only that single Q&A.
|
|
951
|
+
_openId: { state: true },
|
|
874
952
|
_highlightId: { state: true },
|
|
875
953
|
_searchQuery: { state: true },
|
|
876
954
|
_feedbackState: { state: true },
|
package/dist/runtime.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/executors.ts", "../src/FAQWidgetLit.ts", "../src/faq-styles.ts", "../src/runtime.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Adaptive FAQ - Action Executors\n *\n * Three executors that operate on the FAQStore:\n * - executeScrollToFaq: scroll to a FAQ item and optionally expand it\n * - executeToggleFaqItem: open / close / toggle a FAQ item\n * - executeUpdateFaq: add, remove, reorder, or replace FAQ items\n */\n\nimport type { FAQStore } from './state';\nimport type {\n ExecutorContext,\n ExecutorResult,\n FAQQuestionAction,\n ScrollToFaqAction,\n ToggleFaqItemAction,\n UpdateFaqAction,\n} from './types';\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Resolve a FAQ item by direct ID or by fuzzy question text match.\n * Throws if neither yields a result.\n */\nfunction resolveItem(store: FAQStore, itemId?: string, itemQuestion?: string): FAQQuestionAction {\n if (itemId) {\n const found = store.getState().items.find((i) => i.config.id === itemId);\n if (found) return found;\n }\n\n if (itemQuestion) {\n const found = store.findByQuestion(itemQuestion);\n if (found) return found;\n }\n\n throw new Error('FAQ item not found');\n}\n\n// ============================================================================\n// executeScrollToFaq\n// ============================================================================\n\n/**\n * Scroll to a FAQ item in the DOM and optionally expand it.\n *\n * Looks up the item by `itemId` or `itemQuestion`, scrolls the matching\n * `[data-faq-item-id]` element into view, and expands it unless\n * `expand` is explicitly set to `false`.\n */\nexport async function executeScrollToFaq(\n action: ScrollToFaqAction,\n context: ExecutorContext,\n store: FAQStore\n): Promise<ExecutorResult> {\n const item = resolveItem(store, action.itemId, action.itemQuestion);\n const { id } = item.config;\n\n // Expand the item unless explicitly told not to\n if (action.expand !== false) {\n store.expand(id);\n }\n\n // Scroll the DOM element into view (may be absent in test environments)\n const el = document.querySelector(`[data-faq-item-id=\"${id}\"]`);\n if (el) {\n el.scrollIntoView({\n behavior: action.behavior ?? 'smooth',\n });\n }\n\n // Publish analytics event\n context.publishEvent('faq:scroll_to', { itemId: id });\n\n return {\n cleanup: () => {\n // Optionally collapse on revert\n },\n };\n}\n\n// ============================================================================\n// executeToggleFaqItem\n// ============================================================================\n\n/**\n * Open, close, or toggle a FAQ item's expanded state.\n */\nexport async function executeToggleFaqItem(\n action: ToggleFaqItemAction,\n context: ExecutorContext,\n store: FAQStore\n): Promise<ExecutorResult> {\n const item = resolveItem(store, action.itemId, action.itemQuestion);\n const { id } = item.config;\n const desiredState = action.state ?? 'toggle';\n\n let newState: 'open' | 'closed';\n\n switch (desiredState) {\n case 'open':\n store.expand(id);\n newState = 'open';\n break;\n case 'closed':\n store.collapse(id);\n newState = 'closed';\n break;\n default: {\n const wasExpanded = store.getState().expandedItems.has(id);\n store.toggle(id);\n newState = wasExpanded ? 'closed' : 'open';\n break;\n }\n }\n\n context.publishEvent('faq:toggle', { itemId: id, newState });\n\n return {\n cleanup: () => {\n // Revert toggle on cleanup\n },\n };\n}\n\n// ============================================================================\n// executeUpdateFaq\n// ============================================================================\n\n/**\n * Add, remove, reorder, or replace FAQ items in the store.\n */\nexport async function executeUpdateFaq(\n action: UpdateFaqAction,\n context: ExecutorContext,\n store: FAQStore\n): Promise<ExecutorResult> {\n switch (action.operation) {\n case 'add': {\n const items = action.items ?? [];\n const position = action.position === 'prepend' ? 'prepend' : 'append';\n store.addItems(items, position);\n break;\n }\n\n case 'remove': {\n if (!action.itemId) {\n throw new Error('FAQ item not found');\n }\n // Verify the item exists before removing\n const exists = store.getState().items.some((i) => i.config.id === action.itemId);\n if (!exists) {\n throw new Error('FAQ item not found');\n }\n store.removeItem(action.itemId);\n break;\n }\n\n case 'reorder': {\n const order = action.order ?? [];\n store.reorderItems(order);\n break;\n }\n\n case 'replace': {\n const items = action.items ?? [];\n store.replaceItems(items);\n break;\n }\n }\n\n context.publishEvent('faq:update', { operation: action.operation });\n\n return {\n cleanup: () => {\n // Could snapshot previous state for undo\n },\n };\n}\n\n// ============================================================================\n// Executor Definitions for Registration\n// ============================================================================\n\n/**\n * All executors provided by adaptive-faq.\n * These are registered with the runtime's ExecutorRegistry.\n */\nexport const executorDefinitions = [\n { kind: 'faq:scroll_to', executor: executeScrollToFaq },\n { kind: 'faq:toggle_item', executor: executeToggleFaqItem },\n { kind: 'faq:update', executor: executeUpdateFaq },\n] as const;\n", "/**\n * Adaptive FAQ - FAQWidgetLit\n *\n * Lit web component equivalent of FAQWidget.tsx.\n * Renders a collapsible Q&A accordion with search, category grouping,\n * feedback, and markdown rendering \u2014 all as a custom element with no\n * Shadow DOM (light DOM via createRenderRoot).\n *\n * Tag name: <syntro-faq-accordion>\n *\n * Decorator-free: uses `static override properties` (tsconfig has no\n * experimentalDecorators).\n */\n\nimport { purple } from '@syntro/design-system/tokens';\nimport { html, LitElement, nothing } from 'lit';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\nimport { getAnswerText, renderAnswerHtml } from './answerRendering';\nimport { baseStyles, themeStyles } from './faq-styles';\nimport type { FAQWidgetRuntime } from './faq-types';\nimport type {\n FAQAnswer,\n FAQConfig,\n FAQQuestionAction,\n FeedbackConfig,\n FeedbackValue,\n} from './types';\n\n// ============================================================================\n// Utility \u2014 styleMap accepts Record<string, string | number | undefined>\n// but its TypeScript signature is overly narrow in some Lit versions.\n// Cast through unknown to avoid false positives when style values include\n// numeric CSS properties (fontWeight, lineHeight, etc.).\n// ============================================================================\n\nfunction sm(styles: Record<string, unknown>): Record<string, string> {\n return styles as unknown as Record<string, string>;\n}\n\nfunction resolveFeedbackConfig(\n feedback: boolean | FeedbackConfig | undefined\n): FeedbackConfig | null {\n if (!feedback) return null;\n if (feedback === true) return { style: 'thumbs' };\n return feedback;\n}\n\nfunction getFeedbackPrompt(feedbackConfig: FeedbackConfig): string {\n return feedbackConfig.prompt ?? 'Was this helpful?';\n}\n\n/**\n * Small deterministic string hash (djb2, base36) for content-derived atomic\n * FAQ row ids \u2014 stable per question across re-mounts so expand/feedback state\n * keyed by id sticks to the right row even if the list reorders.\n */\nfunction hashFaqId(text: string): string {\n let h = 5381;\n for (let i = 0; i < text.length; i++) {\n h = (Math.imul(h, 33) ^ text.charCodeAt(i)) >>> 0;\n }\n return h.toString(36);\n}\n\nfunction resolveTheme(theme: FAQConfig['theme'] | undefined): 'light' | 'dark' {\n if (theme && theme !== 'auto') return theme;\n if (typeof window !== 'undefined') {\n return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n return 'light';\n}\n\n// ============================================================================\n// FAQAccordionElement \u2014 Lit element\n// ============================================================================\n\n/**\n * <syntro-faq-accordion> \u2014 light-DOM Lit web component.\n *\n * Set properties imperatively (no attribute serialisation for objects):\n * el.faqConfig = { expandBehavior: 'single', ... };\n * el.runtime = runtimeInstance;\n * el.instanceId = 'my-faq';\n */\nexport class FAQAccordionElement extends LitElement {\n // -----------------------------------------------------------------------\n // Reactive properties (no decorators \u2014 tsconfig forbids experimentalDecorators)\n // -----------------------------------------------------------------------\n\n static override properties = {\n // Public API \u2014 set from the outside\n faqConfig: { attribute: false },\n runtime: { attribute: false },\n instanceId: { type: String },\n\n // Internal reactive state (prefixed with _ to signal \"private\")\n _expandedIds: { state: true },\n _highlightId: { state: true },\n _searchQuery: { state: true },\n _feedbackState: { state: true },\n _hoveredId: { state: true },\n };\n\n // -----------------------------------------------------------------------\n // Property declarations\n // -----------------------------------------------------------------------\n\n faqConfig: FAQConfig = {\n expandBehavior: 'single',\n searchable: false,\n theme: 'auto',\n actions: [],\n };\n\n runtime: FAQWidgetRuntime | null = null;\n\n instanceId: string = 'faq-widget';\n\n // Internal state\n _expandedIds: Set<string> = new Set();\n _highlightId: string | null = null;\n _searchQuery: string = '';\n _feedbackState: Map<string, FeedbackValue> = new Map();\n _hoveredId: string | null = null;\n\n // Subscription cleanup handles\n private _unsubContext: (() => void) | null = null;\n private _unsubAccumulator: (() => void) | null = null;\n private _unsubCta: (() => void) | null = null;\n private _unsubDeepLink: (() => void) | null = null;\n private _unsubSessionMetrics: (() => void) | null = null;\n private _highlightTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Compositional-child wiring \u2014 faq:question items the LLM mounts into this\n // accordion's tile arrive as `element.compositional_append` events (see\n // adaptive-chatbot's ItemHandler). Without this subscription the questions\n // are published into the void and the accordion renders empty.\n private _unsubCompositional: (() => void) | null = null;\n private _tileId: string | null = null;\n /** Instance ids already appended via the compositional bus \u2014 dedups\n * the subscribe-then-replay path (and re-subscribes on runtime change). */\n private _llmAppendedIds: Set<string> = new Set();\n\n // -----------------------------------------------------------------------\n // Light DOM \u2014 no Shadow DOM so CSS variables from the host page apply\n // -----------------------------------------------------------------------\n\n override createRenderRoot() {\n return this;\n }\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n override connectedCallback() {\n super.connectedCallback();\n this._subscribeAll();\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._unsubscribeAll();\n if (this._highlightTimer !== null) {\n clearTimeout(this._highlightTimer);\n this._highlightTimer = null;\n }\n }\n\n // Re-subscribe when runtime changes (property may be set after connectedCallback)\n override updated(changedProps: Map<string, unknown>) {\n if (changedProps.has('runtime')) {\n this._unsubscribeAll();\n this._subscribeAll();\n }\n }\n\n // -----------------------------------------------------------------------\n // Subscription management\n // -----------------------------------------------------------------------\n\n private _subscribeAll() {\n if (!this.runtime) return;\n\n // Context changes \u2192 force re-render\n this._unsubContext = this.runtime.context.subscribe(() => {\n this.requestUpdate();\n });\n\n // Accumulator changes \u2192 force re-render (for event_count triggerWhen)\n if (this.runtime.accumulator?.subscribe) {\n this._unsubAccumulator = this.runtime.accumulator.subscribe(() => {\n this.requestUpdate();\n });\n }\n\n // Session metric changes \u2192 force re-render (for session_metric triggerWhen)\n if (this.runtime.sessionMetrics?.subscribe) {\n this._unsubSessionMetrics = this.runtime.sessionMetrics.subscribe(() => {\n this.requestUpdate();\n });\n }\n\n // faq:open:* events from overlay CTA clicks\n if (this.runtime.events.subscribe) {\n // Check EventBus history for pending faq:open events\n if (this.runtime.events.getRecent) {\n const recentEvents = this.runtime.events.getRecent(\n { patterns: ['^action\\\\.tooltip_cta_clicked$', '^action\\\\.modal_cta_clicked$'] },\n 10\n );\n const pendingEvent = recentEvents\n .filter((e) => {\n const actionId = e.props?.actionId;\n return typeof actionId === 'string' && actionId.startsWith('faq:open:');\n })\n .pop();\n\n if (pendingEvent && Date.now() - pendingEvent.ts < 10000) {\n const questionId = (pendingEvent.props!.actionId as string).replace('faq:open:', '');\n this._expandedIds = new Set([questionId]);\n requestAnimationFrame(() => {\n const el = document.querySelector(`[data-faq-item-id=\"${questionId}\"]`);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n });\n }\n }\n\n this._unsubCta = this.runtime.events.subscribe(\n { patterns: ['^action\\\\.tooltip_cta_clicked$', '^action\\\\.modal_cta_clicked$'] },\n (event) => {\n const actionId = event.props?.actionId;\n if (typeof actionId !== 'string' || !actionId.startsWith('faq:open:')) return;\n const questionId = actionId.replace('faq:open:', '');\n this._expandedIds = new Set([questionId]);\n requestAnimationFrame(() => {\n const el = document.querySelector(`[data-faq-item-id=\"${questionId}\"]`);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n });\n this.runtime?.events.publish('canvas.requestOpen');\n }\n );\n }\n\n // notification.deep_link events\n if (this.runtime.events.subscribe) {\n const handleDeepLink = (event: { name: string; props?: Record<string, unknown> }) => {\n const tileId = event.props?.tileId as string | undefined;\n const itemId = event.props?.itemId as string | undefined;\n if (tileId !== this.instanceId) return;\n if (!itemId) return;\n\n this._expandedIds = new Set([itemId]);\n this._highlightId = itemId;\n\n if (this._highlightTimer !== null) clearTimeout(this._highlightTimer);\n this._highlightTimer = setTimeout(() => {\n this._highlightId = null;\n this._highlightTimer = null;\n }, 1500);\n\n requestAnimationFrame(() => {\n const el = document.querySelector(`[data-faq-item-id=\"${itemId}\"]`);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n });\n };\n\n // Check recent events (may have fired before widget mounted)\n if (this.runtime.events.getRecent) {\n const recent = this.runtime.events.getRecent({ names: ['notification.deep_link'] }, 5);\n const pending = recent\n .filter((e) => (e.props?.tileId as string) === this.instanceId && e.props?.itemId)\n .pop();\n if (pending && Date.now() - pending.ts < 10000) {\n handleDeepLink(pending);\n }\n }\n\n this._unsubDeepLink = this.runtime.events.subscribe(\n { names: ['notification.deep_link'] },\n handleDeepLink\n );\n }\n\n // Compositional children: faq:question items mounted into this\n // accordion's tile. The ItemHandler publishes one event per kind-\n // agnostic item mount; we filter to our tile and route into\n // `faqConfig.actions`. Mirrors AdaptiveChipsStrip's CompositionalContainer.\n this._subscribeCompositional();\n }\n\n /**\n * Subscribe to `element.compositional_*` events targeting this accordion's\n * tile, and ask the element store to replay any items it already holds for\n * us (covers the case where the accordion mounts AFTER the item did \u2014 the\n * inline-slot hydration race that otherwise silently drops the question).\n */\n private _subscribeCompositional() {\n const bus = this.runtime?.events;\n if (!bus?.subscribe) return;\n this._tileId = this._resolveTileId();\n if (!this._tileId) return;\n const tileId = this._tileId;\n this._unsubCompositional = bus.subscribe((event) => {\n const props = event.props ?? {};\n if (props.tile_id !== tileId) return;\n const instanceId = String(props.instance_id ?? '');\n if (event.name === 'element.compositional_append') {\n this._insertItem(\n instanceId,\n props.item as FAQQuestionAction,\n (props.position as 'append' | 'prepend') ?? 'append'\n );\n } else if (event.name === 'element.compositional_patch') {\n this._patchItem(instanceId, props.item as FAQQuestionAction);\n } else if (event.name === 'element.compositional_remove') {\n this._removeItem(instanceId);\n }\n });\n bus.publish('element.compositional_replay_request', { tile_id: tileId });\n }\n\n /** Tile id for compositional filtering: the enclosing tile card's\n * `data-tile-id` (set by SyntroTileCard), falling back to `instanceId`\n * when the accordion is mounted outside a tile card. */\n private _resolveTileId(): string | null {\n const anchor = this.closest<HTMLElement>('[data-tile-id]');\n const fromDom = anchor?.getAttribute('data-tile-id');\n if (fromDom) return fromDom;\n return this.instanceId && this.instanceId !== 'faq-widget' ? this.instanceId : null;\n }\n\n /** Append (or prepend) a faq:question the LLM mounted. The wire shape is a\n * fully-formed `{kind, config}` envelope, so we store it verbatim. */\n private _insertItem(\n instanceId: string,\n item: FAQQuestionAction,\n position: 'append' | 'prepend'\n ): void {\n if (!instanceId || !item?.config?.id) return;\n if (this._llmAppendedIds.has(instanceId)) return; // dedup replay / re-subscribe\n this._llmAppendedIds.add(instanceId);\n const actions = this.faqConfig.actions ?? [];\n const next = position === 'prepend' ? [item, ...actions] : [...actions, item];\n // Reassign so Lit sees the change (faqConfig is attribute:false).\n this.faqConfig = { ...this.faqConfig, actions: next };\n }\n\n /** Replace an existing question's content (full replacement). */\n private _patchItem(instanceId: string, item: FAQQuestionAction): void {\n if (!instanceId || !item?.config) return;\n const actions = this.faqConfig.actions ?? [];\n const idx = actions.findIndex((a) => a.config.id === instanceId);\n if (idx < 0) return;\n const next = [...actions];\n next[idx] = item;\n this.faqConfig = { ...this.faqConfig, actions: next };\n }\n\n /** Remove a question by instance id. */\n private _removeItem(instanceId: string): void {\n if (!instanceId) return;\n const actions = this.faqConfig.actions ?? [];\n const next = actions.filter((a) => a.config.id !== instanceId);\n if (next.length === actions.length) return;\n this._llmAppendedIds.delete(instanceId);\n this.faqConfig = { ...this.faqConfig, actions: next };\n }\n\n private _unsubscribeAll() {\n this._unsubContext?.();\n this._unsubAccumulator?.();\n this._unsubSessionMetrics?.();\n this._unsubCta?.();\n this._unsubDeepLink?.();\n this._unsubCompositional?.();\n this._unsubContext = null;\n this._unsubAccumulator = null;\n this._unsubSessionMetrics = null;\n this._unsubCta = null;\n this._unsubDeepLink = null;\n this._unsubCompositional = null;\n }\n\n // -----------------------------------------------------------------------\n // Handlers\n // -----------------------------------------------------------------------\n\n private _handleToggle(id: string) {\n const prev = this._expandedIds;\n let next: Set<string>;\n\n if (this.faqConfig.expandBehavior === 'single') {\n next = prev.has(id) ? new Set() : new Set([id]);\n } else {\n next = new Set(prev);\n if (prev.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n }\n\n const willBeExpanded = !prev.has(id);\n this._expandedIds = next;\n\n this.runtime?.events.publish('faq:toggled', {\n instanceId: this.instanceId,\n questionId: id,\n expanded: willBeExpanded,\n timestamp: Date.now(),\n });\n }\n\n private _handleFeedback(itemId: string, question: string, value: FeedbackValue) {\n const next = new Map(this._feedbackState);\n next.set(itemId, value);\n this._feedbackState = next;\n\n this.runtime?.events.publish('faq:feedback', { itemId, question, value });\n }\n\n // -----------------------------------------------------------------------\n // Computed helpers\n // -----------------------------------------------------------------------\n\n /**\n * Unified render list. Merges compositionally-appended rows\n * (`faqConfig.actions`, the container-then-stream path) with atomically\n * authored rows (`faqConfig.questions`, the struct_list path) normalized\n * into the same `FAQQuestionAction` shape. The atomic path is how the LLM\n * mounts a complete FAQ in one call \u2014 so it renders whole, never empty.\n */\n private _allQuestions(): FAQQuestionAction[] {\n const compositional = this.faqConfig.actions ?? [];\n // Content-derived id (not positional). Expand/feedback state is keyed by id;\n // if the LLM re-mounts the FAQ with a reordered or shortened list, a\n // positional `atomic-${i}` would re-point that state at a different\n // question. Hashing the question text keeps the id stable per question\n // across re-mounts. A `-N` suffix disambiguates same-text rows (including\n // empty strings, which all hash to the same value) so they never share\n // expand/feedback state \u2014 stable as long as their relative order is.\n const seen = new Map<string, number>();\n const atomic = (this.faqConfig.questions ?? []).map((q): FAQQuestionAction => {\n let id = `atomic-${hashFaqId(q.question)}`;\n const dup = seen.get(id) ?? 0;\n seen.set(id, dup + 1);\n if (dup > 0) id = `${id}-${dup}`;\n return {\n kind: 'faq:question',\n config: {\n id,\n question: q.question,\n answer: q.answer,\n category: q.category,\n },\n };\n });\n return [...atomic, ...compositional];\n }\n\n private _visibleQuestions(): FAQQuestionAction[] {\n return this._allQuestions().filter((q) => {\n if (!q.triggerWhen) return true;\n if (!this.runtime) return true;\n const result = this.runtime.evaluateSync<boolean>(q.triggerWhen);\n return result.value;\n });\n }\n\n private _orderedQuestions(visible: FAQQuestionAction[]): FAQQuestionAction[] {\n if (this.faqConfig.ordering === 'priority') {\n return [...visible].sort((a, b) => (b.config.priority ?? 0) - (a.config.priority ?? 0));\n }\n return visible;\n }\n\n private _filteredQuestions(ordered: FAQQuestionAction[]): FAQQuestionAction[] {\n const q = this._searchQuery.trim().toLowerCase();\n if (!this.faqConfig.searchable || !q) return ordered;\n return ordered.filter(\n (item) =>\n item.config.question.toLowerCase().includes(q) ||\n getAnswerText(item.config.answer).toLowerCase().includes(q) ||\n item.config.category?.toLowerCase().includes(q)\n );\n }\n\n private _categoryGroups(\n filtered: FAQQuestionAction[]\n ): Map<string | undefined, FAQQuestionAction[]> {\n const groups = new Map<string | undefined, FAQQuestionAction[]>();\n for (const item of filtered) {\n const cat = item.config.category;\n if (!groups.has(cat)) groups.set(cat, []);\n groups.get(cat)!.push(item);\n }\n return groups;\n }\n\n // -----------------------------------------------------------------------\n // Render helpers\n // -----------------------------------------------------------------------\n\n private _renderAnswer(answer: FAQAnswer) {\n const html_str = renderAnswerHtml(answer);\n return html`<div style=\"margin:0\" data-faq-markdown=\"\">${unsafeHTML(html_str)}</div>`;\n }\n\n private _renderFeedback(\n item: FAQQuestionAction,\n feedbackConfig: FeedbackConfig,\n feedbackValue: FeedbackValue | undefined,\n theme: 'light' | 'dark'\n ) {\n const colors = themeStyles[theme];\n const feedbackStyle = { ...baseStyles.feedback, ...colors.feedbackPrompt };\n\n return html`\n <div style=${styleMap(sm(feedbackStyle))}>\n <span>${getFeedbackPrompt(feedbackConfig)}</span>\n <button\n type=\"button\"\n style=${styleMap(\n sm({\n ...baseStyles.feedbackButton,\n ...(feedbackValue === 'up' ? baseStyles.feedbackButtonSelected : {}),\n })\n )}\n aria-label=\"Thumbs up\"\n @click=${() => this._handleFeedback(item.config.id, item.config.question, 'up')}\n >\\uD83D\\uDC4D</button>\n <button\n type=\"button\"\n style=${styleMap(\n sm({\n ...baseStyles.feedbackButton,\n ...(feedbackValue === 'down' ? baseStyles.feedbackButtonSelected : {}),\n })\n )}\n aria-label=\"Thumbs down\"\n @click=${() => this._handleFeedback(item.config.id, item.config.question, 'down')}\n >\\uD83D\\uDC4E</button>\n </div>\n `;\n }\n\n private _renderItem(\n item: FAQQuestionAction,\n isLast: boolean,\n theme: 'light' | 'dark',\n feedbackConfig: FeedbackConfig | null\n ) {\n const colors = themeStyles[theme];\n const isExpanded = this._expandedIds.has(item.config.id);\n const isHighlighted = this._highlightId === item.config.id;\n const isHovered = this._hoveredId === item.config.id;\n\n const itemStyle = {\n ...baseStyles.item,\n ...colors.item,\n ...(isExpanded ? colors.itemExpanded : {}),\n ...(isHighlighted\n ? {\n boxShadow: `0 0 0 2px ${purple[4]}, 0 0 12px rgba(106, 89, 206, 0.4)`,\n transition: 'box-shadow 0.3s ease',\n }\n : {}),\n ...(!isLast ? { borderBottom: 'var(--sc-content-item-divider, none)' } : {}),\n };\n\n const questionStyle = {\n ...baseStyles.question,\n ...colors.question,\n ...(isHovered ? colors.questionHover : {}),\n };\n\n const chevronStyle = {\n ...baseStyles.chevron,\n transform: isExpanded ? 'rotate(90deg)' : 'rotate(0deg)',\n };\n\n const answerStyle = {\n ...baseStyles.answer,\n ...colors.answer,\n maxHeight: isExpanded ? '500px' : '0',\n paddingBottom: isExpanded ? '16px' : '0',\n };\n\n return html`\n <div\n style=${styleMap(sm(itemStyle))}\n data-faq-item-id=${item.config.id}\n >\n <button\n type=\"button\"\n style=${styleMap(sm(questionStyle))}\n aria-expanded=${isExpanded}\n @click=${() => this._handleToggle(item.config.id)}\n @mouseenter=${() => {\n this._hoveredId = item.config.id;\n }}\n @mouseleave=${() => {\n this._hoveredId = null;\n }}\n >\n <span>${item.config.question}</span>\n <span style=${styleMap(sm(chevronStyle))}>\\u203A</span>\n </button>\n\n <div\n style=${styleMap(sm(answerStyle))}\n aria-hidden=${!isExpanded}\n >\n ${this._renderAnswer(item.config.answer)}\n ${\n isExpanded && feedbackConfig\n ? this._renderFeedback(\n item,\n feedbackConfig,\n this._feedbackState.get(item.config.id),\n theme\n )\n : nothing\n }\n </div>\n </div>\n `;\n }\n\n private _renderItems(\n items: FAQQuestionAction[],\n theme: 'light' | 'dark',\n feedbackConfig: FeedbackConfig | null\n ) {\n return items.map((item, index) =>\n this._renderItem(item, index === items.length - 1, theme, feedbackConfig)\n );\n }\n\n // -----------------------------------------------------------------------\n // Render\n // -----------------------------------------------------------------------\n\n override render() {\n const theme = resolveTheme(this.faqConfig.theme);\n const colors = themeStyles[theme];\n const feedbackConfig = resolveFeedbackConfig(this.faqConfig.feedback);\n\n const visible = this._visibleQuestions();\n const ordered = this._orderedQuestions(visible);\n const filtered = this._filteredQuestions(ordered);\n const hasCategories = filtered.some((q) => q.config.category);\n const groups = hasCategories ? this._categoryGroups(filtered) : null;\n\n const containerStyle = {\n ...baseStyles.container,\n ...colors.container,\n };\n\n const emptyStateStyle = {\n ...baseStyles.emptyState,\n ...colors.emptyState,\n };\n\n const categoryHeaderStyle = {\n ...baseStyles.categoryHeader,\n ...colors.categoryHeader,\n };\n\n const searchInputStyle = {\n ...baseStyles.searchInput,\n ...colors.searchInput,\n };\n\n // Empty state \u2014 no visible questions at all.\n //\n // A runtime-backed FAQ is a compositional container: its `faq:question`\n // items stream in as `element.compositional_append` events after mount\n // (and a replay request). Rendering the \"all set\" reassurance box while\n // we're still empty flashes an empty shell on every mount \u2014 and leaves\n // an orphaned empty box if the agent mounted a container it never filled\n // (the recurring \"empty FAQ showed up then disappeared\" bug). Render\n // nothing until the first question lands. The reassurance copy is only\n // for a standalone (runtime-less) FAQ configured directly with no items.\n if (visible.length === 0) {\n if (this.runtime) return nothing;\n return html`\n <div\n style=${styleMap(sm(containerStyle))}\n data-adaptive-id=${this.instanceId}\n data-adaptive-type=\"adaptive-faq\"\n >\n <div style=${styleMap(sm(emptyStateStyle))}>\n You're all set for now! We'll surface answers here when they're relevant to what\n you're doing.\n </div>\n </div>\n `;\n }\n\n return html`\n <div\n style=${styleMap(sm(containerStyle))}\n data-adaptive-id=${this.instanceId}\n data-adaptive-type=\"adaptive-faq\"\n >\n ${\n this.faqConfig.searchable\n ? html`\n <div style=${styleMap(sm(baseStyles.searchWrapper))}>\n <style>\n [data-adaptive-id=\"${this.instanceId}\"] input::placeholder {\n color: var(--sc-content-search-color, inherit);\n opacity: 0.7;\n }\n </style>\n <input\n type=\"text\"\n placeholder=\"Search questions...\"\n .value=${this._searchQuery}\n style=${styleMap(sm(searchInputStyle))}\n @input=${(e: InputEvent) => {\n this._searchQuery = (e.target as HTMLInputElement).value;\n }}\n />\n </div>\n `\n : nothing\n }\n\n <div style=${styleMap(sm(baseStyles.accordion))}>\n ${\n groups\n ? Array.from(groups.entries()).map(\n ([category, items]) => html`\n ${\n category\n ? html`\n <div\n style=${styleMap(sm(categoryHeaderStyle))}\n data-category-header=${category}\n >\n ${category}\n </div>\n `\n : nothing\n }\n ${this._renderItems(items, theme, feedbackConfig)}\n `\n )\n : this._renderItems(filtered, theme, feedbackConfig)\n }\n </div>\n\n ${\n this.faqConfig.searchable && filtered.length === 0 && this._searchQuery\n ? html`\n <div\n style=${styleMap(sm({ ...baseStyles.noResults, ...colors.emptyState }))}\n >\n No questions found matching "${this._searchQuery}"\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n}\n\n// ============================================================================\n// Custom element registration\n// ============================================================================\n\nif (!customElements.get('syntro-faq-accordion')) {\n customElements.define('syntro-faq-accordion', FAQAccordionElement);\n}\n\nexport default FAQAccordionElement;\n", "/**\n * Adaptive FAQ - Styles\n *\n * BaseStyles object (font, layout, colors, animations) and theme integration\n * for the FAQWidget component.\n */\n\nimport { purple, slateGrey } from '@syntro/design-system/tokens';\n\n// ============================================================================\n// Base Styles\n// ============================================================================\n\nexport const baseStyles = {\n container: {\n fontFamily: 'var(--sc-font-family, system-ui, -apple-system, sans-serif)',\n maxWidth: '800px',\n margin: '0 auto',\n },\n searchWrapper: {\n marginBottom: '8px',\n },\n searchInput: {\n width: '100%',\n padding: '12px 16px',\n borderRadius: '8px',\n fontSize: '14px',\n outline: 'none',\n transition: 'border-color 0.15s ease',\n backgroundColor: 'var(--sc-content-search-background)',\n color: 'var(--sc-content-search-color)',\n },\n accordion: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: 'var(--sc-content-item-gap, 6px)',\n },\n item: {\n borderRadius: 'var(--sc-content-item-border-radius, 10px)',\n border: 'var(--sc-content-item-border, 1px solid rgba(0, 0, 0, 0.08))',\n background: 'var(--sc-content-item-background, rgba(255, 255, 255, 0.5))',\n overflow: 'hidden',\n transition: 'box-shadow 0.15s ease',\n },\n question: {\n width: '100%',\n padding: 'var(--sc-content-item-padding, 12px 16px)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n border: 'none',\n cursor: 'pointer',\n fontSize: 'var(--sc-content-item-font-size, 15px)',\n fontWeight: 500,\n textAlign: 'left' as const,\n transition: 'background-color 0.15s ease',\n },\n chevron: {\n fontSize: '20px',\n transition: 'transform 0.2s ease',\n color: 'var(--sc-content-chevron-color, currentColor)',\n },\n answer: {\n padding: 'var(--sc-content-body-padding, 0 16px 12px 16px)',\n fontSize: 'var(--sc-content-body-font-size, 14px)',\n lineHeight: 1.6,\n overflow: 'hidden',\n transition: 'max-height 0.2s ease, padding 0.2s ease',\n },\n category: {\n display: 'inline-block',\n fontSize: '11px',\n fontWeight: 600,\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n padding: '4px 8px',\n borderRadius: '4px',\n marginBottom: '8px',\n },\n categoryHeader: {\n fontSize: 'var(--sc-content-category-font-size, 12px)',\n fontWeight: 700,\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n padding: 'var(--sc-content-category-padding, 8px 4px 4px 4px)',\n marginTop: 'var(--sc-content-category-gap, 4px)',\n },\n feedback: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginTop: '12px',\n paddingTop: '10px',\n borderTop: '1px solid rgba(0, 0, 0, 0.08)',\n fontSize: '13px',\n },\n feedbackButton: {\n background: 'none',\n border: '1px solid transparent',\n cursor: 'pointer',\n fontSize: '16px',\n padding: '4px 8px',\n borderRadius: '4px',\n transition: 'background-color 0.15s ease, border-color 0.15s ease',\n },\n feedbackButtonSelected: {\n borderColor: 'rgba(0, 0, 0, 0.2)',\n backgroundColor: 'rgba(0, 0, 0, 0.04)',\n },\n emptyState: {\n textAlign: 'center' as const,\n padding: '48px 24px',\n fontSize: '14px',\n },\n noResults: {\n textAlign: 'center' as const,\n padding: '32px 16px',\n fontSize: '14px',\n },\n} as const;\n\n// ============================================================================\n// Theme Styles\n// ============================================================================\n\nexport const themeStyles = {\n light: {\n container: {\n backgroundColor: 'transparent',\n color: 'inherit',\n },\n searchInput: {\n border: `1px solid ${slateGrey[11]}`,\n },\n item: {\n backgroundColor: 'var(--sc-content-background)',\n borderTop: 'var(--sc-content-border)',\n borderRight: 'var(--sc-content-border)',\n borderBottom: 'var(--sc-content-border)',\n borderLeft: 'var(--sc-content-border)',\n },\n itemExpanded: {\n boxShadow: '0 4px 12px rgba(0, 0, 0, 0.08)',\n },\n question: {\n backgroundColor: 'transparent',\n color: 'var(--sc-content-text-color)',\n },\n questionHover: {\n backgroundColor: 'var(--sc-content-background-hover)',\n },\n answer: {\n color: 'var(--sc-content-text-secondary-color)',\n },\n category: {\n backgroundColor: purple[8],\n color: purple[2],\n },\n categoryHeader: {\n color: slateGrey[7],\n },\n emptyState: {\n color: slateGrey[8],\n },\n feedbackPrompt: {\n color: slateGrey[7],\n },\n },\n dark: {\n container: {\n backgroundColor: 'transparent',\n color: 'inherit',\n },\n searchInput: {\n border: `1px solid ${slateGrey[5]}`,\n },\n item: {\n backgroundColor: 'var(--sc-content-background)',\n borderTop: 'var(--sc-content-border)',\n borderRight: 'var(--sc-content-border)',\n borderBottom: 'var(--sc-content-border)',\n borderLeft: 'var(--sc-content-border)',\n },\n itemExpanded: {\n boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',\n },\n question: {\n backgroundColor: 'transparent',\n color: 'var(--sc-content-text-color)',\n },\n questionHover: {\n backgroundColor: 'var(--sc-content-background-hover)',\n },\n answer: {\n color: 'var(--sc-content-text-secondary-color)',\n },\n category: {\n backgroundColor: purple[0],\n color: purple[6],\n },\n categoryHeader: {\n color: slateGrey[8],\n },\n emptyState: {\n color: slateGrey[7],\n },\n feedbackPrompt: {\n color: slateGrey[8],\n },\n },\n};\n", "/**\n * Adaptive FAQ - Runtime Module\n *\n * Runtime manifest for the FAQ accordion adaptive.\n * Mounts the Lit web component <syntro-faq-accordion>.\n * Provides action executors and widget registration.\n */\n\nimport { type MountPlumbing, stripMountPlumbing } from '@syntrologie/sdk-contracts';\nimport { executorDefinitions } from './executors';\nimport './FAQWidgetLit'; // registers <syntro-faq-accordion> custom element\nimport type { FAQWidgetRuntime } from './faq-types';\nimport type { FAQConfig, FAQQuestionAction } from './types';\n\n// ============================================================================\n// Lit Mountable Widget\n// ============================================================================\n\nconst DEFAULT_FAQ_CONFIG: FAQConfig = {\n expandBehavior: 'single',\n searchable: false,\n theme: 'auto',\n actions: [],\n};\n\n/**\n * Mountable widget interface for <syntro-faq-accordion> (Lit web component).\n */\nexport const FAQWidgetLitMountable = {\n mount(\n container: HTMLElement,\n config?: (FAQConfig & MountPlumbing & { runtime?: FAQWidgetRuntime }) | null\n ) {\n const incoming = config ?? null;\n const stripped = stripMountPlumbing<FAQConfig & { runtime?: FAQWidgetRuntime }>(incoming);\n // stripMountPlumbing does NOT strip the non-canonical `runtime` consumer key\n // on this widget because `runtime` is a canonical plumbing key. Pull the\n // explicit references back out for the element wiring.\n const runtime = incoming?.runtime as FAQWidgetRuntime | undefined;\n const instanceId = incoming?.instanceId ?? 'faq-widget';\n const faqConfig: FAQConfig = incoming ? (stripped as FAQConfig) : { ...DEFAULT_FAQ_CONFIG };\n\n const el = document.createElement('syntro-faq-accordion') as HTMLElement & {\n faqConfig: FAQConfig;\n runtime: FAQWidgetRuntime | null;\n instanceId: string;\n };\n\n Object.assign(el, {\n faqConfig,\n runtime: runtime ?? null,\n instanceId,\n });\n\n container.appendChild(el);\n return () => el.remove();\n },\n};\n\n// ============================================================================\n// App Runtime Manifest\n// ============================================================================\n\n/**\n * Runtime manifest for adaptive-faq.\n *\n * Provides:\n * - FAQ action executors (scroll_to, toggle_item, update)\n * - Widget-based accordion using the Lit web component\n */\nexport const runtime = {\n id: 'adaptive-faq',\n version: '2.0.0',\n name: 'FAQ Accordion',\n description:\n 'Collapsible Q&A accordion with actions, rich content, feedback, and personalization',\n\n /**\n * Action executors for programmatic FAQ interaction.\n */\n executors: executorDefinitions,\n\n /**\n * Widget definitions for the runtime's WidgetRegistry.\n */\n widgets: [\n {\n id: 'adaptive-faq:accordion',\n component: FAQWidgetLitMountable,\n metadata: {\n name: 'FAQ Accordion',\n description: 'Collapsible Q&A accordion with search, categories, and feedback',\n icon: '\u2753',\n subtitle: 'Curated just for you.',\n },\n },\n ],\n\n /**\n * Extract notify watcher entries from tile config props.\n * The runtime evaluates these continuously (even with drawer closed)\n * and publishes faq:question_revealed when triggerWhen transitions false \u2192 true.\n */\n notifyWatchers(props: Record<string, unknown>) {\n const actions = (props.actions ?? []) as FAQQuestionAction[];\n return actions\n .filter((a) => a.notify && a.triggerWhen)\n .map((a) => ({\n id: `faq:${a.config.id}`,\n strategy: a.triggerWhen!,\n eventName: 'faq:question_revealed',\n eventProps: {\n questionId: a.config.id,\n question: a.config.question,\n title: a.notify!.title,\n body: a.notify!.body,\n icon: a.notify!.icon,\n },\n }));\n },\n};\n\nexport default runtime;\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Adaptive FAQ - Action Executors\n *\n * Three executors that operate on the FAQStore:\n * - executeScrollToFaq: scroll to a FAQ item and optionally expand it\n * - executeToggleFaqItem: open / close / toggle a FAQ item\n * - executeUpdateFaq: add, remove, reorder, or replace FAQ items\n */\n\nimport type { FAQStore } from './state';\nimport type {\n ExecutorContext,\n ExecutorResult,\n FAQQuestionAction,\n ScrollToFaqAction,\n ToggleFaqItemAction,\n UpdateFaqAction,\n} from './types';\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Resolve a FAQ item by direct ID or by fuzzy question text match.\n * Throws if neither yields a result.\n */\nfunction resolveItem(store: FAQStore, itemId?: string, itemQuestion?: string): FAQQuestionAction {\n if (itemId) {\n const found = store.getState().items.find((i) => i.config.id === itemId);\n if (found) return found;\n }\n\n if (itemQuestion) {\n const found = store.findByQuestion(itemQuestion);\n if (found) return found;\n }\n\n throw new Error('FAQ item not found');\n}\n\n// ============================================================================\n// executeScrollToFaq\n// ============================================================================\n\n/**\n * Scroll to a FAQ item in the DOM and optionally expand it.\n *\n * Looks up the item by `itemId` or `itemQuestion`, scrolls the matching\n * `[data-faq-item-id]` element into view, and expands it unless\n * `expand` is explicitly set to `false`.\n */\nexport async function executeScrollToFaq(\n action: ScrollToFaqAction,\n context: ExecutorContext,\n store: FAQStore\n): Promise<ExecutorResult> {\n const item = resolveItem(store, action.itemId, action.itemQuestion);\n const { id } = item.config;\n\n // Expand the item unless explicitly told not to\n if (action.expand !== false) {\n store.expand(id);\n }\n\n // Scroll the DOM element into view (may be absent in test environments)\n const el = document.querySelector(`[data-faq-item-id=\"${id}\"]`);\n if (el) {\n el.scrollIntoView({\n behavior: action.behavior ?? 'smooth',\n });\n }\n\n // Publish analytics event\n context.publishEvent('faq:scroll_to', { itemId: id });\n\n return {\n cleanup: () => {\n // Optionally collapse on revert\n },\n };\n}\n\n// ============================================================================\n// executeToggleFaqItem\n// ============================================================================\n\n/**\n * Open, close, or toggle a FAQ item's expanded state.\n */\nexport async function executeToggleFaqItem(\n action: ToggleFaqItemAction,\n context: ExecutorContext,\n store: FAQStore\n): Promise<ExecutorResult> {\n const item = resolveItem(store, action.itemId, action.itemQuestion);\n const { id } = item.config;\n const desiredState = action.state ?? 'toggle';\n\n let newState: 'open' | 'closed';\n\n switch (desiredState) {\n case 'open':\n store.expand(id);\n newState = 'open';\n break;\n case 'closed':\n store.collapse(id);\n newState = 'closed';\n break;\n default: {\n const wasExpanded = store.getState().expandedItems.has(id);\n store.toggle(id);\n newState = wasExpanded ? 'closed' : 'open';\n break;\n }\n }\n\n context.publishEvent('faq:toggle', { itemId: id, newState });\n\n return {\n cleanup: () => {\n // Revert toggle on cleanup\n },\n };\n}\n\n// ============================================================================\n// executeUpdateFaq\n// ============================================================================\n\n/**\n * Add, remove, reorder, or replace FAQ items in the store.\n */\nexport async function executeUpdateFaq(\n action: UpdateFaqAction,\n context: ExecutorContext,\n store: FAQStore\n): Promise<ExecutorResult> {\n switch (action.operation) {\n case 'add': {\n const items = action.items ?? [];\n const position = action.position === 'prepend' ? 'prepend' : 'append';\n store.addItems(items, position);\n break;\n }\n\n case 'remove': {\n if (!action.itemId) {\n throw new Error('FAQ item not found');\n }\n // Verify the item exists before removing\n const exists = store.getState().items.some((i) => i.config.id === action.itemId);\n if (!exists) {\n throw new Error('FAQ item not found');\n }\n store.removeItem(action.itemId);\n break;\n }\n\n case 'reorder': {\n const order = action.order ?? [];\n store.reorderItems(order);\n break;\n }\n\n case 'replace': {\n const items = action.items ?? [];\n store.replaceItems(items);\n break;\n }\n }\n\n context.publishEvent('faq:update', { operation: action.operation });\n\n return {\n cleanup: () => {\n // Could snapshot previous state for undo\n },\n };\n}\n\n// ============================================================================\n// Executor Definitions for Registration\n// ============================================================================\n\n/**\n * All executors provided by adaptive-faq.\n * These are registered with the runtime's ExecutorRegistry.\n */\nexport const executorDefinitions = [\n { kind: 'faq:scroll_to', executor: executeScrollToFaq },\n { kind: 'faq:toggle_item', executor: executeToggleFaqItem },\n { kind: 'faq:update', executor: executeUpdateFaq },\n] as const;\n", "/**\n * Adaptive FAQ - FAQWidgetLit\n *\n * Lit web component equivalent of FAQWidget.tsx.\n * Renders a collapsible Q&A accordion with search, category grouping,\n * feedback, and markdown rendering \u2014 all as a custom element with no\n * Shadow DOM (light DOM via createRenderRoot).\n *\n * Tag name: <syntro-faq-accordion>\n *\n * Decorator-free: uses `static override properties` (tsconfig has no\n * experimentalDecorators).\n */\n\nimport { purple } from '@syntro/design-system/tokens';\nimport { html, LitElement, nothing } from 'lit';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\nimport { getAnswerText, renderAnswerHtml } from './answerRendering';\nimport { baseStyles, themeStyles } from './faq-styles';\nimport type { FAQWidgetRuntime } from './faq-types';\nimport type {\n FAQAnswer,\n FAQConfig,\n FAQQuestionAction,\n FeedbackConfig,\n FeedbackValue,\n} from './types';\n\n// ============================================================================\n// Utility \u2014 styleMap accepts Record<string, string | number | undefined>\n// but its TypeScript signature is overly narrow in some Lit versions.\n// Cast through unknown to avoid false positives when style values include\n// numeric CSS properties (fontWeight, lineHeight, etc.).\n// ============================================================================\n\nfunction sm(styles: Record<string, unknown>): Record<string, string> {\n return styles as unknown as Record<string, string>;\n}\n\nfunction resolveFeedbackConfig(\n feedback: boolean | FeedbackConfig | undefined\n): FeedbackConfig | null {\n if (!feedback) return null;\n if (feedback === true) return { style: 'thumbs' };\n return feedback;\n}\n\nfunction getFeedbackPrompt(feedbackConfig: FeedbackConfig): string {\n return feedbackConfig.prompt ?? 'Was this helpful?';\n}\n\n/**\n * Small deterministic string hash (djb2, base36) for content-derived atomic\n * FAQ row ids \u2014 stable per question across re-mounts so expand/feedback state\n * keyed by id sticks to the right row even if the list reorders.\n */\nfunction hashFaqId(text: string): string {\n let h = 5381;\n for (let i = 0; i < text.length; i++) {\n h = (Math.imul(h, 33) ^ text.charCodeAt(i)) >>> 0;\n }\n return h.toString(36);\n}\n\nfunction resolveTheme(theme: FAQConfig['theme'] | undefined): 'light' | 'dark' {\n if (theme && theme !== 'auto') return theme;\n if (typeof window !== 'undefined') {\n return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n return 'light';\n}\n\n// ============================================================================\n// FAQAccordionElement \u2014 Lit element\n// ============================================================================\n\n/**\n * <syntro-faq-accordion> \u2014 light-DOM Lit web component.\n *\n * Set properties imperatively (no attribute serialisation for objects):\n * el.faqConfig = { expandBehavior: 'single', ... };\n * el.runtime = runtimeInstance;\n * el.instanceId = 'my-faq';\n */\nexport class FAQAccordionElement extends LitElement {\n // -----------------------------------------------------------------------\n // Reactive properties (no decorators \u2014 tsconfig forbids experimentalDecorators)\n // -----------------------------------------------------------------------\n\n static override properties = {\n // Public API \u2014 set from the outside\n faqConfig: { attribute: false },\n runtime: { attribute: false },\n instanceId: { type: String },\n\n // Internal reactive state (prefixed with _ to signal \"private\")\n // _openId: currently-open question id for the master\u2192detail takeover.\n // null = LIST view; a value = DETAIL view showing only that single Q&A.\n _openId: { state: true },\n _highlightId: { state: true },\n _searchQuery: { state: true },\n _feedbackState: { state: true },\n _hoveredId: { state: true },\n };\n\n // -----------------------------------------------------------------------\n // Property declarations\n // -----------------------------------------------------------------------\n\n faqConfig: FAQConfig = {\n expandBehavior: 'single',\n searchable: false,\n theme: 'auto',\n actions: [],\n };\n\n runtime: FAQWidgetRuntime | null = null;\n\n instanceId: string = 'faq-widget';\n\n // Internal state\n // The currently-open question id (null = list view, value = detail view).\n // The master\u2192detail takeover swaps the whole widget to a single Q&A so a\n // long answer never overflows the bounded velvet tile.\n _openId: string | null = null;\n _highlightId: string | null = null;\n _searchQuery: string = '';\n _feedbackState: Map<string, FeedbackValue> = new Map();\n _hoveredId: string | null = null;\n\n // Subscription cleanup handles\n private _unsubContext: (() => void) | null = null;\n private _unsubAccumulator: (() => void) | null = null;\n private _unsubCta: (() => void) | null = null;\n private _unsubDeepLink: (() => void) | null = null;\n private _unsubSessionMetrics: (() => void) | null = null;\n private _highlightTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Compositional-child wiring \u2014 faq:question items the LLM mounts into this\n // accordion's tile arrive as `element.compositional_append` events (see\n // adaptive-chatbot's ItemHandler). Without this subscription the questions\n // are published into the void and the accordion renders empty.\n private _unsubCompositional: (() => void) | null = null;\n private _tileId: string | null = null;\n /** Instance ids already appended via the compositional bus \u2014 dedups\n * the subscribe-then-replay path (and re-subscribes on runtime change). */\n private _llmAppendedIds: Set<string> = new Set();\n\n // -----------------------------------------------------------------------\n // Light DOM \u2014 no Shadow DOM so CSS variables from the host page apply\n // -----------------------------------------------------------------------\n\n override createRenderRoot() {\n return this;\n }\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n override connectedCallback() {\n super.connectedCallback();\n this._subscribeAll();\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._unsubscribeAll();\n if (this._highlightTimer !== null) {\n clearTimeout(this._highlightTimer);\n this._highlightTimer = null;\n }\n }\n\n // Re-subscribe when runtime changes (property may be set after connectedCallback)\n override updated(changedProps: Map<string, unknown>) {\n if (changedProps.has('runtime')) {\n this._unsubscribeAll();\n this._subscribeAll();\n }\n }\n\n // -----------------------------------------------------------------------\n // Subscription management\n // -----------------------------------------------------------------------\n\n private _subscribeAll() {\n if (!this.runtime) return;\n\n // Context changes \u2192 force re-render\n this._unsubContext = this.runtime.context.subscribe(() => {\n this.requestUpdate();\n });\n\n // Accumulator changes \u2192 force re-render (for event_count triggerWhen)\n if (this.runtime.accumulator?.subscribe) {\n this._unsubAccumulator = this.runtime.accumulator.subscribe(() => {\n this.requestUpdate();\n });\n }\n\n // Session metric changes \u2192 force re-render (for session_metric triggerWhen)\n if (this.runtime.sessionMetrics?.subscribe) {\n this._unsubSessionMetrics = this.runtime.sessionMetrics.subscribe(() => {\n this.requestUpdate();\n });\n }\n\n // faq:open:* events from overlay CTA clicks\n if (this.runtime.events.subscribe) {\n // Check EventBus history for pending faq:open events\n if (this.runtime.events.getRecent) {\n const recentEvents = this.runtime.events.getRecent(\n { patterns: ['^action\\\\.tooltip_cta_clicked$', '^action\\\\.modal_cta_clicked$'] },\n 10\n );\n const pendingEvent = recentEvents\n .filter((e) => {\n const actionId = e.props?.actionId;\n return typeof actionId === 'string' && actionId.startsWith('faq:open:');\n })\n .pop();\n\n if (pendingEvent && Date.now() - pendingEvent.ts < 10000) {\n const questionId = (pendingEvent.props!.actionId as string).replace('faq:open:', '');\n // Takeover: put the widget into DETAIL view for that question\n // (previously this expanded the row inline).\n this._openId = questionId;\n }\n }\n\n this._unsubCta = this.runtime.events.subscribe(\n { patterns: ['^action\\\\.tooltip_cta_clicked$', '^action\\\\.modal_cta_clicked$'] },\n (event) => {\n const actionId = event.props?.actionId;\n if (typeof actionId !== 'string' || !actionId.startsWith('faq:open:')) return;\n const questionId = actionId.replace('faq:open:', '');\n // Takeover: open the question's detail view instead of inline expand.\n this._openId = questionId;\n this.runtime?.events.publish('canvas.requestOpen');\n }\n );\n }\n\n // notification.deep_link events\n if (this.runtime.events.subscribe) {\n const handleDeepLink = (event: { name: string; props?: Record<string, unknown> }) => {\n const tileId = event.props?.tileId as string | undefined;\n const itemId = event.props?.itemId as string | undefined;\n if (tileId !== this.instanceId) return;\n if (!itemId) return;\n\n // Takeover: open the question's detail view (previously inline expand).\n this._openId = itemId;\n this._highlightId = itemId;\n\n if (this._highlightTimer !== null) clearTimeout(this._highlightTimer);\n this._highlightTimer = setTimeout(() => {\n this._highlightId = null;\n this._highlightTimer = null;\n }, 1500);\n };\n\n // Check recent events (may have fired before widget mounted)\n if (this.runtime.events.getRecent) {\n const recent = this.runtime.events.getRecent({ names: ['notification.deep_link'] }, 5);\n const pending = recent\n .filter((e) => (e.props?.tileId as string) === this.instanceId && e.props?.itemId)\n .pop();\n if (pending && Date.now() - pending.ts < 10000) {\n handleDeepLink(pending);\n }\n }\n\n this._unsubDeepLink = this.runtime.events.subscribe(\n { names: ['notification.deep_link'] },\n handleDeepLink\n );\n }\n\n // Compositional children: faq:question items mounted into this\n // accordion's tile. The ItemHandler publishes one event per kind-\n // agnostic item mount; we filter to our tile and route into\n // `faqConfig.actions`. Mirrors AdaptiveChipsStrip's CompositionalContainer.\n this._subscribeCompositional();\n }\n\n /**\n * Subscribe to `element.compositional_*` events targeting this accordion's\n * tile, and ask the element store to replay any items it already holds for\n * us (covers the case where the accordion mounts AFTER the item did \u2014 the\n * inline-slot hydration race that otherwise silently drops the question).\n */\n private _subscribeCompositional() {\n const bus = this.runtime?.events;\n if (!bus?.subscribe) return;\n this._tileId = this._resolveTileId();\n if (!this._tileId) return;\n const tileId = this._tileId;\n this._unsubCompositional = bus.subscribe((event) => {\n const props = event.props ?? {};\n if (props.tile_id !== tileId) return;\n const instanceId = String(props.instance_id ?? '');\n if (event.name === 'element.compositional_append') {\n this._insertItem(\n instanceId,\n props.item as FAQQuestionAction,\n (props.position as 'append' | 'prepend') ?? 'append'\n );\n } else if (event.name === 'element.compositional_patch') {\n this._patchItem(instanceId, props.item as FAQQuestionAction);\n } else if (event.name === 'element.compositional_remove') {\n this._removeItem(instanceId);\n }\n });\n bus.publish('element.compositional_replay_request', { tile_id: tileId });\n }\n\n /** Tile id for compositional filtering: the enclosing tile card's\n * `data-tile-id` (set by SyntroTileCard), falling back to `instanceId`\n * when the accordion is mounted outside a tile card. */\n private _resolveTileId(): string | null {\n const anchor = this.closest<HTMLElement>('[data-tile-id]');\n const fromDom = anchor?.getAttribute('data-tile-id');\n if (fromDom) return fromDom;\n return this.instanceId && this.instanceId !== 'faq-widget' ? this.instanceId : null;\n }\n\n /** Append (or prepend) a faq:question the LLM mounted. The wire shape is a\n * fully-formed `{kind, config}` envelope, so we store it verbatim. */\n private _insertItem(\n instanceId: string,\n item: FAQQuestionAction,\n position: 'append' | 'prepend'\n ): void {\n if (!instanceId || !item?.config?.id) return;\n if (this._llmAppendedIds.has(instanceId)) return; // dedup replay / re-subscribe\n this._llmAppendedIds.add(instanceId);\n const actions = this.faqConfig.actions ?? [];\n const next = position === 'prepend' ? [item, ...actions] : [...actions, item];\n // Reassign so Lit sees the change (faqConfig is attribute:false).\n this.faqConfig = { ...this.faqConfig, actions: next };\n }\n\n /** Replace an existing question's content (full replacement). */\n private _patchItem(instanceId: string, item: FAQQuestionAction): void {\n if (!instanceId || !item?.config) return;\n const actions = this.faqConfig.actions ?? [];\n const idx = actions.findIndex((a) => a.config.id === instanceId);\n if (idx < 0) return;\n const next = [...actions];\n next[idx] = item;\n this.faqConfig = { ...this.faqConfig, actions: next };\n }\n\n /** Remove a question by instance id. */\n private _removeItem(instanceId: string): void {\n if (!instanceId) return;\n const actions = this.faqConfig.actions ?? [];\n const next = actions.filter((a) => a.config.id !== instanceId);\n if (next.length === actions.length) return;\n this._llmAppendedIds.delete(instanceId);\n this.faqConfig = { ...this.faqConfig, actions: next };\n }\n\n private _unsubscribeAll() {\n this._unsubContext?.();\n this._unsubAccumulator?.();\n this._unsubSessionMetrics?.();\n this._unsubCta?.();\n this._unsubDeepLink?.();\n this._unsubCompositional?.();\n this._unsubContext = null;\n this._unsubAccumulator = null;\n this._unsubSessionMetrics = null;\n this._unsubCta = null;\n this._unsubDeepLink = null;\n this._unsubCompositional = null;\n }\n\n // -----------------------------------------------------------------------\n // Handlers\n // -----------------------------------------------------------------------\n\n /**\n * Master\u2192detail takeover: tapping a list row opens its single-Q&A detail\n * view (the whole widget swaps), so a long answer fills \u2014 and never\n * overflows \u2014 the bounded velvet tile. There is no simultaneous multi-expand;\n * one question owns the tile at a time.\n */\n private _handleOpen(id: string) {\n this._openId = id;\n\n this.runtime?.events.publish('faq:toggled', {\n instanceId: this.instanceId,\n questionId: id,\n expanded: true,\n timestamp: Date.now(),\n });\n }\n\n /** Back affordance: return from the detail view to the full list. */\n private _handleBack() {\n const id = this._openId;\n this._openId = null;\n\n if (id !== null) {\n this.runtime?.events.publish('faq:toggled', {\n instanceId: this.instanceId,\n questionId: id,\n expanded: false,\n timestamp: Date.now(),\n });\n }\n }\n\n private _handleFeedback(itemId: string, question: string, value: FeedbackValue) {\n const next = new Map(this._feedbackState);\n next.set(itemId, value);\n this._feedbackState = next;\n\n this.runtime?.events.publish('faq:feedback', { itemId, question, value });\n }\n\n // -----------------------------------------------------------------------\n // Computed helpers\n // -----------------------------------------------------------------------\n\n /**\n * Unified render list. Merges compositionally-appended rows\n * (`faqConfig.actions`, the container-then-stream path) with atomically\n * authored rows (`faqConfig.questions`, the struct_list path) normalized\n * into the same `FAQQuestionAction` shape. The atomic path is how the LLM\n * mounts a complete FAQ in one call \u2014 so it renders whole, never empty.\n */\n private _allQuestions(): FAQQuestionAction[] {\n const compositional = this.faqConfig.actions ?? [];\n // Content-derived id (not positional). Expand/feedback state is keyed by id;\n // if the LLM re-mounts the FAQ with a reordered or shortened list, a\n // positional `atomic-${i}` would re-point that state at a different\n // question. Hashing the question text keeps the id stable per question\n // across re-mounts. A `-N` suffix disambiguates same-text rows (including\n // empty strings, which all hash to the same value) so they never share\n // expand/feedback state \u2014 stable as long as their relative order is.\n const seen = new Map<string, number>();\n const atomic = (this.faqConfig.questions ?? []).map((q): FAQQuestionAction => {\n let id = `atomic-${hashFaqId(q.question)}`;\n const dup = seen.get(id) ?? 0;\n seen.set(id, dup + 1);\n if (dup > 0) id = `${id}-${dup}`;\n return {\n kind: 'faq:question',\n config: {\n id,\n question: q.question,\n answer: q.answer,\n category: q.category,\n },\n };\n });\n return [...atomic, ...compositional];\n }\n\n private _visibleQuestions(): FAQQuestionAction[] {\n return this._allQuestions().filter((q) => {\n if (!q.triggerWhen) return true;\n if (!this.runtime) return true;\n const result = this.runtime.evaluateSync<boolean>(q.triggerWhen);\n return result.value;\n });\n }\n\n private _orderedQuestions(visible: FAQQuestionAction[]): FAQQuestionAction[] {\n if (this.faqConfig.ordering === 'priority') {\n return [...visible].sort((a, b) => (b.config.priority ?? 0) - (a.config.priority ?? 0));\n }\n return visible;\n }\n\n private _filteredQuestions(ordered: FAQQuestionAction[]): FAQQuestionAction[] {\n const q = this._searchQuery.trim().toLowerCase();\n if (!this.faqConfig.searchable || !q) return ordered;\n return ordered.filter(\n (item) =>\n item.config.question.toLowerCase().includes(q) ||\n getAnswerText(item.config.answer).toLowerCase().includes(q) ||\n item.config.category?.toLowerCase().includes(q)\n );\n }\n\n private _categoryGroups(\n filtered: FAQQuestionAction[]\n ): Map<string | undefined, FAQQuestionAction[]> {\n const groups = new Map<string | undefined, FAQQuestionAction[]>();\n for (const item of filtered) {\n const cat = item.config.category;\n if (!groups.has(cat)) groups.set(cat, []);\n groups.get(cat)!.push(item);\n }\n return groups;\n }\n\n // -----------------------------------------------------------------------\n // Render helpers\n // -----------------------------------------------------------------------\n\n private _renderAnswer(answer: FAQAnswer) {\n const html_str = renderAnswerHtml(answer);\n return html`<div style=\"margin:0\" data-faq-markdown=\"\">${unsafeHTML(html_str)}</div>`;\n }\n\n private _renderFeedback(\n item: FAQQuestionAction,\n feedbackConfig: FeedbackConfig,\n feedbackValue: FeedbackValue | undefined,\n theme: 'light' | 'dark'\n ) {\n const colors = themeStyles[theme];\n const feedbackStyle = { ...baseStyles.feedback, ...colors.feedbackPrompt };\n\n return html`\n <div style=${styleMap(sm(feedbackStyle))}>\n <span>${getFeedbackPrompt(feedbackConfig)}</span>\n <button\n type=\"button\"\n style=${styleMap(\n sm({\n ...baseStyles.feedbackButton,\n ...(feedbackValue === 'up' ? baseStyles.feedbackButtonSelected : {}),\n })\n )}\n aria-label=\"Thumbs up\"\n @click=${() => this._handleFeedback(item.config.id, item.config.question, 'up')}\n >\\uD83D\\uDC4D</button>\n <button\n type=\"button\"\n style=${styleMap(\n sm({\n ...baseStyles.feedbackButton,\n ...(feedbackValue === 'down' ? baseStyles.feedbackButtonSelected : {}),\n })\n )}\n aria-label=\"Thumbs down\"\n @click=${() => this._handleFeedback(item.config.id, item.config.question, 'down')}\n >\\uD83D\\uDC4E</button>\n </div>\n `;\n }\n\n /**\n * LIST-view row. A tappable question with its chevron \\u2014 but NO inline answer\n * body. Tapping it takes over the tile with the question's detail view (see\n * {@link _renderDetail}). Keeps the per-row look/markers/highlight from the\n * old accordion minus the inline-expanded answer that overflowed the tile.\n */\n private _renderItem(item: FAQQuestionAction, isLast: boolean, theme: 'light' | 'dark') {\n const colors = themeStyles[theme];\n const isHighlighted = this._highlightId === item.config.id;\n const isHovered = this._hoveredId === item.config.id;\n\n const itemStyle = {\n ...baseStyles.item,\n ...colors.item,\n ...(isHighlighted\n ? {\n boxShadow: `0 0 0 2px ${purple[4]}, 0 0 12px rgba(106, 89, 206, 0.4)`,\n transition: 'box-shadow 0.3s ease',\n }\n : {}),\n ...(!isLast ? { borderBottom: 'var(--sc-content-item-divider, none)' } : {}),\n };\n\n const questionStyle = {\n ...baseStyles.question,\n ...colors.question,\n ...(isHovered ? colors.questionHover : {}),\n };\n\n const chevronStyle = {\n ...baseStyles.chevron,\n transform: 'rotate(0deg)',\n };\n\n return html`\n <div\n style=${styleMap(sm(itemStyle))}\n data-faq-item-id=${item.config.id}\n >\n <button\n type=\"button\"\n style=${styleMap(sm(questionStyle))}\n aria-expanded=${false}\n @click=${() => this._handleOpen(item.config.id)}\n @mouseenter=${() => {\n this._hoveredId = item.config.id;\n }}\n @mouseleave=${() => {\n this._hoveredId = null;\n }}\n >\n <span>${item.config.question}</span>\n <span style=${styleMap(sm(chevronStyle))}>\\u203A</span>\n </button>\n </div>\n `;\n }\n\n private _renderItems(items: FAQQuestionAction[], theme: 'light' | 'dark') {\n return items.map((item, index) => this._renderItem(item, index === items.length - 1, theme));\n }\n\n /**\n * DETAIL view \\u2014 the master\\u2192detail takeover. Renders ONLY the open question:\n * a back affordance, the question prominently, and its full answer via the\n * SAME {@link _renderAnswer}/`renderAnswerHtml` path (all answer formats still\n * work). The answer area scrolls if extremely long, so a single answer fills\n * the bounded velvet tile and never pushes content past the `overflow:hidden`\n * clip.\n */\n private _renderDetail(\n item: FAQQuestionAction,\n theme: 'light' | 'dark',\n feedbackConfig: FeedbackConfig | null\n ) {\n const colors = themeStyles[theme];\n\n const backStyle = {\n ...baseStyles.detailBack,\n ...colors.question,\n };\n const detailQuestionStyle = {\n ...baseStyles.detailQuestion,\n ...colors.question,\n };\n const detailAnswerStyle = {\n ...baseStyles.detailAnswer,\n ...colors.answer,\n };\n\n return html`\n <div style=${styleMap(sm(baseStyles.detail))} data-faq-detail=${item.config.id}>\n <button\n type=\"button\"\n style=${styleMap(sm(backStyle))}\n data-faq-back=\"\"\n aria-label=\"Back to questions\"\n @click=${() => this._handleBack()}\n >\n \\u2039 Back to questions\n </button>\n\n <div style=${styleMap(sm(detailQuestionStyle))}>${item.config.question}</div>\n\n <div style=${styleMap(sm(detailAnswerStyle))} aria-hidden=${false}>\n ${this._renderAnswer(item.config.answer)}\n ${\n feedbackConfig\n ? this._renderFeedback(\n item,\n feedbackConfig,\n this._feedbackState.get(item.config.id),\n theme\n )\n : nothing\n }\n </div>\n </div>\n `;\n }\n\n // -----------------------------------------------------------------------\n // Render\n // -----------------------------------------------------------------------\n\n override render() {\n const theme = resolveTheme(this.faqConfig.theme);\n const colors = themeStyles[theme];\n const feedbackConfig = resolveFeedbackConfig(this.faqConfig.feedback);\n\n const visible = this._visibleQuestions();\n const ordered = this._orderedQuestions(visible);\n const filtered = this._filteredQuestions(ordered);\n const hasCategories = filtered.some((q) => q.config.category);\n const groups = hasCategories ? this._categoryGroups(filtered) : null;\n\n const containerStyle = {\n ...baseStyles.container,\n ...colors.container,\n };\n\n const emptyStateStyle = {\n ...baseStyles.emptyState,\n ...colors.emptyState,\n };\n\n const categoryHeaderStyle = {\n ...baseStyles.categoryHeader,\n ...colors.categoryHeader,\n };\n\n const searchInputStyle = {\n ...baseStyles.searchInput,\n ...colors.searchInput,\n };\n\n // Empty state \u2014 no visible questions at all.\n //\n // A runtime-backed FAQ is a compositional container: its `faq:question`\n // items stream in as `element.compositional_append` events after mount\n // (and a replay request). Rendering the \"all set\" reassurance box while\n // we're still empty flashes an empty shell on every mount \u2014 and leaves\n // an orphaned empty box if the agent mounted a container it never filled\n // (the recurring \"empty FAQ showed up then disappeared\" bug). Render\n // nothing until the first question lands. The reassurance copy is only\n // for a standalone (runtime-less) FAQ configured directly with no items.\n if (visible.length === 0) {\n if (this.runtime) return nothing;\n return html`\n <div\n style=${styleMap(sm(containerStyle))}\n data-adaptive-id=${this.instanceId}\n data-adaptive-type=\"adaptive-faq\"\n >\n <div style=${styleMap(sm(emptyStateStyle))}>\n You're all set for now! We'll surface answers here when they're relevant to what\n you're doing.\n </div>\n </div>\n `;\n }\n\n // DETAIL view (master\u2192detail takeover). When a question is open, the whole\n // widget swaps to that single Q&A so it fills \u2014 and never overflows \u2014 the\n // bounded velvet tile. We resolve `_openId` against the *visible* list so a\n // stale id (e.g. a question that scrolled out via triggerWhen) falls back\n // to the list instead of rendering a blank detail.\n if (this._openId !== null) {\n const openItem = filtered.find((q) => q.config.id === this._openId);\n if (openItem) {\n return html`\n <div\n style=${styleMap(sm(containerStyle))}\n data-adaptive-id=${this.instanceId}\n data-adaptive-type=\"adaptive-faq\"\n >\n ${this._renderDetail(openItem, theme, feedbackConfig)}\n </div>\n `;\n }\n }\n\n return html`\n <div\n style=${styleMap(sm(containerStyle))}\n data-adaptive-id=${this.instanceId}\n data-adaptive-type=\"adaptive-faq\"\n >\n ${\n this.faqConfig.searchable\n ? html`\n <div style=${styleMap(sm(baseStyles.searchWrapper))}>\n <style>\n [data-adaptive-id=\"${this.instanceId}\"] input::placeholder {\n color: var(--sc-content-search-color, inherit);\n opacity: 0.7;\n }\n </style>\n <input\n type=\"text\"\n placeholder=\"Search questions...\"\n .value=${this._searchQuery}\n style=${styleMap(sm(searchInputStyle))}\n @input=${(e: InputEvent) => {\n this._searchQuery = (e.target as HTMLInputElement).value;\n }}\n />\n </div>\n `\n : nothing\n }\n\n <div style=${styleMap(sm(baseStyles.accordion))}>\n ${\n groups\n ? Array.from(groups.entries()).map(\n ([category, items]) => html`\n ${\n category\n ? html`\n <div\n style=${styleMap(sm(categoryHeaderStyle))}\n data-category-header=${category}\n >\n ${category}\n </div>\n `\n : nothing\n }\n ${this._renderItems(items, theme)}\n `\n )\n : this._renderItems(filtered, theme)\n }\n </div>\n\n ${\n this.faqConfig.searchable && filtered.length === 0 && this._searchQuery\n ? html`\n <div\n style=${styleMap(sm({ ...baseStyles.noResults, ...colors.emptyState }))}\n >\n No questions found matching "${this._searchQuery}"\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n}\n\n// ============================================================================\n// Custom element registration\n// ============================================================================\n\nif (!customElements.get('syntro-faq-accordion')) {\n customElements.define('syntro-faq-accordion', FAQAccordionElement);\n}\n\nexport default FAQAccordionElement;\n", "/**\n * Adaptive FAQ - Styles\n *\n * BaseStyles object (font, layout, colors, animations) and theme integration\n * for the FAQWidget component.\n */\n\nimport { purple, slateGrey } from '@syntro/design-system/tokens';\n\n// ============================================================================\n// Base Styles\n// ============================================================================\n\nexport const baseStyles = {\n container: {\n fontFamily: 'var(--sc-font-family, system-ui, -apple-system, sans-serif)',\n maxWidth: '800px',\n margin: '0 auto',\n },\n searchWrapper: {\n marginBottom: '8px',\n },\n searchInput: {\n width: '100%',\n padding: '12px 16px',\n borderRadius: '8px',\n fontSize: '14px',\n outline: 'none',\n transition: 'border-color 0.15s ease',\n backgroundColor: 'var(--sc-content-search-background)',\n color: 'var(--sc-content-search-color)',\n },\n accordion: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: 'var(--sc-content-item-gap, 6px)',\n },\n item: {\n borderRadius: 'var(--sc-content-item-border-radius, 10px)',\n border: 'var(--sc-content-item-border, 1px solid rgba(0, 0, 0, 0.08))',\n background: 'var(--sc-content-item-background, rgba(255, 255, 255, 0.5))',\n overflow: 'hidden',\n transition: 'box-shadow 0.15s ease',\n },\n question: {\n width: '100%',\n padding: 'var(--sc-content-item-padding, 12px 16px)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n border: 'none',\n cursor: 'pointer',\n fontSize: 'var(--sc-content-item-font-size, 15px)',\n fontWeight: 500,\n textAlign: 'left' as const,\n transition: 'background-color 0.15s ease',\n },\n chevron: {\n fontSize: '20px',\n transition: 'transform 0.2s ease',\n color: 'var(--sc-content-chevron-color, currentColor)',\n },\n answer: {\n padding: 'var(--sc-content-body-padding, 0 16px 12px 16px)',\n fontSize: 'var(--sc-content-body-font-size, 14px)',\n lineHeight: 1.6,\n overflow: 'hidden',\n transition: 'max-height 0.2s ease, padding 0.2s ease',\n },\n category: {\n display: 'inline-block',\n fontSize: '11px',\n fontWeight: 600,\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n padding: '4px 8px',\n borderRadius: '4px',\n marginBottom: '8px',\n },\n categoryHeader: {\n fontSize: 'var(--sc-content-category-font-size, 12px)',\n fontWeight: 700,\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n padding: 'var(--sc-content-category-padding, 8px 4px 4px 4px)',\n marginTop: 'var(--sc-content-category-gap, 4px)',\n },\n feedback: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginTop: '12px',\n paddingTop: '10px',\n borderTop: '1px solid rgba(0, 0, 0, 0.08)',\n fontSize: '13px',\n },\n feedbackButton: {\n background: 'none',\n border: '1px solid transparent',\n cursor: 'pointer',\n fontSize: '16px',\n padding: '4px 8px',\n borderRadius: '4px',\n transition: 'background-color 0.15s ease, border-color 0.15s ease',\n },\n feedbackButtonSelected: {\n borderColor: 'rgba(0, 0, 0, 0.2)',\n backgroundColor: 'rgba(0, 0, 0, 0.04)',\n },\n // \u2500\u2500 Master\u2192detail takeover \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // The detail view fills the tile; the answer area scrolls if extremely long\n // so a single answer never pushes content past the tile's overflow clip.\n detail: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '12px',\n minHeight: '0',\n },\n detailBack: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '4px',\n alignSelf: 'flex-start',\n background: 'none',\n border: 'none',\n padding: '4px 0',\n cursor: 'pointer',\n fontSize: '13px',\n fontWeight: 600,\n opacity: 0.85,\n },\n detailQuestion: {\n fontSize: 'var(--sc-content-item-font-size, 16px)',\n fontWeight: 600,\n lineHeight: 1.4,\n },\n detailAnswer: {\n fontSize: 'var(--sc-content-body-font-size, 14px)',\n lineHeight: 1.6,\n overflowY: 'auto' as const,\n flex: '1 1 auto',\n minHeight: '0',\n },\n emptyState: {\n textAlign: 'center' as const,\n padding: '48px 24px',\n fontSize: '14px',\n },\n noResults: {\n textAlign: 'center' as const,\n padding: '32px 16px',\n fontSize: '14px',\n },\n} as const;\n\n// ============================================================================\n// Theme Styles\n// ============================================================================\n\nexport const themeStyles = {\n light: {\n container: {\n backgroundColor: 'transparent',\n color: 'inherit',\n },\n searchInput: {\n border: `1px solid ${slateGrey[11]}`,\n },\n item: {\n backgroundColor: 'var(--sc-content-background)',\n borderTop: 'var(--sc-content-border)',\n borderRight: 'var(--sc-content-border)',\n borderBottom: 'var(--sc-content-border)',\n borderLeft: 'var(--sc-content-border)',\n },\n itemExpanded: {\n boxShadow: '0 4px 12px rgba(0, 0, 0, 0.08)',\n },\n question: {\n backgroundColor: 'transparent',\n color: 'var(--sc-content-text-color)',\n },\n questionHover: {\n backgroundColor: 'var(--sc-content-background-hover)',\n },\n answer: {\n color: 'var(--sc-content-text-secondary-color)',\n },\n category: {\n backgroundColor: purple[8],\n color: purple[2],\n },\n categoryHeader: {\n color: slateGrey[7],\n },\n emptyState: {\n color: slateGrey[8],\n },\n feedbackPrompt: {\n color: slateGrey[7],\n },\n },\n dark: {\n container: {\n backgroundColor: 'transparent',\n color: 'inherit',\n },\n searchInput: {\n border: `1px solid ${slateGrey[5]}`,\n },\n item: {\n backgroundColor: 'var(--sc-content-background)',\n borderTop: 'var(--sc-content-border)',\n borderRight: 'var(--sc-content-border)',\n borderBottom: 'var(--sc-content-border)',\n borderLeft: 'var(--sc-content-border)',\n },\n itemExpanded: {\n boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',\n },\n question: {\n backgroundColor: 'transparent',\n color: 'var(--sc-content-text-color)',\n },\n questionHover: {\n backgroundColor: 'var(--sc-content-background-hover)',\n },\n answer: {\n color: 'var(--sc-content-text-secondary-color)',\n },\n category: {\n backgroundColor: purple[0],\n color: purple[6],\n },\n categoryHeader: {\n color: slateGrey[8],\n },\n emptyState: {\n color: slateGrey[7],\n },\n feedbackPrompt: {\n color: slateGrey[8],\n },\n },\n};\n", "/**\n * Adaptive FAQ - Runtime Module\n *\n * Runtime manifest for the FAQ accordion adaptive.\n * Mounts the Lit web component <syntro-faq-accordion>.\n * Provides action executors and widget registration.\n */\n\nimport { type MountPlumbing, stripMountPlumbing } from '@syntrologie/sdk-contracts';\nimport { executorDefinitions } from './executors';\nimport './FAQWidgetLit'; // registers <syntro-faq-accordion> custom element\nimport type { FAQWidgetRuntime } from './faq-types';\nimport type { FAQConfig, FAQQuestionAction } from './types';\n\n// ============================================================================\n// Lit Mountable Widget\n// ============================================================================\n\nconst DEFAULT_FAQ_CONFIG: FAQConfig = {\n expandBehavior: 'single',\n searchable: false,\n theme: 'auto',\n actions: [],\n};\n\n/**\n * Mountable widget interface for <syntro-faq-accordion> (Lit web component).\n */\nexport const FAQWidgetLitMountable = {\n mount(\n container: HTMLElement,\n config?: (FAQConfig & MountPlumbing & { runtime?: FAQWidgetRuntime }) | null\n ) {\n const incoming = config ?? null;\n const stripped = stripMountPlumbing<FAQConfig & { runtime?: FAQWidgetRuntime }>(incoming);\n // stripMountPlumbing does NOT strip the non-canonical `runtime` consumer key\n // on this widget because `runtime` is a canonical plumbing key. Pull the\n // explicit references back out for the element wiring.\n const runtime = incoming?.runtime as FAQWidgetRuntime | undefined;\n const instanceId = incoming?.instanceId ?? 'faq-widget';\n const faqConfig: FAQConfig = incoming ? (stripped as FAQConfig) : { ...DEFAULT_FAQ_CONFIG };\n\n const el = document.createElement('syntro-faq-accordion') as HTMLElement & {\n faqConfig: FAQConfig;\n runtime: FAQWidgetRuntime | null;\n instanceId: string;\n };\n\n Object.assign(el, {\n faqConfig,\n runtime: runtime ?? null,\n instanceId,\n });\n\n container.appendChild(el);\n return () => el.remove();\n },\n};\n\n// ============================================================================\n// App Runtime Manifest\n// ============================================================================\n\n/**\n * Runtime manifest for adaptive-faq.\n *\n * Provides:\n * - FAQ action executors (scroll_to, toggle_item, update)\n * - Widget-based accordion using the Lit web component\n */\nexport const runtime = {\n id: 'adaptive-faq',\n version: '2.0.0',\n name: 'FAQ Accordion',\n description:\n 'Collapsible Q&A accordion with actions, rich content, feedback, and personalization',\n\n /**\n * Action executors for programmatic FAQ interaction.\n */\n executors: executorDefinitions,\n\n /**\n * Widget definitions for the runtime's WidgetRegistry.\n */\n widgets: [\n {\n id: 'adaptive-faq:accordion',\n component: FAQWidgetLitMountable,\n metadata: {\n name: 'FAQ Accordion',\n description: 'Collapsible Q&A accordion with search, categories, and feedback',\n icon: '\u2753',\n subtitle: 'Curated just for you.',\n },\n },\n ],\n\n /**\n * Extract notify watcher entries from tile config props.\n * The runtime evaluates these continuously (even with drawer closed)\n * and publishes faq:question_revealed when triggerWhen transitions false \u2192 true.\n */\n notifyWatchers(props: Record<string, unknown>) {\n const actions = (props.actions ?? []) as FAQQuestionAction[];\n return actions\n .filter((a) => a.notify && a.triggerWhen)\n .map((a) => ({\n id: `faq:${a.config.id}`,\n strategy: a.triggerWhen!,\n eventName: 'faq:question_revealed',\n eventProps: {\n questionId: a.config.id,\n question: a.config.question,\n title: a.notify!.title,\n body: a.notify!.body,\n icon: a.notify!.icon,\n },\n }));\n },\n};\n\nexport default runtime;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["runtime"]
|
|
7
7
|
}
|
package/dist/schema.d.ts
CHANGED
|
@@ -5022,40 +5022,40 @@ export declare const ScrollToFaqSchema: z.ZodEffects<z.ZodObject<{
|
|
|
5022
5022
|
kind: "faq:scroll_to";
|
|
5023
5023
|
title?: string | undefined;
|
|
5024
5024
|
itemId?: string | undefined;
|
|
5025
|
-
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
5026
5025
|
id?: string | undefined;
|
|
5027
5026
|
description?: string | undefined;
|
|
5028
5027
|
validation?: string[] | undefined;
|
|
5028
|
+
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
5029
5029
|
itemQuestion?: string | undefined;
|
|
5030
5030
|
expand?: boolean | undefined;
|
|
5031
5031
|
}, {
|
|
5032
5032
|
kind: "faq:scroll_to";
|
|
5033
5033
|
title?: string | undefined;
|
|
5034
5034
|
itemId?: string | undefined;
|
|
5035
|
-
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
5036
5035
|
id?: string | undefined;
|
|
5037
5036
|
description?: string | undefined;
|
|
5038
5037
|
validation?: string[] | undefined;
|
|
5038
|
+
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
5039
5039
|
itemQuestion?: string | undefined;
|
|
5040
5040
|
expand?: boolean | undefined;
|
|
5041
5041
|
}>, {
|
|
5042
5042
|
kind: "faq:scroll_to";
|
|
5043
5043
|
title?: string | undefined;
|
|
5044
5044
|
itemId?: string | undefined;
|
|
5045
|
-
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
5046
5045
|
id?: string | undefined;
|
|
5047
5046
|
description?: string | undefined;
|
|
5048
5047
|
validation?: string[] | undefined;
|
|
5048
|
+
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
5049
5049
|
itemQuestion?: string | undefined;
|
|
5050
5050
|
expand?: boolean | undefined;
|
|
5051
5051
|
}, {
|
|
5052
5052
|
kind: "faq:scroll_to";
|
|
5053
5053
|
title?: string | undefined;
|
|
5054
5054
|
itemId?: string | undefined;
|
|
5055
|
-
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
5056
5055
|
id?: string | undefined;
|
|
5057
5056
|
description?: string | undefined;
|
|
5058
5057
|
validation?: string[] | undefined;
|
|
5058
|
+
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
5059
5059
|
itemQuestion?: string | undefined;
|
|
5060
5060
|
expand?: boolean | undefined;
|
|
5061
5061
|
}>;
|
|
@@ -8634,20 +8634,20 @@ export declare const actionStepSchemas: ({
|
|
|
8634
8634
|
kind: "faq:scroll_to";
|
|
8635
8635
|
title?: string | undefined;
|
|
8636
8636
|
itemId?: string | undefined;
|
|
8637
|
-
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
8638
8637
|
id?: string | undefined;
|
|
8639
8638
|
description?: string | undefined;
|
|
8640
8639
|
validation?: string[] | undefined;
|
|
8640
|
+
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
8641
8641
|
itemQuestion?: string | undefined;
|
|
8642
8642
|
expand?: boolean | undefined;
|
|
8643
8643
|
}, {
|
|
8644
8644
|
kind: "faq:scroll_to";
|
|
8645
8645
|
title?: string | undefined;
|
|
8646
8646
|
itemId?: string | undefined;
|
|
8647
|
-
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
8648
8647
|
id?: string | undefined;
|
|
8649
8648
|
description?: string | undefined;
|
|
8650
8649
|
validation?: string[] | undefined;
|
|
8650
|
+
behavior?: "auto" | "smooth" | "instant" | undefined;
|
|
8651
8651
|
itemQuestion?: string | undefined;
|
|
8652
8652
|
expand?: boolean | undefined;
|
|
8653
8653
|
}>;
|
package/package.json
CHANGED