flet-box 1.0.6 → 1.0.8
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 +90 -11
- package/bin/commands/auditFix.js +682 -0
- package/bin/commands/checkApi.js +20 -6
- package/bin/commands/checkUi.js +1369 -0
- package/bin/commands/create.js +86 -12
- package/bin/commands/createBundle.js +75 -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 +91 -25
- 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/pwaShell.js +137 -0
- package/bin/utils/templates.js +1653 -471
- package/docs/README.md +2 -0
- package/docs/cli/README.md +144 -1
- package/docs/guides/README.md +2 -0
- package/docs/guides/clean-ui.md +211 -0
- package/docs/guides/minification-and-protection.md +1 -1
- package/docs/guides/online-updates.md +105 -9
- package/docs/tools/README.md +1 -1
- package/docs/tools/animation.md +1 -1
- package/docs/tools/markdown.md +3 -3
- package/docs/tools/theme.md +41 -1
- package/docs/widget/Accordion.md +4 -0
- package/docs/widget/AdMob.md +5 -1
- package/docs/widget/AdSense.md +4 -0
- package/docs/widget/AnimatedBox.md +7 -3
- package/docs/widget/AnimatedText.md +4 -0
- package/docs/widget/Audio.md +5 -1
- package/docs/widget/Avatar.md +15 -3
- package/docs/widget/Badge.md +4 -0
- package/docs/widget/Button.md +4 -0
- package/docs/widget/COMMON_PROPS.md +52 -0
- package/docs/widget/Card.md +4 -0
- package/docs/widget/Carousel.md +4 -0
- package/docs/widget/Chart.md +4 -0
- package/docs/widget/Checkbox.md +4 -0
- package/docs/widget/Chip.md +4 -0
- package/docs/widget/CircularBar.md +4 -0
- package/docs/widget/CircularChart.md +4 -0
- package/docs/widget/CodeViewer.md +4 -0
- package/docs/widget/Column.md +4 -0
- package/docs/widget/Container.md +4 -0
- package/docs/widget/DataTable.md +4 -0
- package/docs/widget/Divider.md +4 -0
- package/docs/widget/DraggBox.md +6 -2
- package/docs/widget/Dropdown.md +6 -0
- package/docs/widget/DroppBox.md +5 -1
- package/docs/widget/FloatingActionButton.md +4 -0
- package/docs/widget/GridView.md +4 -0
- package/docs/widget/Icon.md +4 -0
- package/docs/widget/Image.md +14 -3
- package/docs/widget/Input.md +4 -0
- package/docs/widget/Inspector.md +2 -2
- package/docs/widget/InstallButton.md +4 -0
- package/docs/widget/ListTile.md +4 -0
- package/docs/widget/ListView.md +4 -0
- package/docs/widget/Maps.md +191 -0
- package/docs/widget/Markdown.md +4 -0
- package/docs/widget/MatrixRain.md +4 -0
- package/docs/widget/Pagination.md +4 -0
- package/docs/widget/ParallaxBox.md +4 -0
- package/docs/widget/ProgressBar.md +4 -0
- package/docs/widget/QRCode.md +4 -0
- package/docs/widget/README.md +12 -10
- package/docs/widget/Radio.md +5 -1
- package/docs/widget/Rating.md +4 -0
- package/docs/widget/Row.md +4 -0
- package/docs/widget/Skeleton.md +4 -0
- package/docs/widget/Slider.md +4 -0
- package/docs/widget/Stack.md +4 -0
- package/docs/widget/Stepper.md +4 -0
- package/docs/widget/Switch.md +4 -0
- package/docs/widget/Tabs.md +5 -5
- package/docs/widget/Text.md +4 -0
- package/docs/widget/Tooltip.md +14 -13
- package/docs/widget/TreeView.md +4 -0
- package/docs/widget/Video.md +6 -2
- package/package.json +2 -2
- package/src/animations/AnimatedBox.js +4 -1
- package/src/animations/MatrixRain.js +3 -3
- package/src/core/hmr-client.js +129 -34
- package/src/index.d.ts +195 -7
- package/src/index.js +2 -0
- package/src/navigations/AppBar.js +22 -16
- package/src/navigations/BottomNavigation.js +8 -13
- package/src/navigations/CollapsibleSideBar.js +30 -8
- package/src/navigations/Drawer.js +25 -15
- package/src/navigations/DrawerItem.js +3 -1
- package/src/navigations/Scaffold.js +26 -12
- package/src/navigations/Tabs.js +104 -59
- package/src/tools/color.js +54 -0
- package/src/tools/index.js +9 -1
- package/src/tools/scale.js +41 -0
- package/src/tools/shadow.js +20 -0
- package/src/utils/index.js +1 -0
- package/src/utils/readableInk.js +19 -0
- package/src/utils/syntaxHighlight.js +78 -10
- package/src/utils/themes.js +217 -54
- package/src/utils/units.js +33 -11
- package/src/widget-factory/effects.js +56 -5
- package/src/widget-factory/processProps.js +10 -1
- package/src/widget-factory/remTool.js +15 -29
- package/src/widget-factory/stackPosition.js +18 -3
- package/src/widget-factory/translateProps.js +60 -1
- package/src/widgets/Accordion.js +20 -23
- package/src/widgets/AdMob.js +7 -2
- package/src/widgets/Avatar.js +236 -133
- package/src/widgets/Badge.js +3 -2
- package/src/widgets/BottomSheet.js +14 -13
- package/src/widgets/Button.js +69 -30
- package/src/widgets/Card.js +6 -2
- package/src/widgets/Carousel.js +12 -10
- package/src/widgets/Chart.js +28 -5
- package/src/widgets/Checkbox.js +76 -18
- package/src/widgets/Chip.js +31 -10
- package/src/widgets/CircularBar.js +7 -7
- package/src/widgets/CircularChart.js +26 -8
- package/src/widgets/CodeViewer.js +93 -20
- package/src/widgets/Container.js +13 -0
- package/src/widgets/DataTable.js +17 -11
- package/src/widgets/DraggBox.js +2 -1
- package/src/widgets/Dropdown.js +59 -14
- package/src/widgets/DroppBox.js +4 -2
- package/src/widgets/FloatingActionButton.js +13 -7
- package/src/widgets/Icon.js +3 -1
- package/src/widgets/Image.js +102 -3
- package/src/widgets/Input.js +30 -23
- package/src/widgets/Inspector.js +54 -1
- package/src/widgets/InstallButton.js +6 -4
- package/src/widgets/ListTile.js +4 -3
- package/src/widgets/ListView.js +30 -12
- package/src/widgets/Maps.js +1495 -0
- package/src/widgets/Markdown.js +37 -26
- package/src/widgets/Modal.js +14 -11
- package/src/widgets/Pagination.js +16 -11
- package/src/widgets/ProgressBar.js +6 -4
- package/src/widgets/Radio.js +73 -15
- package/src/widgets/Rating.js +24 -6
- package/src/widgets/Skeleton.js +31 -31
- package/src/widgets/Slider.js +29 -18
- package/src/widgets/SnackBar.js +35 -39
- package/src/widgets/Stepper.js +13 -9
- package/src/widgets/Switch.js +59 -18
- package/src/widgets/Tooltip.js +24 -12
- package/src/widgets/TreeView.js +27 -15
- package/src/widgets/index.js +1 -0
package/src/index.d.ts
CHANGED
|
@@ -30,10 +30,48 @@ declare module 'flet-box' {
|
|
|
30
30
|
_cleanup(): void;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// =========================================================================
|
|
34
|
+
// Posicionamiento
|
|
35
|
+
// =========================================================================
|
|
36
|
+
/**
|
|
37
|
+
* Positional props accepted by every widget.
|
|
38
|
+
*
|
|
39
|
+
* `position: 'stack'` takes the widget out of normal flow and places it
|
|
40
|
+
* against its nearest positioned ancestor; the `center*` / `full*` shorthands
|
|
41
|
+
* only take effect in that mode. Numeric offsets are framework units (pixels
|
|
42
|
+
* on the 16px base, emitted as rem).
|
|
43
|
+
*
|
|
44
|
+
* A few widgets give `position` their own meaning — the toast/badge/tooltip
|
|
45
|
+
* anchor — and therefore omit this declaration, as does `Maps` for `center`.
|
|
46
|
+
*/
|
|
47
|
+
export interface StackPositionProps {
|
|
48
|
+
position?: 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky' | 'stack';
|
|
49
|
+
/** Alias of `position`. */
|
|
50
|
+
pos?: 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky' | 'stack';
|
|
51
|
+
top?: Size;
|
|
52
|
+
right?: Size;
|
|
53
|
+
bottom?: Size;
|
|
54
|
+
left?: Size;
|
|
55
|
+
inset?: Size;
|
|
56
|
+
/** Logical spelling of `left`. */
|
|
57
|
+
start?: Size;
|
|
58
|
+
/** Logical spelling of `right`. */
|
|
59
|
+
end?: Size;
|
|
60
|
+
/** Alias of `zIndex`. */
|
|
61
|
+
z?: number;
|
|
62
|
+
zIndex?: number;
|
|
63
|
+
centerX?: boolean;
|
|
64
|
+
centerY?: boolean;
|
|
65
|
+
center?: boolean;
|
|
66
|
+
fullWidth?: boolean;
|
|
67
|
+
fullHeight?: boolean;
|
|
68
|
+
full?: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
33
71
|
// =========================================================================
|
|
34
72
|
// Props comunes (heredadas by todos the widgets)
|
|
35
73
|
// =========================================================================
|
|
36
|
-
export interface CommonProps {
|
|
74
|
+
export interface CommonProps extends StackPositionProps {
|
|
37
75
|
width?: Size;
|
|
38
76
|
height?: Size;
|
|
39
77
|
// `Size`, not `number`: for a Text this is a font size and for a Button it is
|
|
@@ -49,6 +87,12 @@ declare module 'flet-box' {
|
|
|
49
87
|
borderRadius?: number | string;
|
|
50
88
|
elevation?: number;
|
|
51
89
|
shadow?: string;
|
|
90
|
+
// Glass and filters. A CSS value string, not an object: `backdropFilter` is
|
|
91
|
+
// what makes a translucent card frosted rather than merely see-through, and
|
|
92
|
+
// `maskImage` is what fades a list out at its end.
|
|
93
|
+
filter?: string;
|
|
94
|
+
backdropFilter?: string;
|
|
95
|
+
maskImage?: string;
|
|
52
96
|
opacity?: number;
|
|
53
97
|
visible?: boolean;
|
|
54
98
|
disabled?: boolean;
|
|
@@ -242,7 +286,7 @@ declare module 'flet-box' {
|
|
|
242
286
|
|
|
243
287
|
export interface StackProps extends CommonProps {
|
|
244
288
|
children?: Widget[];
|
|
245
|
-
position?: 'relative' | 'absolute';
|
|
289
|
+
position?: 'relative' | 'absolute' | 'stack';
|
|
246
290
|
alignment?: 'top-left' | 'top-center' | 'top-right' | 'center-left' | 'center' | 'center-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
247
291
|
}
|
|
248
292
|
export function Stack(props: StackProps): Widget;
|
|
@@ -341,6 +385,8 @@ declare module 'flet-box' {
|
|
|
341
385
|
height?: Size;
|
|
342
386
|
fit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
|
|
343
387
|
circular?: boolean;
|
|
388
|
+
downloadable?: boolean;
|
|
389
|
+
downloadFileName?: string;
|
|
344
390
|
onLoad?: (widget: Widget) => void;
|
|
345
391
|
onError?: (widget: Widget) => void;
|
|
346
392
|
onPress?: (widget: Widget) => void;
|
|
@@ -355,6 +401,8 @@ declare module 'flet-box' {
|
|
|
355
401
|
bgColor?: Color;
|
|
356
402
|
textColor?: Color;
|
|
357
403
|
shape?: 'circle' | 'rounded' | 'square';
|
|
404
|
+
online?: boolean;
|
|
405
|
+
badgeColor?: Color;
|
|
358
406
|
onPress?: (widget: Widget) => void;
|
|
359
407
|
}
|
|
360
408
|
export function Avatar(props: AvatarProps): Widget & {
|
|
@@ -485,7 +533,7 @@ declare module 'flet-box' {
|
|
|
485
533
|
getElement(): Widget;
|
|
486
534
|
};
|
|
487
535
|
|
|
488
|
-
export interface AdMobProps extends CommonProps {
|
|
536
|
+
export interface AdMobProps extends Omit<CommonProps, 'position'> {
|
|
489
537
|
adId?: string;
|
|
490
538
|
isTesting?: boolean;
|
|
491
539
|
position?: 'top' | 'bottom';
|
|
@@ -516,7 +564,7 @@ declare module 'flet-box' {
|
|
|
516
564
|
getPlugin(): object | null;
|
|
517
565
|
};
|
|
518
566
|
|
|
519
|
-
export interface BadgeProps extends CommonProps {
|
|
567
|
+
export interface BadgeProps extends Omit<CommonProps, 'position'> {
|
|
520
568
|
value: string | number;
|
|
521
569
|
child: Widget;
|
|
522
570
|
bgColor?: Color;
|
|
@@ -1278,9 +1326,14 @@ declare module 'flet-box' {
|
|
|
1278
1326
|
};
|
|
1279
1327
|
|
|
1280
1328
|
export interface InspectorProps {
|
|
1329
|
+
/** The widget whose call is reconstructed and painted. */
|
|
1281
1330
|
widget: Widget;
|
|
1331
|
+
/** Starting indentation depth of the printout. */
|
|
1282
1332
|
indent?: number;
|
|
1283
1333
|
}
|
|
1334
|
+
/** Paints the reconstructed call of a widget tree. */
|
|
1335
|
+
export function Inspector(props: InspectorProps): Widget;
|
|
1336
|
+
/** Rebuilds the call that made a widget, as a string. */
|
|
1284
1337
|
export function Inspector(widget: Widget, indent?: number): string;
|
|
1285
1338
|
export function printWidgetCode(widget: Widget): void;
|
|
1286
1339
|
export function inspectWidget(widget: Widget): Widget;
|
|
@@ -1358,11 +1411,13 @@ declare module 'flet-box' {
|
|
|
1358
1411
|
getCurrentIndex(): number;
|
|
1359
1412
|
};
|
|
1360
1413
|
|
|
1361
|
-
export interface TooltipProps extends CommonProps {
|
|
1414
|
+
export interface TooltipProps extends Omit<CommonProps, 'position'> {
|
|
1362
1415
|
text: string;
|
|
1363
1416
|
child: Widget;
|
|
1364
1417
|
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
1365
1418
|
delay?: number;
|
|
1419
|
+
/** @deprecated Alias of `delay`. */
|
|
1420
|
+
tooltipDelay?: number;
|
|
1366
1421
|
bgColor?: Color;
|
|
1367
1422
|
textColor?: Color;
|
|
1368
1423
|
fontSize?: number;
|
|
@@ -1700,6 +1755,132 @@ declare module 'flet-box' {
|
|
|
1700
1755
|
getSource(): string;
|
|
1701
1756
|
};
|
|
1702
1757
|
|
|
1758
|
+
// =========================================================================
|
|
1759
|
+
// Maps
|
|
1760
|
+
// =========================================================================
|
|
1761
|
+
|
|
1762
|
+
/** A point on the map: `[lat, lng]`, `{lat, lng}` or `{latitude, longitude}`. */
|
|
1763
|
+
export type LatLng = [number, number] | { lat: number; lng: number } | { latitude: number; longitude: number };
|
|
1764
|
+
|
|
1765
|
+
/** `[[south, west], [north, east]]`, a named box, or the points to enclose. */
|
|
1766
|
+
export type MapBounds = [[number, number], [number, number]] | { south: number; west: number; north: number; east: number } | LatLng[];
|
|
1767
|
+
|
|
1768
|
+
/** A pin. A bare `LatLng` is also accepted wherever a marker is expected. */
|
|
1769
|
+
export interface MapMarker {
|
|
1770
|
+
position: LatLng;
|
|
1771
|
+
label?: string;
|
|
1772
|
+
color?: Color;
|
|
1773
|
+
/** Keeps the pooled pin node across updates; auto-generated when omitted. */
|
|
1774
|
+
id?: string | number;
|
|
1775
|
+
/** Degrees clockwise from north, the bearing a GPS fix reports. Turns the pin around its own tip. */
|
|
1776
|
+
rotation?: number;
|
|
1777
|
+
/** `false` lets a tap fall through to the map: a tracked vehicle must not block picking a point. */
|
|
1778
|
+
clickable?: boolean;
|
|
1779
|
+
data?: any;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
/** Payload of `onMapClick`: the geographic point under the cursor. */
|
|
1783
|
+
export interface MapClick {
|
|
1784
|
+
lat: number;
|
|
1785
|
+
lng: number;
|
|
1786
|
+
zoom: number;
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
/** Payload of `onMoveEnd`: the view once it stops changing. */
|
|
1790
|
+
export interface MapState {
|
|
1791
|
+
center: { lat: number; lng: number };
|
|
1792
|
+
zoom: number;
|
|
1793
|
+
bounds: { south: number; west: number; north: number; east: number };
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
/**
|
|
1797
|
+
* A stroked path — a route, a track, a boundary. Needs at least two usable
|
|
1798
|
+
* points. A bare `LatLng[]` is also accepted wherever a polyline is expected.
|
|
1799
|
+
*/
|
|
1800
|
+
export interface MapPolyline {
|
|
1801
|
+
points: LatLng[];
|
|
1802
|
+
/** Stroke colour. Defaults to `polylineColor`. */
|
|
1803
|
+
color?: Color;
|
|
1804
|
+
/** Stroke width in CSS pixels. Defaults to `4`. */
|
|
1805
|
+
width?: number;
|
|
1806
|
+
opacity?: number;
|
|
1807
|
+
dashed?: boolean;
|
|
1808
|
+
/** Identifies the line to `removePolyline()`; auto-generated when omitted. */
|
|
1809
|
+
id?: string | number;
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
/** Payload of `onUserUpdate`: one fix from the watcher, in degrees and metres. */
|
|
1813
|
+
export interface MapFix {
|
|
1814
|
+
lat: number;
|
|
1815
|
+
lng: number;
|
|
1816
|
+
/** Radius of 68% confidence in metres, or null when the browser hides it. */
|
|
1817
|
+
accuracy: number | null;
|
|
1818
|
+
/** Degrees clockwise from true north, or null when the device reports none. */
|
|
1819
|
+
heading: number | null;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
export interface MapsProps extends Omit<CommonProps, 'center'> {
|
|
1823
|
+
/** Initial view centre. Defaults to `[20, 0]`. */
|
|
1824
|
+
center?: LatLng;
|
|
1825
|
+
/** Integer zoom level, 0 = the whole world. Defaults to `2`. */
|
|
1826
|
+
zoom?: number;
|
|
1827
|
+
minZoom?: number;
|
|
1828
|
+
maxZoom?: number;
|
|
1829
|
+
/** Positions and/or `{position, label, color, id, data}` records. */
|
|
1830
|
+
markers?: Array<MapMarker | LatLng>;
|
|
1831
|
+
/** Colour of the pins that do not set their own. Defaults to `colors.primary`. */
|
|
1832
|
+
markerColor?: Color;
|
|
1833
|
+
/** Position lists and/or `{points, color, width, opacity, dashed, id}` records. */
|
|
1834
|
+
polylines?: Array<MapPolyline | LatLng[]>;
|
|
1835
|
+
/** Stroke of the lines that do not set their own. Defaults to `colors.primary`. */
|
|
1836
|
+
polylineColor?: Color;
|
|
1837
|
+
/** `{z}/{x}/{y}` tile template. Defaults to OpenStreetMap. */
|
|
1838
|
+
tileUrl?: string;
|
|
1839
|
+
/** Credit line; most providers require one. */
|
|
1840
|
+
attribution?: string;
|
|
1841
|
+
showAttribution?: boolean;
|
|
1842
|
+
showZoomControl?: boolean;
|
|
1843
|
+
/** When false the view only moves through the imperative API. */
|
|
1844
|
+
interactive?: boolean;
|
|
1845
|
+
scrollZoom?: boolean;
|
|
1846
|
+
doubleClickZoom?: boolean;
|
|
1847
|
+
/** Draws the browser position; asks for permission on the first map paint. */
|
|
1848
|
+
showUserLocation?: boolean;
|
|
1849
|
+
/**
|
|
1850
|
+
* Keeps the view centred on the browser position. Implies the dot and asks
|
|
1851
|
+
* the browser for fresh high-accuracy fixes instead of a cached one.
|
|
1852
|
+
*/
|
|
1853
|
+
followUser?: boolean;
|
|
1854
|
+
onMapClick?: (point: MapClick, event: PointerEvent) => void;
|
|
1855
|
+
onMarkerClick?: (marker: MapMarker, event: MouseEvent) => void;
|
|
1856
|
+
onMoveEnd?: (state: MapState) => void;
|
|
1857
|
+
/** Fires on each watched fix, including the ones while `followUser` is off. */
|
|
1858
|
+
onUserUpdate?: (fix: MapFix) => void;
|
|
1859
|
+
}
|
|
1860
|
+
export function Maps(props: MapsProps): Widget & {
|
|
1861
|
+
setCenter(position: LatLng, zoom?: number): Widget;
|
|
1862
|
+
getCenter(): { lat: number; lng: number };
|
|
1863
|
+
getZoom(): number;
|
|
1864
|
+
zoomTo(zoom: number): Widget;
|
|
1865
|
+
panBy(dx: number, dy: number): Widget;
|
|
1866
|
+
fitBounds(bounds: MapBounds, padding?: number): Widget;
|
|
1867
|
+
getState(): MapState;
|
|
1868
|
+
addMarker(marker: MapMarker | LatLng): MapMarker | null;
|
|
1869
|
+
/** Replace the marker with the same id, or append it when that id is new. */
|
|
1870
|
+
setMarker(marker: MapMarker | LatLng): MapMarker | null;
|
|
1871
|
+
removeMarker(idOrMarker: string | number | MapMarker): Widget;
|
|
1872
|
+
clearMarkers(): Widget;
|
|
1873
|
+
getMarkers(): MapMarker[];
|
|
1874
|
+
addPolyline(line: MapPolyline | LatLng[]): MapPolyline | null;
|
|
1875
|
+
removePolyline(idOrLine: string | number | MapPolyline): Widget;
|
|
1876
|
+
clearPolylines(): Widget;
|
|
1877
|
+
getPolylines(): MapPolyline[];
|
|
1878
|
+
setFollowUser(on: boolean): Widget;
|
|
1879
|
+
locate(settings?: { setCenter?: boolean; zoom?: number; timeout?: number; maximumAge?: number; highAccuracy?: boolean }): Promise<{ lat: number; lng: number }> | null;
|
|
1880
|
+
setUserPosition(position: LatLng | number[] | null, settings?: { setCenter?: boolean; zoom?: number }): Widget;
|
|
1881
|
+
render(): Widget;
|
|
1882
|
+
};
|
|
1883
|
+
|
|
1703
1884
|
// =========================================================================
|
|
1704
1885
|
// Core
|
|
1705
1886
|
// =========================================================================
|
|
@@ -1752,6 +1933,10 @@ declare module 'flet-box' {
|
|
|
1752
1933
|
export const colors: Record<string, string>;
|
|
1753
1934
|
export const palettes: Record<string, Record<string, string>>;
|
|
1754
1935
|
export function setTheme(themeName: 'light' | 'dark'): Record<string, string>;
|
|
1936
|
+
export function registerPalette(
|
|
1937
|
+
themeName: string,
|
|
1938
|
+
palette: Record<string, string>
|
|
1939
|
+
): Record<string, string>;
|
|
1755
1940
|
export function getTheme(): string;
|
|
1756
1941
|
export function toggleTheme(): string;
|
|
1757
1942
|
export function getColor(colorName: string, opacity?: number): string;
|
|
@@ -1952,9 +2137,12 @@ declare module 'flet-box' {
|
|
|
1952
2137
|
isDark(): boolean;
|
|
1953
2138
|
isLight(): boolean;
|
|
1954
2139
|
contrast(): string;
|
|
2140
|
+
luminance(): number;
|
|
2141
|
+
contrastRatio(other: string | ColorInstance): number;
|
|
2142
|
+
meetsContrast(other: string | ColorInstance, minimum?: number): boolean;
|
|
1955
2143
|
}
|
|
1956
2144
|
|
|
1957
|
-
export const color: (value: string) => ColorInstance;
|
|
2145
|
+
export const color: (value: string | ColorInstance) => ColorInstance;
|
|
1958
2146
|
export function rgba(r: number, g: number, b: number, a?: number): string;
|
|
1959
2147
|
export function stackPosition(widget: Widget, props: { top?: any; right?: any; bottom?: any; left?: any }): Widget;
|
|
1960
2148
|
export function flex(grow: number | { grow?: number; shrink?: number; basis?: string }, shrink?: number, basis?: string): string;
|
|
@@ -2063,5 +2251,5 @@ declare module 'flet-box' {
|
|
|
2063
2251
|
// =========================================================================
|
|
2064
2252
|
export const highlightColors: Record<string, string>;
|
|
2065
2253
|
export function tokenize(code: string): Array<{ type: string; value: string }>;
|
|
2066
|
-
export function generateHighlightedHtml(code: string): string;
|
|
2254
|
+
export function generateHighlightedHtml(code: string, palette?: Record<string, string>): string;
|
|
2067
2255
|
}
|
package/src/index.js
CHANGED
|
@@ -59,6 +59,9 @@ import { goBack, goTo } from "./Router.js";
|
|
|
59
59
|
* - `setBackgroundColor(color: string)` — swap the background color or gradient.
|
|
60
60
|
* - `show()` / `hide()` — toggle bar visibility.
|
|
61
61
|
*/
|
|
62
|
+
import { toREM } from "../utils/units.js";
|
|
63
|
+
import { SHADOW_LEVELS } from "../tools/shadow.js";
|
|
64
|
+
|
|
62
65
|
export const AppBar = (props) => {
|
|
63
66
|
const {
|
|
64
67
|
title,
|
|
@@ -119,18 +122,10 @@ export const AppBar = (props) => {
|
|
|
119
122
|
const finalPaddingRight = paddingRight || padding;
|
|
120
123
|
|
|
121
124
|
const finalBorderRadius =
|
|
122
|
-
|
|
125
|
+
toREM(borderRadius);
|
|
123
126
|
|
|
124
|
-
//
|
|
125
|
-
const
|
|
126
|
-
0: "none",
|
|
127
|
-
1: "0 1px 3px rgba(0,0,0,0.12)",
|
|
128
|
-
2: "0 3px 6px rgba(0,0,0,0.16)",
|
|
129
|
-
3: "0 6px 12px rgba(0,0,0,0.2)",
|
|
130
|
-
4: "0 10px 20px rgba(0,0,0,0.25)",
|
|
131
|
-
5: "0 15px 30px rgba(0,0,0,0.3)",
|
|
132
|
-
};
|
|
133
|
-
const boxShadow = shadow === true ? shadows[elevation] : shadow || "none";
|
|
127
|
+
// The framework's depth scale, not a local copy of it (src/tools/shadow.js).
|
|
128
|
+
const boxShadow = shadow === true ? SHADOW_LEVELS[elevation] : shadow || "none";
|
|
134
129
|
|
|
135
130
|
// ========== LEADING SECTION ==========
|
|
136
131
|
// Auto-create a back button if requested and no custom leading was supplied.
|
|
@@ -173,7 +168,7 @@ export const AppBar = (props) => {
|
|
|
173
168
|
marginBottom: finalMarginBottom,
|
|
174
169
|
marginLeft: finalMarginLeft,
|
|
175
170
|
marginRight: finalMarginRight,
|
|
176
|
-
paddingTop: `calc(${finalPaddingTop}
|
|
171
|
+
paddingTop: `calc(${toREM(finalPaddingTop)} + env(safe-area-inset-top, 0px))`,
|
|
177
172
|
paddingBottom: finalPaddingBottom,
|
|
178
173
|
paddingLeft: finalPaddingLeft,
|
|
179
174
|
paddingRight: finalPaddingRight,
|
|
@@ -189,15 +184,20 @@ export const AppBar = (props) => {
|
|
|
189
184
|
|
|
190
185
|
// ========== LEFT SECTION ==========
|
|
191
186
|
// Fixed minimum width ensures the center title stays visually centered
|
|
192
|
-
// even when no leading widget is present.
|
|
187
|
+
// even when no leading widget is present. That balance is only meaningful
|
|
188
|
+
// for a centered title: with `centerTitle: false` the title is flush-left,
|
|
189
|
+
// so reserving the empty 48px zone would push it past the page's content
|
|
190
|
+
// edge. Same reasoning for the title zone's 8px gutter.
|
|
191
|
+
const hasLeading = finalLeading instanceof HTMLElement;
|
|
192
|
+
const balanceZones = centerTitle || hasLeading;
|
|
193
193
|
const leftSection = Container({
|
|
194
194
|
display: "flex",
|
|
195
195
|
alignItems: "center",
|
|
196
196
|
bgColor: "transparent",
|
|
197
197
|
justifyContent: "flex-start",
|
|
198
|
-
minWidth: 48,
|
|
198
|
+
minWidth: balanceZones ? 48 : 0,
|
|
199
199
|
flexShrink: 0,
|
|
200
|
-
child:
|
|
200
|
+
child: hasLeading ? finalLeading : null,
|
|
201
201
|
});
|
|
202
202
|
appBar.appendChild(leftSection);
|
|
203
203
|
|
|
@@ -224,9 +224,15 @@ export const AppBar = (props) => {
|
|
|
224
224
|
// pushes the actions past the viewport edge on narrow screens.
|
|
225
225
|
flex: 1,
|
|
226
226
|
display: "flex",
|
|
227
|
+
// Container defaults to `flex-direction: column`, which silently rewrites
|
|
228
|
+
// the two axes: `alignItems: center` becomes horizontal centring and
|
|
229
|
+
// `justifyContent` (the flag that carries `centerTitle`) becomes vertical.
|
|
230
|
+
// A string title hid this because its Text fills the width; an
|
|
231
|
+
// auto-width widget title got centred no matter what `centerTitle` said.
|
|
232
|
+
flexDirection: "row",
|
|
227
233
|
alignItems: "center",
|
|
228
234
|
justifyContent: centerTitle ? "center" : "flex-start",
|
|
229
|
-
padding: "0 8px",
|
|
235
|
+
padding: balanceZones ? "0 8px" : "0",
|
|
230
236
|
bgColor: "transparent",
|
|
231
237
|
overflow: "hidden",
|
|
232
238
|
minWidth: 0,
|
|
@@ -53,6 +53,9 @@ import { getCurrentPath, subscribe, goTo } from "./Router.js";
|
|
|
53
53
|
* - `getActiveIndex(): number` — returns the currently active tab index.
|
|
54
54
|
* - `getCurrentRoute(): string|null` — returns the current router path (router mode only).
|
|
55
55
|
*/
|
|
56
|
+
import { toREM } from "../utils/units.js";
|
|
57
|
+
import { SHADOW_LEVELS } from "../tools/shadow.js";
|
|
58
|
+
|
|
56
59
|
export const BottomNavigation = (props) => {
|
|
57
60
|
const {
|
|
58
61
|
items = [],
|
|
@@ -90,24 +93,16 @@ export const BottomNavigation = (props) => {
|
|
|
90
93
|
const finalMarginLeft = marginLeft || margin;
|
|
91
94
|
const finalMarginRight = marginRight || margin;
|
|
92
95
|
const finalBorderRadius =
|
|
93
|
-
|
|
94
|
-
const finalPadding =
|
|
96
|
+
toREM(borderRadius);
|
|
97
|
+
const finalPadding = toREM(padding);
|
|
95
98
|
|
|
96
|
-
//
|
|
97
|
-
const
|
|
98
|
-
0: "none",
|
|
99
|
-
1: "0 1px 3px rgba(0,0,0,0.12)",
|
|
100
|
-
2: "0 3px 6px rgba(0,0,0,0.16)",
|
|
101
|
-
3: "0 6px 12px rgba(0,0,0,0.2)",
|
|
102
|
-
4: "0 10px 20px rgba(0,0,0,0.25)",
|
|
103
|
-
5: "0 15px 30px rgba(0,0,0,0.3)",
|
|
104
|
-
};
|
|
105
|
-
const boxShadow = shadow === true ? shadows[elevation] : shadow || "none";
|
|
99
|
+
// The framework's depth scale, not a local copy of it (src/tools/shadow.js).
|
|
100
|
+
const boxShadow = shadow === true ? SHADOW_LEVELS[elevation] : shadow || "none";
|
|
106
101
|
|
|
107
102
|
const container = WidgetFactory({
|
|
108
103
|
tag: "nav",
|
|
109
104
|
display: "flex",
|
|
110
|
-
width: `calc(100% - ${finalMarginLeft}
|
|
105
|
+
width: `calc(100% - ${toREM(finalMarginLeft)} - ${toREM(finalMarginRight)})`,
|
|
111
106
|
height: height,
|
|
112
107
|
backgroundColor: backgroundColor,
|
|
113
108
|
borderRadius: finalBorderRadius,
|
|
@@ -42,6 +42,8 @@ import { colors } from "../utils/themes.js";
|
|
|
42
42
|
* @returns {HTMLElement} The sidebar container element, augmented with:
|
|
43
43
|
* - `updateWidth(w: number|string)` — resize the sidebar programmatically.
|
|
44
44
|
*/
|
|
45
|
+
import { toREM } from "../utils/units.js";
|
|
46
|
+
|
|
45
47
|
export const CollapsibleSideBar = ({
|
|
46
48
|
children,
|
|
47
49
|
expanded = true,
|
|
@@ -63,14 +65,33 @@ export const CollapsibleSideBar = ({
|
|
|
63
65
|
);
|
|
64
66
|
let expandedState = Boolean(stateValue.valueOf());
|
|
65
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Paint the expanded/collapsed state onto the elements built below.
|
|
70
|
+
*
|
|
71
|
+
* The toggle has to do more than record the state: the width, the chevron
|
|
72
|
+
* glyph and the content's interactivity are all written once at build time,
|
|
73
|
+
* so without this the bar never moved.
|
|
74
|
+
*
|
|
75
|
+
* @param {boolean} isExpanded
|
|
76
|
+
* @returns {void}
|
|
77
|
+
*/
|
|
78
|
+
const paint = (isExpanded) => {
|
|
79
|
+
container.style.width = toREM(isExpanded ? widthExpanded : widthCollapsed);
|
|
80
|
+
chevron.textContent = isExpanded ? "chevron_left" : "chevron_right";
|
|
81
|
+
contentWrapper.style.opacity = isExpanded ? "1" : "0";
|
|
82
|
+
contentWrapper.style.pointerEvents = isExpanded ? "auto" : "none";
|
|
83
|
+
};
|
|
84
|
+
|
|
66
85
|
/**
|
|
67
86
|
* Toggle the sidebar between expanded and collapsed states.
|
|
68
|
-
* Updates the persisted state and fires the `onToggle`
|
|
87
|
+
* Updates the persisted state, repaints the bar and fires the `onToggle`
|
|
88
|
+
* callback.
|
|
69
89
|
*/
|
|
70
90
|
const toggle = () => {
|
|
71
91
|
const newState = !expandedState;
|
|
72
92
|
expandedState = newState;
|
|
73
93
|
setIsExpanded(newState);
|
|
94
|
+
paint(newState);
|
|
74
95
|
if (onToggle) onToggle(newState);
|
|
75
96
|
};
|
|
76
97
|
|
|
@@ -81,7 +102,7 @@ export const CollapsibleSideBar = ({
|
|
|
81
102
|
tag: "div",
|
|
82
103
|
id,
|
|
83
104
|
width:
|
|
84
|
-
|
|
105
|
+
toREM(currentWidth),
|
|
85
106
|
height: "100%",
|
|
86
107
|
display: "flex",
|
|
87
108
|
flexDirection: "column",
|
|
@@ -95,15 +116,16 @@ export const CollapsibleSideBar = ({
|
|
|
95
116
|
|
|
96
117
|
// Toggle button — always visible so the user can expand/collapse regardless
|
|
97
118
|
// of the current state. The icon flips direction to reflect the state.
|
|
119
|
+
const chevron = Icon({
|
|
120
|
+
name: expandedState ? "chevron_left" : "chevron_right",
|
|
121
|
+
size: iconSize,
|
|
122
|
+
color: colors.textSecondary,
|
|
123
|
+
});
|
|
98
124
|
const toggleButton = Container({
|
|
99
125
|
padding: 16,
|
|
100
126
|
cursor: "pointer",
|
|
101
127
|
onclick: toggle,
|
|
102
|
-
child:
|
|
103
|
-
name: expandedState ? "chevron_left" : "chevron_right",
|
|
104
|
-
size: iconSize,
|
|
105
|
-
color: colors.textSecondary,
|
|
106
|
-
}),
|
|
128
|
+
child: chevron,
|
|
107
129
|
});
|
|
108
130
|
container.appendChild(toggleButton);
|
|
109
131
|
|
|
@@ -130,7 +152,7 @@ export const CollapsibleSideBar = ({
|
|
|
130
152
|
*/
|
|
131
153
|
container.updateWidth = (newWidth) => {
|
|
132
154
|
container.style.width =
|
|
133
|
-
|
|
155
|
+
toREM(newWidth);
|
|
134
156
|
};
|
|
135
157
|
|
|
136
158
|
return container;
|
|
@@ -58,6 +58,8 @@ let drawerInstance = null;
|
|
|
58
58
|
* @param {DrawerProps} [props={}]
|
|
59
59
|
* @returns {DrawerInstance}
|
|
60
60
|
*/
|
|
61
|
+
import { toREM } from "../utils/units.js";
|
|
62
|
+
|
|
61
63
|
export const Drawer = (props = {}) => {
|
|
62
64
|
const {
|
|
63
65
|
header,
|
|
@@ -107,9 +109,9 @@ export const Drawer = (props = {}) => {
|
|
|
107
109
|
// Sliding drawer panel.
|
|
108
110
|
const drawerPanel = document.createElement("div");
|
|
109
111
|
drawerPanel.style.position = "absolute";
|
|
110
|
-
drawerPanel.style.top =
|
|
111
|
-
drawerPanel.style.bottom =
|
|
112
|
-
drawerPanel.style.height = `calc(100% - ${margin * 2}
|
|
112
|
+
drawerPanel.style.top = toREM(margin);
|
|
113
|
+
drawerPanel.style.bottom = toREM(margin);
|
|
114
|
+
drawerPanel.style.height = `calc(100% - ${toREM(margin * 2)})`;
|
|
113
115
|
drawerPanel.style.display = "flex";
|
|
114
116
|
drawerPanel.style.flexDirection = "column";
|
|
115
117
|
drawerPanel.style.backgroundColor = bgColor;
|
|
@@ -118,22 +120,22 @@ export const Drawer = (props = {}) => {
|
|
|
118
120
|
// Apply border radius only to the corners that face away from the screen edge.
|
|
119
121
|
// A left drawer gets rounded right corners; a right drawer gets rounded left corners.
|
|
120
122
|
if (position === "left") {
|
|
121
|
-
drawerPanel.style.left =
|
|
123
|
+
drawerPanel.style.left = toREM(margin);
|
|
122
124
|
drawerPanel.style.right = "auto";
|
|
123
|
-
drawerPanel.style.borderTopRightRadius =
|
|
124
|
-
drawerPanel.style.borderBottomRightRadius =
|
|
125
|
+
drawerPanel.style.borderTopRightRadius = toREM(borderRadius);
|
|
126
|
+
drawerPanel.style.borderBottomRightRadius = toREM(borderRadius);
|
|
125
127
|
drawerPanel.style.borderTopLeftRadius = "0";
|
|
126
128
|
drawerPanel.style.borderBottomLeftRadius = "0";
|
|
127
129
|
} else {
|
|
128
|
-
drawerPanel.style.right =
|
|
130
|
+
drawerPanel.style.right = toREM(margin);
|
|
129
131
|
drawerPanel.style.left = "auto";
|
|
130
|
-
drawerPanel.style.borderTopLeftRadius =
|
|
131
|
-
drawerPanel.style.borderBottomLeftRadius =
|
|
132
|
+
drawerPanel.style.borderTopLeftRadius = toREM(borderRadius);
|
|
133
|
+
drawerPanel.style.borderBottomLeftRadius = toREM(borderRadius);
|
|
132
134
|
drawerPanel.style.borderTopRightRadius = "0";
|
|
133
135
|
drawerPanel.style.borderBottomRightRadius = "0";
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
drawerPanel.style.width =
|
|
138
|
+
drawerPanel.style.width = toREM(width);
|
|
137
139
|
// Start the panel off-screen so the entrance animation slides it in.
|
|
138
140
|
drawerPanel.style.transform =
|
|
139
141
|
position === "left" ? "translateX(-100%)" : "translateX(100%)";
|
|
@@ -160,8 +162,8 @@ export const Drawer = (props = {}) => {
|
|
|
160
162
|
header &&
|
|
161
163
|
Container({
|
|
162
164
|
flexShrink: 0,
|
|
163
|
-
borderTopLeftRadius: position === "right" ?
|
|
164
|
-
borderTopRightRadius: position === "left" ?
|
|
165
|
+
borderTopLeftRadius: position === "right" ? toREM(borderRadius) : "0",
|
|
166
|
+
borderTopRightRadius: position === "left" ? toREM(borderRadius) : "0",
|
|
165
167
|
overflow: "hidden",
|
|
166
168
|
child: header,
|
|
167
169
|
}),
|
|
@@ -173,16 +175,24 @@ export const Drawer = (props = {}) => {
|
|
|
173
175
|
paddingBottom: 8,
|
|
174
176
|
overflow: "auto",
|
|
175
177
|
backgroundColor: bgColor,
|
|
176
|
-
|
|
178
|
+
// This body is a scroll container inside a fixed-height flex column,
|
|
179
|
+
// and every child defaults to `flex-shrink: 1`. Left alone, a short
|
|
180
|
+
// drawer squeezed its rows down to their own padding (a DrawerItem
|
|
181
|
+
// collapsed to ~24px) instead of overflowing. Pinning the children
|
|
182
|
+
// keeps them at content height so the body scrolls as intended.
|
|
183
|
+
children: body.map((child) => {
|
|
184
|
+
if (child && child.style) child.style.flexShrink = "0";
|
|
185
|
+
return child;
|
|
186
|
+
}),
|
|
177
187
|
}),
|
|
178
188
|
|
|
179
189
|
footer &&
|
|
180
190
|
Container({
|
|
181
191
|
flexShrink: 0,
|
|
182
192
|
borderBottomLeftRadius:
|
|
183
|
-
position === "right" ?
|
|
193
|
+
position === "right" ? toREM(borderRadius) : "0",
|
|
184
194
|
borderBottomRightRadius:
|
|
185
|
-
position === "left" ?
|
|
195
|
+
position === "left" ? toREM(borderRadius) : "0",
|
|
186
196
|
overflow: "hidden",
|
|
187
197
|
child: footer,
|
|
188
198
|
}),
|
|
@@ -143,6 +143,8 @@ export const DrawerItem = (props) => {
|
|
|
143
143
|
* Order of operations: mark selected → fire callbacks → navigate → close drawer.
|
|
144
144
|
*/
|
|
145
145
|
const handleClick = () => {
|
|
146
|
+
// `onSelect` marks the transition into the selected state — it is what an
|
|
147
|
+
// app counts to open a section once. `onPress` fires on every tap.
|
|
146
148
|
if (!isSelected) {
|
|
147
149
|
isSelected = true;
|
|
148
150
|
updateUI();
|
|
@@ -150,8 +152,8 @@ export const DrawerItem = (props) => {
|
|
|
150
152
|
selectionEvent.dispatchEvent(
|
|
151
153
|
new CustomEvent("drawer-item-selected", { detail: { id: label } }),
|
|
152
154
|
);
|
|
155
|
+
if (onSelect) onSelect();
|
|
153
156
|
}
|
|
154
|
-
if (onSelect) onSelect();
|
|
155
157
|
if (onPress) onPress();
|
|
156
158
|
if (route) goTo(route);
|
|
157
159
|
if (closeOnPress) closeDrawer();
|