@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,168 +1,170 @@
1
- # Advanced FUI Techniques
2
-
3
- > Owns: **advanced techniques: `EXE`, `MAP`, complex expressions, pure-expression rule for `:attr`, rule that functions called in `EXE`/`FUN` must really exist**. Basic action engine: [controls-patterns.md](controls-patterns.md).
4
-
5
- ---
6
-
7
- ## 1. `:attr` takes a PURE EXPRESSION — never statements
8
-
9
- **Hard rule.** Every binding value in `module.json` — `:option`, `:config`, `:items`, `:headers`, `:style`, every `v-bind:*` — goes **straight to Vue's template compiler**, which accepts **one expression**. Never include:
10
-
11
- - `function(){ ... }` or IIFE `(function(){...})()`
12
- - `return`
13
- - `var` / `let` / `const`
14
- - `;` joining statements
15
-
16
- ### Why it is worse than it looks
17
-
18
- A statement in `:attr` breaks template compilation and Vue **swallows the error**: **blank page, 0 JS errors, 0 `[Vue warn]`**, no stack trace — found only after many `fui module simulate --render` rounds. That is why `fui module validate` reports it as an **error**, not a warning.
19
-
20
- > Unlike `data[]` / `IN` / `{{ }}`, which go through FUI's `getVueData()` (see [controls-patterns.md](controls-patterns.md) §0 Value Resolution) with their own rules, `:attr` does **not**.
21
-
22
- ### Allowed in `:attr`
23
-
24
- | Form | Example |
25
- | ---------------------------------- | ------------------------------------------------------- |
26
- | Object / array literal | `":config": "{ height: 300, legend: { show: true } }"` |
27
- | Ternary | `":color": "ok ? 'primary' : 'warning'"` |
28
- | Arrow `.map` / `.filter` chains | `":items": "ds.filter(x => x.Active).map(x => x.Name)"` |
29
- | Property access / vueData variable | `":option": "optThe"` |
30
-
31
- ### Complex logic → `script.js` + `EXE`
32
-
33
- Multi-step transforms, temp variables, loops, complex conditions → **not in `:attr`**:
34
-
35
- 1. Write a plain function in `script.js`: `function tenHam(){ ... }`
36
- 2. It **assigns directly to `vueData.xxx`** (does not `return` a value for JSON)
37
- 3. Call it via `EXE` — usually in the data-loading action's `CALLBACK`: `"EXE": "tenHam()"`
38
- 4. `:attr` in `module.json` only points at the variable: `":option": "optThe"`
39
-
40
- ❌ **Wrong** — IIFE in `:attr`:
41
-
42
- ```json
43
- ":option": "(function(){ var src = vueData.ds.filter(r => r.id===1); return { series:[{data: src}] }; })();"
44
- ```
45
-
46
- ✅ **Right**:
47
-
48
- ```javascript
49
- // script.js
50
- function buildChart() {
51
- var src = vueData.ds.filter(function (r) {
52
- return r.id === 1;
53
- });
54
- vueData.optThe = { series: [{ data: src }] };
55
- }
56
- ```
57
-
58
- ```json
59
- // module.json — action nạp dữ liệu
60
- "CALLBACK": { "EXE": "buildChart()" },
61
- // module.json — control
62
- ":option": "optThe"
63
- ```
64
-
65
- Declare `:option`'s variable as `{}` in `data[]` so the first render doesn't break; `buildChart()` assigns the real value after the API returns.
66
-
67
- ### Diagnosing a blank page with "0 JS error, 0 Vue warn"
68
-
69
- Not a runtime error — suspect **`:attr` template compilation** first, not `script.js` or the action engine.
70
-
71
- Isolate: replace a suspect expression with a simple static value (`":option": "{}"` or remove the attr) and re-render. **Page comes back ⇒ that expression is the culprit.** Repeat per suspect `:attr` until one remains.
72
-
73
- Running `fui module validate` before rendering catches most of these as errors.
74
-
75
- ---
76
-
77
- ## 2. Functions called in `EXE` / `FUN` must REALLY EXIST
78
-
79
- **Hard rule.** `"EXE": "buildChart()"` and `"FUN": "buildChart"` work only if `buildChart` is a **real global function** at runtime — declared in `{moduleDir}/script.js`, in an imported `.js` file, or a platform built-in ([default-function.md](default-function.md), [script-map.md](script-map.md)).
80
-
81
- This is the flip side of §1: moving logic to `script.js` and calling via `EXE` **often loses its second half**. `module.json` is edited, `EXE` written, `fui module publish json` run — but nobody writes `script.js` or runs `fui module publish script`.
82
-
83
- ### Why nothing tells you
84
-
85
- Two commands, two failure modes, **neither shows the function name prominently**:
86
-
87
- | Command | Mechanism | Symptom when missing |
88
- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
89
- | `EXE` | Runs through `templateCompiled(\`<% … %>\`)`— lodash`_.template`. A comma-operator bug at `fastproject-3.0.js:490` means **the data object is never passed**, so bare identifiers resolve to **global** | `ReferenceError: buildChart is not defined` — shows only in `fui module simulate --render`, as just **"1 JS error"** in a long report |
90
- | `FUN` | `runFunction()` looks up `window[obj.FUN]`; if absent, `console.log("Func:", …, "not found")` and **continues** | **Completely silent.** No error, no `[Vue warn]`, the action "finishes" and does nothing |
91
-
92
- Measured cost: one module burned **36 consecutive `--render` runs over 5 days** on this bug class (`buildKPI8Columns is not defined`).
93
-
94
- ### The only layer that catches it: **`fui module simulate --render`**
95
-
96
- `fui module validate` does **NOT** check this: it does not read `script.js`. (A static rule once did, and was removed — to avoid false positives it had to know **every** platform global, a list never complete; each missing name blocked publishing a working module.) `fui module simulate` in vm mode doesn't catch it either — it doesn't load `script.js` into the sandbox, so it reports ReferenceError for **every** module using `script.js` functions, even correct ones.
97
-
98
- So verify with **`--render`**: the real browser throws `ReferenceError: buildChart is not defined`, and **every JS error now makes the result an error (`isError`)** — not only init errors; errors from button clicks count too. The message is in the `═══ CHẨN ĐOÁN ═══` block at the **top** of the report, line `[MODULE]`.
99
-
100
- ⚠️ **`--render` does not catch the `FUN` case** — `runFunction` just `console.log`s and continues, throwing nothing. For `FUN`, **check function names against `script.js` yourself**; the only symptom is "action finishes, nothing happens".
101
-
102
- ### Fix
103
-
104
- 1. Write the function in `script.js`: `function buildChart(){ … vueData.optThe = …; }`
105
- 2. **`fui module publish script`** — the most-forgotten step. `fui module publish json` does **not** push `script.js`.
106
- 3. Typo → fix the name; never add an empty function to silence the error.
107
-
108
- ---
109
-
110
- ## 3. Advanced Logic & Scripting
111
-
112
- JSON logic is limited; use `script.js` for complex operations.
113
-
114
- ### Computed properties workaround
115
-
116
- `module.json` has no native computed properties. Define calculation functions in `script.js` and call them from `module.json`.
117
-
118
- **script.js**:
119
-
120
- ```javascript
121
- function getTongTien() {
122
- return vueData.items.reduce((sum, item) => sum + (item.amount || 0), 0);
123
- }
124
- ```
125
-
126
- **module.json**:
127
-
128
- ```json
129
- {
130
- "innerHTML": "Total: {{getTongTien().toLocaleString()}} VNĐ"
131
- }
132
- ```
133
-
134
- ### Complex validation
135
-
136
- Don't write long logic strings in JSON; move validation to `script.js`.
137
-
138
- **script.js**:
139
-
140
- ```javascript
141
- function validateStep1() {
142
- const d = vueData;
143
- if (!d.name || !d.email) {
144
- alert("Missing required fields!");
145
- return false;
146
- }
147
- return true;
148
- }
149
-
150
- function nextStep() {
151
- if (vueData.step === 1 && !validateStep1()) return;
152
- vueData.step++;
153
- }
154
- ```
155
-
156
- **module.json**:
157
-
158
- ```json
159
- "v-on:click": "nextStep()"
160
- ```
161
-
162
- ### Action binding
163
-
164
- For simple UI logic you may bind JS functions to events directly instead of the `CALL` action protocol.
165
-
166
- ```json
167
- "v-on:click": "prevBuoc()"
168
- ```
1
+ # Advanced FUI Techniques
2
+
3
+ > Owns: **advanced techniques: `EXE`, `MAP`, complex expressions, pure-expression rule for `:attr`, rule that functions called in `EXE`/`FUN` must really exist**. Basic action engine: [controls-patterns.md](controls-patterns.md).
4
+
5
+ ---
6
+
7
+ ## 1. `:attr` takes ONE EXPRESSION — never statements
8
+
9
+ **Hard rule.** Every binding value in `module.json` — `:option`, `:config`, `:items`, `:headers`, `:style`, every `v-bind:*` — goes **straight to Vue's template compiler**, which compiles it as `return (<value>)`: it must be **one JavaScript expression**. These break it:
10
+
11
+ - a `;` outside a string, **including one at the end**: `"(function(){ … })();"`
12
+ - a statement at the top: `var` / `let` / `const x = …; x`, a bare `return …`, `if (…) …`
13
+
14
+ A function **inside** the expression is fine, and was checked on the V3 runtime: `ds.map(function (d) { return d.url })`, a callback prop `":on-close": "() => { vueData.show = false }"`, even an IIFE `(function(){ var a = …; return a })()` without the trailing `;`.
15
+
16
+ ### Why it is worse than it looks
17
+
18
+ A binding that is not one expression breaks template compilation: **blank page**. At best a console line names the compile error; the agent sees an empty screenshot and starts suspecting everything else. That is why `fui module validate` reports it as an **error** (it checks whether the value parses as one expression), not a warning.
19
+
20
+ > Unlike `data[]` / `IN` / `{{ }}`, which go through FUI's `getVueData()` (see [controls-patterns.md](controls-patterns.md) §0 Value Resolution) with their own rules, `:attr` does **not**.
21
+
22
+ ### Allowed in `:attr`
23
+
24
+ | Form | Example |
25
+ | ---------------------------------- | ------------------------------------------------------- |
26
+ | Object / array literal | `":config": "{ height: 300, legend: { show: true } }"` |
27
+ | Ternary | `":color": "ok ? 'primary' : 'warning'"` |
28
+ | Arrow `.map` / `.filter` chains | `":items": "ds.filter(x => x.Active).map(x => x.Name)"` |
29
+ | Property access / vueData variable | `":option": "optThe"` |
30
+ | Function inside the expression | `":items": "ds.map(function (d) { return d.url })"` |
31
+ | Callback prop | `":on-close": "() => { vueData.show = false }"` |
32
+
33
+ ### Complex logic → `script.js` + `EXE`
34
+
35
+ Multi-step transforms, temp variables, loops, complex conditions → **not in `:attr`**. A long IIFE parses, but it is hard to read, cannot be tested on its own, and one stray `;` blanks the page:
36
+
37
+ 1. Write a plain function in `script.js`: `function tenHam(){ ... }`
38
+ 2. It **assigns directly to `vueData.xxx`** (does not `return` a value for JSON)
39
+ 3. Call it via `EXE` — usually in the data-loading action's `CALLBACK`: `"EXE": "tenHam()"`
40
+ 4. `:attr` in `module.json` only points at the variable: `":option": "optThe"`
41
+
42
+ ❌ **Wrong** — the trailing `;` blanks the page, and the logic belongs in `script.js` anyway:
43
+
44
+ ```json
45
+ ":option": "(function(){ var src = vueData.ds.filter(r => r.id===1); return { series:[{data: src}] }; })();"
46
+ ```
47
+
48
+ ✅ **Right**:
49
+
50
+ ```javascript
51
+ // script.js
52
+ function buildChart() {
53
+ var src = vueData.ds.filter(function (r) {
54
+ return r.id === 1;
55
+ });
56
+ vueData.optThe = { series: [{ data: src }] };
57
+ }
58
+ ```
59
+
60
+ ```json
61
+ // module.json — action nạp dữ liệu
62
+ "CALLBACK": { "EXE": "buildChart()" },
63
+ // module.json — control
64
+ ":option": "optThe"
65
+ ```
66
+
67
+ Declare `:option`'s variable as `{}` in `data[]` so the first render doesn't break; `buildChart()` assigns the real value after the API returns.
68
+
69
+ ### Diagnosing a blank page
70
+
71
+ Not a runtime error — suspect **`:attr` template compilation** first, not `script.js` or the action engine.
72
+
73
+ Isolate: replace a suspect expression with a simple static value (`":option": "{}"` or remove the attr) and re-render. **Page comes back ⇒ that expression is the culprit.** Repeat per suspect `:attr` until one remains.
74
+
75
+ Running `fui module validate` before rendering catches these as errors: it reports every binding that does not parse as one expression.
76
+
77
+ ---
78
+
79
+ ## 2. Functions called in `EXE` / `FUN` must REALLY EXIST
80
+
81
+ **Hard rule.** `"EXE": "buildChart()"` and `"FUN": "buildChart"` work only if `buildChart` is a **real global function** at runtime — declared in `{moduleDir}/script.js`, in an imported `.js` file, or a platform built-in ([default-function.md](default-function.md), [script-map.md](script-map.md)).
82
+
83
+ This is the flip side of §1: moving logic to `script.js` and calling via `EXE` **often loses its second half**. `module.json` is edited, `EXE` written, `fui module publish json` run — but nobody writes `script.js` or runs `fui module publish script`.
84
+
85
+ ### Why nothing tells you
86
+
87
+ Two commands, two failure modes, **neither shows the function name prominently**:
88
+
89
+ | Command | Mechanism | Symptom when missing |
90
+ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
91
+ | `EXE` | Runs through `templateCompiled(\`<% … %>\`)`— lodash`_.template`. A comma-operator bug at `fastproject-3.0.js:490` means **the data object is never passed**, so bare identifiers resolve to **global** | `ReferenceError: buildChart is not defined` — shows only in `fui module simulate --render`, as just **"1 JS error"** in a long report |
92
+ | `FUN` | `runFunction()` looks up `window[obj.FUN]`; if absent, `console.log("Func:", …, "not found")` and **continues** | **Completely silent.** No error, no `[Vue warn]`, the action "finishes" and does nothing |
93
+
94
+ Measured cost: one module burned **36 consecutive `--render` runs over 5 days** on this bug class (`buildKPI8Columns is not defined`).
95
+
96
+ ### The only layer that catches it: **`fui module simulate --render`**
97
+
98
+ `fui module validate` does **NOT** check this: it does not read `script.js`. (A static rule once did, and was removed — to avoid false positives it had to know **every** platform global, a list never complete; each missing name blocked publishing a working module.) `fui module simulate` in vm mode doesn't catch it either — it doesn't load `script.js` into the sandbox, so it reports ReferenceError for **every** module using `script.js` functions, even correct ones.
99
+
100
+ So verify with **`--render`**: the real browser throws `ReferenceError: buildChart is not defined`, and **every JS error makes the command fail (exit 1)** — not only init errors; errors from button clicks count too. The message is in the `═══ DIAGNOSIS ═══` block at the **top** of the report, line `[MODULE]`.
101
+
102
+ ⚠️ **`--render` does not catch the `FUN` case** — `runFunction` just `console.log`s and continues, throwing nothing. For `FUN`, **check function names against `script.js` yourself**; the only symptom is "action finishes, nothing happens".
103
+
104
+ ### Fix
105
+
106
+ 1. Write the function in `script.js`: `function buildChart(){ … vueData.optThe = …; }`
107
+ 2. **`fui module publish script`** — the most-forgotten step. `fui module publish json` does **not** push `script.js`.
108
+ 3. Typo → fix the name; never add an empty function to silence the error.
109
+
110
+ ---
111
+
112
+ ## 3. Advanced Logic & Scripting
113
+
114
+ JSON logic is limited; use `script.js` for complex operations.
115
+
116
+ ### Computed properties workaround
117
+
118
+ `module.json` has no native computed properties. Define calculation functions in `script.js` and call them from `module.json`.
119
+
120
+ **script.js**:
121
+
122
+ ```javascript
123
+ function getTongTien() {
124
+ return vueData.items.reduce((sum, item) => sum + (item.amount || 0), 0);
125
+ }
126
+ ```
127
+
128
+ **module.json**:
129
+
130
+ ```json
131
+ {
132
+ "innerHTML": "Total: {{getTongTien().toLocaleString()}} VNĐ"
133
+ }
134
+ ```
135
+
136
+ ### Complex validation
137
+
138
+ Don't write long logic strings in JSON; move validation to `script.js`.
139
+
140
+ **script.js**:
141
+
142
+ ```javascript
143
+ function validateStep1() {
144
+ const d = vueData;
145
+ if (!d.name || !d.email) {
146
+ alert("Missing required fields!");
147
+ return false;
148
+ }
149
+ return true;
150
+ }
151
+
152
+ function nextStep() {
153
+ if (vueData.step === 1 && !validateStep1()) return;
154
+ vueData.step++;
155
+ }
156
+ ```
157
+
158
+ **module.json**:
159
+
160
+ ```json
161
+ "v-on:click": "nextStep()"
162
+ ```
163
+
164
+ ### Action binding
165
+
166
+ For simple UI logic you may bind JS functions to events directly instead of the `CALL` action protocol.
167
+
168
+ ```json
169
+ "v-on:click": "prevBuoc()"
170
+ ```
@@ -427,10 +427,10 @@ fui component preview uc-invoice-list -p <pid> --cases '[
427
427
 
428
428
  - **Props**: arrays/objects as **real values** (pushed into `data[]`, bound `:prop`). Strings → static attrs; keys starting `:`/`v-` kept verbatim (use `v-on:`/`v-slot:`, **not** `@`/`#`).
429
429
  - **`cases × devices` ≤ 8** (each render = real browser session).
430
- - Also accepted: `slot` (`innerHTML` content), `vueData`, mocks, `user` (test permission gates), `viewport` (force low height to expose self-measuring components). Flags: `fui component preview --help`.
430
+ - Also accepted: `slot` (`innerHTML` content), `vueData`, `apiMocks` (the same map as `--mocks`), `user` (test permission gates), `viewport` (force low height to expose self-measuring components). Flags: `fui component preview --help`.
431
431
  - `scenario` uses **the exact `--render` grammar on the real DOM**: `set`/`click`/`call`/`exe`/`assert`; pick rows with `nth` (no `item`/`index`).
432
432
  - **Module `style.css` NOT loaded** — component must stand on its own `<style>` + project theme.
433
- - Returns: screenshots (max 4 inline, rest as paths) + JS errors + `[Vue warn]` + DOM audit. **Read the images and fix** before pushing.
433
+ - Prints, per case × device: a `screenshot:` path (nothing is attached) + JS errors + `[Vue warn]` + DOM audit. **Open and read the images, failed runs first, and fix** before pushing.
434
434
 
435
435
  ### Project components: MUST push before rendering a module that uses them
436
436
 
@@ -1,78 +1,78 @@
1
- # FUI Component Quick Reference
2
-
3
- > Owns: **FUI component catalog, components needing JS/CSS imports, add/remove import workflow**. Per-component details: file in the right column.
4
-
5
- Prefer `f-*`; use `v-*` only when no FUI equivalent exists.
6
-
7
- | Component | Use for | Reference |
8
- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
9
- | `f-table` | **Any datatable** — CRUD via dialog form or view-only (readonly = omit `:update-api`); auto-builds headers when `:headers` omitted; totals row via `sum-format` | [component-table.md](component-table.md) |
10
- | `f-dialog` | Modal with form, watch, buttons | [components-dialog.md](components-dialog.md) |
11
- | `f-window` | Dialog opening a URL in an iframe | [components-dialog.md](components-dialog.md) |
12
- | `f-button` | Button with action, hotkey, form validation | [components-input.md](components-input.md) |
13
- | `f-date` | Date input with picker + typed mask | [components-input.md](components-input.md) |
14
- | `f-time` | Time input with picker + typed mask | [components-input.md](components-input.md) |
15
- | `f-time-counter` | Countdown / clock | [components-input.md](components-input.md) |
16
- | `f-search` | API-backed autocomplete | [components-input.md](components-input.md) |
17
- | `f-menu` | Dropdown button menu with icon/action/link | [components-input.md](components-input.md) |
18
- | `f-radiobox` | Radio group from items array | [components-input.md](components-input.md) |
19
- | `f-file-upload` | File upload (Plupload, progress dialog) | [components-input.md](components-input.md) |
20
- | `f-image-update` | Image upload + crop | [components-input.md](components-input.md) |
21
- | `f-excel-reader` | Excel/CSV → JSON (pick sheet, skip first N rows, name columns) | [components-input.md](components-input.md) |
22
- | `f-qrcode` | Render QR code | [components-input.md](components-input.md) |
23
- | `f-qrcode-reader` | Read QR via camera | [components-input.md](components-input.md) |
24
- | `f-editor` | Rich text editor (CKEditor 5) | [components-dialog.md](components-dialog.md) |
25
- | `f-editor-dialog` | Rich text editor in a modal | [components-dialog.md](components-dialog.md) |
26
- | `f-echart` | **Charts** — ECharts V5: bar, line, pie, scatter, gauge, radar, heatmap, sankey, tree, map, graph... | [components-echart.md](components-echart.md) · [echart-templates.md](echart-templates.md) |
27
- | `f-sheet` | **Excel-like in-grid editing** — edit cells in place, paste from Excel, no dialog (AG Grid) — **needs import** | [fsheet.md](fsheet.md) |
28
- | `f-pdfmake` | Render PDF in iframe | [components-display.md](components-display.md) · [pdfmake.md](pdfmake.md) |
29
- | `f-label` | Chip/badge for tags, status | [components-display.md](components-display.md) |
30
- | `f-box` | Display/edit key-value rows | [components-display.md](components-display.md) |
31
- | `f-header` | Large heading (display-1, primary color) | [components-display.md](components-display.md) |
32
- | `f-title` | Small heading (title, primary color) | [components-display.md](components-display.md) |
33
- | `f-slider` | Image carousel | [components-display.md](components-display.md) |
34
- | `fp-profile` | User info/profile block | [components-display.md](components-display.md) |
35
-
36
- ### Table-cell components (`t-*`) — used in f-table `headers`
37
-
38
- `t-html` · `t-label` · `t-num` · `t-time` · `t-boolean` · `t-check` (toggle) · `t-text` · `t-select` · `t-combobox` · `t-menu` (context menu) · `t-link` · `t-button` — details: [ui-table-cell-patterns.md](ui-table-cell-patterns.md).
39
-
40
- > `header-bar` and `f-window` are internal, runtime-built (header menu, `openWindow` window) — never place them directly in `controls`.
41
-
42
- ## Components needing JS/CSS imports
43
-
44
- **When adding or removing one of these, run `fui import list` and add/remove the matching imports.**
45
-
46
- | Component | Required imports |
47
- | ----------------- | -------------------------------------------------------------------------------------------------------- |
48
- | `f-pdfmake` | `/include/pdfmake/pdfmake.min.js` · `/include/pdfmake/print.min.js` · `/include/pdfmake/vfs_fonts.js` |
49
- | `f-file-upload` | `/include/plupload-2.3.7/plupload.full.min.js` |
50
- | `f-image-update` | `/include/vue-advanced-cropper/index.umd.js` · `/include/vue-advanced-cropper/style.css` |
51
- | `f-qrcode` | `/include/qrcode/qrcode.min.js` |
52
- | `f-qrcode-reader` | `/include/qrcode/qrcode-reader.min.js` |
53
- | `f-echart` | `/include/chart/echarts.min.js` · `/include/chart/fechart.js` (**in this order**) — Apache ECharts |
54
- | `f-sheet` | `/include/ag-grid/ag-grid-community.min.js` · `/include/ag-grid/fsheet.js` (**in this order**) — AG Grid |
55
- | `f-editor` | `/include/ckeditor5/build/ckeditor.js` |
56
- | `f-editor-dialog` | `/include/ckeditor5/build/ckeditor.js` |
57
-
58
- > **Bundled, NO import needed:** `v-*` (Vuetify) · `f-table` · `f-dialog` · `f-button` ·
59
- > `f-date` · `f-time` · `f-search` · `f-menu` · `f-radiobox` · `f-box` · `f-label` · `f-header` ·
60
- > `f-title` · `f-slider` · `f-excel-reader` — and any component not in the table above.
61
-
62
- **Workflow when adding a component with imports** (see `fui import --help`):
63
-
64
- 1. `fui import list` (project + module) — check existing imports
65
- 2. Missing → `fui import new` for each file
66
- 3. Removing a component → check whether the import is still used elsewhere; if not → `fui import delete`
67
-
68
- ---
69
-
70
- ## Quick selection rules
71
-
72
- - `f-button` over `v-btn` when you need FUI actions (CALL, hotkey, form validation)
73
- - `f-date` / `f-time` over `v-text-field` + manual date parsing
74
- - `f-search` over `v-autocomplete` for API search
75
- - `f-menu` over `v-menu + v-btn` for dropdown actions
76
- - `f-table` over `v-data-table` for EVERY table — CRUD and view-only (readonly = omit `:update-api`)
77
- - `f-echart` for every chart type (bar, line, pie, gauge, scatter, radar, sankey, tree, map...)
78
- - Dialogs: `f-table` `ctrl-update` for inline CRUD; standalone dialog → hand-build `v-dialog` per the standard anatomy (`fui design read fui` §4 + `ui-dialog-patterns.md`); `f-dialog` only for very small forms
1
+ # FUI Component Quick Reference
2
+
3
+ > Owns: **FUI component catalog, components needing JS/CSS imports, add/remove import workflow**. Per-component details: file in the right column.
4
+
5
+ Prefer `f-*`; use `v-*` only when no FUI equivalent exists.
6
+
7
+ | Component | Use for | Reference |
8
+ | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
9
+ | `f-table` | **Any datatable** — CRUD via dialog form or view-only (readonly = omit `:update-api`); auto-builds headers when `:headers` omitted; totals row via `sum-format` | [component-table.md](component-table.md) |
10
+ | `f-dialog` | Modal with form, watch, buttons | [components-dialog.md](components-dialog.md) |
11
+ | `f-window` | Dialog opening a URL in an iframe | [components-dialog.md](components-dialog.md) |
12
+ | `f-button` | Button with action, hotkey, form validation | [components-input.md](components-input.md) |
13
+ | `f-date` | Date input with picker + typed mask | [components-input.md](components-input.md) |
14
+ | `f-time` | Time input with picker + typed mask | [components-input.md](components-input.md) |
15
+ | `f-time-counter` | Countdown / clock | [components-input.md](components-input.md) |
16
+ | `f-search` | API-backed autocomplete | [components-input.md](components-input.md) |
17
+ | `f-menu` | Dropdown button menu with icon/action/link | [components-input.md](components-input.md) |
18
+ | `f-radiobox` | Radio group from items array | [components-input.md](components-input.md) |
19
+ | `f-file-upload` | File upload (Plupload, progress dialog) | [components-input.md](components-input.md) |
20
+ | `f-image-update` | Image upload + crop | [components-input.md](components-input.md) |
21
+ | `f-excel-reader` | Excel/CSV → JSON (pick sheet, skip first N rows, name columns) | [components-input.md](components-input.md) |
22
+ | `f-qrcode` | Render QR code | [components-input.md](components-input.md) |
23
+ | `f-qrcode-reader` | Read QR via camera | [components-input.md](components-input.md) |
24
+ | `f-editor` | Rich text editor (CKEditor 5) | [components-dialog.md](components-dialog.md) |
25
+ | `f-editor-dialog` | Rich text editor in a modal | [components-dialog.md](components-dialog.md) |
26
+ | `f-echart` | **Charts** — ECharts V5: bar, line, pie, scatter, gauge, radar, heatmap, sankey, tree, map, graph... | [components-echart.md](components-echart.md) · [echart-templates.md](echart-templates.md) |
27
+ | `f-sheet` | **Excel-like in-grid editing** — edit cells in place, paste from Excel, no dialog (AG Grid) — **needs import** | [fsheet.md](fsheet.md) |
28
+ | `f-pdfmake` | Render PDF in iframe | [components-display.md](components-display.md) · [pdfmake.md](pdfmake.md) |
29
+ | `f-label` | Chip/badge for tags, status | [components-display.md](components-display.md) |
30
+ | `f-box` | Display/edit key-value rows | [components-display.md](components-display.md) |
31
+ | `f-header` | Large heading (display-1, primary color) | [components-display.md](components-display.md) |
32
+ | `f-title` | Small heading (title, primary color) | [components-display.md](components-display.md) |
33
+ | `f-slider` | Image carousel | [components-display.md](components-display.md) |
34
+ | `fp-profile` | User info/profile block | [components-display.md](components-display.md) |
35
+
36
+ ### Table-cell components (`t-*`) — used in f-table `headers`
37
+
38
+ `t-html` · `t-label` · `t-num` · `t-time` · `t-boolean` · `t-check` (toggle) · `t-text` · `t-select` · `t-combobox` · `t-menu` (context menu) · `t-link` · `t-button` — details: [ui-table-cell-patterns.md](ui-table-cell-patterns.md).
39
+
40
+ > `header-bar` and `f-window` are internal, runtime-built (header menu, `openWindow` window) — never place them directly in `controls`.
41
+
42
+ ## Components needing JS/CSS imports
43
+
44
+ **When adding or removing one of these, run `fui import list` and add/remove the matching imports.**
45
+
46
+ | Component | Required imports |
47
+ | ----------------- | -------------------------------------------------------------------------------------------------------- |
48
+ | `f-pdfmake` | `/include/pdfmake/pdfmake.min.js` · `/include/pdfmake/print.min.js` · `/include/pdfmake/vfs_fonts.js` |
49
+ | `f-file-upload` | `/include/plupload-2.3.7/plupload.full.min.js` |
50
+ | `f-image-update` | `/include/vue-advanced-cropper/index.umd.js` · `/include/vue-advanced-cropper/style.css` |
51
+ | `f-qrcode` | `/include/qrcode/qrcode.min.js` |
52
+ | `f-qrcode-reader` | `/include/qrcode/qrcode-reader.min.js` |
53
+ | `f-echart` | `/include/chart/echarts.min.js` · `/include/chart/fechart.js` (**in this order**) — Apache ECharts |
54
+ | `f-sheet` | `/include/ag-grid/ag-grid-community.min.js` · `/include/ag-grid/fsheet.js` (**in this order**) — AG Grid |
55
+ | `f-editor` | `/include/ckeditor5/build/ckeditor.js` |
56
+ | `f-editor-dialog` | `/include/ckeditor5/build/ckeditor.js` |
57
+
58
+ > **Bundled, NO import needed:** `v-*` (Vuetify) · `f-table` · `f-dialog` · `f-button` ·
59
+ > `f-date` · `f-time` · `f-search` · `f-menu` · `f-radiobox` · `f-box` · `f-label` · `f-header` ·
60
+ > `f-title` · `f-slider` · `f-excel-reader` — and any component not in the table above.
61
+
62
+ **Workflow when adding a component with imports** (see `fui import --help`):
63
+
64
+ 1. `fui import list` (project + module) — check existing imports
65
+ 2. Missing → `fui import new` for each file
66
+ 3. Removing a component → check whether the import is still used elsewhere; if not → `fui import delete`
67
+
68
+ ---
69
+
70
+ ## Quick selection rules
71
+
72
+ - `f-button` over `v-btn` when you need FUI actions (CALL, hotkey, form validation)
73
+ - `f-date` / `f-time` over `v-text-field` + manual date parsing
74
+ - `f-search` over `v-autocomplete` for API search
75
+ - `f-menu` over `v-menu + v-btn` for dropdown actions
76
+ - `f-table` over `v-data-table` for EVERY table — CRUD and view-only (readonly = omit `:update-api`)
77
+ - `f-echart` for every chart type (bar, line, pie, gauge, scatter, radar, sankey, tree, map...)
78
+ - Dialogs: `f-table` `ctrl-update` for inline CRUD; standalone dialog → hand-build `v-dialog` per the standard anatomy (`fui design read fui` §4 + `ui-dialog-patterns.md`); `f-dialog` only for very small forms