@aintela/chat 0.2.27 → 0.2.29
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/{promptHighlight-BHSQkdFs.js → atMentions-DqhG_vde.js} +37 -17
- package/dist/atMentions-DqhG_vde.js.map +1 -0
- package/dist/{auth-GFZAFz7L.js → auth-BN22f1HF.js} +2 -2
- package/dist/{auth-GFZAFz7L.js.map → auth-BN22f1HF.js.map} +1 -1
- package/dist/components.js +4756 -4639
- package/dist/components.js.map +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.js +54 -52
- package/dist/src/ErrorBondary.d.ts +1 -1
- package/dist/src/components/v2/PromptV2.d.ts +11 -0
- package/dist/src/hooks/usePromptAssist.d.ts +1 -0
- package/dist/src/services/httpPromptAssistService.d.ts +5 -0
- package/dist/src/utils/atMentions.d.ts +28 -0
- package/dist/src/utils/atMentions.test.d.ts +1 -0
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/useContainerWidth-D0CQQqZ2.js +262 -0
- package/dist/useContainerWidth-D0CQQqZ2.js.map +1 -0
- package/dist/utils.js +28 -26
- package/package.json +1 -1
- package/dist/promptHighlight-BHSQkdFs.js.map +0 -1
- package/dist/useContainerWidth-0EA-kdzl.js +0 -260
- package/dist/useContainerWidth-0EA-kdzl.js.map +0 -1
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
var St = Object.defineProperty;
|
|
2
|
-
var R = (a, c) => St(a, "name", { value: c, configurable: !0 });
|
|
3
|
-
import { useState as v, useRef as u, useCallback as A, useEffect as H } from "react";
|
|
4
|
-
const pt = /* @__PURE__ */ R(() => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : `s-${Date.now()}-${Math.random()}`, "newSessionId"), wt = /* @__PURE__ */ R((a, c, h) => {
|
|
5
|
-
var m;
|
|
6
|
-
const l = a.length;
|
|
7
|
-
let n = c;
|
|
8
|
-
for (let f = 0; f < l; f++)
|
|
9
|
-
if (n = (n + h + l) % l, !((m = a[n]) != null && m.disabled)) return n;
|
|
10
|
-
return c;
|
|
11
|
-
}, "nextEnabledIndex"), At = /* @__PURE__ */ R((a) => {
|
|
12
|
-
const c = /* @__PURE__ */ new Date();
|
|
13
|
-
c.setDate(c.getDate() + a);
|
|
14
|
-
const h = String(c.getDate()).padStart(2, "0"), l = String(c.getMonth() + 1).padStart(2, "0");
|
|
15
|
-
return `${h}/${l}/${c.getFullYear()}`;
|
|
16
|
-
}, "plusDaysBR");
|
|
17
|
-
function Lt(a, c, h = {}) {
|
|
18
|
-
const [l, n] = v(null), [m, f] = v(!1), [D, p] = v(0), [O, K] = v([]), [L, ct] = v([]), [$t, J] = v(""), j = u(""), q = u(null), V = u(a);
|
|
19
|
-
V.current = a;
|
|
20
|
-
const P = u(c);
|
|
21
|
-
P.current = c;
|
|
22
|
-
const st = u(h);
|
|
23
|
-
st.current = h;
|
|
24
|
-
const z = u(null), B = u(null), it = u(0), lt = u(0), X = u(null), M = u(""), U = u(null), _ = u(null), tt = u(pt()), N = u(null);
|
|
25
|
-
N.current = l;
|
|
26
|
-
const Q = u(null), at = u(""), ut = u(() => {
|
|
27
|
-
}), yt = A(() => n(null), []), bt = A(() => {
|
|
28
|
-
K([]), ct([]), J(""), j.current = "", U.current = null, tt.current = pt();
|
|
29
|
-
}, []), et = A((t) => {
|
|
30
|
-
if (t.disabled) return;
|
|
31
|
-
n(null);
|
|
32
|
-
const e = V.current, g = e.getTextarea();
|
|
33
|
-
if (!g) return;
|
|
34
|
-
const y = g.selectionStart ?? g.value.length, k = g.value.slice(0, y), T = g.value.slice(y), o = t.kind === "namedLocation" || t.kind === "location";
|
|
35
|
-
let r;
|
|
36
|
-
if (o) {
|
|
37
|
-
const d = at.current, $ = k.replace(/\s+$/, "");
|
|
38
|
-
r = d && $.endsWith(d) ? $.slice(0, $.length - d.length) : k;
|
|
39
|
-
} else {
|
|
40
|
-
const d = k.search(/\S+$/);
|
|
41
|
-
r = d === -1 ? k : k.slice(0, d);
|
|
42
|
-
}
|
|
43
|
-
const s = r.length > 0 && !/\s$/.test(r);
|
|
44
|
-
if (t.kind === "date") {
|
|
45
|
-
const d = `${s ? " " : ""}${t.insert} `, $ = `${r}${d}${T}`;
|
|
46
|
-
e.setDraft($), e.focusCaret(r.length + d.length), M.current = $, U.current = null, ut.current();
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
if (t.kind === "namedLocation" && t.insert) {
|
|
50
|
-
const d = `@${t.insert.replace(/ /g, " ")}`, $ = `${s ? " " : ""}${d} `;
|
|
51
|
-
e.setDraft(`${r}${$}${T}`), e.focusCaret(r.length + $.length);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const Y = t.kind === "location" ? "@" : "#", W = `${s ? " " : ""}${Y}`;
|
|
55
|
-
e.setDraft(`${r}${W}${T}`), e.focusCaret(r.length + W.length), requestAnimationFrame(() => {
|
|
56
|
-
const d = e.getTextarea();
|
|
57
|
-
d && e.syncTrigger(d);
|
|
58
|
-
});
|
|
59
|
-
}, []), nt = A(async () => {
|
|
60
|
-
var y;
|
|
61
|
-
const t = P.current.resolveDates;
|
|
62
|
-
if (!t) return;
|
|
63
|
-
const e = M.current;
|
|
64
|
-
if (e.trim() === "") {
|
|
65
|
-
U.current = null;
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
if (e === U.current) return;
|
|
69
|
-
U.current = e, (y = _.current) == null || y.abort();
|
|
70
|
-
const g = new AbortController();
|
|
71
|
-
_.current = g;
|
|
72
|
-
try {
|
|
73
|
-
const { dates: k, locations: T } = await t(e, tt.current, g.signal);
|
|
74
|
-
if (M.current !== e) return;
|
|
75
|
-
const o = k.filter((s) => s.display).map((s) => ({ text: s.text, display: s.display }));
|
|
76
|
-
ct(o), K(T.map((s) => s.text).filter((s) => s.trim().length > 0));
|
|
77
|
-
const r = o.map((s) => `${s.text}=${s.display}`).join("|");
|
|
78
|
-
o.length > 0 && r !== j.current && (j.current = r, J(o[o.length - 1].text), q.current != null && window.clearTimeout(q.current), q.current = window.setTimeout(() => J(""), 2e3)), o.length === 0 && (j.current = "");
|
|
79
|
-
} catch {
|
|
80
|
-
}
|
|
81
|
-
}, []);
|
|
82
|
-
ut.current = nt;
|
|
83
|
-
const Rt = A((t, e, g) => {
|
|
84
|
-
M.current = t;
|
|
85
|
-
const y = P.current.analyze;
|
|
86
|
-
y && (!g || N.current !== null) && (z.current != null && window.clearTimeout(z.current), z.current = window.setTimeout(async () => {
|
|
87
|
-
var T;
|
|
88
|
-
const k = ++it.current;
|
|
89
|
-
try {
|
|
90
|
-
const o = await y(t, e);
|
|
91
|
-
if (k !== it.current) return;
|
|
92
|
-
const r = V.current, s = r.getTextarea();
|
|
93
|
-
if (!s || s.value !== t) return;
|
|
94
|
-
const Y = (s.selectionStart ?? e) === t.length, W = r.hasAtQuery, d = r.isPickerOpen(), $ = o.suggestions ?? [], { enableHashDatePicker: Tt = !1, datePresets: xt = ["amanhã de manhã", "quarta-feira à noite"] } = st.current;
|
|
95
|
-
let C = o.category === "location" ? "location" : o.category === "date" ? "date" : o.locationExpected ? "location" : o.dateExpected ? "date" : null;
|
|
96
|
-
if (C !== "location" && o.locationCount < 2 && P.current.suggest && N.current !== null && Q.current === "location" && Y && /\s$/.test(t) && (C = "location"), C === "location" && o.locationCount >= 2 && o.locationPartialEmpty) {
|
|
97
|
-
n(null), Q.current = null;
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
if (C === null || !(Y && !d && (C === "location" ? W : C === "date"))) {
|
|
101
|
-
n(null), Q.current = null;
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const b = C;
|
|
105
|
-
Q.current = b;
|
|
106
|
-
const rt = /* @__PURE__ */ R(() => b === "date" && Tt ? [{ key: "cal", label: `📅 no dia #${At(2)}`, kind: "calendar" }] : [], "genericTail"), dt = $.filter((i) => i.kind === "location"), ft = $.filter((i) => i.kind === "date").map((i) => i.value), x = [];
|
|
107
|
-
if (b === "location") {
|
|
108
|
-
for (const i of dt)
|
|
109
|
-
x.push({ key: `loc:${i.value}`, label: `📍 ${i.label}`, kind: "namedLocation", insert: i.value });
|
|
110
|
-
x.push(...rt());
|
|
111
|
-
} else {
|
|
112
|
-
for (const i of ft.length > 0 ? ft : xt)
|
|
113
|
-
x.push({ key: `date:${i}`, label: `📅 ${i}`, kind: "date", insert: i });
|
|
114
|
-
x.push(...rt());
|
|
115
|
-
}
|
|
116
|
-
const Z = P.current.suggest, Dt = b === "location" ? dt.length > 0 : !0;
|
|
117
|
-
if (b === "location" && !Dt && !Z) {
|
|
118
|
-
if (!g && o.locationExpected && o.locationPartialEmpty && o.locationCount < 2 && W && r.currentTriggerChar() !== "@") {
|
|
119
|
-
const i = s.selectionStart ?? t.length, S = t.slice(0, i), ot = S.length > 0 && !/\s$/.test(S);
|
|
120
|
-
if (!S.endsWith("@")) {
|
|
121
|
-
const I = ot ? " @" : "@";
|
|
122
|
-
n(null), r.setDraft(`${S}${I}${t.slice(i)}`), r.focusCaret(i + I.length), requestAnimationFrame(() => {
|
|
123
|
-
const G = r.getTextarea();
|
|
124
|
-
G && r.syncTrigger(G);
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
n(null);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
if (Z ? N.current === null && x.length > 0 && (p(0), f(!0), n(x)) : x.length > 0 ? (p(0), f(!0), n(x)) : n(null), Z) {
|
|
133
|
-
const i = t.slice(0, s.selectionStart ?? t.length), S = i.search(/[ \t\r\n](?=[^ \t\r\n]*$)/), ot = S === -1 ? i : i.slice(S + 1), I = b === "location" && o.locationPartial !== void 0 ? o.locationPartial : ot;
|
|
134
|
-
b === "location" && (at.current = I);
|
|
135
|
-
const G = b === "location" ? [...t.matchAll(/@\(([A-Za-z]{3})\)/g)].map((F) => F[1].toUpperCase()) : void 0, Ct = ++lt.current;
|
|
136
|
-
(T = X.current) == null || T.abort();
|
|
137
|
-
const gt = new AbortController();
|
|
138
|
-
X.current = gt;
|
|
139
|
-
try {
|
|
140
|
-
const F = await Z(I, b, gt.signal, G);
|
|
141
|
-
if (Ct !== lt.current) return;
|
|
142
|
-
const ht = r.getTextarea();
|
|
143
|
-
if (!ht || ht.value !== t || b === "location" && F.length === 0) return;
|
|
144
|
-
const E = [];
|
|
145
|
-
if (b === "location")
|
|
146
|
-
for (const w of F)
|
|
147
|
-
E.push({
|
|
148
|
-
key: `loc:${w.insert}`,
|
|
149
|
-
label: `📍 ${w.label}`,
|
|
150
|
-
kind: "namedLocation",
|
|
151
|
-
insert: w.insert,
|
|
152
|
-
hint: [w.iata, w.region, w.country].filter(Boolean).join(" · ") || void 0,
|
|
153
|
-
// parity with the `@` picker
|
|
154
|
-
disabled: w.disabled
|
|
155
|
-
// already in the prompt (same city) — greyed, not pickable
|
|
156
|
-
});
|
|
157
|
-
else
|
|
158
|
-
for (const w of F)
|
|
159
|
-
E.push({ key: `date:${w.insert}`, label: `📅 ${w.label}`, kind: "date", insert: w.insert });
|
|
160
|
-
if (E.push(...rt()), E.length === 0) {
|
|
161
|
-
n(null);
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const mt = E.findIndex((w) => !w.disabled);
|
|
165
|
-
p(mt < 0 ? 0 : mt), f(I.trim() === ""), n(E);
|
|
166
|
-
} catch {
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
} catch {
|
|
170
|
-
}
|
|
171
|
-
}, 200)), B.current != null && window.clearTimeout(B.current), B.current = window.setTimeout(() => {
|
|
172
|
-
nt();
|
|
173
|
-
}, 300);
|
|
174
|
-
}, [nt]), vt = A((t) => {
|
|
175
|
-
var g, y;
|
|
176
|
-
const e = t.trim();
|
|
177
|
-
e && ((y = (g = P.current).commitIntent) == null || y.call(g, e, tt.current));
|
|
178
|
-
}, []), kt = A((t) => {
|
|
179
|
-
if (!l || l.length === 0) return !1;
|
|
180
|
-
if (t.key === "ArrowDown")
|
|
181
|
-
return t.preventDefault(), p((e) => wt(l, e, 1)), !0;
|
|
182
|
-
if (t.key === "ArrowUp")
|
|
183
|
-
return t.preventDefault(), p((e) => wt(l, e, -1)), !0;
|
|
184
|
-
if (t.key === "Enter" || t.key === "Tab") {
|
|
185
|
-
t.preventDefault();
|
|
186
|
-
const e = l[D];
|
|
187
|
-
return e && !e.disabled && et(e), !0;
|
|
188
|
-
}
|
|
189
|
-
return t.key === "Escape" ? (t.preventDefault(), n(null), !0) : !1;
|
|
190
|
-
}, [l, D, et]);
|
|
191
|
-
return H(() => () => {
|
|
192
|
-
var t, e;
|
|
193
|
-
z.current != null && window.clearTimeout(z.current), B.current != null && window.clearTimeout(B.current), q.current != null && window.clearTimeout(q.current), (t = _.current) == null || t.abort(), (e = X.current) == null || e.abort();
|
|
194
|
-
}, []), {
|
|
195
|
-
predictions: l,
|
|
196
|
-
predictionsRecents: m,
|
|
197
|
-
predictionHighlight: D,
|
|
198
|
-
setPredictionHighlight: p,
|
|
199
|
-
applyPrediction: et,
|
|
200
|
-
clearPredictions: yt,
|
|
201
|
-
resolvedLocations: O,
|
|
202
|
-
resolvedDates: L,
|
|
203
|
-
forceTooltipText: $t,
|
|
204
|
-
scheduleAssist: Rt,
|
|
205
|
-
commit: vt,
|
|
206
|
-
onKeyDown: kt,
|
|
207
|
-
resetSession: bt
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
R(Lt, "usePromptAssist");
|
|
211
|
-
function qt(a, c) {
|
|
212
|
-
const h = u(a), [l, n] = v(null);
|
|
213
|
-
return H(() => {
|
|
214
|
-
h.current = a;
|
|
215
|
-
}, [a]), H(() => {
|
|
216
|
-
function m() {
|
|
217
|
-
h.current();
|
|
218
|
-
}
|
|
219
|
-
if (R(m, "tick"), c !== null) {
|
|
220
|
-
const f = setInterval(m, c);
|
|
221
|
-
return n(f), () => {
|
|
222
|
-
clearInterval(f);
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
}, [c]), l;
|
|
226
|
-
}
|
|
227
|
-
R(qt, "useInterval");
|
|
228
|
-
function zt(a, c, h = 0) {
|
|
229
|
-
const [l, n] = v(h);
|
|
230
|
-
return H(() => {
|
|
231
|
-
const m = a.current;
|
|
232
|
-
if (!m) return;
|
|
233
|
-
const f = new ResizeObserver((D) => {
|
|
234
|
-
const p = D[0];
|
|
235
|
-
p && n(p.contentRect.width);
|
|
236
|
-
});
|
|
237
|
-
return f.observe(m), n(m.getBoundingClientRect().width), () => f.disconnect();
|
|
238
|
-
}, [a, c]), l;
|
|
239
|
-
}
|
|
240
|
-
R(zt, "useContainerWidth");
|
|
241
|
-
function Bt(a, c, h = 0, l = 0) {
|
|
242
|
-
const [n, m] = v(h), [f, D] = v(l);
|
|
243
|
-
return H(() => {
|
|
244
|
-
const p = a.current;
|
|
245
|
-
if (!p) return;
|
|
246
|
-
const O = new ResizeObserver((K) => {
|
|
247
|
-
const L = K[0];
|
|
248
|
-
L && (D(L.contentRect.height), m(L.contentRect.width));
|
|
249
|
-
});
|
|
250
|
-
return O.observe(p), m(p.getBoundingClientRect().width), () => O.disconnect();
|
|
251
|
-
}, [a, c]), [n, f];
|
|
252
|
-
}
|
|
253
|
-
R(Bt, "useContainerRectangle");
|
|
254
|
-
export {
|
|
255
|
-
zt as a,
|
|
256
|
-
qt as b,
|
|
257
|
-
Lt as c,
|
|
258
|
-
Bt as u
|
|
259
|
-
};
|
|
260
|
-
//# sourceMappingURL=useContainerWidth-0EA-kdzl.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useContainerWidth-0EA-kdzl.js","sources":["../src/hooks/usePromptAssist.ts","../src/hooks/useIntervalHook.ts","../src/hooks/useContainerWidth.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState, type KeyboardEvent } from 'react';\nimport type { PromptAnalysis, PromptResolution, SuggestItem } from '../services/httpPromptAssistService';\n\n/** A dropdown item. `namedLocation` inserts `@Name` directly; `location`/`calendar` insert `@`/`#` and open the picker. */\nexport type PredictionItem = {\n key: string;\n label: string;\n kind: 'location' | 'namedLocation' | 'date' | 'calendar';\n insert?: string;\n /** Secondary line (e.g. \"GRU · SP · Brasil\") — parity with the `@` picker's hint. Optional. */\n hint?: string;\n /** Non-pickable (already in the prompt, same place/city) — rendered greyed and skipped by nav/apply. */\n disabled?: boolean;\n};\n\nexport type ResolvedDateItem = { text: string; display: string };\n\n/** The DOM operations the hook needs from its host composer — so the same logic drives PromptV2 and PromptComposer. */\nexport interface PromptAssistAdapter {\n getTextarea: () => HTMLTextAreaElement | null;\n /** Replace the draft value (host owns the React state). */\n setDraft: (next: string) => void;\n /** After a programmatic edit, focus the textarea and place the caret (host defers a frame if needed). */\n focusCaret: (pos: number) => void;\n /** Re-detect the `@`/`#` trigger at the caret and open the matching picker (host's existing flow). */\n syncTrigger: (ta: HTMLTextAreaElement) => void;\n /** Is a location/date picker already open? (suppresses the predictions dropdown / auto-`@`) */\n isPickerOpen: () => boolean;\n /** The trigger char of any open picker, or null — used to avoid re-inserting `@`. */\n currentTriggerChar: () => string | null;\n /** Whether the `@` location fetcher is wired (else no auto-`@` / generic \"Local…\"). */\n hasAtQuery: boolean;\n}\n\nexport interface PromptAssistFetchers {\n analyze?: (text: string, caret: number) => Promise<PromptAnalysis>;\n resolveDates?: (text: string, sessionId?: string, signal?: AbortSignal) => Promise<PromptResolution>;\n commitIntent?: (text: string, sessionId?: string) => void;\n suggest?: (q: string, kind: 'location' | 'date' | 'both', signal?: AbortSignal, exclude?: string[]) => Promise<SuggestItem[]>;\n}\n\nexport interface PromptAssistOptions {\n enableHashDatePicker?: boolean;\n datePresets?: string[];\n}\n\nconst newSessionId = () =>\n typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : `s-${Date.now()}-${Math.random()}`;\n\n/** Next selectable (non-disabled) index from `from` moving `dir` (±1), wrapping. Stays put if all are disabled. */\nconst nextEnabledIndex = (items: PredictionItem[], from: number, dir: 1 | -1): number => {\n const n = items.length;\n let idx = from;\n for (let step = 0; step < n; step++) {\n idx = (idx + dir + n) % n;\n if (!items[idx]?.disabled) return idx;\n }\n return from;\n};\n\n/** Today + n days, formatted DD/MM/YYYY — the default shown on the \"no dia #…\" date-picker suggestion. */\nconst plusDaysBR = (n: number) => {\n const d = new Date();\n d.setDate(d.getDate() + n);\n const dd = String(d.getDate()).padStart(2, '0');\n const mm = String(d.getMonth() + 1).padStart(2, '0');\n return `${dd}/${mm}/${d.getFullYear()}`;\n};\n\n/**\n * Headless prompt-assist logic shared by the chat composer (PromptV2) and the home composer (obtapp PromptComposer):\n * the analyze quick pass (auto-`@` + combined predictions dropdown), the resolve slow pass (date resolution +\n * mapped-location chips), commit-on-send learning, and keyboard nav — all with NO rendering/anchoring assumptions.\n * The host provides its DOM ops via {@link PromptAssistAdapter} and renders the returned `predictions` however it wants.\n */\nexport function usePromptAssist(\n adapter: PromptAssistAdapter,\n fetchers: PromptAssistFetchers,\n options: PromptAssistOptions = {},\n) {\n const [predictions, setPredictions] = useState<PredictionItem[] | null>(null);\n // True when the current predictions are the \"recents\" set (analyze pre-fill or an empty-query suggest) rather\n // than results for a typed query — lets the host label it \"recentes\" + hint that typing surfaces more.\n const [predictionsRecents, setPredictionsRecents] = useState(false);\n const [predictionHighlight, setPredictionHighlight] = useState(0);\n const [resolvedLocations, setResolvedLocations] = useState<string[]>([]);\n const [resolvedDates, setResolvedDates] = useState<ResolvedDateItem[]>([]);\n // The date text whose marker tooltip should auto-open (set on a NEW resolution, cleared after 2s) — identical\n // to PromptV2's behavior so both composers surface a freshly-resolved date the same way.\n const [forceTooltipText, setForceTooltipText] = useState('');\n const lastResolvedKeyRef = useRef('');\n const tooltipTimerRef = useRef<number | null>(null);\n\n // Latest adapter/fetchers/options via refs — the debounced callbacks must not capture stale closures.\n const adapterRef = useRef(adapter); adapterRef.current = adapter;\n const fetchersRef = useRef(fetchers); fetchersRef.current = fetchers;\n const optionsRef = useRef(options); optionsRef.current = options;\n\n const analyzeTimerRef = useRef<number | null>(null);\n const resolveTimerRef = useRef<number | null>(null);\n const analyzeSeqRef = useRef(0);\n const suggestSeqRef = useRef(0);\n const suggestAbortRef = useRef<AbortController | null>(null);\n const draftRef = useRef('');\n const lastResolveTextRef = useRef<string | null>(null);\n const resolveAbortRef = useRef<AbortController | null>(null);\n const sessionIdRef = useRef<string>(newSessionId());\n // Current predictions (mirror of state) so the debounced analyze can tell if the dropdown is already open —\n // lets us pre-fill only on FIRST open instead of re-flashing the tenant list on every keystroke.\n const predictionsRef = useRef<PredictionItem[] | null>(null);\n predictionsRef.current = predictions;\n // The kind the open dropdown is currently showing (null when closed) — lets a trailing space keep an open\n // location dropdown alive (as recents) instead of collapsing it.\n const lastKindRef = useRef<'location' | 'date' | null>(null);\n // The server-parsed location partial the open dropdown filtered on (\"belo\", \"São Paulo\", or \"\" for recents).\n // applyPrediction strips exactly this — including across a trailing space — so a pick REPLACES the partial\n // instead of appending after it, and never eats a completed \"@\" mention (empty partial → append).\n const locationPartialRef = useRef('');\n // Stable pointer to runResolve so applyPrediction (defined earlier) can force a resolve after a date pick.\n const runResolveRef = useRef<() => void>(() => {});\n\n const clearPredictions = useCallback(() => setPredictions(null), []);\n\n /** Call when the draft empties (send / reseed): clear mapped data and start a fresh learning session. */\n const resetSession = useCallback(() => {\n setResolvedLocations([]);\n setResolvedDates([]);\n setForceTooltipText('');\n lastResolvedKeyRef.current = '';\n lastResolveTextRef.current = null;\n sessionIdRef.current = newSessionId();\n }, []);\n\n const applyPrediction = useCallback((p: PredictionItem) => {\n if (p.disabled) return; // already in the prompt (same city) — not selectable; keep the dropdown open\n setPredictions(null);\n const ad = adapterRef.current;\n const ta = ad.getTextarea();\n if (!ta) return;\n const caret = ta.selectionStart ?? ta.value.length;\n const rawBefore = ta.value.slice(0, caret);\n const after = ta.value.slice(caret);\n // A pick must REPLACE what the dropdown filtered on, not append after it (\"sao @São Paulo\" bug).\n // LOCATIONS: strip exactly the server-parsed partial (locationPartialRef) — this spans a trailing space\n // (\"de belo \" → \"belo\") and is \"\" for a recents/mention pick, so we append instead of eating a finished\n // \"@\" mention. DATES: strip the trailing word as before.\n const isLocationPick = p.kind === 'namedLocation' || p.kind === 'location';\n let before: string;\n if (isLocationPick) {\n const partial = locationPartialRef.current;\n const trimmedEnd = rawBefore.replace(/\\s+$/, '');\n before = partial && trimmedEnd.endsWith(partial) ? trimmedEnd.slice(0, trimmedEnd.length - partial.length) : rawBefore;\n } else {\n const wordStart = rawBefore.search(/\\S+$/);\n before = wordStart === -1 ? rawBefore : rawBefore.slice(0, wordStart);\n }\n const needsSpace = before.length > 0 && !/\\s$/.test(before);\n\n if (p.kind === 'date') {\n const ins = `${needsSpace ? ' ' : ''}${p.insert} `;\n const next = `${before}${ins}${after}`;\n ad.setDraft(next);\n ad.focusCaret(before.length + ins.length);\n // A programmatic setDraft doesn't fire onChange, so force a resolve now → the picked date resolves\n // into its chip/marker immediately instead of waiting for the next keystroke.\n draftRef.current = next;\n lastResolveTextRef.current = null;\n runResolveRef.current();\n return;\n }\n if (p.kind === 'namedLocation' && p.insert) {\n // A specific place → finished \"@\" mention (NBSP-joined so a multi-word name stays one chip / one mention).\n const mention = `@${p.insert.replace(/ /g, String.fromCharCode(0xA0))}`;\n const ins = `${needsSpace ? ' ' : ''}${mention} `;\n ad.setDraft(`${before}${ins}${after}`);\n ad.focusCaret(before.length + ins.length);\n return;\n }\n // Generic location / calendar → insert the trigger char and open the host's picker.\n const chr = p.kind === 'location' ? '@' : '#';\n const ins = `${needsSpace ? ' ' : ''}${chr}`;\n ad.setDraft(`${before}${ins}${after}`);\n ad.focusCaret(before.length + ins.length);\n requestAnimationFrame(() => { const t = ad.getTextarea(); if (t) ad.syncTrigger(t); });\n }, []);\n\n const runResolve = useCallback(async () => {\n const resolve = fetchersRef.current.resolveDates;\n if (!resolve) return;\n const text = draftRef.current;\n if (text.trim() === '') { lastResolveTextRef.current = null; return; }\n if (text === lastResolveTextRef.current) return; // unchanged since last call\n lastResolveTextRef.current = text;\n resolveAbortRef.current?.abort();\n const ac = new AbortController();\n resolveAbortRef.current = ac;\n try {\n const { dates, locations } = await resolve(text, sessionIdRef.current, ac.signal);\n if (draftRef.current !== text) return; // moved on while in flight\n const resolved = dates.filter((d) => d.display).map((d) => ({ text: d.text, display: d.display }));\n setResolvedDates(resolved);\n setResolvedLocations(locations.map((l) => l.text).filter((t) => t.trim().length > 0));\n // Auto-open the newest date's tooltip for 2s (only when the resolution set actually changed).\n const key = resolved.map((r) => `${r.text}=${r.display}`).join('|');\n if (resolved.length > 0 && key !== lastResolvedKeyRef.current) {\n lastResolvedKeyRef.current = key;\n setForceTooltipText(resolved[resolved.length - 1].text);\n if (tooltipTimerRef.current != null) window.clearTimeout(tooltipTimerRef.current);\n tooltipTimerRef.current = window.setTimeout(() => setForceTooltipText(''), 2000);\n }\n if (resolved.length === 0) lastResolvedKeyRef.current = '';\n } catch { /* ignore — includes AbortError from a superseded call */ }\n }, []);\n runResolveRef.current = runResolve;\n\n /** Call from the textarea's onChange. Runs the debounced analyze (200ms) + resolve (300ms) passes. */\n const scheduleAssist = useCallback((value: string, caret: number, isDeletion: boolean) => {\n draftRef.current = value;\n const analyze = fetchersRef.current.analyze;\n // Run analyze on typing, AND on deletion WHILE the dropdown is open — so backspacing re-filters the list\n // (shorter query) and closes it once the context ends. When nothing's open, deletion still skips analyze\n // (no auto-'@' / churn while correcting text elsewhere).\n if (analyze && (!isDeletion || predictionsRef.current !== null)) {\n if (analyzeTimerRef.current != null) window.clearTimeout(analyzeTimerRef.current);\n analyzeTimerRef.current = window.setTimeout(async () => {\n const seq = ++analyzeSeqRef.current;\n try {\n const a = await analyze(value, caret);\n if (seq !== analyzeSeqRef.current) return;\n const ad = adapterRef.current;\n const live = ad.getTextarea();\n if (!live || live.value !== value) return;\n\n const caretEnd = (live.selectionStart ?? caret) === value.length;\n const canLoc = ad.hasAtQuery;\n const pickerOpen = ad.isPickerOpen();\n const named = a.suggestions ?? [];\n const { enableHashDatePicker = false, datePresets = ['amanhã de manhã', 'quarta-feira à noite'] } = optionsRef.current;\n\n // Single-winner dropdown kind: prefer a.category, else fall back to the (at-most-one) expected flags.\n let decided: 'location' | 'date' | null =\n a.category === 'location' ? 'location'\n : a.category === 'date' ? 'date'\n : a.locationExpected ? 'location'\n : a.dateExpected ? 'date'\n : null;\n // Grace: a bare trailing space shouldn't collapse — OR flip to dates — an already-open location\n // dropdown. After the space the server may report \"done\" (null) OR predict a date (a learned\n // \"de [loc] \" → date template), but the user just hit space and is likely still on the location —\n // keep it open as the LOCATION recents list (empty query → suggest returns recents). Overrides\n // null AND date. Only when it was a location dropdown, suggest is wired, the caret's at the end,\n // and the text ends in a space. Typing an actual date WORD (no trailing space) still switches.\n // Not when 2 locations are already present — then the natural next slot is a DATE, so let it through.\n if (decided !== 'location' && a.locationCount < 2 && Boolean(fetchersRef.current.suggest)\n && predictionsRef.current !== null && lastKindRef.current === 'location' && caretEnd && /\\s$/.test(value)) {\n decided = 'location';\n }\n\n // 2-location safeguard: with origin + destination already present, a merely PREDICTED (not-being-\n // typed) 3rd location — typically just the model guessing — shouldn't open a dropdown. Actively\n // typing a 3rd location (partial non-empty) still shows.\n if (decided === 'location' && a.locationCount >= 2 && a.locationPartialEmpty) {\n setPredictions(null); lastKindRef.current = null; return;\n }\n\n // A location dropdown needs the `@` fetcher wired to be useful.\n const kindActive = decided === 'location' ? canLoc : decided === 'date';\n\n // Gating: caret at end, no picker open.\n if (decided === null || !(caretEnd && !pickerOpen && kindActive)) { setPredictions(null); lastKindRef.current = null; return; }\n const kind: 'location' | 'date' = decided;\n lastKindRef.current = kind;\n\n // Generic affordances appended after the named items. The location \"Local…\" entry is gone —\n // free-form typing now searches directly, so it's redundant. The date picker entry stays.\n const genericTail = (): PredictionItem[] =>\n kind === 'date' && enableHashDatePicker\n ? [{ key: 'cal', label: `📅 no dia #${plusDaysBR(2)}`, kind: 'calendar' } as PredictionItem]\n : [];\n\n const namedLocs = named.filter((s) => s.kind === 'location');\n const namedDates = named.filter((s) => s.kind === 'date').map((s) => s.value);\n\n // Pre-fill immediately (no await) from analyze's suggestions so the user sees something instantly.\n const prefill: PredictionItem[] = [];\n if (kind === 'location') {\n for (const s of namedLocs)\n prefill.push({ key: `loc:${s.value}`, label: `📍 ${s.label}`, kind: 'namedLocation', insert: s.value });\n prefill.push(...genericTail());\n } else {\n for (const d of (namedDates.length > 0 ? namedDates : datePresets))\n prefill.push({ key: `date:${d}`, label: `📅 ${d}`, kind: 'date', insert: d });\n prefill.push(...genericTail());\n }\n\n const suggest = fetchersRef.current.suggest;\n const hasNamed = kind === 'location' ? namedLocs.length > 0 : true;\n\n // If the dropdown would be empty AND there's no suggest fetcher to fill it, fall back to auto-'@'.\n if (kind === 'location' && !hasNamed && !suggest) {\n if (!isDeletion && a.locationExpected && a.locationPartialEmpty && a.locationCount < 2\n && canLoc && ad.currentTriggerChar() !== '@') {\n const c = live.selectionStart ?? value.length;\n const before = value.slice(0, c);\n const needsSpace = before.length > 0 && !/\\s$/.test(before);\n if (!before.endsWith('@')) {\n const insert = needsSpace ? ' @' : '@';\n setPredictions(null);\n ad.setDraft(`${before}${insert}${value.slice(c)}`);\n ad.focusCaret(c + insert.length);\n requestAnimationFrame(() => { const t = ad.getTextarea(); if (t) ad.syncTrigger(t); });\n }\n return;\n }\n setPredictions(null);\n return;\n }\n\n // Show the pre-filled list. With a suggest fetcher wired, only pre-fill on FIRST open (when the\n // dropdown was closed) — re-setting it every keystroke re-flashes the tenant list under the\n // incoming search results. Once open, keep the current list and let suggest refine it below.\n // Without a suggest fetcher, the pre-fill IS the content, so keep updating it each keystroke.\n if (!suggest) {\n if (prefill.length > 0) { setPredictionHighlight(0); setPredictionsRecents(true); setPredictions(prefill); }\n else setPredictions(null);\n } else if (predictionsRef.current === null && prefill.length > 0) {\n setPredictionHighlight(0);\n setPredictionsRecents(true); // pre-fill = the user's history = recents\n setPredictions(prefill);\n }\n\n // Then refine via the host-provided unified suggest source (search-as-you-type).\n if (suggest) {\n // Query = what the user is typing for the current slot. For LOCATIONS the server owns the\n // parse (a.locationPartial: \"@\"-mentions stripped, so \"@São Paulo \" → \"\" → recents and\n // \"de belo \" → \"belo\" → filter) — no client-side whitespace guessing, which can't tell a\n // partial from a cue or a finished mention. Falls back to the trailing word for dates, or if\n // an older server didn't send the field.\n const beforeCaret = value.slice(0, live.selectionStart ?? value.length);\n const wsIdx = beforeCaret.search(/[ \\t\\r\\n](?=[^ \\t\\r\\n]*$)/);\n const trailingWord = wsIdx === -1 ? beforeCaret : beforeCaret.slice(wsIdx + 1);\n const q = kind === 'location' && a.locationPartial !== undefined ? a.locationPartial : trailingWord;\n // Remember what a location pick should replace (server partial, or the trailing word fallback).\n if (kind === 'location') locationPartialRef.current = q;\n\n // Locations already picked in the prompt (the \"@(IATA) …\" mentions) — the suggest source\n // drops them AND anything in the same city, so it never offers an impossible SAO→SAO / GRU→CGH.\n const exclude = kind === 'location'\n ? [...value.matchAll(/@\\(([A-Za-z]{3})\\)/g)].map((m) => m[1].toUpperCase())\n : undefined;\n\n const sseq = ++suggestSeqRef.current;\n suggestAbortRef.current?.abort();\n const ac = new AbortController();\n suggestAbortRef.current = ac;\n try {\n const items = await suggest(q, kind, ac.signal, exclude);\n if (sseq !== suggestSeqRef.current) return; // overtaken\n const live2 = ad.getTextarea();\n if (!live2 || live2.value !== value) return; // text changed while in flight\n // Keep the useful pre-filled list on an empty result — the \"user is ignoring the dropdown\"\n // case is handled by the server's word cap (partial > 3 plain words → not a location).\n if (kind === 'location' && items.length === 0) return;\n\n const refined: PredictionItem[] = [];\n if (kind === 'location') {\n for (const it of items)\n refined.push({\n key: `loc:${it.insert}`, label: `📍 ${it.label}`, kind: 'namedLocation', insert: it.insert,\n hint: [it.iata, it.region, it.country].filter(Boolean).join(' · ') || undefined, // parity with the `@` picker\n disabled: it.disabled, // already in the prompt (same city) — greyed, not pickable\n });\n } else {\n for (const it of items)\n refined.push({ key: `date:${it.insert}`, label: `📅 ${it.label}`, kind: 'date', insert: it.insert });\n }\n refined.push(...genericTail());\n if (refined.length === 0) { setPredictions(null); return; } // nothing to show\n const firstEnabled = refined.findIndex((p) => !p.disabled); // don't land the highlight on a disabled item\n setPredictionHighlight(firstEnabled < 0 ? 0 : firstEnabled);\n setPredictionsRecents(q.trim() === ''); // empty query → recents; typed query → search results\n setPredictions(refined);\n } catch { /* ignore — includes AbortError from a superseded call */ }\n }\n } catch { /* transient — ignore */ }\n }, 200);\n }\n\n if (resolveTimerRef.current != null) window.clearTimeout(resolveTimerRef.current);\n resolveTimerRef.current = window.setTimeout(() => { void runResolve(); }, 300);\n }, [runResolve]);\n\n /** Call on send with the FINAL text (NBSP-preserving) so the server learns the committed intent. */\n const commit = useCallback((finalText: string) => {\n const t = finalText.trim();\n if (t) fetchersRef.current.commitIntent?.(t, sessionIdRef.current);\n }, []);\n\n /** Wire to the textarea's onKeyDown; returns true if it handled the key (host should then stop). */\n const onKeyDown = useCallback((e: KeyboardEvent<HTMLTextAreaElement>): boolean => {\n if (!predictions || predictions.length === 0) return false;\n if (e.key === 'ArrowDown') { e.preventDefault(); setPredictionHighlight((i) => nextEnabledIndex(predictions, i, 1)); return true; }\n if (e.key === 'ArrowUp') { e.preventDefault(); setPredictionHighlight((i) => nextEnabledIndex(predictions, i, -1)); return true; }\n if (e.key === 'Enter' || e.key === 'Tab') { e.preventDefault(); const it = predictions[predictionHighlight]; if (it && !it.disabled) applyPrediction(it); return true; }\n if (e.key === 'Escape') { e.preventDefault(); setPredictions(null); return true; }\n return false;\n }, [predictions, predictionHighlight, applyPrediction]);\n\n useEffect(() => () => {\n if (analyzeTimerRef.current != null) window.clearTimeout(analyzeTimerRef.current);\n if (resolveTimerRef.current != null) window.clearTimeout(resolveTimerRef.current);\n if (tooltipTimerRef.current != null) window.clearTimeout(tooltipTimerRef.current);\n resolveAbortRef.current?.abort();\n suggestAbortRef.current?.abort();\n }, []);\n\n return {\n predictions, predictionsRecents, predictionHighlight, setPredictionHighlight,\n applyPrediction, clearPredictions,\n resolvedLocations, resolvedDates, forceTooltipText,\n scheduleAssist, commit, onKeyDown, resetSession,\n };\n}\n","import { useEffect, useRef, useState } from \"react\";\n\n// Custom useInterval hook\nfunction useInterval(callback: () => void, delay: number) {\n const savedCallback = useRef(callback);\n const [intervalId, setIntervalId] = useState<NodeJS.Timeout | null>(null)\n\n // Remember the latest callback.\n useEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n // Set up the interval.\n useEffect(() => {\n function tick() {\n savedCallback.current();\n }\n if (delay !== null) {\n const id = setInterval(tick, delay);\n setIntervalId(id)\n return () => {\n\n clearInterval(id); // Cleanup function\n }\n }\n }, [delay]);\n\n return intervalId;\n}\n\nexport default useInterval","import { useState, useEffect } from \"react\";\n\nexport function useContainerWidth(ref: React.RefObject<HTMLElement | null>, renderId: string, initialWidth = 0) {\n const [width, setWidth] = useState(initialWidth);\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry) setWidth(entry.contentRect.width);\n });\n\n observer.observe(el);\n setWidth(el.getBoundingClientRect().width);\n\n return () => observer.disconnect();\n }, [ref, renderId]);\n\n return width;\n}\n\nexport function useContainerRectangle(ref: React.RefObject<HTMLElement | null>, renderId: string, initialWidth = 0, initialHeight = 0) {\n const [width, setWidth] = useState(initialWidth);\n const [height, setHeight] = useState(initialHeight);\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry) {\n setHeight(entry.contentRect.height);\n setWidth(entry.contentRect.width);\n }\n });\n\n observer.observe(el);\n setWidth(el.getBoundingClientRect().width);\n\n return () => observer.disconnect();\n }, [ref, renderId]);\n\n return [width, height];\n}"],"names":["newSessionId","__name","nextEnabledIndex","items","from","dir","n","idx","step","_a","plusDaysBR","d","dd","mm","usePromptAssist","adapter","fetchers","options","predictions","setPredictions","useState","predictionsRecents","setPredictionsRecents","predictionHighlight","setPredictionHighlight","resolvedLocations","setResolvedLocations","resolvedDates","setResolvedDates","forceTooltipText","setForceTooltipText","lastResolvedKeyRef","useRef","tooltipTimerRef","adapterRef","fetchersRef","optionsRef","analyzeTimerRef","resolveTimerRef","analyzeSeqRef","suggestSeqRef","suggestAbortRef","draftRef","lastResolveTextRef","resolveAbortRef","sessionIdRef","predictionsRef","lastKindRef","locationPartialRef","runResolveRef","clearPredictions","useCallback","resetSession","applyPrediction","p","ad","ta","caret","rawBefore","after","isLocationPick","before","partial","trimmedEnd","wordStart","needsSpace","ins","next","mention","chr","t","runResolve","resolve","text","ac","dates","locations","resolved","l","key","r","scheduleAssist","value","isDeletion","analyze","seq","a","live","caretEnd","canLoc","pickerOpen","named","enableHashDatePicker","datePresets","decided","kind","genericTail","namedLocs","s","namedDates","prefill","suggest","hasNamed","c","insert","beforeCaret","wsIdx","trailingWord","q","exclude","m","sseq","live2","refined","it","firstEnabled","commit","finalText","_b","onKeyDown","e","i","useEffect","useInterval","callback","delay","savedCallback","intervalId","setIntervalId","tick","id","useContainerWidth","ref","renderId","initialWidth","width","setWidth","el","observer","entries","entry","useContainerRectangle","initialHeight","height","setHeight"],"mappings":"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"}
|