poe-svelte-ui-lib 1.37.2 → 1.38.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/dist/CommonSnippets.svelte +0 -4
- package/dist/WidgetMap/MapIcon.svelte +12 -0
- package/dist/WidgetMap/MapIcon.svelte.d.ts +18 -0
- package/dist/WidgetMap/README.md +66 -0
- package/dist/WidgetMap/WidgetMap.svelte +381 -0
- package/dist/WidgetMap/WidgetMap.svelte.d.ts +4 -0
- package/dist/WidgetMap/WidgetMapProps.svelte +78 -0
- package/dist/WidgetMap/WidgetMapProps.svelte.d.ts +14 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/locales/translations.js +6 -5
- package/dist/types.d.ts +29 -25
- package/package.json +1 -1
- package/dist/Map/Map.svelte +0 -388
- package/dist/Map/Map.svelte.d.ts +0 -4
- package/dist/Map/MapProps.svelte +0 -115
- package/dist/Map/MapProps.svelte.d.ts +0 -16
- package/dist/Map/README.md +0 -149
- /package/dist/{Map → WidgetMap}/mapWrapper/Line.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/Line.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/MapLibre.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/MapLibre.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/Marker.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/Marker.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/Popup.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/Popup.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/contexts.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/contexts.svelte.js +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/CustomControl.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/CustomControl.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/FullScreenControl.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/FullScreenControl.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/GeolocateControl.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/GeolocateControl.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/NavigationControl.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/NavigationControl.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/ScaleControl.svelte +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/controls/ScaleControl.svelte.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/index.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/index.js +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/types.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/types.js +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/utils.d.ts +0 -0
- /package/dist/{Map → WidgetMap}/mapWrapper/utils.js +0 -0
|
@@ -65,7 +65,6 @@
|
|
|
65
65
|
component.type === "ProgressBar" ||
|
|
66
66
|
component.type === "TextField" ||
|
|
67
67
|
component.type === "Graph" ||
|
|
68
|
-
component.type === "Map" ||
|
|
69
68
|
component.type === "PeriodChart"
|
|
70
69
|
? $optionsStore.ACCESS_OPTION.filter((o) => o.value !== "viewOnly")
|
|
71
70
|
: $optionsStore.ACCESS_OPTION}
|
|
@@ -101,7 +100,6 @@
|
|
|
101
100
|
| UI.ITableProps<object>
|
|
102
101
|
| UI.IFileAttachProps
|
|
103
102
|
| UI.IJoystickProps
|
|
104
|
-
| UI.IMapProps
|
|
105
103
|
).label?.name}
|
|
106
104
|
onUpdate={(value) => updateProperty("label.name", value as string, component, onPropertyChange)}
|
|
107
105
|
/>
|
|
@@ -128,7 +126,6 @@
|
|
|
128
126
|
| UI.ITableProps<object>
|
|
129
127
|
| UI.IFileAttachProps
|
|
130
128
|
| UI.IJoystickProps
|
|
131
|
-
| UI.IMapProps
|
|
132
129
|
).label?.class,
|
|
133
130
|
(option as UI.IOption<string>).value,
|
|
134
131
|
),
|
|
@@ -152,7 +149,6 @@
|
|
|
152
149
|
| UI.ITableProps<object>
|
|
153
150
|
| UI.IFileAttachProps
|
|
154
151
|
| UI.IJoystickProps
|
|
155
|
-
| UI.IMapProps
|
|
156
152
|
).label?.class}
|
|
157
153
|
onUpdate={(value) => updateProperty("label.class", value as string, component, onPropertyChange)}
|
|
158
154
|
/>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script lang="ts"></script>
|
|
2
|
+
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"
|
|
4
|
+
><path
|
|
5
|
+
fill="none"
|
|
6
|
+
stroke="currentColor"
|
|
7
|
+
stroke-linecap="round"
|
|
8
|
+
stroke-linejoin="round"
|
|
9
|
+
stroke-width="2"
|
|
10
|
+
d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2zm0 0v14m6-12v14"
|
|
11
|
+
/></svg
|
|
12
|
+
>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const MapIcon: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type MapIcon = InstanceType<typeof MapIcon>;
|
|
18
|
+
export default MapIcon;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# WidgetMap Component
|
|
2
|
+
|
|
3
|
+
## Описание
|
|
4
|
+
|
|
5
|
+
> **Размеры.** Ширина — 100% контейнера (в конструкторе — ширина ячейки сетки); высота карты задаётся пропом `height` (px), в сетке конструктора виджет занимает одну строку. Мастер-цвет (`componentClass`) перекрашивает шапку.
|
|
6
|
+
|
|
7
|
+
Смарт-виджет «Карта» — положение бортов на карте MapLibre с траекториями. Работает с полями групп устройства
|
|
8
|
+
(по умолчанию `MAV`): каждая группа из `groups` — отдельный борт со своим маркером и своей траекторией, например
|
|
9
|
+
`["MAV", "GNSS"]` — позиция автопилота и собственного GNSS-приёмника модуля. Только отображение: ничего не
|
|
10
|
+
отправляет и не знает про DeviceStore/WebSocket. Заменяет удалённый компонент `Map`.
|
|
11
|
+
|
|
12
|
+
- **Поверх карты** (решает оператор): траектория вкл/выкл и число её точек, таймаут маркеров, кнопка «Все борта»
|
|
13
|
+
(иконка рамки под зумом и полноэкранным режимом) — вписывает в экран все видимые борта, один борт — приближение
|
|
14
|
+
к нему (зум 16). Сама карта вид не меняет.
|
|
15
|
+
- **Свежесть.** Борт зелёный, пока его значения менялись за таймаут; без изменений — красный; ещё через таймаут
|
|
16
|
+
скрывается до новых данных. Кнопка в карточке борта скрывает его до следующего изменения.
|
|
17
|
+
- **Траектория** — точка добавляется только при смене координат (курс и высота могут обновляться чаще позиции).
|
|
18
|
+
- **Шапка** — сколько бортов на связи из заданных: зелёный — все, серый — часть, красный — ни одного.
|
|
19
|
+
- Карта светлая/тёмная по теме приложения (событие `ThemeChange`).
|
|
20
|
+
|
|
21
|
+
## Поля группы
|
|
22
|
+
|
|
23
|
+
| Поле | Что |
|
|
24
|
+
| --------- | ----------------------------------------- |
|
|
25
|
+
| `Lat` | широта, °; вместе с `Lon` = 0 — нет фикса |
|
|
26
|
+
| `Lon` | долгота, ° |
|
|
27
|
+
| `Alt` | высота, м — в карточке борта |
|
|
28
|
+
| `Heading` | курс, 0..360° — поворот маркера |
|
|
29
|
+
| `Sat` | спутников — в карточке борта |
|
|
30
|
+
|
|
31
|
+
В DevCloud и WebApp GUIPreview собирает `value` сам: `{ [группа]: { Lat: <ModSN>|<группа>.Lat, ... } }`.
|
|
32
|
+
|
|
33
|
+
## Пропсы
|
|
34
|
+
|
|
35
|
+
| Название | Тип | По умолчанию | Описание |
|
|
36
|
+
| ---------------- | ----------------------------------------------- | ------------------- | --------------------------------------------------------------- |
|
|
37
|
+
| `wrapperClass` | `string` | `""` | CSS-классы обёртки |
|
|
38
|
+
| `componentClass` | `string` | `""` | «Мастер-цвет» виджета — роль вида `"bg-blue"` |
|
|
39
|
+
| `label` | `{ name?: string }` | `{ name: "Карта" }` | Заголовок карточки |
|
|
40
|
+
| `groups` | `string[]` | `["MAV"]` | Префиксы групп полей — по борту на группу |
|
|
41
|
+
| `value` | `Record<string, Partial<IWidgetMapData>>` | `undefined` | Значения по группам |
|
|
42
|
+
| `keys` | `Partial<Record<keyof IWidgetMapData, string>>` | `undefined` | Переопределение имён полей устройства (используется GUIPreview) |
|
|
43
|
+
| `height` | `number` | `400` | Высота карты, px |
|
|
44
|
+
| `markerIcon` | `ConstructorOfATypedSvelteComponent \| string` | `undefined` | Иконка маркера (SVG-строка или компонент), по умолчанию стрелка |
|
|
45
|
+
| `trackEnabled` | `boolean` | `false` | Начальное состояние «Траектория» (`$bindable`) |
|
|
46
|
+
| `trackLength` | `number` | `1000` | Начальное число точек траектории (`$bindable`) |
|
|
47
|
+
| `markerTimeout` | `number` | `30000` | Начальный таймаут маркеров, мс (`$bindable`) |
|
|
48
|
+
| `collapsed` | `boolean` | `false` | Свёрнуто ли тело виджета (`$bindable`) |
|
|
49
|
+
| `persistKey` | `string` | `undefined` | Ключ для сохранения `collapsed` в `localStorage` |
|
|
50
|
+
|
|
51
|
+
## Пример
|
|
52
|
+
|
|
53
|
+
```svelte
|
|
54
|
+
<UI.WidgetMap groups={["MAV", "GNSS"]} value={{ MAV: mav, GNSS: gnss }} height={400} trackEnabled />
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Конструктор свойств (WidgetMapProps.svelte)
|
|
58
|
+
|
|
59
|
+
Группы панели: общие (заголовок, группы полей через запятую, мастер-цвет), оформление (высота карты, иконка
|
|
60
|
+
маркера), по умолчанию (траектория и её длина — оператор меняет их на карте).
|
|
61
|
+
|
|
62
|
+
## Внутренняя архитектура
|
|
63
|
+
|
|
64
|
+
`mapWrapper/` — тонкие Svelte-обёртки над MapLibre GL (`MapLibre`, `Marker`, `Popup`, `Line`, контролы,
|
|
65
|
+
`CustomControl` для своих элементов поверх карты). MapLibre подгружается при монтировании; без интернета
|
|
66
|
+
показывается заглушка «Карта не загружена».
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
<!-- $lib/WidgetMap/WidgetMap.svelte — смарт-виджет «Карта»: борта из групп полей устройства (по умолчанию MAV) с полями
|
|
2
|
+
Lat/Lon/Alt/Heading/Sat (см. IWidgetMapData), каждая группа — свой маркер и своя траектория. Только отображение:
|
|
3
|
+
ничего не отправляет и не знает про DeviceStore/WebSocket. Траекторию, длину трека, таймаут маркеров и «Все борта»
|
|
4
|
+
оператор переключает прямо поверх карты; вид карта сама не меняет — бортов может быть много. -->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { onMount, untrack } from "svelte"
|
|
7
|
+
import { slide } from "svelte/transition"
|
|
8
|
+
import { twMerge } from "tailwind-merge"
|
|
9
|
+
import { T } from "../locales/i18n"
|
|
10
|
+
import type { IWidgetMapProps } from "../types"
|
|
11
|
+
import CopiedChip from "../CopiedChip.svelte"
|
|
12
|
+
import WidgetHeader from "../WidgetHeader.svelte"
|
|
13
|
+
import { widgetAccentStyle } from "../widgetAccent"
|
|
14
|
+
import { readPersistedCollapsed, writePersistedCollapsed } from "../widgetCollapse"
|
|
15
|
+
import MapIcon from "./MapIcon.svelte"
|
|
16
|
+
import { MapLibre, NavigationControl, ScaleControl, GeolocateControl, FullScreenControl, Marker, Popup, Line, CustomControl } from "./mapWrapper"
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
wrapperClass = "",
|
|
20
|
+
componentClass = "",
|
|
21
|
+
label = { name: "Карта" },
|
|
22
|
+
groups = ["MAV"],
|
|
23
|
+
value,
|
|
24
|
+
height = 400,
|
|
25
|
+
markerIcon,
|
|
26
|
+
trackEnabled = $bindable(false),
|
|
27
|
+
trackLength = $bindable(1000),
|
|
28
|
+
markerTimeout = $bindable(30_000),
|
|
29
|
+
collapsed = $bindable(false),
|
|
30
|
+
persistKey,
|
|
31
|
+
}: IWidgetMapProps = $props()
|
|
32
|
+
|
|
33
|
+
let accentStyle = $derived(widgetAccentStyle(componentClass ?? ""))
|
|
34
|
+
|
|
35
|
+
/* Сворачивание тела по клику на шапку — как у остальных смарт-виджетов (см. WidgetWiFi.svelte) */
|
|
36
|
+
let hasMergedPersisted = false
|
|
37
|
+
$effect(() => {
|
|
38
|
+
if (hasMergedPersisted) return
|
|
39
|
+
hasMergedPersisted = true
|
|
40
|
+
const persisted = readPersistedCollapsed(persistKey, collapsed)
|
|
41
|
+
if (persisted !== collapsed) collapsed = persisted
|
|
42
|
+
})
|
|
43
|
+
$effect(() => writePersistedCollapsed(persistKey, collapsed))
|
|
44
|
+
|
|
45
|
+
interface Board {
|
|
46
|
+
group: string
|
|
47
|
+
lat: number
|
|
48
|
+
lon: number
|
|
49
|
+
alt: number
|
|
50
|
+
heading: number
|
|
51
|
+
sat: number
|
|
52
|
+
track: [number, number][]
|
|
53
|
+
lastChange: number
|
|
54
|
+
hiddenAt: number
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const num = (v: unknown, fallback = 0) => (typeof v === "number" && Number.isFinite(v) ? v : fallback)
|
|
58
|
+
/* (0, 0) и нечисловые координаты — признак отсутствия фикса */
|
|
59
|
+
const hasFix = (lat: unknown, lon: unknown) => Number.isFinite(lat) && Number.isFinite(lon) && (lat !== 0 || lon !== 0)
|
|
60
|
+
|
|
61
|
+
let groupList = $derived(groups.map((g) => g.trim()).filter(Boolean))
|
|
62
|
+
let boards: Board[] = $state([])
|
|
63
|
+
let now = $state(Date.now())
|
|
64
|
+
let mapInstance: any = $state()
|
|
65
|
+
let isCopied = $state(false)
|
|
66
|
+
let isDarkMode = $state(false)
|
|
67
|
+
|
|
68
|
+
/* Борт обновляется только при реальной смене значений — свежесть считается от последнего изменения, а не от перерисовки */
|
|
69
|
+
$effect(() => {
|
|
70
|
+
for (const group of groupList) {
|
|
71
|
+
const v = value?.[group]
|
|
72
|
+
if (!v || !hasFix(v.Lat, v.Lon)) continue
|
|
73
|
+
const lat = v.Lat as number
|
|
74
|
+
const lon = v.Lon as number
|
|
75
|
+
const alt = num(v.Alt)
|
|
76
|
+
const heading = num(v.Heading)
|
|
77
|
+
const sat = num(v.Sat)
|
|
78
|
+
untrack(() => {
|
|
79
|
+
const idx = boards.findIndex((b) => b.group === group)
|
|
80
|
+
const prev = idx === -1 ? null : boards[idx]
|
|
81
|
+
if (prev && prev.lat === lat && prev.lon === lon && prev.alt === alt && prev.heading === heading && prev.sat === sat) return
|
|
82
|
+
const moved = !prev || prev.lat !== lat || prev.lon !== lon
|
|
83
|
+
const track = moved ? [...(prev?.track ?? []), [lon, lat] as [number, number]].slice(-trackLength) : prev!.track
|
|
84
|
+
const next: Board = { group, lat, lon, alt, heading, sat, track, lastChange: Date.now(), hiddenAt: prev?.hiddenAt ?? 0 }
|
|
85
|
+
if (idx === -1) boards.push(next)
|
|
86
|
+
else boards[idx] = next
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
/* Подрезает накопленные траектории при уменьшении trackLength */
|
|
92
|
+
$effect(() => {
|
|
93
|
+
const limit = trackLength
|
|
94
|
+
untrack(() => boards.forEach((b) => b.track.length > limit && (b.track = b.track.slice(-limit))))
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
$effect(() => {
|
|
98
|
+
const timer = setInterval(() => (now = Date.now()), 1000)
|
|
99
|
+
return () => clearInterval(timer)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
/* Свежий — менялся за markerTimeout; устаревший (красный) — ещё markerTimeout; дальше скрыт до новых данных */
|
|
103
|
+
let visibleBoards = $derived(boards.filter((b) => groupList.includes(b.group) && b.lastChange > b.hiddenAt && now - b.lastChange < markerTimeout * 2))
|
|
104
|
+
const isFresh = (b: Board) => now - b.lastChange < markerTimeout
|
|
105
|
+
let freshCount = $derived(visibleBoards.filter(isFresh).length)
|
|
106
|
+
|
|
107
|
+
/* Вписывает в экран все видимые борта, один борт — приближение к нему */
|
|
108
|
+
const fitAllBoards = () => {
|
|
109
|
+
if (!mapInstance || visibleBoards.length === 0) return
|
|
110
|
+
if (visibleBoards.length === 1) return mapInstance.flyTo({ center: [visibleBoards[0].lon, visibleBoards[0].lat], zoom: 16 })
|
|
111
|
+
const lons = visibleBoards.map((b) => b.lon)
|
|
112
|
+
const lats = visibleBoards.map((b) => b.lat)
|
|
113
|
+
mapInstance.fitBounds(
|
|
114
|
+
[
|
|
115
|
+
[Math.min(...lons), Math.min(...lats)],
|
|
116
|
+
[Math.max(...lons), Math.max(...lats)],
|
|
117
|
+
],
|
|
118
|
+
{ padding: 60, maxZoom: 16 },
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const hideBoard = (group: string) => {
|
|
123
|
+
const b = boards.find((x) => x.group === group)
|
|
124
|
+
if (b) b.hiddenAt = b.lastChange
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const copyBoard = (b: Board) => {
|
|
128
|
+
navigator.clipboard.writeText(
|
|
129
|
+
`${b.group}\nLat: ${b.lat.toFixed(6)} | Lon: ${b.lon.toFixed(6)} | Alt: ${b.alt.toFixed(1)}\nHeading: ${b.heading.toFixed(1)} | Satellites: ${b.sat}`,
|
|
130
|
+
)
|
|
131
|
+
isCopied = true
|
|
132
|
+
setTimeout(() => (isCopied = false), 1000)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const handleThemeChange = (event: CustomEvent) => {
|
|
136
|
+
isDarkMode = !event.detail.currentTheme
|
|
137
|
+
}
|
|
138
|
+
onMount(() => {
|
|
139
|
+
isDarkMode = localStorage.getItem("AppTheme") !== "light"
|
|
140
|
+
window.addEventListener("ThemeChange", handleThemeChange as EventListener)
|
|
141
|
+
return () => window.removeEventListener("ThemeChange", handleThemeChange as EventListener)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
const trackLengthOptions = [100, 500, 1000, 5000, 10000, 50000]
|
|
145
|
+
const timeoutOptions: { label: string; value: number }[] = [
|
|
146
|
+
{ label: "30 sec", value: 30_000 },
|
|
147
|
+
{ label: "1 min", value: 60_000 },
|
|
148
|
+
{ label: "3 min", value: 180_000 },
|
|
149
|
+
{ label: "5 min", value: 300_000 },
|
|
150
|
+
{ label: "10 min", value: 600_000 },
|
|
151
|
+
{ label: "30 min", value: 1_800_000 },
|
|
152
|
+
{ label: "1 h", value: 3_600_000 },
|
|
153
|
+
]
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
<div
|
|
157
|
+
class={twMerge("relative flex w-full flex-col gap-4 rounded-2xl border border-(--hairline-color) bg-(--container-color) p-4", wrapperClass)}
|
|
158
|
+
style={accentStyle}
|
|
159
|
+
>
|
|
160
|
+
<WidgetHeader icon={MapIcon} label={label?.name ?? "Карта"} bind:collapsed>
|
|
161
|
+
{#snippet right()}
|
|
162
|
+
<span
|
|
163
|
+
class="text-[12px] font-semibold tabular-nums {freshCount === 0
|
|
164
|
+
? 'text-(--red-color)'
|
|
165
|
+
: freshCount < groupList.length
|
|
166
|
+
? 'text-(--muted-color)'
|
|
167
|
+
: 'text-(--green-color)'}"
|
|
168
|
+
title={$T("constructor.props.map.boards")}
|
|
169
|
+
>
|
|
170
|
+
{freshCount} / {groupList.length}
|
|
171
|
+
</span>
|
|
172
|
+
{/snippet}
|
|
173
|
+
</WidgetHeader>
|
|
174
|
+
|
|
175
|
+
{#if !collapsed}
|
|
176
|
+
<div transition:slide={{ duration: 150 }} style="height: {height}px">
|
|
177
|
+
<MapLibre
|
|
178
|
+
bind:map={mapInstance}
|
|
179
|
+
class="h-full w-full overflow-hidden rounded-[14px] border border-(--hairline-color)"
|
|
180
|
+
style={isDarkMode ? "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json" : "https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"}
|
|
181
|
+
zoom={1.5}
|
|
182
|
+
center={{ lat: 30, lng: 0 }}
|
|
183
|
+
>
|
|
184
|
+
<NavigationControl />
|
|
185
|
+
<ScaleControl />
|
|
186
|
+
<GeolocateControl />
|
|
187
|
+
<FullScreenControl />
|
|
188
|
+
|
|
189
|
+
<!-- Панель оператора поверх карты -->
|
|
190
|
+
<CustomControl position="top-left">
|
|
191
|
+
<div class="flex flex-wrap items-center gap-3 rounded-lg px-2 py-1 text-black">
|
|
192
|
+
<label class="flex items-center gap-1.5 text-sm font-medium">
|
|
193
|
+
<input type="checkbox" bind:checked={trackEnabled} />
|
|
194
|
+
{$T("constructor.props.map.track")}
|
|
195
|
+
</label>
|
|
196
|
+
{#if trackEnabled}
|
|
197
|
+
<div class="flex items-center gap-2">
|
|
198
|
+
<span class="text-sm font-medium">{$T("constructor.props.map.trackLength")}</span>
|
|
199
|
+
<select class="rounded px-2 py-1 text-sm" bind:value={trackLength}>
|
|
200
|
+
{#each trackLengthOptions as opt}
|
|
201
|
+
<option value={opt}>{opt}</option>
|
|
202
|
+
{/each}
|
|
203
|
+
</select>
|
|
204
|
+
</div>
|
|
205
|
+
{/if}
|
|
206
|
+
<div class="flex items-center gap-2">
|
|
207
|
+
<span class="text-sm font-medium">{$T("constructor.props.map.timeout")}</span>
|
|
208
|
+
<select class="rounded px-2 py-1 text-sm" bind:value={markerTimeout}>
|
|
209
|
+
{#each timeoutOptions as opt}
|
|
210
|
+
<option value={opt.value}>{opt.label}</option>
|
|
211
|
+
{/each}
|
|
212
|
+
</select>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
</CustomControl>
|
|
216
|
+
|
|
217
|
+
<!-- Штатная кнопка карты в колонке зума/геолокации/полного экрана -->
|
|
218
|
+
<CustomControl position="top-right">
|
|
219
|
+
<button
|
|
220
|
+
type="button"
|
|
221
|
+
class="flex! items-center justify-center text-[#333] disabled:opacity-40"
|
|
222
|
+
title={$T("constructor.props.map.fitAll")}
|
|
223
|
+
aria-label={$T("constructor.props.map.fitAll")}
|
|
224
|
+
disabled={visibleBoards.length === 0}
|
|
225
|
+
onclick={fitAllBoards}
|
|
226
|
+
>
|
|
227
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
|
|
228
|
+
<path
|
|
229
|
+
fill="none"
|
|
230
|
+
stroke="currentColor"
|
|
231
|
+
stroke-linecap="round"
|
|
232
|
+
stroke-linejoin="round"
|
|
233
|
+
stroke-width="2"
|
|
234
|
+
d="M4 9V5a1 1 0 0 1 1-1h4m6 0h4a1 1 0 0 1 1 1v4m0 6v4a1 1 0 0 1-1 1h-4m-6 0H5a1 1 0 0 1-1-1v-4m5-3a3 3 0 1 0 6 0a3 3 0 1 0-6 0"
|
|
235
|
+
/>
|
|
236
|
+
</svg>
|
|
237
|
+
</button>
|
|
238
|
+
</CustomControl>
|
|
239
|
+
|
|
240
|
+
{#if trackEnabled}
|
|
241
|
+
{#each visibleBoards as board (board.group)}
|
|
242
|
+
{#if board.track.length >= 2}
|
|
243
|
+
<Line id={`track-${board.group}`} coordinates={board.track} color={isFresh(board) ? "#22c55e" : "#ef4444"} />
|
|
244
|
+
{/if}
|
|
245
|
+
{/each}
|
|
246
|
+
{/if}
|
|
247
|
+
|
|
248
|
+
{#each visibleBoards as board (board.group)}
|
|
249
|
+
<Marker lnglat={{ lng: board.lon, lat: board.lat }}>
|
|
250
|
+
{#snippet content()}
|
|
251
|
+
<div class="flex flex-col items-center justify-center leading-none">
|
|
252
|
+
<div
|
|
253
|
+
class="flex size-8 shrink-0 items-center justify-center [&_svg]:h-full [&_svg]:max-h-full [&_svg]:w-full [&_svg]:max-w-full
|
|
254
|
+
{isFresh(board) ? 'text-(--green-color)' : 'text-(--red-color)'}"
|
|
255
|
+
style="rotate: {board.heading}deg;"
|
|
256
|
+
>
|
|
257
|
+
{#if markerIcon}
|
|
258
|
+
{#if typeof markerIcon === "string"}
|
|
259
|
+
{@html markerIcon}
|
|
260
|
+
{:else}
|
|
261
|
+
{@const IconComponent = markerIcon}
|
|
262
|
+
<IconComponent />
|
|
263
|
+
{/if}
|
|
264
|
+
{:else}
|
|
265
|
+
<div class="rotate-270">
|
|
266
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
|
|
267
|
+
<path
|
|
268
|
+
fill="none"
|
|
269
|
+
stroke="currentColor"
|
|
270
|
+
stroke-linecap="round"
|
|
271
|
+
stroke-linejoin="round"
|
|
272
|
+
stroke-width="1.5"
|
|
273
|
+
d="M14.76 12H6.832m0 0c0-.275-.057-.55-.17-.808L4.285 5.814c-.76-1.72 1.058-3.442 2.734-2.591L20.8 10.217c1.46.74 1.46 2.826 0 3.566L7.02 20.777c-1.677.851-3.495-.872-2.735-2.591l2.375-5.378A2 2 0 0 0 6.83 12"
|
|
274
|
+
/></svg
|
|
275
|
+
>
|
|
276
|
+
</div>
|
|
277
|
+
{/if}
|
|
278
|
+
</div>
|
|
279
|
+
<p class="font-bold">{board.group}</p>
|
|
280
|
+
</div>
|
|
281
|
+
{/snippet}
|
|
282
|
+
|
|
283
|
+
<Popup closeButton={false} class="map-popup text-left">
|
|
284
|
+
<div class="flex flex-col gap-1.5">
|
|
285
|
+
<div class="flex items-center gap-1.5">
|
|
286
|
+
<span class="size-2 shrink-0 rounded-full {isFresh(board) ? 'bg-(--green-color)' : 'bg-(--red-color)'}"></span>
|
|
287
|
+
<h6 class="text-sm leading-none font-bold">{board.group}</h6>
|
|
288
|
+
</div>
|
|
289
|
+
|
|
290
|
+
<div class="grid grid-cols-2 gap-x-3 gap-y-1 rounded-lg bg-(--container-color) p-2 text-xs">
|
|
291
|
+
<div>
|
|
292
|
+
<p class="text-[0.6rem] font-semibold tracking-wide uppercase opacity-60">Lat / Lon</p>
|
|
293
|
+
<p class="font-medium">{board.lat.toFixed(6)}, {board.lon.toFixed(6)}</p>
|
|
294
|
+
</div>
|
|
295
|
+
<div>
|
|
296
|
+
<p class="text-[0.6rem] font-semibold tracking-wide uppercase opacity-60">Alt</p>
|
|
297
|
+
<p class="font-medium">{board.alt.toFixed(1)} m</p>
|
|
298
|
+
</div>
|
|
299
|
+
<div>
|
|
300
|
+
<p class="text-[0.6rem] font-semibold tracking-wide uppercase opacity-60">Heading</p>
|
|
301
|
+
<p class="font-medium">{board.heading.toFixed(1)}°</p>
|
|
302
|
+
</div>
|
|
303
|
+
<div>
|
|
304
|
+
<p class="text-[0.6rem] font-semibold tracking-wide uppercase opacity-60">Satellites</p>
|
|
305
|
+
<p class="font-medium">{board.sat}</p>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
|
|
309
|
+
<div class="flex items-center justify-between border-t border-(--hairline-color) pt-1">
|
|
310
|
+
<div class="relative flex items-center">
|
|
311
|
+
<button
|
|
312
|
+
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"
|
|
313
|
+
onclick={(e) => {
|
|
314
|
+
e.preventDefault()
|
|
315
|
+
copyBoard(board)
|
|
316
|
+
}}
|
|
317
|
+
aria-label="Copy"
|
|
318
|
+
title="Copy"
|
|
319
|
+
>
|
|
320
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1.25rem" height="1.25rem" viewBox="0 0 24 24">
|
|
321
|
+
<g fill="none" stroke="currentColor" stroke-width="1.5">
|
|
322
|
+
<path
|
|
323
|
+
d="M6 11c0-2.828 0-4.243.879-5.121C7.757 5 9.172 5 12 5h3c2.828 0 4.243 0 5.121.879C21 6.757 21 8.172 21 11v5c0 2.828 0 4.243-.879 5.121C19.243 22 17.828 22 15 22h-3c-2.828 0-4.243 0-5.121-.879C6 20.243 6 18.828 6 16z"
|
|
324
|
+
/>
|
|
325
|
+
<path d="M6 19a3 3 0 0 1-3-3v-6c0-3.771 0-5.657 1.172-6.828S7.229 2 11 2h4a3 3 0 0 1 3 3" />
|
|
326
|
+
</g>
|
|
327
|
+
</svg>
|
|
328
|
+
</button>
|
|
329
|
+
<CopiedChip show={isCopied} class="-top-1 right-0 -translate-y-full" />
|
|
330
|
+
</div>
|
|
331
|
+
|
|
332
|
+
<button
|
|
333
|
+
class="cursor-pointer rounded-lg border-none bg-transparent p-0.5 text-(--red-color) transition hover:opacity-80"
|
|
334
|
+
aria-label="Hide"
|
|
335
|
+
title="Hide"
|
|
336
|
+
onclick={() => hideBoard(board.group)}
|
|
337
|
+
>
|
|
338
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1.25rem" height="1.25rem" viewBox="0 0 24 24"
|
|
339
|
+
><path
|
|
340
|
+
fill="none"
|
|
341
|
+
stroke="currentColor"
|
|
342
|
+
stroke-linecap="round"
|
|
343
|
+
stroke-linejoin="round"
|
|
344
|
+
stroke-width="1.5"
|
|
345
|
+
d="m19.5 5.5l-.62 10.025c-.158 2.561-.237 3.842-.88 4.763a4 4 0 0 1-1.2 1.128c-.957.584-2.24.584-4.806.584c-2.57 0-3.855 0-4.814-.585a4 4 0 0 1-1.2-1.13c-.642-.922-.72-2.205-.874-4.77L4.5 5.5M3 5.5h18m-4.944 0l-.683-1.408c-.453-.936-.68-1.403-1.071-1.695a2 2 0 0 0-.275-.172C13.594 2 13.074 2 12.035 2c-1.066 0-1.599 0-2.04.234a2 2 0 0 0-.278.18c-.395.303-.616.788-1.058 1.757L8.053 5.5m1.447 11v-6m5 6v-6"
|
|
346
|
+
/></svg
|
|
347
|
+
>
|
|
348
|
+
</button>
|
|
349
|
+
</div>
|
|
350
|
+
</div>
|
|
351
|
+
</Popup>
|
|
352
|
+
</Marker>
|
|
353
|
+
{/each}
|
|
354
|
+
</MapLibre>
|
|
355
|
+
</div>
|
|
356
|
+
{/if}
|
|
357
|
+
</div>
|
|
358
|
+
|
|
359
|
+
<style>
|
|
360
|
+
/* Попап по правилам карточки (design-handoff, раздел 9): радиус 14, линия, тень уровня 2 */
|
|
361
|
+
:global(.map-popup .maplibregl-popup-content) {
|
|
362
|
+
background-color: var(--back-color);
|
|
363
|
+
color: inherit;
|
|
364
|
+
border: 1px solid var(--hairline-color);
|
|
365
|
+
border-radius: 14px;
|
|
366
|
+
box-shadow: var(--elevation-2);
|
|
367
|
+
padding: 12px;
|
|
368
|
+
}
|
|
369
|
+
:global(.map-popup.maplibregl-popup-anchor-bottom .maplibregl-popup-tip) {
|
|
370
|
+
border-top-color: var(--back-color);
|
|
371
|
+
}
|
|
372
|
+
:global(.map-popup.maplibregl-popup-anchor-top .maplibregl-popup-tip) {
|
|
373
|
+
border-bottom-color: var(--back-color);
|
|
374
|
+
}
|
|
375
|
+
:global(.map-popup.maplibregl-popup-anchor-left .maplibregl-popup-tip) {
|
|
376
|
+
border-right-color: var(--back-color);
|
|
377
|
+
}
|
|
378
|
+
:global(.map-popup.maplibregl-popup-anchor-right .maplibregl-popup-tip) {
|
|
379
|
+
border-left-color: var(--back-color);
|
|
380
|
+
}
|
|
381
|
+
</style>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<!-- $lib/WidgetMap/WidgetMapProps.svelte — панель пропсов конструктора для WidgetMap: заголовок, группы полей
|
|
2
|
+
(каждая — борт), мастер-цвет, высота карты, иконка маркера и начальные значения переключателей оператора. -->
|
|
3
|
+
<script lang="ts">
|
|
4
|
+
import { T } from "../locales/i18n"
|
|
5
|
+
import * as UI from ".."
|
|
6
|
+
import { updateProperty, type UIComponent, type IWidgetMapProps } from "../types"
|
|
7
|
+
import { ICONS } from "../icons"
|
|
8
|
+
import WidgetAccentPicker from "../WidgetAccentPicker.svelte"
|
|
9
|
+
import CommonSnippets from "../CommonSnippets.svelte"
|
|
10
|
+
import PropsGroup from "../PropsGroup.svelte"
|
|
11
|
+
|
|
12
|
+
const { component, onPropertyChange } = $props<{
|
|
13
|
+
component: UIComponent & { properties: Partial<IWidgetMapProps> }
|
|
14
|
+
onPropertyChange: (updates: Partial<{ properties?: string | object; name?: string; access?: string }>) => void
|
|
15
|
+
}>()
|
|
16
|
+
|
|
17
|
+
const HEIGHT_OPTIONS = [250, 300, 400, 500, 600, 800].map((value) => ({ id: crypto.randomUUID(), value, name: `${value} px` }))
|
|
18
|
+
const TRACK_LENGTH_OPTIONS = [100, 500, 1000, 5000, 10000, 50000].map((value) => ({ id: crypto.randomUUID(), value, name: String(value) }))
|
|
19
|
+
|
|
20
|
+
/* Группы вводятся через запятую: "MAV, GNSS" */
|
|
21
|
+
const setGroups = (raw: unknown) => {
|
|
22
|
+
const list = String(raw ?? "")
|
|
23
|
+
.split(",")
|
|
24
|
+
.map((g) => g.trim())
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
updateProperty("groups", list.length ? list : ["MAV"], component, onPropertyChange)
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<div class="flex flex-col gap-2">
|
|
31
|
+
<PropsGroup label={$T("constructor.props.group.general")}>
|
|
32
|
+
<UI.Input
|
|
33
|
+
label={{ name: "Заголовок" }}
|
|
34
|
+
value={component.properties.label?.name}
|
|
35
|
+
onUpdate={(value) => updateProperty("label.name", value as string, component, onPropertyChange)}
|
|
36
|
+
/>
|
|
37
|
+
<UI.Input label={{ name: "Группы полей (через запятую)" }} value={(component.properties.groups ?? ["MAV"]).join(", ")} onUpdate={setGroups} />
|
|
38
|
+
<WidgetAccentPicker
|
|
39
|
+
value={component.properties.componentClass ?? ""}
|
|
40
|
+
onUpdate={(value) => updateProperty("componentClass", value, component, onPropertyChange)}
|
|
41
|
+
/>
|
|
42
|
+
</PropsGroup>
|
|
43
|
+
<PropsGroup label={$T("constructor.props.group.appearance")}>
|
|
44
|
+
<UI.Select
|
|
45
|
+
label={{ name: "Высота карты" }}
|
|
46
|
+
type="buttons"
|
|
47
|
+
options={HEIGHT_OPTIONS}
|
|
48
|
+
value={HEIGHT_OPTIONS.find((opt) => opt.value === (component.properties.height ?? 400))}
|
|
49
|
+
onUpdate={(option) => updateProperty("height", (option as { value: number }).value, component, onPropertyChange)}
|
|
50
|
+
/>
|
|
51
|
+
<CommonSnippets
|
|
52
|
+
snippet="IconsLib"
|
|
53
|
+
initialValue={{
|
|
54
|
+
name: $T("constructor.props.markerIcon"),
|
|
55
|
+
icon: component.properties.markerIcon,
|
|
56
|
+
updateProperty: (icon: string) => updateProperty("markerIcon", icon as string, component, onPropertyChange),
|
|
57
|
+
icons: { array: ICONS },
|
|
58
|
+
}}
|
|
59
|
+
{component}
|
|
60
|
+
{onPropertyChange}
|
|
61
|
+
/>
|
|
62
|
+
</PropsGroup>
|
|
63
|
+
<PropsGroup label="По умолчанию (оператор меняет на карте)">
|
|
64
|
+
<UI.Switch
|
|
65
|
+
label={{ name: $T("constructor.props.map.track") }}
|
|
66
|
+
value={component.properties.trackEnabled ? 1 : 0}
|
|
67
|
+
options={[{ id: crypto.randomUUID(), value: 0, class: "" }]}
|
|
68
|
+
onChange={(value) => updateProperty("trackEnabled", Boolean(value), component, onPropertyChange)}
|
|
69
|
+
/>
|
|
70
|
+
<UI.Select
|
|
71
|
+
label={{ name: $T("constructor.props.map.trackLength") }}
|
|
72
|
+
type="input"
|
|
73
|
+
options={TRACK_LENGTH_OPTIONS}
|
|
74
|
+
value={TRACK_LENGTH_OPTIONS.find((opt) => opt.value === (component.properties.trackLength ?? 1000))}
|
|
75
|
+
onUpdate={(option) => updateProperty("trackLength", (option as { value: number }).value, component, onPropertyChange)}
|
|
76
|
+
/>
|
|
77
|
+
</PropsGroup>
|
|
78
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type UIComponent, type IWidgetMapProps } from "../types";
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
component: UIComponent & {
|
|
4
|
+
properties: Partial<IWidgetMapProps>;
|
|
5
|
+
};
|
|
6
|
+
onPropertyChange: (updates: Partial<{
|
|
7
|
+
properties?: string | object;
|
|
8
|
+
name?: string;
|
|
9
|
+
access?: string;
|
|
10
|
+
}>) => void;
|
|
11
|
+
};
|
|
12
|
+
declare const WidgetMapProps: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
|
+
type WidgetMapProps = ReturnType<typeof WidgetMapProps>;
|
|
14
|
+
export default WidgetMapProps;
|
package/dist/index.d.ts
CHANGED
|
@@ -17,8 +17,6 @@ export { default as InputProps } from "./Input/InputProps.svelte";
|
|
|
17
17
|
export { default as Joystick } from "./Joystick/Joystick.svelte";
|
|
18
18
|
export { default as JoystickProps } from "./Joystick/JoystickProps.svelte";
|
|
19
19
|
export { default as Modal } from "./Modal.svelte";
|
|
20
|
-
export { default as Map } from "./Map/Map.svelte";
|
|
21
|
-
export { default as MapProps } from "./Map/MapProps.svelte";
|
|
22
20
|
export { default as PeriodChart } from "./PeriodChart/PeriodChart.svelte";
|
|
23
21
|
export { default as PeriodChartProps } from "./PeriodChart/PeriodChartProps.svelte";
|
|
24
22
|
export { default as ProgressBar } from "./ProgressBar/ProgressBar.svelte";
|
|
@@ -51,7 +49,9 @@ export { default as WidgetRGBStrip } from "./WidgetRGBStrip/WidgetRGBStrip.svelt
|
|
|
51
49
|
export { default as WidgetRGBStripProps } from "./WidgetRGBStrip/WidgetRGBStripProps.svelte";
|
|
52
50
|
export { default as WidgetPFD } from "./WidgetPFD/WidgetPFD.svelte";
|
|
53
51
|
export { default as WidgetPFDProps } from "./WidgetPFD/WidgetPFDProps.svelte";
|
|
52
|
+
export { default as WidgetMap } from "./WidgetMap/WidgetMap.svelte";
|
|
53
|
+
export { default as WidgetMapProps } from "./WidgetMap/WidgetMapProps.svelte";
|
|
54
54
|
export * from "./locales/i18n";
|
|
55
55
|
export * from "./locales/translations";
|
|
56
56
|
export * from "./ModalStackStore";
|
|
57
|
-
export { type UIComponent, type Position, type IUIComponentHandler, type IButtonProps, type IAccordionProps, type IInputProps, type ISelectProps, type IOption, type ISwitchProps, type IColorPickerProps, type IDividerProps, type ISliderProps, type ITextFieldProps, type
|
|
57
|
+
export { type UIComponent, type Position, type IUIComponentHandler, type IButtonProps, type IAccordionProps, type IInputProps, type ISelectProps, type IOption, type ISwitchProps, type IColorPickerProps, type IDividerProps, type ISliderProps, type ITextFieldProps, type IProgressBarProps, type IWidgetProps, type IWidgetWiFiProps, type IWidgetWiFiConfig, type IWidgetDeviceInfoProps, type IWidgetDeviceInfoConfig, type IWidgetFileSystemProps, type IWidgetFileSystemInfo, type IWidgetFileSystemFile, type IWidgetFileSystemUpload, type IWidgetStackInfoProps, type IWidgetStackInfo, type IWidgetStackInfoHeap, type IWidgetStackInfoTask, type IWidgetRGBStripProps, type IWidgetRGBStripConfig, type IWidgetPFDProps, type IWidgetPFDData, type IWidgetPFDLimits, type IWidgetMapProps, type IWidgetMapData, type IGraphProps, type IGraphDataObject, type IGraphHistoryPoint, type IGraphHistorySeries, type ITableHeader, type ITableText, type ITableSelect, type ITableButton, type ITableProgressBar, type ITableImage, type ITableContent, type ITableProps, type ITabsProps, type IJoystickProps, type IFileAttachProps, type ICarouselProps, type IReceivingDataObject, type IVideoViewerProps, type IPeriodChartProps, type IPeriodChartLevel, } from "./types";
|
package/dist/index.js
CHANGED
|
@@ -18,8 +18,6 @@ export { default as InputProps } from "./Input/InputProps.svelte";
|
|
|
18
18
|
export { default as Joystick } from "./Joystick/Joystick.svelte";
|
|
19
19
|
export { default as JoystickProps } from "./Joystick/JoystickProps.svelte";
|
|
20
20
|
export { default as Modal } from "./Modal.svelte";
|
|
21
|
-
export { default as Map } from "./Map/Map.svelte";
|
|
22
|
-
export { default as MapProps } from "./Map/MapProps.svelte";
|
|
23
21
|
export { default as PeriodChart } from "./PeriodChart/PeriodChart.svelte";
|
|
24
22
|
export { default as PeriodChartProps } from "./PeriodChart/PeriodChartProps.svelte";
|
|
25
23
|
export { default as ProgressBar } from "./ProgressBar/ProgressBar.svelte";
|
|
@@ -52,6 +50,8 @@ export { default as WidgetRGBStrip } from "./WidgetRGBStrip/WidgetRGBStrip.svelt
|
|
|
52
50
|
export { default as WidgetRGBStripProps } from "./WidgetRGBStrip/WidgetRGBStripProps.svelte";
|
|
53
51
|
export { default as WidgetPFD } from "./WidgetPFD/WidgetPFD.svelte";
|
|
54
52
|
export { default as WidgetPFDProps } from "./WidgetPFD/WidgetPFDProps.svelte";
|
|
53
|
+
export { default as WidgetMap } from "./WidgetMap/WidgetMap.svelte";
|
|
54
|
+
export { default as WidgetMapProps } from "./WidgetMap/WidgetMapProps.svelte";
|
|
55
55
|
export * from "./locales/i18n";
|
|
56
56
|
export * from "./locales/translations";
|
|
57
57
|
export * from "./ModalStackStore";
|