@tscircuit/core 0.0.1023 → 0.0.1025

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -171,9 +171,9 @@ interface IIsolatedCircuit {
171
171
  interface IRootCircuit extends IIsolatedCircuit {
172
172
  }
173
173
 
174
- declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "InflateSubcircuitCircuitJson", "SourceNameDuplicateComponentRemoval", "PcbFootprintStringRender", "InitializePortsFromChildren", "CreateNetsFromProps", "AssignFallbackProps", "CreateTracesFromProps", "CreateTracesFromNetLabels", "CreateTraceHintsFromProps", "SourceGroupRender", "AssignNameToUnnamedComponents", "SourceRender", "SourceParentAttachment", "PortMatching", "OptimizeSelectorCache", "SourceTraceRender", "SourceAddConnectivityMapKey", "SourceDesignRuleChecks", "SimulationRender", "SchematicComponentRender", "SchematicPortRender", "SymbolContainerRender", "SchematicPrimitiveRender", "SchematicSymbolResize", "SchematicComponentSizeCalculation", "SchematicLayout", "SchematicTraceRender", "SchematicReplaceNetLabelsWithSymbols", "PanelBoardLayout", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbComponentSizeCalculation", "PcbComponentAnchorAlignment", "PcbLayout", "PcbBoardAutoSize", "PanelLayout", "PcbTraceHintRender", "PcbManualTraceRender", "PcbTraceRender", "PcbRouteNetIslands", "PcbCopperPourRender", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "SimulationSpiceEngineRender"];
174
+ declare const orderedRenderPhases: readonly ["RenderIsolatedSubcircuits", "ReactSubtreesRender", "InflateSubcircuitCircuitJson", "SourceNameDuplicateComponentRemoval", "PcbFootprintStringRender", "InitializePortsFromChildren", "CreateNetsFromProps", "AssignFallbackProps", "CreateTracesFromProps", "CreateTracesFromNetLabels", "CreateTraceHintsFromProps", "SourceGroupRender", "AssignNameToUnnamedComponents", "SourceRender", "SourceParentAttachment", "PortMatching", "OptimizeSelectorCache", "SourceTraceRender", "SourceAddConnectivityMapKey", "SourceDesignRuleChecks", "SimulationRender", "SchematicComponentRender", "SchematicPortRender", "SymbolContainerRender", "SchematicPrimitiveRender", "SchematicSymbolResize", "SchematicComponentSizeCalculation", "SchematicLayout", "SchematicTraceRender", "SchematicReplaceNetLabelsWithSymbols", "PanelBoardLayout", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbComponentSizeCalculation", "PcbComponentAnchorAlignment", "PcbLayout", "PcbBoardAutoSize", "PanelLayout", "PcbTraceHintRender", "PcbManualTraceRender", "PcbTraceRender", "PcbRouteNetIslands", "PcbCopperPourRender", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "SimulationSpiceEngineRender"];
175
175
  type RenderPhase = (typeof orderedRenderPhases)[number];
176
- declare const renderPhaseIndexMap: Map<"ReactSubtreesRender" | "InflateSubcircuitCircuitJson" | "SourceNameDuplicateComponentRemoval" | "PcbFootprintStringRender" | "InitializePortsFromChildren" | "CreateNetsFromProps" | "AssignFallbackProps" | "CreateTracesFromProps" | "CreateTracesFromNetLabels" | "CreateTraceHintsFromProps" | "SourceGroupRender" | "AssignNameToUnnamedComponents" | "SourceRender" | "SourceParentAttachment" | "PortMatching" | "OptimizeSelectorCache" | "SourceTraceRender" | "SourceAddConnectivityMapKey" | "SourceDesignRuleChecks" | "SimulationRender" | "SchematicComponentRender" | "SchematicPortRender" | "SymbolContainerRender" | "SchematicPrimitiveRender" | "SchematicSymbolResize" | "SchematicComponentSizeCalculation" | "SchematicLayout" | "SchematicTraceRender" | "SchematicReplaceNetLabelsWithSymbols" | "PanelBoardLayout" | "PcbComponentRender" | "PcbPrimitiveRender" | "PcbFootprintLayout" | "PcbPortRender" | "PcbPortAttachment" | "PcbComponentSizeCalculation" | "PcbComponentAnchorAlignment" | "PcbLayout" | "PcbBoardAutoSize" | "PanelLayout" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbCopperPourRender" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "SimulationSpiceEngineRender", number>;
176
+ declare const renderPhaseIndexMap: Map<"RenderIsolatedSubcircuits" | "ReactSubtreesRender" | "InflateSubcircuitCircuitJson" | "SourceNameDuplicateComponentRemoval" | "PcbFootprintStringRender" | "InitializePortsFromChildren" | "CreateNetsFromProps" | "AssignFallbackProps" | "CreateTracesFromProps" | "CreateTracesFromNetLabels" | "CreateTraceHintsFromProps" | "SourceGroupRender" | "AssignNameToUnnamedComponents" | "SourceRender" | "SourceParentAttachment" | "PortMatching" | "OptimizeSelectorCache" | "SourceTraceRender" | "SourceAddConnectivityMapKey" | "SourceDesignRuleChecks" | "SimulationRender" | "SchematicComponentRender" | "SchematicPortRender" | "SymbolContainerRender" | "SchematicPrimitiveRender" | "SchematicSymbolResize" | "SchematicComponentSizeCalculation" | "SchematicLayout" | "SchematicTraceRender" | "SchematicReplaceNetLabelsWithSymbols" | "PanelBoardLayout" | "PcbComponentRender" | "PcbPrimitiveRender" | "PcbFootprintLayout" | "PcbPortRender" | "PcbPortAttachment" | "PcbComponentSizeCalculation" | "PcbComponentAnchorAlignment" | "PcbLayout" | "PcbBoardAutoSize" | "PanelLayout" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbCopperPourRender" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "SimulationSpiceEngineRender", number>;
177
177
  type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
178
178
  type RenderPhaseStates = Record<RenderPhase, {
179
179
  initialized: boolean;
@@ -362,7 +362,7 @@ declare class IsolatedCircuit {
362
362
  children: PrimitiveComponent[];
363
363
  db: CircuitJsonUtilObjects;
364
364
  root: IsolatedCircuit | null;
365
- isRoot: boolean;
365
+ isRootCircuit: boolean;
366
366
  private _schematicDisabledOverride;
367
367
  get schematicDisabled(): boolean;
368
368
  set schematicDisabled(value: boolean);
@@ -1653,7 +1653,9 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
1653
1653
  subcircuit_id: string | null;
1654
1654
  _hasStartedAsyncAutorouting: boolean;
1655
1655
  _isInflatedFromCircuitJson: boolean;
1656
- private _normalComponentNameMap;
1656
+ _isolatedCircuitJson: AnyCircuitElement[] | null;
1657
+ get _isIsolatedSubcircuit(): boolean;
1658
+ _normalComponentNameMap: Map<string, NormalComponent[]> | null;
1657
1659
  /**
1658
1660
  * Returns a cached map of component names to NormalComponent instances within this subcircuit.
1659
1661
  * The map is built lazily on first access and cached for subsequent calls.
@@ -1684,6 +1686,8 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
1684
1686
  zodProps: Props;
1685
1687
  componentName: string;
1686
1688
  };
1689
+ runRenderPhaseForChildren(phase: RenderPhase): void;
1690
+ doInitialRenderIsolatedSubcircuits(): void;
1687
1691
  doInitialSourceGroupRender(): void;
1688
1692
  doInitialSourceRender(): void;
1689
1693
  doInitialSourceParentAttachment(): void;
@@ -131936,7 +131940,7 @@ declare class VoltageProbe extends PrimitiveComponent<typeof voltageProbeProps>
131936
131940
  declare function resolveStaticFileImport(path: string, platform?: PlatformConfig): Promise<string>;
131937
131941
 
131938
131942
  declare class RootCircuit extends IsolatedCircuit {
131939
- isRoot: boolean;
131943
+ isRootCircuit: boolean;
131940
131944
  constructor({ platform, projectUrl, }?: {
131941
131945
  platform?: PlatformConfig;
131942
131946
  projectUrl?: string;
package/dist/index.js CHANGED
@@ -117,6 +117,7 @@ import { DefaultEventPriority } from "react-reconciler/constants.js";
117
117
  import Debug from "debug";
118
118
  var debug = Debug("tscircuit:renderable");
119
119
  var orderedRenderPhases = [
120
+ "RenderIsolatedSubcircuits",
120
121
  "ReactSubtreesRender",
121
122
  "InflateSubcircuitCircuitJson",
122
123
  "SourceNameDuplicateComponentRemoval",
@@ -172,6 +173,7 @@ var renderPhaseIndexMap = new Map(
172
173
  orderedRenderPhases.map((phase, index) => [phase, index])
173
174
  );
174
175
  var asyncPhaseDependencies = {
176
+ InflateSubcircuitCircuitJson: ["RenderIsolatedSubcircuits"],
175
177
  PcbFootprintLayout: ["PcbFootprintStringRender"],
176
178
  PcbComponentSizeCalculation: ["PcbFootprintStringRender"],
177
179
  PcbLayout: ["PcbFootprintStringRender"],
@@ -951,7 +953,7 @@ var PrimitiveComponent2 = class extends Renderable {
951
953
  * components share the same names) unless you explicitly break out some ports
952
954
  */
953
955
  get isSubcircuit() {
954
- return Boolean(this.props.subcircuit) || this.lowercaseComponentName === "group" && this?.parent?.isRoot;
956
+ return Boolean(this.props.subcircuit) || this.lowercaseComponentName === "group" && this?.parent?.isRootCircuit;
955
957
  }
956
958
  get isGroup() {
957
959
  return this.lowercaseComponentName === "group";
@@ -1356,7 +1358,8 @@ var PrimitiveComponent2 = class extends Renderable {
1356
1358
  let current = this;
1357
1359
  while (current) {
1358
1360
  const maybePrimitive = current;
1359
- if (maybePrimitive.componentName === "Board") {
1361
+ const componentName = maybePrimitive.componentName;
1362
+ if (componentName === "Board" || componentName === "MountedBoard") {
1360
1363
  return maybePrimitive;
1361
1364
  }
1362
1365
  current = current.parent ?? null;
@@ -10283,7 +10286,7 @@ var TscircuitAutorouter = class {
10283
10286
  import {
10284
10287
  distance as distance8
10285
10288
  } from "circuit-json";
10286
- import Debug13 from "debug";
10289
+ import Debug14 from "debug";
10287
10290
  import "zod";
10288
10291
 
10289
10292
  // lib/components/primitive-components/TraceHint.ts
@@ -14649,74 +14652,488 @@ function addPortIdsToTracesAtJumperPads(segments, db) {
14649
14652
  return result;
14650
14653
  }
14651
14654
 
14652
- // lib/components/primitive-components/Group/Group.ts
14653
- var Group6 = class extends NormalComponent3 {
14654
- pcb_group_id = null;
14655
- schematic_group_id = null;
14656
- subcircuit_id = null;
14657
- _hasStartedAsyncAutorouting = false;
14658
- _isInflatedFromCircuitJson = false;
14659
- _normalComponentNameMap = null;
14655
+ // lib/IsolatedCircuit.ts
14656
+ import { su as su5 } from "@tscircuit/circuit-json-util";
14657
+ import Debug13 from "debug";
14658
+ import { isValidElement as isValidElement2 } from "react";
14659
+ import { identity as identity4 } from "transformation-matrix";
14660
+
14661
+ // package.json
14662
+ var package_default = {
14663
+ name: "@tscircuit/core",
14664
+ type: "module",
14665
+ version: "0.0.1024",
14666
+ types: "dist/index.d.ts",
14667
+ main: "dist/index.js",
14668
+ module: "dist/index.js",
14669
+ exports: {
14670
+ ".": {
14671
+ import: "./dist/index.js",
14672
+ types: "./dist/index.d.ts"
14673
+ }
14674
+ },
14675
+ files: [
14676
+ "dist"
14677
+ ],
14678
+ repository: {
14679
+ type: "git",
14680
+ url: "https://github.com/tscircuit/core"
14681
+ },
14682
+ scripts: {
14683
+ build: "tsup-node index.ts --format esm --dts",
14684
+ format: "biome format . --write",
14685
+ "measure-bundle": "howfat -r table .",
14686
+ "pkg-pr-new-release": "bunx pkg-pr-new publish --comment=off --peerDeps",
14687
+ "smoke-test:dist": "bun run scripts/smoke-tests/test-dist-simple-circuit.tsx",
14688
+ "build:benchmarking": "bun build --experimental-html ./benchmarking/website/index.html --outdir ./benchmarking-dist",
14689
+ "build:benchmarking:watch": `chokidar "./{benchmarking,lib}/**/*.{ts,tsx}" -c 'bun build --experimental-html ./benchmarking/website/index.html --outdir ./benchmarking-dist'`,
14690
+ "start:benchmarking": 'concurrently "bun run build:benchmarking:watch" "live-server ./benchmarking-dist"',
14691
+ "generate-test-plan": "bun run scripts/generate-test-plan.ts"
14692
+ },
14693
+ devDependencies: {
14694
+ "@biomejs/biome": "^1.8.3",
14695
+ "@resvg/resvg-js": "^2.6.2",
14696
+ "@tscircuit/alphabet": "0.0.18",
14697
+ "@tscircuit/capacity-autorouter": "^0.0.264",
14698
+ "@tscircuit/checks": "^0.0.88",
14699
+ "@tscircuit/circuit-json-util": "^0.0.77",
14700
+ "@tscircuit/common": "^0.0.20",
14701
+ "@tscircuit/copper-pour-solver": "^0.0.20",
14702
+ "@tscircuit/footprinter": "^0.0.288",
14703
+ "@tscircuit/infgrid-ijump-astar": "^0.0.35",
14704
+ "@tscircuit/log-soup": "^1.0.2",
14705
+ "@tscircuit/matchpack": "^0.0.16",
14706
+ "@tscircuit/math-utils": "^0.0.29",
14707
+ "@tscircuit/miniflex": "^0.0.4",
14708
+ "@tscircuit/ngspice-spice-engine": "^0.0.8",
14709
+ "@tscircuit/props": "^0.0.471",
14710
+ "@tscircuit/schematic-match-adapt": "^0.0.16",
14711
+ "@tscircuit/schematic-trace-solver": "^v0.0.45",
14712
+ "@tscircuit/solver-utils": "^0.0.3",
14713
+ "@tscircuit/soup-util": "^0.0.41",
14714
+ "@types/bun": "^1.2.16",
14715
+ "@types/debug": "^4.1.12",
14716
+ "@types/react": "^19.1.8",
14717
+ "@types/react-dom": "^19.1.6",
14718
+ "@types/react-reconciler": "^0.28.9",
14719
+ "bpc-graph": "^0.0.57",
14720
+ "bun-match-svg": "0.0.12",
14721
+ "calculate-elbow": "^0.0.12",
14722
+ "chokidar-cli": "^3.0.0",
14723
+ "circuit-json": "^0.0.378",
14724
+ "circuit-json-to-bpc": "^0.0.13",
14725
+ "circuit-json-to-connectivity-map": "^0.0.23",
14726
+ "circuit-json-to-gltf": "^0.0.62",
14727
+ "circuit-json-to-simple-3d": "^0.0.9",
14728
+ "circuit-json-to-spice": "^0.0.33",
14729
+ "circuit-to-svg": "^0.0.327",
14730
+ concurrently: "^9.1.2",
14731
+ "connectivity-map": "^1.0.0",
14732
+ debug: "^4.3.6",
14733
+ "eecircuit-engine": "^1.5.6",
14734
+ flatbush: "^4.5.0",
14735
+ "graphics-debug": "^0.0.60",
14736
+ howfat: "^0.3.8",
14737
+ "live-server": "^1.2.2",
14738
+ "looks-same": "^9.0.1",
14739
+ minicssgrid: "^0.0.9",
14740
+ "pkg-pr-new": "^0.0.37",
14741
+ poppygl: "^0.0.16",
14742
+ react: "^19.1.0",
14743
+ "react-dom": "^19.1.0",
14744
+ "schematic-symbols": "^0.0.208",
14745
+ spicey: "^0.0.14",
14746
+ "ts-expect": "^1.3.0",
14747
+ tsup: "^8.2.4"
14748
+ },
14749
+ peerDependencies: {
14750
+ "@tscircuit/capacity-autorouter": "*",
14751
+ "@tscircuit/checks": "*",
14752
+ "@tscircuit/circuit-json-util": "*",
14753
+ "@tscircuit/footprinter": "*",
14754
+ "@tscircuit/infgrid-ijump-astar": "*",
14755
+ "@tscircuit/math-utils": "*",
14756
+ "@tscircuit/props": "*",
14757
+ "@tscircuit/schematic-match-adapt": "*",
14758
+ "circuit-json-to-bpc": "*",
14759
+ "bpc-graph": "*",
14760
+ "@tscircuit/matchpack": "*",
14761
+ "circuit-json": "*",
14762
+ "circuit-json-to-connectivity-map": "*",
14763
+ "schematic-symbols": "*",
14764
+ typescript: "^5.0.0"
14765
+ },
14766
+ dependencies: {
14767
+ "@flatten-js/core": "^1.6.2",
14768
+ "@lume/kiwi": "^0.4.3",
14769
+ "calculate-packing": "0.0.68",
14770
+ "css-select": "5.1.0",
14771
+ "format-si-unit": "^0.0.3",
14772
+ nanoid: "^5.0.7",
14773
+ "performance-now": "^2.1.0",
14774
+ "react-reconciler": "^0.32.0",
14775
+ "svg-path-commander": "^2.1.11",
14776
+ "transformation-matrix": "^2.16.1",
14777
+ zod: "^3.25.67"
14778
+ }
14779
+ };
14780
+
14781
+ // lib/IsolatedCircuit.ts
14782
+ var IsolatedCircuit = class {
14783
+ firstChild = null;
14784
+ children;
14785
+ db;
14786
+ root = null;
14787
+ isRootCircuit = false;
14788
+ _schematicDisabledOverride;
14789
+ get schematicDisabled() {
14790
+ if (this._schematicDisabledOverride !== void 0) {
14791
+ return this._schematicDisabledOverride;
14792
+ }
14793
+ if (this.platform?.schematicDisabled !== void 0) {
14794
+ return this.platform.schematicDisabled;
14795
+ }
14796
+ const board = this._getBoard();
14797
+ return board?._parsedProps?.schematicDisabled ?? false;
14798
+ }
14799
+ set schematicDisabled(value) {
14800
+ this._schematicDisabledOverride = value;
14801
+ }
14802
+ pcbDisabled = false;
14803
+ pcbRoutingDisabled = false;
14804
+ _featureMspSchematicTraceRouting = true;
14660
14805
  /**
14661
- * Returns a cached map of component names to NormalComponent instances within this subcircuit.
14662
- * The map is built lazily on first access and cached for subsequent calls.
14806
+ * The IsolatedCircuit name is usually set by the platform, it's not required but
14807
+ * if supplied can identify the circuit in certain effects, e.g. it is passed
14808
+ * as the display_name parameter for autorouting effects.
14663
14809
  */
14664
- getNormalComponentNameMap() {
14665
- if (this._normalComponentNameMap) {
14666
- return this._normalComponentNameMap;
14667
- }
14668
- const nameMap = /* @__PURE__ */ new Map();
14669
- const collectNamedComponents = (component) => {
14670
- if (component._isNormalComponent && component.name) {
14671
- const componentsWithSameName = nameMap.get(component.name);
14672
- if (componentsWithSameName) {
14673
- componentsWithSameName.push(component);
14674
- } else {
14675
- nameMap.set(component.name, [component]);
14676
- }
14677
- }
14678
- for (const child of component.children) {
14679
- if (!child.isSubcircuit) collectNamedComponents(child);
14680
- }
14681
- };
14682
- for (const child of this.children) {
14683
- if (!child.isSubcircuit) collectNamedComponents(child);
14810
+ name;
14811
+ platform;
14812
+ /**
14813
+ * Optional URL pointing to where this project is hosted or documented.
14814
+ * When provided it is stored in the source_project_metadata.project_url field
14815
+ * of the generated Circuit JSON.
14816
+ */
14817
+ projectUrl;
14818
+ _hasRenderedAtleastOnce = false;
14819
+ _asyncEffectIdsByPhase = /* @__PURE__ */ new Map();
14820
+ _asyncEffectPhaseById = /* @__PURE__ */ new Map();
14821
+ constructor({
14822
+ platform,
14823
+ projectUrl
14824
+ } = {}) {
14825
+ this.children = [];
14826
+ this.db = su5([]);
14827
+ this.platform = platform;
14828
+ this.projectUrl = projectUrl;
14829
+ this.pcbDisabled = platform?.pcbDisabled ?? false;
14830
+ this.root = this;
14831
+ }
14832
+ add(componentOrElm) {
14833
+ let component;
14834
+ if (isValidElement2(componentOrElm)) {
14835
+ component = createInstanceFromReactElement(componentOrElm);
14836
+ } else {
14837
+ component = componentOrElm;
14684
14838
  }
14685
- this._normalComponentNameMap = nameMap;
14686
- return nameMap;
14839
+ this.children.push(component);
14687
14840
  }
14688
- _asyncAutoroutingResult = null;
14689
- get config() {
14690
- return {
14691
- zodProps: groupProps,
14692
- componentName: "Group"
14841
+ setPlatform(platform) {
14842
+ this.platform = {
14843
+ ...this.platform,
14844
+ ...platform
14693
14845
  };
14694
14846
  }
14695
- doInitialSourceGroupRender() {
14696
- const { db } = this.root;
14697
- const hasExplicitName = typeof this._parsedProps.name === "string" && this._parsedProps.name.length > 0;
14698
- const source_group = db.source_group.insert({
14699
- name: this.name,
14700
- is_subcircuit: this.isSubcircuit,
14701
- was_automatically_named: !hasExplicitName
14702
- });
14703
- this.source_group_id = source_group.source_group_id;
14704
- if (this.isSubcircuit) {
14705
- this.subcircuit_id = `subcircuit_${source_group.source_group_id}`;
14706
- db.source_group.update(source_group.source_group_id, {
14707
- subcircuit_id: this.subcircuit_id
14708
- });
14847
+ /**
14848
+ * Get the main board for this Circuit.
14849
+ */
14850
+ _getBoard() {
14851
+ const directBoard = this.children.find((c) => c.componentName === "Board");
14852
+ if (directBoard) {
14853
+ return directBoard;
14709
14854
  }
14855
+ return void 0;
14710
14856
  }
14711
- doInitialSourceRender() {
14712
- const { db } = this.root;
14713
- for (const child of this.children) {
14714
- db.source_component.update(child.source_component_id, {
14715
- source_group_id: this.source_group_id
14716
- });
14857
+ _guessRootComponent() {
14858
+ if (this.firstChild) return;
14859
+ if (this.children.length === 0) {
14860
+ throw new Error(
14861
+ "Not able to guess root component: IsolatedCircuit has no children (use circuit.add(...))"
14862
+ );
14717
14863
  }
14718
- }
14719
- doInitialSourceParentAttachment() {
14864
+ const panels = this.children.filter(
14865
+ (child) => child.lowercaseComponentName === "panel"
14866
+ );
14867
+ if (panels.length > 1) {
14868
+ throw new Error("Only one <panel> is allowed per circuit");
14869
+ }
14870
+ if (panels.length === 1) {
14871
+ if (this.children.length !== 1) {
14872
+ throw new Error("<panel> must be the root element of the circuit");
14873
+ }
14874
+ this.firstChild = panels[0];
14875
+ return;
14876
+ }
14877
+ if (this.children.length === 1 && this.children[0].isGroup) {
14878
+ this.firstChild = this.children[0];
14879
+ return;
14880
+ }
14881
+ const group = new Group6({ subcircuit: true });
14882
+ group.parent = this;
14883
+ group.addAll(this.children);
14884
+ this.children = [group];
14885
+ this.firstChild = group;
14886
+ }
14887
+ render() {
14888
+ if (!this.firstChild) {
14889
+ this._guessRootComponent();
14890
+ }
14891
+ const { firstChild, db } = this;
14892
+ if (!firstChild) throw new Error("IsolatedCircuit has no root component");
14893
+ firstChild.parent = this;
14894
+ firstChild.runRenderCycle();
14895
+ this._hasRenderedAtleastOnce = true;
14896
+ }
14897
+ async renderUntilSettled() {
14898
+ const existing = this.db.source_project_metadata.list()?.[0];
14899
+ if (!existing) {
14900
+ this.db.source_project_metadata.insert({
14901
+ software_used_string: `@tscircuit/core@${this.getCoreVersion()}`,
14902
+ ...this.projectUrl ? { project_url: this.projectUrl } : {}
14903
+ });
14904
+ }
14905
+ this.render();
14906
+ while (this._hasIncompleteAsyncEffects()) {
14907
+ await new Promise((resolve) => setTimeout(resolve, 100));
14908
+ this.render();
14909
+ }
14910
+ this.emit("renderComplete");
14911
+ }
14912
+ _hasIncompleteAsyncEffects() {
14913
+ if (this._asyncEffectPhaseById.size > 0) return true;
14914
+ return this.children.some((child) => child._hasIncompleteAsyncEffects());
14915
+ }
14916
+ _hasIncompleteAsyncEffectsForPhase(phase) {
14917
+ return (this._asyncEffectIdsByPhase.get(phase)?.size ?? 0) > 0;
14918
+ }
14919
+ getCircuitJson() {
14920
+ if (!this._hasRenderedAtleastOnce) this.render();
14921
+ return this.db.toArray();
14922
+ }
14923
+ toJson() {
14924
+ return this.getCircuitJson();
14925
+ }
14926
+ async getSvg(options) {
14927
+ const circuitToSvg = await import("circuit-to-svg").catch((e) => {
14928
+ throw new Error(
14929
+ `To use circuit.getSvg, you must install the "circuit-to-svg" package.
14930
+
14931
+ "${e.message}"`
14932
+ );
14933
+ });
14934
+ if (options.view === "pcb") {
14935
+ return circuitToSvg.convertCircuitJsonToPcbSvg(this.getCircuitJson());
14936
+ }
14937
+ if (options.view === "schematic") {
14938
+ return circuitToSvg.convertCircuitJsonToSchematicSvg(
14939
+ this.getCircuitJson()
14940
+ );
14941
+ }
14942
+ throw new Error(`Invalid view: ${options.view}`);
14943
+ }
14944
+ getCoreVersion() {
14945
+ const [major, minor, patch] = package_default.version.split(".").map(Number);
14946
+ return `${major}.${minor}.${patch + 1}`;
14947
+ }
14948
+ async preview(previewNameOrOpts) {
14949
+ const previewOpts = typeof previewNameOrOpts === "object" ? previewNameOrOpts : { previewName: previewNameOrOpts };
14950
+ throw new Error("project.preview is not yet implemented");
14951
+ }
14952
+ computeSchematicGlobalTransform() {
14953
+ return identity4();
14954
+ }
14955
+ _computePcbGlobalTransformBeforeLayout() {
14956
+ return identity4();
14957
+ }
14958
+ selectAll(selector) {
14959
+ this._guessRootComponent();
14960
+ return this.firstChild?.selectAll(selector) ?? [];
14961
+ }
14962
+ selectOne(selector, opts) {
14963
+ this._guessRootComponent();
14964
+ return this.firstChild?.selectOne(selector, opts) ?? null;
14965
+ }
14966
+ _eventListeners = {};
14967
+ emit(event, ...args) {
14968
+ if (event === "asyncEffect:start") {
14969
+ this._registerAsyncEffectStart(args[0]);
14970
+ } else if (event === "asyncEffect:end") {
14971
+ this._registerAsyncEffectEnd(args[0]);
14972
+ }
14973
+ if (!this._eventListeners[event]) return;
14974
+ for (const listener of this._eventListeners[event]) {
14975
+ listener(...args);
14976
+ }
14977
+ }
14978
+ on(event, listener) {
14979
+ if (!this._eventListeners[event]) {
14980
+ this._eventListeners[event] = [];
14981
+ }
14982
+ this._eventListeners[event].push(listener);
14983
+ }
14984
+ removeListener(event, listener) {
14985
+ if (!this._eventListeners[event]) return;
14986
+ this._eventListeners[event] = this._eventListeners[event].filter(
14987
+ (l) => l !== listener
14988
+ );
14989
+ }
14990
+ enableDebug(debug11) {
14991
+ if (typeof debug11 === "string") {
14992
+ Debug13.enable(debug11);
14993
+ } else if (debug11 === null || debug11 === false) {
14994
+ Debug13.disable();
14995
+ }
14996
+ }
14997
+ getClientOrigin() {
14998
+ if (typeof window !== "undefined" && window.location) {
14999
+ return window.location.origin;
15000
+ }
15001
+ if (typeof self !== "undefined" && self.location) {
15002
+ return self.location.origin;
15003
+ }
15004
+ return "";
15005
+ }
15006
+ _registerAsyncEffectStart(payload) {
15007
+ if (!payload?.asyncEffectId || !payload.phase) return;
15008
+ const { asyncEffectId, phase } = payload;
15009
+ const existingPhase = this._asyncEffectPhaseById.get(asyncEffectId);
15010
+ if (existingPhase && existingPhase !== phase) {
15011
+ this._asyncEffectIdsByPhase.get(existingPhase)?.delete(asyncEffectId);
15012
+ }
15013
+ if (!this._asyncEffectIdsByPhase.has(phase)) {
15014
+ this._asyncEffectIdsByPhase.set(phase, /* @__PURE__ */ new Set());
15015
+ }
15016
+ this._asyncEffectIdsByPhase.get(phase).add(asyncEffectId);
15017
+ this._asyncEffectPhaseById.set(asyncEffectId, phase);
15018
+ }
15019
+ _registerAsyncEffectEnd(payload) {
15020
+ if (!payload?.asyncEffectId) return;
15021
+ const { asyncEffectId } = payload;
15022
+ const phase = this._asyncEffectPhaseById.get(asyncEffectId) ?? payload.phase;
15023
+ if (phase) {
15024
+ const phaseSet = this._asyncEffectIdsByPhase.get(phase);
15025
+ phaseSet?.delete(asyncEffectId);
15026
+ if (phaseSet && phaseSet.size === 0) {
15027
+ this._asyncEffectIdsByPhase.delete(phase);
15028
+ }
15029
+ }
15030
+ this._asyncEffectPhaseById.delete(asyncEffectId);
15031
+ }
15032
+ };
15033
+
15034
+ // lib/components/primitive-components/Group/Group_doInitialRenderIsolatedSubcircuits.ts
15035
+ function Group_doInitialRenderIsolatedSubcircuits(group) {
15036
+ if (!group._isIsolatedSubcircuit) return;
15037
+ if (!group.root) return;
15038
+ const parentRoot = group.root;
15039
+ const isolatedCircuit = new IsolatedCircuit({
15040
+ platform: {
15041
+ ...parentRoot.platform,
15042
+ pcbDisabled: parentRoot.pcbDisabled,
15043
+ schematicDisabled: parentRoot.schematicDisabled
15044
+ }
15045
+ });
15046
+ const childrenSnapshot = [...group.children];
15047
+ for (const child of childrenSnapshot) {
15048
+ isolatedCircuit.add(child);
15049
+ }
15050
+ group._queueAsyncEffect("render-isolated-subcircuit", async () => {
15051
+ await isolatedCircuit.renderUntilSettled();
15052
+ group.children = [];
15053
+ group._normalComponentNameMap = null;
15054
+ group._isolatedCircuitJson = isolatedCircuit.getCircuitJson();
15055
+ });
15056
+ }
15057
+
15058
+ // lib/components/primitive-components/Group/Group.ts
15059
+ var Group6 = class extends NormalComponent3 {
15060
+ pcb_group_id = null;
15061
+ schematic_group_id = null;
15062
+ subcircuit_id = null;
15063
+ _hasStartedAsyncAutorouting = false;
15064
+ _isInflatedFromCircuitJson = false;
15065
+ _isolatedCircuitJson = null;
15066
+ get _isIsolatedSubcircuit() {
15067
+ return Boolean(this._parsedProps._subcircuitCachingEnabled);
15068
+ }
15069
+ _normalComponentNameMap = null;
15070
+ /**
15071
+ * Returns a cached map of component names to NormalComponent instances within this subcircuit.
15072
+ * The map is built lazily on first access and cached for subsequent calls.
15073
+ */
15074
+ getNormalComponentNameMap() {
15075
+ if (this._normalComponentNameMap) {
15076
+ return this._normalComponentNameMap;
15077
+ }
15078
+ const nameMap = /* @__PURE__ */ new Map();
15079
+ const collectNamedComponents = (component) => {
15080
+ if (component._isNormalComponent && component.name) {
15081
+ const componentsWithSameName = nameMap.get(component.name);
15082
+ if (componentsWithSameName) {
15083
+ componentsWithSameName.push(component);
15084
+ } else {
15085
+ nameMap.set(component.name, [component]);
15086
+ }
15087
+ }
15088
+ for (const child of component.children) {
15089
+ if (!child.isSubcircuit) collectNamedComponents(child);
15090
+ }
15091
+ };
15092
+ for (const child of this.children) {
15093
+ if (!child.isSubcircuit) collectNamedComponents(child);
15094
+ }
15095
+ this._normalComponentNameMap = nameMap;
15096
+ return nameMap;
15097
+ }
15098
+ _asyncAutoroutingResult = null;
15099
+ get config() {
15100
+ return {
15101
+ zodProps: groupProps,
15102
+ componentName: "Group"
15103
+ };
15104
+ }
15105
+ runRenderPhaseForChildren(phase) {
15106
+ if (this._isIsolatedSubcircuit && !this._isInflatedFromCircuitJson) return;
15107
+ super.runRenderPhaseForChildren(phase);
15108
+ }
15109
+ doInitialRenderIsolatedSubcircuits() {
15110
+ Group_doInitialRenderIsolatedSubcircuits(this);
15111
+ }
15112
+ doInitialSourceGroupRender() {
15113
+ const { db } = this.root;
15114
+ const hasExplicitName = typeof this._parsedProps.name === "string" && this._parsedProps.name.length > 0;
15115
+ const source_group = db.source_group.insert({
15116
+ name: this.name,
15117
+ is_subcircuit: this.isSubcircuit,
15118
+ was_automatically_named: !hasExplicitName
15119
+ });
15120
+ this.source_group_id = source_group.source_group_id;
15121
+ if (this.isSubcircuit) {
15122
+ this.subcircuit_id = `subcircuit_${source_group.source_group_id}`;
15123
+ db.source_group.update(source_group.source_group_id, {
15124
+ subcircuit_id: this.subcircuit_id
15125
+ });
15126
+ }
15127
+ }
15128
+ doInitialSourceRender() {
15129
+ const { db } = this.root;
15130
+ for (const child of this.children) {
15131
+ db.source_component.update(child.source_component_id, {
15132
+ source_group_id: this.source_group_id
15133
+ });
15134
+ }
15135
+ }
15136
+ doInitialSourceParentAttachment() {
14720
15137
  const { db } = this.root;
14721
15138
  const parentGroup = this.parent?.getGroup?.();
14722
15139
  if (parentGroup?.source_group_id) {
@@ -14880,14 +15297,14 @@ var Group6 = class extends NormalComponent3 {
14880
15297
  return false;
14881
15298
  }
14882
15299
  _hasTracesToRoute() {
14883
- const debug11 = Debug13("tscircuit:core:_hasTracesToRoute");
15300
+ const debug11 = Debug14("tscircuit:core:_hasTracesToRoute");
14884
15301
  const traces = this.selectAll("trace");
14885
15302
  debug11(`[${this.getString()}] has ${traces.length} traces to route`);
14886
15303
  return traces.length > 0;
14887
15304
  }
14888
15305
  async _runEffectMakeHttpAutoroutingRequest() {
14889
15306
  const { db } = this.root;
14890
- const debug11 = Debug13("tscircuit:core:_runEffectMakeHttpAutoroutingRequest");
15307
+ const debug11 = Debug14("tscircuit:core:_runEffectMakeHttpAutoroutingRequest");
14891
15308
  const props = this._parsedProps;
14892
15309
  const autorouterConfig = this._getAutorouterConfig();
14893
15310
  const serverUrl = autorouterConfig.serverUrl;
@@ -15010,7 +15427,7 @@ var Group6 = class extends NormalComponent3 {
15010
15427
  async _runLocalAutorouting() {
15011
15428
  const { db } = this.root;
15012
15429
  const props = this._parsedProps;
15013
- const debug11 = Debug13("tscircuit:core:_runLocalAutorouting");
15430
+ const debug11 = Debug14("tscircuit:core:_runLocalAutorouting");
15014
15431
  debug11(`[${this.getString()}] starting local autorouting`);
15015
15432
  const autorouterConfig = this._getAutorouterConfig();
15016
15433
  const isLaserPrefabPreset = this._isLaserPrefabAutorouter(autorouterConfig);
@@ -15146,7 +15563,7 @@ var Group6 = class extends NormalComponent3 {
15146
15563
  }
15147
15564
  }
15148
15565
  doInitialPcbTraceRender() {
15149
- const debug11 = Debug13("tscircuit:core:doInitialPcbTraceRender");
15566
+ const debug11 = Debug14("tscircuit:core:doInitialPcbTraceRender");
15150
15567
  if (!this.isSubcircuit) return;
15151
15568
  if (this.root?.pcbDisabled) return;
15152
15569
  if (this.getInheritedProperty("routingDisabled")) return;
@@ -15168,7 +15585,7 @@ var Group6 = class extends NormalComponent3 {
15168
15585
  Group_doInitialSchematicTraceRender(this);
15169
15586
  }
15170
15587
  updatePcbTraceRender() {
15171
- const debug11 = Debug13("tscircuit:core:updatePcbTraceRender");
15588
+ const debug11 = Debug14("tscircuit:core:updatePcbTraceRender");
15172
15589
  debug11(`[${this.getString()}] updating...`);
15173
15590
  if (!this.isSubcircuit) return;
15174
15591
  if (this._isInflatedFromCircuitJson) return;
@@ -17078,6 +17495,13 @@ var Subcircuit = class extends Group6 {
17078
17495
  * - Add components to groups in the appropriate hierarchy
17079
17496
  */
17080
17497
  doInitialInflateSubcircuitCircuitJson() {
17498
+ const isolatedJson = this._isolatedCircuitJson;
17499
+ if (isolatedJson) {
17500
+ this._isInflatedFromCircuitJson = true;
17501
+ this._isolatedCircuitJson = null;
17502
+ inflateCircuitJson(this, isolatedJson, []);
17503
+ return;
17504
+ }
17081
17505
  const { circuitJson, children } = this._parsedProps;
17082
17506
  if (circuitJson) {
17083
17507
  this._isInflatedFromCircuitJson = true;
@@ -19449,7 +19873,7 @@ var BreakoutPoint = class extends PrimitiveComponent2 {
19449
19873
  import { netLabelProps } from "@tscircuit/props";
19450
19874
  import {
19451
19875
  applyToPoint as applyToPoint17,
19452
- identity as identity4,
19876
+ identity as identity5,
19453
19877
  translate as translate8
19454
19878
  } from "transformation-matrix";
19455
19879
  import { calculateElbow as calculateElbow2 } from "calculate-elbow";
@@ -19500,7 +19924,7 @@ var NetLabel = class extends PrimitiveComponent2 {
19500
19924
  if (connectedPorts.length > 0) {
19501
19925
  const portPos = connectedPorts[0]._getGlobalSchematicPositionBeforeLayout();
19502
19926
  const parentCenter = applyToPoint17(
19503
- this.parent?.computeSchematicGlobalTransform?.() ?? identity4(),
19927
+ this.parent?.computeSchematicGlobalTransform?.() ?? identity5(),
19504
19928
  { x: 0, y: 0 }
19505
19929
  );
19506
19930
  return translate8(portPos.x - parentCenter.x, portPos.y - parentCenter.y);
@@ -22306,384 +22730,9 @@ var VoltageProbe = class extends PrimitiveComponent2 {
22306
22730
  }
22307
22731
  };
22308
22732
 
22309
- // lib/IsolatedCircuit.ts
22310
- import { su as su5 } from "@tscircuit/circuit-json-util";
22311
- import Debug14 from "debug";
22312
- import { isValidElement as isValidElement2 } from "react";
22313
- import { identity as identity5 } from "transformation-matrix";
22314
-
22315
- // package.json
22316
- var package_default = {
22317
- name: "@tscircuit/core",
22318
- type: "module",
22319
- version: "0.0.1022",
22320
- types: "dist/index.d.ts",
22321
- main: "dist/index.js",
22322
- module: "dist/index.js",
22323
- exports: {
22324
- ".": {
22325
- import: "./dist/index.js",
22326
- types: "./dist/index.d.ts"
22327
- }
22328
- },
22329
- files: [
22330
- "dist"
22331
- ],
22332
- repository: {
22333
- type: "git",
22334
- url: "https://github.com/tscircuit/core"
22335
- },
22336
- scripts: {
22337
- build: "tsup-node index.ts --format esm --dts",
22338
- format: "biome format . --write",
22339
- "measure-bundle": "howfat -r table .",
22340
- "pkg-pr-new-release": "bunx pkg-pr-new publish --comment=off --peerDeps",
22341
- "smoke-test:dist": "bun run scripts/smoke-tests/test-dist-simple-circuit.tsx",
22342
- "build:benchmarking": "bun build --experimental-html ./benchmarking/website/index.html --outdir ./benchmarking-dist",
22343
- "build:benchmarking:watch": `chokidar "./{benchmarking,lib}/**/*.{ts,tsx}" -c 'bun build --experimental-html ./benchmarking/website/index.html --outdir ./benchmarking-dist'`,
22344
- "start:benchmarking": 'concurrently "bun run build:benchmarking:watch" "live-server ./benchmarking-dist"',
22345
- "generate-test-plan": "bun run scripts/generate-test-plan.ts"
22346
- },
22347
- devDependencies: {
22348
- "@biomejs/biome": "^1.8.3",
22349
- "@resvg/resvg-js": "^2.6.2",
22350
- "@tscircuit/alphabet": "0.0.18",
22351
- "@tscircuit/capacity-autorouter": "^0.0.264",
22352
- "@tscircuit/checks": "^0.0.88",
22353
- "@tscircuit/circuit-json-util": "^0.0.77",
22354
- "@tscircuit/common": "^0.0.20",
22355
- "@tscircuit/copper-pour-solver": "^0.0.20",
22356
- "@tscircuit/footprinter": "^0.0.288",
22357
- "@tscircuit/infgrid-ijump-astar": "^0.0.35",
22358
- "@tscircuit/log-soup": "^1.0.2",
22359
- "@tscircuit/matchpack": "^0.0.16",
22360
- "@tscircuit/math-utils": "^0.0.29",
22361
- "@tscircuit/miniflex": "^0.0.4",
22362
- "@tscircuit/ngspice-spice-engine": "^0.0.8",
22363
- "@tscircuit/props": "^0.0.471",
22364
- "@tscircuit/schematic-match-adapt": "^0.0.16",
22365
- "@tscircuit/schematic-trace-solver": "^v0.0.45",
22366
- "@tscircuit/solver-utils": "^0.0.3",
22367
- "@tscircuit/soup-util": "^0.0.41",
22368
- "@types/bun": "^1.2.16",
22369
- "@types/debug": "^4.1.12",
22370
- "@types/react": "^19.1.8",
22371
- "@types/react-dom": "^19.1.6",
22372
- "@types/react-reconciler": "^0.28.9",
22373
- "bpc-graph": "^0.0.57",
22374
- "bun-match-svg": "0.0.12",
22375
- "calculate-elbow": "^0.0.12",
22376
- "chokidar-cli": "^3.0.0",
22377
- "circuit-json": "^0.0.378",
22378
- "circuit-json-to-bpc": "^0.0.13",
22379
- "circuit-json-to-connectivity-map": "^0.0.23",
22380
- "circuit-json-to-gltf": "^0.0.62",
22381
- "circuit-json-to-simple-3d": "^0.0.9",
22382
- "circuit-json-to-spice": "^0.0.33",
22383
- "circuit-to-svg": "^0.0.327",
22384
- concurrently: "^9.1.2",
22385
- "connectivity-map": "^1.0.0",
22386
- debug: "^4.3.6",
22387
- "eecircuit-engine": "^1.5.6",
22388
- flatbush: "^4.5.0",
22389
- "graphics-debug": "^0.0.60",
22390
- howfat: "^0.3.8",
22391
- "live-server": "^1.2.2",
22392
- "looks-same": "^9.0.1",
22393
- minicssgrid: "^0.0.9",
22394
- "pkg-pr-new": "^0.0.37",
22395
- poppygl: "^0.0.16",
22396
- react: "^19.1.0",
22397
- "react-dom": "^19.1.0",
22398
- "schematic-symbols": "^0.0.208",
22399
- spicey: "^0.0.14",
22400
- "ts-expect": "^1.3.0",
22401
- tsup: "^8.2.4"
22402
- },
22403
- peerDependencies: {
22404
- "@tscircuit/capacity-autorouter": "*",
22405
- "@tscircuit/checks": "*",
22406
- "@tscircuit/circuit-json-util": "*",
22407
- "@tscircuit/footprinter": "*",
22408
- "@tscircuit/infgrid-ijump-astar": "*",
22409
- "@tscircuit/math-utils": "*",
22410
- "@tscircuit/props": "*",
22411
- "@tscircuit/schematic-match-adapt": "*",
22412
- "circuit-json-to-bpc": "*",
22413
- "bpc-graph": "*",
22414
- "@tscircuit/matchpack": "*",
22415
- "circuit-json": "*",
22416
- "circuit-json-to-connectivity-map": "*",
22417
- "schematic-symbols": "*",
22418
- typescript: "^5.0.0"
22419
- },
22420
- dependencies: {
22421
- "@flatten-js/core": "^1.6.2",
22422
- "@lume/kiwi": "^0.4.3",
22423
- "calculate-packing": "0.0.68",
22424
- "css-select": "5.1.0",
22425
- "format-si-unit": "^0.0.3",
22426
- nanoid: "^5.0.7",
22427
- "performance-now": "^2.1.0",
22428
- "react-reconciler": "^0.32.0",
22429
- "svg-path-commander": "^2.1.11",
22430
- "transformation-matrix": "^2.16.1",
22431
- zod: "^3.25.67"
22432
- }
22433
- };
22434
-
22435
- // lib/IsolatedCircuit.ts
22436
- var IsolatedCircuit = class {
22437
- firstChild = null;
22438
- children;
22439
- db;
22440
- root = null;
22441
- isRoot = false;
22442
- _schematicDisabledOverride;
22443
- get schematicDisabled() {
22444
- if (this._schematicDisabledOverride !== void 0) {
22445
- return this._schematicDisabledOverride;
22446
- }
22447
- const board = this._getBoard();
22448
- return board?._parsedProps?.schematicDisabled ?? false;
22449
- }
22450
- set schematicDisabled(value) {
22451
- this._schematicDisabledOverride = value;
22452
- }
22453
- pcbDisabled = false;
22454
- pcbRoutingDisabled = false;
22455
- _featureMspSchematicTraceRouting = true;
22456
- /**
22457
- * The IsolatedCircuit name is usually set by the platform, it's not required but
22458
- * if supplied can identify the circuit in certain effects, e.g. it is passed
22459
- * as the display_name parameter for autorouting effects.
22460
- */
22461
- name;
22462
- platform;
22463
- /**
22464
- * Optional URL pointing to where this project is hosted or documented.
22465
- * When provided it is stored in the source_project_metadata.project_url field
22466
- * of the generated Circuit JSON.
22467
- */
22468
- projectUrl;
22469
- _hasRenderedAtleastOnce = false;
22470
- _asyncEffectIdsByPhase = /* @__PURE__ */ new Map();
22471
- _asyncEffectPhaseById = /* @__PURE__ */ new Map();
22472
- constructor({
22473
- platform,
22474
- projectUrl
22475
- } = {}) {
22476
- this.children = [];
22477
- this.db = su5([]);
22478
- this.platform = platform;
22479
- this.projectUrl = projectUrl;
22480
- this.pcbDisabled = platform?.pcbDisabled ?? false;
22481
- }
22482
- add(componentOrElm) {
22483
- let component;
22484
- if (isValidElement2(componentOrElm)) {
22485
- component = createInstanceFromReactElement(componentOrElm);
22486
- } else {
22487
- component = componentOrElm;
22488
- }
22489
- this.children.push(component);
22490
- }
22491
- setPlatform(platform) {
22492
- this.platform = {
22493
- ...this.platform,
22494
- ...platform
22495
- };
22496
- }
22497
- /**
22498
- * Get the main board for this Circuit.
22499
- */
22500
- _getBoard() {
22501
- const directBoard = this.children.find((c) => c.componentName === "Board");
22502
- if (directBoard) {
22503
- return directBoard;
22504
- }
22505
- return void 0;
22506
- }
22507
- _guessRootComponent() {
22508
- if (this.firstChild) return;
22509
- if (this.children.length === 0) {
22510
- throw new Error(
22511
- "Not able to guess root component: IsolatedCircuit has no children (use circuit.add(...))"
22512
- );
22513
- }
22514
- const panels = this.children.filter(
22515
- (child) => child.lowercaseComponentName === "panel"
22516
- );
22517
- if (panels.length > 1) {
22518
- throw new Error("Only one <panel> is allowed per circuit");
22519
- }
22520
- if (panels.length === 1) {
22521
- if (this.children.length !== 1) {
22522
- throw new Error("<panel> must be the root element of the circuit");
22523
- }
22524
- this.firstChild = panels[0];
22525
- return;
22526
- }
22527
- if (this.children.length === 1 && this.children[0].isGroup) {
22528
- this.firstChild = this.children[0];
22529
- return;
22530
- }
22531
- const group = new Group6({ subcircuit: true });
22532
- group.parent = this;
22533
- group.addAll(this.children);
22534
- this.children = [group];
22535
- this.firstChild = group;
22536
- }
22537
- render() {
22538
- if (!this.firstChild) {
22539
- this._guessRootComponent();
22540
- }
22541
- const { firstChild, db } = this;
22542
- if (!firstChild) throw new Error("IsolatedCircuit has no root component");
22543
- firstChild.parent = this;
22544
- firstChild.runRenderCycle();
22545
- this._hasRenderedAtleastOnce = true;
22546
- }
22547
- async renderUntilSettled() {
22548
- const existing = this.db.source_project_metadata.list()?.[0];
22549
- if (!existing) {
22550
- this.db.source_project_metadata.insert({
22551
- software_used_string: `@tscircuit/core@${this.getCoreVersion()}`,
22552
- ...this.projectUrl ? { project_url: this.projectUrl } : {}
22553
- });
22554
- }
22555
- this.render();
22556
- while (this._hasIncompleteAsyncEffects()) {
22557
- await new Promise((resolve) => setTimeout(resolve, 100));
22558
- this.render();
22559
- }
22560
- this.emit("renderComplete");
22561
- }
22562
- _hasIncompleteAsyncEffects() {
22563
- if (this._asyncEffectPhaseById.size > 0) return true;
22564
- return this.children.some((child) => child._hasIncompleteAsyncEffects());
22565
- }
22566
- _hasIncompleteAsyncEffectsForPhase(phase) {
22567
- return (this._asyncEffectIdsByPhase.get(phase)?.size ?? 0) > 0;
22568
- }
22569
- getCircuitJson() {
22570
- if (!this._hasRenderedAtleastOnce) this.render();
22571
- return this.db.toArray();
22572
- }
22573
- toJson() {
22574
- return this.getCircuitJson();
22575
- }
22576
- async getSvg(options) {
22577
- const circuitToSvg = await import("circuit-to-svg").catch((e) => {
22578
- throw new Error(
22579
- `To use circuit.getSvg, you must install the "circuit-to-svg" package.
22580
-
22581
- "${e.message}"`
22582
- );
22583
- });
22584
- if (options.view === "pcb") {
22585
- return circuitToSvg.convertCircuitJsonToPcbSvg(this.getCircuitJson());
22586
- }
22587
- if (options.view === "schematic") {
22588
- return circuitToSvg.convertCircuitJsonToSchematicSvg(
22589
- this.getCircuitJson()
22590
- );
22591
- }
22592
- throw new Error(`Invalid view: ${options.view}`);
22593
- }
22594
- getCoreVersion() {
22595
- const [major, minor, patch] = package_default.version.split(".").map(Number);
22596
- return `${major}.${minor}.${patch + 1}`;
22597
- }
22598
- async preview(previewNameOrOpts) {
22599
- const previewOpts = typeof previewNameOrOpts === "object" ? previewNameOrOpts : { previewName: previewNameOrOpts };
22600
- throw new Error("project.preview is not yet implemented");
22601
- }
22602
- computeSchematicGlobalTransform() {
22603
- return identity5();
22604
- }
22605
- _computePcbGlobalTransformBeforeLayout() {
22606
- return identity5();
22607
- }
22608
- selectAll(selector) {
22609
- this._guessRootComponent();
22610
- return this.firstChild?.selectAll(selector) ?? [];
22611
- }
22612
- selectOne(selector, opts) {
22613
- this._guessRootComponent();
22614
- return this.firstChild?.selectOne(selector, opts) ?? null;
22615
- }
22616
- _eventListeners = {};
22617
- emit(event, ...args) {
22618
- if (event === "asyncEffect:start") {
22619
- this._registerAsyncEffectStart(args[0]);
22620
- } else if (event === "asyncEffect:end") {
22621
- this._registerAsyncEffectEnd(args[0]);
22622
- }
22623
- if (!this._eventListeners[event]) return;
22624
- for (const listener of this._eventListeners[event]) {
22625
- listener(...args);
22626
- }
22627
- }
22628
- on(event, listener) {
22629
- if (!this._eventListeners[event]) {
22630
- this._eventListeners[event] = [];
22631
- }
22632
- this._eventListeners[event].push(listener);
22633
- }
22634
- removeListener(event, listener) {
22635
- if (!this._eventListeners[event]) return;
22636
- this._eventListeners[event] = this._eventListeners[event].filter(
22637
- (l) => l !== listener
22638
- );
22639
- }
22640
- enableDebug(debug11) {
22641
- if (typeof debug11 === "string") {
22642
- Debug14.enable(debug11);
22643
- } else if (debug11 === null || debug11 === false) {
22644
- Debug14.disable();
22645
- }
22646
- }
22647
- getClientOrigin() {
22648
- if (typeof window !== "undefined" && window.location) {
22649
- return window.location.origin;
22650
- }
22651
- if (typeof self !== "undefined" && self.location) {
22652
- return self.location.origin;
22653
- }
22654
- return "";
22655
- }
22656
- _registerAsyncEffectStart(payload) {
22657
- if (!payload?.asyncEffectId || !payload.phase) return;
22658
- const { asyncEffectId, phase } = payload;
22659
- const existingPhase = this._asyncEffectPhaseById.get(asyncEffectId);
22660
- if (existingPhase && existingPhase !== phase) {
22661
- this._asyncEffectIdsByPhase.get(existingPhase)?.delete(asyncEffectId);
22662
- }
22663
- if (!this._asyncEffectIdsByPhase.has(phase)) {
22664
- this._asyncEffectIdsByPhase.set(phase, /* @__PURE__ */ new Set());
22665
- }
22666
- this._asyncEffectIdsByPhase.get(phase).add(asyncEffectId);
22667
- this._asyncEffectPhaseById.set(asyncEffectId, phase);
22668
- }
22669
- _registerAsyncEffectEnd(payload) {
22670
- if (!payload?.asyncEffectId) return;
22671
- const { asyncEffectId } = payload;
22672
- const phase = this._asyncEffectPhaseById.get(asyncEffectId) ?? payload.phase;
22673
- if (phase) {
22674
- const phaseSet = this._asyncEffectIdsByPhase.get(phase);
22675
- phaseSet?.delete(asyncEffectId);
22676
- if (phaseSet && phaseSet.size === 0) {
22677
- this._asyncEffectIdsByPhase.delete(phase);
22678
- }
22679
- }
22680
- this._asyncEffectPhaseById.delete(asyncEffectId);
22681
- }
22682
- };
22683
-
22684
22733
  // lib/RootCircuit.ts
22685
22734
  var RootCircuit = class extends IsolatedCircuit {
22686
- isRoot = true;
22735
+ isRootCircuit = true;
22687
22736
  constructor({
22688
22737
  platform,
22689
22738
  projectUrl
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1023",
4
+ "version": "0.0.1025",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",