@stonecrop/beam 0.4.4 → 0.4.5
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/dist/assets/index.css +1 -1
- package/dist/beam.d.ts +50 -6
- package/dist/beam.js +119 -105
- package/dist/beam.js.map +1 -1
- package/dist/beam.umd.cjs +3 -3
- package/dist/beam.umd.cjs.map +1 -1
- package/dist/composables/mqtt.js +51 -1
- package/dist/src/composables/mqtt.d.ts +11 -2
- package/dist/src/composables/mqtt.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +41 -11
- package/dist/src/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/BeamDayDivider.vue +1 -1
- package/src/components/BeamFilter.vue +10 -7
- package/src/components/BeamFilterOption.vue +20 -21
- package/src/components/ListView.vue +1 -1
- package/src/components/SegmentedDisplay.vue +8 -5
- package/src/composables/mqtt.ts +57 -1
- package/src/index.ts +1 -1
- package/src/types/index.ts +49 -11
package/dist/composables/mqtt.js
CHANGED
|
@@ -6,7 +6,13 @@ import { onMounted, onUnmounted, ref } from 'vue';
|
|
|
6
6
|
* @returns MQTT stream messages
|
|
7
7
|
* @beta
|
|
8
8
|
*/
|
|
9
|
-
export const useMqttStream = (options) => {
|
|
9
|
+
export const useMqttStream = async (options) => {
|
|
10
|
+
if (options.host && options.port) {
|
|
11
|
+
const portActive = await isPortActive(options.host, options.port);
|
|
12
|
+
if (!portActive) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
10
16
|
const client = ref();
|
|
11
17
|
const messages = ref({});
|
|
12
18
|
onMounted(() => {
|
|
@@ -33,3 +39,47 @@ export const useMqttStream = (options) => {
|
|
|
33
39
|
});
|
|
34
40
|
return { messages };
|
|
35
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
* Check if a local port has a service running
|
|
44
|
+
* @param host the host to check
|
|
45
|
+
* @param port the port to check
|
|
46
|
+
* @returns true if the port has a service running, false otherwise
|
|
47
|
+
*
|
|
48
|
+
* @beta
|
|
49
|
+
*/
|
|
50
|
+
export const isPortActive = async (host, port) => {
|
|
51
|
+
try {
|
|
52
|
+
const controller = new AbortController();
|
|
53
|
+
// Set a timeout of 2 seconds
|
|
54
|
+
const timeoutId = setTimeout(() => controller.abort(), 2000);
|
|
55
|
+
try {
|
|
56
|
+
await fetch(`${host}:${port}`, {
|
|
57
|
+
mode: 'no-cors', // This allows checking without CORS issues
|
|
58
|
+
signal: controller.signal,
|
|
59
|
+
});
|
|
60
|
+
clearTimeout(timeoutId);
|
|
61
|
+
// If we get any response, the port is in use
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
clearTimeout(timeoutId);
|
|
66
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
67
|
+
// Timeout - port is probably not in use
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
// For connection refused errors, we need to check the error message
|
|
71
|
+
// as different browsers handle this differently
|
|
72
|
+
const errorString = String(error);
|
|
73
|
+
if (errorString.includes('NetworkError') ||
|
|
74
|
+
errorString.includes('Failed to fetch') ||
|
|
75
|
+
errorString.includes('net::ERR_CONNECTION_REFUSED')) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
// If we get here, there might be something running on the port
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
@@ -5,7 +5,16 @@ import { IMqttStream } from '../types';
|
|
|
5
5
|
* @returns MQTT stream messages
|
|
6
6
|
* @beta
|
|
7
7
|
*/
|
|
8
|
-
export declare const useMqttStream: (options: IMqttStream) => {
|
|
8
|
+
export declare const useMqttStream: (options: IMqttStream) => Promise<{
|
|
9
9
|
messages: import("vue").Ref<Record<string, string[]>, Record<string, string[]>>;
|
|
10
|
-
}
|
|
10
|
+
} | undefined>;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a local port has a service running
|
|
13
|
+
* @param host the host to check
|
|
14
|
+
* @param port the port to check
|
|
15
|
+
* @returns true if the port has a service running, false otherwise
|
|
16
|
+
*
|
|
17
|
+
* @beta
|
|
18
|
+
*/
|
|
19
|
+
export declare const isPortActive: (host: string, port: number) => Promise<boolean>;
|
|
11
20
|
//# sourceMappingURL=mqtt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mqtt.d.ts","sourceRoot":"","sources":["../../../src/composables/mqtt.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"mqtt.d.ts","sourceRoot":"","sources":["../../../src/composables/mqtt.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,aAAa,YAAmB,WAAW;;cAwCvD,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,SAAgB,MAAM,QAAQ,MAAM,qBAuC5D,CAAA"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ import SegmentedDisplay from './components/SegmentedDisplay.vue';
|
|
|
23
23
|
import SplitColumn from './components/SplitColumn.vue';
|
|
24
24
|
import ToggleArrow from './components/ToggleArrow.vue';
|
|
25
25
|
import { useMqttStream } from './composables/mqtt';
|
|
26
|
-
export type
|
|
26
|
+
export type * from './types';
|
|
27
27
|
import '../themes/beam.css';
|
|
28
28
|
/**
|
|
29
29
|
* Install all Beam components
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,OAAO,YAAY,MAAM,+BAA+B,CAAA;AACxD,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,OAAO,MAAM,0BAA0B,CAAA;AAC9C,OAAO,cAAc,MAAM,iCAAiC,CAAA;AAC5D,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,gBAAgB,MAAM,mCAAmC,CAAA;AAChE,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,OAAO,YAAY,MAAM,+BAA+B,CAAA;AACxD,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,eAAe,MAAM,kCAAkC,CAAA;AAC9D,OAAO,YAAY,MAAM,+BAA+B,CAAA;AACxD,OAAO,OAAO,MAAM,0BAA0B,CAAA;AAC9C,OAAO,QAAQ,MAAM,2BAA2B,CAAA;AAChD,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,QAAQ,MAAM,2BAA2B,CAAA;AAChD,OAAO,QAAQ,MAAM,2BAA2B,CAAA;AAChD,OAAO,MAAM,MAAM,yBAAyB,CAAA;AAC5C,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,gBAAgB,MAAM,mCAAmC,CAAA;AAChE,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,OAAO,YAAY,MAAM,+BAA+B,CAAA;AACxD,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,OAAO,MAAM,0BAA0B,CAAA;AAC9C,OAAO,cAAc,MAAM,iCAAiC,CAAA;AAC5D,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,gBAAgB,MAAM,mCAAmC,CAAA;AAChE,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,OAAO,YAAY,MAAM,+BAA+B,CAAA;AACxD,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,eAAe,MAAM,kCAAkC,CAAA;AAC9D,OAAO,YAAY,MAAM,+BAA+B,CAAA;AACxD,OAAO,OAAO,MAAM,0BAA0B,CAAA;AAC9C,OAAO,QAAQ,MAAM,2BAA2B,CAAA;AAChD,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,QAAQ,MAAM,2BAA2B,CAAA;AAChD,OAAO,QAAQ,MAAM,2BAA2B,CAAA;AAChD,OAAO,MAAM,MAAM,yBAAyB,CAAA;AAC5C,OAAO,SAAS,MAAM,4BAA4B,CAAA;AAClD,OAAO,gBAAgB,MAAM,mCAAmC,CAAA;AAChE,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,mBAAmB,SAAS,CAAA;AAC5B,OAAO,oBAAoB,CAAA;AAE3B;;;;GAIG;AACH,iBAAS,OAAO,CAAC,GAAG,EAAE,GAAG,QAwBxB;AAED,OAAO,EACN,YAAY,EACZ,SAAS,EACT,OAAO,EACP,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,eAAe,EACf,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,SAAS,EACT,SAAS,EACT,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,OAAO,EACP,aAAa,GACb,CAAA"}
|
|
@@ -1,28 +1,59 @@
|
|
|
1
1
|
import type { IClientOptions } from 'mqtt';
|
|
2
2
|
/**
|
|
3
|
-
* @
|
|
3
|
+
* @public
|
|
4
4
|
*/
|
|
5
5
|
export type ListViewItem = {
|
|
6
|
-
|
|
7
|
-
label: string;
|
|
6
|
+
barcode?: string;
|
|
8
7
|
checked?: boolean;
|
|
9
8
|
count?: {
|
|
10
9
|
count: number;
|
|
11
10
|
of: number;
|
|
12
|
-
uom
|
|
11
|
+
uom?: string;
|
|
13
12
|
};
|
|
14
13
|
date?: string;
|
|
15
14
|
dateFormat?: string;
|
|
16
15
|
debounce?: number;
|
|
16
|
+
description?: string;
|
|
17
|
+
label?: string;
|
|
17
18
|
linkComponent?: string;
|
|
18
19
|
route?: string;
|
|
19
20
|
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
type
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export type BeamColor = RGB | RGBA | HEX | HSL | HSLA | string;
|
|
25
|
+
/**
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export type BeamFilterChoice = {
|
|
29
|
+
label: string;
|
|
30
|
+
value: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* RGB color string representation
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export type RGB = `rgb(${number}, ${number}, ${number})`;
|
|
37
|
+
/**
|
|
38
|
+
* RGBA color string representation
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
export type RGBA = `rgba(${number}, ${number}, ${number}, ${number})`;
|
|
42
|
+
/**
|
|
43
|
+
* HSL color string representation
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export type HSL = `hsl(${number}, ${number}%, ${number}%)`;
|
|
47
|
+
/**
|
|
48
|
+
* HSLA color string representation
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export type HSLA = `hsl(${number}, ${number}%, ${number}%), ${number}`;
|
|
52
|
+
/**
|
|
53
|
+
* HEX color string representation
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export type HEX = `#${string}`;
|
|
26
57
|
/**
|
|
27
58
|
* MQTT stream options
|
|
28
59
|
* @public
|
|
@@ -30,5 +61,4 @@ export type Color = RGB | RGBA | HEX | HSL | HSLA | string;
|
|
|
30
61
|
export interface IMqttStream extends IClientOptions {
|
|
31
62
|
topics?: string[];
|
|
32
63
|
}
|
|
33
|
-
export {};
|
|
34
64
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AAE1C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IAC1B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AAE1C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAA;QACb,EAAE,EAAE,MAAM,CAAA;QACV,GAAG,CAAC,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAID;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,MAAM,CAAA;AAE9D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,GAAG,GAAG,OAAO,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG,CAAA;AAExD;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG,CAAA;AAErE;;;GAGG;AACH,MAAM,MAAM,GAAG,GAAG,OAAO,MAAM,KAAK,MAAM,MAAM,MAAM,IAAI,CAAA;AAE1D;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,MAAM,MAAM,MAAM,OAAO,MAAM,EAAE,CAAA;AAEtE;;;GAGG;AACH,MAAM,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAA;AAE9B;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,cAAc;IAClD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB"}
|
package/package.json
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
<div ref="beam-filters" class="beam_filters" :style="{ height: isOpen ? '100%' : headerHeight }">
|
|
3
3
|
<div ref="beam-filters-header" @click="toggle" class="beam_filters-heading">
|
|
4
4
|
<ToggleArrow :open="isOpen" />
|
|
5
|
-
<BeamHeading>
|
|
5
|
+
<BeamHeading>Filter</BeamHeading>
|
|
6
6
|
</div>
|
|
7
|
+
|
|
7
8
|
<div class="beam_filters-options">
|
|
8
|
-
<slot>
|
|
9
|
-
<p>OPTIONS GO HERE</p>
|
|
10
|
-
</slot>
|
|
9
|
+
<slot></slot>
|
|
11
10
|
</div>
|
|
12
11
|
</div>
|
|
13
12
|
</template>
|
|
@@ -15,6 +14,8 @@
|
|
|
15
14
|
<script setup lang="ts">
|
|
16
15
|
import { ref, onMounted, useTemplateRef } from 'vue'
|
|
17
16
|
|
|
17
|
+
defineSlots<{ default(): any }>()
|
|
18
|
+
|
|
18
19
|
const header = useTemplateRef('beam-filters-header')
|
|
19
20
|
const beamFilters = useTemplateRef('beam-filters')
|
|
20
21
|
|
|
@@ -27,9 +28,11 @@ const toggle = () => {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
onMounted(() => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
if (header.value && beamFilters.value) {
|
|
32
|
+
headerHeight.value = getTotalHeight(header.value)
|
|
33
|
+
totalHeight.value = getTotalHeight(beamFilters.value)
|
|
34
|
+
beamFilters.value.style.height = headerHeight.value
|
|
35
|
+
}
|
|
33
36
|
})
|
|
34
37
|
|
|
35
38
|
const getTotalHeight = (el: HTMLDivElement) => {
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<BeamHeading class="beam_filter-option-heading">{{ title }}</BeamHeading>
|
|
3
|
-
<div @click="
|
|
4
|
-
<div
|
|
3
|
+
<div @click="open = !open" class="beam_filter-option">
|
|
4
|
+
<div class="beam_filter-option-select">
|
|
5
5
|
<div class="beam_filter-arrow">
|
|
6
6
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35.36 70.71">
|
|
7
7
|
<polygon points="0 70.71 0 0 35.36 35.36 0 70.71" />
|
|
8
8
|
</svg>
|
|
9
9
|
</div>
|
|
10
10
|
<div class="beam_filter-label">
|
|
11
|
-
<label>{{
|
|
11
|
+
<label>{{ label }}</label>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
|
+
|
|
14
15
|
<ul ref="menu" v-if="open" class="beam_filter-select-menu">
|
|
15
16
|
<li
|
|
16
|
-
v-for="
|
|
17
|
-
:class="{ selected:
|
|
18
|
-
:data-value="
|
|
19
|
-
:key="
|
|
17
|
+
v-for="choice in choices"
|
|
18
|
+
:class="{ selected: label == choice.label }"
|
|
19
|
+
:data-value="choice.value"
|
|
20
|
+
:key="choice.value"
|
|
20
21
|
class="beam_filter-select-option"
|
|
21
|
-
@click="
|
|
22
|
-
{{
|
|
22
|
+
@click="selectChoice(choice)">
|
|
23
|
+
{{ choice.label }}
|
|
23
24
|
</li>
|
|
24
25
|
</ul>
|
|
25
26
|
</div>
|
|
@@ -28,27 +29,25 @@
|
|
|
28
29
|
<script setup lang="ts">
|
|
29
30
|
import { ref } from 'vue'
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
import { BeamFilterChoice } from '../types'
|
|
33
|
+
|
|
34
|
+
const emit = defineEmits<{
|
|
35
|
+
select: [choice: BeamFilterChoice]
|
|
36
|
+
}>()
|
|
35
37
|
|
|
36
38
|
const { title = 'title', choices = [] } = defineProps<{
|
|
37
|
-
choices:
|
|
39
|
+
choices: BeamFilterChoice[]
|
|
38
40
|
title?: string
|
|
39
41
|
}>()
|
|
40
42
|
|
|
41
43
|
const open = ref(false)
|
|
44
|
+
const label = ref(choices[0].label)
|
|
42
45
|
const value = ref(choices[0].value)
|
|
43
|
-
const choice = ref(choices[0].choice)
|
|
44
46
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
+
const selectChoice = (data: BeamFilterChoice) => {
|
|
48
|
+
label.value = data.label
|
|
47
49
|
value.value = data.value
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const toggle = () => {
|
|
51
|
-
open.value = !open.value
|
|
50
|
+
emit('select', data)
|
|
52
51
|
}
|
|
53
52
|
</script>
|
|
54
53
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<ul class="beam_list-view">
|
|
3
|
-
<li v-for="item in items" :key="item.label">
|
|
3
|
+
<li v-for="item in items" :key="item.barcode || item.label">
|
|
4
4
|
<template v-if="item.linkComponent == 'BeamDayDivider'">
|
|
5
5
|
<BeamDayDivider :item="item"></BeamDayDivider>
|
|
6
6
|
</template>
|
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
<h1 class="segmented-display-output" :style="{ color: getColor(textColor) }">{{ getOutput }}</h1>
|
|
4
4
|
</div>
|
|
5
5
|
</template>
|
|
6
|
+
|
|
6
7
|
<script setup lang="ts">
|
|
7
|
-
import {
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
|
|
10
|
+
import { BeamColor } from '../types'
|
|
8
11
|
|
|
9
12
|
const {
|
|
10
13
|
displayInput = 120.2568,
|
|
@@ -14,16 +17,16 @@ const {
|
|
|
14
17
|
} = defineProps<{
|
|
15
18
|
displayInput?: number
|
|
16
19
|
decimalPlaces?: number
|
|
17
|
-
displayColor?:
|
|
18
|
-
textColor?:
|
|
20
|
+
displayColor?: BeamColor
|
|
21
|
+
textColor?: BeamColor
|
|
19
22
|
}>()
|
|
20
23
|
|
|
21
24
|
const getOutput = computed(() => {
|
|
22
|
-
if (displayInput
|
|
25
|
+
if (displayInput === 0) return Number(0).toFixed(decimalPlaces)
|
|
23
26
|
return displayInput.toFixed(decimalPlaces)
|
|
24
27
|
})
|
|
25
28
|
|
|
26
|
-
const getColor = color => {
|
|
29
|
+
const getColor = (color: BeamColor) => {
|
|
27
30
|
return color.substr(0, 2) == '--' ? `var(${color})` : color
|
|
28
31
|
}
|
|
29
32
|
</script>
|
package/src/composables/mqtt.ts
CHANGED
|
@@ -9,7 +9,14 @@ import { IMqttStream } from '../types'
|
|
|
9
9
|
* @returns MQTT stream messages
|
|
10
10
|
* @beta
|
|
11
11
|
*/
|
|
12
|
-
export const useMqttStream = (options: IMqttStream) => {
|
|
12
|
+
export const useMqttStream = async (options: IMqttStream) => {
|
|
13
|
+
if (options.host && options.port) {
|
|
14
|
+
const portActive = await isPortActive(options.host, options.port)
|
|
15
|
+
if (!portActive) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
const client = ref<MqttClient>()
|
|
14
21
|
const messages = ref<Record<string, string[]>>({})
|
|
15
22
|
|
|
@@ -43,3 +50,52 @@ export const useMqttStream = (options: IMqttStream) => {
|
|
|
43
50
|
|
|
44
51
|
return { messages }
|
|
45
52
|
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if a local port has a service running
|
|
56
|
+
* @param host the host to check
|
|
57
|
+
* @param port the port to check
|
|
58
|
+
* @returns true if the port has a service running, false otherwise
|
|
59
|
+
*
|
|
60
|
+
* @beta
|
|
61
|
+
*/
|
|
62
|
+
export const isPortActive = async (host: string, port: number) => {
|
|
63
|
+
try {
|
|
64
|
+
const controller = new AbortController()
|
|
65
|
+
// Set a timeout of 2 seconds
|
|
66
|
+
const timeoutId = setTimeout(() => controller.abort(), 2000)
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
await fetch(`${host}:${port}`, {
|
|
70
|
+
mode: 'no-cors', // This allows checking without CORS issues
|
|
71
|
+
signal: controller.signal,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
clearTimeout(timeoutId)
|
|
75
|
+
// If we get any response, the port is in use
|
|
76
|
+
return true
|
|
77
|
+
} catch (error) {
|
|
78
|
+
clearTimeout(timeoutId)
|
|
79
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
80
|
+
// Timeout - port is probably not in use
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// For connection refused errors, we need to check the error message
|
|
85
|
+
// as different browsers handle this differently
|
|
86
|
+
const errorString = String(error)
|
|
87
|
+
if (
|
|
88
|
+
errorString.includes('NetworkError') ||
|
|
89
|
+
errorString.includes('Failed to fetch') ||
|
|
90
|
+
errorString.includes('net::ERR_CONNECTION_REFUSED')
|
|
91
|
+
) {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// If we get here, there might be something running on the port
|
|
96
|
+
return true
|
|
97
|
+
}
|
|
98
|
+
} catch (error) {
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -24,7 +24,7 @@ import SegmentedDisplay from './components/SegmentedDisplay.vue'
|
|
|
24
24
|
import SplitColumn from './components/SplitColumn.vue'
|
|
25
25
|
import ToggleArrow from './components/ToggleArrow.vue'
|
|
26
26
|
import { useMqttStream } from './composables/mqtt'
|
|
27
|
-
export type
|
|
27
|
+
export type * from './types'
|
|
28
28
|
import '../themes/beam.css'
|
|
29
29
|
|
|
30
30
|
/**
|
package/src/types/index.ts
CHANGED
|
@@ -1,32 +1,70 @@
|
|
|
1
1
|
import type { IClientOptions } from 'mqtt'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @
|
|
4
|
+
* @public
|
|
5
5
|
*/
|
|
6
6
|
export type ListViewItem = {
|
|
7
|
-
|
|
8
|
-
label: string
|
|
9
|
-
|
|
7
|
+
barcode?: string
|
|
10
8
|
checked?: boolean
|
|
11
9
|
count?: {
|
|
12
10
|
count: number
|
|
13
11
|
of: number
|
|
14
|
-
uom
|
|
12
|
+
uom?: string
|
|
15
13
|
}
|
|
16
14
|
date?: string
|
|
17
15
|
dateFormat?: string
|
|
18
16
|
debounce?: number
|
|
17
|
+
description?: string
|
|
18
|
+
label?: string
|
|
19
19
|
linkComponent?: string
|
|
20
20
|
route?: string
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
// TODO: the `string` at the end should be replaced by `DataType.Color`
|
|
24
|
+
// in the `csstype` lib but import seems to be missing
|
|
25
|
+
/**
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export type BeamColor = RGB | RGBA | HEX | HSL | HSLA | string
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export type BeamFilterChoice = {
|
|
34
|
+
label: string
|
|
35
|
+
value: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* RGB color string representation
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
export type RGB = `rgb(${number}, ${number}, ${number})`
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* RGBA color string representation
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
export type RGBA = `rgba(${number}, ${number}, ${number}, ${number})`
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* HSL color string representation
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
export type HSL = `hsl(${number}, ${number}%, ${number}%)`
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* HSLA color string representation
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
export type HSLA = `hsl(${number}, ${number}%, ${number}%), ${number}`
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* HEX color string representation
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
export type HEX = `#${string}`
|
|
28
67
|
|
|
29
|
-
export type Color = RGB | RGBA | HEX | HSL | HSLA | string
|
|
30
68
|
/**
|
|
31
69
|
* MQTT stream options
|
|
32
70
|
* @public
|