@tscircuit/pcb-viewer 1.11.391 → 1.11.393
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/index.js +112 -78
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/toggle-selection/index.js","../node_modules/copy-to-clipboard/index.js","../node_modules/svgson/dist/svgson.umd.js","../src/PCBViewer.tsx","../node_modules/@tscircuit/circuit-json-util/lib/cju.ts","../node_modules/@tscircuit/circuit-json-util/lib/subtree.ts","../node_modules/@tscircuit/circuit-json-util/lib/cju-indexed.ts","../node_modules/@tscircuit/circuit-json-util/lib/transform-soup-elements.ts","../node_modules/@tscircuit/circuit-json-util/lib/direction-to-vec.ts","../node_modules/@tscircuit/circuit-json-util/lib/apply-selector.ts","../node_modules/@tscircuit/circuit-json-util/lib/convert-abbreviation-to-soup-element-type.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-element-id.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-element-by-id.ts","../node_modules/@tscircuit/circuit-json-util/lib/readable-name-functions/get-readable-name-for-pcb-port.ts","../node_modules/@tscircuit/circuit-json-util/lib/readable-name-functions/get-readable-name-for-pcb-smtpad.ts","../node_modules/@tscircuit/circuit-json-util/lib/readable-name-functions/get-readable-name-for-pcb-trace.ts","../node_modules/@tscircuit/circuit-json-util/lib/readable-name-functions/get-readable-name-for-element.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-bounds-of-pcb-elements.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-board-bounds.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-schematic-element-bounds.ts","../node_modules/@tscircuit/circuit-json-util/lib/utils/string-hash.ts","../node_modules/@tscircuit/circuit-json-util/lib/utils/get-layout-debug-object.ts","../node_modules/@tscircuit/circuit-json-util/lib/utils/is-truthy.ts","../node_modules/@tscircuit/circuit-json-util/lib/find-bounds-and-center.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-primary-id.ts","../node_modules/@tscircuit/circuit-json-util/lib/reposition-pcb-component.ts","../node_modules/@tscircuit/circuit-json-util/lib/reposition-pcb-group.ts","../node_modules/@tscircuit/circuit-json-util/lib/reposition-schematic-component.ts","../node_modules/@tscircuit/circuit-json-util/lib/reposition-schematic-group.ts","../node_modules/@tscircuit/circuit-json-util/lib/getCircuitJsonTree.ts","../node_modules/@tscircuit/circuit-json-util/lib/getStringFromCircuitJsonTree.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-minimum-flex-container.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-element-render-layers.ts","../node_modules/@tscircuit/circuit-json-util/lib/shape-distances/geometry.ts","../node_modules/@tscircuit/circuit-json-util/lib/shape-distances/decompose-copper-into-shapes.ts","../node_modules/@tscircuit/circuit-json-util/lib/shape-distances/distance-between-shapes.ts","../node_modules/@tscircuit/circuit-json-util/lib/compute-gap-between-copper.ts","../node_modules/@tscircuit/circuit-json-util/lib/shape-distances/decompose-clearance-into-shapes.ts","../node_modules/@tscircuit/circuit-json-util/lib/compute-clearance-between-elements.ts","../node_modules/@tscircuit/circuit-json-util/lib/analyze-pcb-pin1-location.ts","../node_modules/@tscircuit/circuit-json-util/lib/categorize-error-or-warning.ts","../src/components/ContextProviders.tsx","../src/global-store.ts","../src/hooks/useLocalStorage.ts","../src/lib/toast.tsx","../node_modules/react-use/esm/useMountedState.js","../node_modules/react-use/esm/useSetState.js","../node_modules/react-use/esm/misc/util.js","../node_modules/react-use/esm/useCopyToClipboard.js","../node_modules/react-use/esm/useIsomorphicLayoutEffect.js","../node_modules/react-use/esm/useMeasure.js","../node_modules/use-mouse-matrix-transform/src/computePinchTransform.ts","../node_modules/use-mouse-matrix-transform/src/index.ts","../node_modules/circuit-json-to-connectivity-map/src/findConnectedNetworks.ts","../node_modules/circuit-json-to-connectivity-map/src/ConnectivityMap.ts","../node_modules/circuit-json-to-connectivity-map/src/getSourcePortConnectivityMapFromCircuitJson.ts","../node_modules/circuit-json-to-connectivity-map/src/getFullConnectivityMapFromCircuitJson.ts","../node_modules/circuit-json-to-connectivity-map/src/PcbConnectivityMap.ts","../src/lib/util/expand-stroke.ts","../src/lib/convert-element-to-primitive.ts","../src/lib/element-to-primitive-converters/convert-smtpad-rect.ts","../src/lib/element-to-primitive-converters/convert-smtpad-circle.ts","../src/lib/element-to-primitive-converters/convert-smtpad-polygon.ts","../src/lib/element-to-primitive-converters/convert-smtpad-pill.ts","../src/lib/util/addInteractionMetadataToPrimitives.ts","../src/lib/util/error-preview.ts","../src/lib/util/get-error-id.ts","../src/lib/util/transform-animation.ts","../src/components/CanvasElementsRenderer.tsx","../src/lib/Drawer.ts","../src/lib/colors.ts","../src/lib/util/scale-only.ts","../src/lib/util/z-index-map.ts","../src/lib/copper-layers.ts","../src/lib/draw-copper-pour.ts","../src/lib/draw-courtyard.ts","../src/lib/draw-fabrication-note.ts","../src/lib/draw-hole.ts","../src/lib/draw-pcb-board.ts","../src/lib/draw-pcb-copper-text.ts","../src/lib/draw-pcb-cutout.ts","../src/lib/draw-pcb-keepout.ts","../src/lib/draw-pcb-note.ts","../src/lib/draw-pcb-panel.ts","../src/lib/draw-pcb-smtpad.ts","../src/lib/draw-pcb-trace.ts","../src/lib/draw-plated-hole.ts","../src/lib/util/rotate-text.ts","../src/assets/alphabet.ts","../src/lib/convert-text-to-lines.ts","../src/lib/draw-primitives.ts","../src/lib/draw-silkscreen.ts","../src/lib/draw-soldermask.ts","../src/lib/draw-via.ts","../src/components/CanvasPrimitiveRenderer.tsx","../node_modules/graphics-debug/lib/strokeAlphabetText.ts","../node_modules/iobuffer/src/text.ts","../node_modules/iobuffer/src/iobuffer.ts","../node_modules/fast-png/src/helpers/crc.ts","../node_modules/fast-png/src/helpers/decode_interlace_adam7.ts","../node_modules/fast-png/src/helpers/decode_interlace_null.ts","../node_modules/fast-png/src/helpers/signature.ts","../node_modules/fast-png/src/helpers/text.ts","../node_modules/graphics-debug/lib/infiniteLineHelpers.ts","../node_modules/graphics-debug/lib/constants.ts","../node_modules/graphics-debug/lib/rectGeometry.ts","../node_modules/graphics-debug/lib/arrowHelpers.ts","../node_modules/graphics-debug/site/components/InteractiveGraphics/defaultColors.ts","../node_modules/graphics-debug/lib/drawGraphicsToCanvas.ts","../node_modules/graphics-debug/lib/getPngBufferFromGraphicsObject.ts","../node_modules/graphics-debug/lib/getSvgFromGraphicsObject.ts","../src/components/DebugGraphicsOverlay.tsx","../src/components/DimensionOverlay.tsx","../src/lib/util/get-primitive-bounding-box.ts","../src/hooks/useDiagonalLabel.ts","../src/lib/util/calculate-diagonal-label.ts","../src/lib/util/get-primitive-snap-points.ts","../src/components/EditPlacementOverlay.tsx","../src/components/ErrorOverlay.tsx","../src/lib/util/getPopupPosition.ts","../src/components/FocusMarkerSVG.tsx","../src/components/MouseElementTracker.tsx","../src/lib/util/if-sets-match-exactly.ts","../src/components/AnchorOffsetOverlay/common/guards.ts","../src/components/AnchorOffsetOverlay/AnchorOffsetOverlay.tsx","../src/components/AnchorOffsetOverlay/common/constants.ts","../src/components/AnchorOffsetOverlay/BoardAnchorOffsetOverlay.tsx","../src/components/AnchorOffsetOverlay/GroupAnchorOffsetOverlay.tsx","../src/components/AnchorOffsetOverlay/ComponentBoundingBoxOverlay.tsx","../src/components/AnchorOffsetOverlay/PanelAnchorOffsetOverlay.tsx","../src/lib/get-trace-overlay-text.ts","../src/lib/filter-traces-if-multiple.ts","../src/components/ElementOverlayBox.tsx","../src/components/PcbGroupOverlay.tsx","../src/components/RatsNestOverlay.tsx","../src/components/ToolbarOverlay.tsx","../package.json","../src/hooks/useHotKey.ts","../src/hooks/useIsSmallScreen.ts","../src/hooks/useMobileTouch.ts","../src/components/ToolbarButton.tsx","../src/components/ToolbarErrorDropdown.tsx","../src/lib/util/group-errors-by-type.ts","../src/components/useToolbarErrorFocus.ts","../src/components/WarningGraphicsOverlay.tsx","../src/lib/util/get-pcb-warning-highlight.ts","../src/lib/calculate-circuit-json-key.ts","../src/lib/calculate-board-size-key.ts"],"sourcesContent":["\nmodule.exports = function () {\n var selection = document.getSelection();\n if (!selection.rangeCount) {\n return function () {};\n }\n var active = document.activeElement;\n\n var ranges = [];\n for (var i = 0; i < selection.rangeCount; i++) {\n ranges.push(selection.getRangeAt(i));\n }\n\n switch (active.tagName.toUpperCase()) { // .toUpperCase handles XHTML\n case 'INPUT':\n case 'TEXTAREA':\n active.blur();\n break;\n\n default:\n active = null;\n break;\n }\n\n selection.removeAllRanges();\n return function () {\n selection.type === 'Caret' &&\n selection.removeAllRanges();\n\n if (!selection.rangeCount) {\n ranges.forEach(function(range) {\n selection.addRange(range);\n });\n }\n\n active &&\n active.focus();\n };\n};\n","\"use strict\";\n\nvar deselectCurrent = require(\"toggle-selection\");\n\nvar clipboardToIE11Formatting = {\n \"text/plain\": \"Text\",\n \"text/html\": \"Url\",\n \"default\": \"Text\"\n}\n\nvar defaultMessage = \"Copy to clipboard: #{key}, Enter\";\n\nfunction format(message) {\n var copyKey = (/mac os x/i.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\") + \"+C\";\n return message.replace(/#{\\s*key\\s*}/g, copyKey);\n}\n\nfunction copy(text, options) {\n var debug,\n message,\n reselectPrevious,\n range,\n selection,\n mark,\n success = false;\n if (!options) {\n options = {};\n }\n debug = options.debug || false;\n try {\n reselectPrevious = deselectCurrent();\n\n range = document.createRange();\n selection = document.getSelection();\n\n mark = document.createElement(\"span\");\n mark.textContent = text;\n // avoid screen readers from reading out loud the text\n mark.ariaHidden = \"true\"\n // reset user styles for span element\n mark.style.all = \"unset\";\n // prevents scrolling to the end of the page\n mark.style.position = \"fixed\";\n mark.style.top = 0;\n mark.style.clip = \"rect(0, 0, 0, 0)\";\n // used to preserve spaces and line breaks\n mark.style.whiteSpace = \"pre\";\n // do not inherit user-select (it may be `none`)\n mark.style.webkitUserSelect = \"text\";\n mark.style.MozUserSelect = \"text\";\n mark.style.msUserSelect = \"text\";\n mark.style.userSelect = \"text\";\n mark.addEventListener(\"copy\", function(e) {\n e.stopPropagation();\n if (options.format) {\n e.preventDefault();\n if (typeof e.clipboardData === \"undefined\") { // IE 11\n debug && console.warn(\"unable to use e.clipboardData\");\n debug && console.warn(\"trying IE specific stuff\");\n window.clipboardData.clearData();\n var format = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting[\"default\"]\n window.clipboardData.setData(format, text);\n } else { // all other browsers\n e.clipboardData.clearData();\n e.clipboardData.setData(options.format, text);\n }\n }\n if (options.onCopy) {\n e.preventDefault();\n options.onCopy(e.clipboardData);\n }\n });\n\n document.body.appendChild(mark);\n\n range.selectNodeContents(mark);\n selection.addRange(range);\n\n var successful = document.execCommand(\"copy\");\n if (!successful) {\n throw new Error(\"copy command was unsuccessful\");\n }\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using execCommand: \", err);\n debug && console.warn(\"trying IE specific stuff\");\n try {\n window.clipboardData.setData(options.format || \"text\", text);\n options.onCopy && options.onCopy(window.clipboardData);\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using clipboardData: \", err);\n debug && console.error(\"falling back to prompt\");\n message = format(\"message\" in options ? options.message : defaultMessage);\n window.prompt(message, text);\n }\n } finally {\n if (selection) {\n if (typeof selection.removeRange == \"function\") {\n selection.removeRange(range);\n } else {\n selection.removeAllRanges();\n }\n }\n\n if (mark) {\n document.body.removeChild(mark);\n }\n reselectPrevious();\n }\n\n return success;\n}\n\nmodule.exports = copy;\n","(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.svgson = factory());\n})(this, (function () { 'use strict';\n\n /*!\n * Determine if an object is a Buffer\n *\n * @author Feross Aboukhadijeh <https://feross.org>\n * @license MIT\n */\n\n // The _isBuffer check is for Safari 5-7 support, because it's missing\n // Object.prototype.constructor. Remove this eventually\n var isBuffer_1 = function (obj) {\n return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)\n };\n\n function isBuffer (obj) {\n return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)\n }\n\n // For Node v0.10 support. Remove this eventually.\n function isSlowBuffer (obj) {\n return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))\n }\n\n var toString = Object.prototype.toString;\n\n /**\n * Get the native `typeof` a value.\n *\n * @param {*} `val`\n * @return {*} Native javascript type\n */\n\n var kindOf = function kindOf(val) {\n // primitivies\n if (typeof val === 'undefined') {\n return 'undefined';\n }\n if (val === null) {\n return 'null';\n }\n if (val === true || val === false || val instanceof Boolean) {\n return 'boolean';\n }\n if (typeof val === 'string' || val instanceof String) {\n return 'string';\n }\n if (typeof val === 'number' || val instanceof Number) {\n return 'number';\n }\n\n // functions\n if (typeof val === 'function' || val instanceof Function) {\n return 'function';\n }\n\n // array\n if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {\n return 'array';\n }\n\n // check for instances of RegExp and Date before calling `toString`\n if (val instanceof RegExp) {\n return 'regexp';\n }\n if (val instanceof Date) {\n return 'date';\n }\n\n // other objects\n var type = toString.call(val);\n\n if (type === '[object RegExp]') {\n return 'regexp';\n }\n if (type === '[object Date]') {\n return 'date';\n }\n if (type === '[object Arguments]') {\n return 'arguments';\n }\n if (type === '[object Error]') {\n return 'error';\n }\n\n // buffer\n if (isBuffer_1(val)) {\n return 'buffer';\n }\n\n // es6: Map, WeakMap, Set, WeakSet\n if (type === '[object Set]') {\n return 'set';\n }\n if (type === '[object WeakSet]') {\n return 'weakset';\n }\n if (type === '[object Map]') {\n return 'map';\n }\n if (type === '[object WeakMap]') {\n return 'weakmap';\n }\n if (type === '[object Symbol]') {\n return 'symbol';\n }\n\n // typed arrays\n if (type === '[object Int8Array]') {\n return 'int8array';\n }\n if (type === '[object Uint8Array]') {\n return 'uint8array';\n }\n if (type === '[object Uint8ClampedArray]') {\n return 'uint8clampedarray';\n }\n if (type === '[object Int16Array]') {\n return 'int16array';\n }\n if (type === '[object Uint16Array]') {\n return 'uint16array';\n }\n if (type === '[object Int32Array]') {\n return 'int32array';\n }\n if (type === '[object Uint32Array]') {\n return 'uint32array';\n }\n if (type === '[object Float32Array]') {\n return 'float32array';\n }\n if (type === '[object Float64Array]') {\n return 'float64array';\n }\n\n // must be a plain object\n return 'object';\n };\n\n function createCommonjsModule(fn, module) {\n \treturn module = { exports: {} }, fn(module, module.exports), module.exports;\n }\n\n var renameKeys = createCommonjsModule(function (module) {\n (function() {\n\n function rename(obj, fn) {\n if (typeof fn !== 'function') {\n return obj;\n }\n\n var res = {};\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n res[fn(key, obj[key]) || key] = obj[key];\n }\n }\n return res;\n }\n\n if (module.exports) {\n module.exports = rename;\n } else {\n {\n window.rename = rename;\n }\n }\n })();\n });\n\n /**\n * Expose `renameDeep`\n */\n\n var deepRenameKeys = function renameDeep(obj, cb) {\n var type = kindOf(obj);\n\n if (type !== 'object' && type !== 'array') {\n throw new Error('expected an object');\n }\n\n var res = [];\n if (type === 'object') {\n obj = renameKeys(obj, cb);\n res = {};\n }\n\n for (var key in obj) {\n if (obj.hasOwnProperty(key)) {\n var val = obj[key];\n if (kindOf(val) === 'object' || kindOf(val) === 'array') {\n res[key] = renameDeep(val, cb);\n } else {\n res[key] = val;\n }\n }\n }\n return res;\n };\n\n var eventemitter3 = createCommonjsModule(function (module) {\n\n var has = Object.prototype.hasOwnProperty\n , prefix = '~';\n\n /**\n * Constructor to create a storage for our `EE` objects.\n * An `Events` instance is a plain object whose properties are event names.\n *\n * @constructor\n * @api private\n */\n function Events() {}\n\n //\n // We try to not inherit from `Object.prototype`. In some engines creating an\n // instance in this way is faster than calling `Object.create(null)` directly.\n // If `Object.create(null)` is not supported we prefix the event names with a\n // character to make sure that the built-in object properties are not\n // overridden or used as an attack vector.\n //\n if (Object.create) {\n Events.prototype = Object.create(null);\n\n //\n // This hack is needed because the `__proto__` property is still inherited in\n // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.\n //\n if (!new Events().__proto__) prefix = false;\n }\n\n /**\n * Representation of a single event listener.\n *\n * @param {Function} fn The listener function.\n * @param {Mixed} context The context to invoke the listener with.\n * @param {Boolean} [once=false] Specify if the listener is a one-time listener.\n * @constructor\n * @api private\n */\n function EE(fn, context, once) {\n this.fn = fn;\n this.context = context;\n this.once = once || false;\n }\n\n /**\n * Minimal `EventEmitter` interface that is molded against the Node.js\n * `EventEmitter` interface.\n *\n * @constructor\n * @api public\n */\n function EventEmitter() {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n /**\n * Return an array listing the events for which the emitter has registered\n * listeners.\n *\n * @returns {Array}\n * @api public\n */\n EventEmitter.prototype.eventNames = function eventNames() {\n var names = []\n , events\n , name;\n\n if (this._eventsCount === 0) return names;\n\n for (name in (events = this._events)) {\n if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);\n }\n\n if (Object.getOwnPropertySymbols) {\n return names.concat(Object.getOwnPropertySymbols(events));\n }\n\n return names;\n };\n\n /**\n * Return the listeners registered for a given event.\n *\n * @param {String|Symbol} event The event name.\n * @param {Boolean} exists Only check if there are listeners.\n * @returns {Array|Boolean}\n * @api public\n */\n EventEmitter.prototype.listeners = function listeners(event, exists) {\n var evt = prefix ? prefix + event : event\n , available = this._events[evt];\n\n if (exists) return !!available;\n if (!available) return [];\n if (available.fn) return [available.fn];\n\n for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) {\n ee[i] = available[i].fn;\n }\n\n return ee;\n };\n\n /**\n * Calls each of the listeners registered for a given event.\n *\n * @param {String|Symbol} event The event name.\n * @returns {Boolean} `true` if the event had listeners, else `false`.\n * @api public\n */\n EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return false;\n\n var listeners = this._events[evt]\n , len = arguments.length\n , args\n , i;\n\n if (listeners.fn) {\n if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);\n\n switch (len) {\n case 1: return listeners.fn.call(listeners.context), true;\n case 2: return listeners.fn.call(listeners.context, a1), true;\n case 3: return listeners.fn.call(listeners.context, a1, a2), true;\n case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;\n case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;\n case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;\n }\n\n for (i = 1, args = new Array(len -1); i < len; i++) {\n args[i - 1] = arguments[i];\n }\n\n listeners.fn.apply(listeners.context, args);\n } else {\n var length = listeners.length\n , j;\n\n for (i = 0; i < length; i++) {\n if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);\n\n switch (len) {\n case 1: listeners[i].fn.call(listeners[i].context); break;\n case 2: listeners[i].fn.call(listeners[i].context, a1); break;\n case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;\n case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;\n default:\n if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {\n args[j - 1] = arguments[j];\n }\n\n listeners[i].fn.apply(listeners[i].context, args);\n }\n }\n }\n\n return true;\n };\n\n /**\n * Add a listener for a given event.\n *\n * @param {String|Symbol} event The event name.\n * @param {Function} fn The listener function.\n * @param {Mixed} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @api public\n */\n EventEmitter.prototype.on = function on(event, fn, context) {\n var listener = new EE(fn, context || this)\n , evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) this._events[evt] = listener, this._eventsCount++;\n else if (!this._events[evt].fn) this._events[evt].push(listener);\n else this._events[evt] = [this._events[evt], listener];\n\n return this;\n };\n\n /**\n * Add a one-time listener for a given event.\n *\n * @param {String|Symbol} event The event name.\n * @param {Function} fn The listener function.\n * @param {Mixed} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @api public\n */\n EventEmitter.prototype.once = function once(event, fn, context) {\n var listener = new EE(fn, context || this, true)\n , evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) this._events[evt] = listener, this._eventsCount++;\n else if (!this._events[evt].fn) this._events[evt].push(listener);\n else this._events[evt] = [this._events[evt], listener];\n\n return this;\n };\n\n /**\n * Remove the listeners of a given event.\n *\n * @param {String|Symbol} event The event name.\n * @param {Function} fn Only remove the listeners that match this function.\n * @param {Mixed} context Only remove the listeners that have this context.\n * @param {Boolean} once Only remove one-time listeners.\n * @returns {EventEmitter} `this`.\n * @api public\n */\n EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return this;\n if (!fn) {\n if (--this._eventsCount === 0) this._events = new Events();\n else delete this._events[evt];\n return this;\n }\n\n var listeners = this._events[evt];\n\n if (listeners.fn) {\n if (\n listeners.fn === fn\n && (!once || listeners.once)\n && (!context || listeners.context === context)\n ) {\n if (--this._eventsCount === 0) this._events = new Events();\n else delete this._events[evt];\n }\n } else {\n for (var i = 0, events = [], length = listeners.length; i < length; i++) {\n if (\n listeners[i].fn !== fn\n || (once && !listeners[i].once)\n || (context && listeners[i].context !== context)\n ) {\n events.push(listeners[i]);\n }\n }\n\n //\n // Reset the array, or remove it completely if we have no more listeners.\n //\n if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;\n else if (--this._eventsCount === 0) this._events = new Events();\n else delete this._events[evt];\n }\n\n return this;\n };\n\n /**\n * Remove all listeners, or those of the specified event.\n *\n * @param {String|Symbol} [event] The event name.\n * @returns {EventEmitter} `this`.\n * @api public\n */\n EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {\n var evt;\n\n if (event) {\n evt = prefix ? prefix + event : event;\n if (this._events[evt]) {\n if (--this._eventsCount === 0) this._events = new Events();\n else delete this._events[evt];\n }\n } else {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n return this;\n };\n\n //\n // Alias methods names because people roll like that.\n //\n EventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n EventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n //\n // This function doesn't apply anymore.\n //\n EventEmitter.prototype.setMaxListeners = function setMaxListeners() {\n return this;\n };\n\n //\n // Expose the prefix.\n //\n EventEmitter.prefixed = prefix;\n\n //\n // Allow `EventEmitter` to be imported as module namespace.\n //\n EventEmitter.EventEmitter = EventEmitter;\n\n //\n // Expose the module.\n //\n {\n module.exports = EventEmitter;\n }\n });\n\n function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n\n var noop = function noop() {};\n\n var State = {\n data: 'state-data',\n cdata: 'state-cdata',\n tagBegin: 'state-tag-begin',\n tagName: 'state-tag-name',\n tagEnd: 'state-tag-end',\n attributeNameStart: 'state-attribute-name-start',\n attributeName: 'state-attribute-name',\n attributeNameEnd: 'state-attribute-name-end',\n attributeValueBegin: 'state-attribute-value-begin',\n attributeValue: 'state-attribute-value'\n };\n\n var Action = {\n lt: 'action-lt',\n gt: 'action-gt',\n space: 'action-space',\n equal: 'action-equal',\n quote: 'action-quote',\n slash: 'action-slash',\n char: 'action-char',\n error: 'action-error'\n };\n\n var Type$1 = {\n text: 'text',\n openTag: 'open-tag',\n closeTag: 'close-tag',\n attributeName: 'attribute-name',\n attributeValue: 'attribute-value'\n };\n\n var charToAction = {\n ' ': Action.space,\n '\\t': Action.space,\n '\\n': Action.space,\n '\\r': Action.space,\n '<': Action.lt,\n '>': Action.gt,\n '\"': Action.quote,\n \"'\": Action.quote,\n '=': Action.equal,\n '/': Action.slash\n };\n\n var getAction = function getAction(char) {\n return charToAction[char] || Action.char;\n };\n\n /**\n * @param {Object} options\n * @param {Boolean} options.debug\n * @return {Object}\n */\n var create$1 = function create(options) {\n var _State$data, _State$tagBegin, _State$tagName, _State$tagEnd, _State$attributeNameS, _State$attributeName, _State$attributeNameE, _State$attributeValue, _State$attributeValue2, _lexer$stateMachine;\n\n options = Object.assign({ debug: false }, options);\n var lexer = new eventemitter3();\n var state = State.data;\n var data = '';\n var tagName = '';\n var attrName = '';\n var attrValue = '';\n var isClosing = '';\n var openingQuote = '';\n\n var emit = function emit(type, value) {\n // for now, ignore tags like: '?xml', '!DOCTYPE' or comments\n if (tagName[0] === '?' || tagName[0] === '!') {\n return;\n }\n var event = { type: type, value: value };\n if (options.debug) {\n console.log('emit:', event);\n }\n lexer.emit('data', event);\n };\n\n lexer.stateMachine = (_lexer$stateMachine = {}, _defineProperty(_lexer$stateMachine, State.data, (_State$data = {}, _defineProperty(_State$data, Action.lt, function () {\n if (data.trim()) {\n emit(Type$1.text, data);\n }\n tagName = '';\n isClosing = false;\n state = State.tagBegin;\n }), _defineProperty(_State$data, Action.char, function (char) {\n data += char;\n }), _State$data)), _defineProperty(_lexer$stateMachine, State.cdata, _defineProperty({}, Action.char, function (char) {\n data += char;\n if (data.substr(-3) === ']]>') {\n emit(Type$1.text, data.slice(0, -3));\n data = '';\n state = State.data;\n }\n })), _defineProperty(_lexer$stateMachine, State.tagBegin, (_State$tagBegin = {}, _defineProperty(_State$tagBegin, Action.space, noop), _defineProperty(_State$tagBegin, Action.char, function (char) {\n tagName = char;\n state = State.tagName;\n }), _defineProperty(_State$tagBegin, Action.slash, function () {\n tagName = '';\n isClosing = true;\n }), _State$tagBegin)), _defineProperty(_lexer$stateMachine, State.tagName, (_State$tagName = {}, _defineProperty(_State$tagName, Action.space, function () {\n if (isClosing) {\n state = State.tagEnd;\n } else {\n state = State.attributeNameStart;\n emit(Type$1.openTag, tagName);\n }\n }), _defineProperty(_State$tagName, Action.gt, function () {\n if (isClosing) {\n emit(Type$1.closeTag, tagName);\n } else {\n emit(Type$1.openTag, tagName);\n }\n data = '';\n state = State.data;\n }), _defineProperty(_State$tagName, Action.slash, function () {\n state = State.tagEnd;\n emit(Type$1.openTag, tagName);\n }), _defineProperty(_State$tagName, Action.char, function (char) {\n tagName += char;\n if (tagName === '![CDATA[') {\n state = State.cdata;\n data = '';\n tagName = '';\n }\n }), _State$tagName)), _defineProperty(_lexer$stateMachine, State.tagEnd, (_State$tagEnd = {}, _defineProperty(_State$tagEnd, Action.gt, function () {\n emit(Type$1.closeTag, tagName);\n data = '';\n state = State.data;\n }), _defineProperty(_State$tagEnd, Action.char, noop), _State$tagEnd)), _defineProperty(_lexer$stateMachine, State.attributeNameStart, (_State$attributeNameS = {}, _defineProperty(_State$attributeNameS, Action.char, function (char) {\n attrName = char;\n state = State.attributeName;\n }), _defineProperty(_State$attributeNameS, Action.gt, function () {\n data = '';\n state = State.data;\n }), _defineProperty(_State$attributeNameS, Action.space, noop), _defineProperty(_State$attributeNameS, Action.slash, function () {\n isClosing = true;\n state = State.tagEnd;\n }), _State$attributeNameS)), _defineProperty(_lexer$stateMachine, State.attributeName, (_State$attributeName = {}, _defineProperty(_State$attributeName, Action.space, function () {\n state = State.attributeNameEnd;\n }), _defineProperty(_State$attributeName, Action.equal, function () {\n emit(Type$1.attributeName, attrName);\n state = State.attributeValueBegin;\n }), _defineProperty(_State$attributeName, Action.gt, function () {\n attrValue = '';\n emit(Type$1.attributeName, attrName);\n emit(Type$1.attributeValue, attrValue);\n data = '';\n state = State.data;\n }), _defineProperty(_State$attributeName, Action.slash, function () {\n isClosing = true;\n attrValue = '';\n emit(Type$1.attributeName, attrName);\n emit(Type$1.attributeValue, attrValue);\n state = State.tagEnd;\n }), _defineProperty(_State$attributeName, Action.char, function (char) {\n attrName += char;\n }), _State$attributeName)), _defineProperty(_lexer$stateMachine, State.attributeNameEnd, (_State$attributeNameE = {}, _defineProperty(_State$attributeNameE, Action.space, noop), _defineProperty(_State$attributeNameE, Action.equal, function () {\n emit(Type$1.attributeName, attrName);\n state = State.attributeValueBegin;\n }), _defineProperty(_State$attributeNameE, Action.gt, function () {\n attrValue = '';\n emit(Type$1.attributeName, attrName);\n emit(Type$1.attributeValue, attrValue);\n data = '';\n state = State.data;\n }), _defineProperty(_State$attributeNameE, Action.char, function (char) {\n attrValue = '';\n emit(Type$1.attributeName, attrName);\n emit(Type$1.attributeValue, attrValue);\n attrName = char;\n state = State.attributeName;\n }), _State$attributeNameE)), _defineProperty(_lexer$stateMachine, State.attributeValueBegin, (_State$attributeValue = {}, _defineProperty(_State$attributeValue, Action.space, noop), _defineProperty(_State$attributeValue, Action.quote, function (char) {\n openingQuote = char;\n attrValue = '';\n state = State.attributeValue;\n }), _defineProperty(_State$attributeValue, Action.gt, function () {\n attrValue = '';\n emit(Type$1.attributeValue, attrValue);\n data = '';\n state = State.data;\n }), _defineProperty(_State$attributeValue, Action.char, function (char) {\n openingQuote = '';\n attrValue = char;\n state = State.attributeValue;\n }), _State$attributeValue)), _defineProperty(_lexer$stateMachine, State.attributeValue, (_State$attributeValue2 = {}, _defineProperty(_State$attributeValue2, Action.space, function (char) {\n if (openingQuote) {\n attrValue += char;\n } else {\n emit(Type$1.attributeValue, attrValue);\n state = State.attributeNameStart;\n }\n }), _defineProperty(_State$attributeValue2, Action.quote, function (char) {\n if (openingQuote === char) {\n emit(Type$1.attributeValue, attrValue);\n state = State.attributeNameStart;\n } else {\n attrValue += char;\n }\n }), _defineProperty(_State$attributeValue2, Action.gt, function (char) {\n if (openingQuote) {\n attrValue += char;\n } else {\n emit(Type$1.attributeValue, attrValue);\n data = '';\n state = State.data;\n }\n }), _defineProperty(_State$attributeValue2, Action.slash, function (char) {\n if (openingQuote) {\n attrValue += char;\n } else {\n emit(Type$1.attributeValue, attrValue);\n isClosing = true;\n state = State.tagEnd;\n }\n }), _defineProperty(_State$attributeValue2, Action.char, function (char) {\n attrValue += char;\n }), _State$attributeValue2)), _lexer$stateMachine);\n\n var step = function step(char) {\n if (options.debug) {\n console.log(state, char);\n }\n var actions = lexer.stateMachine[state];\n var action = actions[getAction(char)] || actions[Action.error] || actions[Action.char];\n action(char);\n };\n\n lexer.write = function (str) {\n var len = str.length;\n for (var i = 0; i < len; i++) {\n step(str[i]);\n }\n };\n\n return lexer;\n };\n\n var lexer = {\n State: State,\n Action: Action,\n Type: Type$1,\n create: create$1\n };\n\n var Type = lexer.Type;\n\n var NodeType = {\n element: 'element',\n text: 'text'\n };\n\n var createNode = function createNode(params) {\n return Object.assign({\n name: '',\n type: NodeType.element,\n value: '',\n parent: null,\n attributes: {},\n children: []\n }, params);\n };\n\n var create = function create(options) {\n options = Object.assign({\n stream: false,\n parentNodes: true,\n doneEvent: 'done',\n tagPrefix: 'tag:',\n emitTopLevelOnly: false,\n debug: false\n }, options);\n\n var lexer$1 = void 0,\n rootNode = void 0,\n current = void 0,\n attrName = void 0;\n\n var reader = new eventemitter3();\n\n var handleLexerData = function handleLexerData(data) {\n switch (data.type) {\n\n case Type.openTag:\n if (current === null) {\n current = rootNode;\n current.name = data.value;\n } else {\n var node = createNode({\n name: data.value,\n parent: current\n });\n current.children.push(node);\n current = node;\n }\n break;\n\n case Type.closeTag:\n var parent = current.parent;\n if (!options.parentNodes) {\n current.parent = null;\n }\n if (current.name !== data.value) {\n // ignore unexpected closing tag\n break;\n }\n if (options.stream && parent === rootNode) {\n rootNode.children = [];\n // do not expose parent node in top level nodes\n current.parent = null;\n }\n if (!options.emitTopLevelOnly || parent === rootNode) {\n reader.emit(options.tagPrefix + current.name, current);\n reader.emit('tag', current.name, current);\n }\n if (current === rootNode) {\n // end of document, stop listening\n lexer$1.removeAllListeners('data');\n reader.emit(options.doneEvent, current);\n rootNode = null;\n }\n current = parent;\n break;\n\n case Type.text:\n if (current) {\n current.children.push(createNode({\n type: NodeType.text,\n value: data.value,\n parent: options.parentNodes ? current : null\n }));\n }\n break;\n\n case Type.attributeName:\n attrName = data.value;\n current.attributes[attrName] = '';\n break;\n\n case Type.attributeValue:\n current.attributes[attrName] = data.value;\n break;\n }\n };\n\n reader.reset = function () {\n lexer$1 = lexer.create({ debug: options.debug });\n lexer$1.on('data', handleLexerData);\n rootNode = createNode();\n current = null;\n attrName = '';\n reader.parse = lexer$1.write;\n };\n\n reader.reset();\n return reader;\n };\n\n var parseSync = function parseSync(xml, options) {\n options = Object.assign({}, options, { stream: false, tagPrefix: ':' });\n var reader = create(options);\n var res = void 0;\n reader.on('done', function (ast) {\n res = ast;\n });\n reader.parse(xml);\n return res;\n };\n\n var reader = {\n parseSync: parseSync,\n create: create,\n NodeType: NodeType\n };\n var reader_1 = reader.parseSync;\n\n var parseInput = function parseInput(input) {\n var parsed = reader_1(\"<root>\".concat(input, \"</root>\"), {\n parentNodes: false\n });\n var isValid = parsed.children && parsed.children.length > 0 && parsed.children.every(function (node) {\n return node.name === 'svg';\n });\n if (isValid) {\n return parsed.children.length === 1 ? parsed.children[0] : parsed.children;\n } else {\n throw Error('nothing to parse');\n }\n };\n var camelize = function camelize(node) {\n return deepRenameKeys(node, function (key) {\n if (!notCamelcase(key)) {\n return toCamelCase(key);\n }\n return key;\n });\n };\n var toCamelCase = function toCamelCase(prop) {\n return prop.replace(/[-|:]([a-z])/gi, function (all, letter) {\n return letter.toUpperCase();\n });\n };\n var notCamelcase = function notCamelcase(prop) {\n return /^(data|aria)(-\\w+)/.test(prop);\n };\n var escapeText = function escapeText(text) {\n if (text) {\n var str = String(text);\n return /[&<>]/.test(str) ? \"<![CDATA[\".concat(str.replace(/]]>/, ']]]]><![CDATA[>'), \"]]>\") : str;\n }\n return '';\n };\n var escapeAttr = function escapeAttr(attr) {\n return String(attr).replace(/&/g, '&').replace(/'/g, ''').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g, '>');\n };\n\n var svgsonSync = function svgsonSync(input) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$transformNode = _ref.transformNode,\n transformNode = _ref$transformNode === void 0 ? function (node) {\n return node;\n } : _ref$transformNode,\n _ref$camelcase = _ref.camelcase,\n camelcase = _ref$camelcase === void 0 ? false : _ref$camelcase;\n var applyFilters = function applyFilters(input) {\n var n;\n n = transformNode(input);\n if (camelcase) {\n n = camelize(n);\n }\n return n;\n };\n return applyFilters(parseInput(input));\n };\n function svgson() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return new Promise(function (resolve, reject) {\n try {\n var res = svgsonSync.apply(void 0, args);\n resolve(res);\n } catch (e) {\n reject(e);\n }\n });\n }\n\n var stringify = function stringify(_ast) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$transformAttr = _ref.transformAttr,\n transformAttr = _ref$transformAttr === void 0 ? function (key, value, escape) {\n return \"\".concat(key, \"=\\\"\").concat(escape(value), \"\\\"\");\n } : _ref$transformAttr,\n _ref$transformNode = _ref.transformNode,\n transformNode = _ref$transformNode === void 0 ? function (node) {\n return node;\n } : _ref$transformNode,\n _ref$selfClose = _ref.selfClose,\n selfClose = _ref$selfClose === void 0 ? true : _ref$selfClose;\n if (Array.isArray(_ast)) {\n return _ast.map(function (ast) {\n return stringify(ast, {\n transformAttr: transformAttr,\n selfClose: selfClose,\n transformNode: transformNode\n });\n }).join('');\n }\n var ast = transformNode(_ast);\n if (ast.type === 'text') {\n return escapeText(ast.value);\n }\n var attributes = '';\n for (var attr in ast.attributes) {\n var attrStr = transformAttr(attr, ast.attributes[attr], escapeAttr, ast.name);\n attributes += attrStr ? \" \".concat(attrStr) : '';\n }\n return ast.children && ast.children.length > 0 || !selfClose ? \"<\".concat(ast.name).concat(attributes, \">\").concat(stringify(ast.children, {\n transformAttr: transformAttr,\n transformNode: transformNode,\n selfClose: selfClose\n }), \"</\").concat(ast.name, \">\") : \"<\".concat(ast.name).concat(attributes, \"/>\");\n };\n\n var indexUmd = Object.assign({}, {\n parse: svgson,\n parseSync: svgsonSync,\n stringify: stringify\n });\n\n return indexUmd;\n\n}));\n","import { applyEditEvents } from \"@tscircuit/core\"\nimport { findBoundsAndCenter } from \"@tscircuit/circuit-json-util\"\nimport type { AnyCircuitElement, SourceTrace } from \"circuit-json\"\nimport { ContextProviders } from \"./components/ContextProviders\"\nimport type { StateProps } from \"./global-store\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { ToastContainer } from \"lib/toast\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport { compose, scale, translate } from \"transformation-matrix\"\nimport useMouseMatrixTransform from \"use-mouse-matrix-transform\"\nimport { CanvasElementsRenderer } from \"./components/CanvasElementsRenderer\"\nimport type { BoundsSelection } from \"./components/DimensionOverlay\"\nimport type { ManualEditEvent } from \"@tscircuit/props\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { calculateCircuitJsonKey } from \"lib/calculate-circuit-json-key\"\nimport { calculateBoardSizeKey } from \"lib/calculate-board-size-key\"\n\nconst defaultTransform = compose(translate(400, 300), scale(40, -40))\n\ntype Props = {\n circuitJson?: AnyCircuitElement[]\n height?: number\n allowEditing?: boolean\n editEvents?: ManualEditEvent[]\n initialState?: Partial<StateProps>\n onEditEventsChanged?: (editEvents: ManualEditEvent[]) => void\n onBoundsSelected?: (bounds: BoundsSelection) => void\n focusOnHover?: boolean\n clickToInteractEnabled?: boolean\n debugGraphics?: GraphicsObject | null\n disablePcbGroups?: boolean\n}\n\nexport const PCBViewer = ({\n circuitJson,\n debugGraphics,\n height = 600,\n initialState,\n allowEditing = true,\n editEvents: editEventsProp,\n onEditEventsChanged,\n onBoundsSelected,\n focusOnHover = false,\n clickToInteractEnabled = false,\n disablePcbGroups = false,\n}: Props) => {\n const [isInteractionEnabled, setIsInteractionEnabled] = useState(\n !clickToInteractEnabled,\n )\n const [ref, refDimensions] = useMeasure()\n const [transform, setTransformInternal] = useState(defaultTransform)\n const shouldAllowCanvasInteraction = useCallback(\n (event: MouseEvent | TouchEvent | WheelEvent) => {\n const target = event.target\n if (!(target instanceof Element)) return true\n\n return !target.closest(\"[data-toolbar-overlay]\")\n },\n [],\n )\n\n const {\n ref: transformRef,\n setTransform,\n cancelDrag: cancelPanDrag,\n } = useMouseMatrixTransform({\n transform,\n onSetTransform: setTransformInternal,\n enabled: isInteractionEnabled,\n shouldDrag: shouldAllowCanvasInteraction,\n })\n\n let [editEvents, setEditEvents] = useState<ManualEditEvent[]>([])\n editEvents = editEventsProp ?? editEvents\n\n const initialRenderCompleted = useRef(false)\n const touchStartRef = useRef<{ x: number; y: number } | null>(null)\n const circuitJsonKey = useMemo(\n () => calculateCircuitJsonKey(circuitJson),\n [circuitJson],\n )\n const boardSizeKey = calculateBoardSizeKey(circuitJson)\n\n const resetTransform = () => {\n const elmBounds =\n refDimensions?.width > 0 ? refDimensions : { width: 500, height: 500 }\n const { center, width, height } = elements.some((e) =>\n e.type.startsWith(\"pcb_\"),\n )\n ? findBoundsAndCenter(\n elements.filter((e) => e.type.startsWith(\"pcb_\")) as any,\n )\n : { center: { x: 0, y: 0 }, width: 0.001, height: 0.001 }\n const scaleFactor =\n Math.min(\n (elmBounds.width ?? 0) / width,\n (elmBounds.height ?? 0) / height,\n 100,\n ) * 0.75\n\n const targetTransform = compose(\n translate((elmBounds.width ?? 0) / 2, (elmBounds.height ?? 0) / 2),\n scale(scaleFactor, -scaleFactor, 0, 0),\n translate(-center.x, -center.y),\n )\n\n setTransform(targetTransform)\n return\n }\n\n useEffect(() => {\n if (!refDimensions?.width) return\n if (!circuitJson) return\n if (circuitJson.length === 0) return\n\n if (!initialRenderCompleted.current) {\n resetTransform()\n initialRenderCompleted.current = true\n }\n }, [circuitJson, refDimensions])\n\n useEffect(() => {\n if (initialRenderCompleted.current === true) {\n resetTransform()\n }\n }, [boardSizeKey])\n\n const pcbElmsPreEdit = useMemo(() => {\n return (\n circuitJson?.filter(\n (e: any) => e.type.startsWith(\"pcb_\") || e.type.startsWith(\"source_\"),\n ) ?? []\n )\n }, [circuitJsonKey])\n\n const elements = useMemo(() => {\n return applyEditEvents({\n circuitJson: pcbElmsPreEdit as any,\n editEvents,\n })\n }, [pcbElmsPreEdit, editEvents])\n\n const onCreateEditEvent = (event: ManualEditEvent) => {\n setEditEvents([...editEvents, event])\n onEditEventsChanged?.([...editEvents, event])\n }\n const onModifyEditEvent = (modifiedEvent: Partial<ManualEditEvent>) => {\n const newEditEvents: ManualEditEvent[] = editEvents.map((e) =>\n e.edit_event_id === modifiedEvent.edit_event_id\n ? ({ ...e, ...modifiedEvent } as ManualEditEvent)\n : e,\n )\n setEditEvents(newEditEvents)\n onEditEventsChanged?.(newEditEvents)\n }\n\n const mergedInitialState = useMemo(\n () => ({\n ...initialState,\n ...(disablePcbGroups && { is_showing_pcb_groups: false }),\n }),\n [initialState, disablePcbGroups],\n )\n\n return (\n <div\n ref={transformRef as any}\n style={{ position: \"relative\" }}\n onContextMenu={(event) => event.preventDefault()}\n >\n <div ref={ref as any}>\n <ContextProviders\n initialState={mergedInitialState}\n disablePcbGroups={disablePcbGroups}\n >\n <CanvasElementsRenderer\n key={refDimensions.width}\n transform={transform}\n setTransform={setTransform}\n height={height}\n width={refDimensions.width}\n allowEditing={allowEditing}\n focusOnHover={focusOnHover}\n onBoundsSelected={onBoundsSelected}\n cancelPanDrag={cancelPanDrag}\n onCreateEditEvent={onCreateEditEvent}\n onModifyEditEvent={onModifyEditEvent}\n grid={{\n spacing: 1,\n view_window: {\n left: 0,\n right: refDimensions.width || 500,\n top: height,\n bottom: 0,\n },\n }}\n elements={elements as SourceTrace[]}\n debugGraphics={debugGraphics}\n />\n <ToastContainer />\n </ContextProviders>\n </div>\n {clickToInteractEnabled && !isInteractionEnabled && (\n <div\n onClick={() => {\n setIsInteractionEnabled(true)\n resetTransform()\n }}\n onTouchStart={(e) => {\n const touch = e.touches[0]\n touchStartRef.current = {\n x: touch.clientX,\n y: touch.clientY,\n }\n }}\n onTouchEnd={(e) => {\n const touch = e.changedTouches[0]\n const start = touchStartRef.current\n if (!start) return\n\n const deltaX = Math.abs(touch.clientX - start.x)\n const deltaY = Math.abs(touch.clientY - start.y)\n\n if (deltaX < 10 && deltaY < 10) {\n e.preventDefault()\n setIsInteractionEnabled(true)\n resetTransform()\n }\n\n touchStartRef.current = null\n }}\n style={{\n position: \"absolute\",\n inset: 0,\n cursor: \"pointer\",\n zIndex: zIndexMap.clickToInteractOverlay,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n touchAction: \"pan-x pan-y pinch-zoom\",\n }}\n >\n <div\n style={{\n backgroundColor: \"rgba(0, 0, 0, 0.8)\",\n color: \"white\",\n padding: \"12px 24px\",\n borderRadius: \"8px\",\n fontSize: \"16px\",\n pointerEvents: \"none\",\n }}\n >\n {typeof window !== \"undefined\" &&\n (\"ontouchstart\" in window || navigator.maxTouchPoints > 0)\n ? \"Touch to Interact\"\n : \"Click to Interact\"}\n </div>\n </div>\n )}\n </div>\n )\n}\n","import type {\n AnyCircuitElement,\n AnyCircuitElementInput,\n SourceComponentBase,\n SourcePort,\n} from \"circuit-json\"\nimport * as Soup from \"circuit-json\"\nimport type { SubtreeOptions } from \"./subtree\"\nimport { buildSubtree } from \"./subtree\"\n\n// Keep the existing permissive input while preserving discriminated variants.\ntype CircuitJsonElementInsertInput<\n CircuitElementType extends AnyCircuitElement[\"type\"],\n CircuitElement extends { type: CircuitElementType },\n> =\n | Omit<CircuitElement, \"type\" | `${CircuitElementType}_id`>\n | (CircuitElement extends { type: CircuitElementType }\n ? Omit<CircuitElement, \"type\" | `${CircuitElementType}_id`>\n : never)\n\nexport type CircuitJsonOps<\n K extends AnyCircuitElement[\"type\"],\n T extends AnyCircuitElement | AnyCircuitElementInput,\n> = {\n get: (id: string) => Extract<T, { type: K }> | null\n select: (selector: string) => Extract<T, { type: K }> | null\n getWhere: (where: any) => Extract<T, { type: K }> | null\n getUsing: (using: {\n [key: `${string}_id`]: string\n }) => Extract<T, { type: K }> | null\n insert: (\n elm: CircuitJsonElementInsertInput<K, Extract<T, { type: K }>>,\n ) => Extract<T, { type: K }>\n update: (\n id: string,\n newProps: Partial<Extract<T, { type: K }>>,\n ) => Extract<T, { type: K }>\n delete: (id: string) => void\n list: (where?: any) => Extract<T, { type: K }>[]\n}\n\nexport type CircuitJsonUtilObjects = {\n [K in AnyCircuitElement[\"type\"]]: CircuitJsonOps<K, AnyCircuitElement>\n} & {\n insert: (elm: AnyCircuitElementInput) => AnyCircuitElement\n insertAll: (elms: AnyCircuitElementInput[]) => AnyCircuitElement[]\n subtree: (where?: any) => CircuitJsonUtilObjects\n toArray: () => AnyCircuitElement[]\n editCount: number\n}\nexport type CircuitJsonInputUtilObjects = {\n [K in AnyCircuitElementInput[\"type\"]]: CircuitJsonOps<\n K,\n AnyCircuitElementInput\n >\n}\n\nexport type CircuitJsonUtilOptions = {\n validateInserts?: boolean\n}\n\nexport type GetCircuitJsonUtilFn = ((\n soup: AnyCircuitElement[],\n options?: CircuitJsonUtilOptions,\n) => CircuitJsonUtilObjects) & {\n unparsed: (soup: AnyCircuitElementInput[]) => CircuitJsonInputUtilObjects\n}\n\ninterface InternalStore {\n counts: Record<string, number>\n editCount: number\n}\n\nexport const cju: GetCircuitJsonUtilFn = ((\n circuitJsonInput: any[],\n options: CircuitJsonUtilOptions = {},\n) => {\n const circuitJson = circuitJsonInput as AnyCircuitElement[]\n let internalStore: InternalStore = (circuitJson as any)._internal_store\n if (!internalStore) {\n internalStore = {\n counts: {},\n editCount: 0,\n } as InternalStore\n ;(circuitJson as any)._internal_store = internalStore\n\n // Initialize counts\n for (const elm of circuitJson) {\n const type = elm.type\n const idVal = (elm as any)[`${type}_id`]\n if (!idVal) continue\n const idNum = Number.parseInt(idVal.split(\"_\").pop())\n if (!Number.isNaN(idNum)) {\n internalStore.counts[type] = Math.max(\n internalStore.counts[type] ?? 0,\n idNum,\n )\n }\n }\n }\n const su = new Proxy(\n {},\n {\n get: (proxy_target: any, prop: string) => {\n if (prop === \"toArray\") {\n return () => {\n ;(circuitJson as any).editCount = internalStore.editCount\n return circuitJson\n }\n }\n if (prop === \"editCount\") {\n return internalStore.editCount\n }\n\n if (prop === \"subtree\") {\n return (opts: SubtreeOptions) =>\n cju(buildSubtree(circuitJson, opts), options)\n }\n\n if (prop === \"insert\") {\n return (elm: AnyCircuitElementInput) => {\n const component_type = elm.type\n if (!component_type) {\n throw new Error(\"insert requires an element with a type\")\n }\n\n internalStore.counts[component_type] ??= -1\n internalStore.counts[component_type]++\n const index = internalStore.counts[component_type]\n\n const newElm = {\n ...elm,\n type: component_type,\n [`${component_type}_id`]: `${component_type}_${index}`,\n } as AnyCircuitElement\n\n if (options.validateInserts) {\n const parser =\n (Soup as any)[component_type] ?? Soup.any_soup_element\n parser.parse(newElm)\n }\n\n circuitJson.push(newElm)\n internalStore.editCount++\n return newElm\n }\n }\n\n if (prop === \"insertAll\") {\n return (elms: AnyCircuitElementInput[]) => {\n return elms.map((elm) => su.insert(elm))\n }\n }\n\n const component_type = prop\n\n return {\n get: (id: string) =>\n circuitJson.find(\n (e: any) =>\n e.type === component_type && e[`${component_type}_id`] === id,\n ),\n getUsing: (using: any) => {\n const keys = Object.keys(using)\n if (keys.length !== 1) {\n throw new Error(\n \"getUsing requires exactly one key, e.g. { pcb_component_id }\",\n )\n }\n const join_key = keys[0] as string\n const join_type = join_key.replace(\"_id\", \"\")\n const joiner: any = circuitJson.find(\n (e: any) =>\n e.type === join_type && e[join_key] === using[join_key],\n )\n if (!joiner) return null\n return circuitJson.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joiner[`${component_type}_id`],\n )\n },\n getWhere: (where: any) => {\n const keys = Object.keys(where)\n return circuitJson.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key]),\n )\n },\n list: (where?: any) => {\n const keys = !where ? [] : Object.keys(where)\n return circuitJson.filter(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key]),\n )\n },\n insert: (elm: any) => {\n internalStore.counts[component_type] ??= -1\n internalStore.counts[component_type]++\n const index = internalStore.counts[component_type]\n const newElm = {\n type: component_type,\n [`${component_type}_id`]: `${component_type}_${index}`,\n ...elm,\n }\n\n if (options.validateInserts) {\n const parser =\n (Soup as any)[component_type] ?? Soup.any_soup_element\n parser.parse(newElm)\n }\n\n circuitJson.push(newElm)\n internalStore.editCount++\n return newElm\n },\n delete: (id: string) => {\n const elm = circuitJson.find(\n (e) => (e as any)[`${component_type}_id`] === id,\n )\n if (!elm) return\n circuitJson.splice(circuitJson.indexOf(elm), 1)\n internalStore.editCount++\n },\n update: (id: string, newProps: any) => {\n const elm = circuitJson.find(\n (e) =>\n e.type === component_type &&\n (e as any)[`${component_type}_id`] === id,\n )\n if (!elm) return null\n Object.assign(elm, newProps)\n internalStore.editCount++\n return elm\n },\n select: (selector: string) => {\n // TODO when applySelector is isolated we can use it, until then we\n // do a poor man's selector implementation for two common cases\n if (component_type === \"source_component\") {\n return circuitJson.find(\n (e) =>\n e.type === \"source_component\" &&\n e.name === selector.replace(/\\./g, \"\"),\n )\n } else if (\n component_type === \"pcb_port\" ||\n component_type === \"source_port\" ||\n component_type === \"schematic_port\"\n ) {\n const [component_name, port_selector] = selector\n .replace(/\\./g, \"\")\n .split(/[\\s\\>]+/)\n const source_component = circuitJson.find(\n (e) =>\n e.type === \"source_component\" && e.name === component_name,\n ) as SourceComponentBase\n if (!source_component) return null\n const source_port = circuitJson.find(\n (e) =>\n e.type === \"source_port\" &&\n e.source_component_id ===\n source_component.source_component_id &&\n (e.name === port_selector ||\n (e.port_hints ?? []).includes(port_selector!)),\n ) as SourcePort\n if (!source_port) return null\n if (component_type === \"source_port\") return source_port\n\n if (component_type === \"pcb_port\") {\n return circuitJson.find(\n (e) =>\n e.type === \"pcb_port\" &&\n e.source_port_id === source_port.source_port_id,\n )\n } else if (component_type === \"schematic_port\") {\n return circuitJson.find(\n (e) =>\n e.type === \"schematic_port\" &&\n e.source_port_id === source_port.source_port_id,\n )\n }\n }\n },\n }\n },\n },\n )\n\n return su\n}) as any\ncju.unparsed = cju as any\n\nexport const su = cju\n\nexport default cju\n","import type { AnyCircuitElement } from \"circuit-json\"\n\nexport type SubtreeOptions = {\n subcircuit_id?: string\n subcircuit_ids?: string[]\n source_group_id?: string\n source_board_id?: string\n}\n\nfunction connect(\n map: Map<AnyCircuitElement, Set<AnyCircuitElement>>,\n a: AnyCircuitElement | undefined,\n b: AnyCircuitElement | undefined,\n) {\n if (!a || !b) return\n let setA = map.get(a)\n if (!setA) {\n setA = new Set()\n map.set(a, setA)\n }\n setA.add(b)\n let setB = map.get(b)\n if (!setB) {\n setB = new Set()\n map.set(b, setB)\n }\n setB.add(a)\n}\n\nexport function buildSubtree(\n soup: AnyCircuitElement[],\n opts: SubtreeOptions,\n): AnyCircuitElement[] {\n if (!opts.subcircuit_id && !opts.source_group_id) return [...soup]\n\n // For subcircuit_id, also include nested subcircuits\n let effectiveOpts = opts\n if (opts.subcircuit_id) {\n // Find all subcircuit_ids that are children of the target subcircuit\n const subcircuitIds = new Set<string>([opts.subcircuit_id])\n\n // Build group hierarchy\n const groupChildren = new Map<string, string[]>()\n const groupSubcircuit = new Map<string, string>()\n\n for (const elm of soup) {\n if (elm.type === \"source_group\") {\n const groupId = elm.source_group_id\n const subcircuitId = elm.subcircuit_id\n if (subcircuitId) {\n groupSubcircuit.set(groupId, subcircuitId)\n }\n const parentId = elm.parent_source_group_id\n if (parentId) {\n if (!groupChildren.has(parentId)) {\n groupChildren.set(parentId, [])\n }\n groupChildren.get(parentId)!.push(groupId)\n }\n }\n }\n\n // Find the root group for the target subcircuit\n let rootGroupId: string | undefined\n for (const [groupId, subcircuitId] of groupSubcircuit) {\n if (subcircuitId === opts.subcircuit_id) {\n rootGroupId = groupId\n break\n }\n }\n\n if (rootGroupId) {\n // Recursively collect all child subcircuit_ids\n const collectChildSubcircuits = (groupId: string) => {\n const children = groupChildren.get(groupId) || []\n for (const childId of children) {\n const childSubcircuit = groupSubcircuit.get(childId)\n if (childSubcircuit) {\n subcircuitIds.add(childSubcircuit)\n }\n collectChildSubcircuits(childId)\n }\n }\n collectChildSubcircuits(rootGroupId)\n\n // Update opts to include all these subcircuits\n effectiveOpts = { ...opts, subcircuit_ids: Array.from(subcircuitIds) }\n }\n }\n\n const idMap = new Map<string, AnyCircuitElement>()\n for (const elm of soup) {\n const idKey = `${elm.type}_id` as keyof typeof elm\n const idVal = elm[idKey]\n if (typeof idVal === \"string\") {\n idMap.set(idVal, elm)\n }\n }\n\n const adj = new Map<AnyCircuitElement, Set<AnyCircuitElement>>()\n for (const elm of soup) {\n const entries = Object.entries(elm)\n for (const [key, val] of entries) {\n if (key === \"parent_source_group_id\") continue // Skip parent relationships to avoid traversing up\n if (key.endsWith(\"_id\") && typeof val === \"string\") {\n const other = idMap.get(val)\n connect(adj, elm, other)\n } else if (key.endsWith(\"_ids\") && Array.isArray(val)) {\n for (const v of val) {\n if (typeof v === \"string\") {\n const other = idMap.get(v)\n connect(adj, elm, other)\n }\n }\n }\n }\n }\n\n const queue: AnyCircuitElement[] = []\n const included = new Set<AnyCircuitElement>()\n\n for (const elm of soup) {\n let shouldInclude = false\n if (\n effectiveOpts.subcircuit_id &&\n \"subcircuit_id\" in elm &&\n elm.subcircuit_id === effectiveOpts.subcircuit_id\n ) {\n shouldInclude = true\n } else if (\n effectiveOpts.subcircuit_ids &&\n \"subcircuit_id\" in elm &&\n elm.subcircuit_id &&\n effectiveOpts.subcircuit_ids.includes(elm.subcircuit_id)\n ) {\n shouldInclude = true\n } else if (\n effectiveOpts.source_group_id &&\n \"source_group_id\" in elm &&\n elm.source_group_id === effectiveOpts.source_group_id\n ) {\n shouldInclude = true\n } else if (\n effectiveOpts.source_group_id &&\n \"member_source_group_ids\" in elm &&\n Array.isArray(elm.member_source_group_ids) &&\n elm.member_source_group_ids.includes(effectiveOpts.source_group_id)\n ) {\n shouldInclude = true\n }\n\n if (shouldInclude) {\n queue.push(elm)\n included.add(elm)\n }\n }\n\n while (queue.length > 0) {\n const elm = queue.shift()!\n const neighbors = adj.get(elm)\n if (!neighbors) continue\n for (const n of neighbors) {\n if (!included.has(n)) {\n included.add(n)\n queue.push(n)\n }\n }\n }\n\n return soup.filter((e) => included.has(e))\n}\n","import type {\n AnyCircuitElement,\n AnyCircuitElementInput,\n SourceComponentBase,\n SourcePort,\n} from \"circuit-json\"\nimport * as Soup from \"circuit-json\"\nimport type {\n CircuitJsonOps,\n CircuitJsonUtilObjects as CircuitJsonUtilObjects,\n CircuitJsonInputUtilObjects as CircuitJsonInputUtilObjects,\n} from \"./cju\"\n\nexport type IndexedCircuitJsonUtilOptions = {\n validateInserts?: boolean\n indexConfig?: {\n // Enable specific indexes for faster lookups\n byId?: boolean\n byType?: boolean\n byRelation?: boolean\n bySubcircuit?: boolean\n byCustomField?: string[]\n }\n}\n\nexport type GetIndexedCircuitJsonUtilFn = ((\n soup: AnyCircuitElement[],\n options?: IndexedCircuitJsonUtilOptions,\n) => CircuitJsonUtilObjects) & {\n unparsed: (soup: AnyCircuitElementInput[]) => CircuitJsonInputUtilObjects\n}\n\ninterface InternalStore {\n counts: Record<string, number>\n editCount: number\n // Indexes for faster lookups\n indexes: {\n byId?: Map<string, AnyCircuitElement>\n byType?: Map<string, AnyCircuitElement[]>\n // Maps relation fields (like component_id) to elements\n byRelation?: Map<string, Map<string, AnyCircuitElement[]>>\n // Maps subcircuit_id to elements\n bySubcircuit?: Map<string, AnyCircuitElement[]>\n // Custom field indexes\n byCustomField?: Map<string, Map<string, AnyCircuitElement[]>>\n }\n}\n\n// Creates a unique key for the ID index\nfunction createIdKey(element: AnyCircuitElement): string {\n const type = element.type\n return `${type}:${(element as any)[`${type}_id`]}`\n}\n\nexport const cjuIndexed: GetIndexedCircuitJsonUtilFn = ((\n soup: AnyCircuitElement[],\n options: IndexedCircuitJsonUtilOptions = {},\n) => {\n let internalStore: InternalStore = (soup as any)._internal_store_indexed\n\n if (!internalStore) {\n internalStore = {\n counts: {},\n editCount: 0,\n indexes: {},\n } as InternalStore\n\n // Initialize counts\n for (const elm of soup) {\n const type = elm.type\n const idVal = (elm as any)[`${type}_id`]\n if (!idVal) continue\n const idNum = Number.parseInt(idVal.split(\"_\").pop() || \"\")\n if (!Number.isNaN(idNum)) {\n internalStore.counts[type] = Math.max(\n internalStore.counts[type] ?? 0,\n idNum,\n )\n }\n }\n\n // Build indexes\n const indexConfig = options.indexConfig || {}\n const indexes = internalStore.indexes\n\n // Reset indexes before rebuilding\n if (indexConfig.byId) {\n indexes.byId = new Map()\n }\n\n if (indexConfig.byType) {\n indexes.byType = new Map()\n }\n\n if (indexConfig.byRelation) {\n indexes.byRelation = new Map()\n }\n\n if (indexConfig.bySubcircuit) {\n indexes.bySubcircuit = new Map()\n }\n\n if (indexConfig.byCustomField && indexConfig.byCustomField.length > 0) {\n indexes.byCustomField = new Map()\n for (const field of indexConfig.byCustomField) {\n indexes.byCustomField.set(field, new Map())\n }\n }\n\n // Build indexes\n for (const element of soup) {\n // Index by ID\n if (indexConfig.byId) {\n const idKey = createIdKey(element)\n indexes.byId!.set(idKey, element)\n }\n\n // Index by type\n if (indexConfig.byType) {\n const elementsOfType = indexes.byType!.get(element.type) || []\n elementsOfType.push(element)\n indexes.byType!.set(element.type, elementsOfType)\n }\n\n // Index by relation fields (fields ending with _id)\n if (indexConfig.byRelation) {\n const elementEntries = Object.entries(element)\n for (const [key, value] of elementEntries) {\n if (\n key.endsWith(\"_id\") &&\n key !== `${element.type}_id` &&\n typeof value === \"string\"\n ) {\n const relationTypeMap = indexes.byRelation!.get(key) || new Map()\n const relatedElements = relationTypeMap.get(value as string) || []\n relatedElements.push(element)\n relationTypeMap.set(value as string, relatedElements)\n indexes.byRelation!.set(key, relationTypeMap)\n }\n }\n }\n\n // Index by subcircuit_id\n if (indexConfig.bySubcircuit && \"subcircuit_id\" in element) {\n const subcircuitId = (element as any).subcircuit_id\n if (subcircuitId && typeof subcircuitId === \"string\") {\n const subcircuitElements =\n indexes.bySubcircuit!.get(subcircuitId) || []\n subcircuitElements.push(element)\n indexes.bySubcircuit!.set(subcircuitId, subcircuitElements)\n }\n }\n\n // Index by custom fields\n if (indexConfig.byCustomField && indexes.byCustomField) {\n for (const field of indexConfig.byCustomField) {\n if (field in element) {\n const fieldValue = (element as any)[field]\n if (\n fieldValue !== undefined &&\n (typeof fieldValue === \"string\" || typeof fieldValue === \"number\")\n ) {\n const fieldValueStr = String(fieldValue)\n const fieldMap = indexes.byCustomField.get(field)!\n const elementsWithFieldValue = fieldMap.get(fieldValueStr) || []\n elementsWithFieldValue.push(element)\n fieldMap.set(fieldValueStr, elementsWithFieldValue)\n }\n }\n }\n }\n }\n // Store internal state\n ;(soup as any)._internal_store_indexed = internalStore\n }\n\n const suIndexed = new Proxy(\n {},\n {\n get: (proxy_target: any, prop: string) => {\n if (prop === \"toArray\") {\n return () => {\n ;(soup as any).editCount = internalStore.editCount\n return soup\n }\n }\n if (prop === \"editCount\") {\n return internalStore.editCount\n }\n\n const component_type = prop\n\n return {\n get: (id: string) => {\n const indexConfig = options.indexConfig || {}\n\n // Use ID index if available\n if (indexConfig.byId && internalStore.indexes.byId) {\n return (\n (internalStore.indexes.byId.get(\n `${component_type}:${id}`,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n // Use type index if available\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n return (\n (elementsOfType.find(\n (e: any) => e[`${component_type}_id`] === id,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n // Fallback to regular search\n return (\n (soup.find(\n (e: any) =>\n e.type === component_type && e[`${component_type}_id`] === id,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n },\n\n getUsing: (using: any) => {\n const indexConfig = options.indexConfig || {}\n const keys = Object.keys(using)\n\n if (keys.length !== 1) {\n throw new Error(\n \"getUsing requires exactly one key, e.g. { pcb_component_id }\",\n )\n }\n\n const join_key = keys[0] as string\n const join_type = join_key.replace(\"_id\", \"\")\n\n // Use relation index if available\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n const relationMap = internalStore.indexes.byRelation.get(join_key)\n if (relationMap) {\n const relatedElements = relationMap.get(using[join_key]) || []\n const joiner = relatedElements.find((e) => e.type === join_type)\n\n if (!joiner) return null\n\n // Now find the element of component_type with matching ID\n const joinerId =\n joiner[`${component_type}_id` as keyof typeof joiner]\n\n if (indexConfig.byId && internalStore.indexes.byId) {\n return (\n (internalStore.indexes.byId.get(\n `${component_type}:${joinerId}`,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n return (\n (elementsOfType.find(\n (e: any) => e[`${component_type}_id`] === joinerId,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n return (\n (soup.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joinerId,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n }\n\n // Fallback to regular approach\n const joiner: any = soup.find(\n (e: any) =>\n e.type === join_type && e[join_key] === using[join_key],\n )\n\n if (!joiner) return null\n\n return (\n (soup.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joiner[`${component_type}_id`],\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n },\n\n getWhere: (where: any) => {\n const indexConfig = options.indexConfig || {}\n const keys = Object.keys(where)\n\n // If we're looking by a single property and it's indexed as a custom field\n if (\n keys.length === 1 &&\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n const field = keys[0]\n const fieldMap = internalStore.indexes.byCustomField.get(field!)\n\n if (fieldMap) {\n const fieldValue = String(where[field!])\n const elementsWithFieldValue = fieldMap.get(fieldValue) || []\n\n return (\n (elementsWithFieldValue.find(\n (e: any) => e.type === component_type,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n }\n\n // If we're looking by subcircuit_id and it's indexed\n if (\n \"subcircuit_id\" in where &&\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit\n ) {\n const subcircuitId = where.subcircuit_id\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n\n return (\n (subcircuitElements.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key]),\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n // Use type index if available to reduce search space\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n\n return (\n (elementsOfType.find((e: any) =>\n keys.every((key) => e[key] === where[key]),\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n // Fallback to regular approach\n return (\n (soup.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key]),\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n },\n\n list: (where?: any) => {\n const indexConfig = options.indexConfig || {}\n const keys = !where ? [] : Object.keys(where)\n\n // If no filters, just return all elements of this type using the type index\n if (\n keys.length === 0 &&\n indexConfig.byType &&\n internalStore.indexes.byType\n ) {\n return (internalStore.indexes.byType.get(component_type) ||\n []) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >[]\n }\n\n // If filtering by subcircuit_id and it's the only filter\n if (\n keys.length === 1 &&\n keys[0] === \"subcircuit_id\" &&\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit\n ) {\n const subcircuitId = where.subcircuit_id\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n\n return subcircuitElements.filter(\n (e: any) => e.type === component_type,\n ) as Extract<AnyCircuitElement, { type: typeof component_type }>[]\n }\n\n // Start with all elements of this type to reduce search space\n let elementsToFilter: AnyCircuitElement[]\n\n if (indexConfig.byType && internalStore.indexes.byType) {\n elementsToFilter =\n internalStore.indexes.byType.get(component_type) || []\n } else {\n elementsToFilter = soup.filter((e) => e.type === component_type)\n }\n\n // Apply remaining filters\n if (keys.length > 0) {\n return elementsToFilter.filter((e: any) =>\n keys.every((key) => e[key] === where[key]),\n ) as Extract<AnyCircuitElement, { type: typeof component_type }>[]\n }\n\n return elementsToFilter as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >[]\n },\n\n insert: (elm: any) => {\n internalStore.counts[component_type] ??= -1\n internalStore.counts[component_type]++\n const index = internalStore.counts[component_type]\n const newElm = {\n type: component_type,\n [`${component_type}_id`]: `${component_type}_${index}`,\n ...elm,\n }\n\n if (options.validateInserts) {\n const parser =\n (Soup as any)[component_type] ?? Soup.any_soup_element\n parser.parse(newElm)\n }\n\n soup.push(newElm)\n internalStore.editCount++\n\n // Update indexes with the new element\n const indexConfig = options.indexConfig || {}\n\n // Update ID index\n if (indexConfig.byId && internalStore.indexes.byId) {\n const idKey = createIdKey(newElm)\n internalStore.indexes.byId.set(idKey, newElm)\n }\n\n // Update type index\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n elementsOfType.push(newElm)\n internalStore.indexes.byType.set(component_type, elementsOfType)\n }\n\n // Update relation index\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n const elementEntries = Object.entries(newElm)\n for (const [key, value] of elementEntries) {\n if (\n key.endsWith(\"_id\") &&\n key !== `${newElm.type}_id` &&\n typeof value === \"string\"\n ) {\n const relationTypeMap =\n internalStore.indexes.byRelation.get(key) || new Map()\n const relatedElements =\n relationTypeMap.get(value as string) || []\n relatedElements.push(newElm)\n relationTypeMap.set(value as string, relatedElements)\n internalStore.indexes.byRelation.set(key, relationTypeMap)\n }\n }\n }\n\n // Update subcircuit index\n if (\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit &&\n \"subcircuit_id\" in newElm\n ) {\n const subcircuitId = (newElm as any).subcircuit_id\n if (subcircuitId && typeof subcircuitId === \"string\") {\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n subcircuitElements.push(newElm)\n internalStore.indexes.bySubcircuit.set(\n subcircuitId,\n subcircuitElements,\n )\n }\n }\n\n // Update custom field indexes\n if (\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n for (const field of indexConfig.byCustomField) {\n if (field in newElm) {\n const fieldValue = (newElm as any)[field]\n if (\n fieldValue !== undefined &&\n (typeof fieldValue === \"string\" ||\n typeof fieldValue === \"number\")\n ) {\n const fieldValueStr = String(fieldValue)\n const fieldMap =\n internalStore.indexes.byCustomField.get(field)!\n const elementsWithFieldValue =\n fieldMap.get(fieldValueStr) || []\n elementsWithFieldValue.push(newElm)\n fieldMap.set(fieldValueStr, elementsWithFieldValue)\n }\n }\n }\n }\n\n return newElm\n },\n\n delete: (id: string) => {\n const indexConfig = options.indexConfig || {}\n let elm: AnyCircuitElement | undefined\n\n // Find the element to delete\n if (indexConfig.byId && internalStore.indexes.byId) {\n elm = internalStore.indexes.byId.get(`${component_type}:${id}`)\n } else if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n elm = elementsOfType.find(\n (e: any) => e[`${component_type}_id`] === id,\n )\n } else {\n elm = soup.find((e) => (e as any)[`${component_type}_id`] === id)\n }\n\n if (!elm) return\n\n // Remove from array\n const elmIndex = soup.indexOf(elm)\n if (elmIndex >= 0) {\n soup.splice(elmIndex, 1)\n internalStore.editCount++\n }\n\n // Remove from indexes\n if (indexConfig.byId && internalStore.indexes.byId) {\n const idKey = createIdKey(elm)\n internalStore.indexes.byId.delete(idKey)\n }\n\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n const filteredElements = elementsOfType.filter(\n (e: any) => e[`${component_type}_id`] !== id,\n )\n internalStore.indexes.byType.set(component_type, filteredElements)\n }\n\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n // This is more complex - we need to find and remove from all relation maps\n // where this element appears\n for (const [\n relationKey,\n relationMap,\n ] of internalStore.indexes.byRelation.entries()) {\n for (const [relationValue, elements] of relationMap.entries()) {\n const updatedElements = elements.filter((e) => e !== elm)\n\n if (updatedElements.length === 0) {\n relationMap.delete(relationValue)\n } else {\n relationMap.set(relationValue, updatedElements)\n }\n }\n }\n }\n\n if (\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit &&\n \"subcircuit_id\" in elm\n ) {\n const subcircuitId = (elm as any).subcircuit_id\n if (subcircuitId) {\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n const updatedElements = subcircuitElements.filter(\n (e) => e !== elm,\n )\n\n if (updatedElements.length === 0) {\n internalStore.indexes.bySubcircuit.delete(subcircuitId)\n } else {\n internalStore.indexes.bySubcircuit.set(\n subcircuitId,\n updatedElements,\n )\n }\n }\n }\n\n if (\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n for (const fieldMap of internalStore.indexes.byCustomField.values()) {\n for (const [fieldValue, elements] of fieldMap.entries()) {\n const updatedElements = elements.filter((e) => e !== elm)\n\n if (updatedElements.length === 0) {\n fieldMap.delete(fieldValue)\n } else {\n fieldMap.set(fieldValue, updatedElements)\n }\n }\n }\n }\n },\n\n update: (id: string, newProps: any) => {\n const indexConfig = options.indexConfig || {}\n let elm: AnyCircuitElement | undefined | null\n\n // Find the element to update\n if (indexConfig.byId && internalStore.indexes.byId) {\n elm = internalStore.indexes.byId.get(`${component_type}:${id}`)\n } else if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n elm = elementsOfType.find(\n (e: any) => e[`${component_type}_id`] === id,\n )\n } else {\n elm = soup.find(\n (e) =>\n e.type === component_type &&\n (e as any)[`${component_type}_id`] === id,\n )\n }\n\n if (!elm) return null\n\n // Need to remove from indexes before updating\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n // Remove from relation indexes\n const elementEntries = Object.entries(elm)\n for (const [key, value] of elementEntries) {\n if (\n key.endsWith(\"_id\") &&\n key !== `${elm.type}_id` &&\n typeof value === \"string\"\n ) {\n if (key in newProps && newProps[key] !== value) {\n const relationTypeMap =\n internalStore.indexes.byRelation.get(key)\n if (relationTypeMap) {\n const relatedElements =\n relationTypeMap.get(value as string) || []\n const updatedElements = relatedElements.filter(\n (e) => e !== elm,\n )\n\n if (updatedElements.length === 0) {\n relationTypeMap.delete(value as string)\n } else {\n relationTypeMap.set(value as string, updatedElements)\n }\n }\n }\n }\n }\n }\n\n if (\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit &&\n \"subcircuit_id\" in elm &&\n \"subcircuit_id\" in newProps\n ) {\n const oldSubcircuitId = (elm as any).subcircuit_id\n const newSubcircuitId = newProps.subcircuit_id\n\n if (oldSubcircuitId !== newSubcircuitId) {\n // Remove from old subcircuit index\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(oldSubcircuitId) || []\n const updatedElements = subcircuitElements.filter(\n (e) => e !== elm,\n )\n\n if (updatedElements.length === 0) {\n internalStore.indexes.bySubcircuit.delete(oldSubcircuitId)\n } else {\n internalStore.indexes.bySubcircuit.set(\n oldSubcircuitId,\n updatedElements,\n )\n }\n }\n }\n\n if (\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n for (const field of indexConfig.byCustomField) {\n if (\n field in elm &&\n field in newProps &&\n (elm as any)[field] !== newProps[field]\n ) {\n const fieldMap =\n internalStore.indexes.byCustomField.get(field)\n if (fieldMap) {\n const oldValue = String((elm as any)[field])\n const elements = fieldMap.get(oldValue) || []\n const updatedElements = elements.filter((e) => e !== elm)\n\n if (updatedElements.length === 0) {\n fieldMap.delete(oldValue)\n } else {\n fieldMap.set(oldValue, updatedElements)\n }\n }\n }\n }\n }\n\n // Update the element\n Object.assign(elm, newProps)\n internalStore.editCount++\n\n // Add to indexes with updated values\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n const elementEntries = Object.entries(elm)\n for (const [key, value] of elementEntries) {\n if (\n key.endsWith(\"_id\") &&\n key !== `${elm.type}_id` &&\n typeof value === \"string\"\n ) {\n if (key in newProps) {\n const relationTypeMap: any =\n internalStore.indexes.byRelation.get(key) || new Map()\n const relatedElements: any =\n relationTypeMap.get(value as string) || []\n\n if (!relatedElements.includes(elm)) {\n relatedElements.push(elm)\n relationTypeMap.set(value as string, relatedElements)\n internalStore.indexes.byRelation.set(key, relationTypeMap)\n }\n }\n }\n }\n }\n\n if (\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit &&\n \"subcircuit_id\" in elm &&\n \"subcircuit_id\" in newProps\n ) {\n const subcircuitId = (elm as any).subcircuit_id\n if (subcircuitId && typeof subcircuitId === \"string\") {\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n\n if (!subcircuitElements.includes(elm)) {\n subcircuitElements.push(elm)\n internalStore.indexes.bySubcircuit.set(\n subcircuitId,\n subcircuitElements,\n )\n }\n }\n }\n\n if (\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n for (const field of indexConfig.byCustomField) {\n if (field in elm && field in newProps) {\n const fieldValue: any = (elm as any)[field]\n if (\n fieldValue !== undefined &&\n (typeof fieldValue === \"string\" ||\n typeof fieldValue === \"number\")\n ) {\n const fieldValueStr = String(fieldValue)\n const fieldMap =\n internalStore.indexes.byCustomField.get(field)!\n const elementsWithFieldValue =\n fieldMap.get(fieldValueStr) || []\n\n if (!elementsWithFieldValue.includes(elm)) {\n elementsWithFieldValue.push(elm)\n fieldMap.set(fieldValueStr, elementsWithFieldValue)\n }\n }\n }\n }\n }\n\n return elm as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >\n },\n\n select: (selector: string) => {\n // Selection by selector is specialized enough that we don't use indexes here\n // TODO when applySelector is isolated we can use it, until then we\n // do a poor man's selector implementation for two common cases\n if (component_type === \"source_component\") {\n return (\n (soup.find(\n (e) =>\n e.type === \"source_component\" &&\n e.name === selector.replace(/\\./g, \"\"),\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n } else if (\n component_type === \"pcb_port\" ||\n component_type === \"source_port\" ||\n component_type === \"schematic_port\"\n ) {\n const [component_name, port_selector] = selector\n .replace(/\\./g, \"\")\n .split(/[\\s\\>]+/)\n const source_component = soup.find(\n (e) =>\n e.type === \"source_component\" && e.name === component_name,\n ) as SourceComponentBase\n if (!source_component) return null\n const source_port = soup.find(\n (e) =>\n e.type === \"source_port\" &&\n e.source_component_id ===\n source_component.source_component_id &&\n (e.name === port_selector ||\n (e.port_hints ?? []).includes(port_selector!)),\n ) as SourcePort\n if (!source_port) return null\n if (component_type === \"source_port\")\n return source_port as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >\n\n if (component_type === \"pcb_port\") {\n return (\n (soup.find(\n (e) =>\n e.type === \"pcb_port\" &&\n e.source_port_id === source_port.source_port_id,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n } else if (component_type === \"schematic_port\") {\n return (\n (soup.find(\n (e) =>\n e.type === \"schematic_port\" &&\n e.source_port_id === source_port.source_port_id,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n }\n\n return null\n },\n }\n },\n },\n )\n\n return suIndexed\n}) as any\n\ncjuIndexed.unparsed = cjuIndexed as any\n\nexport default cjuIndexed\n","import type { AnyCircuitElement, InsertionDirection } from \"circuit-json\"\nimport { type Matrix, applyToPoint, decomposeTSR } from \"transformation-matrix\"\nimport {\n directionToVec,\n rotateDirection,\n vecToDirection,\n} from \"./direction-to-vec\"\n\nconst getQuarterTurns = (angleRadians: number) =>\n Math.round(angleRadians / (Math.PI / 2))\n\nconst insertionDirectionToVec = (\n direction: Exclude<InsertionDirection, \"from_above\" | \"from_below\">,\n) => {\n switch (direction) {\n case \"from_left\":\n return { x: -1, y: 0 }\n case \"from_right\":\n return { x: 1, y: 0 }\n case \"from_top\":\n return { x: 0, y: 1 }\n case \"from_bottom\":\n return { x: 0, y: -1 }\n }\n}\n\nconst vecToInsertionDirection = ({\n x,\n y,\n}: {\n x: number\n y: number\n}): Exclude<InsertionDirection, \"from_above\" | \"from_below\"> => {\n if (x > 0) return \"from_right\"\n if (x < 0) return \"from_left\"\n if (y > 0) return \"from_top\"\n return \"from_bottom\"\n}\n\nexport const transformInsertionDirection = (\n direction: InsertionDirection | undefined,\n opts: { rotationDegrees: number; isFlipped: boolean },\n) => {\n if (!direction) return direction\n\n // Rotating within the board plane leaves a Z-axis insertion pointing along\n // Z, but moving the part to the other layer reverses which side of the board\n // the mating part approaches from.\n if (direction === \"from_above\" || direction === \"from_below\") {\n if (!opts.isFlipped) return direction\n return direction === \"from_above\" ? \"from_below\" : \"from_above\"\n }\n\n let { x, y } = insertionDirectionToVec(direction)\n let quarterTurns = Math.round(opts.rotationDegrees / 90)\n\n while (quarterTurns > 0) {\n ;[x, y] = [-y, x]\n quarterTurns--\n }\n\n while (quarterTurns < 0) {\n ;[x, y] = [y, -x]\n quarterTurns++\n }\n\n if (opts.isFlipped) {\n y = -y\n }\n\n return vecToInsertionDirection({ x, y })\n}\n\nexport const transformSchematicElement = (\n elm: AnyCircuitElement,\n matrix: Matrix,\n) => {\n if (elm.type === \"schematic_component\") {\n // TODO handle rotation\n elm.center = applyToPoint(matrix, elm.center)\n } else if (elm.type === \"schematic_port\") {\n elm.center = applyToPoint(matrix, elm.center)\n\n if (elm.facing_direction) {\n elm.facing_direction = rotateDirection(\n elm.facing_direction,\n -(Math.atan2(matrix.b, matrix.a) / Math.PI) * 2,\n )\n }\n } else if (elm.type === \"schematic_text\") {\n elm.position = applyToPoint(matrix, elm.position)\n // } else if (elm.type === \"schematic_group\") {\n // elm.center = applyToPoint(matrix, elm.center)\n } else if (elm.type === \"schematic_trace\") {\n const anyElm = elm as any\n anyElm.route = (anyElm.route ?? []).map((rp: any) => {\n const tp = applyToPoint(matrix, rp) as { x: number; y: number }\n rp.x = tp.x\n rp.y = tp.y\n return rp\n })\n if (Array.isArray(anyElm.junctions)) {\n anyElm.junctions = anyElm.junctions.map((j: any) => {\n const tp = applyToPoint(matrix, j) as { x: number; y: number }\n j.x = tp.x\n j.y = tp.y\n return j\n })\n }\n if (Array.isArray(anyElm.edges)) {\n anyElm.edges = anyElm.edges.map((e: any) => {\n e.from = applyToPoint(matrix, e.from)\n e.to = applyToPoint(matrix, e.to)\n return e\n })\n }\n } else if (elm.type === \"schematic_box\") {\n const { x, y } = applyToPoint(matrix, { x: elm.x, y: elm.y })\n elm.x = x\n elm.y = y\n } else if (elm.type === \"schematic_line\") {\n const { x: x1, y: y1 } = applyToPoint(matrix, { x: elm.x1, y: elm.y1 })\n const { x: x2, y: y2 } = applyToPoint(matrix, { x: elm.x2, y: elm.y2 })\n elm.x1 = x1\n elm.y1 = y1\n elm.x2 = x2\n elm.y2 = y2\n }\n return elm\n}\n\nexport const transformSchematicElements = (\n elms: AnyCircuitElement[],\n matrix: Matrix,\n) => {\n return elms.map((elm) => transformSchematicElement(elm, matrix))\n}\n\nexport const transformPCBElement = (elm: AnyCircuitElement, matrix: Matrix) => {\n const tsr = decomposeTSR(matrix)\n const flipPadWidthHeight =\n Math.abs(getQuarterTurns(tsr.rotation.angle)) % 2 === 1\n const rotationDegrees = (tsr.rotation.angle / Math.PI) * 180\n const isFlipped = tsr.scale.sy < 0\n if (\n elm.type === \"pcb_plated_hole\" ||\n elm.type === \"pcb_hole\" ||\n elm.type === \"pcb_via\" ||\n elm.type === \"pcb_smtpad\" ||\n elm.type === \"pcb_solder_paste\" ||\n elm.type === \"pcb_port\"\n ) {\n const { x, y } = applyToPoint(matrix, {\n x: Number((elm as any).x),\n y: Number((elm as any).y),\n })\n ;(elm as any).x = x\n ;(elm as any).y = y\n\n // Handle polygon-shaped SMT pads with points array\n if (\n elm.type === \"pcb_smtpad\" &&\n elm.shape === \"polygon\" &&\n Array.isArray(elm.points)\n ) {\n elm.points = elm.points.map((point: any) => {\n const tp = applyToPoint(matrix, { x: point.x, y: point.y })\n return {\n x: tp.x,\n y: tp.y,\n }\n })\n }\n } else if (elm.type === \"pcb_keepout\" || elm.type === \"pcb_board\") {\n // TODO adjust size/rotation\n elm.center = applyToPoint(matrix, elm.center)\n } else if (\n elm.type === \"pcb_silkscreen_text\" ||\n elm.type === \"pcb_fabrication_note_text\" ||\n elm.type === \"pcb_note_text\"\n ) {\n elm.anchor_position = applyToPoint(matrix, elm.anchor_position)\n } else if (elm.type === \"pcb_copper_text\") {\n if (elm.anchor_position) {\n elm.anchor_position = applyToPoint(matrix, elm.anchor_position)\n }\n } else if (elm.type === \"pcb_courtyard_rect\") {\n elm.center = applyToPoint(matrix, elm.center)\n elm.ccw_rotation = ((elm.ccw_rotation ?? 0) + rotationDegrees) % 360\n } else if (\n elm.type === \"pcb_silkscreen_circle\" ||\n elm.type === \"pcb_silkscreen_rect\" ||\n elm.type === \"pcb_silkscreen_pill\" ||\n elm.type === \"pcb_silkscreen_oval\" ||\n elm.type === \"pcb_note_rect\" ||\n elm.type === \"pcb_courtyard_circle\"\n ) {\n elm.center = applyToPoint(matrix, elm.center)\n } else if (elm.type === \"pcb_component\") {\n elm.center = applyToPoint(matrix, elm.center)\n elm.rotation = elm.rotation + rotationDegrees\n elm.rotation = elm.rotation % 360\n if (elm.cable_insertion_center) {\n elm.cable_insertion_center = applyToPoint(\n matrix,\n elm.cable_insertion_center,\n )\n }\n elm.insertion_direction = transformInsertionDirection(\n elm.insertion_direction,\n {\n rotationDegrees,\n isFlipped,\n },\n )\n if (flipPadWidthHeight) {\n ;[elm.width, elm.height] = [elm.height, elm.width]\n }\n } else if (elm.type === \"pcb_courtyard_outline\") {\n elm.outline = elm.outline.map((p) => {\n const tp = applyToPoint(matrix, p) as { x: number; y: number }\n p.x = tp.x\n p.y = tp.y\n return p\n })\n } else if (elm.type === \"pcb_courtyard_polygon\") {\n elm.points = elm.points.map((p) => {\n const tp = applyToPoint(matrix, p) as { x: number; y: number }\n p.x = tp.x\n p.y = tp.y\n return p\n })\n } else if (elm.type === \"pcb_trace\") {\n elm.route = elm.route.map((rp) => {\n // \"through_pad\" route points describe a segment with start/end rather\n // than a single x/y position.\n if (!(\"x\" in rp)) {\n rp.start = applyToPoint(matrix, rp.start) as { x: number; y: number }\n rp.end = applyToPoint(matrix, rp.end) as { x: number; y: number }\n return rp\n }\n const tp = applyToPoint(matrix, rp) as { x: number; y: number }\n rp.x = tp.x\n rp.y = tp.y\n return rp\n })\n } else if (\n elm.type === \"pcb_silkscreen_path\" ||\n elm.type === \"pcb_trace_hint\" ||\n elm.type === \"pcb_fabrication_note_path\" ||\n elm.type === \"pcb_note_path\"\n ) {\n elm.route = elm.route.map((rp) => {\n const tp = applyToPoint(matrix, rp) as { x: number; y: number }\n rp.x = tp.x\n rp.y = tp.y\n return rp\n })\n } else if (\n elm.type === \"pcb_silkscreen_line\" ||\n elm.type === \"pcb_note_line\"\n ) {\n const p1 = { x: elm.x1, y: elm.y1 }\n const p2 = { x: elm.x2, y: elm.y2 }\n const p1t = applyToPoint(matrix, p1)\n const p2t = applyToPoint(matrix, p2)\n elm.x1 = p1t.x\n elm.y1 = p1t.y\n elm.x2 = p2t.x\n elm.y2 = p2t.y\n } else if (elm.type === \"cad_component\") {\n const newPos = applyToPoint(matrix, {\n x: elm.position.x,\n y: elm.position.y,\n })\n elm.position.x = newPos.x\n elm.position.y = newPos.y\n }\n return elm\n}\n\nexport const transformPCBElements = (\n elms: AnyCircuitElement[],\n matrix: Matrix,\n) => {\n const tsr = decomposeTSR(matrix)\n const quarterTurns = getQuarterTurns(tsr.rotation.angle)\n const flipPadWidthHeight = Math.abs(quarterTurns) % 2 === 1\n let transformedElms = elms.map((elm) => transformPCBElement(elm, matrix))\n if (flipPadWidthHeight) {\n transformedElms = transformedElms.map((elm) => {\n if (\n (elm.type === \"pcb_smtpad\" || elm.type === \"pcb_solder_paste\") &&\n (elm.shape === \"rect\" || elm.shape === \"pill\")\n ) {\n ;[elm.width, elm.height] = [elm.height, elm.width]\n }\n return elm\n })\n }\n return transformedElms\n}\n","export const directionToVec = (direction: \"up\" | \"down\" | \"left\" | \"right\") => {\n if (direction === \"up\") return { x: 0, y: 1 }\n else if (direction === \"down\") return { x: 0, y: -1 }\n else if (direction === \"left\") return { x: -1, y: 0 }\n else if (direction === \"right\") return { x: 1, y: 0 }\n else throw new Error(\"Invalid direction\")\n}\n\nexport const vecToDirection = ({ x, y }: { x: number; y: number }) => {\n if (x > y) y = 0\n if (y > x) x = 0\n if (x > 0 && y === 0) return \"right\"\n else if (x < 0 && y === 0) return \"left\"\n else if (x === 0 && y > 0) return \"up\"\n else if (x === 0 && y < 0) return \"down\"\n else throw new Error(`Invalid vector for direction conversion (${x}, ${y})`)\n}\n\nexport const rotateClockwise = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n) => {\n if (direction === \"up\") return \"right\"\n else if (direction === \"right\") return \"down\"\n else if (direction === \"down\") return \"left\"\n else if (direction === \"left\") return \"up\"\n throw new Error(`Invalid direction: ${direction}`)\n}\n\nexport const rotateCounterClockwise = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n) => {\n if (direction === \"up\") return \"left\"\n else if (direction === \"left\") return \"down\"\n else if (direction === \"down\") return \"right\"\n else if (direction === \"right\") return \"up\"\n throw new Error(`Invalid direction: ${direction}`)\n}\n\nexport const rotateDirection = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n num90DegreeClockwiseTurns: number,\n) => {\n while (num90DegreeClockwiseTurns > 0) {\n direction = rotateClockwise(direction)\n num90DegreeClockwiseTurns--\n }\n while (num90DegreeClockwiseTurns < 0) {\n direction = rotateCounterClockwise(direction)\n num90DegreeClockwiseTurns++\n }\n return direction\n}\n\nexport const oppositeDirection = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n) => {\n if (direction === \"up\") return \"down\"\n else if (direction === \"down\") return \"up\"\n else if (direction === \"left\") return \"right\"\n else if (direction === \"right\") return \"left\"\n throw new Error(`Invalid direction: ${direction}`)\n}\n\nexport const oppositeSide = (\n sideOrDir: \"up\" | \"down\" | \"top\" | \"bottom\" | \"left\" | \"right\",\n) => {\n if (sideOrDir === \"top\" || sideOrDir === \"up\") return \"bottom\"\n else if (sideOrDir === \"bottom\" || sideOrDir === \"down\") return \"top\"\n else if (sideOrDir === \"left\") return \"right\"\n else if (sideOrDir === \"right\") return \"left\"\n throw new Error(`Invalid sideOrDir: ${sideOrDir}`)\n}\n","import * as parsel from \"parsel-js\"\nimport { convertAbbrToType } from \"./convert-abbreviation-to-soup-element-type\"\nimport type { AnyCircuitElement } from \"circuit-json\"\n\nconst filterByType = (\n elements: AnyCircuitElement[],\n type: string,\n): AnyCircuitElement[] => {\n type = convertAbbrToType(type)\n return elements.filter(\n (elm) => (\"ftype\" in elm && elm.ftype === type) || elm.type === type,\n )\n}\n\n/**\n * Filter elements to match the selector, e.g. to access the left port of a\n * resistor you can do \".R1 > port.left\"\n */\nexport const applySelector = (\n elements: AnyCircuitElement[],\n selectorRaw: string,\n): AnyCircuitElement[] => {\n const selectorAST = parsel.parse(selectorRaw)\n return applySelectorAST(elements, selectorAST!)\n}\n\nconst doesElmMatchClassName = (elm: AnyCircuitElement, className: string) =>\n (\"name\" in elm && elm.name === className) ||\n (\"port_hints\" in elm && elm.port_hints?.includes(className))\n\nexport const applySelectorAST = (\n elements: AnyCircuitElement[],\n selectorAST: parsel.AST,\n): AnyCircuitElement[] => {\n switch (selectorAST.type) {\n case \"complex\": {\n switch (selectorAST.combinator) {\n case \" \": // TODO technically should do a deep search\n case \">\": {\n const { left, right } = selectorAST\n if (left.type === \"class\" || left.type === \"type\") {\n // TODO should also check if content matches any element tags\n let matchElms: AnyCircuitElement[]\n if (left.type === \"class\") {\n matchElms = elements.filter((elm) =>\n doesElmMatchClassName(elm, left.name),\n )\n } else if (left.type === \"type\") {\n matchElms = filterByType(elements, left.name)\n } else {\n matchElms = []\n }\n\n const childrenOfMatchingElms = matchElms.flatMap((matchElm) =>\n elements.filter(\n (elm: any) =>\n elm[`${matchElm.type}_id`] ===\n (matchElm as any)[`${matchElm.type}_id`] &&\n elm !== matchElm,\n ),\n )\n return applySelectorAST(childrenOfMatchingElms, right)\n } else {\n throw new Error(`unsupported selector type \"${left.type}\" `)\n }\n }\n default: {\n throw new Error(\n `Couldn't apply selector AST for complex combinator \"${selectorAST.combinator}\"`,\n )\n }\n }\n return []\n }\n case \"compound\": {\n const conditionsToMatch = selectorAST.list.map((part) => {\n switch (part.type) {\n case \"class\": {\n return (elm: any) => doesElmMatchClassName(elm, part.name)\n }\n case \"type\": {\n const name = convertAbbrToType(part.name)\n return (elm: any) => elm.type === name\n }\n }\n })\n\n return elements.filter((elm) =>\n conditionsToMatch.every((condFn) => condFn?.(elm)),\n )\n }\n case \"type\": {\n return filterByType(elements, selectorAST.name) as AnyCircuitElement[]\n }\n case \"class\": {\n return elements.filter((elm) =>\n doesElmMatchClassName(elm, selectorAST.name),\n )\n }\n default: {\n throw new Error(\n `Couldn't apply selector AST for type: \"${\n selectorAST.type\n }\" ${JSON.stringify(selectorAST, null, \" \")}`,\n )\n }\n }\n}\n","export const convertAbbrToType = (abbr: string): string => {\n switch (abbr) {\n case \"port\":\n return \"source_port\"\n case \"net\":\n return \"source_net\"\n case \"power\":\n return \"simple_power_source\"\n case \"silkscreenpath\":\n return \"pcb_silkscreen_path\"\n }\n return abbr\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\n\nexport const getElementId = (elm: AnyCircuitElement): string => {\n const type = elm.type\n const id = (elm as any)[`${type}_id`]\n return id\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { getElementId } from \"./get-element-id\"\n\nexport const getElementById = (\n soup: AnyCircuitElement[],\n id: string,\n): AnyCircuitElement | null => {\n return soup.find((elm) => getElementId(elm) === id) ?? null\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { cju } from \"../cju\"\n\nexport const getReadableNameForPcbPort = (\n soup: AnyCircuitElement[],\n pcb_port_id: string,\n): string => {\n const pcbPort = cju(soup).pcb_port.get(pcb_port_id)\n if (!pcbPort) {\n return `pcb_port[#${pcb_port_id}]`\n }\n\n // Get the component information\n const pcbComponent = pcbPort.pcb_component_id\n ? cju(soup).pcb_component.get(pcbPort.pcb_component_id)\n : undefined\n\n if (!pcbComponent) {\n return `pcb_port[#${pcb_port_id}]`\n }\n\n // Get the source component information\n const sourceComponent = cju(soup).source_component.get(\n pcbComponent.source_component_id,\n )\n\n if (!sourceComponent) {\n return `pcb_port[#${pcb_port_id}]`\n }\n\n // Get the source port information\n const sourcePort = cju(soup).source_port.get(pcbPort.source_port_id)\n\n if (!sourcePort) {\n return `pcb_port[#${pcb_port_id}]`\n }\n\n // Determine the pad number or hint\n let padIdentifier: string\n if (sourcePort?.port_hints && sourcePort.port_hints.length > 0) {\n padIdentifier = sourcePort.port_hints[0]!\n } else if (sourcePort.port_hints && sourcePort.port_hints.length > 0) {\n padIdentifier = sourcePort.port_hints[0]!\n } else {\n padIdentifier = pcb_port_id\n }\n\n return `pcb_port[.${sourceComponent.name} > .${padIdentifier}]`\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { cju } from \"../cju\"\nimport { getReadableNameForPcbPort } from \"./get-readable-name-for-pcb-port\"\n\nexport function getReadableNameForPcbSmtpad(\n soup: AnyCircuitElement[],\n pcb_smtpad_id: string,\n): string {\n // Find the pcb_smtpad object\n const pcbSmtpad = cju(soup).pcb_smtpad.get(pcb_smtpad_id)\n\n if (!pcbSmtpad || !pcbSmtpad.pcb_port_id) {\n return `smtpad[${pcb_smtpad_id}]`\n }\n\n return getReadableNameForPcbPort(soup, pcbSmtpad.pcb_port_id)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { cju } from \"../cju\"\n\nexport function getReadableNameForPcbTrace(\n soup: AnyCircuitElement[],\n pcb_trace_id: string,\n) {\n // Find the pcb_trace object\n const pcbTrace = cju(soup).pcb_trace.get(pcb_trace_id)\n\n if (!pcbTrace) {\n return `trace[${pcb_trace_id}]`\n }\n\n // Get the connected ports\n const connectedPcbPortIds: string[] = pcbTrace.route\n .flatMap((point: any) => [point.start_pcb_port_id, point.end_pcb_port_id])\n .filter(Boolean)\n\n if (connectedPcbPortIds.length === 0) {\n return `trace[${pcb_trace_id}]`\n }\n\n // Function to get component name and port hint\n function getComponentAndPortInfo(pcb_port_id: string) {\n const pcbPort = cju(soup).pcb_port.get(pcb_port_id)\n if (!pcbPort) return null\n\n const pcbComponent = pcbPort.pcb_component_id\n ? cju(soup).pcb_component.get(pcbPort.pcb_component_id)\n : undefined\n if (!pcbComponent) return null\n const sourceComponent = cju(soup).source_component.get(\n pcbComponent.source_component_id,\n )\n if (!sourceComponent) return null\n\n const sourcePort = cju(soup).source_port.get(pcbPort.source_port_id)\n const portHint = sourcePort?.port_hints ? sourcePort.port_hints[1] : \"\"\n\n return {\n componentName: sourceComponent.name,\n portHint: portHint,\n }\n }\n\n // Generate the readable selector\n const selectorParts = connectedPcbPortIds.map((portId) => {\n const info = getComponentAndPortInfo(portId)\n if (info) {\n return `.${info.componentName} > port.${info.portHint}`\n }\n return `port[${portId}]`\n })\n\n return `trace[${selectorParts.join(\", \")}]`\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { getElementById } from \"../get-element-by-id\"\nimport { getElementId } from \"../get-element-id\"\nimport { getReadableNameForPcbPort } from \"./get-readable-name-for-pcb-port\"\nimport { getReadableNameForPcbSmtpad } from \"./get-readable-name-for-pcb-smtpad\"\nimport { getReadableNameForPcbTrace } from \"./get-readable-name-for-pcb-trace\"\n\nexport const getReadableNameForElement = (\n soup: AnyCircuitElement[],\n elm: AnyCircuitElement | string,\n): string => {\n if (typeof elm === \"string\") {\n const elmObj = getElementById(soup, elm)\n if (!elmObj) `unknown (could not find element with id ${elm})`\n return getReadableNameForElement(soup, elmObj as any)\n }\n switch (elm.type) {\n case \"pcb_port\":\n return getReadableNameForPcbPort(soup, elm.pcb_port_id)\n case \"pcb_smtpad\":\n return getReadableNameForPcbSmtpad(soup, elm.pcb_smtpad_id)\n case \"pcb_trace\":\n return getReadableNameForPcbTrace(soup, elm.pcb_trace_id)\n case \"source_component\":\n return `source_component[${elm.name}]`\n default:\n return `${elm.type}[#${getElementId(elm)}]`\n }\n}\n\nexport {\n getReadableNameForPcbPort,\n getReadableNameForPcbSmtpad,\n getReadableNameForPcbTrace,\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\n\nexport interface PcbBounds {\n minX: number\n minY: number\n maxX: number\n maxY: number\n}\n\nconst mergeBounds = (\n currentBounds: PcbBounds,\n nextBounds: PcbBounds,\n): PcbBounds => ({\n minX: Math.min(currentBounds.minX, nextBounds.minX),\n minY: Math.min(currentBounds.minY, nextBounds.minY),\n maxX: Math.max(currentBounds.maxX, nextBounds.maxX),\n maxY: Math.max(currentBounds.maxY, nextBounds.maxY),\n})\n\nconst getCircleBounds = (x: number, y: number, diameter: number) => {\n const radius = diameter / 2\n return {\n minX: x - radius,\n minY: y - radius,\n maxX: x + radius,\n maxY: y + radius,\n }\n}\n\nconst getRotatedRectBounds = (\n x: number,\n y: number,\n width: number,\n height: number,\n rotationDegrees: number,\n) => {\n const halfWidth = width / 2\n const halfHeight = height / 2\n const theta = (rotationDegrees * Math.PI) / 180\n const cosTheta = Math.cos(theta)\n const sinTheta = Math.sin(theta)\n\n const corners = [\n { x: -halfWidth, y: -halfHeight },\n { x: halfWidth, y: -halfHeight },\n { x: halfWidth, y: halfHeight },\n { x: -halfWidth, y: halfHeight },\n ].map((corner) => ({\n x: x + corner.x * cosTheta - corner.y * sinTheta,\n y: y + corner.x * sinTheta + corner.y * cosTheta,\n }))\n\n return {\n minX: Math.min(...corners.map((corner) => corner.x)),\n minY: Math.min(...corners.map((corner) => corner.y)),\n maxX: Math.max(...corners.map((corner) => corner.x)),\n maxY: Math.max(...corners.map((corner) => corner.y)),\n }\n}\n\nconst getRotatedOvalBounds = (\n x: number,\n y: number,\n width: number,\n height: number,\n rotationDegrees: number,\n) => {\n const radiusX = width / 2\n const radiusY = height / 2\n const theta = (rotationDegrees * Math.PI) / 180\n const cosTheta = Math.cos(theta)\n const sinTheta = Math.sin(theta)\n const halfWidth = Math.hypot(radiusX * cosTheta, radiusY * sinTheta)\n const halfHeight = Math.hypot(radiusX * sinTheta, radiusY * cosTheta)\n\n return {\n minX: x - halfWidth,\n minY: y - halfHeight,\n maxX: x + halfWidth,\n maxY: y + halfHeight,\n }\n}\n\nconst getRotatedPillBounds = (\n x: number,\n y: number,\n width: number,\n height: number,\n rotationDegrees: number,\n) => {\n const radius = Math.min(width, height) / 2\n const halfLineLength = Math.max(width, height) / 2 - radius\n const theta = (rotationDegrees * Math.PI) / 180\n const axis =\n width >= height ? { x: halfLineLength, y: 0 } : { x: 0, y: halfLineLength }\n const rotatedAxis = {\n x: axis.x * Math.cos(theta) - axis.y * Math.sin(theta),\n y: axis.x * Math.sin(theta) + axis.y * Math.cos(theta),\n }\n const halfWidth = Math.abs(rotatedAxis.x) + radius\n const halfHeight = Math.abs(rotatedAxis.y) + radius\n\n return {\n minX: x - halfWidth,\n minY: y - halfHeight,\n maxX: x + halfWidth,\n maxY: y + halfHeight,\n }\n}\n\nconst getBoundsFromPoints = (\n points: Array<{ x: number; y: number }>,\n): PcbBounds | null => {\n if (points.length === 0) return null\n\n return {\n minX: Math.min(...points.map((point) => point.x)),\n minY: Math.min(...points.map((point) => point.y)),\n maxX: Math.max(...points.map((point) => point.x)),\n maxY: Math.max(...points.map((point) => point.y)),\n }\n}\n\nconst getRoutePoints = (route: unknown): Array<{ x: number; y: number }> => {\n if (!Array.isArray(route)) return []\n\n return route.flatMap((point): Array<{ x: number; y: number }> => {\n if (!point || typeof point !== \"object\") return []\n if (\n \"x\" in point &&\n \"y\" in point &&\n typeof point.x === \"number\" &&\n typeof point.y === \"number\"\n ) {\n return [{ x: point.x, y: point.y }]\n }\n\n if (\"start\" in point && \"end\" in point) {\n const positions = [point.start, point.end]\n return positions.filter(\n (position): position is { x: number; y: number } =>\n Boolean(\n position &&\n typeof position === \"object\" &&\n \"x\" in position &&\n \"y\" in position &&\n typeof position.x === \"number\" &&\n typeof position.y === \"number\",\n ),\n )\n }\n\n return []\n })\n}\n\n/** Returns the axis-aligned bounds of one drawable PCB element. */\nexport const getPcbElementBounds = (\n elm: AnyCircuitElement,\n): PcbBounds | null => {\n if (!elm.type.startsWith(\"pcb_\")) return null\n\n if (\n elm.type === \"pcb_smtpad\" &&\n elm.shape === \"polygon\" &&\n Array.isArray(elm.points)\n ) {\n return getBoundsFromPoints(elm.points)\n }\n\n if (elm.type === \"pcb_hole\" && elm.hole_shape === \"circle\") {\n return getCircleBounds(elm.x, elm.y, elm.hole_diameter)\n }\n\n if (elm.type === \"pcb_plated_hole\") {\n let platedHoleBounds: PcbBounds | undefined\n\n if (\"outer_diameter\" in elm && typeof elm.outer_diameter === \"number\") {\n platedHoleBounds = getCircleBounds(elm.x, elm.y, elm.outer_diameter)\n } else if (\n \"hole_diameter\" in elm &&\n typeof elm.hole_diameter === \"number\"\n ) {\n platedHoleBounds = getCircleBounds(elm.x, elm.y, elm.hole_diameter)\n }\n\n if (\n (elm.shape === \"oval\" || elm.shape === \"pill\") &&\n typeof elm.outer_width === \"number\" &&\n typeof elm.outer_height === \"number\"\n ) {\n const getOuterBounds =\n elm.shape === \"pill\" ? getRotatedPillBounds : getRotatedOvalBounds\n platedHoleBounds = getOuterBounds(\n elm.x,\n elm.y,\n elm.outer_width,\n elm.outer_height,\n elm.ccw_rotation ?? 0,\n )\n }\n\n if (\n \"rect_pad_width\" in elm &&\n typeof elm.rect_pad_width === \"number\" &&\n \"rect_pad_height\" in elm &&\n typeof elm.rect_pad_height === \"number\"\n ) {\n const rectBounds = getRotatedRectBounds(\n elm.x,\n elm.y,\n elm.rect_pad_width,\n elm.rect_pad_height,\n \"rect_ccw_rotation\" in elm ? (elm.rect_ccw_rotation ?? 0) : 0,\n )\n platedHoleBounds = platedHoleBounds\n ? mergeBounds(platedHoleBounds, rectBounds)\n : rectBounds\n }\n\n if (\"hole_diameter\" in elm && typeof elm.hole_diameter === \"number\") {\n const drillBounds = getCircleBounds(\n elm.x +\n (\"hole_offset_x\" in elm ? ((elm.hole_offset_x as number) ?? 0) : 0),\n elm.y +\n (\"hole_offset_y\" in elm ? ((elm.hole_offset_y as number) ?? 0) : 0),\n elm.hole_diameter,\n )\n platedHoleBounds = platedHoleBounds\n ? mergeBounds(platedHoleBounds, drillBounds)\n : drillBounds\n }\n\n if (platedHoleBounds) return platedHoleBounds\n }\n\n const elementRecord = elm as unknown as Record<string, unknown>\n const routeBounds = getBoundsFromPoints(getRoutePoints(elementRecord.route))\n if (routeBounds) return routeBounds\n\n const outlineBounds = getBoundsFromPoints(\n getRoutePoints(elementRecord.outline),\n )\n if (outlineBounds) return outlineBounds\n\n const pointsBounds = getBoundsFromPoints(getRoutePoints(elementRecord.points))\n if (pointsBounds) return pointsBounds\n\n let centerX: number | undefined\n let centerY: number | undefined\n\n let width: number | undefined\n let height: number | undefined\n\n if (\"x\" in elm && \"y\" in elm) {\n centerX = Number(elm.x)\n centerY = Number(elm.y)\n }\n\n if (\"outer_diameter\" in elm) {\n width = Number(elm.outer_diameter)\n height = Number(elm.outer_diameter)\n }\n\n if (\"width\" in elm) {\n width = Number(elm.width)\n }\n\n if (\"height\" in elm) {\n height = Number(elm.height)\n }\n\n if (\n \"center\" in elm &&\n elm.center &&\n typeof elm.center === \"object\" &&\n \"x\" in elm.center &&\n \"y\" in elm.center\n ) {\n centerX = Number(elm.center.x)\n centerY = Number(elm.center.y)\n }\n\n let rotation = 0\n if (\"rotation\" in elm && typeof elm.rotation === \"number\") {\n rotation = elm.rotation\n }\n if (\"ccw_rotation\" in elm && typeof elm.ccw_rotation === \"number\") {\n rotation = elm.ccw_rotation\n }\n\n if (centerX !== undefined && centerY !== undefined) {\n if (width !== undefined && height !== undefined) {\n return rotation\n ? getRotatedRectBounds(centerX, centerY, width, height, rotation)\n : {\n minX: centerX - width / 2,\n minY: centerY - height / 2,\n maxX: centerX + width / 2,\n maxY: centerY + height / 2,\n }\n }\n\n if (\"radius\" in elm && typeof elm.radius === \"number\") {\n return getCircleBounds(centerX, centerY, elm.radius * 2)\n }\n\n return { minX: centerX, minY: centerY, maxX: centerX, maxY: centerY }\n }\n\n const anchoredPoint = [elementRecord.anchor_position, elementRecord.position]\n .filter((position): position is { x: number; y: number } =>\n Boolean(\n position &&\n typeof position === \"object\" &&\n \"x\" in position &&\n \"y\" in position &&\n typeof position.x === \"number\" &&\n typeof position.y === \"number\",\n ),\n )\n .at(0)\n\n return anchoredPoint\n ? {\n minX: anchoredPoint.x,\n minY: anchoredPoint.y,\n maxX: anchoredPoint.x,\n maxY: anchoredPoint.y,\n }\n : null\n}\n\nexport const getBoundsOfPcbElements = (\n elements: AnyCircuitElement[],\n): PcbBounds => {\n let bounds: PcbBounds = {\n minX: Number.POSITIVE_INFINITY,\n minY: Number.POSITIVE_INFINITY,\n maxX: Number.NEGATIVE_INFINITY,\n maxY: Number.NEGATIVE_INFINITY,\n }\n\n for (const element of elements) {\n const elementBounds = getPcbElementBounds(element)\n if (elementBounds) bounds = mergeBounds(bounds, elementBounds)\n }\n\n return bounds\n}\n\n/** Returns PCB elements whose axis-aligned bounds intersect the given bounds. */\nexport const getPcbElementsWithinBounds = (\n elements: AnyCircuitElement[],\n bounds: PcbBounds,\n): AnyCircuitElement[] =>\n elements.filter((element) => {\n const elementBounds = getPcbElementBounds(element)\n if (!elementBounds) return false\n\n return (\n elementBounds.minX <= bounds.maxX &&\n elementBounds.maxX >= bounds.minX &&\n elementBounds.minY <= bounds.maxY &&\n elementBounds.maxY >= bounds.minY\n )\n })\n","import type { PcbBoard } from \"circuit-json\"\n\nexport interface BoardBounds {\n minX: number\n minY: number\n maxX: number\n maxY: number\n width: number\n height: number\n center: {\n x: number\n y: number\n }\n}\n\nexport const getBoardBounds = (board: PcbBoard): BoardBounds => {\n if (board.width && board.height && board.center) {\n const halfWidth = board.width / 2\n const halfHeight = board.height / 2\n\n return {\n minX: board.center.x - halfWidth,\n minY: board.center.y - halfHeight,\n maxX: board.center.x + halfWidth,\n maxY: board.center.y + halfHeight,\n width: board.width,\n height: board.height,\n center: {\n x: board.center.x,\n y: board.center.y,\n },\n }\n }\n\n if (!board.outline || board.outline.length === 0) {\n throw new Error(\n \"Unable to compute board bounds. pcb_board must include width/height/center or a non-empty outline.\",\n )\n }\n\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n for (const point of board.outline) {\n minX = Math.min(minX, point.x)\n minY = Math.min(minY, point.y)\n maxX = Math.max(maxX, point.x)\n maxY = Math.max(maxY, point.y)\n }\n\n const width = maxX - minX\n const height = maxY - minY\n\n return {\n minX,\n minY,\n maxX,\n maxY,\n width,\n height,\n center: {\n x: minX + width / 2,\n y: minY + height / 2,\n },\n }\n}\n","import type {\n SchematicComponent,\n SchematicNetLabel,\n SchematicTrace,\n} from \"circuit-json\"\n\nexport type SchematicElementWithBounds =\n | SchematicComponent\n | SchematicNetLabel\n | SchematicTrace\n\nexport interface SchematicElementBounds {\n minX: number\n minY: number\n maxX: number\n maxY: number\n width: number\n height: number\n center: {\n x: number\n y: number\n }\n}\n\nconst SCHEMATIC_TRACE_WIDTH = 0.1\nconst SCHEMATIC_NET_LABEL_FONT_SIZE = 0.18\nconst SCHEMATIC_NET_LABEL_HEIGHT = 0.2\n\nconst createBounds = ({\n minX,\n minY,\n maxX,\n maxY,\n}: {\n minX: number\n minY: number\n maxX: number\n maxY: number\n}): SchematicElementBounds => {\n const width = maxX - minX\n const height = maxY - minY\n\n return {\n minX,\n minY,\n maxX,\n maxY,\n width,\n height,\n center: {\n x: minX + width / 2,\n y: minY + height / 2,\n },\n }\n}\n\nconst getSchematicNetLabelTextWidth = (text: string): number => {\n const characterWidth = 0.12 * (SCHEMATIC_NET_LABEL_FONT_SIZE / 0.18)\n const horizontalPadding = 0.12 * (SCHEMATIC_NET_LABEL_FONT_SIZE / 0.18)\n\n return text.length * characterWidth + horizontalPadding\n}\n\nconst getSchematicNetLabelBounds = (\n netLabel: SchematicNetLabel,\n): SchematicElementBounds => {\n const labelLength = getSchematicNetLabelTextWidth(netLabel.text)\n const anchor = netLabel.anchor_position\n\n if (!anchor) {\n const isVertical =\n netLabel.anchor_side === \"top\" || netLabel.anchor_side === \"bottom\"\n const width = isVertical ? SCHEMATIC_NET_LABEL_HEIGHT : labelLength\n const height = isVertical ? labelLength : SCHEMATIC_NET_LABEL_HEIGHT\n\n return createBounds({\n minX: netLabel.center.x - width / 2,\n minY: netLabel.center.y - height / 2,\n maxX: netLabel.center.x + width / 2,\n maxY: netLabel.center.y + height / 2,\n })\n }\n\n switch (netLabel.anchor_side) {\n case \"left\":\n return createBounds({\n minX: anchor.x,\n minY: anchor.y - SCHEMATIC_NET_LABEL_HEIGHT / 2,\n maxX: anchor.x + labelLength,\n maxY: anchor.y + SCHEMATIC_NET_LABEL_HEIGHT / 2,\n })\n case \"right\":\n return createBounds({\n minX: anchor.x - labelLength,\n minY: anchor.y - SCHEMATIC_NET_LABEL_HEIGHT / 2,\n maxX: anchor.x,\n maxY: anchor.y + SCHEMATIC_NET_LABEL_HEIGHT / 2,\n })\n case \"top\":\n return createBounds({\n minX: anchor.x - SCHEMATIC_NET_LABEL_HEIGHT / 2,\n minY: anchor.y - labelLength,\n maxX: anchor.x + SCHEMATIC_NET_LABEL_HEIGHT / 2,\n maxY: anchor.y,\n })\n case \"bottom\":\n return createBounds({\n minX: anchor.x - SCHEMATIC_NET_LABEL_HEIGHT / 2,\n minY: anchor.y,\n maxX: anchor.x + SCHEMATIC_NET_LABEL_HEIGHT / 2,\n maxY: anchor.y + labelLength,\n })\n }\n}\n\n/**\n * Returns the axis-aligned bounds of a schematic component, net label, or\n * trace. Trace bounds include the rendered trace width. An empty trace has no\n * drawable geometry and returns null.\n */\nexport const getSchematicElementBounds = (\n element: SchematicElementWithBounds,\n): SchematicElementBounds | null => {\n if (element.type === \"schematic_component\") {\n return createBounds({\n minX: element.center.x - element.size.width / 2,\n minY: element.center.y - element.size.height / 2,\n maxX: element.center.x + element.size.width / 2,\n maxY: element.center.y + element.size.height / 2,\n })\n }\n\n if (element.type === \"schematic_net_label\") {\n return getSchematicNetLabelBounds(element)\n }\n\n const points = [\n ...element.edges.flatMap((edge) => [edge.from, edge.to]),\n ...element.junctions,\n ]\n if (points.length === 0) return null\n\n const halfTraceWidth = SCHEMATIC_TRACE_WIDTH / 2\n return createBounds({\n minX: Math.min(...points.map((point) => point.x)) - halfTraceWidth,\n minY: Math.min(...points.map((point) => point.y)) - halfTraceWidth,\n maxX: Math.max(...points.map((point) => point.x)) + halfTraceWidth,\n maxY: Math.max(...points.map((point) => point.y)) + halfTraceWidth,\n })\n}\n","export function stringHash(str: string) {\n let hash = 0\n if (str.length == 0) return hash\n for (var i = 0; i < str.length; i++) {\n var char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32bit integer\n }\n return Math.abs(hash)\n}\n","import { stringHash } from \"./string-hash\"\n\nexport type LayoutDebugObject = {\n x: number\n y: number\n width: number\n height: number\n bg_color: string\n title: string\n content: Object\n secondary?: boolean\n}\n\n/**\n * Vendored from \"nice-color-palettes\" package\n */\nconst nice_color_palettes = [\n [\"#69d2e7\", \"#a7dbd8\", \"#e0e4cc\", \"#f38630\", \"#fa6900\"],\n [\"#fe4365\", \"#fc9d9a\", \"#f9cdad\", \"#c8c8a9\", \"#83af9b\"],\n [\"#ecd078\", \"#d95b43\", \"#c02942\", \"#542437\", \"#53777a\"],\n [\"#556270\", \"#4ecdc4\", \"#c7f464\", \"#ff6b6b\", \"#c44d58\"],\n [\"#774f38\", \"#e08e79\", \"#f1d4af\", \"#ece5ce\", \"#c5e0dc\"],\n [\"#e8ddcb\", \"#cdb380\", \"#036564\", \"#033649\", \"#031634\"],\n [\"#490a3d\", \"#bd1550\", \"#e97f02\", \"#f8ca00\", \"#8a9b0f\"],\n [\"#594f4f\", \"#547980\", \"#45ada8\", \"#9de0ad\", \"#e5fcc2\"],\n [\"#00a0b0\", \"#6a4a3c\", \"#cc333f\", \"#eb6841\", \"#edc951\"],\n [\"#e94e77\", \"#d68189\", \"#c6a49a\", \"#c6e5d9\", \"#f4ead5\"],\n [\"#3fb8af\", \"#7fc7af\", \"#dad8a7\", \"#ff9e9d\", \"#ff3d7f\"],\n [\"#d9ceb2\", \"#948c75\", \"#d5ded9\", \"#7a6a53\", \"#99b2b7\"],\n [\"#ffffff\", \"#cbe86b\", \"#f2e9e1\", \"#1c140d\", \"#cbe86b\"],\n [\"#efffcd\", \"#dce9be\", \"#555152\", \"#2e2633\", \"#99173c\"],\n [\"#343838\", \"#005f6b\", \"#008c9e\", \"#00b4cc\", \"#00dffc\"],\n [\"#413e4a\", \"#73626e\", \"#b38184\", \"#f0b49e\", \"#f7e4be\"],\n [\"#ff4e50\", \"#fc913a\", \"#f9d423\", \"#ede574\", \"#e1f5c4\"],\n [\"#99b898\", \"#fecea8\", \"#ff847c\", \"#e84a5f\", \"#2a363b\"],\n [\"#655643\", \"#80bca3\", \"#f6f7bd\", \"#e6ac27\", \"#bf4d28\"],\n [\"#00a8c6\", \"#40c0cb\", \"#f9f2e7\", \"#aee239\", \"#8fbe00\"],\n [\"#351330\", \"#424254\", \"#64908a\", \"#e8caa4\", \"#cc2a41\"],\n [\"#554236\", \"#f77825\", \"#d3ce3d\", \"#f1efa5\", \"#60b99a\"],\n [\"#5d4157\", \"#838689\", \"#a8caba\", \"#cad7b2\", \"#ebe3aa\"],\n [\"#8c2318\", \"#5e8c6a\", \"#88a65e\", \"#bfb35a\", \"#f2c45a\"],\n [\"#fad089\", \"#ff9c5b\", \"#f5634a\", \"#ed303c\", \"#3b8183\"],\n [\"#ff4242\", \"#f4fad2\", \"#d4ee5e\", \"#e1edb9\", \"#f0f2eb\"],\n [\"#f8b195\", \"#f67280\", \"#c06c84\", \"#6c5b7b\", \"#355c7d\"],\n [\"#d1e751\", \"#ffffff\", \"#000000\", \"#4dbce9\", \"#26ade4\"],\n [\"#1b676b\", \"#519548\", \"#88c425\", \"#bef202\", \"#eafde6\"],\n [\"#5e412f\", \"#fcebb6\", \"#78c0a8\", \"#f07818\", \"#f0a830\"],\n [\"#bcbdac\", \"#cfbe27\", \"#f27435\", \"#f02475\", \"#3b2d38\"],\n [\"#452632\", \"#91204d\", \"#e4844a\", \"#e8bf56\", \"#e2f7ce\"],\n [\"#eee6ab\", \"#c5bc8e\", \"#696758\", \"#45484b\", \"#36393b\"],\n [\"#f0d8a8\", \"#3d1c00\", \"#86b8b1\", \"#f2d694\", \"#fa2a00\"],\n [\"#2a044a\", \"#0b2e59\", \"#0d6759\", \"#7ab317\", \"#a0c55f\"],\n [\"#f04155\", \"#ff823a\", \"#f2f26f\", \"#fff7bd\", \"#95cfb7\"],\n [\"#b9d7d9\", \"#668284\", \"#2a2829\", \"#493736\", \"#7b3b3b\"],\n [\"#bbbb88\", \"#ccc68d\", \"#eedd99\", \"#eec290\", \"#eeaa88\"],\n [\"#b3cc57\", \"#ecf081\", \"#ffbe40\", \"#ef746f\", \"#ab3e5b\"],\n [\"#a3a948\", \"#edb92e\", \"#f85931\", \"#ce1836\", \"#009989\"],\n [\"#300030\", \"#480048\", \"#601848\", \"#c04848\", \"#f07241\"],\n [\"#67917a\", \"#170409\", \"#b8af03\", \"#ccbf82\", \"#e33258\"],\n [\"#aab3ab\", \"#c4cbb7\", \"#ebefc9\", \"#eee0b7\", \"#e8caaf\"],\n [\"#e8d5b7\", \"#0e2430\", \"#fc3a51\", \"#f5b349\", \"#e8d5b9\"],\n [\"#ab526b\", \"#bca297\", \"#c5ceae\", \"#f0e2a4\", \"#f4ebc3\"],\n [\"#607848\", \"#789048\", \"#c0d860\", \"#f0f0d8\", \"#604848\"],\n [\"#b6d8c0\", \"#c8d9bf\", \"#dadabd\", \"#ecdbbc\", \"#fedcba\"],\n [\"#a8e6ce\", \"#dcedc2\", \"#ffd3b5\", \"#ffaaa6\", \"#ff8c94\"],\n [\"#3e4147\", \"#fffedf\", \"#dfba69\", \"#5a2e2e\", \"#2a2c31\"],\n [\"#fc354c\", \"#29221f\", \"#13747d\", \"#0abfbc\", \"#fcf7c5\"],\n [\"#cc0c39\", \"#e6781e\", \"#c8cf02\", \"#f8fcc1\", \"#1693a7\"],\n [\"#1c2130\", \"#028f76\", \"#b3e099\", \"#ffeaad\", \"#d14334\"],\n [\"#a7c5bd\", \"#e5ddcb\", \"#eb7b59\", \"#cf4647\", \"#524656\"],\n [\"#dad6ca\", \"#1bb0ce\", \"#4f8699\", \"#6a5e72\", \"#563444\"],\n [\"#5c323e\", \"#a82743\", \"#e15e32\", \"#c0d23e\", \"#e5f04c\"],\n [\"#edebe6\", \"#d6e1c7\", \"#94c7b6\", \"#403b33\", \"#d3643b\"],\n [\"#fdf1cc\", \"#c6d6b8\", \"#987f69\", \"#e3ad40\", \"#fcd036\"],\n [\"#230f2b\", \"#f21d41\", \"#ebebbc\", \"#bce3c5\", \"#82b3ae\"],\n [\"#b9d3b0\", \"#81bda4\", \"#b28774\", \"#f88f79\", \"#f6aa93\"],\n [\"#3a111c\", \"#574951\", \"#83988e\", \"#bcdea5\", \"#e6f9bc\"],\n [\"#5e3929\", \"#cd8c52\", \"#b7d1a3\", \"#dee8be\", \"#fcf7d3\"],\n [\"#1c0113\", \"#6b0103\", \"#a30006\", \"#c21a01\", \"#f03c02\"],\n [\"#000000\", \"#9f111b\", \"#b11623\", \"#292c37\", \"#cccccc\"],\n [\"#382f32\", \"#ffeaf2\", \"#fcd9e5\", \"#fbc5d8\", \"#f1396d\"],\n [\"#e3dfba\", \"#c8d6bf\", \"#93ccc6\", \"#6cbdb5\", \"#1a1f1e\"],\n [\"#f6f6f6\", \"#e8e8e8\", \"#333333\", \"#990100\", \"#b90504\"],\n [\"#1b325f\", \"#9cc4e4\", \"#e9f2f9\", \"#3a89c9\", \"#f26c4f\"],\n [\"#a1dbb2\", \"#fee5ad\", \"#faca66\", \"#f7a541\", \"#f45d4c\"],\n [\"#c1b398\", \"#605951\", \"#fbeec2\", \"#61a6ab\", \"#accec0\"],\n [\"#5e9fa3\", \"#dcd1b4\", \"#fab87f\", \"#f87e7b\", \"#b05574\"],\n [\"#951f2b\", \"#f5f4d7\", \"#e0dfb1\", \"#a5a36c\", \"#535233\"],\n [\"#8dccad\", \"#988864\", \"#fea6a2\", \"#f9d6ac\", \"#ffe9af\"],\n [\"#2d2d29\", \"#215a6d\", \"#3ca2a2\", \"#92c7a3\", \"#dfece6\"],\n [\"#413d3d\", \"#040004\", \"#c8ff00\", \"#fa023c\", \"#4b000f\"],\n [\"#eff3cd\", \"#b2d5ba\", \"#61ada0\", \"#248f8d\", \"#605063\"],\n [\"#ffefd3\", \"#fffee4\", \"#d0ecea\", \"#9fd6d2\", \"#8b7a5e\"],\n [\"#cfffdd\", \"#b4dec1\", \"#5c5863\", \"#a85163\", \"#ff1f4c\"],\n [\"#9dc9ac\", \"#fffec7\", \"#f56218\", \"#ff9d2e\", \"#919167\"],\n [\"#4e395d\", \"#827085\", \"#8ebe94\", \"#ccfc8e\", \"#dc5b3e\"],\n [\"#a8a7a7\", \"#cc527a\", \"#e8175d\", \"#474747\", \"#363636\"],\n [\"#f8edd1\", \"#d88a8a\", \"#474843\", \"#9d9d93\", \"#c5cfc6\"],\n [\"#046d8b\", \"#309292\", \"#2fb8ac\", \"#93a42a\", \"#ecbe13\"],\n [\"#f38a8a\", \"#55443d\", \"#a0cab5\", \"#cde9ca\", \"#f1edd0\"],\n [\"#a70267\", \"#f10c49\", \"#fb6b41\", \"#f6d86b\", \"#339194\"],\n [\"#ff003c\", \"#ff8a00\", \"#fabe28\", \"#88c100\", \"#00c176\"],\n [\"#ffedbf\", \"#f7803c\", \"#f54828\", \"#2e0d23\", \"#f8e4c1\"],\n [\"#4e4d4a\", \"#353432\", \"#94ba65\", \"#2790b0\", \"#2b4e72\"],\n [\"#0ca5b0\", \"#4e3f30\", \"#fefeeb\", \"#f8f4e4\", \"#a5b3aa\"],\n [\"#4d3b3b\", \"#de6262\", \"#ffb88c\", \"#ffd0b3\", \"#f5e0d3\"],\n [\"#fffbb7\", \"#a6f6af\", \"#66b6ab\", \"#5b7c8d\", \"#4f2958\"],\n [\"#edf6ee\", \"#d1c089\", \"#b3204d\", \"#412e28\", \"#151101\"],\n [\"#9d7e79\", \"#ccac95\", \"#9a947c\", \"#748b83\", \"#5b756c\"],\n [\"#fcfef5\", \"#e9ffe1\", \"#cdcfb7\", \"#d6e6c3\", \"#fafbe3\"],\n [\"#9cddc8\", \"#bfd8ad\", \"#ddd9ab\", \"#f7af63\", \"#633d2e\"],\n [\"#30261c\", \"#403831\", \"#36544f\", \"#1f5f61\", \"#0b8185\"],\n [\"#aaff00\", \"#ffaa00\", \"#ff00aa\", \"#aa00ff\", \"#00aaff\"],\n [\"#d1313d\", \"#e5625c\", \"#f9bf76\", \"#8eb2c5\", \"#615375\"],\n [\"#ffe181\", \"#eee9e5\", \"#fad3b2\", \"#ffba7f\", \"#ff9c97\"],\n [\"#73c8a9\", \"#dee1b6\", \"#e1b866\", \"#bd5532\", \"#373b44\"],\n [\"#805841\", \"#dcf7f3\", \"#fffcdd\", \"#ffd8d8\", \"#f5a2a2\"],\n]\n\nexport const getDebugLayoutObject = (lo: any): LayoutDebugObject | null => {\n let {\n x,\n y,\n width,\n height,\n }: { x: number; y: number; width?: number; height?: number } = {\n ...lo,\n ...(lo as any).size,\n ...(lo as any).center,\n ...(lo as any).position,\n }\n\n if (\n lo.x1 !== undefined &&\n lo.x2 !== undefined &&\n lo.y1 !== undefined &&\n lo.y2 !== undefined\n ) {\n x = (lo.x1 + lo.x2) / 2\n y = (lo.y1 + lo.y2) / 2\n width = Math.abs(lo.x1 - lo.x2)\n height = Math.abs(lo.y1 - lo.y2)\n }\n\n if (lo.points && Array.isArray(lo.points) && lo.points.length > 0) {\n const xCoords = lo.points.map((point: { x: number }) => point.x)\n const yCoords = lo.points.map((point: { y: number }) => point.y)\n\n const minX = Math.min(...xCoords)\n const maxX = Math.max(...xCoords)\n const minY = Math.min(...yCoords)\n const maxY = Math.max(...yCoords)\n\n x = (minX + maxX) / 2\n y = (minY + maxY) / 2\n width = maxX - minX\n height = maxY - minY\n }\n\n const title = lo.text || lo.name || lo.source?.text || lo.source?.name || \"?\"\n const content = lo\n\n if (x === undefined || y === undefined) return null\n\n if (width === undefined) {\n if (\"outer_diameter\" in lo) {\n width = lo.outer_diameter\n height = lo.outer_diameter\n } else if (\"rect_pad_width\" in lo && \"rect_pad_height\" in lo) {\n width = lo.rect_pad_width as number\n height = lo.rect_pad_height as number\n if (\"hole_diameter\" in lo) {\n width = Math.max(width, lo.hole_diameter as number)\n height = Math.max(height, lo.hole_diameter as number)\n }\n } else if (\"hole_diameter\" in lo) {\n width = lo.hole_diameter\n height = lo.hole_diameter\n }\n }\n\n if (width === undefined || height === undefined) {\n width = 0.1\n height = 0.1\n }\n\n return {\n x,\n y,\n width,\n height,\n title,\n content,\n bg_color:\n nice_color_palettes[\n stringHash((lo as any).type || title) % nice_color_palettes.length\n ]?.[4] ?? \"#f00\",\n }\n}\n","export const isTruthy = <T>(value: T): value is NonNullable<T> => Boolean(value)\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { getDebugLayoutObject } from \"./utils/get-layout-debug-object\"\nimport { isTruthy } from \"./utils/is-truthy\"\n\nexport const findBoundsAndCenter = (\n elements: AnyCircuitElement[],\n): { center: { x: number; y: number }; width: number; height: number } => {\n const debugObjects = elements\n .filter(\n (elm) => elm.type.startsWith(\"pcb_\") || elm.type.startsWith(\"schematic_\"),\n )\n .concat(\n elements\n .filter(\n (elm) => elm.type === \"pcb_trace\" || elm.type === \"schematic_trace\",\n )\n // @ts-ignore\n .flatMap((elm: any) => elm.route),\n )\n .map((elm) => getDebugLayoutObject(elm))\n .filter(isTruthy)\n\n if (debugObjects.length === 0)\n return { center: { x: 0, y: 0 }, width: 0, height: 0 }\n\n let minX = debugObjects[0]!.x - debugObjects[0]!.width / 2\n let maxX = debugObjects[0]!.x + debugObjects[0]!.width / 2\n let minY = debugObjects[0]!.y - debugObjects[0]!.height / 2\n let maxY = debugObjects[0]!.y + debugObjects[0]!.height / 2\n\n for (const obj of debugObjects.slice(1)) {\n minX = Math.min(minX, obj.x - obj.width / 2)\n maxX = Math.max(maxX, obj.x + obj.width / 2)\n minY = Math.min(minY, obj.y - obj.height / 2)\n maxY = Math.max(maxY, obj.y + obj.height / 2)\n }\n\n const width = maxX - minX\n const height = maxY - minY\n const center = { x: minX + width / 2, y: minY + height / 2 }\n\n return { center, width, height }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\n\nexport const getPrimaryId = (element: AnyCircuitElement): string => {\n // @ts-ignore\n return element[`${element.type}_id`]\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { transformPCBElements } from \"./transform-soup-elements\"\nimport { translate } from \"transformation-matrix\"\n\nexport const repositionPcbComponentTo = (\n circuitJson: AnyCircuitElement[],\n pcb_component_id: string,\n newCenter: { x: number; y: number },\n) => {\n const pcbComponent = circuitJson.find(\n (e) =>\n e.type === \"pcb_component\" &&\n (e as any).pcb_component_id === pcb_component_id,\n )\n if (!pcbComponent) return\n\n const currentCenter =\n \"center\" in pcbComponent\n ? (pcbComponent as any).center\n : { x: (pcbComponent as any).x, y: (pcbComponent as any).y }\n\n const dx = newCenter.x - currentCenter.x\n const dy = newCenter.y - currentCenter.y\n\n const portIds = circuitJson\n .filter(\n (e) =>\n e.type === \"pcb_port\" &&\n (e as any).pcb_component_id === pcb_component_id,\n )\n .map((e) => (e as any).pcb_port_id)\n\n const elementsToMove = circuitJson.filter((elm) => {\n if (elm === pcbComponent) return true\n const anyElm: any = elm\n if (anyElm.pcb_component_id === pcb_component_id) return true\n if (\n Array.isArray(anyElm.pcb_component_ids) &&\n anyElm.pcb_component_ids.includes(pcb_component_id)\n )\n return true\n if (anyElm.pcb_port_id && portIds.includes(anyElm.pcb_port_id)) return true\n if (\n Array.isArray(anyElm.pcb_port_ids) &&\n anyElm.pcb_port_ids.some((id: string) => portIds.includes(id))\n )\n return true\n if (anyElm.start_pcb_port_id && portIds.includes(anyElm.start_pcb_port_id))\n return true\n if (anyElm.end_pcb_port_id && portIds.includes(anyElm.end_pcb_port_id))\n return true\n if (\n Array.isArray(anyElm.route) &&\n anyElm.route.some(\n (pt: any) =>\n (pt.start_pcb_port_id && portIds.includes(pt.start_pcb_port_id)) ||\n (pt.end_pcb_port_id && portIds.includes(pt.end_pcb_port_id)),\n )\n )\n return true\n return false\n })\n\n const matrix = translate(dx, dy)\n transformPCBElements(elementsToMove, matrix)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { buildSubtree } from \"./subtree\"\nimport { findBoundsAndCenter } from \"./find-bounds-and-center\"\nimport { transformPCBElements } from \"./transform-soup-elements\"\nimport { translate } from \"transformation-matrix\"\n\nconst findAllDescendantGroupIds = (\n circuitJson: AnyCircuitElement[],\n parentGroupId: string,\n): string[] => {\n const childGroupIds: string[] = []\n const directChildren = circuitJson\n .filter(\n (elm) =>\n elm.type === \"source_group\" &&\n (elm as any).parent_source_group_id === parentGroupId,\n )\n .map((elm) => (elm as any).source_group_id)\n\n childGroupIds.push(...directChildren)\n\n // Recursively find descendants of child groups\n for (const childId of directChildren) {\n childGroupIds.push(...findAllDescendantGroupIds(circuitJson, childId))\n }\n\n return childGroupIds\n}\n\nexport const repositionPcbGroupTo = (\n circuitJson: AnyCircuitElement[],\n source_group_id: string,\n newCenter: { x: number; y: number },\n) => {\n // Find all descendant group IDs\n const allGroupIds = [\n source_group_id,\n ...findAllDescendantGroupIds(circuitJson, source_group_id),\n ]\n\n // Get all elements for each group (including the main group and its descendants)\n const allGroupElements = new Set<AnyCircuitElement>()\n\n for (const groupId of allGroupIds) {\n const groupElements = buildSubtree(circuitJson, {\n source_group_id: groupId,\n })\n groupElements.forEach((elm) => allGroupElements.add(elm))\n }\n\n // Get all port IDs from elements in the group\n const portIds = Array.from(allGroupElements)\n .filter((e) => e.type === \"pcb_port\")\n .map((e) => (e as any).pcb_port_id)\n\n // Find additional traces that connect to these ports (buildSubtree might miss these)\n const additionalTraces = circuitJson.filter((elm) => {\n if (elm.type !== \"pcb_trace\") return false\n if (allGroupElements.has(elm)) return false // already included\n\n const anyElm: any = elm\n\n // Check direct port connections\n if (anyElm.start_pcb_port_id && portIds.includes(anyElm.start_pcb_port_id))\n return true\n if (anyElm.end_pcb_port_id && portIds.includes(anyElm.end_pcb_port_id))\n return true\n\n // Check route point connections\n if (\n Array.isArray(anyElm.route) &&\n anyElm.route.some(\n (pt: any) =>\n (pt.start_pcb_port_id && portIds.includes(pt.start_pcb_port_id)) ||\n (pt.end_pcb_port_id && portIds.includes(pt.end_pcb_port_id)),\n )\n )\n return true\n\n return false\n })\n\n // Add additional traces to the elements to move\n additionalTraces.forEach((trace) => allGroupElements.add(trace))\n\n // Filter to only PCB elements that can be repositioned\n const pcbElements = Array.from(allGroupElements).filter((elm) =>\n elm.type.startsWith(\"pcb_\"),\n )\n\n if (pcbElements.length === 0) return\n\n // Calculate current bounds and center of the group\n const { center: currentCenter } = findBoundsAndCenter(pcbElements)\n\n // Calculate translation needed\n const dx = newCenter.x - currentCenter.x\n const dy = newCenter.y - currentCenter.y\n\n // Create translation matrix\n const matrix = translate(dx, dy)\n\n // Apply transformation to all PCB elements in the group\n transformPCBElements(pcbElements, matrix)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { transformSchematicElements } from \"./transform-soup-elements\"\nimport { translate } from \"transformation-matrix\"\n\nexport const repositionSchematicComponentTo = (\n circuitJson: AnyCircuitElement[],\n schematic_component_id: string,\n newCenter: { x: number; y: number },\n) => {\n const schematicComponent = circuitJson.find(\n (e) =>\n e.type === \"schematic_component\" &&\n (e as any).schematic_component_id === schematic_component_id,\n )\n if (!schematicComponent) return\n\n const currentCenter =\n \"center\" in schematicComponent\n ? (schematicComponent as any).center\n : { x: (schematicComponent as any).x, y: (schematicComponent as any).y }\n\n const dx = newCenter.x - currentCenter.x\n const dy = newCenter.y - currentCenter.y\n\n const portIds = circuitJson\n .filter(\n (e) =>\n e.type === \"schematic_port\" &&\n (e as any).schematic_component_id === schematic_component_id,\n )\n .map((e) => (e as any).schematic_port_id)\n\n const elementsToMove = circuitJson.filter((elm) => {\n if (elm === schematicComponent) return true\n const anyElm: any = elm\n if (anyElm.schematic_component_id === schematic_component_id) return true\n if (\n Array.isArray(anyElm.schematic_component_ids) &&\n anyElm.schematic_component_ids.includes(schematic_component_id)\n )\n return true\n if (anyElm.schematic_port_id && portIds.includes(anyElm.schematic_port_id))\n return true\n if (\n Array.isArray(anyElm.schematic_port_ids) &&\n anyElm.schematic_port_ids.some((id: string) => portIds.includes(id))\n )\n return true\n if (\n anyElm.start_schematic_port_id &&\n portIds.includes(anyElm.start_schematic_port_id)\n )\n return true\n if (\n anyElm.end_schematic_port_id &&\n portIds.includes(anyElm.end_schematic_port_id)\n )\n return true\n if (\n Array.isArray(anyElm.route) &&\n anyElm.route.some(\n (pt: any) =>\n (pt.start_schematic_port_id &&\n portIds.includes(pt.start_schematic_port_id)) ||\n (pt.end_schematic_port_id &&\n portIds.includes(pt.end_schematic_port_id)),\n )\n )\n return true\n return false\n })\n\n const matrix = translate(dx, dy)\n transformSchematicElements(elementsToMove, matrix)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { buildSubtree } from \"./subtree\"\nimport { findBoundsAndCenter } from \"./find-bounds-and-center\"\nimport { transformSchematicElements } from \"./transform-soup-elements\"\nimport { translate } from \"transformation-matrix\"\n\nconst findAllDescendantGroupIds = (\n circuitJson: AnyCircuitElement[],\n parentGroupId: string,\n): string[] => {\n const childGroupIds: string[] = []\n const directChildren = circuitJson\n .filter(\n (elm) =>\n elm.type === \"source_group\" &&\n (elm as any).parent_source_group_id === parentGroupId,\n )\n .map((elm) => (elm as any).source_group_id)\n\n childGroupIds.push(...directChildren)\n\n for (const childId of directChildren) {\n childGroupIds.push(...findAllDescendantGroupIds(circuitJson, childId))\n }\n\n return childGroupIds\n}\n\nexport const repositionSchematicGroupTo = (\n circuitJson: AnyCircuitElement[],\n source_group_id: string,\n newCenter: { x: number; y: number },\n) => {\n const allGroupIds = [\n source_group_id,\n ...findAllDescendantGroupIds(circuitJson, source_group_id),\n ]\n\n const allGroupElements = new Set<AnyCircuitElement>()\n\n for (const groupId of allGroupIds) {\n const groupElements = buildSubtree(circuitJson, {\n source_group_id: groupId,\n })\n groupElements.forEach((elm) => allGroupElements.add(elm))\n }\n\n const portIds = Array.from(allGroupElements)\n .filter((e) => e.type === \"schematic_port\")\n .map((e) => (e as any).schematic_port_id)\n\n const additionalTraces = circuitJson.filter((elm) => {\n if (elm.type !== \"schematic_trace\") return false\n if (allGroupElements.has(elm)) return false\n\n const anyElm: any = elm\n\n if (\n anyElm.start_schematic_port_id &&\n portIds.includes(anyElm.start_schematic_port_id)\n )\n return true\n if (\n anyElm.end_schematic_port_id &&\n portIds.includes(anyElm.end_schematic_port_id)\n )\n return true\n if (\n Array.isArray(anyElm.route) &&\n anyElm.route.some(\n (pt: any) =>\n (pt.start_schematic_port_id &&\n portIds.includes(pt.start_schematic_port_id)) ||\n (pt.end_schematic_port_id &&\n portIds.includes(pt.end_schematic_port_id)),\n )\n )\n return true\n\n return false\n })\n\n additionalTraces.forEach((trace) => allGroupElements.add(trace))\n\n const schematicElements = Array.from(allGroupElements).filter((elm) =>\n elm.type.startsWith(\"schematic_\"),\n )\n if (schematicElements.length === 0) return\n\n const { center: currentCenter } = findBoundsAndCenter(schematicElements)\n\n const dx = newCenter.x - currentCenter.x\n const dy = newCenter.y - currentCenter.y\n\n const matrix = translate(dx, dy)\n\n transformSchematicElements(schematicElements, matrix)\n}\n","import type {\n AnyCircuitElement,\n SourceComponentBase,\n SourceGroup,\n} from \"circuit-json\"\n\n/**\n * A tree of circuit elements. This is often used for layout because you want\n * to consider only the top-level elements of a group for layout (child groups\n * move together)\n */\nexport interface CircuitJsonTreeNode {\n nodeType: \"group\" | \"component\"\n sourceGroup?: SourceGroup\n sourceComponent?: SourceComponentBase\n childNodes: Array<CircuitJsonTreeNode>\n otherChildElements: Array<AnyCircuitElement>\n}\n\nexport const getCircuitJsonTree = (\n circuitJson: AnyCircuitElement[],\n opts?: {\n source_group_id?: string\n },\n): CircuitJsonTreeNode => {\n type ChildGroupId = string\n type ParentGroupId = string\n type GroupId = string\n const groupChildMap: Map<ParentGroupId, ChildGroupId[]> = new Map()\n\n // Get all source group IDs present in the circuit JSON\n const existingGroupIds = new Set<string>()\n for (const elm of circuitJson) {\n if (elm.type === \"source_group\") {\n existingGroupIds.add(elm.source_group_id)\n }\n }\n\n // Find orphaned groups (groups whose parent is not in the circuit JSON)\n const orphanedGroups: string[] = []\n\n for (const elm of circuitJson) {\n if (elm.type === \"source_group\" && elm.parent_source_group_id) {\n const parentId = elm.parent_source_group_id\n const childId = elm.source_group_id\n\n // If parent doesn't exist in circuit JSON, this is an orphaned group\n if (!existingGroupIds.has(parentId)) {\n orphanedGroups.push(childId)\n // Treat orphaned groups as root-level groups\n if (!groupChildMap.has(childId)) {\n groupChildMap.set(childId, [])\n }\n } else {\n // Normal parent-child relationship\n const children = groupChildMap.get(parentId) ?? []\n children.push(childId)\n groupChildMap.set(parentId, children)\n if (!groupChildMap.has(childId)) {\n groupChildMap.set(childId, [])\n }\n }\n }\n }\n\n // Ensure that every source_group, including root-level groups that have no parent,\n // is present in the groupChildMap. This guarantees that even standalone boards\n // (with no nested groups) are processed and appear at the top of the tree.\n for (const elm of circuitJson) {\n if (\n elm.type === \"source_group\" &&\n !groupChildMap.has(elm.source_group_id)\n ) {\n groupChildMap.set(elm.source_group_id, [])\n }\n }\n\n const groupNodes = new Map<GroupId, CircuitJsonTreeNode>()\n\n const getNextGroupId = () => {\n for (const [parentId, children] of groupChildMap) {\n if (groupNodes.has(parentId)) continue\n if (children.every((childId) => groupNodes.has(childId))) {\n return parentId\n }\n }\n return null\n }\n\n // Compute any node we have the dependencies for until we've computed all of\n // them\n let lastGroupId: GroupId | null = null\n while (true) {\n const nextGroupId = getNextGroupId()\n if (!nextGroupId) break\n\n const sourceGroup = circuitJson.find(\n (elm) =>\n elm.type === \"source_group\" && elm.source_group_id === nextGroupId,\n ) as SourceGroup\n\n // Create the tree node for this group\n const node: CircuitJsonTreeNode = {\n nodeType: \"group\",\n sourceGroup,\n otherChildElements: [],\n childNodes: [\n ...(groupChildMap\n .get(nextGroupId)\n ?.map((childId) => groupNodes.get(childId)!) ?? []),\n ...circuitJson\n .filter(\n (elm) =>\n elm.type === \"source_component\" &&\n elm.source_group_id === nextGroupId,\n )\n .map((elm) => {\n return {\n nodeType: \"component\",\n sourceComponent: elm,\n childNodes: [],\n otherChildElements: [\n ...circuitJson.filter(\n (e) =>\n e.type === \"pcb_component\" &&\n e.source_component_id ===\n (elm as SourceComponentBase).source_component_id,\n ),\n ], // TODO populate\n } as CircuitJsonTreeNode\n }),\n ],\n }\n\n groupNodes.set(nextGroupId, node)\n lastGroupId = nextGroupId\n }\n\n if (!lastGroupId) {\n console.warn(\"No groups were processed, returning tree without sourceGroup\")\n return {\n nodeType: \"group\",\n childNodes: [], // TODO populate\n otherChildElements: circuitJson,\n }\n }\n\n // Determine which group to return as root\n let rootGroupId: string | null = null\n if (opts && opts.source_group_id !== undefined) {\n // Use explicitly specified group\n rootGroupId = opts.source_group_id\n } else if (orphanedGroups.length > 0) {\n // Use the first orphaned group as root (most likely scenario when filtering circuit JSON)\n rootGroupId = orphanedGroups[0]!\n } else {\n // Fall back to the last processed group (typically the top-level parent)\n rootGroupId = lastGroupId as string | null\n }\n\n if (!rootGroupId) {\n console.warn(\n \"No valid root group found, returning tree without sourceGroup\",\n )\n return {\n nodeType: \"group\",\n childNodes: [],\n otherChildElements: circuitJson,\n }\n }\n\n return groupNodes.get(rootGroupId)!\n}\n","import type { CircuitJsonTreeNode } from \"./getCircuitJsonTree\"\n\nexport const getStringFromCircuitJsonTree = (\n circuitJsonTree: CircuitJsonTreeNode,\n indent = 0,\n): string => {\n if (circuitJsonTree.nodeType === \"component\") {\n return `${\" \".repeat(indent)}${circuitJsonTree.sourceComponent?.name ?? circuitJsonTree.sourceComponent?.source_component_id}`\n }\n const lines = []\n\n lines.push(\n `${\" \".repeat(indent)}${circuitJsonTree.sourceGroup?.name ?? circuitJsonTree.sourceGroup?.source_group_id}`,\n )\n for (const child of circuitJsonTree.childNodes) {\n lines.push(getStringFromCircuitJsonTree(child, indent + 2))\n }\n return lines.join(\"\\n\")\n}\n","export type Size = { width: number; height: number }\n\nimport type { FlexBoxOptions } from \"@tscircuit/miniflex\"\n/**\n * Compute the smallest possible dimensions (width & height) for a flex container\n * so that **all** children fit without overflowing _before_ any flex grow / shrink\n * is applied. This is a very lightweight approximation – it only considers the\n * children's explicit `width`/`height` (or `flexBasis`) plus the configured gaps\n * and the main-axis stacking rules derived from the flex direction.\n *\n * This function purposely does **not** try to implement the full flexbox sizing\n * algorithm – we only need a quick estimate so that `RootFlexBox` can be\n * instantiated even when the user did not provide explicit dimensions for the\n * container (e.g. when laying out PCB components directly on the board level\n * instead of inside a sub-circuit).\n */\nexport function getMinimumFlexContainer(\n children: Array<{ width: number; height: number }>,\n options: FlexBoxOptions = {},\n): Size {\n if (children.length === 0) return { width: 0, height: 0 }\n\n const direction = options.direction ?? \"row\"\n const columnGap = options.columnGap ?? 0\n const rowGap = options.rowGap ?? 0\n\n // Flexbox main-axis / cross-axis mapping --------------------------------\n const isRowDirection = direction === \"row\" || direction === \"row-reverse\"\n\n if (isRowDirection) {\n // Main-axis horizontally stacks children\n const totalChildWidth = children.reduce((sum, c) => sum + c.width, 0)\n const width = totalChildWidth + columnGap * Math.max(0, children.length - 1)\n\n const height = children.reduce((max, c) => Math.max(max, c.height), 0)\n return { width, height }\n } else {\n // Column direction – stack vertically\n const totalChildHeight = children.reduce((sum, c) => sum + c.height, 0)\n const height = totalChildHeight + rowGap * Math.max(0, children.length - 1)\n\n const width = children.reduce((max, c) => Math.max(max, c.width), 0)\n return { width, height }\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\n\nexport function getElementRenderLayers(\n element: AnyCircuitElement,\n): PcbRenderLayer[] {\n // Copper elements (pads, traces, copper pour, copper text)\n if (element.type === \"pcb_smtpad\") {\n const layer = element.layer\n return [`${layer}_copper` as PcbRenderLayer]\n }\n\n if (element.type === \"pcb_trace\") {\n // Traces can span multiple layers, return all layers from route\n if (!element.route || !Array.isArray(element.route)) return []\n const layers = new Set<PcbRenderLayer>()\n for (const point of element.route) {\n if (\"layer\" in point && point.layer) {\n layers.add(`${point.layer}_copper` as PcbRenderLayer)\n }\n }\n return Array.from(layers)\n }\n\n if (element.type === \"pcb_copper_pour\") {\n const layer = element.layer\n return [`${layer}_copper` as PcbRenderLayer]\n }\n\n if (element.type === \"pcb_copper_text\") {\n const layer = element.layer\n return [`${layer}_copper` as PcbRenderLayer]\n }\n\n // Silkscreen elements\n if (\n element.type === \"pcb_silkscreen_text\" ||\n element.type === \"pcb_silkscreen_rect\" ||\n element.type === \"pcb_silkscreen_circle\" ||\n element.type === \"pcb_silkscreen_line\" ||\n element.type === \"pcb_silkscreen_path\"\n ) {\n const layer = element.layer\n return [`${layer}_silkscreen` as PcbRenderLayer]\n }\n\n // Fabrication note elements\n if (\n element.type === \"pcb_fabrication_note_text\" ||\n element.type === \"pcb_fabrication_note_rect\" ||\n element.type === \"pcb_fabrication_note_path\"\n ) {\n const layer = element.layer\n return [`${layer}_fabrication_note` as PcbRenderLayer]\n }\n\n // Courtyard elements\n\n if (\n element.type === \"pcb_courtyard_circle\" ||\n element.type === \"pcb_courtyard_polygon\" ||\n element.type === \"pcb_courtyard_rect\" ||\n element.type === \"pcb_courtyard_outline\"\n ) {\n const layer = element.layer\n return [`${layer}_courtyard` as PcbRenderLayer]\n }\n\n // PCB note elements (user annotations)\n if (\n element.type === \"pcb_note_rect\" ||\n element.type === \"pcb_note_path\" ||\n element.type === \"pcb_note_text\" ||\n element.type === \"pcb_note_line\" ||\n element.type === \"pcb_note_dimension\"\n ) {\n const layer = element.layer\n return [`${layer}_user_note` as PcbRenderLayer]\n }\n\n // Elements without layer filtering (always drawn)\n // These include: pcb_board, pcb_hole, pcb_plated_hole, pcb_via, pcb_cutout\n return []\n}\n","import type { Point, Polygon, Rect } from \"./types\"\n\nexport const EPSILON = 1e-9\n\nexport const toRadians = (degrees: number) => (degrees * Math.PI) / 180\n\nexport const clamp = (value: number, min: number, max: number) =>\n Math.max(min, Math.min(max, value))\n\nexport const distanceBetweenPoints = (a: Point, b: Point) =>\n Math.hypot(a.x - b.x, a.y - b.y)\n\nexport const distanceBetweenPointAndSegment = (\n point: Point,\n a: Point,\n b: Point,\n) => {\n const abX = b.x - a.x\n const abY = b.y - a.y\n const lengthSquared = abX * abX + abY * abY\n\n if (lengthSquared <= EPSILON) return distanceBetweenPoints(point, a)\n\n const t = clamp(\n ((point.x - a.x) * abX + (point.y - a.y) * abY) / lengthSquared,\n 0,\n 1,\n )\n\n return Math.hypot(point.x - (a.x + t * abX), point.y - (a.y + t * abY))\n}\n\nexport const cross = (a: Point, b: Point, c: Point) =>\n (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)\n\nexport const isPointOnSegment = (point: Point, a: Point, b: Point) => {\n if (Math.abs(cross(a, b, point)) > EPSILON) return false\n\n return (\n point.x >= Math.min(a.x, b.x) - EPSILON &&\n point.x <= Math.max(a.x, b.x) + EPSILON &&\n point.y >= Math.min(a.y, b.y) - EPSILON &&\n point.y <= Math.max(a.y, b.y) + EPSILON\n )\n}\n\nexport const segmentsIntersect = (\n a1: Point,\n a2: Point,\n b1: Point,\n b2: Point,\n) => {\n const c1 = cross(a1, a2, b1)\n const c2 = cross(a1, a2, b2)\n const c3 = cross(b1, b2, a1)\n const c4 = cross(b1, b2, a2)\n\n if (\n ((c1 > EPSILON && c2 < -EPSILON) || (c1 < -EPSILON && c2 > EPSILON)) &&\n ((c3 > EPSILON && c4 < -EPSILON) || (c3 < -EPSILON && c4 > EPSILON))\n ) {\n return true\n }\n\n return (\n isPointOnSegment(b1, a1, a2) ||\n isPointOnSegment(b2, a1, a2) ||\n isPointOnSegment(a1, b1, b2) ||\n isPointOnSegment(a2, b1, b2)\n )\n}\n\nexport const getPolygonEdges = (polygon: Polygon): Array<[Point, Point]> => {\n const edges: Array<[Point, Point]> = []\n\n if (polygon.points.length < 2) return edges\n\n for (let i = 0; i < polygon.points.length; i += 1) {\n const a = polygon.points[i]\n const b = polygon.points[(i + 1) % polygon.points.length]\n\n if (!a || !b) continue\n\n edges.push([a, b])\n }\n\n return edges\n}\n\nexport const isPointInPolygon = (point: Point, polygon: Polygon) => {\n for (const [a, b] of getPolygonEdges(polygon)) {\n if (isPointOnSegment(point, a, b)) return true\n }\n\n let inside = false\n for (\n let i = 0, j = polygon.points.length - 1;\n i < polygon.points.length;\n j = i++\n ) {\n const pi = polygon.points[i]\n const pj = polygon.points[j]\n\n if (!pi || !pj) continue\n\n const intersects =\n pi.y > point.y !== pj.y > point.y &&\n point.x < ((pj.x - pi.x) * (point.y - pi.y)) / (pj.y - pi.y) + pi.x\n\n if (intersects) inside = !inside\n }\n\n return inside\n}\n\nexport const rotatePoint = (point: Point, angleRadians: number) => ({\n x: point.x * Math.cos(angleRadians) - point.y * Math.sin(angleRadians),\n y: point.x * Math.sin(angleRadians) + point.y * Math.cos(angleRadians),\n})\n\nexport const rectToPolygon = (rect: Rect): Polygon => {\n const halfWidth = rect.width / 2\n const halfHeight = rect.height / 2\n const angle = toRadians(rect.rotationDegrees)\n\n return {\n kind: \"polygon\",\n points: [\n { x: -halfWidth, y: -halfHeight },\n { x: halfWidth, y: -halfHeight },\n { x: halfWidth, y: halfHeight },\n { x: -halfWidth, y: halfHeight },\n ].map((localPoint) => {\n const rotated = rotatePoint(localPoint, angle)\n return { x: rect.centerX + rotated.x, y: rect.centerY + rotated.y }\n }),\n }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { EPSILON } from \"./geometry\"\nimport type { CopperShape, Point, Rect } from \"./types\"\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isFinite(value)\n\nconst createWireSegmentRect = (\n start: Point,\n end: Point,\n width: number,\n): Rect => ({\n kind: \"rect\",\n centerX: (start.x + end.x) / 2,\n centerY: (start.y + end.y) / 2,\n width: Math.hypot(end.x - start.x, end.y - start.y),\n height: width,\n rotationDegrees:\n (Math.atan2(end.y - start.y, end.x - start.x) * 180) / Math.PI,\n})\n\nexport const decomposeCopperIntoShapes = (\n element: AnyCircuitElement,\n): CopperShape[] => {\n const elm: any = element\n const shapes: CopperShape[] = []\n\n if (elm.type === \"pcb_smtpad\") {\n if (elm.shape === \"circle\" && isFiniteNumber(elm.radius)) {\n shapes.push({ kind: \"circle\", x: elm.x, y: elm.y, radius: elm.radius })\n }\n\n if (\n elm.shape === \"rect\" &&\n isFiniteNumber(elm.width) &&\n isFiniteNumber(elm.height)\n ) {\n shapes.push({\n kind: \"rect\",\n centerX: elm.x,\n centerY: elm.y,\n width: elm.width,\n height: elm.height,\n rotationDegrees: isFiniteNumber(elm.ccw_rotation)\n ? elm.ccw_rotation\n : 0,\n })\n }\n\n if (elm.shape === \"polygon\" && Array.isArray(elm.points)) {\n const points = elm.points.filter(\n (point: any): point is Point =>\n isFiniteNumber(point?.x) && isFiniteNumber(point?.y),\n )\n\n if (points.length >= 3) {\n shapes.push({ kind: \"polygon\", points })\n }\n }\n\n return shapes\n }\n\n if (elm.type === \"pcb_trace\" && Array.isArray(elm.route)) {\n for (let i = 0; i < elm.route.length - 1; i += 1) {\n const start = elm.route[i]\n const end = elm.route[i + 1]\n\n if (\n !start ||\n !end ||\n start.route_type !== \"wire\" ||\n end.route_type !== \"wire\" ||\n !isFiniteNumber(start.x) ||\n !isFiniteNumber(start.y) ||\n !isFiniteNumber(end.x) ||\n !isFiniteNumber(end.y)\n ) {\n continue\n }\n\n const width = isFiniteNumber(start.width) ? Math.max(0, start.width) : 0\n const radius = width / 2\n\n shapes.push({ kind: \"circle\", x: start.x, y: start.y, radius })\n shapes.push({ kind: \"circle\", x: end.x, y: end.y, radius })\n\n if (Math.hypot(end.x - start.x, end.y - start.y) > EPSILON) {\n shapes.push(createWireSegmentRect(start, end, width))\n }\n }\n\n return shapes\n }\n\n if (elm.type === \"pcb_via\" && isFiniteNumber(elm.outer_diameter)) {\n shapes.push({\n kind: \"circle\",\n x: elm.x,\n y: elm.y,\n radius: elm.outer_diameter / 2,\n })\n\n return shapes\n }\n\n if (elm.type === \"pcb_plated_hole\") {\n if (isFiniteNumber(elm.outer_diameter)) {\n shapes.push({\n kind: \"circle\",\n x: elm.x,\n y: elm.y,\n radius: elm.outer_diameter / 2,\n })\n }\n\n if (\n isFiniteNumber(elm.rect_pad_width) &&\n isFiniteNumber(elm.rect_pad_height)\n ) {\n shapes.push({\n kind: \"rect\",\n centerX: elm.x,\n centerY: elm.y,\n width: elm.rect_pad_width,\n height: elm.rect_pad_height,\n rotationDegrees: isFiniteNumber(elm.rect_ccw_rotation)\n ? elm.rect_ccw_rotation\n : 0,\n })\n }\n\n if (isFiniteNumber(elm.outer_width) && isFiniteNumber(elm.outer_height)) {\n shapes.push({\n kind: \"rect\",\n centerX: elm.x,\n centerY: elm.y,\n width: elm.outer_width,\n height: elm.outer_height,\n rotationDegrees: 0,\n })\n }\n\n return shapes\n }\n\n return shapes\n}\n","import {\n distanceBetweenPointAndSegment,\n getPolygonEdges,\n isPointInPolygon,\n rectToPolygon,\n segmentsIntersect,\n} from \"./geometry\"\nimport type { Circle, CopperShape, Polygon, Rect } from \"./types\"\n\nexport const distanceBetweenCircleAndCircle = (a: Circle, b: Circle) =>\n Math.max(0, Math.hypot(a.x - b.x, a.y - b.y) - a.radius - b.radius)\n\nexport const distanceBetweenPolygonAndPolygon = (a: Polygon, b: Polygon) => {\n if (a.points.length < 3 || b.points.length < 3) {\n return Number.POSITIVE_INFINITY\n }\n\n for (const [a1, a2] of getPolygonEdges(a)) {\n for (const [b1, b2] of getPolygonEdges(b)) {\n if (segmentsIntersect(a1, a2, b1, b2)) {\n return 0\n }\n }\n }\n\n const aPoint = a.points[0]\n const bPoint = b.points[0]\n if (\n (aPoint && isPointInPolygon(aPoint, b)) ||\n (bPoint && isPointInPolygon(bPoint, a))\n ) {\n return 0\n }\n\n let minDistance = Number.POSITIVE_INFINITY\n\n for (const [a1, a2] of getPolygonEdges(a)) {\n for (const [b1, b2] of getPolygonEdges(b)) {\n minDistance = Math.min(\n minDistance,\n distanceBetweenPointAndSegment(a1, b1, b2),\n distanceBetweenPointAndSegment(a2, b1, b2),\n distanceBetweenPointAndSegment(b1, a1, a2),\n distanceBetweenPointAndSegment(b2, a1, a2),\n )\n }\n }\n\n return minDistance\n}\n\nexport const distanceBetweenCircleAndPolygon = (\n circle: Circle,\n polygon: Polygon,\n) => {\n if (polygon.points.length < 3) {\n return Number.POSITIVE_INFINITY\n }\n\n if (isPointInPolygon({ x: circle.x, y: circle.y }, polygon)) {\n return 0\n }\n\n let minDistanceToEdge = Number.POSITIVE_INFINITY\n\n for (const [start, end] of getPolygonEdges(polygon)) {\n minDistanceToEdge = Math.min(\n minDistanceToEdge,\n distanceBetweenPointAndSegment({ x: circle.x, y: circle.y }, start, end),\n )\n }\n\n return Math.max(0, minDistanceToEdge - circle.radius)\n}\n\nexport const distanceBetweenShapes = (\n a: CopperShape,\n b: CopperShape,\n): number => {\n if (a.kind === \"circle\" && b.kind === \"circle\") {\n return distanceBetweenCircleAndCircle(a, b)\n }\n\n if (a.kind === \"rect\" && b.kind === \"rect\") {\n return distanceBetweenPolygonAndPolygon(rectToPolygon(a), rectToPolygon(b))\n }\n\n if (a.kind === \"circle\" && b.kind === \"rect\") {\n return distanceBetweenCircleAndPolygon(a, rectToPolygon(b))\n }\n\n if (a.kind === \"rect\" && b.kind === \"circle\") {\n return distanceBetweenCircleAndPolygon(b, rectToPolygon(a))\n }\n\n if (a.kind === \"circle\" && b.kind === \"polygon\") {\n return distanceBetweenCircleAndPolygon(a, b)\n }\n\n if (a.kind === \"polygon\" && b.kind === \"circle\") {\n return distanceBetweenCircleAndPolygon(b, a)\n }\n\n if (a.kind === \"rect\" && b.kind === \"polygon\") {\n return distanceBetweenPolygonAndPolygon(rectToPolygon(a), b)\n }\n\n if (a.kind === \"polygon\" && b.kind === \"rect\") {\n return distanceBetweenPolygonAndPolygon(a, rectToPolygon(b))\n }\n\n if (a.kind === \"polygon\" && b.kind === \"polygon\") {\n return distanceBetweenPolygonAndPolygon(a, b)\n }\n\n return Number.POSITIVE_INFINITY\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { decomposeCopperIntoShapes } from \"./shape-distances/decompose-copper-into-shapes\"\nimport { distanceBetweenShapes } from \"./shape-distances/distance-between-shapes\"\n\nexport const computeGapBetweenCopper = (\n elm1: AnyCircuitElement,\n elm2: AnyCircuitElement,\n): number => {\n const shapes1 = decomposeCopperIntoShapes(elm1)\n const shapes2 = decomposeCopperIntoShapes(elm2)\n\n if (shapes1.length === 0 || shapes2.length === 0) {\n return Number.POSITIVE_INFINITY\n }\n\n let minimumGap = Number.POSITIVE_INFINITY\n\n for (const shape1 of shapes1) {\n for (const shape2 of shapes2) {\n minimumGap = Math.min(minimumGap, distanceBetweenShapes(shape1, shape2))\n }\n }\n\n return minimumGap\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { decomposeCopperIntoShapes } from \"./decompose-copper-into-shapes\"\nimport type { CopperShape, Point } from \"./types\"\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isFinite(value)\n\nconst getCenter = (elm: any): { x: number; y: number } | null => {\n if (isFiniteNumber(elm?.x) && isFiniteNumber(elm?.y)) {\n return { x: elm.x, y: elm.y }\n }\n\n if (isFiniteNumber(elm?.center?.x) && isFiniteNumber(elm?.center?.y)) {\n return { x: elm.center.x, y: elm.center.y }\n }\n\n return null\n}\n\nconst addCenterBasedShapes = (elm: any, shapes: CopperShape[]) => {\n const center = getCenter(elm)\n if (!center) return\n\n if (elm.shape === \"circle\") {\n if (isFiniteNumber(elm.radius)) {\n shapes.push({\n kind: \"circle\",\n x: center.x,\n y: center.y,\n radius: elm.radius,\n })\n return\n }\n\n if (isFiniteNumber(elm.diameter)) {\n shapes.push({\n kind: \"circle\",\n x: center.x,\n y: center.y,\n radius: elm.diameter / 2,\n })\n return\n }\n }\n\n if (\n elm.shape === \"rect\" &&\n isFiniteNumber(elm.width) &&\n isFiniteNumber(elm.height)\n ) {\n shapes.push({\n kind: \"rect\",\n centerX: center.x,\n centerY: center.y,\n width: elm.width,\n height: elm.height,\n rotationDegrees: isFiniteNumber(elm.ccw_rotation) ? elm.ccw_rotation : 0,\n })\n return\n }\n\n if (elm.shape === \"polygon\" && Array.isArray(elm.points)) {\n const points = elm.points.filter(\n (point: any): point is Point =>\n isFiniteNumber(point?.x) && isFiniteNumber(point?.y),\n )\n\n if (points.length >= 3) {\n shapes.push({ kind: \"polygon\", points })\n }\n }\n}\n\nexport const decomposeClearanceIntoShapes = (\n element: AnyCircuitElement,\n): CopperShape[] => {\n const elm: any = element\n const shapes: CopperShape[] = [...decomposeCopperIntoShapes(element)]\n\n if (elm.type === \"pcb_hole\" && elm.hole_shape === \"circle\") {\n if (\n isFiniteNumber(elm.hole_diameter) &&\n isFiniteNumber(elm.x) &&\n isFiniteNumber(elm.y)\n ) {\n shapes.push({\n kind: \"circle\",\n x: elm.x,\n y: elm.y,\n radius: elm.hole_diameter / 2,\n })\n }\n return shapes\n }\n\n if (elm.type === \"pcb_plated_hole\") {\n if (\n isFiniteNumber(elm.hole_diameter) &&\n isFiniteNumber(elm.x) &&\n isFiniteNumber(elm.y)\n ) {\n const holeOffsetX = isFiniteNumber(elm.hole_offset_x)\n ? elm.hole_offset_x\n : 0\n const holeOffsetY = isFiniteNumber(elm.hole_offset_y)\n ? elm.hole_offset_y\n : 0\n shapes.push({\n kind: \"circle\",\n x: elm.x + holeOffsetX,\n y: elm.y + holeOffsetY,\n radius: elm.hole_diameter / 2,\n })\n }\n return shapes\n }\n\n if (\n elm.type === \"pcb_keepout\" ||\n elm.type === \"pcb_cutout\" ||\n elm.type === \"pcb_board\"\n ) {\n addCenterBasedShapes(elm, shapes)\n return shapes\n }\n\n return shapes\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { decomposeClearanceIntoShapes } from \"./shape-distances/decompose-clearance-into-shapes\"\nimport { distanceBetweenShapes } from \"./shape-distances/distance-between-shapes\"\n\nexport const computeClearanceBetweenElements = (\n elm1: AnyCircuitElement,\n elm2: AnyCircuitElement,\n): number => {\n const shapes1 = decomposeClearanceIntoShapes(elm1)\n const shapes2 = decomposeClearanceIntoShapes(elm2)\n\n if (shapes1.length === 0 || shapes2.length === 0) {\n return Number.POSITIVE_INFINITY\n }\n\n let minimumGap = Number.POSITIVE_INFINITY\n\n for (const shape1 of shapes1) {\n for (const shape2 of shapes2) {\n minimumGap = Math.min(minimumGap, distanceBetweenShapes(shape1, shape2))\n }\n }\n\n return minimumGap\n}\n","import type { PcbPin1Location } from \"circuit-json\"\n\ntype Point = { x: number; y: number }\n\nexport interface PcbPin1LocationElement {\n type: string\n x?: number\n y?: number\n points?: readonly Point[]\n port_hints?: readonly unknown[]\n}\n\ntype Pin1Side = \"leftside\" | \"rightside\" | \"topside\" | \"bottomside\"\ntype Pin1Alignment = \"left\" | \"right\" | \"top\" | \"bottom\"\n\nconst PIN1_LOCATION_PARTS = {\n leftside_top: { side: \"leftside\", alignment: \"top\" },\n leftside_bottom: { side: \"leftside\", alignment: \"bottom\" },\n rightside_top: { side: \"rightside\", alignment: \"top\" },\n rightside_bottom: { side: \"rightside\", alignment: \"bottom\" },\n topside_left: { side: \"topside\", alignment: \"left\" },\n topside_right: { side: \"topside\", alignment: \"right\" },\n bottomside_left: { side: \"bottomside\", alignment: \"left\" },\n bottomside_right: { side: \"bottomside\", alignment: \"right\" },\n} as const satisfies Record<\n PcbPin1Location,\n { side: Pin1Side; alignment: Pin1Alignment }\n>\n\nconst PIN1_LOCATIONS = Object.keys(PIN1_LOCATION_PARTS) as PcbPin1Location[]\n\nconst getPadCenter = (pad: PcbPin1LocationElement): Point | null => {\n if (typeof pad.x === \"number\" && typeof pad.y === \"number\") {\n return { x: pad.x, y: pad.y }\n }\n\n if (pad.points && pad.points.length > 0) {\n const xs = pad.points.map((point) => point.x)\n const ys = pad.points.map((point) => point.y)\n return {\n x: (Math.min(...xs) + Math.max(...xs)) / 2,\n y: (Math.min(...ys) + Math.max(...ys)) / 2,\n }\n }\n\n return null\n}\n\nconst getPinNumber = (pad: PcbPin1LocationElement): number | null => {\n for (const hint of pad.port_hints ?? []) {\n const match = String(hint)\n .trim()\n .match(/^(?:pin)?(\\d+)$/i)\n if (match) return Number.parseInt(match[1]!, 10)\n }\n return null\n}\n\nconst pinMatchesLocation = (\n padCenters: Point[],\n pin1Center: Point,\n pin1Location: PcbPin1Location,\n) => {\n const xs = padCenters.map((point) => point.x)\n const ys = padCenters.map((point) => point.y)\n const minX = Math.min(...xs)\n const maxX = Math.max(...xs)\n const minY = Math.min(...ys)\n const maxY = Math.max(...ys)\n const centerX = (minX + maxX) / 2\n const centerY = (minY + maxY) / 2\n const spanX = maxX - minX\n const spanY = maxY - minY\n const tolerance = Math.max(spanX, spanY, 1) * 1e-6\n const { side, alignment } = PIN1_LOCATION_PARTS[pin1Location]\n\n const onRequestedSide =\n (side === \"leftside\" && Math.abs(pin1Center.x - minX) <= tolerance) ||\n (side === \"rightside\" && Math.abs(pin1Center.x - maxX) <= tolerance) ||\n (side === \"topside\" && Math.abs(pin1Center.y - maxY) <= tolerance) ||\n (side === \"bottomside\" && Math.abs(pin1Center.y - minY) <= tolerance)\n\n const atRequestedAlignment =\n (alignment === \"left\" &&\n (spanX <= tolerance || pin1Center.x < centerX - tolerance)) ||\n (alignment === \"right\" &&\n (spanX <= tolerance || pin1Center.x > centerX + tolerance)) ||\n (alignment === \"top\" &&\n (spanY <= tolerance || pin1Center.y > centerY + tolerance)) ||\n (alignment === \"bottom\" &&\n (spanY <= tolerance || pin1Center.y < centerY - tolerance))\n\n return onRequestedSide && atRequestedAlignment\n}\n\n/**\n * Infers the semantic pin 1 location from PCB pad positions and numeric port\n * hints. Returns null when pin 1 is missing or the geometry cannot distinguish\n * a rotation from a reflection.\n */\nexport const analyzePcbPin1Location = (\n elements: readonly PcbPin1LocationElement[],\n): PcbPin1Location | null => {\n const pads = elements.filter(\n (element) =>\n element.type === \"pcb_smtpad\" || element.type === \"pcb_plated_hole\",\n )\n const numberedPads = pads.map((pad) => ({\n center: getPadCenter(pad),\n pinNumber: getPinNumber(pad),\n }))\n const pin1Center = numberedPads.find((pad) => pad.pinNumber === 1)?.center\n const padCenters = numberedPads\n .map((pad) => pad.center)\n .filter((point) => point !== null)\n if (!pin1Center || padCenters.length === 0) return null\n\n const candidates = PIN1_LOCATIONS.filter((pin1Location) =>\n pinMatchesLocation(padCenters, pin1Center, pin1Location),\n )\n if (candidates.length === 1) return candidates[0]!\n if (candidates.length === 0) return null\n\n let nextNumberedPad: { center: Point; pinNumber: number } | undefined\n for (const pad of numberedPads) {\n if (!pad.center || pad.pinNumber === null || pad.pinNumber <= 1) continue\n if (!nextNumberedPad || pad.pinNumber < nextNumberedPad.pinNumber) {\n nextNumberedPad = { center: pad.center, pinNumber: pad.pinNumber }\n }\n }\n if (!nextNumberedPad) return null\n\n const xs = padCenters.map((point) => point.x)\n const ys = padCenters.map((point) => point.y)\n const span = Math.max(\n Math.max(...xs) - Math.min(...xs),\n Math.max(...ys) - Math.min(...ys),\n 1,\n )\n const tolerance = span * 1e-6\n const topologyCandidates = candidates.filter((pin1Location) => {\n const { side } = PIN1_LOCATION_PARTS[pin1Location]\n return side === \"leftside\" || side === \"rightside\"\n ? Math.abs(nextNumberedPad.center.x - pin1Center.x) <= tolerance\n : Math.abs(nextNumberedPad.center.y - pin1Center.y) <= tolerance\n })\n\n return topologyCandidates.length === 1 ? topologyCandidates[0]! : null\n}\n","export type DrcCategory =\n | \"netlist\"\n | \"pin_specification\"\n | \"placement\"\n | \"routing\"\n | \"source\"\n | \"unknown\"\n\ntype DrcLike = {\n type?: string\n error_type?: string\n warning_type?: string\n}\n\nconst NETLIST_TYPES = new Set([\"source_pin_must_be_connected_error\"])\n\nconst PIN_SPECIFICATION_TYPES = new Set([\n \"source_component_pins_underspecified_warning\",\n \"source_no_power_pin_defined_warning\",\n \"source_no_ground_pin_defined_warning\",\n])\n\nconst PLACEMENT_TYPES = new Set([\n \"pcb_placement_error\",\n \"pcb_component_outside_board_error\",\n \"pcb_courtyard_overlap_error\",\n \"pcb_footprint_overlap_error\",\n \"pcb_connector_not_in_accessible_orientation_warning\",\n])\n\nconst ROUTING_TYPES = new Set([\n \"pcb_port_not_connected_error\",\n \"pcb_trace_missing_error\",\n \"pcb_trace_error\",\n \"pcb_via_clearance_error\",\n])\n\nconst SOURCE_TYPES = new Set([\"source_property_ignored_warning\"])\n\nexport const categorizeErrorOrWarning = (\n value: string | DrcLike,\n): DrcCategory => {\n const drcType =\n typeof value === \"string\"\n ? value\n : (value.error_type ?? value.warning_type ?? value.type)\n\n if (!drcType) return \"unknown\"\n\n if (NETLIST_TYPES.has(drcType)) return \"netlist\"\n if (PIN_SPECIFICATION_TYPES.has(drcType)) return \"pin_specification\"\n if (PLACEMENT_TYPES.has(drcType)) return \"placement\"\n if (ROUTING_TYPES.has(drcType)) return \"routing\"\n if (SOURCE_TYPES.has(drcType)) return \"source\"\n\n return \"unknown\"\n}\n","import { useMemo } from \"react\"\nimport { createContext, useContext } from \"react\"\nimport { createStore, type StateProps } from \"../global-store\"\n\nexport const StoreContext = createContext(null)\n\nexport const ContextProviders = ({\n children,\n initialState,\n disablePcbGroups,\n}: {\n children?: any\n initialState?: Partial<StateProps>\n disablePcbGroups?: boolean\n}) => {\n const store = useMemo(\n () => createStore(initialState, disablePcbGroups),\n [disablePcbGroups],\n )\n\n return (\n <StoreContext.Provider value={store as any}>\n {children}\n </StoreContext.Provider>\n )\n}\n","import {\n createStore as createZustandStore,\n useStore as useZustandStore,\n} from \"zustand\"\nimport { StoreContext } from \"./components/ContextProviders\"\nimport type { LayerRef } from \"circuit-json\"\nimport { useContext } from \"react\"\nimport {\n getStoredBoolean,\n getStoredString,\n setStoredBoolean,\n setStoredString,\n STORAGE_KEYS,\n} from \"./hooks/useLocalStorage\"\n\nexport interface State {\n selected_layer: LayerRef\n\n pcb_viewer_id: string\n\n in_edit_mode: boolean\n in_move_footprint_mode: boolean\n is_mouse_over_container: boolean\n is_moving_component: boolean\n is_showing_autorouting: boolean\n is_showing_drc_errors: boolean\n is_showing_drc_warnings: boolean\n\n is_showing_multiple_traces_length: boolean\n is_showing_rats_nest: boolean\n is_showing_copper_pours: boolean\n is_showing_courtyards: boolean\n is_showing_pcb_groups: boolean\n is_showing_group_anchor_offsets: boolean\n is_showing_solder_mask: boolean\n is_showing_silkscreen: boolean\n is_showing_fabrication_notes: boolean\n is_showing_pcb_notes: boolean\n pcb_group_view_mode: \"all\" | \"named_only\"\n\n hovered_error_id: string | null\n focused_error_id: string | null\n\n selectLayer: (layer: LayerRef) => void\n setEditMode: (mode: \"off\" | \"move_footprint\") => void\n setIsMovingComponent: (is_moving: boolean) => void\n setIsShowingRatsNest: (is_showing: boolean) => void\n setIsMouseOverContainer: (is_focused: boolean) => void\n setIsShowingAutorouting: (is_showing: boolean) => void\n setIsShowingMultipleTracesLength: (is_showing: boolean) => void\n setIsShowingDrcErrors: (is_showing: boolean) => void\n setIsShowingDrcWarnings: (is_showing: boolean) => void\n setIsShowingCopperPours: (is_showing: boolean) => void\n setIsShowingCourtyards: (is_showing: boolean) => void\n setIsShowingPcbGroups: (is_showing: boolean) => void\n setIsShowingGroupAnchorOffsets: (is_showing: boolean) => void\n setIsShowingSolderMask: (is_showing: boolean) => void\n setIsShowingSilkscreen: (is_showing: boolean) => void\n setIsShowingFabricationNotes: (is_showing: boolean) => void\n setIsShowingPcbNotes: (is_showing: boolean) => void\n setPcbGroupViewMode: (mode: \"all\" | \"named_only\") => void\n setHoveredErrorId: (errorId: string | null) => void\n setFocusedErrorId: (errorId: string | null) => void\n}\n\nexport type StateProps = {\n [key in keyof State]: State[key] extends boolean ? boolean : never\n}\n\nconst DEFAULT_PCB_GROUP_VIEW_MODE: \"all\" | \"named_only\" =\n process.env.NODE_ENV !== \"production\" ? \"named_only\" : \"all\"\n\nexport const createStore = (\n initialState: Partial<StateProps> = {},\n disablePcbGroups = false,\n) =>\n createZustandStore<State>(\n (set) =>\n ({\n selected_layer: \"top\",\n\n pcb_viewer_id: `pcb_viewer_${Math.random().toString().slice(2, 10)}`,\n\n in_edit_mode: false,\n in_move_footprint_mode: false,\n\n is_moving_component: false,\n is_mouse_over_container: false,\n\n is_showing_multiple_traces_length: false,\n is_showing_rats_nest: false,\n is_showing_autorouting: true,\n is_showing_drc_errors: true,\n is_showing_drc_warnings: true,\n is_showing_copper_pours: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_COPPER_POURS,\n true,\n ),\n is_showing_courtyards: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_COURTYARDS,\n true,\n ),\n is_showing_pcb_groups: disablePcbGroups\n ? false\n : getStoredBoolean(STORAGE_KEYS.IS_SHOWING_PCB_GROUPS, true),\n is_showing_group_anchor_offsets: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_GROUP_ANCHOR_OFFSETS,\n false,\n ),\n is_showing_solder_mask: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_SOLDER_MASK,\n false,\n ),\n is_showing_silkscreen: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_SILKSCREEN,\n true,\n ),\n is_showing_fabrication_notes: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_FABRICATION_NOTES,\n false,\n ),\n is_showing_pcb_notes: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_PCB_NOTES,\n true,\n ),\n pcb_group_view_mode: disablePcbGroups\n ? \"all\"\n : (getStoredString(\n STORAGE_KEYS.PCB_GROUP_VIEW_MODE,\n DEFAULT_PCB_GROUP_VIEW_MODE,\n ) as \"all\" | \"named_only\"),\n\n hovered_error_id: null,\n focused_error_id: null,\n ...initialState,\n\n selectLayer: (layer) => set({ selected_layer: layer }),\n setEditMode: (mode) =>\n set({\n in_edit_mode: mode !== \"off\",\n in_move_footprint_mode: mode === \"move_footprint\",\n is_moving_component: false,\n }),\n setIsShowingRatsNest: (is_showing) =>\n set({ is_showing_rats_nest: is_showing }),\n setIsMovingComponent: (is_moving) =>\n set({ is_moving_component: is_moving }),\n setIsMouseOverContainer: (is_focused) =>\n set({ is_mouse_over_container: is_focused }),\n setIsShowingMultipleTracesLength: (is_showing) =>\n set({ is_showing_multiple_traces_length: is_showing }),\n setIsShowingAutorouting: (is_showing) =>\n set({ is_showing_autorouting: is_showing }),\n setIsShowingDrcErrors: (is_showing) =>\n set({ is_showing_drc_errors: is_showing }),\n setIsShowingDrcWarnings: (is_showing) =>\n set({ is_showing_drc_warnings: is_showing }),\n setIsShowingCopperPours: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_COPPER_POURS, is_showing)\n set({ is_showing_copper_pours: is_showing })\n },\n setIsShowingCourtyards: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_COURTYARDS, is_showing)\n set({ is_showing_courtyards: is_showing })\n },\n setIsShowingPcbGroups: (is_showing) => {\n if (disablePcbGroups) return\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_PCB_GROUPS, is_showing)\n set({ is_showing_pcb_groups: is_showing })\n },\n setIsShowingGroupAnchorOffsets: (is_showing) => {\n setStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_GROUP_ANCHOR_OFFSETS,\n is_showing,\n )\n set({ is_showing_group_anchor_offsets: is_showing })\n },\n setIsShowingSolderMask: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_SOLDER_MASK, is_showing)\n set({ is_showing_solder_mask: is_showing })\n },\n setIsShowingSilkscreen: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_SILKSCREEN, is_showing)\n set({ is_showing_silkscreen: is_showing })\n },\n setIsShowingFabricationNotes: (is_showing) => {\n setStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_FABRICATION_NOTES,\n is_showing,\n )\n set({ is_showing_fabrication_notes: is_showing })\n },\n setIsShowingPcbNotes: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_PCB_NOTES, is_showing)\n set({ is_showing_pcb_notes: is_showing })\n },\n setPcbGroupViewMode: (mode) => {\n if (disablePcbGroups) return\n setStoredString(STORAGE_KEYS.PCB_GROUP_VIEW_MODE, mode)\n set({ pcb_group_view_mode: mode })\n },\n setHoveredErrorId: (errorId) => set({ hovered_error_id: errorId }),\n setFocusedErrorId: (errorId) => set({ focused_error_id: errorId }),\n }) as const,\n )\n\nexport const useGlobalStore = <T = State>(s?: (state: State) => T): T => {\n const store = useContext(StoreContext)\n\n return useZustandStore(store as any, s as any)\n}\n","import { useCallback } from \"react\"\n\nexport const STORAGE_KEYS = {\n IS_SHOWING_PCB_GROUPS: \"pcb_viewer_is_showing_pcb_groups\",\n PCB_GROUP_VIEW_MODE: \"pcb_viewer_group_view_mode\",\n IS_SHOWING_COPPER_POURS: \"pcb_viewer_is_showing_copper_pours\",\n IS_SHOWING_COURTYARDS: \"pcb_viewer_is_showing_courtyards\",\n IS_SHOWING_GROUP_ANCHOR_OFFSETS: \"pcb_viewer_is_showing_group_anchor_offsets\",\n IS_SHOWING_SOLDER_MASK: \"pcb_viewer_is_showing_solder_mask\",\n IS_SHOWING_FABRICATION_NOTES: \"pcb_viewer_is_showing_fabrication_notes\",\n IS_SHOWING_PCB_NOTES: \"pcb_viewer_is_showing_pcb_notes\",\n IS_SHOWING_SILKSCREEN: \"pcb_viewer_is_showing_silkscreen\",\n} as const\n\nexport const getStoredBoolean = (\n key: string,\n defaultValue: boolean,\n): boolean => {\n if (typeof window === \"undefined\") return defaultValue\n try {\n const stored = localStorage.getItem(key)\n return stored !== null ? JSON.parse(stored) : defaultValue\n } catch {\n return defaultValue\n }\n}\n\nexport const setStoredBoolean = (key: string, value: boolean): void => {\n if (typeof window === \"undefined\") return\n try {\n localStorage.setItem(key, JSON.stringify(value))\n } catch {}\n}\n\nexport const getStoredString = (key: string, defaultValue: string): string => {\n if (typeof window === \"undefined\") return defaultValue\n try {\n const stored = localStorage.getItem(key)\n return stored !== null ? JSON.parse(stored) : defaultValue\n } catch {\n return defaultValue\n }\n}\n\nexport const setStoredString = (key: string, value: string): void => {\n if (typeof window === \"undefined\") return\n try {\n localStorage.setItem(key, JSON.stringify(value))\n } catch {}\n}\n\nexport const useLocalStorage = () => {\n const getBoolean = useCallback(\n (key: string, defaultValue: boolean): boolean => {\n return getStoredBoolean(key, defaultValue)\n },\n [],\n )\n\n const setBoolean = useCallback((key: string, value: boolean): void => {\n setStoredBoolean(key, value)\n }, [])\n\n return {\n getBoolean,\n setBoolean,\n }\n}\n\nexport const useLocalStorageValue = (key: string, defaultValue: boolean) => {\n const { getBoolean, setBoolean } = useLocalStorage()\n\n const getValue = useCallback(() => {\n return getBoolean(key, defaultValue)\n }, [getBoolean, key, defaultValue])\n\n const setValue = useCallback(\n (value: boolean) => {\n setBoolean(key, value)\n },\n [setBoolean, key],\n )\n\n return {\n getValue,\n setValue,\n }\n}\n","import { useGlobalStore } from \"../global-store\"\nimport { useEffect } from \"react\"\nimport {\n toast as ogToast,\n ToastContainer as OgToastContainer,\n} from \"react-toastify\"\nimport { injectStyle } from \"react-toastify/dist/inject-style\"\n\nexport const useToast = () => {\n const pcb_viewer_id = useGlobalStore((s) => s.pcb_viewer_id)\n const toast = (message: string, opts?: Parameters<typeof ogToast>[1]) =>\n ogToast(message, {\n containerId: pcb_viewer_id,\n ...opts,\n })\n\n toast.error = (message: string, opts?: Parameters<typeof ogToast.error>[1]) =>\n ogToast.error(message, {\n containerId: pcb_viewer_id,\n ...opts,\n })\n\n // TODO add container id to this\n toast.promise = ogToast.promise\n\n return toast as typeof ogToast\n}\n\nexport const ToastContainer = () => {\n useEffect(() => {\n injectStyle()\n }, [])\n const pcb_viewer_id = useGlobalStore((s) => s.pcb_viewer_id)\n return <OgToastContainer position=\"top-center\" containerId={pcb_viewer_id} />\n}\n","import { useCallback, useEffect, useRef } from 'react';\nexport default function useMountedState() {\n var mountedRef = useRef(false);\n var get = useCallback(function () { return mountedRef.current; }, []);\n useEffect(function () {\n mountedRef.current = true;\n return function () {\n mountedRef.current = false;\n };\n }, []);\n return get;\n}\n","import { useCallback, useState } from 'react';\nvar useSetState = function (initialState) {\n if (initialState === void 0) { initialState = {}; }\n var _a = useState(initialState), state = _a[0], set = _a[1];\n var setState = useCallback(function (patch) {\n set(function (prevState) {\n return Object.assign({}, prevState, patch instanceof Function ? patch(prevState) : patch);\n });\n }, []);\n return [state, setState];\n};\nexport default useSetState;\n","export var noop = function () { };\nexport function on(obj) {\n var args = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n args[_i - 1] = arguments[_i];\n }\n if (obj && obj.addEventListener) {\n obj.addEventListener.apply(obj, args);\n }\n}\nexport function off(obj) {\n var args = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n args[_i - 1] = arguments[_i];\n }\n if (obj && obj.removeEventListener) {\n obj.removeEventListener.apply(obj, args);\n }\n}\nexport var isBrowser = typeof window !== 'undefined';\nexport var isNavigator = typeof navigator !== 'undefined';\n","import writeText from 'copy-to-clipboard';\nimport { useCallback } from 'react';\nimport useMountedState from './useMountedState';\nimport useSetState from './useSetState';\nvar useCopyToClipboard = function () {\n var isMounted = useMountedState();\n var _a = useSetState({\n value: undefined,\n error: undefined,\n noUserInteraction: true,\n }), state = _a[0], setState = _a[1];\n var copyToClipboard = useCallback(function (value) {\n if (!isMounted()) {\n return;\n }\n var noUserInteraction;\n var normalizedValue;\n try {\n // only strings and numbers casted to strings can be copied to clipboard\n if (typeof value !== 'string' && typeof value !== 'number') {\n var error = new Error(\"Cannot copy typeof \" + typeof value + \" to clipboard, must be a string\");\n if (process.env.NODE_ENV === 'development')\n console.error(error);\n setState({\n value: value,\n error: error,\n noUserInteraction: true,\n });\n return;\n }\n // empty strings are also considered invalid\n else if (value === '') {\n var error = new Error(\"Cannot copy empty string to clipboard.\");\n if (process.env.NODE_ENV === 'development')\n console.error(error);\n setState({\n value: value,\n error: error,\n noUserInteraction: true,\n });\n return;\n }\n normalizedValue = value.toString();\n noUserInteraction = writeText(normalizedValue);\n setState({\n value: normalizedValue,\n error: undefined,\n noUserInteraction: noUserInteraction,\n });\n }\n catch (error) {\n setState({\n value: normalizedValue,\n error: error,\n noUserInteraction: noUserInteraction,\n });\n }\n }, []);\n return [state, copyToClipboard];\n};\nexport default useCopyToClipboard;\n","import { useEffect, useLayoutEffect } from 'react';\nimport { isBrowser } from './misc/util';\nvar useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;\nexport default useIsomorphicLayoutEffect;\n","import { useMemo, useState } from 'react';\nimport useIsomorphicLayoutEffect from './useIsomorphicLayoutEffect';\nimport { isBrowser, noop } from './misc/util';\nvar defaultState = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n top: 0,\n left: 0,\n bottom: 0,\n right: 0,\n};\nfunction useMeasure() {\n var _a = useState(null), element = _a[0], ref = _a[1];\n var _b = useState(defaultState), rect = _b[0], setRect = _b[1];\n var observer = useMemo(function () {\n return new window.ResizeObserver(function (entries) {\n if (entries[0]) {\n var _a = entries[0].contentRect, x = _a.x, y = _a.y, width = _a.width, height = _a.height, top_1 = _a.top, left = _a.left, bottom = _a.bottom, right = _a.right;\n setRect({ x: x, y: y, width: width, height: height, top: top_1, left: left, bottom: bottom, right: right });\n }\n });\n }, []);\n useIsomorphicLayoutEffect(function () {\n if (!element)\n return;\n observer.observe(element);\n return function () {\n observer.disconnect();\n };\n }, [element]);\n return [ref, rect];\n}\nexport default isBrowser && typeof window.ResizeObserver !== 'undefined'\n ? useMeasure\n : (function () { return [noop, defaultState]; });\n","import { Matrix, compose, translate, scale } from \"transformation-matrix\"\n\ntype Point = { x: number; y: number }\n\ninterface PinchInput {\n initialTransform: Matrix\n initialTouch1: Point\n initialTouch2: Point\n finalTouch1: Point | null\n finalTouch2: Point | null\n}\n\nexport const computePinchTransform = ({\n initialTransform,\n initialTouch1,\n initialTouch2,\n finalTouch1,\n finalTouch2,\n}: PinchInput): Matrix => {\n if (!finalTouch1 || !finalTouch2) {\n return initialTransform\n }\n // Calculate initial and current centers\n const initialCenter = {\n x: (initialTouch1.x + initialTouch2.x) / 2,\n y: (initialTouch1.y + initialTouch2.y) / 2,\n }\n const currentCenter = {\n x: (finalTouch1.x + finalTouch2.x) / 2,\n y: (finalTouch1.y + finalTouch2.y) / 2,\n }\n\n // Calculate initial and current distances between touch points\n const initialDist = Math.hypot(\n initialTouch2.x - initialTouch1.x,\n initialTouch2.y - initialTouch1.y,\n )\n const currentDist = Math.hypot(\n finalTouch2.x - finalTouch1.x,\n finalTouch2.y - finalTouch1.y,\n )\n\n // Calculate the scaling factor, prevent division by zero\n const s = initialDist === 0 ? 1 : currentDist / initialDist\n\n // Calculate the translation delta\n const deltaX = currentCenter.x - initialCenter.x\n const deltaY = currentCenter.y - initialCenter.y\n\n // Compose the transformation matrix\n // 1. Translate by the delta movement of the center\n // 2. Translate to the initial center\n // 3. Scale around the initial center\n // 4. Translate back from the initial center\n // 5. Apply the initial transform before the pinch started\n const pinchTransform = compose(\n translate(deltaX, deltaY),\n translate(initialCenter.x, initialCenter.y),\n scale(s, s),\n translate(-initialCenter.x, -initialCenter.y),\n initialTransform,\n )\n\n return pinchTransform\n}\n","import {\n Matrix,\n identity,\n translate,\n compose,\n applyToPoint,\n scale,\n} from \"transformation-matrix\"\n// import { fromTwoMovingPoints } from \"transformation-matrix\" // Not used currently\nimport { useCallback, useEffect, useReducer, useRef, useState } from \"react\"\nimport { computePinchTransform } from \"./computePinchTransform\"\n\ntype Point = { x: number; y: number }\n\ninterface Props {\n canvasElm?: HTMLElement\n transform?: Matrix\n initialTransform?: Matrix\n onSetTransform?: (transform: Matrix) => any\n enabled?: boolean\n shouldDrag?: (e: MouseEvent | TouchEvent | WheelEvent) => boolean\n}\n\nexport const useMouseMatrixTransform = (props: Props = {}) => {\n const extRef = useRef<any>(null)\n const [lastDragCancelTime, setLastDragCancelTime] = useState(0)\n const outerCanvasElm = props.canvasElm ?? extRef.current\n const [internalTransform, setInternalTransform] = useState<Matrix>(\n props.initialTransform ?? identity(),\n )\n const [waitCounter, setWaitCounter] = useState(0)\n const [extChangeCounter, incExtChangeCounter] = useReducer((s) => s + 1, 0)\n\n const setTransform = useCallback(\n (newTransform: Matrix) => {\n if (props.onSetTransform) {\n props.onSetTransform(newTransform)\n }\n if (!props.transform) {\n setInternalTransform(newTransform)\n }\n },\n [props.onSetTransform, setInternalTransform],\n )\n\n const setTransformExt = useCallback(\n (newTransform: Matrix) => {\n setTransform(newTransform)\n incExtChangeCounter()\n },\n [setTransform],\n )\n\n const transform = props.transform ?? internalTransform\n\n const cancelDrag = useCallback(() => {\n setLastDragCancelTime(Date.now())\n }, [])\n\n const gestureModeRef = useRef<\"none\" | \"drag\" | \"pinch\">(\"none\")\n // const lastTouchRef = useRef<{ x: number; y: number } | null>(null) // No longer needed for delta calculation\n const dragDataRef = useRef<{\n initialTransform: Matrix\n initialTouch: Point\n } | null>(null)\n const pinchDataRef = useRef<{\n initialTransform: Matrix\n initialTouch1: Point\n initialTouch2: Point\n finalTouch1: Point | null\n finalTouch2: Point | null\n } | null>(null)\n\n useEffect(() => {\n const canvasElm: HTMLCanvasElement | null =\n props.canvasElm ?? extRef.current\n if (canvasElm && !outerCanvasElm) {\n setWaitCounter(waitCounter + 1)\n return\n }\n if (!canvasElm) {\n const timeout = setTimeout(() => {\n setWaitCounter(waitCounter + 1)\n }, 100)\n return () => clearTimeout(timeout)\n }\n let init_tf = props.transform ?? internalTransform\n\n let m0: Point = { x: 0, y: 0 },\n m1: Point = { x: 0, y: 0 },\n md = false,\n mlastrel: Point = { x: 0, y: 0 }\n\n const getMousePos = (e: MouseEvent) => {\n return {\n x: e.pageX - canvasElm.getBoundingClientRect().left - window.scrollX,\n y: e.pageY - canvasElm.getBoundingClientRect().top - window.scrollY,\n }\n }\n\n function handleMouseDown(e: MouseEvent) {\n if (props.enabled === false) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n m0 = getMousePos(e)\n if (Date.now() - lastDragCancelTime < 100) return\n md = true\n e.preventDefault()\n }\n function handleMouseUp(e: MouseEvent) {\n if (!md || props.enabled === false) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n m1 = getMousePos(e)\n\n const new_tf = compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf)\n setTransform(new_tf)\n init_tf = new_tf\n\n md = false\n }\n function handleMouseMove(e: MouseEvent) {\n mlastrel = getMousePos(e)\n if (!md || props.enabled === false) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n m1 = getMousePos(e)\n const new_tf = compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf)\n setTransform(new_tf)\n }\n function handleMouseWheel(e: WheelEvent) {\n if (props.enabled === false) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n const center = getMousePos(e)\n const new_tf = compose(\n translate(center.x, center.y),\n scale(1 - e.deltaY / 1000, 1 - e.deltaY / 1000),\n translate(-center.x, -center.y),\n init_tf,\n )\n setTransform(new_tf)\n init_tf = new_tf\n e.preventDefault()\n }\n function handleMouseOut(e: MouseEvent) {\n if (!md) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n\n if (canvasElm) {\n const boundingBox = canvasElm.getBoundingClientRect()\n if (\n e.clientX >= boundingBox.left + 10 &&\n e.clientX <= boundingBox.right - 10 &&\n e.clientY >= boundingBox.top + 10 &&\n e.clientY <= boundingBox.bottom - 10\n ) {\n return\n }\n }\n\n md = false\n m1 = getMousePos(e)\n const new_tf = compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf)\n setTransform(new_tf)\n init_tf = new_tf\n }\n\n function handleTouchStart(e: TouchEvent) {\n e.preventDefault()\n if (props.enabled === false) return\n if (e.touches.length === 1) {\n // Start Drag\n gestureModeRef.current = \"drag\"\n const touch = e.touches[0]\n dragDataRef.current = {\n initialTransform: init_tf, // Capture transform before drag starts\n initialTouch: { x: touch.clientX, y: touch.clientY },\n }\n } else if (e.touches.length === 2) {\n // Start Pinch\n gestureModeRef.current = \"pinch\"\n const touch1 = e.touches[0]\n const touch2 = e.touches[1]\n pinchDataRef.current = {\n initialTransform: init_tf, // Store the transform at the start of the pinch\n initialTouch1: { x: touch1.clientX, y: touch1.clientY },\n initialTouch2: { x: touch2.clientX, y: touch2.clientY },\n finalTouch1: null,\n finalTouch2: null,\n }\n }\n }\n\n function handleTouchMove(e: TouchEvent) {\n e.preventDefault()\n if (props.enabled === false) return\n if (\n gestureModeRef.current === \"drag\" &&\n e.touches.length === 1 &&\n dragDataRef.current // Check if drag has started\n ) {\n // Handle Drag Move\n const touch = e.touches[0]\n const currentTouch = { x: touch.clientX, y: touch.clientY }\n const deltaX = currentTouch.x - dragDataRef.current.initialTouch.x\n const deltaY = currentTouch.y - dragDataRef.current.initialTouch.y\n\n // Apply delta to the transform that existed *before* the drag started\n const new_tf = compose(\n translate(deltaX, deltaY),\n dragDataRef.current.initialTransform,\n )\n setTransform(new_tf)\n // Do not update init_tf here\n } else if (\n gestureModeRef.current === \"pinch\" &&\n e.touches.length === 2 &&\n pinchDataRef.current\n ) {\n const touch1 = e.touches[0]\n const touch2 = e.touches[1]\n\n pinchDataRef.current.finalTouch1 = {\n x: touch1.clientX,\n y: touch1.clientY,\n }\n pinchDataRef.current.finalTouch2 = {\n x: touch2.clientX,\n y: touch2.clientY,\n }\n\n const new_tf = computePinchTransform(pinchDataRef.current)\n setTransform(new_tf)\n // Don't update init_tf here, only on touch end\n }\n }\n\n function handleTouchEnd(e: TouchEvent) {\n e.preventDefault()\n\n // Use changedTouches to get the final position of the lifted finger(s)\n const finalTouch = e.changedTouches[0]\n\n if (\n gestureModeRef.current === \"drag\" &&\n dragDataRef.current && // Check if drag was active\n finalTouch // Ensure we have the final touch info\n ) {\n // Drag End\n const finalTouchPos = { x: finalTouch.clientX, y: finalTouch.clientY }\n const deltaX = finalTouchPos.x - dragDataRef.current.initialTouch.x\n const deltaY = finalTouchPos.y - dragDataRef.current.initialTouch.y\n\n // Calculate the final transform based on the total delta\n const new_tf = compose(\n translate(deltaX, deltaY),\n dragDataRef.current.initialTransform,\n )\n setTransform(new_tf) // Update the visual state\n init_tf = new_tf // Lock in the transform for the next gesture\n } else if (gestureModeRef.current === \"pinch\" && pinchDataRef.current) {\n const new_tf = computePinchTransform(pinchDataRef.current)\n setTransform(new_tf) // Ensure the final state is set\n init_tf = new_tf // Update init_tf\n }\n\n // Reset gesture state and data refs\n gestureModeRef.current = \"none\"\n // lastTouchRef.current = null // No longer used\n dragDataRef.current = null\n pinchDataRef.current = null\n }\n\n canvasElm.addEventListener(\"mousedown\", handleMouseDown)\n canvasElm.addEventListener(\"mouseup\", handleMouseUp)\n window.addEventListener(\"mousemove\", handleMouseMove)\n canvasElm.addEventListener(\"mouseout\", handleMouseOut)\n canvasElm.addEventListener(\"wheel\", handleMouseWheel)\n\n canvasElm.addEventListener(\"touchstart\", handleTouchStart, {\n passive: false,\n })\n canvasElm.addEventListener(\"touchmove\", handleTouchMove, {\n passive: false,\n })\n canvasElm.addEventListener(\"touchend\", handleTouchEnd, { passive: false })\n canvasElm.addEventListener(\"touchcancel\", handleTouchEnd, {\n passive: false,\n })\n\n return () => {\n canvasElm.removeEventListener(\"mousedown\", handleMouseDown)\n canvasElm.removeEventListener(\"mouseup\", handleMouseUp)\n window.removeEventListener(\"mousemove\", handleMouseMove)\n canvasElm.removeEventListener(\"mouseout\", handleMouseOut)\n canvasElm.removeEventListener(\"wheel\", handleMouseWheel)\n\n canvasElm.removeEventListener(\"touchstart\", handleTouchStart)\n canvasElm.removeEventListener(\"touchmove\", handleTouchMove)\n canvasElm.removeEventListener(\"touchend\", handleTouchEnd)\n canvasElm.removeEventListener(\"touchcancel\", handleTouchEnd)\n }\n }, [\n outerCanvasElm,\n waitCounter,\n extChangeCounter,\n lastDragCancelTime,\n props.enabled,\n props.shouldDrag,\n ])\n\n const applyTransformToPoint = useCallback(\n (obj: Point | [number, number]) => applyToPoint(transform, obj),\n [transform],\n )\n\n return {\n ref: extRef,\n transform,\n applyTransformToPoint,\n setTransform: setTransformExt,\n cancelDrag,\n }\n}\n\nexport default useMouseMatrixTransform\n","type NodeId = string\n\nexport function findConnectedNetworks(\n connections: Array<NodeId[]>,\n): Record<string, string[]> {\n const networks: Map<string, Set<string>> = new Map()\n let netCounter = 0\n\n function getOrCreateNetwork(nodeId: string): Set<string> {\n for (const [, network] of networks) {\n if (network.has(nodeId)) {\n return network\n }\n }\n const newNetwork = new Set<string>()\n networks.set(`connectivity_net${netCounter++}`, newNetwork)\n return newNetwork\n }\n\n for (const connection of connections) {\n let network: Set<string> | null = null\n\n for (const nodeId of connection) {\n if (!network) {\n network = getOrCreateNetwork(nodeId)\n } else if (!network.has(nodeId)) {\n const existingNetwork = getOrCreateNetwork(nodeId)\n if (existingNetwork !== network) {\n // Merge networks\n for (const node of existingNetwork) {\n network.add(node)\n }\n networks.delete(\n Array.from(networks.entries()).find(\n ([, net]) => net === existingNetwork,\n )![0],\n )\n }\n }\n network.add(nodeId)\n }\n }\n\n return Object.fromEntries(\n Array.from(networks.entries()).map(([netId, connectedNodes]) => [\n netId,\n Array.from(connectedNodes),\n ]),\n )\n}\n","export class ConnectivityMap {\n netMap: Record<string, string[]>\n\n idToNetMap: Record<string, string>\n\n constructor(netMap: Record<string, string[]>) {\n this.netMap = netMap\n this.idToNetMap = {}\n for (const [netId, ids] of Object.entries(netMap)) {\n for (const id of ids) {\n this.idToNetMap[id] = netId\n }\n }\n }\n\n addConnections(connections: string[][]) {\n for (const connection of connections) {\n const existingNets = new Set<string>()\n\n // Find all existing nets for the connection\n for (const id of connection) {\n const existingNetId = this.idToNetMap[id]\n if (existingNetId) {\n existingNets.add(existingNetId)\n }\n }\n\n let targetNetId: string\n\n if (existingNets.size === 0) {\n // If no existing nets found, create a new one\n targetNetId = `connectivity_net${Object.keys(this.netMap).length}`\n this.netMap[targetNetId] = []\n } else if (existingNets.size === 1) {\n // If only one existing net found, use it\n targetNetId =\n existingNets.values().next().value ??\n `connectivity_net${Object.keys(this.netMap).length}`\n } else {\n // If multiple nets found, merge them\n targetNetId =\n existingNets.values().next().value ??\n `connectivity_net${Object.keys(this.netMap).length}`\n for (const netId of existingNets) {\n if (netId !== targetNetId) {\n this.netMap[targetNetId].push(...this.netMap[netId])\n\n // we could delete the net, but setting it to reference the other net\n // will make sure any usage of the old netId will still work\n this.netMap[netId] = this.netMap[targetNetId]\n for (const id of this.netMap[targetNetId]) {\n this.idToNetMap[id] = targetNetId\n }\n }\n }\n }\n\n // Add all ids to the target net\n for (const id of connection) {\n if (!this.netMap[targetNetId].includes(id)) {\n this.netMap[targetNetId].push(id)\n }\n this.idToNetMap[id] = targetNetId\n }\n }\n }\n\n getIdsConnectedToNet(netId: string): string[] {\n return this.netMap[netId] || []\n }\n\n getNetConnectedToId(id: string): string | undefined {\n return this.idToNetMap[id]\n }\n\n areIdsConnected(id1: string, id2: string): boolean {\n if (id1 === id2) return true\n const netId1 = this.getNetConnectedToId(id1)\n if (!netId1) return false\n const netId2 = this.getNetConnectedToId(id2)\n if (!netId2) return false\n return netId1 === netId2 || netId2 === id1 || netId2 === id1\n }\n\n areAllIdsConnected(ids: string[]): boolean {\n const netId = this.getNetConnectedToId(ids[0])\n for (const id of ids) {\n const nextNetId = this.getNetConnectedToId(id)\n if (nextNetId === undefined) {\n return false\n }\n if (nextNetId !== netId) {\n return false\n }\n }\n return true\n }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getSourcePortConnectivityMapFromCircuitJson = (\n circuitJson: AnyCircuitElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push([\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ])\n } else if (element.type === \"source_component\") {\n if (element.internally_connected_source_port_ids) {\n for (const portGroup of element.internally_connected_source_port_ids) {\n connections.push(portGroup)\n }\n }\n } else if (element.type === \"source_component_internal_connection\") {\n connections.push(element.source_port_ids)\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement, PcbTraceRoutePoint } from \"circuit-json\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getFullConnectivityMapFromCircuitJson = (\n circuitJson: AnyCircuitElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push(\n [\n element.source_trace_id,\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ].filter(Boolean),\n )\n } else if (element.type === \"pcb_port\") {\n const { pcb_port_id, source_port_id } = element\n if (source_port_id && pcb_port_id) {\n connections.push([source_port_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_smtpad\") {\n const { pcb_smtpad_id, pcb_port_id } = element\n if (pcb_port_id && pcb_smtpad_id) {\n connections.push([pcb_smtpad_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_plated_hole\") {\n const { pcb_plated_hole_id, pcb_port_id } = element\n if (pcb_port_id && pcb_plated_hole_id) {\n connections.push([pcb_plated_hole_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_trace\") {\n const { pcb_trace_id, source_trace_id } = element\n const route = Array.isArray(element.route)\n ? element.route.filter(\n (rp: PcbTraceRoutePoint) => rp && rp.route_type === \"wire\",\n )\n : []\n if (source_trace_id && pcb_trace_id) {\n connections.push([pcb_trace_id, source_trace_id])\n }\n if (Array.isArray(route)) {\n const startId = route.find(\n (rp) => rp?.start_pcb_port_id,\n )?.start_pcb_port_id\n const endId = route.find((rp) => rp?.end_pcb_port_id)?.end_pcb_port_id\n if (startId && pcb_trace_id && endId) {\n connections.push([startId, pcb_trace_id, endId])\n }\n }\n } else if (element.type === \"pcb_via\") {\n const { pcb_via_id, pcb_trace_id, source_trace_id, source_net_id } =\n element\n const connectedIds = [\n pcb_trace_id,\n source_trace_id,\n source_net_id,\n ].filter((connectedId): connectedId is string => Boolean(connectedId))\n if (pcb_via_id && connectedIds.length > 0) {\n connections.push([pcb_via_id, ...connectedIds])\n }\n } else if (element.type === \"source_component\") {\n if (element.internally_connected_source_port_ids) {\n for (const portGroup of element.internally_connected_source_port_ids) {\n connections.push(portGroup)\n }\n }\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement, PCBPort, PCBTrace } from \"circuit-json\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\nimport { doesLineIntersectLine } from \"@tscircuit/math-utils\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\n\n/**\n * A PCB Connectivity Map is a connectivity map that has analyzed what traces and ports are actually connected on the\n * PCB.\n *\n * This is useful for determining how to route a trace on the PCB. For example, you may want to determine where the\n * nearest connected net point is to connect an unrouted pin.\n */\nexport class PcbConnectivityMap {\n circuitJson: AnyCircuitElement[]\n traceIdToElm: Map<string, PCBTrace>\n portIdToElm: Map<string, PCBPort>\n connMap: ConnectivityMap\n\n constructor(circuitJson?: AnyCircuitElement[]) {\n this.circuitJson = circuitJson || []\n this.traceIdToElm = new Map()\n this.portIdToElm = new Map()\n if (circuitJson) {\n this._buildTraceMap()\n this._buildPortMap()\n this.connMap = this._buildTraceConnectivityMap()\n } else {\n this.connMap = new ConnectivityMap({})\n }\n }\n\n private _buildPortMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_port\") {\n this.portIdToElm.set(element.pcb_port_id, element as PCBPort)\n }\n }\n }\n\n private _buildTraceMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_trace\") {\n this.traceIdToElm.set(element.pcb_trace_id, element as PCBTrace)\n }\n }\n }\n\n private _buildTraceConnectivityMap(): ConnectivityMap {\n const connections: string[][] = []\n const traceIds = Array.from(this.traceIdToElm.keys())\n\n for (let i = 0; i < traceIds.length; i++) {\n for (let j = i + 1; j < traceIds.length; j++) {\n const trace1 = this.traceIdToElm.get(traceIds[i])!\n const trace2 = this.traceIdToElm.get(traceIds[j])!\n if (this._arePcbTracesConnected(trace1, trace2)) {\n connections.push([traceIds[i], traceIds[j]])\n }\n }\n }\n\n for (const port of this.portIdToElm.values()) {\n for (const trace of this.traceIdToElm.values()) {\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id === port.pcb_port_id) {\n connections.push([port.pcb_port_id, trace.pcb_trace_id])\n } else if (rp.end_pcb_port_id === port.pcb_port_id) {\n connections.push([trace.pcb_trace_id, port.pcb_port_id])\n }\n }\n }\n }\n }\n\n return new ConnectivityMap(findConnectedNetworks(connections))\n }\n\n addTrace(trace: PCBTrace) {\n this.traceIdToElm.set(trace.pcb_trace_id, trace)\n const connections: string[][] = []\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id) {\n connections.push([rp.start_pcb_port_id, trace.pcb_trace_id])\n }\n if (rp.end_pcb_port_id) {\n connections.push([rp.end_pcb_port_id, trace.pcb_trace_id])\n }\n }\n }\n\n this.connMap.addConnections(connections)\n }\n\n _arePcbTracesConnected(trace1: PCBTrace, trace2: PCBTrace): boolean {\n for (let i = 0; i < trace1.route.length - 1; i++) {\n const segment1A = trace1.route[i]\n const segment1B = trace1.route[i + 1]\n if (segment1A.route_type !== \"wire\") continue\n if (segment1B.route_type !== \"wire\") continue\n for (let j = 0; j < trace2.route.length - 1; j++) {\n const segment2A = trace2.route[j]\n const segment2B = trace2.route[j + 1]\n\n if (segment2A.route_type !== \"wire\") continue\n if (segment2B.route_type !== \"wire\") continue\n\n // Check if lines are overlapping\n const isOverlapping = doesLineIntersectLine(\n [segment1A, segment1B],\n [segment2A, segment2B],\n {\n lineThickness: (segment1A.width + segment2A.width) / 2,\n },\n )\n if (isOverlapping) {\n return true\n }\n }\n }\n return false\n }\n\n areTracesConnected(traceId1: string, traceId2: string): boolean {\n return this.connMap.areIdsConnected(traceId1, traceId2)\n }\n\n getAllTracesConnectedToTrace(traceId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(traceId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n\n getAllTracesConnectedToPort(portId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(portId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n}\n","export interface Point {\n x: number\n y: number\n trace_width?: number\n}\n\nexport function getExpandedStroke(\n strokeInput: (Point | [number, number] | number[])[],\n defaultWidth: number,\n): Point[] {\n if (strokeInput.length < 2) {\n throw new Error(\"Stroke must have at least two points\")\n }\n\n const stroke: Point[] = strokeInput.map((point) => {\n if (Array.isArray(point)) {\n return { x: point[0], y: point[1] }\n }\n return point as Point\n })\n\n const leftSide: Point[] = []\n const rightSide: Point[] = []\n\n function getNormal(p1: Point, p2: Point): Point {\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n const length = Math.sqrt(dx * dx + dy * dy)\n return { x: -dy / length, y: dx / length }\n }\n\n function addPoint(\n point: Point,\n normal: Point,\n factor: number,\n width: number,\n ) {\n const halfWidth = width / 2\n const newPoint = {\n x: point.x + normal.x * halfWidth * factor,\n y: point.y + normal.y * halfWidth * factor,\n }\n if (factor > 0) {\n leftSide.push(newPoint)\n } else {\n rightSide.unshift(newPoint)\n }\n }\n\n // Handle the first point\n const firstNormal = getNormal(stroke[0]!, stroke[1]!)\n const firstWidth = stroke[0]!.trace_width ?? defaultWidth\n addPoint(stroke[0]!, firstNormal, 1, firstWidth)\n addPoint(stroke[0]!, firstNormal, -1, firstWidth)\n\n // Handle middle points\n for (let i = 1; i < stroke.length - 1; i++) {\n const prev = stroke[i - 1]!\n const current = stroke[i]!\n const next = stroke[i + 1]!\n\n const normalPrev = getNormal(prev, current)\n const normalNext = getNormal(current, next)\n\n // Calculate miter line\n const miterX = normalPrev.x + normalNext.x\n const miterY = normalPrev.y + normalNext.y\n const miterLength = Math.sqrt(miterX * miterX + miterY * miterY)\n\n const currentWidth = current.trace_width ?? defaultWidth\n\n // Check if miter is too long (sharp corner)\n const miterLimit = 2 // Adjust this value to control when to bevel\n if (miterLength / 2 > miterLimit * (currentWidth / 2)) {\n // Use bevel join\n addPoint(current, normalPrev, 1, currentWidth)\n addPoint(current, normalNext, 1, currentWidth)\n addPoint(current, normalPrev, -1, currentWidth)\n addPoint(current, normalNext, -1, currentWidth)\n } else {\n // Use miter join\n const scale = 1 / miterLength\n addPoint(\n current,\n { x: miterX * scale, y: miterY * scale },\n 1,\n currentWidth,\n )\n addPoint(\n current,\n { x: miterX * scale, y: miterY * scale },\n -1,\n currentWidth,\n )\n }\n }\n\n // Handle the last point\n const lastNormal = getNormal(\n stroke[stroke.length - 2]!,\n stroke[stroke.length - 1]!,\n )\n const lastWidth = stroke[stroke.length - 1]!.trace_width ?? defaultWidth\n addPoint(stroke[stroke.length - 1]!, lastNormal, 1, lastWidth)\n addPoint(stroke[stroke.length - 1]!, lastNormal, -1, lastWidth)\n\n // Combine left and right sides to form a closed polygon\n return [...leftSide, ...rightSide]\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { su } from \"@tscircuit/circuit-json-util\"\nimport type { Primitive } from \"./types\"\nimport { type Point, getExpandedStroke } from \"./util/expand-stroke\"\nimport { distance } from \"circuit-json\"\nimport { convertSmtpadRect } from \"./element-to-primitive-converters/convert-smtpad-rect\"\nimport { convertSmtpadCircle } from \"./element-to-primitive-converters/convert-smtpad-circle\"\nimport { convertSmtpadPolygon } from \"./element-to-primitive-converters/convert-smtpad-polygon\"\nimport {\n convertSmtpadPill,\n convertSmtpadRotatedPill,\n} from \"./element-to-primitive-converters/convert-smtpad-pill\"\n\nimport { convertPcbCopperTextToPrimitive } from \"./element-to-primitive/convert-pcb-copper-text-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nlet globalPcbDrawingObjectCount = 0\n\nexport const getNewPcbDrawingObjectId = (prefix: string) =>\n `${prefix}_${globalPcbDrawingObjectCount++}`\n\nexport const normalizePolygonPoints = (points: Point[] | undefined) =>\n (points ?? []).map((point) => ({\n x: distance.parse(point.x),\n y: distance.parse(point.y),\n }))\n\nexport const convertElementToPrimitives = (\n element: AnyCircuitElement,\n allElements: AnyCircuitElement[],\n): (Primitive & MetaData)[] => {\n const _parent_pcb_component =\n \"pcb_component_id\" in element\n ? allElements.find(\n (elm) =>\n elm.type === \"pcb_component\" &&\n elm.pcb_component_id === element.pcb_component_id,\n )\n : undefined\n const _parent_source_component =\n _parent_pcb_component && \"source_component_id\" in _parent_pcb_component\n ? allElements.find(\n (elm) =>\n elm.type === \"source_component\" &&\n elm.source_component_id ===\n _parent_pcb_component.source_component_id,\n )\n : undefined\n\n const _source_port_id =\n \"source_port_id\" in element\n ? element.source_port_id\n : \"pcb_port_id\" in element\n ? su(allElements).pcb_port.get(element.pcb_port_id!)?.source_port_id\n : undefined\n\n const _source_port = _source_port_id\n ? allElements.find(\n (e) => e.type === \"source_port\" && e.source_port_id === _source_port_id,\n )\n : undefined\n\n switch (element.type) {\n case \"pcb_smtpad\": {\n const metadata: MetaData = {\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n }\n\n if (element.shape === \"rect\" || element.shape === \"rotated_rect\") {\n return convertSmtpadRect(element, metadata)\n } else if (element.shape === \"circle\") {\n return convertSmtpadCircle(element, metadata)\n } else if (element.shape === \"polygon\") {\n return convertSmtpadPolygon(element, metadata)\n } else if (element.shape === \"pill\") {\n return convertSmtpadPill(element, metadata)\n } else if (element.shape === \"rotated_pill\") {\n return convertSmtpadRotatedPill(element, metadata)\n }\n return []\n }\n\n case \"pcb_trace\": {\n const primitives: Primitive[] = []\n\n if (element.route_thickness_mode === \"interpolated\") {\n // Prepare the stroke input\n const strokeInput: Point[] = element.route.flatMap((routePoint) => {\n if (routePoint.route_type === \"through_pad\") {\n return [\n {\n ...routePoint.start,\n trace_width: routePoint.width,\n },\n {\n ...routePoint.end,\n trace_width: routePoint.width,\n },\n ]\n }\n\n return [\n {\n x: routePoint.x,\n y: routePoint.y,\n trace_width:\n routePoint.route_type === \"wire\" ? routePoint.width : 0.5,\n },\n ]\n })\n\n // Use getExpandedStroke to generate the polygon points\n const expandedStroke = getExpandedStroke(strokeInput, 0.5) // Use 0.5 as default width\n\n const layer = (element.route[0] as any).layer\n\n // Generate a single polygon primitive from the expanded stroke\n primitives.push({\n _pcb_drawing_object_id: `polygon_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"polygon\",\n points: expandedStroke,\n layer, // same layer for all points\n })\n\n // Add circles for vias\n element.route.forEach((r) => {\n if (r.route_type === \"via\") {\n primitives.push({\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"circle\",\n x: r.x,\n y: r.y,\n r: (r as any).outer_diameter / 2,\n layer: (r as any).from_layer,\n })\n }\n })\n\n return primitives\n }\n let prevX: number | null = null\n let prevY: number | null = null\n\n for (const route of element.route) {\n if (route.route_type === \"wire\") {\n if (prevX !== null && prevY !== null) {\n primitives.push({\n _pcb_drawing_object_id: `line_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"line\",\n x1: prevX,\n y1: prevY,\n x2: route.x,\n y2: route.y,\n width: route.width,\n squareCap: false,\n layer: route.layer,\n })\n }\n\n prevX = route.x\n prevY = route.y\n }\n }\n\n return primitives\n }\n // The builder currently outputs these as smtpads and holes, so pcb_via isn't\n // used, but that maybe should be changed\n case \"pcb_via\": {\n const { x, y, outer_diameter, hole_diameter } = element\n const from_layer = element.from_layer\n const to_layer = element.to_layer\n const layers = element.layers\n\n // Support both old format (from_layer/to_layer) and new format (layers array)\n const copperLayers: string[] = []\n if (from_layer && to_layer) {\n copperLayers.push(from_layer, to_layer)\n } else if (layers && Array.isArray(layers)) {\n copperLayers.push(...layers)\n } else {\n // Default to top and bottom if no layer info\n copperLayers.push(\"top\", \"bottom\")\n }\n\n // Create the outer copper circles on the via layers\n // and the inner drill hole, similar to how pcb_plated_hole works\n const primitives: Primitive[] = []\n\n // Add outer copper circles for each layer\n for (const layer of copperLayers) {\n primitives.push({\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x,\n y,\n r: outer_diameter / 2,\n layer,\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n })\n }\n\n // Add inner drill hole (drawn on top due to layer order)\n primitives.push({\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x,\n y,\n r: hole_diameter / 2,\n layer: \"drill\",\n _element: element,\n })\n\n return primitives\n }\n\n case \"pcb_plated_hole\": {\n if (element.shape === \"circle\") {\n const { x, y, hole_diameter, outer_diameter } = element\n\n return [\n {\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x,\n y,\n r: outer_diameter / 2,\n // TODO support layer on pcb_plated_hole\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n },\n {\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x,\n y,\n r: hole_diameter / 2,\n // TODO support layer on pcb_plated_hole\n layer: \"drill\",\n _element: element,\n\n // double highlights are annoying\n // _element: element,\n },\n ]\n } else if (element.shape === \"oval\") {\n const { x, y, outer_height, outer_width, hole_height, hole_width } =\n element\n\n return [\n {\n _pcb_drawing_object_id: `oval_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"oval\",\n x,\n y,\n rX: outer_width / 2,\n rY: outer_height / 2,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n },\n {\n _pcb_drawing_object_id: `oval_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"oval\",\n x,\n y,\n rX: hole_width / 2,\n rY: hole_height / 2,\n layer: \"drill\",\n },\n ]\n } else if (element.shape === \"pill\") {\n const { x, y, outer_height, outer_width, hole_height, hole_width } =\n element\n\n return [\n {\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"pill\",\n x,\n y,\n w: outer_width,\n h: outer_height,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n ccw_rotation: element.ccw_rotation,\n },\n {\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"pill\",\n x,\n y,\n w: hole_width,\n h: hole_height,\n layer: \"drill\",\n ccw_rotation: element.ccw_rotation,\n },\n ]\n } else if (element.shape === \"circular_hole_with_rect_pad\") {\n const {\n x,\n y,\n hole_diameter,\n rect_pad_width,\n rect_pad_height,\n rect_border_radius,\n hole_offset_x,\n hole_offset_y,\n } = element\n const parsed_hole_offset_x = distance.parse(hole_offset_x ?? 0)\n const parsed_hole_offset_y = distance.parse(hole_offset_y ?? 0)\n\n return [\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n roundness: rect_border_radius,\n },\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"bottom\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n roundness: rect_border_radius,\n is_hoverable: false,\n },\n {\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"circle\",\n x: x + parsed_hole_offset_x,\n y: y + parsed_hole_offset_y,\n r: hole_diameter / 2,\n layer: \"drill\",\n is_hoverable: false,\n },\n ]\n } else if (element.shape === \"pill_hole_with_rect_pad\") {\n const {\n x,\n y,\n hole_width,\n hole_height,\n rect_pad_width,\n rect_pad_height,\n rect_border_radius,\n } = element\n\n return [\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n roundness: rect_border_radius,\n },\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"bottom\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n roundness: rect_border_radius,\n is_hoverable: false,\n },\n {\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"pill\",\n x,\n y,\n w: hole_width,\n h: hole_height,\n layer: \"drill\",\n is_hoverable: false,\n },\n ]\n } else if (element.shape === \"rotated_pill_hole_with_rect_pad\") {\n const {\n x,\n y,\n hole_width,\n hole_height,\n hole_ccw_rotation,\n rect_pad_width,\n rect_pad_height,\n rect_ccw_rotation,\n rect_border_radius,\n } = element\n\n return [\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n ccw_rotation: rect_ccw_rotation,\n roundness: rect_border_radius,\n },\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"bottom\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n ccw_rotation: rect_ccw_rotation,\n roundness: rect_border_radius,\n is_hoverable: false,\n },\n {\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"pill\",\n x,\n y,\n w: hole_width,\n h: hole_height,\n layer: \"drill\",\n ccw_rotation: hole_ccw_rotation,\n is_hoverable: false,\n },\n ]\n } else if (element.shape === \"hole_with_polygon_pad\") {\n const {\n x,\n y,\n pad_outline,\n hole_shape,\n hole_diameter,\n hole_width,\n hole_height,\n layers,\n hole_offset_x,\n hole_offset_y,\n } = element\n\n const parsed_hole_offset_x = distance.parse(hole_offset_x ?? 0)\n const parsed_hole_offset_y = distance.parse(hole_offset_y ?? 0)\n\n const pcb_outline = pad_outline\n\n const padPrimitives: Primitive[] = []\n if (pcb_outline && Array.isArray(pcb_outline)) {\n const translatedPoints = normalizePolygonPoints(pcb_outline).map(\n (p) => ({ x: p.x + x, y: p.y + y }),\n )\n\n for (const layer of layers || [\"top\", \"bottom\"]) {\n padPrimitives.push({\n _pcb_drawing_object_id: `polygon_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"polygon\",\n points: translatedPoints,\n layer: layer,\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n })\n }\n }\n\n const holeCenter = {\n x: x + parsed_hole_offset_x,\n y: y + parsed_hole_offset_y,\n }\n\n const holePrimitives: Primitive[] = []\n\n if (hole_shape === \"circle\") {\n holePrimitives.push({\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x: holeCenter.x,\n y: holeCenter.y,\n r: (hole_diameter ?? 0) / 2,\n layer: \"drill\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n })\n } else if (hole_shape === \"oval\") {\n holePrimitives.push({\n _pcb_drawing_object_id: `oval_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"oval\",\n x: holeCenter.x,\n y: holeCenter.y,\n rX: (hole_width ?? 0) / 2,\n rY: (hole_height ?? 0) / 2,\n layer: \"drill\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n })\n } else if (hole_shape === \"pill\" || hole_shape === \"rotated_pill\") {\n holePrimitives.push({\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"pill\",\n x: holeCenter.x,\n y: holeCenter.y,\n w: hole_width ?? 0,\n h: hole_height ?? 0,\n layer: \"drill\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n ccw_rotation: element.ccw_rotation,\n })\n }\n\n return [...padPrimitives, ...holePrimitives]\n } else {\n return []\n }\n }\n }\n\n return []\n}\n","import type { PcbSmtPadRect, PcbSmtPadRotatedRect } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\nimport { getNewPcbDrawingObjectId } from \"../convert-element-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nexport const convertSmtpadRect = (\n element: PcbSmtPadRect | PcbSmtPadRotatedRect,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { x, y, width, height, layer, rect_border_radius } = element\n const corner_radius = element.corner_radius ?? rect_border_radius ?? 0\n\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"rect\"),\n pcb_drawing_type: \"rect\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n roundness: corner_radius,\n ...(element.shape === \"rotated_rect\" && element.ccw_rotation !== undefined\n ? { ccw_rotation: element.ccw_rotation }\n : {}),\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitiveBase: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"rect\"),\n pcb_drawing_type: \"rect\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n roundness: corner_radius,\n ...(element.shape === \"rotated_rect\" && element.ccw_rotation !== undefined\n ? { ccw_rotation: element.ccw_rotation }\n : {}),\n }\n const maskPrimitive: Primitive & MetaData = {\n ...maskPrimitiveBase,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color as string }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n","import type { PcbSmtPadCircle } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\nimport { getNewPcbDrawingObjectId } from \"../convert-element-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nexport const convertSmtpadCircle = (\n element: PcbSmtPadCircle,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { x, y, radius, layer } = element\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"circle\"),\n pcb_drawing_type: \"circle\" as const,\n x,\n y,\n r: radius,\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitive: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"circle\"),\n pcb_drawing_type: \"circle\" as const,\n x,\n y,\n r: radius,\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n","import type { PcbSmtPadPolygon } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\nimport {\n getNewPcbDrawingObjectId,\n normalizePolygonPoints,\n} from \"../convert-element-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nexport const convertSmtpadPolygon = (\n element: PcbSmtPadPolygon,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { layer, points } = element\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"polygon\"),\n pcb_drawing_type: \"polygon\" as const,\n points: normalizePolygonPoints(points),\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitive: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"polygon\"),\n pcb_drawing_type: \"polygon\" as const,\n points: normalizePolygonPoints(points),\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n","import type { PcbSmtPadPill, PcbSmtPadRotatedPill } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\nimport { getNewPcbDrawingObjectId } from \"../convert-element-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nexport const convertSmtpadPill = (\n element: PcbSmtPadPill,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { x, y, width, height, layer } = element\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"pill\"),\n pcb_drawing_type: \"pill\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitive: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"pill\"),\n pcb_drawing_type: \"pill\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n\nexport const convertSmtpadRotatedPill = (\n element: PcbSmtPadRotatedPill,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { x, y, width, height, layer, ccw_rotation } = element\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"pill\"),\n pcb_drawing_type: \"pill\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ccw_rotation,\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitive: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"pill\"),\n pcb_drawing_type: \"pill\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ccw_rotation,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n","import { Primitive } from \"lib/types\"\n\nexport function addInteractionMetadataToPrimitives({\n primitivesWithoutInteractionMetadata,\n drawingObjectIdsWithMouseOver,\n primitiveIdsInMousedOverNet,\n}: {\n primitivesWithoutInteractionMetadata: Primitive[]\n drawingObjectIdsWithMouseOver: Set<string>\n primitiveIdsInMousedOverNet: string[]\n}): Primitive[] {\n const newPrimitives = []\n for (const primitive of primitivesWithoutInteractionMetadata) {\n const newPrimitive = { ...primitive }\n const primitiveElement = primitive._element\n const parentComponent = primitive._parent_pcb_component\n if (primitive?.layer === \"drill\") {\n newPrimitive.is_in_highlighted_net = false\n newPrimitive.is_mouse_over = false\n } else if (\n drawingObjectIdsWithMouseOver.has(primitive._pcb_drawing_object_id)\n ) {\n newPrimitive.is_mouse_over = true\n } else if (\n primitiveElement &&\n ((\"pcb_trace_id\" in primitiveElement &&\n primitiveIdsInMousedOverNet.includes(primitiveElement.pcb_trace_id!)) ||\n (\"pcb_port_id\" in primitiveElement &&\n primitiveIdsInMousedOverNet.includes(\n primitiveElement.pcb_port_id!,\n )) ||\n (\"pcb_via_id\" in primitiveElement &&\n primitiveIdsInMousedOverNet.includes(primitiveElement.pcb_via_id!)) ||\n (\"pcb_component_id\" in primitiveElement &&\n primitiveIdsInMousedOverNet.includes(\n primitiveElement.pcb_component_id!,\n )) ||\n (parentComponent &&\n \"pcb_component_id\" in parentComponent &&\n primitiveIdsInMousedOverNet.includes(\n parentComponent.pcb_component_id!,\n )))\n ) {\n newPrimitive.is_in_highlighted_net = true\n } else {\n newPrimitive.is_in_highlighted_net = false\n newPrimitive.is_mouse_over = false\n }\n newPrimitives.push(newPrimitive)\n }\n return newPrimitives\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport {\n getBoundsFromPoints,\n type Bounds,\n type Point,\n} from \"@tscircuit/math-utils\"\nimport { compose, scale, translate, type Matrix } from \"transformation-matrix\"\n\ninterface RoutePoint extends Point {\n width?: number\n}\n\nexport interface ErrorPreviewElementIndexes {\n tracesById: Map<string, any>\n portsById: Map<string, any>\n viasById: Map<string, any>\n componentsById: Map<string, any>\n boardsById: Map<string, any>\n}\n\nexport const buildErrorPreviewElementIndexes = (\n elements: AnyCircuitElement[],\n): ErrorPreviewElementIndexes => {\n const tracesById = new Map<string, any>()\n const portsById = new Map<string, any>()\n const viasById = new Map<string, any>()\n const componentsById = new Map<string, any>()\n const boardsById = new Map<string, any>()\n\n for (const element of elements) {\n if (element.type === \"pcb_trace\" && element.pcb_trace_id) {\n tracesById.set(element.pcb_trace_id, element)\n } else if (element.type === \"pcb_port\" && element.pcb_port_id) {\n portsById.set(element.pcb_port_id, element)\n } else if (element.type === \"pcb_via\" && element.pcb_via_id) {\n viasById.set(element.pcb_via_id, element)\n } else if (element.type === \"pcb_component\" && element.pcb_component_id) {\n componentsById.set(element.pcb_component_id, element)\n } else if (element.type === \"pcb_board\" && element.pcb_board_id) {\n boardsById.set(element.pcb_board_id, element)\n }\n }\n\n return {\n tracesById,\n portsById,\n viasById,\n componentsById,\n boardsById,\n }\n}\n\nconst mergeBounds = (\n existing: Bounds | null,\n next: Bounds | null | undefined,\n): Bounds | null => {\n if (!next) return existing\n if (!existing) return next\n\n return {\n minX: Math.min(existing.minX, next.minX),\n maxX: Math.max(existing.maxX, next.maxX),\n minY: Math.min(existing.minY, next.minY),\n maxY: Math.max(existing.maxY, next.maxY),\n }\n}\n\nconst createBoundsFromCenter = (center: Point, radius = 0.45): Bounds => ({\n minX: center.x - radius,\n maxX: center.x + radius,\n minY: center.y - radius,\n maxY: center.y + radius,\n})\n\nconst createBoundsFromRoute = (route: RoutePoint[]): Bounds | null => {\n if (route.length === 0) return null\n\n let bounds: Bounds | null = null\n for (const point of route) {\n const radius = Math.max((point.width ?? 0.2) / 2, 0.3)\n bounds = mergeBounds(bounds, createBoundsFromCenter(point, radius))\n }\n\n return bounds\n}\n\nconst createBoundsFromComponent = (component: any): Bounds | null => {\n if (!component?.center) return null\n\n const width = Math.max(component.width ?? 0, 1.2)\n const height = Math.max(component.height ?? 0, 1.2)\n\n return {\n minX: component.center.x - width / 2,\n maxX: component.center.x + width / 2,\n minY: component.center.y - height / 2,\n maxY: component.center.y + height / 2,\n }\n}\n\nconst createBoardBounds = (board: any): Bounds | null => {\n if (\n !board?.center ||\n typeof board.width !== \"number\" ||\n typeof board.height !== \"number\"\n ) {\n return null\n }\n\n return {\n minX: board.center.x - board.width / 2,\n maxX: board.center.x + board.width / 2,\n minY: board.center.y - board.height / 2,\n maxY: board.center.y + board.height / 2,\n }\n}\n\nconst expandBounds = (bounds: Bounds, padding: number): Bounds => ({\n minX: bounds.minX - padding,\n maxX: bounds.maxX + padding,\n minY: bounds.minY - padding,\n maxY: bounds.maxY + padding,\n})\n\nconst createBoundsFromPoints = (\n points: Point[],\n radius = 0.35,\n): Bounds | null => {\n const bounds = getBoundsFromPoints(points)\n if (!bounds) return null\n return expandBounds(bounds, radius)\n}\n\nconst getErrorFocusCenter = ({\n error,\n tracesById,\n portsById,\n viasById,\n componentsById,\n}: {\n error: any\n} & ErrorPreviewElementIndexes): Point | null => {\n if (error.center) return error.center\n if (error.pcb_center) return error.pcb_center\n if (error.component_center) return error.component_center\n\n if (error.pcb_via_ids?.length) {\n const vias = error.pcb_via_ids\n .map((pcbViaId: string) => viasById.get(pcbViaId))\n .filter(Boolean)\n\n if (vias.length > 0) {\n return {\n x: vias.reduce((sum: number, via: any) => sum + via.x, 0) / vias.length,\n y: vias.reduce((sum: number, via: any) => sum + via.y, 0) / vias.length,\n }\n }\n }\n\n if (error.pcb_port_ids?.length) {\n const ports = error.pcb_port_ids\n .map((pcbPortId: string) => portsById.get(pcbPortId))\n .filter(Boolean)\n\n if (ports.length > 0) {\n return {\n x:\n ports.reduce((sum: number, port: any) => sum + port.x, 0) /\n ports.length,\n y:\n ports.reduce((sum: number, port: any) => sum + port.y, 0) /\n ports.length,\n }\n }\n }\n\n if (error.pcb_trace_id) {\n const trace = tracesById.get(error.pcb_trace_id)\n if (trace?.route?.length) {\n const middleIndex = Math.floor(trace.route.length / 2)\n return {\n x: trace.route[middleIndex].x,\n y: trace.route[middleIndex].y,\n }\n }\n }\n\n if (error.pcb_component_id) {\n return componentsById.get(error.pcb_component_id)?.center ?? null\n }\n\n return null\n}\n\nexport const getErrorFocusPoint = ({\n error,\n indexes,\n}: {\n error: any\n indexes: ErrorPreviewElementIndexes\n}): Point | null =>\n getErrorFocusCenter({\n error,\n ...indexes,\n })\n\nconst getComponentBoundaryViolationBounds = ({\n error,\n boardsById,\n}: {\n error: any\n boardsById: Map<string, any>\n}): Bounds | null => {\n if (!error.component_bounds || !error.pcb_board_id) return null\n\n const boardBounds = createBoardBounds(boardsById.get(error.pcb_board_id))\n if (!boardBounds) return null\n\n const componentBounds = error.component_bounds\n const violationPoints: Point[] = []\n\n if (componentBounds.min_x < boardBounds.minX) {\n violationPoints.push({\n x: boardBounds.minX,\n y: Math.max(componentBounds.min_y, boardBounds.minY),\n })\n violationPoints.push({\n x: boardBounds.minX,\n y: Math.min(componentBounds.max_y, boardBounds.maxY),\n })\n }\n\n if (componentBounds.max_x > boardBounds.maxX) {\n violationPoints.push({\n x: boardBounds.maxX,\n y: Math.max(componentBounds.min_y, boardBounds.minY),\n })\n violationPoints.push({\n x: boardBounds.maxX,\n y: Math.min(componentBounds.max_y, boardBounds.maxY),\n })\n }\n\n if (componentBounds.min_y < boardBounds.minY) {\n violationPoints.push({\n x: Math.max(componentBounds.min_x, boardBounds.minX),\n y: boardBounds.minY,\n })\n violationPoints.push({\n x: Math.min(componentBounds.max_x, boardBounds.maxX),\n y: boardBounds.minY,\n })\n }\n\n if (componentBounds.max_y > boardBounds.maxY) {\n violationPoints.push({\n x: Math.max(componentBounds.min_x, boardBounds.minX),\n y: boardBounds.maxY,\n })\n violationPoints.push({\n x: Math.min(componentBounds.max_x, boardBounds.maxX),\n y: boardBounds.maxY,\n })\n }\n\n return createBoundsFromPoints(violationPoints, 0.3)\n}\n\nconst nonZoomableErrorTypes = new Set([\n \"source_failed_to_create_component_error\",\n])\n\nexport const getErrorPreviewBounds = ({\n error,\n indexes,\n}: {\n error: any\n indexes: ErrorPreviewElementIndexes\n}): Bounds | null => {\n if (\n nonZoomableErrorTypes.has(error.error_type) ||\n nonZoomableErrorTypes.has(error.type)\n ) {\n return null\n }\n\n let bounds: Bounds | null = null\n const focusCenter = getErrorFocusCenter({\n error,\n ...indexes,\n })\n\n if (focusCenter) {\n bounds = mergeBounds(bounds, createBoundsFromCenter(focusCenter, 0.35))\n }\n\n if (error.error_type === \"pcb_component_outside_board_error\") {\n bounds = mergeBounds(\n bounds,\n getComponentBoundaryViolationBounds({\n error,\n boardsById: indexes.boardsById,\n }),\n )\n } else if (error.component_bounds && !focusCenter) {\n bounds = mergeBounds(bounds, {\n minX: error.component_bounds.min_x,\n maxX: error.component_bounds.max_x,\n minY: error.component_bounds.min_y,\n maxY: error.component_bounds.max_y,\n })\n }\n\n if (error.center && !focusCenter) {\n bounds = mergeBounds(bounds, createBoundsFromCenter(error.center))\n }\n\n if (error.pcb_center && !focusCenter) {\n bounds = mergeBounds(bounds, createBoundsFromCenter(error.pcb_center))\n }\n\n if (error.component_center && !focusCenter) {\n bounds = mergeBounds(bounds, createBoundsFromCenter(error.component_center))\n }\n\n if (error.pcb_port_ids && !focusCenter) {\n for (const pcbPortId of error.pcb_port_ids) {\n const port = indexes.portsById.get(pcbPortId)\n if (port) {\n bounds = mergeBounds(\n bounds,\n createBoundsFromCenter({ x: port.x, y: port.y }, 0.4),\n )\n }\n }\n }\n\n if (error.pcb_trace_id && !focusCenter) {\n const trace = indexes.tracesById.get(error.pcb_trace_id)\n if (trace?.route) {\n bounds = mergeBounds(bounds, createBoundsFromRoute(trace.route))\n }\n }\n\n if (error.pcb_via_ids) {\n for (const pcbViaId of error.pcb_via_ids) {\n const via = indexes.viasById.get(pcbViaId)\n if (via) {\n bounds = mergeBounds(\n bounds,\n createBoundsFromCenter(\n { x: via.x, y: via.y },\n Math.max((via.outer_diameter ?? 0.5) / 2, 0.28),\n ),\n )\n }\n }\n }\n\n if (error.pcb_component_id && !focusCenter) {\n bounds = mergeBounds(\n bounds,\n createBoundsFromComponent(\n indexes.componentsById.get(error.pcb_component_id),\n ),\n )\n }\n\n if (error.pcb_component_ids && !focusCenter) {\n for (const pcbComponentId of error.pcb_component_ids) {\n bounds = mergeBounds(\n bounds,\n createBoundsFromComponent(indexes.componentsById.get(pcbComponentId)),\n )\n }\n }\n\n return bounds\n}\n\nexport const createTransformForBounds = ({\n bounds,\n width,\n height,\n}: {\n bounds: Bounds\n width: number\n height: number\n}): Matrix => {\n const center = {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n }\n const targetWidth = Math.max(bounds.maxX - bounds.minX, 0.8) + 1.4\n const targetHeight = Math.max(bounds.maxY - bounds.minY, 0.8) + 1.4\n const scaleFactor =\n Math.min(width / targetWidth, height / targetHeight, 240) * 0.92\n\n return compose(\n translate(width / 2, height / 2),\n scale(scaleFactor, -scaleFactor, 0, 0),\n translate(-center.x, -center.y),\n )\n}\n\nexport const getRelatedIdsForError = (error: any): string[] => {\n const relatedIds = new Set<string>()\n\n if (error.pcb_trace_id) {\n relatedIds.add(error.pcb_trace_id)\n }\n\n for (const pcbPortId of error.pcb_port_ids ?? []) {\n relatedIds.add(pcbPortId)\n }\n\n for (const pcbViaId of error.pcb_via_ids ?? []) {\n relatedIds.add(pcbViaId)\n }\n\n if (error.pcb_component_id) {\n relatedIds.add(error.pcb_component_id)\n }\n\n for (const pcbComponentId of error.pcb_component_ids ?? []) {\n relatedIds.add(pcbComponentId)\n }\n\n return [...relatedIds]\n}\n","export const getErrorId = (error: any, index: number): string => {\n const explicitIdKeys = [\n \"pcb_trace_error_id\",\n \"pcb_via_clearance_error_id\",\n \"pcb_component_outside_board_error_id\",\n \"source_failed_to_create_component_error_id\",\n \"pcb_error_id\",\n ]\n\n for (const key of explicitIdKeys) {\n if (typeof error?.[key] === \"string\" && error[key].length > 0) {\n return error[key]\n }\n }\n\n for (const [key, value] of Object.entries(error ?? {})) {\n if (\n key.endsWith(\"_error_id\") &&\n typeof value === \"string\" &&\n value.length > 0\n ) {\n return value\n }\n }\n\n return `error_${index}_${error?.error_type}_${error?.message?.slice(0, 20)}`\n}\n\nexport const findErrorElementById = (\n elements: Array<{ type?: string }>,\n errorId: string | null | undefined,\n) => {\n if (!errorId) return null\n\n return (\n elements.find((element, index) => {\n if (!element.type?.includes(\"error\")) return false\n return getErrorId(element, index) === errorId\n }) ?? null\n )\n}\n","import type { Matrix } from \"transformation-matrix\"\n\nconst easeOutCubic = (progress: number) => 1 - (1 - progress) ** 3\n\nconst interpolateTransform = (\n start: Matrix,\n end: Matrix,\n progress: number,\n): Matrix => ({\n a: start.a + (end.a - start.a) * progress,\n b: start.b + (end.b - start.b) * progress,\n c: start.c + (end.c - start.c) * progress,\n d: start.d + (end.d - start.d) * progress,\n e: start.e + (end.e - start.e) * progress,\n f: start.f + (end.f - start.f) * progress,\n})\n\nexport const cancelTransformAnimation = (animationFrameId: number | null) => {\n if (animationFrameId !== null) {\n window.cancelAnimationFrame(animationFrameId)\n }\n}\n\nexport const animateTransform = ({\n startTransform,\n endTransform,\n durationMs,\n onUpdate,\n setAnimationFrameId,\n onComplete,\n}: {\n startTransform: Matrix\n endTransform: Matrix\n durationMs: number\n onUpdate: (transform: Matrix) => void\n setAnimationFrameId: (animationFrameId: number | null) => void\n onComplete?: () => void\n}): number => {\n const startTime = performance.now()\n\n const tick = (timestamp: number): void => {\n const elapsed = timestamp - startTime\n const rawProgress = Math.min(1, elapsed / durationMs)\n const easedProgress = easeOutCubic(rawProgress)\n\n onUpdate(interpolateTransform(startTransform, endTransform, easedProgress))\n\n if (rawProgress < 1) {\n setAnimationFrameId(window.requestAnimationFrame(tick))\n return\n }\n\n setAnimationFrameId(null)\n onComplete?.()\n }\n\n const animationFrameId = window.requestAnimationFrame(tick)\n setAnimationFrameId(animationFrameId)\n return animationFrameId\n}\n","import type { ManualEditEvent } from \"@tscircuit/props\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport { getFullConnectivityMapFromCircuitJson } from \"circuit-json-to-connectivity-map\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { convertElementToPrimitives } from \"lib/convert-element-to-primitive\"\nimport type { GridConfig, Primitive } from \"lib/types\"\nimport { addInteractionMetadataToPrimitives } from \"lib/util/addInteractionMetadataToPrimitives\"\nimport {\n buildErrorPreviewElementIndexes,\n createTransformForBounds,\n getErrorPreviewBounds,\n getRelatedIdsForError,\n} from \"lib/util/error-preview\"\nimport { findErrorElementById, getErrorId } from \"lib/util/get-error-id\"\nimport {\n animateTransform,\n cancelTransformAnimation,\n} from \"lib/util/transform-animation\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\nimport { CanvasPrimitiveRenderer } from \"./CanvasPrimitiveRenderer\"\nimport { DebugGraphicsOverlay } from \"./DebugGraphicsOverlay\"\nimport { type BoundsSelection, DimensionOverlay } from \"./DimensionOverlay\"\nimport { EditPlacementOverlay } from \"./EditPlacementOverlay\"\nimport { ErrorOverlay } from \"./ErrorOverlay\"\nimport { MouseElementTracker } from \"./MouseElementTracker\"\nimport { PcbGroupOverlay } from \"./PcbGroupOverlay\"\nimport { RatsNestOverlay } from \"./RatsNestOverlay\"\nimport { ToolbarOverlay } from \"./ToolbarOverlay\"\nimport { WarningGraphicsOverlay } from \"./WarningGraphicsOverlay\"\n\nexport interface CanvasElementsRendererProps {\n elements: AnyCircuitElement[]\n debugGraphics?: GraphicsObject | null\n transform?: Matrix\n setTransform?: (transform: Matrix) => void\n width?: number\n height?: number\n grid?: GridConfig\n allowEditing: boolean\n focusOnHover?: boolean\n onBoundsSelected?: (bounds: BoundsSelection) => void\n cancelPanDrag: () => void\n onCreateEditEvent: (event: ManualEditEvent) => void\n onModifyEditEvent: (event: Partial<ManualEditEvent>) => void\n}\n\nexport const CanvasElementsRenderer = (props: CanvasElementsRendererProps) => {\n const { transform, elements } = props\n const {\n hoveredErrorId,\n focusedErrorId,\n isShowingCopperPours,\n selectedLayer,\n } = useGlobalStore((state) => ({\n hoveredErrorId: state.hovered_error_id,\n focusedErrorId: state.focused_error_id,\n isShowingCopperPours: state.is_showing_copper_pours,\n selectedLayer: state.selected_layer,\n }))\n const activeErrorId = focusedErrorId ?? hoveredErrorId\n\n const elementsToRender = useMemo(\n () =>\n isShowingCopperPours\n ? elements\n : elements.filter((elm) => elm.type !== \"pcb_copper_pour\"),\n [elements, isShowingCopperPours],\n )\n\n const [primitivesWithoutInteractionMetadata, connectivityMap] =\n useMemo(() => {\n const primitivesWithoutInteractionMetadata = elementsToRender.flatMap(\n (elm) => convertElementToPrimitives(elm, props.elements),\n )\n const connectivityMap = getFullConnectivityMapFromCircuitJson(\n props.elements as any,\n )\n return [primitivesWithoutInteractionMetadata, connectivityMap]\n }, [elementsToRender, props.elements])\n\n const [hoverState, setHoverState] = useState({\n drawingObjectIdsWithMouseOver: new Set<string>(),\n primitiveIdsInMousedOverNet: [] as string[],\n })\n const [hoveredComponentIds, setHoveredComponentIds] = useState<string[]>([])\n const currentTransformRef = useRef<Matrix | null>(transform ?? null)\n const zoomAnimationFrameRef = useRef<number | null>(null)\n\n const elementIndexes = useMemo(\n () => buildErrorPreviewElementIndexes(elements),\n [elements],\n )\n\n const errorRelatedIds = useMemo(() => {\n if (!activeErrorId) return []\n\n const errorElements = elements.filter((el): el is any =>\n el.type.includes(\"error\"),\n )\n\n const activeError = errorElements.find((el, index) => {\n return getErrorId(el, index) === activeErrorId\n })\n\n if (!activeError) return []\n\n return getRelatedIdsForError(activeError)\n }, [activeErrorId, elements])\n\n useEffect(() => {\n if (transform) {\n currentTransformRef.current = transform\n }\n }, [transform])\n\n useEffect(() => {\n return () => {\n cancelTransformAnimation(zoomAnimationFrameRef.current)\n }\n }, [])\n\n useEffect(() => {\n if (!props.width || !props.height || !props.setTransform || !focusedErrorId)\n return\n\n const focusedError = findErrorElementById(elements, focusedErrorId)\n\n if (!focusedError) return\n\n const previewBounds = getErrorPreviewBounds({\n error: focusedError,\n indexes: elementIndexes,\n })\n\n if (!previewBounds) return\n\n const startTransform = currentTransformRef.current ?? transform\n if (!startTransform) return\n\n const targetTransform = createTransformForBounds({\n bounds: previewBounds,\n width: props.width,\n height: props.height,\n })\n\n cancelTransformAnimation(zoomAnimationFrameRef.current)\n\n animateTransform({\n startTransform,\n endTransform: targetTransform,\n durationMs: 420,\n setAnimationFrameId: (animationFrameId) => {\n zoomAnimationFrameRef.current = animationFrameId\n },\n onUpdate: (nextTransform) => {\n currentTransformRef.current = nextTransform\n props.setTransform?.(nextTransform)\n },\n })\n }, [\n focusedErrorId,\n elements,\n elementIndexes,\n props.height,\n props.setTransform,\n props.width,\n ])\n\n const primitives = useMemo(() => {\n const combinedPrimitiveIds = [\n ...hoverState.primitiveIdsInMousedOverNet,\n ...errorRelatedIds,\n ]\n\n return addInteractionMetadataToPrimitives({\n primitivesWithoutInteractionMetadata,\n drawingObjectIdsWithMouseOver: hoverState.drawingObjectIdsWithMouseOver,\n primitiveIdsInMousedOverNet: combinedPrimitiveIds,\n })\n }, [primitivesWithoutInteractionMetadata, hoverState, errorRelatedIds])\n\n const onMouseOverPrimitives = useCallback(\n (primitivesHoveredOver: Primitive[]) => {\n const primitiveIdsInMousedOverNet: string[] = []\n for (const primitive of primitivesHoveredOver) {\n if (primitive._element) {\n const connectedPrimitivesList = connectivityMap.getNetConnectedToId(\n \"pcb_port_id\" in primitive._element\n ? primitive._element?.pcb_port_id!\n : \"pcb_trace_id\" in primitive._element\n ? primitive._element?.pcb_trace_id!\n : \"\",\n )\n primitiveIdsInMousedOverNet.push(\n ...connectivityMap.getIdsConnectedToNet(connectedPrimitivesList!),\n )\n }\n }\n\n const drawingObjectIdsWithMouseOver = new Set(\n primitivesHoveredOver.map((p) => p._pcb_drawing_object_id),\n )\n\n setHoverState({\n drawingObjectIdsWithMouseOver,\n primitiveIdsInMousedOverNet,\n })\n\n const componentIds = primitivesHoveredOver\n .map((primitive) => {\n if (\n primitive._parent_pcb_component?.type === \"pcb_component\" &&\n primitive._parent_pcb_component.pcb_component_id\n ) {\n return primitive._parent_pcb_component.pcb_component_id\n }\n if (\n primitive._element?.type === \"pcb_component\" &&\n primitive._element.pcb_component_id\n ) {\n return primitive._element.pcb_component_id\n }\n return null\n })\n .filter((id): id is string => Boolean(id))\n\n setHoveredComponentIds(Array.from(new Set(componentIds)))\n },\n [connectivityMap],\n )\n\n return (\n <MouseElementTracker\n elements={elementsToRender}\n transform={transform}\n primitives={primitivesWithoutInteractionMetadata}\n selectedLayer={selectedLayer}\n onMouseHoverOverPrimitives={onMouseOverPrimitives}\n >\n <EditPlacementOverlay\n disabled={!props.allowEditing}\n transform={transform}\n soup={elements}\n cancelPanDrag={props.cancelPanDrag}\n onCreateEditEvent={props.onCreateEditEvent}\n onModifyEditEvent={props.onModifyEditEvent}\n >\n <DimensionOverlay\n transform={transform!}\n focusOnHover={props.focusOnHover}\n primitives={primitivesWithoutInteractionMetadata}\n onBoundsSelected={props.onBoundsSelected}\n cancelPanDrag={props.cancelPanDrag}\n >\n <ToolbarOverlay elements={elements}>\n <ErrorOverlay transform={transform} elements={elements}>\n <RatsNestOverlay transform={transform} soup={elements}>\n <PcbGroupOverlay\n transform={transform}\n elements={elements}\n hoveredComponentIds={hoveredComponentIds}\n >\n <DebugGraphicsOverlay\n transform={transform}\n debugGraphics={props.debugGraphics}\n >\n <WarningGraphicsOverlay\n transform={transform}\n elements={elements}\n >\n <CanvasPrimitiveRenderer\n transform={transform}\n primitives={primitives}\n elements={elementsToRender}\n width={props.width}\n height={props.height}\n grid={props.grid}\n />\n </WarningGraphicsOverlay>\n </DebugGraphicsOverlay>\n </PcbGroupOverlay>\n </RatsNestOverlay>\n </ErrorOverlay>\n </ToolbarOverlay>\n </DimensionOverlay>\n </EditPlacementOverlay>\n </MouseElementTracker>\n )\n}\n","import type { Rotation } from \"circuit-json\"\nimport colorParser from \"color\"\nimport type { BRepShape, Ring } from \"lib/types\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n identity,\n inverse,\n translate,\n} from \"transformation-matrix\"\nimport colors from \"./colors\"\nimport { scaleOnly } from \"./util/scale-only\"\nimport { zIndexMap } from \"./util/z-index-map\"\n\nexport interface Aperture {\n shape: \"circle\" | \"square\"\n size: number\n opacity: number\n mode: \"add\" | \"subtract\"\n fontSize: number\n color: string\n layer: string\n}\n\nexport const LAYER_NAME_TO_COLOR = {\n // Standard colors, you shouldn't use these except for testing\n red: \"red\",\n black: \"black\",\n green: \"green\",\n board: \"rgb(255, 255, 255)\",\n other: \"#eee\",\n // TODO more builtin html colors\n\n // Common eagle names\n top: colors.board.copper.f,\n inner1: colors.board.copper.in1,\n inner2: colors.board.copper.in2,\n inner3: colors.board.copper.in3,\n inner4: colors.board.copper.in4,\n inner5: colors.board.copper.in5,\n inner6: colors.board.copper.in6,\n inner7: colors.board.copper.in7,\n inner8: colors.board.copper.in8,\n\n bottom: colors.board.copper.b,\n drill: colors.board.anchor,\n keepout: colors.board.background,\n tkeepout: colors.board.b_crtyd,\n tplace: colors.board.b_silks,\n\n top_courtyard: colors.board.f_crtyd,\n bottom_courtyard: colors.board.b_crtyd,\n\n top_silkscreen: colors.board.f_silks,\n bottom_silkscreen: colors.board.b_silks,\n\n top_fabrication: colors.board.f_fab,\n bottom_fabrication: colors.board.b_fab,\n\n soldermask_top: colors.board.soldermask.top,\n soldermask_bottom: colors.board.soldermask.bottom,\n soldermask_with_copper_top: colors.board.soldermaskWithCopper.top,\n soldermask_with_copper_bottom: colors.board.soldermaskWithCopper.bottom,\n\n bottom_notes: colors.board.user_2,\n top_notes: colors.board.user_2,\n\n ...(colors.board as any),\n}\n\nexport type LayerNameForColor = keyof typeof LAYER_NAME_TO_COLOR\n\nexport const DEFAULT_DRAW_ORDER = [\n \"board\",\n \"bottom\",\n \"soldermask_bottom\",\n \"bottom_silkscreen\",\n \"top\",\n \"soldermask_top\",\n \"bottom_courtyard\",\n \"bottom_fabrication\",\n \"top_courtyard\",\n \"top_fabrication\",\n \"edge_cuts\",\n \"top_silkscreen\",\n] as const\n\nexport const FILL_TYPES = {\n 0: \"Empty\",\n 1: \"Solid\",\n 2: \"Line\",\n 3: \"LtSlash\",\n 4: \"Slash\",\n 5: \"BkSlash\",\n 6: \"LtBkSlash\",\n 7: \"Hatch\",\n 8: \"XHatch\",\n 9: \"Interleave\",\n 10: \"WideDot\",\n 11: \"CloseDot\",\n 12: \"Stipple1\",\n 13: \"Stipple2\",\n 14: \"Stipple3\",\n 15: \"Stipple4\",\n}\n\nexport class Drawer {\n canvasLayerMap: Record<string, HTMLCanvasElement>\n ctxLayerMap: Record<string, CanvasRenderingContext2D>\n // @ts-ignore this.equip({}) handles constructor assignment\n aperture: Aperture\n transform: Matrix\n foregroundLayer = \"top\"\n lastPoint: { x: number; y: number }\n\n constructor(canvasLayerMap: Record<string, HTMLCanvasElement>) {\n this.canvasLayerMap = canvasLayerMap\n this.ctxLayerMap = Object.fromEntries(\n Object.entries(canvasLayerMap).map(([name, canvas]) => [\n name,\n canvas.getContext(\"2d\")!,\n ]),\n )\n this.transform = identity()\n // positive is up (cartesian)\n this.transform.d *= -1\n this.transform = compose(this.transform, translate(0, -500))\n this.lastPoint = { x: 0, y: 0 }\n this.equip({})\n }\n\n clear() {\n for (const ctx of Object.values(this.ctxLayerMap)) {\n ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)\n }\n }\n\n equip(aperture: Partial<Aperture>) {\n this.aperture = {\n fontSize: 0,\n shape: \"circle\",\n mode: \"add\",\n size: 0,\n color: \"red\",\n layer: \"top\",\n opacity: this.foregroundLayer === aperture.color ? 1 : 0.5,\n ...aperture,\n }\n }\n\n drawMeshPattern(\n x: number,\n y: number,\n width: number,\n height: number,\n spacing: number,\n angle = 45,\n ) {\n const ctx = this.getLayerCtx()\n const [x1, y1] = applyToPoint(this.transform, [x, y])\n const [x2, y2] = applyToPoint(this.transform, [x + width, y + height])\n const spacing$ = scaleOnly(this.transform, spacing)\n\n // Set line properties for the mesh\n ctx.lineWidth = 1\n ctx.strokeStyle = this.aperture.color\n\n const drawLines = (angle: number) => {\n const sin = Math.sin(angle)\n const cos = Math.cos(angle)\n const diag = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)\n\n for (let i = -diag; i <= diag; i += spacing$) {\n ctx.beginPath()\n ctx.moveTo(x1 + i * cos - diag * sin, y1 + i * sin + diag * cos)\n ctx.lineTo(x1 + i * cos + diag * sin, y1 + i * sin - diag * cos)\n ctx.stroke()\n }\n }\n\n // Draw first set of parallel lines\n drawLines((angle * Math.PI) / 180)\n // Draw second set of parallel lines (perpendicular to the first set)\n drawLines(((angle + 90) * Math.PI) / 180)\n }\n\n rect({\n x,\n y,\n w,\n h,\n mesh_fill,\n is_filled = true,\n has_stroke,\n is_stroke_dashed,\n stroke_width,\n roundness,\n }: {\n x: number\n y: number\n w: number\n h: number\n mesh_fill?: boolean\n is_filled?: boolean\n has_stroke?: boolean\n is_stroke_dashed?: boolean\n stroke_width?: number\n roundness?: number\n }) {\n const [x1$, y1$] = applyToPoint(this.transform, [x - w / 2, y - h / 2])\n const [x2$, y2$] = applyToPoint(this.transform, [x + w / 2, y + h / 2])\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n const radius$ = roundness ? scaleOnly(this.transform, roundness) : 0\n\n const shouldDrawStroke =\n has_stroke === undefined ? is_filled === false : has_stroke\n\n if (mesh_fill) {\n ctx.save()\n ctx.beginPath()\n if (radius$ > 0 && ctx.roundRect) {\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n } else {\n ctx.rect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n ctx.clip()\n\n // Draw the mesh pattern\n this.drawMeshPattern(x - w / 2, y - h / 2, w, h, 0.15) // Adjust spacing as needed\n\n ctx.restore()\n\n // Draw the outline\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.stroke()\n } else {\n ctx.strokeRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n } else {\n if (is_filled !== false) {\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.fill()\n } else {\n ctx.fillRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n }\n\n if (shouldDrawStroke) {\n const originalLineWidth = ctx.lineWidth\n if (stroke_width !== undefined) {\n ctx.lineWidth = scaleOnly(this.transform, stroke_width)\n }\n if (is_stroke_dashed) {\n let dashPattern: number[] = []\n\n const scale = Math.abs(this.transform.a)\n if (scale > 0) {\n const SEGMENT_LENGTH = 0.1\n const dash = SEGMENT_LENGTH * scale\n const gap = dash * 1.3\n\n if (dash > 0.5) {\n dashPattern = [dash, gap]\n }\n }\n ctx.setLineDash(dashPattern)\n }\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.stroke()\n } else {\n ctx.strokeRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n if (is_stroke_dashed) {\n ctx.setLineDash([]) // Reset dash pattern\n }\n if (stroke_width !== undefined) {\n ctx.lineWidth = originalLineWidth\n }\n }\n }\n }\n\n rotatedRect(\n x: number,\n y: number,\n w: number,\n h: number,\n ccw_rotation: Rotation,\n roundness?: number,\n mesh_fill?: boolean,\n ) {\n const ctx = this.getLayerCtx()\n this.applyAperture()\n\n const [x1$, y1$] = applyToPoint(this.transform, [x - w / 2, y - h / 2])\n const [x2$, y2$] = applyToPoint(this.transform, [x + w / 2, y + h / 2])\n const radius$ = roundness ? scaleOnly(this.transform, roundness) : 0\n\n ctx.save()\n\n const [centerX, centerY] = applyToPoint(this.transform, [x, y])\n ctx.translate(centerX, centerY)\n const cw_rotation = 360 - ccw_rotation\n if (ccw_rotation) ctx.rotate((cw_rotation * Math.PI) / 180)\n ctx.translate(-centerX, -centerY)\n\n if (mesh_fill) {\n ctx.beginPath()\n if (radius$ > 0 && ctx.roundRect) {\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n } else {\n ctx.rect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n ctx.clip()\n\n this.drawMeshPattern(x - w / 2, y - h / 2, w, h, 0.15)\n\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.stroke()\n } else {\n ctx.strokeRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n } else {\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.fill()\n } else {\n ctx.fillRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n }\n\n ctx.restore()\n }\n\n rotatedPill(\n x: number,\n y: number,\n w: number,\n h: number,\n ccw_rotation: Rotation,\n ) {\n const ctx = this.getLayerCtx()\n this.applyAperture()\n\n ctx.save()\n\n const [centerX, centerY] = applyToPoint(this.transform, [x, y])\n ctx.translate(centerX, centerY)\n const cw_rotation = 360 - ccw_rotation\n if (ccw_rotation) ctx.rotate((cw_rotation * Math.PI) / 180)\n ctx.translate(-centerX, -centerY)\n\n this.pill(x, y, w, h)\n\n ctx.restore()\n }\n\n circle(\n x: number,\n y: number,\n r: number,\n mesh_fill?: boolean,\n is_filled = true,\n ) {\n const r$ = scaleOnly(this.transform, r)\n const [x$, y$] = applyToPoint(this.transform, [x, y])\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n if (mesh_fill) {\n ctx.save()\n ctx.beginPath()\n ctx.arc(x$, y$, r$, 0, 2 * Math.PI)\n ctx.clip()\n\n // Draw the mesh pattern\n // We need to cover the entire circular area, so we use a square that fully encloses the circle\n this.drawMeshPattern(x - r, y - r, r * 2, r * 2, 0.15) // Adjust spacing as needed\n\n ctx.restore()\n\n // Draw the outline\n ctx.beginPath()\n ctx.arc(x$, y$, r$, 0, 2 * Math.PI)\n ctx.stroke()\n } else {\n ctx.beginPath()\n ctx.arc(x$, y$, r$, 0, 2 * Math.PI)\n ctx.fill()\n }\n }\n\n oval(x: number, y: number, rx: number, ry: number) {\n const rx$ = scaleOnly(this.transform, rx)\n const ry$ = scaleOnly(this.transform, ry)\n const [x$, y$] = applyToPoint(this.transform, [x, y])\n this.applyAperture()\n const ctx = this.getLayerCtx()\n ctx.beginPath()\n ctx.ellipse(x$, y$, rx$, ry$, 0, 0, 2 * Math.PI)\n ctx.fill()\n ctx.closePath()\n }\n\n pill(x: number, y: number, w: number, h: number) {\n const [x$, y$] = applyToPoint(this.transform, [x - w / 2, y + h / 2])\n const width$ = scaleOnly(this.transform, w)\n const height$ = scaleOnly(this.transform, h)\n const radius = Math.min(width$, height$) / 2\n this.applyAperture()\n const ctx = this.getLayerCtx()\n ctx.beginPath()\n ctx.arc(x$ + radius, y$ + radius, radius, Math.PI, Math.PI * 1.5)\n ctx.arc(x$ + width$ - radius, y$ + radius, radius, Math.PI * 1.5, 0)\n ctx.arc(\n x$ + width$ - radius,\n y$ + height$ - radius,\n radius,\n 0,\n Math.PI * 0.5,\n )\n ctx.arc(x$ + radius, y$ + height$ - radius, radius, Math.PI * 0.5, Math.PI)\n ctx.fill()\n ctx.closePath()\n }\n\n polygon(points: { x: number; y: number }[]) {\n if (points.length < 3) {\n return\n }\n\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n // Transform all points\n const transformedPoints = points.map((point) =>\n applyToPoint(this.transform, [point.x, point.y]),\n )\n\n // Draw the filled polygon\n ctx.beginPath()\n ctx.moveTo(transformedPoints[0][0], transformedPoints[0][1])\n for (let i = 1; i < transformedPoints.length; i++) {\n ctx.lineTo(transformedPoints[i][0], transformedPoints[i][1])\n }\n ctx.closePath()\n ctx.fill(\"evenodd\")\n\n // Draw the outline only if we have a non-zero stroke width.\n // Calling ctx.stroke() with a zero width will re-use the previous\n // stroke width which can cause the polygon to suddenly expand when\n // other primitives (like hovered rectangles) change the aperture size.\n const lineWidth = scaleOnly(this.transform, this.aperture.size)\n if (lineWidth > 0) {\n ctx.lineWidth = lineWidth\n ctx.stroke()\n }\n }\n\n /* NOTE: This is not gerber compatible */\n debugText(text: string, x: number, y: number) {\n const [x$, y$] = applyToPoint(this.transform, [x, y])\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n ctx.font = \"10px sans-serif\"\n ctx.fillText(text, x$, y$)\n }\n\n getLayerCtx() {\n const ctx = this.ctxLayerMap[this.aperture.layer]\n if (!ctx) {\n throw new Error(`No context for layer \"${this.aperture.layer}\"`)\n }\n return ctx\n }\n\n /**\n * Iterate over each canvas and set the z index based on the layer order, but\n * always render the foreground layer on top.\n *\n * Also: Set the opacity of every non-foreground layer to 0.5\n */\n orderAndFadeLayers() {\n const { canvasLayerMap, foregroundLayer } = this\n const innerLayers = Object.keys(canvasLayerMap)\n .filter((layer) => /^inner\\d+$/.test(layer))\n .sort(\n (a, b) =>\n Number(b.slice(\"inner\".length)) - Number(a.slice(\"inner\".length)),\n )\n const defaultDrawOrder = [\n \"board\",\n ...innerLayers,\n ...DEFAULT_DRAW_ORDER.filter((layer) => layer !== \"board\"),\n ]\n const associatedSoldermask =\n foregroundLayer === \"top\"\n ? \"soldermask_top\"\n : foregroundLayer === \"bottom\"\n ? \"soldermask_bottom\"\n : undefined\n const associatedSilkscreen =\n foregroundLayer === \"top\"\n ? \"top_silkscreen\"\n : foregroundLayer === \"bottom\"\n ? \"bottom_silkscreen\"\n : undefined\n const associatedNotes =\n foregroundLayer === \"top\"\n ? \"top_notes\"\n : foregroundLayer === \"bottom\"\n ? \"bottom_notes\"\n : undefined\n const associatedFabrication =\n foregroundLayer === \"top\"\n ? \"top_fabrication\"\n : foregroundLayer === \"bottom\"\n ? \"bottom_fabrication\"\n : undefined\n const associatedCourtyard =\n foregroundLayer === \"top\"\n ? \"top_courtyard\"\n : foregroundLayer === \"bottom\"\n ? \"bottom_courtyard\"\n : undefined\n\n const opaqueLayers = new Set<string>([\n foregroundLayer,\n \"drill\",\n \"edge_cuts\",\n \"other\",\n \"board\",\n ...(associatedSoldermask ? [associatedSoldermask] : []),\n ...(associatedSilkscreen ? [associatedSilkscreen] : []),\n ...(associatedNotes ? [associatedNotes] : []),\n ...(associatedFabrication ? [associatedFabrication] : []),\n ...(associatedCourtyard ? [associatedCourtyard] : []),\n ])\n\n const layersToShiftToTop = [\n foregroundLayer,\n \"edge_cuts\",\n ...(associatedSoldermask ? [associatedSoldermask] : []),\n ...(associatedSilkscreen ? [associatedSilkscreen] : []),\n ...(associatedNotes ? [associatedNotes] : []),\n ...(associatedFabrication ? [associatedFabrication] : []),\n ...(associatedCourtyard ? [associatedCourtyard] : []),\n ]\n\n const order = [\n ...defaultDrawOrder.filter((l) => !layersToShiftToTop.includes(l)),\n ...(foregroundLayer === \"drill\" ? [] : [foregroundLayer]),\n ...(associatedSoldermask ? [associatedSoldermask] : []),\n \"edge_cuts\",\n ...(associatedSilkscreen ? [associatedSilkscreen] : []),\n ...(associatedNotes ? [associatedNotes] : []),\n ...(associatedFabrication ? [associatedFabrication] : []),\n ...(associatedCourtyard ? [associatedCourtyard] : []),\n \"drill\",\n ]\n\n order.forEach((layer, i) => {\n const canvas = canvasLayerMap[layer]\n if (!canvas) return\n\n canvas.style.zIndex = `${zIndexMap.topLayer - (order.length - i)}`\n canvas.style.opacity = opaqueLayers.has(layer) ? \"1\" : \"0.5\"\n })\n }\n\n applyAperture() {\n const { transform, aperture } = this\n let { size, mode, color, fontSize, layer } = aperture\n if (!(layer in this.ctxLayerMap)) this.aperture.layer = \"other\"\n\n const ctx = this.getLayerCtx()\n if (!ctx) {\n throw new Error(`No context for layer \"${this.foregroundLayer}\"`)\n }\n if (!color) color = \"undefined\"\n ctx.lineWidth = scaleOnly(transform, size)\n ctx.lineCap = \"round\"\n\n if (mode === \"add\") {\n ctx.globalCompositeOperation = \"source-over\"\n let colorString = LAYER_NAME_TO_COLOR[color.toLowerCase()]\n if (!colorString)\n try {\n colorString = colorParser(color).rgb().toString()\n } catch (error) {\n console.warn(`Invalid color format: '${color}'`)\n colorString = \"white\"\n }\n\n ctx.fillStyle = colorString\n ctx.strokeStyle = colorString\n } else {\n ctx.globalCompositeOperation = \"destination-out\"\n ctx.fillStyle = \"rgba(0,0,0,1)\"\n ctx.strokeStyle = \"rgba(0,0,0,1)\"\n }\n ctx.font = `${scaleOnly(inverse(transform), fontSize)}px sans-serif`\n }\n\n moveTo(x: number, y: number) {\n this.lastPoint = { x, y }\n }\n lineTo(x: number, y: number) {\n const [x$, y$] = applyToPoint(this.transform, [x, y])\n const { size, shape, mode } = this.aperture\n const size$ = scaleOnly(this.transform, size)\n const { lastPoint } = this\n const lastPoint$ = applyToPoint(this.transform, lastPoint)\n\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n if (shape === \"square\")\n ctx.fillRect(\n lastPoint$.x - size$ / 2,\n lastPoint$.y - size$ / 2,\n size$,\n size$,\n )\n ctx.beginPath()\n ctx.moveTo(lastPoint$.x, lastPoint$.y)\n ctx.lineTo(x$, y$)\n\n ctx.stroke()\n ctx.closePath()\n\n if (shape === \"square\")\n ctx.fillRect(x$ - size$ / 2, y$ - size$ / 2, size$, size$)\n\n this.lastPoint = { x, y }\n }\n\n polygonWithArcs(brep: BRepShape) {\n const ctx = this.getLayerCtx()\n\n const processRing = (ring: Ring) => {\n if (ring.vertices.length === 0) return\n const startPoint = ring.vertices[0]\n const t_start_point = applyToPoint(this.transform, [\n startPoint.x,\n startPoint.y,\n ])\n ctx.moveTo(t_start_point[0], t_start_point[1])\n\n for (let i = 0; i < ring.vertices.length; i++) {\n const p1 = ring.vertices[i]\n const p2 = ring.vertices[(i + 1) % ring.vertices.length]\n\n if (p1.bulge && p1.bulge !== 0) {\n const bulge = p1.bulge\n\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n const chord = Math.sqrt(dx * dx + dy * dy)\n\n if (chord < 1e-9) {\n const t_p2 = applyToPoint(this.transform, [p2.x, p2.y])\n ctx.lineTo(t_p2[0], t_p2[1])\n continue\n }\n\n const angle = 4 * Math.atan(bulge)\n const radius = Math.abs(chord / (2 * Math.sin(angle / 2)))\n\n const mx = (p1.x + p2.x) / 2\n const my = (p1.y + p2.y) / 2\n\n const norm_dx = dx / chord\n const norm_dy = dy / chord\n\n const perp_vx = -norm_dy\n const perp_vy = norm_dx\n\n const dist_to_center = Math.sqrt(\n Math.max(0, radius * radius - (chord / 2) ** 2),\n )\n\n const cx = mx + dist_to_center * perp_vx * Math.sign(bulge)\n const cy = my + dist_to_center * perp_vy * Math.sign(bulge)\n\n const startAngle = Math.atan2(p1.y - cy, p1.x - cx)\n let endAngle = Math.atan2(p2.y - cy, p2.x - cx)\n\n if (bulge > 0 && endAngle < startAngle) {\n endAngle += 2 * Math.PI\n } else if (bulge < 0 && endAngle > startAngle) {\n endAngle -= 2 * Math.PI\n }\n\n const t_center = applyToPoint(this.transform, [cx, cy])\n const t_radius = scaleOnly(this.transform, radius)\n\n ctx.arc(\n t_center[0],\n t_center[1],\n t_radius,\n -startAngle,\n -endAngle,\n bulge > 0,\n )\n } else {\n const t_p2 = applyToPoint(this.transform, [p2.x, p2.y])\n ctx.lineTo(t_p2[0], t_p2[1])\n }\n }\n ctx.closePath()\n }\n\n ctx.beginPath()\n\n processRing(brep.outer_ring)\n if (brep.inner_rings) {\n for (const inner_ring of brep.inner_rings) {\n processRing(inner_ring)\n }\n }\n\n ctx.fill(\"evenodd\")\n }\n}\n","// Mix of Eagle Dark for schematics and KiCAD 2020 for PCBs\n// https://github.com/pointhi/kicad-color-schemes/blob/master/eagle-dark/eagle-dark.jsonO\n// https://github.com/pointhi/kicad-color-schemes/blob/master/kicad-2020/kicad_2020.json\nexport default {\n \"3d_viewer\": {\n background_bottom: \"rgb(102, 102, 128)\",\n background_top: \"rgb(204, 204, 230)\",\n board: \"rgb(51, 43, 23)\",\n copper: \"rgb(179, 156, 0)\",\n silkscreen_bottom: \"rgb(230, 230, 230)\",\n silkscreen_top: \"rgb(230, 230, 230)\",\n soldermask: \"rgb(20, 51, 36)\",\n solderpaste: \"rgb(128, 128, 128)\",\n },\n board: {\n anchor: \"rgb(255, 38, 226)\",\n aux_items: \"rgb(255, 255, 255)\",\n b_adhes: \"rgb(0, 0, 132)\",\n b_crtyd: \"rgb(38, 233, 255)\",\n b_fab: \"rgb(88, 93, 132)\",\n b_mask: \"rgba(2, 255, 238, 0.400)\",\n b_paste: \"rgb(0, 194, 194)\",\n b_silks: \"rgb(242, 237, 161)\",\n background: \"rgb(0, 16, 35)\",\n cmts_user: \"rgb(89, 148, 220)\",\n copper: {\n b: \"rgb(77, 127, 196)\",\n f: \"rgb(200, 52, 52)\",\n in1: \"rgb(127, 200, 127)\",\n in10: \"rgb(237, 124, 51)\",\n in11: \"rgb(91, 195, 235)\",\n in12: \"rgb(247, 111, 142)\",\n in13: \"rgb(167, 165, 198)\",\n in14: \"rgb(40, 204, 217)\",\n in15: \"rgb(232, 178, 167)\",\n in16: \"rgb(242, 237, 161)\",\n in17: \"rgb(237, 124, 51)\",\n in18: \"rgb(91, 195, 235)\",\n in19: \"rgb(247, 111, 142)\",\n in2: \"rgb(206, 125, 44)\",\n in20: \"rgb(167, 165, 198)\",\n in21: \"rgb(40, 204, 217)\",\n in22: \"rgb(232, 178, 167)\",\n in23: \"rgb(242, 237, 161)\",\n in24: \"rgb(237, 124, 51)\",\n in25: \"rgb(91, 195, 235)\",\n in26: \"rgb(247, 111, 142)\",\n in27: \"rgb(167, 165, 198)\",\n in28: \"rgb(40, 204, 217)\",\n in29: \"rgb(232, 178, 167)\",\n in3: \"rgb(79, 203, 203)\",\n in30: \"rgb(242, 237, 161)\",\n in4: \"rgb(219, 98, 139)\",\n in5: \"rgb(167, 165, 198)\",\n in6: \"rgb(40, 204, 217)\",\n in7: \"rgb(232, 178, 167)\",\n in8: \"rgb(242, 237, 161)\",\n in9: \"rgb(141, 203, 129)\",\n },\n cursor: \"rgb(255, 255, 255)\",\n drc: \"rgb(194, 194, 194)\",\n drc_error: \"rgba(215, 91, 107, 0.800)\",\n drc_exclusion: \"rgb(255, 255, 255)\",\n drc_warning: \"rgba(255, 208, 66, 0.902)\",\n dwgs_user: \"rgb(194, 194, 194)\",\n eco1_user: \"rgb(180, 219, 210)\",\n eco2_user: \"rgb(216, 200, 82)\",\n edge_cuts: \"rgb(208, 210, 205)\",\n f_adhes: \"rgb(132, 0, 132)\",\n f_crtyd: \"rgb(255, 0, 245)\",\n f_fab: \"rgb(175, 175, 175)\",\n f_mask: \"rgba(216, 100, 255, 0.400)\",\n f_paste: \"rgba(180, 160, 154, 0.902)\",\n f_silks: \"rgb(242, 237, 161)\",\n footprint_text_back: \"rgb(0, 0, 132)\",\n footprint_text_front: \"rgb(194, 194, 194)\",\n footprint_text_invisible: \"rgb(132, 132, 132)\",\n grid: \"rgb(132, 132, 132)\",\n grid_axes: \"rgb(194, 194, 194)\",\n margin: \"rgb(255, 38, 226)\",\n microvia: \"rgb(0, 132, 132)\",\n no_connect: \"rgb(0, 0, 132)\",\n pad_back: \"rgb(77, 127, 196)\",\n pad_front: \"rgb(200, 52, 52)\",\n pad_plated_hole: \"rgb(194, 194, 0)\",\n pad_through_hole: \"rgb(227, 183, 46)\",\n plated_hole: \"rgb(26, 196, 210)\",\n ratsnest: \"rgba(245, 255, 213, 0.702)\",\n select_overlay: \"rgb(4, 255, 67)\",\n soldermaskWithCopper: {\n top: \"rgb(18, 82, 50)\",\n bottom: \"rgb(77, 127, 196)\",\n },\n soldermask: {\n top: \"rgb(12, 55, 33)\",\n bottom: \"rgb(12, 55, 33)\",\n },\n through_via: \"rgb(236, 236, 236)\",\n user_1: \"rgb(194, 194, 194)\",\n user_2: \"rgb(89, 148, 220)\",\n user_3: \"rgb(180, 219, 210)\",\n user_4: \"rgb(216, 200, 82)\",\n user_5: \"rgb(194, 194, 194)\",\n user_6: \"rgb(89, 148, 220)\",\n user_7: \"rgb(180, 219, 210)\",\n user_8: \"rgb(216, 200, 82)\",\n user_9: \"rgb(232, 178, 167)\",\n via_blind_buried: \"rgb(187, 151, 38)\",\n via_hole: \"rgb(227, 183, 46)\",\n via_micro: \"rgb(0, 132, 132)\",\n via_through: \"rgb(236, 236, 236)\",\n worksheet: \"rgb(200, 114, 171)\",\n },\n gerbview: {\n axes: \"rgb(0, 0, 132)\",\n background: \"rgb(0, 0, 0)\",\n dcodes: \"rgb(255, 255, 255)\",\n grid: \"rgb(132, 132, 132)\",\n layers: [\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n \"rgb(132, 132, 0)\",\n \"rgb(194, 194, 194)\",\n \"rgb(0, 0, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n \"rgb(132, 132, 0)\",\n \"rgb(194, 194, 194)\",\n \"rgb(0, 0, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n \"rgb(132, 132, 0)\",\n \"rgb(194, 194, 194)\",\n \"rgb(0, 0, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n ],\n negative_objects: \"rgb(132, 132, 132)\",\n worksheet: \"rgb(0, 0, 132)\",\n },\n palette: [\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n \"rgb(132, 132, 0)\",\n \"rgb(194, 194, 194)\",\n \"rgb(0, 0, 132)\",\n \"rgb(0, 132, 0)\",\n ],\n schematic: {\n anchor: \"rgb(0, 0, 255)\",\n aux_items: \"rgb(0, 0, 0)\",\n background: \"rgb(33, 33, 33)\",\n brightened: \"rgb(204, 204, 204)\",\n bus: \"rgb(0, 96, 192)\",\n bus_junction: \"rgb(0, 96, 192)\",\n component_body: \"rgb(44, 44, 44)\",\n component_outline: \"rgb(192, 0, 0)\",\n cursor: \"rgb(224, 224, 224)\",\n erc_error: \"rgba(192, 48, 48, 0.800)\",\n erc_warning: \"rgba(192, 140, 0, 0.800)\",\n fields: \"rgb(128, 0, 160)\",\n grid: \"rgb(60, 60, 60)\",\n grid_axes: \"rgb(60, 60, 60)\",\n hidden: \"rgb(194, 194, 194)\",\n junction: \"rgb(0, 160, 0)\",\n label_global: \"rgb(0, 160, 224)\",\n label_hier: \"rgb(160, 160, 0)\",\n label_local: \"rgb(192, 192, 192)\",\n net_name: \"rgb(224, 224, 224)\",\n no_connect: \"rgb(97, 43, 224)\",\n note: \"rgb(192, 192, 0)\",\n override_item_colors: false,\n pin: \"rgb(192, 0, 0)\",\n pin_name: \"rgb(192, 192, 192)\",\n pin_number: \"rgb(192, 0, 0)\",\n reference: \"rgb(192, 192, 192)\",\n shadow: \"rgba(102, 179, 255, 0.800)\",\n sheet: \"rgb(128, 0, 160)\",\n sheet_background: \"rgba(255, 255, 255, 0.000)\",\n sheet_fields: \"rgb(160, 160, 0)\",\n sheet_filename: \"rgb(160, 160, 0)\",\n sheet_label: \"rgb(160, 160, 0)\",\n sheet_name: \"rgb(0, 160, 204)\",\n value: \"rgb(192, 192, 192)\",\n wire: \"rgb(0, 160, 0)\",\n worksheet: \"rgb(192, 0, 0)\",\n },\n}\n","import { Matrix } from \"transformation-matrix\"\n\nexport const scaleOnly = (mat: Matrix, value: number = 1) => {\n if (Math.abs(mat.a) !== Math.abs(mat.d))\n throw new Error(\"Cannot scale non-uniformly\")\n return value * Math.abs(mat.a)\n}\n","export const zIndexMap = {\n elementOverlay: 40,\n dimensionOverlay: 40,\n errorOverlay: 40,\n pcbGroupOverlay: 35,\n ratsNestOverlay: 30,\n toolbarOverlay: 70,\n warnings: 30,\n // Canvas layers are assigned z-indexes below this value. A 10-layer board\n // needs 26 canvas planes once masks, silkscreen, notes, and other overlays\n // are included, so keep enough room for the complete stack.\n topLayer: 30,\n clickToInteractOverlay: 100,\n}\n","import type { AnyCircuitElement, LayerRef, PcbRenderLayer } from \"circuit-json\"\n\nexport const getCopperLayerRefs = (numLayers = 2): LayerRef[] => {\n const layerCount = Math.max(2, Math.min(10, Math.floor(numLayers)))\n return [\n \"top\",\n ...Array.from(\n { length: layerCount - 2 },\n (_, index) => `inner${index + 1}` as LayerRef,\n ),\n \"bottom\",\n ]\n}\n\nexport const getCopperLayerRefsFromElements = (\n elements: AnyCircuitElement[],\n): LayerRef[] => {\n const board = elements.find((element) => element.type === \"pcb_board\")\n return getCopperLayerRefs(board?.num_layers ?? 2)\n}\n\nexport const getCopperRenderLayer = (layer: LayerRef): PcbRenderLayer =>\n `${layer}_copper` as PcbRenderLayer\n\nexport const normalizeCopperRenderLayers = (\n layers: PcbRenderLayer[],\n): LayerRef[] =>\n layers.map((layer) =>\n layer.endsWith(\"_copper\")\n ? (layer.slice(0, -\"_copper\".length) as LayerRef)\n : (layer as LayerRef),\n )\n\nexport const getOrderedCanvasLayers = (\n elements: AnyCircuitElement[],\n): string[] => {\n const innerLayers = getCopperLayerRefsFromElements(elements).filter((layer) =>\n layer.startsWith(\"inner\"),\n )\n\n return [\n \"board\",\n \"bottom\",\n \"soldermask_bottom\",\n \"bottom_silkscreen\",\n \"top\",\n \"soldermask_top\",\n \"soldermask_with_copper_bottom\",\n \"soldermask_with_copper_top\",\n \"top_fabrication\",\n \"bottom_fabrication\",\n ...innerLayers,\n \"drill\",\n \"edge_cuts\",\n \"bottom_notes\",\n \"top_notes\",\n \"top_silkscreen\",\n \"top_courtyard\",\n \"bottom_courtyard\",\n \"other\",\n ]\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isCopperPourElement(element: AnyCircuitElement) {\n return element.type === \"pcb_copper_pour\"\n}\n\nexport function drawCopperPourElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const copperPourElements = elements.filter(isCopperPourElement)\n\n if (copperPourElements.length === 0) return\n\n // Draw all copper pour elements with default colors\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(copperPourElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\n\nconst PCB_VIEWER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n courtyard: {\n top: colors.board.f_crtyd,\n bottom: colors.board.b_crtyd,\n },\n}\n\nexport function isCourtyardElement(element: AnyCircuitElement) {\n return (\n element.type === \"pcb_courtyard_circle\" ||\n element.type === \"pcb_courtyard_rect\" ||\n element.type === \"pcb_courtyard_outline\"\n )\n}\n\nexport function drawCourtyardElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.configure({\n colorOverrides: PCB_VIEWER_COLOR_MAP,\n })\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const courtyardElements = elements.filter(isCourtyardElement)\n\n drawer.drawElements(courtyardElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\n\n// Create a color map that uses pcb-viewer's existing colors for fabrication\n// while using defaults from circuit-to-canvas for other elements\nconst PCB_VIEWER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n silkscreen: {\n top: colors.board.f_fab,\n bottom: colors.board.b_fab,\n },\n}\n\nexport function isFabricationNote(element: AnyCircuitElement) {\n return element.type.includes(\"pcb_fabrication_note\")\n}\n\nexport function drawFabricationNoteElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.configure({\n colorOverrides: PCB_VIEWER_COLOR_MAP,\n })\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const fabricationElements = elements.filter(isFabricationNote)\n\n drawer.drawElements(fabricationElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbHole(element: AnyCircuitElement) {\n return element.type === \"pcb_hole\"\n}\n\nexport function drawPcbHoleElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n drawSoldermask?: boolean\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const holeElements = elements.filter(isPcbHole)\n\n drawer.drawElements(holeElements, { layers, drawSoldermask })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbBoardElement(element: AnyCircuitElement) {\n return element.type === \"pcb_board\"\n}\n\nexport function drawPcbBoardElements({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n drawSoldermask?: boolean\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const pcbBoardElements = elements.filter(isPcbBoardElement)\n\n for (const element of pcbBoardElements) {\n drawer.drawElements([element], {\n layers,\n drawSoldermask: false,\n drawBoardMaterial: drawSoldermask ?? false,\n minBoardOutlineStrokePx: 2,\n })\n }\n}\n","import type {\n AnyCircuitElement,\n PcbCopperText,\n PcbRenderLayer,\n} from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbCopperText(\n element: AnyCircuitElement,\n): element is PcbCopperText {\n return element.type === \"pcb_copper_text\"\n}\n\nexport function drawPcbCopperTextElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const copperTextElements = elements.filter(isPcbCopperText)\n\n if (copperTextElements.length === 0) return\n\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(copperTextElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbCutout(element: AnyCircuitElement) {\n return element.type === \"pcb_cutout\"\n}\n\nexport function drawPcbCutoutElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const cutoutElements = elements.filter(isPcbCutout)\n\n drawer.drawElements(cutoutElements, { layers })\n}\n","import { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\n\n// Color map for keepouts - uses background color for all layers\n\nexport function isPcbKeepout(element: AnyCircuitElement) {\n return element.type === \"pcb_keepout\"\n}\n\nexport function drawPcbKeepoutElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: string[]\n realToCanvasMat: Matrix\n}) {\n // Filter keepouts to only those on the specified layers\n const keepoutElements = elements.filter(isPcbKeepout)\n\n if (keepoutElements.length === 0) return\n\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n\n drawer.drawElements(keepoutElements, { layers: [] })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbNote(element: AnyCircuitElement) {\n return element.type.startsWith(\"pcb_note_\")\n}\n\nexport function drawPcbNoteElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const pcbNoteElements = elements.filter(isPcbNote)\n\n drawer.drawElements(pcbNoteElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbPanelElement(element: AnyCircuitElement) {\n return element.type === \"pcb_panel\"\n}\n\nexport function drawPcbPanelElements({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n drawSoldermask?: boolean\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const pcbPanelElements = elements.filter(isPcbPanelElement)\n\n for (const element of pcbPanelElements) {\n drawer.drawElements([element], { layers })\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\nimport { normalizeCopperRenderLayers } from \"./copper-layers\"\nimport type { Primitive } from \"./types\"\n\n// Color map with lighter copper colors for hover effect\nconst HOVER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: {\n ...DEFAULT_PCB_COLOR_MAP.copper,\n top: color(colors.board.pad_front).lighten(0.5).toString(),\n bottom: color(colors.board.pad_back).lighten(0.5).toString(),\n inner1: color(colors.board.copper.in1).lighten(0.5).toString(),\n inner2: color(colors.board.copper.in2).lighten(0.5).toString(),\n inner3: color(colors.board.copper.in3).lighten(0.5).toString(),\n inner4: color(colors.board.copper.in4).lighten(0.5).toString(),\n inner5: color(colors.board.copper.in5).lighten(0.5).toString(),\n inner6: color(colors.board.copper.in6).lighten(0.5).toString(),\n inner7: color(colors.board.copper.in7).lighten(0.5).toString(),\n inner8: color(colors.board.copper.in8).lighten(0.5).toString(),\n },\n}\n\nexport function isPcbSmtPad(element: AnyCircuitElement) {\n return element.type === \"pcb_smtpad\"\n}\n\nexport function drawPcbSmtPadElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n primitives,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n primitives?: Primitive[]\n drawSoldermask?: boolean\n}) {\n // Filter SMT pads to only those on the specified layers\n const targetLayers = new Set(normalizeCopperRenderLayers(layers))\n const smtPadElements = elements\n .filter(isPcbSmtPad)\n .filter((element) => targetLayers.has(element.layer))\n\n if (smtPadElements.length === 0) return\n\n // Find which SMT pad elements have highlighted primitives\n const highlightedElementIds = new Set<string>()\n if (primitives) {\n for (const primitive of primitives) {\n if (\n (primitive.is_mouse_over || primitive.is_in_highlighted_net) &&\n primitive._element?.type === \"pcb_smtpad\"\n ) {\n highlightedElementIds.add(primitive._element.pcb_smtpad_id)\n }\n }\n }\n\n // Separate highlighted and non-highlighted elements\n const highlightedElements = smtPadElements.filter((element) =>\n highlightedElementIds.has(element.pcb_smtpad_id),\n )\n const nonHighlightedElements = smtPadElements.filter(\n (element) => !highlightedElementIds.has(element.pcb_smtpad_id),\n )\n\n // Draw non-highlighted elements with default colors\n if (nonHighlightedElements.length > 0) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(nonHighlightedElements, { layers, drawSoldermask })\n }\n\n // Draw highlighted elements with lighter colors\n if (highlightedElements.length > 0) {\n const highlightDrawer = new CircuitToCanvasDrawer(canvas)\n highlightDrawer.configure({ colorOverrides: HOVER_COLOR_MAP })\n highlightDrawer.realToCanvasMat = realToCanvasMat\n highlightDrawer.drawElements(highlightedElements, {\n layers,\n drawSoldermask,\n })\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer, PcbTrace } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { normalizeCopperRenderLayers } from \"./copper-layers\"\nimport type { Primitive } from \"./types\"\n\n// Color map with lighter copper colors for hover effect\nconst HOVER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: Object.fromEntries(\n Object.entries(DEFAULT_PCB_COLOR_MAP.copper).map(([layer, layerColor]) => [\n layer,\n color(layerColor).lighten(0.5).toString(),\n ]),\n ) as PcbColorMap[\"copper\"],\n}\n\nexport function isPcbTrace(element: AnyCircuitElement): element is PcbTrace {\n return element.type === \"pcb_trace\"\n}\n\nexport const filterTraceByLayers = (\n trace: PcbTrace,\n targetLayers: Set<string>,\n): PcbTrace | null => {\n const filteredRoute = trace.route.filter((segment) => {\n if (\n segment.route_type === \"wire\" &&\n \"layer\" in segment &&\n targetLayers.has(segment.layer)\n ) {\n return true\n }\n\n if (segment.route_type === \"via\") {\n return (\n targetLayers.has(segment.from_layer) ||\n targetLayers.has(segment.to_layer)\n )\n }\n\n return false\n })\n\n const wireCount = filteredRoute.filter(\n (segment) => segment.route_type === \"wire\",\n ).length\n\n if (wireCount < 2) return null\n\n return {\n ...trace,\n route: filteredRoute,\n }\n}\n\nexport const showTraceSegmentsInsideHiddenCopperPours = (\n trace: PcbTrace,\n): PcbTrace => ({\n ...trace,\n route: trace.route.map((routePoint) => {\n if (\n !(\"is_inside_copper_pour\" in routePoint) ||\n routePoint.is_inside_copper_pour !== true\n ) {\n return routePoint\n }\n\n return {\n ...routePoint,\n is_inside_copper_pour: false,\n }\n }),\n})\n\nexport const getTraceClipContextElements = (\n elements: AnyCircuitElement[],\n showCopperPours: boolean,\n): AnyCircuitElement[] => (showCopperPours ? elements : [])\n\nexport const getHighlightedTraceElementIds = ({\n primitives,\n}: {\n primitives: Primitive[]\n}): Set<string> => {\n const highlightedElementIds = new Set<string>()\n\n for (const primitive of primitives) {\n if (\n (primitive.is_mouse_over || primitive.is_in_highlighted_net) &&\n primitive._element?.type === \"pcb_trace\"\n ) {\n highlightedElementIds.add(primitive._element.pcb_trace_id)\n }\n }\n\n return highlightedElementIds\n}\n\nexport function drawPcbTraceElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n primitives,\n showCopperPours,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n primitives?: Primitive[]\n showCopperPours: boolean\n}) {\n const targetLayers = new Set(normalizeCopperRenderLayers(layers))\n\n const traceElements = elements\n .filter(isPcbTrace)\n .map((trace) => filterTraceByLayers(trace, targetLayers))\n .filter((trace): trace is PcbTrace => trace !== null)\n .map((trace) =>\n showCopperPours ? trace : showTraceSegmentsInsideHiddenCopperPours(trace),\n )\n\n if (traceElements.length === 0) return\n\n const highlightedElementIds = getHighlightedTraceElementIds({\n primitives: primitives ?? [],\n })\n\n const highlightedElements: PcbTrace[] = []\n const nonHighlightedElements: PcbTrace[] = []\n for (const element of traceElements) {\n if (highlightedElementIds.has(element.pcb_trace_id)) {\n highlightedElements.push(element)\n } else {\n nonHighlightedElements.push(element)\n }\n }\n\n // The trace renderer receives a filtered element list. Give it the full\n // circuit only as clipping context while pours are visible; an empty list\n // deliberately disables geometric clipping when pours are hidden.\n const clipContextElements = getTraceClipContextElements(\n elements,\n showCopperPours,\n )\n\n if (nonHighlightedElements.length > 0) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(nonHighlightedElements, {\n layers,\n clipContextElements,\n })\n }\n\n if (highlightedElements.length > 0) {\n const highlightDrawer = new CircuitToCanvasDrawer(canvas)\n highlightDrawer.configure({ colorOverrides: HOVER_COLOR_MAP })\n highlightDrawer.realToCanvasMat = realToCanvasMat\n highlightDrawer.drawElements(highlightedElements, {\n layers,\n clipContextElements,\n })\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\nimport colors from \"./colors\"\nimport type { Primitive } from \"./types\"\n\n// Color map with lighter copper colors for hover effect\nconst HOVER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: {\n ...DEFAULT_PCB_COLOR_MAP.copper,\n top: color(colors.board.pad_front).lighten(0.5).toString(),\n bottom: color(colors.board.pad_back).lighten(0.5).toString(),\n inner1: color(colors.board.copper.in1).lighten(0.5).toString(),\n inner2: color(colors.board.copper.in2).lighten(0.5).toString(),\n inner3: color(colors.board.copper.in3).lighten(0.5).toString(),\n inner4: color(colors.board.copper.in4).lighten(0.5).toString(),\n inner5: color(colors.board.copper.in5).lighten(0.5).toString(),\n inner6: color(colors.board.copper.in6).lighten(0.5).toString(),\n inner7: color(colors.board.copper.in7).lighten(0.5).toString(),\n inner8: color(colors.board.copper.in8).lighten(0.5).toString(),\n },\n}\n\nexport function isPlatedHole(element: AnyCircuitElement) {\n return element.type === \"pcb_plated_hole\"\n}\n\nexport function drawPlatedHolePads({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n primitives,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n primitives?: Primitive[]\n drawSoldermask?: boolean\n}) {\n const platedHoleElements = elements.filter(isPlatedHole)\n\n if (platedHoleElements.length === 0) return\n\n // Find which plated hole elements have highlighted primitives\n const highlightedElementIds = new Set<string>()\n if (primitives) {\n for (const primitive of primitives) {\n if (\n (primitive.is_mouse_over || primitive.is_in_highlighted_net) &&\n primitive._element?.type === \"pcb_plated_hole\"\n ) {\n highlightedElementIds.add(primitive._element.pcb_plated_hole_id)\n }\n }\n }\n\n // Separate highlighted and non-highlighted elements\n const highlightedElements = platedHoleElements.filter((element) =>\n highlightedElementIds.has(element.pcb_plated_hole_id),\n )\n const nonHighlightedElements = platedHoleElements.filter(\n (element) => !highlightedElementIds.has(element.pcb_plated_hole_id),\n )\n\n // Draw non-highlighted elements with default colors\n if (nonHighlightedElements.length > 0) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(nonHighlightedElements, { layers, drawSoldermask })\n }\n\n // Draw highlighted elements with lighter colors\n if (highlightedElements.length > 0) {\n const highlightDrawer = new CircuitToCanvasDrawer(canvas)\n highlightDrawer.configure({ colorOverrides: HOVER_COLOR_MAP })\n highlightDrawer.realToCanvasMat = realToCanvasMat\n highlightDrawer.drawElements(highlightedElements, {\n layers,\n drawSoldermask,\n })\n }\n}\n","import { compose, translate, rotate, applyToPoint } from \"transformation-matrix\"\nimport { Line } from \"../types\"\n\nexport function rotateText(rotateTextParams: {\n lines: Line[]\n anchorPoint: { x: number; y: number }\n ccwRotation: number\n}) {\n const { lines, anchorPoint, ccwRotation } = rotateTextParams\n if (!ccwRotation) return lines\n const rad = (ccwRotation * Math.PI) / 180\n const rotationMatrix = rotate(rad)\n\n // Create rotation transform around anchor point\n const transform = compose(\n translate(anchorPoint.x, anchorPoint.y),\n rotationMatrix,\n translate(-anchorPoint.x, -anchorPoint.y),\n )\n applyToPoint(transform, anchorPoint)\n return lines.map((line) => ({\n ...line,\n x1: applyToPoint(transform, { x: line.x1, y: line.y1 }).x,\n y1: applyToPoint(transform, { x: line.x1, y: line.y1 }).y,\n x2: applyToPoint(transform, { x: line.x2, y: line.y2 }).x,\n y2: applyToPoint(transform, { x: line.x2, y: line.y2 }).y,\n }))\n}\n","export { lineAlphabet, svgAlphabet } from \"@tscircuit/alphabet\"\n","import { lineAlphabet } from \"../assets/alphabet\"\nimport { getNewPcbDrawingObjectId } from \"./convert-element-to-primitive\"\nimport type { Line, Text } from \"./types\"\n\nexport const LETTER_HEIGHT_TO_WIDTH_RATIO = 0.6\nexport const LETTER_HEIGHT_TO_SPACE_RATIO = 0.2\n\nconst getTextGeometry = (text: Text) => {\n const target_height = text.size * 0.7 // Apply 70% scaling\n\n const target_width_char = target_height * LETTER_HEIGHT_TO_WIDTH_RATIO\n const space_between_chars = target_height * LETTER_HEIGHT_TO_SPACE_RATIO\n const space_between_lines = target_height * LETTER_HEIGHT_TO_SPACE_RATIO\n\n const text_lines = text.text.split(/\\r?\\n/)\n const has_text = text.text.length > 0 && target_height > 0\n const line_count = has_text ? text_lines.length : 0\n\n const line_widths = has_text\n ? text_lines.map((line) => {\n if (line.length === 0) return 0\n return (\n line.length * target_width_char +\n (line.length - 1) * space_between_chars\n )\n })\n : []\n\n const width = line_widths.length > 0 ? Math.max(...line_widths) : 0\n\n const height =\n line_count > 0\n ? line_count * target_height + (line_count - 1) * space_between_lines\n : 0\n\n return {\n text_lines,\n line_count,\n line_widths,\n target_height,\n target_width_char,\n space_between_chars,\n space_between_lines,\n width,\n height,\n }\n}\n\nexport const getTextWidth = (text: Text): number => getTextGeometry(text).width\n\nexport const getTextMetrics = (text: Text) => {\n const geometry = getTextGeometry(text)\n\n return {\n width: geometry.width,\n height: geometry.height,\n lineHeight: geometry.target_height,\n lineSpacing: geometry.space_between_lines,\n lineCount: geometry.line_count,\n }\n}\n\nexport const convertTextToLines = (text: Text): Line[] => {\n const {\n text_lines,\n line_count,\n line_widths,\n target_height,\n target_width_char,\n space_between_chars,\n space_between_lines,\n width: maxWidth,\n } = getTextGeometry(text)\n\n if (target_height <= 0 || line_count === 0) return []\n\n const strokeWidth = target_height / 12\n\n const lines: Line[] = []\n\n for (let lineIndex = 0; lineIndex < line_count; lineIndex++) {\n // Lines go from top to bottom: first line (index 0) at highest Y, subsequent lines decrease in Y\n // lineIndex 0 -> offset 0 (top), lineIndex 1 -> offset -step (below), etc.\n const lineYOffset = -lineIndex * (target_height + space_between_lines)\n\n // Center each line within the max width bounding box\n // This ensures multiline text is properly centered when using center alignment\n const lineWidth = line_widths[lineIndex]\n const lineXOffset = (maxWidth - lineWidth) / 2\n let current_x_origin_for_char_box = text.x + lineXOffset\n\n for (\n let letterIndex = 0;\n letterIndex < text_lines[lineIndex].length;\n letterIndex++\n ) {\n const letter = text_lines[lineIndex][letterIndex]\n const letterLines =\n lineAlphabet[letter] ?? lineAlphabet[letter.toUpperCase()]\n\n if (!letterLines) {\n current_x_origin_for_char_box += target_width_char + space_between_chars\n continue\n }\n\n for (const {\n x1: norm_x1,\n y1: norm_y1,\n x2: norm_x2,\n y2: norm_y2,\n } of letterLines) {\n lines.push({\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"line\"),\n pcb_drawing_type: \"line\",\n x1: current_x_origin_for_char_box + target_width_char * norm_x1,\n y1: text.y + lineYOffset + target_height * norm_y1,\n x2: current_x_origin_for_char_box + target_width_char * norm_x2,\n y2: text.y + lineYOffset + target_height * norm_y2,\n width: strokeWidth,\n layer: text.layer,\n unit: text.unit,\n color: text.color,\n })\n }\n current_x_origin_for_char_box += target_width_char + space_between_chars\n }\n }\n\n return lines\n}\n","import { type Drawer, LAYER_NAME_TO_COLOR } from \"./Drawer\"\nimport { rotateText } from \"./util/rotate-text\"\nimport { convertTextToLines, getTextMetrics } from \"./convert-text-to-lines\"\nimport type {\n Circle,\n Line,\n Oval,\n Pill,\n Polygon,\n PolygonWithArcs,\n Primitive,\n Rect,\n Text,\n} from \"./types\"\nimport color from \"color\"\n\nfunction getColor(primitive: Primitive): string {\n const explicitColor = (primitive as any).color\n\n const baseColorString =\n explicitColor ??\n LAYER_NAME_TO_COLOR[primitive.layer as keyof typeof LAYER_NAME_TO_COLOR]\n\n let c = color(baseColorString)\n\n if (primitive._element?.type === \"pcb_copper_pour\") {\n c = c.alpha(0.7)\n }\n\n if (primitive.is_mouse_over || primitive.is_in_highlighted_net) {\n return c.lighten(0.5).rgb().toString()\n }\n\n return c.rgb().toString()\n}\n\nexport const drawLine = (drawer: Drawer, line: Line) => {\n drawer.equip({\n size: line.zoomIndependent ? line.width / drawer.transform.a : line.width,\n shape: line.squareCap ? \"square\" : \"circle\",\n color: getColor(line),\n layer: line.layer,\n })\n drawer.moveTo(line.x1, line.y1)\n drawer.lineTo(line.x2, line.y2)\n}\n\n/**\n * Calculate alignment offset for text based on its dimensions and alignment setting\n */\nconst getAlignOffset = (\n textWidth: number,\n textHeight: number,\n align?: string,\n): { x: number; y: number } => {\n switch (align) {\n case \"top_left\":\n return { x: 0, y: -textHeight }\n case \"top_center\":\n return { x: -textWidth / 2, y: -textHeight }\n case \"top_right\":\n return { x: -textWidth, y: -textHeight }\n case \"center_left\":\n return { x: 0, y: -textHeight / 2 }\n case \"center\":\n return { x: -textWidth / 2, y: -textHeight / 2 }\n case \"center_right\":\n return { x: -textWidth, y: -textHeight / 2 }\n case \"bottom_left\":\n return { x: 0, y: 0 }\n case \"bottom_center\":\n return { x: -textWidth / 2, y: 0 }\n case \"bottom_right\":\n return { x: -textWidth, y: 0 }\n default:\n return { x: 0, y: 0 }\n }\n}\n\n/**\n * Determine if text should be mirrored based on layer and is_mirrored property\n */\nconst shouldMirrorText = (text: Text): boolean => {\n // Bottom copper layer should auto-mirror (like bottom silkscreen)\n if (text.layer === \"bottom_silkscreen\" || text.layer === \"bottom\") {\n // If is_mirrored is explicitly set to false, don't mirror\n return text.is_mirrored !== false\n }\n // For other layers, only mirror if explicitly requested\n return text.is_mirrored === true\n}\n\nexport const drawText = (drawer: Drawer, text: Text) => {\n drawer.equip({\n fontSize: text.size,\n color: getColor(text),\n layer: text.layer,\n })\n\n const { width: textWidth, height: textHeight } = getTextMetrics(text)\n const alignOffset = getAlignOffset(textWidth, textHeight, text.align)\n\n text.x ??= 0\n text.y ??= 0\n\n // Get rotation anchor point based on alignment\n const rotationAnchor = {\n x: text.x,\n y: text.y,\n }\n\n // Generate the text lines with alignment offset\n let text_lines = convertTextToLines({\n ...text,\n x: text.x + alignOffset.x,\n y: text.y + alignOffset.y,\n })\n\n // Mirror text if needed (bottom layers or explicit is_mirrored)\n if (shouldMirrorText(text)) {\n text_lines = text_lines.map((line) => ({\n ...line,\n x1: 2 * text.x - line.x1,\n x2: 2 * text.x - line.x2,\n }))\n }\n\n // Apply rotation if needed\n if (text.ccw_rotation) {\n const rotateTextParams = {\n lines: text_lines,\n anchorPoint: rotationAnchor,\n ccwRotation: text.ccw_rotation,\n }\n text_lines = rotateText(rotateTextParams)\n }\n\n // Draw all lines with transformed context\n for (const line of text_lines) {\n drawLine(drawer, line)\n }\n}\n\n/**\n * Draw knockout text - a filled rectangle with text cut out (transparent)\n */\nexport const drawKnockoutText = (drawer: Drawer, text: Text) => {\n const {\n width: textWidth,\n height: textHeight,\n lineHeight,\n } = getTextMetrics(text)\n\n text.x ??= 0\n text.y ??= 0\n\n // Calculate padding\n const padding = text.knockout_padding ?? {\n left: text.size * 0.5,\n right: text.size * 0.5,\n top: text.size * 0.3,\n bottom: text.size * 0.3,\n }\n\n // Calculate the rectangle bounds\n const rectWidth = textWidth + padding.left + padding.right\n const rectHeight = textHeight + padding.top + padding.bottom\n\n // For knockout, we render text centered within the rectangle.\n // The rectangle is centered at the anchor point (text.x, text.y).\n // Text bounding box when drawn at origin (0,0):\n // - X: from 0 to textWidth (left-aligned, each line centered within)\n // - Y: from 0 (bottom of first line baseline) to lineHeight (top of first line)\n // then going down: line N is at Y = -N * (lineHeight + spacing)\n // - So Y ranges from lineHeight (top) to lineHeight - textHeight (bottom)\n //\n // To center the text in the rectangle, we need to offset it so that\n // the text's center aligns with the rectangle's center (which is at anchor).\n\n // Text center when drawn at (0, 0):\n const textCenterXAtOrigin = textWidth / 2\n const textCenterYAtOrigin = lineHeight - textHeight / 2\n\n // To center text at anchor point, offset by negative of center\n const textDrawX = text.x - textCenterXAtOrigin\n const textDrawY = text.y - textCenterYAtOrigin\n\n // Get rotation anchor point\n const rotationAnchor = {\n x: text.x,\n y: text.y,\n }\n\n // Draw the filled rectangle centered at anchor\n const rect: Rect = {\n _pcb_drawing_object_id: `knockout_rect_${text._pcb_drawing_object_id}`,\n pcb_drawing_type: \"rect\",\n x: text.x,\n y: text.y,\n w: rectWidth,\n h: rectHeight,\n layer: text.layer,\n ccw_rotation: text.ccw_rotation,\n }\n\n // If mirrored, the rectangle stays centered at anchor (no adjustment needed)\n // but text will be mirrored around the anchor\n\n // Draw the background rectangle\n if (text.ccw_rotation) {\n drawRotatedRect(drawer, rect)\n } else {\n drawRect(drawer, rect)\n }\n\n // Generate the text lines positioned to be centered in the rectangle\n let text_lines = convertTextToLines({\n ...text,\n x: textDrawX,\n y: textDrawY,\n })\n\n // Mirror text if needed (around the anchor point)\n if (shouldMirrorText(text)) {\n text_lines = text_lines.map((line) => ({\n ...line,\n x1: 2 * text.x - line.x1,\n x2: 2 * text.x - line.x2,\n }))\n }\n\n // Apply rotation if needed\n if (text.ccw_rotation) {\n const rotateTextParams = {\n lines: text_lines,\n anchorPoint: rotationAnchor,\n ccwRotation: text.ccw_rotation,\n }\n text_lines = rotateText(rotateTextParams)\n }\n\n // Draw text lines with destination-out mode to cut them from the rectangle\n // We draw directly instead of using drawLine to preserve the subtract mode\n for (const line of text_lines) {\n drawer.equip({\n size: line.width,\n shape: \"circle\",\n color: \"black\",\n layer: text.layer,\n mode: \"subtract\",\n })\n drawer.moveTo(line.x1, line.y1)\n drawer.lineTo(line.x2, line.y2)\n }\n\n // Reset to normal mode\n drawer.equip({\n mode: \"add\",\n })\n}\n\nexport const drawRect = (drawer: Drawer, rect: Rect) => {\n drawer.equip({\n color: getColor(rect),\n layer: rect.layer,\n size: rect.stroke_width,\n })\n drawer.rect({\n x: rect.x,\n y: rect.y,\n w: rect.w,\n h: rect.h,\n mesh_fill: rect.mesh_fill,\n is_filled: rect.is_filled,\n has_stroke: rect.has_stroke,\n is_stroke_dashed: rect.is_stroke_dashed,\n stroke_width: rect.stroke_width,\n roundness: rect.roundness,\n })\n}\n\nexport const drawRotatedRect = (drawer: Drawer, rect: Rect) => {\n drawer.equip({\n color: getColor(rect),\n layer: rect.layer,\n })\n\n drawer.rotatedRect(\n rect.x,\n rect.y,\n rect.w,\n rect.h,\n rect.ccw_rotation!,\n rect.roundness,\n rect.mesh_fill,\n )\n}\n\nexport const drawRotatedPill = (drawer: Drawer, pill: Pill) => {\n drawer.equip({\n color: getColor(pill),\n layer: pill.layer,\n })\n drawer.rotatedPill(pill.x, pill.y, pill.w, pill.h, pill.ccw_rotation!)\n}\n\nexport const drawCircle = (drawer: Drawer, circle: Circle) => {\n drawer.equip({\n color: getColor(circle),\n layer: circle.layer,\n })\n drawer.circle(circle.x, circle.y, circle.r, circle.mesh_fill)\n}\n\nexport const drawOval = (drawer: Drawer, oval: Oval) => {\n drawer.equip({\n color: getColor(oval),\n layer: oval.layer,\n })\n drawer.oval(oval.x, oval.y, oval.rX, oval.rY)\n}\n\nexport const drawPill = (drawer: Drawer, pill: Pill) => {\n drawer.equip({\n color: getColor(pill),\n layer: pill.layer,\n })\n drawer.pill(pill.x, pill.y, pill.w, pill.h)\n}\n\nexport const drawPolygon = (drawer: Drawer, polygon: Polygon) => {\n drawer.equip({\n color: getColor(polygon),\n layer: polygon.layer,\n })\n drawer.polygon(polygon.points)\n}\n\nexport const drawPolygonWithArcs = (drawer: Drawer, p: PolygonWithArcs) => {\n drawer.equip({\n color: getColor(p),\n layer: p.layer,\n })\n drawer.polygonWithArcs(p.brep_shape)\n}\n\nexport const drawPrimitive = (drawer: Drawer, primitive: Primitive) => {\n switch (primitive.pcb_drawing_type) {\n case \"line\":\n return drawLine(drawer, primitive)\n case \"text\":\n if (primitive.is_knockout) {\n return drawKnockoutText(drawer, primitive)\n }\n return drawText(drawer, primitive)\n case \"rect\": {\n if (primitive.ccw_rotation) {\n return drawRotatedRect(drawer, primitive)\n }\n return drawRect(drawer, primitive)\n }\n case \"circle\":\n return drawCircle(drawer, primitive)\n case \"oval\":\n return drawOval(drawer, primitive)\n case \"pill\":\n if (primitive.ccw_rotation) {\n return drawRotatedPill(drawer, primitive)\n }\n return drawPill(drawer, primitive)\n case \"polygon\":\n return drawPolygon(drawer, primitive)\n case \"polygon_with_arcs\":\n return drawPolygonWithArcs(drawer, primitive)\n }\n}\n\nexport const drawPrimitives = (drawer: Drawer, primitives: Primitive[]) => {\n for (const primitive of primitives) {\n drawPrimitive(drawer, primitive)\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\n\n// Create a color map that uses pcb-viewer's existing colors for silkscreen\n// while using defaults from circuit-to-canvas for other elements\nconst PCB_VIEWER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n silkscreen: {\n top: colors.board.f_silks,\n bottom: colors.board.b_silks,\n },\n}\n\nexport function isSilkscreenElement(element: AnyCircuitElement) {\n return element.type.includes(\"pcb_silkscreen\")\n}\n\nexport function drawSilkscreenElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.configure({\n colorOverrides: PCB_VIEWER_COLOR_MAP,\n })\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const silkscreenElements = elements.filter(isSilkscreenElement)\n\n drawer.drawElements(silkscreenElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\nimport type { Primitive } from \"./types\"\n\nconst HOVER_SOLDERMASK_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: {\n ...DEFAULT_PCB_COLOR_MAP.copper,\n top: color(colors.board.pad_front).lighten(0.5).toString(),\n bottom: color(colors.board.pad_back).lighten(0.5).toString(),\n inner1: color(colors.board.copper.in1).lighten(0.5).toString(),\n inner2: color(colors.board.copper.in2).lighten(0.5).toString(),\n inner3: color(colors.board.copper.in3).lighten(0.5).toString(),\n inner4: color(colors.board.copper.in4).lighten(0.5).toString(),\n inner5: color(colors.board.copper.in5).lighten(0.5).toString(),\n inner6: color(colors.board.copper.in6).lighten(0.5).toString(),\n inner7: color(colors.board.copper.in7).lighten(0.5).toString(),\n inner8: color(colors.board.copper.in8).lighten(0.5).toString(),\n },\n soldermask: {\n ...DEFAULT_PCB_COLOR_MAP.soldermask,\n top: color(colors.board.soldermask.top).lighten(0.35).toString(),\n bottom: color(colors.board.soldermask.bottom).lighten(0.35).toString(),\n },\n}\n\nexport function drawSoldermaskElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n primitives,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n drawSoldermaskTop?: boolean\n drawSoldermaskBottom?: boolean\n primitives?: Primitive[]\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n const boards = elements.filter((element) => element.type === \"pcb_board\")\n if (boards.length <= 1) {\n drawer.drawElements(elements, {\n layers,\n drawSoldermask: true,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n drawBoardMaterial: false,\n })\n } else {\n const nonBoardElements = elements.filter(\n (element) => element.type !== \"pcb_board\",\n )\n for (const board of boards) {\n drawer.drawElements([board, ...nonBoardElements], {\n layers,\n drawSoldermask: true,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n drawBoardMaterial: false,\n })\n }\n }\n\n if (!primitives) return\n\n const hoveredElementIds = new Set<string>()\n for (const primitive of primitives) {\n if (!(primitive.is_mouse_over || primitive.is_in_highlighted_net)) continue\n const element = primitive._element\n if (element?.type === \"pcb_smtpad\") {\n hoveredElementIds.add(element.pcb_smtpad_id)\n } else if (element?.type === \"pcb_plated_hole\") {\n hoveredElementIds.add(element.pcb_plated_hole_id)\n } else if (element?.type === \"pcb_via\") {\n hoveredElementIds.add(element.pcb_via_id)\n }\n }\n\n if (hoveredElementIds.size === 0) return\n\n const hoveredElements = elements.filter((element) => {\n if (element.type === \"pcb_smtpad\") {\n return hoveredElementIds.has(element.pcb_smtpad_id)\n }\n if (element.type === \"pcb_plated_hole\") {\n return hoveredElementIds.has(element.pcb_plated_hole_id)\n }\n if (element.type === \"pcb_via\") {\n return hoveredElementIds.has(element.pcb_via_id)\n }\n return false\n })\n\n if (hoveredElements.length === 0) return\n\n const hoverDrawer = new CircuitToCanvasDrawer(canvas)\n hoverDrawer.configure({ colorOverrides: HOVER_SOLDERMASK_COLOR_MAP })\n hoverDrawer.realToCanvasMat = realToCanvasMat\n hoverDrawer.drawElements(hoveredElements, {\n layers,\n drawSoldermask: true,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n drawBoardMaterial: false,\n })\n}\n","import {\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n CircuitToCanvasDrawer,\n} from \"circuit-to-canvas\"\nimport type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\nimport color from \"color\"\nimport { Primitive } from \"./types\"\n\n// Color map with lighter copper colors for hover effect\nconst HOVER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: {\n ...DEFAULT_PCB_COLOR_MAP.copper,\n top: color(colors.board.pad_front).lighten(0.5).toString(),\n bottom: color(colors.board.pad_back).lighten(0.5).toString(),\n inner1: color(colors.board.copper.in1).lighten(0.5).toString(),\n inner2: color(colors.board.copper.in2).lighten(0.5).toString(),\n inner3: color(colors.board.copper.in3).lighten(0.5).toString(),\n inner4: color(colors.board.copper.in4).lighten(0.5).toString(),\n inner5: color(colors.board.copper.in5).lighten(0.5).toString(),\n inner6: color(colors.board.copper.in6).lighten(0.5).toString(),\n inner7: color(colors.board.copper.in7).lighten(0.5).toString(),\n inner8: color(colors.board.copper.in8).lighten(0.5).toString(),\n },\n}\n\nexport function isPcbVia(element: AnyCircuitElement) {\n return element.type === \"pcb_via\"\n}\n\nexport function drawPcbViaElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n primitives,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n primitives?: Primitive[]\n drawSoldermask?: boolean\n}) {\n // Filter vias to only those on the specified layers\n const viaElements = elements.filter(isPcbVia).filter((element) => {\n // Vias are typically drawn on copper layers\n return layers.some((layer) => layer.includes(\"copper\"))\n })\n\n if (viaElements.length === 0) return\n\n // Find which via elements have highlighted primitives\n const highlightedElementIds = new Set<string>()\n if (primitives) {\n for (const primitive of primitives) {\n if (\n (primitive.is_mouse_over || primitive.is_in_highlighted_net) &&\n primitive._element?.type === \"pcb_via\"\n ) {\n highlightedElementIds.add(primitive._element.pcb_via_id)\n }\n }\n }\n\n // Separate highlighted and non-highlighted elements\n const highlightedElements = viaElements.filter((element) =>\n highlightedElementIds.has(element.pcb_via_id),\n )\n const nonHighlightedElements = viaElements.filter(\n (element) => !highlightedElementIds.has(element.pcb_via_id),\n )\n\n // Draw non-highlighted elements with default colors\n if (nonHighlightedElements.length > 0) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(nonHighlightedElements, { layers, drawSoldermask })\n }\n\n // Draw highlighted elements with lighter colors\n if (highlightedElements.length > 0) {\n const highlightDrawer = new CircuitToCanvasDrawer(canvas)\n highlightDrawer.configure({ colorOverrides: HOVER_COLOR_MAP })\n highlightDrawer.realToCanvasMat = realToCanvasMat\n highlightDrawer.drawElements(highlightedElements, {\n layers,\n drawSoldermask,\n })\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { Drawer } from \"lib/Drawer\"\nimport {\n getCopperLayerRefsFromElements,\n getCopperRenderLayer,\n getOrderedCanvasLayers,\n} from \"lib/copper-layers\"\nimport { drawCopperPourElementsForLayer } from \"lib/draw-copper-pour\"\nimport { drawCourtyardElementsForLayer } from \"lib/draw-courtyard\"\nimport { drawFabricationNoteElementsForLayer } from \"lib/draw-fabrication-note\"\nimport { drawGrid } from \"lib/draw-grid\"\nimport { drawPcbHoleElementsForLayer } from \"lib/draw-hole\"\nimport { drawPcbBoardElements } from \"lib/draw-pcb-board\"\nimport { drawPcbCopperTextElementsForLayer } from \"lib/draw-pcb-copper-text\"\nimport { drawPcbCutoutElementsForLayer } from \"lib/draw-pcb-cutout\"\nimport { drawPcbKeepoutElementsForLayer } from \"lib/draw-pcb-keepout\"\nimport { drawPcbNoteElementsForLayer } from \"lib/draw-pcb-note\"\nimport { drawPcbPanelElements } from \"lib/draw-pcb-panel\"\nimport { drawPcbSmtPadElementsForLayer } from \"lib/draw-pcb-smtpad\"\nimport { drawPcbTraceElementsForLayer } from \"lib/draw-pcb-trace\"\nimport { drawPlatedHolePads } from \"lib/draw-plated-hole\"\nimport { drawPrimitives } from \"lib/draw-primitives\"\nimport { drawSilkscreenElementsForLayer } from \"lib/draw-silkscreen\"\nimport { drawSoldermaskElementsForLayer } from \"lib/draw-soldermask\"\nimport { drawPcbViaElementsForLayer } from \"lib/draw-via\"\nimport type { GridConfig, Primitive } from \"lib/types\"\nimport React, { useEffect, useRef } from \"react\"\nimport { SuperGrid, toMMSI } from \"react-supergrid\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\n\ninterface Props {\n primitives: Primitive[]\n elements: AnyCircuitElement[]\n defaultUnit?: string\n transform?: Matrix\n grid?: GridConfig\n width?: number\n height?: number\n}\n\nexport const CanvasPrimitiveRenderer = ({\n primitives,\n elements,\n transform,\n grid,\n width = 500,\n height = 500,\n}: Props) => {\n const canvasRefs = useRef<Record<string, HTMLCanvasElement>>({})\n const selectedLayer = useGlobalStore((s) => s.selected_layer)\n const isShowingCopperPours = useGlobalStore((s) => s.is_showing_copper_pours)\n const isShowingSolderMask = useGlobalStore((s) => s.is_showing_solder_mask)\n const isShowingFabricationNotes = useGlobalStore(\n (s) => s.is_showing_fabrication_notes,\n )\n const isShowingPcbNotes = useGlobalStore((s) => s.is_showing_pcb_notes)\n const isShowingCourtyards = useGlobalStore((s) => s.is_showing_courtyards)\n const isShowingSilkscreen = useGlobalStore((s) => s.is_showing_silkscreen)\n\n useEffect(() => {\n if (!canvasRefs.current) return\n if (Object.keys(canvasRefs.current).length === 0) return\n\n // Keep all non-null canvas refs so hidden layers are still cleared.\n const availableCanvasRefs = Object.fromEntries(\n Object.entries(canvasRefs.current).filter(([layer, canvas]) => {\n if (!canvas) return false\n return true\n }),\n )\n\n if (Object.keys(availableCanvasRefs).length === 0) return\n\n const drawer = new Drawer(availableCanvasRefs)\n if (transform) drawer.transform = transform\n drawer.clear()\n drawer.foregroundLayer = selectedLayer\n\n // Filter out solder mask and silkscreen primitives when disabled\n // Also filter out SMT pad primitives since they're drawn with circuit-to-canvas\n const filteredPrimitives = primitives\n .filter((p) => isShowingSolderMask || !p.layer?.includes(\"soldermask\"))\n .filter((p) => isShowingSilkscreen || !p.layer?.includes(\"silkscreen\"))\n .filter(\n (p) => isShowingFabricationNotes || !p.layer?.includes(\"fabrication\"),\n )\n .filter((p) => p.layer !== \"board\")\n .filter((p) => p._element?.type !== \"pcb_smtpad\")\n .filter((p) => p._element?.type !== \"pcb_plated_hole\")\n .filter((p) => p._element?.type !== \"pcb_via\")\n .filter((p) => p._element?.type !== \"pcb_trace\")\n .filter((p) => p._element?.type !== \"pcb_copper_text\")\n\n drawPrimitives(drawer, filteredPrimitives)\n\n // Draw silkscreen elements using circuit-to-canvas\n if (transform) {\n // Draw plated holes using circuit-to-canvas (pads on copper layers, drills on drill layer)\n const topCanvas = canvasRefs.current.top\n const bottomCanvas = canvasRefs.current.bottom\n const copperLayers: Array<{\n canvas?: HTMLCanvasElement\n layer: string\n copperLayer: PcbRenderLayer\n }> = getCopperLayerRefsFromElements(elements).map((layer) => ({\n canvas: canvasRefs.current[layer],\n layer,\n copperLayer: getCopperRenderLayer(layer),\n }))\n\n // Draw PCB traces using circuit-to-canvas (on copper layers)\n for (const { canvas, copperLayer } of copperLayers) {\n if (!canvas) continue\n drawPcbTraceElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n primitives,\n showCopperPours: isShowingCopperPours,\n })\n }\n\n for (const { canvas, copperLayer } of copperLayers) {\n if (!canvas) continue\n drawPcbCopperTextElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n })\n }\n\n for (const { canvas, copperLayer, layer } of copperLayers) {\n if (!canvas) continue\n drawPlatedHolePads({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n primitives,\n drawSoldermask:\n isShowingSolderMask && (layer === \"top\" || layer === \"bottom\"),\n })\n }\n\n // Draw copper pours on every supported copper layer, including inners.\n for (const { canvas, copperLayer } of copperLayers) {\n if (!canvas) continue\n drawCopperPourElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n })\n }\n\n // Draw SMT pads using circuit-to-canvas (on copper layers)\n for (const { canvas, copperLayer } of copperLayers) {\n if (!canvas) continue\n drawPcbSmtPadElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n primitives,\n drawSoldermask: isShowingSolderMask,\n })\n }\n\n // Draw vias using circuit-to-canvas (on copper layers)\n for (const { canvas, copperLayer, layer } of copperLayers) {\n if (!canvas) continue\n drawPcbViaElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n primitives,\n drawSoldermask:\n isShowingSolderMask && (layer === \"top\" || layer === \"bottom\"),\n })\n }\n\n if (isShowingSolderMask) {\n const soldermaskLayer = selectedLayer === \"bottom\" ? \"bottom\" : \"top\"\n const drawSoldermaskTop = soldermaskLayer === \"top\"\n const drawSoldermaskBottom = soldermaskLayer === \"bottom\"\n\n const topSoldermaskCanvas = canvasRefs.current.soldermask_top\n if (topSoldermaskCanvas && soldermaskLayer === \"top\") {\n drawSoldermaskElementsForLayer({\n canvas: topSoldermaskCanvas,\n elements,\n layers: [\"top_soldermask\"],\n realToCanvasMat: transform,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n primitives,\n })\n }\n\n const bottomSoldermaskCanvas = canvasRefs.current.soldermask_bottom\n if (bottomSoldermaskCanvas && soldermaskLayer === \"bottom\") {\n drawSoldermaskElementsForLayer({\n canvas: bottomSoldermaskCanvas,\n elements,\n layers: [\"bottom_soldermask\"],\n realToCanvasMat: transform,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n primitives,\n })\n }\n }\n\n // Draw PCB holes\n const drillCanvas = canvasRefs.current.drill\n if (drillCanvas) {\n drawPcbHoleElementsForLayer({\n canvas: drillCanvas,\n elements,\n layers: [\"drill\"],\n realToCanvasMat: transform,\n })\n }\n\n // Draw silkscreen if enabled\n if (isShowingSilkscreen) {\n const topSilkscreenCanvas = canvasRefs.current.top_silkscreen\n if (topSilkscreenCanvas) {\n drawSilkscreenElementsForLayer({\n canvas: topSilkscreenCanvas,\n elements,\n layers: [\"top_silkscreen\"],\n realToCanvasMat: transform,\n })\n }\n\n const bottomSilkscreenCanvas = canvasRefs.current.bottom_silkscreen\n if (bottomSilkscreenCanvas) {\n drawSilkscreenElementsForLayer({\n canvas: bottomSilkscreenCanvas,\n elements,\n layers: [\"bottom_silkscreen\"],\n realToCanvasMat: transform,\n })\n }\n }\n\n // Draw top fabrication\n if (isShowingFabricationNotes) {\n const topFabCanvas = canvasRefs.current.top_fabrication\n if (topFabCanvas) {\n drawFabricationNoteElementsForLayer({\n canvas: topFabCanvas,\n elements,\n layers: [\"top_fabrication_note\"],\n realToCanvasMat: transform,\n })\n }\n\n // Draw bottom fabrication\n const bottomFabCanvas = canvasRefs.current.bottom_fabrication\n if (bottomFabCanvas) {\n drawFabricationNoteElementsForLayer({\n canvas: bottomFabCanvas,\n elements,\n layers: [\"bottom_fabrication_note\"],\n realToCanvasMat: transform,\n })\n }\n }\n\n if (isShowingPcbNotes) {\n // Draw bottom notes\n const bottomNotesCanvas = canvasRefs.current.bottom_notes\n if (bottomNotesCanvas) {\n drawPcbNoteElementsForLayer({\n canvas: bottomNotesCanvas,\n elements,\n layers: [\"bottom_user_note\"],\n realToCanvasMat: transform,\n })\n }\n\n // Draw top notes\n const topNotesCanvas = canvasRefs.current.top_notes\n if (topNotesCanvas) {\n drawPcbNoteElementsForLayer({\n canvas: topNotesCanvas,\n elements,\n layers: [\"top_user_note\"],\n realToCanvasMat: transform,\n })\n }\n }\n\n // Draw top courtyard\n if (isShowingCourtyards) {\n const topCourtyardCanvas = canvasRefs.current.top_courtyard\n if (topCourtyardCanvas) {\n drawCourtyardElementsForLayer({\n canvas: topCourtyardCanvas,\n elements,\n layers: [\"top_courtyard\" as PcbRenderLayer],\n realToCanvasMat: transform,\n })\n }\n\n // Draw bottom courtyard\n const bottomCourtyardCanvas = canvasRefs.current.bottom_courtyard\n if (bottomCourtyardCanvas) {\n drawCourtyardElementsForLayer({\n canvas: bottomCourtyardCanvas,\n elements,\n layers: [\"bottom_courtyard\" as PcbRenderLayer],\n realToCanvasMat: transform,\n })\n }\n }\n\n // Draw board outline using circuit-to-canvas\n const boardCanvas = canvasRefs.current.board\n if (boardCanvas) {\n drawPcbPanelElements({\n canvas: boardCanvas,\n elements,\n layers: [],\n realToCanvasMat: transform,\n drawSoldermask: isShowingSolderMask,\n })\n drawPcbBoardElements({\n canvas: boardCanvas,\n elements,\n layers: [],\n realToCanvasMat: transform,\n drawSoldermask: isShowingSolderMask,\n })\n }\n\n // Draw PCB cutouts using circuit-to-canvas\n const edgeCutsCanvas = canvasRefs.current.edge_cuts\n if (edgeCutsCanvas) {\n drawPcbCutoutElementsForLayer({\n canvas: edgeCutsCanvas,\n elements,\n layers: [\"edge_cuts\"],\n realToCanvasMat: transform,\n })\n }\n\n // Draw keepouts using circuit-to-canvas (on copper layers)\n const keepoutLayers = [\n { canvas: topCanvas, layer: \"top\" },\n { canvas: bottomCanvas, layer: \"bottom\" },\n ]\n\n for (const { canvas, layer } of keepoutLayers) {\n if (!canvas) continue\n drawPcbKeepoutElementsForLayer({\n canvas,\n elements,\n layers: [layer],\n realToCanvasMat: transform,\n })\n }\n }\n\n drawer.orderAndFadeLayers()\n }, [\n primitives,\n elements,\n transform,\n selectedLayer,\n isShowingCopperPours,\n isShowingSolderMask,\n isShowingFabricationNotes,\n isShowingPcbNotes,\n isShowingCourtyards,\n isShowingSilkscreen,\n ])\n\n return (\n <div\n style={{\n backgroundColor: \"black\",\n width,\n height,\n position: \"relative\",\n }}\n >\n <SuperGrid\n textColor=\"rgba(0,255,0,0.8)\"\n majorColor=\"rgba(0,255,0,0.4)\"\n minorColor=\"rgba(0,255,0,0.2)\"\n screenSpaceCellSize={200}\n width={width}\n height={height}\n transform={transform!}\n stringifyCoord={(x, y, z) => `${toMMSI(x, z)}, ${toMMSI(y, z)}`}\n />\n {getOrderedCanvasLayers(elements)\n .filter((layer) => {\n if (!isShowingSolderMask && layer.includes(\"soldermask\")) return false\n if (!isShowingSilkscreen && layer.includes(\"silkscreen\")) return false\n return true\n })\n .map((l) => l.replace(/-/g, \"\"))\n .map((layer, i) => (\n <canvas\n key={layer}\n className={`pcb-layer-${layer}`}\n ref={(el) => {\n canvasRefs.current ??= {}\n if (el) {\n canvasRefs.current[layer] = el\n } else {\n // Clean up ref when element is removed\n delete canvasRefs.current[layer]\n }\n }}\n style={{\n position: \"absolute\",\n zIndex: i,\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n }}\n width={width}\n height={height}\n />\n ))}\n </div>\n )\n}\n","import {\n glyphAdvanceRatio,\n glyphLineAlphabet,\n kerningRatio,\n textMetrics,\n} from \"@tscircuit/alphabet\"\nimport type { NinePointAnchor } from \"./types\"\n\nexport interface StrokeAlphabetContext {\n beginPath(): void\n moveTo(x: number, y: number): void\n lineTo(x: number, y: number): void\n stroke(): void\n save(): void\n restore(): void\n translate(x: number, y: number): void\n rotate(angleRadians: number): void\n strokeStyle: string\n lineWidth: number\n lineCap?: string\n lineJoin?: string\n}\n\nexport type AlphabetLayout = {\n width: number\n height: number\n glyphWidth: number\n letterSpacing: number\n spaceWidth: number\n strokeWidth: number\n lineHeight: number\n lines: string[]\n lineWidths: number[]\n}\n\nconst getAdvanceRatio = (char: string): number =>\n glyphAdvanceRatio[char] ??\n (char === \" \" ? textMetrics.spaceWidthRatio : textMetrics.glyphWidthRatio)\n\nexport function getAlphabetAdvanceWidth(\n char: string,\n nextChar: string | undefined,\n fontSize: number,\n): number {\n const advanceRatio = getAdvanceRatio(char)\n const letterSpacingRatio = nextChar ? textMetrics.letterSpacingRatio : 0\n const kerningAdjustmentRatio = nextChar\n ? kerningRatio[char]?.[nextChar] ?? 0\n : 0\n\n return fontSize * (advanceRatio + letterSpacingRatio + kerningAdjustmentRatio)\n}\n\nexport function getAlphabetLayout(\n text: string,\n fontSize: number,\n): AlphabetLayout {\n const glyphWidth = fontSize * textMetrics.glyphWidthRatio\n const letterSpacing = fontSize * textMetrics.letterSpacingRatio\n const spaceWidth = fontSize * textMetrics.spaceWidthRatio\n const strokeWidth = fontSize * textMetrics.strokeWidthRatio\n const lineHeight = fontSize * textMetrics.lineHeightRatio\n\n const lines = text.replace(/\\\\n/g, \"\\n\").split(\"\\n\")\n const lineWidths = lines.map((line) => {\n const characters = Array.from(line)\n return characters.reduce(\n (sum, char, index) =>\n sum + getAlphabetAdvanceWidth(char, characters[index + 1], fontSize),\n 0,\n )\n })\n\n const width = lineWidths.reduce(\n (maxWidth, lineWidth) => Math.max(maxWidth, lineWidth),\n 0,\n )\n const height =\n lines.length > 1 ? fontSize + (lines.length - 1) * lineHeight : fontSize\n\n return {\n width,\n height,\n glyphWidth,\n letterSpacing,\n spaceWidth,\n strokeWidth,\n lineHeight,\n lines,\n lineWidths,\n }\n}\n\nexport function getTextStartPosition(\n alignment: NinePointAnchor,\n layout: AlphabetLayout,\n): { x: number; y: number } {\n const totalWidth = layout.width + layout.strokeWidth\n const totalHeight = layout.height + layout.strokeWidth\n\n let x = 0\n let y = 0\n\n if (\n alignment === \"center\" ||\n alignment === \"top_center\" ||\n alignment === \"bottom_center\"\n ) {\n x = -totalWidth / 2\n } else if (\n alignment === \"top_right\" ||\n alignment === \"bottom_right\" ||\n alignment === \"center_right\"\n ) {\n x = -totalWidth\n }\n\n if (\n alignment === \"center\" ||\n alignment === \"center_left\" ||\n alignment === \"center_right\"\n ) {\n y = -totalHeight / 2\n } else if (\n alignment === \"bottom_left\" ||\n alignment === \"bottom_right\" ||\n alignment === \"bottom_center\"\n ) {\n y = -totalHeight\n }\n\n return { x, y }\n}\n\nexport function getLineStartX({\n alignment,\n lineWidth,\n maxWidth,\n strokeWidth,\n}: {\n alignment: NinePointAnchor\n lineWidth: number\n maxWidth: number\n strokeWidth: number\n}): number {\n const totalLineWidth = lineWidth + strokeWidth\n const totalMaxWidth = maxWidth + strokeWidth\n\n if (\n alignment === \"top_left\" ||\n alignment === \"bottom_left\" ||\n alignment === \"center_left\"\n ) {\n return 0\n }\n\n if (\n alignment === \"top_right\" ||\n alignment === \"bottom_right\" ||\n alignment === \"center_right\"\n ) {\n return totalMaxWidth - totalLineWidth\n }\n\n return (totalMaxWidth - totalLineWidth) / 2\n}\n\nexport function strokeAlphabetLine({\n ctx,\n line,\n fontSize,\n startX,\n startY,\n layout,\n}: {\n ctx: StrokeAlphabetContext\n line: string\n fontSize: number\n startX: number\n startY: number\n layout: AlphabetLayout\n}): void {\n const height = fontSize\n const glyphScaleX = fontSize\n const characters = Array.from(line)\n let cursor = startX + layout.strokeWidth / 2\n\n characters.forEach((char, index) => {\n const glyphLines = glyphLineAlphabet[char]\n\n if (glyphLines?.length) {\n ctx.beginPath()\n for (const glyph of glyphLines) {\n const x1 = cursor + glyph.x1 * glyphScaleX\n const y1 = startY + (1 - glyph.y1) * height\n const x2 = cursor + glyph.x2 * glyphScaleX\n const y2 = startY + (1 - glyph.y2) * height\n ctx.moveTo(x1, y1)\n ctx.lineTo(x2, y2)\n }\n ctx.stroke()\n }\n\n cursor += getAlphabetAdvanceWidth(char, characters[index + 1], fontSize)\n })\n}\n\nexport function strokeAlphabetText({\n ctx,\n text,\n fontSize,\n startX,\n startY,\n color,\n anchorAlignment = \"center\",\n rotationRadians,\n}: {\n ctx: StrokeAlphabetContext\n text: string\n fontSize: number\n startX: number\n startY: number\n color: string\n anchorAlignment?: NinePointAnchor\n rotationRadians?: number\n}): void {\n if (!text) return\n\n const layout = getAlphabetLayout(text, fontSize)\n const startPosition = getTextStartPosition(anchorAlignment, layout)\n const { lines, lineWidths, lineHeight, width, strokeWidth } = layout\n\n ctx.save()\n ctx.translate(startX, startY)\n if (rotationRadians) {\n ctx.rotate(rotationRadians)\n }\n\n ctx.strokeStyle = color\n ctx.lineWidth = strokeWidth\n ctx.lineCap = \"round\"\n ctx.lineJoin = \"round\"\n\n lines.forEach((line, lineIndex) => {\n const lineStartX =\n startPosition.x +\n getLineStartX({\n alignment: anchorAlignment,\n lineWidth: lineWidths[lineIndex]!,\n maxWidth: width,\n strokeWidth,\n })\n const lineStartY = startPosition.y + lineIndex * lineHeight\n\n strokeAlphabetLine({\n ctx,\n line,\n fontSize,\n startX: lineStartX,\n startY: lineStartY,\n layout,\n })\n })\n\n ctx.restore()\n}\n","/**\n * Decode bytes to text\n * @param bytes - Bytes to decode\n * @param encoding - Text encoding\n * @returns The decoded text\n */\nexport function decode(bytes: Uint8Array, encoding = 'utf8'): string {\n const decoder = new TextDecoder(encoding);\n return decoder.decode(bytes);\n}\n\nconst encoder = new TextEncoder();\n\n/**\n * Encode text to utf8\n * @param str - Text to encode\n * @returns The encoded bytes\n */\nexport function encode(str: string): Uint8Array {\n return encoder.encode(str);\n}\n","import { decode, encode } from './text.ts';\n\nconst defaultByteLength = 1024 * 8;\n\nconst hostBigEndian = (() => {\n const array = new Uint8Array(4);\n const view = new Uint32Array(array.buffer);\n return !((view[0] = 1) & (array[0] as number));\n})();\n\nexport type InputData = number | ArrayBufferLike | ArrayBufferView | IOBuffer;\n\nconst typedArrays = {\n int8: globalThis.Int8Array,\n uint8: globalThis.Uint8Array,\n int16: globalThis.Int16Array,\n uint16: globalThis.Uint16Array,\n int32: globalThis.Int32Array,\n uint32: globalThis.Uint32Array,\n uint64: globalThis.BigUint64Array,\n int64: globalThis.BigInt64Array,\n float32: globalThis.Float32Array,\n float64: globalThis.Float64Array,\n};\n\ntype TypedArrays = typeof typedArrays;\n\nexport interface IOBufferOptions {\n /**\n * Ignore the first n bytes of the ArrayBuffer.\n */\n offset?: number;\n}\n\nexport class IOBuffer {\n /**\n * Reference to the internal ArrayBuffer object.\n */\n public buffer: ArrayBufferLike;\n\n /**\n * Byte length of the internal ArrayBuffer.\n */\n public byteLength: number;\n\n /**\n * Byte offset of the internal ArrayBuffer.\n */\n public byteOffset: number;\n\n /**\n * Byte length of the internal ArrayBuffer.\n */\n public length: number;\n\n /**\n * The current offset of the buffer's pointer.\n */\n public offset: number;\n\n private lastWrittenByte: number;\n private littleEndian: boolean;\n\n private _data: DataView;\n private _mark: number;\n private _marks: number[];\n\n /**\n * Create a new IOBuffer.\n * @param data - The data to construct the IOBuffer with.\n * If data is a number, it will be the new buffer's length<br>\n * If data is `undefined`, the buffer will be initialized with a default length of 8Kb<br>\n * If data is an ArrayBuffer, SharedArrayBuffer, an ArrayBufferView (Typed Array), an IOBuffer instance,\n * or a Node.js Buffer, a view will be created over the underlying ArrayBuffer.\n * @param options - An object for the options.\n * @returns A new IOBuffer instance.\n */\n public constructor(\n data: InputData = defaultByteLength,\n options: IOBufferOptions = {},\n ) {\n let dataIsGiven = false;\n if (typeof data === 'number') {\n data = new ArrayBuffer(data);\n } else {\n dataIsGiven = true;\n this.lastWrittenByte = data.byteLength;\n }\n const offset = options.offset ? options.offset >>> 0 : 0;\n const byteLength = data.byteLength - offset;\n let dvOffset = offset;\n if (ArrayBuffer.isView(data) || data instanceof IOBuffer) {\n if (data.byteLength !== data.buffer.byteLength) {\n dvOffset = data.byteOffset + offset;\n }\n data = data.buffer;\n }\n if (dataIsGiven) {\n this.lastWrittenByte = byteLength;\n } else {\n this.lastWrittenByte = 0;\n }\n this.buffer = data;\n this.length = byteLength;\n this.byteLength = byteLength;\n this.byteOffset = dvOffset;\n this.offset = 0;\n this.littleEndian = true;\n this._data = new DataView(this.buffer, dvOffset, byteLength);\n this._mark = 0;\n this._marks = [];\n }\n\n /**\n * Checks if the memory allocated to the buffer is sufficient to store more\n * bytes after the offset.\n * @param byteLength - The needed memory in bytes.\n * @returns `true` if there is sufficient space and `false` otherwise.\n */\n public available(byteLength = 1): boolean {\n return this.offset + byteLength <= this.length;\n }\n\n /**\n * Check if little-endian mode is used for reading and writing multi-byte\n * values.\n * @returns `true` if little-endian mode is used, `false` otherwise.\n */\n public isLittleEndian(): boolean {\n return this.littleEndian;\n }\n\n /**\n * Set little-endian mode for reading and writing multi-byte values.\n * @returns This.\n */\n public setLittleEndian(): this {\n this.littleEndian = true;\n return this;\n }\n\n /**\n * Check if big-endian mode is used for reading and writing multi-byte values.\n * @returns `true` if big-endian mode is used, `false` otherwise.\n */\n public isBigEndian(): boolean {\n return !this.littleEndian;\n }\n\n /**\n * Switches to big-endian mode for reading and writing multi-byte values.\n * @returns This.\n */\n public setBigEndian(): this {\n this.littleEndian = false;\n return this;\n }\n\n /**\n * Move the pointer n bytes forward.\n * @param n - Number of bytes to skip.\n * @returns This.\n */\n public skip(n = 1): this {\n this.offset += n;\n return this;\n }\n\n /**\n * Move the pointer n bytes backward.\n * @param n - Number of bytes to move back.\n * @returns This.\n */\n public back(n = 1): this {\n this.offset -= n;\n return this;\n }\n\n /**\n * Move the pointer to the given offset.\n * @param offset - The offset to move to.\n * @returns This.\n */\n public seek(offset: number): this {\n this.offset = offset;\n return this;\n }\n\n /**\n * Store the current pointer offset.\n * @see {@link IOBuffer#reset}\n * @returns This.\n */\n public mark(): this {\n this._mark = this.offset;\n return this;\n }\n\n /**\n * Move the pointer back to the last pointer offset set by mark.\n * @see {@link IOBuffer#mark}\n * @returns This.\n */\n public reset(): this {\n this.offset = this._mark;\n return this;\n }\n\n /**\n * Push the current pointer offset to the mark stack.\n * @see {@link IOBuffer#popMark}\n * @returns This.\n */\n public pushMark(): this {\n this._marks.push(this.offset);\n return this;\n }\n\n /**\n * Pop the last pointer offset from the mark stack, and set the current\n * pointer offset to the popped value.\n * @see {@link IOBuffer#pushMark}\n * @returns This.\n */\n public popMark(): this {\n const offset = this._marks.pop();\n if (offset === undefined) {\n throw new Error('Mark stack empty');\n }\n this.seek(offset);\n return this;\n }\n\n /**\n * Move the pointer offset back to 0.\n * @returns This.\n */\n public rewind(): this {\n this.offset = 0;\n return this;\n }\n\n /**\n * Make sure the buffer has sufficient memory to write a given byteLength at\n * the current pointer offset.\n * If the buffer's memory is insufficient, this method will create a new\n * buffer (a copy) with a length that is twice (byteLength + current offset).\n * @param byteLength - The needed memory in bytes.\n * @returns This.\n */\n public ensureAvailable(byteLength = 1): this {\n if (!this.available(byteLength)) {\n const lengthNeeded = this.offset + byteLength;\n const newLength = lengthNeeded * 2;\n const newArray = new Uint8Array(newLength);\n newArray.set(new Uint8Array(this.buffer));\n this.buffer = newArray.buffer;\n this.length = newLength;\n this.byteLength = newLength;\n this._data = new DataView(this.buffer);\n }\n return this;\n }\n\n /**\n * Read a byte and return false if the byte's value is 0, or true otherwise.\n * Moves pointer forward by one byte.\n * @returns The read boolean.\n */\n public readBoolean(): boolean {\n return this.readUint8() !== 0;\n }\n\n /**\n * Read a signed 8-bit integer and move pointer forward by 1 byte.\n * @returns The read byte.\n */\n public readInt8(): number {\n return this._data.getInt8(this.offset++);\n }\n\n /**\n * Read an unsigned 8-bit integer and move pointer forward by 1 byte.\n * @returns The read byte.\n */\n public readUint8(): number {\n return this._data.getUint8(this.offset++);\n }\n\n /**\n * Alias for {@link IOBuffer#readUint8}.\n * @returns The read byte.\n */\n public readByte(): number {\n return this.readUint8();\n }\n\n /**\n * Read `n` bytes and move pointer forward by `n` bytes.\n * @param n - Number of bytes to read.\n * @returns The read bytes.\n */\n public readBytes(n = 1): Uint8Array {\n return this.readArray(n, 'uint8');\n }\n\n /**\n * Creates an array of corresponding to the type `type` and size `size`.\n * For example, type `uint8` will create a `Uint8Array`.\n * @param size - size of the resulting array\n * @param type - number type of elements to read\n * @returns The read array.\n */\n public readArray<T extends keyof typeof typedArrays>(\n size: number,\n type: T,\n ): InstanceType<TypedArrays[T]> {\n const bytes = typedArrays[type].BYTES_PER_ELEMENT * size;\n const offset = this.byteOffset + this.offset;\n const slice = this.buffer.slice(offset, offset + bytes);\n if (\n this.littleEndian === hostBigEndian &&\n type !== 'uint8' &&\n type !== 'int8'\n ) {\n const slice = new Uint8Array(this.buffer.slice(offset, offset + bytes));\n slice.reverse();\n const returnArray = new typedArrays[type](slice.buffer as ArrayBuffer);\n this.offset += bytes;\n returnArray.reverse();\n return returnArray as InstanceType<TypedArrays[T]>;\n }\n const returnArray = new typedArrays[type](slice as ArrayBuffer);\n this.offset += bytes;\n return returnArray as InstanceType<TypedArrays[T]>;\n }\n\n /**\n * Read a 16-bit signed integer and move pointer forward by 2 bytes.\n * @returns The read value.\n */\n public readInt16(): number {\n const value = this._data.getInt16(this.offset, this.littleEndian);\n this.offset += 2;\n return value;\n }\n\n /**\n * Read a 16-bit unsigned integer and move pointer forward by 2 bytes.\n * @returns The read value.\n */\n public readUint16(): number {\n const value = this._data.getUint16(this.offset, this.littleEndian);\n this.offset += 2;\n return value;\n }\n\n /**\n * Read a 32-bit signed integer and move pointer forward by 4 bytes.\n * @returns The read value.\n */\n public readInt32(): number {\n const value = this._data.getInt32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n /**\n * Read a 32-bit unsigned integer and move pointer forward by 4 bytes.\n * @returns The read value.\n */\n public readUint32(): number {\n const value = this._data.getUint32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n /**\n * Read a 32-bit floating number and move pointer forward by 4 bytes.\n * @returns The read value.\n */\n public readFloat32(): number {\n const value = this._data.getFloat32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n /**\n * Read a 64-bit floating number and move pointer forward by 8 bytes.\n * @returns The read value.\n */\n public readFloat64(): number {\n const value = this._data.getFloat64(this.offset, this.littleEndian);\n this.offset += 8;\n return value;\n }\n\n /**\n * Read a 64-bit signed integer number and move pointer forward by 8 bytes.\n * @returns The read value.\n */\n public readBigInt64(): bigint {\n const value = this._data.getBigInt64(this.offset, this.littleEndian);\n this.offset += 8;\n return value;\n }\n\n /**\n * Read a 64-bit unsigned integer number and move pointer forward by 8 bytes.\n * @returns The read value.\n */\n public readBigUint64(): bigint {\n const value = this._data.getBigUint64(this.offset, this.littleEndian);\n this.offset += 8;\n return value;\n }\n\n /**\n * Read a 1-byte ASCII character and move pointer forward by 1 byte.\n * @returns The read character.\n */\n public readChar(): string {\n // eslint-disable-next-line unicorn/prefer-code-point\n return String.fromCharCode(this.readInt8());\n }\n\n /**\n * Read `n` 1-byte ASCII characters and move pointer forward by `n` bytes.\n * @param n - Number of characters to read.\n * @returns The read characters.\n */\n public readChars(n = 1): string {\n let result = '';\n for (let i = 0; i < n; i++) {\n result += this.readChar();\n }\n return result;\n }\n\n /**\n * Read the next `n` bytes, return a UTF-8 decoded string and move pointer\n * forward by `n` bytes.\n * @param n - Number of bytes to read.\n * @returns The decoded string.\n */\n public readUtf8(n = 1): string {\n return decode(this.readBytes(n));\n }\n\n /**\n * Read the next `n` bytes, return a string decoded with `encoding` and move pointer\n * forward by `n` bytes.\n * If no encoding is passed, the function is equivalent to @see {@link IOBuffer#readUtf8}\n * @param n - Number of bytes to read.\n * @param encoding - The encoding to use. Default is 'utf8'.\n * @returns The decoded string.\n */\n public decodeText(n = 1, encoding = 'utf8'): string {\n return decode(this.readBytes(n), encoding);\n }\n\n /**\n * Write 0xff if the passed value is truthy, 0x00 otherwise and move pointer\n * forward by 1 byte.\n * @param value - The value to write.\n * @returns This.\n */\n public writeBoolean(value: unknown): this {\n this.writeUint8(value ? 0xff : 0x00);\n return this;\n }\n\n /**\n * Write `value` as an 8-bit signed integer and move pointer forward by 1 byte.\n * @param value - The value to write.\n * @returns This.\n */\n public writeInt8(value: number): this {\n this.ensureAvailable(1);\n this._data.setInt8(this.offset++, value);\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as an 8-bit unsigned integer and move pointer forward by 1\n * byte.\n * @param value - The value to write.\n * @returns This.\n */\n public writeUint8(value: number): this {\n this.ensureAvailable(1);\n this._data.setUint8(this.offset++, value);\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * An alias for {@link IOBuffer#writeUint8}.\n * @param value - The value to write.\n * @returns This.\n */\n public writeByte(value: number): this {\n return this.writeUint8(value);\n }\n\n /**\n * Write all elements of `bytes` as uint8 values and move pointer forward by\n * `bytes.length` bytes.\n * @param bytes - The array of bytes to write.\n * @returns This.\n */\n public writeBytes(bytes: ArrayLike<number>): this {\n this.ensureAvailable(bytes.length);\n // eslint-disable-next-line @typescript-eslint/prefer-for-of\n for (let i = 0; i < bytes.length; i++) {\n this._data.setUint8(this.offset++, bytes[i] as number);\n }\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 16-bit signed integer and move pointer forward by 2\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeInt16(value: number): this {\n this.ensureAvailable(2);\n this._data.setInt16(this.offset, value, this.littleEndian);\n this.offset += 2;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 16-bit unsigned integer and move pointer forward by 2\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeUint16(value: number): this {\n this.ensureAvailable(2);\n this._data.setUint16(this.offset, value, this.littleEndian);\n this.offset += 2;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 32-bit signed integer and move pointer forward by 4\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeInt32(value: number): this {\n this.ensureAvailable(4);\n this._data.setInt32(this.offset, value, this.littleEndian);\n this.offset += 4;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 32-bit unsigned integer and move pointer forward by 4\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeUint32(value: number): this {\n this.ensureAvailable(4);\n this._data.setUint32(this.offset, value, this.littleEndian);\n this.offset += 4;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 32-bit floating number and move pointer forward by 4\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeFloat32(value: number): this {\n this.ensureAvailable(4);\n this._data.setFloat32(this.offset, value, this.littleEndian);\n this.offset += 4;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 64-bit floating number and move pointer forward by 8\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeFloat64(value: number): this {\n this.ensureAvailable(8);\n this._data.setFloat64(this.offset, value, this.littleEndian);\n this.offset += 8;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 64-bit signed bigint and move pointer forward by 8\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeBigInt64(value: bigint): this {\n this.ensureAvailable(8);\n this._data.setBigInt64(this.offset, value, this.littleEndian);\n this.offset += 8;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 64-bit unsigned bigint and move pointer forward by 8\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeBigUint64(value: bigint): this {\n this.ensureAvailable(8);\n this._data.setBigUint64(this.offset, value, this.littleEndian);\n this.offset += 8;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write the charCode of `str`'s first character as an 8-bit unsigned integer\n * and move pointer forward by 1 byte.\n * @param str - The character to write.\n * @returns This.\n */\n public writeChar(str: string): this {\n // eslint-disable-next-line unicorn/prefer-code-point\n return this.writeUint8(str.charCodeAt(0));\n }\n\n /**\n * Write the charCodes of all `str`'s characters as 8-bit unsigned integers\n * and move pointer forward by `str.length` bytes.\n * @param str - The characters to write.\n * @returns This.\n */\n public writeChars(str: string): this {\n for (let i = 0; i < str.length; i++) {\n // eslint-disable-next-line unicorn/prefer-code-point\n this.writeUint8(str.charCodeAt(i));\n }\n return this;\n }\n\n /**\n * UTF-8 encode and write `str` to the current pointer offset and move pointer\n * forward according to the encoded length.\n * @param str - The string to write.\n * @returns This.\n */\n public writeUtf8(str: string): this {\n return this.writeBytes(encode(str));\n }\n\n /**\n * Export a Uint8Array view of the internal buffer.\n * The view starts at the byte offset and its length\n * is calculated to stop at the last written byte or the original length.\n * @returns A new Uint8Array view.\n */\n public toArray(): Uint8Array {\n return new Uint8Array(this.buffer, this.byteOffset, this.lastWrittenByte);\n }\n\n /**\n * Get the total number of bytes written so far, regardless of the current offset.\n * @returns - Total number of bytes.\n */\n public getWrittenByteLength() {\n return this.lastWrittenByte - this.byteOffset;\n }\n\n /**\n * Update the last written byte offset\n * @private\n */\n private _updateLastWrittenByte(): void {\n if (this.offset > this.lastWrittenByte) {\n this.lastWrittenByte = this.offset;\n }\n }\n}\n","import type { IOBuffer } from 'iobuffer';\n\nconst crcTable: number[] = [];\nfor (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) {\n if (c & 1) {\n c = 0xedb88320 ^ (c >>> 1);\n } else {\n c = c >>> 1;\n }\n }\n crcTable[n] = c;\n}\n\nconst initialCrc = 0xffffffff;\nfunction updateCrc(\n currentCrc: number,\n data: Uint8Array,\n length: number,\n): number {\n let c = currentCrc;\n for (let n = 0; n < length; n++) {\n c = crcTable[(c ^ data[n]) & 0xff] ^ (c >>> 8);\n }\n return c;\n}\n\nfunction crc(data: Uint8Array, length: number): number {\n return (updateCrc(initialCrc, data, length) ^ initialCrc) >>> 0;\n}\n\nexport function checkCrc(\n buffer: IOBuffer,\n crcLength: number,\n chunkName: string,\n) {\n const expectedCrc = buffer.readUint32();\n const actualCrc = crc(\n new Uint8Array(\n buffer.buffer,\n buffer.byteOffset + buffer.offset - crcLength - 4,\n crcLength,\n ),\n crcLength,\n ); // \"- 4\" because we already advanced by reading the CRC\n if (actualCrc !== expectedCrc) {\n throw new Error(\n `CRC mismatch for chunk ${chunkName}. Expected ${expectedCrc}, found ${actualCrc}`,\n );\n }\n}\n\nexport function writeCrc(buffer: IOBuffer, length: number) {\n buffer.writeUint32(\n crc(\n new Uint8Array(\n buffer.buffer,\n buffer.byteOffset + buffer.offset - length,\n length,\n ),\n length,\n ),\n );\n}\n","import { applyUnfilter } from './apply_unfilter.ts';\nimport type { DecodeInterlaceNullParams } from './decode_interlace_null.ts';\n\nconst uint16 = new Uint16Array([0x00ff]);\nconst uint8 = new Uint8Array(uint16.buffer);\nconst osIsLittleEndian = uint8[0] === 0xff;\n/**\n * Decodes the Adam7 interlaced PNG data.\n * @param params - DecodeInterlaceNullParams\n * @returns - array of pixel data.\n */\nexport function decodeInterlaceAdam7(params: DecodeInterlaceNullParams) {\n const { data, width, height, channels, depth } = params;\n\n // Adam7 interlacing pattern\n const passes = [\n { x: 0, y: 0, xStep: 8, yStep: 8 }, // Pass 1\n { x: 4, y: 0, xStep: 8, yStep: 8 }, // Pass 2\n { x: 0, y: 4, xStep: 4, yStep: 8 }, // Pass 3\n { x: 2, y: 0, xStep: 4, yStep: 4 }, // Pass 4\n { x: 0, y: 2, xStep: 2, yStep: 4 }, // Pass 5\n { x: 1, y: 0, xStep: 2, yStep: 2 }, // Pass 6\n { x: 0, y: 1, xStep: 1, yStep: 2 }, // Pass 7\n ];\n\n const bytesPerPixel = Math.ceil(depth / 8) * channels;\n const resultData = new Uint8Array(height * width * bytesPerPixel);\n\n let offset = 0;\n\n // Process each pass\n for (let passIndex = 0; passIndex < 7; passIndex++) {\n const pass = passes[passIndex];\n\n // Calculate pass dimensions\n const passWidth = Math.ceil((width - pass.x) / pass.xStep);\n const passHeight = Math.ceil((height - pass.y) / pass.yStep);\n\n if (passWidth <= 0 || passHeight <= 0) continue;\n\n const passLineBytes = passWidth * bytesPerPixel;\n const prevLine = new Uint8Array(passLineBytes);\n\n // Process each scanline in this pass\n for (let y = 0; y < passHeight; y++) {\n // First byte is the filter type\n const filterType = data[offset++];\n const currentLine = data.subarray(offset, offset + passLineBytes);\n offset += passLineBytes;\n\n // Create a new line for the unfiltered data\n const newLine = new Uint8Array(passLineBytes);\n\n // Apply the appropriate unfilter\n applyUnfilter(\n filterType,\n currentLine,\n newLine,\n prevLine,\n passLineBytes,\n bytesPerPixel,\n );\n prevLine.set(newLine);\n\n for (let x = 0; x < passWidth; x++) {\n const outputX = pass.x + x * pass.xStep;\n const outputY = pass.y + y * pass.yStep;\n if (outputX >= width || outputY >= height) continue;\n for (let i = 0; i < bytesPerPixel; i++) {\n resultData[(outputY * width + outputX) * bytesPerPixel + i] =\n newLine[x * bytesPerPixel + i];\n }\n }\n }\n }\n if (depth === 16) {\n const uint16Data = new Uint16Array(resultData.buffer);\n if (osIsLittleEndian) {\n for (let k = 0; k < uint16Data.length; k++) {\n // PNG is always big endian. Swap the bytes.\n uint16Data[k] = swap16(uint16Data[k]);\n }\n }\n return uint16Data;\n } else {\n return resultData;\n }\n}\n\nfunction swap16(val: number): number {\n return ((val & 0xff) << 8) | ((val >> 8) & 0xff);\n}\n","import type { PngDataArray } from '../types.ts';\n\nimport {\n unfilterAverage,\n unfilterNone,\n unfilterPaeth,\n unfilterSub,\n unfilterUp,\n} from './unfilter.ts';\n\nconst uint16 = new Uint16Array([0x00ff]);\nconst uint8 = new Uint8Array(uint16.buffer);\nconst osIsLittleEndian = uint8[0] === 0xff;\n\nconst empty = new Uint8Array(0);\n\nexport interface DecodeInterlaceNullParams {\n data: Uint8Array;\n width: number;\n height: number;\n channels: number;\n depth: number;\n}\n\nexport function decodeInterlaceNull(\n params: DecodeInterlaceNullParams,\n): PngDataArray {\n const { data, width, height, channels, depth } = params;\n\n const bytesPerPixel = Math.ceil(depth / 8) * channels;\n\n const bytesPerLine = Math.ceil((depth / 8) * channels * width);\n const newData = new Uint8Array(height * bytesPerLine);\n\n let prevLine = empty;\n let offset = 0;\n let currentLine;\n let newLine;\n\n for (let i = 0; i < height; i++) {\n currentLine = data.subarray(offset + 1, offset + 1 + bytesPerLine);\n newLine = newData.subarray(i * bytesPerLine, (i + 1) * bytesPerLine);\n switch (data[offset]) {\n case 0:\n unfilterNone(currentLine, newLine, bytesPerLine);\n break;\n case 1:\n unfilterSub(currentLine, newLine, bytesPerLine, bytesPerPixel);\n break;\n case 2:\n unfilterUp(currentLine, newLine, prevLine, bytesPerLine);\n break;\n case 3:\n unfilterAverage(\n currentLine,\n newLine,\n prevLine,\n bytesPerLine,\n bytesPerPixel,\n );\n break;\n case 4:\n unfilterPaeth(\n currentLine,\n newLine,\n prevLine,\n bytesPerLine,\n bytesPerPixel,\n );\n break;\n default:\n throw new Error(`Unsupported filter: ${data[offset]}`);\n }\n prevLine = newLine;\n offset += bytesPerLine + 1;\n }\n\n if (depth === 16) {\n const uint16Data = new Uint16Array(newData.buffer);\n if (osIsLittleEndian) {\n for (let k = 0; k < uint16Data.length; k++) {\n // PNG is always big endian. Swap the bytes.\n uint16Data[k] = swap16(uint16Data[k]);\n }\n }\n return uint16Data;\n } else {\n return newData;\n }\n}\n\nfunction swap16(val: number): number {\n return ((val & 0xff) << 8) | ((val >> 8) & 0xff);\n}\n","import type { IOBuffer } from 'iobuffer';\n\n// https://www.w3.org/TR/PNG/#5PNG-file-signature\n\nconst pngSignature = Uint8Array.of(137, 80, 78, 71, 13, 10, 26, 10);\n\nexport function writeSignature(buffer: IOBuffer) {\n buffer.writeBytes(pngSignature);\n}\n\nexport function checkSignature(buffer: IOBuffer) {\n if (!hasPngSignature(buffer.readBytes(pngSignature.length))) {\n throw new Error('wrong PNG signature');\n }\n}\n\nexport function hasPngSignature(array: ArrayLike<number>) {\n if (array.length < pngSignature.length) {\n return false;\n }\n for (let i = 0; i < pngSignature.length; i++) {\n if (array[i] !== pngSignature[i]) {\n return false;\n }\n }\n return true;\n}\n","import type { IOBuffer } from 'iobuffer';\n\nimport { writeCrc } from './crc.ts';\n\n// https://www.w3.org/TR/png/#11tEXt\n\nexport const textChunkName = 'tEXt';\n\nconst NULL = 0;\n\nconst latin1Decoder = new TextDecoder('latin1');\n\nfunction validateKeyword(keyword: string) {\n validateLatin1(keyword);\n if (keyword.length === 0 || keyword.length > 79) {\n throw new Error('keyword length must be between 1 and 79');\n }\n}\n\n// eslint-disable-next-line no-control-regex\nconst latin1Regex = /^[\\u0000-\\u00FF]*$/;\nfunction validateLatin1(text: string) {\n if (!latin1Regex.test(text)) {\n throw new Error('invalid latin1 text');\n }\n}\n\nexport function decodetEXt(\n text: Record<string, string>,\n buffer: IOBuffer,\n length: number,\n) {\n const keyword = readKeyword(buffer);\n text[keyword] = readLatin1(buffer, length - keyword.length - 1);\n}\n\nexport function encodetEXt(buffer: IOBuffer, keyword: string, text: string) {\n validateKeyword(keyword);\n validateLatin1(text);\n const length = keyword.length + 1 /* NULL */ + text.length;\n\n buffer.writeUint32(length);\n buffer.writeChars(textChunkName);\n buffer.writeChars(keyword);\n buffer.writeByte(NULL);\n buffer.writeChars(text);\n writeCrc(buffer, length + 4);\n}\n\n// https://www.w3.org/TR/png/#11keywords\nexport function readKeyword(buffer: IOBuffer): string {\n buffer.mark();\n while (buffer.readByte() !== NULL) {\n /* advance */\n }\n const end = buffer.offset;\n buffer.reset();\n const keyword = latin1Decoder.decode(\n buffer.readBytes(end - buffer.offset - 1),\n );\n // NULL\n buffer.skip(1);\n\n validateKeyword(keyword);\n\n return keyword;\n}\n\nexport function readLatin1(buffer: IOBuffer, length: number): string {\n return latin1Decoder.decode(buffer.readBytes(length));\n}\n","import { type Matrix, applyToPoint, inverse } from \"transformation-matrix\"\nimport type { InfiniteLine, Point, Viewbox } from \"./types\"\n\nconst EPSILON = 1e-9\n\nconst isWithin = (value: number, min: number, max: number) => {\n return value >= min - EPSILON && value <= max + EPSILON\n}\n\nconst dedupePoints = (points: Point[]) => {\n const unique: Point[] = []\n for (const point of points) {\n if (\n !unique.some(\n (other) =>\n Math.abs(other.x - point.x) < EPSILON &&\n Math.abs(other.y - point.y) < EPSILON,\n )\n ) {\n unique.push(point)\n }\n }\n return unique\n}\n\nexport function clipInfiniteLineToBounds(\n infiniteLine: InfiniteLine,\n bounds: Viewbox,\n): [Point, Point] | null {\n const { origin, directionVector } = infiniteLine\n\n if (\n Math.abs(directionVector.x) < EPSILON &&\n Math.abs(directionVector.y) < EPSILON\n ) {\n return null\n }\n\n const intersections: Point[] = []\n\n if (Math.abs(directionVector.x) >= EPSILON) {\n const tAtMinX = (bounds.minX - origin.x) / directionVector.x\n const yAtMinX = origin.y + tAtMinX * directionVector.y\n if (isWithin(yAtMinX, bounds.minY, bounds.maxY)) {\n intersections.push({ x: bounds.minX, y: yAtMinX })\n }\n\n const tAtMaxX = (bounds.maxX - origin.x) / directionVector.x\n const yAtMaxX = origin.y + tAtMaxX * directionVector.y\n if (isWithin(yAtMaxX, bounds.minY, bounds.maxY)) {\n intersections.push({ x: bounds.maxX, y: yAtMaxX })\n }\n }\n\n if (Math.abs(directionVector.y) >= EPSILON) {\n const tAtMinY = (bounds.minY - origin.y) / directionVector.y\n const xAtMinY = origin.x + tAtMinY * directionVector.x\n if (isWithin(xAtMinY, bounds.minX, bounds.maxX)) {\n intersections.push({ x: xAtMinY, y: bounds.minY })\n }\n\n const tAtMaxY = (bounds.maxY - origin.y) / directionVector.y\n const xAtMaxY = origin.x + tAtMaxY * directionVector.x\n if (isWithin(xAtMaxY, bounds.minX, bounds.maxX)) {\n intersections.push({ x: xAtMaxY, y: bounds.maxY })\n }\n }\n\n const uniqueIntersections = dedupePoints(intersections)\n\n if (uniqueIntersections.length < 2) {\n return null\n }\n\n let first = uniqueIntersections[0]\n let second = uniqueIntersections[1]\n let maxDistanceSquared = (first.x - second.x) ** 2 + (first.y - second.y) ** 2\n\n for (let i = 0; i < uniqueIntersections.length; i++) {\n for (let j = i + 1; j < uniqueIntersections.length; j++) {\n const a = uniqueIntersections[i]\n const b = uniqueIntersections[j]\n const distanceSquared = (a.x - b.x) ** 2 + (a.y - b.y) ** 2\n if (distanceSquared > maxDistanceSquared) {\n first = a\n second = b\n maxDistanceSquared = distanceSquared\n }\n }\n }\n\n return [first, second]\n}\n\nexport function getViewportBoundsFromMatrix(\n matrix: Matrix,\n width: number,\n height: number,\n): Viewbox {\n const screenToReal = inverse(matrix)\n const corners = [\n applyToPoint(screenToReal, { x: 0, y: 0 }),\n applyToPoint(screenToReal, { x: width, y: 0 }),\n applyToPoint(screenToReal, { x: 0, y: height }),\n applyToPoint(screenToReal, { x: width, y: height }),\n ]\n\n return {\n minX: Math.min(...corners.map((p) => p.x)),\n maxX: Math.max(...corners.map((p) => p.x)),\n minY: Math.min(...corners.map((p) => p.y)),\n maxY: Math.max(...corners.map((p) => p.y)),\n }\n}\n","export const FONT_SIZE_WIDTH_RATIO = 0.6\nexport const FONT_SIZE_HEIGHT_RATIO = 1\n","import { applyToPoint, type Matrix } from \"transformation-matrix\"\nimport type { Point, Rect, Viewbox } from \"./types\"\n\ntype XYPoint = { x: number; y: number }\n\nconst getDistanceBetweenPoints = (a: XYPoint, b: XYPoint) => {\n return Math.hypot(a.x - b.x, a.y - b.y)\n}\n\nexport const getRectRotationRadians = (\n rect: Pick<Rect, \"ccwRotationDegrees\">,\n) => {\n return ((rect.ccwRotationDegrees ?? 0) * Math.PI) / 180\n}\n\nconst getScreenRotationMultiplier = (matrix: Matrix) => {\n // Screen coordinates have +Y downward. Orientation-preserving transforms\n // therefore need the math angle inverted to look visually CCW.\n const determinant = matrix.a * matrix.d - matrix.b * matrix.c\n return determinant < 0 ? 1 : -1\n}\n\nexport const getRectRotationRadiansForMatrix = (\n rect: Pick<Rect, \"ccwRotationDegrees\">,\n matrix: Matrix,\n) => {\n return getRectRotationRadians(rect) * getScreenRotationMultiplier(matrix)\n}\nconst rotatePoint = (point: XYPoint, angleRadians: number): XYPoint => {\n const cos = Math.cos(angleRadians)\n const sin = Math.sin(angleRadians)\n\n return {\n x: point.x * cos - point.y * sin,\n y: point.x * sin + point.y * cos,\n }\n}\n\nexport const getRectCorners = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n): Point[] => {\n return getRectCornersWithAngle(rect, getRectRotationRadians(rect))\n}\n\nexport const getRectCornersForMatrix = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n matrix: Matrix,\n): Point[] => {\n return getRectCornersWithAngle(\n rect,\n getRectRotationRadiansForMatrix(rect, matrix),\n )\n}\n\nconst getRectCornersWithAngle = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n angleRadians: number,\n): Point[] => {\n const halfWidth = rect.width / 2\n const halfHeight = rect.height / 2\n\n return [\n { x: -halfWidth, y: -halfHeight },\n { x: halfWidth, y: -halfHeight },\n { x: halfWidth, y: halfHeight },\n { x: -halfWidth, y: halfHeight },\n ].map((corner) => {\n const rotatedCorner = rotatePoint(corner, angleRadians)\n return {\n x: rect.center.x + rotatedCorner.x,\n y: rect.center.y + rotatedCorner.y,\n }\n })\n}\n\nexport const getRectBounds = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n): Viewbox => {\n const corners = getRectCorners(rect)\n\n return corners.reduce(\n (bounds, point) => ({\n minX: Math.min(bounds.minX, point.x),\n maxX: Math.max(bounds.maxX, point.x),\n minY: Math.min(bounds.minY, point.y),\n maxY: Math.max(bounds.maxY, point.y),\n }),\n {\n minX: Infinity,\n maxX: -Infinity,\n minY: Infinity,\n maxY: -Infinity,\n },\n )\n}\n\nexport const getProjectedRectGeometry = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n matrix: Matrix,\n) => {\n const corners = getRectCornersForMatrix(rect, matrix).map((point) =>\n applyToPoint(matrix, point),\n )\n const center = applyToPoint(matrix, rect.center)\n const width = getDistanceBetweenPoints(corners[0], corners[1])\n const height = getDistanceBetweenPoints(corners[1], corners[2])\n const angleRadians =\n corners.length >= 2\n ? Math.atan2(corners[1].y - corners[0].y, corners[1].x - corners[0].x)\n : 0\n const angleDegrees = (angleRadians * 180) / Math.PI\n\n const bounds = corners.reduce(\n (result, point) => ({\n minX: Math.min(result.minX, point.x),\n maxX: Math.max(result.maxX, point.x),\n minY: Math.min(result.minY, point.y),\n maxY: Math.max(result.maxY, point.y),\n }),\n {\n minX: Infinity,\n maxX: -Infinity,\n minY: Infinity,\n maxY: -Infinity,\n },\n )\n\n return {\n center,\n corners,\n width,\n height,\n angleRadians,\n angleDegrees,\n bounds,\n }\n}\n","import type { Arrow } from \"./types\"\n\nconst DEFAULT_ARROW_SHAFT_WIDTH = 2\nconst DEFAULT_ARROW_HEAD_WIDTH = 12\nconst DEFAULT_ARROW_HEAD_LENGTH = 12\n\nexport type ArrowHeadGeometry = {\n tip: { x: number; y: number }\n base: { x: number; y: number }\n leftWing: { x: number; y: number }\n rightWing: { x: number; y: number }\n}\n\nexport type ArrowGeometry = {\n shaftStart: { x: number; y: number }\n shaftEnd: { x: number; y: number }\n heads: ArrowHeadGeometry[]\n shaftWidth: number\n headLength: number\n headWidth: number\n length: number\n}\n\nexport type InlineLabelLayout = {\n x: number\n y: number\n angleRadians: number\n angleDegrees: number\n direction: { x: number; y: number }\n normal: { x: number; y: number }\n}\n\nconst createDegenerateHead = (point: {\n x: number\n y: number\n}): ArrowHeadGeometry => ({\n tip: { ...point },\n base: { ...point },\n leftWing: { ...point },\n rightWing: { ...point },\n})\n\nconst createHead = (\n tip: { x: number; y: number },\n base: { x: number; y: number },\n headWidth: number,\n): ArrowHeadGeometry => {\n const dirX = tip.x - base.x\n const dirY = tip.y - base.y\n const length = Math.hypot(dirX, dirY)\n\n if (length === 0) {\n return createDegenerateHead(tip)\n }\n\n const dirUnitX = dirX / length\n const dirUnitY = dirY / length\n const perpX = -dirUnitY * (headWidth / 2)\n const perpY = dirUnitX * (headWidth / 2)\n\n return {\n tip: { ...tip },\n base: { ...base },\n leftWing: { x: base.x + perpX, y: base.y + perpY },\n rightWing: { x: base.x - perpX, y: base.y - perpY },\n }\n}\n\nexport function getArrowGeometry(arrow: Arrow): ArrowGeometry {\n const { start, end } = arrow\n\n const vx = end.x - start.x\n const vy = end.y - start.y\n const length = Math.hypot(vx, vy)\n\n const shaftWidth = DEFAULT_ARROW_SHAFT_WIDTH\n const headWidth = DEFAULT_ARROW_HEAD_WIDTH\n\n if (length === 0) {\n const heads = arrow.doubleSided\n ? [createDegenerateHead(start), createDegenerateHead(start)]\n : [createDegenerateHead(start)]\n return {\n shaftStart: { ...start },\n shaftEnd: { ...start },\n heads,\n shaftWidth,\n headLength: 0,\n headWidth,\n length,\n }\n }\n\n const ux = vx / length\n const uy = vy / length\n\n const baseHeadLength = Math.min(DEFAULT_ARROW_HEAD_LENGTH, length * 0.5)\n const desiredHeadLength = Math.max(baseHeadLength, shaftWidth * 2)\n const maxHeadLength = arrow.doubleSided ? length / 2 : length\n const headLength = Math.min(desiredHeadLength, maxHeadLength)\n\n const endHeadBase = {\n x: end.x - ux * headLength,\n y: end.y - uy * headLength,\n }\n\n const heads: ArrowHeadGeometry[] = [createHead(end, endHeadBase, headWidth)]\n\n let shaftStart = { ...start }\n const shaftEnd = { ...endHeadBase }\n\n if (arrow.doubleSided) {\n const startHeadBase = {\n x: start.x + ux * headLength,\n y: start.y + uy * headLength,\n }\n\n heads.unshift(createHead(start, startHeadBase, headWidth))\n shaftStart = startHeadBase\n }\n\n return {\n shaftStart,\n shaftEnd,\n heads,\n shaftWidth,\n headLength,\n headWidth,\n length,\n }\n}\n\nexport function getArrowBoundingBox(arrow: Arrow) {\n const geometry = getArrowGeometry(arrow)\n const points = [\n geometry.shaftStart,\n geometry.shaftEnd,\n ...geometry.heads.flatMap((head) => [\n head.tip,\n head.base,\n head.leftWing,\n head.rightWing,\n ]),\n ]\n\n return points.reduce(\n (acc, point) => ({\n minX: Math.min(acc.minX, point.x),\n maxX: Math.max(acc.maxX, point.x),\n minY: Math.min(acc.minY, point.y),\n maxY: Math.max(acc.maxY, point.y),\n }),\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n}\n\nexport function getInlineLabelLayout(\n shaftStart: { x: number; y: number },\n shaftEnd: { x: number; y: number },\n {\n fontSize = 12,\n strokeWidth = 2,\n normalPadding = 6,\n alongOffset = 0,\n }: {\n fontSize?: number\n strokeWidth?: number\n normalPadding?: number\n alongOffset?: number\n } = {},\n): InlineLabelLayout {\n const midpoint = {\n x: (shaftStart.x + shaftEnd.x) / 2,\n y: (shaftStart.y + shaftEnd.y) / 2,\n }\n const dx = shaftEnd.x - shaftStart.x\n const dy = shaftEnd.y - shaftStart.y\n const length = Math.hypot(dx, dy)\n\n if (length === 0) {\n return {\n x: midpoint.x + alongOffset,\n y: midpoint.y - (strokeWidth / 2 + fontSize * 0.65 + normalPadding),\n angleRadians: 0,\n angleDegrees: 0,\n direction: { x: 1, y: 0 },\n normal: { x: 0, y: -1 },\n }\n }\n\n let dirX = dx / length\n let dirY = dy / length\n let normalX = -dirY\n let normalY = dirX\n\n const isUpsideDown = dirX < 0 || (dirX === 0 && dirY < 0)\n if (isUpsideDown) {\n dirX = -dirX\n dirY = -dirY\n normalX = -normalX\n normalY = -normalY\n }\n\n const angleRadians = Math.atan2(dirY, dirX)\n const normalOffset = strokeWidth / 2 + fontSize * 0.65 + normalPadding\n\n return {\n x: midpoint.x + normalX * normalOffset + dirX * alongOffset,\n y: midpoint.y + normalY * normalOffset + dirY * alongOffset,\n angleRadians,\n angleDegrees: (angleRadians * 180) / Math.PI,\n direction: { x: dirX, y: dirY },\n normal: { x: normalX, y: normalY },\n }\n}\n","// These are default colors if no color is provided\n// colors are made based on the index of the item in the array\n\nexport const defaultColors = [\n \"rgba(239, 68, 68, 0.8)\", // red-300\n \"rgba(249, 115, 22, 0.8)\", // orange-300\n \"rgba(245, 158, 11, 0.8)\", // amber-300\n \"rgba(234, 179, 8, 0.8)\", // yellow-300\n \"rgba(132, 204, 22, 0.8)\", // lime-300\n \"rgba(34, 197, 94, 0.8)\", // green-300\n \"rgba(16, 185, 129, 0.8)\", // emerald-300\n \"rgba(20, 184, 166, 0.8)\", // teal-300\n \"rgba(6, 182, 212, 0.8)\", // cyan-300\n \"rgba(14, 165, 233, 0.8)\", // sky-300\n \"rgba(59, 130, 246, 0.8)\", // blue-300\n \"rgba(99, 102, 241, 0.8)\", // indigo-300\n \"rgba(139, 92, 246, 0.8)\", // violet-300\n \"rgba(168, 85, 247, 0.8)\", // purple-300\n \"rgba(217, 70, 239, 0.8)\", // fuchsia-300\n \"rgba(236, 72, 153, 0.8)\", // pink-300\n \"rgba(249, 168, 212, 0.8)\", // rose-300\n \"rgba(161, 161, 170, 0.8)\", // zinc-300\n]\n","import { defaultColors } from \"site/components/InteractiveGraphics/defaultColors\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n scale,\n translate,\n} from \"transformation-matrix\"\nimport {\n getArrowBoundingBox,\n getArrowGeometry,\n getInlineLabelLayout,\n} from \"./arrowHelpers\"\nimport { FONT_SIZE_HEIGHT_RATIO, FONT_SIZE_WIDTH_RATIO } from \"./constants\"\nimport {\n clipInfiniteLineToBounds,\n getViewportBoundsFromMatrix,\n} from \"./infiniteLineHelpers\"\nimport { getProjectedRectGeometry, getRectCorners } from \"./rectGeometry\"\nimport type {\n CenterViewbox,\n GraphicsObject,\n TransformOptions,\n Viewbox,\n} from \"./types\"\n\n/**\n * Computes a transformation matrix based on a provided viewbox\n * Handles both min/max style viewboxes and center/width/height style viewboxes\n */\nexport function computeTransformFromViewbox(\n viewbox: Viewbox | CenterViewbox,\n canvasWidth: number,\n canvasHeight: number,\n options: { padding?: number; yFlip?: boolean } = {},\n): Matrix {\n const padding = options.padding ?? 40\n const yFlip = options.yFlip ?? false\n\n // Convert CenterViewbox to Viewbox if needed\n let bounds: Viewbox\n if (\"center\" in viewbox) {\n const halfWidth = viewbox.width / 2\n const halfHeight = viewbox.height / 2\n bounds = {\n minX: viewbox.center.x - halfWidth,\n maxX: viewbox.center.x + halfWidth,\n minY: viewbox.center.y - halfHeight,\n maxY: viewbox.center.y + halfHeight,\n }\n } else {\n bounds = viewbox\n }\n\n const width = bounds.maxX - bounds.minX || 1\n const height = bounds.maxY - bounds.minY || 1\n\n const scale_factor = Math.min(\n (canvasWidth - 2 * padding) / width,\n (canvasHeight - 2 * padding) / height,\n )\n\n return compose(\n translate(canvasWidth / 2, canvasHeight / 2),\n scale(scale_factor, yFlip ? -scale_factor : scale_factor),\n translate(-(bounds.minX + width / 2), -(bounds.minY + height / 2)),\n )\n}\n\n/**\n * Computes bounds for a graphics object\n */\nexport function getBounds(graphics: GraphicsObject): Viewbox {\n const points = [\n ...(graphics.points || []),\n ...(graphics.lines || []).flatMap((line) => line.points),\n ...(graphics.polygons || []).flatMap((polygon) => polygon.points),\n ...(graphics.rects || []).flatMap((rect) => {\n return getRectCorners(rect)\n }),\n ...(graphics.circles || []).flatMap((circle) => [\n { x: circle.center.x - circle.radius, y: circle.center.y }, // left\n { x: circle.center.x + circle.radius, y: circle.center.y }, // right\n { x: circle.center.x, y: circle.center.y - circle.radius }, // top\n { x: circle.center.x, y: circle.center.y + circle.radius }, // bottom\n ]),\n ...(graphics.arrows || []).flatMap((arrow) => {\n const bounds = getArrowBoundingBox(arrow)\n return [\n { x: bounds.minX, y: bounds.minY },\n { x: bounds.maxX, y: bounds.maxY },\n ]\n }),\n ...(graphics.texts || []).flatMap((text) => {\n const fontSize = text.fontSize ?? 12\n const width = text.text.length * fontSize * FONT_SIZE_WIDTH_RATIO\n const height = fontSize * FONT_SIZE_HEIGHT_RATIO\n const anchor = text.anchorSide ?? \"center\"\n const offsetMap: Record<string, { dx: number; dy: number }> = {\n top_left: { dx: 0, dy: 0 },\n top_center: { dx: -width / 2, dy: 0 },\n top_right: { dx: -width, dy: 0 },\n center_left: { dx: 0, dy: -height / 2 },\n center: { dx: -width / 2, dy: -height / 2 },\n center_right: { dx: -width, dy: -height / 2 },\n bottom_left: { dx: 0, dy: -height },\n bottom_center: { dx: -width / 2, dy: -height },\n bottom_right: { dx: -width, dy: -height },\n }\n const { dx, dy } = offsetMap[anchor]\n const x0 = text.x + dx\n const y0 = text.y + dy\n return [\n { x: x0, y: y0 },\n { x: x0 + width, y: y0 + height },\n ]\n }),\n ]\n\n if (points.length === 0) {\n return { minX: -1, maxX: 1, minY: -1, maxY: 1 }\n }\n\n return points.reduce(\n (bounds, point) => ({\n minX: Math.min(bounds.minX, point.x),\n maxX: Math.max(bounds.maxX, point.x),\n minY: Math.min(bounds.minY, point.y),\n maxY: Math.max(bounds.maxY, point.y),\n }),\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n}\n\n/**\n * Draws a graphics object onto a canvas or context\n * @param graphics - The graphics object to draw\n * @param target - The canvas element or 2D context to draw on\n * @param options - Options for controlling the transform and rendering\n */\nexport function drawGraphicsToCanvas(\n graphics: GraphicsObject,\n target: HTMLCanvasElement | CanvasRenderingContext2D,\n options: TransformOptions = {},\n): void {\n const labelsDisabled = options.disableLabels !== false\n const inlineLabelsHidden = options.hideInlineLabels ?? labelsDisabled\n\n // Get the context\n const ctx =\n target instanceof HTMLCanvasElement ? target.getContext(\"2d\") : target\n\n if (!ctx) {\n throw new Error(\"Could not get 2D context from canvas\")\n }\n\n // Get canvas dimensions\n const canvasWidth =\n target instanceof HTMLCanvasElement ? target.width : target.canvas.width\n\n const canvasHeight =\n target instanceof HTMLCanvasElement ? target.height : target.canvas.height\n\n // Get or compute the transform matrix\n let matrix: Matrix\n\n if (options.transform) {\n matrix = options.transform\n } else if (options.viewbox) {\n matrix = computeTransformFromViewbox(\n options.viewbox,\n canvasWidth,\n canvasHeight,\n {\n padding: options.padding,\n yFlip: options.yFlip,\n },\n )\n } else {\n // Auto-compute bounds and transform if not provided\n const bounds = getBounds(graphics)\n const yFlip = graphics.coordinateSystem === \"cartesian\"\n matrix = computeTransformFromViewbox(bounds, canvasWidth, canvasHeight, {\n padding: options.padding ?? 40,\n yFlip,\n })\n }\n\n // Clear the canvas\n ctx.clearRect(0, 0, canvasWidth, canvasHeight)\n\n // Save the current transform state\n ctx.save()\n\n // Draw the graphics elements\n // Draw rectangles\n if (graphics.rects && graphics.rects.length > 0) {\n graphics.rects.forEach((rect) => {\n const projectedRect = getProjectedRectGeometry(rect, matrix)\n\n ctx.save()\n ctx.translate(projectedRect.center.x, projectedRect.center.y)\n if (Math.abs(projectedRect.angleRadians) > 1e-6) {\n ctx.rotate(projectedRect.angleRadians)\n }\n ctx.beginPath()\n ctx.rect(\n -projectedRect.width / 2,\n -projectedRect.height / 2,\n projectedRect.width,\n projectedRect.height,\n )\n\n if (rect.fill) {\n ctx.fillStyle = rect.fill\n ctx.fill()\n }\n\n if (rect.stroke) {\n ctx.strokeStyle = rect.stroke\n ctx.stroke()\n }\n\n ctx.restore()\n })\n }\n\n // Draw circles\n if (graphics.circles && graphics.circles.length > 0) {\n graphics.circles.forEach((circle) => {\n const projected = applyToPoint(matrix, circle.center)\n const scaledRadius = circle.radius * Math.abs(matrix.a) // Use matrix scale factor\n\n ctx.beginPath()\n ctx.arc(projected.x, projected.y, scaledRadius, 0, 2 * Math.PI)\n\n if (circle.fill) {\n ctx.fillStyle = circle.fill\n ctx.fill()\n }\n\n if (circle.stroke) {\n ctx.strokeStyle = circle.stroke ?? \"transparent\"\n ctx.stroke()\n }\n })\n }\n\n // Draw polygons\n if (graphics.polygons && graphics.polygons.length > 0) {\n graphics.polygons.forEach((polygon) => {\n if (polygon.points.length === 0) return\n\n const projectedPoints = polygon.points.map((point) =>\n applyToPoint(matrix, point),\n )\n\n ctx.beginPath()\n ctx.moveTo(projectedPoints[0].x, projectedPoints[0].y)\n for (let i = 1; i < projectedPoints.length; i++) {\n ctx.lineTo(projectedPoints[i].x, projectedPoints[i].y)\n }\n ctx.closePath()\n\n if (polygon.fill) {\n ctx.fillStyle = polygon.fill\n ctx.fill()\n }\n\n if (polygon.stroke) {\n ctx.strokeStyle = polygon.stroke\n if (polygon.strokeWidth !== undefined) {\n ctx.lineWidth = polygon.strokeWidth * Math.abs(matrix.a)\n }\n ctx.stroke()\n }\n })\n }\n\n if (graphics.arrows && graphics.arrows.length > 0) {\n graphics.arrows.forEach((arrow, arrowIndex) => {\n const geometry = getArrowGeometry(arrow)\n const shaftStart = applyToPoint(matrix, geometry.shaftStart)\n const shaftEnd = applyToPoint(matrix, geometry.shaftEnd)\n\n const color =\n arrow.color || defaultColors[arrowIndex % defaultColors.length]\n const scaleFactor = Math.hypot(matrix.a, matrix.b)\n\n ctx.strokeStyle = color\n ctx.fillStyle = color\n ctx.lineWidth = geometry.shaftWidth * (scaleFactor || 1)\n ctx.lineCap = \"round\"\n ctx.setLineDash([])\n\n ctx.beginPath()\n ctx.moveTo(shaftStart.x, shaftStart.y)\n ctx.lineTo(shaftEnd.x, shaftEnd.y)\n ctx.stroke()\n\n geometry.heads.forEach((head) => {\n const tip = applyToPoint(matrix, head.tip)\n const leftWing = applyToPoint(matrix, head.leftWing)\n const rightWing = applyToPoint(matrix, head.rightWing)\n\n ctx.beginPath()\n ctx.moveTo(tip.x, tip.y)\n ctx.lineTo(leftWing.x, leftWing.y)\n ctx.lineTo(rightWing.x, rightWing.y)\n ctx.closePath()\n ctx.fill()\n })\n\n const fontSize = 12\n const screenStrokeWidth = geometry.shaftWidth * (scaleFactor || 1)\n const alongSeparation = fontSize * 0.6\n const inlineLabelLayout = getInlineLabelLayout(shaftStart, shaftEnd, {\n fontSize,\n strokeWidth: screenStrokeWidth,\n normalPadding: 6,\n alongOffset: arrow.label ? alongSeparation : 0,\n })\n const arrowLabelLayout = getInlineLabelLayout(shaftStart, shaftEnd, {\n fontSize,\n strokeWidth: screenStrokeWidth,\n normalPadding: 12,\n alongOffset: arrow.inlineLabel ? -alongSeparation : 0,\n })\n\n ctx.fillStyle = color\n ctx.font = `${fontSize}px sans-serif`\n\n if (!labelsDisabled && arrow.label) {\n const labelX = arrowLabelLayout.x\n const labelY = arrowLabelLayout.y\n\n ctx.save()\n ctx.textAlign = \"center\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(arrow.label, labelX, labelY)\n ctx.restore()\n }\n\n if (!inlineLabelsHidden && arrow.inlineLabel) {\n ctx.save()\n ctx.translate(inlineLabelLayout.x, inlineLabelLayout.y)\n ctx.rotate(inlineLabelLayout.angleRadians)\n ctx.textAlign = \"center\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(arrow.inlineLabel, 0, 0)\n ctx.restore()\n }\n })\n }\n\n // Draw lines\n if (graphics.lines && graphics.lines.length > 0) {\n graphics.lines\n .map((line, originalIndex) => ({ line, originalIndex }))\n .sort(\n (a, b) =>\n (a.line.zIndex ?? 0) - (b.line.zIndex ?? 0) ||\n a.originalIndex - b.originalIndex,\n )\n .forEach(({ line, originalIndex: lineIndex }) => {\n if (line.points.length === 0) return\n\n ctx.beginPath()\n\n const firstPoint = applyToPoint(matrix, line.points[0])\n ctx.moveTo(firstPoint.x, firstPoint.y)\n\n for (let i = 1; i < line.points.length; i++) {\n const projected = applyToPoint(matrix, line.points[i])\n ctx.lineTo(projected.x, projected.y)\n }\n\n ctx.strokeStyle =\n line.strokeColor || defaultColors[lineIndex % defaultColors.length]\n if (line.strokeWidth) {\n ctx.lineWidth = line.strokeWidth * matrix.a\n } else {\n ctx.lineWidth = 2\n }\n ctx.lineCap = \"round\"\n\n if (line.strokeDash) {\n if (typeof line.strokeDash === \"string\") {\n // Convert string to array of numbers, handling single values properly\n let dashArray: number[]\n\n // If the string contains commas, split and convert to numbers\n if (line.strokeDash.includes(\",\")) {\n dashArray = line.strokeDash\n .split(\",\")\n .map((s) => parseFloat(s.trim()))\n .filter((n) => !Number.isNaN(n))\n } else {\n // Handle single value case\n const value = parseFloat(line.strokeDash.trim())\n dashArray = !Number.isNaN(value) ? [value] : []\n }\n\n // Scale dash values based on transform matrix\n ctx.setLineDash(dashArray)\n } else {\n // Handle array format\n ctx.setLineDash(line.strokeDash.map((n) => n * Math.abs(matrix.a)))\n }\n } else {\n ctx.setLineDash([])\n }\n\n ctx.stroke()\n })\n }\n\n if (graphics.infiniteLines && graphics.infiniteLines.length > 0) {\n const viewportBounds = getViewportBoundsFromMatrix(\n matrix,\n canvasWidth,\n canvasHeight,\n )\n\n graphics.infiniteLines.forEach((line, lineIndex) => {\n const segment = clipInfiniteLineToBounds(line, viewportBounds)\n if (!segment) return\n\n const [start, end] = segment\n const projectedStart = applyToPoint(matrix, start)\n const projectedEnd = applyToPoint(matrix, end)\n\n ctx.beginPath()\n ctx.moveTo(projectedStart.x, projectedStart.y)\n ctx.lineTo(projectedEnd.x, projectedEnd.y)\n\n ctx.strokeStyle =\n line.strokeColor || defaultColors[lineIndex % defaultColors.length]\n ctx.lineWidth = line.strokeWidth\n ? line.strokeWidth * Math.abs(matrix.a)\n : 2\n ctx.lineCap = \"round\"\n\n if (line.strokeDash) {\n if (typeof line.strokeDash === \"string\") {\n let dashArray: number[]\n if (line.strokeDash.includes(\",\")) {\n dashArray = line.strokeDash\n .split(\",\")\n .map((s) => parseFloat(s.trim()))\n .filter((n) => !Number.isNaN(n))\n } else {\n const value = parseFloat(line.strokeDash.trim())\n dashArray = !Number.isNaN(value) ? [value] : []\n }\n ctx.setLineDash(dashArray)\n } else {\n ctx.setLineDash(line.strokeDash.map((n) => n * Math.abs(matrix.a)))\n }\n } else {\n ctx.setLineDash([])\n }\n\n ctx.stroke()\n })\n }\n\n // Draw texts\n if (graphics.texts && graphics.texts.length > 0) {\n graphics.texts.forEach((text) => {\n const projected = applyToPoint(matrix, { x: text.x, y: text.y })\n ctx.fillStyle = text.color || \"black\"\n ctx.font = `${(text.fontSize ?? 12) * Math.abs(matrix.a)}px sans-serif`\n\n const anchor = text.anchorSide ?? \"center\"\n const alignMap: Record<string, CanvasTextAlign> = {\n top_left: \"left\",\n center_left: \"left\",\n bottom_left: \"left\",\n top_center: \"center\",\n center: \"center\",\n bottom_center: \"center\",\n top_right: \"right\",\n center_right: \"right\",\n bottom_right: \"right\",\n }\n const baselineMap: Record<string, CanvasTextBaseline> = {\n top_left: \"top\",\n top_center: \"top\",\n top_right: \"top\",\n center_left: \"middle\",\n center: \"middle\",\n center_right: \"middle\",\n bottom_left: \"bottom\",\n bottom_center: \"bottom\",\n bottom_right: \"bottom\",\n }\n ctx.textAlign = alignMap[anchor]\n ctx.textBaseline = baselineMap[anchor]\n\n ctx.fillText(text.text, projected.x, projected.y)\n })\n }\n\n // Draw points\n if (graphics.points && graphics.points.length > 0) {\n graphics.points.forEach((point, pointIndex) => {\n const projected = applyToPoint(matrix, point)\n\n // Draw point as a small circle\n ctx.beginPath()\n ctx.arc(projected.x, projected.y, 3, 0, 2 * Math.PI)\n ctx.fillStyle =\n point.color || defaultColors[pointIndex % defaultColors.length]\n ctx.fill()\n\n // Draw label if present and labels aren't disabled\n if (point.label && !labelsDisabled) {\n ctx.fillStyle = point.color || \"black\"\n ctx.font = \"12px sans-serif\"\n ctx.fillText(point.label, projected.x + 5, projected.y - 5)\n }\n })\n }\n\n // Restore the original transform\n ctx.restore()\n}\n","import { applyToPoint, type Matrix } from \"transformation-matrix\"\nimport { getArrowGeometry, getInlineLabelLayout } from \"./arrowHelpers\"\nimport { computeTransformFromViewbox, getBounds } from \"./drawGraphicsToCanvas\"\nimport {\n clipInfiniteLineToBounds,\n getViewportBoundsFromMatrix,\n} from \"./infiniteLineHelpers\"\nimport {\n createSoftwareRasterSurface,\n type RasterContext,\n} from \"./softwareRasterSurface\"\nimport { getProjectedRectGeometry } from \"./rectGeometry\"\nimport { strokeAlphabetText } from \"./strokeAlphabetText\"\nimport type {\n GraphicsObject,\n NinePointAnchor,\n Point,\n TransformOptions,\n} from \"./types\"\n\nconst DEFAULT_PNG_SIZE = 640\nconst DEFAULT_BACKGROUND_COLOR = \"white\"\n\ntype LabelType =\n | \"points\"\n | \"lines\"\n | \"infiniteLines\"\n | \"rects\"\n | \"polygons\"\n | \"arrows\"\n\nexport type PngRenderOptions = TransformOptions & {\n includeTextLabels?: boolean | LabelType[]\n backgroundColor?: string | null\n pngWidth?: number\n pngHeight?: number\n}\n\nconst hasVisiblePaint = (value?: string) => {\n return Boolean(value && value !== \"none\" && value !== \"transparent\")\n}\n\nconst shouldRenderLabel = (\n includeTextLabels: PngRenderOptions[\"includeTextLabels\"],\n disableLabels: boolean | undefined,\n type: LabelType,\n) => {\n if (disableLabels) return false\n if (typeof includeTextLabels === \"boolean\") return includeTextLabels\n if (Array.isArray(includeTextLabels)) return includeTextLabels.includes(type)\n return false\n}\n\nconst parseStrokeDash = (\n strokeDash: string | number[],\n strokeScale: number,\n): number[] => {\n if (typeof strokeDash === \"string\") {\n if (strokeDash.includes(\",\")) {\n return strokeDash\n .split(\",\")\n .map((part) => Number.parseFloat(part.trim()))\n .filter((value) => Number.isFinite(value) && value > 0)\n }\n\n const singleValue = Number.parseFloat(strokeDash.trim())\n return Number.isFinite(singleValue) && singleValue > 0 ? [singleValue] : []\n }\n\n return strokeDash\n .map((segment) => segment * strokeScale)\n .filter((value) => Number.isFinite(value) && value > 0)\n}\n\nconst normalizeDashPattern = (dashPattern: number[]) => {\n if (dashPattern.length === 0) return dashPattern\n return dashPattern.length % 2 === 0\n ? dashPattern\n : [...dashPattern, ...dashPattern]\n}\n\nconst strokePolyline = (\n ctx: RasterContext,\n points: Point[],\n dashPattern: number[] | undefined,\n) => {\n if (points.length < 2) return\n\n if (!dashPattern || dashPattern.length === 0) {\n ctx.beginPath()\n ctx.moveTo(points[0].x, points[0].y)\n for (let i = 1; i < points.length; i++) {\n ctx.lineTo(points[i].x, points[i].y)\n }\n ctx.stroke()\n return\n }\n\n const normalizedPattern = normalizeDashPattern(dashPattern)\n let patternIndex = 0\n let patternOffset = 0\n let isDrawing = true\n\n ctx.beginPath()\n\n for (let i = 1; i < points.length; i++) {\n const start = points[i - 1]\n const end = points[i]\n const dx = end.x - start.x\n const dy = end.y - start.y\n const segmentLength = Math.hypot(dx, dy)\n\n if (segmentLength === 0) continue\n\n let distanceAlongSegment = 0\n while (distanceAlongSegment < segmentLength) {\n const remainingPatternLength =\n normalizedPattern[patternIndex] - patternOffset\n const stepLength = Math.min(\n remainingPatternLength,\n segmentLength - distanceAlongSegment,\n )\n\n const t1 = distanceAlongSegment / segmentLength\n const t2 = (distanceAlongSegment + stepLength) / segmentLength\n const x1 = start.x + dx * t1\n const y1 = start.y + dy * t1\n const x2 = start.x + dx * t2\n const y2 = start.y + dy * t2\n\n if (isDrawing) {\n ctx.moveTo(x1, y1)\n ctx.lineTo(x2, y2)\n }\n\n distanceAlongSegment += stepLength\n patternOffset += stepLength\n\n if (patternOffset >= normalizedPattern[patternIndex] - 1e-6) {\n patternOffset = 0\n patternIndex = (patternIndex + 1) % normalizedPattern.length\n isDrawing = !isDrawing\n }\n }\n }\n\n ctx.stroke()\n}\n\nconst renderText = (\n ctx: RasterContext,\n {\n text,\n x,\n y,\n fontSize,\n color,\n anchorAlignment = \"top_left\",\n rotationRadians,\n }: {\n text: string\n x: number\n y: number\n fontSize: number\n color?: string\n anchorAlignment?: NinePointAnchor\n rotationRadians?: number\n },\n) => {\n strokeAlphabetText({\n ctx,\n text,\n fontSize,\n startX: x,\n startY: y,\n color: color ?? \"black\",\n anchorAlignment: anchorAlignment ?? \"top_left\",\n rotationRadians,\n })\n}\n\nexport async function getPngBufferFromGraphicsObject(\n graphics: GraphicsObject,\n {\n includeTextLabels = false,\n hideInlineLabels = false,\n backgroundColor = DEFAULT_BACKGROUND_COLOR,\n pngWidth = DEFAULT_PNG_SIZE,\n pngHeight = DEFAULT_PNG_SIZE,\n ...transformOptions\n }: PngRenderOptions = {},\n): Promise<Uint8Array> {\n const surface = createSoftwareRasterSurface(pngWidth, pngHeight)\n const { ctx } = surface\n\n ctx.clearRect(0, 0, pngWidth, pngHeight)\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor\n ctx.fillRect(0, 0, pngWidth, pngHeight)\n }\n\n const yFlip =\n transformOptions.yFlip ?? graphics.coordinateSystem === \"cartesian\"\n const matrix: Matrix =\n transformOptions.transform ??\n computeTransformFromViewbox(\n transformOptions.viewbox ?? getBounds(graphics),\n pngWidth,\n pngHeight,\n {\n padding: transformOptions.padding ?? 40,\n yFlip,\n },\n )\n const strokeScale = Math.abs(matrix.a)\n\n for (const line of (graphics.lines || [])\n .map((value, originalIndex) => ({ value, originalIndex }))\n .sort(\n (a, b) =>\n (a.value.zIndex ?? 0) - (b.value.zIndex ?? 0) ||\n a.originalIndex - b.originalIndex,\n )\n .map(({ value }) => value)) {\n const projectedPoints = line.points.map((point) =>\n applyToPoint(matrix, point),\n )\n const dashPattern = line.strokeDash\n ? parseStrokeDash(line.strokeDash, strokeScale)\n : undefined\n\n ctx.strokeStyle = line.strokeColor || \"black\"\n ctx.lineWidth =\n line.strokeWidth === undefined\n ? 1\n : Math.max(line.strokeWidth * strokeScale, 1)\n strokePolyline(ctx, projectedPoints, dashPattern)\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"lines\",\n ) &&\n line.label &&\n projectedPoints.length > 0\n ) {\n renderText(ctx, {\n text: line.label,\n x: projectedPoints[0].x + 5,\n y: projectedPoints[0].y - 5,\n fontSize: 12,\n color: line.strokeColor || \"black\",\n })\n }\n }\n\n if (graphics.infiniteLines) {\n const viewportBounds = getViewportBoundsFromMatrix(\n matrix,\n pngWidth,\n pngHeight,\n )\n for (const line of graphics.infiniteLines) {\n const segment = clipInfiniteLineToBounds(line, viewportBounds)\n if (!segment) continue\n\n const projectedPoints = segment.map((point) =>\n applyToPoint(matrix, point),\n )\n const dashPattern = line.strokeDash\n ? parseStrokeDash(line.strokeDash, strokeScale)\n : undefined\n\n ctx.strokeStyle = line.strokeColor || \"black\"\n ctx.lineWidth =\n line.strokeWidth === undefined\n ? 1\n : Math.max(line.strokeWidth * strokeScale, 1)\n strokePolyline(ctx, projectedPoints, dashPattern)\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"infiniteLines\",\n ) &&\n line.label\n ) {\n renderText(ctx, {\n text: line.label,\n x: (projectedPoints[0].x + projectedPoints[1].x) / 2 + 5,\n y: (projectedPoints[0].y + projectedPoints[1].y) / 2 - 5,\n fontSize: 12,\n color: line.strokeColor || \"black\",\n })\n }\n }\n }\n\n for (const rect of graphics.rects || []) {\n const projectedRect = getProjectedRectGeometry(rect, matrix)\n const x = projectedRect.center.x - projectedRect.width / 2\n const y = projectedRect.center.y - projectedRect.height / 2\n\n ctx.save()\n ctx.translate(projectedRect.center.x, projectedRect.center.y)\n if (Math.abs(projectedRect.angleRadians) > 1e-6) {\n ctx.rotate(projectedRect.angleRadians)\n }\n\n if (hasVisiblePaint(rect.fill)) {\n ctx.beginPath()\n ctx.rect(\n -projectedRect.width / 2,\n -projectedRect.height / 2,\n projectedRect.width,\n projectedRect.height,\n )\n ctx.fillStyle = rect.fill!\n ctx.fill()\n }\n\n if (hasVisiblePaint(rect.stroke)) {\n ctx.beginPath()\n ctx.rect(\n -projectedRect.width / 2,\n -projectedRect.height / 2,\n projectedRect.width,\n projectedRect.height,\n )\n ctx.strokeStyle = rect.stroke!\n ctx.lineWidth = 1\n ctx.stroke()\n }\n\n ctx.restore()\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"rects\",\n ) &&\n rect.label\n ) {\n renderText(ctx, {\n text: rect.label,\n x: projectedRect.bounds.minX + 5,\n y: projectedRect.bounds.minY,\n fontSize: ((projectedRect.width + projectedRect.height) / 2) * 0.06,\n color: rect.stroke || \"black\",\n })\n }\n }\n\n for (const polygon of graphics.polygons || []) {\n if (polygon.points.length === 0) continue\n\n const projectedPoints = polygon.points.map((point) =>\n applyToPoint(matrix, point),\n )\n const minX = Math.min(...projectedPoints.map((point) => point.x))\n const minY = Math.min(...projectedPoints.map((point) => point.y))\n\n ctx.beginPath()\n ctx.moveTo(projectedPoints[0].x, projectedPoints[0].y)\n for (let i = 1; i < projectedPoints.length; i++) {\n ctx.lineTo(projectedPoints[i].x, projectedPoints[i].y)\n }\n ctx.closePath()\n\n if (hasVisiblePaint(polygon.fill)) {\n ctx.fillStyle = polygon.fill!\n ctx.fill()\n }\n\n if (hasVisiblePaint(polygon.stroke)) {\n ctx.strokeStyle = polygon.stroke!\n ctx.lineWidth =\n polygon.strokeWidth === undefined\n ? 1\n : Math.max(polygon.strokeWidth * strokeScale, 1)\n ctx.stroke()\n }\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"polygons\",\n ) &&\n polygon.label\n ) {\n renderText(ctx, {\n text: polygon.label,\n x: minX + 5,\n y: minY,\n fontSize: 12,\n color: polygon.stroke || \"black\",\n })\n }\n }\n\n for (const circle of graphics.circles || []) {\n const projectedCenter = applyToPoint(matrix, circle.center)\n const scaledRadius = circle.radius * strokeScale\n\n ctx.beginPath()\n ctx.arc(projectedCenter.x, projectedCenter.y, scaledRadius, 0, Math.PI * 2)\n\n if (hasVisiblePaint(circle.fill)) {\n ctx.fillStyle = circle.fill!\n ctx.fill()\n }\n\n if (hasVisiblePaint(circle.stroke)) {\n ctx.strokeStyle = circle.stroke!\n ctx.lineWidth = 1\n ctx.stroke()\n }\n }\n\n for (const arrow of graphics.arrows || []) {\n const geometry = getArrowGeometry(arrow)\n const shaftStart = applyToPoint(matrix, geometry.shaftStart)\n const shaftEnd = applyToPoint(matrix, geometry.shaftEnd)\n const fontSize = 12\n const inlineLabelLayout = getInlineLabelLayout(shaftStart, shaftEnd, {\n fontSize,\n strokeWidth: geometry.shaftWidth,\n normalPadding: 6,\n alongOffset: arrow.label ? fontSize * 0.6 : 0,\n })\n const arrowLabelLayout = getInlineLabelLayout(shaftStart, shaftEnd, {\n fontSize,\n strokeWidth: geometry.shaftWidth,\n normalPadding: 12,\n alongOffset: arrow.inlineLabel ? -(fontSize * 0.6) : 0,\n })\n const color = arrow.color || \"black\"\n\n if (shaftStart.x !== shaftEnd.x || shaftStart.y !== shaftEnd.y) {\n ctx.strokeStyle = color\n ctx.lineWidth = geometry.shaftWidth\n strokePolyline(ctx, [shaftStart, shaftEnd], undefined)\n }\n\n ctx.fillStyle = color\n for (const head of geometry.heads) {\n const tip = applyToPoint(matrix, head.tip)\n const leftWing = applyToPoint(matrix, head.leftWing)\n const rightWing = applyToPoint(matrix, head.rightWing)\n\n ctx.beginPath()\n ctx.moveTo(tip.x, tip.y)\n ctx.lineTo(leftWing.x, leftWing.y)\n ctx.lineTo(rightWing.x, rightWing.y)\n ctx.closePath()\n ctx.fill()\n }\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"arrows\",\n ) &&\n arrow.label\n ) {\n renderText(ctx, {\n text: arrow.label,\n x: arrowLabelLayout.x,\n y: arrowLabelLayout.y,\n fontSize,\n color,\n anchorAlignment: \"center\",\n })\n }\n\n if (\n !transformOptions.disableLabels &&\n !hideInlineLabels &&\n arrow.inlineLabel\n ) {\n renderText(ctx, {\n text: arrow.inlineLabel,\n x: inlineLabelLayout.x,\n y: inlineLabelLayout.y,\n fontSize,\n color,\n anchorAlignment: \"center\",\n rotationRadians: inlineLabelLayout.angleRadians,\n })\n }\n }\n\n for (const text of graphics.texts || []) {\n const projected = applyToPoint(matrix, { x: text.x, y: text.y })\n renderText(ctx, {\n text: text.text,\n x: projected.x,\n y: projected.y,\n fontSize: (text.fontSize ?? 12) * strokeScale,\n color: text.color || \"black\",\n anchorAlignment: text.anchorSide ?? \"center\",\n })\n }\n\n for (const point of graphics.points || []) {\n const projected = applyToPoint(matrix, point)\n\n ctx.beginPath()\n ctx.arc(projected.x, projected.y, 3, 0, Math.PI * 2)\n ctx.fillStyle = point.color || \"black\"\n ctx.fill()\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"points\",\n ) &&\n point.label\n ) {\n renderText(ctx, {\n text: point.label,\n x: projected.x + 5,\n y: projected.y - 5,\n fontSize: 12,\n color: point.color || \"black\",\n })\n }\n }\n\n return surface.exportPng()\n}\n","import { stringify } from \"svgson\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n identity,\n scale,\n transform,\n translate,\n} from \"transformation-matrix\"\nimport {\n getArrowBoundingBox,\n getArrowGeometry,\n getInlineLabelLayout,\n} from \"./arrowHelpers\"\nimport { FONT_SIZE_HEIGHT_RATIO, FONT_SIZE_WIDTH_RATIO } from \"./constants\"\nimport { clipInfiniteLineToBounds } from \"./infiniteLineHelpers\"\nimport { getProjectedRectGeometry, getRectCorners } from \"./rectGeometry\"\nimport type { GraphicsObject, Point } from \"./types\"\n\nconst DEFAULT_SVG_SIZE = 640\nconst PADDING = 40\n\ninterface Bounds {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\nfunction getBounds(graphics: GraphicsObject): Bounds {\n const points: Point[] = [\n ...(graphics.points || []),\n ...(graphics.lines || []).flatMap((line) => line.points),\n ...(graphics.polygons || []).flatMap((polygon) => polygon.points),\n ...(graphics.rects || []).flatMap((rect) => {\n return getRectCorners(rect)\n }),\n ...(graphics.circles || []).flatMap((circle) => [\n { x: circle.center.x - circle.radius, y: circle.center.y }, // left\n { x: circle.center.x + circle.radius, y: circle.center.y }, // right\n { x: circle.center.x, y: circle.center.y - circle.radius }, // top\n { x: circle.center.x, y: circle.center.y + circle.radius }, // bottom\n ]),\n ...(graphics.arrows || []).flatMap((arrow) => {\n const bounds = getArrowBoundingBox(arrow)\n return [\n { x: bounds.minX, y: bounds.minY },\n { x: bounds.maxX, y: bounds.maxY },\n ]\n }),\n ...(graphics.texts || []).flatMap((t) => {\n const fontSize = t.fontSize ?? 12\n const width = t.text.length * fontSize * FONT_SIZE_WIDTH_RATIO\n const height = fontSize * FONT_SIZE_HEIGHT_RATIO\n const anchor = t.anchorSide ?? \"center\"\n const offsetMap: Record<string, { dx: number; dy: number }> = {\n top_left: { dx: 0, dy: 0 },\n top_center: { dx: -width / 2, dy: 0 },\n top_right: { dx: -width, dy: 0 },\n center_left: { dx: 0, dy: -height / 2 },\n center: { dx: -width / 2, dy: -height / 2 },\n center_right: { dx: -width, dy: -height / 2 },\n bottom_left: { dx: 0, dy: -height },\n bottom_center: { dx: -width / 2, dy: -height },\n bottom_right: { dx: -width, dy: -height },\n }\n const { dx, dy } = offsetMap[anchor]\n const x0 = t.x + dx\n const y0 = t.y + dy\n return [\n { x: x0, y: y0 },\n { x: x0 + width, y: y0 + height },\n ]\n }),\n ]\n\n if (points.length === 0) {\n return { minX: -1, maxX: 1, minY: -1, maxY: 1 }\n }\n\n return points.reduce(\n (bounds, point) => ({\n minX: Math.min(bounds.minX, point.x),\n maxX: Math.max(bounds.maxX, point.x),\n minY: Math.min(bounds.minY, point.y),\n maxY: Math.max(bounds.maxY, point.y),\n }),\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n}\n\nfunction getProjectionMatrix(\n bounds: Bounds,\n coordinateSystem: GraphicsObject[\"coordinateSystem\"],\n svgWidth: number,\n svgHeight: number,\n) {\n const width = bounds.maxX - bounds.minX || 1\n const height = bounds.maxY - bounds.minY || 1\n\n const scale_factor = Math.min(\n (svgWidth - 2 * PADDING) / width,\n (svgHeight - 2 * PADDING) / height,\n )\n\n const yFlip = coordinateSystem === \"screen\" ? 1 : -1\n\n return compose(\n translate(svgWidth / 2, svgHeight / 2),\n scale(scale_factor, yFlip * scale_factor),\n translate(-(bounds.minX + width / 2), -(bounds.minY + height / 2)),\n )\n}\n\nfunction projectPoint(point: Point, matrix: Matrix) {\n const projected = applyToPoint(matrix, { x: point.x, y: point.y })\n return { ...point, ...projected }\n}\n\nexport function getSvgFromGraphicsObject(\n graphics: GraphicsObject,\n {\n includeTextLabels = false,\n hideInlineLabels = false,\n backgroundColor = \"white\",\n svgWidth = DEFAULT_SVG_SIZE,\n svgHeight = DEFAULT_SVG_SIZE,\n }: {\n includeTextLabels?:\n | boolean\n | Array<\n \"points\" | \"lines\" | \"infiniteLines\" | \"rects\" | \"polygons\" | \"arrows\"\n >\n backgroundColor?: string | null\n hideInlineLabels?: boolean\n svgWidth?: number\n svgHeight?: number\n } = {},\n): string {\n const bounds = getBounds(graphics)\n const matrix = getProjectionMatrix(\n bounds,\n graphics.coordinateSystem,\n svgWidth,\n svgHeight,\n )\n const strokeScale = Math.abs(matrix.a)\n\n const shouldRenderLabel = (\n type:\n | \"points\"\n | \"lines\"\n | \"infiniteLines\"\n | \"rects\"\n | \"polygons\"\n | \"arrows\",\n ): boolean => {\n if (typeof includeTextLabels === \"boolean\") {\n return includeTextLabels\n }\n if (Array.isArray(includeTextLabels)) {\n return includeTextLabels.includes(type)\n }\n return false\n }\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n viewBox: `0 0 ${svgWidth} ${svgHeight}`,\n xmlns: \"http://www.w3.org/2000/svg\",\n },\n children: [\n // Background rectangle (optional)\n ...(backgroundColor\n ? [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n width: \"100%\",\n height: \"100%\",\n fill: backgroundColor,\n },\n },\n ]\n : []),\n // Lines\n ...(graphics.lines || [])\n .map((line, originalIndex) => ({ line, originalIndex }))\n .sort(\n (a, b) =>\n (a.line.zIndex ?? 0) - (b.line.zIndex ?? 0) ||\n a.originalIndex - b.originalIndex,\n )\n .map(({ line }) => {\n const projectedPoints = line.points.map((p) =>\n projectPoint(p, matrix),\n )\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"polyline\",\n type: \"element\",\n attributes: {\n \"data-points\": line.points\n .map((p) => `${p.x},${p.y}`)\n .join(\" \"),\n \"data-type\": \"line\",\n \"data-label\": line.label || \"\",\n points: projectedPoints.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: line.strokeColor || \"black\",\n \"stroke-width\": !line.strokeWidth\n ? \"1px\"\n : typeof line.strokeWidth === \"string\"\n ? line.strokeWidth\n : (strokeScale * line.strokeWidth).toString(),\n ...(line.strokeDash && {\n \"stroke-dasharray\": Array.isArray(line.strokeDash)\n ? line.strokeDash.join(\" \")\n : line.strokeDash,\n }),\n },\n },\n ...(shouldRenderLabel(\"lines\") &&\n line.label &&\n projectedPoints.length > 0\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (projectedPoints[0].x + 5).toString(),\n y: (projectedPoints[0].y - 5).toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n fill: line.strokeColor || \"black\",\n },\n children: [{ type: \"text\", value: line.label }],\n },\n ]\n : []),\n ],\n }\n }),\n ...(graphics.infiniteLines || []).flatMap((line) => {\n const segment = clipInfiniteLineToBounds(line, bounds)\n if (!segment) return []\n\n const [start, end] = segment\n const projectedStart = projectPoint(start, matrix)\n const projectedEnd = projectPoint(end, matrix)\n\n return [\n {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n \"data-type\": \"infinite-line\",\n \"data-label\": line.label || \"\",\n \"data-origin\": `${line.origin.x},${line.origin.y}`,\n \"data-direction\": `${line.directionVector.x},${line.directionVector.y}`,\n x1: projectedStart.x.toString(),\n y1: projectedStart.y.toString(),\n x2: projectedEnd.x.toString(),\n y2: projectedEnd.y.toString(),\n stroke: line.strokeColor || \"black\",\n \"stroke-width\": !line.strokeWidth\n ? \"1px\"\n : typeof line.strokeWidth === \"string\"\n ? line.strokeWidth\n : (strokeScale * line.strokeWidth).toString(),\n ...(line.strokeDash && {\n \"stroke-dasharray\": Array.isArray(line.strokeDash)\n ? line.strokeDash.join(\" \")\n : line.strokeDash,\n }),\n },\n },\n ...(shouldRenderLabel(\"infiniteLines\") && line.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (\n (projectedStart.x + projectedEnd.x) / 2 +\n 5\n ).toString(),\n y: (\n (projectedStart.y + projectedEnd.y) / 2 -\n 5\n ).toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n fill: line.strokeColor || \"black\",\n },\n children: [{ type: \"text\", value: line.label }],\n },\n ]\n : []),\n ],\n },\n ]\n }),\n // Rectangles\n ...(graphics.rects || []).map((rect) => {\n const projectedRect = getProjectedRectGeometry(rect, matrix)\n const rectX = projectedRect.center.x - projectedRect.width / 2\n const rectY = projectedRect.center.y - projectedRect.height / 2\n const labelX = projectedRect.bounds.minX + 5\n const labelY = projectedRect.bounds.minY\n const hasRotation = Math.abs(projectedRect.angleDegrees) > 1e-6\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n \"data-type\": \"rect\",\n \"data-label\": rect.label || \"\",\n \"data-x\": rect.center.x.toString(),\n \"data-y\": rect.center.y.toString(),\n ...(rect.ccwRotationDegrees !== undefined && {\n \"data-ccw-rotation-degrees\":\n rect.ccwRotationDegrees.toString(),\n }),\n x: rectX.toString(),\n y: rectY.toString(),\n width: projectedRect.width.toString(),\n height: projectedRect.height.toString(),\n fill: rect.fill || \"none\",\n stroke: rect.stroke || \"black\",\n \"stroke-width\": Math.abs(1 / matrix.a).toString(), // Consider scaling stroke width like lines if needed\n ...(hasRotation && {\n transform: `rotate(${projectedRect.angleDegrees} ${projectedRect.center.x} ${projectedRect.center.y})`,\n }),\n },\n },\n ...(shouldRenderLabel(\"rects\") && rect.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: labelX.toString(),\n y: labelY.toString(),\n \"font-family\": \"sans-serif\",\n \"dominant-baseline\": \"text-before-edge\",\n \"font-size\": (\n ((projectedRect.width + projectedRect.height) / 2) *\n 0.06\n ).toString(),\n fill: rect.stroke || \"black\", // Default to stroke color for label\n },\n children: [{ type: \"text\", value: rect.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Polygons\n ...(graphics.polygons || []).map((polygon) => {\n const projectedPoints = polygon.points.map((point) =>\n projectPoint(point, matrix),\n )\n const xs = projectedPoints.map((p) => p.x)\n const ys = projectedPoints.map((p) => p.y)\n const minX = xs.length > 0 ? Math.min(...xs) : 0\n const minY = ys.length > 0 ? Math.min(...ys) : 0\n const polygonStrokeWidth =\n polygon.strokeWidth === undefined\n ? Math.abs(1 / matrix.a)\n : strokeScale * polygon.strokeWidth\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"polygon\",\n type: \"element\",\n attributes: {\n \"data-type\": \"polygon\",\n \"data-label\": polygon.label || \"\",\n \"data-points\": polygon.points\n .map((p) => `${p.x},${p.y}`)\n .join(\" \"),\n points: projectedPoints.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: polygon.fill || \"none\",\n stroke: polygon.stroke || \"black\",\n \"stroke-width\": polygonStrokeWidth.toString(),\n },\n },\n ...(shouldRenderLabel(\"polygons\") && polygon.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (minX + 5).toString(),\n y: minY.toString(),\n \"font-family\": \"sans-serif\",\n \"dominant-baseline\": \"text-before-edge\",\n \"font-size\": \"12\",\n fill: polygon.stroke || \"black\",\n },\n children: [{ type: \"text\", value: polygon.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Circles\n ...(graphics.circles || []).map((circle) => {\n const projected = projectPoint(circle.center, matrix)\n const scaledRadius = circle.radius * Math.abs(matrix.a)\n return {\n name: \"circle\",\n type: \"element\",\n attributes: {\n \"data-type\": \"circle\",\n \"data-label\": \"\",\n \"data-x\": circle.center.x.toString(),\n \"data-y\": circle.center.y.toString(),\n cx: projected.x.toString(),\n cy: projected.y.toString(),\n r: scaledRadius.toString(),\n fill: circle.fill || \"none\",\n stroke: circle.stroke || \"black\",\n \"stroke-width\": Math.abs(1 / matrix.a).toString(),\n },\n }\n }),\n ...(graphics.arrows || []).map((arrow) => {\n const geometry = getArrowGeometry(arrow)\n const projectedShaftStart = projectPoint(geometry.shaftStart, matrix)\n const projectedShaftEnd = projectPoint(geometry.shaftEnd, matrix)\n const fontSize = 12\n const strokeWidth = geometry.shaftWidth\n const alongSeparation = fontSize * 0.6\n const inlineLabelLayout = getInlineLabelLayout(\n projectedShaftStart,\n projectedShaftEnd,\n {\n fontSize,\n strokeWidth,\n normalPadding: 6,\n alongOffset: arrow.label ? alongSeparation : 0,\n },\n )\n const arrowLabelLayout = getInlineLabelLayout(\n projectedShaftStart,\n projectedShaftEnd,\n {\n fontSize,\n strokeWidth,\n normalPadding: 12,\n alongOffset: arrow.inlineLabel ? -alongSeparation : 0,\n },\n )\n\n const color = arrow.color || \"black\"\n\n const headChildren = geometry.heads.map((head) => {\n const projectedTip = projectPoint(head.tip, matrix)\n const projectedLeftWing = projectPoint(head.leftWing, matrix)\n const projectedRightWing = projectPoint(head.rightWing, matrix)\n\n return {\n name: \"polygon\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow-head\",\n points: [\n `${projectedTip.x},${projectedTip.y}`,\n `${projectedLeftWing.x},${projectedLeftWing.y}`,\n `${projectedRightWing.x},${projectedRightWing.y}`,\n ].join(\" \"),\n fill: color,\n },\n }\n })\n\n const children = [\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow-shaft\",\n x1: projectedShaftStart.x.toString(),\n y1: projectedShaftStart.y.toString(),\n x2: projectedShaftEnd.x.toString(),\n y2: projectedShaftEnd.y.toString(),\n stroke: color,\n \"stroke-width\": geometry.shaftWidth.toString(),\n \"stroke-linecap\": \"round\",\n },\n },\n ...headChildren,\n ...(shouldRenderLabel(\"arrows\") && arrow.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow-label\",\n x: arrowLabelLayout.x.toString(),\n y: arrowLabelLayout.y.toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": fontSize.toString(),\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n fill: color,\n },\n children: [{ type: \"text\", value: arrow.label }],\n },\n ]\n : []),\n ...(!hideInlineLabels && arrow.inlineLabel\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow-inline-label\",\n x: inlineLabelLayout.x.toString(),\n y: inlineLabelLayout.y.toString(),\n transform: `rotate(${inlineLabelLayout.angleDegrees} ${inlineLabelLayout.x} ${inlineLabelLayout.y})`,\n \"font-family\": \"sans-serif\",\n \"font-size\": fontSize.toString(),\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n fill: color,\n },\n children: [{ type: \"text\", value: arrow.inlineLabel }],\n },\n ]\n : []),\n ]\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow\",\n \"data-start\": `${arrow.start.x},${arrow.start.y}`,\n \"data-end\": `${arrow.end.x},${arrow.end.y}`,\n \"data-double-sided\": arrow.doubleSided ? \"true\" : \"false\",\n ...(arrow.label ? { \"data-label\": arrow.label } : {}),\n ...(arrow.inlineLabel\n ? { \"data-inline-label\": arrow.inlineLabel }\n : {}),\n },\n children,\n }\n }),\n // Texts\n ...(graphics.texts || []).map((txt) => {\n const projected = projectPoint({ x: txt.x, y: txt.y }, matrix)\n const anchor = txt.anchorSide ?? \"center\"\n const alignMap: Record<string, string> = {\n top_left: \"start\",\n center_left: \"start\",\n bottom_left: \"start\",\n top_center: \"middle\",\n center: \"middle\",\n bottom_center: \"middle\",\n top_right: \"end\",\n center_right: \"end\",\n bottom_right: \"end\",\n }\n const baselineMap: Record<string, string> = {\n top_left: \"text-before-edge\",\n top_center: \"text-before-edge\",\n top_right: \"text-before-edge\",\n center_left: \"central\",\n center: \"central\",\n center_right: \"central\",\n bottom_left: \"text-after-edge\",\n bottom_center: \"text-after-edge\",\n bottom_right: \"text-after-edge\",\n }\n return {\n name: \"text\",\n type: \"element\",\n attributes: {\n \"data-type\": \"text\",\n \"data-label\": txt.text,\n \"data-x\": txt.x.toString(),\n \"data-y\": txt.y.toString(),\n x: projected.x.toString(),\n y: projected.y.toString(),\n fill: txt.color || \"black\",\n \"font-size\": ((txt.fontSize ?? 12) * Math.abs(matrix.a)).toString(),\n \"font-family\": \"sans-serif\",\n \"text-anchor\": alignMap[anchor],\n \"dominant-baseline\": baselineMap[anchor],\n },\n children: [{ type: \"text\", value: txt.text }],\n }\n }),\n // Points\n ...(graphics.points || []).map((point) => {\n const projected = projectPoint(point, matrix)\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n \"data-type\": \"point\",\n \"data-label\": point.label || \"\",\n \"data-x\": point.x.toString(),\n \"data-y\": point.y.toString(),\n cx: projected.x.toString(),\n cy: projected.y.toString(),\n r: \"3\",\n fill: point.color || \"black\",\n },\n },\n ...(shouldRenderLabel(\"points\") && point.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (projected.x + 5).toString(),\n y: (projected.y - 5).toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n },\n children: [{ type: \"text\", value: point.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Crosshair lines and coordinates (initially hidden)\n {\n name: \"g\",\n type: \"element\",\n attributes: {\n id: \"crosshair\",\n style: \"display: none\",\n },\n children: [\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n id: \"crosshair-h\",\n y1: \"0\",\n y2: svgHeight.toString(),\n stroke: \"#666\",\n \"stroke-width\": \"0.5\",\n },\n },\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n id: \"crosshair-v\",\n x1: \"0\",\n x2: svgWidth.toString(),\n stroke: \"#666\",\n \"stroke-width\": \"0.5\",\n },\n },\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n id: \"coordinates\",\n \"font-family\": \"monospace\",\n \"font-size\": \"12\",\n fill: \"#666\",\n },\n children: [{ type: \"text\", value: \"\" }],\n },\n ],\n },\n // Mouse tracking script\n {\n name: \"script\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n document.currentScript.parentElement.addEventListener('mousemove', (e) => {\n const svg = e.currentTarget;\n const rect = svg.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n const crosshair = svg.getElementById('crosshair');\n const h = svg.getElementById('crosshair-h');\n const v = svg.getElementById('crosshair-v');\n const coords = svg.getElementById('coordinates');\n \n crosshair.style.display = 'block';\n h.setAttribute('x1', '0');\n h.setAttribute('x2', '${svgWidth}');\n h.setAttribute('y1', y);\n h.setAttribute('y2', y);\n v.setAttribute('x1', x);\n v.setAttribute('x2', x);\n v.setAttribute('y1', '0');\n v.setAttribute('y2', '${svgHeight}');\n\n // Calculate real coordinates using inverse transformation\n const matrix = ${JSON.stringify(matrix)};\n // Manually invert and apply the affine transform\n // Since we only use translate and scale, we can directly compute:\n // x' = (x - tx) / sx\n // y' = (y - ty) / sy\n const sx = matrix.a;\n const sy = matrix.d;\n const tx = matrix.e; \n const ty = matrix.f;\n const realPoint = {\n x: (x - tx) / sx,\n y: (y - ty) / sy // Flip y back since we used negative scale\n }\n \n coords.textContent = \\`(\\${realPoint.x.toFixed(2)}, \\${realPoint.y.toFixed(2)})\\`;\n coords.setAttribute('x', (x + 5).toString());\n coords.setAttribute('y', (y - 5).toString());\n });\n document.currentScript.parentElement.addEventListener('mouseleave', () => {\n document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';\n });\n `,\n },\n ],\n },\n ],\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: TODO\n return stringify(svgObject as any)\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { drawGraphicsToCanvas } from \"graphics-debug\"\nimport { useEffect, useRef } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport { useGlobalStore } from \"../global-store\"\n\ninterface Props {\n transform?: Matrix\n debugGraphics?: GraphicsObject | null\n children?: any\n}\n\nexport const DebugGraphicsOverlay = ({\n children,\n transform,\n debugGraphics,\n}: Props) => {\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const [containerRef, { width, height }] = useMeasure<HTMLDivElement>()\n const is_showing_autorouting = useGlobalStore((s) => s.is_showing_autorouting)\n\n useEffect(() => {\n if (!is_showing_autorouting) return\n if (canvasRef.current && debugGraphics && width && height) {\n canvasRef.current.width = width\n canvasRef.current.height = height\n drawGraphicsToCanvas(debugGraphics, canvasRef.current, {\n transform,\n disableLabels: true,\n })\n }\n }, [debugGraphics, transform, width, height, is_showing_autorouting])\n\n if (!is_showing_autorouting) return children\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n >\n {children}\n <canvas\n ref={canvasRef}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n opacity: 0.5,\n zIndex: 100,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n }}\n />\n </div>\n )\n}\n","import { zIndexMap } from \"lib/util/z-index-map\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { applyToPoint, identity, inverse } from \"transformation-matrix\"\nimport type { Primitive } from \"lib/types\"\nimport type { NinePointAnchor } from \"circuit-json\"\nimport {\n getPrimitiveBoundingBox,\n mergeBoundingBoxes,\n} from \"lib/util/get-primitive-bounding-box\"\nimport type { BoundingBox } from \"lib/util/get-primitive-bounding-box\"\nimport { useDiagonalLabel } from \"hooks/useDiagonalLabel\"\nimport { getPrimitiveSnapPoints } from \"lib/util/get-primitive-snap-points\"\nimport { useGlobalStore } from \"../global-store\"\n\ninterface Props {\n transform?: Matrix\n children: any\n focusOnHover?: boolean\n primitives?: Primitive[]\n onBoundsSelected?: (bounds: BoundsSelection) => void\n cancelPanDrag?: () => void\n}\n\nconst SNAP_THRESHOLD_PX = 16\nconst SNAP_MARKER_SIZE = 5\n\nexport interface BoundsSelection {\n minX: number\n minY: number\n maxX: number\n maxY: number\n}\n\nconst shouldExcludePrimitiveFromSnapping = (primitive: Primitive) => {\n if (primitive.pcb_drawing_type === \"text\") return true\n\n const element = primitive._element as { type?: unknown } | undefined\n if (!element || typeof element !== \"object\") {\n return false\n }\n\n const elementType =\n typeof element.type === \"string\" ? (element.type as string) : undefined\n\n if (!elementType) return false\n\n if (elementType.startsWith(\"pcb_silkscreen_\")) return true\n if (elementType.startsWith(\"pcb_note_\")) return true\n if (elementType === \"pcb_text\") return true\n if (\n elementType.startsWith(\"pcb_fabrication_note_\") &&\n elementType !== \"pcb_fabrication_note_rect\"\n ) {\n return true\n }\n\n return false\n}\n\nexport const DimensionOverlay = ({\n children,\n transform,\n focusOnHover = false,\n primitives = [],\n onBoundsSelected,\n cancelPanDrag,\n}: Props) => {\n if (!transform) transform = identity()\n const [dimensionToolVisible, setDimensionToolVisible] = useState(false)\n const [dimensionToolStretching, setDimensionToolStretching] = useState(false)\n const [measureToolArmed, setMeasureToolArmed] = useState(false)\n const [boundsToolArmed, setBoundsToolArmed] = useState(false)\n const [boundsToolVisible, setBoundsToolVisible] = useState(false)\n const [boundsToolDragging, setBoundsToolDragging] = useState(false)\n const [activeSnapIds, setActiveSnapIds] = useState({\n start: null as string | null,\n end: null as string | null,\n })\n\n const isMouseOverContainer = useGlobalStore((s) => s.is_mouse_over_container)\n\n const disarmMeasure = useCallback(() => {\n if (measureToolArmed) {\n setMeasureToolArmed(false)\n window.dispatchEvent(new Event(\"disarm-dimension-tool\"))\n }\n }, [measureToolArmed])\n const disarmBounds = useCallback(() => {\n if (boundsToolArmed) {\n setBoundsToolArmed(false)\n window.dispatchEvent(new Event(\"disarm-bounds-tool\"))\n }\n }, [boundsToolArmed])\n // Start of dimension tool line in real-world coordinates (not screen)\n const [dStart, setDStart] = useState({ x: 0, y: 0 })\n // End of dimension tool line in real-world coordinates (not screen)\n const [dEnd, setDEnd] = useState({ x: 0, y: 0 })\n const [boundsStart, setBoundsStart] = useState({ x: 0, y: 0 })\n const [boundsEnd, setBoundsEnd] = useState({ x: 0, y: 0 })\n const mousePosRef = useRef({ x: 0, y: 0 })\n const containerRef = useRef<HTMLDivElement | null>(null)\n const container = containerRef.current!\n const containerBounds = container?.getBoundingClientRect()\n\n const elementBoundingBoxes = useMemo(() => {\n const boundingBoxes = new Map<object, BoundingBox>()\n\n for (const primitive of primitives) {\n if (!primitive._element) continue\n if (shouldExcludePrimitiveFromSnapping(primitive)) continue\n if (primitive.pcb_drawing_type === \"pill\") continue\n if (\n primitive.pcb_drawing_type === \"rect\" &&\n primitive.ccw_rotation &&\n primitive.ccw_rotation !== 0\n )\n continue\n const bbox = getPrimitiveBoundingBox(primitive)\n if (!bbox) continue\n\n const existing = boundingBoxes.get(primitive._element as object)\n boundingBoxes.set(\n primitive._element as object,\n mergeBoundingBoxes(existing ?? undefined, bbox),\n )\n }\n\n return boundingBoxes\n }, [primitives])\n\n const primitiveSnappingPoints = useMemo(() => {\n const snapPoints: {\n anchor: NinePointAnchor | string\n point: { x: number; y: number }\n element: object\n }[] = []\n\n for (const primitive of primitives) {\n if (!primitive._element) continue\n if (shouldExcludePrimitiveFromSnapping(primitive)) continue\n\n const primitivePoints = getPrimitiveSnapPoints(primitive)\n if (primitivePoints.length === 0) continue\n\n for (const snap of primitivePoints) {\n snapPoints.push({\n anchor: snap.anchor,\n point: snap.point,\n element: primitive._element as object,\n })\n }\n }\n\n return snapPoints\n }, [primitives])\n\n const snappingPoints = useMemo(() => {\n const points: {\n anchor: NinePointAnchor | \"origin\" | string\n point: { x: number; y: number }\n element: object | null\n }[] = []\n\n elementBoundingBoxes.forEach((bounds, element) => {\n if (!bounds) return\n\n const centerX = (bounds.minX + bounds.maxX) / 2\n const centerY = (bounds.minY + bounds.maxY) / 2\n\n const anchorPoints: Record<NinePointAnchor, { x: number; y: number }> = {\n top_left: { x: bounds.minX, y: bounds.minY },\n top_center: { x: centerX, y: bounds.minY },\n top_right: { x: bounds.maxX, y: bounds.minY },\n center_left: { x: bounds.minX, y: centerY },\n center: { x: centerX, y: centerY },\n center_right: { x: bounds.maxX, y: centerY },\n bottom_left: { x: bounds.minX, y: bounds.maxY },\n bottom_center: { x: centerX, y: bounds.maxY },\n bottom_right: { x: bounds.maxX, y: bounds.maxY },\n }\n\n for (const [anchor, point] of Object.entries(anchorPoints) as [\n NinePointAnchor,\n { x: number; y: number },\n ][]) {\n points.push({\n anchor,\n point,\n element,\n })\n }\n })\n\n for (const snap of primitiveSnappingPoints) {\n points.push(snap)\n }\n\n points.push({\n anchor: \"origin\",\n point: { x: 0, y: 0 },\n element: null,\n })\n\n return points\n }, [elementBoundingBoxes, primitiveSnappingPoints])\n\n const snappingPointsWithScreen = useMemo(() => {\n return snappingPoints.map((snap, index) => ({\n ...snap,\n id: `${index}-${snap.anchor}`,\n screenPoint: applyToPoint(transform!, snap.point),\n }))\n }, [snappingPoints, transform])\n\n const findSnap = useCallback(\n (rwPoint: { x: number; y: number }) => {\n if (snappingPointsWithScreen.length === 0) {\n return { point: rwPoint, id: null as string | null }\n }\n\n const screenPoint = applyToPoint(transform!, rwPoint)\n let bestMatch: {\n distance: number\n id: string\n point: { x: number; y: number }\n } | null = null\n\n for (const snap of snappingPointsWithScreen) {\n const dx = snap.screenPoint.x - screenPoint.x\n const dy = snap.screenPoint.y - screenPoint.y\n const distance = Math.hypot(dx, dy)\n\n if (distance > SNAP_THRESHOLD_PX) continue\n if (!bestMatch || distance < bestMatch.distance) {\n bestMatch = {\n distance,\n id: snap.id,\n point: snap.point,\n }\n }\n }\n\n if (!bestMatch) {\n return { point: rwPoint, id: null as string | null }\n }\n\n return { point: bestMatch.point, id: bestMatch.id }\n },\n [snappingPointsWithScreen, transform],\n )\n\n useEffect(() => {\n const down = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement\n if (\n target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.isContentEditable\n ) {\n return\n }\n\n const containerHasFocus =\n containerRef.current?.contains(document.activeElement) ||\n document.activeElement === containerRef.current\n if (!isMouseOverContainer && !containerHasFocus) return\n\n if (e.key === \"d\") {\n const snap = findSnap({\n x: mousePosRef.current.x,\n y: mousePosRef.current.y,\n })\n\n setDStart({ x: snap.point.x, y: snap.point.y })\n setDEnd({ x: snap.point.x, y: snap.point.y })\n setActiveSnapIds({ start: snap.id, end: snap.id })\n\n if (dimensionToolVisible) {\n setDimensionToolVisible(false)\n setDimensionToolStretching(false)\n setActiveSnapIds({ start: null, end: null })\n } else {\n setDimensionToolVisible(true)\n setDimensionToolStretching(true)\n }\n disarmMeasure()\n }\n if (e.key === \"Escape\") {\n setDimensionToolVisible(false)\n setDimensionToolStretching(false)\n setActiveSnapIds({ start: null, end: null })\n setBoundsToolVisible(false)\n setBoundsToolDragging(false)\n disarmMeasure()\n disarmBounds()\n }\n }\n\n const armMeasure = () => {\n setMeasureToolArmed(true)\n setBoundsToolArmed(false)\n window.dispatchEvent(new Event(\"disarm-bounds-tool\"))\n }\n\n const armBounds = () => {\n setBoundsToolArmed(true)\n setMeasureToolArmed(false)\n setDimensionToolVisible(false)\n setDimensionToolStretching(false)\n window.dispatchEvent(new Event(\"disarm-dimension-tool\"))\n }\n\n window.addEventListener(\"keydown\", down)\n window.addEventListener(\"arm-dimension-tool\", armMeasure)\n window.addEventListener(\"arm-bounds-tool\", armBounds)\n\n return () => {\n window.removeEventListener(\"keydown\", down)\n window.removeEventListener(\"arm-dimension-tool\", armMeasure)\n window.removeEventListener(\"arm-bounds-tool\", armBounds)\n disarmMeasure()\n disarmBounds()\n }\n }, [\n isMouseOverContainer,\n dimensionToolVisible,\n disarmMeasure,\n disarmBounds,\n findSnap,\n ])\n\n const screenDStart = applyToPoint(transform, dStart)\n const screenDEnd = applyToPoint(transform, dEnd)\n const screenBoundsStart = applyToPoint(transform, boundsStart)\n const screenBoundsEnd = applyToPoint(transform, boundsEnd)\n\n const selectedBounds = {\n minX: Math.min(boundsStart.x, boundsEnd.x),\n minY: Math.min(boundsStart.y, boundsEnd.y),\n maxX: Math.max(boundsStart.x, boundsEnd.x),\n maxY: Math.max(boundsStart.y, boundsEnd.y),\n }\n\n const boundsScreenRect = {\n left: Math.min(screenBoundsStart.x, screenBoundsEnd.x),\n top: Math.min(screenBoundsStart.y, screenBoundsEnd.y),\n width: Math.abs(screenBoundsStart.x - screenBoundsEnd.x),\n height: Math.abs(screenBoundsStart.y - screenBoundsEnd.y),\n }\n\n const emitBounds = useCallback(\n (start: { x: number; y: number }, end: { x: number; y: number }) => {\n const bounds = {\n minX: Math.min(start.x, end.x),\n minY: Math.min(start.y, end.y),\n maxX: Math.max(start.x, end.x),\n maxY: Math.max(start.y, end.y),\n }\n\n onBoundsSelected?.(bounds)\n window.dispatchEvent(\n new CustomEvent(\"pcb-viewer:bounds-selected\", {\n detail: bounds,\n }),\n )\n },\n [onBoundsSelected],\n )\n\n const arrowScreenBounds = {\n left: Math.min(screenDStart.x, screenDEnd.x),\n right: Math.max(screenDStart.x, screenDEnd.x),\n top: Math.min(screenDStart.y, screenDEnd.y),\n bottom: Math.max(screenDStart.y, screenDEnd.y),\n flipX: screenDStart.x > screenDEnd.x,\n flipY: screenDStart.y > screenDEnd.y,\n width: 0,\n height: 0,\n }\n arrowScreenBounds.width = arrowScreenBounds.right - arrowScreenBounds.left\n arrowScreenBounds.height = arrowScreenBounds.bottom - arrowScreenBounds.top\n\n const diagonalLabel = useDiagonalLabel({\n dimensionStart: dStart,\n dimensionEnd: dEnd,\n screenDimensionStart: screenDStart,\n screenDimensionEnd: screenDEnd,\n flipX: arrowScreenBounds.flipX,\n flipY: arrowScreenBounds.flipY,\n })\n\n return (\n <div\n ref={containerRef}\n data-pcb-viewer\n // biome-ignore lint/a11y/noNoninteractiveTabindex: <explanation>\n tabIndex={0}\n style={{ position: \"relative\", outline: \"none\" }}\n onMouseEnter={() => {\n if (focusOnHover && containerRef.current) {\n containerRef.current.focus()\n }\n }}\n onMouseLeave={() => {\n if (containerRef.current) {\n containerRef.current.blur()\n }\n }}\n onClick={() => {\n if (containerRef.current) {\n containerRef.current.focus()\n }\n }}\n onMouseMove={(e: React.MouseEvent<HTMLDivElement>) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const rwPoint = applyToPoint(inverse(transform!), { x, y })\n mousePosRef.current.x = rwPoint.x\n mousePosRef.current.y = rwPoint.y\n\n if (dimensionToolStretching) {\n const snap = findSnap(rwPoint)\n setDEnd({ x: snap.point.x, y: snap.point.y })\n setActiveSnapIds((prev) => ({ ...prev, end: snap.id }))\n }\n if (boundsToolDragging) {\n cancelPanDrag?.()\n setBoundsEnd({ x: rwPoint.x, y: rwPoint.y })\n }\n }}\n onMouseDown={(e) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const rwPoint = applyToPoint(inverse(transform!), { x, y })\n\n if (boundsToolArmed) {\n e.preventDefault()\n e.stopPropagation()\n cancelPanDrag?.()\n setBoundsStart({ x: rwPoint.x, y: rwPoint.y })\n setBoundsEnd({ x: rwPoint.x, y: rwPoint.y })\n setBoundsToolVisible(true)\n setBoundsToolDragging(true)\n disarmBounds()\n } else if (measureToolArmed && !dimensionToolVisible) {\n const snap = findSnap(rwPoint)\n setDStart({ x: snap.point.x, y: snap.point.y })\n setDEnd({ x: snap.point.x, y: snap.point.y })\n setActiveSnapIds({ start: snap.id, end: snap.id })\n setDimensionToolVisible(true)\n setDimensionToolStretching(true)\n disarmMeasure()\n } else if (dimensionToolStretching) {\n setDimensionToolStretching(false)\n setActiveSnapIds((prev) => ({ ...prev, end: null }))\n } else if (dimensionToolVisible) {\n setDimensionToolVisible(false)\n setActiveSnapIds({ start: null, end: null })\n }\n }}\n onMouseUp={(e) => {\n if (!boundsToolDragging) return\n\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const rwPoint = applyToPoint(inverse(transform!), { x, y })\n const end = { x: rwPoint.x, y: rwPoint.y }\n\n e.preventDefault()\n e.stopPropagation()\n cancelPanDrag?.()\n setBoundsEnd(end)\n setBoundsToolDragging(false)\n emitBounds(boundsStart, end)\n }}\n >\n {children}\n {boundsToolVisible && (\n <>\n {/* biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> */}\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n width={containerBounds.width}\n height={containerBounds.height}\n >\n <rect\n x={boundsScreenRect.left}\n y={boundsScreenRect.top}\n width={boundsScreenRect.width}\n height={boundsScreenRect.height}\n stroke=\"red\"\n strokeWidth={1.5}\n strokeDasharray=\"4,3\"\n fill=\"rgba(255, 0, 0, 0.12)\"\n />\n </svg>\n <div\n style={{\n left: 0,\n bottom: dimensionToolVisible ? 58 : 0,\n position: \"absolute\",\n color: \"red\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n margin: 4,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n minX: {selectedBounds.minX.toFixed(2)}, minY:{\" \"}\n {selectedBounds.minY.toFixed(2)}\n <br />\n maxX: {selectedBounds.maxX.toFixed(2)}, maxY:{\" \"}\n {selectedBounds.maxY.toFixed(2)}\n </div>\n </>\n )}\n {dimensionToolVisible && (\n <>\n {diagonalLabel.show && (\n <div\n style={{\n position: \"absolute\",\n left: diagonalLabel.x,\n top: diagonalLabel.y,\n color: \"red\",\n mixBlendMode: \"difference\",\n pointerEvents: \"none\",\n fontSize: 12,\n fontFamily: \"sans-serif\",\n whiteSpace: \"nowrap\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n {diagonalLabel.distance.toFixed(2)}\n </div>\n )}\n\n <div\n style={{\n position: \"absolute\",\n left: arrowScreenBounds.left,\n width: arrowScreenBounds.width,\n textAlign: \"center\",\n top: screenDStart.y + 2,\n color: \"red\",\n mixBlendMode: \"difference\",\n pointerEvents: \"none\",\n marginTop: arrowScreenBounds.flipY ? 0 : -20,\n fontSize: 12,\n fontFamily: \"sans-serif\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n {Math.abs(dStart.x - dEnd.x).toFixed(2)}\n </div>\n\n <div\n style={{\n position: \"absolute\",\n left: screenDEnd.x,\n height: arrowScreenBounds.height,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n top: arrowScreenBounds.top,\n color: \"red\",\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n fontSize: 12,\n fontFamily: \"sans-serif\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n <div\n style={{\n marginLeft: arrowScreenBounds.flipX ? \"-100%\" : 4,\n paddingRight: 4,\n }}\n >\n {Math.abs(dStart.y - dEnd.y).toFixed(2)}\n </div>\n </div>\n {/* biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> */}\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n width={containerBounds.width}\n height={containerBounds.height}\n >\n <defs>\n <marker\n id=\"head\"\n orient=\"auto\"\n markerWidth=\"3\"\n markerHeight=\"4\"\n refX=\"2\"\n refY=\"2\"\n >\n <path d=\"M0,0 V4 L2,2 Z\" fill=\"red\" />\n </marker>\n </defs>\n <line\n x1={screenDStart.x}\n y1={screenDStart.y}\n x2={screenDEnd.x}\n y2={screenDEnd.y}\n markerEnd=\"url(#head)\"\n strokeWidth={1.5}\n fill=\"none\"\n stroke=\"red\"\n />\n <line\n x1={screenDStart.x}\n y1={screenDStart.y}\n x2={screenDEnd.x}\n y2={screenDStart.y}\n strokeWidth={1.5}\n fill=\"none\"\n strokeDasharray={\"2,2\"}\n stroke=\"red\"\n />\n <line\n x1={screenDEnd.x}\n y1={screenDStart.y}\n x2={screenDEnd.x}\n y2={screenDEnd.y}\n strokeWidth={1.5}\n fill=\"none\"\n strokeDasharray={\"2,2\"}\n stroke=\"red\"\n />\n </svg>\n {dimensionToolStretching &&\n snappingPointsWithScreen.map((snap) => {\n const isActive =\n snap.id === activeSnapIds.start || snap.id === activeSnapIds.end\n const half = SNAP_MARKER_SIZE / 2\n return (\n <svg\n key={snap.id}\n width={SNAP_MARKER_SIZE}\n height={SNAP_MARKER_SIZE}\n style={{\n position: \"absolute\",\n left: snap.screenPoint.x - half,\n top: snap.screenPoint.y - half,\n pointerEvents: \"none\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n <line\n x1={0}\n y1={0}\n x2={SNAP_MARKER_SIZE}\n y2={SNAP_MARKER_SIZE}\n stroke={isActive ? \"#66ccff\" : \"white\"}\n strokeWidth={1}\n />\n <line\n x1={SNAP_MARKER_SIZE}\n y1={0}\n x2={0}\n y2={SNAP_MARKER_SIZE}\n stroke={isActive ? \"#66ccff\" : \"white\"}\n strokeWidth={1}\n />\n </svg>\n )\n })}\n <div\n style={{\n right: 0,\n bottom: 0,\n position: \"absolute\",\n color: \"red\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n margin: 4,\n }}\n >\n ({dStart.x.toFixed(2)},{dStart.y.toFixed(2)})<br />(\n {dEnd.x.toFixed(2)},{dEnd.y.toFixed(2)})<br />\n dist:{\" \"}\n {Math.sqrt(\n (dEnd.x - dStart.x) ** 2 + (dEnd.y - dStart.y) ** 2,\n ).toFixed(2)}\n </div>\n </>\n )}\n </div>\n )\n}\n","import type { Primitive } from \"../types\"\n\nexport interface BoundingBox {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\nconst mergeNumber = (\n a: number,\n b: number,\n fn: typeof Math.min | typeof Math.max,\n) => fn(a, b)\n\nconst rotatePoint = (\n x: number,\n y: number,\n centerX: number,\n centerY: number,\n rotationDeg: number,\n) => {\n const radians = (rotationDeg * Math.PI) / 180\n const cos = Math.cos(radians)\n const sin = Math.sin(radians)\n const translatedX = x - centerX\n const translatedY = y - centerY\n\n const rotatedX = translatedX * cos - translatedY * sin\n const rotatedY = translatedX * sin + translatedY * cos\n\n return {\n x: rotatedX + centerX,\n y: rotatedY + centerY,\n }\n}\n\nconst createBoxFromPoints = (\n points: { x: number; y: number }[],\n): BoundingBox | null => {\n if (points.length === 0) return null\n\n let minX = points[0]!.x\n let maxX = points[0]!.x\n let minY = points[0]!.y\n let maxY = points[0]!.y\n\n for (const point of points) {\n minX = mergeNumber(minX, point.x, Math.min)\n maxX = mergeNumber(maxX, point.x, Math.max)\n minY = mergeNumber(minY, point.y, Math.min)\n maxY = mergeNumber(maxY, point.y, Math.max)\n }\n\n return { minX, maxX, minY, maxY }\n}\nexport const getBoundsFromPoints = createBoxFromPoints\n\nconst mergeBoundingBoxesInternal = (\n a: BoundingBox,\n b: BoundingBox,\n): BoundingBox => ({\n minX: Math.min(a.minX, b.minX),\n maxX: Math.max(a.maxX, b.maxX),\n minY: Math.min(a.minY, b.minY),\n maxY: Math.max(a.maxY, b.maxY),\n})\n\nexport const mergeBoundingBoxes = (\n existing: BoundingBox | undefined,\n next: BoundingBox,\n): BoundingBox => {\n if (!existing) return next\n return mergeBoundingBoxesInternal(existing, next)\n}\n\nexport const getPrimitiveBoundingBox = (\n primitive: Primitive,\n): BoundingBox | null => {\n switch (primitive.pcb_drawing_type) {\n case \"line\": {\n const halfWidth = (primitive.width ?? 0) / 2\n const points = [\n { x: primitive.x1, y: primitive.y1 },\n { x: primitive.x2, y: primitive.y2 },\n ]\n\n const baseBox = createBoxFromPoints(points)\n if (!baseBox) return null\n\n return {\n minX: baseBox.minX - halfWidth,\n maxX: baseBox.maxX + halfWidth,\n minY: baseBox.minY - halfWidth,\n maxY: baseBox.maxY + halfWidth,\n }\n }\n case \"rect\": {\n const halfW = primitive.w / 2\n const halfH = primitive.h / 2\n const corners = [\n { x: primitive.x - halfW, y: primitive.y - halfH },\n { x: primitive.x + halfW, y: primitive.y - halfH },\n { x: primitive.x + halfW, y: primitive.y + halfH },\n { x: primitive.x - halfW, y: primitive.y + halfH },\n ]\n\n const rotation = primitive.ccw_rotation ?? 0\n const rotatedCorners =\n rotation === 0\n ? corners\n : corners.map((corner) =>\n rotatePoint(\n corner.x,\n corner.y,\n primitive.x,\n primitive.y,\n rotation,\n ),\n )\n\n return createBoxFromPoints(rotatedCorners)\n }\n case \"circle\": {\n return {\n minX: primitive.x - primitive.r,\n maxX: primitive.x + primitive.r,\n minY: primitive.y - primitive.r,\n maxY: primitive.y + primitive.r,\n }\n }\n case \"oval\": {\n return {\n minX: primitive.x - primitive.rX,\n maxX: primitive.x + primitive.rX,\n minY: primitive.y - primitive.rY,\n maxY: primitive.y + primitive.rY,\n }\n }\n case \"pill\": {\n const halfW = primitive.w / 2\n const halfH = primitive.h / 2\n const corners = [\n { x: primitive.x - halfW, y: primitive.y - halfH },\n { x: primitive.x + halfW, y: primitive.y - halfH },\n { x: primitive.x + halfW, y: primitive.y + halfH },\n { x: primitive.x - halfW, y: primitive.y + halfH },\n ]\n const rotation = primitive.ccw_rotation ?? 0\n const rotatedCorners =\n rotation === 0\n ? corners\n : corners.map((corner) =>\n rotatePoint(\n corner.x,\n corner.y,\n primitive.x,\n primitive.y,\n rotation,\n ),\n )\n return createBoxFromPoints(rotatedCorners)\n }\n case \"polygon\": {\n return createBoxFromPoints(primitive.points)\n }\n case \"polygon_with_arcs\": {\n const points = primitive.brep_shape.outer_ring.vertices.map((vertex) => ({\n x: vertex.x,\n y: vertex.y,\n }))\n return createBoxFromPoints(points)\n }\n case \"text\": {\n const size = primitive.size ?? 0\n const width = primitive.text ? primitive.text.length * size * 0.6 : 0\n const height = size\n\n if (width === 0 && height === 0) {\n return {\n minX: primitive.x,\n maxX: primitive.x,\n minY: primitive.y,\n maxY: primitive.y,\n }\n }\n\n const halfW = width / 2\n const halfH = height / 2\n return {\n minX: primitive.x - halfW,\n maxX: primitive.x + halfW,\n minY: primitive.y - halfH,\n maxY: primitive.y + halfH,\n }\n }\n default:\n return null\n }\n}\n","import { useMemo } from \"react\"\nimport {\n calculateDiagonalLabel,\n type DiagonalLabelResult,\n} from \"lib/util/calculate-diagonal-label\"\n\nexport interface UseDiagonalLabelParams {\n dimensionStart: { x: number; y: number }\n dimensionEnd: { x: number; y: number }\n screenDimensionStart: { x: number; y: number }\n screenDimensionEnd: { x: number; y: number }\n flipX: boolean\n flipY: boolean\n}\n\nexport function useDiagonalLabel(\n params: UseDiagonalLabelParams,\n): DiagonalLabelResult {\n const {\n dimensionStart,\n dimensionEnd,\n screenDimensionStart,\n screenDimensionEnd,\n flipX,\n flipY,\n } = params\n\n return useMemo(\n () =>\n calculateDiagonalLabel({\n dimensionStart,\n dimensionEnd,\n screenDimensionStart,\n screenDimensionEnd,\n flipX,\n flipY,\n }),\n [\n dimensionStart,\n dimensionEnd,\n screenDimensionStart,\n screenDimensionEnd,\n flipX,\n flipY,\n ],\n )\n}\n","export interface DiagonalLabelParams {\n dimensionStart: { x: number; y: number }\n dimensionEnd: { x: number; y: number }\n screenDimensionStart: { x: number; y: number }\n screenDimensionEnd: { x: number; y: number }\n flipX: boolean\n flipY: boolean\n}\n\nexport interface DiagonalLabelResult {\n distance: number\n screenDistance: number\n x: number\n y: number\n show: boolean\n}\n\nexport function calculateDiagonalLabel(\n params: DiagonalLabelParams,\n): DiagonalLabelResult {\n const {\n dimensionStart,\n dimensionEnd,\n screenDimensionStart,\n screenDimensionEnd,\n flipX,\n flipY,\n } = params\n\n // Calculate dimension distance in world coordinates\n const deltaX = dimensionEnd.x - dimensionStart.x\n const deltaY = dimensionEnd.y - dimensionStart.y\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)\n\n // Calculate screen distance and angle\n const screenDeltaX = screenDimensionEnd.x - screenDimensionStart.x\n const screenDeltaY = screenDimensionEnd.y - screenDimensionStart.y\n const screenDistance = Math.sqrt(\n screenDeltaX * screenDeltaX + screenDeltaY * screenDeltaY,\n )\n\n // Calculate angle of the measurement line\n const angle = Math.atan2(screenDeltaY, screenDeltaX) * (180 / Math.PI)\n\n const normalizedAngle = Math.abs(angle) % 90\n const angleFromAxis = Math.min(normalizedAngle, 90 - normalizedAngle)\n const isDiagonal = angleFromAxis > 15\n\n // Find midpoint of the diagonal line\n const midX = (screenDimensionStart.x + screenDimensionEnd.x) / 2\n const midY = (screenDimensionStart.y + screenDimensionEnd.y) / 2\n\n // Offset perpendicular to the line, always pointing away from the inner triangle\n const offsetDistance = 15\n const perpendicularAngle = angle + 90\n\n let offsetX = Math.cos((perpendicularAngle * Math.PI) / 180) * offsetDistance\n let offsetY = Math.sin((perpendicularAngle * Math.PI) / 180) * offsetDistance\n\n const isNE = screenDeltaX > 0 && screenDeltaY < 0\n const isNW = screenDeltaX < 0 && screenDeltaY < 0\n const isSE = screenDeltaX > 0 && screenDeltaY > 0\n const isSW = screenDeltaX < 0 && screenDeltaY > 0\n\n if (flipX !== flipY && !isNE) {\n offsetX = -offsetX\n offsetY = -offsetY\n }\n\n if (isNE) {\n const lessOffset = -45\n offsetX += Math.cos((perpendicularAngle * Math.PI) / 180) * lessOffset\n offsetY += Math.sin((perpendicularAngle * Math.PI) / 180) * lessOffset\n }\n\n if (isSE) {\n const seAdjust = -10\n offsetX += Math.cos((perpendicularAngle * Math.PI) / 180) + seAdjust * 2\n offsetY += Math.sin((perpendicularAngle * Math.PI) / 180) + seAdjust\n }\n\n if (isSW) {\n const reduceOffset = 10\n offsetX += Math.cos((perpendicularAngle * Math.PI) / 180) * reduceOffset\n offsetY += Math.sin((perpendicularAngle * Math.PI) / 180) * reduceOffset\n }\n\n const x = midX + offsetX\n const y = midY + offsetY\n\n return {\n distance,\n screenDistance,\n x,\n y,\n show: distance > 0.01 && screenDistance > 30 && isDiagonal,\n }\n}\n","import type { NinePointAnchor } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\n\nexport interface PrimitiveSnapPoint {\n anchor: NinePointAnchor | string\n point: { x: number; y: number }\n}\n\nconst rotatePoint = (\n point: { x: number; y: number },\n center: { x: number; y: number },\n rotationDeg: number,\n) => {\n const radians = (rotationDeg * Math.PI) / 180\n const cos = Math.cos(radians)\n const sin = Math.sin(radians)\n\n const translatedX = point.x - center.x\n const translatedY = point.y - center.y\n\n const rotatedX = translatedX * cos - translatedY * sin\n const rotatedY = translatedX * sin + translatedY * cos\n\n return {\n x: rotatedX + center.x,\n y: rotatedY + center.y,\n }\n}\n\nconst getNinePointAnchors = (\n center: { x: number; y: number },\n halfWidth: number,\n halfHeight: number,\n rotationDeg: number,\n): PrimitiveSnapPoint[] => {\n const basePoints: Record<NinePointAnchor, { x: number; y: number }> = {\n top_left: { x: center.x - halfWidth, y: center.y - halfHeight },\n top_center: { x: center.x, y: center.y - halfHeight },\n top_right: { x: center.x + halfWidth, y: center.y - halfHeight },\n center_left: { x: center.x - halfWidth, y: center.y },\n center: { x: center.x, y: center.y },\n center_right: { x: center.x + halfWidth, y: center.y },\n bottom_left: { x: center.x - halfWidth, y: center.y + halfHeight },\n bottom_center: { x: center.x, y: center.y + halfHeight },\n bottom_right: { x: center.x + halfWidth, y: center.y + halfHeight },\n }\n\n if (rotationDeg === 0) {\n return Object.entries(basePoints).map(([anchor, point]) => ({\n anchor: anchor as NinePointAnchor,\n point,\n }))\n }\n\n return Object.entries(basePoints).map(([anchor, point]) => ({\n anchor: anchor as NinePointAnchor,\n point: rotatePoint(point, center, rotationDeg),\n }))\n}\n\nexport const getPrimitiveSnapPoints = (\n primitive: Primitive,\n): PrimitiveSnapPoint[] => {\n switch (primitive.pcb_drawing_type) {\n case \"rect\": {\n const rotation = primitive.ccw_rotation ?? 0\n return getNinePointAnchors(\n { x: primitive.x, y: primitive.y },\n primitive.w / 2,\n primitive.h / 2,\n rotation,\n )\n }\n case \"pill\": {\n const rotation = primitive.ccw_rotation ?? 0\n return getNinePointAnchors(\n { x: primitive.x, y: primitive.y },\n primitive.w / 2,\n primitive.h / 2,\n rotation,\n )\n }\n case \"circle\": {\n return [\n { anchor: \"circle_center\", point: { x: primitive.x, y: primitive.y } },\n {\n anchor: \"circle_right\",\n point: { x: primitive.x + primitive.r, y: primitive.y },\n },\n {\n anchor: \"circle_left\",\n point: { x: primitive.x - primitive.r, y: primitive.y },\n },\n {\n anchor: \"circle_top\",\n point: { x: primitive.x, y: primitive.y - primitive.r },\n },\n {\n anchor: \"circle_bottom\",\n point: { x: primitive.x, y: primitive.y + primitive.r },\n },\n ]\n }\n case \"oval\": {\n return [\n { anchor: \"oval_center\", point: { x: primitive.x, y: primitive.y } },\n {\n anchor: \"oval_right\",\n point: { x: primitive.x + primitive.rX, y: primitive.y },\n },\n {\n anchor: \"oval_left\",\n point: { x: primitive.x - primitive.rX, y: primitive.y },\n },\n {\n anchor: \"oval_top\",\n point: { x: primitive.x, y: primitive.y - primitive.rY },\n },\n {\n anchor: \"oval_bottom\",\n point: { x: primitive.x, y: primitive.y + primitive.rY },\n },\n ]\n }\n case \"line\": {\n const midPoint = {\n x: (primitive.x1 + primitive.x2) / 2,\n y: (primitive.y1 + primitive.y2) / 2,\n }\n return [\n { anchor: \"line_start\", point: { x: primitive.x1, y: primitive.y1 } },\n { anchor: \"line_mid\", point: midPoint },\n { anchor: \"line_end\", point: { x: primitive.x2, y: primitive.y2 } },\n ]\n }\n case \"polygon\": {\n return primitive.points.map((point, index) => ({\n anchor: `polygon_vertex_${index}`,\n point,\n }))\n }\n case \"polygon_with_arcs\": {\n return primitive.brep_shape.outer_ring.vertices.map((vertex, index) => ({\n anchor: `polygon_with_arcs_vertex_${index}`,\n point: { x: vertex.x, y: vertex.y },\n }))\n }\n default:\n return []\n }\n}\n","import type { AnyCircuitElement, PcbComponent } from \"circuit-json\"\nimport { useGlobalStore } from \"../global-store\"\nimport { useEffect, useRef, useState } from \"react\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { applyToPoint, identity, inverse } from \"transformation-matrix\"\nimport type { ManualEditEvent } from \"@tscircuit/props\"\n\ninterface Props {\n transform?: Matrix\n children: any\n soup: AnyCircuitElement[]\n disabled?: boolean\n cancelPanDrag: () => void\n onCreateEditEvent: (event: ManualEditEvent) => void\n onModifyEditEvent: (event: Partial<ManualEditEvent>) => void\n}\n\nconst isInsideOf = (\n pcb_component: PcbComponent,\n point: { x: number; y: number },\n padding = 0,\n) => {\n const halfWidth = pcb_component.width / 2\n const halfHeight = pcb_component.height / 2\n\n const left = pcb_component.center.x - halfWidth - padding\n const right = pcb_component.center.x + halfWidth + padding\n const top = pcb_component.center.y - halfHeight - padding\n const bottom = pcb_component.center.y + halfHeight + padding\n\n return point.x > left && point.x < right && point.y > top && point.y < bottom\n}\n\nexport const EditPlacementOverlay = ({\n children,\n disabled: disabledProp,\n transform,\n soup,\n cancelPanDrag,\n onCreateEditEvent,\n onModifyEditEvent,\n}: Props) => {\n if (!transform) transform = identity()\n const containerRef = useRef<HTMLDivElement | null>(null)\n const [activePcbComponentId, setActivePcbComponent] = useState<null | string>(\n null,\n )\n const [dragState, setDragState] = useState<{\n dragStart: { x: number; y: number }\n originalCenter: { x: number; y: number }\n dragEnd: { x: number; y: number }\n edit_event_id: string\n } | null>(null)\n const isPcbComponentActive = activePcbComponentId !== null\n const in_edit_mode = useGlobalStore((s) => s.in_edit_mode)\n const in_move_footprint_mode = useGlobalStore((s) => s.in_move_footprint_mode)\n const setIsMovingComponent = useGlobalStore((s) => s.setIsMovingComponent)\n\n const disabled = disabledProp || !in_move_footprint_mode\n\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n }}\n onMouseDown={(e) => {\n if (disabled) return\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n if (Number.isNaN(x) || Number.isNaN(y)) return\n const rwMousePoint = applyToPoint(inverse(transform!), { x, y })\n\n let foundActiveComponent = false\n for (const e of soup) {\n if (\n e.type === \"pcb_component\" &&\n isInsideOf(e, rwMousePoint, 10 / transform.a)\n ) {\n cancelPanDrag()\n setActivePcbComponent(e.pcb_component_id)\n foundActiveComponent = true\n const edit_event_id = Math.random().toString()\n setDragState({\n dragStart: rwMousePoint,\n originalCenter: e.center,\n dragEnd: rwMousePoint,\n edit_event_id,\n })\n\n onCreateEditEvent({\n edit_event_id,\n edit_event_type: \"edit_pcb_component_location\",\n pcb_edit_event_type: \"edit_component_location\",\n pcb_component_id: e.pcb_component_id,\n original_center: e.center,\n new_center: e.center,\n in_progress: true,\n created_at: Date.now(),\n })\n\n setIsMovingComponent(true)\n break\n }\n }\n if (!foundActiveComponent) {\n setActivePcbComponent(null)\n }\n\n if (foundActiveComponent) {\n e.preventDefault()\n return false\n }\n }}\n onMouseMove={(e) => {\n if (!activePcbComponentId || !dragState) return\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n if (Number.isNaN(x) || Number.isNaN(y)) return\n const rwMousePoint = applyToPoint(inverse(transform!), { x, y })\n setDragState({\n ...dragState,\n dragEnd: rwMousePoint,\n })\n onModifyEditEvent({\n edit_event_id: dragState.edit_event_id,\n new_center: {\n x:\n dragState.originalCenter.x +\n rwMousePoint.x -\n dragState.dragStart.x,\n y:\n dragState.originalCenter.y +\n rwMousePoint.y -\n dragState.dragStart.y,\n },\n })\n }}\n onMouseUp={(e) => {\n if (!activePcbComponentId) return\n setActivePcbComponent(null)\n setIsMovingComponent(false)\n if (dragState) {\n onModifyEditEvent({\n edit_event_id: dragState.edit_event_id,\n in_progress: false,\n })\n setDragState(null)\n }\n }}\n >\n {children}\n {!disabled &&\n soup\n .filter((e): e is PcbComponent => e.type === \"pcb_component\")\n .map((e) => {\n if (!e?.center) return null\n const projectedCenter = applyToPoint(transform, e.center)\n\n return (\n <div\n key={e.pcb_component_id}\n style={{\n position: \"absolute\",\n pointerEvents: \"none\",\n // b/c of transform, this is actually center not left/top\n left: projectedCenter.x,\n top: projectedCenter.y,\n width: e.width * transform.a + 20,\n height: e.height * transform.a + 20,\n transform: \"translate(-50%, -50%)\",\n background:\n isPcbComponentActive &&\n activePcbComponentId === e.pcb_component_id\n ? \"rgba(255, 0, 0, 0.2)\"\n : \"\",\n }}\n />\n )\n })}\n </div>\n )\n}\n","import React, { useRef, Fragment } from \"react\"\nimport { css } from \"@emotion/css\"\nimport type { AnyCircuitElement, PcbTraceError } from \"circuit-json\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { type Matrix, applyToPoint, identity } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\nimport { getPopupPosition } from \"lib/util/getPopupPosition\"\nimport type { PcbViaClearanceError } from \"circuit-json\"\nimport { findErrorElementById, getErrorId } from \"lib/util/get-error-id\"\nimport {\n buildErrorPreviewElementIndexes,\n getErrorFocusPoint,\n} from \"lib/util/error-preview\"\nimport { FocusMarkerSVG } from \"./FocusMarkerSVG\"\n\ninterface Props {\n transform?: Matrix\n elements?: AnyCircuitElement[]\n children: React.ReactNode\n}\n\ninterface ErrorMarkerSVGProps {\n errorCenter: { x: number; y: number }\n isHighlighted?: boolean\n}\n\nconst ErrorMarkerSVG = ({\n errorCenter,\n isHighlighted = false,\n}: ErrorMarkerSVGProps) => (\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.errorOverlay,\n }}\n width=\"100%\"\n height=\"100%\"\n >\n <rect\n x={errorCenter.x - 7}\n y={errorCenter.y - 7}\n width={14}\n height={14}\n transform={`rotate(45 ${errorCenter.x} ${errorCenter.y})`}\n fill={isHighlighted ? \"#ff4444\" : \"transparent\"}\n stroke={isHighlighted ? \"#ff4444\" : \"red\"}\n strokeWidth={isHighlighted ? 2.5 : 1.5}\n />\n </svg>\n)\n\nconst errorMessageStyles = css`\n opacity: 0;\n pointer-events: none;\n background-color: rgba(0, 0, 0, 0.8);\n padding: 8px 12px;\n border-radius: 4px;\n width: 200px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n word-wrap: break-word;\n line-height: 1.4;\n transition: opacity 0.2s;\n margin-bottom: 10px;\n color: red;\n`\n\nexport const ErrorOverlay = ({\n children,\n transform = identity(),\n elements,\n}: Props) => {\n const containerRef = useRef<HTMLDivElement | null>(null)\n\n const { isShowingDRCErrors, hoveredErrorId, focusedErrorId } = useGlobalStore(\n (state) => ({\n isShowingDRCErrors: state.is_showing_drc_errors,\n hoveredErrorId: state.hovered_error_id,\n focusedErrorId: state.focused_error_id,\n }),\n )\n const activeErrorId = focusedErrorId ?? hoveredErrorId\n\n if (!elements) {\n return (\n <div style={{ position: \"relative\" }} ref={containerRef}>\n {children}\n </div>\n )\n }\n\n const traceErrors = elements.filter(\n (el): el is PcbTraceError =>\n el.type === \"pcb_trace_error\" &&\n !el.message?.includes(\"Multiple components found with name\"),\n )\n const viaClearanceErrors = elements.filter(\n (el): el is PcbViaClearanceError => el.type === \"pcb_via_clearance_error\",\n )\n\n const componentErrors = elements.filter(\n (el): el is PcbTraceError =>\n el.type === \"pcb_trace_error\" &&\n el.message?.includes(\"Multiple components found with name\"),\n )\n\n const elementIndexes = buildErrorPreviewElementIndexes(elements)\n\n const focusedErrorElement = findErrorElementById(elements, activeErrorId)\n const getScreenErrorCenter = (error: AnyCircuitElement) => {\n const focusCenter = getErrorFocusPoint({\n error,\n indexes: elementIndexes,\n })\n\n if (\n !focusCenter ||\n typeof focusCenter.x !== \"number\" ||\n typeof focusCenter.y !== \"number\"\n ) {\n return null\n }\n\n const screenCenter = applyToPoint(transform, focusCenter as any) as any\n\n if (Number.isNaN(screenCenter.x) || Number.isNaN(screenCenter.y)) {\n return null\n }\n\n return screenCenter as { x: number; y: number }\n }\n\n let focusScreenCenter: { x: number; y: number } | null = null\n if (focusedErrorElement) {\n focusScreenCenter = getScreenErrorCenter(\n focusedErrorElement as AnyCircuitElement,\n )\n }\n\n return (\n <div style={{ position: \"relative\" }} ref={containerRef}>\n {children}\n {traceErrors.map((el: PcbTraceError, index) => {\n const errorId = getErrorId(el, index)\n const isHighlighted = activeErrorId === errorId\n\n if (!isHighlighted && !isShowingDRCErrors) return null\n\n const errorCenter = getScreenErrorCenter(el)\n if (!errorCenter) return null\n\n const popupPosition = getPopupPosition(errorCenter, containerRef)\n\n return (\n <Fragment key={errorId}>\n <ErrorMarkerSVG\n errorCenter={errorCenter}\n isHighlighted={isHighlighted}\n />\n <div\n style={{\n position: \"absolute\",\n left: errorCenter.x - 15,\n top: errorCenter.y - 15,\n width: 30,\n height: 30,\n zIndex: zIndexMap.errorOverlay + 5,\n cursor: \"pointer\",\n borderRadius: \"50%\",\n }}\n onMouseEnter={(e) => {\n const popup = e.currentTarget.nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"1\"\n }\n }}\n onMouseLeave={(e) => {\n if (!isHighlighted) {\n const popup = e.currentTarget\n .nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"0\"\n }\n }\n }}\n />\n <div\n style={{\n position: \"absolute\",\n zIndex: isHighlighted ? 200 : 100,\n left: popupPosition.left,\n top: popupPosition.top,\n color: isHighlighted ? \"#ff4444\" : \"red\",\n textAlign: \"center\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n display: isShowingDRCErrors || isHighlighted ? \"flex\" : \"none\",\n flexDirection: \"column\",\n alignItems: \"center\",\n pointerEvents: \"none\",\n transform: popupPosition.transform,\n }}\n >\n <div\n className={`error-message ${errorMessageStyles}`}\n style={{\n opacity: isHighlighted ? 1 : 0,\n border: `1px solid ${isHighlighted ? \"#ff4444\" : \"red\"}`,\n }}\n >\n {el.message}\n </div>\n </div>\n </Fragment>\n )\n })}\n {viaClearanceErrors.map((el, index) => {\n const errorId = getErrorId(el, index)\n const isHighlighted = activeErrorId === errorId\n\n if (!isHighlighted && !isShowingDRCErrors) return null\n\n const errorCenter = getScreenErrorCenter(el)\n if (!errorCenter) return null\n\n const popupPosition = getPopupPosition(\n { x: errorCenter.x, y: errorCenter.y },\n containerRef,\n )\n\n return (\n <Fragment key={errorId}>\n <ErrorMarkerSVG\n errorCenter={errorCenter}\n isHighlighted={isHighlighted}\n />\n <div\n style={{\n position: \"absolute\",\n left: errorCenter.x - 15,\n top: errorCenter.y - 15,\n width: 30,\n height: 30,\n zIndex: zIndexMap.errorOverlay + 5,\n cursor: \"pointer\",\n borderRadius: \"50%\",\n }}\n onMouseEnter={(e) => {\n const popup = e.currentTarget.nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"1\"\n }\n }}\n onMouseLeave={(e) => {\n if (!isHighlighted) {\n const popup = e.currentTarget\n .nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"0\"\n }\n }\n }}\n />\n <div\n style={{\n position: \"absolute\",\n zIndex: isHighlighted\n ? zIndexMap.errorOverlay + 10\n : zIndexMap.errorOverlay + 1,\n left: popupPosition.left,\n top: popupPosition.top,\n color: isHighlighted ? \"#ff4444\" : \"red\",\n textAlign: \"center\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n pointerEvents: \"none\",\n transform: popupPosition.transform,\n }}\n >\n <div\n className={`error-message ${errorMessageStyles}`}\n style={{\n opacity: isHighlighted ? 1 : 0,\n border: `1px solid ${isHighlighted ? \"#ff4444\" : \"red\"}`,\n }}\n >\n {el.message}\n </div>\n </div>\n </Fragment>\n )\n })}\n {componentErrors.map((el: any, index) => {\n const componentName =\n el.component_name || el.message?.match(/name \"([^\"]+)\"/)?.[1]\n if (!componentName) return null\n\n const components =\n elements?.filter(\n (comp) =>\n (comp.type === \"source_component\" &&\n comp.name === componentName) ||\n (comp.type === \"pcb_component\" &&\n elements?.find(\n (src) =>\n src.type === \"source_component\" &&\n src.source_component_id === comp.source_component_id &&\n src.name === componentName,\n )),\n ) || []\n\n const errorId = getErrorId(el, index)\n const isHighlighted = activeErrorId === errorId\n\n if (!isHighlighted && !isShowingDRCErrors) return null\n\n return components.map((comp, compIndex) => {\n let center = { x: 0, y: 0 }\n\n if (comp.type === \"pcb_component\") {\n center = comp.center || { x: 0, y: 0 }\n } else if (comp.type === \"source_component\") {\n const pcbComp = elements?.find(\n (pc) =>\n pc.type === \"pcb_component\" &&\n pc.source_component_id === comp.source_component_id,\n )\n if (pcbComp && pcbComp.type === \"pcb_component\")\n center = pcbComp.center || { x: 0, y: 0 }\n }\n\n const screenCenter = applyToPoint(transform, center)\n if (Number.isNaN(screenCenter.x) || Number.isNaN(screenCenter.y))\n return null\n\n const scale = Math.abs(transform.a)\n const baseRadius = 0.5\n const minRadius = 8\n const maxRadius = 30\n const scaledRadius = Math.max(\n minRadius,\n Math.min(maxRadius, baseRadius * scale),\n )\n\n const popupPosition = getPopupPosition(screenCenter, containerRef)\n\n return (\n <Fragment key={`${errorId}_${compIndex}`}>\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.errorOverlay,\n }}\n width=\"100%\"\n height=\"100%\"\n >\n {isHighlighted ? (\n <polygon\n points={`${screenCenter.x},${screenCenter.y - scaledRadius * 1.25} ${screenCenter.x + scaledRadius},${screenCenter.y} ${screenCenter.x},${screenCenter.y + scaledRadius * 1.25} ${screenCenter.x - scaledRadius},${screenCenter.y}`}\n fill=\"#ff4444\"\n />\n ) : (\n <circle\n cx={screenCenter.x}\n cy={screenCenter.y}\n r={scaledRadius}\n fill=\"none\"\n stroke={isHighlighted ? \"#ff4444\" : \"red\"}\n strokeWidth={\n isHighlighted\n ? Math.max(2, scaledRadius * 0.15)\n : Math.max(1, scaledRadius * 0.1)\n }\n opacity={1}\n />\n )}\n </svg>\n\n <div\n style={{\n position: \"absolute\",\n left: screenCenter.x - (scaledRadius + 10),\n top: screenCenter.y - (scaledRadius + 10),\n width: (scaledRadius + 10) * 2,\n height: (scaledRadius + 10) * 2,\n zIndex: zIndexMap.errorOverlay + 5,\n cursor: \"pointer\",\n borderRadius: \"50%\",\n }}\n onMouseEnter={(e) => {\n const popup = e.currentTarget\n .nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"1\"\n }\n }}\n onMouseLeave={(e) => {\n if (!isHighlighted) {\n const popup = e.currentTarget\n .nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"0\"\n }\n }\n }}\n />\n <div\n style={{\n position: \"absolute\",\n zIndex: isHighlighted\n ? zIndexMap.errorOverlay + 20\n : zIndexMap.errorOverlay + 10,\n left: popupPosition.left,\n top: popupPosition.top,\n color: isHighlighted ? \"#ff4444\" : \"red\",\n textAlign: \"center\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n display:\n isShowingDRCErrors || isHighlighted ? \"flex\" : \"none\",\n flexDirection: \"column\",\n alignItems: \"center\",\n pointerEvents: \"none\",\n transform: popupPosition.transform,\n }}\n >\n <div\n className={`error-message ${errorMessageStyles}`}\n style={{\n opacity: isHighlighted ? 1 : 0,\n border: `1px solid ${isHighlighted ? \"#ff4444\" : \"red\"}`,\n }}\n >\n {el.message}\n </div>\n </div>\n </Fragment>\n )\n })\n })}\n {focusScreenCenter && <FocusMarkerSVG center={focusScreenCenter} />}\n </div>\n )\n}\n","export const getPopupPosition = (\n errorCenter: { x: number; y: number },\n containerRef: React.RefObject<HTMLDivElement | null>,\n) => {\n const container = containerRef.current\n if (!container)\n return {\n transform: \"translate(-50%, -100%)\",\n left: errorCenter.x,\n top: errorCenter.y,\n }\n\n const containerRect = container.getBoundingClientRect()\n const popupWidth = 200\n const margin = 10\n const horizontalOffset = 60\n let transformX = \"-50%\"\n let transformY = \"-100%\"\n let left = errorCenter.x\n let top = errorCenter.y\n\n if (\n errorCenter.x + horizontalOffset + popupWidth <\n containerRect.width - margin\n ) {\n left = errorCenter.x + horizontalOffset\n transformX = \"0%\"\n } else if (errorCenter.x - horizontalOffset - popupWidth > margin) {\n left = errorCenter.x - horizontalOffset\n transformX = \"-100%\"\n } else {\n left = errorCenter.x\n transformX = \"-50%\"\n }\n\n return {\n transform: `translate(${transformX}, ${transformY})`,\n left,\n top,\n }\n}\n","import React from \"react\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\n\nexport const FocusMarkerSVG = ({\n center,\n}: {\n center: { x: number; y: number }\n}) => (\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.errorOverlay + 30,\n }}\n width=\"100%\"\n height=\"100%\"\n >\n <circle\n cx={center.x}\n cy={center.y}\n r={11}\n fill=\"none\"\n stroke=\"#ff6b6b\"\n strokeWidth={2.5}\n opacity={0.95}\n />\n <circle cx={center.x} cy={center.y} r={4.5} fill=\"#ff6b6b\" opacity={0.95} />\n <line\n x1={center.x - 18}\n y1={center.y}\n x2={center.x - 8}\n y2={center.y}\n stroke=\"#ff6b6b\"\n strokeWidth={2}\n />\n <line\n x1={center.x + 8}\n y1={center.y}\n x2={center.x + 18}\n y2={center.y}\n stroke=\"#ff6b6b\"\n strokeWidth={2}\n />\n <line\n x1={center.x}\n y1={center.y - 18}\n x2={center.x}\n y2={center.y - 8}\n stroke=\"#ff6b6b\"\n strokeWidth={2}\n />\n <line\n x1={center.x}\n y1={center.y + 8}\n x2={center.x}\n y2={center.y + 18}\n stroke=\"#ff6b6b\"\n strokeWidth={2}\n />\n </svg>\n)\n","import { pointToSegmentDistance } from \"@tscircuit/math-utils\"\nimport type { AnyCircuitElement, LayerRef } from \"circuit-json\"\nimport { distance } from \"circuit-json\"\nimport type { Primitive } from \"lib/types\"\nimport { ifSetsMatchExactly } from \"lib/util/if-sets-match-exactly\"\nimport type React from \"react\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { applyToPoint, inverse } from \"transformation-matrix\"\nimport {\n BoardAnchorOffsetOverlay,\n ComponentBoundingBoxOverlay,\n GroupAnchorOffsetOverlay,\n PanelAnchorOffsetOverlay,\n} from \"./AnchorOffsetOverlay\"\nimport { ElementOverlayBox } from \"./ElementOverlayBox\"\n\nconst getPolygonBoundingBox = (\n points: ReadonlyArray<{ x: number; y: number }>,\n) => {\n if (points.length === 0) return null\n\n let minX = points[0]!.x\n let minY = points[0]!.y\n let maxX = points[0]!.x\n let maxY = points[0]!.y\n\n for (const point of points) {\n if (point.x < minX) minX = point.x\n if (point.y < minY) minY = point.y\n if (point.x > maxX) maxX = point.x\n if (point.y > maxY) maxY = point.y\n }\n\n return {\n center: {\n x: (minX + maxX) / 2,\n y: (minY + maxY) / 2,\n },\n width: maxX - minX,\n height: maxY - minY,\n }\n}\n\nconst isPointInsidePolygon = (\n point: { x: number; y: number },\n polygon: ReadonlyArray<{ x: number; y: number }>,\n) => {\n if (polygon.length < 3) return false\n\n let isInside = false\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i]!.x\n const yi = polygon[i]!.y\n const xj = polygon[j]!.x\n const yj = polygon[j]!.y\n\n const intersects =\n yi > point.y !== yj > point.y &&\n point.x < ((xj - xi) * (point.y - yi)) / (yj - yi || Number.EPSILON) + xi\n\n if (intersects) {\n isInside = !isInside\n }\n }\n\n return isInside\n}\n\nexport const getPrimitivesUnderPoint = (\n primitives: Primitive[],\n rwPoint: { x: number; y: number },\n transform: Matrix,\n selectedLayer: LayerRef,\n): Primitive[] => {\n const newMousedPrimitives: Primitive[] = []\n\n for (const primitive of primitives) {\n if (!primitive._element) continue\n if (\n primitive._element.type === \"pcb_trace\" &&\n primitive.layer !== selectedLayer\n ) {\n continue\n }\n\n // Handle PCB traces\n if (\"x1\" in primitive && primitive._element?.type === \"pcb_trace\") {\n const distance = pointToSegmentDistance(\n { x: rwPoint.x, y: rwPoint.y },\n { x: primitive.x1, y: primitive.y1 },\n { x: primitive.x2, y: primitive.y2 },\n )\n\n const lineWidth = primitive.width || 0.5\n const detectionThreshold = Math.max(lineWidth * 25, 2) / transform!.a\n\n if (distance < detectionThreshold) {\n newMousedPrimitives.push(primitive)\n }\n continue\n }\n\n if (primitive.pcb_drawing_type === \"polygon\") {\n const points = primitive.points.map((point) => ({\n x: distance.parse(point.x),\n y: distance.parse(point.y),\n }))\n const boundingBox = getPolygonBoundingBox(points)\n if (!boundingBox) continue\n\n if (\n rwPoint.x < boundingBox.center.x - boundingBox.width / 2 ||\n rwPoint.x > boundingBox.center.x + boundingBox.width / 2 ||\n rwPoint.y < boundingBox.center.y - boundingBox.height / 2 ||\n rwPoint.y > boundingBox.center.y + boundingBox.height / 2\n ) {\n continue\n }\n\n if (isPointInsidePolygon(rwPoint, points)) {\n newMousedPrimitives.push(primitive)\n }\n continue\n }\n\n if (primitive.pcb_drawing_type === \"polygon_with_arcs\") {\n const points = primitive.brep_shape.outer_ring.vertices.map((v) => ({\n x: distance.parse(v.x),\n y: distance.parse(v.y),\n }))\n const boundingBox = getPolygonBoundingBox(points)\n if (!boundingBox) continue\n\n if (\n rwPoint.x < boundingBox.center.x - boundingBox.width / 2 ||\n rwPoint.x > boundingBox.center.x + boundingBox.width / 2 ||\n rwPoint.y < boundingBox.center.y - boundingBox.height / 2 ||\n rwPoint.y > boundingBox.center.y + boundingBox.height / 2\n ) {\n continue\n }\n\n if (isPointInsidePolygon(rwPoint, points)) {\n newMousedPrimitives.push(primitive)\n }\n continue\n }\n\n // Handle primitives with x, y coordinates\n if (!(\"x\" in primitive && \"y\" in primitive)) continue\n\n let w = 0\n let h = 0\n\n if (\"w\" in primitive && \"h\" in primitive) {\n w = primitive.w\n h = primitive.h\n } else if (\"r\" in primitive) {\n w = (primitive as any).r * 2\n h = (primitive as any).r * 2\n } else if (\"rX\" in primitive && \"rY\" in primitive) {\n w = primitive.rX * 2\n h = primitive.rY * 2\n } else {\n continue\n }\n\n if (\n Math.abs((primitive as any).x - rwPoint.x) < w / 2 &&\n Math.abs((primitive as any).y - rwPoint.y) < h / 2\n ) {\n newMousedPrimitives.push(primitive)\n }\n }\n\n return newMousedPrimitives\n}\n\nexport const MouseElementTracker = ({\n elements,\n children,\n transform,\n primitives,\n selectedLayer,\n onMouseHoverOverPrimitives,\n}: {\n elements: AnyCircuitElement[]\n children: React.ReactNode\n transform?: Matrix\n primitives: Primitive[]\n selectedLayer: LayerRef\n onMouseHoverOverPrimitives: (primitivesHoveredOver: Primitive[]) => void\n}) => {\n const [mousedPrimitives, setMousedPrimitives] = useState<Primitive[]>([])\n const [mousePos, setMousePos] = useState({ x: 0, y: 0 })\n const [containerRef, { width, height }] = useMeasure<HTMLDivElement>()\n\n useEffect(() => {\n setMousedPrimitives([])\n onMouseHoverOverPrimitives([])\n }, [selectedLayer, onMouseHoverOverPrimitives])\n\n const highlightedPrimitives = useMemo(() => {\n const highlightedPrimitives: HighlightedPrimitive[] = []\n\n for (const primitive of mousedPrimitives) {\n if (primitive._element?.type === \"pcb_via\") continue\n if (primitive._element?.type === \"pcb_component\") continue\n if (primitive?.layer === \"drill\") continue\n if (primitive?.is_hoverable === false) continue\n\n let basePoint: { x: number; y: number } | null = null\n let w = 0\n let h = 0\n\n if (primitive.pcb_drawing_type === \"polygon\") {\n const boundingBox = getPolygonBoundingBox(primitive.points)\n if (!boundingBox) continue\n basePoint = boundingBox.center\n w = boundingBox.width\n h = boundingBox.height\n } else if (primitive.pcb_drawing_type === \"polygon_with_arcs\") {\n const points = primitive.brep_shape.outer_ring.vertices.map((v) => ({\n x: v.x,\n y: v.y,\n }))\n const boundingBox = getPolygonBoundingBox(points)\n if (!boundingBox) continue\n basePoint = boundingBox.center\n w = boundingBox.width\n h = boundingBox.height\n } else if (primitive.pcb_drawing_type === \"line\") {\n basePoint = {\n x: (primitive.x1 + primitive.x2) / 2,\n y: (primitive.y1 + primitive.y2) / 2,\n }\n w = Math.abs(primitive.x2 - primitive.x1)\n h = Math.abs(primitive.y2 - primitive.y1)\n } else if (\"x\" in primitive && \"y\" in primitive) {\n basePoint = { x: primitive.x, y: primitive.y }\n w =\n \"w\" in primitive\n ? primitive.w\n : \"r\" in primitive\n ? primitive.r * 2\n : \"rX\" in primitive && \"rY\" in primitive\n ? primitive.rX * 2\n : 0\n h =\n \"h\" in primitive\n ? primitive.h\n : \"r\" in primitive\n ? primitive.r * 2\n : \"rX\" in primitive && \"rY\" in primitive\n ? primitive.rY * 2\n : 0\n }\n\n if (!basePoint) continue\n\n const screenPos = applyToPoint(transform!, basePoint)\n const screenSize = {\n w: w * transform!.a,\n h: h * transform!.a,\n }\n\n // FANCY: If 2+ highlighted primitives inhabit the same space, give\n // them an incrementing same_space_index\n const same_space_index = highlightedPrimitives.filter(\n (hp) =>\n screenPos.x === hp.screen_x &&\n screenPos.y === hp.screen_y &&\n screenSize.w === hp.screen_w &&\n screenSize.h === hp.screen_h,\n ).length\n\n highlightedPrimitives.push({\n ...(primitive as any),\n x: basePoint.x,\n y: basePoint.y,\n w,\n h,\n screen_x: screenPos.x,\n screen_y: screenPos.y,\n screen_w: screenSize.w,\n screen_h: screenSize.h,\n same_space_index,\n })\n }\n\n return highlightedPrimitives\n }, [mousedPrimitives, transform])\n\n const handleInteraction = (\n x: number,\n y: number,\n transform: Matrix,\n primitives: Primitive[],\n ) => {\n setMousePos({ x, y })\n const rwPoint = applyToPoint(inverse(transform), { x, y })\n const newMousedPrimitives = getPrimitivesUnderPoint(\n primitives,\n rwPoint,\n transform,\n selectedLayer,\n )\n\n if (\n ifSetsMatchExactly(\n new Set(newMousedPrimitives.map((p) => p._pcb_drawing_object_id)),\n new Set(mousedPrimitives.map((p) => p._pcb_drawing_object_id)),\n )\n ) {\n return\n }\n\n setMousedPrimitives(newMousedPrimitives)\n onMouseHoverOverPrimitives(newMousedPrimitives)\n }\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n onMouseMove={(e) => {\n if (transform) {\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n handleInteraction(x, y, transform, primitives)\n }\n }}\n onTouchStart={(e) => {\n if (transform) {\n const touch = e.touches[0]\n const rect = e.currentTarget.getBoundingClientRect()\n const x = touch.clientX - rect.left\n const y = touch.clientY - rect.top\n handleInteraction(x, y, transform, primitives)\n }\n }}\n >\n {children}\n <ElementOverlayBox\n elements={elements}\n mousePos={mousePos}\n highlightedPrimitives={highlightedPrimitives}\n />\n {transform && (\n <>\n <BoardAnchorOffsetOverlay\n elements={elements}\n highlightedPrimitives={highlightedPrimitives}\n transform={transform}\n containerWidth={width}\n containerHeight={height}\n />\n <GroupAnchorOffsetOverlay\n elements={elements}\n highlightedPrimitives={highlightedPrimitives}\n transform={transform}\n containerWidth={width}\n containerHeight={height}\n />\n <ComponentBoundingBoxOverlay\n elements={elements}\n highlightedPrimitives={highlightedPrimitives}\n transform={transform}\n containerWidth={width}\n containerHeight={height}\n />\n <PanelAnchorOffsetOverlay\n elements={elements}\n highlightedPrimitives={highlightedPrimitives}\n transform={transform}\n containerWidth={width}\n containerHeight={height}\n />\n </>\n )}\n </div>\n )\n}\n\nexport type HighlightedPrimitive = {\n _pcb_drawing_object_id: string\n x: number\n y: number\n w: number\n h: number\n same_space_index?: number\n _element: AnyCircuitElement\n _parent_pcb_component?: AnyCircuitElement\n _parent_source_component?: AnyCircuitElement\n _source_port?: AnyCircuitElement\n screen_x: number\n screen_y: number\n screen_w: number\n screen_h: number\n}\n","export function ifSetsMatchExactly(set1: Set<any>, set2: Set<any>) {\n if (set1.size !== set2.size) return false\n return Array.from(set1).every((item) => set2.has(item))\n}\n","import type {\n AnyCircuitElement,\n PcbBoard,\n PcbComponent,\n PcbGroup,\n PcbPanel,\n} from \"circuit-json\"\n\nexport const isPcbComponent = (\n element?: AnyCircuitElement,\n): element is PcbComponent => element?.type === \"pcb_component\"\n\nexport const isPcbGroup = (element?: AnyCircuitElement): element is PcbGroup =>\n element?.type === \"pcb_group\"\n\nexport const isPcbPanel = (element?: AnyCircuitElement): element is PcbPanel =>\n element?.type === \"pcb_panel\"\n\nexport const isPcbBoard = (element?: AnyCircuitElement): element is PcbBoard =>\n element?.type === \"pcb_board\"\n\nexport type BoardAnchoredComponent = PcbComponent & {\n positioned_relative_to_pcb_board_id?: string\n}\n\nexport const isBoardAnchoredComponent = (\n component: PcbComponent,\n): component is BoardAnchoredComponent =>\n \"positioned_relative_to_pcb_board_id\" in component\n","import type { Point } from \"circuit-json\"\nimport type { CSSProperties } from \"react\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { zIndexMap } from \"../../lib/util/z-index-map\"\nimport { COLORS, VISUAL_CONFIG } from \"./common/constants\"\n\nexport interface AnchorOffsetTarget {\n id: string\n anchor: Point\n anchor_id: string\n target: Point\n type: \"component\" | \"group\" | \"board\"\n display_offset_x?: string\n display_offset_y?: string\n}\n\ninterface Props {\n targets: AnchorOffsetTarget[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\nexport const AnchorOffsetOverlay = ({\n targets,\n transform,\n containerWidth,\n containerHeight,\n}: Props) => {\n if (targets.length === 0) return null\n\n const labelStyle: CSSProperties = {\n color: COLORS.LABEL_TEXT,\n mixBlendMode: \"difference\",\n pointerEvents: \"none\",\n fontSize: VISUAL_CONFIG.LABEL_FONT_SIZE,\n fontFamily: \"monospace\",\n fontWeight: \"bold\",\n }\n\n const anchorScreens = new Map<string, Point>()\n targets.forEach((target) => {\n if (!anchorScreens.has(target.anchor_id)) {\n const screenPoint = applyToPoint(transform, target.anchor)\n anchorScreens.set(target.anchor_id, screenPoint)\n }\n })\n\n return (\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: containerWidth,\n height: containerHeight,\n overflow: \"hidden\",\n pointerEvents: \"none\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n }}\n width={containerWidth}\n height={containerHeight}\n >\n {targets.map((target) => {\n const anchorPosition = target.anchor\n const anchorKey = target.anchor_id\n\n const targetCenter = target.target\n\n const anchorMarkerScreen = anchorScreens.get(anchorKey)!\n const targetScreen = applyToPoint(transform, targetCenter)\n\n const offsetX = targetCenter.x - anchorPosition.x\n const offsetY = targetCenter.y - anchorPosition.y\n\n const xLineLength = Math.abs(targetScreen.x - anchorMarkerScreen.x)\n const yLineLength = Math.abs(targetScreen.y - anchorMarkerScreen.y)\n\n const isTargetAboveAnchor = targetScreen.y < anchorMarkerScreen.y\n const isTargetRightOfAnchor = targetScreen.x > anchorMarkerScreen.x\n\n const xLabelOffset = isTargetAboveAnchor\n ? VISUAL_CONFIG.LABEL_OFFSET_ABOVE\n : VISUAL_CONFIG.LABEL_OFFSET_BELOW\n\n const yLabelOffset = isTargetRightOfAnchor\n ? VISUAL_CONFIG.LABEL_OFFSET_RIGHT\n : VISUAL_CONFIG.LABEL_OFFSET_LEFT\n\n const shouldShowXLabel =\n xLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL\n const shouldShowYLabel =\n yLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL\n\n const xLabelText = `${\n target.display_offset_x ?? offsetX.toFixed(2)\n }mm`\n const yLabelText = `${\n target.display_offset_y ?? offsetY.toFixed(2)\n }mm`\n\n return (\n <g key={target.id}>\n <line\n x1={anchorMarkerScreen.x}\n y1={anchorMarkerScreen.y}\n x2={targetScreen.x}\n y2={anchorMarkerScreen.y}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.LINE_STROKE_WIDTH}\n strokeDasharray={VISUAL_CONFIG.LINE_DASH_PATTERN}\n />\n\n <line\n x1={targetScreen.x}\n y1={anchorMarkerScreen.y}\n x2={targetScreen.x}\n y2={targetScreen.y}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.LINE_STROKE_WIDTH}\n strokeDasharray={VISUAL_CONFIG.LINE_DASH_PATTERN}\n />\n\n {target.type === \"component\" || target.type === \"board\" ? (\n <circle\n cx={targetScreen.x}\n cy={targetScreen.y}\n r={VISUAL_CONFIG.COMPONENT_MARKER_RADIUS}\n fill={COLORS.COMPONENT_MARKER_FILL}\n stroke={COLORS.COMPONENT_MARKER_STROKE}\n strokeWidth={1}\n />\n ) : (\n // assumes \"group\"\n <>\n <line\n x1={targetScreen.x - VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n y1={targetScreen.y}\n x2={targetScreen.x + VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n y2={targetScreen.y}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH}\n />\n <line\n x1={targetScreen.x}\n y1={targetScreen.y - VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n x2={targetScreen.x}\n y2={targetScreen.y + VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH}\n />\n </>\n )}\n\n {shouldShowXLabel && (\n <foreignObject\n x={Math.min(anchorMarkerScreen.x, targetScreen.x)}\n y={anchorMarkerScreen.y + xLabelOffset}\n width={Math.abs(targetScreen.x - anchorMarkerScreen.x)}\n height={20}\n style={{ overflow: \"visible\" }}\n >\n <div style={{ ...labelStyle, textAlign: \"center\" }}>\n {xLabelText}\n </div>\n </foreignObject>\n )}\n\n {shouldShowYLabel && (\n <foreignObject\n x={targetScreen.x + yLabelOffset}\n y={Math.min(anchorMarkerScreen.y, targetScreen.y)}\n width={VISUAL_CONFIG.Y_LABEL_MIN_WIDTH}\n height={Math.abs(targetScreen.y - anchorMarkerScreen.y)}\n style={{ overflow: \"visible\" }}\n >\n <div\n style={{\n ...labelStyle,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: isTargetRightOfAnchor\n ? \"flex-start\"\n : \"flex-end\",\n whiteSpace: \"nowrap\",\n padding: \"0 4px\",\n height: \"100%\",\n }}\n >\n {yLabelText}\n </div>\n </foreignObject>\n )}\n </g>\n )\n })}\n\n {Array.from(anchorScreens.entries()).map(([anchorId, anchorScreen]) => (\n <g key={`anchor-${anchorId}`}>\n <line\n x1={anchorScreen.x - VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n y1={anchorScreen.y}\n x2={anchorScreen.x + VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n y2={anchorScreen.y}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH}\n />\n <line\n x1={anchorScreen.x}\n y1={anchorScreen.y - VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n x2={anchorScreen.x}\n y2={anchorScreen.y + VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH}\n />\n </g>\n ))}\n </svg>\n </div>\n )\n}\n","export const VISUAL_CONFIG = {\n GROUP_PADDING: 1,\n MIN_LINE_LENGTH_FOR_LABEL: 40,\n LABEL_OFFSET_ABOVE: 2,\n LABEL_OFFSET_BELOW: -18,\n LABEL_OFFSET_RIGHT: 8,\n LABEL_OFFSET_LEFT: -120,\n Y_LABEL_MIN_WIDTH: 110,\n LINE_STROKE_WIDTH: 1.5,\n LINE_DASH_PATTERN: \"4,4\",\n COMPONENT_MARKER_RADIUS: 3,\n LABEL_FONT_SIZE: 11,\n ANCHOR_MARKER_SIZE: 6,\n ANCHOR_MARKER_STROKE_WIDTH: 1.5,\n} as const\n\nexport const COLORS = {\n OFFSET_LINE: \"white\",\n COMPONENT_MARKER_FILL: \"#66ccff\",\n COMPONENT_MARKER_STROKE: \"white\",\n LABEL_TEXT: \"white\",\n} as const\n","import type {\n AnyCircuitElement,\n PcbBoard,\n PcbComponent,\n PcbGroup,\n} from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../../global-store\"\nimport type { HighlightedPrimitive } from \"../MouseElementTracker\"\nimport { isPcbBoard, isPcbComponent, isPcbGroup } from \"./common/guards\"\nimport {\n type AnchorOffsetTarget,\n AnchorOffsetOverlay,\n} from \"./AnchorOffsetOverlay\"\n\ntype Point = {\n x: number\n y: number\n}\n\ninterface Props {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\nexport const BoardAnchorOffsetOverlay = ({\n elements,\n highlightedPrimitives,\n transform,\n containerWidth,\n containerHeight,\n}: Props) => {\n const boards = elements.filter((el): el is PcbBoard => isPcbBoard(el))\n const components = elements.filter((el): el is PcbComponent =>\n isPcbComponent(el),\n )\n const groups = elements.filter((el): el is PcbGroup => isPcbGroup(el))\n\n const hoveredComponentIds = highlightedPrimitives\n .map((primitive) => {\n if (isPcbComponent(primitive._parent_pcb_component)) {\n return primitive._parent_pcb_component.pcb_component_id\n }\n if (isPcbComponent(primitive._element)) {\n return primitive._element.pcb_component_id\n }\n return null\n })\n .filter((id): id is string => Boolean(id))\n\n // Track hovered groups by checking if any components in the group are hovered\n const hoveredGroupIds = new Set<string>()\n hoveredComponentIds.forEach((componentId) => {\n const component = components.find((c) => c.pcb_component_id === componentId)\n if (component?.pcb_group_id) {\n hoveredGroupIds.add(component.pcb_group_id)\n }\n })\n\n const isShowingAnchorOffsets = useGlobalStore(\n (state) => state.is_showing_group_anchor_offsets,\n )\n\n if (!isShowingAnchorOffsets && hoveredComponentIds.length === 0) {\n return null\n }\n\n // Component-to-board targets\n const componentTargets = components\n .map((component) => {\n const boardId = component.positioned_relative_to_pcb_board_id\n if (!boardId) return null\n\n const board = boards.find((b) => b.pcb_board_id === boardId)\n return board ? { component, board, type: \"component\" as const } : null\n })\n .filter(\n (\n target,\n ): target is {\n component: PcbComponent\n board: PcbBoard\n type: \"component\"\n } => Boolean(target),\n )\n\n // Group-to-board targets\n const groupTargets = groups\n .map((group) => {\n const boardId = group.positioned_relative_to_pcb_board_id\n if (!boardId || !group.center) return null\n\n const board = boards.find((b) => b.pcb_board_id === boardId)\n return board ? { group, board, type: \"group\" as const } : null\n })\n .filter(\n (target): target is { group: PcbGroup; board: PcbBoard; type: \"group\" } =>\n Boolean(target),\n )\n\n const targets = [...componentTargets, ...groupTargets]\n\n if (targets.length === 0) return null\n\n const shouldShowAllTargets = hoveredComponentIds.length === 0\n\n const targetEntries = targets.filter((target) => {\n if (target.type === \"component\") {\n return (\n shouldShowAllTargets ||\n hoveredComponentIds.includes(target.component.pcb_component_id)\n )\n } else {\n // For group targets, show if the group is hovered\n return (\n shouldShowAllTargets || hoveredGroupIds.has(target.group.pcb_group_id)\n )\n }\n })\n\n if (targetEntries.length === 0) return null\n\n const sharedTargets: AnchorOffsetTarget[] = targetEntries\n .map((target): AnchorOffsetTarget | null => {\n if (target.type === \"component\") {\n return {\n id: `${target.board.pcb_board_id}-${target.component.pcb_component_id}-${target.type}`,\n anchor: target.board.center,\n anchor_id: target.board.pcb_board_id,\n target: target.component.center as Point,\n type: \"component\",\n display_offset_x: target.component.display_offset_x,\n display_offset_y: target.component.display_offset_y,\n }\n }\n // group\n return {\n id: `${target.board.pcb_board_id}-${target.group.pcb_group_id}-${target.type}`,\n anchor: target.board.center,\n anchor_id: target.board.pcb_board_id,\n target: {\n x: target.group.anchor_position?.x ?? target.group.center.x,\n y: target.group.anchor_position?.y ?? target.group.center.y,\n },\n type: \"group\",\n display_offset_x: target.group.display_offset_x,\n display_offset_y: target.group.display_offset_y,\n }\n })\n .filter((t): t is AnchorOffsetTarget => Boolean(t))\n\n return (\n <AnchorOffsetOverlay\n targets={sharedTargets}\n transform={transform}\n containerWidth={containerWidth}\n containerHeight={containerHeight}\n />\n )\n}\n","import type { AnyCircuitElement, PcbComponent, PcbGroup } from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../../global-store\"\nimport type { HighlightedPrimitive } from \"../MouseElementTracker\"\nimport { isPcbComponent, isPcbGroup } from \"./common/guards\"\nimport {\n type AnchorOffsetTarget,\n AnchorOffsetOverlay,\n} from \"./AnchorOffsetOverlay\"\n\ntype Point = {\n x: number\n y: number\n}\n\ninterface Props {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\n/**\n * Overlay that shows offsets from group anchors to their components and groups.\n * When the view toggle is on, offsets are always shown. Hover narrows the\n * view to the hovered component/group only, but pads/components still always show.\n */\nexport const GroupAnchorOffsetOverlay = ({\n elements,\n highlightedPrimitives,\n transform,\n containerWidth,\n containerHeight,\n}: Props) => {\n const groups = elements.filter((el): el is PcbGroup => isPcbGroup(el))\n const components = elements.filter((el): el is PcbComponent =>\n isPcbComponent(el),\n )\n\n const hoveredComponentIds = highlightedPrimitives\n .map((primitive) => {\n if (isPcbComponent(primitive._parent_pcb_component)) {\n return primitive._parent_pcb_component.pcb_component_id\n }\n if (isPcbComponent(primitive._element)) {\n return primitive._element.pcb_component_id\n }\n return null\n })\n .filter((id): id is string => Boolean(id))\n\n // Helper function to traverse up the group hierarchy and collect all parent groups\n const collectParentGroups = (groupId: string, collected: Set<string>) => {\n if (collected.has(groupId)) return // Avoid infinite loops\n collected.add(groupId)\n\n const group = groups.find((g) => g.pcb_group_id === groupId)\n if (\n group?.position_mode === \"relative_to_group_anchor\" &&\n group.positioned_relative_to_pcb_group_id\n ) {\n // This group is positioned relative to another group, so add that parent too\n collectParentGroups(group.positioned_relative_to_pcb_group_id, collected)\n }\n }\n\n // Track hovered groups by checking if any components in the group are hovered\n // This includes traversing up the group hierarchy for nested groups\n const hoveredGroupIds = new Set<string>()\n hoveredComponentIds.forEach((componentId) => {\n const component = components.find((c) => c.pcb_component_id === componentId)\n if (!component) return\n\n // If component is directly positioned relative to a group anchor\n if (\n component.position_mode === \"relative_to_group_anchor\" &&\n component.positioned_relative_to_pcb_group_id\n ) {\n collectParentGroups(\n component.positioned_relative_to_pcb_group_id,\n hoveredGroupIds,\n )\n }\n\n // If component belongs to a group (via pcb_group_id)\n if (component.pcb_group_id) {\n collectParentGroups(component.pcb_group_id, hoveredGroupIds)\n }\n })\n\n const isShowingAnchorOffsets = useGlobalStore(\n (s) => s.is_showing_group_anchor_offsets,\n )\n\n if (!isShowingAnchorOffsets && hoveredComponentIds.length === 0) {\n return null\n }\n\n // Component-to-group targets\n const componentTargets = components\n .map((component) => {\n if (\n component.position_mode === \"relative_to_group_anchor\" &&\n component.positioned_relative_to_pcb_group_id\n ) {\n const parentGroup = groups.find(\n (group) =>\n group.pcb_group_id ===\n component.positioned_relative_to_pcb_group_id,\n )\n return parentGroup && parentGroup.anchor_position\n ? { component, parentGroup, type: \"component\" as const }\n : null\n }\n\n if (component.pcb_group_id) {\n const parentGroup = groups.find(\n (group) => group.pcb_group_id === component.pcb_group_id,\n )\n return parentGroup && parentGroup.anchor_position\n ? { component, parentGroup, type: \"component\" as const }\n : null\n }\n\n return null\n })\n .filter(\n (\n target,\n ): target is {\n component: PcbComponent\n parentGroup: PcbGroup\n type: \"component\"\n } => Boolean(target),\n )\n\n // Group-to-group targets (anchor-to-anchor offsets)\n const groupTargets = groups\n .map((group) => {\n if (\n group.position_mode === \"relative_to_group_anchor\" &&\n group.positioned_relative_to_pcb_group_id\n ) {\n const parentGroup = groups.find(\n (g) => g.pcb_group_id === group.positioned_relative_to_pcb_group_id,\n )\n if (\n parentGroup &&\n parentGroup.anchor_position &&\n group.anchor_position\n ) {\n return { group, parentGroup, type: \"group\" as const }\n }\n }\n return null\n })\n .filter(\n (\n target,\n ): target is {\n group: PcbGroup\n parentGroup: PcbGroup\n type: \"group\"\n } => Boolean(target),\n )\n\n const targets = [...componentTargets, ...groupTargets]\n\n if (targets.length === 0) return null\n\n const shouldShowAllTargets = hoveredComponentIds.length === 0\n\n const targetEntries = targets.filter((target) => {\n if (target.type === \"component\") {\n // Only show offset for the specific hovered component, not all components in the group\n return (\n shouldShowAllTargets ||\n hoveredComponentIds.includes(target.component.pcb_component_id)\n )\n } else {\n // For group targets, show if the group or parent group is hovered\n return (\n shouldShowAllTargets ||\n hoveredGroupIds.has(target.group.pcb_group_id) ||\n hoveredGroupIds.has(target.parentGroup.pcb_group_id)\n )\n }\n })\n\n if (targetEntries.length === 0) return null\n\n const sharedTargets: AnchorOffsetTarget[] = targetEntries\n .map((target): AnchorOffsetTarget | null => {\n const anchor = target.parentGroup.anchor_position\n if (!anchor) return null\n\n if (target.type === \"component\") {\n if (!target.component.center) return null\n return {\n id: `${target.parentGroup.pcb_group_id}-${target.component.pcb_component_id}-${target.type}`,\n anchor,\n anchor_id: target.parentGroup.pcb_group_id,\n target: target.component.center,\n type: \"component\",\n display_offset_x: target.component.display_offset_x,\n display_offset_y: target.component.display_offset_y,\n }\n }\n // group - use anchor_position for anchor-to-anchor offsets\n if (!target.group.anchor_position) return null\n return {\n id: `${target.parentGroup.pcb_group_id}-${target.group.pcb_group_id}-${target.type}`,\n anchor,\n anchor_id: target.parentGroup.pcb_group_id,\n target: target.group.anchor_position,\n type: \"group\",\n display_offset_x: target.group.display_offset_x,\n display_offset_y: target.group.display_offset_y,\n }\n })\n .filter((t): t is AnchorOffsetTarget => Boolean(t))\n\n return (\n <AnchorOffsetOverlay\n targets={sharedTargets}\n transform={transform}\n containerWidth={containerWidth}\n containerHeight={containerHeight}\n />\n )\n}\n","import type { AnyCircuitElement, PcbComponent, PcbGroup } from \"circuit-json\"\nimport { getBoundsOfPcbElements, su } from \"@tscircuit/circuit-json-util\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { zIndexMap } from \"../../lib/util/z-index-map\"\nimport type { HighlightedPrimitive } from \"../MouseElementTracker\"\nimport { COLORS, VISUAL_CONFIG } from \"./common/constants\"\nimport { isPcbComponent } from \"./common/guards\"\n\ninterface Props {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\nconst calculateComponentBoundingBox = (\n component: PcbComponent,\n elements: AnyCircuitElement[],\n): { minX: number; maxX: number; minY: number; maxY: number } | null => {\n const componentId = component.pcb_component_id\n const padsAndHoles = elements.filter(\n (el) =>\n ((el.type === \"pcb_smtpad\" || el.type === \"pcb_plated_hole\") &&\n el.pcb_component_id === componentId) ||\n (el.type === \"pcb_hole\" && (el as any).pcb_component_id === componentId),\n )\n\n if (padsAndHoles.length === 0) {\n return getBoundsOfPcbElements([component])\n }\n\n return getBoundsOfPcbElements(padsAndHoles)\n}\n\nexport const ComponentBoundingBoxOverlay = ({\n elements,\n highlightedPrimitives,\n transform,\n containerWidth,\n containerHeight,\n}: Props) => {\n const hoveredComponents = new Map<string, PcbComponent>()\n for (const primitive of highlightedPrimitives) {\n if (isPcbComponent(primitive._parent_pcb_component)) {\n hoveredComponents.set(\n primitive._parent_pcb_component.pcb_component_id,\n primitive._parent_pcb_component,\n )\n }\n if (isPcbComponent(primitive._element)) {\n hoveredComponents.set(\n primitive._element.pcb_component_id,\n primitive._element,\n )\n }\n }\n\n if (hoveredComponents.size === 0) return null\n\n const renderData: Array<{\n component: PcbComponent\n bbox: { minX: number; maxX: number; minY: number; maxY: number }\n group: PcbGroup | null\n }> = []\n\n for (const component of hoveredComponents.values()) {\n const bbox = calculateComponentBoundingBox(component, elements)\n if (!bbox) continue\n\n const groupId =\n component.positioned_relative_to_pcb_group_id ?? component.pcb_group_id\n const group = groupId\n ? (su(elements).pcb_group.get(groupId) as PcbGroup | null)\n : null\n\n renderData.push({ component, bbox, group })\n }\n\n if (renderData.length === 0) return null\n\n return (\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: containerWidth,\n height: containerHeight,\n overflow: \"hidden\",\n pointerEvents: \"none\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n <svg\n style={{ position: \"absolute\", left: 0, top: 0, pointerEvents: \"none\" }}\n width={containerWidth}\n height={containerHeight}\n >\n {renderData.map(({ component, bbox, group }) => {\n const topLeft = applyToPoint(transform, {\n x: bbox.minX,\n y: bbox.maxY,\n })\n const bottomRight = applyToPoint(transform, {\n x: bbox.maxX,\n y: bbox.minY,\n })\n\n const screenBbox = {\n x: Math.min(topLeft.x, bottomRight.x),\n y: Math.min(topLeft.y, bottomRight.y),\n width: Math.abs(bottomRight.x - topLeft.x),\n height: Math.abs(bottomRight.y - topLeft.y),\n }\n\n const componentCenter = component.center ?? {\n x: (bbox.minX + bbox.maxX) / 2,\n y: (bbox.minY + bbox.maxY) / 2,\n }\n const componentCenterScreen = applyToPoint(transform, componentCenter)\n\n return (\n <g key={component.pcb_component_id}>\n <rect\n x={screenBbox.x}\n y={screenBbox.y}\n width={screenBbox.width}\n height={screenBbox.height}\n fill=\"none\"\n stroke=\"white\"\n strokeWidth={1.5}\n strokeDasharray=\"4,4\"\n />\n\n <line\n x1={componentCenterScreen.x - 6}\n y1={componentCenterScreen.y}\n x2={componentCenterScreen.x + 6}\n y2={componentCenterScreen.y}\n stroke={COLORS.COMPONENT_MARKER_STROKE}\n strokeWidth={1.5}\n />\n <line\n x1={componentCenterScreen.x}\n y1={componentCenterScreen.y - 6}\n x2={componentCenterScreen.x}\n y2={componentCenterScreen.y + 6}\n stroke={COLORS.COMPONENT_MARKER_STROKE}\n strokeWidth={1.5}\n />\n <circle\n cx={componentCenterScreen.x}\n cy={componentCenterScreen.y}\n r={VISUAL_CONFIG.COMPONENT_MARKER_RADIUS}\n fill={COLORS.COMPONENT_MARKER_FILL}\n stroke={COLORS.COMPONENT_MARKER_STROKE}\n strokeWidth={1}\n />\n </g>\n )\n })}\n </svg>\n </div>\n )\n}\n","import type { AnyCircuitElement, PcbPanel, PcbBoard, Point } from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../../global-store\"\nimport type { HighlightedPrimitive } from \"../MouseElementTracker\"\nimport { isPcbPanel, isPcbBoard } from \"./common/guards\"\nimport {\n type AnchorOffsetTarget,\n AnchorOffsetOverlay,\n} from \"./AnchorOffsetOverlay\"\n\ninterface PanelAnchorOffsetOverlayProps {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\nexport const PanelAnchorOffsetOverlay = ({\n elements,\n highlightedPrimitives,\n transform,\n containerWidth,\n containerHeight,\n}: PanelAnchorOffsetOverlayProps) => {\n const panels = elements.filter((el): el is PcbPanel => isPcbPanel(el))\n const boards = elements.filter((el): el is PcbBoard => isPcbBoard(el))\n\n const hoveredBoardIds = highlightedPrimitives\n .map((primitive) => {\n if (isPcbBoard(primitive._element)) {\n return primitive._element.pcb_board_id\n }\n return null\n })\n .filter((id): id is string => Boolean(id))\n\n const isShowingAnchorOffsets = useGlobalStore(\n (state) => state.is_showing_group_anchor_offsets,\n )\n\n if (!isShowingAnchorOffsets && hoveredBoardIds.length === 0) {\n return null\n }\n\n // Board-to-panel targets\n const boardTargets = boards\n .map((board) => {\n const panelId = board.pcb_panel_id\n const positionMode = board.position_mode\n if (!panelId || positionMode !== \"relative_to_panel_anchor\") return null\n\n const panel = panels.find((p) => p.pcb_panel_id === panelId)\n return panel ? { board, panel, type: \"board\" as const } : null\n })\n .filter(\n (\n target,\n ): target is {\n board: PcbBoard\n panel: PcbPanel\n type: \"board\"\n } => Boolean(target),\n )\n\n if (boardTargets.length === 0) return null\n\n const shouldShowAllTargets = hoveredBoardIds.length === 0\n\n const targetEntries = boardTargets.filter((target) => {\n return (\n shouldShowAllTargets ||\n hoveredBoardIds.includes(target.board.pcb_board_id)\n )\n })\n\n if (targetEntries.length === 0) return null\n\n const sharedTargets: AnchorOffsetTarget[] = targetEntries\n .map((target): AnchorOffsetTarget | null => {\n if (!target.board.center) return null\n return {\n id: `${target.panel.pcb_panel_id}-${target.board.pcb_board_id}-${target.type}`,\n anchor: target.panel.center,\n anchor_id: target.panel.pcb_panel_id,\n target: target.board.center,\n type: \"board\",\n display_offset_x: target.board.display_offset_x,\n display_offset_y: target.board.display_offset_y,\n }\n })\n .filter((t): t is AnchorOffsetTarget => Boolean(t))\n\n return (\n <AnchorOffsetOverlay\n targets={sharedTargets}\n transform={transform}\n containerWidth={containerWidth}\n containerHeight={containerHeight}\n />\n )\n}\n","import { su } from \"@tscircuit/circuit-json-util\"\nimport type { AnyCircuitElement, PcbTrace } from \"circuit-json\"\n\ninterface TraceTextContext {\n primitiveElement: PcbTrace\n elements: AnyCircuitElement[]\n}\n\ninterface TraceOverlayInfo {\n text: string\n name: string | null\n isOverLength: boolean\n}\n\nconst getNonEmptyName = (name?: string) => name?.trim() || null\n\nexport function getAssociatedTraceName({\n primitiveElement,\n elements,\n}: TraceTextContext): string | null {\n const sourceElementId = primitiveElement.source_trace_id\n if (!sourceElementId) return null\n\n const circuitJson = su(elements)\n const sourceTrace = circuitJson.source_trace.get(sourceElementId)\n\n const sourceTraceName = getNonEmptyName(sourceTrace?.name)\n if (sourceTraceName) return sourceTraceName\n\n const sourceNet = circuitJson.source_net.get(sourceElementId)\n const sourceNetName = getNonEmptyName(sourceNet?.name)\n if (sourceNetName) return sourceNetName\n\n for (const sourceNetId of sourceTrace?.connected_source_net_ids ?? []) {\n const connectedSourceNetName = getNonEmptyName(\n circuitJson.source_net.get(sourceNetId)?.name,\n )\n if (connectedSourceNetName) return connectedSourceNetName\n }\n\n return null\n}\n\nexport function getTraceOverlayInfo({\n primitiveElement,\n elements,\n}: TraceTextContext): TraceOverlayInfo | null {\n const trace = su(elements).source_trace.get(\n primitiveElement?.source_trace_id!,\n )\n const traceLength = primitiveElement.trace_length\n const hasTraceLength = typeof traceLength === \"number\"\n const maxLength = trace?.max_length\n const text = hasTraceLength\n ? `${traceLength.toFixed(3)}${\n typeof maxLength === \"number\" ? ` / ${maxLength}` : \"\"\n } mm`\n : \"\"\n const name =\n getAssociatedTraceName({ primitiveElement, elements }) ??\n getNonEmptyName(trace?.display_name)\n\n if (!text && !name) return null\n\n const isOverLength = Boolean(\n hasTraceLength && typeof maxLength === \"number\" && traceLength > maxLength,\n )\n\n return {\n text,\n name,\n isOverLength,\n }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport type { HighlightedPrimitive } from \"../components/MouseElementTracker\"\nimport { getAssociatedTraceName } from \"./get-trace-overlay-text\"\n\nexport function filterTracesIfMultiple(filterTraces: {\n primitives: HighlightedPrimitive[]\n is_showing_multiple_traces_length: boolean\n elements: AnyCircuitElement[]\n}): HighlightedPrimitive[] {\n const { primitives, is_showing_multiple_traces_length, elements } =\n filterTraces\n\n // Filter traces to get only PCB traces\n const traces = primitives.filter(\n (\n p,\n ): p is HighlightedPrimitive & {\n _element: {\n type: \"pcb_trace\"\n trace_length?: number\n }\n } => p._element.type === \"pcb_trace\",\n )\n\n // Find all source traces\n const sourceTraces = elements.filter((e) => e.type === \"source_trace\")\n\n // Get non-trace primitives\n const nonTraces = primitives.filter((p) => p._element.type !== \"pcb_trace\")\n\n // Named traces and nets should always have a hover label, even when the\n // viewer is configured to hide ordinary trace-length overlays.\n const tracesWithPersistentOverlay = traces.filter((trace) => {\n const hasMaxLength = sourceTraces.some(\n (sourceTrace) =>\n trace._element.source_trace_id === sourceTrace.source_trace_id &&\n sourceTrace.max_length !== undefined,\n )\n\n return (\n hasMaxLength ||\n getAssociatedTraceName({\n primitiveElement: trace._element,\n elements,\n }) !== null\n )\n })\n\n // If not showing multiple trace lengths, keep only overlays that carry\n // important metadata (a configured max length or a source name).\n if (!is_showing_multiple_traces_length) {\n return [...nonTraces, ...tracesWithPersistentOverlay]\n }\n\n // If multiple traces exist, return only the shortest one\n if (traces.length > 1) {\n const shortestTrace = traces.reduce((shortest, current) => {\n const shortestLength = shortest._element.trace_length\n const currentLength = current._element.trace_length\n return currentLength! < shortestLength! ? current : shortest\n }, traces[0])\n\n return [...nonTraces, shortestTrace]\n }\n\n return primitives\n}\n","import type {\n AnyCircuitElement,\n PcbPlatedHoleOval,\n PcbSmtPadRotatedPill,\n} from \"circuit-json\"\nimport { filterTracesIfMultiple } from \"lib/filter-traces-if-multiple\"\nimport { getTraceOverlayInfo } from \"lib/get-trace-overlay-text\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport React, { useEffect, useState } from \"react\"\nimport { useGlobalStore } from \"../global-store\"\nimport type { HighlightedPrimitive } from \"./MouseElementTracker\"\n\nconst containerStyle = {\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n color: \"red\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n textShadow: \"0 0 2px black\",\n} as const\n\nexport const getTextForHighlightedPrimitive = (\n prim: HighlightedPrimitive,\n): string => {\n const {\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n } = prim\n switch (element.type) {\n case \"pcb_trace\": {\n if (element.trace_length) {\n return `${element.trace_length.toFixed(3)}`\n }\n return \"\"\n }\n case \"pcb_smtpad\":\n case \"pcb_plated_hole\": {\n const selectors: string[] = []\n\n const port_hints = Array.from(\n new Set(\n (element.port_hints ?? []).concat(\n (_source_port as any)?.port_hints ?? [],\n ),\n ),\n )\n .filter((ph) => !/^[0-9]+$/.test(ph))\n .filter((ph) => !ph.includes(\"unnamed_\"))\n // reverse alphabetical order\n .sort((a, b) => b.localeCompare(a))\n\n const parentName =\n _parent_source_component &&\n \"name\" in _parent_source_component &&\n _parent_source_component.name &&\n !_parent_source_component.name.includes(\"unnamed_\")\n ? _parent_source_component.name\n : null\n\n if (port_hints.length > 0) {\n if (parentName) {\n selectors.push(\n ...port_hints.map((ph: string) => `${parentName}.${ph}`),\n )\n } else {\n selectors.push(...port_hints)\n }\n } else if (parentName) {\n selectors.push(parentName)\n }\n\n return selectors.join(\", \")\n }\n default: {\n return \"\"\n }\n }\n}\n\nconst layerColorHightlightMap = {\n top: \"red\",\n bottom: \"aqua\",\n}\n\nexport const HighlightedPrimitiveBoxWithText = ({\n primitive,\n mousePos,\n elements,\n}: {\n elements: AnyCircuitElement[]\n primitive: HighlightedPrimitive\n mousePos: { x: number; y: number }\n}) => {\n const [finalState, setFinalState] = useState(false)\n const primitiveElement = primitive._element\n\n useEffect(() => {\n setTimeout(() => {\n setFinalState(true)\n }, 100)\n }, [])\n\n const [x, y, w, h] = [\n primitive.screen_x,\n primitive.screen_y,\n primitive.screen_w,\n primitive.screen_h,\n ]\n\n const si = primitive.same_space_index ?? 0\n const sip = 26\n\n const color: string =\n layerColorHightlightMap[\n (primitive as any)?._element\n ?.layer as keyof typeof layerColorHightlightMap\n ] ?? \"red\"\n\n // Check for rotation on the parent PCB component\n let rotation = 0\n if (\n primitiveElement.type === \"pcb_smtpad\" &&\n primitiveElement?.shape === \"rotated_rect\"\n ) {\n rotation = primitiveElement?.ccw_rotation ?? 0\n } else if (\n primitiveElement.type === \"pcb_smtpad\" &&\n (primitiveElement?.shape === \"pill\" ||\n primitiveElement?.shape === \"rotated_pill\") &&\n \"ccw_rotation\" in primitive\n ) {\n rotation = (primitiveElement as PcbSmtPadRotatedPill).ccw_rotation ?? 0\n } else if (\n primitiveElement.type === \"pcb_plated_hole\" &&\n (primitiveElement?.shape === \"pill\" ||\n primitiveElement?.shape === \"oval\") &&\n \"ccw_rotation\" in primitive\n ) {\n rotation = (primitiveElement as PcbPlatedHoleOval).ccw_rotation ?? 0\n }\n // In HighlightedPrimitiveBoxWithText component\n if (primitiveElement.type === \"pcb_trace\") {\n const traceTextContext = { primitiveElement, elements }\n const overlayInfo = getTraceOverlayInfo(traceTextContext)\n if (!overlayInfo) return null\n\n return (\n <div\n style={{\n zIndex: zIndexMap.elementOverlay,\n position: \"absolute\",\n left: mousePos.x + 12,\n top: mousePos.y + 12,\n color,\n pointerEvents: \"none\",\n }}\n >\n <div\n style={{\n backgroundColor: \"#f2efcc\",\n color: overlayInfo.isOverLength ? \"red\" : \"black\",\n textShadow: \"none\",\n WebkitFontSmoothing: \"antialiased\",\n MozOsxFontSmoothing: \"grayscale\",\n padding: \"4px 6px\",\n borderRadius: \"4px\",\n fontSize: \"11px\",\n lineHeight: 1.2,\n textAlign: \"left\",\n whiteSpace: \"nowrap\",\n }}\n >\n {overlayInfo.text && <div>{overlayInfo.text}</div>}\n {overlayInfo.name && (\n <div\n style={{\n marginTop: overlayInfo.text ? \"2px\" : 0,\n }}\n >\n {overlayInfo.name}\n </div>\n )}\n </div>\n </div>\n )\n }\n\n const label = getTextForHighlightedPrimitive(primitive)\n if (label.trim().length === 0) {\n return null\n }\n\n return (\n <div\n style={{\n zIndex: zIndexMap.elementOverlay,\n position: \"absolute\",\n left: x - w / 2 - 8,\n top: y - h / 2 - 8,\n width: w + 16,\n height: h + 16,\n color,\n transform: `rotate(${-rotation}deg)`,\n transformOrigin: \"center center\",\n }}\n >\n <div\n style={{\n // width: finalState ? `${100 + 20 * si}%` : \"100%\",\n // height: finalState ? `${100 + 20 * si}%` : \"100%\",\n // marginLeft: finalState ? `${-10 * si}%` : 0,\n // marginTop: finalState ? `${-10 * si}%` : 0,\n width: finalState ? `calc(100% + ${sip * 2 * si}px)` : \"100%\",\n height: finalState ? `calc(100% + ${sip * 2 * si}px)` : \"100%\",\n marginLeft: finalState ? `${-sip * si}px` : 0,\n marginTop: finalState ? `${-sip * si}px` : 0,\n border: `1px solid ${color}`,\n opacity: finalState ? 1 : si === 0 ? 1 : 0,\n transition:\n \"width 0.2s, height 0.2s, margin-left 0.2s, margin-top 0.2s, opacity 0.2s\",\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: h + 20 + sip * si,\n marginRight: finalState ? `${-sip * si}px` : 0,\n marginBottom: finalState ? 0 : -sip * si,\n transition: \"margin-right 0.2s, margin-bottom 0.2s\",\n backgroundColor: \"#f2efcc\",\n color: \"black\",\n textShadow: \"none\",\n WebkitFontSmoothing: \"antialiased\",\n MozOsxFontSmoothing: \"grayscale\",\n padding: \"6px 6px\",\n borderRadius: \"6px\",\n fontSize: \"14px\",\n transform: `rotate(${rotation}deg)`,\n minWidth: \"45px\",\n textAlign: \"center\",\n }}\n >\n {label}\n </div>\n </div>\n </div>\n )\n}\n\nexport const ElementOverlayBox = ({\n highlightedPrimitives,\n mousePos,\n elements,\n}: {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n mousePos: { x: number; y: number }\n}) => {\n const [is_moving_component, is_showing_multiple_traces_length] =\n useGlobalStore((s) => [\n s.is_moving_component,\n s.is_showing_multiple_traces_length,\n ])\n const hasSmtPadAndTrace =\n highlightedPrimitives.some((p) => p._element.type === \"pcb_smtpad\") &&\n highlightedPrimitives.some((p) => p._element.type === \"pcb_trace\")\n\n let primitives = highlightedPrimitives\n // If both smtpad and trace are present, only return smtpads\n if (hasSmtPadAndTrace) {\n primitives = primitives.filter((p) => p._element.type === \"pcb_smtpad\")\n }\n // When having multiple traces filter traces to get only the shortest one\n primitives = filterTracesIfMultiple({\n primitives,\n is_showing_multiple_traces_length,\n elements,\n })\n\n return (\n <div style={containerStyle}>\n {!is_moving_component &&\n primitives.map((primitive) => (\n <HighlightedPrimitiveBoxWithText\n key={primitive._pcb_drawing_object_id}\n primitive={primitive}\n mousePos={mousePos}\n elements={elements}\n />\n ))}\n </div>\n )\n}\n","import type {\n AnyCircuitElement,\n PcbComponent,\n PcbGroup,\n SourceGroup,\n} from \"circuit-json\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { identity } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\nimport { useRef, useEffect } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport { zIndexMap } from \"../lib/util/z-index-map\"\n\ninterface Props {\n transform?: Matrix\n elements: AnyCircuitElement[]\n children: any\n hoveredComponentIds?: string[]\n}\n\nconst GROUP_COLORS = [\n \"rgb(255, 100, 100)\",\n \"rgb(100, 255, 100)\",\n \"rgb(100, 100, 255)\",\n \"rgb(255, 255, 100)\",\n \"rgb(255, 100, 255)\",\n \"rgb(100, 255, 255)\",\n \"rgb(255, 150, 100)\",\n \"rgb(150, 100, 255)\",\n \"rgb(100, 255, 150)\",\n \"rgb(255, 100, 150)\",\n]\n\nexport const PcbGroupOverlay = ({\n children,\n transform = identity(),\n elements = [],\n hoveredComponentIds = [],\n}: Props) => {\n const [containerRef, { width, height }] = useMeasure<HTMLDivElement>()\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const {\n is_showing_pcb_groups,\n pcb_group_view_mode,\n is_showing_group_anchor_offsets,\n } = useGlobalStore((s) => ({\n is_showing_pcb_groups: s.is_showing_pcb_groups,\n pcb_group_view_mode: s.pcb_group_view_mode,\n is_showing_group_anchor_offsets: s.is_showing_group_anchor_offsets,\n }))\n\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas || !width || !height) return\n\n canvas.width = width\n canvas.height = height\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n\n ctx.clearRect(0, 0, width, height)\n\n if (!is_showing_pcb_groups) return\n\n const pcbGroups = elements.filter(\n (el): el is PcbGroup => el.type === \"pcb_group\",\n ) as PcbGroup[]\n\n const pcbComponents = elements.filter(\n (el): el is PcbComponent => el.type === \"pcb_component\",\n ) as PcbComponent[]\n\n const sourceGroups = elements.filter(\n (el): el is SourceGroup => el.type === \"source_group\",\n ) as SourceGroup[]\n\n const sourceGroupById = new Map(\n sourceGroups.map((group) => [group.source_group_id, group]),\n )\n\n const visiblePcbGroups = pcbGroups.filter((group) => {\n if (group.name?.toLowerCase().includes(\"subpanel\")) {\n return false\n }\n\n if (pcb_group_view_mode === \"all\") return true\n if (!group.source_group_id) return false\n const sourceGroup = sourceGroupById.get(group.source_group_id)\n if (!sourceGroup) return false\n return sourceGroup.was_automatically_named !== true\n })\n\n const sourceGroupHierarchy = new Map<string, string[]>()\n sourceGroups.forEach((group) => {\n const groupWithParent = group as any\n if (groupWithParent.parent_source_group_id) {\n const children =\n sourceGroupHierarchy.get(groupWithParent.parent_source_group_id) || []\n children.push(group.source_group_id)\n sourceGroupHierarchy.set(\n groupWithParent.parent_source_group_id,\n children,\n )\n }\n })\n\n const getAllDescendantSourceGroups = (sourceGroupId: string): string[] => {\n const descendants: string[] = []\n const children = sourceGroupHierarchy.get(sourceGroupId) || []\n\n for (const child of children) {\n descendants.push(child)\n descendants.push(...getAllDescendantSourceGroups(child))\n }\n\n return descendants\n }\n\n const getGroupDepthLevel = (sourceGroupId: string): number => {\n const groupWithParent = sourceGroups.find(\n (g) => g.source_group_id === sourceGroupId,\n ) as any\n if (!groupWithParent?.parent_source_group_id) {\n return 0\n }\n return 1 + getGroupDepthLevel(groupWithParent.parent_source_group_id)\n }\n\n const hoveredGroupIds = new Set<string>()\n if (hoveredComponentIds.length > 0) {\n for (const comp of pcbComponents) {\n if (!hoveredComponentIds.includes(comp.pcb_component_id)) continue\n const targetGroupId =\n comp.positioned_relative_to_pcb_group_id ?? comp.pcb_group_id\n if (targetGroupId) hoveredGroupIds.add(targetGroupId)\n }\n }\n\n visiblePcbGroups.forEach((group, groupIndex) => {\n let groupComponents = pcbComponents.filter(\n (comp) => comp.pcb_group_id === group.pcb_group_id,\n )\n\n if (group.source_group_id) {\n const descendantSourceGroups = getAllDescendantSourceGroups(\n group.source_group_id,\n )\n\n const childPcbGroups = pcbGroups.filter(\n (pcbGroup) =>\n pcbGroup.source_group_id &&\n descendantSourceGroups.includes(pcbGroup.source_group_id),\n )\n\n for (const childPcbGroup of childPcbGroups) {\n const childComponents = pcbComponents.filter(\n (comp) => comp.pcb_group_id === childPcbGroup.pcb_group_id,\n )\n groupComponents = [...groupComponents, ...childComponents]\n }\n }\n\n let minX: number, minY: number, maxX: number, maxY: number\n let isExplicitlySized = false\n\n if (group.center && group.width && group.height) {\n isExplicitlySized = true\n const halfWidth = group.width / 2\n const halfHeight = group.height / 2\n minX = group.center.x - halfWidth\n maxX = group.center.x + halfWidth\n minY = group.center.y - halfHeight\n maxY = group.center.y + halfHeight\n } else {\n if (groupComponents.length === 0) return\n\n minX = Infinity\n minY = Infinity\n maxX = -Infinity\n maxY = -Infinity\n\n groupComponents.forEach((comp) => {\n if (\n comp.center &&\n typeof comp.width === \"number\" &&\n typeof comp.height === \"number\"\n ) {\n const left = comp.center.x - comp.width / 2\n const right = comp.center.x + comp.width / 2\n const top = comp.center.y + comp.height / 2\n const bottom = comp.center.y - comp.height / 2\n\n minX = Math.min(minX, left)\n maxX = Math.max(maxX, right)\n minY = Math.min(minY, bottom)\n maxY = Math.max(maxY, top)\n }\n })\n\n if (minX === Infinity || maxX === -Infinity) return\n }\n\n const depthLevel = group.source_group_id\n ? getGroupDepthLevel(group.source_group_id)\n : 0\n const hasChildren = group.source_group_id\n ? getAllDescendantSourceGroups(group.source_group_id).length > 0\n : false\n\n if (!isExplicitlySized) {\n const basePadding = 1\n const hierarchyPadding = hasChildren ? 0.5 : 0\n const totalPadding = basePadding + hierarchyPadding\n\n minX -= totalPadding\n maxX += totalPadding\n minY -= totalPadding\n maxY += totalPadding\n }\n\n const topLeft = applyToPoint(transform, { x: minX, y: maxY })\n const topRight = applyToPoint(transform, { x: maxX, y: maxY })\n const bottomLeft = applyToPoint(transform, { x: minX, y: minY })\n const bottomRight = applyToPoint(transform, { x: maxX, y: minY })\n\n const groupColor = GROUP_COLORS[groupIndex % GROUP_COLORS.length]\n ctx.strokeStyle = groupColor\n\n ctx.lineWidth = 2\n\n const baseDashSize = Math.max(4, Math.min(12, 8 * Math.abs(transform.a)))\n const baseGapSize = Math.max(2, Math.min(6, 4 * Math.abs(transform.a)))\n const dashMultiplier = hasChildren ? 1.3 : 1\n const dashSize = baseDashSize * dashMultiplier\n const gapSize = baseGapSize\n ctx.setLineDash([dashSize, gapSize])\n\n ctx.beginPath()\n ctx.moveTo(topLeft.x, topLeft.y)\n ctx.lineTo(topRight.x, topRight.y)\n ctx.lineTo(bottomRight.x, bottomRight.y)\n ctx.lineTo(bottomLeft.x, bottomLeft.y)\n ctx.closePath()\n ctx.stroke()\n\n const baseFontSize = Math.max(8, Math.min(12, 10 * Math.abs(transform.a)))\n const fontSizeReduction =\n depthLevel == 0 || depthLevel == 1 ? 0 : depthLevel * 0.11\n const fontSize = baseFontSize * (1 - fontSizeReduction)\n const labelPadding = 4\n\n const labelText = group.name || `Group ${groupIndex + 1}`\n\n ctx.font = `${fontSize}px sans-serif`\n ctx.setLineDash([])\n\n const labelMetrics = ctx.measureText(labelText)\n const labelWidth = labelMetrics.width + labelPadding * 2\n const labelHeight = fontSize + labelPadding * 2\n\n const labelX = topLeft.x - 5\n const labelY = topLeft.y - 5\n\n const borderRadius = 3\n ctx.fillStyle = \"rgba(0, 0, 0, 0.8)\"\n ctx.beginPath()\n ctx.roundRect(\n labelX,\n labelY - labelHeight,\n labelWidth,\n labelHeight,\n borderRadius,\n )\n ctx.fill()\n\n ctx.fillStyle = groupColor\n ctx.textAlign = \"left\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(labelText, labelX + labelPadding, labelY - labelHeight / 2)\n\n const shouldShowAnchorMarker =\n is_showing_group_anchor_offsets &&\n hoveredGroupIds.has(group.pcb_group_id) &&\n Boolean(group.anchor_position)\n\n if (shouldShowAnchorMarker && group.anchor_position) {\n const anchorPositionValue = Array.isArray(group.anchor_position)\n ? {\n x: group.anchor_position[0] ?? 0,\n y: group.anchor_position[1] ?? 0,\n }\n : { x: group.anchor_position.x, y: group.anchor_position.y }\n const anchorScreenPos = applyToPoint(transform, anchorPositionValue)\n\n // Draw a simple \"+\" symbol\n ctx.strokeStyle = \"white\"\n ctx.lineWidth = 1.5\n ctx.setLineDash([])\n\n const plusSize = Math.max(4, Math.min(8, 6 * Math.abs(transform.a)))\n\n // Draw horizontal line of \"+\"\n ctx.beginPath()\n ctx.moveTo(anchorScreenPos.x - plusSize, anchorScreenPos.y)\n ctx.lineTo(anchorScreenPos.x + plusSize, anchorScreenPos.y)\n ctx.stroke()\n\n // Draw vertical line of \"+\"\n ctx.beginPath()\n ctx.moveTo(anchorScreenPos.x, anchorScreenPos.y - plusSize)\n ctx.lineTo(anchorScreenPos.x, anchorScreenPos.y + plusSize)\n ctx.stroke()\n }\n })\n }, [\n elements,\n transform,\n width,\n height,\n is_showing_pcb_groups,\n pcb_group_view_mode,\n is_showing_group_anchor_offsets,\n hoveredComponentIds,\n ])\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n >\n {children}\n <canvas\n ref={canvasRef}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n pointerEvents: \"none\",\n zIndex: zIndexMap.pcbGroupOverlay,\n display: is_showing_pcb_groups ? \"block\" : \"none\",\n }}\n />\n </div>\n )\n}\n","import { type Matrix, applyToPoint, identity } from \"transformation-matrix\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport { su } from \"@tscircuit/circuit-json-util\"\nimport { useGlobalStore } from \"../global-store\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { getFullConnectivityMapFromCircuitJson } from \"circuit-json-to-connectivity-map\"\nimport { useMemo } from \"react\"\n\ninterface Props {\n transform?: Matrix\n soup?: AnyCircuitElement[]\n children: any\n}\n\ntype Point = { x: number; y: number }\ntype RatsNestLine = {\n key: string\n startPoint: Point\n endPoint: Point\n isInNet: boolean\n}\n\nexport const RatsNestOverlay = ({ transform, soup, children }: Props) => {\n const isShowingRatsNest = useGlobalStore((s) => s.is_showing_rats_nest)\n\n const { netMap, idToNetMap } = useMemo(\n () => getFullConnectivityMapFromCircuitJson(soup || []),\n [soup],\n )\n\n const ratsNestLines = useMemo(() => {\n if (!soup || !isShowingRatsNest) return []\n\n const getElementPosition = (id: string): Point | null => {\n // @ts-ignore\n const element = su(soup)[id.replace(/_\\d+$/, \"\")].get(id)\n if (element && \"x\" in element && \"y\" in element) {\n return { x: element.x, y: element.y }\n }\n return null\n }\n\n const findNearestPointInNet = (\n sourcePoint: Point,\n netId: string,\n ): Point | null => {\n const connectedIds = netMap[netId] || []\n let nearestPoint: Point | null = null\n let minDistance = Infinity\n\n connectedIds.forEach((id) => {\n const pos = getElementPosition(id)\n if (pos) {\n const distance = Math.sqrt(\n (sourcePoint.x - pos.x) ** 2 + (sourcePoint.y - pos.y) ** 2,\n )\n if (distance < minDistance && distance > 0) {\n minDistance = distance\n nearestPoint = pos\n }\n }\n })\n\n return nearestPoint\n }\n\n const pcbPorts = su(soup).pcb_port.list()\n const sourceTraces = su(soup).source_trace.list()\n const lines: RatsNestLine[] = []\n\n pcbPorts.forEach((port, index) => {\n const netId = idToNetMap[port.pcb_port_id]\n\n let isInNet = false\n\n for (const trace of sourceTraces) {\n const sourceTrace = trace.connected_source_port_ids.includes(\n port.source_port_id,\n )\n if (sourceTrace && trace.connected_source_net_ids.length > 0) {\n isInNet = true\n }\n }\n\n if (!netId) return\n\n const startPoint = { x: port.x, y: port.y }\n const nearestPoint = findNearestPointInNet(startPoint, netId)\n\n if (!nearestPoint) return\n\n lines.push({\n key: `${port.pcb_port_id}-${index}`,\n startPoint,\n endPoint: nearestPoint,\n isInNet,\n })\n })\n\n return lines\n }, [soup, netMap, idToNetMap, isShowingRatsNest])\n\n if (!soup || !isShowingRatsNest) return children\n if (!transform) transform = identity()\n\n return (\n <div style={{ position: \"relative\" }}>\n {children}\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n opacity: 0.5,\n zIndex: zIndexMap.ratsNestOverlay,\n }}\n >\n {ratsNestLines.map(({ key, startPoint, endPoint, isInNet }) => {\n const transformedStart = applyToPoint(transform, startPoint)\n const transformedEnd = applyToPoint(transform, endPoint)\n\n return (\n <line\n key={key}\n x1={transformedStart.x}\n y1={transformedStart.y}\n x2={transformedEnd.x}\n y2={transformedEnd.y}\n stroke=\"white\"\n strokeWidth=\"1\"\n strokeDasharray={isInNet ? \"6,6\" : undefined}\n />\n )\n })}\n </svg>\n </div>\n )\n}\n","import {\n useEffect,\n useState,\n useCallback,\n useRef,\n useLayoutEffect,\n} from \"react\"\nimport { css } from \"@emotion/css\"\nimport { type LayerRef } from \"circuit-json\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport { getCopperLayerRefsFromElements } from \"lib/copper-layers\"\nimport { LAYER_NAME_TO_COLOR } from \"lib/Drawer\"\nimport { useGlobalStore } from \"../global-store\"\nimport packageJson from \"../../package.json\"\nimport { useHotKey } from \"hooks/useHotKey\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { useIsSmallScreen } from \"hooks/useIsSmallScreen\"\nimport { useMobileTouch } from \"hooks/useMobileTouch\"\nimport { ToolbarButton } from \"./ToolbarButton\"\nimport { ToolbarErrorDropdown } from \"./ToolbarErrorDropdown\"\n\ninterface Props {\n children?: React.ReactNode\n elements?: AnyCircuitElement[]\n}\n\ninterface LayerButtonProps {\n name: string\n selected?: boolean\n onClick: (\n e: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>,\n ) => void\n}\n\ninterface CheckboxMenuItemProps {\n label: string\n checked: boolean\n onClick: () => void\n}\n\ninterface RadioMenuItemProps {\n label: string\n checked: boolean\n onClick: () => void\n}\n\nexport const LayerButton = ({ name, selected, onClick }: LayerButtonProps) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick)\n return (\n <div\n className={css`\n margin-top: 2px;\n padding: 4px;\n padding-left: 8px;\n padding-right: 18px;\n cursor: pointer;\n\n &:hover {\n background-color: rgba(255, 255, 255, 0.1);\n }\n `}\n {...touchHandlers}\n style={touchStyle}\n >\n <span style={{ marginRight: 2, opacity: selected ? 1 : 0 }}>•</span>\n <span\n style={{\n marginLeft: 2,\n fontWeight: 500,\n color: (LAYER_NAME_TO_COLOR as any)[name.replace(/-/, \"\")],\n }}\n >\n {name}\n </span>\n </div>\n )\n}\n\nconst CheckboxMenuItem = ({\n label,\n checked,\n onClick,\n}: CheckboxMenuItemProps) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick)\n return (\n <div\n className={css`\n margin-top: 2px;\n padding: 4px;\n padding-left: 8px;\n padding-right: 18px;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n\n &:hover {\n background-color: rgba(255, 255, 255, 0.1);\n }\n `}\n {...touchHandlers}\n style={touchStyle}\n >\n <input type=\"checkbox\" checked={checked} onChange={() => {}} readOnly />\n <span style={{ color: \"#eee\" }}>{label}</span>\n </div>\n )\n}\n\nconst RadioMenuItem = ({ label, checked, onClick }: RadioMenuItemProps) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick)\n return (\n <div\n className={css`\n margin-top: 2px;\n padding: 4px;\n padding-left: 8px;\n padding-right: 18px;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n\n &:hover {\n background-color: rgba(255, 255, 255, 0.1);\n }\n `}\n {...touchHandlers}\n style={touchStyle}\n >\n <input type=\"radio\" checked={checked} onChange={() => {}} readOnly />\n <span style={{ color: \"#eee\" }}>{label}</span>\n </div>\n )\n}\n\nexport const ToolbarOverlay = ({ children, elements }: Props) => {\n const isSmallScreen = useIsSmallScreen()\n\n const {\n isMouseOverContainer,\n setIsMouseOverContainer,\n selectedLayer,\n selectLayer,\n viewSettings,\n setIsShowingRatsNest,\n setIsShowingMultipleTracesLength,\n setIsShowingAutorouting,\n setIsShowingDrcErrors,\n setIsShowingDrcWarnings,\n setIsShowingCopperPours,\n setIsShowingCourtyards,\n setIsShowingPcbGroups,\n setIsShowingGroupAnchorOffsets,\n setIsShowingSolderMask,\n setIsShowingSilkscreen,\n setIsShowingFabricationNotes,\n setIsShowingPcbNotes,\n setPcbGroupViewMode,\n setHoveredErrorId,\n setFocusedErrorId,\n } = useGlobalStore((s) => ({\n isMouseOverContainer: s.is_mouse_over_container,\n setIsMouseOverContainer: s.setIsMouseOverContainer,\n selectedLayer: s.selected_layer,\n selectLayer: s.selectLayer,\n viewSettings: {\n is_showing_rats_nest: s.is_showing_rats_nest,\n is_showing_multiple_traces_length: s.is_showing_multiple_traces_length,\n is_showing_autorouting: s.is_showing_autorouting,\n is_showing_drc_errors: s.is_showing_drc_errors,\n is_showing_drc_warnings: s.is_showing_drc_warnings,\n is_showing_copper_pours: s.is_showing_copper_pours,\n is_showing_courtyards: s.is_showing_courtyards,\n is_showing_pcb_groups: s.is_showing_pcb_groups,\n is_showing_group_anchor_offsets: s.is_showing_group_anchor_offsets,\n is_showing_solder_mask: s.is_showing_solder_mask,\n is_showing_silkscreen: s.is_showing_silkscreen,\n is_showing_fabrication_notes: s.is_showing_fabrication_notes,\n is_showing_pcb_notes: s.is_showing_pcb_notes,\n pcb_group_view_mode: s.pcb_group_view_mode,\n },\n setIsShowingRatsNest: s.setIsShowingRatsNest,\n setIsShowingMultipleTracesLength: s.setIsShowingMultipleTracesLength,\n setIsShowingAutorouting: s.setIsShowingAutorouting,\n setIsShowingDrcErrors: s.setIsShowingDrcErrors,\n setIsShowingDrcWarnings: s.setIsShowingDrcWarnings,\n setIsShowingCopperPours: s.setIsShowingCopperPours,\n setIsShowingCourtyards: s.setIsShowingCourtyards,\n setIsShowingPcbGroups: s.setIsShowingPcbGroups,\n setIsShowingGroupAnchorOffsets: s.setIsShowingGroupAnchorOffsets,\n setIsShowingSolderMask: s.setIsShowingSolderMask,\n setIsShowingSilkscreen: s.setIsShowingSilkscreen,\n setIsShowingFabricationNotes: s.setIsShowingFabricationNotes,\n setIsShowingPcbNotes: s.setIsShowingPcbNotes,\n setPcbGroupViewMode: s.setPcbGroupViewMode,\n setHoveredErrorId: s.setHoveredErrorId,\n setFocusedErrorId: s.setFocusedErrorId,\n }))\n\n const [isViewMenuOpen, setViewMenuOpen] = useState(false)\n const [isLayerMenuOpen, setLayerMenuOpen] = useState(false)\n const [isErrorsOpen, setErrorsOpen] = useState(false)\n const [measureToolArmed, setMeasureToolArmed] = useState(false)\n const [boundsToolArmed, setBoundsToolArmed] = useState(false)\n\n useEffect(() => {\n const arm = () => setMeasureToolArmed(true)\n const disarm = () => setMeasureToolArmed(false)\n const armBounds = () => setBoundsToolArmed(true)\n const disarmBounds = () => setBoundsToolArmed(false)\n window.addEventListener(\"arm-dimension-tool\", arm)\n window.addEventListener(\"disarm-dimension-tool\", disarm)\n window.addEventListener(\"arm-bounds-tool\", armBounds)\n window.addEventListener(\"disarm-bounds-tool\", disarmBounds)\n return () => {\n window.removeEventListener(\"arm-dimension-tool\", arm)\n window.removeEventListener(\"disarm-dimension-tool\", disarm)\n window.removeEventListener(\"arm-bounds-tool\", armBounds)\n window.removeEventListener(\"disarm-bounds-tool\", disarmBounds)\n }\n }, [])\n\n const availableLayers = getCopperLayerRefsFromElements(elements ?? [])\n\n const processedLayers = availableLayers\n\n const hasRunInitialMouseCheck = useRef(false)\n const hotkeyBoundaryRef = useRef<HTMLDivElement>(null)\n\n const hotKeyCallbacks = {\n \"1\": availableLayers[0]\n ? () => selectLayer(availableLayers[0] as LayerRef)\n : () => {},\n \"2\": availableLayers[1]\n ? () => selectLayer(availableLayers[1] as LayerRef)\n : () => {},\n \"3\": availableLayers[2]\n ? () => selectLayer(availableLayers[2] as LayerRef)\n : () => {},\n \"4\": availableLayers[3]\n ? () => selectLayer(availableLayers[3] as LayerRef)\n : () => {},\n \"5\": availableLayers[4]\n ? () => selectLayer(availableLayers[4] as LayerRef)\n : () => {},\n \"6\": availableLayers[5]\n ? () => selectLayer(availableLayers[5] as LayerRef)\n : () => {},\n \"7\": availableLayers[6]\n ? () => selectLayer(availableLayers[6] as LayerRef)\n : () => {},\n \"8\": availableLayers[7]\n ? () => selectLayer(availableLayers[7] as LayerRef)\n : () => {},\n \"9\": availableLayers[8]\n ? () => selectLayer(availableLayers[8] as LayerRef)\n : () => {},\n \"0\": availableLayers[9]\n ? () => selectLayer(availableLayers[9] as LayerRef)\n : () => {},\n }\n\n useHotKey(\"1\", hotKeyCallbacks[\"1\"], hotkeyBoundaryRef)\n useHotKey(\"2\", hotKeyCallbacks[\"2\"], hotkeyBoundaryRef)\n useHotKey(\"3\", hotKeyCallbacks[\"3\"], hotkeyBoundaryRef)\n useHotKey(\"4\", hotKeyCallbacks[\"4\"], hotkeyBoundaryRef)\n useHotKey(\"5\", hotKeyCallbacks[\"5\"], hotkeyBoundaryRef)\n useHotKey(\"6\", hotKeyCallbacks[\"6\"], hotkeyBoundaryRef)\n useHotKey(\"7\", hotKeyCallbacks[\"7\"], hotkeyBoundaryRef)\n useHotKey(\"8\", hotKeyCallbacks[\"8\"], hotkeyBoundaryRef)\n useHotKey(\"9\", hotKeyCallbacks[\"9\"], hotkeyBoundaryRef)\n useHotKey(\"0\", hotKeyCallbacks[\"0\"], hotkeyBoundaryRef)\n\n useLayoutEffect(() => {\n if (hasRunInitialMouseCheck.current) return\n hasRunInitialMouseCheck.current = true\n\n const checkMousePosition = (e: MouseEvent) => {\n if (hotkeyBoundaryRef.current) {\n const rect = hotkeyBoundaryRef.current.getBoundingClientRect()\n const isInside =\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom\n\n if (isInside) {\n setIsMouseOverContainer(true)\n }\n }\n document.removeEventListener(\"mousemove\", checkMousePosition)\n }\n\n document.addEventListener(\"mousemove\", checkMousePosition)\n return () => {\n document.removeEventListener(\"mousemove\", checkMousePosition)\n }\n }, [setIsMouseOverContainer])\n\n const handleMouseEnter = useCallback(() => {\n setIsMouseOverContainer(true)\n }, [setIsMouseOverContainer])\n\n const handleMouseMove = useCallback(() => {\n if (!isMouseOverContainer) {\n setIsMouseOverContainer(true)\n }\n }, [isMouseOverContainer, setIsMouseOverContainer])\n\n const handleMouseLeave = useCallback(() => {\n setIsMouseOverContainer(false)\n setLayerMenuOpen(false)\n setViewMenuOpen(false)\n setErrorsOpen(false)\n }, [setIsMouseOverContainer])\n\n const handleLayerMenuToggle = useCallback(() => {\n setLayerMenuOpen(!isLayerMenuOpen)\n }, [isLayerMenuOpen])\n\n const handleErrorsToggle = useCallback(() => {\n const newErrorsOpen = !isErrorsOpen\n setErrorsOpen(newErrorsOpen)\n if (newErrorsOpen) {\n setViewMenuOpen(false)\n }\n if (!newErrorsOpen) {\n setHoveredErrorId(null)\n }\n }, [isErrorsOpen, setHoveredErrorId])\n\n const closeErrorsMenu = useCallback(() => {\n setErrorsOpen(false)\n }, [])\n\n const handleRatsNestToggle = useCallback(() => {\n setIsShowingRatsNest(!viewSettings.is_showing_rats_nest)\n }, [viewSettings.is_showing_rats_nest, setIsShowingRatsNest])\n\n const handleMeasureToolClick = useCallback(() => {\n setMeasureToolArmed(true)\n setBoundsToolArmed(false)\n window.dispatchEvent(new Event(\"arm-dimension-tool\"))\n }, [])\n\n const handleBoundsToolClick = useCallback(() => {\n setBoundsToolArmed(true)\n setMeasureToolArmed(false)\n window.dispatchEvent(new Event(\"arm-bounds-tool\"))\n }, [])\n\n const handleViewMenuToggle = useCallback(() => {\n const newViewMenuOpen = !isViewMenuOpen\n setViewMenuOpen(newViewMenuOpen)\n if (newViewMenuOpen) {\n setErrorsOpen(false)\n }\n }, [isViewMenuOpen])\n\n const stopCanvasInteractionPropagation = useCallback(\n (\n event:\n | React.MouseEvent<HTMLElement>\n | React.TouchEvent<HTMLElement>\n | React.WheelEvent<HTMLElement>\n | React.PointerEvent<HTMLElement>,\n ) => {\n event.stopPropagation()\n },\n [],\n )\n\n return (\n <div\n ref={hotkeyBoundaryRef}\n style={{ position: \"relative\", zIndex: \"999 !important\" }}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onMouseMove={handleMouseMove}\n >\n {children}\n <div\n style={{\n position: \"absolute\",\n bottom: 4,\n right: 8,\n pointerEvents: \"none\",\n color: \"white\",\n fontSize: 11,\n opacity: isMouseOverContainer ? 0.5 : 0,\n transition: \"opacity 1s\",\n transitionDelay: \"2s\",\n fontFamily: \"sans-serif\",\n }}\n >\n @tscircuit/pcb-viewer@{packageJson.version}\n </div>\n <div\n data-toolbar-overlay\n onTouchStart={(e) => e.stopPropagation()}\n onTouchEnd={(e) => e.stopPropagation()}\n onTouchMove={(e) => e.stopPropagation()}\n onMouseDown={stopCanvasInteractionPropagation}\n onMouseMove={stopCanvasInteractionPropagation}\n onMouseUp={stopCanvasInteractionPropagation}\n onPointerDown={stopCanvasInteractionPropagation}\n onPointerMove={stopCanvasInteractionPropagation}\n onPointerUp={stopCanvasInteractionPropagation}\n onWheel={stopCanvasInteractionPropagation}\n style={{\n position: \"absolute\",\n opacity: isSmallScreen ? 1 : isMouseOverContainer ? 1 : 0,\n top: 16,\n left: 16,\n right: isSmallScreen ? 16 : \"auto\",\n transition: isMouseOverContainer\n ? \"opacity 100ms linear\"\n : \"opacity 300ms linear\",\n zIndex: zIndexMap.toolbarOverlay,\n color: \"red\",\n display: \"flex\",\n flexWrap: \"wrap\",\n maxWidth: \"550px\",\n gap: 4,\n fontSize: 12,\n fontFamily: \"sans-serif\",\n }}\n >\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n onClick={handleLayerMenuToggle}\n onMouseLeave={() => {\n if (isLayerMenuOpen) {\n setLayerMenuOpen(false)\n }\n }}\n >\n <div>\n layer:{\" \"}\n <span\n style={{\n marginLeft: 2,\n fontWeight: 500,\n color: (LAYER_NAME_TO_COLOR as any)[selectedLayer as string],\n }}\n >\n {selectedLayer as string}\n </span>\n </div>\n {isLayerMenuOpen && (\n <div style={{ marginTop: 4, minWidth: 120 }}>\n {processedLayers.map((layer) => (\n <LayerButton\n key={layer}\n name={layer}\n selected={layer === selectedLayer}\n onClick={() => {\n selectLayer(layer as LayerRef)\n }}\n />\n ))}\n </div>\n )}\n </ToolbarButton>\n <ToolbarErrorDropdown\n elements={elements}\n isOpen={isErrorsOpen}\n isSmallScreen={isSmallScreen}\n onToggle={handleErrorsToggle}\n onClose={closeErrorsMenu}\n setHoveredErrorId={setHoveredErrorId}\n setFocusedErrorId={setFocusedErrorId}\n />\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n style={{}}\n onClick={handleRatsNestToggle}\n >\n <div>\n {viewSettings.is_showing_rats_nest ? \"✖ \" : \"\"}\n Rats Nest\n </div>\n </ToolbarButton>\n\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n style={measureToolArmed ? { backgroundColor: \"#444\" } : {}}\n onClick={handleMeasureToolClick}\n >\n <div>📏</div>\n </ToolbarButton>\n\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n style={boundsToolArmed ? { backgroundColor: \"#444\" } : {}}\n onClick={handleBoundsToolClick}\n >\n <div>Bounds</div>\n </ToolbarButton>\n\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n onClick={handleViewMenuToggle}\n >\n <div>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"4px\",\n }}\n >\n View\n <span\n style={{\n fontSize: \"8px\",\n transform: isViewMenuOpen ? \"rotate(180deg)\" : \"rotate(0)\",\n transition: \"transform 0.1s ease\",\n display: \"inline-block\",\n }}\n >\n ▼\n </span>\n </div>\n {isViewMenuOpen && (\n <div style={{ marginTop: 4, minWidth: 120 }}>\n <CheckboxMenuItem\n label=\"Show All Trace Lengths\"\n checked={viewSettings.is_showing_multiple_traces_length}\n onClick={() => {\n setIsShowingMultipleTracesLength(\n !viewSettings.is_showing_multiple_traces_length,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show Autorouting Animation\"\n checked={viewSettings.is_showing_autorouting}\n onClick={() => {\n setIsShowingAutorouting(\n !viewSettings.is_showing_autorouting,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show DRC Errors\"\n checked={viewSettings.is_showing_drc_errors}\n onClick={() => {\n setIsShowingDrcErrors(!viewSettings.is_showing_drc_errors)\n }}\n />\n <CheckboxMenuItem\n label=\"Show DRC Warnings\"\n checked={viewSettings.is_showing_drc_warnings}\n onClick={() => {\n setIsShowingDrcWarnings(\n !viewSettings.is_showing_drc_warnings,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show Copper Pours\"\n checked={viewSettings.is_showing_copper_pours}\n onClick={() => {\n setIsShowingCopperPours(\n !viewSettings.is_showing_copper_pours,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show Courtyards\"\n checked={viewSettings.is_showing_courtyards}\n onClick={() => {\n setIsShowingCourtyards(!viewSettings.is_showing_courtyards)\n }}\n />\n <CheckboxMenuItem\n label=\"Show Solder Mask\"\n checked={viewSettings.is_showing_solder_mask}\n onClick={() => {\n setIsShowingSolderMask(!viewSettings.is_showing_solder_mask)\n }}\n />\n <CheckboxMenuItem\n label=\"Show Silkscreen\"\n checked={viewSettings.is_showing_silkscreen}\n onClick={() => {\n setIsShowingSilkscreen(!viewSettings.is_showing_silkscreen)\n }}\n />\n <CheckboxMenuItem\n label=\"Show Fabrication Notes\"\n checked={viewSettings.is_showing_fabrication_notes}\n onClick={() => {\n setIsShowingFabricationNotes(\n !viewSettings.is_showing_fabrication_notes,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show PCB Notes\"\n checked={viewSettings.is_showing_pcb_notes}\n onClick={() => {\n setIsShowingPcbNotes(!viewSettings.is_showing_pcb_notes)\n }}\n />\n <CheckboxMenuItem\n label=\"Show Group Anchor Offsets\"\n checked={viewSettings.is_showing_group_anchor_offsets}\n onClick={() => {\n setIsShowingGroupAnchorOffsets(\n !viewSettings.is_showing_group_anchor_offsets,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show PCB Groups\"\n checked={viewSettings.is_showing_pcb_groups}\n onClick={() => {\n setIsShowingPcbGroups(!viewSettings.is_showing_pcb_groups)\n }}\n />\n {viewSettings.is_showing_pcb_groups && (\n <div style={{ marginLeft: 16 }}>\n <RadioMenuItem\n label=\"Show All Groups\"\n checked={viewSettings.pcb_group_view_mode === \"all\"}\n onClick={() => {\n setPcbGroupViewMode(\"all\")\n }}\n />\n <RadioMenuItem\n label=\"Show Named Groups\"\n checked={\n viewSettings.pcb_group_view_mode === \"named_only\"\n }\n onClick={() => {\n setPcbGroupViewMode(\"named_only\")\n }}\n />\n </div>\n )}\n </div>\n )}\n </div>\n </ToolbarButton>\n </div>\n </div>\n )\n}\n","{\n \"name\": \"@tscircuit/pcb-viewer\",\n \"version\": \"1.11.390\",\n \"main\": \"dist/index.js\",\n \"type\": \"module\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/tscircuit/pcb-viewer\"\n },\n \"license\": \"MIT\",\n \"scripts\": {\n \"start\": \"cosmos\",\n \"build\": \"tsup ./src/index.tsx --platform browser --external @tscircuit/core --dts --sourcemap --format esm --outDir dist\",\n \"yalc\": \"npm run build && yalc push\",\n \"format\": \"biome format . --write\",\n \"format:check\": \"biome format .\",\n \"cosmos\": \"cosmos\",\n \"cosmos-export\": \"cosmos-export\"\n },\n \"files\": [\n \"dist\"\n ],\n \"devDependencies\": {\n \"@biomejs/biome\": \"^1.9.4\",\n \"@semantic-release/commit-analyzer\": \"^9.0.2\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@semantic-release/npm\": \"^9.0.1\",\n \"@semantic-release/release-notes-generator\": \"^10.0.3\",\n \"@swc/core\": \"^1.4.12\",\n \"@tscircuit/circuit-json-util\": \"^0.0.108\",\n \"@tscircuit/eagle-xml-converter\": \"^1.0.0\",\n \"@types/bun\": \"latest\",\n \"@types/color\": \"^3.0.6\",\n \"@types/node\": \"18.7.23\",\n \"@types/react\": \"19\",\n \"format-si-unit\": \"^0.0.12\",\n \"next\": \"^14.1.4\",\n \"pixi.js\": \"^8.6.6\",\n \"react\": \"19.1.0\",\n \"react-cosmos\": \"7.0.0-beta.4\",\n \"react-cosmos-plugin-vite\": \"7.0.0-beta.0\",\n \"react-dom\": \"19.1.0\",\n \"react-use\": \"^17.4.0\",\n \"tscircuit\": \"^0.0.2354\",\n \"tsup\": \"^8.0.2\",\n \"type-fest\": \"^3.0.0\",\n \"typescript\": \"^5.4.4\",\n \"use-mouse-matrix-transform\": \"^1.3.4\",\n \"zod\": \"^3.23.5\"\n },\n \"peerDependencies\": {\n \"react\": \"*\",\n \"tscircuit\": \"*\"\n },\n \"dependencies\": {\n \"@emotion/css\": \"^11.11.2\",\n \"@tscircuit/alphabet\": \"^0.0.25\",\n \"@tscircuit/math-utils\": \"^0.0.36\",\n \"@vitejs/plugin-react\": \"^5.0.2\",\n \"circuit-json\": \"^0.0.469\",\n \"circuit-to-canvas\": \"0.0.124\",\n \"color\": \"^4.2.3\",\n \"react-supergrid\": \"^1.0.10\",\n \"react-toastify\": \"^10.0.5\",\n \"transformation-matrix\": \"^2.13.0\",\n \"zustand\": \"^4.5.2\"\n }\n}\n","import { useEffect, useRef, type RefObject } from \"react\"\nimport { useGlobalStore } from \"../global-store\"\n\nexport const useHotKey = (\n key: string,\n onUse: () => void,\n containerRef?: RefObject<HTMLElement | null>,\n) => {\n const isMouseOverContainer = useGlobalStore(\n (s) => s.is_mouse_over_container,\n ) as boolean\n\n const isMouseOverContainerRef = useRef(isMouseOverContainer)\n const onUseRef = useRef(onUse)\n\n useEffect(() => {\n isMouseOverContainerRef.current = isMouseOverContainer\n }, [isMouseOverContainer])\n\n useEffect(() => {\n onUseRef.current = onUse\n }, [onUse])\n\n useEffect(() => {\n if (!key) return\n\n const handleKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement\n if (\n target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.isContentEditable\n ) {\n return\n }\n\n const keyParts = key.split(\"+\")\n\n const ctrlRequired = keyParts.includes(\"ctrl\")\n const shiftRequired = keyParts.includes(\"shift\")\n const altRequired = keyParts.includes(\"alt\")\n const metaRequired = keyParts.includes(\"meta\")\n const mainKey = keyParts[keyParts.length - 1]\n\n const containerHasFocus = containerRef?.current\n ? containerRef.current.contains(document.activeElement) ||\n document.activeElement === containerRef.current\n : false\n\n const shouldTrigger = isMouseOverContainerRef.current || containerHasFocus\n\n if (\n shouldTrigger &&\n (!ctrlRequired || event.ctrlKey) &&\n (!shiftRequired || event.shiftKey) &&\n (!altRequired || event.altKey) &&\n (!metaRequired || event.metaKey) &&\n event.key.toLowerCase() === mainKey.toLowerCase()\n ) {\n event.preventDefault()\n onUseRef.current()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n\n return () => {\n window.removeEventListener(\"keydown\", handleKeyDown)\n }\n }, [key])\n}\n","import { useEffect, useState } from \"react\"\n\nexport const useIsSmallScreen = () => {\n const [isSmallScreen, setIsSmallScreen] = useState(false)\n\n useEffect(() => {\n const checkIsMobile = () => {\n setIsSmallScreen(window.innerWidth <= 768)\n }\n\n checkIsMobile()\n window.addEventListener(\"resize\", checkIsMobile)\n\n return () => window.removeEventListener(\"resize\", checkIsMobile)\n }, [])\n\n return isSmallScreen\n}\n","import {\n useCallback,\n useRef,\n type MouseEvent,\n type TouchEvent,\n type CSSProperties,\n} from \"react\"\n\n/**\n * A hook to handle mobile touch events and prevent \"ghost clicks\" or double-firing\n * when using both click and touch handlers.\n */\nexport const useMobileTouch = <T extends HTMLElement = HTMLElement>(\n onClick?: (e: MouseEvent<T> | TouchEvent<T>) => void,\n options: { stopPropagation?: boolean } = { stopPropagation: true },\n) => {\n const lastInteractionRef = useRef(0)\n\n const handleInteraction = useCallback(\n (e: MouseEvent<T> | TouchEvent<T>) => {\n if (options.stopPropagation) {\n e.stopPropagation()\n }\n\n const now = Date.now()\n if (now - lastInteractionRef.current < 300) return\n lastInteractionRef.current = now\n\n onClick?.(e)\n },\n [onClick, options.stopPropagation],\n )\n\n const onTouchEnd = useCallback(\n (e: TouchEvent<T>) => {\n e.preventDefault()\n handleInteraction(e)\n },\n [handleInteraction],\n )\n\n const style: CSSProperties = { touchAction: \"manipulation\" }\n\n return {\n onClick: handleInteraction,\n onTouchEnd,\n style,\n }\n}\n","import type React from \"react\"\nimport { useMobileTouch } from \"hooks/useMobileTouch\"\n\nexport interface ToolbarButtonProps {\n children: React.ReactNode\n isSmallScreen: boolean\n onClick?: (\n e: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>,\n ) => void\n style?: React.CSSProperties\n onMouseLeave?: (e: React.MouseEvent<HTMLElement>) => void\n}\n\nexport const ToolbarButton = ({\n children,\n isSmallScreen,\n onClick,\n ...props\n}: ToolbarButtonProps) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick)\n\n return (\n <div\n {...props}\n {...touchHandlers}\n style={{\n backgroundColor: \"#1F1F1F\",\n border: \"1px solid #666\",\n margin: 0,\n padding: 4,\n paddingLeft: isSmallScreen ? 8 : 6,\n paddingRight: isSmallScreen ? 8 : 6,\n borderRadius: 2,\n color: \"#eee\",\n cursor: \"pointer\",\n fontSize: 12,\n height: \"fit-content\",\n userSelect: \"none\",\n whiteSpace: \"nowrap\",\n ...touchStyle,\n ...props.style,\n }}\n >\n {children}\n </div>\n )\n}\n","import { useCallback, useMemo, useState } from \"react\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport { useCopyToClipboard } from \"react-use\"\nimport { useMobileTouch } from \"hooks/useMobileTouch\"\nimport { ToolbarButton } from \"./ToolbarButton\"\nimport { groupErrorsByType } from \"lib/util/group-errors-by-type\"\nimport { useToolbarErrorFocus } from \"./useToolbarErrorFocus\"\n\ntype ToolbarErrorElement = AnyCircuitElement & {\n error_type?: string\n message?: string\n pcb_trace_error_id?: string\n}\n\nconst CopyErrorButton = ({\n errorId,\n errorMessage,\n copiedErrorId,\n onCopy,\n}: {\n errorId: string\n errorMessage: string\n copiedErrorId: string | null\n onCopy: (errorMessage: string, errorId: string) => void\n}) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(() =>\n onCopy(errorMessage, errorId),\n )\n\n return (\n <button\n type=\"button\"\n aria-label={\n copiedErrorId === errorId\n ? \"Error message copied\"\n : \"Copy error message\"\n }\n style={{\n position: \"absolute\",\n top: 12,\n right: 16,\n cursor: \"pointer\",\n color: \"#888\",\n fontSize: 16,\n background: \"none\",\n border: \"none\",\n padding: 0,\n display: \"flex\",\n alignItems: \"center\",\n ...touchStyle,\n }}\n {...touchHandlers}\n >\n {copiedErrorId === errorId ? (\n <span style={{ color: \"#4caf50\", fontSize: 12 }}>Copied!</span>\n ) : (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\" />\n </svg>\n )}\n </button>\n )\n}\n\ninterface ToolbarErrorDropdownProps {\n elements?: AnyCircuitElement[]\n isOpen: boolean\n isSmallScreen: boolean\n onToggle: () => void\n onClose: () => void\n setHoveredErrorId: (errorId: string | null) => void\n setFocusedErrorId: (errorId: string | null) => void\n}\n\nexport const ToolbarErrorDropdown = ({\n elements,\n isOpen,\n isSmallScreen,\n onToggle,\n onClose,\n setHoveredErrorId,\n setFocusedErrorId,\n}: ToolbarErrorDropdownProps) => {\n const [copiedErrorId, setCopiedErrorId] = useState<string | null>(null)\n const [collapsedErrorGroups, setCollapsedErrorGroups] = useState<Set<string>>(\n new Set(),\n )\n const [expandedErrorIds, setExpandedErrorIds] = useState<Set<string>>(\n new Set(),\n )\n const [, copyToClipboard] = useCopyToClipboard()\n const { handleErrorSelect, isSelectedError } = useToolbarErrorFocus({\n onClose,\n setHoveredErrorId,\n setFocusedErrorId,\n })\n\n const errorElements = useMemo(\n () =>\n elements?.filter((el): el is ToolbarErrorElement =>\n el.type.includes(\"error\"),\n ) ?? [],\n [elements],\n )\n\n const errorCount = errorElements.length\n\n const groupedErrorElements = useMemo(\n () => groupErrorsByType(errorElements),\n [errorElements],\n )\n\n const toggleErrorGroup = useCallback((errorType: string) => {\n setCollapsedErrorGroups((prev) => {\n const next = new Set(prev)\n if (next.has(errorType)) {\n next.delete(errorType)\n } else {\n next.add(errorType)\n }\n return next\n })\n }, [])\n\n const toggleExpandedError = useCallback((errorId: string) => {\n setExpandedErrorIds((prev) => {\n const next = new Set(prev)\n if (next.has(errorId)) {\n next.delete(errorId)\n } else {\n next.add(errorId)\n }\n return next\n })\n }, [])\n\n return (\n <div style={{ position: \"relative\" }}>\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n style={errorCount > 0 ? { color: \"red\" } : undefined}\n onClick={onToggle}\n >\n <div>{errorCount} errors</div>\n </ToolbarButton>\n {isOpen && errorCount > 0 && (\n <div\n style={{\n position: \"absolute\",\n top: \"100%\",\n left: 0,\n backgroundColor: \"#2a2a2a\",\n border: \"1px solid #666\",\n borderRadius: 4,\n marginTop: 4,\n zIndex: 1000,\n minWidth: isSmallScreen ? \"280px\" : \"400px\",\n maxWidth: isSmallScreen ? \"90vw\" : \"600px\",\n maxHeight: \"400px\",\n overflow: \"auto\",\n boxShadow: \"0 4px 12px rgba(0, 0, 0, 0.3)\",\n }}\n >\n {groupedErrorElements.map(({ errorType, errors }, groupIndex) => {\n const isGroupCollapsed = collapsedErrorGroups.has(errorType)\n\n return (\n <div\n key={errorType}\n style={{\n borderBottom:\n groupIndex < groupedErrorElements.length - 1\n ? \"1px solid #444\"\n : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n backgroundColor: \"#232323\",\n transition: \"background-color 0.2s ease\",\n touchAction: \"manipulation\",\n position: \"sticky\",\n top: 0,\n zIndex: 1,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#303030\"\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#232323\"\n }}\n onTouchStart={(e) => {\n e.stopPropagation()\n e.currentTarget.style.backgroundColor = \"#303030\"\n }}\n onTouchEnd={(e) => {\n e.stopPropagation()\n e.preventDefault()\n e.currentTarget.style.backgroundColor = \"#232323\"\n toggleErrorGroup(errorType)\n }}\n onClick={(e) => {\n e.stopPropagation()\n toggleErrorGroup(errorType)\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n color: \"#ff6b6b\",\n }}\n >\n <div\n style={{\n color: \"#888\",\n fontSize: \"16px\",\n transform: isGroupCollapsed\n ? \"rotate(90deg)\"\n : \"rotate(0deg)\",\n transition: \"transform 0.2s ease\",\n flexShrink: 0,\n }}\n >\n ›\n </div>\n <div\n style={{\n fontWeight: \"bold\",\n fontSize: isSmallScreen ? \"12px\" : \"13px\",\n }}\n >\n {errorType}\n </div>\n </div>\n <div\n style={{\n fontSize: isSmallScreen ? \"12px\" : \"13px\",\n color: \"#aaa\",\n whiteSpace: \"nowrap\",\n marginLeft: 12,\n }}\n >\n {errors.length}\n </div>\n </div>\n {!isGroupCollapsed &&\n errors.map(({ error, index, errorId }) => {\n const isExpanded = expandedErrorIds.has(errorId)\n const errorMessage = error.message ?? \"No error message\"\n\n return (\n <div\n key={errorId}\n style={{\n borderTop: \"1px solid #3a3a3a\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n padding: \"12px 16px 12px 24px\",\n cursor: \"pointer\",\n backgroundColor: \"#2a2a2a\",\n transition: \"background-color 0.2s ease\",\n touchAction: \"manipulation\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#333\"\n setHoveredErrorId(errorId)\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#2a2a2a\"\n if (!isSelectedError(errorId)) {\n setHoveredErrorId(null)\n }\n }}\n onTouchStart={(e) => {\n e.stopPropagation()\n e.currentTarget.style.backgroundColor = \"#333\"\n setHoveredErrorId(errorId)\n }}\n onTouchEnd={(e) => {\n e.stopPropagation()\n e.preventDefault()\n e.currentTarget.style.backgroundColor = \"#2a2a2a\"\n handleErrorSelect(errorId)\n }}\n onClick={(e) => {\n e.stopPropagation()\n handleErrorSelect(errorId)\n }}\n >\n <div\n style={{\n flex: 1,\n fontSize: isSmallScreen ? \"12px\" : \"13px\",\n color: \"#ddd\",\n lineHeight: 1.4,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n userSelect: \"text\",\n }}\n >\n {errorMessage}\n </div>\n <button\n type=\"button\"\n aria-label={\n isExpanded\n ? \"Collapse error details\"\n : \"Expand error details\"\n }\n style={{\n color: \"#888\",\n fontSize: \"16px\",\n transform: isExpanded\n ? \"rotate(0deg)\"\n : \"rotate(90deg)\",\n transition: \"transform 0.2s ease\",\n flexShrink: 0,\n background: \"none\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n }}\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation()\n toggleExpandedError(errorId)\n }}\n onTouchEnd={(event) => {\n event.stopPropagation()\n event.preventDefault()\n toggleExpandedError(errorId)\n }}\n >\n ›\n </button>\n </div>\n {isExpanded && (\n <div\n data-error-id={index}\n style={{\n display: \"block\",\n padding: \"12px 16px 12px 24px\",\n backgroundColor: \"#1a1a1a\",\n borderTop: \"1px solid #444\",\n position: \"relative\",\n }}\n >\n <div\n style={{\n fontSize: isSmallScreen ? \"11px\" : \"12px\",\n color: \"#ccc\",\n lineHeight: 1.5,\n wordWrap: \"break-word\",\n overflowWrap: \"break-word\",\n hyphens: \"auto\",\n userSelect: \"text\",\n paddingRight: 30,\n }}\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => event.stopPropagation()}\n >\n {errorMessage}\n </div>\n <CopyErrorButton\n errorId={errorId}\n errorMessage={errorMessage}\n copiedErrorId={copiedErrorId}\n onCopy={(message, id) => {\n copyToClipboard(message)\n setCopiedErrorId(id)\n setTimeout(() => setCopiedErrorId(null), 2000)\n }}\n />\n </div>\n )}\n </div>\n )\n })}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n","import { getErrorId } from \"lib/util/get-error-id\"\n\nexport const groupErrorsByType = <\n T extends {\n error_type?: string\n },\n>(\n errors: T[],\n) => {\n const groups = new Map<\n string,\n { error: T; index: number; errorId: string }[]\n >()\n\n errors.forEach((error, index) => {\n const errorType = error.error_type || \"unknown_error\"\n const existingGroup = groups.get(errorType) || []\n\n existingGroup.push({\n error,\n index,\n errorId: getErrorId(error, index),\n })\n\n groups.set(errorType, existingGroup)\n })\n\n return Array.from(groups.entries()).map(([errorType, groupedErrors]) => ({\n errorType,\n errors: groupedErrors,\n }))\n}\n","import { useCallback, useEffect, useRef } from \"react\"\n\nexport const useToolbarErrorFocus = ({\n onClose,\n setHoveredErrorId,\n setFocusedErrorId,\n highlightDurationMs = 3000,\n}: {\n onClose: () => void\n setHoveredErrorId: (errorId: string | null) => void\n setFocusedErrorId: (errorId: string | null) => void\n highlightDurationMs?: number\n}) => {\n const clearHighlightTimeoutRef = useRef<number | null>(null)\n const focusRequestRef = useRef<number | null>(null)\n const selectedErrorIdRef = useRef<string | null>(null)\n\n const clearPendingSelection = useCallback(() => {\n if (clearHighlightTimeoutRef.current !== null) {\n window.clearTimeout(clearHighlightTimeoutRef.current)\n clearHighlightTimeoutRef.current = null\n }\n\n if (focusRequestRef.current !== null) {\n window.cancelAnimationFrame(focusRequestRef.current)\n focusRequestRef.current = null\n }\n }, [])\n\n useEffect(() => clearPendingSelection, [clearPendingSelection])\n\n const handleErrorSelect = useCallback(\n (errorId: string) => {\n clearPendingSelection()\n\n selectedErrorIdRef.current = errorId\n setHoveredErrorId(errorId)\n setFocusedErrorId(null)\n\n focusRequestRef.current = window.requestAnimationFrame(() => {\n setFocusedErrorId(errorId)\n focusRequestRef.current = null\n })\n\n onClose()\n\n clearHighlightTimeoutRef.current = window.setTimeout(() => {\n selectedErrorIdRef.current = null\n setHoveredErrorId(null)\n setFocusedErrorId(null)\n clearHighlightTimeoutRef.current = null\n }, highlightDurationMs)\n },\n [\n clearPendingSelection,\n highlightDurationMs,\n onClose,\n setFocusedErrorId,\n setHoveredErrorId,\n ],\n )\n\n const isSelectedError = useCallback(\n (errorId: string) => selectedErrorIdRef.current === errorId,\n [],\n )\n\n return {\n handleErrorSelect,\n isSelectedError,\n }\n}\n","import type { AnyCircuitElement, LayerRef } from \"circuit-json\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { useEffect, useRef } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport { type Matrix, applyToPoint, identity } from \"transformation-matrix\"\nimport colors from \"lib/colors\"\nimport {\n getPcbWarningHighlightLabel,\n isHighlightablePcbWarning,\n} from \"lib/util/get-pcb-warning-highlight\"\nimport { useGlobalStore } from \"../global-store\"\n\ninterface BaseCircuitElement {\n type: string\n}\n\ninterface PcbComponent extends BaseCircuitElement {\n type: \"pcb_component\"\n pcb_component_id: string\n width: number\n height: number\n source_component_id: string\n center: { x: number; y: number }\n rotation: number\n layer: LayerRef\n obstructs_within_bounds: boolean\n}\n\ninterface Props {\n transform?: Matrix\n elements?: AnyCircuitElement[]\n children: any\n}\n\nexport const WarningGraphicsOverlay = ({\n children,\n transform = identity(),\n elements = [],\n}: Props) => {\n const [containerRef, { width, height }] = useMeasure<HTMLDivElement>()\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const isShowingDrcWarnings = useGlobalStore(\n (state) => state.is_showing_drc_warnings,\n )\n\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas || !width || !height) return\n\n canvas.width = width\n canvas.height = height\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n\n ctx.clearRect(0, 0, width, height)\n\n const pcbComponents = elements.filter(\n (el): el is PcbComponent => el.type === \"pcb_component\",\n ) as PcbComponent[]\n\n const warnings = elements.filter(isHighlightablePcbWarning)\n\n ctx.strokeStyle = colors.board.drc_warning\n ctx.lineWidth = 2\n\n warnings.forEach((warning) => {\n const component = pcbComponents.find(\n (comp) => comp.pcb_component_id === warning.pcb_component_id,\n )\n\n if (!component) return\n\n const { width, height, center } = component\n\n const transformedCenter = applyToPoint(transform, center)\n\n const scaledWidth = width * Math.abs(transform.a)\n const scaledHeight = height * Math.abs(transform.d)\n\n const boxPadding = 0.1 * Math.abs(transform.a)\n\n const boxWidth = scaledWidth + boxPadding * 2\n const boxHeight = scaledHeight + boxPadding * 2\n const x = transformedCenter.x - boxWidth / 2\n const y = transformedCenter.y - boxHeight / 2\n\n ctx.beginPath()\n ctx.rect(x, y, boxWidth, boxHeight)\n ctx.stroke()\n\n const labelText = getPcbWarningHighlightLabel(warning)\n const labelPadding = 4\n const fontSize = Math.max(8, Math.min(12, 10 * Math.abs(transform.a)))\n ctx.font = `${fontSize}px sans-serif`\n const labelMetrics = ctx.measureText(labelText)\n const labelWidth = labelMetrics.width + labelPadding * 2\n const labelHeight = fontSize + labelPadding * 2\n const labelX = x + (boxWidth - labelWidth) / 2\n const labelY = y + boxHeight + 5\n\n ctx.fillStyle = \"rgba(0, 0, 0, 0.7)\"\n ctx.beginPath()\n ctx.roundRect(labelX, labelY, labelWidth, labelHeight, 3)\n ctx.fill()\n\n ctx.fillStyle = colors.board.drc_warning\n ctx.textAlign = \"center\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(labelText, labelX + labelWidth / 2, labelY + labelHeight / 2)\n })\n }, [elements, transform, width, height, isShowingDrcWarnings])\n\n if (!isShowingDrcWarnings) {\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n >\n {children}\n </div>\n )\n }\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n >\n {children}\n <canvas\n ref={canvasRef}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n pointerEvents: \"none\",\n zIndex: zIndexMap.warnings,\n }}\n />\n </div>\n )\n}\n","import type {\n AnyCircuitElement,\n PcbConnectorNotInAccessibleOrientationWarning,\n PcbManualEditConflictWarning,\n} from \"circuit-json\"\n\nexport type HighlightablePcbWarning =\n | PcbManualEditConflictWarning\n | PcbConnectorNotInAccessibleOrientationWarning\n\nexport const isHighlightablePcbWarning = (\n element: AnyCircuitElement,\n): element is HighlightablePcbWarning =>\n element.type === \"pcb_manual_edit_conflict_warning\" ||\n element.type === \"pcb_connector_not_in_accessible_orientation_warning\"\n\nexport const getPcbWarningHighlightLabel = (\n warning: HighlightablePcbWarning,\n): string => {\n if (warning.type === \"pcb_connector_not_in_accessible_orientation_warning\") {\n return `Connector faces ${warning.facing_direction}; expected ${warning.recommended_facing_direction}`\n }\n\n return \"Manual Edit Conflict\"\n}\n","import {\n getBoundsOfPcbElements,\n getElementId,\n} from \"@tscircuit/circuit-json-util\"\nimport type { AnyCircuitElement, PcbTrace } from \"circuit-json\"\n\nconst formatToFixed4 = (value: number): string =>\n Number.isFinite(value) ? value.toFixed(4) : \"NaN\"\n\nconst generateHash = (input: string): number => {\n let hash = 5381\n for (let i = 0; i < input.length; i++) {\n hash = (hash << 5) + hash + input.charCodeAt(i)\n }\n return Math.abs(hash)\n}\n\nexport const calculateCircuitJsonKey = (\n circuitJson?: AnyCircuitElement[],\n): string => {\n if (!circuitJson?.length) {\n return \"0\"\n }\n\n const elementSignatures: string[] = []\n\n for (const element of circuitJson) {\n if (!element?.type?.startsWith(\"pcb_\")) {\n continue\n }\n\n const id = getElementId(element)\n\n const bounds = getBoundsOfPcbElements([element])\n\n const boundsStr = [\n formatToFixed4(bounds.minX),\n formatToFixed4(bounds.minY),\n formatToFixed4(bounds.maxX),\n formatToFixed4(bounds.maxY),\n ].join(\",\")\n let signature = `${id}:${boundsStr}`\n if (element.type === \"pcb_trace\") {\n const routeLength = ((element as PcbTrace).route ?? []).length\n signature += `:${routeLength}`\n }\n\n elementSignatures.push(signature)\n }\n\n if (elementSignatures.length === 0) {\n return \"0\"\n }\n\n elementSignatures.sort()\n\n const combinedSignature = elementSignatures.join(\",\")\n const hash = generateHash(combinedSignature)\n\n return `${elementSignatures.length}_${hash.toString(36)}`\n}\n","import type { AnyCircuitElement, PcbBoard } from \"circuit-json\"\n\nexport const calculateBoardSizeKey = (\n circuitJson?: AnyCircuitElement[],\n): string => {\n if (!circuitJson) return \"empty\"\n\n const board = circuitJson.find((e) => e.type === \"pcb_board\") as\n | PcbBoard\n | undefined\n\n if (!board) return \"no-board\"\n const round = (n: number) => Math.round(n * 1000) / 1000\n\n if (board.outline) {\n return board.outline.map((o) => `${round(o.x)}_${round(o.y)}`).join(\",\")\n }\n\n return `${round(board.width!)}_${round(board.height!)}`\n}\n"],"mappings":"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D,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WA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","names":["format","err","kindOf","module","noop","getAction","create","lexer","emit","step","createNode","reader","handleLexerData","parseSync","parseInput","camelize","toCamelCase","notCamelcase","escapeText","escapeAttr","svgsonSync","applyFilters","input","stringify","ast","Soup","translate","su","component_type","joiner","Soup","jsx","jsx","useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useCallback","useCallback","useCallback","writeText","error","useEffect","useEffect","useMemo","useState","useState","useMemo","_a","compose","scale","translate","translate","translate","compose","applyToPoint","scale","useCallback","useEffect","useRef","useState","scale","getBoundsFromPoints","compose","scale","translate","mergeBounds","useCallback","useEffect","useMemo","useRef","useState","applyToPoint","compose","identity","translate","identity","compose","translate","applyToPoint","angle","scale","color","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","PCB_VIEWER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","color","HOVER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","color","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","color","HOVER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","color","CircuitToCanvasDrawer","compose","translate","applyToPoint","color","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","PCB_VIEWER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","color","DEFAULT_PCB_COLOR_MAP","color","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","color","HOVER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","useEffect","useRef","jsx","useRef","useEffect","uint16","uint8","osIsLittleEndian","applyToPoint","inverse","applyToPoint","applyToPoint","heads","applyToPoint","compose","scale","translate","color","applyToPoint","applyToPoint","compose","scale","translate","useEffect","useRef","jsx","jsxs","useRef","useEffect","useCallback","useEffect","useMemo","useRef","useState","applyToPoint","identity","inverse","rotatePoint","rotatePoint","useMemo","distance","useMemo","rotatePoint","jsx","jsxs","identity","useState","useCallback","useRef","useMemo","applyToPoint","distance","useEffect","inverse","useRef","useState","applyToPoint","identity","inverse","jsx","jsxs","e","useRef","Fragment","applyToPoint","identity","jsx","jsxs","jsx","jsxs","identity","useRef","applyToPoint","Fragment","scale","distance","useEffect","useMemo","useState","applyToPoint","inverse","applyToPoint","Fragment","jsx","jsxs","applyToPoint","jsx","jsx","applyToPoint","jsx","jsxs","applyToPoint","jsx","useEffect","useState","jsx","jsxs","useState","useEffect","color","Fragment","jsx","jsxs","distance","useState","useEffect","useMemo","highlightedPrimitives","applyToPoint","transform","primitives","inverse","applyToPoint","identity","useRef","useEffect","jsx","jsxs","identity","useRef","useEffect","children","applyToPoint","applyToPoint","identity","useMemo","jsx","jsxs","distance","identity","applyToPoint","useEffect","useState","useCallback","useRef","useLayoutEffect","css","useEffect","useRef","useRef","useEffect","useEffect","useState","useCallback","useRef","jsx","useCallback","useMemo","useState","useCallback","useEffect","useRef","jsx","jsxs","useState","useMemo","useCallback","jsx","jsxs","css","useState","useEffect","useRef","useLayoutEffect","useCallback","useEffect","useRef","applyToPoint","identity","jsx","jsxs","identity","useRef","useEffect","width","height","applyToPoint","jsx","useMemo","primitivesWithoutInteractionMetadata","connectivityMap","useState","useRef","useEffect","useCallback","jsx","jsxs","compose","translate","scale","useState","useCallback","useRef","useMemo","height","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/toggle-selection/index.js","../node_modules/copy-to-clipboard/index.js","../node_modules/svgson/dist/svgson.umd.js","../src/PCBViewer.tsx","../node_modules/@tscircuit/circuit-json-util/lib/cju.ts","../node_modules/@tscircuit/circuit-json-util/lib/subtree.ts","../node_modules/@tscircuit/circuit-json-util/lib/cju-indexed.ts","../node_modules/@tscircuit/circuit-json-util/lib/transform-soup-elements.ts","../node_modules/@tscircuit/circuit-json-util/lib/direction-to-vec.ts","../node_modules/@tscircuit/circuit-json-util/lib/apply-selector.ts","../node_modules/@tscircuit/circuit-json-util/lib/convert-abbreviation-to-soup-element-type.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-element-id.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-element-by-id.ts","../node_modules/@tscircuit/circuit-json-util/lib/readable-name-functions/get-readable-name-for-pcb-port.ts","../node_modules/@tscircuit/circuit-json-util/lib/readable-name-functions/get-readable-name-for-pcb-smtpad.ts","../node_modules/@tscircuit/circuit-json-util/lib/readable-name-functions/get-readable-name-for-pcb-trace.ts","../node_modules/@tscircuit/circuit-json-util/lib/readable-name-functions/get-readable-name-for-element.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-bounds-of-pcb-elements.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-board-bounds.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-schematic-element-bounds.ts","../node_modules/@tscircuit/circuit-json-util/lib/utils/string-hash.ts","../node_modules/@tscircuit/circuit-json-util/lib/utils/get-layout-debug-object.ts","../node_modules/@tscircuit/circuit-json-util/lib/utils/is-truthy.ts","../node_modules/@tscircuit/circuit-json-util/lib/find-bounds-and-center.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-primary-id.ts","../node_modules/@tscircuit/circuit-json-util/lib/reposition-pcb-component.ts","../node_modules/@tscircuit/circuit-json-util/lib/reposition-pcb-group.ts","../node_modules/@tscircuit/circuit-json-util/lib/reposition-schematic-component.ts","../node_modules/@tscircuit/circuit-json-util/lib/reposition-schematic-group.ts","../node_modules/@tscircuit/circuit-json-util/lib/getCircuitJsonTree.ts","../node_modules/@tscircuit/circuit-json-util/lib/getStringFromCircuitJsonTree.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-minimum-flex-container.ts","../node_modules/@tscircuit/circuit-json-util/lib/get-element-render-layers.ts","../node_modules/@tscircuit/circuit-json-util/lib/shape-distances/geometry.ts","../node_modules/@tscircuit/circuit-json-util/lib/shape-distances/decompose-copper-into-shapes.ts","../node_modules/@tscircuit/circuit-json-util/lib/shape-distances/distance-between-shapes.ts","../node_modules/@tscircuit/circuit-json-util/lib/compute-gap-between-copper.ts","../node_modules/@tscircuit/circuit-json-util/lib/shape-distances/decompose-clearance-into-shapes.ts","../node_modules/@tscircuit/circuit-json-util/lib/compute-clearance-between-elements.ts","../node_modules/@tscircuit/circuit-json-util/lib/analyze-pcb-pin1-location.ts","../node_modules/@tscircuit/circuit-json-util/lib/categorize-error-or-warning.ts","../src/components/ContextProviders.tsx","../src/global-store.ts","../src/hooks/useLocalStorage.ts","../src/lib/toast.tsx","../node_modules/react-use/esm/useMountedState.js","../node_modules/react-use/esm/useSetState.js","../node_modules/react-use/esm/misc/util.js","../node_modules/react-use/esm/useCopyToClipboard.js","../node_modules/react-use/esm/useIsomorphicLayoutEffect.js","../node_modules/react-use/esm/useMeasure.js","../node_modules/use-mouse-matrix-transform/src/computePinchTransform.ts","../node_modules/use-mouse-matrix-transform/src/index.ts","../node_modules/circuit-json-to-connectivity-map/src/findConnectedNetworks.ts","../node_modules/circuit-json-to-connectivity-map/src/ConnectivityMap.ts","../node_modules/circuit-json-to-connectivity-map/src/getSourcePortConnectivityMapFromCircuitJson.ts","../node_modules/circuit-json-to-connectivity-map/src/getFullConnectivityMapFromCircuitJson.ts","../node_modules/circuit-json-to-connectivity-map/src/PcbConnectivityMap.ts","../src/lib/util/expand-stroke.ts","../src/lib/convert-element-to-primitive.ts","../src/lib/element-to-primitive-converters/convert-smtpad-rect.ts","../src/lib/element-to-primitive-converters/convert-smtpad-circle.ts","../src/lib/element-to-primitive-converters/convert-smtpad-polygon.ts","../src/lib/element-to-primitive-converters/convert-smtpad-pill.ts","../src/lib/util/addInteractionMetadataToPrimitives.ts","../src/lib/util/error-preview.ts","../src/lib/util/get-error-id.ts","../src/lib/util/transform-animation.ts","../src/components/CanvasElementsRenderer.tsx","../src/lib/Drawer.ts","../src/lib/colors.ts","../src/lib/util/scale-only.ts","../src/lib/util/z-index-map.ts","../src/lib/copper-layers.ts","../src/lib/draw-copper-pour.ts","../src/lib/draw-courtyard.ts","../src/lib/draw-fabrication-note.ts","../src/lib/draw-hole.ts","../src/lib/draw-pcb-board.ts","../src/lib/draw-pcb-copper-text.ts","../src/lib/draw-pcb-cutout.ts","../src/lib/draw-pcb-keepout.ts","../src/lib/draw-pcb-note.ts","../src/lib/draw-pcb-panel.ts","../src/lib/draw-pcb-smtpad.ts","../src/lib/draw-pcb-trace.ts","../src/lib/draw-plated-hole.ts","../src/lib/util/rotate-text.ts","../src/assets/alphabet.ts","../src/lib/convert-text-to-lines.ts","../src/lib/draw-primitives.ts","../src/lib/draw-silkscreen.ts","../src/lib/draw-soldermask.ts","../src/lib/draw-via.ts","../src/lib/get-primitives-for-drawer.ts","../src/components/CanvasPrimitiveRenderer.tsx","../node_modules/graphics-debug/lib/strokeAlphabetText.ts","../node_modules/iobuffer/src/text.ts","../node_modules/iobuffer/src/iobuffer.ts","../node_modules/fast-png/src/helpers/crc.ts","../node_modules/fast-png/src/helpers/decode_interlace_adam7.ts","../node_modules/fast-png/src/helpers/decode_interlace_null.ts","../node_modules/fast-png/src/helpers/signature.ts","../node_modules/fast-png/src/helpers/text.ts","../node_modules/graphics-debug/lib/infiniteLineHelpers.ts","../node_modules/graphics-debug/lib/constants.ts","../node_modules/graphics-debug/lib/rectGeometry.ts","../node_modules/graphics-debug/lib/arrowHelpers.ts","../node_modules/graphics-debug/site/components/InteractiveGraphics/defaultColors.ts","../node_modules/graphics-debug/lib/drawGraphicsToCanvas.ts","../node_modules/graphics-debug/lib/getPngBufferFromGraphicsObject.ts","../node_modules/graphics-debug/lib/getSvgFromGraphicsObject.ts","../src/components/DebugGraphicsOverlay.tsx","../src/components/DimensionOverlay.tsx","../src/lib/util/get-primitive-bounding-box.ts","../src/hooks/useDiagonalLabel.ts","../src/lib/util/calculate-diagonal-label.ts","../src/lib/util/get-primitive-snap-points.ts","../src/components/EditPlacementOverlay.tsx","../src/components/ErrorOverlay.tsx","../src/lib/util/getPopupPosition.ts","../src/components/FocusMarkerSVG.tsx","../src/components/MouseElementTracker.tsx","../src/lib/util/if-sets-match-exactly.ts","../src/components/AnchorOffsetOverlay/common/guards.ts","../src/components/AnchorOffsetOverlay/AnchorOffsetOverlay.tsx","../src/components/AnchorOffsetOverlay/common/constants.ts","../src/components/AnchorOffsetOverlay/BoardAnchorOffsetOverlay.tsx","../src/components/AnchorOffsetOverlay/GroupAnchorOffsetOverlay.tsx","../src/components/AnchorOffsetOverlay/ComponentBoundingBoxOverlay.tsx","../src/components/AnchorOffsetOverlay/PanelAnchorOffsetOverlay.tsx","../src/lib/get-trace-overlay-text.ts","../src/lib/filter-traces-if-multiple.ts","../src/components/ElementOverlayBox.tsx","../src/components/PcbGroupOverlay.tsx","../src/components/RatsNestOverlay.tsx","../src/components/ToolbarOverlay.tsx","../package.json","../src/hooks/useHotKey.ts","../src/hooks/useIsSmallScreen.ts","../src/hooks/useMobileTouch.ts","../src/components/ToolbarButton.tsx","../src/components/ToolbarErrorDropdown.tsx","../src/lib/util/group-errors-by-type.ts","../src/components/useToolbarErrorFocus.ts","../src/components/WarningGraphicsOverlay.tsx","../src/lib/util/get-pcb-warning-highlight.ts","../src/lib/calculate-circuit-json-key.ts","../src/lib/calculate-board-size-key.ts"],"sourcesContent":["\nmodule.exports = function () {\n var selection = document.getSelection();\n if (!selection.rangeCount) {\n return function () {};\n }\n var active = document.activeElement;\n\n var ranges = [];\n for (var i = 0; i < selection.rangeCount; i++) {\n ranges.push(selection.getRangeAt(i));\n }\n\n switch (active.tagName.toUpperCase()) { // .toUpperCase handles XHTML\n case 'INPUT':\n case 'TEXTAREA':\n active.blur();\n break;\n\n default:\n active = null;\n break;\n }\n\n selection.removeAllRanges();\n return function () {\n selection.type === 'Caret' &&\n selection.removeAllRanges();\n\n if (!selection.rangeCount) {\n ranges.forEach(function(range) {\n selection.addRange(range);\n });\n }\n\n active &&\n active.focus();\n };\n};\n","\"use strict\";\n\nvar deselectCurrent = require(\"toggle-selection\");\n\nvar clipboardToIE11Formatting = {\n \"text/plain\": \"Text\",\n \"text/html\": \"Url\",\n \"default\": \"Text\"\n}\n\nvar defaultMessage = \"Copy to clipboard: #{key}, Enter\";\n\nfunction format(message) {\n var copyKey = (/mac os x/i.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\") + \"+C\";\n return message.replace(/#{\\s*key\\s*}/g, copyKey);\n}\n\nfunction copy(text, options) {\n var debug,\n message,\n reselectPrevious,\n range,\n selection,\n mark,\n success = false;\n if (!options) {\n options = {};\n }\n debug = options.debug || false;\n try {\n reselectPrevious = deselectCurrent();\n\n range = document.createRange();\n selection = document.getSelection();\n\n mark = document.createElement(\"span\");\n mark.textContent = text;\n // avoid screen readers from reading out loud the text\n mark.ariaHidden = \"true\"\n // reset user styles for span element\n mark.style.all = \"unset\";\n // prevents scrolling to the end of the page\n mark.style.position = \"fixed\";\n mark.style.top = 0;\n mark.style.clip = \"rect(0, 0, 0, 0)\";\n // used to preserve spaces and line breaks\n mark.style.whiteSpace = \"pre\";\n // do not inherit user-select (it may be `none`)\n mark.style.webkitUserSelect = \"text\";\n mark.style.MozUserSelect = \"text\";\n mark.style.msUserSelect = \"text\";\n mark.style.userSelect = \"text\";\n mark.addEventListener(\"copy\", function(e) {\n e.stopPropagation();\n if (options.format) {\n e.preventDefault();\n if (typeof e.clipboardData === \"undefined\") { // IE 11\n debug && console.warn(\"unable to use e.clipboardData\");\n debug && console.warn(\"trying IE specific stuff\");\n window.clipboardData.clearData();\n var format = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting[\"default\"]\n window.clipboardData.setData(format, text);\n } else { // all other browsers\n e.clipboardData.clearData();\n e.clipboardData.setData(options.format, text);\n }\n }\n if (options.onCopy) {\n e.preventDefault();\n options.onCopy(e.clipboardData);\n }\n });\n\n document.body.appendChild(mark);\n\n range.selectNodeContents(mark);\n selection.addRange(range);\n\n var successful = document.execCommand(\"copy\");\n if (!successful) {\n throw new Error(\"copy command was unsuccessful\");\n }\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using execCommand: \", err);\n debug && console.warn(\"trying IE specific stuff\");\n try {\n window.clipboardData.setData(options.format || \"text\", text);\n options.onCopy && options.onCopy(window.clipboardData);\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using clipboardData: \", err);\n debug && console.error(\"falling back to prompt\");\n message = format(\"message\" in options ? options.message : defaultMessage);\n window.prompt(message, text);\n }\n } finally {\n if (selection) {\n if (typeof selection.removeRange == \"function\") {\n selection.removeRange(range);\n } else {\n selection.removeAllRanges();\n }\n }\n\n if (mark) {\n document.body.removeChild(mark);\n }\n reselectPrevious();\n }\n\n return success;\n}\n\nmodule.exports = copy;\n","(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.svgson = factory());\n})(this, (function () { 'use strict';\n\n /*!\n * Determine if an object is a Buffer\n *\n * @author Feross Aboukhadijeh <https://feross.org>\n * @license MIT\n */\n\n // The _isBuffer check is for Safari 5-7 support, because it's missing\n // Object.prototype.constructor. Remove this eventually\n var isBuffer_1 = function (obj) {\n return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)\n };\n\n function isBuffer (obj) {\n return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)\n }\n\n // For Node v0.10 support. Remove this eventually.\n function isSlowBuffer (obj) {\n return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))\n }\n\n var toString = Object.prototype.toString;\n\n /**\n * Get the native `typeof` a value.\n *\n * @param {*} `val`\n * @return {*} Native javascript type\n */\n\n var kindOf = function kindOf(val) {\n // primitivies\n if (typeof val === 'undefined') {\n return 'undefined';\n }\n if (val === null) {\n return 'null';\n }\n if (val === true || val === false || val instanceof Boolean) {\n return 'boolean';\n }\n if (typeof val === 'string' || val instanceof String) {\n return 'string';\n }\n if (typeof val === 'number' || val instanceof Number) {\n return 'number';\n }\n\n // functions\n if (typeof val === 'function' || val instanceof Function) {\n return 'function';\n }\n\n // array\n if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {\n return 'array';\n }\n\n // check for instances of RegExp and Date before calling `toString`\n if (val instanceof RegExp) {\n return 'regexp';\n }\n if (val instanceof Date) {\n return 'date';\n }\n\n // other objects\n var type = toString.call(val);\n\n if (type === '[object RegExp]') {\n return 'regexp';\n }\n if (type === '[object Date]') {\n return 'date';\n }\n if (type === '[object Arguments]') {\n return 'arguments';\n }\n if (type === '[object Error]') {\n return 'error';\n }\n\n // buffer\n if (isBuffer_1(val)) {\n return 'buffer';\n }\n\n // es6: Map, WeakMap, Set, WeakSet\n if (type === '[object Set]') {\n return 'set';\n }\n if (type === '[object WeakSet]') {\n return 'weakset';\n }\n if (type === '[object Map]') {\n return 'map';\n }\n if (type === '[object WeakMap]') {\n return 'weakmap';\n }\n if (type === '[object Symbol]') {\n return 'symbol';\n }\n\n // typed arrays\n if (type === '[object Int8Array]') {\n return 'int8array';\n }\n if (type === '[object Uint8Array]') {\n return 'uint8array';\n }\n if (type === '[object Uint8ClampedArray]') {\n return 'uint8clampedarray';\n }\n if (type === '[object Int16Array]') {\n return 'int16array';\n }\n if (type === '[object Uint16Array]') {\n return 'uint16array';\n }\n if (type === '[object Int32Array]') {\n return 'int32array';\n }\n if (type === '[object Uint32Array]') {\n return 'uint32array';\n }\n if (type === '[object Float32Array]') {\n return 'float32array';\n }\n if (type === '[object Float64Array]') {\n return 'float64array';\n }\n\n // must be a plain object\n return 'object';\n };\n\n function createCommonjsModule(fn, module) {\n \treturn module = { exports: {} }, fn(module, module.exports), module.exports;\n }\n\n var renameKeys = createCommonjsModule(function (module) {\n (function() {\n\n function rename(obj, fn) {\n if (typeof fn !== 'function') {\n return obj;\n }\n\n var res = {};\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n res[fn(key, obj[key]) || key] = obj[key];\n }\n }\n return res;\n }\n\n if (module.exports) {\n module.exports = rename;\n } else {\n {\n window.rename = rename;\n }\n }\n })();\n });\n\n /**\n * Expose `renameDeep`\n */\n\n var deepRenameKeys = function renameDeep(obj, cb) {\n var type = kindOf(obj);\n\n if (type !== 'object' && type !== 'array') {\n throw new Error('expected an object');\n }\n\n var res = [];\n if (type === 'object') {\n obj = renameKeys(obj, cb);\n res = {};\n }\n\n for (var key in obj) {\n if (obj.hasOwnProperty(key)) {\n var val = obj[key];\n if (kindOf(val) === 'object' || kindOf(val) === 'array') {\n res[key] = renameDeep(val, cb);\n } else {\n res[key] = val;\n }\n }\n }\n return res;\n };\n\n var eventemitter3 = createCommonjsModule(function (module) {\n\n var has = Object.prototype.hasOwnProperty\n , prefix = '~';\n\n /**\n * Constructor to create a storage for our `EE` objects.\n * An `Events` instance is a plain object whose properties are event names.\n *\n * @constructor\n * @api private\n */\n function Events() {}\n\n //\n // We try to not inherit from `Object.prototype`. In some engines creating an\n // instance in this way is faster than calling `Object.create(null)` directly.\n // If `Object.create(null)` is not supported we prefix the event names with a\n // character to make sure that the built-in object properties are not\n // overridden or used as an attack vector.\n //\n if (Object.create) {\n Events.prototype = Object.create(null);\n\n //\n // This hack is needed because the `__proto__` property is still inherited in\n // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.\n //\n if (!new Events().__proto__) prefix = false;\n }\n\n /**\n * Representation of a single event listener.\n *\n * @param {Function} fn The listener function.\n * @param {Mixed} context The context to invoke the listener with.\n * @param {Boolean} [once=false] Specify if the listener is a one-time listener.\n * @constructor\n * @api private\n */\n function EE(fn, context, once) {\n this.fn = fn;\n this.context = context;\n this.once = once || false;\n }\n\n /**\n * Minimal `EventEmitter` interface that is molded against the Node.js\n * `EventEmitter` interface.\n *\n * @constructor\n * @api public\n */\n function EventEmitter() {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n /**\n * Return an array listing the events for which the emitter has registered\n * listeners.\n *\n * @returns {Array}\n * @api public\n */\n EventEmitter.prototype.eventNames = function eventNames() {\n var names = []\n , events\n , name;\n\n if (this._eventsCount === 0) return names;\n\n for (name in (events = this._events)) {\n if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);\n }\n\n if (Object.getOwnPropertySymbols) {\n return names.concat(Object.getOwnPropertySymbols(events));\n }\n\n return names;\n };\n\n /**\n * Return the listeners registered for a given event.\n *\n * @param {String|Symbol} event The event name.\n * @param {Boolean} exists Only check if there are listeners.\n * @returns {Array|Boolean}\n * @api public\n */\n EventEmitter.prototype.listeners = function listeners(event, exists) {\n var evt = prefix ? prefix + event : event\n , available = this._events[evt];\n\n if (exists) return !!available;\n if (!available) return [];\n if (available.fn) return [available.fn];\n\n for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) {\n ee[i] = available[i].fn;\n }\n\n return ee;\n };\n\n /**\n * Calls each of the listeners registered for a given event.\n *\n * @param {String|Symbol} event The event name.\n * @returns {Boolean} `true` if the event had listeners, else `false`.\n * @api public\n */\n EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return false;\n\n var listeners = this._events[evt]\n , len = arguments.length\n , args\n , i;\n\n if (listeners.fn) {\n if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);\n\n switch (len) {\n case 1: return listeners.fn.call(listeners.context), true;\n case 2: return listeners.fn.call(listeners.context, a1), true;\n case 3: return listeners.fn.call(listeners.context, a1, a2), true;\n case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;\n case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;\n case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;\n }\n\n for (i = 1, args = new Array(len -1); i < len; i++) {\n args[i - 1] = arguments[i];\n }\n\n listeners.fn.apply(listeners.context, args);\n } else {\n var length = listeners.length\n , j;\n\n for (i = 0; i < length; i++) {\n if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);\n\n switch (len) {\n case 1: listeners[i].fn.call(listeners[i].context); break;\n case 2: listeners[i].fn.call(listeners[i].context, a1); break;\n case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;\n case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;\n default:\n if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {\n args[j - 1] = arguments[j];\n }\n\n listeners[i].fn.apply(listeners[i].context, args);\n }\n }\n }\n\n return true;\n };\n\n /**\n * Add a listener for a given event.\n *\n * @param {String|Symbol} event The event name.\n * @param {Function} fn The listener function.\n * @param {Mixed} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @api public\n */\n EventEmitter.prototype.on = function on(event, fn, context) {\n var listener = new EE(fn, context || this)\n , evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) this._events[evt] = listener, this._eventsCount++;\n else if (!this._events[evt].fn) this._events[evt].push(listener);\n else this._events[evt] = [this._events[evt], listener];\n\n return this;\n };\n\n /**\n * Add a one-time listener for a given event.\n *\n * @param {String|Symbol} event The event name.\n * @param {Function} fn The listener function.\n * @param {Mixed} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @api public\n */\n EventEmitter.prototype.once = function once(event, fn, context) {\n var listener = new EE(fn, context || this, true)\n , evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) this._events[evt] = listener, this._eventsCount++;\n else if (!this._events[evt].fn) this._events[evt].push(listener);\n else this._events[evt] = [this._events[evt], listener];\n\n return this;\n };\n\n /**\n * Remove the listeners of a given event.\n *\n * @param {String|Symbol} event The event name.\n * @param {Function} fn Only remove the listeners that match this function.\n * @param {Mixed} context Only remove the listeners that have this context.\n * @param {Boolean} once Only remove one-time listeners.\n * @returns {EventEmitter} `this`.\n * @api public\n */\n EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return this;\n if (!fn) {\n if (--this._eventsCount === 0) this._events = new Events();\n else delete this._events[evt];\n return this;\n }\n\n var listeners = this._events[evt];\n\n if (listeners.fn) {\n if (\n listeners.fn === fn\n && (!once || listeners.once)\n && (!context || listeners.context === context)\n ) {\n if (--this._eventsCount === 0) this._events = new Events();\n else delete this._events[evt];\n }\n } else {\n for (var i = 0, events = [], length = listeners.length; i < length; i++) {\n if (\n listeners[i].fn !== fn\n || (once && !listeners[i].once)\n || (context && listeners[i].context !== context)\n ) {\n events.push(listeners[i]);\n }\n }\n\n //\n // Reset the array, or remove it completely if we have no more listeners.\n //\n if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;\n else if (--this._eventsCount === 0) this._events = new Events();\n else delete this._events[evt];\n }\n\n return this;\n };\n\n /**\n * Remove all listeners, or those of the specified event.\n *\n * @param {String|Symbol} [event] The event name.\n * @returns {EventEmitter} `this`.\n * @api public\n */\n EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {\n var evt;\n\n if (event) {\n evt = prefix ? prefix + event : event;\n if (this._events[evt]) {\n if (--this._eventsCount === 0) this._events = new Events();\n else delete this._events[evt];\n }\n } else {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n return this;\n };\n\n //\n // Alias methods names because people roll like that.\n //\n EventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n EventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n //\n // This function doesn't apply anymore.\n //\n EventEmitter.prototype.setMaxListeners = function setMaxListeners() {\n return this;\n };\n\n //\n // Expose the prefix.\n //\n EventEmitter.prefixed = prefix;\n\n //\n // Allow `EventEmitter` to be imported as module namespace.\n //\n EventEmitter.EventEmitter = EventEmitter;\n\n //\n // Expose the module.\n //\n {\n module.exports = EventEmitter;\n }\n });\n\n function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n\n var noop = function noop() {};\n\n var State = {\n data: 'state-data',\n cdata: 'state-cdata',\n tagBegin: 'state-tag-begin',\n tagName: 'state-tag-name',\n tagEnd: 'state-tag-end',\n attributeNameStart: 'state-attribute-name-start',\n attributeName: 'state-attribute-name',\n attributeNameEnd: 'state-attribute-name-end',\n attributeValueBegin: 'state-attribute-value-begin',\n attributeValue: 'state-attribute-value'\n };\n\n var Action = {\n lt: 'action-lt',\n gt: 'action-gt',\n space: 'action-space',\n equal: 'action-equal',\n quote: 'action-quote',\n slash: 'action-slash',\n char: 'action-char',\n error: 'action-error'\n };\n\n var Type$1 = {\n text: 'text',\n openTag: 'open-tag',\n closeTag: 'close-tag',\n attributeName: 'attribute-name',\n attributeValue: 'attribute-value'\n };\n\n var charToAction = {\n ' ': Action.space,\n '\\t': Action.space,\n '\\n': Action.space,\n '\\r': Action.space,\n '<': Action.lt,\n '>': Action.gt,\n '\"': Action.quote,\n \"'\": Action.quote,\n '=': Action.equal,\n '/': Action.slash\n };\n\n var getAction = function getAction(char) {\n return charToAction[char] || Action.char;\n };\n\n /**\n * @param {Object} options\n * @param {Boolean} options.debug\n * @return {Object}\n */\n var create$1 = function create(options) {\n var _State$data, _State$tagBegin, _State$tagName, _State$tagEnd, _State$attributeNameS, _State$attributeName, _State$attributeNameE, _State$attributeValue, _State$attributeValue2, _lexer$stateMachine;\n\n options = Object.assign({ debug: false }, options);\n var lexer = new eventemitter3();\n var state = State.data;\n var data = '';\n var tagName = '';\n var attrName = '';\n var attrValue = '';\n var isClosing = '';\n var openingQuote = '';\n\n var emit = function emit(type, value) {\n // for now, ignore tags like: '?xml', '!DOCTYPE' or comments\n if (tagName[0] === '?' || tagName[0] === '!') {\n return;\n }\n var event = { type: type, value: value };\n if (options.debug) {\n console.log('emit:', event);\n }\n lexer.emit('data', event);\n };\n\n lexer.stateMachine = (_lexer$stateMachine = {}, _defineProperty(_lexer$stateMachine, State.data, (_State$data = {}, _defineProperty(_State$data, Action.lt, function () {\n if (data.trim()) {\n emit(Type$1.text, data);\n }\n tagName = '';\n isClosing = false;\n state = State.tagBegin;\n }), _defineProperty(_State$data, Action.char, function (char) {\n data += char;\n }), _State$data)), _defineProperty(_lexer$stateMachine, State.cdata, _defineProperty({}, Action.char, function (char) {\n data += char;\n if (data.substr(-3) === ']]>') {\n emit(Type$1.text, data.slice(0, -3));\n data = '';\n state = State.data;\n }\n })), _defineProperty(_lexer$stateMachine, State.tagBegin, (_State$tagBegin = {}, _defineProperty(_State$tagBegin, Action.space, noop), _defineProperty(_State$tagBegin, Action.char, function (char) {\n tagName = char;\n state = State.tagName;\n }), _defineProperty(_State$tagBegin, Action.slash, function () {\n tagName = '';\n isClosing = true;\n }), _State$tagBegin)), _defineProperty(_lexer$stateMachine, State.tagName, (_State$tagName = {}, _defineProperty(_State$tagName, Action.space, function () {\n if (isClosing) {\n state = State.tagEnd;\n } else {\n state = State.attributeNameStart;\n emit(Type$1.openTag, tagName);\n }\n }), _defineProperty(_State$tagName, Action.gt, function () {\n if (isClosing) {\n emit(Type$1.closeTag, tagName);\n } else {\n emit(Type$1.openTag, tagName);\n }\n data = '';\n state = State.data;\n }), _defineProperty(_State$tagName, Action.slash, function () {\n state = State.tagEnd;\n emit(Type$1.openTag, tagName);\n }), _defineProperty(_State$tagName, Action.char, function (char) {\n tagName += char;\n if (tagName === '![CDATA[') {\n state = State.cdata;\n data = '';\n tagName = '';\n }\n }), _State$tagName)), _defineProperty(_lexer$stateMachine, State.tagEnd, (_State$tagEnd = {}, _defineProperty(_State$tagEnd, Action.gt, function () {\n emit(Type$1.closeTag, tagName);\n data = '';\n state = State.data;\n }), _defineProperty(_State$tagEnd, Action.char, noop), _State$tagEnd)), _defineProperty(_lexer$stateMachine, State.attributeNameStart, (_State$attributeNameS = {}, _defineProperty(_State$attributeNameS, Action.char, function (char) {\n attrName = char;\n state = State.attributeName;\n }), _defineProperty(_State$attributeNameS, Action.gt, function () {\n data = '';\n state = State.data;\n }), _defineProperty(_State$attributeNameS, Action.space, noop), _defineProperty(_State$attributeNameS, Action.slash, function () {\n isClosing = true;\n state = State.tagEnd;\n }), _State$attributeNameS)), _defineProperty(_lexer$stateMachine, State.attributeName, (_State$attributeName = {}, _defineProperty(_State$attributeName, Action.space, function () {\n state = State.attributeNameEnd;\n }), _defineProperty(_State$attributeName, Action.equal, function () {\n emit(Type$1.attributeName, attrName);\n state = State.attributeValueBegin;\n }), _defineProperty(_State$attributeName, Action.gt, function () {\n attrValue = '';\n emit(Type$1.attributeName, attrName);\n emit(Type$1.attributeValue, attrValue);\n data = '';\n state = State.data;\n }), _defineProperty(_State$attributeName, Action.slash, function () {\n isClosing = true;\n attrValue = '';\n emit(Type$1.attributeName, attrName);\n emit(Type$1.attributeValue, attrValue);\n state = State.tagEnd;\n }), _defineProperty(_State$attributeName, Action.char, function (char) {\n attrName += char;\n }), _State$attributeName)), _defineProperty(_lexer$stateMachine, State.attributeNameEnd, (_State$attributeNameE = {}, _defineProperty(_State$attributeNameE, Action.space, noop), _defineProperty(_State$attributeNameE, Action.equal, function () {\n emit(Type$1.attributeName, attrName);\n state = State.attributeValueBegin;\n }), _defineProperty(_State$attributeNameE, Action.gt, function () {\n attrValue = '';\n emit(Type$1.attributeName, attrName);\n emit(Type$1.attributeValue, attrValue);\n data = '';\n state = State.data;\n }), _defineProperty(_State$attributeNameE, Action.char, function (char) {\n attrValue = '';\n emit(Type$1.attributeName, attrName);\n emit(Type$1.attributeValue, attrValue);\n attrName = char;\n state = State.attributeName;\n }), _State$attributeNameE)), _defineProperty(_lexer$stateMachine, State.attributeValueBegin, (_State$attributeValue = {}, _defineProperty(_State$attributeValue, Action.space, noop), _defineProperty(_State$attributeValue, Action.quote, function (char) {\n openingQuote = char;\n attrValue = '';\n state = State.attributeValue;\n }), _defineProperty(_State$attributeValue, Action.gt, function () {\n attrValue = '';\n emit(Type$1.attributeValue, attrValue);\n data = '';\n state = State.data;\n }), _defineProperty(_State$attributeValue, Action.char, function (char) {\n openingQuote = '';\n attrValue = char;\n state = State.attributeValue;\n }), _State$attributeValue)), _defineProperty(_lexer$stateMachine, State.attributeValue, (_State$attributeValue2 = {}, _defineProperty(_State$attributeValue2, Action.space, function (char) {\n if (openingQuote) {\n attrValue += char;\n } else {\n emit(Type$1.attributeValue, attrValue);\n state = State.attributeNameStart;\n }\n }), _defineProperty(_State$attributeValue2, Action.quote, function (char) {\n if (openingQuote === char) {\n emit(Type$1.attributeValue, attrValue);\n state = State.attributeNameStart;\n } else {\n attrValue += char;\n }\n }), _defineProperty(_State$attributeValue2, Action.gt, function (char) {\n if (openingQuote) {\n attrValue += char;\n } else {\n emit(Type$1.attributeValue, attrValue);\n data = '';\n state = State.data;\n }\n }), _defineProperty(_State$attributeValue2, Action.slash, function (char) {\n if (openingQuote) {\n attrValue += char;\n } else {\n emit(Type$1.attributeValue, attrValue);\n isClosing = true;\n state = State.tagEnd;\n }\n }), _defineProperty(_State$attributeValue2, Action.char, function (char) {\n attrValue += char;\n }), _State$attributeValue2)), _lexer$stateMachine);\n\n var step = function step(char) {\n if (options.debug) {\n console.log(state, char);\n }\n var actions = lexer.stateMachine[state];\n var action = actions[getAction(char)] || actions[Action.error] || actions[Action.char];\n action(char);\n };\n\n lexer.write = function (str) {\n var len = str.length;\n for (var i = 0; i < len; i++) {\n step(str[i]);\n }\n };\n\n return lexer;\n };\n\n var lexer = {\n State: State,\n Action: Action,\n Type: Type$1,\n create: create$1\n };\n\n var Type = lexer.Type;\n\n var NodeType = {\n element: 'element',\n text: 'text'\n };\n\n var createNode = function createNode(params) {\n return Object.assign({\n name: '',\n type: NodeType.element,\n value: '',\n parent: null,\n attributes: {},\n children: []\n }, params);\n };\n\n var create = function create(options) {\n options = Object.assign({\n stream: false,\n parentNodes: true,\n doneEvent: 'done',\n tagPrefix: 'tag:',\n emitTopLevelOnly: false,\n debug: false\n }, options);\n\n var lexer$1 = void 0,\n rootNode = void 0,\n current = void 0,\n attrName = void 0;\n\n var reader = new eventemitter3();\n\n var handleLexerData = function handleLexerData(data) {\n switch (data.type) {\n\n case Type.openTag:\n if (current === null) {\n current = rootNode;\n current.name = data.value;\n } else {\n var node = createNode({\n name: data.value,\n parent: current\n });\n current.children.push(node);\n current = node;\n }\n break;\n\n case Type.closeTag:\n var parent = current.parent;\n if (!options.parentNodes) {\n current.parent = null;\n }\n if (current.name !== data.value) {\n // ignore unexpected closing tag\n break;\n }\n if (options.stream && parent === rootNode) {\n rootNode.children = [];\n // do not expose parent node in top level nodes\n current.parent = null;\n }\n if (!options.emitTopLevelOnly || parent === rootNode) {\n reader.emit(options.tagPrefix + current.name, current);\n reader.emit('tag', current.name, current);\n }\n if (current === rootNode) {\n // end of document, stop listening\n lexer$1.removeAllListeners('data');\n reader.emit(options.doneEvent, current);\n rootNode = null;\n }\n current = parent;\n break;\n\n case Type.text:\n if (current) {\n current.children.push(createNode({\n type: NodeType.text,\n value: data.value,\n parent: options.parentNodes ? current : null\n }));\n }\n break;\n\n case Type.attributeName:\n attrName = data.value;\n current.attributes[attrName] = '';\n break;\n\n case Type.attributeValue:\n current.attributes[attrName] = data.value;\n break;\n }\n };\n\n reader.reset = function () {\n lexer$1 = lexer.create({ debug: options.debug });\n lexer$1.on('data', handleLexerData);\n rootNode = createNode();\n current = null;\n attrName = '';\n reader.parse = lexer$1.write;\n };\n\n reader.reset();\n return reader;\n };\n\n var parseSync = function parseSync(xml, options) {\n options = Object.assign({}, options, { stream: false, tagPrefix: ':' });\n var reader = create(options);\n var res = void 0;\n reader.on('done', function (ast) {\n res = ast;\n });\n reader.parse(xml);\n return res;\n };\n\n var reader = {\n parseSync: parseSync,\n create: create,\n NodeType: NodeType\n };\n var reader_1 = reader.parseSync;\n\n var parseInput = function parseInput(input) {\n var parsed = reader_1(\"<root>\".concat(input, \"</root>\"), {\n parentNodes: false\n });\n var isValid = parsed.children && parsed.children.length > 0 && parsed.children.every(function (node) {\n return node.name === 'svg';\n });\n if (isValid) {\n return parsed.children.length === 1 ? parsed.children[0] : parsed.children;\n } else {\n throw Error('nothing to parse');\n }\n };\n var camelize = function camelize(node) {\n return deepRenameKeys(node, function (key) {\n if (!notCamelcase(key)) {\n return toCamelCase(key);\n }\n return key;\n });\n };\n var toCamelCase = function toCamelCase(prop) {\n return prop.replace(/[-|:]([a-z])/gi, function (all, letter) {\n return letter.toUpperCase();\n });\n };\n var notCamelcase = function notCamelcase(prop) {\n return /^(data|aria)(-\\w+)/.test(prop);\n };\n var escapeText = function escapeText(text) {\n if (text) {\n var str = String(text);\n return /[&<>]/.test(str) ? \"<![CDATA[\".concat(str.replace(/]]>/, ']]]]><![CDATA[>'), \"]]>\") : str;\n }\n return '';\n };\n var escapeAttr = function escapeAttr(attr) {\n return String(attr).replace(/&/g, '&').replace(/'/g, ''').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g, '>');\n };\n\n var svgsonSync = function svgsonSync(input) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$transformNode = _ref.transformNode,\n transformNode = _ref$transformNode === void 0 ? function (node) {\n return node;\n } : _ref$transformNode,\n _ref$camelcase = _ref.camelcase,\n camelcase = _ref$camelcase === void 0 ? false : _ref$camelcase;\n var applyFilters = function applyFilters(input) {\n var n;\n n = transformNode(input);\n if (camelcase) {\n n = camelize(n);\n }\n return n;\n };\n return applyFilters(parseInput(input));\n };\n function svgson() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return new Promise(function (resolve, reject) {\n try {\n var res = svgsonSync.apply(void 0, args);\n resolve(res);\n } catch (e) {\n reject(e);\n }\n });\n }\n\n var stringify = function stringify(_ast) {\n var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n _ref$transformAttr = _ref.transformAttr,\n transformAttr = _ref$transformAttr === void 0 ? function (key, value, escape) {\n return \"\".concat(key, \"=\\\"\").concat(escape(value), \"\\\"\");\n } : _ref$transformAttr,\n _ref$transformNode = _ref.transformNode,\n transformNode = _ref$transformNode === void 0 ? function (node) {\n return node;\n } : _ref$transformNode,\n _ref$selfClose = _ref.selfClose,\n selfClose = _ref$selfClose === void 0 ? true : _ref$selfClose;\n if (Array.isArray(_ast)) {\n return _ast.map(function (ast) {\n return stringify(ast, {\n transformAttr: transformAttr,\n selfClose: selfClose,\n transformNode: transformNode\n });\n }).join('');\n }\n var ast = transformNode(_ast);\n if (ast.type === 'text') {\n return escapeText(ast.value);\n }\n var attributes = '';\n for (var attr in ast.attributes) {\n var attrStr = transformAttr(attr, ast.attributes[attr], escapeAttr, ast.name);\n attributes += attrStr ? \" \".concat(attrStr) : '';\n }\n return ast.children && ast.children.length > 0 || !selfClose ? \"<\".concat(ast.name).concat(attributes, \">\").concat(stringify(ast.children, {\n transformAttr: transformAttr,\n transformNode: transformNode,\n selfClose: selfClose\n }), \"</\").concat(ast.name, \">\") : \"<\".concat(ast.name).concat(attributes, \"/>\");\n };\n\n var indexUmd = Object.assign({}, {\n parse: svgson,\n parseSync: svgsonSync,\n stringify: stringify\n });\n\n return indexUmd;\n\n}));\n","import { applyEditEvents } from \"@tscircuit/core\"\nimport { findBoundsAndCenter } from \"@tscircuit/circuit-json-util\"\nimport type { AnyCircuitElement, SourceTrace } from \"circuit-json\"\nimport { ContextProviders } from \"./components/ContextProviders\"\nimport type { StateProps } from \"./global-store\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { ToastContainer } from \"lib/toast\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport { compose, scale, translate } from \"transformation-matrix\"\nimport useMouseMatrixTransform from \"use-mouse-matrix-transform\"\nimport { CanvasElementsRenderer } from \"./components/CanvasElementsRenderer\"\nimport type { BoundsSelection } from \"./components/DimensionOverlay\"\nimport type { ManualEditEvent } from \"@tscircuit/props\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { calculateCircuitJsonKey } from \"lib/calculate-circuit-json-key\"\nimport { calculateBoardSizeKey } from \"lib/calculate-board-size-key\"\n\nconst defaultTransform = compose(translate(400, 300), scale(40, -40))\n\ntype Props = {\n circuitJson?: AnyCircuitElement[]\n height?: number\n allowEditing?: boolean\n editEvents?: ManualEditEvent[]\n initialState?: Partial<StateProps>\n onEditEventsChanged?: (editEvents: ManualEditEvent[]) => void\n onBoundsSelected?: (bounds: BoundsSelection) => void\n focusOnHover?: boolean\n clickToInteractEnabled?: boolean\n debugGraphics?: GraphicsObject | null\n disablePcbGroups?: boolean\n}\n\nexport const PCBViewer = ({\n circuitJson,\n debugGraphics,\n height = 600,\n initialState,\n allowEditing = true,\n editEvents: editEventsProp,\n onEditEventsChanged,\n onBoundsSelected,\n focusOnHover = false,\n clickToInteractEnabled = false,\n disablePcbGroups = false,\n}: Props) => {\n const [isInteractionEnabled, setIsInteractionEnabled] = useState(\n !clickToInteractEnabled,\n )\n const [ref, refDimensions] = useMeasure()\n const [transform, setTransformInternal] = useState(defaultTransform)\n const shouldAllowCanvasInteraction = useCallback(\n (event: MouseEvent | TouchEvent | WheelEvent) => {\n const target = event.target\n if (!(target instanceof Element)) return true\n\n return !target.closest(\"[data-toolbar-overlay]\")\n },\n [],\n )\n\n const {\n ref: transformRef,\n setTransform,\n cancelDrag: cancelPanDrag,\n } = useMouseMatrixTransform({\n transform,\n onSetTransform: setTransformInternal,\n enabled: isInteractionEnabled,\n shouldDrag: shouldAllowCanvasInteraction,\n })\n\n let [editEvents, setEditEvents] = useState<ManualEditEvent[]>([])\n editEvents = editEventsProp ?? editEvents\n\n const initialRenderCompleted = useRef(false)\n const touchStartRef = useRef<{ x: number; y: number } | null>(null)\n const circuitJsonKey = useMemo(\n () => calculateCircuitJsonKey(circuitJson),\n [circuitJson],\n )\n const boardSizeKey = calculateBoardSizeKey(circuitJson)\n\n const resetTransform = () => {\n const elmBounds =\n refDimensions?.width > 0 ? refDimensions : { width: 500, height: 500 }\n const { center, width, height } = elements.some((e) =>\n e.type.startsWith(\"pcb_\"),\n )\n ? findBoundsAndCenter(\n elements.filter((e) => e.type.startsWith(\"pcb_\")) as any,\n )\n : { center: { x: 0, y: 0 }, width: 0.001, height: 0.001 }\n const scaleFactor =\n Math.min(\n (elmBounds.width ?? 0) / width,\n (elmBounds.height ?? 0) / height,\n 100,\n ) * 0.75\n\n const targetTransform = compose(\n translate((elmBounds.width ?? 0) / 2, (elmBounds.height ?? 0) / 2),\n scale(scaleFactor, -scaleFactor, 0, 0),\n translate(-center.x, -center.y),\n )\n\n setTransform(targetTransform)\n return\n }\n\n useEffect(() => {\n if (!refDimensions?.width) return\n if (!circuitJson) return\n if (circuitJson.length === 0) return\n\n if (!initialRenderCompleted.current) {\n resetTransform()\n initialRenderCompleted.current = true\n }\n }, [circuitJson, refDimensions])\n\n useEffect(() => {\n if (initialRenderCompleted.current === true) {\n resetTransform()\n }\n }, [boardSizeKey])\n\n const pcbElmsPreEdit = useMemo(() => {\n return (\n circuitJson?.filter(\n (e: any) => e.type.startsWith(\"pcb_\") || e.type.startsWith(\"source_\"),\n ) ?? []\n )\n }, [circuitJsonKey])\n\n const elements = useMemo(() => {\n return applyEditEvents({\n circuitJson: pcbElmsPreEdit as any,\n editEvents,\n })\n }, [pcbElmsPreEdit, editEvents])\n\n const onCreateEditEvent = (event: ManualEditEvent) => {\n setEditEvents([...editEvents, event])\n onEditEventsChanged?.([...editEvents, event])\n }\n const onModifyEditEvent = (modifiedEvent: Partial<ManualEditEvent>) => {\n const newEditEvents: ManualEditEvent[] = editEvents.map((e) =>\n e.edit_event_id === modifiedEvent.edit_event_id\n ? ({ ...e, ...modifiedEvent } as ManualEditEvent)\n : e,\n )\n setEditEvents(newEditEvents)\n onEditEventsChanged?.(newEditEvents)\n }\n\n const mergedInitialState = useMemo(\n () => ({\n ...initialState,\n ...(disablePcbGroups && { is_showing_pcb_groups: false }),\n }),\n [initialState, disablePcbGroups],\n )\n\n return (\n <div\n ref={transformRef as any}\n style={{ position: \"relative\" }}\n onContextMenu={(event) => event.preventDefault()}\n >\n <div ref={ref as any}>\n <ContextProviders\n initialState={mergedInitialState}\n disablePcbGroups={disablePcbGroups}\n >\n <CanvasElementsRenderer\n key={refDimensions.width}\n transform={transform}\n setTransform={setTransform}\n height={height}\n width={refDimensions.width}\n allowEditing={allowEditing}\n focusOnHover={focusOnHover}\n onBoundsSelected={onBoundsSelected}\n cancelPanDrag={cancelPanDrag}\n onCreateEditEvent={onCreateEditEvent}\n onModifyEditEvent={onModifyEditEvent}\n grid={{\n spacing: 1,\n view_window: {\n left: 0,\n right: refDimensions.width || 500,\n top: height,\n bottom: 0,\n },\n }}\n elements={elements as SourceTrace[]}\n debugGraphics={debugGraphics}\n />\n <ToastContainer />\n </ContextProviders>\n </div>\n {clickToInteractEnabled && !isInteractionEnabled && (\n <div\n onClick={() => {\n setIsInteractionEnabled(true)\n resetTransform()\n }}\n onTouchStart={(e) => {\n const touch = e.touches[0]\n touchStartRef.current = {\n x: touch.clientX,\n y: touch.clientY,\n }\n }}\n onTouchEnd={(e) => {\n const touch = e.changedTouches[0]\n const start = touchStartRef.current\n if (!start) return\n\n const deltaX = Math.abs(touch.clientX - start.x)\n const deltaY = Math.abs(touch.clientY - start.y)\n\n if (deltaX < 10 && deltaY < 10) {\n e.preventDefault()\n setIsInteractionEnabled(true)\n resetTransform()\n }\n\n touchStartRef.current = null\n }}\n style={{\n position: \"absolute\",\n inset: 0,\n cursor: \"pointer\",\n zIndex: zIndexMap.clickToInteractOverlay,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n touchAction: \"pan-x pan-y pinch-zoom\",\n }}\n >\n <div\n style={{\n backgroundColor: \"rgba(0, 0, 0, 0.8)\",\n color: \"white\",\n padding: \"12px 24px\",\n borderRadius: \"8px\",\n fontSize: \"16px\",\n pointerEvents: \"none\",\n }}\n >\n {typeof window !== \"undefined\" &&\n (\"ontouchstart\" in window || navigator.maxTouchPoints > 0)\n ? \"Touch to Interact\"\n : \"Click to Interact\"}\n </div>\n </div>\n )}\n </div>\n )\n}\n","import type {\n AnyCircuitElement,\n AnyCircuitElementInput,\n SourceComponentBase,\n SourcePort,\n} from \"circuit-json\"\nimport * as Soup from \"circuit-json\"\nimport type { SubtreeOptions } from \"./subtree\"\nimport { buildSubtree } from \"./subtree\"\n\n// Keep the existing permissive input while preserving discriminated variants.\ntype CircuitJsonElementInsertInput<\n CircuitElementType extends AnyCircuitElement[\"type\"],\n CircuitElement extends { type: CircuitElementType },\n> =\n | Omit<CircuitElement, \"type\" | `${CircuitElementType}_id`>\n | (CircuitElement extends { type: CircuitElementType }\n ? Omit<CircuitElement, \"type\" | `${CircuitElementType}_id`>\n : never)\n\nexport type CircuitJsonOps<\n K extends AnyCircuitElement[\"type\"],\n T extends AnyCircuitElement | AnyCircuitElementInput,\n> = {\n get: (id: string) => Extract<T, { type: K }> | null\n select: (selector: string) => Extract<T, { type: K }> | null\n getWhere: (where: any) => Extract<T, { type: K }> | null\n getUsing: (using: {\n [key: `${string}_id`]: string\n }) => Extract<T, { type: K }> | null\n insert: (\n elm: CircuitJsonElementInsertInput<K, Extract<T, { type: K }>>,\n ) => Extract<T, { type: K }>\n update: (\n id: string,\n newProps: Partial<Extract<T, { type: K }>>,\n ) => Extract<T, { type: K }>\n delete: (id: string) => void\n list: (where?: any) => Extract<T, { type: K }>[]\n}\n\nexport type CircuitJsonUtilObjects = {\n [K in AnyCircuitElement[\"type\"]]: CircuitJsonOps<K, AnyCircuitElement>\n} & {\n insert: (elm: AnyCircuitElementInput) => AnyCircuitElement\n insertAll: (elms: AnyCircuitElementInput[]) => AnyCircuitElement[]\n subtree: (where?: any) => CircuitJsonUtilObjects\n toArray: () => AnyCircuitElement[]\n editCount: number\n}\nexport type CircuitJsonInputUtilObjects = {\n [K in AnyCircuitElementInput[\"type\"]]: CircuitJsonOps<\n K,\n AnyCircuitElementInput\n >\n}\n\nexport type CircuitJsonUtilOptions = {\n validateInserts?: boolean\n}\n\nexport type GetCircuitJsonUtilFn = ((\n soup: AnyCircuitElement[],\n options?: CircuitJsonUtilOptions,\n) => CircuitJsonUtilObjects) & {\n unparsed: (soup: AnyCircuitElementInput[]) => CircuitJsonInputUtilObjects\n}\n\ninterface InternalStore {\n counts: Record<string, number>\n editCount: number\n}\n\nexport const cju: GetCircuitJsonUtilFn = ((\n circuitJsonInput: any[],\n options: CircuitJsonUtilOptions = {},\n) => {\n const circuitJson = circuitJsonInput as AnyCircuitElement[]\n let internalStore: InternalStore = (circuitJson as any)._internal_store\n if (!internalStore) {\n internalStore = {\n counts: {},\n editCount: 0,\n } as InternalStore\n ;(circuitJson as any)._internal_store = internalStore\n\n // Initialize counts\n for (const elm of circuitJson) {\n const type = elm.type\n const idVal = (elm as any)[`${type}_id`]\n if (!idVal) continue\n const idNum = Number.parseInt(idVal.split(\"_\").pop())\n if (!Number.isNaN(idNum)) {\n internalStore.counts[type] = Math.max(\n internalStore.counts[type] ?? 0,\n idNum,\n )\n }\n }\n }\n const su = new Proxy(\n {},\n {\n get: (proxy_target: any, prop: string) => {\n if (prop === \"toArray\") {\n return () => {\n ;(circuitJson as any).editCount = internalStore.editCount\n return circuitJson\n }\n }\n if (prop === \"editCount\") {\n return internalStore.editCount\n }\n\n if (prop === \"subtree\") {\n return (opts: SubtreeOptions) =>\n cju(buildSubtree(circuitJson, opts), options)\n }\n\n if (prop === \"insert\") {\n return (elm: AnyCircuitElementInput) => {\n const component_type = elm.type\n if (!component_type) {\n throw new Error(\"insert requires an element with a type\")\n }\n\n internalStore.counts[component_type] ??= -1\n internalStore.counts[component_type]++\n const index = internalStore.counts[component_type]\n\n const newElm = {\n ...elm,\n type: component_type,\n [`${component_type}_id`]: `${component_type}_${index}`,\n } as AnyCircuitElement\n\n if (options.validateInserts) {\n const parser =\n (Soup as any)[component_type] ?? Soup.any_soup_element\n parser.parse(newElm)\n }\n\n circuitJson.push(newElm)\n internalStore.editCount++\n return newElm\n }\n }\n\n if (prop === \"insertAll\") {\n return (elms: AnyCircuitElementInput[]) => {\n return elms.map((elm) => su.insert(elm))\n }\n }\n\n const component_type = prop\n\n return {\n get: (id: string) =>\n circuitJson.find(\n (e: any) =>\n e.type === component_type && e[`${component_type}_id`] === id,\n ),\n getUsing: (using: any) => {\n const keys = Object.keys(using)\n if (keys.length !== 1) {\n throw new Error(\n \"getUsing requires exactly one key, e.g. { pcb_component_id }\",\n )\n }\n const join_key = keys[0] as string\n const join_type = join_key.replace(\"_id\", \"\")\n const joiner: any = circuitJson.find(\n (e: any) =>\n e.type === join_type && e[join_key] === using[join_key],\n )\n if (!joiner) return null\n return circuitJson.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joiner[`${component_type}_id`],\n )\n },\n getWhere: (where: any) => {\n const keys = Object.keys(where)\n return circuitJson.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key]),\n )\n },\n list: (where?: any) => {\n const keys = !where ? [] : Object.keys(where)\n return circuitJson.filter(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key]),\n )\n },\n insert: (elm: any) => {\n internalStore.counts[component_type] ??= -1\n internalStore.counts[component_type]++\n const index = internalStore.counts[component_type]\n const newElm = {\n type: component_type,\n [`${component_type}_id`]: `${component_type}_${index}`,\n ...elm,\n }\n\n if (options.validateInserts) {\n const parser =\n (Soup as any)[component_type] ?? Soup.any_soup_element\n parser.parse(newElm)\n }\n\n circuitJson.push(newElm)\n internalStore.editCount++\n return newElm\n },\n delete: (id: string) => {\n const elm = circuitJson.find(\n (e) => (e as any)[`${component_type}_id`] === id,\n )\n if (!elm) return\n circuitJson.splice(circuitJson.indexOf(elm), 1)\n internalStore.editCount++\n },\n update: (id: string, newProps: any) => {\n const elm = circuitJson.find(\n (e) =>\n e.type === component_type &&\n (e as any)[`${component_type}_id`] === id,\n )\n if (!elm) return null\n Object.assign(elm, newProps)\n internalStore.editCount++\n return elm\n },\n select: (selector: string) => {\n // TODO when applySelector is isolated we can use it, until then we\n // do a poor man's selector implementation for two common cases\n if (component_type === \"source_component\") {\n return circuitJson.find(\n (e) =>\n e.type === \"source_component\" &&\n e.name === selector.replace(/\\./g, \"\"),\n )\n } else if (\n component_type === \"pcb_port\" ||\n component_type === \"source_port\" ||\n component_type === \"schematic_port\"\n ) {\n const [component_name, port_selector] = selector\n .replace(/\\./g, \"\")\n .split(/[\\s\\>]+/)\n const source_component = circuitJson.find(\n (e) =>\n e.type === \"source_component\" && e.name === component_name,\n ) as SourceComponentBase\n if (!source_component) return null\n const source_port = circuitJson.find(\n (e) =>\n e.type === \"source_port\" &&\n e.source_component_id ===\n source_component.source_component_id &&\n (e.name === port_selector ||\n (e.port_hints ?? []).includes(port_selector!)),\n ) as SourcePort\n if (!source_port) return null\n if (component_type === \"source_port\") return source_port\n\n if (component_type === \"pcb_port\") {\n return circuitJson.find(\n (e) =>\n e.type === \"pcb_port\" &&\n e.source_port_id === source_port.source_port_id,\n )\n } else if (component_type === \"schematic_port\") {\n return circuitJson.find(\n (e) =>\n e.type === \"schematic_port\" &&\n e.source_port_id === source_port.source_port_id,\n )\n }\n }\n },\n }\n },\n },\n )\n\n return su\n}) as any\ncju.unparsed = cju as any\n\nexport const su = cju\n\nexport default cju\n","import type { AnyCircuitElement } from \"circuit-json\"\n\nexport type SubtreeOptions = {\n subcircuit_id?: string\n subcircuit_ids?: string[]\n source_group_id?: string\n source_board_id?: string\n}\n\nfunction connect(\n map: Map<AnyCircuitElement, Set<AnyCircuitElement>>,\n a: AnyCircuitElement | undefined,\n b: AnyCircuitElement | undefined,\n) {\n if (!a || !b) return\n let setA = map.get(a)\n if (!setA) {\n setA = new Set()\n map.set(a, setA)\n }\n setA.add(b)\n let setB = map.get(b)\n if (!setB) {\n setB = new Set()\n map.set(b, setB)\n }\n setB.add(a)\n}\n\nexport function buildSubtree(\n soup: AnyCircuitElement[],\n opts: SubtreeOptions,\n): AnyCircuitElement[] {\n if (!opts.subcircuit_id && !opts.source_group_id) return [...soup]\n\n // For subcircuit_id, also include nested subcircuits\n let effectiveOpts = opts\n if (opts.subcircuit_id) {\n // Find all subcircuit_ids that are children of the target subcircuit\n const subcircuitIds = new Set<string>([opts.subcircuit_id])\n\n // Build group hierarchy\n const groupChildren = new Map<string, string[]>()\n const groupSubcircuit = new Map<string, string>()\n\n for (const elm of soup) {\n if (elm.type === \"source_group\") {\n const groupId = elm.source_group_id\n const subcircuitId = elm.subcircuit_id\n if (subcircuitId) {\n groupSubcircuit.set(groupId, subcircuitId)\n }\n const parentId = elm.parent_source_group_id\n if (parentId) {\n if (!groupChildren.has(parentId)) {\n groupChildren.set(parentId, [])\n }\n groupChildren.get(parentId)!.push(groupId)\n }\n }\n }\n\n // Find the root group for the target subcircuit\n let rootGroupId: string | undefined\n for (const [groupId, subcircuitId] of groupSubcircuit) {\n if (subcircuitId === opts.subcircuit_id) {\n rootGroupId = groupId\n break\n }\n }\n\n if (rootGroupId) {\n // Recursively collect all child subcircuit_ids\n const collectChildSubcircuits = (groupId: string) => {\n const children = groupChildren.get(groupId) || []\n for (const childId of children) {\n const childSubcircuit = groupSubcircuit.get(childId)\n if (childSubcircuit) {\n subcircuitIds.add(childSubcircuit)\n }\n collectChildSubcircuits(childId)\n }\n }\n collectChildSubcircuits(rootGroupId)\n\n // Update opts to include all these subcircuits\n effectiveOpts = { ...opts, subcircuit_ids: Array.from(subcircuitIds) }\n }\n }\n\n const idMap = new Map<string, AnyCircuitElement>()\n for (const elm of soup) {\n const idKey = `${elm.type}_id` as keyof typeof elm\n const idVal = elm[idKey]\n if (typeof idVal === \"string\") {\n idMap.set(idVal, elm)\n }\n }\n\n const adj = new Map<AnyCircuitElement, Set<AnyCircuitElement>>()\n for (const elm of soup) {\n const entries = Object.entries(elm)\n for (const [key, val] of entries) {\n if (key === \"parent_source_group_id\") continue // Skip parent relationships to avoid traversing up\n if (key.endsWith(\"_id\") && typeof val === \"string\") {\n const other = idMap.get(val)\n connect(adj, elm, other)\n } else if (key.endsWith(\"_ids\") && Array.isArray(val)) {\n for (const v of val) {\n if (typeof v === \"string\") {\n const other = idMap.get(v)\n connect(adj, elm, other)\n }\n }\n }\n }\n }\n\n const queue: AnyCircuitElement[] = []\n const included = new Set<AnyCircuitElement>()\n\n for (const elm of soup) {\n let shouldInclude = false\n if (\n effectiveOpts.subcircuit_id &&\n \"subcircuit_id\" in elm &&\n elm.subcircuit_id === effectiveOpts.subcircuit_id\n ) {\n shouldInclude = true\n } else if (\n effectiveOpts.subcircuit_ids &&\n \"subcircuit_id\" in elm &&\n elm.subcircuit_id &&\n effectiveOpts.subcircuit_ids.includes(elm.subcircuit_id)\n ) {\n shouldInclude = true\n } else if (\n effectiveOpts.source_group_id &&\n \"source_group_id\" in elm &&\n elm.source_group_id === effectiveOpts.source_group_id\n ) {\n shouldInclude = true\n } else if (\n effectiveOpts.source_group_id &&\n \"member_source_group_ids\" in elm &&\n Array.isArray(elm.member_source_group_ids) &&\n elm.member_source_group_ids.includes(effectiveOpts.source_group_id)\n ) {\n shouldInclude = true\n }\n\n if (shouldInclude) {\n queue.push(elm)\n included.add(elm)\n }\n }\n\n while (queue.length > 0) {\n const elm = queue.shift()!\n const neighbors = adj.get(elm)\n if (!neighbors) continue\n for (const n of neighbors) {\n if (!included.has(n)) {\n included.add(n)\n queue.push(n)\n }\n }\n }\n\n return soup.filter((e) => included.has(e))\n}\n","import type {\n AnyCircuitElement,\n AnyCircuitElementInput,\n SourceComponentBase,\n SourcePort,\n} from \"circuit-json\"\nimport * as Soup from \"circuit-json\"\nimport type {\n CircuitJsonOps,\n CircuitJsonUtilObjects as CircuitJsonUtilObjects,\n CircuitJsonInputUtilObjects as CircuitJsonInputUtilObjects,\n} from \"./cju\"\n\nexport type IndexedCircuitJsonUtilOptions = {\n validateInserts?: boolean\n indexConfig?: {\n // Enable specific indexes for faster lookups\n byId?: boolean\n byType?: boolean\n byRelation?: boolean\n bySubcircuit?: boolean\n byCustomField?: string[]\n }\n}\n\nexport type GetIndexedCircuitJsonUtilFn = ((\n soup: AnyCircuitElement[],\n options?: IndexedCircuitJsonUtilOptions,\n) => CircuitJsonUtilObjects) & {\n unparsed: (soup: AnyCircuitElementInput[]) => CircuitJsonInputUtilObjects\n}\n\ninterface InternalStore {\n counts: Record<string, number>\n editCount: number\n // Indexes for faster lookups\n indexes: {\n byId?: Map<string, AnyCircuitElement>\n byType?: Map<string, AnyCircuitElement[]>\n // Maps relation fields (like component_id) to elements\n byRelation?: Map<string, Map<string, AnyCircuitElement[]>>\n // Maps subcircuit_id to elements\n bySubcircuit?: Map<string, AnyCircuitElement[]>\n // Custom field indexes\n byCustomField?: Map<string, Map<string, AnyCircuitElement[]>>\n }\n}\n\n// Creates a unique key for the ID index\nfunction createIdKey(element: AnyCircuitElement): string {\n const type = element.type\n return `${type}:${(element as any)[`${type}_id`]}`\n}\n\nexport const cjuIndexed: GetIndexedCircuitJsonUtilFn = ((\n soup: AnyCircuitElement[],\n options: IndexedCircuitJsonUtilOptions = {},\n) => {\n let internalStore: InternalStore = (soup as any)._internal_store_indexed\n\n if (!internalStore) {\n internalStore = {\n counts: {},\n editCount: 0,\n indexes: {},\n } as InternalStore\n\n // Initialize counts\n for (const elm of soup) {\n const type = elm.type\n const idVal = (elm as any)[`${type}_id`]\n if (!idVal) continue\n const idNum = Number.parseInt(idVal.split(\"_\").pop() || \"\")\n if (!Number.isNaN(idNum)) {\n internalStore.counts[type] = Math.max(\n internalStore.counts[type] ?? 0,\n idNum,\n )\n }\n }\n\n // Build indexes\n const indexConfig = options.indexConfig || {}\n const indexes = internalStore.indexes\n\n // Reset indexes before rebuilding\n if (indexConfig.byId) {\n indexes.byId = new Map()\n }\n\n if (indexConfig.byType) {\n indexes.byType = new Map()\n }\n\n if (indexConfig.byRelation) {\n indexes.byRelation = new Map()\n }\n\n if (indexConfig.bySubcircuit) {\n indexes.bySubcircuit = new Map()\n }\n\n if (indexConfig.byCustomField && indexConfig.byCustomField.length > 0) {\n indexes.byCustomField = new Map()\n for (const field of indexConfig.byCustomField) {\n indexes.byCustomField.set(field, new Map())\n }\n }\n\n // Build indexes\n for (const element of soup) {\n // Index by ID\n if (indexConfig.byId) {\n const idKey = createIdKey(element)\n indexes.byId!.set(idKey, element)\n }\n\n // Index by type\n if (indexConfig.byType) {\n const elementsOfType = indexes.byType!.get(element.type) || []\n elementsOfType.push(element)\n indexes.byType!.set(element.type, elementsOfType)\n }\n\n // Index by relation fields (fields ending with _id)\n if (indexConfig.byRelation) {\n const elementEntries = Object.entries(element)\n for (const [key, value] of elementEntries) {\n if (\n key.endsWith(\"_id\") &&\n key !== `${element.type}_id` &&\n typeof value === \"string\"\n ) {\n const relationTypeMap = indexes.byRelation!.get(key) || new Map()\n const relatedElements = relationTypeMap.get(value as string) || []\n relatedElements.push(element)\n relationTypeMap.set(value as string, relatedElements)\n indexes.byRelation!.set(key, relationTypeMap)\n }\n }\n }\n\n // Index by subcircuit_id\n if (indexConfig.bySubcircuit && \"subcircuit_id\" in element) {\n const subcircuitId = (element as any).subcircuit_id\n if (subcircuitId && typeof subcircuitId === \"string\") {\n const subcircuitElements =\n indexes.bySubcircuit!.get(subcircuitId) || []\n subcircuitElements.push(element)\n indexes.bySubcircuit!.set(subcircuitId, subcircuitElements)\n }\n }\n\n // Index by custom fields\n if (indexConfig.byCustomField && indexes.byCustomField) {\n for (const field of indexConfig.byCustomField) {\n if (field in element) {\n const fieldValue = (element as any)[field]\n if (\n fieldValue !== undefined &&\n (typeof fieldValue === \"string\" || typeof fieldValue === \"number\")\n ) {\n const fieldValueStr = String(fieldValue)\n const fieldMap = indexes.byCustomField.get(field)!\n const elementsWithFieldValue = fieldMap.get(fieldValueStr) || []\n elementsWithFieldValue.push(element)\n fieldMap.set(fieldValueStr, elementsWithFieldValue)\n }\n }\n }\n }\n }\n // Store internal state\n ;(soup as any)._internal_store_indexed = internalStore\n }\n\n const suIndexed = new Proxy(\n {},\n {\n get: (proxy_target: any, prop: string) => {\n if (prop === \"toArray\") {\n return () => {\n ;(soup as any).editCount = internalStore.editCount\n return soup\n }\n }\n if (prop === \"editCount\") {\n return internalStore.editCount\n }\n\n const component_type = prop\n\n return {\n get: (id: string) => {\n const indexConfig = options.indexConfig || {}\n\n // Use ID index if available\n if (indexConfig.byId && internalStore.indexes.byId) {\n return (\n (internalStore.indexes.byId.get(\n `${component_type}:${id}`,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n // Use type index if available\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n return (\n (elementsOfType.find(\n (e: any) => e[`${component_type}_id`] === id,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n // Fallback to regular search\n return (\n (soup.find(\n (e: any) =>\n e.type === component_type && e[`${component_type}_id`] === id,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n },\n\n getUsing: (using: any) => {\n const indexConfig = options.indexConfig || {}\n const keys = Object.keys(using)\n\n if (keys.length !== 1) {\n throw new Error(\n \"getUsing requires exactly one key, e.g. { pcb_component_id }\",\n )\n }\n\n const join_key = keys[0] as string\n const join_type = join_key.replace(\"_id\", \"\")\n\n // Use relation index if available\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n const relationMap = internalStore.indexes.byRelation.get(join_key)\n if (relationMap) {\n const relatedElements = relationMap.get(using[join_key]) || []\n const joiner = relatedElements.find((e) => e.type === join_type)\n\n if (!joiner) return null\n\n // Now find the element of component_type with matching ID\n const joinerId =\n joiner[`${component_type}_id` as keyof typeof joiner]\n\n if (indexConfig.byId && internalStore.indexes.byId) {\n return (\n (internalStore.indexes.byId.get(\n `${component_type}:${joinerId}`,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n return (\n (elementsOfType.find(\n (e: any) => e[`${component_type}_id`] === joinerId,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n return (\n (soup.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joinerId,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n }\n\n // Fallback to regular approach\n const joiner: any = soup.find(\n (e: any) =>\n e.type === join_type && e[join_key] === using[join_key],\n )\n\n if (!joiner) return null\n\n return (\n (soup.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joiner[`${component_type}_id`],\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n },\n\n getWhere: (where: any) => {\n const indexConfig = options.indexConfig || {}\n const keys = Object.keys(where)\n\n // If we're looking by a single property and it's indexed as a custom field\n if (\n keys.length === 1 &&\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n const field = keys[0]\n const fieldMap = internalStore.indexes.byCustomField.get(field!)\n\n if (fieldMap) {\n const fieldValue = String(where[field!])\n const elementsWithFieldValue = fieldMap.get(fieldValue) || []\n\n return (\n (elementsWithFieldValue.find(\n (e: any) => e.type === component_type,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n }\n\n // If we're looking by subcircuit_id and it's indexed\n if (\n \"subcircuit_id\" in where &&\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit\n ) {\n const subcircuitId = where.subcircuit_id\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n\n return (\n (subcircuitElements.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key]),\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n // Use type index if available to reduce search space\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n\n return (\n (elementsOfType.find((e: any) =>\n keys.every((key) => e[key] === where[key]),\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n\n // Fallback to regular approach\n return (\n (soup.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key]),\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n },\n\n list: (where?: any) => {\n const indexConfig = options.indexConfig || {}\n const keys = !where ? [] : Object.keys(where)\n\n // If no filters, just return all elements of this type using the type index\n if (\n keys.length === 0 &&\n indexConfig.byType &&\n internalStore.indexes.byType\n ) {\n return (internalStore.indexes.byType.get(component_type) ||\n []) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >[]\n }\n\n // If filtering by subcircuit_id and it's the only filter\n if (\n keys.length === 1 &&\n keys[0] === \"subcircuit_id\" &&\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit\n ) {\n const subcircuitId = where.subcircuit_id\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n\n return subcircuitElements.filter(\n (e: any) => e.type === component_type,\n ) as Extract<AnyCircuitElement, { type: typeof component_type }>[]\n }\n\n // Start with all elements of this type to reduce search space\n let elementsToFilter: AnyCircuitElement[]\n\n if (indexConfig.byType && internalStore.indexes.byType) {\n elementsToFilter =\n internalStore.indexes.byType.get(component_type) || []\n } else {\n elementsToFilter = soup.filter((e) => e.type === component_type)\n }\n\n // Apply remaining filters\n if (keys.length > 0) {\n return elementsToFilter.filter((e: any) =>\n keys.every((key) => e[key] === where[key]),\n ) as Extract<AnyCircuitElement, { type: typeof component_type }>[]\n }\n\n return elementsToFilter as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >[]\n },\n\n insert: (elm: any) => {\n internalStore.counts[component_type] ??= -1\n internalStore.counts[component_type]++\n const index = internalStore.counts[component_type]\n const newElm = {\n type: component_type,\n [`${component_type}_id`]: `${component_type}_${index}`,\n ...elm,\n }\n\n if (options.validateInserts) {\n const parser =\n (Soup as any)[component_type] ?? Soup.any_soup_element\n parser.parse(newElm)\n }\n\n soup.push(newElm)\n internalStore.editCount++\n\n // Update indexes with the new element\n const indexConfig = options.indexConfig || {}\n\n // Update ID index\n if (indexConfig.byId && internalStore.indexes.byId) {\n const idKey = createIdKey(newElm)\n internalStore.indexes.byId.set(idKey, newElm)\n }\n\n // Update type index\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n elementsOfType.push(newElm)\n internalStore.indexes.byType.set(component_type, elementsOfType)\n }\n\n // Update relation index\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n const elementEntries = Object.entries(newElm)\n for (const [key, value] of elementEntries) {\n if (\n key.endsWith(\"_id\") &&\n key !== `${newElm.type}_id` &&\n typeof value === \"string\"\n ) {\n const relationTypeMap =\n internalStore.indexes.byRelation.get(key) || new Map()\n const relatedElements =\n relationTypeMap.get(value as string) || []\n relatedElements.push(newElm)\n relationTypeMap.set(value as string, relatedElements)\n internalStore.indexes.byRelation.set(key, relationTypeMap)\n }\n }\n }\n\n // Update subcircuit index\n if (\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit &&\n \"subcircuit_id\" in newElm\n ) {\n const subcircuitId = (newElm as any).subcircuit_id\n if (subcircuitId && typeof subcircuitId === \"string\") {\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n subcircuitElements.push(newElm)\n internalStore.indexes.bySubcircuit.set(\n subcircuitId,\n subcircuitElements,\n )\n }\n }\n\n // Update custom field indexes\n if (\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n for (const field of indexConfig.byCustomField) {\n if (field in newElm) {\n const fieldValue = (newElm as any)[field]\n if (\n fieldValue !== undefined &&\n (typeof fieldValue === \"string\" ||\n typeof fieldValue === \"number\")\n ) {\n const fieldValueStr = String(fieldValue)\n const fieldMap =\n internalStore.indexes.byCustomField.get(field)!\n const elementsWithFieldValue =\n fieldMap.get(fieldValueStr) || []\n elementsWithFieldValue.push(newElm)\n fieldMap.set(fieldValueStr, elementsWithFieldValue)\n }\n }\n }\n }\n\n return newElm\n },\n\n delete: (id: string) => {\n const indexConfig = options.indexConfig || {}\n let elm: AnyCircuitElement | undefined\n\n // Find the element to delete\n if (indexConfig.byId && internalStore.indexes.byId) {\n elm = internalStore.indexes.byId.get(`${component_type}:${id}`)\n } else if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n elm = elementsOfType.find(\n (e: any) => e[`${component_type}_id`] === id,\n )\n } else {\n elm = soup.find((e) => (e as any)[`${component_type}_id`] === id)\n }\n\n if (!elm) return\n\n // Remove from array\n const elmIndex = soup.indexOf(elm)\n if (elmIndex >= 0) {\n soup.splice(elmIndex, 1)\n internalStore.editCount++\n }\n\n // Remove from indexes\n if (indexConfig.byId && internalStore.indexes.byId) {\n const idKey = createIdKey(elm)\n internalStore.indexes.byId.delete(idKey)\n }\n\n if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n const filteredElements = elementsOfType.filter(\n (e: any) => e[`${component_type}_id`] !== id,\n )\n internalStore.indexes.byType.set(component_type, filteredElements)\n }\n\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n // This is more complex - we need to find and remove from all relation maps\n // where this element appears\n for (const [\n relationKey,\n relationMap,\n ] of internalStore.indexes.byRelation.entries()) {\n for (const [relationValue, elements] of relationMap.entries()) {\n const updatedElements = elements.filter((e) => e !== elm)\n\n if (updatedElements.length === 0) {\n relationMap.delete(relationValue)\n } else {\n relationMap.set(relationValue, updatedElements)\n }\n }\n }\n }\n\n if (\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit &&\n \"subcircuit_id\" in elm\n ) {\n const subcircuitId = (elm as any).subcircuit_id\n if (subcircuitId) {\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n const updatedElements = subcircuitElements.filter(\n (e) => e !== elm,\n )\n\n if (updatedElements.length === 0) {\n internalStore.indexes.bySubcircuit.delete(subcircuitId)\n } else {\n internalStore.indexes.bySubcircuit.set(\n subcircuitId,\n updatedElements,\n )\n }\n }\n }\n\n if (\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n for (const fieldMap of internalStore.indexes.byCustomField.values()) {\n for (const [fieldValue, elements] of fieldMap.entries()) {\n const updatedElements = elements.filter((e) => e !== elm)\n\n if (updatedElements.length === 0) {\n fieldMap.delete(fieldValue)\n } else {\n fieldMap.set(fieldValue, updatedElements)\n }\n }\n }\n }\n },\n\n update: (id: string, newProps: any) => {\n const indexConfig = options.indexConfig || {}\n let elm: AnyCircuitElement | undefined | null\n\n // Find the element to update\n if (indexConfig.byId && internalStore.indexes.byId) {\n elm = internalStore.indexes.byId.get(`${component_type}:${id}`)\n } else if (indexConfig.byType && internalStore.indexes.byType) {\n const elementsOfType =\n internalStore.indexes.byType.get(component_type) || []\n elm = elementsOfType.find(\n (e: any) => e[`${component_type}_id`] === id,\n )\n } else {\n elm = soup.find(\n (e) =>\n e.type === component_type &&\n (e as any)[`${component_type}_id`] === id,\n )\n }\n\n if (!elm) return null\n\n // Need to remove from indexes before updating\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n // Remove from relation indexes\n const elementEntries = Object.entries(elm)\n for (const [key, value] of elementEntries) {\n if (\n key.endsWith(\"_id\") &&\n key !== `${elm.type}_id` &&\n typeof value === \"string\"\n ) {\n if (key in newProps && newProps[key] !== value) {\n const relationTypeMap =\n internalStore.indexes.byRelation.get(key)\n if (relationTypeMap) {\n const relatedElements =\n relationTypeMap.get(value as string) || []\n const updatedElements = relatedElements.filter(\n (e) => e !== elm,\n )\n\n if (updatedElements.length === 0) {\n relationTypeMap.delete(value as string)\n } else {\n relationTypeMap.set(value as string, updatedElements)\n }\n }\n }\n }\n }\n }\n\n if (\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit &&\n \"subcircuit_id\" in elm &&\n \"subcircuit_id\" in newProps\n ) {\n const oldSubcircuitId = (elm as any).subcircuit_id\n const newSubcircuitId = newProps.subcircuit_id\n\n if (oldSubcircuitId !== newSubcircuitId) {\n // Remove from old subcircuit index\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(oldSubcircuitId) || []\n const updatedElements = subcircuitElements.filter(\n (e) => e !== elm,\n )\n\n if (updatedElements.length === 0) {\n internalStore.indexes.bySubcircuit.delete(oldSubcircuitId)\n } else {\n internalStore.indexes.bySubcircuit.set(\n oldSubcircuitId,\n updatedElements,\n )\n }\n }\n }\n\n if (\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n for (const field of indexConfig.byCustomField) {\n if (\n field in elm &&\n field in newProps &&\n (elm as any)[field] !== newProps[field]\n ) {\n const fieldMap =\n internalStore.indexes.byCustomField.get(field)\n if (fieldMap) {\n const oldValue = String((elm as any)[field])\n const elements = fieldMap.get(oldValue) || []\n const updatedElements = elements.filter((e) => e !== elm)\n\n if (updatedElements.length === 0) {\n fieldMap.delete(oldValue)\n } else {\n fieldMap.set(oldValue, updatedElements)\n }\n }\n }\n }\n }\n\n // Update the element\n Object.assign(elm, newProps)\n internalStore.editCount++\n\n // Add to indexes with updated values\n if (indexConfig.byRelation && internalStore.indexes.byRelation) {\n const elementEntries = Object.entries(elm)\n for (const [key, value] of elementEntries) {\n if (\n key.endsWith(\"_id\") &&\n key !== `${elm.type}_id` &&\n typeof value === \"string\"\n ) {\n if (key in newProps) {\n const relationTypeMap: any =\n internalStore.indexes.byRelation.get(key) || new Map()\n const relatedElements: any =\n relationTypeMap.get(value as string) || []\n\n if (!relatedElements.includes(elm)) {\n relatedElements.push(elm)\n relationTypeMap.set(value as string, relatedElements)\n internalStore.indexes.byRelation.set(key, relationTypeMap)\n }\n }\n }\n }\n }\n\n if (\n indexConfig.bySubcircuit &&\n internalStore.indexes.bySubcircuit &&\n \"subcircuit_id\" in elm &&\n \"subcircuit_id\" in newProps\n ) {\n const subcircuitId = (elm as any).subcircuit_id\n if (subcircuitId && typeof subcircuitId === \"string\") {\n const subcircuitElements =\n internalStore.indexes.bySubcircuit.get(subcircuitId) || []\n\n if (!subcircuitElements.includes(elm)) {\n subcircuitElements.push(elm)\n internalStore.indexes.bySubcircuit.set(\n subcircuitId,\n subcircuitElements,\n )\n }\n }\n }\n\n if (\n indexConfig.byCustomField &&\n internalStore.indexes.byCustomField\n ) {\n for (const field of indexConfig.byCustomField) {\n if (field in elm && field in newProps) {\n const fieldValue: any = (elm as any)[field]\n if (\n fieldValue !== undefined &&\n (typeof fieldValue === \"string\" ||\n typeof fieldValue === \"number\")\n ) {\n const fieldValueStr = String(fieldValue)\n const fieldMap =\n internalStore.indexes.byCustomField.get(field)!\n const elementsWithFieldValue =\n fieldMap.get(fieldValueStr) || []\n\n if (!elementsWithFieldValue.includes(elm)) {\n elementsWithFieldValue.push(elm)\n fieldMap.set(fieldValueStr, elementsWithFieldValue)\n }\n }\n }\n }\n }\n\n return elm as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >\n },\n\n select: (selector: string) => {\n // Selection by selector is specialized enough that we don't use indexes here\n // TODO when applySelector is isolated we can use it, until then we\n // do a poor man's selector implementation for two common cases\n if (component_type === \"source_component\") {\n return (\n (soup.find(\n (e) =>\n e.type === \"source_component\" &&\n e.name === selector.replace(/\\./g, \"\"),\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n } else if (\n component_type === \"pcb_port\" ||\n component_type === \"source_port\" ||\n component_type === \"schematic_port\"\n ) {\n const [component_name, port_selector] = selector\n .replace(/\\./g, \"\")\n .split(/[\\s\\>]+/)\n const source_component = soup.find(\n (e) =>\n e.type === \"source_component\" && e.name === component_name,\n ) as SourceComponentBase\n if (!source_component) return null\n const source_port = soup.find(\n (e) =>\n e.type === \"source_port\" &&\n e.source_component_id ===\n source_component.source_component_id &&\n (e.name === port_selector ||\n (e.port_hints ?? []).includes(port_selector!)),\n ) as SourcePort\n if (!source_port) return null\n if (component_type === \"source_port\")\n return source_port as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >\n\n if (component_type === \"pcb_port\") {\n return (\n (soup.find(\n (e) =>\n e.type === \"pcb_port\" &&\n e.source_port_id === source_port.source_port_id,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n } else if (component_type === \"schematic_port\") {\n return (\n (soup.find(\n (e) =>\n e.type === \"schematic_port\" &&\n e.source_port_id === source_port.source_port_id,\n ) as Extract<\n AnyCircuitElement,\n { type: typeof component_type }\n >) || null\n )\n }\n }\n\n return null\n },\n }\n },\n },\n )\n\n return suIndexed\n}) as any\n\ncjuIndexed.unparsed = cjuIndexed as any\n\nexport default cjuIndexed\n","import type { AnyCircuitElement, InsertionDirection } from \"circuit-json\"\nimport { type Matrix, applyToPoint, decomposeTSR } from \"transformation-matrix\"\nimport {\n directionToVec,\n rotateDirection,\n vecToDirection,\n} from \"./direction-to-vec\"\n\nconst getQuarterTurns = (angleRadians: number) =>\n Math.round(angleRadians / (Math.PI / 2))\n\nconst insertionDirectionToVec = (\n direction: Exclude<InsertionDirection, \"from_above\" | \"from_below\">,\n) => {\n switch (direction) {\n case \"from_left\":\n return { x: -1, y: 0 }\n case \"from_right\":\n return { x: 1, y: 0 }\n case \"from_top\":\n return { x: 0, y: 1 }\n case \"from_bottom\":\n return { x: 0, y: -1 }\n }\n}\n\nconst vecToInsertionDirection = ({\n x,\n y,\n}: {\n x: number\n y: number\n}): Exclude<InsertionDirection, \"from_above\" | \"from_below\"> => {\n if (x > 0) return \"from_right\"\n if (x < 0) return \"from_left\"\n if (y > 0) return \"from_top\"\n return \"from_bottom\"\n}\n\nexport const transformInsertionDirection = (\n direction: InsertionDirection | undefined,\n opts: { rotationDegrees: number; isFlipped: boolean },\n) => {\n if (!direction) return direction\n\n // Rotating within the board plane leaves a Z-axis insertion pointing along\n // Z, but moving the part to the other layer reverses which side of the board\n // the mating part approaches from.\n if (direction === \"from_above\" || direction === \"from_below\") {\n if (!opts.isFlipped) return direction\n return direction === \"from_above\" ? \"from_below\" : \"from_above\"\n }\n\n let { x, y } = insertionDirectionToVec(direction)\n let quarterTurns = Math.round(opts.rotationDegrees / 90)\n\n while (quarterTurns > 0) {\n ;[x, y] = [-y, x]\n quarterTurns--\n }\n\n while (quarterTurns < 0) {\n ;[x, y] = [y, -x]\n quarterTurns++\n }\n\n if (opts.isFlipped) {\n y = -y\n }\n\n return vecToInsertionDirection({ x, y })\n}\n\nexport const transformSchematicElement = (\n elm: AnyCircuitElement,\n matrix: Matrix,\n) => {\n if (elm.type === \"schematic_component\") {\n // TODO handle rotation\n elm.center = applyToPoint(matrix, elm.center)\n } else if (elm.type === \"schematic_port\") {\n elm.center = applyToPoint(matrix, elm.center)\n\n if (elm.facing_direction) {\n elm.facing_direction = rotateDirection(\n elm.facing_direction,\n -(Math.atan2(matrix.b, matrix.a) / Math.PI) * 2,\n )\n }\n } else if (elm.type === \"schematic_text\") {\n elm.position = applyToPoint(matrix, elm.position)\n // } else if (elm.type === \"schematic_group\") {\n // elm.center = applyToPoint(matrix, elm.center)\n } else if (elm.type === \"schematic_trace\") {\n const anyElm = elm as any\n anyElm.route = (anyElm.route ?? []).map((rp: any) => {\n const tp = applyToPoint(matrix, rp) as { x: number; y: number }\n rp.x = tp.x\n rp.y = tp.y\n return rp\n })\n if (Array.isArray(anyElm.junctions)) {\n anyElm.junctions = anyElm.junctions.map((j: any) => {\n const tp = applyToPoint(matrix, j) as { x: number; y: number }\n j.x = tp.x\n j.y = tp.y\n return j\n })\n }\n if (Array.isArray(anyElm.edges)) {\n anyElm.edges = anyElm.edges.map((e: any) => {\n e.from = applyToPoint(matrix, e.from)\n e.to = applyToPoint(matrix, e.to)\n return e\n })\n }\n } else if (elm.type === \"schematic_box\") {\n const { x, y } = applyToPoint(matrix, { x: elm.x, y: elm.y })\n elm.x = x\n elm.y = y\n } else if (elm.type === \"schematic_line\") {\n const { x: x1, y: y1 } = applyToPoint(matrix, { x: elm.x1, y: elm.y1 })\n const { x: x2, y: y2 } = applyToPoint(matrix, { x: elm.x2, y: elm.y2 })\n elm.x1 = x1\n elm.y1 = y1\n elm.x2 = x2\n elm.y2 = y2\n }\n return elm\n}\n\nexport const transformSchematicElements = (\n elms: AnyCircuitElement[],\n matrix: Matrix,\n) => {\n return elms.map((elm) => transformSchematicElement(elm, matrix))\n}\n\nexport const transformPCBElement = (elm: AnyCircuitElement, matrix: Matrix) => {\n const tsr = decomposeTSR(matrix)\n const flipPadWidthHeight =\n Math.abs(getQuarterTurns(tsr.rotation.angle)) % 2 === 1\n const rotationDegrees = (tsr.rotation.angle / Math.PI) * 180\n const isFlipped = tsr.scale.sy < 0\n if (\n elm.type === \"pcb_plated_hole\" ||\n elm.type === \"pcb_hole\" ||\n elm.type === \"pcb_via\" ||\n elm.type === \"pcb_smtpad\" ||\n elm.type === \"pcb_solder_paste\" ||\n elm.type === \"pcb_port\"\n ) {\n const { x, y } = applyToPoint(matrix, {\n x: Number((elm as any).x),\n y: Number((elm as any).y),\n })\n ;(elm as any).x = x\n ;(elm as any).y = y\n\n // Handle polygon-shaped SMT pads with points array\n if (\n elm.type === \"pcb_smtpad\" &&\n elm.shape === \"polygon\" &&\n Array.isArray(elm.points)\n ) {\n elm.points = elm.points.map((point: any) => {\n const tp = applyToPoint(matrix, { x: point.x, y: point.y })\n return {\n x: tp.x,\n y: tp.y,\n }\n })\n }\n } else if (elm.type === \"pcb_keepout\" || elm.type === \"pcb_board\") {\n // TODO adjust size/rotation\n elm.center = applyToPoint(matrix, elm.center)\n } else if (\n elm.type === \"pcb_silkscreen_text\" ||\n elm.type === \"pcb_fabrication_note_text\" ||\n elm.type === \"pcb_note_text\"\n ) {\n elm.anchor_position = applyToPoint(matrix, elm.anchor_position)\n } else if (elm.type === \"pcb_copper_text\") {\n if (elm.anchor_position) {\n elm.anchor_position = applyToPoint(matrix, elm.anchor_position)\n }\n } else if (elm.type === \"pcb_courtyard_rect\") {\n elm.center = applyToPoint(matrix, elm.center)\n elm.ccw_rotation = ((elm.ccw_rotation ?? 0) + rotationDegrees) % 360\n } else if (\n elm.type === \"pcb_silkscreen_circle\" ||\n elm.type === \"pcb_silkscreen_rect\" ||\n elm.type === \"pcb_silkscreen_pill\" ||\n elm.type === \"pcb_silkscreen_oval\" ||\n elm.type === \"pcb_note_rect\" ||\n elm.type === \"pcb_courtyard_circle\"\n ) {\n elm.center = applyToPoint(matrix, elm.center)\n } else if (elm.type === \"pcb_component\") {\n elm.center = applyToPoint(matrix, elm.center)\n elm.rotation = elm.rotation + rotationDegrees\n elm.rotation = elm.rotation % 360\n if (elm.cable_insertion_center) {\n elm.cable_insertion_center = applyToPoint(\n matrix,\n elm.cable_insertion_center,\n )\n }\n elm.insertion_direction = transformInsertionDirection(\n elm.insertion_direction,\n {\n rotationDegrees,\n isFlipped,\n },\n )\n if (flipPadWidthHeight) {\n ;[elm.width, elm.height] = [elm.height, elm.width]\n }\n } else if (elm.type === \"pcb_courtyard_outline\") {\n elm.outline = elm.outline.map((p) => {\n const tp = applyToPoint(matrix, p) as { x: number; y: number }\n p.x = tp.x\n p.y = tp.y\n return p\n })\n } else if (elm.type === \"pcb_courtyard_polygon\") {\n elm.points = elm.points.map((p) => {\n const tp = applyToPoint(matrix, p) as { x: number; y: number }\n p.x = tp.x\n p.y = tp.y\n return p\n })\n } else if (elm.type === \"pcb_trace\") {\n elm.route = elm.route.map((rp) => {\n // \"through_pad\" route points describe a segment with start/end rather\n // than a single x/y position.\n if (!(\"x\" in rp)) {\n rp.start = applyToPoint(matrix, rp.start) as { x: number; y: number }\n rp.end = applyToPoint(matrix, rp.end) as { x: number; y: number }\n return rp\n }\n const tp = applyToPoint(matrix, rp) as { x: number; y: number }\n rp.x = tp.x\n rp.y = tp.y\n return rp\n })\n } else if (\n elm.type === \"pcb_silkscreen_path\" ||\n elm.type === \"pcb_trace_hint\" ||\n elm.type === \"pcb_fabrication_note_path\" ||\n elm.type === \"pcb_note_path\"\n ) {\n elm.route = elm.route.map((rp) => {\n const tp = applyToPoint(matrix, rp) as { x: number; y: number }\n rp.x = tp.x\n rp.y = tp.y\n return rp\n })\n } else if (\n elm.type === \"pcb_silkscreen_line\" ||\n elm.type === \"pcb_note_line\"\n ) {\n const p1 = { x: elm.x1, y: elm.y1 }\n const p2 = { x: elm.x2, y: elm.y2 }\n const p1t = applyToPoint(matrix, p1)\n const p2t = applyToPoint(matrix, p2)\n elm.x1 = p1t.x\n elm.y1 = p1t.y\n elm.x2 = p2t.x\n elm.y2 = p2t.y\n } else if (elm.type === \"cad_component\") {\n const newPos = applyToPoint(matrix, {\n x: elm.position.x,\n y: elm.position.y,\n })\n elm.position.x = newPos.x\n elm.position.y = newPos.y\n }\n return elm\n}\n\nexport const transformPCBElements = (\n elms: AnyCircuitElement[],\n matrix: Matrix,\n) => {\n const tsr = decomposeTSR(matrix)\n const quarterTurns = getQuarterTurns(tsr.rotation.angle)\n const flipPadWidthHeight = Math.abs(quarterTurns) % 2 === 1\n let transformedElms = elms.map((elm) => transformPCBElement(elm, matrix))\n if (flipPadWidthHeight) {\n transformedElms = transformedElms.map((elm) => {\n if (\n (elm.type === \"pcb_smtpad\" || elm.type === \"pcb_solder_paste\") &&\n (elm.shape === \"rect\" || elm.shape === \"pill\")\n ) {\n ;[elm.width, elm.height] = [elm.height, elm.width]\n }\n return elm\n })\n }\n return transformedElms\n}\n","export const directionToVec = (direction: \"up\" | \"down\" | \"left\" | \"right\") => {\n if (direction === \"up\") return { x: 0, y: 1 }\n else if (direction === \"down\") return { x: 0, y: -1 }\n else if (direction === \"left\") return { x: -1, y: 0 }\n else if (direction === \"right\") return { x: 1, y: 0 }\n else throw new Error(\"Invalid direction\")\n}\n\nexport const vecToDirection = ({ x, y }: { x: number; y: number }) => {\n if (x > y) y = 0\n if (y > x) x = 0\n if (x > 0 && y === 0) return \"right\"\n else if (x < 0 && y === 0) return \"left\"\n else if (x === 0 && y > 0) return \"up\"\n else if (x === 0 && y < 0) return \"down\"\n else throw new Error(`Invalid vector for direction conversion (${x}, ${y})`)\n}\n\nexport const rotateClockwise = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n) => {\n if (direction === \"up\") return \"right\"\n else if (direction === \"right\") return \"down\"\n else if (direction === \"down\") return \"left\"\n else if (direction === \"left\") return \"up\"\n throw new Error(`Invalid direction: ${direction}`)\n}\n\nexport const rotateCounterClockwise = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n) => {\n if (direction === \"up\") return \"left\"\n else if (direction === \"left\") return \"down\"\n else if (direction === \"down\") return \"right\"\n else if (direction === \"right\") return \"up\"\n throw new Error(`Invalid direction: ${direction}`)\n}\n\nexport const rotateDirection = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n num90DegreeClockwiseTurns: number,\n) => {\n while (num90DegreeClockwiseTurns > 0) {\n direction = rotateClockwise(direction)\n num90DegreeClockwiseTurns--\n }\n while (num90DegreeClockwiseTurns < 0) {\n direction = rotateCounterClockwise(direction)\n num90DegreeClockwiseTurns++\n }\n return direction\n}\n\nexport const oppositeDirection = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n) => {\n if (direction === \"up\") return \"down\"\n else if (direction === \"down\") return \"up\"\n else if (direction === \"left\") return \"right\"\n else if (direction === \"right\") return \"left\"\n throw new Error(`Invalid direction: ${direction}`)\n}\n\nexport const oppositeSide = (\n sideOrDir: \"up\" | \"down\" | \"top\" | \"bottom\" | \"left\" | \"right\",\n) => {\n if (sideOrDir === \"top\" || sideOrDir === \"up\") return \"bottom\"\n else if (sideOrDir === \"bottom\" || sideOrDir === \"down\") return \"top\"\n else if (sideOrDir === \"left\") return \"right\"\n else if (sideOrDir === \"right\") return \"left\"\n throw new Error(`Invalid sideOrDir: ${sideOrDir}`)\n}\n","import * as parsel from \"parsel-js\"\nimport { convertAbbrToType } from \"./convert-abbreviation-to-soup-element-type\"\nimport type { AnyCircuitElement } from \"circuit-json\"\n\nconst filterByType = (\n elements: AnyCircuitElement[],\n type: string,\n): AnyCircuitElement[] => {\n type = convertAbbrToType(type)\n return elements.filter(\n (elm) => (\"ftype\" in elm && elm.ftype === type) || elm.type === type,\n )\n}\n\n/**\n * Filter elements to match the selector, e.g. to access the left port of a\n * resistor you can do \".R1 > port.left\"\n */\nexport const applySelector = (\n elements: AnyCircuitElement[],\n selectorRaw: string,\n): AnyCircuitElement[] => {\n const selectorAST = parsel.parse(selectorRaw)\n return applySelectorAST(elements, selectorAST!)\n}\n\nconst doesElmMatchClassName = (elm: AnyCircuitElement, className: string) =>\n (\"name\" in elm && elm.name === className) ||\n (\"port_hints\" in elm && elm.port_hints?.includes(className))\n\nexport const applySelectorAST = (\n elements: AnyCircuitElement[],\n selectorAST: parsel.AST,\n): AnyCircuitElement[] => {\n switch (selectorAST.type) {\n case \"complex\": {\n switch (selectorAST.combinator) {\n case \" \": // TODO technically should do a deep search\n case \">\": {\n const { left, right } = selectorAST\n if (left.type === \"class\" || left.type === \"type\") {\n // TODO should also check if content matches any element tags\n let matchElms: AnyCircuitElement[]\n if (left.type === \"class\") {\n matchElms = elements.filter((elm) =>\n doesElmMatchClassName(elm, left.name),\n )\n } else if (left.type === \"type\") {\n matchElms = filterByType(elements, left.name)\n } else {\n matchElms = []\n }\n\n const childrenOfMatchingElms = matchElms.flatMap((matchElm) =>\n elements.filter(\n (elm: any) =>\n elm[`${matchElm.type}_id`] ===\n (matchElm as any)[`${matchElm.type}_id`] &&\n elm !== matchElm,\n ),\n )\n return applySelectorAST(childrenOfMatchingElms, right)\n } else {\n throw new Error(`unsupported selector type \"${left.type}\" `)\n }\n }\n default: {\n throw new Error(\n `Couldn't apply selector AST for complex combinator \"${selectorAST.combinator}\"`,\n )\n }\n }\n return []\n }\n case \"compound\": {\n const conditionsToMatch = selectorAST.list.map((part) => {\n switch (part.type) {\n case \"class\": {\n return (elm: any) => doesElmMatchClassName(elm, part.name)\n }\n case \"type\": {\n const name = convertAbbrToType(part.name)\n return (elm: any) => elm.type === name\n }\n }\n })\n\n return elements.filter((elm) =>\n conditionsToMatch.every((condFn) => condFn?.(elm)),\n )\n }\n case \"type\": {\n return filterByType(elements, selectorAST.name) as AnyCircuitElement[]\n }\n case \"class\": {\n return elements.filter((elm) =>\n doesElmMatchClassName(elm, selectorAST.name),\n )\n }\n default: {\n throw new Error(\n `Couldn't apply selector AST for type: \"${\n selectorAST.type\n }\" ${JSON.stringify(selectorAST, null, \" \")}`,\n )\n }\n }\n}\n","export const convertAbbrToType = (abbr: string): string => {\n switch (abbr) {\n case \"port\":\n return \"source_port\"\n case \"net\":\n return \"source_net\"\n case \"power\":\n return \"simple_power_source\"\n case \"silkscreenpath\":\n return \"pcb_silkscreen_path\"\n }\n return abbr\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\n\nexport const getElementId = (elm: AnyCircuitElement): string => {\n const type = elm.type\n const id = (elm as any)[`${type}_id`]\n return id\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { getElementId } from \"./get-element-id\"\n\nexport const getElementById = (\n soup: AnyCircuitElement[],\n id: string,\n): AnyCircuitElement | null => {\n return soup.find((elm) => getElementId(elm) === id) ?? null\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { cju } from \"../cju\"\n\nexport const getReadableNameForPcbPort = (\n soup: AnyCircuitElement[],\n pcb_port_id: string,\n): string => {\n const pcbPort = cju(soup).pcb_port.get(pcb_port_id)\n if (!pcbPort) {\n return `pcb_port[#${pcb_port_id}]`\n }\n\n // Get the component information\n const pcbComponent = pcbPort.pcb_component_id\n ? cju(soup).pcb_component.get(pcbPort.pcb_component_id)\n : undefined\n\n if (!pcbComponent) {\n return `pcb_port[#${pcb_port_id}]`\n }\n\n // Get the source component information\n const sourceComponent = cju(soup).source_component.get(\n pcbComponent.source_component_id,\n )\n\n if (!sourceComponent) {\n return `pcb_port[#${pcb_port_id}]`\n }\n\n // Get the source port information\n const sourcePort = cju(soup).source_port.get(pcbPort.source_port_id)\n\n if (!sourcePort) {\n return `pcb_port[#${pcb_port_id}]`\n }\n\n // Determine the pad number or hint\n let padIdentifier: string\n if (sourcePort?.port_hints && sourcePort.port_hints.length > 0) {\n padIdentifier = sourcePort.port_hints[0]!\n } else if (sourcePort.port_hints && sourcePort.port_hints.length > 0) {\n padIdentifier = sourcePort.port_hints[0]!\n } else {\n padIdentifier = pcb_port_id\n }\n\n return `pcb_port[.${sourceComponent.name} > .${padIdentifier}]`\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { cju } from \"../cju\"\nimport { getReadableNameForPcbPort } from \"./get-readable-name-for-pcb-port\"\n\nexport function getReadableNameForPcbSmtpad(\n soup: AnyCircuitElement[],\n pcb_smtpad_id: string,\n): string {\n // Find the pcb_smtpad object\n const pcbSmtpad = cju(soup).pcb_smtpad.get(pcb_smtpad_id)\n\n if (!pcbSmtpad || !pcbSmtpad.pcb_port_id) {\n return `smtpad[${pcb_smtpad_id}]`\n }\n\n return getReadableNameForPcbPort(soup, pcbSmtpad.pcb_port_id)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { cju } from \"../cju\"\n\nexport function getReadableNameForPcbTrace(\n soup: AnyCircuitElement[],\n pcb_trace_id: string,\n) {\n // Find the pcb_trace object\n const pcbTrace = cju(soup).pcb_trace.get(pcb_trace_id)\n\n if (!pcbTrace) {\n return `trace[${pcb_trace_id}]`\n }\n\n // Get the connected ports\n const connectedPcbPortIds: string[] = pcbTrace.route\n .flatMap((point: any) => [point.start_pcb_port_id, point.end_pcb_port_id])\n .filter(Boolean)\n\n if (connectedPcbPortIds.length === 0) {\n return `trace[${pcb_trace_id}]`\n }\n\n // Function to get component name and port hint\n function getComponentAndPortInfo(pcb_port_id: string) {\n const pcbPort = cju(soup).pcb_port.get(pcb_port_id)\n if (!pcbPort) return null\n\n const pcbComponent = pcbPort.pcb_component_id\n ? cju(soup).pcb_component.get(pcbPort.pcb_component_id)\n : undefined\n if (!pcbComponent) return null\n const sourceComponent = cju(soup).source_component.get(\n pcbComponent.source_component_id,\n )\n if (!sourceComponent) return null\n\n const sourcePort = cju(soup).source_port.get(pcbPort.source_port_id)\n const portHint = sourcePort?.port_hints ? sourcePort.port_hints[1] : \"\"\n\n return {\n componentName: sourceComponent.name,\n portHint: portHint,\n }\n }\n\n // Generate the readable selector\n const selectorParts = connectedPcbPortIds.map((portId) => {\n const info = getComponentAndPortInfo(portId)\n if (info) {\n return `.${info.componentName} > port.${info.portHint}`\n }\n return `port[${portId}]`\n })\n\n return `trace[${selectorParts.join(\", \")}]`\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { getElementById } from \"../get-element-by-id\"\nimport { getElementId } from \"../get-element-id\"\nimport { getReadableNameForPcbPort } from \"./get-readable-name-for-pcb-port\"\nimport { getReadableNameForPcbSmtpad } from \"./get-readable-name-for-pcb-smtpad\"\nimport { getReadableNameForPcbTrace } from \"./get-readable-name-for-pcb-trace\"\n\nexport const getReadableNameForElement = (\n soup: AnyCircuitElement[],\n elm: AnyCircuitElement | string,\n): string => {\n if (typeof elm === \"string\") {\n const elmObj = getElementById(soup, elm)\n if (!elmObj) `unknown (could not find element with id ${elm})`\n return getReadableNameForElement(soup, elmObj as any)\n }\n switch (elm.type) {\n case \"pcb_port\":\n return getReadableNameForPcbPort(soup, elm.pcb_port_id)\n case \"pcb_smtpad\":\n return getReadableNameForPcbSmtpad(soup, elm.pcb_smtpad_id)\n case \"pcb_trace\":\n return getReadableNameForPcbTrace(soup, elm.pcb_trace_id)\n case \"source_component\":\n return `source_component[${elm.name}]`\n default:\n return `${elm.type}[#${getElementId(elm)}]`\n }\n}\n\nexport {\n getReadableNameForPcbPort,\n getReadableNameForPcbSmtpad,\n getReadableNameForPcbTrace,\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\n\nexport interface PcbBounds {\n minX: number\n minY: number\n maxX: number\n maxY: number\n}\n\nconst mergeBounds = (\n currentBounds: PcbBounds,\n nextBounds: PcbBounds,\n): PcbBounds => ({\n minX: Math.min(currentBounds.minX, nextBounds.minX),\n minY: Math.min(currentBounds.minY, nextBounds.minY),\n maxX: Math.max(currentBounds.maxX, nextBounds.maxX),\n maxY: Math.max(currentBounds.maxY, nextBounds.maxY),\n})\n\nconst getCircleBounds = (x: number, y: number, diameter: number) => {\n const radius = diameter / 2\n return {\n minX: x - radius,\n minY: y - radius,\n maxX: x + radius,\n maxY: y + radius,\n }\n}\n\nconst getRotatedRectBounds = (\n x: number,\n y: number,\n width: number,\n height: number,\n rotationDegrees: number,\n) => {\n const halfWidth = width / 2\n const halfHeight = height / 2\n const theta = (rotationDegrees * Math.PI) / 180\n const cosTheta = Math.cos(theta)\n const sinTheta = Math.sin(theta)\n\n const corners = [\n { x: -halfWidth, y: -halfHeight },\n { x: halfWidth, y: -halfHeight },\n { x: halfWidth, y: halfHeight },\n { x: -halfWidth, y: halfHeight },\n ].map((corner) => ({\n x: x + corner.x * cosTheta - corner.y * sinTheta,\n y: y + corner.x * sinTheta + corner.y * cosTheta,\n }))\n\n return {\n minX: Math.min(...corners.map((corner) => corner.x)),\n minY: Math.min(...corners.map((corner) => corner.y)),\n maxX: Math.max(...corners.map((corner) => corner.x)),\n maxY: Math.max(...corners.map((corner) => corner.y)),\n }\n}\n\nconst getRotatedOvalBounds = (\n x: number,\n y: number,\n width: number,\n height: number,\n rotationDegrees: number,\n) => {\n const radiusX = width / 2\n const radiusY = height / 2\n const theta = (rotationDegrees * Math.PI) / 180\n const cosTheta = Math.cos(theta)\n const sinTheta = Math.sin(theta)\n const halfWidth = Math.hypot(radiusX * cosTheta, radiusY * sinTheta)\n const halfHeight = Math.hypot(radiusX * sinTheta, radiusY * cosTheta)\n\n return {\n minX: x - halfWidth,\n minY: y - halfHeight,\n maxX: x + halfWidth,\n maxY: y + halfHeight,\n }\n}\n\nconst getRotatedPillBounds = (\n x: number,\n y: number,\n width: number,\n height: number,\n rotationDegrees: number,\n) => {\n const radius = Math.min(width, height) / 2\n const halfLineLength = Math.max(width, height) / 2 - radius\n const theta = (rotationDegrees * Math.PI) / 180\n const axis =\n width >= height ? { x: halfLineLength, y: 0 } : { x: 0, y: halfLineLength }\n const rotatedAxis = {\n x: axis.x * Math.cos(theta) - axis.y * Math.sin(theta),\n y: axis.x * Math.sin(theta) + axis.y * Math.cos(theta),\n }\n const halfWidth = Math.abs(rotatedAxis.x) + radius\n const halfHeight = Math.abs(rotatedAxis.y) + radius\n\n return {\n minX: x - halfWidth,\n minY: y - halfHeight,\n maxX: x + halfWidth,\n maxY: y + halfHeight,\n }\n}\n\nconst getBoundsFromPoints = (\n points: Array<{ x: number; y: number }>,\n): PcbBounds | null => {\n if (points.length === 0) return null\n\n return {\n minX: Math.min(...points.map((point) => point.x)),\n minY: Math.min(...points.map((point) => point.y)),\n maxX: Math.max(...points.map((point) => point.x)),\n maxY: Math.max(...points.map((point) => point.y)),\n }\n}\n\nconst getRoutePoints = (route: unknown): Array<{ x: number; y: number }> => {\n if (!Array.isArray(route)) return []\n\n return route.flatMap((point): Array<{ x: number; y: number }> => {\n if (!point || typeof point !== \"object\") return []\n if (\n \"x\" in point &&\n \"y\" in point &&\n typeof point.x === \"number\" &&\n typeof point.y === \"number\"\n ) {\n return [{ x: point.x, y: point.y }]\n }\n\n if (\"start\" in point && \"end\" in point) {\n const positions = [point.start, point.end]\n return positions.filter(\n (position): position is { x: number; y: number } =>\n Boolean(\n position &&\n typeof position === \"object\" &&\n \"x\" in position &&\n \"y\" in position &&\n typeof position.x === \"number\" &&\n typeof position.y === \"number\",\n ),\n )\n }\n\n return []\n })\n}\n\n/** Returns the axis-aligned bounds of one drawable PCB element. */\nexport const getPcbElementBounds = (\n elm: AnyCircuitElement,\n): PcbBounds | null => {\n if (!elm.type.startsWith(\"pcb_\")) return null\n\n if (\n elm.type === \"pcb_smtpad\" &&\n elm.shape === \"polygon\" &&\n Array.isArray(elm.points)\n ) {\n return getBoundsFromPoints(elm.points)\n }\n\n if (elm.type === \"pcb_hole\" && elm.hole_shape === \"circle\") {\n return getCircleBounds(elm.x, elm.y, elm.hole_diameter)\n }\n\n if (elm.type === \"pcb_plated_hole\") {\n let platedHoleBounds: PcbBounds | undefined\n\n if (\"outer_diameter\" in elm && typeof elm.outer_diameter === \"number\") {\n platedHoleBounds = getCircleBounds(elm.x, elm.y, elm.outer_diameter)\n } else if (\n \"hole_diameter\" in elm &&\n typeof elm.hole_diameter === \"number\"\n ) {\n platedHoleBounds = getCircleBounds(elm.x, elm.y, elm.hole_diameter)\n }\n\n if (\n (elm.shape === \"oval\" || elm.shape === \"pill\") &&\n typeof elm.outer_width === \"number\" &&\n typeof elm.outer_height === \"number\"\n ) {\n const getOuterBounds =\n elm.shape === \"pill\" ? getRotatedPillBounds : getRotatedOvalBounds\n platedHoleBounds = getOuterBounds(\n elm.x,\n elm.y,\n elm.outer_width,\n elm.outer_height,\n elm.ccw_rotation ?? 0,\n )\n }\n\n if (\n \"rect_pad_width\" in elm &&\n typeof elm.rect_pad_width === \"number\" &&\n \"rect_pad_height\" in elm &&\n typeof elm.rect_pad_height === \"number\"\n ) {\n const rectBounds = getRotatedRectBounds(\n elm.x,\n elm.y,\n elm.rect_pad_width,\n elm.rect_pad_height,\n \"rect_ccw_rotation\" in elm ? (elm.rect_ccw_rotation ?? 0) : 0,\n )\n platedHoleBounds = platedHoleBounds\n ? mergeBounds(platedHoleBounds, rectBounds)\n : rectBounds\n }\n\n if (\"hole_diameter\" in elm && typeof elm.hole_diameter === \"number\") {\n const drillBounds = getCircleBounds(\n elm.x +\n (\"hole_offset_x\" in elm ? ((elm.hole_offset_x as number) ?? 0) : 0),\n elm.y +\n (\"hole_offset_y\" in elm ? ((elm.hole_offset_y as number) ?? 0) : 0),\n elm.hole_diameter,\n )\n platedHoleBounds = platedHoleBounds\n ? mergeBounds(platedHoleBounds, drillBounds)\n : drillBounds\n }\n\n if (platedHoleBounds) return platedHoleBounds\n }\n\n const elementRecord = elm as unknown as Record<string, unknown>\n const routeBounds = getBoundsFromPoints(getRoutePoints(elementRecord.route))\n if (routeBounds) return routeBounds\n\n const outlineBounds = getBoundsFromPoints(\n getRoutePoints(elementRecord.outline),\n )\n if (outlineBounds) return outlineBounds\n\n const pointsBounds = getBoundsFromPoints(getRoutePoints(elementRecord.points))\n if (pointsBounds) return pointsBounds\n\n let centerX: number | undefined\n let centerY: number | undefined\n\n let width: number | undefined\n let height: number | undefined\n\n if (\"x\" in elm && \"y\" in elm) {\n centerX = Number(elm.x)\n centerY = Number(elm.y)\n }\n\n if (\"outer_diameter\" in elm) {\n width = Number(elm.outer_diameter)\n height = Number(elm.outer_diameter)\n }\n\n if (\"width\" in elm) {\n width = Number(elm.width)\n }\n\n if (\"height\" in elm) {\n height = Number(elm.height)\n }\n\n if (\n \"center\" in elm &&\n elm.center &&\n typeof elm.center === \"object\" &&\n \"x\" in elm.center &&\n \"y\" in elm.center\n ) {\n centerX = Number(elm.center.x)\n centerY = Number(elm.center.y)\n }\n\n let rotation = 0\n if (\"rotation\" in elm && typeof elm.rotation === \"number\") {\n rotation = elm.rotation\n }\n if (\"ccw_rotation\" in elm && typeof elm.ccw_rotation === \"number\") {\n rotation = elm.ccw_rotation\n }\n\n if (centerX !== undefined && centerY !== undefined) {\n if (width !== undefined && height !== undefined) {\n return rotation\n ? getRotatedRectBounds(centerX, centerY, width, height, rotation)\n : {\n minX: centerX - width / 2,\n minY: centerY - height / 2,\n maxX: centerX + width / 2,\n maxY: centerY + height / 2,\n }\n }\n\n if (\"radius\" in elm && typeof elm.radius === \"number\") {\n return getCircleBounds(centerX, centerY, elm.radius * 2)\n }\n\n return { minX: centerX, minY: centerY, maxX: centerX, maxY: centerY }\n }\n\n const anchoredPoint = [elementRecord.anchor_position, elementRecord.position]\n .filter((position): position is { x: number; y: number } =>\n Boolean(\n position &&\n typeof position === \"object\" &&\n \"x\" in position &&\n \"y\" in position &&\n typeof position.x === \"number\" &&\n typeof position.y === \"number\",\n ),\n )\n .at(0)\n\n return anchoredPoint\n ? {\n minX: anchoredPoint.x,\n minY: anchoredPoint.y,\n maxX: anchoredPoint.x,\n maxY: anchoredPoint.y,\n }\n : null\n}\n\nexport const getBoundsOfPcbElements = (\n elements: AnyCircuitElement[],\n): PcbBounds => {\n let bounds: PcbBounds = {\n minX: Number.POSITIVE_INFINITY,\n minY: Number.POSITIVE_INFINITY,\n maxX: Number.NEGATIVE_INFINITY,\n maxY: Number.NEGATIVE_INFINITY,\n }\n\n for (const element of elements) {\n const elementBounds = getPcbElementBounds(element)\n if (elementBounds) bounds = mergeBounds(bounds, elementBounds)\n }\n\n return bounds\n}\n\n/** Returns PCB elements whose axis-aligned bounds intersect the given bounds. */\nexport const getPcbElementsWithinBounds = (\n elements: AnyCircuitElement[],\n bounds: PcbBounds,\n): AnyCircuitElement[] =>\n elements.filter((element) => {\n const elementBounds = getPcbElementBounds(element)\n if (!elementBounds) return false\n\n return (\n elementBounds.minX <= bounds.maxX &&\n elementBounds.maxX >= bounds.minX &&\n elementBounds.minY <= bounds.maxY &&\n elementBounds.maxY >= bounds.minY\n )\n })\n","import type { PcbBoard } from \"circuit-json\"\n\nexport interface BoardBounds {\n minX: number\n minY: number\n maxX: number\n maxY: number\n width: number\n height: number\n center: {\n x: number\n y: number\n }\n}\n\nexport const getBoardBounds = (board: PcbBoard): BoardBounds => {\n if (board.width && board.height && board.center) {\n const halfWidth = board.width / 2\n const halfHeight = board.height / 2\n\n return {\n minX: board.center.x - halfWidth,\n minY: board.center.y - halfHeight,\n maxX: board.center.x + halfWidth,\n maxY: board.center.y + halfHeight,\n width: board.width,\n height: board.height,\n center: {\n x: board.center.x,\n y: board.center.y,\n },\n }\n }\n\n if (!board.outline || board.outline.length === 0) {\n throw new Error(\n \"Unable to compute board bounds. pcb_board must include width/height/center or a non-empty outline.\",\n )\n }\n\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n for (const point of board.outline) {\n minX = Math.min(minX, point.x)\n minY = Math.min(minY, point.y)\n maxX = Math.max(maxX, point.x)\n maxY = Math.max(maxY, point.y)\n }\n\n const width = maxX - minX\n const height = maxY - minY\n\n return {\n minX,\n minY,\n maxX,\n maxY,\n width,\n height,\n center: {\n x: minX + width / 2,\n y: minY + height / 2,\n },\n }\n}\n","import type {\n SchematicComponent,\n SchematicNetLabel,\n SchematicTrace,\n} from \"circuit-json\"\n\nexport type SchematicElementWithBounds =\n | SchematicComponent\n | SchematicNetLabel\n | SchematicTrace\n\nexport interface SchematicElementBounds {\n minX: number\n minY: number\n maxX: number\n maxY: number\n width: number\n height: number\n center: {\n x: number\n y: number\n }\n}\n\nconst SCHEMATIC_TRACE_WIDTH = 0.1\nconst SCHEMATIC_NET_LABEL_FONT_SIZE = 0.18\nconst SCHEMATIC_NET_LABEL_HEIGHT = 0.2\n\nconst createBounds = ({\n minX,\n minY,\n maxX,\n maxY,\n}: {\n minX: number\n minY: number\n maxX: number\n maxY: number\n}): SchematicElementBounds => {\n const width = maxX - minX\n const height = maxY - minY\n\n return {\n minX,\n minY,\n maxX,\n maxY,\n width,\n height,\n center: {\n x: minX + width / 2,\n y: minY + height / 2,\n },\n }\n}\n\nconst getSchematicNetLabelTextWidth = (text: string): number => {\n const characterWidth = 0.12 * (SCHEMATIC_NET_LABEL_FONT_SIZE / 0.18)\n const horizontalPadding = 0.12 * (SCHEMATIC_NET_LABEL_FONT_SIZE / 0.18)\n\n return text.length * characterWidth + horizontalPadding\n}\n\nconst getSchematicNetLabelBounds = (\n netLabel: SchematicNetLabel,\n): SchematicElementBounds => {\n const labelLength = getSchematicNetLabelTextWidth(netLabel.text)\n const anchor = netLabel.anchor_position\n\n if (!anchor) {\n const isVertical =\n netLabel.anchor_side === \"top\" || netLabel.anchor_side === \"bottom\"\n const width = isVertical ? SCHEMATIC_NET_LABEL_HEIGHT : labelLength\n const height = isVertical ? labelLength : SCHEMATIC_NET_LABEL_HEIGHT\n\n return createBounds({\n minX: netLabel.center.x - width / 2,\n minY: netLabel.center.y - height / 2,\n maxX: netLabel.center.x + width / 2,\n maxY: netLabel.center.y + height / 2,\n })\n }\n\n switch (netLabel.anchor_side) {\n case \"left\":\n return createBounds({\n minX: anchor.x,\n minY: anchor.y - SCHEMATIC_NET_LABEL_HEIGHT / 2,\n maxX: anchor.x + labelLength,\n maxY: anchor.y + SCHEMATIC_NET_LABEL_HEIGHT / 2,\n })\n case \"right\":\n return createBounds({\n minX: anchor.x - labelLength,\n minY: anchor.y - SCHEMATIC_NET_LABEL_HEIGHT / 2,\n maxX: anchor.x,\n maxY: anchor.y + SCHEMATIC_NET_LABEL_HEIGHT / 2,\n })\n case \"top\":\n return createBounds({\n minX: anchor.x - SCHEMATIC_NET_LABEL_HEIGHT / 2,\n minY: anchor.y - labelLength,\n maxX: anchor.x + SCHEMATIC_NET_LABEL_HEIGHT / 2,\n maxY: anchor.y,\n })\n case \"bottom\":\n return createBounds({\n minX: anchor.x - SCHEMATIC_NET_LABEL_HEIGHT / 2,\n minY: anchor.y,\n maxX: anchor.x + SCHEMATIC_NET_LABEL_HEIGHT / 2,\n maxY: anchor.y + labelLength,\n })\n }\n}\n\n/**\n * Returns the axis-aligned bounds of a schematic component, net label, or\n * trace. Trace bounds include the rendered trace width. An empty trace has no\n * drawable geometry and returns null.\n */\nexport const getSchematicElementBounds = (\n element: SchematicElementWithBounds,\n): SchematicElementBounds | null => {\n if (element.type === \"schematic_component\") {\n return createBounds({\n minX: element.center.x - element.size.width / 2,\n minY: element.center.y - element.size.height / 2,\n maxX: element.center.x + element.size.width / 2,\n maxY: element.center.y + element.size.height / 2,\n })\n }\n\n if (element.type === \"schematic_net_label\") {\n return getSchematicNetLabelBounds(element)\n }\n\n const points = [\n ...element.edges.flatMap((edge) => [edge.from, edge.to]),\n ...element.junctions,\n ]\n if (points.length === 0) return null\n\n const halfTraceWidth = SCHEMATIC_TRACE_WIDTH / 2\n return createBounds({\n minX: Math.min(...points.map((point) => point.x)) - halfTraceWidth,\n minY: Math.min(...points.map((point) => point.y)) - halfTraceWidth,\n maxX: Math.max(...points.map((point) => point.x)) + halfTraceWidth,\n maxY: Math.max(...points.map((point) => point.y)) + halfTraceWidth,\n })\n}\n","export function stringHash(str: string) {\n let hash = 0\n if (str.length == 0) return hash\n for (var i = 0; i < str.length; i++) {\n var char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32bit integer\n }\n return Math.abs(hash)\n}\n","import { stringHash } from \"./string-hash\"\n\nexport type LayoutDebugObject = {\n x: number\n y: number\n width: number\n height: number\n bg_color: string\n title: string\n content: Object\n secondary?: boolean\n}\n\n/**\n * Vendored from \"nice-color-palettes\" package\n */\nconst nice_color_palettes = [\n [\"#69d2e7\", \"#a7dbd8\", \"#e0e4cc\", \"#f38630\", \"#fa6900\"],\n [\"#fe4365\", \"#fc9d9a\", \"#f9cdad\", \"#c8c8a9\", \"#83af9b\"],\n [\"#ecd078\", \"#d95b43\", \"#c02942\", \"#542437\", \"#53777a\"],\n [\"#556270\", \"#4ecdc4\", \"#c7f464\", \"#ff6b6b\", \"#c44d58\"],\n [\"#774f38\", \"#e08e79\", \"#f1d4af\", \"#ece5ce\", \"#c5e0dc\"],\n [\"#e8ddcb\", \"#cdb380\", \"#036564\", \"#033649\", \"#031634\"],\n [\"#490a3d\", \"#bd1550\", \"#e97f02\", \"#f8ca00\", \"#8a9b0f\"],\n [\"#594f4f\", \"#547980\", \"#45ada8\", \"#9de0ad\", \"#e5fcc2\"],\n [\"#00a0b0\", \"#6a4a3c\", \"#cc333f\", \"#eb6841\", \"#edc951\"],\n [\"#e94e77\", \"#d68189\", \"#c6a49a\", \"#c6e5d9\", \"#f4ead5\"],\n [\"#3fb8af\", \"#7fc7af\", \"#dad8a7\", \"#ff9e9d\", \"#ff3d7f\"],\n [\"#d9ceb2\", \"#948c75\", \"#d5ded9\", \"#7a6a53\", \"#99b2b7\"],\n [\"#ffffff\", \"#cbe86b\", \"#f2e9e1\", \"#1c140d\", \"#cbe86b\"],\n [\"#efffcd\", \"#dce9be\", \"#555152\", \"#2e2633\", \"#99173c\"],\n [\"#343838\", \"#005f6b\", \"#008c9e\", \"#00b4cc\", \"#00dffc\"],\n [\"#413e4a\", \"#73626e\", \"#b38184\", \"#f0b49e\", \"#f7e4be\"],\n [\"#ff4e50\", \"#fc913a\", \"#f9d423\", \"#ede574\", \"#e1f5c4\"],\n [\"#99b898\", \"#fecea8\", \"#ff847c\", \"#e84a5f\", \"#2a363b\"],\n [\"#655643\", \"#80bca3\", \"#f6f7bd\", \"#e6ac27\", \"#bf4d28\"],\n [\"#00a8c6\", \"#40c0cb\", \"#f9f2e7\", \"#aee239\", \"#8fbe00\"],\n [\"#351330\", \"#424254\", \"#64908a\", \"#e8caa4\", \"#cc2a41\"],\n [\"#554236\", \"#f77825\", \"#d3ce3d\", \"#f1efa5\", \"#60b99a\"],\n [\"#5d4157\", \"#838689\", \"#a8caba\", \"#cad7b2\", \"#ebe3aa\"],\n [\"#8c2318\", \"#5e8c6a\", \"#88a65e\", \"#bfb35a\", \"#f2c45a\"],\n [\"#fad089\", \"#ff9c5b\", \"#f5634a\", \"#ed303c\", \"#3b8183\"],\n [\"#ff4242\", \"#f4fad2\", \"#d4ee5e\", \"#e1edb9\", \"#f0f2eb\"],\n [\"#f8b195\", \"#f67280\", \"#c06c84\", \"#6c5b7b\", \"#355c7d\"],\n [\"#d1e751\", \"#ffffff\", \"#000000\", \"#4dbce9\", \"#26ade4\"],\n [\"#1b676b\", \"#519548\", \"#88c425\", \"#bef202\", \"#eafde6\"],\n [\"#5e412f\", \"#fcebb6\", \"#78c0a8\", \"#f07818\", \"#f0a830\"],\n [\"#bcbdac\", \"#cfbe27\", \"#f27435\", \"#f02475\", \"#3b2d38\"],\n [\"#452632\", \"#91204d\", \"#e4844a\", \"#e8bf56\", \"#e2f7ce\"],\n [\"#eee6ab\", \"#c5bc8e\", \"#696758\", \"#45484b\", \"#36393b\"],\n [\"#f0d8a8\", \"#3d1c00\", \"#86b8b1\", \"#f2d694\", \"#fa2a00\"],\n [\"#2a044a\", \"#0b2e59\", \"#0d6759\", \"#7ab317\", \"#a0c55f\"],\n [\"#f04155\", \"#ff823a\", \"#f2f26f\", \"#fff7bd\", \"#95cfb7\"],\n [\"#b9d7d9\", \"#668284\", \"#2a2829\", \"#493736\", \"#7b3b3b\"],\n [\"#bbbb88\", \"#ccc68d\", \"#eedd99\", \"#eec290\", \"#eeaa88\"],\n [\"#b3cc57\", \"#ecf081\", \"#ffbe40\", \"#ef746f\", \"#ab3e5b\"],\n [\"#a3a948\", \"#edb92e\", \"#f85931\", \"#ce1836\", \"#009989\"],\n [\"#300030\", \"#480048\", \"#601848\", \"#c04848\", \"#f07241\"],\n [\"#67917a\", \"#170409\", \"#b8af03\", \"#ccbf82\", \"#e33258\"],\n [\"#aab3ab\", \"#c4cbb7\", \"#ebefc9\", \"#eee0b7\", \"#e8caaf\"],\n [\"#e8d5b7\", \"#0e2430\", \"#fc3a51\", \"#f5b349\", \"#e8d5b9\"],\n [\"#ab526b\", \"#bca297\", \"#c5ceae\", \"#f0e2a4\", \"#f4ebc3\"],\n [\"#607848\", \"#789048\", \"#c0d860\", \"#f0f0d8\", \"#604848\"],\n [\"#b6d8c0\", \"#c8d9bf\", \"#dadabd\", \"#ecdbbc\", \"#fedcba\"],\n [\"#a8e6ce\", \"#dcedc2\", \"#ffd3b5\", \"#ffaaa6\", \"#ff8c94\"],\n [\"#3e4147\", \"#fffedf\", \"#dfba69\", \"#5a2e2e\", \"#2a2c31\"],\n [\"#fc354c\", \"#29221f\", \"#13747d\", \"#0abfbc\", \"#fcf7c5\"],\n [\"#cc0c39\", \"#e6781e\", \"#c8cf02\", \"#f8fcc1\", \"#1693a7\"],\n [\"#1c2130\", \"#028f76\", \"#b3e099\", \"#ffeaad\", \"#d14334\"],\n [\"#a7c5bd\", \"#e5ddcb\", \"#eb7b59\", \"#cf4647\", \"#524656\"],\n [\"#dad6ca\", \"#1bb0ce\", \"#4f8699\", \"#6a5e72\", \"#563444\"],\n [\"#5c323e\", \"#a82743\", \"#e15e32\", \"#c0d23e\", \"#e5f04c\"],\n [\"#edebe6\", \"#d6e1c7\", \"#94c7b6\", \"#403b33\", \"#d3643b\"],\n [\"#fdf1cc\", \"#c6d6b8\", \"#987f69\", \"#e3ad40\", \"#fcd036\"],\n [\"#230f2b\", \"#f21d41\", \"#ebebbc\", \"#bce3c5\", \"#82b3ae\"],\n [\"#b9d3b0\", \"#81bda4\", \"#b28774\", \"#f88f79\", \"#f6aa93\"],\n [\"#3a111c\", \"#574951\", \"#83988e\", \"#bcdea5\", \"#e6f9bc\"],\n [\"#5e3929\", \"#cd8c52\", \"#b7d1a3\", \"#dee8be\", \"#fcf7d3\"],\n [\"#1c0113\", \"#6b0103\", \"#a30006\", \"#c21a01\", \"#f03c02\"],\n [\"#000000\", \"#9f111b\", \"#b11623\", \"#292c37\", \"#cccccc\"],\n [\"#382f32\", \"#ffeaf2\", \"#fcd9e5\", \"#fbc5d8\", \"#f1396d\"],\n [\"#e3dfba\", \"#c8d6bf\", \"#93ccc6\", \"#6cbdb5\", \"#1a1f1e\"],\n [\"#f6f6f6\", \"#e8e8e8\", \"#333333\", \"#990100\", \"#b90504\"],\n [\"#1b325f\", \"#9cc4e4\", \"#e9f2f9\", \"#3a89c9\", \"#f26c4f\"],\n [\"#a1dbb2\", \"#fee5ad\", \"#faca66\", \"#f7a541\", \"#f45d4c\"],\n [\"#c1b398\", \"#605951\", \"#fbeec2\", \"#61a6ab\", \"#accec0\"],\n [\"#5e9fa3\", \"#dcd1b4\", \"#fab87f\", \"#f87e7b\", \"#b05574\"],\n [\"#951f2b\", \"#f5f4d7\", \"#e0dfb1\", \"#a5a36c\", \"#535233\"],\n [\"#8dccad\", \"#988864\", \"#fea6a2\", \"#f9d6ac\", \"#ffe9af\"],\n [\"#2d2d29\", \"#215a6d\", \"#3ca2a2\", \"#92c7a3\", \"#dfece6\"],\n [\"#413d3d\", \"#040004\", \"#c8ff00\", \"#fa023c\", \"#4b000f\"],\n [\"#eff3cd\", \"#b2d5ba\", \"#61ada0\", \"#248f8d\", \"#605063\"],\n [\"#ffefd3\", \"#fffee4\", \"#d0ecea\", \"#9fd6d2\", \"#8b7a5e\"],\n [\"#cfffdd\", \"#b4dec1\", \"#5c5863\", \"#a85163\", \"#ff1f4c\"],\n [\"#9dc9ac\", \"#fffec7\", \"#f56218\", \"#ff9d2e\", \"#919167\"],\n [\"#4e395d\", \"#827085\", \"#8ebe94\", \"#ccfc8e\", \"#dc5b3e\"],\n [\"#a8a7a7\", \"#cc527a\", \"#e8175d\", \"#474747\", \"#363636\"],\n [\"#f8edd1\", \"#d88a8a\", \"#474843\", \"#9d9d93\", \"#c5cfc6\"],\n [\"#046d8b\", \"#309292\", \"#2fb8ac\", \"#93a42a\", \"#ecbe13\"],\n [\"#f38a8a\", \"#55443d\", \"#a0cab5\", \"#cde9ca\", \"#f1edd0\"],\n [\"#a70267\", \"#f10c49\", \"#fb6b41\", \"#f6d86b\", \"#339194\"],\n [\"#ff003c\", \"#ff8a00\", \"#fabe28\", \"#88c100\", \"#00c176\"],\n [\"#ffedbf\", \"#f7803c\", \"#f54828\", \"#2e0d23\", \"#f8e4c1\"],\n [\"#4e4d4a\", \"#353432\", \"#94ba65\", \"#2790b0\", \"#2b4e72\"],\n [\"#0ca5b0\", \"#4e3f30\", \"#fefeeb\", \"#f8f4e4\", \"#a5b3aa\"],\n [\"#4d3b3b\", \"#de6262\", \"#ffb88c\", \"#ffd0b3\", \"#f5e0d3\"],\n [\"#fffbb7\", \"#a6f6af\", \"#66b6ab\", \"#5b7c8d\", \"#4f2958\"],\n [\"#edf6ee\", \"#d1c089\", \"#b3204d\", \"#412e28\", \"#151101\"],\n [\"#9d7e79\", \"#ccac95\", \"#9a947c\", \"#748b83\", \"#5b756c\"],\n [\"#fcfef5\", \"#e9ffe1\", \"#cdcfb7\", \"#d6e6c3\", \"#fafbe3\"],\n [\"#9cddc8\", \"#bfd8ad\", \"#ddd9ab\", \"#f7af63\", \"#633d2e\"],\n [\"#30261c\", \"#403831\", \"#36544f\", \"#1f5f61\", \"#0b8185\"],\n [\"#aaff00\", \"#ffaa00\", \"#ff00aa\", \"#aa00ff\", \"#00aaff\"],\n [\"#d1313d\", \"#e5625c\", \"#f9bf76\", \"#8eb2c5\", \"#615375\"],\n [\"#ffe181\", \"#eee9e5\", \"#fad3b2\", \"#ffba7f\", \"#ff9c97\"],\n [\"#73c8a9\", \"#dee1b6\", \"#e1b866\", \"#bd5532\", \"#373b44\"],\n [\"#805841\", \"#dcf7f3\", \"#fffcdd\", \"#ffd8d8\", \"#f5a2a2\"],\n]\n\nexport const getDebugLayoutObject = (lo: any): LayoutDebugObject | null => {\n let {\n x,\n y,\n width,\n height,\n }: { x: number; y: number; width?: number; height?: number } = {\n ...lo,\n ...(lo as any).size,\n ...(lo as any).center,\n ...(lo as any).position,\n }\n\n if (\n lo.x1 !== undefined &&\n lo.x2 !== undefined &&\n lo.y1 !== undefined &&\n lo.y2 !== undefined\n ) {\n x = (lo.x1 + lo.x2) / 2\n y = (lo.y1 + lo.y2) / 2\n width = Math.abs(lo.x1 - lo.x2)\n height = Math.abs(lo.y1 - lo.y2)\n }\n\n if (lo.points && Array.isArray(lo.points) && lo.points.length > 0) {\n const xCoords = lo.points.map((point: { x: number }) => point.x)\n const yCoords = lo.points.map((point: { y: number }) => point.y)\n\n const minX = Math.min(...xCoords)\n const maxX = Math.max(...xCoords)\n const minY = Math.min(...yCoords)\n const maxY = Math.max(...yCoords)\n\n x = (minX + maxX) / 2\n y = (minY + maxY) / 2\n width = maxX - minX\n height = maxY - minY\n }\n\n const title = lo.text || lo.name || lo.source?.text || lo.source?.name || \"?\"\n const content = lo\n\n if (x === undefined || y === undefined) return null\n\n if (width === undefined) {\n if (\"outer_diameter\" in lo) {\n width = lo.outer_diameter\n height = lo.outer_diameter\n } else if (\"rect_pad_width\" in lo && \"rect_pad_height\" in lo) {\n width = lo.rect_pad_width as number\n height = lo.rect_pad_height as number\n if (\"hole_diameter\" in lo) {\n width = Math.max(width, lo.hole_diameter as number)\n height = Math.max(height, lo.hole_diameter as number)\n }\n } else if (\"hole_diameter\" in lo) {\n width = lo.hole_diameter\n height = lo.hole_diameter\n }\n }\n\n if (width === undefined || height === undefined) {\n width = 0.1\n height = 0.1\n }\n\n return {\n x,\n y,\n width,\n height,\n title,\n content,\n bg_color:\n nice_color_palettes[\n stringHash((lo as any).type || title) % nice_color_palettes.length\n ]?.[4] ?? \"#f00\",\n }\n}\n","export const isTruthy = <T>(value: T): value is NonNullable<T> => Boolean(value)\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { getDebugLayoutObject } from \"./utils/get-layout-debug-object\"\nimport { isTruthy } from \"./utils/is-truthy\"\n\nexport const findBoundsAndCenter = (\n elements: AnyCircuitElement[],\n): { center: { x: number; y: number }; width: number; height: number } => {\n const debugObjects = elements\n .filter(\n (elm) => elm.type.startsWith(\"pcb_\") || elm.type.startsWith(\"schematic_\"),\n )\n .concat(\n elements\n .filter(\n (elm) => elm.type === \"pcb_trace\" || elm.type === \"schematic_trace\",\n )\n // @ts-ignore\n .flatMap((elm: any) => elm.route),\n )\n .map((elm) => getDebugLayoutObject(elm))\n .filter(isTruthy)\n\n if (debugObjects.length === 0)\n return { center: { x: 0, y: 0 }, width: 0, height: 0 }\n\n let minX = debugObjects[0]!.x - debugObjects[0]!.width / 2\n let maxX = debugObjects[0]!.x + debugObjects[0]!.width / 2\n let minY = debugObjects[0]!.y - debugObjects[0]!.height / 2\n let maxY = debugObjects[0]!.y + debugObjects[0]!.height / 2\n\n for (const obj of debugObjects.slice(1)) {\n minX = Math.min(minX, obj.x - obj.width / 2)\n maxX = Math.max(maxX, obj.x + obj.width / 2)\n minY = Math.min(minY, obj.y - obj.height / 2)\n maxY = Math.max(maxY, obj.y + obj.height / 2)\n }\n\n const width = maxX - minX\n const height = maxY - minY\n const center = { x: minX + width / 2, y: minY + height / 2 }\n\n return { center, width, height }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\n\nexport const getPrimaryId = (element: AnyCircuitElement): string => {\n // @ts-ignore\n return element[`${element.type}_id`]\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { transformPCBElements } from \"./transform-soup-elements\"\nimport { translate } from \"transformation-matrix\"\n\nexport const repositionPcbComponentTo = (\n circuitJson: AnyCircuitElement[],\n pcb_component_id: string,\n newCenter: { x: number; y: number },\n) => {\n const pcbComponent = circuitJson.find(\n (e) =>\n e.type === \"pcb_component\" &&\n (e as any).pcb_component_id === pcb_component_id,\n )\n if (!pcbComponent) return\n\n const currentCenter =\n \"center\" in pcbComponent\n ? (pcbComponent as any).center\n : { x: (pcbComponent as any).x, y: (pcbComponent as any).y }\n\n const dx = newCenter.x - currentCenter.x\n const dy = newCenter.y - currentCenter.y\n\n const portIds = circuitJson\n .filter(\n (e) =>\n e.type === \"pcb_port\" &&\n (e as any).pcb_component_id === pcb_component_id,\n )\n .map((e) => (e as any).pcb_port_id)\n\n const elementsToMove = circuitJson.filter((elm) => {\n if (elm === pcbComponent) return true\n const anyElm: any = elm\n if (anyElm.pcb_component_id === pcb_component_id) return true\n if (\n Array.isArray(anyElm.pcb_component_ids) &&\n anyElm.pcb_component_ids.includes(pcb_component_id)\n )\n return true\n if (anyElm.pcb_port_id && portIds.includes(anyElm.pcb_port_id)) return true\n if (\n Array.isArray(anyElm.pcb_port_ids) &&\n anyElm.pcb_port_ids.some((id: string) => portIds.includes(id))\n )\n return true\n if (anyElm.start_pcb_port_id && portIds.includes(anyElm.start_pcb_port_id))\n return true\n if (anyElm.end_pcb_port_id && portIds.includes(anyElm.end_pcb_port_id))\n return true\n if (\n Array.isArray(anyElm.route) &&\n anyElm.route.some(\n (pt: any) =>\n (pt.start_pcb_port_id && portIds.includes(pt.start_pcb_port_id)) ||\n (pt.end_pcb_port_id && portIds.includes(pt.end_pcb_port_id)),\n )\n )\n return true\n return false\n })\n\n const matrix = translate(dx, dy)\n transformPCBElements(elementsToMove, matrix)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { buildSubtree } from \"./subtree\"\nimport { findBoundsAndCenter } from \"./find-bounds-and-center\"\nimport { transformPCBElements } from \"./transform-soup-elements\"\nimport { translate } from \"transformation-matrix\"\n\nconst findAllDescendantGroupIds = (\n circuitJson: AnyCircuitElement[],\n parentGroupId: string,\n): string[] => {\n const childGroupIds: string[] = []\n const directChildren = circuitJson\n .filter(\n (elm) =>\n elm.type === \"source_group\" &&\n (elm as any).parent_source_group_id === parentGroupId,\n )\n .map((elm) => (elm as any).source_group_id)\n\n childGroupIds.push(...directChildren)\n\n // Recursively find descendants of child groups\n for (const childId of directChildren) {\n childGroupIds.push(...findAllDescendantGroupIds(circuitJson, childId))\n }\n\n return childGroupIds\n}\n\nexport const repositionPcbGroupTo = (\n circuitJson: AnyCircuitElement[],\n source_group_id: string,\n newCenter: { x: number; y: number },\n) => {\n // Find all descendant group IDs\n const allGroupIds = [\n source_group_id,\n ...findAllDescendantGroupIds(circuitJson, source_group_id),\n ]\n\n // Get all elements for each group (including the main group and its descendants)\n const allGroupElements = new Set<AnyCircuitElement>()\n\n for (const groupId of allGroupIds) {\n const groupElements = buildSubtree(circuitJson, {\n source_group_id: groupId,\n })\n groupElements.forEach((elm) => allGroupElements.add(elm))\n }\n\n // Get all port IDs from elements in the group\n const portIds = Array.from(allGroupElements)\n .filter((e) => e.type === \"pcb_port\")\n .map((e) => (e as any).pcb_port_id)\n\n // Find additional traces that connect to these ports (buildSubtree might miss these)\n const additionalTraces = circuitJson.filter((elm) => {\n if (elm.type !== \"pcb_trace\") return false\n if (allGroupElements.has(elm)) return false // already included\n\n const anyElm: any = elm\n\n // Check direct port connections\n if (anyElm.start_pcb_port_id && portIds.includes(anyElm.start_pcb_port_id))\n return true\n if (anyElm.end_pcb_port_id && portIds.includes(anyElm.end_pcb_port_id))\n return true\n\n // Check route point connections\n if (\n Array.isArray(anyElm.route) &&\n anyElm.route.some(\n (pt: any) =>\n (pt.start_pcb_port_id && portIds.includes(pt.start_pcb_port_id)) ||\n (pt.end_pcb_port_id && portIds.includes(pt.end_pcb_port_id)),\n )\n )\n return true\n\n return false\n })\n\n // Add additional traces to the elements to move\n additionalTraces.forEach((trace) => allGroupElements.add(trace))\n\n // Filter to only PCB elements that can be repositioned\n const pcbElements = Array.from(allGroupElements).filter((elm) =>\n elm.type.startsWith(\"pcb_\"),\n )\n\n if (pcbElements.length === 0) return\n\n // Calculate current bounds and center of the group\n const { center: currentCenter } = findBoundsAndCenter(pcbElements)\n\n // Calculate translation needed\n const dx = newCenter.x - currentCenter.x\n const dy = newCenter.y - currentCenter.y\n\n // Create translation matrix\n const matrix = translate(dx, dy)\n\n // Apply transformation to all PCB elements in the group\n transformPCBElements(pcbElements, matrix)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { transformSchematicElements } from \"./transform-soup-elements\"\nimport { translate } from \"transformation-matrix\"\n\nexport const repositionSchematicComponentTo = (\n circuitJson: AnyCircuitElement[],\n schematic_component_id: string,\n newCenter: { x: number; y: number },\n) => {\n const schematicComponent = circuitJson.find(\n (e) =>\n e.type === \"schematic_component\" &&\n (e as any).schematic_component_id === schematic_component_id,\n )\n if (!schematicComponent) return\n\n const currentCenter =\n \"center\" in schematicComponent\n ? (schematicComponent as any).center\n : { x: (schematicComponent as any).x, y: (schematicComponent as any).y }\n\n const dx = newCenter.x - currentCenter.x\n const dy = newCenter.y - currentCenter.y\n\n const portIds = circuitJson\n .filter(\n (e) =>\n e.type === \"schematic_port\" &&\n (e as any).schematic_component_id === schematic_component_id,\n )\n .map((e) => (e as any).schematic_port_id)\n\n const elementsToMove = circuitJson.filter((elm) => {\n if (elm === schematicComponent) return true\n const anyElm: any = elm\n if (anyElm.schematic_component_id === schematic_component_id) return true\n if (\n Array.isArray(anyElm.schematic_component_ids) &&\n anyElm.schematic_component_ids.includes(schematic_component_id)\n )\n return true\n if (anyElm.schematic_port_id && portIds.includes(anyElm.schematic_port_id))\n return true\n if (\n Array.isArray(anyElm.schematic_port_ids) &&\n anyElm.schematic_port_ids.some((id: string) => portIds.includes(id))\n )\n return true\n if (\n anyElm.start_schematic_port_id &&\n portIds.includes(anyElm.start_schematic_port_id)\n )\n return true\n if (\n anyElm.end_schematic_port_id &&\n portIds.includes(anyElm.end_schematic_port_id)\n )\n return true\n if (\n Array.isArray(anyElm.route) &&\n anyElm.route.some(\n (pt: any) =>\n (pt.start_schematic_port_id &&\n portIds.includes(pt.start_schematic_port_id)) ||\n (pt.end_schematic_port_id &&\n portIds.includes(pt.end_schematic_port_id)),\n )\n )\n return true\n return false\n })\n\n const matrix = translate(dx, dy)\n transformSchematicElements(elementsToMove, matrix)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { buildSubtree } from \"./subtree\"\nimport { findBoundsAndCenter } from \"./find-bounds-and-center\"\nimport { transformSchematicElements } from \"./transform-soup-elements\"\nimport { translate } from \"transformation-matrix\"\n\nconst findAllDescendantGroupIds = (\n circuitJson: AnyCircuitElement[],\n parentGroupId: string,\n): string[] => {\n const childGroupIds: string[] = []\n const directChildren = circuitJson\n .filter(\n (elm) =>\n elm.type === \"source_group\" &&\n (elm as any).parent_source_group_id === parentGroupId,\n )\n .map((elm) => (elm as any).source_group_id)\n\n childGroupIds.push(...directChildren)\n\n for (const childId of directChildren) {\n childGroupIds.push(...findAllDescendantGroupIds(circuitJson, childId))\n }\n\n return childGroupIds\n}\n\nexport const repositionSchematicGroupTo = (\n circuitJson: AnyCircuitElement[],\n source_group_id: string,\n newCenter: { x: number; y: number },\n) => {\n const allGroupIds = [\n source_group_id,\n ...findAllDescendantGroupIds(circuitJson, source_group_id),\n ]\n\n const allGroupElements = new Set<AnyCircuitElement>()\n\n for (const groupId of allGroupIds) {\n const groupElements = buildSubtree(circuitJson, {\n source_group_id: groupId,\n })\n groupElements.forEach((elm) => allGroupElements.add(elm))\n }\n\n const portIds = Array.from(allGroupElements)\n .filter((e) => e.type === \"schematic_port\")\n .map((e) => (e as any).schematic_port_id)\n\n const additionalTraces = circuitJson.filter((elm) => {\n if (elm.type !== \"schematic_trace\") return false\n if (allGroupElements.has(elm)) return false\n\n const anyElm: any = elm\n\n if (\n anyElm.start_schematic_port_id &&\n portIds.includes(anyElm.start_schematic_port_id)\n )\n return true\n if (\n anyElm.end_schematic_port_id &&\n portIds.includes(anyElm.end_schematic_port_id)\n )\n return true\n if (\n Array.isArray(anyElm.route) &&\n anyElm.route.some(\n (pt: any) =>\n (pt.start_schematic_port_id &&\n portIds.includes(pt.start_schematic_port_id)) ||\n (pt.end_schematic_port_id &&\n portIds.includes(pt.end_schematic_port_id)),\n )\n )\n return true\n\n return false\n })\n\n additionalTraces.forEach((trace) => allGroupElements.add(trace))\n\n const schematicElements = Array.from(allGroupElements).filter((elm) =>\n elm.type.startsWith(\"schematic_\"),\n )\n if (schematicElements.length === 0) return\n\n const { center: currentCenter } = findBoundsAndCenter(schematicElements)\n\n const dx = newCenter.x - currentCenter.x\n const dy = newCenter.y - currentCenter.y\n\n const matrix = translate(dx, dy)\n\n transformSchematicElements(schematicElements, matrix)\n}\n","import type {\n AnyCircuitElement,\n SourceComponentBase,\n SourceGroup,\n} from \"circuit-json\"\n\n/**\n * A tree of circuit elements. This is often used for layout because you want\n * to consider only the top-level elements of a group for layout (child groups\n * move together)\n */\nexport interface CircuitJsonTreeNode {\n nodeType: \"group\" | \"component\"\n sourceGroup?: SourceGroup\n sourceComponent?: SourceComponentBase\n childNodes: Array<CircuitJsonTreeNode>\n otherChildElements: Array<AnyCircuitElement>\n}\n\nexport const getCircuitJsonTree = (\n circuitJson: AnyCircuitElement[],\n opts?: {\n source_group_id?: string\n },\n): CircuitJsonTreeNode => {\n type ChildGroupId = string\n type ParentGroupId = string\n type GroupId = string\n const groupChildMap: Map<ParentGroupId, ChildGroupId[]> = new Map()\n\n // Get all source group IDs present in the circuit JSON\n const existingGroupIds = new Set<string>()\n for (const elm of circuitJson) {\n if (elm.type === \"source_group\") {\n existingGroupIds.add(elm.source_group_id)\n }\n }\n\n // Find orphaned groups (groups whose parent is not in the circuit JSON)\n const orphanedGroups: string[] = []\n\n for (const elm of circuitJson) {\n if (elm.type === \"source_group\" && elm.parent_source_group_id) {\n const parentId = elm.parent_source_group_id\n const childId = elm.source_group_id\n\n // If parent doesn't exist in circuit JSON, this is an orphaned group\n if (!existingGroupIds.has(parentId)) {\n orphanedGroups.push(childId)\n // Treat orphaned groups as root-level groups\n if (!groupChildMap.has(childId)) {\n groupChildMap.set(childId, [])\n }\n } else {\n // Normal parent-child relationship\n const children = groupChildMap.get(parentId) ?? []\n children.push(childId)\n groupChildMap.set(parentId, children)\n if (!groupChildMap.has(childId)) {\n groupChildMap.set(childId, [])\n }\n }\n }\n }\n\n // Ensure that every source_group, including root-level groups that have no parent,\n // is present in the groupChildMap. This guarantees that even standalone boards\n // (with no nested groups) are processed and appear at the top of the tree.\n for (const elm of circuitJson) {\n if (\n elm.type === \"source_group\" &&\n !groupChildMap.has(elm.source_group_id)\n ) {\n groupChildMap.set(elm.source_group_id, [])\n }\n }\n\n const groupNodes = new Map<GroupId, CircuitJsonTreeNode>()\n\n const getNextGroupId = () => {\n for (const [parentId, children] of groupChildMap) {\n if (groupNodes.has(parentId)) continue\n if (children.every((childId) => groupNodes.has(childId))) {\n return parentId\n }\n }\n return null\n }\n\n // Compute any node we have the dependencies for until we've computed all of\n // them\n let lastGroupId: GroupId | null = null\n while (true) {\n const nextGroupId = getNextGroupId()\n if (!nextGroupId) break\n\n const sourceGroup = circuitJson.find(\n (elm) =>\n elm.type === \"source_group\" && elm.source_group_id === nextGroupId,\n ) as SourceGroup\n\n // Create the tree node for this group\n const node: CircuitJsonTreeNode = {\n nodeType: \"group\",\n sourceGroup,\n otherChildElements: [],\n childNodes: [\n ...(groupChildMap\n .get(nextGroupId)\n ?.map((childId) => groupNodes.get(childId)!) ?? []),\n ...circuitJson\n .filter(\n (elm) =>\n elm.type === \"source_component\" &&\n elm.source_group_id === nextGroupId,\n )\n .map((elm) => {\n return {\n nodeType: \"component\",\n sourceComponent: elm,\n childNodes: [],\n otherChildElements: [\n ...circuitJson.filter(\n (e) =>\n e.type === \"pcb_component\" &&\n e.source_component_id ===\n (elm as SourceComponentBase).source_component_id,\n ),\n ], // TODO populate\n } as CircuitJsonTreeNode\n }),\n ],\n }\n\n groupNodes.set(nextGroupId, node)\n lastGroupId = nextGroupId\n }\n\n if (!lastGroupId) {\n console.warn(\"No groups were processed, returning tree without sourceGroup\")\n return {\n nodeType: \"group\",\n childNodes: [], // TODO populate\n otherChildElements: circuitJson,\n }\n }\n\n // Determine which group to return as root\n let rootGroupId: string | null = null\n if (opts && opts.source_group_id !== undefined) {\n // Use explicitly specified group\n rootGroupId = opts.source_group_id\n } else if (orphanedGroups.length > 0) {\n // Use the first orphaned group as root (most likely scenario when filtering circuit JSON)\n rootGroupId = orphanedGroups[0]!\n } else {\n // Fall back to the last processed group (typically the top-level parent)\n rootGroupId = lastGroupId as string | null\n }\n\n if (!rootGroupId) {\n console.warn(\n \"No valid root group found, returning tree without sourceGroup\",\n )\n return {\n nodeType: \"group\",\n childNodes: [],\n otherChildElements: circuitJson,\n }\n }\n\n return groupNodes.get(rootGroupId)!\n}\n","import type { CircuitJsonTreeNode } from \"./getCircuitJsonTree\"\n\nexport const getStringFromCircuitJsonTree = (\n circuitJsonTree: CircuitJsonTreeNode,\n indent = 0,\n): string => {\n if (circuitJsonTree.nodeType === \"component\") {\n return `${\" \".repeat(indent)}${circuitJsonTree.sourceComponent?.name ?? circuitJsonTree.sourceComponent?.source_component_id}`\n }\n const lines = []\n\n lines.push(\n `${\" \".repeat(indent)}${circuitJsonTree.sourceGroup?.name ?? circuitJsonTree.sourceGroup?.source_group_id}`,\n )\n for (const child of circuitJsonTree.childNodes) {\n lines.push(getStringFromCircuitJsonTree(child, indent + 2))\n }\n return lines.join(\"\\n\")\n}\n","export type Size = { width: number; height: number }\n\nimport type { FlexBoxOptions } from \"@tscircuit/miniflex\"\n/**\n * Compute the smallest possible dimensions (width & height) for a flex container\n * so that **all** children fit without overflowing _before_ any flex grow / shrink\n * is applied. This is a very lightweight approximation – it only considers the\n * children's explicit `width`/`height` (or `flexBasis`) plus the configured gaps\n * and the main-axis stacking rules derived from the flex direction.\n *\n * This function purposely does **not** try to implement the full flexbox sizing\n * algorithm – we only need a quick estimate so that `RootFlexBox` can be\n * instantiated even when the user did not provide explicit dimensions for the\n * container (e.g. when laying out PCB components directly on the board level\n * instead of inside a sub-circuit).\n */\nexport function getMinimumFlexContainer(\n children: Array<{ width: number; height: number }>,\n options: FlexBoxOptions = {},\n): Size {\n if (children.length === 0) return { width: 0, height: 0 }\n\n const direction = options.direction ?? \"row\"\n const columnGap = options.columnGap ?? 0\n const rowGap = options.rowGap ?? 0\n\n // Flexbox main-axis / cross-axis mapping --------------------------------\n const isRowDirection = direction === \"row\" || direction === \"row-reverse\"\n\n if (isRowDirection) {\n // Main-axis horizontally stacks children\n const totalChildWidth = children.reduce((sum, c) => sum + c.width, 0)\n const width = totalChildWidth + columnGap * Math.max(0, children.length - 1)\n\n const height = children.reduce((max, c) => Math.max(max, c.height), 0)\n return { width, height }\n } else {\n // Column direction – stack vertically\n const totalChildHeight = children.reduce((sum, c) => sum + c.height, 0)\n const height = totalChildHeight + rowGap * Math.max(0, children.length - 1)\n\n const width = children.reduce((max, c) => Math.max(max, c.width), 0)\n return { width, height }\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\n\nexport function getElementRenderLayers(\n element: AnyCircuitElement,\n): PcbRenderLayer[] {\n // Copper elements (pads, traces, copper pour, copper text)\n if (element.type === \"pcb_smtpad\") {\n const layer = element.layer\n return [`${layer}_copper` as PcbRenderLayer]\n }\n\n if (element.type === \"pcb_trace\") {\n // Traces can span multiple layers, return all layers from route\n if (!element.route || !Array.isArray(element.route)) return []\n const layers = new Set<PcbRenderLayer>()\n for (const point of element.route) {\n if (\"layer\" in point && point.layer) {\n layers.add(`${point.layer}_copper` as PcbRenderLayer)\n }\n }\n return Array.from(layers)\n }\n\n if (element.type === \"pcb_copper_pour\") {\n const layer = element.layer\n return [`${layer}_copper` as PcbRenderLayer]\n }\n\n if (element.type === \"pcb_copper_text\") {\n const layer = element.layer\n return [`${layer}_copper` as PcbRenderLayer]\n }\n\n // Silkscreen elements\n if (\n element.type === \"pcb_silkscreen_text\" ||\n element.type === \"pcb_silkscreen_rect\" ||\n element.type === \"pcb_silkscreen_circle\" ||\n element.type === \"pcb_silkscreen_line\" ||\n element.type === \"pcb_silkscreen_path\"\n ) {\n const layer = element.layer\n return [`${layer}_silkscreen` as PcbRenderLayer]\n }\n\n // Fabrication note elements\n if (\n element.type === \"pcb_fabrication_note_text\" ||\n element.type === \"pcb_fabrication_note_rect\" ||\n element.type === \"pcb_fabrication_note_path\"\n ) {\n const layer = element.layer\n return [`${layer}_fabrication_note` as PcbRenderLayer]\n }\n\n // Courtyard elements\n\n if (\n element.type === \"pcb_courtyard_circle\" ||\n element.type === \"pcb_courtyard_polygon\" ||\n element.type === \"pcb_courtyard_rect\" ||\n element.type === \"pcb_courtyard_outline\"\n ) {\n const layer = element.layer\n return [`${layer}_courtyard` as PcbRenderLayer]\n }\n\n // PCB note elements (user annotations)\n if (\n element.type === \"pcb_note_rect\" ||\n element.type === \"pcb_note_path\" ||\n element.type === \"pcb_note_text\" ||\n element.type === \"pcb_note_line\" ||\n element.type === \"pcb_note_dimension\"\n ) {\n const layer = element.layer\n return [`${layer}_user_note` as PcbRenderLayer]\n }\n\n // Elements without layer filtering (always drawn)\n // These include: pcb_board, pcb_hole, pcb_plated_hole, pcb_via, pcb_cutout\n return []\n}\n","import type { Point, Polygon, Rect } from \"./types\"\n\nexport const EPSILON = 1e-9\n\nexport const toRadians = (degrees: number) => (degrees * Math.PI) / 180\n\nexport const clamp = (value: number, min: number, max: number) =>\n Math.max(min, Math.min(max, value))\n\nexport const distanceBetweenPoints = (a: Point, b: Point) =>\n Math.hypot(a.x - b.x, a.y - b.y)\n\nexport const distanceBetweenPointAndSegment = (\n point: Point,\n a: Point,\n b: Point,\n) => {\n const abX = b.x - a.x\n const abY = b.y - a.y\n const lengthSquared = abX * abX + abY * abY\n\n if (lengthSquared <= EPSILON) return distanceBetweenPoints(point, a)\n\n const t = clamp(\n ((point.x - a.x) * abX + (point.y - a.y) * abY) / lengthSquared,\n 0,\n 1,\n )\n\n return Math.hypot(point.x - (a.x + t * abX), point.y - (a.y + t * abY))\n}\n\nexport const cross = (a: Point, b: Point, c: Point) =>\n (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)\n\nexport const isPointOnSegment = (point: Point, a: Point, b: Point) => {\n if (Math.abs(cross(a, b, point)) > EPSILON) return false\n\n return (\n point.x >= Math.min(a.x, b.x) - EPSILON &&\n point.x <= Math.max(a.x, b.x) + EPSILON &&\n point.y >= Math.min(a.y, b.y) - EPSILON &&\n point.y <= Math.max(a.y, b.y) + EPSILON\n )\n}\n\nexport const segmentsIntersect = (\n a1: Point,\n a2: Point,\n b1: Point,\n b2: Point,\n) => {\n const c1 = cross(a1, a2, b1)\n const c2 = cross(a1, a2, b2)\n const c3 = cross(b1, b2, a1)\n const c4 = cross(b1, b2, a2)\n\n if (\n ((c1 > EPSILON && c2 < -EPSILON) || (c1 < -EPSILON && c2 > EPSILON)) &&\n ((c3 > EPSILON && c4 < -EPSILON) || (c3 < -EPSILON && c4 > EPSILON))\n ) {\n return true\n }\n\n return (\n isPointOnSegment(b1, a1, a2) ||\n isPointOnSegment(b2, a1, a2) ||\n isPointOnSegment(a1, b1, b2) ||\n isPointOnSegment(a2, b1, b2)\n )\n}\n\nexport const getPolygonEdges = (polygon: Polygon): Array<[Point, Point]> => {\n const edges: Array<[Point, Point]> = []\n\n if (polygon.points.length < 2) return edges\n\n for (let i = 0; i < polygon.points.length; i += 1) {\n const a = polygon.points[i]\n const b = polygon.points[(i + 1) % polygon.points.length]\n\n if (!a || !b) continue\n\n edges.push([a, b])\n }\n\n return edges\n}\n\nexport const isPointInPolygon = (point: Point, polygon: Polygon) => {\n for (const [a, b] of getPolygonEdges(polygon)) {\n if (isPointOnSegment(point, a, b)) return true\n }\n\n let inside = false\n for (\n let i = 0, j = polygon.points.length - 1;\n i < polygon.points.length;\n j = i++\n ) {\n const pi = polygon.points[i]\n const pj = polygon.points[j]\n\n if (!pi || !pj) continue\n\n const intersects =\n pi.y > point.y !== pj.y > point.y &&\n point.x < ((pj.x - pi.x) * (point.y - pi.y)) / (pj.y - pi.y) + pi.x\n\n if (intersects) inside = !inside\n }\n\n return inside\n}\n\nexport const rotatePoint = (point: Point, angleRadians: number) => ({\n x: point.x * Math.cos(angleRadians) - point.y * Math.sin(angleRadians),\n y: point.x * Math.sin(angleRadians) + point.y * Math.cos(angleRadians),\n})\n\nexport const rectToPolygon = (rect: Rect): Polygon => {\n const halfWidth = rect.width / 2\n const halfHeight = rect.height / 2\n const angle = toRadians(rect.rotationDegrees)\n\n return {\n kind: \"polygon\",\n points: [\n { x: -halfWidth, y: -halfHeight },\n { x: halfWidth, y: -halfHeight },\n { x: halfWidth, y: halfHeight },\n { x: -halfWidth, y: halfHeight },\n ].map((localPoint) => {\n const rotated = rotatePoint(localPoint, angle)\n return { x: rect.centerX + rotated.x, y: rect.centerY + rotated.y }\n }),\n }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { EPSILON } from \"./geometry\"\nimport type { CopperShape, Point, Rect } from \"./types\"\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isFinite(value)\n\nconst createWireSegmentRect = (\n start: Point,\n end: Point,\n width: number,\n): Rect => ({\n kind: \"rect\",\n centerX: (start.x + end.x) / 2,\n centerY: (start.y + end.y) / 2,\n width: Math.hypot(end.x - start.x, end.y - start.y),\n height: width,\n rotationDegrees:\n (Math.atan2(end.y - start.y, end.x - start.x) * 180) / Math.PI,\n})\n\nexport const decomposeCopperIntoShapes = (\n element: AnyCircuitElement,\n): CopperShape[] => {\n const elm: any = element\n const shapes: CopperShape[] = []\n\n if (elm.type === \"pcb_smtpad\") {\n if (elm.shape === \"circle\" && isFiniteNumber(elm.radius)) {\n shapes.push({ kind: \"circle\", x: elm.x, y: elm.y, radius: elm.radius })\n }\n\n if (\n elm.shape === \"rect\" &&\n isFiniteNumber(elm.width) &&\n isFiniteNumber(elm.height)\n ) {\n shapes.push({\n kind: \"rect\",\n centerX: elm.x,\n centerY: elm.y,\n width: elm.width,\n height: elm.height,\n rotationDegrees: isFiniteNumber(elm.ccw_rotation)\n ? elm.ccw_rotation\n : 0,\n })\n }\n\n if (elm.shape === \"polygon\" && Array.isArray(elm.points)) {\n const points = elm.points.filter(\n (point: any): point is Point =>\n isFiniteNumber(point?.x) && isFiniteNumber(point?.y),\n )\n\n if (points.length >= 3) {\n shapes.push({ kind: \"polygon\", points })\n }\n }\n\n return shapes\n }\n\n if (elm.type === \"pcb_trace\" && Array.isArray(elm.route)) {\n for (let i = 0; i < elm.route.length - 1; i += 1) {\n const start = elm.route[i]\n const end = elm.route[i + 1]\n\n if (\n !start ||\n !end ||\n start.route_type !== \"wire\" ||\n end.route_type !== \"wire\" ||\n !isFiniteNumber(start.x) ||\n !isFiniteNumber(start.y) ||\n !isFiniteNumber(end.x) ||\n !isFiniteNumber(end.y)\n ) {\n continue\n }\n\n const width = isFiniteNumber(start.width) ? Math.max(0, start.width) : 0\n const radius = width / 2\n\n shapes.push({ kind: \"circle\", x: start.x, y: start.y, radius })\n shapes.push({ kind: \"circle\", x: end.x, y: end.y, radius })\n\n if (Math.hypot(end.x - start.x, end.y - start.y) > EPSILON) {\n shapes.push(createWireSegmentRect(start, end, width))\n }\n }\n\n return shapes\n }\n\n if (elm.type === \"pcb_via\" && isFiniteNumber(elm.outer_diameter)) {\n shapes.push({\n kind: \"circle\",\n x: elm.x,\n y: elm.y,\n radius: elm.outer_diameter / 2,\n })\n\n return shapes\n }\n\n if (elm.type === \"pcb_plated_hole\") {\n if (isFiniteNumber(elm.outer_diameter)) {\n shapes.push({\n kind: \"circle\",\n x: elm.x,\n y: elm.y,\n radius: elm.outer_diameter / 2,\n })\n }\n\n if (\n isFiniteNumber(elm.rect_pad_width) &&\n isFiniteNumber(elm.rect_pad_height)\n ) {\n shapes.push({\n kind: \"rect\",\n centerX: elm.x,\n centerY: elm.y,\n width: elm.rect_pad_width,\n height: elm.rect_pad_height,\n rotationDegrees: isFiniteNumber(elm.rect_ccw_rotation)\n ? elm.rect_ccw_rotation\n : 0,\n })\n }\n\n if (isFiniteNumber(elm.outer_width) && isFiniteNumber(elm.outer_height)) {\n shapes.push({\n kind: \"rect\",\n centerX: elm.x,\n centerY: elm.y,\n width: elm.outer_width,\n height: elm.outer_height,\n rotationDegrees: 0,\n })\n }\n\n return shapes\n }\n\n return shapes\n}\n","import {\n distanceBetweenPointAndSegment,\n getPolygonEdges,\n isPointInPolygon,\n rectToPolygon,\n segmentsIntersect,\n} from \"./geometry\"\nimport type { Circle, CopperShape, Polygon, Rect } from \"./types\"\n\nexport const distanceBetweenCircleAndCircle = (a: Circle, b: Circle) =>\n Math.max(0, Math.hypot(a.x - b.x, a.y - b.y) - a.radius - b.radius)\n\nexport const distanceBetweenPolygonAndPolygon = (a: Polygon, b: Polygon) => {\n if (a.points.length < 3 || b.points.length < 3) {\n return Number.POSITIVE_INFINITY\n }\n\n for (const [a1, a2] of getPolygonEdges(a)) {\n for (const [b1, b2] of getPolygonEdges(b)) {\n if (segmentsIntersect(a1, a2, b1, b2)) {\n return 0\n }\n }\n }\n\n const aPoint = a.points[0]\n const bPoint = b.points[0]\n if (\n (aPoint && isPointInPolygon(aPoint, b)) ||\n (bPoint && isPointInPolygon(bPoint, a))\n ) {\n return 0\n }\n\n let minDistance = Number.POSITIVE_INFINITY\n\n for (const [a1, a2] of getPolygonEdges(a)) {\n for (const [b1, b2] of getPolygonEdges(b)) {\n minDistance = Math.min(\n minDistance,\n distanceBetweenPointAndSegment(a1, b1, b2),\n distanceBetweenPointAndSegment(a2, b1, b2),\n distanceBetweenPointAndSegment(b1, a1, a2),\n distanceBetweenPointAndSegment(b2, a1, a2),\n )\n }\n }\n\n return minDistance\n}\n\nexport const distanceBetweenCircleAndPolygon = (\n circle: Circle,\n polygon: Polygon,\n) => {\n if (polygon.points.length < 3) {\n return Number.POSITIVE_INFINITY\n }\n\n if (isPointInPolygon({ x: circle.x, y: circle.y }, polygon)) {\n return 0\n }\n\n let minDistanceToEdge = Number.POSITIVE_INFINITY\n\n for (const [start, end] of getPolygonEdges(polygon)) {\n minDistanceToEdge = Math.min(\n minDistanceToEdge,\n distanceBetweenPointAndSegment({ x: circle.x, y: circle.y }, start, end),\n )\n }\n\n return Math.max(0, minDistanceToEdge - circle.radius)\n}\n\nexport const distanceBetweenShapes = (\n a: CopperShape,\n b: CopperShape,\n): number => {\n if (a.kind === \"circle\" && b.kind === \"circle\") {\n return distanceBetweenCircleAndCircle(a, b)\n }\n\n if (a.kind === \"rect\" && b.kind === \"rect\") {\n return distanceBetweenPolygonAndPolygon(rectToPolygon(a), rectToPolygon(b))\n }\n\n if (a.kind === \"circle\" && b.kind === \"rect\") {\n return distanceBetweenCircleAndPolygon(a, rectToPolygon(b))\n }\n\n if (a.kind === \"rect\" && b.kind === \"circle\") {\n return distanceBetweenCircleAndPolygon(b, rectToPolygon(a))\n }\n\n if (a.kind === \"circle\" && b.kind === \"polygon\") {\n return distanceBetweenCircleAndPolygon(a, b)\n }\n\n if (a.kind === \"polygon\" && b.kind === \"circle\") {\n return distanceBetweenCircleAndPolygon(b, a)\n }\n\n if (a.kind === \"rect\" && b.kind === \"polygon\") {\n return distanceBetweenPolygonAndPolygon(rectToPolygon(a), b)\n }\n\n if (a.kind === \"polygon\" && b.kind === \"rect\") {\n return distanceBetweenPolygonAndPolygon(a, rectToPolygon(b))\n }\n\n if (a.kind === \"polygon\" && b.kind === \"polygon\") {\n return distanceBetweenPolygonAndPolygon(a, b)\n }\n\n return Number.POSITIVE_INFINITY\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { decomposeCopperIntoShapes } from \"./shape-distances/decompose-copper-into-shapes\"\nimport { distanceBetweenShapes } from \"./shape-distances/distance-between-shapes\"\n\nexport const computeGapBetweenCopper = (\n elm1: AnyCircuitElement,\n elm2: AnyCircuitElement,\n): number => {\n const shapes1 = decomposeCopperIntoShapes(elm1)\n const shapes2 = decomposeCopperIntoShapes(elm2)\n\n if (shapes1.length === 0 || shapes2.length === 0) {\n return Number.POSITIVE_INFINITY\n }\n\n let minimumGap = Number.POSITIVE_INFINITY\n\n for (const shape1 of shapes1) {\n for (const shape2 of shapes2) {\n minimumGap = Math.min(minimumGap, distanceBetweenShapes(shape1, shape2))\n }\n }\n\n return minimumGap\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { decomposeCopperIntoShapes } from \"./decompose-copper-into-shapes\"\nimport type { CopperShape, Point } from \"./types\"\n\nconst isFiniteNumber = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isFinite(value)\n\nconst getCenter = (elm: any): { x: number; y: number } | null => {\n if (isFiniteNumber(elm?.x) && isFiniteNumber(elm?.y)) {\n return { x: elm.x, y: elm.y }\n }\n\n if (isFiniteNumber(elm?.center?.x) && isFiniteNumber(elm?.center?.y)) {\n return { x: elm.center.x, y: elm.center.y }\n }\n\n return null\n}\n\nconst addCenterBasedShapes = (elm: any, shapes: CopperShape[]) => {\n const center = getCenter(elm)\n if (!center) return\n\n if (elm.shape === \"circle\") {\n if (isFiniteNumber(elm.radius)) {\n shapes.push({\n kind: \"circle\",\n x: center.x,\n y: center.y,\n radius: elm.radius,\n })\n return\n }\n\n if (isFiniteNumber(elm.diameter)) {\n shapes.push({\n kind: \"circle\",\n x: center.x,\n y: center.y,\n radius: elm.diameter / 2,\n })\n return\n }\n }\n\n if (\n elm.shape === \"rect\" &&\n isFiniteNumber(elm.width) &&\n isFiniteNumber(elm.height)\n ) {\n shapes.push({\n kind: \"rect\",\n centerX: center.x,\n centerY: center.y,\n width: elm.width,\n height: elm.height,\n rotationDegrees: isFiniteNumber(elm.ccw_rotation) ? elm.ccw_rotation : 0,\n })\n return\n }\n\n if (elm.shape === \"polygon\" && Array.isArray(elm.points)) {\n const points = elm.points.filter(\n (point: any): point is Point =>\n isFiniteNumber(point?.x) && isFiniteNumber(point?.y),\n )\n\n if (points.length >= 3) {\n shapes.push({ kind: \"polygon\", points })\n }\n }\n}\n\nexport const decomposeClearanceIntoShapes = (\n element: AnyCircuitElement,\n): CopperShape[] => {\n const elm: any = element\n const shapes: CopperShape[] = [...decomposeCopperIntoShapes(element)]\n\n if (elm.type === \"pcb_hole\" && elm.hole_shape === \"circle\") {\n if (\n isFiniteNumber(elm.hole_diameter) &&\n isFiniteNumber(elm.x) &&\n isFiniteNumber(elm.y)\n ) {\n shapes.push({\n kind: \"circle\",\n x: elm.x,\n y: elm.y,\n radius: elm.hole_diameter / 2,\n })\n }\n return shapes\n }\n\n if (elm.type === \"pcb_plated_hole\") {\n if (\n isFiniteNumber(elm.hole_diameter) &&\n isFiniteNumber(elm.x) &&\n isFiniteNumber(elm.y)\n ) {\n const holeOffsetX = isFiniteNumber(elm.hole_offset_x)\n ? elm.hole_offset_x\n : 0\n const holeOffsetY = isFiniteNumber(elm.hole_offset_y)\n ? elm.hole_offset_y\n : 0\n shapes.push({\n kind: \"circle\",\n x: elm.x + holeOffsetX,\n y: elm.y + holeOffsetY,\n radius: elm.hole_diameter / 2,\n })\n }\n return shapes\n }\n\n if (\n elm.type === \"pcb_keepout\" ||\n elm.type === \"pcb_cutout\" ||\n elm.type === \"pcb_board\"\n ) {\n addCenterBasedShapes(elm, shapes)\n return shapes\n }\n\n return shapes\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { decomposeClearanceIntoShapes } from \"./shape-distances/decompose-clearance-into-shapes\"\nimport { distanceBetweenShapes } from \"./shape-distances/distance-between-shapes\"\n\nexport const computeClearanceBetweenElements = (\n elm1: AnyCircuitElement,\n elm2: AnyCircuitElement,\n): number => {\n const shapes1 = decomposeClearanceIntoShapes(elm1)\n const shapes2 = decomposeClearanceIntoShapes(elm2)\n\n if (shapes1.length === 0 || shapes2.length === 0) {\n return Number.POSITIVE_INFINITY\n }\n\n let minimumGap = Number.POSITIVE_INFINITY\n\n for (const shape1 of shapes1) {\n for (const shape2 of shapes2) {\n minimumGap = Math.min(minimumGap, distanceBetweenShapes(shape1, shape2))\n }\n }\n\n return minimumGap\n}\n","import type { PcbPin1Location } from \"circuit-json\"\n\ntype Point = { x: number; y: number }\n\nexport interface PcbPin1LocationElement {\n type: string\n x?: number\n y?: number\n points?: readonly Point[]\n port_hints?: readonly unknown[]\n}\n\ntype Pin1Side = \"leftside\" | \"rightside\" | \"topside\" | \"bottomside\"\ntype Pin1Alignment = \"left\" | \"right\" | \"top\" | \"bottom\"\n\nconst PIN1_LOCATION_PARTS = {\n leftside_top: { side: \"leftside\", alignment: \"top\" },\n leftside_bottom: { side: \"leftside\", alignment: \"bottom\" },\n rightside_top: { side: \"rightside\", alignment: \"top\" },\n rightside_bottom: { side: \"rightside\", alignment: \"bottom\" },\n topside_left: { side: \"topside\", alignment: \"left\" },\n topside_right: { side: \"topside\", alignment: \"right\" },\n bottomside_left: { side: \"bottomside\", alignment: \"left\" },\n bottomside_right: { side: \"bottomside\", alignment: \"right\" },\n} as const satisfies Record<\n PcbPin1Location,\n { side: Pin1Side; alignment: Pin1Alignment }\n>\n\nconst PIN1_LOCATIONS = Object.keys(PIN1_LOCATION_PARTS) as PcbPin1Location[]\n\nconst getPadCenter = (pad: PcbPin1LocationElement): Point | null => {\n if (typeof pad.x === \"number\" && typeof pad.y === \"number\") {\n return { x: pad.x, y: pad.y }\n }\n\n if (pad.points && pad.points.length > 0) {\n const xs = pad.points.map((point) => point.x)\n const ys = pad.points.map((point) => point.y)\n return {\n x: (Math.min(...xs) + Math.max(...xs)) / 2,\n y: (Math.min(...ys) + Math.max(...ys)) / 2,\n }\n }\n\n return null\n}\n\nconst getPinNumber = (pad: PcbPin1LocationElement): number | null => {\n for (const hint of pad.port_hints ?? []) {\n const match = String(hint)\n .trim()\n .match(/^(?:pin)?(\\d+)$/i)\n if (match) return Number.parseInt(match[1]!, 10)\n }\n return null\n}\n\nconst pinMatchesLocation = (\n padCenters: Point[],\n pin1Center: Point,\n pin1Location: PcbPin1Location,\n) => {\n const xs = padCenters.map((point) => point.x)\n const ys = padCenters.map((point) => point.y)\n const minX = Math.min(...xs)\n const maxX = Math.max(...xs)\n const minY = Math.min(...ys)\n const maxY = Math.max(...ys)\n const centerX = (minX + maxX) / 2\n const centerY = (minY + maxY) / 2\n const spanX = maxX - minX\n const spanY = maxY - minY\n const tolerance = Math.max(spanX, spanY, 1) * 1e-6\n const { side, alignment } = PIN1_LOCATION_PARTS[pin1Location]\n\n const onRequestedSide =\n (side === \"leftside\" && Math.abs(pin1Center.x - minX) <= tolerance) ||\n (side === \"rightside\" && Math.abs(pin1Center.x - maxX) <= tolerance) ||\n (side === \"topside\" && Math.abs(pin1Center.y - maxY) <= tolerance) ||\n (side === \"bottomside\" && Math.abs(pin1Center.y - minY) <= tolerance)\n\n const atRequestedAlignment =\n (alignment === \"left\" &&\n (spanX <= tolerance || pin1Center.x < centerX - tolerance)) ||\n (alignment === \"right\" &&\n (spanX <= tolerance || pin1Center.x > centerX + tolerance)) ||\n (alignment === \"top\" &&\n (spanY <= tolerance || pin1Center.y > centerY + tolerance)) ||\n (alignment === \"bottom\" &&\n (spanY <= tolerance || pin1Center.y < centerY - tolerance))\n\n return onRequestedSide && atRequestedAlignment\n}\n\n/**\n * Infers the semantic pin 1 location from PCB pad positions and numeric port\n * hints. Returns null when pin 1 is missing or the geometry cannot distinguish\n * a rotation from a reflection.\n */\nexport const analyzePcbPin1Location = (\n elements: readonly PcbPin1LocationElement[],\n): PcbPin1Location | null => {\n const pads = elements.filter(\n (element) =>\n element.type === \"pcb_smtpad\" || element.type === \"pcb_plated_hole\",\n )\n const numberedPads = pads.map((pad) => ({\n center: getPadCenter(pad),\n pinNumber: getPinNumber(pad),\n }))\n const pin1Center = numberedPads.find((pad) => pad.pinNumber === 1)?.center\n const padCenters = numberedPads\n .map((pad) => pad.center)\n .filter((point) => point !== null)\n if (!pin1Center || padCenters.length === 0) return null\n\n const candidates = PIN1_LOCATIONS.filter((pin1Location) =>\n pinMatchesLocation(padCenters, pin1Center, pin1Location),\n )\n if (candidates.length === 1) return candidates[0]!\n if (candidates.length === 0) return null\n\n let nextNumberedPad: { center: Point; pinNumber: number } | undefined\n for (const pad of numberedPads) {\n if (!pad.center || pad.pinNumber === null || pad.pinNumber <= 1) continue\n if (!nextNumberedPad || pad.pinNumber < nextNumberedPad.pinNumber) {\n nextNumberedPad = { center: pad.center, pinNumber: pad.pinNumber }\n }\n }\n if (!nextNumberedPad) return null\n\n const xs = padCenters.map((point) => point.x)\n const ys = padCenters.map((point) => point.y)\n const span = Math.max(\n Math.max(...xs) - Math.min(...xs),\n Math.max(...ys) - Math.min(...ys),\n 1,\n )\n const tolerance = span * 1e-6\n const topologyCandidates = candidates.filter((pin1Location) => {\n const { side } = PIN1_LOCATION_PARTS[pin1Location]\n return side === \"leftside\" || side === \"rightside\"\n ? Math.abs(nextNumberedPad.center.x - pin1Center.x) <= tolerance\n : Math.abs(nextNumberedPad.center.y - pin1Center.y) <= tolerance\n })\n\n return topologyCandidates.length === 1 ? topologyCandidates[0]! : null\n}\n","export type DrcCategory =\n | \"netlist\"\n | \"pin_specification\"\n | \"placement\"\n | \"routing\"\n | \"source\"\n | \"unknown\"\n\ntype DrcLike = {\n type?: string\n error_type?: string\n warning_type?: string\n}\n\nconst NETLIST_TYPES = new Set([\"source_pin_must_be_connected_error\"])\n\nconst PIN_SPECIFICATION_TYPES = new Set([\n \"source_component_pins_underspecified_warning\",\n \"source_no_power_pin_defined_warning\",\n \"source_no_ground_pin_defined_warning\",\n])\n\nconst PLACEMENT_TYPES = new Set([\n \"pcb_placement_error\",\n \"pcb_component_outside_board_error\",\n \"pcb_courtyard_overlap_error\",\n \"pcb_footprint_overlap_error\",\n \"pcb_connector_not_in_accessible_orientation_warning\",\n])\n\nconst ROUTING_TYPES = new Set([\n \"pcb_port_not_connected_error\",\n \"pcb_trace_missing_error\",\n \"pcb_trace_error\",\n \"pcb_via_clearance_error\",\n])\n\nconst SOURCE_TYPES = new Set([\"source_property_ignored_warning\"])\n\nexport const categorizeErrorOrWarning = (\n value: string | DrcLike,\n): DrcCategory => {\n const drcType =\n typeof value === \"string\"\n ? value\n : (value.error_type ?? value.warning_type ?? value.type)\n\n if (!drcType) return \"unknown\"\n\n if (NETLIST_TYPES.has(drcType)) return \"netlist\"\n if (PIN_SPECIFICATION_TYPES.has(drcType)) return \"pin_specification\"\n if (PLACEMENT_TYPES.has(drcType)) return \"placement\"\n if (ROUTING_TYPES.has(drcType)) return \"routing\"\n if (SOURCE_TYPES.has(drcType)) return \"source\"\n\n return \"unknown\"\n}\n","import { useMemo } from \"react\"\nimport { createContext, useContext } from \"react\"\nimport { createStore, type StateProps } from \"../global-store\"\n\nexport const StoreContext = createContext(null)\n\nexport const ContextProviders = ({\n children,\n initialState,\n disablePcbGroups,\n}: {\n children?: any\n initialState?: Partial<StateProps>\n disablePcbGroups?: boolean\n}) => {\n const store = useMemo(\n () => createStore(initialState, disablePcbGroups),\n [disablePcbGroups],\n )\n\n return (\n <StoreContext.Provider value={store as any}>\n {children}\n </StoreContext.Provider>\n )\n}\n","import {\n createStore as createZustandStore,\n useStore as useZustandStore,\n} from \"zustand\"\nimport { StoreContext } from \"./components/ContextProviders\"\nimport type { LayerRef } from \"circuit-json\"\nimport { useContext } from \"react\"\nimport {\n getStoredBoolean,\n getStoredString,\n setStoredBoolean,\n setStoredString,\n STORAGE_KEYS,\n} from \"./hooks/useLocalStorage\"\n\nexport interface State {\n selected_layer: LayerRef\n\n pcb_viewer_id: string\n\n in_edit_mode: boolean\n in_move_footprint_mode: boolean\n is_mouse_over_container: boolean\n is_moving_component: boolean\n is_showing_autorouting: boolean\n is_showing_drc_errors: boolean\n is_showing_drc_warnings: boolean\n\n is_showing_multiple_traces_length: boolean\n is_showing_rats_nest: boolean\n is_showing_copper_pours: boolean\n is_showing_courtyards: boolean\n is_showing_pcb_groups: boolean\n is_showing_group_anchor_offsets: boolean\n is_showing_solder_mask: boolean\n is_showing_silkscreen: boolean\n is_showing_fabrication_notes: boolean\n is_showing_pcb_notes: boolean\n pcb_group_view_mode: \"all\" | \"named_only\"\n\n hovered_error_id: string | null\n focused_error_id: string | null\n\n selectLayer: (layer: LayerRef) => void\n setEditMode: (mode: \"off\" | \"move_footprint\") => void\n setIsMovingComponent: (is_moving: boolean) => void\n setIsShowingRatsNest: (is_showing: boolean) => void\n setIsMouseOverContainer: (is_focused: boolean) => void\n setIsShowingAutorouting: (is_showing: boolean) => void\n setIsShowingMultipleTracesLength: (is_showing: boolean) => void\n setIsShowingDrcErrors: (is_showing: boolean) => void\n setIsShowingDrcWarnings: (is_showing: boolean) => void\n setIsShowingCopperPours: (is_showing: boolean) => void\n setIsShowingCourtyards: (is_showing: boolean) => void\n setIsShowingPcbGroups: (is_showing: boolean) => void\n setIsShowingGroupAnchorOffsets: (is_showing: boolean) => void\n setIsShowingSolderMask: (is_showing: boolean) => void\n setIsShowingSilkscreen: (is_showing: boolean) => void\n setIsShowingFabricationNotes: (is_showing: boolean) => void\n setIsShowingPcbNotes: (is_showing: boolean) => void\n setPcbGroupViewMode: (mode: \"all\" | \"named_only\") => void\n setHoveredErrorId: (errorId: string | null) => void\n setFocusedErrorId: (errorId: string | null) => void\n}\n\nexport type StateProps = {\n [key in keyof State]: State[key] extends boolean ? boolean : never\n}\n\nconst DEFAULT_PCB_GROUP_VIEW_MODE: \"all\" | \"named_only\" =\n process.env.NODE_ENV !== \"production\" ? \"named_only\" : \"all\"\n\nexport const createStore = (\n initialState: Partial<StateProps> = {},\n disablePcbGroups = false,\n) =>\n createZustandStore<State>(\n (set) =>\n ({\n selected_layer: \"top\",\n\n pcb_viewer_id: `pcb_viewer_${Math.random().toString().slice(2, 10)}`,\n\n in_edit_mode: false,\n in_move_footprint_mode: false,\n\n is_moving_component: false,\n is_mouse_over_container: false,\n\n is_showing_multiple_traces_length: false,\n is_showing_rats_nest: false,\n is_showing_autorouting: true,\n is_showing_drc_errors: true,\n is_showing_drc_warnings: true,\n is_showing_copper_pours: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_COPPER_POURS,\n true,\n ),\n is_showing_courtyards: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_COURTYARDS,\n true,\n ),\n is_showing_pcb_groups: disablePcbGroups\n ? false\n : getStoredBoolean(STORAGE_KEYS.IS_SHOWING_PCB_GROUPS, true),\n is_showing_group_anchor_offsets: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_GROUP_ANCHOR_OFFSETS,\n false,\n ),\n is_showing_solder_mask: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_SOLDER_MASK,\n false,\n ),\n is_showing_silkscreen: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_SILKSCREEN,\n true,\n ),\n is_showing_fabrication_notes: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_FABRICATION_NOTES,\n false,\n ),\n is_showing_pcb_notes: getStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_PCB_NOTES,\n true,\n ),\n pcb_group_view_mode: disablePcbGroups\n ? \"all\"\n : (getStoredString(\n STORAGE_KEYS.PCB_GROUP_VIEW_MODE,\n DEFAULT_PCB_GROUP_VIEW_MODE,\n ) as \"all\" | \"named_only\"),\n\n hovered_error_id: null,\n focused_error_id: null,\n ...initialState,\n\n selectLayer: (layer) => set({ selected_layer: layer }),\n setEditMode: (mode) =>\n set({\n in_edit_mode: mode !== \"off\",\n in_move_footprint_mode: mode === \"move_footprint\",\n is_moving_component: false,\n }),\n setIsShowingRatsNest: (is_showing) =>\n set({ is_showing_rats_nest: is_showing }),\n setIsMovingComponent: (is_moving) =>\n set({ is_moving_component: is_moving }),\n setIsMouseOverContainer: (is_focused) =>\n set({ is_mouse_over_container: is_focused }),\n setIsShowingMultipleTracesLength: (is_showing) =>\n set({ is_showing_multiple_traces_length: is_showing }),\n setIsShowingAutorouting: (is_showing) =>\n set({ is_showing_autorouting: is_showing }),\n setIsShowingDrcErrors: (is_showing) =>\n set({ is_showing_drc_errors: is_showing }),\n setIsShowingDrcWarnings: (is_showing) =>\n set({ is_showing_drc_warnings: is_showing }),\n setIsShowingCopperPours: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_COPPER_POURS, is_showing)\n set({ is_showing_copper_pours: is_showing })\n },\n setIsShowingCourtyards: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_COURTYARDS, is_showing)\n set({ is_showing_courtyards: is_showing })\n },\n setIsShowingPcbGroups: (is_showing) => {\n if (disablePcbGroups) return\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_PCB_GROUPS, is_showing)\n set({ is_showing_pcb_groups: is_showing })\n },\n setIsShowingGroupAnchorOffsets: (is_showing) => {\n setStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_GROUP_ANCHOR_OFFSETS,\n is_showing,\n )\n set({ is_showing_group_anchor_offsets: is_showing })\n },\n setIsShowingSolderMask: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_SOLDER_MASK, is_showing)\n set({ is_showing_solder_mask: is_showing })\n },\n setIsShowingSilkscreen: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_SILKSCREEN, is_showing)\n set({ is_showing_silkscreen: is_showing })\n },\n setIsShowingFabricationNotes: (is_showing) => {\n setStoredBoolean(\n STORAGE_KEYS.IS_SHOWING_FABRICATION_NOTES,\n is_showing,\n )\n set({ is_showing_fabrication_notes: is_showing })\n },\n setIsShowingPcbNotes: (is_showing) => {\n setStoredBoolean(STORAGE_KEYS.IS_SHOWING_PCB_NOTES, is_showing)\n set({ is_showing_pcb_notes: is_showing })\n },\n setPcbGroupViewMode: (mode) => {\n if (disablePcbGroups) return\n setStoredString(STORAGE_KEYS.PCB_GROUP_VIEW_MODE, mode)\n set({ pcb_group_view_mode: mode })\n },\n setHoveredErrorId: (errorId) => set({ hovered_error_id: errorId }),\n setFocusedErrorId: (errorId) => set({ focused_error_id: errorId }),\n }) as const,\n )\n\nexport const useGlobalStore = <T = State>(s?: (state: State) => T): T => {\n const store = useContext(StoreContext)\n\n return useZustandStore(store as any, s as any)\n}\n","import { useCallback } from \"react\"\n\nexport const STORAGE_KEYS = {\n IS_SHOWING_PCB_GROUPS: \"pcb_viewer_is_showing_pcb_groups\",\n PCB_GROUP_VIEW_MODE: \"pcb_viewer_group_view_mode\",\n IS_SHOWING_COPPER_POURS: \"pcb_viewer_is_showing_copper_pours\",\n IS_SHOWING_COURTYARDS: \"pcb_viewer_is_showing_courtyards\",\n IS_SHOWING_GROUP_ANCHOR_OFFSETS: \"pcb_viewer_is_showing_group_anchor_offsets\",\n IS_SHOWING_SOLDER_MASK: \"pcb_viewer_is_showing_solder_mask\",\n IS_SHOWING_FABRICATION_NOTES: \"pcb_viewer_is_showing_fabrication_notes\",\n IS_SHOWING_PCB_NOTES: \"pcb_viewer_is_showing_pcb_notes\",\n IS_SHOWING_SILKSCREEN: \"pcb_viewer_is_showing_silkscreen\",\n} as const\n\nexport const getStoredBoolean = (\n key: string,\n defaultValue: boolean,\n): boolean => {\n if (typeof window === \"undefined\") return defaultValue\n try {\n const stored = localStorage.getItem(key)\n return stored !== null ? JSON.parse(stored) : defaultValue\n } catch {\n return defaultValue\n }\n}\n\nexport const setStoredBoolean = (key: string, value: boolean): void => {\n if (typeof window === \"undefined\") return\n try {\n localStorage.setItem(key, JSON.stringify(value))\n } catch {}\n}\n\nexport const getStoredString = (key: string, defaultValue: string): string => {\n if (typeof window === \"undefined\") return defaultValue\n try {\n const stored = localStorage.getItem(key)\n return stored !== null ? JSON.parse(stored) : defaultValue\n } catch {\n return defaultValue\n }\n}\n\nexport const setStoredString = (key: string, value: string): void => {\n if (typeof window === \"undefined\") return\n try {\n localStorage.setItem(key, JSON.stringify(value))\n } catch {}\n}\n\nexport const useLocalStorage = () => {\n const getBoolean = useCallback(\n (key: string, defaultValue: boolean): boolean => {\n return getStoredBoolean(key, defaultValue)\n },\n [],\n )\n\n const setBoolean = useCallback((key: string, value: boolean): void => {\n setStoredBoolean(key, value)\n }, [])\n\n return {\n getBoolean,\n setBoolean,\n }\n}\n\nexport const useLocalStorageValue = (key: string, defaultValue: boolean) => {\n const { getBoolean, setBoolean } = useLocalStorage()\n\n const getValue = useCallback(() => {\n return getBoolean(key, defaultValue)\n }, [getBoolean, key, defaultValue])\n\n const setValue = useCallback(\n (value: boolean) => {\n setBoolean(key, value)\n },\n [setBoolean, key],\n )\n\n return {\n getValue,\n setValue,\n }\n}\n","import { useGlobalStore } from \"../global-store\"\nimport { useEffect } from \"react\"\nimport {\n toast as ogToast,\n ToastContainer as OgToastContainer,\n} from \"react-toastify\"\nimport { injectStyle } from \"react-toastify/dist/inject-style\"\n\nexport const useToast = () => {\n const pcb_viewer_id = useGlobalStore((s) => s.pcb_viewer_id)\n const toast = (message: string, opts?: Parameters<typeof ogToast>[1]) =>\n ogToast(message, {\n containerId: pcb_viewer_id,\n ...opts,\n })\n\n toast.error = (message: string, opts?: Parameters<typeof ogToast.error>[1]) =>\n ogToast.error(message, {\n containerId: pcb_viewer_id,\n ...opts,\n })\n\n // TODO add container id to this\n toast.promise = ogToast.promise\n\n return toast as typeof ogToast\n}\n\nexport const ToastContainer = () => {\n useEffect(() => {\n injectStyle()\n }, [])\n const pcb_viewer_id = useGlobalStore((s) => s.pcb_viewer_id)\n return <OgToastContainer position=\"top-center\" containerId={pcb_viewer_id} />\n}\n","import { useCallback, useEffect, useRef } from 'react';\nexport default function useMountedState() {\n var mountedRef = useRef(false);\n var get = useCallback(function () { return mountedRef.current; }, []);\n useEffect(function () {\n mountedRef.current = true;\n return function () {\n mountedRef.current = false;\n };\n }, []);\n return get;\n}\n","import { useCallback, useState } from 'react';\nvar useSetState = function (initialState) {\n if (initialState === void 0) { initialState = {}; }\n var _a = useState(initialState), state = _a[0], set = _a[1];\n var setState = useCallback(function (patch) {\n set(function (prevState) {\n return Object.assign({}, prevState, patch instanceof Function ? patch(prevState) : patch);\n });\n }, []);\n return [state, setState];\n};\nexport default useSetState;\n","export var noop = function () { };\nexport function on(obj) {\n var args = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n args[_i - 1] = arguments[_i];\n }\n if (obj && obj.addEventListener) {\n obj.addEventListener.apply(obj, args);\n }\n}\nexport function off(obj) {\n var args = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n args[_i - 1] = arguments[_i];\n }\n if (obj && obj.removeEventListener) {\n obj.removeEventListener.apply(obj, args);\n }\n}\nexport var isBrowser = typeof window !== 'undefined';\nexport var isNavigator = typeof navigator !== 'undefined';\n","import writeText from 'copy-to-clipboard';\nimport { useCallback } from 'react';\nimport useMountedState from './useMountedState';\nimport useSetState from './useSetState';\nvar useCopyToClipboard = function () {\n var isMounted = useMountedState();\n var _a = useSetState({\n value: undefined,\n error: undefined,\n noUserInteraction: true,\n }), state = _a[0], setState = _a[1];\n var copyToClipboard = useCallback(function (value) {\n if (!isMounted()) {\n return;\n }\n var noUserInteraction;\n var normalizedValue;\n try {\n // only strings and numbers casted to strings can be copied to clipboard\n if (typeof value !== 'string' && typeof value !== 'number') {\n var error = new Error(\"Cannot copy typeof \" + typeof value + \" to clipboard, must be a string\");\n if (process.env.NODE_ENV === 'development')\n console.error(error);\n setState({\n value: value,\n error: error,\n noUserInteraction: true,\n });\n return;\n }\n // empty strings are also considered invalid\n else if (value === '') {\n var error = new Error(\"Cannot copy empty string to clipboard.\");\n if (process.env.NODE_ENV === 'development')\n console.error(error);\n setState({\n value: value,\n error: error,\n noUserInteraction: true,\n });\n return;\n }\n normalizedValue = value.toString();\n noUserInteraction = writeText(normalizedValue);\n setState({\n value: normalizedValue,\n error: undefined,\n noUserInteraction: noUserInteraction,\n });\n }\n catch (error) {\n setState({\n value: normalizedValue,\n error: error,\n noUserInteraction: noUserInteraction,\n });\n }\n }, []);\n return [state, copyToClipboard];\n};\nexport default useCopyToClipboard;\n","import { useEffect, useLayoutEffect } from 'react';\nimport { isBrowser } from './misc/util';\nvar useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;\nexport default useIsomorphicLayoutEffect;\n","import { useMemo, useState } from 'react';\nimport useIsomorphicLayoutEffect from './useIsomorphicLayoutEffect';\nimport { isBrowser, noop } from './misc/util';\nvar defaultState = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n top: 0,\n left: 0,\n bottom: 0,\n right: 0,\n};\nfunction useMeasure() {\n var _a = useState(null), element = _a[0], ref = _a[1];\n var _b = useState(defaultState), rect = _b[0], setRect = _b[1];\n var observer = useMemo(function () {\n return new window.ResizeObserver(function (entries) {\n if (entries[0]) {\n var _a = entries[0].contentRect, x = _a.x, y = _a.y, width = _a.width, height = _a.height, top_1 = _a.top, left = _a.left, bottom = _a.bottom, right = _a.right;\n setRect({ x: x, y: y, width: width, height: height, top: top_1, left: left, bottom: bottom, right: right });\n }\n });\n }, []);\n useIsomorphicLayoutEffect(function () {\n if (!element)\n return;\n observer.observe(element);\n return function () {\n observer.disconnect();\n };\n }, [element]);\n return [ref, rect];\n}\nexport default isBrowser && typeof window.ResizeObserver !== 'undefined'\n ? useMeasure\n : (function () { return [noop, defaultState]; });\n","import { Matrix, compose, translate, scale } from \"transformation-matrix\"\n\ntype Point = { x: number; y: number }\n\ninterface PinchInput {\n initialTransform: Matrix\n initialTouch1: Point\n initialTouch2: Point\n finalTouch1: Point | null\n finalTouch2: Point | null\n}\n\nexport const computePinchTransform = ({\n initialTransform,\n initialTouch1,\n initialTouch2,\n finalTouch1,\n finalTouch2,\n}: PinchInput): Matrix => {\n if (!finalTouch1 || !finalTouch2) {\n return initialTransform\n }\n // Calculate initial and current centers\n const initialCenter = {\n x: (initialTouch1.x + initialTouch2.x) / 2,\n y: (initialTouch1.y + initialTouch2.y) / 2,\n }\n const currentCenter = {\n x: (finalTouch1.x + finalTouch2.x) / 2,\n y: (finalTouch1.y + finalTouch2.y) / 2,\n }\n\n // Calculate initial and current distances between touch points\n const initialDist = Math.hypot(\n initialTouch2.x - initialTouch1.x,\n initialTouch2.y - initialTouch1.y,\n )\n const currentDist = Math.hypot(\n finalTouch2.x - finalTouch1.x,\n finalTouch2.y - finalTouch1.y,\n )\n\n // Calculate the scaling factor, prevent division by zero\n const s = initialDist === 0 ? 1 : currentDist / initialDist\n\n // Calculate the translation delta\n const deltaX = currentCenter.x - initialCenter.x\n const deltaY = currentCenter.y - initialCenter.y\n\n // Compose the transformation matrix\n // 1. Translate by the delta movement of the center\n // 2. Translate to the initial center\n // 3. Scale around the initial center\n // 4. Translate back from the initial center\n // 5. Apply the initial transform before the pinch started\n const pinchTransform = compose(\n translate(deltaX, deltaY),\n translate(initialCenter.x, initialCenter.y),\n scale(s, s),\n translate(-initialCenter.x, -initialCenter.y),\n initialTransform,\n )\n\n return pinchTransform\n}\n","import {\n Matrix,\n identity,\n translate,\n compose,\n applyToPoint,\n scale,\n} from \"transformation-matrix\"\n// import { fromTwoMovingPoints } from \"transformation-matrix\" // Not used currently\nimport { useCallback, useEffect, useReducer, useRef, useState } from \"react\"\nimport { computePinchTransform } from \"./computePinchTransform\"\n\ntype Point = { x: number; y: number }\n\ninterface Props {\n canvasElm?: HTMLElement\n transform?: Matrix\n initialTransform?: Matrix\n onSetTransform?: (transform: Matrix) => any\n enabled?: boolean\n shouldDrag?: (e: MouseEvent | TouchEvent | WheelEvent) => boolean\n}\n\nexport const useMouseMatrixTransform = (props: Props = {}) => {\n const extRef = useRef<any>(null)\n const [lastDragCancelTime, setLastDragCancelTime] = useState(0)\n const outerCanvasElm = props.canvasElm ?? extRef.current\n const [internalTransform, setInternalTransform] = useState<Matrix>(\n props.initialTransform ?? identity(),\n )\n const [waitCounter, setWaitCounter] = useState(0)\n const [extChangeCounter, incExtChangeCounter] = useReducer((s) => s + 1, 0)\n\n const setTransform = useCallback(\n (newTransform: Matrix) => {\n if (props.onSetTransform) {\n props.onSetTransform(newTransform)\n }\n if (!props.transform) {\n setInternalTransform(newTransform)\n }\n },\n [props.onSetTransform, setInternalTransform],\n )\n\n const setTransformExt = useCallback(\n (newTransform: Matrix) => {\n setTransform(newTransform)\n incExtChangeCounter()\n },\n [setTransform],\n )\n\n const transform = props.transform ?? internalTransform\n\n const cancelDrag = useCallback(() => {\n setLastDragCancelTime(Date.now())\n }, [])\n\n const gestureModeRef = useRef<\"none\" | \"drag\" | \"pinch\">(\"none\")\n // const lastTouchRef = useRef<{ x: number; y: number } | null>(null) // No longer needed for delta calculation\n const dragDataRef = useRef<{\n initialTransform: Matrix\n initialTouch: Point\n } | null>(null)\n const pinchDataRef = useRef<{\n initialTransform: Matrix\n initialTouch1: Point\n initialTouch2: Point\n finalTouch1: Point | null\n finalTouch2: Point | null\n } | null>(null)\n\n useEffect(() => {\n const canvasElm: HTMLCanvasElement | null =\n props.canvasElm ?? extRef.current\n if (canvasElm && !outerCanvasElm) {\n setWaitCounter(waitCounter + 1)\n return\n }\n if (!canvasElm) {\n const timeout = setTimeout(() => {\n setWaitCounter(waitCounter + 1)\n }, 100)\n return () => clearTimeout(timeout)\n }\n let init_tf = props.transform ?? internalTransform\n\n let m0: Point = { x: 0, y: 0 },\n m1: Point = { x: 0, y: 0 },\n md = false,\n mlastrel: Point = { x: 0, y: 0 }\n\n const getMousePos = (e: MouseEvent) => {\n return {\n x: e.pageX - canvasElm.getBoundingClientRect().left - window.scrollX,\n y: e.pageY - canvasElm.getBoundingClientRect().top - window.scrollY,\n }\n }\n\n function handleMouseDown(e: MouseEvent) {\n if (props.enabled === false) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n m0 = getMousePos(e)\n if (Date.now() - lastDragCancelTime < 100) return\n md = true\n e.preventDefault()\n }\n function handleMouseUp(e: MouseEvent) {\n if (!md || props.enabled === false) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n m1 = getMousePos(e)\n\n const new_tf = compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf)\n setTransform(new_tf)\n init_tf = new_tf\n\n md = false\n }\n function handleMouseMove(e: MouseEvent) {\n mlastrel = getMousePos(e)\n if (!md || props.enabled === false) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n m1 = getMousePos(e)\n const new_tf = compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf)\n setTransform(new_tf)\n }\n function handleMouseWheel(e: WheelEvent) {\n if (props.enabled === false) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n const center = getMousePos(e)\n const new_tf = compose(\n translate(center.x, center.y),\n scale(1 - e.deltaY / 1000, 1 - e.deltaY / 1000),\n translate(-center.x, -center.y),\n init_tf,\n )\n setTransform(new_tf)\n init_tf = new_tf\n e.preventDefault()\n }\n function handleMouseOut(e: MouseEvent) {\n if (!md) return\n if (props.shouldDrag && !props.shouldDrag(e)) return\n\n if (canvasElm) {\n const boundingBox = canvasElm.getBoundingClientRect()\n if (\n e.clientX >= boundingBox.left + 10 &&\n e.clientX <= boundingBox.right - 10 &&\n e.clientY >= boundingBox.top + 10 &&\n e.clientY <= boundingBox.bottom - 10\n ) {\n return\n }\n }\n\n md = false\n m1 = getMousePos(e)\n const new_tf = compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf)\n setTransform(new_tf)\n init_tf = new_tf\n }\n\n function handleTouchStart(e: TouchEvent) {\n e.preventDefault()\n if (props.enabled === false) return\n if (e.touches.length === 1) {\n // Start Drag\n gestureModeRef.current = \"drag\"\n const touch = e.touches[0]\n dragDataRef.current = {\n initialTransform: init_tf, // Capture transform before drag starts\n initialTouch: { x: touch.clientX, y: touch.clientY },\n }\n } else if (e.touches.length === 2) {\n // Start Pinch\n gestureModeRef.current = \"pinch\"\n const touch1 = e.touches[0]\n const touch2 = e.touches[1]\n pinchDataRef.current = {\n initialTransform: init_tf, // Store the transform at the start of the pinch\n initialTouch1: { x: touch1.clientX, y: touch1.clientY },\n initialTouch2: { x: touch2.clientX, y: touch2.clientY },\n finalTouch1: null,\n finalTouch2: null,\n }\n }\n }\n\n function handleTouchMove(e: TouchEvent) {\n e.preventDefault()\n if (props.enabled === false) return\n if (\n gestureModeRef.current === \"drag\" &&\n e.touches.length === 1 &&\n dragDataRef.current // Check if drag has started\n ) {\n // Handle Drag Move\n const touch = e.touches[0]\n const currentTouch = { x: touch.clientX, y: touch.clientY }\n const deltaX = currentTouch.x - dragDataRef.current.initialTouch.x\n const deltaY = currentTouch.y - dragDataRef.current.initialTouch.y\n\n // Apply delta to the transform that existed *before* the drag started\n const new_tf = compose(\n translate(deltaX, deltaY),\n dragDataRef.current.initialTransform,\n )\n setTransform(new_tf)\n // Do not update init_tf here\n } else if (\n gestureModeRef.current === \"pinch\" &&\n e.touches.length === 2 &&\n pinchDataRef.current\n ) {\n const touch1 = e.touches[0]\n const touch2 = e.touches[1]\n\n pinchDataRef.current.finalTouch1 = {\n x: touch1.clientX,\n y: touch1.clientY,\n }\n pinchDataRef.current.finalTouch2 = {\n x: touch2.clientX,\n y: touch2.clientY,\n }\n\n const new_tf = computePinchTransform(pinchDataRef.current)\n setTransform(new_tf)\n // Don't update init_tf here, only on touch end\n }\n }\n\n function handleTouchEnd(e: TouchEvent) {\n e.preventDefault()\n\n // Use changedTouches to get the final position of the lifted finger(s)\n const finalTouch = e.changedTouches[0]\n\n if (\n gestureModeRef.current === \"drag\" &&\n dragDataRef.current && // Check if drag was active\n finalTouch // Ensure we have the final touch info\n ) {\n // Drag End\n const finalTouchPos = { x: finalTouch.clientX, y: finalTouch.clientY }\n const deltaX = finalTouchPos.x - dragDataRef.current.initialTouch.x\n const deltaY = finalTouchPos.y - dragDataRef.current.initialTouch.y\n\n // Calculate the final transform based on the total delta\n const new_tf = compose(\n translate(deltaX, deltaY),\n dragDataRef.current.initialTransform,\n )\n setTransform(new_tf) // Update the visual state\n init_tf = new_tf // Lock in the transform for the next gesture\n } else if (gestureModeRef.current === \"pinch\" && pinchDataRef.current) {\n const new_tf = computePinchTransform(pinchDataRef.current)\n setTransform(new_tf) // Ensure the final state is set\n init_tf = new_tf // Update init_tf\n }\n\n // Reset gesture state and data refs\n gestureModeRef.current = \"none\"\n // lastTouchRef.current = null // No longer used\n dragDataRef.current = null\n pinchDataRef.current = null\n }\n\n canvasElm.addEventListener(\"mousedown\", handleMouseDown)\n canvasElm.addEventListener(\"mouseup\", handleMouseUp)\n window.addEventListener(\"mousemove\", handleMouseMove)\n canvasElm.addEventListener(\"mouseout\", handleMouseOut)\n canvasElm.addEventListener(\"wheel\", handleMouseWheel)\n\n canvasElm.addEventListener(\"touchstart\", handleTouchStart, {\n passive: false,\n })\n canvasElm.addEventListener(\"touchmove\", handleTouchMove, {\n passive: false,\n })\n canvasElm.addEventListener(\"touchend\", handleTouchEnd, { passive: false })\n canvasElm.addEventListener(\"touchcancel\", handleTouchEnd, {\n passive: false,\n })\n\n return () => {\n canvasElm.removeEventListener(\"mousedown\", handleMouseDown)\n canvasElm.removeEventListener(\"mouseup\", handleMouseUp)\n window.removeEventListener(\"mousemove\", handleMouseMove)\n canvasElm.removeEventListener(\"mouseout\", handleMouseOut)\n canvasElm.removeEventListener(\"wheel\", handleMouseWheel)\n\n canvasElm.removeEventListener(\"touchstart\", handleTouchStart)\n canvasElm.removeEventListener(\"touchmove\", handleTouchMove)\n canvasElm.removeEventListener(\"touchend\", handleTouchEnd)\n canvasElm.removeEventListener(\"touchcancel\", handleTouchEnd)\n }\n }, [\n outerCanvasElm,\n waitCounter,\n extChangeCounter,\n lastDragCancelTime,\n props.enabled,\n props.shouldDrag,\n ])\n\n const applyTransformToPoint = useCallback(\n (obj: Point | [number, number]) => applyToPoint(transform, obj),\n [transform],\n )\n\n return {\n ref: extRef,\n transform,\n applyTransformToPoint,\n setTransform: setTransformExt,\n cancelDrag,\n }\n}\n\nexport default useMouseMatrixTransform\n","type NodeId = string\n\nexport function findConnectedNetworks(\n connections: Array<NodeId[]>,\n): Record<string, string[]> {\n const networks: Map<string, Set<string>> = new Map()\n let netCounter = 0\n\n function getOrCreateNetwork(nodeId: string): Set<string> {\n for (const [, network] of networks) {\n if (network.has(nodeId)) {\n return network\n }\n }\n const newNetwork = new Set<string>()\n networks.set(`connectivity_net${netCounter++}`, newNetwork)\n return newNetwork\n }\n\n for (const connection of connections) {\n let network: Set<string> | null = null\n\n for (const nodeId of connection) {\n if (!network) {\n network = getOrCreateNetwork(nodeId)\n } else if (!network.has(nodeId)) {\n const existingNetwork = getOrCreateNetwork(nodeId)\n if (existingNetwork !== network) {\n // Merge networks\n for (const node of existingNetwork) {\n network.add(node)\n }\n networks.delete(\n Array.from(networks.entries()).find(\n ([, net]) => net === existingNetwork,\n )![0],\n )\n }\n }\n network.add(nodeId)\n }\n }\n\n return Object.fromEntries(\n Array.from(networks.entries()).map(([netId, connectedNodes]) => [\n netId,\n Array.from(connectedNodes),\n ]),\n )\n}\n","export class ConnectivityMap {\n netMap: Record<string, string[]>\n\n idToNetMap: Record<string, string>\n\n constructor(netMap: Record<string, string[]>) {\n this.netMap = netMap\n this.idToNetMap = {}\n for (const [netId, ids] of Object.entries(netMap)) {\n for (const id of ids) {\n this.idToNetMap[id] = netId\n }\n }\n }\n\n addConnections(connections: string[][]) {\n for (const connection of connections) {\n const existingNets = new Set<string>()\n\n // Find all existing nets for the connection\n for (const id of connection) {\n const existingNetId = this.idToNetMap[id]\n if (existingNetId) {\n existingNets.add(existingNetId)\n }\n }\n\n let targetNetId: string\n\n if (existingNets.size === 0) {\n // If no existing nets found, create a new one\n targetNetId = `connectivity_net${Object.keys(this.netMap).length}`\n this.netMap[targetNetId] = []\n } else if (existingNets.size === 1) {\n // If only one existing net found, use it\n targetNetId =\n existingNets.values().next().value ??\n `connectivity_net${Object.keys(this.netMap).length}`\n } else {\n // If multiple nets found, merge them\n targetNetId =\n existingNets.values().next().value ??\n `connectivity_net${Object.keys(this.netMap).length}`\n for (const netId of existingNets) {\n if (netId !== targetNetId) {\n this.netMap[targetNetId].push(...this.netMap[netId])\n\n // we could delete the net, but setting it to reference the other net\n // will make sure any usage of the old netId will still work\n this.netMap[netId] = this.netMap[targetNetId]\n for (const id of this.netMap[targetNetId]) {\n this.idToNetMap[id] = targetNetId\n }\n }\n }\n }\n\n // Add all ids to the target net\n for (const id of connection) {\n if (!this.netMap[targetNetId].includes(id)) {\n this.netMap[targetNetId].push(id)\n }\n this.idToNetMap[id] = targetNetId\n }\n }\n }\n\n getIdsConnectedToNet(netId: string): string[] {\n return this.netMap[netId] || []\n }\n\n getNetConnectedToId(id: string): string | undefined {\n return this.idToNetMap[id]\n }\n\n areIdsConnected(id1: string, id2: string): boolean {\n if (id1 === id2) return true\n const netId1 = this.getNetConnectedToId(id1)\n if (!netId1) return false\n const netId2 = this.getNetConnectedToId(id2)\n if (!netId2) return false\n return netId1 === netId2 || netId2 === id1 || netId2 === id1\n }\n\n areAllIdsConnected(ids: string[]): boolean {\n const netId = this.getNetConnectedToId(ids[0])\n for (const id of ids) {\n const nextNetId = this.getNetConnectedToId(id)\n if (nextNetId === undefined) {\n return false\n }\n if (nextNetId !== netId) {\n return false\n }\n }\n return true\n }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getSourcePortConnectivityMapFromCircuitJson = (\n circuitJson: AnyCircuitElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push([\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ])\n } else if (element.type === \"source_component\") {\n if (element.internally_connected_source_port_ids) {\n for (const portGroup of element.internally_connected_source_port_ids) {\n connections.push(portGroup)\n }\n }\n } else if (element.type === \"source_component_internal_connection\") {\n connections.push(element.source_port_ids)\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement, PcbTraceRoutePoint } from \"circuit-json\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getFullConnectivityMapFromCircuitJson = (\n circuitJson: AnyCircuitElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push(\n [\n element.source_trace_id,\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ].filter(Boolean),\n )\n } else if (element.type === \"pcb_port\") {\n const { pcb_port_id, source_port_id } = element\n if (source_port_id && pcb_port_id) {\n connections.push([source_port_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_smtpad\") {\n const { pcb_smtpad_id, pcb_port_id } = element\n if (pcb_port_id && pcb_smtpad_id) {\n connections.push([pcb_smtpad_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_plated_hole\") {\n const { pcb_plated_hole_id, pcb_port_id } = element\n if (pcb_port_id && pcb_plated_hole_id) {\n connections.push([pcb_plated_hole_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_trace\") {\n const { pcb_trace_id, source_trace_id } = element\n const route = Array.isArray(element.route)\n ? element.route.filter(\n (rp: PcbTraceRoutePoint) => rp && rp.route_type === \"wire\",\n )\n : []\n if (source_trace_id && pcb_trace_id) {\n connections.push([pcb_trace_id, source_trace_id])\n }\n if (Array.isArray(route)) {\n const startId = route.find(\n (rp) => rp?.start_pcb_port_id,\n )?.start_pcb_port_id\n const endId = route.find((rp) => rp?.end_pcb_port_id)?.end_pcb_port_id\n if (startId && pcb_trace_id && endId) {\n connections.push([startId, pcb_trace_id, endId])\n }\n }\n } else if (element.type === \"pcb_via\") {\n const { pcb_via_id, pcb_trace_id, source_trace_id, source_net_id } =\n element\n const connectedIds = [\n pcb_trace_id,\n source_trace_id,\n source_net_id,\n ].filter((connectedId): connectedId is string => Boolean(connectedId))\n if (pcb_via_id && connectedIds.length > 0) {\n connections.push([pcb_via_id, ...connectedIds])\n }\n } else if (element.type === \"source_component\") {\n if (element.internally_connected_source_port_ids) {\n for (const portGroup of element.internally_connected_source_port_ids) {\n connections.push(portGroup)\n }\n }\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement, PCBPort, PCBTrace } from \"circuit-json\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\nimport { doesLineIntersectLine } from \"@tscircuit/math-utils\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\n\n/**\n * A PCB Connectivity Map is a connectivity map that has analyzed what traces and ports are actually connected on the\n * PCB.\n *\n * This is useful for determining how to route a trace on the PCB. For example, you may want to determine where the\n * nearest connected net point is to connect an unrouted pin.\n */\nexport class PcbConnectivityMap {\n circuitJson: AnyCircuitElement[]\n traceIdToElm: Map<string, PCBTrace>\n portIdToElm: Map<string, PCBPort>\n connMap: ConnectivityMap\n\n constructor(circuitJson?: AnyCircuitElement[]) {\n this.circuitJson = circuitJson || []\n this.traceIdToElm = new Map()\n this.portIdToElm = new Map()\n if (circuitJson) {\n this._buildTraceMap()\n this._buildPortMap()\n this.connMap = this._buildTraceConnectivityMap()\n } else {\n this.connMap = new ConnectivityMap({})\n }\n }\n\n private _buildPortMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_port\") {\n this.portIdToElm.set(element.pcb_port_id, element as PCBPort)\n }\n }\n }\n\n private _buildTraceMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_trace\") {\n this.traceIdToElm.set(element.pcb_trace_id, element as PCBTrace)\n }\n }\n }\n\n private _buildTraceConnectivityMap(): ConnectivityMap {\n const connections: string[][] = []\n const traceIds = Array.from(this.traceIdToElm.keys())\n\n for (let i = 0; i < traceIds.length; i++) {\n for (let j = i + 1; j < traceIds.length; j++) {\n const trace1 = this.traceIdToElm.get(traceIds[i])!\n const trace2 = this.traceIdToElm.get(traceIds[j])!\n if (this._arePcbTracesConnected(trace1, trace2)) {\n connections.push([traceIds[i], traceIds[j]])\n }\n }\n }\n\n for (const port of this.portIdToElm.values()) {\n for (const trace of this.traceIdToElm.values()) {\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id === port.pcb_port_id) {\n connections.push([port.pcb_port_id, trace.pcb_trace_id])\n } else if (rp.end_pcb_port_id === port.pcb_port_id) {\n connections.push([trace.pcb_trace_id, port.pcb_port_id])\n }\n }\n }\n }\n }\n\n return new ConnectivityMap(findConnectedNetworks(connections))\n }\n\n addTrace(trace: PCBTrace) {\n this.traceIdToElm.set(trace.pcb_trace_id, trace)\n const connections: string[][] = []\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id) {\n connections.push([rp.start_pcb_port_id, trace.pcb_trace_id])\n }\n if (rp.end_pcb_port_id) {\n connections.push([rp.end_pcb_port_id, trace.pcb_trace_id])\n }\n }\n }\n\n this.connMap.addConnections(connections)\n }\n\n _arePcbTracesConnected(trace1: PCBTrace, trace2: PCBTrace): boolean {\n for (let i = 0; i < trace1.route.length - 1; i++) {\n const segment1A = trace1.route[i]\n const segment1B = trace1.route[i + 1]\n if (segment1A.route_type !== \"wire\") continue\n if (segment1B.route_type !== \"wire\") continue\n for (let j = 0; j < trace2.route.length - 1; j++) {\n const segment2A = trace2.route[j]\n const segment2B = trace2.route[j + 1]\n\n if (segment2A.route_type !== \"wire\") continue\n if (segment2B.route_type !== \"wire\") continue\n\n // Check if lines are overlapping\n const isOverlapping = doesLineIntersectLine(\n [segment1A, segment1B],\n [segment2A, segment2B],\n {\n lineThickness: (segment1A.width + segment2A.width) / 2,\n },\n )\n if (isOverlapping) {\n return true\n }\n }\n }\n return false\n }\n\n areTracesConnected(traceId1: string, traceId2: string): boolean {\n return this.connMap.areIdsConnected(traceId1, traceId2)\n }\n\n getAllTracesConnectedToTrace(traceId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(traceId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n\n getAllTracesConnectedToPort(portId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(portId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n}\n","export interface Point {\n x: number\n y: number\n trace_width?: number\n}\n\nexport function getExpandedStroke(\n strokeInput: (Point | [number, number] | number[])[],\n defaultWidth: number,\n): Point[] {\n if (strokeInput.length < 2) {\n throw new Error(\"Stroke must have at least two points\")\n }\n\n const stroke: Point[] = strokeInput.map((point) => {\n if (Array.isArray(point)) {\n return { x: point[0], y: point[1] }\n }\n return point as Point\n })\n\n const leftSide: Point[] = []\n const rightSide: Point[] = []\n\n function getNormal(p1: Point, p2: Point): Point {\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n const length = Math.sqrt(dx * dx + dy * dy)\n return { x: -dy / length, y: dx / length }\n }\n\n function addPoint(\n point: Point,\n normal: Point,\n factor: number,\n width: number,\n ) {\n const halfWidth = width / 2\n const newPoint = {\n x: point.x + normal.x * halfWidth * factor,\n y: point.y + normal.y * halfWidth * factor,\n }\n if (factor > 0) {\n leftSide.push(newPoint)\n } else {\n rightSide.unshift(newPoint)\n }\n }\n\n // Handle the first point\n const firstNormal = getNormal(stroke[0]!, stroke[1]!)\n const firstWidth = stroke[0]!.trace_width ?? defaultWidth\n addPoint(stroke[0]!, firstNormal, 1, firstWidth)\n addPoint(stroke[0]!, firstNormal, -1, firstWidth)\n\n // Handle middle points\n for (let i = 1; i < stroke.length - 1; i++) {\n const prev = stroke[i - 1]!\n const current = stroke[i]!\n const next = stroke[i + 1]!\n\n const normalPrev = getNormal(prev, current)\n const normalNext = getNormal(current, next)\n\n // Calculate miter line\n const miterX = normalPrev.x + normalNext.x\n const miterY = normalPrev.y + normalNext.y\n const miterLength = Math.sqrt(miterX * miterX + miterY * miterY)\n\n const currentWidth = current.trace_width ?? defaultWidth\n\n // Check if miter is too long (sharp corner)\n const miterLimit = 2 // Adjust this value to control when to bevel\n if (miterLength / 2 > miterLimit * (currentWidth / 2)) {\n // Use bevel join\n addPoint(current, normalPrev, 1, currentWidth)\n addPoint(current, normalNext, 1, currentWidth)\n addPoint(current, normalPrev, -1, currentWidth)\n addPoint(current, normalNext, -1, currentWidth)\n } else {\n // Use miter join\n const scale = 1 / miterLength\n addPoint(\n current,\n { x: miterX * scale, y: miterY * scale },\n 1,\n currentWidth,\n )\n addPoint(\n current,\n { x: miterX * scale, y: miterY * scale },\n -1,\n currentWidth,\n )\n }\n }\n\n // Handle the last point\n const lastNormal = getNormal(\n stroke[stroke.length - 2]!,\n stroke[stroke.length - 1]!,\n )\n const lastWidth = stroke[stroke.length - 1]!.trace_width ?? defaultWidth\n addPoint(stroke[stroke.length - 1]!, lastNormal, 1, lastWidth)\n addPoint(stroke[stroke.length - 1]!, lastNormal, -1, lastWidth)\n\n // Combine left and right sides to form a closed polygon\n return [...leftSide, ...rightSide]\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { su } from \"@tscircuit/circuit-json-util\"\nimport type { Primitive } from \"./types\"\nimport { type Point, getExpandedStroke } from \"./util/expand-stroke\"\nimport { distance } from \"circuit-json\"\nimport { convertSmtpadRect } from \"./element-to-primitive-converters/convert-smtpad-rect\"\nimport { convertSmtpadCircle } from \"./element-to-primitive-converters/convert-smtpad-circle\"\nimport { convertSmtpadPolygon } from \"./element-to-primitive-converters/convert-smtpad-polygon\"\nimport {\n convertSmtpadPill,\n convertSmtpadRotatedPill,\n} from \"./element-to-primitive-converters/convert-smtpad-pill\"\n\nimport { convertPcbCopperTextToPrimitive } from \"./element-to-primitive/convert-pcb-copper-text-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nlet globalPcbDrawingObjectCount = 0\n\nexport const getNewPcbDrawingObjectId = (prefix: string) =>\n `${prefix}_${globalPcbDrawingObjectCount++}`\n\nexport const normalizePolygonPoints = (points: Point[] | undefined) =>\n (points ?? []).map((point) => ({\n x: distance.parse(point.x),\n y: distance.parse(point.y),\n }))\n\nexport const convertElementToPrimitives = (\n element: AnyCircuitElement,\n allElements: AnyCircuitElement[],\n): (Primitive & MetaData)[] => {\n const _parent_pcb_component =\n \"pcb_component_id\" in element\n ? allElements.find(\n (elm) =>\n elm.type === \"pcb_component\" &&\n elm.pcb_component_id === element.pcb_component_id,\n )\n : undefined\n const _parent_source_component =\n _parent_pcb_component && \"source_component_id\" in _parent_pcb_component\n ? allElements.find(\n (elm) =>\n elm.type === \"source_component\" &&\n elm.source_component_id ===\n _parent_pcb_component.source_component_id,\n )\n : undefined\n\n const _source_port_id =\n \"source_port_id\" in element\n ? element.source_port_id\n : \"pcb_port_id\" in element\n ? su(allElements).pcb_port.get(element.pcb_port_id!)?.source_port_id\n : undefined\n\n const _source_port = _source_port_id\n ? allElements.find(\n (e) => e.type === \"source_port\" && e.source_port_id === _source_port_id,\n )\n : undefined\n\n switch (element.type) {\n case \"pcb_smtpad\": {\n const metadata: MetaData = {\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n }\n\n if (element.shape === \"rect\" || element.shape === \"rotated_rect\") {\n return convertSmtpadRect(element, metadata)\n } else if (element.shape === \"circle\") {\n return convertSmtpadCircle(element, metadata)\n } else if (element.shape === \"polygon\") {\n return convertSmtpadPolygon(element, metadata)\n } else if (element.shape === \"pill\") {\n return convertSmtpadPill(element, metadata)\n } else if (element.shape === \"rotated_pill\") {\n return convertSmtpadRotatedPill(element, metadata)\n }\n return []\n }\n\n case \"pcb_trace\": {\n const primitives: Primitive[] = []\n\n if (element.route_thickness_mode === \"interpolated\") {\n // Prepare the stroke input\n const strokeInput: Point[] = element.route.flatMap((routePoint) => {\n if (routePoint.route_type === \"through_pad\") {\n return [\n {\n ...routePoint.start,\n trace_width: routePoint.width,\n },\n {\n ...routePoint.end,\n trace_width: routePoint.width,\n },\n ]\n }\n\n return [\n {\n x: routePoint.x,\n y: routePoint.y,\n trace_width:\n routePoint.route_type === \"wire\" ? routePoint.width : 0.5,\n },\n ]\n })\n\n // Use getExpandedStroke to generate the polygon points\n const expandedStroke = getExpandedStroke(strokeInput, 0.5) // Use 0.5 as default width\n\n const layer = (element.route[0] as any).layer\n\n // Generate a single polygon primitive from the expanded stroke\n primitives.push({\n _pcb_drawing_object_id: `polygon_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"polygon\",\n points: expandedStroke,\n layer, // same layer for all points\n })\n\n // Add circles for vias\n element.route.forEach((r) => {\n if (r.route_type === \"via\") {\n primitives.push({\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"circle\",\n x: r.x,\n y: r.y,\n r: (r as any).outer_diameter / 2,\n layer: (r as any).from_layer,\n })\n }\n })\n\n return primitives\n }\n let prevX: number | null = null\n let prevY: number | null = null\n\n for (const route of element.route) {\n if (route.route_type === \"wire\") {\n if (prevX !== null && prevY !== null) {\n primitives.push({\n _pcb_drawing_object_id: `line_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"line\",\n x1: prevX,\n y1: prevY,\n x2: route.x,\n y2: route.y,\n width: route.width,\n squareCap: false,\n layer: route.layer,\n })\n }\n\n prevX = route.x\n prevY = route.y\n }\n }\n\n return primitives\n }\n // The builder currently outputs these as smtpads and holes, so pcb_via isn't\n // used, but that maybe should be changed\n case \"pcb_via\": {\n const { x, y, outer_diameter, hole_diameter } = element\n const from_layer = element.from_layer\n const to_layer = element.to_layer\n const layers = element.layers\n\n // Support both old format (from_layer/to_layer) and new format (layers array)\n const copperLayers: string[] = []\n if (from_layer && to_layer) {\n copperLayers.push(from_layer, to_layer)\n } else if (layers && Array.isArray(layers)) {\n copperLayers.push(...layers)\n } else {\n // Default to top and bottom if no layer info\n copperLayers.push(\"top\", \"bottom\")\n }\n\n // Create the outer copper circles on the via layers\n // and the inner drill hole, similar to how pcb_plated_hole works\n const primitives: Primitive[] = []\n\n // Add outer copper circles for each layer\n for (const layer of copperLayers) {\n primitives.push({\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x,\n y,\n r: outer_diameter / 2,\n layer,\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n })\n }\n\n // Add inner drill hole (drawn on top due to layer order)\n primitives.push({\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x,\n y,\n r: hole_diameter / 2,\n layer: \"drill\",\n _element: element,\n })\n\n return primitives\n }\n\n case \"pcb_plated_hole\": {\n if (element.shape === \"circle\") {\n const { x, y, hole_diameter, outer_diameter } = element\n\n return [\n {\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x,\n y,\n r: outer_diameter / 2,\n // TODO support layer on pcb_plated_hole\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n },\n {\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x,\n y,\n r: hole_diameter / 2,\n // TODO support layer on pcb_plated_hole\n layer: \"drill\",\n _element: element,\n\n // double highlights are annoying\n // _element: element,\n },\n ]\n } else if (element.shape === \"oval\") {\n const { x, y, outer_height, outer_width, hole_height, hole_width } =\n element\n\n return [\n {\n _pcb_drawing_object_id: `oval_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"oval\",\n x,\n y,\n rX: outer_width / 2,\n rY: outer_height / 2,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n },\n {\n _pcb_drawing_object_id: `oval_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"oval\",\n x,\n y,\n rX: hole_width / 2,\n rY: hole_height / 2,\n layer: \"drill\",\n },\n ]\n } else if (element.shape === \"pill\") {\n const { x, y, outer_height, outer_width, hole_height, hole_width } =\n element\n\n return [\n {\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"pill\",\n x,\n y,\n w: outer_width,\n h: outer_height,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n ccw_rotation: element.ccw_rotation,\n },\n {\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"pill\",\n x,\n y,\n w: hole_width,\n h: hole_height,\n layer: \"drill\",\n ccw_rotation: element.ccw_rotation,\n },\n ]\n } else if (element.shape === \"circular_hole_with_rect_pad\") {\n const {\n x,\n y,\n hole_diameter,\n rect_pad_width,\n rect_pad_height,\n rect_border_radius,\n hole_offset_x,\n hole_offset_y,\n } = element\n const parsed_hole_offset_x = distance.parse(hole_offset_x ?? 0)\n const parsed_hole_offset_y = distance.parse(hole_offset_y ?? 0)\n\n return [\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n roundness: rect_border_radius,\n },\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"bottom\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n roundness: rect_border_radius,\n is_hoverable: false,\n },\n {\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"circle\",\n x: x + parsed_hole_offset_x,\n y: y + parsed_hole_offset_y,\n r: hole_diameter / 2,\n layer: \"drill\",\n is_hoverable: false,\n },\n ]\n } else if (element.shape === \"pill_hole_with_rect_pad\") {\n const {\n x,\n y,\n hole_width,\n hole_height,\n rect_pad_width,\n rect_pad_height,\n rect_border_radius,\n } = element\n\n return [\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n roundness: rect_border_radius,\n },\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"bottom\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n roundness: rect_border_radius,\n is_hoverable: false,\n },\n {\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"pill\",\n x,\n y,\n w: hole_width,\n h: hole_height,\n layer: \"drill\",\n is_hoverable: false,\n },\n ]\n } else if (element.shape === \"rotated_pill_hole_with_rect_pad\") {\n const {\n x,\n y,\n hole_width,\n hole_height,\n hole_ccw_rotation,\n rect_pad_width,\n rect_pad_height,\n rect_ccw_rotation,\n rect_border_radius,\n } = element\n\n return [\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"top\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n ccw_rotation: rect_ccw_rotation,\n roundness: rect_border_radius,\n },\n {\n _pcb_drawing_object_id: `rect_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"rect\",\n x,\n y,\n w: rect_pad_width,\n h: rect_pad_height,\n layer: \"bottom\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n ccw_rotation: rect_ccw_rotation,\n roundness: rect_border_radius,\n is_hoverable: false,\n },\n {\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n _element: element,\n pcb_drawing_type: \"pill\",\n x,\n y,\n w: hole_width,\n h: hole_height,\n layer: \"drill\",\n ccw_rotation: hole_ccw_rotation,\n is_hoverable: false,\n },\n ]\n } else if (element.shape === \"hole_with_polygon_pad\") {\n const {\n x,\n y,\n pad_outline,\n hole_shape,\n hole_diameter,\n hole_width,\n hole_height,\n layers,\n hole_offset_x,\n hole_offset_y,\n } = element\n\n const parsed_hole_offset_x = distance.parse(hole_offset_x ?? 0)\n const parsed_hole_offset_y = distance.parse(hole_offset_y ?? 0)\n\n const pcb_outline = pad_outline\n\n const padPrimitives: Primitive[] = []\n if (pcb_outline && Array.isArray(pcb_outline)) {\n const translatedPoints = normalizePolygonPoints(pcb_outline).map(\n (p) => ({ x: p.x + x, y: p.y + y }),\n )\n\n for (const layer of layers || [\"top\", \"bottom\"]) {\n padPrimitives.push({\n _pcb_drawing_object_id: `polygon_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"polygon\",\n points: translatedPoints,\n layer: layer,\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n })\n }\n }\n\n const holeCenter = {\n x: x + parsed_hole_offset_x,\n y: y + parsed_hole_offset_y,\n }\n\n const holePrimitives: Primitive[] = []\n\n if (hole_shape === \"circle\") {\n holePrimitives.push({\n _pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"circle\",\n x: holeCenter.x,\n y: holeCenter.y,\n r: (hole_diameter ?? 0) / 2,\n layer: \"drill\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n })\n } else if (hole_shape === \"oval\") {\n holePrimitives.push({\n _pcb_drawing_object_id: `oval_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"oval\",\n x: holeCenter.x,\n y: holeCenter.y,\n rX: (hole_width ?? 0) / 2,\n rY: (hole_height ?? 0) / 2,\n layer: \"drill\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n })\n } else if (hole_shape === \"pill\" || hole_shape === \"rotated_pill\") {\n holePrimitives.push({\n _pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,\n pcb_drawing_type: \"pill\",\n x: holeCenter.x,\n y: holeCenter.y,\n w: hole_width ?? 0,\n h: hole_height ?? 0,\n layer: \"drill\",\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n ccw_rotation: element.ccw_rotation,\n })\n }\n\n return [...padPrimitives, ...holePrimitives]\n } else {\n return []\n }\n }\n }\n\n return []\n}\n","import type { PcbSmtPadRect, PcbSmtPadRotatedRect } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\nimport { getNewPcbDrawingObjectId } from \"../convert-element-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nexport const convertSmtpadRect = (\n element: PcbSmtPadRect | PcbSmtPadRotatedRect,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { x, y, width, height, layer, rect_border_radius } = element\n const corner_radius = element.corner_radius ?? rect_border_radius ?? 0\n\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"rect\"),\n pcb_drawing_type: \"rect\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n roundness: corner_radius,\n ...(element.shape === \"rotated_rect\" && element.ccw_rotation !== undefined\n ? { ccw_rotation: element.ccw_rotation }\n : {}),\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitiveBase: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"rect\"),\n pcb_drawing_type: \"rect\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n roundness: corner_radius,\n ...(element.shape === \"rotated_rect\" && element.ccw_rotation !== undefined\n ? { ccw_rotation: element.ccw_rotation }\n : {}),\n }\n const maskPrimitive: Primitive & MetaData = {\n ...maskPrimitiveBase,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color as string }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n","import type { PcbSmtPadCircle } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\nimport { getNewPcbDrawingObjectId } from \"../convert-element-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nexport const convertSmtpadCircle = (\n element: PcbSmtPadCircle,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { x, y, radius, layer } = element\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"circle\"),\n pcb_drawing_type: \"circle\" as const,\n x,\n y,\n r: radius,\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitive: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"circle\"),\n pcb_drawing_type: \"circle\" as const,\n x,\n y,\n r: radius,\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n","import type { PcbSmtPadPolygon } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\nimport {\n getNewPcbDrawingObjectId,\n normalizePolygonPoints,\n} from \"../convert-element-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nexport const convertSmtpadPolygon = (\n element: PcbSmtPadPolygon,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { layer, points } = element\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"polygon\"),\n pcb_drawing_type: \"polygon\" as const,\n points: normalizePolygonPoints(points),\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitive: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"polygon\"),\n pcb_drawing_type: \"polygon\" as const,\n points: normalizePolygonPoints(points),\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n","import type { PcbSmtPadPill, PcbSmtPadRotatedPill } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\nimport { getNewPcbDrawingObjectId } from \"../convert-element-to-primitive\"\n\ntype MetaData = {\n _parent_pcb_component?: any\n _parent_source_component?: any\n _source_port?: any\n}\n\nexport const convertSmtpadPill = (\n element: PcbSmtPadPill,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { x, y, width, height, layer } = element\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"pill\"),\n pcb_drawing_type: \"pill\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitive: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"pill\"),\n pcb_drawing_type: \"pill\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n\nexport const convertSmtpadRotatedPill = (\n element: PcbSmtPadRotatedPill,\n metadata: MetaData,\n): (Primitive & MetaData)[] => {\n const { x, y, width, height, layer, ccw_rotation } = element\n const primitives: (Primitive & MetaData)[] = [\n {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"pill\"),\n pcb_drawing_type: \"pill\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: layer || \"top\",\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ccw_rotation,\n },\n ]\n\n // Add solder mask if enabled\n if (element.is_covered_with_solder_mask) {\n const maskLayer =\n layer === \"bottom\"\n ? \"soldermask_with_copper_bottom\"\n : \"soldermask_with_copper_top\"\n const maskPrimitive: Primitive & MetaData = {\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"pill\"),\n pcb_drawing_type: \"pill\" as const,\n x,\n y,\n w: width,\n h: height,\n layer: maskLayer,\n _element: element,\n _parent_pcb_component: metadata._parent_pcb_component,\n _parent_source_component: metadata._parent_source_component,\n _source_port: metadata._source_port,\n ccw_rotation,\n ...(\"solder_mask_color\" in element && element.solder_mask_color\n ? { color: element.solder_mask_color }\n : {}),\n }\n primitives.push(maskPrimitive)\n }\n\n return primitives\n}\n","import { Primitive } from \"lib/types\"\n\nexport function addInteractionMetadataToPrimitives({\n primitivesWithoutInteractionMetadata,\n drawingObjectIdsWithMouseOver,\n primitiveIdsInMousedOverNet,\n}: {\n primitivesWithoutInteractionMetadata: Primitive[]\n drawingObjectIdsWithMouseOver: Set<string>\n primitiveIdsInMousedOverNet: string[]\n}): Primitive[] {\n const newPrimitives = []\n for (const primitive of primitivesWithoutInteractionMetadata) {\n const newPrimitive = { ...primitive }\n const primitiveElement = primitive._element\n const parentComponent = primitive._parent_pcb_component\n if (primitive?.layer === \"drill\") {\n newPrimitive.is_in_highlighted_net = false\n newPrimitive.is_mouse_over = false\n } else if (\n drawingObjectIdsWithMouseOver.has(primitive._pcb_drawing_object_id)\n ) {\n newPrimitive.is_mouse_over = true\n } else if (\n primitiveElement &&\n ((\"pcb_trace_id\" in primitiveElement &&\n primitiveIdsInMousedOverNet.includes(primitiveElement.pcb_trace_id!)) ||\n (\"pcb_port_id\" in primitiveElement &&\n primitiveIdsInMousedOverNet.includes(\n primitiveElement.pcb_port_id!,\n )) ||\n (\"pcb_via_id\" in primitiveElement &&\n primitiveIdsInMousedOverNet.includes(primitiveElement.pcb_via_id!)) ||\n (\"pcb_component_id\" in primitiveElement &&\n primitiveIdsInMousedOverNet.includes(\n primitiveElement.pcb_component_id!,\n )) ||\n (parentComponent &&\n \"pcb_component_id\" in parentComponent &&\n primitiveIdsInMousedOverNet.includes(\n parentComponent.pcb_component_id!,\n )))\n ) {\n newPrimitive.is_in_highlighted_net = true\n } else {\n newPrimitive.is_in_highlighted_net = false\n newPrimitive.is_mouse_over = false\n }\n newPrimitives.push(newPrimitive)\n }\n return newPrimitives\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport {\n getBoundsFromPoints,\n type Bounds,\n type Point,\n} from \"@tscircuit/math-utils\"\nimport { compose, scale, translate, type Matrix } from \"transformation-matrix\"\n\ninterface RoutePoint extends Point {\n width?: number\n}\n\nexport interface ErrorPreviewElementIndexes {\n tracesById: Map<string, any>\n portsById: Map<string, any>\n viasById: Map<string, any>\n componentsById: Map<string, any>\n boardsById: Map<string, any>\n}\n\nexport const buildErrorPreviewElementIndexes = (\n elements: AnyCircuitElement[],\n): ErrorPreviewElementIndexes => {\n const tracesById = new Map<string, any>()\n const portsById = new Map<string, any>()\n const viasById = new Map<string, any>()\n const componentsById = new Map<string, any>()\n const boardsById = new Map<string, any>()\n\n for (const element of elements) {\n if (element.type === \"pcb_trace\" && element.pcb_trace_id) {\n tracesById.set(element.pcb_trace_id, element)\n } else if (element.type === \"pcb_port\" && element.pcb_port_id) {\n portsById.set(element.pcb_port_id, element)\n } else if (element.type === \"pcb_via\" && element.pcb_via_id) {\n viasById.set(element.pcb_via_id, element)\n } else if (element.type === \"pcb_component\" && element.pcb_component_id) {\n componentsById.set(element.pcb_component_id, element)\n } else if (element.type === \"pcb_board\" && element.pcb_board_id) {\n boardsById.set(element.pcb_board_id, element)\n }\n }\n\n return {\n tracesById,\n portsById,\n viasById,\n componentsById,\n boardsById,\n }\n}\n\nconst mergeBounds = (\n existing: Bounds | null,\n next: Bounds | null | undefined,\n): Bounds | null => {\n if (!next) return existing\n if (!existing) return next\n\n return {\n minX: Math.min(existing.minX, next.minX),\n maxX: Math.max(existing.maxX, next.maxX),\n minY: Math.min(existing.minY, next.minY),\n maxY: Math.max(existing.maxY, next.maxY),\n }\n}\n\nconst createBoundsFromCenter = (center: Point, radius = 0.45): Bounds => ({\n minX: center.x - radius,\n maxX: center.x + radius,\n minY: center.y - radius,\n maxY: center.y + radius,\n})\n\nconst createBoundsFromRoute = (route: RoutePoint[]): Bounds | null => {\n if (route.length === 0) return null\n\n let bounds: Bounds | null = null\n for (const point of route) {\n const radius = Math.max((point.width ?? 0.2) / 2, 0.3)\n bounds = mergeBounds(bounds, createBoundsFromCenter(point, radius))\n }\n\n return bounds\n}\n\nconst createBoundsFromComponent = (component: any): Bounds | null => {\n if (!component?.center) return null\n\n const width = Math.max(component.width ?? 0, 1.2)\n const height = Math.max(component.height ?? 0, 1.2)\n\n return {\n minX: component.center.x - width / 2,\n maxX: component.center.x + width / 2,\n minY: component.center.y - height / 2,\n maxY: component.center.y + height / 2,\n }\n}\n\nconst createBoardBounds = (board: any): Bounds | null => {\n if (\n !board?.center ||\n typeof board.width !== \"number\" ||\n typeof board.height !== \"number\"\n ) {\n return null\n }\n\n return {\n minX: board.center.x - board.width / 2,\n maxX: board.center.x + board.width / 2,\n minY: board.center.y - board.height / 2,\n maxY: board.center.y + board.height / 2,\n }\n}\n\nconst expandBounds = (bounds: Bounds, padding: number): Bounds => ({\n minX: bounds.minX - padding,\n maxX: bounds.maxX + padding,\n minY: bounds.minY - padding,\n maxY: bounds.maxY + padding,\n})\n\nconst createBoundsFromPoints = (\n points: Point[],\n radius = 0.35,\n): Bounds | null => {\n const bounds = getBoundsFromPoints(points)\n if (!bounds) return null\n return expandBounds(bounds, radius)\n}\n\nconst getErrorFocusCenter = ({\n error,\n tracesById,\n portsById,\n viasById,\n componentsById,\n}: {\n error: any\n} & ErrorPreviewElementIndexes): Point | null => {\n if (error.center) return error.center\n if (error.pcb_center) return error.pcb_center\n if (error.component_center) return error.component_center\n\n if (error.pcb_via_ids?.length) {\n const vias = error.pcb_via_ids\n .map((pcbViaId: string) => viasById.get(pcbViaId))\n .filter(Boolean)\n\n if (vias.length > 0) {\n return {\n x: vias.reduce((sum: number, via: any) => sum + via.x, 0) / vias.length,\n y: vias.reduce((sum: number, via: any) => sum + via.y, 0) / vias.length,\n }\n }\n }\n\n if (error.pcb_port_ids?.length) {\n const ports = error.pcb_port_ids\n .map((pcbPortId: string) => portsById.get(pcbPortId))\n .filter(Boolean)\n\n if (ports.length > 0) {\n return {\n x:\n ports.reduce((sum: number, port: any) => sum + port.x, 0) /\n ports.length,\n y:\n ports.reduce((sum: number, port: any) => sum + port.y, 0) /\n ports.length,\n }\n }\n }\n\n if (error.pcb_trace_id) {\n const trace = tracesById.get(error.pcb_trace_id)\n if (trace?.route?.length) {\n const middleIndex = Math.floor(trace.route.length / 2)\n return {\n x: trace.route[middleIndex].x,\n y: trace.route[middleIndex].y,\n }\n }\n }\n\n if (error.pcb_component_id) {\n return componentsById.get(error.pcb_component_id)?.center ?? null\n }\n\n return null\n}\n\nexport const getErrorFocusPoint = ({\n error,\n indexes,\n}: {\n error: any\n indexes: ErrorPreviewElementIndexes\n}): Point | null =>\n getErrorFocusCenter({\n error,\n ...indexes,\n })\n\nconst getComponentBoundaryViolationBounds = ({\n error,\n boardsById,\n}: {\n error: any\n boardsById: Map<string, any>\n}): Bounds | null => {\n if (!error.component_bounds || !error.pcb_board_id) return null\n\n const boardBounds = createBoardBounds(boardsById.get(error.pcb_board_id))\n if (!boardBounds) return null\n\n const componentBounds = error.component_bounds\n const violationPoints: Point[] = []\n\n if (componentBounds.min_x < boardBounds.minX) {\n violationPoints.push({\n x: boardBounds.minX,\n y: Math.max(componentBounds.min_y, boardBounds.minY),\n })\n violationPoints.push({\n x: boardBounds.minX,\n y: Math.min(componentBounds.max_y, boardBounds.maxY),\n })\n }\n\n if (componentBounds.max_x > boardBounds.maxX) {\n violationPoints.push({\n x: boardBounds.maxX,\n y: Math.max(componentBounds.min_y, boardBounds.minY),\n })\n violationPoints.push({\n x: boardBounds.maxX,\n y: Math.min(componentBounds.max_y, boardBounds.maxY),\n })\n }\n\n if (componentBounds.min_y < boardBounds.minY) {\n violationPoints.push({\n x: Math.max(componentBounds.min_x, boardBounds.minX),\n y: boardBounds.minY,\n })\n violationPoints.push({\n x: Math.min(componentBounds.max_x, boardBounds.maxX),\n y: boardBounds.minY,\n })\n }\n\n if (componentBounds.max_y > boardBounds.maxY) {\n violationPoints.push({\n x: Math.max(componentBounds.min_x, boardBounds.minX),\n y: boardBounds.maxY,\n })\n violationPoints.push({\n x: Math.min(componentBounds.max_x, boardBounds.maxX),\n y: boardBounds.maxY,\n })\n }\n\n return createBoundsFromPoints(violationPoints, 0.3)\n}\n\nconst nonZoomableErrorTypes = new Set([\n \"source_failed_to_create_component_error\",\n])\n\nexport const getErrorPreviewBounds = ({\n error,\n indexes,\n}: {\n error: any\n indexes: ErrorPreviewElementIndexes\n}): Bounds | null => {\n if (\n nonZoomableErrorTypes.has(error.error_type) ||\n nonZoomableErrorTypes.has(error.type)\n ) {\n return null\n }\n\n let bounds: Bounds | null = null\n const focusCenter = getErrorFocusCenter({\n error,\n ...indexes,\n })\n\n if (focusCenter) {\n bounds = mergeBounds(bounds, createBoundsFromCenter(focusCenter, 0.35))\n }\n\n if (error.error_type === \"pcb_component_outside_board_error\") {\n bounds = mergeBounds(\n bounds,\n getComponentBoundaryViolationBounds({\n error,\n boardsById: indexes.boardsById,\n }),\n )\n } else if (error.component_bounds && !focusCenter) {\n bounds = mergeBounds(bounds, {\n minX: error.component_bounds.min_x,\n maxX: error.component_bounds.max_x,\n minY: error.component_bounds.min_y,\n maxY: error.component_bounds.max_y,\n })\n }\n\n if (error.center && !focusCenter) {\n bounds = mergeBounds(bounds, createBoundsFromCenter(error.center))\n }\n\n if (error.pcb_center && !focusCenter) {\n bounds = mergeBounds(bounds, createBoundsFromCenter(error.pcb_center))\n }\n\n if (error.component_center && !focusCenter) {\n bounds = mergeBounds(bounds, createBoundsFromCenter(error.component_center))\n }\n\n if (error.pcb_port_ids && !focusCenter) {\n for (const pcbPortId of error.pcb_port_ids) {\n const port = indexes.portsById.get(pcbPortId)\n if (port) {\n bounds = mergeBounds(\n bounds,\n createBoundsFromCenter({ x: port.x, y: port.y }, 0.4),\n )\n }\n }\n }\n\n if (error.pcb_trace_id && !focusCenter) {\n const trace = indexes.tracesById.get(error.pcb_trace_id)\n if (trace?.route) {\n bounds = mergeBounds(bounds, createBoundsFromRoute(trace.route))\n }\n }\n\n if (error.pcb_via_ids) {\n for (const pcbViaId of error.pcb_via_ids) {\n const via = indexes.viasById.get(pcbViaId)\n if (via) {\n bounds = mergeBounds(\n bounds,\n createBoundsFromCenter(\n { x: via.x, y: via.y },\n Math.max((via.outer_diameter ?? 0.5) / 2, 0.28),\n ),\n )\n }\n }\n }\n\n if (error.pcb_component_id && !focusCenter) {\n bounds = mergeBounds(\n bounds,\n createBoundsFromComponent(\n indexes.componentsById.get(error.pcb_component_id),\n ),\n )\n }\n\n if (error.pcb_component_ids && !focusCenter) {\n for (const pcbComponentId of error.pcb_component_ids) {\n bounds = mergeBounds(\n bounds,\n createBoundsFromComponent(indexes.componentsById.get(pcbComponentId)),\n )\n }\n }\n\n return bounds\n}\n\nexport const createTransformForBounds = ({\n bounds,\n width,\n height,\n}: {\n bounds: Bounds\n width: number\n height: number\n}): Matrix => {\n const center = {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n }\n const targetWidth = Math.max(bounds.maxX - bounds.minX, 0.8) + 1.4\n const targetHeight = Math.max(bounds.maxY - bounds.minY, 0.8) + 1.4\n const scaleFactor =\n Math.min(width / targetWidth, height / targetHeight, 240) * 0.92\n\n return compose(\n translate(width / 2, height / 2),\n scale(scaleFactor, -scaleFactor, 0, 0),\n translate(-center.x, -center.y),\n )\n}\n\nexport const getRelatedIdsForError = (error: any): string[] => {\n const relatedIds = new Set<string>()\n\n if (error.pcb_trace_id) {\n relatedIds.add(error.pcb_trace_id)\n }\n\n for (const pcbPortId of error.pcb_port_ids ?? []) {\n relatedIds.add(pcbPortId)\n }\n\n for (const pcbViaId of error.pcb_via_ids ?? []) {\n relatedIds.add(pcbViaId)\n }\n\n if (error.pcb_component_id) {\n relatedIds.add(error.pcb_component_id)\n }\n\n for (const pcbComponentId of error.pcb_component_ids ?? []) {\n relatedIds.add(pcbComponentId)\n }\n\n return [...relatedIds]\n}\n","export const getErrorId = (error: any, index: number): string => {\n const explicitIdKeys = [\n \"pcb_trace_error_id\",\n \"pcb_via_clearance_error_id\",\n \"pcb_component_outside_board_error_id\",\n \"source_failed_to_create_component_error_id\",\n \"pcb_error_id\",\n ]\n\n for (const key of explicitIdKeys) {\n if (typeof error?.[key] === \"string\" && error[key].length > 0) {\n return error[key]\n }\n }\n\n for (const [key, value] of Object.entries(error ?? {})) {\n if (\n key.endsWith(\"_error_id\") &&\n typeof value === \"string\" &&\n value.length > 0\n ) {\n return value\n }\n }\n\n return `error_${index}_${error?.error_type}_${error?.message?.slice(0, 20)}`\n}\n\nexport const findErrorElementById = (\n elements: Array<{ type?: string }>,\n errorId: string | null | undefined,\n) => {\n if (!errorId) return null\n\n return (\n elements.find((element, index) => {\n if (!element.type?.includes(\"error\")) return false\n return getErrorId(element, index) === errorId\n }) ?? null\n )\n}\n","import type { Matrix } from \"transformation-matrix\"\n\nconst easeOutCubic = (progress: number) => 1 - (1 - progress) ** 3\n\nconst interpolateTransform = (\n start: Matrix,\n end: Matrix,\n progress: number,\n): Matrix => ({\n a: start.a + (end.a - start.a) * progress,\n b: start.b + (end.b - start.b) * progress,\n c: start.c + (end.c - start.c) * progress,\n d: start.d + (end.d - start.d) * progress,\n e: start.e + (end.e - start.e) * progress,\n f: start.f + (end.f - start.f) * progress,\n})\n\nexport const cancelTransformAnimation = (animationFrameId: number | null) => {\n if (animationFrameId !== null) {\n window.cancelAnimationFrame(animationFrameId)\n }\n}\n\nexport const animateTransform = ({\n startTransform,\n endTransform,\n durationMs,\n onUpdate,\n setAnimationFrameId,\n onComplete,\n}: {\n startTransform: Matrix\n endTransform: Matrix\n durationMs: number\n onUpdate: (transform: Matrix) => void\n setAnimationFrameId: (animationFrameId: number | null) => void\n onComplete?: () => void\n}): number => {\n const startTime = performance.now()\n\n const tick = (timestamp: number): void => {\n const elapsed = timestamp - startTime\n const rawProgress = Math.min(1, elapsed / durationMs)\n const easedProgress = easeOutCubic(rawProgress)\n\n onUpdate(interpolateTransform(startTransform, endTransform, easedProgress))\n\n if (rawProgress < 1) {\n setAnimationFrameId(window.requestAnimationFrame(tick))\n return\n }\n\n setAnimationFrameId(null)\n onComplete?.()\n }\n\n const animationFrameId = window.requestAnimationFrame(tick)\n setAnimationFrameId(animationFrameId)\n return animationFrameId\n}\n","import type { ManualEditEvent } from \"@tscircuit/props\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport { getFullConnectivityMapFromCircuitJson } from \"circuit-json-to-connectivity-map\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { convertElementToPrimitives } from \"lib/convert-element-to-primitive\"\nimport type { GridConfig, Primitive } from \"lib/types\"\nimport { addInteractionMetadataToPrimitives } from \"lib/util/addInteractionMetadataToPrimitives\"\nimport {\n buildErrorPreviewElementIndexes,\n createTransformForBounds,\n getErrorPreviewBounds,\n getRelatedIdsForError,\n} from \"lib/util/error-preview\"\nimport { findErrorElementById, getErrorId } from \"lib/util/get-error-id\"\nimport {\n animateTransform,\n cancelTransformAnimation,\n} from \"lib/util/transform-animation\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\nimport { CanvasPrimitiveRenderer } from \"./CanvasPrimitiveRenderer\"\nimport { DebugGraphicsOverlay } from \"./DebugGraphicsOverlay\"\nimport { type BoundsSelection, DimensionOverlay } from \"./DimensionOverlay\"\nimport { EditPlacementOverlay } from \"./EditPlacementOverlay\"\nimport { ErrorOverlay } from \"./ErrorOverlay\"\nimport { MouseElementTracker } from \"./MouseElementTracker\"\nimport { PcbGroupOverlay } from \"./PcbGroupOverlay\"\nimport { RatsNestOverlay } from \"./RatsNestOverlay\"\nimport { ToolbarOverlay } from \"./ToolbarOverlay\"\nimport { WarningGraphicsOverlay } from \"./WarningGraphicsOverlay\"\n\nexport interface CanvasElementsRendererProps {\n elements: AnyCircuitElement[]\n debugGraphics?: GraphicsObject | null\n transform?: Matrix\n setTransform?: (transform: Matrix) => void\n width?: number\n height?: number\n grid?: GridConfig\n allowEditing: boolean\n focusOnHover?: boolean\n onBoundsSelected?: (bounds: BoundsSelection) => void\n cancelPanDrag: () => void\n onCreateEditEvent: (event: ManualEditEvent) => void\n onModifyEditEvent: (event: Partial<ManualEditEvent>) => void\n}\n\nexport const CanvasElementsRenderer = (props: CanvasElementsRendererProps) => {\n const { transform, elements } = props\n const {\n hoveredErrorId,\n focusedErrorId,\n isShowingCopperPours,\n selectedLayer,\n } = useGlobalStore((state) => ({\n hoveredErrorId: state.hovered_error_id,\n focusedErrorId: state.focused_error_id,\n isShowingCopperPours: state.is_showing_copper_pours,\n selectedLayer: state.selected_layer,\n }))\n const activeErrorId = focusedErrorId ?? hoveredErrorId\n\n const elementsToRender = useMemo(\n () =>\n isShowingCopperPours\n ? elements\n : elements.filter((elm) => elm.type !== \"pcb_copper_pour\"),\n [elements, isShowingCopperPours],\n )\n\n const [primitivesWithoutInteractionMetadata, connectivityMap] =\n useMemo(() => {\n const primitivesWithoutInteractionMetadata = elementsToRender.flatMap(\n (elm) => convertElementToPrimitives(elm, props.elements),\n )\n const connectivityMap = getFullConnectivityMapFromCircuitJson(\n props.elements as any,\n )\n return [primitivesWithoutInteractionMetadata, connectivityMap]\n }, [elementsToRender, props.elements])\n\n const [hoverState, setHoverState] = useState({\n drawingObjectIdsWithMouseOver: new Set<string>(),\n primitiveIdsInMousedOverNet: [] as string[],\n })\n const [hoveredComponentIds, setHoveredComponentIds] = useState<string[]>([])\n const currentTransformRef = useRef<Matrix | null>(transform ?? null)\n const zoomAnimationFrameRef = useRef<number | null>(null)\n\n const elementIndexes = useMemo(\n () => buildErrorPreviewElementIndexes(elements),\n [elements],\n )\n\n const errorRelatedIds = useMemo(() => {\n if (!activeErrorId) return []\n\n const errorElements = elements.filter((el): el is any =>\n el.type.includes(\"error\"),\n )\n\n const activeError = errorElements.find((el, index) => {\n return getErrorId(el, index) === activeErrorId\n })\n\n if (!activeError) return []\n\n return getRelatedIdsForError(activeError)\n }, [activeErrorId, elements])\n\n useEffect(() => {\n if (transform) {\n currentTransformRef.current = transform\n }\n }, [transform])\n\n useEffect(() => {\n return () => {\n cancelTransformAnimation(zoomAnimationFrameRef.current)\n }\n }, [])\n\n useEffect(() => {\n if (!props.width || !props.height || !props.setTransform || !focusedErrorId)\n return\n\n const focusedError = findErrorElementById(elements, focusedErrorId)\n\n if (!focusedError) return\n\n const previewBounds = getErrorPreviewBounds({\n error: focusedError,\n indexes: elementIndexes,\n })\n\n if (!previewBounds) return\n\n const startTransform = currentTransformRef.current ?? transform\n if (!startTransform) return\n\n const targetTransform = createTransformForBounds({\n bounds: previewBounds,\n width: props.width,\n height: props.height,\n })\n\n cancelTransformAnimation(zoomAnimationFrameRef.current)\n\n animateTransform({\n startTransform,\n endTransform: targetTransform,\n durationMs: 420,\n setAnimationFrameId: (animationFrameId) => {\n zoomAnimationFrameRef.current = animationFrameId\n },\n onUpdate: (nextTransform) => {\n currentTransformRef.current = nextTransform\n props.setTransform?.(nextTransform)\n },\n })\n }, [\n focusedErrorId,\n elements,\n elementIndexes,\n props.height,\n props.setTransform,\n props.width,\n ])\n\n const primitives = useMemo(() => {\n const combinedPrimitiveIds = [\n ...hoverState.primitiveIdsInMousedOverNet,\n ...errorRelatedIds,\n ]\n\n return addInteractionMetadataToPrimitives({\n primitivesWithoutInteractionMetadata,\n drawingObjectIdsWithMouseOver: hoverState.drawingObjectIdsWithMouseOver,\n primitiveIdsInMousedOverNet: combinedPrimitiveIds,\n })\n }, [primitivesWithoutInteractionMetadata, hoverState, errorRelatedIds])\n\n const onMouseOverPrimitives = useCallback(\n (primitivesHoveredOver: Primitive[]) => {\n const primitiveIdsInMousedOverNet: string[] = []\n for (const primitive of primitivesHoveredOver) {\n if (primitive._element) {\n const connectedPrimitivesList = connectivityMap.getNetConnectedToId(\n \"pcb_port_id\" in primitive._element\n ? primitive._element?.pcb_port_id!\n : \"pcb_trace_id\" in primitive._element\n ? primitive._element?.pcb_trace_id!\n : \"\",\n )\n primitiveIdsInMousedOverNet.push(\n ...connectivityMap.getIdsConnectedToNet(connectedPrimitivesList!),\n )\n }\n }\n\n const drawingObjectIdsWithMouseOver = new Set(\n primitivesHoveredOver.map((p) => p._pcb_drawing_object_id),\n )\n\n setHoverState({\n drawingObjectIdsWithMouseOver,\n primitiveIdsInMousedOverNet,\n })\n\n const componentIds = primitivesHoveredOver\n .map((primitive) => {\n if (\n primitive._parent_pcb_component?.type === \"pcb_component\" &&\n primitive._parent_pcb_component.pcb_component_id\n ) {\n return primitive._parent_pcb_component.pcb_component_id\n }\n if (\n primitive._element?.type === \"pcb_component\" &&\n primitive._element.pcb_component_id\n ) {\n return primitive._element.pcb_component_id\n }\n return null\n })\n .filter((id): id is string => Boolean(id))\n\n setHoveredComponentIds(Array.from(new Set(componentIds)))\n },\n [connectivityMap],\n )\n\n return (\n <MouseElementTracker\n elements={elementsToRender}\n transform={transform}\n primitives={primitivesWithoutInteractionMetadata}\n selectedLayer={selectedLayer}\n onMouseHoverOverPrimitives={onMouseOverPrimitives}\n >\n <EditPlacementOverlay\n disabled={!props.allowEditing}\n transform={transform}\n soup={elements}\n cancelPanDrag={props.cancelPanDrag}\n onCreateEditEvent={props.onCreateEditEvent}\n onModifyEditEvent={props.onModifyEditEvent}\n >\n <DimensionOverlay\n transform={transform!}\n focusOnHover={props.focusOnHover}\n primitives={primitivesWithoutInteractionMetadata}\n onBoundsSelected={props.onBoundsSelected}\n cancelPanDrag={props.cancelPanDrag}\n >\n <ToolbarOverlay elements={elements}>\n <ErrorOverlay transform={transform} elements={elements}>\n <RatsNestOverlay transform={transform} soup={elements}>\n <PcbGroupOverlay\n transform={transform}\n elements={elements}\n hoveredComponentIds={hoveredComponentIds}\n >\n <DebugGraphicsOverlay\n transform={transform}\n debugGraphics={props.debugGraphics}\n >\n <WarningGraphicsOverlay\n transform={transform}\n elements={elements}\n >\n <CanvasPrimitiveRenderer\n transform={transform}\n primitives={primitives}\n elements={elementsToRender}\n width={props.width}\n height={props.height}\n grid={props.grid}\n />\n </WarningGraphicsOverlay>\n </DebugGraphicsOverlay>\n </PcbGroupOverlay>\n </RatsNestOverlay>\n </ErrorOverlay>\n </ToolbarOverlay>\n </DimensionOverlay>\n </EditPlacementOverlay>\n </MouseElementTracker>\n )\n}\n","import type { Rotation } from \"circuit-json\"\nimport colorParser from \"color\"\nimport type { BRepShape, Ring } from \"lib/types\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n identity,\n inverse,\n translate,\n} from \"transformation-matrix\"\nimport colors from \"./colors\"\nimport { scaleOnly } from \"./util/scale-only\"\nimport { zIndexMap } from \"./util/z-index-map\"\n\nexport interface Aperture {\n shape: \"circle\" | \"square\"\n size: number\n opacity: number\n mode: \"add\" | \"subtract\"\n fontSize: number\n color: string\n layer: string\n}\n\nexport const LAYER_NAME_TO_COLOR = {\n // Standard colors, you shouldn't use these except for testing\n red: \"red\",\n black: \"black\",\n green: \"green\",\n board: \"rgb(255, 255, 255)\",\n other: \"#eee\",\n // TODO more builtin html colors\n\n // Common eagle names\n top: colors.board.copper.f,\n inner1: colors.board.copper.in1,\n inner2: colors.board.copper.in2,\n inner3: colors.board.copper.in3,\n inner4: colors.board.copper.in4,\n inner5: colors.board.copper.in5,\n inner6: colors.board.copper.in6,\n inner7: colors.board.copper.in7,\n inner8: colors.board.copper.in8,\n\n bottom: colors.board.copper.b,\n drill: colors.board.anchor,\n keepout: colors.board.background,\n tkeepout: colors.board.b_crtyd,\n tplace: colors.board.b_silks,\n\n top_courtyard: colors.board.f_crtyd,\n bottom_courtyard: colors.board.b_crtyd,\n\n top_silkscreen: colors.board.f_silks,\n bottom_silkscreen: colors.board.b_silks,\n\n top_fabrication: colors.board.f_fab,\n bottom_fabrication: colors.board.b_fab,\n\n soldermask_top: colors.board.soldermask.top,\n soldermask_bottom: colors.board.soldermask.bottom,\n soldermask_with_copper_top: colors.board.soldermaskWithCopper.top,\n soldermask_with_copper_bottom: colors.board.soldermaskWithCopper.bottom,\n\n bottom_notes: colors.board.user_2,\n top_notes: colors.board.user_2,\n\n ...(colors.board as any),\n}\n\nexport type LayerNameForColor = keyof typeof LAYER_NAME_TO_COLOR\n\nexport const DEFAULT_DRAW_ORDER = [\n \"board\",\n \"bottom\",\n \"soldermask_bottom\",\n \"bottom_silkscreen\",\n \"top\",\n \"soldermask_top\",\n \"bottom_courtyard\",\n \"bottom_fabrication\",\n \"top_courtyard\",\n \"top_fabrication\",\n \"edge_cuts\",\n \"top_silkscreen\",\n] as const\n\nexport const FILL_TYPES = {\n 0: \"Empty\",\n 1: \"Solid\",\n 2: \"Line\",\n 3: \"LtSlash\",\n 4: \"Slash\",\n 5: \"BkSlash\",\n 6: \"LtBkSlash\",\n 7: \"Hatch\",\n 8: \"XHatch\",\n 9: \"Interleave\",\n 10: \"WideDot\",\n 11: \"CloseDot\",\n 12: \"Stipple1\",\n 13: \"Stipple2\",\n 14: \"Stipple3\",\n 15: \"Stipple4\",\n}\n\nexport class Drawer {\n canvasLayerMap: Record<string, HTMLCanvasElement>\n ctxLayerMap: Record<string, CanvasRenderingContext2D>\n // @ts-ignore this.equip({}) handles constructor assignment\n aperture: Aperture\n transform: Matrix\n foregroundLayer = \"top\"\n lastPoint: { x: number; y: number }\n\n constructor(canvasLayerMap: Record<string, HTMLCanvasElement>) {\n this.canvasLayerMap = canvasLayerMap\n this.ctxLayerMap = Object.fromEntries(\n Object.entries(canvasLayerMap).map(([name, canvas]) => [\n name,\n canvas.getContext(\"2d\")!,\n ]),\n )\n this.transform = identity()\n // positive is up (cartesian)\n this.transform.d *= -1\n this.transform = compose(this.transform, translate(0, -500))\n this.lastPoint = { x: 0, y: 0 }\n this.equip({})\n }\n\n clear() {\n for (const ctx of Object.values(this.ctxLayerMap)) {\n ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)\n }\n }\n\n equip(aperture: Partial<Aperture>) {\n this.aperture = {\n fontSize: 0,\n shape: \"circle\",\n mode: \"add\",\n size: 0,\n color: \"red\",\n layer: \"top\",\n opacity: this.foregroundLayer === aperture.color ? 1 : 0.5,\n ...aperture,\n }\n }\n\n drawMeshPattern(\n x: number,\n y: number,\n width: number,\n height: number,\n spacing: number,\n angle = 45,\n ) {\n const ctx = this.getLayerCtx()\n const [x1, y1] = applyToPoint(this.transform, [x, y])\n const [x2, y2] = applyToPoint(this.transform, [x + width, y + height])\n const spacing$ = scaleOnly(this.transform, spacing)\n\n // Set line properties for the mesh\n ctx.lineWidth = 1\n ctx.strokeStyle = this.aperture.color\n\n const drawLines = (angle: number) => {\n const sin = Math.sin(angle)\n const cos = Math.cos(angle)\n const diag = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)\n\n for (let i = -diag; i <= diag; i += spacing$) {\n ctx.beginPath()\n ctx.moveTo(x1 + i * cos - diag * sin, y1 + i * sin + diag * cos)\n ctx.lineTo(x1 + i * cos + diag * sin, y1 + i * sin - diag * cos)\n ctx.stroke()\n }\n }\n\n // Draw first set of parallel lines\n drawLines((angle * Math.PI) / 180)\n // Draw second set of parallel lines (perpendicular to the first set)\n drawLines(((angle + 90) * Math.PI) / 180)\n }\n\n rect({\n x,\n y,\n w,\n h,\n mesh_fill,\n is_filled = true,\n has_stroke,\n is_stroke_dashed,\n stroke_width,\n roundness,\n }: {\n x: number\n y: number\n w: number\n h: number\n mesh_fill?: boolean\n is_filled?: boolean\n has_stroke?: boolean\n is_stroke_dashed?: boolean\n stroke_width?: number\n roundness?: number\n }) {\n const [x1$, y1$] = applyToPoint(this.transform, [x - w / 2, y - h / 2])\n const [x2$, y2$] = applyToPoint(this.transform, [x + w / 2, y + h / 2])\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n const radius$ = roundness ? scaleOnly(this.transform, roundness) : 0\n\n const shouldDrawStroke =\n has_stroke === undefined ? is_filled === false : has_stroke\n\n if (mesh_fill) {\n ctx.save()\n ctx.beginPath()\n if (radius$ > 0 && ctx.roundRect) {\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n } else {\n ctx.rect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n ctx.clip()\n\n // Draw the mesh pattern\n this.drawMeshPattern(x - w / 2, y - h / 2, w, h, 0.15) // Adjust spacing as needed\n\n ctx.restore()\n\n // Draw the outline\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.stroke()\n } else {\n ctx.strokeRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n } else {\n if (is_filled !== false) {\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.fill()\n } else {\n ctx.fillRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n }\n\n if (shouldDrawStroke) {\n const originalLineWidth = ctx.lineWidth\n if (stroke_width !== undefined) {\n ctx.lineWidth = scaleOnly(this.transform, stroke_width)\n }\n if (is_stroke_dashed) {\n let dashPattern: number[] = []\n\n const scale = Math.abs(this.transform.a)\n if (scale > 0) {\n const SEGMENT_LENGTH = 0.1\n const dash = SEGMENT_LENGTH * scale\n const gap = dash * 1.3\n\n if (dash > 0.5) {\n dashPattern = [dash, gap]\n }\n }\n ctx.setLineDash(dashPattern)\n }\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.stroke()\n } else {\n ctx.strokeRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n if (is_stroke_dashed) {\n ctx.setLineDash([]) // Reset dash pattern\n }\n if (stroke_width !== undefined) {\n ctx.lineWidth = originalLineWidth\n }\n }\n }\n }\n\n rotatedRect(\n x: number,\n y: number,\n w: number,\n h: number,\n ccw_rotation: Rotation,\n roundness?: number,\n mesh_fill?: boolean,\n ) {\n const ctx = this.getLayerCtx()\n this.applyAperture()\n\n const [x1$, y1$] = applyToPoint(this.transform, [x - w / 2, y - h / 2])\n const [x2$, y2$] = applyToPoint(this.transform, [x + w / 2, y + h / 2])\n const radius$ = roundness ? scaleOnly(this.transform, roundness) : 0\n\n ctx.save()\n\n const [centerX, centerY] = applyToPoint(this.transform, [x, y])\n ctx.translate(centerX, centerY)\n const cw_rotation = 360 - ccw_rotation\n if (ccw_rotation) ctx.rotate((cw_rotation * Math.PI) / 180)\n ctx.translate(-centerX, -centerY)\n\n if (mesh_fill) {\n ctx.beginPath()\n if (radius$ > 0 && ctx.roundRect) {\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n } else {\n ctx.rect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n ctx.clip()\n\n this.drawMeshPattern(x - w / 2, y - h / 2, w, h, 0.15)\n\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.stroke()\n } else {\n ctx.strokeRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n } else {\n if (radius$ > 0 && ctx.roundRect) {\n ctx.beginPath()\n ctx.roundRect(x1$, y1$, x2$ - x1$, y2$ - y1$, radius$)\n ctx.fill()\n } else {\n ctx.fillRect(x1$, y1$, x2$ - x1$, y2$ - y1$)\n }\n }\n\n ctx.restore()\n }\n\n rotatedPill(\n x: number,\n y: number,\n w: number,\n h: number,\n ccw_rotation: Rotation,\n ) {\n const ctx = this.getLayerCtx()\n this.applyAperture()\n\n ctx.save()\n\n const [centerX, centerY] = applyToPoint(this.transform, [x, y])\n ctx.translate(centerX, centerY)\n const cw_rotation = 360 - ccw_rotation\n if (ccw_rotation) ctx.rotate((cw_rotation * Math.PI) / 180)\n ctx.translate(-centerX, -centerY)\n\n this.pill(x, y, w, h)\n\n ctx.restore()\n }\n\n circle(\n x: number,\n y: number,\n r: number,\n mesh_fill?: boolean,\n is_filled = true,\n ) {\n const r$ = scaleOnly(this.transform, r)\n const [x$, y$] = applyToPoint(this.transform, [x, y])\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n if (mesh_fill) {\n ctx.save()\n ctx.beginPath()\n ctx.arc(x$, y$, r$, 0, 2 * Math.PI)\n ctx.clip()\n\n // Draw the mesh pattern\n // We need to cover the entire circular area, so we use a square that fully encloses the circle\n this.drawMeshPattern(x - r, y - r, r * 2, r * 2, 0.15) // Adjust spacing as needed\n\n ctx.restore()\n\n // Draw the outline\n ctx.beginPath()\n ctx.arc(x$, y$, r$, 0, 2 * Math.PI)\n ctx.stroke()\n } else {\n ctx.beginPath()\n ctx.arc(x$, y$, r$, 0, 2 * Math.PI)\n ctx.fill()\n }\n }\n\n oval(x: number, y: number, rx: number, ry: number) {\n const rx$ = scaleOnly(this.transform, rx)\n const ry$ = scaleOnly(this.transform, ry)\n const [x$, y$] = applyToPoint(this.transform, [x, y])\n this.applyAperture()\n const ctx = this.getLayerCtx()\n ctx.beginPath()\n ctx.ellipse(x$, y$, rx$, ry$, 0, 0, 2 * Math.PI)\n ctx.fill()\n ctx.closePath()\n }\n\n pill(x: number, y: number, w: number, h: number) {\n const [x$, y$] = applyToPoint(this.transform, [x - w / 2, y + h / 2])\n const width$ = scaleOnly(this.transform, w)\n const height$ = scaleOnly(this.transform, h)\n const radius = Math.min(width$, height$) / 2\n this.applyAperture()\n const ctx = this.getLayerCtx()\n ctx.beginPath()\n ctx.arc(x$ + radius, y$ + radius, radius, Math.PI, Math.PI * 1.5)\n ctx.arc(x$ + width$ - radius, y$ + radius, radius, Math.PI * 1.5, 0)\n ctx.arc(\n x$ + width$ - radius,\n y$ + height$ - radius,\n radius,\n 0,\n Math.PI * 0.5,\n )\n ctx.arc(x$ + radius, y$ + height$ - radius, radius, Math.PI * 0.5, Math.PI)\n ctx.fill()\n ctx.closePath()\n }\n\n polygon(points: { x: number; y: number }[]) {\n if (points.length < 3) {\n return\n }\n\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n // Transform all points\n const transformedPoints = points.map((point) =>\n applyToPoint(this.transform, [point.x, point.y]),\n )\n\n // Draw the filled polygon\n ctx.beginPath()\n ctx.moveTo(transformedPoints[0][0], transformedPoints[0][1])\n for (let i = 1; i < transformedPoints.length; i++) {\n ctx.lineTo(transformedPoints[i][0], transformedPoints[i][1])\n }\n ctx.closePath()\n ctx.fill(\"evenodd\")\n\n // Draw the outline only if we have a non-zero stroke width.\n // Calling ctx.stroke() with a zero width will re-use the previous\n // stroke width which can cause the polygon to suddenly expand when\n // other primitives (like hovered rectangles) change the aperture size.\n const lineWidth = scaleOnly(this.transform, this.aperture.size)\n if (lineWidth > 0) {\n ctx.lineWidth = lineWidth\n ctx.stroke()\n }\n }\n\n /* NOTE: This is not gerber compatible */\n debugText(text: string, x: number, y: number) {\n const [x$, y$] = applyToPoint(this.transform, [x, y])\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n ctx.font = \"10px sans-serif\"\n ctx.fillText(text, x$, y$)\n }\n\n getLayerCtx() {\n const ctx = this.ctxLayerMap[this.aperture.layer]\n if (!ctx) {\n throw new Error(`No context for layer \"${this.aperture.layer}\"`)\n }\n return ctx\n }\n\n /**\n * Iterate over each canvas and set the z index based on the layer order, but\n * always render the foreground layer on top.\n *\n * Also: Set the opacity of every non-foreground layer to 0.5\n */\n orderAndFadeLayers() {\n const { canvasLayerMap, foregroundLayer } = this\n const innerLayers = Object.keys(canvasLayerMap)\n .filter((layer) => /^inner\\d+$/.test(layer))\n .sort(\n (a, b) =>\n Number(b.slice(\"inner\".length)) - Number(a.slice(\"inner\".length)),\n )\n const defaultDrawOrder = [\n \"board\",\n ...innerLayers,\n ...DEFAULT_DRAW_ORDER.filter((layer) => layer !== \"board\"),\n ]\n const associatedSoldermask =\n foregroundLayer === \"top\"\n ? \"soldermask_top\"\n : foregroundLayer === \"bottom\"\n ? \"soldermask_bottom\"\n : undefined\n const associatedSilkscreen =\n foregroundLayer === \"top\"\n ? \"top_silkscreen\"\n : foregroundLayer === \"bottom\"\n ? \"bottom_silkscreen\"\n : undefined\n const associatedNotes =\n foregroundLayer === \"top\"\n ? \"top_notes\"\n : foregroundLayer === \"bottom\"\n ? \"bottom_notes\"\n : undefined\n const associatedFabrication =\n foregroundLayer === \"top\"\n ? \"top_fabrication\"\n : foregroundLayer === \"bottom\"\n ? \"bottom_fabrication\"\n : undefined\n const associatedCourtyard =\n foregroundLayer === \"top\"\n ? \"top_courtyard\"\n : foregroundLayer === \"bottom\"\n ? \"bottom_courtyard\"\n : undefined\n\n const opaqueLayers = new Set<string>([\n foregroundLayer,\n \"drill\",\n \"edge_cuts\",\n \"other\",\n \"board\",\n ...(associatedSoldermask ? [associatedSoldermask] : []),\n ...(associatedSilkscreen ? [associatedSilkscreen] : []),\n ...(associatedNotes ? [associatedNotes] : []),\n ...(associatedFabrication ? [associatedFabrication] : []),\n ...(associatedCourtyard ? [associatedCourtyard] : []),\n ])\n\n const layersToShiftToTop = [\n foregroundLayer,\n \"edge_cuts\",\n ...(associatedSoldermask ? [associatedSoldermask] : []),\n ...(associatedSilkscreen ? [associatedSilkscreen] : []),\n ...(associatedNotes ? [associatedNotes] : []),\n ...(associatedFabrication ? [associatedFabrication] : []),\n ...(associatedCourtyard ? [associatedCourtyard] : []),\n ]\n\n const order = [\n ...defaultDrawOrder.filter((l) => !layersToShiftToTop.includes(l)),\n ...(foregroundLayer === \"drill\" ? [] : [foregroundLayer]),\n ...(associatedSoldermask ? [associatedSoldermask] : []),\n \"edge_cuts\",\n ...(associatedSilkscreen ? [associatedSilkscreen] : []),\n ...(associatedNotes ? [associatedNotes] : []),\n ...(associatedFabrication ? [associatedFabrication] : []),\n ...(associatedCourtyard ? [associatedCourtyard] : []),\n \"drill\",\n ]\n\n order.forEach((layer, i) => {\n const canvas = canvasLayerMap[layer]\n if (!canvas) return\n\n canvas.style.zIndex = `${zIndexMap.topLayer - (order.length - i)}`\n canvas.style.opacity = opaqueLayers.has(layer) ? \"1\" : \"0.5\"\n })\n }\n\n applyAperture() {\n const { transform, aperture } = this\n let { size, mode, color, fontSize, layer } = aperture\n if (!(layer in this.ctxLayerMap)) this.aperture.layer = \"other\"\n\n const ctx = this.getLayerCtx()\n if (!ctx) {\n throw new Error(`No context for layer \"${this.foregroundLayer}\"`)\n }\n if (!color) color = \"undefined\"\n ctx.lineWidth = scaleOnly(transform, size)\n ctx.lineCap = \"round\"\n\n if (mode === \"add\") {\n ctx.globalCompositeOperation = \"source-over\"\n let colorString = LAYER_NAME_TO_COLOR[color.toLowerCase()]\n if (!colorString)\n try {\n colorString = colorParser(color).rgb().toString()\n } catch (error) {\n console.warn(`Invalid color format: '${color}'`)\n colorString = \"white\"\n }\n\n ctx.fillStyle = colorString\n ctx.strokeStyle = colorString\n } else {\n ctx.globalCompositeOperation = \"destination-out\"\n ctx.fillStyle = \"rgba(0,0,0,1)\"\n ctx.strokeStyle = \"rgba(0,0,0,1)\"\n }\n ctx.font = `${scaleOnly(inverse(transform), fontSize)}px sans-serif`\n }\n\n moveTo(x: number, y: number) {\n this.lastPoint = { x, y }\n }\n lineTo(x: number, y: number) {\n const [x$, y$] = applyToPoint(this.transform, [x, y])\n const { size, shape, mode } = this.aperture\n const size$ = scaleOnly(this.transform, size)\n const { lastPoint } = this\n const lastPoint$ = applyToPoint(this.transform, lastPoint)\n\n this.applyAperture()\n const ctx = this.getLayerCtx()\n\n if (shape === \"square\")\n ctx.fillRect(\n lastPoint$.x - size$ / 2,\n lastPoint$.y - size$ / 2,\n size$,\n size$,\n )\n ctx.beginPath()\n ctx.moveTo(lastPoint$.x, lastPoint$.y)\n ctx.lineTo(x$, y$)\n\n ctx.stroke()\n ctx.closePath()\n\n if (shape === \"square\")\n ctx.fillRect(x$ - size$ / 2, y$ - size$ / 2, size$, size$)\n\n this.lastPoint = { x, y }\n }\n\n polygonWithArcs(brep: BRepShape) {\n const ctx = this.getLayerCtx()\n\n const processRing = (ring: Ring) => {\n if (ring.vertices.length === 0) return\n const startPoint = ring.vertices[0]\n const t_start_point = applyToPoint(this.transform, [\n startPoint.x,\n startPoint.y,\n ])\n ctx.moveTo(t_start_point[0], t_start_point[1])\n\n for (let i = 0; i < ring.vertices.length; i++) {\n const p1 = ring.vertices[i]\n const p2 = ring.vertices[(i + 1) % ring.vertices.length]\n\n if (p1.bulge && p1.bulge !== 0) {\n const bulge = p1.bulge\n\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n const chord = Math.sqrt(dx * dx + dy * dy)\n\n if (chord < 1e-9) {\n const t_p2 = applyToPoint(this.transform, [p2.x, p2.y])\n ctx.lineTo(t_p2[0], t_p2[1])\n continue\n }\n\n const angle = 4 * Math.atan(bulge)\n const radius = Math.abs(chord / (2 * Math.sin(angle / 2)))\n\n const mx = (p1.x + p2.x) / 2\n const my = (p1.y + p2.y) / 2\n\n const norm_dx = dx / chord\n const norm_dy = dy / chord\n\n const perp_vx = -norm_dy\n const perp_vy = norm_dx\n\n const dist_to_center = Math.sqrt(\n Math.max(0, radius * radius - (chord / 2) ** 2),\n )\n\n const cx = mx + dist_to_center * perp_vx * Math.sign(bulge)\n const cy = my + dist_to_center * perp_vy * Math.sign(bulge)\n\n const startAngle = Math.atan2(p1.y - cy, p1.x - cx)\n let endAngle = Math.atan2(p2.y - cy, p2.x - cx)\n\n if (bulge > 0 && endAngle < startAngle) {\n endAngle += 2 * Math.PI\n } else if (bulge < 0 && endAngle > startAngle) {\n endAngle -= 2 * Math.PI\n }\n\n const t_center = applyToPoint(this.transform, [cx, cy])\n const t_radius = scaleOnly(this.transform, radius)\n\n ctx.arc(\n t_center[0],\n t_center[1],\n t_radius,\n -startAngle,\n -endAngle,\n bulge > 0,\n )\n } else {\n const t_p2 = applyToPoint(this.transform, [p2.x, p2.y])\n ctx.lineTo(t_p2[0], t_p2[1])\n }\n }\n ctx.closePath()\n }\n\n ctx.beginPath()\n\n processRing(brep.outer_ring)\n if (brep.inner_rings) {\n for (const inner_ring of brep.inner_rings) {\n processRing(inner_ring)\n }\n }\n\n ctx.fill(\"evenodd\")\n }\n}\n","// Mix of Eagle Dark for schematics and KiCAD 2020 for PCBs\n// https://github.com/pointhi/kicad-color-schemes/blob/master/eagle-dark/eagle-dark.jsonO\n// https://github.com/pointhi/kicad-color-schemes/blob/master/kicad-2020/kicad_2020.json\nexport default {\n \"3d_viewer\": {\n background_bottom: \"rgb(102, 102, 128)\",\n background_top: \"rgb(204, 204, 230)\",\n board: \"rgb(51, 43, 23)\",\n copper: \"rgb(179, 156, 0)\",\n silkscreen_bottom: \"rgb(230, 230, 230)\",\n silkscreen_top: \"rgb(230, 230, 230)\",\n soldermask: \"rgb(20, 51, 36)\",\n solderpaste: \"rgb(128, 128, 128)\",\n },\n board: {\n anchor: \"rgb(255, 38, 226)\",\n aux_items: \"rgb(255, 255, 255)\",\n b_adhes: \"rgb(0, 0, 132)\",\n b_crtyd: \"rgb(38, 233, 255)\",\n b_fab: \"rgb(88, 93, 132)\",\n b_mask: \"rgba(2, 255, 238, 0.400)\",\n b_paste: \"rgb(0, 194, 194)\",\n b_silks: \"rgb(242, 237, 161)\",\n background: \"rgb(0, 16, 35)\",\n cmts_user: \"rgb(89, 148, 220)\",\n copper: {\n b: \"rgb(77, 127, 196)\",\n f: \"rgb(200, 52, 52)\",\n in1: \"rgb(127, 200, 127)\",\n in10: \"rgb(237, 124, 51)\",\n in11: \"rgb(91, 195, 235)\",\n in12: \"rgb(247, 111, 142)\",\n in13: \"rgb(167, 165, 198)\",\n in14: \"rgb(40, 204, 217)\",\n in15: \"rgb(232, 178, 167)\",\n in16: \"rgb(242, 237, 161)\",\n in17: \"rgb(237, 124, 51)\",\n in18: \"rgb(91, 195, 235)\",\n in19: \"rgb(247, 111, 142)\",\n in2: \"rgb(206, 125, 44)\",\n in20: \"rgb(167, 165, 198)\",\n in21: \"rgb(40, 204, 217)\",\n in22: \"rgb(232, 178, 167)\",\n in23: \"rgb(242, 237, 161)\",\n in24: \"rgb(237, 124, 51)\",\n in25: \"rgb(91, 195, 235)\",\n in26: \"rgb(247, 111, 142)\",\n in27: \"rgb(167, 165, 198)\",\n in28: \"rgb(40, 204, 217)\",\n in29: \"rgb(232, 178, 167)\",\n in3: \"rgb(79, 203, 203)\",\n in30: \"rgb(242, 237, 161)\",\n in4: \"rgb(219, 98, 139)\",\n in5: \"rgb(167, 165, 198)\",\n in6: \"rgb(40, 204, 217)\",\n in7: \"rgb(232, 178, 167)\",\n in8: \"rgb(242, 237, 161)\",\n in9: \"rgb(141, 203, 129)\",\n },\n cursor: \"rgb(255, 255, 255)\",\n drc: \"rgb(194, 194, 194)\",\n drc_error: \"rgba(215, 91, 107, 0.800)\",\n drc_exclusion: \"rgb(255, 255, 255)\",\n drc_warning: \"rgba(255, 208, 66, 0.902)\",\n dwgs_user: \"rgb(194, 194, 194)\",\n eco1_user: \"rgb(180, 219, 210)\",\n eco2_user: \"rgb(216, 200, 82)\",\n edge_cuts: \"rgb(208, 210, 205)\",\n f_adhes: \"rgb(132, 0, 132)\",\n f_crtyd: \"rgb(255, 0, 245)\",\n f_fab: \"rgb(175, 175, 175)\",\n f_mask: \"rgba(216, 100, 255, 0.400)\",\n f_paste: \"rgba(180, 160, 154, 0.902)\",\n f_silks: \"rgb(242, 237, 161)\",\n footprint_text_back: \"rgb(0, 0, 132)\",\n footprint_text_front: \"rgb(194, 194, 194)\",\n footprint_text_invisible: \"rgb(132, 132, 132)\",\n grid: \"rgb(132, 132, 132)\",\n grid_axes: \"rgb(194, 194, 194)\",\n margin: \"rgb(255, 38, 226)\",\n microvia: \"rgb(0, 132, 132)\",\n no_connect: \"rgb(0, 0, 132)\",\n pad_back: \"rgb(77, 127, 196)\",\n pad_front: \"rgb(200, 52, 52)\",\n pad_plated_hole: \"rgb(194, 194, 0)\",\n pad_through_hole: \"rgb(227, 183, 46)\",\n plated_hole: \"rgb(26, 196, 210)\",\n ratsnest: \"rgba(245, 255, 213, 0.702)\",\n select_overlay: \"rgb(4, 255, 67)\",\n soldermaskWithCopper: {\n top: \"rgb(18, 82, 50)\",\n bottom: \"rgb(77, 127, 196)\",\n },\n soldermask: {\n top: \"rgb(12, 55, 33)\",\n bottom: \"rgb(12, 55, 33)\",\n },\n through_via: \"rgb(236, 236, 236)\",\n user_1: \"rgb(194, 194, 194)\",\n user_2: \"rgb(89, 148, 220)\",\n user_3: \"rgb(180, 219, 210)\",\n user_4: \"rgb(216, 200, 82)\",\n user_5: \"rgb(194, 194, 194)\",\n user_6: \"rgb(89, 148, 220)\",\n user_7: \"rgb(180, 219, 210)\",\n user_8: \"rgb(216, 200, 82)\",\n user_9: \"rgb(232, 178, 167)\",\n via_blind_buried: \"rgb(187, 151, 38)\",\n via_hole: \"rgb(227, 183, 46)\",\n via_micro: \"rgb(0, 132, 132)\",\n via_through: \"rgb(236, 236, 236)\",\n worksheet: \"rgb(200, 114, 171)\",\n },\n gerbview: {\n axes: \"rgb(0, 0, 132)\",\n background: \"rgb(0, 0, 0)\",\n dcodes: \"rgb(255, 255, 255)\",\n grid: \"rgb(132, 132, 132)\",\n layers: [\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n \"rgb(132, 132, 0)\",\n \"rgb(194, 194, 194)\",\n \"rgb(0, 0, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n \"rgb(132, 132, 0)\",\n \"rgb(194, 194, 194)\",\n \"rgb(0, 0, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n \"rgb(132, 132, 0)\",\n \"rgb(194, 194, 194)\",\n \"rgb(0, 0, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n ],\n negative_objects: \"rgb(132, 132, 132)\",\n worksheet: \"rgb(0, 0, 132)\",\n },\n palette: [\n \"rgb(132, 0, 0)\",\n \"rgb(194, 194, 0)\",\n \"rgb(194, 0, 194)\",\n \"rgb(194, 0, 0)\",\n \"rgb(0, 132, 132)\",\n \"rgb(0, 132, 0)\",\n \"rgb(0, 0, 132)\",\n \"rgb(132, 132, 132)\",\n \"rgb(132, 0, 132)\",\n \"rgb(194, 194, 194)\",\n \"rgb(132, 0, 132)\",\n \"rgb(132, 0, 0)\",\n \"rgb(132, 132, 0)\",\n \"rgb(194, 194, 194)\",\n \"rgb(0, 0, 132)\",\n \"rgb(0, 132, 0)\",\n ],\n schematic: {\n anchor: \"rgb(0, 0, 255)\",\n aux_items: \"rgb(0, 0, 0)\",\n background: \"rgb(33, 33, 33)\",\n brightened: \"rgb(204, 204, 204)\",\n bus: \"rgb(0, 96, 192)\",\n bus_junction: \"rgb(0, 96, 192)\",\n component_body: \"rgb(44, 44, 44)\",\n component_outline: \"rgb(192, 0, 0)\",\n cursor: \"rgb(224, 224, 224)\",\n erc_error: \"rgba(192, 48, 48, 0.800)\",\n erc_warning: \"rgba(192, 140, 0, 0.800)\",\n fields: \"rgb(128, 0, 160)\",\n grid: \"rgb(60, 60, 60)\",\n grid_axes: \"rgb(60, 60, 60)\",\n hidden: \"rgb(194, 194, 194)\",\n junction: \"rgb(0, 160, 0)\",\n label_global: \"rgb(0, 160, 224)\",\n label_hier: \"rgb(160, 160, 0)\",\n label_local: \"rgb(192, 192, 192)\",\n net_name: \"rgb(224, 224, 224)\",\n no_connect: \"rgb(97, 43, 224)\",\n note: \"rgb(192, 192, 0)\",\n override_item_colors: false,\n pin: \"rgb(192, 0, 0)\",\n pin_name: \"rgb(192, 192, 192)\",\n pin_number: \"rgb(192, 0, 0)\",\n reference: \"rgb(192, 192, 192)\",\n shadow: \"rgba(102, 179, 255, 0.800)\",\n sheet: \"rgb(128, 0, 160)\",\n sheet_background: \"rgba(255, 255, 255, 0.000)\",\n sheet_fields: \"rgb(160, 160, 0)\",\n sheet_filename: \"rgb(160, 160, 0)\",\n sheet_label: \"rgb(160, 160, 0)\",\n sheet_name: \"rgb(0, 160, 204)\",\n value: \"rgb(192, 192, 192)\",\n wire: \"rgb(0, 160, 0)\",\n worksheet: \"rgb(192, 0, 0)\",\n },\n}\n","import { Matrix } from \"transformation-matrix\"\n\nexport const scaleOnly = (mat: Matrix, value: number = 1) => {\n if (Math.abs(mat.a) !== Math.abs(mat.d))\n throw new Error(\"Cannot scale non-uniformly\")\n return value * Math.abs(mat.a)\n}\n","export const zIndexMap = {\n elementOverlay: 40,\n dimensionOverlay: 40,\n errorOverlay: 40,\n pcbGroupOverlay: 35,\n ratsNestOverlay: 30,\n toolbarOverlay: 70,\n warnings: 30,\n // Canvas layers are assigned z-indexes below this value. A 10-layer board\n // needs 26 canvas planes once masks, silkscreen, notes, and other overlays\n // are included, so keep enough room for the complete stack.\n topLayer: 30,\n clickToInteractOverlay: 100,\n}\n","import type { AnyCircuitElement, LayerRef, PcbRenderLayer } from \"circuit-json\"\n\nexport const getCopperLayerRefs = (numLayers = 2): LayerRef[] => {\n const layerCount = Math.max(2, Math.min(10, Math.floor(numLayers)))\n return [\n \"top\",\n ...Array.from(\n { length: layerCount - 2 },\n (_, index) => `inner${index + 1}` as LayerRef,\n ),\n \"bottom\",\n ]\n}\n\nexport const getCopperLayerRefsFromElements = (\n elements: AnyCircuitElement[],\n): LayerRef[] => {\n const board = elements.find((element) => element.type === \"pcb_board\")\n return getCopperLayerRefs(board?.num_layers ?? 2)\n}\n\nexport const getCopperRenderLayer = (layer: LayerRef): PcbRenderLayer =>\n `${layer}_copper` as PcbRenderLayer\n\nexport const normalizeCopperRenderLayers = (\n layers: PcbRenderLayer[],\n): LayerRef[] =>\n layers.map((layer) =>\n layer.endsWith(\"_copper\")\n ? (layer.slice(0, -\"_copper\".length) as LayerRef)\n : (layer as LayerRef),\n )\n\nexport const getOrderedCanvasLayers = (\n elements: AnyCircuitElement[],\n): string[] => {\n const innerLayers = getCopperLayerRefsFromElements(elements).filter((layer) =>\n layer.startsWith(\"inner\"),\n )\n\n return [\n \"board\",\n \"bottom\",\n \"soldermask_bottom\",\n \"bottom_silkscreen\",\n \"top\",\n \"soldermask_top\",\n \"soldermask_with_copper_bottom\",\n \"soldermask_with_copper_top\",\n \"top_fabrication\",\n \"bottom_fabrication\",\n ...innerLayers,\n \"drill\",\n \"edge_cuts\",\n \"bottom_notes\",\n \"top_notes\",\n \"top_silkscreen\",\n \"top_courtyard\",\n \"bottom_courtyard\",\n \"other\",\n ]\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isCopperPourElement(element: AnyCircuitElement) {\n return element.type === \"pcb_copper_pour\"\n}\n\nexport function drawCopperPourElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const copperPourElements = elements.filter(isCopperPourElement)\n\n if (copperPourElements.length === 0) return\n\n // Draw all copper pour elements with default colors\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(copperPourElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\n\nconst PCB_VIEWER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n courtyard: {\n top: colors.board.f_crtyd,\n bottom: colors.board.b_crtyd,\n },\n}\n\nexport function isCourtyardElement(element: AnyCircuitElement) {\n return (\n element.type === \"pcb_courtyard_circle\" ||\n element.type === \"pcb_courtyard_rect\" ||\n element.type === \"pcb_courtyard_outline\"\n )\n}\n\nexport function drawCourtyardElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.configure({\n colorOverrides: PCB_VIEWER_COLOR_MAP,\n })\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const courtyardElements = elements.filter(isCourtyardElement)\n\n drawer.drawElements(courtyardElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\n\n// Create a color map that uses pcb-viewer's existing colors for fabrication\n// while using defaults from circuit-to-canvas for other elements\nconst PCB_VIEWER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n silkscreen: {\n top: colors.board.f_fab,\n bottom: colors.board.b_fab,\n },\n}\n\nexport function isFabricationNote(element: AnyCircuitElement) {\n return element.type.includes(\"pcb_fabrication_note\")\n}\n\nexport function drawFabricationNoteElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.configure({\n colorOverrides: PCB_VIEWER_COLOR_MAP,\n })\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const fabricationElements = elements.filter(isFabricationNote)\n\n drawer.drawElements(fabricationElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbHole(element: AnyCircuitElement) {\n return element.type === \"pcb_hole\"\n}\n\nexport function drawPcbHoleElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n drawSoldermask?: boolean\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const holeElements = elements.filter(isPcbHole)\n\n drawer.drawElements(holeElements, { layers, drawSoldermask })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbBoardElement(element: AnyCircuitElement) {\n return element.type === \"pcb_board\"\n}\n\nexport function drawPcbBoardElements({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n drawSoldermask?: boolean\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const pcbBoardElements = elements.filter(isPcbBoardElement)\n\n for (const element of pcbBoardElements) {\n drawer.drawElements([element], {\n layers,\n drawSoldermask: false,\n drawBoardMaterial: drawSoldermask ?? false,\n minBoardOutlineStrokePx: 2,\n })\n }\n}\n","import type {\n AnyCircuitElement,\n PcbCopperText,\n PcbRenderLayer,\n} from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbCopperText(\n element: AnyCircuitElement,\n): element is PcbCopperText {\n return element.type === \"pcb_copper_text\"\n}\n\nexport function drawPcbCopperTextElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const copperTextElements = elements.filter(isPcbCopperText)\n\n if (copperTextElements.length === 0) return\n\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(copperTextElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbCutout(element: AnyCircuitElement) {\n return element.type === \"pcb_cutout\"\n}\n\nexport function drawPcbCutoutElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const cutoutElements = elements.filter(isPcbCutout)\n\n drawer.drawElements(cutoutElements, { layers })\n}\n","import type { AnyCircuitElement, LayerRef, PCBKeepout } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { LAYER_NAME_TO_COLOR } from \"./Drawer\"\nimport { getCopperRenderLayer } from \"./copper-layers\"\n\nexport function isPcbKeepout(\n element: AnyCircuitElement,\n): element is PCBKeepout {\n return element.type === \"pcb_keepout\"\n}\n\nexport function getPcbKeepoutElementsForLayer({\n elements,\n layer,\n}: {\n elements: AnyCircuitElement[]\n layer: LayerRef\n}): PCBKeepout[] {\n return elements\n .filter(isPcbKeepout)\n .filter((keepout) => keepout.layers.includes(layer))\n}\n\nexport function getPcbKeepoutColorForLayer(layer: LayerRef): string {\n return color(LAYER_NAME_TO_COLOR[layer]).lighten(0.4).hex()\n}\n\nexport function drawPcbKeepoutElementsForLayer({\n canvas,\n elements,\n layer,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layer: LayerRef\n realToCanvasMat: Matrix\n}) {\n const keepoutElements = getPcbKeepoutElementsForLayer({ elements, layer })\n\n if (keepoutElements.length === 0) return\n\n const drawer = new CircuitToCanvasDrawer(canvas)\n const keepoutColor = getPcbKeepoutColorForLayer(layer)\n drawer.configure({\n colorOverrides: {\n keepout: {\n top: keepoutColor,\n bottom: keepoutColor,\n },\n },\n })\n drawer.realToCanvasMat = realToCanvasMat\n\n drawer.drawElements(keepoutElements, {\n layers: [getCopperRenderLayer(layer)],\n })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbNote(element: AnyCircuitElement) {\n return element.type.startsWith(\"pcb_note_\")\n}\n\nexport function drawPcbNoteElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const pcbNoteElements = elements.filter(isPcbNote)\n\n drawer.drawElements(pcbNoteElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport { CircuitToCanvasDrawer } from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\n\nexport function isPcbPanelElement(element: AnyCircuitElement) {\n return element.type === \"pcb_panel\"\n}\n\nexport function drawPcbPanelElements({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n drawSoldermask?: boolean\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const pcbPanelElements = elements.filter(isPcbPanelElement)\n\n for (const element of pcbPanelElements) {\n drawer.drawElements([element], { layers })\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\nimport { normalizeCopperRenderLayers } from \"./copper-layers\"\nimport type { Primitive } from \"./types\"\n\n// Color map with lighter copper colors for hover effect\nconst HOVER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: {\n ...DEFAULT_PCB_COLOR_MAP.copper,\n top: color(colors.board.pad_front).lighten(0.5).toString(),\n bottom: color(colors.board.pad_back).lighten(0.5).toString(),\n inner1: color(colors.board.copper.in1).lighten(0.5).toString(),\n inner2: color(colors.board.copper.in2).lighten(0.5).toString(),\n inner3: color(colors.board.copper.in3).lighten(0.5).toString(),\n inner4: color(colors.board.copper.in4).lighten(0.5).toString(),\n inner5: color(colors.board.copper.in5).lighten(0.5).toString(),\n inner6: color(colors.board.copper.in6).lighten(0.5).toString(),\n inner7: color(colors.board.copper.in7).lighten(0.5).toString(),\n inner8: color(colors.board.copper.in8).lighten(0.5).toString(),\n },\n}\n\nexport function isPcbSmtPad(element: AnyCircuitElement) {\n return element.type === \"pcb_smtpad\"\n}\n\nexport function drawPcbSmtPadElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n primitives,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n primitives?: Primitive[]\n drawSoldermask?: boolean\n}) {\n // Filter SMT pads to only those on the specified layers\n const targetLayers = new Set(normalizeCopperRenderLayers(layers))\n const smtPadElements = elements\n .filter(isPcbSmtPad)\n .filter((element) => targetLayers.has(element.layer))\n\n if (smtPadElements.length === 0) return\n\n // Find which SMT pad elements have highlighted primitives\n const highlightedElementIds = new Set<string>()\n if (primitives) {\n for (const primitive of primitives) {\n if (\n (primitive.is_mouse_over || primitive.is_in_highlighted_net) &&\n primitive._element?.type === \"pcb_smtpad\"\n ) {\n highlightedElementIds.add(primitive._element.pcb_smtpad_id)\n }\n }\n }\n\n // Separate highlighted and non-highlighted elements\n const highlightedElements = smtPadElements.filter((element) =>\n highlightedElementIds.has(element.pcb_smtpad_id),\n )\n const nonHighlightedElements = smtPadElements.filter(\n (element) => !highlightedElementIds.has(element.pcb_smtpad_id),\n )\n\n // Draw non-highlighted elements with default colors\n if (nonHighlightedElements.length > 0) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(nonHighlightedElements, { layers, drawSoldermask })\n }\n\n // Draw highlighted elements with lighter colors\n if (highlightedElements.length > 0) {\n const highlightDrawer = new CircuitToCanvasDrawer(canvas)\n highlightDrawer.configure({ colorOverrides: HOVER_COLOR_MAP })\n highlightDrawer.realToCanvasMat = realToCanvasMat\n highlightDrawer.drawElements(highlightedElements, {\n layers,\n drawSoldermask,\n })\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer, PcbTrace } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { normalizeCopperRenderLayers } from \"./copper-layers\"\nimport type { Primitive } from \"./types\"\n\n// Color map with lighter copper colors for hover effect\nconst HOVER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: Object.fromEntries(\n Object.entries(DEFAULT_PCB_COLOR_MAP.copper).map(([layer, layerColor]) => [\n layer,\n color(layerColor).lighten(0.5).toString(),\n ]),\n ) as PcbColorMap[\"copper\"],\n}\n\nexport function isPcbTrace(element: AnyCircuitElement): element is PcbTrace {\n return element.type === \"pcb_trace\"\n}\n\nexport const filterTraceByLayers = (\n trace: PcbTrace,\n targetLayers: Set<string>,\n): PcbTrace | null => {\n const filteredRoute = trace.route.filter((segment) => {\n if (\n segment.route_type === \"wire\" &&\n \"layer\" in segment &&\n targetLayers.has(segment.layer)\n ) {\n return true\n }\n\n if (segment.route_type === \"via\") {\n return (\n targetLayers.has(segment.from_layer) ||\n targetLayers.has(segment.to_layer)\n )\n }\n\n return false\n })\n\n const wireCount = filteredRoute.filter(\n (segment) => segment.route_type === \"wire\",\n ).length\n\n if (wireCount < 2) return null\n\n return {\n ...trace,\n route: filteredRoute,\n }\n}\n\nexport const showTraceSegmentsInsideHiddenCopperPours = (\n trace: PcbTrace,\n): PcbTrace => ({\n ...trace,\n route: trace.route.map((routePoint) => {\n if (\n !(\"is_inside_copper_pour\" in routePoint) ||\n routePoint.is_inside_copper_pour !== true\n ) {\n return routePoint\n }\n\n return {\n ...routePoint,\n is_inside_copper_pour: false,\n }\n }),\n})\n\nexport const getTraceClipContextElements = (\n elements: AnyCircuitElement[],\n showCopperPours: boolean,\n): AnyCircuitElement[] => (showCopperPours ? elements : [])\n\nexport const getHighlightedTraceElementIds = ({\n primitives,\n}: {\n primitives: Primitive[]\n}): Set<string> => {\n const highlightedElementIds = new Set<string>()\n\n for (const primitive of primitives) {\n if (\n (primitive.is_mouse_over || primitive.is_in_highlighted_net) &&\n primitive._element?.type === \"pcb_trace\"\n ) {\n highlightedElementIds.add(primitive._element.pcb_trace_id)\n }\n }\n\n return highlightedElementIds\n}\n\nexport function drawPcbTraceElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n primitives,\n showCopperPours,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n primitives?: Primitive[]\n showCopperPours: boolean\n}) {\n const targetLayers = new Set(normalizeCopperRenderLayers(layers))\n\n const traceElements = elements\n .filter(isPcbTrace)\n .map((trace) => filterTraceByLayers(trace, targetLayers))\n .filter((trace): trace is PcbTrace => trace !== null)\n .map((trace) =>\n showCopperPours ? trace : showTraceSegmentsInsideHiddenCopperPours(trace),\n )\n\n if (traceElements.length === 0) return\n\n const highlightedElementIds = getHighlightedTraceElementIds({\n primitives: primitives ?? [],\n })\n\n const highlightedElements: PcbTrace[] = []\n const nonHighlightedElements: PcbTrace[] = []\n for (const element of traceElements) {\n if (highlightedElementIds.has(element.pcb_trace_id)) {\n highlightedElements.push(element)\n } else {\n nonHighlightedElements.push(element)\n }\n }\n\n // The trace renderer receives a filtered element list. Give it the full\n // circuit only as clipping context while pours are visible; an empty list\n // deliberately disables geometric clipping when pours are hidden.\n const clipContextElements = getTraceClipContextElements(\n elements,\n showCopperPours,\n )\n\n if (nonHighlightedElements.length > 0) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(nonHighlightedElements, {\n layers,\n clipContextElements,\n })\n }\n\n if (highlightedElements.length > 0) {\n const highlightDrawer = new CircuitToCanvasDrawer(canvas)\n highlightDrawer.configure({ colorOverrides: HOVER_COLOR_MAP })\n highlightDrawer.realToCanvasMat = realToCanvasMat\n highlightDrawer.drawElements(highlightedElements, {\n layers,\n clipContextElements,\n })\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\nimport colors from \"./colors\"\nimport type { Primitive } from \"./types\"\n\n// Color map with lighter copper colors for hover effect\nconst HOVER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: {\n ...DEFAULT_PCB_COLOR_MAP.copper,\n top: color(colors.board.pad_front).lighten(0.5).toString(),\n bottom: color(colors.board.pad_back).lighten(0.5).toString(),\n inner1: color(colors.board.copper.in1).lighten(0.5).toString(),\n inner2: color(colors.board.copper.in2).lighten(0.5).toString(),\n inner3: color(colors.board.copper.in3).lighten(0.5).toString(),\n inner4: color(colors.board.copper.in4).lighten(0.5).toString(),\n inner5: color(colors.board.copper.in5).lighten(0.5).toString(),\n inner6: color(colors.board.copper.in6).lighten(0.5).toString(),\n inner7: color(colors.board.copper.in7).lighten(0.5).toString(),\n inner8: color(colors.board.copper.in8).lighten(0.5).toString(),\n },\n}\n\nexport function isPlatedHole(element: AnyCircuitElement) {\n return element.type === \"pcb_plated_hole\"\n}\n\nexport function drawPlatedHolePads({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n primitives,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n primitives?: Primitive[]\n drawSoldermask?: boolean\n}) {\n const platedHoleElements = elements.filter(isPlatedHole)\n\n if (platedHoleElements.length === 0) return\n\n // Find which plated hole elements have highlighted primitives\n const highlightedElementIds = new Set<string>()\n if (primitives) {\n for (const primitive of primitives) {\n if (\n (primitive.is_mouse_over || primitive.is_in_highlighted_net) &&\n primitive._element?.type === \"pcb_plated_hole\"\n ) {\n highlightedElementIds.add(primitive._element.pcb_plated_hole_id)\n }\n }\n }\n\n // Separate highlighted and non-highlighted elements\n const highlightedElements = platedHoleElements.filter((element) =>\n highlightedElementIds.has(element.pcb_plated_hole_id),\n )\n const nonHighlightedElements = platedHoleElements.filter(\n (element) => !highlightedElementIds.has(element.pcb_plated_hole_id),\n )\n\n // Draw non-highlighted elements with default colors\n if (nonHighlightedElements.length > 0) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(nonHighlightedElements, { layers, drawSoldermask })\n }\n\n // Draw highlighted elements with lighter colors\n if (highlightedElements.length > 0) {\n const highlightDrawer = new CircuitToCanvasDrawer(canvas)\n highlightDrawer.configure({ colorOverrides: HOVER_COLOR_MAP })\n highlightDrawer.realToCanvasMat = realToCanvasMat\n highlightDrawer.drawElements(highlightedElements, {\n layers,\n drawSoldermask,\n })\n }\n}\n","import { compose, translate, rotate, applyToPoint } from \"transformation-matrix\"\nimport { Line } from \"../types\"\n\nexport function rotateText(rotateTextParams: {\n lines: Line[]\n anchorPoint: { x: number; y: number }\n ccwRotation: number\n}) {\n const { lines, anchorPoint, ccwRotation } = rotateTextParams\n if (!ccwRotation) return lines\n const rad = (ccwRotation * Math.PI) / 180\n const rotationMatrix = rotate(rad)\n\n // Create rotation transform around anchor point\n const transform = compose(\n translate(anchorPoint.x, anchorPoint.y),\n rotationMatrix,\n translate(-anchorPoint.x, -anchorPoint.y),\n )\n applyToPoint(transform, anchorPoint)\n return lines.map((line) => ({\n ...line,\n x1: applyToPoint(transform, { x: line.x1, y: line.y1 }).x,\n y1: applyToPoint(transform, { x: line.x1, y: line.y1 }).y,\n x2: applyToPoint(transform, { x: line.x2, y: line.y2 }).x,\n y2: applyToPoint(transform, { x: line.x2, y: line.y2 }).y,\n }))\n}\n","export { lineAlphabet, svgAlphabet } from \"@tscircuit/alphabet\"\n","import { lineAlphabet } from \"../assets/alphabet\"\nimport { getNewPcbDrawingObjectId } from \"./convert-element-to-primitive\"\nimport type { Line, Text } from \"./types\"\n\nexport const LETTER_HEIGHT_TO_WIDTH_RATIO = 0.6\nexport const LETTER_HEIGHT_TO_SPACE_RATIO = 0.2\n\nconst getTextGeometry = (text: Text) => {\n const target_height = text.size * 0.7 // Apply 70% scaling\n\n const target_width_char = target_height * LETTER_HEIGHT_TO_WIDTH_RATIO\n const space_between_chars = target_height * LETTER_HEIGHT_TO_SPACE_RATIO\n const space_between_lines = target_height * LETTER_HEIGHT_TO_SPACE_RATIO\n\n const text_lines = text.text.split(/\\r?\\n/)\n const has_text = text.text.length > 0 && target_height > 0\n const line_count = has_text ? text_lines.length : 0\n\n const line_widths = has_text\n ? text_lines.map((line) => {\n if (line.length === 0) return 0\n return (\n line.length * target_width_char +\n (line.length - 1) * space_between_chars\n )\n })\n : []\n\n const width = line_widths.length > 0 ? Math.max(...line_widths) : 0\n\n const height =\n line_count > 0\n ? line_count * target_height + (line_count - 1) * space_between_lines\n : 0\n\n return {\n text_lines,\n line_count,\n line_widths,\n target_height,\n target_width_char,\n space_between_chars,\n space_between_lines,\n width,\n height,\n }\n}\n\nexport const getTextWidth = (text: Text): number => getTextGeometry(text).width\n\nexport const getTextMetrics = (text: Text) => {\n const geometry = getTextGeometry(text)\n\n return {\n width: geometry.width,\n height: geometry.height,\n lineHeight: geometry.target_height,\n lineSpacing: geometry.space_between_lines,\n lineCount: geometry.line_count,\n }\n}\n\nexport const convertTextToLines = (text: Text): Line[] => {\n const {\n text_lines,\n line_count,\n line_widths,\n target_height,\n target_width_char,\n space_between_chars,\n space_between_lines,\n width: maxWidth,\n } = getTextGeometry(text)\n\n if (target_height <= 0 || line_count === 0) return []\n\n const strokeWidth = target_height / 12\n\n const lines: Line[] = []\n\n for (let lineIndex = 0; lineIndex < line_count; lineIndex++) {\n // Lines go from top to bottom: first line (index 0) at highest Y, subsequent lines decrease in Y\n // lineIndex 0 -> offset 0 (top), lineIndex 1 -> offset -step (below), etc.\n const lineYOffset = -lineIndex * (target_height + space_between_lines)\n\n // Center each line within the max width bounding box\n // This ensures multiline text is properly centered when using center alignment\n const lineWidth = line_widths[lineIndex]\n const lineXOffset = (maxWidth - lineWidth) / 2\n let current_x_origin_for_char_box = text.x + lineXOffset\n\n for (\n let letterIndex = 0;\n letterIndex < text_lines[lineIndex].length;\n letterIndex++\n ) {\n const letter = text_lines[lineIndex][letterIndex]\n const letterLines =\n lineAlphabet[letter] ?? lineAlphabet[letter.toUpperCase()]\n\n if (!letterLines) {\n current_x_origin_for_char_box += target_width_char + space_between_chars\n continue\n }\n\n for (const {\n x1: norm_x1,\n y1: norm_y1,\n x2: norm_x2,\n y2: norm_y2,\n } of letterLines) {\n lines.push({\n _pcb_drawing_object_id: getNewPcbDrawingObjectId(\"line\"),\n pcb_drawing_type: \"line\",\n x1: current_x_origin_for_char_box + target_width_char * norm_x1,\n y1: text.y + lineYOffset + target_height * norm_y1,\n x2: current_x_origin_for_char_box + target_width_char * norm_x2,\n y2: text.y + lineYOffset + target_height * norm_y2,\n width: strokeWidth,\n layer: text.layer,\n unit: text.unit,\n color: text.color,\n })\n }\n current_x_origin_for_char_box += target_width_char + space_between_chars\n }\n }\n\n return lines\n}\n","import { type Drawer, LAYER_NAME_TO_COLOR } from \"./Drawer\"\nimport { rotateText } from \"./util/rotate-text\"\nimport { convertTextToLines, getTextMetrics } from \"./convert-text-to-lines\"\nimport type {\n Circle,\n Line,\n Oval,\n Pill,\n Polygon,\n PolygonWithArcs,\n Primitive,\n Rect,\n Text,\n} from \"./types\"\nimport color from \"color\"\n\nfunction getColor(primitive: Primitive): string {\n const explicitColor = (primitive as any).color\n\n const baseColorString =\n explicitColor ??\n LAYER_NAME_TO_COLOR[primitive.layer as keyof typeof LAYER_NAME_TO_COLOR]\n\n let c = color(baseColorString)\n\n if (primitive._element?.type === \"pcb_copper_pour\") {\n c = c.alpha(0.7)\n }\n\n if (primitive.is_mouse_over || primitive.is_in_highlighted_net) {\n return c.lighten(0.5).rgb().toString()\n }\n\n return c.rgb().toString()\n}\n\nexport const drawLine = (drawer: Drawer, line: Line) => {\n drawer.equip({\n size: line.zoomIndependent ? line.width / drawer.transform.a : line.width,\n shape: line.squareCap ? \"square\" : \"circle\",\n color: getColor(line),\n layer: line.layer,\n })\n drawer.moveTo(line.x1, line.y1)\n drawer.lineTo(line.x2, line.y2)\n}\n\n/**\n * Calculate alignment offset for text based on its dimensions and alignment setting\n */\nconst getAlignOffset = (\n textWidth: number,\n textHeight: number,\n align?: string,\n): { x: number; y: number } => {\n switch (align) {\n case \"top_left\":\n return { x: 0, y: -textHeight }\n case \"top_center\":\n return { x: -textWidth / 2, y: -textHeight }\n case \"top_right\":\n return { x: -textWidth, y: -textHeight }\n case \"center_left\":\n return { x: 0, y: -textHeight / 2 }\n case \"center\":\n return { x: -textWidth / 2, y: -textHeight / 2 }\n case \"center_right\":\n return { x: -textWidth, y: -textHeight / 2 }\n case \"bottom_left\":\n return { x: 0, y: 0 }\n case \"bottom_center\":\n return { x: -textWidth / 2, y: 0 }\n case \"bottom_right\":\n return { x: -textWidth, y: 0 }\n default:\n return { x: 0, y: 0 }\n }\n}\n\n/**\n * Determine if text should be mirrored based on layer and is_mirrored property\n */\nconst shouldMirrorText = (text: Text): boolean => {\n // Bottom copper layer should auto-mirror (like bottom silkscreen)\n if (text.layer === \"bottom_silkscreen\" || text.layer === \"bottom\") {\n // If is_mirrored is explicitly set to false, don't mirror\n return text.is_mirrored !== false\n }\n // For other layers, only mirror if explicitly requested\n return text.is_mirrored === true\n}\n\nexport const drawText = (drawer: Drawer, text: Text) => {\n drawer.equip({\n fontSize: text.size,\n color: getColor(text),\n layer: text.layer,\n })\n\n const { width: textWidth, height: textHeight } = getTextMetrics(text)\n const alignOffset = getAlignOffset(textWidth, textHeight, text.align)\n\n text.x ??= 0\n text.y ??= 0\n\n // Get rotation anchor point based on alignment\n const rotationAnchor = {\n x: text.x,\n y: text.y,\n }\n\n // Generate the text lines with alignment offset\n let text_lines = convertTextToLines({\n ...text,\n x: text.x + alignOffset.x,\n y: text.y + alignOffset.y,\n })\n\n // Mirror text if needed (bottom layers or explicit is_mirrored)\n if (shouldMirrorText(text)) {\n text_lines = text_lines.map((line) => ({\n ...line,\n x1: 2 * text.x - line.x1,\n x2: 2 * text.x - line.x2,\n }))\n }\n\n // Apply rotation if needed\n if (text.ccw_rotation) {\n const rotateTextParams = {\n lines: text_lines,\n anchorPoint: rotationAnchor,\n ccwRotation: text.ccw_rotation,\n }\n text_lines = rotateText(rotateTextParams)\n }\n\n // Draw all lines with transformed context\n for (const line of text_lines) {\n drawLine(drawer, line)\n }\n}\n\n/**\n * Draw knockout text - a filled rectangle with text cut out (transparent)\n */\nexport const drawKnockoutText = (drawer: Drawer, text: Text) => {\n const {\n width: textWidth,\n height: textHeight,\n lineHeight,\n } = getTextMetrics(text)\n\n text.x ??= 0\n text.y ??= 0\n\n // Calculate padding\n const padding = text.knockout_padding ?? {\n left: text.size * 0.5,\n right: text.size * 0.5,\n top: text.size * 0.3,\n bottom: text.size * 0.3,\n }\n\n // Calculate the rectangle bounds\n const rectWidth = textWidth + padding.left + padding.right\n const rectHeight = textHeight + padding.top + padding.bottom\n\n // For knockout, we render text centered within the rectangle.\n // The rectangle is centered at the anchor point (text.x, text.y).\n // Text bounding box when drawn at origin (0,0):\n // - X: from 0 to textWidth (left-aligned, each line centered within)\n // - Y: from 0 (bottom of first line baseline) to lineHeight (top of first line)\n // then going down: line N is at Y = -N * (lineHeight + spacing)\n // - So Y ranges from lineHeight (top) to lineHeight - textHeight (bottom)\n //\n // To center the text in the rectangle, we need to offset it so that\n // the text's center aligns with the rectangle's center (which is at anchor).\n\n // Text center when drawn at (0, 0):\n const textCenterXAtOrigin = textWidth / 2\n const textCenterYAtOrigin = lineHeight - textHeight / 2\n\n // To center text at anchor point, offset by negative of center\n const textDrawX = text.x - textCenterXAtOrigin\n const textDrawY = text.y - textCenterYAtOrigin\n\n // Get rotation anchor point\n const rotationAnchor = {\n x: text.x,\n y: text.y,\n }\n\n // Draw the filled rectangle centered at anchor\n const rect: Rect = {\n _pcb_drawing_object_id: `knockout_rect_${text._pcb_drawing_object_id}`,\n pcb_drawing_type: \"rect\",\n x: text.x,\n y: text.y,\n w: rectWidth,\n h: rectHeight,\n layer: text.layer,\n ccw_rotation: text.ccw_rotation,\n }\n\n // If mirrored, the rectangle stays centered at anchor (no adjustment needed)\n // but text will be mirrored around the anchor\n\n // Draw the background rectangle\n if (text.ccw_rotation) {\n drawRotatedRect(drawer, rect)\n } else {\n drawRect(drawer, rect)\n }\n\n // Generate the text lines positioned to be centered in the rectangle\n let text_lines = convertTextToLines({\n ...text,\n x: textDrawX,\n y: textDrawY,\n })\n\n // Mirror text if needed (around the anchor point)\n if (shouldMirrorText(text)) {\n text_lines = text_lines.map((line) => ({\n ...line,\n x1: 2 * text.x - line.x1,\n x2: 2 * text.x - line.x2,\n }))\n }\n\n // Apply rotation if needed\n if (text.ccw_rotation) {\n const rotateTextParams = {\n lines: text_lines,\n anchorPoint: rotationAnchor,\n ccwRotation: text.ccw_rotation,\n }\n text_lines = rotateText(rotateTextParams)\n }\n\n // Draw text lines with destination-out mode to cut them from the rectangle\n // We draw directly instead of using drawLine to preserve the subtract mode\n for (const line of text_lines) {\n drawer.equip({\n size: line.width,\n shape: \"circle\",\n color: \"black\",\n layer: text.layer,\n mode: \"subtract\",\n })\n drawer.moveTo(line.x1, line.y1)\n drawer.lineTo(line.x2, line.y2)\n }\n\n // Reset to normal mode\n drawer.equip({\n mode: \"add\",\n })\n}\n\nexport const drawRect = (drawer: Drawer, rect: Rect) => {\n drawer.equip({\n color: getColor(rect),\n layer: rect.layer,\n size: rect.stroke_width,\n })\n drawer.rect({\n x: rect.x,\n y: rect.y,\n w: rect.w,\n h: rect.h,\n mesh_fill: rect.mesh_fill,\n is_filled: rect.is_filled,\n has_stroke: rect.has_stroke,\n is_stroke_dashed: rect.is_stroke_dashed,\n stroke_width: rect.stroke_width,\n roundness: rect.roundness,\n })\n}\n\nexport const drawRotatedRect = (drawer: Drawer, rect: Rect) => {\n drawer.equip({\n color: getColor(rect),\n layer: rect.layer,\n })\n\n drawer.rotatedRect(\n rect.x,\n rect.y,\n rect.w,\n rect.h,\n rect.ccw_rotation!,\n rect.roundness,\n rect.mesh_fill,\n )\n}\n\nexport const drawRotatedPill = (drawer: Drawer, pill: Pill) => {\n drawer.equip({\n color: getColor(pill),\n layer: pill.layer,\n })\n drawer.rotatedPill(pill.x, pill.y, pill.w, pill.h, pill.ccw_rotation!)\n}\n\nexport const drawCircle = (drawer: Drawer, circle: Circle) => {\n drawer.equip({\n color: getColor(circle),\n layer: circle.layer,\n })\n drawer.circle(circle.x, circle.y, circle.r, circle.mesh_fill)\n}\n\nexport const drawOval = (drawer: Drawer, oval: Oval) => {\n drawer.equip({\n color: getColor(oval),\n layer: oval.layer,\n })\n drawer.oval(oval.x, oval.y, oval.rX, oval.rY)\n}\n\nexport const drawPill = (drawer: Drawer, pill: Pill) => {\n drawer.equip({\n color: getColor(pill),\n layer: pill.layer,\n })\n drawer.pill(pill.x, pill.y, pill.w, pill.h)\n}\n\nexport const drawPolygon = (drawer: Drawer, polygon: Polygon) => {\n drawer.equip({\n color: getColor(polygon),\n layer: polygon.layer,\n })\n drawer.polygon(polygon.points)\n}\n\nexport const drawPolygonWithArcs = (drawer: Drawer, p: PolygonWithArcs) => {\n drawer.equip({\n color: getColor(p),\n layer: p.layer,\n })\n drawer.polygonWithArcs(p.brep_shape)\n}\n\nexport const drawPrimitive = (drawer: Drawer, primitive: Primitive) => {\n switch (primitive.pcb_drawing_type) {\n case \"line\":\n return drawLine(drawer, primitive)\n case \"text\":\n if (primitive.is_knockout) {\n return drawKnockoutText(drawer, primitive)\n }\n return drawText(drawer, primitive)\n case \"rect\": {\n if (primitive.ccw_rotation) {\n return drawRotatedRect(drawer, primitive)\n }\n return drawRect(drawer, primitive)\n }\n case \"circle\":\n return drawCircle(drawer, primitive)\n case \"oval\":\n return drawOval(drawer, primitive)\n case \"pill\":\n if (primitive.ccw_rotation) {\n return drawRotatedPill(drawer, primitive)\n }\n return drawPill(drawer, primitive)\n case \"polygon\":\n return drawPolygon(drawer, primitive)\n case \"polygon_with_arcs\":\n return drawPolygonWithArcs(drawer, primitive)\n }\n}\n\nexport const drawPrimitives = (drawer: Drawer, primitives: Primitive[]) => {\n for (const primitive of primitives) {\n drawPrimitive(drawer, primitive)\n }\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\n\n// Create a color map that uses pcb-viewer's existing colors for silkscreen\n// while using defaults from circuit-to-canvas for other elements\nconst PCB_VIEWER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n silkscreen: {\n top: colors.board.f_silks,\n bottom: colors.board.b_silks,\n },\n}\n\nexport function isSilkscreenElement(element: AnyCircuitElement) {\n return element.type.includes(\"pcb_silkscreen\")\n}\n\nexport function drawSilkscreenElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n\n drawer.configure({\n colorOverrides: PCB_VIEWER_COLOR_MAP,\n })\n\n drawer.realToCanvasMat = realToCanvasMat\n\n const silkscreenElements = elements.filter(isSilkscreenElement)\n\n drawer.drawElements(silkscreenElements, { layers })\n}\n","import type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport {\n CircuitToCanvasDrawer,\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n} from \"circuit-to-canvas\"\nimport color from \"color\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\nimport type { Primitive } from \"./types\"\n\nconst HOVER_SOLDERMASK_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: {\n ...DEFAULT_PCB_COLOR_MAP.copper,\n top: color(colors.board.pad_front).lighten(0.5).toString(),\n bottom: color(colors.board.pad_back).lighten(0.5).toString(),\n inner1: color(colors.board.copper.in1).lighten(0.5).toString(),\n inner2: color(colors.board.copper.in2).lighten(0.5).toString(),\n inner3: color(colors.board.copper.in3).lighten(0.5).toString(),\n inner4: color(colors.board.copper.in4).lighten(0.5).toString(),\n inner5: color(colors.board.copper.in5).lighten(0.5).toString(),\n inner6: color(colors.board.copper.in6).lighten(0.5).toString(),\n inner7: color(colors.board.copper.in7).lighten(0.5).toString(),\n inner8: color(colors.board.copper.in8).lighten(0.5).toString(),\n },\n soldermask: {\n ...DEFAULT_PCB_COLOR_MAP.soldermask,\n top: color(colors.board.soldermask.top).lighten(0.35).toString(),\n bottom: color(colors.board.soldermask.bottom).lighten(0.35).toString(),\n },\n}\n\nexport function drawSoldermaskElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n primitives,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n drawSoldermaskTop?: boolean\n drawSoldermaskBottom?: boolean\n primitives?: Primitive[]\n}) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n const boards = elements.filter((element) => element.type === \"pcb_board\")\n if (boards.length <= 1) {\n drawer.drawElements(elements, {\n layers,\n drawSoldermask: true,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n drawBoardMaterial: false,\n })\n } else {\n const nonBoardElements = elements.filter(\n (element) => element.type !== \"pcb_board\",\n )\n for (const board of boards) {\n drawer.drawElements([board, ...nonBoardElements], {\n layers,\n drawSoldermask: true,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n drawBoardMaterial: false,\n })\n }\n }\n\n if (!primitives) return\n\n const hoveredElementIds = new Set<string>()\n for (const primitive of primitives) {\n if (!(primitive.is_mouse_over || primitive.is_in_highlighted_net)) continue\n const element = primitive._element\n if (element?.type === \"pcb_smtpad\") {\n hoveredElementIds.add(element.pcb_smtpad_id)\n } else if (element?.type === \"pcb_plated_hole\") {\n hoveredElementIds.add(element.pcb_plated_hole_id)\n } else if (element?.type === \"pcb_via\") {\n hoveredElementIds.add(element.pcb_via_id)\n }\n }\n\n if (hoveredElementIds.size === 0) return\n\n const hoveredElements = elements.filter((element) => {\n if (element.type === \"pcb_smtpad\") {\n return hoveredElementIds.has(element.pcb_smtpad_id)\n }\n if (element.type === \"pcb_plated_hole\") {\n return hoveredElementIds.has(element.pcb_plated_hole_id)\n }\n if (element.type === \"pcb_via\") {\n return hoveredElementIds.has(element.pcb_via_id)\n }\n return false\n })\n\n if (hoveredElements.length === 0) return\n\n const hoverDrawer = new CircuitToCanvasDrawer(canvas)\n hoverDrawer.configure({ colorOverrides: HOVER_SOLDERMASK_COLOR_MAP })\n hoverDrawer.realToCanvasMat = realToCanvasMat\n hoverDrawer.drawElements(hoveredElements, {\n layers,\n drawSoldermask: true,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n drawBoardMaterial: false,\n })\n}\n","import {\n DEFAULT_PCB_COLOR_MAP,\n type PcbColorMap,\n CircuitToCanvasDrawer,\n} from \"circuit-to-canvas\"\nimport type { AnyCircuitElement, PcbRenderLayer } from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\nimport colors from \"./colors\"\nimport color from \"color\"\nimport { Primitive } from \"./types\"\n\n// Color map with lighter copper colors for hover effect\nconst HOVER_COLOR_MAP: PcbColorMap = {\n ...DEFAULT_PCB_COLOR_MAP,\n copper: {\n ...DEFAULT_PCB_COLOR_MAP.copper,\n top: color(colors.board.pad_front).lighten(0.5).toString(),\n bottom: color(colors.board.pad_back).lighten(0.5).toString(),\n inner1: color(colors.board.copper.in1).lighten(0.5).toString(),\n inner2: color(colors.board.copper.in2).lighten(0.5).toString(),\n inner3: color(colors.board.copper.in3).lighten(0.5).toString(),\n inner4: color(colors.board.copper.in4).lighten(0.5).toString(),\n inner5: color(colors.board.copper.in5).lighten(0.5).toString(),\n inner6: color(colors.board.copper.in6).lighten(0.5).toString(),\n inner7: color(colors.board.copper.in7).lighten(0.5).toString(),\n inner8: color(colors.board.copper.in8).lighten(0.5).toString(),\n },\n}\n\nexport function isPcbVia(element: AnyCircuitElement) {\n return element.type === \"pcb_via\"\n}\n\nexport function drawPcbViaElementsForLayer({\n canvas,\n elements,\n layers,\n realToCanvasMat,\n primitives,\n drawSoldermask,\n}: {\n canvas: HTMLCanvasElement\n elements: AnyCircuitElement[]\n layers: PcbRenderLayer[]\n realToCanvasMat: Matrix\n primitives?: Primitive[]\n drawSoldermask?: boolean\n}) {\n // Filter vias to only those on the specified layers\n const viaElements = elements.filter(isPcbVia).filter((element) => {\n // Vias are typically drawn on copper layers\n return layers.some((layer) => layer.includes(\"copper\"))\n })\n\n if (viaElements.length === 0) return\n\n // Find which via elements have highlighted primitives\n const highlightedElementIds = new Set<string>()\n if (primitives) {\n for (const primitive of primitives) {\n if (\n (primitive.is_mouse_over || primitive.is_in_highlighted_net) &&\n primitive._element?.type === \"pcb_via\"\n ) {\n highlightedElementIds.add(primitive._element.pcb_via_id)\n }\n }\n }\n\n // Separate highlighted and non-highlighted elements\n const highlightedElements = viaElements.filter((element) =>\n highlightedElementIds.has(element.pcb_via_id),\n )\n const nonHighlightedElements = viaElements.filter(\n (element) => !highlightedElementIds.has(element.pcb_via_id),\n )\n\n // Draw non-highlighted elements with default colors\n if (nonHighlightedElements.length > 0) {\n const drawer = new CircuitToCanvasDrawer(canvas)\n drawer.realToCanvasMat = realToCanvasMat\n drawer.drawElements(nonHighlightedElements, { layers, drawSoldermask })\n }\n\n // Draw highlighted elements with lighter colors\n if (highlightedElements.length > 0) {\n const highlightDrawer = new CircuitToCanvasDrawer(canvas)\n highlightDrawer.configure({ colorOverrides: HOVER_COLOR_MAP })\n highlightDrawer.realToCanvasMat = realToCanvasMat\n highlightDrawer.drawElements(highlightedElements, {\n layers,\n drawSoldermask,\n })\n }\n}\n","import type { Primitive } from \"./types\"\n\nexport const getPrimitivesForDrawer = ({\n primitives,\n isShowingSolderMask,\n isShowingSilkscreen,\n isShowingFabricationNotes,\n}: {\n primitives: Primitive[]\n isShowingSolderMask: boolean\n isShowingSilkscreen: boolean\n isShowingFabricationNotes: boolean\n}) =>\n primitives\n .filter(\n (primitive) =>\n isShowingSolderMask || !primitive.layer?.includes(\"soldermask\"),\n )\n .filter(\n (primitive) =>\n isShowingSilkscreen || !primitive.layer?.includes(\"silkscreen\"),\n )\n .filter(\n (primitive) =>\n isShowingFabricationNotes || !primitive.layer?.includes(\"fabrication\"),\n )\n .filter((primitive) => primitive.layer !== \"board\")\n .filter((primitive) => primitive._element?.type !== \"pcb_smtpad\")\n .filter(\n (primitive) =>\n primitive._element?.type !== \"pcb_plated_hole\" ||\n primitive.layer === \"drill\",\n )\n .filter((primitive) => primitive._element?.type !== \"pcb_via\")\n .filter((primitive) => primitive._element?.type !== \"pcb_trace\")\n .filter((primitive) => primitive._element?.type !== \"pcb_copper_text\")\n","import type { AnyCircuitElement, LayerRef, PcbRenderLayer } from \"circuit-json\"\nimport { Drawer } from \"lib/Drawer\"\nimport {\n getCopperLayerRefsFromElements,\n getCopperRenderLayer,\n getOrderedCanvasLayers,\n} from \"lib/copper-layers\"\nimport { drawCopperPourElementsForLayer } from \"lib/draw-copper-pour\"\nimport { drawCourtyardElementsForLayer } from \"lib/draw-courtyard\"\nimport { drawFabricationNoteElementsForLayer } from \"lib/draw-fabrication-note\"\nimport { drawGrid } from \"lib/draw-grid\"\nimport { drawPcbHoleElementsForLayer } from \"lib/draw-hole\"\nimport { drawPcbBoardElements } from \"lib/draw-pcb-board\"\nimport { drawPcbCopperTextElementsForLayer } from \"lib/draw-pcb-copper-text\"\nimport { drawPcbCutoutElementsForLayer } from \"lib/draw-pcb-cutout\"\nimport { drawPcbKeepoutElementsForLayer } from \"lib/draw-pcb-keepout\"\nimport { drawPcbNoteElementsForLayer } from \"lib/draw-pcb-note\"\nimport { drawPcbPanelElements } from \"lib/draw-pcb-panel\"\nimport { drawPcbSmtPadElementsForLayer } from \"lib/draw-pcb-smtpad\"\nimport { drawPcbTraceElementsForLayer } from \"lib/draw-pcb-trace\"\nimport { drawPlatedHolePads } from \"lib/draw-plated-hole\"\nimport { drawPrimitives } from \"lib/draw-primitives\"\nimport { drawSilkscreenElementsForLayer } from \"lib/draw-silkscreen\"\nimport { drawSoldermaskElementsForLayer } from \"lib/draw-soldermask\"\nimport { drawPcbViaElementsForLayer } from \"lib/draw-via\"\nimport { getPrimitivesForDrawer } from \"lib/get-primitives-for-drawer\"\nimport type { GridConfig, Primitive } from \"lib/types\"\nimport React, { useEffect, useRef } from \"react\"\nimport { SuperGrid, toMMSI } from \"react-supergrid\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\n\ninterface Props {\n primitives: Primitive[]\n elements: AnyCircuitElement[]\n defaultUnit?: string\n transform?: Matrix\n grid?: GridConfig\n width?: number\n height?: number\n}\n\nexport const CanvasPrimitiveRenderer = ({\n primitives,\n elements,\n transform,\n grid,\n width = 500,\n height = 500,\n}: Props) => {\n const canvasRefs = useRef<Record<string, HTMLCanvasElement>>({})\n const selectedLayer = useGlobalStore((s) => s.selected_layer)\n const isShowingCopperPours = useGlobalStore((s) => s.is_showing_copper_pours)\n const isShowingSolderMask = useGlobalStore((s) => s.is_showing_solder_mask)\n const isShowingFabricationNotes = useGlobalStore(\n (s) => s.is_showing_fabrication_notes,\n )\n const isShowingPcbNotes = useGlobalStore((s) => s.is_showing_pcb_notes)\n const isShowingCourtyards = useGlobalStore((s) => s.is_showing_courtyards)\n const isShowingSilkscreen = useGlobalStore((s) => s.is_showing_silkscreen)\n\n useEffect(() => {\n if (!canvasRefs.current) return\n if (Object.keys(canvasRefs.current).length === 0) return\n\n // Keep all non-null canvas refs so hidden layers are still cleared.\n const availableCanvasRefs = Object.fromEntries(\n Object.entries(canvasRefs.current).filter(([layer, canvas]) => {\n if (!canvas) return false\n return true\n }),\n )\n\n if (Object.keys(availableCanvasRefs).length === 0) return\n\n const drawer = new Drawer(availableCanvasRefs)\n if (transform) drawer.transform = transform\n drawer.clear()\n drawer.foregroundLayer = selectedLayer\n\n // Filter out solder mask and silkscreen primitives when disabled\n // Also filter out SMT pad primitives since they're drawn with circuit-to-canvas\n const filteredPrimitives = getPrimitivesForDrawer({\n primitives,\n isShowingSolderMask,\n isShowingSilkscreen,\n isShowingFabricationNotes,\n })\n\n drawPrimitives(drawer, filteredPrimitives)\n\n // Draw silkscreen elements using circuit-to-canvas\n if (transform) {\n // Draw plated holes using circuit-to-canvas (pads on copper layers, drills on drill layer)\n const copperLayers: Array<{\n canvas?: HTMLCanvasElement\n layer: LayerRef\n copperLayer: PcbRenderLayer\n }> = getCopperLayerRefsFromElements(elements).map((layer) => ({\n canvas: canvasRefs.current[layer],\n layer,\n copperLayer: getCopperRenderLayer(layer),\n }))\n\n // Draw PCB traces using circuit-to-canvas (on copper layers)\n for (const { canvas, copperLayer } of copperLayers) {\n if (!canvas) continue\n drawPcbTraceElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n primitives,\n showCopperPours: isShowingCopperPours,\n })\n }\n\n for (const { canvas, copperLayer } of copperLayers) {\n if (!canvas) continue\n drawPcbCopperTextElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n })\n }\n\n for (const { canvas, copperLayer, layer } of copperLayers) {\n if (!canvas) continue\n drawPlatedHolePads({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n primitives,\n drawSoldermask:\n isShowingSolderMask && (layer === \"top\" || layer === \"bottom\"),\n })\n }\n\n // Draw copper pours on every supported copper layer, including inners.\n for (const { canvas, copperLayer } of copperLayers) {\n if (!canvas) continue\n drawCopperPourElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n })\n }\n\n // Draw SMT pads using circuit-to-canvas (on copper layers)\n for (const { canvas, copperLayer } of copperLayers) {\n if (!canvas) continue\n drawPcbSmtPadElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n primitives,\n drawSoldermask: isShowingSolderMask,\n })\n }\n\n // Draw vias using circuit-to-canvas (on copper layers)\n for (const { canvas, copperLayer, layer } of copperLayers) {\n if (!canvas) continue\n drawPcbViaElementsForLayer({\n canvas,\n elements,\n layers: [copperLayer],\n realToCanvasMat: transform,\n primitives,\n drawSoldermask:\n isShowingSolderMask && (layer === \"top\" || layer === \"bottom\"),\n })\n }\n\n if (isShowingSolderMask) {\n const soldermaskLayer = selectedLayer === \"bottom\" ? \"bottom\" : \"top\"\n const drawSoldermaskTop = soldermaskLayer === \"top\"\n const drawSoldermaskBottom = soldermaskLayer === \"bottom\"\n\n const topSoldermaskCanvas = canvasRefs.current.soldermask_top\n if (topSoldermaskCanvas && soldermaskLayer === \"top\") {\n drawSoldermaskElementsForLayer({\n canvas: topSoldermaskCanvas,\n elements,\n layers: [\"top_soldermask\"],\n realToCanvasMat: transform,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n primitives,\n })\n }\n\n const bottomSoldermaskCanvas = canvasRefs.current.soldermask_bottom\n if (bottomSoldermaskCanvas && soldermaskLayer === \"bottom\") {\n drawSoldermaskElementsForLayer({\n canvas: bottomSoldermaskCanvas,\n elements,\n layers: [\"bottom_soldermask\"],\n realToCanvasMat: transform,\n drawSoldermaskTop,\n drawSoldermaskBottom,\n primitives,\n })\n }\n }\n\n // Draw PCB holes\n const drillCanvas = canvasRefs.current.drill\n if (drillCanvas) {\n drawPcbHoleElementsForLayer({\n canvas: drillCanvas,\n elements,\n layers: [\"drill\"],\n realToCanvasMat: transform,\n })\n }\n\n // Draw silkscreen if enabled\n if (isShowingSilkscreen) {\n const topSilkscreenCanvas = canvasRefs.current.top_silkscreen\n if (topSilkscreenCanvas) {\n drawSilkscreenElementsForLayer({\n canvas: topSilkscreenCanvas,\n elements,\n layers: [\"top_silkscreen\"],\n realToCanvasMat: transform,\n })\n }\n\n const bottomSilkscreenCanvas = canvasRefs.current.bottom_silkscreen\n if (bottomSilkscreenCanvas) {\n drawSilkscreenElementsForLayer({\n canvas: bottomSilkscreenCanvas,\n elements,\n layers: [\"bottom_silkscreen\"],\n realToCanvasMat: transform,\n })\n }\n }\n\n // Draw top fabrication\n if (isShowingFabricationNotes) {\n const topFabCanvas = canvasRefs.current.top_fabrication\n if (topFabCanvas) {\n drawFabricationNoteElementsForLayer({\n canvas: topFabCanvas,\n elements,\n layers: [\"top_fabrication_note\"],\n realToCanvasMat: transform,\n })\n }\n\n // Draw bottom fabrication\n const bottomFabCanvas = canvasRefs.current.bottom_fabrication\n if (bottomFabCanvas) {\n drawFabricationNoteElementsForLayer({\n canvas: bottomFabCanvas,\n elements,\n layers: [\"bottom_fabrication_note\"],\n realToCanvasMat: transform,\n })\n }\n }\n\n if (isShowingPcbNotes) {\n // Draw bottom notes\n const bottomNotesCanvas = canvasRefs.current.bottom_notes\n if (bottomNotesCanvas) {\n drawPcbNoteElementsForLayer({\n canvas: bottomNotesCanvas,\n elements,\n layers: [\"bottom_user_note\"],\n realToCanvasMat: transform,\n })\n }\n\n // Draw top notes\n const topNotesCanvas = canvasRefs.current.top_notes\n if (topNotesCanvas) {\n drawPcbNoteElementsForLayer({\n canvas: topNotesCanvas,\n elements,\n layers: [\"top_user_note\"],\n realToCanvasMat: transform,\n })\n }\n }\n\n // Draw top courtyard\n if (isShowingCourtyards) {\n const topCourtyardCanvas = canvasRefs.current.top_courtyard\n if (topCourtyardCanvas) {\n drawCourtyardElementsForLayer({\n canvas: topCourtyardCanvas,\n elements,\n layers: [\"top_courtyard\" as PcbRenderLayer],\n realToCanvasMat: transform,\n })\n }\n\n // Draw bottom courtyard\n const bottomCourtyardCanvas = canvasRefs.current.bottom_courtyard\n if (bottomCourtyardCanvas) {\n drawCourtyardElementsForLayer({\n canvas: bottomCourtyardCanvas,\n elements,\n layers: [\"bottom_courtyard\" as PcbRenderLayer],\n realToCanvasMat: transform,\n })\n }\n }\n\n // Draw board outline using circuit-to-canvas\n const boardCanvas = canvasRefs.current.board\n if (boardCanvas) {\n drawPcbPanelElements({\n canvas: boardCanvas,\n elements,\n layers: [],\n realToCanvasMat: transform,\n drawSoldermask: isShowingSolderMask,\n })\n drawPcbBoardElements({\n canvas: boardCanvas,\n elements,\n layers: [],\n realToCanvasMat: transform,\n drawSoldermask: isShowingSolderMask,\n })\n }\n\n // Draw PCB cutouts using circuit-to-canvas\n const edgeCutsCanvas = canvasRefs.current.edge_cuts\n if (edgeCutsCanvas) {\n drawPcbCutoutElementsForLayer({\n canvas: edgeCutsCanvas,\n elements,\n layers: [\"edge_cuts\"],\n realToCanvasMat: transform,\n })\n }\n\n // Draw keepouts using circuit-to-canvas (on copper layers)\n for (const { canvas, layer } of copperLayers) {\n if (!canvas) continue\n drawPcbKeepoutElementsForLayer({\n canvas,\n elements,\n layer,\n realToCanvasMat: transform,\n })\n }\n }\n\n drawer.orderAndFadeLayers()\n }, [\n primitives,\n elements,\n transform,\n selectedLayer,\n isShowingCopperPours,\n isShowingSolderMask,\n isShowingFabricationNotes,\n isShowingPcbNotes,\n isShowingCourtyards,\n isShowingSilkscreen,\n ])\n\n return (\n <div\n style={{\n backgroundColor: \"black\",\n width,\n height,\n position: \"relative\",\n }}\n >\n <SuperGrid\n textColor=\"rgba(0,255,0,0.8)\"\n majorColor=\"rgba(0,255,0,0.4)\"\n minorColor=\"rgba(0,255,0,0.2)\"\n screenSpaceCellSize={200}\n width={width}\n height={height}\n transform={transform!}\n stringifyCoord={(x, y, z) => `${toMMSI(x, z)}, ${toMMSI(y, z)}`}\n />\n {getOrderedCanvasLayers(elements)\n .filter((layer) => {\n if (!isShowingSolderMask && layer.includes(\"soldermask\")) return false\n if (!isShowingSilkscreen && layer.includes(\"silkscreen\")) return false\n return true\n })\n .map((l) => l.replace(/-/g, \"\"))\n .map((layer, i) => (\n <canvas\n key={layer}\n className={`pcb-layer-${layer}`}\n ref={(el) => {\n canvasRefs.current ??= {}\n if (el) {\n canvasRefs.current[layer] = el\n } else {\n // Clean up ref when element is removed\n delete canvasRefs.current[layer]\n }\n }}\n style={{\n position: \"absolute\",\n zIndex: i,\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n }}\n width={width}\n height={height}\n />\n ))}\n </div>\n )\n}\n","import {\n glyphAdvanceRatio,\n glyphLineAlphabet,\n kerningRatio,\n textMetrics,\n} from \"@tscircuit/alphabet\"\nimport type { NinePointAnchor } from \"./types\"\n\nexport interface StrokeAlphabetContext {\n beginPath(): void\n moveTo(x: number, y: number): void\n lineTo(x: number, y: number): void\n stroke(): void\n save(): void\n restore(): void\n translate(x: number, y: number): void\n rotate(angleRadians: number): void\n strokeStyle: string\n lineWidth: number\n lineCap?: string\n lineJoin?: string\n}\n\nexport type AlphabetLayout = {\n width: number\n height: number\n glyphWidth: number\n letterSpacing: number\n spaceWidth: number\n strokeWidth: number\n lineHeight: number\n lines: string[]\n lineWidths: number[]\n}\n\nconst getAdvanceRatio = (char: string): number =>\n glyphAdvanceRatio[char] ??\n (char === \" \" ? textMetrics.spaceWidthRatio : textMetrics.glyphWidthRatio)\n\nexport function getAlphabetAdvanceWidth(\n char: string,\n nextChar: string | undefined,\n fontSize: number,\n): number {\n const advanceRatio = getAdvanceRatio(char)\n const letterSpacingRatio = nextChar ? textMetrics.letterSpacingRatio : 0\n const kerningAdjustmentRatio = nextChar\n ? kerningRatio[char]?.[nextChar] ?? 0\n : 0\n\n return fontSize * (advanceRatio + letterSpacingRatio + kerningAdjustmentRatio)\n}\n\nexport function getAlphabetLayout(\n text: string,\n fontSize: number,\n): AlphabetLayout {\n const glyphWidth = fontSize * textMetrics.glyphWidthRatio\n const letterSpacing = fontSize * textMetrics.letterSpacingRatio\n const spaceWidth = fontSize * textMetrics.spaceWidthRatio\n const strokeWidth = fontSize * textMetrics.strokeWidthRatio\n const lineHeight = fontSize * textMetrics.lineHeightRatio\n\n const lines = text.replace(/\\\\n/g, \"\\n\").split(\"\\n\")\n const lineWidths = lines.map((line) => {\n const characters = Array.from(line)\n return characters.reduce(\n (sum, char, index) =>\n sum + getAlphabetAdvanceWidth(char, characters[index + 1], fontSize),\n 0,\n )\n })\n\n const width = lineWidths.reduce(\n (maxWidth, lineWidth) => Math.max(maxWidth, lineWidth),\n 0,\n )\n const height =\n lines.length > 1 ? fontSize + (lines.length - 1) * lineHeight : fontSize\n\n return {\n width,\n height,\n glyphWidth,\n letterSpacing,\n spaceWidth,\n strokeWidth,\n lineHeight,\n lines,\n lineWidths,\n }\n}\n\nexport function getTextStartPosition(\n alignment: NinePointAnchor,\n layout: AlphabetLayout,\n): { x: number; y: number } {\n const totalWidth = layout.width + layout.strokeWidth\n const totalHeight = layout.height + layout.strokeWidth\n\n let x = 0\n let y = 0\n\n if (\n alignment === \"center\" ||\n alignment === \"top_center\" ||\n alignment === \"bottom_center\"\n ) {\n x = -totalWidth / 2\n } else if (\n alignment === \"top_right\" ||\n alignment === \"bottom_right\" ||\n alignment === \"center_right\"\n ) {\n x = -totalWidth\n }\n\n if (\n alignment === \"center\" ||\n alignment === \"center_left\" ||\n alignment === \"center_right\"\n ) {\n y = -totalHeight / 2\n } else if (\n alignment === \"bottom_left\" ||\n alignment === \"bottom_right\" ||\n alignment === \"bottom_center\"\n ) {\n y = -totalHeight\n }\n\n return { x, y }\n}\n\nexport function getLineStartX({\n alignment,\n lineWidth,\n maxWidth,\n strokeWidth,\n}: {\n alignment: NinePointAnchor\n lineWidth: number\n maxWidth: number\n strokeWidth: number\n}): number {\n const totalLineWidth = lineWidth + strokeWidth\n const totalMaxWidth = maxWidth + strokeWidth\n\n if (\n alignment === \"top_left\" ||\n alignment === \"bottom_left\" ||\n alignment === \"center_left\"\n ) {\n return 0\n }\n\n if (\n alignment === \"top_right\" ||\n alignment === \"bottom_right\" ||\n alignment === \"center_right\"\n ) {\n return totalMaxWidth - totalLineWidth\n }\n\n return (totalMaxWidth - totalLineWidth) / 2\n}\n\nexport function strokeAlphabetLine({\n ctx,\n line,\n fontSize,\n startX,\n startY,\n layout,\n}: {\n ctx: StrokeAlphabetContext\n line: string\n fontSize: number\n startX: number\n startY: number\n layout: AlphabetLayout\n}): void {\n const height = fontSize\n const glyphScaleX = fontSize\n const characters = Array.from(line)\n let cursor = startX + layout.strokeWidth / 2\n\n characters.forEach((char, index) => {\n const glyphLines = glyphLineAlphabet[char]\n\n if (glyphLines?.length) {\n ctx.beginPath()\n for (const glyph of glyphLines) {\n const x1 = cursor + glyph.x1 * glyphScaleX\n const y1 = startY + (1 - glyph.y1) * height\n const x2 = cursor + glyph.x2 * glyphScaleX\n const y2 = startY + (1 - glyph.y2) * height\n ctx.moveTo(x1, y1)\n ctx.lineTo(x2, y2)\n }\n ctx.stroke()\n }\n\n cursor += getAlphabetAdvanceWidth(char, characters[index + 1], fontSize)\n })\n}\n\nexport function strokeAlphabetText({\n ctx,\n text,\n fontSize,\n startX,\n startY,\n color,\n anchorAlignment = \"center\",\n rotationRadians,\n}: {\n ctx: StrokeAlphabetContext\n text: string\n fontSize: number\n startX: number\n startY: number\n color: string\n anchorAlignment?: NinePointAnchor\n rotationRadians?: number\n}): void {\n if (!text) return\n\n const layout = getAlphabetLayout(text, fontSize)\n const startPosition = getTextStartPosition(anchorAlignment, layout)\n const { lines, lineWidths, lineHeight, width, strokeWidth } = layout\n\n ctx.save()\n ctx.translate(startX, startY)\n if (rotationRadians) {\n ctx.rotate(rotationRadians)\n }\n\n ctx.strokeStyle = color\n ctx.lineWidth = strokeWidth\n ctx.lineCap = \"round\"\n ctx.lineJoin = \"round\"\n\n lines.forEach((line, lineIndex) => {\n const lineStartX =\n startPosition.x +\n getLineStartX({\n alignment: anchorAlignment,\n lineWidth: lineWidths[lineIndex]!,\n maxWidth: width,\n strokeWidth,\n })\n const lineStartY = startPosition.y + lineIndex * lineHeight\n\n strokeAlphabetLine({\n ctx,\n line,\n fontSize,\n startX: lineStartX,\n startY: lineStartY,\n layout,\n })\n })\n\n ctx.restore()\n}\n","/**\n * Decode bytes to text\n * @param bytes - Bytes to decode\n * @param encoding - Text encoding\n * @returns The decoded text\n */\nexport function decode(bytes: Uint8Array, encoding = 'utf8'): string {\n const decoder = new TextDecoder(encoding);\n return decoder.decode(bytes);\n}\n\nconst encoder = new TextEncoder();\n\n/**\n * Encode text to utf8\n * @param str - Text to encode\n * @returns The encoded bytes\n */\nexport function encode(str: string): Uint8Array {\n return encoder.encode(str);\n}\n","import { decode, encode } from './text.ts';\n\nconst defaultByteLength = 1024 * 8;\n\nconst hostBigEndian = (() => {\n const array = new Uint8Array(4);\n const view = new Uint32Array(array.buffer);\n return !((view[0] = 1) & (array[0] as number));\n})();\n\nexport type InputData = number | ArrayBufferLike | ArrayBufferView | IOBuffer;\n\nconst typedArrays = {\n int8: globalThis.Int8Array,\n uint8: globalThis.Uint8Array,\n int16: globalThis.Int16Array,\n uint16: globalThis.Uint16Array,\n int32: globalThis.Int32Array,\n uint32: globalThis.Uint32Array,\n uint64: globalThis.BigUint64Array,\n int64: globalThis.BigInt64Array,\n float32: globalThis.Float32Array,\n float64: globalThis.Float64Array,\n};\n\ntype TypedArrays = typeof typedArrays;\n\nexport interface IOBufferOptions {\n /**\n * Ignore the first n bytes of the ArrayBuffer.\n */\n offset?: number;\n}\n\nexport class IOBuffer {\n /**\n * Reference to the internal ArrayBuffer object.\n */\n public buffer: ArrayBufferLike;\n\n /**\n * Byte length of the internal ArrayBuffer.\n */\n public byteLength: number;\n\n /**\n * Byte offset of the internal ArrayBuffer.\n */\n public byteOffset: number;\n\n /**\n * Byte length of the internal ArrayBuffer.\n */\n public length: number;\n\n /**\n * The current offset of the buffer's pointer.\n */\n public offset: number;\n\n private lastWrittenByte: number;\n private littleEndian: boolean;\n\n private _data: DataView;\n private _mark: number;\n private _marks: number[];\n\n /**\n * Create a new IOBuffer.\n * @param data - The data to construct the IOBuffer with.\n * If data is a number, it will be the new buffer's length<br>\n * If data is `undefined`, the buffer will be initialized with a default length of 8Kb<br>\n * If data is an ArrayBuffer, SharedArrayBuffer, an ArrayBufferView (Typed Array), an IOBuffer instance,\n * or a Node.js Buffer, a view will be created over the underlying ArrayBuffer.\n * @param options - An object for the options.\n * @returns A new IOBuffer instance.\n */\n public constructor(\n data: InputData = defaultByteLength,\n options: IOBufferOptions = {},\n ) {\n let dataIsGiven = false;\n if (typeof data === 'number') {\n data = new ArrayBuffer(data);\n } else {\n dataIsGiven = true;\n this.lastWrittenByte = data.byteLength;\n }\n const offset = options.offset ? options.offset >>> 0 : 0;\n const byteLength = data.byteLength - offset;\n let dvOffset = offset;\n if (ArrayBuffer.isView(data) || data instanceof IOBuffer) {\n if (data.byteLength !== data.buffer.byteLength) {\n dvOffset = data.byteOffset + offset;\n }\n data = data.buffer;\n }\n if (dataIsGiven) {\n this.lastWrittenByte = byteLength;\n } else {\n this.lastWrittenByte = 0;\n }\n this.buffer = data;\n this.length = byteLength;\n this.byteLength = byteLength;\n this.byteOffset = dvOffset;\n this.offset = 0;\n this.littleEndian = true;\n this._data = new DataView(this.buffer, dvOffset, byteLength);\n this._mark = 0;\n this._marks = [];\n }\n\n /**\n * Checks if the memory allocated to the buffer is sufficient to store more\n * bytes after the offset.\n * @param byteLength - The needed memory in bytes.\n * @returns `true` if there is sufficient space and `false` otherwise.\n */\n public available(byteLength = 1): boolean {\n return this.offset + byteLength <= this.length;\n }\n\n /**\n * Check if little-endian mode is used for reading and writing multi-byte\n * values.\n * @returns `true` if little-endian mode is used, `false` otherwise.\n */\n public isLittleEndian(): boolean {\n return this.littleEndian;\n }\n\n /**\n * Set little-endian mode for reading and writing multi-byte values.\n * @returns This.\n */\n public setLittleEndian(): this {\n this.littleEndian = true;\n return this;\n }\n\n /**\n * Check if big-endian mode is used for reading and writing multi-byte values.\n * @returns `true` if big-endian mode is used, `false` otherwise.\n */\n public isBigEndian(): boolean {\n return !this.littleEndian;\n }\n\n /**\n * Switches to big-endian mode for reading and writing multi-byte values.\n * @returns This.\n */\n public setBigEndian(): this {\n this.littleEndian = false;\n return this;\n }\n\n /**\n * Move the pointer n bytes forward.\n * @param n - Number of bytes to skip.\n * @returns This.\n */\n public skip(n = 1): this {\n this.offset += n;\n return this;\n }\n\n /**\n * Move the pointer n bytes backward.\n * @param n - Number of bytes to move back.\n * @returns This.\n */\n public back(n = 1): this {\n this.offset -= n;\n return this;\n }\n\n /**\n * Move the pointer to the given offset.\n * @param offset - The offset to move to.\n * @returns This.\n */\n public seek(offset: number): this {\n this.offset = offset;\n return this;\n }\n\n /**\n * Store the current pointer offset.\n * @see {@link IOBuffer#reset}\n * @returns This.\n */\n public mark(): this {\n this._mark = this.offset;\n return this;\n }\n\n /**\n * Move the pointer back to the last pointer offset set by mark.\n * @see {@link IOBuffer#mark}\n * @returns This.\n */\n public reset(): this {\n this.offset = this._mark;\n return this;\n }\n\n /**\n * Push the current pointer offset to the mark stack.\n * @see {@link IOBuffer#popMark}\n * @returns This.\n */\n public pushMark(): this {\n this._marks.push(this.offset);\n return this;\n }\n\n /**\n * Pop the last pointer offset from the mark stack, and set the current\n * pointer offset to the popped value.\n * @see {@link IOBuffer#pushMark}\n * @returns This.\n */\n public popMark(): this {\n const offset = this._marks.pop();\n if (offset === undefined) {\n throw new Error('Mark stack empty');\n }\n this.seek(offset);\n return this;\n }\n\n /**\n * Move the pointer offset back to 0.\n * @returns This.\n */\n public rewind(): this {\n this.offset = 0;\n return this;\n }\n\n /**\n * Make sure the buffer has sufficient memory to write a given byteLength at\n * the current pointer offset.\n * If the buffer's memory is insufficient, this method will create a new\n * buffer (a copy) with a length that is twice (byteLength + current offset).\n * @param byteLength - The needed memory in bytes.\n * @returns This.\n */\n public ensureAvailable(byteLength = 1): this {\n if (!this.available(byteLength)) {\n const lengthNeeded = this.offset + byteLength;\n const newLength = lengthNeeded * 2;\n const newArray = new Uint8Array(newLength);\n newArray.set(new Uint8Array(this.buffer));\n this.buffer = newArray.buffer;\n this.length = newLength;\n this.byteLength = newLength;\n this._data = new DataView(this.buffer);\n }\n return this;\n }\n\n /**\n * Read a byte and return false if the byte's value is 0, or true otherwise.\n * Moves pointer forward by one byte.\n * @returns The read boolean.\n */\n public readBoolean(): boolean {\n return this.readUint8() !== 0;\n }\n\n /**\n * Read a signed 8-bit integer and move pointer forward by 1 byte.\n * @returns The read byte.\n */\n public readInt8(): number {\n return this._data.getInt8(this.offset++);\n }\n\n /**\n * Read an unsigned 8-bit integer and move pointer forward by 1 byte.\n * @returns The read byte.\n */\n public readUint8(): number {\n return this._data.getUint8(this.offset++);\n }\n\n /**\n * Alias for {@link IOBuffer#readUint8}.\n * @returns The read byte.\n */\n public readByte(): number {\n return this.readUint8();\n }\n\n /**\n * Read `n` bytes and move pointer forward by `n` bytes.\n * @param n - Number of bytes to read.\n * @returns The read bytes.\n */\n public readBytes(n = 1): Uint8Array {\n return this.readArray(n, 'uint8');\n }\n\n /**\n * Creates an array of corresponding to the type `type` and size `size`.\n * For example, type `uint8` will create a `Uint8Array`.\n * @param size - size of the resulting array\n * @param type - number type of elements to read\n * @returns The read array.\n */\n public readArray<T extends keyof typeof typedArrays>(\n size: number,\n type: T,\n ): InstanceType<TypedArrays[T]> {\n const bytes = typedArrays[type].BYTES_PER_ELEMENT * size;\n const offset = this.byteOffset + this.offset;\n const slice = this.buffer.slice(offset, offset + bytes);\n if (\n this.littleEndian === hostBigEndian &&\n type !== 'uint8' &&\n type !== 'int8'\n ) {\n const slice = new Uint8Array(this.buffer.slice(offset, offset + bytes));\n slice.reverse();\n const returnArray = new typedArrays[type](slice.buffer as ArrayBuffer);\n this.offset += bytes;\n returnArray.reverse();\n return returnArray as InstanceType<TypedArrays[T]>;\n }\n const returnArray = new typedArrays[type](slice as ArrayBuffer);\n this.offset += bytes;\n return returnArray as InstanceType<TypedArrays[T]>;\n }\n\n /**\n * Read a 16-bit signed integer and move pointer forward by 2 bytes.\n * @returns The read value.\n */\n public readInt16(): number {\n const value = this._data.getInt16(this.offset, this.littleEndian);\n this.offset += 2;\n return value;\n }\n\n /**\n * Read a 16-bit unsigned integer and move pointer forward by 2 bytes.\n * @returns The read value.\n */\n public readUint16(): number {\n const value = this._data.getUint16(this.offset, this.littleEndian);\n this.offset += 2;\n return value;\n }\n\n /**\n * Read a 32-bit signed integer and move pointer forward by 4 bytes.\n * @returns The read value.\n */\n public readInt32(): number {\n const value = this._data.getInt32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n /**\n * Read a 32-bit unsigned integer and move pointer forward by 4 bytes.\n * @returns The read value.\n */\n public readUint32(): number {\n const value = this._data.getUint32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n /**\n * Read a 32-bit floating number and move pointer forward by 4 bytes.\n * @returns The read value.\n */\n public readFloat32(): number {\n const value = this._data.getFloat32(this.offset, this.littleEndian);\n this.offset += 4;\n return value;\n }\n\n /**\n * Read a 64-bit floating number and move pointer forward by 8 bytes.\n * @returns The read value.\n */\n public readFloat64(): number {\n const value = this._data.getFloat64(this.offset, this.littleEndian);\n this.offset += 8;\n return value;\n }\n\n /**\n * Read a 64-bit signed integer number and move pointer forward by 8 bytes.\n * @returns The read value.\n */\n public readBigInt64(): bigint {\n const value = this._data.getBigInt64(this.offset, this.littleEndian);\n this.offset += 8;\n return value;\n }\n\n /**\n * Read a 64-bit unsigned integer number and move pointer forward by 8 bytes.\n * @returns The read value.\n */\n public readBigUint64(): bigint {\n const value = this._data.getBigUint64(this.offset, this.littleEndian);\n this.offset += 8;\n return value;\n }\n\n /**\n * Read a 1-byte ASCII character and move pointer forward by 1 byte.\n * @returns The read character.\n */\n public readChar(): string {\n // eslint-disable-next-line unicorn/prefer-code-point\n return String.fromCharCode(this.readInt8());\n }\n\n /**\n * Read `n` 1-byte ASCII characters and move pointer forward by `n` bytes.\n * @param n - Number of characters to read.\n * @returns The read characters.\n */\n public readChars(n = 1): string {\n let result = '';\n for (let i = 0; i < n; i++) {\n result += this.readChar();\n }\n return result;\n }\n\n /**\n * Read the next `n` bytes, return a UTF-8 decoded string and move pointer\n * forward by `n` bytes.\n * @param n - Number of bytes to read.\n * @returns The decoded string.\n */\n public readUtf8(n = 1): string {\n return decode(this.readBytes(n));\n }\n\n /**\n * Read the next `n` bytes, return a string decoded with `encoding` and move pointer\n * forward by `n` bytes.\n * If no encoding is passed, the function is equivalent to @see {@link IOBuffer#readUtf8}\n * @param n - Number of bytes to read.\n * @param encoding - The encoding to use. Default is 'utf8'.\n * @returns The decoded string.\n */\n public decodeText(n = 1, encoding = 'utf8'): string {\n return decode(this.readBytes(n), encoding);\n }\n\n /**\n * Write 0xff if the passed value is truthy, 0x00 otherwise and move pointer\n * forward by 1 byte.\n * @param value - The value to write.\n * @returns This.\n */\n public writeBoolean(value: unknown): this {\n this.writeUint8(value ? 0xff : 0x00);\n return this;\n }\n\n /**\n * Write `value` as an 8-bit signed integer and move pointer forward by 1 byte.\n * @param value - The value to write.\n * @returns This.\n */\n public writeInt8(value: number): this {\n this.ensureAvailable(1);\n this._data.setInt8(this.offset++, value);\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as an 8-bit unsigned integer and move pointer forward by 1\n * byte.\n * @param value - The value to write.\n * @returns This.\n */\n public writeUint8(value: number): this {\n this.ensureAvailable(1);\n this._data.setUint8(this.offset++, value);\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * An alias for {@link IOBuffer#writeUint8}.\n * @param value - The value to write.\n * @returns This.\n */\n public writeByte(value: number): this {\n return this.writeUint8(value);\n }\n\n /**\n * Write all elements of `bytes` as uint8 values and move pointer forward by\n * `bytes.length` bytes.\n * @param bytes - The array of bytes to write.\n * @returns This.\n */\n public writeBytes(bytes: ArrayLike<number>): this {\n this.ensureAvailable(bytes.length);\n // eslint-disable-next-line @typescript-eslint/prefer-for-of\n for (let i = 0; i < bytes.length; i++) {\n this._data.setUint8(this.offset++, bytes[i] as number);\n }\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 16-bit signed integer and move pointer forward by 2\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeInt16(value: number): this {\n this.ensureAvailable(2);\n this._data.setInt16(this.offset, value, this.littleEndian);\n this.offset += 2;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 16-bit unsigned integer and move pointer forward by 2\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeUint16(value: number): this {\n this.ensureAvailable(2);\n this._data.setUint16(this.offset, value, this.littleEndian);\n this.offset += 2;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 32-bit signed integer and move pointer forward by 4\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeInt32(value: number): this {\n this.ensureAvailable(4);\n this._data.setInt32(this.offset, value, this.littleEndian);\n this.offset += 4;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 32-bit unsigned integer and move pointer forward by 4\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeUint32(value: number): this {\n this.ensureAvailable(4);\n this._data.setUint32(this.offset, value, this.littleEndian);\n this.offset += 4;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 32-bit floating number and move pointer forward by 4\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeFloat32(value: number): this {\n this.ensureAvailable(4);\n this._data.setFloat32(this.offset, value, this.littleEndian);\n this.offset += 4;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 64-bit floating number and move pointer forward by 8\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeFloat64(value: number): this {\n this.ensureAvailable(8);\n this._data.setFloat64(this.offset, value, this.littleEndian);\n this.offset += 8;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 64-bit signed bigint and move pointer forward by 8\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeBigInt64(value: bigint): this {\n this.ensureAvailable(8);\n this._data.setBigInt64(this.offset, value, this.littleEndian);\n this.offset += 8;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write `value` as a 64-bit unsigned bigint and move pointer forward by 8\n * bytes.\n * @param value - The value to write.\n * @returns This.\n */\n public writeBigUint64(value: bigint): this {\n this.ensureAvailable(8);\n this._data.setBigUint64(this.offset, value, this.littleEndian);\n this.offset += 8;\n this._updateLastWrittenByte();\n return this;\n }\n\n /**\n * Write the charCode of `str`'s first character as an 8-bit unsigned integer\n * and move pointer forward by 1 byte.\n * @param str - The character to write.\n * @returns This.\n */\n public writeChar(str: string): this {\n // eslint-disable-next-line unicorn/prefer-code-point\n return this.writeUint8(str.charCodeAt(0));\n }\n\n /**\n * Write the charCodes of all `str`'s characters as 8-bit unsigned integers\n * and move pointer forward by `str.length` bytes.\n * @param str - The characters to write.\n * @returns This.\n */\n public writeChars(str: string): this {\n for (let i = 0; i < str.length; i++) {\n // eslint-disable-next-line unicorn/prefer-code-point\n this.writeUint8(str.charCodeAt(i));\n }\n return this;\n }\n\n /**\n * UTF-8 encode and write `str` to the current pointer offset and move pointer\n * forward according to the encoded length.\n * @param str - The string to write.\n * @returns This.\n */\n public writeUtf8(str: string): this {\n return this.writeBytes(encode(str));\n }\n\n /**\n * Export a Uint8Array view of the internal buffer.\n * The view starts at the byte offset and its length\n * is calculated to stop at the last written byte or the original length.\n * @returns A new Uint8Array view.\n */\n public toArray(): Uint8Array {\n return new Uint8Array(this.buffer, this.byteOffset, this.lastWrittenByte);\n }\n\n /**\n * Get the total number of bytes written so far, regardless of the current offset.\n * @returns - Total number of bytes.\n */\n public getWrittenByteLength() {\n return this.lastWrittenByte - this.byteOffset;\n }\n\n /**\n * Update the last written byte offset\n * @private\n */\n private _updateLastWrittenByte(): void {\n if (this.offset > this.lastWrittenByte) {\n this.lastWrittenByte = this.offset;\n }\n }\n}\n","import type { IOBuffer } from 'iobuffer';\n\nconst crcTable: number[] = [];\nfor (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) {\n if (c & 1) {\n c = 0xedb88320 ^ (c >>> 1);\n } else {\n c = c >>> 1;\n }\n }\n crcTable[n] = c;\n}\n\nconst initialCrc = 0xffffffff;\nfunction updateCrc(\n currentCrc: number,\n data: Uint8Array,\n length: number,\n): number {\n let c = currentCrc;\n for (let n = 0; n < length; n++) {\n c = crcTable[(c ^ data[n]) & 0xff] ^ (c >>> 8);\n }\n return c;\n}\n\nfunction crc(data: Uint8Array, length: number): number {\n return (updateCrc(initialCrc, data, length) ^ initialCrc) >>> 0;\n}\n\nexport function checkCrc(\n buffer: IOBuffer,\n crcLength: number,\n chunkName: string,\n) {\n const expectedCrc = buffer.readUint32();\n const actualCrc = crc(\n new Uint8Array(\n buffer.buffer,\n buffer.byteOffset + buffer.offset - crcLength - 4,\n crcLength,\n ),\n crcLength,\n ); // \"- 4\" because we already advanced by reading the CRC\n if (actualCrc !== expectedCrc) {\n throw new Error(\n `CRC mismatch for chunk ${chunkName}. Expected ${expectedCrc}, found ${actualCrc}`,\n );\n }\n}\n\nexport function writeCrc(buffer: IOBuffer, length: number) {\n buffer.writeUint32(\n crc(\n new Uint8Array(\n buffer.buffer,\n buffer.byteOffset + buffer.offset - length,\n length,\n ),\n length,\n ),\n );\n}\n","import { applyUnfilter } from './apply_unfilter.ts';\nimport type { DecodeInterlaceNullParams } from './decode_interlace_null.ts';\n\nconst uint16 = new Uint16Array([0x00ff]);\nconst uint8 = new Uint8Array(uint16.buffer);\nconst osIsLittleEndian = uint8[0] === 0xff;\n/**\n * Decodes the Adam7 interlaced PNG data.\n * @param params - DecodeInterlaceNullParams\n * @returns - array of pixel data.\n */\nexport function decodeInterlaceAdam7(params: DecodeInterlaceNullParams) {\n const { data, width, height, channels, depth } = params;\n\n // Adam7 interlacing pattern\n const passes = [\n { x: 0, y: 0, xStep: 8, yStep: 8 }, // Pass 1\n { x: 4, y: 0, xStep: 8, yStep: 8 }, // Pass 2\n { x: 0, y: 4, xStep: 4, yStep: 8 }, // Pass 3\n { x: 2, y: 0, xStep: 4, yStep: 4 }, // Pass 4\n { x: 0, y: 2, xStep: 2, yStep: 4 }, // Pass 5\n { x: 1, y: 0, xStep: 2, yStep: 2 }, // Pass 6\n { x: 0, y: 1, xStep: 1, yStep: 2 }, // Pass 7\n ];\n\n const bytesPerPixel = Math.ceil(depth / 8) * channels;\n const resultData = new Uint8Array(height * width * bytesPerPixel);\n\n let offset = 0;\n\n // Process each pass\n for (let passIndex = 0; passIndex < 7; passIndex++) {\n const pass = passes[passIndex];\n\n // Calculate pass dimensions\n const passWidth = Math.ceil((width - pass.x) / pass.xStep);\n const passHeight = Math.ceil((height - pass.y) / pass.yStep);\n\n if (passWidth <= 0 || passHeight <= 0) continue;\n\n const passLineBytes = passWidth * bytesPerPixel;\n const prevLine = new Uint8Array(passLineBytes);\n\n // Process each scanline in this pass\n for (let y = 0; y < passHeight; y++) {\n // First byte is the filter type\n const filterType = data[offset++];\n const currentLine = data.subarray(offset, offset + passLineBytes);\n offset += passLineBytes;\n\n // Create a new line for the unfiltered data\n const newLine = new Uint8Array(passLineBytes);\n\n // Apply the appropriate unfilter\n applyUnfilter(\n filterType,\n currentLine,\n newLine,\n prevLine,\n passLineBytes,\n bytesPerPixel,\n );\n prevLine.set(newLine);\n\n for (let x = 0; x < passWidth; x++) {\n const outputX = pass.x + x * pass.xStep;\n const outputY = pass.y + y * pass.yStep;\n if (outputX >= width || outputY >= height) continue;\n for (let i = 0; i < bytesPerPixel; i++) {\n resultData[(outputY * width + outputX) * bytesPerPixel + i] =\n newLine[x * bytesPerPixel + i];\n }\n }\n }\n }\n if (depth === 16) {\n const uint16Data = new Uint16Array(resultData.buffer);\n if (osIsLittleEndian) {\n for (let k = 0; k < uint16Data.length; k++) {\n // PNG is always big endian. Swap the bytes.\n uint16Data[k] = swap16(uint16Data[k]);\n }\n }\n return uint16Data;\n } else {\n return resultData;\n }\n}\n\nfunction swap16(val: number): number {\n return ((val & 0xff) << 8) | ((val >> 8) & 0xff);\n}\n","import type { PngDataArray } from '../types.ts';\n\nimport {\n unfilterAverage,\n unfilterNone,\n unfilterPaeth,\n unfilterSub,\n unfilterUp,\n} from './unfilter.ts';\n\nconst uint16 = new Uint16Array([0x00ff]);\nconst uint8 = new Uint8Array(uint16.buffer);\nconst osIsLittleEndian = uint8[0] === 0xff;\n\nconst empty = new Uint8Array(0);\n\nexport interface DecodeInterlaceNullParams {\n data: Uint8Array;\n width: number;\n height: number;\n channels: number;\n depth: number;\n}\n\nexport function decodeInterlaceNull(\n params: DecodeInterlaceNullParams,\n): PngDataArray {\n const { data, width, height, channels, depth } = params;\n\n const bytesPerPixel = Math.ceil(depth / 8) * channels;\n\n const bytesPerLine = Math.ceil((depth / 8) * channels * width);\n const newData = new Uint8Array(height * bytesPerLine);\n\n let prevLine = empty;\n let offset = 0;\n let currentLine;\n let newLine;\n\n for (let i = 0; i < height; i++) {\n currentLine = data.subarray(offset + 1, offset + 1 + bytesPerLine);\n newLine = newData.subarray(i * bytesPerLine, (i + 1) * bytesPerLine);\n switch (data[offset]) {\n case 0:\n unfilterNone(currentLine, newLine, bytesPerLine);\n break;\n case 1:\n unfilterSub(currentLine, newLine, bytesPerLine, bytesPerPixel);\n break;\n case 2:\n unfilterUp(currentLine, newLine, prevLine, bytesPerLine);\n break;\n case 3:\n unfilterAverage(\n currentLine,\n newLine,\n prevLine,\n bytesPerLine,\n bytesPerPixel,\n );\n break;\n case 4:\n unfilterPaeth(\n currentLine,\n newLine,\n prevLine,\n bytesPerLine,\n bytesPerPixel,\n );\n break;\n default:\n throw new Error(`Unsupported filter: ${data[offset]}`);\n }\n prevLine = newLine;\n offset += bytesPerLine + 1;\n }\n\n if (depth === 16) {\n const uint16Data = new Uint16Array(newData.buffer);\n if (osIsLittleEndian) {\n for (let k = 0; k < uint16Data.length; k++) {\n // PNG is always big endian. Swap the bytes.\n uint16Data[k] = swap16(uint16Data[k]);\n }\n }\n return uint16Data;\n } else {\n return newData;\n }\n}\n\nfunction swap16(val: number): number {\n return ((val & 0xff) << 8) | ((val >> 8) & 0xff);\n}\n","import type { IOBuffer } from 'iobuffer';\n\n// https://www.w3.org/TR/PNG/#5PNG-file-signature\n\nconst pngSignature = Uint8Array.of(137, 80, 78, 71, 13, 10, 26, 10);\n\nexport function writeSignature(buffer: IOBuffer) {\n buffer.writeBytes(pngSignature);\n}\n\nexport function checkSignature(buffer: IOBuffer) {\n if (!hasPngSignature(buffer.readBytes(pngSignature.length))) {\n throw new Error('wrong PNG signature');\n }\n}\n\nexport function hasPngSignature(array: ArrayLike<number>) {\n if (array.length < pngSignature.length) {\n return false;\n }\n for (let i = 0; i < pngSignature.length; i++) {\n if (array[i] !== pngSignature[i]) {\n return false;\n }\n }\n return true;\n}\n","import type { IOBuffer } from 'iobuffer';\n\nimport { writeCrc } from './crc.ts';\n\n// https://www.w3.org/TR/png/#11tEXt\n\nexport const textChunkName = 'tEXt';\n\nconst NULL = 0;\n\nconst latin1Decoder = new TextDecoder('latin1');\n\nfunction validateKeyword(keyword: string) {\n validateLatin1(keyword);\n if (keyword.length === 0 || keyword.length > 79) {\n throw new Error('keyword length must be between 1 and 79');\n }\n}\n\n// eslint-disable-next-line no-control-regex\nconst latin1Regex = /^[\\u0000-\\u00FF]*$/;\nfunction validateLatin1(text: string) {\n if (!latin1Regex.test(text)) {\n throw new Error('invalid latin1 text');\n }\n}\n\nexport function decodetEXt(\n text: Record<string, string>,\n buffer: IOBuffer,\n length: number,\n) {\n const keyword = readKeyword(buffer);\n text[keyword] = readLatin1(buffer, length - keyword.length - 1);\n}\n\nexport function encodetEXt(buffer: IOBuffer, keyword: string, text: string) {\n validateKeyword(keyword);\n validateLatin1(text);\n const length = keyword.length + 1 /* NULL */ + text.length;\n\n buffer.writeUint32(length);\n buffer.writeChars(textChunkName);\n buffer.writeChars(keyword);\n buffer.writeByte(NULL);\n buffer.writeChars(text);\n writeCrc(buffer, length + 4);\n}\n\n// https://www.w3.org/TR/png/#11keywords\nexport function readKeyword(buffer: IOBuffer): string {\n buffer.mark();\n while (buffer.readByte() !== NULL) {\n /* advance */\n }\n const end = buffer.offset;\n buffer.reset();\n const keyword = latin1Decoder.decode(\n buffer.readBytes(end - buffer.offset - 1),\n );\n // NULL\n buffer.skip(1);\n\n validateKeyword(keyword);\n\n return keyword;\n}\n\nexport function readLatin1(buffer: IOBuffer, length: number): string {\n return latin1Decoder.decode(buffer.readBytes(length));\n}\n","import { type Matrix, applyToPoint, inverse } from \"transformation-matrix\"\nimport type { InfiniteLine, Point, Viewbox } from \"./types\"\n\nconst EPSILON = 1e-9\n\nconst isWithin = (value: number, min: number, max: number) => {\n return value >= min - EPSILON && value <= max + EPSILON\n}\n\nconst dedupePoints = (points: Point[]) => {\n const unique: Point[] = []\n for (const point of points) {\n if (\n !unique.some(\n (other) =>\n Math.abs(other.x - point.x) < EPSILON &&\n Math.abs(other.y - point.y) < EPSILON,\n )\n ) {\n unique.push(point)\n }\n }\n return unique\n}\n\nexport function clipInfiniteLineToBounds(\n infiniteLine: InfiniteLine,\n bounds: Viewbox,\n): [Point, Point] | null {\n const { origin, directionVector } = infiniteLine\n\n if (\n Math.abs(directionVector.x) < EPSILON &&\n Math.abs(directionVector.y) < EPSILON\n ) {\n return null\n }\n\n const intersections: Point[] = []\n\n if (Math.abs(directionVector.x) >= EPSILON) {\n const tAtMinX = (bounds.minX - origin.x) / directionVector.x\n const yAtMinX = origin.y + tAtMinX * directionVector.y\n if (isWithin(yAtMinX, bounds.minY, bounds.maxY)) {\n intersections.push({ x: bounds.minX, y: yAtMinX })\n }\n\n const tAtMaxX = (bounds.maxX - origin.x) / directionVector.x\n const yAtMaxX = origin.y + tAtMaxX * directionVector.y\n if (isWithin(yAtMaxX, bounds.minY, bounds.maxY)) {\n intersections.push({ x: bounds.maxX, y: yAtMaxX })\n }\n }\n\n if (Math.abs(directionVector.y) >= EPSILON) {\n const tAtMinY = (bounds.minY - origin.y) / directionVector.y\n const xAtMinY = origin.x + tAtMinY * directionVector.x\n if (isWithin(xAtMinY, bounds.minX, bounds.maxX)) {\n intersections.push({ x: xAtMinY, y: bounds.minY })\n }\n\n const tAtMaxY = (bounds.maxY - origin.y) / directionVector.y\n const xAtMaxY = origin.x + tAtMaxY * directionVector.x\n if (isWithin(xAtMaxY, bounds.minX, bounds.maxX)) {\n intersections.push({ x: xAtMaxY, y: bounds.maxY })\n }\n }\n\n const uniqueIntersections = dedupePoints(intersections)\n\n if (uniqueIntersections.length < 2) {\n return null\n }\n\n let first = uniqueIntersections[0]\n let second = uniqueIntersections[1]\n let maxDistanceSquared = (first.x - second.x) ** 2 + (first.y - second.y) ** 2\n\n for (let i = 0; i < uniqueIntersections.length; i++) {\n for (let j = i + 1; j < uniqueIntersections.length; j++) {\n const a = uniqueIntersections[i]\n const b = uniqueIntersections[j]\n const distanceSquared = (a.x - b.x) ** 2 + (a.y - b.y) ** 2\n if (distanceSquared > maxDistanceSquared) {\n first = a\n second = b\n maxDistanceSquared = distanceSquared\n }\n }\n }\n\n return [first, second]\n}\n\nexport function getViewportBoundsFromMatrix(\n matrix: Matrix,\n width: number,\n height: number,\n): Viewbox {\n const screenToReal = inverse(matrix)\n const corners = [\n applyToPoint(screenToReal, { x: 0, y: 0 }),\n applyToPoint(screenToReal, { x: width, y: 0 }),\n applyToPoint(screenToReal, { x: 0, y: height }),\n applyToPoint(screenToReal, { x: width, y: height }),\n ]\n\n return {\n minX: Math.min(...corners.map((p) => p.x)),\n maxX: Math.max(...corners.map((p) => p.x)),\n minY: Math.min(...corners.map((p) => p.y)),\n maxY: Math.max(...corners.map((p) => p.y)),\n }\n}\n","export const FONT_SIZE_WIDTH_RATIO = 0.6\nexport const FONT_SIZE_HEIGHT_RATIO = 1\n","import { applyToPoint, type Matrix } from \"transformation-matrix\"\nimport type { Point, Rect, Viewbox } from \"./types\"\n\ntype XYPoint = { x: number; y: number }\n\nconst getDistanceBetweenPoints = (a: XYPoint, b: XYPoint) => {\n return Math.hypot(a.x - b.x, a.y - b.y)\n}\n\nexport const getRectRotationRadians = (\n rect: Pick<Rect, \"ccwRotationDegrees\">,\n) => {\n return ((rect.ccwRotationDegrees ?? 0) * Math.PI) / 180\n}\n\nconst getScreenRotationMultiplier = (matrix: Matrix) => {\n // Screen coordinates have +Y downward. Orientation-preserving transforms\n // therefore need the math angle inverted to look visually CCW.\n const determinant = matrix.a * matrix.d - matrix.b * matrix.c\n return determinant < 0 ? 1 : -1\n}\n\nexport const getRectRotationRadiansForMatrix = (\n rect: Pick<Rect, \"ccwRotationDegrees\">,\n matrix: Matrix,\n) => {\n return getRectRotationRadians(rect) * getScreenRotationMultiplier(matrix)\n}\nconst rotatePoint = (point: XYPoint, angleRadians: number): XYPoint => {\n const cos = Math.cos(angleRadians)\n const sin = Math.sin(angleRadians)\n\n return {\n x: point.x * cos - point.y * sin,\n y: point.x * sin + point.y * cos,\n }\n}\n\nexport const getRectCorners = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n): Point[] => {\n return getRectCornersWithAngle(rect, getRectRotationRadians(rect))\n}\n\nexport const getRectCornersForMatrix = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n matrix: Matrix,\n): Point[] => {\n return getRectCornersWithAngle(\n rect,\n getRectRotationRadiansForMatrix(rect, matrix),\n )\n}\n\nconst getRectCornersWithAngle = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n angleRadians: number,\n): Point[] => {\n const halfWidth = rect.width / 2\n const halfHeight = rect.height / 2\n\n return [\n { x: -halfWidth, y: -halfHeight },\n { x: halfWidth, y: -halfHeight },\n { x: halfWidth, y: halfHeight },\n { x: -halfWidth, y: halfHeight },\n ].map((corner) => {\n const rotatedCorner = rotatePoint(corner, angleRadians)\n return {\n x: rect.center.x + rotatedCorner.x,\n y: rect.center.y + rotatedCorner.y,\n }\n })\n}\n\nexport const getRectBounds = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n): Viewbox => {\n const corners = getRectCorners(rect)\n\n return corners.reduce(\n (bounds, point) => ({\n minX: Math.min(bounds.minX, point.x),\n maxX: Math.max(bounds.maxX, point.x),\n minY: Math.min(bounds.minY, point.y),\n maxY: Math.max(bounds.maxY, point.y),\n }),\n {\n minX: Infinity,\n maxX: -Infinity,\n minY: Infinity,\n maxY: -Infinity,\n },\n )\n}\n\nexport const getProjectedRectGeometry = (\n rect: Pick<Rect, \"center\" | \"width\" | \"height\" | \"ccwRotationDegrees\">,\n matrix: Matrix,\n) => {\n const corners = getRectCornersForMatrix(rect, matrix).map((point) =>\n applyToPoint(matrix, point),\n )\n const center = applyToPoint(matrix, rect.center)\n const width = getDistanceBetweenPoints(corners[0], corners[1])\n const height = getDistanceBetweenPoints(corners[1], corners[2])\n const angleRadians =\n corners.length >= 2\n ? Math.atan2(corners[1].y - corners[0].y, corners[1].x - corners[0].x)\n : 0\n const angleDegrees = (angleRadians * 180) / Math.PI\n\n const bounds = corners.reduce(\n (result, point) => ({\n minX: Math.min(result.minX, point.x),\n maxX: Math.max(result.maxX, point.x),\n minY: Math.min(result.minY, point.y),\n maxY: Math.max(result.maxY, point.y),\n }),\n {\n minX: Infinity,\n maxX: -Infinity,\n minY: Infinity,\n maxY: -Infinity,\n },\n )\n\n return {\n center,\n corners,\n width,\n height,\n angleRadians,\n angleDegrees,\n bounds,\n }\n}\n","import type { Arrow } from \"./types\"\n\nconst DEFAULT_ARROW_SHAFT_WIDTH = 2\nconst DEFAULT_ARROW_HEAD_WIDTH = 12\nconst DEFAULT_ARROW_HEAD_LENGTH = 12\n\nexport type ArrowHeadGeometry = {\n tip: { x: number; y: number }\n base: { x: number; y: number }\n leftWing: { x: number; y: number }\n rightWing: { x: number; y: number }\n}\n\nexport type ArrowGeometry = {\n shaftStart: { x: number; y: number }\n shaftEnd: { x: number; y: number }\n heads: ArrowHeadGeometry[]\n shaftWidth: number\n headLength: number\n headWidth: number\n length: number\n}\n\nexport type InlineLabelLayout = {\n x: number\n y: number\n angleRadians: number\n angleDegrees: number\n direction: { x: number; y: number }\n normal: { x: number; y: number }\n}\n\nconst createDegenerateHead = (point: {\n x: number\n y: number\n}): ArrowHeadGeometry => ({\n tip: { ...point },\n base: { ...point },\n leftWing: { ...point },\n rightWing: { ...point },\n})\n\nconst createHead = (\n tip: { x: number; y: number },\n base: { x: number; y: number },\n headWidth: number,\n): ArrowHeadGeometry => {\n const dirX = tip.x - base.x\n const dirY = tip.y - base.y\n const length = Math.hypot(dirX, dirY)\n\n if (length === 0) {\n return createDegenerateHead(tip)\n }\n\n const dirUnitX = dirX / length\n const dirUnitY = dirY / length\n const perpX = -dirUnitY * (headWidth / 2)\n const perpY = dirUnitX * (headWidth / 2)\n\n return {\n tip: { ...tip },\n base: { ...base },\n leftWing: { x: base.x + perpX, y: base.y + perpY },\n rightWing: { x: base.x - perpX, y: base.y - perpY },\n }\n}\n\nexport function getArrowGeometry(arrow: Arrow): ArrowGeometry {\n const { start, end } = arrow\n\n const vx = end.x - start.x\n const vy = end.y - start.y\n const length = Math.hypot(vx, vy)\n\n const shaftWidth = DEFAULT_ARROW_SHAFT_WIDTH\n const headWidth = DEFAULT_ARROW_HEAD_WIDTH\n\n if (length === 0) {\n const heads = arrow.doubleSided\n ? [createDegenerateHead(start), createDegenerateHead(start)]\n : [createDegenerateHead(start)]\n return {\n shaftStart: { ...start },\n shaftEnd: { ...start },\n heads,\n shaftWidth,\n headLength: 0,\n headWidth,\n length,\n }\n }\n\n const ux = vx / length\n const uy = vy / length\n\n const baseHeadLength = Math.min(DEFAULT_ARROW_HEAD_LENGTH, length * 0.5)\n const desiredHeadLength = Math.max(baseHeadLength, shaftWidth * 2)\n const maxHeadLength = arrow.doubleSided ? length / 2 : length\n const headLength = Math.min(desiredHeadLength, maxHeadLength)\n\n const endHeadBase = {\n x: end.x - ux * headLength,\n y: end.y - uy * headLength,\n }\n\n const heads: ArrowHeadGeometry[] = [createHead(end, endHeadBase, headWidth)]\n\n let shaftStart = { ...start }\n const shaftEnd = { ...endHeadBase }\n\n if (arrow.doubleSided) {\n const startHeadBase = {\n x: start.x + ux * headLength,\n y: start.y + uy * headLength,\n }\n\n heads.unshift(createHead(start, startHeadBase, headWidth))\n shaftStart = startHeadBase\n }\n\n return {\n shaftStart,\n shaftEnd,\n heads,\n shaftWidth,\n headLength,\n headWidth,\n length,\n }\n}\n\nexport function getArrowBoundingBox(arrow: Arrow) {\n const geometry = getArrowGeometry(arrow)\n const points = [\n geometry.shaftStart,\n geometry.shaftEnd,\n ...geometry.heads.flatMap((head) => [\n head.tip,\n head.base,\n head.leftWing,\n head.rightWing,\n ]),\n ]\n\n return points.reduce(\n (acc, point) => ({\n minX: Math.min(acc.minX, point.x),\n maxX: Math.max(acc.maxX, point.x),\n minY: Math.min(acc.minY, point.y),\n maxY: Math.max(acc.maxY, point.y),\n }),\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n}\n\nexport function getInlineLabelLayout(\n shaftStart: { x: number; y: number },\n shaftEnd: { x: number; y: number },\n {\n fontSize = 12,\n strokeWidth = 2,\n normalPadding = 6,\n alongOffset = 0,\n }: {\n fontSize?: number\n strokeWidth?: number\n normalPadding?: number\n alongOffset?: number\n } = {},\n): InlineLabelLayout {\n const midpoint = {\n x: (shaftStart.x + shaftEnd.x) / 2,\n y: (shaftStart.y + shaftEnd.y) / 2,\n }\n const dx = shaftEnd.x - shaftStart.x\n const dy = shaftEnd.y - shaftStart.y\n const length = Math.hypot(dx, dy)\n\n if (length === 0) {\n return {\n x: midpoint.x + alongOffset,\n y: midpoint.y - (strokeWidth / 2 + fontSize * 0.65 + normalPadding),\n angleRadians: 0,\n angleDegrees: 0,\n direction: { x: 1, y: 0 },\n normal: { x: 0, y: -1 },\n }\n }\n\n let dirX = dx / length\n let dirY = dy / length\n let normalX = -dirY\n let normalY = dirX\n\n const isUpsideDown = dirX < 0 || (dirX === 0 && dirY < 0)\n if (isUpsideDown) {\n dirX = -dirX\n dirY = -dirY\n normalX = -normalX\n normalY = -normalY\n }\n\n const angleRadians = Math.atan2(dirY, dirX)\n const normalOffset = strokeWidth / 2 + fontSize * 0.65 + normalPadding\n\n return {\n x: midpoint.x + normalX * normalOffset + dirX * alongOffset,\n y: midpoint.y + normalY * normalOffset + dirY * alongOffset,\n angleRadians,\n angleDegrees: (angleRadians * 180) / Math.PI,\n direction: { x: dirX, y: dirY },\n normal: { x: normalX, y: normalY },\n }\n}\n","// These are default colors if no color is provided\n// colors are made based on the index of the item in the array\n\nexport const defaultColors = [\n \"rgba(239, 68, 68, 0.8)\", // red-300\n \"rgba(249, 115, 22, 0.8)\", // orange-300\n \"rgba(245, 158, 11, 0.8)\", // amber-300\n \"rgba(234, 179, 8, 0.8)\", // yellow-300\n \"rgba(132, 204, 22, 0.8)\", // lime-300\n \"rgba(34, 197, 94, 0.8)\", // green-300\n \"rgba(16, 185, 129, 0.8)\", // emerald-300\n \"rgba(20, 184, 166, 0.8)\", // teal-300\n \"rgba(6, 182, 212, 0.8)\", // cyan-300\n \"rgba(14, 165, 233, 0.8)\", // sky-300\n \"rgba(59, 130, 246, 0.8)\", // blue-300\n \"rgba(99, 102, 241, 0.8)\", // indigo-300\n \"rgba(139, 92, 246, 0.8)\", // violet-300\n \"rgba(168, 85, 247, 0.8)\", // purple-300\n \"rgba(217, 70, 239, 0.8)\", // fuchsia-300\n \"rgba(236, 72, 153, 0.8)\", // pink-300\n \"rgba(249, 168, 212, 0.8)\", // rose-300\n \"rgba(161, 161, 170, 0.8)\", // zinc-300\n]\n","import { defaultColors } from \"site/components/InteractiveGraphics/defaultColors\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n scale,\n translate,\n} from \"transformation-matrix\"\nimport {\n getArrowBoundingBox,\n getArrowGeometry,\n getInlineLabelLayout,\n} from \"./arrowHelpers\"\nimport { FONT_SIZE_HEIGHT_RATIO, FONT_SIZE_WIDTH_RATIO } from \"./constants\"\nimport {\n clipInfiniteLineToBounds,\n getViewportBoundsFromMatrix,\n} from \"./infiniteLineHelpers\"\nimport { getProjectedRectGeometry, getRectCorners } from \"./rectGeometry\"\nimport type {\n CenterViewbox,\n GraphicsObject,\n TransformOptions,\n Viewbox,\n} from \"./types\"\n\n/**\n * Computes a transformation matrix based on a provided viewbox\n * Handles both min/max style viewboxes and center/width/height style viewboxes\n */\nexport function computeTransformFromViewbox(\n viewbox: Viewbox | CenterViewbox,\n canvasWidth: number,\n canvasHeight: number,\n options: { padding?: number; yFlip?: boolean } = {},\n): Matrix {\n const padding = options.padding ?? 40\n const yFlip = options.yFlip ?? false\n\n // Convert CenterViewbox to Viewbox if needed\n let bounds: Viewbox\n if (\"center\" in viewbox) {\n const halfWidth = viewbox.width / 2\n const halfHeight = viewbox.height / 2\n bounds = {\n minX: viewbox.center.x - halfWidth,\n maxX: viewbox.center.x + halfWidth,\n minY: viewbox.center.y - halfHeight,\n maxY: viewbox.center.y + halfHeight,\n }\n } else {\n bounds = viewbox\n }\n\n const width = bounds.maxX - bounds.minX || 1\n const height = bounds.maxY - bounds.minY || 1\n\n const scale_factor = Math.min(\n (canvasWidth - 2 * padding) / width,\n (canvasHeight - 2 * padding) / height,\n )\n\n return compose(\n translate(canvasWidth / 2, canvasHeight / 2),\n scale(scale_factor, yFlip ? -scale_factor : scale_factor),\n translate(-(bounds.minX + width / 2), -(bounds.minY + height / 2)),\n )\n}\n\n/**\n * Computes bounds for a graphics object\n */\nexport function getBounds(graphics: GraphicsObject): Viewbox {\n const points = [\n ...(graphics.points || []),\n ...(graphics.lines || []).flatMap((line) => line.points),\n ...(graphics.polygons || []).flatMap((polygon) => polygon.points),\n ...(graphics.rects || []).flatMap((rect) => {\n return getRectCorners(rect)\n }),\n ...(graphics.circles || []).flatMap((circle) => [\n { x: circle.center.x - circle.radius, y: circle.center.y }, // left\n { x: circle.center.x + circle.radius, y: circle.center.y }, // right\n { x: circle.center.x, y: circle.center.y - circle.radius }, // top\n { x: circle.center.x, y: circle.center.y + circle.radius }, // bottom\n ]),\n ...(graphics.arrows || []).flatMap((arrow) => {\n const bounds = getArrowBoundingBox(arrow)\n return [\n { x: bounds.minX, y: bounds.minY },\n { x: bounds.maxX, y: bounds.maxY },\n ]\n }),\n ...(graphics.texts || []).flatMap((text) => {\n const fontSize = text.fontSize ?? 12\n const width = text.text.length * fontSize * FONT_SIZE_WIDTH_RATIO\n const height = fontSize * FONT_SIZE_HEIGHT_RATIO\n const anchor = text.anchorSide ?? \"center\"\n const offsetMap: Record<string, { dx: number; dy: number }> = {\n top_left: { dx: 0, dy: 0 },\n top_center: { dx: -width / 2, dy: 0 },\n top_right: { dx: -width, dy: 0 },\n center_left: { dx: 0, dy: -height / 2 },\n center: { dx: -width / 2, dy: -height / 2 },\n center_right: { dx: -width, dy: -height / 2 },\n bottom_left: { dx: 0, dy: -height },\n bottom_center: { dx: -width / 2, dy: -height },\n bottom_right: { dx: -width, dy: -height },\n }\n const { dx, dy } = offsetMap[anchor]\n const x0 = text.x + dx\n const y0 = text.y + dy\n return [\n { x: x0, y: y0 },\n { x: x0 + width, y: y0 + height },\n ]\n }),\n ]\n\n if (points.length === 0) {\n return { minX: -1, maxX: 1, minY: -1, maxY: 1 }\n }\n\n return points.reduce(\n (bounds, point) => ({\n minX: Math.min(bounds.minX, point.x),\n maxX: Math.max(bounds.maxX, point.x),\n minY: Math.min(bounds.minY, point.y),\n maxY: Math.max(bounds.maxY, point.y),\n }),\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n}\n\n/**\n * Draws a graphics object onto a canvas or context\n * @param graphics - The graphics object to draw\n * @param target - The canvas element or 2D context to draw on\n * @param options - Options for controlling the transform and rendering\n */\nexport function drawGraphicsToCanvas(\n graphics: GraphicsObject,\n target: HTMLCanvasElement | CanvasRenderingContext2D,\n options: TransformOptions = {},\n): void {\n const labelsDisabled = options.disableLabels !== false\n const inlineLabelsHidden = options.hideInlineLabels ?? labelsDisabled\n\n // Get the context\n const ctx =\n target instanceof HTMLCanvasElement ? target.getContext(\"2d\") : target\n\n if (!ctx) {\n throw new Error(\"Could not get 2D context from canvas\")\n }\n\n // Get canvas dimensions\n const canvasWidth =\n target instanceof HTMLCanvasElement ? target.width : target.canvas.width\n\n const canvasHeight =\n target instanceof HTMLCanvasElement ? target.height : target.canvas.height\n\n // Get or compute the transform matrix\n let matrix: Matrix\n\n if (options.transform) {\n matrix = options.transform\n } else if (options.viewbox) {\n matrix = computeTransformFromViewbox(\n options.viewbox,\n canvasWidth,\n canvasHeight,\n {\n padding: options.padding,\n yFlip: options.yFlip,\n },\n )\n } else {\n // Auto-compute bounds and transform if not provided\n const bounds = getBounds(graphics)\n const yFlip = graphics.coordinateSystem === \"cartesian\"\n matrix = computeTransformFromViewbox(bounds, canvasWidth, canvasHeight, {\n padding: options.padding ?? 40,\n yFlip,\n })\n }\n\n // Clear the canvas\n ctx.clearRect(0, 0, canvasWidth, canvasHeight)\n\n // Save the current transform state\n ctx.save()\n\n // Draw the graphics elements\n // Draw rectangles\n if (graphics.rects && graphics.rects.length > 0) {\n graphics.rects.forEach((rect) => {\n const projectedRect = getProjectedRectGeometry(rect, matrix)\n\n ctx.save()\n ctx.translate(projectedRect.center.x, projectedRect.center.y)\n if (Math.abs(projectedRect.angleRadians) > 1e-6) {\n ctx.rotate(projectedRect.angleRadians)\n }\n ctx.beginPath()\n ctx.rect(\n -projectedRect.width / 2,\n -projectedRect.height / 2,\n projectedRect.width,\n projectedRect.height,\n )\n\n if (rect.fill) {\n ctx.fillStyle = rect.fill\n ctx.fill()\n }\n\n if (rect.stroke) {\n ctx.strokeStyle = rect.stroke\n ctx.stroke()\n }\n\n ctx.restore()\n })\n }\n\n // Draw circles\n if (graphics.circles && graphics.circles.length > 0) {\n graphics.circles.forEach((circle) => {\n const projected = applyToPoint(matrix, circle.center)\n const scaledRadius = circle.radius * Math.abs(matrix.a) // Use matrix scale factor\n\n ctx.beginPath()\n ctx.arc(projected.x, projected.y, scaledRadius, 0, 2 * Math.PI)\n\n if (circle.fill) {\n ctx.fillStyle = circle.fill\n ctx.fill()\n }\n\n if (circle.stroke) {\n ctx.strokeStyle = circle.stroke ?? \"transparent\"\n ctx.stroke()\n }\n })\n }\n\n // Draw polygons\n if (graphics.polygons && graphics.polygons.length > 0) {\n graphics.polygons.forEach((polygon) => {\n if (polygon.points.length === 0) return\n\n const projectedPoints = polygon.points.map((point) =>\n applyToPoint(matrix, point),\n )\n\n ctx.beginPath()\n ctx.moveTo(projectedPoints[0].x, projectedPoints[0].y)\n for (let i = 1; i < projectedPoints.length; i++) {\n ctx.lineTo(projectedPoints[i].x, projectedPoints[i].y)\n }\n ctx.closePath()\n\n if (polygon.fill) {\n ctx.fillStyle = polygon.fill\n ctx.fill()\n }\n\n if (polygon.stroke) {\n ctx.strokeStyle = polygon.stroke\n if (polygon.strokeWidth !== undefined) {\n ctx.lineWidth = polygon.strokeWidth * Math.abs(matrix.a)\n }\n ctx.stroke()\n }\n })\n }\n\n if (graphics.arrows && graphics.arrows.length > 0) {\n graphics.arrows.forEach((arrow, arrowIndex) => {\n const geometry = getArrowGeometry(arrow)\n const shaftStart = applyToPoint(matrix, geometry.shaftStart)\n const shaftEnd = applyToPoint(matrix, geometry.shaftEnd)\n\n const color =\n arrow.color || defaultColors[arrowIndex % defaultColors.length]\n const scaleFactor = Math.hypot(matrix.a, matrix.b)\n\n ctx.strokeStyle = color\n ctx.fillStyle = color\n ctx.lineWidth = geometry.shaftWidth * (scaleFactor || 1)\n ctx.lineCap = \"round\"\n ctx.setLineDash([])\n\n ctx.beginPath()\n ctx.moveTo(shaftStart.x, shaftStart.y)\n ctx.lineTo(shaftEnd.x, shaftEnd.y)\n ctx.stroke()\n\n geometry.heads.forEach((head) => {\n const tip = applyToPoint(matrix, head.tip)\n const leftWing = applyToPoint(matrix, head.leftWing)\n const rightWing = applyToPoint(matrix, head.rightWing)\n\n ctx.beginPath()\n ctx.moveTo(tip.x, tip.y)\n ctx.lineTo(leftWing.x, leftWing.y)\n ctx.lineTo(rightWing.x, rightWing.y)\n ctx.closePath()\n ctx.fill()\n })\n\n const fontSize = 12\n const screenStrokeWidth = geometry.shaftWidth * (scaleFactor || 1)\n const alongSeparation = fontSize * 0.6\n const inlineLabelLayout = getInlineLabelLayout(shaftStart, shaftEnd, {\n fontSize,\n strokeWidth: screenStrokeWidth,\n normalPadding: 6,\n alongOffset: arrow.label ? alongSeparation : 0,\n })\n const arrowLabelLayout = getInlineLabelLayout(shaftStart, shaftEnd, {\n fontSize,\n strokeWidth: screenStrokeWidth,\n normalPadding: 12,\n alongOffset: arrow.inlineLabel ? -alongSeparation : 0,\n })\n\n ctx.fillStyle = color\n ctx.font = `${fontSize}px sans-serif`\n\n if (!labelsDisabled && arrow.label) {\n const labelX = arrowLabelLayout.x\n const labelY = arrowLabelLayout.y\n\n ctx.save()\n ctx.textAlign = \"center\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(arrow.label, labelX, labelY)\n ctx.restore()\n }\n\n if (!inlineLabelsHidden && arrow.inlineLabel) {\n ctx.save()\n ctx.translate(inlineLabelLayout.x, inlineLabelLayout.y)\n ctx.rotate(inlineLabelLayout.angleRadians)\n ctx.textAlign = \"center\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(arrow.inlineLabel, 0, 0)\n ctx.restore()\n }\n })\n }\n\n // Draw lines\n if (graphics.lines && graphics.lines.length > 0) {\n graphics.lines\n .map((line, originalIndex) => ({ line, originalIndex }))\n .sort(\n (a, b) =>\n (a.line.zIndex ?? 0) - (b.line.zIndex ?? 0) ||\n a.originalIndex - b.originalIndex,\n )\n .forEach(({ line, originalIndex: lineIndex }) => {\n if (line.points.length === 0) return\n\n ctx.beginPath()\n\n const firstPoint = applyToPoint(matrix, line.points[0])\n ctx.moveTo(firstPoint.x, firstPoint.y)\n\n for (let i = 1; i < line.points.length; i++) {\n const projected = applyToPoint(matrix, line.points[i])\n ctx.lineTo(projected.x, projected.y)\n }\n\n ctx.strokeStyle =\n line.strokeColor || defaultColors[lineIndex % defaultColors.length]\n if (line.strokeWidth) {\n ctx.lineWidth = line.strokeWidth * matrix.a\n } else {\n ctx.lineWidth = 2\n }\n ctx.lineCap = \"round\"\n\n if (line.strokeDash) {\n if (typeof line.strokeDash === \"string\") {\n // Convert string to array of numbers, handling single values properly\n let dashArray: number[]\n\n // If the string contains commas, split and convert to numbers\n if (line.strokeDash.includes(\",\")) {\n dashArray = line.strokeDash\n .split(\",\")\n .map((s) => parseFloat(s.trim()))\n .filter((n) => !Number.isNaN(n))\n } else {\n // Handle single value case\n const value = parseFloat(line.strokeDash.trim())\n dashArray = !Number.isNaN(value) ? [value] : []\n }\n\n // Scale dash values based on transform matrix\n ctx.setLineDash(dashArray)\n } else {\n // Handle array format\n ctx.setLineDash(line.strokeDash.map((n) => n * Math.abs(matrix.a)))\n }\n } else {\n ctx.setLineDash([])\n }\n\n ctx.stroke()\n })\n }\n\n if (graphics.infiniteLines && graphics.infiniteLines.length > 0) {\n const viewportBounds = getViewportBoundsFromMatrix(\n matrix,\n canvasWidth,\n canvasHeight,\n )\n\n graphics.infiniteLines.forEach((line, lineIndex) => {\n const segment = clipInfiniteLineToBounds(line, viewportBounds)\n if (!segment) return\n\n const [start, end] = segment\n const projectedStart = applyToPoint(matrix, start)\n const projectedEnd = applyToPoint(matrix, end)\n\n ctx.beginPath()\n ctx.moveTo(projectedStart.x, projectedStart.y)\n ctx.lineTo(projectedEnd.x, projectedEnd.y)\n\n ctx.strokeStyle =\n line.strokeColor || defaultColors[lineIndex % defaultColors.length]\n ctx.lineWidth = line.strokeWidth\n ? line.strokeWidth * Math.abs(matrix.a)\n : 2\n ctx.lineCap = \"round\"\n\n if (line.strokeDash) {\n if (typeof line.strokeDash === \"string\") {\n let dashArray: number[]\n if (line.strokeDash.includes(\",\")) {\n dashArray = line.strokeDash\n .split(\",\")\n .map((s) => parseFloat(s.trim()))\n .filter((n) => !Number.isNaN(n))\n } else {\n const value = parseFloat(line.strokeDash.trim())\n dashArray = !Number.isNaN(value) ? [value] : []\n }\n ctx.setLineDash(dashArray)\n } else {\n ctx.setLineDash(line.strokeDash.map((n) => n * Math.abs(matrix.a)))\n }\n } else {\n ctx.setLineDash([])\n }\n\n ctx.stroke()\n })\n }\n\n // Draw texts\n if (graphics.texts && graphics.texts.length > 0) {\n graphics.texts.forEach((text) => {\n const projected = applyToPoint(matrix, { x: text.x, y: text.y })\n ctx.fillStyle = text.color || \"black\"\n ctx.font = `${(text.fontSize ?? 12) * Math.abs(matrix.a)}px sans-serif`\n\n const anchor = text.anchorSide ?? \"center\"\n const alignMap: Record<string, CanvasTextAlign> = {\n top_left: \"left\",\n center_left: \"left\",\n bottom_left: \"left\",\n top_center: \"center\",\n center: \"center\",\n bottom_center: \"center\",\n top_right: \"right\",\n center_right: \"right\",\n bottom_right: \"right\",\n }\n const baselineMap: Record<string, CanvasTextBaseline> = {\n top_left: \"top\",\n top_center: \"top\",\n top_right: \"top\",\n center_left: \"middle\",\n center: \"middle\",\n center_right: \"middle\",\n bottom_left: \"bottom\",\n bottom_center: \"bottom\",\n bottom_right: \"bottom\",\n }\n ctx.textAlign = alignMap[anchor]\n ctx.textBaseline = baselineMap[anchor]\n\n ctx.fillText(text.text, projected.x, projected.y)\n })\n }\n\n // Draw points\n if (graphics.points && graphics.points.length > 0) {\n graphics.points.forEach((point, pointIndex) => {\n const projected = applyToPoint(matrix, point)\n\n // Draw point as a small circle\n ctx.beginPath()\n ctx.arc(projected.x, projected.y, 3, 0, 2 * Math.PI)\n ctx.fillStyle =\n point.color || defaultColors[pointIndex % defaultColors.length]\n ctx.fill()\n\n // Draw label if present and labels aren't disabled\n if (point.label && !labelsDisabled) {\n ctx.fillStyle = point.color || \"black\"\n ctx.font = \"12px sans-serif\"\n ctx.fillText(point.label, projected.x + 5, projected.y - 5)\n }\n })\n }\n\n // Restore the original transform\n ctx.restore()\n}\n","import { applyToPoint, type Matrix } from \"transformation-matrix\"\nimport { getArrowGeometry, getInlineLabelLayout } from \"./arrowHelpers\"\nimport { computeTransformFromViewbox, getBounds } from \"./drawGraphicsToCanvas\"\nimport {\n clipInfiniteLineToBounds,\n getViewportBoundsFromMatrix,\n} from \"./infiniteLineHelpers\"\nimport {\n createSoftwareRasterSurface,\n type RasterContext,\n} from \"./softwareRasterSurface\"\nimport { getProjectedRectGeometry } from \"./rectGeometry\"\nimport { strokeAlphabetText } from \"./strokeAlphabetText\"\nimport type {\n GraphicsObject,\n NinePointAnchor,\n Point,\n TransformOptions,\n} from \"./types\"\n\nconst DEFAULT_PNG_SIZE = 640\nconst DEFAULT_BACKGROUND_COLOR = \"white\"\n\ntype LabelType =\n | \"points\"\n | \"lines\"\n | \"infiniteLines\"\n | \"rects\"\n | \"polygons\"\n | \"arrows\"\n\nexport type PngRenderOptions = TransformOptions & {\n includeTextLabels?: boolean | LabelType[]\n backgroundColor?: string | null\n pngWidth?: number\n pngHeight?: number\n}\n\nconst hasVisiblePaint = (value?: string) => {\n return Boolean(value && value !== \"none\" && value !== \"transparent\")\n}\n\nconst shouldRenderLabel = (\n includeTextLabels: PngRenderOptions[\"includeTextLabels\"],\n disableLabels: boolean | undefined,\n type: LabelType,\n) => {\n if (disableLabels) return false\n if (typeof includeTextLabels === \"boolean\") return includeTextLabels\n if (Array.isArray(includeTextLabels)) return includeTextLabels.includes(type)\n return false\n}\n\nconst parseStrokeDash = (\n strokeDash: string | number[],\n strokeScale: number,\n): number[] => {\n if (typeof strokeDash === \"string\") {\n if (strokeDash.includes(\",\")) {\n return strokeDash\n .split(\",\")\n .map((part) => Number.parseFloat(part.trim()))\n .filter((value) => Number.isFinite(value) && value > 0)\n }\n\n const singleValue = Number.parseFloat(strokeDash.trim())\n return Number.isFinite(singleValue) && singleValue > 0 ? [singleValue] : []\n }\n\n return strokeDash\n .map((segment) => segment * strokeScale)\n .filter((value) => Number.isFinite(value) && value > 0)\n}\n\nconst normalizeDashPattern = (dashPattern: number[]) => {\n if (dashPattern.length === 0) return dashPattern\n return dashPattern.length % 2 === 0\n ? dashPattern\n : [...dashPattern, ...dashPattern]\n}\n\nconst strokePolyline = (\n ctx: RasterContext,\n points: Point[],\n dashPattern: number[] | undefined,\n) => {\n if (points.length < 2) return\n\n if (!dashPattern || dashPattern.length === 0) {\n ctx.beginPath()\n ctx.moveTo(points[0].x, points[0].y)\n for (let i = 1; i < points.length; i++) {\n ctx.lineTo(points[i].x, points[i].y)\n }\n ctx.stroke()\n return\n }\n\n const normalizedPattern = normalizeDashPattern(dashPattern)\n let patternIndex = 0\n let patternOffset = 0\n let isDrawing = true\n\n ctx.beginPath()\n\n for (let i = 1; i < points.length; i++) {\n const start = points[i - 1]\n const end = points[i]\n const dx = end.x - start.x\n const dy = end.y - start.y\n const segmentLength = Math.hypot(dx, dy)\n\n if (segmentLength === 0) continue\n\n let distanceAlongSegment = 0\n while (distanceAlongSegment < segmentLength) {\n const remainingPatternLength =\n normalizedPattern[patternIndex] - patternOffset\n const stepLength = Math.min(\n remainingPatternLength,\n segmentLength - distanceAlongSegment,\n )\n\n const t1 = distanceAlongSegment / segmentLength\n const t2 = (distanceAlongSegment + stepLength) / segmentLength\n const x1 = start.x + dx * t1\n const y1 = start.y + dy * t1\n const x2 = start.x + dx * t2\n const y2 = start.y + dy * t2\n\n if (isDrawing) {\n ctx.moveTo(x1, y1)\n ctx.lineTo(x2, y2)\n }\n\n distanceAlongSegment += stepLength\n patternOffset += stepLength\n\n if (patternOffset >= normalizedPattern[patternIndex] - 1e-6) {\n patternOffset = 0\n patternIndex = (patternIndex + 1) % normalizedPattern.length\n isDrawing = !isDrawing\n }\n }\n }\n\n ctx.stroke()\n}\n\nconst renderText = (\n ctx: RasterContext,\n {\n text,\n x,\n y,\n fontSize,\n color,\n anchorAlignment = \"top_left\",\n rotationRadians,\n }: {\n text: string\n x: number\n y: number\n fontSize: number\n color?: string\n anchorAlignment?: NinePointAnchor\n rotationRadians?: number\n },\n) => {\n strokeAlphabetText({\n ctx,\n text,\n fontSize,\n startX: x,\n startY: y,\n color: color ?? \"black\",\n anchorAlignment: anchorAlignment ?? \"top_left\",\n rotationRadians,\n })\n}\n\nexport async function getPngBufferFromGraphicsObject(\n graphics: GraphicsObject,\n {\n includeTextLabels = false,\n hideInlineLabels = false,\n backgroundColor = DEFAULT_BACKGROUND_COLOR,\n pngWidth = DEFAULT_PNG_SIZE,\n pngHeight = DEFAULT_PNG_SIZE,\n ...transformOptions\n }: PngRenderOptions = {},\n): Promise<Uint8Array> {\n const surface = createSoftwareRasterSurface(pngWidth, pngHeight)\n const { ctx } = surface\n\n ctx.clearRect(0, 0, pngWidth, pngHeight)\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor\n ctx.fillRect(0, 0, pngWidth, pngHeight)\n }\n\n const yFlip =\n transformOptions.yFlip ?? graphics.coordinateSystem === \"cartesian\"\n const matrix: Matrix =\n transformOptions.transform ??\n computeTransformFromViewbox(\n transformOptions.viewbox ?? getBounds(graphics),\n pngWidth,\n pngHeight,\n {\n padding: transformOptions.padding ?? 40,\n yFlip,\n },\n )\n const strokeScale = Math.abs(matrix.a)\n\n for (const line of (graphics.lines || [])\n .map((value, originalIndex) => ({ value, originalIndex }))\n .sort(\n (a, b) =>\n (a.value.zIndex ?? 0) - (b.value.zIndex ?? 0) ||\n a.originalIndex - b.originalIndex,\n )\n .map(({ value }) => value)) {\n const projectedPoints = line.points.map((point) =>\n applyToPoint(matrix, point),\n )\n const dashPattern = line.strokeDash\n ? parseStrokeDash(line.strokeDash, strokeScale)\n : undefined\n\n ctx.strokeStyle = line.strokeColor || \"black\"\n ctx.lineWidth =\n line.strokeWidth === undefined\n ? 1\n : Math.max(line.strokeWidth * strokeScale, 1)\n strokePolyline(ctx, projectedPoints, dashPattern)\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"lines\",\n ) &&\n line.label &&\n projectedPoints.length > 0\n ) {\n renderText(ctx, {\n text: line.label,\n x: projectedPoints[0].x + 5,\n y: projectedPoints[0].y - 5,\n fontSize: 12,\n color: line.strokeColor || \"black\",\n })\n }\n }\n\n if (graphics.infiniteLines) {\n const viewportBounds = getViewportBoundsFromMatrix(\n matrix,\n pngWidth,\n pngHeight,\n )\n for (const line of graphics.infiniteLines) {\n const segment = clipInfiniteLineToBounds(line, viewportBounds)\n if (!segment) continue\n\n const projectedPoints = segment.map((point) =>\n applyToPoint(matrix, point),\n )\n const dashPattern = line.strokeDash\n ? parseStrokeDash(line.strokeDash, strokeScale)\n : undefined\n\n ctx.strokeStyle = line.strokeColor || \"black\"\n ctx.lineWidth =\n line.strokeWidth === undefined\n ? 1\n : Math.max(line.strokeWidth * strokeScale, 1)\n strokePolyline(ctx, projectedPoints, dashPattern)\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"infiniteLines\",\n ) &&\n line.label\n ) {\n renderText(ctx, {\n text: line.label,\n x: (projectedPoints[0].x + projectedPoints[1].x) / 2 + 5,\n y: (projectedPoints[0].y + projectedPoints[1].y) / 2 - 5,\n fontSize: 12,\n color: line.strokeColor || \"black\",\n })\n }\n }\n }\n\n for (const rect of graphics.rects || []) {\n const projectedRect = getProjectedRectGeometry(rect, matrix)\n const x = projectedRect.center.x - projectedRect.width / 2\n const y = projectedRect.center.y - projectedRect.height / 2\n\n ctx.save()\n ctx.translate(projectedRect.center.x, projectedRect.center.y)\n if (Math.abs(projectedRect.angleRadians) > 1e-6) {\n ctx.rotate(projectedRect.angleRadians)\n }\n\n if (hasVisiblePaint(rect.fill)) {\n ctx.beginPath()\n ctx.rect(\n -projectedRect.width / 2,\n -projectedRect.height / 2,\n projectedRect.width,\n projectedRect.height,\n )\n ctx.fillStyle = rect.fill!\n ctx.fill()\n }\n\n if (hasVisiblePaint(rect.stroke)) {\n ctx.beginPath()\n ctx.rect(\n -projectedRect.width / 2,\n -projectedRect.height / 2,\n projectedRect.width,\n projectedRect.height,\n )\n ctx.strokeStyle = rect.stroke!\n ctx.lineWidth = 1\n ctx.stroke()\n }\n\n ctx.restore()\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"rects\",\n ) &&\n rect.label\n ) {\n renderText(ctx, {\n text: rect.label,\n x: projectedRect.bounds.minX + 5,\n y: projectedRect.bounds.minY,\n fontSize: ((projectedRect.width + projectedRect.height) / 2) * 0.06,\n color: rect.stroke || \"black\",\n })\n }\n }\n\n for (const polygon of graphics.polygons || []) {\n if (polygon.points.length === 0) continue\n\n const projectedPoints = polygon.points.map((point) =>\n applyToPoint(matrix, point),\n )\n const minX = Math.min(...projectedPoints.map((point) => point.x))\n const minY = Math.min(...projectedPoints.map((point) => point.y))\n\n ctx.beginPath()\n ctx.moveTo(projectedPoints[0].x, projectedPoints[0].y)\n for (let i = 1; i < projectedPoints.length; i++) {\n ctx.lineTo(projectedPoints[i].x, projectedPoints[i].y)\n }\n ctx.closePath()\n\n if (hasVisiblePaint(polygon.fill)) {\n ctx.fillStyle = polygon.fill!\n ctx.fill()\n }\n\n if (hasVisiblePaint(polygon.stroke)) {\n ctx.strokeStyle = polygon.stroke!\n ctx.lineWidth =\n polygon.strokeWidth === undefined\n ? 1\n : Math.max(polygon.strokeWidth * strokeScale, 1)\n ctx.stroke()\n }\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"polygons\",\n ) &&\n polygon.label\n ) {\n renderText(ctx, {\n text: polygon.label,\n x: minX + 5,\n y: minY,\n fontSize: 12,\n color: polygon.stroke || \"black\",\n })\n }\n }\n\n for (const circle of graphics.circles || []) {\n const projectedCenter = applyToPoint(matrix, circle.center)\n const scaledRadius = circle.radius * strokeScale\n\n ctx.beginPath()\n ctx.arc(projectedCenter.x, projectedCenter.y, scaledRadius, 0, Math.PI * 2)\n\n if (hasVisiblePaint(circle.fill)) {\n ctx.fillStyle = circle.fill!\n ctx.fill()\n }\n\n if (hasVisiblePaint(circle.stroke)) {\n ctx.strokeStyle = circle.stroke!\n ctx.lineWidth = 1\n ctx.stroke()\n }\n }\n\n for (const arrow of graphics.arrows || []) {\n const geometry = getArrowGeometry(arrow)\n const shaftStart = applyToPoint(matrix, geometry.shaftStart)\n const shaftEnd = applyToPoint(matrix, geometry.shaftEnd)\n const fontSize = 12\n const inlineLabelLayout = getInlineLabelLayout(shaftStart, shaftEnd, {\n fontSize,\n strokeWidth: geometry.shaftWidth,\n normalPadding: 6,\n alongOffset: arrow.label ? fontSize * 0.6 : 0,\n })\n const arrowLabelLayout = getInlineLabelLayout(shaftStart, shaftEnd, {\n fontSize,\n strokeWidth: geometry.shaftWidth,\n normalPadding: 12,\n alongOffset: arrow.inlineLabel ? -(fontSize * 0.6) : 0,\n })\n const color = arrow.color || \"black\"\n\n if (shaftStart.x !== shaftEnd.x || shaftStart.y !== shaftEnd.y) {\n ctx.strokeStyle = color\n ctx.lineWidth = geometry.shaftWidth\n strokePolyline(ctx, [shaftStart, shaftEnd], undefined)\n }\n\n ctx.fillStyle = color\n for (const head of geometry.heads) {\n const tip = applyToPoint(matrix, head.tip)\n const leftWing = applyToPoint(matrix, head.leftWing)\n const rightWing = applyToPoint(matrix, head.rightWing)\n\n ctx.beginPath()\n ctx.moveTo(tip.x, tip.y)\n ctx.lineTo(leftWing.x, leftWing.y)\n ctx.lineTo(rightWing.x, rightWing.y)\n ctx.closePath()\n ctx.fill()\n }\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"arrows\",\n ) &&\n arrow.label\n ) {\n renderText(ctx, {\n text: arrow.label,\n x: arrowLabelLayout.x,\n y: arrowLabelLayout.y,\n fontSize,\n color,\n anchorAlignment: \"center\",\n })\n }\n\n if (\n !transformOptions.disableLabels &&\n !hideInlineLabels &&\n arrow.inlineLabel\n ) {\n renderText(ctx, {\n text: arrow.inlineLabel,\n x: inlineLabelLayout.x,\n y: inlineLabelLayout.y,\n fontSize,\n color,\n anchorAlignment: \"center\",\n rotationRadians: inlineLabelLayout.angleRadians,\n })\n }\n }\n\n for (const text of graphics.texts || []) {\n const projected = applyToPoint(matrix, { x: text.x, y: text.y })\n renderText(ctx, {\n text: text.text,\n x: projected.x,\n y: projected.y,\n fontSize: (text.fontSize ?? 12) * strokeScale,\n color: text.color || \"black\",\n anchorAlignment: text.anchorSide ?? \"center\",\n })\n }\n\n for (const point of graphics.points || []) {\n const projected = applyToPoint(matrix, point)\n\n ctx.beginPath()\n ctx.arc(projected.x, projected.y, 3, 0, Math.PI * 2)\n ctx.fillStyle = point.color || \"black\"\n ctx.fill()\n\n if (\n shouldRenderLabel(\n includeTextLabels,\n transformOptions.disableLabels,\n \"points\",\n ) &&\n point.label\n ) {\n renderText(ctx, {\n text: point.label,\n x: projected.x + 5,\n y: projected.y - 5,\n fontSize: 12,\n color: point.color || \"black\",\n })\n }\n }\n\n return surface.exportPng()\n}\n","import { stringify } from \"svgson\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n identity,\n scale,\n transform,\n translate,\n} from \"transformation-matrix\"\nimport {\n getArrowBoundingBox,\n getArrowGeometry,\n getInlineLabelLayout,\n} from \"./arrowHelpers\"\nimport { FONT_SIZE_HEIGHT_RATIO, FONT_SIZE_WIDTH_RATIO } from \"./constants\"\nimport { clipInfiniteLineToBounds } from \"./infiniteLineHelpers\"\nimport { getProjectedRectGeometry, getRectCorners } from \"./rectGeometry\"\nimport type { GraphicsObject, Point } from \"./types\"\n\nconst DEFAULT_SVG_SIZE = 640\nconst PADDING = 40\n\ninterface Bounds {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\nfunction getBounds(graphics: GraphicsObject): Bounds {\n const points: Point[] = [\n ...(graphics.points || []),\n ...(graphics.lines || []).flatMap((line) => line.points),\n ...(graphics.polygons || []).flatMap((polygon) => polygon.points),\n ...(graphics.rects || []).flatMap((rect) => {\n return getRectCorners(rect)\n }),\n ...(graphics.circles || []).flatMap((circle) => [\n { x: circle.center.x - circle.radius, y: circle.center.y }, // left\n { x: circle.center.x + circle.radius, y: circle.center.y }, // right\n { x: circle.center.x, y: circle.center.y - circle.radius }, // top\n { x: circle.center.x, y: circle.center.y + circle.radius }, // bottom\n ]),\n ...(graphics.arrows || []).flatMap((arrow) => {\n const bounds = getArrowBoundingBox(arrow)\n return [\n { x: bounds.minX, y: bounds.minY },\n { x: bounds.maxX, y: bounds.maxY },\n ]\n }),\n ...(graphics.texts || []).flatMap((t) => {\n const fontSize = t.fontSize ?? 12\n const width = t.text.length * fontSize * FONT_SIZE_WIDTH_RATIO\n const height = fontSize * FONT_SIZE_HEIGHT_RATIO\n const anchor = t.anchorSide ?? \"center\"\n const offsetMap: Record<string, { dx: number; dy: number }> = {\n top_left: { dx: 0, dy: 0 },\n top_center: { dx: -width / 2, dy: 0 },\n top_right: { dx: -width, dy: 0 },\n center_left: { dx: 0, dy: -height / 2 },\n center: { dx: -width / 2, dy: -height / 2 },\n center_right: { dx: -width, dy: -height / 2 },\n bottom_left: { dx: 0, dy: -height },\n bottom_center: { dx: -width / 2, dy: -height },\n bottom_right: { dx: -width, dy: -height },\n }\n const { dx, dy } = offsetMap[anchor]\n const x0 = t.x + dx\n const y0 = t.y + dy\n return [\n { x: x0, y: y0 },\n { x: x0 + width, y: y0 + height },\n ]\n }),\n ]\n\n if (points.length === 0) {\n return { minX: -1, maxX: 1, minY: -1, maxY: 1 }\n }\n\n return points.reduce(\n (bounds, point) => ({\n minX: Math.min(bounds.minX, point.x),\n maxX: Math.max(bounds.maxX, point.x),\n minY: Math.min(bounds.minY, point.y),\n maxY: Math.max(bounds.maxY, point.y),\n }),\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n}\n\nfunction getProjectionMatrix(\n bounds: Bounds,\n coordinateSystem: GraphicsObject[\"coordinateSystem\"],\n svgWidth: number,\n svgHeight: number,\n) {\n const width = bounds.maxX - bounds.minX || 1\n const height = bounds.maxY - bounds.minY || 1\n\n const scale_factor = Math.min(\n (svgWidth - 2 * PADDING) / width,\n (svgHeight - 2 * PADDING) / height,\n )\n\n const yFlip = coordinateSystem === \"screen\" ? 1 : -1\n\n return compose(\n translate(svgWidth / 2, svgHeight / 2),\n scale(scale_factor, yFlip * scale_factor),\n translate(-(bounds.minX + width / 2), -(bounds.minY + height / 2)),\n )\n}\n\nfunction projectPoint(point: Point, matrix: Matrix) {\n const projected = applyToPoint(matrix, { x: point.x, y: point.y })\n return { ...point, ...projected }\n}\n\nexport function getSvgFromGraphicsObject(\n graphics: GraphicsObject,\n {\n includeTextLabels = false,\n hideInlineLabels = false,\n backgroundColor = \"white\",\n svgWidth = DEFAULT_SVG_SIZE,\n svgHeight = DEFAULT_SVG_SIZE,\n }: {\n includeTextLabels?:\n | boolean\n | Array<\n \"points\" | \"lines\" | \"infiniteLines\" | \"rects\" | \"polygons\" | \"arrows\"\n >\n backgroundColor?: string | null\n hideInlineLabels?: boolean\n svgWidth?: number\n svgHeight?: number\n } = {},\n): string {\n const bounds = getBounds(graphics)\n const matrix = getProjectionMatrix(\n bounds,\n graphics.coordinateSystem,\n svgWidth,\n svgHeight,\n )\n const strokeScale = Math.abs(matrix.a)\n\n const shouldRenderLabel = (\n type:\n | \"points\"\n | \"lines\"\n | \"infiniteLines\"\n | \"rects\"\n | \"polygons\"\n | \"arrows\",\n ): boolean => {\n if (typeof includeTextLabels === \"boolean\") {\n return includeTextLabels\n }\n if (Array.isArray(includeTextLabels)) {\n return includeTextLabels.includes(type)\n }\n return false\n }\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n viewBox: `0 0 ${svgWidth} ${svgHeight}`,\n xmlns: \"http://www.w3.org/2000/svg\",\n },\n children: [\n // Background rectangle (optional)\n ...(backgroundColor\n ? [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n width: \"100%\",\n height: \"100%\",\n fill: backgroundColor,\n },\n },\n ]\n : []),\n // Lines\n ...(graphics.lines || [])\n .map((line, originalIndex) => ({ line, originalIndex }))\n .sort(\n (a, b) =>\n (a.line.zIndex ?? 0) - (b.line.zIndex ?? 0) ||\n a.originalIndex - b.originalIndex,\n )\n .map(({ line }) => {\n const projectedPoints = line.points.map((p) =>\n projectPoint(p, matrix),\n )\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"polyline\",\n type: \"element\",\n attributes: {\n \"data-points\": line.points\n .map((p) => `${p.x},${p.y}`)\n .join(\" \"),\n \"data-type\": \"line\",\n \"data-label\": line.label || \"\",\n points: projectedPoints.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: line.strokeColor || \"black\",\n \"stroke-width\": !line.strokeWidth\n ? \"1px\"\n : typeof line.strokeWidth === \"string\"\n ? line.strokeWidth\n : (strokeScale * line.strokeWidth).toString(),\n ...(line.strokeDash && {\n \"stroke-dasharray\": Array.isArray(line.strokeDash)\n ? line.strokeDash.join(\" \")\n : line.strokeDash,\n }),\n },\n },\n ...(shouldRenderLabel(\"lines\") &&\n line.label &&\n projectedPoints.length > 0\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (projectedPoints[0].x + 5).toString(),\n y: (projectedPoints[0].y - 5).toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n fill: line.strokeColor || \"black\",\n },\n children: [{ type: \"text\", value: line.label }],\n },\n ]\n : []),\n ],\n }\n }),\n ...(graphics.infiniteLines || []).flatMap((line) => {\n const segment = clipInfiniteLineToBounds(line, bounds)\n if (!segment) return []\n\n const [start, end] = segment\n const projectedStart = projectPoint(start, matrix)\n const projectedEnd = projectPoint(end, matrix)\n\n return [\n {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n \"data-type\": \"infinite-line\",\n \"data-label\": line.label || \"\",\n \"data-origin\": `${line.origin.x},${line.origin.y}`,\n \"data-direction\": `${line.directionVector.x},${line.directionVector.y}`,\n x1: projectedStart.x.toString(),\n y1: projectedStart.y.toString(),\n x2: projectedEnd.x.toString(),\n y2: projectedEnd.y.toString(),\n stroke: line.strokeColor || \"black\",\n \"stroke-width\": !line.strokeWidth\n ? \"1px\"\n : typeof line.strokeWidth === \"string\"\n ? line.strokeWidth\n : (strokeScale * line.strokeWidth).toString(),\n ...(line.strokeDash && {\n \"stroke-dasharray\": Array.isArray(line.strokeDash)\n ? line.strokeDash.join(\" \")\n : line.strokeDash,\n }),\n },\n },\n ...(shouldRenderLabel(\"infiniteLines\") && line.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (\n (projectedStart.x + projectedEnd.x) / 2 +\n 5\n ).toString(),\n y: (\n (projectedStart.y + projectedEnd.y) / 2 -\n 5\n ).toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n fill: line.strokeColor || \"black\",\n },\n children: [{ type: \"text\", value: line.label }],\n },\n ]\n : []),\n ],\n },\n ]\n }),\n // Rectangles\n ...(graphics.rects || []).map((rect) => {\n const projectedRect = getProjectedRectGeometry(rect, matrix)\n const rectX = projectedRect.center.x - projectedRect.width / 2\n const rectY = projectedRect.center.y - projectedRect.height / 2\n const labelX = projectedRect.bounds.minX + 5\n const labelY = projectedRect.bounds.minY\n const hasRotation = Math.abs(projectedRect.angleDegrees) > 1e-6\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n \"data-type\": \"rect\",\n \"data-label\": rect.label || \"\",\n \"data-x\": rect.center.x.toString(),\n \"data-y\": rect.center.y.toString(),\n ...(rect.ccwRotationDegrees !== undefined && {\n \"data-ccw-rotation-degrees\":\n rect.ccwRotationDegrees.toString(),\n }),\n x: rectX.toString(),\n y: rectY.toString(),\n width: projectedRect.width.toString(),\n height: projectedRect.height.toString(),\n fill: rect.fill || \"none\",\n stroke: rect.stroke || \"black\",\n \"stroke-width\": Math.abs(1 / matrix.a).toString(), // Consider scaling stroke width like lines if needed\n ...(hasRotation && {\n transform: `rotate(${projectedRect.angleDegrees} ${projectedRect.center.x} ${projectedRect.center.y})`,\n }),\n },\n },\n ...(shouldRenderLabel(\"rects\") && rect.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: labelX.toString(),\n y: labelY.toString(),\n \"font-family\": \"sans-serif\",\n \"dominant-baseline\": \"text-before-edge\",\n \"font-size\": (\n ((projectedRect.width + projectedRect.height) / 2) *\n 0.06\n ).toString(),\n fill: rect.stroke || \"black\", // Default to stroke color for label\n },\n children: [{ type: \"text\", value: rect.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Polygons\n ...(graphics.polygons || []).map((polygon) => {\n const projectedPoints = polygon.points.map((point) =>\n projectPoint(point, matrix),\n )\n const xs = projectedPoints.map((p) => p.x)\n const ys = projectedPoints.map((p) => p.y)\n const minX = xs.length > 0 ? Math.min(...xs) : 0\n const minY = ys.length > 0 ? Math.min(...ys) : 0\n const polygonStrokeWidth =\n polygon.strokeWidth === undefined\n ? Math.abs(1 / matrix.a)\n : strokeScale * polygon.strokeWidth\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"polygon\",\n type: \"element\",\n attributes: {\n \"data-type\": \"polygon\",\n \"data-label\": polygon.label || \"\",\n \"data-points\": polygon.points\n .map((p) => `${p.x},${p.y}`)\n .join(\" \"),\n points: projectedPoints.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: polygon.fill || \"none\",\n stroke: polygon.stroke || \"black\",\n \"stroke-width\": polygonStrokeWidth.toString(),\n },\n },\n ...(shouldRenderLabel(\"polygons\") && polygon.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (minX + 5).toString(),\n y: minY.toString(),\n \"font-family\": \"sans-serif\",\n \"dominant-baseline\": \"text-before-edge\",\n \"font-size\": \"12\",\n fill: polygon.stroke || \"black\",\n },\n children: [{ type: \"text\", value: polygon.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Circles\n ...(graphics.circles || []).map((circle) => {\n const projected = projectPoint(circle.center, matrix)\n const scaledRadius = circle.radius * Math.abs(matrix.a)\n return {\n name: \"circle\",\n type: \"element\",\n attributes: {\n \"data-type\": \"circle\",\n \"data-label\": \"\",\n \"data-x\": circle.center.x.toString(),\n \"data-y\": circle.center.y.toString(),\n cx: projected.x.toString(),\n cy: projected.y.toString(),\n r: scaledRadius.toString(),\n fill: circle.fill || \"none\",\n stroke: circle.stroke || \"black\",\n \"stroke-width\": Math.abs(1 / matrix.a).toString(),\n },\n }\n }),\n ...(graphics.arrows || []).map((arrow) => {\n const geometry = getArrowGeometry(arrow)\n const projectedShaftStart = projectPoint(geometry.shaftStart, matrix)\n const projectedShaftEnd = projectPoint(geometry.shaftEnd, matrix)\n const fontSize = 12\n const strokeWidth = geometry.shaftWidth\n const alongSeparation = fontSize * 0.6\n const inlineLabelLayout = getInlineLabelLayout(\n projectedShaftStart,\n projectedShaftEnd,\n {\n fontSize,\n strokeWidth,\n normalPadding: 6,\n alongOffset: arrow.label ? alongSeparation : 0,\n },\n )\n const arrowLabelLayout = getInlineLabelLayout(\n projectedShaftStart,\n projectedShaftEnd,\n {\n fontSize,\n strokeWidth,\n normalPadding: 12,\n alongOffset: arrow.inlineLabel ? -alongSeparation : 0,\n },\n )\n\n const color = arrow.color || \"black\"\n\n const headChildren = geometry.heads.map((head) => {\n const projectedTip = projectPoint(head.tip, matrix)\n const projectedLeftWing = projectPoint(head.leftWing, matrix)\n const projectedRightWing = projectPoint(head.rightWing, matrix)\n\n return {\n name: \"polygon\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow-head\",\n points: [\n `${projectedTip.x},${projectedTip.y}`,\n `${projectedLeftWing.x},${projectedLeftWing.y}`,\n `${projectedRightWing.x},${projectedRightWing.y}`,\n ].join(\" \"),\n fill: color,\n },\n }\n })\n\n const children = [\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow-shaft\",\n x1: projectedShaftStart.x.toString(),\n y1: projectedShaftStart.y.toString(),\n x2: projectedShaftEnd.x.toString(),\n y2: projectedShaftEnd.y.toString(),\n stroke: color,\n \"stroke-width\": geometry.shaftWidth.toString(),\n \"stroke-linecap\": \"round\",\n },\n },\n ...headChildren,\n ...(shouldRenderLabel(\"arrows\") && arrow.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow-label\",\n x: arrowLabelLayout.x.toString(),\n y: arrowLabelLayout.y.toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": fontSize.toString(),\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n fill: color,\n },\n children: [{ type: \"text\", value: arrow.label }],\n },\n ]\n : []),\n ...(!hideInlineLabels && arrow.inlineLabel\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow-inline-label\",\n x: inlineLabelLayout.x.toString(),\n y: inlineLabelLayout.y.toString(),\n transform: `rotate(${inlineLabelLayout.angleDegrees} ${inlineLabelLayout.x} ${inlineLabelLayout.y})`,\n \"font-family\": \"sans-serif\",\n \"font-size\": fontSize.toString(),\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n fill: color,\n },\n children: [{ type: \"text\", value: arrow.inlineLabel }],\n },\n ]\n : []),\n ]\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: {\n \"data-type\": \"arrow\",\n \"data-start\": `${arrow.start.x},${arrow.start.y}`,\n \"data-end\": `${arrow.end.x},${arrow.end.y}`,\n \"data-double-sided\": arrow.doubleSided ? \"true\" : \"false\",\n ...(arrow.label ? { \"data-label\": arrow.label } : {}),\n ...(arrow.inlineLabel\n ? { \"data-inline-label\": arrow.inlineLabel }\n : {}),\n },\n children,\n }\n }),\n // Texts\n ...(graphics.texts || []).map((txt) => {\n const projected = projectPoint({ x: txt.x, y: txt.y }, matrix)\n const anchor = txt.anchorSide ?? \"center\"\n const alignMap: Record<string, string> = {\n top_left: \"start\",\n center_left: \"start\",\n bottom_left: \"start\",\n top_center: \"middle\",\n center: \"middle\",\n bottom_center: \"middle\",\n top_right: \"end\",\n center_right: \"end\",\n bottom_right: \"end\",\n }\n const baselineMap: Record<string, string> = {\n top_left: \"text-before-edge\",\n top_center: \"text-before-edge\",\n top_right: \"text-before-edge\",\n center_left: \"central\",\n center: \"central\",\n center_right: \"central\",\n bottom_left: \"text-after-edge\",\n bottom_center: \"text-after-edge\",\n bottom_right: \"text-after-edge\",\n }\n return {\n name: \"text\",\n type: \"element\",\n attributes: {\n \"data-type\": \"text\",\n \"data-label\": txt.text,\n \"data-x\": txt.x.toString(),\n \"data-y\": txt.y.toString(),\n x: projected.x.toString(),\n y: projected.y.toString(),\n fill: txt.color || \"black\",\n \"font-size\": ((txt.fontSize ?? 12) * Math.abs(matrix.a)).toString(),\n \"font-family\": \"sans-serif\",\n \"text-anchor\": alignMap[anchor],\n \"dominant-baseline\": baselineMap[anchor],\n },\n children: [{ type: \"text\", value: txt.text }],\n }\n }),\n // Points\n ...(graphics.points || []).map((point) => {\n const projected = projectPoint(point, matrix)\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n \"data-type\": \"point\",\n \"data-label\": point.label || \"\",\n \"data-x\": point.x.toString(),\n \"data-y\": point.y.toString(),\n cx: projected.x.toString(),\n cy: projected.y.toString(),\n r: \"3\",\n fill: point.color || \"black\",\n },\n },\n ...(shouldRenderLabel(\"points\") && point.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (projected.x + 5).toString(),\n y: (projected.y - 5).toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n },\n children: [{ type: \"text\", value: point.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Crosshair lines and coordinates (initially hidden)\n {\n name: \"g\",\n type: \"element\",\n attributes: {\n id: \"crosshair\",\n style: \"display: none\",\n },\n children: [\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n id: \"crosshair-h\",\n y1: \"0\",\n y2: svgHeight.toString(),\n stroke: \"#666\",\n \"stroke-width\": \"0.5\",\n },\n },\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n id: \"crosshair-v\",\n x1: \"0\",\n x2: svgWidth.toString(),\n stroke: \"#666\",\n \"stroke-width\": \"0.5\",\n },\n },\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n id: \"coordinates\",\n \"font-family\": \"monospace\",\n \"font-size\": \"12\",\n fill: \"#666\",\n },\n children: [{ type: \"text\", value: \"\" }],\n },\n ],\n },\n // Mouse tracking script\n {\n name: \"script\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n document.currentScript.parentElement.addEventListener('mousemove', (e) => {\n const svg = e.currentTarget;\n const rect = svg.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n const crosshair = svg.getElementById('crosshair');\n const h = svg.getElementById('crosshair-h');\n const v = svg.getElementById('crosshair-v');\n const coords = svg.getElementById('coordinates');\n \n crosshair.style.display = 'block';\n h.setAttribute('x1', '0');\n h.setAttribute('x2', '${svgWidth}');\n h.setAttribute('y1', y);\n h.setAttribute('y2', y);\n v.setAttribute('x1', x);\n v.setAttribute('x2', x);\n v.setAttribute('y1', '0');\n v.setAttribute('y2', '${svgHeight}');\n\n // Calculate real coordinates using inverse transformation\n const matrix = ${JSON.stringify(matrix)};\n // Manually invert and apply the affine transform\n // Since we only use translate and scale, we can directly compute:\n // x' = (x - tx) / sx\n // y' = (y - ty) / sy\n const sx = matrix.a;\n const sy = matrix.d;\n const tx = matrix.e; \n const ty = matrix.f;\n const realPoint = {\n x: (x - tx) / sx,\n y: (y - ty) / sy // Flip y back since we used negative scale\n }\n \n coords.textContent = \\`(\\${realPoint.x.toFixed(2)}, \\${realPoint.y.toFixed(2)})\\`;\n coords.setAttribute('x', (x + 5).toString());\n coords.setAttribute('y', (y - 5).toString());\n });\n document.currentScript.parentElement.addEventListener('mouseleave', () => {\n document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';\n });\n `,\n },\n ],\n },\n ],\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: TODO\n return stringify(svgObject as any)\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { drawGraphicsToCanvas } from \"graphics-debug\"\nimport { useEffect, useRef } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport { useGlobalStore } from \"../global-store\"\n\ninterface Props {\n transform?: Matrix\n debugGraphics?: GraphicsObject | null\n children?: any\n}\n\nexport const DebugGraphicsOverlay = ({\n children,\n transform,\n debugGraphics,\n}: Props) => {\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const [containerRef, { width, height }] = useMeasure<HTMLDivElement>()\n const is_showing_autorouting = useGlobalStore((s) => s.is_showing_autorouting)\n\n useEffect(() => {\n if (!is_showing_autorouting) return\n if (canvasRef.current && debugGraphics && width && height) {\n canvasRef.current.width = width\n canvasRef.current.height = height\n drawGraphicsToCanvas(debugGraphics, canvasRef.current, {\n transform,\n disableLabels: true,\n })\n }\n }, [debugGraphics, transform, width, height, is_showing_autorouting])\n\n if (!is_showing_autorouting) return children\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n >\n {children}\n <canvas\n ref={canvasRef}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n opacity: 0.5,\n zIndex: 100,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n }}\n />\n </div>\n )\n}\n","import { zIndexMap } from \"lib/util/z-index-map\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { applyToPoint, identity, inverse } from \"transformation-matrix\"\nimport type { Primitive } from \"lib/types\"\nimport type { NinePointAnchor } from \"circuit-json\"\nimport {\n getPrimitiveBoundingBox,\n mergeBoundingBoxes,\n} from \"lib/util/get-primitive-bounding-box\"\nimport type { BoundingBox } from \"lib/util/get-primitive-bounding-box\"\nimport { useDiagonalLabel } from \"hooks/useDiagonalLabel\"\nimport { getPrimitiveSnapPoints } from \"lib/util/get-primitive-snap-points\"\nimport { useGlobalStore } from \"../global-store\"\n\ninterface Props {\n transform?: Matrix\n children: any\n focusOnHover?: boolean\n primitives?: Primitive[]\n onBoundsSelected?: (bounds: BoundsSelection) => void\n cancelPanDrag?: () => void\n}\n\nconst SNAP_THRESHOLD_PX = 16\nconst SNAP_MARKER_SIZE = 5\n\nexport interface BoundsSelection {\n minX: number\n minY: number\n maxX: number\n maxY: number\n}\n\nconst shouldExcludePrimitiveFromSnapping = (primitive: Primitive) => {\n if (primitive.pcb_drawing_type === \"text\") return true\n\n const element = primitive._element as { type?: unknown } | undefined\n if (!element || typeof element !== \"object\") {\n return false\n }\n\n const elementType =\n typeof element.type === \"string\" ? (element.type as string) : undefined\n\n if (!elementType) return false\n\n if (elementType.startsWith(\"pcb_silkscreen_\")) return true\n if (elementType.startsWith(\"pcb_note_\")) return true\n if (elementType === \"pcb_text\") return true\n if (\n elementType.startsWith(\"pcb_fabrication_note_\") &&\n elementType !== \"pcb_fabrication_note_rect\"\n ) {\n return true\n }\n\n return false\n}\n\nexport const DimensionOverlay = ({\n children,\n transform,\n focusOnHover = false,\n primitives = [],\n onBoundsSelected,\n cancelPanDrag,\n}: Props) => {\n if (!transform) transform = identity()\n const [dimensionToolVisible, setDimensionToolVisible] = useState(false)\n const [dimensionToolStretching, setDimensionToolStretching] = useState(false)\n const [measureToolArmed, setMeasureToolArmed] = useState(false)\n const [boundsToolArmed, setBoundsToolArmed] = useState(false)\n const [boundsToolVisible, setBoundsToolVisible] = useState(false)\n const [boundsToolDragging, setBoundsToolDragging] = useState(false)\n const [activeSnapIds, setActiveSnapIds] = useState({\n start: null as string | null,\n end: null as string | null,\n })\n\n const isMouseOverContainer = useGlobalStore((s) => s.is_mouse_over_container)\n\n const disarmMeasure = useCallback(() => {\n if (measureToolArmed) {\n setMeasureToolArmed(false)\n window.dispatchEvent(new Event(\"disarm-dimension-tool\"))\n }\n }, [measureToolArmed])\n const disarmBounds = useCallback(() => {\n if (boundsToolArmed) {\n setBoundsToolArmed(false)\n window.dispatchEvent(new Event(\"disarm-bounds-tool\"))\n }\n }, [boundsToolArmed])\n // Start of dimension tool line in real-world coordinates (not screen)\n const [dStart, setDStart] = useState({ x: 0, y: 0 })\n // End of dimension tool line in real-world coordinates (not screen)\n const [dEnd, setDEnd] = useState({ x: 0, y: 0 })\n const [boundsStart, setBoundsStart] = useState({ x: 0, y: 0 })\n const [boundsEnd, setBoundsEnd] = useState({ x: 0, y: 0 })\n const mousePosRef = useRef({ x: 0, y: 0 })\n const containerRef = useRef<HTMLDivElement | null>(null)\n const container = containerRef.current!\n const containerBounds = container?.getBoundingClientRect()\n\n const elementBoundingBoxes = useMemo(() => {\n const boundingBoxes = new Map<object, BoundingBox>()\n\n for (const primitive of primitives) {\n if (!primitive._element) continue\n if (shouldExcludePrimitiveFromSnapping(primitive)) continue\n if (primitive.pcb_drawing_type === \"pill\") continue\n if (\n primitive.pcb_drawing_type === \"rect\" &&\n primitive.ccw_rotation &&\n primitive.ccw_rotation !== 0\n )\n continue\n const bbox = getPrimitiveBoundingBox(primitive)\n if (!bbox) continue\n\n const existing = boundingBoxes.get(primitive._element as object)\n boundingBoxes.set(\n primitive._element as object,\n mergeBoundingBoxes(existing ?? undefined, bbox),\n )\n }\n\n return boundingBoxes\n }, [primitives])\n\n const primitiveSnappingPoints = useMemo(() => {\n const snapPoints: {\n anchor: NinePointAnchor | string\n point: { x: number; y: number }\n element: object\n }[] = []\n\n for (const primitive of primitives) {\n if (!primitive._element) continue\n if (shouldExcludePrimitiveFromSnapping(primitive)) continue\n\n const primitivePoints = getPrimitiveSnapPoints(primitive)\n if (primitivePoints.length === 0) continue\n\n for (const snap of primitivePoints) {\n snapPoints.push({\n anchor: snap.anchor,\n point: snap.point,\n element: primitive._element as object,\n })\n }\n }\n\n return snapPoints\n }, [primitives])\n\n const snappingPoints = useMemo(() => {\n const points: {\n anchor: NinePointAnchor | \"origin\" | string\n point: { x: number; y: number }\n element: object | null\n }[] = []\n\n elementBoundingBoxes.forEach((bounds, element) => {\n if (!bounds) return\n\n const centerX = (bounds.minX + bounds.maxX) / 2\n const centerY = (bounds.minY + bounds.maxY) / 2\n\n const anchorPoints: Record<NinePointAnchor, { x: number; y: number }> = {\n top_left: { x: bounds.minX, y: bounds.minY },\n top_center: { x: centerX, y: bounds.minY },\n top_right: { x: bounds.maxX, y: bounds.minY },\n center_left: { x: bounds.minX, y: centerY },\n center: { x: centerX, y: centerY },\n center_right: { x: bounds.maxX, y: centerY },\n bottom_left: { x: bounds.minX, y: bounds.maxY },\n bottom_center: { x: centerX, y: bounds.maxY },\n bottom_right: { x: bounds.maxX, y: bounds.maxY },\n }\n\n for (const [anchor, point] of Object.entries(anchorPoints) as [\n NinePointAnchor,\n { x: number; y: number },\n ][]) {\n points.push({\n anchor,\n point,\n element,\n })\n }\n })\n\n for (const snap of primitiveSnappingPoints) {\n points.push(snap)\n }\n\n points.push({\n anchor: \"origin\",\n point: { x: 0, y: 0 },\n element: null,\n })\n\n return points\n }, [elementBoundingBoxes, primitiveSnappingPoints])\n\n const snappingPointsWithScreen = useMemo(() => {\n return snappingPoints.map((snap, index) => ({\n ...snap,\n id: `${index}-${snap.anchor}`,\n screenPoint: applyToPoint(transform!, snap.point),\n }))\n }, [snappingPoints, transform])\n\n const findSnap = useCallback(\n (rwPoint: { x: number; y: number }) => {\n if (snappingPointsWithScreen.length === 0) {\n return { point: rwPoint, id: null as string | null }\n }\n\n const screenPoint = applyToPoint(transform!, rwPoint)\n let bestMatch: {\n distance: number\n id: string\n point: { x: number; y: number }\n } | null = null\n\n for (const snap of snappingPointsWithScreen) {\n const dx = snap.screenPoint.x - screenPoint.x\n const dy = snap.screenPoint.y - screenPoint.y\n const distance = Math.hypot(dx, dy)\n\n if (distance > SNAP_THRESHOLD_PX) continue\n if (!bestMatch || distance < bestMatch.distance) {\n bestMatch = {\n distance,\n id: snap.id,\n point: snap.point,\n }\n }\n }\n\n if (!bestMatch) {\n return { point: rwPoint, id: null as string | null }\n }\n\n return { point: bestMatch.point, id: bestMatch.id }\n },\n [snappingPointsWithScreen, transform],\n )\n\n useEffect(() => {\n const down = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement\n if (\n target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.isContentEditable\n ) {\n return\n }\n\n const containerHasFocus =\n containerRef.current?.contains(document.activeElement) ||\n document.activeElement === containerRef.current\n if (!isMouseOverContainer && !containerHasFocus) return\n\n if (e.key === \"d\") {\n const snap = findSnap({\n x: mousePosRef.current.x,\n y: mousePosRef.current.y,\n })\n\n setDStart({ x: snap.point.x, y: snap.point.y })\n setDEnd({ x: snap.point.x, y: snap.point.y })\n setActiveSnapIds({ start: snap.id, end: snap.id })\n\n if (dimensionToolVisible) {\n setDimensionToolVisible(false)\n setDimensionToolStretching(false)\n setActiveSnapIds({ start: null, end: null })\n } else {\n setDimensionToolVisible(true)\n setDimensionToolStretching(true)\n }\n disarmMeasure()\n }\n if (e.key === \"Escape\") {\n setDimensionToolVisible(false)\n setDimensionToolStretching(false)\n setActiveSnapIds({ start: null, end: null })\n setBoundsToolVisible(false)\n setBoundsToolDragging(false)\n disarmMeasure()\n disarmBounds()\n }\n }\n\n const armMeasure = () => {\n setMeasureToolArmed(true)\n setBoundsToolArmed(false)\n window.dispatchEvent(new Event(\"disarm-bounds-tool\"))\n }\n\n const armBounds = () => {\n setBoundsToolArmed(true)\n setMeasureToolArmed(false)\n setDimensionToolVisible(false)\n setDimensionToolStretching(false)\n window.dispatchEvent(new Event(\"disarm-dimension-tool\"))\n }\n\n window.addEventListener(\"keydown\", down)\n window.addEventListener(\"arm-dimension-tool\", armMeasure)\n window.addEventListener(\"arm-bounds-tool\", armBounds)\n\n return () => {\n window.removeEventListener(\"keydown\", down)\n window.removeEventListener(\"arm-dimension-tool\", armMeasure)\n window.removeEventListener(\"arm-bounds-tool\", armBounds)\n disarmMeasure()\n disarmBounds()\n }\n }, [\n isMouseOverContainer,\n dimensionToolVisible,\n disarmMeasure,\n disarmBounds,\n findSnap,\n ])\n\n const screenDStart = applyToPoint(transform, dStart)\n const screenDEnd = applyToPoint(transform, dEnd)\n const screenBoundsStart = applyToPoint(transform, boundsStart)\n const screenBoundsEnd = applyToPoint(transform, boundsEnd)\n\n const selectedBounds = {\n minX: Math.min(boundsStart.x, boundsEnd.x),\n minY: Math.min(boundsStart.y, boundsEnd.y),\n maxX: Math.max(boundsStart.x, boundsEnd.x),\n maxY: Math.max(boundsStart.y, boundsEnd.y),\n }\n\n const boundsScreenRect = {\n left: Math.min(screenBoundsStart.x, screenBoundsEnd.x),\n top: Math.min(screenBoundsStart.y, screenBoundsEnd.y),\n width: Math.abs(screenBoundsStart.x - screenBoundsEnd.x),\n height: Math.abs(screenBoundsStart.y - screenBoundsEnd.y),\n }\n\n const emitBounds = useCallback(\n (start: { x: number; y: number }, end: { x: number; y: number }) => {\n const bounds = {\n minX: Math.min(start.x, end.x),\n minY: Math.min(start.y, end.y),\n maxX: Math.max(start.x, end.x),\n maxY: Math.max(start.y, end.y),\n }\n\n onBoundsSelected?.(bounds)\n window.dispatchEvent(\n new CustomEvent(\"pcb-viewer:bounds-selected\", {\n detail: bounds,\n }),\n )\n },\n [onBoundsSelected],\n )\n\n const arrowScreenBounds = {\n left: Math.min(screenDStart.x, screenDEnd.x),\n right: Math.max(screenDStart.x, screenDEnd.x),\n top: Math.min(screenDStart.y, screenDEnd.y),\n bottom: Math.max(screenDStart.y, screenDEnd.y),\n flipX: screenDStart.x > screenDEnd.x,\n flipY: screenDStart.y > screenDEnd.y,\n width: 0,\n height: 0,\n }\n arrowScreenBounds.width = arrowScreenBounds.right - arrowScreenBounds.left\n arrowScreenBounds.height = arrowScreenBounds.bottom - arrowScreenBounds.top\n\n const diagonalLabel = useDiagonalLabel({\n dimensionStart: dStart,\n dimensionEnd: dEnd,\n screenDimensionStart: screenDStart,\n screenDimensionEnd: screenDEnd,\n flipX: arrowScreenBounds.flipX,\n flipY: arrowScreenBounds.flipY,\n })\n\n return (\n <div\n ref={containerRef}\n data-pcb-viewer\n // biome-ignore lint/a11y/noNoninteractiveTabindex: <explanation>\n tabIndex={0}\n style={{ position: \"relative\", outline: \"none\" }}\n onMouseEnter={() => {\n if (focusOnHover && containerRef.current) {\n containerRef.current.focus()\n }\n }}\n onMouseLeave={() => {\n if (containerRef.current) {\n containerRef.current.blur()\n }\n }}\n onClick={() => {\n if (containerRef.current) {\n containerRef.current.focus()\n }\n }}\n onMouseMove={(e: React.MouseEvent<HTMLDivElement>) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const rwPoint = applyToPoint(inverse(transform!), { x, y })\n mousePosRef.current.x = rwPoint.x\n mousePosRef.current.y = rwPoint.y\n\n if (dimensionToolStretching) {\n const snap = findSnap(rwPoint)\n setDEnd({ x: snap.point.x, y: snap.point.y })\n setActiveSnapIds((prev) => ({ ...prev, end: snap.id }))\n }\n if (boundsToolDragging) {\n cancelPanDrag?.()\n setBoundsEnd({ x: rwPoint.x, y: rwPoint.y })\n }\n }}\n onMouseDown={(e) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const rwPoint = applyToPoint(inverse(transform!), { x, y })\n\n if (boundsToolArmed) {\n e.preventDefault()\n e.stopPropagation()\n cancelPanDrag?.()\n setBoundsStart({ x: rwPoint.x, y: rwPoint.y })\n setBoundsEnd({ x: rwPoint.x, y: rwPoint.y })\n setBoundsToolVisible(true)\n setBoundsToolDragging(true)\n disarmBounds()\n } else if (measureToolArmed && !dimensionToolVisible) {\n const snap = findSnap(rwPoint)\n setDStart({ x: snap.point.x, y: snap.point.y })\n setDEnd({ x: snap.point.x, y: snap.point.y })\n setActiveSnapIds({ start: snap.id, end: snap.id })\n setDimensionToolVisible(true)\n setDimensionToolStretching(true)\n disarmMeasure()\n } else if (dimensionToolStretching) {\n setDimensionToolStretching(false)\n setActiveSnapIds((prev) => ({ ...prev, end: null }))\n } else if (dimensionToolVisible) {\n setDimensionToolVisible(false)\n setActiveSnapIds({ start: null, end: null })\n }\n }}\n onMouseUp={(e) => {\n if (!boundsToolDragging) return\n\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const rwPoint = applyToPoint(inverse(transform!), { x, y })\n const end = { x: rwPoint.x, y: rwPoint.y }\n\n e.preventDefault()\n e.stopPropagation()\n cancelPanDrag?.()\n setBoundsEnd(end)\n setBoundsToolDragging(false)\n emitBounds(boundsStart, end)\n }}\n >\n {children}\n {boundsToolVisible && (\n <>\n {/* biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> */}\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n width={containerBounds.width}\n height={containerBounds.height}\n >\n <rect\n x={boundsScreenRect.left}\n y={boundsScreenRect.top}\n width={boundsScreenRect.width}\n height={boundsScreenRect.height}\n stroke=\"red\"\n strokeWidth={1.5}\n strokeDasharray=\"4,3\"\n fill=\"rgba(255, 0, 0, 0.12)\"\n />\n </svg>\n <div\n style={{\n left: 0,\n bottom: dimensionToolVisible ? 58 : 0,\n position: \"absolute\",\n color: \"red\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n margin: 4,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n minX: {selectedBounds.minX.toFixed(2)}, minY:{\" \"}\n {selectedBounds.minY.toFixed(2)}\n <br />\n maxX: {selectedBounds.maxX.toFixed(2)}, maxY:{\" \"}\n {selectedBounds.maxY.toFixed(2)}\n </div>\n </>\n )}\n {dimensionToolVisible && (\n <>\n {diagonalLabel.show && (\n <div\n style={{\n position: \"absolute\",\n left: diagonalLabel.x,\n top: diagonalLabel.y,\n color: \"red\",\n mixBlendMode: \"difference\",\n pointerEvents: \"none\",\n fontSize: 12,\n fontFamily: \"sans-serif\",\n whiteSpace: \"nowrap\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n {diagonalLabel.distance.toFixed(2)}\n </div>\n )}\n\n <div\n style={{\n position: \"absolute\",\n left: arrowScreenBounds.left,\n width: arrowScreenBounds.width,\n textAlign: \"center\",\n top: screenDStart.y + 2,\n color: \"red\",\n mixBlendMode: \"difference\",\n pointerEvents: \"none\",\n marginTop: arrowScreenBounds.flipY ? 0 : -20,\n fontSize: 12,\n fontFamily: \"sans-serif\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n {Math.abs(dStart.x - dEnd.x).toFixed(2)}\n </div>\n\n <div\n style={{\n position: \"absolute\",\n left: screenDEnd.x,\n height: arrowScreenBounds.height,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n top: arrowScreenBounds.top,\n color: \"red\",\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n fontSize: 12,\n fontFamily: \"sans-serif\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n <div\n style={{\n marginLeft: arrowScreenBounds.flipX ? \"-100%\" : 4,\n paddingRight: 4,\n }}\n >\n {Math.abs(dStart.y - dEnd.y).toFixed(2)}\n </div>\n </div>\n {/* biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> */}\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n width={containerBounds.width}\n height={containerBounds.height}\n >\n <defs>\n <marker\n id=\"head\"\n orient=\"auto\"\n markerWidth=\"3\"\n markerHeight=\"4\"\n refX=\"2\"\n refY=\"2\"\n >\n <path d=\"M0,0 V4 L2,2 Z\" fill=\"red\" />\n </marker>\n </defs>\n <line\n x1={screenDStart.x}\n y1={screenDStart.y}\n x2={screenDEnd.x}\n y2={screenDEnd.y}\n markerEnd=\"url(#head)\"\n strokeWidth={1.5}\n fill=\"none\"\n stroke=\"red\"\n />\n <line\n x1={screenDStart.x}\n y1={screenDStart.y}\n x2={screenDEnd.x}\n y2={screenDStart.y}\n strokeWidth={1.5}\n fill=\"none\"\n strokeDasharray={\"2,2\"}\n stroke=\"red\"\n />\n <line\n x1={screenDEnd.x}\n y1={screenDStart.y}\n x2={screenDEnd.x}\n y2={screenDEnd.y}\n strokeWidth={1.5}\n fill=\"none\"\n strokeDasharray={\"2,2\"}\n stroke=\"red\"\n />\n </svg>\n {dimensionToolStretching &&\n snappingPointsWithScreen.map((snap) => {\n const isActive =\n snap.id === activeSnapIds.start || snap.id === activeSnapIds.end\n const half = SNAP_MARKER_SIZE / 2\n return (\n <svg\n key={snap.id}\n width={SNAP_MARKER_SIZE}\n height={SNAP_MARKER_SIZE}\n style={{\n position: \"absolute\",\n left: snap.screenPoint.x - half,\n top: snap.screenPoint.y - half,\n pointerEvents: \"none\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n <line\n x1={0}\n y1={0}\n x2={SNAP_MARKER_SIZE}\n y2={SNAP_MARKER_SIZE}\n stroke={isActive ? \"#66ccff\" : \"white\"}\n strokeWidth={1}\n />\n <line\n x1={SNAP_MARKER_SIZE}\n y1={0}\n x2={0}\n y2={SNAP_MARKER_SIZE}\n stroke={isActive ? \"#66ccff\" : \"white\"}\n strokeWidth={1}\n />\n </svg>\n )\n })}\n <div\n style={{\n right: 0,\n bottom: 0,\n position: \"absolute\",\n color: \"red\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n margin: 4,\n }}\n >\n ({dStart.x.toFixed(2)},{dStart.y.toFixed(2)})<br />(\n {dEnd.x.toFixed(2)},{dEnd.y.toFixed(2)})<br />\n dist:{\" \"}\n {Math.sqrt(\n (dEnd.x - dStart.x) ** 2 + (dEnd.y - dStart.y) ** 2,\n ).toFixed(2)}\n </div>\n </>\n )}\n </div>\n )\n}\n","import type { Primitive } from \"../types\"\n\nexport interface BoundingBox {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\nconst mergeNumber = (\n a: number,\n b: number,\n fn: typeof Math.min | typeof Math.max,\n) => fn(a, b)\n\nconst rotatePoint = (\n x: number,\n y: number,\n centerX: number,\n centerY: number,\n rotationDeg: number,\n) => {\n const radians = (rotationDeg * Math.PI) / 180\n const cos = Math.cos(radians)\n const sin = Math.sin(radians)\n const translatedX = x - centerX\n const translatedY = y - centerY\n\n const rotatedX = translatedX * cos - translatedY * sin\n const rotatedY = translatedX * sin + translatedY * cos\n\n return {\n x: rotatedX + centerX,\n y: rotatedY + centerY,\n }\n}\n\nconst createBoxFromPoints = (\n points: { x: number; y: number }[],\n): BoundingBox | null => {\n if (points.length === 0) return null\n\n let minX = points[0]!.x\n let maxX = points[0]!.x\n let minY = points[0]!.y\n let maxY = points[0]!.y\n\n for (const point of points) {\n minX = mergeNumber(minX, point.x, Math.min)\n maxX = mergeNumber(maxX, point.x, Math.max)\n minY = mergeNumber(minY, point.y, Math.min)\n maxY = mergeNumber(maxY, point.y, Math.max)\n }\n\n return { minX, maxX, minY, maxY }\n}\nexport const getBoundsFromPoints = createBoxFromPoints\n\nconst mergeBoundingBoxesInternal = (\n a: BoundingBox,\n b: BoundingBox,\n): BoundingBox => ({\n minX: Math.min(a.minX, b.minX),\n maxX: Math.max(a.maxX, b.maxX),\n minY: Math.min(a.minY, b.minY),\n maxY: Math.max(a.maxY, b.maxY),\n})\n\nexport const mergeBoundingBoxes = (\n existing: BoundingBox | undefined,\n next: BoundingBox,\n): BoundingBox => {\n if (!existing) return next\n return mergeBoundingBoxesInternal(existing, next)\n}\n\nexport const getPrimitiveBoundingBox = (\n primitive: Primitive,\n): BoundingBox | null => {\n switch (primitive.pcb_drawing_type) {\n case \"line\": {\n const halfWidth = (primitive.width ?? 0) / 2\n const points = [\n { x: primitive.x1, y: primitive.y1 },\n { x: primitive.x2, y: primitive.y2 },\n ]\n\n const baseBox = createBoxFromPoints(points)\n if (!baseBox) return null\n\n return {\n minX: baseBox.minX - halfWidth,\n maxX: baseBox.maxX + halfWidth,\n minY: baseBox.minY - halfWidth,\n maxY: baseBox.maxY + halfWidth,\n }\n }\n case \"rect\": {\n const halfW = primitive.w / 2\n const halfH = primitive.h / 2\n const corners = [\n { x: primitive.x - halfW, y: primitive.y - halfH },\n { x: primitive.x + halfW, y: primitive.y - halfH },\n { x: primitive.x + halfW, y: primitive.y + halfH },\n { x: primitive.x - halfW, y: primitive.y + halfH },\n ]\n\n const rotation = primitive.ccw_rotation ?? 0\n const rotatedCorners =\n rotation === 0\n ? corners\n : corners.map((corner) =>\n rotatePoint(\n corner.x,\n corner.y,\n primitive.x,\n primitive.y,\n rotation,\n ),\n )\n\n return createBoxFromPoints(rotatedCorners)\n }\n case \"circle\": {\n return {\n minX: primitive.x - primitive.r,\n maxX: primitive.x + primitive.r,\n minY: primitive.y - primitive.r,\n maxY: primitive.y + primitive.r,\n }\n }\n case \"oval\": {\n return {\n minX: primitive.x - primitive.rX,\n maxX: primitive.x + primitive.rX,\n minY: primitive.y - primitive.rY,\n maxY: primitive.y + primitive.rY,\n }\n }\n case \"pill\": {\n const halfW = primitive.w / 2\n const halfH = primitive.h / 2\n const corners = [\n { x: primitive.x - halfW, y: primitive.y - halfH },\n { x: primitive.x + halfW, y: primitive.y - halfH },\n { x: primitive.x + halfW, y: primitive.y + halfH },\n { x: primitive.x - halfW, y: primitive.y + halfH },\n ]\n const rotation = primitive.ccw_rotation ?? 0\n const rotatedCorners =\n rotation === 0\n ? corners\n : corners.map((corner) =>\n rotatePoint(\n corner.x,\n corner.y,\n primitive.x,\n primitive.y,\n rotation,\n ),\n )\n return createBoxFromPoints(rotatedCorners)\n }\n case \"polygon\": {\n return createBoxFromPoints(primitive.points)\n }\n case \"polygon_with_arcs\": {\n const points = primitive.brep_shape.outer_ring.vertices.map((vertex) => ({\n x: vertex.x,\n y: vertex.y,\n }))\n return createBoxFromPoints(points)\n }\n case \"text\": {\n const size = primitive.size ?? 0\n const width = primitive.text ? primitive.text.length * size * 0.6 : 0\n const height = size\n\n if (width === 0 && height === 0) {\n return {\n minX: primitive.x,\n maxX: primitive.x,\n minY: primitive.y,\n maxY: primitive.y,\n }\n }\n\n const halfW = width / 2\n const halfH = height / 2\n return {\n minX: primitive.x - halfW,\n maxX: primitive.x + halfW,\n minY: primitive.y - halfH,\n maxY: primitive.y + halfH,\n }\n }\n default:\n return null\n }\n}\n","import { useMemo } from \"react\"\nimport {\n calculateDiagonalLabel,\n type DiagonalLabelResult,\n} from \"lib/util/calculate-diagonal-label\"\n\nexport interface UseDiagonalLabelParams {\n dimensionStart: { x: number; y: number }\n dimensionEnd: { x: number; y: number }\n screenDimensionStart: { x: number; y: number }\n screenDimensionEnd: { x: number; y: number }\n flipX: boolean\n flipY: boolean\n}\n\nexport function useDiagonalLabel(\n params: UseDiagonalLabelParams,\n): DiagonalLabelResult {\n const {\n dimensionStart,\n dimensionEnd,\n screenDimensionStart,\n screenDimensionEnd,\n flipX,\n flipY,\n } = params\n\n return useMemo(\n () =>\n calculateDiagonalLabel({\n dimensionStart,\n dimensionEnd,\n screenDimensionStart,\n screenDimensionEnd,\n flipX,\n flipY,\n }),\n [\n dimensionStart,\n dimensionEnd,\n screenDimensionStart,\n screenDimensionEnd,\n flipX,\n flipY,\n ],\n )\n}\n","export interface DiagonalLabelParams {\n dimensionStart: { x: number; y: number }\n dimensionEnd: { x: number; y: number }\n screenDimensionStart: { x: number; y: number }\n screenDimensionEnd: { x: number; y: number }\n flipX: boolean\n flipY: boolean\n}\n\nexport interface DiagonalLabelResult {\n distance: number\n screenDistance: number\n x: number\n y: number\n show: boolean\n}\n\nexport function calculateDiagonalLabel(\n params: DiagonalLabelParams,\n): DiagonalLabelResult {\n const {\n dimensionStart,\n dimensionEnd,\n screenDimensionStart,\n screenDimensionEnd,\n flipX,\n flipY,\n } = params\n\n // Calculate dimension distance in world coordinates\n const deltaX = dimensionEnd.x - dimensionStart.x\n const deltaY = dimensionEnd.y - dimensionStart.y\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)\n\n // Calculate screen distance and angle\n const screenDeltaX = screenDimensionEnd.x - screenDimensionStart.x\n const screenDeltaY = screenDimensionEnd.y - screenDimensionStart.y\n const screenDistance = Math.sqrt(\n screenDeltaX * screenDeltaX + screenDeltaY * screenDeltaY,\n )\n\n // Calculate angle of the measurement line\n const angle = Math.atan2(screenDeltaY, screenDeltaX) * (180 / Math.PI)\n\n const normalizedAngle = Math.abs(angle) % 90\n const angleFromAxis = Math.min(normalizedAngle, 90 - normalizedAngle)\n const isDiagonal = angleFromAxis > 15\n\n // Find midpoint of the diagonal line\n const midX = (screenDimensionStart.x + screenDimensionEnd.x) / 2\n const midY = (screenDimensionStart.y + screenDimensionEnd.y) / 2\n\n // Offset perpendicular to the line, always pointing away from the inner triangle\n const offsetDistance = 15\n const perpendicularAngle = angle + 90\n\n let offsetX = Math.cos((perpendicularAngle * Math.PI) / 180) * offsetDistance\n let offsetY = Math.sin((perpendicularAngle * Math.PI) / 180) * offsetDistance\n\n const isNE = screenDeltaX > 0 && screenDeltaY < 0\n const isNW = screenDeltaX < 0 && screenDeltaY < 0\n const isSE = screenDeltaX > 0 && screenDeltaY > 0\n const isSW = screenDeltaX < 0 && screenDeltaY > 0\n\n if (flipX !== flipY && !isNE) {\n offsetX = -offsetX\n offsetY = -offsetY\n }\n\n if (isNE) {\n const lessOffset = -45\n offsetX += Math.cos((perpendicularAngle * Math.PI) / 180) * lessOffset\n offsetY += Math.sin((perpendicularAngle * Math.PI) / 180) * lessOffset\n }\n\n if (isSE) {\n const seAdjust = -10\n offsetX += Math.cos((perpendicularAngle * Math.PI) / 180) + seAdjust * 2\n offsetY += Math.sin((perpendicularAngle * Math.PI) / 180) + seAdjust\n }\n\n if (isSW) {\n const reduceOffset = 10\n offsetX += Math.cos((perpendicularAngle * Math.PI) / 180) * reduceOffset\n offsetY += Math.sin((perpendicularAngle * Math.PI) / 180) * reduceOffset\n }\n\n const x = midX + offsetX\n const y = midY + offsetY\n\n return {\n distance,\n screenDistance,\n x,\n y,\n show: distance > 0.01 && screenDistance > 30 && isDiagonal,\n }\n}\n","import type { NinePointAnchor } from \"circuit-json\"\nimport type { Primitive } from \"../types\"\n\nexport interface PrimitiveSnapPoint {\n anchor: NinePointAnchor | string\n point: { x: number; y: number }\n}\n\nconst rotatePoint = (\n point: { x: number; y: number },\n center: { x: number; y: number },\n rotationDeg: number,\n) => {\n const radians = (rotationDeg * Math.PI) / 180\n const cos = Math.cos(radians)\n const sin = Math.sin(radians)\n\n const translatedX = point.x - center.x\n const translatedY = point.y - center.y\n\n const rotatedX = translatedX * cos - translatedY * sin\n const rotatedY = translatedX * sin + translatedY * cos\n\n return {\n x: rotatedX + center.x,\n y: rotatedY + center.y,\n }\n}\n\nconst getNinePointAnchors = (\n center: { x: number; y: number },\n halfWidth: number,\n halfHeight: number,\n rotationDeg: number,\n): PrimitiveSnapPoint[] => {\n const basePoints: Record<NinePointAnchor, { x: number; y: number }> = {\n top_left: { x: center.x - halfWidth, y: center.y - halfHeight },\n top_center: { x: center.x, y: center.y - halfHeight },\n top_right: { x: center.x + halfWidth, y: center.y - halfHeight },\n center_left: { x: center.x - halfWidth, y: center.y },\n center: { x: center.x, y: center.y },\n center_right: { x: center.x + halfWidth, y: center.y },\n bottom_left: { x: center.x - halfWidth, y: center.y + halfHeight },\n bottom_center: { x: center.x, y: center.y + halfHeight },\n bottom_right: { x: center.x + halfWidth, y: center.y + halfHeight },\n }\n\n if (rotationDeg === 0) {\n return Object.entries(basePoints).map(([anchor, point]) => ({\n anchor: anchor as NinePointAnchor,\n point,\n }))\n }\n\n return Object.entries(basePoints).map(([anchor, point]) => ({\n anchor: anchor as NinePointAnchor,\n point: rotatePoint(point, center, rotationDeg),\n }))\n}\n\nexport const getPrimitiveSnapPoints = (\n primitive: Primitive,\n): PrimitiveSnapPoint[] => {\n switch (primitive.pcb_drawing_type) {\n case \"rect\": {\n const rotation = primitive.ccw_rotation ?? 0\n return getNinePointAnchors(\n { x: primitive.x, y: primitive.y },\n primitive.w / 2,\n primitive.h / 2,\n rotation,\n )\n }\n case \"pill\": {\n const rotation = primitive.ccw_rotation ?? 0\n return getNinePointAnchors(\n { x: primitive.x, y: primitive.y },\n primitive.w / 2,\n primitive.h / 2,\n rotation,\n )\n }\n case \"circle\": {\n return [\n { anchor: \"circle_center\", point: { x: primitive.x, y: primitive.y } },\n {\n anchor: \"circle_right\",\n point: { x: primitive.x + primitive.r, y: primitive.y },\n },\n {\n anchor: \"circle_left\",\n point: { x: primitive.x - primitive.r, y: primitive.y },\n },\n {\n anchor: \"circle_top\",\n point: { x: primitive.x, y: primitive.y - primitive.r },\n },\n {\n anchor: \"circle_bottom\",\n point: { x: primitive.x, y: primitive.y + primitive.r },\n },\n ]\n }\n case \"oval\": {\n return [\n { anchor: \"oval_center\", point: { x: primitive.x, y: primitive.y } },\n {\n anchor: \"oval_right\",\n point: { x: primitive.x + primitive.rX, y: primitive.y },\n },\n {\n anchor: \"oval_left\",\n point: { x: primitive.x - primitive.rX, y: primitive.y },\n },\n {\n anchor: \"oval_top\",\n point: { x: primitive.x, y: primitive.y - primitive.rY },\n },\n {\n anchor: \"oval_bottom\",\n point: { x: primitive.x, y: primitive.y + primitive.rY },\n },\n ]\n }\n case \"line\": {\n const midPoint = {\n x: (primitive.x1 + primitive.x2) / 2,\n y: (primitive.y1 + primitive.y2) / 2,\n }\n return [\n { anchor: \"line_start\", point: { x: primitive.x1, y: primitive.y1 } },\n { anchor: \"line_mid\", point: midPoint },\n { anchor: \"line_end\", point: { x: primitive.x2, y: primitive.y2 } },\n ]\n }\n case \"polygon\": {\n return primitive.points.map((point, index) => ({\n anchor: `polygon_vertex_${index}`,\n point,\n }))\n }\n case \"polygon_with_arcs\": {\n return primitive.brep_shape.outer_ring.vertices.map((vertex, index) => ({\n anchor: `polygon_with_arcs_vertex_${index}`,\n point: { x: vertex.x, y: vertex.y },\n }))\n }\n default:\n return []\n }\n}\n","import type { AnyCircuitElement, PcbComponent } from \"circuit-json\"\nimport { useGlobalStore } from \"../global-store\"\nimport { useEffect, useRef, useState } from \"react\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { applyToPoint, identity, inverse } from \"transformation-matrix\"\nimport type { ManualEditEvent } from \"@tscircuit/props\"\n\ninterface Props {\n transform?: Matrix\n children: any\n soup: AnyCircuitElement[]\n disabled?: boolean\n cancelPanDrag: () => void\n onCreateEditEvent: (event: ManualEditEvent) => void\n onModifyEditEvent: (event: Partial<ManualEditEvent>) => void\n}\n\nconst isInsideOf = (\n pcb_component: PcbComponent,\n point: { x: number; y: number },\n padding = 0,\n) => {\n const halfWidth = pcb_component.width / 2\n const halfHeight = pcb_component.height / 2\n\n const left = pcb_component.center.x - halfWidth - padding\n const right = pcb_component.center.x + halfWidth + padding\n const top = pcb_component.center.y - halfHeight - padding\n const bottom = pcb_component.center.y + halfHeight + padding\n\n return point.x > left && point.x < right && point.y > top && point.y < bottom\n}\n\nexport const EditPlacementOverlay = ({\n children,\n disabled: disabledProp,\n transform,\n soup,\n cancelPanDrag,\n onCreateEditEvent,\n onModifyEditEvent,\n}: Props) => {\n if (!transform) transform = identity()\n const containerRef = useRef<HTMLDivElement | null>(null)\n const [activePcbComponentId, setActivePcbComponent] = useState<null | string>(\n null,\n )\n const [dragState, setDragState] = useState<{\n dragStart: { x: number; y: number }\n originalCenter: { x: number; y: number }\n dragEnd: { x: number; y: number }\n edit_event_id: string\n } | null>(null)\n const isPcbComponentActive = activePcbComponentId !== null\n const in_edit_mode = useGlobalStore((s) => s.in_edit_mode)\n const in_move_footprint_mode = useGlobalStore((s) => s.in_move_footprint_mode)\n const setIsMovingComponent = useGlobalStore((s) => s.setIsMovingComponent)\n\n const disabled = disabledProp || !in_move_footprint_mode\n\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n }}\n onMouseDown={(e) => {\n if (disabled) return\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n if (Number.isNaN(x) || Number.isNaN(y)) return\n const rwMousePoint = applyToPoint(inverse(transform!), { x, y })\n\n let foundActiveComponent = false\n for (const e of soup) {\n if (\n e.type === \"pcb_component\" &&\n isInsideOf(e, rwMousePoint, 10 / transform.a)\n ) {\n cancelPanDrag()\n setActivePcbComponent(e.pcb_component_id)\n foundActiveComponent = true\n const edit_event_id = Math.random().toString()\n setDragState({\n dragStart: rwMousePoint,\n originalCenter: e.center,\n dragEnd: rwMousePoint,\n edit_event_id,\n })\n\n onCreateEditEvent({\n edit_event_id,\n edit_event_type: \"edit_pcb_component_location\",\n pcb_edit_event_type: \"edit_component_location\",\n pcb_component_id: e.pcb_component_id,\n original_center: e.center,\n new_center: e.center,\n in_progress: true,\n created_at: Date.now(),\n })\n\n setIsMovingComponent(true)\n break\n }\n }\n if (!foundActiveComponent) {\n setActivePcbComponent(null)\n }\n\n if (foundActiveComponent) {\n e.preventDefault()\n return false\n }\n }}\n onMouseMove={(e) => {\n if (!activePcbComponentId || !dragState) return\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n if (Number.isNaN(x) || Number.isNaN(y)) return\n const rwMousePoint = applyToPoint(inverse(transform!), { x, y })\n setDragState({\n ...dragState,\n dragEnd: rwMousePoint,\n })\n onModifyEditEvent({\n edit_event_id: dragState.edit_event_id,\n new_center: {\n x:\n dragState.originalCenter.x +\n rwMousePoint.x -\n dragState.dragStart.x,\n y:\n dragState.originalCenter.y +\n rwMousePoint.y -\n dragState.dragStart.y,\n },\n })\n }}\n onMouseUp={(e) => {\n if (!activePcbComponentId) return\n setActivePcbComponent(null)\n setIsMovingComponent(false)\n if (dragState) {\n onModifyEditEvent({\n edit_event_id: dragState.edit_event_id,\n in_progress: false,\n })\n setDragState(null)\n }\n }}\n >\n {children}\n {!disabled &&\n soup\n .filter((e): e is PcbComponent => e.type === \"pcb_component\")\n .map((e) => {\n if (!e?.center) return null\n const projectedCenter = applyToPoint(transform, e.center)\n\n return (\n <div\n key={e.pcb_component_id}\n style={{\n position: \"absolute\",\n pointerEvents: \"none\",\n // b/c of transform, this is actually center not left/top\n left: projectedCenter.x,\n top: projectedCenter.y,\n width: e.width * transform.a + 20,\n height: e.height * transform.a + 20,\n transform: \"translate(-50%, -50%)\",\n background:\n isPcbComponentActive &&\n activePcbComponentId === e.pcb_component_id\n ? \"rgba(255, 0, 0, 0.2)\"\n : \"\",\n }}\n />\n )\n })}\n </div>\n )\n}\n","import React, { useRef, Fragment } from \"react\"\nimport { css } from \"@emotion/css\"\nimport type { AnyCircuitElement, PcbTraceError } from \"circuit-json\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { type Matrix, applyToPoint, identity } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\nimport { getPopupPosition } from \"lib/util/getPopupPosition\"\nimport type { PcbViaClearanceError } from \"circuit-json\"\nimport { findErrorElementById, getErrorId } from \"lib/util/get-error-id\"\nimport {\n buildErrorPreviewElementIndexes,\n getErrorFocusPoint,\n} from \"lib/util/error-preview\"\nimport { FocusMarkerSVG } from \"./FocusMarkerSVG\"\n\ninterface Props {\n transform?: Matrix\n elements?: AnyCircuitElement[]\n children: React.ReactNode\n}\n\ninterface ErrorMarkerSVGProps {\n errorCenter: { x: number; y: number }\n isHighlighted?: boolean\n}\n\nconst ErrorMarkerSVG = ({\n errorCenter,\n isHighlighted = false,\n}: ErrorMarkerSVGProps) => (\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.errorOverlay,\n }}\n width=\"100%\"\n height=\"100%\"\n >\n <rect\n x={errorCenter.x - 7}\n y={errorCenter.y - 7}\n width={14}\n height={14}\n transform={`rotate(45 ${errorCenter.x} ${errorCenter.y})`}\n fill={isHighlighted ? \"#ff4444\" : \"transparent\"}\n stroke={isHighlighted ? \"#ff4444\" : \"red\"}\n strokeWidth={isHighlighted ? 2.5 : 1.5}\n />\n </svg>\n)\n\nconst errorMessageStyles = css`\n opacity: 0;\n pointer-events: none;\n background-color: rgba(0, 0, 0, 0.8);\n padding: 8px 12px;\n border-radius: 4px;\n width: 200px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n word-wrap: break-word;\n line-height: 1.4;\n transition: opacity 0.2s;\n margin-bottom: 10px;\n color: red;\n`\n\nexport const ErrorOverlay = ({\n children,\n transform = identity(),\n elements,\n}: Props) => {\n const containerRef = useRef<HTMLDivElement | null>(null)\n\n const { isShowingDRCErrors, hoveredErrorId, focusedErrorId } = useGlobalStore(\n (state) => ({\n isShowingDRCErrors: state.is_showing_drc_errors,\n hoveredErrorId: state.hovered_error_id,\n focusedErrorId: state.focused_error_id,\n }),\n )\n const activeErrorId = focusedErrorId ?? hoveredErrorId\n\n if (!elements) {\n return (\n <div style={{ position: \"relative\" }} ref={containerRef}>\n {children}\n </div>\n )\n }\n\n const traceErrors = elements.filter(\n (el): el is PcbTraceError =>\n el.type === \"pcb_trace_error\" &&\n !el.message?.includes(\"Multiple components found with name\"),\n )\n const viaClearanceErrors = elements.filter(\n (el): el is PcbViaClearanceError => el.type === \"pcb_via_clearance_error\",\n )\n\n const componentErrors = elements.filter(\n (el): el is PcbTraceError =>\n el.type === \"pcb_trace_error\" &&\n el.message?.includes(\"Multiple components found with name\"),\n )\n\n const elementIndexes = buildErrorPreviewElementIndexes(elements)\n\n const focusedErrorElement = findErrorElementById(elements, activeErrorId)\n const getScreenErrorCenter = (error: AnyCircuitElement) => {\n const focusCenter = getErrorFocusPoint({\n error,\n indexes: elementIndexes,\n })\n\n if (\n !focusCenter ||\n typeof focusCenter.x !== \"number\" ||\n typeof focusCenter.y !== \"number\"\n ) {\n return null\n }\n\n const screenCenter = applyToPoint(transform, focusCenter as any) as any\n\n if (Number.isNaN(screenCenter.x) || Number.isNaN(screenCenter.y)) {\n return null\n }\n\n return screenCenter as { x: number; y: number }\n }\n\n let focusScreenCenter: { x: number; y: number } | null = null\n if (focusedErrorElement) {\n focusScreenCenter = getScreenErrorCenter(\n focusedErrorElement as AnyCircuitElement,\n )\n }\n\n return (\n <div style={{ position: \"relative\" }} ref={containerRef}>\n {children}\n {traceErrors.map((el: PcbTraceError, index) => {\n const errorId = getErrorId(el, index)\n const isHighlighted = activeErrorId === errorId\n\n if (!isHighlighted && !isShowingDRCErrors) return null\n\n const errorCenter = getScreenErrorCenter(el)\n if (!errorCenter) return null\n\n const popupPosition = getPopupPosition(errorCenter, containerRef)\n\n return (\n <Fragment key={errorId}>\n <ErrorMarkerSVG\n errorCenter={errorCenter}\n isHighlighted={isHighlighted}\n />\n <div\n style={{\n position: \"absolute\",\n left: errorCenter.x - 15,\n top: errorCenter.y - 15,\n width: 30,\n height: 30,\n zIndex: zIndexMap.errorOverlay + 5,\n cursor: \"pointer\",\n borderRadius: \"50%\",\n }}\n onMouseEnter={(e) => {\n const popup = e.currentTarget.nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"1\"\n }\n }}\n onMouseLeave={(e) => {\n if (!isHighlighted) {\n const popup = e.currentTarget\n .nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"0\"\n }\n }\n }}\n />\n <div\n style={{\n position: \"absolute\",\n zIndex: isHighlighted ? 200 : 100,\n left: popupPosition.left,\n top: popupPosition.top,\n color: isHighlighted ? \"#ff4444\" : \"red\",\n textAlign: \"center\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n display: isShowingDRCErrors || isHighlighted ? \"flex\" : \"none\",\n flexDirection: \"column\",\n alignItems: \"center\",\n pointerEvents: \"none\",\n transform: popupPosition.transform,\n }}\n >\n <div\n className={`error-message ${errorMessageStyles}`}\n style={{\n opacity: isHighlighted ? 1 : 0,\n border: `1px solid ${isHighlighted ? \"#ff4444\" : \"red\"}`,\n }}\n >\n {el.message}\n </div>\n </div>\n </Fragment>\n )\n })}\n {viaClearanceErrors.map((el, index) => {\n const errorId = getErrorId(el, index)\n const isHighlighted = activeErrorId === errorId\n\n if (!isHighlighted && !isShowingDRCErrors) return null\n\n const errorCenter = getScreenErrorCenter(el)\n if (!errorCenter) return null\n\n const popupPosition = getPopupPosition(\n { x: errorCenter.x, y: errorCenter.y },\n containerRef,\n )\n\n return (\n <Fragment key={errorId}>\n <ErrorMarkerSVG\n errorCenter={errorCenter}\n isHighlighted={isHighlighted}\n />\n <div\n style={{\n position: \"absolute\",\n left: errorCenter.x - 15,\n top: errorCenter.y - 15,\n width: 30,\n height: 30,\n zIndex: zIndexMap.errorOverlay + 5,\n cursor: \"pointer\",\n borderRadius: \"50%\",\n }}\n onMouseEnter={(e) => {\n const popup = e.currentTarget.nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"1\"\n }\n }}\n onMouseLeave={(e) => {\n if (!isHighlighted) {\n const popup = e.currentTarget\n .nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"0\"\n }\n }\n }}\n />\n <div\n style={{\n position: \"absolute\",\n zIndex: isHighlighted\n ? zIndexMap.errorOverlay + 10\n : zIndexMap.errorOverlay + 1,\n left: popupPosition.left,\n top: popupPosition.top,\n color: isHighlighted ? \"#ff4444\" : \"red\",\n textAlign: \"center\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n pointerEvents: \"none\",\n transform: popupPosition.transform,\n }}\n >\n <div\n className={`error-message ${errorMessageStyles}`}\n style={{\n opacity: isHighlighted ? 1 : 0,\n border: `1px solid ${isHighlighted ? \"#ff4444\" : \"red\"}`,\n }}\n >\n {el.message}\n </div>\n </div>\n </Fragment>\n )\n })}\n {componentErrors.map((el: any, index) => {\n const componentName =\n el.component_name || el.message?.match(/name \"([^\"]+)\"/)?.[1]\n if (!componentName) return null\n\n const components =\n elements?.filter(\n (comp) =>\n (comp.type === \"source_component\" &&\n comp.name === componentName) ||\n (comp.type === \"pcb_component\" &&\n elements?.find(\n (src) =>\n src.type === \"source_component\" &&\n src.source_component_id === comp.source_component_id &&\n src.name === componentName,\n )),\n ) || []\n\n const errorId = getErrorId(el, index)\n const isHighlighted = activeErrorId === errorId\n\n if (!isHighlighted && !isShowingDRCErrors) return null\n\n return components.map((comp, compIndex) => {\n let center = { x: 0, y: 0 }\n\n if (comp.type === \"pcb_component\") {\n center = comp.center || { x: 0, y: 0 }\n } else if (comp.type === \"source_component\") {\n const pcbComp = elements?.find(\n (pc) =>\n pc.type === \"pcb_component\" &&\n pc.source_component_id === comp.source_component_id,\n )\n if (pcbComp && pcbComp.type === \"pcb_component\")\n center = pcbComp.center || { x: 0, y: 0 }\n }\n\n const screenCenter = applyToPoint(transform, center)\n if (Number.isNaN(screenCenter.x) || Number.isNaN(screenCenter.y))\n return null\n\n const scale = Math.abs(transform.a)\n const baseRadius = 0.5\n const minRadius = 8\n const maxRadius = 30\n const scaledRadius = Math.max(\n minRadius,\n Math.min(maxRadius, baseRadius * scale),\n )\n\n const popupPosition = getPopupPosition(screenCenter, containerRef)\n\n return (\n <Fragment key={`${errorId}_${compIndex}`}>\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.errorOverlay,\n }}\n width=\"100%\"\n height=\"100%\"\n >\n {isHighlighted ? (\n <polygon\n points={`${screenCenter.x},${screenCenter.y - scaledRadius * 1.25} ${screenCenter.x + scaledRadius},${screenCenter.y} ${screenCenter.x},${screenCenter.y + scaledRadius * 1.25} ${screenCenter.x - scaledRadius},${screenCenter.y}`}\n fill=\"#ff4444\"\n />\n ) : (\n <circle\n cx={screenCenter.x}\n cy={screenCenter.y}\n r={scaledRadius}\n fill=\"none\"\n stroke={isHighlighted ? \"#ff4444\" : \"red\"}\n strokeWidth={\n isHighlighted\n ? Math.max(2, scaledRadius * 0.15)\n : Math.max(1, scaledRadius * 0.1)\n }\n opacity={1}\n />\n )}\n </svg>\n\n <div\n style={{\n position: \"absolute\",\n left: screenCenter.x - (scaledRadius + 10),\n top: screenCenter.y - (scaledRadius + 10),\n width: (scaledRadius + 10) * 2,\n height: (scaledRadius + 10) * 2,\n zIndex: zIndexMap.errorOverlay + 5,\n cursor: \"pointer\",\n borderRadius: \"50%\",\n }}\n onMouseEnter={(e) => {\n const popup = e.currentTarget\n .nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"1\"\n }\n }}\n onMouseLeave={(e) => {\n if (!isHighlighted) {\n const popup = e.currentTarget\n .nextElementSibling as HTMLElement\n if (popup) {\n const msg = popup.querySelector(\n \".error-message\",\n ) as HTMLElement\n if (msg) msg.style.opacity = \"0\"\n }\n }\n }}\n />\n <div\n style={{\n position: \"absolute\",\n zIndex: isHighlighted\n ? zIndexMap.errorOverlay + 20\n : zIndexMap.errorOverlay + 10,\n left: popupPosition.left,\n top: popupPosition.top,\n color: isHighlighted ? \"#ff4444\" : \"red\",\n textAlign: \"center\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n display:\n isShowingDRCErrors || isHighlighted ? \"flex\" : \"none\",\n flexDirection: \"column\",\n alignItems: \"center\",\n pointerEvents: \"none\",\n transform: popupPosition.transform,\n }}\n >\n <div\n className={`error-message ${errorMessageStyles}`}\n style={{\n opacity: isHighlighted ? 1 : 0,\n border: `1px solid ${isHighlighted ? \"#ff4444\" : \"red\"}`,\n }}\n >\n {el.message}\n </div>\n </div>\n </Fragment>\n )\n })\n })}\n {focusScreenCenter && <FocusMarkerSVG center={focusScreenCenter} />}\n </div>\n )\n}\n","export const getPopupPosition = (\n errorCenter: { x: number; y: number },\n containerRef: React.RefObject<HTMLDivElement | null>,\n) => {\n const container = containerRef.current\n if (!container)\n return {\n transform: \"translate(-50%, -100%)\",\n left: errorCenter.x,\n top: errorCenter.y,\n }\n\n const containerRect = container.getBoundingClientRect()\n const popupWidth = 200\n const margin = 10\n const horizontalOffset = 60\n let transformX = \"-50%\"\n let transformY = \"-100%\"\n let left = errorCenter.x\n let top = errorCenter.y\n\n if (\n errorCenter.x + horizontalOffset + popupWidth <\n containerRect.width - margin\n ) {\n left = errorCenter.x + horizontalOffset\n transformX = \"0%\"\n } else if (errorCenter.x - horizontalOffset - popupWidth > margin) {\n left = errorCenter.x - horizontalOffset\n transformX = \"-100%\"\n } else {\n left = errorCenter.x\n transformX = \"-50%\"\n }\n\n return {\n transform: `translate(${transformX}, ${transformY})`,\n left,\n top,\n }\n}\n","import React from \"react\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\n\nexport const FocusMarkerSVG = ({\n center,\n}: {\n center: { x: number; y: number }\n}) => (\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n mixBlendMode: \"difference\",\n zIndex: zIndexMap.errorOverlay + 30,\n }}\n width=\"100%\"\n height=\"100%\"\n >\n <circle\n cx={center.x}\n cy={center.y}\n r={11}\n fill=\"none\"\n stroke=\"#ff6b6b\"\n strokeWidth={2.5}\n opacity={0.95}\n />\n <circle cx={center.x} cy={center.y} r={4.5} fill=\"#ff6b6b\" opacity={0.95} />\n <line\n x1={center.x - 18}\n y1={center.y}\n x2={center.x - 8}\n y2={center.y}\n stroke=\"#ff6b6b\"\n strokeWidth={2}\n />\n <line\n x1={center.x + 8}\n y1={center.y}\n x2={center.x + 18}\n y2={center.y}\n stroke=\"#ff6b6b\"\n strokeWidth={2}\n />\n <line\n x1={center.x}\n y1={center.y - 18}\n x2={center.x}\n y2={center.y - 8}\n stroke=\"#ff6b6b\"\n strokeWidth={2}\n />\n <line\n x1={center.x}\n y1={center.y + 8}\n x2={center.x}\n y2={center.y + 18}\n stroke=\"#ff6b6b\"\n strokeWidth={2}\n />\n </svg>\n)\n","import { pointToSegmentDistance } from \"@tscircuit/math-utils\"\nimport type { AnyCircuitElement, LayerRef } from \"circuit-json\"\nimport { distance } from \"circuit-json\"\nimport type { Primitive } from \"lib/types\"\nimport { ifSetsMatchExactly } from \"lib/util/if-sets-match-exactly\"\nimport type React from \"react\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { applyToPoint, inverse } from \"transformation-matrix\"\nimport {\n BoardAnchorOffsetOverlay,\n ComponentBoundingBoxOverlay,\n GroupAnchorOffsetOverlay,\n PanelAnchorOffsetOverlay,\n} from \"./AnchorOffsetOverlay\"\nimport { ElementOverlayBox } from \"./ElementOverlayBox\"\n\nconst getPolygonBoundingBox = (\n points: ReadonlyArray<{ x: number; y: number }>,\n) => {\n if (points.length === 0) return null\n\n let minX = points[0]!.x\n let minY = points[0]!.y\n let maxX = points[0]!.x\n let maxY = points[0]!.y\n\n for (const point of points) {\n if (point.x < minX) minX = point.x\n if (point.y < minY) minY = point.y\n if (point.x > maxX) maxX = point.x\n if (point.y > maxY) maxY = point.y\n }\n\n return {\n center: {\n x: (minX + maxX) / 2,\n y: (minY + maxY) / 2,\n },\n width: maxX - minX,\n height: maxY - minY,\n }\n}\n\nconst isPointInsidePolygon = (\n point: { x: number; y: number },\n polygon: ReadonlyArray<{ x: number; y: number }>,\n) => {\n if (polygon.length < 3) return false\n\n let isInside = false\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i]!.x\n const yi = polygon[i]!.y\n const xj = polygon[j]!.x\n const yj = polygon[j]!.y\n\n const intersects =\n yi > point.y !== yj > point.y &&\n point.x < ((xj - xi) * (point.y - yi)) / (yj - yi || Number.EPSILON) + xi\n\n if (intersects) {\n isInside = !isInside\n }\n }\n\n return isInside\n}\n\nexport const getPrimitivesUnderPoint = (\n primitives: Primitive[],\n rwPoint: { x: number; y: number },\n transform: Matrix,\n selectedLayer: LayerRef,\n): Primitive[] => {\n const newMousedPrimitives: Primitive[] = []\n\n for (const primitive of primitives) {\n if (!primitive._element) continue\n if (\n primitive._element.type === \"pcb_trace\" &&\n primitive.layer !== selectedLayer\n ) {\n continue\n }\n\n // Handle PCB traces\n if (\"x1\" in primitive && primitive._element?.type === \"pcb_trace\") {\n const distance = pointToSegmentDistance(\n { x: rwPoint.x, y: rwPoint.y },\n { x: primitive.x1, y: primitive.y1 },\n { x: primitive.x2, y: primitive.y2 },\n )\n\n const lineWidth = primitive.width || 0.5\n const detectionThreshold = Math.max(lineWidth * 25, 2) / transform!.a\n\n if (distance < detectionThreshold) {\n newMousedPrimitives.push(primitive)\n }\n continue\n }\n\n if (primitive.pcb_drawing_type === \"polygon\") {\n const points = primitive.points.map((point) => ({\n x: distance.parse(point.x),\n y: distance.parse(point.y),\n }))\n const boundingBox = getPolygonBoundingBox(points)\n if (!boundingBox) continue\n\n if (\n rwPoint.x < boundingBox.center.x - boundingBox.width / 2 ||\n rwPoint.x > boundingBox.center.x + boundingBox.width / 2 ||\n rwPoint.y < boundingBox.center.y - boundingBox.height / 2 ||\n rwPoint.y > boundingBox.center.y + boundingBox.height / 2\n ) {\n continue\n }\n\n if (isPointInsidePolygon(rwPoint, points)) {\n newMousedPrimitives.push(primitive)\n }\n continue\n }\n\n if (primitive.pcb_drawing_type === \"polygon_with_arcs\") {\n const points = primitive.brep_shape.outer_ring.vertices.map((v) => ({\n x: distance.parse(v.x),\n y: distance.parse(v.y),\n }))\n const boundingBox = getPolygonBoundingBox(points)\n if (!boundingBox) continue\n\n if (\n rwPoint.x < boundingBox.center.x - boundingBox.width / 2 ||\n rwPoint.x > boundingBox.center.x + boundingBox.width / 2 ||\n rwPoint.y < boundingBox.center.y - boundingBox.height / 2 ||\n rwPoint.y > boundingBox.center.y + boundingBox.height / 2\n ) {\n continue\n }\n\n if (isPointInsidePolygon(rwPoint, points)) {\n newMousedPrimitives.push(primitive)\n }\n continue\n }\n\n // Handle primitives with x, y coordinates\n if (!(\"x\" in primitive && \"y\" in primitive)) continue\n\n let w = 0\n let h = 0\n\n if (\"w\" in primitive && \"h\" in primitive) {\n w = primitive.w\n h = primitive.h\n } else if (\"r\" in primitive) {\n w = (primitive as any).r * 2\n h = (primitive as any).r * 2\n } else if (\"rX\" in primitive && \"rY\" in primitive) {\n w = primitive.rX * 2\n h = primitive.rY * 2\n } else {\n continue\n }\n\n if (\n Math.abs((primitive as any).x - rwPoint.x) < w / 2 &&\n Math.abs((primitive as any).y - rwPoint.y) < h / 2\n ) {\n newMousedPrimitives.push(primitive)\n }\n }\n\n return newMousedPrimitives\n}\n\nexport const MouseElementTracker = ({\n elements,\n children,\n transform,\n primitives,\n selectedLayer,\n onMouseHoverOverPrimitives,\n}: {\n elements: AnyCircuitElement[]\n children: React.ReactNode\n transform?: Matrix\n primitives: Primitive[]\n selectedLayer: LayerRef\n onMouseHoverOverPrimitives: (primitivesHoveredOver: Primitive[]) => void\n}) => {\n const [mousedPrimitives, setMousedPrimitives] = useState<Primitive[]>([])\n const [mousePos, setMousePos] = useState({ x: 0, y: 0 })\n const [containerRef, { width, height }] = useMeasure<HTMLDivElement>()\n\n useEffect(() => {\n setMousedPrimitives([])\n onMouseHoverOverPrimitives([])\n }, [selectedLayer, onMouseHoverOverPrimitives])\n\n const highlightedPrimitives = useMemo(() => {\n const highlightedPrimitives: HighlightedPrimitive[] = []\n\n for (const primitive of mousedPrimitives) {\n if (primitive._element?.type === \"pcb_via\") continue\n if (primitive._element?.type === \"pcb_component\") continue\n if (primitive?.layer === \"drill\") continue\n if (primitive?.is_hoverable === false) continue\n\n let basePoint: { x: number; y: number } | null = null\n let w = 0\n let h = 0\n\n if (primitive.pcb_drawing_type === \"polygon\") {\n const boundingBox = getPolygonBoundingBox(primitive.points)\n if (!boundingBox) continue\n basePoint = boundingBox.center\n w = boundingBox.width\n h = boundingBox.height\n } else if (primitive.pcb_drawing_type === \"polygon_with_arcs\") {\n const points = primitive.brep_shape.outer_ring.vertices.map((v) => ({\n x: v.x,\n y: v.y,\n }))\n const boundingBox = getPolygonBoundingBox(points)\n if (!boundingBox) continue\n basePoint = boundingBox.center\n w = boundingBox.width\n h = boundingBox.height\n } else if (primitive.pcb_drawing_type === \"line\") {\n basePoint = {\n x: (primitive.x1 + primitive.x2) / 2,\n y: (primitive.y1 + primitive.y2) / 2,\n }\n w = Math.abs(primitive.x2 - primitive.x1)\n h = Math.abs(primitive.y2 - primitive.y1)\n } else if (\"x\" in primitive && \"y\" in primitive) {\n basePoint = { x: primitive.x, y: primitive.y }\n w =\n \"w\" in primitive\n ? primitive.w\n : \"r\" in primitive\n ? primitive.r * 2\n : \"rX\" in primitive && \"rY\" in primitive\n ? primitive.rX * 2\n : 0\n h =\n \"h\" in primitive\n ? primitive.h\n : \"r\" in primitive\n ? primitive.r * 2\n : \"rX\" in primitive && \"rY\" in primitive\n ? primitive.rY * 2\n : 0\n }\n\n if (!basePoint) continue\n\n const screenPos = applyToPoint(transform!, basePoint)\n const screenSize = {\n w: w * transform!.a,\n h: h * transform!.a,\n }\n\n // FANCY: If 2+ highlighted primitives inhabit the same space, give\n // them an incrementing same_space_index\n const same_space_index = highlightedPrimitives.filter(\n (hp) =>\n screenPos.x === hp.screen_x &&\n screenPos.y === hp.screen_y &&\n screenSize.w === hp.screen_w &&\n screenSize.h === hp.screen_h,\n ).length\n\n highlightedPrimitives.push({\n ...(primitive as any),\n x: basePoint.x,\n y: basePoint.y,\n w,\n h,\n screen_x: screenPos.x,\n screen_y: screenPos.y,\n screen_w: screenSize.w,\n screen_h: screenSize.h,\n same_space_index,\n })\n }\n\n return highlightedPrimitives\n }, [mousedPrimitives, transform])\n\n const handleInteraction = (\n x: number,\n y: number,\n transform: Matrix,\n primitives: Primitive[],\n ) => {\n setMousePos({ x, y })\n const rwPoint = applyToPoint(inverse(transform), { x, y })\n const newMousedPrimitives = getPrimitivesUnderPoint(\n primitives,\n rwPoint,\n transform,\n selectedLayer,\n )\n\n if (\n ifSetsMatchExactly(\n new Set(newMousedPrimitives.map((p) => p._pcb_drawing_object_id)),\n new Set(mousedPrimitives.map((p) => p._pcb_drawing_object_id)),\n )\n ) {\n return\n }\n\n setMousedPrimitives(newMousedPrimitives)\n onMouseHoverOverPrimitives(newMousedPrimitives)\n }\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n onMouseMove={(e) => {\n if (transform) {\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n handleInteraction(x, y, transform, primitives)\n }\n }}\n onTouchStart={(e) => {\n if (transform) {\n const touch = e.touches[0]\n const rect = e.currentTarget.getBoundingClientRect()\n const x = touch.clientX - rect.left\n const y = touch.clientY - rect.top\n handleInteraction(x, y, transform, primitives)\n }\n }}\n >\n {children}\n <ElementOverlayBox\n elements={elements}\n mousePos={mousePos}\n highlightedPrimitives={highlightedPrimitives}\n />\n {transform && (\n <>\n <BoardAnchorOffsetOverlay\n elements={elements}\n highlightedPrimitives={highlightedPrimitives}\n transform={transform}\n containerWidth={width}\n containerHeight={height}\n />\n <GroupAnchorOffsetOverlay\n elements={elements}\n highlightedPrimitives={highlightedPrimitives}\n transform={transform}\n containerWidth={width}\n containerHeight={height}\n />\n <ComponentBoundingBoxOverlay\n elements={elements}\n highlightedPrimitives={highlightedPrimitives}\n transform={transform}\n containerWidth={width}\n containerHeight={height}\n />\n <PanelAnchorOffsetOverlay\n elements={elements}\n highlightedPrimitives={highlightedPrimitives}\n transform={transform}\n containerWidth={width}\n containerHeight={height}\n />\n </>\n )}\n </div>\n )\n}\n\nexport type HighlightedPrimitive = {\n _pcb_drawing_object_id: string\n x: number\n y: number\n w: number\n h: number\n same_space_index?: number\n _element: AnyCircuitElement\n _parent_pcb_component?: AnyCircuitElement\n _parent_source_component?: AnyCircuitElement\n _source_port?: AnyCircuitElement\n screen_x: number\n screen_y: number\n screen_w: number\n screen_h: number\n}\n","export function ifSetsMatchExactly(set1: Set<any>, set2: Set<any>) {\n if (set1.size !== set2.size) return false\n return Array.from(set1).every((item) => set2.has(item))\n}\n","import type {\n AnyCircuitElement,\n PcbBoard,\n PcbComponent,\n PcbGroup,\n PcbPanel,\n} from \"circuit-json\"\n\nexport const isPcbComponent = (\n element?: AnyCircuitElement,\n): element is PcbComponent => element?.type === \"pcb_component\"\n\nexport const isPcbGroup = (element?: AnyCircuitElement): element is PcbGroup =>\n element?.type === \"pcb_group\"\n\nexport const isPcbPanel = (element?: AnyCircuitElement): element is PcbPanel =>\n element?.type === \"pcb_panel\"\n\nexport const isPcbBoard = (element?: AnyCircuitElement): element is PcbBoard =>\n element?.type === \"pcb_board\"\n\nexport type BoardAnchoredComponent = PcbComponent & {\n positioned_relative_to_pcb_board_id?: string\n}\n\nexport const isBoardAnchoredComponent = (\n component: PcbComponent,\n): component is BoardAnchoredComponent =>\n \"positioned_relative_to_pcb_board_id\" in component\n","import type { Point } from \"circuit-json\"\nimport type { CSSProperties } from \"react\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { zIndexMap } from \"../../lib/util/z-index-map\"\nimport { COLORS, VISUAL_CONFIG } from \"./common/constants\"\n\nexport interface AnchorOffsetTarget {\n id: string\n anchor: Point\n anchor_id: string\n target: Point\n type: \"component\" | \"group\" | \"board\"\n display_offset_x?: string\n display_offset_y?: string\n}\n\ninterface Props {\n targets: AnchorOffsetTarget[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\nexport const AnchorOffsetOverlay = ({\n targets,\n transform,\n containerWidth,\n containerHeight,\n}: Props) => {\n if (targets.length === 0) return null\n\n const labelStyle: CSSProperties = {\n color: COLORS.LABEL_TEXT,\n mixBlendMode: \"difference\",\n pointerEvents: \"none\",\n fontSize: VISUAL_CONFIG.LABEL_FONT_SIZE,\n fontFamily: \"monospace\",\n fontWeight: \"bold\",\n }\n\n const anchorScreens = new Map<string, Point>()\n targets.forEach((target) => {\n if (!anchorScreens.has(target.anchor_id)) {\n const screenPoint = applyToPoint(transform, target.anchor)\n anchorScreens.set(target.anchor_id, screenPoint)\n }\n })\n\n return (\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: containerWidth,\n height: containerHeight,\n overflow: \"hidden\",\n pointerEvents: \"none\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n }}\n width={containerWidth}\n height={containerHeight}\n >\n {targets.map((target) => {\n const anchorPosition = target.anchor\n const anchorKey = target.anchor_id\n\n const targetCenter = target.target\n\n const anchorMarkerScreen = anchorScreens.get(anchorKey)!\n const targetScreen = applyToPoint(transform, targetCenter)\n\n const offsetX = targetCenter.x - anchorPosition.x\n const offsetY = targetCenter.y - anchorPosition.y\n\n const xLineLength = Math.abs(targetScreen.x - anchorMarkerScreen.x)\n const yLineLength = Math.abs(targetScreen.y - anchorMarkerScreen.y)\n\n const isTargetAboveAnchor = targetScreen.y < anchorMarkerScreen.y\n const isTargetRightOfAnchor = targetScreen.x > anchorMarkerScreen.x\n\n const xLabelOffset = isTargetAboveAnchor\n ? VISUAL_CONFIG.LABEL_OFFSET_ABOVE\n : VISUAL_CONFIG.LABEL_OFFSET_BELOW\n\n const yLabelOffset = isTargetRightOfAnchor\n ? VISUAL_CONFIG.LABEL_OFFSET_RIGHT\n : VISUAL_CONFIG.LABEL_OFFSET_LEFT\n\n const shouldShowXLabel =\n xLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL\n const shouldShowYLabel =\n yLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL\n\n const xLabelText = `${\n target.display_offset_x ?? offsetX.toFixed(2)\n }mm`\n const yLabelText = `${\n target.display_offset_y ?? offsetY.toFixed(2)\n }mm`\n\n return (\n <g key={target.id}>\n <line\n x1={anchorMarkerScreen.x}\n y1={anchorMarkerScreen.y}\n x2={targetScreen.x}\n y2={anchorMarkerScreen.y}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.LINE_STROKE_WIDTH}\n strokeDasharray={VISUAL_CONFIG.LINE_DASH_PATTERN}\n />\n\n <line\n x1={targetScreen.x}\n y1={anchorMarkerScreen.y}\n x2={targetScreen.x}\n y2={targetScreen.y}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.LINE_STROKE_WIDTH}\n strokeDasharray={VISUAL_CONFIG.LINE_DASH_PATTERN}\n />\n\n {target.type === \"component\" || target.type === \"board\" ? (\n <circle\n cx={targetScreen.x}\n cy={targetScreen.y}\n r={VISUAL_CONFIG.COMPONENT_MARKER_RADIUS}\n fill={COLORS.COMPONENT_MARKER_FILL}\n stroke={COLORS.COMPONENT_MARKER_STROKE}\n strokeWidth={1}\n />\n ) : (\n // assumes \"group\"\n <>\n <line\n x1={targetScreen.x - VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n y1={targetScreen.y}\n x2={targetScreen.x + VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n y2={targetScreen.y}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH}\n />\n <line\n x1={targetScreen.x}\n y1={targetScreen.y - VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n x2={targetScreen.x}\n y2={targetScreen.y + VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH}\n />\n </>\n )}\n\n {shouldShowXLabel && (\n <foreignObject\n x={Math.min(anchorMarkerScreen.x, targetScreen.x)}\n y={anchorMarkerScreen.y + xLabelOffset}\n width={Math.abs(targetScreen.x - anchorMarkerScreen.x)}\n height={20}\n style={{ overflow: \"visible\" }}\n >\n <div style={{ ...labelStyle, textAlign: \"center\" }}>\n {xLabelText}\n </div>\n </foreignObject>\n )}\n\n {shouldShowYLabel && (\n <foreignObject\n x={targetScreen.x + yLabelOffset}\n y={Math.min(anchorMarkerScreen.y, targetScreen.y)}\n width={VISUAL_CONFIG.Y_LABEL_MIN_WIDTH}\n height={Math.abs(targetScreen.y - anchorMarkerScreen.y)}\n style={{ overflow: \"visible\" }}\n >\n <div\n style={{\n ...labelStyle,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: isTargetRightOfAnchor\n ? \"flex-start\"\n : \"flex-end\",\n whiteSpace: \"nowrap\",\n padding: \"0 4px\",\n height: \"100%\",\n }}\n >\n {yLabelText}\n </div>\n </foreignObject>\n )}\n </g>\n )\n })}\n\n {Array.from(anchorScreens.entries()).map(([anchorId, anchorScreen]) => (\n <g key={`anchor-${anchorId}`}>\n <line\n x1={anchorScreen.x - VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n y1={anchorScreen.y}\n x2={anchorScreen.x + VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n y2={anchorScreen.y}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH}\n />\n <line\n x1={anchorScreen.x}\n y1={anchorScreen.y - VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n x2={anchorScreen.x}\n y2={anchorScreen.y + VISUAL_CONFIG.ANCHOR_MARKER_SIZE}\n stroke={COLORS.OFFSET_LINE}\n strokeWidth={VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH}\n />\n </g>\n ))}\n </svg>\n </div>\n )\n}\n","export const VISUAL_CONFIG = {\n GROUP_PADDING: 1,\n MIN_LINE_LENGTH_FOR_LABEL: 40,\n LABEL_OFFSET_ABOVE: 2,\n LABEL_OFFSET_BELOW: -18,\n LABEL_OFFSET_RIGHT: 8,\n LABEL_OFFSET_LEFT: -120,\n Y_LABEL_MIN_WIDTH: 110,\n LINE_STROKE_WIDTH: 1.5,\n LINE_DASH_PATTERN: \"4,4\",\n COMPONENT_MARKER_RADIUS: 3,\n LABEL_FONT_SIZE: 11,\n ANCHOR_MARKER_SIZE: 6,\n ANCHOR_MARKER_STROKE_WIDTH: 1.5,\n} as const\n\nexport const COLORS = {\n OFFSET_LINE: \"white\",\n COMPONENT_MARKER_FILL: \"#66ccff\",\n COMPONENT_MARKER_STROKE: \"white\",\n LABEL_TEXT: \"white\",\n} as const\n","import type {\n AnyCircuitElement,\n PcbBoard,\n PcbComponent,\n PcbGroup,\n} from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../../global-store\"\nimport type { HighlightedPrimitive } from \"../MouseElementTracker\"\nimport { isPcbBoard, isPcbComponent, isPcbGroup } from \"./common/guards\"\nimport {\n type AnchorOffsetTarget,\n AnchorOffsetOverlay,\n} from \"./AnchorOffsetOverlay\"\n\ntype Point = {\n x: number\n y: number\n}\n\ninterface Props {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\nexport const BoardAnchorOffsetOverlay = ({\n elements,\n highlightedPrimitives,\n transform,\n containerWidth,\n containerHeight,\n}: Props) => {\n const boards = elements.filter((el): el is PcbBoard => isPcbBoard(el))\n const components = elements.filter((el): el is PcbComponent =>\n isPcbComponent(el),\n )\n const groups = elements.filter((el): el is PcbGroup => isPcbGroup(el))\n\n const hoveredComponentIds = highlightedPrimitives\n .map((primitive) => {\n if (isPcbComponent(primitive._parent_pcb_component)) {\n return primitive._parent_pcb_component.pcb_component_id\n }\n if (isPcbComponent(primitive._element)) {\n return primitive._element.pcb_component_id\n }\n return null\n })\n .filter((id): id is string => Boolean(id))\n\n // Track hovered groups by checking if any components in the group are hovered\n const hoveredGroupIds = new Set<string>()\n hoveredComponentIds.forEach((componentId) => {\n const component = components.find((c) => c.pcb_component_id === componentId)\n if (component?.pcb_group_id) {\n hoveredGroupIds.add(component.pcb_group_id)\n }\n })\n\n const isShowingAnchorOffsets = useGlobalStore(\n (state) => state.is_showing_group_anchor_offsets,\n )\n\n if (!isShowingAnchorOffsets && hoveredComponentIds.length === 0) {\n return null\n }\n\n // Component-to-board targets\n const componentTargets = components\n .map((component) => {\n const boardId = component.positioned_relative_to_pcb_board_id\n if (!boardId) return null\n\n const board = boards.find((b) => b.pcb_board_id === boardId)\n return board ? { component, board, type: \"component\" as const } : null\n })\n .filter(\n (\n target,\n ): target is {\n component: PcbComponent\n board: PcbBoard\n type: \"component\"\n } => Boolean(target),\n )\n\n // Group-to-board targets\n const groupTargets = groups\n .map((group) => {\n const boardId = group.positioned_relative_to_pcb_board_id\n if (!boardId || !group.center) return null\n\n const board = boards.find((b) => b.pcb_board_id === boardId)\n return board ? { group, board, type: \"group\" as const } : null\n })\n .filter(\n (target): target is { group: PcbGroup; board: PcbBoard; type: \"group\" } =>\n Boolean(target),\n )\n\n const targets = [...componentTargets, ...groupTargets]\n\n if (targets.length === 0) return null\n\n const shouldShowAllTargets = hoveredComponentIds.length === 0\n\n const targetEntries = targets.filter((target) => {\n if (target.type === \"component\") {\n return (\n shouldShowAllTargets ||\n hoveredComponentIds.includes(target.component.pcb_component_id)\n )\n } else {\n // For group targets, show if the group is hovered\n return (\n shouldShowAllTargets || hoveredGroupIds.has(target.group.pcb_group_id)\n )\n }\n })\n\n if (targetEntries.length === 0) return null\n\n const sharedTargets: AnchorOffsetTarget[] = targetEntries\n .map((target): AnchorOffsetTarget | null => {\n if (target.type === \"component\") {\n return {\n id: `${target.board.pcb_board_id}-${target.component.pcb_component_id}-${target.type}`,\n anchor: target.board.center,\n anchor_id: target.board.pcb_board_id,\n target: target.component.center as Point,\n type: \"component\",\n display_offset_x: target.component.display_offset_x,\n display_offset_y: target.component.display_offset_y,\n }\n }\n // group\n return {\n id: `${target.board.pcb_board_id}-${target.group.pcb_group_id}-${target.type}`,\n anchor: target.board.center,\n anchor_id: target.board.pcb_board_id,\n target: {\n x: target.group.anchor_position?.x ?? target.group.center.x,\n y: target.group.anchor_position?.y ?? target.group.center.y,\n },\n type: \"group\",\n display_offset_x: target.group.display_offset_x,\n display_offset_y: target.group.display_offset_y,\n }\n })\n .filter((t): t is AnchorOffsetTarget => Boolean(t))\n\n return (\n <AnchorOffsetOverlay\n targets={sharedTargets}\n transform={transform}\n containerWidth={containerWidth}\n containerHeight={containerHeight}\n />\n )\n}\n","import type { AnyCircuitElement, PcbComponent, PcbGroup } from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../../global-store\"\nimport type { HighlightedPrimitive } from \"../MouseElementTracker\"\nimport { isPcbComponent, isPcbGroup } from \"./common/guards\"\nimport {\n type AnchorOffsetTarget,\n AnchorOffsetOverlay,\n} from \"./AnchorOffsetOverlay\"\n\ntype Point = {\n x: number\n y: number\n}\n\ninterface Props {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\n/**\n * Overlay that shows offsets from group anchors to their components and groups.\n * When the view toggle is on, offsets are always shown. Hover narrows the\n * view to the hovered component/group only, but pads/components still always show.\n */\nexport const GroupAnchorOffsetOverlay = ({\n elements,\n highlightedPrimitives,\n transform,\n containerWidth,\n containerHeight,\n}: Props) => {\n const groups = elements.filter((el): el is PcbGroup => isPcbGroup(el))\n const components = elements.filter((el): el is PcbComponent =>\n isPcbComponent(el),\n )\n\n const hoveredComponentIds = highlightedPrimitives\n .map((primitive) => {\n if (isPcbComponent(primitive._parent_pcb_component)) {\n return primitive._parent_pcb_component.pcb_component_id\n }\n if (isPcbComponent(primitive._element)) {\n return primitive._element.pcb_component_id\n }\n return null\n })\n .filter((id): id is string => Boolean(id))\n\n // Helper function to traverse up the group hierarchy and collect all parent groups\n const collectParentGroups = (groupId: string, collected: Set<string>) => {\n if (collected.has(groupId)) return // Avoid infinite loops\n collected.add(groupId)\n\n const group = groups.find((g) => g.pcb_group_id === groupId)\n if (\n group?.position_mode === \"relative_to_group_anchor\" &&\n group.positioned_relative_to_pcb_group_id\n ) {\n // This group is positioned relative to another group, so add that parent too\n collectParentGroups(group.positioned_relative_to_pcb_group_id, collected)\n }\n }\n\n // Track hovered groups by checking if any components in the group are hovered\n // This includes traversing up the group hierarchy for nested groups\n const hoveredGroupIds = new Set<string>()\n hoveredComponentIds.forEach((componentId) => {\n const component = components.find((c) => c.pcb_component_id === componentId)\n if (!component) return\n\n // If component is directly positioned relative to a group anchor\n if (\n component.position_mode === \"relative_to_group_anchor\" &&\n component.positioned_relative_to_pcb_group_id\n ) {\n collectParentGroups(\n component.positioned_relative_to_pcb_group_id,\n hoveredGroupIds,\n )\n }\n\n // If component belongs to a group (via pcb_group_id)\n if (component.pcb_group_id) {\n collectParentGroups(component.pcb_group_id, hoveredGroupIds)\n }\n })\n\n const isShowingAnchorOffsets = useGlobalStore(\n (s) => s.is_showing_group_anchor_offsets,\n )\n\n if (!isShowingAnchorOffsets && hoveredComponentIds.length === 0) {\n return null\n }\n\n // Component-to-group targets\n const componentTargets = components\n .map((component) => {\n if (\n component.position_mode === \"relative_to_group_anchor\" &&\n component.positioned_relative_to_pcb_group_id\n ) {\n const parentGroup = groups.find(\n (group) =>\n group.pcb_group_id ===\n component.positioned_relative_to_pcb_group_id,\n )\n return parentGroup && parentGroup.anchor_position\n ? { component, parentGroup, type: \"component\" as const }\n : null\n }\n\n if (component.pcb_group_id) {\n const parentGroup = groups.find(\n (group) => group.pcb_group_id === component.pcb_group_id,\n )\n return parentGroup && parentGroup.anchor_position\n ? { component, parentGroup, type: \"component\" as const }\n : null\n }\n\n return null\n })\n .filter(\n (\n target,\n ): target is {\n component: PcbComponent\n parentGroup: PcbGroup\n type: \"component\"\n } => Boolean(target),\n )\n\n // Group-to-group targets (anchor-to-anchor offsets)\n const groupTargets = groups\n .map((group) => {\n if (\n group.position_mode === \"relative_to_group_anchor\" &&\n group.positioned_relative_to_pcb_group_id\n ) {\n const parentGroup = groups.find(\n (g) => g.pcb_group_id === group.positioned_relative_to_pcb_group_id,\n )\n if (\n parentGroup &&\n parentGroup.anchor_position &&\n group.anchor_position\n ) {\n return { group, parentGroup, type: \"group\" as const }\n }\n }\n return null\n })\n .filter(\n (\n target,\n ): target is {\n group: PcbGroup\n parentGroup: PcbGroup\n type: \"group\"\n } => Boolean(target),\n )\n\n const targets = [...componentTargets, ...groupTargets]\n\n if (targets.length === 0) return null\n\n const shouldShowAllTargets = hoveredComponentIds.length === 0\n\n const targetEntries = targets.filter((target) => {\n if (target.type === \"component\") {\n // Only show offset for the specific hovered component, not all components in the group\n return (\n shouldShowAllTargets ||\n hoveredComponentIds.includes(target.component.pcb_component_id)\n )\n } else {\n // For group targets, show if the group or parent group is hovered\n return (\n shouldShowAllTargets ||\n hoveredGroupIds.has(target.group.pcb_group_id) ||\n hoveredGroupIds.has(target.parentGroup.pcb_group_id)\n )\n }\n })\n\n if (targetEntries.length === 0) return null\n\n const sharedTargets: AnchorOffsetTarget[] = targetEntries\n .map((target): AnchorOffsetTarget | null => {\n const anchor = target.parentGroup.anchor_position\n if (!anchor) return null\n\n if (target.type === \"component\") {\n if (!target.component.center) return null\n return {\n id: `${target.parentGroup.pcb_group_id}-${target.component.pcb_component_id}-${target.type}`,\n anchor,\n anchor_id: target.parentGroup.pcb_group_id,\n target: target.component.center,\n type: \"component\",\n display_offset_x: target.component.display_offset_x,\n display_offset_y: target.component.display_offset_y,\n }\n }\n // group - use anchor_position for anchor-to-anchor offsets\n if (!target.group.anchor_position) return null\n return {\n id: `${target.parentGroup.pcb_group_id}-${target.group.pcb_group_id}-${target.type}`,\n anchor,\n anchor_id: target.parentGroup.pcb_group_id,\n target: target.group.anchor_position,\n type: \"group\",\n display_offset_x: target.group.display_offset_x,\n display_offset_y: target.group.display_offset_y,\n }\n })\n .filter((t): t is AnchorOffsetTarget => Boolean(t))\n\n return (\n <AnchorOffsetOverlay\n targets={sharedTargets}\n transform={transform}\n containerWidth={containerWidth}\n containerHeight={containerHeight}\n />\n )\n}\n","import type { AnyCircuitElement, PcbComponent, PcbGroup } from \"circuit-json\"\nimport { getBoundsOfPcbElements, su } from \"@tscircuit/circuit-json-util\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { zIndexMap } from \"../../lib/util/z-index-map\"\nimport type { HighlightedPrimitive } from \"../MouseElementTracker\"\nimport { COLORS, VISUAL_CONFIG } from \"./common/constants\"\nimport { isPcbComponent } from \"./common/guards\"\n\ninterface Props {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\nconst calculateComponentBoundingBox = (\n component: PcbComponent,\n elements: AnyCircuitElement[],\n): { minX: number; maxX: number; minY: number; maxY: number } | null => {\n const componentId = component.pcb_component_id\n const padsAndHoles = elements.filter(\n (el) =>\n ((el.type === \"pcb_smtpad\" || el.type === \"pcb_plated_hole\") &&\n el.pcb_component_id === componentId) ||\n (el.type === \"pcb_hole\" && (el as any).pcb_component_id === componentId),\n )\n\n if (padsAndHoles.length === 0) {\n return getBoundsOfPcbElements([component])\n }\n\n return getBoundsOfPcbElements(padsAndHoles)\n}\n\nexport const ComponentBoundingBoxOverlay = ({\n elements,\n highlightedPrimitives,\n transform,\n containerWidth,\n containerHeight,\n}: Props) => {\n const hoveredComponents = new Map<string, PcbComponent>()\n for (const primitive of highlightedPrimitives) {\n if (isPcbComponent(primitive._parent_pcb_component)) {\n hoveredComponents.set(\n primitive._parent_pcb_component.pcb_component_id,\n primitive._parent_pcb_component,\n )\n }\n if (isPcbComponent(primitive._element)) {\n hoveredComponents.set(\n primitive._element.pcb_component_id,\n primitive._element,\n )\n }\n }\n\n if (hoveredComponents.size === 0) return null\n\n const renderData: Array<{\n component: PcbComponent\n bbox: { minX: number; maxX: number; minY: number; maxY: number }\n group: PcbGroup | null\n }> = []\n\n for (const component of hoveredComponents.values()) {\n const bbox = calculateComponentBoundingBox(component, elements)\n if (!bbox) continue\n\n const groupId =\n component.positioned_relative_to_pcb_group_id ?? component.pcb_group_id\n const group = groupId\n ? (su(elements).pcb_group.get(groupId) as PcbGroup | null)\n : null\n\n renderData.push({ component, bbox, group })\n }\n\n if (renderData.length === 0) return null\n\n return (\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: containerWidth,\n height: containerHeight,\n overflow: \"hidden\",\n pointerEvents: \"none\",\n zIndex: zIndexMap.dimensionOverlay,\n }}\n >\n <svg\n style={{ position: \"absolute\", left: 0, top: 0, pointerEvents: \"none\" }}\n width={containerWidth}\n height={containerHeight}\n >\n {renderData.map(({ component, bbox, group }) => {\n const topLeft = applyToPoint(transform, {\n x: bbox.minX,\n y: bbox.maxY,\n })\n const bottomRight = applyToPoint(transform, {\n x: bbox.maxX,\n y: bbox.minY,\n })\n\n const screenBbox = {\n x: Math.min(topLeft.x, bottomRight.x),\n y: Math.min(topLeft.y, bottomRight.y),\n width: Math.abs(bottomRight.x - topLeft.x),\n height: Math.abs(bottomRight.y - topLeft.y),\n }\n\n const componentCenter = component.center ?? {\n x: (bbox.minX + bbox.maxX) / 2,\n y: (bbox.minY + bbox.maxY) / 2,\n }\n const componentCenterScreen = applyToPoint(transform, componentCenter)\n\n return (\n <g key={component.pcb_component_id}>\n <rect\n x={screenBbox.x}\n y={screenBbox.y}\n width={screenBbox.width}\n height={screenBbox.height}\n fill=\"none\"\n stroke=\"white\"\n strokeWidth={1.5}\n strokeDasharray=\"4,4\"\n />\n\n <line\n x1={componentCenterScreen.x - 6}\n y1={componentCenterScreen.y}\n x2={componentCenterScreen.x + 6}\n y2={componentCenterScreen.y}\n stroke={COLORS.COMPONENT_MARKER_STROKE}\n strokeWidth={1.5}\n />\n <line\n x1={componentCenterScreen.x}\n y1={componentCenterScreen.y - 6}\n x2={componentCenterScreen.x}\n y2={componentCenterScreen.y + 6}\n stroke={COLORS.COMPONENT_MARKER_STROKE}\n strokeWidth={1.5}\n />\n <circle\n cx={componentCenterScreen.x}\n cy={componentCenterScreen.y}\n r={VISUAL_CONFIG.COMPONENT_MARKER_RADIUS}\n fill={COLORS.COMPONENT_MARKER_FILL}\n stroke={COLORS.COMPONENT_MARKER_STROKE}\n strokeWidth={1}\n />\n </g>\n )\n })}\n </svg>\n </div>\n )\n}\n","import type { AnyCircuitElement, PcbPanel, PcbBoard, Point } from \"circuit-json\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../../global-store\"\nimport type { HighlightedPrimitive } from \"../MouseElementTracker\"\nimport { isPcbPanel, isPcbBoard } from \"./common/guards\"\nimport {\n type AnchorOffsetTarget,\n AnchorOffsetOverlay,\n} from \"./AnchorOffsetOverlay\"\n\ninterface PanelAnchorOffsetOverlayProps {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n transform: Matrix\n containerWidth: number\n containerHeight: number\n}\n\nexport const PanelAnchorOffsetOverlay = ({\n elements,\n highlightedPrimitives,\n transform,\n containerWidth,\n containerHeight,\n}: PanelAnchorOffsetOverlayProps) => {\n const panels = elements.filter((el): el is PcbPanel => isPcbPanel(el))\n const boards = elements.filter((el): el is PcbBoard => isPcbBoard(el))\n\n const hoveredBoardIds = highlightedPrimitives\n .map((primitive) => {\n if (isPcbBoard(primitive._element)) {\n return primitive._element.pcb_board_id\n }\n return null\n })\n .filter((id): id is string => Boolean(id))\n\n const isShowingAnchorOffsets = useGlobalStore(\n (state) => state.is_showing_group_anchor_offsets,\n )\n\n if (!isShowingAnchorOffsets && hoveredBoardIds.length === 0) {\n return null\n }\n\n // Board-to-panel targets\n const boardTargets = boards\n .map((board) => {\n const panelId = board.pcb_panel_id\n const positionMode = board.position_mode\n if (!panelId || positionMode !== \"relative_to_panel_anchor\") return null\n\n const panel = panels.find((p) => p.pcb_panel_id === panelId)\n return panel ? { board, panel, type: \"board\" as const } : null\n })\n .filter(\n (\n target,\n ): target is {\n board: PcbBoard\n panel: PcbPanel\n type: \"board\"\n } => Boolean(target),\n )\n\n if (boardTargets.length === 0) return null\n\n const shouldShowAllTargets = hoveredBoardIds.length === 0\n\n const targetEntries = boardTargets.filter((target) => {\n return (\n shouldShowAllTargets ||\n hoveredBoardIds.includes(target.board.pcb_board_id)\n )\n })\n\n if (targetEntries.length === 0) return null\n\n const sharedTargets: AnchorOffsetTarget[] = targetEntries\n .map((target): AnchorOffsetTarget | null => {\n if (!target.board.center) return null\n return {\n id: `${target.panel.pcb_panel_id}-${target.board.pcb_board_id}-${target.type}`,\n anchor: target.panel.center,\n anchor_id: target.panel.pcb_panel_id,\n target: target.board.center,\n type: \"board\",\n display_offset_x: target.board.display_offset_x,\n display_offset_y: target.board.display_offset_y,\n }\n })\n .filter((t): t is AnchorOffsetTarget => Boolean(t))\n\n return (\n <AnchorOffsetOverlay\n targets={sharedTargets}\n transform={transform}\n containerWidth={containerWidth}\n containerHeight={containerHeight}\n />\n )\n}\n","import { su } from \"@tscircuit/circuit-json-util\"\nimport type { AnyCircuitElement, PcbTrace } from \"circuit-json\"\n\ninterface TraceTextContext {\n primitiveElement: PcbTrace\n elements: AnyCircuitElement[]\n}\n\ninterface TraceOverlayInfo {\n text: string\n name: string | null\n isOverLength: boolean\n}\n\nconst getNonEmptyName = (name?: string) => name?.trim() || null\n\nexport function getAssociatedTraceName({\n primitiveElement,\n elements,\n}: TraceTextContext): string | null {\n const sourceElementId = primitiveElement.source_trace_id\n if (!sourceElementId) return null\n\n const circuitJson = su(elements)\n const sourceTrace = circuitJson.source_trace.get(sourceElementId)\n\n const sourceTraceName = getNonEmptyName(sourceTrace?.name)\n if (sourceTraceName) return sourceTraceName\n\n const sourceNet = circuitJson.source_net.get(sourceElementId)\n const sourceNetName = getNonEmptyName(sourceNet?.name)\n if (sourceNetName) return sourceNetName\n\n for (const sourceNetId of sourceTrace?.connected_source_net_ids ?? []) {\n const connectedSourceNetName = getNonEmptyName(\n circuitJson.source_net.get(sourceNetId)?.name,\n )\n if (connectedSourceNetName) return connectedSourceNetName\n }\n\n return null\n}\n\nexport function getTraceOverlayInfo({\n primitiveElement,\n elements,\n}: TraceTextContext): TraceOverlayInfo | null {\n const trace = su(elements).source_trace.get(\n primitiveElement?.source_trace_id!,\n )\n const traceLength = primitiveElement.trace_length\n const hasTraceLength = typeof traceLength === \"number\"\n const maxLength = trace?.max_length\n const text = hasTraceLength\n ? `${traceLength.toFixed(3)}${\n typeof maxLength === \"number\" ? ` / ${maxLength}` : \"\"\n } mm`\n : \"\"\n const name =\n getAssociatedTraceName({ primitiveElement, elements }) ??\n getNonEmptyName(trace?.display_name)\n\n if (!text && !name) return null\n\n const isOverLength = Boolean(\n hasTraceLength && typeof maxLength === \"number\" && traceLength > maxLength,\n )\n\n return {\n text,\n name,\n isOverLength,\n }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport type { HighlightedPrimitive } from \"../components/MouseElementTracker\"\nimport { getAssociatedTraceName } from \"./get-trace-overlay-text\"\n\nexport function filterTracesIfMultiple(filterTraces: {\n primitives: HighlightedPrimitive[]\n is_showing_multiple_traces_length: boolean\n elements: AnyCircuitElement[]\n}): HighlightedPrimitive[] {\n const { primitives, is_showing_multiple_traces_length, elements } =\n filterTraces\n\n // Filter traces to get only PCB traces\n const traces = primitives.filter(\n (\n p,\n ): p is HighlightedPrimitive & {\n _element: {\n type: \"pcb_trace\"\n trace_length?: number\n }\n } => p._element.type === \"pcb_trace\",\n )\n\n // Find all source traces\n const sourceTraces = elements.filter((e) => e.type === \"source_trace\")\n\n // Get non-trace primitives\n const nonTraces = primitives.filter((p) => p._element.type !== \"pcb_trace\")\n\n // Named traces and nets should always have a hover label, even when the\n // viewer is configured to hide ordinary trace-length overlays.\n const tracesWithPersistentOverlay = traces.filter((trace) => {\n const hasMaxLength = sourceTraces.some(\n (sourceTrace) =>\n trace._element.source_trace_id === sourceTrace.source_trace_id &&\n sourceTrace.max_length !== undefined,\n )\n\n return (\n hasMaxLength ||\n getAssociatedTraceName({\n primitiveElement: trace._element,\n elements,\n }) !== null\n )\n })\n\n // If not showing multiple trace lengths, keep only overlays that carry\n // important metadata (a configured max length or a source name).\n if (!is_showing_multiple_traces_length) {\n return [...nonTraces, ...tracesWithPersistentOverlay]\n }\n\n // If multiple traces exist, return only the shortest one\n if (traces.length > 1) {\n const shortestTrace = traces.reduce((shortest, current) => {\n const shortestLength = shortest._element.trace_length\n const currentLength = current._element.trace_length\n return currentLength! < shortestLength! ? current : shortest\n }, traces[0])\n\n return [...nonTraces, shortestTrace]\n }\n\n return primitives\n}\n","import type {\n AnyCircuitElement,\n PcbPlatedHoleOval,\n PcbSmtPadRotatedPill,\n} from \"circuit-json\"\nimport { filterTracesIfMultiple } from \"lib/filter-traces-if-multiple\"\nimport { getTraceOverlayInfo } from \"lib/get-trace-overlay-text\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport React, { useEffect, useState } from \"react\"\nimport { useGlobalStore } from \"../global-store\"\nimport type { HighlightedPrimitive } from \"./MouseElementTracker\"\n\nconst containerStyle = {\n position: \"absolute\",\n left: 0,\n top: 0,\n pointerEvents: \"none\",\n color: \"red\",\n fontFamily: \"sans-serif\",\n fontSize: 12,\n textShadow: \"0 0 2px black\",\n} as const\n\nexport const getTextForHighlightedPrimitive = (\n prim: HighlightedPrimitive,\n): string => {\n const {\n _element: element,\n _parent_pcb_component,\n _parent_source_component,\n _source_port,\n } = prim\n switch (element.type) {\n case \"pcb_trace\": {\n if (element.trace_length) {\n return `${element.trace_length.toFixed(3)}`\n }\n return \"\"\n }\n case \"pcb_smtpad\":\n case \"pcb_plated_hole\": {\n const selectors: string[] = []\n\n const port_hints = Array.from(\n new Set(\n (element.port_hints ?? []).concat(\n (_source_port as any)?.port_hints ?? [],\n ),\n ),\n )\n .filter((ph) => !/^[0-9]+$/.test(ph))\n .filter((ph) => !ph.includes(\"unnamed_\"))\n // reverse alphabetical order\n .sort((a, b) => b.localeCompare(a))\n\n const parentName =\n _parent_source_component &&\n \"name\" in _parent_source_component &&\n _parent_source_component.name &&\n !_parent_source_component.name.includes(\"unnamed_\")\n ? _parent_source_component.name\n : null\n\n if (port_hints.length > 0) {\n if (parentName) {\n selectors.push(\n ...port_hints.map((ph: string) => `${parentName}.${ph}`),\n )\n } else {\n selectors.push(...port_hints)\n }\n } else if (parentName) {\n selectors.push(parentName)\n }\n\n return selectors.join(\", \")\n }\n default: {\n return \"\"\n }\n }\n}\n\nconst layerColorHightlightMap = {\n top: \"red\",\n bottom: \"aqua\",\n}\n\nexport const HighlightedPrimitiveBoxWithText = ({\n primitive,\n mousePos,\n elements,\n}: {\n elements: AnyCircuitElement[]\n primitive: HighlightedPrimitive\n mousePos: { x: number; y: number }\n}) => {\n const [finalState, setFinalState] = useState(false)\n const primitiveElement = primitive._element\n\n useEffect(() => {\n setTimeout(() => {\n setFinalState(true)\n }, 100)\n }, [])\n\n const [x, y, w, h] = [\n primitive.screen_x,\n primitive.screen_y,\n primitive.screen_w,\n primitive.screen_h,\n ]\n\n const si = primitive.same_space_index ?? 0\n const sip = 26\n\n const color: string =\n layerColorHightlightMap[\n (primitive as any)?._element\n ?.layer as keyof typeof layerColorHightlightMap\n ] ?? \"red\"\n\n // Check for rotation on the parent PCB component\n let rotation = 0\n if (\n primitiveElement.type === \"pcb_smtpad\" &&\n primitiveElement?.shape === \"rotated_rect\"\n ) {\n rotation = primitiveElement?.ccw_rotation ?? 0\n } else if (\n primitiveElement.type === \"pcb_smtpad\" &&\n (primitiveElement?.shape === \"pill\" ||\n primitiveElement?.shape === \"rotated_pill\") &&\n \"ccw_rotation\" in primitive\n ) {\n rotation = (primitiveElement as PcbSmtPadRotatedPill).ccw_rotation ?? 0\n } else if (\n primitiveElement.type === \"pcb_plated_hole\" &&\n (primitiveElement?.shape === \"pill\" ||\n primitiveElement?.shape === \"oval\") &&\n \"ccw_rotation\" in primitive\n ) {\n rotation = (primitiveElement as PcbPlatedHoleOval).ccw_rotation ?? 0\n }\n // In HighlightedPrimitiveBoxWithText component\n if (primitiveElement.type === \"pcb_trace\") {\n const traceTextContext = { primitiveElement, elements }\n const overlayInfo = getTraceOverlayInfo(traceTextContext)\n if (!overlayInfo) return null\n\n return (\n <div\n style={{\n zIndex: zIndexMap.elementOverlay,\n position: \"absolute\",\n left: mousePos.x + 12,\n top: mousePos.y + 12,\n color,\n pointerEvents: \"none\",\n }}\n >\n <div\n style={{\n backgroundColor: \"#f2efcc\",\n color: overlayInfo.isOverLength ? \"red\" : \"black\",\n textShadow: \"none\",\n WebkitFontSmoothing: \"antialiased\",\n MozOsxFontSmoothing: \"grayscale\",\n padding: \"4px 6px\",\n borderRadius: \"4px\",\n fontSize: \"11px\",\n lineHeight: 1.2,\n textAlign: \"left\",\n whiteSpace: \"nowrap\",\n }}\n >\n {overlayInfo.text && <div>{overlayInfo.text}</div>}\n {overlayInfo.name && (\n <div\n style={{\n marginTop: overlayInfo.text ? \"2px\" : 0,\n }}\n >\n {overlayInfo.name}\n </div>\n )}\n </div>\n </div>\n )\n }\n\n const label = getTextForHighlightedPrimitive(primitive)\n if (label.trim().length === 0) {\n return null\n }\n\n return (\n <div\n style={{\n zIndex: zIndexMap.elementOverlay,\n position: \"absolute\",\n left: x - w / 2 - 8,\n top: y - h / 2 - 8,\n width: w + 16,\n height: h + 16,\n color,\n transform: `rotate(${-rotation}deg)`,\n transformOrigin: \"center center\",\n }}\n >\n <div\n style={{\n // width: finalState ? `${100 + 20 * si}%` : \"100%\",\n // height: finalState ? `${100 + 20 * si}%` : \"100%\",\n // marginLeft: finalState ? `${-10 * si}%` : 0,\n // marginTop: finalState ? `${-10 * si}%` : 0,\n width: finalState ? `calc(100% + ${sip * 2 * si}px)` : \"100%\",\n height: finalState ? `calc(100% + ${sip * 2 * si}px)` : \"100%\",\n marginLeft: finalState ? `${-sip * si}px` : 0,\n marginTop: finalState ? `${-sip * si}px` : 0,\n border: `1px solid ${color}`,\n opacity: finalState ? 1 : si === 0 ? 1 : 0,\n transition:\n \"width 0.2s, height 0.2s, margin-left 0.2s, margin-top 0.2s, opacity 0.2s\",\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: h + 20 + sip * si,\n marginRight: finalState ? `${-sip * si}px` : 0,\n marginBottom: finalState ? 0 : -sip * si,\n transition: \"margin-right 0.2s, margin-bottom 0.2s\",\n backgroundColor: \"#f2efcc\",\n color: \"black\",\n textShadow: \"none\",\n WebkitFontSmoothing: \"antialiased\",\n MozOsxFontSmoothing: \"grayscale\",\n padding: \"6px 6px\",\n borderRadius: \"6px\",\n fontSize: \"14px\",\n transform: `rotate(${rotation}deg)`,\n minWidth: \"45px\",\n textAlign: \"center\",\n }}\n >\n {label}\n </div>\n </div>\n </div>\n )\n}\n\nexport const ElementOverlayBox = ({\n highlightedPrimitives,\n mousePos,\n elements,\n}: {\n elements: AnyCircuitElement[]\n highlightedPrimitives: HighlightedPrimitive[]\n mousePos: { x: number; y: number }\n}) => {\n const [is_moving_component, is_showing_multiple_traces_length] =\n useGlobalStore((s) => [\n s.is_moving_component,\n s.is_showing_multiple_traces_length,\n ])\n const hasSmtPadAndTrace =\n highlightedPrimitives.some((p) => p._element.type === \"pcb_smtpad\") &&\n highlightedPrimitives.some((p) => p._element.type === \"pcb_trace\")\n\n let primitives = highlightedPrimitives\n // If both smtpad and trace are present, only return smtpads\n if (hasSmtPadAndTrace) {\n primitives = primitives.filter((p) => p._element.type === \"pcb_smtpad\")\n }\n // When having multiple traces filter traces to get only the shortest one\n primitives = filterTracesIfMultiple({\n primitives,\n is_showing_multiple_traces_length,\n elements,\n })\n\n return (\n <div style={containerStyle}>\n {!is_moving_component &&\n primitives.map((primitive) => (\n <HighlightedPrimitiveBoxWithText\n key={primitive._pcb_drawing_object_id}\n primitive={primitive}\n mousePos={mousePos}\n elements={elements}\n />\n ))}\n </div>\n )\n}\n","import type {\n AnyCircuitElement,\n PcbComponent,\n PcbGroup,\n SourceGroup,\n} from \"circuit-json\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { Matrix } from \"transformation-matrix\"\nimport { identity } from \"transformation-matrix\"\nimport { useGlobalStore } from \"../global-store\"\nimport { useRef, useEffect } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport { zIndexMap } from \"../lib/util/z-index-map\"\n\ninterface Props {\n transform?: Matrix\n elements: AnyCircuitElement[]\n children: any\n hoveredComponentIds?: string[]\n}\n\nconst GROUP_COLORS = [\n \"rgb(255, 100, 100)\",\n \"rgb(100, 255, 100)\",\n \"rgb(100, 100, 255)\",\n \"rgb(255, 255, 100)\",\n \"rgb(255, 100, 255)\",\n \"rgb(100, 255, 255)\",\n \"rgb(255, 150, 100)\",\n \"rgb(150, 100, 255)\",\n \"rgb(100, 255, 150)\",\n \"rgb(255, 100, 150)\",\n]\n\nexport const PcbGroupOverlay = ({\n children,\n transform = identity(),\n elements = [],\n hoveredComponentIds = [],\n}: Props) => {\n const [containerRef, { width, height }] = useMeasure<HTMLDivElement>()\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const {\n is_showing_pcb_groups,\n pcb_group_view_mode,\n is_showing_group_anchor_offsets,\n } = useGlobalStore((s) => ({\n is_showing_pcb_groups: s.is_showing_pcb_groups,\n pcb_group_view_mode: s.pcb_group_view_mode,\n is_showing_group_anchor_offsets: s.is_showing_group_anchor_offsets,\n }))\n\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas || !width || !height) return\n\n canvas.width = width\n canvas.height = height\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n\n ctx.clearRect(0, 0, width, height)\n\n if (!is_showing_pcb_groups) return\n\n const pcbGroups = elements.filter(\n (el): el is PcbGroup => el.type === \"pcb_group\",\n ) as PcbGroup[]\n\n const pcbComponents = elements.filter(\n (el): el is PcbComponent => el.type === \"pcb_component\",\n ) as PcbComponent[]\n\n const sourceGroups = elements.filter(\n (el): el is SourceGroup => el.type === \"source_group\",\n ) as SourceGroup[]\n\n const sourceGroupById = new Map(\n sourceGroups.map((group) => [group.source_group_id, group]),\n )\n\n const visiblePcbGroups = pcbGroups.filter((group) => {\n if (group.name?.toLowerCase().includes(\"subpanel\")) {\n return false\n }\n\n if (pcb_group_view_mode === \"all\") return true\n if (!group.source_group_id) return false\n const sourceGroup = sourceGroupById.get(group.source_group_id)\n if (!sourceGroup) return false\n return sourceGroup.was_automatically_named !== true\n })\n\n const sourceGroupHierarchy = new Map<string, string[]>()\n sourceGroups.forEach((group) => {\n const groupWithParent = group as any\n if (groupWithParent.parent_source_group_id) {\n const children =\n sourceGroupHierarchy.get(groupWithParent.parent_source_group_id) || []\n children.push(group.source_group_id)\n sourceGroupHierarchy.set(\n groupWithParent.parent_source_group_id,\n children,\n )\n }\n })\n\n const getAllDescendantSourceGroups = (sourceGroupId: string): string[] => {\n const descendants: string[] = []\n const children = sourceGroupHierarchy.get(sourceGroupId) || []\n\n for (const child of children) {\n descendants.push(child)\n descendants.push(...getAllDescendantSourceGroups(child))\n }\n\n return descendants\n }\n\n const getGroupDepthLevel = (sourceGroupId: string): number => {\n const groupWithParent = sourceGroups.find(\n (g) => g.source_group_id === sourceGroupId,\n ) as any\n if (!groupWithParent?.parent_source_group_id) {\n return 0\n }\n return 1 + getGroupDepthLevel(groupWithParent.parent_source_group_id)\n }\n\n const hoveredGroupIds = new Set<string>()\n if (hoveredComponentIds.length > 0) {\n for (const comp of pcbComponents) {\n if (!hoveredComponentIds.includes(comp.pcb_component_id)) continue\n const targetGroupId =\n comp.positioned_relative_to_pcb_group_id ?? comp.pcb_group_id\n if (targetGroupId) hoveredGroupIds.add(targetGroupId)\n }\n }\n\n visiblePcbGroups.forEach((group, groupIndex) => {\n let groupComponents = pcbComponents.filter(\n (comp) => comp.pcb_group_id === group.pcb_group_id,\n )\n\n if (group.source_group_id) {\n const descendantSourceGroups = getAllDescendantSourceGroups(\n group.source_group_id,\n )\n\n const childPcbGroups = pcbGroups.filter(\n (pcbGroup) =>\n pcbGroup.source_group_id &&\n descendantSourceGroups.includes(pcbGroup.source_group_id),\n )\n\n for (const childPcbGroup of childPcbGroups) {\n const childComponents = pcbComponents.filter(\n (comp) => comp.pcb_group_id === childPcbGroup.pcb_group_id,\n )\n groupComponents = [...groupComponents, ...childComponents]\n }\n }\n\n let minX: number, minY: number, maxX: number, maxY: number\n let isExplicitlySized = false\n\n if (group.center && group.width && group.height) {\n isExplicitlySized = true\n const halfWidth = group.width / 2\n const halfHeight = group.height / 2\n minX = group.center.x - halfWidth\n maxX = group.center.x + halfWidth\n minY = group.center.y - halfHeight\n maxY = group.center.y + halfHeight\n } else {\n if (groupComponents.length === 0) return\n\n minX = Infinity\n minY = Infinity\n maxX = -Infinity\n maxY = -Infinity\n\n groupComponents.forEach((comp) => {\n if (\n comp.center &&\n typeof comp.width === \"number\" &&\n typeof comp.height === \"number\"\n ) {\n const left = comp.center.x - comp.width / 2\n const right = comp.center.x + comp.width / 2\n const top = comp.center.y + comp.height / 2\n const bottom = comp.center.y - comp.height / 2\n\n minX = Math.min(minX, left)\n maxX = Math.max(maxX, right)\n minY = Math.min(minY, bottom)\n maxY = Math.max(maxY, top)\n }\n })\n\n if (minX === Infinity || maxX === -Infinity) return\n }\n\n const depthLevel = group.source_group_id\n ? getGroupDepthLevel(group.source_group_id)\n : 0\n const hasChildren = group.source_group_id\n ? getAllDescendantSourceGroups(group.source_group_id).length > 0\n : false\n\n if (!isExplicitlySized) {\n const basePadding = 1\n const hierarchyPadding = hasChildren ? 0.5 : 0\n const totalPadding = basePadding + hierarchyPadding\n\n minX -= totalPadding\n maxX += totalPadding\n minY -= totalPadding\n maxY += totalPadding\n }\n\n const topLeft = applyToPoint(transform, { x: minX, y: maxY })\n const topRight = applyToPoint(transform, { x: maxX, y: maxY })\n const bottomLeft = applyToPoint(transform, { x: minX, y: minY })\n const bottomRight = applyToPoint(transform, { x: maxX, y: minY })\n\n const groupColor = GROUP_COLORS[groupIndex % GROUP_COLORS.length]\n ctx.strokeStyle = groupColor\n\n ctx.lineWidth = 2\n\n const baseDashSize = Math.max(4, Math.min(12, 8 * Math.abs(transform.a)))\n const baseGapSize = Math.max(2, Math.min(6, 4 * Math.abs(transform.a)))\n const dashMultiplier = hasChildren ? 1.3 : 1\n const dashSize = baseDashSize * dashMultiplier\n const gapSize = baseGapSize\n ctx.setLineDash([dashSize, gapSize])\n\n ctx.beginPath()\n ctx.moveTo(topLeft.x, topLeft.y)\n ctx.lineTo(topRight.x, topRight.y)\n ctx.lineTo(bottomRight.x, bottomRight.y)\n ctx.lineTo(bottomLeft.x, bottomLeft.y)\n ctx.closePath()\n ctx.stroke()\n\n const baseFontSize = Math.max(8, Math.min(12, 10 * Math.abs(transform.a)))\n const fontSizeReduction =\n depthLevel == 0 || depthLevel == 1 ? 0 : depthLevel * 0.11\n const fontSize = baseFontSize * (1 - fontSizeReduction)\n const labelPadding = 4\n\n const labelText = group.name || `Group ${groupIndex + 1}`\n\n ctx.font = `${fontSize}px sans-serif`\n ctx.setLineDash([])\n\n const labelMetrics = ctx.measureText(labelText)\n const labelWidth = labelMetrics.width + labelPadding * 2\n const labelHeight = fontSize + labelPadding * 2\n\n const labelX = topLeft.x - 5\n const labelY = topLeft.y - 5\n\n const borderRadius = 3\n ctx.fillStyle = \"rgba(0, 0, 0, 0.8)\"\n ctx.beginPath()\n ctx.roundRect(\n labelX,\n labelY - labelHeight,\n labelWidth,\n labelHeight,\n borderRadius,\n )\n ctx.fill()\n\n ctx.fillStyle = groupColor\n ctx.textAlign = \"left\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(labelText, labelX + labelPadding, labelY - labelHeight / 2)\n\n const shouldShowAnchorMarker =\n is_showing_group_anchor_offsets &&\n hoveredGroupIds.has(group.pcb_group_id) &&\n Boolean(group.anchor_position)\n\n if (shouldShowAnchorMarker && group.anchor_position) {\n const anchorPositionValue = Array.isArray(group.anchor_position)\n ? {\n x: group.anchor_position[0] ?? 0,\n y: group.anchor_position[1] ?? 0,\n }\n : { x: group.anchor_position.x, y: group.anchor_position.y }\n const anchorScreenPos = applyToPoint(transform, anchorPositionValue)\n\n // Draw a simple \"+\" symbol\n ctx.strokeStyle = \"white\"\n ctx.lineWidth = 1.5\n ctx.setLineDash([])\n\n const plusSize = Math.max(4, Math.min(8, 6 * Math.abs(transform.a)))\n\n // Draw horizontal line of \"+\"\n ctx.beginPath()\n ctx.moveTo(anchorScreenPos.x - plusSize, anchorScreenPos.y)\n ctx.lineTo(anchorScreenPos.x + plusSize, anchorScreenPos.y)\n ctx.stroke()\n\n // Draw vertical line of \"+\"\n ctx.beginPath()\n ctx.moveTo(anchorScreenPos.x, anchorScreenPos.y - plusSize)\n ctx.lineTo(anchorScreenPos.x, anchorScreenPos.y + plusSize)\n ctx.stroke()\n }\n })\n }, [\n elements,\n transform,\n width,\n height,\n is_showing_pcb_groups,\n pcb_group_view_mode,\n is_showing_group_anchor_offsets,\n hoveredComponentIds,\n ])\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n >\n {children}\n <canvas\n ref={canvasRef}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n pointerEvents: \"none\",\n zIndex: zIndexMap.pcbGroupOverlay,\n display: is_showing_pcb_groups ? \"block\" : \"none\",\n }}\n />\n </div>\n )\n}\n","import { type Matrix, applyToPoint, identity } from \"transformation-matrix\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport { su } from \"@tscircuit/circuit-json-util\"\nimport { useGlobalStore } from \"../global-store\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { getFullConnectivityMapFromCircuitJson } from \"circuit-json-to-connectivity-map\"\nimport { useMemo } from \"react\"\n\ninterface Props {\n transform?: Matrix\n soup?: AnyCircuitElement[]\n children: any\n}\n\ntype Point = { x: number; y: number }\ntype RatsNestLine = {\n key: string\n startPoint: Point\n endPoint: Point\n isInNet: boolean\n}\n\nexport const RatsNestOverlay = ({ transform, soup, children }: Props) => {\n const isShowingRatsNest = useGlobalStore((s) => s.is_showing_rats_nest)\n\n const { netMap, idToNetMap } = useMemo(\n () => getFullConnectivityMapFromCircuitJson(soup || []),\n [soup],\n )\n\n const ratsNestLines = useMemo(() => {\n if (!soup || !isShowingRatsNest) return []\n\n const getElementPosition = (id: string): Point | null => {\n // @ts-ignore\n const element = su(soup)[id.replace(/_\\d+$/, \"\")].get(id)\n if (element && \"x\" in element && \"y\" in element) {\n return { x: element.x, y: element.y }\n }\n return null\n }\n\n const findNearestPointInNet = (\n sourcePoint: Point,\n netId: string,\n ): Point | null => {\n const connectedIds = netMap[netId] || []\n let nearestPoint: Point | null = null\n let minDistance = Infinity\n\n connectedIds.forEach((id) => {\n const pos = getElementPosition(id)\n if (pos) {\n const distance = Math.sqrt(\n (sourcePoint.x - pos.x) ** 2 + (sourcePoint.y - pos.y) ** 2,\n )\n if (distance < minDistance && distance > 0) {\n minDistance = distance\n nearestPoint = pos\n }\n }\n })\n\n return nearestPoint\n }\n\n const pcbPorts = su(soup).pcb_port.list()\n const sourceTraces = su(soup).source_trace.list()\n const lines: RatsNestLine[] = []\n\n pcbPorts.forEach((port, index) => {\n const netId = idToNetMap[port.pcb_port_id]\n\n let isInNet = false\n\n for (const trace of sourceTraces) {\n const sourceTrace = trace.connected_source_port_ids.includes(\n port.source_port_id,\n )\n if (sourceTrace && trace.connected_source_net_ids.length > 0) {\n isInNet = true\n }\n }\n\n if (!netId) return\n\n const startPoint = { x: port.x, y: port.y }\n const nearestPoint = findNearestPointInNet(startPoint, netId)\n\n if (!nearestPoint) return\n\n lines.push({\n key: `${port.pcb_port_id}-${index}`,\n startPoint,\n endPoint: nearestPoint,\n isInNet,\n })\n })\n\n return lines\n }, [soup, netMap, idToNetMap, isShowingRatsNest])\n\n if (!soup || !isShowingRatsNest) return children\n if (!transform) transform = identity()\n\n return (\n <div style={{ position: \"relative\" }}>\n {children}\n <svg\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n opacity: 0.5,\n zIndex: zIndexMap.ratsNestOverlay,\n }}\n >\n {ratsNestLines.map(({ key, startPoint, endPoint, isInNet }) => {\n const transformedStart = applyToPoint(transform, startPoint)\n const transformedEnd = applyToPoint(transform, endPoint)\n\n return (\n <line\n key={key}\n x1={transformedStart.x}\n y1={transformedStart.y}\n x2={transformedEnd.x}\n y2={transformedEnd.y}\n stroke=\"white\"\n strokeWidth=\"1\"\n strokeDasharray={isInNet ? \"6,6\" : undefined}\n />\n )\n })}\n </svg>\n </div>\n )\n}\n","import {\n useEffect,\n useState,\n useCallback,\n useRef,\n useLayoutEffect,\n} from \"react\"\nimport { css } from \"@emotion/css\"\nimport { type LayerRef } from \"circuit-json\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport { getCopperLayerRefsFromElements } from \"lib/copper-layers\"\nimport { LAYER_NAME_TO_COLOR } from \"lib/Drawer\"\nimport { useGlobalStore } from \"../global-store\"\nimport packageJson from \"../../package.json\"\nimport { useHotKey } from \"hooks/useHotKey\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { useIsSmallScreen } from \"hooks/useIsSmallScreen\"\nimport { useMobileTouch } from \"hooks/useMobileTouch\"\nimport { ToolbarButton } from \"./ToolbarButton\"\nimport { ToolbarErrorDropdown } from \"./ToolbarErrorDropdown\"\n\ninterface Props {\n children?: React.ReactNode\n elements?: AnyCircuitElement[]\n}\n\ninterface LayerButtonProps {\n name: string\n selected?: boolean\n onClick: (\n e: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>,\n ) => void\n}\n\ninterface CheckboxMenuItemProps {\n label: string\n checked: boolean\n onClick: () => void\n}\n\ninterface RadioMenuItemProps {\n label: string\n checked: boolean\n onClick: () => void\n}\n\nexport const LayerButton = ({ name, selected, onClick }: LayerButtonProps) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick)\n return (\n <div\n className={css`\n margin-top: 2px;\n padding: 4px;\n padding-left: 8px;\n padding-right: 18px;\n cursor: pointer;\n\n &:hover {\n background-color: rgba(255, 255, 255, 0.1);\n }\n `}\n {...touchHandlers}\n style={touchStyle}\n >\n <span style={{ marginRight: 2, opacity: selected ? 1 : 0 }}>•</span>\n <span\n style={{\n marginLeft: 2,\n fontWeight: 500,\n color: (LAYER_NAME_TO_COLOR as any)[name.replace(/-/, \"\")],\n }}\n >\n {name}\n </span>\n </div>\n )\n}\n\nconst CheckboxMenuItem = ({\n label,\n checked,\n onClick,\n}: CheckboxMenuItemProps) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick)\n return (\n <div\n className={css`\n margin-top: 2px;\n padding: 4px;\n padding-left: 8px;\n padding-right: 18px;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n\n &:hover {\n background-color: rgba(255, 255, 255, 0.1);\n }\n `}\n {...touchHandlers}\n style={touchStyle}\n >\n <input type=\"checkbox\" checked={checked} onChange={() => {}} readOnly />\n <span style={{ color: \"#eee\" }}>{label}</span>\n </div>\n )\n}\n\nconst RadioMenuItem = ({ label, checked, onClick }: RadioMenuItemProps) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick)\n return (\n <div\n className={css`\n margin-top: 2px;\n padding: 4px;\n padding-left: 8px;\n padding-right: 18px;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n\n &:hover {\n background-color: rgba(255, 255, 255, 0.1);\n }\n `}\n {...touchHandlers}\n style={touchStyle}\n >\n <input type=\"radio\" checked={checked} onChange={() => {}} readOnly />\n <span style={{ color: \"#eee\" }}>{label}</span>\n </div>\n )\n}\n\nexport const ToolbarOverlay = ({ children, elements }: Props) => {\n const isSmallScreen = useIsSmallScreen()\n\n const {\n isMouseOverContainer,\n setIsMouseOverContainer,\n selectedLayer,\n selectLayer,\n viewSettings,\n setIsShowingRatsNest,\n setIsShowingMultipleTracesLength,\n setIsShowingAutorouting,\n setIsShowingDrcErrors,\n setIsShowingDrcWarnings,\n setIsShowingCopperPours,\n setIsShowingCourtyards,\n setIsShowingPcbGroups,\n setIsShowingGroupAnchorOffsets,\n setIsShowingSolderMask,\n setIsShowingSilkscreen,\n setIsShowingFabricationNotes,\n setIsShowingPcbNotes,\n setPcbGroupViewMode,\n setHoveredErrorId,\n setFocusedErrorId,\n } = useGlobalStore((s) => ({\n isMouseOverContainer: s.is_mouse_over_container,\n setIsMouseOverContainer: s.setIsMouseOverContainer,\n selectedLayer: s.selected_layer,\n selectLayer: s.selectLayer,\n viewSettings: {\n is_showing_rats_nest: s.is_showing_rats_nest,\n is_showing_multiple_traces_length: s.is_showing_multiple_traces_length,\n is_showing_autorouting: s.is_showing_autorouting,\n is_showing_drc_errors: s.is_showing_drc_errors,\n is_showing_drc_warnings: s.is_showing_drc_warnings,\n is_showing_copper_pours: s.is_showing_copper_pours,\n is_showing_courtyards: s.is_showing_courtyards,\n is_showing_pcb_groups: s.is_showing_pcb_groups,\n is_showing_group_anchor_offsets: s.is_showing_group_anchor_offsets,\n is_showing_solder_mask: s.is_showing_solder_mask,\n is_showing_silkscreen: s.is_showing_silkscreen,\n is_showing_fabrication_notes: s.is_showing_fabrication_notes,\n is_showing_pcb_notes: s.is_showing_pcb_notes,\n pcb_group_view_mode: s.pcb_group_view_mode,\n },\n setIsShowingRatsNest: s.setIsShowingRatsNest,\n setIsShowingMultipleTracesLength: s.setIsShowingMultipleTracesLength,\n setIsShowingAutorouting: s.setIsShowingAutorouting,\n setIsShowingDrcErrors: s.setIsShowingDrcErrors,\n setIsShowingDrcWarnings: s.setIsShowingDrcWarnings,\n setIsShowingCopperPours: s.setIsShowingCopperPours,\n setIsShowingCourtyards: s.setIsShowingCourtyards,\n setIsShowingPcbGroups: s.setIsShowingPcbGroups,\n setIsShowingGroupAnchorOffsets: s.setIsShowingGroupAnchorOffsets,\n setIsShowingSolderMask: s.setIsShowingSolderMask,\n setIsShowingSilkscreen: s.setIsShowingSilkscreen,\n setIsShowingFabricationNotes: s.setIsShowingFabricationNotes,\n setIsShowingPcbNotes: s.setIsShowingPcbNotes,\n setPcbGroupViewMode: s.setPcbGroupViewMode,\n setHoveredErrorId: s.setHoveredErrorId,\n setFocusedErrorId: s.setFocusedErrorId,\n }))\n\n const [isViewMenuOpen, setViewMenuOpen] = useState(false)\n const [isLayerMenuOpen, setLayerMenuOpen] = useState(false)\n const [isErrorsOpen, setErrorsOpen] = useState(false)\n const [measureToolArmed, setMeasureToolArmed] = useState(false)\n const [boundsToolArmed, setBoundsToolArmed] = useState(false)\n\n useEffect(() => {\n const arm = () => setMeasureToolArmed(true)\n const disarm = () => setMeasureToolArmed(false)\n const armBounds = () => setBoundsToolArmed(true)\n const disarmBounds = () => setBoundsToolArmed(false)\n window.addEventListener(\"arm-dimension-tool\", arm)\n window.addEventListener(\"disarm-dimension-tool\", disarm)\n window.addEventListener(\"arm-bounds-tool\", armBounds)\n window.addEventListener(\"disarm-bounds-tool\", disarmBounds)\n return () => {\n window.removeEventListener(\"arm-dimension-tool\", arm)\n window.removeEventListener(\"disarm-dimension-tool\", disarm)\n window.removeEventListener(\"arm-bounds-tool\", armBounds)\n window.removeEventListener(\"disarm-bounds-tool\", disarmBounds)\n }\n }, [])\n\n const availableLayers = getCopperLayerRefsFromElements(elements ?? [])\n\n const processedLayers = availableLayers\n\n const hasRunInitialMouseCheck = useRef(false)\n const hotkeyBoundaryRef = useRef<HTMLDivElement>(null)\n\n const hotKeyCallbacks = {\n \"1\": availableLayers[0]\n ? () => selectLayer(availableLayers[0] as LayerRef)\n : () => {},\n \"2\": availableLayers[1]\n ? () => selectLayer(availableLayers[1] as LayerRef)\n : () => {},\n \"3\": availableLayers[2]\n ? () => selectLayer(availableLayers[2] as LayerRef)\n : () => {},\n \"4\": availableLayers[3]\n ? () => selectLayer(availableLayers[3] as LayerRef)\n : () => {},\n \"5\": availableLayers[4]\n ? () => selectLayer(availableLayers[4] as LayerRef)\n : () => {},\n \"6\": availableLayers[5]\n ? () => selectLayer(availableLayers[5] as LayerRef)\n : () => {},\n \"7\": availableLayers[6]\n ? () => selectLayer(availableLayers[6] as LayerRef)\n : () => {},\n \"8\": availableLayers[7]\n ? () => selectLayer(availableLayers[7] as LayerRef)\n : () => {},\n \"9\": availableLayers[8]\n ? () => selectLayer(availableLayers[8] as LayerRef)\n : () => {},\n \"0\": availableLayers[9]\n ? () => selectLayer(availableLayers[9] as LayerRef)\n : () => {},\n }\n\n useHotKey(\"1\", hotKeyCallbacks[\"1\"], hotkeyBoundaryRef)\n useHotKey(\"2\", hotKeyCallbacks[\"2\"], hotkeyBoundaryRef)\n useHotKey(\"3\", hotKeyCallbacks[\"3\"], hotkeyBoundaryRef)\n useHotKey(\"4\", hotKeyCallbacks[\"4\"], hotkeyBoundaryRef)\n useHotKey(\"5\", hotKeyCallbacks[\"5\"], hotkeyBoundaryRef)\n useHotKey(\"6\", hotKeyCallbacks[\"6\"], hotkeyBoundaryRef)\n useHotKey(\"7\", hotKeyCallbacks[\"7\"], hotkeyBoundaryRef)\n useHotKey(\"8\", hotKeyCallbacks[\"8\"], hotkeyBoundaryRef)\n useHotKey(\"9\", hotKeyCallbacks[\"9\"], hotkeyBoundaryRef)\n useHotKey(\"0\", hotKeyCallbacks[\"0\"], hotkeyBoundaryRef)\n\n useLayoutEffect(() => {\n if (hasRunInitialMouseCheck.current) return\n hasRunInitialMouseCheck.current = true\n\n const checkMousePosition = (e: MouseEvent) => {\n if (hotkeyBoundaryRef.current) {\n const rect = hotkeyBoundaryRef.current.getBoundingClientRect()\n const isInside =\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom\n\n if (isInside) {\n setIsMouseOverContainer(true)\n }\n }\n document.removeEventListener(\"mousemove\", checkMousePosition)\n }\n\n document.addEventListener(\"mousemove\", checkMousePosition)\n return () => {\n document.removeEventListener(\"mousemove\", checkMousePosition)\n }\n }, [setIsMouseOverContainer])\n\n const handleMouseEnter = useCallback(() => {\n setIsMouseOverContainer(true)\n }, [setIsMouseOverContainer])\n\n const handleMouseMove = useCallback(() => {\n if (!isMouseOverContainer) {\n setIsMouseOverContainer(true)\n }\n }, [isMouseOverContainer, setIsMouseOverContainer])\n\n const handleMouseLeave = useCallback(() => {\n setIsMouseOverContainer(false)\n setLayerMenuOpen(false)\n setViewMenuOpen(false)\n setErrorsOpen(false)\n }, [setIsMouseOverContainer])\n\n const handleLayerMenuToggle = useCallback(() => {\n setLayerMenuOpen(!isLayerMenuOpen)\n }, [isLayerMenuOpen])\n\n const handleErrorsToggle = useCallback(() => {\n const newErrorsOpen = !isErrorsOpen\n setErrorsOpen(newErrorsOpen)\n if (newErrorsOpen) {\n setViewMenuOpen(false)\n }\n if (!newErrorsOpen) {\n setHoveredErrorId(null)\n }\n }, [isErrorsOpen, setHoveredErrorId])\n\n const closeErrorsMenu = useCallback(() => {\n setErrorsOpen(false)\n }, [])\n\n const handleRatsNestToggle = useCallback(() => {\n setIsShowingRatsNest(!viewSettings.is_showing_rats_nest)\n }, [viewSettings.is_showing_rats_nest, setIsShowingRatsNest])\n\n const handleMeasureToolClick = useCallback(() => {\n setMeasureToolArmed(true)\n setBoundsToolArmed(false)\n window.dispatchEvent(new Event(\"arm-dimension-tool\"))\n }, [])\n\n const handleBoundsToolClick = useCallback(() => {\n setBoundsToolArmed(true)\n setMeasureToolArmed(false)\n window.dispatchEvent(new Event(\"arm-bounds-tool\"))\n }, [])\n\n const handleViewMenuToggle = useCallback(() => {\n const newViewMenuOpen = !isViewMenuOpen\n setViewMenuOpen(newViewMenuOpen)\n if (newViewMenuOpen) {\n setErrorsOpen(false)\n }\n }, [isViewMenuOpen])\n\n const stopCanvasInteractionPropagation = useCallback(\n (\n event:\n | React.MouseEvent<HTMLElement>\n | React.TouchEvent<HTMLElement>\n | React.WheelEvent<HTMLElement>\n | React.PointerEvent<HTMLElement>,\n ) => {\n event.stopPropagation()\n },\n [],\n )\n\n return (\n <div\n ref={hotkeyBoundaryRef}\n style={{ position: \"relative\", zIndex: \"999 !important\" }}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onMouseMove={handleMouseMove}\n >\n {children}\n <div\n style={{\n position: \"absolute\",\n bottom: 4,\n right: 8,\n pointerEvents: \"none\",\n color: \"white\",\n fontSize: 11,\n opacity: isMouseOverContainer ? 0.5 : 0,\n transition: \"opacity 1s\",\n transitionDelay: \"2s\",\n fontFamily: \"sans-serif\",\n }}\n >\n @tscircuit/pcb-viewer@{packageJson.version}\n </div>\n <div\n data-toolbar-overlay\n onTouchStart={(e) => e.stopPropagation()}\n onTouchEnd={(e) => e.stopPropagation()}\n onTouchMove={(e) => e.stopPropagation()}\n onMouseDown={stopCanvasInteractionPropagation}\n onMouseMove={stopCanvasInteractionPropagation}\n onMouseUp={stopCanvasInteractionPropagation}\n onPointerDown={stopCanvasInteractionPropagation}\n onPointerMove={stopCanvasInteractionPropagation}\n onPointerUp={stopCanvasInteractionPropagation}\n onWheel={stopCanvasInteractionPropagation}\n style={{\n position: \"absolute\",\n opacity: isSmallScreen ? 1 : isMouseOverContainer ? 1 : 0,\n top: 16,\n left: 16,\n right: isSmallScreen ? 16 : \"auto\",\n transition: isMouseOverContainer\n ? \"opacity 100ms linear\"\n : \"opacity 300ms linear\",\n zIndex: zIndexMap.toolbarOverlay,\n color: \"red\",\n display: \"flex\",\n flexWrap: \"wrap\",\n maxWidth: \"550px\",\n gap: 4,\n fontSize: 12,\n fontFamily: \"sans-serif\",\n }}\n >\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n onClick={handleLayerMenuToggle}\n onMouseLeave={() => {\n if (isLayerMenuOpen) {\n setLayerMenuOpen(false)\n }\n }}\n >\n <div>\n layer:{\" \"}\n <span\n style={{\n marginLeft: 2,\n fontWeight: 500,\n color: (LAYER_NAME_TO_COLOR as any)[selectedLayer as string],\n }}\n >\n {selectedLayer as string}\n </span>\n </div>\n {isLayerMenuOpen && (\n <div style={{ marginTop: 4, minWidth: 120 }}>\n {processedLayers.map((layer) => (\n <LayerButton\n key={layer}\n name={layer}\n selected={layer === selectedLayer}\n onClick={() => {\n selectLayer(layer as LayerRef)\n }}\n />\n ))}\n </div>\n )}\n </ToolbarButton>\n <ToolbarErrorDropdown\n elements={elements}\n isOpen={isErrorsOpen}\n isSmallScreen={isSmallScreen}\n onToggle={handleErrorsToggle}\n onClose={closeErrorsMenu}\n setHoveredErrorId={setHoveredErrorId}\n setFocusedErrorId={setFocusedErrorId}\n />\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n style={{}}\n onClick={handleRatsNestToggle}\n >\n <div>\n {viewSettings.is_showing_rats_nest ? \"✖ \" : \"\"}\n Rats Nest\n </div>\n </ToolbarButton>\n\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n style={measureToolArmed ? { backgroundColor: \"#444\" } : {}}\n onClick={handleMeasureToolClick}\n >\n <div>📏</div>\n </ToolbarButton>\n\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n style={boundsToolArmed ? { backgroundColor: \"#444\" } : {}}\n onClick={handleBoundsToolClick}\n >\n <div>Bounds</div>\n </ToolbarButton>\n\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n onClick={handleViewMenuToggle}\n >\n <div>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"4px\",\n }}\n >\n View\n <span\n style={{\n fontSize: \"8px\",\n transform: isViewMenuOpen ? \"rotate(180deg)\" : \"rotate(0)\",\n transition: \"transform 0.1s ease\",\n display: \"inline-block\",\n }}\n >\n ▼\n </span>\n </div>\n {isViewMenuOpen && (\n <div style={{ marginTop: 4, minWidth: 120 }}>\n <CheckboxMenuItem\n label=\"Show All Trace Lengths\"\n checked={viewSettings.is_showing_multiple_traces_length}\n onClick={() => {\n setIsShowingMultipleTracesLength(\n !viewSettings.is_showing_multiple_traces_length,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show Autorouting Animation\"\n checked={viewSettings.is_showing_autorouting}\n onClick={() => {\n setIsShowingAutorouting(\n !viewSettings.is_showing_autorouting,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show DRC Errors\"\n checked={viewSettings.is_showing_drc_errors}\n onClick={() => {\n setIsShowingDrcErrors(!viewSettings.is_showing_drc_errors)\n }}\n />\n <CheckboxMenuItem\n label=\"Show DRC Warnings\"\n checked={viewSettings.is_showing_drc_warnings}\n onClick={() => {\n setIsShowingDrcWarnings(\n !viewSettings.is_showing_drc_warnings,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show Copper Pours\"\n checked={viewSettings.is_showing_copper_pours}\n onClick={() => {\n setIsShowingCopperPours(\n !viewSettings.is_showing_copper_pours,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show Courtyards\"\n checked={viewSettings.is_showing_courtyards}\n onClick={() => {\n setIsShowingCourtyards(!viewSettings.is_showing_courtyards)\n }}\n />\n <CheckboxMenuItem\n label=\"Show Solder Mask\"\n checked={viewSettings.is_showing_solder_mask}\n onClick={() => {\n setIsShowingSolderMask(!viewSettings.is_showing_solder_mask)\n }}\n />\n <CheckboxMenuItem\n label=\"Show Silkscreen\"\n checked={viewSettings.is_showing_silkscreen}\n onClick={() => {\n setIsShowingSilkscreen(!viewSettings.is_showing_silkscreen)\n }}\n />\n <CheckboxMenuItem\n label=\"Show Fabrication Notes\"\n checked={viewSettings.is_showing_fabrication_notes}\n onClick={() => {\n setIsShowingFabricationNotes(\n !viewSettings.is_showing_fabrication_notes,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show PCB Notes\"\n checked={viewSettings.is_showing_pcb_notes}\n onClick={() => {\n setIsShowingPcbNotes(!viewSettings.is_showing_pcb_notes)\n }}\n />\n <CheckboxMenuItem\n label=\"Show Group Anchor Offsets\"\n checked={viewSettings.is_showing_group_anchor_offsets}\n onClick={() => {\n setIsShowingGroupAnchorOffsets(\n !viewSettings.is_showing_group_anchor_offsets,\n )\n }}\n />\n <CheckboxMenuItem\n label=\"Show PCB Groups\"\n checked={viewSettings.is_showing_pcb_groups}\n onClick={() => {\n setIsShowingPcbGroups(!viewSettings.is_showing_pcb_groups)\n }}\n />\n {viewSettings.is_showing_pcb_groups && (\n <div style={{ marginLeft: 16 }}>\n <RadioMenuItem\n label=\"Show All Groups\"\n checked={viewSettings.pcb_group_view_mode === \"all\"}\n onClick={() => {\n setPcbGroupViewMode(\"all\")\n }}\n />\n <RadioMenuItem\n label=\"Show Named Groups\"\n checked={\n viewSettings.pcb_group_view_mode === \"named_only\"\n }\n onClick={() => {\n setPcbGroupViewMode(\"named_only\")\n }}\n />\n </div>\n )}\n </div>\n )}\n </div>\n </ToolbarButton>\n </div>\n </div>\n )\n}\n","{\n \"name\": \"@tscircuit/pcb-viewer\",\n \"version\": \"1.11.392\",\n \"main\": \"dist/index.js\",\n \"type\": \"module\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/tscircuit/pcb-viewer\"\n },\n \"license\": \"MIT\",\n \"scripts\": {\n \"start\": \"cosmos\",\n \"build\": \"tsup ./src/index.tsx --platform browser --external @tscircuit/core --dts --sourcemap --format esm --outDir dist\",\n \"yalc\": \"npm run build && yalc push\",\n \"format\": \"biome format . --write\",\n \"format:check\": \"biome format .\",\n \"cosmos\": \"cosmos\",\n \"cosmos-export\": \"cosmos-export\"\n },\n \"files\": [\n \"dist\"\n ],\n \"devDependencies\": {\n \"@biomejs/biome\": \"^1.9.4\",\n \"@semantic-release/commit-analyzer\": \"^9.0.2\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@semantic-release/npm\": \"^9.0.1\",\n \"@semantic-release/release-notes-generator\": \"^10.0.3\",\n \"@swc/core\": \"^1.4.12\",\n \"@tscircuit/circuit-json-util\": \"^0.0.108\",\n \"@tscircuit/eagle-xml-converter\": \"^1.0.0\",\n \"@types/bun\": \"latest\",\n \"@types/color\": \"^3.0.6\",\n \"@types/node\": \"18.7.23\",\n \"@types/react\": \"19\",\n \"format-si-unit\": \"^0.0.12\",\n \"next\": \"^14.1.4\",\n \"pixi.js\": \"^8.6.6\",\n \"react\": \"19.1.0\",\n \"react-cosmos\": \"7.0.0-beta.4\",\n \"react-cosmos-plugin-vite\": \"7.0.0-beta.0\",\n \"react-dom\": \"19.1.0\",\n \"react-use\": \"^17.4.0\",\n \"tscircuit\": \"^0.0.2354\",\n \"tsup\": \"^8.0.2\",\n \"type-fest\": \"^3.0.0\",\n \"typescript\": \"^5.4.4\",\n \"use-mouse-matrix-transform\": \"^1.3.4\",\n \"zod\": \"^3.23.5\"\n },\n \"peerDependencies\": {\n \"react\": \"*\",\n \"tscircuit\": \"*\"\n },\n \"dependencies\": {\n \"@emotion/css\": \"^11.11.2\",\n \"@tscircuit/alphabet\": \"^0.0.25\",\n \"@tscircuit/math-utils\": \"^0.0.36\",\n \"@vitejs/plugin-react\": \"^5.0.2\",\n \"circuit-json\": \"^0.0.469\",\n \"circuit-to-canvas\": \"0.0.124\",\n \"color\": \"^4.2.3\",\n \"react-supergrid\": \"^1.0.10\",\n \"react-toastify\": \"^10.0.5\",\n \"transformation-matrix\": \"^2.13.0\",\n \"zustand\": \"^4.5.2\"\n }\n}\n","import { useEffect, useRef, type RefObject } from \"react\"\nimport { useGlobalStore } from \"../global-store\"\n\nexport const useHotKey = (\n key: string,\n onUse: () => void,\n containerRef?: RefObject<HTMLElement | null>,\n) => {\n const isMouseOverContainer = useGlobalStore(\n (s) => s.is_mouse_over_container,\n ) as boolean\n\n const isMouseOverContainerRef = useRef(isMouseOverContainer)\n const onUseRef = useRef(onUse)\n\n useEffect(() => {\n isMouseOverContainerRef.current = isMouseOverContainer\n }, [isMouseOverContainer])\n\n useEffect(() => {\n onUseRef.current = onUse\n }, [onUse])\n\n useEffect(() => {\n if (!key) return\n\n const handleKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement\n if (\n target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.isContentEditable\n ) {\n return\n }\n\n const keyParts = key.split(\"+\")\n\n const ctrlRequired = keyParts.includes(\"ctrl\")\n const shiftRequired = keyParts.includes(\"shift\")\n const altRequired = keyParts.includes(\"alt\")\n const metaRequired = keyParts.includes(\"meta\")\n const mainKey = keyParts[keyParts.length - 1]\n\n const containerHasFocus = containerRef?.current\n ? containerRef.current.contains(document.activeElement) ||\n document.activeElement === containerRef.current\n : false\n\n const shouldTrigger = isMouseOverContainerRef.current || containerHasFocus\n\n if (\n shouldTrigger &&\n (!ctrlRequired || event.ctrlKey) &&\n (!shiftRequired || event.shiftKey) &&\n (!altRequired || event.altKey) &&\n (!metaRequired || event.metaKey) &&\n event.key.toLowerCase() === mainKey.toLowerCase()\n ) {\n event.preventDefault()\n onUseRef.current()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n\n return () => {\n window.removeEventListener(\"keydown\", handleKeyDown)\n }\n }, [key])\n}\n","import { useEffect, useState } from \"react\"\n\nexport const useIsSmallScreen = () => {\n const [isSmallScreen, setIsSmallScreen] = useState(false)\n\n useEffect(() => {\n const checkIsMobile = () => {\n setIsSmallScreen(window.innerWidth <= 768)\n }\n\n checkIsMobile()\n window.addEventListener(\"resize\", checkIsMobile)\n\n return () => window.removeEventListener(\"resize\", checkIsMobile)\n }, [])\n\n return isSmallScreen\n}\n","import {\n useCallback,\n useRef,\n type MouseEvent,\n type TouchEvent,\n type CSSProperties,\n} from \"react\"\n\n/**\n * A hook to handle mobile touch events and prevent \"ghost clicks\" or double-firing\n * when using both click and touch handlers.\n */\nexport const useMobileTouch = <T extends HTMLElement = HTMLElement>(\n onClick?: (e: MouseEvent<T> | TouchEvent<T>) => void,\n options: { stopPropagation?: boolean } = { stopPropagation: true },\n) => {\n const lastInteractionRef = useRef(0)\n\n const handleInteraction = useCallback(\n (e: MouseEvent<T> | TouchEvent<T>) => {\n if (options.stopPropagation) {\n e.stopPropagation()\n }\n\n const now = Date.now()\n if (now - lastInteractionRef.current < 300) return\n lastInteractionRef.current = now\n\n onClick?.(e)\n },\n [onClick, options.stopPropagation],\n )\n\n const onTouchEnd = useCallback(\n (e: TouchEvent<T>) => {\n e.preventDefault()\n handleInteraction(e)\n },\n [handleInteraction],\n )\n\n const style: CSSProperties = { touchAction: \"manipulation\" }\n\n return {\n onClick: handleInteraction,\n onTouchEnd,\n style,\n }\n}\n","import type React from \"react\"\nimport { useMobileTouch } from \"hooks/useMobileTouch\"\n\nexport interface ToolbarButtonProps {\n children: React.ReactNode\n isSmallScreen: boolean\n onClick?: (\n e: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>,\n ) => void\n style?: React.CSSProperties\n onMouseLeave?: (e: React.MouseEvent<HTMLElement>) => void\n}\n\nexport const ToolbarButton = ({\n children,\n isSmallScreen,\n onClick,\n ...props\n}: ToolbarButtonProps) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick)\n\n return (\n <div\n {...props}\n {...touchHandlers}\n style={{\n backgroundColor: \"#1F1F1F\",\n border: \"1px solid #666\",\n margin: 0,\n padding: 4,\n paddingLeft: isSmallScreen ? 8 : 6,\n paddingRight: isSmallScreen ? 8 : 6,\n borderRadius: 2,\n color: \"#eee\",\n cursor: \"pointer\",\n fontSize: 12,\n height: \"fit-content\",\n userSelect: \"none\",\n whiteSpace: \"nowrap\",\n ...touchStyle,\n ...props.style,\n }}\n >\n {children}\n </div>\n )\n}\n","import { useCallback, useMemo, useState } from \"react\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport { useCopyToClipboard } from \"react-use\"\nimport { useMobileTouch } from \"hooks/useMobileTouch\"\nimport { ToolbarButton } from \"./ToolbarButton\"\nimport { groupErrorsByType } from \"lib/util/group-errors-by-type\"\nimport { useToolbarErrorFocus } from \"./useToolbarErrorFocus\"\n\ntype ToolbarErrorElement = AnyCircuitElement & {\n error_type?: string\n message?: string\n pcb_trace_error_id?: string\n}\n\nconst CopyErrorButton = ({\n errorId,\n errorMessage,\n copiedErrorId,\n onCopy,\n}: {\n errorId: string\n errorMessage: string\n copiedErrorId: string | null\n onCopy: (errorMessage: string, errorId: string) => void\n}) => {\n const { style: touchStyle, ...touchHandlers } = useMobileTouch(() =>\n onCopy(errorMessage, errorId),\n )\n\n return (\n <button\n type=\"button\"\n aria-label={\n copiedErrorId === errorId\n ? \"Error message copied\"\n : \"Copy error message\"\n }\n style={{\n position: \"absolute\",\n top: 12,\n right: 16,\n cursor: \"pointer\",\n color: \"#888\",\n fontSize: 16,\n background: \"none\",\n border: \"none\",\n padding: 0,\n display: \"flex\",\n alignItems: \"center\",\n ...touchStyle,\n }}\n {...touchHandlers}\n >\n {copiedErrorId === errorId ? (\n <span style={{ color: \"#4caf50\", fontSize: 12 }}>Copied!</span>\n ) : (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\" />\n </svg>\n )}\n </button>\n )\n}\n\ninterface ToolbarErrorDropdownProps {\n elements?: AnyCircuitElement[]\n isOpen: boolean\n isSmallScreen: boolean\n onToggle: () => void\n onClose: () => void\n setHoveredErrorId: (errorId: string | null) => void\n setFocusedErrorId: (errorId: string | null) => void\n}\n\nexport const ToolbarErrorDropdown = ({\n elements,\n isOpen,\n isSmallScreen,\n onToggle,\n onClose,\n setHoveredErrorId,\n setFocusedErrorId,\n}: ToolbarErrorDropdownProps) => {\n const [copiedErrorId, setCopiedErrorId] = useState<string | null>(null)\n const [collapsedErrorGroups, setCollapsedErrorGroups] = useState<Set<string>>(\n new Set(),\n )\n const [expandedErrorIds, setExpandedErrorIds] = useState<Set<string>>(\n new Set(),\n )\n const [, copyToClipboard] = useCopyToClipboard()\n const { handleErrorSelect, isSelectedError } = useToolbarErrorFocus({\n onClose,\n setHoveredErrorId,\n setFocusedErrorId,\n })\n\n const errorElements = useMemo(\n () =>\n elements?.filter((el): el is ToolbarErrorElement =>\n el.type.includes(\"error\"),\n ) ?? [],\n [elements],\n )\n\n const errorCount = errorElements.length\n\n const groupedErrorElements = useMemo(\n () => groupErrorsByType(errorElements),\n [errorElements],\n )\n\n const toggleErrorGroup = useCallback((errorType: string) => {\n setCollapsedErrorGroups((prev) => {\n const next = new Set(prev)\n if (next.has(errorType)) {\n next.delete(errorType)\n } else {\n next.add(errorType)\n }\n return next\n })\n }, [])\n\n const toggleExpandedError = useCallback((errorId: string) => {\n setExpandedErrorIds((prev) => {\n const next = new Set(prev)\n if (next.has(errorId)) {\n next.delete(errorId)\n } else {\n next.add(errorId)\n }\n return next\n })\n }, [])\n\n return (\n <div style={{ position: \"relative\" }}>\n <ToolbarButton\n isSmallScreen={isSmallScreen}\n style={errorCount > 0 ? { color: \"red\" } : undefined}\n onClick={onToggle}\n >\n <div>{errorCount} errors</div>\n </ToolbarButton>\n {isOpen && errorCount > 0 && (\n <div\n style={{\n position: \"absolute\",\n top: \"100%\",\n left: 0,\n backgroundColor: \"#2a2a2a\",\n border: \"1px solid #666\",\n borderRadius: 4,\n marginTop: 4,\n zIndex: 1000,\n minWidth: isSmallScreen ? \"280px\" : \"400px\",\n maxWidth: isSmallScreen ? \"90vw\" : \"600px\",\n maxHeight: \"400px\",\n overflow: \"auto\",\n boxShadow: \"0 4px 12px rgba(0, 0, 0, 0.3)\",\n }}\n >\n {groupedErrorElements.map(({ errorType, errors }, groupIndex) => {\n const isGroupCollapsed = collapsedErrorGroups.has(errorType)\n\n return (\n <div\n key={errorType}\n style={{\n borderBottom:\n groupIndex < groupedErrorElements.length - 1\n ? \"1px solid #444\"\n : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n backgroundColor: \"#232323\",\n transition: \"background-color 0.2s ease\",\n touchAction: \"manipulation\",\n position: \"sticky\",\n top: 0,\n zIndex: 1,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#303030\"\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#232323\"\n }}\n onTouchStart={(e) => {\n e.stopPropagation()\n e.currentTarget.style.backgroundColor = \"#303030\"\n }}\n onTouchEnd={(e) => {\n e.stopPropagation()\n e.preventDefault()\n e.currentTarget.style.backgroundColor = \"#232323\"\n toggleErrorGroup(errorType)\n }}\n onClick={(e) => {\n e.stopPropagation()\n toggleErrorGroup(errorType)\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n color: \"#ff6b6b\",\n }}\n >\n <div\n style={{\n color: \"#888\",\n fontSize: \"16px\",\n transform: isGroupCollapsed\n ? \"rotate(90deg)\"\n : \"rotate(0deg)\",\n transition: \"transform 0.2s ease\",\n flexShrink: 0,\n }}\n >\n ›\n </div>\n <div\n style={{\n fontWeight: \"bold\",\n fontSize: isSmallScreen ? \"12px\" : \"13px\",\n }}\n >\n {errorType}\n </div>\n </div>\n <div\n style={{\n fontSize: isSmallScreen ? \"12px\" : \"13px\",\n color: \"#aaa\",\n whiteSpace: \"nowrap\",\n marginLeft: 12,\n }}\n >\n {errors.length}\n </div>\n </div>\n {!isGroupCollapsed &&\n errors.map(({ error, index, errorId }) => {\n const isExpanded = expandedErrorIds.has(errorId)\n const errorMessage = error.message ?? \"No error message\"\n\n return (\n <div\n key={errorId}\n style={{\n borderTop: \"1px solid #3a3a3a\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n padding: \"12px 16px 12px 24px\",\n cursor: \"pointer\",\n backgroundColor: \"#2a2a2a\",\n transition: \"background-color 0.2s ease\",\n touchAction: \"manipulation\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#333\"\n setHoveredErrorId(errorId)\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"#2a2a2a\"\n if (!isSelectedError(errorId)) {\n setHoveredErrorId(null)\n }\n }}\n onTouchStart={(e) => {\n e.stopPropagation()\n e.currentTarget.style.backgroundColor = \"#333\"\n setHoveredErrorId(errorId)\n }}\n onTouchEnd={(e) => {\n e.stopPropagation()\n e.preventDefault()\n e.currentTarget.style.backgroundColor = \"#2a2a2a\"\n handleErrorSelect(errorId)\n }}\n onClick={(e) => {\n e.stopPropagation()\n handleErrorSelect(errorId)\n }}\n >\n <div\n style={{\n flex: 1,\n fontSize: isSmallScreen ? \"12px\" : \"13px\",\n color: \"#ddd\",\n lineHeight: 1.4,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n userSelect: \"text\",\n }}\n >\n {errorMessage}\n </div>\n <button\n type=\"button\"\n aria-label={\n isExpanded\n ? \"Collapse error details\"\n : \"Expand error details\"\n }\n style={{\n color: \"#888\",\n fontSize: \"16px\",\n transform: isExpanded\n ? \"rotate(0deg)\"\n : \"rotate(90deg)\",\n transition: \"transform 0.2s ease\",\n flexShrink: 0,\n background: \"none\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n }}\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation()\n toggleExpandedError(errorId)\n }}\n onTouchEnd={(event) => {\n event.stopPropagation()\n event.preventDefault()\n toggleExpandedError(errorId)\n }}\n >\n ›\n </button>\n </div>\n {isExpanded && (\n <div\n data-error-id={index}\n style={{\n display: \"block\",\n padding: \"12px 16px 12px 24px\",\n backgroundColor: \"#1a1a1a\",\n borderTop: \"1px solid #444\",\n position: \"relative\",\n }}\n >\n <div\n style={{\n fontSize: isSmallScreen ? \"11px\" : \"12px\",\n color: \"#ccc\",\n lineHeight: 1.5,\n wordWrap: \"break-word\",\n overflowWrap: \"break-word\",\n hyphens: \"auto\",\n userSelect: \"text\",\n paddingRight: 30,\n }}\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => event.stopPropagation()}\n >\n {errorMessage}\n </div>\n <CopyErrorButton\n errorId={errorId}\n errorMessage={errorMessage}\n copiedErrorId={copiedErrorId}\n onCopy={(message, id) => {\n copyToClipboard(message)\n setCopiedErrorId(id)\n setTimeout(() => setCopiedErrorId(null), 2000)\n }}\n />\n </div>\n )}\n </div>\n )\n })}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n","import { getErrorId } from \"lib/util/get-error-id\"\n\nexport const groupErrorsByType = <\n T extends {\n error_type?: string\n },\n>(\n errors: T[],\n) => {\n const groups = new Map<\n string,\n { error: T; index: number; errorId: string }[]\n >()\n\n errors.forEach((error, index) => {\n const errorType = error.error_type || \"unknown_error\"\n const existingGroup = groups.get(errorType) || []\n\n existingGroup.push({\n error,\n index,\n errorId: getErrorId(error, index),\n })\n\n groups.set(errorType, existingGroup)\n })\n\n return Array.from(groups.entries()).map(([errorType, groupedErrors]) => ({\n errorType,\n errors: groupedErrors,\n }))\n}\n","import { useCallback, useEffect, useRef } from \"react\"\n\nexport const useToolbarErrorFocus = ({\n onClose,\n setHoveredErrorId,\n setFocusedErrorId,\n highlightDurationMs = 3000,\n}: {\n onClose: () => void\n setHoveredErrorId: (errorId: string | null) => void\n setFocusedErrorId: (errorId: string | null) => void\n highlightDurationMs?: number\n}) => {\n const clearHighlightTimeoutRef = useRef<number | null>(null)\n const focusRequestRef = useRef<number | null>(null)\n const selectedErrorIdRef = useRef<string | null>(null)\n\n const clearPendingSelection = useCallback(() => {\n if (clearHighlightTimeoutRef.current !== null) {\n window.clearTimeout(clearHighlightTimeoutRef.current)\n clearHighlightTimeoutRef.current = null\n }\n\n if (focusRequestRef.current !== null) {\n window.cancelAnimationFrame(focusRequestRef.current)\n focusRequestRef.current = null\n }\n }, [])\n\n useEffect(() => clearPendingSelection, [clearPendingSelection])\n\n const handleErrorSelect = useCallback(\n (errorId: string) => {\n clearPendingSelection()\n\n selectedErrorIdRef.current = errorId\n setHoveredErrorId(errorId)\n setFocusedErrorId(null)\n\n focusRequestRef.current = window.requestAnimationFrame(() => {\n setFocusedErrorId(errorId)\n focusRequestRef.current = null\n })\n\n onClose()\n\n clearHighlightTimeoutRef.current = window.setTimeout(() => {\n selectedErrorIdRef.current = null\n setHoveredErrorId(null)\n setFocusedErrorId(null)\n clearHighlightTimeoutRef.current = null\n }, highlightDurationMs)\n },\n [\n clearPendingSelection,\n highlightDurationMs,\n onClose,\n setFocusedErrorId,\n setHoveredErrorId,\n ],\n )\n\n const isSelectedError = useCallback(\n (errorId: string) => selectedErrorIdRef.current === errorId,\n [],\n )\n\n return {\n handleErrorSelect,\n isSelectedError,\n }\n}\n","import type { AnyCircuitElement, LayerRef } from \"circuit-json\"\nimport { zIndexMap } from \"lib/util/z-index-map\"\nimport { useEffect, useRef } from \"react\"\nimport { useMeasure } from \"react-use\"\nimport { type Matrix, applyToPoint, identity } from \"transformation-matrix\"\nimport colors from \"lib/colors\"\nimport {\n getPcbWarningHighlightLabel,\n isHighlightablePcbWarning,\n} from \"lib/util/get-pcb-warning-highlight\"\nimport { useGlobalStore } from \"../global-store\"\n\ninterface BaseCircuitElement {\n type: string\n}\n\ninterface PcbComponent extends BaseCircuitElement {\n type: \"pcb_component\"\n pcb_component_id: string\n width: number\n height: number\n source_component_id: string\n center: { x: number; y: number }\n rotation: number\n layer: LayerRef\n obstructs_within_bounds: boolean\n}\n\ninterface Props {\n transform?: Matrix\n elements?: AnyCircuitElement[]\n children: any\n}\n\nexport const WarningGraphicsOverlay = ({\n children,\n transform = identity(),\n elements = [],\n}: Props) => {\n const [containerRef, { width, height }] = useMeasure<HTMLDivElement>()\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const isShowingDrcWarnings = useGlobalStore(\n (state) => state.is_showing_drc_warnings,\n )\n\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas || !width || !height) return\n\n canvas.width = width\n canvas.height = height\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n\n ctx.clearRect(0, 0, width, height)\n\n const pcbComponents = elements.filter(\n (el): el is PcbComponent => el.type === \"pcb_component\",\n ) as PcbComponent[]\n\n const warnings = elements.filter(isHighlightablePcbWarning)\n\n ctx.strokeStyle = colors.board.drc_warning\n ctx.lineWidth = 2\n\n warnings.forEach((warning) => {\n const component = pcbComponents.find(\n (comp) => comp.pcb_component_id === warning.pcb_component_id,\n )\n\n if (!component) return\n\n const { width, height, center } = component\n\n const transformedCenter = applyToPoint(transform, center)\n\n const scaledWidth = width * Math.abs(transform.a)\n const scaledHeight = height * Math.abs(transform.d)\n\n const boxPadding = 0.1 * Math.abs(transform.a)\n\n const boxWidth = scaledWidth + boxPadding * 2\n const boxHeight = scaledHeight + boxPadding * 2\n const x = transformedCenter.x - boxWidth / 2\n const y = transformedCenter.y - boxHeight / 2\n\n ctx.beginPath()\n ctx.rect(x, y, boxWidth, boxHeight)\n ctx.stroke()\n\n const labelText = getPcbWarningHighlightLabel(warning)\n const labelPadding = 4\n const fontSize = Math.max(8, Math.min(12, 10 * Math.abs(transform.a)))\n ctx.font = `${fontSize}px sans-serif`\n const labelMetrics = ctx.measureText(labelText)\n const labelWidth = labelMetrics.width + labelPadding * 2\n const labelHeight = fontSize + labelPadding * 2\n const labelX = x + (boxWidth - labelWidth) / 2\n const labelY = y + boxHeight + 5\n\n ctx.fillStyle = \"rgba(0, 0, 0, 0.7)\"\n ctx.beginPath()\n ctx.roundRect(labelX, labelY, labelWidth, labelHeight, 3)\n ctx.fill()\n\n ctx.fillStyle = colors.board.drc_warning\n ctx.textAlign = \"center\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(labelText, labelX + labelWidth / 2, labelY + labelHeight / 2)\n })\n }, [elements, transform, width, height, isShowingDrcWarnings])\n\n if (!isShowingDrcWarnings) {\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n >\n {children}\n </div>\n )\n }\n\n return (\n <div\n ref={containerRef}\n style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}\n >\n {children}\n <canvas\n ref={canvasRef}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n pointerEvents: \"none\",\n zIndex: zIndexMap.warnings,\n }}\n />\n </div>\n )\n}\n","import type {\n AnyCircuitElement,\n PcbConnectorNotInAccessibleOrientationWarning,\n PcbManualEditConflictWarning,\n} from \"circuit-json\"\n\nexport type HighlightablePcbWarning =\n | PcbManualEditConflictWarning\n | PcbConnectorNotInAccessibleOrientationWarning\n\nexport const isHighlightablePcbWarning = (\n element: AnyCircuitElement,\n): element is HighlightablePcbWarning =>\n element.type === \"pcb_manual_edit_conflict_warning\" ||\n element.type === \"pcb_connector_not_in_accessible_orientation_warning\"\n\nexport const getPcbWarningHighlightLabel = (\n warning: HighlightablePcbWarning,\n): string => {\n if (warning.type === \"pcb_connector_not_in_accessible_orientation_warning\") {\n return `Connector faces ${warning.facing_direction}; expected ${warning.recommended_facing_direction}`\n }\n\n return \"Manual Edit Conflict\"\n}\n","import {\n getBoundsOfPcbElements,\n getElementId,\n} from \"@tscircuit/circuit-json-util\"\nimport type { AnyCircuitElement, PcbTrace } from \"circuit-json\"\n\nconst formatToFixed4 = (value: number): string =>\n Number.isFinite(value) ? value.toFixed(4) : \"NaN\"\n\nconst generateHash = (input: string): number => {\n let hash = 5381\n for (let i = 0; i < input.length; i++) {\n hash = (hash << 5) + hash + input.charCodeAt(i)\n }\n return Math.abs(hash)\n}\n\nexport const calculateCircuitJsonKey = (\n circuitJson?: AnyCircuitElement[],\n): string => {\n if (!circuitJson?.length) {\n return \"0\"\n }\n\n const elementSignatures: string[] = []\n\n for (const element of circuitJson) {\n if (!element?.type?.startsWith(\"pcb_\")) {\n continue\n }\n\n const id = getElementId(element)\n\n const bounds = getBoundsOfPcbElements([element])\n\n const boundsStr = [\n formatToFixed4(bounds.minX),\n formatToFixed4(bounds.minY),\n formatToFixed4(bounds.maxX),\n formatToFixed4(bounds.maxY),\n ].join(\",\")\n let signature = `${id}:${boundsStr}`\n if (element.type === \"pcb_trace\") {\n const routeLength = ((element as PcbTrace).route ?? []).length\n signature += `:${routeLength}`\n }\n\n elementSignatures.push(signature)\n }\n\n if (elementSignatures.length === 0) {\n return \"0\"\n }\n\n elementSignatures.sort()\n\n const combinedSignature = elementSignatures.join(\",\")\n const hash = generateHash(combinedSignature)\n\n return `${elementSignatures.length}_${hash.toString(36)}`\n}\n","import type { AnyCircuitElement, PcbBoard } from \"circuit-json\"\n\nexport const calculateBoardSizeKey = (\n circuitJson?: AnyCircuitElement[],\n): string => {\n if (!circuitJson) return \"empty\"\n\n const board = circuitJson.find((e) => e.type === \"pcb_board\") as\n | PcbBoard\n | undefined\n\n if (!board) return \"no-board\"\n const round = (n: number) => Math.round(n * 1000) / 1000\n\n if (board.outline) {\n return board.outline.map((o) => `${round(o.x)}_${round(o.y)}`).join(\",\")\n }\n\n return `${round(board.width!)}_${round(board.height!)}`\n}\n"],"mappings":"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D,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;EACtD,CAAC,WAAW,WAAW,WAAW,WA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","names":["format","err","kindOf","module","noop","getAction","create","lexer","emit","step","createNode","reader","handleLexerData","parseSync","parseInput","camelize","toCamelCase","notCamelcase","escapeText","escapeAttr","svgsonSync","applyFilters","input","stringify","ast","Soup","translate","su","component_type","joiner","Soup","jsx","jsx","useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useCallback","useCallback","useCallback","writeText","error","useEffect","useEffect","useMemo","useState","useState","useMemo","_a","compose","scale","translate","translate","translate","compose","applyToPoint","scale","useCallback","useEffect","useRef","useState","scale","getBoundsFromPoints","compose","scale","translate","mergeBounds","useCallback","useEffect","useMemo","useRef","useState","applyToPoint","compose","identity","translate","identity","compose","translate","applyToPoint","angle","scale","color","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","PCB_VIEWER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","color","DEFAULT_PCB_COLOR_MAP","color","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","color","HOVER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","color","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","color","HOVER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","color","CircuitToCanvasDrawer","compose","translate","applyToPoint","color","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","PCB_VIEWER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","color","DEFAULT_PCB_COLOR_MAP","color","CircuitToCanvasDrawer","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","color","HOVER_COLOR_MAP","DEFAULT_PCB_COLOR_MAP","CircuitToCanvasDrawer","useEffect","useRef","jsx","useRef","useEffect","uint16","uint8","osIsLittleEndian","applyToPoint","inverse","applyToPoint","applyToPoint","heads","applyToPoint","compose","scale","translate","color","applyToPoint","applyToPoint","compose","scale","translate","useEffect","useRef","jsx","jsxs","useRef","useEffect","useCallback","useEffect","useMemo","useRef","useState","applyToPoint","identity","inverse","rotatePoint","rotatePoint","useMemo","distance","useMemo","rotatePoint","jsx","jsxs","identity","useState","useCallback","useRef","useMemo","applyToPoint","distance","useEffect","inverse","useRef","useState","applyToPoint","identity","inverse","jsx","jsxs","e","useRef","Fragment","applyToPoint","identity","jsx","jsxs","jsx","jsxs","identity","useRef","applyToPoint","Fragment","scale","distance","useEffect","useMemo","useState","applyToPoint","inverse","applyToPoint","Fragment","jsx","jsxs","applyToPoint","jsx","jsx","applyToPoint","jsx","jsxs","applyToPoint","jsx","useEffect","useState","jsx","jsxs","useState","useEffect","color","Fragment","jsx","jsxs","distance","useState","useEffect","useMemo","highlightedPrimitives","applyToPoint","transform","primitives","inverse","applyToPoint","identity","useRef","useEffect","jsx","jsxs","identity","useRef","useEffect","children","applyToPoint","applyToPoint","identity","useMemo","jsx","jsxs","distance","identity","applyToPoint","useEffect","useState","useCallback","useRef","useLayoutEffect","css","useEffect","useRef","useRef","useEffect","useEffect","useState","useCallback","useRef","jsx","useCallback","useMemo","useState","useCallback","useEffect","useRef","jsx","jsxs","useState","useMemo","useCallback","jsx","jsxs","css","useState","useEffect","useRef","useLayoutEffect","useCallback","useEffect","useRef","applyToPoint","identity","jsx","jsxs","identity","useRef","useEffect","width","height","applyToPoint","jsx","useMemo","primitivesWithoutInteractionMetadata","connectivityMap","useState","useRef","useEffect","useCallback","jsx","jsxs","compose","translate","scale","useState","useCallback","useRef","useMemo","height","useEffect"]}
|