@geoit/ui 0.0.5 → 0.0.7

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 (53) 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 +328 -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 +11 -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 +6 -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 +49 -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/components/geo-tree.md +2 -0
  36. package/ai/mockup.html +2 -2
  37. package/ai/recipes.md +86 -0
  38. package/esm2022/lib/figma/geo-chart/geo-chart.component.mjs +14 -3
  39. package/esm2022/lib/figma/geo-list-page/geo-list-page.component.mjs +3 -3
  40. package/esm2022/lib/figma/geo-map/chrome/geo-map-admin-filter/geo-map-admin-filter.component.mjs +5 -3
  41. package/esm2022/lib/figma/geo-map/chrome/geo-map-legend/geo-map-legend.component.mjs +5 -3
  42. package/esm2022/lib/figma/geo-map/chrome/geo-map-shell/geo-map-shell.component.mjs +22 -3
  43. package/esm2022/lib/figma/geo-map/geo-map.constants.mjs +13 -1
  44. package/esm2022/lib/figma/geo-tree/geo-tree.component.mjs +17 -3
  45. package/fesm2022/geoit-ui.mjs +72 -13
  46. package/fesm2022/geoit-ui.mjs.map +1 -1
  47. package/lib/figma/geo-chart/geo-chart.component.d.ts +9 -0
  48. package/lib/figma/geo-map/chrome/geo-map-admin-filter/geo-map-admin-filter.component.d.ts +3 -1
  49. package/lib/figma/geo-map/chrome/geo-map-legend/geo-map-legend.component.d.ts +3 -1
  50. package/lib/figma/geo-map/chrome/geo-map-shell/geo-map-shell.component.d.ts +19 -2
  51. package/lib/figma/geo-map/geo-map.constants.d.ts +6 -0
  52. package/lib/figma/geo-tree/geo-tree.component.d.ts +5 -1
  53. package/package.json +1 -1
package/ai/catalog.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "package": "@geoit/ui",
3
3
  "import": "@geoit/ui",
4
- "version": "0.0.5",
5
- "generatedAt": "2026-08-24T03:07:52.099Z",
4
+ "version": "0.0.7",
5
+ "generatedAt": "2026-09-04T07:20:22.166Z",
6
6
  "styles": [
7
7
  "@geoit/ui/src/lib/styles/design-tokens.scss",
8
8
  "@geoit/ui/src/lib/styles/theme.scss"
@@ -339,12 +339,15 @@
339
339
  {
340
340
  "name": "GeoChartComponent",
341
341
  "selector": "geo-chart",
342
- "category": "other",
343
- "summary": "GeoChartComponent",
344
- "whenToUse": "",
345
- "doNotUseWhen": "",
346
- "howTo": "",
347
- "tips": [],
342
+ "category": "data",
343
+ "summary": "Bar / donut chart for dashboard statistics (ApexCharts).",
344
+ "whenToUse": "KPI breakdowns on dashboard pages.",
345
+ "doNotUseWhen": "Maps / spatial — use geo-map; single KPI — use geo-stat-card.",
346
+ "howTo": "Biểu đồ bar/donut cho dashboard. [data] = { label, value, color? }[]; (segmentClick) khi click lát.",
347
+ "tips": [
348
+ "Màu ưu tiên CSS var(--geo-color-*).",
349
+ "KPI đơn → geo-stat-card; ghép sẵn → geo-dashboard."
350
+ ],
348
351
  "binding": "none",
349
352
  "cva": false,
350
353
  "path": "projects/geo-ui/src/lib/figma/geo-chart/geo-chart.component.ts",
@@ -419,12 +422,17 @@
419
422
  ],
420
423
  "examples": [
421
424
  {
422
- "title": "Example",
423
- "lang": "html"
425
+ "title": "Bar",
426
+ "lang": "html",
427
+ "code": "<geo-chart type=\"bar\" title=\"Theo xã\" [data]=\"wardData\" [height]=\"280\"></geo-chart>"
424
428
  }
425
429
  ],
426
- "example": "<geo-chart></geo-chart>",
427
- "related": []
430
+ "example": "<geo-chart type=\"bar\" title=\"Theo xã\" [data]=\"wardData\" [height]=\"280\"></geo-chart>",
431
+ "related": [
432
+ "geo-stat-card",
433
+ "geo-dashboard",
434
+ "geo-empty-state"
435
+ ]
428
436
  },
429
437
  {
430
438
  "name": "GeoCheckboxComponent",
@@ -675,12 +683,14 @@
675
683
  {
676
684
  "name": "GeoDashboardComponent",
677
685
  "selector": "geo-dashboard",
678
- "category": "other",
679
- "summary": "GeoDashboardComponent",
680
- "whenToUse": "",
681
- "doNotUseWhen": "",
682
- "howTo": "",
683
- "tips": [],
686
+ "category": "layout",
687
+ "summary": "Composed dashboard: period, KPI cards, ward/mismatch charts.",
688
+ "whenToUse": "TCQH overview pages (thống kê nhanh).",
689
+ "doNotUseWhen": "Custom layouts — compose geo-stat-card + geo-chart yourself.",
690
+ "howTo": "Dashboard ghép sẵn: stats + biểu đồ xã + lệch kỳ. [(period)] điều khiển kỳ thống kê.",
691
+ "tips": [
692
+ "Tự layout → geo-stat-card + geo-chart."
693
+ ],
684
694
  "binding": "none",
685
695
  "cva": false,
686
696
  "path": "projects/geo-ui/src/lib/figma/geo-dashboard/geo-dashboard.component.ts",
@@ -760,12 +770,17 @@
760
770
  ],
761
771
  "examples": [
762
772
  {
763
- "title": "Example",
764
- "lang": "html"
773
+ "title": "Basic",
774
+ "lang": "html",
775
+ "code": "<geo-dashboard [stats]=\"stats\" [wardData]=\"wards\" [mismatchData]=\"mismatch\" [(period)]=\"period\"></geo-dashboard>"
765
776
  }
766
777
  ],
767
- "example": "<geo-dashboard></geo-dashboard>",
768
- "related": []
778
+ "example": "<geo-dashboard [stats]=\"stats\" [wardData]=\"wards\" [mismatchData]=\"mismatch\" [(period)]=\"period\"></geo-dashboard>",
779
+ "related": [
780
+ "geo-stat-card",
781
+ "geo-chart",
782
+ "geo-page-header"
783
+ ]
769
784
  },
770
785
  {
771
786
  "name": "GeoDatePickerComponent",
@@ -1033,10 +1048,10 @@
1033
1048
  {
1034
1049
  "name": "GeoEmptyStateComponent",
1035
1050
  "selector": "geo-empty-state",
1036
- "category": "other",
1037
- "summary": "GeoEmptyStateComponent",
1038
- "whenToUse": "",
1039
- "doNotUseWhen": "",
1051
+ "category": "feedback",
1052
+ "summary": "Empty region placeholder (icon + title + optional action).",
1053
+ "whenToUse": "No data / no results areas inside pages or cards.",
1054
+ "doNotUseWhen": "Inline form validation — use field errorMessage / geo-alert.",
1040
1055
  "howTo": "",
1041
1056
  "tips": [],
1042
1057
  "binding": "none",
@@ -1079,19 +1094,20 @@
1079
1094
  "examples": [
1080
1095
  {
1081
1096
  "title": "Example",
1082
- "lang": "html"
1097
+ "lang": "html",
1098
+ "code": "<geo-empty-state title=\"Chưa có dữ liệu\" description=\"Thử đổi bộ lọc.\"></geo-empty-state>"
1083
1099
  }
1084
1100
  ],
1085
- "example": "<geo-empty-state></geo-empty-state>",
1101
+ "example": "<geo-empty-state title=\"Chưa có dữ liệu\" description=\"Thử đổi bộ lọc.\"></geo-empty-state>",
1086
1102
  "related": []
1087
1103
  },
1088
1104
  {
1089
1105
  "name": "GeoFeedbackFormComponent",
1090
1106
  "selector": "geo-feedback-form",
1091
- "category": "other",
1092
- "summary": "GeoFeedbackFormComponent",
1093
- "whenToUse": "",
1094
- "doNotUseWhen": "",
1107
+ "category": "forms",
1108
+ "summary": "Citizen feedback / phản ánh form with validation.",
1109
+ "whenToUse": "Public feedback submission pages.",
1110
+ "doNotUseWhen": "Admin feedback inbox — use geo-list-page + geo-table.",
1095
1111
  "howTo": "",
1096
1112
  "tips": [],
1097
1113
  "binding": "none",
@@ -1175,10 +1191,11 @@
1175
1191
  "examples": [
1176
1192
  {
1177
1193
  "title": "Example",
1178
- "lang": "html"
1194
+ "lang": "html",
1195
+ "code": "<geo-feedback-form (submittedFeedback)=\"send($event)\"></geo-feedback-form>"
1179
1196
  }
1180
1197
  ],
1181
- "example": "<geo-feedback-form></geo-feedback-form>",
1198
+ "example": "<geo-feedback-form (submittedFeedback)=\"send($event)\"></geo-feedback-form>",
1182
1199
  "related": []
1183
1200
  },
1184
1201
  {
@@ -1301,10 +1318,10 @@
1301
1318
  {
1302
1319
  "name": "GeoForgotPasswordComponent",
1303
1320
  "selector": "geo-forgot-password",
1304
- "category": "other",
1305
- "summary": "GeoForgotPasswordComponent",
1306
- "whenToUse": "",
1307
- "doNotUseWhen": "",
1321
+ "category": "forms",
1322
+ "summary": "Forgot-password form (email + submit / back to login).",
1323
+ "whenToUse": "Password reset entry page.",
1324
+ "doNotUseWhen": "Inside login card — navigate to a dedicated route.",
1308
1325
  "howTo": "",
1309
1326
  "tips": [],
1310
1327
  "binding": "none",
@@ -1364,10 +1381,11 @@
1364
1381
  "examples": [
1365
1382
  {
1366
1383
  "title": "Example",
1367
- "lang": "html"
1384
+ "lang": "html",
1385
+ "code": "<geo-forgot-password\n (submitEmail)=\"reset($event)\"\n (backToLogin)=\"goLogin()\"\n></geo-forgot-password>"
1368
1386
  }
1369
1387
  ],
1370
- "example": "<geo-forgot-password></geo-forgot-password>",
1388
+ "example": "<geo-forgot-password\n (submitEmail)=\"reset($event)\"\n (backToLogin)=\"goLogin()\"\n></geo-forgot-password>",
1371
1389
  "related": []
1372
1390
  },
1373
1391
  {
@@ -2282,10 +2300,10 @@
2282
2300
  {
2283
2301
  "name": "GeoListPageComponent",
2284
2302
  "selector": "geo-list-page",
2285
- "category": "other",
2286
- "summary": "GeoListPageComponent",
2287
- "whenToUse": "",
2288
- "doNotUseWhen": "",
2303
+ "category": "layout",
2304
+ "summary": "List page chrome: title + breadcrumb shell for admin CRUD screens.",
2305
+ "whenToUse": "Wrap table toolbars on admin list pages.",
2306
+ "doNotUseWhen": "Map portals — use geo-map-shell; dashboards — use geo-dashboard.",
2289
2307
  "howTo": "",
2290
2308
  "tips": [],
2291
2309
  "binding": "none",
@@ -2316,21 +2334,25 @@
2316
2334
  "examples": [
2317
2335
  {
2318
2336
  "title": "Example",
2319
- "lang": "html"
2337
+ "lang": "html",
2338
+ "code": "<geo-list-page title=\"Quản lý người dùng\" [breadcrumb]=\"crumbs\">\n <geo-table-toolbar ...></geo-table-toolbar>\n <geo-table ...></geo-table>\n</geo-list-page>"
2320
2339
  }
2321
2340
  ],
2322
- "example": "<geo-list-page></geo-list-page>",
2341
+ "example": "<geo-list-page title=\"Quản lý người dùng\" [breadcrumb]=\"crumbs\">\n <geo-table-toolbar ...></geo-table-toolbar>\n <geo-table ...></geo-table>\n</geo-list-page>",
2323
2342
  "related": []
2324
2343
  },
2325
2344
  {
2326
2345
  "name": "GeoLoginComponent",
2327
2346
  "selector": "geo-login",
2328
- "category": "other",
2329
- "summary": "GeoLoginComponent",
2330
- "whenToUse": "",
2331
- "doNotUseWhen": "",
2332
- "howTo": "",
2333
- "tips": [],
2347
+ "category": "forms",
2348
+ "summary": "Login form (username, password, captcha, remember).",
2349
+ "whenToUse": "Specialist / admin login page.",
2350
+ "doNotUseWhen": "SSO-only flows without local credentials.",
2351
+ "howTo": "Form đăng nhập: username/password/captcha/remember. (submitLogin) payload; (forgotPassword) điều hướng quên mật khẩu.",
2352
+ "tips": [
2353
+ "Cần FormsModule + styles tokens.",
2354
+ "Ghép geo-forgot-password trên route riêng."
2355
+ ],
2334
2356
  "binding": "none",
2335
2357
  "cva": false,
2336
2358
  "path": "projects/geo-ui/src/lib/figma/geo-login/geo-login.component.ts",
@@ -2411,12 +2433,17 @@
2411
2433
  ],
2412
2434
  "examples": [
2413
2435
  {
2414
- "title": "Example",
2415
- "lang": "html"
2436
+ "title": "Basic",
2437
+ "lang": "html",
2438
+ "code": "<geo-login (submitLogin)=\"login($event)\" (forgotPassword)=\"goForgot()\"></geo-login>"
2416
2439
  }
2417
2440
  ],
2418
- "example": "<geo-login></geo-login>",
2419
- "related": []
2441
+ "example": "<geo-login (submitLogin)=\"login($event)\" (forgotPassword)=\"goForgot()\"></geo-login>",
2442
+ "related": [
2443
+ "geo-forgot-password",
2444
+ "geo-input",
2445
+ "geo-button"
2446
+ ]
2420
2447
  },
2421
2448
  {
2422
2449
  "name": "GeoMapComponent",
@@ -2424,9 +2451,13 @@
2424
2451
  "category": "map",
2425
2452
  "summary": "OpenLayers map host with basemap, typed layers, and GeoMapController.",
2426
2453
  "whenToUse": "Any map viewport (portal quy hoạch, tra cứu thửa). Peers: ol, proj4.",
2427
- "doNotUseWhen": "Non-map charting — use dashboard libs.",
2428
- "howTo": "",
2429
- "tips": [],
2454
+ "doNotUseWhen": "Full portal chrome — prefer geo-map-shell; non-map charts — use geo-chart.",
2455
+ "howTo": "Host OpenLayers thuần. (mapReady) nhận GeoMapController để zoom/fit/addLayer. Layers typed (osm/xyz/wms/wmts/geojson). Projections tùy chỉnh qua [projections] — không invent VN-2000.",
2456
+ "tips": [
2457
+ "Portal đầy đủ → geo-map-shell.",
2458
+ "showZoomControl=false khi dùng geo-map-zoom riêng.",
2459
+ "Peers: ol, proj4."
2460
+ ],
2430
2461
  "binding": "none",
2431
2462
  "cva": false,
2432
2463
  "path": "projects/geo-ui/src/lib/figma/geo-map/geo-map.component.ts",
@@ -2535,21 +2566,25 @@
2535
2566
  ],
2536
2567
  "examples": [
2537
2568
  {
2538
- "title": "Example",
2569
+ "title": "Basic",
2539
2570
  "lang": "html",
2540
- "code": "<geo-map\n [center]=\"center\"\n [zoom]=\"12\"\n [layers]=\"layers\"\n height=\"480px\"\n (mapReady)=\"ctrl = $event\"\n></geo-map>"
2571
+ "code": "<geo-map height=\"480px\" basemap=\"osm\" [center]=\"[108.45, 11.94]\" [zoom]=\"12\" (mapReady)=\"ctrl = $event\"></geo-map>"
2541
2572
  }
2542
2573
  ],
2543
- "example": "<geo-map\n [center]=\"center\"\n [zoom]=\"12\"\n [layers]=\"layers\"\n height=\"480px\"\n (mapReady)=\"ctrl = $event\"\n></geo-map>",
2544
- "related": []
2574
+ "example": "<geo-map height=\"480px\" basemap=\"osm\" [center]=\"[108.45, 11.94]\" [zoom]=\"12\" (mapReady)=\"ctrl = $event\"></geo-map>",
2575
+ "related": [
2576
+ "geo-map-shell",
2577
+ "geo-map-zoom",
2578
+ "geo-map-toolbar"
2579
+ ]
2545
2580
  },
2546
2581
  {
2547
2582
  "name": "GeoMapAdminFilterComponent",
2548
2583
  "selector": "geo-map-admin-filter",
2549
- "category": "other",
2550
- "summary": "GeoMapAdminFilterComponent",
2551
- "whenToUse": "",
2552
- "doNotUseWhen": "",
2584
+ "category": "map",
2585
+ "summary": "Administrative unit tree filter (ĐVHC) for map extent.",
2586
+ "whenToUse": "Filter map by tỉnh/huyện/xã; included in geo-map-shell.",
2587
+ "doNotUseWhen": "Generic trees outside map — use geo-tree.",
2553
2588
  "howTo": "",
2554
2589
  "tips": [],
2555
2590
  "binding": "none",
@@ -2575,6 +2610,12 @@
2575
2610
  "default": "[]",
2576
2611
  "note": ""
2577
2612
  },
2613
+ {
2614
+ "name": "selectionMode",
2615
+ "type": "'single' | 'multi'",
2616
+ "default": "'multi'",
2617
+ "note": "`single` — chọn đúng 1 xã/phường (BR-06-03); `multi` — checkbox nhiều cấp (mặc định)."
2618
+ },
2578
2619
  {
2579
2620
  "name": "checkedKeys",
2580
2621
  "type": "Array<string | number>",
@@ -2618,19 +2659,20 @@
2618
2659
  "examples": [
2619
2660
  {
2620
2661
  "title": "Example",
2621
- "lang": "html"
2662
+ "lang": "html",
2663
+ "code": "<geo-map-admin-filter\n [(open)]=\"adminOpen\"\n [nodes]=\"adminNodes\"\n [(checkedKeys)]=\"checked\"\n (apply)=\"applyAdmin($event)\"\n></geo-map-admin-filter>"
2622
2664
  }
2623
2665
  ],
2624
- "example": "<geo-map-admin-filter></geo-map-admin-filter>",
2666
+ "example": "<geo-map-admin-filter\n [(open)]=\"adminOpen\"\n [nodes]=\"adminNodes\"\n [(checkedKeys)]=\"checked\"\n (apply)=\"applyAdmin($event)\"\n></geo-map-admin-filter>",
2625
2667
  "related": []
2626
2668
  },
2627
2669
  {
2628
2670
  "name": "GeoMapBasemapSwitcherComponent",
2629
2671
  "selector": "geo-map-basemap-switcher",
2630
- "category": "other",
2631
- "summary": "GeoMapBasemapSwitcherComponent",
2632
- "whenToUse": "",
2633
- "doNotUseWhen": "",
2672
+ "category": "map",
2673
+ "summary": "Basemap preview chip (e.g. street ↔ satellite).",
2674
+ "whenToUse": "Bottom-right basemap toggle; included in geo-map-shell.",
2675
+ "doNotUseWhen": "Programmatic basemap only — set geo-map [basemap] / shell basemapId.",
2634
2676
  "howTo": "",
2635
2677
  "tips": [],
2636
2678
  "binding": "none",
@@ -2673,19 +2715,20 @@
2673
2715
  "examples": [
2674
2716
  {
2675
2717
  "title": "Example",
2676
- "lang": "html"
2718
+ "lang": "html",
2719
+ "code": "<geo-map-basemap-switcher\n [options]=\"basemapOptions\"\n [(selectedId)]=\"basemapId\"\n (basemapChange)=\"onBasemap($event)\"\n></geo-map-basemap-switcher>"
2677
2720
  }
2678
2721
  ],
2679
- "example": "<geo-map-basemap-switcher></geo-map-basemap-switcher>",
2722
+ "example": "<geo-map-basemap-switcher\n [options]=\"basemapOptions\"\n [(selectedId)]=\"basemapId\"\n (basemapChange)=\"onBasemap($event)\"\n></geo-map-basemap-switcher>",
2680
2723
  "related": []
2681
2724
  },
2682
2725
  {
2683
2726
  "name": "GeoMapHelpComponent",
2684
2727
  "selector": "geo-map-help",
2685
- "category": "other",
2686
- "summary": "GeoMapHelpComponent",
2687
- "whenToUse": "",
2688
- "doNotUseWhen": "",
2728
+ "category": "map",
2729
+ "summary": "Map help / hướng dẫn popover with sections.",
2730
+ "whenToUse": "Help affordance on map chrome.",
2731
+ "doNotUseWhen": "App-wide help pages — use normal content pages.",
2689
2732
  "howTo": "",
2690
2733
  "tips": [],
2691
2734
  "binding": "none",
@@ -2716,19 +2759,20 @@
2716
2759
  "examples": [
2717
2760
  {
2718
2761
  "title": "Example",
2719
- "lang": "html"
2762
+ "lang": "html",
2763
+ "code": "<geo-map-help [(open)]=\"helpOpen\" [sections]=\"helpSections\"></geo-map-help>"
2720
2764
  }
2721
2765
  ],
2722
- "example": "<geo-map-help></geo-map-help>",
2766
+ "example": "<geo-map-help [(open)]=\"helpOpen\" [sections]=\"helpSections\"></geo-map-help>",
2723
2767
  "related": []
2724
2768
  },
2725
2769
  {
2726
2770
  "name": "GeoMapLayerCardComponent",
2727
2771
  "selector": "geo-map-layer-card",
2728
- "category": "other",
2729
- "summary": "GeoMapLayerCardComponent",
2730
- "whenToUse": "",
2731
- "doNotUseWhen": "",
2772
+ "category": "map",
2773
+ "summary": "Basemap / layer preview card (thumbnail + title).",
2774
+ "whenToUse": "Layer pickers and basemap grids.",
2775
+ "doNotUseWhen": "Full layer management — use geo-map-layer-panel.",
2732
2776
  "howTo": "",
2733
2777
  "tips": [],
2734
2778
  "binding": "none",
@@ -2759,19 +2803,20 @@
2759
2803
  "examples": [
2760
2804
  {
2761
2805
  "title": "Example",
2762
- "lang": "html"
2806
+ "lang": "html",
2807
+ "code": "<geo-map-layer-card title=\"Đường phố\" [previewUrl]=\"url\" (clicked)=\"select()\"></geo-map-layer-card>"
2763
2808
  }
2764
2809
  ],
2765
- "example": "<geo-map-layer-card></geo-map-layer-card>",
2810
+ "example": "<geo-map-layer-card title=\"Đường phố\" [previewUrl]=\"url\" (clicked)=\"select()\"></geo-map-layer-card>",
2766
2811
  "related": []
2767
2812
  },
2768
2813
  {
2769
2814
  "name": "GeoMapLayerPanelComponent",
2770
2815
  "selector": "geo-map-layer-panel",
2771
- "category": "other",
2772
- "summary": "GeoMapLayerPanelComponent",
2773
- "whenToUse": "",
2774
- "doNotUseWhen": "",
2816
+ "category": "map",
2817
+ "summary": "Layer list with visibility / opacity / group selection.",
2818
+ "whenToUse": "Standalone layer manager or inside geo-map-layers-drawer.",
2819
+ "doNotUseWhen": "Single opacity control — use geo-map-opacity.",
2775
2820
  "howTo": "",
2776
2821
  "tips": [],
2777
2822
  "binding": "none",
@@ -2814,19 +2859,20 @@
2814
2859
  "examples": [
2815
2860
  {
2816
2861
  "title": "Example",
2817
- "lang": "html"
2862
+ "lang": "html",
2863
+ "code": "<geo-map-layer-panel [layers]=\"layers\" [controller]=\"ctrl\" [embedded]=\"true\"></geo-map-layer-panel>"
2818
2864
  }
2819
2865
  ],
2820
- "example": "<geo-map-layer-panel></geo-map-layer-panel>",
2866
+ "example": "<geo-map-layer-panel [layers]=\"layers\" [controller]=\"ctrl\" [embedded]=\"true\"></geo-map-layer-panel>",
2821
2867
  "related": []
2822
2868
  },
2823
2869
  {
2824
2870
  "name": "GeoMapLayersDrawerComponent",
2825
2871
  "selector": "geo-map-layers-drawer",
2826
- "category": "other",
2827
- "summary": "GeoMapLayersDrawerComponent",
2828
- "whenToUse": "",
2829
- "doNotUseWhen": "",
2872
+ "category": "map",
2873
+ "summary": "Popover/drawer hosting the layer panel (“Lớp bản đồ”).",
2874
+ "whenToUse": "Portal layer UI; included in geo-map-shell.",
2875
+ "doNotUseWhen": "Always-visible side panel — embed geo-map-layer-panel directly.",
2830
2876
  "howTo": "",
2831
2877
  "tips": [],
2832
2878
  "binding": "none",
@@ -2887,19 +2933,20 @@
2887
2933
  "examples": [
2888
2934
  {
2889
2935
  "title": "Example",
2890
- "lang": "html"
2936
+ "lang": "html",
2937
+ "code": "<geo-map-layers-drawer [(open)]=\"layersOpen\" [layers]=\"layers\" [controller]=\"ctrl\"></geo-map-layers-drawer>"
2891
2938
  }
2892
2939
  ],
2893
- "example": "<geo-map-layers-drawer></geo-map-layers-drawer>",
2940
+ "example": "<geo-map-layers-drawer [(open)]=\"layersOpen\" [layers]=\"layers\" [controller]=\"ctrl\"></geo-map-layers-drawer>",
2894
2941
  "related": []
2895
2942
  },
2896
2943
  {
2897
2944
  "name": "GeoMapLegendComponent",
2898
2945
  "selector": "geo-map-legend",
2899
- "category": "other",
2900
- "summary": "GeoMapLegendComponent",
2901
- "whenToUse": "",
2902
- "doNotUseWhen": "",
2946
+ "category": "map",
2947
+ "summary": "Map legend popover / panel with color swatches.",
2948
+ "whenToUse": "Show thematic legend; geo-map-shell includes this.",
2949
+ "doNotUseWhen": "Non-map legends in dashboards — use static markup / geo-status-tag.",
2903
2950
  "howTo": "",
2904
2951
  "tips": [],
2905
2952
  "binding": "none",
@@ -2919,6 +2966,12 @@
2919
2966
  "default": "[]",
2920
2967
  "note": ""
2921
2968
  },
2969
+ {
2970
+ "name": "catalogMissing",
2971
+ "type": "boolean",
2972
+ "default": "false",
2973
+ "note": "True khi danh mục chú giải không tải được (`ERR_MAP_LEGEND_CATALOG_MISSING`)."
2974
+ },
2922
2975
  {
2923
2976
  "name": "open",
2924
2977
  "type": "boolean",
@@ -2936,19 +2989,20 @@
2936
2989
  "examples": [
2937
2990
  {
2938
2991
  "title": "Example",
2939
- "lang": "html"
2992
+ "lang": "html",
2993
+ "code": "<geo-map-legend [(open)]=\"legendOpen\" [items]=\"legendItems\"></geo-map-legend>"
2940
2994
  }
2941
2995
  ],
2942
- "example": "<geo-map-legend></geo-map-legend>",
2996
+ "example": "<geo-map-legend [(open)]=\"legendOpen\" [items]=\"legendItems\"></geo-map-legend>",
2943
2997
  "related": []
2944
2998
  },
2945
2999
  {
2946
3000
  "name": "GeoMapLocateComponent",
2947
3001
  "selector": "geo-map-locate",
2948
- "category": "other",
2949
- "summary": "GeoMapLocateComponent",
2950
- "whenToUse": "",
2951
- "doNotUseWhen": "",
3002
+ "category": "map",
3003
+ "summary": "Geolocation button (browser GPS) for the map view.",
3004
+ "whenToUse": "Locate-me control on custom map chrome.",
3005
+ "doNotUseWhen": "Inside geo-map-shell (already wired) unless building a custom shell.",
2952
3006
  "howTo": "",
2953
3007
  "tips": [],
2954
3008
  "binding": "none",
@@ -2989,19 +3043,20 @@
2989
3043
  "examples": [
2990
3044
  {
2991
3045
  "title": "Example",
2992
- "lang": "html"
3046
+ "lang": "html",
3047
+ "code": "<geo-map-locate [controller]=\"ctrl\" (denied)=\"onDenied()\"></geo-map-locate>"
2993
3048
  }
2994
3049
  ],
2995
- "example": "<geo-map-locate></geo-map-locate>",
3050
+ "example": "<geo-map-locate [controller]=\"ctrl\" (denied)=\"onDenied()\"></geo-map-locate>",
2996
3051
  "related": []
2997
3052
  },
2998
3053
  {
2999
3054
  "name": "GeoMapLocationChipComponent",
3000
3055
  "selector": "geo-map-location-chip",
3001
- "category": "other",
3002
- "summary": "GeoMapLocationChipComponent",
3003
- "whenToUse": "",
3004
- "doNotUseWhen": "",
3056
+ "category": "map",
3057
+ "summary": "Location breadcrumb chip shown on the map (ward / province).",
3058
+ "whenToUse": "Show current admin context on map chrome.",
3059
+ "doNotUseWhen": "Page breadcrumb — use geo-breadcrumb.",
3005
3060
  "howTo": "",
3006
3061
  "tips": [],
3007
3062
  "binding": "none",
@@ -3026,19 +3081,20 @@
3026
3081
  "examples": [
3027
3082
  {
3028
3083
  "title": "Example",
3029
- "lang": "html"
3084
+ "lang": "html",
3085
+ "code": "<geo-map-location-chip label=\"Phường 1 — TP Đà Lạt, Lâm Đồng\"></geo-map-location-chip>"
3030
3086
  }
3031
3087
  ],
3032
- "example": "<geo-map-location-chip></geo-map-location-chip>",
3088
+ "example": "<geo-map-location-chip label=\"Phường 1 — TP Đà Lạt, Lâm Đồng\"></geo-map-location-chip>",
3033
3089
  "related": []
3034
3090
  },
3035
3091
  {
3036
3092
  "name": "GeoMapMeasureComponent",
3037
3093
  "selector": "geo-map-measure",
3038
- "category": "other",
3039
- "summary": "GeoMapMeasureComponent",
3040
- "whenToUse": "",
3041
- "doNotUseWhen": "",
3094
+ "category": "map",
3095
+ "summary": "Distance / area measure interaction on the map.",
3096
+ "whenToUse": "Measure tool mode; usually driven by toolbar via geo-map-shell.",
3097
+ "doNotUseWhen": "Static length labels without interaction.",
3042
3098
  "howTo": "",
3043
3099
  "tips": [],
3044
3100
  "binding": "none",
@@ -3075,19 +3131,20 @@
3075
3131
  "examples": [
3076
3132
  {
3077
3133
  "title": "Example",
3078
- "lang": "html"
3134
+ "lang": "html",
3135
+ "code": "<geo-map-measure [controller]=\"ctrl\" [(mode)]=\"measureMode\"></geo-map-measure>"
3079
3136
  }
3080
3137
  ],
3081
- "example": "<geo-map-measure></geo-map-measure>",
3138
+ "example": "<geo-map-measure [controller]=\"ctrl\" [(mode)]=\"measureMode\"></geo-map-measure>",
3082
3139
  "related": []
3083
3140
  },
3084
3141
  {
3085
3142
  "name": "GeoMapOpacityComponent",
3086
3143
  "selector": "geo-map-opacity",
3087
- "category": "other",
3088
- "summary": "GeoMapOpacityComponent",
3089
- "whenToUse": "",
3090
- "doNotUseWhen": "",
3144
+ "category": "map",
3145
+ "summary": "Layer opacity slider bound to a map layer id.",
3146
+ "whenToUse": "Adjust overlay transparency in custom layer UI.",
3147
+ "doNotUseWhen": "Full layer list — use geo-map-layer-panel / layers drawer.",
3091
3148
  "howTo": "",
3092
3149
  "tips": [],
3093
3150
  "binding": "none",
@@ -3136,19 +3193,20 @@
3136
3193
  "examples": [
3137
3194
  {
3138
3195
  "title": "Example",
3139
- "lang": "html"
3196
+ "lang": "html",
3197
+ "code": "<geo-map-opacity [controller]=\"ctrl\" layerId=\"demo-qhsdd-2020\" [(opacity)]=\"opacity\"></geo-map-opacity>"
3140
3198
  }
3141
3199
  ],
3142
- "example": "<geo-map-opacity></geo-map-opacity>",
3200
+ "example": "<geo-map-opacity [controller]=\"ctrl\" layerId=\"demo-qhsdd-2020\" [(opacity)]=\"opacity\"></geo-map-opacity>",
3143
3201
  "related": []
3144
3202
  },
3145
3203
  {
3146
3204
  "name": "GeoMapParcelPopupComponent",
3147
3205
  "selector": "geo-map-parcel-popup",
3148
- "category": "other",
3149
- "summary": "GeoMapParcelPopupComponent",
3150
- "whenToUse": "",
3151
- "doNotUseWhen": "",
3206
+ "category": "map",
3207
+ "summary": "Parcel detail popup (citizen / specialist audience).",
3208
+ "whenToUse": "Show thửa detail after search or map click.",
3209
+ "doNotUseWhen": "Full detail page — navigate to a route instead.",
3152
3210
  "howTo": "",
3153
3211
  "tips": [],
3154
3212
  "binding": "none",
@@ -3212,19 +3270,20 @@
3212
3270
  "examples": [
3213
3271
  {
3214
3272
  "title": "Example",
3215
- "lang": "html"
3273
+ "lang": "html",
3274
+ "code": "<geo-map-parcel-popup\n [(open)]=\"parcelOpen\"\n [parcel]=\"selected\"\n audience=\"citizen\"\n (exportClick)=\"exportPdf($event)\"\n></geo-map-parcel-popup>"
3216
3275
  }
3217
3276
  ],
3218
- "example": "<geo-map-parcel-popup></geo-map-parcel-popup>",
3277
+ "example": "<geo-map-parcel-popup\n [(open)]=\"parcelOpen\"\n [parcel]=\"selected\"\n audience=\"citizen\"\n (exportClick)=\"exportPdf($event)\"\n></geo-map-parcel-popup>",
3219
3278
  "related": []
3220
3279
  },
3221
3280
  {
3222
3281
  "name": "GeoMapSearchComponent",
3223
3282
  "selector": "geo-map-search",
3224
- "category": "other",
3225
- "summary": "GeoMapSearchComponent",
3226
- "whenToUse": "",
3227
- "doNotUseWhen": "",
3283
+ "category": "map",
3284
+ "summary": "Map search panel (owner / certificate / parcel / address / coordinates).",
3285
+ "whenToUse": "Tra cứu thửa on portal; prefer via geo-map-shell.",
3286
+ "doNotUseWhen": "Global app search unrelated to map.",
3228
3287
  "howTo": "",
3229
3288
  "tips": [],
3230
3289
  "binding": "none",
@@ -3312,21 +3371,28 @@
3312
3371
  "examples": [
3313
3372
  {
3314
3373
  "title": "Example",
3315
- "lang": "html"
3374
+ "lang": "html",
3375
+ "code": "<geo-map-search\n [(open)]=\"searchOpen\"\n mode=\"parcel\"\n [results]=\"results\"\n (search)=\"runSearch($event)\"\n (resultSelect)=\"onSelect($event)\"\n></geo-map-search>"
3316
3376
  }
3317
3377
  ],
3318
- "example": "<geo-map-search></geo-map-search>",
3378
+ "example": "<geo-map-search\n [(open)]=\"searchOpen\"\n mode=\"parcel\"\n [results]=\"results\"\n (search)=\"runSearch($event)\"\n (resultSelect)=\"onSelect($event)\"\n></geo-map-search>",
3319
3379
  "related": []
3320
3380
  },
3321
3381
  {
3322
3382
  "name": "GeoMapShellComponent",
3323
3383
  "selector": "geo-map-shell",
3324
- "category": "other",
3325
- "summary": "GeoMapShellComponent",
3326
- "whenToUse": "",
3327
- "doNotUseWhen": "",
3328
- "howTo": "",
3329
- "tips": [],
3384
+ "category": "map",
3385
+ "summary": "Full map portal chrome: search, ĐVHC, layers, legend, measure, basemap, parcel popup.",
3386
+ "whenToUse": "Public / specialist map portal pages (tra cứu quy hoạch). Prefer this over composing chrome by hand.",
3387
+ "doNotUseWhen": "Bare map embed without UI chrome — use geo-map only.",
3388
+ "howTo": "Shell portal tra cứu: gắn height + layers API; tắt demoSearch trên production. Lắng nghe (search)/(resultSelect)/(parcelExport). Models [(searchOpen)], [(layersOpen)], … để điều khiển panel từ ngoài.",
3389
+ "tips": [
3390
+ "Ưu tiên geo-map-shell thay vì tự ghép chrome.",
3391
+ "Peers bắt buộc: ol, proj4.",
3392
+ "demoSearch=true chỉ cho Storybook/demo — production phải false + API thật.",
3393
+ "parcelAudience: citizen | specialist.",
3394
+ "Đọc geo-map.md cho layer types / projections."
3395
+ ],
3330
3396
  "binding": "none",
3331
3397
  "cva": false,
3332
3398
  "path": "projects/geo-ui/src/lib/figma/geo-map/chrome/geo-map-shell/geo-map-shell.component.ts",
@@ -3398,12 +3464,30 @@
3398
3464
  "default": "GEO_MAP_DEMO_ADMIN_NODES",
3399
3465
  "note": ""
3400
3466
  },
3467
+ {
3468
+ "name": "adminSelectionMode",
3469
+ "type": "'single' | 'multi'",
3470
+ "default": "'multi'",
3471
+ "note": "`single` — chọn đúng 1 xã/phường (BR-06-03); `multi` — checkbox nhiều cấp (mặc định)."
3472
+ },
3401
3473
  {
3402
3474
  "name": "locationLabel",
3403
3475
  "type": "string",
3404
3476
  "default": "'Phường 1 — TP Đà Lạt, Lâm Đồng'",
3405
3477
  "note": ""
3406
3478
  },
3479
+ {
3480
+ "name": "measureDisclaimer",
3481
+ "type": "string | null",
3482
+ "default": "'Giá trị tham khảo trên bản đồ, không có giá trị pháp lý. Diện tích pháp lý của thửa đất lấy theo hồ sơ địa chính.'",
3483
+ "note": "Ghi chú pháp lý hiển thị khi đang đo (BR-10-03). `null` ẩn ghi chú — mặc định giữ nguyên câu chữ đã dùng ở `qh-map-shell`."
3484
+ },
3485
+ {
3486
+ "name": "legendCatalogMissing",
3487
+ "type": "boolean",
3488
+ "default": "false",
3489
+ "note": "True khi danh mục chú giải không tải được (`ERR_MAP_LEGEND_CATALOG_MISSING`)."
3490
+ },
3407
3491
  {
3408
3492
  "name": "parcelAudience",
3409
3493
  "type": "GeoMapParcelAudience",
@@ -3530,11 +3614,21 @@
3530
3614
  "type": "OutputEmitterRef<GeoMapClickEvent>",
3531
3615
  "note": ""
3532
3616
  },
3617
+ {
3618
+ "name": "located",
3619
+ "type": "OutputEmitterRef<[number, number]>",
3620
+ "note": ""
3621
+ },
3533
3622
  {
3534
3623
  "name": "locateDenied",
3535
3624
  "type": "OutputEmitterRef<void>",
3536
3625
  "note": ""
3537
3626
  },
3627
+ {
3628
+ "name": "locateError",
3629
+ "type": "OutputEmitterRef<{ reason: GeoMapLocateErrorReason; message?: string }>",
3630
+ "note": ""
3631
+ },
3538
3632
  {
3539
3633
  "name": "actionClick",
3540
3634
  "type": "OutputEmitterRef<GeoMapToolbarAction>",
@@ -3564,24 +3658,45 @@
3564
3658
  "name": "adminApply",
3565
3659
  "type": "OutputEmitterRef<Array<string | number>>",
3566
3660
  "note": ""
3661
+ },
3662
+ {
3663
+ "name": "snapshotCaptured",
3664
+ "type": "OutputEmitterRef<void>",
3665
+ "note": ""
3666
+ },
3667
+ {
3668
+ "name": "snapshotError",
3669
+ "type": "OutputEmitterRef<unknown>",
3670
+ "note": ""
3567
3671
  }
3568
3672
  ],
3569
3673
  "examples": [
3570
3674
  {
3571
- "title": "Example",
3572
- "lang": "html"
3675
+ "title": "Basic portal",
3676
+ "lang": "html",
3677
+ "code": "<geo-map-shell\n height=\"640px\"\n [demoSearch]=\"false\"\n parcelAudience=\"citizen\"\n [layers]=\"layers\"\n (mapReady)=\"ctrl = $event\"\n (search)=\"onSearch($event)\"\n></geo-map-shell>"
3678
+ },
3679
+ {
3680
+ "title": "Open search panel",
3681
+ "lang": "html",
3682
+ "code": "<geo-map-shell\n height=\"640px\"\n [demoSearch]=\"false\"\n [(searchOpen)]=\"searchOpen\"\n [(searchResults)]=\"results\"\n (search)=\"runQuery($event)\"\n (resultSelect)=\"onResult($event)\"\n></geo-map-shell>"
3573
3683
  }
3574
3684
  ],
3575
- "example": "<geo-map-shell></geo-map-shell>",
3576
- "related": []
3685
+ "example": "<geo-map-shell\n height=\"640px\"\n [demoSearch]=\"false\"\n parcelAudience=\"citizen\"\n [layers]=\"layers\"\n (mapReady)=\"ctrl = $event\"\n (search)=\"onSearch($event)\"\n></geo-map-shell>",
3686
+ "related": [
3687
+ "geo-map",
3688
+ "geo-map-search",
3689
+ "geo-map-toolbar",
3690
+ "geo-map-layers-drawer"
3691
+ ]
3577
3692
  },
3578
3693
  {
3579
3694
  "name": "GeoMapSnapshotComponent",
3580
3695
  "selector": "geo-map-snapshot",
3581
- "category": "other",
3582
- "summary": "GeoMapSnapshotComponent",
3583
- "whenToUse": "",
3584
- "doNotUseWhen": "",
3696
+ "category": "map",
3697
+ "summary": "Capture current map canvas to image / download.",
3698
+ "whenToUse": "Export screenshot control on map chrome.",
3699
+ "doNotUseWhen": "Server-side tile export pipelines.",
3585
3700
  "howTo": "",
3586
3701
  "tips": [],
3587
3702
  "binding": "none",
@@ -3623,19 +3738,20 @@
3623
3738
  "examples": [
3624
3739
  {
3625
3740
  "title": "Example",
3626
- "lang": "html"
3741
+ "lang": "html",
3742
+ "code": "<geo-map-snapshot [controller]=\"ctrl\" (captured)=\"onShot($event)\"></geo-map-snapshot>"
3627
3743
  }
3628
3744
  ],
3629
- "example": "<geo-map-snapshot></geo-map-snapshot>",
3745
+ "example": "<geo-map-snapshot [controller]=\"ctrl\" (captured)=\"onShot($event)\"></geo-map-snapshot>",
3630
3746
  "related": []
3631
3747
  },
3632
3748
  {
3633
3749
  "name": "GeoMapSwipeComponent",
3634
3750
  "selector": "geo-map-swipe",
3635
- "category": "other",
3636
- "summary": "GeoMapSwipeComponent",
3637
- "whenToUse": "",
3638
- "doNotUseWhen": "",
3751
+ "category": "map",
3752
+ "summary": "Swipe compare control between two map layers.",
3753
+ "whenToUse": "Before/after planning vs current-use comparison.",
3754
+ "doNotUseWhen": "Simple opacity blend — use geo-map-opacity.",
3639
3755
  "howTo": "",
3640
3756
  "tips": [],
3641
3757
  "binding": "none",
@@ -3672,19 +3788,20 @@
3672
3788
  "examples": [
3673
3789
  {
3674
3790
  "title": "Example",
3675
- "lang": "html"
3791
+ "lang": "html",
3792
+ "code": "<geo-map-swipe [controller]=\"ctrl\" [(active)]=\"swipeOn\" layerId=\"demo-qhsdd-2020\"></geo-map-swipe>"
3676
3793
  }
3677
3794
  ],
3678
- "example": "<geo-map-swipe></geo-map-swipe>",
3795
+ "example": "<geo-map-swipe [controller]=\"ctrl\" [(active)]=\"swipeOn\" layerId=\"demo-qhsdd-2020\"></geo-map-swipe>",
3679
3796
  "related": []
3680
3797
  },
3681
3798
  {
3682
3799
  "name": "GeoMapToolbarComponent",
3683
3800
  "selector": "geo-map-toolbar",
3684
- "category": "other",
3685
- "summary": "GeoMapToolbarComponent",
3686
- "whenToUse": "",
3687
- "doNotUseWhen": "",
3801
+ "category": "map",
3802
+ "summary": "Vertical map tool strip (search, pan, measure, layers, …).",
3803
+ "whenToUse": "Custom map layouts; usually included inside geo-map-shell.",
3804
+ "doNotUseWhen": "Full portal — use geo-map-shell.",
3688
3805
  "howTo": "",
3689
3806
  "tips": [],
3690
3807
  "binding": "none",
@@ -3732,19 +3849,20 @@
3732
3849
  "examples": [
3733
3850
  {
3734
3851
  "title": "Example",
3735
- "lang": "html"
3852
+ "lang": "html",
3853
+ "code": "<geo-map-toolbar\n [controller]=\"ctrl\"\n [actions]=\"actions\"\n [(checkedMap)]=\"checked\"\n (actionClick)=\"onTool($event)\"\n></geo-map-toolbar>"
3736
3854
  }
3737
3855
  ],
3738
- "example": "<geo-map-toolbar></geo-map-toolbar>",
3856
+ "example": "<geo-map-toolbar\n [controller]=\"ctrl\"\n [actions]=\"actions\"\n [(checkedMap)]=\"checked\"\n (actionClick)=\"onTool($event)\"\n></geo-map-toolbar>",
3739
3857
  "related": []
3740
3858
  },
3741
3859
  {
3742
3860
  "name": "GeoMapZoomComponent",
3743
3861
  "selector": "geo-map-zoom",
3744
- "category": "other",
3745
- "summary": "GeoMapZoomComponent",
3746
- "whenToUse": "",
3747
- "doNotUseWhen": "",
3862
+ "category": "map",
3863
+ "summary": "Zoom +/- and optional province / home navigation control.",
3864
+ "whenToUse": "Custom map chrome; geo-map-shell embeds this.",
3865
+ "doNotUseWhen": "Relying on OpenLayers built-in zoom alone is fine for bare geo-map.",
3748
3866
  "howTo": "",
3749
3867
  "tips": [],
3750
3868
  "binding": "none",
@@ -3787,19 +3905,20 @@
3787
3905
  "examples": [
3788
3906
  {
3789
3907
  "title": "Example",
3790
- "lang": "html"
3908
+ "lang": "html",
3909
+ "code": "<geo-map-zoom [controller]=\"ctrl\" [showNav]=\"true\"></geo-map-zoom>"
3791
3910
  }
3792
3911
  ],
3793
- "example": "<geo-map-zoom></geo-map-zoom>",
3912
+ "example": "<geo-map-zoom [controller]=\"ctrl\" [showNav]=\"true\"></geo-map-zoom>",
3794
3913
  "related": []
3795
3914
  },
3796
3915
  {
3797
3916
  "name": "GeoOverlapResultComponent",
3798
3917
  "selector": "geo-overlap-result",
3799
- "category": "other",
3800
- "summary": "GeoOverlapResultComponent",
3801
- "whenToUse": "",
3802
- "doNotUseWhen": "",
3918
+ "category": "data",
3919
+ "summary": "Overlap analysis result list (planning type, area, percent).",
3920
+ "whenToUse": "Show giao cắt quy hoạch vs hiện trạng results.",
3921
+ "doNotUseWhen": "Generic tables — use geo-table.",
3803
3922
  "howTo": "",
3804
3923
  "tips": [],
3805
3924
  "binding": "none",
@@ -3842,19 +3961,20 @@
3842
3961
  "examples": [
3843
3962
  {
3844
3963
  "title": "Example",
3845
- "lang": "html"
3964
+ "lang": "html",
3965
+ "code": "<geo-overlap-result [rows]=\"rows\" (rowClick)=\"focus($event)\"></geo-overlap-result>"
3846
3966
  }
3847
3967
  ],
3848
- "example": "<geo-overlap-result></geo-overlap-result>",
3968
+ "example": "<geo-overlap-result [rows]=\"rows\" (rowClick)=\"focus($event)\"></geo-overlap-result>",
3849
3969
  "related": []
3850
3970
  },
3851
3971
  {
3852
3972
  "name": "GeoPageHeaderComponent",
3853
3973
  "selector": "geo-page-header",
3854
- "category": "other",
3855
- "summary": "GeoPageHeaderComponent",
3856
- "whenToUse": "",
3857
- "doNotUseWhen": "",
3974
+ "category": "display",
3975
+ "summary": "Compact page header block (title + optional actions slot).",
3976
+ "whenToUse": "Section headers on dashboard / list pages.",
3977
+ "doNotUseWhen": "Full page title under breadcrumb — prefer geo-page-title.",
3858
3978
  "howTo": "",
3859
3979
  "tips": [],
3860
3980
  "binding": "none",
@@ -3885,10 +4005,11 @@
3885
4005
  "examples": [
3886
4006
  {
3887
4007
  "title": "Example",
3888
- "lang": "html"
4008
+ "lang": "html",
4009
+ "code": "<geo-page-header title=\"Thống kê nhanh\"></geo-page-header>"
3889
4010
  }
3890
4011
  ],
3891
- "example": "<geo-page-header></geo-page-header>",
4012
+ "example": "<geo-page-header title=\"Thống kê nhanh\"></geo-page-header>",
3892
4013
  "related": []
3893
4014
  },
3894
4015
  {
@@ -4346,7 +4467,7 @@
4346
4467
  "selector": "geo-slider",
4347
4468
  "category": "forms",
4348
4469
  "summary": "Numeric range slider.",
4349
- "whenToUse": "Continuous numeric value in a range.",
4470
+ "whenToUse": "Continuous numeric value in a range (opacity, percent).",
4350
4471
  "doNotUseWhen": "Discrete small sets — use select/radio.",
4351
4472
  "howTo": "Thanh trượt số liên tục. Two-way [(value)] / (valueChange); min/max/step; tipFormatter tùy chỉnh tooltip.",
4352
4473
  "tips": [
@@ -4418,10 +4539,10 @@
4418
4539
  {
4419
4540
  "name": "GeoStatCardComponent",
4420
4541
  "selector": "geo-stat-card",
4421
- "category": "other",
4422
- "summary": "GeoStatCardComponent",
4423
- "whenToUse": "",
4424
- "doNotUseWhen": "",
4542
+ "category": "data",
4543
+ "summary": "KPI stat card (label, value, optional delta / icon).",
4544
+ "whenToUse": "Dashboard summary tiles.",
4545
+ "doNotUseWhen": "Detailed tables — use geo-table.",
4425
4546
  "howTo": "",
4426
4547
  "tips": [],
4427
4548
  "binding": "none",
@@ -4500,10 +4621,11 @@
4500
4621
  "examples": [
4501
4622
  {
4502
4623
  "title": "Example",
4503
- "lang": "html"
4624
+ "lang": "html",
4625
+ "code": "<geo-stat-card label=\"Tổng thửa\" [value]=\"12450\" unit=\"thửa\"></geo-stat-card>"
4504
4626
  }
4505
4627
  ],
4506
- "example": "<geo-stat-card></geo-stat-card>",
4628
+ "example": "<geo-stat-card label=\"Tổng thửa\" [value]=\"12450\" unit=\"thửa\"></geo-stat-card>",
4507
4629
  "related": []
4508
4630
  },
4509
4631
  {
@@ -5709,12 +5831,24 @@
5709
5831
  "default": "false",
5710
5832
  "note": ""
5711
5833
  },
5834
+ {
5835
+ "name": "selectionMode",
5836
+ "type": "'single' | 'multi'",
5837
+ "default": "'multi'",
5838
+ "note": "`single` — click chọn đúng 1 node (BR-06-03); `multi` — giữ hành vi checkbox hiện có."
5839
+ },
5712
5840
  {
5713
5841
  "name": "checkedKeys",
5714
5842
  "type": "Array<string | number>",
5715
5843
  "default": "[]",
5716
5844
  "note": "Two-way `model()` (supports banana binding)."
5717
5845
  },
5846
+ {
5847
+ "name": "selectedKeys",
5848
+ "type": "Array<string | number>",
5849
+ "default": "[]",
5850
+ "note": "Two-way `model()` (supports banana binding)."
5851
+ },
5718
5852
  {
5719
5853
  "name": "expandedKeys",
5720
5854
  "type": "Array<string | number>",