brep-io-kernel 1.0.0-ci.10

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 (271) hide show
  1. package/LICENSE.md +32 -0
  2. package/README.md +157 -0
  3. package/dist-kernel/brep-kernel.js +74699 -0
  4. package/package.json +58 -0
  5. package/src/BREP/AssemblyComponent.js +42 -0
  6. package/src/BREP/BREP.js +43 -0
  7. package/src/BREP/BetterSolid.js +805 -0
  8. package/src/BREP/Edge.js +103 -0
  9. package/src/BREP/Extrude.js +403 -0
  10. package/src/BREP/Face.js +187 -0
  11. package/src/BREP/MeshRepairer.js +634 -0
  12. package/src/BREP/OffsetShellSolid.js +614 -0
  13. package/src/BREP/PointCloudWrap.js +302 -0
  14. package/src/BREP/Revolve.js +345 -0
  15. package/src/BREP/SolidMethods/authoring.js +112 -0
  16. package/src/BREP/SolidMethods/booleanOps.js +230 -0
  17. package/src/BREP/SolidMethods/chamfer.js +122 -0
  18. package/src/BREP/SolidMethods/edgeResolution.js +25 -0
  19. package/src/BREP/SolidMethods/fillet.js +792 -0
  20. package/src/BREP/SolidMethods/index.js +72 -0
  21. package/src/BREP/SolidMethods/io.js +105 -0
  22. package/src/BREP/SolidMethods/lifecycle.js +103 -0
  23. package/src/BREP/SolidMethods/manifoldOps.js +375 -0
  24. package/src/BREP/SolidMethods/meshCleanup.js +2512 -0
  25. package/src/BREP/SolidMethods/meshQueries.js +264 -0
  26. package/src/BREP/SolidMethods/metadata.js +106 -0
  27. package/src/BREP/SolidMethods/metrics.js +51 -0
  28. package/src/BREP/SolidMethods/transforms.js +361 -0
  29. package/src/BREP/SolidMethods/visualize.js +508 -0
  30. package/src/BREP/SolidShared.js +26 -0
  31. package/src/BREP/Sweep.js +1596 -0
  32. package/src/BREP/Tube.js +857 -0
  33. package/src/BREP/Vertex.js +43 -0
  34. package/src/BREP/applyBooleanOperation.js +704 -0
  35. package/src/BREP/boundsUtils.js +48 -0
  36. package/src/BREP/chamfer.js +551 -0
  37. package/src/BREP/edgePolylineUtils.js +85 -0
  38. package/src/BREP/fillets/common.js +388 -0
  39. package/src/BREP/fillets/fillet.js +1422 -0
  40. package/src/BREP/fillets/filletGeometry.js +15 -0
  41. package/src/BREP/fillets/inset.js +389 -0
  42. package/src/BREP/fillets/offsetHelper.js +143 -0
  43. package/src/BREP/fillets/outset.js +88 -0
  44. package/src/BREP/helix.js +193 -0
  45. package/src/BREP/meshToBrep.js +234 -0
  46. package/src/BREP/primitives.js +279 -0
  47. package/src/BREP/setupManifold.js +71 -0
  48. package/src/BREP/threadGeometry.js +1120 -0
  49. package/src/BREP/triangleUtils.js +8 -0
  50. package/src/BREP/triangulate.js +608 -0
  51. package/src/FeatureRegistry.js +183 -0
  52. package/src/PartHistory.js +1132 -0
  53. package/src/UI/AccordionWidget.js +292 -0
  54. package/src/UI/CADmaterials.js +850 -0
  55. package/src/UI/EnvMonacoEditor.js +522 -0
  56. package/src/UI/FloatingWindow.js +396 -0
  57. package/src/UI/HistoryWidget.js +457 -0
  58. package/src/UI/MainToolbar.js +131 -0
  59. package/src/UI/ModelLibraryView.js +194 -0
  60. package/src/UI/OrthoCameraIdle.js +206 -0
  61. package/src/UI/PluginsWidget.js +280 -0
  62. package/src/UI/SceneListing.js +606 -0
  63. package/src/UI/SelectionFilter.js +629 -0
  64. package/src/UI/ViewCube.js +389 -0
  65. package/src/UI/assembly/AssemblyConstraintCollectionWidget.js +329 -0
  66. package/src/UI/assembly/AssemblyConstraintControlsWidget.js +282 -0
  67. package/src/UI/assembly/AssemblyConstraintsWidget.css +292 -0
  68. package/src/UI/assembly/AssemblyConstraintsWidget.js +1373 -0
  69. package/src/UI/assembly/constraintFaceUtils.js +115 -0
  70. package/src/UI/assembly/constraintHighlightUtils.js +70 -0
  71. package/src/UI/assembly/constraintLabelUtils.js +31 -0
  72. package/src/UI/assembly/constraintPointUtils.js +64 -0
  73. package/src/UI/assembly/constraintSelectionUtils.js +185 -0
  74. package/src/UI/assembly/constraintStatusUtils.js +142 -0
  75. package/src/UI/componentSelectorModal.js +240 -0
  76. package/src/UI/controls/CombinedTransformControls.js +386 -0
  77. package/src/UI/dialogs.js +351 -0
  78. package/src/UI/expressionsManager.js +100 -0
  79. package/src/UI/featureDialogWidgets/booleanField.js +25 -0
  80. package/src/UI/featureDialogWidgets/booleanOperationField.js +97 -0
  81. package/src/UI/featureDialogWidgets/buttonField.js +45 -0
  82. package/src/UI/featureDialogWidgets/componentSelectorField.js +102 -0
  83. package/src/UI/featureDialogWidgets/defaultField.js +23 -0
  84. package/src/UI/featureDialogWidgets/fileField.js +66 -0
  85. package/src/UI/featureDialogWidgets/index.js +34 -0
  86. package/src/UI/featureDialogWidgets/numberField.js +165 -0
  87. package/src/UI/featureDialogWidgets/optionsField.js +33 -0
  88. package/src/UI/featureDialogWidgets/referenceSelectionField.js +208 -0
  89. package/src/UI/featureDialogWidgets/stringField.js +24 -0
  90. package/src/UI/featureDialogWidgets/textareaField.js +28 -0
  91. package/src/UI/featureDialogWidgets/threadDesignationField.js +160 -0
  92. package/src/UI/featureDialogWidgets/transformField.js +252 -0
  93. package/src/UI/featureDialogWidgets/utils.js +43 -0
  94. package/src/UI/featureDialogWidgets/vec3Field.js +133 -0
  95. package/src/UI/featureDialogs.js +1414 -0
  96. package/src/UI/fileManagerWidget.js +615 -0
  97. package/src/UI/history/HistoryCollectionWidget.js +1294 -0
  98. package/src/UI/history/historyCollectionWidget.css.js +257 -0
  99. package/src/UI/history/historyDisplayInfo.js +133 -0
  100. package/src/UI/mobile.js +28 -0
  101. package/src/UI/objectDump.js +442 -0
  102. package/src/UI/pmi/AnnotationCollectionWidget.js +120 -0
  103. package/src/UI/pmi/AnnotationHistory.js +353 -0
  104. package/src/UI/pmi/AnnotationRegistry.js +90 -0
  105. package/src/UI/pmi/BaseAnnotation.js +269 -0
  106. package/src/UI/pmi/LabelOverlay.css +102 -0
  107. package/src/UI/pmi/LabelOverlay.js +191 -0
  108. package/src/UI/pmi/PMIMode.js +1550 -0
  109. package/src/UI/pmi/PMIViewsWidget.js +1098 -0
  110. package/src/UI/pmi/annUtils.js +729 -0
  111. package/src/UI/pmi/dimensions/AngleDimensionAnnotation.js +647 -0
  112. package/src/UI/pmi/dimensions/ExplodeBodyAnnotation.js +507 -0
  113. package/src/UI/pmi/dimensions/HoleCalloutAnnotation.js +462 -0
  114. package/src/UI/pmi/dimensions/LeaderAnnotation.js +403 -0
  115. package/src/UI/pmi/dimensions/LinearDimensionAnnotation.js +532 -0
  116. package/src/UI/pmi/dimensions/NoteAnnotation.js +110 -0
  117. package/src/UI/pmi/dimensions/RadialDimensionAnnotation.js +659 -0
  118. package/src/UI/pmi/pmiStyle.js +44 -0
  119. package/src/UI/sketcher/SketchMode3D.js +4095 -0
  120. package/src/UI/sketcher/dimensions.js +674 -0
  121. package/src/UI/sketcher/glyphs.js +236 -0
  122. package/src/UI/sketcher/highlights.js +60 -0
  123. package/src/UI/toolbarButtons/aboutButton.js +5 -0
  124. package/src/UI/toolbarButtons/exportButton.js +609 -0
  125. package/src/UI/toolbarButtons/flatPatternButton.js +307 -0
  126. package/src/UI/toolbarButtons/importButton.js +160 -0
  127. package/src/UI/toolbarButtons/inspectorToggleButton.js +12 -0
  128. package/src/UI/toolbarButtons/metadataButton.js +1063 -0
  129. package/src/UI/toolbarButtons/orientToFaceButton.js +114 -0
  130. package/src/UI/toolbarButtons/registerDefaultButtons.js +46 -0
  131. package/src/UI/toolbarButtons/saveButton.js +99 -0
  132. package/src/UI/toolbarButtons/scriptRunnerButton.js +302 -0
  133. package/src/UI/toolbarButtons/testsButton.js +26 -0
  134. package/src/UI/toolbarButtons/undoRedoButtons.js +25 -0
  135. package/src/UI/toolbarButtons/wireframeToggleButton.js +5 -0
  136. package/src/UI/toolbarButtons/zoomToFitButton.js +5 -0
  137. package/src/UI/triangleDebuggerWindow.js +945 -0
  138. package/src/UI/viewer.js +4228 -0
  139. package/src/assemblyConstraints/AssemblyConstraintHistory.js +1576 -0
  140. package/src/assemblyConstraints/AssemblyConstraintRegistry.js +120 -0
  141. package/src/assemblyConstraints/BaseAssemblyConstraint.js +66 -0
  142. package/src/assemblyConstraints/constraintExpressionUtils.js +35 -0
  143. package/src/assemblyConstraints/constraintUtils/parallelAlignment.js +676 -0
  144. package/src/assemblyConstraints/constraints/AngleConstraint.js +485 -0
  145. package/src/assemblyConstraints/constraints/CoincidentConstraint.js +194 -0
  146. package/src/assemblyConstraints/constraints/DistanceConstraint.js +616 -0
  147. package/src/assemblyConstraints/constraints/FixedConstraint.js +78 -0
  148. package/src/assemblyConstraints/constraints/ParallelConstraint.js +252 -0
  149. package/src/assemblyConstraints/constraints/TouchAlignConstraint.js +961 -0
  150. package/src/core/entities/HistoryCollectionBase.js +72 -0
  151. package/src/core/entities/ListEntityBase.js +109 -0
  152. package/src/core/entities/schemaProcesser.js +121 -0
  153. package/src/exporters/sheetMetalFlatPattern.js +659 -0
  154. package/src/exporters/sheetMetalUnfold.js +862 -0
  155. package/src/exporters/step.js +1135 -0
  156. package/src/exporters/threeMF.js +575 -0
  157. package/src/features/assemblyComponent/AssemblyComponentFeature.js +780 -0
  158. package/src/features/boolean/BooleanFeature.js +94 -0
  159. package/src/features/chamfer/ChamferFeature.js +116 -0
  160. package/src/features/datium/DatiumFeature.js +80 -0
  161. package/src/features/edgeFeatureUtils.js +41 -0
  162. package/src/features/extrude/ExtrudeFeature.js +143 -0
  163. package/src/features/fillet/FilletFeature.js +197 -0
  164. package/src/features/helix/HelixFeature.js +405 -0
  165. package/src/features/hole/HoleFeature.js +1050 -0
  166. package/src/features/hole/screwClearance.js +86 -0
  167. package/src/features/hole/threadDesignationCatalog.js +149 -0
  168. package/src/features/imageHeightSolid/ImageHeightmapSolidFeature.js +463 -0
  169. package/src/features/imageToFace/ImageToFaceFeature.js +727 -0
  170. package/src/features/imageToFace/imageEditor.js +1270 -0
  171. package/src/features/imageToFace/traceUtils.js +971 -0
  172. package/src/features/import3dModel/Import3dModelFeature.js +151 -0
  173. package/src/features/loft/LoftFeature.js +605 -0
  174. package/src/features/mirror/MirrorFeature.js +151 -0
  175. package/src/features/offsetFace/OffsetFaceFeature.js +370 -0
  176. package/src/features/offsetShell/OffsetShellFeature.js +89 -0
  177. package/src/features/overlapCleanup/OverlapCleanupFeature.js +85 -0
  178. package/src/features/pattern/PatternFeature.js +275 -0
  179. package/src/features/patternLinear/PatternLinearFeature.js +120 -0
  180. package/src/features/patternRadial/PatternRadialFeature.js +186 -0
  181. package/src/features/plane/PlaneFeature.js +154 -0
  182. package/src/features/primitiveCone/primitiveConeFeature.js +99 -0
  183. package/src/features/primitiveCube/primitiveCubeFeature.js +70 -0
  184. package/src/features/primitiveCylinder/primitiveCylinderFeature.js +91 -0
  185. package/src/features/primitivePyramid/primitivePyramidFeature.js +72 -0
  186. package/src/features/primitiveSphere/primitiveSphereFeature.js +62 -0
  187. package/src/features/primitiveTorus/primitiveTorusFeature.js +109 -0
  188. package/src/features/remesh/RemeshFeature.js +97 -0
  189. package/src/features/revolve/RevolveFeature.js +111 -0
  190. package/src/features/selectionUtils.js +118 -0
  191. package/src/features/sheetMetal/SheetMetalContourFlangeFeature.js +1656 -0
  192. package/src/features/sheetMetal/SheetMetalCutoutFeature.js +1056 -0
  193. package/src/features/sheetMetal/SheetMetalFlangeFeature.js +1568 -0
  194. package/src/features/sheetMetal/SheetMetalHemFeature.js +43 -0
  195. package/src/features/sheetMetal/SheetMetalObject.js +141 -0
  196. package/src/features/sheetMetal/SheetMetalTabFeature.js +176 -0
  197. package/src/features/sheetMetal/UNFOLD_NEUTRAL_REQUIREMENTS.md +153 -0
  198. package/src/features/sheetMetal/contour-flange-rebuild-spec.md +261 -0
  199. package/src/features/sheetMetal/profileUtils.js +25 -0
  200. package/src/features/sheetMetal/sheetMetalCleanup.js +9 -0
  201. package/src/features/sheetMetal/sheetMetalFaceTypes.js +146 -0
  202. package/src/features/sheetMetal/sheetMetalMetadata.js +165 -0
  203. package/src/features/sheetMetal/sheetMetalPipeline.js +169 -0
  204. package/src/features/sheetMetal/sheetMetalProfileUtils.js +216 -0
  205. package/src/features/sheetMetal/sheetMetalTabUtils.js +29 -0
  206. package/src/features/sheetMetal/sheetMetalTree.js +210 -0
  207. package/src/features/sketch/SketchFeature.js +955 -0
  208. package/src/features/sketch/sketchSolver2D/ConstraintEngine.js +800 -0
  209. package/src/features/sketch/sketchSolver2D/constraintDefinitions.js +704 -0
  210. package/src/features/sketch/sketchSolver2D/mathHelpersMod.js +307 -0
  211. package/src/features/spline/SplineEditorSession.js +988 -0
  212. package/src/features/spline/SplineFeature.js +1388 -0
  213. package/src/features/spline/splineUtils.js +218 -0
  214. package/src/features/sweep/SweepFeature.js +110 -0
  215. package/src/features/transform/TransformFeature.js +152 -0
  216. package/src/features/tube/TubeFeature.js +635 -0
  217. package/src/fs.proxy.js +625 -0
  218. package/src/idbStorage.js +254 -0
  219. package/src/index.js +12 -0
  220. package/src/main.js +15 -0
  221. package/src/metadataManager.js +64 -0
  222. package/src/path.proxy.js +277 -0
  223. package/src/plugins/ghLoader.worker.js +151 -0
  224. package/src/plugins/pluginManager.js +286 -0
  225. package/src/pmi/PMIViewsManager.js +134 -0
  226. package/src/services/componentLibrary.js +198 -0
  227. package/src/tests/ConsoleCapture.js +189 -0
  228. package/src/tests/S7-diagnostics-2025-12-23T18-37-23-570Z.json +630 -0
  229. package/src/tests/browserTests.js +597 -0
  230. package/src/tests/debugBoolean.js +225 -0
  231. package/src/tests/partFiles/badBoolean.json +957 -0
  232. package/src/tests/partFiles/extrudeTest.json +88 -0
  233. package/src/tests/partFiles/filletFail.json +58 -0
  234. package/src/tests/partFiles/import_TEst.part.part.json +646 -0
  235. package/src/tests/partFiles/sheetMetalHem.BREP.json +734 -0
  236. package/src/tests/test_boolean_subtract.js +27 -0
  237. package/src/tests/test_chamfer.js +17 -0
  238. package/src/tests/test_extrudeFace.js +24 -0
  239. package/src/tests/test_fillet.js +17 -0
  240. package/src/tests/test_fillet_nonClosed.js +45 -0
  241. package/src/tests/test_filletsMoreDifficult.js +46 -0
  242. package/src/tests/test_history_features_basic.js +149 -0
  243. package/src/tests/test_hole.js +282 -0
  244. package/src/tests/test_mirror.js +16 -0
  245. package/src/tests/test_offsetShellGrouping.js +85 -0
  246. package/src/tests/test_plane.js +4 -0
  247. package/src/tests/test_primitiveCone.js +11 -0
  248. package/src/tests/test_primitiveCube.js +7 -0
  249. package/src/tests/test_primitiveCylinder.js +8 -0
  250. package/src/tests/test_primitivePyramid.js +9 -0
  251. package/src/tests/test_primitiveSphere.js +17 -0
  252. package/src/tests/test_primitiveTorus.js +21 -0
  253. package/src/tests/test_pushFace.js +126 -0
  254. package/src/tests/test_sheetMetalContourFlange.js +125 -0
  255. package/src/tests/test_sheetMetal_features.js +80 -0
  256. package/src/tests/test_sketch_openLoop.js +45 -0
  257. package/src/tests/test_solidMetrics.js +58 -0
  258. package/src/tests/test_stlLoader.js +1889 -0
  259. package/src/tests/test_sweepFace.js +55 -0
  260. package/src/tests/test_tube.js +45 -0
  261. package/src/tests/test_tube_closedLoop.js +67 -0
  262. package/src/tests/tests.js +493 -0
  263. package/src/tools/assemblyConstraintDialogCapturePage.js +56 -0
  264. package/src/tools/dialogCapturePageFactory.js +227 -0
  265. package/src/tools/featureDialogCapturePage.js +47 -0
  266. package/src/tools/pmiAnnotationDialogCapturePage.js +60 -0
  267. package/src/utils/axisHelpers.js +99 -0
  268. package/src/utils/deepClone.js +69 -0
  269. package/src/utils/geometryTolerance.js +37 -0
  270. package/src/utils/normalizeTypeString.js +8 -0
  271. package/src/utils/xformMath.js +51 -0
@@ -0,0 +1,351 @@
1
+
2
+ const overlayStyle = {
3
+ position: 'fixed',
4
+ inset: '0',
5
+ background: 'rgba(0,0,0,.6)',
6
+ display: 'flex',
7
+ alignItems: 'center',
8
+ justifyContent: 'center',
9
+ zIndex: '10000',
10
+ };
11
+
12
+ const dialogStyle = {
13
+ // Centered within overlay
14
+ position: 'relative',
15
+ background: 'var(--bg-elev, #12141b)',
16
+ color: 'var(--text, #e6e6e6)',
17
+ padding: '14px',
18
+ boxShadow: '0 10px 40px rgba(0,0,0,.5)',
19
+ borderRadius: '12px',
20
+ border: '1px solid var(--border, #262b36)',
21
+ fontSize: '14px',
22
+ lineHeight: '1.4',
23
+ textAlign: 'left',
24
+ width: 'min(480px, calc(100vw - 32px))',
25
+ maxWidth: '100%',
26
+ };
27
+
28
+ // Buttons follow the app's neutral button style; the "confirm" style is the emphasized/primary look.
29
+ const neutralButtonStyle = {
30
+ //appearance: 'none',
31
+ border: '1px solid var(--border, #262b36)',
32
+ background: 'linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.03))',
33
+ color: 'var(--text, #e6e6e6)',
34
+ borderRadius: '10px',
35
+ padding: '8px 12px',
36
+ fontWeight: '700',
37
+ fontSize: '12px',
38
+ cursor: 'pointer',
39
+ };
40
+
41
+ const emphasizedButtonStyle = {
42
+ ...neutralButtonStyle,
43
+ border: '1px solid var(--focus, #3b82f6)',
44
+ boxShadow: '0 0 0 3px rgba(59,130,246,.15)'
45
+ };
46
+
47
+ // Keep variable names used below; map to our neutral/emphasized styles.
48
+ const confirmButtonStyle = emphasizedButtonStyle; // used for the default/emphasized action
49
+ const cancelButtonStyle = neutralButtonStyle; // used for the secondary action
50
+
51
+ let _dialogOpenCount = 0;
52
+ const markDialogOpen = () => {
53
+ _dialogOpenCount += 1;
54
+ window.__BREPDialogOpen = _dialogOpenCount > 0;
55
+ };
56
+ const markDialogClosed = () => {
57
+ _dialogOpenCount = Math.max(0, _dialogOpenCount - 1);
58
+ window.__BREPDialogOpen = _dialogOpenCount > 0;
59
+ };
60
+ window.isDialogOpen = () => _dialogOpenCount > 0;
61
+
62
+
63
+ window.confirm = async (message, timeoutInSeconds = null, defaultValue = true) => {
64
+ return new Promise((resolve) => {
65
+ markDialogOpen();
66
+ const overlay = document.createElement('div');
67
+ const dialog = document.createElement('div');
68
+ const messageDiv = document.createElement('div');
69
+ const countdownDiv = document.createElement('div');
70
+ const buttonContainer = document.createElement('div');
71
+ const confirmButton = document.createElement('button');
72
+ const cancelButton = document.createElement('button');
73
+
74
+ // Overlay + dialog styles
75
+ Object.assign(overlay.style, overlayStyle);
76
+ Object.assign(dialog.style, dialogStyle);
77
+
78
+ messageDiv.textContent = message;
79
+ // preformatted text and spacing
80
+ messageDiv.style.whiteSpace = 'pre-wrap';
81
+ messageDiv.style.marginBottom = '8px';
82
+ messageDiv.style.color = 'var(--text, #e6e6e6)';
83
+
84
+ // Countdown indicator
85
+ if (timeoutInSeconds && timeoutInSeconds > 0) {
86
+ countdownDiv.textContent = `Time remaining: ${timeoutInSeconds} seconds`;
87
+ countdownDiv.style.marginBottom = '8px';
88
+ countdownDiv.style.fontSize = '12px';
89
+ countdownDiv.style.color = 'var(--muted, #9aa4b2)';
90
+ dialog.appendChild(countdownDiv);
91
+ }
92
+
93
+ confirmButton.textContent = 'Yes';
94
+ cancelButton.textContent = 'No';
95
+
96
+
97
+ // Highlight default button
98
+ const defaultButton = defaultValue ? confirmButton : cancelButton;
99
+ if (defaultValue) {
100
+ Object.assign(confirmButton.style, confirmButtonStyle);
101
+ Object.assign(cancelButton.style, cancelButtonStyle);
102
+ } else {
103
+ Object.assign(confirmButton.style, cancelButtonStyle);
104
+ Object.assign(cancelButton.style, confirmButtonStyle);
105
+ }
106
+
107
+ // Button container styling
108
+ buttonContainer.style.display = 'flex';
109
+ buttonContainer.style.justifyContent = 'flex-end';
110
+ buttonContainer.style.gap = '8px';
111
+ buttonContainer.style.marginTop = '12px';
112
+
113
+ buttonContainer.appendChild(confirmButton);
114
+ buttonContainer.appendChild(cancelButton);
115
+
116
+ dialog.appendChild(messageDiv);
117
+ dialog.appendChild(buttonContainer);
118
+ overlay.appendChild(dialog);
119
+ document.body.appendChild(overlay);
120
+
121
+ let timeout = null;
122
+ let countdownInterval = null;
123
+
124
+ if (timeoutInSeconds && timeoutInSeconds > 0) {
125
+ timeout = setTimeout(() => {
126
+ cleanup();
127
+ resolve(defaultValue);
128
+ }, timeoutInSeconds * 1000);
129
+
130
+ // Update countdown every second
131
+ let remainingTime = timeoutInSeconds;
132
+ countdownInterval = setInterval(() => {
133
+ remainingTime -= 1;
134
+ if (remainingTime <= 0) {
135
+ clearInterval(countdownInterval);
136
+ }
137
+ countdownDiv.textContent = `Time remaining: ${remainingTime} seconds`;
138
+ }, 1000);
139
+ }
140
+
141
+ const cleanup = () => {
142
+ if (timeout) clearTimeout(timeout); // Clear the timeout if it exists
143
+ if (countdownInterval) clearInterval(countdownInterval); // Clear the countdown interval
144
+ confirmButton.removeEventListener('click', onConfirm);
145
+ cancelButton.removeEventListener('click', onCancel);
146
+ try { overlay.remove(); } catch (_) { try { dialog.remove(); } catch (_) {} }
147
+ markDialogClosed();
148
+ };
149
+
150
+ const onConfirm = () => {
151
+ cleanup(); // Ensure dialog is removed first
152
+ resolve(true); // Then resolve the promise
153
+ };
154
+
155
+ const onCancel = () => {
156
+ cleanup(); // Ensure dialog is removed first
157
+ resolve(false); // Then resolve the promise
158
+ };
159
+
160
+ confirmButton.addEventListener('click', onConfirm);
161
+ cancelButton.addEventListener('click', onCancel);
162
+
163
+ // ensure the emphasized/default action receives focus for Enter/Space
164
+ requestAnimationFrame(() => defaultButton.focus());
165
+ });
166
+ };
167
+
168
+
169
+
170
+
171
+ window.alert = async (message, timeoutInSeconds = null) => {
172
+ return new Promise((resolve) => {
173
+ markDialogOpen();
174
+ const overlay = document.createElement('div');
175
+ const dialog = document.createElement('div');
176
+ const messageDiv = document.createElement('div');
177
+ const countdownDiv = document.createElement('div');
178
+ const buttonContainer = document.createElement('div');
179
+ const okButton = document.createElement('button');
180
+
181
+ // Set up styles
182
+ Object.assign(overlay.style, overlayStyle);
183
+ Object.assign(dialog.style, dialogStyle);
184
+
185
+ messageDiv.textContent = message;
186
+ // set style to preformatted text
187
+ messageDiv.style.whiteSpace = 'pre-wrap';
188
+ messageDiv.style.marginBottom = '8px';
189
+ messageDiv.style.color = 'var(--text, #e6e6e6)';
190
+
191
+ // Countdown indicator
192
+ if (timeoutInSeconds && timeoutInSeconds > 0) {
193
+ countdownDiv.textContent = `Time remaining: ${timeoutInSeconds} seconds`;
194
+ countdownDiv.style.marginBottom = '8px';
195
+ countdownDiv.style.fontSize = '12px';
196
+ countdownDiv.style.color = 'var(--muted, #9aa4b2)';
197
+ dialog.appendChild(countdownDiv);
198
+ }
199
+
200
+ okButton.textContent = 'OK';
201
+ Object.assign(okButton.style, confirmButtonStyle);
202
+
203
+ // Button container styling
204
+ buttonContainer.style.display = 'flex';
205
+ buttonContainer.style.justifyContent = 'flex-end';
206
+ buttonContainer.style.gap = '8px';
207
+ buttonContainer.style.marginTop = '12px';
208
+
209
+ buttonContainer.appendChild(okButton);
210
+
211
+ dialog.appendChild(messageDiv);
212
+ dialog.appendChild(buttonContainer);
213
+ overlay.appendChild(dialog);
214
+ document.body.appendChild(overlay);
215
+
216
+ let timeout = null;
217
+ let countdownInterval = null;
218
+
219
+ if (timeoutInSeconds && timeoutInSeconds > 0) {
220
+ timeout = setTimeout(() => {
221
+ cleanup();
222
+ resolve();
223
+ }, timeoutInSeconds * 1000);
224
+
225
+ // Update countdown every second
226
+ let remainingTime = timeoutInSeconds;
227
+ countdownInterval = setInterval(() => {
228
+ remainingTime -= 1;
229
+ if (remainingTime <= 0) {
230
+ clearInterval(countdownInterval);
231
+ }
232
+ countdownDiv.textContent = `Time remaining: ${remainingTime} seconds`;
233
+ }, 1000);
234
+ }
235
+
236
+ const cleanup = () => {
237
+ if (timeout) clearTimeout(timeout); // Clear the timeout if it exists
238
+ if (countdownInterval) clearInterval(countdownInterval); // Clear the countdown interval
239
+ okButton.removeEventListener('click', onOk);
240
+ try { overlay.remove(); } catch (_) { try { dialog.remove(); } catch (_) {} }
241
+ markDialogClosed();
242
+ };
243
+
244
+ const onOk = () => {
245
+ cleanup(); // Ensure dialog is removed first
246
+ resolve(); // Then resolve the promise
247
+ };
248
+
249
+ okButton.addEventListener('click', onOk);
250
+
251
+ // make the OK button focused by default
252
+ okButton.focus();
253
+
254
+ });
255
+ };
256
+
257
+
258
+
259
+
260
+ window.prompt = async (message, defaultValue = '') => {
261
+ return new Promise((resolve) => {
262
+ markDialogOpen();
263
+ const overlay = document.createElement('div');
264
+ const dialog = document.createElement('div');
265
+ const messageDiv = document.createElement('div');
266
+ const inputField = document.createElement('input');
267
+ const buttonContainer = document.createElement('div');
268
+ const okButton = document.createElement('button');
269
+ const cancelButton = document.createElement('button');
270
+
271
+ // Set up styles
272
+ Object.assign(overlay.style, overlayStyle);
273
+ Object.assign(dialog.style, dialogStyle);
274
+
275
+ messageDiv.textContent = message;
276
+ messageDiv.style.whiteSpace = 'pre-wrap';
277
+ messageDiv.style.marginBottom = '8px';
278
+ messageDiv.style.color = 'var(--text, #e6e6e6)';
279
+
280
+ inputField.type = 'text';
281
+ inputField.value = defaultValue;
282
+ inputField.style.width = '100%';
283
+ inputField.style.boxSizing = 'border-box';
284
+ inputField.style.padding = '8px 10px';
285
+ inputField.style.border = '1px solid var(--border, #262b36)';
286
+ inputField.style.borderRadius = '10px';
287
+ inputField.style.marginBottom = '10px';
288
+ inputField.style.fontSize = '14px';
289
+ inputField.style.background = 'var(--input-bg, #0b0e14)';
290
+ inputField.style.color = 'var(--text, #e6e6e6)';
291
+ inputField.style.outline = 'none';
292
+
293
+ okButton.textContent = 'OK';
294
+ Object.assign(okButton.style, confirmButtonStyle);
295
+ cancelButton.textContent = 'Cancel';
296
+ Object.assign(cancelButton.style, cancelButtonStyle);
297
+
298
+ buttonContainer.appendChild(okButton);
299
+ buttonContainer.appendChild(cancelButton);
300
+
301
+ // Button container styling
302
+ buttonContainer.style.display = 'flex';
303
+ buttonContainer.style.justifyContent = 'flex-end';
304
+ buttonContainer.style.gap = '8px';
305
+ buttonContainer.style.marginTop = '4px';
306
+
307
+ dialog.appendChild(messageDiv);
308
+ dialog.appendChild(inputField);
309
+ dialog.appendChild(buttonContainer);
310
+ overlay.appendChild(dialog);
311
+ document.body.appendChild(overlay);
312
+
313
+ // Focus and select the existing text so typing replaces it by default.
314
+ requestAnimationFrame(() => {
315
+ inputField.focus();
316
+ inputField.select();
317
+ });
318
+
319
+ const cleanup = () => {
320
+ okButton.removeEventListener('click', onOk);
321
+ cancelButton.removeEventListener('click', onCancel);
322
+ inputField.removeEventListener('keydown', onEnter);
323
+ try { overlay.remove(); } catch (_) { try { dialog.remove(); } catch (_) {} }
324
+ markDialogClosed();
325
+ };
326
+
327
+ const onOk = () => {
328
+ cleanup();
329
+ resolve(inputField.value); // Resolve with the value entered
330
+ };
331
+
332
+ const onCancel = () => {
333
+ cleanup();
334
+ resolve(null); // Resolve with null for cancel
335
+ };
336
+
337
+ const onEnter = (event) => {
338
+ if (event.key === 'Enter') {
339
+ event.preventDefault();
340
+ onOk();
341
+ } else if (event.key === 'Escape') {
342
+ event.preventDefault();
343
+ onCancel();
344
+ }
345
+ };
346
+
347
+ okButton.addEventListener('click', onOk);
348
+ cancelButton.addEventListener('click', onCancel);
349
+ inputField.addEventListener('keydown', onEnter);
350
+ });
351
+ };
@@ -0,0 +1,100 @@
1
+ // This is a simple widget that contains a text area.
2
+ // The text area is going to have javascript code
3
+
4
+
5
+
6
+ export class expressionsManager {
7
+ constructor(viewer) {
8
+ this.viewer = viewer;
9
+ this.uiElement = document.createElement('div');
10
+ this.expressionCode = '';
11
+ this.generateUI();
12
+ }
13
+
14
+ generateUI() {
15
+ // add a style element with the styles
16
+ const style = document.createElement('style');
17
+ style.textContent = `
18
+ .test-expressions-button {
19
+ background: rgb(31, 41, 55);
20
+ color: rgb(249, 250, 251);
21
+ border: 1px solid rgb(55, 65, 81);
22
+ padding: 3px;
23
+ border-radius: 8px;
24
+ cursor: pointer;
25
+ font-weight: 700;
26
+ outline: none;
27
+ transition: background 120ms, transform 60ms, box-shadow 120ms;
28
+ user-select: none;
29
+ box-shadow: none;
30
+ transform: none;
31
+ }
32
+ .test-expressions-button:hover {
33
+ background-color: #45a049;
34
+ }
35
+ .expressions-textarea {
36
+ width: 100%;
37
+ height: 200px;
38
+ font-family: monospace;
39
+ padding: 5px;
40
+ }
41
+ .expressions-results {
42
+ margin-top: 10px;
43
+ font-weight: bold;
44
+ padding: 5px;
45
+ color: red;
46
+ }
47
+ `;
48
+ document.head.appendChild(style);
49
+
50
+ const textArea = document.createElement('textarea');
51
+ textArea.placeholder = `// example Javascript math syntax . . .\nx = 30;\ny = 2 * x;`;
52
+ this.uiElement.appendChild(textArea);
53
+ this.textArea = textArea;
54
+ this.textArea.classList.add('expressions-textarea');
55
+ textArea.value = this.viewer.partHistory.expressions;
56
+ this.textArea.addEventListener('change', () => this.saveAndTest());
57
+ this.uiElement.appendChild(this.textArea);
58
+
59
+ // add a button that can trigger the save and test method
60
+ this.saveButton = document.createElement('button');
61
+ this.saveButton.textContent = 'Test Expressions';
62
+ this.saveButton.classList.add('test-expressions-button');
63
+ this.saveButton.addEventListener('click', () => this.saveAndTest());
64
+ this.uiElement.appendChild(this.saveButton);
65
+
66
+
67
+ this.resultDiv = document.createElement('div');
68
+ this.resultDiv.classList.add('expressions-results');
69
+ this.uiElement.appendChild(this.resultDiv);
70
+ }
71
+
72
+ saveAndTest() {
73
+ this.resultDiv.textContent = "Expressions evaluated successfully.";
74
+ this.resultDiv.style.color = 'green';
75
+ let succeeded = false;
76
+ try {
77
+ const functionString = `return (function(){ ${this.textArea.value} ;});`;
78
+ Function(functionString)();
79
+ this.viewer.partHistory.expressions = this.textArea.value;
80
+ succeeded = true;
81
+ } catch (error) {
82
+ this.resultDiv.innerHTML = "Error occurred while testing expressions. <br>" + error.message;
83
+ this.resultDiv.style.color = 'red';
84
+ succeeded = false;
85
+ }
86
+
87
+ if (succeeded) {
88
+ this.resultDiv.textContent = "Expressions evaluated successfully.";
89
+ this.resultDiv.style.color = 'green';
90
+ const runPromise = this.viewer.partHistory.runHistory();
91
+ if (runPromise && typeof runPromise.then === 'function') {
92
+ runPromise.then(() => {
93
+ this.viewer.partHistory?.queueHistorySnapshot?.({ reason: 'expressions' });
94
+ });
95
+ } else {
96
+ this.viewer.partHistory?.queueHistorySnapshot?.({ reason: 'expressions' });
97
+ }
98
+ }
99
+ }
100
+ }
@@ -0,0 +1,25 @@
1
+ export function renderBooleanField({ ui, key, def, id }) {
2
+ const inputEl = document.createElement('input');
3
+ inputEl.type = 'checkbox';
4
+ inputEl.id = id;
5
+ inputEl.className = 'checkbox';
6
+
7
+ ui._setInputValue(inputEl, 'boolean', ui._pickInitialValue(key, def));
8
+
9
+ inputEl.addEventListener('change', () => {
10
+ const v = Boolean(inputEl.checked);
11
+ ui.params[key] = v;
12
+ ui._emitParamsChange(key, v);
13
+ ui._stopActiveReferenceSelection();
14
+ });
15
+
16
+ return {
17
+ inputEl,
18
+ activate() {
19
+ inputEl.focus();
20
+ },
21
+ readValue() {
22
+ return Boolean(inputEl.checked);
23
+ },
24
+ };
25
+ }
@@ -0,0 +1,97 @@
1
+ export function renderBooleanOperationField({ ui, key, def, controlWrap }) {
2
+ if (!ui.params[key] || typeof ui.params[key] !== 'object') {
3
+ ui.params[key] = { targets: [], operation: 'NONE', operation: 'NONE' };
4
+ } else {
5
+ if (!Array.isArray(ui.params[key].targets)) ui.params[key].targets = [];
6
+ if (!ui.params[key].operation && !ui.params[key].operation) ui.params[key].operation = 'NONE';
7
+ }
8
+
9
+ const wrap = document.createElement('div');
10
+ wrap.className = 'bool-op-wrap';
11
+
12
+ const sel = document.createElement('select');
13
+ sel.className = 'select';
14
+ sel.dataset.role = 'bool-op';
15
+ const ops = Array.isArray(def.options) && def.options.length ? def.options : ['NONE', 'UNION', 'SUBTRACT', 'INTERSECT'];
16
+ for (const op of ops) {
17
+ const opt = document.createElement('option');
18
+ opt.value = String(op);
19
+ opt.textContent = String(op);
20
+ sel.appendChild(opt);
21
+ }
22
+ sel.value = String((ui.params[key].operation ?? ui.params[key].operation) || 'NONE');
23
+ sel.addEventListener('change', () => {
24
+ if (!ui.params[key] || typeof ui.params[key] !== 'object') ui.params[key] = { targets: [], operation: 'NONE' };
25
+ ui.params[key].operation = sel.value;
26
+ ui.params[key].operation = sel.value;
27
+ ui._emitParamsChange(key, ui.params[key]);
28
+ });
29
+ wrap.appendChild(sel);
30
+
31
+ const refWrap = document.createElement('div');
32
+ refWrap.className = 'ref-multi-wrap';
33
+ const chipsWrap = document.createElement('div');
34
+ chipsWrap.className = 'ref-chips';
35
+ refWrap.appendChild(chipsWrap);
36
+
37
+ const inputElTargets = document.createElement('input');
38
+ inputElTargets.type = 'text';
39
+ inputElTargets.className = 'input';
40
+ inputElTargets.dataset.multiple = 'true';
41
+ inputElTargets.placeholder = 'Click then select solids…';
42
+ ui._renderChips(chipsWrap, key, Array.isArray(ui.params[key].targets) ? ui.params[key].targets : []);
43
+
44
+ const activate = () => {
45
+ ui._activateReferenceSelection(inputElTargets, { selectionFilter: ['SOLID'] });
46
+ };
47
+ chipsWrap.addEventListener('click', activate);
48
+ inputElTargets.addEventListener('click', activate);
49
+
50
+ inputElTargets.addEventListener('change', () => {
51
+ if (inputElTargets.dataset && inputElTargets.dataset.forceClear === 'true') {
52
+ if (!ui.params[key] || typeof ui.params[key] !== 'object') ui.params[key] = { targets: [], operation: 'NONE' };
53
+ ui.params[key].targets = [];
54
+ ui._renderChips(chipsWrap, key, ui.params[key].targets);
55
+ inputElTargets.value = '';
56
+ delete inputElTargets.dataset.forceClear;
57
+ ui._emitParamsChange(key, ui.params[key]);
58
+ return;
59
+ }
60
+ if (!ui.params[key] || typeof ui.params[key] !== 'object') ui.params[key] = { targets: [], operation: 'NONE' };
61
+ let incoming = [];
62
+ try {
63
+ const parsed = JSON.parse(inputElTargets.value);
64
+ if (Array.isArray(parsed)) incoming = parsed;
65
+ } catch (_) {
66
+ if (inputElTargets.value && String(inputElTargets.value).trim() !== '') incoming = [String(inputElTargets.value).trim()];
67
+ }
68
+ const cur = Array.isArray(ui.params[key].targets) ? ui.params[key].targets : [];
69
+ for (const name of incoming) {
70
+ if (!cur.includes(name)) cur.push(name);
71
+ }
72
+ ui.params[key].targets = cur;
73
+ ui._renderChips(chipsWrap, key, cur);
74
+ inputElTargets.value = '';
75
+ ui._emitParamsChange(key, ui.params[key]);
76
+ });
77
+
78
+ refWrap.appendChild(inputElTargets);
79
+ wrap.appendChild(refWrap);
80
+
81
+ controlWrap.appendChild(wrap);
82
+
83
+ return {
84
+ inputEl: inputElTargets,
85
+ activate,
86
+ readValue() {
87
+ const current = ui.params[key];
88
+ if (!current || typeof current !== 'object') {
89
+ return { targets: [], operation: 'NONE' };
90
+ }
91
+ return {
92
+ targets: Array.isArray(current.targets) ? current.targets.slice() : [],
93
+ operation: current.operation || 'NONE',
94
+ };
95
+ },
96
+ };
97
+ }
@@ -0,0 +1,45 @@
1
+ export function renderButtonField({ ui, key, def, id }) {
2
+ const inputEl = document.createElement('button');
3
+ inputEl.type = 'button';
4
+ inputEl.id = id;
5
+ inputEl.className = 'btn';
6
+ inputEl.textContent = String(def.label || ui._prettyLabel(key));
7
+
8
+ inputEl.addEventListener('click', (ev) => {
9
+ ev.preventDefault();
10
+ ui._stopActiveReferenceSelection();
11
+ const fid = (ui.params && Object.prototype.hasOwnProperty.call(ui.params, 'featureID'))
12
+ ? ui.params.featureID
13
+ : (ui.params?.id ?? null);
14
+ let handled = false;
15
+ try {
16
+ if (def && typeof def.actionFunction === 'function') {
17
+ const ctx = {
18
+ featureID: fid,
19
+ key,
20
+ viewer: ui.options?.viewer || null,
21
+ partHistory: ui.options?.partHistory || null,
22
+ feature: ui.options?.featureRef || null,
23
+ params: ui.params,
24
+ schemaDef: def,
25
+ };
26
+ const r = def.actionFunction(ctx);
27
+ handled = true;
28
+ void r;
29
+ }
30
+ } catch (_) { }
31
+ if (!handled) {
32
+ try { if (typeof ui.options.onAction === 'function') ui.options.onAction(fid, key); } catch (_) { }
33
+ }
34
+ });
35
+
36
+ return {
37
+ inputEl,
38
+ activate() {
39
+ inputEl.focus();
40
+ },
41
+ readValue() {
42
+ return null;
43
+ },
44
+ };
45
+ }