poe-svelte-ui-lib 1.40.2 → 1.41.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 CHANGED
@@ -26,6 +26,8 @@ npm install poe-svelte-ui-lib
26
26
  /* дальше — только собственные отличия приложения, например :root { min-width: 640px; } */
27
27
  ```
28
28
 
29
+ **Предпросмотр темы** — страница «Тема» витрины (`src/routes/components/theme`): один и тот же интерфейс облака (шапка устройства, палитра токенов, кнопки во всех ролях, поля, таблица, виджеты, типографика, Markdown) в светлой и тёмной теме рядом — палитра задаётся классами `.light`/`.dark`, поэтому обе темы видны одновременно. Правьте `theme.css` и смотрите результат там.
30
+
29
31
  Текст в Markdown, таблицы и код переносятся по ширине контейнера — горизонтальной прокрутки быть не должно, только вертикальная. Markdown рендерится с `breaks: true` (как в облаке), поэтому абзац и пункт списка пишутся одной строкой — ручной перенос внутри абзаца превращается в разрыв строки.
30
32
 
31
33
  **Глобальные стили тегов — только в `@layer base`.** Компоненты задают размеры текста и отступы Tailwind-утилитами (например `text-[12px]` у подписи `<h5>`). Правило вне слоя (`h5 { font-size: 1rem }`, `label { … }`, `p { … }`) сильнее любой утилиты, и в приложении подписи станут крупнее задуманного и перестанут помещаться. Поэтому типографику тегов оборачивайте:
@@ -95,7 +97,7 @@ npm run Formatting # prettier --write .
95
97
 
96
98
  Связь настраивается на npmjs.com → пакет → Settings → Trusted Publisher: GitHub Actions, `Oleg-Perevyshin/ElementsUI`, workflow `npm_publish.yaml`, разрешение «npm publish». Новая связь подтверждается первой успешной публикацией и должна пройти её в течение 2 дней, иначе истекает. Существующую связь изменить нельзя — только удалить и создать заново.
97
99
 
98
- **Обновление DevCloud — автоматически.** После публикации job `update-devcloud` того же workflow ждёт новую версию в npm, клонирует `xPOE-Studio/DevCloud` (Forgejo) по секрету `FORGEJO_ACCESS_TOKEN`, ставит `poe-svelte-ui-lib@<версия>`, прогоняет `prisma generate` и `svelte-check` и, если проверка прошла, пушит в `main` коммит `poe-svelte-ui-lib <версия> [deploy]` — облако разворачивается само. Вручную версию в облаке не поднимаем; изменения кода облака, которым нужна новая версия библиотеки, коммитятся без `[deploy]` до выпуска — их развернёт этот коммит. Если `svelte-check` упал, коммита нет, облако остаётся на прежней версии (смотрите лог job в GitHub Actions).
100
+ **Обновление DevCloud — автоматически.** После публикации job `update-devcloud` того же workflow ждёт новую версию в npm, клонирует `xPOE-Studio/DevCloud` (Forgejo) по секрету `DEVCLOUD_ACCESS_TOKEN` (токен Forgejo с правом записи в репозиторий), ставит `poe-svelte-ui-lib@<версия>`, прогоняет `svelte-kit sync`, `prisma generate` (с заглушкой `DATABASE_URL`, к БД не подключается) и `svelte-check` и, если проверка прошла, пушит в `main` коммит `poe-svelte-ui-lib <версия> [deploy]` — облако разворачивается само. Вручную версию в облаке не поднимаем; изменения кода облака, которым нужна новая версия библиотеки, коммитятся без `[deploy]` до выпуска — их развернёт этот коммит. Если `svelte-check` упал, коммита нет, облако остаётся на прежней версии (смотрите лог job в GitHub Actions).
99
101
 
100
102
  ---
101
103
 
@@ -54,7 +54,7 @@ Telemetry_SendObject(g_telemetry_stream, g_mcfg.DevSN, "Data", dev, sizeof(dev)
54
54
  - **Траектория** — точка добавляется только при смене координат (курс и высота могут обновляться чаще позиции).
55
55
  - **Только 2D** — наклон (3D) запрещён; правой кнопкой мыши карта только поворачивается, кнопка-компас под зумом возвращает её на север.
56
56
  - **Шапка** — сколько бортов на связи из заданных: зелёный — все, серый — часть, красный — ни одного.
57
- - Карта светлая/тёмная по теме приложения (событие `ThemeChange`).
57
+ - Карта светлая/тёмная по ближайшему предку `.dark`/`.light` (как токены `theme.css`), пересчёт по событию `ThemeChange`.
58
58
 
59
59
  ## Пропсы
60
60
 
@@ -94,4 +94,4 @@ Telemetry_SendObject(g_telemetry_stream, g_mcfg.DevSN, "Data", dev, sizeof(dev)
94
94
 
95
95
  ## Внутреннее устройство
96
96
 
97
- `mapWrapper/` — тонкие Svelte-обёртки над MapLibre GL (`MapLibre`, `Marker`, `Popup`, `Line`, контролы, `CustomControl` для своих элементов поверх карты). MapLibre подгружается при монтировании; без интернета показывается заглушка «Карта не загружена».
97
+ `mapWrapper/` — тонкие Svelte-обёртки над MapLibre GL (`MapLibre`, `Marker`, `Popup`, `Line`, контролы, `CustomControl` для своих элементов поверх карты). MapLibre подгружается с CDN один раз на страницу (несколько карт ждут одну загрузку); без интернета показывается заглушка «Карта не загружена».
@@ -148,13 +148,16 @@
148
148
  setTimeout(() => (isCopied = false), 1000)
149
149
  }
150
150
 
151
- const handleThemeChange = (event: CustomEvent) => {
152
- isDarkMode = !event.detail.currentTheme
151
+ /* Тема карты — по ближайшему предку .dark/.light (как у токенов theme.css), а не по localStorage: работает и внутри блока с другой темой */
152
+ let rootEl: HTMLDivElement | undefined = $state()
153
+ const detectTheme = () => {
154
+ const scope = rootEl?.closest(".dark, .light")
155
+ isDarkMode = scope ? scope.classList.contains("dark") : localStorage.getItem("AppTheme") !== "light"
153
156
  }
154
157
  onMount(() => {
155
- isDarkMode = localStorage.getItem("AppTheme") !== "light"
156
- window.addEventListener("ThemeChange", handleThemeChange as EventListener)
157
- return () => window.removeEventListener("ThemeChange", handleThemeChange as EventListener)
158
+ detectTheme()
159
+ window.addEventListener("ThemeChange", detectTheme)
160
+ return () => window.removeEventListener("ThemeChange", detectTheme)
158
161
  })
159
162
 
160
163
  const trackLengthOptions = [100, 500, 1000, 5000, 10000, 50000]
@@ -170,6 +173,7 @@
170
173
  </script>
171
174
 
172
175
  <div
176
+ bind:this={rootEl}
173
177
  class={twMerge("relative flex w-full flex-col gap-4 rounded-2xl border border-(--hairline-color) bg-(--container-color) p-4", wrapperClass)}
174
178
  style={accentStyle}
175
179
  >
@@ -58,7 +58,7 @@
58
58
 
59
59
  onMount(async () => {
60
60
  isLoading = true
61
- hasConnection = await loadMapLibre(hasConnection)
61
+ hasConnection = await loadMapLibre()
62
62
  isLoading = false
63
63
 
64
64
  if (!window.maplibregl || map || !container) return
@@ -1 +1 @@
1
- export declare const loadMapLibre: (hasConnectionState: boolean) => Promise<boolean>;
1
+ export declare const loadMapLibre: () => Promise<boolean>;
@@ -1,27 +1,26 @@
1
1
  const CDN_URL = "https://cdn.jsdelivr.net/npm/maplibre-gl@5.17.0/dist/maplibre-gl.min.js";
2
2
  const CSS_URL = "https://cdn.jsdelivr.net/npm/maplibre-gl@5.17.0/dist/maplibre-gl.min.css";
3
- export const loadMapLibre = async (hasConnectionState) => {
3
+ /* Одна загрузка на страницу: несколько карт ждут один и тот же промис, иначе вторая видит уже вставленный <script> до его загрузки */
4
+ let loading = null;
5
+ export const loadMapLibre = () => {
4
6
  if (typeof window === "undefined")
5
- return false;
6
- if (!navigator.onLine) {
7
- hasConnectionState = false;
8
- return false;
9
- }
10
- try {
11
- if (!window.maplibregl) {
12
- await loadScript(CDN_URL);
13
- await loadCSS(CSS_URL);
14
- if (!window.maplibregl) {
15
- throw new Error("MapLibre GL не был загружен корректно.");
16
- }
17
- }
18
- }
19
- catch (err) {
7
+ return Promise.resolve(false);
8
+ if (window.maplibregl)
9
+ return Promise.resolve(true);
10
+ if (!navigator.onLine)
11
+ return Promise.resolve(false);
12
+ loading ??= Promise.all([loadScript(CDN_URL), loadCSS(CSS_URL)])
13
+ .then(() => {
14
+ if (!window.maplibregl)
15
+ throw new Error("MapLibre GL не был загружен корректно.");
16
+ return true;
17
+ })
18
+ .catch((err) => {
20
19
  console.error("Ошибка загрузки MapLibre GL:", err);
21
- hasConnectionState = false;
20
+ loading = null;
22
21
  return false;
23
- }
24
- return true;
22
+ });
23
+ return loading;
25
24
  };
26
25
  const loadScript = (src) => {
27
26
  return new Promise((resolve, reject) => {
@@ -33,7 +32,10 @@ const loadScript = (src) => {
33
32
  script.src = src;
34
33
  script.async = true;
35
34
  script.onload = () => resolve();
36
- script.onerror = () => reject(new Error(`Не удалось загрузить скрипт ${src}`));
35
+ script.onerror = () => {
36
+ script.remove(); /* иначе повторная попытка увидит тег и не станет грузить заново */
37
+ reject(new Error(`Не удалось загрузить скрипт ${src}`));
38
+ };
37
39
  document.head.appendChild(script);
38
40
  });
39
41
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-svelte-ui-lib",
3
- "version": "1.40.2",
3
+ "version": "1.41.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Oleg-Perevyshin/ElementsUI.git"