poe-svelte-ui-lib 1.35.0 → 1.36.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 +24 -0
- package/dist/Carousel/Carousel.svelte +4 -3
- package/dist/ColorPicker/ColorPicker.svelte +12 -14
- package/dist/Divider/README.md +8 -8
- package/dist/Dragging.README.md +9 -9
- package/dist/FileAttach/FileAttach.svelte +12 -11
- package/dist/FileAttach/README.md +17 -17
- package/dist/Graph/Graph.svelte +3 -2
- package/dist/Input/README.md +29 -29
- package/dist/Joystick/Joystick.svelte +8 -8
- package/dist/Map/Map.svelte +12 -9
- package/dist/Map/MapProps.svelte +1 -3
- package/dist/Modal.README.md +10 -10
- package/dist/Select/README.md +25 -22
- package/dist/Table/README.md +5 -0
- package/dist/Table/TableProps.svelte +211 -213
- package/dist/VideoViewer/VideoViewer.svelte +8 -7
- package/dist/Widget/README.md +4 -0
- package/dist/WidgetDeviceInfo/README.md +22 -20
- package/dist/WidgetDeviceInfo/WidgetDeviceInfo.svelte +1 -4
- package/dist/WidgetDeviceInfo/WidgetDeviceInfoProps.svelte +1 -12
- package/dist/WidgetFileSystem/README.md +2 -0
- package/dist/WidgetRGBStrip/LightIcon.svelte +12 -0
- package/dist/WidgetRGBStrip/LightIcon.svelte.d.ts +18 -0
- package/dist/WidgetRGBStrip/README.md +60 -0
- package/dist/WidgetRGBStrip/WidgetRGBStrip.svelte +185 -0
- package/dist/WidgetRGBStrip/WidgetRGBStrip.svelte.d.ts +4 -0
- package/dist/WidgetRGBStrip/WidgetRGBStripProps.svelte +33 -0
- package/dist/WidgetRGBStrip/WidgetRGBStripProps.svelte.d.ts +14 -0
- package/dist/WidgetStackInfo/README.md +2 -0
- package/dist/WidgetWiFi/README.md +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/locales/translations.js +5 -0
- package/dist/types.d.ts +27 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,6 +22,24 @@ npm install poe-svelte-ui-lib
|
|
|
22
22
|
@source "../node_modules/poe-svelte-ui-lib/dist";
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
**Глобальные стили тегов — только в `@layer base`.** Компоненты задают размеры текста и отступы Tailwind-утилитами (например `text-[12px]` у подписи `<h5>`). Правило вне слоя (`h5 { font-size: 1rem }`, `label { … }`, `p { … }`) сильнее любой утилиты, и в приложении подписи станут крупнее задуманного и перестанут помещаться. Поэтому типографику тегов оборачивайте:
|
|
26
|
+
|
|
27
|
+
```css
|
|
28
|
+
@layer base {
|
|
29
|
+
h5 {
|
|
30
|
+
font-size: 1rem;
|
|
31
|
+
font-weight: 600;
|
|
32
|
+
}
|
|
33
|
+
label {
|
|
34
|
+
font-size: 0.8rem;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Классы ролей (`.bg-red`, `.bg-max`, …) и темы (`.light`/`.dark`) остаются вне слоя — они как раз должны перебивать утилиты.
|
|
40
|
+
|
|
41
|
+
Необязательный токен `--table-header-color` — фон шапки `Table` (по умолчанию `--container-color`); смарт-виджеты задают его сами из мастер-цвета.
|
|
42
|
+
|
|
25
43
|
Справочник по регулярным выражениям (`docs/info/RegExp.md`) и протокол обмена данными с устройством (`docs/info/ExchangeRules.md`) — вспомогательные материалы для тех, кто настраивает валидацию полей и работу с `DeviceStore`.
|
|
26
44
|
|
|
27
45
|
## Использование
|
|
@@ -39,6 +57,12 @@ npm install poe-svelte-ui-lib
|
|
|
39
57
|
|
|
40
58
|
Полный список компонентов и типов — в `src/lib/index.ts`. У каждого компонента есть README рядом с исходником (`src/lib/<Component>/README.md`, для `Modal`/`Dragging` — `src/lib/<Component>.README.md`) с описанием пропсов, примерами и внутренним устройством; живая витрина всех компонентов — `npm run dev` → `/components/all`.
|
|
41
59
|
|
|
60
|
+
**Витрина повторяет конструктор DevCloud:** слева компонент и код (прижат к низу), справа панель свойств шириной `24rem` с тем же оформлением, что в облаке, — переполнение подписей видно сразу. Кнопка (i) в шапке панели открывает описание компонента.
|
|
61
|
+
|
|
62
|
+
**Описания компонентов (i)** — ключи `component.info.<Тип>` в `src/lib/locales/translations.ts` (ru/en/zh, Markdown). Один источник для витрины и конструктора DevCloud: облако показывает кнопку (i) у любого компонента, для которого есть описание. Добавляя компонент, допишите и описание: для чего он, какую переменную устройства показывает, что и когда отправляет, главные настройки и ограничения.
|
|
63
|
+
|
|
64
|
+
**Иконки вариантов панелей свойств** — `src/lib/libIcons/propsIcons.ts` (контурные SVG 24×24 строками), подставляются в `IOption.icon` в `options.ts`.
|
|
65
|
+
|
|
42
66
|
## Разработка
|
|
43
67
|
|
|
44
68
|
```bash
|
|
@@ -42,12 +42,13 @@
|
|
|
42
42
|
<h5 class={`${label.class}`}>{label.name}</h5>
|
|
43
43
|
{/if}
|
|
44
44
|
<!-- Карусель -->
|
|
45
|
-
|
|
45
|
+
<!-- По design-handoff (раздел 9): сплошной фон, стрелки 32 px на поверхности с линией и тенью уровня 2 -->
|
|
46
|
+
<div class="relative w-full overflow-hidden rounded-2xl bg-(--container-color)">
|
|
46
47
|
<!-- Кнопки навигации -->
|
|
47
48
|
{#if !isAtStart}
|
|
48
49
|
<button
|
|
49
50
|
transition:slide={{ axis: "x" }}
|
|
50
|
-
class="absolute z-10 size-
|
|
51
|
+
class="absolute z-10 size-[32px] -translate-y-1/2 cursor-pointer top-1/2 left-1 p-1.5 rounded-full border border-(--hairline-color) bg-(--back-color) text-(--muted-color) transition-colors duration-150 hover:text-(--font-color) [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full shadow-(--elevation-2) rotate-180"
|
|
51
52
|
onclick={() => scrollCarousel(-scrollValue)}
|
|
52
53
|
>
|
|
53
54
|
<ArrowIcon />
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
{#if !isAtEnd}
|
|
57
58
|
<button
|
|
58
59
|
transition:slide={{ axis: "x" }}
|
|
59
|
-
class="absolute z-10 size-
|
|
60
|
+
class="absolute z-10 size-[32px] -translate-y-1/2 cursor-pointer top-1/2 right-1 p-1.5 rounded-full border border-(--hairline-color) bg-(--back-color) text-(--muted-color) transition-colors duration-150 hover:text-(--font-color) [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full shadow-(--elevation-2)"
|
|
60
61
|
onclick={() => scrollCarousel(scrollValue)}
|
|
61
62
|
>
|
|
62
63
|
<ArrowIcon />
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
<div class="flex w-full flex-col gap-2">
|
|
138
138
|
<!-- Выбор цвета -->
|
|
139
139
|
<div
|
|
140
|
-
class="hue-slider relative h-7 w-full cursor-pointer overflow-hidden rounded-
|
|
140
|
+
class="hue-slider relative h-7 w-full cursor-pointer overflow-hidden rounded-[10px] border border-(--hairline-color)"
|
|
141
141
|
role="slider"
|
|
142
142
|
aria-valuenow={null}
|
|
143
143
|
tabindex={null}
|
|
@@ -152,17 +152,15 @@
|
|
|
152
152
|
></div>
|
|
153
153
|
{#if mode === "hsv"}
|
|
154
154
|
<div
|
|
155
|
-
class="pointer-events-none absolute
|
|
156
|
-
style={`left: ${huePointer}
|
|
155
|
+
class="pointer-events-none absolute inset-y-0 w-[2px] -translate-x-1/2 bg-white shadow-[0_0_0_1px_rgb(0_0_0/0.25),0_1px_3px_rgb(0_0_0/0.4)]"
|
|
156
|
+
style={`left: ${huePointer}%`}
|
|
157
157
|
></div>
|
|
158
158
|
{/if}
|
|
159
159
|
</div>
|
|
160
160
|
|
|
161
161
|
<!-- Яркость цвета -->
|
|
162
162
|
<div
|
|
163
|
-
class="brightness-slider relative h-4 w-full cursor-pointer overflow-hidden rounded-
|
|
164
|
-
? 'shadow-sm transition duration-200 hover:shadow-md'
|
|
165
|
-
: ''}"
|
|
163
|
+
class="brightness-slider relative h-4 w-full cursor-pointer overflow-hidden rounded-[10px] border border-(--hairline-color)"
|
|
166
164
|
role="slider"
|
|
167
165
|
aria-valuenow={null}
|
|
168
166
|
tabindex={null}
|
|
@@ -172,15 +170,15 @@
|
|
|
172
170
|
<div class="absolute inset-0" style={`background: linear-gradient(to right, rgb(0,0,0), rgb(${hsvToRgb(hsv.h, hsv.s, 100).join(",")}))`}></div>
|
|
173
171
|
|
|
174
172
|
<div
|
|
175
|
-
class="pointer-events-none absolute
|
|
176
|
-
style={`left: ${brightnessPointer}
|
|
173
|
+
class="pointer-events-none absolute inset-y-0 w-[2px] -translate-x-1/2 bg-white shadow-[0_0_0_1px_rgb(0_0_0/0.25),0_1px_3px_rgb(0_0_0/0.4)]"
|
|
174
|
+
style={`left: ${brightnessPointer}%`}
|
|
177
175
|
></div>
|
|
178
176
|
{/if}
|
|
179
177
|
</div>
|
|
180
178
|
|
|
181
179
|
<!-- Яркость белого цвета -->
|
|
182
180
|
<div
|
|
183
|
-
class="white-slider relative mt-4 h-4 w-full cursor-pointer overflow-hidden rounded-
|
|
181
|
+
class="white-slider relative mt-4 h-4 w-full cursor-pointer overflow-hidden rounded-[10px] border border-(--hairline-color)"
|
|
184
182
|
role="slider"
|
|
185
183
|
aria-valuenow={null}
|
|
186
184
|
tabindex={null}
|
|
@@ -189,21 +187,21 @@
|
|
|
189
187
|
<div class="absolute inset-0 bg-linear-to-r from-black to-white"></div>
|
|
190
188
|
{#if mode === "white"}
|
|
191
189
|
<div
|
|
192
|
-
class="pointer-events-none absolute
|
|
193
|
-
style={`left: ${whiteValue}
|
|
190
|
+
class="pointer-events-none absolute inset-y-0 w-[2px] -translate-x-1/2 bg-white shadow-[0_0_0_1px_rgb(0_0_0/0.25),0_1px_3px_rgb(0_0_0/0.4)]"
|
|
191
|
+
style={`left: ${whiteValue}%`}
|
|
194
192
|
></div>
|
|
195
193
|
{/if}
|
|
196
194
|
</div>
|
|
197
195
|
</div>
|
|
198
196
|
{/if}
|
|
199
197
|
|
|
200
|
-
<!-- Превью
|
|
198
|
+
<!-- Превью цвета: квадрат 48 с радиусом 10 (design-handoff, раздел 9) -->
|
|
201
199
|
<div class="flex flex-col items-center m-auto" style="width: 7rem;">
|
|
202
200
|
<div
|
|
203
|
-
class={`
|
|
201
|
+
class={`size-[48px] rounded-[10px] border border-(--hairline-color) transition-colors duration-200 select-none ${textColor()}`}
|
|
204
202
|
style={`background: rgb(${previewBaseColor().join(",")})`}
|
|
205
203
|
></div>
|
|
206
|
-
<div class="w-full text-center font-semibold">{hex()}</div>
|
|
204
|
+
<div class="mt-1 w-full text-center font-mono text-[12px] font-semibold text-(--muted-color)">{hex()}</div>
|
|
207
205
|
</div>
|
|
208
206
|
</div>
|
|
209
207
|
</div>
|
package/dist/Divider/README.md
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
## Пропсы
|
|
8
8
|
|
|
9
|
-
| Название | Тип | По умолчанию | Описание
|
|
10
|
-
| -------------- | ------------------------------- | --------------------- |
|
|
11
|
-
| `id` | `string` | `crypto.randomUUID()` | Уникальный идентификатор компонента
|
|
12
|
-
| `wrapperClass` | `string` | `""` | CSS-классы для обёртки компонента
|
|
13
|
-
| `type` | `"line" \| "empty"` | `"line"` | `line` — видимая полоса, `empty` — чистый отступ без полосы
|
|
14
|
-
| `width` | `number` | `1` | Толщина полосы в пикселях (применяется только при `type="line"`)
|
|
15
|
-
| `color` | `string` | `""` | Класс цвета полосы из общей палитры (`bg-max`, `bg-red`, `bg-yellow`, `bg-green`, `bg-blue`, `bg-purple`, `bg-gray`); при пустом значении полоса красится в нейтральный `--hairline-color`, при заданном `bg-*` — в `--bg-color` (как в `Button.svelte`)
|
|
16
|
-
| `anchor` | `"top" \| "center" \| "bottom"` | `"center"` | Положение полосы внутри выделенной компоненту высоты сетки
|
|
9
|
+
| Название | Тип | По умолчанию | Описание |
|
|
10
|
+
| -------------- | ------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| `id` | `string` | `crypto.randomUUID()` | Уникальный идентификатор компонента |
|
|
12
|
+
| `wrapperClass` | `string` | `""` | CSS-классы для обёртки компонента |
|
|
13
|
+
| `type` | `"line" \| "empty"` | `"line"` | `line` — видимая полоса, `empty` — чистый отступ без полосы |
|
|
14
|
+
| `width` | `number` | `1` | Толщина полосы в пикселях (применяется только при `type="line"`) |
|
|
15
|
+
| `color` | `string` | `""` | Класс цвета полосы из общей палитры (`bg-max`, `bg-red`, `bg-yellow`, `bg-green`, `bg-blue`, `bg-purple`, `bg-gray`); при пустом значении полоса красится в нейтральный `--hairline-color`, при заданном `bg-*` — в `--bg-color` (как в `Button.svelte`) |
|
|
16
|
+
| `anchor` | `"top" \| "center" \| "bottom"` | `"center"` | Положение полосы внутри выделенной компоненту высоты сетки |
|
|
17
17
|
|
|
18
18
|
## События
|
|
19
19
|
|
package/dist/Dragging.README.md
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
## Пропсы
|
|
10
10
|
|
|
11
|
-
| Название | Тип
|
|
12
|
-
| ---------------- |
|
|
13
|
-
| `wrapperClass` | `string`
|
|
14
|
-
| `container` | `HTMLDivElement`
|
|
15
|
-
| `array` | `any[]`
|
|
16
|
-
| `elementsId` | `string`
|
|
17
|
-
| `elementIndex` | `number`
|
|
18
|
-
| `containerIndex` | `number`
|
|
19
|
-
| `onUpdate` | `(arr: any[], index?: number \| null) => void` | `undefined`
|
|
11
|
+
| Название | Тип | По умолчанию | Описание |
|
|
12
|
+
| ---------------- | ---------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| `wrapperClass` | `string` | `undefined` | CSS-классы для обёртки ручки перетаскивания |
|
|
14
|
+
| `container` | `HTMLDivElement` | `-` (обязателен) | Контейнер, внутри которого ищутся элементы списка (по атрибуту `id`, см. ниже) для определения точки вставки |
|
|
15
|
+
| `array` | `any[]` | `-` (обязателен) | Массив элементов списка — мутируется на месте (`splice`) в процессе перетаскивания |
|
|
16
|
+
| `elementsId` | `string` | `"item"` | Префикс `id` DOM-элементов списка: ожидается `#{elementsId}-{index}` или `#{elementsId}-{index}-{containerIndex}` |
|
|
17
|
+
| `elementIndex` | `number` | `-` (обязателен) | Индекс элемента, которому принадлежит эта ручка, в `array` |
|
|
18
|
+
| `containerIndex` | `number` | `undefined` | Индекс контейнера — нужен, когда на странице несколько независимых списков и id элементов включают ещё и номер контейнера |
|
|
19
|
+
| `onUpdate` | `(arr: any[], index?: number \| null) => void` | `undefined` | Вызывается дважды за одно перетаскивание: сразу после извлечения элемента (`array` без него) и по завершении (`array` с элементом на новом месте, вторым аргументом — `containerIndex`) |
|
|
20
20
|
|
|
21
21
|
## События
|
|
22
22
|
|
|
@@ -53,10 +53,8 @@
|
|
|
53
53
|
}
|
|
54
54
|
</script>
|
|
55
55
|
|
|
56
|
-
<!--
|
|
57
|
-
|
|
58
|
-
радиус 10/высота 36 как у Input/Select, сегмент "Выбрать файл" залит акцентом
|
|
59
|
-
с текстом --on-accent (было --font-color по тёмно-синему — нечитаемо). -->
|
|
56
|
+
<!-- По design-handoff (раздел 9): зона сброса — пунктир 1 px с радиусом 12 вместо залитой кнопки,
|
|
57
|
+
высота как у Input; «Выбрать файл» — акцентный текст, имя файла — обычным цветом, пока не выбрано — бледным. -->
|
|
60
58
|
<div class={twMerge(`flex flex-col items-center gap-1`, wrapperClass)}>
|
|
61
59
|
{#if label.name}
|
|
62
60
|
<span class={twMerge(`w-full text-[12px] font-semibold text-(--muted-color)`, label.class)}>{label.name}</span>
|
|
@@ -65,8 +63,8 @@
|
|
|
65
63
|
{#if type === "image"}
|
|
66
64
|
<div class="relative">
|
|
67
65
|
<button
|
|
68
|
-
class="flex items-center justify-center overflow-hidden {imageSize.form === 'circle' ? 'rounded-full' : 'rounded-
|
|
69
|
-
border border-(--
|
|
66
|
+
class="flex items-center justify-center overflow-hidden {imageSize.form === 'circle' ? 'rounded-full' : 'rounded-[12px]'}
|
|
67
|
+
border border-dashed border-(--border-color) bg-(--container-color) transition-colors duration-150
|
|
70
68
|
{disabled ? 'cursor-not-allowed opacity-45' : 'cursor-pointer hover:bg-(--border-color)'}"
|
|
71
69
|
style={`height: ${imageSize.height}; width: ${imageSize.width}`}
|
|
72
70
|
onclick={triggerFileInput}
|
|
@@ -98,13 +96,16 @@
|
|
|
98
96
|
onchange={handleFileChange}
|
|
99
97
|
/>
|
|
100
98
|
<div
|
|
101
|
-
class=
|
|
102
|
-
|
|
99
|
+
class={twMerge(
|
|
100
|
+
`flex h-8 w-full items-center gap-3 overflow-hidden rounded-[12px] border border-dashed border-(--border-color) bg-(--field-color) px-3 text-[14px]
|
|
101
|
+
transition-colors duration-150 ${disabled ? "opacity-45" : "hover:border-(--accent-color)"}`,
|
|
102
|
+
componentClass,
|
|
103
|
+
)}
|
|
103
104
|
>
|
|
104
|
-
<
|
|
105
|
+
<span class="shrink-0 font-semibold whitespace-nowrap text-(--accent-color)">
|
|
105
106
|
{$T("constructor.props.file.select")}
|
|
106
|
-
</
|
|
107
|
-
<div class=
|
|
107
|
+
</span>
|
|
108
|
+
<div class="flex min-w-0 flex-1 items-center justify-start truncate {fileName ? 'text-(--font-color)' : 'text-(--faint-color)'}">
|
|
108
109
|
<p class="w-full truncate">{fileName || $T("constructor.props.file.notselected")}</p>
|
|
109
110
|
</div>
|
|
110
111
|
</div>
|
|
@@ -6,24 +6,24 @@
|
|
|
6
6
|
|
|
7
7
|
## Пропсы
|
|
8
8
|
|
|
9
|
-
| Название | Тип | По умолчанию | Описание
|
|
10
|
-
| ------------------- | -------------------------------------------- | --------------------- |
|
|
11
|
-
| `id` | `string` | `crypto.randomUUID()` | Уникальный идентификатор компонента
|
|
12
|
-
| `wrapperClass` | `string` | `""` | Дополнительные CSS-классы для обертки компонента
|
|
9
|
+
| Название | Тип | По умолчанию | Описание |
|
|
10
|
+
| ------------------- | -------------------------------------------- | --------------------- | ---------------------------------------------------------------- |
|
|
11
|
+
| `id` | `string` | `crypto.randomUUID()` | Уникальный идентификатор компонента |
|
|
12
|
+
| `wrapperClass` | `string` | `""` | Дополнительные CSS-классы для обертки компонента |
|
|
13
13
|
| `componentClass` | `string` | `""` | Дополнительные CSS-классы для элемента с именем выбранного файла |
|
|
14
|
-
| `label` | `object` | `-` | Настройки заголовка компонента
|
|
15
|
-
| `label.name` | `string` | `""` | Текст заголовка компонента
|
|
16
|
-
| `label.class` | `string` | `""` | CSS-классы для стилизации текста заголовка
|
|
17
|
-
| `type` | `"file" \| "image"` | `"file"` | Тип компонента (файл или изображение)
|
|
18
|
-
| `accept` | `string` | `"*/*"` | MIME-типы файлов, которые можно выбрать
|
|
19
|
-
| `imageSize` | `object` | `-` | Настройки отображения изображения
|
|
20
|
-
| `imageSize.height` | `string` | `"10rem"` | Высота области отображения изображения
|
|
21
|
-
| `imageSize.width` | `string` | `"10rem"` | Ширина области отображения изображения
|
|
22
|
-
| `imageSize.fitMode` | `"cover" \| "contain"` | `"cover"` | Режим масштабирования изображения
|
|
23
|
-
| `imageSize.form` | `"square" \| "circle"` | `"square"` | Форма области отображения изображения
|
|
24
|
-
| `disabled` | `boolean` | `false` | Состояние отключения компонента
|
|
25
|
-
| `currentImage` | `string \| null` | `""` | Текущее изображение (для связывания)
|
|
26
|
-
| `onChange` | `(event: Event, file: File \| null) => void` | `() => {}` | Обработчик изменения файла
|
|
14
|
+
| `label` | `object` | `-` | Настройки заголовка компонента |
|
|
15
|
+
| `label.name` | `string` | `""` | Текст заголовка компонента |
|
|
16
|
+
| `label.class` | `string` | `""` | CSS-классы для стилизации текста заголовка |
|
|
17
|
+
| `type` | `"file" \| "image"` | `"file"` | Тип компонента (файл или изображение) |
|
|
18
|
+
| `accept` | `string` | `"*/*"` | MIME-типы файлов, которые можно выбрать |
|
|
19
|
+
| `imageSize` | `object` | `-` | Настройки отображения изображения |
|
|
20
|
+
| `imageSize.height` | `string` | `"10rem"` | Высота области отображения изображения |
|
|
21
|
+
| `imageSize.width` | `string` | `"10rem"` | Ширина области отображения изображения |
|
|
22
|
+
| `imageSize.fitMode` | `"cover" \| "contain"` | `"cover"` | Режим масштабирования изображения |
|
|
23
|
+
| `imageSize.form` | `"square" \| "circle"` | `"square"` | Форма области отображения изображения |
|
|
24
|
+
| `disabled` | `boolean` | `false` | Состояние отключения компонента |
|
|
25
|
+
| `currentImage` | `string \| null` | `""` | Текущее изображение (для связывания) |
|
|
26
|
+
| `onChange` | `(event: Event, file: File \| null) => void` | `() => {}` | Обработчик изменения файла |
|
|
27
27
|
|
|
28
28
|
## События
|
|
29
29
|
|
package/dist/Graph/Graph.svelte
CHANGED
|
@@ -390,12 +390,13 @@
|
|
|
390
390
|
|
|
391
391
|
<div class="flex w-full flex-row gap-4">
|
|
392
392
|
<!-- График -->
|
|
393
|
-
|
|
393
|
+
<!-- design-handoff, раздел 9: рамка --hairline-color без тени, тултип в оформлении общего Tooltip.svelte -->
|
|
394
|
+
<div bind:this={container} class="relative h-64 grow overflow-hidden rounded-[14px] border border-(--hairline-color)">
|
|
394
395
|
<canvas class="h-full w-full bg-(--back-color)" bind:this={canvas} onmousemove={handleMouseMove} onmouseleave={handleMouseLeave}></canvas>
|
|
395
396
|
|
|
396
397
|
{#if tooltip.visible}
|
|
397
398
|
<div
|
|
398
|
-
class="pointer-events-none absolute z-10 rounded-lg border border-(--
|
|
399
|
+
class="pointer-events-none absolute z-10 rounded-lg border border-(--hairline-color) bg-(--back-color) px-2.5 py-1.5 text-[12px] whitespace-nowrap shadow-(--elevation-2)"
|
|
399
400
|
style="left: {Math.min(tooltip.x + 12, width - 150)}px; top: {Math.min(tooltip.y + 12, height - 16 - tooltip.items.length * 16)}px;"
|
|
400
401
|
>
|
|
401
402
|
<div class="mb-1 font-semibold">{formatTooltipTime(tooltip.time)}</div>
|
package/dist/Input/README.md
CHANGED
|
@@ -6,35 +6,35 @@
|
|
|
6
6
|
|
|
7
7
|
## Пропсы
|
|
8
8
|
|
|
9
|
-
| Название | Тип | По умолчанию | Описание
|
|
10
|
-
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
|
|
11
|
-
| `id` | `string` | `crypto.randomUUID()` | Уникальный идентификатор компонента
|
|
12
|
-
| `type` | `"text" \| "password" \| "number" \| "text-area" \| "bitMode"` | `"text"` | Тип поля ввода: `text` — обычный текст, `password` — скрытый ввод с кнопкой показа, `number` — числовое поле со стрелками, `text-area` — многострочное поле, `bitMode` — числовое поле, диапазон которого рассчитывается из `range`
|
|
13
|
-
| `wrapperClass` | `string` | `""` | Дополнительные CSS-классы для внешней обёртки компонента
|
|
14
|
-
| `label` | `object` | `-` | Настройки подписи компонента
|
|
15
|
-
| `label.name` | `string` | `""` | Текст заголовка
|
|
16
|
-
| `label.class` | `string` | `""` | CSS-классы для стилизации заголовка
|
|
17
|
-
| `componentClass` | `string` | `""` | Дополнительные CSS-классы для самого элемента ввода (`input`/`textarea`)
|
|
18
|
-
| `disabled` | `boolean` | `false` | Отключает ввод: блокирует взаимодействие с элементом и визуально затемняет компонент
|
|
19
|
-
| `readonly` | `boolean` | `false` | Режим только для чтения: позволяет выделять и копировать текст, но запрещает редактирование
|
|
20
|
-
| `value` | `string \| number` | `undefined` | Текущее значение поля; поддерживает двустороннее связывание (`$bindable`)
|
|
21
|
-
| `range` | `object` | `undefined` | ⚠️ Читается только конструкторской панелью `InputProps.svelte` (для расчёта `number.maxNum`, `2^(end - start + 1) - 1`) — сам `Input.svelte` проп `range` не использует. На голом `<UI.Input type="bitMode">` диапазон задаётся напрямую через `number.maxNum`
|
|
22
|
-
| `range.start` | `number` | `undefined` | Начальный индекс бита (только для конструкторской панели)
|
|
23
|
-
| `range.end` | `number` | `undefined` | Конечный индекс бита (только для конструкторской панели)
|
|
24
|
-
| `maxlength` | `number` | `100` | Максимальное количество символов, разрешённых для ввода
|
|
25
|
-
| `textareaRows` | `number` | `3` | Количество видимых строк для типа `text-area`
|
|
26
|
-
| `placeholder` | `string` | `""` | Текст-подсказка, отображаемый в пустом поле ввода
|
|
27
|
-
| `isValid` | `boolean` | `true` | Состояние валидации: при `false` поле подсвечивается красным; поддерживает двустороннее связывание (`$bindable`)
|
|
28
|
-
| `number` | `object` | `-` | Настройки для числового ввода
|
|
29
|
-
| `number.minNum` | `number` | `-1000000` | Минимальное значение диапазона
|
|
30
|
-
| `number.maxNum` | `number` | `1000000` | Максимальное значение диапазона
|
|
31
|
-
| `number.step` | `number` | `1` | Шаг изменения значения стрелками
|
|
32
|
-
| `help` | `object` | `-` | Дополнительные настройки поля
|
|
33
|
-
| `help.info` | `string` | `""` | Текст всплывающей подсказки
|
|
34
|
-
| `help.copyButton` | `boolean` | `false` | Показать кнопку копирования значения
|
|
35
|
-
| `help.regExp` | `string \| RegExp` | `undefined` | Регулярное выражение для валидации ввода
|
|
36
|
-
| `help.autocomplete` | `"on" \| "off" \| "given-name" \| "family-name" \| "nickname" \| "username" \| "new-password" \| "current-password" \| "organization-title" \| "country-name" \| "address-level1" \| "address-level2" \| "street-address" \| "postal-code" \| "email" \| "tel" \| null` | `"off"` | Атрибут автозаполнения браузера
|
|
37
|
-
| `onUpdate` | `(value: string \| number) => void` | `undefined` | Callback-функция, вызываемая при изменении значения поля; передаёт новое значение
|
|
9
|
+
| Название | Тип | По умолчанию | Описание |
|
|
10
|
+
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| `id` | `string` | `crypto.randomUUID()` | Уникальный идентификатор компонента |
|
|
12
|
+
| `type` | `"text" \| "password" \| "number" \| "text-area" \| "bitMode"` | `"text"` | Тип поля ввода: `text` — обычный текст, `password` — скрытый ввод с кнопкой показа, `number` — числовое поле со стрелками, `text-area` — многострочное поле, `bitMode` — числовое поле, диапазон которого рассчитывается из `range` |
|
|
13
|
+
| `wrapperClass` | `string` | `""` | Дополнительные CSS-классы для внешней обёртки компонента |
|
|
14
|
+
| `label` | `object` | `-` | Настройки подписи компонента |
|
|
15
|
+
| `label.name` | `string` | `""` | Текст заголовка |
|
|
16
|
+
| `label.class` | `string` | `""` | CSS-классы для стилизации заголовка |
|
|
17
|
+
| `componentClass` | `string` | `""` | Дополнительные CSS-классы для самого элемента ввода (`input`/`textarea`) |
|
|
18
|
+
| `disabled` | `boolean` | `false` | Отключает ввод: блокирует взаимодействие с элементом и визуально затемняет компонент |
|
|
19
|
+
| `readonly` | `boolean` | `false` | Режим только для чтения: позволяет выделять и копировать текст, но запрещает редактирование |
|
|
20
|
+
| `value` | `string \| number` | `undefined` | Текущее значение поля; поддерживает двустороннее связывание (`$bindable`) |
|
|
21
|
+
| `range` | `object` | `undefined` | ⚠️ Читается только конструкторской панелью `InputProps.svelte` (для расчёта `number.maxNum`, `2^(end - start + 1) - 1`) — сам `Input.svelte` проп `range` не использует. На голом `<UI.Input type="bitMode">` диапазон задаётся напрямую через `number.maxNum` |
|
|
22
|
+
| `range.start` | `number` | `undefined` | Начальный индекс бита (только для конструкторской панели) |
|
|
23
|
+
| `range.end` | `number` | `undefined` | Конечный индекс бита (только для конструкторской панели) |
|
|
24
|
+
| `maxlength` | `number` | `100` | Максимальное количество символов, разрешённых для ввода |
|
|
25
|
+
| `textareaRows` | `number` | `3` | Количество видимых строк для типа `text-area` |
|
|
26
|
+
| `placeholder` | `string` | `""` | Текст-подсказка, отображаемый в пустом поле ввода |
|
|
27
|
+
| `isValid` | `boolean` | `true` | Состояние валидации: при `false` поле подсвечивается красным; поддерживает двустороннее связывание (`$bindable`) |
|
|
28
|
+
| `number` | `object` | `-` | Настройки для числового ввода |
|
|
29
|
+
| `number.minNum` | `number` | `-1000000` | Минимальное значение диапазона |
|
|
30
|
+
| `number.maxNum` | `number` | `1000000` | Максимальное значение диапазона |
|
|
31
|
+
| `number.step` | `number` | `1` | Шаг изменения значения стрелками |
|
|
32
|
+
| `help` | `object` | `-` | Дополнительные настройки поля |
|
|
33
|
+
| `help.info` | `string` | `""` | Текст всплывающей подсказки |
|
|
34
|
+
| `help.copyButton` | `boolean` | `false` | Показать кнопку копирования значения |
|
|
35
|
+
| `help.regExp` | `string \| RegExp` | `undefined` | Регулярное выражение для валидации ввода |
|
|
36
|
+
| `help.autocomplete` | `"on" \| "off" \| "given-name" \| "family-name" \| "nickname" \| "username" \| "new-password" \| "current-password" \| "organization-title" \| "country-name" \| "address-level1" \| "address-level2" \| "street-address" \| "postal-code" \| "email" \| "tel" \| null` | `"off"` | Атрибут автозаполнения браузера |
|
|
37
|
+
| `onUpdate` | `(value: string \| number) => void` | `undefined` | Callback-функция, вызываемая при изменении значения поля; передаёт новое значение |
|
|
38
38
|
|
|
39
39
|
## События
|
|
40
40
|
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
|
|
131
131
|
{#if !readonly}
|
|
132
132
|
<div class="flex w-1/2 items-center justify-center">
|
|
133
|
-
<div class="relative z-10 flex size-40 min-h-40 min-w-40 items-center justify-center rounded-full bg-(--bg-color) shadow-
|
|
133
|
+
<div class="relative z-10 flex size-40 min-h-40 min-w-40 items-center justify-center rounded-full bg-(--bg-color) shadow-(--elevation-2)">
|
|
134
134
|
<!-- Основные кнопки (оси pitch и yaw) -->
|
|
135
135
|
<div class="absolute h-full w-full overflow-hidden rounded-full">
|
|
136
136
|
{#each directions as direction, index}
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
{/each}
|
|
177
177
|
</div>
|
|
178
178
|
<!-- Кнопка по центру -->
|
|
179
|
-
<div class="z-20 flex size-20 items-center justify-center rounded-full bg-(--bg-color) shadow-
|
|
179
|
+
<div class="z-20 flex size-20 items-center justify-center rounded-full bg-(--bg-color) shadow-(--elevation-2)">
|
|
180
180
|
<button
|
|
181
181
|
class="flex size-18 cursor-pointer rounded-full p-2 origin-center active:scale-95
|
|
182
182
|
[&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full [&_svg]:max-w-full"
|
|
@@ -202,11 +202,11 @@
|
|
|
202
202
|
</div>
|
|
203
203
|
</div>
|
|
204
204
|
|
|
205
|
-
<!--
|
|
205
|
+
<!-- Кнопка 0 — 32 px по общему правилу кнопок-иконок (design-handoff, раздел 9) -->
|
|
206
206
|
<div class="absolute {label.name ? 'top-4' : 'top-0'} w-55 flex items-center justify-end">
|
|
207
207
|
<button
|
|
208
|
-
class="flex
|
|
209
|
-
|
|
208
|
+
class="flex size-[32px] cursor-pointer items-center justify-center rounded-full border border-(--hairline-color) bg-(--back-color) p-0.5 text-[15px] font-semibold
|
|
209
|
+
transition-colors duration-150 hover:border-(--border-color) [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full [&_svg]:max-w-full"
|
|
210
210
|
style="background: color-mix(in srgb, var(--bg-color), var(--back-color) 70%);"
|
|
211
211
|
title=""
|
|
212
212
|
onclick={() => (value = [0, 0, 0, 0])}
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
<!-- Боковые кнопки (ось roll) -->
|
|
219
219
|
{#if axes[2].name !== ""}
|
|
220
220
|
<div
|
|
221
|
-
class="absolute flex h-15 w-65 items-center justify-between rounded-full shadow-
|
|
221
|
+
class="absolute flex h-15 w-65 items-center justify-between rounded-full shadow-(--elevation-2)"
|
|
222
222
|
style="background: color-mix(in srgb, var(--bg-color), var(--shadow-color) 10%)"
|
|
223
223
|
>
|
|
224
224
|
<button
|
|
@@ -234,7 +234,7 @@
|
|
|
234
234
|
onUpdate(value)
|
|
235
235
|
}}
|
|
236
236
|
onmouseenter={(e) => (e.currentTarget.style.backgroundColor = "color-mix(in srgb, var(--bg-color), var(--shadow-color) 30%)")}
|
|
237
|
-
onmouseleave={(e) => (e.currentTarget.style.backgroundColor = "
|
|
237
|
+
onmouseleave={(e) => (e.currentTarget.style.backgroundColor = "")}
|
|
238
238
|
>
|
|
239
239
|
<svg xmlns="http://www.w3.org/2000/svg" class="segment-icon rotate-270" width="24" height="24" viewBox="0 0 24 24"
|
|
240
240
|
><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.5"
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
onUpdate(value)
|
|
259
259
|
}}
|
|
260
260
|
onmouseenter={(e) => (e.currentTarget.style.backgroundColor = "color-mix(in srgb, var(--bg-color), var(--shadow-color) 30%)")}
|
|
261
|
-
onmouseleave={(e) => (e.currentTarget.style.backgroundColor = "
|
|
261
|
+
onmouseleave={(e) => (e.currentTarget.style.backgroundColor = "")}
|
|
262
262
|
>
|
|
263
263
|
<svg xmlns="http://www.w3.org/2000/svg" class="segment-icon rotate-90" width="24" height="24" viewBox="0 0 24 24"
|
|
264
264
|
><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.5"
|
package/dist/Map/Map.svelte
CHANGED
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
<h5 class={twMerge(` w-full px-4 text-center`, label.class)}>{label.name}</h5>
|
|
165
165
|
{/if}
|
|
166
166
|
<MapLibre
|
|
167
|
-
class={twMerge("h-[calc(100%-2rem)] min-h-50 overflow-hidden rounded-
|
|
167
|
+
class={twMerge("h-[calc(100%-2rem)] min-h-50 overflow-hidden rounded-[14px] border border-(--hairline-color)", roleRingClass)}
|
|
168
168
|
style={isDarkMode ? "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json" : "https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"}
|
|
169
169
|
zoom={1.5}
|
|
170
170
|
center={{ lat: 30, lng: 0 }}
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
<div class="flex flex-col items-center justify-center leading-none">
|
|
223
223
|
<div
|
|
224
224
|
class="flex size-8 shrink-0 items-center justify-center [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full [&_svg]:max-w-full
|
|
225
|
-
{device.isFresh ? 'text-green-
|
|
225
|
+
{device.isFresh ? 'text-(--green-color)' : 'text-(--red-color)'}"
|
|
226
226
|
style="rotate: {device.NavHeading}deg;"
|
|
227
227
|
>
|
|
228
228
|
{#if markerIcon}
|
|
@@ -251,16 +251,14 @@
|
|
|
251
251
|
</div>
|
|
252
252
|
{/snippet}
|
|
253
253
|
|
|
254
|
-
<Popup closeButton={false} class="map-popup
|
|
254
|
+
<Popup closeButton={false} class="map-popup text-left">
|
|
255
255
|
<div class="flex flex-col gap-1.5">
|
|
256
256
|
<div class="flex items-center gap-1.5">
|
|
257
|
-
<span class="size-2 shrink-0 rounded-full {device.isFresh ? 'bg-green-
|
|
257
|
+
<span class="size-2 shrink-0 rounded-full {device.isFresh ? 'bg-(--green-color)' : 'bg-(--red-color)'}"></span>
|
|
258
258
|
<h6 class="text-sm leading-none font-bold">{device.DevName}</h6>
|
|
259
259
|
</div>
|
|
260
260
|
|
|
261
|
-
<div
|
|
262
|
-
class={`${twMerge("grid grid-cols-2 gap-x-3 gap-y-1 rounded-lg bg-(--container-color) p-2 text-xs", roleBgClass)} ${roleBgPaint}`}
|
|
263
|
-
>
|
|
261
|
+
<div class={`${twMerge("grid grid-cols-2 gap-x-3 gap-y-1 rounded-lg bg-(--container-color) p-2 text-xs", roleBgClass)} ${roleBgPaint}`}>
|
|
264
262
|
<div>
|
|
265
263
|
<p class="text-[0.6rem] font-semibold tracking-wide uppercase opacity-60">Lat / Lon</p>
|
|
266
264
|
<p class="font-medium">{device.NavLat.toFixed(5)}, {device.NavLon.toFixed(5)}</p>
|
|
@@ -281,7 +279,7 @@
|
|
|
281
279
|
|
|
282
280
|
<p class="text-[0.6rem] font-mono text-center tracking-wide uppercase">{device.DevSN}</p>
|
|
283
281
|
|
|
284
|
-
<div class="flex items-center justify-between border-t border-(--
|
|
282
|
+
<div class="flex items-center justify-between border-t border-(--hairline-color) pt-1">
|
|
285
283
|
<div class="relative flex items-center">
|
|
286
284
|
<button
|
|
287
285
|
class="flex cursor-pointer items-center gap-1 rounded-lg border-none bg-transparent px-1 py-0.5 opacity-70 transition hover:opacity-100"
|
|
@@ -309,7 +307,7 @@
|
|
|
309
307
|
</div>
|
|
310
308
|
|
|
311
309
|
<button
|
|
312
|
-
class="cursor-pointer rounded-lg border-none bg-transparent p-0.5 text-red-
|
|
310
|
+
class="cursor-pointer rounded-lg border-none bg-transparent p-0.5 text-(--red-color) transition hover:opacity-80"
|
|
313
311
|
aria-label="Delete"
|
|
314
312
|
title="Delete"
|
|
315
313
|
onclick={() => (devices = devices.filter((dev) => dev.DevSN !== device.DevSN))}
|
|
@@ -335,9 +333,14 @@
|
|
|
335
333
|
</div>
|
|
336
334
|
|
|
337
335
|
<style>
|
|
336
|
+
/* Попап по правилам карточки (design-handoff, раздел 9): радиус 14, линия, тень уровня 2 */
|
|
338
337
|
:global(.map-popup .maplibregl-popup-content) {
|
|
339
338
|
background-color: var(--back-color);
|
|
340
339
|
color: inherit;
|
|
340
|
+
border: 1px solid var(--hairline-color);
|
|
341
|
+
border-radius: 14px;
|
|
342
|
+
box-shadow: var(--elevation-2);
|
|
343
|
+
padding: 12px;
|
|
341
344
|
}
|
|
342
345
|
|
|
343
346
|
:global(.map-popup.maplibregl-popup-anchor-bottom .maplibregl-popup-tip) {
|
package/dist/Map/MapProps.svelte
CHANGED
|
@@ -29,9 +29,7 @@
|
|
|
29
29
|
),
|
|
30
30
|
)
|
|
31
31
|
|
|
32
|
-
const initialColor = $derived(
|
|
33
|
-
findColorOption($optionsStore.COLOR_OPTIONS, component.properties.wrapperClass),
|
|
34
|
-
)
|
|
32
|
+
const initialColor = $derived(findColorOption($optionsStore.COLOR_OPTIONS, component.properties.wrapperClass))
|
|
35
33
|
</script>
|
|
36
34
|
|
|
37
35
|
{#if forConstructor}
|