pcb-scene3d-viewer 1.0.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.
Files changed (65) hide show
  1. package/AGENTS.md +67 -0
  2. package/COMMERCIAL-LICENSE.md +15 -0
  3. package/CONTRIBUTING.md +14 -0
  4. package/LICENSE +19 -0
  5. package/LICENSES/AGPL-3.0-or-later.txt +235 -0
  6. package/LICENSES/CC-BY-SA-4.0.txt +170 -0
  7. package/LICENSES/LGPL-2.1-or-later.txt +176 -0
  8. package/LICENSES/LicenseRef-PolyForm-Noncommercial-1.0.0.txt +131 -0
  9. package/NOTICE.md +36 -0
  10. package/README.md +128 -0
  11. package/REUSE.toml +16 -0
  12. package/docs/api.md +148 -0
  13. package/docs/circuitjson.md +190 -0
  14. package/docs/model-format.md +117 -0
  15. package/docs/testing.md +23 -0
  16. package/package.json +65 -0
  17. package/spec/library-scope.md +36 -0
  18. package/src/PcbModelArchiveExporter.mjs +320 -0
  19. package/src/PcbScene3dArcUtils.mjs +27 -0
  20. package/src/PcbScene3dBoardAssemblyPlacement.mjs +36 -0
  21. package/src/PcbScene3dBoardAssemblyPresentation.mjs +859 -0
  22. package/src/PcbScene3dBoardEdgeCutoutBuilder.mjs +537 -0
  23. package/src/PcbScene3dBoardMaterialPalette.mjs +40 -0
  24. package/src/PcbScene3dBoardShapeFactory.mjs +895 -0
  25. package/src/PcbScene3dBoardSolderMaskFactory.mjs +613 -0
  26. package/src/PcbScene3dCameraRig.mjs +168 -0
  27. package/src/PcbScene3dCircuitJsonAdapter.mjs +545 -0
  28. package/src/PcbScene3dController.mjs +956 -0
  29. package/src/PcbScene3dCopperDetailFilter.mjs +490 -0
  30. package/src/PcbScene3dCopperFactory.mjs +559 -0
  31. package/src/PcbScene3dCopperTextFactory.mjs +534 -0
  32. package/src/PcbScene3dCutoutGeometryFilter.mjs +873 -0
  33. package/src/PcbScene3dDetailCoordinateNormalizer.mjs +65 -0
  34. package/src/PcbScene3dDrillCutoutFilter.mjs +224 -0
  35. package/src/PcbScene3dDrillPathFactory.mjs +362 -0
  36. package/src/PcbScene3dDrillVoidFactory.mjs +268 -0
  37. package/src/PcbScene3dExternalModelLoadOrder.mjs +54 -0
  38. package/src/PcbScene3dExternalModels.mjs +968 -0
  39. package/src/PcbScene3dFallbackVisibility.mjs +82 -0
  40. package/src/PcbScene3dInteractionHints.mjs +56 -0
  41. package/src/PcbScene3dMountRig.mjs +53 -0
  42. package/src/PcbScene3dOutlineBuilder.mjs +210 -0
  43. package/src/PcbScene3dPadFactory.mjs +553 -0
  44. package/src/PcbScene3dPresetState.mjs +48 -0
  45. package/src/PcbScene3dRenderGroupVisibility.mjs +134 -0
  46. package/src/PcbScene3dRuntime.mjs +996 -0
  47. package/src/PcbScene3dRuntimeBoardMeshes.mjs +99 -0
  48. package/src/PcbScene3dSelectionStyler.mjs +252 -0
  49. package/src/PcbScene3dShapePathFactory.mjs +220 -0
  50. package/src/PcbScene3dShellRenderer.mjs +131 -0
  51. package/src/PcbScene3dSilkscreenFactory.mjs +854 -0
  52. package/src/PcbScene3dSilkscreenStrokeWidthResolver.mjs +81 -0
  53. package/src/PcbScene3dStepLoader.mjs +611 -0
  54. package/src/PcbScene3dStrokeFont.mjs +671 -0
  55. package/src/PcbScene3dStrokeGeometryBuilder.mjs +322 -0
  56. package/src/PcbScene3dText.mjs +99 -0
  57. package/src/PcbScene3dTrueTypeTextFactory.mjs +885 -0
  58. package/src/PcbScene3dViaFactory.mjs +176 -0
  59. package/src/PcbScene3dViewCompensation.mjs +109 -0
  60. package/src/PcbScene3dViewScale.mjs +24 -0
  61. package/src/PcbScene3dViewportResize.mjs +35 -0
  62. package/src/PcbScene3dWorkerClient.mjs +123 -0
  63. package/src/index.mjs +1 -0
  64. package/src/scene3d.mjs +44 -0
  65. package/src/styles/scene3d.css +295 -0
@@ -0,0 +1,295 @@
1
+ .scene-3d {
2
+ display: grid;
3
+ grid-template-rows:
4
+ auto auto minmax(clamp(520px, 62vh, 760px), 1fr)
5
+ auto auto;
6
+ gap: 1.2rem;
7
+ width: 100%;
8
+ max-width: 100%;
9
+ height: 100%;
10
+ min-width: 0;
11
+ min-height: 0;
12
+ }
13
+
14
+ body.is-viewer-mode.is-viewer-3d .scene-3d {
15
+ grid-template-rows: auto auto minmax(0, 1fr) auto auto;
16
+ }
17
+
18
+ .scene-3d__toolbar {
19
+ display: flex;
20
+ flex-wrap: wrap;
21
+ gap: 0.55rem;
22
+ }
23
+
24
+ .scene-3d__preset {
25
+ border: 1px solid rgba(95, 112, 124, 0.16);
26
+ border-radius: 999px;
27
+ padding: 0.55rem 0.9rem;
28
+ background: rgba(255, 255, 255, 0.76);
29
+ color: var(--text);
30
+ cursor: pointer;
31
+ transition:
32
+ transform 140ms ease,
33
+ border-color 140ms ease,
34
+ box-shadow 140ms ease;
35
+ }
36
+
37
+ .scene-3d__preset:hover {
38
+ transform: translateY(-1px);
39
+ border-color: rgba(184, 90, 37, 0.34);
40
+ box-shadow: 0 10px 18px rgba(35, 44, 50, 0.1);
41
+ }
42
+
43
+ .scene-3d__preset.is-active,
44
+ .scene-3d__preset[aria-pressed='true'] {
45
+ background: linear-gradient(135deg, var(--brand), var(--accent));
46
+ color: #fff;
47
+ border-color: transparent;
48
+ transform: translateY(-1px);
49
+ box-shadow: 0 12px 22px rgba(35, 44, 50, 0.14);
50
+ }
51
+
52
+ .scene-3d__stage {
53
+ position: relative;
54
+ height: 100%;
55
+ max-width: 100%;
56
+ min-width: 0;
57
+ min-height: 0;
58
+ border-radius: 28px;
59
+ overflow: hidden;
60
+ background:
61
+ radial-gradient(
62
+ circle at top,
63
+ rgba(255, 255, 255, 0.82),
64
+ transparent 48%
65
+ ),
66
+ linear-gradient(180deg, #fff7f1 0%, #edf5f1 100%);
67
+ display: grid;
68
+ grid-template-columns: minmax(0, 1fr) 220px;
69
+ }
70
+
71
+ .scene-3d__viewport {
72
+ position: relative;
73
+ width: 100%;
74
+ max-width: 100%;
75
+ height: 100%;
76
+ min-width: 0;
77
+ min-height: 0;
78
+ background:
79
+ radial-gradient(
80
+ circle at top,
81
+ rgba(255, 255, 255, 0.18),
82
+ transparent 44%
83
+ ),
84
+ linear-gradient(180deg, rgba(24, 31, 35, 0.06), rgba(255, 255, 255, 0));
85
+ }
86
+
87
+ .scene-3d__canvas-mount {
88
+ position: absolute;
89
+ inset: 0;
90
+ }
91
+
92
+ .scene-3d__loading {
93
+ position: absolute;
94
+ inset: 0;
95
+ display: flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ text-align: center;
99
+ padding: 1.5rem;
100
+ color: var(--muted);
101
+ background: radial-gradient(
102
+ circle at top,
103
+ rgba(255, 255, 255, 0.78),
104
+ rgba(255, 247, 241, 0.92) 48%,
105
+ rgba(237, 245, 241, 0.95)
106
+ );
107
+ backdrop-filter: blur(8px);
108
+ z-index: 1;
109
+ }
110
+
111
+ .scene-3d__loading-content {
112
+ display: grid;
113
+ justify-items: center;
114
+ gap: 0.9rem;
115
+ max-width: min(100%, 20rem);
116
+ }
117
+
118
+ .scene-3d__loading[hidden] {
119
+ display: none;
120
+ }
121
+
122
+ .scene-3d__loading p {
123
+ margin: 0;
124
+ }
125
+
126
+ .scene-3d__canvas {
127
+ display: block;
128
+ width: 100%;
129
+ height: 100%;
130
+ cursor: grab;
131
+ touch-action: none;
132
+ }
133
+
134
+ .scene-3d__canvas:active {
135
+ cursor: grabbing;
136
+ }
137
+
138
+ .scene-3d__controls {
139
+ display: grid;
140
+ gap: 0.75rem;
141
+ align-content: start;
142
+ max-height: 100%;
143
+ overflow: auto;
144
+ padding: 1rem;
145
+ background: rgba(255, 255, 255, 0.76);
146
+ border-left: 1px solid rgba(95, 112, 124, 0.12);
147
+ backdrop-filter: blur(10px);
148
+ }
149
+
150
+ .scene-3d__toggle {
151
+ display: flex;
152
+ align-items: center;
153
+ gap: 0.6rem;
154
+ padding: 0.7rem 0.8rem;
155
+ border-radius: 16px;
156
+ background: rgba(255, 255, 255, 0.72);
157
+ border: 1px solid rgba(95, 112, 124, 0.12);
158
+ color: var(--text);
159
+ }
160
+
161
+ .scene-3d__toggle input {
162
+ width: 1rem;
163
+ height: 1rem;
164
+ accent-color: var(--accent);
165
+ }
166
+
167
+ .scene-3d__selection {
168
+ display: grid;
169
+ gap: 0.65rem;
170
+ padding: 0.8rem;
171
+ border-radius: 16px;
172
+ background: rgba(255, 255, 255, 0.72);
173
+ border: 1px solid rgba(95, 112, 124, 0.12);
174
+ }
175
+
176
+ .scene-3d__selection-title {
177
+ margin: 0;
178
+ font-size: 0.9rem;
179
+ }
180
+
181
+ .scene-3d__selection-empty {
182
+ margin: 0;
183
+ color: var(--muted);
184
+ line-height: 1.45;
185
+ }
186
+
187
+ .scene-3d__selection-list {
188
+ display: grid;
189
+ gap: 0.5rem;
190
+ margin: 0;
191
+ }
192
+
193
+ .scene-3d__selection-field {
194
+ display: grid;
195
+ gap: 0.14rem;
196
+ }
197
+
198
+ .scene-3d__selection-field dt {
199
+ color: var(--muted);
200
+ font-size: 0.72rem;
201
+ text-transform: uppercase;
202
+ letter-spacing: 0.05em;
203
+ }
204
+
205
+ .scene-3d__selection-field dd {
206
+ margin: 0;
207
+ font-weight: 600;
208
+ line-height: 1.35;
209
+ word-break: break-word;
210
+ }
211
+
212
+ .scene-3d__diagnostics {
213
+ padding: 0.9rem 1rem;
214
+ border-radius: 18px;
215
+ background: rgba(255, 255, 255, 0.72);
216
+ border: 1px solid rgba(95, 112, 124, 0.12);
217
+ color: var(--muted);
218
+ line-height: 1.45;
219
+ }
220
+
221
+ .scene-3d__stats {
222
+ display: grid;
223
+ grid-template-columns: repeat(3, minmax(0, 1fr));
224
+ gap: 0.8rem;
225
+ }
226
+
227
+ .scene-3d__stats div {
228
+ padding: 0.9rem 1rem;
229
+ border-radius: 18px;
230
+ background: rgba(255, 255, 255, 0.72);
231
+ border: 1px solid rgba(95, 112, 124, 0.12);
232
+ }
233
+
234
+ .scene-3d__stats dt {
235
+ color: var(--muted);
236
+ font-size: 0.82rem;
237
+ text-transform: uppercase;
238
+ letter-spacing: 0.06em;
239
+ }
240
+
241
+ .scene-3d__stats dd {
242
+ margin: 0.4rem 0 0;
243
+ font-weight: 700;
244
+ }
245
+
246
+ @media (min-width: 761px) and (max-height: 1280px) {
247
+ body.is-viewer-mode.is-viewer-3d .scene-3d {
248
+ height: auto;
249
+ grid-template-rows:
250
+ auto auto minmax(clamp(460px, 50vh, 600px), auto)
251
+ auto auto;
252
+ }
253
+ }
254
+
255
+ @media (max-width: 760px) {
256
+ .scene-3d {
257
+ grid-template-rows: auto auto auto auto auto;
258
+ }
259
+
260
+ .scene-3d .svg-panel__header {
261
+ align-items: flex-start;
262
+ }
263
+
264
+ .scene-3d .svg-panel__header p {
265
+ flex: 1 1 100%;
266
+ line-height: 1.35;
267
+ white-space: normal;
268
+ }
269
+
270
+ .scene-3d__action {
271
+ flex-basis: 100%;
272
+ }
273
+
274
+ .scene-3d__stats {
275
+ grid-template-columns: 1fr;
276
+ }
277
+
278
+ .scene-3d__stage {
279
+ display: block;
280
+ grid-template-columns: 1fr;
281
+ overflow: visible;
282
+ }
283
+
284
+ .scene-3d__viewport {
285
+ height: clamp(360px, 58vh, 560px);
286
+ min-height: 360px;
287
+ }
288
+
289
+ .scene-3d__controls {
290
+ border-left: 0;
291
+ border-top: 1px solid rgba(95, 112, 124, 0.12);
292
+ max-height: none;
293
+ overflow: visible;
294
+ }
295
+ }