@darqlabs/curator-sdk-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/dist/cjs/CuratorAdapter.d.ts +28 -0
  4. package/dist/cjs/CuratorAdapter.d.ts.map +1 -0
  5. package/dist/cjs/CuratorAdapter.js +100 -0
  6. package/dist/cjs/CuratorAdapter.js.map +1 -0
  7. package/dist/cjs/CuratorChat.d.ts +70 -0
  8. package/dist/cjs/CuratorChat.d.ts.map +1 -0
  9. package/dist/cjs/CuratorChat.js +454 -0
  10. package/dist/cjs/CuratorChat.js.map +1 -0
  11. package/dist/cjs/CuratorChatLauncher.d.ts +57 -0
  12. package/dist/cjs/CuratorChatLauncher.d.ts.map +1 -0
  13. package/dist/cjs/CuratorChatLauncher.js +134 -0
  14. package/dist/cjs/CuratorChatLauncher.js.map +1 -0
  15. package/dist/cjs/CuratorProvider.d.ts +37 -0
  16. package/dist/cjs/CuratorProvider.d.ts.map +1 -0
  17. package/dist/cjs/CuratorProvider.js +49 -0
  18. package/dist/cjs/CuratorProvider.js.map +1 -0
  19. package/dist/cjs/Markdown.d.ts +16 -0
  20. package/dist/cjs/Markdown.d.ts.map +1 -0
  21. package/dist/cjs/Markdown.js +18 -0
  22. package/dist/cjs/Markdown.js.map +1 -0
  23. package/dist/cjs/brand.d.ts +26 -0
  24. package/dist/cjs/brand.d.ts.map +1 -0
  25. package/dist/cjs/brand.js +47 -0
  26. package/dist/cjs/brand.js.map +1 -0
  27. package/dist/cjs/index.d.ts +10 -0
  28. package/dist/cjs/index.d.ts.map +1 -0
  29. package/dist/cjs/index.js +17 -0
  30. package/dist/cjs/index.js.map +1 -0
  31. package/dist/cjs/normalizeMarkdown.d.ts +24 -0
  32. package/dist/cjs/normalizeMarkdown.d.ts.map +1 -0
  33. package/dist/cjs/normalizeMarkdown.js +111 -0
  34. package/dist/cjs/normalizeMarkdown.js.map +1 -0
  35. package/dist/cjs/useCuratorChat.d.ts +79 -0
  36. package/dist/cjs/useCuratorChat.d.ts.map +1 -0
  37. package/dist/cjs/useCuratorChat.js +135 -0
  38. package/dist/cjs/useCuratorChat.js.map +1 -0
  39. package/dist/esm/CuratorAdapter.d.ts +28 -0
  40. package/dist/esm/CuratorAdapter.d.ts.map +1 -0
  41. package/dist/esm/CuratorAdapter.js +97 -0
  42. package/dist/esm/CuratorAdapter.js.map +1 -0
  43. package/dist/esm/CuratorChat.d.ts +70 -0
  44. package/dist/esm/CuratorChat.d.ts.map +1 -0
  45. package/dist/esm/CuratorChat.js +451 -0
  46. package/dist/esm/CuratorChat.js.map +1 -0
  47. package/dist/esm/CuratorChatLauncher.d.ts +57 -0
  48. package/dist/esm/CuratorChatLauncher.d.ts.map +1 -0
  49. package/dist/esm/CuratorChatLauncher.js +131 -0
  50. package/dist/esm/CuratorChatLauncher.js.map +1 -0
  51. package/dist/esm/CuratorProvider.d.ts +37 -0
  52. package/dist/esm/CuratorProvider.d.ts.map +1 -0
  53. package/dist/esm/CuratorProvider.js +44 -0
  54. package/dist/esm/CuratorProvider.js.map +1 -0
  55. package/dist/esm/Markdown.d.ts +16 -0
  56. package/dist/esm/Markdown.d.ts.map +1 -0
  57. package/dist/esm/Markdown.js +12 -0
  58. package/dist/esm/Markdown.js.map +1 -0
  59. package/dist/esm/brand.d.ts +26 -0
  60. package/dist/esm/brand.d.ts.map +1 -0
  61. package/dist/esm/brand.js +43 -0
  62. package/dist/esm/brand.js.map +1 -0
  63. package/dist/esm/index.d.ts +10 -0
  64. package/dist/esm/index.d.ts.map +1 -0
  65. package/dist/esm/index.js +6 -0
  66. package/dist/esm/index.js.map +1 -0
  67. package/dist/esm/normalizeMarkdown.d.ts +24 -0
  68. package/dist/esm/normalizeMarkdown.d.ts.map +1 -0
  69. package/dist/esm/normalizeMarkdown.js +108 -0
  70. package/dist/esm/normalizeMarkdown.js.map +1 -0
  71. package/dist/esm/package.json +3 -0
  72. package/dist/esm/useCuratorChat.d.ts +79 -0
  73. package/dist/esm/useCuratorChat.d.ts.map +1 -0
  74. package/dist/esm/useCuratorChat.js +132 -0
  75. package/dist/esm/useCuratorChat.js.map +1 -0
  76. package/package.json +66 -0
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CuratorChatLauncher = CuratorChatLauncher;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ /**
6
+ * <CuratorChatLauncher /> — floating chat bubble that opens an
7
+ * anchored panel containing `<CuratorChat />`. The drop-in shape
8
+ * customers reach for when they want an Intercom-style widget on
9
+ * their site without rolling their own positioning.
10
+ *
11
+ * <CuratorChatLauncher agent="support-bot" placement="bottom-right" />
12
+ *
13
+ * Rendered via a portal to `document.body` so stacking contexts in
14
+ * the consuming app don't trap it. The panel reuses `<CuratorChat />`
15
+ * verbatim — same theming, same hook, same provider context.
16
+ *
17
+ * ESC closes the panel; clicking outside does NOT (intentional — losing
18
+ * chat state on a stray click is the most annoying widget UX there is).
19
+ */
20
+ const react_1 = require("react");
21
+ const react_dom_1 = require("react-dom");
22
+ const CuratorChat_js_1 = require("./CuratorChat.js");
23
+ function CuratorChatLauncher(props) {
24
+ const { placement = "bottom-right", offset = 24, defaultOpen = false, panelWidth = 440, panelHeight = 620, icon, ariaLabel = "Open chat", onOpen, onClose, ...chatProps } = props;
25
+ const [open, setOpen] = (0, react_1.useState)(defaultOpen);
26
+ // Defer portal mounting until after first client render so SSR
27
+ // frameworks (Next.js, Remix) don't trip on `document` not existing.
28
+ const [mounted, setMounted] = (0, react_1.useState)(false);
29
+ (0, react_1.useEffect)(() => setMounted(true), []);
30
+ // ESC closes the panel. Mounted only while open so we don't add a
31
+ // global listener for a usually-idle widget.
32
+ (0, react_1.useEffect)(() => {
33
+ if (!open)
34
+ return;
35
+ const onKey = (e) => {
36
+ if (e.key === "Escape")
37
+ doClose();
38
+ };
39
+ window.addEventListener("keydown", onKey);
40
+ return () => window.removeEventListener("keydown", onKey);
41
+ // eslint-disable-next-line react-hooks/exhaustive-deps
42
+ }, [open]);
43
+ const doOpen = (0, react_1.useCallback)(() => {
44
+ setOpen(true);
45
+ onOpen?.();
46
+ }, [onOpen]);
47
+ const doClose = (0, react_1.useCallback)(() => {
48
+ setOpen(false);
49
+ onClose?.();
50
+ }, [onClose]);
51
+ if (!mounted)
52
+ return null;
53
+ const corner = cornerStyle(placement, offset);
54
+ return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", { style: containerStyle, "data-curator-chat-launcher": true, "data-open": open ? "true" : "false", children: [open && ((0, jsx_runtime_1.jsx)("div", { role: "dialog", "aria-modal": "false", "aria-label": chatProps.title ?? "Chat", style: {
55
+ ...panelStyle,
56
+ ...panelAnchor(placement, offset),
57
+ width: panelWidth,
58
+ height: panelHeight,
59
+ }, children: (0, jsx_runtime_1.jsx)(CuratorChat_js_1.CuratorChat, { ...chatProps, onClose: doClose, style: {
60
+ height: "100%",
61
+ borderRadius: "inherit",
62
+ border: "none",
63
+ boxShadow: "none",
64
+ } }) })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: open ? doClose : doOpen, "aria-label": open ? "Close chat" : ariaLabel, "aria-expanded": open, style: {
65
+ ...bubbleStyle,
66
+ ...corner,
67
+ }, children: icon ?? (open ? (0, jsx_runtime_1.jsx)(CloseGlyph, {}) : (0, jsx_runtime_1.jsx)(ChatGlyph, {})) })] }), document.body);
68
+ }
69
+ function ChatGlyph() {
70
+ return ((0, jsx_runtime_1.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M3 5.5A2.5 2.5 0 0 1 5.5 3h13A2.5 2.5 0 0 1 21 5.5v9A2.5 2.5 0 0 1 18.5 17H9l-4.3 3.4a.75.75 0 0 1-1.2-.59V5.5Z", stroke: "currentColor", strokeWidth: "1.75", strokeLinejoin: "round", fill: "none" }) }));
71
+ }
72
+ function CloseGlyph() {
73
+ return ((0, jsx_runtime_1.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M6 6 18 18 M18 6 6 18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }));
74
+ }
75
+ // ── positioning ─────────────────────────────────────────────────
76
+ function cornerStyle(placement, offset) {
77
+ switch (placement) {
78
+ case "bottom-left":
79
+ return { bottom: offset, left: offset };
80
+ case "top-right":
81
+ return { top: offset, right: offset };
82
+ case "top-left":
83
+ return { top: offset, left: offset };
84
+ case "bottom-right":
85
+ default:
86
+ return { bottom: offset, right: offset };
87
+ }
88
+ }
89
+ const PANEL_GAP = 16;
90
+ const BUBBLE_SIZE = 56;
91
+ function panelAnchor(placement, offset) {
92
+ // Anchor the panel above/below the bubble depending on which vertical
93
+ // edge the launcher hugs. Horizontal alignment follows the same edge.
94
+ const vertical = placement === "top-right" || placement === "top-left"
95
+ ? { top: offset + BUBBLE_SIZE + PANEL_GAP }
96
+ : { bottom: offset + BUBBLE_SIZE + PANEL_GAP };
97
+ const horizontal = placement === "bottom-left" || placement === "top-left"
98
+ ? { left: offset }
99
+ : { right: offset };
100
+ return { ...vertical, ...horizontal };
101
+ }
102
+ // ── styles ──────────────────────────────────────────────────────
103
+ const containerStyle = {
104
+ position: "fixed",
105
+ inset: 0,
106
+ pointerEvents: "none",
107
+ zIndex: 2_147_483_000, // sit above Intercom/Crisp/etc; intentional max-ish
108
+ };
109
+ const bubbleStyle = {
110
+ position: "fixed",
111
+ width: BUBBLE_SIZE,
112
+ height: BUBBLE_SIZE,
113
+ borderRadius: "50%",
114
+ border: "none",
115
+ cursor: "pointer",
116
+ background: "#0f172a",
117
+ color: "#ffffff",
118
+ display: "flex",
119
+ alignItems: "center",
120
+ justifyContent: "center",
121
+ boxShadow: "0 8px 20px rgba(15, 23, 42, 0.25), 0 2px 6px rgba(15, 23, 42, 0.15)",
122
+ pointerEvents: "auto",
123
+ transition: "transform 120ms ease, box-shadow 120ms ease",
124
+ fontFamily: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
125
+ };
126
+ const panelStyle = {
127
+ position: "fixed",
128
+ background: "transparent",
129
+ borderRadius: 16,
130
+ overflow: "hidden",
131
+ boxShadow: "0 20px 50px rgba(15, 23, 42, 0.25), 0 4px 12px rgba(15, 23, 42, 0.12)",
132
+ pointerEvents: "auto",
133
+ };
134
+ //# sourceMappingURL=CuratorChatLauncher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CuratorChatLauncher.js","sourceRoot":"","sources":["../../src/CuratorChatLauncher.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * <CuratorProvider> — context provider for a Curator SDK client.
3
+ *
4
+ * const curator = new Curator({ apiKey, project, environment })
5
+ *
6
+ * <CuratorProvider client={curator}>
7
+ * <App />
8
+ * </CuratorProvider>
9
+ *
10
+ * Components beneath the provider can read the client via `useCurator()`
11
+ * or implicitly via `<CuratorChat agent="..." />` / `useCuratorChat({ agent })`.
12
+ *
13
+ * The provider deliberately holds no state of its own — it's a one-line
14
+ * pass-through. Treating the client as plain context (rather than a
15
+ * module-level singleton) keeps tests, SSR, and multi-tenant trees clean.
16
+ */
17
+ import { type ReactNode } from "react";
18
+ import type { Curator } from "@darqlabs/curator-sdk";
19
+ export interface CuratorProviderProps {
20
+ /** The SDK instance — create once and reuse for the lifetime of the app. */
21
+ client: Curator;
22
+ children: ReactNode;
23
+ }
24
+ export declare function CuratorProvider({ client, children }: CuratorProviderProps): import("react").JSX.Element;
25
+ /**
26
+ * Read the Curator client from context. Throws if no `<CuratorProvider>`
27
+ * is mounted higher in the tree — a hard failure here is friendlier than
28
+ * a silent null that surfaces later as a confusing runtime error.
29
+ */
30
+ export declare function useCurator(): Curator;
31
+ /**
32
+ * Same as `useCurator()` but returns `null` instead of throwing when no
33
+ * provider is mounted. Useful inside components that want to fall back
34
+ * to a `curator` prop, like `<CuratorChat>`.
35
+ */
36
+ export declare function useCuratorOrNull(): Curator | null;
37
+ //# sourceMappingURL=CuratorProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CuratorProvider.d.ts","sourceRoot":"","sources":["../../src/CuratorProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAIpD,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,oBAAoB,+BAEzE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,OAAO,CASpC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,GAAG,IAAI,CAEjD"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CuratorProvider = CuratorProvider;
4
+ exports.useCurator = useCurator;
5
+ exports.useCuratorOrNull = useCuratorOrNull;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ /**
8
+ * <CuratorProvider> — context provider for a Curator SDK client.
9
+ *
10
+ * const curator = new Curator({ apiKey, project, environment })
11
+ *
12
+ * <CuratorProvider client={curator}>
13
+ * <App />
14
+ * </CuratorProvider>
15
+ *
16
+ * Components beneath the provider can read the client via `useCurator()`
17
+ * or implicitly via `<CuratorChat agent="..." />` / `useCuratorChat({ agent })`.
18
+ *
19
+ * The provider deliberately holds no state of its own — it's a one-line
20
+ * pass-through. Treating the client as plain context (rather than a
21
+ * module-level singleton) keeps tests, SSR, and multi-tenant trees clean.
22
+ */
23
+ const react_1 = require("react");
24
+ const CuratorContext = (0, react_1.createContext)(null);
25
+ function CuratorProvider({ client, children }) {
26
+ return (0, jsx_runtime_1.jsx)(CuratorContext.Provider, { value: client, children: children });
27
+ }
28
+ /**
29
+ * Read the Curator client from context. Throws if no `<CuratorProvider>`
30
+ * is mounted higher in the tree — a hard failure here is friendlier than
31
+ * a silent null that surfaces later as a confusing runtime error.
32
+ */
33
+ function useCurator() {
34
+ const client = (0, react_1.useContext)(CuratorContext);
35
+ if (!client) {
36
+ throw new Error("useCurator() (or a Curator component) was called outside a <CuratorProvider>. " +
37
+ "Wrap your app: <CuratorProvider client={curator}>…</CuratorProvider>.");
38
+ }
39
+ return client;
40
+ }
41
+ /**
42
+ * Same as `useCurator()` but returns `null` instead of throwing when no
43
+ * provider is mounted. Useful inside components that want to fall back
44
+ * to a `curator` prop, like `<CuratorChat>`.
45
+ */
46
+ function useCuratorOrNull() {
47
+ return (0, react_1.useContext)(CuratorContext);
48
+ }
49
+ //# sourceMappingURL=CuratorProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CuratorProvider.js","sourceRoot":"","sources":["../../src/CuratorProvider.tsx"],"names":[],"mappings":";;AA4BA,0CAEC;AAOD,gCASC;AAOD,4CAEC;;AAvDD;;;;;;;;;;;;;;;GAeG;AAEH,iCAAiE;AAGjE,MAAM,cAAc,GAAG,IAAA,qBAAa,EAAiB,IAAI,CAAC,CAAA;AAQ1D,SAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAwB;IACxE,OAAO,uBAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,YAAG,QAAQ,GAA2B,CAAA;AACrF,CAAC;AAED;;;;GAIG;AACH,SAAgB,UAAU;IACxB,MAAM,MAAM,GAAG,IAAA,kBAAU,EAAC,cAAc,CAAC,CAAA;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,gFAAgF;YAC9E,uEAAuE,CAC1E,CAAA;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB;IAC9B,OAAO,IAAA,kBAAU,EAAC,cAAc,CAAC,CAAA;AACnC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Markdown renderer for assistant messages.
3
+ *
4
+ * Wraps `react-markdown` with a couple of safe defaults:
5
+ * - Links open in a new tab with rel="noopener noreferrer".
6
+ * - No raw HTML execution (react-markdown's default; documented for
7
+ * clarity).
8
+ *
9
+ * Styling is in CuratorChat.tsx via a `data-curator-md` selector so
10
+ * the rules can target the markdown output without touching the
11
+ * surrounding bubble layout.
12
+ */
13
+ export declare function Markdown({ content }: {
14
+ content: string;
15
+ }): import("react").JSX.Element;
16
+ //# sourceMappingURL=Markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkBH,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,+BAMxD"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Markdown = Markdown;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_markdown_1 = __importDefault(require("react-markdown"));
9
+ const normalizeMarkdown_js_1 = require("./normalizeMarkdown.js");
10
+ const components = {
11
+ a({ children, ...props }) {
12
+ return ((0, jsx_runtime_1.jsx)("a", { ...props, target: "_blank", rel: "noopener noreferrer", children: children }));
13
+ },
14
+ };
15
+ function Markdown({ content }) {
16
+ return ((0, jsx_runtime_1.jsx)("div", { "data-curator-md": true, children: (0, jsx_runtime_1.jsx)(react_markdown_1.default, { components: components, children: (0, normalizeMarkdown_js_1.normalizeMarkdown)(content) }) }));
17
+ }
18
+ //# sourceMappingURL=Markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Markdown.js","sourceRoot":"","sources":["../../src/Markdown.tsx"],"names":[],"mappings":";;;;;AA6BA,4BAMC;;AArBD,oEAA0C;AAC1C,iEAA0D;AAI1D,MAAM,UAAU,GAAiB;IAC/B,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE;QACtB,OAAO,CACL,iCAAO,KAAK,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,YACpD,QAAQ,GACP,CACL,CAAA;IACH,CAAC;CACF,CAAA;AAED,SAAgB,QAAQ,CAAC,EAAE,OAAO,EAAuB;IACvD,OAAO,CACL,mEACE,uBAAC,wBAAa,IAAC,UAAU,EAAE,UAAU,YAAG,IAAA,wCAAiB,EAAC,OAAO,CAAC,GAAiB,GAC/E,CACP,CAAA;AACH,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * "Powered by Curator" brand mark + footer used inside `<CuratorChat />`.
3
+ *
4
+ * Inline SVG so no asset fetch, no external dep. Sized to be quiet — it
5
+ * sits at the bottom of the chat panel without competing with content.
6
+ */
7
+ /**
8
+ * Brand footer rendered at the bottom of every chat panel. Deliberately
9
+ * has no props — visibility is not consumer-configurable. Enterprise
10
+ * subscriptions may later unlock hiding, but that gating belongs on the
11
+ * server (key claim or org tier), not in a client-side boolean.
12
+ */
13
+ export declare function PoweredByCurator(): import("react").JSX.Element;
14
+ /**
15
+ * Curator brand mark — the icosahedron logo. Inlined as a single path
16
+ * so it renders without an asset fetch, and bound to `currentColor` so
17
+ * it inherits the surrounding text color (light vs. dark theme).
18
+ *
19
+ * Path geometry is the same one used across the brand site and in-app
20
+ * TopNav; ported here so `@darqlabs/curator-sdk-react` doesn't depend on the host
21
+ * shipping the SVG asset.
22
+ */
23
+ export declare function CuratorMark({ size }: {
24
+ size?: number;
25
+ }): import("react").JSX.Element;
26
+ //# sourceMappingURL=brand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../../src/brand.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;;;GAKG;AACH,wBAAgB,gBAAgB,gCAc/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAS,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,+BAa3D"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PoweredByCurator = PoweredByCurator;
4
+ exports.CuratorMark = CuratorMark;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const POWERED_BY_URL = "https://curator.darqlabs.ai";
7
+ /**
8
+ * Brand footer rendered at the bottom of every chat panel. Deliberately
9
+ * has no props — visibility is not consumer-configurable. Enterprise
10
+ * subscriptions may later unlock hiding, but that gating belongs on the
11
+ * server (key claim or org tier), not in a client-side boolean.
12
+ */
13
+ function PoweredByCurator() {
14
+ return ((0, jsx_runtime_1.jsxs)("a", { href: POWERED_BY_URL, target: "_blank", rel: "noopener noreferrer", style: footerStyle, "aria-label": "Powered by Curator", children: [(0, jsx_runtime_1.jsx)("span", { children: "Powered by" }), (0, jsx_runtime_1.jsx)(CuratorMark, {}), (0, jsx_runtime_1.jsx)("span", { style: wordmarkStyle, children: "Curator" })] }));
15
+ }
16
+ /**
17
+ * Curator brand mark — the icosahedron logo. Inlined as a single path
18
+ * so it renders without an asset fetch, and bound to `currentColor` so
19
+ * it inherits the surrounding text color (light vs. dark theme).
20
+ *
21
+ * Path geometry is the same one used across the brand site and in-app
22
+ * TopNav; ported here so `@darqlabs/curator-sdk-react` doesn't depend on the host
23
+ * shipping the SVG asset.
24
+ */
25
+ function CuratorMark({ size = 14 }) {
26
+ return ((0, jsx_runtime_1.jsx)("svg", { width: size, height: size, viewBox: "0 0 512 512", fill: "currentColor", "aria-hidden": "true", style: { flexShrink: 0 }, children: (0, jsx_runtime_1.jsx)("path", { d: "M490.421,137.707c-0.085-1.003-0.149-2.005-0.555-2.987c-0.107-0.256-0.32-0.427-0.448-0.683c-0.277-0.533-0.597-0.981-0.96-1.472c-0.725-1.003-1.536-1.835-2.517-2.517c-0.256-0.171-0.363-0.491-0.64-0.64l-224-128c-3.285-1.877-7.296-1.877-10.581,0l-224,128c-0.256,0.171-0.363,0.469-0.619,0.64c-1.024,0.704-1.899,1.557-2.645,2.624c-0.299,0.427-0.597,0.811-0.832,1.28c-0.149,0.277-0.384,0.469-0.512,0.768c-0.469,1.173-0.619,2.389-0.661,3.584c0,0.128-0.107,0.256-0.107,0.384v0.171c0,0.021,0,0.021,0,0.043v234.304c0,0.021,0,0.064,0,0.085v0.064c0,0.213,0.149,0.405,0.171,0.619c0.085,1.493,0.32,2.987,1.045,4.352c0.043,0.085,0.128,0.107,0.171,0.192c0.277,0.491,0.768,0.811,1.131,1.259c0.789,0.981,1.557,1.941,2.603,2.603c0.107,0.064,0.149,0.192,0.235,0.235l224,128c1.664,0.939,3.477,1.408,5.312,1.408s3.648-0.469,5.291-1.408l224-128c0.107-0.064,0.149-0.192,0.256-0.256c0.981-0.597,1.664-1.493,2.411-2.389c0.427-0.512,1.003-0.896,1.323-1.472c0.043-0.064,0.107-0.107,0.149-0.171c0.576-1.109,0.683-2.325,0.853-3.52c0.064-0.491,0.384-0.939,0.384-1.451V138.688C490.677,138.347,490.443,138.048,490.421,137.707z M455.52,136.981l-78.251,31.296L291.211,43.093L455.52,136.981z M256.011,29.504l97.067,141.184H158.944L256.011,29.504z M220.747,43.115l-86.037,125.163L56.48,136.981L220.747,43.115z M42.677,154.432l80.768,32.32L42.677,332.16V154.432z M138.635,203.392l98.325,178.773L49.248,364.288L138.635,203.392z M245.344,482.965l-165.12-94.336l165.12,15.573V482.965z M256.011,372.544l-99.285-180.523h198.571L256.011,372.544z M266.677,482.965v-78.571l165.035-15.723L266.677,482.965z M274.997,382.357l98.411-178.901l89.365,160.853L274.997,382.357z M469.344,332.203l-80.811-145.451l80.811-32.32V332.203z" }) }));
27
+ }
28
+ const footerStyle = {
29
+ display: "inline-flex",
30
+ alignItems: "center",
31
+ gap: 7,
32
+ textDecoration: "none",
33
+ color: "var(--curator-muted)",
34
+ fontSize: 11,
35
+ lineHeight: 1,
36
+ letterSpacing: 0.1,
37
+ padding: "14px 18px",
38
+ alignSelf: "center",
39
+ // No visible border / background — sits as a quiet caption
40
+ opacity: 0.7,
41
+ transition: "opacity 120ms ease",
42
+ };
43
+ const wordmarkStyle = {
44
+ fontWeight: 600,
45
+ color: "var(--curator-text)",
46
+ };
47
+ //# sourceMappingURL=brand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand.js","sourceRoot":"","sources":["../../src/brand.tsx"],"names":[],"mappings":";;AAiBA,4CAcC;AAWD,kCAaC;;AA9CD,MAAM,cAAc,GAAG,6BAA6B,CAAA;AAEpD;;;;;GAKG;AACH,SAAgB,gBAAgB;IAC9B,OAAO,CACL,+BACE,IAAI,EAAE,cAAc,EACpB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,KAAK,EAAE,WAAW,gBACP,oBAAoB,aAE/B,0DAAuB,EACvB,uBAAC,WAAW,KAAG,EACf,iCAAM,KAAK,EAAE,aAAa,wBAAgB,IACxC,CACL,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,WAAW,CAAC,EAAE,IAAI,GAAG,EAAE,EAAqB;IAC1D,OAAO,CACL,gCACE,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,OAAO,EAAC,aAAa,EACrB,IAAI,EAAC,cAAc,iBACP,MAAM,EAClB,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,YAExB,iCAAM,CAAC,EAAC,6oDAA6oD,GAAG,GACppD,CACP,CAAA;AACH,CAAC;AAED,MAAM,WAAW,GAAkB;IACjC,OAAO,EAAE,aAAa;IACtB,UAAU,EAAE,QAAQ;IACpB,GAAG,EAAE,CAAC;IACN,cAAc,EAAE,MAAM;IACtB,KAAK,EAAE,sBAAsB;IAC7B,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,CAAC;IACb,aAAa,EAAE,GAAG;IAClB,OAAO,EAAE,WAAW;IACpB,SAAS,EAAE,QAAQ;IACnB,2DAA2D;IAC3D,OAAO,EAAE,GAAG;IACZ,UAAU,EAAE,oBAAoB;CACjC,CAAA;AAED,MAAM,aAAa,GAAkB;IACnC,UAAU,EAAE,GAAG;IACf,KAAK,EAAE,qBAAqB;CAC7B,CAAA"}
@@ -0,0 +1,10 @@
1
+ export { CuratorChat } from "./CuratorChat.js";
2
+ export type { CuratorChatProps } from "./CuratorChat.js";
3
+ export { CuratorChatLauncher } from "./CuratorChatLauncher.js";
4
+ export type { CuratorChatLauncherProps, LauncherPlacement, } from "./CuratorChatLauncher.js";
5
+ export { useCuratorChat } from "./useCuratorChat.js";
6
+ export type { ChatBubble, UseCuratorChatOptions, UseCuratorChatResult, SendArgs, } from "./useCuratorChat.js";
7
+ export { CuratorProvider, useCurator, useCuratorOrNull } from "./CuratorProvider.js";
8
+ export type { CuratorProviderProps } from "./CuratorProvider.js";
9
+ export { PoweredByCurator, CuratorMark } from "./brand.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,YAAY,EACV,wBAAwB,EACxB,iBAAiB,GAClB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EACV,UAAU,EACV,qBAAqB,EACrB,oBAAoB,EACpB,QAAQ,GACT,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACpF,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CuratorMark = exports.PoweredByCurator = exports.useCuratorOrNull = exports.useCurator = exports.CuratorProvider = exports.useCuratorChat = exports.CuratorChatLauncher = exports.CuratorChat = void 0;
4
+ var CuratorChat_js_1 = require("./CuratorChat.js");
5
+ Object.defineProperty(exports, "CuratorChat", { enumerable: true, get: function () { return CuratorChat_js_1.CuratorChat; } });
6
+ var CuratorChatLauncher_js_1 = require("./CuratorChatLauncher.js");
7
+ Object.defineProperty(exports, "CuratorChatLauncher", { enumerable: true, get: function () { return CuratorChatLauncher_js_1.CuratorChatLauncher; } });
8
+ var useCuratorChat_js_1 = require("./useCuratorChat.js");
9
+ Object.defineProperty(exports, "useCuratorChat", { enumerable: true, get: function () { return useCuratorChat_js_1.useCuratorChat; } });
10
+ var CuratorProvider_js_1 = require("./CuratorProvider.js");
11
+ Object.defineProperty(exports, "CuratorProvider", { enumerable: true, get: function () { return CuratorProvider_js_1.CuratorProvider; } });
12
+ Object.defineProperty(exports, "useCurator", { enumerable: true, get: function () { return CuratorProvider_js_1.useCurator; } });
13
+ Object.defineProperty(exports, "useCuratorOrNull", { enumerable: true, get: function () { return CuratorProvider_js_1.useCuratorOrNull; } });
14
+ var brand_js_1 = require("./brand.js");
15
+ Object.defineProperty(exports, "PoweredByCurator", { enumerable: true, get: function () { return brand_js_1.PoweredByCurator; } });
16
+ Object.defineProperty(exports, "CuratorMark", { enumerable: true, get: function () { return brand_js_1.CuratorMark; } });
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,mDAA8C;AAArC,6GAAA,WAAW,OAAA;AAEpB,mEAA8D;AAArD,6HAAA,mBAAmB,OAAA;AAK5B,yDAAoD;AAA3C,mHAAA,cAAc,OAAA;AAOvB,2DAAoF;AAA3E,qHAAA,eAAe,OAAA;AAAE,gHAAA,UAAU,OAAA;AAAE,sHAAA,gBAAgB,OAAA;AAEtD,uCAA0D;AAAjD,4GAAA,gBAAgB,OAAA;AAAE,uGAAA,WAAW,OAAA"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Pre-pass that tightens chat-friendly markdown without changing prose.
3
+ *
4
+ * 1. Trim, and collapse 3+ blank lines to a single blank line.
5
+ * 2. Collapse blank lines *between list items* so the list stays
6
+ * "tight" (per CommonMark). A blank line anywhere in a list flips
7
+ * the whole thing to "loose," and loose lists wrap every item in
8
+ * a `<p>` — the paragraph margins then make a structured list look
9
+ * like a stack of disconnected sentences. LLMs frequently emit a
10
+ * stray blank line inside a long list, so this is the highest-
11
+ * impact normalization step.
12
+ * 3. When the LLM emits a run of short single-line "facts" separated
13
+ * by blank lines (`Status: Job Closed\n\nCreated At: …\n\nTimeline:
14
+ * …`), merge each run into one paragraph with hard line breaks
15
+ * (` \n`). Markdown then renders the run as a single <p> with
16
+ * <br>s between lines instead of N separate paragraphs.
17
+ *
18
+ * Multi-line paragraphs, list items, headings, code fences, block
19
+ * quotes, and tables are left untouched so real prose, lists, and
20
+ * structured blocks render normally. Blank lines inside fenced code
21
+ * blocks are preserved exactly.
22
+ */
23
+ export declare function normalizeMarkdown(content: string): string;
24
+ //# sourceMappingURL=normalizeMarkdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeMarkdown.d.ts","sourceRoot":"","sources":["../../src/normalizeMarkdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAkEH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAyBzD"}
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ /**
3
+ * Pre-pass that tightens chat-friendly markdown without changing prose.
4
+ *
5
+ * 1. Trim, and collapse 3+ blank lines to a single blank line.
6
+ * 2. Collapse blank lines *between list items* so the list stays
7
+ * "tight" (per CommonMark). A blank line anywhere in a list flips
8
+ * the whole thing to "loose," and loose lists wrap every item in
9
+ * a `<p>` — the paragraph margins then make a structured list look
10
+ * like a stack of disconnected sentences. LLMs frequently emit a
11
+ * stray blank line inside a long list, so this is the highest-
12
+ * impact normalization step.
13
+ * 3. When the LLM emits a run of short single-line "facts" separated
14
+ * by blank lines (`Status: Job Closed\n\nCreated At: …\n\nTimeline:
15
+ * …`), merge each run into one paragraph with hard line breaks
16
+ * (` \n`). Markdown then renders the run as a single <p> with
17
+ * <br>s between lines instead of N separate paragraphs.
18
+ *
19
+ * Multi-line paragraphs, list items, headings, code fences, block
20
+ * quotes, and tables are left untouched so real prose, lists, and
21
+ * structured blocks render normally. Blank lines inside fenced code
22
+ * blocks are preserved exactly.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.normalizeMarkdown = normalizeMarkdown;
26
+ const FACT_LINE_MAX = 120;
27
+ const MARKDOWN_BLOCK_START = /^\s*([-*+]\s|\d+\.\s|#{1,6}\s|>\s|```|\||\t)/;
28
+ const LIST_ITEM = /^\s*(?:[-*+]|\d+\.)\s/;
29
+ // "Continuation" of a list item: an indented non-blank line. Captures the
30
+ // case where the previous logical entry is something like
31
+ // ` - Location: 4000 Redondo Beach Ave, ...` and the next item sits
32
+ // at a different indent.
33
+ const LIST_CONTINUATION = /^[ \t]+\S/;
34
+ const CODE_FENCE = /^\s*```/;
35
+ /**
36
+ * Drop blank lines that sit between two list-y lines. A code-fence state
37
+ * machine guards blank lines inside fenced code blocks — those stay.
38
+ */
39
+ function collapseLooseListBlanks(input) {
40
+ const lines = input.split("\n");
41
+ const out = [];
42
+ let inFence = false;
43
+ for (let i = 0; i < lines.length; i++) {
44
+ const line = lines[i];
45
+ if (CODE_FENCE.test(line)) {
46
+ inFence = !inFence;
47
+ out.push(line);
48
+ continue;
49
+ }
50
+ if (inFence) {
51
+ out.push(line);
52
+ continue;
53
+ }
54
+ if (line.trim() === "") {
55
+ // Look back to the most recent non-blank line we've already emitted.
56
+ let prevIdx = out.length - 1;
57
+ while (prevIdx >= 0 && out[prevIdx].trim() === "")
58
+ prevIdx--;
59
+ // Look forward to the next non-blank source line.
60
+ let nextIdx = i + 1;
61
+ while (nextIdx < lines.length && lines[nextIdx].trim() === "")
62
+ nextIdx++;
63
+ if (prevIdx >= 0 && nextIdx < lines.length) {
64
+ const prev = out[prevIdx];
65
+ const next = lines[nextIdx];
66
+ if ((LIST_ITEM.test(prev) || LIST_CONTINUATION.test(prev)) &&
67
+ LIST_ITEM.test(next)) {
68
+ // Drop this blank — the list stays tight.
69
+ continue;
70
+ }
71
+ }
72
+ }
73
+ out.push(line);
74
+ }
75
+ return out.join("\n");
76
+ }
77
+ function isShortFact(paragraph) {
78
+ if (paragraph.includes("\n"))
79
+ return false;
80
+ if (paragraph.length > FACT_LINE_MAX)
81
+ return false;
82
+ if (MARKDOWN_BLOCK_START.test(paragraph))
83
+ return false;
84
+ return true;
85
+ }
86
+ function normalizeMarkdown(content) {
87
+ const trimmed = collapseLooseListBlanks(content.trim()).replace(/\n{3,}/g, "\n\n");
88
+ const paragraphs = trimmed.split(/\n\n/);
89
+ const out = [];
90
+ let factRun = [];
91
+ const flushRun = () => {
92
+ if (factRun.length === 0)
93
+ return;
94
+ // ` \n` (two trailing spaces + newline) is markdown's hard line
95
+ // break — renders as <br> instead of a new paragraph.
96
+ out.push(factRun.join(" \n"));
97
+ factRun = [];
98
+ };
99
+ for (const p of paragraphs) {
100
+ if (isShortFact(p)) {
101
+ factRun.push(p);
102
+ }
103
+ else {
104
+ flushRun();
105
+ out.push(p);
106
+ }
107
+ }
108
+ flushRun();
109
+ return out.join("\n\n");
110
+ }
111
+ //# sourceMappingURL=normalizeMarkdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeMarkdown.js","sourceRoot":"","sources":["../../src/normalizeMarkdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Headless chat hook for the Curator SDK.
3
+ *
4
+ * Manages a single conversation against a deployed agent. Owns the
5
+ * `Chat` instance from the SDK, exposes the rolling message list, a
6
+ * `send()` action, and the various pending/error states the UI needs.
7
+ *
8
+ * Bring your own UI on top of this hook, or use `<CuratorChat />` for
9
+ * the drop-in styled widget that consumes this hook internally.
10
+ */
11
+ import type { AssistantMessage, Chat, Curator, CuratorError, Environment, FileAttachment } from "@darqlabs/curator-sdk";
12
+ /** Local message representation — superset of what the SDK returns plus
13
+ * optimistic user messages and inline error markers. */
14
+ export type ChatBubble = {
15
+ kind: "user";
16
+ content: string;
17
+ /** Stable local id; not persisted to the server. */
18
+ localId: string;
19
+ } | {
20
+ kind: "assistant";
21
+ content: string;
22
+ sequence: number;
23
+ stepId: string | null;
24
+ createdAt: string;
25
+ runId: string;
26
+ } | {
27
+ kind: "error";
28
+ message: string;
29
+ localId: string;
30
+ };
31
+ export interface UseCuratorChatOptions {
32
+ /**
33
+ * SDK instance. Optional when a `<CuratorProvider>` is mounted higher
34
+ * in the tree — the hook reads the client from context as a fallback.
35
+ * Pass explicitly to override or to address multiple clients.
36
+ */
37
+ curator?: Curator;
38
+ /** Deployment slug to address. */
39
+ agent: string;
40
+ /** Override the SDK's default project for this chat. */
41
+ project?: string;
42
+ /** Override the SDK's default environment for this chat. */
43
+ environment?: Environment;
44
+ /** Hit a system-scoped deployment instead of a project-scoped one. */
45
+ system?: boolean;
46
+ /**
47
+ * Reattach to an existing conversation id instead of opening a fresh one.
48
+ * Useful for resuming across sessions.
49
+ */
50
+ conversationId?: string;
51
+ /** Fired once per successfully-returned assistant message. */
52
+ onMessage?: (message: AssistantMessage) => void;
53
+ /** Fired on any send-time error (typed SDK error or unknown). */
54
+ onError?: (error: CuratorError | Error) => void;
55
+ }
56
+ export interface SendArgs {
57
+ files?: FileAttachment[];
58
+ /** Override the SDK-default sync-wait timeout for this send. */
59
+ timeoutMs?: number;
60
+ }
61
+ export interface UseCuratorChatResult {
62
+ /** All bubbles, in chronological order. */
63
+ messages: ChatBubble[];
64
+ /** Send a user message and await the assistant's reply. */
65
+ send: (content: string, args?: SendArgs) => Promise<void>;
66
+ /** True while a send is in flight. */
67
+ sending: boolean;
68
+ /** Most recent error, or null. Cleared on the next successful send. */
69
+ error: CuratorError | Error | null;
70
+ /** Underlying SDK `Chat` instance; exposed for advanced use. */
71
+ chat: Chat;
72
+ /** Conversation id, or null until the first send creates one. */
73
+ conversationId: string | null;
74
+ /** Clear the visible message list and detach the current conversation
75
+ * by allocating a fresh Chat. */
76
+ reset: () => void;
77
+ }
78
+ export declare function useCuratorChat(opts: UseCuratorChatOptions): UseCuratorChatResult;
79
+ //# sourceMappingURL=useCuratorChat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCuratorChat.d.ts","sourceRoot":"","sources":["../../src/useCuratorChat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EACV,gBAAgB,EAChB,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,WAAW,EACX,cAAc,EACf,MAAM,uBAAuB,CAAA;AAa9B;yDACyD;AACzD,MAAM,MAAM,UAAU,GAClB;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAA;CAChB,GACD;IACE,IAAI,EAAE,WAAW,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,GACD;IACE,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAEL,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC/C,iEAAiE;IACjE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,KAAK,IAAI,CAAA;CAChD;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAA;IACxB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,2CAA2C;IAC3C,QAAQ,EAAE,UAAU,EAAE,CAAA;IACtB,2DAA2D;IAC3D,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACzD,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,uEAAuE;IACvE,KAAK,EAAE,YAAY,GAAG,KAAK,GAAG,IAAI,CAAA;IAClC,gEAAgE;IAChE,IAAI,EAAE,IAAI,CAAA;IACV,iEAAiE;IACjE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B;sCACkC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAQD,wBAAgB,cAAc,CAAC,IAAI,EAAE,qBAAqB,GAAG,oBAAoB,CAgGhF"}