@viamrobotics/test-widgets 0.6.1 → 0.8.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.
- package/README.md +1 -1
- package/dist/api-docs-href.d.ts +8 -0
- package/dist/api-docs-href.js +17 -0
- package/dist/client-map.d.ts +30 -30
- package/dist/client-map.js +32 -29
- package/dist/components/angle-unit-toggle.svelte +1 -4
- package/dist/components/api-section.svelte +21 -23
- package/dist/components/api-section.svelte.d.ts +2 -0
- package/dist/components/index.d.ts +21 -0
- package/dist/components/index.js +21 -0
- package/dist/components/is-moving.svelte +4 -5
- package/dist/components/is-moving.svelte.d.ts +1 -0
- package/dist/components/mutation-section.svelte +20 -23
- package/dist/components/mutation-section.svelte.d.ts +2 -0
- package/dist/components/section-title.svelte +63 -0
- package/dist/components/section-title.svelte.d.ts +14 -0
- package/dist/components/widgets/arm/arm.svelte +25 -29
- package/dist/components/widgets/arm/get-joint-positions-widget.svelte +36 -0
- package/dist/components/widgets/arm/get-joint-positions-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/arm/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/arm/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/arm/joint-position-editor.svelte +89 -0
- package/dist/components/widgets/arm/joint-position-editor.svelte.d.ts +11 -0
- package/dist/components/widgets/arm/joint-position-quick-move.svelte +85 -0
- package/dist/components/widgets/arm/joint-position-quick-move.svelte.d.ts +9 -0
- package/dist/components/widgets/arm/joint-position-slider.svelte +36 -0
- package/dist/components/widgets/arm/joint-position-slider.svelte.d.ts +9 -0
- package/dist/components/widgets/arm/move-to-joint-positions-widget.svelte +9 -5
- package/dist/components/widgets/arm/move-to-joint-positions.svelte +73 -127
- package/dist/components/widgets/arm/move-to-joint-positions.svelte.d.ts +1 -0
- package/dist/components/widgets/arm/move-to-position.svelte +31 -3
- package/dist/components/widgets/audio-input/audio-input.svelte +2 -0
- package/dist/components/widgets/audio-input/get-properties-widget.svelte +43 -0
- package/dist/components/widgets/audio-input/get-properties-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/audio-output/audio-output.svelte +2 -0
- package/dist/components/widgets/audio-output/get-properties-widget.svelte +43 -0
- package/dist/components/widgets/audio-output/get-properties-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/base/base.svelte +9 -1
- package/dist/components/widgets/base/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/base/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/base/quick-move.svelte +12 -5
- package/dist/components/widgets/camera/camera.svelte +156 -142
- package/dist/components/widgets/camera/live-or-polling-video.svelte +9 -1
- package/dist/components/widgets/discovery/discovery.svelte +1 -0
- package/dist/components/widgets/encoder/encoder-position-type.d.ts +8 -0
- package/dist/components/widgets/encoder/encoder-position-type.js +20 -0
- package/dist/components/widgets/encoder/encoder.svelte +5 -20
- package/dist/components/widgets/encoder/get-position-widget.svelte +54 -0
- package/dist/components/widgets/encoder/get-position-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/gantry/gantry.svelte +28 -5
- package/dist/components/widgets/gantry/get-position-widget.svelte +43 -0
- package/dist/components/widgets/gantry/get-position-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/gantry/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/gantry/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/generic/generic.svelte +8 -1
- package/dist/components/widgets/gripper/gripper.svelte +11 -5
- package/dist/components/widgets/gripper/is-holding-something.svelte +2 -4
- package/dist/components/widgets/gripper/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/gripper/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/input-controller/input-controller.svelte +2 -1
- package/dist/components/widgets/motor/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/motor/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/motor/motor.svelte +13 -9
- package/dist/components/widgets/movement-sensor/get-accuracy-widget.svelte +38 -0
- package/dist/components/widgets/movement-sensor/get-accuracy-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/movement-sensor/get-compass-heading-widget.svelte +38 -0
- package/dist/components/widgets/movement-sensor/get-compass-heading-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/movement-sensor/get-orientation-widget.svelte +38 -0
- package/dist/components/widgets/movement-sensor/get-orientation-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/movement-sensor/get-position-widget.svelte +38 -0
- package/dist/components/widgets/movement-sensor/get-position-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/movement-sensor/movement-sensor.svelte +53 -26
- package/dist/components/widgets/power-sensor/get-current-widget.svelte +38 -0
- package/dist/components/widgets/power-sensor/get-current-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/power-sensor/get-power-widget.svelte +38 -0
- package/dist/components/widgets/power-sensor/get-power-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/power-sensor/get-voltage-widget.svelte +38 -0
- package/dist/components/widgets/power-sensor/get-voltage-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/power-sensor/power-sensor.svelte +4 -0
- package/dist/components/widgets/sensor/sensor.svelte +1 -0
- package/dist/components/widgets/servo/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/servo/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/servo/servo.svelte +10 -2
- package/dist/components/widgets/slam/get-position-widget.svelte +38 -0
- package/dist/components/widgets/slam/get-position-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/slam/move-on-map.svelte +4 -1
- package/dist/components/widgets/slam/slam.svelte +4 -1
- package/dist/components/widgets/vision-service/context.svelte.d.ts +1 -0
- package/dist/components/widgets/vision-service/context.svelte.js +7 -0
- package/dist/components/widgets/vision-service/detection-row.svelte +38 -0
- package/dist/components/widgets/vision-service/detection-row.svelte.d.ts +8 -0
- package/dist/components/widgets/vision-service/detection.svelte +7 -4
- package/dist/components/widgets/vision-service/legend.svelte +14 -11
- package/dist/components/widgets/vision-service/vision-service.svelte +9 -10
- package/dist/index.d.ts +5 -1
- package/dist/index.js +6 -1
- package/dist/pip/context.svelte.d.ts +2 -0
- package/dist/pip/context.svelte.js +48 -20
- package/dist/resource-triplet.d.ts +37 -0
- package/dist/resource-triplet.js +37 -0
- package/dist/resource-widget.js +187 -0
- package/dist/resource.d.ts +0 -9
- package/dist/resource.js +0 -72
- package/package.json +7 -4
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { PowerSensorClient } from '@viamrobotics/sdk'
|
|
3
|
+
import { createResourceClient, createResourceQuery } from '@viamrobotics/svelte-sdk'
|
|
4
|
+
|
|
5
|
+
import ApiSection from '../../api-section.svelte'
|
|
6
|
+
import Query from '../../query.svelte'
|
|
7
|
+
|
|
8
|
+
import PowerReading from './power-reading.svelte'
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
partID: string
|
|
12
|
+
resourceName: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { partID, resourceName }: Props = $props()
|
|
16
|
+
|
|
17
|
+
const client = createResourceClient(
|
|
18
|
+
PowerSensorClient,
|
|
19
|
+
() => partID,
|
|
20
|
+
() => resourceName
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
const query = createResourceQuery(client, 'getPower', { refetchInterval: 500 })
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<ApiSection
|
|
27
|
+
title="GetPower"
|
|
28
|
+
class="grow"
|
|
29
|
+
>
|
|
30
|
+
<Query
|
|
31
|
+
{query}
|
|
32
|
+
contentCx="h-6"
|
|
33
|
+
>
|
|
34
|
+
{#if query.data !== undefined}
|
|
35
|
+
<PowerReading data={query.data} />
|
|
36
|
+
{/if}
|
|
37
|
+
</Query>
|
|
38
|
+
</ApiSection>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { PowerSensorClient } from '@viamrobotics/sdk'
|
|
3
|
+
import { createResourceClient, createResourceQuery } from '@viamrobotics/svelte-sdk'
|
|
4
|
+
|
|
5
|
+
import ApiSection from '../../api-section.svelte'
|
|
6
|
+
import Query from '../../query.svelte'
|
|
7
|
+
|
|
8
|
+
import VoltageReading from './voltage-reading.svelte'
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
partID: string
|
|
12
|
+
resourceName: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { partID, resourceName }: Props = $props()
|
|
16
|
+
|
|
17
|
+
const client = createResourceClient(
|
|
18
|
+
PowerSensorClient,
|
|
19
|
+
() => partID,
|
|
20
|
+
() => resourceName
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
const query = createResourceQuery(client, 'getVoltage', { refetchInterval: 500 })
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<ApiSection
|
|
27
|
+
title="GetVoltage"
|
|
28
|
+
class="grow"
|
|
29
|
+
>
|
|
30
|
+
<Query
|
|
31
|
+
{query}
|
|
32
|
+
contentCx="h-6"
|
|
33
|
+
>
|
|
34
|
+
{#if query.data !== undefined}
|
|
35
|
+
<VoltageReading data={query.data} />
|
|
36
|
+
{/if}
|
|
37
|
+
</Query>
|
|
38
|
+
</ApiSection>
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
<div class="grid w-full grid-cols-3 divide-x">
|
|
67
67
|
<ApiSection
|
|
68
68
|
title="GetCurrent"
|
|
69
|
+
api="rdk:component:power_sensor"
|
|
69
70
|
class="pb-5"
|
|
70
71
|
>
|
|
71
72
|
<Query
|
|
@@ -79,6 +80,7 @@
|
|
|
79
80
|
</ApiSection>
|
|
80
81
|
<ApiSection
|
|
81
82
|
title="GetVoltage"
|
|
83
|
+
api="rdk:component:power_sensor"
|
|
82
84
|
class="pb-5"
|
|
83
85
|
>
|
|
84
86
|
<Query
|
|
@@ -92,6 +94,7 @@
|
|
|
92
94
|
</ApiSection>
|
|
93
95
|
<ApiSection
|
|
94
96
|
title="GetPower"
|
|
97
|
+
api="rdk:component:power_sensor"
|
|
95
98
|
class="pb-5"
|
|
96
99
|
>
|
|
97
100
|
<Query
|
|
@@ -107,6 +110,7 @@
|
|
|
107
110
|
|
|
108
111
|
<ApiSection
|
|
109
112
|
title="GetReadings"
|
|
113
|
+
api="rdk:component:power_sensor"
|
|
110
114
|
description="Get all the measurements and data that this power sensor provides"
|
|
111
115
|
>
|
|
112
116
|
<Switch
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ServoClient } from '@viamrobotics/sdk'
|
|
3
|
+
|
|
4
|
+
import IsMoving from '../../is-moving.svelte'
|
|
5
|
+
import { ResourceTriplets } from '../../../resource-triplet'
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
partID: string
|
|
9
|
+
resourceName: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { partID, resourceName }: Props = $props()
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<IsMoving
|
|
16
|
+
client={ServoClient}
|
|
17
|
+
api={ResourceTriplets.Servo}
|
|
18
|
+
{partID}
|
|
19
|
+
{resourceName}
|
|
20
|
+
/>
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
<div class="grid grow grid-cols-3 divide-x">
|
|
53
53
|
<ApiSection
|
|
54
54
|
title="GetPosition"
|
|
55
|
+
api="rdk:component:servo"
|
|
55
56
|
bottomText="Updates automatically"
|
|
56
57
|
>
|
|
57
58
|
<Query query={positionQuery}>
|
|
@@ -65,7 +66,10 @@
|
|
|
65
66
|
{/if}
|
|
66
67
|
</Query>
|
|
67
68
|
</ApiSection>
|
|
68
|
-
<ApiSection
|
|
69
|
+
<ApiSection
|
|
70
|
+
title="Move"
|
|
71
|
+
api="rdk:component:servo"
|
|
72
|
+
>
|
|
69
73
|
<Query query={positionQuery}>
|
|
70
74
|
{#if positionQuery.data !== undefined}
|
|
71
75
|
<Move
|
|
@@ -92,7 +96,10 @@
|
|
|
92
96
|
</ApiSection>
|
|
93
97
|
</div>
|
|
94
98
|
<div class="ml-auto flex w-full max-w-40 flex-col divide-y">
|
|
95
|
-
<ApiSection
|
|
99
|
+
<ApiSection
|
|
100
|
+
title="Stop"
|
|
101
|
+
api="rdk:component:servo"
|
|
102
|
+
>
|
|
96
103
|
<StopButton
|
|
97
104
|
error={stopMutation.error}
|
|
98
105
|
onStop={() => {
|
|
@@ -102,6 +109,7 @@
|
|
|
102
109
|
</ApiSection>
|
|
103
110
|
<IsMoving
|
|
104
111
|
client={ServoClient}
|
|
112
|
+
api="rdk:component:servo"
|
|
105
113
|
{partID}
|
|
106
114
|
{resourceName}
|
|
107
115
|
/>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { SlamClient } from '@viamrobotics/sdk'
|
|
3
|
+
import { createResourceClient, createResourceQuery } from '@viamrobotics/svelte-sdk'
|
|
4
|
+
|
|
5
|
+
import ApiSection from '../../api-section.svelte'
|
|
6
|
+
import Query from '../../query.svelte'
|
|
7
|
+
|
|
8
|
+
import Position from './position.svelte'
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
partID: string
|
|
12
|
+
resourceName: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { partID, resourceName }: Props = $props()
|
|
16
|
+
|
|
17
|
+
const client = createResourceClient(
|
|
18
|
+
SlamClient,
|
|
19
|
+
() => partID,
|
|
20
|
+
() => resourceName
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
const query = createResourceQuery(client, 'getPosition', { refetchInterval: 1000 })
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<ApiSection
|
|
27
|
+
title="GetPosition"
|
|
28
|
+
class="grow"
|
|
29
|
+
>
|
|
30
|
+
<Query
|
|
31
|
+
{query}
|
|
32
|
+
contentCx="h-6"
|
|
33
|
+
>
|
|
34
|
+
{#if query.data !== undefined}
|
|
35
|
+
<Position position={query.data} />
|
|
36
|
+
{/if}
|
|
37
|
+
</Query>
|
|
38
|
+
</ApiSection>
|
|
@@ -16,6 +16,7 @@ export interface DetectionsContext {
|
|
|
16
16
|
readonly current: Detection[];
|
|
17
17
|
readonly byLabel: Record<string, DetectionGroup>;
|
|
18
18
|
readonly hovered: SvelteSet<string>;
|
|
19
|
+
selected: string | null;
|
|
19
20
|
}
|
|
20
21
|
export declare const DETECTIONS_CONTEXT_KEY: unique symbol;
|
|
21
22
|
export declare const createDetectionContext: (getDetections: () => DetectionPb[]) => DetectionsContext;
|
|
@@ -29,6 +29,7 @@ export const createDetectionContext = (getDetections) => {
|
|
|
29
29
|
const detections = $derived(addIdsToDetections(getDetections()));
|
|
30
30
|
const detectionsByLabel = $derived(categorize(detections));
|
|
31
31
|
const hovered = new SvelteSet();
|
|
32
|
+
let selected = $state(null);
|
|
32
33
|
const context = {
|
|
33
34
|
get current() {
|
|
34
35
|
return detections;
|
|
@@ -37,6 +38,12 @@ export const createDetectionContext = (getDetections) => {
|
|
|
37
38
|
return detectionsByLabel;
|
|
38
39
|
},
|
|
39
40
|
hovered,
|
|
41
|
+
get selected() {
|
|
42
|
+
return selected;
|
|
43
|
+
},
|
|
44
|
+
set selected(value) {
|
|
45
|
+
selected = value;
|
|
46
|
+
},
|
|
40
47
|
};
|
|
41
48
|
return context;
|
|
42
49
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Detection } from './context.svelte.js'
|
|
3
|
+
|
|
4
|
+
import { useDetections } from './context.svelte.js'
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
detection: Detection
|
|
8
|
+
label: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { detection, label }: Props = $props()
|
|
12
|
+
|
|
13
|
+
const context = useDetections()
|
|
14
|
+
|
|
15
|
+
let node: HTMLElement | undefined
|
|
16
|
+
|
|
17
|
+
$effect(() => {
|
|
18
|
+
if (context.selected === detection.id && node) {
|
|
19
|
+
node.scrollIntoView({ block: 'nearest' })
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<button
|
|
25
|
+
bind:this={node}
|
|
26
|
+
class={[
|
|
27
|
+
'hover:bg-light w-full py-1 pl-11 text-left',
|
|
28
|
+
(context.hovered.has(detection.id) || context.selected === detection.id) && 'bg-light',
|
|
29
|
+
]}
|
|
30
|
+
onpointerenter={() => context.hovered.add(detection.id)}
|
|
31
|
+
onpointerleave={() => context.hovered.delete(detection.id)}
|
|
32
|
+
onclick={() => {
|
|
33
|
+
context.selected = context.selected === detection.id ? null : detection.id
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
{label}
|
|
37
|
+
<span class="text-subtle-2 pl-1">{detection.confidence}%</span>
|
|
38
|
+
</button>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Detection } from './context.svelte.ts';
|
|
2
|
+
interface Props {
|
|
3
|
+
detection: Detection;
|
|
4
|
+
label: string;
|
|
5
|
+
}
|
|
6
|
+
declare const DetectionRow: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type DetectionRow = ReturnType<typeof DetectionRow>;
|
|
8
|
+
export default DetectionRow;
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
|
|
24
24
|
let hovering = $state(false)
|
|
25
25
|
|
|
26
|
+
const isSelected = $derived(context.selected === detection.id)
|
|
27
|
+
const isActive = $derived(isSelected || context.hovered.has(detection.id))
|
|
28
|
+
|
|
26
29
|
// These are ballparking, but seem good enough for nearly all cases
|
|
27
30
|
const isDetectionNearTop = $derived(factoredyMin < 30)
|
|
28
31
|
const isDetectionNearRight = $derived(factoredxMin > $size.width * 0.66)
|
|
@@ -32,10 +35,7 @@
|
|
|
32
35
|
positionType="absolute"
|
|
33
36
|
positionLeft={factoredxMin}
|
|
34
37
|
positionTop={factoredyMin}
|
|
35
|
-
borderColor=
|
|
36
|
-
hover={{
|
|
37
|
-
borderColor: detection.color,
|
|
38
|
-
}}
|
|
38
|
+
borderColor={isActive ? detection.color : '#aaa'}
|
|
39
39
|
borderWidth={2}
|
|
40
40
|
width={factoredxMax - factoredxMin}
|
|
41
41
|
height={factoredyMax - factoredyMin}
|
|
@@ -47,6 +47,9 @@
|
|
|
47
47
|
context.hovered.delete(detection.id)
|
|
48
48
|
hovering = false
|
|
49
49
|
}}
|
|
50
|
+
onclick={() => {
|
|
51
|
+
context.selected = context.selected === detection.id ? null : detection.id
|
|
52
|
+
}}
|
|
50
53
|
>
|
|
51
54
|
{#if hovering}
|
|
52
55
|
<Text
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { SvelteSet } from 'svelte/reactivity'
|
|
6
6
|
|
|
7
7
|
import { useDetections } from './context.svelte'
|
|
8
|
+
import DetectionRow from './detection-row.svelte'
|
|
8
9
|
|
|
9
10
|
interface Props {
|
|
10
11
|
classifications?: Classification[]
|
|
@@ -46,6 +47,16 @@
|
|
|
46
47
|
}
|
|
47
48
|
})
|
|
48
49
|
|
|
50
|
+
$effect.pre(() => {
|
|
51
|
+
if (context.selected === undefined) return
|
|
52
|
+
for (const [label, { detections }] of Object.entries(context.byLabel)) {
|
|
53
|
+
if (detections.some((d) => d.id === context.selected)) {
|
|
54
|
+
expandedLabels.add(label)
|
|
55
|
+
break
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
49
60
|
const compareConfidence = (a: Classification, b: Classification) => {
|
|
50
61
|
return b.confidence - a.confidence
|
|
51
62
|
}
|
|
@@ -113,18 +124,10 @@
|
|
|
113
124
|
<ul>
|
|
114
125
|
{#each detections as detection (detection.id)}
|
|
115
126
|
<li>
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
detection.id
|
|
119
|
-
)
|
|
120
|
-
? 'bg-light'
|
|
121
|
-
: ''}"
|
|
122
|
-
onpointerenter={() => context.hovered.add(detection.id)}
|
|
123
|
-
onpointerleave={() => context.hovered.delete(detection.id)}
|
|
124
|
-
>
|
|
127
|
+
<DetectionRow
|
|
128
|
+
{detection}
|
|
125
129
|
{label}
|
|
126
|
-
|
|
127
|
-
</button>
|
|
130
|
+
/>
|
|
128
131
|
</li>
|
|
129
132
|
{/each}
|
|
130
133
|
</ul>
|
|
@@ -147,16 +147,15 @@
|
|
|
147
147
|
</Select>
|
|
148
148
|
</Label>
|
|
149
149
|
</div>
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
</Label>
|
|
150
|
+
<div class="w-fit">
|
|
151
|
+
<Label position="top">
|
|
152
|
+
Is remote?
|
|
153
|
+
<Switch
|
|
154
|
+
slot="input"
|
|
155
|
+
bind:on={isRemote}
|
|
156
|
+
/>
|
|
157
|
+
</Label>
|
|
158
|
+
</div>
|
|
160
159
|
</div>
|
|
161
160
|
|
|
162
161
|
<h6 class="text-subtle-1 font-semibold">Detections/Classifications</h6>
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export { createAddImageToDatasetContext, type ImageData, useAddImageToDataset, } from './add-image-to-dataset';
|
|
2
|
+
export { apiDocsHref } from './api-docs-href';
|
|
2
3
|
export { clientForResource } from './client-map';
|
|
3
4
|
export * from './components';
|
|
4
5
|
export { getResourceAPI } from './get-resource-api';
|
|
5
6
|
export { providePip, usePip } from './pip/context.svelte';
|
|
6
|
-
export {
|
|
7
|
+
export { ResourceTriplets } from './resource-triplet';
|
|
8
|
+
export { apiWidgetsForResource, availableAPIWidgets, isKnownResource,
|
|
9
|
+
/** @deprecated use `isKnownResource` instead. Will be deleted in the next release */
|
|
10
|
+
isKnownResource as hasWidget, type ResourceAPIWidget, showResourceWidget, widgetForResource, } from './resource-widget';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
export { createAddImageToDatasetContext, useAddImageToDataset, } from './add-image-to-dataset';
|
|
2
|
+
export { apiDocsHref } from './api-docs-href';
|
|
2
3
|
export { clientForResource } from './client-map';
|
|
3
4
|
export * from './components';
|
|
4
5
|
export { getResourceAPI } from './get-resource-api';
|
|
5
6
|
export { providePip, usePip } from './pip/context.svelte';
|
|
6
|
-
export {
|
|
7
|
+
export { ResourceTriplets } from './resource-triplet';
|
|
8
|
+
export { apiWidgetsForResource, availableAPIWidgets, isKnownResource,
|
|
9
|
+
// TODO: Delete `hasWidget`
|
|
10
|
+
/** @deprecated use `isKnownResource` instead. Will be deleted in the next release */
|
|
11
|
+
isKnownResource as hasWidget, showResourceWidget, widgetForResource, } from './resource-widget';
|
|
@@ -2,6 +2,8 @@ interface PipContext {
|
|
|
2
2
|
/** Called by PictureInPictureButton to start or stop PiP. */
|
|
3
3
|
toggle(resourceName: string): Promise<void>;
|
|
4
4
|
setRate(rate: 'live' | number | false): void;
|
|
5
|
+
/** Register the media stream from the main camera view when its card is open. */
|
|
6
|
+
setStream(resourceName: string, stream: MediaStream | null): void;
|
|
5
7
|
error: Error | undefined;
|
|
6
8
|
/** Whether the PictureInPicture is active */
|
|
7
9
|
readyState: 'inactive' | 'loading' | 'active';
|
|
@@ -14,12 +14,21 @@ export function providePip(partID) {
|
|
|
14
14
|
const canvasCtx = canvas.getContext('2d');
|
|
15
15
|
const canvasStream = canvas.captureStream();
|
|
16
16
|
const img = document.createElement('img');
|
|
17
|
+
const externalStreams = new Map();
|
|
18
|
+
let externalStreamVersion = $state(0);
|
|
17
19
|
let error = $state();
|
|
18
20
|
let readyState = $state('inactive');
|
|
19
21
|
let rate = $state('live');
|
|
20
22
|
let activeName = $state();
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
+
const externalStream = $derived.by(() => {
|
|
24
|
+
void externalStreamVersion;
|
|
25
|
+
return activeName ? externalStreams.get(activeName) : undefined;
|
|
26
|
+
});
|
|
27
|
+
const needsOwnedStream = $derived(activeName !== undefined && !externalStream);
|
|
28
|
+
const cameraClient = $derived(needsOwnedStream && activeName
|
|
29
|
+
? createResourceClient(CameraClient, partID, () => activeName ?? '')
|
|
30
|
+
: undefined);
|
|
31
|
+
const streamClient = $derived(needsOwnedStream && activeName ? createStreamClient(partID, () => activeName ?? '') : undefined);
|
|
23
32
|
const imageQuery = $derived(cameraClient?.current
|
|
24
33
|
? createResourceQuery(cameraClient, 'getImages', () => ({
|
|
25
34
|
enabled: rate !== 'live',
|
|
@@ -27,22 +36,39 @@ export function providePip(partID) {
|
|
|
27
36
|
refetchIntervalInBackground: activeName === cameraClient?.current?.name,
|
|
28
37
|
}))
|
|
29
38
|
: undefined);
|
|
30
|
-
const
|
|
39
|
+
const ownedMediaStream = $derived(needsOwnedStream ? ((rate === 'live' ? streamClient?.mediaStream : canvasStream) ?? null) : null);
|
|
40
|
+
const playbackStream = $derived(externalStream ?? ownedMediaStream);
|
|
41
|
+
const setStream = (resourceName, stream) => {
|
|
42
|
+
if (stream) {
|
|
43
|
+
externalStreams.set(resourceName, stream);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
externalStreams.delete(resourceName);
|
|
47
|
+
}
|
|
48
|
+
externalStreamVersion++;
|
|
49
|
+
};
|
|
31
50
|
$effect(() => {
|
|
32
51
|
document.body.append(video);
|
|
52
|
+
const handleLeave = () => {
|
|
53
|
+
readyState = 'inactive';
|
|
54
|
+
activeName = undefined;
|
|
55
|
+
error = undefined;
|
|
56
|
+
};
|
|
57
|
+
video.addEventListener('leavepictureinpicture', handleLeave);
|
|
33
58
|
return () => {
|
|
59
|
+
video.removeEventListener('leavepictureinpicture', handleLeave);
|
|
34
60
|
video.remove();
|
|
35
61
|
};
|
|
36
62
|
});
|
|
37
63
|
$effect(() => {
|
|
38
|
-
video.srcObject =
|
|
64
|
+
video.srcObject = playbackStream;
|
|
39
65
|
return () => {
|
|
40
66
|
video.srcObject = null;
|
|
41
67
|
};
|
|
42
68
|
});
|
|
43
69
|
$effect(() => {
|
|
44
70
|
const currentRate = rate;
|
|
45
|
-
if (currentRate === 'live')
|
|
71
|
+
if (!needsOwnedStream || currentRate === 'live')
|
|
46
72
|
return;
|
|
47
73
|
const image = imageQuery?.data?.images[0];
|
|
48
74
|
if (!image)
|
|
@@ -64,12 +90,11 @@ export function providePip(partID) {
|
|
|
64
90
|
img.removeEventListener('load', drawImage);
|
|
65
91
|
};
|
|
66
92
|
});
|
|
67
|
-
const toggle = async () => {
|
|
68
|
-
if (activeName ===
|
|
69
|
-
readyState === 'active' &&
|
|
70
|
-
document.pictureInPictureElement === video) {
|
|
93
|
+
const toggle = async (resourceName) => {
|
|
94
|
+
if (activeName === resourceName && document.pictureInPictureElement === video) {
|
|
71
95
|
try {
|
|
72
96
|
await document.exitPictureInPicture();
|
|
97
|
+
activeName = undefined;
|
|
73
98
|
readyState = 'inactive';
|
|
74
99
|
error = undefined;
|
|
75
100
|
}
|
|
@@ -78,28 +103,31 @@ export function providePip(partID) {
|
|
|
78
103
|
}
|
|
79
104
|
return;
|
|
80
105
|
}
|
|
106
|
+
activeName = resourceName;
|
|
81
107
|
readyState = 'loading';
|
|
82
|
-
// Wait for the new stream's metadata to load before requesting PiP,
|
|
83
|
-
// otherwise the browser throws InvalidStateError.
|
|
84
|
-
if (video.readyState < 1 /* HAVE_METADATA */) {
|
|
85
|
-
await new Promise((resolve) => {
|
|
86
|
-
video.addEventListener('loadedmetadata', () => resolve(), { once: true });
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
108
|
try {
|
|
109
|
+
const stream = ownedMediaStream;
|
|
110
|
+
video.srcObject = stream;
|
|
111
|
+
// Wait for the stream's metadata to load before requesting PiP,
|
|
112
|
+
// otherwise the browser throws InvalidStateError.
|
|
113
|
+
if (video.readyState < 1 /* HAVE_METADATA */) {
|
|
114
|
+
await new Promise((resolve) => {
|
|
115
|
+
video.addEventListener('loadedmetadata', () => resolve(), { once: true });
|
|
116
|
+
});
|
|
117
|
+
}
|
|
90
118
|
await video.requestPictureInPicture();
|
|
91
119
|
readyState = 'active';
|
|
92
120
|
error = undefined;
|
|
93
121
|
}
|
|
94
122
|
catch (nextError) {
|
|
123
|
+
readyState = 'inactive';
|
|
124
|
+
activeName = undefined;
|
|
95
125
|
error = nextError;
|
|
96
126
|
}
|
|
97
127
|
};
|
|
98
128
|
const context = {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
await toggle();
|
|
102
|
-
},
|
|
129
|
+
toggle,
|
|
130
|
+
setStream,
|
|
103
131
|
setRate(newRate) {
|
|
104
132
|
rate = newRate;
|
|
105
133
|
},
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** The canonical set of Viam resource API triplets. */
|
|
2
|
+
export declare const ResourceTriplets: {
|
|
3
|
+
readonly Arm: "rdk:component:arm";
|
|
4
|
+
readonly AudioInput: "rdk:component:audio_in";
|
|
5
|
+
readonly AudioOutput: "rdk:component:audio_out";
|
|
6
|
+
readonly Base: "rdk:component:base";
|
|
7
|
+
readonly Board: "rdk:component:board";
|
|
8
|
+
readonly Button: "rdk:component:button";
|
|
9
|
+
readonly Camera: "rdk:component:camera";
|
|
10
|
+
readonly Encoder: "rdk:component:encoder";
|
|
11
|
+
readonly Gantry: "rdk:component:gantry";
|
|
12
|
+
readonly GenericComponent: "rdk:component:generic";
|
|
13
|
+
readonly Gripper: "rdk:component:gripper";
|
|
14
|
+
readonly InputController: "rdk:component:input_controller";
|
|
15
|
+
readonly Motor: "rdk:component:motor";
|
|
16
|
+
readonly MovementSensor: "rdk:component:movement_sensor";
|
|
17
|
+
readonly PoseTracker: "rdk:component:pose_tracker";
|
|
18
|
+
readonly PowerSensor: "rdk:component:power_sensor";
|
|
19
|
+
readonly Sensor: "rdk:component:sensor";
|
|
20
|
+
readonly Servo: "rdk:component:servo";
|
|
21
|
+
readonly Switch: "rdk:component:switch";
|
|
22
|
+
readonly BaseRemoteControl: "rdk:service:base_remote_control";
|
|
23
|
+
readonly DataManager: "rdk:service:data_manager";
|
|
24
|
+
readonly Discovery: "rdk:service:discovery";
|
|
25
|
+
readonly GenericService: "rdk:service:generic";
|
|
26
|
+
readonly MLModel: "rdk:service:mlmodel";
|
|
27
|
+
readonly Motion: "rdk:service:motion";
|
|
28
|
+
readonly Navigation: "rdk:service:navigation";
|
|
29
|
+
readonly Slam: "rdk:service:slam";
|
|
30
|
+
readonly Sensors: "rdk:service:sensors";
|
|
31
|
+
readonly Shell: "rdk:service:shell";
|
|
32
|
+
readonly Video: "rdk:service:video";
|
|
33
|
+
readonly Vision: "rdk:service:vision";
|
|
34
|
+
readonly WorldStateStore: "rdk:service:world_state_store";
|
|
35
|
+
};
|
|
36
|
+
/** A Viam resource API triplet, e.g. `'rdk:component:arm'`. */
|
|
37
|
+
export type ResourceTriplet = (typeof ResourceTriplets)[keyof typeof ResourceTriplets];
|