@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/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@konce-pt/angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.5",
|
|
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",
|
|
7
|
-
"homepage": "https://
|
|
7
|
+
"homepage": "https://ui.konce.pt/",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://gitlab.com/konce-pt/koncept-ui.git",
|
|
@@ -26,68 +26,58 @@
|
|
|
26
26
|
"cdk",
|
|
27
27
|
"data-table",
|
|
28
28
|
"kpt",
|
|
29
|
-
"koncept-ui"
|
|
29
|
+
"koncept-ui",
|
|
30
|
+
"map",
|
|
31
|
+
"leaflet",
|
|
32
|
+
"openstreetmap"
|
|
30
33
|
],
|
|
31
34
|
"sideEffects": false,
|
|
32
|
-
"files": [
|
|
33
|
-
"dist"
|
|
34
|
-
],
|
|
35
|
-
"module": "./dist/fesm2022/konce-pt-angular.mjs",
|
|
36
|
-
"types": "./dist/types/konce-pt-angular.d.ts",
|
|
37
|
-
"exports": {
|
|
38
|
-
".": {
|
|
39
|
-
"types": "./dist/types/konce-pt-angular.d.ts",
|
|
40
|
-
"default": "./dist/fesm2022/konce-pt-angular.mjs"
|
|
41
|
-
},
|
|
42
|
-
"./icons": {
|
|
43
|
-
"types": "./dist/types/konce-pt-angular-icons.d.ts",
|
|
44
|
-
"default": "./dist/fesm2022/konce-pt-angular-icons.mjs"
|
|
45
|
-
},
|
|
46
|
-
"./charts": {
|
|
47
|
-
"types": "./dist/types/konce-pt-angular-charts.d.ts",
|
|
48
|
-
"default": "./dist/fesm2022/konce-pt-angular-charts.mjs"
|
|
49
|
-
},
|
|
50
|
-
"./grid": {
|
|
51
|
-
"types": "./dist/types/konce-pt-angular-grid.d.ts",
|
|
52
|
-
"default": "./dist/fesm2022/konce-pt-angular-grid.mjs"
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
35
|
"peerDependencies": {
|
|
56
36
|
"@angular/cdk": "^22.0.0",
|
|
57
37
|
"@angular/common": "^22.0.0",
|
|
58
38
|
"@angular/core": "^22.0.0",
|
|
59
|
-
"@angular/forms": "^22.0.0"
|
|
39
|
+
"@angular/forms": "^22.0.0",
|
|
40
|
+
"leaflet": "^1.9.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"leaflet": {
|
|
44
|
+
"optional": true
|
|
45
|
+
}
|
|
60
46
|
},
|
|
61
47
|
"dependencies": {
|
|
62
48
|
"tslib": "^2.3.0"
|
|
63
49
|
},
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
50
|
+
"module": "fesm2022/konce-pt-angular.mjs",
|
|
51
|
+
"typings": "types/konce-pt-angular.d.ts",
|
|
52
|
+
"exports": {
|
|
53
|
+
"./package.json": {
|
|
54
|
+
"default": "./package.json"
|
|
55
|
+
},
|
|
56
|
+
".": {
|
|
57
|
+
"types": "./types/konce-pt-angular.d.ts",
|
|
58
|
+
"default": "./fesm2022/konce-pt-angular.mjs"
|
|
59
|
+
},
|
|
60
|
+
"./charts": {
|
|
61
|
+
"types": "./types/konce-pt-angular-charts.d.ts",
|
|
62
|
+
"default": "./fesm2022/konce-pt-angular-charts.mjs"
|
|
63
|
+
},
|
|
64
|
+
"./grid": {
|
|
65
|
+
"types": "./types/konce-pt-angular-grid.d.ts",
|
|
66
|
+
"default": "./fesm2022/konce-pt-angular-grid.mjs"
|
|
67
|
+
},
|
|
68
|
+
"./icons": {
|
|
69
|
+
"types": "./types/konce-pt-angular-icons.d.ts",
|
|
70
|
+
"default": "./fesm2022/konce-pt-angular-icons.mjs"
|
|
71
|
+
},
|
|
72
|
+
"./map": {
|
|
73
|
+
"types": "./types/konce-pt-angular-map.d.ts",
|
|
74
|
+
"default": "./fesm2022/konce-pt-angular-map.mjs"
|
|
75
|
+
},
|
|
76
|
+
"./roadmap": {
|
|
77
|
+
"types": "./types/konce-pt-angular-roadmap.d.ts",
|
|
78
|
+
"default": "./fesm2022/konce-pt-angular-roadmap.mjs"
|
|
87
79
|
}
|
|
88
80
|
},
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
|
|
92
|
-
}
|
|
81
|
+
"type": "module",
|
|
82
|
+
"scripts": {}
|
|
93
83
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# KptRoadmap (kpt-roadmap)
|
|
2
|
+
|
|
3
|
+
Roadmapa — wiersze zadań na poziomej osi czasu (widok typu Gantt). Kolumna etykiet i nagłówek osi
|
|
4
|
+
są przyklejone przy przewijaniu, paski pozycjonowane procentowo, zależności rysuje warstwa SVG.
|
|
5
|
+
Import: `import { KptRoadmap } from '@konce-pt/angular/roadmap';`
|
|
6
|
+
|
|
7
|
+
## Selektor
|
|
8
|
+
`kpt-roadmap` — standalone, OnPush, zoneless. Generyk `KptRoadmap<TItem, TGroup>` typuje pole `meta`.
|
|
9
|
+
|
|
10
|
+
## Wejścia
|
|
11
|
+
- `config`: KptRoadmapConfig (wymagane) — dane i wszystkie opcje
|
|
12
|
+
- `scrollHeight`: string | null — stała wysokość, np. '420px'; włącza przyklejony nagłówek
|
|
13
|
+
- `labelWidth`: string — szerokość kolumny etykiet (domyślnie '14rem')
|
|
14
|
+
- `cellWidthPx`: number | null — szerokość kolumny osi; brak ⇒ wartość zależna od zoomu
|
|
15
|
+
- `showToday`: boolean — znacznik „dziś" (domyślnie true)
|
|
16
|
+
- `virtual`: boolean — renderuje tylko widoczne wiersze; warto od ~100 wierszy
|
|
17
|
+
|
|
18
|
+
## Model / zdarzenia
|
|
19
|
+
- `collapsedGroups`: model<string[]> — dwukierunkowe id zwiniętych grup
|
|
20
|
+
- `itemClick`: output<KptRoadmapItem>
|
|
21
|
+
- `rangeChange`: output<KptTimeRange> — wyliczony zakres osi
|
|
22
|
+
|
|
23
|
+
## KptRoadmapConfig
|
|
24
|
+
- `items`: KptRoadmapItem[] (wymagane)
|
|
25
|
+
- `groups?`: KptRoadmapGroup[]
|
|
26
|
+
- `links?`: KptRoadmapLink[] — zależności podane grafowo
|
|
27
|
+
- `zoom?`: 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' (domyślnie 'week')
|
|
28
|
+
- `range?`: { start?: number; end?: number } — brakujący kraniec wyliczany z danych
|
|
29
|
+
- `locale?`: string; `today?`: Date | number | string
|
|
30
|
+
- `timeline?`, `rows?`, `dependencies?`, `interaction?` — opcje szczegółowe
|
|
31
|
+
|
|
32
|
+
### KptRoadmapItem
|
|
33
|
+
- `id`: string, `label`: string (wymagane)
|
|
34
|
+
- `start`: Date | number | string; `end?`: to samo — brak `end` oznacza kamień milowy
|
|
35
|
+
- `sublabel?`, `icon?`, `disabled?`
|
|
36
|
+
- `variant?`: 'neutral' | 'primary' | 'success' | 'danger' | 'warning' | 'info'
|
|
37
|
+
- `color?`: string — dowolny kolor CSS, nadpisuje `variant`
|
|
38
|
+
- `progress?`: number 0..1 — wypełnienie wewnątrz paska
|
|
39
|
+
- `groupId?`: string; `dependsOn?`: (string | KptRoadmapLink)[] — sam string oznacza zależność 'FS'
|
|
40
|
+
- `milestone?`: boolean — wymusza romb
|
|
41
|
+
- `meta?`: TItem
|
|
42
|
+
- Pola `draggable`, `resizable`, `locked`, `constraints` są zarezerwowane pod edycję i dziś ignorowane.
|
|
43
|
+
|
|
44
|
+
### KptRoadmapGroup
|
|
45
|
+
- `id`, `label` (wymagane); `sublabel?`, `parentId?`, `collapsed?`, `variant?`, `color?`
|
|
46
|
+
- `summary?`: 'auto' | 'none' — 'auto' rysuje pasek zbiorczy od min(start) do max(end) dzieci
|
|
47
|
+
|
|
48
|
+
### KptTimelineOptions (`config.timeline`)
|
|
49
|
+
- `weekendDays?`: number[] (domyślnie [0, 6]); `weekPrefix?`: string (domyślnie z i18n)
|
|
50
|
+
- `workHours?`: { from, to, mode?: 'skip' | 'dim', skipWeekends? } — tylko przy `zoom: 'hour'`;
|
|
51
|
+
'skip' wycina noce z osi, 'dim' zostawia kolumny wyszarzone
|
|
52
|
+
- `positionMode?`: 'uniform' (domyślnie) | 'linear'
|
|
53
|
+
- `bandUnit?`: jednostka górnego poziomu nagłówka; `maxCells?`: number (domyślnie 4000)
|
|
54
|
+
|
|
55
|
+
### KptRoadmapRowOptions (`config.rows`)
|
|
56
|
+
- `mode?`: 'row-per-item' (domyślnie) | 'pack' — 'pack' układa nienachodzące zadania w jednym wierszu
|
|
57
|
+
- `itemHeight?`, `groupHeight?`, `laneHeight?`, `packMinGapMs?`
|
|
58
|
+
- `showUngroupedHeader?`, `ungroupedLabel?`
|
|
59
|
+
|
|
60
|
+
## Przykład
|
|
61
|
+
|
|
62
|
+
<kpt-roadmap [config]="roadmap" scrollHeight="420px" />
|
|
63
|
+
|
|
64
|
+
roadmap: KptRoadmapConfig = {
|
|
65
|
+
zoom: 'week',
|
|
66
|
+
groups: [{ id: 'app', label: 'Aplikacja' }],
|
|
67
|
+
items: [
|
|
68
|
+
{ id: 'auth', label: 'Logowanie', start: '2026-08-24', end: '2026-08-31',
|
|
69
|
+
groupId: 'app', variant: 'success', progress: 1 },
|
|
70
|
+
{ id: 'ship', label: 'Wydanie', start: '2026-09-14', groupId: 'app',
|
|
71
|
+
variant: 'warning', dependsOn: ['auth'] },
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
## Zachowanie
|
|
76
|
+
- Oś liczona w czasie lokalnym; numeracja tygodni wg ISO 8601 (tydzień 1 zawiera pierwszy czwartek roku).
|
|
77
|
+
- Tryb 'uniform' daje kolumny równej szerokości mimo zmiany czasu i różnej długości miesięcy;
|
|
78
|
+
wewnątrz kolumny pozycja jest interpolowana liniowo, więc zadanie może zaczynać się w środku dnia.
|
|
79
|
+
- Zmiana roku: mocniejsza pionowa linia i czarny znacznik z rokiem na pierwszym paśmie danego roku.
|
|
80
|
+
Przy zoomie tygodniowym granica liczona po roku tygodnia ISO, więc W53 nie trafia do kolejnego roku.
|
|
81
|
+
- Item wystający poza zakres osi jest ścinany od strony przycięcia.
|
|
82
|
+
- Podpowiedzi to dyrektywa `kptTooltip` (nie natywny `title`): dymek pojawia się od razu, jest
|
|
83
|
+
stylowany tokenami i działa też na focusie z klawiatury.
|
|
84
|
+
- Zasada: dymek pokazuje to, czego nie widać. Paski, etykiety wierszy i pasma nagłówka mają go
|
|
85
|
+
z `kptTooltipOnlyWhenTruncated`, więc podpowiedź wyskakuje wyłącznie przy tekście uciętym
|
|
86
|
+
wielokropkiem — sprawdzanym przy najechaniu, więc reagującym na zmianę szerokości i zoomu.
|
|
87
|
+
Kamienie milowe i komórki nagłówka mają dymek bezwarunkowo: romb nie pokazuje tekstu w ogóle,
|
|
88
|
+
a komórka dopowiada rok, którego w „W35 / 24.08–30.08" nie widać.
|
|
89
|
+
- Zależności: 'FS' (domyślna), 'SS', 'FF', 'SF'; naruszone są rysowane linią przerywaną w kolorze danger.
|
|
90
|
+
- Elementy z niepoprawną datą lub zduplikowanym `id` są pomijane, z ostrzeżeniem w trybie deweloperskim.
|
|
91
|
+
|
|
92
|
+
## i18n
|
|
93
|
+
Klucze `roadmap.*`: `empty`, `week`, `today`, `milestone`, `expandGroup`, `collapseGroup`.
|
|
94
|
+
Nazwy miesięcy i dni tygodnia pochodzą z `Intl` wg `config.locale` albo locale z `KptI18n`,
|
|
95
|
+
więc mają formę zgodną z ortografią języka (po polsku małą literą, po angielsku wielką).
|
|
96
|
+
W nagłówku pierwszy znak jest kapitalizowany przez `::first-letter`, żeby wygląd osi był ten sam
|
|
97
|
+
niezależnie od języka; sam tekst pozostaje niezmieniony, więc podpowiedzi i odczyt przez czytnik
|
|
98
|
+
ekranu dostają formę oryginalną.
|
|
99
|
+
|
|
100
|
+
## Tokeny
|
|
101
|
+
Powierzchnie `--kpt-color-surface{,-variant,-sunken,-hover}`, obrys `--kpt-color-border{,-strong}`,
|
|
102
|
+
paski wg wariantu `--kpt-color-{primary,success,danger,warning,info,muted}`.
|
|
103
|
+
Etykieta paska jest biała, ale wariant `neutral` ma jasne tło, więc jego napis używa
|
|
104
|
+
`--kpt-color-on-muted`. Pasek zbiorczy grupy w wariancie `neutral` rysuje się kolorem
|
|
105
|
+
`--kpt-color-on-surface-muted` — `--kpt-color-muted` byłby nieodróżnialny od tła wiersza.
|
|
106
|
+
Dalej:
|
|
107
|
+
znacznik roku na inwersji `--kpt-color-on-surface` / `--kpt-color-surface`.
|
|
108
|
+
Rozmiary: `--kpt-roadmap-label-w`, `--kpt-roadmap-cell-w` (obie można nadpisać z zewnątrz).
|
|
109
|
+
|
|
110
|
+
## Do zrobienia (roadmap)
|
|
111
|
+
Przeciąganie i zmiana zakresu pasków, rysowanie zależności myszą, dodawanie wierszy —
|
|
112
|
+
typy (`KptRoadmapChange`, `constraints`, `interaction`) są już częścią API.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# KptAppShell (kpt-app-shell)
|
|
2
|
+
|
|
3
|
+
Szkielet aplikacji: pasek u góry, panel boczny, treść. Responsywny bez konfiguracji.
|
|
4
|
+
Import: `import { KptAppShell, KptShellNavToggle } from '@konce-pt/angular';`
|
|
5
|
+
|
|
6
|
+
## Selektor
|
|
7
|
+
`kpt-app-shell`
|
|
8
|
+
|
|
9
|
+
## Wejścia / wyjścia
|
|
10
|
+
- `sidenavOpen`: model<boolean> (domyślnie `true`) — stan panelu ZADOKOWANEGO
|
|
11
|
+
(oraz wymuszonego trybu `over`); dwukierunkowe `[(sidenavOpen)]`
|
|
12
|
+
- `sidenavCompactOpen`: model<boolean> (domyślnie `false`) — stan NAKŁADKI w trybie `auto`
|
|
13
|
+
- `sidenavMode`: `'auto' | 'side' | 'over'` (domyślnie **`'auto'`**)
|
|
14
|
+
- `sidenavBreakpoint`: `'sm'|'md'|'lg'|'xl'|'2xl'` (domyślnie `'lg'`) — od tego progu w górę
|
|
15
|
+
tryb `auto` dokuje panel, poniżej robi z niego nakładkę
|
|
16
|
+
- `sidenavRailBreakpoint`: ten sam zbiór albo `null` (domyślnie `null`) — włącza szynę ikon
|
|
17
|
+
w paśmie od `sidenavBreakpoint` do tego progu; wartość musi być WYŻSZA niż `sidenavBreakpoint`
|
|
18
|
+
- `sidenavLabel`: string — etykieta a11y panelu; puste = `appShell.navigation` ze słownika
|
|
19
|
+
- `sidenavId`: readonly string — identyfikator panelu (`aria-controls`)
|
|
20
|
+
- `isOverlay()`, `isSidenavOpen()`: Signal<boolean> — stan efektywny dla bieżącego układu
|
|
21
|
+
- `toggleSidenav()`, `openSidenav()`, `closeSidenav()` — trafiają w stan właściwy dla układu
|
|
22
|
+
|
|
23
|
+
## Sloty projekcji
|
|
24
|
+
- `[kptShellToolbar]` → pasek u góry
|
|
25
|
+
- `[kptShellSidenav]` → panel boczny
|
|
26
|
+
- treść domyślna → obszar główny
|
|
27
|
+
|
|
28
|
+
## Przykład
|
|
29
|
+
<kpt-app-shell [(sidenavOpen)]="navOpen">
|
|
30
|
+
<kpt-toolbar kptShellToolbar elevated>
|
|
31
|
+
<kpt-icon-button kptShellNavToggle variant="text" ariaLabel="Menu">
|
|
32
|
+
<kpt-icon name="menu" />
|
|
33
|
+
</kpt-icon-button>
|
|
34
|
+
</kpt-toolbar>
|
|
35
|
+
<kpt-sidenav kptShellSidenav>
|
|
36
|
+
<a href="#"><kpt-icon name="list" /> <span kptNavLabel>Pulpit</span></a>
|
|
37
|
+
</kpt-sidenav>
|
|
38
|
+
<router-outlet />
|
|
39
|
+
</kpt-app-shell>
|
|
40
|
+
|
|
41
|
+
## Trzy pasma trybu 'auto'
|
|
42
|
+
| szerokość | układ | co robi zamknięcie |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `< sidenavBreakpoint` | nakładka + scrim | panel wyjeżdża poza krawędź (stan: `sidenavCompactOpen`) |
|
|
45
|
+
| `>= sidenavBreakpoint`, `< sidenavRailBreakpoint` | szyna ikon | panel zwęża się do `--kpt-sidenav-rail-width` |
|
|
46
|
+
| `>= sidenavRailBreakpoint` (lub brak szyny) | pełny panel | panel chowa się w całości |
|
|
47
|
+
|
|
48
|
+
## Dlaczego DWA stany otwarcia
|
|
49
|
+
„Otwarty" znaczy co innego po obu stronach progu: na desktopie panel domyślnie stoi otwarty,
|
|
50
|
+
na telefonie domyślnie musi być schowany. Gdyby oba układy dzieliły jeden model, wejście na wąski
|
|
51
|
+
ekran musiałoby nadpisać stan aplikacji, a powrót na szeroki nie miałby czego przywrócić.
|
|
52
|
+
Rozdzielenie sprawia, że intencja z desktopu przeżywa zwężenie i rozszerzenie okna za darmo.
|
|
53
|
+
|
|
54
|
+
Przycisk `kptShellNavToggle` sam trafia we właściwy stan — nie pisz `navOpen.set(...)` ręcznie,
|
|
55
|
+
bo na wąskim ekranie ustawisz nie ten model.
|
|
56
|
+
|
|
57
|
+
## Konwencja treści menu (potrzebna tylko dla szyny)
|
|
58
|
+
- `[kptNavLabel]` — tekst pozycji; w szynie chowany techniką „visually hidden", więc pozycja
|
|
59
|
+
zachowuje dostępną nazwę dla czytnika ekranu.
|
|
60
|
+
- `[kptNavSection]` — nagłówek grupy; chowany tak samo.
|
|
61
|
+
|
|
62
|
+
To płaskie atrybuty (jak `kptShellToolbar` czy `kptToolbarSpacer`), nie dyrektywy — nic nie trzeba
|
|
63
|
+
importować. Bez nich szyna pokaże ucięty tekst zamiast ikony. W szynie warto opatrzyć pozycje
|
|
64
|
+
`kptTooltip`, bo widać sam znak.
|
|
65
|
+
|
|
66
|
+
## Zachowanie
|
|
67
|
+
- O układzie decyduje wyłącznie CSS (`@media`), więc nic nie migocze przed hydracją i całość
|
|
68
|
+
działa na SSR. JavaScript odpowiada tylko za to, który stan przełącza przycisk.
|
|
69
|
+
- Zamknięty panel wypada z kolejki Tab przez `visibility: hidden` (nie `inert`) — jest poprawny
|
|
70
|
+
już na pierwszej klatce.
|
|
71
|
+
- Otwarta nakładka nakłada `inert` na treść (`<main>`), więc Tab nie wchodzi pod scrim.
|
|
72
|
+
- `Escape` zamyka nakładkę; klik w scrim też.
|
|
73
|
+
- Kierunek wysuwu idzie za `dir` (RTL wyjeżdża z prawej).
|
|
74
|
+
- Wysokość: `100dvh` z fallbackiem `100vh`.
|
|
75
|
+
- **Nie** zamyka menu po nawigacji — shell nie wie, co w danej aplikacji nią jest.
|
|
76
|
+
Zrób to sam: `if (shell.isOverlay()) shell.closeSidenav();`.
|
|
77
|
+
|
|
78
|
+
## Tryby wymuszone (zgodność wsteczna)
|
|
79
|
+
`sidenavMode="side"` i `"over"` ignorują szerokość okna i czytają `sidenavOpen`, dokładnie jak
|
|
80
|
+
przed wprowadzeniem `auto`. Ustaw `"side"`, jeśli aplikacja sama zarządza responsywnością —
|
|
81
|
+
inaczej dostaniesz dwie warstwy tej samej logiki.
|
|
82
|
+
|
|
83
|
+
## Tokeny
|
|
84
|
+
`--kpt-sidenav-width` (16rem), `--kpt-sidenav-rail-width` (4rem), `--kpt-z-overlay`,
|
|
85
|
+
`--kpt-color-overlay-scrim`, `--kpt-elevation-3`, `--kpt-motion-duration-base`.
|
|
86
|
+
|
|
87
|
+
## Odłożone
|
|
88
|
+
Focus trap i zwrot fokusu do przycisku po zamknięciu (spójnie z `kpt-drawer`, który też ich
|
|
89
|
+
nie ma — to osobne zadanie dla całego repo). `<aside>` ma już `tabindex="-1"`.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# KptBreakpointObserver
|
|
2
|
+
|
|
3
|
+
Serwis (root) zamieniający media query na sygnały. Jedyny w bibliotece sposób na zapytanie
|
|
4
|
+
„jak szerokie jest okno" z poziomu TypeScriptu.
|
|
5
|
+
|
|
6
|
+
## API
|
|
7
|
+
|
|
8
|
+
inject(KptBreakpointObserver)
|
|
9
|
+
|
|
10
|
+
- `up(bp: KptBreakpoint): Signal<boolean>` — `(min-width: <próg>px)`, mobile-first.
|
|
11
|
+
- `down(bp: KptBreakpoint): Signal<boolean>` — `(max-width: <próg - 0.02>px)`; odjęcie 0.02px
|
|
12
|
+
sprawia, że pasma `up`/`down` nie nakładają się na ułamkowych szerokościach (zoom, DPI).
|
|
13
|
+
- `matches(query: string): Signal<boolean>` — dowolne media query.
|
|
14
|
+
|
|
15
|
+
`KptBreakpoint` = `'sm' | 'md' | 'lg' | 'xl' | '2xl'`; progi w `KPT_BREAKPOINTS`
|
|
16
|
+
(640 / 768 / 1024 / 1280 / 1536 px).
|
|
17
|
+
|
|
18
|
+
## Skąd biorą się wartości
|
|
19
|
+
|
|
20
|
+
Z tokenów: `packages/tokens/tokens/primitives/breakpoint.json` → `scripts/gen-tokens.mjs`
|
|
21
|
+
generuje `breakpoint/breakpoints.generated.ts` (dla JS) i `styles/_breakpoints.generated.scss`
|
|
22
|
+
(dla `@media` w SCSS komponentów). Oba pliki są commitowane i **nie edytuje się ich ręcznie** —
|
|
23
|
+
zmiana progu idzie przez token i `pnpm nx build angular`. Dzięki jednemu źródłu CSS biblioteki
|
|
24
|
+
i jej JavaScript nie mogą rozjechać się cicho.
|
|
25
|
+
|
|
26
|
+
## SSR
|
|
27
|
+
|
|
28
|
+
Poza przeglądarką każdy sygnał to stałe `false`. Nie buduj na nim układu strony — od tego jest
|
|
29
|
+
CSS (`@media`), inaczej dostaniesz migotanie przed hydracją. Serwis służy do zachowań:
|
|
30
|
+
w którą stronę ma zadziałać przycisk, czy zamykać panel po nawigacji, co odłożyć na później.
|
|
31
|
+
|
|
32
|
+
## Przykład
|
|
33
|
+
|
|
34
|
+
@Component({ /* … */ })
|
|
35
|
+
export class Header {
|
|
36
|
+
private readonly breakpoints = inject(KptBreakpointObserver);
|
|
37
|
+
readonly isDesktop = this.breakpoints.up('lg');
|
|
38
|
+
readonly isCompact = this.breakpoints.down('md');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
## Uwagi
|
|
42
|
+
|
|
43
|
+
- Zapytania są memoizowane per string — `up('lg')` w dziesięciu komponentach to jeden
|
|
44
|
+
`MediaQueryList` i jeden nasłuch; nie trzeba tego cache'ować u siebie.
|
|
45
|
+
- Sprzątanie idzie przez `DestroyRef` root injectora, więc nie ma czego odsubskrybować.
|
|
@@ -23,6 +23,9 @@ Import: `import { KptDatepicker } from '@konce-pt/angular';`
|
|
|
23
23
|
- `monthDisplay`: 'long' | 'number' (domyślnie 'long') — w trybie 'month' i etykietach miesięcy: słownie (styczeń) lub liczbą (01)
|
|
24
24
|
- `displayFormat`: 'pl' | 'iso' (domyślnie 'pl') — format wyświetlania i domyślnego placeholdera
|
|
25
25
|
- `disabled`/`invalid`/`touched`: boolean; output `touch`.
|
|
26
|
+
- `ariaLabel`: string|null — nazwa dostępna, gdy pola nie opisuje `<label for>`
|
|
27
|
+
(np. dwie godziny w jednym wierszu edytora). Bez niej czytnik ekranu ogłasza samą wartość.
|
|
28
|
+
- Ikona w polu: kalendarz, a w trybie 'time' zegar.
|
|
26
29
|
- Panel: nawigacja (‹ ›) miesięcy/lat/dekad wg trybu; tarcza zegara z „Gotowe"; przycisk czyszczenia (×).
|
|
27
30
|
|
|
28
31
|
## i18n
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# KptDialog (kpt-dialog)
|
|
2
|
+
|
|
3
|
+
Okno modalne na natywnym `<dialog>` (focus trap, Esc, backdrop w standardzie).
|
|
4
|
+
Import: `import { KptDialog } from '@konce-pt/angular';`
|
|
5
|
+
|
|
6
|
+
## Selektor
|
|
7
|
+
`kpt-dialog`
|
|
8
|
+
|
|
9
|
+
## Wejścia
|
|
10
|
+
- `open`: model<boolean> — dwukierunkowe `[(open)]`
|
|
11
|
+
- `header`: string; `dismissible`: boolean (Esc/× zamyka; domyślnie true)
|
|
12
|
+
|
|
13
|
+
## Sloty
|
|
14
|
+
- treść domyślna → body; element z atrybutem `kptDialogFooter` → stopka
|
|
15
|
+
|
|
16
|
+
## Przykład
|
|
17
|
+
<kpt-dialog [(open)]="confirmOpen" header="Usunąć?">
|
|
18
|
+
Nieodwracalne.
|
|
19
|
+
<div kptDialogFooter>
|
|
20
|
+
<kpt-button variant="text" (click)="confirmOpen.set(false)">Anuluj</kpt-button>
|
|
21
|
+
<kpt-button variant="danger" (click)="remove()">Usuń</kpt-button>
|
|
22
|
+
</div>
|
|
23
|
+
</kpt-dialog>
|
|
24
|
+
|
|
25
|
+
## Tokeny
|
|
26
|
+
`--kpt-color-surface-raised`, `--kpt-color-overlay-scrim` (::backdrop), `--kpt-elevation-4`.
|
|
27
|
+
Uwaga: globalny reset zeruje margin — komponent przywraca `margin:auto` (centrowanie).
|
|
28
|
+
|
|
29
|
+
## Kontrolki na CDK Overlay w środku okna
|
|
30
|
+
|
|
31
|
+
`kpt-dialog` stoi na natywnym `<dialog>` i otwiera się przez `showModal()`, co wynosi je
|
|
32
|
+
do **warstwy szczytowej** przeglądarki — a ta jest ponad całym drzewem dokumentu i żaden
|
|
33
|
+
`z-index` jej nie przebije. Kontener CDK Overlay wisi domyślnie na `<body>`, więc panele
|
|
34
|
+
`kpt-select`, `kpt-datepicker`, `kpt-autocomplete` i `kpt-menu` otwierałyby się w środku
|
|
35
|
+
okna NIEWIDOCZNE, schowane za jego tłem.
|
|
36
|
+
|
|
37
|
+
Dlatego `kpt-dialog` na czas otwarcia przenosi kontener overlayów do wnętrza `<dialog>`
|
|
38
|
+
i oddaje go na miejsce przy zamknięciu (również gdy komponent zostanie zniszczony
|
|
39
|
+
z otwartym oknem). Nie trzeba nic konfigurować — kontrolki overlayowe działają w oknie
|
|
40
|
+
tak samo jak poza nim.
|
|
41
|
+
|
|
42
|
+
## Układ i przewijanie
|
|
43
|
+
|
|
44
|
+
Otwarte okno jest kolumną flex: nagłówek (`.kpt-dialog__header`) i stopka
|
|
45
|
+
(`[kptDialogFooter]`) stoją nieruchomo, a przewija się wyłącznie `.kpt-dialog__body`.
|
|
46
|
+
Pasek przewijania biegnie więc tylko wzdłuż treści, nie wzdłuż całego okna.
|
|
47
|
+
|
|
48
|
+
Treść dostaje `flex: 0 1 auto` (domyślne) + `min-height: 0`, celowo **nie** `flex: 1`
|
|
49
|
+
jak w `kpt-drawer`. Szuflada wypełnia wysokość ekranu, okno ma kurczyć się do treści:
|
|
50
|
+
krótkie (`kpt-confirm` — dwa zdania i dwa przyciski) zostaje krótkie, długie zatrzymuje się
|
|
51
|
+
na `max-height: calc(100vh - 4rem)` i przewija samą treść.
|
|
52
|
+
|
|
53
|
+
Deklaracja `display: flex` jest scopowana `&[open]` i musi taka zostać. Regułę
|
|
54
|
+
`dialog:not([open]) { display: none }` daje arkusz przeglądarki, a każda deklaracja
|
|
55
|
+
autorska ją bije — także z `@layer`. Niescopowane `display: flex` zostawiłoby wszystkie
|
|
56
|
+
zamknięte okna widoczne na stronie.
|
|
57
|
+
|
|
58
|
+
`.kpt-dialog` nie dostaje `overflow: hidden` — kontener CDK Overlay jest na czas otwarcia
|
|
59
|
+
przeniesiony do wnętrza `<dialog>` (patrz sekcja wyżej), więc przycięcie okna ucięłoby
|
|
60
|
+
panele `kpt-select` czy `kpt-datepicker`. Do samego przewijania nie jest potrzebne:
|
|
61
|
+
po przejściu na flex nic nie wystaje poza okno.
|
|
62
|
+
|
|
63
|
+
Przypięty pasek akcji wewnątrz treści (np. „Anuluj / Zapisz" w `kpt-map-create-dialog`)
|
|
64
|
+
robi się przez `position: sticky` — kontenerem przewijania jest `.kpt-dialog__body`.
|
|
65
|
+
Ujemne marginesy boczne muszą zgadzać się z jego paddingiem (`--kpt-space-6`),
|
|
66
|
+
a przesunięcie `bottom` musi być lustrem ujemnego marginesu dolnego
|
|
67
|
+
(`bottom: calc(var(--kpt-space-6) * -1)`) — przyklejanie liczy się dla marginesowego
|
|
68
|
+
pudełka, więc przy `bottom: 0` pod paskiem przesuwałby się skrawek treści.
|
|
@@ -24,12 +24,30 @@ Import: `import { KptFormField } from '@konce-pt/angular';`
|
|
|
24
24
|
Warianty float mają animowane przejście etykiety (pozycja spoczynkowa w miejscu placeholdera →
|
|
25
25
|
uniesiona). Uniesienie następuje przy focusie kontrolki **lub** gdy pole ma wartość. Wykrywanie
|
|
26
26
|
wypełnienia jest po stronie komponentu (zdarzenia `input`/`change` + wartość początkowa) — **nie**
|
|
27
|
-
wymaga ustawiania placeholdera na kontrolce.
|
|
27
|
+
wymaga ustawiania placeholdera na kontrolce.
|
|
28
28
|
|
|
29
29
|
<kpt-form-field label="E-mail" labelType="over">
|
|
30
30
|
<kpt-input />
|
|
31
31
|
</kpt-form-field>
|
|
32
32
|
|
|
33
|
+
### Kontrolki bez natywnego `input`/`textarea`
|
|
34
|
+
|
|
35
|
+
Wartości `kpt-select` nie da się odczytać z DOM (panel żyje w overlayu), więc taka kontrolka
|
|
36
|
+
zgłasza wypełnienie sama — dostarcza token `KPT_FORM_FIELD_CONTROL` z sygnałem `filled`.
|
|
37
|
+
`kpt-select` robi to z pudełka; własna kontrolka wymaga:
|
|
38
|
+
|
|
39
|
+
import { KPT_FORM_FIELD_CONTROL, type KptFormFieldControl } from '@konce-pt/angular';
|
|
40
|
+
|
|
41
|
+
@Component({
|
|
42
|
+
providers: [{ provide: KPT_FORM_FIELD_CONTROL, useExisting: forwardRef(() => MyControl) }],
|
|
43
|
+
})
|
|
44
|
+
export class MyControl implements KptFormFieldControl {
|
|
45
|
+
readonly filled = computed(() => this.value() != null);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Gdy kontrolka dostarczy token, `kpt-form-field` przestaje zaglądać do DOM i ufa wyłącznie
|
|
49
|
+
sygnałowi `filled` — dlatego etykieta unosi się natychmiast po zmianie wartości.
|
|
50
|
+
|
|
33
51
|
## Projekcja
|
|
34
52
|
Kontrolkę umieszcza się w treści (ng-content):
|
|
35
53
|
|
|
@@ -45,6 +63,11 @@ Kontrolkę umieszcza się w treści (ng-content):
|
|
|
45
63
|
return s.touched() && s.invalid() ? s.errors()[0]?.message ?? null : null;
|
|
46
64
|
});
|
|
47
65
|
|
|
66
|
+
Bramka `touched()` dotyczy wyłącznie komunikatu — walidatorów nie warunkuj (`when:` na
|
|
67
|
+
`state.touched()` sprawia, że `valid()` kłamie na nietkniętym formularzu). Kontrolki `kpt-*`
|
|
68
|
+
same bramkują swój stan wizualny tak samo. Pełny przepływ submit: sekcja
|
|
69
|
+
`## Formularz od zera (Signal Forms)` w głównym llms.txt.
|
|
70
|
+
|
|
48
71
|
## Tokeny
|
|
49
72
|
`--kpt-form-field-label`, `--kpt-form-field-hint`, `--kpt-form-field-error`, `--kpt-color-danger`.
|
|
50
73
|
Warianty float dodatkowo: `--kpt-form-field-placeholder` (etykieta spoczynkowa),
|
|
@@ -14,7 +14,8 @@ kolor z `currentColor`. Import: `import { KptIcon } from '@konce-pt/angular';`
|
|
|
14
14
|
menu, x, chevron-up, chevron-down, chevron-left, chevron-right, check, search,
|
|
15
15
|
grip-vertical, info, alert-triangle, circle-check, circle-x, calendar, copy, link, code,
|
|
16
16
|
star, phone, map-pin, world, clock, align-left, align-center, align-right, align-justified,
|
|
17
|
-
palette, highlight, clipboard, clipboard-text, table
|
|
17
|
+
palette, highlight, clipboard, clipboard-text, table, mail, share, external-link, crosshair
|
|
18
|
+
(pełna lista w `icons.ts`).
|
|
18
19
|
|
|
19
20
|
## Pełny zestaw (5130 ikon Tabler)
|
|
20
21
|
Opcjonalny entry point `@konce-pt/angular/icons` (pobierany tylko przy imporcie):
|
|
@@ -17,11 +17,18 @@ Bez `ControlValueAccessor`. Import: `import { KptInput } from '@konce-pt/angular
|
|
|
17
17
|
email(p.email, { message: 'Podaj poprawny adres e-mail' });
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
// szablon (imports: [KptInput, FormField])
|
|
21
|
-
<
|
|
20
|
+
// szablon (imports: [KptInput, FormField, FormRoot, KptButton])
|
|
21
|
+
<form [formRoot]="loginForm" (submit)="onSubmit()">
|
|
22
|
+
<kpt-input [formField]="loginForm.email" type="email" id="f-email" />
|
|
23
|
+
<kpt-button type="submit" [disabled]="loginForm().invalid()">Zaloguj</kpt-button>
|
|
24
|
+
</form>
|
|
25
|
+
|
|
26
|
+
`[formRoot]` sam ustawia `novalidate` i woła `submit()`; `submit()` sam robi `markAsTouched()`.
|
|
27
|
+
Nie warunkuj walidatorów przez `when: state.touched()` — psuje to `valid()`.
|
|
28
|
+
Pełny przepływ: sekcja `## Formularz od zera (Signal Forms)` w głównym llms.txt.
|
|
22
29
|
|
|
23
30
|
## Wejścia prezentacyjne
|
|
24
|
-
- `type`: 'text'|'email'|'password'|'number'|'search'|'tel'|'url' (domyślnie 'text')
|
|
31
|
+
- `type`: 'text'|'email'|'password'|'number'|'search'|'tel'|'url'|'time' (domyślnie 'text')
|
|
25
32
|
- `placeholder`: string
|
|
26
33
|
- `id`: string — trafia na wewnętrzny `<input>` (do `label[for]`); host go nie nosi
|
|
27
34
|
- `ariaLabel`: string | null
|
|
@@ -34,5 +41,8 @@ Bez `ControlValueAccessor`. Import: `import { KptInput } from '@konce-pt/angular
|
|
|
34
41
|
`--kpt-form-field-{bg,text,placeholder,border,border-hover,border-focus,border-error,radius}`.
|
|
35
42
|
|
|
36
43
|
## Dostępność
|
|
37
|
-
- `aria-invalid="true"`
|
|
44
|
+
- `aria-invalid="true"` dopiero gdy pole jest nieprawidłowe **i** dotknięte (`blur`) — świeży,
|
|
45
|
+
pusty formularz nie jest malowany na czerwono.
|
|
46
|
+
- `aria-required="true"` przy `required` — celowo nie natywny atrybut `required`, który
|
|
47
|
+
blokowałby zdarzenie submit i uruchamiał walidację przeglądarki obok Signal Forms.
|
|
38
48
|
- Komunikaty błędów wyświetla zwykle `kpt-form-field` (`role="alert"`).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# KptInputNumber (kpt-input-number)
|
|
2
|
+
|
|
3
|
+
Pole liczbowe ze strzałkami krokowania na Signal Forms. Wartość = number | null.
|
|
4
|
+
`showButtons="false"` daje wariant bez strzałek — do zakresów „od–do".
|
|
5
|
+
Import: `import { KptInputNumber } from '@konce-pt/angular';`
|
|
6
|
+
|
|
7
|
+
## Wejścia / model
|
|
8
|
+
- `value`: model<number | null> (lub `formField`)
|
|
9
|
+
- `min`/`max`: number | undefined; `step`: number (domyślnie 1)
|
|
10
|
+
- `suffix`: string (np. ' %'); `placeholder`: string
|
|
11
|
+
- `showButtons`: boolean (domyślnie `true`) — `false` chowa strzałki `−`/`+`; treść pola
|
|
12
|
+
wyrównuje się wtedy do lewej, jak w `kpt-input` (modyfikator `.kpt-input-number--plain`)
|
|
13
|
+
- `disabled`/`invalid`/`touched`: boolean; `touch`: output
|
|
14
|
+
|
|
15
|
+
## Przykład
|
|
16
|
+
<kpt-input-number [formField]="f.qty" [min]="0" [max]="99" [step]="1" />
|
|
17
|
+
<kpt-input-number [(value)]="qty" suffix=" szt." />
|
|
18
|
+
<kpt-input-number [formField]="f.priceFrom" [showButtons]="false" suffix=" zł" />
|
|
19
|
+
|
|
20
|
+
## Zakres „od–do" (walidacja między polami)
|
|
21
|
+
|
|
22
|
+
Dwa osobne pola formularza; regułę „do ≥ od" wpina się przez `validateTree` na korzeniu.
|
|
23
|
+
Błąd celuje się w konkretne pole właściwością `fieldTree` — inaczej wylądowałby na formularzu
|
|
24
|
+
i nie pokazałby się pod żadną kontrolką.
|
|
25
|
+
|
|
26
|
+
import { form, min, validateTree } from '@angular/forms/signals';
|
|
27
|
+
|
|
28
|
+
model = signal({ priceFrom: null as number | null, priceTo: null as number | null });
|
|
29
|
+
|
|
30
|
+
rangeForm = form(this.model, (path) => {
|
|
31
|
+
min(path.priceFrom, 0, { message: 'Wartość nie może być ujemna' });
|
|
32
|
+
min(path.priceTo, 0, { message: 'Wartość nie może być ujemna' });
|
|
33
|
+
|
|
34
|
+
validateTree(path, (ctx) => {
|
|
35
|
+
const from = ctx.valueOf(path.priceFrom);
|
|
36
|
+
const to = ctx.valueOf(path.priceTo);
|
|
37
|
+
if (from === null || to === null || from <= to) return null;
|
|
38
|
+
return {
|
|
39
|
+
kind: 'range',
|
|
40
|
+
message: 'Wartość „do" nie może być mniejsza niż „od"',
|
|
41
|
+
fieldTree: ctx.fieldTreeOf(path.priceTo), // błąd ląduje na polu „do"
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// szablon — dwie kolumny od md (klasy utility z @konce-pt/grid)
|
|
47
|
+
<form class="kpt-grid" [formRoot]="rangeForm" (submit)="onSubmit()">
|
|
48
|
+
<kpt-form-field class="kpt-col-12 kpt-col-md-6" label="Cena od" [error]="fromError()">
|
|
49
|
+
<kpt-input-number [formField]="rangeForm.priceFrom" [min]="0" [showButtons]="false" suffix=" zł" />
|
|
50
|
+
</kpt-form-field>
|
|
51
|
+
<kpt-form-field class="kpt-col-12 kpt-col-md-6" label="Cena do" [error]="toError()">
|
|
52
|
+
<kpt-input-number [formField]="rangeForm.priceTo" [min]="0" [showButtons]="false" suffix=" zł" />
|
|
53
|
+
</kpt-form-field>
|
|
54
|
+
</form>
|
|
55
|
+
|
|
56
|
+
`ctx.valueOf(path.x)` czyta wartość innego pola, `ctx.fieldTreeOf(path.x)` wskazuje pole
|
|
57
|
+
docelowe błędu. Komunikaty podaje się przez `errorFor()` z bramką `touched()` — walidatorów
|
|
58
|
+
nie warunkuj. Pełny przepływ submit: `## Formularz od zera (Signal Forms)` w głównym llms.txt.
|
|
59
|
+
|
|
60
|
+
## Tokeny
|
|
61
|
+
Pole `--kpt-form-field-*`; przyciski `--kpt-color-muted`.
|
|
@@ -18,6 +18,15 @@ Wymaga stylów overlay CDK w aplikacji: `import '@angular/cdk/overlay-prebuilt.c
|
|
|
18
18
|
- `disabled`/`invalid`/`touched`: boolean; output `touch`.
|
|
19
19
|
- Klawiatura: Enter/↓ otwiera, ↑/↓ nawigacja, Enter wybiera, Esc zamyka.
|
|
20
20
|
|
|
21
|
+
## Float Label
|
|
22
|
+
W `kpt-form-field` z `labelType` `over`/`in`/`on` etykieta unosi się także po wybraniu opcji —
|
|
23
|
+
select dostarcza token `KPT_FORM_FIELD_CONTROL` z sygnałem `filled` (wartości w overlayu nie da
|
|
24
|
+
się odczytać z DOM). Nic nie trzeba konfigurować:
|
|
25
|
+
|
|
26
|
+
<kpt-form-field label="Kraj" labelType="on">
|
|
27
|
+
<kpt-select [formField]="f.country" [options]="countries" />
|
|
28
|
+
</kpt-form-field>
|
|
29
|
+
|
|
21
30
|
## i18n
|
|
22
31
|
Etykiety „Szukaj…", „Brak wyników" i aria usuwania chipa z i18n (namespace `select`).
|
|
23
32
|
Domyślnie EN; konfiguracja przez `provideKptI18n` — patrz `i18n/llms.txt`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# KptSidenav (kpt-sidenav)
|
|
2
|
+
|
|
3
|
+
Panel boczny — stylowany kontener nawigacji, zwykle w slocie `kptShellSidenav`
|
|
4
|
+
komponentu `kpt-app-shell`. Import: `import { KptSidenav } from '@konce-pt/angular';`
|
|
5
|
+
|
|
6
|
+
## Selektor
|
|
7
|
+
`kpt-sidenav`
|
|
8
|
+
|
|
9
|
+
## Treść
|
|
10
|
+
Dowolna zawartość (ng-content). Elementy `<a>` mają wbudowane style pozycji nawigacji
|
|
11
|
+
(hover z `--kpt-color-muted`).
|
|
12
|
+
|
|
13
|
+
## Przykład
|
|
14
|
+
<kpt-sidenav kptShellSidenav>
|
|
15
|
+
<a href="#">Pulpit</a>
|
|
16
|
+
<a href="#">Ustawienia</a>
|
|
17
|
+
</kpt-sidenav>
|
|
18
|
+
|
|
19
|
+
## Szyna ikon (kpt-app-shell)
|
|
20
|
+
Jeśli shell ma włączone `sidenavRailBreakpoint`, opatrz tekst pozycji atrybutem `kptNavLabel`,
|
|
21
|
+
a nagłówek grupy `kptNavSection` — w zwiniętej szynie zostaje sama ikona, a etykieta jest
|
|
22
|
+
chowana technicznie (visually hidden), więc czytnik ekranu wciąż zna nazwę pozycji:
|
|
23
|
+
|
|
24
|
+
<a href="#"><kpt-icon name="list" /> <span kptNavLabel>Pulpit</span></a>
|
|
25
|
+
|
|
26
|
+
To płaskie atrybuty, nie dyrektywy — nic nie trzeba importować. Bez ikony szyna będzie pusta.
|
|
27
|
+
|
|
28
|
+
## Tokeny
|
|
29
|
+
`--kpt-sidenav-{bg,fg,border,width,rail-width}` (szerokość ustawia `kpt-app-shell`).
|