@konce-pt/angular 0.7.10 → 0.7.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konce-pt/angular",
3
- "version": "0.7.10",
3
+ "version": "0.7.11",
4
4
  "description": "Open-source Angular 22 component library on Signals & Signal Forms — 70+ components, rich data table, zoneless, fully tokenized. Selektory kpt-*, klasy Kpt*.",
5
5
  "license": "MIT",
6
6
  "author": "konce.pt",
@@ -0,0 +1,104 @@
1
+ # KptAuth (kpt-auth)
2
+
3
+ Ekran uwierzytelniania: logowanie, rejestracja i odzyskiwanie hasła w jednym komponencie,
4
+ z panelem promocyjnym i listą dostawców zewnętrznych (OAuth/SSO). Signal Forms.
5
+ Komponent jest **prezentacyjny** — nie woła API i nie nawiguje; robi to aplikacja w handlerach.
6
+ Import: `import { KptAuth, KptAuthProviderDef } from '@konce-pt/angular';`
7
+
8
+ ## Selektor
9
+ `kpt-auth`
10
+
11
+ ## Wejścia
12
+ - `mode`: model<'signIn' | 'signUp' | 'forgot'> = 'signIn' — dwukierunkowy (aplikacja może wymusić tryb)
13
+ - `layout`: 'slider' | 'split' = 'slider' — panel promocyjny przejeżdża na drugą stronę / stoi w miejscu
14
+ - `providers`: KptAuthProvider[] = [] — `{ id, label, icon?, iconUrl?, description? }`
15
+ - `providerLayout`: 'list' | 'grid' = 'list' — lista pełnej szerokości / siatka ikon z podpisami
16
+ - `showName`, `requireTerms`, `showRemember`: boolean = true — obecność pól
17
+ - `busy`: boolean — przyciski w stanie ładowania, dostawcy zablokowani
18
+ - `error` / `notice`: string | null — komunikat serwera (kpt-alert `danger` / `success`)
19
+ - `promoTitle` / `promoText`: string | null — `null` = tekst z i18n zależny od trybu,
20
+ `''` = ukryj (miejsce na slot `[kptAuthPromo]`)
21
+ - `animated`: boolean = true; `animationDuration`: number = 320 (ms)
22
+
23
+ ## Wyjścia
24
+ - `signIn`: { email, password, remember }
25
+ - `signUp`: { name, email, password, terms }
26
+ - `resetPassword`: { email }
27
+ - `providerSelect`: KptAuthProvider — wybrany dostawca (pełny obiekt, nie samo `id`)
28
+ - `modeChange` — z `model` `mode`
29
+
30
+ ## Projekcja
31
+ - `[kptAuthBrand]` — logo/nazwa nad nagłówkiem
32
+ - `[kptAuthPromo]` — treść panelu promocyjnego (pod tytułem/tekstem, nad CTA)
33
+ - `[kptAuthSso]` — przycisk logowania firmowego **nad** separatorem dostawców
34
+ - `[kptAuthFields]` — dodatkowe pola wewnątrz `<form>` (logowanie i rejestracja)
35
+ - `[kptAuthFooter]` — stopka (regulamin, prawa autorskie)
36
+ - `ng-template[kptAuthProvider]="id"` (`KptAuthProviderDef`) — własny markup jednego dostawcy;
37
+ kontekst: `$implicit` = dostawca, `select` = funkcja zgłaszająca wybór
38
+
39
+ **Pola ze slotu `[kptAuthFields]` nie wchodzą do modelu komponentu.** Konsument wiąże je do
40
+ własnego formularza i czyta w handlerze `signIn`/`signUp` — w emitowanej wartości ich nie ma.
41
+
42
+ ## Walidacja
43
+ Trzy niezależne formularze (po jednym na tryb), walidatory bezwarunkowe: e-mail wymagany
44
+ i poprawny, hasło wymagane (rejestracja: min. 8 znaków), zgodność hasła i powtórzenia
45
+ (`validateTree`), zgoda wymagana gdy `requireTerms`. Komunikaty składane są z `kind` błędu
46
+ w czasie renderowania, więc **zmiana języka w runtime przerysowuje je** (walidatory tworzą się raz).
47
+ Błąd pokazuje się dopiero po dotknięciu pola; `submit()` sam oznacza całe drzewo jako dotknięte.
48
+
49
+ ## Ikony dostawców
50
+ Rdzeń nie zawiera ikon marek. Trzy drogi:
51
+ 1. `provideKptTablerIcons()` z `@konce-pt/angular/icons` → `icon: 'brand-google'`,
52
+ `'brand-facebook'`, `'brand-linkedin'`, `'brand-windows'`, `'brand-apple'`, `'brand-github'`, `'key'`.
53
+ 2. `KptIconRegistry.register({ google: '<path …/>' })` — uwaga: sanityzator przepuszcza
54
+ `fill`/`stroke`/`opacity`, ale wycina `defs`/gradienty i `fill-rule`, a `viewBox` jest ustalony
55
+ na `0 0 24 24`. Wielokolorowe logo wymaga jawnego `fill` na każdej ścieżce.
56
+ 3. `iconUrl` (zwykły `<img alt="">`) albo szablon `kptAuthProvider` — dla logo z gradientem.
57
+
58
+ Ikona jest dekoracyjna (`kpt-icon` ma `aria-hidden`), więc nazwa dostępna przycisku zawsze
59
+ pochodzi z `label`.
60
+
61
+ ## Dostępność
62
+ - W drzewie żyje **wyłącznie formularz aktywnego trybu** — nie ma elementów niewidocznych,
63
+ ale wciąż fokusowalnych.
64
+ - Nagłówek panelu ma `tabindex="-1"` i dostaje fokus po zmianie trybu (inaczej zmiana nie
65
+ zostaje ogłoszona, a fokus zostaje na przycisku, który zjechał z ekranu).
66
+ - Etykiety przez `kpt-form-field` + `controlId`; `autocomplete`: `email`, `current-password`,
67
+ `new-password`, `name`.
68
+ - Przełączniki trybu to `<button>` z tekstem, nie `<a href="#">`.
69
+ - `prefers-reduced-motion` wyłącza przejazdy i wjazd treści.
70
+
71
+ ## Stylowanie
72
+ Publiczne zmienne: `--kpt-auth-width` (64rem), `--kpt-auth-card-height` (34rem),
73
+ `--kpt-auth-min-height` (100dvh), `--kpt-auth-promo-bg` (własny gradient marki),
74
+ `--kpt-auth-padding`, `--kpt-auth-card-radius` / `--kpt-auth-card-border` / `--kpt-auth-card-shadow`.
75
+ Wariant na całe okno (karta bez ramki, od krawędzi do krawędzi):
76
+
77
+ kpt-auth {
78
+ --kpt-auth-padding: 0;
79
+ --kpt-auth-width: 100%;
80
+ --kpt-auth-card-height: 100dvh;
81
+ --kpt-auth-card-radius: 0;
82
+ --kpt-auth-card-border: 0;
83
+ --kpt-auth-card-shadow: none;
84
+ }
85
+ Poniżej breakpointu `md` układ schodzi do jednej kolumny (promo nad formularzem, bez przejazdu).
86
+
87
+ ## Przykład
88
+ <kpt-auth
89
+ [providers]="[{ id: 'google', label: 'Google', icon: 'brand-google' }]"
90
+ [busy]="loading()"
91
+ [error]="serverError()"
92
+ (signIn)="login($event)"
93
+ (signUp)="register($event)"
94
+ (resetPassword)="sendLink($event.email)"
95
+ (providerSelect)="oauth($event.id)"
96
+ >
97
+ <img kptAuthBrand src="/logo.svg" alt="Konce" />
98
+ <small kptAuthFooter>© 2026 Konce</small>
99
+ </kpt-auth>
100
+
101
+ ## i18n
102
+ Wszystkie napisy pochodzą z namespace `auth` (EN/PL), w tym `auth.promo.*` i interpolacje
103
+ `auth.continueWith` ({provider}), `auth.passwordHint` / `auth.errorMinLength` ({min}).
104
+ Patrz `i18n/llms.txt`.
@@ -27,8 +27,8 @@ Import: `import { provideKptI18n, KptI18n } from '@konce-pt/angular';`
27
27
  Namespace'y: `common` (close/remove/previous/next/clear/done/all), `paginator` (rowsPerPage/range/prevPage/nextPage),
28
28
  `select`, `listbox`, `dataView`, `dataTable`, `confirm`, `fileUpload`, `chipsInput`, `dateRange`, `datepicker`,
29
29
  `pickList`, `orderList`, `inputNumber`, `password`, `spinner`, `speedDial`, `scrollTop`, `splitButton`, `panel`,
30
- `breadcrumb`, `richText`. Interpolacje: `paginator.range` ({start},{end},{total}), `dataTable.filter*` ({column}),
31
- `richText.styleHeading` ({level}). Nazwy dni/miesięcy w kalendarzach są wyliczane z `Intl` wg locale (nie ze słownika).
30
+ `breadcrumb`, `richText`, `auth` (w tym `auth.promo.*`). Interpolacje: `paginator.range` ({start},{end},{total}), `dataTable.filter*` ({column}),
31
+ `richText.styleHeading` ({level}), `auth.continueWith` ({provider}), `auth.passwordHint` i `auth.errorMinLength` ({min}). Nazwy dni/miesięcy w kalendarzach są wyliczane z `Intl` wg locale (nie ze słownika).
32
32
 
33
33
  ## Uwaga
34
34
  Pojedyncze etykiety można też nadpisać per-komponent przez odpowiedni `input()` (np. `emptyMessage`, `acceptLabel`) —
@@ -32,6 +32,8 @@ Pełny przepływ: sekcja `## Formularz od zera (Signal Forms)` w głównym llms.
32
32
  - `placeholder`: string
33
33
  - `id`: string — trafia na wewnętrzny `<input>` (do `label[for]`); host go nie nosi
34
34
  - `ariaLabel`: string | null
35
+ - `autocomplete`: string | null — podpowiedź dla przeglądarki i menedżera haseł
36
+ (np. `email`, `username`, `one-time-code`); bez niej autouzupełnianie nie działa
35
37
 
36
38
  ## Stan wiązany automatycznie przez FormField
37
39
  `value` (model, wymagane), `disabled`, `readonly`, `required`, `invalid`, `errors`,
@@ -7,6 +7,9 @@ Import: `import { KptPassword } from '@konce-pt/angular';`
7
7
  - `value`: model<string> (lub `formField`)
8
8
  - `feedback`: boolean — pokazuje miernik siły (4 paski + etykieta)
9
9
  - `placeholder`: string
10
+ - `id`: string — id natywnego pola; wiąże etykietę z `kpt-form-field [controlId]`
11
+ - `autocomplete`: string | null = 'current-password' — w rejestracji i resecie ustaw
12
+ `new-password`, inaczej menedżer haseł podstawi stare hasło zamiast zaproponować nowe
10
13
  - `disabled`/`invalid`/`touched`: boolean; `touch`: output
11
14
 
12
15
  ## Siła hasła
@@ -10,11 +10,20 @@ Import: `import { KptRichText, KptRichTool, KptRichToolbar } from '@konce-pt/ang
10
10
  - `toolbar`: KptRichToolbar = KptRichTool[] | KptRichTool[][] (płaska lista lub grupy=sekcje).
11
11
  Pominięcie narzędzia/grupy je wyłącza; między grupami separator. Domyślnie pełny pasek w 5 sekcjach.
12
12
  - `placeholder`: string; `disabled`/`invalid`/`touched`: boolean; `touch`: output
13
+ - `maxListLevel`: number = 6 — maksymalna głębokość zagnieżdżenia list. Limit dotyczy interakcji
14
+ (Tab i narzędzia `indent`/`outdent`); wklejonej treści nie spłaszczamy, żeby nie gubić danych.
13
15
 
14
16
  ## Narzędzia (KptRichTool)
15
17
  - Schowek: `copy`, `paste` (z formatowaniem, oczyszczone), `pasteText` (bez formatowania)
16
18
  - Styl: `heading` (select: Normalny/paragraf + Nagłówek 1–6)
17
19
  - Format: `bold`, `italic`, `underline`, `strike`, `ul`, `ol`
20
+ - Wcięcia list: `indent` (dodaj wcięcie), `outdent` (usuń wcięcie) — działają wyłącznie w `li`,
21
+ zagnieżdżają zgodnie ze specyfikacją (`li > ul/ol > li`, podlista dziedziczy typ listy rodzica).
22
+ Aktywne tylko tam, gdzie coś zrobią (poza listą i przy limicie przycisk jest wyszarzony).
23
+ Znaczniki poziomów cyklują co 3 (jak w edytorach tekstu): `ol` 1. → a. → i., `ul` • → ○ → ▪.
24
+ Reguły `list-style-type` obowiązują w widoku edytora (`.kpt-rich-text__editor`) do 6. poziomu.
25
+ Zapisany HTML nie niesie klas — renderując `value` poza edytorem opakuj go w `.kpt-rich-content`
26
+ z `@konce-pt/styles`, żeby listy wyglądały tak samo.
18
27
  - Kolory: `foreColor` (kolor tekstu), `backColor` (kolor tła) — popover z próbkami + `input type=color`
19
28
  - Wyrównanie: `alignLeft`, `alignCenter`, `alignRight`, `alignJustify`
20
29
  - `table` (wstaw tabelę: popover z siatką NxM). W komórce prawy klik = menu kontekstowe
@@ -26,6 +35,15 @@ Import: `import { KptRichText, KptRichTool, KptRichToolbar } from '@konce-pt/ang
26
35
  Odłożone: selekcja nieregularna, Ctrl+Backspace, zbiorcze formatowanie z górnego paska.
27
36
  - `link` (prompt URL), `clear` (usuń formatowanie), `html` (przełącznik podglądu źródła HTML — edycja surowego HTML)
28
37
 
38
+ ## Klawiatura
39
+ - Tab / Shift+Tab w punkcie listy = wcięcie / poziom wyżej (to samo co `indent`/`outdent`).
40
+ - Tab / Shift+Tab w komórce tabeli = następna / poprzednia komórka (z zaznaczeniem jej treści).
41
+ Lista wewnątrz komórki ma pierwszeństwo — dopiero gdy nie da się już wciąć, Tab zmienia komórkę.
42
+ - Wszędzie indziej — a także na pierwszym punkcie listy, na poziomie najwyższym, przy `maxListLevel`
43
+ i w ostatniej komórce tabeli — Tab zostaje **natywny** i wyprowadza fokus z edytora. To celowe:
44
+ edytor nie może być pułapką klawiaturową (WCAG 2.1.2), więc `preventDefault()` wołamy wyłącznie
45
+ wtedy, gdy operacja faktycznie zmieniła treść.
46
+
29
47
  ## Przykład
30
48
  <kpt-rich-text [formField]="f.body" /> <!-- pełny pasek -->
31
49
  <kpt-rich-text [(value)]="v" [toolbar]="[['bold','italic'],['ul','ol'],['link']]" />
@@ -42,4 +60,5 @@ Sanityzacja obejmuje **każdy** zapis do DOM edytora, nie tylko paste — w tym
42
60
  zewnątrz (`[(value)]`/`formField` z aplikacji, tryb źródła HTML). Traktuj `value` na wejściu jako
43
61
  potencjalnie niezaufane (DB, inny użytkownik, CMS); na wyjściu z komponentu jest sanityzowane.
44
62
  Schowek „wklej"/„wklej bez formatowania" używa async Clipboard API (wymaga uprawnień przeglądarki).
45
- Tabele: odłożone na osobne zadanie.
63
+ Wyjątek od execCommand: wcięcia list robimy własnym kodem na DOM — `execCommand('indent')` produkuje
64
+ w Chrome niepoprawne `ul > ul` (albo `blockquote` z marginesem, który i tak zdjąłby sanityzator).