@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.
@@ -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,YAAa,WAAW;;CAiCjD,CAAA"}
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"}
@@ -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 { IMqttStream, ListViewItem } from './types';
26
+ export type * from './types';
27
27
  import '../themes/beam.css';
28
28
  /**
29
29
  * Install all Beam components
@@ -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,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACxD,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
+ {"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
- * @beta
3
+ * @public
4
4
  */
5
5
  export type ListViewItem = {
6
- description: string;
7
- label: string;
6
+ barcode?: string;
8
7
  checked?: boolean;
9
8
  count?: {
10
9
  count: number;
11
10
  of: number;
12
- uom: string;
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
- type RGB = `rgb(${number}, ${number}, ${number})`;
21
- type HSL = `hsl(${number}, ${number}%, ${number}%)`;
22
- type HSLA = `hsl(${number}, ${number}%, ${number}%), ${number}`;
23
- type RGBA = `rgba(${number}, ${number}, ${number}, ${number})`;
24
- type HEX = `#${string}`;
25
- export type Color = RGB | RGBA | HEX | HSL | HSLA | string;
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,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IAEb,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAA;QACb,EAAE,EAAE,MAAM,CAAA;QACV,GAAG,EAAE,MAAM,CAAA;KACX,CAAA;IACD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,GAAG,GAAG,OAAO,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG,CAAA;AACjD,KAAK,GAAG,GAAG,OAAO,MAAM,KAAK,MAAM,MAAM,MAAM,IAAI,CAAA;AACnD,KAAK,IAAI,GAAG,OAAO,MAAM,KAAK,MAAM,MAAM,MAAM,OAAO,MAAM,EAAE,CAAA;AAC/D,KAAK,IAAI,GAAG,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG,CAAA;AAC9D,KAAK,GAAG,GAAG,IAAI,MAAM,EAAE,CAAA;AAEvB,MAAM,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,MAAM,CAAA;AAC1D;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,cAAc;IAClD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/beam",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": {
@@ -7,7 +7,7 @@
7
7
  </template>
8
8
 
9
9
  <script setup lang="ts">
10
- import { defineProps, computed } from 'vue'
10
+ import { computed } from 'vue'
11
11
 
12
12
  import type { ListViewItem } from '../types'
13
13
 
@@ -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> Filter </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
- headerHeight.value = getTotalHeight(header.value)
31
- totalHeight.value = getTotalHeight(beamFilters.value)
32
- beamFilters.value.style.height = headerHeight.value
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="toggle" class="beam_filter-option">
4
- <div ref="select" class="beam_filter-option-select">
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>{{ choice }}</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="(opt, index) in choices"
17
- :class="{ selected: choice == opt.choice }"
18
- :data-value="opt.value"
19
- :key="index"
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="updateValue(opt)">
22
- {{ opt.choice }}
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
- type Choice = {
32
- choice: string
33
- value: string
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: Choice[]
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 updateValue = (data: Choice) => {
46
- choice.value = data.choice
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 { ref, defineProps, computed } from 'vue'
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?: Color
18
- textColor?: Color
20
+ displayColor?: BeamColor
21
+ textColor?: BeamColor
19
22
  }>()
20
23
 
21
24
  const getOutput = computed(() => {
22
- if (displayInput.length == 0) return Number(0).toFixed(decimalPlaces)
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>
@@ -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 { IMqttStream, ListViewItem } from './types'
27
+ export type * from './types'
28
28
  import '../themes/beam.css'
29
29
 
30
30
  /**
@@ -1,32 +1,70 @@
1
1
  import type { IClientOptions } from 'mqtt'
2
2
 
3
3
  /**
4
- * @beta
4
+ * @public
5
5
  */
6
6
  export type ListViewItem = {
7
- description: string
8
- label: string
9
-
7
+ barcode?: string
10
8
  checked?: boolean
11
9
  count?: {
12
10
  count: number
13
11
  of: number
14
- uom: string
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
- type RGB = `rgb(${number}, ${number}, ${number})`
24
- type HSL = `hsl(${number}, ${number}%, ${number}%)`
25
- type HSLA = `hsl(${number}, ${number}%, ${number}%), ${number}`
26
- type RGBA = `rgba(${number}, ${number}, ${number}, ${number})`
27
- type HEX = `#${string}`
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