poe-svelte-ui-lib 1.82.1 → 1.83.1

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 (40) hide show
  1. package/dist/Accordion/AccordionProps.svelte +9 -13
  2. package/dist/Button/ButtonProps.svelte +18 -22
  3. package/dist/CommonSnippets.svelte +1 -1
  4. package/dist/CommonSnippets.svelte.d.ts +1 -1
  5. package/dist/Divider/DividerProps.svelte +2 -2
  6. package/dist/FileAttach/FileAttachProps.svelte +13 -13
  7. package/dist/Graph/GraphProps.svelte +5 -9
  8. package/dist/Input/InputProps.svelte +25 -25
  9. package/dist/Joystick/JoystickProps.svelte +5 -9
  10. package/dist/PeriodChart/PeriodChartProps.svelte +3 -3
  11. package/dist/ProgressBar/ProgressBarProps.svelte +22 -17
  12. package/dist/PropsListModal.svelte +1 -1
  13. package/dist/Select/SelectProps.svelte +23 -24
  14. package/dist/Slider/SliderProps.svelte +5 -11
  15. package/dist/Switch/SwitchProps.svelte +17 -21
  16. package/dist/Table/TableProps.svelte +72 -57
  17. package/dist/Tabs/TabsProps.svelte +14 -14
  18. package/dist/TextField/TextFieldProps.svelte +11 -19
  19. package/dist/VideoViewer/VideoViewerProps.svelte +2 -2
  20. package/dist/Widget/WidgetProps.svelte +12 -14
  21. package/dist/WidgetDeviceInfo/README.md +10 -10
  22. package/dist/WidgetDeviceInfo/WidgetDeviceInfo.svelte +38 -6
  23. package/dist/WidgetDeviceInfo/WidgetDeviceInfoProps.svelte +5 -2
  24. package/dist/WidgetFileSystem/WidgetFileSystemProps.svelte +5 -2
  25. package/dist/WidgetMap/WidgetMapProps.svelte +5 -2
  26. package/dist/WidgetMap/mapWrapper/Line.svelte +1 -1
  27. package/dist/WidgetMap/mapWrapper/MapLibre.svelte +1 -0
  28. package/dist/WidgetMap/mapWrapper/contexts.svelte.d.ts +1 -0
  29. package/dist/WidgetMap/mapWrapper/utils.js +9 -24
  30. package/dist/WidgetPFD/WidgetPFDProps.svelte +5 -2
  31. package/dist/WidgetRGBStrip/WidgetRGBStripProps.svelte +5 -2
  32. package/dist/WidgetStackInfo/WidgetStackInfoProps.svelte +5 -2
  33. package/dist/WidgetWiFi/WidgetWiFi.svelte +31 -27
  34. package/dist/WidgetWiFi/WidgetWiFiProps.svelte +5 -2
  35. package/dist/index.js +0 -1
  36. package/dist/locales/translations.js +17 -13
  37. package/dist/protocols/cbor/json.js +0 -1
  38. package/dist/types.d.ts +3 -0
  39. package/dist/types.js +5 -0
  40. package/package.json +20 -20
@@ -1,7 +1,7 @@
1
1
  <!-- $lib/ElementsUI/AccordionProps.svelte -->
2
2
  <script lang="ts">
3
3
  import { T } from "../locales/i18n"
4
- import { updateProperty, type IAccordionProps, type IUIComponentHandler, type UIComponent } from "../types"
4
+ import { findOptionByClass, updateProperty, type IAccordionProps, type IUIComponentHandler, type UIComponent } from "../types"
5
5
  import * as UI from ".."
6
6
  import { optionsStore } from "../options"
7
7
  import { ICONS } from "../icons"
@@ -15,17 +15,13 @@
15
15
  component,
16
16
  onPropertyChange,
17
17
  forConstructor = true,
18
- } = $props<{
18
+ }: {
19
19
  component: UIComponent & { properties: Partial<IAccordionProps> }
20
20
  onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string; eventHandler?: IUIComponentHandler }>) => void
21
21
  forConstructor?: boolean
22
- }>()
22
+ } = $props()
23
23
 
24
- const initialAlign = $derived(
25
- $optionsStore.JUSTIFY_ALIGN_OPTIONS.find((a) =>
26
- (a.value as string).includes(component.properties.label?.class?.split(" ").find((cls: string) => cls.startsWith("justify-"))),
27
- ),
28
- )
24
+ const initialAlign = $derived(findOptionByClass($optionsStore.JUSTIFY_ALIGN_OPTIONS, component.properties.label?.class, "justify-"))
29
25
 
30
26
  const handleImageUpload = (event: Event) => {
31
27
  const input = event.target as HTMLInputElement
@@ -69,14 +65,14 @@
69
65
  <div class="flex w-full gap-4">
70
66
  <UI.Input
71
67
  label={{ name: $T("constructor.props.size.height") }}
72
- value={component.properties.size.height}
68
+ value={component.properties.size?.height}
73
69
  onUpdate={(value) => updateProperty("size.height", value as number, component, onPropertyChange)}
74
70
  number={{ minNum: 1, maxNum: 1000, step: 1 }}
75
71
  type="number"
76
72
  />
77
73
  <UI.Input
78
74
  label={{ name: $T("constructor.props.size.width") }}
79
- value={component.properties.size.width}
75
+ value={component.properties.size?.width}
80
76
  onUpdate={(value) => updateProperty("size.width", value as number, component, onPropertyChange)}
81
77
  number={{ minNum: 1, maxNum: 1000, step: 1 }}
82
78
  type="number"
@@ -87,7 +83,7 @@
87
83
  {#snippet AccordionIsOpen()}
88
84
  <UI.Switch
89
85
  label={{ name: $T("constructor.props.open") }}
90
- value={component.properties.isOpen}
86
+ value={component.properties.isOpen ? 1 : 0}
91
87
  options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
92
88
  onChange={(value) => updateProperty("isOpen", value === 1, component, onPropertyChange)}
93
89
  />
@@ -105,7 +101,7 @@
105
101
  snippet="IconsLib"
106
102
  initialValue={{
107
103
  name: $T("constructor.props.labelicon"),
108
- icon: component.properties.label.icon,
104
+ icon: component.properties.label?.icon,
109
105
  updateProperty: (icon: string) => updateProperty("label.icon", icon as string, component, onPropertyChange),
110
106
  icons: { array: ICONS },
111
107
  }}
@@ -137,7 +133,7 @@
137
133
  initialValue={{
138
134
  name: $T("constructor.props.labelicon"),
139
135
  icons: { array: ICONS },
140
- icon: component.properties.label.icon,
136
+ icon: component.properties.label?.icon,
141
137
  updateProperty: (icon: string) => updateProperty("label.icon", icon as string, component, onPropertyChange),
142
138
  }}
143
139
  {component}
@@ -4,7 +4,7 @@
4
4
  import { localizeText } from "../locales/localize"
5
5
  import { DEFAULT_LANGUAGE } from "../locales/languages"
6
6
  import { T } from "../locales/i18n"
7
- import { type UIComponent, type IButtonProps, type IOption, updateProperty, type IUIComponentHandler } from "../types"
7
+ import { type UIComponent, type IButtonProps, type IOption, updateProperty, findOptionByClass, type IUIComponentHandler } from "../types"
8
8
  import * as UI from ".."
9
9
  import { optionsStore, findColorOption } from "../options"
10
10
  import { twMerge } from "tailwind-merge"
@@ -17,37 +17,33 @@
17
17
  component,
18
18
  onPropertyChange,
19
19
  forConstructor = true,
20
- } = $props<{
20
+ }: {
21
21
  component: UIComponent & { properties: Partial<IButtonProps> }
22
22
  onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string; eventHandler?: IUIComponentHandler }>) => void
23
23
  forConstructor?: boolean
24
- }>()
24
+ } = $props()
25
25
 
26
26
  /* Argument пуст — поле ниже лишь визуально показывает "ModCfg", реальное значение нужно проставить в состояние */
27
27
  $effect(() => {
28
- if (!component.eventHandler.Argument) onPropertyChange({ eventHandler: { Argument: "ModCfg" } })
28
+ if (!component.eventHandler?.Argument) onPropertyChange({ eventHandler: { Argument: "ModCfg" } })
29
29
  })
30
30
 
31
- let hasValue: boolean = $derived(component.eventHandler.Value)
31
+ let hasValue: boolean = $derived(!!component.eventHandler?.Value)
32
32
 
33
33
  let Header: IOption = $derived(
34
- $optionsStore.HEADER_OPTIONS.find((h) => h.value === component.eventHandler.Header) ?? { id: "", name: "", value: "", class: "!w-1/4" },
34
+ $optionsStore.HEADER_OPTIONS.find((h) => h.value === component.eventHandler?.Header) ?? { id: "", name: "", value: "", class: "!w-1/4" },
35
35
  )
36
36
 
37
37
  const initialColor = $derived(findColorOption($optionsStore.COLOR_OPTIONS, component.properties.componentClass))
38
38
 
39
- const initialHeight = $derived(
40
- $optionsStore.HEIGHT_OPTIONS.find((h) =>
41
- (h.value as string).includes(component.properties.componentClass?.split(" ").find((cls: string) => cls.startsWith("py-"))),
42
- ),
43
- )
39
+ const initialHeight = $derived(findOptionByClass($optionsStore.HEIGHT_OPTIONS, component.properties.componentClass, "py-"))
44
40
  const updateIconProperty = (propertyName: string, value: string) => {
45
41
  updateProperty(propertyName, value, component, onPropertyChange)
46
- if (component.properties.content.icon && !localizeText(component.properties.content.name, DEFAULT_LANGUAGE).trim())
42
+ if (component.properties.content?.icon && !localizeText(component.properties.content?.name, DEFAULT_LANGUAGE).trim())
47
43
  updateProperty("componentClass", twMerge((component.properties as UI.IButtonProps).componentClass, "w-fit p-2"), component, onPropertyChange)
48
44
  else if (
49
- (component.properties.content.icon && localizeText(component.properties.content.name, DEFAULT_LANGUAGE).trim()) ||
50
- (!component.properties.content.icon && !localizeText(component.properties.content.name, DEFAULT_LANGUAGE).trim())
45
+ (component.properties.content?.icon && localizeText(component.properties.content?.name, DEFAULT_LANGUAGE).trim()) ||
46
+ (!component.properties.content?.icon && !localizeText(component.properties.content?.name, DEFAULT_LANGUAGE).trim())
51
47
  )
52
48
  updateProperty("componentClass", twMerge((component.properties as UI.IButtonProps).componentClass, "w-full px-1 py-1"), component, onPropertyChange)
53
49
  }
@@ -75,7 +71,7 @@
75
71
  />
76
72
  <UI.Input
77
73
  label={{ name: $T("constructor.props.argument") }}
78
- value={component.eventHandler.Argument || "ModCfg"}
74
+ value={component.eventHandler?.Argument || "ModCfg"}
79
75
  maxlength={32}
80
76
  help={{ info: $T("constructor.props.argument.info"), autocomplete: "on", regExp: /^[a-zA-Z0-9\-_]{0,32}$/ }}
81
77
  onUpdate={(value) => onPropertyChange({ eventHandler: { Argument: value as string } })}
@@ -83,10 +79,10 @@
83
79
  {/snippet}
84
80
 
85
81
  {#snippet ButtonVariables()}
86
- {#if component.eventHandler.Argument !== "ModCfg" || Header.value === "SET"}
82
+ {#if component.eventHandler?.Argument !== "ModCfg" || Header.value === "SET"}
87
83
  <UI.Input
88
84
  label={{ name: $T("constructor.props.value") }}
89
- value={component.eventHandler.Value}
85
+ value={component.eventHandler?.Value}
90
86
  help={{ info: $T("constructor.props.value.info") }}
91
87
  maxlength={500}
92
88
  onUpdate={(value) => onPropertyChange({ eventHandler: { Value: value as string } })}
@@ -95,7 +91,7 @@
95
91
  <UI.Input
96
92
  label={{ name: $T("constructor.props.variables") }}
97
93
  disabled={hasValue}
98
- value={component.eventHandler.Variables.join(" ")}
94
+ value={component.eventHandler?.Variables?.join(" ")}
99
95
  help={{ info: $T("constructor.props.variables.info"), autocomplete: "on", regExp: /^[a-zA-Z0-9.\-_ ":{}]{0,500}$/ }}
100
96
  maxlength={500}
101
97
  onUpdate={(value) => onPropertyChange({ eventHandler: { Variables: (value as string).trim().split(/\s+/) } })}
@@ -107,7 +103,7 @@
107
103
  {/snippet}
108
104
 
109
105
  {#snippet ButtonHeight()}
110
- {#if !(!localizeText(component.properties.content.name, DEFAULT_LANGUAGE).trim() && component.properties.content.icon)}
106
+ {#if !(!localizeText(component.properties.content?.name, DEFAULT_LANGUAGE).trim() && component.properties.content?.icon)}
111
107
  <UI.Select
112
108
  label={{ name: $T("constructor.props.height") }}
113
109
  type="buttons"
@@ -124,7 +120,7 @@
124
120
  label={{ name: $T("constructor.props.info.side") }}
125
121
  type="buttons"
126
122
  options={$optionsStore.INFO_SIDE_OPTIONS}
127
- value={$optionsStore.INFO_SIDE_OPTIONS.find((h) => h.value === component.properties.content.info.side)}
123
+ value={$optionsStore.INFO_SIDE_OPTIONS.find((h) => h.value === component.properties.content?.info?.side)}
128
124
  onUpdate={(option) => updateProperty("content.info.side", (option as IOption<string>).value as string, component, onPropertyChange)}
129
125
  />
130
126
  {/snippet}
@@ -168,7 +164,7 @@
168
164
  snippet="IconsLib"
169
165
  initialValue={{
170
166
  name: $T("constructor.props.buttonIcon"),
171
- icon: component.properties.content.icon,
167
+ icon: component.properties.content?.icon,
172
168
  updateProperty: (icon: string) => updateIconProperty("content.icon", icon as string),
173
169
  icons: { array: ICONS },
174
170
  }}
@@ -197,7 +193,7 @@
197
193
  snippet="IconsLib"
198
194
  initialValue={{
199
195
  name: $T("constructor.props.buttonIcon"),
200
- icon: component.properties.content.icon,
196
+ icon: component.properties.content?.icon,
201
197
  updateProperty: (icon: string) => updateIconProperty("content.icon", icon as string),
202
198
  icons: { array: ICONS },
203
199
  }}
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import * as UI from "./"
2
+ import * as UI from "./index"
3
3
  import { T } from "./locales/i18n"
4
4
  import CrossIcon from "./libIcons/CrossIcon.svelte"
5
5
  import { optionsStore } from "./options"
@@ -1,4 +1,4 @@
1
- import * as UI from "./";
1
+ import * as UI from "./index";
2
2
  type snippetNames = "Variable" | "Access" | "Colors" | "Label" | "LabelAlign" | "LabelClass" | "Identificator" | "WrapperClass" | "Disabled" | "EventHandlerArgument" | "IconsLib" | "Readonly" | "BitModeInfo" | "MinMaxStep" | "";
3
3
  type $$ComponentProps = {
4
4
  snippet: snippetNames;
@@ -11,11 +11,11 @@
11
11
  component,
12
12
  onPropertyChange,
13
13
  forConstructor = true,
14
- } = $props<{
14
+ }: {
15
15
  component: UIComponent & { properties: Partial<IDividerProps> }
16
16
  onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string; eventHandler?: IUIComponentHandler }>) => void
17
17
  forConstructor?: boolean
18
- }>()
18
+ } = $props()
19
19
 
20
20
  let currentType = $derived($optionsStore.DIVIDER_TYPE_OPTIONS.find((t) => t.value === component.properties.type))
21
21
  let currentAnchor = $derived($optionsStore.DIVIDER_ANCHOR_OPTIONS.find((a) => a.value === component.properties.anchor))
@@ -1,7 +1,7 @@
1
1
  <!-- $lib/ElementsUI/ButtonProps.svelte -->
2
2
  <script lang="ts">
3
3
  import { T } from "../locales/i18n"
4
- import { type IFileAttachProps, type IUIComponentHandler, type UIComponent, updateProperty } from "../types"
4
+ import { type IFileAttachProps, type IUIComponentHandler, type UIComponent, updateProperty, findOptionByClass } from "../types"
5
5
  import * as UI from ".."
6
6
  import { optionsStore } from "../options"
7
7
  import { getContext } from "svelte"
@@ -13,20 +13,16 @@
13
13
  component,
14
14
  onPropertyChange,
15
15
  forConstructor = true,
16
- } = $props<{
16
+ }: {
17
17
  component: UIComponent & { properties: Partial<IFileAttachProps> }
18
18
  onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string; eventHandler?: IUIComponentHandler }>) => void
19
19
  forConstructor?: boolean
20
- }>()
20
+ } = $props()
21
21
 
22
22
  const DeviceVariables = getContext<{ id: string; value: string; name: string }[]>("DeviceVariables")
23
23
  let VARIABLE_OPTIONS = $derived(DeviceVariables && Array.isArray(DeviceVariables) ? DeviceVariables : [])
24
24
 
25
- const initialAlign = $derived(
26
- $optionsStore.TEXT_ALIGN_OPTIONS.find((a) =>
27
- (a.value as string).includes(component.properties.label?.class?.split(" ").find((cls: string) => cls.startsWith("text-"))),
28
- ),
29
- )
25
+ const initialAlign = $derived(findOptionByClass($optionsStore.TEXT_ALIGN_OPTIONS, component.properties.label?.class, "text-"))
30
26
  </script>
31
27
 
32
28
  {#snippet FileAccept()}
@@ -42,7 +38,7 @@
42
38
  <UI.Select
43
39
  label={{ name: $T("constructor.props.type") }}
44
40
  type="buttons"
45
- value={$optionsStore.FILE_ATTACH_TYPE_OPTIONS.find((c) => (c.value as string).includes(component.properties.type))}
41
+ value={$optionsStore.FILE_ATTACH_TYPE_OPTIONS.find((c) => !!component.properties.type && (c.value as string).includes(component.properties.type))}
46
42
  options={$optionsStore.FILE_ATTACH_TYPE_OPTIONS}
47
43
  onUpdate={(option) => updateProperty("type", (option as UI.IOption).value as string, component, onPropertyChange)}
48
44
  />
@@ -52,13 +48,13 @@
52
48
  <UI.Input
53
49
  label={{ name: $T("constructor.props.imageSize.height") }}
54
50
  type="number"
55
- value={component.properties.imageSize.height.replace("rem", "")}
51
+ value={component.properties.imageSize?.height?.replace("rem", "")}
56
52
  onUpdate={(value) => updateProperty("imageSize.height", `${value as string}rem`, component, onPropertyChange)}
57
53
  />
58
54
  <UI.Input
59
55
  label={{ name: $T("constructor.props.imageSize.width") }}
60
56
  type="number"
61
- value={component.properties.imageSize.width.replace("rem", "")}
57
+ value={component.properties.imageSize?.width?.replace("rem", "")}
62
58
  onUpdate={(value) => updateProperty("imageSize.width", `${value as string}rem`, component, onPropertyChange)}
63
59
  />
64
60
  </div>
@@ -66,14 +62,18 @@
66
62
  <UI.Select
67
63
  label={{ name: $T("constructor.props.fitmode") }}
68
64
  type="buttons"
69
- value={$optionsStore.FITMODE_OPTIONS.find((c) => (c.value as string).includes(component.properties.imageSize.fitMode))}
65
+ value={$optionsStore.FITMODE_OPTIONS.find(
66
+ (c) => !!component.properties.imageSize?.fitMode && (c.value as string).includes(component.properties.imageSize?.fitMode),
67
+ )}
70
68
  options={$optionsStore.FITMODE_OPTIONS}
71
69
  onUpdate={(option) => updateProperty("imageSize.fitMode", (option as UI.IOption).value as string, component, onPropertyChange)}
72
70
  />
73
71
  <UI.Select
74
72
  label={{ name: $T("constructor.props.form") }}
75
73
  type="buttons"
76
- value={$optionsStore.FORM_OPTIONS.find((c) => (c.value as string).includes(component.properties.imageSize.form))}
74
+ value={$optionsStore.FORM_OPTIONS.find(
75
+ (c) => !!component.properties.imageSize?.form && (c.value as string).includes(component.properties.imageSize?.form),
76
+ )}
77
77
  options={$optionsStore.FORM_OPTIONS}
78
78
  onUpdate={(option) => updateProperty("imageSize.form", (option as UI.IOption).value as string, component, onPropertyChange)}
79
79
  />
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { getContext } from "svelte"
3
3
  import { T } from "../locales/i18n"
4
- import { type UIComponent, type IGraphProps, type IOption, updateProperty, type IUIComponentHandler } from "../types"
4
+ import { type UIComponent, type IGraphProps, type IOption, updateProperty, findOptionByClass, type IUIComponentHandler } from "../types"
5
5
  import * as UI from ".."
6
6
  import { optionsStore } from "../options"
7
7
  import { twMerge } from "tailwind-merge"
@@ -13,27 +13,23 @@
13
13
  component,
14
14
  onPropertyChange,
15
15
  forConstructor = true,
16
- } = $props<{
16
+ }: {
17
17
  component: UIComponent & { properties: Partial<IGraphProps> }
18
18
  onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string; eventHandler?: IUIComponentHandler }>) => void
19
19
  forConstructor?: boolean
20
- }>()
20
+ } = $props()
21
21
 
22
22
  const DeviceVariables = getContext<{ id: string; value: string; name: string }[]>("DeviceVariables")
23
23
  let VARIABLE_OPTIONS = $derived(DeviceVariables && Array.isArray(DeviceVariables) ? DeviceVariables : [])
24
24
 
25
- const initialAlign = $derived(
26
- $optionsStore.TEXT_ALIGN_OPTIONS.find((a) =>
27
- (a.value as string).includes(component.properties.label?.class?.split(" ").find((cls: string) => cls.startsWith("text-"))),
28
- ),
29
- )
25
+ const initialAlign = $derived(findOptionByClass($optionsStore.TEXT_ALIGN_OPTIONS, component.properties.label?.class, "text-"))
30
26
  </script>
31
27
 
32
28
  {#snippet GraphIsTest()}
33
29
  <UI.Switch
34
30
  wrapperClass="bg-blue"
35
31
  label={{ name: $T("constructor.props.istest") }}
36
- value={component.properties.isTest}
32
+ value={component.properties.isTest ? 1 : 0}
37
33
  options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
38
34
  onChange={(value) => updateProperty("isTest", value === 1, component, onPropertyChange)}
39
35
  />
@@ -5,6 +5,7 @@
5
5
  import translations from "../locales/translations"
6
6
  import { DEFAULT_LANGUAGE, LANGUAGE_CODES } from "../locales/languages"
7
7
  import type { IInputProps, UIComponent, IOption, IUIComponentHandler } from "../types"
8
+ import { findOptionByClass } from "../types"
8
9
  import * as UI from ".."
9
10
  import { optionsStore, findColorOption } from "../options"
10
11
  import { twMerge } from "tailwind-merge"
@@ -16,11 +17,11 @@
16
17
  component,
17
18
  onPropertyChange,
18
19
  forConstructor = true,
19
- } = $props<{
20
+ }: {
20
21
  component: UIComponent & { properties: Partial<IInputProps> }
21
22
  onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string; eventHandler?: IUIComponentHandler }>) => void
22
23
  forConstructor?: boolean
23
- }>()
24
+ } = $props()
24
25
 
25
26
  let isValidRegExp = $state(true)
26
27
  let showRegExpLibrary = $state(false)
@@ -29,11 +30,7 @@
29
30
 
30
31
  const initialColor = $derived(findColorOption($optionsStore.COLOR_OPTIONS, component.properties.componentClass))
31
32
 
32
- const initialAlign = $derived(
33
- $optionsStore.TEXT_ALIGN_OPTIONS.find((a) =>
34
- (a.value as string).includes(component.properties.label?.class?.split(" ").find((cls: string) => cls.startsWith("text-"))),
35
- ),
36
- )
33
+ const initialAlign = $derived(findOptionByClass($optionsStore.TEXT_ALIGN_OPTIONS, component.properties.label?.class, "text-"))
37
34
 
38
35
  /* Обновление свойства */
39
36
  /* Подсказка битового режима «Максимальное число: N» сразу на всех языках — иначе записалась бы на языке интерфейса конструктора */
@@ -43,6 +40,9 @@
43
40
  return Object.fromEntries(LANGUAGE_CODES.map((lang) => [lang, `${row[lang] || row[DEFAULT_LANGUAGE]}: ${max}`]))
44
41
  }
45
42
 
43
+ /* Диапазон битов поля bitMode; без range в свойствах — один нулевой бит */
44
+ const bitRange = $derived(component.properties.range ?? { start: 0, end: 0 })
45
+
46
46
  const updateProperty = (path: string, value: string | object | boolean | number | RegExp) => {
47
47
  const newProperties = JSON.parse(JSON.stringify(component.properties))
48
48
  if (path === "regExp") {
@@ -116,7 +116,7 @@
116
116
  type="buttons"
117
117
  options={$optionsStore.ACCESS_OPTION}
118
118
  value={$optionsStore.ACCESS_OPTION.find((o) => o.value === component.access)}
119
- onUpdate={(option) => onPropertyChange({ access: (option as IOption).value })}
119
+ onUpdate={(option) => onPropertyChange({ access: (option as IOption).value as string })}
120
120
  />
121
121
  {/snippet}
122
122
 
@@ -130,7 +130,7 @@
130
130
  type="buttons"
131
131
  value={initialAlign}
132
132
  options={$optionsStore.TEXT_ALIGN_OPTIONS}
133
- onUpdate={(option) => updateProperty("label.class", twMerge(component.properties.label.class, (option as IOption<string>).value))}
133
+ onUpdate={(option) => updateProperty("label.class", twMerge(component.properties.label?.class, (option as IOption<string>).value))}
134
134
  />
135
135
  {/snippet}
136
136
 
@@ -141,13 +141,13 @@
141
141
  type="buttons"
142
142
  value={$optionsStore.INPUT_TYPE_OPTIONS.find((opt) => opt.value === (component.properties.type || "text"))}
143
143
  onUpdate={(option) => {
144
- if ((option as IOption<string>).value == "password" && component.properties.help.copyButton) updateProperty("help.copyButton", false)
144
+ if ((option as IOption<string>).value == "password" && component.properties.help?.copyButton) updateProperty("help.copyButton", false)
145
145
  if ((option as IOption<string>).value === "bitMode") {
146
146
  updateProperty("type", "number")
147
147
  updateProperty("number.minNum", 0)
148
- updateProperty("number.maxNum", Math.pow(2, component.properties.range.end - component.properties.range.start + 1) - 1)
148
+ updateProperty("number.maxNum", Math.pow(2, bitRange.end - bitRange.start + 1) - 1)
149
149
  updateProperty("number.step", 1)
150
- updateProperty("help.info", maxNumInfo(component.properties.range))
150
+ updateProperty("help.info", maxNumInfo(bitRange))
151
151
  } else {
152
152
  updateProperty("help.info", "")
153
153
  }
@@ -166,7 +166,7 @@
166
166
  <div class="flex items-end">
167
167
  <UI.Input
168
168
  label={{ name: $T("constructor.props.regexp") }}
169
- value={component.properties.help.regExp}
169
+ value={component.properties.help?.regExp?.toString()}
170
170
  maxlength={150}
171
171
  componentClass={isValidRegExp === false ? "!border-2 !border-red-400" : ""}
172
172
  onUpdate={(value) => updateProperty("help.regExp", value as string)}
@@ -187,7 +187,7 @@
187
187
  role="button"
188
188
  tabindex={null}
189
189
  onkeydown={null}
190
- onclick={() => (component.properties.help.regExp = regexp.value)}
190
+ onclick={() => component.properties.help && (component.properties.help.regExp = regexp.value)}
191
191
  >
192
192
  <h5>{regexp.name}</h5>
193
193
  <span>{regexp.value}</span>
@@ -211,7 +211,7 @@
211
211
  options={$optionsStore.TEXT_ALIGN_OPTIONS}
212
212
  type="buttons"
213
213
  value={$optionsStore.TEXT_ALIGN_OPTIONS.find(
214
- (opt) => opt.value === (component.properties.componentClass.split(" ").find((cl: string) => cl.startsWith("text-")) || "text-center"),
214
+ (opt) => opt.value === (component.properties.componentClass?.split(" ").find((cl: string) => cl.startsWith("text-")) || "text-center"),
215
215
  )}
216
216
  onUpdate={(option) => {
217
217
  updateProperty("componentClass", twMerge(component.properties.componentClass, (option as IOption<string>).value))
@@ -222,7 +222,7 @@
222
222
  <div class="flex">
223
223
  <UI.Input
224
224
  label={{ name: $T("constructor.props.min") }}
225
- value={component.properties.number.minNum as number}
225
+ value={component.properties.number?.minNum as number}
226
226
  type="number"
227
227
  onUpdate={(value) => {
228
228
  updateProperty("number.minNum", Number(value))
@@ -230,7 +230,7 @@
230
230
  />
231
231
  <UI.Input
232
232
  label={{ name: $T("constructor.props.max") }}
233
- value={component.properties.number.maxNum as number}
233
+ value={component.properties.number?.maxNum as number}
234
234
  type="number"
235
235
  onUpdate={(value) => {
236
236
  updateProperty("number.maxNum", Number(value))
@@ -238,7 +238,7 @@
238
238
  />
239
239
  <UI.Input
240
240
  label={{ name: $T("constructor.props.step") }}
241
- value={component.properties.number.step as number}
241
+ value={component.properties.number?.step as number}
242
242
  type="number"
243
243
  onUpdate={(value) => updateProperty("number.step", Number(value))}
244
244
  />
@@ -248,13 +248,13 @@
248
248
  label={{ name: $T("constructor.props.range") }}
249
249
  type="range"
250
250
  number={{ minNum: 0, maxNum: 31, step: 1 }}
251
- value={[component.properties.range.start, component.properties.range.end]}
251
+ value={[bitRange.start, bitRange.end]}
252
252
  onUpdate={(value) => {
253
253
  if (Array.isArray(value)) {
254
254
  updateProperty("range.start", value[0] as number)
255
255
  updateProperty("range.end", value[1] as number)
256
256
  updateProperty("number.minNum", 0)
257
- updateProperty("number.maxNum", Math.pow(2, component.properties.range.end - component.properties.range.start + 1) - 1)
257
+ updateProperty("number.maxNum", Math.pow(2, bitRange.end - bitRange.start + 1) - 1)
258
258
  updateProperty("number.step", 1)
259
259
  updateProperty("help.info", maxNumInfo({ start: value[0] as number, end: value[1] as number }))
260
260
  }
@@ -273,12 +273,12 @@
273
273
  type="buttons"
274
274
  multiSelect={true}
275
275
  value={$optionsStore.INPUT_SETTING_OPTIONS.filter((opt) => {
276
- if (opt.value.split(".").reduce((o, key) => o?.[key], component.properties)) return opt
276
+ if (opt.value.split(".").reduce((o: any, key) => o?.[key], component.properties)) return opt
277
277
  })}
278
278
  onUpdate={(value) => {
279
279
  const currentActiveValues = $optionsStore.INPUT_SETTING_OPTIONS.filter((opt) => {
280
280
  if (!opt?.value) return false
281
- return opt.value.split(".").reduce((o, key) => o?.[key], component.properties)
281
+ return opt.value.split(".").reduce((o: any, key) => o?.[key], component.properties)
282
282
  }).map((opt) => opt.value)
283
283
  if (Array.isArray(value)) {
284
284
  value.forEach((opt) => {
@@ -300,7 +300,7 @@
300
300
  <UI.Select
301
301
  label={{ name: $T("constructor.props.autocomplete") }}
302
302
  options={$optionsStore.AUTOCOMPLETE_CONSTRUCTOR_OPTIONS}
303
- value={$optionsStore.AUTOCOMPLETE_CONSTRUCTOR_OPTIONS.find((opt) => opt.value === (component.properties.help.autocomplete || "off"))}
303
+ value={$optionsStore.AUTOCOMPLETE_CONSTRUCTOR_OPTIONS.find((opt) => opt.value === (component.properties.help?.autocomplete || "off"))}
304
304
  onUpdate={(option) => updateProperty("help.autocomplete", (option as UI.IOption).value as string)}
305
305
  />
306
306
  {/snippet}
@@ -331,7 +331,7 @@
331
331
  {#snippet InputLabelClass()}
332
332
  <UI.Input
333
333
  label={{ name: $T("constructor.props.label.class") }}
334
- value={component.properties.label.class}
334
+ value={component.properties.label?.class}
335
335
  onUpdate={(value) => updateProperty("label.class", value as string)}
336
336
  />
337
337
  {/snippet}
@@ -356,7 +356,7 @@
356
356
  {#snippet InputDisabled()}
357
357
  <UI.Switch
358
358
  label={{ name: $T("constructor.props.disabled") }}
359
- value={component.properties.disabled}
359
+ value={component.properties.disabled ? 1 : 0}
360
360
  options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
361
361
  onChange={(value) => updateProperty("disabled", value === 1)}
362
362
  />
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { getContext } from "svelte"
3
3
  import { T } from "../locales/i18n"
4
- import { type UIComponent, type IJoystickProps, updateProperty, type IUIComponentHandler } from "../types"
4
+ import { type UIComponent, type IJoystickProps, updateProperty, findOptionByClass, type IUIComponentHandler } from "../types"
5
5
  import * as UI from ".."
6
6
  import { ICONS } from "../icons"
7
7
  import { optionsStore, findColorOption } from "../options"
@@ -12,20 +12,16 @@
12
12
  component,
13
13
  onPropertyChange,
14
14
  forConstructor = true,
15
- } = $props<{
15
+ }: {
16
16
  component: UIComponent & { properties: Partial<IJoystickProps> }
17
17
  onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string; eventHandler?: IUIComponentHandler }>) => void
18
18
  forConstructor?: boolean
19
- }>()
19
+ } = $props()
20
20
 
21
21
  const DeviceVariables = getContext<{ id: string; value: string; name: string }[]>("DeviceVariables")
22
22
  let VARIABLE_OPTIONS = $derived(DeviceVariables && Array.isArray(DeviceVariables) ? DeviceVariables : [])
23
23
 
24
- const initialAlign = $derived(
25
- $optionsStore.TEXT_ALIGN_OPTIONS.find((a) =>
26
- (a.value as string).includes(component.properties.label?.class?.split(" ").find((cls: string) => cls.startsWith("text-"))),
27
- ),
28
- )
24
+ const initialAlign = $derived(findOptionByClass($optionsStore.TEXT_ALIGN_OPTIONS, component.properties.label?.class, "text-"))
29
25
 
30
26
  const initialColor = $derived(findColorOption($optionsStore.COLOR_OPTIONS, component.properties.wrapperClass))
31
27
  </script>
@@ -47,7 +43,7 @@
47
43
  updateProperty: (value: number, property: string) => {
48
44
  updateProperty(
49
45
  "axes",
50
- component.properties.axes.map((a: any, i: number) => (i === index ? { ...a, [property.split(".")[1]]: value } : a)),
46
+ (component.properties.axes ?? []).map((a: any, i: number) => (i === index ? { ...a, [property.split(".")[1]]: value } : a)),
51
47
  component,
52
48
  onPropertyChange,
53
49
  )
@@ -16,11 +16,11 @@
16
16
  component,
17
17
  onPropertyChange,
18
18
  forConstructor = true,
19
- } = $props<{
19
+ }: {
20
20
  component: UIComponent & { properties: Partial<IPeriodChartProps> }
21
21
  onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string; eventHandler?: IUIComponentHandler }>) => void
22
22
  forConstructor?: boolean
23
- }>()
23
+ } = $props()
24
24
 
25
25
  const DeviceVariables = getContext<{ id: string; value: string; name: string }[]>("DeviceVariables")
26
26
  let VARIABLE_OPTIONS = $derived(DeviceVariables && Array.isArray(DeviceVariables) ? DeviceVariables : [])
@@ -91,7 +91,7 @@
91
91
  >
92
92
  <UI.Dragging
93
93
  container={itemsContainer}
94
- array={component.properties.levels}
94
+ array={component.properties.levels ?? []}
95
95
  elementIndex={index}
96
96
  onUpdate={(updatedArray) => updateLevels(updatedArray)}
97
97
  />