@konce-pt/angular 0.6.1 → 0.7.5
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/CHANGELOG.md +384 -0
- package/README.md +38 -19
- package/fesm2022/konce-pt-angular-charts.mjs +1409 -0
- package/fesm2022/konce-pt-angular-charts.mjs.map +1 -0
- package/fesm2022/konce-pt-angular-grid.mjs +232 -0
- package/{dist/fesm2022 → fesm2022}/konce-pt-angular-grid.mjs.map +1 -1
- package/fesm2022/konce-pt-angular-map.mjs +4568 -0
- package/fesm2022/konce-pt-angular-map.mjs.map +1 -0
- package/fesm2022/konce-pt-angular-roadmap.mjs +1919 -0
- package/fesm2022/konce-pt-angular-roadmap.mjs.map +1 -0
- package/fesm2022/konce-pt-angular.mjs +12307 -0
- package/fesm2022/konce-pt-angular.mjs.map +1 -0
- package/map/src/lib/llms.txt +741 -0
- package/package.json +44 -54
- package/roadmap/src/lib/llms.txt +112 -0
- package/src/lib/app-shell/llms.txt +89 -0
- package/src/lib/breakpoint/llms.txt +45 -0
- package/{dist/src → src}/lib/datepicker/llms.txt +3 -0
- package/src/lib/dialog/llms.txt +68 -0
- package/{dist/src → src}/lib/form-field/llms.txt +24 -1
- package/{dist/src → src}/lib/icon/llms.txt +2 -1
- package/{dist/src → src}/lib/input/llms.txt +14 -4
- package/src/lib/input-number/llms.txt +61 -0
- package/{dist/src → src}/lib/select/llms.txt +9 -0
- package/src/lib/sidenav/llms.txt +29 -0
- package/src/lib/toolbar/llms.txt +31 -0
- package/src/lib/tooltip/llms.txt +33 -0
- package/{dist/types → types}/konce-pt-angular-charts.d.ts +1 -0
- package/types/konce-pt-angular-charts.d.ts.map +1 -0
- package/{dist/types → types}/konce-pt-angular-grid.d.ts +1 -0
- package/types/konce-pt-angular-grid.d.ts.map +1 -0
- package/{dist/types → types}/konce-pt-angular-icons.d.ts +1 -0
- package/types/konce-pt-angular-icons.d.ts.map +1 -0
- package/types/konce-pt-angular-map.d.ts +1585 -0
- package/types/konce-pt-angular-map.d.ts.map +1 -0
- package/types/konce-pt-angular-roadmap.d.ts +649 -0
- package/types/konce-pt-angular-roadmap.d.ts.map +1 -0
- package/{dist/types → types}/konce-pt-angular.d.ts +373 -23
- package/types/konce-pt-angular.d.ts.map +1 -0
- package/dist/LICENSE +0 -21
- package/dist/README.md +0 -316
- package/dist/fesm2022/konce-pt-angular-charts.mjs +0 -957
- package/dist/fesm2022/konce-pt-angular-charts.mjs.map +0 -1
- package/dist/fesm2022/konce-pt-angular-grid.mjs +0 -218
- package/dist/fesm2022/konce-pt-angular.mjs +0 -8462
- package/dist/fesm2022/konce-pt-angular.mjs.map +0 -1
- package/dist/package.json +0 -79
- package/dist/src/lib/app-shell/llms.txt +0 -29
- package/dist/src/lib/dialog/llms.txt +0 -27
- package/dist/src/lib/input-number/llms.txt +0 -17
- package/dist/src/lib/sidenav/llms.txt +0 -20
- package/dist/src/lib/toolbar/llms.txt +0 -23
- package/dist/src/lib/tooltip/llms.txt +0 -19
- /package/{dist/charts → charts}/src/lib/llms.txt +0 -0
- /package/{dist/fesm2022 → fesm2022}/konce-pt-angular-icons.mjs +0 -0
- /package/{dist/fesm2022 → fesm2022}/konce-pt-angular-icons.mjs.map +0 -0
- /package/{dist/grid → grid}/src/lib/llms.txt +0 -0
- /package/{dist/src → src}/lib/accordion/llms.txt +0 -0
- /package/{dist/src → src}/lib/alert/llms.txt +0 -0
- /package/{dist/src → src}/lib/autocomplete/llms.txt +0 -0
- /package/{dist/src → src}/lib/avatar/llms.txt +0 -0
- /package/{dist/src → src}/lib/avatar-group/llms.txt +0 -0
- /package/{dist/src → src}/lib/badge/llms.txt +0 -0
- /package/{dist/src → src}/lib/bottom-sheet/llms.txt +0 -0
- /package/{dist/src → src}/lib/breadcrumb/llms.txt +0 -0
- /package/{dist/src → src}/lib/button/llms.txt +0 -0
- /package/{dist/src → src}/lib/button-group/llms.txt +0 -0
- /package/{dist/src → src}/lib/card/llms.txt +0 -0
- /package/{dist/src → src}/lib/carousel/llms.txt +0 -0
- /package/{dist/src → src}/lib/checkbox/llms.txt +0 -0
- /package/{dist/src → src}/lib/chip/llms.txt +0 -0
- /package/{dist/src → src}/lib/chips-input/llms.txt +0 -0
- /package/{dist/src → src}/lib/color-picker/llms.txt +0 -0
- /package/{dist/src → src}/lib/confirm/llms.txt +0 -0
- /package/{dist/src → src}/lib/context-menu/llms.txt +0 -0
- /package/{dist/src → src}/lib/data-table/llms.txt +0 -0
- /package/{dist/src → src}/lib/data-view/llms.txt +0 -0
- /package/{dist/src → src}/lib/date-range/llms.txt +0 -0
- /package/{dist/src → src}/lib/divider/llms.txt +0 -0
- /package/{dist/src → src}/lib/drawer/llms.txt +0 -0
- /package/{dist/src → src}/lib/empty/llms.txt +0 -0
- /package/{dist/src → src}/lib/fab/llms.txt +0 -0
- /package/{dist/src → src}/lib/fieldset/llms.txt +0 -0
- /package/{dist/src → src}/lib/file-upload/llms.txt +0 -0
- /package/{dist/src → src}/lib/galleria/llms.txt +0 -0
- /package/{dist/src → src}/lib/i18n/llms.txt +0 -0
- /package/{dist/src → src}/lib/icon-button/llms.txt +0 -0
- /package/{dist/src → src}/lib/image/llms.txt +0 -0
- /package/{dist/src → src}/lib/input-mask/llms.txt +0 -0
- /package/{dist/src → src}/lib/input-otp/llms.txt +0 -0
- /package/{dist/src → src}/lib/knob/llms.txt +0 -0
- /package/{dist/src → src}/lib/listbox/llms.txt +0 -0
- /package/{dist/src → src}/lib/megamenu/llms.txt +0 -0
- /package/{dist/src → src}/lib/menu/llms.txt +0 -0
- /package/{dist/src → src}/lib/menubar/llms.txt +0 -0
- /package/{dist/src → src}/lib/meter-group/llms.txt +0 -0
- /package/{dist/src → src}/lib/order-list/llms.txt +0 -0
- /package/{dist/src → src}/lib/paginator/llms.txt +0 -0
- /package/{dist/src → src}/lib/panel/llms.txt +0 -0
- /package/{dist/src → src}/lib/password/llms.txt +0 -0
- /package/{dist/src → src}/lib/pick-list/llms.txt +0 -0
- /package/{dist/src → src}/lib/popover/llms.txt +0 -0
- /package/{dist/src → src}/lib/progress/llms.txt +0 -0
- /package/{dist/src → src}/lib/radio-group/llms.txt +0 -0
- /package/{dist/src → src}/lib/rating/llms.txt +0 -0
- /package/{dist/src → src}/lib/rich-text/llms.txt +0 -0
- /package/{dist/src → src}/lib/scroll-top/llms.txt +0 -0
- /package/{dist/src → src}/lib/skeleton/llms.txt +0 -0
- /package/{dist/src → src}/lib/slider/llms.txt +0 -0
- /package/{dist/src → src}/lib/speed-dial/llms.txt +0 -0
- /package/{dist/src → src}/lib/spinner/llms.txt +0 -0
- /package/{dist/src → src}/lib/split-button/llms.txt +0 -0
- /package/{dist/src → src}/lib/splitter/llms.txt +0 -0
- /package/{dist/src → src}/lib/stepper/llms.txt +0 -0
- /package/{dist/src → src}/lib/switch/llms.txt +0 -0
- /package/{dist/src → src}/lib/switch-group/llms.txt +0 -0
- /package/{dist/src → src}/lib/tabs/llms.txt +0 -0
- /package/{dist/src → src}/lib/textarea/llms.txt +0 -0
- /package/{dist/src → src}/lib/timeline/llms.txt +0 -0
- /package/{dist/src → src}/lib/toast/llms.txt +0 -0
- /package/{dist/src → src}/lib/tree/llms.txt +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# @konce-pt/angular
|
|
2
|
+
|
|
3
|
+
## 0.7.5
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Responsywny `kpt-app-shell`: nakładka, szyna ikon i panel zadokowany
|
|
8
|
+
|
|
9
|
+
`kpt-app-shell` sam dobiera układ do szerokości okna. Nowy tryb `auto` (od `sidenavBreakpoint`,
|
|
10
|
+
domyślnie `lg`, panel jest zadokowany; poniżej — nakładka ze scrimem, domyślnie zamknięta),
|
|
11
|
+
opcjonalna szyna ikon w paśmie do `sidenavRailBreakpoint`, `Escape` zamykające nakładkę,
|
|
12
|
+
`inert` na treści pod nią, poprawny kierunek wysuwu w RTL i wysokość `100dvh`.
|
|
13
|
+
|
|
14
|
+
O układzie decyduje wyłącznie CSS, więc nic nie migocze przed hydracją i całość działa na SSR.
|
|
15
|
+
|
|
16
|
+
**Zmiana zachowania:** domyślną wartością `sidenavMode` jest teraz `'auto'` zamiast `'side'`.
|
|
17
|
+
Jeśli aplikacja sama zarządza responsywnością szkieletu (własne `@media` i własny hamburger),
|
|
18
|
+
ustaw jawnie `sidenavMode="side"` — inaczej dostaniesz dwie warstwy tej samej logiki.
|
|
19
|
+
Tryby `'side'` i `'over'` działają dokładnie jak wcześniej.
|
|
20
|
+
|
|
21
|
+
Nowe API:
|
|
22
|
+
|
|
23
|
+
- `KptBreakpointObserver` — media query jako sygnały (`up`, `down`, `matches`), spięte
|
|
24
|
+
z tokenami `--kpt-breakpoint-*`; poza przeglądarką zwraca `false`.
|
|
25
|
+
- `KptShellNavToggle` (`[kptShellNavToggle]`) — hamburger, który sam trafia w stan właściwy
|
|
26
|
+
dla bieżącego układu i dokłada `aria-expanded` / `aria-controls` / etykietę z i18n.
|
|
27
|
+
- `kpt-app-shell`: `sidenavCompactOpen`, `sidenavBreakpoint`, `sidenavRailBreakpoint`,
|
|
28
|
+
`sidenavLabel`, `sidenavId`, `isOverlay()`, `isSidenavOpen()`,
|
|
29
|
+
`toggleSidenav()` / `openSidenav()` / `closeSidenav()`.
|
|
30
|
+
- `kpt-toolbar`: input `wrap` (zawijanie zawartości) oraz kompaktowa wysokość poniżej `sm`.
|
|
31
|
+
- `@konce-pt/grid`: klasy `kpt-display-*` z wariantami per breakpoint i skrótem `kpt-hide`.
|
|
32
|
+
- Tokeny: `--kpt-sidenav-rail-width` (4rem), `--kpt-toolbar-height-compact` (3rem).
|
|
33
|
+
- Słownik: namespace `appShell` (`toggleNavigation`, `navigation`) w EN i PL.
|
|
34
|
+
|
|
35
|
+
Poprawka: `kpt-drawer` używał fallbacku `--kpt-z-overlay: 1000` (wartość `z.dropdown`)
|
|
36
|
+
zamiast `1100`.
|
|
37
|
+
|
|
38
|
+
- Nowy komponent `KptMap` (kpt-map) w subpathu `@konce-pt/angular/map` — interaktywna mapa
|
|
39
|
+
z konfigurowalnymi znacznikami, na silniku Leaflet + OpenStreetMap.
|
|
40
|
+
|
|
41
|
+
- Kategorie obiektów z kolorem (rola semantyczna tokenów, nie literał) i ikoną z `KptIconRegistry`;
|
|
42
|
+
kształty `pin` / `dot` / `square`.
|
|
43
|
+
- Grupowanie znaczników z licznikiem — własny rdzeń pure TS (siatka w przestrzeni pikseli, O(n),
|
|
44
|
+
deterministyczna), wspólny dla obu silników i przenośny do portu React. Bez `leaflet.markercluster`.
|
|
45
|
+
- Popup szczegółów o szablonie zależnym od kategorii (`ng-template kptMapPopup`), renderowany
|
|
46
|
+
przez Angulara i pozycjonowany przez `engine.project()` — pełne komponenty `kpt-*` w treści.
|
|
47
|
+
Kontekst szablonu niesie też `distance` — odległość punktu w metrach od `[distanceFrom]`,
|
|
48
|
+
a bez niego od pozycji użytkownika.
|
|
49
|
+
- **Karta miejsca `KptMapPoiCard` (kpt-map-poi-card)**: dystans, zdjęcie 16:9, przycisk główny
|
|
50
|
+
z udostępnianiem i ulubionymi, wiersz kategorii, rozwijane godziny otwarcia ze statusem
|
|
51
|
+
otwarte/zamknięte i wiersze kontaktowe (telefon, www, e-mail, współrzędne) z kopiowaniem
|
|
52
|
+
do schowka. Sterowana danymi: bierze `KptMapPoi`, nie model domenowy aplikacji.
|
|
53
|
+
- `[popupLayout]="'card'"` oddaje popup w całości treści — bez paddingu, szerszy, przewijalny
|
|
54
|
+
i bez wbudowanego krzyżyka (daje go karta). Domyślne `plain` zostaje bez zmian.
|
|
55
|
+
- Nagłówek karty (tytuł, krzyżyk, dystans i adres) stoi nieruchomo; przewija się wyłącznie
|
|
56
|
+
reszta treści, w osobnym `.kpt-map-poi__scroll`. Przewijanie schodzi w tym celu z popupu
|
|
57
|
+
do karty — `popupLayout="card"` daje `.kpt-map__popup-body` `display: flex` i `overflow:
|
|
58
|
+
hidden`, a karcie pełną wysokość. Sam popup zostaje bez `overflow: hidden`, bo ucięłby
|
|
59
|
+
strzałkę `::after` wiszącą na `top: 100%`. Karta poza popupem, bez limitu wysokości,
|
|
60
|
+
nie przewija się wcale.
|
|
61
|
+
- Pasek „Anuluj / Zapisz" w formularzu dodawania jest przypięty do dołu (`position: sticky`),
|
|
62
|
+
więc nie ucieka na koniec długiej listy pól.
|
|
63
|
+
- Legenda jako filtr: `KptMapLegend` (kpt-map-legend) z `aria-pressed`, liczniki per kategoria,
|
|
64
|
+
ukrycie kategorii usuwa ją także z grup.
|
|
65
|
+
- Dodawanie lokalizacji prawym przyciskiem myszy: formularz budowany ze schemy `category.fields`
|
|
66
|
+
na Signal Forms albo własny `ng-template kptMapCreateForm`. Poza `text`/`textarea`/`number`/
|
|
67
|
+
`date`/`select`/`multiselect`/`checkbox` schema przyjmuje `tel`, `email` i `url` (z walidacją
|
|
68
|
+
formatu), `image` — wybór pliku czytany jako `data:` **albo** wklejony adres, oraz `hours` —
|
|
69
|
+
edytor tygodnia dający `KptMapOpeningHours`.
|
|
70
|
+
Plik zdjęcia zostaje w przeglądarce: biblioteka nigdzie go nie wysyła i nie ma wiedzy
|
|
71
|
+
o storage'u aplikacji. Limit 2 MB jest realny — data URL puchnie o ~⅓, a cała wartość
|
|
72
|
+
leci w `locationCreate`.
|
|
73
|
+
- Widok startowy z presetu kraju (`KPT_MAP_COUNTRIES`, domyślnie Polska) oraz opcjonalne
|
|
74
|
+
ograniczenie przesuwania do jego zasięgu.
|
|
75
|
+
- Znacznik własnego położenia z geolokalizacji wraz z kręgiem dokładności i kontrolką
|
|
76
|
+
„wyśrodkuj na mnie"; źródło pozycji przez port DI `KPT_MAP_GEOLOCATION`
|
|
77
|
+
(`provideKptMapGeolocationStub()` dla Storybooka i testów).
|
|
78
|
+
- Silnik za interfejsem `KptMapEngine` — `provideKptLeafletMap()` dziś, adapter Google Maps
|
|
79
|
+
bez zmian w API komponentu.
|
|
80
|
+
- Rdzeń pure TS w publicznym API: `clusterLocations`, `countryPreset`, projekcja Mercatora
|
|
81
|
+
(`project`/`unproject`/`boundsOf`/`haversine`/`metersPerPixel`/`zoomForBounds`),
|
|
82
|
+
generatory HTML znaczników, formatowanie (`formatDistance`, `formatLatLng`) oraz godziny
|
|
83
|
+
otwarcia (`isOpenAt`, `isAlwaysOpen`, `nextChange`, `groupWeek`, `weekdayName`, `emptyWeek`,
|
|
84
|
+
`parseTime`, `formatTime`). Testy: `packages/angular/map/src/core/*.test.ts`.
|
|
85
|
+
`isOpenAt()` liczy dwa dni — bieżący i poprzedni — więc przedział `22:00–01:00` obejmuje
|
|
86
|
+
wczesne godziny dnia następnego; `24:00` to koniec doby, a nie przejście przez północ.
|
|
87
|
+
`groupWeek()` skleja sąsiadujące dni o identycznym rozkładzie w `pon.–pt.`, ale nie zawija
|
|
88
|
+
tygodnia przez granicę niedziela–poniedziałek. Nazwy dni idą z `Intl`, nie ze słownika —
|
|
89
|
+
karta i edytor godzin działają dla dowolnego locale bez dopisywania tłumaczeń.
|
|
90
|
+
- Nowe tokeny komponentowe `--kpt-map-*` (w tym `popup-width`, `popup-width-card`,
|
|
91
|
+
`popup-max-height`, `poi-media-radius`, `poi-row-hover`) oraz klucze i18n `map.*`,
|
|
92
|
+
`map.poi.*` i `map.field.*` (EN + PL).
|
|
93
|
+
- Cztery ikony dopisane do **wbudowanego** zestawu `KPT_ICONS`: `mail`, `share`,
|
|
94
|
+
`external-link`, `crosshair`. Karta miejsca ich potrzebuje, a komponent biblioteczny nie może
|
|
95
|
+
wymagać `provideKptTablerIcons()`.
|
|
96
|
+
- `KptInput` przyjmuje `type="time"`.
|
|
97
|
+
- `KptDatepicker` dostaje wejście `ariaLabel` (nazwa dostępna tam, gdzie pola nie opisuje
|
|
98
|
+
`<label for>` — np. dwie godziny w jednym wierszu) i w trybie `time` rysuje w polu ikonę
|
|
99
|
+
zegara zamiast kalendarza. Godziny otwarcia wybiera się właśnie nim
|
|
100
|
+
(`selectionMode="time"`, `minuteStep=5`), a nie natywnym `<input type="time">`: tamten
|
|
101
|
+
otwiera systemowy dropdown, którego nie da się ostylować.
|
|
102
|
+
- **Naprawiony kolor ikony kategorii `muted` poza mapą.** Legenda malowała glif zaszytą
|
|
103
|
+
bielą na tle koloru roli, a `--kpt-color-muted` to neutral-100 — token tła, nie treści.
|
|
104
|
+
Kategoria `muted` miała więc w legendzie ikonę praktycznie niewidoczną, choć jej znacznik
|
|
105
|
+
na mapie był poprawny (ten bierze `contrastVarOf()`). Legenda używa teraz `contrastVarOf()`,
|
|
106
|
+
a nowe `foregroundVarOf()` w publicznym API daje kolor glifu stojącego wprost na powierzchni
|
|
107
|
+
(bez własnego tła) — z niego korzysta wiersz kategorii w karcie miejsca.
|
|
108
|
+
- `renderKptIconSvg()` wydzielone z `kpt-icon` do publicznego API — mapa buduje z niego
|
|
109
|
+
znaczniki poza Angularem, więc oba miejsca mają jedno źródło prawdy.
|
|
110
|
+
|
|
111
|
+
**Nowa zależność opcjonalna:** `leaflet` jako `peerDependencies` + `peerDependenciesMeta.optional`.
|
|
112
|
+
To pierwsza zależność runtime biblioteki. Ładowana dynamicznym `import()`, więc aplikacje bez mapy
|
|
113
|
+
jej nie pobierają. Użycie mapy wymaga `pnpm add leaflet` i dołączenia `leaflet/dist/leaflet.css`
|
|
114
|
+
(Angular CLI: `angular.json → styles[]`, nie `import` w `main.ts`).
|
|
115
|
+
|
|
116
|
+
**Uwaga o kaskadzie:** nadpisania `.leaflet-*` w `map.component.scss` stoją poza `@layer` — celowo
|
|
117
|
+
i jako jedyne w bibliotece. `leaflet.css` nie jest warstwowany, a CSS spoza warstw wygrywa z każdą
|
|
118
|
+
regułą w `@layer` niezależnie od specyficzności.
|
|
119
|
+
|
|
120
|
+
- Podpowiadanie adresu w formularzu „dodaj lokalizację": pole z `autofill` (`city`, `address`,
|
|
121
|
+
`street`, `houseNumber`, `postcode`, `state`, `county`, `country`, `countryCode`, `label`)
|
|
122
|
+
wypełnia się z geokodowania wstecznego współrzędnych kliknięcia. Źródło przez port DI
|
|
123
|
+
`KPT_MAP_GEOCODER`; gotowy adapter `provideKptNominatimGeocoder()` jest **opt-in** —
|
|
124
|
+
biblioteka nie odpytuje cudzego serwera bez zgody aplikacji. Podpowiedź wypełnia wyłącznie
|
|
125
|
+
pola puste, więc nigdy nie kasuje tego, co użytkownik wpisał.
|
|
126
|
+
|
|
127
|
+
**Uwaga o kaflach:** domyślne `tile.openstreetmap.org` to usługa best-effort bez SLA, z wymogiem
|
|
128
|
+
widocznej atrybucji i zakazem pre-fetchowania. Do produkcji podstaw własny serwer przez `[tileUrl]`.
|
|
129
|
+
To samo dotyczy Nominatim (jedno zapytanie na sekundę, zakaz masowego odpytywania) — adapter sam
|
|
130
|
+
trzyma odstęp, ale produkcja powinna mieć własną instancję albo dostawcę komercyjnego.
|
|
131
|
+
|
|
132
|
+
***
|
|
133
|
+
|
|
134
|
+
Przy okazji naprawiony **utajony błąd `KptDialog`**: kontrolki na CDK Overlay (`kpt-select`,
|
|
135
|
+
`kpt-datepicker`, `kpt-autocomplete`, `kpt-menu`) otwierały się w środku okna modalnego
|
|
136
|
+
niewidoczne. `showModal()` wynosi `<dialog>` do warstwy szczytowej przeglądarki, ponad całe
|
|
137
|
+
drzewo dokumentu, a kontener CDK Overlay wisi na `<body>` — żaden `z-index` tego nie przebija.
|
|
138
|
+
`kpt-dialog` przenosi teraz kontener overlayów do wnętrza okna na czas jego otwarcia i oddaje
|
|
139
|
+
go na miejsce przy zamknięciu.
|
|
140
|
+
|
|
141
|
+
Błąd był w bibliotece od początku, ale nieuruchomiony: żaden przykład nie umieszczał kontrolki
|
|
142
|
+
overlayowej w oknie modalnym. Ujawnił go formularz „dodaj lokalizację" z pól `date` i `select`.
|
|
143
|
+
|
|
144
|
+
**Nieruchomy nagłówek okna.** `.kpt-dialog` jest teraz kolumną flex: nagłówek z krzyżykiem
|
|
145
|
+
i stopka `[kptDialogFooter]` stoją, a pasek przewijania biegnie wyłącznie wzdłuż
|
|
146
|
+
`.kpt-dialog__body`. Wcześniej okno przewijało się w całości, razem z nagłówkiem. Treść
|
|
147
|
+
dostaje `flex: 0 1 auto` + `min-height: 0`, celowo nie `flex: 1` — krótkie okno (`kpt-confirm`)
|
|
148
|
+
dalej kurczy się do treści, zamiast rozciągać na `max-height`. `display: flex` jest scopowane
|
|
149
|
+
`&[open]`: regułę `dialog:not([open]) { display: none }` daje arkusz przeglądarki, a każda
|
|
150
|
+
deklaracja autorska ją bije — także z `@layer`, więc bez scopingu zamknięte okna zostałyby
|
|
151
|
+
widoczne. `overflow: hidden` na oknie celowo nie ma: przycięłoby panele CDK Overlay
|
|
152
|
+
przeniesione do jego wnętrza.
|
|
153
|
+
|
|
154
|
+
`.kpt-map .leaflet-container` dostaje `z-index: 0`, żeby zamknąć skalę z-index Leafleta
|
|
155
|
+
(panes 200–700, kontrolki 800) we własnym kontekście układania — bez tego popup, kontrolki
|
|
156
|
+
zoomu i menu prawego przycisku są malowane pod kaflami.
|
|
157
|
+
|
|
158
|
+
***
|
|
159
|
+
|
|
160
|
+
Naprawiony też **utajony błąd `KptSwitch`, `KptCheckbox` i `KptRadioGroup`**: ukryty `<input>`
|
|
161
|
+
tych kontrolek jest `position: absolute`, ale ich element główny nie był pozycjonowany. Blokiem
|
|
162
|
+
zawierającym stawał się więc najbliższy pozycjonowany przodek — w praktyce kontener aplikacji —
|
|
163
|
+
przez co input uciekał poza przewijany obszar i rozpychał dokument, dając **drugi pasek
|
|
164
|
+
przewijania** obok paska treści. Kontrolki zatrzymują teraz swój input u siebie
|
|
165
|
+
(`position: relative` na elemencie głównym).
|
|
166
|
+
|
|
167
|
+
Widoczne dopiero, gdy któraś z tych kontrolek trafi dostatecznie nisko w długiej, przewijanej
|
|
168
|
+
stronie — stąd ujawniło się na stronie mapy, która ma pięć przełączników.
|
|
169
|
+
|
|
170
|
+
- Geokoder per mapa — nowe wejście `[geocoder]` w `kpt-map`, symetryczne do `[engine]`.
|
|
171
|
+
|
|
172
|
+
- `[geocoder]` przyjmuje `KptMapGeocoderPort` i wygrywa nad `KPT_MAP_GEOCODER` z DI. Trafia do
|
|
173
|
+
obu konsumentów portu naraz: wyszukiwarki adresów i podpowiadania adresu w formularzu
|
|
174
|
+
„dodaj lokalizację". To samo wejście mają `kpt-map-search` i `kpt-map-create-dialog`, gdy stoją
|
|
175
|
+
poza mapą. Bez niego nic się nie zmienia — port przychodzi z DI, jak dotąd.
|
|
176
|
+
- **Po co.** Service Specific Terms §6.2 i §14.2 wiążą geokoder Google z **mapą** Google, a nie
|
|
177
|
+
z aplikacją. Odkąd `[engine]` pozwala postawić dwa silniki na jednej stronie, globalny provider
|
|
178
|
+
nie umiał tej reguły dotrzymać: musiałby złamać ją po jednej ze stron. Teraz mapa Leafleta
|
|
179
|
+
z geokoderem OSM i mapa Google z geokoderem Google mieszczą się obok siebie.
|
|
180
|
+
- W odróżnieniu od `[engine]` port czytany jest **reaktywnie**: podmiana zeruje listę podpowiedzi
|
|
181
|
+
i od następnej frazy pyta nowego dostawcę.
|
|
182
|
+
- `loadGoogleMapsApi(options)` wyeksportowany z `@konce-pt/angular/map` (plus typy
|
|
183
|
+
`KptGoogleLoadOptions` i `KptGoogleMapsApi`) — ten sam loader, którego używa silnik. Adapter
|
|
184
|
+
geokodera Google **musi** iść przez SDK, a nie przez REST: web service
|
|
185
|
+
`maps.googleapis.com/maps/api/geocode/json` odrzuca klucze ograniczone po `Referer`
|
|
186
|
+
(„API keys with referer restrictions cannot be used with this API"), a to jedyna restrykcja
|
|
187
|
+
mająca sens dla klucza leżącego jawnie w bundlu przeglądarki. CORS na tym endpoincie działa,
|
|
188
|
+
więc odmowa przychodzi jako `200` z `REQUEST_DENIED` w treści — łatwo ją przeoczyć.
|
|
189
|
+
Samego adaptera biblioteka nadal nie dostarcza; przykład od początku do końca stoi
|
|
190
|
+
w playgroundzie.
|
|
191
|
+
|
|
192
|
+
- Drugi silnik mapy — Google Maps — i wybór silnika per instancja przez wejście `[engine]`.
|
|
193
|
+
|
|
194
|
+
- `provideKptGoogleMap({ apiKey, mapId, language?, region?, version?, minZoom?, maxZoom?,
|
|
195
|
+
scrollWheelZoom? })` obok `provideKptLeafletMap()`. **Zero nowych zależności npm**: Google Maps
|
|
196
|
+
JavaScript API dogrywa się skryptem przy pierwszej mapie, tak jak Leaflet ładuje się dynamicznym
|
|
197
|
+
`import()`. Paczka `@googlemaps/js-api-loader` dokładałaby wersję do pilnowania w zamian za te
|
|
198
|
+
same kilkanaście linijek.
|
|
199
|
+
- **`mapId` jest wymagany.** Bez niego nie działa `AdvancedMarkerElement`, a znaczniki tej
|
|
200
|
+
biblioteki to gotowy HTML z `marker-html.ts` — starsze `Marker` go nie przyjmie.
|
|
201
|
+
- Nowe wejście **`[engine]`** (`KptMapEngineFactory | null`) wygrywa nad `KPT_MAP_ENGINE` z DI.
|
|
202
|
+
Dwie mapy o różnych silnikach mieszczą się dzięki temu na jednej stronie bez komponentów-opakowań.
|
|
203
|
+
`KPT_MAP_ENGINE` staje się wstrzykiwany opcjonalnie, a brak silnika w obu źródłach daje czytelny
|
|
204
|
+
komunikat z instrukcją zamiast `NullInjectorError` z nazwą tokenu.
|
|
205
|
+
- Kontrakt `KptMapEngine` **nie zmienił się o ani jedną sygnaturę** — to był cel tego interfejsu
|
|
206
|
+
i teraz się zweryfikował. Grupowanie, popup, legenda, menu prawego przycisku, wyszukiwarka
|
|
207
|
+
i formularz dodawania działają w obu silnikach z tego samego kodu.
|
|
208
|
+
- Adapter Google liczy `project()`/`unproject()` **rdzeniem** (`core/geo.ts`), a nie
|
|
209
|
+
`map.getProjection()`: ten zwraca `null` do pierwszego `idle` i tak czy owak wymaga przeliczenia
|
|
210
|
+
na piksele kontenera. Wspólna matematyka znaczy, że popup ląduje piksel w piksel tak samo w obu
|
|
211
|
+
silnikach, zgadza się z grupowaniem i obsługuje zoom ułamkowy, którego Google używa przy gestach.
|
|
212
|
+
- Kliknięcie w znacznik łapie listener DOM ze `stopPropagation()`, a nie `gmp-click`
|
|
213
|
+
z `gmpClickable`. Bez zatrzymania propagacji to samo kliknięcie doszłoby do mapy i `onMapClick()`
|
|
214
|
+
zamknąłby popup w tej samej klatce, w której go otwieramy. Adapter Leafleta robi dokładnie to
|
|
215
|
+
samo przez `L.DomEvent.stopPropagation`; przy okazji odpada zależność od zachowania `gmp-click`
|
|
216
|
+
w danej wersji API.
|
|
217
|
+
- Krąg dokładności przy silniku Google jest elementem z tłem, a nie `google.maps.Circle`: Circle
|
|
218
|
+
przyjmuje kolory w opcjach, a kontrakt repo wymaga stylowania tokenami `var(--kpt-*)`. Średnicę
|
|
219
|
+
liczy `metersPerPixel()` z rdzenia i odświeża na `zoom_changed`. Silnik trafia na host jako
|
|
220
|
+
`[data-engine]`, więc różnicę widać w jednej regule SCSS.
|
|
221
|
+
- `[tileUrl]` i `[attribution]` są przy silniku Google **ignorowane** — kafle i atrybucję dostarcza
|
|
222
|
+
Google, a jej zasłonięcie albo usunięcie łamie warunki usługi. `setTileSource()` i
|
|
223
|
+
`invalidateSize()` to tam świadome no-opy.
|
|
224
|
+
|
|
225
|
+
**Dlaczego to w ogóle powstało.** Google Maps Platform Service Specific Terms §6.2 (Geocoding API)
|
|
226
|
+
i §14.2 (Places API) zabraniają używać ich wyników „in conjunction with a non-Google map".
|
|
227
|
+
Dopóki `kpt-map` umiał tylko Leaflet z kaflami OSM, każdy adapter Google pod `KPT_MAP_GEOCODER`
|
|
228
|
+
był niezgodny z umową. Silnik Google zdejmuje to u źródła. Sama biblioteka adaptera geokodera
|
|
229
|
+
Google **nie dostarcza** — jego miejsce jest w aplikacji, bo wolno go użyć tylko z jednym
|
|
230
|
+
z dwóch silników.
|
|
231
|
+
|
|
232
|
+
- Wyszukiwarka adresów w `kpt-map` — `[search]` (domyślnie wyłączona) pokazuje w rogu mapy pole
|
|
233
|
+
z podpowiedziami; wybór podpowiedzi przenosi widok na znalezione miejsce.
|
|
234
|
+
|
|
235
|
+
- Port `KPT_MAP_GEOCODER` dostaje **opcjonalną** metodę `search(query, options)` obok istniejącego
|
|
236
|
+
`reverse()`. Opcjonalną celowo: porty napisane w aplikacjach przed jej powstaniem kompilują się
|
|
237
|
+
bez zmian, a `kpt-map` bez niej po prostu nie renderuje pola. Nowe typy `KptMapSuggestion`
|
|
238
|
+
(`{ id, label, at?, bounds?, address? }`), `KptMapSearchResult` (to samo z wymaganym `at`)
|
|
239
|
+
i `KptMapSearchOptions` w publicznym API; `address` to ten sam `KptMapAddress`, co przy
|
|
240
|
+
geokodowaniu wstecznym — bez drugiego modelu adresu.
|
|
241
|
+
- `KptNominatimGeocoder` implementuje `search()` na `/search` i wchodzi w **tę samą kolejkę**
|
|
242
|
+
co `reverse()`: polityka Nominatim liczy jedno zapytanie na sekundę na całego klienta,
|
|
243
|
+
a nie na metodę.
|
|
244
|
+
- **Kolejka adaptera Nominatim liczy odstęp od zegara**, a nie stałym `delay(1000)` przed każdym
|
|
245
|
+
zapytaniem. Wcześniej pierwsze zapytanie po dowolnie długiej bezczynności też płaciło sekundę
|
|
246
|
+
— przy podpowiadaniu w trakcie pisania to różnica między „działa" a „zacina się". Zmiana
|
|
247
|
+
dotyczy także istniejącego `reverse()`; górna granica jednego zapytania na sekundę
|
|
248
|
+
zostaje nienaruszona.
|
|
249
|
+
- Nowe w rdzeniu (pure TS, publiczne API): `isFittableBounds(bounds, minSpan?)` i `KPT_MIN_FIT_SPAN`
|
|
250
|
+
(0,001°, ~100 m) — czy prostokąt warto wpasowywać w kadr, czy potraktować jak punkt.
|
|
251
|
+
Geokodery obrysowują pojedynczy adres prostokątem rzędu 0,0001°, więc `fitBounds` wjeżdżałby
|
|
252
|
+
na nim na górny limit zoomu, a dwa sąsiednie adresy lądowałyby w różnych przybliżeniach.
|
|
253
|
+
Próg wystarczy przekroczyć w jednej osi — długa, wąska ulica dalej zasługuje na `fitBounds`.
|
|
254
|
+
Testy: `packages/angular/map/src/core/geo.test.ts`.
|
|
255
|
+
- Nowe wejścia `kpt-map`: `search`, `searchPlaceholder`, `searchOptions`
|
|
256
|
+
(`minLength` = 3, `debounce` = 300 ms, `limit` = 5, `countryCodes`), `searchZoom` = 16,
|
|
257
|
+
`searchMarker` = true. Nowe wyjście `searchSelect`.
|
|
258
|
+
- Wynik z własnym zasięgiem (miasto, region) wchodzi w kadr przez `fitBounds`, a pojedynczy
|
|
259
|
+
punkt dostaje `[searchZoom]` — dzięki temu każdy adres ląduje w tym samym, przewidywalnym
|
|
260
|
+
przybliżeniu, niezależnie od tego, jak dostawca obrysował budynek.
|
|
261
|
+
- Zapytania są nachylone ku presetowi `[country]` (albo `[bounds]`) przez `viewbox`. To sam
|
|
262
|
+
bias — przestawia kolejność wyników i niczego nie odcina; adres z zagranicy dalej da się
|
|
263
|
+
znaleźć. Twarde `countrycodes` dokłada się dopiero przy `restrictToCountry` (mapa i tak nie
|
|
264
|
+
pozwoli przesunąć widoku poza kraj) albo jawnie przez `searchOptions.countryCodes`.
|
|
265
|
+
- Tymczasowa pinezka wyniku idzie tą samą drogą co reszta znaczników — przez
|
|
266
|
+
`engine.setMarkers()` — więc przesuwa się z mapą klatka po klatce i **nie wymaga niczego
|
|
267
|
+
od silnika**. Nie należy do wyniku grupowania, więc kliknięcie w nią nic nie otwiera.
|
|
268
|
+
Znika po wyczyszczeniu pola i po kliknięciu w mapę.
|
|
269
|
+
- Nowy komponent `KptMapSearch` (kpt-map-search) w publicznym API — jak legenda, do postawienia
|
|
270
|
+
także poza mapą. Świadomie **nie** stoi na `kpt-autocomplete`: tamten filtruje opcje po stronie
|
|
271
|
+
klienta (`includes(q)`), więc wynik geokodera tolerancyjny na literówki wypadałby z listy;
|
|
272
|
+
jego wartością jest sam `string`, więc nie ma czym przewieźć współrzędnych; i wymaga CDK
|
|
273
|
+
Overlay, którego mapa poza tym nie potrzebuje. Panel podpowiedzi rysuje więc warstwa Angulara
|
|
274
|
+
nad mapą, tak samo jak popup i menu prawego przycisku (`z-index: 5`, nad tamtymi).
|
|
275
|
+
- Wzorzec combobox z `aria-activedescendant` (fokus zostaje w `<input>`), klawiatura ↑/↓/Enter,
|
|
276
|
+
pierwszy Esc zamyka listę, drugi czyści pole; liczba wyników i „brak wyników" w `aria-live`.
|
|
277
|
+
- **Port przyjmuje dostawców, którzy nie podają współrzędnych na liście.** `search()` zwraca teraz
|
|
278
|
+
`KptMapSuggestion` (`at` opcjonalne) zamiast `KptMapSearchResult`, a port może dopisać
|
|
279
|
+
`resolve(suggestion)`, które dokłada `lat`/`lng` **po wybraniu pozycji**. Tak działa Google Places
|
|
280
|
+
Autocomplete: oddaje `placeId` i tekst, a współrzędne dociąga osobny Place Details — na tym stoi
|
|
281
|
+
jego rozliczanie sesyjne, więc bez tego kroku podpowiadanie z Google kosztowałoby pięć wywołań
|
|
282
|
+
Place Details na każdy zestaw podpowiedzi zamiast jednego na wybór.
|
|
283
|
+
Zmiana jest **wstecznie zgodna**: `KptMapSearchResult` to teraz `KptMapSuggestion` z wymaganym
|
|
284
|
+
`at`, więc adaptery zwracające pełne wyniki (Nominatim, Photon, każdy geokoder pytany wprost)
|
|
285
|
+
spełniają interfejs bez zmiany linijki, a `selected`/`searchSelect` dalej mają ten sam typ.
|
|
286
|
+
- Obsługa `resolve()` siedzi w `KptMapSearch`, nie w `kpt-map` — dzięki temu **`selected`
|
|
287
|
+
i `searchSelect` zawsze niosą współrzędne**, także gdy pole stoi poza mapą, i aplikacja nigdy
|
|
288
|
+
nie musi sprawdzać, czy `at` jest. Podpowiedź ze współrzędnymi emituje się natychmiast (zero
|
|
289
|
+
opóźnienia dla Nominatima); bez nich panel pokazuje „Szukam…" i `aria-busy`, a nieudane
|
|
290
|
+
dociągnięcie zostawia etykietę w polu i wraca do listy zamiast wywracać pole. Gdy port nie ma
|
|
291
|
+
`resolve()`, podpowiedzi bez `at` w ogóle nie trafiają na listę — pozycja, której kliknięcie
|
|
292
|
+
nie miałoby dokąd polecieć, jest gorsza niż jej brak.
|
|
293
|
+
- **`KptNominatimOptions.minIntervalMs`** — sekundowy odstęp przestał być stałą w kodzie.
|
|
294
|
+
Domyślna zależy od `baseUrl`: publiczna instancja OSM dostaje 1000 ms jak dotąd, własna 0,
|
|
295
|
+
bo regulamin OSMF nie obowiązuje na cudzym serwerze. `0` zdejmuje też kolejkowanie.
|
|
296
|
+
Wcześniej własna instancja Nominatima płaciła sekundę za każdą podpowiedź bez żadnego powodu
|
|
297
|
+
i nie dało się tego wyłączyć opcją.
|
|
298
|
+
- `provideKptMapGeocoderStub(address, results?, options?)` przyjmuje teraz listę podpowiedzi —
|
|
299
|
+
Storybook i testy dostają wyszukiwarkę bez ruchu sieciowego. Trzeci argument
|
|
300
|
+
(`{ deferCoordinates: true }`) każe atrapie udawać dostawcę bez współrzędnych na liście, żeby
|
|
301
|
+
ścieżkę `resolve()` dało się pokazać bez prawdziwego klucza API. Sygnatura wstecznie zgodna.
|
|
302
|
+
- Nowe tokeny `--kpt-map-search-width` i `--kpt-map-search-panel-max-height` oraz klucze
|
|
303
|
+
i18n `map.search.*` (EN + PL).
|
|
304
|
+
- Wyszukiwarkę pozycjonuje **opakowanie** `<div class="kpt-map__search">`, a nie klasa
|
|
305
|
+
postawiona wprost na `<kpt-map-search>`. Jeden element z obiema klasami znaczył dwie reguły
|
|
306
|
+
o identycznej specyficzności (0,1,0) w tej samej warstwie `kpt.components`, więc rozstrzygała
|
|
307
|
+
kolejność wstrzyknięcia stylów — a Angular wstrzykuje style dziecka po stylach rodzica.
|
|
308
|
+
`.kpt-map-search { position: relative }` (blok zawierający dla panelu podpowiedzi) wygrywało
|
|
309
|
+
z `absolute` rodzica, pole wypadało do normalnego przepływu za `.kpt-map__canvas`
|
|
310
|
+
(`height: 100%`) i znikało przycięte przez `overflow: hidden` widoku. Element był w DOM
|
|
311
|
+
z poprawnymi atrybutami — usterkę widać wyłącznie na zrzucie ekranu.
|
|
312
|
+
|
|
313
|
+
**Uwaga o polityce Nominatim.** Podpowiadanie w trakcie pisania z natury generuje serie zapytań,
|
|
314
|
+
więc pole broni się progiem `minLength` i `debounce`, a adapter wspólną kolejką i przerywaniem
|
|
315
|
+
porzuconych zapytań przez `AbortController`. Do produkcji dalej obowiązuje własna instancja
|
|
316
|
+
(`baseUrl`) albo dostawca komercyjny pod `KPT_MAP_GEOCODER` — publiczna instancja OSM zabrania
|
|
317
|
+
masowego odpytywania i może zablokować ruch bez uprzedzenia.
|
|
318
|
+
|
|
319
|
+
## 0.7.0
|
|
320
|
+
|
|
321
|
+
### Minor Changes
|
|
322
|
+
|
|
323
|
+
- Nowy komponent `KptRoadmap` (`kpt-roadmap`) w subpathu `@konce-pt/angular/roadmap` — zadania na
|
|
324
|
+
poziomej osi czasu w widoku typu Gantt. Przyklejona kolumna etykiet i nagłówek osi, przewijanie
|
|
325
|
+
w obu osiach, opcjonalna stała wysokość. Zoom: rok / kwartał / miesiąc / tydzień / dzień / godzina,
|
|
326
|
+
z oknem godzin roboczych. Numeracja tygodni wg ISO 8601 wraz z realnym zakresem dat; zmiana roku
|
|
327
|
+
oznaczona mocniejszą linią i czarnym znacznikiem. Kolumny zachowują równą szerokość mimo zmiany
|
|
328
|
+
czasu i różnej długości miesięcy. Grupy zwijane z paskiem zbiorczym, kamienie milowe, zależności
|
|
329
|
+
FS/SS/FF/SF z wykrywaniem naruszeń, wirtualizacja wierszy. Rdzeń obliczeń jako pure TS — subpath
|
|
330
|
+
eksportuje `buildTimeline`, `buildRows`, `resolveLinks`, `autoRange` i pomocniki kalendarza ISO.
|
|
331
|
+
Nowe klucze i18n `roadmap.*` (EN + PL).
|
|
332
|
+
- `KptTooltip`: nowe wejście `kptTooltipOnlyWhenTruncated` — dymek pojawia się wyłącznie wtedy, gdy
|
|
333
|
+
treść nie mieści się w elemencie i jest ucięta wielokropkiem. Przepełnienie sprawdzane jest przy
|
|
334
|
+
najechaniu (nie przy renderze), więc wynik pozostaje aktualny po zmianie szerokości czy powiększenia
|
|
335
|
+
bez użycia `ResizeObserver`. Pomiar obejmuje hosta i jego bezpośrednie dzieci, bo `text-overflow`
|
|
336
|
+
zwykle siedzi na wewnętrznym elemencie.
|
|
337
|
+
- `KptTooltip`: dymek podąża za hostem przy przewijaniu zagnieżdżonych kontenerów — wcześniej
|
|
338
|
+
zostawał w miejscu, gdy host przesuwał się we własnym obszarze przewijania.
|
|
339
|
+
|
|
340
|
+
## 0.6.1
|
|
341
|
+
|
|
342
|
+
### Patch Changes
|
|
343
|
+
|
|
344
|
+
- Wydanie porządkowe — wyrównanie wersji paczek. Bez zmian w API.
|
|
345
|
+
|
|
346
|
+
## 0.6.0
|
|
347
|
+
|
|
348
|
+
### Minor Changes
|
|
349
|
+
|
|
350
|
+
- Nowy entry point `@konce-pt/angular/grid` z dyrektywami `[kptGrid]`, `[kptCol]` i `[kptFlex]`
|
|
351
|
+
(sygnałowe inputy, zoneless) oraz skrótem `KPT_GRID_IMPORTS`. Ustawiają custom properties
|
|
352
|
+
inline, więc zmiana rozpiętości nie dodaje ani nie usuwa klas w DOM. Wymaga arkusza
|
|
353
|
+
`@konce-pt/grid`.
|
|
354
|
+
- `llms.txt` podpaczek `charts` i `grid` trafiają teraz do `dist` (wcześniej pomijane).
|
|
355
|
+
|
|
356
|
+
### Patch Changes
|
|
357
|
+
|
|
358
|
+
- Updated dependencies
|
|
359
|
+
- @konce-pt/tokens@0.6.0
|
|
360
|
+
|
|
361
|
+
## 0.1.2
|
|
362
|
+
|
|
363
|
+
### Patch Changes
|
|
364
|
+
|
|
365
|
+
- Naprawa dokumentacji ładowania stylów: metodą główną dla Angular CLI jest `angular.json → styles[]`
|
|
366
|
+
(import '...css' w main.ts zostaje jako wariant dla Vite/webpack). Tokeny SCSS dostają mixiny
|
|
367
|
+
`kpt-root-tokens`/`kpt-dark-tokens` emitujące custom properties w runtime. Wejścia CSS dostają
|
|
368
|
+
warunek `types` + stub `.d.ts` (usuwa TS2882 w projektach z tsc). Bez zmian w API komponentów.
|
|
369
|
+
|
|
370
|
+
## 0.1.1
|
|
371
|
+
|
|
372
|
+
### Patch Changes
|
|
373
|
+
|
|
374
|
+
- Dodano profesjonalne README (EN/PL) i plik LICENSE do każdej paczki oraz metadane npm
|
|
375
|
+
(repository/homepage/bugs/keywords). Bez zmian w API komponentów.
|
|
376
|
+
|
|
377
|
+
## 0.1.0
|
|
378
|
+
|
|
379
|
+
### Minor Changes
|
|
380
|
+
|
|
381
|
+
- Pierwsze wydanie Koncept UI: design tokeny (OKLCH, motyw jasny/ciemny), bazowy CSS,
|
|
382
|
+
oraz komponenty Angular 22 — layout (app-shell/toolbar/sidenav/card/divider), formularze
|
|
383
|
+
na Signal Forms (input/select/checkbox/radio/switch/datepicker/form-field), flagowa tabela
|
|
384
|
+
danych (kpt-data-table) z paginatorem, oraz feedback (alert/dialog/toast/tooltip).
|
package/README.md
CHANGED
|
@@ -93,40 +93,59 @@ import '@angular/cdk/overlay-prebuilt.css';
|
|
|
93
93
|
|
|
94
94
|
## Quick start
|
|
95
95
|
|
|
96
|
-
A form powered by **Signal Forms** — no `ControlValueAccessor`, no `FormsModule`:
|
|
96
|
+
A login form powered by **Signal Forms** — no `ControlValueAccessor`, no `FormsModule`:
|
|
97
97
|
|
|
98
98
|
```ts
|
|
99
|
-
import { Component, signal } from '@angular/core';
|
|
100
|
-
import {
|
|
101
|
-
import { KptFormField, KptInput
|
|
99
|
+
import { Component, computed, signal } from '@angular/core';
|
|
100
|
+
import { FormField, FormRoot, email, form, required, submit } from '@angular/forms/signals';
|
|
101
|
+
import { KptButton, KptFormField, KptInput } from '@konce-pt/angular';
|
|
102
102
|
|
|
103
103
|
@Component({
|
|
104
104
|
selector: 'app-login',
|
|
105
|
-
imports: [FormField, KptFormField, KptInput,
|
|
105
|
+
imports: [FormRoot, FormField, KptFormField, KptInput, KptButton],
|
|
106
106
|
template: `
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
<!-- formRoot sets novalidate, intercepts submit and calls submit() for you -->
|
|
108
|
+
<form [formRoot]="loginForm" (submit)="onSubmit()">
|
|
109
|
+
<kpt-form-field label="E-mail" [error]="emailError()" required controlId="f-email">
|
|
110
|
+
<kpt-input [formField]="loginForm.email" type="email" id="f-email" />
|
|
111
|
+
</kpt-form-field>
|
|
112
|
+
|
|
113
|
+
<kpt-form-field label="Password" [error]="passwordError()" required controlId="f-pass">
|
|
114
|
+
<kpt-input [formField]="loginForm.password" type="password" id="f-pass" />
|
|
115
|
+
</kpt-form-field>
|
|
116
|
+
|
|
117
|
+
<kpt-button type="submit" [disabled]="formInvalid()">Sign in</kpt-button>
|
|
118
|
+
</form>
|
|
116
119
|
`,
|
|
117
120
|
})
|
|
118
121
|
export class Login {
|
|
119
|
-
readonly model = signal({ email: '',
|
|
122
|
+
readonly model = signal({ email: '', password: '' });
|
|
120
123
|
readonly loginForm = form(this.model, (p) => {
|
|
121
|
-
required(p.email
|
|
122
|
-
|
|
124
|
+
required(p.email, { message: 'E-mail is required' });
|
|
125
|
+
email(p.email, { message: 'Enter a valid e-mail address' });
|
|
126
|
+
required(p.password, { message: 'Password is required' });
|
|
123
127
|
});
|
|
124
|
-
readonly roles = [{ label: 'Admin', value: 'admin' }, { label: 'Editor', value: 'editor' }];
|
|
125
128
|
|
|
126
|
-
|
|
129
|
+
// Validators stay pure — only the *message* waits for the field to be touched.
|
|
130
|
+
private errorFor(name: 'email' | 'password'): string | null {
|
|
131
|
+
const s = this.loginForm[name]();
|
|
132
|
+
return s.touched() && s.invalid() ? s.errors()[0]?.message ?? null : null;
|
|
133
|
+
}
|
|
134
|
+
readonly emailError = computed(() => this.errorFor('email'));
|
|
135
|
+
readonly passwordError = computed(() => this.errorFor('password'));
|
|
136
|
+
readonly formInvalid = computed(() => this.loginForm().invalid());
|
|
137
|
+
|
|
138
|
+
async onSubmit(): Promise<void> {
|
|
139
|
+
// submit() marks the whole tree as touched before running the action
|
|
140
|
+
await submit(this.loginForm, { action: async () => { console.log(this.model()); } });
|
|
141
|
+
}
|
|
127
142
|
}
|
|
128
143
|
```
|
|
129
144
|
|
|
145
|
+
> Don't gate validators on UI state (`when: ({ state }) => state.touched()`) — it makes
|
|
146
|
+
> `loginForm().valid()` return `true` on an untouched form. Koncept UI controls already show
|
|
147
|
+
> the invalid state only once a field is touched.
|
|
148
|
+
|
|
130
149
|
Data table with sorting, filtering, pagination and a custom cell template:
|
|
131
150
|
|
|
132
151
|
```html
|