@leverege/tpi-viz 0.2.0 → 0.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/tpi-viz",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "3D scene viewer for TPI manufacturing data — renders blade geometry, PTZ cameras, defects, ply layers, and flows. Exports mountViewer()/destroy() for embedding (e.g. an Imaginarium React route); also runs standalone.",
5
5
  "type": "module",
6
6
  "exports": {
package/src/main.js CHANGED
@@ -2580,6 +2580,7 @@ function fmtN(v, d) {
2580
2580
  export async function mountViewer( container, opts = {} ) {
2581
2581
  if ( _alive ) { destroy(); } // idempotent re-mount
2582
2582
  _container = container || document.body;
2583
+ _container.classList.add( 'tpi-viz' ); // scopes all viewer CSS to this subtree
2583
2584
  if ( !_container.querySelector( '#app' ) ) { _container.innerHTML = VIEWER_SKELETON; }
2584
2585
  _opts = opts || {};
2585
2586
  _alive = true;
@@ -2612,5 +2613,5 @@ export function destroy() {
2612
2613
  selectedCameraIdx = -1;
2613
2614
  povCameraIdx = -1;
2614
2615
  activeFlowName = null;
2615
- if ( _container ) { _container.innerHTML = ''; _container = null; }
2616
+ if ( _container ) { _container.classList.remove( 'tpi-viz' ); _container.innerHTML = ''; _container = null; }
2616
2617
  }
@@ -747,7 +747,7 @@
747
747
  font-weight: bold;
748
748
  }
749
749
 
750
- input[type="range"] {
750
+ .tpi-viz input[type="range"] {
751
751
  width: 100%;
752
752
  height: 4px;
753
753
  appearance: none;
@@ -757,7 +757,7 @@ input[type="range"] {
757
757
  cursor: pointer;
758
758
  }
759
759
 
760
- input[type="range"]::-webkit-slider-thumb {
760
+ .tpi-viz input[type="range"]::-webkit-slider-thumb {
761
761
  appearance: none;
762
762
  width: 14px;
763
763
  height: 14px;
@@ -766,7 +766,7 @@ input[type="range"]::-webkit-slider-thumb {
766
766
  cursor: pointer;
767
767
  }
768
768
 
769
- input[type="range"]::-moz-range-thumb {
769
+ .tpi-viz input[type="range"]::-moz-range-thumb {
770
770
  width: 14px;
771
771
  height: 14px;
772
772
  background: var(--accent-blue);
@@ -7,27 +7,7 @@
7
7
  */
8
8
 
9
9
  :root {
10
- /* Surfaceslayered darks, cool-tinted */
11
- --bg-canvas: #0b0d14;
12
- --bg-sidebar: #11141d;
13
- --bg-panel: #161a26;
14
- --bg-panel-strong: #1c2030;
15
- --bg-hover: #1d2230;
16
- --bg-active: #232a3d;
17
- --bg-overlay: rgba(10, 12, 20, 0.88);
18
-
19
- /* Borders — barely-there to subtly-visible */
20
- --border-hairline: #1a1d28;
21
- --border-subtle: #232733;
22
- --border-strong: #2e3344;
23
-
24
- /* Text scale */
25
- --text-1: #e7e9ef; /* body / primary */
26
- --text-2: #aab1c0; /* labels */
27
- --text-3: #7b8294; /* secondary, counts */
28
- --text-4: #6b7488; /* hints, disabled — bumped from #535a6b for legibility on dark bg */
29
-
30
- /* Accents (paired w/ semantic uses across the app) */
10
+ /* Accents (semantic; theme-independent read on both light + dark) */
31
11
  --accent-blue: #7a9bff; /* elements / general info */
32
12
  --accent-blue-soft: #5063a8;
33
13
  --accent-pink: #ff95c2; /* flows */
@@ -46,21 +26,71 @@
46
26
  --r-sm: 4px;
47
27
  --r-md: 6px;
48
28
  --r-lg: 10px;
29
+ }
30
+
31
+ /* Surfaces / borders / text / shadows follow the host's light–dark theme.
32
+ Imaginarium toggles `.dark` on <html> (shadcn `darkMode:["class"]`), so the
33
+ embedded viewer tracks the app by keying off the SAME class. Light is the
34
+ default; standalone (index.html) forces `.dark` to keep its original look.
35
+ The 3D WebGL clear-color stays dark in both — a dark viewport reads best for
36
+ the varied-hue ply contours — so only the chrome re-themes. */
37
+ .tpi-viz {
38
+ /* Light surfaces — cool grays mirroring the dark scale */
39
+ --bg-canvas: #eceef3;
40
+ --bg-sidebar: #f5f6f9;
41
+ --bg-panel: #ffffff;
42
+ --bg-panel-strong: #eef0f4;
43
+ --bg-hover: #e9edf4;
44
+ --bg-active: #dde6f7;
45
+ --bg-overlay: rgba(244, 246, 250, 0.92);
46
+
47
+ --border-hairline: #e8eaef;
48
+ --border-subtle: #dde0e7;
49
+ --border-strong: #c7cdd8;
50
+
51
+ --text-1: #181b24; /* body / primary */
52
+ --text-2: #424a59; /* labels */
53
+ --text-3: #667083; /* secondary, counts */
54
+ --text-4: #8891a1; /* hints, disabled */
55
+
56
+ --shadow-soft: 0 2px 10px rgba(20, 28, 50, 0.10);
57
+ --shadow-med: 0 4px 18px rgba(20, 28, 50, 0.16);
58
+ }
59
+
60
+ .dark .tpi-viz {
61
+ /* Dark surfaces — the original palette */
62
+ --bg-canvas: #0b0d14;
63
+ --bg-sidebar: #11141d;
64
+ --bg-panel: #161a26;
65
+ --bg-panel-strong: #1c2030;
66
+ --bg-hover: #1d2230;
67
+ --bg-active: #232a3d;
68
+ --bg-overlay: rgba(10, 12, 20, 0.88);
69
+
70
+ --border-hairline: #1a1d28;
71
+ --border-subtle: #232733;
72
+ --border-strong: #2e3344;
73
+
74
+ --text-1: #e7e9ef;
75
+ --text-2: #aab1c0;
76
+ --text-3: #7b8294;
77
+ --text-4: #6b7488;
49
78
 
50
- /* Shadows */
51
79
  --shadow-soft: 0 2px 10px rgba(0, 0, 0, 0.35);
52
80
  --shadow-med: 0 4px 18px rgba(0, 0, 0, 0.45);
53
81
  }
54
82
 
55
- /* Reset and base */
56
- * { margin: 0; padding: 0; box-sizing: border-box; }
83
+ /* Reset and base. Everything is scoped under .tpi-viz (the viewer root that
84
+ mountViewer adds to its container) so these rules NEVER leak into a host app
85
+ when the viewer is embedded — only the viewer's own subtree is affected. */
86
+ .tpi-viz, .tpi-viz * { margin: 0; padding: 0; box-sizing: border-box; }
57
87
 
58
- body {
88
+ .tpi-viz {
59
89
  font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
60
90
  font-feature-settings: 'tnum' 1, 'cv11' 1; /* tabular numerals */
61
91
  background: var(--bg-canvas);
62
92
  color: var(--text-1);
63
- height: 100vh;
93
+ height: 100%; /* fill the mount container (standalone: #viewer-root @ 100vh; embedded: the host's sized div) */
64
94
  overflow: hidden;
65
95
  -webkit-font-smoothing: antialiased;
66
96
  text-rendering: optimizeLegibility;
@@ -82,35 +112,35 @@ body {
82
112
  }
83
113
 
84
114
  /* Custom scrollbars — thin, blend with the dark surface */
85
- * {
115
+ .tpi-viz, .tpi-viz * {
86
116
  scrollbar-width: thin;
87
117
  scrollbar-color: var(--border-strong) transparent;
88
118
  }
89
- *::-webkit-scrollbar {
119
+ .tpi-viz ::-webkit-scrollbar {
90
120
  width: 8px;
91
121
  height: 8px;
92
122
  }
93
- *::-webkit-scrollbar-track { background: transparent; }
94
- *::-webkit-scrollbar-thumb {
123
+ .tpi-viz ::-webkit-scrollbar-track { background: transparent; }
124
+ .tpi-viz ::-webkit-scrollbar-thumb {
95
125
  background: var(--border-subtle);
96
126
  border-radius: 999px;
97
127
  border: 2px solid transparent;
98
128
  background-clip: padding-box;
99
129
  }
100
- *::-webkit-scrollbar-thumb:hover {
130
+ .tpi-viz ::-webkit-scrollbar-thumb:hover {
101
131
  background: var(--border-strong);
102
132
  background-clip: padding-box;
103
133
  border: 2px solid transparent;
104
134
  }
105
135
 
106
136
  /* Selection styling */
107
- ::selection {
137
+ .tpi-viz ::selection {
108
138
  background: rgba(122, 155, 255, 0.32);
109
139
  color: var(--text-1);
110
140
  }
111
141
 
112
142
  /* Focus ring for keyboard nav (subtle but visible) */
113
- :focus-visible {
143
+ .tpi-viz :focus-visible {
114
144
  outline: 2px solid var(--accent-blue);
115
145
  outline-offset: 2px;
116
146
  border-radius: var(--r-sm);
@@ -119,7 +149,7 @@ body {
119
149
  /* Layout */
120
150
  .container {
121
151
  display: flex;
122
- height: 100vh;
152
+ height: 100%;
123
153
  }
124
154
 
125
155
  .sidebar {