@inkindcards/semantic-layer 2.4.0 → 2.4.1
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/components.cjs +205 -33
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.cts +4 -1
- package/dist/components.d.ts +4 -1
- package/dist/components.js +205 -34
- package/dist/components.js.map +1 -1
- package/package.json +1 -1
package/dist/components.d.cts
CHANGED
|
@@ -142,9 +142,11 @@ interface WidgetConfig {
|
|
|
142
142
|
grain: TimeGrain | null;
|
|
143
143
|
comparisonMetric?: SemanticField;
|
|
144
144
|
}
|
|
145
|
+
type TimePreset = "12m" | "6m" | "3m" | "1m" | "1w" | "1d";
|
|
145
146
|
interface SharedFilter {
|
|
146
147
|
dimension: SemanticField;
|
|
147
148
|
label: string;
|
|
149
|
+
timePreset?: TimePreset | null;
|
|
148
150
|
}
|
|
149
151
|
interface ReportConfig {
|
|
150
152
|
dashboardTitle: string;
|
|
@@ -153,7 +155,8 @@ interface ReportConfig {
|
|
|
153
155
|
sharedFilters: SharedFilter[];
|
|
154
156
|
}
|
|
155
157
|
declare function generateReportPrompt(config: ReportConfig): string;
|
|
158
|
+
declare function isRunningInIframe(): boolean;
|
|
156
159
|
declare function canOpenInLovable(prompt: string): boolean;
|
|
157
160
|
declare function openInLovable(prompt: string): void;
|
|
158
161
|
|
|
159
|
-
export { AdminDashboard, type AdminDashboardProps, type ChartAnalysis, type DashboardLayout, DataCatalog, type DataCatalogProps, DataInspector, type DataInspectorProps, type DimensionMapping, type FieldMapping, type FieldMatch, Inspectable, type InspectableProps, type MatchConfidence, MetricPicker, type MetricPickerProps, type MigrationConfig, type ReportConfig, ResultsTable, type ResultsTableProps, type SharedFilter, type WidgetConfig, type WidgetType, analyzeChartData, canOpenInLovable, generateMigrationPrompt, generateReportPrompt, matchField, matchFields, openInLovable };
|
|
162
|
+
export { AdminDashboard, type AdminDashboardProps, type ChartAnalysis, type DashboardLayout, DataCatalog, type DataCatalogProps, DataInspector, type DataInspectorProps, type DimensionMapping, type FieldMapping, type FieldMatch, Inspectable, type InspectableProps, type MatchConfidence, MetricPicker, type MetricPickerProps, type MigrationConfig, type ReportConfig, ResultsTable, type ResultsTableProps, type SharedFilter, type TimePreset, type WidgetConfig, type WidgetType, analyzeChartData, canOpenInLovable, generateMigrationPrompt, generateReportPrompt, isRunningInIframe, matchField, matchFields, openInLovable };
|
package/dist/components.d.ts
CHANGED
|
@@ -142,9 +142,11 @@ interface WidgetConfig {
|
|
|
142
142
|
grain: TimeGrain | null;
|
|
143
143
|
comparisonMetric?: SemanticField;
|
|
144
144
|
}
|
|
145
|
+
type TimePreset = "12m" | "6m" | "3m" | "1m" | "1w" | "1d";
|
|
145
146
|
interface SharedFilter {
|
|
146
147
|
dimension: SemanticField;
|
|
147
148
|
label: string;
|
|
149
|
+
timePreset?: TimePreset | null;
|
|
148
150
|
}
|
|
149
151
|
interface ReportConfig {
|
|
150
152
|
dashboardTitle: string;
|
|
@@ -153,7 +155,8 @@ interface ReportConfig {
|
|
|
153
155
|
sharedFilters: SharedFilter[];
|
|
154
156
|
}
|
|
155
157
|
declare function generateReportPrompt(config: ReportConfig): string;
|
|
158
|
+
declare function isRunningInIframe(): boolean;
|
|
156
159
|
declare function canOpenInLovable(prompt: string): boolean;
|
|
157
160
|
declare function openInLovable(prompt: string): void;
|
|
158
161
|
|
|
159
|
-
export { AdminDashboard, type AdminDashboardProps, type ChartAnalysis, type DashboardLayout, DataCatalog, type DataCatalogProps, DataInspector, type DataInspectorProps, type DimensionMapping, type FieldMapping, type FieldMatch, Inspectable, type InspectableProps, type MatchConfidence, MetricPicker, type MetricPickerProps, type MigrationConfig, type ReportConfig, ResultsTable, type ResultsTableProps, type SharedFilter, type WidgetConfig, type WidgetType, analyzeChartData, canOpenInLovable, generateMigrationPrompt, generateReportPrompt, matchField, matchFields, openInLovable };
|
|
162
|
+
export { AdminDashboard, type AdminDashboardProps, type ChartAnalysis, type DashboardLayout, DataCatalog, type DataCatalogProps, DataInspector, type DataInspectorProps, type DimensionMapping, type FieldMapping, type FieldMatch, Inspectable, type InspectableProps, type MatchConfidence, MetricPicker, type MetricPickerProps, type MigrationConfig, type ReportConfig, ResultsTable, type ResultsTableProps, type SharedFilter, type TimePreset, type WidgetConfig, type WidgetType, analyzeChartData, canOpenInLovable, generateMigrationPrompt, generateReportPrompt, isRunningInIframe, matchField, matchFields, openInLovable };
|
package/dist/components.js
CHANGED
|
@@ -1081,6 +1081,14 @@ function generateMigrationPrompt(config) {
|
|
|
1081
1081
|
}
|
|
1082
1082
|
|
|
1083
1083
|
// src/components/report-prompt-generator.ts
|
|
1084
|
+
var TIME_PRESET_LABELS = {
|
|
1085
|
+
"12m": "12 months",
|
|
1086
|
+
"6m": "6 months",
|
|
1087
|
+
"3m": "3 months",
|
|
1088
|
+
"1m": "1 month",
|
|
1089
|
+
"1w": "1 week",
|
|
1090
|
+
"1d": "1 day"
|
|
1091
|
+
};
|
|
1084
1092
|
var PALETTE = [
|
|
1085
1093
|
"#3b82f6",
|
|
1086
1094
|
"#10b981",
|
|
@@ -1138,8 +1146,19 @@ function generateReportPrompt(config) {
|
|
|
1138
1146
|
parts.push("};");
|
|
1139
1147
|
parts.push("```");
|
|
1140
1148
|
parts.push("");
|
|
1141
|
-
|
|
1142
|
-
|
|
1149
|
+
const timeFilters = sharedFilters.filter((f) => f.dimension.type === "time_dimension" && f.timePreset);
|
|
1150
|
+
const dimFilters = sharedFilters.filter((f) => f.dimension.type !== "time_dimension" || !f.timePreset);
|
|
1151
|
+
if (timeFilters.length > 0) {
|
|
1152
|
+
parts.push("For time filters, compute a date range relative to today:");
|
|
1153
|
+
for (const f of timeFilters) {
|
|
1154
|
+
parts.push(` - "${f.dimension.name}": default to the last ${TIME_PRESET_LABELS[f.timePreset]}. Compute a start date (e.g. \`new Date(); startDate.setMonth(startDate.getMonth() - N)\`) and pass it as a filter value. Include preset buttons (${Object.values(TIME_PRESET_LABELS).join(", ")}) so the user can switch ranges.`);
|
|
1155
|
+
}
|
|
1156
|
+
parts.push("");
|
|
1157
|
+
}
|
|
1158
|
+
if (dimFilters.length > 0) {
|
|
1159
|
+
parts.push("For each dimension filter dropdown, query the distinct values of the dimension using useSemanticQuery with that dimension as a groupBy and any single metric, then populate the dropdown options from the returned rows.");
|
|
1160
|
+
parts.push("");
|
|
1161
|
+
}
|
|
1143
1162
|
}
|
|
1144
1163
|
parts.push("## Layout");
|
|
1145
1164
|
parts.push("");
|
|
@@ -1294,6 +1313,13 @@ function sanitize(name) {
|
|
|
1294
1313
|
return name.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
1295
1314
|
}
|
|
1296
1315
|
var LOVABLE_CHAR_LIMIT = 5e4;
|
|
1316
|
+
function isRunningInIframe() {
|
|
1317
|
+
try {
|
|
1318
|
+
return window.self !== window.top;
|
|
1319
|
+
} catch {
|
|
1320
|
+
return true;
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1297
1323
|
function canOpenInLovable(prompt) {
|
|
1298
1324
|
return prompt.length <= LOVABLE_CHAR_LIMIT;
|
|
1299
1325
|
}
|
|
@@ -1439,16 +1465,48 @@ function UnifiedModal({
|
|
|
1439
1465
|
entry,
|
|
1440
1466
|
onClose
|
|
1441
1467
|
}) {
|
|
1468
|
+
const [dragPos, setDragPos] = useState(null);
|
|
1469
|
+
const dragRef = useRef(null);
|
|
1470
|
+
const modalRef = useRef(null);
|
|
1471
|
+
const handleHeaderMouseDown = useCallback((e) => {
|
|
1472
|
+
if (e.target.closest("button")) return;
|
|
1473
|
+
e.preventDefault();
|
|
1474
|
+
const modal = modalRef.current;
|
|
1475
|
+
if (!modal) return;
|
|
1476
|
+
const rect = modal.getBoundingClientRect();
|
|
1477
|
+
dragRef.current = { startX: e.clientX, startY: e.clientY, origX: rect.left, origY: rect.top };
|
|
1478
|
+
const onMove = (ev) => {
|
|
1479
|
+
if (!dragRef.current) return;
|
|
1480
|
+
const dx = ev.clientX - dragRef.current.startX;
|
|
1481
|
+
const dy = ev.clientY - dragRef.current.startY;
|
|
1482
|
+
setDragPos({ x: dragRef.current.origX + dx, y: dragRef.current.origY + dy });
|
|
1483
|
+
};
|
|
1484
|
+
const onUp = () => {
|
|
1485
|
+
dragRef.current = null;
|
|
1486
|
+
document.removeEventListener("mousemove", onMove);
|
|
1487
|
+
document.removeEventListener("mouseup", onUp);
|
|
1488
|
+
};
|
|
1489
|
+
document.addEventListener("mousemove", onMove);
|
|
1490
|
+
document.addEventListener("mouseup", onUp);
|
|
1491
|
+
}, []);
|
|
1492
|
+
const positionStyle = dragPos ? { position: "fixed", top: dragPos.y, left: dragPos.x, transform: "none" } : { position: "fixed", top: "50%", left: "50%", transform: "translate(-50%, -50%)" };
|
|
1442
1493
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1443
1494
|
/* @__PURE__ */ jsx("div", { onClick: onClose, style: backdropStyle }),
|
|
1444
|
-
/* @__PURE__ */ jsxs("div", { style: modalStyle, children: [
|
|
1445
|
-
/* @__PURE__ */ jsxs(
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1495
|
+
/* @__PURE__ */ jsxs("div", { ref: modalRef, style: { ...modalStyle, ...positionStyle }, children: [
|
|
1496
|
+
/* @__PURE__ */ jsxs(
|
|
1497
|
+
"div",
|
|
1498
|
+
{
|
|
1499
|
+
onMouseDown: handleHeaderMouseDown,
|
|
1500
|
+
style: { ...modalHeaderStyle, cursor: dragRef.current ? "grabbing" : "grab" },
|
|
1501
|
+
children: [
|
|
1502
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 0 }, children: [
|
|
1503
|
+
/* @__PURE__ */ jsx(TabButton, { label: "Migrate", active: tab === "migrate", onClick: () => onTabChange("migrate") }),
|
|
1504
|
+
/* @__PURE__ */ jsx(TabButton, { label: "Build", active: tab === "build", onClick: () => onTabChange("build") })
|
|
1505
|
+
] }),
|
|
1506
|
+
/* @__PURE__ */ jsx("button", { onClick: onClose, style: closeBtnStyle, children: "\xD7" })
|
|
1507
|
+
]
|
|
1508
|
+
}
|
|
1509
|
+
),
|
|
1452
1510
|
tab === "migrate" ? /* @__PURE__ */ jsx(MigrateTab, { entry, onClose }) : /* @__PURE__ */ jsx(BuildTab, {})
|
|
1453
1511
|
] })
|
|
1454
1512
|
] });
|
|
@@ -1681,7 +1739,14 @@ var WIDGET_TYPES = [
|
|
|
1681
1739
|
function BuildTab() {
|
|
1682
1740
|
const { fields: catalog, isLoading: catalogLoading } = useMetrics();
|
|
1683
1741
|
const allMetrics = useMemo(() => catalog.filter((f) => f.type === "metric"), [catalog]);
|
|
1684
|
-
const allDimensions = useMemo(() =>
|
|
1742
|
+
const allDimensions = useMemo(() => {
|
|
1743
|
+
const dims = catalog.filter((f) => f.type === "dimension" || f.type === "time_dimension");
|
|
1744
|
+
return dims.sort((a, b) => {
|
|
1745
|
+
if (a.name === "metric_time") return -1;
|
|
1746
|
+
if (b.name === "metric_time") return 1;
|
|
1747
|
+
return 0;
|
|
1748
|
+
});
|
|
1749
|
+
}, [catalog]);
|
|
1685
1750
|
const [dashboardTitle, setDashboardTitle] = useState("Dashboard");
|
|
1686
1751
|
const [layout, setLayout] = useState("dashboard");
|
|
1687
1752
|
const [widgets, setWidgets] = useState([]);
|
|
@@ -1690,29 +1755,74 @@ function BuildTab() {
|
|
|
1690
1755
|
const [copied, setCopied] = useState(false);
|
|
1691
1756
|
const [lovableSent, setLovableSent] = useState(false);
|
|
1692
1757
|
const [previewOpen, setPreviewOpen] = useState(false);
|
|
1758
|
+
const [catalogWidth, setCatalogWidth] = useState(220);
|
|
1759
|
+
const catalogDragRef = useRef(null);
|
|
1760
|
+
const inIframe = useMemo(() => isRunningInIframe(), []);
|
|
1761
|
+
const handleCatalogDragStart = useCallback((e) => {
|
|
1762
|
+
e.preventDefault();
|
|
1763
|
+
catalogDragRef.current = { startX: e.clientX, startW: catalogWidth };
|
|
1764
|
+
const onMove = (ev) => {
|
|
1765
|
+
if (!catalogDragRef.current) return;
|
|
1766
|
+
const delta = ev.clientX - catalogDragRef.current.startX;
|
|
1767
|
+
setCatalogWidth(Math.max(160, Math.min(400, catalogDragRef.current.startW + delta)));
|
|
1768
|
+
};
|
|
1769
|
+
const onUp = () => {
|
|
1770
|
+
catalogDragRef.current = null;
|
|
1771
|
+
document.removeEventListener("mousemove", onMove);
|
|
1772
|
+
document.removeEventListener("mouseup", onUp);
|
|
1773
|
+
};
|
|
1774
|
+
document.addEventListener("mousemove", onMove);
|
|
1775
|
+
document.addEventListener("mouseup", onUp);
|
|
1776
|
+
}, [catalogWidth]);
|
|
1693
1777
|
const addWidget = useCallback((type) => {
|
|
1778
|
+
const isTimeSeries = type === "line" || type === "area" || type === "kpi";
|
|
1779
|
+
const metricTime = allDimensions.find((d) => d.name === "metric_time");
|
|
1694
1780
|
setWidgets((prev) => [...prev, {
|
|
1695
1781
|
id: nextWidgetId(),
|
|
1696
1782
|
title: `${WIDGET_TYPES.find((t) => t.type === type)?.label ?? "Widget"} ${prev.length + 1}`,
|
|
1697
1783
|
type,
|
|
1698
1784
|
metrics: [],
|
|
1699
|
-
groupBy: [],
|
|
1700
|
-
grain: null
|
|
1785
|
+
groupBy: isTimeSeries && metricTime ? [metricTime] : [],
|
|
1786
|
+
grain: isTimeSeries && metricTime ? "month" : null
|
|
1701
1787
|
}]);
|
|
1702
|
-
}, []);
|
|
1788
|
+
}, [allDimensions]);
|
|
1703
1789
|
const removeWidget = useCallback((id) => {
|
|
1704
1790
|
setWidgets((prev) => prev.filter((w) => w.id !== id));
|
|
1705
1791
|
}, []);
|
|
1706
1792
|
const updateWidget = useCallback((id, patch) => {
|
|
1707
1793
|
setWidgets((prev) => prev.map((w) => w.id === id ? { ...w, ...patch } : w));
|
|
1708
1794
|
}, []);
|
|
1795
|
+
const duplicateWidget = useCallback((id) => {
|
|
1796
|
+
setWidgets((prev) => {
|
|
1797
|
+
const source = prev.find((w) => w.id === id);
|
|
1798
|
+
if (!source) return prev;
|
|
1799
|
+
const copy = {
|
|
1800
|
+
...source,
|
|
1801
|
+
id: nextWidgetId(),
|
|
1802
|
+
title: `${source.title} (2)`,
|
|
1803
|
+
metrics: [...source.metrics],
|
|
1804
|
+
groupBy: [...source.groupBy]
|
|
1805
|
+
};
|
|
1806
|
+
const idx = prev.findIndex((w) => w.id === id);
|
|
1807
|
+
return [...prev.slice(0, idx + 1), copy, ...prev.slice(idx + 1)];
|
|
1808
|
+
});
|
|
1809
|
+
}, []);
|
|
1709
1810
|
const addFilter = useCallback((dim) => {
|
|
1710
1811
|
if (sharedFilters.some((f) => f.dimension.name === dim.name)) return;
|
|
1711
|
-
setSharedFilters((prev) => [...prev, {
|
|
1812
|
+
setSharedFilters((prev) => [...prev, {
|
|
1813
|
+
dimension: dim,
|
|
1814
|
+
label: dim.displayName,
|
|
1815
|
+
timePreset: dim.type === "time_dimension" ? "12m" : null
|
|
1816
|
+
}]);
|
|
1712
1817
|
}, [sharedFilters]);
|
|
1713
1818
|
const removeFilter = useCallback((name) => {
|
|
1714
1819
|
setSharedFilters((prev) => prev.filter((f) => f.dimension.name !== name));
|
|
1715
1820
|
}, []);
|
|
1821
|
+
const updateFilterPreset = useCallback((name, preset) => {
|
|
1822
|
+
setSharedFilters((prev) => prev.map(
|
|
1823
|
+
(f) => f.dimension.name === name ? { ...f, timePreset: preset } : f
|
|
1824
|
+
));
|
|
1825
|
+
}, []);
|
|
1716
1826
|
const addFieldToWidget = useCallback((widgetId, field) => {
|
|
1717
1827
|
setWidgets((prev) => prev.map((w) => {
|
|
1718
1828
|
if (w.id !== widgetId) return w;
|
|
@@ -1746,11 +1856,17 @@ function BuildTab() {
|
|
|
1746
1856
|
setCopied(true);
|
|
1747
1857
|
setTimeout(() => setCopied(false), 2e3);
|
|
1748
1858
|
}, [prompt]);
|
|
1749
|
-
const handleLovable = useCallback(() => {
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1859
|
+
const handleLovable = useCallback(async () => {
|
|
1860
|
+
if (inIframe) {
|
|
1861
|
+
await copyToClipboard(prompt);
|
|
1862
|
+
setLovableSent(true);
|
|
1863
|
+
setTimeout(() => setLovableSent(false), 3e3);
|
|
1864
|
+
} else {
|
|
1865
|
+
openInLovable(prompt);
|
|
1866
|
+
setLovableSent(true);
|
|
1867
|
+
setTimeout(() => setLovableSent(false), 3e3);
|
|
1868
|
+
}
|
|
1869
|
+
}, [prompt, inIframe]);
|
|
1754
1870
|
const filteredMetrics = useMemo(() => {
|
|
1755
1871
|
const q = catalogSearch.toLowerCase();
|
|
1756
1872
|
if (!q) return allMetrics;
|
|
@@ -1794,7 +1910,7 @@ function BuildTab() {
|
|
|
1794
1910
|
)) })
|
|
1795
1911
|
] }),
|
|
1796
1912
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flex: 1, minHeight: 0 }, children: [
|
|
1797
|
-
/* @__PURE__ */ jsxs("div", { style: { width:
|
|
1913
|
+
/* @__PURE__ */ jsxs("div", { style: { width: catalogWidth, borderRight: "1px solid #e5e7eb", overflow: "auto", flexShrink: 0 }, children: [
|
|
1798
1914
|
/* @__PURE__ */ jsx("div", { style: { padding: "8px 12px" }, children: /* @__PURE__ */ jsx(
|
|
1799
1915
|
"input",
|
|
1800
1916
|
{
|
|
@@ -1820,11 +1936,40 @@ function BuildTab() {
|
|
|
1820
1936
|
filteredDimensions.length,
|
|
1821
1937
|
")"
|
|
1822
1938
|
] }),
|
|
1823
|
-
filteredDimensions.map((f) => /* @__PURE__ */ jsx(
|
|
1939
|
+
filteredDimensions.map((f) => /* @__PURE__ */ jsx(
|
|
1940
|
+
CatalogChip,
|
|
1941
|
+
{
|
|
1942
|
+
field: f,
|
|
1943
|
+
widgets,
|
|
1944
|
+
onAddToWidget: addFieldToWidget,
|
|
1945
|
+
onAddAsFilter: addFilter,
|
|
1946
|
+
suffix: f.name === "metric_time" ? " (recommended)" : void 0
|
|
1947
|
+
},
|
|
1948
|
+
f.name
|
|
1949
|
+
)),
|
|
1824
1950
|
filteredDimensions.length === 0 && /* @__PURE__ */ jsx("div", { style: { fontSize: 11, color: "#9ca3af", padding: "4px 0" }, children: "None found" })
|
|
1825
1951
|
] })
|
|
1826
1952
|
] })
|
|
1827
1953
|
] }),
|
|
1954
|
+
/* @__PURE__ */ jsx(
|
|
1955
|
+
"div",
|
|
1956
|
+
{
|
|
1957
|
+
onMouseDown: handleCatalogDragStart,
|
|
1958
|
+
style: {
|
|
1959
|
+
width: 4,
|
|
1960
|
+
cursor: "col-resize",
|
|
1961
|
+
backgroundColor: "transparent",
|
|
1962
|
+
flexShrink: 0,
|
|
1963
|
+
position: "relative"
|
|
1964
|
+
},
|
|
1965
|
+
onMouseEnter: (e) => {
|
|
1966
|
+
e.currentTarget.style.backgroundColor = "#d1d5db";
|
|
1967
|
+
},
|
|
1968
|
+
onMouseLeave: (e) => {
|
|
1969
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
),
|
|
1828
1973
|
/* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "auto", padding: "12px 16px" }, children: widgets.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "40px 20px", color: "#9ca3af" }, children: [
|
|
1829
1974
|
/* @__PURE__ */ jsx("div", { style: { fontSize: 14, fontWeight: 500, marginBottom: 12 }, children: "Compose your dashboard" }),
|
|
1830
1975
|
/* @__PURE__ */ jsx("div", { style: { fontSize: 12, marginBottom: 20 }, children: "Add widgets below, then pick metrics and dimensions from the catalog on the left." }),
|
|
@@ -1836,6 +1981,7 @@ function BuildTab() {
|
|
|
1836
1981
|
widget: w,
|
|
1837
1982
|
onUpdate: updateWidget,
|
|
1838
1983
|
onRemove: removeWidget,
|
|
1984
|
+
onDuplicate: duplicateWidget,
|
|
1839
1985
|
onRemoveField: removeFieldFromWidget,
|
|
1840
1986
|
allDimensions
|
|
1841
1987
|
},
|
|
@@ -1845,9 +1991,31 @@ function BuildTab() {
|
|
|
1845
1991
|
/* @__PURE__ */ jsxs("div", { style: { marginTop: 16, padding: "12px 0", borderTop: "1px solid #f3f4f6" }, children: [
|
|
1846
1992
|
/* @__PURE__ */ jsx("div", { style: sectionTitleStyle, children: "Shared Filters" }),
|
|
1847
1993
|
/* @__PURE__ */ jsx("div", { style: { fontSize: 11, color: "#9ca3af", marginBottom: 8 }, children: "Dimensions that filter all widgets together. Add from the catalog sidebar." }),
|
|
1848
|
-
sharedFilters.length === 0 ? /* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: "#d1d5db", fontStyle: "italic" }, children: "None added yet" }) : /* @__PURE__ */ jsx("div", { style: { display: "flex",
|
|
1849
|
-
|
|
1850
|
-
|
|
1994
|
+
sharedFilters.length === 0 ? /* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: "#d1d5db", fontStyle: "italic" }, children: "None added yet" }) : /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: sharedFilters.map((f) => /* @__PURE__ */ jsxs("div", { children: [
|
|
1995
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: /* @__PURE__ */ jsxs("span", { style: chipStyle, children: [
|
|
1996
|
+
f.label,
|
|
1997
|
+
/* @__PURE__ */ jsx("button", { onClick: () => removeFilter(f.dimension.name), style: chipRemoveStyle, children: "\xD7" })
|
|
1998
|
+
] }) }),
|
|
1999
|
+
f.dimension.type === "time_dimension" && /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 4, marginTop: 4, marginLeft: 4 }, children: Object.keys(TIME_PRESET_LABELS).map((p) => /* @__PURE__ */ jsx(
|
|
2000
|
+
"button",
|
|
2001
|
+
{
|
|
2002
|
+
onClick: () => updateFilterPreset(f.dimension.name, p),
|
|
2003
|
+
style: {
|
|
2004
|
+
padding: "2px 8px",
|
|
2005
|
+
fontSize: 10,
|
|
2006
|
+
fontWeight: 600,
|
|
2007
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
2008
|
+
borderRadius: 999,
|
|
2009
|
+
border: f.timePreset === p ? "1px solid #3b82f6" : "1px solid #e5e7eb",
|
|
2010
|
+
backgroundColor: f.timePreset === p ? "#eff6ff" : "#fff",
|
|
2011
|
+
color: f.timePreset === p ? "#3b82f6" : "#9ca3af",
|
|
2012
|
+
cursor: "pointer",
|
|
2013
|
+
transition: "all 0.1s"
|
|
2014
|
+
},
|
|
2015
|
+
children: TIME_PRESET_LABELS[p]
|
|
2016
|
+
},
|
|
2017
|
+
p
|
|
2018
|
+
)) })
|
|
1851
2019
|
] }, f.dimension.name)) })
|
|
1852
2020
|
] }),
|
|
1853
2021
|
canGenerate && /* @__PURE__ */ jsxs("div", { style: { marginTop: 12 }, children: [
|
|
@@ -1899,8 +2067,8 @@ function BuildTab() {
|
|
|
1899
2067
|
gap: 6
|
|
1900
2068
|
},
|
|
1901
2069
|
children: [
|
|
1902
|
-
lovableSent ? "Opening Lovable..." : "Build in Lovable",
|
|
1903
|
-
!lovableSent && /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2070
|
+
lovableSent ? inIframe ? "Copied! Paste into Lovable chat" : "Opening Lovable..." : inIframe ? "Send to Lovable \u2764\uFE0F" : "Build in Lovable \u2764\uFE0F",
|
|
2071
|
+
!lovableSent && !inIframe && /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1904
2072
|
/* @__PURE__ */ jsx("path", { d: "M7 17L17 7" }),
|
|
1905
2073
|
/* @__PURE__ */ jsx("path", { d: "M7 7h10v10" })
|
|
1906
2074
|
] })
|
|
@@ -1914,7 +2082,8 @@ function CatalogChip({
|
|
|
1914
2082
|
field,
|
|
1915
2083
|
widgets,
|
|
1916
2084
|
onAddToWidget,
|
|
1917
|
-
onAddAsFilter
|
|
2085
|
+
onAddAsFilter,
|
|
2086
|
+
suffix
|
|
1918
2087
|
}) {
|
|
1919
2088
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
1920
2089
|
const typeIcon = field.type === "metric" ? "\u2581" : field.type === "time_dimension" ? "\u25F7" : "\u2022";
|
|
@@ -1956,7 +2125,10 @@ ${field.description}`,
|
|
|
1956
2125
|
},
|
|
1957
2126
|
children: [
|
|
1958
2127
|
/* @__PURE__ */ jsx("span", { style: { color: typeColor, fontSize: 10, flexShrink: 0 }, children: typeIcon }),
|
|
1959
|
-
/* @__PURE__ */
|
|
2128
|
+
/* @__PURE__ */ jsxs("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
|
|
2129
|
+
field.displayName,
|
|
2130
|
+
suffix && /* @__PURE__ */ jsx("span", { style: { color: "#9ca3af", fontWeight: 400 }, children: suffix })
|
|
2131
|
+
] })
|
|
1960
2132
|
]
|
|
1961
2133
|
}
|
|
1962
2134
|
),
|
|
@@ -2046,6 +2218,7 @@ function WidgetCard({
|
|
|
2046
2218
|
widget,
|
|
2047
2219
|
onUpdate,
|
|
2048
2220
|
onRemove,
|
|
2221
|
+
onDuplicate,
|
|
2049
2222
|
onRemoveField,
|
|
2050
2223
|
allDimensions
|
|
2051
2224
|
}) {
|
|
@@ -2084,6 +2257,7 @@ function WidgetCard({
|
|
|
2084
2257
|
},
|
|
2085
2258
|
wt.type
|
|
2086
2259
|
)) }),
|
|
2260
|
+
/* @__PURE__ */ jsx("button", { onClick: () => onDuplicate(widget.id), style: { background: "none", border: "none", cursor: "pointer", fontSize: 12, color: "#d1d5db", padding: "0 2px" }, title: "Duplicate widget", children: "\u2398" }),
|
|
2087
2261
|
/* @__PURE__ */ jsx("button", { onClick: () => onRemove(widget.id), style: { background: "none", border: "none", cursor: "pointer", fontSize: 14, color: "#d1d5db", padding: "0 2px" }, title: "Remove widget", children: "\xD7" })
|
|
2088
2262
|
] }),
|
|
2089
2263
|
!collapsed && /* @__PURE__ */ jsxs("div", { style: { padding: "8px 12px" }, children: [
|
|
@@ -2142,12 +2316,9 @@ var backdropStyle = {
|
|
|
2142
2316
|
zIndex: 1e5
|
|
2143
2317
|
};
|
|
2144
2318
|
var modalStyle = {
|
|
2145
|
-
position: "fixed",
|
|
2146
|
-
top: "50%",
|
|
2147
|
-
left: "50%",
|
|
2148
|
-
transform: "translate(-50%, -50%)",
|
|
2149
2319
|
zIndex: 100001,
|
|
2150
2320
|
width: "min(900px, 95vw)",
|
|
2321
|
+
height: "85vh",
|
|
2151
2322
|
maxHeight: "85vh",
|
|
2152
2323
|
backgroundColor: "#fff",
|
|
2153
2324
|
borderRadius: 12,
|
|
@@ -2291,6 +2462,6 @@ var chipRemoveStyle = {
|
|
|
2291
2462
|
lineHeight: 1
|
|
2292
2463
|
};
|
|
2293
2464
|
|
|
2294
|
-
export { AdminDashboard, DataCatalog, DataInspector, Inspectable, MetricPicker, ResultsTable, analyzeChartData, canOpenInLovable, generateMigrationPrompt, generateReportPrompt, matchField, matchFields, openInLovable };
|
|
2465
|
+
export { AdminDashboard, DataCatalog, DataInspector, Inspectable, MetricPicker, ResultsTable, analyzeChartData, canOpenInLovable, generateMigrationPrompt, generateReportPrompt, isRunningInIframe, matchField, matchFields, openInLovable };
|
|
2295
2466
|
//# sourceMappingURL=components.js.map
|
|
2296
2467
|
//# sourceMappingURL=components.js.map
|