@braincrew-lab/langchain-canvas 0.2.0 → 0.3.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.ko.md +23 -11
- package/README.md +23 -11
- package/dist/{ChartRenderer-AAWVGKV5.js → ChartRenderer-ABRQ5YFN.js} +49 -31
- package/dist/{DocumentRenderer-NBRBPYU6.js → DocumentRenderer-YTEMC3Z4.js} +17 -12
- package/dist/{PdfRenderer-DPQT4E7O.js → PdfRenderer-GDA67MES.js} +11 -10
- package/dist/{SlidesRenderer-6ZGHXTQX.js → SlidesRenderer-JNPXNTNJ.js} +152 -65
- package/dist/TableRenderer-BJQE2HMO.js +636 -0
- package/dist/{chunk-UL5F66PN.js → chunk-FSFOURG5.js} +1 -1
- package/dist/chunk-QMOJEGRH.js +207 -0
- package/dist/{chunk-S54GJDSJ.js → chunk-ZLXAWRUP.js} +16 -0
- package/dist/index.d.ts +753 -5
- package/dist/index.js +1897 -195
- package/dist/styles.css +379 -4
- package/package.json +26 -2
- package/dist/TableRenderer-VKDD3CB6.js +0 -419
|
@@ -1,419 +0,0 @@
|
|
|
1
|
-
import { loadOptional } from './chunk-YZZSJJMQ.js';
|
|
2
|
-
import { useCanvasStore } from './chunk-S54GJDSJ.js';
|
|
3
|
-
import { lazy, useMemo, useState, useRef, useEffect, useCallback, Suspense } from 'react';
|
|
4
|
-
import '@fortune-sheet/react/dist/index.css';
|
|
5
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
-
|
|
7
|
-
// src/io/formula.ts
|
|
8
|
-
var EMPTY = /* @__PURE__ */ new Map();
|
|
9
|
-
async function computeFormulas(columns, rows) {
|
|
10
|
-
const formulaCells = [];
|
|
11
|
-
rows.forEach(
|
|
12
|
-
(row, dataIdx) => columns.forEach((col, c) => {
|
|
13
|
-
const v = row[col.key];
|
|
14
|
-
if (typeof v === "string" && v.startsWith("=")) formulaCells.push({ dataIdx, col: c, formula: v });
|
|
15
|
-
})
|
|
16
|
-
);
|
|
17
|
-
if (formulaCells.length === 0) return EMPTY;
|
|
18
|
-
const mod = await loadOptional("fast-formula-parser", () => import('fast-formula-parser'));
|
|
19
|
-
const FormulaParser = mod.default ?? mod;
|
|
20
|
-
const memo = /* @__PURE__ */ new Map();
|
|
21
|
-
const inProgress = /* @__PURE__ */ new Set();
|
|
22
|
-
const rawAt = (row, col) => {
|
|
23
|
-
const colIdx = col - 1;
|
|
24
|
-
if (row === 1) return columns[colIdx]?.label ?? columns[colIdx]?.key ?? null;
|
|
25
|
-
const dataRow = rows[row - 2];
|
|
26
|
-
const column = columns[colIdx];
|
|
27
|
-
if (!dataRow || !column) return null;
|
|
28
|
-
const v = dataRow[column.key];
|
|
29
|
-
return v ?? null;
|
|
30
|
-
};
|
|
31
|
-
const valueAt = (row, col) => {
|
|
32
|
-
const raw = rawAt(row, col);
|
|
33
|
-
if (typeof raw !== "string" || !raw.startsWith("=")) return raw ?? 0;
|
|
34
|
-
const key = `${row},${col}`;
|
|
35
|
-
const cached = memo.get(key);
|
|
36
|
-
if (cached !== void 0) return cached;
|
|
37
|
-
if (inProgress.has(key)) return 0;
|
|
38
|
-
inProgress.add(key);
|
|
39
|
-
const value = evaluate(raw, row, col);
|
|
40
|
-
inProgress.delete(key);
|
|
41
|
-
memo.set(key, value);
|
|
42
|
-
return value;
|
|
43
|
-
};
|
|
44
|
-
const parser = new FormulaParser({
|
|
45
|
-
onCell: ({ row, col }) => valueAt(row, col),
|
|
46
|
-
onRange: (ref) => {
|
|
47
|
-
const maxRow = Math.min(ref.to.row, rows.length + 1);
|
|
48
|
-
const maxCol = Math.min(ref.to.col, columns.length);
|
|
49
|
-
const grid = [];
|
|
50
|
-
for (let r = ref.from.row; r <= maxRow; r++) {
|
|
51
|
-
const line = [];
|
|
52
|
-
for (let c = ref.from.col; c <= maxCol; c++) line.push(valueAt(r, c));
|
|
53
|
-
grid.push(line);
|
|
54
|
-
}
|
|
55
|
-
return grid;
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
const evaluate = (formula, row, col) => {
|
|
59
|
-
try {
|
|
60
|
-
const result = parser.parse(formula.slice(1), { row, col });
|
|
61
|
-
if (result != null && typeof result === "object") return "#ERR";
|
|
62
|
-
return result ?? 0;
|
|
63
|
-
} catch {
|
|
64
|
-
return "#ERR";
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
const out = /* @__PURE__ */ new Map();
|
|
68
|
-
for (const { dataIdx, col, formula } of formulaCells) {
|
|
69
|
-
out.set(`${dataIdx + 1},${col}`, evaluate(formula, dataIdx + 2, col + 1));
|
|
70
|
-
}
|
|
71
|
-
return out;
|
|
72
|
-
}
|
|
73
|
-
var Workbook = lazy(() => import('@fortune-sheet/react').then((m) => ({ default: m.Workbook })));
|
|
74
|
-
var isFormula = (v) => typeof v === "string" && v.startsWith("=");
|
|
75
|
-
function toWorkbook(columns, rows, formulas) {
|
|
76
|
-
const celldata = [];
|
|
77
|
-
columns.forEach((col, c) => {
|
|
78
|
-
const label = col.label ?? col.key;
|
|
79
|
-
celldata.push({ r: 0, c, v: { v: label, m: String(label), bl: 1, bg: "#f3f4f6" } });
|
|
80
|
-
});
|
|
81
|
-
rows.forEach((row, r) => {
|
|
82
|
-
columns.forEach((col, c) => {
|
|
83
|
-
const val = row[col.key];
|
|
84
|
-
if (val === void 0 || val === null || val === "") return;
|
|
85
|
-
if (isFormula(val)) {
|
|
86
|
-
const computed = formulas.get(`${r + 1},${c}`);
|
|
87
|
-
const v = { f: val };
|
|
88
|
-
if (computed !== void 0) {
|
|
89
|
-
v.v = computed;
|
|
90
|
-
v.m = String(computed);
|
|
91
|
-
if (typeof computed === "number") v.ct = { fa: "General", t: "n" };
|
|
92
|
-
}
|
|
93
|
-
celldata.push({ r: r + 1, c, v });
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const numeric = typeof val === "number";
|
|
97
|
-
celldata.push({
|
|
98
|
-
r: r + 1,
|
|
99
|
-
c,
|
|
100
|
-
v: { v: val, m: String(val), ...numeric ? { ct: { fa: "General", t: "n" } } : {} }
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
const sample = Math.min(rows.length, 400);
|
|
105
|
-
const columnlen = {};
|
|
106
|
-
columns.forEach((col, c) => {
|
|
107
|
-
let widest = String(col.label ?? col.key).length;
|
|
108
|
-
for (let ri = 0; ri < sample; ri++) {
|
|
109
|
-
let v = rows[ri][col.key];
|
|
110
|
-
if (isFormula(v)) v = formulas.get(`${ri + 1},${c}`) ?? "";
|
|
111
|
-
if (v != null && v !== "") widest = Math.max(widest, String(v).length);
|
|
112
|
-
}
|
|
113
|
-
columnlen[c] = Math.min(360, Math.max(64, Math.round(widest * 8.5) + 18));
|
|
114
|
-
});
|
|
115
|
-
return [
|
|
116
|
-
{
|
|
117
|
-
name: "Sheet1",
|
|
118
|
-
id: "sheet1",
|
|
119
|
-
order: 0,
|
|
120
|
-
// Size the grid to the data plus a modest buffer — big enough to feel like a
|
|
121
|
-
// real sheet and to keep growing, small enough that the scrollbar stays
|
|
122
|
-
// proportional (a huge empty grid makes scrolling feel disconnected).
|
|
123
|
-
row: Math.max(rows.length + 40, 60),
|
|
124
|
-
column: Math.max(columns.length + 2, 8),
|
|
125
|
-
celldata,
|
|
126
|
-
// No frozen pane: a freeze split offsets the initial scroll and hides the
|
|
127
|
-
// first data rows behind the split line. A plain grid scrolls cleanly.
|
|
128
|
-
config: { rowlen: { 0: 28 }, columnlen }
|
|
129
|
-
}
|
|
130
|
-
];
|
|
131
|
-
}
|
|
132
|
-
function deriveColumns(rows) {
|
|
133
|
-
const keys = /* @__PURE__ */ new Set();
|
|
134
|
-
for (let i = 0; i < Math.min(rows.length, 50); i++) Object.keys(rows[i] ?? {}).forEach((k) => keys.add(k));
|
|
135
|
-
return [...keys].map((key) => ({ key }));
|
|
136
|
-
}
|
|
137
|
-
var EMPTY_FORMULAS = /* @__PURE__ */ new Map();
|
|
138
|
-
function TableRenderer({ artifact }) {
|
|
139
|
-
const rows = artifact.data.rows;
|
|
140
|
-
const columns = useMemo(
|
|
141
|
-
() => artifact.data.columns.length ? artifact.data.columns : deriveColumns(rows),
|
|
142
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
143
|
-
[artifact.id, artifact.version, artifact.data.columns.length, rows.length]
|
|
144
|
-
);
|
|
145
|
-
const [mounted, setMounted] = useState(false);
|
|
146
|
-
const rootRef = useRef(null);
|
|
147
|
-
useEffect(() => setMounted(true), []);
|
|
148
|
-
useEffect(() => {
|
|
149
|
-
const root = rootRef.current;
|
|
150
|
-
if (!root) return;
|
|
151
|
-
const onWheel = (e) => {
|
|
152
|
-
const y = root.querySelector(".luckysheet-scrollbar-y");
|
|
153
|
-
const x = root.querySelector(".luckysheet-scrollbar-x");
|
|
154
|
-
let moved = false;
|
|
155
|
-
if (y && e.deltaY && y.scrollHeight > y.clientHeight) {
|
|
156
|
-
const max = y.scrollHeight - y.clientHeight;
|
|
157
|
-
const next = Math.max(0, Math.min(max, y.scrollTop + e.deltaY));
|
|
158
|
-
if (next !== y.scrollTop) {
|
|
159
|
-
y.scrollTop = next;
|
|
160
|
-
moved = true;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (x && e.deltaX && x.scrollWidth > x.clientWidth) {
|
|
164
|
-
const max = x.scrollWidth - x.clientWidth;
|
|
165
|
-
const next = Math.max(0, Math.min(max, x.scrollLeft + e.deltaX));
|
|
166
|
-
if (next !== x.scrollLeft) {
|
|
167
|
-
x.scrollLeft = next;
|
|
168
|
-
moved = true;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
const horizontal = Math.abs(e.deltaX) > Math.abs(e.deltaY);
|
|
172
|
-
if (moved || horizontal && e.deltaX) {
|
|
173
|
-
e.preventDefault();
|
|
174
|
-
e.stopPropagation();
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
root.addEventListener("wheel", onWheel, { passive: false, capture: true });
|
|
178
|
-
return () => root.removeEventListener("wheel", onWheel, { capture: true });
|
|
179
|
-
}, [mounted]);
|
|
180
|
-
const dataKey = `${artifact.id}:v${artifact.version}:${columns.length}x${rows.length}`;
|
|
181
|
-
const hasFormulas = useMemo(
|
|
182
|
-
() => rows.slice(0, 400).some((row) => columns.some((col) => isFormula(row[col.key]))),
|
|
183
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
184
|
-
[dataKey]
|
|
185
|
-
);
|
|
186
|
-
const [formulas, setFormulas] = useState(EMPTY_FORMULAS);
|
|
187
|
-
const [formulasReady, setFormulasReady] = useState(!hasFormulas);
|
|
188
|
-
useEffect(() => {
|
|
189
|
-
if (!hasFormulas) {
|
|
190
|
-
setFormulas(EMPTY_FORMULAS);
|
|
191
|
-
setFormulasReady(true);
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
let alive = true;
|
|
195
|
-
setFormulasReady(false);
|
|
196
|
-
computeFormulas(columns, rows).then((values) => {
|
|
197
|
-
if (!alive) return;
|
|
198
|
-
setFormulas(values);
|
|
199
|
-
setFormulasReady(true);
|
|
200
|
-
});
|
|
201
|
-
return () => {
|
|
202
|
-
alive = false;
|
|
203
|
-
};
|
|
204
|
-
}, [dataKey, hasFormulas]);
|
|
205
|
-
const hasSheet = !!artifact.data.sheet?.length;
|
|
206
|
-
const [sortCol, setSortCol] = useState("");
|
|
207
|
-
const [sortDir, setSortDir] = useState(1);
|
|
208
|
-
const [filter, setFilter] = useState("");
|
|
209
|
-
const [appliedFilter, setAppliedFilter] = useState("");
|
|
210
|
-
useEffect(() => {
|
|
211
|
-
const t = setTimeout(() => setAppliedFilter(filter), 300);
|
|
212
|
-
return () => clearTimeout(t);
|
|
213
|
-
}, [filter]);
|
|
214
|
-
const viewRows = useMemo(() => {
|
|
215
|
-
let r = rows;
|
|
216
|
-
const q = appliedFilter.trim().toLowerCase();
|
|
217
|
-
if (q) r = r.filter((row) => columns.some((c) => String(row[c.key] ?? "").toLowerCase().includes(q)));
|
|
218
|
-
if (sortCol) {
|
|
219
|
-
r = [...r].sort((a, b) => {
|
|
220
|
-
const av = a[sortCol];
|
|
221
|
-
const bv = b[sortCol];
|
|
222
|
-
const cmp = typeof av === "number" && typeof bv === "number" ? av - bv : String(av ?? "").localeCompare(String(bv ?? ""));
|
|
223
|
-
return cmp * sortDir;
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
return r;
|
|
227
|
-
}, [rows, columns, appliedFilter, sortCol, sortDir]);
|
|
228
|
-
const viewActive = !!appliedFilter.trim() || !!sortCol;
|
|
229
|
-
const wbKey = `${dataKey}:${viewActive ? `view-s${sortCol}${sortDir}-f${appliedFilter}` : hasSheet ? "sheet" : "rows"}`;
|
|
230
|
-
const initialData = useMemo(
|
|
231
|
-
() => viewActive ? toWorkbook(columns, viewRows, formulas) : hasSheet ? artifact.data.sheet : toWorkbook(columns, rows, formulas),
|
|
232
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
233
|
-
[wbKey, formulasReady]
|
|
234
|
-
);
|
|
235
|
-
const applyEvent = useCanvasStore((s) => s.applyUserEvent);
|
|
236
|
-
const persistTimer = useRef(null);
|
|
237
|
-
const handleChange = useCallback(
|
|
238
|
-
(sheets) => {
|
|
239
|
-
if (persistTimer.current) clearTimeout(persistTimer.current);
|
|
240
|
-
persistTimer.current = setTimeout(() => {
|
|
241
|
-
applyEvent({ type: "canvas.patch", id: artifact.id, patch: { sheet: sheets } });
|
|
242
|
-
}, 400);
|
|
243
|
-
},
|
|
244
|
-
[applyEvent, artifact.id]
|
|
245
|
-
);
|
|
246
|
-
useEffect(() => () => {
|
|
247
|
-
if (persistTimer.current) clearTimeout(persistTimer.current);
|
|
248
|
-
}, []);
|
|
249
|
-
const wbRef = useRef(null);
|
|
250
|
-
const insert = (type) => {
|
|
251
|
-
const sel = wbRef.current?.getSelection?.();
|
|
252
|
-
const range = sel?.[0]?.[type] ?? [0, 0];
|
|
253
|
-
wbRef.current?.insertRowOrColumn(type, Math.max(0, range[1]), 1, "rightbottom");
|
|
254
|
-
};
|
|
255
|
-
const [selection, setSelection] = useState(null);
|
|
256
|
-
const [boldOn, setBoldOn] = useState(false);
|
|
257
|
-
const [fillColor, setFillColor] = useState("#fef3c7");
|
|
258
|
-
const [textColor, setTextColor] = useState("#111827");
|
|
259
|
-
const handleSelectionChange = useCallback((_sheetId, sel) => {
|
|
260
|
-
setSelection({ row: [...sel.row], column: [...sel.column] });
|
|
261
|
-
const bl = wbRef.current?.getCellValue?.(sel.row[0], sel.column[0], { type: "bl" });
|
|
262
|
-
setBoldOn(bl === 1 || bl === "1");
|
|
263
|
-
}, []);
|
|
264
|
-
const workbookHooks = useMemo(() => ({ afterSelectionChange: handleSelectionChange }), [handleSelectionChange]);
|
|
265
|
-
const applyFormat = (attr, value) => {
|
|
266
|
-
const sel = wbRef.current?.getSelection?.();
|
|
267
|
-
if (!sel?.length) return;
|
|
268
|
-
const ranges = sel.map((s) => ({ row: [s.row[0], s.row[1]], column: [s.column[0], s.column[1]] }));
|
|
269
|
-
wbRef.current?.setCellFormatByRange(attr, value, ranges);
|
|
270
|
-
};
|
|
271
|
-
const toggleBold = () => {
|
|
272
|
-
applyFormat("bl", boldOn ? 0 : 1);
|
|
273
|
-
setBoldOn((b) => !b);
|
|
274
|
-
};
|
|
275
|
-
const cleanStyling = () => {
|
|
276
|
-
const wb = wbRef.current;
|
|
277
|
-
const sheet = wb?.getSheet?.();
|
|
278
|
-
const sheetId = sheet?.id;
|
|
279
|
-
if (!wb || !sheet || !sheetId) return;
|
|
280
|
-
const ops = [];
|
|
281
|
-
sheet.celldata.forEach(({ r, c, v }) => {
|
|
282
|
-
if (!v || typeof v !== "object") return;
|
|
283
|
-
const cell = v;
|
|
284
|
-
if (cell.bg != null) ops.push({ op: "remove", id: sheetId, path: ["data", r, c, "bg"] });
|
|
285
|
-
if (cell.fc != null) ops.push({ op: "remove", id: sheetId, path: ["data", r, c, "fc"] });
|
|
286
|
-
const spans = cell.ct?.s;
|
|
287
|
-
if (!Array.isArray(spans)) return;
|
|
288
|
-
spans.forEach((span, i) => {
|
|
289
|
-
if (!span || typeof span !== "object") return;
|
|
290
|
-
const run = span;
|
|
291
|
-
if (run.bg != null) ops.push({ op: "remove", id: sheetId, path: ["data", r, c, "ct", "s", i, "bg"] });
|
|
292
|
-
if (run.fc != null) ops.push({ op: "remove", id: sheetId, path: ["data", r, c, "ct", "s", i, "fc"] });
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
if (ops.length) wb.applyOp(ops);
|
|
296
|
-
};
|
|
297
|
-
const [frozen, setFrozen] = useState(false);
|
|
298
|
-
const toggleFreeze = () => {
|
|
299
|
-
const wb = wbRef.current;
|
|
300
|
-
if (!wb) return;
|
|
301
|
-
if (frozen) {
|
|
302
|
-
const sheetId = wb.getSheet?.()?.id;
|
|
303
|
-
if (sheetId) wb.applyOp([{ op: "remove", id: sheetId, path: ["frozen"] }]);
|
|
304
|
-
} else {
|
|
305
|
-
wb.freeze("row", { row: 0, column: 0 });
|
|
306
|
-
}
|
|
307
|
-
setFrozen((f) => !f);
|
|
308
|
-
};
|
|
309
|
-
useEffect(() => {
|
|
310
|
-
setFrozen(!viewActive && hasSheet && !!artifact.data.sheet?.[0]?.frozen);
|
|
311
|
-
setSelection(null);
|
|
312
|
-
setBoldOn(false);
|
|
313
|
-
}, [wbKey]);
|
|
314
|
-
if (!mounted) {
|
|
315
|
-
return /* @__PURE__ */ jsx("div", { className: "cv-sheet cv-sheet--empty", children: "Loading spreadsheet\u2026" });
|
|
316
|
-
}
|
|
317
|
-
if (!hasSheet && columns.length === 0) {
|
|
318
|
-
return /* @__PURE__ */ jsx("div", { className: "cv-sheet cv-sheet--empty", children: "Waiting for data\u2026" });
|
|
319
|
-
}
|
|
320
|
-
if (!hasSheet && !formulasReady) {
|
|
321
|
-
return /* @__PURE__ */ jsx("div", { className: "cv-sheet cv-sheet--empty", children: "Calculating\u2026" });
|
|
322
|
-
}
|
|
323
|
-
return /* @__PURE__ */ jsxs("div", { className: "cv-sheet-panel", children: [
|
|
324
|
-
/* @__PURE__ */ jsxs("div", { className: "cv-sheet-tools", children: [
|
|
325
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => insert("column"), children: "\uFF0B Column" }),
|
|
326
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => insert("row"), children: "\uFF0B Row" }),
|
|
327
|
-
/* @__PURE__ */ jsx("span", { className: "cv-sheet-tools__sep" }),
|
|
328
|
-
/* @__PURE__ */ jsxs("span", { className: "cv-sheet-tools__fmt", children: [
|
|
329
|
-
/* @__PURE__ */ jsx(
|
|
330
|
-
"button",
|
|
331
|
-
{
|
|
332
|
-
type: "button",
|
|
333
|
-
className: `cv-sheet-tools__bold${boldOn ? " cv-sheet-tools__bold--on" : ""}`,
|
|
334
|
-
title: "Bold",
|
|
335
|
-
"aria-pressed": boldOn,
|
|
336
|
-
disabled: !selection,
|
|
337
|
-
onClick: toggleBold,
|
|
338
|
-
children: "B"
|
|
339
|
-
}
|
|
340
|
-
),
|
|
341
|
-
/* @__PURE__ */ jsx(
|
|
342
|
-
"input",
|
|
343
|
-
{
|
|
344
|
-
type: "color",
|
|
345
|
-
className: "cv-sheet-tools__color cv-sheet-tools__color--fill",
|
|
346
|
-
title: "Fill color",
|
|
347
|
-
disabled: !selection,
|
|
348
|
-
value: fillColor,
|
|
349
|
-
onChange: (e) => {
|
|
350
|
-
setFillColor(e.target.value);
|
|
351
|
-
applyFormat("bg", e.target.value);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
),
|
|
355
|
-
/* @__PURE__ */ jsx(
|
|
356
|
-
"input",
|
|
357
|
-
{
|
|
358
|
-
type: "color",
|
|
359
|
-
className: "cv-sheet-tools__color cv-sheet-tools__color--text",
|
|
360
|
-
title: "Text color",
|
|
361
|
-
disabled: !selection,
|
|
362
|
-
value: textColor,
|
|
363
|
-
onChange: (e) => {
|
|
364
|
-
setTextColor(e.target.value);
|
|
365
|
-
applyFormat("fc", e.target.value);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
),
|
|
369
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "cv-sheet-tools__align", title: "Align left", disabled: !selection, onClick: () => applyFormat("ht", 1), children: "\u21E4" }),
|
|
370
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "cv-sheet-tools__align", title: "Align center", disabled: !selection, onClick: () => applyFormat("ht", 0), children: "\u2194" }),
|
|
371
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "cv-sheet-tools__align", title: "Align right", disabled: !selection, onClick: () => applyFormat("ht", 2), children: "\u21E5" })
|
|
372
|
-
] }),
|
|
373
|
-
/* @__PURE__ */ jsx("span", { className: "cv-sheet-tools__sep" }),
|
|
374
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "cv-sheet-tools__clean", title: "Remove all cell fills and font colors", onClick: cleanStyling, children: "Clean styling" }),
|
|
375
|
-
/* @__PURE__ */ jsx(
|
|
376
|
-
"button",
|
|
377
|
-
{
|
|
378
|
-
type: "button",
|
|
379
|
-
className: `cv-sheet-tools__freeze${frozen ? " cv-sheet-tools__freeze--on" : ""}`,
|
|
380
|
-
title: frozen ? "Unfreeze the header row" : "Keep the header row visible while scrolling",
|
|
381
|
-
"aria-pressed": frozen,
|
|
382
|
-
onClick: toggleFreeze,
|
|
383
|
-
children: "Freeze header"
|
|
384
|
-
}
|
|
385
|
-
),
|
|
386
|
-
columns.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
387
|
-
/* @__PURE__ */ jsx("span", { className: "cv-sheet-tools__sep" }),
|
|
388
|
-
/* @__PURE__ */ jsxs(
|
|
389
|
-
"select",
|
|
390
|
-
{
|
|
391
|
-
className: "cv-sheet-tools__sort",
|
|
392
|
-
value: sortCol,
|
|
393
|
-
title: "Sort by column",
|
|
394
|
-
onChange: (e) => setSortCol(e.target.value),
|
|
395
|
-
children: [
|
|
396
|
-
/* @__PURE__ */ jsx("option", { value: "", children: "Sort\u2026" }),
|
|
397
|
-
columns.map((c) => /* @__PURE__ */ jsx("option", { value: c.key, children: c.label ?? c.key }, c.key))
|
|
398
|
-
]
|
|
399
|
-
}
|
|
400
|
-
),
|
|
401
|
-
sortCol && /* @__PURE__ */ jsx("button", { type: "button", title: sortDir === 1 ? "Ascending" : "Descending", onClick: () => setSortDir((d) => d === 1 ? -1 : 1), children: sortDir === 1 ? "\u25B2" : "\u25BC" }),
|
|
402
|
-
/* @__PURE__ */ jsx(
|
|
403
|
-
"input",
|
|
404
|
-
{
|
|
405
|
-
className: "cv-sheet-tools__filter",
|
|
406
|
-
value: filter,
|
|
407
|
-
placeholder: "Filter\u2026",
|
|
408
|
-
onChange: (e) => setFilter(e.target.value),
|
|
409
|
-
title: "Filter rows"
|
|
410
|
-
}
|
|
411
|
-
)
|
|
412
|
-
] }),
|
|
413
|
-
/* @__PURE__ */ jsx("span", { className: "cv-sheet-tools__hint", children: "Right-click a header for more, or drag to edit" })
|
|
414
|
-
] }),
|
|
415
|
-
/* @__PURE__ */ jsx("div", { className: "cv-sheet", ref: rootRef, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "cv-sheet--empty", children: "Loading\u2026" }), children: /* @__PURE__ */ jsx(Workbook, { ref: wbRef, data: initialData, onChange: handleChange, hooks: workbookHooks }, wbKey) }) })
|
|
416
|
-
] });
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
export { TableRenderer };
|