flet-box 1.0.5 → 1.0.7
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 +28 -1
- package/bin/cli.js +85 -18
- package/bin/commands/auditFix.js +682 -0
- package/bin/commands/checkApi.js +7 -5
- package/bin/commands/create.js +40 -10
- package/bin/commands/createBundle.js +54 -1
- package/bin/commands/images.js +349 -0
- package/bin/commands/pruneAssets.js +170 -0
- package/bin/commands/release.js +34 -1
- package/bin/commands/runCloudflare.js +47 -9
- package/bin/commands/runServer.js +81 -24
- package/bin/commands/toPng.js +346 -0
- package/bin/commands/unpack.js +1173 -0
- package/bin/ota/loader.js +90 -0
- package/bin/utils/appSources.js +101 -0
- package/bin/utils/bundleConfig.js +166 -0
- package/bin/utils/dtsProps.js +147 -0
- package/bin/utils/imageTools.js +271 -0
- package/bin/utils/images/bmp.js +99 -0
- package/bin/utils/images/gif.js +244 -0
- package/bin/utils/images/index.js +163 -0
- package/bin/utils/images/jpeg.js +643 -0
- package/bin/utils/images/png.js +486 -0
- package/bin/utils/images/unsupported.js +29 -0
- package/bin/utils/neutralise.js +109 -6
- package/bin/utils/templates.js +307 -64
- package/docs/cli/README.md +82 -0
- package/docs/guides/online-updates.md +57 -9
- package/docs/widget/Accordion.md +1 -0
- package/docs/widget/AdMob.md +1 -0
- package/docs/widget/AdSense.md +1 -0
- package/docs/widget/AnimatedBox.md +1 -0
- package/docs/widget/AnimatedText.md +1 -0
- package/docs/widget/Audio.md +2 -1
- package/docs/widget/Avatar.md +12 -3
- package/docs/widget/Badge.md +1 -0
- package/docs/widget/Button.md +1 -0
- package/docs/widget/Card.md +1 -0
- package/docs/widget/Carousel.md +1 -0
- package/docs/widget/Chart.md +1 -0
- package/docs/widget/Checkbox.md +1 -0
- package/docs/widget/Chip.md +1 -0
- package/docs/widget/CircularBar.md +1 -0
- package/docs/widget/CircularChart.md +1 -0
- package/docs/widget/CodeViewer.md +1 -0
- package/docs/widget/Column.md +1 -0
- package/docs/widget/Container.md +1 -0
- package/docs/widget/DataTable.md +1 -0
- package/docs/widget/Divider.md +1 -0
- package/docs/widget/DraggBox.md +3 -2
- package/docs/widget/Dropdown.md +3 -0
- package/docs/widget/DroppBox.md +2 -1
- package/docs/widget/FloatingActionButton.md +1 -0
- package/docs/widget/GridView.md +1 -0
- package/docs/widget/Icon.md +1 -0
- package/docs/widget/Image.md +11 -3
- package/docs/widget/Input.md +1 -0
- package/docs/widget/InstallButton.md +1 -0
- package/docs/widget/ListTile.md +1 -0
- package/docs/widget/ListView.md +1 -0
- package/docs/widget/Maps.md +188 -0
- package/docs/widget/Markdown.md +1 -0
- package/docs/widget/MatrixRain.md +1 -0
- package/docs/widget/Pagination.md +1 -0
- package/docs/widget/ParallaxBox.md +1 -0
- package/docs/widget/ProgressBar.md +1 -0
- package/docs/widget/QRCode.md +1 -0
- package/docs/widget/README.md +12 -10
- package/docs/widget/Radio.md +1 -0
- package/docs/widget/Rating.md +1 -0
- package/docs/widget/Row.md +1 -0
- package/docs/widget/Skeleton.md +1 -0
- package/docs/widget/Slider.md +1 -0
- package/docs/widget/Stack.md +1 -0
- package/docs/widget/Stepper.md +1 -0
- package/docs/widget/Switch.md +1 -0
- package/docs/widget/Text.md +1 -0
- package/docs/widget/Tooltip.md +11 -13
- package/docs/widget/TreeView.md +1 -0
- package/docs/widget/Video.md +3 -2
- package/package.json +2 -2
- package/src/core/hmr-client.js +129 -34
- package/src/index.d.ts +132 -0
- package/src/index.js +1 -0
- package/src/navigations/AppBar.js +15 -4
- package/src/navigations/Drawer.js +9 -1
- package/src/widget-factory/translateProps.js +32 -1
- package/src/widgets/Avatar.js +228 -131
- package/src/widgets/Container.js +13 -0
- package/src/widgets/Dropdown.js +33 -1
- package/src/widgets/Image.js +102 -3
- package/src/widgets/Maps.js +1495 -0
- package/src/widgets/Tooltip.js +12 -2
- package/src/widgets/index.js +1 -0
package/README.md
CHANGED
|
@@ -101,11 +101,38 @@ flet-box check-api # scan src/ for invented widgets/props
|
|
|
101
101
|
flet-box check-api --props Button # print the real props of one widget
|
|
102
102
|
flet-box check-api --list # print every public export
|
|
103
103
|
flet-box check-api --emit-api # (re)generate .fletbox/api/cheatsheet.md
|
|
104
|
+
|
|
105
|
+
# Read one widget from every surface at once (offline)
|
|
106
|
+
flet-box unpack Text # each prop, where it goes, and what is dead
|
|
107
|
+
flet-box unpack Text --example # a paste-ready call, built only from verified props
|
|
108
|
+
flet-box unpack Modal --diff # where types, engine, docs and code disagree
|
|
109
|
+
flet-box unpack --all --md # every widget, as .fletbox/api/api.json + api.md
|
|
110
|
+
|
|
111
|
+
# Repair (writes files; run `npm run check` afterwards to confirm)
|
|
112
|
+
flet-box audit-fix # fix imports and prop typos in one pass
|
|
113
|
+
flet-box audit-fix --only imports # just the import wiring
|
|
114
|
+
flet-box audit-fix --only props # just `chilldren` → `children`
|
|
104
115
|
```
|
|
105
116
|
|
|
106
117
|
In a generated app these are also `npm run check` (and `npm run check -- --props Button`),
|
|
107
118
|
because `flet-box create` writes `scripts/check-app.mjs` plus the `AGENTS.md` contract
|
|
108
|
-
that points any AI assistant at the real API.
|
|
119
|
+
that points any AI assistant at the real API. `npm run fix` runs `audit-fix`.
|
|
120
|
+
|
|
121
|
+
`audit-fix` only rewrites a name when exactly one real name is close enough to be
|
|
122
|
+
certain — a wrong "fix" that happens to be a valid prop changes the UI silently and
|
|
123
|
+
silences the gate, which is worse than the error it replaced. Anything ambiguous is
|
|
124
|
+
printed under *Left for you to decide* and the file is not touched.
|
|
125
|
+
|
|
126
|
+
`flet-box unpack` answers the question the types alone cannot: a prop can be declared,
|
|
127
|
+
documented and still reach nothing. It cross-checks the four places a prop lives —
|
|
128
|
+
`src/index.d.ts`, the `ALL_PROPS` translation table, the widget's own source, its doc
|
|
129
|
+
page — and labels each disagreement: **DEAD** (typed, read by nothing), **INVENTED**
|
|
130
|
+
(read by the widget, declared nowhere), **UNDOCUMENTED** (the engine routes it, the
|
|
131
|
+
interface hides it), **DOC-ONLY** and **CODE-ONLY** (the page and the code each promise
|
|
132
|
+
something the other never heard of). `--example` uses only that verified set, so what it
|
|
133
|
+
prints is the whole API you can safely paste; `unpack --all --json` writes the same facts
|
|
134
|
+
as `.fletbox/api/api.json` for the AI agent inside an app, which is the surface it should
|
|
135
|
+
invent against.
|
|
109
136
|
|
|
110
137
|
## Android and iOS
|
|
111
138
|
|
package/bin/cli.js
CHANGED
|
@@ -14,17 +14,19 @@ import fs from "fs";
|
|
|
14
14
|
import path from "path";
|
|
15
15
|
import { createProject } from "./commands/create.js";
|
|
16
16
|
import { checkApi } from "./commands/checkApi.js";
|
|
17
|
+
import { auditFix } from "./commands/auditFix.js";
|
|
18
|
+
import { toPng } from "./commands/toPng.js";
|
|
19
|
+
import { images } from "./commands/images.js";
|
|
20
|
+
import { pruneAssets } from "./commands/pruneAssets.js";
|
|
21
|
+
import { unpack } from "./commands/unpack.js";
|
|
17
22
|
import { packageManager } from "./commands/package.js";
|
|
18
23
|
import { createBundle } from "./commands/createBundle.js";
|
|
19
24
|
import { buildAndroid } from "./commands/buildAndroid.js";
|
|
20
25
|
import { buildIOS } from "./commands/buildIOS.js";
|
|
21
26
|
import { runNative } from "./commands/runNative.js";
|
|
22
|
-
import { runDevServer } from "./commands/runServer.js";
|
|
23
27
|
import { createScreen } from "./commands/createScreen.js";
|
|
24
28
|
import { createComponent } from "./commands/createComponent.js";
|
|
25
29
|
import { killServer } from "./commands/killServer.js";
|
|
26
|
-
import { runBundle } from "./commands/runBundle.js";
|
|
27
|
-
import { runCloudflareDemo } from "./commands/runCloudflare.js";
|
|
28
30
|
import { release } from "./commands/release.js";
|
|
29
31
|
import { c, gradient, section, banner, divider, width, setupCtrlC } from "./utils/colors.js";
|
|
30
32
|
|
|
@@ -66,6 +68,7 @@ ${cmd("create --adaptive", "responsive (mobile + desktop)")}
|
|
|
66
68
|
${cmd("create --blank", "empty project")}
|
|
67
69
|
${cmd("create --full", "AppBar+Drawer+BottomNav")}
|
|
68
70
|
${cmd("create --sidebar", "desktop (Sidebar+AppBar)")}
|
|
71
|
+
${cmd("create --template <name>", "same four by name: basic|adaptive|blank|full|sidebar")}
|
|
69
72
|
${cmd("create --repo <user/repo>", "set GitHub repo for OTA updates")}
|
|
70
73
|
${cmd("screen <name|num>", "Create screen(s) (1-10)")}
|
|
71
74
|
${cmd("component <name|num>", "Create component(s) (1-10)")}
|
|
@@ -79,6 +82,23 @@ ${cmd(" └─ --props <Widget>", "print one widget's real props")}
|
|
|
79
82
|
${cmd(" └─ --list", "list every widget")}
|
|
80
83
|
${cmd(" └─ --emit-api", "write .fletbox/api/cheatsheet.md")}
|
|
81
84
|
${cmd(" └─ alias", "check | checkApi | doctor")}
|
|
85
|
+
${cmd("unpack <Widget>", "Everything one widget really accepts, and what works")}
|
|
86
|
+
${cmd(" └─ --example", "paste-ready call using only verified props")}
|
|
87
|
+
${cmd(" └─ --diff", "what the docs or types claim that the code ignores")}
|
|
88
|
+
${cmd(" └─ unpack --all", "every widget; --json / --md write .fletbox/api/")}
|
|
89
|
+
${cmd("audit-fix", "Rewrite broken imports, missing imports and misspelled props")}
|
|
90
|
+
${cmd(" └─ --only imports|props", "run one repair instead of both")}
|
|
91
|
+
${cmd(" └─ alias", "fix-imports | fix-path-imports | auditFix")}
|
|
92
|
+
${cmd("to-png [dir]", "Convert JPEG/BMP/GIF images to PNG, no dependencies")}
|
|
93
|
+
${cmd(" └─ --replace", "remove each source after its PNG was written and read back")}
|
|
94
|
+
${cmd(" └─ --out <dir> | --force | --flat | --dry-run", "where to write, and what to touch")}
|
|
95
|
+
${cmd(" └─ alias", "topng | convert-images")}
|
|
96
|
+
${cmd("images [dir]", "Shrink JPG/PNG photos to a byte budget with the platform WebP encoder")}
|
|
97
|
+
${cmd(" └─ --budget <KB> | --width <px>", "what 'small enough' means (default 40KB)")}
|
|
98
|
+
${cmd(" └─ --install", "install the encoder this machine is missing")}
|
|
99
|
+
${cmd(" └─ alias", "optimize-images | imgs")}
|
|
100
|
+
${cmd("prune-assets [dir]", "Delete images the app never references (dry run unless --apply)")}
|
|
101
|
+
${cmd(" └─ alias", "prune")}
|
|
82
102
|
${cmd("build android", "Build Android debug APK")}
|
|
83
103
|
${cmd("build android --release", "Build unsigned release APK/AAB to sign yourself")}
|
|
84
104
|
${cmd("build ios", "Build iOS Simulator app (macOS + Xcode)")}
|
|
@@ -89,7 +109,7 @@ ${cmd(" └─ --livereload", "hot reload on the device")}
|
|
|
89
109
|
${cmd("run", "Static file server")}
|
|
90
110
|
${cmd("run --hot", "Dev server with hot reload")}
|
|
91
111
|
${cmd("run-spa", "SPA + hot reload")}
|
|
92
|
-
${cmd("cloudflare", "
|
|
112
|
+
${cmd("cloudflare [dir]", "Build the bundle, then tunnel it: public HTTPS demo link")}
|
|
93
113
|
${cmd(" └─ alias", "cf | demo | tunnel")}
|
|
94
114
|
${cmd("run-bundle [dir]", "Build & serve the bundle (single app.js)")}
|
|
95
115
|
${cmd("pkg", "Open the package manager")}
|
|
@@ -113,6 +133,8 @@ ${section("✨", "EXAMPLES")}
|
|
|
113
133
|
${c("gray", "cd my-app && flet-box run-spa")}
|
|
114
134
|
${c("gray", "flet-box run-bundle # build & preview production")}
|
|
115
135
|
${c("gray", "flet-box cloudflare # public HTTPS demo link in console")}
|
|
136
|
+
${c("gray", "flet-box unpack Text --example # what Text really accepts, as code")}
|
|
137
|
+
${c("gray", "flet-box unpack --all --json # dump the verified API for your AI agent")}
|
|
116
138
|
${c("gray", "flet-box kill-server 8000 # kill the parasite server")}
|
|
117
139
|
|
|
118
140
|
${divider("", "#3730a3")}
|
|
@@ -168,6 +190,16 @@ const parseFlags = () => {
|
|
|
168
190
|
return flags;
|
|
169
191
|
};
|
|
170
192
|
|
|
193
|
+
/**
|
|
194
|
+
* The bundle directory a command works on: the second argument when it is a
|
|
195
|
+
* plain name, `www` otherwise. Flags never reach here, so `flet-box cloudflare
|
|
196
|
+
* --port 9000` cannot mistake `--port` for a target.
|
|
197
|
+
*
|
|
198
|
+
* @returns {string}
|
|
199
|
+
*/
|
|
200
|
+
const bundleTarget = () =>
|
|
201
|
+
args[1] && /^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/.test(args[1]) ? args[1] : "www";
|
|
202
|
+
|
|
171
203
|
/**
|
|
172
204
|
* Guards commands that must run inside a FletBox project directory.
|
|
173
205
|
* Exits with a descriptive error when `src/app.js` is not found in the
|
|
@@ -210,7 +242,7 @@ async function main() {
|
|
|
210
242
|
console.log(
|
|
211
243
|
c(
|
|
212
244
|
"gray",
|
|
213
|
-
"Usage: flet-box create <project-name> [--adaptive|--blank|--full|--sidebar|--repo user/repo]",
|
|
245
|
+
"Usage: flet-box create <project-name> [--adaptive|--blank|--full|--sidebar|--template <name>|--repo user/repo]",
|
|
214
246
|
),
|
|
215
247
|
);
|
|
216
248
|
process.exit(1);
|
|
@@ -277,6 +309,44 @@ async function main() {
|
|
|
277
309
|
break;
|
|
278
310
|
}
|
|
279
311
|
|
|
312
|
+
case "unpack": {
|
|
313
|
+
const { exitCode } = await unpack(args.slice(1));
|
|
314
|
+
if (exitCode) process.exit(exitCode);
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
case "audit-fix":
|
|
319
|
+
case "auditFix":
|
|
320
|
+
case "fix-imports":
|
|
321
|
+
case "fix-path-imports": {
|
|
322
|
+
const { exitCode } = await auditFix(args.slice(1));
|
|
323
|
+
if (exitCode) process.exit(exitCode);
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
case "to-png":
|
|
328
|
+
case "topng":
|
|
329
|
+
case "convert-images": {
|
|
330
|
+
const { exitCode } = await toPng(args.slice(1));
|
|
331
|
+
if (exitCode) process.exit(exitCode);
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
case "images":
|
|
336
|
+
case "optimize-images":
|
|
337
|
+
case "imgs": {
|
|
338
|
+
const { exitCode } = await images(args.slice(1));
|
|
339
|
+
if (exitCode) process.exit(exitCode);
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
case "prune-assets":
|
|
344
|
+
case "prune": {
|
|
345
|
+
const { exitCode } = await pruneAssets(args.slice(1));
|
|
346
|
+
if (exitCode) process.exit(exitCode);
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
|
|
280
350
|
case "build":
|
|
281
351
|
if (args[1] === "android") {
|
|
282
352
|
buildAndroid(args.slice(2));
|
|
@@ -323,7 +393,11 @@ async function main() {
|
|
|
323
393
|
runNative(args.slice(1));
|
|
324
394
|
break;
|
|
325
395
|
}
|
|
326
|
-
|
|
396
|
+
// The server commands are the only ones that pull in `ws`/`chokidar`,
|
|
397
|
+
// which are devDependencies: a consumer installing `flet-box` from npm
|
|
398
|
+
// has neither, so loading them at module scope would break every CLI
|
|
399
|
+
// command for them. Import them when a server is actually started.
|
|
400
|
+
await (await import("./commands/runServer.js")).runDevServer({
|
|
327
401
|
spaMode: false,
|
|
328
402
|
hotReload: flags.hot,
|
|
329
403
|
port: flags.port,
|
|
@@ -336,16 +410,8 @@ async function main() {
|
|
|
336
410
|
case "runBundle":
|
|
337
411
|
case "preview": {
|
|
338
412
|
ensureProject();
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
const targetDir =
|
|
342
|
-
args[1] &&
|
|
343
|
-
/^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/.test(args[1]) &&
|
|
344
|
-
!args[1].startsWith("-")
|
|
345
|
-
? args[1]
|
|
346
|
-
: "www";
|
|
347
|
-
await runBundle({
|
|
348
|
-
target: targetDir,
|
|
413
|
+
await (await import("./commands/runBundle.js")).runBundle({
|
|
414
|
+
target: bundleTarget(),
|
|
349
415
|
port: flags.port,
|
|
350
416
|
askPort: !flags.portExplicit,
|
|
351
417
|
logRequests: flags.logRequests,
|
|
@@ -357,7 +423,7 @@ async function main() {
|
|
|
357
423
|
case "runSpa":
|
|
358
424
|
case "spa":
|
|
359
425
|
ensureProject();
|
|
360
|
-
await runDevServer({
|
|
426
|
+
await (await import("./commands/runServer.js")).runDevServer({
|
|
361
427
|
spaMode: true,
|
|
362
428
|
hotReload: true,
|
|
363
429
|
port: flags.port,
|
|
@@ -371,7 +437,8 @@ async function main() {
|
|
|
371
437
|
case "demo":
|
|
372
438
|
case "tunnel":
|
|
373
439
|
ensureProject();
|
|
374
|
-
await runCloudflareDemo({
|
|
440
|
+
await (await import("./commands/runCloudflare.js")).runCloudflareDemo({
|
|
441
|
+
target: bundleTarget(),
|
|
375
442
|
port: flags.port,
|
|
376
443
|
logRequests: flags.logRequests,
|
|
377
444
|
});
|