@syntrologie/adapt-chatbot 2.37.2 → 2.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AdaptiveChatBarMountable.d.ts.map +1 -1
- package/dist/LeaveAMessageLit.d.ts +109 -0
- package/dist/LeaveAMessageLit.d.ts.map +1 -0
- package/dist/LeaveAMessageLit.test.d.ts +2 -0
- package/dist/LeaveAMessageLit.test.d.ts.map +1 -0
- package/dist/LeaveAMessageMountable.test.d.ts +2 -0
- package/dist/LeaveAMessageMountable.test.d.ts.map +1 -0
- package/dist/cdn.d.ts +13 -2
- package/dist/cdn.d.ts.map +1 -1
- package/dist/runtime.d.ts +50 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +366 -1
- package/dist/runtime.js.map +4 -4
- package/dist/schema.d.ts +36 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +23 -0
- package/dist/schema.js.map +2 -2
- package/dist/support-chat/boot.d.ts +12 -0
- package/dist/support-chat/boot.d.ts.map +1 -0
- package/dist/support-chat/boot.test.d.ts +2 -0
- package/dist/support-chat/boot.test.d.ts.map +1 -0
- package/dist/support-chat/crisp.d.ts +4 -0
- package/dist/support-chat/crisp.d.ts.map +1 -0
- package/dist/support-chat/crisp.test.d.ts +2 -0
- package/dist/support-chat/crisp.test.d.ts.map +1 -0
- package/dist/support-chat/registry.d.ts +5 -0
- package/dist/support-chat/registry.d.ts.map +1 -0
- package/dist/support-chat/registry.test.d.ts +2 -0
- package/dist/support-chat/registry.test.d.ts.map +1 -0
- package/dist/support-chat/types.d.ts +19 -0
- package/dist/support-chat/types.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdaptiveChatBarMountable.d.ts","sourceRoot":"","sources":["../src/AdaptiveChatBarMountable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAIL,KAAK,wBAAwB,EAI9B,MAAM,4BAA4B,CAAC;AAkBpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"AdaptiveChatBarMountable.d.ts","sourceRoot":"","sources":["../src/AdaptiveChatBarMountable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAIL,KAAK,wBAAwB,EAI9B,MAAM,4BAA4B,CAAC;AAkBpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGvE,OAAO,KAAK,EAAmB,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsIxE;;;;;;GAMG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD;AA6BD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAgB/F;AA+DD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE;IAC9C,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;CAC/C,GAAG,CAAC,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,QAAQ,KAAK,gBAAgB,CAkC5D;AAOD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAoExF;AAED,6EAA6E;AAC7E,wBAAgB,0BAA0B,IAAI,IAAI,CAMjD;AAsGD,0BAA0B;AAC1B,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD;AA0ED,wBAAgB,+BAA+B,IAAI,IAAI,CAUtD;AAyID,eAAO,MAAM,wBAAwB;qBAClB,WAAW,gBAAgB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,IAAI;sBAkG9D,WAAW,gBAAgB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAQ5E,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <syntro-leave-a-message> — escalation-only async human handoff
|
|
3
|
+
* (spec: docs/superpowers/specs/2026-08-13-async-handoff-crisp-design.md).
|
|
4
|
+
* Four states: form → sent → mail ("You got mail!") → flipped (reply +
|
|
5
|
+
* inline follow-up). All delivery through an injected SupportChatBridge;
|
|
6
|
+
* fail closed when the bridge is absent or the vendor SDK undetected.
|
|
7
|
+
*/
|
|
8
|
+
import { LitElement, nothing } from 'lit';
|
|
9
|
+
import type { SupportChatBridge } from './support-chat/types';
|
|
10
|
+
export type LeaveAMessageState = 'form' | 'sent' | 'mail' | 'flipped';
|
|
11
|
+
/**
|
|
12
|
+
* Minimal runtime slice the widget needs to raise the "You got mail!"
|
|
13
|
+
* toast — mirrors adaptive-nav's `NavWidgetRuntime.events` shape (see
|
|
14
|
+
* `NavWidgetLit#publishEvent`) so tile `notifications` rules (which
|
|
15
|
+
* subscribe to the runtime EventBus, not DOM CustomEvents) can match
|
|
16
|
+
* on `supportchat:reply_received`.
|
|
17
|
+
*/
|
|
18
|
+
export interface LeaveAMessageRuntime {
|
|
19
|
+
events: {
|
|
20
|
+
publish: (name: string, props?: Record<string, unknown>) => void;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Optional persistence seam (I2, final-review fixes 2026-08-13) — mirrors
|
|
24
|
+
* adaptive-overlays' `WorkflowWidgetLit.runtimeRef?.state?.user?.ns?.(...)`
|
|
25
|
+
* pattern exactly. On an MPA the tile unmounts and remounts fresh per
|
|
26
|
+
* page; without this, a visitor who already sent a message and is
|
|
27
|
+
* waiting on a reply loses that thread on their very next click (state
|
|
28
|
+
* resets to 'form', the operator's reply becomes invisible). Optional
|
|
29
|
+
* because older host bundles / the playground don't inject it — the
|
|
30
|
+
* widget still works, it just can't survive navigation.
|
|
31
|
+
*/
|
|
32
|
+
state?: {
|
|
33
|
+
user?: {
|
|
34
|
+
ns?: (namespace: string) => {
|
|
35
|
+
get: (key: string) => unknown;
|
|
36
|
+
set: (key: string, value: unknown) => void;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export declare class LeaveAMessageLit extends LitElement {
|
|
42
|
+
static properties: {
|
|
43
|
+
bridge: {
|
|
44
|
+
attribute: boolean;
|
|
45
|
+
};
|
|
46
|
+
message: {
|
|
47
|
+
type: StringConstructor;
|
|
48
|
+
};
|
|
49
|
+
contextSummary: {
|
|
50
|
+
attribute: boolean;
|
|
51
|
+
};
|
|
52
|
+
state: {
|
|
53
|
+
type: StringConstructor;
|
|
54
|
+
};
|
|
55
|
+
runtime: {
|
|
56
|
+
attribute: boolean;
|
|
57
|
+
};
|
|
58
|
+
replyToast: {
|
|
59
|
+
attribute: boolean;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
bridge: SupportChatBridge | undefined;
|
|
63
|
+
message: string;
|
|
64
|
+
contextSummary: string;
|
|
65
|
+
state: LeaveAMessageState;
|
|
66
|
+
/** Runtime plumbing injected by the mountable — undefined outside a live SDK mount. */
|
|
67
|
+
runtime: LeaveAMessageRuntime | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Visitor-facing toast copy, authored by the WORKSPACE CONFIG
|
|
70
|
+
* (`default_widget_props.replyToast`) — presentation belongs to
|
|
71
|
+
* configuration, not to this bundle: every workspace has its own voice
|
|
72
|
+
* and language. The built-in fallback below exists only so an
|
|
73
|
+
* unconfigured mount still says something truthful.
|
|
74
|
+
*/
|
|
75
|
+
replyToast: {
|
|
76
|
+
title?: string;
|
|
77
|
+
body?: string;
|
|
78
|
+
} | undefined;
|
|
79
|
+
private _email;
|
|
80
|
+
private _reply;
|
|
81
|
+
private _operatorMessages;
|
|
82
|
+
private _unsubscribe;
|
|
83
|
+
createRenderRoot(): HTMLElement;
|
|
84
|
+
connectedCallback(): void;
|
|
85
|
+
updated(): void;
|
|
86
|
+
disconnectedCallback(): void;
|
|
87
|
+
/** Read the injected persistence store, if any (I2). */
|
|
88
|
+
private _persistStore;
|
|
89
|
+
/** Hydrate {state, operatorMessages, email} from a prior page's mount. */
|
|
90
|
+
private _loadPersisted;
|
|
91
|
+
/** Snapshot {state, operatorMessages, email} so the NEXT mount (a fresh
|
|
92
|
+
* page in the same session) can pick the thread back up. */
|
|
93
|
+
private _persist;
|
|
94
|
+
/**
|
|
95
|
+
* Raise the reply toast through the canvas element. Pierces shadow roots to
|
|
96
|
+
* find `<smart-canvas>` (same resolution AdaptiveChatBarMountable uses), and
|
|
97
|
+
* no-ops when no canvas is present — the tile's own "You got mail!" face is
|
|
98
|
+
* always the durable signal.
|
|
99
|
+
*/
|
|
100
|
+
private _toastReplyArrived;
|
|
101
|
+
private _onReply;
|
|
102
|
+
private _submit;
|
|
103
|
+
private _flip;
|
|
104
|
+
private _sendReply;
|
|
105
|
+
render(): typeof nothing | import("lit-html").TemplateResult<1>;
|
|
106
|
+
}
|
|
107
|
+
/** Idempotent registration — called by the mountable on first mount. */
|
|
108
|
+
export declare function registerLeaveAMessageLit(): void;
|
|
109
|
+
//# sourceMappingURL=LeaveAMessageLit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LeaveAMessageLit.d.ts","sourceRoot":"","sources":["../src/LeaveAMessageLit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAQ,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAGhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAsD9D,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE;QACN,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAClE,CAAC;IACF;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE;YACL,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK;gBAC1B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;gBAC9B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;aAC5C,CAAC;SACH,CAAC;KACH,CAAC;CACH;AASD,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,OAAgB,UAAU;;;;;;;;;;;;;;;;;;;MAOxB;IAEF,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACtC,OAAO,SAAM;IACb,cAAc,SAAM;IACpB,KAAK,EAAE,kBAAkB,CAAU;IACnC,uFAAuF;IACvF,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAE1C;;;;;;OAMG;IACH,UAAU,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAE1D,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,YAAY,CAA2B;IAEtC,gBAAgB,IAAI,WAAW;IAI/B,iBAAiB,IAAI,IAAI;IAYzB,OAAO,IAAI,IAAI;IAcf,oBAAoB,IAAI,IAAI;IAMrC,wDAAwD;IACxD,OAAO,CAAC,aAAa;IAIrB,0EAA0E;IAC1E,OAAO,CAAC,cAAc;IAUtB;iEAC6D;IAC7D,OAAO,CAAC,QAAQ;IAahB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAiC1B,OAAO,CAAC,QAAQ,CAgCd;IAEF,OAAO,CAAC,OAAO,CAOb;IAEF,OAAO,CAAC,KAAK,CAGX;IAEF,OAAO,CAAC,UAAU,CAKhB;IAEO,MAAM;CA6DhB;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LeaveAMessageLit.test.d.ts","sourceRoot":"","sources":["../src/LeaveAMessageLit.test.ts"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LeaveAMessageMountable.test.d.ts","sourceRoot":"","sources":["../src/LeaveAMessageMountable.test.ts"],"names":[],"mappings":""}
|
package/dist/cdn.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare const manifest: {
|
|
|
12
12
|
description: string;
|
|
13
13
|
runtime: {
|
|
14
14
|
actions: never[];
|
|
15
|
-
widgets: {
|
|
15
|
+
widgets: ({
|
|
16
16
|
id: string;
|
|
17
17
|
component: {
|
|
18
18
|
mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void;
|
|
@@ -22,7 +22,18 @@ export declare const manifest: {
|
|
|
22
22
|
description: string;
|
|
23
23
|
icon: string;
|
|
24
24
|
};
|
|
25
|
-
}
|
|
25
|
+
} | {
|
|
26
|
+
id: string;
|
|
27
|
+
component: {
|
|
28
|
+
mount(container: HTMLElement, config?: (Record<string, unknown> & import("packages/sdk-contracts/dist").MountPlumbing) | null): () => void;
|
|
29
|
+
update(container: HTMLElement, config?: (Record<string, unknown> & import("packages/sdk-contracts/dist").MountPlumbing) | null): void;
|
|
30
|
+
};
|
|
31
|
+
metadata: {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
icon: string;
|
|
35
|
+
};
|
|
36
|
+
})[];
|
|
26
37
|
};
|
|
27
38
|
editor: {
|
|
28
39
|
component: typeof ChatbotEditorLit;
|
package/dist/cdn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdn.d.ts","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,eAAO,MAAM,QAAQ
|
|
1
|
+
{"version":3,"file":"cdn.d.ts","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoBpB,CAAC;AAaF,eAAe,QAAQ,CAAC"}
|
package/dist/runtime.d.ts
CHANGED
|
@@ -9,8 +9,34 @@
|
|
|
9
9
|
* replace the launcher FAB) or any other slot's `lid` / tile slot. The
|
|
10
10
|
* adaptive no longer auto-registers a canvas lid renderer.
|
|
11
11
|
*/
|
|
12
|
+
import { type MountPlumbing } from '@syntrologie/sdk-contracts';
|
|
12
13
|
import './AdaptiveChatBar';
|
|
13
14
|
import './AdaptiveChatTrail';
|
|
15
|
+
/**
|
|
16
|
+
* LeaveAMessageMountable — mounts `<syntro-leave-a-message>`
|
|
17
|
+
* (adaptive-chatbot:leave-a-message). Escalation-only async human handoff:
|
|
18
|
+
* resolves the vendor bridge named in `supportChat.vendor` (per FEAT
|
|
19
|
+
* docs/superpowers/specs/2026-08-13-async-handoff-crisp-design.md) and
|
|
20
|
+
* passes the mount plumbing's `runtime` through exactly as
|
|
21
|
+
* `NavWidgetLitMountable` does — the element needs it to publish
|
|
22
|
+
* `supportchat:reply_received` on the runtime EventBus so tile
|
|
23
|
+
* `notifications` rules can badge the "You got mail!" toast.
|
|
24
|
+
*/
|
|
25
|
+
export declare const LeaveAMessageMountable: {
|
|
26
|
+
mount(container: HTMLElement, config?: (Record<string, unknown> & MountPlumbing) | null): () => void;
|
|
27
|
+
/**
|
|
28
|
+
* I1 (final-review fixes 2026-08-13): without this, `WidgetRegistry`
|
|
29
|
+
* falls back to unmount+remount on every config patch (e.g. the agent
|
|
30
|
+
* editing the prefilled `message` mid-conversation), which destroys the
|
|
31
|
+
* live element and with it the visitor's in-flight escalation state
|
|
32
|
+
* (email already captured, an operator reply already sitting in
|
|
33
|
+
* `mail`/`flipped`). Mirrors `AdaptiveChatBarMountable.update`'s
|
|
34
|
+
* pattern: patch the presentational props in place, touch nothing
|
|
35
|
+
* else. `state`, `bridge`, and the operator-message thread are NEVER
|
|
36
|
+
* reset here.
|
|
37
|
+
*/
|
|
38
|
+
update(container: HTMLElement, config?: (Record<string, unknown> & MountPlumbing) | null): void;
|
|
39
|
+
};
|
|
14
40
|
export { ElementInstanceStore, TileHandler } from './elements';
|
|
15
41
|
export { getElementInstanceStore, setElementInstanceStore } from './elements/store-singleton';
|
|
16
42
|
export declare const runtime: {
|
|
@@ -19,7 +45,7 @@ export declare const runtime: {
|
|
|
19
45
|
name: string;
|
|
20
46
|
description: string;
|
|
21
47
|
executors: never[];
|
|
22
|
-
widgets: {
|
|
48
|
+
widgets: ({
|
|
23
49
|
id: string;
|
|
24
50
|
component: {
|
|
25
51
|
mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void;
|
|
@@ -29,7 +55,29 @@ export declare const runtime: {
|
|
|
29
55
|
description: string;
|
|
30
56
|
icon: string;
|
|
31
57
|
};
|
|
32
|
-
}
|
|
58
|
+
} | {
|
|
59
|
+
id: string;
|
|
60
|
+
component: {
|
|
61
|
+
mount(container: HTMLElement, config?: (Record<string, unknown> & MountPlumbing) | null): () => void;
|
|
62
|
+
/**
|
|
63
|
+
* I1 (final-review fixes 2026-08-13): without this, `WidgetRegistry`
|
|
64
|
+
* falls back to unmount+remount on every config patch (e.g. the agent
|
|
65
|
+
* editing the prefilled `message` mid-conversation), which destroys the
|
|
66
|
+
* live element and with it the visitor's in-flight escalation state
|
|
67
|
+
* (email already captured, an operator reply already sitting in
|
|
68
|
+
* `mail`/`flipped`). Mirrors `AdaptiveChatBarMountable.update`'s
|
|
69
|
+
* pattern: patch the presentational props in place, touch nothing
|
|
70
|
+
* else. `state`, `bridge`, and the operator-message thread are NEVER
|
|
71
|
+
* reset here.
|
|
72
|
+
*/
|
|
73
|
+
update(container: HTMLElement, config?: (Record<string, unknown> & MountPlumbing) | null): void;
|
|
74
|
+
};
|
|
75
|
+
metadata: {
|
|
76
|
+
name: string;
|
|
77
|
+
description: string;
|
|
78
|
+
icon: string;
|
|
79
|
+
};
|
|
80
|
+
})[];
|
|
33
81
|
};
|
|
34
82
|
export default runtime;
|
|
35
83
|
//# sourceMappingURL=runtime.d.ts.map
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAsB,MAAM,4BAA4B,CAAC;AAGpF,OAAO,mBAAmB,CAAC;AAC3B,OAAO,qBAAqB,CAAC;AAuC7B;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB;qBAChB,WAAW,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC,GAAG,IAAI;IAwBvF;;;;;;;;;;OAUG;sBACe,WAAW,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC,GAAG,IAAI;CASzF,CAAC;AAMF,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAE9F,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;6BArDD,WAAW,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC,GAAG,IAAI;YAwBvF;;;;;;;;;;eAUG;8BACe,WAAW,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC,GAAG,IAAI;;;;;;;;CA2GzF,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
package/dist/runtime.js
CHANGED
|
@@ -23,7 +23,8 @@ import "./chunk-OIGVZGSX.js";
|
|
|
23
23
|
import {
|
|
24
24
|
DIVE_DEEPER_EVENT,
|
|
25
25
|
TILE_MOUNTED_EVENT,
|
|
26
|
-
TILE_UNMOUNTED_EVENT
|
|
26
|
+
TILE_UNMOUNTED_EVENT,
|
|
27
|
+
stripMountPlumbing
|
|
27
28
|
} from "./chunk-EACGDSJI.js";
|
|
28
29
|
import "./chunk-UVKRO5ER.js";
|
|
29
30
|
|
|
@@ -1770,6 +1771,69 @@ function busEventToRawEvent(e) {
|
|
|
1770
1771
|
return { event: e.name, timestamp: ts, properties: { ...e.props ?? {} } };
|
|
1771
1772
|
}
|
|
1772
1773
|
|
|
1774
|
+
// src/support-chat/registry.ts
|
|
1775
|
+
var bridges = /* @__PURE__ */ new Map();
|
|
1776
|
+
function registerSupportChatBridge(bridge) {
|
|
1777
|
+
bridges.set(bridge.vendor, bridge);
|
|
1778
|
+
}
|
|
1779
|
+
function getSupportChatBridge(vendor) {
|
|
1780
|
+
return bridges.get(vendor);
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
// src/support-chat/crisp.ts
|
|
1784
|
+
function crisp() {
|
|
1785
|
+
if (typeof window === "undefined") return void 0;
|
|
1786
|
+
return window.$crisp;
|
|
1787
|
+
}
|
|
1788
|
+
function push(cmd) {
|
|
1789
|
+
try {
|
|
1790
|
+
crisp()?.push(cmd);
|
|
1791
|
+
} catch (err) {
|
|
1792
|
+
console.warn("supportChat.bridge: crisp push failed", cmd[0], cmd[1], err);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
var crispBridge = {
|
|
1796
|
+
vendor: "crisp",
|
|
1797
|
+
detect: () => crisp() !== void 0,
|
|
1798
|
+
hideNative: () => push(["do", "chat:hide"]),
|
|
1799
|
+
setVisitorEmail: (email) => push(["set", "user:email", [email]]),
|
|
1800
|
+
sendMessage: (text) => push(["do", "message:send", ["text", text]]),
|
|
1801
|
+
onOperatorReply: (cb) => {
|
|
1802
|
+
let active = true;
|
|
1803
|
+
push([
|
|
1804
|
+
"on",
|
|
1805
|
+
"message:received",
|
|
1806
|
+
(msg) => {
|
|
1807
|
+
if (!active) return;
|
|
1808
|
+
push(["do", "chat:hide"]);
|
|
1809
|
+
if (typeof msg?.content === "string") cb(msg.content);
|
|
1810
|
+
}
|
|
1811
|
+
]);
|
|
1812
|
+
return () => {
|
|
1813
|
+
active = false;
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
};
|
|
1817
|
+
function registerCrispBridge() {
|
|
1818
|
+
registerSupportChatBridge(crispBridge);
|
|
1819
|
+
}
|
|
1820
|
+
registerCrispBridge();
|
|
1821
|
+
|
|
1822
|
+
// src/support-chat/boot.ts
|
|
1823
|
+
function bootSupportChat(cfg) {
|
|
1824
|
+
if (!cfg?.vendor) return void 0;
|
|
1825
|
+
registerCrispBridge();
|
|
1826
|
+
const bridge = getSupportChatBridge(cfg.vendor);
|
|
1827
|
+
if (!bridge || !bridge.detect()) {
|
|
1828
|
+
console.warn(
|
|
1829
|
+
`supportChat.bridge: vendor '${cfg.vendor}' not detected on this page \u2014 handoff disabled`
|
|
1830
|
+
);
|
|
1831
|
+
return void 0;
|
|
1832
|
+
}
|
|
1833
|
+
if (cfg.suppressNative) bridge.hideNative();
|
|
1834
|
+
return bridge;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1773
1837
|
// src/AdaptiveChatBarMountable.ts
|
|
1774
1838
|
var STATE_KEY = "__syntroChatBarMount";
|
|
1775
1839
|
function getState(container) {
|
|
@@ -2060,6 +2124,7 @@ var AdaptiveChatBarMountable = {
|
|
|
2060
2124
|
mount(container, mountConfig) {
|
|
2061
2125
|
const cfg = mountConfig ?? {};
|
|
2062
2126
|
configureTransportIfPossible(cfg);
|
|
2127
|
+
bootSupportChat(cfg.supportChat);
|
|
2063
2128
|
wireDiveDeeperListener();
|
|
2064
2129
|
const bar = document.createElement("adaptive-chat-bar");
|
|
2065
2130
|
applyPlaceholder(bar, cfg);
|
|
@@ -2196,6 +2261,241 @@ var AdaptiveChipsStripMountable = {
|
|
|
2196
2261
|
}
|
|
2197
2262
|
};
|
|
2198
2263
|
|
|
2264
|
+
// src/LeaveAMessageLit.ts
|
|
2265
|
+
import { html, LitElement, nothing } from "lit";
|
|
2266
|
+
import { styleMap } from "lit/directives/style-map.js";
|
|
2267
|
+
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2268
|
+
var box = {
|
|
2269
|
+
display: "flex",
|
|
2270
|
+
flexDirection: "column",
|
|
2271
|
+
gap: "var(--sc-content-item-gap, 10px)",
|
|
2272
|
+
fontFamily: "var(--sc-font-family, system-ui)",
|
|
2273
|
+
fontSize: "var(--sc-content-body-font-size, 13px)"
|
|
2274
|
+
};
|
|
2275
|
+
var fieldStyles = {
|
|
2276
|
+
padding: "var(--sc-content-item-padding, 8px 10px)",
|
|
2277
|
+
borderRadius: "var(--sc-content-border-radius, 8px)",
|
|
2278
|
+
border: "var(--sc-content-bubble-border, 1px solid currentColor)",
|
|
2279
|
+
background: "var(--sc-content-bubble-background, transparent)",
|
|
2280
|
+
color: "inherit",
|
|
2281
|
+
font: "inherit"
|
|
2282
|
+
};
|
|
2283
|
+
var buttonStyles = {
|
|
2284
|
+
// No chip padding token exists (ChipElementConfigZ only has
|
|
2285
|
+
// background/foreground/border/shadow) — plain constant, no fake var().
|
|
2286
|
+
padding: "10px 12px",
|
|
2287
|
+
borderRadius: "var(--sc-chip-border-radius, 9999px)",
|
|
2288
|
+
border: "var(--sc-chip-border, 1px solid currentColor)",
|
|
2289
|
+
background: "var(--sc-chip-background, transparent)",
|
|
2290
|
+
color: "var(--sc-tile-title-color, inherit)",
|
|
2291
|
+
fontWeight: "600",
|
|
2292
|
+
cursor: "pointer",
|
|
2293
|
+
font: "inherit"
|
|
2294
|
+
};
|
|
2295
|
+
var textStyles = {
|
|
2296
|
+
margin: "0"
|
|
2297
|
+
};
|
|
2298
|
+
var mutedTextStyles = {
|
|
2299
|
+
margin: "0",
|
|
2300
|
+
// No opacity token exists in any publishable section — plain constant.
|
|
2301
|
+
opacity: "0.8"
|
|
2302
|
+
};
|
|
2303
|
+
var PERSIST_NAMESPACE = "supportchat";
|
|
2304
|
+
var PERSIST_KEY = "leave-a-message";
|
|
2305
|
+
var LeaveAMessageLit = class extends LitElement {
|
|
2306
|
+
constructor() {
|
|
2307
|
+
super(...arguments);
|
|
2308
|
+
this.message = "";
|
|
2309
|
+
this.contextSummary = "";
|
|
2310
|
+
this.state = "form";
|
|
2311
|
+
this._email = "";
|
|
2312
|
+
this._reply = "";
|
|
2313
|
+
this._operatorMessages = [];
|
|
2314
|
+
this._onReply = (text) => {
|
|
2315
|
+
this._operatorMessages = [...this._operatorMessages, text];
|
|
2316
|
+
if (this.state !== "flipped") {
|
|
2317
|
+
this.state = "mail";
|
|
2318
|
+
this.runtime?.events.publish("supportchat:reply_received", { text });
|
|
2319
|
+
this._toastReplyArrived();
|
|
2320
|
+
this.dispatchEvent(
|
|
2321
|
+
new CustomEvent("syntro:supportchat-reply", {
|
|
2322
|
+
bubbles: true,
|
|
2323
|
+
composed: true,
|
|
2324
|
+
detail: { text }
|
|
2325
|
+
})
|
|
2326
|
+
);
|
|
2327
|
+
}
|
|
2328
|
+
this._persist();
|
|
2329
|
+
this.requestUpdate();
|
|
2330
|
+
};
|
|
2331
|
+
this._submit = () => {
|
|
2332
|
+
if (!this.bridge || !EMAIL_RE.test(this._email)) return;
|
|
2333
|
+
this.bridge.setVisitorEmail(this._email);
|
|
2334
|
+
const context = this.contextSummary ? `[Site assistant context: ${this.contextSummary}]
|
|
2335
|
+
` : "";
|
|
2336
|
+
this.bridge.sendMessage(`${context}${this.message}`);
|
|
2337
|
+
this.state = "sent";
|
|
2338
|
+
this._persist();
|
|
2339
|
+
};
|
|
2340
|
+
this._flip = () => {
|
|
2341
|
+
this.state = "flipped";
|
|
2342
|
+
this._persist();
|
|
2343
|
+
};
|
|
2344
|
+
this._sendReply = () => {
|
|
2345
|
+
if (!this.bridge || !this._reply.trim()) return;
|
|
2346
|
+
this.bridge.sendMessage(this._reply.trim());
|
|
2347
|
+
this._reply = "";
|
|
2348
|
+
this.requestUpdate();
|
|
2349
|
+
};
|
|
2350
|
+
}
|
|
2351
|
+
createRenderRoot() {
|
|
2352
|
+
return this;
|
|
2353
|
+
}
|
|
2354
|
+
connectedCallback() {
|
|
2355
|
+
super.connectedCallback();
|
|
2356
|
+
this._loadPersisted();
|
|
2357
|
+
}
|
|
2358
|
+
updated() {
|
|
2359
|
+
if (this.state !== "form" && this.bridge && this.bridge.detect() && !this._unsubscribe) {
|
|
2360
|
+
this._unsubscribe = this.bridge.onOperatorReply(this._onReply);
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
disconnectedCallback() {
|
|
2364
|
+
this._unsubscribe?.();
|
|
2365
|
+
this._unsubscribe = void 0;
|
|
2366
|
+
super.disconnectedCallback();
|
|
2367
|
+
}
|
|
2368
|
+
/** Read the injected persistence store, if any (I2). */
|
|
2369
|
+
_persistStore() {
|
|
2370
|
+
return this.runtime?.state?.user?.ns?.(PERSIST_NAMESPACE);
|
|
2371
|
+
}
|
|
2372
|
+
/** Hydrate {state, operatorMessages, email} from a prior page's mount. */
|
|
2373
|
+
_loadPersisted() {
|
|
2374
|
+
const store = this._persistStore();
|
|
2375
|
+
if (!store) return;
|
|
2376
|
+
const saved = store.get(PERSIST_KEY);
|
|
2377
|
+
if (!saved) return;
|
|
2378
|
+
if (saved.state) this.state = saved.state;
|
|
2379
|
+
if (Array.isArray(saved.operatorMessages)) this._operatorMessages = saved.operatorMessages;
|
|
2380
|
+
if (typeof saved.email === "string") this._email = saved.email;
|
|
2381
|
+
}
|
|
2382
|
+
/** Snapshot {state, operatorMessages, email} so the NEXT mount (a fresh
|
|
2383
|
+
* page in the same session) can pick the thread back up. */
|
|
2384
|
+
_persist() {
|
|
2385
|
+
const store = this._persistStore();
|
|
2386
|
+
if (!store) return;
|
|
2387
|
+
const state = this.state;
|
|
2388
|
+
const operatorMessages = this._operatorMessages;
|
|
2389
|
+
const email = this._email;
|
|
2390
|
+
const snapshot = { state, operatorMessages, email };
|
|
2391
|
+
store.set(PERSIST_KEY, snapshot);
|
|
2392
|
+
}
|
|
2393
|
+
/**
|
|
2394
|
+
* Raise the reply toast through the canvas element. Pierces shadow roots to
|
|
2395
|
+
* find `<smart-canvas>` (same resolution AdaptiveChatBarMountable uses), and
|
|
2396
|
+
* no-ops when no canvas is present — the tile's own "You got mail!" face is
|
|
2397
|
+
* always the durable signal.
|
|
2398
|
+
*/
|
|
2399
|
+
_toastReplyArrived() {
|
|
2400
|
+
if (typeof document === "undefined") return;
|
|
2401
|
+
const title = this.replyToast?.title?.trim();
|
|
2402
|
+
if (!title) return;
|
|
2403
|
+
const find = (root) => {
|
|
2404
|
+
const direct = root.querySelector("smart-canvas");
|
|
2405
|
+
if (direct) return direct;
|
|
2406
|
+
for (const el of root.querySelectorAll("*")) {
|
|
2407
|
+
const sr = el.shadowRoot;
|
|
2408
|
+
if (sr) {
|
|
2409
|
+
const found = find(sr);
|
|
2410
|
+
if (found) return found;
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
return null;
|
|
2414
|
+
};
|
|
2415
|
+
try {
|
|
2416
|
+
const canvas = find(document);
|
|
2417
|
+
canvas?.previewNotification?.({ title, body: this.replyToast?.body });
|
|
2418
|
+
} catch (err) {
|
|
2419
|
+
console.warn("supportChat.widget: reply toast failed", err);
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
render() {
|
|
2423
|
+
if (!this.bridge || !this.bridge.detect()) return nothing;
|
|
2424
|
+
if (this.state === "form") {
|
|
2425
|
+
return html`<div data-lam style=${styleMap(box)}>
|
|
2426
|
+
<textarea
|
|
2427
|
+
data-lam-message
|
|
2428
|
+
rows="3"
|
|
2429
|
+
style=${styleMap(fieldStyles)}
|
|
2430
|
+
.value=${this.message}
|
|
2431
|
+
@input=${(e) => {
|
|
2432
|
+
this.message = e.target.value;
|
|
2433
|
+
}}
|
|
2434
|
+
></textarea>
|
|
2435
|
+
<input
|
|
2436
|
+
data-lam-email
|
|
2437
|
+
type="email"
|
|
2438
|
+
placeholder="Your email — so the team can reach you"
|
|
2439
|
+
style=${styleMap(fieldStyles)}
|
|
2440
|
+
@input=${(e) => {
|
|
2441
|
+
this._email = e.target.value;
|
|
2442
|
+
this.requestUpdate();
|
|
2443
|
+
}}
|
|
2444
|
+
/>
|
|
2445
|
+
<button type="button" data-lam-send style=${styleMap(buttonStyles)} @click=${this._submit}>
|
|
2446
|
+
Send to the team
|
|
2447
|
+
</button>
|
|
2448
|
+
</div>`;
|
|
2449
|
+
}
|
|
2450
|
+
if (this.state === "sent") {
|
|
2451
|
+
return html`<div data-lam style=${styleMap(box)}>
|
|
2452
|
+
<p style=${styleMap(mutedTextStyles)}>
|
|
2453
|
+
Sent. The team will reply here — or by email if you step away.
|
|
2454
|
+
</p>
|
|
2455
|
+
</div>`;
|
|
2456
|
+
}
|
|
2457
|
+
if (this.state === "mail") {
|
|
2458
|
+
return html`<div data-lam style=${styleMap(box)}>
|
|
2459
|
+
<button type="button" data-lam-mail style=${styleMap(buttonStyles)} @click=${this._flip}>
|
|
2460
|
+
📬 You got mail! — tap to read
|
|
2461
|
+
</button>
|
|
2462
|
+
</div>`;
|
|
2463
|
+
}
|
|
2464
|
+
return html`<div data-lam style=${styleMap(box)}>
|
|
2465
|
+
${this._operatorMessages.map(
|
|
2466
|
+
(m) => html`<p data-lam-operator style=${styleMap(textStyles)}>${m}</p>`
|
|
2467
|
+
)}
|
|
2468
|
+
<input
|
|
2469
|
+
data-lam-reply
|
|
2470
|
+
type="text"
|
|
2471
|
+
placeholder="Reply to the team…"
|
|
2472
|
+
style=${styleMap(fieldStyles)}
|
|
2473
|
+
.value=${this._reply}
|
|
2474
|
+
@input=${(e) => {
|
|
2475
|
+
this._reply = e.target.value;
|
|
2476
|
+
}}
|
|
2477
|
+
/>
|
|
2478
|
+
<button type="button" data-lam-reply-send style=${styleMap(buttonStyles)} @click=${this._sendReply}>
|
|
2479
|
+
Send
|
|
2480
|
+
</button>
|
|
2481
|
+
</div>`;
|
|
2482
|
+
}
|
|
2483
|
+
};
|
|
2484
|
+
LeaveAMessageLit.properties = {
|
|
2485
|
+
bridge: { attribute: false },
|
|
2486
|
+
message: { type: String },
|
|
2487
|
+
contextSummary: { attribute: false },
|
|
2488
|
+
state: { type: String },
|
|
2489
|
+
runtime: { attribute: false },
|
|
2490
|
+
replyToast: { attribute: false }
|
|
2491
|
+
};
|
|
2492
|
+
function registerLeaveAMessageLit() {
|
|
2493
|
+
if (typeof customElements !== "undefined" && !customElements.get("syntro-leave-a-message")) {
|
|
2494
|
+
customElements.define("syntro-leave-a-message", LeaveAMessageLit);
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
registerLeaveAMessageLit();
|
|
2498
|
+
|
|
2199
2499
|
// src/NavLinkMountable.ts
|
|
2200
2500
|
var STATE_KEY3 = "__syntroNavLinkMount";
|
|
2201
2501
|
var SAFE_NAVIGATION_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
@@ -2317,6 +2617,58 @@ var TextAnswerMountable = {
|
|
|
2317
2617
|
};
|
|
2318
2618
|
|
|
2319
2619
|
// src/runtime.ts
|
|
2620
|
+
var LEAVE_A_MESSAGE_STATE_KEY = "__syntroLeaveAMessageMount";
|
|
2621
|
+
function getLeaveAMessageState(container) {
|
|
2622
|
+
return container[LEAVE_A_MESSAGE_STATE_KEY] ?? null;
|
|
2623
|
+
}
|
|
2624
|
+
function setLeaveAMessageState(container, state) {
|
|
2625
|
+
container[LEAVE_A_MESSAGE_STATE_KEY] = state;
|
|
2626
|
+
}
|
|
2627
|
+
var LeaveAMessageMountable = {
|
|
2628
|
+
mount(container, config) {
|
|
2629
|
+
registerLeaveAMessageLit();
|
|
2630
|
+
const el = document.createElement("syntro-leave-a-message");
|
|
2631
|
+
const incoming = config ?? null;
|
|
2632
|
+
const stripped = stripMountPlumbing(incoming) ?? {};
|
|
2633
|
+
const supportChat = stripped.supportChat;
|
|
2634
|
+
const runtime2 = incoming?.runtime;
|
|
2635
|
+
Object.assign(el, {
|
|
2636
|
+
bridge: bootSupportChat(supportChat),
|
|
2637
|
+
message: stripped.message ?? "",
|
|
2638
|
+
contextSummary: stripped.context_summary ?? "",
|
|
2639
|
+
// Visitor-facing toast copy from the workspace config — see
|
|
2640
|
+
// LeaveAMessageLit#replyToast (presentation is configuration).
|
|
2641
|
+
replyToast: stripped.replyToast,
|
|
2642
|
+
runtime: runtime2
|
|
2643
|
+
});
|
|
2644
|
+
container.appendChild(el);
|
|
2645
|
+
setLeaveAMessageState(container, { el });
|
|
2646
|
+
return () => {
|
|
2647
|
+
setLeaveAMessageState(container, null);
|
|
2648
|
+
el.remove();
|
|
2649
|
+
};
|
|
2650
|
+
},
|
|
2651
|
+
/**
|
|
2652
|
+
* I1 (final-review fixes 2026-08-13): without this, `WidgetRegistry`
|
|
2653
|
+
* falls back to unmount+remount on every config patch (e.g. the agent
|
|
2654
|
+
* editing the prefilled `message` mid-conversation), which destroys the
|
|
2655
|
+
* live element and with it the visitor's in-flight escalation state
|
|
2656
|
+
* (email already captured, an operator reply already sitting in
|
|
2657
|
+
* `mail`/`flipped`). Mirrors `AdaptiveChatBarMountable.update`'s
|
|
2658
|
+
* pattern: patch the presentational props in place, touch nothing
|
|
2659
|
+
* else. `state`, `bridge`, and the operator-message thread are NEVER
|
|
2660
|
+
* reset here.
|
|
2661
|
+
*/
|
|
2662
|
+
update(container, config) {
|
|
2663
|
+
const mounted = getLeaveAMessageState(container);
|
|
2664
|
+
if (!mounted) return;
|
|
2665
|
+
const stripped = stripMountPlumbing(config ?? null) ?? {};
|
|
2666
|
+
if (typeof stripped.message === "string") mounted.el.message = stripped.message;
|
|
2667
|
+
if (typeof stripped.context_summary === "string") {
|
|
2668
|
+
mounted.el.contextSummary = stripped.context_summary;
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
};
|
|
2320
2672
|
var runtime = {
|
|
2321
2673
|
id: "adaptive-chatbot",
|
|
2322
2674
|
version: "2.0.0",
|
|
@@ -2387,12 +2739,25 @@ var runtime = {
|
|
|
2387
2739
|
description: "Same-origin navigation button \u2014 used as a chip payload for LLM-authored nav suggestions.",
|
|
2388
2740
|
icon: "\u2192"
|
|
2389
2741
|
}
|
|
2742
|
+
},
|
|
2743
|
+
// Escalation-only async human handoff: email + message into the site's
|
|
2744
|
+
// own support-chat inbox (Crisp first); operator replies flip the tile
|
|
2745
|
+
// ("You got mail!"). See docs/superpowers/specs/2026-08-13-async-handoff-crisp-design.md.
|
|
2746
|
+
{
|
|
2747
|
+
id: "adaptive-chatbot:leave-a-message",
|
|
2748
|
+
component: LeaveAMessageMountable,
|
|
2749
|
+
metadata: {
|
|
2750
|
+
name: "Leave a Message",
|
|
2751
|
+
description: `Escalation-only async human handoff: email + message into the site's own support-chat inbox; operator replies flip the tile ("You got mail!")`,
|
|
2752
|
+
icon: "\u{1F4EC}"
|
|
2753
|
+
}
|
|
2390
2754
|
}
|
|
2391
2755
|
]
|
|
2392
2756
|
};
|
|
2393
2757
|
var runtime_default = runtime;
|
|
2394
2758
|
export {
|
|
2395
2759
|
ElementInstanceStore,
|
|
2760
|
+
LeaveAMessageMountable,
|
|
2396
2761
|
TileHandler,
|
|
2397
2762
|
runtime_default as default,
|
|
2398
2763
|
getElementInstanceStore,
|