orchid-ai 2.1.5 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/orchid-ai.css
CHANGED
|
@@ -860,6 +860,39 @@
|
|
|
860
860
|
color: #1f2937;
|
|
861
861
|
}
|
|
862
862
|
|
|
863
|
+
.ai-chart-card-header {
|
|
864
|
+
display: flex;
|
|
865
|
+
align-items: center;
|
|
866
|
+
justify-content: space-between;
|
|
867
|
+
gap: 12px;
|
|
868
|
+
margin-bottom: 10px;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
.ai-chart-card-header .ai-chart-title {
|
|
872
|
+
margin: 0;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
.ai-chart-csv-btn {
|
|
876
|
+
display: inline-flex;
|
|
877
|
+
align-items: center;
|
|
878
|
+
gap: 4px;
|
|
879
|
+
flex-shrink: 0;
|
|
880
|
+
padding: 4px 10px;
|
|
881
|
+
font-size: 12px;
|
|
882
|
+
font-weight: 500;
|
|
883
|
+
color: #1eaaf1;
|
|
884
|
+
background: #ffffff;
|
|
885
|
+
border: 1px solid #d1d5db;
|
|
886
|
+
border-radius: 6px;
|
|
887
|
+
cursor: pointer;
|
|
888
|
+
transition: background 0.15s, border-color 0.15s;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
.ai-chart-csv-btn:hover {
|
|
892
|
+
background: #f0f9ff;
|
|
893
|
+
border-color: #1eaaf1;
|
|
894
|
+
}
|
|
895
|
+
|
|
863
896
|
.ai-chart-error {
|
|
864
897
|
color: #b91c1c;
|
|
865
898
|
background: #fef2f2;
|
|
@@ -1877,8 +1910,9 @@
|
|
|
1877
1910
|
font-size: 22px;
|
|
1878
1911
|
font-weight: 700;
|
|
1879
1912
|
color: #1f2937;
|
|
1880
|
-
line-height: 1;
|
|
1913
|
+
line-height: 1.15;
|
|
1881
1914
|
margin-bottom: 5px;
|
|
1915
|
+
overflow-wrap: break-word;
|
|
1882
1916
|
}
|
|
1883
1917
|
|
|
1884
1918
|
.ai-stat-unit {
|
|
@@ -2762,6 +2796,20 @@
|
|
|
2762
2796
|
color: #1f2937 !important;
|
|
2763
2797
|
box-shadow: none !important;
|
|
2764
2798
|
}
|
|
2799
|
+
|
|
2800
|
+
body.ai-chat-printing #ai-cortex-print-section .ai-stat-card {
|
|
2801
|
+
padding: 8px 10px !important;
|
|
2802
|
+
min-width: 80px !important;
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2805
|
+
body.ai-chat-printing #ai-cortex-print-section .ai-stat-value {
|
|
2806
|
+
font-size: 17px !important;
|
|
2807
|
+
line-height: 1.2 !important;
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
body.ai-chat-printing #ai-cortex-print-section .ai-stat-label {
|
|
2811
|
+
font-size: 9px !important;
|
|
2812
|
+
}
|
|
2765
2813
|
}
|
|
2766
2814
|
|
|
2767
2815
|
/* ── Responsive ── */
|
package/package.json
CHANGED
|
@@ -1,11 +1,58 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
+
function csvEscape(value) {
|
|
4
|
+
const s = (value ?? "").toString();
|
|
5
|
+
return /[",\n\r]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function buildCsv(columns, rows) {
|
|
9
|
+
const header = columns.map((c) => csvEscape(c.label)).join(",");
|
|
10
|
+
const body = rows.map((row) => columns.map((c) => csvEscape(row[c.key])).join(",")).join("\r\n");
|
|
11
|
+
return `${header}\r\n${body}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function downloadCsv(filename, csv) {
|
|
15
|
+
// Prepend a BOM so Excel reads UTF-8 correctly.
|
|
16
|
+
const blob = new Blob([`${csv}`], { type: "text/csv;charset=utf-8;" });
|
|
17
|
+
const url = URL.createObjectURL(blob);
|
|
18
|
+
const a = document.createElement("a");
|
|
19
|
+
a.href = url;
|
|
20
|
+
a.download = filename;
|
|
21
|
+
document.body.appendChild(a);
|
|
22
|
+
a.click();
|
|
23
|
+
document.body.removeChild(a);
|
|
24
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function safeFilename(title) {
|
|
28
|
+
const base = (title || "table").replace(/[\\/:*?"<>|]+/g, "").trim().slice(0, 80);
|
|
29
|
+
return `${base || "table"}.csv`;
|
|
30
|
+
}
|
|
31
|
+
|
|
3
32
|
export default function DataTable({ chart }) {
|
|
4
33
|
const { title, columns, rows } = chart;
|
|
5
34
|
|
|
35
|
+
const handleDownload = () => downloadCsv(safeFilename(title), buildCsv(columns, rows));
|
|
36
|
+
|
|
6
37
|
return (
|
|
7
38
|
<div className="ai-chart-card">
|
|
8
|
-
|
|
39
|
+
<div className="ai-chart-card-header">
|
|
40
|
+
{title ? <h4 className="ai-chart-title">{title}</h4> : <span />}
|
|
41
|
+
<button
|
|
42
|
+
type="button"
|
|
43
|
+
className="ai-chart-csv-btn"
|
|
44
|
+
onClick={handleDownload}
|
|
45
|
+
title="Download as CSV"
|
|
46
|
+
aria-label="Download table as CSV"
|
|
47
|
+
>
|
|
48
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
49
|
+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
|
50
|
+
<polyline points="7 10 12 15 17 10" />
|
|
51
|
+
<line x1="12" y1="15" x2="12" y2="3" />
|
|
52
|
+
</svg>
|
|
53
|
+
CSV
|
|
54
|
+
</button>
|
|
55
|
+
</div>
|
|
9
56
|
<div className="ai-data-table-wrap">
|
|
10
57
|
<table className="ai-data-table">
|
|
11
58
|
<thead>
|