poe-svelte-ui-lib 1.24.2 → 1.25.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.
@@ -3,9 +3,12 @@
3
3
  <script lang="ts">
4
4
  import { T } from "../locales/i18n"
5
5
  import * as UI from ".."
6
- import { updateProperty, type UIComponent, type IWidgetDeviceInfoProps } from "../types"
6
+ import { updateProperty, type UIComponent, type IWidgetDeviceInfoProps, type IWidgetDeviceInfoConfig, type IOption } from "../types"
7
7
  import WidgetAccentPicker from "../WidgetAccentPicker.svelte"
8
8
  import PropsGroup from "../PropsGroup.svelte"
9
+ import { optionsStore } from "../options"
10
+
11
+ const DEVICE_INFO_KEYS: (keyof IWidgetDeviceInfoConfig)[] = ["DevSN", "DevID", "DevFW", "RunCnt", "DevName", "HostName", "WebUser", "WebPsw"]
9
12
 
10
13
  const { component, onPropertyChange } = $props<{
11
14
  component: UIComponent & { properties: Partial<IWidgetDeviceInfoProps> }
@@ -13,14 +16,52 @@
13
16
  }>()
14
17
  </script>
15
18
 
16
- <PropsGroup label={$T("constructor.props.group.general")}>
17
- <UI.Input
18
- label={{ name: "Заголовок" }}
19
- value={component.properties.label?.name}
20
- onUpdate={(value) => updateProperty("label.name", value as string, component, onPropertyChange)}
19
+ {#snippet WidgetKeys()}
20
+ {#each DEVICE_INFO_KEYS as key (key)}
21
+ <UI.Input
22
+ label={{ name: key }}
23
+ value={component.properties.keys?.[key] ?? key}
24
+ onUpdate={(value) => updateProperty(`keys.${key}`, value as string, component, onPropertyChange)}
25
+ />
26
+ {/each}
27
+ {/snippet}
28
+
29
+ {#snippet WidgetRestartCommand()}
30
+ <UI.Select
31
+ label={{ name: "Заголовок пакета" }}
32
+ type="buttons"
33
+ options={$optionsStore.HEADER_OPTIONS}
34
+ value={$optionsStore.HEADER_OPTIONS.find((o) => o.value === (component.properties.restartCommand?.header || "SET"))}
35
+ onUpdate={(option) => updateProperty("restartCommand.header", (option as IOption<string>).value as string, component, onPropertyChange)}
21
36
  />
22
- <WidgetAccentPicker
23
- value={component.properties.componentClass ?? ""}
24
- onUpdate={(value) => updateProperty("componentClass", value, component, onPropertyChange)}
37
+ <UI.Input
38
+ label={{ name: "Аргумент" }}
39
+ value={component.properties.restartCommand?.argument ?? "Restart"}
40
+ onUpdate={(value) => updateProperty("restartCommand.argument", value as string, component, onPropertyChange)}
25
41
  />
26
- </PropsGroup>
42
+ {/snippet}
43
+
44
+ <div class="flex flex-col gap-2">
45
+ <PropsGroup label={$T("constructor.props.group.general")}>
46
+ <UI.Input
47
+ label={{ name: "Заголовок" }}
48
+ value={component.properties.label?.name}
49
+ onUpdate={(value) => updateProperty("label.name", value as string, component, onPropertyChange)}
50
+ />
51
+ <UI.Input
52
+ label={{ name: "Префикс группы (ID)" }}
53
+ value={component.properties.id}
54
+ onUpdate={(value) => updateProperty("id", value as string, component, onPropertyChange)}
55
+ />
56
+ <WidgetAccentPicker
57
+ value={component.properties.componentClass ?? ""}
58
+ onUpdate={(value) => updateProperty("componentClass", value, component, onPropertyChange)}
59
+ />
60
+ </PropsGroup>
61
+ <PropsGroup label="Ключи устройства">
62
+ {@render WidgetKeys()}
63
+ </PropsGroup>
64
+ <PropsGroup label="Команда перезагрузки">
65
+ {@render WidgetRestartCommand()}
66
+ </PropsGroup>
67
+ </div>
@@ -4,9 +4,25 @@
4
4
  <script lang="ts">
5
5
  import { T } from "../locales/i18n"
6
6
  import * as UI from ".."
7
- import { updateProperty, type UIComponent, type IWidgetWiFiProps, type IOption } from "../types"
7
+ import { updateProperty, type UIComponent, type IWidgetWiFiProps, type IWidgetWiFiConfig, type IOption } from "../types"
8
8
  import WidgetAccentPicker from "../WidgetAccentPicker.svelte"
9
9
  import PropsGroup from "../PropsGroup.svelte"
10
+ import { optionsStore } from "../options"
11
+
12
+ const WIFI_KEYS: (keyof IWidgetWiFiConfig)[] = [
13
+ "WiFiMode",
14
+ "StaSSID",
15
+ "StaPSK",
16
+ "StaticIP",
17
+ "StaIP",
18
+ "StaMS",
19
+ "StaGW",
20
+ "ApSSID",
21
+ "ApPSK",
22
+ "ApIP",
23
+ "ApMS",
24
+ "ApGW",
25
+ ]
10
26
 
11
27
  const { component, onPropertyChange } = $props<{
12
28
  component: UIComponent & { properties: Partial<IWidgetWiFiProps> }
@@ -28,6 +44,39 @@
28
44
  />
29
45
  {/snippet}
30
46
 
47
+ {#snippet WidgetGroupPrefix()}
48
+ <UI.Input
49
+ label={{ name: "Префикс группы (ID)" }}
50
+ value={component.properties.id}
51
+ onUpdate={(value) => updateProperty("id", value as string, component, onPropertyChange)}
52
+ />
53
+ {/snippet}
54
+
55
+ {#snippet WidgetKeys()}
56
+ {#each WIFI_KEYS as key (key)}
57
+ <UI.Input
58
+ label={{ name: key }}
59
+ value={component.properties.keys?.[key] ?? key}
60
+ onUpdate={(value) => updateProperty(`keys.${key}`, value as string, component, onPropertyChange)}
61
+ />
62
+ {/each}
63
+ {/snippet}
64
+
65
+ {#snippet WidgetScanCommand()}
66
+ <UI.Select
67
+ label={{ name: "Заголовок пакета" }}
68
+ type="buttons"
69
+ options={$optionsStore.HEADER_OPTIONS}
70
+ value={$optionsStore.HEADER_OPTIONS.find((o) => o.value === (component.properties.scanCommand?.header || "GET"))}
71
+ onUpdate={(option) => updateProperty("scanCommand.header", (option as IOption<string>).value as string, component, onPropertyChange)}
72
+ />
73
+ <UI.Input
74
+ label={{ name: "Аргумент" }}
75
+ value={component.properties.scanCommand?.argument ?? "APsList"}
76
+ onUpdate={(value) => updateProperty("scanCommand.argument", value as string, component, onPropertyChange)}
77
+ />
78
+ {/snippet}
79
+
31
80
  {#snippet WidgetAllowedModes()}
32
81
  <UI.Select
33
82
  label={{ name: "Разрешённые режимы" }}
@@ -60,10 +109,17 @@
60
109
  <div class="flex flex-col gap-2">
61
110
  <PropsGroup label={$T("constructor.props.group.general")}>
62
111
  {@render WidgetLabel()}
112
+ {@render WidgetGroupPrefix()}
63
113
  {@render WidgetAllowedModes()}
64
114
  {@render WidgetColor()}
65
115
  </PropsGroup>
66
116
  <PropsGroup label={$T("constructor.props.group.behavior")}>
67
117
  {@render WidgetConfirmAP()}
68
118
  </PropsGroup>
119
+ <PropsGroup label="Ключи устройства">
120
+ {@render WidgetKeys()}
121
+ </PropsGroup>
122
+ <PropsGroup label="Команда сканирования">
123
+ {@render WidgetScanCommand()}
124
+ </PropsGroup>
69
125
  </div>
@@ -9,6 +9,19 @@ const translations = {
9
9
  "library.regexp": ["Регулярные выражения", "Regular expressions", "正则表达式"],
10
10
  "library.info": ["Инфо", "Info", "信息"],
11
11
  "library.retry": ["Повторить", "Retry", "重试"],
12
+ /* Документация компонентов для ⓘ в конструкторе (приложение читает через UI.T) — механизм общий
13
+ для всех типов компонентов, заполнено пока только там, где есть что объяснить (фиксированная
14
+ прошивочная конвенция у смарт-виджетов) */
15
+ "component.info.WidgetWiFi": [
16
+ "📶 Виджет работает с фиксированным набором полей группы `CFG` на устройстве — привязка переменных вручную не нужна.\n\n**📡 Режим клиента (STA)**\n- `WiFiMode`, `StaSSID`, `StaPSK`\n- `StaticIP`, `StaIP`, `StaMS`, `StaGW`\n\n**📡 Точка доступа (AP)**\n- `ApSSID`, `ApPSK`\n- `ApIP`, `ApMS`, `ApGW`\n\n🔍 Сканирование сетей отправляет `Header: GET`, `Argument: APsList` — ответ устройства ожидается в поле `CFG.StaSSID-S`.\n\n⚙️ Если на устройстве используется другое имя группы вместо `CFG`, поменяйте префикс (ID) в настройках виджета.",
17
+ "📶 The widget works with a fixed set of fields in the device's `CFG` group — no manual variable binding needed.\n\n**📡 Client mode (STA)**\n- `WiFiMode`, `StaSSID`, `StaPSK`\n- `StaticIP`, `StaIP`, `StaMS`, `StaGW`\n\n**📡 Access point (AP)**\n- `ApSSID`, `ApPSK`\n- `ApIP`, `ApMS`, `ApGW`\n\n🔍 Network scanning sends `Header: GET`, `Argument: APsList` — the device response is expected in the `CFG.StaSSID-S` field.\n\n⚙️ If the device uses a different group name instead of `CFG`, change the prefix (ID) in the widget settings.",
18
+ "📶 该组件使用设备 `CFG` 分组下的一组固定字段——无需手动绑定变量。\n\n**📡 客户端模式(STA)**\n- `WiFiMode`、`StaSSID`、`StaPSK`\n- `StaticIP`、`StaIP`、`StaMS`、`StaGW`\n\n**📡 接入点(AP)**\n- `ApSSID`、`ApPSK`\n- `ApIP`、`ApMS`、`ApGW`\n\n🔍 扫描网络会发送 `Header: GET`、`Argument: APsList`——设备应在 `CFG.StaSSID-S` 字段中返回结果。\n\n⚙️ 如果设备使用的分组名称不是 `CFG`,请在组件设置中修改前缀(ID)。",
19
+ ],
20
+ "component.info.WidgetDeviceInfo": [
21
+ "ℹ️ Виджет работает с фиксированным набором полей группы `CFG` на устройстве — привязка переменных вручную не нужна.\n\n**🔒 Только чтение**\n- `DevSN`, `DevID`, `DevFW`, `RunCnt`\n\n**✏️ Редактируемые** (сохраняются одним пакетом по кнопке «Сохранить»)\n- `DevName`, `HostName`, `WebUser`, `WebPsw`\n\n🔌 Кнопка «Перезагрузить» отправляет `Argument: Restart`.\n\n⚙️ Если на устройстве используется другое имя группы вместо `CFG`, поменяйте префикс (ID) в настройках виджета.",
22
+ "ℹ️ The widget works with a fixed set of fields in the device's `CFG` group — no manual variable binding needed.\n\n**🔒 Read-only**\n- `DevSN`, `DevID`, `DevFW`, `RunCnt`\n\n**✏️ Editable** (saved as one packet via the \"Save\" button)\n- `DevName`, `HostName`, `WebUser`, `WebPsw`\n\n🔌 The \"Restart\" button sends `Argument: Restart`.\n\n⚙️ If the device uses a different group name instead of `CFG`, change the prefix (ID) in the widget settings.",
23
+ "ℹ️ 该组件使用设备 `CFG` 分组下的一组固定字段——无需手动绑定变量。\n\n**🔒 只读字段**\n- `DevSN`、`DevID`、`DevFW`、`RunCnt`\n\n**✏️ 可编辑字段**(通过「保存」按钮一次性发送)\n- `DevName`、`HostName`、`WebUser`、`WebPsw`\n\n🔌 「重启」按钮会发送 `Argument: Restart`。\n\n⚙️ 如果设备使用的分组名称不是 `CFG`,请在组件设置中修改前缀(ID)。",
24
+ ],
12
25
  /* Опции редактора свойств */
13
26
  "constructor.props.action.update": ["Обновить", "Update", "更新"],
14
27
  "constructor.props.action.save": ["Сохранить", "Save", "保存"],
package/dist/types.d.ts CHANGED
@@ -514,6 +514,11 @@ export interface IWidgetWiFiProps {
514
514
  name?: string;
515
515
  };
516
516
  value?: IWidgetWiFiConfig;
517
+ keys?: Partial<Record<keyof IWidgetWiFiConfig, string>>;
518
+ scanCommand?: {
519
+ header?: string;
520
+ argument?: string;
521
+ };
517
522
  allowedModes?: number[];
518
523
  confirmOnAP?: boolean;
519
524
  collapsed?: boolean;
@@ -543,6 +548,11 @@ export interface IWidgetDeviceInfoProps {
543
548
  name?: string;
544
549
  };
545
550
  value?: IWidgetDeviceInfoConfig;
551
+ keys?: Partial<Record<keyof IWidgetDeviceInfoConfig, string>>;
552
+ restartCommand?: {
553
+ header?: string;
554
+ argument?: string;
555
+ };
546
556
  collapsed?: boolean;
547
557
  persistKey?: string;
548
558
  onSave?: (info: IWidgetDeviceInfoConfig) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-svelte-ui-lib",
3
- "version": "1.24.2",
3
+ "version": "1.25.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {