@inkindcards/semantic-layer 0.2.2 → 2.0.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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkSHHZ37FE_cjs = require('./chunk-SHHZ37FE.cjs');
3
+ var chunkT2C43AAL_cjs = require('./chunk-T2C43AAL.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
@@ -56,7 +56,7 @@ function MetricPicker({
56
56
  searchPlaceholder = "Search metrics and dimensions...",
57
57
  className
58
58
  }) {
59
- const { fields, categories, isLoading, error } = chunkSHHZ37FE_cjs.useMetrics();
59
+ const { fields, categories, isLoading, error } = chunkT2C43AAL_cjs.useMetrics();
60
60
  const [search, setSearch] = react.useState("");
61
61
  const filtered = react.useMemo(() => {
62
62
  let result = fields;
@@ -312,7 +312,7 @@ var emptyStyle = {
312
312
  fontSize: 14
313
313
  };
314
314
  function DataCatalog({ className, showCopyButton = true, fieldTypes }) {
315
- const { fields, metrics, dimensions, isLoading, error } = chunkSHHZ37FE_cjs.useMetrics();
315
+ const { fields, metrics, dimensions, isLoading, error } = chunkT2C43AAL_cjs.useMetrics();
316
316
  const [search, setSearch] = react.useState("");
317
317
  const [typeFilter, setTypeFilter] = react.useState("all");
318
318
  const [copiedField, setCopiedField] = react.useState(null);
@@ -522,7 +522,7 @@ var emptyStyle2 = {
522
522
  fontSize: 14
523
523
  };
524
524
  function FieldsTab() {
525
- const { fields, isLoading, error, createField, updateField, deleteField } = chunkSHHZ37FE_cjs.useAdminFields();
525
+ const { fields, isLoading, error, createField, updateField, deleteField } = chunkT2C43AAL_cjs.useAdminFields();
526
526
  const [showAdd, setShowAdd] = react.useState(false);
527
527
  const [newName, setNewName] = react.useState("");
528
528
  const [newType, setNewType] = react.useState("metric");
@@ -611,8 +611,8 @@ function FieldsTab() {
611
611
  ] });
612
612
  }
613
613
  function RolesTab() {
614
- const { roles, isLoading, error, createRole, deleteRole, setRoleFields } = chunkSHHZ37FE_cjs.useAdminRoles();
615
- const { fields } = chunkSHHZ37FE_cjs.useAdminFields();
614
+ const { roles, isLoading, error, createRole, deleteRole, setRoleFields } = chunkT2C43AAL_cjs.useAdminRoles();
615
+ const { fields } = chunkT2C43AAL_cjs.useAdminFields();
616
616
  const [showAdd, setShowAdd] = react.useState(false);
617
617
  const [newName, setNewName] = react.useState("");
618
618
  const [newDesc, setNewDesc] = react.useState("");
@@ -699,8 +699,8 @@ function RolesTab() {
699
699
  ] });
700
700
  }
701
701
  function UsersTab() {
702
- const { users, isLoading, error, assignUserRole, removeUserRole } = chunkSHHZ37FE_cjs.useAdminUsers();
703
- const { roles } = chunkSHHZ37FE_cjs.useAdminRoles();
702
+ const { users, isLoading, error, assignUserRole, removeUserRole } = chunkT2C43AAL_cjs.useAdminUsers();
703
+ const { roles } = chunkT2C43AAL_cjs.useAdminRoles();
704
704
  const [showAdd, setShowAdd] = react.useState(false);
705
705
  const [newEmail, setNewEmail] = react.useState("");
706
706
  const [newRoleId, setNewRoleId] = react.useState(0);
@@ -787,7 +787,7 @@ function UsersTab() {
787
787
  ] });
788
788
  }
789
789
  function AdminDashboard({ className }) {
790
- const { isAuthenticated, isLoading: authLoading } = chunkSHHZ37FE_cjs.useAuth();
790
+ const { isAuthenticated, isLoading: authLoading } = chunkT2C43AAL_cjs.useAuth();
791
791
  const [tab, setTab] = react.useState("fields");
792
792
  const [initError, setInitError] = react.useState(null);
793
793
  if (authLoading) return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...rootStyle2, ...emptyStyle2 }, children: "Loading..." });
@@ -805,10 +805,556 @@ function AdminDashboard({ className }) {
805
805
  tab === "users" && /* @__PURE__ */ jsxRuntime.jsx(UsersTab, {})
806
806
  ] });
807
807
  }
808
+ var InspectableRegistryContext = react.createContext(null);
809
+ function InspectableRegistry({ children }) {
810
+ const [entries, setEntries] = react.useState(/* @__PURE__ */ new Map());
811
+ const [inspectActive, setInspectActive] = react.useState(false);
812
+ const [selectedId, setSelectedId] = react.useState(null);
813
+ const register = react.useCallback((entry) => {
814
+ setEntries((prev) => {
815
+ const next = new Map(prev);
816
+ next.set(entry.id, entry);
817
+ return next;
818
+ });
819
+ }, []);
820
+ const unregister = react.useCallback((id) => {
821
+ setEntries((prev) => {
822
+ const next = new Map(prev);
823
+ next.delete(id);
824
+ return next;
825
+ });
826
+ setSelectedId((prev) => prev === id ? null : prev);
827
+ }, []);
828
+ const value = {
829
+ entries,
830
+ register,
831
+ unregister,
832
+ inspectActive,
833
+ setInspectActive,
834
+ selectedId,
835
+ setSelectedId
836
+ };
837
+ return /* @__PURE__ */ jsxRuntime.jsx(InspectableRegistryContext.Provider, { value, children });
838
+ }
839
+ function Inspectable({
840
+ label,
841
+ currentSource = "unknown",
842
+ data,
843
+ columns,
844
+ children
845
+ }) {
846
+ const registry = react.useContext(InspectableRegistryContext);
847
+ const id = react.useId();
848
+ const ref = react.useRef(null);
849
+ const inferredColumns = columns ?? (data?.[0] ? Object.keys(data[0]) : []);
850
+ const sampleValues = data?.slice(0, 3) ?? [];
851
+ react.useEffect(() => {
852
+ if (!registry) return;
853
+ registry.register({
854
+ id,
855
+ label,
856
+ currentSource,
857
+ columns: inferredColumns,
858
+ sampleValues,
859
+ element: ref.current
860
+ });
861
+ return () => registry.unregister(id);
862
+ }, [id, label, currentSource, inferredColumns.join(","), registry]);
863
+ if (!registry) {
864
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
865
+ }
866
+ const isSelected = registry.selectedId === id;
867
+ const showOutline = registry.inspectActive;
868
+ const handleClick = (e) => {
869
+ if (!registry.inspectActive) return;
870
+ e.stopPropagation();
871
+ registry.setSelectedId(isSelected ? null : id);
872
+ };
873
+ return /* @__PURE__ */ jsxRuntime.jsxs(
874
+ "div",
875
+ {
876
+ ref,
877
+ onClick: handleClick,
878
+ style: {
879
+ position: "relative",
880
+ outline: showOutline ? isSelected ? "2px solid #3b82f6" : "2px dashed #93c5fd" : "none",
881
+ outlineOffset: 2,
882
+ borderRadius: 4,
883
+ cursor: showOutline ? "pointer" : "inherit",
884
+ transition: "outline 0.15s ease"
885
+ },
886
+ children: [
887
+ showOutline && /* @__PURE__ */ jsxRuntime.jsx(
888
+ "div",
889
+ {
890
+ style: {
891
+ position: "absolute",
892
+ top: -10,
893
+ left: 4,
894
+ fontSize: 10,
895
+ fontWeight: 600,
896
+ fontFamily: "system-ui, -apple-system, sans-serif",
897
+ color: "#fff",
898
+ backgroundColor: isSelected ? "#3b82f6" : "#93c5fd",
899
+ padding: "1px 6px",
900
+ borderRadius: 3,
901
+ zIndex: 1e4,
902
+ pointerEvents: "none",
903
+ whiteSpace: "nowrap"
904
+ },
905
+ children: label
906
+ }
907
+ ),
908
+ children
909
+ ]
910
+ }
911
+ );
912
+ }
913
+
914
+ // src/components/field-matcher.ts
915
+ var AGG_PREFIXES = ["total_", "sum_", "avg_", "count_", "min_", "max_", "num_"];
916
+ var NOISE_SUFFIXES = ["_name", "_id", "_value", "_val", "_amt", "_amount"];
917
+ function camelToSnake(s) {
918
+ return s.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
919
+ }
920
+ function normalize(s) {
921
+ let result = camelToSnake(s).toLowerCase().trim();
922
+ for (const prefix of AGG_PREFIXES) {
923
+ if (result.startsWith(prefix) && result.length > prefix.length) {
924
+ result = result.slice(prefix.length);
925
+ break;
926
+ }
927
+ }
928
+ for (const suffix of NOISE_SUFFIXES) {
929
+ if (result.endsWith(suffix) && result.length > suffix.length) {
930
+ result = result.slice(0, -suffix.length);
931
+ break;
932
+ }
933
+ }
934
+ return result;
935
+ }
936
+ function matchExact(column, catalog) {
937
+ const lower = column.toLowerCase();
938
+ return catalog.find((f) => f.name.toLowerCase() === lower) ?? null;
939
+ }
940
+ function matchNormalized(column, catalog) {
941
+ const norm = normalize(column);
942
+ return catalog.find((f) => normalize(f.name) === norm) ?? null;
943
+ }
944
+ function matchDisplayName(column, catalog) {
945
+ const lower = normalize(column).replace(/_/g, " ");
946
+ if (lower.length < 3) return null;
947
+ return catalog.find((f) => f.displayName.toLowerCase().includes(lower)) ?? catalog.find((f) => f.description.toLowerCase().includes(lower)) ?? null;
948
+ }
949
+ function matchFields(columns, catalog) {
950
+ return columns.map((column) => {
951
+ const exact = matchExact(column, catalog);
952
+ if (exact) return { column, suggestedField: exact, confidence: "exact" };
953
+ const normalized = matchNormalized(column, catalog);
954
+ if (normalized) return { column, suggestedField: normalized, confidence: "fuzzy" };
955
+ const display = matchDisplayName(column, catalog);
956
+ if (display) return { column, suggestedField: display, confidence: "fuzzy" };
957
+ return { column, suggestedField: null, confidence: "manual" };
958
+ });
959
+ }
960
+
961
+ // src/components/prompt-generator.ts
962
+ function generateMigrationPrompt(componentLabel, mappings) {
963
+ const resolved = mappings.filter((m) => m.field !== null);
964
+ if (resolved.length === 0) {
965
+ return `Replace the sample/hardcoded data in the "${componentLabel}" component with live data from the semantic layer using useSemanticQuery. Use the DataCatalog to find the right field names.`;
966
+ }
967
+ const metrics = resolved.filter((m) => m.field.type === "metric").map((m) => m.field.name);
968
+ const timeDims = resolved.filter((m) => m.field.type === "time_dimension").map((m) => m.field.name);
969
+ const dims = resolved.filter((m) => m.field.type === "dimension").map((m) => m.field.name);
970
+ const groupBy = [...timeDims, ...dims];
971
+ const parts = [
972
+ `Replace the sample/hardcoded data in the "${componentLabel}" component with a useSemanticQuery call using:`
973
+ ];
974
+ if (metrics.length > 0) {
975
+ parts.push(` metrics: [${metrics.map((n) => `'${n}'`).join(", ")}]`);
976
+ }
977
+ if (groupBy.length > 0) {
978
+ parts.push(` groupBy: [${groupBy.map((n) => `'${n}'`).join(", ")}]`);
979
+ }
980
+ if (timeDims.length > 0) {
981
+ parts.push(` grain: 'month'`);
982
+ }
983
+ parts.push("");
984
+ parts.push("Map the query result columns to the component's props:");
985
+ for (const m of resolved) {
986
+ parts.push(` "${m.column}" \u2192 data column "${m.field.name}"`);
987
+ }
988
+ parts.push("");
989
+ parts.push(
990
+ "Remove the old hardcoded/sample data and any fetch logic it used. Use the data, isLoading, and error values from useSemanticQuery to render the component."
991
+ );
992
+ return parts.join("\n");
993
+ }
994
+ function DataInspector({ children }) {
995
+ return /* @__PURE__ */ jsxRuntime.jsxs(InspectableRegistry, { children: [
996
+ /* @__PURE__ */ jsxRuntime.jsx(InspectorOverlay, {}),
997
+ children
998
+ ] });
999
+ }
1000
+ function InspectorOverlay() {
1001
+ const registry = react.useContext(InspectableRegistryContext);
1002
+ if (!registry) return null;
1003
+ const { inspectActive, setInspectActive, selectedId, setSelectedId, entries } = registry;
1004
+ react.useEffect(() => {
1005
+ function handleKeyDown(e) {
1006
+ if (e.ctrlKey && e.shiftKey && e.key === "I") {
1007
+ e.preventDefault();
1008
+ setInspectActive(!inspectActive);
1009
+ }
1010
+ }
1011
+ window.addEventListener("keydown", handleKeyDown);
1012
+ return () => window.removeEventListener("keydown", handleKeyDown);
1013
+ }, [inspectActive, setInspectActive]);
1014
+ const selectedEntry = selectedId ? entries.get(selectedId) ?? null : null;
1015
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1016
+ /* @__PURE__ */ jsxRuntime.jsx(
1017
+ ToggleButton,
1018
+ {
1019
+ active: inspectActive,
1020
+ count: entries.size,
1021
+ onToggle: () => {
1022
+ setInspectActive(!inspectActive);
1023
+ if (inspectActive) setSelectedId(null);
1024
+ }
1025
+ }
1026
+ ),
1027
+ selectedEntry && /* @__PURE__ */ jsxRuntime.jsx(
1028
+ InspectorModal,
1029
+ {
1030
+ entry: selectedEntry,
1031
+ onClose: () => setSelectedId(null)
1032
+ }
1033
+ )
1034
+ ] });
1035
+ }
1036
+ function ToggleButton({
1037
+ active,
1038
+ count,
1039
+ onToggle
1040
+ }) {
1041
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1042
+ "button",
1043
+ {
1044
+ onClick: onToggle,
1045
+ title: active ? "Exit inspect mode (Ctrl+Shift+I)" : "Enter inspect mode (Ctrl+Shift+I)",
1046
+ style: {
1047
+ position: "fixed",
1048
+ bottom: 20,
1049
+ right: 20,
1050
+ zIndex: 99999,
1051
+ display: "flex",
1052
+ alignItems: "center",
1053
+ gap: 6,
1054
+ padding: "8px 16px",
1055
+ fontSize: 13,
1056
+ fontWeight: 600,
1057
+ fontFamily: "system-ui, -apple-system, sans-serif",
1058
+ color: active ? "#fff" : "#374151",
1059
+ backgroundColor: active ? "#3b82f6" : "#fff",
1060
+ border: `1px solid ${active ? "#2563eb" : "#d1d5db"}`,
1061
+ borderRadius: 999,
1062
+ cursor: "pointer",
1063
+ boxShadow: "0 2px 8px rgba(0,0,0,0.12)",
1064
+ transition: "all 0.15s ease"
1065
+ },
1066
+ children: [
1067
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
1068
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "8" }),
1069
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
1070
+ ] }),
1071
+ active ? "Inspecting" : "Inspect Data",
1072
+ count > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1073
+ "span",
1074
+ {
1075
+ style: {
1076
+ display: "inline-flex",
1077
+ alignItems: "center",
1078
+ justifyContent: "center",
1079
+ minWidth: 18,
1080
+ height: 18,
1081
+ fontSize: 11,
1082
+ fontWeight: 700,
1083
+ borderRadius: 999,
1084
+ backgroundColor: active ? "rgba(255,255,255,0.25)" : "#e5e7eb",
1085
+ color: active ? "#fff" : "#6b7280",
1086
+ padding: "0 5px"
1087
+ },
1088
+ children: count
1089
+ }
1090
+ )
1091
+ ]
1092
+ }
1093
+ );
1094
+ }
1095
+ function InspectorModal({
1096
+ entry,
1097
+ onClose
1098
+ }) {
1099
+ const { fields: catalog } = chunkT2C43AAL_cjs.useMetrics();
1100
+ const initialMatches = react.useMemo(
1101
+ () => matchFields(entry.columns, catalog),
1102
+ [entry.columns, catalog]
1103
+ );
1104
+ const [mappings, setMappings] = react.useState(
1105
+ () => new Map(initialMatches.map((m) => [m.column, m.suggestedField]))
1106
+ );
1107
+ react.useEffect(() => {
1108
+ setMappings(new Map(initialMatches.map((m) => [m.column, m.suggestedField])));
1109
+ }, [initialMatches]);
1110
+ const [copied, setCopied] = react.useState(false);
1111
+ const handleFieldChange = react.useCallback((column, field) => {
1112
+ setMappings((prev) => {
1113
+ const next = new Map(prev);
1114
+ next.set(column, field);
1115
+ return next;
1116
+ });
1117
+ }, []);
1118
+ const handleGenerate = react.useCallback(async () => {
1119
+ const fieldMappings = entry.columns.map((col) => ({
1120
+ column: col,
1121
+ field: mappings.get(col) ?? null
1122
+ }));
1123
+ const prompt = generateMigrationPrompt(entry.label, fieldMappings);
1124
+ try {
1125
+ await navigator.clipboard.writeText(prompt);
1126
+ setCopied(true);
1127
+ setTimeout(() => setCopied(false), 2e3);
1128
+ } catch {
1129
+ const ta = document.createElement("textarea");
1130
+ ta.value = prompt;
1131
+ document.body.appendChild(ta);
1132
+ ta.select();
1133
+ document.execCommand("copy");
1134
+ document.body.removeChild(ta);
1135
+ setCopied(true);
1136
+ setTimeout(() => setCopied(false), 2e3);
1137
+ }
1138
+ }, [entry, mappings]);
1139
+ const confidenceMap = react.useMemo(() => {
1140
+ const map = /* @__PURE__ */ new Map();
1141
+ for (const m of initialMatches) map.set(m.column, m.confidence);
1142
+ return map;
1143
+ }, [initialMatches]);
1144
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1145
+ /* @__PURE__ */ jsxRuntime.jsx("div", { onClick: onClose, style: backdropStyle }),
1146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: modalStyle, children: [
1147
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: modalHeaderStyle, children: [
1148
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1149
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 700, color: "#111827" }, children: entry.label }),
1150
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: "#6b7280", marginTop: 2 }, children: [
1151
+ "Source: ",
1152
+ entry.currentSource
1153
+ ] })
1154
+ ] }),
1155
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onClose, style: closeBtnStyle, children: "\xD7" })
1156
+ ] }),
1157
+ entry.sampleValues.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: sectionStyle, children: [
1158
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: sectionTitleStyle, children: "Current Data Preview" }),
1159
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflow: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { style: previewTableStyle, children: [
1160
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: entry.columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { style: previewThStyle, children: col }, col)) }) }),
1161
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: entry.sampleValues.map((row, i) => /* @__PURE__ */ jsxRuntime.jsx("tr", { children: entry.columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("td", { style: previewTdStyle, children: row[col] === null || row[col] === void 0 ? "\u2014" : String(row[col]) }, col)) }, i)) })
1162
+ ] }) })
1163
+ ] }),
1164
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: sectionStyle, children: [
1165
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: sectionTitleStyle, children: "Field Mapping" }),
1166
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: 13 }, children: [
1167
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1168
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Current Column" }),
1169
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Confidence" }),
1170
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: mappingThStyle, children: "Semantic Layer Field" })
1171
+ ] }) }),
1172
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: entry.columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
1173
+ MappingRow,
1174
+ {
1175
+ column: col,
1176
+ confidence: confidenceMap.get(col) ?? "manual",
1177
+ selectedField: mappings.get(col) ?? null,
1178
+ catalog,
1179
+ onChange: (field) => handleFieldChange(col, field)
1180
+ },
1181
+ col
1182
+ )) })
1183
+ ] }),
1184
+ catalog.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: "#9ca3af", marginTop: 8, textAlign: "center" }, children: "No semantic layer catalog available. Connect to the gateway to enable smart matching." })
1185
+ ] }),
1186
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "12px 20px", borderTop: "1px solid #e5e7eb" }, children: /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleGenerate, style: generateBtnStyle, children: copied ? "Copied to clipboard!" : "Generate Migration Prompt" }) })
1187
+ ] })
1188
+ ] });
1189
+ }
1190
+ function MappingRow({
1191
+ column,
1192
+ confidence,
1193
+ selectedField,
1194
+ catalog,
1195
+ onChange
1196
+ }) {
1197
+ const badgeColors = {
1198
+ exact: { bg: "#dcfce7", color: "#15803d" },
1199
+ fuzzy: { bg: "#fef9c3", color: "#a16207" },
1200
+ manual: { bg: "#fee2e2", color: "#dc2626" }
1201
+ };
1202
+ const badge = badgeColors[confidence] ?? badgeColors.manual;
1203
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1204
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: mappingTdStyle, children: /* @__PURE__ */ jsxRuntime.jsx("code", { style: { fontSize: 12, color: "#6366f1", fontFamily: "monospace" }, children: column }) }),
1205
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { ...mappingTdStyle, textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1206
+ "span",
1207
+ {
1208
+ style: {
1209
+ display: "inline-block",
1210
+ padding: "1px 6px",
1211
+ fontSize: 10,
1212
+ fontWeight: 600,
1213
+ borderRadius: 4,
1214
+ backgroundColor: badge.bg,
1215
+ color: badge.color
1216
+ },
1217
+ children: confidence
1218
+ }
1219
+ ) }),
1220
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: mappingTdStyle, children: catalog.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
1221
+ "select",
1222
+ {
1223
+ value: selectedField?.name ?? "",
1224
+ onChange: (e) => {
1225
+ const field = catalog.find((f) => f.name === e.target.value) ?? null;
1226
+ onChange(field);
1227
+ },
1228
+ style: selectStyle2,
1229
+ children: [
1230
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "-- none --" }),
1231
+ catalog.map((f) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: f.name, children: [
1232
+ f.displayName,
1233
+ " (",
1234
+ f.type,
1235
+ ") \u2014 ",
1236
+ f.name
1237
+ ] }, f.name))
1238
+ ]
1239
+ }
1240
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#9ca3af" }, children: selectedField ? selectedField.name : "No catalog" }) })
1241
+ ] });
1242
+ }
1243
+ var backdropStyle = {
1244
+ position: "fixed",
1245
+ inset: 0,
1246
+ backgroundColor: "rgba(0,0,0,0.3)",
1247
+ zIndex: 1e5
1248
+ };
1249
+ var modalStyle = {
1250
+ position: "fixed",
1251
+ top: "50%",
1252
+ left: "50%",
1253
+ transform: "translate(-50%, -50%)",
1254
+ zIndex: 100001,
1255
+ width: "min(640px, 90vw)",
1256
+ maxHeight: "80vh",
1257
+ backgroundColor: "#fff",
1258
+ borderRadius: 12,
1259
+ boxShadow: "0 8px 30px rgba(0,0,0,0.2)",
1260
+ display: "flex",
1261
+ flexDirection: "column",
1262
+ overflow: "hidden",
1263
+ fontFamily: "system-ui, -apple-system, sans-serif"
1264
+ };
1265
+ var modalHeaderStyle = {
1266
+ display: "flex",
1267
+ justifyContent: "space-between",
1268
+ alignItems: "flex-start",
1269
+ padding: "16px 20px",
1270
+ borderBottom: "1px solid #e5e7eb"
1271
+ };
1272
+ var closeBtnStyle = {
1273
+ background: "none",
1274
+ border: "none",
1275
+ fontSize: 22,
1276
+ color: "#6b7280",
1277
+ cursor: "pointer",
1278
+ padding: "0 4px",
1279
+ lineHeight: 1
1280
+ };
1281
+ var sectionStyle = {
1282
+ padding: "12px 20px",
1283
+ overflow: "auto",
1284
+ flex: 1
1285
+ };
1286
+ var sectionTitleStyle = {
1287
+ fontSize: 11,
1288
+ fontWeight: 700,
1289
+ textTransform: "uppercase",
1290
+ letterSpacing: "0.05em",
1291
+ color: "#6b7280",
1292
+ marginBottom: 8
1293
+ };
1294
+ var previewTableStyle = {
1295
+ width: "100%",
1296
+ borderCollapse: "collapse",
1297
+ fontSize: 12
1298
+ };
1299
+ var previewThStyle = {
1300
+ padding: "4px 8px",
1301
+ textAlign: "left",
1302
+ fontWeight: 600,
1303
+ color: "#374151",
1304
+ backgroundColor: "#f9fafb",
1305
+ borderBottom: "1px solid #e5e7eb",
1306
+ whiteSpace: "nowrap"
1307
+ };
1308
+ var previewTdStyle = {
1309
+ padding: "4px 8px",
1310
+ color: "#6b7280",
1311
+ borderBottom: "1px solid #f3f4f6",
1312
+ whiteSpace: "nowrap",
1313
+ maxWidth: 150,
1314
+ overflow: "hidden",
1315
+ textOverflow: "ellipsis"
1316
+ };
1317
+ var mappingThStyle = {
1318
+ padding: "6px 8px",
1319
+ textAlign: "left",
1320
+ fontWeight: 600,
1321
+ fontSize: 11,
1322
+ color: "#6b7280",
1323
+ borderBottom: "1px solid #e5e7eb"
1324
+ };
1325
+ var mappingTdStyle = {
1326
+ padding: "6px 8px",
1327
+ borderBottom: "1px solid #f3f4f6",
1328
+ verticalAlign: "middle"
1329
+ };
1330
+ var selectStyle2 = {
1331
+ width: "100%",
1332
+ padding: "4px 6px",
1333
+ fontSize: 12,
1334
+ border: "1px solid #d1d5db",
1335
+ borderRadius: 4,
1336
+ backgroundColor: "#fff",
1337
+ color: "#111827"
1338
+ };
1339
+ var generateBtnStyle = {
1340
+ width: "100%",
1341
+ padding: "10px 16px",
1342
+ fontSize: 14,
1343
+ fontWeight: 600,
1344
+ color: "#fff",
1345
+ backgroundColor: "#3b82f6",
1346
+ border: "none",
1347
+ borderRadius: 8,
1348
+ cursor: "pointer"
1349
+ };
808
1350
 
809
1351
  exports.AdminDashboard = AdminDashboard;
810
1352
  exports.DataCatalog = DataCatalog;
1353
+ exports.DataInspector = DataInspector;
1354
+ exports.Inspectable = Inspectable;
811
1355
  exports.MetricPicker = MetricPicker;
812
1356
  exports.ResultsTable = ResultsTable;
1357
+ exports.generateMigrationPrompt = generateMigrationPrompt;
1358
+ exports.matchFields = matchFields;
813
1359
  //# sourceMappingURL=components.cjs.map
814
1360
  //# sourceMappingURL=components.cjs.map