@skillpet/circuit 0.5.2 → 0.6.1

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.
@@ -30173,15 +30173,37 @@ var BUILTIN_THEMES = {
30173
30173
  lw: 1.5
30174
30174
  }
30175
30175
  };
30176
+ var CSS_VARS = {
30177
+ bg: "--circuit-bg",
30178
+ stroke: "--circuit-stroke",
30179
+ fill: "--circuit-fill",
30180
+ text: "--circuit-text",
30181
+ font: "--circuit-font",
30182
+ lw: "--circuit-lw"
30183
+ };
30184
+ function readCssTheme() {
30185
+ if (typeof getComputedStyle === "undefined") return { ...BUILTIN_THEMES.light };
30186
+ const s = getComputedStyle(document.documentElement);
30187
+ const v = (name) => s.getPropertyValue(name).trim();
30188
+ return {
30189
+ bg: v(CSS_VARS.bg) || "transparent",
30190
+ stroke: v(CSS_VARS.stroke) || BUILTIN_THEMES.light.stroke,
30191
+ fill: v(CSS_VARS.fill) || "none",
30192
+ text: v(CSS_VARS.text) || BUILTIN_THEMES.light.text,
30193
+ font: v(CSS_VARS.font) || BUILTIN_THEMES.light.font,
30194
+ lw: parseFloat(v(CSS_VARS.lw)) || BUILTIN_THEMES.light.lw
30195
+ };
30196
+ }
30176
30197
  function resolveTheme(theme2) {
30177
30198
  if (theme2 === void 0) {
30178
30199
  return { ...BUILTIN_THEMES.light };
30179
30200
  }
30180
30201
  if (typeof theme2 === "string") {
30202
+ if (theme2 === "auto") return readCssTheme();
30181
30203
  const found = BUILTIN_THEMES[theme2];
30182
30204
  if (!found) {
30183
30205
  throw new Error(
30184
- `Unknown theme "${theme2}". Available: ${Object.keys(BUILTIN_THEMES).join(", ")}`
30206
+ `Unknown theme "${theme2}". Available: ${Object.keys(BUILTIN_THEMES).join(", ")}, auto`
30185
30207
  );
30186
30208
  }
30187
30209
  return { ...found };
@@ -30402,6 +30424,9 @@ var SchemdrawController = class {
30402
30424
  __publicField(this, "_theme");
30403
30425
  __publicField(this, "_destroyed", false);
30404
30426
  __publicField(this, "_tooltipEl", null);
30427
+ __publicField(this, "_autoObserver", null);
30428
+ __publicField(this, "_mediaQuery", null);
30429
+ __publicField(this, "_mediaHandler", null);
30405
30430
  __publicField(this, "_boundClick");
30406
30431
  __publicField(this, "_boundMouseover");
30407
30432
  __publicField(this, "_boundMouseout");
@@ -30419,6 +30444,42 @@ var SchemdrawController = class {
30419
30444
  this._render();
30420
30445
  this._bindEvents();
30421
30446
  this._initTooltip();
30447
+ this._initAutoTheme();
30448
+ }
30449
+ _isAutoTheme() {
30450
+ return (this._opts.theme ?? this._json.theme) === "auto";
30451
+ }
30452
+ _initAutoTheme() {
30453
+ if (!this._isAutoTheme()) return;
30454
+ const rerender = () => {
30455
+ if (this._destroyed) return;
30456
+ this._theme = resolveTheme("auto");
30457
+ this._unbindEvents();
30458
+ this._render();
30459
+ this._bindEvents();
30460
+ this._selectedId = null;
30461
+ };
30462
+ this._autoObserver = new MutationObserver(rerender);
30463
+ this._autoObserver.observe(document.documentElement, {
30464
+ attributes: true,
30465
+ attributeFilter: ["class", "data-theme", "data-color-mode", "style"]
30466
+ });
30467
+ if (typeof matchMedia !== "undefined") {
30468
+ this._mediaQuery = matchMedia("(prefers-color-scheme: dark)");
30469
+ this._mediaHandler = rerender;
30470
+ this._mediaQuery.addEventListener("change", this._mediaHandler);
30471
+ }
30472
+ }
30473
+ _teardownAutoTheme() {
30474
+ if (this._autoObserver) {
30475
+ this._autoObserver.disconnect();
30476
+ this._autoObserver = null;
30477
+ }
30478
+ if (this._mediaQuery && this._mediaHandler) {
30479
+ this._mediaQuery.removeEventListener("change", this._mediaHandler);
30480
+ this._mediaQuery = null;
30481
+ this._mediaHandler = null;
30482
+ }
30422
30483
  }
30423
30484
  _render() {
30424
30485
  const svgString = renderFromJson(this._json, this._opts);
@@ -30466,13 +30527,28 @@ var SchemdrawController = class {
30466
30527
  }
30467
30528
  _initTooltip() {
30468
30529
  const tip = document.createElement("div");
30469
- tip.style.cssText = "position:fixed;z-index:99999;pointer-events:none;opacity:0;transition:opacity .12s ease;background:rgba(30,30,30,.92);color:#fff;font-size:12px;line-height:1.4;padding:5px 10px;border-radius:4px;max-width:260px;white-space:pre-wrap;box-shadow:0 2px 8px rgba(0,0,0,.25)";
30530
+ tip.className = "schemdraw-tooltip";
30531
+ tip.style.cssText = "position:fixed;z-index:99999;pointer-events:none;opacity:0;transition:opacity .15s ease;font-size:12px;line-height:1.4;padding:6px 12px;border-radius:6px;max-width:260px;white-space:pre-wrap;";
30532
+ this._applyTooltipTheme(tip);
30470
30533
  document.body.appendChild(tip);
30471
30534
  this._tooltipEl = tip;
30472
30535
  }
30536
+ _applyTooltipTheme(tip) {
30537
+ const isDark = document.documentElement.classList.contains("dark") || document.documentElement.getAttribute("data-theme") === "dark" || typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches && !document.documentElement.classList.contains("light");
30538
+ if (isDark) {
30539
+ tip.style.background = "rgba(250,250,250,.95)";
30540
+ tip.style.color = "#1a1a1a";
30541
+ tip.style.boxShadow = "0 2px 12px rgba(0,0,0,.4)";
30542
+ } else {
30543
+ tip.style.background = "rgba(15,15,15,.92)";
30544
+ tip.style.color = "#fff";
30545
+ tip.style.boxShadow = "0 2px 8px rgba(0,0,0,.2)";
30546
+ }
30547
+ }
30473
30548
  _showTooltip(text2, clientX, clientY) {
30474
30549
  const tip = this._tooltipEl;
30475
30550
  if (!tip) return;
30551
+ this._applyTooltipTheme(tip);
30476
30552
  tip.textContent = text2;
30477
30553
  tip.style.opacity = "1";
30478
30554
  const gap2 = 10;
@@ -30652,9 +30728,11 @@ var SchemdrawController = class {
30652
30728
  this._selectedId = null;
30653
30729
  }
30654
30730
  setTheme(theme2) {
30731
+ this._teardownAutoTheme();
30655
30732
  this._opts = { ...this._opts, theme: theme2 };
30656
30733
  this._theme = resolveTheme(theme2);
30657
30734
  this.update(this._json);
30735
+ this._initAutoTheme();
30658
30736
  }
30659
30737
  update(json) {
30660
30738
  const circuit = typeof json === "string" ? JSON.parse(json) : json;
@@ -30668,6 +30746,7 @@ var SchemdrawController = class {
30668
30746
  if (this._destroyed) return;
30669
30747
  this._destroyed = true;
30670
30748
  this._unbindEvents();
30749
+ this._teardownAutoTheme();
30671
30750
  if (this._tooltipEl) {
30672
30751
  this._tooltipEl.remove();
30673
30752
  this._tooltipEl = null;
@@ -30744,6 +30823,7 @@ export {
30744
30823
  BusLine,
30745
30824
  Button,
30746
30825
  CPE,
30826
+ CSS_VARS,
30747
30827
  Capacitor,
30748
30828
  Capacitor2,
30749
30829
  CapacitorTrim,
package/dist/index.cjs CHANGED
@@ -14380,6 +14380,7 @@ __export(index_exports, {
14380
14380
  BusLine: () => BusLine,
14381
14381
  Button: () => Button,
14382
14382
  CPE: () => CPE,
14383
+ CSS_VARS: () => CSS_VARS,
14383
14384
  Capacitor: () => Capacitor,
14384
14385
  Capacitor2: () => Capacitor2,
14385
14386
  CapacitorTrim: () => CapacitorTrim,
@@ -30559,15 +30560,37 @@ var BUILTIN_THEMES = {
30559
30560
  lw: 1.5
30560
30561
  }
30561
30562
  };
30563
+ var CSS_VARS = {
30564
+ bg: "--circuit-bg",
30565
+ stroke: "--circuit-stroke",
30566
+ fill: "--circuit-fill",
30567
+ text: "--circuit-text",
30568
+ font: "--circuit-font",
30569
+ lw: "--circuit-lw"
30570
+ };
30571
+ function readCssTheme() {
30572
+ if (typeof getComputedStyle === "undefined") return { ...BUILTIN_THEMES.light };
30573
+ const s = getComputedStyle(document.documentElement);
30574
+ const v = (name) => s.getPropertyValue(name).trim();
30575
+ return {
30576
+ bg: v(CSS_VARS.bg) || "transparent",
30577
+ stroke: v(CSS_VARS.stroke) || BUILTIN_THEMES.light.stroke,
30578
+ fill: v(CSS_VARS.fill) || "none",
30579
+ text: v(CSS_VARS.text) || BUILTIN_THEMES.light.text,
30580
+ font: v(CSS_VARS.font) || BUILTIN_THEMES.light.font,
30581
+ lw: parseFloat(v(CSS_VARS.lw)) || BUILTIN_THEMES.light.lw
30582
+ };
30583
+ }
30562
30584
  function resolveTheme(theme2) {
30563
30585
  if (theme2 === void 0) {
30564
30586
  return { ...BUILTIN_THEMES.light };
30565
30587
  }
30566
30588
  if (typeof theme2 === "string") {
30589
+ if (theme2 === "auto") return readCssTheme();
30567
30590
  const found = BUILTIN_THEMES[theme2];
30568
30591
  if (!found) {
30569
30592
  throw new Error(
30570
- `Unknown theme "${theme2}". Available: ${Object.keys(BUILTIN_THEMES).join(", ")}`
30593
+ `Unknown theme "${theme2}". Available: ${Object.keys(BUILTIN_THEMES).join(", ")}, auto`
30571
30594
  );
30572
30595
  }
30573
30596
  return { ...found };
@@ -30788,6 +30811,9 @@ var SchemdrawController = class {
30788
30811
  __publicField(this, "_theme");
30789
30812
  __publicField(this, "_destroyed", false);
30790
30813
  __publicField(this, "_tooltipEl", null);
30814
+ __publicField(this, "_autoObserver", null);
30815
+ __publicField(this, "_mediaQuery", null);
30816
+ __publicField(this, "_mediaHandler", null);
30791
30817
  __publicField(this, "_boundClick");
30792
30818
  __publicField(this, "_boundMouseover");
30793
30819
  __publicField(this, "_boundMouseout");
@@ -30805,6 +30831,42 @@ var SchemdrawController = class {
30805
30831
  this._render();
30806
30832
  this._bindEvents();
30807
30833
  this._initTooltip();
30834
+ this._initAutoTheme();
30835
+ }
30836
+ _isAutoTheme() {
30837
+ return (this._opts.theme ?? this._json.theme) === "auto";
30838
+ }
30839
+ _initAutoTheme() {
30840
+ if (!this._isAutoTheme()) return;
30841
+ const rerender = () => {
30842
+ if (this._destroyed) return;
30843
+ this._theme = resolveTheme("auto");
30844
+ this._unbindEvents();
30845
+ this._render();
30846
+ this._bindEvents();
30847
+ this._selectedId = null;
30848
+ };
30849
+ this._autoObserver = new MutationObserver(rerender);
30850
+ this._autoObserver.observe(document.documentElement, {
30851
+ attributes: true,
30852
+ attributeFilter: ["class", "data-theme", "data-color-mode", "style"]
30853
+ });
30854
+ if (typeof matchMedia !== "undefined") {
30855
+ this._mediaQuery = matchMedia("(prefers-color-scheme: dark)");
30856
+ this._mediaHandler = rerender;
30857
+ this._mediaQuery.addEventListener("change", this._mediaHandler);
30858
+ }
30859
+ }
30860
+ _teardownAutoTheme() {
30861
+ if (this._autoObserver) {
30862
+ this._autoObserver.disconnect();
30863
+ this._autoObserver = null;
30864
+ }
30865
+ if (this._mediaQuery && this._mediaHandler) {
30866
+ this._mediaQuery.removeEventListener("change", this._mediaHandler);
30867
+ this._mediaQuery = null;
30868
+ this._mediaHandler = null;
30869
+ }
30808
30870
  }
30809
30871
  _render() {
30810
30872
  const svgString = renderFromJson(this._json, this._opts);
@@ -30852,13 +30914,28 @@ var SchemdrawController = class {
30852
30914
  }
30853
30915
  _initTooltip() {
30854
30916
  const tip = document.createElement("div");
30855
- tip.style.cssText = "position:fixed;z-index:99999;pointer-events:none;opacity:0;transition:opacity .12s ease;background:rgba(30,30,30,.92);color:#fff;font-size:12px;line-height:1.4;padding:5px 10px;border-radius:4px;max-width:260px;white-space:pre-wrap;box-shadow:0 2px 8px rgba(0,0,0,.25)";
30917
+ tip.className = "schemdraw-tooltip";
30918
+ tip.style.cssText = "position:fixed;z-index:99999;pointer-events:none;opacity:0;transition:opacity .15s ease;font-size:12px;line-height:1.4;padding:6px 12px;border-radius:6px;max-width:260px;white-space:pre-wrap;";
30919
+ this._applyTooltipTheme(tip);
30856
30920
  document.body.appendChild(tip);
30857
30921
  this._tooltipEl = tip;
30858
30922
  }
30923
+ _applyTooltipTheme(tip) {
30924
+ const isDark = document.documentElement.classList.contains("dark") || document.documentElement.getAttribute("data-theme") === "dark" || typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches && !document.documentElement.classList.contains("light");
30925
+ if (isDark) {
30926
+ tip.style.background = "rgba(250,250,250,.95)";
30927
+ tip.style.color = "#1a1a1a";
30928
+ tip.style.boxShadow = "0 2px 12px rgba(0,0,0,.4)";
30929
+ } else {
30930
+ tip.style.background = "rgba(15,15,15,.92)";
30931
+ tip.style.color = "#fff";
30932
+ tip.style.boxShadow = "0 2px 8px rgba(0,0,0,.2)";
30933
+ }
30934
+ }
30859
30935
  _showTooltip(text2, clientX, clientY) {
30860
30936
  const tip = this._tooltipEl;
30861
30937
  if (!tip) return;
30938
+ this._applyTooltipTheme(tip);
30862
30939
  tip.textContent = text2;
30863
30940
  tip.style.opacity = "1";
30864
30941
  const gap2 = 10;
@@ -31038,9 +31115,11 @@ var SchemdrawController = class {
31038
31115
  this._selectedId = null;
31039
31116
  }
31040
31117
  setTheme(theme2) {
31118
+ this._teardownAutoTheme();
31041
31119
  this._opts = { ...this._opts, theme: theme2 };
31042
31120
  this._theme = resolveTheme(theme2);
31043
31121
  this.update(this._json);
31122
+ this._initAutoTheme();
31044
31123
  }
31045
31124
  update(json) {
31046
31125
  const circuit = typeof json === "string" ? JSON.parse(json) : json;
@@ -31054,6 +31133,7 @@ var SchemdrawController = class {
31054
31133
  if (this._destroyed) return;
31055
31134
  this._destroyed = true;
31056
31135
  this._unbindEvents();
31136
+ this._teardownAutoTheme();
31057
31137
  if (this._tooltipEl) {
31058
31138
  this._tooltipEl.remove();
31059
31139
  this._tooltipEl = null;
@@ -31131,6 +31211,7 @@ function mountFromJson(container, json, opts) {
31131
31211
  BusLine,
31132
31212
  Button,
31133
31213
  CPE,
31214
+ CSS_VARS,
31134
31215
  Capacitor,
31135
31216
  Capacitor2,
31136
31217
  CapacitorTrim,
package/dist/index.d.ts CHANGED
@@ -68,7 +68,7 @@ export { OutletA, OutletB, OutletC, OutletD, OutletE, OutletF, OutletG, OutletH,
68
68
  export { VacuumTube, DualVacuumTube, NixieTube, TubeDiode, Triode, Tetrode, Pentode, } from "./elements/tubes.js";
69
69
  export { ElementImage } from "./elements/image.js";
70
70
  export { renderFromJson, type CircuitJson, type DrawingConfig, type ElementObject, type ElementSpec, type LabelSpec, type RenderOptions, } from "./json/render.js";
71
- export { type Theme, BUILTIN_THEMES, resolveTheme } from "./json/theme.js";
71
+ export { type Theme, BUILTIN_THEMES, resolveTheme, CSS_VARS } from "./json/theme.js";
72
72
  export { ELEMENT_REGISTRY, getRegisteredTypes, getAvailableTypes, getAnchors, type ElementFactory } from "./json/registry.js";
73
73
  export { resolvePosition, resolvePositionX, resolvePositionY } from "./json/anchor-ref.js";
74
74
  export { validateCircuitJson, type ValidationResult, type ValidationError } from "./json/validate.js";
@@ -17,14 +17,21 @@ export declare class SchemdrawController {
17
17
  private _theme;
18
18
  private _destroyed;
19
19
  private _tooltipEl;
20
+ private _autoObserver;
21
+ private _mediaQuery;
22
+ private _mediaHandler;
20
23
  private _boundClick;
21
24
  private _boundMouseover;
22
25
  private _boundMouseout;
23
26
  private _boundContextmenu;
24
27
  private _boundMousemove;
25
28
  constructor(container: HTMLElement, json: CircuitJson, opts: RenderOptions);
29
+ private _isAutoTheme;
30
+ private _initAutoTheme;
31
+ private _teardownAutoTheme;
26
32
  private _render;
27
33
  private _initTooltip;
34
+ private _applyTooltipTheme;
28
35
  private _showTooltip;
29
36
  private _hideTooltip;
30
37
  private _bindEvents;
@@ -13,5 +13,14 @@ export interface Theme {
13
13
  lw: number;
14
14
  }
15
15
  export declare const BUILTIN_THEMES: Record<string, Theme>;
16
+ /** CSS variable names used by `theme: "auto"`. Host page defines these to control circuit colors. */
17
+ export declare const CSS_VARS: {
18
+ readonly bg: "--circuit-bg";
19
+ readonly stroke: "--circuit-stroke";
20
+ readonly fill: "--circuit-fill";
21
+ readonly text: "--circuit-text";
22
+ readonly font: "--circuit-font";
23
+ readonly lw: "--circuit-lw";
24
+ };
16
25
  export declare function resolveTheme(theme?: string | Partial<Theme>): Theme;
17
26
  export declare function applyThemeToDrawingConfig(theme: Theme, drawingConfig?: Record<string, unknown>): Record<string, unknown>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillpet/circuit",
3
- "version": "0.5.2",
3
+ "version": "0.6.1",
4
4
  "description": "Circuit diagram library — render electrical schematics from JSON, with interactive SVG, themes, and Vue/React components",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",