@columenlabs/lumen-ui 0.1.34 → 0.1.35
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/formula-input.js +19 -9
- package/dist/view-formulas.js +1 -1
- package/package.json +2 -2
package/dist/formula-input.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { renameFormula } from '@columenlabs/lumen-ui-types/views';
|
|
2
|
+
import { FORMULA_FUNCTIONS, renameFormula } from '@columenlabs/lumen-ui-types/views';
|
|
3
3
|
// Formula box with autocomplete: a formula reads fields by name, where they
|
|
4
4
|
// come from and their key (`symbol.price`, `frame.earnings_next_week.eps`, a formula's bare key),
|
|
5
5
|
// but people know fields by their labels (Price). Typing a word opens a LumenSelectorList under
|
|
@@ -8,20 +8,29 @@ import { renameFormula } from '@columenlabs/lumen-ui-types/views';
|
|
|
8
8
|
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
9
9
|
import { LumenSelectorList, fuzzyScore } from './lumen-selector.js';
|
|
10
10
|
import { Textarea } from './ui/textarea.js';
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* The functions a formula can call, offered beside the fields: the two roll-ups, then the date,
|
|
13
|
+
* text and number functions, each with how to call it under its name.
|
|
14
|
+
*/
|
|
12
15
|
const FUNCTIONS = [
|
|
13
16
|
{
|
|
14
17
|
value: 'group_sum("")',
|
|
15
18
|
label: 'group_sum',
|
|
16
|
-
|
|
17
|
-
group: '
|
|
19
|
+
description: 'group_sum("field") · a field summed over its group',
|
|
20
|
+
group: 'Sums',
|
|
18
21
|
},
|
|
19
22
|
{
|
|
20
23
|
value: 'total_sum("")',
|
|
21
24
|
label: 'total_sum',
|
|
22
|
-
|
|
23
|
-
group: '
|
|
25
|
+
description: 'total_sum("field") · a field summed over every row',
|
|
26
|
+
group: 'Sums',
|
|
24
27
|
},
|
|
28
|
+
...FORMULA_FUNCTIONS.map((f) => ({
|
|
29
|
+
value: `${f.name}()`,
|
|
30
|
+
label: f.name,
|
|
31
|
+
description: `${f.call} · ${f.detail}`,
|
|
32
|
+
group: `${f.group} functions`,
|
|
33
|
+
})),
|
|
25
34
|
];
|
|
26
35
|
/** The name the caret is in (dots included), from its start to the caret. */
|
|
27
36
|
function wordAt(text, caret) {
|
|
@@ -55,10 +64,11 @@ export function FormulaInput({ id, value, onChange, fields, invalid, placeholder
|
|
|
55
64
|
if (caret === null)
|
|
56
65
|
return;
|
|
57
66
|
const end = wordEnd(value, caret);
|
|
58
|
-
const
|
|
67
|
+
const back = o.value.endsWith('("")') ? 2 : o.value.endsWith('()') ? 1 : 0;
|
|
59
68
|
const next = value.slice(0, start) + o.value + value.slice(end);
|
|
60
|
-
// A function's caret goes between
|
|
61
|
-
|
|
69
|
+
// A function's caret goes inside it: between a sum's quotes, ready for the field it sums, or
|
|
70
|
+
// between the brackets, ready for its arguments.
|
|
71
|
+
moveTo.current = start + o.value.length - back;
|
|
62
72
|
onChange(next);
|
|
63
73
|
};
|
|
64
74
|
const track = () => setCaret(box.current?.selectionStart ?? null);
|
package/dist/view-formulas.js
CHANGED
|
@@ -227,7 +227,7 @@ export function FormulaForm({ formula: f, issue, blank, fields, onChange, onRemo
|
|
|
227
227
|
const to = guessField(name, fields);
|
|
228
228
|
return to ? [{ name, to }] : [];
|
|
229
229
|
});
|
|
230
|
-
return (_jsxs("div", { className: row ? 'col-span-full grid gap-3 border-t bg-muted/30 px-3 py-3 md:pl-10' : 'grid gap-3 p-4', children: [_jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: `${id}-label`, children: "Label" }), _jsx(Input, { id: `${id}-label`, value: f.label, onChange: (e) => onChange({ label: e.target.value }) })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: `${id}-key`, children: "Key" }), _jsx(Input, { id: `${id}-key`, className: "font-mono text-xs", value: f.key, onChange: (e) => onChange({ key: e.target.value }) })] })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: `${id}-expr`, children: "Expression" }), _jsx(FormulaInput, { id: `${id}-expr`, invalid: !!issue, fields: fields, placeholder: 'Type a field:
|
|
230
|
+
return (_jsxs("div", { className: row ? 'col-span-full grid gap-3 border-t bg-muted/30 px-3 py-3 md:pl-10' : 'grid gap-3 p-4', children: [_jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: `${id}-label`, children: "Label" }), _jsx(Input, { id: `${id}-label`, value: f.label, onChange: (e) => onChange({ label: e.target.value }) })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: `${id}-key`, children: "Key" }), _jsx(Input, { id: `${id}-key`, className: "font-mono text-xs", value: f.key, onChange: (e) => onChange({ key: e.target.value }) })] })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { htmlFor: `${id}-expr`, children: "Expression" }), _jsx(FormulaInput, { id: `${id}-expr`, invalid: !!issue, fields: fields, placeholder: 'Type a field or a function: year(date), round(value / group_sum("value") * 100, 1)', value: f.expr, onChange: setExpr }), issue ? (_jsxs("p", { role: "alert", className: "flex flex-wrap items-center gap-1.5 text-xs text-destructive", children: [_jsx(CircleAlertIcon, { className: "size-3.5" }), fixes.length
|
|
231
231
|
? fixes.map(({ name, to }) => (_jsxs("span", { className: "flex items-center gap-1.5", children: ["No field ", name, ". Did you mean ", _jsx("code", { className: "font-mono", children: to.value }), " (", to.label, ")?", _jsxs(Button, { variant: "outline", size: "xs", onClick: () => setExpr(swapWord(f.expr, name, to.value)), children: [_jsx(WandSparklesIcon, {}), "Fix"] })] }, name)))
|
|
232
232
|
: issue] })) : blank ? (_jsxs("p", { className: "flex items-center gap-1.5 text-xs text-warning", children: [_jsx(CircleAlertIcon, { className: "size-3.5" }), "Reads fine, but ", blank] })) : (_jsxs("p", { className: "flex items-center gap-1.5 text-xs text-gain", children: [_jsx(CheckIcon, { className: "size-3.5" }), "Reads fine"] }))] }), _jsxs("div", { className: "flex flex-wrap items-end gap-3", children: [_jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { children: "Format" }), _jsx(LumenSelector, { label: "Format", size: "sm", className: "w-40", options: [
|
|
233
233
|
...formatOptions(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
4
4
|
"description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@codemirror/lang-javascript": "6.2.5",
|
|
42
42
|
"@codemirror/lang-json": "6.0.2",
|
|
43
43
|
"@codemirror/lang-sql": "6.10.0",
|
|
44
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
44
|
+
"@columenlabs/lumen-ui-types": "0.1.35",
|
|
45
45
|
"@dnd-kit/core": "6.3.1",
|
|
46
46
|
"@dnd-kit/sortable": "10.0.0",
|
|
47
47
|
"@dnd-kit/utilities": "3.2.2",
|