@fui-org/fui-cli 2.1.4 → 2.2.1

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 (214) hide show
  1. package/README.md +16 -7
  2. package/dist/fui-xg17j3f9.js +396 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +1 -1
  5. package/skills/fui/SKILL.md +152 -39
  6. package/skills/{fui-skill → fui}/assets/projectdefaultstyle.css +489 -489
  7. package/skills/{fui-skill → fui}/examples/component.vue +162 -162
  8. package/skills/{fui-skill → fui}/references/INDEX.md +4 -5
  9. package/skills/{fui-skill → fui}/references/advanced-techniques.md +170 -168
  10. package/skills/{fui-skill → fui}/references/component-design.md +2 -2
  11. package/skills/{fui-skill → fui}/references/component-quickref.md +78 -78
  12. package/skills/{fui-skill → fui}/references/component-table.md +287 -287
  13. package/skills/{fui-skill → fui}/references/components-dialog.md +191 -191
  14. package/skills/{fui-skill → fui}/references/components-display.md +141 -141
  15. package/skills/{fui-skill → fui}/references/components-echart.md +316 -316
  16. package/skills/{fui-skill → fui}/references/components-input.md +335 -335
  17. package/skills/{fui-skill → fui}/references/controls-patterns.md +2 -2
  18. package/skills/{fui-skill → fui}/references/controls-styling-vocabulary.md +173 -173
  19. package/skills/{fui-skill → fui}/references/db-workflow.md +9 -9
  20. package/skills/{fui-skill → fui}/references/default-function.md +456 -456
  21. package/skills/{fui-skill → fui}/references/design-modes.md +57 -57
  22. package/skills/{fui-skill → fui}/references/echart-templates.md +489 -489
  23. package/skills/{fui-skill → fui}/references/fastproject.md +99 -99
  24. package/skills/{fui-skill → fui}/references/fullstack-workflow.md +314 -313
  25. package/skills/{fui-skill → fui}/references/module-data-patterns.md +117 -117
  26. package/skills/{fui-skill → fui}/references/module-json-anatomy.md +132 -132
  27. package/skills/{fui-skill → fui}/references/module-structure.md +144 -144
  28. package/skills/{fui-skill → fui}/references/new-session.md +3 -20
  29. package/skills/{fui-skill → fui}/references/pdfmake.md +60 -60
  30. package/skills/{fui-skill → fui}/references/permission-system.md +1 -1
  31. package/skills/{fui-skill → fui}/references/platform-architecture.md +269 -269
  32. package/skills/{fui-skill → fui}/references/project-config.md +303 -303
  33. package/skills/{fui-skill → fui}/references/project-provisioning.md +4 -4
  34. package/skills/{fui-skill → fui}/references/script-map.md +262 -262
  35. package/skills/{fui-skill → fui}/references/sql-clr-functions.md +225 -225
  36. package/skills/{fui-skill → fui}/references/system-design.md +3 -3
  37. package/skills/{fui-skill → fui}/references/tapi-permission-patterns.md +156 -156
  38. package/skills/{fui-skill → fui}/references/tapi-reference.md +474 -474
  39. package/skills/fui/references/tools-registry.md +214 -0
  40. package/skills/{fui-skill → fui}/references/ui-crosswindow-patterns.md +321 -321
  41. package/skills/{fui-skill → fui}/references/ui-dialog-patterns.md +255 -255
  42. package/skills/{fui-skill → fui}/references/ui-layout-patterns.md +176 -176
  43. package/skills/{fui-skill → fui}/references/ui-patterns.md +303 -303
  44. package/skills/{fui-skill → fui}/references/ui-screenshot-review.md +95 -95
  45. package/skills/{fui-skill → fui}/references/ui-table-cell-patterns.md +318 -318
  46. package/skills/{fui-skill → fui}/references/verification.md +18 -18
  47. package/skills/{fui-skill → fui}/references/watcher-patterns.md +163 -163
  48. package/skills/{fui-skill → fui}/references/websocket-realtime.md +271 -271
  49. package/skills/{fui-skill → fui}/scripts/component-3.0.js +2715 -2715
  50. package/skills/{fui-skill → fui}/scripts/component.js +3147 -3147
  51. package/skills/{fui-skill → fui}/scripts/componentTable-3.0.js +1038 -1038
  52. package/skills/{fui-skill → fui}/scripts/componentTable.js +891 -891
  53. package/skills/{fui-skill → fui}/scripts/defaultfunction-3.0.js +866 -866
  54. package/skills/{fui-skill → fui}/scripts/defaultfunction.js +1051 -1051
  55. package/skills/{fui-skill → fui}/scripts/fastproject-3.0.js +870 -870
  56. package/skills/{fui-skill → fui}/scripts/fastproject.js +828 -828
  57. package/dist/fui-h4z7zhk2.js +0 -381
  58. package/skills/fui-skill/SKILL.md +0 -139
  59. package/skills/fui-skill/references/tools-registry.md +0 -84
  60. /package/skills/{fui-skill → fui}/assets/projectdefaultstyle-3.0.css +0 -0
  61. /package/skills/{fui-skill → fui}/design-md/airbnb/DESIGN.md +0 -0
  62. /package/skills/{fui-skill → fui}/design-md/airbnb/README.md +0 -0
  63. /package/skills/{fui-skill → fui}/design-md/airtable/DESIGN.md +0 -0
  64. /package/skills/{fui-skill → fui}/design-md/airtable/README.md +0 -0
  65. /package/skills/{fui-skill → fui}/design-md/apple/DESIGN.md +0 -0
  66. /package/skills/{fui-skill → fui}/design-md/apple/README.md +0 -0
  67. /package/skills/{fui-skill → fui}/design-md/asu/DESIGN.md +0 -0
  68. /package/skills/{fui-skill → fui}/design-md/asu/README.md +0 -0
  69. /package/skills/{fui-skill → fui}/design-md/binance/DESIGN.md +0 -0
  70. /package/skills/{fui-skill → fui}/design-md/binance/README.md +0 -0
  71. /package/skills/{fui-skill → fui}/design-md/bmw/DESIGN.md +0 -0
  72. /package/skills/{fui-skill → fui}/design-md/bmw/README.md +0 -0
  73. /package/skills/{fui-skill → fui}/design-md/bmw-m/DESIGN.md +0 -0
  74. /package/skills/{fui-skill → fui}/design-md/bmw-m/README.md +0 -0
  75. /package/skills/{fui-skill → fui}/design-md/bugatti/DESIGN.md +0 -0
  76. /package/skills/{fui-skill → fui}/design-md/bugatti/README.md +0 -0
  77. /package/skills/{fui-skill → fui}/design-md/cal/DESIGN.md +0 -0
  78. /package/skills/{fui-skill → fui}/design-md/cal/README.md +0 -0
  79. /package/skills/{fui-skill → fui}/design-md/claude/DESIGN.md +0 -0
  80. /package/skills/{fui-skill → fui}/design-md/claude/README.md +0 -0
  81. /package/skills/{fui-skill → fui}/design-md/clay/DESIGN.md +0 -0
  82. /package/skills/{fui-skill → fui}/design-md/clay/README.md +0 -0
  83. /package/skills/{fui-skill → fui}/design-md/clickhouse/DESIGN.md +0 -0
  84. /package/skills/{fui-skill → fui}/design-md/clickhouse/README.md +0 -0
  85. /package/skills/{fui-skill → fui}/design-md/cohere/DESIGN.md +0 -0
  86. /package/skills/{fui-skill → fui}/design-md/cohere/README.md +0 -0
  87. /package/skills/{fui-skill → fui}/design-md/coinbase/DESIGN.md +0 -0
  88. /package/skills/{fui-skill → fui}/design-md/coinbase/README.md +0 -0
  89. /package/skills/{fui-skill → fui}/design-md/composio/DESIGN.md +0 -0
  90. /package/skills/{fui-skill → fui}/design-md/composio/README.md +0 -0
  91. /package/skills/{fui-skill → fui}/design-md/cursor/DESIGN.md +0 -0
  92. /package/skills/{fui-skill → fui}/design-md/cursor/README.md +0 -0
  93. /package/skills/{fui-skill → fui}/design-md/elevenlabs/DESIGN.md +0 -0
  94. /package/skills/{fui-skill → fui}/design-md/elevenlabs/README.md +0 -0
  95. /package/skills/{fui-skill → fui}/design-md/expo/DESIGN.md +0 -0
  96. /package/skills/{fui-skill → fui}/design-md/expo/README.md +0 -0
  97. /package/skills/{fui-skill → fui}/design-md/ferrari/DESIGN.md +0 -0
  98. /package/skills/{fui-skill → fui}/design-md/ferrari/README.md +0 -0
  99. /package/skills/{fui-skill → fui}/design-md/figma/DESIGN.md +0 -0
  100. /package/skills/{fui-skill → fui}/design-md/figma/README.md +0 -0
  101. /package/skills/{fui-skill → fui}/design-md/framer/DESIGN.md +0 -0
  102. /package/skills/{fui-skill → fui}/design-md/framer/README.md +0 -0
  103. /package/skills/{fui-skill → fui}/design-md/fui/DESIGN.md +0 -0
  104. /package/skills/{fui-skill → fui}/design-md/hashicorp/DESIGN.md +0 -0
  105. /package/skills/{fui-skill → fui}/design-md/hashicorp/README.md +0 -0
  106. /package/skills/{fui-skill → fui}/design-md/ibm/DESIGN.md +0 -0
  107. /package/skills/{fui-skill → fui}/design-md/ibm/README.md +0 -0
  108. /package/skills/{fui-skill → fui}/design-md/intercom/DESIGN.md +0 -0
  109. /package/skills/{fui-skill → fui}/design-md/intercom/README.md +0 -0
  110. /package/skills/{fui-skill → fui}/design-md/kraken/DESIGN.md +0 -0
  111. /package/skills/{fui-skill → fui}/design-md/kraken/README.md +0 -0
  112. /package/skills/{fui-skill → fui}/design-md/lamborghini/DESIGN.md +0 -0
  113. /package/skills/{fui-skill → fui}/design-md/lamborghini/README.md +0 -0
  114. /package/skills/{fui-skill → fui}/design-md/linear.app/DESIGN.md +0 -0
  115. /package/skills/{fui-skill → fui}/design-md/linear.app/README.md +0 -0
  116. /package/skills/{fui-skill → fui}/design-md/lovable/DESIGN.md +0 -0
  117. /package/skills/{fui-skill → fui}/design-md/lovable/README.md +0 -0
  118. /package/skills/{fui-skill → fui}/design-md/mastercard/DESIGN.md +0 -0
  119. /package/skills/{fui-skill → fui}/design-md/mastercard/README.md +0 -0
  120. /package/skills/{fui-skill → fui}/design-md/meta/DESIGN.md +0 -0
  121. /package/skills/{fui-skill → fui}/design-md/meta/README.md +0 -0
  122. /package/skills/{fui-skill → fui}/design-md/minimax/DESIGN.md +0 -0
  123. /package/skills/{fui-skill → fui}/design-md/minimax/README.md +0 -0
  124. /package/skills/{fui-skill → fui}/design-md/mintlify/DESIGN.md +0 -0
  125. /package/skills/{fui-skill → fui}/design-md/mintlify/README.md +0 -0
  126. /package/skills/{fui-skill → fui}/design-md/miro/DESIGN.md +0 -0
  127. /package/skills/{fui-skill → fui}/design-md/miro/README.md +0 -0
  128. /package/skills/{fui-skill → fui}/design-md/mistral.ai/DESIGN.md +0 -0
  129. /package/skills/{fui-skill → fui}/design-md/mistral.ai/README.md +0 -0
  130. /package/skills/{fui-skill → fui}/design-md/mongodb/DESIGN.md +0 -0
  131. /package/skills/{fui-skill → fui}/design-md/mongodb/README.md +0 -0
  132. /package/skills/{fui-skill → fui}/design-md/nike/DESIGN.md +0 -0
  133. /package/skills/{fui-skill → fui}/design-md/nike/README.md +0 -0
  134. /package/skills/{fui-skill → fui}/design-md/notion/DESIGN.md +0 -0
  135. /package/skills/{fui-skill → fui}/design-md/notion/README.md +0 -0
  136. /package/skills/{fui-skill → fui}/design-md/nvidia/DESIGN.md +0 -0
  137. /package/skills/{fui-skill → fui}/design-md/nvidia/README.md +0 -0
  138. /package/skills/{fui-skill → fui}/design-md/ollama/DESIGN.md +0 -0
  139. /package/skills/{fui-skill → fui}/design-md/ollama/README.md +0 -0
  140. /package/skills/{fui-skill → fui}/design-md/opencode.ai/DESIGN.md +0 -0
  141. /package/skills/{fui-skill → fui}/design-md/opencode.ai/README.md +0 -0
  142. /package/skills/{fui-skill → fui}/design-md/pinterest/DESIGN.md +0 -0
  143. /package/skills/{fui-skill → fui}/design-md/pinterest/README.md +0 -0
  144. /package/skills/{fui-skill → fui}/design-md/playstation/DESIGN.md +0 -0
  145. /package/skills/{fui-skill → fui}/design-md/playstation/README.md +0 -0
  146. /package/skills/{fui-skill → fui}/design-md/posthog/DESIGN.md +0 -0
  147. /package/skills/{fui-skill → fui}/design-md/posthog/README.md +0 -0
  148. /package/skills/{fui-skill → fui}/design-md/raycast/DESIGN.md +0 -0
  149. /package/skills/{fui-skill → fui}/design-md/raycast/README.md +0 -0
  150. /package/skills/{fui-skill → fui}/design-md/renault/DESIGN.md +0 -0
  151. /package/skills/{fui-skill → fui}/design-md/renault/README.md +0 -0
  152. /package/skills/{fui-skill → fui}/design-md/replicate/DESIGN.md +0 -0
  153. /package/skills/{fui-skill → fui}/design-md/replicate/README.md +0 -0
  154. /package/skills/{fui-skill → fui}/design-md/resend/DESIGN.md +0 -0
  155. /package/skills/{fui-skill → fui}/design-md/resend/README.md +0 -0
  156. /package/skills/{fui-skill → fui}/design-md/revolut/DESIGN.md +0 -0
  157. /package/skills/{fui-skill → fui}/design-md/revolut/README.md +0 -0
  158. /package/skills/{fui-skill → fui}/design-md/runwayml/DESIGN.md +0 -0
  159. /package/skills/{fui-skill → fui}/design-md/runwayml/README.md +0 -0
  160. /package/skills/{fui-skill → fui}/design-md/sanity/DESIGN.md +0 -0
  161. /package/skills/{fui-skill → fui}/design-md/sanity/README.md +0 -0
  162. /package/skills/{fui-skill → fui}/design-md/sentry/DESIGN.md +0 -0
  163. /package/skills/{fui-skill → fui}/design-md/sentry/README.md +0 -0
  164. /package/skills/{fui-skill → fui}/design-md/shopify/DESIGN.md +0 -0
  165. /package/skills/{fui-skill → fui}/design-md/shopify/README.md +0 -0
  166. /package/skills/{fui-skill → fui}/design-md/slack/DESIGN.md +0 -0
  167. /package/skills/{fui-skill → fui}/design-md/spacex/DESIGN.md +0 -0
  168. /package/skills/{fui-skill → fui}/design-md/spacex/README.md +0 -0
  169. /package/skills/{fui-skill → fui}/design-md/spotify/DESIGN.md +0 -0
  170. /package/skills/{fui-skill → fui}/design-md/spotify/README.md +0 -0
  171. /package/skills/{fui-skill → fui}/design-md/starbucks/DESIGN.md +0 -0
  172. /package/skills/{fui-skill → fui}/design-md/starbucks/README.md +0 -0
  173. /package/skills/{fui-skill → fui}/design-md/stripe/DESIGN.md +0 -0
  174. /package/skills/{fui-skill → fui}/design-md/stripe/README.md +0 -0
  175. /package/skills/{fui-skill → fui}/design-md/supabase/DESIGN.md +0 -0
  176. /package/skills/{fui-skill → fui}/design-md/supabase/README.md +0 -0
  177. /package/skills/{fui-skill → fui}/design-md/superhuman/DESIGN.md +0 -0
  178. /package/skills/{fui-skill → fui}/design-md/superhuman/README.md +0 -0
  179. /package/skills/{fui-skill → fui}/design-md/tesla/DESIGN.md +0 -0
  180. /package/skills/{fui-skill → fui}/design-md/tesla/README.md +0 -0
  181. /package/skills/{fui-skill → fui}/design-md/theverge/DESIGN.md +0 -0
  182. /package/skills/{fui-skill → fui}/design-md/theverge/README.md +0 -0
  183. /package/skills/{fui-skill → fui}/design-md/together.ai/DESIGN.md +0 -0
  184. /package/skills/{fui-skill → fui}/design-md/together.ai/README.md +0 -0
  185. /package/skills/{fui-skill → fui}/design-md/uber/DESIGN.md +0 -0
  186. /package/skills/{fui-skill → fui}/design-md/uber/README.md +0 -0
  187. /package/skills/{fui-skill → fui}/design-md/vercel/DESIGN.md +0 -0
  188. /package/skills/{fui-skill → fui}/design-md/vercel/README.md +0 -0
  189. /package/skills/{fui-skill → fui}/design-md/vodafone/DESIGN.md +0 -0
  190. /package/skills/{fui-skill → fui}/design-md/vodafone/README.md +0 -0
  191. /package/skills/{fui-skill → fui}/design-md/voltagent/DESIGN.md +0 -0
  192. /package/skills/{fui-skill → fui}/design-md/voltagent/README.md +0 -0
  193. /package/skills/{fui-skill → fui}/design-md/warp/DESIGN.md +0 -0
  194. /package/skills/{fui-skill → fui}/design-md/warp/README.md +0 -0
  195. /package/skills/{fui-skill → fui}/design-md/webflow/DESIGN.md +0 -0
  196. /package/skills/{fui-skill → fui}/design-md/webflow/README.md +0 -0
  197. /package/skills/{fui-skill → fui}/design-md/wired/DESIGN.md +0 -0
  198. /package/skills/{fui-skill → fui}/design-md/wired/README.md +0 -0
  199. /package/skills/{fui-skill → fui}/design-md/wise/DESIGN.md +0 -0
  200. /package/skills/{fui-skill → fui}/design-md/wise/README.md +0 -0
  201. /package/skills/{fui-skill → fui}/design-md/x.ai/DESIGN.md +0 -0
  202. /package/skills/{fui-skill → fui}/design-md/x.ai/README.md +0 -0
  203. /package/skills/{fui-skill → fui}/design-md/zapier/DESIGN.md +0 -0
  204. /package/skills/{fui-skill → fui}/design-md/zapier/README.md +0 -0
  205. /package/skills/{fui-skill → fui}/examples/f-table-patterns.json +0 -0
  206. /package/skills/{fui-skill → fui}/examples/module-patterns.json +0 -0
  207. /package/skills/{fui-skill → fui}/examples/project-patterns.json +0 -0
  208. /package/skills/{fui-skill → fui}/references/coding-standards.md +0 -0
  209. /package/skills/{fui-skill → fui}/references/db-table-design.md +0 -0
  210. /package/skills/{fui-skill → fui}/references/fsheet.md +0 -0
  211. /package/skills/{fui-skill → fui}/references/tapi-file-api.md +0 -0
  212. /package/skills/{fui-skill → fui}/references/ui-templates.md +0 -0
  213. /package/skills/{fui-skill → fui}/scripts/fechart.js +0 -0
  214. /package/skills/{fui-skill → fui}/scripts/fsheet.js +0 -0
@@ -1,318 +1,318 @@
1
- # FUI Table Cell Patterns — f-table & in-cell controls
2
-
3
- > Owns: **in-cell `f-table` controls (`t-*`), `ctrl-update`, show-select, chip-group, `t-button` vs `t-menu`**. Table props: [component-table.md](component-table.md).
4
-
5
- Patterns for `f-table` and in-cell controls (`t-check`, `t-button`, `t-select`, `t-menu`, `ctrl-update`, `show-select`, `v-chip-group`), from project **security-manager**.
6
-
7
- > See also: [ui-patterns.md](ui-patterns.md) (data/watch/toolbar), [ui-dialog-patterns.md](ui-dialog-patterns.md), [component-table.md](component-table.md).
8
-
9
- ---
10
-
11
- ## 1. Basic f-table with fixed header
12
-
13
- ```json
14
- {
15
- "el": "f-table",
16
- "attr": {
17
- "label": "User list",
18
- ":items-per-page": 50,
19
- ":height": -16,
20
- ":items": "dsUser",
21
- "item-key": "UserID",
22
- ":hide-default-footer": false,
23
- ":item-class": "item => item.ChuaKichHoat>0 ? 'danger' : ''",
24
- ":headers": [
25
- { "align": "center", "text": "UserID", "value": "UserID" },
26
- { "text": "Username", "value": "UserName" },
27
- { "text": "Fullname", "value": "FullName" }
28
- ]
29
- },
30
- "w": 12
31
- }
32
- ```
33
-
34
- - **Table height RULE (lint D9)**: the module's main data table declares `":height": -16` — f-table **measures its real position** after layout (`getBoundingClientRect().top`), fills to the screen bottom leaving 16px, and enables `fixed-header`. Data scrolls **inside the table** only, header stays put, no nested page scrollbars. Updates on window resize and when `items` changes.
35
-
36
- | `:height` | Behavior |
37
- | ----------- | ----------------------------------------------------------------------------------------------------- |
38
- | _(omitted)_ | Grows with row count — intentional short/lookup tables; wrong for the main table (whole page scrolls) |
39
- | `<= 0` | Fill to bottom leaving `abs(height)` px — **standard for main table** |
40
- | `> 0` | Fixed px — **table inside a dialog** (e.g. `":height": 360`) |
41
-
42
- Same three modes apply to `f-sheet` — see [fsheet.md](fsheet.md) §Height.
43
-
44
- ⚠ Old pattern `":height": "$( window ).height()-285"` is **deprecated** — it forces guessing total toolbar/filter/menu height; wrong guess = short or overflowing. It returns a **positive** number so it still works as fixed px (doesn't break) but loses auto-measure; lint D9 warns so you replace it with `-16`.
45
-
46
- - `:item-class`: conditional row highlight — `"item => item.Active==0 ? 'danger' : ''"`
47
-
48
- ---
49
-
50
- ## 2. t-check — toggle in cell
51
-
52
- In `headers`, renders a checkbox/icon toggle that fires an API on click.
53
-
54
- ```json
55
- {
56
- "text": "Active",
57
- "value": "Enable",
58
- "align": "center",
59
- "el": "t-check",
60
- "attr": {
61
- "on-icon": "mdi-check",
62
- "off-icon": "mdi-lock",
63
- ":action": [
64
- { "API": "/SM_Users_SetActive", "IN": { "UserID": "item.UserID" } },
65
- { "dsUser": [] },
66
- { "CALL": "getUser" }
67
- ]
68
- }
69
- }
70
- ```
71
-
72
- ---
73
-
74
- ## 3. t-button — button in cell
75
-
76
- Button/icon with an action in a cell; supports dynamic icons.
77
-
78
- ```json
79
- {
80
- "text": "Allow",
81
- "value": "Locked",
82
- "align": "center",
83
- "el": "t-button",
84
- "attr": {
85
- "color": "primary",
86
- ":outlined": false,
87
- ":icon-text": "`${ item.Locked==0 ? 'mdi-check-bold':'mdi-lock'}`",
88
- ":action": [
89
- { "API": "/SM_Computer_SetLocked", "IN": { "ComputerID": "item.ComputerID" } },
90
- { "dsComputer": [] },
91
- { "CALL": "getComputer" }
92
- ]
93
- }
94
- }
95
- ```
96
-
97
- ---
98
-
99
- ## 4. t-select — inline dropdown in cell
100
-
101
- Edit a field in the table; fires an API on selection.
102
-
103
- ```json
104
- {
105
- "text": "SystemRight",
106
- "value": "SysRight",
107
- "el": "t-select",
108
- "width": "250px",
109
- "attr": {
110
- "class": "flex-md-grow-0 my-2",
111
- ":items": "vueData.dsSystemRight",
112
- "item-text": "Note",
113
- "item-value": "SysRight",
114
- ":action": [
115
- {
116
- "CONFIRM": "Bạn có chắc cập nhật System Right cho user này không?",
117
- "API": "/SM_UserModule_UpdateSystemRight",
118
- "IN": {
119
- "ModuleID": "sModuleID",
120
- "UserID": "item.UserID",
121
- "SysRight": "item.SysRight"
122
- },
123
- "CALLBACK": { "MESS": "Cập nhật thành công." }
124
- }
125
- ]
126
- }
127
- }
128
- ```
129
-
130
- ---
131
-
132
- ## 5. t-menu — context menu in table (menuChucNang)
133
-
134
- Define menu items in `data[]`, reference via `t-menu` in headers.
135
-
136
- **Step 1 — `menuChucNang` in `data[]`:**
137
-
138
- ```json
139
- {
140
- "menuChucNang": [
141
- {
142
- "color": "primary",
143
- "icon-text": "mdi-account-details",
144
- "text": "Update Info",
145
- "action": [
146
- {
147
- "addNew": 0,
148
- "dongChon": "item",
149
- "sUserID": "item.UserID",
150
- "sUserName": "item.UserName",
151
- "sLastName": "item.LastName",
152
- "sFirstName": "item.FirstName"
153
- },
154
- { "dlUserInfo": true }
155
- ]
156
- },
157
- {
158
- "color": "primary",
159
- "icon-text": "mdi-shield-account-outline",
160
- "text": "User Permission",
161
- "action": [
162
- {
163
- "dongChon": "item",
164
- "sUserID": "item.UserID",
165
- "sFullName": "item.FullName"
166
- },
167
- {
168
- "FUN": "openWindow",
169
- "IN": {
170
- "id": "`WinPer",
171
- "title": "`User Permission",
172
- "url": "`/UserPermission"
173
- }
174
- }
175
- ]
176
- }
177
- ]
178
- }
179
- ```
180
-
181
- **Step 2 — `t-menu` in `headers`:**
182
-
183
- ```json
184
- {
185
- "el": "t-menu",
186
- "width": "120px",
187
- "align": "center",
188
- "text": "Update",
189
- "value": "Update",
190
- "attr": { ":items": "vueData.menuChucNang" }
191
- }
192
- ```
193
-
194
- - `"dongChon": "item"` — stores the current record in `dongChon`
195
- - `"sUserID": "item.UserID"` etc. — copy item fields into state
196
- - `{ "dlXxx": true }` — open the dialog after state is ready
197
-
198
- ---
199
-
200
- ## 6. ctrl-update CRUD
201
-
202
- CRUD directly in the table — no manual dialog.
203
-
204
- ```json
205
- {
206
- "el": "f-table",
207
- "attr": {
208
- ":items": "dsFunctionRight",
209
- "item-key": "FunctionID",
210
- ":headers": [
211
- { "text": "Code", "value": "FunctionCode" },
212
- { "text": "Name", "value": "FunctionName" },
213
- { "text": "Update", "value": "ctrl-update" }
214
- ],
215
- ":update-form": [
216
- {
217
- "el": "v-text-field",
218
- "w": 12,
219
- "attr": { "v-model": "FunctionCode", "label": "Function Code", ":required": true }
220
- },
221
- {
222
- "el": "v-text-field",
223
- "w": 12,
224
- "attr": { "v-model": "FunctionName", "label": "Function Name" }
225
- }
226
- ],
227
- ":update-api": {
228
- "new": {
229
- "API": "/SM_Function_Insert",
230
- "IN": { "ModuleID": "sModuleID", "FunctionCode": "item.FunctionCode", "FunctionName": "item.FunctionName" },
231
- "CALLBACK": { "CALL": "getFunctionRight" }
232
- },
233
- "edit": {
234
- "API": "/SM_Function_Update",
235
- "IN": {
236
- "FunctionID": "item.FunctionID",
237
- "FunctionCode": "item.FunctionCode",
238
- "FunctionName": "item.FunctionName"
239
- },
240
- "CALLBACK": { "CALL": "getFunctionRight" }
241
- },
242
- "delete": {
243
- "CONFIRM": "Bạn có chắc muốn xóa quyền này không?",
244
- "API": "/SM_Function_Delete",
245
- "IN": { "FunctionID": "item.FunctionID" },
246
- "CALLBACK": [{ "MESS": "Xóa thành công" }, { "CALL": "getFunctionRight" }]
247
- }
248
- }
249
- }
250
- }
251
- ```
252
-
253
- Use ctrl-update for simple edit forms (2–5 fields) with no complex layout.
254
-
255
- ---
256
-
257
- ## 7. f-table with show-select (multi-select)
258
-
259
- ```json
260
- {
261
- "el": "f-table",
262
- "attr": {
263
- ":show-select": true,
264
- "v-model": "sUserSelected",
265
- ":items": "dsUsers",
266
- "item-key": "UserID",
267
- ":items-per-page": -1,
268
- ":hide-default-footer": true,
269
- ":update-api": { "default-item": { "xAA": [] } },
270
- ":headers": [...]
271
- }
272
- }
273
- ```
274
-
275
- - `v-model`: array of selected items
276
- - `:update-api.default-item`: injects default fields into each item on load (here `xAA: []` for chip-group)
277
-
278
- ---
279
-
280
- ## 8. v-chip-group in cell
281
-
282
- Tag list in a cell; click opens a dialog.
283
-
284
- ```json
285
- {
286
- "text": "FunctionRight",
287
- "value": "FunctionName",
288
- "el": "v-chip-group",
289
- "attr": {
290
- "v-model": "item.xAA",
291
- "column": true,
292
- "v-if": "item.FunctionName"
293
- },
294
- "innerHTML": [
295
- {
296
- "el": "v-chip",
297
- "attr": {
298
- ":small": true,
299
- "color": "primary",
300
- "outlined": "",
301
- "v-for": "fn in item.FunctionName",
302
- ":key": "fn",
303
- "v-on:click": "vueData.dlFunction = true; CALL(setFunction(item, item.FunctionName));"
304
- },
305
- "innerHTML": "<div>{{fn.FunctionCode}}-{{fn.FunctionName}}</div>"
306
- }
307
- ]
308
- }
309
- ```
310
-
311
- ---
312
-
313
- ## `t-button` vs `t-menu`
314
-
315
- - **`t-button`**: the only action is viewing/loading related data → one direct click
316
- - **`t-menu`**: several actions **or** a state-changing action (Kích hoạt, Chốt điểm, Xóa...)
317
-
318
- > Don't wrap "Xem chi tiết" in `t-menu` — adds a wasted click; use `t-button`. See Master-Detail in [ui-layout-patterns.md](ui-layout-patterns.md).
1
+ # FUI Table Cell Patterns — f-table & in-cell controls
2
+
3
+ > Owns: **in-cell `f-table` controls (`t-*`), `ctrl-update`, show-select, chip-group, `t-button` vs `t-menu`**. Table props: [component-table.md](component-table.md).
4
+
5
+ Patterns for `f-table` and in-cell controls (`t-check`, `t-button`, `t-select`, `t-menu`, `ctrl-update`, `show-select`, `v-chip-group`), from project **security-manager**.
6
+
7
+ > See also: [ui-patterns.md](ui-patterns.md) (data/watch/toolbar), [ui-dialog-patterns.md](ui-dialog-patterns.md), [component-table.md](component-table.md).
8
+
9
+ ---
10
+
11
+ ## 1. Basic f-table with fixed header
12
+
13
+ ```json
14
+ {
15
+ "el": "f-table",
16
+ "attr": {
17
+ "label": "User list",
18
+ ":items-per-page": 50,
19
+ ":height": -16,
20
+ ":items": "dsUser",
21
+ "item-key": "UserID",
22
+ ":hide-default-footer": false,
23
+ ":item-class": "item => item.ChuaKichHoat>0 ? 'danger' : ''",
24
+ ":headers": [
25
+ { "align": "center", "text": "UserID", "value": "UserID" },
26
+ { "text": "Username", "value": "UserName" },
27
+ { "text": "Fullname", "value": "FullName" }
28
+ ]
29
+ },
30
+ "w": 12
31
+ }
32
+ ```
33
+
34
+ - **Table height RULE (lint D9)**: the module's main data table declares `":height": -16` — f-table **measures its real position** after layout (`getBoundingClientRect().top`), fills to the screen bottom leaving 16px, and enables `fixed-header`. Data scrolls **inside the table** only, header stays put, no nested page scrollbars. Updates on window resize and when `items` changes.
35
+
36
+ | `:height` | Behavior |
37
+ | ----------- | ----------------------------------------------------------------------------------------------------- |
38
+ | _(omitted)_ | Grows with row count — intentional short/lookup tables; wrong for the main table (whole page scrolls) |
39
+ | `<= 0` | Fill to bottom leaving `abs(height)` px — **standard for main table** |
40
+ | `> 0` | Fixed px — **table inside a dialog** (e.g. `":height": 360`) |
41
+
42
+ Same three modes apply to `f-sheet` — see [fsheet.md](fsheet.md) §Height.
43
+
44
+ ⚠ Old pattern `":height": "$( window ).height()-285"` is **deprecated** — it forces guessing total toolbar/filter/menu height; wrong guess = short or overflowing. It returns a **positive** number so it still works as fixed px (doesn't break) but loses auto-measure; lint D9 warns so you replace it with `-16`.
45
+
46
+ - `:item-class`: conditional row highlight — `"item => item.Active==0 ? 'danger' : ''"`
47
+
48
+ ---
49
+
50
+ ## 2. t-check — toggle in cell
51
+
52
+ In `headers`, renders a checkbox/icon toggle that fires an API on click.
53
+
54
+ ```json
55
+ {
56
+ "text": "Active",
57
+ "value": "Enable",
58
+ "align": "center",
59
+ "el": "t-check",
60
+ "attr": {
61
+ "on-icon": "mdi-check",
62
+ "off-icon": "mdi-lock",
63
+ ":action": [
64
+ { "API": "/SM_Users_SetActive", "IN": { "UserID": "item.UserID" } },
65
+ { "dsUser": [] },
66
+ { "CALL": "getUser" }
67
+ ]
68
+ }
69
+ }
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 3. t-button — button in cell
75
+
76
+ Button/icon with an action in a cell; supports dynamic icons.
77
+
78
+ ```json
79
+ {
80
+ "text": "Allow",
81
+ "value": "Locked",
82
+ "align": "center",
83
+ "el": "t-button",
84
+ "attr": {
85
+ "color": "primary",
86
+ ":outlined": false,
87
+ ":icon-text": "`${ item.Locked==0 ? 'mdi-check-bold':'mdi-lock'}`",
88
+ ":action": [
89
+ { "API": "/SM_Computer_SetLocked", "IN": { "ComputerID": "item.ComputerID" } },
90
+ { "dsComputer": [] },
91
+ { "CALL": "getComputer" }
92
+ ]
93
+ }
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## 4. t-select — inline dropdown in cell
100
+
101
+ Edit a field in the table; fires an API on selection.
102
+
103
+ ```json
104
+ {
105
+ "text": "SystemRight",
106
+ "value": "SysRight",
107
+ "el": "t-select",
108
+ "width": "250px",
109
+ "attr": {
110
+ "class": "flex-md-grow-0 my-2",
111
+ ":items": "vueData.dsSystemRight",
112
+ "item-text": "Note",
113
+ "item-value": "SysRight",
114
+ ":action": [
115
+ {
116
+ "CONFIRM": "Bạn có chắc cập nhật System Right cho user này không?",
117
+ "API": "/SM_UserModule_UpdateSystemRight",
118
+ "IN": {
119
+ "ModuleID": "sModuleID",
120
+ "UserID": "item.UserID",
121
+ "SysRight": "item.SysRight"
122
+ },
123
+ "CALLBACK": { "MESS": "Cập nhật thành công." }
124
+ }
125
+ ]
126
+ }
127
+ }
128
+ ```
129
+
130
+ ---
131
+
132
+ ## 5. t-menu — context menu in table (menuChucNang)
133
+
134
+ Define menu items in `data[]`, reference via `t-menu` in headers.
135
+
136
+ **Step 1 — `menuChucNang` in `data[]`:**
137
+
138
+ ```json
139
+ {
140
+ "menuChucNang": [
141
+ {
142
+ "color": "primary",
143
+ "icon-text": "mdi-account-details",
144
+ "text": "Update Info",
145
+ "action": [
146
+ {
147
+ "addNew": 0,
148
+ "dongChon": "item",
149
+ "sUserID": "item.UserID",
150
+ "sUserName": "item.UserName",
151
+ "sLastName": "item.LastName",
152
+ "sFirstName": "item.FirstName"
153
+ },
154
+ { "dlUserInfo": true }
155
+ ]
156
+ },
157
+ {
158
+ "color": "primary",
159
+ "icon-text": "mdi-shield-account-outline",
160
+ "text": "User Permission",
161
+ "action": [
162
+ {
163
+ "dongChon": "item",
164
+ "sUserID": "item.UserID",
165
+ "sFullName": "item.FullName"
166
+ },
167
+ {
168
+ "FUN": "openWindow",
169
+ "IN": {
170
+ "id": "`WinPer",
171
+ "title": "`User Permission",
172
+ "url": "`/UserPermission"
173
+ }
174
+ }
175
+ ]
176
+ }
177
+ ]
178
+ }
179
+ ```
180
+
181
+ **Step 2 — `t-menu` in `headers`:**
182
+
183
+ ```json
184
+ {
185
+ "el": "t-menu",
186
+ "width": "120px",
187
+ "align": "center",
188
+ "text": "Update",
189
+ "value": "Update",
190
+ "attr": { ":items": "vueData.menuChucNang" }
191
+ }
192
+ ```
193
+
194
+ - `"dongChon": "item"` — stores the current record in `dongChon`
195
+ - `"sUserID": "item.UserID"` etc. — copy item fields into state
196
+ - `{ "dlXxx": true }` — open the dialog after state is ready
197
+
198
+ ---
199
+
200
+ ## 6. ctrl-update CRUD
201
+
202
+ CRUD directly in the table — no manual dialog.
203
+
204
+ ```json
205
+ {
206
+ "el": "f-table",
207
+ "attr": {
208
+ ":items": "dsFunctionRight",
209
+ "item-key": "FunctionID",
210
+ ":headers": [
211
+ { "text": "Code", "value": "FunctionCode" },
212
+ { "text": "Name", "value": "FunctionName" },
213
+ { "text": "Update", "value": "ctrl-update" }
214
+ ],
215
+ ":update-form": [
216
+ {
217
+ "el": "v-text-field",
218
+ "w": 12,
219
+ "attr": { "v-model": "FunctionCode", "label": "Function Code", ":required": true }
220
+ },
221
+ {
222
+ "el": "v-text-field",
223
+ "w": 12,
224
+ "attr": { "v-model": "FunctionName", "label": "Function Name" }
225
+ }
226
+ ],
227
+ ":update-api": {
228
+ "new": {
229
+ "API": "/SM_Function_Insert",
230
+ "IN": { "ModuleID": "sModuleID", "FunctionCode": "item.FunctionCode", "FunctionName": "item.FunctionName" },
231
+ "CALLBACK": { "CALL": "getFunctionRight" }
232
+ },
233
+ "edit": {
234
+ "API": "/SM_Function_Update",
235
+ "IN": {
236
+ "FunctionID": "item.FunctionID",
237
+ "FunctionCode": "item.FunctionCode",
238
+ "FunctionName": "item.FunctionName"
239
+ },
240
+ "CALLBACK": { "CALL": "getFunctionRight" }
241
+ },
242
+ "delete": {
243
+ "CONFIRM": "Bạn có chắc muốn xóa quyền này không?",
244
+ "API": "/SM_Function_Delete",
245
+ "IN": { "FunctionID": "item.FunctionID" },
246
+ "CALLBACK": [{ "MESS": "Xóa thành công" }, { "CALL": "getFunctionRight" }]
247
+ }
248
+ }
249
+ }
250
+ }
251
+ ```
252
+
253
+ Use ctrl-update for simple edit forms (2–5 fields) with no complex layout.
254
+
255
+ ---
256
+
257
+ ## 7. f-table with show-select (multi-select)
258
+
259
+ ```json
260
+ {
261
+ "el": "f-table",
262
+ "attr": {
263
+ ":show-select": true,
264
+ "v-model": "sUserSelected",
265
+ ":items": "dsUsers",
266
+ "item-key": "UserID",
267
+ ":items-per-page": -1,
268
+ ":hide-default-footer": true,
269
+ ":update-api": { "default-item": { "xAA": [] } },
270
+ ":headers": [...]
271
+ }
272
+ }
273
+ ```
274
+
275
+ - `v-model`: array of selected items
276
+ - `:update-api.default-item`: injects default fields into each item on load (here `xAA: []` for chip-group)
277
+
278
+ ---
279
+
280
+ ## 8. v-chip-group in cell
281
+
282
+ Tag list in a cell; click opens a dialog.
283
+
284
+ ```json
285
+ {
286
+ "text": "FunctionRight",
287
+ "value": "FunctionName",
288
+ "el": "v-chip-group",
289
+ "attr": {
290
+ "v-model": "item.xAA",
291
+ "column": true,
292
+ "v-if": "item.FunctionName"
293
+ },
294
+ "innerHTML": [
295
+ {
296
+ "el": "v-chip",
297
+ "attr": {
298
+ ":small": true,
299
+ "color": "primary",
300
+ "outlined": "",
301
+ "v-for": "fn in item.FunctionName",
302
+ ":key": "fn",
303
+ "v-on:click": "vueData.dlFunction = true; CALL(setFunction(item, item.FunctionName));"
304
+ },
305
+ "innerHTML": "<div>{{fn.FunctionCode}}-{{fn.FunctionName}}</div>"
306
+ }
307
+ ]
308
+ }
309
+ ```
310
+
311
+ ---
312
+
313
+ ## `t-button` vs `t-menu`
314
+
315
+ - **`t-button`**: the only action is viewing/loading related data → one direct click
316
+ - **`t-menu`**: several actions **or** a state-changing action (Kích hoạt, Chốt điểm, Xóa...)
317
+
318
+ > Don't wrap "Xem chi tiết" in `t-menu` — adds a wasted click; use `t-button`. See Master-Detail in [ui-layout-patterns.md](ui-layout-patterns.md).