@viamrobotics/motion-tools 0.19.2 → 1.0.3

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 (150) hide show
  1. package/README.md +56 -26
  2. package/dist/FrameConfigUpdater.svelte.d.ts +11 -17
  3. package/dist/FrameConfigUpdater.svelte.js +109 -109
  4. package/dist/WorldObject.svelte.js +2 -15
  5. package/dist/common/v1/common_pb.d.ts +950 -0
  6. package/dist/common/v1/common_pb.js +1399 -0
  7. package/dist/components/App.svelte +38 -22
  8. package/dist/components/App.svelte.d.ts +1 -0
  9. package/dist/components/BatchedArrows.svelte +102 -0
  10. package/dist/components/BatchedArrows.svelte.d.ts +3 -0
  11. package/dist/components/CameraControls.svelte +2 -3
  12. package/dist/components/Details.svelte +364 -365
  13. package/dist/components/Entities.svelte +80 -0
  14. package/dist/components/{WorldObjects.svelte.d.ts → Entities.svelte.d.ts} +3 -3
  15. package/dist/components/FileDrop/FileDrop.svelte +96 -0
  16. package/dist/components/FileDrop/FileDrop.svelte.d.ts +4 -0
  17. package/dist/components/FileDrop/file-dropper.d.ts +36 -0
  18. package/dist/components/FileDrop/file-dropper.js +6 -0
  19. package/dist/components/FileDrop/file-names.d.ts +27 -0
  20. package/dist/components/FileDrop/file-names.js +85 -0
  21. package/dist/components/FileDrop/pcd-dropper.d.ts +2 -0
  22. package/dist/components/FileDrop/pcd-dropper.js +27 -0
  23. package/dist/components/FileDrop/ply-dropper.d.ts +2 -0
  24. package/dist/components/FileDrop/ply-dropper.js +27 -0
  25. package/dist/components/FileDrop/snapshot-dropper.d.ts +2 -0
  26. package/dist/components/FileDrop/snapshot-dropper.js +96 -0
  27. package/dist/components/FileDrop/useFileDrop.svelte.d.ts +9 -0
  28. package/dist/components/FileDrop/useFileDrop.svelte.js +97 -0
  29. package/dist/components/Focus.svelte +2 -3
  30. package/dist/components/Frame.svelte +41 -22
  31. package/dist/components/Frame.svelte.d.ts +4 -6
  32. package/dist/components/GLTF.svelte +36 -0
  33. package/dist/components/GLTF.svelte.d.ts +11 -0
  34. package/dist/components/Geometry2.svelte +206 -0
  35. package/dist/components/Geometry2.svelte.d.ts +18 -0
  36. package/dist/components/KeyboardControls.svelte +3 -3
  37. package/dist/components/Line.svelte +15 -14
  38. package/dist/components/Line.svelte.d.ts +2 -2
  39. package/dist/components/LiveUpdatesBanner.svelte +51 -15
  40. package/dist/components/MeasureTool.svelte +4 -5
  41. package/dist/components/Pointcloud.svelte +27 -14
  42. package/dist/components/Pointcloud.svelte.d.ts +2 -2
  43. package/dist/components/PointerMissBox.svelte +3 -3
  44. package/dist/components/Pose.svelte +31 -6
  45. package/dist/components/Pose.svelte.d.ts +2 -2
  46. package/dist/components/Scene.svelte +7 -6
  47. package/dist/components/SceneProviders.svelte +0 -6
  48. package/dist/components/Selected.svelte +22 -16
  49. package/dist/components/StaticGeometries.svelte +51 -27
  50. package/dist/components/Tree/Tree.svelte +51 -38
  51. package/dist/components/Tree/Tree.svelte.d.ts +3 -4
  52. package/dist/components/Tree/TreeContainer.svelte +75 -40
  53. package/dist/components/Tree/Widgets.svelte +2 -5
  54. package/dist/components/Tree/buildTree.d.ts +7 -6
  55. package/dist/components/Tree/buildTree.js +22 -41
  56. package/dist/components/__tests__/__fixtures__/entity.d.ts +2 -0
  57. package/dist/components/__tests__/__fixtures__/entity.js +20 -0
  58. package/dist/components/__tests__/__fixtures__/resource.d.ts +17 -0
  59. package/dist/components/__tests__/__fixtures__/resource.js +13 -0
  60. package/dist/components/dashboard/Dashboard.svelte +5 -3
  61. package/dist/components/dashboard/Dashboard.svelte.d.ts +7 -2
  62. package/dist/components/widgets/ArmPositions.svelte +19 -7
  63. package/dist/draw/v1/drawing_pb.d.ts +341 -0
  64. package/dist/draw/v1/drawing_pb.js +417 -0
  65. package/dist/draw/v1/metadata_pb.d.ts +23 -0
  66. package/dist/draw/v1/metadata_pb.js +39 -0
  67. package/dist/draw/v1/scene_pb.d.ts +230 -0
  68. package/dist/draw/v1/scene_pb.js +298 -0
  69. package/dist/draw/v1/snapshot_pb.d.ts +42 -0
  70. package/dist/draw/v1/snapshot_pb.js +61 -0
  71. package/dist/draw/v1/transforms_pb.d.ts +23 -0
  72. package/dist/draw/v1/transforms_pb.js +39 -0
  73. package/dist/ecs/index.d.ts +4 -0
  74. package/dist/ecs/index.js +4 -0
  75. package/dist/ecs/traits.d.ts +132 -0
  76. package/dist/ecs/traits.js +85 -0
  77. package/dist/ecs/useQuery.svelte.d.ts +4 -0
  78. package/dist/ecs/useQuery.svelte.js +49 -0
  79. package/dist/ecs/useTrait.svelte.d.ts +19 -0
  80. package/dist/ecs/useTrait.svelte.js +40 -0
  81. package/dist/ecs/useWorld.d.ts +4 -0
  82. package/dist/ecs/useWorld.js +10 -0
  83. package/dist/geometry.js +6 -6
  84. package/dist/hooks/__tests__/fixtures/ResizableTestWrapper.svelte +41 -0
  85. package/dist/hooks/__tests__/fixtures/ResizableTestWrapper.svelte.d.ts +6 -0
  86. package/dist/hooks/use3DModels.svelte.js +6 -4
  87. package/dist/hooks/useDrawAPI.svelte.d.ts +0 -10
  88. package/dist/hooks/useDrawAPI.svelte.js +143 -267
  89. package/dist/hooks/useFramelessComponents.svelte.js +1 -1
  90. package/dist/hooks/useFrames.svelte.d.ts +6 -2
  91. package/dist/hooks/useFrames.svelte.js +123 -19
  92. package/dist/hooks/useGeometries.svelte.d.ts +0 -2
  93. package/dist/hooks/useGeometries.svelte.js +49 -25
  94. package/dist/hooks/useObjectEvents.svelte.d.ts +3 -2
  95. package/dist/hooks/useObjectEvents.svelte.js +11 -7
  96. package/dist/hooks/usePartConfig.svelte.d.ts +1 -1
  97. package/dist/hooks/usePartConfig.svelte.js +2 -1
  98. package/dist/hooks/usePointclouds.svelte.d.ts +0 -2
  99. package/dist/hooks/usePointclouds.svelte.js +52 -21
  100. package/dist/hooks/usePose.svelte.js +15 -7
  101. package/dist/hooks/useResizable.svelte.d.ts +12 -0
  102. package/dist/hooks/useResizable.svelte.js +45 -0
  103. package/dist/hooks/useResourceByName.svelte.js +8 -5
  104. package/dist/hooks/useSelection.svelte.d.ts +13 -23
  105. package/dist/hooks/useSelection.svelte.js +45 -65
  106. package/dist/hooks/useVisibility.svelte.d.ts +2 -1
  107. package/dist/hooks/useWeblabs.svelte.d.ts +0 -1
  108. package/dist/hooks/useWeblabs.svelte.js +0 -1
  109. package/dist/hooks/useWorldState.svelte.d.ts +9 -0
  110. package/dist/hooks/useWorldState.svelte.js +158 -107
  111. package/dist/lib.d.ts +1 -0
  112. package/dist/lib.js +2 -0
  113. package/dist/three/BatchedArrow.d.ts +2 -3
  114. package/dist/three/BatchedArrow.js +3 -11
  115. package/dist/three/CapsuleGeometry.d.ts +1 -1
  116. package/dist/three/CapsuleGeometry.js +3 -1
  117. package/dist/transform.js +0 -15
  118. package/package.json +13 -7
  119. package/dist/components/FileDrop.svelte +0 -158
  120. package/dist/components/FileDrop.svelte.d.ts +0 -3
  121. package/dist/components/WorldObject.svelte +0 -28
  122. package/dist/components/WorldObject.svelte.d.ts +0 -11
  123. package/dist/components/WorldObjects.svelte +0 -159
  124. package/dist/components/WorldState.svelte +0 -92
  125. package/dist/components/WorldState.svelte.d.ts +0 -7
  126. package/dist/components/__tests__/__fixtures__/worldObject.svelte.d.ts +0 -2
  127. package/dist/components/__tests__/__fixtures__/worldObject.svelte.js +0 -35
  128. package/dist/components/portal/Portal.svelte +0 -25
  129. package/dist/components/portal/Portal.svelte.d.ts +0 -8
  130. package/dist/components/portal/PortalTarget.svelte +0 -18
  131. package/dist/components/portal/PortalTarget.svelte.d.ts +0 -6
  132. package/dist/components/portal/index.d.ts +0 -2
  133. package/dist/components/portal/index.js +0 -2
  134. package/dist/components/portal/usePortalContext.svelte.d.ts +0 -5
  135. package/dist/components/portal/usePortalContext.svelte.js +0 -5
  136. package/dist/hooks/useArrows.svelte.d.ts +0 -3
  137. package/dist/hooks/useArrows.svelte.js +0 -9
  138. package/dist/hooks/useDraggable.svelte.d.ts +0 -10
  139. package/dist/hooks/useDraggable.svelte.js +0 -36
  140. package/dist/hooks/useObjects.svelte.d.ts +0 -7
  141. package/dist/hooks/useObjects.svelte.js +0 -35
  142. package/dist/hooks/usePersistentUUIDs.svelte.d.ts +0 -5
  143. package/dist/hooks/usePersistentUUIDs.svelte.js +0 -13
  144. package/dist/hooks/useResourceByName.svelte.d.ts +0 -7
  145. package/dist/hooks/useStaticGeometries.svelte.d.ts +0 -9
  146. package/dist/hooks/useStaticGeometries.svelte.js +0 -47
  147. package/dist/workers/worldStateWorker.d.ts +0 -1
  148. package/dist/workers/worldStateWorker.js +0 -114
  149. package/dist/world-state-messages.d.ts +0 -23
  150. package/dist/world-state-messages.js +0 -1
@@ -1,74 +1,109 @@
1
1
  <script lang="ts">
2
+ import type { Vector2Like } from 'three'
3
+ import { draggable } from '@neodrag/svelte'
2
4
  import Tree from './Tree.svelte'
3
-
4
- import { buildTreeNodes, type TreeNode } from './buildTree'
5
- import { useSelected } from '../../hooks/useSelection.svelte'
5
+ import { useSelectedEntity } from '../../hooks/useSelection.svelte'
6
6
  import { provideTreeExpandedContext } from './useExpanded.svelte'
7
- import { isEqual } from 'lodash-es'
8
- import { useObjects } from '../../hooks/useObjects.svelte'
9
7
  import Settings from './Settings.svelte'
10
8
  import Logs from './Logs.svelte'
11
- import { useDraggable } from '../../hooks/useDraggable.svelte'
12
- import { useWorldStates } from '../../hooks/useWorldState.svelte'
13
9
  import Widgets from './Widgets.svelte'
14
10
  import AddFrames from './AddFrames.svelte'
15
11
  import { useEnvironment } from '../../hooks/useEnvironment.svelte'
16
12
  import { usePartID } from '../../hooks/usePartID.svelte'
17
13
  import { usePartConfig } from '../../hooks/usePartConfig.svelte'
18
- import WeblabActive from '../weblab/WeblabActive.svelte'
19
- import { WEBLABS_EXPERIMENTS } from '../../hooks/useWeblabs.svelte'
14
+ import { traits, useWorld } from '../../ecs'
15
+ import { IsExcluded, type Entity } from 'koota'
16
+ import { buildTreeNodes, type TreeNode } from './buildTree'
17
+ import { MIN_DIMENSIONS, useResizable } from '../../hooks/useResizable.svelte'
18
+ import { PersistedState } from 'runed'
19
+
20
20
  const { ...rest } = $props()
21
21
 
22
+ const dragPosition = new PersistedState<Vector2Like | undefined>('tree-drag-position', undefined)
23
+
22
24
  provideTreeExpandedContext()
23
25
 
26
+ let container = $state.raw<HTMLDivElement>()
27
+ let dragElement = $state.raw<HTMLElement>()
28
+
24
29
  const partID = usePartID()
25
- const selected = useSelected()
26
- const objects = useObjects()
27
- const draggable = useDraggable('treeview')
28
- const worldStates = useWorldStates()
30
+ const selectedEntity = useSelectedEntity()
31
+ const resizable = useResizable(() => 'treeview')
29
32
  const environment = useEnvironment()
30
33
  const partConfig = usePartConfig()
34
+ const world = useWorld()
31
35
 
32
- let rootNode = $state<TreeNode>({
33
- id: 'world',
34
- name: 'World',
35
- children: [],
36
- href: '/',
37
- })
36
+ const worldEntity = world.spawn(IsExcluded, traits.Name('World'))
37
+
38
+ let children = $state.raw<TreeNode[]>([])
39
+ let nodeMap = $state.raw<Record<string, TreeNode | undefined>>({})
40
+
41
+ let pending = false
42
+ const flush = () => {
43
+ if (pending) return
44
+ pending = true
45
+ window.setTimeout(() => {
46
+ const results = buildTreeNodes(world.query(traits.Name))
47
+ children = results.rootNodes
48
+ nodeMap = results.nodeMap
49
+ pending = false
50
+ })
51
+ }
38
52
 
39
- const nodes = $derived(buildTreeNodes(objects.current, worldStates.current))
53
+ world.onAdd(traits.Name, flush)
54
+ world.onAdd(traits.Parent, flush)
55
+ world.onRemove(traits.Name, flush)
56
+ world.onRemove(traits.Parent, flush)
57
+ world.onChange(traits.Name, flush)
58
+ world.onChange(traits.Parent, flush)
40
59
 
41
- $effect.pre(() => {
42
- if (!isEqual(rootNode.children, nodes)) {
43
- rootNode.children = nodes
60
+ const rootNode = $derived<TreeNode>({
61
+ entity: worldEntity,
62
+ children,
63
+ })
64
+
65
+ $effect(() => {
66
+ if (container) {
67
+ resizable.observe(container)
44
68
  }
45
69
  })
46
70
  </script>
47
71
 
48
- <div
49
- class="bg-extralight border-medium absolute top-0 left-0 z-1000 m-2 w-60 overflow-y-auto border text-xs"
50
- style:transform="translate({draggable.current.x}px, {draggable.current.y}px)"
51
- {...rest}
52
- >
53
- {#key rootNode}
72
+ {#if resizable.isLoaded}
73
+ <div
74
+ bind:this={container}
75
+ class="bg-extralight border-medium absolute top-0 left-0 z-1000 m-2 resize overflow-y-auto border text-xs"
76
+ style:min-width="{MIN_DIMENSIONS.width}px"
77
+ style:min-height="{MIN_DIMENSIONS.height}px"
78
+ style:width={resizable.current ? `${resizable.current.width}px` : undefined}
79
+ style:height={resizable.current ? `${resizable.current.height}px` : undefined}
80
+ use:draggable={{
81
+ bounds: 'body',
82
+ handle: dragElement,
83
+ defaultPosition: dragPosition.current,
84
+ onDragEnd(data) {
85
+ dragPosition.current = { x: data.offsetX, y: data.offsetY }
86
+ },
87
+ }}
88
+ {...rest}
89
+ >
54
90
  <Tree
55
91
  {rootNode}
56
- selections={selected.current ? [selected.current] : []}
92
+ {nodeMap}
93
+ bind:dragElement
57
94
  onSelectionChange={(event) => {
58
- selected.set(event.selectedValue[0])
95
+ const value = event.selectedValue[0]
96
+
97
+ selectedEntity.set(value ? (Number(value) as Entity) : undefined)
59
98
  }}
60
- onDragStart={draggable.onDragStart}
61
- onDragEnd={draggable.onDragEnd}
62
99
  />
63
- {/key}
64
100
 
65
- <WeblabActive experiment={WEBLABS_EXPERIMENTS.MOTION_TOOLS_EDIT_FRAME}>
66
101
  {#if environment.current.isStandalone && partID.current && partConfig.hasEditPermissions}
67
102
  <AddFrames />
68
103
  {/if}
69
- </WeblabActive>
70
104
 
71
- <Logs />
72
- <Settings />
73
- <Widgets />
74
- </div>
105
+ <Logs />
106
+ <Settings />
107
+ <Widgets />
108
+ </div>
109
+ {/if}
@@ -6,11 +6,8 @@
6
6
  const settings = useSettings()
7
7
  </script>
8
8
 
9
- <Drawer
10
- name="Widgets"
11
- defaultOpen
12
- >
13
- <div class="flex h-24 flex-col gap-2 overflow-scroll p-3">
9
+ <Drawer name="Widgets">
10
+ <div class="flex flex-col gap-2 overflow-scroll p-3">
14
11
  <div class="flex items-center justify-between gap-4 py-2">
15
12
  Arm positions
16
13
  <Switch
@@ -1,12 +1,13 @@
1
- import type { useWorldStates } from '../../hooks/useWorldState.svelte';
2
- import type { WorldObject } from '../../WorldObject.svelte';
1
+ import type { Entity, QueryResult, Trait } from 'koota';
3
2
  export interface TreeNode {
4
- id: string;
5
- name: string;
3
+ entity: Entity;
4
+ parent?: TreeNode;
6
5
  children?: TreeNode[];
7
- href: string;
8
6
  }
9
7
  /**
10
8
  * Creates a tree representing parent child / relationships from a set of frames.
11
9
  */
12
- export declare const buildTreeNodes: (objects: WorldObject[], worldStates: ReturnType<typeof useWorldStates>["current"]) => TreeNode[];
10
+ export declare const buildTreeNodes: (entities: QueryResult<[Trait]>) => {
11
+ rootNodes: TreeNode[];
12
+ nodeMap: Record<string, TreeNode | undefined>;
13
+ };
@@ -1,52 +1,33 @@
1
+ import { traits } from '../../ecs';
1
2
  /**
2
3
  * Creates a tree representing parent child / relationships from a set of frames.
3
4
  */
4
- export const buildTreeNodes = (objects, worldStates) => {
5
- const nodeMap = new Map();
5
+ export const buildTreeNodes = (entities) => {
6
+ const nodeMap = {};
6
7
  const rootNodes = [];
7
- for (const object of objects) {
8
- const node = {
9
- name: object.name,
10
- id: object.uuid,
11
- children: [],
12
- href: `/selection/${object.name}`,
13
- };
14
- nodeMap.set(object.name, node);
15
- if (object.referenceFrame === 'world') {
8
+ const childNodes = [];
9
+ for (const entity of entities) {
10
+ const parent = entity.get(traits.Parent);
11
+ const name = entity.get(traits.Name) ?? '';
12
+ const node = { entity };
13
+ nodeMap[name] = node;
14
+ if (!parent || parent === 'world') {
16
15
  rootNodes.push(node);
17
16
  }
18
- }
19
- for (const object of objects) {
20
- if (object.referenceFrame && object.referenceFrame !== 'world') {
21
- const parentNode = nodeMap.get(object.referenceFrame);
22
- const child = nodeMap.get(object.name);
23
- if (parentNode && child) {
24
- parentNode.children?.push(child);
25
- }
17
+ else {
18
+ childNodes.push(node);
26
19
  }
27
20
  }
28
- for (const worldState of Object.values(worldStates)) {
29
- const node = {
30
- name: worldState.name,
31
- id: worldState.name,
32
- children: [],
33
- href: `/world-state/${worldState.name}`,
34
- };
35
- for (const object of worldState.worldObjects) {
36
- const child = {
37
- name: object.name,
38
- id: object.uuid,
39
- children: [],
40
- href: `/world-state/${worldState.name}/${object.name}`,
41
- };
42
- const parentNode = object.referenceFrame && nodeMap.has(object.referenceFrame)
43
- ? nodeMap.get(object.referenceFrame)
44
- : node;
45
- nodeMap.set(object.name, child);
46
- parentNode.children?.push(child);
21
+ for (const node of childNodes) {
22
+ const parent = node.entity.get(traits.Parent);
23
+ if (parent) {
24
+ const parentNode = nodeMap[parent];
25
+ node.parent = parentNode;
26
+ if (parentNode) {
27
+ parentNode.children ??= [];
28
+ parentNode.children?.push(node);
29
+ }
47
30
  }
48
- nodeMap.set(worldState.name, node);
49
- rootNodes.push(node);
50
31
  }
51
- return rootNodes;
32
+ return { rootNodes, nodeMap };
52
33
  };
@@ -0,0 +1,2 @@
1
+ import type { Entity, World } from 'koota';
2
+ export declare const createEntityFixture: (world: World) => Entity;
@@ -0,0 +1,20 @@
1
+ import { traits } from '../../../ecs';
2
+ export const createEntityFixture = (world) => {
3
+ return world.spawn(traits.Parent('parent_frame'), traits.Name('Test Object'), traits.Pose({
4
+ x: 10,
5
+ y: 20,
6
+ z: 30,
7
+ oX: 0.1,
8
+ oY: 0.2,
9
+ oZ: 0.3,
10
+ theta: 0.4,
11
+ }), traits.EditedPose({
12
+ x: 10,
13
+ y: 20,
14
+ z: 30,
15
+ oX: 0.1,
16
+ oY: 0.2,
17
+ oZ: 0.3,
18
+ theta: 0.4,
19
+ }), traits.Box({ x: 0.01, y: 0.02, z: 0.03 }));
20
+ };
@@ -0,0 +1,17 @@
1
+ export declare const resource: {
2
+ name: string;
3
+ frame: {
4
+ parent: string;
5
+ translation: {
6
+ x: number;
7
+ y: number;
8
+ z: number;
9
+ };
10
+ geometry: {
11
+ type: string;
12
+ x: number;
13
+ y: number;
14
+ z: number;
15
+ };
16
+ };
17
+ };
@@ -0,0 +1,13 @@
1
+ export const resource = {
2
+ name: 'Test Object',
3
+ frame: {
4
+ parent: 'parent_frame',
5
+ translation: { x: 10, y: 20, z: 30 },
6
+ geometry: {
7
+ type: 'box',
8
+ x: 10,
9
+ y: 20,
10
+ z: 30,
11
+ },
12
+ },
13
+ };
@@ -1,15 +1,15 @@
1
1
  <script>
2
2
  import { useSettings } from '../../hooks/useSettings.svelte'
3
- import PortalTarget from '../portal/PortalTarget.svelte'
3
+ import { PortalTarget } from '@threlte/extras'
4
4
  import Button from './Button.svelte'
5
5
 
6
- let { ...rest } = $props()
6
+ let { dashboard, ...rest } = $props()
7
7
 
8
8
  const settings = useSettings()
9
9
  </script>
10
10
 
11
11
  <div
12
- class="absolute top-2 z-1000 flex w-full justify-center gap-2"
12
+ class="absolute top-2 z-10 flex w-full justify-center gap-2"
13
13
  {...rest}
14
14
  >
15
15
  <!-- camera view -->
@@ -83,4 +83,6 @@
83
83
  {/if}
84
84
 
85
85
  <PortalTarget id="dashboard" />
86
+
87
+ {@render dashboard?.()}
86
88
  </div>
@@ -1,6 +1,11 @@
1
1
  export default Dashboard;
2
2
  type Dashboard = {
3
3
  $on?(type: string, callback: (e: any) => void): () => void;
4
- $set?(props: Partial<Record<string, any>>): void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
5
  };
6
- declare const Dashboard: import("svelte").Component<Record<string, any>, {}, "">;
6
+ declare const Dashboard: import("svelte").Component<{
7
+ dashboard: any;
8
+ } & Record<string, any>, {}, "">;
9
+ type $$ComponentProps = {
10
+ dashboard: any;
11
+ } & Record<string, any>;
@@ -1,13 +1,21 @@
1
1
  <script lang="ts">
2
+ import type { Vector2Like } from 'three'
3
+ import { draggable } from '@neodrag/svelte'
2
4
  import { formatNumeric } from '../../format'
3
5
  import Table from '../shared/Table.svelte'
4
- import { useDraggable } from '../../hooks/useDraggable.svelte'
5
6
  import { useArmClient } from '../../hooks/useArmClient.svelte'
6
7
  import { Icon, Label, Select } from '@viamrobotics/prime-core'
8
+ import { PersistedState } from 'runed'
7
9
 
8
10
  const { ...rest } = $props()
9
11
 
10
- const draggable = useDraggable('arm-current-positions')
12
+ const dragPosition = new PersistedState<Vector2Like | undefined>(
13
+ 'details-drag-position',
14
+ undefined
15
+ )
16
+
17
+ let dragElement = $state.raw<HTMLElement>()
18
+
11
19
  const armClient = useArmClient()
12
20
 
13
21
  let selectedArm = $state(armClient.names[0])
@@ -17,16 +25,20 @@
17
25
 
18
26
  <div
19
27
  class="bg-extralight border-medium absolute top-0 left-0 z-1000 m-2 overflow-y-auto border text-xs"
20
- style:transform="translate({draggable.current.x}px, {draggable.current.y}px)"
28
+ use:draggable={{
29
+ bounds: 'body',
30
+ handle: dragElement,
31
+ defaultPosition: dragPosition.current,
32
+ onDragEnd(data) {
33
+ dragPosition.current = { x: data.offsetX, y: data.offsetY }
34
+ },
35
+ }}
21
36
  {...rest}
22
37
  >
23
38
  <div class="flex min-w-0 flex-col">
24
39
  <div class="flex w-full items-center justify-between">
25
40
  <div class="border-medium flex w-full items-center gap-1 border-b p-2">
26
- <button
27
- onmousedown={draggable.onDragStart}
28
- onmouseup={draggable.onDragEnd}
29
- >
41
+ <button bind:this={dragElement}>
30
42
  <Icon name="drag" />
31
43
  </button>
32
44
  <h3>Arm positions</h3>