flet-box 1.1.1 → 1.1.3

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 (156) hide show
  1. package/AGENTS_FOR_CODE_GEN.md +284 -0
  2. package/CONTRIBUTING.md +238 -0
  3. package/README.md +17 -13
  4. package/bin/cli.js +88 -1
  5. package/bin/commands/auditFix.js +181 -27
  6. package/bin/commands/checkApi.js +14 -3
  7. package/bin/commands/checkStructure.js +368 -0
  8. package/bin/commands/checkSyntax.js +293 -0
  9. package/bin/commands/checkUi.js +666 -14
  10. package/bin/commands/create.js +18 -1
  11. package/bin/commands/createBundle.js +20 -8
  12. package/bin/commands/metrics.js +448 -0
  13. package/bin/commands/release.js +18 -0
  14. package/bin/commands/report.js +849 -0
  15. package/bin/commands/tools.js +76 -0
  16. package/bin/commands/unpack.js +39 -11
  17. package/bin/commands/verify.js +879 -0
  18. package/bin/mcp.js +280 -0
  19. package/bin/utils/bundleConfig.js +47 -3
  20. package/bin/utils/contract.js +27 -0
  21. package/bin/utils/dtsProps.js +5 -1
  22. package/bin/utils/migrationGuide.js +146 -0
  23. package/bin/utils/moduleExports.js +9 -5
  24. package/bin/utils/templates.js +248 -30
  25. package/bin/utils/toolkit.js +191 -0
  26. package/docs/README.md +26 -1
  27. package/docs/arquitectura.md +1 -1
  28. package/docs/cli/README.md +201 -11
  29. package/docs/guides/README.md +6 -0
  30. package/docs/guides/accessibility.md +2 -1
  31. package/docs/guides/ai-toolkit.md +166 -0
  32. package/docs/guides/compatibility.md +1 -1
  33. package/docs/guides/first-app.md +6 -7
  34. package/docs/guides/migration.md +92 -0
  35. package/docs/guides/minification-and-protection.md +2 -1
  36. package/docs/guides/mobile-and-platforms.md +1 -1
  37. package/docs/guides/online-updates.md +20 -6
  38. package/docs/server/deployment.md +1 -1
  39. package/docs/tools/styling.md +2 -2
  40. package/docs/tools/theme.md +139 -4
  41. package/docs/widget/Accordion.md +74 -8
  42. package/docs/widget/AdMob.md +68 -3
  43. package/docs/widget/AdSense.md +67 -2
  44. package/docs/widget/AlertDialog.md +1 -1
  45. package/docs/widget/AnimatedBox.md +80 -39
  46. package/docs/widget/AnimatedText.md +74 -18
  47. package/docs/widget/Audio.md +73 -14
  48. package/docs/widget/Avatar.md +69 -4
  49. package/docs/widget/Badge.md +68 -3
  50. package/docs/widget/BottomSheet.md +2 -2
  51. package/docs/widget/Button.md +69 -3
  52. package/docs/widget/Card.md +69 -4
  53. package/docs/widget/Carousel.md +67 -2
  54. package/docs/widget/Chart.md +67 -2
  55. package/docs/widget/Checkbox.md +74 -8
  56. package/docs/widget/Chip.md +68 -3
  57. package/docs/widget/CircularBar.md +74 -15
  58. package/docs/widget/CircularChart.md +71 -10
  59. package/docs/widget/CodeViewer.md +67 -2
  60. package/docs/widget/Column.md +68 -3
  61. package/docs/widget/Container.md +68 -3
  62. package/docs/widget/DataTable.md +67 -2
  63. package/docs/widget/Divider.md +67 -2
  64. package/docs/widget/DraggBox.md +67 -2
  65. package/docs/widget/Dropdown.md +76 -10
  66. package/docs/widget/DroppBox.md +67 -2
  67. package/docs/widget/FloatingActionButton.md +68 -3
  68. package/docs/widget/GridView.md +67 -2
  69. package/docs/widget/Icon.md +71 -5
  70. package/docs/widget/Image.md +68 -3
  71. package/docs/widget/Input.md +68 -3
  72. package/docs/widget/Inspector.md +2 -2
  73. package/docs/widget/InstallButton.md +73 -13
  74. package/docs/widget/ListTile.md +69 -3
  75. package/docs/widget/ListView.md +67 -2
  76. package/docs/widget/Maps.md +68 -3
  77. package/docs/widget/Markdown.md +74 -15
  78. package/docs/widget/MatrixRain.md +72 -11
  79. package/docs/widget/Menu.md +209 -0
  80. package/docs/widget/Modal.md +3 -3
  81. package/docs/widget/Pagination.md +68 -3
  82. package/docs/widget/ParallaxBox.md +72 -12
  83. package/docs/widget/ProgressBar.md +69 -4
  84. package/docs/widget/QRCode.md +67 -2
  85. package/docs/widget/README.md +54 -50
  86. package/docs/widget/Radio.md +76 -10
  87. package/docs/widget/Rating.md +70 -6
  88. package/docs/widget/Row.md +68 -3
  89. package/docs/widget/Skeleton.md +68 -3
  90. package/docs/widget/Slider.md +75 -9
  91. package/docs/widget/SnackBar.md +2 -2
  92. package/docs/widget/Stack.md +68 -3
  93. package/docs/widget/Stepper.md +68 -3
  94. package/docs/widget/Switch.md +74 -8
  95. package/docs/widget/Text.md +71 -4
  96. package/docs/widget/ThemePicker.md +197 -0
  97. package/docs/widget/Tooltip.md +72 -7
  98. package/docs/widget/TreeView.md +70 -10
  99. package/docs/widget/Video.md +71 -10
  100. package/package.json +10 -3
  101. package/skills/fletbox-design/SKILL.md +89 -5
  102. package/skills/fletbox-motion/SKILL.md +1 -1
  103. package/skills/fletbox-rules/SKILL.md +56 -4
  104. package/src/core/runApp.js +12 -0
  105. package/src/index.d.ts +374 -101
  106. package/src/index.js +9 -0
  107. package/src/navigations/AdaptiveScaffold.js +2 -2
  108. package/src/navigations/BottomNavigation.js +1 -1
  109. package/src/navigations/Scaffold.js +18 -6
  110. package/src/tools/useState.js +11 -4
  111. package/src/utils/colors.js +275 -0
  112. package/src/utils/errorBoundary.js +288 -0
  113. package/src/utils/index.js +10 -2
  114. package/src/utils/stackPosition.js +39 -24
  115. package/src/utils/syntaxHighlight.js +4 -1
  116. package/src/utils/themes.js +279 -3
  117. package/src/widget-factory/addChildren.js +17 -10
  118. package/src/widget-factory/assignProps.js +18 -6
  119. package/src/widget-factory/createWidget.js +7 -0
  120. package/src/widget-factory/deprecations.js +77 -0
  121. package/src/widget-factory/translateProps.js +11 -1
  122. package/src/widget-factory/warnings.js +1 -27
  123. package/src/widget-factory/widgetFactory.js +59 -17
  124. package/src/widgets/Accordion.js +21 -7
  125. package/src/widgets/Badge.js +11 -2
  126. package/src/widgets/Button.js +15 -3
  127. package/src/widgets/Carousel.js +12 -4
  128. package/src/widgets/Chart.js +7 -2
  129. package/src/widgets/Checkbox.js +1 -2
  130. package/src/widgets/Chip.js +24 -10
  131. package/src/widgets/CircularBar.js +9 -3
  132. package/src/widgets/CircularChart.js +5 -3
  133. package/src/widgets/Container.js +6 -0
  134. package/src/widgets/Divider.js +3 -1
  135. package/src/widgets/DraggBox.js +9 -0
  136. package/src/widgets/Dropdown.js +3 -3
  137. package/src/widgets/DroppBox.js +5 -0
  138. package/src/widgets/FloatingActionButton.js +1 -1
  139. package/src/widgets/Icon.js +5 -1
  140. package/src/widgets/InstallButton.js +4 -2
  141. package/src/widgets/Markdown.js +171 -103
  142. package/src/widgets/Menu.js +340 -0
  143. package/src/widgets/Modal.js +7 -1
  144. package/src/widgets/Pagination.js +10 -5
  145. package/src/widgets/ProgressBar.js +5 -4
  146. package/src/widgets/QRCode.js +4 -0
  147. package/src/widgets/Radio.js +1 -2
  148. package/src/widgets/Rating.js +9 -0
  149. package/src/widgets/Slider.js +4 -1
  150. package/src/widgets/SnackBar.js +2 -2
  151. package/src/widgets/Switch.js +1 -2
  152. package/src/widgets/Text.js +9 -5
  153. package/src/widgets/ThemePicker.js +234 -0
  154. package/src/widgets/TreeView.js +2 -1
  155. package/src/widgets/index.js +2 -0
  156. package/docs/CONTRIBUTING.md +0 -156
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @file bin/utils/toolkit.js
3
+ * @description The diagnosis toolkit, as data — one entry per question an agent
4
+ * may ask, and the command that answers it.
5
+ *
6
+ * The problem this file solves is not "there are no checkers". There are ten,
7
+ * and each one is right about its own slice. The problem is that an agent does
8
+ * not know which one to run for the question in front of it, so it runs the one
9
+ * it remembers and reports a number that answers something else.
10
+ *
11
+ * So the tools are listed here with the question each one answers, in the
12
+ * language a person uses when they are stuck, and every entry names the exact
13
+ * command. The CLI prints this list (`flet-box tools`), the report links every
14
+ * finding back to the tool that proves it, and the MCP server (`flet-box mcp`)
15
+ * exposes the same entries to an assistant that has no shell. One source, three
16
+ * mouths.
17
+ *
18
+ * The rule for membership: a tool in this catalogue **reads**. No entry may
19
+ * repair, rename, delete, build or write — those are decisions, and the assistant
20
+ * asks a human before taking one. `writes` is therefore empty on every entry;
21
+ * the field exists so a future write tool cannot be added silently.
22
+ *
23
+ * Pure data: this module imports nothing. Renderers live in
24
+ * `bin/commands/tools.js` and `bin/mcp.js`.
25
+ */
26
+
27
+ /** Bumped only when an entry's shape changes, so a cached copy can be noticed. */
28
+ export const CATALOG_VERSION = 1;
29
+
30
+ /**
31
+ * Every read-only tool, ordered from "where do I start" to "one narrow check".
32
+ *
33
+ * `params` is the JSON-Schema source used by the MCP server:
34
+ * `{ name, type: "string"|"boolean", required?, description }`.
35
+ */
36
+ export const TOOLS = [
37
+ {
38
+ id: "report",
39
+ title: "Project report",
40
+ question: "Where is the work? Which file is wrong, how wrong, and what is missing?",
41
+ cli: "flet-box report",
42
+ usage: "flet-box report [--json | --md | --html] [--tests]",
43
+ output: ["text", "json", "md", "html"],
44
+ writes: ["--html only: .fletbox/reports/report.html (or --out <file>)"],
45
+ params: [
46
+ { name: "tests", type: "boolean", description: "Also run the project's own test scripts (slow)." },
47
+ { name: "root", type: "string", description: "Project folder; defaults to the current directory." },
48
+ ],
49
+ when: [
50
+ "after any edit, before saying the work is done",
51
+ "when a screen renders but is wrong and the file is not obvious",
52
+ "when the user asks what is missing or what to do next",
53
+ ],
54
+ },
55
+ {
56
+ id: "widget_props",
57
+ title: "Widget props",
58
+ question: "Which props does this widget really accept, with types and deprecations?",
59
+ cli: "flet-box check-api --props <Widget>",
60
+ usage: "flet-box check-api --props Text",
61
+ output: ["text"],
62
+ writes: [],
63
+ params: [
64
+ { name: "widget", type: "string", required: true, description: "Widget name, e.g. Text or Container." },
65
+ { name: "root", type: "string", description: "Project folder; defaults to the current directory." },
66
+ ],
67
+ when: ["before writing a call", "when a prop silently does nothing", "when the cheatsheet looks wrong"],
68
+ },
69
+ {
70
+ id: "widget_contract",
71
+ title: "Widget contract",
72
+ question: "Do the declaration, the engine and the docs agree about this widget — and which props are dead?",
73
+ cli: "flet-box unpack <Widget> --json",
74
+ usage: "flet-box unpack Text --json",
75
+ output: ["text", "json"],
76
+ writes: [],
77
+ params: [
78
+ { name: "widget", type: "string", required: true, description: "Widget name, e.g. Text or Container." },
79
+ { name: "root", type: "string", description: "Project folder; defaults to the current directory." },
80
+ ],
81
+ when: ["when a prop is typed but does nothing", "when reading the framework's own gaps"],
82
+ },
83
+ {
84
+ id: "list_widgets",
85
+ title: "List widgets",
86
+ question: "What exists in this version of the framework?",
87
+ cli: "flet-box check-api --list",
88
+ usage: "flet-box check-api --list",
89
+ output: ["text"],
90
+ writes: [],
91
+ params: [{ name: "root", type: "string", description: "Project folder; defaults to the current directory." }],
92
+ when: ["before inventing a name", "when unsure whether a helper is real"],
93
+ },
94
+ {
95
+ id: "check",
96
+ title: "API check",
97
+ question: "Is any widget, prop or import invented?",
98
+ cli: "flet-box check-api",
99
+ usage: "flet-box check-api [--json] [--full]",
100
+ output: ["text", "json"],
101
+ writes: [],
102
+ params: [
103
+ { name: "full", type: "boolean", description: "List every warning site instead of collapsing repeated ones." },
104
+ { name: "root", type: "string", description: "Project folder; defaults to the current directory." },
105
+ ],
106
+ when: ["when a screen is blank or a widget renders nothing", "after copying code from another project"],
107
+ },
108
+ {
109
+ id: "design",
110
+ title: "Design check",
111
+ question: "Are the tokens, the scale, the tap targets, the labels and the contrast legal?",
112
+ cli: "flet-box check-ui",
113
+ usage: "flet-box check-ui [--json] [--strict] [--tokens]",
114
+ output: ["text", "json"],
115
+ writes: [],
116
+ params: [
117
+ { name: "tokens", type: "boolean", description: "Print the measured contrast of every colour token and exit." },
118
+ { name: "strict", type: "boolean", description: "Fail on contrast warnings too." },
119
+ { name: "root", type: "string", description: "Project folder; defaults to the current directory." },
120
+ ],
121
+ when: ["after building or editing a screen", "when the user says it looks off"],
122
+ },
123
+ {
124
+ id: "syntax",
125
+ title: "Parse check",
126
+ question: "Does every module parse?",
127
+ cli: "flet-box verify --only syntax --no-tests",
128
+ usage: "flet-box verify --only syntax --no-tests [--json]",
129
+ output: ["text", "json"],
130
+ writes: [],
131
+ params: [{ name: "root", type: "string", description: "Project folder; defaults to the current directory." }],
132
+ when: ["when the app is blank and the console says nothing", "before blaming the framework"],
133
+ },
134
+ {
135
+ id: "types",
136
+ title: "Type check",
137
+ question: "What does the editor complain about?",
138
+ cli: "flet-box verify --only types --no-tests",
139
+ usage: "flet-box verify --only types --no-tests [--json]",
140
+ output: ["text", "json"],
141
+ writes: [],
142
+ params: [{ name: "root", type: "string", description: "Project folder; defaults to the current directory." }],
143
+ when: ["when a widget method or prop is flagged in the editor", "after upgrading the package"],
144
+ },
145
+ {
146
+ id: "metrics",
147
+ title: "Recurring failures",
148
+ question: "Which mistakes keep coming back, and does a rule own each one?",
149
+ cli: "flet-box metrics",
150
+ usage: "flet-box metrics [--log <file>]",
151
+ output: ["text"],
152
+ writes: [],
153
+ params: [{ name: "root", type: "string", description: "Project folder; defaults to the current directory." }],
154
+ when: ["when the same finding keeps returning", "when deciding which rule to write"],
155
+ },
156
+ ];
157
+
158
+ /**
159
+ * One entry by id.
160
+ *
161
+ * @param {string} id
162
+ * @returns {object|null}
163
+ */
164
+ export const toolById = (id) => TOOLS.find((tool) => tool.id === id) || null;
165
+
166
+ /**
167
+ * The catalogue as the JSON a tool reads: stable, relative to nothing, and with
168
+ * the invariant stated in the payload so a consumer can assert it.
169
+ *
170
+ * @returns {object}
171
+ */
172
+ export const catalogJson = () => ({
173
+ tool: "flet-box tools",
174
+ version: CATALOG_VERSION,
175
+ // No entry edits a source, deletes, builds or publishes. The only file any of
176
+ // them can produce is the report's own HTML, and only when `--html` asks.
177
+ readOnly: true,
178
+ tools: TOOLS.map((tool) => ({
179
+ id: tool.id,
180
+ title: tool.title,
181
+ question: tool.question,
182
+ cli: tool.cli,
183
+ usage: tool.usage,
184
+ output: tool.output,
185
+ writes: tool.writes,
186
+ // The arguments are part of the map: a reader that cannot ask the MCP
187
+ // server still has to know that `widget_props` needs a widget name.
188
+ params: tool.params,
189
+ when: tool.when,
190
+ })),
191
+ });
package/docs/README.md CHANGED
@@ -18,6 +18,8 @@ This documentation is one continuous book. Start at **Chapter 0** and follow the
18
18
  | 11 | [The CLI](cli/README.md) | Create, run, and build projects with `flet-box` | Intermediate |
19
19
  | 12 | [Clean UI](guides/clean-ui.md) | The four skills every app ships with, the design system they hold, and the gate that enforces it | Intermediate |
20
20
  | 13 | [Accessibility](guides/accessibility.md) | The focus ring, the keyboard pass over every press, the roles the widgets declare, and the overlays that hold the keyboard | Intermediate |
21
+ | 14 | [Migrate an app to a newer FletBox](guides/migration.md) | What changed between releases, and the codemod that writes it for you | Intermediate |
22
+ | 15 | [The AI toolkit](guides/ai-toolkit.md) | The map from a question to the command, the per-file report, and the MCP server | Intermediate |
21
23
  | A | [Appendices](guides/minification-and-protection.md) | Minification, mobile, compatibility, embedding, online updates (OTA) | Advanced |
22
24
 
23
25
  > **Levels.** *Beginner:* start here and read in order. *Intermediate:* continue in order — you are comfortable with widgets. *Advanced:* for when you ship, skip on a first read.
@@ -56,6 +58,8 @@ Front cover (this page)
56
58
  → The CLI · cli/README.md
57
59
  → Clean UI · guides/clean-ui.md
58
60
  → Accessibility · guides/accessibility.md
61
+ → Migrating · guides/migration.md
62
+ → The AI toolkit · guides/ai-toolkit.md
59
63
  → Appendices (minification → mobile → compatibility → embedding → online updates)
60
64
  → The end of the book
61
65
  ```
@@ -71,4 +75,25 @@ Front cover (this page)
71
75
 
72
76
  - [Server toolkit](server/README.md) — Express/SQLite/Redis backend helpers (separate toolkit).
73
77
  - [Architecture](arquitectura.md) — how the framework is built inside.
74
- - [Contributing](CONTRIBUTING.md) — for people who add code or docs to FletBox.
78
+ - [Contributing](../CONTRIBUTING.md) — for people who add code or docs to FletBox.
79
+
80
+ ## Read this book as an app
81
+
82
+ The same pages are also a FletBox application: **[flet-box-docs](https://github.com/kuko53348/flet-box-docs)**, published to npm as its own package.
83
+
84
+ ```bash
85
+ npm install flet-box-docs # then: cd node_modules/flet-box-docs && npm install && npm run dev
86
+ ```
87
+
88
+ It is a normal FletBox project — the router, a categorized index, cross-document
89
+ Previous/Next, a light/dark toggle, an offline cache, and Capacitor wrappers for
90
+ Android and iOS — and every page is rendered by the framework's own `Markdown`
91
+ widget, so the book is also a live demo of the widget that writes it.
92
+
93
+ Its `docs/` folder is a **snapshot** of this folder, refreshed before each
94
+ release; when the app is online it reads the published source instead, so a page
95
+ added here arrives on an installed device without a new build. That is why
96
+ `flet-box-docs` carries a version of its own: it is a shipping app, and its
97
+ `npm run build` refuses to bundle until `src/constants.js` states both versions
98
+ out loud — the app's own, which must match its `package.json`, and the framework
99
+ release its pages describe.
@@ -161,4 +161,4 @@ and strips dev warnings from the shipped output. See
161
161
  - [Routing](guides/router.md)
162
162
  - [Utilities](guides/utilities.md)
163
163
  - [Frontend services](guides/frontend-services.md)
164
- - [Contributing](CONTRIBUTING.md)
164
+ - [Contributing](../CONTRIBUTING.md)
@@ -2,13 +2,13 @@
2
2
 
3
3
  The FletBox CLI helps you create, run, expand, and build FletBox applications from the terminal.
4
4
 
5
- You do not need to create every folder by hand. The CLI can create a working project, add screens and components, start a development server, and prepare a production bundle.
5
+ You do not need to create every folder by hand. The CLI can create a working project, add screens and components, start a development server, prepare a production bundle, and check the code against the API the installed framework really has.
6
6
 
7
7
  ## Before you start
8
8
 
9
9
  Install:
10
10
 
11
- - Node.js 18 or newer.
11
+ - Node.js 20.9 or newer.
12
12
  - npm.
13
13
  - A terminal such as Terminal, iTerm, PowerShell, or the VS Code terminal.
14
14
 
@@ -21,14 +21,17 @@ npm --version
21
21
 
22
22
  ## Install FletBox
23
23
 
24
- Inside the FletBox package directory:
24
+ FletBox is published to npm, so the CLI is one install away:
25
25
 
26
26
  ```bash
27
- npm install
28
- npm link
27
+ npm install -g flet-box
29
28
  ```
30
29
 
31
- After linking, the `flet-box` command is available globally on your computer.
30
+ Or run it without installing anything globally — `npx` fetches the same package:
31
+
32
+ ```bash
33
+ npx flet-box create my-app
34
+ ```
32
35
 
33
36
  Check that it works:
34
37
 
@@ -37,12 +40,22 @@ flet-box --version
37
40
  flet-box --help
38
41
  ```
39
42
 
40
- When using the published package, install it in a project with:
43
+ Inside a project the framework itself is an ordinary dependency:
41
44
 
42
45
  ```bash
43
46
  npm install flet-box
44
47
  ```
45
48
 
49
+ Cloning the repository and linking it is the exception, and it is for people
50
+ editing the framework:
51
+
52
+ ```bash
53
+ git clone https://github.com/kuko53348/flet-box.git
54
+ cd flet-box
55
+ npm install
56
+ npm link # the `flet-box` command now points at this checkout
57
+ ```
58
+
46
59
  ## Your first project
47
60
 
48
61
  Create a project with the default template:
@@ -84,9 +97,12 @@ CI: .github/workflows/build.yml publishes the web to GitHub Pages on every
84
97
  ```
85
98
 
86
99
  The first positional argument is always the project name; a flag that arrives
87
- before it is read as the name. Without `--repo` nothing is invented — the
88
- placeholder stays in both files and the workflow says which two to edit. The
89
- reason the workflow log, not the header, is the authority on the live address is
100
+ before it is read as the name. Without `--repo` nothing is invented: the
101
+ placeholder stays in `fletbox.config.json` and in the workflow header, and the
102
+ header says which part of it is still a guess. `flet-box createBundle` reads that
103
+ placeholder as "not configured" and derives the real Pages address from the
104
+ project, so the manifest is never aimed at a host that does not exist. The reason
105
+ the workflow log, not the header, is the authority on the live address is
90
106
  explained in [The Pages address of a generated app](../guides/online-updates.md).
91
107
 
92
108
  ## Project templates
@@ -574,6 +590,156 @@ alongside the app, and that file says so.
574
590
  The full contract — the 21 rules, every finding code, and how to fix one — is
575
591
  [Chapter 12, Clean UI](../guides/clean-ui.md).
576
592
 
593
+ ## Look up the API the app really has
594
+
595
+ `flet-box check-api` reads your own `src/` and reports every name that does not
596
+ belong to the installed package: a widget that does not exist, a prop the real
597
+ widget never reads, a widget called with a positional string instead of a props
598
+ object, an import from another framework, and a broken import between two of your
599
+ own modules — the last two resolved statically, so it works offline and in CI.
600
+
601
+ It imports the package's barrel for real and reads its own types, so it cannot
602
+ judge your code against an API you do not have.
603
+
604
+ ```bash
605
+ flet-box check-api # scan ./src
606
+ flet-box check-api --props Button # print one widget's real props
607
+ flet-box check-api --list # print every public export
608
+ flet-box check-api --emit-api # write .fletbox/api/cheatsheet.md
609
+ flet-box check-api --json # the findings as data
610
+ flet-box check-api --root ../my-app # scan another project
611
+ ```
612
+
613
+ Aliases: `flet-box check`, `checkApi`, `doctor`. It exits `1` when it finds an
614
+ error, which is what lets it be the `api` gate inside `flet-box verify` and the
615
+ `npm run check` a created app ships.
616
+
617
+ `--emit-api` writes the cheatsheet an assistant should read before it writes any
618
+ code for the app: every widget, every prop the package can prove, and a prop that
619
+ has been renamed marked `(deprecated → onPress)` — the old spelling still works,
620
+ so nothing else will tell you it is the one being retired. `flet-box create`
621
+ generates the file at scaffold time; after a version bump, regenerate it with the
622
+ command above. It is the API at that version, not the one you remember.
623
+
624
+ ## Unpack a widget
625
+
626
+ Every prop lives in four places, and they can disagree: the type declaration, the
627
+ engine's prop registry, the widget's own source, and its doc page.
628
+ `flet-box unpack <Widget>` cross-checks the four and labels each disagreement
629
+ instead of hiding it:
630
+
631
+ | Label | What it means |
632
+ | --- | --- |
633
+ | `DEAD` | Declared in the interface, routed by the engine nowhere and read by the widget nowhere — writing it has no effect. |
634
+ | `INVENTED` | The widget reads it, and no interface declares it. |
635
+ | `UNDOCUMENTED` | The engine handles it for this widget and the interface hides it — the editor underlines a call that works. |
636
+ | `DOC-ONLY` | The doc page promises it and the code has never heard of it. |
637
+ | `CODE-ONLY` | The code accepts it and the doc page never mentions it. |
638
+
639
+ ```bash
640
+ flet-box unpack Button # what Button really accepts, prop by prop
641
+ flet-box unpack Button --example # a paste-ready call using only verified props
642
+ flet-box unpack Modal --diff # declared vs real, and what disagrees
643
+ flet-box unpack Button --json # the same contract as data
644
+ flet-box unpack --all # every widget → .fletbox/api/api.json
645
+ flet-box unpack --all --md # and the readable api.md beside it
646
+ flet-box unpack --all --json # the whole surface on stdout, writing nothing
647
+ flet-box unpack Button --root ../my-app # read another project's package
648
+ ```
649
+
650
+ `--example` is the answer to "what can I paste". It is built only from props the
651
+ four surfaces agree on, never carries a renamed one, samples no blind `width` or
652
+ `height` (a number pasted into `Switch` collapses it), and never drops a required
653
+ prop — so the call it prints runs.
654
+
655
+ `--all` writes the whole verified surface to `.fletbox/api/api.json`, the file a
656
+ created app's assistant reads as data; `--md` puts `api.md` beside it and
657
+ `--json` prints the same tree to stdout instead of writing anything. `npm run
658
+ api` in a created app is `unpack --all --md`.
659
+
660
+ ## Verify everything at once
661
+
662
+ `flet-box verify` is the single command: it parses every module, then runs the
663
+ anti-hallucination check, the type check (the project's own `jsconfig.json`
664
+ through TypeScript — the same service the editor uses, so a widget declared as
665
+ a bare `HTMLElement` and the `widget.update({ … })` call it rejects are a gate
666
+ failure with a line, not a squiggle to be ignored), the clean-UI check, the
667
+ structural check and the prop contract **in parallel**, and then runs whichever
668
+ test scripts the project declares — one report, one exit code. It is the command
669
+ to run after every edit: the report names the gate, the file at `line:column`
670
+ and what to do about it, instead of making you run seven commands and remember
671
+ which one failed.
672
+
673
+ ```bash
674
+ flet-box verify # every gate and every suite, one report
675
+ flet-box verify --only syntax # one gate: syntax | api | types | ui | structure | surface | tests
676
+ flet-box verify --only tests # the project's own suites, nothing else
677
+ flet-box verify --fix # the mechanical repair first, then the gates
678
+ flet-box verify --json # the report as data
679
+ flet-box verify --watch # re-runs the fast gates on every edit (no suites)
680
+ flet-box verify --no-tests # the static gates only; run the suites yourself
681
+ flet-box run --verify # the same, while the dev server runs
682
+ ```
683
+
684
+ Every generated app ships it as `npm run verify`. The gates read the installed
685
+ package, so they cannot judge your code against an API you do not have.
686
+
687
+ The gates, and what each one owns:
688
+
689
+ | Gate | What it proves |
690
+ | --- | --- |
691
+ | `syntax` | Every module loads. Each `.js`/`.mjs`/`.cjs` outside `node_modules`, `www` and `dist` is handed to `node --check` — the parser the runtime uses — and a parse error is reported at `file:line:column` with the offending source line, a caret under the character and a hint: an unclosed brace, a backtick that never closes, a smart quote that only looks like a quote. |
692
+ | `api` | The code only names widgets and props that exist, and its own modules resolve each other. |
693
+ | `ui` | The code is on the tokens, on the scale, and every control has a name. |
694
+ | `structure` | Two of your modules do not import each other in a circle, every module lives where the project expects it, and no screen writes the DOM by hand. |
695
+ | `surface` | Every prop a widget reads is declared, and every declared prop is read. |
696
+ | `tests` | The project's own suites run and pass. `test`, `test:browser` and `test:visual` are run one after another when `package.json` declares them; a failing suite's own last output is the finding, which is where the rule is named. A project that declares none — a generated app — gets a skipped step, not a green one. |
697
+
698
+ The parse gate runs first because the other four read code as text. A file that
699
+ does not load is a line, not a finding about an invented prop, and telling the
700
+ two apart is the difference between one edit and a guess.
701
+
702
+ Every finding prints the same four things: the file at `line:column`, the code,
703
+ what is wrong and a `→` suggestion. Warnings are printed too, under *what to
704
+ review* — they do not fail the run, but they name the same line, which is the
705
+ only form in which an agent can act on them.
706
+
707
+ `--fix` runs `flet-box audit-fix` first: it rewrites what it can prove — a
708
+ mistyped prop, a wrong relative path, a missing import — and then the gates
709
+ read the result. A typo is mechanical, and it should never reach you as work
710
+ to do.
711
+
712
+ ## The north metric
713
+
714
+ Every `flet-box verify` run appends a row to the project's log —
715
+ `.fletbox/metrics/generations.md` for a generated app, `metrics/generations.md`
716
+ for this repository — with the time, the project, whether the gates were green,
717
+ which gates failed and which codes they reported. **Every** run, green or not: a
718
+ log that keeps only the successes cannot tell a correction from a first try.
719
+
720
+ ```bash
721
+ flet-box metrics # the metric and the failures that recur
722
+ flet-box metrics --log <file> # read another log
723
+ ```
724
+
725
+ A **generation** is a run of failing rows closed by the first green one. The
726
+ **north metric** is the share of generations whose *first* run was green — the
727
+ share of code that passed the gate with no correction at all. It is the number
728
+ that moves when the code gets better, not when the report gets softer.
729
+
730
+ The same command prints the three failures that recur most often and the rule
731
+ each one should belong to, and it **exits non-zero** when a code has come back
732
+ three times with no rule behind it. That is the loop closing: a code that keeps
733
+ coming back is a rule that has not been written yet.
734
+
735
+ The log also holds a **Gate defects** table. A code written there with its
736
+ window — the first and the last day it explains — is the framework's debt, not
737
+ the project's correction: those runs are left out of the metric, never asked to
738
+ justify a rule, and printed on their own (`fixed`, or `⚠ OPEN`). A run after the
739
+ window's last day counts again, so an old row can never silence the same mistake
740
+ coming back. The table is data in the log, not a list inside the command: a
741
+ project records what it proved, and the next release cannot rewrite its past.
742
+
577
743
  ## Command reference
578
744
 
579
745
 
@@ -607,6 +773,21 @@ The full contract — the 21 rules, every finding code, and how to fix one — i
607
773
  | `flet-box check-ui` | Runs the clean-UI gate over `src/`: tokens, scale, tap targets, labels, contrast. |
608
774
  | `flet-box check-ui --tokens` | Prints the measured contrast of every color token, on the background and on the surface. |
609
775
  | `flet-box check-ui --strict` | Makes the contrast warnings fail the run, not just the errors. |
776
+ | `flet-box check-api` | Checks that every widget, prop and import your code names really exists. |
777
+ | `flet-box check-api --props <Widget>` | Prints the real props of one widget. |
778
+ | `flet-box check-api --list` | Prints every public export. |
779
+ | `flet-box check-api --emit-api` | Writes `.fletbox/api/cheatsheet.md`, the API an assistant reads first. |
780
+ | `flet-box unpack <Widget>` | Cross-checks a widget's four surfaces and labels what disagrees. |
781
+ | `flet-box unpack <Widget> --example` | Prints a paste-ready call built only from verified props. |
782
+ | `flet-box unpack <Widget> --diff` | Prints the reconciliation alone: declared vs real, and what disagrees. |
783
+ | `flet-box unpack --all` | Writes the whole verified surface to `.fletbox/api/api.json`. |
784
+ | `flet-box unpack --all --md` | Adds the readable `api.md` beside it. |
785
+ | `flet-box verify` | Runs every gate at once: one report, one exit code. |
786
+ | `flet-box verify --no-tests` | The static gates only, for a pipeline that runs the suites in their own jobs. |
787
+ | `flet-box verify --fix` | Runs the mechanical repair first, then the gates. |
788
+ | `flet-box metrics` | Reads the project's log: the north metric and the failures that recur. |
789
+ | `flet-box audit-fix` | Rewrites what it can prove: a broken import, a mistyped prop, a renamed prop. |
790
+ | `flet-box audit-fix --only migrations` | Applies only the renames from [the migration guide](../guides/migration.md). |
610
791
  | `flet-box pkg` | Opens the package manager. |
611
792
  | `flet-box --version` | Shows the CLI version. |
612
793
  | `flet-box --help` | Shows the command list. |
@@ -636,9 +817,17 @@ For normal application development, `npm install flet-box` is usually enough.
636
817
 
637
818
  ### `flet-box: command not found`
638
819
 
639
- The CLI is not linked or installed globally. From the FletBox package directory, run:
820
+ The CLI is not installed globally. Install the published package:
821
+
822
+ ```bash
823
+ npm install -g flet-box
824
+ ```
825
+
826
+ If you are working from a clone of the framework instead, link that checkout so the
827
+ command points at the code you are editing:
640
828
 
641
829
  ```bash
830
+ cd flet-box
642
831
  npm install
643
832
  npm link
644
833
  ```
@@ -690,6 +879,7 @@ npm install --save-dev esbuild
690
879
  - Learn the basics in [Start here](../widget/START_HERE.md).
691
880
  - Learn complete app structures in [Build your first FletBox app](../guides/app-templates.md).
692
881
  - Explore every widget in the [widget documentation](../widget/README.md).
882
+ - Ask "where is the work?" with [the AI toolkit](../guides/ai-toolkit.md) — `flet-box report`, `flet-box tools`, `flet-box mcp`.
693
883
 
694
884
  ---
695
885
 
@@ -16,6 +16,12 @@ This directory is the **conceptual index** of FletBox: how to build apps, set up
16
16
  - **[Accessibility](accessibility.md)** — Chapter 13 · the focus ring, the
17
17
  keyboard pass over every press, the roles and states the widgets declare, and
18
18
  the overlays that hold the keyboard.
19
+ - **[Migrate an app to a newer FletBox](migration.md)** — Chapter 14 · what
20
+ changed between releases, the "de X a Y" table, and the codemod that writes
21
+ the new names for you.
22
+ - **[The AI toolkit](ai-toolkit.md)** — Chapter 15 · the map from a question to
23
+ the command (`flet-box tools`), the per-file diagnosis (`flet-box report`), and
24
+ the same tools over MCP stdio (`flet-box mcp`).
19
25
  - **[Widget structure](widget-structure.md)** — the canonical, modular shape every widget follows (and how new ones are added).
20
26
 
21
27
  ## Appendices (Advanced — for shipping)
@@ -158,6 +158,7 @@ is already in place; the table exists so you know what not to duplicate.
158
158
  | `Switch` | `switch` | `aria-checked` |
159
159
  | `Checkbox` | `checkbox` | `aria-checked` |
160
160
  | `Radio` / `Rating` | `radio` / `radiogroup` | `aria-checked` |
161
+ | `ThemePicker` | `radiogroup` / `radio` | `aria-checked`; one Tab stop per swatch, and Enter or Space picks |
161
162
  | `Slider` | `slider` | `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, `aria-orientation` |
162
163
  | `ProgressBar`, `CircularBar` | `progressbar` | `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, `aria-busy` while indeterminate |
163
164
  | `Dropdown` | `combobox` | `aria-expanded`, `aria-controls`, `aria-activedescendant`, `aria-invalid`, `aria-labelledby` |
@@ -276,7 +277,7 @@ forbids. The runtime half lives in `/tests/a11y.html`.
276
277
  ## Continue reading
277
278
 
278
279
  - **Previous:** [Clean UI](clean-ui.md) — Chapter 12
279
- - **Next:** [Minify and protect a FletBox build](minification-and-protection.md) — Appendix A
280
+ - **Next:** [Migrate an app to a newer FletBox](migration.md) — Chapter 14
280
281
  - **Index:** [Guides index](README.md) · [The FletBox Book](../README.md)
281
282
 
282
283
  You are reading **Chapter 13 · Accessibility**.