bolt-table 0.1.36 → 0.1.38
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 +106 -2
- package/dist/index.d.ts +106 -2
- package/dist/index.js +1109 -137
- package/dist/index.mjs +1107 -136
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,8 @@ __export(index_exports, {
|
|
|
33
33
|
BoltTable: () => BoltTable,
|
|
34
34
|
DraggableHeader: () => DraggableHeader_default,
|
|
35
35
|
ResizeOverlay: () => ResizeOverlay_default,
|
|
36
|
-
TableBody: () => TableBody_default
|
|
36
|
+
TableBody: () => TableBody_default,
|
|
37
|
+
defineConfig: () => defineConfig
|
|
37
38
|
});
|
|
38
39
|
module.exports = __toCommonJS(index_exports);
|
|
39
40
|
|
|
@@ -136,6 +137,18 @@ var XIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx
|
|
|
136
137
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 6 6 18" }),
|
|
137
138
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m6 6 12 12" })
|
|
138
139
|
] });
|
|
140
|
+
var SparklesIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgBase, style, className, children: [
|
|
141
|
+
/* @__PURE__ */ (0, import_jsx_runtime.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" }),
|
|
142
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 3v4" }),
|
|
143
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 17v4" }),
|
|
144
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 5h4" }),
|
|
145
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 19h4" })
|
|
146
|
+
] });
|
|
147
|
+
var SendIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgBase, style, className, children: [
|
|
148
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m22 2-7 20-4-9-9-4Z" }),
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M22 2 11 13" })
|
|
150
|
+
] });
|
|
151
|
+
var LoaderIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...svgBase, style, className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
|
|
139
152
|
|
|
140
153
|
// src/DraggableHeader.tsx
|
|
141
154
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
@@ -677,6 +690,298 @@ var DraggableHeader = import_react.default.memo(
|
|
|
677
690
|
DraggableHeader.displayName = "DraggableHeader";
|
|
678
691
|
var DraggableHeader_default = DraggableHeader;
|
|
679
692
|
|
|
693
|
+
// src/ai.ts
|
|
694
|
+
function detectColumnType(key, data) {
|
|
695
|
+
const values = [];
|
|
696
|
+
for (let i = 0; i < Math.min(data.length, 20); i++) {
|
|
697
|
+
const v = data[i]?.[key];
|
|
698
|
+
if (v != null) values.push(v);
|
|
699
|
+
}
|
|
700
|
+
if (values.length === 0) return { type: "unknown", sample: "" };
|
|
701
|
+
const allNumbers = values.every((v) => typeof v === "number");
|
|
702
|
+
const allBooleans = values.every((v) => typeof v === "boolean");
|
|
703
|
+
const uniqueVals = [...new Set(values.map(String))];
|
|
704
|
+
const sampleStr = uniqueVals.length <= 8 ? uniqueVals.join(", ") : uniqueVals.slice(0, 6).join(", ") + "...";
|
|
705
|
+
if (allBooleans) return { type: "boolean", sample: sampleStr };
|
|
706
|
+
if (allNumbers) {
|
|
707
|
+
const nums = values;
|
|
708
|
+
const min = Math.min(...nums);
|
|
709
|
+
const max = Math.max(...nums);
|
|
710
|
+
return { type: "number", sample: `range ${min}\u2013${max}` };
|
|
711
|
+
}
|
|
712
|
+
return { type: "string", sample: sampleStr };
|
|
713
|
+
}
|
|
714
|
+
var cachedSchema = null;
|
|
715
|
+
function buildSchemaFingerprint(columns, dataLen) {
|
|
716
|
+
return columns.filter((c) => c.key !== "__select__" && c.key !== "__expand__").map((c) => c.key).join(",") + `:${dataLen}`;
|
|
717
|
+
}
|
|
718
|
+
function buildSystemPrompt(columns, data) {
|
|
719
|
+
const fingerprint = buildSchemaFingerprint(columns, data.length);
|
|
720
|
+
if (cachedSchema?.fingerprint === fingerprint) {
|
|
721
|
+
return cachedSchema.prompt;
|
|
722
|
+
}
|
|
723
|
+
const cols = columns.filter((c) => c.key !== "__select__" && c.key !== "__expand__");
|
|
724
|
+
const schema = cols.map((c) => {
|
|
725
|
+
const key = c.dataIndex ?? c.key;
|
|
726
|
+
const title = typeof c.title === "string" ? c.title : c.key;
|
|
727
|
+
const info = detectColumnType(key, data);
|
|
728
|
+
const w = c.width ?? 150;
|
|
729
|
+
const pin = c.pinned ? `, pinned: "${c.pinned}"` : "";
|
|
730
|
+
const hidden = c.hidden ? ", hidden: true" : "";
|
|
731
|
+
const vals = info.sample ? "|vals: " + info.sample : "";
|
|
732
|
+
return ` ${c.key}|${key}|"${title}"|${info.type}|w:${w}${pin}${hidden}${vals}`;
|
|
733
|
+
}).join("\n");
|
|
734
|
+
const sample = data.slice(0, 3).map((row) => {
|
|
735
|
+
const obj = {};
|
|
736
|
+
for (const col of cols) {
|
|
737
|
+
const di = col.dataIndex ?? col.key;
|
|
738
|
+
obj[di] = row[di];
|
|
739
|
+
}
|
|
740
|
+
return obj;
|
|
741
|
+
});
|
|
742
|
+
const prompt = `Data table AI. Respond ONLY with valid JSON, no markdown/explanation.
|
|
743
|
+
|
|
744
|
+
SCHEMA (key|dataIndex|title|type|width|flags|sample):
|
|
745
|
+
${schema}
|
|
746
|
+
|
|
747
|
+
SAMPLE (${sample.length}/${data.length} rows):
|
|
748
|
+
${JSON.stringify(sample)}
|
|
749
|
+
|
|
750
|
+
COLUMN ORDER: [${cols.map((c) => `"${c.key}"`).join(",")}]
|
|
751
|
+
|
|
752
|
+
OPS (combine any):
|
|
753
|
+
filter: {type:"filter",conditions:[{column:"<dataIndex>",op:"<op>",value:<v>}],logic:"and"|"or"}
|
|
754
|
+
sort: {type:"sort",column:"<dataIndex>",direction:"asc"|"desc"}
|
|
755
|
+
rowStyle: {type:"rowStyle",conditions:[...],logic:"and"|"or",style:{cssProp:"val"}}
|
|
756
|
+
cellStyle: {type:"cellStyle",column:"<dataIndex>",conditions:[...],logic:"and"|"or",style:{cssProp:"val"}}
|
|
757
|
+
hideColumns: {type:"hideColumns",columns:["key",...]}
|
|
758
|
+
showColumns: {type:"showColumns",columns:["key",...]}
|
|
759
|
+
resizeColumn: {type:"resizeColumn",column:"<key>",width:<px>}
|
|
760
|
+
reorderColumns: {type:"reorderColumns",order:["key1","key2",...]} (full column order)
|
|
761
|
+
pinColumn: {type:"pinColumn",column:"<key>",pinned:"left"|"right"|false}
|
|
762
|
+
setPage: {type:"setPage",page:<number>}
|
|
763
|
+
|
|
764
|
+
OPS: eq,neq,gt,gte,lt,lte,contains,notContains,startsWith,endsWith,in,notIn
|
|
765
|
+
|
|
766
|
+
FORMAT: {"operations":[...],"message":"brief description"}
|
|
767
|
+
|
|
768
|
+
RULES:
|
|
769
|
+
- Use dataIndex for data ops, key for column ops (hide/show/resize/reorder/pin).
|
|
770
|
+
- Colors: semi-transparent rgba. CSS props: camelCase.
|
|
771
|
+
- reorderColumns: provide FULL ordered array of ALL visible column keys.
|
|
772
|
+
- resizeColumn width: integer pixels (min 40, max 800).
|
|
773
|
+
- Combine multiple ops freely. Message: concise plain English.`;
|
|
774
|
+
cachedSchema = { fingerprint, prompt };
|
|
775
|
+
return prompt;
|
|
776
|
+
}
|
|
777
|
+
async function callAI(config, systemPrompt, userQuery) {
|
|
778
|
+
const { provider, apiKey, model, baseUrl, maxTokens = 1024, temperature = 0.1 } = config;
|
|
779
|
+
if (provider === "openai" || provider === "custom") {
|
|
780
|
+
const url = baseUrl ? `${baseUrl.replace(/\/$/, "")}/chat/completions` : "https://api.openai.com/v1/chat/completions";
|
|
781
|
+
const res = await fetch(url, {
|
|
782
|
+
method: "POST",
|
|
783
|
+
headers: {
|
|
784
|
+
"Content-Type": "application/json",
|
|
785
|
+
Authorization: `Bearer ${apiKey}`
|
|
786
|
+
},
|
|
787
|
+
body: JSON.stringify({
|
|
788
|
+
model: model ?? "gpt-4o-mini",
|
|
789
|
+
messages: [
|
|
790
|
+
{ role: "system", content: systemPrompt },
|
|
791
|
+
{ role: "user", content: userQuery }
|
|
792
|
+
],
|
|
793
|
+
max_tokens: maxTokens,
|
|
794
|
+
temperature
|
|
795
|
+
})
|
|
796
|
+
});
|
|
797
|
+
if (!res.ok) {
|
|
798
|
+
const body = await res.text().catch(() => "");
|
|
799
|
+
throw new Error(`AI request failed (${res.status}): ${body}`);
|
|
800
|
+
}
|
|
801
|
+
const json = await res.json();
|
|
802
|
+
return json.choices?.[0]?.message?.content ?? "";
|
|
803
|
+
}
|
|
804
|
+
if (provider === "anthropic") {
|
|
805
|
+
const url = baseUrl ? `${baseUrl.replace(/\/$/, "")}/messages` : "https://api.anthropic.com/v1/messages";
|
|
806
|
+
const res = await fetch(url, {
|
|
807
|
+
method: "POST",
|
|
808
|
+
headers: {
|
|
809
|
+
"Content-Type": "application/json",
|
|
810
|
+
"x-api-key": apiKey,
|
|
811
|
+
"anthropic-version": "2023-06-01",
|
|
812
|
+
"anthropic-dangerous-direct-browser-access": "true"
|
|
813
|
+
},
|
|
814
|
+
body: JSON.stringify({
|
|
815
|
+
model: model ?? "claude-sonnet-4-20250514",
|
|
816
|
+
system: systemPrompt,
|
|
817
|
+
messages: [{ role: "user", content: userQuery }],
|
|
818
|
+
max_tokens: maxTokens,
|
|
819
|
+
temperature
|
|
820
|
+
})
|
|
821
|
+
});
|
|
822
|
+
if (!res.ok) {
|
|
823
|
+
const body = await res.text().catch(() => "");
|
|
824
|
+
throw new Error(`AI request failed (${res.status}): ${body}`);
|
|
825
|
+
}
|
|
826
|
+
const json = await res.json();
|
|
827
|
+
const textBlock = json.content?.find(
|
|
828
|
+
(b) => b.type === "text"
|
|
829
|
+
);
|
|
830
|
+
return textBlock?.text ?? "";
|
|
831
|
+
}
|
|
832
|
+
throw new Error(`Unsupported AI provider: ${provider}`);
|
|
833
|
+
}
|
|
834
|
+
function parseAIResponse(raw) {
|
|
835
|
+
let text = raw.trim();
|
|
836
|
+
const fenceMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
837
|
+
if (fenceMatch) text = fenceMatch[1].trim();
|
|
838
|
+
const start = text.indexOf("{");
|
|
839
|
+
const end = text.lastIndexOf("}");
|
|
840
|
+
if (start !== -1 && end > start) {
|
|
841
|
+
text = text.slice(start, end + 1);
|
|
842
|
+
}
|
|
843
|
+
const parsed = JSON.parse(text);
|
|
844
|
+
if (!parsed.operations || !Array.isArray(parsed.operations)) {
|
|
845
|
+
throw new Error("Invalid AI response: missing operations array");
|
|
846
|
+
}
|
|
847
|
+
return {
|
|
848
|
+
operations: parsed.operations,
|
|
849
|
+
message: parsed.message ?? "AI operations applied."
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
function evaluateCondition(condition, row) {
|
|
853
|
+
const rawVal = row[condition.column];
|
|
854
|
+
const target = condition.value;
|
|
855
|
+
switch (condition.op) {
|
|
856
|
+
case "eq":
|
|
857
|
+
return rawVal == target;
|
|
858
|
+
case "neq":
|
|
859
|
+
return rawVal != target;
|
|
860
|
+
case "gt":
|
|
861
|
+
return Number(rawVal) > Number(target);
|
|
862
|
+
case "gte":
|
|
863
|
+
return Number(rawVal) >= Number(target);
|
|
864
|
+
case "lt":
|
|
865
|
+
return Number(rawVal) < Number(target);
|
|
866
|
+
case "lte":
|
|
867
|
+
return Number(rawVal) <= Number(target);
|
|
868
|
+
case "contains":
|
|
869
|
+
return String(rawVal ?? "").toLowerCase().includes(String(target).toLowerCase());
|
|
870
|
+
case "notContains":
|
|
871
|
+
return !String(rawVal ?? "").toLowerCase().includes(String(target).toLowerCase());
|
|
872
|
+
case "startsWith":
|
|
873
|
+
return String(rawVal ?? "").toLowerCase().startsWith(String(target).toLowerCase());
|
|
874
|
+
case "endsWith":
|
|
875
|
+
return String(rawVal ?? "").toLowerCase().endsWith(String(target).toLowerCase());
|
|
876
|
+
case "in":
|
|
877
|
+
if (Array.isArray(target)) {
|
|
878
|
+
return target.some((t) => rawVal == t);
|
|
879
|
+
}
|
|
880
|
+
return false;
|
|
881
|
+
case "notIn":
|
|
882
|
+
if (Array.isArray(target)) {
|
|
883
|
+
return !target.some((t) => rawVal == t);
|
|
884
|
+
}
|
|
885
|
+
return true;
|
|
886
|
+
default:
|
|
887
|
+
return true;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
function matchesConditions(conditions, logic, row) {
|
|
891
|
+
if (!conditions || conditions.length === 0) return true;
|
|
892
|
+
if (logic === "or") {
|
|
893
|
+
return conditions.some((c) => evaluateCondition(c, row));
|
|
894
|
+
}
|
|
895
|
+
return conditions.every((c) => evaluateCondition(c, row));
|
|
896
|
+
}
|
|
897
|
+
function applyAIFilter(data, op) {
|
|
898
|
+
return data.filter((row) => matchesConditions(op.conditions, op.logic, row));
|
|
899
|
+
}
|
|
900
|
+
function applyAISort(data, op) {
|
|
901
|
+
const dir = op.direction === "asc" ? 1 : -1;
|
|
902
|
+
const col = op.column;
|
|
903
|
+
return [...data].sort((a, b) => {
|
|
904
|
+
const aVal = a[col];
|
|
905
|
+
const bVal = b[col];
|
|
906
|
+
if (aVal == null && bVal == null) return 0;
|
|
907
|
+
if (aVal == null) return 1;
|
|
908
|
+
if (bVal == null) return -1;
|
|
909
|
+
if (typeof aVal === "number" && typeof bVal === "number")
|
|
910
|
+
return (aVal - bVal) * dir;
|
|
911
|
+
return String(aVal).localeCompare(String(bVal)) * dir;
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
function getAIRowStyle(row, ops) {
|
|
915
|
+
let merged;
|
|
916
|
+
for (const op of ops) {
|
|
917
|
+
if (matchesConditions(op.conditions, op.logic, row)) {
|
|
918
|
+
if (!merged) merged = {};
|
|
919
|
+
Object.assign(merged, op.style);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return merged;
|
|
923
|
+
}
|
|
924
|
+
function getAICellStyle(row, columnKey, ops) {
|
|
925
|
+
let merged;
|
|
926
|
+
for (const op of ops) {
|
|
927
|
+
if (op.column === columnKey && matchesConditions(op.conditions, op.logic, row)) {
|
|
928
|
+
if (!merged) merged = {};
|
|
929
|
+
Object.assign(merged, op.style);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
return merged;
|
|
933
|
+
}
|
|
934
|
+
function applyAIOperations(data, operations) {
|
|
935
|
+
let filteredData = data;
|
|
936
|
+
let sortOp = null;
|
|
937
|
+
const styleOps = [];
|
|
938
|
+
const cellStyleOps = [];
|
|
939
|
+
const hideColumns = [];
|
|
940
|
+
const showColumns = [];
|
|
941
|
+
const resizeOps = [];
|
|
942
|
+
let reorderOp = null;
|
|
943
|
+
const pinOps = [];
|
|
944
|
+
let setPageOp = null;
|
|
945
|
+
for (const op of operations) {
|
|
946
|
+
switch (op.type) {
|
|
947
|
+
case "filter":
|
|
948
|
+
filteredData = applyAIFilter(filteredData, op);
|
|
949
|
+
break;
|
|
950
|
+
case "sort":
|
|
951
|
+
sortOp = op;
|
|
952
|
+
break;
|
|
953
|
+
case "rowStyle":
|
|
954
|
+
styleOps.push(op);
|
|
955
|
+
break;
|
|
956
|
+
case "cellStyle":
|
|
957
|
+
cellStyleOps.push(op);
|
|
958
|
+
break;
|
|
959
|
+
case "hideColumns":
|
|
960
|
+
hideColumns.push(...op.columns);
|
|
961
|
+
break;
|
|
962
|
+
case "showColumns":
|
|
963
|
+
showColumns.push(...op.columns);
|
|
964
|
+
break;
|
|
965
|
+
case "resizeColumn":
|
|
966
|
+
resizeOps.push(op);
|
|
967
|
+
break;
|
|
968
|
+
case "reorderColumns":
|
|
969
|
+
reorderOp = op;
|
|
970
|
+
break;
|
|
971
|
+
case "pinColumn":
|
|
972
|
+
pinOps.push(op);
|
|
973
|
+
break;
|
|
974
|
+
case "setPage":
|
|
975
|
+
setPageOp = op;
|
|
976
|
+
break;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
if (sortOp) {
|
|
980
|
+
filteredData = applyAISort(filteredData, sortOp);
|
|
981
|
+
}
|
|
982
|
+
return { filteredData, sortOp, styleOps, cellStyleOps, hideColumns, showColumns, resizeOps, reorderOp, pinOps, setPageOp };
|
|
983
|
+
}
|
|
984
|
+
|
|
680
985
|
// src/ResizeOverlay.tsx
|
|
681
986
|
var import_react2 = require("react");
|
|
682
987
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
@@ -898,9 +1203,11 @@ var Cell = import_react3.default.memo(
|
|
|
898
1203
|
isLoading,
|
|
899
1204
|
onEdit,
|
|
900
1205
|
isEditing,
|
|
901
|
-
onEditComplete
|
|
1206
|
+
onEditComplete,
|
|
1207
|
+
cellStyleFn
|
|
902
1208
|
}) => {
|
|
903
1209
|
const isPinned = Boolean(column.pinned);
|
|
1210
|
+
const extraCellStyle = cellStyleFn?.(record, column.dataIndex ?? column.key);
|
|
904
1211
|
if (isLoading && column.key !== "__select__" && column.key !== "__expand__") {
|
|
905
1212
|
const shimmerContent = column.shimmerRender ? column.shimmerRender() : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
906
1213
|
"div",
|
|
@@ -1052,7 +1359,8 @@ var Cell = import_react3.default.memo(
|
|
|
1052
1359
|
minWidth: 0,
|
|
1053
1360
|
...column.style,
|
|
1054
1361
|
...isPinned ? styles?.pinnedCell : void 0,
|
|
1055
|
-
...styles?.cell
|
|
1362
|
+
...styles?.cell,
|
|
1363
|
+
...extraCellStyle
|
|
1056
1364
|
},
|
|
1057
1365
|
children: isSystem ? content : showEditor ? content : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1058
1366
|
"div",
|
|
@@ -1079,6 +1387,7 @@ var Cell = import_react3.default.memo(
|
|
|
1079
1387
|
if (prev.onEdit !== next.onEdit) return false;
|
|
1080
1388
|
if (prev.isEditing !== next.isEditing) return false;
|
|
1081
1389
|
if (prev.onEditComplete !== next.onEditComplete) return false;
|
|
1390
|
+
if (prev.cellStyleFn !== next.cellStyleFn) return false;
|
|
1082
1391
|
if (prev.column.key === "__select__") {
|
|
1083
1392
|
return prev.isSelected === next.isSelected && prev.normalizedSelectedKeys === next.normalizedSelectedKeys;
|
|
1084
1393
|
}
|
|
@@ -1180,7 +1489,8 @@ var TableBody = ({
|
|
|
1180
1489
|
onEditComplete,
|
|
1181
1490
|
enableDynamicRowHeight = false,
|
|
1182
1491
|
onRowHeightChange,
|
|
1183
|
-
columnGridIndexMap
|
|
1492
|
+
columnGridIndexMap,
|
|
1493
|
+
cellStyleFn
|
|
1184
1494
|
}) => {
|
|
1185
1495
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1186
1496
|
const totalSize = rowVirtualizer.getTotalSize();
|
|
@@ -1309,7 +1619,8 @@ var TableBody = ({
|
|
|
1309
1619
|
recordFingerprint,
|
|
1310
1620
|
onEdit,
|
|
1311
1621
|
isEditing: editingCell?.rowKey === rowKey && editingCell?.columnKey === col.key,
|
|
1312
|
-
onEditComplete
|
|
1622
|
+
onEditComplete,
|
|
1623
|
+
cellStyleFn
|
|
1313
1624
|
}
|
|
1314
1625
|
)
|
|
1315
1626
|
}
|
|
@@ -1346,7 +1657,8 @@ var TableBody = ({
|
|
|
1346
1657
|
recordFingerprint,
|
|
1347
1658
|
onEdit,
|
|
1348
1659
|
isEditing: editingCell?.rowKey === rowKey && editingCell?.columnKey === col.key,
|
|
1349
|
-
onEditComplete
|
|
1660
|
+
onEditComplete,
|
|
1661
|
+
cellStyleFn
|
|
1350
1662
|
}
|
|
1351
1663
|
)
|
|
1352
1664
|
}
|
|
@@ -1536,7 +1848,8 @@ var TableBody = ({
|
|
|
1536
1848
|
recordFingerprint,
|
|
1537
1849
|
onEdit,
|
|
1538
1850
|
isEditing: editingCell?.rowKey === rk && editingCell?.columnKey === col.key,
|
|
1539
|
-
onEditComplete
|
|
1851
|
+
onEditComplete,
|
|
1852
|
+
cellStyleFn
|
|
1540
1853
|
}
|
|
1541
1854
|
)
|
|
1542
1855
|
}
|
|
@@ -1664,7 +1977,8 @@ var TableBody = ({
|
|
|
1664
1977
|
recordFingerprint,
|
|
1665
1978
|
onEdit,
|
|
1666
1979
|
isEditing: editingCell?.rowKey === rk && editingCell?.columnKey === col.key,
|
|
1667
|
-
onEditComplete
|
|
1980
|
+
onEditComplete,
|
|
1981
|
+
cellStyleFn
|
|
1668
1982
|
}
|
|
1669
1983
|
)
|
|
1670
1984
|
}
|
|
@@ -1759,7 +2073,13 @@ function BoltTable({
|
|
|
1759
2073
|
globalSearchValue,
|
|
1760
2074
|
onGlobalSearchChange,
|
|
1761
2075
|
toolbarContent,
|
|
1762
|
-
columnSettingsLabel
|
|
2076
|
+
columnSettingsLabel,
|
|
2077
|
+
aiMode = false,
|
|
2078
|
+
aiConfig,
|
|
2079
|
+
onAIQuery,
|
|
2080
|
+
onAIResponse,
|
|
2081
|
+
aiPlaceholder = "Ask AI anything about your data...",
|
|
2082
|
+
aiButtonLabel
|
|
1763
2083
|
}) {
|
|
1764
2084
|
const data = (0, import_react4.useMemo)(() => {
|
|
1765
2085
|
if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
|
|
@@ -1933,6 +2253,213 @@ function BoltTable({
|
|
|
1933
2253
|
document.removeEventListener("keydown", onKey);
|
|
1934
2254
|
};
|
|
1935
2255
|
}, [showColumnPicker]);
|
|
2256
|
+
const [aiBarOpen, setAiBarOpen] = (0, import_react4.useState)(false);
|
|
2257
|
+
const [aiQuery, setAiQuery] = (0, import_react4.useState)("");
|
|
2258
|
+
const [aiLoading, setAiLoading] = (0, import_react4.useState)(false);
|
|
2259
|
+
const [aiResult, setAiResult] = (0, import_react4.useState)(null);
|
|
2260
|
+
const [aiError, setAiError] = (0, import_react4.useState)(null);
|
|
2261
|
+
const aiInputRef = (0, import_react4.useRef)(null);
|
|
2262
|
+
const [aiStyleOps, setAiStyleOps] = (0, import_react4.useState)([]);
|
|
2263
|
+
const [aiCellStyleOps, setAiCellStyleOps] = (0, import_react4.useState)(
|
|
2264
|
+
[]
|
|
2265
|
+
);
|
|
2266
|
+
const [aiFilteredDataKeys, setAiFilteredDataKeys] = (0, import_react4.useState)(null);
|
|
2267
|
+
const [aiSortKey, setAiSortKey] = (0, import_react4.useState)(null);
|
|
2268
|
+
const [aiSortDir, setAiSortDir] = (0, import_react4.useState)(null);
|
|
2269
|
+
const aiFiltersStorageKey = columnPersistence && typeof columnPersistence === "object" ? `bt-ai-filters-${columnPersistence.storageKey}` : "bt-ai-filters";
|
|
2270
|
+
const [savedAIFilters, setSavedAIFilters] = (0, import_react4.useState)(() => {
|
|
2271
|
+
try {
|
|
2272
|
+
const raw = localStorage.getItem(aiFiltersStorageKey);
|
|
2273
|
+
return raw ? JSON.parse(raw) : [];
|
|
2274
|
+
} catch {
|
|
2275
|
+
return [];
|
|
2276
|
+
}
|
|
2277
|
+
});
|
|
2278
|
+
const [showSavedFilters, setShowSavedFilters] = (0, import_react4.useState)(false);
|
|
2279
|
+
const savedFiltersRef = (0, import_react4.useRef)(null);
|
|
2280
|
+
import_react4.default.useEffect(() => {
|
|
2281
|
+
if (!showSavedFilters) return;
|
|
2282
|
+
const close = (e) => {
|
|
2283
|
+
if (savedFiltersRef.current && !savedFiltersRef.current.contains(e.target)) {
|
|
2284
|
+
setShowSavedFilters(false);
|
|
2285
|
+
}
|
|
2286
|
+
};
|
|
2287
|
+
document.addEventListener("mousedown", close);
|
|
2288
|
+
return () => document.removeEventListener("mousedown", close);
|
|
2289
|
+
}, [showSavedFilters]);
|
|
2290
|
+
const saveCurrentAIFilter = (0, import_react4.useCallback)(() => {
|
|
2291
|
+
if (!aiResult) return;
|
|
2292
|
+
const label = aiQuery || aiResult.message;
|
|
2293
|
+
const entry = { label, operations: aiResult.operations, query: aiQuery };
|
|
2294
|
+
const next = [...savedAIFilters, entry];
|
|
2295
|
+
setSavedAIFilters(next);
|
|
2296
|
+
try {
|
|
2297
|
+
localStorage.setItem(aiFiltersStorageKey, JSON.stringify(next));
|
|
2298
|
+
} catch {
|
|
2299
|
+
}
|
|
2300
|
+
}, [aiResult, aiQuery, savedAIFilters, aiFiltersStorageKey]);
|
|
2301
|
+
const removeSavedFilter = (0, import_react4.useCallback)((index) => {
|
|
2302
|
+
const next = savedAIFilters.filter((_, i) => i !== index);
|
|
2303
|
+
setSavedAIFilters(next);
|
|
2304
|
+
try {
|
|
2305
|
+
localStorage.setItem(aiFiltersStorageKey, JSON.stringify(next));
|
|
2306
|
+
} catch {
|
|
2307
|
+
}
|
|
2308
|
+
}, [savedAIFilters, aiFiltersStorageKey]);
|
|
2309
|
+
const applySavedFilter = (0, import_react4.useCallback)((filter) => {
|
|
2310
|
+
const { filteredData, sortOp, styleOps: sOps, cellStyleOps: csOps, hideColumns: hideCols, showColumns: showCols, resizeOps, reorderOp, pinOps, setPageOp } = applyAIOperations(data, filter.operations);
|
|
2311
|
+
setAiStyleOps(sOps);
|
|
2312
|
+
setAiCellStyleOps(csOps);
|
|
2313
|
+
if (filter.operations.some((op) => op.type === "filter")) {
|
|
2314
|
+
const keySet = /* @__PURE__ */ new Set();
|
|
2315
|
+
filteredData.forEach((row, idx) => {
|
|
2316
|
+
const k = typeof rowKey === "function" ? rowKey(row) : String(row[typeof rowKey === "string" ? rowKey : "id"] ?? idx);
|
|
2317
|
+
keySet.add(k);
|
|
2318
|
+
});
|
|
2319
|
+
setAiFilteredDataKeys(keySet);
|
|
2320
|
+
} else {
|
|
2321
|
+
setAiFilteredDataKeys(null);
|
|
2322
|
+
}
|
|
2323
|
+
if (sortOp) {
|
|
2324
|
+
setAiSortKey(sortOp.column);
|
|
2325
|
+
setAiSortDir(sortOp.direction);
|
|
2326
|
+
} else {
|
|
2327
|
+
setAiSortKey(null);
|
|
2328
|
+
setAiSortDir(null);
|
|
2329
|
+
}
|
|
2330
|
+
if (hideCols.length > 0 || showCols.length > 0) {
|
|
2331
|
+
setColumns(
|
|
2332
|
+
(prev) => prev.map((col) => {
|
|
2333
|
+
if (hideCols.includes(col.key)) return { ...col, hidden: true };
|
|
2334
|
+
if (showCols.includes(col.key)) return { ...col, hidden: false };
|
|
2335
|
+
return col;
|
|
2336
|
+
})
|
|
2337
|
+
);
|
|
2338
|
+
}
|
|
2339
|
+
for (const rOp of resizeOps) {
|
|
2340
|
+
const w = Math.max(40, Math.min(800, rOp.width));
|
|
2341
|
+
setColumnWidths((prev) => {
|
|
2342
|
+
const n = new Map(prev);
|
|
2343
|
+
n.set(rOp.column, w);
|
|
2344
|
+
return n;
|
|
2345
|
+
});
|
|
2346
|
+
onColumnResize?.(rOp.column, w);
|
|
2347
|
+
}
|
|
2348
|
+
if (reorderOp) {
|
|
2349
|
+
setColumnOrder(reorderOp.order);
|
|
2350
|
+
onColumnOrderChange?.(reorderOp.order);
|
|
2351
|
+
}
|
|
2352
|
+
for (const pOp of pinOps) {
|
|
2353
|
+
setColumns(
|
|
2354
|
+
(prev) => prev.map((col) => col.key === pOp.column ? { ...col, pinned: pOp.pinned } : col)
|
|
2355
|
+
);
|
|
2356
|
+
onColumnPin?.(pOp.column, pOp.pinned);
|
|
2357
|
+
}
|
|
2358
|
+
if (setPageOp) {
|
|
2359
|
+
setInternalPage(setPageOp.page);
|
|
2360
|
+
}
|
|
2361
|
+
setAiResult({ operations: filter.operations, message: `Applied saved filter: ${filter.label}` });
|
|
2362
|
+
setShowSavedFilters(false);
|
|
2363
|
+
}, [data, rowKey, onColumnResize, onColumnOrderChange, onColumnPin]);
|
|
2364
|
+
const onAIResponseRef = (0, import_react4.useRef)(onAIResponse);
|
|
2365
|
+
onAIResponseRef.current = onAIResponse;
|
|
2366
|
+
const handleAISubmit = (0, import_react4.useCallback)(async () => {
|
|
2367
|
+
const query = aiQuery.trim();
|
|
2368
|
+
if (!query) return;
|
|
2369
|
+
setAiLoading(true);
|
|
2370
|
+
setAiError(null);
|
|
2371
|
+
try {
|
|
2372
|
+
let response;
|
|
2373
|
+
if (onAIQuery) {
|
|
2374
|
+
response = await onAIQuery(query, {
|
|
2375
|
+
data,
|
|
2376
|
+
columns: initialColumns
|
|
2377
|
+
});
|
|
2378
|
+
} else if (aiConfig) {
|
|
2379
|
+
const sysPrompt = buildSystemPrompt(initialColumns, data);
|
|
2380
|
+
const raw = await callAI(aiConfig, sysPrompt, query);
|
|
2381
|
+
response = parseAIResponse(raw);
|
|
2382
|
+
} else {
|
|
2383
|
+
throw new Error("AI mode requires either aiConfig or onAIQuery prop");
|
|
2384
|
+
}
|
|
2385
|
+
const { filteredData, sortOp, styleOps: sOps, cellStyleOps: csOps, hideColumns: hideCols, showColumns: showCols, resizeOps, reorderOp, pinOps, setPageOp } = applyAIOperations(data, response.operations);
|
|
2386
|
+
setAiStyleOps(sOps);
|
|
2387
|
+
setAiCellStyleOps(csOps);
|
|
2388
|
+
if (response.operations.some((op) => op.type === "filter")) {
|
|
2389
|
+
const keySet = /* @__PURE__ */ new Set();
|
|
2390
|
+
filteredData.forEach((row, idx) => {
|
|
2391
|
+
const k = typeof rowKey === "function" ? rowKey(row) : String(row[typeof rowKey === "string" ? rowKey : "id"] ?? idx);
|
|
2392
|
+
keySet.add(k);
|
|
2393
|
+
});
|
|
2394
|
+
setAiFilteredDataKeys(keySet);
|
|
2395
|
+
} else {
|
|
2396
|
+
setAiFilteredDataKeys(null);
|
|
2397
|
+
}
|
|
2398
|
+
if (sortOp) {
|
|
2399
|
+
setAiSortKey(sortOp.column);
|
|
2400
|
+
setAiSortDir(sortOp.direction);
|
|
2401
|
+
} else {
|
|
2402
|
+
setAiSortKey(null);
|
|
2403
|
+
setAiSortDir(null);
|
|
2404
|
+
}
|
|
2405
|
+
if (hideCols.length > 0 || showCols.length > 0) {
|
|
2406
|
+
setColumns(
|
|
2407
|
+
(prev) => prev.map((col) => {
|
|
2408
|
+
if (hideCols.includes(col.key)) return { ...col, hidden: true };
|
|
2409
|
+
if (showCols.includes(col.key)) return { ...col, hidden: false };
|
|
2410
|
+
return col;
|
|
2411
|
+
})
|
|
2412
|
+
);
|
|
2413
|
+
}
|
|
2414
|
+
for (const rOp of resizeOps) {
|
|
2415
|
+
const w = Math.max(40, Math.min(800, rOp.width));
|
|
2416
|
+
setColumnWidths((prev) => {
|
|
2417
|
+
const n = new Map(prev);
|
|
2418
|
+
n.set(rOp.column, w);
|
|
2419
|
+
return n;
|
|
2420
|
+
});
|
|
2421
|
+
onColumnResize?.(rOp.column, w);
|
|
2422
|
+
}
|
|
2423
|
+
if (reorderOp) {
|
|
2424
|
+
setColumnOrder(reorderOp.order);
|
|
2425
|
+
onColumnOrderChange?.(reorderOp.order);
|
|
2426
|
+
}
|
|
2427
|
+
for (const pOp of pinOps) {
|
|
2428
|
+
setColumns(
|
|
2429
|
+
(prev) => prev.map((col) => col.key === pOp.column ? { ...col, pinned: pOp.pinned } : col)
|
|
2430
|
+
);
|
|
2431
|
+
onColumnPin?.(pOp.column, pOp.pinned);
|
|
2432
|
+
}
|
|
2433
|
+
if (setPageOp) {
|
|
2434
|
+
setInternalPage(setPageOp.page);
|
|
2435
|
+
}
|
|
2436
|
+
setAiResult(response);
|
|
2437
|
+
onAIResponseRef.current?.(response);
|
|
2438
|
+
} catch (err) {
|
|
2439
|
+
setAiError(err instanceof Error ? err.message : "AI query failed");
|
|
2440
|
+
} finally {
|
|
2441
|
+
setAiLoading(false);
|
|
2442
|
+
}
|
|
2443
|
+
}, [aiQuery, aiConfig, onAIQuery, data, initialColumns, rowKey]);
|
|
2444
|
+
const handleAIClear = (0, import_react4.useCallback)(() => {
|
|
2445
|
+
setAiResult(null);
|
|
2446
|
+
setAiError(null);
|
|
2447
|
+
setAiStyleOps([]);
|
|
2448
|
+
setAiCellStyleOps([]);
|
|
2449
|
+
setAiFilteredDataKeys(null);
|
|
2450
|
+
setAiSortKey(null);
|
|
2451
|
+
setAiSortDir(null);
|
|
2452
|
+
setAiQuery("");
|
|
2453
|
+
}, []);
|
|
2454
|
+
const handleAIBarClose = (0, import_react4.useCallback)(() => {
|
|
2455
|
+
setAiBarOpen(false);
|
|
2456
|
+
handleAIClear();
|
|
2457
|
+
}, [handleAIClear]);
|
|
2458
|
+
import_react4.default.useEffect(() => {
|
|
2459
|
+
if (aiBarOpen && aiInputRef.current) {
|
|
2460
|
+
setTimeout(() => aiInputRef.current?.focus(), 300);
|
|
2461
|
+
}
|
|
2462
|
+
}, [aiBarOpen]);
|
|
1936
2463
|
const columnsWithPersistedWidths = (0, import_react4.useMemo)(
|
|
1937
2464
|
() => columns.map((col) => ({
|
|
1938
2465
|
...col,
|
|
@@ -2574,6 +3101,47 @@ function BoltTable({
|
|
|
2574
3101
|
}
|
|
2575
3102
|
return result;
|
|
2576
3103
|
}, [data, sortState, columnFilters, globalSearchValue, internalGlobalSearch]);
|
|
3104
|
+
const aiProcessedData = (0, import_react4.useMemo)(() => {
|
|
3105
|
+
let result = processedData;
|
|
3106
|
+
if (aiFilteredDataKeys) {
|
|
3107
|
+
result = result.filter((row, idx) => {
|
|
3108
|
+
if (row == null) return false;
|
|
3109
|
+
const k = typeof rowKey === "function" ? rowKey(row) : String(
|
|
3110
|
+
row[typeof rowKey === "string" ? rowKey : "id"] ?? idx
|
|
3111
|
+
);
|
|
3112
|
+
return aiFilteredDataKeys.has(k);
|
|
3113
|
+
});
|
|
3114
|
+
}
|
|
3115
|
+
if (aiSortKey && aiSortDir) {
|
|
3116
|
+
const dir = aiSortDir === "asc" ? 1 : -1;
|
|
3117
|
+
const col = aiSortKey;
|
|
3118
|
+
result = [...result].sort((a, b) => {
|
|
3119
|
+
const aVal = a[col];
|
|
3120
|
+
const bVal = b[col];
|
|
3121
|
+
if (aVal == null && bVal == null) return 0;
|
|
3122
|
+
if (aVal == null) return 1;
|
|
3123
|
+
if (bVal == null) return -1;
|
|
3124
|
+
if (typeof aVal === "number" && typeof bVal === "number")
|
|
3125
|
+
return (aVal - bVal) * dir;
|
|
3126
|
+
return String(aVal).localeCompare(String(bVal)) * dir;
|
|
3127
|
+
});
|
|
3128
|
+
}
|
|
3129
|
+
return result;
|
|
3130
|
+
}, [processedData, aiFilteredDataKeys, aiSortKey, aiSortDir, rowKey]);
|
|
3131
|
+
const getAIRowStyleForRecord = (0, import_react4.useCallback)(
|
|
3132
|
+
(record) => {
|
|
3133
|
+
if (aiStyleOps.length === 0) return void 0;
|
|
3134
|
+
return getAIRowStyle(record, aiStyleOps);
|
|
3135
|
+
},
|
|
3136
|
+
[aiStyleOps]
|
|
3137
|
+
);
|
|
3138
|
+
const getAICellStyleForRecord = (0, import_react4.useCallback)(
|
|
3139
|
+
(record, columnKey) => {
|
|
3140
|
+
if (aiCellStyleOps.length === 0) return void 0;
|
|
3141
|
+
return getAICellStyle(record, columnKey, aiCellStyleOps);
|
|
3142
|
+
},
|
|
3143
|
+
[aiCellStyleOps]
|
|
3144
|
+
);
|
|
2577
3145
|
const pinnedRowCacheRef = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
|
|
2578
3146
|
const { pinnedTopRows, pinnedBottomRows, unpinnedProcessedData } = (0, import_react4.useMemo)(() => {
|
|
2579
3147
|
if (!resolvedRowPinning || !resolvedRowPinning.top?.length && !resolvedRowPinning.bottom?.length) {
|
|
@@ -2581,7 +3149,7 @@ function BoltTable({
|
|
|
2581
3149
|
return {
|
|
2582
3150
|
pinnedTopRows: [],
|
|
2583
3151
|
pinnedBottomRows: [],
|
|
2584
|
-
unpinnedProcessedData:
|
|
3152
|
+
unpinnedProcessedData: aiProcessedData
|
|
2585
3153
|
};
|
|
2586
3154
|
}
|
|
2587
3155
|
const topKeySet = new Set((resolvedRowPinning.top ?? []).map(String));
|
|
@@ -2591,7 +3159,7 @@ function BoltTable({
|
|
|
2591
3159
|
const topMap = /* @__PURE__ */ new Map();
|
|
2592
3160
|
const bottomMap = /* @__PURE__ */ new Map();
|
|
2593
3161
|
const rest = [];
|
|
2594
|
-
|
|
3162
|
+
aiProcessedData.forEach((row, idx) => {
|
|
2595
3163
|
if (row == null) return;
|
|
2596
3164
|
const key = getSafeRowKey(row, idx);
|
|
2597
3165
|
if (topKeySet.has(key)) {
|
|
@@ -2631,7 +3199,7 @@ function BoltTable({
|
|
|
2631
3199
|
unpinnedProcessedData: rest
|
|
2632
3200
|
};
|
|
2633
3201
|
}, [
|
|
2634
|
-
|
|
3202
|
+
aiProcessedData,
|
|
2635
3203
|
resolvedRowPinning,
|
|
2636
3204
|
getSafeRowKey,
|
|
2637
3205
|
keepPinnedRowsAcrossPages
|
|
@@ -2700,7 +3268,7 @@ function BoltTable({
|
|
|
2700
3268
|
return unpinnedProcessedData.slice(start, start + pgSize);
|
|
2701
3269
|
}, [unpinnedProcessedData, needsClientPagination, pgCurrent, pgSize]);
|
|
2702
3270
|
const shimmerCount = pgEnabled ? pgSize : 15;
|
|
2703
|
-
const showShimmer = isLoading &&
|
|
3271
|
+
const showShimmer = isLoading && aiProcessedData.length === 0;
|
|
2704
3272
|
const shimmerRowKeyField = typeof rowKey === "string" ? rowKey : "id";
|
|
2705
3273
|
const shimmerData = (0, import_react4.useMemo)(() => {
|
|
2706
3274
|
if (!showShimmer) return null;
|
|
@@ -2984,49 +3552,395 @@ function BoltTable({
|
|
|
2984
3552
|
border: 1px dashed ${accentColor} !important;
|
|
2985
3553
|
}
|
|
2986
3554
|
${onRowClick ? "[data-bt-cell] { cursor: pointer; }" : ""}
|
|
3555
|
+
@keyframes bt-spin { to { transform: rotate(360deg); } }
|
|
3556
|
+
@keyframes bt-ai-shimmer {
|
|
3557
|
+
0% { background-position: -200% 0; }
|
|
3558
|
+
100% { background-position: 200% 0; }
|
|
3559
|
+
}
|
|
2987
3560
|
` }),
|
|
2988
|
-
(!hideGlobalSearch || showColumnSettings) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3561
|
+
(!hideGlobalSearch || showColumnSettings || aiMode) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2989
3562
|
"div",
|
|
2990
3563
|
{
|
|
2991
3564
|
style: {
|
|
3565
|
+
position: "relative",
|
|
2992
3566
|
display: "flex",
|
|
2993
3567
|
alignItems: "center",
|
|
2994
3568
|
gap: 8,
|
|
2995
3569
|
padding: "6px 8px",
|
|
2996
3570
|
borderBottom: "1px solid rgba(128,128,128,0.2)",
|
|
2997
3571
|
fontSize: 12,
|
|
2998
|
-
flexShrink: 0
|
|
3572
|
+
flexShrink: 0,
|
|
3573
|
+
zIndex: 20
|
|
2999
3574
|
},
|
|
3000
3575
|
children: [
|
|
3001
|
-
|
|
3576
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3002
3577
|
"div",
|
|
3003
3578
|
{
|
|
3004
3579
|
style: {
|
|
3005
3580
|
display: "flex",
|
|
3006
3581
|
alignItems: "center",
|
|
3007
|
-
gap:
|
|
3582
|
+
gap: 8,
|
|
3008
3583
|
flex: "1 1 0%",
|
|
3009
|
-
|
|
3584
|
+
opacity: aiBarOpen ? 0 : 1,
|
|
3585
|
+
transform: aiBarOpen ? "scale(0.97)" : "scale(1)",
|
|
3586
|
+
transition: "opacity 0.25s ease, transform 0.25s ease",
|
|
3587
|
+
pointerEvents: aiBarOpen ? "none" : "auto",
|
|
3588
|
+
minWidth: 0
|
|
3589
|
+
},
|
|
3590
|
+
children: [
|
|
3591
|
+
!hideGlobalSearch && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3592
|
+
"div",
|
|
3593
|
+
{
|
|
3594
|
+
style: {
|
|
3595
|
+
display: "flex",
|
|
3596
|
+
alignItems: "center",
|
|
3597
|
+
gap: 4,
|
|
3598
|
+
flex: "1 1 0%",
|
|
3599
|
+
position: "relative"
|
|
3600
|
+
},
|
|
3601
|
+
children: [
|
|
3602
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3603
|
+
"span",
|
|
3604
|
+
{
|
|
3605
|
+
style: {
|
|
3606
|
+
display: "flex",
|
|
3607
|
+
color: "GrayText",
|
|
3608
|
+
flexShrink: 0
|
|
3609
|
+
},
|
|
3610
|
+
children: icons?.search ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SearchIcon, { style: { width: 14, height: 14 } })
|
|
3611
|
+
}
|
|
3612
|
+
),
|
|
3613
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3614
|
+
"input",
|
|
3615
|
+
{
|
|
3616
|
+
type: "text",
|
|
3617
|
+
placeholder: "Search all columns...",
|
|
3618
|
+
value: globalSearchValue ?? internalGlobalSearch,
|
|
3619
|
+
onChange: (e) => {
|
|
3620
|
+
const v = e.target.value;
|
|
3621
|
+
if (onGlobalSearchChange) onGlobalSearchChange(v);
|
|
3622
|
+
else setInternalGlobalSearch(v);
|
|
3623
|
+
},
|
|
3624
|
+
style: {
|
|
3625
|
+
flex: "1 1 0%",
|
|
3626
|
+
border: "none",
|
|
3627
|
+
outline: "none",
|
|
3628
|
+
background: "transparent",
|
|
3629
|
+
font: "inherit",
|
|
3630
|
+
color: "inherit",
|
|
3631
|
+
padding: "4px 6px",
|
|
3632
|
+
minWidth: 0
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
),
|
|
3636
|
+
(globalSearchValue ?? internalGlobalSearch) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3637
|
+
"button",
|
|
3638
|
+
{
|
|
3639
|
+
type: "button",
|
|
3640
|
+
onClick: () => {
|
|
3641
|
+
if (onGlobalSearchChange) onGlobalSearchChange("");
|
|
3642
|
+
else setInternalGlobalSearch("");
|
|
3643
|
+
},
|
|
3644
|
+
style: {
|
|
3645
|
+
display: "flex",
|
|
3646
|
+
alignItems: "center",
|
|
3647
|
+
justifyContent: "center",
|
|
3648
|
+
background: "none",
|
|
3649
|
+
border: "none",
|
|
3650
|
+
cursor: "pointer",
|
|
3651
|
+
padding: 2,
|
|
3652
|
+
color: "GrayText",
|
|
3653
|
+
flexShrink: 0
|
|
3654
|
+
},
|
|
3655
|
+
children: icons?.close ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(XIcon, { style: { width: 12, height: 12 } })
|
|
3656
|
+
}
|
|
3657
|
+
)
|
|
3658
|
+
]
|
|
3659
|
+
}
|
|
3660
|
+
),
|
|
3661
|
+
toolbarContent,
|
|
3662
|
+
showColumnSettings && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
3663
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3664
|
+
"button",
|
|
3665
|
+
{
|
|
3666
|
+
type: "button",
|
|
3667
|
+
onClick: () => setShowColumnPicker((p) => !p),
|
|
3668
|
+
style: {
|
|
3669
|
+
display: "flex",
|
|
3670
|
+
alignItems: "center",
|
|
3671
|
+
justifyContent: "center",
|
|
3672
|
+
background: "none",
|
|
3673
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
3674
|
+
borderRadius: 4,
|
|
3675
|
+
cursor: "pointer",
|
|
3676
|
+
padding: "4px 6px",
|
|
3677
|
+
color: "inherit",
|
|
3678
|
+
gap: 4,
|
|
3679
|
+
fontSize: 12
|
|
3680
|
+
},
|
|
3681
|
+
title: "Column settings",
|
|
3682
|
+
children: [
|
|
3683
|
+
icons?.columns ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ColumnsIcon, { style: { width: 14, height: 14 } }),
|
|
3684
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: columnSettingsLabel ?? "Columns" })
|
|
3685
|
+
]
|
|
3686
|
+
}
|
|
3687
|
+
),
|
|
3688
|
+
showColumnPicker && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3689
|
+
"div",
|
|
3690
|
+
{
|
|
3691
|
+
ref: columnPickerRef,
|
|
3692
|
+
style: {
|
|
3693
|
+
position: "absolute",
|
|
3694
|
+
top: "100%",
|
|
3695
|
+
right: 0,
|
|
3696
|
+
zIndex: 99999,
|
|
3697
|
+
minWidth: 200,
|
|
3698
|
+
maxHeight: 320,
|
|
3699
|
+
overflowY: "auto",
|
|
3700
|
+
borderRadius: 8,
|
|
3701
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
3702
|
+
boxShadow: "0 4px 24px rgba(0,0,0,0.12)",
|
|
3703
|
+
backdropFilter: "blur(16px)",
|
|
3704
|
+
WebkitBackdropFilter: "blur(16px)",
|
|
3705
|
+
backgroundColor: "rgba(128,128,128,0.08)",
|
|
3706
|
+
padding: "4px 0",
|
|
3707
|
+
marginTop: 4
|
|
3708
|
+
},
|
|
3709
|
+
children: initialColumns.filter(
|
|
3710
|
+
(c) => c.key !== "__select__" && c.key !== "__expand__"
|
|
3711
|
+
).map((col) => {
|
|
3712
|
+
const current = columns.find(
|
|
3713
|
+
(c) => c.key === col.key
|
|
3714
|
+
);
|
|
3715
|
+
const isHidden = current?.hidden ?? false;
|
|
3716
|
+
const isPinned = !!current?.pinned;
|
|
3717
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3718
|
+
"label",
|
|
3719
|
+
{
|
|
3720
|
+
style: {
|
|
3721
|
+
display: "flex",
|
|
3722
|
+
alignItems: "center",
|
|
3723
|
+
gap: 8,
|
|
3724
|
+
padding: "6px 12px",
|
|
3725
|
+
cursor: isPinned ? "not-allowed" : "pointer",
|
|
3726
|
+
opacity: isPinned ? 0.5 : 1,
|
|
3727
|
+
fontSize: 12
|
|
3728
|
+
},
|
|
3729
|
+
children: [
|
|
3730
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3731
|
+
"input",
|
|
3732
|
+
{
|
|
3733
|
+
type: "checkbox",
|
|
3734
|
+
checked: !isHidden,
|
|
3735
|
+
disabled: isPinned,
|
|
3736
|
+
onChange: () => {
|
|
3737
|
+
if (isPinned) return;
|
|
3738
|
+
handleToggleHide(col.key);
|
|
3739
|
+
},
|
|
3740
|
+
style: {
|
|
3741
|
+
cursor: isPinned ? "not-allowed" : "pointer",
|
|
3742
|
+
accentColor
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
),
|
|
3746
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3747
|
+
"span",
|
|
3748
|
+
{
|
|
3749
|
+
style: {
|
|
3750
|
+
overflow: "hidden",
|
|
3751
|
+
textOverflow: "ellipsis",
|
|
3752
|
+
whiteSpace: "nowrap"
|
|
3753
|
+
},
|
|
3754
|
+
children: typeof col.title === "string" ? col.title : col.key
|
|
3755
|
+
}
|
|
3756
|
+
)
|
|
3757
|
+
]
|
|
3758
|
+
},
|
|
3759
|
+
col.key
|
|
3760
|
+
);
|
|
3761
|
+
})
|
|
3762
|
+
}
|
|
3763
|
+
)
|
|
3764
|
+
] }),
|
|
3765
|
+
aiMode && savedAIFilters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: savedFiltersRef, style: { position: "relative", flexShrink: 0 }, children: [
|
|
3766
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3767
|
+
"button",
|
|
3768
|
+
{
|
|
3769
|
+
type: "button",
|
|
3770
|
+
onClick: () => setShowSavedFilters((p) => !p),
|
|
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: "4px 6px",
|
|
3780
|
+
color: "inherit",
|
|
3781
|
+
fontSize: 12
|
|
3782
|
+
},
|
|
3783
|
+
title: "Saved AI filters",
|
|
3784
|
+
children: [
|
|
3785
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polygon", { points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" }) }),
|
|
3786
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: savedAIFilters.length })
|
|
3787
|
+
]
|
|
3788
|
+
}
|
|
3789
|
+
),
|
|
3790
|
+
showSavedFilters && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3791
|
+
"div",
|
|
3792
|
+
{
|
|
3793
|
+
style: {
|
|
3794
|
+
position: "absolute",
|
|
3795
|
+
top: "100%",
|
|
3796
|
+
right: 0,
|
|
3797
|
+
zIndex: 99999,
|
|
3798
|
+
minWidth: 240,
|
|
3799
|
+
maxWidth: 360,
|
|
3800
|
+
maxHeight: 320,
|
|
3801
|
+
overflowY: "auto",
|
|
3802
|
+
borderRadius: 8,
|
|
3803
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
3804
|
+
boxShadow: "0 4px 24px rgba(0,0,0,0.12)",
|
|
3805
|
+
backdropFilter: "blur(16px)",
|
|
3806
|
+
WebkitBackdropFilter: "blur(16px)",
|
|
3807
|
+
backgroundColor: "rgba(128,128,128,0.08)",
|
|
3808
|
+
padding: "4px 0",
|
|
3809
|
+
marginTop: 4
|
|
3810
|
+
},
|
|
3811
|
+
children: [
|
|
3812
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { padding: "6px 12px", fontSize: 11, opacity: 0.5, fontWeight: 600 }, children: "Saved Filters" }),
|
|
3813
|
+
savedAIFilters.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3814
|
+
"div",
|
|
3815
|
+
{
|
|
3816
|
+
style: {
|
|
3817
|
+
display: "flex",
|
|
3818
|
+
alignItems: "center",
|
|
3819
|
+
gap: 6,
|
|
3820
|
+
padding: "6px 12px",
|
|
3821
|
+
cursor: "pointer",
|
|
3822
|
+
fontSize: 12
|
|
3823
|
+
},
|
|
3824
|
+
onMouseEnter: (e) => {
|
|
3825
|
+
e.currentTarget.style.backgroundColor = "rgba(128,128,128,0.15)";
|
|
3826
|
+
},
|
|
3827
|
+
onMouseLeave: (e) => {
|
|
3828
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
3829
|
+
},
|
|
3830
|
+
children: [
|
|
3831
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3832
|
+
"span",
|
|
3833
|
+
{
|
|
3834
|
+
style: { flex: "1 1 0%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
3835
|
+
onClick: () => applySavedFilter(f),
|
|
3836
|
+
children: f.label
|
|
3837
|
+
}
|
|
3838
|
+
),
|
|
3839
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3840
|
+
"button",
|
|
3841
|
+
{
|
|
3842
|
+
type: "button",
|
|
3843
|
+
onClick: (e) => {
|
|
3844
|
+
e.stopPropagation();
|
|
3845
|
+
removeSavedFilter(i);
|
|
3846
|
+
},
|
|
3847
|
+
style: {
|
|
3848
|
+
display: "flex",
|
|
3849
|
+
alignItems: "center",
|
|
3850
|
+
background: "none",
|
|
3851
|
+
border: "none",
|
|
3852
|
+
cursor: "pointer",
|
|
3853
|
+
padding: 2,
|
|
3854
|
+
color: "GrayText",
|
|
3855
|
+
flexShrink: 0
|
|
3856
|
+
},
|
|
3857
|
+
title: "Remove",
|
|
3858
|
+
children: icons?.close ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(XIcon, { style: { width: 10, height: 10 } })
|
|
3859
|
+
}
|
|
3860
|
+
)
|
|
3861
|
+
]
|
|
3862
|
+
},
|
|
3863
|
+
i
|
|
3864
|
+
))
|
|
3865
|
+
]
|
|
3866
|
+
}
|
|
3867
|
+
)
|
|
3868
|
+
] }),
|
|
3869
|
+
aiMode && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3870
|
+
"button",
|
|
3871
|
+
{
|
|
3872
|
+
type: "button",
|
|
3873
|
+
onClick: () => setAiBarOpen(true),
|
|
3874
|
+
style: {
|
|
3875
|
+
display: "flex",
|
|
3876
|
+
alignItems: "center",
|
|
3877
|
+
justifyContent: "center",
|
|
3878
|
+
gap: 4,
|
|
3879
|
+
background: `linear-gradient(135deg, ${accentColor}18, ${accentColor}08)`,
|
|
3880
|
+
border: `1px solid ${accentColor}40`,
|
|
3881
|
+
borderRadius: 4,
|
|
3882
|
+
cursor: "pointer",
|
|
3883
|
+
padding: "4px 8px",
|
|
3884
|
+
color: accentColor,
|
|
3885
|
+
fontSize: 12,
|
|
3886
|
+
fontWeight: 500,
|
|
3887
|
+
flexShrink: 0,
|
|
3888
|
+
transition: "all 0.2s ease"
|
|
3889
|
+
},
|
|
3890
|
+
title: "Ask AI",
|
|
3891
|
+
children: [
|
|
3892
|
+
icons?.sparkles ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SparklesIcon, { style: { width: 14, height: 14 } }),
|
|
3893
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: aiButtonLabel ?? "Ask AI" })
|
|
3894
|
+
]
|
|
3895
|
+
}
|
|
3896
|
+
)
|
|
3897
|
+
]
|
|
3898
|
+
}
|
|
3899
|
+
),
|
|
3900
|
+
aiMode && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3901
|
+
"div",
|
|
3902
|
+
{
|
|
3903
|
+
style: {
|
|
3904
|
+
position: "absolute",
|
|
3905
|
+
inset: 0,
|
|
3906
|
+
display: "flex",
|
|
3907
|
+
alignItems: "center",
|
|
3908
|
+
gap: 8,
|
|
3909
|
+
padding: "4px 8px",
|
|
3910
|
+
opacity: aiBarOpen ? 1 : 0,
|
|
3911
|
+
transform: aiBarOpen ? "translateX(0)" : "translateX(40px)",
|
|
3912
|
+
transition: "opacity 0.3s cubic-bezier(0.4,0,0.2,1), transform 0.3s cubic-bezier(0.4,0,0.2,1)",
|
|
3913
|
+
pointerEvents: aiBarOpen ? "auto" : "none",
|
|
3914
|
+
zIndex: 2,
|
|
3915
|
+
background: "inherit",
|
|
3916
|
+
backdropFilter: "blur(12px)",
|
|
3917
|
+
WebkitBackdropFilter: "blur(12px)"
|
|
3010
3918
|
},
|
|
3011
3919
|
children: [
|
|
3012
3920
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3013
3921
|
"span",
|
|
3014
3922
|
{
|
|
3015
|
-
style: {
|
|
3016
|
-
|
|
3923
|
+
style: {
|
|
3924
|
+
display: "flex",
|
|
3925
|
+
color: accentColor,
|
|
3926
|
+
flexShrink: 0
|
|
3927
|
+
},
|
|
3928
|
+
children: icons?.sparkles ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SparklesIcon, { style: { width: 16, height: 16 } })
|
|
3017
3929
|
}
|
|
3018
3930
|
),
|
|
3019
3931
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3020
3932
|
"input",
|
|
3021
3933
|
{
|
|
3934
|
+
ref: aiInputRef,
|
|
3022
3935
|
type: "text",
|
|
3023
|
-
placeholder:
|
|
3024
|
-
value:
|
|
3025
|
-
onChange: (e) =>
|
|
3026
|
-
|
|
3027
|
-
if (
|
|
3028
|
-
|
|
3936
|
+
placeholder: aiPlaceholder,
|
|
3937
|
+
value: aiQuery,
|
|
3938
|
+
onChange: (e) => setAiQuery(e.target.value),
|
|
3939
|
+
onKeyDown: (e) => {
|
|
3940
|
+
if (e.key === "Enter" && !aiLoading) handleAISubmit();
|
|
3941
|
+
if (e.key === "Escape") handleAIBarClose();
|
|
3029
3942
|
},
|
|
3943
|
+
disabled: aiLoading,
|
|
3030
3944
|
style: {
|
|
3031
3945
|
flex: "1 1 0%",
|
|
3032
3946
|
border: "none",
|
|
@@ -3035,18 +3949,51 @@ function BoltTable({
|
|
|
3035
3949
|
font: "inherit",
|
|
3036
3950
|
color: "inherit",
|
|
3037
3951
|
padding: "4px 6px",
|
|
3038
|
-
minWidth: 0
|
|
3952
|
+
minWidth: 0,
|
|
3953
|
+
fontSize: 12
|
|
3039
3954
|
}
|
|
3040
3955
|
}
|
|
3041
3956
|
),
|
|
3042
|
-
|
|
3957
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3043
3958
|
"button",
|
|
3044
3959
|
{
|
|
3045
3960
|
type: "button",
|
|
3046
|
-
onClick:
|
|
3047
|
-
|
|
3048
|
-
|
|
3961
|
+
onClick: handleAISubmit,
|
|
3962
|
+
disabled: aiLoading || !aiQuery.trim(),
|
|
3963
|
+
style: {
|
|
3964
|
+
display: "flex",
|
|
3965
|
+
alignItems: "center",
|
|
3966
|
+
justifyContent: "center",
|
|
3967
|
+
background: aiQuery.trim() ? accentColor : "rgba(128,128,128,0.15)",
|
|
3968
|
+
border: "none",
|
|
3969
|
+
borderRadius: 4,
|
|
3970
|
+
cursor: aiLoading || !aiQuery.trim() ? "not-allowed" : "pointer",
|
|
3971
|
+
padding: "4px 8px",
|
|
3972
|
+
color: aiQuery.trim() ? "#fff" : "GrayText",
|
|
3973
|
+
transition: "all 0.2s ease",
|
|
3974
|
+
flexShrink: 0,
|
|
3975
|
+
gap: 4,
|
|
3976
|
+
fontSize: 12,
|
|
3977
|
+
opacity: aiLoading ? 0.7 : 1
|
|
3049
3978
|
},
|
|
3979
|
+
title: "Send",
|
|
3980
|
+
children: aiLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: icons?.loader ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3981
|
+
LoaderIcon,
|
|
3982
|
+
{
|
|
3983
|
+
style: {
|
|
3984
|
+
width: 14,
|
|
3985
|
+
height: 14,
|
|
3986
|
+
animation: "bt-spin 1s linear infinite"
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: icons?.send ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SendIcon, { style: { width: 14, height: 14 } }) })
|
|
3990
|
+
}
|
|
3991
|
+
),
|
|
3992
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3993
|
+
"button",
|
|
3994
|
+
{
|
|
3995
|
+
type: "button",
|
|
3996
|
+
onClick: handleAIBarClose,
|
|
3050
3997
|
style: {
|
|
3051
3998
|
display: "flex",
|
|
3052
3999
|
alignItems: "center",
|
|
@@ -3058,114 +4005,127 @@ function BoltTable({
|
|
|
3058
4005
|
color: "GrayText",
|
|
3059
4006
|
flexShrink: 0
|
|
3060
4007
|
},
|
|
3061
|
-
|
|
4008
|
+
title: "Close AI",
|
|
4009
|
+
children: icons?.close ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(XIcon, { style: { width: 14, height: 14 } })
|
|
3062
4010
|
}
|
|
3063
4011
|
)
|
|
3064
4012
|
]
|
|
3065
4013
|
}
|
|
4014
|
+
)
|
|
4015
|
+
]
|
|
4016
|
+
}
|
|
4017
|
+
),
|
|
4018
|
+
aiResult && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4019
|
+
"div",
|
|
4020
|
+
{
|
|
4021
|
+
style: {
|
|
4022
|
+
display: "flex",
|
|
4023
|
+
alignItems: "center",
|
|
4024
|
+
gap: 8,
|
|
4025
|
+
padding: "6px 12px",
|
|
4026
|
+
fontSize: 12,
|
|
4027
|
+
borderBottom: "1px solid rgba(128,128,128,0.2)",
|
|
4028
|
+
background: `linear-gradient(90deg, ${accentColor}08, transparent)`,
|
|
4029
|
+
flexShrink: 0
|
|
4030
|
+
},
|
|
4031
|
+
children: [
|
|
4032
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: accentColor, display: "flex", flexShrink: 0 }, children: icons?.sparkles ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SparklesIcon, { style: { width: 14, height: 14 } }) }),
|
|
4033
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { flex: "1 1 0%", opacity: 0.85 }, children: aiResult.message }),
|
|
4034
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4035
|
+
"button",
|
|
4036
|
+
{
|
|
4037
|
+
type: "button",
|
|
4038
|
+
onClick: saveCurrentAIFilter,
|
|
4039
|
+
style: {
|
|
4040
|
+
display: "flex",
|
|
4041
|
+
alignItems: "center",
|
|
4042
|
+
gap: 4,
|
|
4043
|
+
background: `${accentColor}12`,
|
|
4044
|
+
border: `1px solid ${accentColor}30`,
|
|
4045
|
+
borderRadius: 4,
|
|
4046
|
+
cursor: "pointer",
|
|
4047
|
+
padding: "2px 8px",
|
|
4048
|
+
color: accentColor,
|
|
4049
|
+
fontSize: 11,
|
|
4050
|
+
flexShrink: 0,
|
|
4051
|
+
fontWeight: 500,
|
|
4052
|
+
transition: "all 0.2s ease"
|
|
4053
|
+
},
|
|
4054
|
+
title: "Save this filter for quick access later",
|
|
4055
|
+
children: [
|
|
4056
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4057
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
|
|
4058
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "17 21 17 13 7 13 7 21" }),
|
|
4059
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "7 3 7 8 15 8" })
|
|
4060
|
+
] }),
|
|
4061
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Save Filter" })
|
|
4062
|
+
]
|
|
4063
|
+
}
|
|
3066
4064
|
),
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
"button",
|
|
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
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
fontSize: 12
|
|
3132
|
-
},
|
|
3133
|
-
children: [
|
|
3134
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3135
|
-
"input",
|
|
3136
|
-
{
|
|
3137
|
-
type: "checkbox",
|
|
3138
|
-
checked: !isHidden,
|
|
3139
|
-
disabled: isPinned,
|
|
3140
|
-
onChange: () => {
|
|
3141
|
-
if (isPinned) return;
|
|
3142
|
-
handleToggleHide(col.key);
|
|
3143
|
-
},
|
|
3144
|
-
style: {
|
|
3145
|
-
cursor: isPinned ? "not-allowed" : "pointer",
|
|
3146
|
-
accentColor
|
|
3147
|
-
}
|
|
3148
|
-
}
|
|
3149
|
-
),
|
|
3150
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3151
|
-
"span",
|
|
3152
|
-
{
|
|
3153
|
-
style: {
|
|
3154
|
-
overflow: "hidden",
|
|
3155
|
-
textOverflow: "ellipsis",
|
|
3156
|
-
whiteSpace: "nowrap"
|
|
3157
|
-
},
|
|
3158
|
-
children: typeof col.title === "string" ? col.title : col.key
|
|
3159
|
-
}
|
|
3160
|
-
)
|
|
3161
|
-
]
|
|
3162
|
-
},
|
|
3163
|
-
col.key
|
|
3164
|
-
);
|
|
3165
|
-
})
|
|
3166
|
-
}
|
|
3167
|
-
)
|
|
3168
|
-
] })
|
|
4065
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4066
|
+
"button",
|
|
4067
|
+
{
|
|
4068
|
+
type: "button",
|
|
4069
|
+
onClick: handleAIClear,
|
|
4070
|
+
style: {
|
|
4071
|
+
display: "flex",
|
|
4072
|
+
alignItems: "center",
|
|
4073
|
+
gap: 4,
|
|
4074
|
+
background: "none",
|
|
4075
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
4076
|
+
borderRadius: 4,
|
|
4077
|
+
cursor: "pointer",
|
|
4078
|
+
padding: "2px 8px",
|
|
4079
|
+
color: "inherit",
|
|
4080
|
+
fontSize: 11,
|
|
4081
|
+
flexShrink: 0,
|
|
4082
|
+
opacity: 0.7
|
|
4083
|
+
},
|
|
4084
|
+
title: "Clear AI results",
|
|
4085
|
+
children: [
|
|
4086
|
+
icons?.close ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(XIcon, { style: { width: 10, height: 10 } }),
|
|
4087
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Clear" })
|
|
4088
|
+
]
|
|
4089
|
+
}
|
|
4090
|
+
)
|
|
4091
|
+
]
|
|
4092
|
+
}
|
|
4093
|
+
),
|
|
4094
|
+
aiError && !aiResult && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4095
|
+
"div",
|
|
4096
|
+
{
|
|
4097
|
+
style: {
|
|
4098
|
+
display: "flex",
|
|
4099
|
+
alignItems: "center",
|
|
4100
|
+
gap: 8,
|
|
4101
|
+
padding: "6px 12px",
|
|
4102
|
+
fontSize: 12,
|
|
4103
|
+
borderBottom: "1px solid rgba(239,68,68,0.2)",
|
|
4104
|
+
background: "rgba(239,68,68,0.06)",
|
|
4105
|
+
color: "#ef4444",
|
|
4106
|
+
flexShrink: 0
|
|
4107
|
+
},
|
|
4108
|
+
children: [
|
|
4109
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { flex: "1 1 0%" }, children: aiError }),
|
|
4110
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
4111
|
+
"button",
|
|
4112
|
+
{
|
|
4113
|
+
type: "button",
|
|
4114
|
+
onClick: () => setAiError(null),
|
|
4115
|
+
style: {
|
|
4116
|
+
display: "flex",
|
|
4117
|
+
alignItems: "center",
|
|
4118
|
+
justifyContent: "center",
|
|
4119
|
+
background: "none",
|
|
4120
|
+
border: "none",
|
|
4121
|
+
cursor: "pointer",
|
|
4122
|
+
padding: 2,
|
|
4123
|
+
color: "#ef4444",
|
|
4124
|
+
flexShrink: 0
|
|
4125
|
+
},
|
|
4126
|
+
children: icons?.close ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(XIcon, { style: { width: 12, height: 12 } })
|
|
4127
|
+
}
|
|
4128
|
+
)
|
|
3169
4129
|
]
|
|
3170
4130
|
}
|
|
3171
4131
|
),
|
|
@@ -3667,14 +4627,20 @@ function BoltTable({
|
|
|
3667
4627
|
gridTemplateColumns,
|
|
3668
4628
|
headerHeight: HEADER_HEIGHT,
|
|
3669
4629
|
rowClassName,
|
|
3670
|
-
rowStyle,
|
|
4630
|
+
rowStyle: aiStyleOps.length > 0 ? (record, index) => {
|
|
4631
|
+
const base = rowStyle ? rowStyle(record, index) : void 0;
|
|
4632
|
+
const ai = getAIRowStyleForRecord(record);
|
|
4633
|
+
if (!base && !ai) return {};
|
|
4634
|
+
return { ...base, ...ai };
|
|
4635
|
+
} : rowStyle,
|
|
3671
4636
|
bodyGridRow: hasColumnGroups ? 3 : 2,
|
|
3672
4637
|
onEdit,
|
|
3673
4638
|
editingCell,
|
|
3674
4639
|
onEditComplete: handleEditComplete,
|
|
3675
4640
|
enableDynamicRowHeight,
|
|
3676
4641
|
onRowHeightChange: handleRowHeightChange,
|
|
3677
|
-
columnGridIndexMap
|
|
4642
|
+
columnGridIndexMap,
|
|
4643
|
+
cellStyleFn: aiCellStyleOps.length > 0 ? (record, columnKey) => getAICellStyleForRecord(record, columnKey) : void 0
|
|
3678
4644
|
}
|
|
3679
4645
|
)
|
|
3680
4646
|
]
|
|
@@ -4292,10 +5258,16 @@ function BoltTable({
|
|
|
4292
5258
|
})()
|
|
4293
5259
|
] });
|
|
4294
5260
|
}
|
|
5261
|
+
|
|
5262
|
+
// src/types.ts
|
|
5263
|
+
function defineConfig(config) {
|
|
5264
|
+
return config;
|
|
5265
|
+
}
|
|
4295
5266
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4296
5267
|
0 && (module.exports = {
|
|
4297
5268
|
BoltTable,
|
|
4298
5269
|
DraggableHeader,
|
|
4299
5270
|
ResizeOverlay,
|
|
4300
|
-
TableBody
|
|
5271
|
+
TableBody,
|
|
5272
|
+
defineConfig
|
|
4301
5273
|
});
|