@pythia-software/query-table-ui 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +382 -8
- package/dist/FormulaEditor-NZWSPFJQ.js +7 -0
- package/dist/FormulaEditor-NZWSPFJQ.js.map +1 -0
- package/dist/chunk-TC5KDYUF.js +778 -0
- package/dist/chunk-TC5KDYUF.js.map +1 -0
- package/dist/index.d.ts +527 -14
- package/dist/index.js +13697 -3353
- package/dist/index.js.map +1 -1
- package/dist/theme.css +4557 -415
- package/dist/theme.css.map +1 -1
- package/package.json +6 -11
- package/dist/FormulaEditor-YCPICDIH.js +0 -251
- package/dist/FormulaEditor-YCPICDIH.js.map +0 -1
- package/dist/theme.d.ts +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/FormulaEditor.tsx","../src/formulaEditorHelpers.ts","../src/FormulaFunctionBrowser.tsx","../src/formulaFunctionCatalogue.ts"],"sourcesContent":["import {\n useEffect,\n useId,\n useImperativeHandle,\n useRef,\n useState,\n type KeyboardEvent,\n type MutableRefObject,\n type Ref,\n} from \"react\";\nimport {\n FORMULA_FUNCTIONS,\n FormulaError,\n type FormulaFunction,\n type FieldDef,\n} from \"@pythia-software/query-table-core\";\nimport {\n formulaCompletions,\n formulaContext,\n signatureAt,\n type FormulaCompletions,\n type FormulaSuggestion,\n} from \"./formulaEditorHelpers\";\n\nimport { FormulaFunctionBrowser } from \"./FormulaFunctionBrowser\";\n\nexport interface FormulaEditorActions {\n insertFunction: (name: string) => void;\n}\n\nexport interface FormulaEditorProps {\n actionsRef?: Ref<FormulaEditorActions>;\n functions?: readonly FormulaFunction[];\n value: string;\n onChange: (value: string) => void;\n fields: FieldDef[];\n compile: (value: string) => unknown;\n /** Metric authoring uses a separate reference pane and no suggestions. */\n suggestions?: boolean;\n showLibrary?: boolean;\n rows?: number;\n ariaLabel?: string;\n inputRef?: MutableRefObject<HTMLTextAreaElement | null>;\n onFocus?: () => void;\n onReady?: (input: HTMLTextAreaElement) => void;\n}\n\nexport default function FormulaEditor({\n value,\n actionsRef,\n functions = FORMULA_FUNCTIONS,\n onChange,\n fields,\n compile,\n suggestions = true,\n showLibrary = true,\n ariaLabel = \"Computed column formula\",\n inputRef,\n onFocus,\n onReady,\n rows = 6,\n}: FormulaEditorProps) {\n const id = useId();\n const editor = useRef<HTMLTextAreaElement | null>(null);\n const applyingEdit = useRef(false);\n const composing = useRef(false);\n // Track generated pairs through edits; existing closing characters stay editable.\n const paired = useRef<{\n value: string;\n ranges: { open: number; close: number }[];\n }>({ value, ranges: [] });\n const trackEdit = (next: string) => {\n const previous = paired.current.value;\n if (previous === next) return;\n let from = 0;\n while (\n from < previous.length &&\n from < next.length &&\n previous[from] === next[from]\n )\n from++;\n let oldEnd = previous.length,\n newEnd = next.length;\n while (\n oldEnd > from &&\n newEnd > from &&\n previous[oldEnd - 1] === next[newEnd - 1]\n ) {\n oldEnd--;\n newEnd--;\n }\n const shift = newEnd - oldEnd;\n paired.current.ranges = paired.current.ranges\n .filter(\n ({ open, close }) =>\n !(open >= from && open < oldEnd) &&\n !(close >= from && close < oldEnd),\n )\n .map(({ open, close }) => ({\n open: open >= oldEnd ? open + shift : open,\n close: close >= oldEnd ? close + shift : close,\n }));\n paired.current.value = next;\n };\n const selection = useRef({ start: 0, end: 0 });\n const latestCompile = useRef(compile);\n latestCompile.current = compile;\n const [caret, setCaret] = useState(0);\n const [completions, setCompletions] = useState<FormulaCompletions | null>(\n null,\n );\n const [active, setActive] = useState(0);\n const [diagnostic, setDiagnostic] = useState<{\n message: string;\n from: number;\n to: number;\n } | null>(null);\n const options = suggestions ? (completions?.options.slice(0, 50) ?? []) : [];\n const hint = suggestions ? signatureAt(value.slice(0, caret), functions) : \"\";\n\n useEffect(() => {\n // Native edits already updated the DOM; avoid resetting selection/undo on each keystroke.\n const input = editor.current;\n if (input && input.value !== value) {\n input.value = value;\n paired.current = { value, ranges: [] };\n setCaret(input.selectionStart);\n setCompletions(null);\n }\n setDiagnostic(null);\n const timer = setTimeout(() => {\n try {\n latestCompile.current(value);\n setDiagnostic(null);\n } catch (error) {\n const from = error instanceof FormulaError ? error.from : 0;\n const to = error instanceof FormulaError ? error.to : value.length;\n setDiagnostic({\n message: error instanceof Error ? error.message : String(error),\n from: Math.max(0, Math.min(from, value.length)),\n to: Math.max(0, Math.min(to, value.length)),\n });\n }\n }, 250);\n return () => clearTimeout(timer);\n }, [value]);\n\n useEffect(() => {\n if (editor.current) onReady?.(editor.current);\n }, [onReady]);\n\n useEffect(() => {\n document\n .getElementById(`${id}-option-${active}`)\n ?.scrollIntoView?.({ block: \"nearest\" });\n }, [active, id]);\n\n const suggest = (explicit = false) => {\n const input = editor.current;\n if (!suggestions || !input || composing.current) return;\n selection.current = {\n start: input.selectionStart,\n end: input.selectionEnd,\n };\n setCaret(input.selectionStart);\n setActive(0);\n setCompletions(\n formulaCompletions(\n input.value,\n input.selectionStart,\n input.selectionEnd,\n fields,\n explicit,\n functions,\n ),\n );\n };\n\n const insert = (\n from: number,\n to: number,\n text: string,\n caretOffset = text.length,\n pair?: { open: number; close: number },\n ) => {\n const input = editor.current;\n if (!input) return;\n input.focus();\n input.setSelectionRange(from, to);\n applyingEdit.current = true;\n try {\n // insertText preserves native textarea undo in Chromium/WebKit. Browsers\n // without this editing command still have a plain-text insertion fallback.\n const before = input.value;\n try {\n document.execCommand?.(\"insertText\", false, text);\n } catch {\n /* use fallback */\n }\n if (input.value === before) input.setRangeText(text, from, to, \"end\");\n } finally {\n applyingEdit.current = false;\n }\n trackEdit(input.value);\n if (pair)\n paired.current.ranges.push({\n open: from + pair.open,\n close: from + pair.close,\n });\n input.setSelectionRange(from + caretOffset, from + caretOffset);\n setCaret(input.selectionStart);\n setCompletions(null);\n onChange(input.value);\n };\n\n const accept = (option: FormulaSuggestion) => {\n if (completions)\n insert(\n completions.from,\n completions.to,\n option.insert,\n option.caretOffset,\n option.insert.endsWith(\"()\")\n ? { open: option.insert.length - 2, close: option.insert.length - 1 }\n : undefined,\n );\n };\n\n const insertFunction = (name: string) => {\n const input = editor.current;\n if (!input) return;\n const from = input.selectionStart;\n const to = input.selectionEnd;\n const selected = input.value.slice(from, to);\n insert(\n from,\n to,\n `${name}(${selected})`,\n name.length + selected.length + 1,\n { open: name.length, close: name.length + selected.length + 1 },\n );\n };\n useImperativeHandle(actionsRef, () => ({ insertFunction }));\n\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n const input = event.currentTarget;\n if (composing.current || event.nativeEvent.isComposing) return;\n if (suggestions && event.ctrlKey && event.code === \"Space\") {\n event.preventDefault();\n suggest(true);\n return;\n }\n if (options.length) {\n if (event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n setCompletions(null);\n return;\n }\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n setActive(\n (index) =>\n (index + (event.key === \"ArrowDown\" ? 1 : options.length - 1)) %\n options.length,\n );\n return;\n }\n if (event.key === \"Enter\") {\n event.preventDefault();\n const option = options[active];\n if (option) accept(option);\n return;\n }\n }\n if (event.ctrlKey || event.metaKey || event.altKey) return;\n const start = input.selectionStart,\n end = input.selectionEnd;\n const context = formulaContext(input.value, start);\n const close = event.key === \"(\" ? \")\" : event.key === '\"' ? '\"' : undefined;\n if (\n close &&\n !context.quoted &&\n context.fieldStart < 0 &&\n (start !== end ||\n end === input.value.length ||\n /[\\s)\\]}]/.test(input.value[end]!))\n ) {\n event.preventDefault();\n const selection = input.value.slice(start, end);\n insert(start, end, event.key + selection + close, selection.length + 1, {\n open: 0,\n close: selection.length + 1,\n });\n } else if (\n start === end &&\n input.value[start] === event.key &&\n paired.current.ranges.some((pair) => pair.close === start) &&\n ((event.key === \")\" && !context.quoted && context.fieldStart < 0) ||\n (event.key === '\"' && context.quoted && !context.escaped))\n ) {\n event.preventDefault();\n paired.current.ranges = paired.current.ranges.filter(\n (pair) => pair.close !== start,\n );\n input.setSelectionRange(start + 1, start + 1);\n setCaret(start + 1);\n setCompletions(null);\n } else if (\n event.key === \"Backspace\" &&\n start === end &&\n start > 0 &&\n [\"()\", \"[]\", '\"\"'].includes(input.value.slice(start - 1, start + 1)) &&\n (!context.quoted ||\n (input.value.slice(start - 1, start + 1) === '\"\"' && !context.escaped))\n ) {\n event.preventDefault();\n insert(start - 1, start + 1, \"\");\n }\n };\n\n return (\n <div className=\"qt-formula-layout\">\n <div className=\"qt-formula-editor\">\n <textarea\n ref={(input) => {\n editor.current = input;\n if (inputRef) inputRef.current = input;\n }}\n className=\"qt-formula-input\"\n aria-label={ariaLabel}\n aria-describedby={`${id}-hint${diagnostic ? ` ${id}-error` : \"\"}`}\n aria-invalid={diagnostic ? true : undefined}\n aria-autocomplete={suggestions ? \"list\" : \"none\"}\n aria-controls={options.length ? `${id}-suggestions` : undefined}\n aria-activedescendant={\n options.length ? `${id}-option-${active}` : undefined\n }\n defaultValue={value}\n rows={rows}\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n onChange={(event) => {\n if (applyingEdit.current) return;\n trackEdit(event.currentTarget.value);\n onChange(event.currentTarget.value);\n if (!composing.current) suggest();\n }}\n onSelect={(event) => {\n setCaret(event.currentTarget.selectionStart);\n const input = event.currentTarget;\n if (\n !applyingEdit.current &&\n (input.selectionStart !== selection.current.start ||\n input.selectionEnd !== selection.current.end)\n )\n setCompletions(null);\n }}\n onKeyDown={onKeyDown}\n onCompositionStart={() => {\n composing.current = true;\n setCompletions(null);\n }}\n onCompositionEnd={() => {\n composing.current = false;\n suggest();\n }}\n onBlur={() => setCompletions(null)}\n onFocus={onFocus}\n />\n <div className=\"qt-formula-tools\">\n {suggestions && (\n <button\n type=\"button\"\n className=\"qt-link-btn\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n editor.current?.focus();\n suggest(true);\n }}\n >\n Suggestions\n </button>\n )}\n <span>\n Line {value.slice(0, caret).split(\"\\n\").length}, column{\" \"}\n {caret - value.slice(0, caret).lastIndexOf(\"\\n\")}\n </span>\n </div>\n {options.length > 0 && (\n <div\n className=\"qt-formula-completions\"\n data-qt-formula-suggestions=\"\"\n >\n <ul\n id={`${id}-suggestions`}\n role=\"listbox\"\n aria-label=\"Formula suggestions\"\n onMouseDown={(event) => event.preventDefault()}\n >\n {options.map((option, index) => (\n <li\n key={option.label}\n id={`${id}-option-${index}`}\n role=\"option\"\n aria-selected={index === active}\n title={option.description}\n onClick={() => accept(option)}\n >\n <strong>{option.label}</strong>\n <small>{option.detail}</small>\n </li>\n ))}\n </ul>\n <p>\n {options[active]?.description} · ↑↓ choose, Enter inserts, Esc\n closes\n </p>\n {completions && completions.options.length > options.length && (\n <p>Type to narrow the first {options.length} suggestions.</p>\n )}\n </div>\n )}\n <p id={`${id}-hint`} className=\"qt-formula-hint\" aria-live=\"polite\">\n {hint}\n </p>\n {diagnostic && (\n <div id={`${id}-error`} className=\"qt-formula-error\" role=\"status\">\n {diagnostic.message}{\" \"}\n <button\n type=\"button\"\n className=\"qt-link-btn\"\n onClick={() => {\n editor.current?.focus();\n editor.current?.setSelectionRange(\n diagnostic.from,\n diagnostic.to,\n );\n setCaret(diagnostic.from);\n }}\n >\n Select error location\n </button>\n </div>\n )}\n </div>\n {showLibrary && (\n <FormulaFunctionBrowser\n functions={functions}\n onInsert={insertFunction}\n />\n )}\n </div>\n );\n}\n","import {\n FORMULA_FUNCTIONS,\n type FieldDef,\n type FormulaFunction,\n} from \"@pythia-software/query-table-core\";\n\nexport const FORMULA_EDITOR_HELP =\n \"Use [field] references. Ctrl+Space opens suggestions.\";\n\nexport interface FormulaSuggestion {\n label: string;\n detail: string;\n description: string;\n insert: string;\n // Place the caret inside the function call after inserting paired parentheses.\n caretOffset?: number;\n}\n\nexport interface FormulaCompletions {\n from: number;\n to: number;\n options: FormulaSuggestion[];\n}\n\n/** Scan strings and escaped field names before interpreting punctuation. */\nexport function formulaContext(text: string, end = text.length) {\n let quoted = false;\n let fieldStart = -1;\n let escaped = false;\n for (let i = 0; i < end; i++) {\n const c = text[i];\n if (quoted) {\n if (c === \"\\\\\") {\n escaped = i + 1 >= end;\n i++;\n } else if (c === '\"') quoted = false;\n } else if (fieldStart >= 0) {\n if (c === \"]\") {\n if (text[i + 1] === \"]\") i++;\n else fieldStart = -1;\n }\n } else if (c === '\"') quoted = true;\n else if (c === \"[\") fieldStart = i;\n }\n return { quoted, fieldStart, escaped };\n}\n\nexport function formulaCompletions(\n text: string,\n start: number,\n end: number,\n fields: FieldDef[],\n explicit = false,\n functions: readonly FormulaFunction[] = FORMULA_FUNCTIONS,\n): FormulaCompletions | null {\n const before = text.slice(0, start);\n const { quoted, fieldStart } = formulaContext(text, start);\n if (quoted || (!explicit && start !== end)) return null;\n const word = before.match(/\\b[A-Za-z_][A-Za-z_0-9]*$/)?.[0] ?? \"\";\n if (!explicit && fieldStart < 0 && !word) return null;\n const from =\n start !== end ? start : fieldStart >= 0 ? fieldStart : start - word.length;\n let to = end;\n if (start === end && fieldStart >= 0) {\n // Replace the rest of a field reference too, including escaped ]] characters.\n for (let i = fieldStart + 1; i < text.length; i++) {\n if (text[i] === \"]\") {\n if (text[i + 1] === \"]\") {\n i++;\n continue;\n }\n to = i + 1;\n break;\n }\n if (text[i] === \"\\n\" || text[i] === \"[\") break;\n }\n } else if (start === end) {\n to += text.slice(end).match(/^[A-Za-z_0-9]*/)?.[0].length ?? 0;\n }\n const prefix = start !== end ? \"\" : before.slice(from).toLowerCase();\n const options: FormulaSuggestion[] = fields.map((f) => ({\n label: `[${f.name.replace(/\\]/g, \"]]\")}]`,\n detail: `${f.label} · ${f.type}`,\n description: f.name,\n insert: `[${f.name.replace(/\\]/g, \"]]\")}]`,\n }));\n if (fieldStart < 0) {\n options.push(\n ...functions.map((f) => ({\n label: f.name,\n detail: f.signature,\n description: f.description,\n insert: text[to] === \"(\" ? f.name : `${f.name}()`,\n caretOffset: f.name.length + 1,\n })),\n ...[\"TRUE\", \"FALSE\", \"NULL\", \"AND\", \"OR\", \"NOT\", \"IN\", \"BETWEEN\"].map(\n (label) => ({\n label,\n detail: \"Keyword\",\n description: \"\",\n insert: label,\n }),\n ),\n );\n }\n return {\n from,\n to,\n options: options.filter(\n (option) =>\n option.label.toLowerCase().startsWith(prefix) ||\n (fieldStart >= 0 &&\n option.detail.toLowerCase().includes(prefix.slice(1))),\n ),\n };\n}\n\nexport function signatureAt(\n text: string,\n functions: readonly FormulaFunction[] = FORMULA_FUNCTIONS,\n): string {\n const stack: { name: string; argument: number }[] = [];\n let quoted = false,\n field = false;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quoted) {\n if (c === \"\\\\\") i++;\n else if (c === '\"') quoted = false;\n continue;\n }\n if (field) {\n if (c === \"]\") {\n if (text[i + 1] === \"]\") i++;\n else field = false;\n }\n continue;\n }\n if (c === '\"') {\n quoted = true;\n continue;\n }\n if (c === \"[\") {\n field = true;\n continue;\n }\n if (c === \"(\")\n stack.push({\n name:\n text\n .slice(0, i)\n .match(/([A-Za-z_]+)\\s*$/)?.[1]\n ?.toUpperCase() ?? \"\",\n argument: 1,\n });\n else if (c === \")\") stack.pop();\n else if (c === \",\" && stack.length) stack[stack.length - 1]!.argument++;\n }\n const call = stack[stack.length - 1],\n spec = functions.find((f) => f.name === call?.name);\n return spec && call\n ? `${spec.signature} · Argument ${call.argument} — ${spec.description}`\n : FORMULA_EDITOR_HELP;\n}\n","import { useEffect, useId, useRef, useState } from \"react\";\nimport {\n FUNCTION_CATEGORIES,\n FUNCTION_RESULT_TYPES,\n findFormulaFunctions,\n functionCategory,\n functionResultLabel,\n type FunctionCategory,\n} from \"./formulaFunctionCatalogue\";\nimport {\n FORMULA_FUNCTIONS,\n type FormulaFunction,\n} from \"@pythia-software/query-table-core\";\n\nexport function FormulaFunctionBrowser({\n onInsert,\n functions = FORMULA_FUNCTIONS,\n variant = \"card\",\n}: {\n onInsert?: (name: string) => void;\n functions?: readonly FormulaFunction[];\n variant?: \"card\" | \"panel\";\n}) {\n const id = useId();\n const list = useRef<HTMLDivElement>(null);\n const [search, setSearch] = useState(\"\");\n const [category, setCategory] = useState<FunctionCategory | \"all\">(\"all\");\n const [result, setResult] = useState<FormulaFunction[\"result\"] | \"all\">(\n \"all\",\n );\n const [active, setActive] = useState(0);\n const matches = findFormulaFunctions(search, category, result, functions);\n const concept = FUNCTION_CATEGORIES.find((item) => item.id === category);\n\n useEffect(() => {\n // Scroll the list itself without moving the workbench while searching.\n const option = list.current?.children[active] as HTMLElement | undefined;\n const viewport = list.current;\n if (!option || !viewport) return;\n // The positioned list is the option’s offset parent.\n const top = option.offsetTop;\n if (top < viewport.scrollTop) viewport.scrollTop = top;\n else if (\n top + option.offsetHeight >\n viewport.scrollTop + viewport.clientHeight\n )\n viewport.scrollTop = top + option.offsetHeight - viewport.clientHeight;\n }, [active, search, category, result]);\n\n return (\n <aside\n className={`qt-function-library qt-function-library--${variant}`}\n aria-label=\"Function library\"\n >\n {variant === \"card\" && (\n <>\n <h4>Function library</h4>\n <p className=\"qt-muted\">Find a function by name or what it does.</p>\n </>\n )}\n <label className=\"qt-function-search\">\n Search functions\n <input\n className=\"qt-input\"\n type=\"search\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded={matches.length > 0}\n aria-controls={`${id}-results`}\n aria-activedescendant={\n matches[active] ? `${id}-${matches[active]!.name}` : undefined\n }\n placeholder=\"e.g. trim, minimum, date…\"\n value={search}\n onChange={(event) => {\n setSearch(event.target.value);\n setActive(0);\n }}\n onKeyDown={(event) => {\n if (\n event.nativeEvent.isComposing ||\n event.ctrlKey ||\n event.metaKey ||\n event.altKey ||\n !matches.length\n )\n return;\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n setActive(\n (index) =>\n (index +\n (event.key === \"ArrowDown\" ? 1 : matches.length - 1)) %\n matches.length,\n );\n } else if (event.key === \"Enter\") {\n event.preventDefault();\n const fn = matches[active];\n if (fn) onInsert?.(fn.name);\n }\n }}\n />\n </label>\n <div className=\"qt-function-filters\">\n <label>\n Browse by concept\n <select\n value={category}\n onChange={(event) => {\n setCategory(event.target.value as FunctionCategory | \"all\");\n setActive(0);\n }}\n >\n <option value=\"all\">All functions</option>\n {FUNCTION_CATEGORIES.filter((item) =>\n functions.some((fn) => functionCategory(fn) === item.id),\n ).map((item) => (\n <option key={item.id} value={item.id}>\n {item.label}\n </option>\n ))}\n </select>\n </label>\n <label>\n Return type\n <select\n value={result}\n onChange={(event) => {\n setResult(\n event.target.value as FormulaFunction[\"result\"] | \"all\",\n );\n setActive(0);\n }}\n >\n <option value=\"all\">Any type</option>\n {FUNCTION_RESULT_TYPES.map((type) => (\n <option key={type.value} value={type.value}>\n {type.label}\n </option>\n ))}\n </select>\n </label>\n </div>\n {concept && <p className=\"qt-function-concept\">{concept.description}</p>}\n <p className=\"qt-function-count\" aria-live=\"polite\">\n {matches.length} {matches.length === 1 ? \"function\" : \"functions\"}\n </p>\n <div\n ref={list}\n className=\"qt-function-list\"\n id={`${id}-results`}\n role=\"listbox\"\n aria-label=\"Function library results\"\n >\n {matches.map((fn, index) => (\n <button\n type=\"button\"\n role=\"option\"\n id={`${id}-${fn.name}`}\n key={fn.name}\n aria-selected={index === active}\n aria-label={onInsert ? `Insert ${fn.name}` : fn.name}\n disabled={!onInsert}\n onMouseDown={(event) => event.preventDefault()}\n onFocus={() => setActive(index)}\n onClick={() => onInsert?.(fn.name)}\n >\n <span className=\"qt-function-card-title\">\n <strong>{fn.name}</strong>\n <span>{functionResultLabel(fn.result)}</span>\n </span>\n <code>{fn.signature}</code>\n <small>{fn.description}</small>\n <span className=\"qt-function-card-concept\">\n {\n FUNCTION_CATEGORIES.find(\n (item) => item.id === functionCategory(fn),\n )!.label\n }\n </span>\n </button>\n ))}\n </div>\n {!matches.length && (\n <p className=\"qt-function-empty\">\n No functions match. Try a shorter search or a different concept or\n return type.\n </p>\n )}\n <p className=\"qt-function-insert-hint\">\n {onInsert\n ? \"Click a function or use ↑↓ and Enter in search to insert it at the cursor. Select formula text first to wrap it.\"\n : \"Select a formula column to insert a function.\"}\n </p>\n </aside>\n );\n}\n","import {\n FORMULA_FUNCTIONS,\n type FormulaFunction,\n type FormulaType,\n} from \"@pythia-software/query-table-core\";\n\nexport const FUNCTION_CATEGORIES = [\n {\n id: \"aggregates\",\n label: \"Aggregate functions\",\n description: \"Combine values from the rows in each group.\",\n keywords: \"aggregate summary group median average count sum\",\n },\n {\n id: \"strings\",\n label: \"String functions\",\n description: \"Slice, combine, format, and clean text.\",\n keywords: \"string text characters whitespace case concatenate\",\n },\n {\n id: \"matching\",\n label: \"Matching & regex\",\n description: \"Find text, test patterns, and extract matches.\",\n keywords: \"search matching regex regular expression pattern capture\",\n },\n {\n id: \"numbers\",\n label: \"Numbers & statistics\",\n description: \"Round, transform, and compare numbers within a row.\",\n keywords: \"math numeric arithmetic statistics statistical rounding\",\n },\n {\n id: \"logic\",\n label: \"Conditions & missing values\",\n description: \"Choose results, handle errors, and work with empty values.\",\n keywords: \"logic boolean conditional null missing empty fallback error\",\n },\n {\n id: \"conversion\",\n label: \"Type conversion\",\n description: \"Convert values to text, numbers, booleans, or dates.\",\n keywords: \"convert conversion cast type parse\",\n },\n {\n id: \"arrays\",\n label: \"Array functions\",\n description: \"Split, join, count, and organize lists of text.\",\n keywords: \"array list collection elements unique deduplicate\",\n },\n {\n id: \"dates\",\n label: \"Dates & times\",\n description:\n \"Extract date parts, format timestamps, and calculate durations.\",\n keywords: \"date datetime time timestamp calendar duration UTC\",\n },\n] as const;\nexport type FunctionCategory = (typeof FUNCTION_CATEGORIES)[number][\"id\"];\n\nexport const FUNCTION_RESULT_TYPES: {\n value: FormulaFunction[\"result\"];\n label: string;\n}[] = [\n { value: \"text\", label: \"Text\" },\n { value: \"number\", label: \"Number\" },\n { value: \"bool\", label: \"Boolean\" },\n { value: \"datetime\", label: \"Date/time\" },\n { value: \"textarray\", label: \"Text array\" },\n { value: \"branch\", label: \"Depends on arguments\" },\n];\nexport function functionResultLabel(result: FormulaType | \"branch\"): string {\n return (\n FUNCTION_RESULT_TYPES.find((type) => type.value === result)?.label ?? result\n );\n}\n\n/** Concept is separate from return type: LENGTH is a string operation returning a number. */\nexport function functionCategory(fn: FormulaFunction): FunctionCategory {\n if (\n [\"COUNT\", \"COUNT_DISTINCT\", \"SUM\", \"AVG\", \"MIN\", \"MAX\", \"MEDIAN\"].includes(\n fn.name,\n )\n )\n return \"aggregates\";\n if (fn.name.startsWith(\"TO_\")) return \"conversion\";\n if (\n fn.name.startsWith(\"REGEX_\") ||\n [\"CONTAINS\", \"STARTS_WITH\", \"ENDS_WITH\"].includes(fn.name)\n )\n return \"matching\";\n if (fn.name.startsWith(\"ARRAY_\") || [\"SPLIT\", \"JOIN\"].includes(fn.name))\n return \"arrays\";\n if (\n fn.name.includes(\"DATE\") ||\n (fn.args !== \"any\" && fn.args.includes(\"datetime\"))\n )\n return \"dates\";\n if (fn.result === \"branch\" || fn.args === \"any\") return \"logic\";\n if (fn.args.includes(\"text\")) return \"strings\";\n return \"numbers\";\n}\n\nconst SEARCH_ALIASES: Record<string, string> = {\n LEFT: \"prefix beginning first characters\",\n RIGHT: \"suffix ending last characters\",\n SUBSTRING: \"slice middle characters\",\n LENGTH: \"size count characters\",\n LOWER: \"lowercase\",\n UPPER: \"uppercase\",\n CONCAT: \"concatenate combine append\",\n CONCAT_WS: \"concatenate separator combine append\",\n LEAST: \"minimum smallest min\",\n GREATEST: \"maximum largest max\",\n ABS: \"absolute magnitude\",\n SQRT: \"square root\",\n CEIL: \"ceiling round up\",\n FLOOR: \"round down\",\n IF: \"if else decision\",\n COALESCE: \"default first non-null missing fallback\",\n NULLIF: \"equal missing null\",\n IFERROR: \"recover error default fallback\",\n ARRAY_LENGTH: \"size count elements\",\n DATE_DIFF: \"difference elapsed duration\",\n};\nconst normalize = (text: string) =>\n text.toLowerCase().replace(/[_-]/g, \" \").trim();\n\nexport function findFormulaFunctions(\n search: string,\n category: FunctionCategory | \"all\" = \"all\",\n result: FormulaFunction[\"result\"] | \"all\" = \"all\",\n catalogue: readonly FormulaFunction[] = FORMULA_FUNCTIONS,\n): FormulaFunction[] {\n const query = normalize(search);\n const terms = query.split(/\\s+/).filter(Boolean);\n const functions = catalogue.filter((fn) => {\n const concept = functionCategory(fn);\n if (\n (category !== \"all\" && concept !== category) ||\n (result !== \"all\" && fn.result !== result)\n )\n return false;\n const metadata = FUNCTION_CATEGORIES.find((item) => item.id === concept)!;\n const haystack = normalize(\n `${fn.name} ${fn.signature} ${fn.description} ${metadata.label} ${metadata.keywords} ${SEARCH_ALIASES[fn.name] ?? \"\"} ${functionResultLabel(fn.result)}`,\n );\n return terms.every((term) => haystack.includes(term));\n });\n // Exact/prefix name matches appear first; browsing stays alphabetical.\n const rank = (fn: FormulaFunction) =>\n !query\n ? 2\n : normalize(fn.name) === query\n ? 0\n : normalize(fn.name).startsWith(query)\n ? 1\n : 2;\n return functions.sort(\n (a, b) => rank(a) - rank(b) || a.name.localeCompare(b.name),\n );\n}\n"],"mappings":";AAAA;AAAA,EACE,aAAAA;AAAA,EACA,SAAAC;AAAA,EACA;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,OAIK;AACP;AAAA,EACE,qBAAAC;AAAA,EACA;AAAA,OAGK;;;ACfP;AAAA,EACE;AAAA,OAGK;AAEA,IAAM,sBACX;AAkBK,SAAS,eAAe,MAAc,MAAM,KAAK,QAAQ;AAC9D,MAAI,SAAS;AACb,MAAI,aAAa;AACjB,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,QAAQ;AACV,UAAI,MAAM,MAAM;AACd,kBAAU,IAAI,KAAK;AACnB;AAAA,MACF,WAAW,MAAM,IAAK,UAAS;AAAA,IACjC,WAAW,cAAc,GAAG;AAC1B,UAAI,MAAM,KAAK;AACb,YAAI,KAAK,IAAI,CAAC,MAAM,IAAK;AAAA,YACpB,cAAa;AAAA,MACpB;AAAA,IACF,WAAW,MAAM,IAAK,UAAS;AAAA,aACtB,MAAM,IAAK,cAAa;AAAA,EACnC;AACA,SAAO,EAAE,QAAQ,YAAY,QAAQ;AACvC;AAEO,SAAS,mBACd,MACA,OACA,KACA,QACA,WAAW,OACX,YAAwC,mBACb;AAC3B,QAAM,SAAS,KAAK,MAAM,GAAG,KAAK;AAClC,QAAM,EAAE,QAAQ,WAAW,IAAI,eAAe,MAAM,KAAK;AACzD,MAAI,UAAW,CAAC,YAAY,UAAU,IAAM,QAAO;AACnD,QAAM,OAAO,OAAO,MAAM,2BAA2B,IAAI,CAAC,KAAK;AAC/D,MAAI,CAAC,YAAY,aAAa,KAAK,CAAC,KAAM,QAAO;AACjD,QAAM,OACJ,UAAU,MAAM,QAAQ,cAAc,IAAI,aAAa,QAAQ,KAAK;AACtE,MAAI,KAAK;AACT,MAAI,UAAU,OAAO,cAAc,GAAG;AAEpC,aAAS,IAAI,aAAa,GAAG,IAAI,KAAK,QAAQ,KAAK;AACjD,UAAI,KAAK,CAAC,MAAM,KAAK;AACnB,YAAI,KAAK,IAAI,CAAC,MAAM,KAAK;AACvB;AACA;AAAA,QACF;AACA,aAAK,IAAI;AACT;AAAA,MACF;AACA,UAAI,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAM,IAAK;AAAA,IAC3C;AAAA,EACF,WAAW,UAAU,KAAK;AACxB,UAAM,KAAK,MAAM,GAAG,EAAE,MAAM,gBAAgB,IAAI,CAAC,EAAE,UAAU;AAAA,EAC/D;AACA,QAAM,SAAS,UAAU,MAAM,KAAK,OAAO,MAAM,IAAI,EAAE,YAAY;AACnE,QAAM,UAA+B,OAAO,IAAI,CAAC,OAAO;AAAA,IACtD,OAAO,IAAI,EAAE,KAAK,QAAQ,OAAO,IAAI,CAAC;AAAA,IACtC,QAAQ,GAAG,EAAE,KAAK,SAAM,EAAE,IAAI;AAAA,IAC9B,aAAa,EAAE;AAAA,IACf,QAAQ,IAAI,EAAE,KAAK,QAAQ,OAAO,IAAI,CAAC;AAAA,EACzC,EAAE;AACF,MAAI,aAAa,GAAG;AAClB,YAAQ;AAAA,MACN,GAAG,UAAU,IAAI,CAAC,OAAO;AAAA,QACvB,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,aAAa,EAAE;AAAA,QACf,QAAQ,KAAK,EAAE,MAAM,MAAM,EAAE,OAAO,GAAG,EAAE,IAAI;AAAA,QAC7C,aAAa,EAAE,KAAK,SAAS;AAAA,MAC/B,EAAE;AAAA,MACF,GAAG,CAAC,QAAQ,SAAS,QAAQ,OAAO,MAAM,OAAO,MAAM,SAAS,EAAE;AAAA,QAChE,CAAC,WAAW;AAAA,UACV;AAAA,UACA,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,QAAQ;AAAA,MACf,CAAC,WACC,OAAO,MAAM,YAAY,EAAE,WAAW,MAAM,KAC3C,cAAc,KACb,OAAO,OAAO,YAAY,EAAE,SAAS,OAAO,MAAM,CAAC,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;AAEO,SAAS,YACd,MACA,YAAwC,mBAChC;AACR,QAAM,QAA8C,CAAC;AACrD,MAAI,SAAS,OACX,QAAQ;AACV,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,QAAQ;AACV,UAAI,MAAM,KAAM;AAAA,eACP,MAAM,IAAK,UAAS;AAC7B;AAAA,IACF;AACA,QAAI,OAAO;AACT,UAAI,MAAM,KAAK;AACb,YAAI,KAAK,IAAI,CAAC,MAAM,IAAK;AAAA,YACpB,SAAQ;AAAA,MACf;AACA;AAAA,IACF;AACA,QAAI,MAAM,KAAK;AACb,eAAS;AACT;AAAA,IACF;AACA,QAAI,MAAM,KAAK;AACb,cAAQ;AACR;AAAA,IACF;AACA,QAAI,MAAM;AACR,YAAM,KAAK;AAAA,QACT,MACE,KACG,MAAM,GAAG,CAAC,EACV,MAAM,kBAAkB,IAAI,CAAC,GAC5B,YAAY,KAAK;AAAA,QACvB,UAAU;AAAA,MACZ,CAAC;AAAA,aACM,MAAM,IAAK,OAAM,IAAI;AAAA,aACrB,MAAM,OAAO,MAAM,OAAQ,OAAM,MAAM,SAAS,CAAC,EAAG;AAAA,EAC/D;AACA,QAAM,OAAO,MAAM,MAAM,SAAS,CAAC,GACjC,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,IAAI;AACpD,SAAO,QAAQ,OACX,GAAG,KAAK,SAAS,kBAAe,KAAK,QAAQ,WAAM,KAAK,WAAW,KACnE;AACN;;;ACnKA,SAAS,WAAW,OAAO,QAAQ,gBAAgB;;;ACAnD;AAAA,EACE,qBAAAC;AAAA,OAGK;AAEA,IAAM,sBAAsB;AAAA,EACjC;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aACE;AAAA,IACF,UAAU;AAAA,EACZ;AACF;AAGO,IAAM,wBAGP;AAAA,EACJ,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,EAC/B,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,EACnC,EAAE,OAAO,QAAQ,OAAO,UAAU;AAAA,EAClC,EAAE,OAAO,YAAY,OAAO,YAAY;AAAA,EACxC,EAAE,OAAO,aAAa,OAAO,aAAa;AAAA,EAC1C,EAAE,OAAO,UAAU,OAAO,uBAAuB;AACnD;AACO,SAAS,oBAAoB,QAAwC;AAC1E,SACE,sBAAsB,KAAK,CAAC,SAAS,KAAK,UAAU,MAAM,GAAG,SAAS;AAE1E;AAGO,SAAS,iBAAiB,IAAuC;AACtE,MACE,CAAC,SAAS,kBAAkB,OAAO,OAAO,OAAO,OAAO,QAAQ,EAAE;AAAA,IAChE,GAAG;AAAA,EACL;AAEA,WAAO;AACT,MAAI,GAAG,KAAK,WAAW,KAAK,EAAG,QAAO;AACtC,MACE,GAAG,KAAK,WAAW,QAAQ,KAC3B,CAAC,YAAY,eAAe,WAAW,EAAE,SAAS,GAAG,IAAI;AAEzD,WAAO;AACT,MAAI,GAAG,KAAK,WAAW,QAAQ,KAAK,CAAC,SAAS,MAAM,EAAE,SAAS,GAAG,IAAI;AACpE,WAAO;AACT,MACE,GAAG,KAAK,SAAS,MAAM,KACtB,GAAG,SAAS,SAAS,GAAG,KAAK,SAAS,UAAU;AAEjD,WAAO;AACT,MAAI,GAAG,WAAW,YAAY,GAAG,SAAS,MAAO,QAAO;AACxD,MAAI,GAAG,KAAK,SAAS,MAAM,EAAG,QAAO;AACrC,SAAO;AACT;AAEA,IAAM,iBAAyC;AAAA,EAC7C,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,cAAc;AAAA,EACd,WAAW;AACb;AACA,IAAM,YAAY,CAAC,SACjB,KAAK,YAAY,EAAE,QAAQ,SAAS,GAAG,EAAE,KAAK;AAEzC,SAAS,qBACd,QACA,WAAqC,OACrC,SAA4C,OAC5C,YAAwCA,oBACrB;AACnB,QAAM,QAAQ,UAAU,MAAM;AAC9B,QAAM,QAAQ,MAAM,MAAM,KAAK,EAAE,OAAO,OAAO;AAC/C,QAAM,YAAY,UAAU,OAAO,CAAC,OAAO;AACzC,UAAM,UAAU,iBAAiB,EAAE;AACnC,QACG,aAAa,SAAS,YAAY,YAClC,WAAW,SAAS,GAAG,WAAW;AAEnC,aAAO;AACT,UAAM,WAAW,oBAAoB,KAAK,CAAC,SAAS,KAAK,OAAO,OAAO;AACvE,UAAM,WAAW;AAAA,MACf,GAAG,GAAG,IAAI,IAAI,GAAG,SAAS,IAAI,GAAG,WAAW,IAAI,SAAS,KAAK,IAAI,SAAS,QAAQ,IAAI,eAAe,GAAG,IAAI,KAAK,EAAE,IAAI,oBAAoB,GAAG,MAAM,CAAC;AAAA,IACxJ;AACA,WAAO,MAAM,MAAM,CAAC,SAAS,SAAS,SAAS,IAAI,CAAC;AAAA,EACtD,CAAC;AAED,QAAM,OAAO,CAAC,OACZ,CAAC,QACG,IACA,UAAU,GAAG,IAAI,MAAM,QACrB,IACA,UAAU,GAAG,IAAI,EAAE,WAAW,KAAK,IACjC,IACA;AACV,SAAO,UAAU;AAAA,IACf,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EAC5D;AACF;;;ADvJA;AAAA,EACE,qBAAAC;AAAA,OAEK;AA2CC,mBACE,KADF;AAzCD,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA,YAAYA;AAAA,EACZ,UAAU;AACZ,GAIG;AACD,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,OAAuB,IAAI;AACxC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,EAAE;AACvC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmC,KAAK;AACxE,QAAM,CAAC,QAAQ,SAAS,IAAI;AAAA,IAC1B;AAAA,EACF;AACA,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,CAAC;AACtC,QAAM,UAAU,qBAAqB,QAAQ,UAAU,QAAQ,SAAS;AACxE,QAAM,UAAU,oBAAoB,KAAK,CAAC,SAAS,KAAK,OAAO,QAAQ;AAEvE,YAAU,MAAM;AAEd,UAAM,SAAS,KAAK,SAAS,SAAS,MAAM;AAC5C,UAAM,WAAW,KAAK;AACtB,QAAI,CAAC,UAAU,CAAC,SAAU;AAE1B,UAAM,MAAM,OAAO;AACnB,QAAI,MAAM,SAAS,UAAW,UAAS,YAAY;AAAA,aAEjD,MAAM,OAAO,eACb,SAAS,YAAY,SAAS;AAE9B,eAAS,YAAY,MAAM,OAAO,eAAe,SAAS;AAAA,EAC9D,GAAG,CAAC,QAAQ,QAAQ,UAAU,MAAM,CAAC;AAErC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,4CAA4C,OAAO;AAAA,MAC9D,cAAW;AAAA,MAEV;AAAA,oBAAY,UACX,iCACE;AAAA,8BAAC,QAAG,8BAAgB;AAAA,UACpB,oBAAC,OAAE,WAAU,YAAW,sDAAwC;AAAA,WAClE;AAAA,QAEF,qBAAC,WAAM,WAAU,sBAAqB;AAAA;AAAA,UAEpC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,MAAK;AAAA,cACL,MAAK;AAAA,cACL,qBAAkB;AAAA,cAClB,iBAAe,QAAQ,SAAS;AAAA,cAChC,iBAAe,GAAG,EAAE;AAAA,cACpB,yBACE,QAAQ,MAAM,IAAI,GAAG,EAAE,IAAI,QAAQ,MAAM,EAAG,IAAI,KAAK;AAAA,cAEvD,aAAY;AAAA,cACZ,OAAO;AAAA,cACP,UAAU,CAAC,UAAU;AACnB,0BAAU,MAAM,OAAO,KAAK;AAC5B,0BAAU,CAAC;AAAA,cACb;AAAA,cACA,WAAW,CAAC,UAAU;AACpB,oBACE,MAAM,YAAY,eAClB,MAAM,WACN,MAAM,WACN,MAAM,UACN,CAAC,QAAQ;AAET;AACF,oBAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;AACxD,wBAAM,eAAe;AACrB;AAAA,oBACE,CAAC,WACE,SACE,MAAM,QAAQ,cAAc,IAAI,QAAQ,SAAS,MACpD,QAAQ;AAAA,kBACZ;AAAA,gBACF,WAAW,MAAM,QAAQ,SAAS;AAChC,wBAAM,eAAe;AACrB,wBAAM,KAAK,QAAQ,MAAM;AACzB,sBAAI,GAAI,YAAW,GAAG,IAAI;AAAA,gBAC5B;AAAA,cACF;AAAA;AAAA,UACF;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,uBACb;AAAA,+BAAC,WAAM;AAAA;AAAA,YAEL;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,gBACP,UAAU,CAAC,UAAU;AACnB,8BAAY,MAAM,OAAO,KAAiC;AAC1D,4BAAU,CAAC;AAAA,gBACb;AAAA,gBAEA;AAAA,sCAAC,YAAO,OAAM,OAAM,2BAAa;AAAA,kBAChC,oBAAoB;AAAA,oBAAO,CAAC,SAC3B,UAAU,KAAK,CAAC,OAAO,iBAAiB,EAAE,MAAM,KAAK,EAAE;AAAA,kBACzD,EAAE,IAAI,CAAC,SACL,oBAAC,YAAqB,OAAO,KAAK,IAC/B,eAAK,SADK,KAAK,EAElB,CACD;AAAA;AAAA;AAAA,YACH;AAAA,aACF;AAAA,UACA,qBAAC,WAAM;AAAA;AAAA,YAEL;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,gBACP,UAAU,CAAC,UAAU;AACnB;AAAA,oBACE,MAAM,OAAO;AAAA,kBACf;AACA,4BAAU,CAAC;AAAA,gBACb;AAAA,gBAEA;AAAA,sCAAC,YAAO,OAAM,OAAM,sBAAQ;AAAA,kBAC3B,sBAAsB,IAAI,CAAC,SAC1B,oBAAC,YAAwB,OAAO,KAAK,OAClC,eAAK,SADK,KAAK,KAElB,CACD;AAAA;AAAA;AAAA,YACH;AAAA,aACF;AAAA,WACF;AAAA,QACC,WAAW,oBAAC,OAAE,WAAU,uBAAuB,kBAAQ,aAAY;AAAA,QACpE,qBAAC,OAAE,WAAU,qBAAoB,aAAU,UACxC;AAAA,kBAAQ;AAAA,UAAO;AAAA,UAAE,QAAQ,WAAW,IAAI,aAAa;AAAA,WACxD;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,WAAU;AAAA,YACV,IAAI,GAAG,EAAE;AAAA,YACT,MAAK;AAAA,YACL,cAAW;AAAA,YAEV,kBAAQ,IAAI,CAAC,IAAI,UAChB;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,IAAI,GAAG,EAAE,IAAI,GAAG,IAAI;AAAA,gBAEpB,iBAAe,UAAU;AAAA,gBACzB,cAAY,WAAW,UAAU,GAAG,IAAI,KAAK,GAAG;AAAA,gBAChD,UAAU,CAAC;AAAA,gBACX,aAAa,CAAC,UAAU,MAAM,eAAe;AAAA,gBAC7C,SAAS,MAAM,UAAU,KAAK;AAAA,gBAC9B,SAAS,MAAM,WAAW,GAAG,IAAI;AAAA,gBAEjC;AAAA,uCAAC,UAAK,WAAU,0BACd;AAAA,wCAAC,YAAQ,aAAG,MAAK;AAAA,oBACjB,oBAAC,UAAM,8BAAoB,GAAG,MAAM,GAAE;AAAA,qBACxC;AAAA,kBACA,oBAAC,UAAM,aAAG,WAAU;AAAA,kBACpB,oBAAC,WAAO,aAAG,aAAY;AAAA,kBACvB,oBAAC,UAAK,WAAU,4BAEZ,8BAAoB;AAAA,oBAClB,CAAC,SAAS,KAAK,OAAO,iBAAiB,EAAE;AAAA,kBAC3C,EAAG,OAEP;AAAA;AAAA;AAAA,cApBK,GAAG;AAAA,YAqBV,CACD;AAAA;AAAA,QACH;AAAA,QACC,CAAC,QAAQ,UACR,oBAAC,OAAE,WAAU,qBAAoB,6FAGjC;AAAA,QAEF,oBAAC,OAAE,WAAU,2BACV,qBACG,+HACA,iDACN;AAAA;AAAA;AAAA,EACF;AAEJ;;;AFgIQ,gBAAAC,MA6DE,QAAAC,aA7DF;AArRO,SAAR,cAA+B;AAAA,EACpC;AAAA,EACA;AAAA,EACA,YAAYC;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AACT,GAAuB;AACrB,QAAM,KAAKC,OAAM;AACjB,QAAM,SAASC,QAAmC,IAAI;AACtD,QAAM,eAAeA,QAAO,KAAK;AACjC,QAAM,YAAYA,QAAO,KAAK;AAE9B,QAAM,SAASA,QAGZ,EAAE,OAAO,QAAQ,CAAC,EAAE,CAAC;AACxB,QAAM,YAAY,CAAC,SAAiB;AAClC,UAAM,WAAW,OAAO,QAAQ;AAChC,QAAI,aAAa,KAAM;AACvB,QAAI,OAAO;AACX,WACE,OAAO,SAAS,UAChB,OAAO,KAAK,UACZ,SAAS,IAAI,MAAM,KAAK,IAAI;AAE5B;AACF,QAAI,SAAS,SAAS,QACpB,SAAS,KAAK;AAChB,WACE,SAAS,QACT,SAAS,QACT,SAAS,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,GACxC;AACA;AACA;AAAA,IACF;AACA,UAAM,QAAQ,SAAS;AACvB,WAAO,QAAQ,SAAS,OAAO,QAAQ,OACpC;AAAA,MACC,CAAC,EAAE,MAAM,MAAM,MACb,EAAE,QAAQ,QAAQ,OAAO,WACzB,EAAE,SAAS,QAAQ,QAAQ;AAAA,IAC/B,EACC,IAAI,CAAC,EAAE,MAAM,MAAM,OAAO;AAAA,MACzB,MAAM,QAAQ,SAAS,OAAO,QAAQ;AAAA,MACtC,OAAO,SAAS,SAAS,QAAQ,QAAQ;AAAA,IAC3C,EAAE;AACJ,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACA,QAAM,YAAYA,QAAO,EAAE,OAAO,GAAG,KAAK,EAAE,CAAC;AAC7C,QAAM,gBAAgBA,QAAO,OAAO;AACpC,gBAAc,UAAU;AACxB,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,CAAC;AACpC,QAAM,CAAC,aAAa,cAAc,IAAIA;AAAA,IACpC;AAAA,EACF;AACA,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAS,CAAC;AACtC,QAAM,CAAC,YAAY,aAAa,IAAIA,UAI1B,IAAI;AACd,QAAM,UAAU,cAAe,aAAa,QAAQ,MAAM,GAAG,EAAE,KAAK,CAAC,IAAK,CAAC;AAC3E,QAAM,OAAO,cAAc,YAAY,MAAM,MAAM,GAAG,KAAK,GAAG,SAAS,IAAI;AAE3E,EAAAC,WAAU,MAAM;AAEd,UAAM,QAAQ,OAAO;AACrB,QAAI,SAAS,MAAM,UAAU,OAAO;AAClC,YAAM,QAAQ;AACd,aAAO,UAAU,EAAE,OAAO,QAAQ,CAAC,EAAE;AACrC,eAAS,MAAM,cAAc;AAC7B,qBAAe,IAAI;AAAA,IACrB;AACA,kBAAc,IAAI;AAClB,UAAM,QAAQ,WAAW,MAAM;AAC7B,UAAI;AACF,sBAAc,QAAQ,KAAK;AAC3B,sBAAc,IAAI;AAAA,MACpB,SAAS,OAAO;AACd,cAAM,OAAO,iBAAiB,eAAe,MAAM,OAAO;AAC1D,cAAM,KAAK,iBAAiB,eAAe,MAAM,KAAK,MAAM;AAC5D,sBAAc;AAAA,UACZ,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC9D,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,MAAM,MAAM,CAAC;AAAA,UAC9C,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,MAAM,CAAC;AAAA,QAC5C,CAAC;AAAA,MACH;AAAA,IACF,GAAG,GAAG;AACN,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,KAAK,CAAC;AAEV,EAAAA,WAAU,MAAM;AACd,QAAI,OAAO,QAAS,WAAU,OAAO,OAAO;AAAA,EAC9C,GAAG,CAAC,OAAO,CAAC;AAEZ,EAAAA,WAAU,MAAM;AACd,aACG,eAAe,GAAG,EAAE,WAAW,MAAM,EAAE,GACtC,iBAAiB,EAAE,OAAO,UAAU,CAAC;AAAA,EAC3C,GAAG,CAAC,QAAQ,EAAE,CAAC;AAEf,QAAM,UAAU,CAAC,WAAW,UAAU;AACpC,UAAM,QAAQ,OAAO;AACrB,QAAI,CAAC,eAAe,CAAC,SAAS,UAAU,QAAS;AACjD,cAAU,UAAU;AAAA,MAClB,OAAO,MAAM;AAAA,MACb,KAAK,MAAM;AAAA,IACb;AACA,aAAS,MAAM,cAAc;AAC7B,cAAU,CAAC;AACX;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,CACb,MACA,IACA,MACA,cAAc,KAAK,QACnB,SACG;AACH,UAAM,QAAQ,OAAO;AACrB,QAAI,CAAC,MAAO;AACZ,UAAM,MAAM;AACZ,UAAM,kBAAkB,MAAM,EAAE;AAChC,iBAAa,UAAU;AACvB,QAAI;AAGF,YAAM,SAAS,MAAM;AACrB,UAAI;AACF,iBAAS,cAAc,cAAc,OAAO,IAAI;AAAA,MAClD,QAAQ;AAAA,MAER;AACA,UAAI,MAAM,UAAU,OAAQ,OAAM,aAAa,MAAM,MAAM,IAAI,KAAK;AAAA,IACtE,UAAE;AACA,mBAAa,UAAU;AAAA,IACzB;AACA,cAAU,MAAM,KAAK;AACrB,QAAI;AACF,aAAO,QAAQ,OAAO,KAAK;AAAA,QACzB,MAAM,OAAO,KAAK;AAAA,QAClB,OAAO,OAAO,KAAK;AAAA,MACrB,CAAC;AACH,UAAM,kBAAkB,OAAO,aAAa,OAAO,WAAW;AAC9D,aAAS,MAAM,cAAc;AAC7B,mBAAe,IAAI;AACnB,aAAS,MAAM,KAAK;AAAA,EACtB;AAEA,QAAM,SAAS,CAAC,WAA8B;AAC5C,QAAI;AACF;AAAA,QACE,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO,OAAO,SAAS,IAAI,IACvB,EAAE,MAAM,OAAO,OAAO,SAAS,GAAG,OAAO,OAAO,OAAO,SAAS,EAAE,IAClE;AAAA,MACN;AAAA,EACJ;AAEA,QAAM,iBAAiB,CAAC,SAAiB;AACvC,UAAM,QAAQ,OAAO;AACrB,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,MAAM;AACnB,UAAM,KAAK,MAAM;AACjB,UAAM,WAAW,MAAM,MAAM,MAAM,MAAM,EAAE;AAC3C;AAAA,MACE;AAAA,MACA;AAAA,MACA,GAAG,IAAI,IAAI,QAAQ;AAAA,MACnB,KAAK,SAAS,SAAS,SAAS;AAAA,MAChC,EAAE,MAAM,KAAK,QAAQ,OAAO,KAAK,SAAS,SAAS,SAAS,EAAE;AAAA,IAChE;AAAA,EACF;AACA,sBAAoB,YAAY,OAAO,EAAE,eAAe,EAAE;AAE1D,QAAM,YAAY,CAAC,UAA8C;AAC/D,UAAM,QAAQ,MAAM;AACpB,QAAI,UAAU,WAAW,MAAM,YAAY,YAAa;AACxD,QAAI,eAAe,MAAM,WAAW,MAAM,SAAS,SAAS;AAC1D,YAAM,eAAe;AACrB,cAAQ,IAAI;AACZ;AAAA,IACF;AACA,QAAI,QAAQ,QAAQ;AAClB,UAAI,MAAM,QAAQ,UAAU;AAC1B,cAAM,eAAe;AACrB,cAAM,gBAAgB;AACtB,uBAAe,IAAI;AACnB;AAAA,MACF;AACA,UAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;AACxD,cAAM,eAAe;AACrB;AAAA,UACE,CAAC,WACE,SAAS,MAAM,QAAQ,cAAc,IAAI,QAAQ,SAAS,MAC3D,QAAQ;AAAA,QACZ;AACA;AAAA,MACF;AACA,UAAI,MAAM,QAAQ,SAAS;AACzB,cAAM,eAAe;AACrB,cAAM,SAAS,QAAQ,MAAM;AAC7B,YAAI,OAAQ,QAAO,MAAM;AACzB;AAAA,MACF;AAAA,IACF;AACA,QAAI,MAAM,WAAW,MAAM,WAAW,MAAM,OAAQ;AACpD,UAAM,QAAQ,MAAM,gBAClB,MAAM,MAAM;AACd,UAAM,UAAU,eAAe,MAAM,OAAO,KAAK;AACjD,UAAM,QAAQ,MAAM,QAAQ,MAAM,MAAM,MAAM,QAAQ,MAAM,MAAM;AAClE,QACE,SACA,CAAC,QAAQ,UACT,QAAQ,aAAa,MACpB,UAAU,OACT,QAAQ,MAAM,MAAM,UACpB,WAAW,KAAK,MAAM,MAAM,GAAG,CAAE,IACnC;AACA,YAAM,eAAe;AACrB,YAAMC,aAAY,MAAM,MAAM,MAAM,OAAO,GAAG;AAC9C,aAAO,OAAO,KAAK,MAAM,MAAMA,aAAY,OAAOA,WAAU,SAAS,GAAG;AAAA,QACtE,MAAM;AAAA,QACN,OAAOA,WAAU,SAAS;AAAA,MAC5B,CAAC;AAAA,IACH,WACE,UAAU,OACV,MAAM,MAAM,KAAK,MAAM,MAAM,OAC7B,OAAO,QAAQ,OAAO,KAAK,CAAC,SAAS,KAAK,UAAU,KAAK,MACvD,MAAM,QAAQ,OAAO,CAAC,QAAQ,UAAU,QAAQ,aAAa,KAC5D,MAAM,QAAQ,OAAO,QAAQ,UAAU,CAAC,QAAQ,UACnD;AACA,YAAM,eAAe;AACrB,aAAO,QAAQ,SAAS,OAAO,QAAQ,OAAO;AAAA,QAC5C,CAAC,SAAS,KAAK,UAAU;AAAA,MAC3B;AACA,YAAM,kBAAkB,QAAQ,GAAG,QAAQ,CAAC;AAC5C,eAAS,QAAQ,CAAC;AAClB,qBAAe,IAAI;AAAA,IACrB,WACE,MAAM,QAAQ,eACd,UAAU,OACV,QAAQ,KACR,CAAC,MAAM,MAAM,IAAI,EAAE,SAAS,MAAM,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,MAClE,CAAC,QAAQ,UACP,MAAM,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,QAAQ,CAAC,QAAQ,UAChE;AACA,YAAM,eAAe;AACrB,aAAO,QAAQ,GAAG,QAAQ,GAAG,EAAE;AAAA,IACjC;AAAA,EACF;AAEA,SACE,gBAAAN,MAAC,SAAI,WAAU,qBACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,qBACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,KAAK,CAAC,UAAU;AACd,mBAAO,UAAU;AACjB,gBAAI,SAAU,UAAS,UAAU;AAAA,UACnC;AAAA,UACA,WAAU;AAAA,UACV,cAAY;AAAA,UACZ,oBAAkB,GAAG,EAAE,QAAQ,aAAa,IAAI,EAAE,WAAW,EAAE;AAAA,UAC/D,gBAAc,aAAa,OAAO;AAAA,UAClC,qBAAmB,cAAc,SAAS;AAAA,UAC1C,iBAAe,QAAQ,SAAS,GAAG,EAAE,iBAAiB;AAAA,UACtD,yBACE,QAAQ,SAAS,GAAG,EAAE,WAAW,MAAM,KAAK;AAAA,UAE9C,cAAc;AAAA,UACd;AAAA,UACA,YAAY;AAAA,UACZ,gBAAe;AAAA,UACf,aAAY;AAAA,UACZ,UAAU,CAAC,UAAU;AACnB,gBAAI,aAAa,QAAS;AAC1B,sBAAU,MAAM,cAAc,KAAK;AACnC,qBAAS,MAAM,cAAc,KAAK;AAClC,gBAAI,CAAC,UAAU,QAAS,SAAQ;AAAA,UAClC;AAAA,UACA,UAAU,CAAC,UAAU;AACnB,qBAAS,MAAM,cAAc,cAAc;AAC3C,kBAAM,QAAQ,MAAM;AACpB,gBACE,CAAC,aAAa,YACb,MAAM,mBAAmB,UAAU,QAAQ,SAC1C,MAAM,iBAAiB,UAAU,QAAQ;AAE3C,6BAAe,IAAI;AAAA,UACvB;AAAA,UACA;AAAA,UACA,oBAAoB,MAAM;AACxB,sBAAU,UAAU;AACpB,2BAAe,IAAI;AAAA,UACrB;AAAA,UACA,kBAAkB,MAAM;AACtB,sBAAU,UAAU;AACpB,oBAAQ;AAAA,UACV;AAAA,UACA,QAAQ,MAAM,eAAe,IAAI;AAAA,UACjC;AAAA;AAAA,MACF;AAAA,MACA,gBAAAC,MAAC,SAAI,WAAU,oBACZ;AAAA,uBACC,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,aAAa,CAAC,UAAU,MAAM,eAAe;AAAA,YAC7C,SAAS,MAAM;AACb,qBAAO,SAAS,MAAM;AACtB,sBAAQ,IAAI;AAAA,YACd;AAAA,YACD;AAAA;AAAA,QAED;AAAA,QAEF,gBAAAC,MAAC,UAAK;AAAA;AAAA,UACE,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,IAAI,EAAE;AAAA,UAAO;AAAA,UAAS;AAAA,UACvD,QAAQ,MAAM,MAAM,GAAG,KAAK,EAAE,YAAY,IAAI;AAAA,WACjD;AAAA,SACF;AAAA,MACC,QAAQ,SAAS,KAChB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,+BAA4B;AAAA,UAE5B;AAAA,4BAAAD;AAAA,cAAC;AAAA;AAAA,gBACC,IAAI,GAAG,EAAE;AAAA,gBACT,MAAK;AAAA,gBACL,cAAW;AAAA,gBACX,aAAa,CAAC,UAAU,MAAM,eAAe;AAAA,gBAE5C,kBAAQ,IAAI,CAAC,QAAQ,UACpB,gBAAAC;AAAA,kBAAC;AAAA;AAAA,oBAEC,IAAI,GAAG,EAAE,WAAW,KAAK;AAAA,oBACzB,MAAK;AAAA,oBACL,iBAAe,UAAU;AAAA,oBACzB,OAAO,OAAO;AAAA,oBACd,SAAS,MAAM,OAAO,MAAM;AAAA,oBAE5B;AAAA,sCAAAD,KAAC,YAAQ,iBAAO,OAAM;AAAA,sBACtB,gBAAAA,KAAC,WAAO,iBAAO,QAAO;AAAA;AAAA;AAAA,kBARjB,OAAO;AAAA,gBASd,CACD;AAAA;AAAA,YACH;AAAA,YACA,gBAAAC,MAAC,OACE;AAAA,sBAAQ,MAAM,GAAG;AAAA,cAAY;AAAA,eAEhC;AAAA,YACC,eAAe,YAAY,QAAQ,SAAS,QAAQ,UACnD,gBAAAA,MAAC,OAAE;AAAA;AAAA,cAA0B,QAAQ;AAAA,cAAO;AAAA,eAAa;AAAA;AAAA;AAAA,MAE7D;AAAA,MAEF,gBAAAD,KAAC,OAAE,IAAI,GAAG,EAAE,SAAS,WAAU,mBAAkB,aAAU,UACxD,gBACH;AAAA,MACC,cACC,gBAAAC,MAAC,SAAI,IAAI,GAAG,EAAE,UAAU,WAAU,oBAAmB,MAAK,UACvD;AAAA,mBAAW;AAAA,QAAS;AAAA,QACrB,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAM;AACb,qBAAO,SAAS,MAAM;AACtB,qBAAO,SAAS;AAAA,gBACd,WAAW;AAAA,gBACX,WAAW;AAAA,cACb;AACA,uBAAS,WAAW,IAAI;AAAA,YAC1B;AAAA,YACD;AAAA;AAAA,QAED;AAAA,SACF;AAAA,OAEJ;AAAA,IACC,eACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU;AAAA;AAAA,IACZ;AAAA,KAEJ;AAEJ;","names":["useEffect","useId","useRef","useState","FORMULA_FUNCTIONS","FORMULA_FUNCTIONS","FORMULA_FUNCTIONS","jsx","jsxs","FORMULA_FUNCTIONS","useId","useRef","useState","useEffect","selection"]}
|