@mica-js/schematic-editor 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["symbols.nextDesignator","wires.connectWireAt","wires.previewWireSegment","styles"],"sources":["../src/controller/inspector.ts","../src/controller/selection.ts","../src/controller/types.ts","../src/controller/session.ts","../src/controller/wires.ts","../src/controller/symbols.ts","../src/controller/controller.ts","../src/render/theme.ts","../src/render/viewport.ts","../src/render/canvas-renderer.ts","../src/render/scene.ts","../src/editor/snapping/nodes.ts","../src/editor/snapping/drag.ts","../src/editor/snapping/wire.ts","../src/editor/snapping/label.ts","../src/editor/interactions/placement.ts","../src/editor/selection-box.ts","../src/editor/interactions/selection.ts","../src/editor/interactions/wire.ts","../src/editor/interactions/keyboard.ts","../src/editor/interactions/move.ts","../src/editor/interactions/pointer.ts","../src/editor/interactions/segment.ts","../src/editor/interactions/state.ts","../src/editor/interactions/input.ts","../src/editor/scene-input.ts","../src/styles/editor.css?inline","../src/styles/index.ts","../src/editor/icons.ts","../src/editor/shell.ts","../src/editor/viewport-state.ts","../src/editor/mount.ts"],"sourcesContent":["import {\n DEFAULT_TEXT_CONTENT,\n designatorOf,\n isTextDevice,\n namesNet,\n netNameOf,\n parseDeviceReference,\n propertyValueProblem,\n symbolRole,\n textDeviceContent,\n type DeviceSymbolProvider,\n type PropertyDescriptor,\n type PropertyValue,\n type SchematicDocument,\n type SchematicSymbol,\n type SchematicTopology,\n} from '@mica-js/core/schematic';\nimport type { EditorSelection, Inspector, PropertyField, SymbolInspector } from './types';\n\nexport interface InspectorContext {\n readonly devices: DeviceSymbolProvider | undefined;\n readonly topology: () => SchematicTopology;\n}\n\n/** Builds the property-panel payload for the current selection. */\nexport function buildInspector(\n document: SchematicDocument,\n selection: readonly EditorSelection[],\n context: InspectorContext,\n): Inspector {\n if (selection.length !== 1) {\n return undefined;\n }\n const [item] = selection;\n if (item === undefined) {\n return undefined;\n }\n if (item.kind === 'wire') {\n const wire = document.sheet.wires.find((candidate) => candidate.id === item.id);\n if (wire === undefined) {\n return undefined;\n }\n const net = context.topology().nets.find((candidate) => candidate.wireIds.includes(wire.id));\n return { kind: 'wire', id: wire.id, netName: net?.name ?? null, points: wire.points };\n }\n if (item.kind !== 'symbol' && item.kind !== 'reference') {\n return undefined;\n }\n const symbolId = item.kind === 'symbol' ? item.id : item.symbolId;\n const symbol = document.sheet.symbols.find((candidate) => candidate.id === symbolId);\n if (symbol === undefined) {\n return undefined;\n }\n return symbolInspector(symbol, context.devices);\n}\n\nfunction symbolInspector(\n symbol: SchematicSymbol,\n devices: DeviceSymbolProvider | undefined,\n): SymbolInspector {\n const reference = parseDeviceReference(symbol.device);\n const role = symbolRole(symbol.device);\n const designator = designatorOf(symbol);\n const net = netNameOf(symbol);\n return {\n kind: 'symbol',\n id: symbol.id,\n role,\n device: symbol.device,\n name:\n (reference === undefined ? undefined : devices?.getDeviceName(reference)) ??\n builtinName(symbol),\n builtin: role !== 'component',\n ...(designator === undefined ? {} : { designator }),\n ...(net === undefined ? {} : { net }),\n x: symbol.x,\n y: symbol.y,\n rotation: symbol.rotation,\n properties: propertyFields(symbol, devices),\n };\n}\n\nfunction propertyFields(\n symbol: SchematicSymbol,\n devices: DeviceSymbolProvider | undefined,\n): readonly PropertyField[] {\n const overrides = symbol.properties ?? {};\n\n if (isTextDevice(symbol.device)) {\n const override = overrides['text'];\n return [toField(TEXT_DESCRIPTOR, typeof override === 'string' ? override : undefined)];\n }\n\n // Net-naming symbols expose their net name as a dedicated inspector row, not as a property.\n if (namesNet(symbolRole(symbol.device))) {\n return [];\n }\n\n const fields: PropertyField[] = [];\n for (const descriptor of devicePropertyDescriptors(symbol, devices).values()) {\n const override = overrides[descriptor.key];\n const valid =\n override !== undefined && propertyValueProblem(descriptor, override) === undefined;\n fields.push(toField(descriptor, valid ? override : undefined));\n }\n return fields;\n}\n\n/** Moves the declared default to `defaultValue` so hosts can tell it apart from the instance value. */\nfunction toField(descriptor: PropertyDescriptor, value: PropertyValue | undefined): PropertyField {\n const { default: defaultValue, ...rest } = descriptor;\n return {\n ...rest,\n ...(defaultValue === undefined ? {} : { defaultValue }),\n ...(value === undefined ? {} : { value }),\n };\n}\n\nfunction devicePropertyDescriptors(\n symbol: SchematicSymbol,\n devices: DeviceSymbolProvider | undefined,\n): ReadonlyMap<string, PropertyDescriptor> {\n const reference = parseDeviceReference(symbol.device);\n if (reference === undefined) {\n return new Map();\n }\n return devices?.getDevicePropertyDescriptors?.(reference) ?? new Map();\n}\n\nfunction builtinName(symbol: SchematicSymbol): string | undefined {\n if (isTextDevice(symbol.device)) {\n return textDeviceContent(symbol);\n }\n return netNameOf(symbol);\n}\n\n/** `builtin:text` carries its content in one string property, described like any other (#7). */\nconst TEXT_DESCRIPTOR: PropertyDescriptor = {\n key: 'text',\n type: 'string',\n title: '文本',\n default: DEFAULT_TEXT_CONTENT,\n};\n","import type { SchematicDocument } from '@mica-js/core/schematic';\nimport type { EditorSelection } from './types';\n\nexport function sameSelectionItem(left: EditorSelection, right: EditorSelection): boolean {\n if (left.kind !== right.kind) {\n return false;\n }\n if (left.kind === 'vertex' && right.kind === 'vertex') {\n return left.wireId === right.wireId && left.index === right.index;\n }\n if (left.kind === 'reference' && right.kind === 'reference') {\n return left.symbolId === right.symbolId;\n }\n return 'id' in left && 'id' in right ? left.id === right.id : false;\n}\n\nexport function sameSelection(\n left: readonly EditorSelection[],\n right: readonly EditorSelection[],\n): boolean {\n return (\n left.length === right.length &&\n left.every((item, index) => {\n const other = right[index];\n return other !== undefined && sameSelectionItem(item, other);\n })\n );\n}\n\n/** Drops entries whose target disappeared from the document. */\nexport function pruneSelection(\n selection: readonly EditorSelection[],\n document: SchematicDocument,\n): readonly EditorSelection[] {\n if (selection.length === 0) {\n return selection;\n }\n const symbols = new Set(document.sheet.symbols.map((symbol) => symbol.id));\n const wires = new Map(document.sheet.wires.map((wire) => [wire.id, wire]));\n const junctions = new Set(document.sheet.junctions.map((junction) => junction.id));\n const kept = selection.filter((item) => {\n switch (item.kind) {\n case 'symbol':\n return symbols.has(item.id);\n case 'reference':\n return symbols.has(item.symbolId);\n case 'wire':\n return wires.has(item.id);\n case 'junction':\n return junctions.has(item.id);\n case 'vertex': {\n const wire = wires.get(item.wireId);\n return wire !== undefined && item.index < wire.points.length;\n }\n default:\n return false;\n }\n });\n return kept.length === selection.length ? selection : kept;\n}\n","import type {\n Point,\n PropertyDescriptor,\n PropertyValue,\n SchematicDocument,\n SchematicError,\n SymbolRole,\n} from '@mica-js/core/schematic';\n\nexport type EditorTool = 'select' | 'wire' | 'power' | 'ground' | 'label' | 'text';\n\nexport type EditorSelection =\n | { readonly kind: 'symbol'; readonly id: string }\n | { readonly kind: 'reference'; readonly symbolId: string }\n | { readonly kind: 'wire'; readonly id: string }\n | { readonly kind: 'junction'; readonly id: string }\n | { readonly kind: 'vertex'; readonly wireId: string; readonly index: number };\n\nexport interface DisplayOptions {\n readonly grid: boolean;\n readonly snap: boolean;\n readonly labels: boolean;\n /** Snap step in page units. */\n readonly gridSize: number;\n /** Visible grid lines per snap cell; `1` shows only the snap grid. */\n readonly gridSubdivisions: number;\n}\n\nexport const DEFAULT_DISPLAY_OPTIONS: DisplayOptions = {\n grid: true,\n snap: true,\n labels: true,\n gridSize: 10,\n gridSubdivisions: 2,\n};\n\n/**\n * One editable property of the selected symbol, described by its device (#7).\n *\n * `type` selects the control a host renders; the remaining constraint fields (`options`, `min`,\n * `max`, `step`, `unit`, `maxLength`, `alpha`, `maxBytes`, `maxPixels`) come from the declaration.\n */\nexport type PropertyField = Omit<PropertyDescriptor, 'default'> & {\n /** Declared default; absent when the device declares none. */\n readonly defaultValue?: PropertyValue;\n /** Instance override; absent when the instance inherits the default, `null` when cleared. */\n readonly value?: PropertyValue;\n};\n\nexport interface SymbolInspector {\n readonly kind: 'symbol';\n readonly id: string;\n /** What the symbol is for; drives which fields the panel shows. */\n readonly role: SymbolRole;\n readonly device: string;\n readonly name: string | undefined;\n /** True for the builtin symbols (`label` / `power` / `ground` / `text`). */\n readonly builtin: boolean;\n /** Reference designator; absent for symbols that carry none. */\n readonly designator?: string;\n /** Net name; absent for symbols that name no net. */\n readonly net?: string;\n readonly x: number;\n readonly y: number;\n readonly rotation: number;\n readonly properties: readonly PropertyField[];\n}\n\nexport interface WireInspector {\n readonly kind: 'wire';\n readonly id: string;\n /** Net name derived from the topology; `null` for anonymous nets. */\n readonly netName: string | null;\n readonly points: readonly Point[];\n}\n\nexport type Inspector = SymbolInspector | WireInspector | undefined;\n\n/**\n * Field subset the canvas needs. Reading it never builds the inspector, so a repaint (pointer\n * hover, drag preview) stays cheap.\n */\nexport interface EditorRenderState {\n readonly document: SchematicDocument;\n readonly selection: readonly EditorSelection[];\n readonly tool: EditorTool;\n readonly display: DisplayOptions;\n}\n\nexport interface EditorState {\n readonly document: SchematicDocument;\n readonly selection: readonly EditorSelection[];\n readonly tool: EditorTool;\n /** Device armed for placement by the host's device list; `undefined` when idle. */\n readonly placingDevice: string | undefined;\n readonly display: DisplayOptions;\n readonly canUndo: boolean;\n readonly canRedo: boolean;\n readonly inspector: Inspector;\n /** Last captured edit error; cleared by the next successful edit. */\n readonly lastError: SchematicError | undefined;\n}\n","import {\n SchematicEditor,\n SchematicError,\n createDesignatorFactory,\n defaultElementIdFactory,\n deriveSchematicTopology,\n hitTestSchematic,\n mergeWiresAtJunction,\n type DesignatorFactory,\n type DeviceSymbolProvider,\n type Diagnostic,\n type ElementIdFactory,\n type HitTestOptions,\n type SchematicDocument,\n type SchematicHit,\n type SchematicSymbol,\n type SchematicTopology,\n type SchematicWire,\n} from '@mica-js/core/schematic';\nimport { buildInspector } from './inspector';\nimport { pruneSelection } from './selection';\nimport {\n DEFAULT_DISPLAY_OPTIONS,\n type DisplayOptions,\n type EditorRenderState,\n type EditorSelection,\n type EditorState,\n type EditorTool,\n type Inspector,\n} from './types';\n\nconst MAX_MERGE_PASSES = 64;\n\nexport interface EditorSessionOptions {\n readonly document: SchematicDocument;\n readonly devices?: DeviceSymbolProvider;\n readonly tolerance?: number;\n readonly historyLimit?: number;\n readonly display?: Partial<DisplayOptions>;\n readonly createId?: ElementIdFactory;\n /** Designator policy; defaults to the device's `designatorPrefix` (`U` when it declares none). */\n readonly createDesignator?: DesignatorFactory;\n}\n\n/**\n * Editing session: the document editor, the session-level state (selection, tool, display,\n * errors), the caches derived from them and the mutation plumbing.\n * Actions in `symbols.ts` / `wires.ts` operate on it; the controller is only a façade.\n */\nexport class EditorSession {\n editor: SchematicEditor;\n readonly devices: DeviceSymbolProvider | undefined;\n readonly tolerance: number | undefined;\n readonly createId: ElementIdFactory;\n readonly createDesignator: DesignatorFactory;\n selection: readonly EditorSelection[] = [];\n tool: EditorTool = 'select';\n display: DisplayOptions;\n placingDevice: string | undefined;\n lastError: SchematicError | undefined;\n readonly #listeners = new Set<(state: EditorState) => void>();\n #topology:\n { readonly document: SchematicDocument; readonly value: SchematicTopology } | undefined;\n #stateCache: EditorState | undefined;\n #renderCache: EditorRenderState | undefined;\n\n constructor(options: EditorSessionOptions) {\n this.editor = new SchematicEditor(options.document, {\n ...deriveOptions(options.devices, options.tolerance),\n ...(options.historyLimit === undefined ? {} : { historyLimit: options.historyLimit }),\n });\n this.devices = options.devices;\n this.tolerance = options.tolerance;\n this.createId = options.createId ?? defaultElementIdFactory;\n this.createDesignator = options.createDesignator ?? createDesignatorFactory(options.devices);\n this.display = { ...DEFAULT_DISPLAY_OPTIONS, ...options.display };\n }\n\n get document(): SchematicDocument {\n return this.editor.document;\n }\n\n /** Editing options for core calls (`exactOptionalPropertyTypes` friendly). */\n get options(): { devices?: DeviceSymbolProvider; tolerance?: number } {\n return deriveOptions(this.devices, this.tolerance);\n }\n\n /**\n * Full editor state. Cached until the next change so hosts can compare references, and so a\n * repaint does not rebuild the inspector payload.\n */\n state(): EditorState {\n if (this.#stateCache !== undefined) {\n return this.#stateCache;\n }\n this.#stateCache = {\n ...this.renderState(),\n placingDevice: this.placingDevice,\n canUndo: this.editor.canUndo,\n canRedo: this.editor.canRedo,\n inspector: this.inspect(),\n lastError: this.lastError,\n };\n return this.#stateCache;\n }\n\n /** Everything the canvas draws from; never builds the inspector. */\n renderState(): EditorRenderState {\n if (this.#renderCache !== undefined) {\n return this.#renderCache;\n }\n this.#renderCache = {\n document: this.editor.document,\n selection: this.selection,\n tool: this.tool,\n display: this.display,\n };\n return this.#renderCache;\n }\n\n subscribe(listener: (state: EditorState) => void): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n emit(): void {\n this.#stateCache = undefined;\n this.#renderCache = undefined;\n const state = this.state();\n for (const listener of [...this.#listeners]) {\n listener(state);\n }\n }\n\n /**\n * Runs `run` as one undoable edit, then reconciles junctions. Failures are recorded in\n * `lastError` and rethrown; the document stays untouched.\n */\n mutate(run: () => void, options: { reconcile?: boolean } = {}): void {\n try {\n this.editor.transaction(() => {\n run();\n if (options.reconcile !== false) {\n this.mergeDegenerateJunctions();\n }\n });\n } catch (error) {\n this.lastError = toSchematicError(error);\n this.emit();\n throw error;\n }\n this.lastError = undefined;\n this.pruneSelection();\n this.emit();\n }\n\n afterHistoryChange(): void {\n this.lastError = undefined;\n this.pruneSelection();\n this.emit();\n }\n\n /** Records a rejected edit in `state.lastError`, notifies listeners, then rethrows. */\n reject(error: SchematicError): never {\n this.lastError = error;\n this.emit();\n throw error;\n }\n\n undo(): void {\n if (!this.editor.canUndo) {\n return;\n }\n this.editor.undo();\n this.afterHistoryChange();\n }\n\n redo(): void {\n if (!this.editor.canRedo) {\n return;\n }\n this.editor.redo();\n this.afterHistoryChange();\n }\n\n /** Swaps the edited document and clears history, selection and errors. */\n reset(document: SchematicDocument): void {\n this.editor = new SchematicEditor(document, deriveOptions(this.devices, this.tolerance));\n this.selection = [];\n this.lastError = undefined;\n this.#topology = undefined;\n this.placingDevice = undefined;\n this.emit();\n }\n\n inspect(): Inspector {\n return buildInspector(this.editor.document, this.selection, {\n devices: this.devices,\n topology: () => this.topology(),\n });\n }\n\n topology(): SchematicTopology {\n const document = this.editor.document;\n if (this.#topology?.document !== document) {\n this.#topology = {\n document,\n value: deriveSchematicTopology(document, this.options),\n };\n }\n return this.#topology.value;\n }\n\n hitTest(\n point: { readonly x: number; readonly y: number },\n options: HitTestOptions = {},\n ): SchematicHit | undefined {\n return hitTestSchematic(this.editor.document, point, { ...this.options, ...options });\n }\n\n pruneSelection(): void {\n const kept = pruneSelection(this.selection, this.editor.document);\n if (kept !== this.selection) {\n this.selection = kept;\n }\n }\n\n findSymbol(id: string): SchematicSymbol | undefined {\n return this.editor.document.sheet.symbols.find((symbol) => symbol.id === id);\n }\n\n findWire(id: string): SchematicWire | undefined {\n return this.editor.document.sheet.wires.find((wire) => wire.id === id);\n }\n\n /** @throws {SchematicError} when the symbol is unknown. */\n requireSymbol(symbolId: string): SchematicSymbol {\n const symbol = this.findSymbol(symbolId);\n if (symbol === undefined) {\n this.reject(\n new SchematicError([\n {\n severity: 'error',\n code: 'edit/unknown-entity',\n message: `Unknown symbol \"${symbolId}\".`,\n entity: { kind: 'symbol', id: symbolId },\n },\n ]),\n );\n }\n return symbol;\n }\n\n /** Device outline in symbol-local coordinates, used as the reference-designator default. */\n outlineOf(\n symbol: SchematicSymbol,\n ): { x: number; y: number; width: number; height: number } | undefined {\n const separator = symbol.device.indexOf(':');\n if (separator <= 0) {\n return undefined;\n }\n return this.devices?.getDeviceSymbol({\n raw: symbol.device,\n packageId: symbol.device.slice(0, separator),\n deviceId: symbol.device.slice(separator + 1),\n })?.bounds;\n }\n\n /** A junction that only splices two collinear wires collapses back into a single wire. */\n mergeDegenerateJunctions(): void {\n for (let pass = 0; pass < MAX_MERGE_PASSES; pass += 1) {\n const junctions = this.editor.document.sheet.junctions;\n let merged = false;\n for (const junction of junctions) {\n const result = mergeWiresAtJunction(this.editor.document, junction.id, {\n ...deriveOptions(undefined, this.tolerance),\n createId: this.createId,\n });\n if (result === undefined) {\n continue;\n }\n this.editor.replace(result.document);\n merged = true;\n break;\n }\n if (!merged) {\n return;\n }\n }\n }\n}\n\n/** Builds provider options without `undefined` values (`exactOptionalPropertyTypes`). */\nexport function deriveOptions(\n devices: DeviceSymbolProvider | undefined,\n tolerance: number | undefined,\n): { devices?: DeviceSymbolProvider; tolerance?: number } {\n const options: { devices?: DeviceSymbolProvider; tolerance?: number } = {};\n if (devices !== undefined) {\n options.devices = devices;\n }\n if (tolerance !== undefined) {\n options.tolerance = tolerance;\n }\n return options;\n}\n\nexport function toSchematicError(error: unknown): SchematicError {\n if (error instanceof SchematicError) {\n return error;\n }\n const message = error instanceof Error ? error.message : String(error);\n const diagnostics: readonly Diagnostic[] = [\n { severity: 'error', code: 'edit/invalid-command', message },\n ];\n return new SchematicError(diagnostics);\n}\n","import {\n SchematicError,\n joinJunctionAt,\n planJunctionRelease,\n planSegmentDrag,\n pointOnPolyline,\n samePoint,\n splitWireAt,\n type Point,\n} from '@mica-js/core/schematic';\nimport type { EditorSession } from './session';\n\n/**\n * Appends a wire. Endpoints that land inside another wire split it and create a junction, and\n * endpoints that land on an existing junction join it, so the new wire is electrically connected.\n */\nexport function addWire(session: EditorSession, points: readonly Point[]): void {\n if (points.length < 2) {\n session.reject(\n new SchematicError([\n { severity: 'error', code: 'wire/invalid-points', message: 'A wire needs two points.' },\n ]),\n );\n }\n session.mutate(\n () => {\n const id = session.createId('wire', session.document);\n session.editor.dispatch({ type: 'add-wire', id, points });\n for (const point of [points[0], points[points.length - 1]]) {\n if (point === undefined) {\n continue;\n }\n const host = hitTestWire(session, point, id);\n if (host !== undefined) {\n splitInto(session, id, host.wireId, point);\n continue;\n }\n const join = joinJunctionAt(session.document, id, point);\n if (join !== undefined) {\n session.editor.dispatch({ type: 'update-junction', id: join.id, wires: join.wires });\n }\n }\n },\n { reconcile: false },\n );\n}\n\n/** Splits `wireId` at `point` and creates a junction there. */\nexport function connectWireAt(\n session: EditorSession,\n wireId: string,\n point: Point,\n otherWireId?: string,\n): string {\n let junctionId = '';\n session.mutate(\n () => {\n junctionId = splitInto(session, otherWireId, wireId, point, { strict: true });\n },\n { reconcile: false },\n );\n return junctionId;\n}\n\n/**\n * Slides one wire segment by `delta` along its normal. The whole run of segments parallel to it\n * moves along; junctions left behind on the old geometry let go of this wire.\n */\nexport function moveWireSegment(\n session: EditorSession,\n wireId: string,\n segment: number,\n delta: Point,\n): void {\n const points = previewWireSegment(session, wireId, segment, delta);\n if (points === undefined) {\n return;\n }\n session.mutate(() => {\n for (const release of planJunctionRelease(session.document, wireId, points)) {\n session.editor.dispatch(\n release.wires === undefined\n ? { type: 'remove-junction', id: release.id }\n : { type: 'update-junction', id: release.id, wires: release.wires },\n );\n }\n session.editor.dispatch({ type: 'set-wire-points', id: wireId, points });\n });\n}\n\n/** Wire points a segment drag would produce; the renderer previews them before the commit. */\nexport function previewWireSegment(\n session: EditorSession,\n wireId: string,\n segment: number,\n delta: Point,\n): readonly Point[] | undefined {\n return planSegmentDrag(session.document, wireId, segment, delta, session.options);\n}\n\n/** Removes a wire while keeping its junctions for the merge pass to collapse. */\nexport function removeWire(session: EditorSession, wireId: string): void {\n const attached = session.document.sheet.junctions.filter((junction) =>\n junction.wires.includes(wireId),\n );\n for (const junction of attached) {\n const remaining = junction.wires.filter((id) => id !== wireId);\n if (remaining.length >= 2) {\n session.editor.dispatch({ type: 'update-junction', id: junction.id, wires: remaining });\n } else {\n session.editor.dispatch({ type: 'remove-junction', id: junction.id });\n }\n }\n session.editor.dispatch({ type: 'remove-wire', id: wireId });\n}\n\n/** Wire whose interior (not its ends) passes through `point`, excluding `excludeWireId`. */\nfunction hitTestWire(\n session: EditorSession,\n point: Point,\n excludeWireId: string,\n): { wireId: string } | undefined {\n // Scanned directly instead of through `hitTest`: the point sits on both the new wire and the\n // host, and which one a plain hit reports depends on element order.\n for (const wire of session.document.sheet.wires) {\n if (wire.id === excludeWireId || !pointOnPolyline(wire.points, point, session.tolerance ?? 0)) {\n continue;\n }\n const [first, last] = [wire.points[0], wire.points[wire.points.length - 1]];\n if (first === undefined || last === undefined) {\n continue;\n }\n if (samePoint(first, point) || samePoint(last, point)) {\n continue;\n }\n return { wireId: wire.id };\n }\n return undefined;\n}\n\n/** Splits `hostWireId` at `point` and joins `newWireId` to the junction it creates. */\nfunction splitInto(\n session: EditorSession,\n newWireId: string | undefined,\n hostWireId: string,\n point: Point,\n options: { strict?: boolean } = {},\n): string {\n const document = session.document;\n if (!options.strict) {\n const wire = session.findWire(hostWireId);\n const [first, last] = [wire?.points[0], wire?.points[wire.points.length - 1]];\n if (\n wire === undefined ||\n first === undefined ||\n last === undefined ||\n samePoint(first, point) ||\n samePoint(last, point)\n ) {\n return '';\n }\n }\n const split = splitWireAt(document, hostWireId, point, {\n ...(session.tolerance === undefined ? {} : { tolerance: session.tolerance }),\n createId: session.createId,\n });\n const junctionId = session.createId('junction', split.document);\n const wires = [split.firstWireId, split.secondWireId];\n if (newWireId !== undefined && newWireId.length > 0 && !wires.includes(newWireId)) {\n wires.push(newWireId);\n }\n const junctions = [\n ...split.document.sheet.junctions,\n { id: junctionId, x: point.x, y: point.y, wires },\n ];\n session.editor.replace({\n ...split.document,\n sheet: { ...split.document.sheet, junctions },\n });\n return junctionId;\n}\n","import {\n SchematicError,\n designatorOf,\n hasDesignator,\n namesNet,\n netNameOf,\n parseDeviceReference,\n previewSymbolDrag,\n referenceAnchor,\n rotatePoint,\n symbolRole,\n type Point,\n type PropertyValue,\n type SchematicSymbol,\n} from '@mica-js/core/schematic';\nimport type { EditorSession } from './session';\nimport { removeWire } from './wires';\n\n/** Arms placement of `device`: the next canvas click inserts it and disarms again. */\nexport function placeDevice(session: EditorSession, device: string): void {\n if (parseDeviceReference(device) === undefined) {\n session.reject(\n new SchematicError([\n {\n severity: 'error',\n code: 'device/invalid-reference',\n message: `Invalid device reference ${JSON.stringify(device)}.`,\n },\n ]),\n );\n }\n session.placingDevice = device;\n session.tool = 'select';\n session.emit();\n}\n\nexport function cancelPlacement(session: EditorSession): void {\n if (session.placingDevice === undefined) {\n return;\n }\n session.placingDevice = undefined;\n session.emit();\n}\n\n/** Reference designator the next placed component gets, per the host's policy. */\nexport function nextDesignator(session: EditorSession, device: string): string {\n return session.createDesignator(device, session.document);\n}\n\nexport function moveSelectionBy(session: EditorSession, dx: number, dy: number): void {\n if (session.selection.length === 0 || (dx === 0 && dy === 0)) {\n return;\n }\n session.mutate(() => {\n for (const item of session.selection) {\n switch (item.kind) {\n case 'symbol': {\n const symbol = session.findSymbol(item.id);\n if (symbol !== undefined) {\n repositionSymbol(session, symbol, { ...symbol, x: symbol.x + dx, y: symbol.y + dy });\n }\n break;\n }\n case 'vertex': {\n const wire = session.findWire(item.wireId);\n const target = wire?.points[item.index];\n if (wire !== undefined && target !== undefined) {\n session.editor.dispatch({\n type: 'set-wire-points',\n id: wire.id,\n points: wire.points.map((point, index) =>\n index === item.index ? { x: point.x + dx, y: point.y + dy } : point,\n ),\n });\n }\n break;\n }\n case 'reference':\n moveReferenceBy(session, item.symbolId, dx, dy);\n break;\n case 'junction':\n // Junctions are derived from wire geometry; moving one would break orthogonality.\n break;\n default:\n break;\n }\n }\n });\n}\n\nexport function rotateSelection(session: EditorSession, degrees: number): void {\n if (session.selection.length === 0 || degrees === 0) {\n return;\n }\n session.mutate(() => {\n for (const item of session.selection) {\n if (item.kind !== 'symbol') {\n continue;\n }\n const symbol = session.findSymbol(item.id);\n if (symbol === undefined) {\n continue;\n }\n repositionSymbol(session, symbol, {\n ...symbol,\n rotation: normalizeRotation(symbol.rotation + degrees),\n });\n }\n });\n}\n\n/**\n * Replaces a symbol's placement and drags everything anchored to its pins: wire ends keep\n * orthogonal routing, junctions and attached builtin anchors follow.\n */\nexport function repositionSymbol(\n session: EditorSession,\n symbol: SchematicSymbol,\n next: SchematicSymbol,\n): void {\n const document = session.document;\n const preview = previewSymbolDrag(document, session.devices, symbol.id, next);\n if (preview === undefined) {\n return;\n }\n const symbols = document.sheet.symbols.map((item) => {\n if (item.id === symbol.id) {\n return next;\n }\n const target = preview.symbols.get(item.id);\n return target === undefined ? item : { ...item, x: target.x, y: target.y };\n });\n const wires = document.sheet.wires.map((wire) => {\n const points = preview.wires.get(wire.id);\n return points === undefined ? wire : { ...wire, points };\n });\n const junctions = document.sheet.junctions.map((junction) => {\n const target = preview.junctions.get(junction.id);\n return target === undefined ? junction : { ...junction, x: target.x, y: target.y };\n });\n\n session.editor.replace({\n ...document,\n sheet: { ...document.sheet, symbols, wires, junctions },\n });\n}\n\nexport function deleteSelection(session: EditorSession): void {\n if (session.selection.length === 0) {\n return;\n }\n session.mutate(() => {\n for (const item of session.selection) {\n switch (item.kind) {\n case 'symbol':\n session.editor.dispatch({ type: 'remove-symbol', id: item.id });\n break;\n case 'wire':\n removeWire(session, item.id);\n break;\n case 'junction':\n session.editor.dispatch({ type: 'remove-junction', id: item.id });\n break;\n case 'vertex': {\n const wire = session.findWire(item.wireId);\n if (wire === undefined) {\n break;\n }\n const points = wire.points.filter((_, index) => index !== item.index);\n if (points.length < 2) {\n removeWire(session, wire.id);\n } else {\n session.editor.dispatch({ type: 'set-wire-points', id: wire.id, points });\n }\n break;\n }\n default:\n break;\n }\n }\n session.selection = [];\n });\n}\n\n/** Moves a reference designator by a world-space delta; the offset is stored locally. */\nexport function moveReferenceBy(\n session: EditorSession,\n symbolId: string,\n dx: number,\n dy: number,\n): void {\n const symbol = session.findSymbol(symbolId);\n if (symbol === undefined || (dx === 0 && dy === 0)) {\n return;\n }\n session.mutate(() => {\n const anchor = referenceAnchor(session.outlineOf(symbol), symbol.reference);\n // Offsets live in symbol-local space, so undo the rotation before moving.\n const local = rotatePoint({ x: dx, y: dy }, -symbol.rotation);\n session.editor.dispatch({\n type: 'update-symbol',\n id: symbol.id,\n reference: { x: anchor.x + local.x, y: anchor.y + local.y },\n });\n });\n}\n\nexport function setSymbolProperty(\n session: EditorSession,\n symbolId: string,\n key: string,\n value: PropertyValue,\n): void {\n session.mutate(() => {\n session.editor.dispatch({ type: 'set-symbol-property', id: symbolId, key, value });\n });\n}\n\nexport function removeSymbolProperty(session: EditorSession, symbolId: string, key: string): void {\n session.mutate(() => {\n session.editor.dispatch({ type: 'remove-symbol-property', id: symbolId, key });\n });\n}\n\n/**\n * Sets a component's reference designator. The symbol id stays untouched, so selections and\n * Stable ids keep references pointing at the same element.\n */\nexport function renameDesignator(\n session: EditorSession,\n symbolId: string,\n nextDesignator: string,\n): void {\n const trimmed = nextDesignator.trim();\n const symbol = session.requireSymbol(symbolId);\n const role = symbolRole(symbol.device);\n if (!hasDesignator(role)) {\n session.reject(\n new SchematicError([\n {\n severity: 'error',\n code: 'symbol/unsupported-field',\n message: `Symbols of role \"${role}\" carry no reference designator.`,\n entity: { kind: 'symbol', id: symbolId },\n },\n ]),\n );\n }\n if (trimmed.length === 0) {\n session.reject(\n new SchematicError([\n {\n severity: 'error',\n code: 'schema/invalid-value',\n message: 'Reference designator must not be empty.',\n },\n ]),\n );\n }\n if (trimmed === designatorOf(symbol)) {\n return;\n }\n const duplicate = session.document.sheet.symbols.find(\n (candidate) => candidate.id !== symbolId && designatorOf(candidate) === trimmed,\n );\n if (duplicate !== undefined) {\n session.reject(\n new SchematicError([\n {\n severity: 'error',\n code: 'symbol/designator-duplicate',\n message: `Reference designator ${JSON.stringify(trimmed)} is already used.`,\n entity: { kind: 'symbol', id: duplicate.id },\n },\n ]),\n );\n }\n session.mutate(() => {\n session.editor.dispatch({ type: 'update-symbol', id: symbolId, designator: trimmed });\n });\n}\n\n/**\n * Sets the net name of a label / power / ground symbol. Same-named ports are one net, so\n * duplicates are allowed.\n */\nexport function renameNet(session: EditorSession, symbolId: string, nextNet: string): void {\n const trimmed = nextNet.trim();\n const symbol = session.requireSymbol(symbolId);\n const role = symbolRole(symbol.device);\n if (!namesNet(role)) {\n session.reject(\n new SchematicError([\n {\n severity: 'error',\n code: 'symbol/unsupported-field',\n message: `Symbols of role \"${role}\" name no net.`,\n entity: { kind: 'symbol', id: symbolId },\n },\n ]),\n );\n }\n if (trimmed.length === 0) {\n session.reject(\n new SchematicError([\n {\n severity: 'error',\n code: 'schema/invalid-value',\n message: 'Net name must not be empty.',\n },\n ]),\n );\n }\n if (trimmed === netNameOf(symbol)) {\n return;\n }\n session.mutate(() => {\n session.editor.dispatch({ type: 'update-symbol', id: symbolId, net: trimmed });\n });\n}\n\nfunction normalizeRotation(degrees: number): number {\n return ((degrees % 360) + 360) % 360;\n}\n\nexport type { Point };\n","import type {\n HitTestOptions,\n SchematicCommand,\n SchematicDocument,\n SchematicHit,\n SchematicTopology,\n} from '@mica-js/core/schematic';\nimport type { PropertyValue } from '@mica-js/core/schematic';\nimport { EditorSession, type EditorSessionOptions } from './session';\nimport * as symbols from './symbols';\nimport * as wires from './wires';\nimport type {\n DisplayOptions,\n EditorRenderState,\n EditorSelection,\n EditorState,\n EditorTool,\n Inspector,\n} from './types';\n\nexport type SchematicEditorControllerOptions = EditorSessionOptions;\n\n/**\n * Editing state without any DOM dependency: selection, tool, undo history and the derived data\n * the UI needs. It is a façade over {@link EditorSession} (state + mutation plumbing) and the\n * action modules `symbols.ts` / `wires.ts`; every mutation flows through `applySchematicCommand`.\n */\nexport class SchematicEditorController {\n readonly #session: EditorSession;\n\n constructor(options: SchematicEditorControllerOptions) {\n this.#session = new EditorSession(options);\n }\n\n get state(): EditorState {\n return this.#session.state();\n }\n\n /** Everything the canvas draws from; never builds the inspector. */\n get renderState(): EditorRenderState {\n return this.#session.renderState();\n }\n\n get document(): SchematicDocument {\n return this.#session.document;\n }\n\n get selection(): readonly EditorSelection[] {\n return this.#session.selection;\n }\n\n get tool(): EditorTool {\n return this.#session.tool;\n }\n\n get display(): DisplayOptions {\n return this.#session.display;\n }\n\n get canUndo(): boolean {\n return this.#session.editor.canUndo;\n }\n\n get canRedo(): boolean {\n return this.#session.editor.canRedo;\n }\n\n /** Device armed for placement by the host's device list; `undefined` when idle. */\n get placingDevice(): string | undefined {\n return this.#session.placingDevice;\n }\n\n setTool(tool: EditorTool): void {\n if (this.#session.tool === tool && this.#session.placingDevice === undefined) {\n return;\n }\n this.#session.tool = tool;\n this.#session.placingDevice = undefined;\n this.#session.emit();\n }\n\n setSelection(selection: readonly EditorSelection[]): void {\n this.#session.selection = selection;\n this.#session.pruneSelection();\n this.#session.emit();\n }\n\n setDisplayOptions(patch: Partial<DisplayOptions>): void {\n this.#session.display = { ...this.#session.display, ...patch };\n this.#session.emit();\n }\n\n /** Swaps the edited document and clears history, selection and errors. */\n reset(document: SchematicDocument): void {\n this.#session.reset(document);\n }\n\n /** @throws {SchematicError} leaving document, history and selection untouched. */\n dispatch(command: SchematicCommand): void {\n this.#session.mutate(() => {\n this.#session.editor.dispatch(command);\n });\n }\n\n /**\n * Swaps the whole document as one undoable edit, so a host can reload a file without losing\n * the history it already has.\n */\n replace(document: SchematicDocument): void {\n this.#session.mutate(() => {\n this.#session.editor.replace(document);\n });\n }\n\n /** Runs several edits as one history step; a failure rolls all of them back. */\n transaction(run: () => void): void {\n this.#session.mutate(run);\n }\n\n undo(): void {\n this.#session.undo();\n }\n\n redo(): void {\n this.#session.redo();\n }\n\n /** Arms placement of `device`: the next canvas click inserts it and disarms again. */\n placeDevice(device: string): void {\n symbols.placeDevice(this.#session, device);\n }\n\n cancelPlacement(): void {\n symbols.cancelPlacement(this.#session);\n }\n\n /** Reference designator the next placed component gets, per the host's policy. */\n nextDesignator(device: string): string {\n return symbols.nextDesignator(this.#session, device);\n }\n\n moveSelectionBy(dx: number, dy: number): void {\n symbols.moveSelectionBy(this.#session, dx, dy);\n }\n\n rotateSelection(degrees: number): void {\n symbols.rotateSelection(this.#session, degrees);\n }\n\n deleteSelection(): void {\n symbols.deleteSelection(this.#session);\n }\n\n moveReferenceBy(symbolId: string, dx: number, dy: number): void {\n symbols.moveReferenceBy(this.#session, symbolId, dx, dy);\n }\n\n setSymbolProperty(symbolId: string, key: string, value: PropertyValue): void {\n symbols.setSymbolProperty(this.#session, symbolId, key, value);\n }\n\n removeSymbolProperty(symbolId: string, key: string): void {\n symbols.removeSymbolProperty(this.#session, symbolId, key);\n }\n\n renameDesignator(symbolId: string, nextDesignator: string): void {\n symbols.renameDesignator(this.#session, symbolId, nextDesignator);\n }\n\n renameNet(symbolId: string, nextNet: string): void {\n symbols.renameNet(this.#session, symbolId, nextNet);\n }\n\n addWire(points: readonly { readonly x: number; readonly y: number }[]): void {\n wires.addWire(this.#session, points);\n }\n\n connectWireAt(\n wireId: string,\n point: { readonly x: number; readonly y: number },\n otherWireId?: string,\n ): string {\n return wires.connectWireAt(this.#session, wireId, point, otherWireId);\n }\n\n moveWireSegment(\n wireId: string,\n segment: number,\n delta: { readonly x: number; readonly y: number },\n ): void {\n wires.moveWireSegment(this.#session, wireId, segment, delta);\n }\n\n previewWireSegment(\n wireId: string,\n segment: number,\n delta: { readonly x: number; readonly y: number },\n ): readonly { readonly x: number; readonly y: number }[] | undefined {\n return wires.previewWireSegment(this.#session, wireId, segment, delta);\n }\n\n inspect(): Inspector {\n return this.#session.inspect();\n }\n\n topology(): SchematicTopology {\n return this.#session.topology();\n }\n\n hitTest(\n point: { readonly x: number; readonly y: number },\n options: HitTestOptions = {},\n ): SchematicHit | undefined {\n return this.#session.hitTest(point, options);\n }\n\n subscribe(listener: (state: EditorState) => void): () => void {\n return this.#session.subscribe(listener);\n }\n}\n","/** Any CSS color string; Canvas and CSS parse it. */\nexport type ThemeColor = string;\n\n/**\n * Rendering and chrome tokens. The renderer never hard-codes colors: every visible\n * value comes from a theme.\n */\nexport interface SchematicTheme {\n background: ThemeColor;\n grid: ThemeColor;\n gridMajor: ThemeColor;\n\n wire: ThemeColor;\n wireSelected: ThemeColor;\n junction: ThemeColor;\n junctionSelected: ThemeColor;\n pendingWire: ThemeColor;\n\n symbolFill: ThemeColor;\n symbolStroke: ThemeColor;\n symbolText: ThemeColor;\n symbolPlaceholder: ThemeColor;\n pin: ThemeColor;\n pinText: ThemeColor;\n pinOpen: ThemeColor;\n\n labelAnchor: ThemeColor;\n labelText: ThemeColor;\n\n selection: ThemeColor;\n hover: ThemeColor;\n\n uiBackground: ThemeColor;\n uiSurface: ThemeColor;\n uiBorder: ThemeColor;\n uiText: ThemeColor;\n uiMutedText: ThemeColor;\n uiAccent: ThemeColor;\n uiAccentText: ThemeColor;\n focusRing: ThemeColor;\n\n fontFamily: string;\n fontSize: number;\n /** Pin name text; smaller than `fontSize` so labels stay inside the body. */\n pinFontSize: number;\n /** Device name drawn in the symbol centre. */\n symbolFontSize: number;\n gridSize: number;\n}\n\n/**\n * Default dark theme: neutral greys on near-black, matching the reference palette\n * (background `#0a0a0a`, foreground `#fafafa`, muted `#a1a1a1`, ring `#737373`).\n */\nexport const DARK_SCHEMATIC_THEME: SchematicTheme = {\n background: '#0a0a0a',\n grid: 'rgba(250, 250, 250, 0.06)',\n gridMajor: 'rgba(250, 250, 250, 0.12)',\n\n wire: '#a1a1a1',\n wireSelected: '#fafafa',\n junction: '#e5e5e5',\n junctionSelected: '#fafafa',\n pendingWire: '#fafafa',\n\n symbolFill: '#171717',\n symbolStroke: '#737373',\n /** Device name in the symbol centre: quiet until the symbol is hovered or selected. */\n symbolText: '#a1a1a1',\n symbolPlaceholder: 'rgba(250, 250, 250, 0.28)',\n pin: '#737373',\n pinText: '#a1a1a1',\n pinOpen: '#e5e5e5',\n\n labelAnchor: '#737373',\n labelText: '#a1a1a1',\n\n selection: '#fafafa',\n hover: '#a1a1a1',\n\n uiBackground: '#0a0a0a',\n uiSurface: '#171717',\n uiBorder: 'rgba(250, 250, 250, 0.1)',\n uiText: '#fafafa',\n uiMutedText: '#a1a1a1',\n uiAccent: '#e5e5e5',\n uiAccentText: '#171717',\n focusRing: '#737373',\n\n fontFamily: 'ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif',\n fontSize: 9,\n pinFontSize: 7,\n symbolFontSize: 9,\n gridSize: 10,\n};\n\nexport const LIGHT_SCHEMATIC_THEME: SchematicTheme = {\n background: '#ffffff',\n grid: 'rgba(10, 10, 10, 0.05)',\n gridMajor: 'rgba(10, 10, 10, 0.1)',\n\n wire: '#525252',\n wireSelected: '#0a0a0a',\n junction: '#262626',\n junctionSelected: '#0a0a0a',\n pendingWire: '#0a0a0a',\n\n symbolFill: '#fafafa',\n symbolStroke: '#a1a1a1',\n /** Device name in the symbol centre: quiet until the symbol is hovered or selected. */\n symbolText: '#525252',\n symbolPlaceholder: 'rgba(10, 10, 10, 0.3)',\n pin: '#a1a1a1',\n pinText: '#525252',\n pinOpen: '#262626',\n\n labelAnchor: '#a1a1a1',\n labelText: '#525252',\n\n selection: '#0a0a0a',\n hover: '#525252',\n\n uiBackground: '#ffffff',\n uiSurface: '#f5f5f5',\n uiBorder: 'rgba(10, 10, 10, 0.1)',\n uiText: '#0a0a0a',\n uiMutedText: '#525252',\n uiAccent: '#171717',\n uiAccentText: '#fafafa',\n focusRing: '#a1a1a1',\n\n fontFamily: DARK_SCHEMATIC_THEME.fontFamily,\n fontSize: DARK_SCHEMATIC_THEME.fontSize,\n pinFontSize: DARK_SCHEMATIC_THEME.pinFontSize,\n symbolFontSize: DARK_SCHEMATIC_THEME.symbolFontSize,\n gridSize: DARK_SCHEMATIC_THEME.gridSize,\n};\n\n/** Merges overrides onto the dark baseline, so partial themes stay readable. */\nexport function resolveSchematicTheme(overrides: Partial<SchematicTheme> = {}): SchematicTheme {\n const resolved: SchematicTheme = { ...DARK_SCHEMATIC_THEME };\n for (const key of Object.keys(overrides) as (keyof SchematicTheme)[]) {\n const value = overrides[key];\n if (value !== undefined) {\n Object.assign(resolved, { [key]: value });\n }\n }\n return resolved;\n}\n\n/** Maps the theme onto `--mica-schematic-*` CSS variables for light-DOM chrome. */\nexport function themeToCssVariables(theme: SchematicTheme): Readonly<Record<string, string>> {\n const variables: Record<string, string> = {};\n for (const [key, value] of Object.entries(theme)) {\n variables[`--mica-schematic-${kebabCase(key)}`] = String(value);\n }\n return variables;\n}\n\nfunction kebabCase(value: string): string {\n return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n}\n","import type { Point, Rect } from '@mica-js/core/schematic';\n\nexport interface ViewportState {\n readonly scale: number;\n readonly offsetX: number;\n readonly offsetY: number;\n}\n\nexport interface ViewportLimits {\n readonly minScale: number;\n readonly maxScale: number;\n}\n\nexport const DEFAULT_VIEWPORT_LIMITS: ViewportLimits = { minScale: 0.25, maxScale: 4 };\n\n/** Merges partial overrides onto the defaults; rejects non-positive and inverted ranges. */\nexport function resolveViewportLimits(limits?: Partial<ViewportLimits>): ViewportLimits {\n const minScale = limits?.minScale;\n const maxScale = limits?.maxScale;\n const resolved: ViewportLimits = {\n minScale:\n minScale !== undefined && Number.isFinite(minScale) && minScale > 0\n ? minScale\n : DEFAULT_VIEWPORT_LIMITS.minScale,\n maxScale:\n maxScale !== undefined && Number.isFinite(maxScale) && maxScale > 0\n ? maxScale\n : DEFAULT_VIEWPORT_LIMITS.maxScale,\n };\n if (resolved.minScale > resolved.maxScale) {\n return { minScale: resolved.maxScale, maxScale: resolved.minScale };\n }\n return resolved;\n}\n\nexport const IDENTITY_VIEWPORT: ViewportState = { scale: 1, offsetX: 0, offsetY: 0 };\n\nexport function screenToPage(viewport: ViewportState, point: Point): Point {\n return {\n x: (point.x - viewport.offsetX) / viewport.scale,\n y: (point.y - viewport.offsetY) / viewport.scale,\n };\n}\n\nexport function pageToScreen(viewport: ViewportState, point: Point): Point {\n return {\n x: point.x * viewport.scale + viewport.offsetX,\n y: point.y * viewport.scale + viewport.offsetY,\n };\n}\n\nexport function clampScale(\n scale: number,\n limits: ViewportLimits = DEFAULT_VIEWPORT_LIMITS,\n): number {\n return Math.min(limits.maxScale, Math.max(limits.minScale, scale));\n}\n\n/**\n * Clamps a viewport to `limits` while keeping the page point at the centre of `size` in place,\n * so restoring a saved view can never jump the content off screen.\n */\nexport function clampViewport(\n viewport: ViewportState,\n size: { readonly width: number; readonly height: number },\n limits: ViewportLimits = DEFAULT_VIEWPORT_LIMITS,\n): ViewportState {\n const scale = clampScale(\n Number.isFinite(viewport.scale) && viewport.scale > 0 ? viewport.scale : limits.minScale,\n limits,\n );\n if (scale === viewport.scale) {\n return viewport;\n }\n const center = { x: size.width / 2, y: size.height / 2 };\n const anchor = screenToPage(viewport, center);\n return {\n scale,\n offsetX: center.x - anchor.x * scale,\n offsetY: center.y - anchor.y * scale,\n };\n}\n\n/** Zooms around a screen-space point so the page point under the cursor stays fixed. */ export function zoomAt(\n viewport: ViewportState,\n screenPoint: Point,\n factor: number,\n limits: ViewportLimits = DEFAULT_VIEWPORT_LIMITS,\n): ViewportState {\n const scale = clampScale(viewport.scale * factor, limits);\n if (scale === viewport.scale) {\n return viewport;\n }\n const anchor = screenToPage(viewport, screenPoint);\n return {\n scale,\n offsetX: screenPoint.x - anchor.x * scale,\n offsetY: screenPoint.y - anchor.y * scale,\n };\n}\n\nexport function panBy(viewport: ViewportState, dx: number, dy: number): ViewportState {\n return { ...viewport, offsetX: viewport.offsetX + dx, offsetY: viewport.offsetY + dy };\n}\n\n/** Fits `bounds` into `size` with padding, centering the content. */\nexport function fitBounds(\n bounds: Rect,\n size: { readonly width: number; readonly height: number },\n padding = 32,\n limits: ViewportLimits = DEFAULT_VIEWPORT_LIMITS,\n): ViewportState {\n const availableWidth = Math.max(1, size.width - padding * 2);\n const availableHeight = Math.max(1, size.height - padding * 2);\n const width = Math.max(bounds.width, 1e-6);\n const height = Math.max(bounds.height, 1e-6);\n const scale = clampScale(Math.min(availableWidth / width, availableHeight / height), limits);\n const centerX = bounds.x + bounds.width / 2;\n const centerY = bounds.y + bounds.height / 2;\n return {\n scale,\n offsetX: size.width / 2 - centerX * scale,\n offsetY: size.height / 2 - centerY * scale,\n };\n}\n","import type { Point } from '@mica-js/core/schematic';\nimport type { SchematicScene, SceneItem } from './scene';\nimport { resolveSchematicTheme, type SchematicTheme } from './theme';\nimport { pageToScreen, type ViewportState } from './viewport';\n\nexport interface CanvasRendererOptions {\n readonly theme?: Partial<SchematicTheme>;\n}\n\nconst MAJOR_GRID_INTERVAL = 5;\n/** Sub-grid lines are hidden once they get closer together than this (CSS pixels). */\nconst MIN_GRID_PIXELS = 4;\n/** Emphasised lines are stretched to stay at least this far apart (CSS pixels). */\nconst MIN_MAJOR_GRID_PIXELS = 20;\n\n/** Draws a {@link SchematicScene} onto a canvas, honoring device pixel ratio. */\nexport class CanvasSchematicRenderer {\n #canvas: HTMLCanvasElement;\n #context: CanvasRenderingContext2D | null;\n #theme: SchematicTheme;\n #width = 0;\n #height = 0;\n #pixelRatio = 1;\n\n constructor(canvas: HTMLCanvasElement, options: CanvasRendererOptions = {}) {\n this.#canvas = canvas;\n this.#context = canvas.getContext('2d');\n this.#theme = resolveSchematicTheme(options.theme);\n }\n\n get theme(): SchematicTheme {\n return this.#theme;\n }\n\n setTheme(theme: SchematicTheme): void {\n this.#theme = theme;\n }\n\n resize(width: number, height: number, pixelRatio = 1): void {\n this.#width = width;\n this.#height = height;\n this.#pixelRatio = pixelRatio;\n // Only the bitmap size is set here; CSS keeps ownership of the display size.\n this.#canvas.width = Math.max(1, Math.round(width * pixelRatio));\n this.#canvas.height = Math.max(1, Math.round(height * pixelRatio));\n }\n\n render(scene: SchematicScene, viewport: ViewportState): void {\n const context = this.#context;\n if (context === null) {\n return;\n }\n context.setTransform(this.#pixelRatio, 0, 0, this.#pixelRatio, 0, 0);\n context.clearRect(0, 0, this.#width, this.#height);\n\n context.fillStyle = scene.background;\n context.fillRect(0, 0, this.#width, this.#height);\n\n if (scene.grid !== undefined) {\n this.#drawGrid(context, scene, viewport);\n }\n\n for (const item of scene.items) {\n this.#drawItem(context, item, viewport);\n }\n }\n\n destroy(): void {\n this.#context = null;\n }\n\n #drawGrid(\n context: CanvasRenderingContext2D,\n scene: SchematicScene,\n viewport: ViewportState,\n ): void {\n const grid = scene.grid;\n if (grid === undefined) {\n return;\n }\n const cell = grid.size * viewport.scale;\n if (!Number.isFinite(cell) || cell <= 0) {\n return;\n }\n // Too fine to read at this zoom: drop subdivisions, then fall back to emphasised lines only.\n let subdivisions = grid.subdivisions;\n while (subdivisions > 1 && cell / subdivisions < MIN_GRID_PIXELS) {\n subdivisions = Math.max(1, Math.round(subdivisions / 2));\n }\n let step = cell / subdivisions;\n if (step < MIN_GRID_PIXELS) {\n step = cell;\n }\n let majorSpacing = cell * MAJOR_GRID_INTERVAL;\n while (majorSpacing < MIN_MAJOR_GRID_PIXELS) {\n majorSpacing *= 2;\n }\n const majorOnly = step < MIN_GRID_PIXELS;\n if (majorOnly) {\n step = majorSpacing;\n }\n\n const origin = pageToScreen(viewport, { x: 0, y: 0 });\n const startX = origin.x - Math.ceil(origin.x / step) * step;\n const startY = origin.y - Math.ceil(origin.y / step) * step;\n\n context.lineWidth = 1;\n for (let x = startX; x <= this.#width; x += step) {\n if (x < 0) {\n continue;\n }\n const major = majorOnly || isMajorGridLine(x - origin.x, majorSpacing);\n context.strokeStyle = major ? grid.major : grid.minor;\n strokeLine(\n context,\n { x: Math.round(x) + 0.5, y: 0 },\n { x: Math.round(x) + 0.5, y: this.#height },\n );\n }\n for (let y = startY; y <= this.#height; y += step) {\n if (y < 0) {\n continue;\n }\n const major = majorOnly || isMajorGridLine(y - origin.y, majorSpacing);\n context.strokeStyle = major ? grid.major : grid.minor;\n strokeLine(\n context,\n { x: 0, y: Math.round(y) + 0.5 },\n { x: this.#width, y: Math.round(y) + 0.5 },\n );\n }\n }\n\n #drawItem(context: CanvasRenderingContext2D, item: SceneItem, viewport: ViewportState): void {\n switch (item.kind) {\n case 'line': {\n context.strokeStyle = item.color;\n context.lineWidth = item.width;\n context.setLineDash(item.dash === undefined ? [] : [...item.dash]);\n strokeLine(context, pageToScreen(viewport, item.from), pageToScreen(viewport, item.to));\n context.setLineDash([]);\n break;\n }\n case 'polyline': {\n context.strokeStyle = item.color;\n context.lineWidth = item.width;\n context.lineJoin = 'round';\n context.lineCap = 'round';\n context.setLineDash(item.dash === undefined ? [] : [...item.dash]);\n context.beginPath();\n item.points.forEach((point, index) => {\n const screen = pageToScreen(viewport, point);\n if (index === 0) {\n context.moveTo(screen.x, screen.y);\n } else {\n context.lineTo(screen.x, screen.y);\n }\n });\n context.stroke();\n context.setLineDash([]);\n break;\n }\n case 'rect': {\n const topLeft = pageToScreen(viewport, { x: item.bounds.x, y: item.bounds.y });\n const width = item.bounds.width * viewport.scale;\n const height = item.bounds.height * viewport.scale;\n context.setLineDash(item.dash === undefined ? [] : [...item.dash]);\n if (item.fill !== undefined) {\n context.fillStyle = item.fill;\n context.fillRect(topLeft.x, topLeft.y, width, height);\n }\n if (item.stroke !== undefined) {\n context.strokeStyle = item.stroke;\n context.lineWidth = item.width;\n context.strokeRect(topLeft.x, topLeft.y, width, height);\n }\n context.setLineDash([]);\n break;\n }\n case 'circle': {\n const center = pageToScreen(viewport, item.center);\n context.beginPath();\n context.arc(\n center.x,\n center.y,\n Math.max(0.5, item.radius * viewport.scale),\n 0,\n Math.PI * 2,\n );\n if (item.fill !== undefined) {\n context.fillStyle = item.fill;\n context.fill();\n }\n if (item.stroke !== undefined) {\n context.strokeStyle = item.stroke;\n context.lineWidth = item.width;\n context.stroke();\n }\n break;\n }\n case 'text': {\n const position = pageToScreen(viewport, item.position);\n context.fillStyle = item.color;\n context.font = scaleFont(item.font, viewport.scale);\n context.textAlign = item.align;\n context.textBaseline = item.baseline;\n if (item.rotation === undefined || item.rotation === 0) {\n context.fillText(item.text, position.x, position.y);\n break;\n }\n context.save();\n context.translate(position.x, position.y);\n context.rotate((item.rotation * Math.PI) / 180);\n context.fillText(item.text, 0, 0);\n context.restore();\n break;\n }\n default:\n break;\n }\n }\n}\n\nfunction strokeLine(context: CanvasRenderingContext2D, from: Point, to: Point): void {\n context.beginPath();\n context.moveTo(from.x, from.y);\n context.lineTo(to.x, to.y);\n context.stroke();\n}\n\nfunction isMajorGridLine(offset: number, spacing: number): boolean {\n if (!Number.isFinite(spacing) || spacing <= 0) {\n return false;\n }\n const remainder = Math.abs(offset % spacing);\n return remainder < 0.5 || spacing - remainder < 0.5;\n}\n\nfunction scaleFont(font: string, scale: number): string {\n const match = /^(\\d+(?:\\.\\d+)?)px(.*)$/.exec(font);\n if (match === null) {\n return font;\n }\n return `${(Number(match[1]) * Math.max(scale, 0.01)).toFixed(1)}px${match[2]}`;\n}\n","import {\n DEFAULT_TEXT_CONTENT,\n builtinSymbolKind,\n designatorOf,\n isTextDevice,\n netNameOf,\n parseDeviceReference,\n pinSide,\n pinStubEnd,\n pinsBounds,\n previewSymbolDrag,\n referencePosition,\n rotatePoint,\n symbolBounds,\n symbolPinPosition,\n textDeviceContent,\n type DeviceSymbolProvider,\n type Placement,\n type Point,\n type Rect,\n type SchematicDocument,\n type SchematicHit,\n type SchematicSymbol,\n} from '@mica-js/core/schematic';\nimport type { SchematicTheme } from './theme';\nexport type SceneTool = 'select' | 'wire' | 'power' | 'ground' | 'label' | 'text';\n\nexport interface SceneSelection {\n readonly symbols?: ReadonlySet<string>;\n readonly wires?: ReadonlySet<string>;\n readonly junctions?: ReadonlySet<string>;\n readonly vertices?: readonly { readonly wireId: string; readonly index: number }[];\n /** Preview offset applied to the selected symbols while dragging. */\n readonly offset?: Point;\n}\n\nexport interface SceneDisplayOptions {\n readonly grid: boolean;\n readonly gridSize?: number;\n /** Visible grid lines per snap cell; `1` draws only the snap grid. */\n readonly gridSubdivisions?: number;\n readonly labels: boolean;\n}\n\nexport type SceneItem =\n | {\n readonly kind: 'line';\n readonly from: Point;\n readonly to: Point;\n readonly color: string;\n readonly width: number;\n readonly dash?: readonly number[];\n }\n | {\n readonly kind: 'polyline';\n readonly points: readonly Point[];\n readonly color: string;\n readonly width: number;\n readonly dash?: readonly number[];\n }\n | {\n readonly kind: 'rect';\n readonly bounds: Rect;\n readonly fill?: string;\n readonly stroke?: string;\n readonly width: number;\n readonly dash?: readonly number[];\n }\n | {\n readonly kind: 'circle';\n readonly center: Point;\n readonly radius: number;\n readonly fill?: string;\n readonly stroke?: string;\n readonly width: number;\n }\n | {\n readonly kind: 'text';\n readonly position: Point;\n readonly text: string;\n readonly color: string;\n readonly align: 'left' | 'center' | 'right';\n readonly baseline: 'top' | 'middle' | 'bottom';\n readonly font: string;\n /** Degrees, clockwise around `position`. */\n readonly rotation?: number;\n };\n\nexport interface SchematicScene {\n readonly background: string;\n readonly grid:\n | {\n readonly size: number;\n /** Minor lines drawn per snap cell; `1` means the cell size is the only step. */\n readonly subdivisions: number;\n readonly minor: string;\n readonly major: string;\n }\n | undefined;\n readonly items: readonly SceneItem[];\n}\n\nexport interface RenderInput {\n readonly document: SchematicDocument;\n readonly devices?: DeviceSymbolProvider;\n readonly theme: SchematicTheme;\n readonly selection?: SceneSelection;\n readonly hover?: SchematicHit;\n readonly tool?: SceneTool;\n readonly display?: SceneDisplayOptions;\n readonly pendingWire?: readonly Point[];\n /** Rubber-band selection rectangle in page units. */\n readonly marquee?: Rect;\n /** Ghost of the symbol the current placement tool would insert. */\n readonly placementPreview?: {\n readonly device: string;\n readonly position: Point;\n readonly rotation: number;\n /** Stub wire the placement will add, e.g. when a label lands on a pin. */\n readonly wire?: readonly Point[];\n };\n /** Reference designator being dragged; drawn at this world position instead. */\n readonly referencePreview?: { readonly symbolId: string; readonly position: Point };\n /** Wire being reshaped by a segment drag; drawn with these points instead of the document's. */\n readonly wirePreview?: { readonly wireId: string; readonly points: readonly Point[] };\n}\n\nconst WIRE_WIDTH = 1.5;\nconst SELECTED_WIDTH = 2.5;\nconst JUNCTION_RADIUS = 3;\nconst VERTEX_SIZE = 5;\n\n/** Visible grid lines per snap cell; anything unset or invalid falls back to the snap grid. */\nfunction gridSubdivisions(value: number | undefined): number {\n return value !== undefined && Number.isFinite(value) && value >= 1 ? Math.round(value) : 1;\n}\n\ninterface TextPlacement {\n readonly align: 'left' | 'center' | 'right';\n readonly baseline: 'top' | 'middle' | 'bottom';\n readonly rotation: number;\n}\n\nconst ALIGN_MIRROR: Readonly<Record<TextPlacement['align'], TextPlacement['align']>> = {\n left: 'right',\n center: 'center',\n right: 'left',\n};\n\nconst BASELINE_MIRROR: Readonly<Record<TextPlacement['baseline'], TextPlacement['baseline']>> = {\n top: 'bottom',\n middle: 'middle',\n bottom: 'top',\n};\n\n/**\n * Text turns with the symbol, except at half turns where it would read upside down: those flip\n * back and mirror the anchor alignment so the glyphs stay on the same side of the anchor.\n */\nfunction uprightText(\n rotation: number,\n align: TextPlacement['align'],\n baseline: TextPlacement['baseline'],\n): TextPlacement {\n const normalized = (((rotation % 360) + 540) % 360) - 180;\n if (Math.abs(normalized) === 180) {\n return { align: ALIGN_MIRROR[align], baseline: BASELINE_MIRROR[baseline], rotation: 0 };\n }\n return { align, baseline, rotation: normalized };\n}\n\ninterface PreviewDrag {\n readonly wires: ReadonlyMap<string, readonly Point[]>;\n readonly junctions: ReadonlyMap<string, Point>;\n readonly symbols: ReadonlyMap<string, Point>;\n}\n\nconst NO_PREVIEW: PreviewDrag = { wires: new Map(), junctions: new Map(), symbols: new Map() };\n\n/** Live preview of the dragged symbols: wires, junctions and anchors follow their pins. */\nfunction previewDrag(\n document: SchematicDocument,\n devices: DeviceSymbolProvider | undefined,\n selection: SceneSelection,\n): PreviewDrag {\n const offset = selection.offset;\n if (offset === undefined || selection.symbols === undefined) {\n return NO_PREVIEW;\n }\n const wires = new Map<string, readonly Point[]>();\n const junctions = new Map<string, Point>();\n const symbols = new Map<string, Point>();\n for (const symbol of document.sheet.symbols) {\n if (!selection.symbols.has(symbol.id)) {\n continue;\n }\n const placed = { x: symbol.x, y: symbol.y, rotation: symbol.rotation };\n const preview = previewSymbolDrag(document, devices, symbol.id, {\n ...placed,\n x: placed.x + offset.x,\n y: placed.y + offset.y,\n });\n if (preview === undefined) {\n continue;\n }\n for (const [id, points] of preview.wires) {\n wires.set(id, points);\n }\n for (const [id, point] of preview.junctions) {\n junctions.set(id, point);\n }\n for (const [id, point] of preview.symbols) {\n symbols.set(id, point);\n }\n symbols.set(symbol.id, { x: placed.x + offset.x, y: placed.y + offset.y });\n }\n return { wires, junctions, symbols };\n}\n\n/** Builds a flat, drawable scene. Every color comes from `theme`. */\nexport function buildSchematicScene(input: RenderInput): SchematicScene {\n const { document, devices, theme } = input;\n const selection = input.selection ?? {};\n const tool = input.tool ?? 'select';\n const display = input.display ?? { grid: true, labels: true };\n const font = `${theme.fontSize}px ${theme.fontFamily}`;\n const pinFont = `${theme.pinFontSize}px ${theme.fontFamily}`;\n const symbolFont = `${theme.symbolFontSize}px ${theme.fontFamily}`;\n const items: SceneItem[] = [];\n const drag = previewDrag(document, devices, selection);\n\n for (const wire of document.sheet.wires) {\n const selected = selection.wires?.has(wire.id) ?? false;\n const hovered = input.hover?.kind === 'wire' && input.hover.id === wire.id;\n const preview = input.wirePreview;\n const points =\n preview !== undefined && preview.wireId === wire.id\n ? preview.points\n : (drag.wires.get(wire.id) ?? wire.points);\n items.push({\n kind: 'polyline',\n points,\n color: selected ? theme.wireSelected : hovered ? theme.hover : theme.wire,\n width: selected ? SELECTED_WIDTH : WIRE_WIDTH,\n });\n }\n\n for (const junction of document.sheet.junctions) {\n const selected = selection.junctions?.has(junction.id) ?? false;\n const hovered = input.hover?.kind === 'junction' && input.hover.id === junction.id;\n const center = drag.junctions.get(junction.id) ?? { x: junction.x, y: junction.y };\n items.push({\n kind: 'circle',\n center,\n radius: JUNCTION_RADIUS,\n fill: selected ? theme.junctionSelected : hovered ? theme.hover : theme.junction,\n width: 0,\n });\n }\n\n for (const symbol of document.sheet.symbols) {\n const selected = selection.symbols?.has(symbol.id) ?? false;\n const hovered =\n (input.hover?.kind === 'symbol' && input.hover.id === symbol.id) ||\n (input.hover?.kind === 'reference' && input.hover.symbolId === symbol.id);\n const placed = { x: symbol.x, y: symbol.y, rotation: symbol.rotation };\n const dragged = drag.symbols.get(symbol.id);\n drawSymbol(items, {\n symbol,\n placement: dragged === undefined ? placed : { ...placed, x: dragged.x, y: dragged.y },\n theme,\n devices,\n labels: display.labels,\n fonts: { font, pinFont, symbolFont },\n selected,\n hovered,\n ...(input.referencePreview?.symbolId === symbol.id\n ? { referenceOverride: input.referencePreview.position }\n : {}),\n });\n }\n for (const vertex of selection.vertices ?? []) {\n const wire = document.sheet.wires.find((candidate) => candidate.id === vertex.wireId);\n const point = wire?.points[vertex.index];\n if (point === undefined) {\n continue;\n }\n const center = point;\n items.push({\n kind: 'rect',\n bounds: {\n x: center.x - VERTEX_SIZE / 2,\n y: center.y - VERTEX_SIZE / 2,\n width: VERTEX_SIZE,\n height: VERTEX_SIZE,\n },\n fill: theme.selection,\n width: 0,\n });\n }\n\n if (input.marquee !== undefined) {\n items.push({\n kind: 'rect',\n bounds: input.marquee,\n stroke: theme.selection,\n width: 1,\n dash: [4, 3],\n });\n }\n\n if (input.placementPreview !== undefined) {\n const { device, position, rotation, wire } = input.placementPreview;\n if (wire !== undefined) {\n items.push({ kind: 'polyline', points: wire, color: theme.hover, width: WIRE_WIDTH });\n }\n drawSymbol(items, {\n symbol: previewSymbol(device, position),\n placement: { ...position, rotation },\n theme,\n devices,\n labels: display.labels,\n fonts: { font, pinFont, symbolFont },\n selected: false,\n hovered: false,\n ghost: true,\n });\n }\n\n if (tool === 'wire' && input.pendingWire !== undefined && input.pendingWire.length > 0) {\n items.push({\n kind: 'polyline',\n points: input.pendingWire,\n color: theme.pendingWire,\n width: WIRE_WIDTH,\n dash: [5, 4],\n });\n const last = input.pendingWire[input.pendingWire.length - 1];\n if (last !== undefined) {\n items.push({ kind: 'circle', center: last, radius: 2.5, fill: theme.pendingWire, width: 0 });\n }\n }\n\n return {\n background: theme.background,\n grid:\n display.grid === false\n ? undefined\n : {\n size: display.gridSize ?? theme.gridSize,\n subdivisions: gridSubdivisions(display.gridSubdivisions),\n minor: theme.grid,\n major: theme.gridMajor,\n },\n items,\n };\n}\n\ninterface SymbolFonts {\n readonly font: string;\n readonly pinFont: string;\n readonly symbolFont: string;\n}\n\ninterface DrawSymbolOptions {\n readonly symbol: SchematicSymbol;\n readonly placement: Placement;\n readonly theme: SchematicTheme;\n readonly devices: DeviceSymbolProvider | undefined;\n readonly labels: boolean;\n readonly fonts: SymbolFonts;\n readonly selected: boolean;\n readonly hovered: boolean;\n /** Drawn as a placement ghost (hover color, no reference override). */\n readonly ghost?: boolean;\n readonly referenceOverride?: Point;\n}\n\n/**\n * Draws one symbol: the single code path shared by placed symbols and the placement preview,\n * so what follows the cursor is exactly what will be inserted.\n */\nfunction drawSymbol(items: SceneItem[], options: DrawSymbolOptions): void {\n const { symbol, placement, theme, devices, fonts, selected, hovered } = options;\n const ghost = options.ghost ?? false;\n const highlight = selected ? theme.selection : hovered || ghost ? theme.hover : undefined;\n const stroke = highlight ?? theme.symbolStroke;\n const annotation = highlight ?? theme.labelText;\n\n if (isTextDevice(symbol.device)) {\n items.push({\n kind: 'text',\n position: placement,\n text: textDeviceContent(symbol),\n color: annotation,\n ...uprightText(placement.rotation, 'left', 'middle'),\n font: fonts.symbolFont,\n });\n return;\n }\n\n const builtin = builtinSymbolKind(symbol.device);\n if (builtin !== undefined) {\n drawBuiltin(items, {\n kind: builtin,\n placement,\n text: netNameOf(symbol) ?? symbol.id,\n color: annotation,\n anchorColor: highlight ?? theme.labelAnchor,\n font: builtin === 'label' ? fonts.font : fonts.pinFont,\n });\n return;\n }\n\n const reference = parseDeviceReference(symbol.device);\n const definition = reference === undefined ? undefined : devices?.getDeviceSymbol(reference);\n\n if (definition === undefined) {\n const half = 12;\n items.push({\n kind: 'rect',\n bounds: { x: placement.x - half, y: placement.y - half, width: half * 2, height: half * 2 },\n stroke: theme.symbolPlaceholder,\n width: 1,\n dash: [4, 3],\n });\n items.push({\n kind: 'text',\n position: { x: placement.x, y: placement.y },\n text: (reference === undefined ? undefined : devices?.getDeviceName(reference)) ?? symbol.id,\n color: theme.symbolPlaceholder,\n align: 'center',\n baseline: 'middle',\n font: fonts.symbolFont,\n });\n return;\n }\n\n const localBody = definition.bounds ??\n pinsBounds(definition.pins) ?? { x: -12, y: -12, width: 24, height: 24 };\n const body = symbolBounds(placement, localBody, {}) ?? fallbackBounds(placement);\n\n items.push({ kind: 'rect', bounds: body, fill: theme.symbolFill, stroke, width: 1.5 });\n items.push({\n kind: 'text',\n position:\n options.referenceOverride ?? referencePosition(placement, localBody, symbol.reference),\n text: designatorOf(symbol) ?? symbol.id,\n color: options.referenceOverride === undefined ? annotation : theme.selection,\n ...uprightText(placement.rotation, 'left', 'bottom'),\n font: fonts.pinFont,\n });\n items.push({\n kind: 'text',\n position: { x: body.x + body.width / 2, y: body.y + body.height / 2 },\n text: definition.name,\n // Inverted on purpose: the name is quiet by default and lights up on hover / selection.\n color: selected || hovered ? theme.selection : theme.symbolText,\n ...uprightText(placement.rotation, 'center', 'middle'),\n font: fonts.symbolFont,\n });\n\n for (const [pinId, anchor] of Object.entries(definition.pins)) {\n const side = pinSide(anchor, localBody) ?? 'left';\n const pinPosition = symbolPinPosition(placement, anchor);\n const edge = symbolPinPosition(placement, pinStubEnd(localBody, anchor, side));\n items.push({\n kind: 'line',\n from: edge,\n to: pinPosition,\n color: highlight ?? theme.pin,\n width: 1.2,\n });\n if (!options.labels) {\n continue;\n }\n const label = pinLabel(localBody, side, anchor);\n items.push({\n kind: 'text',\n position: symbolPinPosition(placement, label.position),\n text: pinId,\n color: highlight ?? theme.pinText,\n ...uprightText(placement.rotation + label.rotation, label.align, label.baseline),\n font: fonts.pinFont,\n });\n }\n}\n\n/** Synthetic symbol used to preview the current placement tool. */\nfunction previewSymbol(device: string, position: Point): SchematicSymbol {\n const base: SchematicSymbol = { id: 'N', device, x: position.x, y: position.y, rotation: 0 };\n if (isTextDevice(device)) {\n return { ...base, properties: { text: DEFAULT_TEXT_CONTENT } };\n }\n return base;\n}\n\nfunction fallbackBounds(placement: { readonly x: number; readonly y: number }): Rect {\n return { x: placement.x - 12, y: placement.y - 12, width: 24, height: 24 };\n}\n\nfunction pinLabel(\n body: Rect,\n side: 'left' | 'right' | 'top' | 'bottom',\n anchor: { readonly x: number; readonly y: number },\n): {\n position: Point;\n align: 'left' | 'center' | 'right';\n baseline: 'top' | 'middle' | 'bottom';\n rotation: number;\n} {\n const centerX = body.x + body.width / 2;\n const centerY = body.y + body.height / 2;\n const clampX = Math.min(Math.max(anchor.x, body.x), body.x + body.width);\n const clampY = Math.min(Math.max(anchor.y, body.y), body.y + body.height);\n switch (side) {\n case 'left':\n return {\n position: { x: body.x + 5, y: clampY },\n align: 'left',\n baseline: 'middle',\n rotation: 0,\n };\n case 'right':\n return {\n position: { x: body.x + body.width - 5, y: clampY },\n align: 'right',\n baseline: 'middle',\n rotation: 0,\n };\n case 'top':\n return {\n position: { x: clampX, y: body.y + 10 },\n align: 'center',\n baseline: 'middle',\n rotation: -90,\n };\n case 'bottom':\n return {\n position: { x: clampX, y: body.y + body.height - 10 },\n align: 'center',\n baseline: 'middle',\n rotation: -90,\n };\n default:\n return {\n position: { x: centerX, y: centerY },\n align: 'center',\n baseline: 'middle',\n rotation: 0,\n };\n }\n}\n\nfunction drawBuiltin(\n items: SceneItem[],\n input: {\n readonly kind: 'label' | 'power' | 'ground';\n readonly placement: Placement;\n readonly text: string;\n readonly color: string;\n readonly anchorColor: string;\n readonly font: string;\n },\n): void {\n const { placement, color, anchorColor, font } = input;\n const at = (x: number, y: number): Point => symbolPinPosition(placement, { x, y });\n // Annotation text keeps its orientation and grows away from the glyph, so it stays readable\n // whatever the rotation.\n const push = (x: number, y: number): void => {\n const rotated = rotatePoint({ x, y }, placement.rotation);\n items.push({\n kind: 'text',\n position: { x: placement.x + rotated.x, y: placement.y + rotated.y },\n text: input.text,\n color,\n ...outwardLabel(rotated),\n font,\n });\n };\n\n // Power and ground mark their connection point with the stem itself; only free-standing\n // labels need a marker, drawn as a small cross.\n if (input.kind === 'label') {\n items.push({ kind: 'line', from: at(-3, 0), to: at(3, 0), color: anchorColor, width: 1.2 });\n items.push({ kind: 'line', from: at(0, -3), to: at(0, 3), color: anchorColor, width: 1.2 });\n // The name sits beside the cross, off the wire it names, so the wire never crosses the text.\n const layout = LABEL_TEXT_LAYOUTS[quarterTurns(placement.rotation)];\n items.push({\n kind: 'text',\n position: { x: placement.x + layout.offset.x, y: placement.y + layout.offset.y },\n text: input.text,\n color,\n align: layout.align,\n baseline: layout.baseline,\n font,\n });\n return;\n }\n\n if (input.kind === 'power') {\n items.push({ kind: 'line', from: at(0, 0), to: at(0, -10), color, width: 1.5 });\n items.push({ kind: 'line', from: at(-6, -10), to: at(6, -10), color, width: 1.5 });\n push(0, -13);\n return;\n }\n\n if (input.kind === 'ground') {\n items.push({ kind: 'line', from: at(0, 0), to: at(0, 6), color, width: 1.5 });\n for (const [offset, width] of [\n [6, 12],\n [9, 8],\n [12, 4],\n ] as const) {\n items.push({\n kind: 'line',\n from: at(-width / 2, offset),\n to: at(width / 2, offset),\n color,\n width: 1.5,\n });\n }\n push(0, 16);\n }\n}\n\n/** Rotation snapped to the 90° steps builtin glyphs support. */\nfunction quarterTurns(rotation: number): 0 | 90 | 180 | 270 {\n const normalized = ((((rotation % 360) + 360) % 360) + 45) % 360;\n return (Math.floor(normalized / 90) * 90) as 0 | 90 | 180 | 270;\n}\n\n/** Distance between a label's name and the wire it names. */\nconst LABEL_TEXT_GAP = 1;\n/** Clearance from the anchor cross, so the name starts just past its arms. */\nconst LABEL_TEXT_INSET = 4;\n\n/**\n * Where a label's name goes for each rotation: right above the wire for horizontal labels and\n * just past its tip for vertical ones, clear of the anchor cross.\n */\nconst LABEL_TEXT_LAYOUTS: Readonly<\n Record<\n 0 | 90 | 180 | 270,\n {\n readonly offset: Point;\n readonly align: TextPlacement['align'];\n readonly baseline: TextPlacement['baseline'];\n }\n >\n> = {\n 0: {\n offset: { x: LABEL_TEXT_INSET, y: -LABEL_TEXT_GAP },\n align: 'left',\n baseline: 'bottom',\n },\n 90: { offset: { x: LABEL_TEXT_INSET, y: 0 }, align: 'left', baseline: 'middle' },\n 180: {\n offset: { x: -LABEL_TEXT_INSET, y: -LABEL_TEXT_GAP },\n align: 'right',\n baseline: 'bottom',\n },\n 270: { offset: { x: LABEL_TEXT_INSET, y: 0 }, align: 'left', baseline: 'middle' },\n};\n\n/** Horizontal text starting at `offset` (already rotated) and growing away from the origin. */\nfunction outwardLabel(offset: Point): TextPlacement {\n if (Math.abs(offset.x) >= Math.abs(offset.y)) {\n return { align: offset.x >= 0 ? 'left' : 'right', baseline: 'middle', rotation: 0 };\n }\n return { align: 'center', baseline: offset.y >= 0 ? 'top' : 'bottom', rotation: 0 };\n}\n","import {\n GROUND_DEVICE,\n LABEL_DEVICE,\n POWER_DEVICE,\n parseDeviceReference,\n symbolPinPosition,\n type DeviceSymbolProvider,\n type Point,\n} from '@mica-js/core/schematic';\nimport type { SchematicEditorController } from '../../controller/controller';\n\n/** Screen-space hit radius; callers divide by the viewport scale. */\nexport const MIN_HIT_PIXELS = 6;\n\nexport interface SnapContext {\n readonly controller: SchematicEditorController;\n readonly devices: DeviceSymbolProvider | undefined;\n /** Hit tolerance in page units. */\n readonly tolerance: number;\n}\n\n/** World position of a pin / label / power / ground anchor under `point`. */\nexport function connectionNodeAt(context: SnapContext, point: Point): Point | undefined {\n const hit = context.controller.hitTest(point, {\n tolerance: context.tolerance * 2,\n includeSymbols: false,\n });\n if (hit?.kind === 'pin') {\n return pinPosition(context, hit);\n }\n const anchor = anchorSymbolAt(context, point);\n if (anchor !== undefined) {\n return { x: anchor.x, y: anchor.y };\n }\n return wireEndpointAt(context, point);\n}\n\n/** Endpoint of an existing wire under `point`; used to close a connection. */\nexport function wireEndpointAt(context: SnapContext, point: Point): Point | undefined {\n for (const wire of context.controller.document.sheet.wires) {\n for (const endpoint of [wire.points[0], wire.points[wire.points.length - 1]]) {\n if (\n endpoint !== undefined &&\n Math.abs(endpoint.x - point.x) <= context.tolerance * 2 &&\n Math.abs(endpoint.y - point.y) <= context.tolerance * 2\n ) {\n return { x: endpoint.x, y: endpoint.y };\n }\n }\n }\n return undefined;\n}\n\n/** Builtin connection symbol (label / power / ground) anchored under `point`. */\nexport function anchorSymbolAt(\n context: SnapContext,\n point: Point,\n): { readonly x: number; readonly y: number } | undefined {\n // Anchors sit on wire endpoints, where `hitTest` reports the wire first, so scan directly.\n for (const symbol of context.controller.document.sheet.symbols) {\n const device = symbol.device;\n if (device !== LABEL_DEVICE && device !== POWER_DEVICE && device !== GROUND_DEVICE) {\n continue;\n }\n if (\n Math.abs(symbol.x - point.x) <= context.tolerance &&\n Math.abs(symbol.y - point.y) <= context.tolerance\n ) {\n return symbol;\n }\n }\n return undefined;\n}\n\nexport function pinPosition(\n context: SnapContext,\n hit: { readonly symbolId: string; readonly pinId: string },\n): Point | undefined {\n const symbol = context.controller.document.sheet.symbols.find((item) => item.id === hit.symbolId);\n if (symbol === undefined) {\n return undefined;\n }\n const reference = parseDeviceReference(symbol.device);\n const anchor =\n reference === undefined\n ? undefined\n : context.devices?.getDeviceSymbol(reference)?.pins[hit.pinId];\n return anchor === undefined ? undefined : symbolPinPosition(symbol, anchor);\n}\n","import type { Point } from '@mica-js/core/schematic';\nimport type { DisplayOptions } from '../../controller/types';\n\nexport function snapToGrid(point: Point, display: DisplayOptions): Point {\n if (!display.snap || !(display.gridSize > 0)) {\n return point;\n }\n const size = display.gridSize;\n return { x: Math.round(point.x / size) * size, y: Math.round(point.y / size) * size };\n}\n\n/**\n * Offset for dragging something anchored at `anchor` from `from` to `to`: the result is snapped,\n * not the raw pointer delta, so an off-grid symbol lands on the grid.\n *\n * A drag that stays within half a grid cell on one axis does not move that axis at all, so an\n * anchor that started off-grid keeps its column/row instead of jittering sideways.\n */\nexport function snapDragOffset(\n anchor: Point,\n from: Point,\n to: Point,\n display: DisplayOptions,\n): Point {\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n if (!display.snap || !(display.gridSize > 0)) {\n return { x: dx, y: dy };\n }\n const target = snapToGrid({ x: anchor.x + dx, y: anchor.y + dy }, display);\n const lock = display.gridSize / 2;\n return {\n x: (Math.abs(dx) < lock ? anchor.x : target.x) - anchor.x,\n y: (Math.abs(dy) < lock ? anchor.y : target.y) - anchor.y,\n };\n}\n","import { projectOnSegment, type Point } from '@mica-js/core/schematic';\nimport type { SnapContext } from './nodes';\nimport { connectionNodeAt } from './nodes';\nimport { snapToGrid } from './drag';\n\n/**\n * Waypoints needed to reach `to` from `from` with horizontal/vertical segments only.\n * Returns `[to]` when already aligned, otherwise an elbow plus `to` (long axis first).\n */\nexport function orthogonalWaypoints(from: Point, to: Point): readonly Point[] {\n if (from.x === to.x || from.y === to.y) {\n return [to];\n }\n const elbow =\n Math.abs(to.x - from.x) >= Math.abs(to.y - from.y)\n ? { x: to.x, y: from.y }\n : { x: from.x, y: to.y };\n return [elbow, to];\n}\n\nexport type WireAxis = 'horizontal' | 'vertical';\n\n/**\n * Waypoints for one new wire leg. When the target lands on an existing wire the last leg runs\n * perpendicular to it, so the branch taps into a T instead of doubling back along the host.\n */\nexport function wireWaypoints(\n from: Point,\n to: Point,\n host: WireAxis | undefined,\n): readonly Point[] {\n if (host === undefined || from.x === to.x || from.y === to.y) {\n return orthogonalWaypoints(from, to);\n }\n return host === 'vertical' ? [{ x: from.x, y: to.y }, to] : [{ x: to.x, y: from.y }, to];\n}\n\n/** Snaps to a nearby connection node, then to a nearby wire, otherwise to the grid. */\nexport function snapForWire(context: SnapContext, point: Point): Point {\n return (\n connectionNodeAt(context, point) ??\n wireBodyPointAt(context, point) ??\n snapToGrid(point, context.controller.display)\n );\n}\n\n/**\n * Closest point on an existing wire's run when `point` is within the snap radius. Lets the wire\n * tool land exactly on another wire, which is what turns the run into a T junction.\n */\nexport function wireBodyPointAt(context: SnapContext, point: Point): Point | undefined {\n const radius = context.tolerance * 2;\n let best: { readonly point: Point; readonly distance: number } | undefined;\n for (const wire of context.controller.document.sheet.wires) {\n for (let index = 1; index < wire.points.length; index += 1) {\n const a = wire.points[index - 1];\n const b = wire.points[index];\n if (a === undefined || b === undefined) {\n continue;\n }\n const projected = projectOnSegment(point, a, b);\n const distance = Math.hypot(projected.x - point.x, projected.y - point.y);\n if (distance > radius || (best !== undefined && distance >= best.distance)) {\n continue;\n }\n best = { point: { x: projected.x, y: projected.y }, distance };\n }\n }\n return best?.point;\n}\n","import {\n DEFAULT_TEXT_CONTENT,\n GROUND_DEVICE,\n LABEL_DEVICE,\n POWER_DEVICE,\n TEXT_DEVICE,\n isTextDevice,\n netNameOf,\n parseDeviceReference,\n pinSide,\n pinsBounds,\n rotatePoint,\n type Point,\n type SchematicDocument,\n} from '@mica-js/core/schematic';\nimport type { EditorTool } from '../../controller/types';\nimport { pinPosition, type SnapContext } from './nodes';\n\nexport function isPlacementTool(tool: EditorTool): boolean {\n return tool === 'power' || tool === 'ground' || tool === 'label' || tool === 'text';\n}\n\nexport function toolDevice(tool: EditorTool): string {\n switch (tool) {\n case 'power':\n return POWER_DEVICE;\n case 'ground':\n return GROUND_DEVICE;\n case 'label':\n return LABEL_DEVICE;\n default:\n return TEXT_DEVICE;\n }\n}\n\n/** Smallest unused `N<n>` net name for a freshly placed net label. */\nexport function nextNetName(document: SchematicDocument): string {\n const used = new Set(\n document.sheet.symbols\n .map((symbol) => netNameOf(symbol))\n .filter((name): name is string => name !== undefined),\n );\n for (let index = 1; index < Number.MAX_SAFE_INTEGER; index += 1) {\n const candidate = `N${index}`;\n if (!used.has(candidate)) {\n return candidate;\n }\n }\n return 'N';\n}\n\n/** Length of the lead added when a label is dropped straight onto a pin. */\nexport const LABEL_STUB_LENGTH = 20;\n\nexport interface LabelStub {\n /** Pin connection point. */\n readonly pin: Point;\n /** Where the label anchor goes: one lead away from the pin. */\n readonly anchor: Point;\n /** Rotation that draws the net name away from the symbol. */\n readonly rotation: number;\n /** Lead to insert; absent when an existing wire already reaches the anchor. */\n readonly wire?: readonly Point[];\n}\n\n/**\n * Lead used when a label is placed directly on a pin: labels hang off a short wire in the pin's\n * outward direction instead of sitting on the pin itself.\n */\nexport function labelStubAt(context: SnapContext, point: Point): LabelStub | undefined {\n const hit = context.controller.hitTest(point, {\n tolerance: context.tolerance * 2,\n includeSymbols: false,\n });\n if (hit?.kind !== 'pin') {\n return undefined;\n }\n const pin = pinPosition(context, hit);\n const direction = pinOutward(context, hit);\n if (pin === undefined || direction === undefined) {\n return undefined;\n }\n // Directions are axis aligned, so rounding removes the rotation's floating point noise.\n const dx = Math.round(direction.x);\n const dy = Math.round(direction.y);\n const anchor = {\n x: pin.x + dx * LABEL_STUB_LENGTH,\n y: pin.y + dy * LABEL_STUB_LENGTH,\n };\n const rotation = dx > 0 ? 0 : dx < 0 ? 180 : dy > 0 ? 90 : 270;\n return { pin, anchor, rotation, ...stubWire(context, pin, anchor) };\n}\n\n/** The lead only has to be drawn where no wire already runs; labels bind to any wire they touch. */\nfunction stubWire(\n context: SnapContext,\n pin: Point,\n anchor: Point,\n): { readonly wire?: readonly Point[] } {\n const host = context.controller.hitTest(anchor, {\n includeSymbols: false,\n tolerance: context.tolerance,\n });\n return host?.kind === 'wire' ? {} : { wire: [pin, anchor] };\n}\n\n/** Unit vector, in world space, pointing away from the symbol body at a pin. */\nfunction pinOutward(\n context: SnapContext,\n hit: { readonly symbolId: string; readonly pinId: string },\n): Point | undefined {\n const symbol = context.controller.document.sheet.symbols.find((item) => item.id === hit.symbolId);\n const reference = symbol === undefined ? undefined : parseDeviceReference(symbol.device);\n const definition =\n reference === undefined ? undefined : context.devices?.getDeviceSymbol(reference);\n const anchor = definition?.pins[hit.pinId];\n if (symbol === undefined || definition === undefined || anchor === undefined) {\n return undefined;\n }\n const side = pinSide(anchor, definition.bounds ?? pinsBounds(definition.pins));\n const local =\n side === 'left'\n ? { x: -1, y: 0 }\n : side === 'right'\n ? { x: 1, y: 0 }\n : side === 'top'\n ? { x: 0, y: -1 }\n : side === 'bottom'\n ? { x: 0, y: 1 }\n : undefined;\n return local === undefined ? undefined : rotatePoint(local, symbol.rotation);\n}\n\n/** Extra properties written when a placement inserts a builtin symbol. */\nexport function placementProperties(device: string): Record<string, string> | undefined {\n return isTextDevice(device) ? { text: DEFAULT_TEXT_CONTENT } : undefined;\n}\n","import { LABEL_DEVICE, symbolRole, type Point } from '@mica-js/core/schematic';\nimport {\n isPlacementTool,\n labelStubAt,\n nextNetName,\n placementProperties,\n snapToGrid,\n toolDevice,\n type LabelStub,\n} from '../snapping';\nimport type { InteractionContext } from './context';\n\n/** Device the next click inserts: the host's armed device wins over the toolbar tool. */\nexport function placementDevice(context: InteractionContext): string | undefined {\n const armed = context.deps.controller.placingDevice;\n if (armed !== undefined) {\n return armed;\n }\n const tool = context.deps.controller.tool;\n return isPlacementTool(tool) ? toolDevice(tool) : undefined;\n}\n\n/** Lead a label placement adds when the pointer is on a pin. */\nexport function labelStub(\n context: InteractionContext,\n device: string,\n point: Point,\n): LabelStub | undefined {\n return device === LABEL_DEVICE ? labelStubAt(context.pointer.snapContext(), point) : undefined;\n}\n\n/** Ghost rotation: the pin lead picks a readable angle unless the user rotated it. */\nexport function placeRotation(context: InteractionContext, stub: LabelStub | undefined): number {\n return context.state.placementRotation === 0 && stub !== undefined\n ? stub.rotation\n : context.state.placementRotation;\n}\n\n/** Ghost shown while a placement tool or armed device follows the pointer. */\nexport function placementPreview(context: InteractionContext):\n | {\n readonly device: string;\n readonly position: Point;\n readonly rotation: number;\n readonly wire?: readonly Point[];\n }\n | undefined {\n const device = placementDevice(context);\n const cursor = context.state.cursorPoint;\n if (cursor === undefined || device === undefined) {\n return undefined;\n }\n const stub = labelStub(context, device, cursor);\n return {\n device,\n position: stub?.anchor ?? cursor,\n rotation: placeRotation(context, stub),\n ...(stub?.wire === undefined ? {} : { wire: stub.wire }),\n };\n}\n\n/** Rotates the ghost while a placement tool is active. */\nexport function rotatePlacement(context: InteractionContext, degrees: number): boolean {\n if (placementDevice(context) === undefined) {\n return false;\n }\n context.state.placementRotation =\n (((context.state.placementRotation + degrees) % 360) + 360) % 360;\n context.deps.onChange();\n return true;\n}\n\n/** Places the armed device at `page`. */\nexport function place(context: InteractionContext, page: Point): void {\n const controller = context.deps.controller;\n const device = placementDevice(context);\n if (device === undefined || context.deps.readOnly) {\n return;\n }\n const role = symbolRole(device);\n // Connection points snap to pins and wire ends; components only snap to the grid.\n const snapped =\n role === 'component' ? snapToGrid(page, controller.display) : context.pointer.snapWire(page);\n // A label dropped on a pin hangs off a short lead instead of sitting on the pin.\n const stub = labelStub(context, device, snapped);\n const point = stub?.anchor ?? snapped;\n const properties = placementProperties(device);\n const designator = role === 'component' ? controller.nextDesignator(device) : undefined;\n context.deps.run(() =>\n controller.transaction(() => {\n if (stub?.wire !== undefined) {\n controller.addWire(stub.wire);\n }\n controller.dispatch({\n type: 'add-symbol',\n ...(device === LABEL_DEVICE ? { net: nextNetName(controller.document) } : {}),\n ...(designator === undefined ? {} : { designator }),\n device,\n x: point.x,\n y: point.y,\n rotation: placeRotation(context, stub),\n ...(properties === undefined ? {} : { properties }),\n });\n }),\n );\n controller.setTool('select');\n context.state.cursorPoint = undefined;\n context.state.placementRotation = 0;\n}\n\n/** Snapping applied to the placement ghost so it matches where the click will land. */\nexport function snapPlacementPoint(\n context: InteractionContext,\n page: Point,\n device: string,\n): Point {\n return symbolRole(device) === 'component'\n ? snapToGrid(page, context.deps.controller.display)\n : context.pointer.snapWire(page);\n}\n","import {\n parseDeviceReference,\n symbolBounds,\n type DeviceSymbolProvider,\n type Point,\n type Rect,\n type SchematicDocument,\n} from '@mica-js/core/schematic';\nimport type { EditorSelection } from '../controller/types';\n\nexport function rectOf(from: Point, to: Point): Rect {\n return {\n x: Math.min(from.x, to.x),\n y: Math.min(from.y, to.y),\n width: Math.abs(to.x - from.x),\n height: Math.abs(to.y - from.y),\n };\n}\n\nexport function pointInRect(point: Point, rect: Rect): boolean {\n return (\n point.x >= rect.x &&\n point.x <= rect.x + rect.width &&\n point.y >= rect.y &&\n point.y <= rect.y + rect.height\n );\n}\n\nexport function rectsIntersect(left: Rect, right: Rect): boolean {\n return (\n left.x + left.width >= right.x &&\n left.x <= right.x + right.width &&\n left.y + left.height >= right.y &&\n left.y <= right.y + right.height\n );\n}\n\n/** Everything touched by the rubber-band rectangle. */\nexport function marqueeSelection(\n document: SchematicDocument,\n rect: Rect,\n devices: DeviceSymbolProvider | undefined,\n): readonly EditorSelection[] {\n if (rect.width === 0 && rect.height === 0) {\n return [];\n }\n const result: EditorSelection[] = [];\n for (const symbol of document.sheet.symbols) {\n if (rectsIntersect(symbolRect(symbol, devices), rect)) {\n result.push({ kind: 'symbol', id: symbol.id });\n }\n }\n for (const wire of document.sheet.wires) {\n if (wire.points.some((point) => pointInRect(point, rect))) {\n result.push({ kind: 'wire', id: wire.id });\n }\n }\n for (const junction of document.sheet.junctions) {\n if (pointInRect({ x: junction.x, y: junction.y }, rect)) {\n result.push({ kind: 'junction', id: junction.id });\n }\n }\n return result;\n}\n\nfunction symbolRect(\n symbol: {\n readonly id: string;\n readonly device: string;\n readonly x: number;\n readonly y: number;\n readonly rotation: number;\n },\n devices: DeviceSymbolProvider | undefined,\n): Rect {\n const reference = parseDeviceReference(symbol.device);\n const definition = reference === undefined ? undefined : devices?.getDeviceSymbol(reference);\n return (\n (definition === undefined\n ? undefined\n : symbolBounds(symbol, definition.bounds, definition.pins)) ?? {\n x: symbol.x,\n y: symbol.y,\n width: 0,\n height: 0,\n }\n );\n}\n","import { symbolRole, type Point, type SchematicHit } from '@mica-js/core/schematic';\nimport { sameSelectionItem } from '../../controller/selection';\nimport type { EditorSelection } from '../../controller/types';\nimport { marqueeSelection, rectOf } from '../selection-box';\nimport type { InteractionContext } from './context';\n\n/** Selection under the pointer: vertices win over wire bodies, then pins/anchors/symbols. */\nexport function selectionAt(context: InteractionContext, page: Point): EditorSelection | undefined {\n const vertex = vertexAt(context, page);\n if (vertex !== undefined) {\n return vertex;\n }\n const hit = context.deps.controller.hitTest(page, { tolerance: context.pointer.tolerance() });\n return hit === undefined ? undefined : selectionFromHit(hit);\n}\n\nexport function vertexAt(context: InteractionContext, page: Point): EditorSelection | undefined {\n const tolerance = context.pointer.tolerance();\n for (const wire of context.deps.controller.document.sheet.wires) {\n for (let index = 0; index < wire.points.length; index += 1) {\n const point = wire.points[index];\n if (point === undefined) {\n continue;\n }\n if (Math.abs(point.x - page.x) <= tolerance && Math.abs(point.y - page.y) <= tolerance) {\n return { kind: 'vertex', wireId: wire.id, index };\n }\n }\n }\n return undefined;\n}\n\n/** True when the pointer is over a builtin annotation (label / power / ground / text). */\nexport function annotationSymbolAt(context: InteractionContext, page: Point): boolean {\n const hit = context.deps.controller.hitTest(page, { tolerance: context.pointer.tolerance() });\n if (hit?.kind !== 'symbol') {\n return false;\n }\n const symbol = context.deps.controller.document.sheet.symbols.find((item) => item.id === hit.id);\n return symbol !== undefined && symbolRole(symbol.device) !== 'component';\n}\n\n/** Applies a click selection, honouring additive (shift) clicks. */\nexport function selectItem(\n context: InteractionContext,\n selection: EditorSelection | undefined,\n additive: boolean,\n): void {\n const controller = context.deps.controller;\n if (selection === undefined) {\n controller.setSelection(additive ? controller.selection : []);\n return;\n }\n const current = controller.selection;\n const exists = current.some((item) => sameSelectionItem(item, selection));\n if (!additive) {\n controller.setSelection([selection]);\n return;\n }\n controller.setSelection(\n exists\n ? current.filter((item) => !sameSelectionItem(item, selection))\n : [...current, selection],\n );\n}\n\n/** Commits a rubber-band selection. */\nexport function finishMarquee(context: InteractionContext, origin: Point, current: Point): void {\n context.deps.controller.setSelection(\n marqueeSelection(\n context.deps.controller.document,\n rectOf(origin, current),\n context.deps.devices,\n ),\n );\n}\n\nexport function selectionFromHit(hit: SchematicHit): EditorSelection | undefined {\n switch (hit.kind) {\n case 'symbol':\n return { kind: 'symbol', id: hit.id };\n case 'reference':\n return { kind: 'reference', symbolId: hit.symbolId };\n case 'wire':\n return { kind: 'wire', id: hit.id };\n case 'junction':\n return { kind: 'junction', id: hit.id };\n case 'pin':\n return { kind: 'symbol', id: hit.symbolId };\n default:\n return undefined;\n }\n}\n\nexport function sameHit(left: SchematicHit | undefined, right: SchematicHit | undefined): boolean {\n if (left === undefined || right === undefined) {\n return left === right;\n }\n return JSON.stringify(left) === JSON.stringify(right);\n}\n","import type { Point } from '@mica-js/core/schematic';\nimport { connectionNodeAt, wireWaypoints } from '../snapping';\nimport { annotationSymbolAt } from './selection';\nimport type { InteractionContext } from './context';\n\n/** Adds the next waypoint of the wire being drawn, closing the run on a connection. */\nexport function addWirePoint(context: InteractionContext, page: Point): void {\n const state = context.state;\n const point = context.pointer.snapWire(page);\n const previous = state.pendingWire[state.pendingWire.length - 1];\n state.pendingWire = [\n ...state.pendingWire,\n ...(previous === undefined\n ? [point]\n : wireWaypoints(previous, point, context.pointer.hostAxisAt(point))),\n ];\n state.cursorPoint = point;\n // Landing on another endpoint (pin, anchor, wire end) or an existing wire closes the run.\n const node = connectionNodeAt(context.pointer.snapContext(), point);\n const host = context.deps.controller.hitTest(point, {\n includeSymbols: false,\n tolerance: context.pointer.tolerance(),\n });\n const closes = node !== undefined || host?.kind === 'wire';\n if (closes && state.pendingWire.length >= 2) {\n finishWire(context);\n context.deps.controller.setTool('select');\n return;\n }\n context.deps.onChange();\n}\n\n/** Commits the pending wire as one edit; nothing is written in read-only mode. */\nexport function finishWire(context: InteractionContext): void {\n const points = context.state.pendingWire;\n context.state.pendingWire = [];\n context.state.cursorPoint = undefined;\n context.state.hover = undefined;\n if (points.length < 2 || context.deps.readOnly) {\n context.deps.onChange();\n return;\n }\n context.deps.run(() => context.deps.controller.addWire(points));\n}\n\n/** Pending wire plus the live cursor leg, for the dashed preview. */\nexport function pendingWireWithCursor(context: InteractionContext): readonly Point[] {\n const state = context.state;\n const cursor = state.cursorPoint;\n if (cursor === undefined) {\n return state.pendingWire;\n }\n const previous = state.pendingWire[state.pendingWire.length - 1];\n if (previous === undefined) {\n return [cursor];\n }\n return [\n ...state.pendingWire,\n ...wireWaypoints(previous, cursor, context.pointer.hostAxisAt(cursor)),\n ];\n}\n\n/** Clicking a pin or wire end in select mode starts a wire from there. */\nexport function startWireAtNode(context: InteractionContext, page: Point): boolean {\n const controller = context.deps.controller;\n if (controller.tool !== 'select' || context.deps.readOnly) {\n return false;\n }\n // Net labels, ports and text are selection/drag targets, so a tap on their body must not be\n // eaten by a new wire; the wire tool still connects to their anchors by snapping to them.\n if (annotationSymbolAt(context, page)) {\n return false;\n }\n const node = connectionNodeAt(context.pointer.snapContext(), page);\n if (node === undefined) {\n return false;\n }\n // Switch the tool first: the tool change resets transient state, which must not eat the anchor.\n controller.setTool('wire');\n context.state.pendingWire = [node];\n context.state.cursorPoint = node;\n context.deps.onChange();\n return true;\n}\n","import type { Point } from '@mica-js/core/schematic';\nimport type { InteractionContext } from './context';\nimport { rotatePlacement } from './placement';\nimport { finishWire } from './wire';\n\n/**\n * Cancels whatever interaction is pending: placement, the wire being drawn, a drag or the active\n * tool, and clears the selection. Returns whether there was anything to cancel.\n */\nexport function cancelInteraction(context: InteractionContext): boolean {\n const controller = context.deps.controller;\n const active =\n controller.placingDevice !== undefined ||\n controller.tool !== 'select' ||\n controller.selection.length > 0 ||\n context.state.pendingWire.length > 0 ||\n context.state.drag !== undefined;\n if (!active) {\n return false;\n }\n if (controller.placingDevice !== undefined) {\n controller.cancelPlacement();\n }\n context.state.reset();\n controller.setSelection([]);\n controller.setTool('select');\n context.deps.onChange();\n return true;\n}\n\n/** Keyboard shortcuts; the canvas keeps focus, so the root element owns the listener. */\nexport function handleKeyDown(context: InteractionContext, event: KeyboardEvent): void {\n const controller = context.deps.controller;\n const readOnly = context.deps.readOnly;\n\n if (event.key === ' ') {\n event.preventDefault();\n if (rotatePlacement(context, 90)) {\n return;\n }\n if (!readOnly) {\n context.deps.run(() => controller.rotateSelection(90));\n }\n return;\n }\n if (event.key === 'Escape') {\n cancelInteraction(context);\n return;\n }\n if (event.key === 'Enter') {\n if (controller.tool === 'wire') {\n finishWire(context);\n }\n return;\n }\n if (\n event.key === 'Backspace' &&\n controller.tool === 'wire' &&\n context.state.pendingWire.length > 0\n ) {\n event.preventDefault();\n context.state.pendingWire = context.state.pendingWire.slice(0, -1);\n context.deps.onChange();\n return;\n }\n if (event.key === 'Delete' || event.key === 'Backspace') {\n event.preventDefault();\n if (!readOnly) {\n context.deps.run(() => controller.deleteSelection());\n }\n return;\n }\n if (event.key === 'r' || event.key === 'R') {\n if (!readOnly) {\n context.deps.run(() => controller.rotateSelection(90));\n }\n return;\n }\n if (event.key === 'f' || event.key === 'F') {\n context.deps.onFit();\n return;\n }\n if ((event.ctrlKey || event.metaKey) && (event.key === 'z' || event.key === 'Z')) {\n event.preventDefault();\n if (readOnly) {\n return;\n }\n if (event.shiftKey) {\n controller.redo();\n } else {\n controller.undo();\n }\n return;\n }\n if ((event.ctrlKey || event.metaKey) && (event.key === 'y' || event.key === 'Y')) {\n event.preventDefault();\n if (readOnly) {\n return;\n }\n controller.redo();\n return;\n }\n if (readOnly) {\n return;\n }\n const step = controller.display.gridSize > 0 ? controller.display.gridSize : 1;\n const distance = event.shiftKey ? step * 10 : step;\n const deltas: Readonly<Record<string, Point>> = {\n ArrowLeft: { x: -distance, y: 0 },\n ArrowRight: { x: distance, y: 0 },\n ArrowUp: { x: 0, y: -distance },\n ArrowDown: { x: 0, y: distance },\n };\n const delta = deltas[event.key];\n if (delta !== undefined) {\n event.preventDefault();\n context.deps.run(() => controller.moveSelectionBy(delta.x, delta.y));\n }\n}\n","import { parseDeviceReference, referencePosition, type Point } from '@mica-js/core/schematic';\nimport { snapDragOffset } from '../snapping';\nimport type { InteractionContext } from './context';\n\n/** Starts dragging a symbol; the grid is applied where it lands, not to the pointer delta. */\nexport function beginMoveDrag(context: InteractionContext, page: Point, symbolId: string): boolean {\n const symbol = context.deps.controller.document.sheet.symbols.find(\n (item) => item.id === symbolId,\n );\n context.state.drag = {\n mode: 'move',\n origin: page,\n anchor: symbol === undefined ? page : { x: symbol.x, y: symbol.y },\n offset: { x: 0, y: 0 },\n };\n return true;\n}\n\nexport function beginReferenceDrag(\n context: InteractionContext,\n page: Point,\n symbolId: string,\n): boolean {\n const symbol = context.deps.controller.document.sheet.symbols.find(\n (item) => item.id === symbolId,\n );\n if (symbol === undefined) {\n return false;\n }\n const start = referenceWorldPosition(context, symbol);\n context.state.drag = {\n mode: 'reference',\n symbolId: symbol.id,\n start,\n origin: page,\n position: start,\n };\n return true;\n}\n\n/** Updates an in-flight move drag; returns `true` when this drag is the active one. */\nexport function updateMoveDrag(context: InteractionContext, page: Point): boolean {\n const drag = context.state.drag;\n if (drag?.mode !== 'move') {\n return false;\n }\n const next = snapDragOffset(drag.anchor, drag.origin, page, context.deps.controller.display);\n if (next.x !== drag.offset.x || next.y !== drag.offset.y) {\n context.state.drag = { ...drag, offset: next };\n context.deps.onChange();\n }\n return true;\n}\n\nexport function updateReferenceDrag(context: InteractionContext, page: Point): boolean {\n const drag = context.state.drag;\n if (drag?.mode !== 'reference') {\n return false;\n }\n context.state.drag = {\n ...drag,\n position: {\n x: drag.start.x + (page.x - drag.origin.x),\n y: drag.start.y + (page.y - drag.origin.y),\n },\n };\n context.deps.onChange();\n return true;\n}\n\n/** Commits a finished move drag; returns whether an edit was recorded. */\nexport function finishMoveDrag(\n context: InteractionContext,\n drag: { readonly offset: Point },\n): boolean {\n if (drag.offset.x === 0 && drag.offset.y === 0) {\n return false;\n }\n const { offset } = drag;\n context.deps.run(() => context.deps.controller.moveSelectionBy(offset.x, offset.y));\n return true;\n}\n\nexport function finishReferenceDrag(\n context: InteractionContext,\n drag: {\n readonly symbolId: string;\n readonly start: Point;\n readonly position: Point;\n },\n): boolean {\n const dx = drag.position.x - drag.start.x;\n const dy = drag.position.y - drag.start.y;\n if (dx === 0 && dy === 0) {\n return false;\n }\n context.deps.run(() => context.deps.controller.moveReferenceBy(drag.symbolId, dx, dy));\n return true;\n}\n\n/** World position of the reference designator of `symbol`, used as the drag anchor. */\nexport function referenceWorldPosition(\n context: InteractionContext,\n symbol: {\n readonly id: string;\n readonly device: string;\n readonly x: number;\n readonly y: number;\n readonly rotation: number;\n readonly reference?: Point;\n },\n): Point {\n const reference = parseDeviceReference(symbol.device);\n const definition =\n reference === undefined ? undefined : context.deps.devices?.getDeviceSymbol(reference);\n return referencePosition(symbol, definition?.bounds, symbol.reference);\n}\n","import type { DeviceSymbolProvider, Point } from '@mica-js/core/schematic';\nimport type { SchematicEditorController } from '../../controller/controller';\nimport { screenToPage, type ViewportState } from '../../render/viewport';\nimport { MIN_HIT_PIXELS, snapForWire, type SnapContext, type WireAxis } from '../snapping';\nimport type { EditorViewport } from '../viewport-state';\n\nexport interface PointerDeps {\n readonly controller: SchematicEditorController;\n readonly devices: DeviceSymbolProvider | undefined;\n readonly viewport: EditorViewport;\n readonly canvas: HTMLCanvasElement;\n}\n\n/** Screen-space geometry of the canvas: event → page coordinates, hit tolerance and snapping. */\nexport class Pointer {\n readonly #deps: PointerDeps;\n\n constructor(deps: PointerDeps) {\n this.#deps = deps;\n }\n\n viewport(): ViewportState {\n return this.#deps.viewport.state;\n }\n\n screen(event: PointerEvent | MouseEvent | WheelEvent): Point {\n const rect = this.#deps.canvas.getBoundingClientRect();\n return { x: event.clientX - rect.left, y: event.clientY - rect.top };\n }\n\n page(event: PointerEvent | MouseEvent | WheelEvent): Point {\n return screenToPage(this.viewport(), this.screen(event));\n }\n\n /** Hit tolerance in page units, so it stays constant on screen while zooming. */\n tolerance(): number {\n return MIN_HIT_PIXELS / this.viewport().scale;\n }\n\n snapContext(): SnapContext {\n return {\n controller: this.#deps.controller,\n devices: this.#deps.devices,\n tolerance: this.tolerance(),\n };\n }\n\n snapWire(point: Point): Point {\n return snapForWire(this.snapContext(), point);\n }\n\n /** Orientation of the existing wire under `point`, so a branch can approach it perpendicularly. */\n hostAxisAt(point: Point): WireAxis | undefined {\n const hit = this.#deps.controller.hitTest(point, {\n includeSymbols: false,\n tolerance: this.tolerance(),\n });\n if (hit?.kind !== 'wire') {\n return undefined;\n }\n const wire = this.#deps.controller.document.sheet.wires.find((item) => item.id === hit.id);\n const a = wire?.points[hit.segment];\n const b = wire?.points[hit.segment + 1];\n if (a === undefined || b === undefined) {\n return undefined;\n }\n return a.y === b.y ? 'horizontal' : a.x === b.x ? 'vertical' : undefined;\n }\n}\n","import type { Point } from '@mica-js/core/schematic';\nimport { snapToGrid, type WireAxis } from '../snapping';\nimport type { InteractionContext } from './context';\n\n/** Starts dragging a wire segment; the moved run is snapped so it lands on grid lines. */\nexport function beginSegmentDrag(\n context: InteractionContext,\n page: Point,\n wireId: string,\n): boolean {\n const hit = context.deps.controller.hitTest(page, {\n includeSymbols: false,\n tolerance: context.pointer.tolerance(),\n });\n if (hit?.kind !== 'wire' || hit.id !== wireId) {\n return false;\n }\n context.state.drag = {\n mode: 'segment',\n wireId: hit.id,\n segment: hit.segment,\n origin: page,\n delta: { x: 0, y: 0 },\n };\n return true;\n}\n\n/** Updates an in-flight segment drag; returns `true` when this drag is the active one. */\nexport function updateSegmentDrag(context: InteractionContext, page: Point): boolean {\n const drag = context.state.drag;\n if (drag?.mode !== 'segment') {\n return false;\n }\n const wire = context.deps.controller.document.sheet.wires.find((item) => item.id === drag.wireId);\n const start = wire?.points[drag.segment];\n const end = wire?.points[drag.segment + 1];\n if (wire === undefined || start === undefined || end === undefined) {\n return true;\n }\n // Segments only slide along their normal, so the wire stays orthogonal; the moved vertex is\n // snapped (not the delta) so the run lands on grid lines.\n const horizontal = start.y === end.y;\n const target = snapToGrid(\n horizontal\n ? { x: start.x, y: start.y + (page.y - drag.origin.y) }\n : { x: start.x + (page.x - drag.origin.x), y: start.y },\n context.deps.controller.display,\n );\n const candidate = horizontal ? { x: 0, y: target.y - start.y } : { x: target.x - start.x, y: 0 };\n if (candidate.x !== drag.delta.x || candidate.y !== drag.delta.y) {\n context.state.drag = { ...drag, delta: candidate };\n context.deps.onChange();\n }\n return true;\n}\n\n/** Commits a finished segment drag; returns whether an edit was recorded. */\nexport function finishSegmentDrag(\n context: InteractionContext,\n drag: { readonly wireId: string; readonly segment: number; readonly delta: Point },\n): boolean {\n if (drag.delta.x === 0 && drag.delta.y === 0) {\n return false;\n }\n context.deps.run(() =>\n context.deps.controller.moveWireSegment(drag.wireId, drag.segment, drag.delta),\n );\n return true;\n}\n\n/** Wire preview for the renderer, plus the orientation helper used by the wire tool. */\nexport function wirePreview(\n context: InteractionContext,\n): { readonly wireId: string; readonly points: readonly Point[] } | undefined {\n const drag = context.state.drag;\n if (drag?.mode !== 'segment') {\n return undefined;\n }\n const points = context.deps.controller.previewWireSegment(drag.wireId, drag.segment, drag.delta);\n return points === undefined ? undefined : { wireId: drag.wireId, points };\n}\n\nexport type { WireAxis };\n","import type { Point, Rect, SchematicHit } from '@mica-js/core/schematic';\nimport { rectOf } from '../selection-box';\n\nexport type DragInteraction =\n | { readonly mode: 'pan'; readonly lastX: number; readonly lastY: number }\n | { readonly mode: 'marquee'; readonly origin: Point; readonly current: Point }\n | {\n readonly mode: 'move';\n readonly origin: Point;\n /** World position of the dragged symbol when the drag started. */\n readonly anchor: Point;\n readonly offset: Point;\n }\n | {\n readonly mode: 'reference';\n readonly symbolId: string;\n /** Reference anchor when the drag started. */\n readonly start: Point;\n readonly origin: Point;\n readonly position: Point;\n }\n | {\n readonly mode: 'segment';\n readonly wireId: string;\n readonly segment: number;\n readonly origin: Point;\n readonly delta: Point;\n }\n | undefined;\n\n/**\n * Transient interaction state owned by the canvas. Nothing here belongs in the document, so the\n * controller never sees hovers, in-progress wires or previews.\n */\nexport class InteractionState {\n hover: SchematicHit | undefined;\n drag: DragInteraction;\n pendingWire: Point[] = [];\n cursorPoint: Point | undefined;\n placementRotation = 0;\n\n get marquee(): Rect | undefined {\n return this.drag?.mode === 'marquee' ? rectOf(this.drag.origin, this.drag.current) : undefined;\n }\n\n /** Live offset of the symbols being dragged. */\n get dragOffset(): Point | undefined {\n if (this.drag?.mode !== 'move') {\n return undefined;\n }\n const { offset } = this.drag;\n return offset.x === 0 && offset.y === 0 ? undefined : offset;\n }\n\n /** Reference designator being dragged, in world coordinates. */\n get referencePreview(): { readonly symbolId: string; readonly position: Point } | undefined {\n return this.drag?.mode === 'reference'\n ? { symbolId: this.drag.symbolId, position: this.drag.position }\n : undefined;\n }\n\n /** Drops the interaction in progress; called when the tool changes or an edit is cancelled. */\n reset(): void {\n this.pendingWire = [];\n this.cursorPoint = undefined;\n this.placementRotation = 0;\n this.drag = undefined;\n }\n}\n","import type { Point, Rect, SchematicHit } from '@mica-js/core/schematic';\nimport type { EditorSelection } from '../../controller/types';\nimport type { EditorInputDeps, InteractionContext } from './context';\nimport { cancelInteraction, handleKeyDown } from './keyboard';\nimport {\n beginMoveDrag,\n beginReferenceDrag,\n finishMoveDrag,\n finishReferenceDrag,\n updateMoveDrag,\n updateReferenceDrag,\n} from './move';\nimport {\n place,\n placementDevice,\n placementPreview,\n rotatePlacement,\n snapPlacementPoint,\n} from './placement';\nimport { Pointer } from './pointer';\nimport { finishMarquee, sameHit, selectItem, selectionAt, selectionFromHit } from './selection';\nimport { beginSegmentDrag, finishSegmentDrag, updateSegmentDrag, wirePreview } from './segment';\nimport { InteractionState } from './state';\nimport { addWirePoint, finishWire, pendingWireWithCursor, startWireAtNode } from './wire';\n\nexport type { EditorInputDeps } from './context';\n\n/**\n * Pointer and keyboard state machine: panning, rubber-band selection, wire drawing, placement\n * previews and shortcuts. It owns the transient interaction state and delegates to the modules\n * under `interactions/`, which never touch the DOM directly.\n */\nexport class EditorInput {\n readonly #context: InteractionContext;\n #detached = false;\n\n constructor(deps: EditorInputDeps) {\n this.#context = {\n deps,\n state: new InteractionState(),\n pointer: new Pointer({\n controller: deps.controller,\n devices: deps.devices,\n viewport: deps.viewport,\n canvas: deps.canvas,\n }),\n };\n }\n\n get hover(): SchematicHit | undefined {\n return this.#context.state.hover;\n }\n\n get pendingWire(): readonly Point[] {\n return this.#context.state.pendingWire;\n }\n\n get cursorPoint(): Point | undefined {\n return this.#context.state.cursorPoint;\n }\n\n get marquee(): Rect | undefined {\n return this.#context.state.marquee;\n }\n\n /** Live offset of the symbols being dragged. */\n get dragOffset(): Point | undefined {\n return this.#context.state.dragOffset;\n }\n\n /** Wire being reshaped by a segment drag, so the renderer can show it before the commit. */\n get wirePreview(): { readonly wireId: string; readonly points: readonly Point[] } | undefined {\n return wirePreview(this.#context);\n }\n\n /** Reference designator being dragged, in world coordinates. */\n get referencePreview(): { readonly symbolId: string; readonly position: Point } | undefined {\n return this.#context.state.referencePreview;\n }\n\n /** Placement ghost for the current tool or armed device, if the pointer is inside the canvas. */\n get placementPreview(): ReturnType<typeof placementPreview> {\n return placementPreview(this.#context);\n }\n\n get pendingWireWithCursor(): readonly Point[] {\n return pendingWireWithCursor(this.#context);\n }\n\n /** Rotates the ghost while a placement tool is active. */\n rotatePlacement(degrees: number): boolean {\n return rotatePlacement(this.#context, degrees);\n }\n\n /** Drops the in-progress wire; called when the tool changes. */\n resetTransient(): void {\n this.#context.state.reset();\n }\n\n attach(): void {\n const { canvas, root } = this.#context.deps;\n canvas.addEventListener('pointerdown', this.#onPointerDown);\n canvas.addEventListener('pointermove', this.#onPointerMove);\n canvas.addEventListener('pointerup', this.#onPointerUp);\n canvas.addEventListener('pointercancel', this.#onPointerUp);\n canvas.addEventListener('pointerleave', this.#onPointerLeave);\n canvas.addEventListener('wheel', this.#onWheel, { passive: false });\n canvas.addEventListener('dblclick', this.#onDoubleClick);\n canvas.addEventListener('contextmenu', this.#onContextMenu);\n root.addEventListener('keydown', this.#onKeyDown);\n root.addEventListener('keyup', this.#onKeyUp);\n root.ownerDocument.addEventListener('keydown', this.#onDocumentKeyDown);\n }\n\n detach(): void {\n if (this.#detached) {\n return;\n }\n this.#detached = true;\n const { canvas, root } = this.#context.deps;\n canvas.removeEventListener('pointerdown', this.#onPointerDown);\n canvas.removeEventListener('pointermove', this.#onPointerMove);\n canvas.removeEventListener('pointerup', this.#onPointerUp);\n canvas.removeEventListener('pointercancel', this.#onPointerUp);\n canvas.removeEventListener('pointerleave', this.#onPointerLeave);\n canvas.removeEventListener('wheel', this.#onWheel);\n canvas.removeEventListener('dblclick', this.#onDoubleClick);\n canvas.removeEventListener('contextmenu', this.#onContextMenu);\n root.removeEventListener('keydown', this.#onKeyDown);\n root.removeEventListener('keyup', this.#onKeyUp);\n root.ownerDocument.removeEventListener('keydown', this.#onDocumentKeyDown);\n }\n\n #onPointerDown = (event: PointerEvent): void => {\n const { deps, state, pointer } = this.#context;\n deps.root.focus();\n const screen = pointer.screen(event);\n const page = pointer.page(event);\n\n if (event.button === 1) {\n event.preventDefault();\n state.drag = { mode: 'pan', lastX: screen.x, lastY: screen.y };\n deps.canvas.setPointerCapture(event.pointerId);\n return;\n }\n if (event.button !== 0) {\n return;\n }\n\n if (deps.controller.tool === 'wire' && !deps.readOnly) {\n addWirePoint(this.#context, page);\n return;\n }\n if (!deps.readOnly && placementDevice(this.#context) !== undefined) {\n place(this.#context, page);\n return;\n }\n if (startWireAtNode(this.#context, page)) {\n return;\n }\n\n const selection = selectionAt(this.#context, page);\n if (selection === undefined) {\n selectItem(this.#context, undefined, event.shiftKey);\n state.drag = { mode: 'marquee', origin: page, current: page };\n deps.canvas.setPointerCapture(event.pointerId);\n deps.onChange();\n return;\n }\n selectItem(this.#context, selection, event.shiftKey);\n if (!deps.readOnly) {\n const started = beginDragFor(this.#context, page, selection);\n if (started) {\n deps.canvas.setPointerCapture(event.pointerId);\n }\n }\n deps.onChange();\n };\n\n #onPointerMove = (event: PointerEvent): void => {\n const { deps, state, pointer } = this.#context;\n const screen = pointer.screen(event);\n const page = pointer.page(event);\n\n if (state.drag?.mode === 'pan') {\n deps.viewport.pan(screen.x - state.drag.lastX, screen.y - state.drag.lastY);\n state.drag = { mode: 'pan', lastX: screen.x, lastY: screen.y };\n deps.onChange();\n return;\n }\n if (state.drag?.mode === 'marquee') {\n state.drag = { mode: 'marquee', origin: state.drag.origin, current: page };\n deps.onChange();\n return;\n }\n if (updateMoveDrag(this.#context, page)) {\n return;\n }\n if (updateReferenceDrag(this.#context, page)) {\n return;\n }\n if (updateSegmentDrag(this.#context, page)) {\n return;\n }\n\n const device = placementDevice(this.#context);\n if (deps.controller.tool === 'wire') {\n state.cursorPoint = pointer.snapWire(page);\n deps.onChange();\n return;\n }\n if (device !== undefined) {\n // Same snapping as the click so the ghost already shows where the symbol will land.\n state.cursorPoint = snapPlacementPoint(this.#context, page, device);\n deps.onChange();\n return;\n }\n\n const next = deps.controller.hitTest(page, { tolerance: pointer.tolerance() });\n if (!sameHit(next, state.hover)) {\n state.hover = next;\n deps.onChange();\n }\n };\n\n #onPointerUp = (event: PointerEvent): void => {\n const { deps, state } = this.#context;\n const drag = state.drag;\n state.drag = undefined;\n if (deps.canvas.hasPointerCapture(event.pointerId)) {\n deps.canvas.releasePointerCapture(event.pointerId);\n }\n if (drag?.mode === 'marquee') {\n finishMarquee(this.#context, drag.origin, drag.current);\n return;\n }\n if (drag?.mode === 'move') {\n if (!finishMoveDrag(this.#context, drag)) {\n deps.onChange();\n }\n return;\n }\n if (drag?.mode === 'reference') {\n if (!finishReferenceDrag(this.#context, drag)) {\n deps.onChange();\n }\n return;\n }\n if (drag?.mode === 'segment') {\n if (!finishSegmentDrag(this.#context, drag)) {\n deps.onChange();\n }\n return;\n }\n if (drag !== undefined) {\n deps.onChange();\n }\n };\n\n #onPointerLeave = (): void => {\n const { deps, state } = this.#context;\n if (state.hover !== undefined && state.drag === undefined) {\n state.hover = undefined;\n deps.onChange();\n }\n };\n\n #onWheel = (event: WheelEvent): void => {\n const { deps, pointer } = this.#context;\n event.preventDefault();\n deps.viewport.zoomAt(pointer.screen(event), event.deltaY < 0 ? 1.1 : 1 / 1.1);\n deps.onChange();\n };\n\n #onDoubleClick = (event: MouseEvent): void => {\n const { deps, pointer } = this.#context;\n if (deps.controller.tool === 'wire') {\n finishWire(this.#context);\n return;\n }\n const page = pointer.page(event);\n const hit = deps.controller.hitTest(page, { tolerance: pointer.tolerance() });\n const selection = hit === undefined ? undefined : selectionFromHit(hit);\n if (selection !== undefined) {\n deps.controller.setSelection([selection]);\n }\n };\n\n #onContextMenu = (event: Event): void => {\n event.preventDefault();\n };\n\n #onKeyDown = (event: KeyboardEvent): void => {\n handleKeyDown(this.#context, event);\n };\n\n #onKeyUp = (): void => {\n // No key-up handling: Space now rotates instead of acting as a pan modifier.\n };\n\n /**\n * Esc fallback for hosts that arm placement from their own UI: the event may never reach the\n * editor root, so listen on the document while an interaction is pending.\n */\n #onDocumentKeyDown = (event: KeyboardEvent): void => {\n const { deps } = this.#context;\n if (event.key !== 'Escape' || event.defaultPrevented) {\n return;\n }\n if (deps.root.contains(event.target as Node | null)) {\n return;\n }\n if (cancelInteraction(this.#context)) {\n event.preventDefault();\n }\n };\n}\n\nfunction beginDragFor(\n context: InteractionContext,\n page: Point,\n selection: EditorSelection,\n): boolean {\n switch (selection.kind) {\n case 'symbol':\n return beginMoveDrag(context, page, selection.id);\n case 'reference':\n return beginReferenceDrag(context, page, selection.symbolId);\n case 'wire':\n return beginSegmentDrag(context, page, selection.id);\n default:\n return false;\n }\n}\n","import type { Point } from '@mica-js/core/schematic';\nimport type { EditorSelection } from '../controller/types';\n\nexport interface SceneHighlight {\n readonly symbols: ReadonlySet<string>;\n readonly wires: ReadonlySet<string>;\n readonly junctions: ReadonlySet<string>;\n readonly vertices: readonly { readonly wireId: string; readonly index: number }[];\n}\n\n/** Translates controller selections into the flat sets the scene builder expects. */\nexport function toSceneHighlight(selection: readonly EditorSelection[]): SceneHighlight {\n const symbols = new Set<string>();\n const wires = new Set<string>();\n const junctions = new Set<string>();\n const vertices: { wireId: string; index: number }[] = [];\n for (const item of selection) {\n switch (item.kind) {\n case 'symbol':\n symbols.add(item.id);\n break;\n case 'wire':\n wires.add(item.id);\n break;\n case 'junction':\n junctions.add(item.id);\n break;\n case 'vertex':\n wires.add(item.wireId);\n vertices.push({ wireId: item.wireId, index: item.index });\n break;\n default:\n break;\n }\n }\n return { symbols, wires, junctions, vertices };\n}\n\n/** Appends the cursor to a pending wire so it rubber-bands to the pointer. */\nexport function withCursor(pending: readonly Point[], cursor: Point | undefined): readonly Point[] {\n return cursor === undefined ? pending : [...pending, cursor];\n}\n",".mica-schematic {\n position: relative;\n width: 100%;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n background: var(--mica-schematic-background);\n color: var(--mica-schematic-ui-text);\n font: 12px/1.45 var(--mica-schematic-font-family);\n outline: none;\n}\n\n.mica-schematic__canvas-host {\n position: absolute;\n inset: 0;\n overflow: hidden;\n}\n\n.mica-schematic__canvas {\n display: block;\n width: 100%;\n height: 100%;\n touch-action: none;\n}\n\n/* Floating tool strip; the editor owns it so the canvas stays usable without a host toolbar. */\n.mica-schematic__toolbar {\n position: absolute;\n top: 8px;\n right: 8px;\n z-index: 1;\n display: flex;\n gap: 4px;\n align-items: center;\n padding: 3px;\n border: 1px solid var(--mica-schematic-ui-border);\n border-radius: 8px;\n background: color-mix(in srgb, var(--mica-schematic-ui-surface) 88%, transparent);\n box-shadow: 0 4px 12px rgb(0 0 0 / 18%);\n backdrop-filter: blur(6px);\n}\n\n.mica-schematic--no-toolbar .mica-schematic__toolbar {\n display: none;\n}\n\n.mica-schematic__tool {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 24px;\n padding: 0;\n border: 1px solid transparent;\n border-radius: 6px;\n background: transparent;\n color: var(--mica-schematic-ui-muted-text);\n font: inherit;\n cursor: pointer;\n}\n\n.mica-schematic__tool:hover:not(:disabled) {\n color: var(--mica-schematic-ui-text);\n background: var(--mica-schematic-ui-border);\n}\n\n.mica-schematic__tool[aria-pressed='true'] {\n background: var(--mica-schematic-ui-accent);\n color: var(--mica-schematic-ui-accent-text);\n}\n\n.mica-schematic__tool:focus-visible {\n outline: 2px solid var(--mica-schematic-focus-ring);\n outline-offset: 1px;\n}\n\n.mica-schematic__tool:disabled {\n cursor: default;\n opacity: 0.5;\n}\n","import styles from './editor.css?inline';\n\n/** Editor chrome styles, injected as a single `<style>` element inside the editor root. */\nexport const EDITOR_STYLES: string = styles;\n","import type { EditorTool } from '../controller/types';\n\nexport interface ToolIcon {\n readonly tool: EditorTool;\n readonly label: string;\n /** 16×16 figure drawn with `currentColor`: stroked segments plus terminal dots. */\n readonly segments: readonly string[];\n readonly dots: readonly (readonly [number, number])[];\n}\n\n/** Toolbar entries, in display order. */\nexport const TOOL_ICONS: readonly ToolIcon[] = [\n {\n // Classic pointer arrow: the select tool the other tools fall back to.\n tool: 'select',\n label: '选择',\n segments: ['M4 2.5 L4 12.5 L6.6 10.1 L8.4 13.5 L10 12.7 L8.2 9.4 L11.8 9.4 Z'],\n dots: [],\n },\n {\n tool: 'wire',\n label: '导线',\n segments: ['M3.5 12.5 L12.5 3.5'],\n dots: [\n [3.5, 12.5],\n [12.5, 3.5],\n ],\n },\n {\n tool: 'power',\n label: '电源',\n segments: ['M8 14 V6', 'M4 6 H12'],\n dots: [[8, 14]],\n },\n {\n tool: 'ground',\n label: '地',\n segments: ['M8 3 V8', 'M3.5 8 H12.5', 'M5.5 11 H10.5', 'M7 14 H9'],\n dots: [[8, 3]],\n },\n {\n tool: 'label',\n label: '网络标签',\n segments: ['M8 4 V12', 'M4.5 8 L8 4 L11.5 8'],\n dots: [[8, 12]],\n },\n {\n tool: 'text',\n label: '文本',\n segments: ['M4 4 H12', 'M8 4 V12'],\n dots: [],\n },\n];\n\nconst SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\nexport function createToolIcon(doc: Document, icon: ToolIcon): SVGSVGElement {\n const svg = doc.createElementNS(SVG_NAMESPACE, 'svg');\n svg.setAttribute('viewBox', '0 0 16 16');\n svg.setAttribute('width', '16');\n svg.setAttribute('height', '16');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '1.4');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n svg.setAttribute('aria-hidden', 'true');\n for (const d of icon.segments) {\n const path = doc.createElementNS(SVG_NAMESPACE, 'path');\n path.setAttribute('d', d);\n svg.append(path);\n }\n for (const [cx, cy] of icon.dots) {\n const circle = doc.createElementNS(SVG_NAMESPACE, 'circle');\n circle.setAttribute('cx', String(cx));\n circle.setAttribute('cy', String(cy));\n circle.setAttribute('r', '1.5');\n circle.setAttribute('fill', 'currentColor');\n circle.setAttribute('stroke', 'none');\n svg.append(circle);\n }\n return svg;\n}\n","import type { EditorTool } from '../controller/types';\nimport { EDITOR_STYLES } from '../styles';\nimport { TOOL_ICONS, createToolIcon } from './icons';\n\nexport interface EditorShell {\n readonly root: HTMLElement;\n readonly canvasHost: HTMLElement;\n readonly canvas: HTMLCanvasElement;\n readonly toolButtons: ReadonlyMap<EditorTool, HTMLButtonElement>;\n setToolActive(tool: EditorTool): void;\n}\n\nexport interface ShellOptions {\n readonly document: Document;\n readonly readOnly: boolean;\n readonly toolbar: boolean;\n readonly onToolClick: (tool: EditorTool) => void;\n}\n\n/** Builds the canvas surface and the floating tool strip; it owns no behaviour beyond wiring. */\nexport function createShell(options: ShellOptions): EditorShell {\n const doc = options.document;\n const root = doc.createElement('div');\n root.className = 'mica-schematic';\n root.tabIndex = 0;\n\n const style = doc.createElement('style');\n style.textContent = EDITOR_STYLES;\n\n const canvasHost = doc.createElement('div');\n canvasHost.className = 'mica-schematic__canvas-host';\n\n const canvas = doc.createElement('canvas');\n canvas.className = 'mica-schematic__canvas';\n canvasHost.append(canvas);\n\n root.append(style, canvasHost);\n\n const toolButtons = new Map<EditorTool, HTMLButtonElement>();\n if (options.toolbar) {\n const toolbar = doc.createElement('div');\n toolbar.className = 'mica-schematic__toolbar';\n for (const icon of TOOL_ICONS) {\n const button = doc.createElement('button');\n button.type = 'button';\n button.className = 'mica-schematic__tool';\n button.title = icon.label;\n button.setAttribute('aria-label', icon.label);\n button.disabled = options.readOnly;\n button.append(createToolIcon(doc, icon));\n button.addEventListener('click', () => options.onToolClick(icon.tool));\n toolButtons.set(icon.tool, button);\n toolbar.append(button);\n }\n root.append(toolbar);\n } else {\n root.classList.add('mica-schematic--no-toolbar');\n }\n\n return {\n root,\n canvasHost,\n canvas,\n toolButtons,\n setToolActive(tool) {\n for (const [candidate, button] of toolButtons) {\n button.setAttribute('aria-pressed', String(candidate === tool));\n }\n },\n };\n}\n","import type { Point, Rect } from '@mica-js/core/schematic';\nimport {\n DEFAULT_VIEWPORT_LIMITS,\n IDENTITY_VIEWPORT,\n fitBounds,\n panBy,\n resolveViewportLimits,\n zoomAt,\n type ViewportLimits,\n type ViewportState,\n} from '../render/viewport';\n\n/**\n * Owns the viewport and the \"auto fit until the user takes over\" rule.\n * An empty canvas keeps refitting while the container resizes.\n */\nexport class EditorViewport {\n #state: ViewportState = IDENTITY_VIEWPORT;\n #autoFit = true;\n readonly #limits: ViewportLimits;\n\n constructor(limits: ViewportLimits = DEFAULT_VIEWPORT_LIMITS) {\n this.#limits = resolveViewportLimits(limits);\n }\n\n get state(): ViewportState {\n return this.#state;\n }\n\n get limits(): ViewportLimits {\n return this.#limits;\n }\n\n get autoFit(): boolean {\n return this.#autoFit;\n }\n\n /** Fits `bounds` into the given viewport size and re-enables auto fit. */\n fit(bounds: Rect | undefined, size: { readonly width: number; readonly height: number }): void {\n if (size.width === 0 || size.height === 0) {\n return;\n }\n this.#state = fitBounds(\n bounds ?? { x: -50, y: -50, width: 100, height: 100 },\n size,\n 48,\n this.#limits,\n );\n this.#autoFit = true;\n }\n\n pan(dx: number, dy: number): void {\n this.#autoFit = false;\n this.#state = panBy(this.#state, dx, dy);\n }\n\n zoomAt(screenPoint: Point, factor: number): void {\n this.#autoFit = false;\n this.#state = zoomAt(this.#state, screenPoint, factor, this.#limits);\n }\n\n zoomTo(scale: number, center: Point): void {\n if (scale <= 0 || !Number.isFinite(scale)) {\n return;\n }\n this.#autoFit = false;\n this.#state = zoomAt(this.#state, center, scale / this.#state.scale, this.#limits);\n }\n\n /** Restores a saved viewport (already clamped by the caller); turns auto fit off. */\n setState(state: ViewportState): void {\n this.#autoFit = false;\n this.#state = state;\n }\n\n /** Turns off auto fit when the user interacts with the view. */\n takeOver(): void {\n this.#autoFit = false;\n }\n}\n","import type {\n DesignatorFactory,\n DeviceSymbolProvider,\n Point,\n SchematicDocument,\n SchematicError,\n} from '@mica-js/core/schematic';\nimport { serializeSchematic } from '@mica-js/core/schematic';\nimport { SchematicEditorController } from '../controller/controller';\nimport { sameSelection } from '../controller/selection';\nimport type {\n DisplayOptions,\n EditorRenderState,\n EditorSelection,\n EditorState,\n EditorTool,\n} from '../controller/types';\nimport { CanvasSchematicRenderer } from '../render/canvas-renderer';\nimport { buildSchematicScene } from '../render/scene';\nimport { resolveSchematicTheme, themeToCssVariables, type SchematicTheme } from '../render/theme';\nimport {\n resolveViewportLimits,\n clampViewport,\n pageToScreen,\n screenToPage,\n type ViewportLimits,\n type ViewportState,\n} from '../render/viewport';\nimport { EditorInput } from './interactions/input';\nimport { toSceneHighlight } from './scene-input';\nimport { createShell } from './shell';\nimport { EditorViewport } from './viewport-state';\n\nexport interface MountSchematicEditorOptions {\n /** Caller-provided container; the editor only appends and removes its own root. */\n readonly container: HTMLElement;\n readonly schematic: SchematicDocument;\n readonly devices?: DeviceSymbolProvider;\n readonly theme?: Partial<SchematicTheme>;\n readonly display?: Partial<DisplayOptions>;\n readonly tolerance?: number;\n readonly historyLimit?: number;\n /** Reference designator policy; defaults to the device's `designatorPrefix`, then `U`. */\n readonly createDesignator?: DesignatorFactory;\n /** Zoom range for wheel, fit and `zoomTo`; defaults to 0.25×–4×. */\n readonly zoomLimits?: Partial<ViewportLimits>;\n /** Disables the built-in interactions; the controller stays writable. */\n readonly readOnly?: boolean;\n /** Renders the floating tool strip in the canvas corner; defaults to true. */\n readonly toolbar?: boolean;\n readonly onChange?: (state: EditorState) => void;\n readonly onSelectionChange?: (selection: readonly EditorSelection[]) => void;\n readonly onToolChange?: (tool: EditorTool) => void;\n /** Fires whenever the last edit error changes; `undefined` once an edit succeeds. */\n readonly onError?: (error: SchematicError | undefined) => void;\n /** Fires on wheel/pan/fit/`zoomTo`/`setViewport` and when auto fit re-runs. */\n readonly onViewportChange?: (viewport: ViewportState) => void;\n}\n\nexport interface MountedSchematicEditor {\n readonly controller: SchematicEditorController;\n readonly root: HTMLElement;\n readonly canvas: HTMLCanvasElement;\n\n /**\n * Loads another document. By default history and selection start over; `keepHistory` records\n * the swap as one undoable edit instead.\n */\n setSchematic(document: SchematicDocument, options?: { readonly keepHistory?: boolean }): void;\n setTheme(theme: Partial<SchematicTheme>): void;\n getTheme(): SchematicTheme;\n setDisplayOptions(patch: Partial<DisplayOptions>): void;\n setTool(tool: EditorTool): void;\n /**\n * Arms placement of `device`: the next canvas click inserts it. Hosts drive this from their own\n * device list, so the editor never needs to know where the parts come from.\n *\n * @throws {SchematicError} when the device reference is malformed.\n */\n placeDevice(device: string): void;\n /** Disarms a pending placement without touching the document. */\n cancelPlacement(): void;\n fitToContent(): void;\n zoomTo(scale: number): void;\n /** Current zoom/pan; safe to persist and hand back to {@link setViewport}. */\n getViewport(): ViewportState;\n /** Restores a saved viewport; the scale is clamped to `zoomLimits` around the canvas centre. */\n setViewport(viewport: ViewportState): void;\n /** Serializes the current document as `.sch` JSON. */\n toJSON(): string;\n /** Moves keyboard focus to the canvas surface; call after host toolbar interactions. */\n focus(): void;\n /** Canvas-relative client coordinates → page coordinates (for host overlays). */\n toPage(clientPoint: Point): Point;\n /** Page coordinates → canvas-relative CSS pixels (for host overlays). */\n toScreen(pagePoint: Point): Point;\n /** Re-measures the container; call after showing a previously hidden editor. */\n resize(): void;\n /** Repaints without touching layout (e.g. after a device-pixel-ratio change). */\n invalidate(): void;\n undo(): void;\n redo(): void;\n /** Removes the DOM and listeners created by the editor, keeping the container contents. */\n dispose(): void;\n}\n\n/** Mounts a canvas schematic editor inside `options.container`. */\nexport function mountSchematicEditor(options: MountSchematicEditorOptions): MountedSchematicEditor {\n const doc = options.container.ownerDocument;\n const readOnly = options.readOnly ?? false;\n\n const controller = new SchematicEditorController({\n document: options.schematic,\n ...(options.devices === undefined ? {} : { devices: options.devices }),\n ...(options.display === undefined ? {} : { display: options.display }),\n ...(options.tolerance === undefined ? {} : { tolerance: options.tolerance }),\n ...(options.historyLimit === undefined ? {} : { historyLimit: options.historyLimit }),\n ...(options.createDesignator === undefined\n ? {}\n : { createDesignator: options.createDesignator }),\n });\n\n const shell = createShell({\n document: doc,\n readOnly,\n toolbar: options.toolbar !== false,\n onToolClick: (tool) => {\n controller.setTool(controller.tool === tool ? 'select' : tool);\n shell.root.focus();\n },\n });\n\n const viewport = new EditorViewport(resolveViewportLimits(options.zoomLimits));\n const renderer = new CanvasSchematicRenderer(shell.canvas, {\n theme: resolveSchematicTheme(options.theme),\n });\n let theme = resolveSchematicTheme(options.theme);\n let disposed = false;\n let lastSelection: readonly EditorSelection[] = [];\n let lastTool: EditorTool = controller.tool;\n let lastPlacing: string | undefined = controller.placingDevice;\n let lastError: SchematicError | undefined = controller.state.lastError;\n let lastViewport: ViewportState | undefined = viewport.state;\n\n const input = new EditorInput({\n controller,\n devices: options.devices,\n viewport,\n root: shell.root,\n canvas: shell.canvas,\n readOnly,\n onChange: () => {\n render();\n },\n onFit: () => {\n fitToContent();\n },\n run: (edit) => {\n run(edit);\n },\n });\n\n function run(edit: () => void): void {\n try {\n edit();\n } catch {\n // Errors surface through `state.lastError` / `onError`; the document stays untouched.\n }\n }\n\n function applyTheme(): void {\n for (const [name, value] of Object.entries(themeToCssVariables(theme))) {\n shell.root.style.setProperty(name, value);\n }\n renderer.setTheme(theme);\n }\n\n function render(state: EditorRenderState = controller.renderState): void {\n if (disposed) {\n return;\n }\n const scene = buildSchematicScene({\n document: state.document,\n ...(options.devices === undefined ? {} : { devices: options.devices }),\n theme,\n selection: {\n ...toSceneHighlight(state.selection),\n ...(input.dragOffset === undefined ? {} : { offset: input.dragOffset }),\n },\n ...(input.hover === undefined ? {} : { hover: input.hover }),\n tool: state.tool,\n display: {\n grid: state.display.grid,\n labels: state.display.labels,\n gridSize: state.display.gridSize,\n gridSubdivisions: state.display.gridSubdivisions,\n },\n ...(input.pendingWire.length === 0 ? {} : { pendingWire: input.pendingWireWithCursor }),\n ...(input.marquee === undefined ? {} : { marquee: input.marquee }),\n ...(input.placementPreview === undefined ? {} : { placementPreview: input.placementPreview }),\n ...(input.referencePreview === undefined ? {} : { referencePreview: input.referencePreview }),\n ...(input.wirePreview === undefined ? {} : { wirePreview: input.wirePreview }),\n });\n renderer.render(scene, viewport.state);\n if (!sameViewport(viewport.state, lastViewport)) {\n lastViewport = viewport.state;\n options.onViewportChange?.(viewport.state);\n }\n }\n\n function sync(state: EditorState): void {\n shell.setToolActive(state.tool);\n shell.canvas.style.cursor =\n state.tool === 'select' && state.placingDevice === undefined ? 'default' : 'crosshair';\n if (state.lastError !== lastError) {\n lastError = state.lastError;\n options.onError?.(state.lastError);\n }\n if (state.tool !== lastTool || state.placingDevice !== lastPlacing) {\n lastTool = state.tool;\n lastPlacing = state.placingDevice;\n input.resetTransient();\n options.onToolChange?.(state.tool);\n }\n if (!sameSelection(state.selection, lastSelection)) {\n lastSelection = state.selection;\n options.onSelectionChange?.(state.selection);\n }\n options.onChange?.(state);\n // The state came from this emit: reuse it instead of building another one for the repaint.\n render(state);\n }\n\n function resize(): void {\n const width = shell.canvasHost.clientWidth;\n const height = shell.canvasHost.clientHeight;\n if (width === 0 || height === 0) {\n return;\n }\n renderer.resize(width, height, Math.max(1, window.devicePixelRatio || 1));\n if (viewport.autoFit) {\n fitToContent();\n return;\n }\n render();\n }\n\n function fitToContent(): void {\n viewport.fit(controller.topology().bounds, {\n width: shell.canvasHost.clientWidth,\n height: shell.canvasHost.clientHeight,\n });\n render();\n }\n\n const unsubscribe = controller.subscribe(sync);\n applyTheme();\n input.attach();\n sync(controller.state);\n\n const resizeObserver = new ResizeObserver(() => resize());\n resizeObserver.observe(shell.canvasHost);\n options.container.append(shell.root);\n resize();\n\n return {\n controller,\n root: shell.root,\n canvas: shell.canvas,\n setSchematic(document: SchematicDocument, setOptions: { keepHistory?: boolean } = {}): void {\n if (setOptions.keepHistory === true) {\n run(() => controller.replace(document));\n return;\n }\n controller.reset(document);\n fitToContent();\n },\n setTheme(next: Partial<SchematicTheme>): void {\n theme = resolveSchematicTheme(next);\n applyTheme();\n render();\n },\n getTheme(): SchematicTheme {\n return theme;\n },\n setDisplayOptions(patch: Partial<DisplayOptions>): void {\n controller.setDisplayOptions(patch);\n },\n setTool(tool: EditorTool): void {\n controller.setTool(tool);\n },\n placeDevice(device: string): void {\n // Read-only editors cannot place: the canvas would have nowhere to commit the symbol.\n if (readOnly) {\n return;\n }\n controller.placeDevice(device);\n shell.root.focus();\n },\n cancelPlacement(): void {\n controller.cancelPlacement();\n },\n fitToContent,\n zoomTo(scale: number): void {\n viewport.zoomTo(scale, {\n x: shell.canvasHost.clientWidth / 2,\n y: shell.canvasHost.clientHeight / 2,\n });\n render();\n },\n getViewport(): ViewportState {\n return viewport.state;\n },\n setViewport(next: ViewportState): void {\n viewport.setState(\n clampViewport(\n next,\n { width: shell.canvasHost.clientWidth, height: shell.canvasHost.clientHeight },\n viewport.limits,\n ),\n );\n render();\n },\n toJSON(): string {\n return serializeSchematic(controller.document);\n },\n focus(): void {\n shell.root.focus();\n },\n toPage(clientPoint: Point): Point {\n const rect = shell.canvas.getBoundingClientRect();\n return screenToPage(viewport.state, {\n x: clientPoint.x - rect.left,\n y: clientPoint.y - rect.top,\n });\n },\n toScreen(pagePoint: Point): Point {\n return pageToScreen(viewport.state, pagePoint);\n },\n resize,\n invalidate: render,\n undo(): void {\n controller.undo();\n },\n redo(): void {\n controller.redo();\n },\n dispose(): void {\n disposed = true;\n unsubscribe();\n resizeObserver.disconnect();\n input.detach();\n renderer.destroy();\n shell.root.remove();\n },\n };\n}\n\nfunction sameViewport(left: ViewportState, right: ViewportState | undefined): boolean {\n return (\n right !== undefined &&\n left.scale === right.scale &&\n left.offsetX === right.offsetX &&\n left.offsetY === right.offsetY\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,40 @@
1
1
  {
2
2
  "name": "@mica-js/schematic-editor",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Mica schematic editor: canvas renderer and interaction",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/x-botlab/mica-js.git",
9
+ "directory": "packages/schematic-editor"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "dependencies": {
26
+ "@mica-js/core": "0.1.0"
27
+ },
28
+ "devDependencies": {
29
+ "typescript": "^6.0.3",
30
+ "vite": "^8.3.4",
31
+ "vite-plugin-dts": "^5.1.2",
32
+ "vitest": "^5.0.5"
33
+ },
34
+ "scripts": {
35
+ "build": "vite build",
36
+ "test": "vitest run",
37
+ "test:watch": "vitest",
38
+ "typecheck": "tsc --noEmit"
39
+ }
6
40
  }