@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.
- package/README.md +27 -7
- package/dist/fui-qrb1j9jz.js +397 -0
- package/dist/fui.js +1 -1
- package/package.json +1 -1
- package/skills/fui/SKILL.md +143 -38
- package/skills/fui/agents/fui-builder.md +62 -0
- package/skills/fui/agents/fui-tester.md +77 -0
- package/skills/{fui-skill → fui}/assets/projectdefaultstyle.css +489 -489
- package/skills/{fui-skill → fui}/examples/component.vue +162 -162
- package/skills/{fui-skill → fui}/references/INDEX.md +5 -4
- package/skills/{fui-skill → fui}/references/advanced-techniques.md +170 -168
- package/skills/{fui-skill → fui}/references/component-design.md +2 -2
- package/skills/{fui-skill → fui}/references/component-quickref.md +78 -78
- package/skills/{fui-skill → fui}/references/component-table.md +287 -287
- package/skills/{fui-skill → fui}/references/components-dialog.md +191 -191
- package/skills/{fui-skill → fui}/references/components-display.md +141 -141
- package/skills/{fui-skill → fui}/references/components-echart.md +316 -316
- package/skills/{fui-skill → fui}/references/components-input.md +335 -335
- package/skills/{fui-skill → fui}/references/controls-patterns.md +2 -2
- package/skills/{fui-skill → fui}/references/controls-styling-vocabulary.md +173 -173
- package/skills/{fui-skill → fui}/references/db-workflow.md +9 -9
- package/skills/{fui-skill → fui}/references/default-function.md +456 -456
- package/skills/{fui-skill → fui}/references/design-modes.md +57 -57
- package/skills/{fui-skill → fui}/references/echart-templates.md +489 -489
- package/skills/{fui-skill → fui}/references/fastproject.md +99 -99
- package/skills/{fui-skill → fui}/references/fullstack-workflow.md +314 -313
- package/skills/{fui-skill → fui}/references/module-data-patterns.md +117 -117
- package/skills/{fui-skill → fui}/references/module-json-anatomy.md +132 -132
- package/skills/{fui-skill → fui}/references/module-structure.md +144 -144
- package/skills/{fui-skill → fui}/references/new-session.md +1 -2
- package/skills/{fui-skill → fui}/references/pdfmake.md +60 -60
- package/skills/{fui-skill → fui}/references/permission-system.md +1 -1
- package/skills/{fui-skill → fui}/references/platform-architecture.md +269 -269
- package/skills/{fui-skill → fui}/references/project-config.md +303 -303
- package/skills/{fui-skill → fui}/references/project-provisioning.md +4 -4
- package/skills/{fui-skill → fui}/references/script-map.md +262 -262
- package/skills/{fui-skill → fui}/references/sql-clr-functions.md +225 -225
- package/skills/{fui-skill → fui}/references/system-design.md +2 -2
- package/skills/{fui-skill → fui}/references/tapi-permission-patterns.md +156 -156
- package/skills/{fui-skill → fui}/references/tapi-reference.md +474 -474
- package/skills/fui/references/team-run.md +141 -0
- package/skills/fui/references/tools-registry.md +211 -0
- package/skills/{fui-skill → fui}/references/ui-crosswindow-patterns.md +321 -321
- package/skills/{fui-skill → fui}/references/ui-dialog-patterns.md +255 -255
- package/skills/{fui-skill → fui}/references/ui-layout-patterns.md +176 -176
- package/skills/{fui-skill → fui}/references/ui-patterns.md +303 -303
- package/skills/{fui-skill → fui}/references/ui-screenshot-review.md +95 -95
- package/skills/{fui-skill → fui}/references/ui-table-cell-patterns.md +318 -318
- package/skills/{fui-skill → fui}/references/verification.md +11 -11
- package/skills/{fui-skill → fui}/references/watcher-patterns.md +163 -163
- package/skills/{fui-skill → fui}/references/websocket-realtime.md +271 -271
- package/skills/{fui-skill → fui}/scripts/component-3.0.js +2715 -2715
- package/skills/{fui-skill → fui}/scripts/component.js +3147 -3147
- package/skills/{fui-skill → fui}/scripts/componentTable-3.0.js +1038 -1038
- package/skills/{fui-skill → fui}/scripts/componentTable.js +891 -891
- package/skills/{fui-skill → fui}/scripts/defaultfunction-3.0.js +866 -866
- package/skills/{fui-skill → fui}/scripts/defaultfunction.js +1051 -1051
- package/skills/{fui-skill → fui}/scripts/fastproject-3.0.js +870 -870
- package/skills/{fui-skill → fui}/scripts/fastproject.js +828 -828
- package/dist/fui-h4z7zhk2.js +0 -381
- package/skills/fui-skill/SKILL.md +0 -139
- package/skills/fui-skill/references/tools-registry.md +0 -84
- /package/skills/{fui-skill → fui}/assets/projectdefaultstyle-3.0.css +0 -0
- /package/skills/{fui-skill → fui}/design-md/airbnb/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airbnb/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airtable/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airtable/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/apple/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/apple/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/asu/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/asu/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/binance/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/binance/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw-m/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw-m/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bugatti/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bugatti/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cal/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cal/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/claude/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/claude/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clay/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clay/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clickhouse/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clickhouse/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cohere/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cohere/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/coinbase/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/coinbase/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/composio/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/composio/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cursor/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cursor/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/elevenlabs/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/elevenlabs/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/expo/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/expo/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ferrari/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ferrari/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/figma/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/figma/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/framer/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/framer/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/fui/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/hashicorp/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/hashicorp/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ibm/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ibm/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/intercom/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/intercom/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/kraken/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/kraken/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lamborghini/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lamborghini/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/linear.app/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/linear.app/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lovable/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lovable/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mastercard/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mastercard/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/meta/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/meta/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/minimax/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/minimax/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mintlify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mintlify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/miro/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/miro/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mistral.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mistral.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mongodb/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mongodb/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nike/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nike/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/notion/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/notion/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nvidia/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nvidia/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ollama/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ollama/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/opencode.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/opencode.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/pinterest/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/pinterest/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/playstation/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/playstation/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/posthog/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/posthog/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/raycast/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/raycast/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/renault/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/renault/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/replicate/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/replicate/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/resend/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/resend/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/revolut/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/revolut/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/runwayml/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/runwayml/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sanity/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sanity/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sentry/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sentry/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/shopify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/shopify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/slack/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spacex/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spacex/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spotify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spotify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/starbucks/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/starbucks/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/stripe/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/stripe/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/supabase/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/supabase/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/superhuman/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/superhuman/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/tesla/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/tesla/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/theverge/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/theverge/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/together.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/together.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/uber/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/uber/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vercel/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vercel/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vodafone/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vodafone/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/voltagent/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/voltagent/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/warp/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/warp/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/webflow/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/webflow/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wired/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wired/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wise/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wise/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/x.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/x.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/zapier/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/zapier/README.md +0 -0
- /package/skills/{fui-skill → fui}/examples/f-table-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/examples/module-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/examples/project-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/references/coding-standards.md +0 -0
- /package/skills/{fui-skill → fui}/references/db-table-design.md +0 -0
- /package/skills/{fui-skill → fui}/references/fsheet.md +0 -0
- /package/skills/{fui-skill → fui}/references/tapi-file-api.md +0 -0
- /package/skills/{fui-skill → fui}/references/ui-templates.md +0 -0
- /package/skills/{fui-skill → fui}/scripts/fechart.js +0 -0
- /package/skills/{fui-skill → fui}/scripts/fsheet.js +0 -0
|
@@ -1,191 +1,191 @@
|
|
|
1
|
-
# FUI Dialog & Overlay Components
|
|
2
|
-
|
|
3
|
-
> Owns: **`f-dialog`, `f-window`, `f-editor`**. Hand-built dialog pattern (`v-dialog` + hidden-container): [ui-dialog-patterns.md](ui-dialog-patterns.md).
|
|
4
|
-
|
|
5
|
-
Dialog, overlay and content-editor components. Prefix/binding rules: [components-display.md](components-display.md).
|
|
6
|
-
|
|
7
|
-
## f-window
|
|
8
|
-
|
|
9
|
-
- Props (source): `id`
|
|
10
|
-
- Internal iframe dialog host, usually opened via `openWindow(...)`
|
|
11
|
-
|
|
12
|
-
```json
|
|
13
|
-
{
|
|
14
|
-
"FUN": "openWindow",
|
|
15
|
-
"IN": {
|
|
16
|
-
"id": "`winUser",
|
|
17
|
-
"url": "'/fp/module?mid=123'",
|
|
18
|
-
"title": "Chi tiet user",
|
|
19
|
-
"width": 1100
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## f-editor
|
|
25
|
-
|
|
26
|
-
- Props (source): `value`, `imageapi`, `height`, `toolbar`
|
|
27
|
-
- Emit: `input` with HTML content
|
|
28
|
-
- Wraps CKEditor with upload auth header
|
|
29
|
-
|
|
30
|
-
```json
|
|
31
|
-
{
|
|
32
|
-
"el": "f-editor",
|
|
33
|
-
"w": "12",
|
|
34
|
-
"attr": {
|
|
35
|
-
"v-model": "formData.contentHtml",
|
|
36
|
-
"imageapi": "/api/editor/upload",
|
|
37
|
-
":height": 360
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## f-editor-dialog
|
|
43
|
-
|
|
44
|
-
- Props (source): `value`, `imageapi`, `label`, `width`, `toolbar`
|
|
45
|
-
- `value` must be an object (`open`, `text`, `object`, `ok`), not a plain string
|
|
46
|
-
- Modal editor, writes back on OK
|
|
47
|
-
|
|
48
|
-
```json
|
|
49
|
-
{
|
|
50
|
-
"el": "f-editor-dialog",
|
|
51
|
-
"w": "6",
|
|
52
|
-
"attr": {
|
|
53
|
-
":value": "editorState",
|
|
54
|
-
"label": "Noi dung mo rong",
|
|
55
|
-
":width": 1000,
|
|
56
|
-
"imageapi": "/api/editor/upload"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## f-dialog
|
|
62
|
-
|
|
63
|
-
Modal that builds a form from a `controls` array; supports local watchers, validation and action buttons.
|
|
64
|
-
|
|
65
|
-
- Props:
|
|
66
|
-
- `value` (Boolean, default `false`) — v-model open/close
|
|
67
|
-
- `data` (Object, default `{}`) — input data, bind with `:data.sync`; copied into fields when the dialog opens
|
|
68
|
-
- `dataOut` (Object, default `{}`) — output, bind with `:data-out.sync`; receives the component instance on open
|
|
69
|
-
- `title` (String, default `''`)
|
|
70
|
-
- `controls` (Array, default `[]`) — control definitions (`el`, `attr`, `w` col width); any field whose `v-model` doesn't start with `vueData.` gets local data auto-created (init `null`)
|
|
71
|
-
- `watch` (Object, default `{}`) — local watchers; key = field name, value = action run on change; registered on open, removed on close
|
|
72
|
-
- `button` (Array, default `[]`) — button definitions (below)
|
|
73
|
-
- `disableValidate` (Boolean, default `false`) — skip form validation when `true`
|
|
74
|
-
- `width` (Number, default `800`) — px
|
|
75
|
-
- `openAction` (Object, default `null`) — action run as soon as the dialog opens
|
|
76
|
-
|
|
77
|
-
- Emits:
|
|
78
|
-
- `input` — open/close (v-model)
|
|
79
|
-
- `update:data-out` — component instance on open (parent can reach local data)
|
|
80
|
-
- `update:data` — `v_outData` when a button with `getoutdata: true` is clicked (after validation passes)
|
|
81
|
-
|
|
82
|
-
- On open (`value = true`):
|
|
83
|
-
1. Reset all fields from `:data` (`setDefaultData`)
|
|
84
|
-
2. Register watchers from `watch`
|
|
85
|
-
3. Run `openAction` if set
|
|
86
|
-
4. Emit `update:data-out` with the instance
|
|
87
|
-
|
|
88
|
-
- On close (`value = false`): remove all registered watchers.
|
|
89
|
-
|
|
90
|
-
- Button object:
|
|
91
|
-
- `label` (String)
|
|
92
|
-
- `color` (String, default `"primary"`)
|
|
93
|
-
- `elevation` (Number, default `0`)
|
|
94
|
-
- `text` (Boolean, default `true`) — text button
|
|
95
|
-
- `type` (String) — e.g. `"submit"`
|
|
96
|
-
- `:disabled` (String) — Vue expression, e.g. `"!checkBoxValue"`
|
|
97
|
-
- `v-if` (String) — Vue expression to show/hide, e.g. `"ModuleID==1"`
|
|
98
|
-
- `icon-text` (String) — MDI icon left of the label
|
|
99
|
-
- `checkvalid` (Boolean) — validate before running the action; stop if invalid
|
|
100
|
-
- `getoutdata` (Boolean) — sync field values into `v_outData` then emit `update:data`; also triggers validation
|
|
101
|
-
- `action` (Array | Function) — actions run on click; context = all `v_outData` fields plus `dData` pointing to `v_outData`
|
|
102
|
-
|
|
103
|
-
- Notes:
|
|
104
|
-
- Button clicks debounced 500ms (leading edge) against double-click
|
|
105
|
-
- Controls support `br: true` for a row break
|
|
106
|
-
- Template is built statically at `data()` init; no re-render when `controls` changes
|
|
107
|
-
- In the template, `watch` is `:watch` (dynamic bind), not Vue's default `watch`
|
|
108
|
-
- **Never put `f-dialog` inside a component template:** it works only when declared directly in the module JSON `controls`; inside a Vue component it misbehaves.
|
|
109
|
-
- **Declare `vueData` variables before binding them in controls:** a control bound to `vueData.someVar` needs that variable declared in the module `data` first — Vue can't make a variable reactive if it doesn't exist at init.
|
|
110
|
-
|
|
111
|
-
```json
|
|
112
|
-
"data": [
|
|
113
|
-
{ "projectList": [] }
|
|
114
|
-
],
|
|
115
|
-
"controls": [
|
|
116
|
-
{
|
|
117
|
-
"prop": "fluid pa-0",
|
|
118
|
-
"rows": [{ "prop": "", "cols": [
|
|
119
|
-
{
|
|
120
|
-
"el": "v-autocomplete",
|
|
121
|
-
"attr": {
|
|
122
|
-
"v-model": "pid",
|
|
123
|
-
"label": "Module name",
|
|
124
|
-
":items": "vueData.projectList",
|
|
125
|
-
"item-text": "ModuleName",
|
|
126
|
-
"item-value": "ModuleID"
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
]}]
|
|
130
|
-
}
|
|
131
|
-
]
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
- Full example:
|
|
135
|
-
|
|
136
|
-
```json
|
|
137
|
-
{
|
|
138
|
-
"el": "f-dialog",
|
|
139
|
-
"attr": {
|
|
140
|
-
"v-model": "dialogOpen",
|
|
141
|
-
":data.sync": "dialogData",
|
|
142
|
-
"title": "Nhap du lieu",
|
|
143
|
-
":open-action": { "MESSBOX": "Bạn vừa mở dialog" },
|
|
144
|
-
":controls": [
|
|
145
|
-
{ "el": "v-text-field", "attr": { "v-model": "Domain", "label": "Domain" }, "w": 4 },
|
|
146
|
-
{ "el": "v-text-field", "attr": { "v-model": "ModuleID", "label": "ModuleID" }, "w": 3 },
|
|
147
|
-
{ "el": "v-text-field", "attr": { "v-model": "ModuleName", "label": "ModuleName" }, "w": 8 },
|
|
148
|
-
{
|
|
149
|
-
"el": "v-checkbox",
|
|
150
|
-
"attr": { ":label": "`Tôi đã hiểu và đồng ý: ${checkBoxValue}`", "v-model": "checkBoxValue" }
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
"el": "v-select",
|
|
154
|
-
"attr": {
|
|
155
|
-
"label": "select",
|
|
156
|
-
"v-model": "bienselect",
|
|
157
|
-
":items": "vueData.Mang",
|
|
158
|
-
"item-text": "AppName",
|
|
159
|
-
"item-value": "AppListID"
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
],
|
|
163
|
-
":watch": {
|
|
164
|
-
"bienselect": { "MESSBOX": "Watch Select {{bienselect}}" },
|
|
165
|
-
"Domain": { "MESSBOX": "Watch textbox {{Domain}}" }
|
|
166
|
-
},
|
|
167
|
-
":button": [
|
|
168
|
-
{
|
|
169
|
-
"label": "Submit OK",
|
|
170
|
-
"type": "submit",
|
|
171
|
-
":disabled": "!checkBoxValue",
|
|
172
|
-
"action": [
|
|
173
|
-
{ "ModuleName": "gan gia tri cho ModuleName" },
|
|
174
|
-
{ "MESSBOX": "thong bao 1" },
|
|
175
|
-
{ "dialogOpen": false }
|
|
176
|
-
]
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
"label": "Chay mot API",
|
|
180
|
-
"checkvalid": true,
|
|
181
|
-
"v-if": "ModuleID==1",
|
|
182
|
-
"action": [{ "API": "/chaymotapi" }]
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
"label": "Close",
|
|
186
|
-
"action": [{ "dialogOpen": false }]
|
|
187
|
-
}
|
|
188
|
-
]
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
```
|
|
1
|
+
# FUI Dialog & Overlay Components
|
|
2
|
+
|
|
3
|
+
> Owns: **`f-dialog`, `f-window`, `f-editor`**. Hand-built dialog pattern (`v-dialog` + hidden-container): [ui-dialog-patterns.md](ui-dialog-patterns.md).
|
|
4
|
+
|
|
5
|
+
Dialog, overlay and content-editor components. Prefix/binding rules: [components-display.md](components-display.md).
|
|
6
|
+
|
|
7
|
+
## f-window
|
|
8
|
+
|
|
9
|
+
- Props (source): `id`
|
|
10
|
+
- Internal iframe dialog host, usually opened via `openWindow(...)`
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"FUN": "openWindow",
|
|
15
|
+
"IN": {
|
|
16
|
+
"id": "`winUser",
|
|
17
|
+
"url": "'/fp/module?mid=123'",
|
|
18
|
+
"title": "Chi tiet user",
|
|
19
|
+
"width": 1100
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## f-editor
|
|
25
|
+
|
|
26
|
+
- Props (source): `value`, `imageapi`, `height`, `toolbar`
|
|
27
|
+
- Emit: `input` with HTML content
|
|
28
|
+
- Wraps CKEditor with upload auth header
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"el": "f-editor",
|
|
33
|
+
"w": "12",
|
|
34
|
+
"attr": {
|
|
35
|
+
"v-model": "formData.contentHtml",
|
|
36
|
+
"imageapi": "/api/editor/upload",
|
|
37
|
+
":height": 360
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## f-editor-dialog
|
|
43
|
+
|
|
44
|
+
- Props (source): `value`, `imageapi`, `label`, `width`, `toolbar`
|
|
45
|
+
- `value` must be an object (`open`, `text`, `object`, `ok`), not a plain string
|
|
46
|
+
- Modal editor, writes back on OK
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"el": "f-editor-dialog",
|
|
51
|
+
"w": "6",
|
|
52
|
+
"attr": {
|
|
53
|
+
":value": "editorState",
|
|
54
|
+
"label": "Noi dung mo rong",
|
|
55
|
+
":width": 1000,
|
|
56
|
+
"imageapi": "/api/editor/upload"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## f-dialog
|
|
62
|
+
|
|
63
|
+
Modal that builds a form from a `controls` array; supports local watchers, validation and action buttons.
|
|
64
|
+
|
|
65
|
+
- Props:
|
|
66
|
+
- `value` (Boolean, default `false`) — v-model open/close
|
|
67
|
+
- `data` (Object, default `{}`) — input data, bind with `:data.sync`; copied into fields when the dialog opens
|
|
68
|
+
- `dataOut` (Object, default `{}`) — output, bind with `:data-out.sync`; receives the component instance on open
|
|
69
|
+
- `title` (String, default `''`)
|
|
70
|
+
- `controls` (Array, default `[]`) — control definitions (`el`, `attr`, `w` col width); any field whose `v-model` doesn't start with `vueData.` gets local data auto-created (init `null`)
|
|
71
|
+
- `watch` (Object, default `{}`) — local watchers; key = field name, value = action run on change; registered on open, removed on close
|
|
72
|
+
- `button` (Array, default `[]`) — button definitions (below)
|
|
73
|
+
- `disableValidate` (Boolean, default `false`) — skip form validation when `true`
|
|
74
|
+
- `width` (Number, default `800`) — px
|
|
75
|
+
- `openAction` (Object, default `null`) — action run as soon as the dialog opens
|
|
76
|
+
|
|
77
|
+
- Emits:
|
|
78
|
+
- `input` — open/close (v-model)
|
|
79
|
+
- `update:data-out` — component instance on open (parent can reach local data)
|
|
80
|
+
- `update:data` — `v_outData` when a button with `getoutdata: true` is clicked (after validation passes)
|
|
81
|
+
|
|
82
|
+
- On open (`value = true`):
|
|
83
|
+
1. Reset all fields from `:data` (`setDefaultData`)
|
|
84
|
+
2. Register watchers from `watch`
|
|
85
|
+
3. Run `openAction` if set
|
|
86
|
+
4. Emit `update:data-out` with the instance
|
|
87
|
+
|
|
88
|
+
- On close (`value = false`): remove all registered watchers.
|
|
89
|
+
|
|
90
|
+
- Button object:
|
|
91
|
+
- `label` (String)
|
|
92
|
+
- `color` (String, default `"primary"`)
|
|
93
|
+
- `elevation` (Number, default `0`)
|
|
94
|
+
- `text` (Boolean, default `true`) — text button
|
|
95
|
+
- `type` (String) — e.g. `"submit"`
|
|
96
|
+
- `:disabled` (String) — Vue expression, e.g. `"!checkBoxValue"`
|
|
97
|
+
- `v-if` (String) — Vue expression to show/hide, e.g. `"ModuleID==1"`
|
|
98
|
+
- `icon-text` (String) — MDI icon left of the label
|
|
99
|
+
- `checkvalid` (Boolean) — validate before running the action; stop if invalid
|
|
100
|
+
- `getoutdata` (Boolean) — sync field values into `v_outData` then emit `update:data`; also triggers validation
|
|
101
|
+
- `action` (Array | Function) — actions run on click; context = all `v_outData` fields plus `dData` pointing to `v_outData`
|
|
102
|
+
|
|
103
|
+
- Notes:
|
|
104
|
+
- Button clicks debounced 500ms (leading edge) against double-click
|
|
105
|
+
- Controls support `br: true` for a row break
|
|
106
|
+
- Template is built statically at `data()` init; no re-render when `controls` changes
|
|
107
|
+
- In the template, `watch` is `:watch` (dynamic bind), not Vue's default `watch`
|
|
108
|
+
- **Never put `f-dialog` inside a component template:** it works only when declared directly in the module JSON `controls`; inside a Vue component it misbehaves.
|
|
109
|
+
- **Declare `vueData` variables before binding them in controls:** a control bound to `vueData.someVar` needs that variable declared in the module `data` first — Vue can't make a variable reactive if it doesn't exist at init.
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
"data": [
|
|
113
|
+
{ "projectList": [] }
|
|
114
|
+
],
|
|
115
|
+
"controls": [
|
|
116
|
+
{
|
|
117
|
+
"prop": "fluid pa-0",
|
|
118
|
+
"rows": [{ "prop": "", "cols": [
|
|
119
|
+
{
|
|
120
|
+
"el": "v-autocomplete",
|
|
121
|
+
"attr": {
|
|
122
|
+
"v-model": "pid",
|
|
123
|
+
"label": "Module name",
|
|
124
|
+
":items": "vueData.projectList",
|
|
125
|
+
"item-text": "ModuleName",
|
|
126
|
+
"item-value": "ModuleID"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
]}]
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
- Full example:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"el": "f-dialog",
|
|
139
|
+
"attr": {
|
|
140
|
+
"v-model": "dialogOpen",
|
|
141
|
+
":data.sync": "dialogData",
|
|
142
|
+
"title": "Nhap du lieu",
|
|
143
|
+
":open-action": { "MESSBOX": "Bạn vừa mở dialog" },
|
|
144
|
+
":controls": [
|
|
145
|
+
{ "el": "v-text-field", "attr": { "v-model": "Domain", "label": "Domain" }, "w": 4 },
|
|
146
|
+
{ "el": "v-text-field", "attr": { "v-model": "ModuleID", "label": "ModuleID" }, "w": 3 },
|
|
147
|
+
{ "el": "v-text-field", "attr": { "v-model": "ModuleName", "label": "ModuleName" }, "w": 8 },
|
|
148
|
+
{
|
|
149
|
+
"el": "v-checkbox",
|
|
150
|
+
"attr": { ":label": "`Tôi đã hiểu và đồng ý: ${checkBoxValue}`", "v-model": "checkBoxValue" }
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"el": "v-select",
|
|
154
|
+
"attr": {
|
|
155
|
+
"label": "select",
|
|
156
|
+
"v-model": "bienselect",
|
|
157
|
+
":items": "vueData.Mang",
|
|
158
|
+
"item-text": "AppName",
|
|
159
|
+
"item-value": "AppListID"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
],
|
|
163
|
+
":watch": {
|
|
164
|
+
"bienselect": { "MESSBOX": "Watch Select {{bienselect}}" },
|
|
165
|
+
"Domain": { "MESSBOX": "Watch textbox {{Domain}}" }
|
|
166
|
+
},
|
|
167
|
+
":button": [
|
|
168
|
+
{
|
|
169
|
+
"label": "Submit OK",
|
|
170
|
+
"type": "submit",
|
|
171
|
+
":disabled": "!checkBoxValue",
|
|
172
|
+
"action": [
|
|
173
|
+
{ "ModuleName": "gan gia tri cho ModuleName" },
|
|
174
|
+
{ "MESSBOX": "thong bao 1" },
|
|
175
|
+
{ "dialogOpen": false }
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"label": "Chay mot API",
|
|
180
|
+
"checkvalid": true,
|
|
181
|
+
"v-if": "ModuleID==1",
|
|
182
|
+
"action": [{ "API": "/chaymotapi" }]
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"label": "Close",
|
|
186
|
+
"action": [{ "dialogOpen": false }]
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
@@ -1,141 +1,141 @@
|
|
|
1
|
-
# FUI Display & Presentation Components
|
|
2
|
-
|
|
3
|
-
> Owns: **display components: `f-label`, `f-title`, `f-box`, `f-header`, `f-slider`, chip/badge**.
|
|
4
|
-
|
|
5
|
-
Components for showing info, charts, media. Also holds prefix/binding rules for all f-* components.
|
|
6
|
-
|
|
7
|
-
## Prefix and binding rules
|
|
8
|
-
|
|
9
|
-
- `f-*`: FUI components (FUI runtime)
|
|
10
|
-
- `v-*`: Vuetify components
|
|
11
|
-
- `uc-*`: custom module components from `components/`
|
|
12
|
-
- In `module.json`, pass props via `attr`
|
|
13
|
-
- Kebab-case in JSON for custom props (`api-upload`, `item-value`)
|
|
14
|
-
- Dynamic values use `:prop`
|
|
15
|
-
- Use `v-on:*` in JSON (not `@*`)
|
|
16
|
-
- Props without `:` (e.g. `url`, `api-upload`) are plain strings by default
|
|
17
|
-
- Literal-string forcing (backtick/quote) only in Action `IN` mappings, never for static props
|
|
18
|
-
|
|
19
|
-
## Minimal control pattern
|
|
20
|
-
|
|
21
|
-
```json
|
|
22
|
-
{
|
|
23
|
-
"el": "f-date",
|
|
24
|
-
"w": "6",
|
|
25
|
-
"attr": {
|
|
26
|
-
"v-model": "formData.fromDate",
|
|
27
|
-
"label": "From date"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## f-label
|
|
35
|
-
|
|
36
|
-
- Props (source): `items`, `text`, `color`, `iconText`
|
|
37
|
-
- Renders `v-chip` from `text` and/or `items`
|
|
38
|
-
|
|
39
|
-
```json
|
|
40
|
-
{
|
|
41
|
-
"el": "f-label",
|
|
42
|
-
"w": "12",
|
|
43
|
-
"attr": {
|
|
44
|
-
"text": "Trang thai",
|
|
45
|
-
"icon-text": "mdi-information"
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## f-box
|
|
51
|
-
|
|
52
|
-
- Props (source): `rowFormat`, `items`, `label`, `edit`, `saveclick`
|
|
53
|
-
- Emits `input` when internal data changes
|
|
54
|
-
- Displays/edits key-value rows; auto-builds row format from data if missing
|
|
55
|
-
- `rowFormat`: array of `{ text, value, noEdit }` — `noEdit: true` locks that column when `edit=true`
|
|
56
|
-
- `items`: object or array; an object is auto-wrapped into a 1-element array
|
|
57
|
-
|
|
58
|
-
```json
|
|
59
|
-
{
|
|
60
|
-
"el": "f-box",
|
|
61
|
-
"w": "12",
|
|
62
|
-
"attr": {
|
|
63
|
-
"label": "Thong tin",
|
|
64
|
-
":items": "detailData",
|
|
65
|
-
":edit": "isEditMode",
|
|
66
|
-
":row-format": [
|
|
67
|
-
{ "text": "Mã", "value": "StudentID", "noEdit": true },
|
|
68
|
-
{ "text": "Họ tên", "value": "FullName" },
|
|
69
|
-
{ "text": "Ngày sinh", "value": "BirthDate" }
|
|
70
|
-
]
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## f-header
|
|
76
|
-
|
|
77
|
-
- Props (source): `label`
|
|
78
|
-
|
|
79
|
-
```json
|
|
80
|
-
{
|
|
81
|
-
"el": "f-header",
|
|
82
|
-
"w": "12",
|
|
83
|
-
"attr": { "label": "Bao cao tong hop" }
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## f-title
|
|
88
|
-
|
|
89
|
-
- Props (source): `label`
|
|
90
|
-
|
|
91
|
-
```json
|
|
92
|
-
{
|
|
93
|
-
"el": "f-title",
|
|
94
|
-
"w": "12",
|
|
95
|
-
"attr": { "label": "Danh sach ho so" }
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## f-slider
|
|
100
|
-
|
|
101
|
-
- Props (source): `items`, `itemAttr`
|
|
102
|
-
- Wraps `v-carousel` and `v-carousel-item`
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
{
|
|
106
|
-
"el": "f-slider",
|
|
107
|
-
"w": "12",
|
|
108
|
-
"attr": {
|
|
109
|
-
":items": "slideItems",
|
|
110
|
-
":item-attr": { "contain": true }
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## f-echart
|
|
116
|
-
|
|
117
|
-
→ See [`components-echart.md`](components-echart.md) — props, config, global `FEchartFormatter` module, examples.
|
|
118
|
-
|
|
119
|
-
## f-pdfmake
|
|
120
|
-
|
|
121
|
-
- Props (source): `data`
|
|
122
|
-
- Renders PDF in an iframe; re-renders when `data` changes (deep watch)
|
|
123
|
-
|
|
124
|
-
```json
|
|
125
|
-
{
|
|
126
|
-
"el": "f-pdfmake",
|
|
127
|
-
"w": "12",
|
|
128
|
-
"attr": {
|
|
129
|
-
":data": "pdfDefinition",
|
|
130
|
-
"height": "550"
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
## Practical notes
|
|
138
|
-
|
|
139
|
-
1. Most `f-*` components forward unknown attrs via `v-bind="$attrs"` — Vuetify attrs still work when the child is a Vuetify control.
|
|
140
|
-
2. The literal-string rule applies only to API/path strings in Action `IN` mappings.
|
|
141
|
-
3. See `references/component-table.md` for `f-table`.
|
|
1
|
+
# FUI Display & Presentation Components
|
|
2
|
+
|
|
3
|
+
> Owns: **display components: `f-label`, `f-title`, `f-box`, `f-header`, `f-slider`, chip/badge**.
|
|
4
|
+
|
|
5
|
+
Components for showing info, charts, media. Also holds prefix/binding rules for all f-* components.
|
|
6
|
+
|
|
7
|
+
## Prefix and binding rules
|
|
8
|
+
|
|
9
|
+
- `f-*`: FUI components (FUI runtime)
|
|
10
|
+
- `v-*`: Vuetify components
|
|
11
|
+
- `uc-*`: custom module components from `components/`
|
|
12
|
+
- In `module.json`, pass props via `attr`
|
|
13
|
+
- Kebab-case in JSON for custom props (`api-upload`, `item-value`)
|
|
14
|
+
- Dynamic values use `:prop`
|
|
15
|
+
- Use `v-on:*` in JSON (not `@*`)
|
|
16
|
+
- Props without `:` (e.g. `url`, `api-upload`) are plain strings by default
|
|
17
|
+
- Literal-string forcing (backtick/quote) only in Action `IN` mappings, never for static props
|
|
18
|
+
|
|
19
|
+
## Minimal control pattern
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"el": "f-date",
|
|
24
|
+
"w": "6",
|
|
25
|
+
"attr": {
|
|
26
|
+
"v-model": "formData.fromDate",
|
|
27
|
+
"label": "From date"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## f-label
|
|
35
|
+
|
|
36
|
+
- Props (source): `items`, `text`, `color`, `iconText`
|
|
37
|
+
- Renders `v-chip` from `text` and/or `items`
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"el": "f-label",
|
|
42
|
+
"w": "12",
|
|
43
|
+
"attr": {
|
|
44
|
+
"text": "Trang thai",
|
|
45
|
+
"icon-text": "mdi-information"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## f-box
|
|
51
|
+
|
|
52
|
+
- Props (source): `rowFormat`, `items`, `label`, `edit`, `saveclick`
|
|
53
|
+
- Emits `input` when internal data changes
|
|
54
|
+
- Displays/edits key-value rows; auto-builds row format from data if missing
|
|
55
|
+
- `rowFormat`: array of `{ text, value, noEdit }` — `noEdit: true` locks that column when `edit=true`
|
|
56
|
+
- `items`: object or array; an object is auto-wrapped into a 1-element array
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"el": "f-box",
|
|
61
|
+
"w": "12",
|
|
62
|
+
"attr": {
|
|
63
|
+
"label": "Thong tin",
|
|
64
|
+
":items": "detailData",
|
|
65
|
+
":edit": "isEditMode",
|
|
66
|
+
":row-format": [
|
|
67
|
+
{ "text": "Mã", "value": "StudentID", "noEdit": true },
|
|
68
|
+
{ "text": "Họ tên", "value": "FullName" },
|
|
69
|
+
{ "text": "Ngày sinh", "value": "BirthDate" }
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## f-header
|
|
76
|
+
|
|
77
|
+
- Props (source): `label`
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"el": "f-header",
|
|
82
|
+
"w": "12",
|
|
83
|
+
"attr": { "label": "Bao cao tong hop" }
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## f-title
|
|
88
|
+
|
|
89
|
+
- Props (source): `label`
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"el": "f-title",
|
|
94
|
+
"w": "12",
|
|
95
|
+
"attr": { "label": "Danh sach ho so" }
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## f-slider
|
|
100
|
+
|
|
101
|
+
- Props (source): `items`, `itemAttr`
|
|
102
|
+
- Wraps `v-carousel` and `v-carousel-item`
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"el": "f-slider",
|
|
107
|
+
"w": "12",
|
|
108
|
+
"attr": {
|
|
109
|
+
":items": "slideItems",
|
|
110
|
+
":item-attr": { "contain": true }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## f-echart
|
|
116
|
+
|
|
117
|
+
→ See [`components-echart.md`](components-echart.md) — props, config, global `FEchartFormatter` module, examples.
|
|
118
|
+
|
|
119
|
+
## f-pdfmake
|
|
120
|
+
|
|
121
|
+
- Props (source): `data`
|
|
122
|
+
- Renders PDF in an iframe; re-renders when `data` changes (deep watch)
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"el": "f-pdfmake",
|
|
127
|
+
"w": "12",
|
|
128
|
+
"attr": {
|
|
129
|
+
":data": "pdfDefinition",
|
|
130
|
+
"height": "550"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Practical notes
|
|
138
|
+
|
|
139
|
+
1. Most `f-*` components forward unknown attrs via `v-bind="$attrs"` — Vuetify attrs still work when the child is a Vuetify control.
|
|
140
|
+
2. The literal-string rule applies only to API/path strings in Action `IN` mappings.
|
|
141
|
+
3. See `references/component-table.md` for `f-table`.
|