@geoit/ui 0.0.5 → 0.0.6

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.
Files changed (37) hide show
  1. package/README.md +45 -4
  2. package/ai/AGENTS.md +122 -42
  3. package/ai/README.md +29 -29
  4. package/ai/catalog.json +266 -194
  5. package/ai/components/geo-chart.md +18 -6
  6. package/ai/components/geo-dashboard.md +17 -6
  7. package/ai/components/geo-empty-state.md +5 -5
  8. package/ai/components/geo-feedback-form.md +5 -5
  9. package/ai/components/geo-forgot-password.md +8 -5
  10. package/ai/components/geo-list-page.md +8 -5
  11. package/ai/components/geo-login.md +18 -6
  12. package/ai/components/geo-map-admin-filter.md +10 -5
  13. package/ai/components/geo-map-basemap-switcher.md +9 -5
  14. package/ai/components/geo-map-help.md +5 -5
  15. package/ai/components/geo-map-layer-card.md +5 -5
  16. package/ai/components/geo-map-layer-panel.md +5 -5
  17. package/ai/components/geo-map-layers-drawer.md +5 -5
  18. package/ai/components/geo-map-legend.md +5 -5
  19. package/ai/components/geo-map-locate.md +5 -5
  20. package/ai/components/geo-map-location-chip.md +5 -5
  21. package/ai/components/geo-map-measure.md +5 -5
  22. package/ai/components/geo-map-opacity.md +5 -5
  23. package/ai/components/geo-map-parcel-popup.md +10 -5
  24. package/ai/components/geo-map-search.md +11 -5
  25. package/ai/components/geo-map-shell.md +42 -6
  26. package/ai/components/geo-map-snapshot.md +5 -5
  27. package/ai/components/geo-map-swipe.md +5 -5
  28. package/ai/components/geo-map-toolbar.md +10 -5
  29. package/ai/components/geo-map-zoom.md +5 -5
  30. package/ai/components/geo-map.md +16 -9
  31. package/ai/components/geo-overlap-result.md +5 -5
  32. package/ai/components/geo-page-header.md +5 -5
  33. package/ai/components/geo-slider.md +1 -1
  34. package/ai/components/geo-stat-card.md +5 -5
  35. package/ai/mockup.html +2 -2
  36. package/ai/recipes.md +86 -0
  37. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @geoit/ui
2
2
 
3
- GEO design system for **Angular 18** + **ng-zorro 18**. Standalone components, design tokens, and AI-ready usage docs.
3
+ GEO design system for **Angular 18** + **ng-zorro 18**. Standalone components, design tokens, and AI-ready usage docs (shipped in the package under `ai/`).
4
4
 
5
5
  ## Install
6
6
 
@@ -12,18 +12,37 @@ npm install @geoit/ui
12
12
 
13
13
  ```bash
14
14
  npm install @angular/animations@^18 @angular/common@^18 @angular/core@^18 \
15
- @angular/forms@^18 @angular/cdk@^18 @ant-design/icons-angular@^18 ng-zorro-antd@^18
15
+ @angular/forms@^18 @angular/cdk@^18 @ant-design/icons-angular@^18 ng-zorro-antd@^18 \
16
+ ol@^10 proj4@^2
16
17
  ```
17
18
 
19
+ > `ol` + `proj4` are required when you use map components (`geo-map`, `geo-map-shell`, …).
20
+
18
21
  ## Setup styles (once per app)
19
22
 
20
23
  In your global styles (e.g. `styles.scss`):
21
24
 
22
25
  ```scss
26
+ @import "node_modules/ng-zorro-antd/ng-zorro-antd.min.css";
23
27
  @import "node_modules/@geoit/ui/src/lib/styles/design-tokens.scss";
24
28
  @import "node_modules/@geoit/ui/src/lib/styles/theme.scss";
25
29
  ```
26
30
 
31
+ Providers (animations + Vietnamese i18n for date pickers):
32
+
33
+ ```ts
34
+ import { provideAnimations } from "@angular/platform-browser/animations";
35
+ import { provideNzI18n, vi_VN } from "ng-zorro-antd/i18n";
36
+ import { registerLocaleData } from "@angular/common";
37
+ import vi from "@angular/common/locales/vi";
38
+
39
+ registerLocaleData(vi);
40
+
41
+ // in appConfig.providers:
42
+ provideAnimations(),
43
+ provideNzI18n(vi_VN),
44
+ ```
45
+
27
46
  Use tokens in your CSS — do not hardcode brand colors or radius:
28
47
 
29
48
  - `var(--geo-color-primary-default)`
@@ -69,9 +88,11 @@ export class DemoComponent {
69
88
  | Select | `geo-select` | `<geo-select [options]="opts" [(ngModel)]="v" [block]="true">` |
70
89
  | Checkbox | `geo-checkbox` | `<geo-checkbox label="Đồng ý" [(checked)]="ok">` |
71
90
  | Radio | `geo-radio` | `<geo-radio [options]="opts" [(ngModel)]="v">` |
91
+ | Date / range | `geo-date-picker` / `geo-date-range-picker` | `[(ngModel)]` + `format="dd/MM/yyyy"` |
72
92
  | Form dialog | `geo-form-modal` | See Quick start |
73
93
  | Confirm delete | `geo-confirm-modal` | `[visible]` + `(confirm)` |
74
94
  | Steps in dialog | `geo-form-modal` + `geo-stepper` | See recipes |
95
+ | App shell | `geo-layout` | menu + header + content |
75
96
  | Page title | `geo-page-title` | `<geo-page-title title="Chi tiết hồ sơ">` |
76
97
  | Breadcrumb | `geo-breadcrumb` | `[items]="[{ label, link? }]"` |
77
98
  | Toast | `GeoToastService` | `this.toast.success(title, message)` |
@@ -79,6 +100,8 @@ export class DemoComponent {
79
100
  | Status pill | `geo-status-tag` | `status="success" label="Đã duyệt"` |
80
101
  | Table | `geo-table` | `[columns]` + `[data]` + paging |
81
102
  | Upload | `geo-upload` | Drag-drop multi-file |
103
+ | **Map portal** | **`geo-map-shell`** | Search + layers + legend + parcel (recommended) |
104
+ | Bare map | `geo-map` | OpenLayers host + `GeoMapController` |
82
105
  | Typography | `geo-typography` | `variant="h3" \| "body" \| …` |
83
106
 
84
107
  ### Button API (quick)
@@ -100,9 +123,25 @@ export class DemoComponent {
100
123
 
101
124
  These implement **ControlValueAccessor** — use `[(ngModel)]` or reactive forms:
102
125
 
103
- `geo-input`, `geo-textarea`, `geo-select`, `geo-radio`, `geo-date-picker`, `geo-date-range-picker`, `geo-slider`
126
+ `geo-input`, `geo-textarea`, `geo-select`, `geo-radio`, `geo-date-picker`, `geo-date-range-picker`, `geo-file-picker`
127
+
128
+ - `geo-checkbox` → **`[(checked)]`** (not CVA)
129
+ - `geo-slider` → **`[(value)]`** (`model()`)
130
+
131
+ ### Map portal (quick)
132
+
133
+ ```html
134
+ <geo-map-shell
135
+ height="640px"
136
+ [demoSearch]="false"
137
+ parcelAudience="citizen"
138
+ [layers]="layers"
139
+ (mapReady)="ctrl = $event"
140
+ (search)="onSearch($event)"
141
+ ></geo-map-shell>
142
+ ```
104
143
 
105
- `geo-checkbox` uses **`[(checked)]`** (not CVA).
144
+ See `ai/recipes.md` §13 and `ai/components/geo-map-shell.md`.
106
145
 
107
146
  ### Toast (preferred)
108
147
 
@@ -132,6 +171,7 @@ Open a component doc before using it, e.g.:
132
171
  ```text
133
172
  node_modules/@geoit/ui/ai/components/geo-button.md
134
173
  node_modules/@geoit/ui/ai/components/geo-form-modal.md
174
+ node_modules/@geoit/ui/ai/components/geo-map-shell.md
135
175
  node_modules/@geoit/ui/ai/components/geo-table.md
136
176
  ```
137
177
 
@@ -150,6 +190,7 @@ UI must use `@geoit/ui`. Before writing UI, read:
150
190
  - node_modules/@geoit/ui/ai/AGENTS.md
151
191
  - node_modules/@geoit/ui/ai/catalog.json
152
192
  - node_modules/@geoit/ui/ai/components/<selector>.md when needed
193
+ - node_modules/@geoit/ui/ai/recipes.md for screen patterns
153
194
  ```
154
195
 
155
196
  ## Design tokens
package/ai/AGENTS.md CHANGED
@@ -1,29 +1,83 @@
1
1
  # GEO UI — Agent instructions
2
2
 
3
- Instructions for AI coding agents (Cursor, Copilot, etc.) when building UI with **geo-ui**.
3
+ Instructions for **humans and AI coding agents** when building UI with **`@geoit/ui`** (installed from npm).
4
+
5
+ Package paths after install:
6
+
7
+ | Doc | Path |
8
+ |-----|------|
9
+ | This file | `node_modules/@geoit/ui/ai/AGENTS.md` |
10
+ | Index | `node_modules/@geoit/ui/ai/README.md` |
11
+ | Catalog | `node_modules/@geoit/ui/ai/catalog.json` |
12
+ | Per component | `node_modules/@geoit/ui/ai/components/<selector>.md` |
13
+ | Recipes | `node_modules/@geoit/ui/ai/recipes.md` |
4
14
 
5
15
  ## Mandatory
6
16
 
7
- 1. **Use `geo-*` components** from package `@geoit/ui` for all UI that has a match in the catalog.
8
- 2. **Do not** invent parallel wrappers or raw `nz-button` / `nz-input` / `nz-modal` when a `geo-*` equivalent exists.
17
+ 1. **Use `geo-*` components** from `@geoit/ui` for all UI that has a match in the catalog.
18
+ 2. **Do not** invent parallel wrappers or raw `nz-button` / `nz-input` / `nz-modal` / `nz-date-picker` when a `geo-*` equivalent exists.
9
19
  3. **Do not hardcode** brand colors or border-radius. Use tokens:
10
20
  - Colors: `var(--geo-color-*)` or `geoColorTokens` from `@geoit/ui`
11
21
  - Radius: `var(--geo-radius)` (default **8px**; scale: sm 6 / md 10 / lg 12 / xl 14)
12
- 4. Before implementing a component, **read the full doc** `ai/components/<selector>.md` (Inputs/Outputs/Examples/Tips) and/or `ai/catalog.json`.
22
+ 4. Before implementing a component, **read** `ai/components/<selector>.md` (Inputs/Outputs/Examples/Tips) and/or `ai/catalog.json`.
13
23
  5. Prefer **copying examples** from those docs — adapt labels/bindings only; do not invent props.
14
24
 
15
- ## Library implementation (maintainers)
25
+ ## Install (consumer app)
16
26
 
17
- When changing `projects/geo-ui/src/lib/figma`:
27
+ ```bash
28
+ npm install @geoit/ui
29
+ ```
18
30
 
19
- - Angular **18**: `input()` / `output()` / `model()`, `OnPush`, `@if`/`@for`, `inject()`
20
- - Do **not** add new `@Input` / `@Output` / `EventEmitter`
21
- - After API changes: `npm run ai:docs`
31
+ Peer dependencies (install if missing):
32
+
33
+ ```bash
34
+ npm install @angular/animations@^18 @angular/common@^18 @angular/core@^18 \
35
+ @angular/forms@^18 @angular/cdk@^18 @ant-design/icons-angular@^18 ng-zorro-antd@^18 \
36
+ ol@^10 proj4@^2
37
+ ```
38
+
39
+ > `ol` + `proj4` are required for map components (`geo-map`, `geo-map-shell`, …).
40
+
41
+ ## Styles (once per app)
42
+
43
+ In global styles (e.g. `styles.scss`):
44
+
45
+ ```scss
46
+ @import "node_modules/@geoit/ui/src/lib/styles/design-tokens.scss";
47
+ @import "node_modules/@geoit/ui/src/lib/styles/theme.scss";
48
+ ```
49
+
50
+ Also load ng-zorro CSS once (if not already):
51
+
52
+ ```scss
53
+ @import "node_modules/ng-zorro-antd/ng-zorro-antd.min.css";
54
+ ```
55
+
56
+ App providers typically need animations + ng-zorro i18n (vi):
57
+
58
+ ```ts
59
+ import { provideAnimations } from "@angular/platform-browser/animations";
60
+ import { provideNzI18n, vi_VN } from "ng-zorro-antd/i18n";
61
+ import { registerLocaleData } from "@angular/common";
62
+ import vi from "@angular/common/locales/vi";
63
+
64
+ registerLocaleData(vi);
65
+
66
+ export const appConfig = {
67
+ providers: [provideAnimations(), provideNzI18n(vi_VN), /* … */],
68
+ };
69
+ ```
22
70
 
23
71
  ## Import pattern
24
72
 
25
73
  ```ts
26
- import { GeoButtonComponent, GeoInputComponent, GeoFormModalComponent, GeoStepperComponent } from "@geoit/ui";
74
+ import {
75
+ GeoButtonComponent,
76
+ GeoInputComponent,
77
+ GeoFormModalComponent,
78
+ GeoMapShellComponent,
79
+ GeoToastService,
80
+ } from "@geoit/ui";
27
81
  ```
28
82
 
29
83
  Standalone consumers:
@@ -35,63 +89,89 @@ Standalone consumers:
35
89
  })
36
90
  ```
37
91
 
38
- ## Styles (app once)
92
+ ### Form controls & binding
39
93
 
40
- ```scss
41
- @import "node_modules/@geoit/ui/src/lib/styles/design-tokens.scss";
42
- @import "node_modules/@geoit/ui/src/lib/styles/theme.scss";
43
- ```
94
+ | Components | Binding |
95
+ |------------|---------|
96
+ | `geo-input`, `geo-textarea`, `geo-select`, `geo-radio`, `geo-date-picker`, `geo-date-range-picker`, `geo-file-picker` | **CVA** → `[(ngModel)]` or reactive forms |
97
+ | `geo-checkbox` | `[(checked)]` (not CVA) |
98
+ | `geo-slider` | `[(value)]` (`model()`) |
99
+ | Overlays (`geo-form-modal`, search panels, …) | often `[(open)]` / `[(visible)]` |
44
100
 
45
101
  ## Composition recipes
46
102
 
47
- See [`recipes.md`](./recipes.md) for:
103
+ See [`recipes.md`](./recipes.md) for copy-paste screens:
48
104
 
49
105
  - Form modal + steps
50
106
  - Page: breadcrumb + page title
51
107
  - Table + toolbar + filter
52
108
  - Toast via service
109
+ - App shell (`geo-layout`)
110
+ - Dashboard
111
+ - Auth login / forgot password
112
+ - **Map portal (`geo-map-shell`)**
53
113
 
54
114
  ## Decision cheat-sheet
55
115
 
56
- | Need | Use |
57
- | -------------------- | ------------------------------------- |
58
- | CTA / actions | `geo-button` |
59
- | Text field | `geo-input` / `geo-textarea` |
60
- | Select | `geo-select` |
61
- | Exclusive options | `geo-radio` |
62
- | Checkbox | `geo-checkbox` |
63
- | Dialog form | `geo-form-modal` |
64
- | Confirm delete | `geo-confirm-modal` |
65
- | Multi-step in dialog | `geo-form-modal` + `geo-stepper` |
66
- | Multi-step full page | `geo-step-form-layout` |
67
- | App shell (sider+header) | `geo-layout` |
68
- | Layout sidebar / header / footer | `geo-layout-sidebar` / `geo-layout-header` / `geo-layout-footer` |
69
- | Page heading | `geo-page-title` (+ `geo-breadcrumb`) or `geo-page-header` |
116
+ | Need | Use |
117
+ |------|-----|
118
+ | CTA / actions | `geo-button` |
119
+ | Text field | `geo-input` / `geo-textarea` |
120
+ | Select | `geo-select` |
121
+ | Exclusive options | `geo-radio` |
122
+ | Checkbox | `geo-checkbox` |
123
+ | Date / date range | `geo-date-picker` / `geo-date-range-picker` |
124
+ | Dialog form | `geo-form-modal` |
125
+ | Confirm delete | `geo-confirm-modal` |
126
+ | Multi-step in dialog | `geo-form-modal` + `geo-stepper` |
127
+ | Multi-step full page | `geo-step-form-layout` |
128
+ | App shell (sider+header) | `geo-layout` |
129
+ | Layout pieces | `geo-layout-sidebar` / `geo-layout-header` / `geo-layout-footer` |
130
+ | Page heading | `geo-page-title` (+ `geo-breadcrumb`) or `geo-page-header` |
70
131
  | Dashboard KPI / chart | `geo-stat-card` / `geo-chart` / `geo-dashboard` |
71
132
  | Login / forgot password | `geo-login` / `geo-forgot-password` |
72
- | Feedback form | `geo-feedback-form` |
73
- | Overlap analysis | `geo-overlap-result` |
74
- | Empty region | `geo-empty-state` |
75
- | Status pill | `geo-status-tag` |
76
- | Transient notice | `GeoToastService` / `geo-toast` |
77
- | Inline notice | `geo-alert` |
78
- | Upload drag-drop | `geo-upload` |
79
- | Compact file field | `geo-file-picker` |
80
- | Data grid | `geo-table` (+ toolbar/filter) |
81
- | Typography | `geo-typography` |
133
+ | Feedback form | `geo-feedback-form` |
134
+ | Overlap analysis | `geo-overlap-result` |
135
+ | Empty region | `geo-empty-state` |
136
+ | Status pill | `geo-status-tag` |
137
+ | Transient notice | `GeoToastService` / `geo-toast` |
138
+ | Inline notice | `geo-alert` |
139
+ | Upload drag-drop | `geo-upload` |
140
+ | Compact file field | `geo-file-picker` |
141
+ | Data grid | `geo-table` (+ toolbar/filter) |
142
+ | **Map portal (recommended)** | **`geo-map-shell`** |
143
+ | Bare OpenLayers host | `geo-map` + `GeoMapController` |
144
+ | Map chrome pieces | `geo-map-toolbar`, `geo-map-search`, `geo-map-layers-drawer`, … |
145
+ | Typography | `geo-typography` |
146
+
147
+ ## Map guidance
148
+
149
+ 1. Prefer **`geo-map-shell`** for portal tra cứu (search, ĐVHC, layers, legend, measure, basemap, parcel popup).
150
+ 2. Use **`geo-map`** alone only for embedded/minimal maps.
151
+ 3. Import constants/types from `@geoit/ui` (`GEO_MAP_DEFAULT_*`, `GeoMapLayerConfig`, …).
152
+ 4. Do **not** invent VN-2000 proj4 strings — pass via `projections` / env.
153
+ 5. Peer deps: `ol`, `proj4`.
82
154
 
83
155
  ## Anti-patterns
84
156
 
85
157
  - Hardcoded `#9A4828`, `border-radius: 8px`, etc.
86
158
  - Custom modal markup instead of `geo-form-modal`
159
+ - Raw `nz-date-picker` / `nz-select` instead of `geo-date-picker` / `geo-select`
87
160
  - Using Ant Design Steps instead of `geo-stepper`
161
+ - Assembling map chrome from scratch when `geo-map-shell` fits
88
162
  - Mixing Inter/system fonts inconsistently — use `--geo-font-family`
89
163
 
164
+ ## Library maintainers only
165
+
166
+ When changing `projects/geo-ui/src/lib/figma`:
167
+
168
+ - Angular **18**: `input()` / `output()` / `model()`, `OnPush`, `@if`/`@for`, `inject()`
169
+ - Do **not** add new `@Input` / `@Output` / `EventEmitter`
170
+ - After API changes: `npm run ai:docs` (regenerates this package’s `ai/`)
171
+
90
172
  ## Catalog
91
173
 
92
174
  - Index: [`README.md`](./README.md)
93
175
  - Machine catalog: [`catalog.json`](./catalog.json) (includes input types/defaults)
94
176
  - Per component: [`components/`](./components/) — full Inputs/Outputs tables
95
177
  - Recipes: [`recipes.md`](./recipes.md)
96
-
97
- Regenerate docs: `npm run ai:docs`
package/ai/README.md CHANGED
@@ -10,17 +10,17 @@ Agent rules: [`AGENTS.md`](./AGENTS.md) · Recipes: [`recipes.md`](./recipes.md)
10
10
  | `geo-back-button` | navigation | Back navigation control (history or custom click). | [geo-back-button.md](./components/geo-back-button.md) |
11
11
  | `geo-breadcrumb` | navigation | Breadcrumb trail; last item active (primary). | [geo-breadcrumb.md](./components/geo-breadcrumb.md) |
12
12
  | `geo-button` | actions | Primary action button with brand/semantic colors and icons. | [geo-button.md](./components/geo-button.md) |
13
- | `geo-chart` | other | GeoChartComponent | [geo-chart.md](./components/geo-chart.md) |
13
+ | `geo-chart` | data | Bar / donut chart for dashboard statistics (ApexCharts). | [geo-chart.md](./components/geo-chart.md) |
14
14
  | `geo-checkbox` | forms | Checkbox with label; bind with [(checked)] (not CVA/ngModel). | [geo-checkbox.md](./components/geo-checkbox.md) |
15
15
  | `geo-column-picker` | data | Column visibility picker for tables (optional persistence). | [geo-column-picker.md](./components/geo-column-picker.md) |
16
16
  | `geo-confirm-modal` | overlay | Confirm / danger dialog (destroy actions). | [geo-confirm-modal.md](./components/geo-confirm-modal.md) |
17
- | `geo-dashboard` | other | GeoDashboardComponent | [geo-dashboard.md](./components/geo-dashboard.md) |
17
+ | `geo-dashboard` | layout | Composed dashboard: period, KPI cards, ward/mismatch charts. | [geo-dashboard.md](./components/geo-dashboard.md) |
18
18
  | `geo-date-picker` | forms | Single date (optional time) picker. | [geo-date-picker.md](./components/geo-date-picker.md) |
19
19
  | `geo-date-range-picker` | forms | Start–end date range picker. | [geo-date-range-picker.md](./components/geo-date-range-picker.md) |
20
- | `geo-empty-state` | other | GeoEmptyStateComponent | [geo-empty-state.md](./components/geo-empty-state.md) |
21
- | `geo-feedback-form` | other | GeoFeedbackFormComponent | [geo-feedback-form.md](./components/geo-feedback-form.md) |
20
+ | `geo-empty-state` | feedback | Empty region placeholder (icon + title + optional action). | [geo-empty-state.md](./components/geo-empty-state.md) |
21
+ | `geo-feedback-form` | forms | Citizen feedback / phản ánh form with validation. | [geo-feedback-form.md](./components/geo-feedback-form.md) |
22
22
  | `geo-file-picker` | forms | Compact file input for forms (button + filename). | [geo-file-picker.md](./components/geo-file-picker.md) |
23
- | `geo-forgot-password` | other | GeoForgotPasswordComponent | [geo-forgot-password.md](./components/geo-forgot-password.md) |
23
+ | `geo-forgot-password` | forms | Forgot-password form (email + submit / back to login). | [geo-forgot-password.md](./components/geo-forgot-password.md) |
24
24
  | `geo-form-modal` | overlay | Form modal: fixed header/footer, scrollable body via ng-content. | [geo-form-modal.md](./components/geo-form-modal.md) |
25
25
  | `geo-icon` | display | Ant Design icon wrapper with GEO size/color tokens. | [geo-icon.md](./components/geo-icon.md) |
26
26
  | `geo-input` | forms | Text input with label, validation, icons; CVA/ngModel. | [geo-input.md](./components/geo-input.md) |
@@ -29,36 +29,36 @@ Agent rules: [`AGENTS.md`](./AGENTS.md) · Recipes: [`recipes.md`](./recipes.md)
29
29
  | `geo-layout-header` | layout | Soft top bar: toggle + breadcrumb + user/notification actions. | [geo-layout-header.md](./components/geo-layout-header.md) |
30
30
  | `geo-layout-header-actions` | layout | Header actions: notification/subsystem icons + user chip with popovers. | [geo-layout-header-actions.md](./components/geo-layout-header-actions.md) |
31
31
  | `geo-layout-sidebar` | layout | White sidebar: brand + recursive menu (collapse / mobile drawer). | [geo-layout-sidebar.md](./components/geo-layout-sidebar.md) |
32
- | `geo-list-page` | other | GeoListPageComponent | [geo-list-page.md](./components/geo-list-page.md) |
33
- | `geo-login` | other | GeoLoginComponent | [geo-login.md](./components/geo-login.md) |
32
+ | `geo-list-page` | layout | List page chrome: title + breadcrumb shell for admin CRUD screens. | [geo-list-page.md](./components/geo-list-page.md) |
33
+ | `geo-login` | forms | Login form (username, password, captcha, remember). | [geo-login.md](./components/geo-login.md) |
34
34
  | `geo-map` | map | OpenLayers map host with basemap, typed layers, and GeoMapController. | [geo-map.md](./components/geo-map.md) |
35
- | `geo-map-admin-filter` | other | GeoMapAdminFilterComponent | [geo-map-admin-filter.md](./components/geo-map-admin-filter.md) |
36
- | `geo-map-basemap-switcher` | other | GeoMapBasemapSwitcherComponent | [geo-map-basemap-switcher.md](./components/geo-map-basemap-switcher.md) |
37
- | `geo-map-help` | other | GeoMapHelpComponent | [geo-map-help.md](./components/geo-map-help.md) |
38
- | `geo-map-layer-card` | other | GeoMapLayerCardComponent | [geo-map-layer-card.md](./components/geo-map-layer-card.md) |
39
- | `geo-map-layer-panel` | other | GeoMapLayerPanelComponent | [geo-map-layer-panel.md](./components/geo-map-layer-panel.md) |
40
- | `geo-map-layers-drawer` | other | GeoMapLayersDrawerComponent | [geo-map-layers-drawer.md](./components/geo-map-layers-drawer.md) |
41
- | `geo-map-legend` | other | GeoMapLegendComponent | [geo-map-legend.md](./components/geo-map-legend.md) |
42
- | `geo-map-locate` | other | GeoMapLocateComponent | [geo-map-locate.md](./components/geo-map-locate.md) |
43
- | `geo-map-location-chip` | other | GeoMapLocationChipComponent | [geo-map-location-chip.md](./components/geo-map-location-chip.md) |
44
- | `geo-map-measure` | other | GeoMapMeasureComponent | [geo-map-measure.md](./components/geo-map-measure.md) |
45
- | `geo-map-opacity` | other | GeoMapOpacityComponent | [geo-map-opacity.md](./components/geo-map-opacity.md) |
46
- | `geo-map-parcel-popup` | other | GeoMapParcelPopupComponent | [geo-map-parcel-popup.md](./components/geo-map-parcel-popup.md) |
47
- | `geo-map-search` | other | GeoMapSearchComponent | [geo-map-search.md](./components/geo-map-search.md) |
48
- | `geo-map-shell` | other | GeoMapShellComponent | [geo-map-shell.md](./components/geo-map-shell.md) |
49
- | `geo-map-snapshot` | other | GeoMapSnapshotComponent | [geo-map-snapshot.md](./components/geo-map-snapshot.md) |
50
- | `geo-map-swipe` | other | GeoMapSwipeComponent | [geo-map-swipe.md](./components/geo-map-swipe.md) |
51
- | `geo-map-toolbar` | other | GeoMapToolbarComponent | [geo-map-toolbar.md](./components/geo-map-toolbar.md) |
52
- | `geo-map-zoom` | other | GeoMapZoomComponent | [geo-map-zoom.md](./components/geo-map-zoom.md) |
53
- | `geo-overlap-result` | other | GeoOverlapResultComponent | [geo-overlap-result.md](./components/geo-overlap-result.md) |
54
- | `geo-page-header` | other | GeoPageHeaderComponent | [geo-page-header.md](./components/geo-page-header.md) |
35
+ | `geo-map-admin-filter` | map | Administrative unit tree filter (ĐVHC) for map extent. | [geo-map-admin-filter.md](./components/geo-map-admin-filter.md) |
36
+ | `geo-map-basemap-switcher` | map | Basemap preview chip (e.g. street ↔ satellite). | [geo-map-basemap-switcher.md](./components/geo-map-basemap-switcher.md) |
37
+ | `geo-map-help` | map | Map help / hướng dẫn popover with sections. | [geo-map-help.md](./components/geo-map-help.md) |
38
+ | `geo-map-layer-card` | map | Basemap / layer preview card (thumbnail + title). | [geo-map-layer-card.md](./components/geo-map-layer-card.md) |
39
+ | `geo-map-layer-panel` | map | Layer list with visibility / opacity / group selection. | [geo-map-layer-panel.md](./components/geo-map-layer-panel.md) |
40
+ | `geo-map-layers-drawer` | map | Popover/drawer hosting the layer panel (“Lớp bản đồ”). | [geo-map-layers-drawer.md](./components/geo-map-layers-drawer.md) |
41
+ | `geo-map-legend` | map | Map legend popover / panel with color swatches. | [geo-map-legend.md](./components/geo-map-legend.md) |
42
+ | `geo-map-locate` | map | Geolocation button (browser GPS) for the map view. | [geo-map-locate.md](./components/geo-map-locate.md) |
43
+ | `geo-map-location-chip` | map | Location breadcrumb chip shown on the map (ward / province). | [geo-map-location-chip.md](./components/geo-map-location-chip.md) |
44
+ | `geo-map-measure` | map | Distance / area measure interaction on the map. | [geo-map-measure.md](./components/geo-map-measure.md) |
45
+ | `geo-map-opacity` | map | Layer opacity slider bound to a map layer id. | [geo-map-opacity.md](./components/geo-map-opacity.md) |
46
+ | `geo-map-parcel-popup` | map | Parcel detail popup (citizen / specialist audience). | [geo-map-parcel-popup.md](./components/geo-map-parcel-popup.md) |
47
+ | `geo-map-search` | map | Map search panel (owner / certificate / parcel / address / coordinates). | [geo-map-search.md](./components/geo-map-search.md) |
48
+ | `geo-map-shell` | map | Full map portal chrome: search, ĐVHC, layers, legend, measure, basemap, parcel popup. | [geo-map-shell.md](./components/geo-map-shell.md) |
49
+ | `geo-map-snapshot` | map | Capture current map canvas to image / download. | [geo-map-snapshot.md](./components/geo-map-snapshot.md) |
50
+ | `geo-map-swipe` | map | Swipe compare control between two map layers. | [geo-map-swipe.md](./components/geo-map-swipe.md) |
51
+ | `geo-map-toolbar` | map | Vertical map tool strip (search, pan, measure, layers, …). | [geo-map-toolbar.md](./components/geo-map-toolbar.md) |
52
+ | `geo-map-zoom` | map | Zoom +/- and optional province / home navigation control. | [geo-map-zoom.md](./components/geo-map-zoom.md) |
53
+ | `geo-overlap-result` | data | Overlap analysis result list (planning type, area, percent). | [geo-overlap-result.md](./components/geo-overlap-result.md) |
54
+ | `geo-page-header` | display | Compact page header block (title + optional actions slot). | [geo-page-header.md](./components/geo-page-header.md) |
55
55
  | `geo-page-title` | display | Page title (uppercase) with short primary accent underline; uses geo-typography. | [geo-page-title.md](./components/geo-page-title.md) |
56
56
  | `geo-pagination` | navigation | Standalone pagination control. | [geo-pagination.md](./components/geo-pagination.md) |
57
57
  | `geo-radio` | forms | Radio group (horizontal/vertical or button style). | [geo-radio.md](./components/geo-radio.md) |
58
58
  | `geo-row-actions` | data | Row action icons/menu (edit, more, custom). | [geo-row-actions.md](./components/geo-row-actions.md) |
59
59
  | `geo-select` | forms | Select / multi-select dropdown. | [geo-select.md](./components/geo-select.md) |
60
60
  | `geo-slider` | forms | Numeric range slider. | [geo-slider.md](./components/geo-slider.md) |
61
- | `geo-stat-card` | other | GeoStatCardComponent | [geo-stat-card.md](./components/geo-stat-card.md) |
61
+ | `geo-stat-card` | data | KPI stat card (label, value, optional delta / icon). | [geo-stat-card.md](./components/geo-stat-card.md) |
62
62
  | `geo-status-tag` | display | Pill status tag with optional dot (success/error/warning/info/teal/…). | [geo-status-tag.md](./components/geo-status-tag.md) |
63
63
  | `geo-step-form-layout` | layout | Full-page multi-step form: vertical stepper + content card + footer actions. | [geo-step-form-layout.md](./components/geo-step-form-layout.md) |
64
64
  | `geo-stepper` | navigation | Steps indicator (horizontal default). Active=primary, completed=success+check. | [geo-stepper.md](./components/geo-stepper.md) |
@@ -73,6 +73,6 @@ Agent rules: [`AGENTS.md`](./AGENTS.md) · Recipes: [`recipes.md`](./recipes.md)
73
73
  | `geo-typography` | display | Text with GEO type scale (h1–tiny) and semantic colors. | [geo-typography.md](./components/geo-typography.md) |
74
74
  | `geo-upload` | forms | Drag-drop upload zone with progress list. | [geo-upload.md](./components/geo-upload.md) |
75
75
 
76
- Generated: 2026-08-24T03:07:52.099Z
76
+ Generated: 2026-09-03T03:52:29.749Z
77
77
 
78
78
  Regenerate: `npm run ai:docs`