@fui-org/fui-cli 2.1.4 → 2.2.0

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 (217) hide show
  1. package/README.md +27 -7
  2. package/dist/fui-qrb1j9jz.js +397 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +1 -1
  5. package/skills/fui/SKILL.md +143 -38
  6. package/skills/fui/agents/fui-builder.md +62 -0
  7. package/skills/fui/agents/fui-tester.md +77 -0
  8. package/skills/{fui-skill → fui}/assets/projectdefaultstyle.css +489 -489
  9. package/skills/{fui-skill → fui}/examples/component.vue +162 -162
  10. package/skills/{fui-skill → fui}/references/INDEX.md +5 -4
  11. package/skills/{fui-skill → fui}/references/advanced-techniques.md +170 -168
  12. package/skills/{fui-skill → fui}/references/component-design.md +2 -2
  13. package/skills/{fui-skill → fui}/references/component-quickref.md +78 -78
  14. package/skills/{fui-skill → fui}/references/component-table.md +287 -287
  15. package/skills/{fui-skill → fui}/references/components-dialog.md +191 -191
  16. package/skills/{fui-skill → fui}/references/components-display.md +141 -141
  17. package/skills/{fui-skill → fui}/references/components-echart.md +316 -316
  18. package/skills/{fui-skill → fui}/references/components-input.md +335 -335
  19. package/skills/{fui-skill → fui}/references/controls-patterns.md +2 -2
  20. package/skills/{fui-skill → fui}/references/controls-styling-vocabulary.md +173 -173
  21. package/skills/{fui-skill → fui}/references/db-workflow.md +9 -9
  22. package/skills/{fui-skill → fui}/references/default-function.md +456 -456
  23. package/skills/{fui-skill → fui}/references/design-modes.md +57 -57
  24. package/skills/{fui-skill → fui}/references/echart-templates.md +489 -489
  25. package/skills/{fui-skill → fui}/references/fastproject.md +99 -99
  26. package/skills/{fui-skill → fui}/references/fullstack-workflow.md +314 -313
  27. package/skills/{fui-skill → fui}/references/module-data-patterns.md +117 -117
  28. package/skills/{fui-skill → fui}/references/module-json-anatomy.md +132 -132
  29. package/skills/{fui-skill → fui}/references/module-structure.md +144 -144
  30. package/skills/{fui-skill → fui}/references/new-session.md +1 -2
  31. package/skills/{fui-skill → fui}/references/pdfmake.md +60 -60
  32. package/skills/{fui-skill → fui}/references/permission-system.md +1 -1
  33. package/skills/{fui-skill → fui}/references/platform-architecture.md +269 -269
  34. package/skills/{fui-skill → fui}/references/project-config.md +303 -303
  35. package/skills/{fui-skill → fui}/references/project-provisioning.md +4 -4
  36. package/skills/{fui-skill → fui}/references/script-map.md +262 -262
  37. package/skills/{fui-skill → fui}/references/sql-clr-functions.md +225 -225
  38. package/skills/{fui-skill → fui}/references/system-design.md +2 -2
  39. package/skills/{fui-skill → fui}/references/tapi-permission-patterns.md +156 -156
  40. package/skills/{fui-skill → fui}/references/tapi-reference.md +474 -474
  41. package/skills/fui/references/team-run.md +141 -0
  42. package/skills/fui/references/tools-registry.md +211 -0
  43. package/skills/{fui-skill → fui}/references/ui-crosswindow-patterns.md +321 -321
  44. package/skills/{fui-skill → fui}/references/ui-dialog-patterns.md +255 -255
  45. package/skills/{fui-skill → fui}/references/ui-layout-patterns.md +176 -176
  46. package/skills/{fui-skill → fui}/references/ui-patterns.md +303 -303
  47. package/skills/{fui-skill → fui}/references/ui-screenshot-review.md +95 -95
  48. package/skills/{fui-skill → fui}/references/ui-table-cell-patterns.md +318 -318
  49. package/skills/{fui-skill → fui}/references/verification.md +11 -11
  50. package/skills/{fui-skill → fui}/references/watcher-patterns.md +163 -163
  51. package/skills/{fui-skill → fui}/references/websocket-realtime.md +271 -271
  52. package/skills/{fui-skill → fui}/scripts/component-3.0.js +2715 -2715
  53. package/skills/{fui-skill → fui}/scripts/component.js +3147 -3147
  54. package/skills/{fui-skill → fui}/scripts/componentTable-3.0.js +1038 -1038
  55. package/skills/{fui-skill → fui}/scripts/componentTable.js +891 -891
  56. package/skills/{fui-skill → fui}/scripts/defaultfunction-3.0.js +866 -866
  57. package/skills/{fui-skill → fui}/scripts/defaultfunction.js +1051 -1051
  58. package/skills/{fui-skill → fui}/scripts/fastproject-3.0.js +870 -870
  59. package/skills/{fui-skill → fui}/scripts/fastproject.js +828 -828
  60. package/dist/fui-h4z7zhk2.js +0 -381
  61. package/skills/fui-skill/SKILL.md +0 -139
  62. package/skills/fui-skill/references/tools-registry.md +0 -84
  63. /package/skills/{fui-skill → fui}/assets/projectdefaultstyle-3.0.css +0 -0
  64. /package/skills/{fui-skill → fui}/design-md/airbnb/DESIGN.md +0 -0
  65. /package/skills/{fui-skill → fui}/design-md/airbnb/README.md +0 -0
  66. /package/skills/{fui-skill → fui}/design-md/airtable/DESIGN.md +0 -0
  67. /package/skills/{fui-skill → fui}/design-md/airtable/README.md +0 -0
  68. /package/skills/{fui-skill → fui}/design-md/apple/DESIGN.md +0 -0
  69. /package/skills/{fui-skill → fui}/design-md/apple/README.md +0 -0
  70. /package/skills/{fui-skill → fui}/design-md/asu/DESIGN.md +0 -0
  71. /package/skills/{fui-skill → fui}/design-md/asu/README.md +0 -0
  72. /package/skills/{fui-skill → fui}/design-md/binance/DESIGN.md +0 -0
  73. /package/skills/{fui-skill → fui}/design-md/binance/README.md +0 -0
  74. /package/skills/{fui-skill → fui}/design-md/bmw/DESIGN.md +0 -0
  75. /package/skills/{fui-skill → fui}/design-md/bmw/README.md +0 -0
  76. /package/skills/{fui-skill → fui}/design-md/bmw-m/DESIGN.md +0 -0
  77. /package/skills/{fui-skill → fui}/design-md/bmw-m/README.md +0 -0
  78. /package/skills/{fui-skill → fui}/design-md/bugatti/DESIGN.md +0 -0
  79. /package/skills/{fui-skill → fui}/design-md/bugatti/README.md +0 -0
  80. /package/skills/{fui-skill → fui}/design-md/cal/DESIGN.md +0 -0
  81. /package/skills/{fui-skill → fui}/design-md/cal/README.md +0 -0
  82. /package/skills/{fui-skill → fui}/design-md/claude/DESIGN.md +0 -0
  83. /package/skills/{fui-skill → fui}/design-md/claude/README.md +0 -0
  84. /package/skills/{fui-skill → fui}/design-md/clay/DESIGN.md +0 -0
  85. /package/skills/{fui-skill → fui}/design-md/clay/README.md +0 -0
  86. /package/skills/{fui-skill → fui}/design-md/clickhouse/DESIGN.md +0 -0
  87. /package/skills/{fui-skill → fui}/design-md/clickhouse/README.md +0 -0
  88. /package/skills/{fui-skill → fui}/design-md/cohere/DESIGN.md +0 -0
  89. /package/skills/{fui-skill → fui}/design-md/cohere/README.md +0 -0
  90. /package/skills/{fui-skill → fui}/design-md/coinbase/DESIGN.md +0 -0
  91. /package/skills/{fui-skill → fui}/design-md/coinbase/README.md +0 -0
  92. /package/skills/{fui-skill → fui}/design-md/composio/DESIGN.md +0 -0
  93. /package/skills/{fui-skill → fui}/design-md/composio/README.md +0 -0
  94. /package/skills/{fui-skill → fui}/design-md/cursor/DESIGN.md +0 -0
  95. /package/skills/{fui-skill → fui}/design-md/cursor/README.md +0 -0
  96. /package/skills/{fui-skill → fui}/design-md/elevenlabs/DESIGN.md +0 -0
  97. /package/skills/{fui-skill → fui}/design-md/elevenlabs/README.md +0 -0
  98. /package/skills/{fui-skill → fui}/design-md/expo/DESIGN.md +0 -0
  99. /package/skills/{fui-skill → fui}/design-md/expo/README.md +0 -0
  100. /package/skills/{fui-skill → fui}/design-md/ferrari/DESIGN.md +0 -0
  101. /package/skills/{fui-skill → fui}/design-md/ferrari/README.md +0 -0
  102. /package/skills/{fui-skill → fui}/design-md/figma/DESIGN.md +0 -0
  103. /package/skills/{fui-skill → fui}/design-md/figma/README.md +0 -0
  104. /package/skills/{fui-skill → fui}/design-md/framer/DESIGN.md +0 -0
  105. /package/skills/{fui-skill → fui}/design-md/framer/README.md +0 -0
  106. /package/skills/{fui-skill → fui}/design-md/fui/DESIGN.md +0 -0
  107. /package/skills/{fui-skill → fui}/design-md/hashicorp/DESIGN.md +0 -0
  108. /package/skills/{fui-skill → fui}/design-md/hashicorp/README.md +0 -0
  109. /package/skills/{fui-skill → fui}/design-md/ibm/DESIGN.md +0 -0
  110. /package/skills/{fui-skill → fui}/design-md/ibm/README.md +0 -0
  111. /package/skills/{fui-skill → fui}/design-md/intercom/DESIGN.md +0 -0
  112. /package/skills/{fui-skill → fui}/design-md/intercom/README.md +0 -0
  113. /package/skills/{fui-skill → fui}/design-md/kraken/DESIGN.md +0 -0
  114. /package/skills/{fui-skill → fui}/design-md/kraken/README.md +0 -0
  115. /package/skills/{fui-skill → fui}/design-md/lamborghini/DESIGN.md +0 -0
  116. /package/skills/{fui-skill → fui}/design-md/lamborghini/README.md +0 -0
  117. /package/skills/{fui-skill → fui}/design-md/linear.app/DESIGN.md +0 -0
  118. /package/skills/{fui-skill → fui}/design-md/linear.app/README.md +0 -0
  119. /package/skills/{fui-skill → fui}/design-md/lovable/DESIGN.md +0 -0
  120. /package/skills/{fui-skill → fui}/design-md/lovable/README.md +0 -0
  121. /package/skills/{fui-skill → fui}/design-md/mastercard/DESIGN.md +0 -0
  122. /package/skills/{fui-skill → fui}/design-md/mastercard/README.md +0 -0
  123. /package/skills/{fui-skill → fui}/design-md/meta/DESIGN.md +0 -0
  124. /package/skills/{fui-skill → fui}/design-md/meta/README.md +0 -0
  125. /package/skills/{fui-skill → fui}/design-md/minimax/DESIGN.md +0 -0
  126. /package/skills/{fui-skill → fui}/design-md/minimax/README.md +0 -0
  127. /package/skills/{fui-skill → fui}/design-md/mintlify/DESIGN.md +0 -0
  128. /package/skills/{fui-skill → fui}/design-md/mintlify/README.md +0 -0
  129. /package/skills/{fui-skill → fui}/design-md/miro/DESIGN.md +0 -0
  130. /package/skills/{fui-skill → fui}/design-md/miro/README.md +0 -0
  131. /package/skills/{fui-skill → fui}/design-md/mistral.ai/DESIGN.md +0 -0
  132. /package/skills/{fui-skill → fui}/design-md/mistral.ai/README.md +0 -0
  133. /package/skills/{fui-skill → fui}/design-md/mongodb/DESIGN.md +0 -0
  134. /package/skills/{fui-skill → fui}/design-md/mongodb/README.md +0 -0
  135. /package/skills/{fui-skill → fui}/design-md/nike/DESIGN.md +0 -0
  136. /package/skills/{fui-skill → fui}/design-md/nike/README.md +0 -0
  137. /package/skills/{fui-skill → fui}/design-md/notion/DESIGN.md +0 -0
  138. /package/skills/{fui-skill → fui}/design-md/notion/README.md +0 -0
  139. /package/skills/{fui-skill → fui}/design-md/nvidia/DESIGN.md +0 -0
  140. /package/skills/{fui-skill → fui}/design-md/nvidia/README.md +0 -0
  141. /package/skills/{fui-skill → fui}/design-md/ollama/DESIGN.md +0 -0
  142. /package/skills/{fui-skill → fui}/design-md/ollama/README.md +0 -0
  143. /package/skills/{fui-skill → fui}/design-md/opencode.ai/DESIGN.md +0 -0
  144. /package/skills/{fui-skill → fui}/design-md/opencode.ai/README.md +0 -0
  145. /package/skills/{fui-skill → fui}/design-md/pinterest/DESIGN.md +0 -0
  146. /package/skills/{fui-skill → fui}/design-md/pinterest/README.md +0 -0
  147. /package/skills/{fui-skill → fui}/design-md/playstation/DESIGN.md +0 -0
  148. /package/skills/{fui-skill → fui}/design-md/playstation/README.md +0 -0
  149. /package/skills/{fui-skill → fui}/design-md/posthog/DESIGN.md +0 -0
  150. /package/skills/{fui-skill → fui}/design-md/posthog/README.md +0 -0
  151. /package/skills/{fui-skill → fui}/design-md/raycast/DESIGN.md +0 -0
  152. /package/skills/{fui-skill → fui}/design-md/raycast/README.md +0 -0
  153. /package/skills/{fui-skill → fui}/design-md/renault/DESIGN.md +0 -0
  154. /package/skills/{fui-skill → fui}/design-md/renault/README.md +0 -0
  155. /package/skills/{fui-skill → fui}/design-md/replicate/DESIGN.md +0 -0
  156. /package/skills/{fui-skill → fui}/design-md/replicate/README.md +0 -0
  157. /package/skills/{fui-skill → fui}/design-md/resend/DESIGN.md +0 -0
  158. /package/skills/{fui-skill → fui}/design-md/resend/README.md +0 -0
  159. /package/skills/{fui-skill → fui}/design-md/revolut/DESIGN.md +0 -0
  160. /package/skills/{fui-skill → fui}/design-md/revolut/README.md +0 -0
  161. /package/skills/{fui-skill → fui}/design-md/runwayml/DESIGN.md +0 -0
  162. /package/skills/{fui-skill → fui}/design-md/runwayml/README.md +0 -0
  163. /package/skills/{fui-skill → fui}/design-md/sanity/DESIGN.md +0 -0
  164. /package/skills/{fui-skill → fui}/design-md/sanity/README.md +0 -0
  165. /package/skills/{fui-skill → fui}/design-md/sentry/DESIGN.md +0 -0
  166. /package/skills/{fui-skill → fui}/design-md/sentry/README.md +0 -0
  167. /package/skills/{fui-skill → fui}/design-md/shopify/DESIGN.md +0 -0
  168. /package/skills/{fui-skill → fui}/design-md/shopify/README.md +0 -0
  169. /package/skills/{fui-skill → fui}/design-md/slack/DESIGN.md +0 -0
  170. /package/skills/{fui-skill → fui}/design-md/spacex/DESIGN.md +0 -0
  171. /package/skills/{fui-skill → fui}/design-md/spacex/README.md +0 -0
  172. /package/skills/{fui-skill → fui}/design-md/spotify/DESIGN.md +0 -0
  173. /package/skills/{fui-skill → fui}/design-md/spotify/README.md +0 -0
  174. /package/skills/{fui-skill → fui}/design-md/starbucks/DESIGN.md +0 -0
  175. /package/skills/{fui-skill → fui}/design-md/starbucks/README.md +0 -0
  176. /package/skills/{fui-skill → fui}/design-md/stripe/DESIGN.md +0 -0
  177. /package/skills/{fui-skill → fui}/design-md/stripe/README.md +0 -0
  178. /package/skills/{fui-skill → fui}/design-md/supabase/DESIGN.md +0 -0
  179. /package/skills/{fui-skill → fui}/design-md/supabase/README.md +0 -0
  180. /package/skills/{fui-skill → fui}/design-md/superhuman/DESIGN.md +0 -0
  181. /package/skills/{fui-skill → fui}/design-md/superhuman/README.md +0 -0
  182. /package/skills/{fui-skill → fui}/design-md/tesla/DESIGN.md +0 -0
  183. /package/skills/{fui-skill → fui}/design-md/tesla/README.md +0 -0
  184. /package/skills/{fui-skill → fui}/design-md/theverge/DESIGN.md +0 -0
  185. /package/skills/{fui-skill → fui}/design-md/theverge/README.md +0 -0
  186. /package/skills/{fui-skill → fui}/design-md/together.ai/DESIGN.md +0 -0
  187. /package/skills/{fui-skill → fui}/design-md/together.ai/README.md +0 -0
  188. /package/skills/{fui-skill → fui}/design-md/uber/DESIGN.md +0 -0
  189. /package/skills/{fui-skill → fui}/design-md/uber/README.md +0 -0
  190. /package/skills/{fui-skill → fui}/design-md/vercel/DESIGN.md +0 -0
  191. /package/skills/{fui-skill → fui}/design-md/vercel/README.md +0 -0
  192. /package/skills/{fui-skill → fui}/design-md/vodafone/DESIGN.md +0 -0
  193. /package/skills/{fui-skill → fui}/design-md/vodafone/README.md +0 -0
  194. /package/skills/{fui-skill → fui}/design-md/voltagent/DESIGN.md +0 -0
  195. /package/skills/{fui-skill → fui}/design-md/voltagent/README.md +0 -0
  196. /package/skills/{fui-skill → fui}/design-md/warp/DESIGN.md +0 -0
  197. /package/skills/{fui-skill → fui}/design-md/warp/README.md +0 -0
  198. /package/skills/{fui-skill → fui}/design-md/webflow/DESIGN.md +0 -0
  199. /package/skills/{fui-skill → fui}/design-md/webflow/README.md +0 -0
  200. /package/skills/{fui-skill → fui}/design-md/wired/DESIGN.md +0 -0
  201. /package/skills/{fui-skill → fui}/design-md/wired/README.md +0 -0
  202. /package/skills/{fui-skill → fui}/design-md/wise/DESIGN.md +0 -0
  203. /package/skills/{fui-skill → fui}/design-md/wise/README.md +0 -0
  204. /package/skills/{fui-skill → fui}/design-md/x.ai/DESIGN.md +0 -0
  205. /package/skills/{fui-skill → fui}/design-md/x.ai/README.md +0 -0
  206. /package/skills/{fui-skill → fui}/design-md/zapier/DESIGN.md +0 -0
  207. /package/skills/{fui-skill → fui}/design-md/zapier/README.md +0 -0
  208. /package/skills/{fui-skill → fui}/examples/f-table-patterns.json +0 -0
  209. /package/skills/{fui-skill → fui}/examples/module-patterns.json +0 -0
  210. /package/skills/{fui-skill → fui}/examples/project-patterns.json +0 -0
  211. /package/skills/{fui-skill → fui}/references/coding-standards.md +0 -0
  212. /package/skills/{fui-skill → fui}/references/db-table-design.md +0 -0
  213. /package/skills/{fui-skill → fui}/references/fsheet.md +0 -0
  214. /package/skills/{fui-skill → fui}/references/tapi-file-api.md +0 -0
  215. /package/skills/{fui-skill → fui}/references/ui-templates.md +0 -0
  216. /package/skills/{fui-skill → fui}/scripts/fechart.js +0 -0
  217. /package/skills/{fui-skill → fui}/scripts/fsheet.js +0 -0
@@ -1,255 +1,255 @@
1
- # FUI Dialog Patterns — manual v-dialog (STANDARD), hidden-container, checkbox-list
2
-
3
- > Owns: **manual dialogs: `hidden-container`, `v-card`/`v-toolbar` anatomy, opening a dialog with a row, checkbox-list**. `f-dialog`: [components-dialog.md](components-dialog.md).
4
-
5
- From **security-manager** and demo **ex-v3-dialog**.
6
-
7
- > **Dialog STANDARD: build `v-dialog` manually per the §1 anatomy** (easy to read/edit piecewise), **styled like `f-dialog`**: uncolored `dense flat` toolbar + close icon, floating-label form, last row is `v-card-actions`. Actions right-aligned, buttons keep natural width; only the primary action gets a filled color, secondary actions are text buttons. Full anatomy + rule table: `fui design read fui` §4–5. `f-dialog` (§0) is the secondary option for very small forms.
8
-
9
- > See also: [ui-patterns.md](ui-patterns.md), [ui-table-cell-patterns.md](ui-table-cell-patterns.md) (menuChucNang opening a dialog), [components-dialog.md](components-dialog.md).
10
-
11
- ---
12
-
13
- ## 0. `f-dialog` — compact dialog component (secondary)
14
-
15
- `f-dialog` bundles card + toolbar + buttons — shorter than manual `v-dialog` but hard to customise layout. Use only for very small/simple forms; default is manual `v-dialog` (§1). Inner fields' `v-model` **points directly at keys of the `data` object** (no `vueData.dialogData.X`).
16
-
17
- ```json
18
- {
19
- "el": "f-dialog",
20
- "attr": {
21
- "v-model": "dialogOpen", // boolean mở/đóng
22
- "v-model:data": "dialogData", // object dữ liệu của form
23
- "title": "Nhập dữ liệu",
24
- ":open-action": { "MESSBOX": "Bạn vừa mở dialog" },
25
- ":controls": [
26
- { "el": "v-text-field", "attr": { "v-model": "Domain", "label": "Domain" }, "w": 4 },
27
- { "el": "v-text-field", "attr": { "v-model": "ModuleID", "label": "ModuleID" }, "w": 3 },
28
- { "el": "v-checkbox", "attr": { "v-model": "checkBoxValue", ":label": "`Tôi đồng ý: ${checkBoxValue}`" } },
29
- {
30
- "el": "v-select",
31
- "attr": {
32
- "label": "Chọn",
33
- "v-model": "bienselect",
34
- ":items": "vueData.Mang",
35
- "item-title": "AppName",
36
- "item-value": "AppListID"
37
- }
38
- }
39
- ],
40
- ":watch": {
41
- "bienselect": { "MESSBOX": "Watch {{bienselect}}" }
42
- },
43
- ":button": [
44
- {
45
- "label": "Lưu",
46
- "type": "submit",
47
- ":disabled": "!checkBoxValue",
48
- "action": [{ "MESSBOX": "Đã lưu" }, { "dialogOpen": false }]
49
- },
50
- { "label": "Chạy API", "checkvalid": true, "v-if": "ModuleID==1", "action": [{ "API": "/chaymotapi" }] },
51
- { "label": "Đóng", "action": [{ "dialogOpen": false }] }
52
- ]
53
- }
54
- }
55
- ```
56
-
57
- | Prop | Role |
58
- | -------------- | ------------------------------------------------------------------------------ |
59
- | `v-model` | Boolean open/close |
60
- | `v-model:data` | Form data object; `:controls` fields bind directly to its keys |
61
- | `title` | Dialog title |
62
- | `:open-action` | Action run on open |
63
- | `:controls` | Control Object array = form fields |
64
- | `:watch` | Dialog-scoped watchers (by field name) |
65
- | `:button` | Buttons: `label`, `type:"submit"`, `checkvalid`, `:disabled`, `v-if`, `action` |
66
-
67
- **Which to use:** every dialog by default → **manual `v-dialog` per §1** (project standard). `f-dialog` only for very small forms (1–3 fields, no special layout) with no customisation requested.
68
-
69
- ---
70
-
71
- ## 1. Manual v-dialog in hidden-container (STANDARD)
72
-
73
- Dialogs always live in their own container with `prop: "hidden-container"` — never inside the main rows.
74
-
75
- ```json
76
- {
77
- "prop": "hidden-container",
78
- "rows": [
79
- {
80
- "prop": "",
81
- "cols": [
82
- {
83
- "el": "v-dialog",
84
- "attr": {
85
- "v-model": "dlUserInfo",
86
- "width": 650
87
- },
88
- "innerHTML": [
89
- {
90
- "el": "v-card",
91
- "attr": { "class": "pa-0" },
92
- "innerHTML": [
93
- {
94
- "el": "v-toolbar",
95
- "attr": { "dense": "", "flat": "" },
96
- "innerHTML": [
97
- { "el": "v-toolbar-title", "attr": {}, "innerHTML": "Update User Info" },
98
- { "el": "v-spacer", "attr": {} },
99
- {
100
- "el": "v-btn",
101
- "innerHTML": "<v-icon>mdi-close</v-icon>",
102
- "attr": { "icon": "", "v-on:click": "vueData.dlUserInfo = false" }
103
- }
104
- ]
105
- },
106
- {
107
- "el": "v-container",
108
- "attr": { "class": "grid-list-md px-4" },
109
- "innerHTML": [
110
- {
111
- "el": "v-layout",
112
- "w": 12,
113
- "attr": { "row": "", "wrap": "" },
114
- "innerHTML": [
115
- {
116
- "el": "v-text-field",
117
- "col": {},
118
- "attr": { "v-model": "vueData.sUserName", "label": "Tên đăng nhập" },
119
- "w": 6
120
- },
121
- {
122
- "el": "v-text-field",
123
- "col": {},
124
- "attr": { "v-model": "vueData.sLastName", "label": "Họ tên" },
125
- "w": 6
126
- }
127
- ]
128
- }
129
- ]
130
- },
131
- {
132
- "el": "v-card-actions",
133
- "attr": { "class": "mr-1 mb-1" },
134
- "innerHTML": [
135
- { "el": "v-spacer", "attr": {} },
136
- {
137
- "el": "f-button",
138
- "attr": {
139
- "text": "",
140
- "label": "Đặt lại",
141
- ":action": { "CALL": "resetForm" }
142
- }
143
- },
144
- {
145
- "el": "f-button",
146
- "attr": {
147
- "color": "primary",
148
- ":checkvalid": true,
149
- "label": "Lưu",
150
- "icon-text": "mdi-content-save",
151
- ":action": {
152
- "API": "SM_Users_Update",
153
- "IN": { "UserID": "sUserID", "UserName": "sUserName" },
154
- "CALLBACK": [
155
- { "MESS": "Cập nhật thành công." },
156
- { "dlUserInfo": false },
157
- { "CALL": "getUser" }
158
- ]
159
- }
160
- }
161
- }
162
- ]
163
- }
164
- ]
165
- }
166
- ]
167
- }
168
- ]
169
- }
170
- ]
171
- }
172
- ```
173
-
174
- **Rules (f-dialog look):**
175
-
176
- - `v-card[class="pa-0"]` — removes padding so the toolbar touches the edges (Vuetify class, not inline style); no elevation/outlined.
177
- - `v-toolbar[dense flat]` — thin title bar, **no** color/dark.
178
- - Close: `v-btn[icon]` mdi-close + `v-on:click: "vueData.dlXxx = false"` — no extra "Đóng" button in actions.
179
- - Form body: `v-container.grid-list-md.px-4` > `v-layout[row wrap]` > **floating-label** fields (`label` in attr; w:12 long / 6+6 short) — NO separate label divs.
180
- - Last button row MUST be `v-card-actions[class="mr-1 mb-1"]` — not a `v-layout`, `v-container` or normal form row.
181
- - `v-spacer` before the buttons → all actions right-aligned.
182
- - Buttons keep natural content width: no `w`, `width`, `block`, `flex-grow`, and don't wrap each in a growing column.
183
- - At most one primary action (e.g. **Lưu**) gets filled `color="primary"`; secondary actions use `f-button` + `"text": ""`, unfilled. Few buttons, short labels, restrained.
184
- - Save CALLBACK: MESS → close dialog → reload data.
185
-
186
- ---
187
-
188
- ## 2. Open dialog with row data
189
-
190
- Two steps: copy data into state → set `dlXxx = true`.
191
-
192
- **From menuChucNang:**
193
-
194
- ```json
195
- "action": [
196
- {
197
- "addNew": 0,
198
- "dongChon": "item",
199
- "sUserID": "item.UserID",
200
- "sUserName": "item.UserName",
201
- "sLastName": "item.LastName"
202
- },
203
- { "dlUserInfo": true }
204
- ]
205
- ```
206
-
207
- **From f-button:**
208
-
209
- ```json
210
- ":action": [
211
- { "addNew": 1, "sUserID": "", "sUserName": "" },
212
- { "dlUserInfo": true }
213
- ]
214
- ```
215
-
216
- > `addNew: 0` = edit, `addNew: 1` = new. In the dialog use `:disabled="addNew==0"` to lock the ID field on edit.
217
-
218
- ---
219
-
220
- ## 3. Checkbox-list dialog
221
-
222
- Dialog with a checkbox list for multi-select, saving on each click.
223
-
224
- ```json
225
- {
226
- "el": "v-card-text",
227
- "attr": {},
228
- "innerHTML": [
229
- {
230
- "el": "v-layout",
231
- "attr": { "class": "fluid row justify-center grid-list-lg fill-height mt-3" },
232
- "innerHTML": [
233
- {
234
- "el": "div",
235
- "attr": { "v-for": "fc in vueData.dsFunctionRight", ":key": "fc.FunctionID" },
236
- "innerHTML": [
237
- {
238
- "el": "v-checkbox",
239
- "attr": {
240
- "color": "primary",
241
- "v-model": "sFunctionSelected",
242
- ":value": "`${fc.FunctionID}`",
243
- ":label": "`${fc.FunctionName}`",
244
- "v-on:click": "CALL(saveFunction)"
245
- }
246
- }
247
- ]
248
- }
249
- ]
250
- }
251
- ]
252
- }
253
- ```
254
-
255
- > `v-on:click` on the checkbox → saves immediately, no Save button. `v-model` holds an array; `:value` uses a backtick literal.
1
+ # FUI Dialog Patterns — manual v-dialog (STANDARD), hidden-container, checkbox-list
2
+
3
+ > Owns: **manual dialogs: `hidden-container`, `v-card`/`v-toolbar` anatomy, opening a dialog with a row, checkbox-list**. `f-dialog`: [components-dialog.md](components-dialog.md).
4
+
5
+ From **security-manager** and demo **ex-v3-dialog**.
6
+
7
+ > **Dialog STANDARD: build `v-dialog` manually per the §1 anatomy** (easy to read/edit piecewise), **styled like `f-dialog`**: uncolored `dense flat` toolbar + close icon, floating-label form, last row is `v-card-actions`. Actions right-aligned, buttons keep natural width; only the primary action gets a filled color, secondary actions are text buttons. Full anatomy + rule table: `fui design read fui` §4–5. `f-dialog` (§0) is the secondary option for very small forms.
8
+
9
+ > See also: [ui-patterns.md](ui-patterns.md), [ui-table-cell-patterns.md](ui-table-cell-patterns.md) (menuChucNang opening a dialog), [components-dialog.md](components-dialog.md).
10
+
11
+ ---
12
+
13
+ ## 0. `f-dialog` — compact dialog component (secondary)
14
+
15
+ `f-dialog` bundles card + toolbar + buttons — shorter than manual `v-dialog` but hard to customise layout. Use only for very small/simple forms; default is manual `v-dialog` (§1). Inner fields' `v-model` **points directly at keys of the `data` object** (no `vueData.dialogData.X`).
16
+
17
+ ```json
18
+ {
19
+ "el": "f-dialog",
20
+ "attr": {
21
+ "v-model": "dialogOpen", // boolean mở/đóng
22
+ "v-model:data": "dialogData", // object dữ liệu của form
23
+ "title": "Nhập dữ liệu",
24
+ ":open-action": { "MESSBOX": "Bạn vừa mở dialog" },
25
+ ":controls": [
26
+ { "el": "v-text-field", "attr": { "v-model": "Domain", "label": "Domain" }, "w": 4 },
27
+ { "el": "v-text-field", "attr": { "v-model": "ModuleID", "label": "ModuleID" }, "w": 3 },
28
+ { "el": "v-checkbox", "attr": { "v-model": "checkBoxValue", ":label": "`Tôi đồng ý: ${checkBoxValue}`" } },
29
+ {
30
+ "el": "v-select",
31
+ "attr": {
32
+ "label": "Chọn",
33
+ "v-model": "bienselect",
34
+ ":items": "vueData.Mang",
35
+ "item-title": "AppName",
36
+ "item-value": "AppListID"
37
+ }
38
+ }
39
+ ],
40
+ ":watch": {
41
+ "bienselect": { "MESSBOX": "Watch {{bienselect}}" }
42
+ },
43
+ ":button": [
44
+ {
45
+ "label": "Lưu",
46
+ "type": "submit",
47
+ ":disabled": "!checkBoxValue",
48
+ "action": [{ "MESSBOX": "Đã lưu" }, { "dialogOpen": false }]
49
+ },
50
+ { "label": "Chạy API", "checkvalid": true, "v-if": "ModuleID==1", "action": [{ "API": "/chaymotapi" }] },
51
+ { "label": "Đóng", "action": [{ "dialogOpen": false }] }
52
+ ]
53
+ }
54
+ }
55
+ ```
56
+
57
+ | Prop | Role |
58
+ | -------------- | ------------------------------------------------------------------------------ |
59
+ | `v-model` | Boolean open/close |
60
+ | `v-model:data` | Form data object; `:controls` fields bind directly to its keys |
61
+ | `title` | Dialog title |
62
+ | `:open-action` | Action run on open |
63
+ | `:controls` | Control Object array = form fields |
64
+ | `:watch` | Dialog-scoped watchers (by field name) |
65
+ | `:button` | Buttons: `label`, `type:"submit"`, `checkvalid`, `:disabled`, `v-if`, `action` |
66
+
67
+ **Which to use:** every dialog by default → **manual `v-dialog` per §1** (project standard). `f-dialog` only for very small forms (1–3 fields, no special layout) with no customisation requested.
68
+
69
+ ---
70
+
71
+ ## 1. Manual v-dialog in hidden-container (STANDARD)
72
+
73
+ Dialogs always live in their own container with `prop: "hidden-container"` — never inside the main rows.
74
+
75
+ ```json
76
+ {
77
+ "prop": "hidden-container",
78
+ "rows": [
79
+ {
80
+ "prop": "",
81
+ "cols": [
82
+ {
83
+ "el": "v-dialog",
84
+ "attr": {
85
+ "v-model": "dlUserInfo",
86
+ "width": 650
87
+ },
88
+ "innerHTML": [
89
+ {
90
+ "el": "v-card",
91
+ "attr": { "class": "pa-0" },
92
+ "innerHTML": [
93
+ {
94
+ "el": "v-toolbar",
95
+ "attr": { "dense": "", "flat": "" },
96
+ "innerHTML": [
97
+ { "el": "v-toolbar-title", "attr": {}, "innerHTML": "Update User Info" },
98
+ { "el": "v-spacer", "attr": {} },
99
+ {
100
+ "el": "v-btn",
101
+ "innerHTML": "<v-icon>mdi-close</v-icon>",
102
+ "attr": { "icon": "", "v-on:click": "vueData.dlUserInfo = false" }
103
+ }
104
+ ]
105
+ },
106
+ {
107
+ "el": "v-container",
108
+ "attr": { "class": "grid-list-md px-4" },
109
+ "innerHTML": [
110
+ {
111
+ "el": "v-layout",
112
+ "w": 12,
113
+ "attr": { "row": "", "wrap": "" },
114
+ "innerHTML": [
115
+ {
116
+ "el": "v-text-field",
117
+ "col": {},
118
+ "attr": { "v-model": "vueData.sUserName", "label": "Tên đăng nhập" },
119
+ "w": 6
120
+ },
121
+ {
122
+ "el": "v-text-field",
123
+ "col": {},
124
+ "attr": { "v-model": "vueData.sLastName", "label": "Họ tên" },
125
+ "w": 6
126
+ }
127
+ ]
128
+ }
129
+ ]
130
+ },
131
+ {
132
+ "el": "v-card-actions",
133
+ "attr": { "class": "mr-1 mb-1" },
134
+ "innerHTML": [
135
+ { "el": "v-spacer", "attr": {} },
136
+ {
137
+ "el": "f-button",
138
+ "attr": {
139
+ "text": "",
140
+ "label": "Đặt lại",
141
+ ":action": { "CALL": "resetForm" }
142
+ }
143
+ },
144
+ {
145
+ "el": "f-button",
146
+ "attr": {
147
+ "color": "primary",
148
+ ":checkvalid": true,
149
+ "label": "Lưu",
150
+ "icon-text": "mdi-content-save",
151
+ ":action": {
152
+ "API": "SM_Users_Update",
153
+ "IN": { "UserID": "sUserID", "UserName": "sUserName" },
154
+ "CALLBACK": [
155
+ { "MESS": "Cập nhật thành công." },
156
+ { "dlUserInfo": false },
157
+ { "CALL": "getUser" }
158
+ ]
159
+ }
160
+ }
161
+ }
162
+ ]
163
+ }
164
+ ]
165
+ }
166
+ ]
167
+ }
168
+ ]
169
+ }
170
+ ]
171
+ }
172
+ ```
173
+
174
+ **Rules (f-dialog look):**
175
+
176
+ - `v-card[class="pa-0"]` — removes padding so the toolbar touches the edges (Vuetify class, not inline style); no elevation/outlined.
177
+ - `v-toolbar[dense flat]` — thin title bar, **no** color/dark.
178
+ - Close: `v-btn[icon]` mdi-close + `v-on:click: "vueData.dlXxx = false"` — no extra "Đóng" button in actions.
179
+ - Form body: `v-container.grid-list-md.px-4` > `v-layout[row wrap]` > **floating-label** fields (`label` in attr; w:12 long / 6+6 short) — NO separate label divs.
180
+ - Last button row MUST be `v-card-actions[class="mr-1 mb-1"]` — not a `v-layout`, `v-container` or normal form row.
181
+ - `v-spacer` before the buttons → all actions right-aligned.
182
+ - Buttons keep natural content width: no `w`, `width`, `block`, `flex-grow`, and don't wrap each in a growing column.
183
+ - At most one primary action (e.g. **Lưu**) gets filled `color="primary"`; secondary actions use `f-button` + `"text": ""`, unfilled. Few buttons, short labels, restrained.
184
+ - Save CALLBACK: MESS → close dialog → reload data.
185
+
186
+ ---
187
+
188
+ ## 2. Open dialog with row data
189
+
190
+ Two steps: copy data into state → set `dlXxx = true`.
191
+
192
+ **From menuChucNang:**
193
+
194
+ ```json
195
+ "action": [
196
+ {
197
+ "addNew": 0,
198
+ "dongChon": "item",
199
+ "sUserID": "item.UserID",
200
+ "sUserName": "item.UserName",
201
+ "sLastName": "item.LastName"
202
+ },
203
+ { "dlUserInfo": true }
204
+ ]
205
+ ```
206
+
207
+ **From f-button:**
208
+
209
+ ```json
210
+ ":action": [
211
+ { "addNew": 1, "sUserID": "", "sUserName": "" },
212
+ { "dlUserInfo": true }
213
+ ]
214
+ ```
215
+
216
+ > `addNew: 0` = edit, `addNew: 1` = new. In the dialog use `:disabled="addNew==0"` to lock the ID field on edit.
217
+
218
+ ---
219
+
220
+ ## 3. Checkbox-list dialog
221
+
222
+ Dialog with a checkbox list for multi-select, saving on each click.
223
+
224
+ ```json
225
+ {
226
+ "el": "v-card-text",
227
+ "attr": {},
228
+ "innerHTML": [
229
+ {
230
+ "el": "v-layout",
231
+ "attr": { "class": "fluid row justify-center grid-list-lg fill-height mt-3" },
232
+ "innerHTML": [
233
+ {
234
+ "el": "div",
235
+ "attr": { "v-for": "fc in vueData.dsFunctionRight", ":key": "fc.FunctionID" },
236
+ "innerHTML": [
237
+ {
238
+ "el": "v-checkbox",
239
+ "attr": {
240
+ "color": "primary",
241
+ "v-model": "sFunctionSelected",
242
+ ":value": "`${fc.FunctionID}`",
243
+ ":label": "`${fc.FunctionName}`",
244
+ "v-on:click": "CALL(saveFunction)"
245
+ }
246
+ }
247
+ ]
248
+ }
249
+ ]
250
+ }
251
+ ]
252
+ }
253
+ ```
254
+
255
+ > `v-on:click` on the checkbox → saves immediately, no Save button. `v-model` holds an array; `:value` uses a backtick literal.