1import { _ as q } from "./three-drei-CobgFk8Q.js"; 2import { b as r, k as e } from "./three-fiber-GW7QWJN8.js"; 3import { cm as $, e3 as o, bZ as z, e4 as T, e5 as P, bA as G, bh as I, e6 as K, bO as Q, e7 as U, e8 as ee, dZ as te, bm as se, e9 as ae, cl as re, bg as le, ea as ne, eb as de, by as oe, cE as ce, __tla as __tla_0 } from "./index-CO3RsAq4.js"; 4import { f as ie } from "./Gear.es-B_Mv-z5e.js"; 5import { p as xe } from "./Spinner.es-xrTtSKsN.js"; 6import { f as me } from "./Square.es-BsRRJlWh.js"; 7import "./three-tnxpQXqG.js"; 8let Ae, fe, ve, W; 9let __tla = Promise.all([ 10 (() => { 11 try { 12 return __tla_0; 13 } catch { 14 } 15 })() 16]).then(async () => { 17 const ue = /* @__PURE__ */ new Map([ 18 [ 19 "bold", 20 r.createElement(r.Fragment, null, r.createElement("path", { 21 d: "M208.49,152.49l-72,72a12,12,0,0,1-17,0l-72-72a12,12,0,0,1,17-17L116,187V40a12,12,0,0,1,24,0V187l51.51-51.52a12,12,0,0,1,17,17Z" 22 })) 23 ], 24 [ 25 "duotone", 26 r.createElement(r.Fragment, null, r.createElement("path", { 27 d: "M200,144l-72,72L56,144Z", 28 opacity: "0.2" 29 }), r.createElement("path", { 30 d: "M207.39,140.94A8,8,0,0,0,200,136H136V40a8,8,0,0,0-16,0v96H56a8,8,0,0,0-5.66,13.66l72,72a8,8,0,0,0,11.32,0l72-72A8,8,0,0,0,207.39,140.94ZM128,204.69,75.31,152H180.69Z" 31 })) 32 ], 33 [ 34 "fill", 35 r.createElement(r.Fragment, null, r.createElement("path", { 36 d: "M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72A8,8,0,0,1,56,136h64V40a8,8,0,0,1,16,0v96h64a8,8,0,0,1,5.66,13.66Z" 37 })) 38 ], 39 [ 40 "light", 41 r.createElement(r.Fragment, null, r.createElement("path", { 42 d: "M204.24,148.24l-72,72a6,6,0,0,1-8.48,0l-72-72a6,6,0,0,1,8.48-8.48L122,201.51V40a6,6,0,0,1,12,0V201.51l61.76-61.75a6,6,0,0,1,8.48,8.48Z" 43 })) 44 ], 45 [ 46 "regular", 47 r.createElement(r.Fragment, null, r.createElement("path", { 48 d: "M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72a8,8,0,0,1,11.32-11.32L120,196.69V40a8,8,0,0,1,16,0V196.69l58.34-58.35a8,8,0,0,1,11.32,11.32Z" 49 })) 50 ], 51 [ 52 "thin", 53 r.createElement(r.Fragment, null, r.createElement("path", { 54 d: "M202.83,146.83l-72,72a4,4,0,0,1-5.66,0l-72-72a4,4,0,0,1,5.66-5.66L124,206.34V40a4,4,0,0,1,8,0V206.34l65.17-65.17a4,4,0,0,1,5.66,5.66Z" 55 })) 56 ] 57 ]), Y = r.forwardRef((s, a) => r.createElement($, { 58 ref: a, 59 ...s, 60 weights: ue 61 })); 62 Y.displayName = "ArrowDownIcon"; 63 const V = Y, he = /* @__PURE__ */ new Map([ 64 [ 65 "bold", 66 r.createElement(r.Fragment, null, r.createElement("path", { 67 d: "M156,80H48a20,20,0,0,0-20,20V208a20,20,0,0,0,20,20H156a20,20,0,0,0,20-20V100A20,20,0,0,0,156,80Zm-4,124H52V104H152ZM132,40a12,12,0,0,1,12-12h16a12,12,0,0,1,0,24H144A12,12,0,0,1,132,40Zm96,8v8a12,12,0,0,1-24,0V52h-4a12,12,0,0,1,0-24h8A20,20,0,0,1,228,48Zm0,48v16a12,12,0,0,1-24,0V96a12,12,0,0,1,24,0Zm0,56v8a20,20,0,0,1-20,20h-8a12,12,0,0,1,0-24h4v-4a12,12,0,0,1,24,0ZM76,56V48A20,20,0,0,1,96,28h8a12,12,0,0,1,0,24h-4v4a12,12,0,0,1-24,0Z" 68 })) 69 ], 70 [ 71 "duotone", 72 r.createElement(r.Fragment, null, r.createElement("path", { 73 d: "M216,48V160a8,8,0,0,1-8,8H168V96a8,8,0,0,0-8-8H88V48a8,8,0,0,1,8-8H208A8,8,0,0,1,216,48Z", 74 opacity: "0.2" 75 }), r.createElement("path", { 76 d: "M160,80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H160a16,16,0,0,0,16-16V96A16,16,0,0,0,160,80Zm0,128H48V96H160ZM136,40a8,8,0,0,1,8-8h16a8,8,0,0,1,0,16H144A8,8,0,0,1,136,40Zm88,8v8a8,8,0,0,1-16,0V48h-8a8,8,0,0,1,0-16h8A16,16,0,0,1,224,48Zm0,48v16a8,8,0,0,1-16,0V96a8,8,0,0,1,16,0Zm0,56v8a16,16,0,0,1-16,16h-8a8,8,0,0,1,0-16h8v-8a8,8,0,0,1,16,0ZM80,56V48A16,16,0,0,1,96,32h8a8,8,0,0,1,0,16H96v8a8,8,0,0,1-16,0Z" 77 })) 78 ], 79 [ 80 "fill", 81 r.createElement(r.Fragment, null, r.createElement("path", { 82 d: "M72,112h72v72H72ZM224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48ZM96,72a8,8,0,0,0,16,0h16a8,8,0,0,0,0-16H112A16,16,0,0,0,96,72Zm64,40a16,16,0,0,0-16-16H72a16,16,0,0,0-16,16v72a16,16,0,0,0,16,16h72a16,16,0,0,0,16-16Zm40,16a8,8,0,0,0-16,0v16a8,8,0,0,0,0,16,16,16,0,0,0,16-16Zm0-56a16,16,0,0,0-16-16H168a8,8,0,0,0,0,16h16V88a8,8,0,0,0,16,0Z" 83 })) 84 ], 85 [ 86 "light", 87 r.createElement(r.Fragment, null, r.createElement("path", { 88 d: "M160,82H48A14,14,0,0,0,34,96V208a14,14,0,0,0,14,14H160a14,14,0,0,0,14-14V96A14,14,0,0,0,160,82Zm2,126a2,2,0,0,1-2,2H48a2,2,0,0,1-2-2V96a2,2,0,0,1,2-2H160a2,2,0,0,1,2,2ZM138,40a6,6,0,0,1,6-6h16a6,6,0,0,1,0,12H144A6,6,0,0,1,138,40Zm84,8v8a6,6,0,0,1-12,0V48a2,2,0,0,0-2-2h-8a6,6,0,0,1,0-12h8A14,14,0,0,1,222,48Zm0,48v16a6,6,0,0,1-12,0V96a6,6,0,0,1,12,0Zm0,56v8a14,14,0,0,1-14,14h-8a6,6,0,0,1,0-12h8a2,2,0,0,0,2-2v-8a6,6,0,0,1,12,0ZM82,56V48A14,14,0,0,1,96,34h8a6,6,0,0,1,0,12H96a2,2,0,0,0-2,2v8a6,6,0,0,1-12,0Z" 89 })) 90 ], 91 [ 92 "regular", 93 r.createElement(r.Fragment, null, r.createElement("path", { 94 d: "M160,80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H160a16,
9416,0,0,0,16-16V96A16,16,0,0,0,160,80Zm0,128H48V96H160ZM136,40a8,8,0,0,1,8-8h16a8,8,0,0,1,0,16H144A8,8,0,0,1,136,40Zm88,8v8a8,8,0,0,1-16,0V48h-8a8,8,0,0,1,0-16h8A16,16,0,0,1,224,48Zm0,48v16a8,8,0,0,1-16,0V96a8,8,0,0,1,16,0Zm0,56v8a16,16,0,0,1-16,16h-8a8,8,0,0,1,0-16h8v-8a8,8,0,0,1,16,0ZM80,56V48A16,16,0,0,1,96,32h8a8,8,0,0,1,0,16H96v8a8,8,0,0,1-16,0Z" 95 })) 96 ], 97 [ 98 "thin", 99 r.createElement(r.Fragment, null, r.createElement("path", { 100 d: "M160,84H48A12,12,0,0,0,36,96V208a12,12,0,0,0,12,12H160a12,12,0,0,0,12-12V96A12,12,0,0,0,160,84Zm4,124a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V96a4,4,0,0,1,4-4H160a4,4,0,0,1,4,4ZM140,40a4,4,0,0,1,4-4h16a4,4,0,0,1,0,8H144A4,4,0,0,1,140,40Zm80,8v8a4,4,0,0,1-8,0V48a4,4,0,0,0-4-4h-8a4,4,0,0,1,0-8h8A12,12,0,0,1,220,48Zm0,48v16a4,4,0,0,1-8,0V96a4,4,0,0,1,8,0Zm0,56v8a12,12,0,0,1-12,12h-8a4,4,0,0,1,0-8h8a4,4,0,0,0,4-4v-8a4,4,0,0,1,8,0ZM84,56V48A12,12,0,0,1,96,36h8a4,4,0,0,1,0,8H96a4,4,0,0,0-4,4v8a4,4,0,0,1-8,0Z" 101 })) 102 ] 103 ]), X = r.forwardRef((s, a) => r.createElement($, { 104 ref: a, 105 ...s, 106 weights: he 107 })); 108 X.displayName = "SelectionBackgroundIcon"; 109 const L = X, R = { 110 flat_endmill: "Flat Endmill", 111 ball_endmill: "Ball Endmill", 112 bull_endmill: "Bull Endmill", 113 vbit: "V-Bit", 114 drill: "Drill", 115 face_mill: "Face Mill" 116 }, pe = { 117 flat_endmill: T, 118 ball_endmill: P, 119 bull_endmill: T, 120 vbit: V, 121 drill: V, 122 face_mill: T 123 }; 124 W = function({ compact: s = false }) { 125 const a = o((n) => n.tools), m = o((n) => n.selectedToolId), t = o((n) => n.selectTool), y = o((n) => n.addTool), u = o((n) => n.removeTool), [p, f] = r.useState(false), [x, b] = r.useState({ 126 name: "", 127 type: "flat_endmill", 128 diameter: 6, 129 fluteLength: 20, 130 flutes: 2, 131 defaultRpm: 12e3, 132 defaultFeed: 1e3, 133 defaultPlunge: 300 134 }), w = () => { 135 x.name && x.type && x.diameter && (y(x), b({ 136 name: "", 137 type: "flat_endmill", 138 diameter: 6, 139 fluteLength: 20, 140 flutes: 2, 141 defaultRpm: 12e3, 142 defaultFeed: 1e3, 143 defaultPlunge: 300 144 }), f(false)); 145 }; 146 return s ? e.jsxs("div", { 147 className: "space-y-1", 148 children: [ 149 e.jsx("label", { 150 className: "text-xs text-text-muted", 151 children: "Tool" 152 }), 153 e.jsxs("select", { 154 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 155 value: m ?? "", 156 onChange: (n) => t(n.target.value || null), 157 children: [ 158 e.jsx("option", { 159 value: "", 160 children: "Select tool..." 161 }), 162 a.map((n) => e.jsxs("option", { 163 value: n.id, 164 children: [ 165 n.name, 166 " (", 167 n.diameter, 168 "mm)" 169 ] 170 }, n.id)) 171 ] 172 }) 173 ] 174 }) : e.jsxs("div", { 175 className: "space-y-2", 176 children: [ 177 e.jsxs("div", { 178 className: "flex items-center justify-between", 179 children: [ 180 e.jsx("h3", { 181 className: "text-sm font-medium", 182 children: "Tool Library" 183 }), 184 e.jsx("button", { 185 className: "p-1 hover:bg-hover rounded text-text-muted hover:text-text", 186 onClick: () => f(!p), 187 children: e.jsx(z, { 188 size: 14 189 }) 190 }) 191 ] 192 }), 193 p && e.jsxs("div", { 194 className: "bg-surface-secondary p-2 rounded space-y-2 text-xs", 195 children: [ 196 e.jsx("input", { 197 type: "text", 198 placeholder: "Tool name", 199 className: "w-full bg-surface border border-border rounded px-2 py-1", 200 value: x.name, 201 onChange: (n) => b({ 202 ...x, 203 name: n.target.value 204 }) 205 }), 206 e.jsxs("div", { 207 className: "grid grid-cols-2 gap-2", 208 children: [ 209 e.jsx("select", { 210 className: "bg-surface border border-border rounded px-2 py-1",
211 value: x.type, 212 onChange: (n) => b({ 213 ...x, 214 type: n.target.value 215 }), 216 children: Object.entries(R).map(([n, j]) => e.jsx("option", { 217 value: n, 218 children: j 219 }, n)) 220 }), 221 e.jsx("input", { 222 type: "number", 223 placeholder: "Diameter", 224 className: "bg-surface border border-border rounded px-2 py-1", 225 value: x.diameter, 226 onChange: (n) => b({ 227 ...x, 228 diameter: parseFloat(n.target.value) 229 }) 230 }) 231 ] 232 }), 233 e.jsxs("div", { 234 className: "flex justify-end gap-2", 235 children: [ 236 e.jsx("button", { 237 className: "px-2 py-1 text-text-muted hover:text-text", 238 onClick: () => f(false), 239 children: "Cancel" 240 }), 241 e.jsx("button", { 242 className: "px-2 py-1 bg-brand text-white rounded hover:bg-brand/90", 243 onClick: w, 244 children: "Add" 245 }) 246 ] 247 }) 248 ] 249 }), 250 e.jsx("div", { 251 className: "space-y-1 max-h-40 overflow-y-auto", 252 children: a.map((n) => { 253 const j = pe[n.type]; 254 return e.jsxs("div", { 255 className: I("flex items-center gap-2 p-2 rounded cursor-pointer text-sm", "hover:bg-hover transition-colors", m === n.id && "bg-brand/20 border border-brand/40"), 256 onClick: () => t(n.id), 257 children: [ 258 e.jsx(j, { 259 size: 14, 260 className: "text-text-muted" 261 }), 262 e.jsxs("div", { 263 className: "flex-1 min-w-0", 264 children: [ 265 e.jsx("div", { 266 className: "truncate", 267 children: n.name 268 }), 269 e.jsxs("div", { 270 className: "text-xs text-text-muted", 271 children: [ 272 n.diameter, 273 "mm ", 274 R[n.type] 275 ] 276 }) 277 ] 278 }), 279 e.jsx("button", { 280 className: "p-1 hover:bg-error/20 rounded text-text-muted hover:text-error", 281 onClick: (N) => { 282 N.stopPropagation(), u(n.id); 283 }, 284 children: e.jsx(G, { 285 size: 12 286 }) 287 }) 288 ] 289 }, n.id); 290 }) 291 }) 292 ] 293 }); 294 }; 295 const O = { 296 face: "Face", 297 pocket: "Pocket", 298 pocket_circle: "Circular Pocket", 299 contour: "Contour", 300 roughing3d: "3D Roughing" 301 }, B = { 302 face: L, 303 pocket: me, 304 pocket_circle: P, 305 contour: K, 306 roughing3d: L 307 }; 308 function be({ onAdd: s, onCancel: a }) { 309 return e.jsxs("div", { 310 className: "bg-surface-secondary p-2 rounded space-y-2 text-xs", 311 children: [ 312 e.jsx("div", { 313 className: "text-text-muted mb-1", 314 children: "Select operation type:" 315 }), 316 e.jsx("div", { 317 className: "grid grid-cols-2 gap-1", 318 children: Object.entries(O).map(([m, t]) => { 319 const y = B[m]; 320 return e.jsxs("button", { 321 className: "flex items-center gap-2 p-2 hover:bg-hover rounded text-left", 322 onClick: () => s(m), 323 children: [ 324 e.jsx(y, { 325 size: 14 326 }), 327 e.jsx("span", { 328 children: t 329 }) 330 ] 331 }, m); 332 }) 333 }), 334 e.jsx("div", { 335 className: "flex justify-end", 336 children: e.jsx("button", { 337 className: "px-2 py-1 text-text-muted hover:text-text", 338 onClick: a, 339 children: "Cancel" 340 }) 341 }) 342 ] 343 }); 344 } 345 function ge({ operation: s, onUpdate: a }) { 346 const m = () => { 347 switch (s.type) { 348 case "face": 349 return e.jsx(e.Fragment, { 350 children: e.jsxs("div", { 351 className: "grid grid-cols-2 gap-2", 352 children: [ 353 e.jsxs("div", { 354 children: [ 355 e.jsx("label", { 356 className: "text-xs text-text-muted", 357 children: "Min X" 358 }), 359 e.jsx("input", { 360 type: "number", 361 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 362 value: s.minX, 363 onChange: (t) => a({ 364 minX: parseFloat(t.target.value) 365 }) 366 }) 367 ] 368 }), 369 e.jsxs("div", { 370 children: [ 371 e.jsx("label", { 372 className: "text-xs text-text-muted", 373 children: "Min Y" 374 }), 375 e.jsx("input", { 376 type: "number", 377 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 378 value: s.minY, 379 onChange: (t) => a({ 380 minY: parseFloat(t.target.value) 381 }) 382 }) 383 ] 384 }), 385 e.jsxs("div", { 386 children: [ 387 e.jsx("label", { 388 className: "text-xs text-text-muted", 389 children: "Max X" 390 }), 391 e.jsx("input", { 392 type: "number", 393 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 394 value: s.maxX, 395 onChange: (t) => a({ 396 maxX: parseFloat(t.target.value) 397 }) 398 }) 399 ] 400 }), 401 e.jsxs("div", { 402 children: [ 403 e.jsx("label", { 404 className: "text-xs text-text-muted", 405 children: "Max Y" 406 }), 407 e.jsx("input", { 408 type: "number", 409 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 410 value: s.maxY, 411 onChange: (t) => a({ 412 maxY: parseFloat(t.target.value) 413 }) 414 }) 415 ] 416 }) 417 ] 418 }) 419 }); 420 case "pocket": 421 return e.jsxs(e.Fragment, { 422 children: [ 423 e.jsxs("div", { 424 className: "grid grid-cols-2 gap-2", 425 children: [ 426 e.jsxs("div", { 427 children: [ 428 e.jsx("label", { 429 className: "text-xs text-text-muted", 430 children: "X" 431 }), 432 e.jsx("input", { 433 type: "number", 434 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 435 value: s.x, 436 onChange: (t) => a({ 437 x: parseFloat(t.target.value) 438 }) 439 }) 440 ] 441 }), 442 e.jsxs("div", { 443 children: [ 444 e.jsx("label", { 445 className: "text-xs text-text-muted", 446 children: "Y" 447 }), 448 e.jsx("input", { 449 type: "number", 450 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 451 value: s.y, 452 onChange: (t) => a({ 453 y: parseFloat(t.target.value) 454 }) 455 }) 456 ] 457 }), 458 e.jsxs("div", { 459 children: [ 460 e.jsx("label", { 461 className: "text-xs text-text-muted", 462 children: "Width" 463 }), 464 e.jsx("input", { 465 type: "number", 466 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 467 value: s.width, 468 onChange: (t) => a({ 469 width: parseFloat(t.target.value) 470 }) 471 }) 472 ] 473 }), 474 e.jsxs("div", { 475 children: [ 476 e.jsx("label", { 477 className: "text-xs text-text-muted", 478 children: "Height" 479 }), 480 e.jsx("input", { 481 type: "number", 482 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 483 value: s.height, 484 onChange: (t) => a({ 485 height: parseFloat(t.target.value) 486 }) 487 }) 488 ] 489 }) 490 ] 491 }), 492 e.jsxs("div", { 493 children: [ 494 e.jsx("label", { 495 className: "text-xs text-text-muted", 496 children: "Stock to Leave" 497 }), 498 e.jsx("input", { 499 type: "number", 500 step: "0.1", 501 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 502 value: s.stockToLeave, 503 onChange: (t) => a({ 504 stockToLeave: parseFloat(t.target.value) 505 }) 506 }) 507 ] 508 }) 509 ] 510 }); 511 case "pocket_circle": 512 return e.jsxs(e.Fragment, { 513 children: [ 514 e.jsxs("div", { 515 className: "grid grid-cols-2 gap-2", 516 children: [ 517 e.jsxs("div", { 518 children: [ 519 e.jsx("label", { 520 className: "text-xs text-text-muted", 521 children: "Center X" 522 }), 523 e.jsx("input", { 524 type: "number", 525 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 526 value: s.centerX, 527 onChange: (t) => a({ 528 centerX: parseFloat(t.target.value) 529 }) 530 }) 531 ] 532 }), 533 e.jsxs("div", { 534 children: [ 535 e.jsx("label", { 536 className: "text-xs text-text-muted", 537 children: "Center Y" 538 }), 539 e.jsx("input", { 540 type: "number", 541 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 542 value: s.centerY, 543 onChange: (t) => a({ 544 centerY: parseFloat(t.target.value) 545 }) 546 }) 547 ] 548 }) 549 ] 550 }), 551 e.jsxs("div", { 552 children: [ 553 e.jsx("label", { 554 className: "text-xs text-text-muted", 555 children: "Radius" 556 }), 557 e.jsx("input", { 558 type: "number", 559 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 560 value: s.radius, 561 onChange: (t) => a({ 562 radius: parseFloat(t.target.value) 563 }) 564 }) 565 ] 566 }) 567 ] 568 }); 569 case "contour": 570 return e.jsxs(e.Fragment, { 571 children: [ 572 e.jsxs("div", { 573 className: "grid grid-cols-2 gap-2", 574 children: [ 575 e.jsxs("div", { 576 children: [ 577 e.jsx("label", { 578 className: "text-xs text-text-muted", 579 children: "X" 580 }), 581 e.jsx("input", { 582 type: "number", 583 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 584 value: s.x, 585 onChange: (t) => a({ 586 x: parseFloat(t.target.value) 587 }) 588 }) 589 ] 590 }), 591 e.jsxs("div", { 592 children: [ 593 e.jsx("label", { 594 className: "text-xs text-text-muted", 595 children: "Y" 596 }), 597 e.jsx("input", { 598 type: "number", 599 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 600 value: s.y, 601 onChange: (t) => a({ 602 y: parseFloat(t.target.value) 603 }) 604 }) 605 ] 606 }), 607 e.jsxs("div", { 608 children: [ 609 e.jsx("label", { 610 className: "text-xs text-text-muted", 611 children: "Width" 612 }), 613 e.jsx("input", { 614 type: "number", 615 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 616 value: s.width, 617 onChange: (t) => a({ 618 width: parseFloat(t.target.value) 619 }) 620 }) 621 ] 622 }), 623 e.jsxs("div", { 624 children: [ 625 e.jsx("label", { 626 className: "text-xs text-text-muted", 627 children: "Height" 628 }), 629 e.jsx("input", { 630 type: "number", 631 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 632 value: s.height, 633 onChange: (t) => a({ 634 height: parseFloat(t.target.value) 635 }) 636 }) 637 ] 638 }) 639 ] 640 }), 641 e.jsxs("div", { 642 children: [ 643 e.jsx("label", { 644 className: "text-xs text-text-muted", 645 children: "Offset" 646 }), 647 e.jsx("input", { 648 type: "number", 649 step: "0.1", 650 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 651 value: s.offset, 652 onChange: (t) => a({ 653 offset: parseFloat(t.target.value) 654 }) 655 }) 656 ] 657 }), 658 e.jsxs("div", { 659 className: "grid grid-cols-3 gap-2", 660 children: [ 661 e.jsxs("div", { 662
662 children: [ 663 e.jsx("label", { 664 className: "text-xs text-text-muted", 665 children: "Tab Count" 666 }), 667 e.jsx("input", { 668 type: "number", 669 min: "0", 670 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 671 value: s.tabCount, 672 onChange: (t) => a({ 673 tabCount: parseInt(t.target.value) 674 }) 675 }) 676 ] 677 }), 678 e.jsxs("div", { 679 children: [ 680 e.jsx("label", { 681 className: "text-xs text-text-muted", 682 children: "Tab Width" 683 }), 684 e.jsx("input", { 685 type: "number", 686 step: "0.5", 687 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 688 value: s.tabWidth, 689 onChange: (t) => a({ 690 tabWidth: parseFloat(t.target.value) 691 }) 692 }) 693 ] 694 }), 695 e.jsxs("div", { 696 children: [ 697 e.jsx("label", { 698 className: "text-xs text-text-muted", 699 children: "Tab Height" 700 }), 701 e.jsx("input", { 702 type: "number", 703 step: "0.5", 704 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 705 value: s.tabHeight, 706 onChange: (t) => a({ 707 tabHeight: parseFloat(t.target.value) 708 }) 709 }) 710 ] 711 }) 712 ] 713 }) 714 ] 715 }); 716 case "roughing3d": 717 return e.jsxs(e.Fragment, { 718 children: [ 719 e.jsxs("div", { 720 className: "grid grid-cols-2 gap-2", 721 children: [ 722 e.jsxs("div", { 723 children: [ 724 e.jsx("label", { 725 className: "text-xs text-text-muted", 726 children: "Top Z" 727 }), 728 e.jsx("input", { 729 type: "number", 730 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 731 value: s.topZ, 732 onChange: (t) => a({ 733 topZ: parseFloat(t.target.value) 734 }) 735 }) 736 ] 737 }), 738 e.jsxs("div", { 739 children: [ 740 e.jsx("label", { 741 className: "text-xs text-text-muted", 742 children: "Target Z" 743 }), 744 e.jsx("input", { 745 type: "number", 746 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 747 value: s.targetZ, 748 onChange: (t) => a({ 749 targetZ: parseFloat(t.target.value) 750 }) 751 }) 752 ] 753 }) 754 ] 755 }), 756 e.jsxs("div", { 757 className: "grid grid-cols-2 gap-2", 758 children: [ 759 e.jsxs("div", { 760 children: [ 761 e.jsx("label", { 762 className: "text-xs text-text-muted", 763 children: "Stock Margin" 764 }), 765 e.jsx("input", { 766 type: "number", 767 step: "0.1", 768 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 769 value: s.stockMargin, 770 onChange: (t) => a({ 771 stockMargin: parseFloat(t.target.value) 772 }) 773 }) 774 ] 775 }), 776 e.jsxs("div", { 777 children: [ 778 e.jsx("label", { 779 className: "text-xs text-text-muted", 780 children: "Direction (\xB0)" 781 }), 782 e.jsx("input", { 783 type: "number", 784 step: "45", 785 className: "w-full bg-surface border border-border rounded px-2 py-1 text-sm", 786 value: s.direction, 787 onChange: (t) => a({ 788 direction: parseFloat(t.target.value) 789 }) 790 }) 791 ] 792 }) 793 ] 794 }), 795 e.jsx("div", { 796 className: "text-xs text-text-muted mt-2",
797 children: "Note: 3D roughing requires a part with tessellated mesh." 798 }) 799 ] 800 }); 801 } 802 }; 803 return e.jsxs("div", { 804 className: "space-y-2 p-2 bg-surface-secondary rounded text-sm", 805 children: [ 806 e.jsxs("div", { 807 children: [ 808 e.jsx("label", { 809 className: "text-xs text-text-muted", 810 children: "Name" 811 }), 812 e.jsx("input", { 813 type: "text", 814 className: "w-full bg-surface border border-border rounded px-2 py-1", 815 value: s.name, 816 onChange: (t) => a({ 817 name: t.target.value 818 }) 819 }) 820 ] 821 }), 822 e.jsxs("div", { 823 children: [ 824 e.jsx("label", { 825 className: "text-xs text-text-muted", 826 children: "Depth" 827 }), 828 e.jsx("input", { 829 type: "number", 830 step: "0.5", 831 className: "w-full bg-surface border border-border rounded px-2 py-1", 832 value: s.depth, 833 onChange: (t) => a({ 834 depth: parseFloat(t.target.value) 835 }) 836 }) 837 ] 838 }), 839 e.jsx(W, { 840 compact: true 841 }), 842 m() 843 ] 844 }); 845 } 846 ve = function() { 847 const s = o((l) => l.operations), a = o((l) => l.selectedOperationId), m = o((l) => l.selectedToolId), t = o((l) => l.tools), y = o((l) => l.selectTool), u = o((l) => l.selectOperation), p = o((l) => l.addOperation), f = o((l) => l.updateOperation), x = o((l) => l.removeOperation), b = o((l) => l.moveOperation), [w, n] = r.useState(false), j = (l) => { 848 const g = O[l], C = s.filter((H) => H.type === l).length + 1; 849 let i = m; 850 !i && t.length > 0 && (i = t[0].id, y(i)); 851 const Z = { 852 name: `${g} ${C}`, 853 type: l, 854 toolId: i ?? "", 855 depth: 5, 856 enabled: true 857 }; 858 switch (l) { 859 case "face": 860 p({ 861 ...Z, 862 type: "face", 863 minX: 0, 864 minY: 0, 865 maxX: 100, 866 maxY: 50 867 }); 868 break; 869 case "pocket": 870 p({ 871 ...Z, 872 type: "pocket", 873 x: 10, 874 y: 10, 875 width: 30, 876 height: 20, 877 stockToLeave: 0 878 }); 879 break; 880 case "pocket_circle": 881 p({ 882 ...Z, 883 type: "pocket_circle", 884 centerX: 25, 885 centerY: 25, 886 radius: 15 887 }); 888 break; 889 case "contour": 890 p({ 891 ...Z, 892 type: "contour", 893 x: 0, 894 y: 0, 895 width: 50, 896 height: 40, 897 offset: 0, 898 tabCount: 4, 899 tabWidth: 5, 900 tabHeight: 2 901 }); 902 break; 903 case "roughing3d": 904 p({ 905 ...Z, 906 type: "roughing3d", 907 targetZ: -10, 908 topZ: 0, 909 stockMargin: 0.5, 910 direction: 0 911 }); 912 break; 913 } 914 n(false); 915 }, N = s.find((l) => l.id === a); 916 return e.jsxs("div", { 917 className: "space-y-2", 918 children: [ 919 e.jsxs("div", { 920 className: "flex items-center justify-between", 921 children: [ 922 e.jsx("h3", { 923 className: "text-sm font-medium", 924 children: "Operations" 925 }), 926 e.jsx("button", { 927 className: "p-1 hover:bg-hover rounded text-text-muted hover:text-text", 928 onClick: () => n(!w), 929 children: e.jsx(z, { 930 size: 14 931 }) 932 }) 933 ] 934 }), 935 w && e.jsx(be, { 936 onAdd: j, 937 onCancel: () => n(false) 938 }), 939 s.length === 0 && !w && e.jsx("div", { 940 className: "text-center text-text-muted text-sm py-4", 941 children: "No operations yet. Click + to add one." 942 }), 943 e.jsx("div", { 944 className: "space-y-1", 945 children: s.map((l, g) => { 946 const C = B[l.type]; 947 return e.jsxs("div", { 948 className: I("flex items-center gap-2 p-2 rounded cursor-pointer text-sm", "hover:bg-hover transition-colors", a === l.id && "bg-brand/20 border border-brand/40"), 949 onClick: () => u(l.id), 950 children: [ 951 e.jsx("button", { 952 className: "p-1 hover:bg-hover rounded", 953 onClick: (i) => { 954 i.stopPropagation(), f(l.id, { 955 enabled: !l.enabled 956 }); 957 }, 958 children: l.enabled ? e.jsx(Q, { 959 size: 14, 960 className: "text-text-muted" 961 }) : e.jsx(U, { 962 size: 14, 963 className: "text-text-muted" 964 }) 965 }), 966 e.jsx(C, { 967 size: 14, 968 className: "text-text-muted" 969 }), 970 e.jsxs("div", { 971 className: "flex-1 min-w-0", 972 children: [ 973 e.jsx("div", { 974 className: "truncate", 975 children: l.name 976 }), 977 e.jsxs("div", { 978 className: "text-xs text-text-muted", 979 children: [ 980 O[l.type], 981 ", depth: ", 982 l.depth, 983 "mm" 984 ] 985 }) 986 ] 987 }), 988 e.jsxs("div", { 989 className: "flex items-center gap-1", 990 children: [ 991 e.jsx("button", { 992 className: "p-1 hover:bg-hover rounded text-text-muted", 993 onClick: (i) => { 994 i.stopPropagation(), b(l.id, "up"); 995 }, 996 disabled: g === 0, 997 children: e.jsx(ee, { 998 size: 12 999 }) 1000 }), 1001 e.jsx("button", { 1002 className: "p-1 hover:bg-hover rounded text-text-muted", 1003 onClick: (i) => { 1004 i.stopPropagation(), b(l.id, "down"); 1005 }, 1006 disabled: g === s.length - 1, 1007 children: e.jsx(V, { 1008 size: 12 1009 }) 1010 }), 1011 e.jsx("button", { 1012 className: "p-1 hover:bg-error/20 rounded text-text-muted hover:text-error", 1013 onClick: (i) => { 1014 i.stopPropagation(), x(l.id); 1015 }, 1016 children: e.jsx(G, { 1017 size: 12 1018 }) 1019 }) 1020 ] 1021 }) 1022 ] 1023 }, l.id); 1024 }) 1025 }), 1026 N && e.jsx(ge, { 1027 operation: N, 1028 onUpdate: (l) => f(N.id, l) 1029 }) 1030 ] 1031 }); 1032 }; 1033 fe = function() { 1034 const s = o((t) => t.settings), a = o((t) => t.setSettings), m = o((t) => t.resetSettings); 1035 return e.jsxs("div", { 1036 className: "space-y-3", 1037 children: [ 1038 e.jsxs("div", { 1039 className: "flex items-center justify-between", 1040 children: [ 1041 e.jsx("h3", { 1042 className: "text-sm font-medium", 1043 children: "CAM Settings" 1044 }), 1045 e.jsx("button", { 1046 className: "p-1 hover:bg-hover rounded text-text-muted hover:text-text", 1047 onClick: m, 1048 title: "Reset to defaults", 1049 children: e.jsx(te, { 1050 size: 14 1051 }) 1052 }) 1053 ] 1054 }), 1055 e.jsxs("div", { 1056 className: "space-y-2 text-sm", 1057 children: [ 1058 e.jsxs("div", { 1059 className: "grid grid-cols-2 gap-2", 1060 children: [ 1061 e.jsxs("div", { 1062 children: [ 1063 e.jsx("label", { 1064 className: "text-xs text-text-muted", 1065 children: "Stepover (mm)" 1066 }), 1067 e.jsx("input", { 1068 type: "number", 1069 step: "0.5", 1070 className: "w-full bg-surface border border-border rounded px-2 py-1", 1071 value: s.stepover, 1072 onChange: (t) => a({ 1073 stepover: parseFloat(t.target.value) 1074 }) 1075 }) 1076 ] 1077 }), 1078 e.jsxs("div", { 1079 children: [ 1080 e.jsx("label", { 1081 className: "text-xs text-text-muted", 1082 children: "Stepdown (mm)" 1083 }), 1084 e.jsx("input", { 1085 type: "number", 1086 step: "0.5", 1087 className: "w-full bg-surface border border-border rounded px-2 py-1", 1088 value: s.stepdown, 1089 onChange: (t) => a({ 1090 stepdown: parseFloat(t.target.value) 1091 }) 1092 }) 1093 ] 1094 }) 1095 ] 1096 }), 1097 e.jsxs("div", { 1098 className: "grid grid-cols-2 gap-2", 1099 children: [ 1100 e.jsxs("div", { 1101 children: [ 1102 e.jsx("label", { 1103 className: "text-xs text-text-muted", 1104 children: "Feed Rate (mm/min)" 1105 }), 1106 e.jsx("input", { 1107 type: "number", 1108 step: "100", 1109 className: "w-full bg-surface border border-border rounded px-2 py-1", 1110 value: s.feedRate, 1111 onChange: (t) => a({ 1112 feedRate: parseFloat(t.target.value) 1113 }) 1114 }) 1115 ] 1116 }), 1117 e.jsxs("div", { 1118 children: [ 1119 e.jsx("label", { 1120 className: "text-xs text-text-muted", 1121 children: "Plunge Rate (mm/min)" 1122 }), 1123 e.jsx("input", { 1124 type: "number", 1125 step: "50", 1126 className: "w-full bg-surface border border-border rounded px-2 py-1", 1127 value: s.plungeRate, 1128 onChange: (t) => a({ 1129 plungeRate: parseFloat(t.target.value) 1130 }) 1131 }) 1132 ] 1133 }) 1134 ] 1135 }), 1136 e.jsxs("div", { 1137 children: [ 1138 e.jsx("label", { 1139 className: "text-xs text-text-muted", 1140 children: "Spindle RPM" 1141 }), 1142 e.jsx("input", { 1143 type: "number", 1144 step: "1000", 1145 className: "w-full bg-surface border border-border rounded px-2 py-1", 1146 value: s.spindleRpm, 1147 onChange: (t) => a({ 1148 spindleRpm: parseFloat(t.target.value) 1149 }) 1150 }) 1151 ] 1152 }), 1153 e.jsxs("div", { 1154 className: "grid grid-cols-2 gap-2", 1155 children: [ 1156 e.jsxs("div", { 1157 children: [ 1158 e.jsx("label", { 1159 className: "text-xs text-text-muted", 1160 children: "Safe Z (mm)" 1161 }), 1162 e.jsx("input", { 1163 type: "number", 1164 step: "1", 1165 className: "w-full bg-surface border border-border rounded px-2 py-1", 1166 value: s.safeZ, 1167 onChange: (t) => a({ 1168 safeZ: parseFloat(t.target.value) 1169 }) 1170 }) 1171 ] 1172 }), 1173 e.jsxs("div", { 1174 children: [ 1175 e.jsx("label", { 1176 className: "text-xs text-text-muted", 1177 children: "Retract Z (mm)" 1178 }), 1179 e.jsx("input", { 1180 type: "number", 1181 step: "1", 1182 className: "w-full bg-surface border border-border rounded px-2 py-1", 1183 value: s.retractZ, 1184 onChange: (t) => a({ 1185 retractZ: parseFloat(t.target.value) 1186 }) 1187 }) 1188 ] 1189 }) 1190 ] 1191 }) 1192 ] 1193 }) 1194 ] 1195 }); 1196 }; 1197 let E = null; 1198 async function je() { 1199 if (E) return E; 1200 try { 1201 const s = await q(() => import("./vcad_kernel_wasm-CHkrj4lE.js"), []); 1202 return typeof s.isCamAvailable != "function" ? null : (E = s, E); 1203 } catch { 1204 return null; 1205 } 1206 } 1207 Ae = function() { 1208 const [s, a] = r.useState("operations"), m = o((d) => d.closeCamPanel), t = o((d) => d.operations), y = o((d) => d.tools), u = o((d) => d.settings), p = o((d) => d.isGenerating), f = o((d) => d.setGenerating), x = o((d) => d.generateError), b = o((d) => d.setGenerateError), w = o((d) => d.setToolpathJson), n = o((d) => d.setGcodeOutput), j = o((d) => d.stats), N = o((d) => d.setStats), l = o((d) => d.gcodeOutput), g = se((d) => d.addToast), C = t.filter((d) => d.enabled), i = C.length > 0, Z = r.useCallback(async () => { 1209 if (!i) { 1210 g("No operations to generate", "error"); 1211 return; 1212 } 1213 f(true), b(null), N(null), n(null);
1214 try { 1215 const d = await je(); 1216 if (!d) throw new Error("CAM not available in this WASM build"); 1217 const v = d; 1218 if (!v.isCamAvailable()) throw new Error("CAM not available in this WASM build"); 1219 const h = new v.WasmCamSettings(); 1220 h.stepover = u.stepover, h.stepdown = u.stepdown, h.feed_rate = u.feedRate, h.plunge_rate = u.plungeRate, h.spindle_rpm = u.spindleRpm, h.safe_z = u.safeZ, h.retract_z = u.retractZ; 1221 let S = ""; 1222 const k = { 1223 cuttingLength: 0, 1224 estimatedTime: 0, 1225 segmentCount: 0 1226 }; 1227 for (const c of C) { 1228 const _ = y.find((J) => J.id === c.toolId); 1229 if (!_) throw new Error(`Tool not found for operation "${c.name}"`); 1230 const A = ae(_); 1231 let F; 1232 switch (c.type) { 1233 case "face": 1234 F = v.camGenerateFace(c.minX, c.minY, c.maxX, c.maxY, c.depth, A, h); 1235 break; 1236 case "pocket": 1237 F = v.camGeneratePocket(c.x, c.y, c.width, c.height, c.depth, A, h); 1238 break; 1239 case "pocket_circle": 1240 F = v.camGenerateCircularPocket(c.centerX, c.centerY, c.radius, c.depth, A, h); 1241 break; 1242 case "contour": 1243 F = v.camGenerateContour(c.x, c.y, c.width, c.height, c.depth, c.offset, c.tabCount, c.tabWidth, c.tabHeight, A, h); 1244 break; 1245 case "roughing3d": 1246 throw new Error(`3D roughing operation "${c.name}" requires a part mesh. Select a part first.`); 1247 } 1248 const M = v.camToolpathStats(F); 1249 k.cuttingLength += M.cutting_length || 0, k.estimatedTime += M.estimated_time || 0, k.segmentCount += M.segment_count || 0; 1250 const D = v.camExportGcode(F, c.name, A, h); 1251 S += ` 1252; === ${c.name} === 1253${D} 1254`, w(F); 1255 } 1256 N({ 1257 cuttingLength: k.cuttingLength, 1258 estimatedTime: k.estimatedTime, 1259 segmentCount: k.segmentCount, 1260 boundingBox: null 1261 }), n(S), g("Toolpath generated successfully", "success"); 1262 } catch (d) { 1263 console.error("CAM generation failed:", d); 1264 const v = d instanceof Error ? d.message : "Generation failed"; 1265 b(v), g(v, "error"); 1266 } finally { 1267 f(false); 1268 } 1269 }, [ 1270 i, 1271 C, 1272 y, 1273 u, 1274 g, 1275 f, 1276 b, 1277 N, 1278 n, 1279 w 1280 ]), H = r.useCallback(() => { 1281 if (!l) return; 1282 const d = new Blob([ 1283 l 1284 ], { 1285 type: "text/plain" 1286 }); 1287 re(d, "toolpath.nc"), g("Exported toolpath.nc", "success"); 1288 }, [ 1289 l, 1290 g 1291 ]); 1292 return e.jsxs("div", { 1293 className: "fixed right-0 top-0 bottom-0 w-80 bg-surface border-l border-border z-50 flex flex-col", 1294 children: [ 1295 e.jsxs("div", { 1296 className: "flex items-center justify-between p-3 border-b border-border", 1297 children: [ 1298 e.jsx("h2", { 1299 className: "font-medium", 1300 children: "CAM" 1301 }), 1302 e.jsx("button", { 1303 className: "p-1 hover:bg-hover rounded text-text-muted", 1304 onClick: m, 1305 children: e.jsx(le, { 1306 size: 16 1307 }) 1308 }) 1309 ] 1310 }), 1311 e.jsxs("div", { 1312 className: "flex border-b border-border", 1313 children: [ 1314 e.jsxs("button", { 1315 className: `flex-1 flex items-center justify-center gap-1 py-2 text-sm ${s === "operations" ? "border-b-2 border-brand text-text" : "text-text-muted"}`, 1316 onClick: () => a("operations"), 1317 children: [ 1318 e.jsx(ne, { 1319 size: 14 1320 }), 1321 "Ops" 1322 ] 1323 }), 1324 e.jsxs("button", { 1325 className: `flex-1 flex items-center justify-center gap-1 py-2 text-sm ${s === "tools" ? "border-b-2 border-brand text-text" : "text-text-muted"}`, 1326 onClick: () => a("tools"), 1327 children: [ 1328 e.jsx(T, { 1329 size: 14 1330 }), 1331 "Tools" 1332 ] 1333 }), 1334 e.jsxs("button", { 1335 className: `flex-1 flex items-center justify-center gap-1 py-2 text-sm ${s === "settings" ? "border-b-2 border-brand text-text" : "text-text-muted"}`, 1336 onClick: () => a("settings"), 1337 children: [ 1338 e.jsx(ie, { 1339 size: 14 1340 }), 1341 "Settings" 1342 ] 1343 }) 1344 ] 1345 }), 1346 e.jsxs("div", { 1347 className: "flex-1 overflow-y-auto p-3", 1348 children: [ 1349 s === "operations" && e.jsx(ve, {}), 1350 s === "tools" && e.jsx(W, {}), 1351 s === "settings" && e.jsx(fe, {}) 1352 ] 1353 }), 1354 j && e.jsx("div", { 1355 className: "px-3 py-2 border-t border-border bg-surface-secondary text-xs", 1356 children: e.jsxs("div", { 1357 className: "grid grid-cols-2 gap-2", 1358 children: [ 1359 e.jsxs("div", { 1360 children: [ 1361 e.jsx("span", { 1362 className: "text-text-muted", 1363 children: "Cutting length: " 1364 }), 1365 e.jsxs("span", { 1366 children: [ 1367 j.cuttingLength.toFixed(1), 1368 " mm" 1369 ] 1370 }) 1371 ] 1372 }), 1373 e.jsxs("div", { 1374 children: [ 1375 e.jsx("span", { 1376 className: "text-text-muted", 1377 children: "Est. time: " 1378 }), 1379 e.jsx("span", { 1380 children: de(j.estimatedTime) 1381 }) 1382 ] 1383 }) 1384 ] 1385 }) 1386 }), 1387 x && e.jsx("div", { 1388 className: "px-3 py-2 bg-error/10 text-error text-xs", 1389 children: x 1390 }), 1391 e.jsxs("div", { 1392 className: "p-3 border-t border-border space-y-2", 1393 children: [ 1394 e.jsx("button", { 1395 className: "w-full flex items-center justify-center gap-2 py-2 bg-brand text-white rounded hover:bg-brand/90 disabled:opacity-50", 1396 onClick: Z, 1397 disabled: p || !i, 1398 children: p ? e.jsxs(e.Fragment, { 1399 children: [ 1400 e.jsx(xe, { 1401 size: 16, 1402 className: "animate-spin" 1403 }), 1404 "Generating..." 1405 ] 1406 }) : e.jsxs(e.Fragment, { 1407 children: [ 1408 e.jsx(oe, { 1409 size: 16 1410 }), 1411 "Generate Toolpath" 1412 ] 1413 }) 1414 }), 1415 l && e.jsxs("button", { 1416 className: "w-full flex items-center justify-center gap-2 py-2 border border-border rounded hover:bg-hover", 1417 onClick: H, 1418 children: [ 1419 e.jsx(ce, { 1420 size: 16 1421 }), 1422 "Export G-Code" 1423 ] 1424 }) 1425 ] 1426 }) 1427 ] 1428 }); 1429 }; 1430}); 1431export { 1432 Ae as CamPanel, 1433 fe as CamSettings, 1434 ve as OperationList, 1435 W as ToolLibrary, 1436 __tla 1437};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.