@tscircuit/runframe 0.0.274 → 0.0.276
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/{chunk-XJXAIAEQ.js → chunk-TPHHXIJB.js} +5 -2
- package/dist/preview.js +1 -1
- package/dist/runner.js +488 -123
- package/dist/standalone-preview.min.js +931 -1121
- package/dist/standalone.min.js +963 -1143
- package/package.json +2 -2
package/dist/runner.js
CHANGED
|
@@ -9,9 +9,12 @@ import {
|
|
|
9
9
|
DropdownMenuSubContent,
|
|
10
10
|
DropdownMenuSubTrigger,
|
|
11
11
|
DropdownMenuTrigger,
|
|
12
|
+
Tabs,
|
|
13
|
+
TabsList,
|
|
14
|
+
TabsTrigger,
|
|
12
15
|
buttonVariants,
|
|
13
16
|
cn
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-TPHHXIJB.js";
|
|
15
18
|
|
|
16
19
|
// lib/components/RunFrame/RunFrame.tsx
|
|
17
20
|
import { createCircuitWebWorker } from "@tscircuit/eval/worker";
|
|
@@ -745,7 +748,7 @@ function useLocalStorageState(key, initialValue) {
|
|
|
745
748
|
}
|
|
746
749
|
|
|
747
750
|
// lib/components/RunFrameForCli/LeftHeader.tsx
|
|
748
|
-
import { useEffect as
|
|
751
|
+
import { useEffect as useEffect7, useMemo as useMemo4, useState as useState7 } from "react";
|
|
749
752
|
|
|
750
753
|
// lib/components/RunFrameForCli/SelectSnippetDialog.tsx
|
|
751
754
|
import { useState as useState5 } from "react";
|
|
@@ -984,8 +987,334 @@ var Checkbox = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
984
987
|
));
|
|
985
988
|
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
986
989
|
|
|
990
|
+
// lib/components/ImportComponentDialog/ImportComponentDialog.tsx
|
|
991
|
+
import "react";
|
|
992
|
+
import { useState as useState6, useEffect as useEffect6 } from "react";
|
|
993
|
+
import { Loader2 as Loader22, Search, ExternalLink } from "lucide-react";
|
|
994
|
+
|
|
995
|
+
// lib/components/ui/input.tsx
|
|
996
|
+
import * as React3 from "react";
|
|
997
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
998
|
+
var Input = React3.forwardRef(
|
|
999
|
+
({ className, type, ...props }, ref) => {
|
|
1000
|
+
return /* @__PURE__ */ jsx6(
|
|
1001
|
+
"input",
|
|
1002
|
+
{
|
|
1003
|
+
type,
|
|
1004
|
+
className: cn(
|
|
1005
|
+
"rf-flex rf-h-9 rf-w-full rf-rounded-md rf-border rf-border-zinc-200 rf-bg-white rf-px-3 rf-py-1 rf-text-sm rf-shadow-sm rf-transition-colors file:rf-border-0 file:rf-bg-transparent file:rf-text-sm file:rf-font-medium placeholder:rf-text-zinc-500 focus-visible:rf-outline-none focus-visible:rf-ring-1 focus-visible:rf-ring-zinc-950 disabled:rf-cursor-not-allowed disabled:rf-opacity-50 dark:rf-border-zinc-800 dark:rf-bg-zinc-950 dark:rf-placeholder-zinc-400 dark:focus-visible:rf-ring-zinc-300",
|
|
1006
|
+
className
|
|
1007
|
+
),
|
|
1008
|
+
ref,
|
|
1009
|
+
...props
|
|
1010
|
+
}
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
);
|
|
1014
|
+
Input.displayName = "Input";
|
|
1015
|
+
|
|
1016
|
+
// lib/components/ImportComponentDialog/jlc-api.ts
|
|
1017
|
+
var searchJLCComponents = async (query, limit = 10) => {
|
|
1018
|
+
try {
|
|
1019
|
+
const encodedQuery = encodeURIComponent(query);
|
|
1020
|
+
const response = await fetch(
|
|
1021
|
+
`https://jlcsearch.tscircuit.com/api/search?limit=${limit}&q=${encodedQuery}`
|
|
1022
|
+
);
|
|
1023
|
+
if (!response.ok) {
|
|
1024
|
+
throw new Error(
|
|
1025
|
+
`JLC API error: ${response.status} ${response.statusText}`
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
1028
|
+
const data = await response.json();
|
|
1029
|
+
return data.components || [];
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
console.error("Error searching JLC components:", error);
|
|
1032
|
+
throw error;
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
var mapJLCComponentToSearchResult = (jlcComponent) => {
|
|
1036
|
+
return {
|
|
1037
|
+
id: `jlc-${jlcComponent.lcsc}`,
|
|
1038
|
+
name: jlcComponent.mfr,
|
|
1039
|
+
description: jlcComponent.description,
|
|
1040
|
+
source: "jlcpcb",
|
|
1041
|
+
partNumber: `C${jlcComponent.lcsc}`,
|
|
1042
|
+
package: jlcComponent.package,
|
|
1043
|
+
price: jlcComponent.price
|
|
1044
|
+
};
|
|
1045
|
+
};
|
|
1046
|
+
|
|
1047
|
+
// lib/components/ImportComponentDialog/tscircuit-registry-api.ts
|
|
1048
|
+
var searchTscircuitComponents = async (query, limit = 10) => {
|
|
1049
|
+
try {
|
|
1050
|
+
const encodedQuery = encodeURIComponent(query);
|
|
1051
|
+
const response = await fetch(
|
|
1052
|
+
`https://registry-api.tscircuit.com/snippets/search?q=${encodedQuery}&limit=${limit}`
|
|
1053
|
+
);
|
|
1054
|
+
if (!response.ok) {
|
|
1055
|
+
throw new Error(
|
|
1056
|
+
`tscircuit Registry API error: ${response.status} ${response.statusText}`
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
const data = await response.json();
|
|
1060
|
+
return data.snippets || [];
|
|
1061
|
+
} catch (error) {
|
|
1062
|
+
console.error("Error searching tscircuit components:", error);
|
|
1063
|
+
throw error;
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
var mapTscircuitSnippetToSearchResult = (tscircuitSnippet) => {
|
|
1067
|
+
return {
|
|
1068
|
+
id: `tscircuit-${tscircuitSnippet.snippet_id}`,
|
|
1069
|
+
name: tscircuitSnippet.unscoped_name,
|
|
1070
|
+
description: tscircuitSnippet.description || `Component by ${tscircuitSnippet.owner_name}`,
|
|
1071
|
+
source: "tscircuit",
|
|
1072
|
+
partNumber: tscircuitSnippet.name,
|
|
1073
|
+
previewUrl: tscircuitSnippet.preview_url,
|
|
1074
|
+
// Additional tscircuit-specific properties
|
|
1075
|
+
code: tscircuitSnippet.code,
|
|
1076
|
+
owner: tscircuitSnippet.owner_name
|
|
1077
|
+
};
|
|
1078
|
+
};
|
|
1079
|
+
|
|
1080
|
+
// lib/components/ImportComponentDialog/ImportComponentDialog.tsx
|
|
1081
|
+
import { createSvgUrl as createPngUrl } from "@tscircuit/create-snippet-url";
|
|
1082
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1083
|
+
var ImportComponentDialog = ({
|
|
1084
|
+
isOpen,
|
|
1085
|
+
onClose,
|
|
1086
|
+
onImport
|
|
1087
|
+
}) => {
|
|
1088
|
+
const [searchQuery, setSearchQuery] = useState6("");
|
|
1089
|
+
const [searchResults, setSearchResults] = useState6(
|
|
1090
|
+
[]
|
|
1091
|
+
);
|
|
1092
|
+
const [hasSearched, setHasSearched] = useState6(false);
|
|
1093
|
+
const [isLoading, setIsLoading] = useState6(false);
|
|
1094
|
+
const [selectedComponent, setSelectedComponent] = useState6(null);
|
|
1095
|
+
const [activeTab, setActiveTab] = useState6(
|
|
1096
|
+
"tscircuit"
|
|
1097
|
+
);
|
|
1098
|
+
const [detailsOpen, setDetailsOpen] = useState6(false);
|
|
1099
|
+
const [detailsComponent, setDetailsComponent] = useState6(null);
|
|
1100
|
+
const handleSearch = async () => {
|
|
1101
|
+
if (!searchQuery.trim()) return;
|
|
1102
|
+
setIsLoading(true);
|
|
1103
|
+
const isJlcPartNumber = /^C\d+/.test(searchQuery);
|
|
1104
|
+
if (isJlcPartNumber) {
|
|
1105
|
+
setActiveTab("jlcpcb");
|
|
1106
|
+
}
|
|
1107
|
+
try {
|
|
1108
|
+
if (activeTab === "jlcpcb") {
|
|
1109
|
+
const query = isJlcPartNumber ? searchQuery.substring(1) : searchQuery;
|
|
1110
|
+
const jlcComponents = await searchJLCComponents(query, 10);
|
|
1111
|
+
const mappedResults = jlcComponents.map(mapJLCComponentToSearchResult);
|
|
1112
|
+
setSearchResults(mappedResults);
|
|
1113
|
+
} else {
|
|
1114
|
+
const tscircuitComponents = await searchTscircuitComponents(
|
|
1115
|
+
searchQuery,
|
|
1116
|
+
10
|
|
1117
|
+
);
|
|
1118
|
+
const mappedResults = tscircuitComponents.map(
|
|
1119
|
+
mapTscircuitSnippetToSearchResult
|
|
1120
|
+
);
|
|
1121
|
+
setSearchResults(mappedResults);
|
|
1122
|
+
}
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
console.error("Error searching components:", error);
|
|
1125
|
+
setSearchResults([]);
|
|
1126
|
+
} finally {
|
|
1127
|
+
setIsLoading(false);
|
|
1128
|
+
setHasSearched(true);
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
const handleKeyDown = (e) => {
|
|
1132
|
+
if (e.key === "Enter") {
|
|
1133
|
+
handleSearch();
|
|
1134
|
+
}
|
|
1135
|
+
};
|
|
1136
|
+
useEffect6(() => {
|
|
1137
|
+
setSearchResults([]);
|
|
1138
|
+
setSelectedComponent(null);
|
|
1139
|
+
}, [activeTab]);
|
|
1140
|
+
const showDetails = (component) => {
|
|
1141
|
+
setDetailsComponent(component);
|
|
1142
|
+
setDetailsOpen(true);
|
|
1143
|
+
};
|
|
1144
|
+
return /* @__PURE__ */ jsxs5(AlertDialog, { open: isOpen, onOpenChange: () => onClose(), children: [
|
|
1145
|
+
/* @__PURE__ */ jsxs5(AlertDialogContent, { className: "rf-max-w-3xl rf-w-full rf-max-h-[90vh] rf-overflow-y-auto rf-flex rf-flex-col", children: [
|
|
1146
|
+
/* @__PURE__ */ jsxs5(AlertDialogHeader, { children: [
|
|
1147
|
+
/* @__PURE__ */ jsx7(AlertDialogTitle, { children: "Import Component" }),
|
|
1148
|
+
/* @__PURE__ */ jsx7(AlertDialogDescription, { children: "Search for components from tscircuit.com or JLCPCB parts library." })
|
|
1149
|
+
] }),
|
|
1150
|
+
/* @__PURE__ */ jsxs5(
|
|
1151
|
+
Tabs,
|
|
1152
|
+
{
|
|
1153
|
+
value: activeTab,
|
|
1154
|
+
onValueChange: (value) => setActiveTab(value),
|
|
1155
|
+
children: [
|
|
1156
|
+
/* @__PURE__ */ jsxs5(TabsList, { className: "rf-grid rf-w-full rf-grid-cols-2", children: [
|
|
1157
|
+
/* @__PURE__ */ jsx7(TabsTrigger, { value: "tscircuit", children: "tscircuit.com" }),
|
|
1158
|
+
/* @__PURE__ */ jsx7(TabsTrigger, { value: "jlcpcb", children: "JLCPCB Parts" })
|
|
1159
|
+
] }),
|
|
1160
|
+
/* @__PURE__ */ jsxs5("div", { className: "rf-flex rf-items-center rf-gap-2 rf-mt-4", children: [
|
|
1161
|
+
/* @__PURE__ */ jsxs5("div", { className: "rf-relative rf-flex-grow", children: [
|
|
1162
|
+
/* @__PURE__ */ jsx7(Search, { className: "rf-absolute rf-left-2 rf-top-2.5 rf-h-4 rf-w-4 rf-text-muted-foreground" }),
|
|
1163
|
+
/* @__PURE__ */ jsx7(
|
|
1164
|
+
Input,
|
|
1165
|
+
{
|
|
1166
|
+
placeholder: activeTab === "tscircuit" ? "Search components..." : "Search JLCPCB parts (e.g. C14663)...",
|
|
1167
|
+
className: "rf-pl-8",
|
|
1168
|
+
value: searchQuery,
|
|
1169
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
1170
|
+
onKeyDown: handleKeyDown
|
|
1171
|
+
}
|
|
1172
|
+
)
|
|
1173
|
+
] }),
|
|
1174
|
+
/* @__PURE__ */ jsx7(Button, { onClick: handleSearch, disabled: isLoading, children: isLoading ? /* @__PURE__ */ jsx7(Loader22, { className: "rf-h-4 rf-w-4 rf-animate-spin" }) : "Search" })
|
|
1175
|
+
] }),
|
|
1176
|
+
/* @__PURE__ */ jsx7("div", { className: "rf-mt-4 rf-flex-1 rf-min-h-[200px] !rf-max-h-[40vh] !rf-overflow-y-auto rf-border rf-rounded-md", children: searchResults.length > 0 ? /* @__PURE__ */ jsx7("div", { className: "rf-divide-y", children: searchResults.map((result) => /* @__PURE__ */ jsxs5(
|
|
1177
|
+
"div",
|
|
1178
|
+
{
|
|
1179
|
+
className: `rf-p-3 rf-flex rf-items-center rf-justify-between rf-cursor-pointer hover:rf-bg-zinc-100 ${selectedComponent?.id === result.id ? "rf-bg-zinc-100" : ""}`,
|
|
1180
|
+
onClick: () => setSelectedComponent(result),
|
|
1181
|
+
children: [
|
|
1182
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
1183
|
+
/* @__PURE__ */ jsx7("div", { className: "rf-font-medium", children: result.name }),
|
|
1184
|
+
/* @__PURE__ */ jsxs5("div", { className: "rf-text-sm rf-text-zinc-500", children: [
|
|
1185
|
+
result.partNumber && /* @__PURE__ */ jsx7("span", { className: "rf-mr-2", children: result.partNumber }),
|
|
1186
|
+
result.description
|
|
1187
|
+
] })
|
|
1188
|
+
] }),
|
|
1189
|
+
/* @__PURE__ */ jsx7("div", { className: "rf-flex rf-gap-2", children: result.source === "tscircuit" && /* @__PURE__ */ jsx7(
|
|
1190
|
+
Button,
|
|
1191
|
+
{
|
|
1192
|
+
variant: "outline",
|
|
1193
|
+
size: "sm",
|
|
1194
|
+
onClick: (e) => {
|
|
1195
|
+
e.stopPropagation();
|
|
1196
|
+
showDetails(result);
|
|
1197
|
+
},
|
|
1198
|
+
children: "See Details"
|
|
1199
|
+
}
|
|
1200
|
+
) })
|
|
1201
|
+
]
|
|
1202
|
+
},
|
|
1203
|
+
result.id
|
|
1204
|
+
)) }) : isLoading ? /* @__PURE__ */ jsxs5("div", { className: "rf-p-8 rf-text-center rf-text-zinc-500", children: [
|
|
1205
|
+
/* @__PURE__ */ jsx7(Loader22, { className: "rf-h-8 rf-w-8 rf-animate-spin rf-mx-auto rf-mb-2" }),
|
|
1206
|
+
/* @__PURE__ */ jsx7("p", { children: "Searching..." })
|
|
1207
|
+
] }) : /* @__PURE__ */ jsx7("div", { className: "rf-p-8 rf-text-center rf-text-zinc-500", children: hasSearched ? "No results found" : "Enter a search term to find components" }) })
|
|
1208
|
+
]
|
|
1209
|
+
}
|
|
1210
|
+
),
|
|
1211
|
+
/* @__PURE__ */ jsxs5(AlertDialogFooter, { children: [
|
|
1212
|
+
/* @__PURE__ */ jsx7(AlertDialogCancel, { onClick: onClose, children: "Cancel" }),
|
|
1213
|
+
/* @__PURE__ */ jsx7(
|
|
1214
|
+
Button,
|
|
1215
|
+
{
|
|
1216
|
+
onClick: () => {
|
|
1217
|
+
if (selectedComponent) {
|
|
1218
|
+
onImport(selectedComponent);
|
|
1219
|
+
onClose();
|
|
1220
|
+
}
|
|
1221
|
+
},
|
|
1222
|
+
disabled: !selectedComponent,
|
|
1223
|
+
children: "Import Component"
|
|
1224
|
+
}
|
|
1225
|
+
)
|
|
1226
|
+
] })
|
|
1227
|
+
] }),
|
|
1228
|
+
/* @__PURE__ */ jsx7(AlertDialog, { open: detailsOpen, onOpenChange: setDetailsOpen, children: /* @__PURE__ */ jsxs5(AlertDialogContent, { className: "!rf-max-h-[70%] !rf-overflow-y-auto rf-flex rf-flex-col !rf-max-w-[60vw] !rf-overflow-x-hidden", children: [
|
|
1229
|
+
/* @__PURE__ */ jsxs5(AlertDialogHeader, { children: [
|
|
1230
|
+
/* @__PURE__ */ jsx7(AlertDialogTitle, { children: detailsComponent?.name }),
|
|
1231
|
+
/* @__PURE__ */ jsx7(AlertDialogDescription, { children: "Detailed information about the selected component" }),
|
|
1232
|
+
/* @__PURE__ */ jsxs5("div", { className: "rf-text-sm rf-text-muted-foreground", children: [
|
|
1233
|
+
detailsComponent?.partNumber && /* @__PURE__ */ jsx7("div", { className: "rf-font-mono rf-text-sm rf-mb-2", children: detailsComponent.partNumber }),
|
|
1234
|
+
detailsComponent?.description
|
|
1235
|
+
] })
|
|
1236
|
+
] }),
|
|
1237
|
+
detailsComponent?.source === "jlcpcb" && /* @__PURE__ */ jsxs5("div", { className: "rf-my-4 rf-border rf-rounded-md rf-p-4", children: [
|
|
1238
|
+
/* @__PURE__ */ jsx7("div", { className: "rf-text-sm rf-font-medium rf-mb-2", children: "JLCPCB Details" }),
|
|
1239
|
+
/* @__PURE__ */ jsxs5("div", { className: "rf-grid rf-grid-cols-2 rf-gap-2", children: [
|
|
1240
|
+
detailsComponent.package && /* @__PURE__ */ jsxs5("div", { className: "rf-flex rf-flex-col", children: [
|
|
1241
|
+
/* @__PURE__ */ jsx7("span", { className: "rf-text-xs rf-text-zinc-500", children: "Package" }),
|
|
1242
|
+
/* @__PURE__ */ jsx7("span", { className: "rf-font-medium", children: detailsComponent.package })
|
|
1243
|
+
] }),
|
|
1244
|
+
detailsComponent.price !== void 0 && /* @__PURE__ */ jsxs5("div", { className: "rf-flex rf-flex-col", children: [
|
|
1245
|
+
/* @__PURE__ */ jsx7("span", { className: "rf-text-xs rf-text-zinc-500", children: "Price" }),
|
|
1246
|
+
/* @__PURE__ */ jsxs5("span", { className: "rf-font-medium", children: [
|
|
1247
|
+
"$",
|
|
1248
|
+
detailsComponent.price.toFixed(4)
|
|
1249
|
+
] })
|
|
1250
|
+
] })
|
|
1251
|
+
] })
|
|
1252
|
+
] }),
|
|
1253
|
+
detailsComponent?.source === "tscircuit" && /* @__PURE__ */ jsxs5("div", { className: "rf-my-4 rf-border rf-rounded-md rf-p-4 !rf-max-w-[60vw] !rf-overflow-x-hidden", children: [
|
|
1254
|
+
/* @__PURE__ */ jsx7("div", { className: "rf-text-sm rf-font-medium rf-mb-2", children: "tscircuit Details" }),
|
|
1255
|
+
/* @__PURE__ */ jsx7("div", { className: "rf-grid rf-grid-cols-2 rf-gap-2", children: detailsComponent.owner && /* @__PURE__ */ jsxs5("div", { className: "rf-flex rf-flex-col", children: [
|
|
1256
|
+
/* @__PURE__ */ jsx7("span", { className: "rf-text-xs rf-text-zinc-500", children: "Owner" }),
|
|
1257
|
+
/* @__PURE__ */ jsx7("span", { className: "rf-font-medium", children: detailsComponent.owner })
|
|
1258
|
+
] }) }),
|
|
1259
|
+
detailsComponent.code && /* @__PURE__ */ jsxs5("div", { className: "rf-mt-2", children: [
|
|
1260
|
+
/* @__PURE__ */ jsx7("div", { className: "rf-text-xs rf-text-zinc-500 rf-mb-1", children: "Code Preview" }),
|
|
1261
|
+
/* @__PURE__ */ jsxs5("pre", { className: "rf-bg-zinc-50 rf-p-2 rf-rounded rf-text-xs rf-font-mono rf-max-h-32 rf-overflow-y-auto", children: [
|
|
1262
|
+
detailsComponent.code.substring(0, 500),
|
|
1263
|
+
detailsComponent.code.length > 500 && "..."
|
|
1264
|
+
] })
|
|
1265
|
+
] })
|
|
1266
|
+
] }),
|
|
1267
|
+
/* @__PURE__ */ jsxs5("div", { className: "rf-my-4 rf-border rf-rounded-md rf-p-4", children: [
|
|
1268
|
+
/* @__PURE__ */ jsx7("div", { className: "rf-text-sm rf-font-medium rf-mb-2", children: "Preview" }),
|
|
1269
|
+
detailsComponent?.source === "tscircuit" && detailsComponent.code ? /* @__PURE__ */ jsx7("div", { className: "rf-flex rf-justify-center", children: /* @__PURE__ */ jsx7("div", { className: "rf-border rf-rounded rf-p-4 rf-bg-zinc-50", children: /* @__PURE__ */ jsx7(
|
|
1270
|
+
"img",
|
|
1271
|
+
{
|
|
1272
|
+
src: createPngUrl(detailsComponent.code, "pcb"),
|
|
1273
|
+
alt: detailsComponent.name,
|
|
1274
|
+
className: "rf-w-full rf-aspect-video rf-object-contain"
|
|
1275
|
+
}
|
|
1276
|
+
) }) }) : /* @__PURE__ */ jsx7("div", { className: "rf-text-center rf-text-zinc-500 rf-p-4", children: "No preview available" })
|
|
1277
|
+
] }),
|
|
1278
|
+
/* @__PURE__ */ jsxs5("div", { className: "rf-flex rf-justify-between", children: [
|
|
1279
|
+
/* @__PURE__ */ jsxs5(
|
|
1280
|
+
Button,
|
|
1281
|
+
{
|
|
1282
|
+
variant: "outline",
|
|
1283
|
+
size: "sm",
|
|
1284
|
+
className: "rf-gap-1",
|
|
1285
|
+
onClick: () => {
|
|
1286
|
+
const url = detailsComponent?.source === "jlcpcb" ? `https://jlcpcb.com/partdetail/${detailsComponent.partNumber}` : `https://tscircuit.com/${detailsComponent.owner}/${detailsComponent?.name.split("/").pop()}`;
|
|
1287
|
+
window.open(url, "_blank");
|
|
1288
|
+
},
|
|
1289
|
+
children: [
|
|
1290
|
+
"View on",
|
|
1291
|
+
" ",
|
|
1292
|
+
detailsComponent?.source === "jlcpcb" ? "JLCPCB" : "tscircuit.com",
|
|
1293
|
+
" ",
|
|
1294
|
+
/* @__PURE__ */ jsx7(ExternalLink, { className: "rf-h-3 rf-w-3" })
|
|
1295
|
+
]
|
|
1296
|
+
}
|
|
1297
|
+
),
|
|
1298
|
+
/* @__PURE__ */ jsx7(
|
|
1299
|
+
Button,
|
|
1300
|
+
{
|
|
1301
|
+
onClick: () => {
|
|
1302
|
+
setDetailsOpen(false);
|
|
1303
|
+
if (detailsComponent) {
|
|
1304
|
+
onImport(detailsComponent);
|
|
1305
|
+
onClose();
|
|
1306
|
+
}
|
|
1307
|
+
},
|
|
1308
|
+
children: "Import Component"
|
|
1309
|
+
}
|
|
1310
|
+
)
|
|
1311
|
+
] })
|
|
1312
|
+
] }) })
|
|
1313
|
+
] });
|
|
1314
|
+
};
|
|
1315
|
+
|
|
987
1316
|
// lib/components/RunFrameForCli/LeftHeader.tsx
|
|
988
|
-
import { jsx as
|
|
1317
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
989
1318
|
var availableExports = [
|
|
990
1319
|
{ extension: "json", name: "JSON" },
|
|
991
1320
|
{ extension: "svg", name: "SVG" },
|
|
@@ -999,23 +1328,23 @@ var availableExports = [
|
|
|
999
1328
|
];
|
|
1000
1329
|
var RunframeCliLeftHeader = (props) => {
|
|
1001
1330
|
const lastRunEvalVersion = useRunnerStore((s) => s.lastRunEvalVersion);
|
|
1002
|
-
const [snippetName, setSnippetName] =
|
|
1003
|
-
const [hasUnsavedChanges, setHasUnsavedChanges] =
|
|
1004
|
-
const [hasNeverBeenSaved, setHasNeverBeenSaved] =
|
|
1005
|
-
const [isSaving, setIsSaving] =
|
|
1006
|
-
const [requestToSaveSentAt, setRequestToSaveSentAt] =
|
|
1331
|
+
const [snippetName, setSnippetName] = useState7(null);
|
|
1332
|
+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState7(false);
|
|
1333
|
+
const [hasNeverBeenSaved, setHasNeverBeenSaved] = useState7(true);
|
|
1334
|
+
const [isSaving, setIsSaving] = useState7(false);
|
|
1335
|
+
const [requestToSaveSentAt, setRequestToSaveSentAt] = useState7(
|
|
1007
1336
|
null
|
|
1008
1337
|
);
|
|
1009
|
-
const [availableSnippets, setAvailableSnippets] =
|
|
1338
|
+
const [availableSnippets, setAvailableSnippets] = useState7(
|
|
1010
1339
|
null
|
|
1011
1340
|
);
|
|
1012
|
-
const [isSelectSnippetDialogOpen, setIsSelectSnippetDialogOpen] =
|
|
1013
|
-
const [notificationMessage, setNotificationMessage] =
|
|
1341
|
+
const [isSelectSnippetDialogOpen, setIsSelectSnippetDialogOpen] = useState7(false);
|
|
1342
|
+
const [notificationMessage, setNotificationMessage] = useState7(
|
|
1014
1343
|
null
|
|
1015
1344
|
);
|
|
1016
|
-
const [errorMessage, setErrorMessage] =
|
|
1017
|
-
const [isError, setIsError] =
|
|
1018
|
-
const [isExporting, setisExporting] =
|
|
1345
|
+
const [errorMessage, setErrorMessage] = useState7(null);
|
|
1346
|
+
const [isError, setIsError] = useState7(false);
|
|
1347
|
+
const [isExporting, setisExporting] = useState7(false);
|
|
1019
1348
|
const pushEvent = useRunFrameStore((state) => state.pushEvent);
|
|
1020
1349
|
const recentEvents = useRunFrameStore((state) => state.recentEvents);
|
|
1021
1350
|
const firstRenderTime = useMemo4(() => Date.now(), []);
|
|
@@ -1043,7 +1372,7 @@ var RunframeCliLeftHeader = (props) => {
|
|
|
1043
1372
|
setisExporting(false);
|
|
1044
1373
|
}
|
|
1045
1374
|
});
|
|
1046
|
-
|
|
1375
|
+
useEffect7(() => {
|
|
1047
1376
|
if (!isSaving || requestToSaveSentAt === null) return;
|
|
1048
1377
|
const eventsSinceRequestToSave = recentEvents.filter(
|
|
1049
1378
|
(event) => new Date(event.created_at).valueOf() > requestToSaveSentAt
|
|
@@ -1084,144 +1413,180 @@ var RunframeCliLeftHeader = (props) => {
|
|
|
1084
1413
|
snippet_name: snippetName
|
|
1085
1414
|
});
|
|
1086
1415
|
};
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
className: "rf-text-xs",
|
|
1094
|
-
onSelect: triggerSaveSnippet,
|
|
1095
|
-
disabled: isSaving,
|
|
1096
|
-
children: isSaving ? "Saving..." : "Push"
|
|
1097
|
-
}
|
|
1098
|
-
),
|
|
1099
|
-
/* @__PURE__ */ jsxs5(DropdownMenuSub, { children: [
|
|
1100
|
-
/* @__PURE__ */ jsx6(DropdownMenuSubTrigger, { className: "rf-text-xs", disabled: isExporting, children: isExporting ? "Exporting..." : "Export" }),
|
|
1101
|
-
/* @__PURE__ */ jsx6(DropdownMenuPortal, { children: /* @__PURE__ */ jsx6(DropdownMenuSubContent, { children: availableExports.map((exp, i) => /* @__PURE__ */ jsx6(
|
|
1416
|
+
const [isImportDialogOpen, setIsImportDialogOpen] = useState7(false);
|
|
1417
|
+
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1418
|
+
/* @__PURE__ */ jsxs6(DropdownMenu, { children: [
|
|
1419
|
+
/* @__PURE__ */ jsx8(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx8("div", { className: "rf-whitespace-nowrap rf-text-xs font-medium rf-p-2 rf-mx-1 rf-cursor-pointer rf-relative", children: "File" }) }),
|
|
1420
|
+
/* @__PURE__ */ jsxs6(DropdownMenuContent, { children: [
|
|
1421
|
+
/* @__PURE__ */ jsx8(
|
|
1102
1422
|
DropdownMenuItem,
|
|
1103
1423
|
{
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1424
|
+
className: "rf-text-xs",
|
|
1425
|
+
onSelect: triggerSaveSnippet,
|
|
1426
|
+
disabled: isSaving,
|
|
1427
|
+
children: isSaving ? "Saving..." : "Push"
|
|
1428
|
+
}
|
|
1429
|
+
),
|
|
1430
|
+
/* @__PURE__ */ jsx8(
|
|
1431
|
+
DropdownMenuItem,
|
|
1432
|
+
{
|
|
1433
|
+
className: "rf-text-xs",
|
|
1434
|
+
onSelect: () => setIsImportDialogOpen(true),
|
|
1435
|
+
disabled: isSaving,
|
|
1436
|
+
children: "Import"
|
|
1437
|
+
}
|
|
1438
|
+
),
|
|
1439
|
+
/* @__PURE__ */ jsxs6(DropdownMenuSub, { children: [
|
|
1440
|
+
/* @__PURE__ */ jsx8(
|
|
1441
|
+
DropdownMenuSubTrigger,
|
|
1442
|
+
{
|
|
1443
|
+
className: "rf-text-xs",
|
|
1444
|
+
disabled: isExporting,
|
|
1445
|
+
children: isExporting ? "Exporting..." : "Export"
|
|
1446
|
+
}
|
|
1447
|
+
),
|
|
1448
|
+
/* @__PURE__ */ jsx8(DropdownMenuPortal, { children: /* @__PURE__ */ jsx8(DropdownMenuSubContent, { children: availableExports.map((exp, i) => /* @__PURE__ */ jsx8(
|
|
1449
|
+
DropdownMenuItem,
|
|
1450
|
+
{
|
|
1451
|
+
onSelect: () => {
|
|
1452
|
+
if (!isExporting) {
|
|
1453
|
+
pushEvent({
|
|
1454
|
+
event_type: "REQUEST_EXPORT",
|
|
1455
|
+
exportType: exp.extension
|
|
1456
|
+
});
|
|
1457
|
+
setNotificationMessage(
|
|
1458
|
+
`Export requested for ${exp.name}`
|
|
1459
|
+
);
|
|
1460
|
+
setIsError(false);
|
|
1461
|
+
}
|
|
1462
|
+
},
|
|
1463
|
+
disabled: isExporting,
|
|
1464
|
+
children: /* @__PURE__ */ jsx8("span", { className: "rf-text-xs", children: exp.name })
|
|
1113
1465
|
},
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
onCheckedChange: (checked) => {
|
|
1130
|
-
props.onChangeShouldLoadLatestEval(checked === true);
|
|
1466
|
+
i
|
|
1467
|
+
)) }) })
|
|
1468
|
+
] }),
|
|
1469
|
+
/* @__PURE__ */ jsxs6(DropdownMenuSub, { children: [
|
|
1470
|
+
/* @__PURE__ */ jsx8(DropdownMenuSubTrigger, { className: "rf-text-xs", children: "Advanced" }),
|
|
1471
|
+
/* @__PURE__ */ jsx8(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs6(DropdownMenuSubContent, { children: [
|
|
1472
|
+
/* @__PURE__ */ jsx8(DropdownMenuItem, { className: "rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsxs6("div", { className: "rf-flex rf-items-center rf-gap-2", children: [
|
|
1473
|
+
/* @__PURE__ */ jsx8(
|
|
1474
|
+
Checkbox,
|
|
1475
|
+
{
|
|
1476
|
+
id: "load-latest-eval",
|
|
1477
|
+
checked: props.shouldLoadLatestEval,
|
|
1478
|
+
onCheckedChange: (checked) => {
|
|
1479
|
+
props.onChangeShouldLoadLatestEval(checked === true);
|
|
1480
|
+
}
|
|
1131
1481
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1482
|
+
),
|
|
1483
|
+
/* @__PURE__ */ jsx8(
|
|
1484
|
+
"label",
|
|
1485
|
+
{
|
|
1486
|
+
htmlFor: "load-latest-eval",
|
|
1487
|
+
className: "rf-text-xs rf-cursor-pointer",
|
|
1488
|
+
children: "Force Latest @tscircuit/eval"
|
|
1489
|
+
}
|
|
1490
|
+
)
|
|
1491
|
+
] }) }),
|
|
1492
|
+
lastRunEvalVersion && /* @__PURE__ */ jsx8(DropdownMenuItem, { className: "rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsx8("div", { className: "rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsxs6("span", { className: "rf-text-xs", children: [
|
|
1493
|
+
"@tscircuit/eval@",
|
|
1494
|
+
lastRunEvalVersion
|
|
1495
|
+
] }) }) }),
|
|
1496
|
+
/* @__PURE__ */ jsx8(
|
|
1497
|
+
DropdownMenuItem,
|
|
1136
1498
|
{
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1499
|
+
className: "rf-flex rf-items-center rf-gap-2",
|
|
1500
|
+
onClick: () => {
|
|
1501
|
+
window.open("/api/admin", "_blank");
|
|
1502
|
+
},
|
|
1503
|
+
children: /* @__PURE__ */ jsx8("div", { className: "rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsx8("span", { className: "rf-text-xs", children: "CLI Admin Panel" }) })
|
|
1140
1504
|
}
|
|
1141
1505
|
)
|
|
1142
|
-
] }) })
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
"
|
|
1506
|
+
] }) })
|
|
1507
|
+
] })
|
|
1508
|
+
] }),
|
|
1509
|
+
/* @__PURE__ */ jsx8("div", { className: "!rf-h-full rf-w-fit rf-grid rf-place-items-center rf-my-auto", children: /* @__PURE__ */ jsxs6("div", { className: "rf-flex rf-gap-4", children: [
|
|
1510
|
+
hasUnsavedChanges || hasNeverBeenSaved && /* @__PURE__ */ jsx8(
|
|
1511
|
+
"button",
|
|
1512
|
+
{
|
|
1513
|
+
type: "button",
|
|
1514
|
+
disabled: isSaving,
|
|
1515
|
+
onClick: triggerSaveSnippet,
|
|
1516
|
+
className: "transition ease-in-out hover:scale-105 pointer-cursor rf-text-xs rf-h-fit disabled:rf-bg-blue-600/60 rf-bg-blue-600/70 rf-text-white rf-p-0.5 rf-px-1.5 rf-rounded",
|
|
1517
|
+
children: isSaving ? "Syncing..." : "Not Synced"
|
|
1518
|
+
}
|
|
1519
|
+
),
|
|
1520
|
+
notificationMessage && /* @__PURE__ */ jsx8(
|
|
1521
|
+
"div",
|
|
1522
|
+
{
|
|
1523
|
+
className: `rf-text-xs rf-font-medium rf-mt-1 rf-flex rf-max-w-xl rf-text-blue-500 rf-break-words rf-text-center rf-h-full`,
|
|
1524
|
+
children: /* @__PURE__ */ jsxs6("div", { className: "rf-flex rf-items-center", children: [
|
|
1525
|
+
/* @__PURE__ */ jsx8(CheckCircle, { className: "rf-w-4 rf-h-4 rf-inline rf-mr-1" }),
|
|
1526
|
+
notificationMessage
|
|
1527
|
+
] })
|
|
1528
|
+
}
|
|
1529
|
+
)
|
|
1530
|
+
] }) }),
|
|
1531
|
+
/* @__PURE__ */ jsx8(AlertDialog, { open: isError, onOpenChange: setIsError, children: /* @__PURE__ */ jsxs6(AlertDialogContent, { children: [
|
|
1532
|
+
/* @__PURE__ */ jsxs6(AlertDialogHeader, { children: [
|
|
1533
|
+
/* @__PURE__ */ jsx8(AlertDialogTitle, { children: "Error Saving Snippet" }),
|
|
1534
|
+
/* @__PURE__ */ jsx8(AlertDialogDescription, { children: errorMessage })
|
|
1535
|
+
] }),
|
|
1536
|
+
/* @__PURE__ */ jsx8(AlertDialogFooter, { children: /* @__PURE__ */ jsx8(AlertDialogCancel, { onClick: () => setIsError(false), children: "Dismiss" }) })
|
|
1537
|
+
] }) }),
|
|
1538
|
+
/* @__PURE__ */ jsx8(
|
|
1539
|
+
SelectSnippetDialog,
|
|
1173
1540
|
{
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1541
|
+
snippetNames: availableSnippets ?? [],
|
|
1542
|
+
onSelect: async (name) => {
|
|
1543
|
+
setIsSaving(true);
|
|
1544
|
+
setRequestToSaveSentAt(Date.now());
|
|
1545
|
+
setSnippetName(name);
|
|
1546
|
+
await pushEvent({
|
|
1547
|
+
event_type: "REQUEST_TO_SAVE_SNIPPET",
|
|
1548
|
+
snippet_name: name
|
|
1549
|
+
});
|
|
1550
|
+
setIsSelectSnippetDialogOpen(false);
|
|
1551
|
+
},
|
|
1552
|
+
onCancel: () => setIsSelectSnippetDialogOpen(false),
|
|
1553
|
+
isOpen: isSelectSnippetDialogOpen
|
|
1179
1554
|
}
|
|
1180
1555
|
)
|
|
1181
|
-
] })
|
|
1182
|
-
/* @__PURE__ */
|
|
1183
|
-
|
|
1184
|
-
/* @__PURE__ */ jsx6(AlertDialogTitle, { children: "Error Saving Snippet" }),
|
|
1185
|
-
/* @__PURE__ */ jsx6(AlertDialogDescription, { children: errorMessage })
|
|
1186
|
-
] }),
|
|
1187
|
-
/* @__PURE__ */ jsx6(AlertDialogFooter, { children: /* @__PURE__ */ jsx6(AlertDialogCancel, { onClick: () => setIsError(false), children: "Dismiss" }) })
|
|
1188
|
-
] }) }),
|
|
1189
|
-
/* @__PURE__ */ jsx6(
|
|
1190
|
-
SelectSnippetDialog,
|
|
1556
|
+
] }),
|
|
1557
|
+
/* @__PURE__ */ jsx8(
|
|
1558
|
+
ImportComponentDialog,
|
|
1191
1559
|
{
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1560
|
+
isOpen: isImportDialogOpen,
|
|
1561
|
+
onClose: () => setIsImportDialogOpen(false),
|
|
1562
|
+
onImport: async (component) => {
|
|
1563
|
+
console.log("Component imported:", component);
|
|
1564
|
+
setIsImportDialogOpen(false);
|
|
1197
1565
|
await pushEvent({
|
|
1198
|
-
event_type: "
|
|
1199
|
-
|
|
1566
|
+
event_type: "IMPORT_COMPONENT",
|
|
1567
|
+
component
|
|
1200
1568
|
});
|
|
1201
|
-
|
|
1202
|
-
},
|
|
1203
|
-
onCancel: () => setIsSelectSnippetDialogOpen(false),
|
|
1204
|
-
isOpen: isSelectSnippetDialogOpen
|
|
1569
|
+
}
|
|
1205
1570
|
}
|
|
1206
1571
|
)
|
|
1207
1572
|
] });
|
|
1208
1573
|
};
|
|
1209
1574
|
|
|
1210
1575
|
// lib/components/RunFrameForCli/RunFrameForCli.tsx
|
|
1211
|
-
import { jsx as
|
|
1576
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1212
1577
|
var RunFrameForCli = (props) => {
|
|
1213
1578
|
const [shouldLoadLatestEval, setLoadLatestEval] = useLocalStorageState(
|
|
1214
1579
|
"load-latest-eval",
|
|
1215
1580
|
true
|
|
1216
1581
|
);
|
|
1217
|
-
return /* @__PURE__ */
|
|
1582
|
+
return /* @__PURE__ */ jsx9(
|
|
1218
1583
|
RunFrameWithApi,
|
|
1219
1584
|
{
|
|
1220
1585
|
debug: props.debug,
|
|
1221
1586
|
forceLatestEvalVersion: shouldLoadLatestEval,
|
|
1222
1587
|
defaultToFullScreen: true,
|
|
1223
1588
|
showToggleFullScreen: false,
|
|
1224
|
-
leftHeaderContent: /* @__PURE__ */
|
|
1589
|
+
leftHeaderContent: /* @__PURE__ */ jsx9("div", { className: "rf-flex", children: /* @__PURE__ */ jsx9(
|
|
1225
1590
|
RunframeCliLeftHeader,
|
|
1226
1591
|
{
|
|
1227
1592
|
shouldLoadLatestEval,
|