bolt-table 0.1.35 → 0.1.37
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/index.d.mts +117 -14
- package/dist/index.d.ts +117 -14
- package/dist/index.js +930 -208
- package/dist/index.mjs +928 -207
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -102,6 +102,18 @@ var XIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgBase,
|
|
|
102
102
|
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
103
103
|
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
104
104
|
] });
|
|
105
|
+
var SparklesIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgBase, style, className, children: [
|
|
106
|
+
/* @__PURE__ */ jsx("path", { d: "m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z" }),
|
|
107
|
+
/* @__PURE__ */ jsx("path", { d: "M5 3v4" }),
|
|
108
|
+
/* @__PURE__ */ jsx("path", { d: "M19 17v4" }),
|
|
109
|
+
/* @__PURE__ */ jsx("path", { d: "M3 5h4" }),
|
|
110
|
+
/* @__PURE__ */ jsx("path", { d: "M17 19h4" })
|
|
111
|
+
] });
|
|
112
|
+
var SendIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgBase, style, className, children: [
|
|
113
|
+
/* @__PURE__ */ jsx("path", { d: "m22 2-7 20-4-9-9-4Z" }),
|
|
114
|
+
/* @__PURE__ */ jsx("path", { d: "M22 2 11 13" })
|
|
115
|
+
] });
|
|
116
|
+
var LoaderIcon = ({ style, className }) => /* @__PURE__ */ jsx("svg", { ...svgBase, style, className, children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
|
|
105
117
|
|
|
106
118
|
// src/DraggableHeader.tsx
|
|
107
119
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -589,40 +601,44 @@ var DraggableHeader = React.memo(
|
|
|
589
601
|
] }),
|
|
590
602
|
customContextMenuItems && customContextMenuItems.length > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
591
603
|
/* @__PURE__ */ jsx2("div", { style: { marginTop: 4, marginBottom: 4, borderTop: "1px solid rgba(128,128,128,0.2)" } }),
|
|
592
|
-
customContextMenuItems.map((item) =>
|
|
593
|
-
"
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
"
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
604
|
+
customContextMenuItems.map((item) => {
|
|
605
|
+
const resolvedIcon = typeof item.icon === "function" ? item.icon(column.key) : item.icon;
|
|
606
|
+
const resolvedLabel = typeof item.label === "function" ? item.label(column.key) : item.label;
|
|
607
|
+
return /* @__PURE__ */ jsxs2(
|
|
608
|
+
"button",
|
|
609
|
+
{
|
|
610
|
+
type: "button",
|
|
611
|
+
"data-bt-ctx-item": "",
|
|
612
|
+
disabled: item.disabled,
|
|
613
|
+
style: {
|
|
614
|
+
display: "flex",
|
|
615
|
+
width: "100%",
|
|
616
|
+
alignItems: "center",
|
|
617
|
+
gap: 8,
|
|
618
|
+
paddingLeft: 12,
|
|
619
|
+
paddingRight: 12,
|
|
620
|
+
paddingTop: 6,
|
|
621
|
+
paddingBottom: 6,
|
|
622
|
+
textAlign: "left",
|
|
623
|
+
background: "none",
|
|
624
|
+
border: "none",
|
|
625
|
+
fontSize: "inherit",
|
|
626
|
+
cursor: item.disabled ? "not-allowed" : "pointer",
|
|
627
|
+
opacity: item.disabled ? 0.5 : 1,
|
|
628
|
+
color: item.danger ? "#ef4444" : "inherit"
|
|
629
|
+
},
|
|
630
|
+
onClick: () => {
|
|
631
|
+
item.onClick?.(column.key);
|
|
632
|
+
setContextMenu(null);
|
|
633
|
+
},
|
|
634
|
+
children: [
|
|
635
|
+
resolvedIcon && /* @__PURE__ */ jsx2("span", { style: { display: "flex", width: 12, height: 12, alignItems: "center", justifyContent: "center" }, children: resolvedIcon }),
|
|
636
|
+
resolvedLabel
|
|
637
|
+
]
|
|
618
638
|
},
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
]
|
|
623
|
-
},
|
|
624
|
-
item.key
|
|
625
|
-
))
|
|
639
|
+
item.key
|
|
640
|
+
);
|
|
641
|
+
})
|
|
626
642
|
] })
|
|
627
643
|
] });
|
|
628
644
|
})()
|
|
@@ -639,6 +655,280 @@ var DraggableHeader = React.memo(
|
|
|
639
655
|
DraggableHeader.displayName = "DraggableHeader";
|
|
640
656
|
var DraggableHeader_default = DraggableHeader;
|
|
641
657
|
|
|
658
|
+
// src/ai.ts
|
|
659
|
+
function detectColumnType(key, data) {
|
|
660
|
+
const values = [];
|
|
661
|
+
for (let i = 0; i < Math.min(data.length, 20); i++) {
|
|
662
|
+
const v = data[i]?.[key];
|
|
663
|
+
if (v != null) values.push(v);
|
|
664
|
+
}
|
|
665
|
+
if (values.length === 0) return { type: "unknown", sample: "" };
|
|
666
|
+
const allNumbers = values.every((v) => typeof v === "number");
|
|
667
|
+
const allBooleans = values.every((v) => typeof v === "boolean");
|
|
668
|
+
const uniqueVals = [...new Set(values.map(String))];
|
|
669
|
+
const sampleStr = uniqueVals.length <= 8 ? uniqueVals.join(", ") : uniqueVals.slice(0, 6).join(", ") + "...";
|
|
670
|
+
if (allBooleans) return { type: "boolean", sample: sampleStr };
|
|
671
|
+
if (allNumbers) {
|
|
672
|
+
const nums = values;
|
|
673
|
+
const min = Math.min(...nums);
|
|
674
|
+
const max = Math.max(...nums);
|
|
675
|
+
return { type: "number", sample: `range ${min}\u2013${max}` };
|
|
676
|
+
}
|
|
677
|
+
return { type: "string", sample: sampleStr };
|
|
678
|
+
}
|
|
679
|
+
function buildSystemPrompt(columns, data) {
|
|
680
|
+
const schemaLines = columns.filter((c) => c.key !== "__select__" && c.key !== "__expand__").map((c) => {
|
|
681
|
+
const key = c.dataIndex ?? c.key;
|
|
682
|
+
const title = typeof c.title === "string" ? c.title : c.key;
|
|
683
|
+
const info = detectColumnType(key, data);
|
|
684
|
+
return ` - key: "${c.key}", title: "${title}", dataIndex: "${key}", type: ${info.type}${info.sample ? ` (values: ${info.sample})` : ""}`;
|
|
685
|
+
}).join("\n");
|
|
686
|
+
const sample = data.slice(0, 5).map((row) => {
|
|
687
|
+
const obj = {};
|
|
688
|
+
for (const col of columns) {
|
|
689
|
+
if (col.key === "__select__" || col.key === "__expand__") continue;
|
|
690
|
+
const di = col.dataIndex ?? col.key;
|
|
691
|
+
obj[di] = row[di];
|
|
692
|
+
}
|
|
693
|
+
return obj;
|
|
694
|
+
});
|
|
695
|
+
return `You are a data table assistant. You help users query, filter, sort, and style tabular data.
|
|
696
|
+
You MUST respond with ONLY a valid JSON object \u2014 no markdown fences, no explanation, no extra text.
|
|
697
|
+
|
|
698
|
+
## Table Schema
|
|
699
|
+
${schemaLines}
|
|
700
|
+
|
|
701
|
+
## Sample Data (first ${sample.length} of ${data.length} rows)
|
|
702
|
+
${JSON.stringify(sample, null, 2)}
|
|
703
|
+
|
|
704
|
+
## Available Operations
|
|
705
|
+
Combine any of these in a single response:
|
|
706
|
+
|
|
707
|
+
1. **filter** \u2014 show only rows matching conditions
|
|
708
|
+
{ "type": "filter", "conditions": [{ "column": "<dataIndex>", "op": "<op>", "value": <val> }], "logic": "and" | "or" }
|
|
709
|
+
|
|
710
|
+
2. **rowStyle** \u2014 apply CSS styles to entire rows matching conditions
|
|
711
|
+
{ "type": "rowStyle", "conditions": [...], "logic": "and"|"or", "style": { "<cssProp>": "<value>" } }
|
|
712
|
+
|
|
713
|
+
3. **cellStyle** \u2014 apply CSS styles to a specific column's cells matching conditions
|
|
714
|
+
{ "type": "cellStyle", "column": "<dataIndex>", "conditions": [...], "logic": "and"|"or", "style": { "<cssProp>": "<value>" } }
|
|
715
|
+
|
|
716
|
+
4. **sort** \u2014 sort data by a column
|
|
717
|
+
{ "type": "sort", "column": "<dataIndex>", "direction": "asc" | "desc" }
|
|
718
|
+
|
|
719
|
+
5. **hideColumns** / **showColumns** \u2014 toggle column visibility
|
|
720
|
+
{ "type": "hideColumns" | "showColumns", "columns": ["<key>", ...] }
|
|
721
|
+
|
|
722
|
+
## Operators
|
|
723
|
+
eq, neq, gt, gte, lt, lte, contains, notContains, startsWith, endsWith, in, notIn
|
|
724
|
+
|
|
725
|
+
## Response format
|
|
726
|
+
{
|
|
727
|
+
"operations": [ ... ],
|
|
728
|
+
"message": "Brief user-friendly description of what was applied"
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
## Rules
|
|
732
|
+
- Use the dataIndex values from the schema, not display titles.
|
|
733
|
+
- For colors use semi-transparent values like "rgba(255,0,0,0.15)" so text stays readable.
|
|
734
|
+
- CSS property names must be camelCase (e.g. "backgroundColor", "color", "fontWeight").
|
|
735
|
+
- If the user asks to highlight / color / mark specific rows, use rowStyle or cellStyle.
|
|
736
|
+
- If the user asks to show only certain rows, use filter.
|
|
737
|
+
- You can combine filter + rowStyle + sort etc. in one response.
|
|
738
|
+
- The "message" should be concise: what was done, in plain English.`;
|
|
739
|
+
}
|
|
740
|
+
async function callAI(config, systemPrompt, userQuery) {
|
|
741
|
+
const { provider, apiKey, model, baseUrl, maxTokens = 1024, temperature = 0.1 } = config;
|
|
742
|
+
if (provider === "openai" || provider === "custom") {
|
|
743
|
+
const url = baseUrl ? `${baseUrl.replace(/\/$/, "")}/chat/completions` : "https://api.openai.com/v1/chat/completions";
|
|
744
|
+
const res = await fetch(url, {
|
|
745
|
+
method: "POST",
|
|
746
|
+
headers: {
|
|
747
|
+
"Content-Type": "application/json",
|
|
748
|
+
Authorization: `Bearer ${apiKey}`
|
|
749
|
+
},
|
|
750
|
+
body: JSON.stringify({
|
|
751
|
+
model: model ?? "gpt-4o-mini",
|
|
752
|
+
messages: [
|
|
753
|
+
{ role: "system", content: systemPrompt },
|
|
754
|
+
{ role: "user", content: userQuery }
|
|
755
|
+
],
|
|
756
|
+
max_tokens: maxTokens,
|
|
757
|
+
temperature
|
|
758
|
+
})
|
|
759
|
+
});
|
|
760
|
+
if (!res.ok) {
|
|
761
|
+
const body = await res.text().catch(() => "");
|
|
762
|
+
throw new Error(`AI request failed (${res.status}): ${body}`);
|
|
763
|
+
}
|
|
764
|
+
const json = await res.json();
|
|
765
|
+
return json.choices?.[0]?.message?.content ?? "";
|
|
766
|
+
}
|
|
767
|
+
if (provider === "anthropic") {
|
|
768
|
+
const url = baseUrl ? `${baseUrl.replace(/\/$/, "")}/messages` : "https://api.anthropic.com/v1/messages";
|
|
769
|
+
const res = await fetch(url, {
|
|
770
|
+
method: "POST",
|
|
771
|
+
headers: {
|
|
772
|
+
"Content-Type": "application/json",
|
|
773
|
+
"x-api-key": apiKey,
|
|
774
|
+
"anthropic-version": "2023-06-01",
|
|
775
|
+
"anthropic-dangerous-direct-browser-access": "true"
|
|
776
|
+
},
|
|
777
|
+
body: JSON.stringify({
|
|
778
|
+
model: model ?? "claude-sonnet-4-20250514",
|
|
779
|
+
system: systemPrompt,
|
|
780
|
+
messages: [{ role: "user", content: userQuery }],
|
|
781
|
+
max_tokens: maxTokens,
|
|
782
|
+
temperature
|
|
783
|
+
})
|
|
784
|
+
});
|
|
785
|
+
if (!res.ok) {
|
|
786
|
+
const body = await res.text().catch(() => "");
|
|
787
|
+
throw new Error(`AI request failed (${res.status}): ${body}`);
|
|
788
|
+
}
|
|
789
|
+
const json = await res.json();
|
|
790
|
+
const textBlock = json.content?.find(
|
|
791
|
+
(b) => b.type === "text"
|
|
792
|
+
);
|
|
793
|
+
return textBlock?.text ?? "";
|
|
794
|
+
}
|
|
795
|
+
throw new Error(`Unsupported AI provider: ${provider}`);
|
|
796
|
+
}
|
|
797
|
+
function parseAIResponse(raw) {
|
|
798
|
+
let text = raw.trim();
|
|
799
|
+
const fenceMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
800
|
+
if (fenceMatch) text = fenceMatch[1].trim();
|
|
801
|
+
const start = text.indexOf("{");
|
|
802
|
+
const end = text.lastIndexOf("}");
|
|
803
|
+
if (start !== -1 && end > start) {
|
|
804
|
+
text = text.slice(start, end + 1);
|
|
805
|
+
}
|
|
806
|
+
const parsed = JSON.parse(text);
|
|
807
|
+
if (!parsed.operations || !Array.isArray(parsed.operations)) {
|
|
808
|
+
throw new Error("Invalid AI response: missing operations array");
|
|
809
|
+
}
|
|
810
|
+
return {
|
|
811
|
+
operations: parsed.operations,
|
|
812
|
+
message: parsed.message ?? "AI operations applied."
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
function evaluateCondition(condition, row) {
|
|
816
|
+
const rawVal = row[condition.column];
|
|
817
|
+
const target = condition.value;
|
|
818
|
+
switch (condition.op) {
|
|
819
|
+
case "eq":
|
|
820
|
+
return rawVal == target;
|
|
821
|
+
case "neq":
|
|
822
|
+
return rawVal != target;
|
|
823
|
+
case "gt":
|
|
824
|
+
return Number(rawVal) > Number(target);
|
|
825
|
+
case "gte":
|
|
826
|
+
return Number(rawVal) >= Number(target);
|
|
827
|
+
case "lt":
|
|
828
|
+
return Number(rawVal) < Number(target);
|
|
829
|
+
case "lte":
|
|
830
|
+
return Number(rawVal) <= Number(target);
|
|
831
|
+
case "contains":
|
|
832
|
+
return String(rawVal ?? "").toLowerCase().includes(String(target).toLowerCase());
|
|
833
|
+
case "notContains":
|
|
834
|
+
return !String(rawVal ?? "").toLowerCase().includes(String(target).toLowerCase());
|
|
835
|
+
case "startsWith":
|
|
836
|
+
return String(rawVal ?? "").toLowerCase().startsWith(String(target).toLowerCase());
|
|
837
|
+
case "endsWith":
|
|
838
|
+
return String(rawVal ?? "").toLowerCase().endsWith(String(target).toLowerCase());
|
|
839
|
+
case "in":
|
|
840
|
+
if (Array.isArray(target)) {
|
|
841
|
+
return target.some((t) => rawVal == t);
|
|
842
|
+
}
|
|
843
|
+
return false;
|
|
844
|
+
case "notIn":
|
|
845
|
+
if (Array.isArray(target)) {
|
|
846
|
+
return !target.some((t) => rawVal == t);
|
|
847
|
+
}
|
|
848
|
+
return true;
|
|
849
|
+
default:
|
|
850
|
+
return true;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
function matchesConditions(conditions, logic, row) {
|
|
854
|
+
if (!conditions || conditions.length === 0) return true;
|
|
855
|
+
if (logic === "or") {
|
|
856
|
+
return conditions.some((c) => evaluateCondition(c, row));
|
|
857
|
+
}
|
|
858
|
+
return conditions.every((c) => evaluateCondition(c, row));
|
|
859
|
+
}
|
|
860
|
+
function applyAIFilter(data, op) {
|
|
861
|
+
return data.filter((row) => matchesConditions(op.conditions, op.logic, row));
|
|
862
|
+
}
|
|
863
|
+
function applyAISort(data, op) {
|
|
864
|
+
const dir = op.direction === "asc" ? 1 : -1;
|
|
865
|
+
const col = op.column;
|
|
866
|
+
return [...data].sort((a, b) => {
|
|
867
|
+
const aVal = a[col];
|
|
868
|
+
const bVal = b[col];
|
|
869
|
+
if (aVal == null && bVal == null) return 0;
|
|
870
|
+
if (aVal == null) return 1;
|
|
871
|
+
if (bVal == null) return -1;
|
|
872
|
+
if (typeof aVal === "number" && typeof bVal === "number")
|
|
873
|
+
return (aVal - bVal) * dir;
|
|
874
|
+
return String(aVal).localeCompare(String(bVal)) * dir;
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
function getAIRowStyle(row, ops) {
|
|
878
|
+
let merged;
|
|
879
|
+
for (const op of ops) {
|
|
880
|
+
if (matchesConditions(op.conditions, op.logic, row)) {
|
|
881
|
+
if (!merged) merged = {};
|
|
882
|
+
Object.assign(merged, op.style);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return merged;
|
|
886
|
+
}
|
|
887
|
+
function getAICellStyle(row, columnKey, ops) {
|
|
888
|
+
let merged;
|
|
889
|
+
for (const op of ops) {
|
|
890
|
+
if (op.column === columnKey && matchesConditions(op.conditions, op.logic, row)) {
|
|
891
|
+
if (!merged) merged = {};
|
|
892
|
+
Object.assign(merged, op.style);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
return merged;
|
|
896
|
+
}
|
|
897
|
+
function applyAIOperations(data, operations) {
|
|
898
|
+
let filteredData = data;
|
|
899
|
+
let sortOp = null;
|
|
900
|
+
const styleOps = [];
|
|
901
|
+
const cellStyleOps = [];
|
|
902
|
+
const hideColumns = [];
|
|
903
|
+
const showColumns = [];
|
|
904
|
+
for (const op of operations) {
|
|
905
|
+
switch (op.type) {
|
|
906
|
+
case "filter":
|
|
907
|
+
filteredData = applyAIFilter(filteredData, op);
|
|
908
|
+
break;
|
|
909
|
+
case "sort":
|
|
910
|
+
sortOp = op;
|
|
911
|
+
break;
|
|
912
|
+
case "rowStyle":
|
|
913
|
+
styleOps.push(op);
|
|
914
|
+
break;
|
|
915
|
+
case "cellStyle":
|
|
916
|
+
cellStyleOps.push(op);
|
|
917
|
+
break;
|
|
918
|
+
case "hideColumns":
|
|
919
|
+
hideColumns.push(...op.columns);
|
|
920
|
+
break;
|
|
921
|
+
case "showColumns":
|
|
922
|
+
showColumns.push(...op.columns);
|
|
923
|
+
break;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
if (sortOp) {
|
|
927
|
+
filteredData = applyAISort(filteredData, sortOp);
|
|
928
|
+
}
|
|
929
|
+
return { filteredData, sortOp, styleOps, cellStyleOps, hideColumns, showColumns };
|
|
930
|
+
}
|
|
931
|
+
|
|
642
932
|
// src/ResizeOverlay.tsx
|
|
643
933
|
import { forwardRef, useImperativeHandle, useRef as useRef2 } from "react";
|
|
644
934
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -866,9 +1156,11 @@ var Cell = React3.memo(
|
|
|
866
1156
|
isLoading,
|
|
867
1157
|
onEdit,
|
|
868
1158
|
isEditing,
|
|
869
|
-
onEditComplete
|
|
1159
|
+
onEditComplete,
|
|
1160
|
+
cellStyleFn
|
|
870
1161
|
}) => {
|
|
871
1162
|
const isPinned = Boolean(column.pinned);
|
|
1163
|
+
const extraCellStyle = cellStyleFn?.(record, column.dataIndex ?? column.key);
|
|
872
1164
|
if (isLoading && column.key !== "__select__" && column.key !== "__expand__") {
|
|
873
1165
|
const shimmerContent = column.shimmerRender ? column.shimmerRender() : /* @__PURE__ */ jsx4(
|
|
874
1166
|
"div",
|
|
@@ -1020,7 +1312,8 @@ var Cell = React3.memo(
|
|
|
1020
1312
|
minWidth: 0,
|
|
1021
1313
|
...column.style,
|
|
1022
1314
|
...isPinned ? styles?.pinnedCell : void 0,
|
|
1023
|
-
...styles?.cell
|
|
1315
|
+
...styles?.cell,
|
|
1316
|
+
...extraCellStyle
|
|
1024
1317
|
},
|
|
1025
1318
|
children: isSystem ? content : showEditor ? content : /* @__PURE__ */ jsx4(
|
|
1026
1319
|
"div",
|
|
@@ -1047,6 +1340,7 @@ var Cell = React3.memo(
|
|
|
1047
1340
|
if (prev.onEdit !== next.onEdit) return false;
|
|
1048
1341
|
if (prev.isEditing !== next.isEditing) return false;
|
|
1049
1342
|
if (prev.onEditComplete !== next.onEditComplete) return false;
|
|
1343
|
+
if (prev.cellStyleFn !== next.cellStyleFn) return false;
|
|
1050
1344
|
if (prev.column.key === "__select__") {
|
|
1051
1345
|
return prev.isSelected === next.isSelected && prev.normalizedSelectedKeys === next.normalizedSelectedKeys;
|
|
1052
1346
|
}
|
|
@@ -1148,7 +1442,8 @@ var TableBody = ({
|
|
|
1148
1442
|
onEditComplete,
|
|
1149
1443
|
enableDynamicRowHeight = false,
|
|
1150
1444
|
onRowHeightChange,
|
|
1151
|
-
columnGridIndexMap
|
|
1445
|
+
columnGridIndexMap,
|
|
1446
|
+
cellStyleFn
|
|
1152
1447
|
}) => {
|
|
1153
1448
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1154
1449
|
const totalSize = rowVirtualizer.getTotalSize();
|
|
@@ -1277,7 +1572,8 @@ var TableBody = ({
|
|
|
1277
1572
|
recordFingerprint,
|
|
1278
1573
|
onEdit,
|
|
1279
1574
|
isEditing: editingCell?.rowKey === rowKey && editingCell?.columnKey === col.key,
|
|
1280
|
-
onEditComplete
|
|
1575
|
+
onEditComplete,
|
|
1576
|
+
cellStyleFn
|
|
1281
1577
|
}
|
|
1282
1578
|
)
|
|
1283
1579
|
}
|
|
@@ -1314,7 +1610,8 @@ var TableBody = ({
|
|
|
1314
1610
|
recordFingerprint,
|
|
1315
1611
|
onEdit,
|
|
1316
1612
|
isEditing: editingCell?.rowKey === rowKey && editingCell?.columnKey === col.key,
|
|
1317
|
-
onEditComplete
|
|
1613
|
+
onEditComplete,
|
|
1614
|
+
cellStyleFn
|
|
1318
1615
|
}
|
|
1319
1616
|
)
|
|
1320
1617
|
}
|
|
@@ -1504,7 +1801,8 @@ var TableBody = ({
|
|
|
1504
1801
|
recordFingerprint,
|
|
1505
1802
|
onEdit,
|
|
1506
1803
|
isEditing: editingCell?.rowKey === rk && editingCell?.columnKey === col.key,
|
|
1507
|
-
onEditComplete
|
|
1804
|
+
onEditComplete,
|
|
1805
|
+
cellStyleFn
|
|
1508
1806
|
}
|
|
1509
1807
|
)
|
|
1510
1808
|
}
|
|
@@ -1632,7 +1930,8 @@ var TableBody = ({
|
|
|
1632
1930
|
recordFingerprint,
|
|
1633
1931
|
onEdit,
|
|
1634
1932
|
isEditing: editingCell?.rowKey === rk && editingCell?.columnKey === col.key,
|
|
1635
|
-
onEditComplete
|
|
1933
|
+
onEditComplete,
|
|
1934
|
+
cellStyleFn
|
|
1636
1935
|
}
|
|
1637
1936
|
)
|
|
1638
1937
|
}
|
|
@@ -1727,7 +2026,13 @@ function BoltTable({
|
|
|
1727
2026
|
globalSearchValue,
|
|
1728
2027
|
onGlobalSearchChange,
|
|
1729
2028
|
toolbarContent,
|
|
1730
|
-
columnSettingsLabel
|
|
2029
|
+
columnSettingsLabel,
|
|
2030
|
+
aiMode = false,
|
|
2031
|
+
aiConfig,
|
|
2032
|
+
onAIQuery,
|
|
2033
|
+
onAIResponse,
|
|
2034
|
+
aiPlaceholder = "Ask AI anything about your data...",
|
|
2035
|
+
aiButtonLabel
|
|
1731
2036
|
}) {
|
|
1732
2037
|
const data = useMemo2(() => {
|
|
1733
2038
|
if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
|
|
@@ -1901,6 +2206,96 @@ function BoltTable({
|
|
|
1901
2206
|
document.removeEventListener("keydown", onKey);
|
|
1902
2207
|
};
|
|
1903
2208
|
}, [showColumnPicker]);
|
|
2209
|
+
const [aiBarOpen, setAiBarOpen] = useState3(false);
|
|
2210
|
+
const [aiQuery, setAiQuery] = useState3("");
|
|
2211
|
+
const [aiLoading, setAiLoading] = useState3(false);
|
|
2212
|
+
const [aiResult, setAiResult] = useState3(null);
|
|
2213
|
+
const [aiError, setAiError] = useState3(null);
|
|
2214
|
+
const aiInputRef = useRef4(null);
|
|
2215
|
+
const [aiStyleOps, setAiStyleOps] = useState3([]);
|
|
2216
|
+
const [aiCellStyleOps, setAiCellStyleOps] = useState3(
|
|
2217
|
+
[]
|
|
2218
|
+
);
|
|
2219
|
+
const [aiFilteredDataKeys, setAiFilteredDataKeys] = useState3(null);
|
|
2220
|
+
const [aiSortKey, setAiSortKey] = useState3(null);
|
|
2221
|
+
const [aiSortDir, setAiSortDir] = useState3(null);
|
|
2222
|
+
const onAIResponseRef = useRef4(onAIResponse);
|
|
2223
|
+
onAIResponseRef.current = onAIResponse;
|
|
2224
|
+
const handleAISubmit = useCallback2(async () => {
|
|
2225
|
+
const query = aiQuery.trim();
|
|
2226
|
+
if (!query) return;
|
|
2227
|
+
setAiLoading(true);
|
|
2228
|
+
setAiError(null);
|
|
2229
|
+
try {
|
|
2230
|
+
let response;
|
|
2231
|
+
if (onAIQuery) {
|
|
2232
|
+
response = await onAIQuery(query, {
|
|
2233
|
+
data,
|
|
2234
|
+
columns: initialColumns
|
|
2235
|
+
});
|
|
2236
|
+
} else if (aiConfig) {
|
|
2237
|
+
const sysPrompt = buildSystemPrompt(initialColumns, data);
|
|
2238
|
+
const raw = await callAI(aiConfig, sysPrompt, query);
|
|
2239
|
+
response = parseAIResponse(raw);
|
|
2240
|
+
} else {
|
|
2241
|
+
throw new Error("AI mode requires either aiConfig or onAIQuery prop");
|
|
2242
|
+
}
|
|
2243
|
+
const { filteredData, sortOp, styleOps: sOps, cellStyleOps: csOps, hideColumns, showColumns } = applyAIOperations(data, response.operations);
|
|
2244
|
+
setAiStyleOps(sOps);
|
|
2245
|
+
setAiCellStyleOps(csOps);
|
|
2246
|
+
if (response.operations.some((op) => op.type === "filter")) {
|
|
2247
|
+
const keySet = /* @__PURE__ */ new Set();
|
|
2248
|
+
filteredData.forEach((row, idx) => {
|
|
2249
|
+
const k = typeof rowKey === "function" ? rowKey(row) : String(row[typeof rowKey === "string" ? rowKey : "id"] ?? idx);
|
|
2250
|
+
keySet.add(k);
|
|
2251
|
+
});
|
|
2252
|
+
setAiFilteredDataKeys(keySet);
|
|
2253
|
+
} else {
|
|
2254
|
+
setAiFilteredDataKeys(null);
|
|
2255
|
+
}
|
|
2256
|
+
if (sortOp) {
|
|
2257
|
+
setAiSortKey(sortOp.column);
|
|
2258
|
+
setAiSortDir(sortOp.direction);
|
|
2259
|
+
} else {
|
|
2260
|
+
setAiSortKey(null);
|
|
2261
|
+
setAiSortDir(null);
|
|
2262
|
+
}
|
|
2263
|
+
if (hideColumns.length > 0 || showColumns.length > 0) {
|
|
2264
|
+
setColumns(
|
|
2265
|
+
(prev) => prev.map((col) => {
|
|
2266
|
+
if (hideColumns.includes(col.key)) return { ...col, hidden: true };
|
|
2267
|
+
if (showColumns.includes(col.key)) return { ...col, hidden: false };
|
|
2268
|
+
return col;
|
|
2269
|
+
})
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2272
|
+
setAiResult(response);
|
|
2273
|
+
onAIResponseRef.current?.(response);
|
|
2274
|
+
} catch (err) {
|
|
2275
|
+
setAiError(err instanceof Error ? err.message : "AI query failed");
|
|
2276
|
+
} finally {
|
|
2277
|
+
setAiLoading(false);
|
|
2278
|
+
}
|
|
2279
|
+
}, [aiQuery, aiConfig, onAIQuery, data, initialColumns, rowKey]);
|
|
2280
|
+
const handleAIClear = useCallback2(() => {
|
|
2281
|
+
setAiResult(null);
|
|
2282
|
+
setAiError(null);
|
|
2283
|
+
setAiStyleOps([]);
|
|
2284
|
+
setAiCellStyleOps([]);
|
|
2285
|
+
setAiFilteredDataKeys(null);
|
|
2286
|
+
setAiSortKey(null);
|
|
2287
|
+
setAiSortDir(null);
|
|
2288
|
+
setAiQuery("");
|
|
2289
|
+
}, []);
|
|
2290
|
+
const handleAIBarClose = useCallback2(() => {
|
|
2291
|
+
setAiBarOpen(false);
|
|
2292
|
+
handleAIClear();
|
|
2293
|
+
}, [handleAIClear]);
|
|
2294
|
+
React4.useEffect(() => {
|
|
2295
|
+
if (aiBarOpen && aiInputRef.current) {
|
|
2296
|
+
setTimeout(() => aiInputRef.current?.focus(), 300);
|
|
2297
|
+
}
|
|
2298
|
+
}, [aiBarOpen]);
|
|
1904
2299
|
const columnsWithPersistedWidths = useMemo2(
|
|
1905
2300
|
() => columns.map((col) => ({
|
|
1906
2301
|
...col,
|
|
@@ -2542,6 +2937,47 @@ function BoltTable({
|
|
|
2542
2937
|
}
|
|
2543
2938
|
return result;
|
|
2544
2939
|
}, [data, sortState, columnFilters, globalSearchValue, internalGlobalSearch]);
|
|
2940
|
+
const aiProcessedData = useMemo2(() => {
|
|
2941
|
+
let result = processedData;
|
|
2942
|
+
if (aiFilteredDataKeys) {
|
|
2943
|
+
result = result.filter((row, idx) => {
|
|
2944
|
+
if (row == null) return false;
|
|
2945
|
+
const k = typeof rowKey === "function" ? rowKey(row) : String(
|
|
2946
|
+
row[typeof rowKey === "string" ? rowKey : "id"] ?? idx
|
|
2947
|
+
);
|
|
2948
|
+
return aiFilteredDataKeys.has(k);
|
|
2949
|
+
});
|
|
2950
|
+
}
|
|
2951
|
+
if (aiSortKey && aiSortDir) {
|
|
2952
|
+
const dir = aiSortDir === "asc" ? 1 : -1;
|
|
2953
|
+
const col = aiSortKey;
|
|
2954
|
+
result = [...result].sort((a, b) => {
|
|
2955
|
+
const aVal = a[col];
|
|
2956
|
+
const bVal = b[col];
|
|
2957
|
+
if (aVal == null && bVal == null) return 0;
|
|
2958
|
+
if (aVal == null) return 1;
|
|
2959
|
+
if (bVal == null) return -1;
|
|
2960
|
+
if (typeof aVal === "number" && typeof bVal === "number")
|
|
2961
|
+
return (aVal - bVal) * dir;
|
|
2962
|
+
return String(aVal).localeCompare(String(bVal)) * dir;
|
|
2963
|
+
});
|
|
2964
|
+
}
|
|
2965
|
+
return result;
|
|
2966
|
+
}, [processedData, aiFilteredDataKeys, aiSortKey, aiSortDir, rowKey]);
|
|
2967
|
+
const getAIRowStyleForRecord = useCallback2(
|
|
2968
|
+
(record) => {
|
|
2969
|
+
if (aiStyleOps.length === 0) return void 0;
|
|
2970
|
+
return getAIRowStyle(record, aiStyleOps);
|
|
2971
|
+
},
|
|
2972
|
+
[aiStyleOps]
|
|
2973
|
+
);
|
|
2974
|
+
const getAICellStyleForRecord = useCallback2(
|
|
2975
|
+
(record, columnKey) => {
|
|
2976
|
+
if (aiCellStyleOps.length === 0) return void 0;
|
|
2977
|
+
return getAICellStyle(record, columnKey, aiCellStyleOps);
|
|
2978
|
+
},
|
|
2979
|
+
[aiCellStyleOps]
|
|
2980
|
+
);
|
|
2545
2981
|
const pinnedRowCacheRef = useRef4(/* @__PURE__ */ new Map());
|
|
2546
2982
|
const { pinnedTopRows, pinnedBottomRows, unpinnedProcessedData } = useMemo2(() => {
|
|
2547
2983
|
if (!resolvedRowPinning || !resolvedRowPinning.top?.length && !resolvedRowPinning.bottom?.length) {
|
|
@@ -2549,7 +2985,7 @@ function BoltTable({
|
|
|
2549
2985
|
return {
|
|
2550
2986
|
pinnedTopRows: [],
|
|
2551
2987
|
pinnedBottomRows: [],
|
|
2552
|
-
unpinnedProcessedData:
|
|
2988
|
+
unpinnedProcessedData: aiProcessedData
|
|
2553
2989
|
};
|
|
2554
2990
|
}
|
|
2555
2991
|
const topKeySet = new Set((resolvedRowPinning.top ?? []).map(String));
|
|
@@ -2559,7 +2995,7 @@ function BoltTable({
|
|
|
2559
2995
|
const topMap = /* @__PURE__ */ new Map();
|
|
2560
2996
|
const bottomMap = /* @__PURE__ */ new Map();
|
|
2561
2997
|
const rest = [];
|
|
2562
|
-
|
|
2998
|
+
aiProcessedData.forEach((row, idx) => {
|
|
2563
2999
|
if (row == null) return;
|
|
2564
3000
|
const key = getSafeRowKey(row, idx);
|
|
2565
3001
|
if (topKeySet.has(key)) {
|
|
@@ -2599,7 +3035,7 @@ function BoltTable({
|
|
|
2599
3035
|
unpinnedProcessedData: rest
|
|
2600
3036
|
};
|
|
2601
3037
|
}, [
|
|
2602
|
-
|
|
3038
|
+
aiProcessedData,
|
|
2603
3039
|
resolvedRowPinning,
|
|
2604
3040
|
getSafeRowKey,
|
|
2605
3041
|
keepPinnedRowsAcrossPages
|
|
@@ -2668,7 +3104,7 @@ function BoltTable({
|
|
|
2668
3104
|
return unpinnedProcessedData.slice(start, start + pgSize);
|
|
2669
3105
|
}, [unpinnedProcessedData, needsClientPagination, pgCurrent, pgSize]);
|
|
2670
3106
|
const shimmerCount = pgEnabled ? pgSize : 15;
|
|
2671
|
-
const showShimmer = isLoading &&
|
|
3107
|
+
const showShimmer = isLoading && aiProcessedData.length === 0;
|
|
2672
3108
|
const shimmerRowKeyField = typeof rowKey === "string" ? rowKey : "id";
|
|
2673
3109
|
const shimmerData = useMemo2(() => {
|
|
2674
3110
|
if (!showShimmer) return null;
|
|
@@ -2952,49 +3388,291 @@ function BoltTable({
|
|
|
2952
3388
|
border: 1px dashed ${accentColor} !important;
|
|
2953
3389
|
}
|
|
2954
3390
|
${onRowClick ? "[data-bt-cell] { cursor: pointer; }" : ""}
|
|
3391
|
+
@keyframes bt-spin { to { transform: rotate(360deg); } }
|
|
3392
|
+
@keyframes bt-ai-shimmer {
|
|
3393
|
+
0% { background-position: -200% 0; }
|
|
3394
|
+
100% { background-position: 200% 0; }
|
|
3395
|
+
}
|
|
2955
3396
|
` }),
|
|
2956
|
-
(!hideGlobalSearch || showColumnSettings) && /* @__PURE__ */ jsxs5(
|
|
3397
|
+
(!hideGlobalSearch || showColumnSettings || aiMode) && /* @__PURE__ */ jsxs5(
|
|
2957
3398
|
"div",
|
|
2958
3399
|
{
|
|
2959
3400
|
style: {
|
|
3401
|
+
position: "relative",
|
|
2960
3402
|
display: "flex",
|
|
2961
3403
|
alignItems: "center",
|
|
2962
3404
|
gap: 8,
|
|
2963
3405
|
padding: "6px 8px",
|
|
2964
3406
|
borderBottom: "1px solid rgba(128,128,128,0.2)",
|
|
2965
3407
|
fontSize: 12,
|
|
2966
|
-
flexShrink: 0
|
|
3408
|
+
flexShrink: 0,
|
|
3409
|
+
overflow: "hidden"
|
|
2967
3410
|
},
|
|
2968
3411
|
children: [
|
|
2969
|
-
|
|
3412
|
+
/* @__PURE__ */ jsxs5(
|
|
2970
3413
|
"div",
|
|
2971
3414
|
{
|
|
2972
3415
|
style: {
|
|
2973
3416
|
display: "flex",
|
|
2974
3417
|
alignItems: "center",
|
|
2975
|
-
gap:
|
|
3418
|
+
gap: 8,
|
|
2976
3419
|
flex: "1 1 0%",
|
|
2977
|
-
|
|
3420
|
+
opacity: aiBarOpen ? 0 : 1,
|
|
3421
|
+
transform: aiBarOpen ? "scale(0.97)" : "scale(1)",
|
|
3422
|
+
transition: "opacity 0.25s ease, transform 0.25s ease",
|
|
3423
|
+
pointerEvents: aiBarOpen ? "none" : "auto",
|
|
3424
|
+
minWidth: 0
|
|
3425
|
+
},
|
|
3426
|
+
children: [
|
|
3427
|
+
!hideGlobalSearch && /* @__PURE__ */ jsxs5(
|
|
3428
|
+
"div",
|
|
3429
|
+
{
|
|
3430
|
+
style: {
|
|
3431
|
+
display: "flex",
|
|
3432
|
+
alignItems: "center",
|
|
3433
|
+
gap: 4,
|
|
3434
|
+
flex: "1 1 0%",
|
|
3435
|
+
position: "relative"
|
|
3436
|
+
},
|
|
3437
|
+
children: [
|
|
3438
|
+
/* @__PURE__ */ jsx5(
|
|
3439
|
+
"span",
|
|
3440
|
+
{
|
|
3441
|
+
style: {
|
|
3442
|
+
display: "flex",
|
|
3443
|
+
color: "GrayText",
|
|
3444
|
+
flexShrink: 0
|
|
3445
|
+
},
|
|
3446
|
+
children: icons?.search ?? /* @__PURE__ */ jsx5(SearchIcon, { style: { width: 14, height: 14 } })
|
|
3447
|
+
}
|
|
3448
|
+
),
|
|
3449
|
+
/* @__PURE__ */ jsx5(
|
|
3450
|
+
"input",
|
|
3451
|
+
{
|
|
3452
|
+
type: "text",
|
|
3453
|
+
placeholder: "Search all columns...",
|
|
3454
|
+
value: globalSearchValue ?? internalGlobalSearch,
|
|
3455
|
+
onChange: (e) => {
|
|
3456
|
+
const v = e.target.value;
|
|
3457
|
+
if (onGlobalSearchChange) onGlobalSearchChange(v);
|
|
3458
|
+
else setInternalGlobalSearch(v);
|
|
3459
|
+
},
|
|
3460
|
+
style: {
|
|
3461
|
+
flex: "1 1 0%",
|
|
3462
|
+
border: "none",
|
|
3463
|
+
outline: "none",
|
|
3464
|
+
background: "transparent",
|
|
3465
|
+
font: "inherit",
|
|
3466
|
+
color: "inherit",
|
|
3467
|
+
padding: "4px 6px",
|
|
3468
|
+
minWidth: 0
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
),
|
|
3472
|
+
(globalSearchValue ?? internalGlobalSearch) && /* @__PURE__ */ jsx5(
|
|
3473
|
+
"button",
|
|
3474
|
+
{
|
|
3475
|
+
type: "button",
|
|
3476
|
+
onClick: () => {
|
|
3477
|
+
if (onGlobalSearchChange) onGlobalSearchChange("");
|
|
3478
|
+
else setInternalGlobalSearch("");
|
|
3479
|
+
},
|
|
3480
|
+
style: {
|
|
3481
|
+
display: "flex",
|
|
3482
|
+
alignItems: "center",
|
|
3483
|
+
justifyContent: "center",
|
|
3484
|
+
background: "none",
|
|
3485
|
+
border: "none",
|
|
3486
|
+
cursor: "pointer",
|
|
3487
|
+
padding: 2,
|
|
3488
|
+
color: "GrayText",
|
|
3489
|
+
flexShrink: 0
|
|
3490
|
+
},
|
|
3491
|
+
children: icons?.close ?? /* @__PURE__ */ jsx5(XIcon, { style: { width: 12, height: 12 } })
|
|
3492
|
+
}
|
|
3493
|
+
)
|
|
3494
|
+
]
|
|
3495
|
+
}
|
|
3496
|
+
),
|
|
3497
|
+
toolbarContent,
|
|
3498
|
+
showColumnSettings && /* @__PURE__ */ jsxs5("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
3499
|
+
/* @__PURE__ */ jsxs5(
|
|
3500
|
+
"button",
|
|
3501
|
+
{
|
|
3502
|
+
type: "button",
|
|
3503
|
+
onClick: () => setShowColumnPicker((p) => !p),
|
|
3504
|
+
style: {
|
|
3505
|
+
display: "flex",
|
|
3506
|
+
alignItems: "center",
|
|
3507
|
+
justifyContent: "center",
|
|
3508
|
+
background: "none",
|
|
3509
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
3510
|
+
borderRadius: 4,
|
|
3511
|
+
cursor: "pointer",
|
|
3512
|
+
padding: "4px 6px",
|
|
3513
|
+
color: "inherit",
|
|
3514
|
+
gap: 4,
|
|
3515
|
+
fontSize: 12
|
|
3516
|
+
},
|
|
3517
|
+
title: "Column settings",
|
|
3518
|
+
children: [
|
|
3519
|
+
icons?.columns ?? /* @__PURE__ */ jsx5(ColumnsIcon, { style: { width: 14, height: 14 } }),
|
|
3520
|
+
/* @__PURE__ */ jsx5("span", { children: columnSettingsLabel ?? "Columns" })
|
|
3521
|
+
]
|
|
3522
|
+
}
|
|
3523
|
+
),
|
|
3524
|
+
showColumnPicker && /* @__PURE__ */ jsx5(
|
|
3525
|
+
"div",
|
|
3526
|
+
{
|
|
3527
|
+
ref: columnPickerRef,
|
|
3528
|
+
style: {
|
|
3529
|
+
position: "absolute",
|
|
3530
|
+
top: "100%",
|
|
3531
|
+
right: 0,
|
|
3532
|
+
zIndex: 99999,
|
|
3533
|
+
minWidth: 200,
|
|
3534
|
+
maxHeight: 320,
|
|
3535
|
+
overflowY: "auto",
|
|
3536
|
+
borderRadius: 8,
|
|
3537
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
3538
|
+
boxShadow: "0 4px 24px rgba(0,0,0,0.12)",
|
|
3539
|
+
backdropFilter: "blur(16px)",
|
|
3540
|
+
WebkitBackdropFilter: "blur(16px)",
|
|
3541
|
+
backgroundColor: "rgba(128,128,128,0.08)",
|
|
3542
|
+
padding: "4px 0",
|
|
3543
|
+
marginTop: 4
|
|
3544
|
+
},
|
|
3545
|
+
children: initialColumns.filter(
|
|
3546
|
+
(c) => c.key !== "__select__" && c.key !== "__expand__"
|
|
3547
|
+
).map((col) => {
|
|
3548
|
+
const current = columns.find(
|
|
3549
|
+
(c) => c.key === col.key
|
|
3550
|
+
);
|
|
3551
|
+
const isHidden = current?.hidden ?? false;
|
|
3552
|
+
const isPinned = !!current?.pinned;
|
|
3553
|
+
return /* @__PURE__ */ jsxs5(
|
|
3554
|
+
"label",
|
|
3555
|
+
{
|
|
3556
|
+
style: {
|
|
3557
|
+
display: "flex",
|
|
3558
|
+
alignItems: "center",
|
|
3559
|
+
gap: 8,
|
|
3560
|
+
padding: "6px 12px",
|
|
3561
|
+
cursor: isPinned ? "not-allowed" : "pointer",
|
|
3562
|
+
opacity: isPinned ? 0.5 : 1,
|
|
3563
|
+
fontSize: 12
|
|
3564
|
+
},
|
|
3565
|
+
children: [
|
|
3566
|
+
/* @__PURE__ */ jsx5(
|
|
3567
|
+
"input",
|
|
3568
|
+
{
|
|
3569
|
+
type: "checkbox",
|
|
3570
|
+
checked: !isHidden,
|
|
3571
|
+
disabled: isPinned,
|
|
3572
|
+
onChange: () => {
|
|
3573
|
+
if (isPinned) return;
|
|
3574
|
+
handleToggleHide(col.key);
|
|
3575
|
+
},
|
|
3576
|
+
style: {
|
|
3577
|
+
cursor: isPinned ? "not-allowed" : "pointer",
|
|
3578
|
+
accentColor
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
),
|
|
3582
|
+
/* @__PURE__ */ jsx5(
|
|
3583
|
+
"span",
|
|
3584
|
+
{
|
|
3585
|
+
style: {
|
|
3586
|
+
overflow: "hidden",
|
|
3587
|
+
textOverflow: "ellipsis",
|
|
3588
|
+
whiteSpace: "nowrap"
|
|
3589
|
+
},
|
|
3590
|
+
children: typeof col.title === "string" ? col.title : col.key
|
|
3591
|
+
}
|
|
3592
|
+
)
|
|
3593
|
+
]
|
|
3594
|
+
},
|
|
3595
|
+
col.key
|
|
3596
|
+
);
|
|
3597
|
+
})
|
|
3598
|
+
}
|
|
3599
|
+
)
|
|
3600
|
+
] }),
|
|
3601
|
+
aiMode && /* @__PURE__ */ jsxs5(
|
|
3602
|
+
"button",
|
|
3603
|
+
{
|
|
3604
|
+
type: "button",
|
|
3605
|
+
onClick: () => setAiBarOpen(true),
|
|
3606
|
+
style: {
|
|
3607
|
+
display: "flex",
|
|
3608
|
+
alignItems: "center",
|
|
3609
|
+
justifyContent: "center",
|
|
3610
|
+
gap: 4,
|
|
3611
|
+
background: `linear-gradient(135deg, ${accentColor}18, ${accentColor}08)`,
|
|
3612
|
+
border: `1px solid ${accentColor}40`,
|
|
3613
|
+
borderRadius: 4,
|
|
3614
|
+
cursor: "pointer",
|
|
3615
|
+
padding: "4px 8px",
|
|
3616
|
+
color: accentColor,
|
|
3617
|
+
fontSize: 12,
|
|
3618
|
+
fontWeight: 500,
|
|
3619
|
+
flexShrink: 0,
|
|
3620
|
+
transition: "all 0.2s ease"
|
|
3621
|
+
},
|
|
3622
|
+
title: "Ask AI",
|
|
3623
|
+
children: [
|
|
3624
|
+
icons?.sparkles ?? /* @__PURE__ */ jsx5(SparklesIcon, { style: { width: 14, height: 14 } }),
|
|
3625
|
+
/* @__PURE__ */ jsx5("span", { children: aiButtonLabel ?? "Ask AI" })
|
|
3626
|
+
]
|
|
3627
|
+
}
|
|
3628
|
+
)
|
|
3629
|
+
]
|
|
3630
|
+
}
|
|
3631
|
+
),
|
|
3632
|
+
aiMode && /* @__PURE__ */ jsxs5(
|
|
3633
|
+
"div",
|
|
3634
|
+
{
|
|
3635
|
+
style: {
|
|
3636
|
+
position: "absolute",
|
|
3637
|
+
inset: 0,
|
|
3638
|
+
display: "flex",
|
|
3639
|
+
alignItems: "center",
|
|
3640
|
+
gap: 8,
|
|
3641
|
+
padding: "4px 8px",
|
|
3642
|
+
opacity: aiBarOpen ? 1 : 0,
|
|
3643
|
+
transform: aiBarOpen ? "translateX(0)" : "translateX(40px)",
|
|
3644
|
+
transition: "opacity 0.3s cubic-bezier(0.4,0,0.2,1), transform 0.3s cubic-bezier(0.4,0,0.2,1)",
|
|
3645
|
+
pointerEvents: aiBarOpen ? "auto" : "none",
|
|
3646
|
+
zIndex: 2,
|
|
3647
|
+
background: "inherit",
|
|
3648
|
+
backdropFilter: "blur(12px)",
|
|
3649
|
+
WebkitBackdropFilter: "blur(12px)"
|
|
2978
3650
|
},
|
|
2979
3651
|
children: [
|
|
2980
3652
|
/* @__PURE__ */ jsx5(
|
|
2981
3653
|
"span",
|
|
2982
3654
|
{
|
|
2983
|
-
style: {
|
|
2984
|
-
|
|
3655
|
+
style: {
|
|
3656
|
+
display: "flex",
|
|
3657
|
+
color: accentColor,
|
|
3658
|
+
flexShrink: 0
|
|
3659
|
+
},
|
|
3660
|
+
children: icons?.sparkles ?? /* @__PURE__ */ jsx5(SparklesIcon, { style: { width: 16, height: 16 } })
|
|
2985
3661
|
}
|
|
2986
3662
|
),
|
|
2987
3663
|
/* @__PURE__ */ jsx5(
|
|
2988
3664
|
"input",
|
|
2989
3665
|
{
|
|
3666
|
+
ref: aiInputRef,
|
|
2990
3667
|
type: "text",
|
|
2991
|
-
placeholder:
|
|
2992
|
-
value:
|
|
2993
|
-
onChange: (e) =>
|
|
2994
|
-
|
|
2995
|
-
if (
|
|
2996
|
-
|
|
3668
|
+
placeholder: aiPlaceholder,
|
|
3669
|
+
value: aiQuery,
|
|
3670
|
+
onChange: (e) => setAiQuery(e.target.value),
|
|
3671
|
+
onKeyDown: (e) => {
|
|
3672
|
+
if (e.key === "Enter" && !aiLoading) handleAISubmit();
|
|
3673
|
+
if (e.key === "Escape") handleAIBarClose();
|
|
2997
3674
|
},
|
|
3675
|
+
disabled: aiLoading,
|
|
2998
3676
|
style: {
|
|
2999
3677
|
flex: "1 1 0%",
|
|
3000
3678
|
border: "none",
|
|
@@ -3003,18 +3681,51 @@ function BoltTable({
|
|
|
3003
3681
|
font: "inherit",
|
|
3004
3682
|
color: "inherit",
|
|
3005
3683
|
padding: "4px 6px",
|
|
3006
|
-
minWidth: 0
|
|
3684
|
+
minWidth: 0,
|
|
3685
|
+
fontSize: 12
|
|
3007
3686
|
}
|
|
3008
3687
|
}
|
|
3009
3688
|
),
|
|
3010
|
-
|
|
3689
|
+
/* @__PURE__ */ jsx5(
|
|
3011
3690
|
"button",
|
|
3012
3691
|
{
|
|
3013
3692
|
type: "button",
|
|
3014
|
-
onClick:
|
|
3015
|
-
|
|
3016
|
-
|
|
3693
|
+
onClick: handleAISubmit,
|
|
3694
|
+
disabled: aiLoading || !aiQuery.trim(),
|
|
3695
|
+
style: {
|
|
3696
|
+
display: "flex",
|
|
3697
|
+
alignItems: "center",
|
|
3698
|
+
justifyContent: "center",
|
|
3699
|
+
background: aiQuery.trim() ? accentColor : "rgba(128,128,128,0.15)",
|
|
3700
|
+
border: "none",
|
|
3701
|
+
borderRadius: 4,
|
|
3702
|
+
cursor: aiLoading || !aiQuery.trim() ? "not-allowed" : "pointer",
|
|
3703
|
+
padding: "4px 8px",
|
|
3704
|
+
color: aiQuery.trim() ? "#fff" : "GrayText",
|
|
3705
|
+
transition: "all 0.2s ease",
|
|
3706
|
+
flexShrink: 0,
|
|
3707
|
+
gap: 4,
|
|
3708
|
+
fontSize: 12,
|
|
3709
|
+
opacity: aiLoading ? 0.7 : 1
|
|
3017
3710
|
},
|
|
3711
|
+
title: "Send",
|
|
3712
|
+
children: aiLoading ? /* @__PURE__ */ jsx5(Fragment4, { children: icons?.loader ?? /* @__PURE__ */ jsx5(
|
|
3713
|
+
LoaderIcon,
|
|
3714
|
+
{
|
|
3715
|
+
style: {
|
|
3716
|
+
width: 14,
|
|
3717
|
+
height: 14,
|
|
3718
|
+
animation: "bt-spin 1s linear infinite"
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
) }) : /* @__PURE__ */ jsx5(Fragment4, { children: icons?.send ?? /* @__PURE__ */ jsx5(SendIcon, { style: { width: 14, height: 14 } }) })
|
|
3722
|
+
}
|
|
3723
|
+
),
|
|
3724
|
+
/* @__PURE__ */ jsx5(
|
|
3725
|
+
"button",
|
|
3726
|
+
{
|
|
3727
|
+
type: "button",
|
|
3728
|
+
onClick: handleAIBarClose,
|
|
3018
3729
|
style: {
|
|
3019
3730
|
display: "flex",
|
|
3020
3731
|
alignItems: "center",
|
|
@@ -3026,114 +3737,96 @@ function BoltTable({
|
|
|
3026
3737
|
color: "GrayText",
|
|
3027
3738
|
flexShrink: 0
|
|
3028
3739
|
},
|
|
3029
|
-
|
|
3740
|
+
title: "Close AI",
|
|
3741
|
+
children: icons?.close ?? /* @__PURE__ */ jsx5(XIcon, { style: { width: 14, height: 14 } })
|
|
3030
3742
|
}
|
|
3031
3743
|
)
|
|
3032
3744
|
]
|
|
3033
3745
|
}
|
|
3034
|
-
)
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
/* @__PURE__ */ jsx5(
|
|
3119
|
-
"span",
|
|
3120
|
-
{
|
|
3121
|
-
style: {
|
|
3122
|
-
overflow: "hidden",
|
|
3123
|
-
textOverflow: "ellipsis",
|
|
3124
|
-
whiteSpace: "nowrap"
|
|
3125
|
-
},
|
|
3126
|
-
children: typeof col.title === "string" ? col.title : col.key
|
|
3127
|
-
}
|
|
3128
|
-
)
|
|
3129
|
-
]
|
|
3130
|
-
},
|
|
3131
|
-
col.key
|
|
3132
|
-
);
|
|
3133
|
-
})
|
|
3134
|
-
}
|
|
3135
|
-
)
|
|
3136
|
-
] })
|
|
3746
|
+
)
|
|
3747
|
+
]
|
|
3748
|
+
}
|
|
3749
|
+
),
|
|
3750
|
+
aiResult && /* @__PURE__ */ jsxs5(
|
|
3751
|
+
"div",
|
|
3752
|
+
{
|
|
3753
|
+
style: {
|
|
3754
|
+
display: "flex",
|
|
3755
|
+
alignItems: "center",
|
|
3756
|
+
gap: 8,
|
|
3757
|
+
padding: "6px 12px",
|
|
3758
|
+
fontSize: 12,
|
|
3759
|
+
borderBottom: "1px solid rgba(128,128,128,0.2)",
|
|
3760
|
+
background: `linear-gradient(90deg, ${accentColor}08, transparent)`,
|
|
3761
|
+
flexShrink: 0
|
|
3762
|
+
},
|
|
3763
|
+
children: [
|
|
3764
|
+
/* @__PURE__ */ jsx5("span", { style: { color: accentColor, display: "flex", flexShrink: 0 }, children: icons?.sparkles ?? /* @__PURE__ */ jsx5(SparklesIcon, { style: { width: 14, height: 14 } }) }),
|
|
3765
|
+
/* @__PURE__ */ jsx5("span", { style: { flex: "1 1 0%", opacity: 0.85 }, children: aiResult.message }),
|
|
3766
|
+
/* @__PURE__ */ jsxs5(
|
|
3767
|
+
"button",
|
|
3768
|
+
{
|
|
3769
|
+
type: "button",
|
|
3770
|
+
onClick: handleAIClear,
|
|
3771
|
+
style: {
|
|
3772
|
+
display: "flex",
|
|
3773
|
+
alignItems: "center",
|
|
3774
|
+
gap: 4,
|
|
3775
|
+
background: "none",
|
|
3776
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
3777
|
+
borderRadius: 4,
|
|
3778
|
+
cursor: "pointer",
|
|
3779
|
+
padding: "2px 8px",
|
|
3780
|
+
color: "inherit",
|
|
3781
|
+
fontSize: 11,
|
|
3782
|
+
flexShrink: 0,
|
|
3783
|
+
opacity: 0.7
|
|
3784
|
+
},
|
|
3785
|
+
title: "Clear AI results",
|
|
3786
|
+
children: [
|
|
3787
|
+
icons?.close ?? /* @__PURE__ */ jsx5(XIcon, { style: { width: 10, height: 10 } }),
|
|
3788
|
+
/* @__PURE__ */ jsx5("span", { children: "Clear" })
|
|
3789
|
+
]
|
|
3790
|
+
}
|
|
3791
|
+
)
|
|
3792
|
+
]
|
|
3793
|
+
}
|
|
3794
|
+
),
|
|
3795
|
+
aiError && !aiResult && /* @__PURE__ */ jsxs5(
|
|
3796
|
+
"div",
|
|
3797
|
+
{
|
|
3798
|
+
style: {
|
|
3799
|
+
display: "flex",
|
|
3800
|
+
alignItems: "center",
|
|
3801
|
+
gap: 8,
|
|
3802
|
+
padding: "6px 12px",
|
|
3803
|
+
fontSize: 12,
|
|
3804
|
+
borderBottom: "1px solid rgba(239,68,68,0.2)",
|
|
3805
|
+
background: "rgba(239,68,68,0.06)",
|
|
3806
|
+
color: "#ef4444",
|
|
3807
|
+
flexShrink: 0
|
|
3808
|
+
},
|
|
3809
|
+
children: [
|
|
3810
|
+
/* @__PURE__ */ jsx5("span", { style: { flex: "1 1 0%" }, children: aiError }),
|
|
3811
|
+
/* @__PURE__ */ jsx5(
|
|
3812
|
+
"button",
|
|
3813
|
+
{
|
|
3814
|
+
type: "button",
|
|
3815
|
+
onClick: () => setAiError(null),
|
|
3816
|
+
style: {
|
|
3817
|
+
display: "flex",
|
|
3818
|
+
alignItems: "center",
|
|
3819
|
+
justifyContent: "center",
|
|
3820
|
+
background: "none",
|
|
3821
|
+
border: "none",
|
|
3822
|
+
cursor: "pointer",
|
|
3823
|
+
padding: 2,
|
|
3824
|
+
color: "#ef4444",
|
|
3825
|
+
flexShrink: 0
|
|
3826
|
+
},
|
|
3827
|
+
children: icons?.close ?? /* @__PURE__ */ jsx5(XIcon, { style: { width: 12, height: 12 } })
|
|
3828
|
+
}
|
|
3829
|
+
)
|
|
3137
3830
|
]
|
|
3138
3831
|
}
|
|
3139
3832
|
),
|
|
@@ -3635,14 +4328,20 @@ function BoltTable({
|
|
|
3635
4328
|
gridTemplateColumns,
|
|
3636
4329
|
headerHeight: HEADER_HEIGHT,
|
|
3637
4330
|
rowClassName,
|
|
3638
|
-
rowStyle,
|
|
4331
|
+
rowStyle: aiStyleOps.length > 0 ? (record, index) => {
|
|
4332
|
+
const base = rowStyle ? rowStyle(record, index) : void 0;
|
|
4333
|
+
const ai = getAIRowStyleForRecord(record);
|
|
4334
|
+
if (!base && !ai) return {};
|
|
4335
|
+
return { ...base, ...ai };
|
|
4336
|
+
} : rowStyle,
|
|
3639
4337
|
bodyGridRow: hasColumnGroups ? 3 : 2,
|
|
3640
4338
|
onEdit,
|
|
3641
4339
|
editingCell,
|
|
3642
4340
|
onEditComplete: handleEditComplete,
|
|
3643
4341
|
enableDynamicRowHeight,
|
|
3644
4342
|
onRowHeightChange: handleRowHeightChange,
|
|
3645
|
-
columnGridIndexMap
|
|
4343
|
+
columnGridIndexMap,
|
|
4344
|
+
cellStyleFn: aiCellStyleOps.length > 0 ? (record, columnKey) => getAICellStyleForRecord(record, columnKey) : void 0
|
|
3646
4345
|
}
|
|
3647
4346
|
)
|
|
3648
4347
|
]
|
|
@@ -4197,44 +4896,60 @@ function BoltTable({
|
|
|
4197
4896
|
}
|
|
4198
4897
|
}
|
|
4199
4898
|
),
|
|
4200
|
-
menuCol.columnCellContextMenuItems.map((item) =>
|
|
4201
|
-
"
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
children: item.icon
|
|
4899
|
+
menuCol.columnCellContextMenuItems.map((item) => {
|
|
4900
|
+
const resolvedIcon = typeof item.icon === "function" ? menuRecord ? item.icon(
|
|
4901
|
+
menuCol.key,
|
|
4902
|
+
menuRecord,
|
|
4903
|
+
menuRowIndex
|
|
4904
|
+
) : null : item.icon;
|
|
4905
|
+
const resolvedLabel = typeof item.label === "function" ? menuRecord ? item.label(
|
|
4906
|
+
menuCol.key,
|
|
4907
|
+
menuRecord,
|
|
4908
|
+
menuRowIndex
|
|
4909
|
+
) : null : item.label;
|
|
4910
|
+
return /* @__PURE__ */ jsxs5(
|
|
4911
|
+
"button",
|
|
4912
|
+
{
|
|
4913
|
+
type: "button",
|
|
4914
|
+
"data-bt-ctx-item": "",
|
|
4915
|
+
disabled: item.disabled,
|
|
4916
|
+
style: {
|
|
4917
|
+
...btnStyle,
|
|
4918
|
+
cursor: item.disabled ? "not-allowed" : "pointer",
|
|
4919
|
+
opacity: item.disabled ? 0.5 : 1,
|
|
4920
|
+
color: item.danger ? "#ef4444" : "inherit"
|
|
4921
|
+
},
|
|
4922
|
+
onClick: () => {
|
|
4923
|
+
if (menuRecord && item.onClick) {
|
|
4924
|
+
item.onClick(
|
|
4925
|
+
menuCol.key,
|
|
4926
|
+
menuRecord,
|
|
4927
|
+
menuRowIndex
|
|
4928
|
+
);
|
|
4231
4929
|
}
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4930
|
+
setCellContextMenu(null);
|
|
4931
|
+
},
|
|
4932
|
+
children: [
|
|
4933
|
+
resolvedIcon && /* @__PURE__ */ jsx5(
|
|
4934
|
+
"span",
|
|
4935
|
+
{
|
|
4936
|
+
style: {
|
|
4937
|
+
display: "flex",
|
|
4938
|
+
width: 14,
|
|
4939
|
+
height: 14,
|
|
4940
|
+
alignItems: "center",
|
|
4941
|
+
justifyContent: "center",
|
|
4942
|
+
flexShrink: 0
|
|
4943
|
+
},
|
|
4944
|
+
children: resolvedIcon
|
|
4945
|
+
}
|
|
4946
|
+
),
|
|
4947
|
+
resolvedLabel
|
|
4948
|
+
]
|
|
4949
|
+
},
|
|
4950
|
+
item.key
|
|
4951
|
+
);
|
|
4952
|
+
})
|
|
4238
4953
|
] })
|
|
4239
4954
|
]
|
|
4240
4955
|
}
|
|
@@ -4244,9 +4959,15 @@ function BoltTable({
|
|
|
4244
4959
|
})()
|
|
4245
4960
|
] });
|
|
4246
4961
|
}
|
|
4962
|
+
|
|
4963
|
+
// src/types.ts
|
|
4964
|
+
function defineConfig(config) {
|
|
4965
|
+
return config;
|
|
4966
|
+
}
|
|
4247
4967
|
export {
|
|
4248
4968
|
BoltTable,
|
|
4249
4969
|
DraggableHeader_default as DraggableHeader,
|
|
4250
4970
|
ResizeOverlay_default as ResizeOverlay,
|
|
4251
|
-
TableBody_default as TableBody
|
|
4971
|
+
TableBody_default as TableBody,
|
|
4972
|
+
defineConfig
|
|
4252
4973
|
};
|