flet-box 1.0.4 → 1.0.6
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 +10 -0
- package/bin/cli.js +23 -7
- package/bin/commands/checkApi.js +761 -0
- package/bin/commands/create.js +77 -5
- package/bin/utils/dtsProps.js +191 -0
- package/bin/utils/moduleExports.js +165 -0
- package/bin/utils/neutralise.js +64 -0
- package/bin/utils/templates.js +366 -27
- package/docs/CONTRIBUTING.md +156 -0
- package/docs/README.md +68 -0
- package/docs/arquitectura.md +164 -0
- package/docs/cli/README.md +542 -0
- package/docs/guides/README.md +33 -0
- package/docs/guides/app-templates.md +197 -0
- package/docs/guides/compatibility.md +95 -0
- package/docs/guides/embedding.md +284 -0
- package/docs/guides/first-app.md +208 -0
- package/docs/guides/frontend-services.md +171 -0
- package/docs/guides/minification-and-protection.md +260 -0
- package/docs/guides/mobile-and-platforms.md +439 -0
- package/docs/guides/online-updates.md +196 -0
- package/docs/guides/router.md +282 -0
- package/docs/guides/state.md +283 -0
- package/docs/guides/syntax-philosophy.md +150 -0
- package/docs/guides/utilities.md +241 -0
- package/docs/guides/widget-structure.md +163 -0
- package/docs/server/README.md +68 -0
- package/docs/server/START_HERE.md +121 -0
- package/docs/server/api.md +225 -0
- package/docs/server/data-services.md +300 -0
- package/docs/server/deployment.md +113 -0
- package/docs/server/security.md +196 -0
- package/docs/services/README.md +79 -0
- package/docs/services/RamStore.md +84 -0
- package/docs/services/Session.md +84 -0
- package/docs/services/Storage.md +88 -0
- package/docs/services/http.md +86 -0
- package/docs/tools/README.md +138 -0
- package/docs/tools/animation.md +87 -0
- package/docs/tools/async-ids-log.md +80 -0
- package/docs/tools/device.md +132 -0
- package/docs/tools/introspection.md +67 -0
- package/docs/tools/lists.md +96 -0
- package/docs/tools/markdown.md +79 -0
- package/docs/tools/reactivity.md +288 -0
- package/docs/tools/state.md +103 -0
- package/docs/tools/styling.md +92 -0
- package/docs/tools/text-and-time.md +89 -0
- package/docs/tools/theme.md +102 -0
- package/docs/tools/validation.md +75 -0
- package/docs/tools/visual-effects.md +84 -0
- package/docs/widget/Accordion.md +144 -0
- package/docs/widget/AdMob.md +144 -0
- package/docs/widget/AdSense.md +133 -0
- package/docs/widget/AdaptiveScaffold.md +105 -0
- package/docs/widget/AlertDialog.md +103 -0
- package/docs/widget/AnimatedBox.md +130 -0
- package/docs/widget/AnimatedText.md +123 -0
- package/docs/widget/AppBar.md +118 -0
- package/docs/widget/Audio.md +135 -0
- package/docs/widget/Avatar.md +119 -0
- package/docs/widget/Badge.md +128 -0
- package/docs/widget/BottomNavigation.md +116 -0
- package/docs/widget/BottomSheet.md +125 -0
- package/docs/widget/Button.md +137 -0
- package/docs/widget/COMMON_PROPS.md +150 -0
- package/docs/widget/Card.md +125 -0
- package/docs/widget/Carousel.md +151 -0
- package/docs/widget/Chart.md +151 -0
- package/docs/widget/Checkbox.md +118 -0
- package/docs/widget/Chip.md +126 -0
- package/docs/widget/CircularBar.md +168 -0
- package/docs/widget/CircularChart.md +164 -0
- package/docs/widget/CodeViewer.md +130 -0
- package/docs/widget/CollapsibleSideBar.md +112 -0
- package/docs/widget/Column.md +129 -0
- package/docs/widget/Container.md +136 -0
- package/docs/widget/DataTable.md +150 -0
- package/docs/widget/Divider.md +109 -0
- package/docs/widget/DraggBox.md +129 -0
- package/docs/widget/Drawer.md +135 -0
- package/docs/widget/DrawerItem.md +98 -0
- package/docs/widget/Dropdown.md +139 -0
- package/docs/widget/DroppBox.md +152 -0
- package/docs/widget/FloatingActionButton.md +120 -0
- package/docs/widget/GridView.md +140 -0
- package/docs/widget/Icon.md +117 -0
- package/docs/widget/Image.md +125 -0
- package/docs/widget/Input.md +151 -0
- package/docs/widget/Inspector.md +92 -0
- package/docs/widget/InstallButton.md +128 -0
- package/docs/widget/ListTile.md +132 -0
- package/docs/widget/ListView.md +138 -0
- package/docs/widget/Markdown.md +175 -0
- package/docs/widget/MatrixRain.md +122 -0
- package/docs/widget/Modal.md +129 -0
- package/docs/widget/Pagination.md +135 -0
- package/docs/widget/ParallaxBox.md +128 -0
- package/docs/widget/ProgressBar.md +130 -0
- package/docs/widget/QRCode.md +117 -0
- package/docs/widget/README.md +188 -0
- package/docs/widget/Radio.md +123 -0
- package/docs/widget/Rating.md +131 -0
- package/docs/widget/Row.md +131 -0
- package/docs/widget/START_HERE.md +146 -0
- package/docs/widget/Scaffold.md +152 -0
- package/docs/widget/Skeleton.md +130 -0
- package/docs/widget/Slider.md +146 -0
- package/docs/widget/SnackBar.md +102 -0
- package/docs/widget/Stack.md +128 -0
- package/docs/widget/Stepper.md +145 -0
- package/docs/widget/Switch.md +118 -0
- package/docs/widget/Tabs.md +124 -0
- package/docs/widget/Text.md +133 -0
- package/docs/widget/Tooltip.md +145 -0
- package/docs/widget/TreeView.md +176 -0
- package/docs/widget/Video.md +127 -0
- package/docs/widget/_template.md +61 -0
- package/package.json +3 -2
- package/src/animations/animate.js +180 -70
- package/src/animations/index.js +1 -0
- package/src/create-index.sh +1 -1
- package/src/index.d.ts +45 -22
- package/src/index.js +1 -0
- package/src/navigations/AdaptiveScaffold.js +11 -2
- package/src/navigations/BottomNavigation.js +10 -3
- package/src/navigations/Tabs.js +6 -2
- package/src/tools/useState.js +54 -63
- package/src/widget-factory/assignProps.js +23 -1
- package/src/widget-factory/processProps.js +10 -3
- package/src/widget-factory/reactiveValue.js +43 -18
- package/src/widget-factory/translateProps.js +777 -901
- package/src/widgets/AlertDialog.js +7 -5
- package/src/widgets/Checkbox.js +9 -7
- package/src/widgets/CircularBar.js +12 -1
- package/src/widgets/FloatingActionButton.js +4 -7
- package/src/widgets/Image.js +5 -7
- package/src/widgets/Input.js +92 -0
- package/src/widgets/ListView.js +73 -29
- package/src/widgets/Pagination.js +6 -3
- package/src/widgets/ProgressBar.js +16 -13
- package/src/widgets/Radio.js +6 -7
- package/src/widgets/Slider.js +23 -4
- package/src/widgets/Stack.js +36 -3
- package/src/widgets/Stepper.js +4 -3
- package/src/widgets/Switch.js +3 -4
- package/src/widgets/TreeView.js +0 -1
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides two tiers of animation helpers:
|
|
5
5
|
* - **Fire-and-forget** (`animate`, `fadeOut`, `fadeIn`, `pulse`): start an
|
|
6
|
-
* animation and move on —
|
|
6
|
+
* animation and move on — each returns a cancel function instead of awaiting.
|
|
7
7
|
* - **Async/awaitable** (`animateAsync`, `fadeOutAsync`, `fadeInAsync`,
|
|
8
8
|
* `pulseAsync`): return a Promise that resolves when the animation finishes,
|
|
9
9
|
* allowing sequential composition with `await`.
|
|
10
10
|
*
|
|
11
|
+
* Every loop is registered per widget and property, so starting a second
|
|
12
|
+
* animation on the same property replaces the first (two loops writing one style
|
|
13
|
+
* fight each other), and {@link stopAnimation} ends whatever is still running on
|
|
14
|
+
* a widget — the usual cleanup an unmount needs when the caller kept no handle.
|
|
15
|
+
*
|
|
11
16
|
* All functions drive the browser's `requestAnimationFrame` loop directly and
|
|
12
17
|
* do not rely on CSS transitions or the Web Animations API.
|
|
13
18
|
*
|
|
@@ -162,6 +167,151 @@ const writeAnimatedValue = (widget, property, value) => {
|
|
|
162
167
|
widget[property] = value;
|
|
163
168
|
};
|
|
164
169
|
|
|
170
|
+
// ========== ACTIVE LOOP REGISTRY ==========
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Live loops by widget and property.
|
|
174
|
+
*
|
|
175
|
+
* Two loops writing the same style property fight each other: the older one keeps
|
|
176
|
+
* overwriting the newer value on every frame and neither can be stopped. The
|
|
177
|
+
* registry lets a fresh animation replace whatever already animates that
|
|
178
|
+
* property, and lets {@link stopAnimation} end loops whose caller never kept the
|
|
179
|
+
* handle — the usual case for a widget that unmounts mid-fade.
|
|
180
|
+
*
|
|
181
|
+
* @type {WeakMap<object, Map<string, { raf: number, running: boolean, cancel: () => boolean }>>}
|
|
182
|
+
*/
|
|
183
|
+
const activeLoops = new WeakMap();
|
|
184
|
+
|
|
185
|
+
const isTrackable = (widget) =>
|
|
186
|
+
widget !== null &&
|
|
187
|
+
(typeof widget === "object" || typeof widget === "function");
|
|
188
|
+
|
|
189
|
+
const registerLoop = (widget, property, state) => {
|
|
190
|
+
if (!isTrackable(widget)) return;
|
|
191
|
+
let byProperty = activeLoops.get(widget);
|
|
192
|
+
if (!byProperty) {
|
|
193
|
+
byProperty = new Map();
|
|
194
|
+
activeLoops.set(widget, byProperty);
|
|
195
|
+
}
|
|
196
|
+
byProperty.set(property, state);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const unregisterLoop = (widget, property, state) => {
|
|
200
|
+
if (!isTrackable(widget)) return;
|
|
201
|
+
const byProperty = activeLoops.get(widget);
|
|
202
|
+
if (byProperty && byProperty.get(property) === state) byProperty.delete(property);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Stops the animation currently running on a widget.
|
|
207
|
+
*
|
|
208
|
+
* @param {HTMLElement|object} widget - The animated widget or DOM element.
|
|
209
|
+
* @param {string} [property] - Stop only this property; every animated property when omitted.
|
|
210
|
+
* @returns {boolean} True when at least one loop was stopped.
|
|
211
|
+
*/
|
|
212
|
+
export const stopAnimation = (widget, property) => {
|
|
213
|
+
if (!isTrackable(widget)) return false;
|
|
214
|
+
const byProperty = activeLoops.get(widget);
|
|
215
|
+
if (!byProperty) return false;
|
|
216
|
+
|
|
217
|
+
if (property !== undefined) {
|
|
218
|
+
const state = byProperty.get(property);
|
|
219
|
+
if (!state) return false;
|
|
220
|
+
return state.cancel();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const loops = Array.from(byProperty.values());
|
|
224
|
+
loops.forEach((state) => state.cancel());
|
|
225
|
+
return loops.length > 0;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Runs one property animation and returns its cancel function.
|
|
230
|
+
*
|
|
231
|
+
* Shared engine behind `animate`, `animateAsync` and `pulse`, so all three get
|
|
232
|
+
* the same guarantees: the loop is bounded by a sanitised duration, it replaces
|
|
233
|
+
* any animation already driving that property, and it stops the moment its
|
|
234
|
+
* handle is called.
|
|
235
|
+
*
|
|
236
|
+
* @param {HTMLElement|object} widget
|
|
237
|
+
* @param {string} property
|
|
238
|
+
* @param {number|string} from - Starting value; reads the widget when `undefined`.
|
|
239
|
+
* @param {number|string} to
|
|
240
|
+
* @param {number} duration
|
|
241
|
+
* @param {string} easing
|
|
242
|
+
* @param {(progress: number) => number|string} [valueAt] - Custom value curve,
|
|
243
|
+
* receiving eased progress in `[0, 1]`. Used by `pulse` to keep the whole
|
|
244
|
+
* up-and-down gesture inside a single cancelable loop.
|
|
245
|
+
* @param {(progress: number) => number|string} [valueAt] - Custom value curve,
|
|
246
|
+
* receiving eased progress in `[0, 1]`. Used by `pulse` to keep the whole
|
|
247
|
+
* up-and-down gesture inside a single cancelable loop.
|
|
248
|
+
* @param {(widget: HTMLElement|object) => void} [onDone] - Called when the loop
|
|
249
|
+
* ends — also when it is cancelled or replaced, so awaiting code never hangs.
|
|
250
|
+
* @returns {() => boolean} Cancel function; true when it stopped a live loop.
|
|
251
|
+
*/
|
|
252
|
+
const runAnimation = (
|
|
253
|
+
widget,
|
|
254
|
+
property,
|
|
255
|
+
from,
|
|
256
|
+
to,
|
|
257
|
+
duration,
|
|
258
|
+
easing,
|
|
259
|
+
valueAt,
|
|
260
|
+
onDone,
|
|
261
|
+
) => {
|
|
262
|
+
// A negative duration makes elapsed/duration increasingly negative, so progress
|
|
263
|
+
// never reaches 1 and the loop re-arms forever (and `animateAsync` never
|
|
264
|
+
// resolves). Clamping the progress is not enough — it just sits at 0 and
|
|
265
|
+
// `0 < 1` stays true — so sanitise the duration itself. `0` collapses to one frame.
|
|
266
|
+
const safeDuration = Math.max(0, Number(duration) || 0);
|
|
267
|
+
const startValue = from !== undefined ? from : readAnimatedValue(widget, property);
|
|
268
|
+
|
|
269
|
+
// Replace the loop already animating this property instead of racing it.
|
|
270
|
+
stopAnimation(widget, property);
|
|
271
|
+
|
|
272
|
+
const startTime = performance.now();
|
|
273
|
+
const state = { raf: 0, running: true, cancel: null };
|
|
274
|
+
|
|
275
|
+
const finish = () => {
|
|
276
|
+
if (!state.running) return;
|
|
277
|
+
state.running = false;
|
|
278
|
+
unregisterLoop(widget, property, state);
|
|
279
|
+
if (onDone) onDone(widget);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
state.cancel = () => {
|
|
283
|
+
if (!state.running) return false;
|
|
284
|
+
cancelAnimationFrame(state.raf);
|
|
285
|
+
finish();
|
|
286
|
+
return true;
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
registerLoop(widget, property, state);
|
|
290
|
+
|
|
291
|
+
const step = (currentTime) => {
|
|
292
|
+
if (!state.running) return;
|
|
293
|
+
const progress = Math.max(
|
|
294
|
+
0,
|
|
295
|
+
Math.min(1, (currentTime - startTime) / safeDuration),
|
|
296
|
+
);
|
|
297
|
+
const easedProgress = getEasing(easing, progress);
|
|
298
|
+
const currentValue = valueAt
|
|
299
|
+
? valueAt(easedProgress)
|
|
300
|
+
: interpolate(startValue, to, easedProgress);
|
|
301
|
+
|
|
302
|
+
writeAnimatedValue(widget, property, currentValue);
|
|
303
|
+
|
|
304
|
+
if (progress < 1) {
|
|
305
|
+
state.raf = requestAnimationFrame(step);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
finish();
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
state.raf = requestAnimationFrame(step);
|
|
312
|
+
return state.cancel;
|
|
313
|
+
};
|
|
314
|
+
|
|
165
315
|
// ========== FIRE AND FORGET (No Promise) ==========
|
|
166
316
|
|
|
167
317
|
/**
|
|
@@ -176,7 +326,9 @@ const writeAnimatedValue = (widget, property, value) => {
|
|
|
176
326
|
* @param {number|string} to - Ending value.
|
|
177
327
|
* @param {number} [duration=300] - Animation duration in milliseconds.
|
|
178
328
|
* @param {string} [easing="linear"] - Easing curve name (see {@link getEasing}).
|
|
179
|
-
* @returns {
|
|
329
|
+
* @returns {() => boolean} Cancel function — true if it stopped a loop still running.
|
|
330
|
+
* The animation also stops on its own when a new animation takes the same property,
|
|
331
|
+
* or via {@link stopAnimation}.
|
|
180
332
|
*/
|
|
181
333
|
export const animate = (
|
|
182
334
|
widget,
|
|
@@ -185,34 +337,7 @@ export const animate = (
|
|
|
185
337
|
to,
|
|
186
338
|
duration = 300,
|
|
187
339
|
easing = "linear",
|
|
188
|
-
) =>
|
|
189
|
-
// A negative duration makes elapsed/duration increasingly negative, so the
|
|
190
|
-
// loop re-armed forever and the property was driven backwards. Clamping the
|
|
191
|
-
// progress is not enough (it just sits at 0 and `0 < 1` stays true), so
|
|
192
|
-
// sanitise the duration itself. `0` collapses to a single frame.
|
|
193
|
-
duration = Math.max(0, Number(duration) || 0);
|
|
194
|
-
const startTime = performance.now();
|
|
195
|
-
const startValue = from !== undefined ? from : readAnimatedValue(widget, property);
|
|
196
|
-
const endValue = to;
|
|
197
|
-
|
|
198
|
-
const step = (currentTime) => {
|
|
199
|
-
const elapsed = currentTime - startTime;
|
|
200
|
-
// Clamp both ends. A negative `duration` makes elapsed/duration increasingly
|
|
201
|
-
// negative, so `progress` never reached 1 and the loop re-armed forever (and
|
|
202
|
-
// `animateAsync` never resolved). `duration: 0` yields Infinity, clamped to 1.
|
|
203
|
-
const progress = Math.max(0, Math.min(1, elapsed / duration));
|
|
204
|
-
const easedProgress = getEasing(easing, progress);
|
|
205
|
-
const currentValue = interpolate(startValue, endValue, easedProgress);
|
|
206
|
-
|
|
207
|
-
writeAnimatedValue(widget, property, currentValue);
|
|
208
|
-
|
|
209
|
-
if (progress < 1) {
|
|
210
|
-
requestAnimationFrame(step);
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
requestAnimationFrame(step);
|
|
215
|
-
};
|
|
340
|
+
) => runAnimation(widget, property, from, to, duration, easing, null);
|
|
216
341
|
|
|
217
342
|
// ========== ASYNC ANIMATION (Returns Promise) ==========
|
|
218
343
|
|
|
@@ -228,7 +353,8 @@ export const animate = (
|
|
|
228
353
|
* @param {number|string} to - Ending value.
|
|
229
354
|
* @param {number} [duration=300] - Animation duration in milliseconds.
|
|
230
355
|
* @param {string} [easing="linear"] - Easing curve name (see {@link getEasing}).
|
|
231
|
-
* @returns {Promise<HTMLElement|object>} Resolves with `widget` when the animation
|
|
356
|
+
* @returns {Promise<HTMLElement|object>} Resolves with `widget` when the animation
|
|
357
|
+
* finishes — or as soon as it is cancelled or replaced, so `await` never hangs.
|
|
232
358
|
*/
|
|
233
359
|
export const animateAsync = (
|
|
234
360
|
widget,
|
|
@@ -237,35 +363,12 @@ export const animateAsync = (
|
|
|
237
363
|
to,
|
|
238
364
|
duration = 300,
|
|
239
365
|
easing = "linear",
|
|
240
|
-
) =>
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const startTime = performance.now();
|
|
246
|
-
const startValue = from !== undefined ? from : readAnimatedValue(widget, property);
|
|
247
|
-
const endValue = to;
|
|
248
|
-
|
|
249
|
-
const step = (currentTime) => {
|
|
250
|
-
const elapsed = currentTime - startTime;
|
|
251
|
-
// Same clamp as `animate`: a negative `duration` would otherwise never
|
|
252
|
-
// reach progress 1 and this promise would never resolve.
|
|
253
|
-
const progress = Math.max(0, Math.min(1, elapsed / duration));
|
|
254
|
-
const easedProgress = getEasing(easing, progress);
|
|
255
|
-
const currentValue = interpolate(startValue, endValue, easedProgress);
|
|
256
|
-
|
|
257
|
-
writeAnimatedValue(widget, property, currentValue);
|
|
258
|
-
|
|
259
|
-
if (progress < 1) {
|
|
260
|
-
requestAnimationFrame(step);
|
|
261
|
-
} else {
|
|
262
|
-
resolve(widget);
|
|
263
|
-
}
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
requestAnimationFrame(step);
|
|
366
|
+
) =>
|
|
367
|
+
new Promise((resolve) => {
|
|
368
|
+
// `resolve` runs on completion AND when the loop is cancelled or replaced, so
|
|
369
|
+
// an `await` chain cannot hang on an animation that never got to finish.
|
|
370
|
+
runAnimation(widget, property, from, to, duration, easing, null, resolve);
|
|
267
371
|
});
|
|
268
|
-
};
|
|
269
372
|
|
|
270
373
|
// ========== HELPER FUNCTIONS (Fire and Forget) ==========
|
|
271
374
|
|
|
@@ -275,10 +378,10 @@ export const animateAsync = (
|
|
|
275
378
|
*
|
|
276
379
|
* @param {HTMLElement|object} widget - The target widget.
|
|
277
380
|
* @param {number} [duration=300] - Fade duration in milliseconds.
|
|
278
|
-
* @returns {
|
|
381
|
+
* @returns {() => boolean} Cancel function (see {@link animate}).
|
|
279
382
|
*/
|
|
280
383
|
export const fadeOut = (widget, duration = 300) => {
|
|
281
|
-
animate(widget, "opacity", 1, 0, duration);
|
|
384
|
+
return animate(widget, "opacity", 1, 0, duration);
|
|
282
385
|
};
|
|
283
386
|
|
|
284
387
|
/**
|
|
@@ -287,10 +390,10 @@ export const fadeOut = (widget, duration = 300) => {
|
|
|
287
390
|
*
|
|
288
391
|
* @param {HTMLElement|object} widget - The target widget.
|
|
289
392
|
* @param {number} [duration=300] - Fade duration in milliseconds.
|
|
290
|
-
* @returns {
|
|
393
|
+
* @returns {() => boolean} Cancel function (see {@link animate}).
|
|
291
394
|
*/
|
|
292
395
|
export const fadeIn = (widget, duration = 300) => {
|
|
293
|
-
animate(widget, "opacity", 0, 1, duration);
|
|
396
|
+
return animate(widget, "opacity", 0, 1, duration);
|
|
294
397
|
};
|
|
295
398
|
|
|
296
399
|
/**
|
|
@@ -301,14 +404,21 @@ export const fadeIn = (widget, duration = 300) => {
|
|
|
301
404
|
* @param {HTMLElement|object} widget - The target widget.
|
|
302
405
|
* @param {number} [duration=300] - Total pulse duration in milliseconds
|
|
303
406
|
* (split evenly between scale-up and scale-down).
|
|
304
|
-
* @returns {
|
|
407
|
+
* @returns {() => boolean} Cancel function (see {@link animate}).
|
|
305
408
|
*/
|
|
306
|
-
export const pulse = (widget, duration = 300) =>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
409
|
+
export const pulse = (widget, duration = 300) =>
|
|
410
|
+
runAnimation(
|
|
411
|
+
widget,
|
|
412
|
+
"scale",
|
|
413
|
+
1,
|
|
414
|
+
1,
|
|
415
|
+
duration,
|
|
416
|
+
"linear",
|
|
417
|
+
// One loop with a triangular curve instead of an animation plus a
|
|
418
|
+
// `setTimeout`: the timer used to start phase two on a widget that had
|
|
419
|
+
// already been removed from the DOM, and nothing could cancel it.
|
|
420
|
+
(progress) => interpolate(1, 1.1, progress < 0.5 ? progress * 2 : 2 - progress * 2),
|
|
421
|
+
);
|
|
312
422
|
|
|
313
423
|
// ========== ASYNC HELPER FUNCTIONS (Returns Promise) ==========
|
|
314
424
|
|
package/src/animations/index.js
CHANGED
package/src/create-index.sh
CHANGED
|
@@ -32,7 +32,7 @@ export {
|
|
|
32
32
|
useState, useWatchState,
|
|
33
33
|
tokenize, generateHighlightedHtml, highlightColors,
|
|
34
34
|
parseMarkdown, parseInlineMarkdown, escapeHtml, wrapListItems,
|
|
35
|
-
animate, fadeOut, fadeIn, pulse,
|
|
35
|
+
animate, stopAnimation, fadeOut, fadeIn, pulse,
|
|
36
36
|
applyStripes, removeStripes, applyShimmer, applyGlow,
|
|
37
37
|
applyIndeterminate, applyPulse, injectKeyframes,
|
|
38
38
|
Gradient, Shadow, rgba, stackPosition,
|
package/src/index.d.ts
CHANGED
|
@@ -36,10 +36,15 @@ declare module 'flet-box' {
|
|
|
36
36
|
export interface CommonProps {
|
|
37
37
|
width?: Size;
|
|
38
38
|
height?: Size;
|
|
39
|
-
size
|
|
39
|
+
// `Size`, not `number`: for a Text this is a font size and for a Button it is
|
|
40
|
+
// the `small | medium | large` preset — the widget decides which it reads.
|
|
41
|
+
size?: Size;
|
|
40
42
|
padding?: Padding;
|
|
41
43
|
margin?: Margin;
|
|
42
44
|
bgColor?: Color;
|
|
45
|
+
// Alias kept because the engine routes it and every generated template uses
|
|
46
|
+
// it: `bgColor` is the Flet-style short name for the same style.
|
|
47
|
+
backgroundColor?: Color;
|
|
43
48
|
color?: Color;
|
|
44
49
|
borderRadius?: number | string;
|
|
45
50
|
elevation?: number;
|
|
@@ -203,10 +208,10 @@ declare module 'flet-box' {
|
|
|
203
208
|
gap?: number | string;
|
|
204
209
|
justifyContent?: 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly';
|
|
205
210
|
alignItems?: 'flex-start' | 'center' | 'flex-end' | 'stretch';
|
|
206
|
-
wrap?: boolean;
|
|
211
|
+
wrap?: boolean | 'wrap' | 'nowrap' | 'wrap-reverse';
|
|
207
212
|
child?: Widget;
|
|
208
213
|
children?: Widget[];
|
|
209
|
-
expand?: boolean;
|
|
214
|
+
expand?: boolean | number;
|
|
210
215
|
flex?: number;
|
|
211
216
|
minHeight?: Size;
|
|
212
217
|
maxHeight?: Size;
|
|
@@ -220,7 +225,7 @@ declare module 'flet-box' {
|
|
|
220
225
|
gap?: number | string;
|
|
221
226
|
justifyContent?: ContainerProps['justifyContent'];
|
|
222
227
|
alignItems?: ContainerProps['alignItems'];
|
|
223
|
-
wrap?: boolean;
|
|
228
|
+
wrap?: boolean | 'wrap' | 'nowrap' | 'wrap-reverse';
|
|
224
229
|
children?: Widget[];
|
|
225
230
|
onPress?: (widget: Widget) => void;
|
|
226
231
|
}
|
|
@@ -259,7 +264,7 @@ declare module 'flet-box' {
|
|
|
259
264
|
ListEmptyComponent?: (() => Widget) | Widget;
|
|
260
265
|
showsScrollIndicator?: boolean;
|
|
261
266
|
bufferSize?: number;
|
|
262
|
-
expand?: boolean;
|
|
267
|
+
expand?: boolean | number;
|
|
263
268
|
}
|
|
264
269
|
export function ListView(props: ListViewProps): Widget & {
|
|
265
270
|
data: any[];
|
|
@@ -375,6 +380,12 @@ declare module 'flet-box' {
|
|
|
375
380
|
title?: string | Widget;
|
|
376
381
|
subtitle?: string | Widget;
|
|
377
382
|
description?: string | Widget;
|
|
383
|
+
/** Text props merged into the title, e.g. `{ size: 16, weight: "700" }`. */
|
|
384
|
+
titleProps?: Partial<TextProps>;
|
|
385
|
+
/** Text props merged into the subtitle. */
|
|
386
|
+
subtitleProps?: Partial<TextProps>;
|
|
387
|
+
/** Text props merged into the description line. */
|
|
388
|
+
descriptionProps?: Partial<TextProps>;
|
|
378
389
|
rightItem?: Widget;
|
|
379
390
|
onPress?: (widget: Widget) => void;
|
|
380
391
|
selected?: boolean;
|
|
@@ -522,7 +533,7 @@ declare module 'flet-box' {
|
|
|
522
533
|
updateValue(newValue: string | number): void;
|
|
523
534
|
};
|
|
524
535
|
|
|
525
|
-
export interface SliderProps extends CommonProps {
|
|
536
|
+
export interface SliderProps extends Omit<CommonProps, 'onPress'> {
|
|
526
537
|
value?: number;
|
|
527
538
|
min?: number;
|
|
528
539
|
max?: number;
|
|
@@ -544,6 +555,9 @@ declare module 'flet-box' {
|
|
|
544
555
|
animatedStripes?: boolean;
|
|
545
556
|
stripeColor?: string;
|
|
546
557
|
glow?: boolean;
|
|
558
|
+
/** Canonical press/change callback, like every other FletBox widget. */
|
|
559
|
+
onPress?: (value: number) => void;
|
|
560
|
+
/** @deprecated Alias of `onPress`. */
|
|
547
561
|
onChanged?: (value: number) => void;
|
|
548
562
|
onChangeEnd?: (value: number) => void;
|
|
549
563
|
}
|
|
@@ -588,7 +602,7 @@ declare module 'flet-box' {
|
|
|
588
602
|
update(props: Partial<AccordionProps>): void;
|
|
589
603
|
};
|
|
590
604
|
|
|
591
|
-
export interface DividerProps extends CommonProps {
|
|
605
|
+
export interface DividerProps extends Omit<CommonProps, 'margin'> {
|
|
592
606
|
color?: Color;
|
|
593
607
|
thickness?: number;
|
|
594
608
|
margin?: number | { top?: number; right?: number; bottom?: number; left?: number };
|
|
@@ -857,6 +871,7 @@ declare module 'flet-box' {
|
|
|
857
871
|
navSideBarWidth?: number;
|
|
858
872
|
navSideBarPosition?: 'left' | 'right';
|
|
859
873
|
routes?: Record<string, any>;
|
|
874
|
+
basePath?: string;
|
|
860
875
|
backgroundColor?: Color;
|
|
861
876
|
closeDrawerOnNavigate?: boolean;
|
|
862
877
|
}
|
|
@@ -893,7 +908,7 @@ declare module 'flet-box' {
|
|
|
893
908
|
closeDrawer?(): void;
|
|
894
909
|
};
|
|
895
910
|
|
|
896
|
-
export interface AppBarProps extends CommonProps {
|
|
911
|
+
export interface AppBarProps extends Omit<CommonProps, 'shadow'> {
|
|
897
912
|
title?: string | Widget;
|
|
898
913
|
leading?: Widget;
|
|
899
914
|
actions?: Widget[];
|
|
@@ -915,7 +930,7 @@ declare module 'flet-box' {
|
|
|
915
930
|
margin?: Margin;
|
|
916
931
|
padding?: Padding;
|
|
917
932
|
borderRadius?: number;
|
|
918
|
-
shadow?: boolean;
|
|
933
|
+
shadow?: boolean | string;
|
|
919
934
|
}
|
|
920
935
|
export function AppBar(props: AppBarProps): Widget & {
|
|
921
936
|
setTitle(title: string): void;
|
|
@@ -971,7 +986,7 @@ declare module 'flet-box' {
|
|
|
971
986
|
export function toggleDrawer(): void;
|
|
972
987
|
export function destroyDrawer(): void;
|
|
973
988
|
|
|
974
|
-
export interface BottomNavigationProps extends CommonProps {
|
|
989
|
+
export interface BottomNavigationProps extends Omit<CommonProps, 'shadow'> {
|
|
975
990
|
items: Array<{ icon: string; label?: string; route?: string; onPress?: () => void }>;
|
|
976
991
|
currentIndex?: number;
|
|
977
992
|
onTabChange?: (index: number) => void;
|
|
@@ -984,7 +999,7 @@ declare module 'flet-box' {
|
|
|
984
999
|
margin?: Margin;
|
|
985
1000
|
borderRadius?: number;
|
|
986
1001
|
padding?: Padding;
|
|
987
|
-
shadow?: boolean;
|
|
1002
|
+
shadow?: boolean | string;
|
|
988
1003
|
elevation?: number;
|
|
989
1004
|
useRouter?: boolean;
|
|
990
1005
|
}
|
|
@@ -1141,7 +1156,8 @@ declare module 'flet-box' {
|
|
|
1141
1156
|
to: any,
|
|
1142
1157
|
duration?: number,
|
|
1143
1158
|
easing?: string
|
|
1144
|
-
):
|
|
1159
|
+
): () => boolean;
|
|
1160
|
+
export function stopAnimation(widget: Widget, property?: string): boolean;
|
|
1145
1161
|
export function animateAsync(
|
|
1146
1162
|
widget: Widget,
|
|
1147
1163
|
property: string,
|
|
@@ -1150,9 +1166,9 @@ declare module 'flet-box' {
|
|
|
1150
1166
|
duration?: number,
|
|
1151
1167
|
easing?: string
|
|
1152
1168
|
): Promise<Widget>;
|
|
1153
|
-
export function fadeOut(widget: Widget, duration?: number):
|
|
1154
|
-
export function fadeIn(widget: Widget, duration?: number):
|
|
1155
|
-
export function pulse(widget: Widget, duration?: number):
|
|
1169
|
+
export function fadeOut(widget: Widget, duration?: number): () => boolean;
|
|
1170
|
+
export function fadeIn(widget: Widget, duration?: number): () => boolean;
|
|
1171
|
+
export function pulse(widget: Widget, duration?: number): () => boolean;
|
|
1156
1172
|
export function fadeOutAsync(widget: Widget, duration?: number): Promise<Widget>;
|
|
1157
1173
|
export function fadeInAsync(widget: Widget, duration?: number): Promise<Widget>;
|
|
1158
1174
|
export function pulseAsync(widget: Widget, duration?: number): Promise<Widget>;
|
|
@@ -1192,7 +1208,7 @@ declare module 'flet-box' {
|
|
|
1192
1208
|
updateColumns(columns: DataTableColumn[]): void;
|
|
1193
1209
|
};
|
|
1194
1210
|
|
|
1195
|
-
export interface ChartProps extends CommonProps {
|
|
1211
|
+
export interface ChartProps extends Omit<CommonProps, 'padding'> {
|
|
1196
1212
|
type?: 'bar' | 'line' | 'area' | 'candle';
|
|
1197
1213
|
data: number[] | Array<{ open: number; high: number; low: number; close: number }>;
|
|
1198
1214
|
labels?: string[];
|
|
@@ -1494,7 +1510,7 @@ declare module 'flet-box' {
|
|
|
1494
1510
|
}
|
|
1495
1511
|
export function InstallButton(props: InstallButtonProps): Widget;
|
|
1496
1512
|
|
|
1497
|
-
export interface VideoProps extends CommonProps {
|
|
1513
|
+
export interface VideoProps extends Omit<CommonProps, 'ref'> {
|
|
1498
1514
|
src: string;
|
|
1499
1515
|
width?: number | string;
|
|
1500
1516
|
height?: number | string;
|
|
@@ -1516,7 +1532,7 @@ declare module 'flet-box' {
|
|
|
1516
1532
|
unmuteVideo(): void;
|
|
1517
1533
|
};
|
|
1518
1534
|
|
|
1519
|
-
export interface AudioProps extends CommonProps {
|
|
1535
|
+
export interface AudioProps extends Omit<CommonProps, 'ref'> {
|
|
1520
1536
|
src: string;
|
|
1521
1537
|
autoplay?: boolean;
|
|
1522
1538
|
controls?: boolean;
|
|
@@ -1547,7 +1563,7 @@ declare module 'flet-box' {
|
|
|
1547
1563
|
isPlaying(): boolean;
|
|
1548
1564
|
};
|
|
1549
1565
|
|
|
1550
|
-
export interface CircularBarProps extends CommonProps {
|
|
1566
|
+
export interface CircularBarProps extends Omit<CommonProps, 'onClick' | 'ref'> {
|
|
1551
1567
|
value?: number;
|
|
1552
1568
|
max?: number;
|
|
1553
1569
|
size?: number;
|
|
@@ -1597,7 +1613,7 @@ declare module 'flet-box' {
|
|
|
1597
1613
|
color?: Color;
|
|
1598
1614
|
}
|
|
1599
1615
|
|
|
1600
|
-
export interface CircularChartProps extends CommonProps {
|
|
1616
|
+
export interface CircularChartProps extends Omit<CommonProps, 'onClick' | 'ref'> {
|
|
1601
1617
|
data?: CircularChartSlice[];
|
|
1602
1618
|
size?: number;
|
|
1603
1619
|
strokeWidth?: number;
|
|
@@ -1920,7 +1936,12 @@ declare module 'flet-box' {
|
|
|
1920
1936
|
export function padding(value: number | string | { all?: number; horizontal?: number; vertical?: number; top?: number; right?: number; bottom?: number; left?: number }): string;
|
|
1921
1937
|
export function gradient(type: 'linear' | 'circle' | 'conic', colors: string[], angle?: number): string;
|
|
1922
1938
|
export function shadow(x: number, y: number, blur: number, spread: number, color: string): string;
|
|
1923
|
-
|
|
1939
|
+
/**
|
|
1940
|
+
* Fluent color instance returned by `color()`. The chained methods mutate this
|
|
1941
|
+
* very instance and return it, which is why their type is `this` and not a
|
|
1942
|
+
* fixed interface name.
|
|
1943
|
+
*/
|
|
1944
|
+
export interface ColorInstance {
|
|
1924
1945
|
hex(): string;
|
|
1925
1946
|
rgb(): string;
|
|
1926
1947
|
rgba(): string;
|
|
@@ -1931,7 +1952,9 @@ declare module 'flet-box' {
|
|
|
1931
1952
|
isDark(): boolean;
|
|
1932
1953
|
isLight(): boolean;
|
|
1933
1954
|
contrast(): string;
|
|
1934
|
-
}
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
export const color: (value: string) => ColorInstance;
|
|
1935
1958
|
export function rgba(r: number, g: number, b: number, a?: number): string;
|
|
1936
1959
|
export function stackPosition(widget: Widget, props: { top?: any; right?: any; bottom?: any; left?: any }): Widget;
|
|
1937
1960
|
export function flex(grow: number | { grow?: number; shrink?: number; basis?: string }, shrink?: number, basis?: string): string;
|
package/src/index.js
CHANGED
|
@@ -81,7 +81,10 @@ export const AdaptiveScaffold = (props) => {
|
|
|
81
81
|
// button to drawerInstance.open().
|
|
82
82
|
drawerInstance = Drawer({
|
|
83
83
|
header: null,
|
|
84
|
-
body
|
|
84
|
+
// `body` is an array of widgets, and `leftNavBar` may itself be one, so
|
|
85
|
+
// the content is flattened here. A nested array would reach `children`
|
|
86
|
+
// as a single item and break the append.
|
|
87
|
+
body: Array.isArray(content) ? content : [content],
|
|
85
88
|
footer: null,
|
|
86
89
|
position: "left",
|
|
87
90
|
width: leftNavBarWidth,
|
|
@@ -125,6 +128,12 @@ export const AdaptiveScaffold = (props) => {
|
|
|
125
128
|
widthExpanded: rightNavBarWidth,
|
|
126
129
|
widthCollapsed: 50,
|
|
127
130
|
bgColor: colors.surface,
|
|
131
|
+
// FIX: CollapsibleSideBar aplica `borderRight` por defecto (default
|
|
132
|
+
// `1px solid ${colors.border}`), así que un sidebar derecho acababa
|
|
133
|
+
// con doble borde: `borderRight` (heredado del default) + `borderLeft`
|
|
134
|
+
// (el que pedimos aquí). Forzamos `borderRight: "none"` para que solo
|
|
135
|
+
// tenga el borde izquierdo (el que da al contenido central).
|
|
136
|
+
borderRight: "none",
|
|
128
137
|
borderLeft: `1px solid ${colors.border}`,
|
|
129
138
|
children: content,
|
|
130
139
|
});
|
|
@@ -146,4 +155,4 @@ export const AdaptiveScaffold = (props) => {
|
|
|
146
155
|
});
|
|
147
156
|
};
|
|
148
157
|
|
|
149
|
-
export default AdaptiveScaffold;
|
|
158
|
+
export default AdaptiveScaffold;
|
|
@@ -149,6 +149,7 @@ export const BottomNavigation = (props) => {
|
|
|
149
149
|
if (!useRouter) return;
|
|
150
150
|
|
|
151
151
|
const currentPath = getCurrentPath();
|
|
152
|
+
const previousIndex = activeIndex;
|
|
152
153
|
|
|
153
154
|
buttons.forEach((btnData, idx) => {
|
|
154
155
|
const isSelected = btnData.route === currentPath;
|
|
@@ -163,7 +164,10 @@ export const BottomNavigation = (props) => {
|
|
|
163
164
|
if (isSelected) activeIndex = idx;
|
|
164
165
|
});
|
|
165
166
|
|
|
166
|
-
|
|
167
|
+
// Fire only when the route actually moved the selection. A consumer that
|
|
168
|
+
// navigates from `onTabChange` (the normal case) would otherwise recurse:
|
|
169
|
+
// route change -> callback -> goTo -> route change, until the stack blows.
|
|
170
|
+
if (activeIndex !== previousIndex && onTabChange) onTabChange(activeIndex);
|
|
167
171
|
};
|
|
168
172
|
|
|
169
173
|
// ========== BUILD TAB BUTTONS ==========
|
|
@@ -214,8 +218,11 @@ export const BottomNavigation = (props) => {
|
|
|
214
218
|
|
|
215
219
|
let labelWidget = null;
|
|
216
220
|
if (showLabels && item.label) {
|
|
221
|
+
// FIX: `value` es una prop `special` que `applySpecial` solo maneja
|
|
222
|
+
// en <input>/<textarea>. En un <span> no hace nada → el label quedaba
|
|
223
|
+
// vacío. La prop correcta para contenido de texto es `text`.
|
|
217
224
|
labelWidget = Text({
|
|
218
|
-
|
|
225
|
+
text: item.label,
|
|
219
226
|
size: 11,
|
|
220
227
|
color: isActive ? selectedColor : unselectedColor,
|
|
221
228
|
fontWeight: isActive ? "500" : "400",
|
|
@@ -307,4 +314,4 @@ export const BottomNavigation = (props) => {
|
|
|
307
314
|
return container;
|
|
308
315
|
};
|
|
309
316
|
|
|
310
|
-
export default BottomNavigation;
|
|
317
|
+
export default BottomNavigation;
|
package/src/navigations/Tabs.js
CHANGED
|
@@ -67,7 +67,11 @@ export const Tabs = (props) => {
|
|
|
67
67
|
size = "medium",
|
|
68
68
|
color = colors.primary,
|
|
69
69
|
textColor = colors.text,
|
|
70
|
-
|
|
70
|
+
// FIX: `colors.white` no existe en themes.js → caía a `undefined`
|
|
71
|
+
// y el tab activo no se distinguía visualmente. Uso `colors.background`
|
|
72
|
+
// (que es "#ffffff" en el tema claro y "#0f172a" en el oscuro, que es
|
|
73
|
+
// lo correcto: contraste sobre el fondo del tab activo).
|
|
74
|
+
activeTextColor = colors.background,
|
|
71
75
|
bgColor = colors.gray100,
|
|
72
76
|
buttonColor = colors.secondary,
|
|
73
77
|
alignment = "left",
|
|
@@ -409,4 +413,4 @@ export const Tabs = (props) => {
|
|
|
409
413
|
return container;
|
|
410
414
|
};
|
|
411
415
|
|
|
412
|
-
export default Tabs;
|
|
416
|
+
export default Tabs;
|