@aintela/chat 0.2.28 → 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 +3030 -2993
- 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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useContainerWidth-D0CQQqZ2.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 // Issue #112 — the latest analyze's person-intent signal (P the user is referring to a PERSON/passenger). Hosts\n // use this to order/section the `@` picker's sources (people vs places). Updated on every analyze; 0 when the\n // feature is off server-side or the text is empty.\n const [personConfidence, setPersonConfidence] = useState(0);\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 // Person-intent (issue #112) — surfaced regardless of the loc/date dropdown decision below, so the\n // host's `@` picker can consult it whether or not a predictions dropdown is currently open.\n setPersonConfidence(a.personConfidence ?? 0);\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 personConfidence,\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","personConfidence","setPersonConfidence","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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"}
|
package/dist/utils.js
CHANGED
|
@@ -1,51 +1,53 @@
|
|
|
1
|
-
import { A as e, D as t, l as r, n as i, o, q as n, r as c, s as d, t as
|
|
2
|
-
import { A as g, a as U, b as E, G as
|
|
3
|
-
import { S as
|
|
1
|
+
import { A as e, D as t, l as r, n as i, o, q as n, r as c, s as d, t as A, u as l } from "./environmentUtils-CUVZ6Dq1.js";
|
|
2
|
+
import { A as g, a as U, b as E, G as S, d as p, c as m, e as B, f as L, g as f, h, i as v, j as N, k as D, l as _, m as C, n as b, o as x, p as O, q as G, r as V, s as k, t as F, u as T, v as u } from "./auth-BN22f1HF.js";
|
|
3
|
+
import { S as R, c as W, a as y, e as q, b as H, f as P, i as j, d as w, p as z, g as J, s as K, k as Y, t as Q } from "./atMentions-DqhG_vde.js";
|
|
4
4
|
export {
|
|
5
5
|
g as ALLOWED_DOMAINS,
|
|
6
6
|
U as ALLOWED_EMAILS,
|
|
7
7
|
e as ANALYTICS_AGENT_NAME,
|
|
8
8
|
E as AUTH_CONFIG,
|
|
9
9
|
t as DEV_SERVER_CONFIG,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
S as GOOGLE_CLIENT_ID,
|
|
11
|
+
R as SortableTable,
|
|
12
|
+
W as chipLocations,
|
|
13
|
+
y as chunkArray,
|
|
14
|
+
p as dateReviver,
|
|
15
|
+
m as decodeBase64,
|
|
16
16
|
B as decodeUri,
|
|
17
17
|
L as decodeUriFromPython,
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
f as encodeBase64,
|
|
19
|
+
h as encodeUri,
|
|
20
20
|
q as extractInteractionId,
|
|
21
21
|
H as extractLinkAction,
|
|
22
|
-
|
|
22
|
+
P as fetchAtMentions,
|
|
23
|
+
v as getAgentBaseUrl,
|
|
23
24
|
r as getAgentServerBaseUrl,
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
N as getArtifactsBaseUrl,
|
|
26
|
+
D as getDotNetBaseUrl,
|
|
26
27
|
i as getEnvVar,
|
|
27
28
|
o as getEnvironmentInfo,
|
|
28
|
-
|
|
29
|
+
_ as getIconByName,
|
|
29
30
|
n as getRandomUUID,
|
|
30
31
|
c as getServerBaseUrl,
|
|
31
32
|
d as getServerClientBaseUrl,
|
|
32
33
|
C as iconCategories,
|
|
33
34
|
b as isBase64Encoded,
|
|
34
|
-
|
|
35
|
+
j as isSectionStart,
|
|
36
|
+
A as isServer,
|
|
35
37
|
x as isUriEncoded,
|
|
36
|
-
|
|
38
|
+
w as isValidInteractionId,
|
|
37
39
|
O as isValidUri,
|
|
38
40
|
G as materialIcons,
|
|
39
|
-
|
|
41
|
+
z as parseAndValidateArtifactUrl,
|
|
40
42
|
V as parseArtifactFromJson,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
J as parseKnownNumbers,
|
|
44
|
+
k as parseUriParams,
|
|
45
|
+
l as resolveApiUrl,
|
|
46
|
+
F as searchIcons,
|
|
47
|
+
T as setEbiContextData,
|
|
46
48
|
u as setEbiContextSessionId,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
K as splitBigLinesWithSpaces,
|
|
50
|
+
Y as startsWithInteractionId,
|
|
51
|
+
Q as tokenizeForHighlight
|
|
50
52
|
};
|
|
51
53
|
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"promptHighlight-BHSQkdFs.js","sources":["../src/utils/urlParser.ts","../src/utils/stringUtils.ts","../src/utils/interactionIdChecker.ts","../src/utils/sortable-table.js","../src/utils/promptHighlight.ts"],"sourcesContent":["export const parseAndValidateArtifactUrl = (url: string): string | null => {\n if (url[0] == \"#\")\n return null;\n\n const urlParts = url.split(\"/\");\n let lastPart = urlParts[urlParts.length - 1];\n if (lastPart == \"\" && urlParts.length > 1)\n lastPart = urlParts[urlParts.length - 2];\n if (lastPart == \"\")\n return null;\n\n const removedUrlParams = lastPart.split(\"?\")[0];\n const removedUrlHash = removedUrlParams.startsWith(\"#\") ? removedUrlParams : removedUrlParams.split(\"#\")[0];\n const stripExtension = removedUrlHash;\n return stripExtension;\n}\n\n/*\nlink can be:\n#openartifact:qual-é-o-valor-total-de-tarifas-em-maio?\n#openartifact:e97c89936040425cba07d42a4e89c2bb_valor_medio_por_num_passageiros.png\n#openartifact:http://localhost:8000/static/artifacts/e97c89936040425cba07d42a4e89c2bb_valor_medio_por_num_passageiros.png\n\ncontent can be:\nQual é o valor total de tarifas em maio?\n*/\n// export const extractLinkAction = (link: string, content: string | null): { artifactId: string | null, question: string | null } => {\n\n// const parts = link.split(\"-\");\n// if (parts[0] && parts[0] == \"#openartifact\") {\n// const artifactId = decodeURIComponent(parts.slice(1).join(\"-\"));\n// if (artifactId == \"\") {\n// return { artifactId: null, question: null };\n// }\n// else {\n// return { artifactId: artifactId, question: null };\n// }\n// }\n// else if (link[0] !== \"#\") {\n// return { artifactId: null, question: null };\n// }\n// else {\n// if (!content) {\n// const extractedArtifactId = parseAndValidateArtifactUrl(link);\n// if (extractedArtifactId) {\n// return { artifactId: extractedArtifactId, question: null };\n// }\n// else if (isValidUri(link)) { //to not transform a mal formed full URL into a question\n// return { artifactId: null, question: null };\n// }\n// }\n// }\n// content = content == \"\" ? null : content;\n// if (link || content) {\n// return { artifactId: null, question: content ?? link };\n// }\n// else {\n// console.warn(\"Unknown link format: \", link, content);\n// return { artifactId: null, question: null };\n// }\n// }\n\nexport type LinkAction = 'Export' | 'Question' | 'OpenDashboard' | 'URL'\n\nexport const extractLinkAction = (link: string, sessionId: string, content: string | null): { action: LinkAction, url: string | null, question: string | null, parameter: string | null } => {\n let action: LinkAction = 'URL';\n let question: string | null = null;\n let url: string | null = null;\n let parameter: string | null = null;\n if (link[0] == '#') {\n const firstDash = link.indexOf(\"-\");\n const firstPart = link.slice(1, firstDash);\n parameter = link.slice(firstDash + 1);\n switch (firstPart.toLowerCase()) {\n case \"opendashboard\":\n action = 'OpenDashboard'\n break;\n case \"ask\":\n action = 'Question'\n question = content\n break;\n }\n }\n else {\n if (link.indexOf(\"http\") > -1) {\n action = 'URL'\n url = link\n }\n else {\n link = link.replaceAll(\"exported/\", `exported/${sessionId}/`)\n action = 'Export'\n }\n }\n\n return { action, url, question, parameter }\n}","export const chunkArray = (char: string[], size: number): string[][] =>\n Array.from({ length: Math.ceil(char.length / size) }, (_v, i) =>\n char.slice(i * size, i * size + size)\n );\n\nexport const splitBigLinesWithSpaces = (content: string): string => {\n // If content already contains newlines or is short, return as-is\n content = content.replaceAll(\"\\\\n\", \"\\n\");\n\n const limit = 90;\n\n const whiteSpaceBreak = content.split(\" \");\n const allWords: string[] = []\n let hadOne = false;\n for (const word of whiteSpaceBreak) {\n if (word.length > limit) {\n hadOne = true;\n const charArray = [...word];\n const chunkedText = chunkArray(charArray, limit);\n const chunkedWord = chunkedText.map(chunk => chunk.join(\"\")).join(\"\\n\");\n allWords.push(chunkedWord);\n }\n else {\n allWords.push(word);\n }\n }\n\n return hadOne ? allWords.join(\" \") : content;\n}\n\nexport function parseRawNumber(text: string): number {\n let number = parseFloat(text);\n if (!isNaN(number)) {\n text = text.replaceAll(/[,\\.]/g, '');\n return parseInt(text);\n }\n\n var finalNumber = \"\"\n for (const char of text) {\n if (char.match(/[0-9]/)) {\n finalNumber += char;\n }\n }\n\n const ratio = finalNumber.length / text.length;\n number = parseInt(finalNumber);\n if (!isNaN(number) && ratio > 0.5) {\n return number;\n }\n\n return NaN;\n}\n\nexport function parseKnownNumbers(text?: string): { prefix?: string, suffix?: string, number?: number } {\n if (!text) return { prefix: undefined, suffix: undefined, number: undefined };\n\n const knownChars = /[$%(\\w?\\$)]/gi;\n const currencySymbol = /[a-z]?\\$/gi;\n\n let prefix = \"\";\n let suffix = \"\";\n\n if (text.match(knownChars)) {\n if (text.indexOf(\"%\") > -1) {\n suffix = \" %\"\n }\n const match = text.match(currencySymbol)\n if (match) {\n prefix = match[0] + \" \";\n }\n }\n\n let number = parseFloat(text);\n\n if (!isNaN(number)) {\n text = text.replaceAll(\".\", '').replaceAll(\",\", \".\");\n return { prefix, suffix, number: parseFloat(text) };\n }\n\n var finalNumber = \"\"\n for (const char of text) {\n if (char.match(/[0-9.,]/)) {\n let replacedChar = char;\n if (replacedChar == '.')\n replacedChar = \"\"\n else if (replacedChar == \",\")\n replacedChar = \".\"\n finalNumber += replacedChar;\n }\n }\n\n number = parseFloat(finalNumber);\n if (!isNaN(number)) {\n return { prefix, suffix, number: number };\n }\n\n return { prefix: undefined, suffix: undefined, number: undefined };;\n}","/**\n * Utility function to check if a string starts with an interaction ID (UUID)\n * Supports both formats:\n * - With dashes: ebd067ef-0dbd-49b3-8eff-c54b2a9ff314\n * - Without dashes: 62ec037ae42c439192c64dd112136583\n */\n\n/**\n * Regular expression for UUID with dashes (standard format)\n * Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n */\nconst UUID_WITH_DASHES_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;\n\n/**\n * Regular expression for UUID without dashes (compact format)\n * Format: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (32 hex characters)\n */\nconst UUID_WITHOUT_DASHES_REGEX = /^[0-9a-f]{32}/i;\n\n/**\n * Check if a string starts with an interaction ID (UUID)\n * @param str - The string to check\n * @returns true if the string starts with a valid UUID, false otherwise\n */\nexport function startsWithInteractionId(str: string): boolean {\n if (!str || typeof str !== 'string') {\n return false;\n }\n\n const interactionId = extractInteractionId(str);\n\n return interactionId === null ? false : str.startsWith(interactionId);\n}\n\n/**\n * Extract the interaction ID from the beginning of a string\n * @param str - The string to extract from\n * @returns The interaction ID if found, null otherwise\n */\nexport function extractInteractionId(str: string): string | null {\n if (!str || typeof str !== 'string') {\n return null;\n }\n\n // Try to match UUID with dashes first\n const withDashesMatch = str.match(UUID_WITH_DASHES_REGEX);\n if (withDashesMatch) {\n return withDashesMatch[0];\n }\n\n // Try to match UUID without dashes\n const withoutDashesMatch = str.match(UUID_WITHOUT_DASHES_REGEX);\n if (withoutDashesMatch) {\n return withoutDashesMatch[0];\n }\n\n return null;\n}\n\nexport function prettiffyFileName(fileName: string) {\n const prettyName = fileName.replaceAll(\"_\", \" \").replaceAll(\"-\", \" \");\n const userRemoved = prettyName.replaceAll(\"user:\", \"\");\n const withNoExtension = userRemoved.replace(/\\.[^/.]+$/, \"\");\n const withNoInteractionId = extractNameFromStringWithInteractionId(withNoExtension).trim();\n if (withNoInteractionId.length > 1)\n return withNoInteractionId[0].toUpperCase() + withNoInteractionId.slice(1);\n else\n return withNoInteractionId;\n}\n\nexport function prettiffyPythonFunctionName(functionName: string) {\n if (functionName.length == 0)\n return functionName;\n\n const prettyName = functionName.replaceAll(\"_\", \" \").replaceAll(\"-\", \" \");\n const withFirstCapitalLetter = prettyName[0].toUpperCase() + prettyName.slice(1);\n\n return withFirstCapitalLetter;\n}\n\nexport function extractNameFromStringWithInteractionId(str: string): string {\n // Try to match UUID with dashes first and remove it\n const withDashesMatch = str.match(UUID_WITH_DASHES_REGEX);\n if (withDashesMatch) {\n return str.replace(withDashesMatch[0], \"\");\n }\n\n // Try to match UUID without dashes\n const withoutDashesMatch = str.match(UUID_WITHOUT_DASHES_REGEX);\n if (withoutDashesMatch) {\n return str.replace(withoutDashesMatch[0], \"\");\n }\n\n return str;\n}\n\n/**\n * Check if a string is a valid interaction ID (UUID) on its own\n * @param str - The string to check\n * @returns true if the string is a valid UUID, false otherwise\n */\nexport function isValidInteractionId(str: string): boolean {\n if (!str || typeof str !== 'string') {\n return false;\n }\n\n // Check if it's exactly a UUID with dashes\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(str)) {\n return true;\n }\n\n // Check if it's exactly a UUID without dashes\n if (/^[0-9a-f]{32}$/i.test(str)) {\n return true;\n }\n\n return false;\n}\n","/**\n * SortableTable - A pure JavaScript library for making tables sortable\n * \n * Features:\n * - Automatically scans document for tables\n * - Supports tables with or without thead elements (converts first row to header if needed)\n * - Adds Material UI icons to column headers\n * - Supports text, number, and date sorting\n * - Visual feedback for sort direction\n * - Preserves existing table styling\n */\n\nconst initializedTables = new Set(); // Track which tables have been initialized\n\nimport { parseRawNumber } from './stringUtils';\n\nclass SortableTable {\n constructor(options = {}) {\n this.options = {\n // CSS class for sortable headers\n sortableClass: 'sortable-header',\n // CSS class for active sort\n activeSortClass: 'active-sort',\n // CSS class for ascending sort\n ascendingClass: 'sort-asc',\n // CSS class for descending sort\n descendingClass: 'sort-desc',\n // Icon for unsorted state\n unsortedIcon: 'unfold_more',\n // Icon for ascending sort\n ascendingIcon: 'keyboard_arrow_up',\n // Icon for descending sort\n descendingIcon: 'keyboard_arrow_down',\n // Whether to sort on first click (true) or cycle through states (false)\n sortOnFirstClick: true,\n // Custom sort functions for specific columns\n customSorters: {},\n // Columns to exclude from sorting (0-based index)\n excludeColumns: [],\n // Whether to preserve existing icons in headers\n preserveExistingIcons: false,\n // Enable column resizing\n enableResizing: true,\n // Enable column reordering\n enableReordering: true,\n // CSS class for resizable columns\n resizableClass: 'resizable-column',\n // CSS class for draggable columns\n draggableClass: 'draggable-column',\n // CSS class for drag placeholder\n dragPlaceholderClass: 'drag-placeholder',\n // CSS class for drag over state\n dragOverClass: 'drag-over',\n theme: {\n palette: {\n primary: {\n main: '#999',\n },\n background: {\n default: '#fff',\n paper: '#555',\n },\n text: {\n primary: \"#000\",\n secondary: \"#999\",\n disabled: \"#BBB\",\n },\n surface: {\n panel: \"#999\",\n raised: \"#999\",\n hover: \"#444\",\n },\n divider: \"#999\",\n border: {\n default: \"#999\",\n soft: \"#BBB\",\n },\n },\n shape: {\n borderRadius: 7,\n radiusSm: 1,\n radiusLg: 10,\n },\n },\n ...options\n };\n\n this.tables = [];\n this.sortStates = new Map(); // Track sort state for each table\n this.originalColumnOrder = new Map(); // Track original column order\n this.isDragging = false;\n this.dragSource = null;\n this.dragTarget = null;\n this.charWidth = 0;\n }\n\n /**\n * Initialize the library - scan document for tables and make them sortable\n * @param {HTMLElement} container - Optional container element to limit search scope\n */\n init(container = null) {\n if (this.charWidth == 0)\n this.charWidth = this.getCharWidth(this.options.theme.typography.fontFamily, this.options.theme.typography.fontMono)\n\n this.scanTables(container);\n this.makeTablesSortable();\n this.addStyles();\n }\n\n /**\n * Scan for tables in the document or within a specific container\n * @param {HTMLElement} container - Optional container element to limit search scope\n */\n scanTables(container = null) {\n const searchScope = container || document;\n const tables = searchScope.querySelectorAll('table');\n this.tables = Array.from(tables);\n }\n\n /**\n * Make all found tables sortable\n */\n makeTablesSortable() {\n this.tables.forEach((table, tableIndex) => {\n this.makeTableSortable(table, tableIndex);\n });\n }\n\n /**\n * Make a specific table sortable\n */\n makeTableSortable(table, tableIndex) {\n let thead = table.querySelector('thead');\n let headerRow = null;\n let headers = [];\n\n // Check if table has a proper thead\n if (thead) {\n headerRow = thead.querySelector('tr');\n if (headerRow) {\n headers = headerRow.querySelectorAll('th');\n }\n }\n\n if (headers.length === 0) {\n console.warn('Table has no sortable columns, skipping');\n return;\n }\n // First-time-only arrival animation. ChatPane's effect\n // destroys + re-inits the SortableTable on every `messages`\n // update, so a CSS animation tied to `.sortable-table`\n // alone would replay on each new chunk and feel jittery.\n // The DOM attribute persists across destroy/init cycles\n // (destroy() doesn't touch table attributes), so it cleanly\n // marks \"this table has already arrived once.\"\n const isFirstSortableMount = !table.hasAttribute('data-sortable-arrived');\n // Add sortable-table class for styling\n table.classList.add('sortable-table');\n if (isFirstSortableMount) {\n table.setAttribute('data-sortable-arrived', 'true');\n table.classList.add('sortable-table-arriving');\n // Drop the trigger class after the animation finishes so\n // it can't fire again if the table is somehow re-added to\n // a different DOM position.\n setTimeout(() => {\n table.classList.remove('sortable-table-arriving');\n }, 400);\n }\n\n // Calculate intelligent table width based on header text length\n //const calculatedWidth = this.calculateTableWidth(table);\n // table.style.width = 'auto';\n // table.style.minWidth = '80%';\n //table.style.tableLayout = 'fixed'; // Use fixed layout to respect manual widths\n\n // Cell styles are now handled by CSS only\n\n // Initialize sort state for this table\n this.sortStates.set(tableIndex, {\n currentColumn: -1,\n direction: 'none'\n });\n\n // Capture the table's pre-transform width once so calculateTableWidth\n // can use it as a floor. Persisted as a data attribute (like\n // data-sortable-arrived) so it survives ChatPane's destroy/init\n // cycle — re-reading on every mount would pick up the inline\n // width left behind by the previous calculation, not the\n // natural width the user originally saw.\n if (!table.hasAttribute('data-original-width')) {\n table.setAttribute('data-original-width', table.getBoundingClientRect().width);\n }\n\n this.applyTableStyles(table);\n\n // Store original column order\n this.originalColumnOrder.set(tableIndex, Array.from(headers).map((_, index) => index));\n\n // Make each header sortable\n headers.forEach((header, columnIndex) => {\n if (this.options.excludeColumns.includes(columnIndex)) {\n return;\n }\n\n this.makeHeaderSortable(header, table, tableIndex, columnIndex);\n });\n\n // Replace exponential values in all cells with full numbers\n this.replaceExponentialValues(table);\n\n // Mark this table as initialized\n initializedTables.add(table);\n }\n\n /**\n * Replace exponential values in table cells with full numbers\n * @param {HTMLElement} table - The table to process\n */\n replaceExponentialValues(table) {\n const tbody = table.querySelector('tbody');\n if (!tbody) return;\n\n const rows = tbody.querySelectorAll('tr');\n rows.forEach(row => {\n const cells = row.querySelectorAll('td, th');\n cells.forEach(cell => {\n const text = cell.textContent.trim();\n const exponentialMatch = text.match(/^([\\d,]+\\.?\\d*)[eE][+-]?(\\d+)$/);\n\n if (exponentialMatch) {\n const base = parseFloat(exponentialMatch[1].replace(/,/g, ''));\n const exponent = parseInt(exponentialMatch[2]);\n const fullNumber = base * Math.pow(10, exponent);\n\n // Format the number with commas for readability\n const formattedNumber = this.formatNumber(fullNumber);\n cell.textContent = formattedNumber;\n }\n });\n });\n }\n\n /**\n * Format a number with commas for readability\n * @param {number} num - The number to format\n * @returns {string} The formatted number\n */\n formatNumber(num) {\n if (num === 0) return '0';\n\n // Handle very large or very small numbers\n if (Math.abs(num) >= 1e12) {\n return (num / 1e12).toFixed(2) + 'T';\n } else if (Math.abs(num) >= 1e9) {\n return (num / 1e9).toFixed(2) + 'B';\n } else if (Math.abs(num) >= 1e6) {\n return (num / 1e6).toFixed(2) + 'M';\n } else if (Math.abs(num) >= 1e3) {\n return (num / 1e3).toFixed(2) + 'K';\n } else if (Math.abs(num) < 0.01 && num !== 0) {\n return num.toExponential(2);\n } else {\n return num.toLocaleString();\n }\n }\n\n /**\n * Convert the first row to a header row\n * @param {HTMLElement} firstRow - The first row to convert\n * @param {HTMLElement} thead - The thead element to append to\n * @param {HTMLElement} tbody - The tbody element to remove from\n * @returns {HTMLElement} The converted header row\n */\n convertRowToHeader(firstRow, thead, tbody) {\n try {\n // Clone the row\n const headerRow = firstRow.cloneNode(true);\n\n // Convert all td elements to th elements\n const cells = headerRow.querySelectorAll('td');\n cells.forEach(td => {\n const th = document.createElement('th');\n\n // Copy all attributes\n Array.from(td.attributes).forEach(attr => {\n th.setAttribute(attr.name, attr.value);\n });\n\n // Copy content\n th.innerHTML = td.innerHTML;\n\n // Copy styles\n th.style.cssText = td.style.cssText;\n\n // Replace td with th\n td.parentNode.replaceChild(th, td);\n });\n\n // Remove the original first row from tbody\n if (tbody && tbody.contains(firstRow)) {\n tbody.removeChild(firstRow);\n } else if (firstRow.parentNode) {\n firstRow.parentNode.removeChild(firstRow);\n }\n\n // Add the header row to thead\n thead.appendChild(headerRow);\n\n return headerRow;\n\n } catch (error) {\n console.error('Error converting row to header:', error);\n return null;\n }\n }\n\n /**\n * Make a specific header sortable\n */\n makeHeaderSortable(header, table, tableIndex, columnIndex) {\n // Add sortable class\n header.classList.add(this.options.sortableClass);\n\n // Add cursor pointer\n header.style.cursor = 'pointer';\n\n // Add sort icon if not preserving existing icons\n if (!this.options.preserveExistingIcons || !header.querySelector('.material-icons')) {\n this.addSortIcon(header);\n }\n\n // Add resizing functionality\n if (this.options.enableResizing) {\n this.addResizing(header, table, tableIndex, columnIndex);\n }\n\n // Add drag and drop functionality\n if (this.options.enableReordering) {\n this.addDragAndDrop(header, table, tableIndex, columnIndex);\n // Note: We rely on header drop targets only for better reliability\n }\n\n const clickListener = (e) => {\n e.preventDefault();\n this.sortTable(table, tableIndex, columnIndex);\n }\n\n const mouseEnterListener = (e) => {\n if (!header.classList.contains(this.options.activeSortClass)) {\n header.style.background = this.options.theme.palette.surface.hover;\n }\n }\n\n const mouseLeaveListener = (e) => {\n if (!header.classList.contains(this.options.activeSortClass)) {\n header.style.background = '';\n }\n }\n\n header.removeEventListener('click', clickListener);\n const resp = header.addEventListener('click', clickListener);\n header.removeEventListener('mouseenter', mouseEnterListener);\n header.addEventListener('mouseenter', mouseEnterListener);\n header.removeEventListener('mouseleave', mouseLeaveListener);\n header.addEventListener('mouseleave', mouseLeaveListener);\n }\n\n /**\n * Add sort icon to header\n */\n addSortIcon(header) {\n if (header.querySelector('.sortable-table-icon')) {\n return;\n }\n\n const icon = document.createElement('i');\n icon.id = 'sortable-table-icon';\n icon.className = 'material-icons';\n icon.textContent = this.options.unsortedIcon;\n icon.style.marginRight = '2px';\n icon.style.fontSize = '12px';\n icon.style.verticalAlign = 'middle';\n // Start invisible, then animate to the resting opacity on a\n // later frame so the existing `.sortable-header .material-icons\n // { transition: opacity 0.2s ease }` rule fades in instead of\n // popping in alongside the rest of the table transformation.\n // Double-rAF guarantees the browser paints the 0 state first;\n // a single rAF can be coalesced into the insertion frame in\n // some engines and skip the transition.\n icon.style.opacity = '0';\n\n const existingIcon = header.querySelector('.material-icons');\n if (!existingIcon) {\n header.insertBefore(icon, header.firstChild);\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n icon.style.opacity = '0.6';\n });\n });\n }\n }\n\n /**\n * Sort table by column\n */\n sortTable(table, tableIndex, columnIndex) {\n const tbody = table.querySelector('tbody');\n if (!tbody) {\n console.warn('Table has no tbody element');\n return;\n }\n\n const rows = Array.from(tbody.querySelectorAll('tr'));\n if (rows.length === 0) {\n console.warn('Table has no data rows');\n return;\n }\n\n const sortState = this.sortStates.get(tableIndex);\n const header = table.querySelector(`thead tr th:nth-child(${columnIndex + 1})`);\n\n // Determine sort direction\n let newDirection;\n if (this.options.sortOnFirstClick) {\n newDirection = sortState.currentColumn === columnIndex && sortState.direction === 'asc' ? 'desc' : 'asc';\n } else {\n if (sortState.currentColumn !== columnIndex) {\n newDirection = 'asc';\n } else {\n newDirection = sortState.direction === 'none' ? 'asc' :\n sortState.direction === 'asc' ? 'desc' : 'none';\n }\n }\n\n // Update sort state\n sortState.currentColumn = columnIndex;\n sortState.direction = newDirection;\n this.sortStates.set(tableIndex, sortState);\n\n // Update visual indicators\n this.updateSortIndicators(table, tableIndex, columnIndex, newDirection);\n\n // If direction is 'none', restore original order\n if (newDirection === 'none') {\n this.restoreOriginalOrder(table, rows);\n return;\n }\n\n // Sort the rows\n const sortedRows = this.sortRows(rows, columnIndex, newDirection);\n\n // Re-append sorted rows\n sortedRows.forEach(row => tbody.appendChild(row));\n }\n\n /**\n * Sort rows based on column data\n */\n sortRows(rows, columnIndex, direction) {\n return rows.sort((a, b) => {\n const cellA = a.cells[columnIndex];\n const cellB = b.cells[columnIndex];\n\n if (!cellA || !cellB) return 0;\n\n const valueA = this.extractValue(cellA);\n const valueB = this.extractValue(cellB);\n\n // Use custom sorter if available\n if (this.options.customSorters[columnIndex]) {\n return this.options.customSorters[columnIndex](valueA, valueB, direction);\n }\n\n // Default sorting logic\n const comparison = this.compareValues(valueA, valueB);\n return direction === 'asc' ? comparison : -comparison;\n });\n }\n\n /**\n * Extract sortable value from cell\n */\n extractValue(cell) {\n let text = cell.textContent.trim();\n\n let number = parseRawNumber(text);\n if (!isNaN(number)) {\n console.log(number);\n return number;\n }\n\n // Remove all material icons and common symbols from the text\n text = text.replace(/arrow_upward|arrow_downward|remove|keyboard_arrow_up|keyboard_arrow_down|unfold_more|expand_more|expand_less|trending_up|trending_down|↗|↘|↑|↓|→|←/g, '').trim();\n\n // Handle N/A, N/D, ND, blank and variants as -1\n const naVariants = /^(N\\/A|N\\/D|ND|N\\/A|n\\/a|n\\/d|nd|N\\/A|N\\/D|ND|\\s*)$/i;\n if (naVariants.test(text)) {\n return -1;\n }\n\n // Try to parse as percentage\n const percentageMatch = text.match(/^([\\d,]+\\.?\\d*)\\s*%$/);\n if (percentageMatch) {\n return parseFloat(percentageMatch[1].replace(/,/g, ''));\n }\n\n // Try to parse as exponential notation (scientific notation)\n const exponentialMatch = text.match(/^([\\d,]+\\.?\\d*)[eE][+-]?(\\d+)$/);\n if (exponentialMatch) {\n const base = parseFloat(exponentialMatch[1].replace(/,/g, ''));\n const exponent = parseInt(exponentialMatch[2]);\n return base * Math.pow(10, exponent);\n }\n\n // Try to parse as number\n const numberMatch = text.match(/^[\\d,]+\\.?\\d*[KMB]?$/);\n if (numberMatch) {\n return this.parseNumber(text);\n }\n\n // Try to parse as currency\n const currencyMatch = text.match(/^R\\$\\s*([\\d,]+\\.?\\d*)$/);\n if (currencyMatch) {\n return this.parseNumber(currencyMatch[1]);\n }\n\n // Try to parse as date\n const date = new Date(text);\n if (!isNaN(date.getTime())) {\n return date.getTime();\n }\n\n // Return as string (case-insensitive)\n return text.toLowerCase();\n }\n\n /**\n * Compare two values for sorting\n */\n compareValues(a, b) {\n // Handle null/undefined values\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n\n // Handle different types\n if (typeof a !== typeof b) {\n return String(a).localeCompare(String(b));\n }\n\n // Handle numbers\n if (typeof a === 'number') {\n return a - b;\n }\n\n // Handle dates\n if (a instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n // Handle strings\n return a.localeCompare(b);\n }\n\n /**\n * Update visual indicators for sort state\n */\n updateSortIndicators(table, tableIndex, columnIndex, direction) {\n const headers = table.querySelectorAll('thead tr th');\n\n // Reset all headers\n headers.forEach((header, index) => {\n header.classList.remove(this.options.activeSortClass, this.options.ascendingClass, this.options.descendingClass);\n const icon = header.querySelector('.material-icons');\n if (icon) {\n icon.textContent = this.options.unsortedIcon;\n icon.style.opacity = '0.6';\n }\n });\n\n // Update active header\n if (direction !== 'none') {\n const activeHeader = headers[columnIndex];\n activeHeader.classList.add(this.options.activeSortClass);\n\n const icon = activeHeader.querySelector('.material-icons');\n if (icon) {\n if (direction === 'asc') {\n activeHeader.classList.add(this.options.ascendingClass);\n icon.textContent = this.options.ascendingIcon;\n } else {\n activeHeader.classList.add(this.options.descendingClass);\n icon.textContent = this.options.descendingIcon;\n }\n icon.style.opacity = '1';\n }\n }\n }\n\n /**\n * Restore original order (when sort direction is 'none')\n */\n restoreOriginalOrder(table, rows) {\n // This is a simplified implementation\n // In a real scenario, you might want to store the original order\n const tbody = table.querySelector('tbody');\n rows.forEach(row => tbody.appendChild(row));\n }\n\n /**\n * Add resizing functionality to a header\n */\n addResizing(header, table, tableIndex, columnIndex) {\n header.classList.add(this.options.resizableClass);\n header.style.position = 'relative';\n\n\n if (header.querySelector('.resize-handle')) {\n return;\n }\n\n const resizeHandle = document.createElement('div');\n resizeHandle.className = 'resize-handle';\n resizeHandle.style.cssText = `\n position: absolute;\n top: 0;\n right: 0;\n width: 4px;\n height: 100%;\n background: transparent;\n cursor: col-resize;\n z-index: 10;\n `;\n\n header.appendChild(resizeHandle);\n\n let isResizing = false;\n let startX = 0;\n let startWidth = 0;\n\n resizeHandle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation(); // Prevent sort from triggering\n isResizing = true;\n startX = e.clientX;\n startWidth = header.offsetWidth;\n\n // Add visual feedback\n header.style.borderRight = '2px solid var(--primary-main, #2196F3)';\n header.style.background = 'var(--background-active, rgba(255, 255, 255, 0.1))';\n\n document.addEventListener('mousemove', handleResize);\n document.addEventListener('mouseup', stopResize);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n });\n\n const handleResize = (e) => {\n if (!isResizing) return;\n const newWidth = startWidth + (e.clientX - startX);\n if (newWidth > 30) { // Minimum width\n header.style.width = newWidth + 'px';\n\n // Set the same width on all cells in this column\n const columnIndex = Array.from(header.parentNode.children).indexOf(header);\n const tbody = table.querySelector('tbody');\n if (tbody) {\n const rows = tbody.querySelectorAll('tr');\n rows.forEach(row => {\n const cell = row.children[columnIndex];\n if (cell) {\n cell.style.width = newWidth + 'px';\n }\n });\n }\n\n // Update table width if column width increased\n this.updateTableWidth(table);\n }\n };\n\n const stopResize = () => {\n isResizing = false;\n\n // Remove visual feedback\n header.style.borderRight = '';\n header.style.background = '';\n\n document.removeEventListener('mousemove', handleResize);\n document.removeEventListener('mouseup', stopResize);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n };\n }\n\n /**\n * Add drag and drop functionality to a header\n */\n addDragAndDrop(header, table, tableIndex, columnIndex) {\n if (header.querySelector('.drag-handle')) {\n return;\n }\n\n header.classList.add(this.options.draggableClass);\n header.draggable = true;\n\n const thead = table.querySelector('thead tr');\n\n header.addEventListener('dragstart', (e) => {\n this.isDragging = true;\n // Store the current DOM position, not the original column index\n const currentPosition = Array.from(thead.children).indexOf(header);\n this.dragSource = { table, tableIndex, columnIndex: currentPosition };\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/html', header.outerHTML);\n const headerContent = header.outerHTML;\n header.style.opacity = '0.5';\n\n // Create a custom drag image\n this.createCustomDragImage(e, header, headerContent);\n });\n\n header.addEventListener('dragend', (e) => {\n this.isDragging = false;\n this.dragSource = null;\n header.style.opacity = '';\n // Remove all column highlights\n this.clearAllColumnHighlights(table);\n });\n\n header.addEventListener('dragover', (e) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n });\n\n header.addEventListener('dragenter', (e) => {\n e.preventDefault();\n if (this.dragSource && this.dragSource.tableIndex === tableIndex) {\n const currentColumnIndex = Array.from(thead.children).indexOf(header);\n if (this.dragSource.columnIndex !== currentColumnIndex) {\n // Add visual feedback to the entire column\n this.highlightColumn(table, currentColumnIndex, true);\n }\n }\n });\n\n header.addEventListener('dragleave', (e) => {\n // Only remove highlight if we're leaving the entire column\n if (!header.contains(e.relatedTarget)) {\n const currentColumnIndex = Array.from(thead.children).indexOf(header);\n this.highlightColumn(table, currentColumnIndex, false);\n }\n });\n\n header.addEventListener('drop', (e) => {\n e.preventDefault();\n\n if (this.dragSource && this.dragSource.tableIndex === tableIndex) {\n const currentColumnIndex = Array.from(thead.children).indexOf(header);\n if (this.dragSource.columnIndex !== currentColumnIndex) {\n this.reorderColumns(table, tableIndex, this.dragSource.columnIndex, currentColumnIndex);\n }\n }\n\n // Remove all column highlights\n this.clearAllColumnHighlights(table);\n });\n }\n\n /**\n * Create a custom drag image for better UX\n */\n createCustomDragImage(e, header, headerContent) {\n // Create a temporary element for the drag image\n const dragImage = document.createElement('div');\n dragImage.style.cssText = `\n position: absolute;\n top: -1000px;\n left: -1000px;\n background: var(--background-elevated, #333);\n border: 2px solid var(--primary-main, #2196F3);\n border-radius: 4px;\n padding: 8px 12px;\n font-size: 12px;\n font-weight: bold;\n color: var(--text-primary, #fff);\n white-space: nowrap;\n max-width: 150px;\n min-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n z-index: 10000;\n pointer-events: none;\n min-height: 50px;\n display: flex;\n align-items: center;\n `;\n\n // Get the header text without icons and create a compact representation\n const headerText = headerContent;\n dragImage.innerHTML = `\n <div style=\"display: flex; align-items: center; gap: 5px; align-content: center;color:white;\">\n <span style=\"overflow: hidden; text-overflow: ellipsis\">${headerText}</span>\n <svg style=\"fill: grey; font-size: 10px\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" ><defs><path id=\"a\" d=\"M0 0h24v24H0V0z\"/></defs><clipPath id=\"b\"><use xlink:href=\"#a\" overflow=\"visible\"/></clipPath><path clip-path=\"url(#b)\" d=\"M9.01 14H2v2h7.01v3L13 15l-3.99-4v3zm5.98-1v-3H22V8h-7.01V5L11 9l3.99 4z\"/></svg>\n </div> \n `;\n\n // Add to document temporarily\n document.body.appendChild(dragImage);\n\n // Set as drag image with centered offset\n e.dataTransfer.setDragImage(dragImage, 50, 12);\n\n // Clean up after a short delay\n setTimeout(() => {\n if (document.body.contains(dragImage)) {\n document.body.removeChild(dragImage);\n }\n }, 100);\n }\n\n\n\n /**\n * Highlight an entire column during drag operations\n */\n highlightColumn(table, columnIndex, highlight) {\n const thead = table.querySelector('thead tr');\n const tbody = table.querySelector('tbody');\n\n if (!thead || !tbody) return;\n\n const header = thead.children[columnIndex];\n if (!header) return;\n\n if (highlight) {\n header.classList.add(this.options.dragOverClass);\n // Highlight all cells in this column\n const rows = tbody.children;\n for (let i = 0; i < rows.length; i++) {\n const cell = rows[i].children[columnIndex];\n if (cell) {\n cell.classList.add(this.options.dragOverClass);\n }\n }\n } else {\n header.classList.remove(this.options.dragOverClass);\n // Remove highlight from all cells in this column\n const rows = tbody.children;\n for (let i = 0; i < rows.length; i++) {\n const cell = rows[i].children[columnIndex];\n if (cell) {\n cell.classList.remove(this.options.dragOverClass);\n }\n }\n }\n }\n\n /**\n * Clear all column highlights\n */\n clearAllColumnHighlights(table) {\n const thead = table.querySelector('thead tr');\n const tbody = table.querySelector('tbody');\n\n if (!thead || !tbody) return;\n\n // Clear header highlights\n const headers = thead.children;\n for (let i = 0; i < headers.length; i++) {\n headers[i].classList.remove(this.options.dragOverClass);\n }\n\n // Clear cell highlights\n const rows = tbody.children;\n for (let i = 0; i < rows.length; i++) {\n const cells = rows[i].children;\n for (let j = 0; j < cells.length; j++) {\n cells[j].classList.remove(this.options.dragOverClass);\n }\n }\n }\n\n /**\n * Reorder columns in a table\n */\n reorderColumns(table, tableIndex, fromIndex, toIndex) {\n const thead = table.querySelector('thead tr');\n const tbody = table.querySelector('tbody');\n\n if (!thead || !tbody) return;\n\n const headers = Array.from(thead.children);\n const rows = Array.from(tbody.children);\n\n // Validate indices\n if (fromIndex < 0 || fromIndex >= headers.length || toIndex < 0 || toIndex >= headers.length) {\n console.warn('Invalid column indices for reordering');\n return;\n }\n\n // Don't do anything if dropping on the same position\n if (fromIndex === toIndex) {\n return;\n }\n\n // Move the header element directly in the DOM\n const headerToMove = headers[fromIndex];\n const targetHeader = headers[toIndex];\n\n if (fromIndex < toIndex) {\n // Moving right: insert after target\n thead.insertBefore(headerToMove, targetHeader.nextSibling);\n } else {\n // Moving left: insert before target\n thead.insertBefore(headerToMove, targetHeader);\n }\n\n // Move cells in each row\n rows.forEach((row, rowIndex) => {\n const cells = Array.from(row.children);\n const cellToMove = cells[fromIndex];\n const targetCell = cells[toIndex];\n\n if (fromIndex < toIndex) {\n // Moving right: insert after target\n row.insertBefore(cellToMove, targetCell.nextSibling);\n } else {\n // Moving left: insert before target\n row.insertBefore(cellToMove, targetCell);\n }\n });\n\n // Update column order tracking\n const currentOrder = this.originalColumnOrder.get(tableIndex);\n if (currentOrder) {\n const newOrder = [...currentOrder];\n const columnToMove = newOrder[fromIndex];\n newOrder.splice(fromIndex, 1);\n newOrder.splice(toIndex, 0, columnToMove);\n this.originalColumnOrder.set(tableIndex, newOrder);\n }\n\n // Reapply inline styles after reordering\n this.applyTableStyles(table);\n\n // Refresh drag and drop listeners for the reordered columns\n this.refreshDragAndDropListeners(table, tableIndex);\n }\n\n /**\n * Refresh drag and drop listeners after column reordering\n */\n refreshDragAndDropListeners(table, tableIndex) {\n const thead = table.querySelector('thead tr');\n if (!thead) return;\n\n const headers = Array.from(thead.children);\n\n // Remove existing listeners by cloning headers and re-adding all functionality\n headers.forEach((header, columnIndex) => {\n if (header.classList.contains(this.options.draggableClass)) {\n // Clear any drag-related inline styles before cloning\n header.style.opacity = '';\n header.style.background = '';\n header.style.borderRight = '';\n\n const newHeader = header.cloneNode(true);\n header.parentNode.replaceChild(newHeader, header);\n\n // Re-add all functionality (sorting, resizing, drag and drop)\n this.makeHeaderSortable(newHeader, table, tableIndex, columnIndex);\n }\n });\n }\n\n /**\n * Update table width based on current column widths\n */\n updateTableWidth(table) {\n const headers = table.querySelectorAll('th');\n let totalWidth = 0;\n\n headers.forEach(header => {\n const width = header.style.width;\n if (width) {\n const widthValue = parseInt(width.replace('px', ''));\n totalWidth += widthValue;\n } else {\n // Fallback to estimated width if no explicit width set\n const text = header.textContent.replace(/[📊🔍]/g, '').trim();\n totalWidth += text.length;\n }\n });\n\n // Convert to percentage\n table.style.width = `${totalWidth}px`;\n }\n\n /**\n * Calculate intelligent table width based on header text length\n */\n calculateTableWidth(table) {\n const originalWidthAttr = table.getAttribute('data-original-width');\n const originalWidth = originalWidthAttr ? parseFloat(originalWidthAttr) : 0;\n const headers = table.querySelectorAll('th');\n let totalWidth = 0;\n\n const parentWidth = table.parentElement.clientWidth\n\n const headersWidth = [];\n headers.forEach(header => {\n // Get text content without icons\n const text = header.textContent.replace(/[📊🔍]/g, '').trim();\n\n let estimatedWidth = text.length * this.charWidth + 15;\n\n headersWidth.push(estimatedWidth);\n\n totalWidth += estimatedWidth;\n });\n\n const rows = table.querySelectorAll('tr');\n\n const containerWidth = table.parentElement?.getBoundingClientRect().width ?? totalWidth;\n\n var maxRowWidth = 0;\n for (const row of rows) {\n const cells = row.querySelectorAll('td');\n\n cells.forEach((cell, index) => {\n // Get text content without icons\n const text = cell.textContent;\n\n const cellWidth = text.length * this.charWidth + 15;\n if (cellWidth > headersWidth[index] && index < headersWidth.length)\n headersWidth[index] = cellWidth;\n });\n };\n\n maxRowWidth = headersWidth.reduce((prev, current) => prev += current, 0);\n\n headers.forEach((header, index) => {\n if (maxRowWidth > containerWidth) {\n const factor = headersWidth[index] / maxRowWidth;\n header.style.width = `${containerWidth * factor}px`\n }\n else {\n header.style.width = `${headersWidth[index]}px`\n }\n });\n\n // Convert to percentage or pixel value\n let finalWidth = 0\n if (maxRowWidth > containerWidth) {\n finalWidth = `100%`\n }\n else {\n // If the calculated width would shrink the table below its\n // pre-transform rendered width, preserve the original.\n const effectiveWidth = Math.max(maxRowWidth, originalWidth);\n finalWidth = `${effectiveWidth}px`;\n }\n\n return finalWidth;\n }\n\n /**\n * Apply inline styles to ensure text clipping and horizontal scroll work\n */\n applyTableStyles(table) {\n // Force table styles\n const calculatedWidth = this.calculateTableWidth(table);\n // The \"fits comfortably\" branch of calculateTableWidth used\n // to force width: 100%, which made every chat table stretch\n // edge-to-edge regardless of content. Instead, let the table\n // be content-fit (auto) but floor it at 60% of the container\n // so very narrow tables don't look orphaned next to the\n // chat gutter, and cap it at 100% so wider data still fits.\n // The overflow branch still uses the calculated pixel width\n // because it's already wider than the container would allow.\n table.style.width = calculatedWidth;\n table.style.maxWidth = '100%';\n // if (calculatedWidth === '100%') {\n // table.style.width = 'auto';\n // table.style.minWidth = '60%';\n // table.style.maxWidth = '100%';\n // } else {\n // table.style.width = `${calculatedWidth}`;\n // table.style.minWidth = 'auto';\n // table.style.maxWidth = 'auto';\n // }\n // table.style.tableLayout = 'fixed'; // Use fixed layout to respect manual widths\n }\n\n getCharWidth(char, font, mono) {\n // Create a temporary canvas element\n const canvas = document.createElement(\"canvas\");\n const context = canvas.getContext(\"2d\");\n\n // Set the font (e.g., \"16px Arial\")\n context.fontFamily = font;\n context.fontMono = mono;\n\n // Measure the specific character\n const metrics = context.measureText(\"A \");\n return metrics.width; // Returns width in pixels\n }\n\n /**\n * Add CSS styles for sortable tables\n */\n addStyles() {\n if (document.getElementById('sortable-table-styles')) {\n return; // Styles already added\n }\n\n const style = document.createElement('style');\n style.id = 'sortable-table-styles';\n style.textContent = ` \n .${this.options.sortableClass} {\n position: relative;\n user-select: none;\n transition: background-color 0.2s ease;\n }\n \n .${this.options.sortableClass}:hover {\n background-color: ${this.options.theme.palette.surface.hover} !important;\n }\n \n .${this.options.activeSortClass} {\n background-color: ${this.options.theme.palette.surface.raised} !important;\n font-weight: bold;\n }\n \n .${this.options.ascendingClass} {\n border-bottom: 2px solid var(${this.options.theme.palette.primary.main}, #3a3a3a);\n }\n \n .${this.options.descendingClass} {\n border-bottom: 2px solid var(${this.options.theme.palette.primary.main}, #3a3a3a);\n }\n \n .${this.options.sortableClass} .material-icons {\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n \n .${this.options.activeSortClass} .material-icons {\n color: var(${this.options.theme.palette.primary.main}, #3a3a3a);\n }\n \n .${this.options.resizableClass} .resize-handle:hover {\n background-color: var(${this.options.theme.palette.primary.light}, #64B5F6);\n }\n \n .${this.options.draggableClass} {\n cursor: move;\n position: relative;\n }\n \n .${this.options.draggableClass}::before {\n content: '';\n position: absolute;\n top: 0;\n left: -5px;\n right: -5px;\n bottom: 0;\n z-index: 1;\n pointer-events: none;\n }\n \n .${this.options.dragOverClass} {\n background-color: rgba(128, 128, 128, 0.2) !important;\n border: 2px dashed rgba(128, 128, 128, 0.8);\n }\n \n .${this.options.draggableClass}:hover {\n background-color: var(${this.options.theme.palette.surface.raised}, rgba(100, 181, 246, 0.1)) !important;\n }\n\n .sortable-table tbody td {\n width: auto\n } \n\n .sortable-table {\n background-color: 'inherit';\n /* Cross-fade bg/row stripes when the .sortable-table\n * class flip lands on a freshly-streamed markdown\n * table. Width is NOT animated: column widths set\n * by calculateTableWidth can be narrower than the\n * content currently fills, so animating them down\n * causes mid-transition cell wrap. Snap widths,\n * animate only colours. */\n transition: background-color 280ms ease-out;\n }\n\n .sortable-table th {\n transition: background-color 280ms ease-out;\n }\n\n /* Zebra striping for table rows */\n .sortable-table tbody tr:nth-child(odd) {\n background-color: ${this.options.theme.palette.background.defalt};\n color: ${this.options.theme.palette.text.primary};\n }\n\n .sortable-table tbody tr:nth-child(even) {\n background-color: ${this.options.theme.palette.background.defalt};\n color: ${this.options.theme.palette.text.primary};\n }\n\n /* One-shot arrival animation. Applied via a transient\n * class (added by makeTableSortable on first mount only)\n * so it does NOT re-fire on every destroy/init cycle.\n * scaleX with origin top-left gives the \"right edge\n * grows outward\" feel the user asked for; the 0.96\n * start is subtle enough that text compression isn't\n * obvious. */\n @keyframes sortable-table-arrive {\n from {\n opacity: 0.35;\n transform: scaleX(0.96);\n transform-origin: top left;\n }\n to {\n opacity: 1;\n transform: scaleX(1);\n }\n }\n\n .sortable-table-arriving {\n animation: sortable-table-arrive 320ms cubic-bezier(0.16, 1, 0.3, 1) both;\n }\n \n /* Ensure hover effects work with zebra striping */\n .sortable-table tbody tr:hover {\n background-color: ${this.options.theme.palette.surface.hover} !important;\n }\n \n /* Fix table-container overflow issue */\n .table-container {\n overflow: auto !important;\n overflow-x: auto !important;\n overflow-y: auto !important;\n }\n `;\n\n const existingStyle = document.getElementById('sortable-table-styles');\n if (!existingStyle) {\n document.head.appendChild(style);\n }\n }\n\n /**\n * Destroy the sortable functionality\n */\n destroy() {\n this.tables.forEach(table => {\n const headers = table.querySelectorAll(`.${this.options.sortableClass}`);\n headers.forEach(header => {\n header.classList.remove(\n this.options.sortableClass,\n this.options.activeSortClass,\n this.options.ascendingClass,\n this.options.descendingClass\n );\n header.style.cursor = '';\n header.style.background = '';\n\n // Remove event listeners by cloning the element\n const newHeader = header.cloneNode(true);\n header.parentNode.replaceChild(newHeader, header);\n });\n });\n\n // Remove styles\n const styleElement = document.getElementById('sortable-table-styles');\n if (styleElement) {\n styleElement.remove();\n }\n\n this.tables = [];\n this.sortStates.clear();\n initializedTables.clear();\n }\n\n /**\n * Refresh the library (useful after DOM changes)\n */\n refresh() {\n this.destroy();\n this.init();\n }\n}\n\n// // Create global instance but don't auto-initialize\n// Guard the global assignment so this module is import-safe outside the\n// browser (Node/SSR/tests). Importing it for the class export alone — as the\n// session-replay decode path does transitively — must not throw on `window`.\nif (typeof window !== 'undefined') {\n window.SortableTable = SortableTable;\n}\n\n// Export for module systems\nexport default SortableTable;\n","// Shared prompt-overlay helpers used by both the chat composer (PromptV2) and the home composer (obtapp's\n// PromptComposer): tokenize a draft into chip/plain runs, and chip server-mapped locations inline like \"@\" mentions.\n\nexport type HighlightToken = { type: 'plain' | 'slash' | 'at' | 'hash'; text: string };\n\nconst TRIGGER_CHARS: ReadonlySet<string> = new Set(['/', '@', '#']);\nconst triggerTypeFor = (ch: string): 'slash' | 'at' | 'hash' =>\n ch === '/' ? 'slash' : ch === '@' ? 'at' : 'hash';\n// A token boundary is ASCII whitespace only — NOT the non-breaking space (U+00A0). Hosts join a multi-word\n// \"@mention\" (e.g. \"@São Paulo\") with NBSPs so the whole name stays a single chip; a regular space separates tokens.\nconst HIGHLIGHT_WS = /[ \\t\\r\\n\\f\\v]/;\n\n/**\n * Splits `text` into a flat list of runs so the overlay can paint chip styling around `/cmd` / `@user` / `#date`\n * tokens while keeping surrounding text plain. Boundary rule mirrors the autocomplete trigger detection (trigger\n * char at line start or after whitespace), so a `/` inside `http://` or `@` inside an email stays plain.\n */\nexport const tokenizeForHighlight = (text: string): HighlightToken[] => {\n if (!text) return [];\n const tokens: HighlightToken[] = [];\n let i = 0;\n while (i < text.length) {\n const ch = text[i];\n const atBoundary = i === 0 || HIGHLIGHT_WS.test(text[i - 1]);\n if (atBoundary && TRIGGER_CHARS.has(ch)) {\n let end = i + 1;\n while (end < text.length && !HIGHLIGHT_WS.test(text[end])) end += 1;\n tokens.push({ type: triggerTypeFor(ch), text: text.slice(i, end) });\n i = end;\n } else {\n let end = i + 1;\n while (end < text.length) {\n const c = text[end];\n const prevIsWs = HIGHLIGHT_WS.test(text[end - 1]);\n if (TRIGGER_CHARS.has(c) && prevIsWs) break;\n end += 1;\n }\n tokens.push({ type: 'plain', text: text.slice(i, end) });\n i = end;\n }\n }\n return tokens;\n};\n\n/**\n * Second pass: chip the locations the slow pass mapped (pasted / dictated, no typed \"@\") as if they were \"@\"\n * mentions — same inline chip style. Only PLAIN runs are scanned (real \"@\" mentions are already their own chips);\n * longest names win so \"São Paulo\" beats \"São\".\n */\nexport const chipLocations = (tokens: HighlightToken[], locTexts: readonly string[]): HighlightToken[] => {\n const needles = locTexts.filter((t) => t.trim().length > 0).sort((a, b) => b.length - a.length);\n if (needles.length === 0) return tokens;\n const out: HighlightToken[] = [];\n for (const tok of tokens) {\n if (tok.type !== 'plain') { out.push(tok); continue; }\n let rest = tok.text;\n while (rest.length > 0) {\n let at = -1;\n let len = 0;\n for (const n of needles) {\n const idx = rest.indexOf(n);\n if (idx >= 0 && (at === -1 || idx < at)) { at = idx; len = n.length; }\n }\n if (at === -1) { out.push({ type: 'plain', text: rest }); break; }\n if (at > 0) out.push({ type: 'plain', text: rest.slice(0, at) });\n out.push({ type: 'at', text: rest.slice(at, at + len) });\n rest = rest.slice(at + len);\n }\n }\n return out;\n};\n"],"names":["parseAndValidateArtifactUrl","__name","url","urlParts","lastPart","removedUrlParams","extractLinkAction","link","sessionId","content","action","question","parameter","firstDash","firstPart","chunkArray","char","size","_v","i","splitBigLinesWithSpaces","limit","whiteSpaceBreak","allWords","hadOne","word","charArray","chunkedWord","chunk","parseRawNumber","text","number","finalNumber","ratio","parseKnownNumbers","knownChars","currencySymbol","prefix","suffix","match","replacedChar","UUID_WITH_DASHES_REGEX","UUID_WITHOUT_DASHES_REGEX","startsWithInteractionId","str","interactionId","extractInteractionId","withDashesMatch","withoutDashesMatch","prettiffyFileName","fileName","withNoExtension","withNoInteractionId","extractNameFromStringWithInteractionId","prettiffyPythonFunctionName","functionName","prettyName","isValidInteractionId","initializedTables","_SortableTable","options","container","tables","table","tableIndex","thead","headerRow","headers","isFirstSortableMount","_","index","header","columnIndex","tbody","row","cell","exponentialMatch","base","exponent","fullNumber","formattedNumber","num","firstRow","td","th","attr","error","clickListener","e","mouseEnterListener","mouseLeaveListener","icon","rows","sortState","newDirection","direction","a","b","cellA","cellB","valueA","valueB","comparison","percentageMatch","currencyMatch","date","activeHeader","resizeHandle","isResizing","startX","startWidth","handleResize","stopResize","newWidth","currentPosition","headerContent","currentColumnIndex","dragImage","headerText","highlight","cells","j","fromIndex","toIndex","headerToMove","targetHeader","rowIndex","cellToMove","targetCell","currentOrder","newOrder","columnToMove","newHeader","totalWidth","width","widthValue","_a","originalWidthAttr","originalWidth","headersWidth","estimatedWidth","containerWidth","maxRowWidth","cellWidth","prev","current","factor","finalWidth","calculatedWidth","font","mono","context","style","styleElement","SortableTable","TRIGGER_CHARS","triggerTypeFor","ch","HIGHLIGHT_WS","tokenizeForHighlight","tokens","end","c","prevIsWs","chipLocations","locTexts","needles","t","out","tok","rest","at","len","n","idx"],"mappings":"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"}
|