@wandelbots/wandelbots-js-react-components 4.6.0 → 4.7.0

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 (50) hide show
  1. package/dist/3d.cjs.js +1 -1
  2. package/dist/3d.es.js +1 -1
  3. package/dist/{LoadingCover-6gWr11KP.js → LoadingCover-B3UN1lnU.js} +12 -19
  4. package/dist/LoadingCover-B3UN1lnU.js.map +1 -0
  5. package/dist/LoadingCover-DXcsXWDy.cjs +2 -0
  6. package/dist/LoadingCover-DXcsXWDy.cjs.map +1 -0
  7. package/dist/MotionGroupVisualizer-D8_sA8PA.js +1347 -0
  8. package/dist/MotionGroupVisualizer-D8_sA8PA.js.map +1 -0
  9. package/dist/MotionGroupVisualizer-DcHXsQ4A.cjs +2 -0
  10. package/dist/MotionGroupVisualizer-DcHXsQ4A.cjs.map +1 -0
  11. package/dist/{WandelscriptEditor-D6_vS5Uk.cjs → WandelscriptEditor-6sAoniLC.cjs} +2 -2
  12. package/dist/{WandelscriptEditor-D6_vS5Uk.cjs.map → WandelscriptEditor-6sAoniLC.cjs.map} +1 -1
  13. package/dist/{WandelscriptEditor-7eN-Yw7m.js → WandelscriptEditor-kWC2VyG_.js} +3 -3
  14. package/dist/{WandelscriptEditor-7eN-Yw7m.js.map → WandelscriptEditor-kWC2VyG_.js.map} +1 -1
  15. package/dist/components/3d-viewport/SafetyZonesRenderer.d.ts +1 -1
  16. package/dist/components/3d-viewport/SafetyZonesRenderer.d.ts.map +1 -1
  17. package/dist/components/utils/converters.d.ts +9 -0
  18. package/dist/components/utils/converters.d.ts.map +1 -1
  19. package/dist/core.cjs.js +1 -1
  20. package/dist/core.es.js +4 -4
  21. package/dist/{externalizeComponent-CkVWk2F_.cjs → externalizeComponent-B98tgTPP.cjs} +6 -6
  22. package/dist/externalizeComponent-B98tgTPP.cjs.map +1 -0
  23. package/dist/{externalizeComponent-Dc3fViZA.js → externalizeComponent-BOqKMZMc.js} +167 -130
  24. package/dist/externalizeComponent-BOqKMZMc.js.map +1 -0
  25. package/dist/index.cjs.js +1 -1
  26. package/dist/index.es.js +6 -6
  27. package/dist/{interpolation-BxZtUOAs.js → interpolation-B8AcxfdD.js} +274 -274
  28. package/dist/interpolation-B8AcxfdD.js.map +1 -0
  29. package/dist/{interpolation-D4zTPZou.cjs → interpolation-SWzo5zr4.cjs} +4 -4
  30. package/dist/interpolation-SWzo5zr4.cjs.map +1 -0
  31. package/dist/{theming-3PEA0ksG.js → theming-BKpqgTRM.js} +4 -4
  32. package/dist/{theming-3PEA0ksG.js.map → theming-BKpqgTRM.js.map} +1 -1
  33. package/dist/{theming-U3LOZpcT.cjs → theming-CatQaIl_.cjs} +2 -2
  34. package/dist/{theming-U3LOZpcT.cjs.map → theming-CatQaIl_.cjs.map} +1 -1
  35. package/dist/wandelscript.cjs.js +1 -1
  36. package/dist/wandelscript.es.js +1 -1
  37. package/package.json +1 -1
  38. package/src/components/3d-viewport/SafetyZonesRenderer.tsx +139 -149
  39. package/src/components/utils/converters.ts +64 -0
  40. package/dist/LoadingCover-6gWr11KP.js.map +0 -1
  41. package/dist/LoadingCover-CukpS_aj.cjs +0 -2
  42. package/dist/LoadingCover-CukpS_aj.cjs.map +0 -1
  43. package/dist/MotionGroupVisualizer-BlWkdkaM.js +0 -1338
  44. package/dist/MotionGroupVisualizer-BlWkdkaM.js.map +0 -1
  45. package/dist/MotionGroupVisualizer-Bw-h3U_t.cjs +0 -2
  46. package/dist/MotionGroupVisualizer-Bw-h3U_t.cjs.map +0 -1
  47. package/dist/externalizeComponent-CkVWk2F_.cjs.map +0 -1
  48. package/dist/externalizeComponent-Dc3fViZA.js.map +0 -1
  49. package/dist/interpolation-BxZtUOAs.js.map +0 -1
  50. package/dist/interpolation-D4zTPZou.cjs.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./WandelscriptEditor-D6_vS5Uk.cjs");exports.WandelscriptEditor=t.WandelscriptEditor;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./WandelscriptEditor-6sAoniLC.cjs");exports.WandelscriptEditor=t.WandelscriptEditor;
2
2
  //# sourceMappingURL=wandelscript.cjs.js.map
@@ -1,4 +1,4 @@
1
- import { W as t } from "./WandelscriptEditor-7eN-Yw7m.js";
1
+ import { W as t } from "./WandelscriptEditor-kWC2VyG_.js";
2
2
  export {
3
3
  t as WandelscriptEditor
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wandelbots/wandelbots-js-react-components",
3
- "version": "4.6.0",
3
+ "version": "4.7.0",
4
4
  "description": "React UI toolkit for building applications on top of the Wandelbots platform",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1,170 +1,165 @@
1
1
  import { useEffect, useMemo } from "react"
2
2
  import { type ThreeElements } from "@react-three/fiber"
3
- import { type Collider, type ConvexHull, type DHParameter, type MotionGroupDescription } from "@wandelbots/nova-js/v2"
4
- import type { Geometry, SafetySetupSafetyZone } from "@wandelbots/nova-js/v1"
5
3
  import * as THREE from "three"
6
- import { ConvexGeometry } from "three-stdlib"
7
- import type { Vector3 } from "three"
4
+ import { ConvexGeometry, RoundedBoxGeometry } from "three-stdlib"
5
+
6
+ import type {
7
+ Collider,
8
+ ConvexHull,
9
+ DHParameter,
10
+ MotionGroupDescription,
11
+ Sphere,
12
+ Capsule,
13
+ RectangularCapsule,
14
+ } from "@wandelbots/nova-js/v2"
15
+ import type { Geometry, SafetySetupSafetyZone } from "@wandelbots/nova-js/v1"
16
+
17
+ import { dhParametersToPlaneSize, orientationToQuaternion, verticesToCoplanarity } from "../utils/converters"
8
18
 
9
19
  export type SafetyZonesRendererProps = {
10
20
  safetyZones: SafetySetupSafetyZone[] | MotionGroupDescription["safety_zones"]
11
21
  dhParameters?: DHParameter[]
12
22
  } & ThreeElements["group"]
13
23
 
14
- interface CoplanarityResult {
15
- isCoplanar: boolean
16
- normal?: THREE.Vector3
17
- }
18
-
19
- function areVerticesCoplanar(vertices: THREE.Vector3[]): CoplanarityResult {
20
- if (vertices.length < 3) {
21
- console.log("Not enough vertices to define a plane")
22
- return { isCoplanar: false }
23
- }
24
-
25
- // Convert Vector3d to THREE.Vector3
26
- const v0 = new THREE.Vector3(vertices[0].x, vertices[0].y, vertices[0].z)
27
- const v1 = new THREE.Vector3(vertices[1].x, vertices[1].y, vertices[1].z)
28
- const v2 = new THREE.Vector3(vertices[2].x, vertices[2].y, vertices[2].z)
29
-
30
- const vector1 = new THREE.Vector3().subVectors(v1, v0)
31
- const vector2 = new THREE.Vector3().subVectors(v2, v0)
32
- const normal = new THREE.Vector3().crossVectors(vector1, vector2).normalize()
33
-
34
- // Check if all remaining vertices lie on the same plane
35
- for (let i = 3; i < vertices.length; i++) {
36
- const vi = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z)
37
- const vector = new THREE.Vector3().subVectors(vi, v0)
38
- const dotProduct = normal.dot(vector)
39
- if (Math.abs(dotProduct) > 1e-6) {
40
- // Allowing a small tolerance
41
- console.log("Vertices are not on the same plane")
42
- return { isCoplanar: false }
43
- }
44
- }
45
-
46
- return { isCoplanar: true, normal }
47
- }
48
-
49
24
  export function SafetyZonesRenderer({
50
25
  safetyZones,
51
26
  dhParameters,
52
27
  ...props
53
28
  }: SafetyZonesRendererProps) {
29
+ /**
30
+ * Common material properties for safety zone meshes
31
+ */
32
+ const safetyZoneMaterialProps = {
33
+ attach: "material" as const,
34
+ color: "#009f4d",
35
+ opacity: 0.2,
36
+ depthTest: false,
37
+ depthWrite: false,
38
+ transparent: true,
39
+ polygonOffset: true,
40
+ }
41
+
42
+ /**
43
+ * Plane size for the plane safety zones, returns the reach distance
44
+ * of the robot
45
+ */
46
+ const planeSize = dhParametersToPlaneSize(dhParameters ?? [])
54
47
 
55
48
  /**
56
49
  * Warning during runtime stating the deprecation of the V1 safety zones
57
50
  */
58
51
  useEffect(() => {
59
- Array.isArray(safetyZones) && console.warn("SafetyZonesRenderer: The support of V1 safety zones is deprecated. Please migrate to V2 safety zones.")
52
+ Array.isArray(safetyZones) &&
53
+ console.warn("SafetyZonesRenderer: The support of V1 safety zones is deprecated. Please migrate to V2 safety zones.")
60
54
  }, [safetyZones])
61
55
 
62
56
  /**
63
- * Helper function to render convex hulls mesh materials
64
- * @param vertices Vector3[]
57
+ * Helper function to render plane, sphere, and capsule meshes
65
58
  * @param id number
59
+ * @param zone Collider
66
60
  */
67
- const renderHullMesh = (vertices: Vector3[], id: number) => {
68
- // Check if the vertices are on the same plane and only define a plane
69
- // Algorithm has troubles with vertices that are on the same plane so we
70
- // add a new vertex slightly moved along the normal direction
71
- const coplanarityResult = areVerticesCoplanar(vertices)
72
-
73
- if (coplanarityResult.isCoplanar && coplanarityResult.normal) {
74
- // Add a new vertex slightly moved along the normal direction
75
- const offset = 0.0001 // Adjust the offset as needed
76
- const newVertex = new THREE.Vector3().addVectors(
77
- vertices[0],
78
- coplanarityResult.normal.multiplyScalar(offset),
79
- )
80
- vertices.push(newVertex)
81
- }
82
-
83
- let convexGeometry
84
- try {
85
- convexGeometry = new ConvexGeometry(vertices)
86
- } catch (error) {
87
- console.log("Error creating ConvexGeometry:", error)
61
+ const renderMesh = (id: number, zone: Collider) => {
62
+ if (!zone?.pose?.position || !zone?.pose?.orientation) {
88
63
  return null
89
64
  }
90
65
 
91
- return (
92
- <mesh key={`safety-zone-mesh-${id}`} geometry={convexGeometry}>
93
- <meshStandardMaterial
94
- key={`safety-zone-material-${id}`}
95
- attach="material"
96
- color="#009f4d"
97
- opacity={0.2}
98
- depthTest={false}
99
- depthWrite={false}
100
- transparent
101
- polygonOffset
102
- polygonOffsetFactor={-id}
103
- />
104
- </mesh>
105
- )
106
- }
66
+ const position = new THREE.Vector3(zone.pose.position[0] / 1000, zone.pose.position[1] / 1000, zone.pose.position[2] / 1000)
67
+ const orientation = new THREE.Vector3(zone.pose.orientation[0], zone.pose.orientation[1], zone.pose.orientation[2])
68
+
69
+ let geometry: React.ReactElement | null
70
+
71
+ const materialProps = zone.shape.shape_type === "plane"
72
+ ? { ...safetyZoneMaterialProps, side: THREE.DoubleSide }
73
+ : { ...safetyZoneMaterialProps, side: THREE.FrontSide }
74
+
75
+ switch (zone.shape.shape_type) {
76
+ /**
77
+ * Plane shape, uses DH parameters to calculate the size of the plane (reach distance of a robot)
78
+ */
79
+ case "plane":
80
+ geometry = <planeGeometry args={[planeSize, planeSize]} />
81
+ break
82
+
83
+ /**
84
+ * Sphere shape
85
+ */
86
+ case "sphere": {
87
+ const radius = (zone?.shape as Sphere).radius / 1000
88
+ geometry = <sphereGeometry args={[radius]} />
89
+ break
90
+ }
107
91
 
108
- /**
109
- * Plane size is calculated based on the reach radius of the robot
110
- */
111
- const planeSize = useMemo(() => {
112
- const defaultPlaneSize = 5
113
- if (!dhParameters || dhParameters.length === 0) {
114
- return defaultPlaneSize
115
- }
116
- const reachRadiusM = dhParameters.reduce((sum, p) => {
117
- return sum + (Math.abs(p.a ?? 0) / 1000) + (Math.abs(p.d ?? 0) / 1000)
118
- }, 0)
119
- const size = reachRadiusM * 2
120
- if (!Number.isFinite(size) || size <= 0) {
121
- return defaultPlaneSize
122
- }
123
- return size
124
- }, [dhParameters])
92
+ /**
93
+ * Capsule shape
94
+ */
95
+ case "capsule": {
96
+ const capsuleRadius = (zone?.shape as Capsule).radius / 1000
97
+ const height = (zone?.shape as Capsule).cylinder_height / 1000
98
+ geometry = <capsuleGeometry args={[capsuleRadius, height]} />
99
+ break
100
+ }
125
101
 
126
- /**
127
- * Helper function to render plane meshes
128
- *
129
- * @param position THREE.Vector3 - The transform origin. This is the point on the plane defined in the Nova V2 API.
130
- * In this visualization, we center the (theoretically infinite) plane on this point.
131
- * This point also acts as the pivot around which the rotation is applied.
132
- * @param orientationVector THREE.Vector3 - A rotation vector (Rodrigues notation).
133
- * - Direction: The axis around which the plane is rotated.
134
- * - Length: The angle of rotation in radians.
135
- * @param id number
136
- */
137
- const renderPlaneMesh = (position: THREE.Vector3, orientationVector: THREE.Vector3, id: number) => {
138
- // The orientation is provided as a rotation vector (also known as Rodrigues notation or axis-angle representation).
139
- // 1. The direction of the vector defines the axis of rotation in 3D space.
140
- // 2. The magnitude (length) of the vector represents the rotation angle in radians.
141
- // The rotation is applied to the default THREE.PlaneGeometry (which starts in the XY plane with normal along +Z).
142
- const angle = orientationVector.length()
143
-
144
- const quaternion = new THREE.Quaternion()
145
- if (angle > 1e-6) {
146
- const axis = orientationVector.clone().normalize()
147
- quaternion.setFromAxisAngle(axis, angle)
102
+ /**
103
+ * Convex hull, checks at first if the vertices are coplanar - if yes, adds a small offset for
104
+ * renderer to be able to visualize the convex hull.
105
+ */
106
+ case "convex_hull": {
107
+ const vertices = (zone?.shape as ConvexHull).vertices.map(
108
+ (v) => new THREE.Vector3(v[0] / 1000, v[1] / 1000, v[2] / 1000),
109
+ )
110
+ // Check if the vertices are on the same plane
111
+ const coplanarityResult = verticesToCoplanarity(vertices)
112
+ if (coplanarityResult.isCoplanar && coplanarityResult.normal) {
113
+ const offset = 0.0001
114
+ const newVertex = new THREE.Vector3().addVectors(
115
+ vertices[0],
116
+ coplanarityResult.normal.multiplyScalar(offset),
117
+ )
118
+ vertices.push(newVertex)
119
+ }
120
+ try {
121
+ geometry = <primitive object={new ConvexGeometry(vertices)} attach="geometry" />
122
+ } catch (error) {
123
+ console.log("Error creating ConvexGeometry:", error)
124
+ return null
125
+ }
126
+ break
127
+ }
128
+
129
+ /**
130
+ * Convex hull around four spheres. Sphere center points in x/y-plane,
131
+ * offset by either combination "+/- sizeX" or "+/- sizeY".
132
+ * Alternative description: Rectangle in x/y-plane with a 3D padding (source: nova-api docs)
133
+ *
134
+ * Basically a rounded box with a rectangular cross-section.
135
+ */
136
+ case "rectangular_capsule": {
137
+ const shape = (zone.shape as RectangularCapsule)
138
+ const rcRadius = shape.radius / 1000
139
+ const width = shape.sphere_center_distance_x / 1000
140
+ const height = shape.sphere_center_distance_y / 1000
141
+ const depth = rcRadius * 2
142
+
143
+ geometry = <primitive object={new RoundedBoxGeometry(width, height, depth, 2, rcRadius)} attach="geometry" />
144
+ break
145
+ }
146
+
147
+ default: {
148
+ console.warn("Unsupported safety zone shape type:", zone.shape.shape_type)
149
+ geometry = null
150
+ }
148
151
  }
149
152
 
150
153
  return (
151
154
  <mesh
152
- key={`safety-zone-plane-${id}`}
155
+ key={`safety-zone-${zone.shape.shape_type}-${id}`}
153
156
  renderOrder={id}
154
157
  position={position}
155
- quaternion={quaternion}
158
+ quaternion={orientationToQuaternion(orientation)}
156
159
  >
157
- <planeGeometry args={[planeSize, planeSize]} />
160
+ {geometry}
158
161
  <meshStandardMaterial
159
- key={`safety-zone-plane-material-${id}`}
160
- attach="material"
161
- color="#009f4d"
162
- opacity={0.2}
163
- depthTest={false}
164
- depthWrite={false}
165
- transparent
166
- side={THREE.DoubleSide}
167
- polygonOffset
162
+ {...materialProps}
168
163
  polygonOffsetFactor={-id}
169
164
  />
170
165
  </mesh>
@@ -176,20 +171,7 @@ export function SafetyZonesRenderer({
176
171
  */
177
172
  const renderV2SafetyZones = () => {
178
173
  return Object.values(safetyZones ?? {}).map((zone: Collider, index: number) => {
179
- switch (zone.shape.shape_type) {
180
- case "convex_hull":
181
- return renderHullMesh(
182
- (zone.shape as ConvexHull).vertices
183
- .map((vertex: number[]) => new THREE.Vector3(vertex[0] / 1000, vertex[1] / 1000, vertex[2] / 1000)), index,
184
- )
185
-
186
- case "plane":
187
- return zone?.pose?.position && zone?.pose?.orientation && renderPlaneMesh(
188
- new THREE.Vector3(zone.pose.position[0] / 1000, zone.pose.position[1] / 1000, zone.pose.position[2] / 1000),
189
- new THREE.Vector3(zone.pose.orientation[0], zone.pose.orientation[1], zone.pose.orientation[2]),
190
- index,
191
- )
192
- }
174
+ return renderMesh(index, zone)
193
175
  })
194
176
  }
195
177
 
@@ -213,12 +195,20 @@ export function SafetyZonesRenderer({
213
195
  return geometries.map((geometry, i) => {
214
196
  if (!geometry.convex_hull) return null
215
197
 
216
- const vertices = geometry.convex_hull.vertices.map(
217
- (v) => new THREE.Vector3(v.x / 1000, v.y / 1000, v.z / 1000),
218
- )
219
-
220
198
  // Use a per-geometry identifier derived from both zone index and geometry index
221
- return renderHullMesh(vertices, index * 1000 + i)
199
+ const id = index * 1000 + i
200
+ // Build a compatible zone object for renderMesh
201
+ const zone: Collider = {
202
+ pose: {
203
+ position: [0, 0, 0],
204
+ orientation: [0, 0, 0],
205
+ },
206
+ shape: {
207
+ shape_type: "convex_hull",
208
+ vertices: geometry.convex_hull.vertices.map((v) => [v.x, v.y, v.z]),
209
+ } as ConvexHull,
210
+ }
211
+ return renderMesh(id, zone)
222
212
  })
223
213
  })
224
214
  }
@@ -1,3 +1,11 @@
1
+ import * as THREE from "three"
2
+ import type { DHParameter } from "@wandelbots/nova-js/v2"
3
+
4
+ export interface CoplanarityResult {
5
+ isCoplanar: boolean
6
+ normal?: THREE.Vector3
7
+ }
8
+
1
9
  export function radiansToDegree(radians: number): number {
2
10
  return radians * (180 / Math.PI)
3
11
  }
@@ -21,3 +29,59 @@ export function tryStringifyJson(json: unknown): string | undefined {
21
29
  return undefined
22
30
  }
23
31
  }
32
+
33
+ export function orientationToQuaternion(orientation: THREE.Vector3): THREE.Quaternion {
34
+ const angle = orientation.length()
35
+ const quaternion = new THREE.Quaternion()
36
+ if (angle > 1e-6) {
37
+ const axis = orientation.clone().normalize()
38
+ quaternion.setFromAxisAngle(axis, angle)
39
+ }
40
+ return quaternion
41
+ }
42
+
43
+ export function dhParametersToPlaneSize(dhParameters: DHParameter[]) {
44
+ const defaultPlaneSize = 5
45
+ if (!dhParameters || dhParameters.length === 0) {
46
+ return defaultPlaneSize
47
+ }
48
+ const reachRadiusM = dhParameters.reduce((sum, p) => {
49
+ return sum + (Math.abs(p.a ?? 0) / 1000) + (Math.abs(p.d ?? 0) / 1000)
50
+ }, 0)
51
+ const size = reachRadiusM * 2
52
+ if (!Number.isFinite(size) || size <= 0) {
53
+ return defaultPlaneSize
54
+ }
55
+ return size
56
+ }
57
+
58
+
59
+ export function verticesToCoplanarity(vertices: THREE.Vector3[]): CoplanarityResult {
60
+ if (vertices.length < 3) {
61
+ console.log("Not enough vertices to define a plane")
62
+ return { isCoplanar: false }
63
+ }
64
+
65
+ // Convert Vector3d to THREE.Vector3
66
+ const v0 = new THREE.Vector3(vertices[0].x, vertices[0].y, vertices[0].z)
67
+ const v1 = new THREE.Vector3(vertices[1].x, vertices[1].y, vertices[1].z)
68
+ const v2 = new THREE.Vector3(vertices[2].x, vertices[2].y, vertices[2].z)
69
+
70
+ const vector1 = new THREE.Vector3().subVectors(v1, v0)
71
+ const vector2 = new THREE.Vector3().subVectors(v2, v0)
72
+ const normal = new THREE.Vector3().crossVectors(vector1, vector2).normalize()
73
+
74
+ // Check if all remaining vertices lie on the same plane
75
+ for (let i = 3; i < vertices.length; i++) {
76
+ const vi = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z)
77
+ const vector = new THREE.Vector3().subVectors(vi, v0)
78
+ const dotProduct = normal.dot(vector)
79
+ if (Math.abs(dotProduct) > 1e-6) {
80
+ // Allowing a small tolerance
81
+ console.log("Vertices are not on the same plane")
82
+ return { isCoplanar: false }
83
+ }
84
+ }
85
+
86
+ return { isCoplanar: true, normal }
87
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"LoadingCover-6gWr11KP.js","sources":["../src/components/utils/converters.ts","../src/components/utils/errorHandling.ts","../src/components/LoadingCover.tsx"],"sourcesContent":["export function radiansToDegree(radians: number): number {\n return radians * (180 / Math.PI)\n}\n\nexport function degreesToRadians(degrees: number): number {\n return degrees * (Math.PI / 180)\n}\n\nexport function tryParseJson(json: unknown): any {\n try {\n return JSON.parse(json as string)\n } catch {\n return undefined\n }\n}\n\nexport function tryStringifyJson(json: unknown): string | undefined {\n try {\n return JSON.stringify(json)\n } catch {\n return undefined\n }\n}\n","import { AxiosError } from \"axios\"\nimport { tryStringifyJson } from \"./converters\"\n\n// Please note: These helper functions also exist in nova.js\n// (with slightly different formatting), and will be unified\n// at some point in the future.\n\nexport function delay(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function makeShortErrorMessage(err: unknown) {\n if (err instanceof AxiosError && err.code === \"ERR_NETWORK\") {\n return \"Failed to connect to the server. Please check your internet connection.\"\n } else if (err instanceof AxiosError && err.response) {\n return `${err.response?.status} ${err.response?.statusText}: ${JSON.stringify(err.response?.data)}`\n } else if (err instanceof Error) {\n return err.message\n } else {\n return `Unexpected error: ${err}`\n }\n}\n\nexport function assertUnreachable(x: never, msg: string): never {\n throw new Error(msg + ` ${JSON.stringify(x)}`)\n}\n\nexport function makeErrorMessage(err: unknown) {\n if (err instanceof AxiosError && err.code === \"ERR_NETWORK\") {\n return \"Failed to connect to the server. Please check your internet connection.\"\n } else if (err instanceof AxiosError && err.response) {\n return `${err.response?.status} ${err.response?.statusText} from ${err.response?.config.url}: ${JSON.stringify(err.response?.data)}`\n } else if (err instanceof Error) {\n return err.message\n } else {\n return `Unexpected error: ${tryStringifyJson(err) || err}`\n }\n}\n","import { capitalize, CircularProgress, Stack, useTheme } from \"@mui/material\"\nimport { lowerFirst } from \"lodash-es\"\nimport { useEffect, useState } from \"react\"\nimport { makeErrorMessage } from \"./utils/errorHandling\"\n\nexport const LoadingCover = (props: {\n message?: string\n error?: unknown\n softTimeout?: number\n}) => {\n const softTimeout = props.softTimeout || 3000\n\n const [showSlowLoadingMessage, setShowSlowLoadingMessage] = useState(false)\n const theme = useTheme()\n\n useEffect(() => {\n const timeout = setTimeout(() => {\n setShowSlowLoadingMessage(true)\n }, softTimeout)\n\n return () => clearTimeout(timeout)\n })\n\n return (\n <Stack\n width=\"100%\"\n height=\"100%\"\n alignItems=\"center\"\n justifyContent=\"center\"\n sx={{ color: theme.palette.text.primary }}\n >\n {props.error ? (\n <LoadingErrorMessage\n loadingMessage={props.message}\n error={props.error}\n />\n ) : (\n <>\n <CircularProgress sx={{ marginBottom: \"24px\" }} />\n {!!props.message && <div>{props.message}</div>}\n <Stack\n sx={{\n visibility: showSlowLoadingMessage ? \"visible\" : \"hidden\",\n marginTop: \"1rem\",\n color: theme.palette.text.secondary,\n }}\n >\n {\"This is taking longer than expected...\"}\n </Stack>\n </>\n )}\n </Stack>\n )\n}\n\nexport const LoadingErrorMessage = (props: {\n loadingMessage?: string\n error: unknown\n}) => {\n const errorMessage = makeErrorMessage(props.error)\n const stack = props.error instanceof Error ? props.error.stack : null\n const theme = useTheme()\n\n return (\n <Stack\n sx={{\n maxHeight: \"100%\",\n maxWidth: \"min(100%, 800px)\",\n padding: 2,\n overflow: \"auto\",\n color: theme.palette.error.main,\n \"& pre\": {\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n paddingBottom: \"3rem\",\n },\n }}\n >\n {(props.loadingMessage\n ? `Error while ${lowerFirst(capitalize(props.loadingMessage))} - `\n : \"\") + errorMessage}\n <br />\n {stack && <pre>{stack}</pre>}\n </Stack>\n )\n}\n"],"names":["tryStringifyJson","json","assertUnreachable","x","msg","makeErrorMessage","err","AxiosError","_a","_b","_c","_d","LoadingCover","props","softTimeout","showSlowLoadingMessage","setShowSlowLoadingMessage","useState","theme","useTheme","useEffect","timeout","jsx","Stack","LoadingErrorMessage","jsxs","Fragment","CircularProgress","errorMessage","stack","lowerFirst","capitalize"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- "use strict";const t=require("./externalizeComponent-CkVWk2F_.cjs"),o=require("@mui/material"),l=require("lodash-es"),a=require("react"),c=require("axios");function m(e){try{return JSON.stringify(e)}catch{return}}function g(e,r){throw new Error(r+` ${JSON.stringify(e)}`)}function d(e){var r,s,n,i;return e instanceof c.AxiosError&&e.code==="ERR_NETWORK"?"Failed to connect to the server. Please check your internet connection.":e instanceof c.AxiosError&&e.response?`${(r=e.response)==null?void 0:r.status} ${(s=e.response)==null?void 0:s.statusText} from ${(n=e.response)==null?void 0:n.config.url}: ${JSON.stringify((i=e.response)==null?void 0:i.data)}`:e instanceof Error?e.message:`Unexpected error: ${m(e)||e}`}const h=e=>{const r=e.softTimeout||3e3,[s,n]=a.useState(!1),i=o.useTheme();return a.useEffect(()=>{const x=setTimeout(()=>{n(!0)},r);return()=>clearTimeout(x)}),t.jsxRuntimeExports.jsx(o.Stack,{width:"100%",height:"100%",alignItems:"center",justifyContent:"center",sx:{color:i.palette.text.primary},children:e.error?t.jsxRuntimeExports.jsx(u,{loadingMessage:e.message,error:e.error}):t.jsxRuntimeExports.jsxs(t.jsxRuntimeExports.Fragment,{children:[t.jsxRuntimeExports.jsx(o.CircularProgress,{sx:{marginBottom:"24px"}}),!!e.message&&t.jsxRuntimeExports.jsx("div",{children:e.message}),t.jsxRuntimeExports.jsx(o.Stack,{sx:{visibility:s?"visible":"hidden",marginTop:"1rem",color:i.palette.text.secondary},children:"This is taking longer than expected..."})]})})},u=e=>{const r=d(e.error),s=e.error instanceof Error?e.error.stack:null,n=o.useTheme();return t.jsxRuntimeExports.jsxs(o.Stack,{sx:{maxHeight:"100%",maxWidth:"min(100%, 800px)",padding:2,overflow:"auto",color:n.palette.error.main,"& pre":{whiteSpace:"pre-wrap",wordBreak:"break-word",paddingBottom:"3rem"}},children:[(e.loadingMessage?`Error while ${l.lowerFirst(o.capitalize(e.loadingMessage))} - `:"")+r,t.jsxRuntimeExports.jsx("br",{}),s&&t.jsxRuntimeExports.jsx("pre",{children:s})]})};exports.LoadingCover=h;exports.LoadingErrorMessage=u;exports.assertUnreachable=g;
2
- //# sourceMappingURL=LoadingCover-CukpS_aj.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LoadingCover-CukpS_aj.cjs","sources":["../src/components/utils/converters.ts","../src/components/utils/errorHandling.ts","../src/components/LoadingCover.tsx"],"sourcesContent":["export function radiansToDegree(radians: number): number {\n return radians * (180 / Math.PI)\n}\n\nexport function degreesToRadians(degrees: number): number {\n return degrees * (Math.PI / 180)\n}\n\nexport function tryParseJson(json: unknown): any {\n try {\n return JSON.parse(json as string)\n } catch {\n return undefined\n }\n}\n\nexport function tryStringifyJson(json: unknown): string | undefined {\n try {\n return JSON.stringify(json)\n } catch {\n return undefined\n }\n}\n","import { AxiosError } from \"axios\"\nimport { tryStringifyJson } from \"./converters\"\n\n// Please note: These helper functions also exist in nova.js\n// (with slightly different formatting), and will be unified\n// at some point in the future.\n\nexport function delay(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function makeShortErrorMessage(err: unknown) {\n if (err instanceof AxiosError && err.code === \"ERR_NETWORK\") {\n return \"Failed to connect to the server. Please check your internet connection.\"\n } else if (err instanceof AxiosError && err.response) {\n return `${err.response?.status} ${err.response?.statusText}: ${JSON.stringify(err.response?.data)}`\n } else if (err instanceof Error) {\n return err.message\n } else {\n return `Unexpected error: ${err}`\n }\n}\n\nexport function assertUnreachable(x: never, msg: string): never {\n throw new Error(msg + ` ${JSON.stringify(x)}`)\n}\n\nexport function makeErrorMessage(err: unknown) {\n if (err instanceof AxiosError && err.code === \"ERR_NETWORK\") {\n return \"Failed to connect to the server. Please check your internet connection.\"\n } else if (err instanceof AxiosError && err.response) {\n return `${err.response?.status} ${err.response?.statusText} from ${err.response?.config.url}: ${JSON.stringify(err.response?.data)}`\n } else if (err instanceof Error) {\n return err.message\n } else {\n return `Unexpected error: ${tryStringifyJson(err) || err}`\n }\n}\n","import { capitalize, CircularProgress, Stack, useTheme } from \"@mui/material\"\nimport { lowerFirst } from \"lodash-es\"\nimport { useEffect, useState } from \"react\"\nimport { makeErrorMessage } from \"./utils/errorHandling\"\n\nexport const LoadingCover = (props: {\n message?: string\n error?: unknown\n softTimeout?: number\n}) => {\n const softTimeout = props.softTimeout || 3000\n\n const [showSlowLoadingMessage, setShowSlowLoadingMessage] = useState(false)\n const theme = useTheme()\n\n useEffect(() => {\n const timeout = setTimeout(() => {\n setShowSlowLoadingMessage(true)\n }, softTimeout)\n\n return () => clearTimeout(timeout)\n })\n\n return (\n <Stack\n width=\"100%\"\n height=\"100%\"\n alignItems=\"center\"\n justifyContent=\"center\"\n sx={{ color: theme.palette.text.primary }}\n >\n {props.error ? (\n <LoadingErrorMessage\n loadingMessage={props.message}\n error={props.error}\n />\n ) : (\n <>\n <CircularProgress sx={{ marginBottom: \"24px\" }} />\n {!!props.message && <div>{props.message}</div>}\n <Stack\n sx={{\n visibility: showSlowLoadingMessage ? \"visible\" : \"hidden\",\n marginTop: \"1rem\",\n color: theme.palette.text.secondary,\n }}\n >\n {\"This is taking longer than expected...\"}\n </Stack>\n </>\n )}\n </Stack>\n )\n}\n\nexport const LoadingErrorMessage = (props: {\n loadingMessage?: string\n error: unknown\n}) => {\n const errorMessage = makeErrorMessage(props.error)\n const stack = props.error instanceof Error ? props.error.stack : null\n const theme = useTheme()\n\n return (\n <Stack\n sx={{\n maxHeight: \"100%\",\n maxWidth: \"min(100%, 800px)\",\n padding: 2,\n overflow: \"auto\",\n color: theme.palette.error.main,\n \"& pre\": {\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n paddingBottom: \"3rem\",\n },\n }}\n >\n {(props.loadingMessage\n ? `Error while ${lowerFirst(capitalize(props.loadingMessage))} - `\n : \"\") + errorMessage}\n <br />\n {stack && <pre>{stack}</pre>}\n </Stack>\n )\n}\n"],"names":["tryStringifyJson","json","assertUnreachable","x","msg","makeErrorMessage","err","AxiosError","_a","_b","_c","_d","LoadingCover","props","softTimeout","showSlowLoadingMessage","setShowSlowLoadingMessage","useState","theme","useTheme","useEffect","timeout","jsx","Stack","LoadingErrorMessage","jsxs","Fragment","CircularProgress","errorMessage","stack","lowerFirst","capitalize"],"mappings":"4JAgBO,SAASA,EAAiBC,EAAmC,CAClE,GAAI,CACF,OAAO,KAAK,UAAUA,CAAI,CAC5B,MAAQ,CACN,MACF,CACF,CCCO,SAASC,EAAkBC,EAAUC,EAAoB,CAC9D,MAAM,IAAI,MAAMA,EAAM,IAAI,KAAK,UAAUD,CAAC,CAAC,EAAE,CAC/C,CAEO,SAASE,EAAiBC,EAAc,aAC7C,OAAIA,aAAeC,EAAAA,YAAcD,EAAI,OAAS,cACrC,0EACEA,aAAeC,cAAcD,EAAI,SACnC,IAAGE,EAAAF,EAAI,WAAJ,YAAAE,EAAc,MAAM,KAAIC,EAAAH,EAAI,WAAJ,YAAAG,EAAc,UAAU,UAASC,EAAAJ,EAAI,WAAJ,YAAAI,EAAc,OAAO,GAAG,KAAK,KAAK,WAAUC,EAAAL,EAAI,WAAJ,YAAAK,EAAc,IAAI,CAAC,GACzHL,aAAe,MACjBA,EAAI,QAEJ,qBAAqBN,EAAiBM,CAAG,GAAKA,CAAG,EAE5D,CChCO,MAAMM,EAAgBC,GAIvB,CACJ,MAAMC,EAAcD,EAAM,aAAe,IAEnC,CAACE,EAAwBC,CAAyB,EAAIC,EAAAA,SAAS,EAAK,EACpEC,EAAQC,EAAAA,SAAA,EAEdC,OAAAA,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAU,WAAW,IAAM,CAC/BL,EAA0B,EAAI,CAChC,EAAGF,CAAW,EAEd,MAAO,IAAM,aAAaO,CAAO,CACnC,CAAC,EAGCC,EAAAA,kBAAAA,IAACC,EAAAA,MAAA,CACC,MAAM,OACN,OAAO,OACP,WAAW,SACX,eAAe,SACf,GAAI,CAAE,MAAOL,EAAM,QAAQ,KAAK,OAAA,EAE/B,WAAM,MACLI,EAAAA,kBAAAA,IAACE,EAAA,CACC,eAAgBX,EAAM,QACtB,MAAOA,EAAM,KAAA,CAAA,EAGfY,EAAAA,kBAAAA,KAAAC,6BAAA,CACE,SAAA,CAAAJ,EAAAA,kBAAAA,IAACK,EAAAA,iBAAA,CAAiB,GAAI,CAAE,aAAc,QAAU,EAC/C,CAAC,CAACd,EAAM,SAAWS,EAAAA,kBAAAA,IAAC,MAAA,CAAK,WAAM,QAAQ,EACxCA,EAAAA,kBAAAA,IAACC,EAAAA,MAAA,CACC,GAAI,CACF,WAAYR,EAAyB,UAAY,SACjD,UAAW,OACX,MAAOG,EAAM,QAAQ,KAAK,SAAA,EAG3B,SAAA,wCAAA,CAAA,CACH,CAAA,CACF,CAAA,CAAA,CAIR,EAEaM,EAAuBX,GAG9B,CACJ,MAAMe,EAAevB,EAAiBQ,EAAM,KAAK,EAC3CgB,EAAQhB,EAAM,iBAAiB,MAAQA,EAAM,MAAM,MAAQ,KAC3DK,EAAQC,EAAAA,SAAA,EAEd,OACEM,EAAAA,kBAAAA,KAACF,EAAAA,MAAA,CACC,GAAI,CACF,UAAW,OACX,SAAU,mBACV,QAAS,EACT,SAAU,OACV,MAAOL,EAAM,QAAQ,MAAM,KAC3B,QAAS,CACP,WAAY,WACZ,UAAW,aACX,cAAe,MAAA,CACjB,EAGA,SAAA,EAAAL,EAAM,eACJ,eAAeiB,EAAAA,WAAWC,EAAAA,WAAWlB,EAAM,cAAc,CAAC,CAAC,MAC3D,IAAMe,0BACT,KAAA,EAAG,EACHC,GAASP,EAAAA,kBAAAA,IAAC,MAAA,CAAK,SAAAO,CAAA,CAAM,CAAA,CAAA,CAAA,CAG5B"}