@wandelbots/wandelbots-js-react-components 3.7.2 → 3.7.4-pr.feat-add-linear-axis-support.509.b65ac1c

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 (94) hide show
  1. package/README.md +46 -0
  2. package/dist/3d.cjs.js +1 -1
  3. package/dist/3d.d.ts +2 -1
  4. package/dist/3d.d.ts.map +1 -1
  5. package/dist/3d.es.js +8 -7
  6. package/dist/{LoadingCover-Dr9hDTku.js → LoadingCover-6gWr11KP.js} +11 -10
  7. package/dist/{LoadingCover-Dr9hDTku.js.map → LoadingCover-6gWr11KP.js.map} +1 -1
  8. package/dist/LoadingCover-CukpS_aj.cjs +2 -0
  9. package/dist/{LoadingCover-r2yhJZF9.cjs.map → LoadingCover-CukpS_aj.cjs.map} +1 -1
  10. package/dist/SupportedLinearAxis-Cc5zohcs.cjs +2 -0
  11. package/dist/SupportedLinearAxis-Cc5zohcs.cjs.map +1 -0
  12. package/dist/SupportedLinearAxis-DAK0IyqZ.js +1228 -0
  13. package/dist/SupportedLinearAxis-DAK0IyqZ.js.map +1 -0
  14. package/dist/{WandelscriptEditor-DnJvITTA.js → WandelscriptEditor-7eN-Yw7m.js} +3 -3
  15. package/dist/{WandelscriptEditor-DnJvITTA.js.map → WandelscriptEditor-7eN-Yw7m.js.map} +1 -1
  16. package/dist/WandelscriptEditor-D6_vS5Uk.cjs +2 -0
  17. package/dist/{WandelscriptEditor-Dj7TBCkF.cjs.map → WandelscriptEditor-D6_vS5Uk.cjs.map} +1 -1
  18. package/dist/auth0-spa-js.production.esm-D_IhPirK.cjs +5 -0
  19. package/dist/auth0-spa-js.production.esm-D_IhPirK.cjs.map +1 -0
  20. package/dist/auth0-spa-js.production.esm-mvPojIrB.js +4043 -0
  21. package/dist/auth0-spa-js.production.esm-mvPojIrB.js.map +1 -0
  22. package/dist/components/RobotCard.d.ts +1 -1
  23. package/dist/components/RobotCard.d.ts.map +1 -1
  24. package/dist/components/robots/DHLinearAxis.d.ts +3 -0
  25. package/dist/components/robots/DHLinearAxis.d.ts.map +1 -0
  26. package/dist/components/robots/GenericRobot.d.ts +2 -2
  27. package/dist/components/robots/GenericRobot.d.ts.map +1 -1
  28. package/dist/components/robots/LinearAxis.d.ts +25 -0
  29. package/dist/components/robots/LinearAxis.d.ts.map +1 -0
  30. package/dist/components/robots/LinearAxisAnimator.d.ts +12 -0
  31. package/dist/components/robots/LinearAxisAnimator.d.ts.map +1 -0
  32. package/dist/components/robots/Robot.d.ts +3 -1
  33. package/dist/components/robots/Robot.d.ts.map +1 -1
  34. package/dist/components/robots/SupportedLinearAxis.d.ts +18 -0
  35. package/dist/components/robots/SupportedLinearAxis.d.ts.map +1 -0
  36. package/dist/components/robots/SupportedRobot.d.ts +1 -1
  37. package/dist/components/robots/SupportedRobot.d.ts.map +1 -1
  38. package/dist/components/robots/robotModelLogic.d.ts +11 -1
  39. package/dist/components/robots/robotModelLogic.d.ts.map +1 -1
  40. package/dist/core.cjs.js +1 -1
  41. package/dist/core.es.js +4 -4
  42. package/dist/externalizeComponent-CkVWk2F_.cjs +24 -0
  43. package/dist/externalizeComponent-CkVWk2F_.cjs.map +1 -0
  44. package/dist/externalizeComponent-Dc3fViZA.js +489 -0
  45. package/dist/externalizeComponent-Dc3fViZA.js.map +1 -0
  46. package/dist/index.cjs.js +1 -1
  47. package/dist/index.es.js +58 -57
  48. package/dist/interpolation-DZhBKo-u.cjs +20 -0
  49. package/dist/interpolation-DZhBKo-u.cjs.map +1 -0
  50. package/dist/interpolation-baUmFLkh.js +6924 -0
  51. package/dist/interpolation-baUmFLkh.js.map +1 -0
  52. package/dist/lib/JoggerConnection.d.ts.map +1 -1
  53. package/dist/{theming-DxiD0Q3m.js → theming-BTlS2afw.js} +4951 -6394
  54. package/dist/theming-BTlS2afw.js.map +1 -0
  55. package/dist/theming-DPoEjzxv.cjs +115 -0
  56. package/dist/theming-DPoEjzxv.cjs.map +1 -0
  57. package/dist/wandelscript.cjs.js +1 -1
  58. package/dist/wandelscript.es.js +1 -1
  59. package/package.json +16 -6
  60. package/src/3d.ts +3 -2
  61. package/src/components/RobotCard.tsx +1 -1
  62. package/src/components/robots/DHLinearAxis.tsx +128 -0
  63. package/src/components/robots/GenericRobot.tsx +97 -36
  64. package/src/components/robots/LinearAxis.tsx +73 -0
  65. package/src/components/robots/LinearAxisAnimator.tsx +115 -0
  66. package/src/components/robots/Robot.tsx +3 -1
  67. package/src/components/robots/RobotAnimator.test.tsx +1 -1
  68. package/src/components/robots/SupportedLinearAxis.tsx +99 -0
  69. package/src/components/robots/SupportedRobot.tsx +11 -3
  70. package/src/components/robots/robotModelLogic.ts +75 -6
  71. package/src/env.d.ts +3 -0
  72. package/src/lib/JoggerConnection.ts +10 -10
  73. package/src/lib/MotionStreamConnection.ts +1 -1
  74. package/dist/LoadingCover-r2yhJZF9.cjs +0 -2
  75. package/dist/WandelscriptEditor-Dj7TBCkF.cjs +0 -2
  76. package/dist/auth0-spa-js.production.esm-DL9f1uDJ.js +0 -1438
  77. package/dist/auth0-spa-js.production.esm-DL9f1uDJ.js.map +0 -1
  78. package/dist/auth0-spa-js.production.esm-DTiWXa87.cjs +0 -5
  79. package/dist/auth0-spa-js.production.esm-DTiWXa87.cjs.map +0 -1
  80. package/dist/index-CAib4NKw.js +0 -2261
  81. package/dist/index-CAib4NKw.js.map +0 -1
  82. package/dist/index-CqMZL0FV.cjs +0 -2
  83. package/dist/index-CqMZL0FV.cjs.map +0 -1
  84. package/dist/index-CxasuX80.js +0 -5212
  85. package/dist/index-CxasuX80.js.map +0 -1
  86. package/dist/index-DxwppshT.cjs +0 -29
  87. package/dist/index-DxwppshT.cjs.map +0 -1
  88. package/dist/manufacturerHomePositions-BW0KbWeg.js +0 -980
  89. package/dist/manufacturerHomePositions-BW0KbWeg.js.map +0 -1
  90. package/dist/manufacturerHomePositions-r9dAEtsx.cjs +0 -2
  91. package/dist/manufacturerHomePositions-r9dAEtsx.cjs.map +0 -1
  92. package/dist/theming-CKlFOjJ_.cjs +0 -133
  93. package/dist/theming-CKlFOjJ_.cjs.map +0 -1
  94. package/dist/theming-DxiD0Q3m.js.map +0 -1
@@ -0,0 +1,99 @@
1
+ import type { ThreeElements } from "@react-three/fiber"
2
+ import type { DHParameter, MotionGroupState } from "@wandelbots/nova-js/v2"
3
+ import { Suspense, useCallback, useEffect, useState } from "react"
4
+ import { ErrorBoundary } from "react-error-boundary"
5
+ import type * as THREE from "three"
6
+ import { externalizeComponent } from "../../externalizeComponent"
7
+ import ConsoleFilter from "../ConsoleFilter"
8
+ import { DHLinearAxis } from "./DHLinearAxis"
9
+ import { GenericRobot } from "./GenericRobot"
10
+ import LinearAxisAnimator from "./LinearAxisAnimator"
11
+ import { applyGhostStyle, removeGhostStyle } from "./ghostStyle"
12
+ import { defaultGetModel } from "./robotModelLogic"
13
+
14
+ export type DHLinearAxisProps = {
15
+ rapidlyChangingMotionState: MotionGroupState
16
+ dhParameters: Array<DHParameter>
17
+ } & ThreeElements["group"]
18
+
19
+ export type SupportedLinearAxisProps = {
20
+ rapidlyChangingMotionState: MotionGroupState
21
+ modelFromController: string
22
+ dhParameters: DHParameter[]
23
+ flangeRef?: React.Ref<THREE.Group>
24
+ getModel?: (modelFromController: string) => Promise<string> | undefined
25
+ postModelRender?: () => void
26
+ transparentColor?: string
27
+ } & ThreeElements["group"]
28
+
29
+ export const SupportedLinearAxis = externalizeComponent(
30
+ ({
31
+ rapidlyChangingMotionState,
32
+ modelFromController,
33
+ dhParameters,
34
+ getModel = defaultGetModel,
35
+ flangeRef,
36
+ postModelRender,
37
+ transparentColor,
38
+ ...props
39
+ }: SupportedLinearAxisProps) => {
40
+ const [robotGroup, setRobotGroup] = useState<THREE.Group | null>(null)
41
+
42
+ const setRobotRef = useCallback((instance: THREE.Group | null) => {
43
+ setRobotGroup(instance)
44
+ }, [])
45
+
46
+ useEffect(() => {
47
+ if (!robotGroup) return
48
+
49
+ if (transparentColor) {
50
+ applyGhostStyle(robotGroup, transparentColor)
51
+ } else {
52
+ removeGhostStyle(robotGroup)
53
+ }
54
+ }, [robotGroup, transparentColor])
55
+
56
+ const dhLinearAxis = (
57
+ <DHLinearAxis
58
+ rapidlyChangingMotionState={rapidlyChangingMotionState}
59
+ dhParameters={dhParameters}
60
+ {...props}
61
+ />
62
+ )
63
+
64
+ return (
65
+ <ErrorBoundary
66
+ fallback={dhLinearAxis}
67
+ onError={(err) => {
68
+ // Missing model; show the fallback for now
69
+ console.warn(err)
70
+ }}
71
+ >
72
+ <Suspense fallback={dhLinearAxis}>
73
+ <group ref={setRobotRef}>
74
+ <LinearAxisAnimator
75
+ rapidlyChangingMotionState={rapidlyChangingMotionState}
76
+ dhParameters={dhParameters}
77
+ >
78
+ <GenericRobot
79
+ modelURL={(() => {
80
+ const result = getModel(modelFromController)
81
+ if (!result) {
82
+ const mockBlob = new Blob([], { type: 'model/gltf-binary' })
83
+ const mockFile = new File([mockBlob], `${modelFromController}.glb`, { type: 'model/gltf-binary' })
84
+ return Promise.resolve(URL.createObjectURL(mockFile))
85
+ }
86
+ return result
87
+ })()}
88
+ postModelRender={postModelRender}
89
+ flangeRef={flangeRef}
90
+ {...props}
91
+ />
92
+ </LinearAxisAnimator>
93
+ </group>
94
+ </Suspense>
95
+ <ConsoleFilter />
96
+ </ErrorBoundary>
97
+ )
98
+ },
99
+ )
@@ -22,7 +22,7 @@ export type SupportedRobotProps = {
22
22
  modelFromController: string
23
23
  dhParameters: DHParameter[]
24
24
  flangeRef?: React.Ref<THREE.Group>
25
- getModel?: (modelFromController: string) => string
25
+ getModel?: (modelFromController: string) => Promise<string> | undefined
26
26
  postModelRender?: () => void
27
27
  transparentColor?: string
28
28
  } & ThreeElements["group"]
@@ -67,7 +67,7 @@ export const SupportedRobot = externalizeComponent(
67
67
  fallback={dhrobot}
68
68
  onError={(err) => {
69
69
  // Missing model; show the fallback for now
70
- console.error(err)
70
+ console.warn(err)
71
71
  }}
72
72
  >
73
73
  <Suspense fallback={dhrobot}>
@@ -77,7 +77,15 @@ export const SupportedRobot = externalizeComponent(
77
77
  dhParameters={dhParameters}
78
78
  >
79
79
  <GenericRobot
80
- modelURL={getModel(modelFromController)}
80
+ modelURL={(() => {
81
+ const result = getModel(modelFromController)
82
+ if (!result) {
83
+ const mockBlob = new Blob([], { type: 'model/gltf-binary' })
84
+ const mockFile = new File([mockBlob], `${modelFromController}.glb`, { type: 'model/gltf-binary' })
85
+ return Promise.resolve(URL.createObjectURL(mockFile))
86
+ }
87
+ return result
88
+ })()}
81
89
  postModelRender={postModelRender}
82
90
  flangeRef={flangeRef}
83
91
  {...props}
@@ -1,13 +1,82 @@
1
+ import { NovaClient } from "@wandelbots/nova-js/v2"
1
2
  import type { Object3D } from "three"
2
3
  import type { GLTF } from "three-stdlib"
3
- import { version } from "../../../package.json"
4
4
 
5
- export function defaultGetModel(modelFromController: string): string {
6
- let useVersion = version
7
- if (version.startsWith("0.")) {
8
- useVersion = ""
5
+ const modelCache = new Map<string, Promise<string>>()
6
+
7
+ /**
8
+ * Revoke a cached model's object URL to prevent memory leaks.
9
+ * Call this when a component unmounts or no longer needs the model.
10
+ */
11
+ export async function revokeModelUrl(modelFromController: string): Promise<void> {
12
+ const urlPromise = modelCache.get(modelFromController)
13
+ if (!urlPromise) return
14
+
15
+ try {
16
+ const url = await urlPromise
17
+ URL.revokeObjectURL(url)
18
+ } catch (e) {
19
+ // Ignore errors - URL may already be revoked
20
+ }
21
+ modelCache.delete(modelFromController)
22
+ }
23
+
24
+ /**
25
+ * Revoke all cached model object URLs and clear the cache.
26
+ * Useful for cleanup on app teardown.
27
+ */
28
+ export async function revokeAllModelUrls(): Promise<void> {
29
+ const entries = Array.from(modelCache.entries())
30
+ await Promise.allSettled(
31
+ entries.map(async ([key, urlPromise]) => {
32
+ try {
33
+ const url = await urlPromise
34
+ URL.revokeObjectURL(url)
35
+ } catch (e) {
36
+ // Ignore errors
37
+ }
38
+ })
39
+ )
40
+ modelCache.clear()
41
+ }
42
+
43
+ export async function defaultGetModel(modelFromController: string): Promise<string> {
44
+ // Check cache first
45
+ if (modelCache.has(modelFromController)) {
46
+ return modelCache.get(modelFromController)!
9
47
  }
10
- return `https://cdn.jsdelivr.net/gh/wandelbotsgmbh/wandelbots-js-react-components${useVersion ? `@${useVersion}` : ""}/public/models/${modelFromController}.glb`
48
+
49
+ // Create the promise and cache it immediately to prevent duplicate calls
50
+ const modelPromise = (async () => {
51
+ const instanceUrl = import.meta.env.WANDELAPI_BASE_URL
52
+ const nova = new NovaClient({ instanceUrl })
53
+
54
+ // Configure axios to handle binary responses for GLB files
55
+ const apiInstance = nova.api.motionGroupModels as any
56
+ if (apiInstance.axios?.interceptors) {
57
+ apiInstance.axios.interceptors.request.use((config: any) => {
58
+ if (config.url?.includes('/glb')) {
59
+ config.responseType = 'blob'
60
+ }
61
+ return config
62
+ })
63
+ }
64
+
65
+ try {
66
+ const file = await nova.api.motionGroupModels.getMotionGroupGlbModel(modelFromController)
67
+
68
+ // Create object URL from the file and return it
69
+ const url = URL.createObjectURL(file)
70
+ return url
71
+ } catch (error) {
72
+ console.error("Failed to fetch model:", error)
73
+ throw error
74
+ }
75
+ })()
76
+
77
+ // Cache the promise
78
+ modelCache.set(modelFromController, modelPromise)
79
+ return modelPromise
11
80
  }
12
81
 
13
82
  /**
package/src/env.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ // Ensure ImportMeta.env types from Vite are available to TypeScript.
@@ -390,14 +390,14 @@ export class JoggerConnection {
390
390
  axis: "x" | "y" | "z"
391
391
  direction: "-" | "+"
392
392
  motion:
393
- | {
394
- type: "rotate"
395
- distanceRads: number
396
- }
397
- | {
398
- type: "translate"
399
- distanceMm: number
400
- }
393
+ | {
394
+ type: "rotate"
395
+ distanceRads: number
396
+ }
397
+ | {
398
+ type: "translate"
399
+ distanceMm: number
400
+ }
401
401
  }) {
402
402
  const commands: MotionCommand[] = []
403
403
 
@@ -559,8 +559,8 @@ export class JoggerConnection {
559
559
  } else {
560
560
  throw new Error(
561
561
  result?.add_trajectory_error?.message ||
562
- result?.message ||
563
- "Failed to execute trajectory, unknown error",
562
+ result?.message ||
563
+ "Failed to execute trajectory, unknown error",
564
564
  )
565
565
  }
566
566
  }
@@ -31,7 +31,7 @@ export class MotionStreamConnection {
31
31
  const controller =
32
32
  await nova.api.controller.getCurrentRobotControllerState(controllerId)
33
33
  const motionGroup = controller?.motion_groups.find(
34
- (mg) => mg.motion_group === motionGroupId,
34
+ (mg: MotionGroupState) => mg.motion_group === motionGroupId,
35
35
  )
36
36
  if (!controller || !motionGroup) {
37
37
  throw new Error(
@@ -1,2 +0,0 @@
1
- "use strict";const t=require("./index-DxwppshT.cjs"),n=require("@mui/material"),x=require("lodash-es"),a=require("react");function l(e){try{return JSON.stringify(e)}catch{return}}function m(e,s){throw new Error(s+` ${JSON.stringify(e)}`)}function g(e){var s,r,o,i;return e instanceof t.AxiosError&&e.code==="ERR_NETWORK"?"Failed to connect to the server. Please check your internet connection.":e instanceof t.AxiosError&&e.response?`${(s=e.response)==null?void 0:s.status} ${(r=e.response)==null?void 0:r.statusText} from ${(o=e.response)==null?void 0:o.config.url}: ${JSON.stringify((i=e.response)==null?void 0:i.data)}`:e instanceof Error?e.message:`Unexpected error: ${l(e)||e}`}const d=e=>{const s=e.softTimeout||3e3,[r,o]=a.useState(!1),i=n.useTheme();return a.useEffect(()=>{const u=setTimeout(()=>{o(!0)},s);return()=>clearTimeout(u)}),t.jsxRuntimeExports.jsx(n.Stack,{width:"100%",height:"100%",alignItems:"center",justifyContent:"center",sx:{color:i.palette.text.primary},children:e.error?t.jsxRuntimeExports.jsx(c,{loadingMessage:e.message,error:e.error}):t.jsxRuntimeExports.jsxs(t.jsxRuntimeExports.Fragment,{children:[t.jsxRuntimeExports.jsx(n.CircularProgress,{sx:{marginBottom:"24px"}}),!!e.message&&t.jsxRuntimeExports.jsx("div",{children:e.message}),t.jsxRuntimeExports.jsx(n.Stack,{sx:{visibility:r?"visible":"hidden",marginTop:"1rem",color:i.palette.text.secondary},children:"This is taking longer than expected..."})]})})},c=e=>{const s=g(e.error),r=e.error instanceof Error?e.error.stack:null,o=n.useTheme();return t.jsxRuntimeExports.jsxs(n.Stack,{sx:{maxHeight:"100%",maxWidth:"min(100%, 800px)",padding:2,overflow:"auto",color:o.palette.error.main,"& pre":{whiteSpace:"pre-wrap",wordBreak:"break-word",paddingBottom:"3rem"}},children:[(e.loadingMessage?`Error while ${x.lowerFirst(n.capitalize(e.loadingMessage))} - `:"")+s,t.jsxRuntimeExports.jsx("br",{}),r&&t.jsxRuntimeExports.jsx("pre",{children:r})]})};exports.LoadingCover=d;exports.LoadingErrorMessage=c;exports.assertUnreachable=m;
2
- //# sourceMappingURL=LoadingCover-r2yhJZF9.cjs.map
@@ -1,2 +0,0 @@
1
- "use strict";var w=Object.create;var p=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,b=Object.prototype.hasOwnProperty;var v=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of f(t))!b.call(e,i)&&i!==n&&p(e,i,{get:()=>t[i],enumerable:!(s=k(t,i))||s.enumerable});return e};var c=(e,t,n)=>(n=e!=null?w(x(e)):{},v(t||!e||!e.__esModule?p(n,"default",{value:e,enumerable:!0}):n,e));const r=require("./index-DxwppshT.cjs"),u=require("react"),T=require("@mui/material"),y=require("./LoadingCover-r2yhJZF9.cjs"),C={$schema:"https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",name:"wandelscript",patterns:[{include:"#keywords"},{include:"#strings"},{include:"#comments"},{include:"#functions"}],repository:{keywords:{patterns:[{name:"keyword.control.flow.wandelscript",match:"\\b(move|via|to|interrupt|def|False|True|for|if|else|elif|while|return|switch|activate|deactivate|print|and|or|not)\\b"}]},strings:{name:"string.quoted.double.wandelscript",begin:'"',end:'"',patterns:[{name:"constant.character.escape.wandelscript",match:"\\\\."}]},comments:{patterns:[{begin:"#",beginCaptures:{0:{name:"punctuation.definition.comment.wandelscript"}},end:"$",name:"comment.line.number-sign.wandelscript"}]},functions:{patterns:[{match:"[a-zA-Z_-]+\\(",name:"entity.name.function.wandelscript"}]}},scopeName:"source.wandelscript"},E=u.lazy(()=>import("@monaco-editor/react"));let l=null;async function S(){if(!l){const[{createHighlighter:e},{shikiToMonaco:t}]=await Promise.all([import("shiki"),import("@shikijs/monaco")]);l={shiki:await e({langs:[C],themes:["dark-plus","light-plus"]}),shikiToMonaco:t}}return l}const j=r.externalizeComponent(e=>{const t=T.useTheme(),[n,s]=u.useState("dark-plus"),i=t.palette.mode==="dark"?"dark-plus":"light-plus";async function g(a){var m,d;a.languages.register({id:"wandelscript"}),a.languages.setLanguageConfiguration("wandelscript",{comments:{lineComment:"#"},brackets:[["(",")"],["[","]"]],autoClosingPairs:[{open:"[",close:"]"},{open:"(",close:")"}],surroundingPairs:[{open:"[",close:"]"},{open:"(",close:")"}]});const{shiki:o,shikiToMonaco:h}=await S();h(o,a),a.editor.defineTheme(i,((d=(m=t.componentsExt)==null?void 0:m.WandelscriptEditor)==null?void 0:d.monacoTheme)??{base:t.palette.mode==="dark"?"vs-dark":"vs",inherit:!0,rules:[],colors:{}}),e.monacoSetup&&e.monacoSetup(a),s(i)}return r.jsxRuntimeExports.jsx(u.Suspense,{fallback:r.jsxRuntimeExports.jsx(y.LoadingCover,{}),children:r.jsxRuntimeExports.jsx(E,{value:e.code,onMount:(a,o)=>{g(o)},onChange:e.onChange,defaultLanguage:"wandelscript",theme:n,options:{minimap:{enabled:!1},wordWrap:"on",automaticLayout:!0,...e.monacoOptions}})})});exports.WandelscriptEditor=j;
2
- //# sourceMappingURL=WandelscriptEditor-Dj7TBCkF.cjs.map