flet-box 1.0.3 → 1.0.5
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 +15 -0
- 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 +4 -2
- package/src/animations/AnimatedBox.js +32 -1
- package/src/animations/AnimatedText.js +7 -3
- package/src/animations/MatrixRain.js +37 -12
- package/src/animations/ParallaxBox.js +16 -3
- package/src/animations/animate.js +187 -58
- package/src/animations/index.js +1 -0
- package/src/core/runApp.js +13 -1
- package/src/create-index.sh +1 -1
- package/src/index.d.ts +227 -91
- package/src/index.js +1 -0
- package/src/navigations/AdaptiveScaffold.js +11 -2
- package/src/navigations/AppBar.js +8 -2
- package/src/navigations/BottomNavigation.js +24 -5
- package/src/navigations/DrawerItem.js +16 -3
- package/src/navigations/Scaffold.js +8 -1
- package/src/navigations/Tabs.js +40 -8
- package/src/tools/dimensions.js +11 -3
- package/src/tools/useState.js +139 -101
- package/src/utils/getWidgetProps.js +5 -3
- package/src/widget-factory/assignProps.js +30 -11
- package/src/widget-factory/processProps.js +17 -5
- package/src/widget-factory/reactiveValue.js +172 -0
- package/src/widget-factory/translateProps.js +777 -901
- package/src/widget-factory/warnings.js +15 -0
- package/src/widget-factory/widgetFactory.js +27 -0
- package/src/widgets/Accordion.js +6 -5
- package/src/widgets/AlertDialog.js +7 -5
- package/src/widgets/Audio.js +30 -8
- package/src/widgets/BottomSheet.js +24 -1
- package/src/widgets/Chart.js +4 -1
- package/src/widgets/Checkbox.js +16 -8
- package/src/widgets/CircularBar.js +12 -1
- package/src/widgets/CircularChart.js +4 -1
- package/src/widgets/CodeViewer.js +26 -8
- package/src/widgets/DataTable.js +11 -2
- package/src/widgets/Dropdown.js +5 -1
- package/src/widgets/FloatingActionButton.js +4 -7
- package/src/widgets/Image.js +7 -2
- package/src/widgets/Input.js +119 -6
- package/src/widgets/Inspector.js +16 -10
- package/src/widgets/ListView.js +80 -30
- package/src/widgets/Markdown.js +53 -8
- package/src/widgets/Modal.js +24 -1
- package/src/widgets/Pagination.js +6 -3
- package/src/widgets/ProgressBar.js +16 -13
- package/src/widgets/QRCode.js +9 -2
- package/src/widgets/Radio.js +11 -8
- package/src/widgets/Slider.js +26 -4
- package/src/widgets/SnackBar.js +20 -2
- package/src/widgets/Stack.js +36 -3
- package/src/widgets/Stepper.js +4 -3
- package/src/widgets/Switch.js +8 -5
- package/src/widgets/TreeView.js +3 -2
|
@@ -43,9 +43,9 @@ export const ProgressBar = (props) => {
|
|
|
43
43
|
position: "relative",
|
|
44
44
|
...(striped || indeterminate
|
|
45
45
|
? {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
backgroundImage: `repeating-linear-gradient(45deg, rgba(255,255,255,0.15) 0px, rgba(255,255,255,0.15) 10px, transparent 10px, transparent 20px)`,
|
|
47
|
+
backgroundSize: "28px 28px",
|
|
48
|
+
}
|
|
49
49
|
: {}),
|
|
50
50
|
});
|
|
51
51
|
|
|
@@ -115,9 +115,15 @@ export const ProgressBar = (props) => {
|
|
|
115
115
|
);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
// Value percentage
|
|
118
|
+
// Value percentage.
|
|
119
|
+
// FIX: guardo referencia directa al span del valor (`valueElRef`) en vez de
|
|
120
|
+
// buscarlo con `querySelector("span:last-child")` — la versión anterior
|
|
121
|
+
// podía escribir el porcentaje dentro del label (si el label estaba a la
|
|
122
|
+
// derecha, era el último span) y el check `valueEl !== label` nunca fallaba
|
|
123
|
+
// porque `label` era un string.
|
|
124
|
+
let valueElRef = null;
|
|
119
125
|
if (showValue && !indeterminate) {
|
|
120
|
-
|
|
126
|
+
valueElRef = WidgetFactory({
|
|
121
127
|
tag: "span",
|
|
122
128
|
textContent: `${Math.round(percentage)}%`,
|
|
123
129
|
fontSize: "12px",
|
|
@@ -129,9 +135,9 @@ export const ProgressBar = (props) => {
|
|
|
129
135
|
});
|
|
130
136
|
|
|
131
137
|
if (valuePosition === "left" || valuePosition === "top") {
|
|
132
|
-
children.unshift(
|
|
138
|
+
children.unshift(valueElRef);
|
|
133
139
|
} else {
|
|
134
|
-
children.push(
|
|
140
|
+
children.push(valueElRef);
|
|
135
141
|
}
|
|
136
142
|
}
|
|
137
143
|
|
|
@@ -154,11 +160,8 @@ export const ProgressBar = (props) => {
|
|
|
154
160
|
percentage = (progressValue / max) * 100;
|
|
155
161
|
fill.style.width = `${percentage}%`;
|
|
156
162
|
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
if (valueEl && valueEl !== label) {
|
|
160
|
-
valueEl.textContent = `${Math.round(percentage)}%`;
|
|
161
|
-
}
|
|
163
|
+
if (valueElRef) {
|
|
164
|
+
valueElRef.textContent = `${Math.round(percentage)}%`;
|
|
162
165
|
}
|
|
163
166
|
};
|
|
164
167
|
|
|
@@ -175,4 +178,4 @@ export const ProgressBar = (props) => {
|
|
|
175
178
|
return container;
|
|
176
179
|
};
|
|
177
180
|
|
|
178
|
-
export default ProgressBar;
|
|
181
|
+
export default ProgressBar;
|
package/src/widgets/QRCode.js
CHANGED
|
@@ -116,7 +116,9 @@ function buildQRMatrix(text, ecLevel = "M") {
|
|
|
116
116
|
for (let i = len - 1; i >= 0; i--) bits.push((val >> i) & 1);
|
|
117
117
|
};
|
|
118
118
|
pushBits(0b0100, 4); // mode indicator: byte
|
|
119
|
-
|
|
119
|
+
// Character count: 8 bits for versions 1-9, 16 bits for versions 10-40
|
|
120
|
+
// (ISO/IEC 18004). Emitting 8 bits at version 10 misaligns every later bit.
|
|
121
|
+
pushBits(bytes.length, version < 10 ? 8 : 16);
|
|
120
122
|
for (const b of bytes) pushBits(b, 8);
|
|
121
123
|
// Terminator
|
|
122
124
|
for (let i = 0; i < 4 && bits.length < dataCodewords * 8; i++) bits.push(0);
|
|
@@ -161,7 +163,12 @@ function buildQRMatrix(text, ecLevel = "M") {
|
|
|
161
163
|
|
|
162
164
|
// 7. Build final bit sequence
|
|
163
165
|
const finalBits = [];
|
|
164
|
-
|
|
166
|
+
// NOTE: `pushBits` writes into `bits` (the pre-interleave stream), so it must
|
|
167
|
+
// not be used here. Using it left `finalBits` empty, and the placement pass
|
|
168
|
+
// then wrote every data module as 0 — the symbol carried no payload at all.
|
|
169
|
+
for (const cw of finalCW) {
|
|
170
|
+
for (let i = 7; i >= 0; i--) finalBits.push((cw >> i) & 1);
|
|
171
|
+
}
|
|
165
172
|
// Remainder bits (version-dependent, versions 2–6 need 7)
|
|
166
173
|
const remainderBitsCount = version >= 2 && version <= 6 ? 7 : 0;
|
|
167
174
|
for (let i = 0; i < remainderBitsCount; i++) finalBits.push(0);
|
package/src/widgets/Radio.js
CHANGED
|
@@ -13,6 +13,7 @@ export const Radio = (props) => {
|
|
|
13
13
|
disabled = false,
|
|
14
14
|
size = 20,
|
|
15
15
|
name,
|
|
16
|
+
activeColor = colors.primary,
|
|
16
17
|
...rest
|
|
17
18
|
} = props;
|
|
18
19
|
|
|
@@ -26,10 +27,8 @@ export const Radio = (props) => {
|
|
|
26
27
|
|
|
27
28
|
const updateUI = (newSelected) => {
|
|
28
29
|
if (radioRef) {
|
|
29
|
-
radioRef.style.backgroundColor = newSelected
|
|
30
|
-
|
|
31
|
-
: "transparent";
|
|
32
|
-
radioRef.style.border = `2px solid ${newSelected ? colors.primary : colors.border}`;
|
|
30
|
+
radioRef.style.backgroundColor = newSelected ? activeColor : "transparent";
|
|
31
|
+
radioRef.style.border = `2px solid ${newSelected ? activeColor : colors.border}`;
|
|
33
32
|
}
|
|
34
33
|
if (dotRef) {
|
|
35
34
|
dotRef.style.display = newSelected ? "block" : "none";
|
|
@@ -51,9 +50,9 @@ export const Radio = (props) => {
|
|
|
51
50
|
widgetName: "Radio",
|
|
52
51
|
width: size,
|
|
53
52
|
height: size,
|
|
54
|
-
border: `2px solid ${disabled ? colors.border : internalSelected ?
|
|
53
|
+
border: `2px solid ${disabled ? colors.border : internalSelected ? activeColor : colors.border}`,
|
|
55
54
|
borderRadius: "50%",
|
|
56
|
-
backgroundColor: internalSelected ?
|
|
55
|
+
backgroundColor: internalSelected ? activeColor : "transparent",
|
|
57
56
|
display: "flex",
|
|
58
57
|
alignItems: "center",
|
|
59
58
|
justifyContent: "center",
|
|
@@ -67,7 +66,7 @@ export const Radio = (props) => {
|
|
|
67
66
|
|
|
68
67
|
// Handle click
|
|
69
68
|
if (!disabled) {
|
|
70
|
-
|
|
69
|
+
const handleClick = (e) => {
|
|
71
70
|
e.stopPropagation();
|
|
72
71
|
if (internalSelected) return;
|
|
73
72
|
|
|
@@ -88,11 +87,15 @@ export const Radio = (props) => {
|
|
|
88
87
|
|
|
89
88
|
if (onPress) onPress(true);
|
|
90
89
|
};
|
|
90
|
+
// Routed through the factory props: `assignProps` clears `onclick` on every
|
|
91
|
+
// update and only re-applies handlers present in the merged props, so a
|
|
92
|
+
// direct assignment died on the first `update()` or reactive setter.
|
|
93
|
+
radio.update({ onPress: handleClick });
|
|
91
94
|
|
|
92
95
|
// Hover effect
|
|
93
96
|
radio.addEventListener("mouseenter", () => {
|
|
94
97
|
if (!disabled && !internalSelected) {
|
|
95
|
-
radio.style.backgroundColor =
|
|
98
|
+
radio.style.backgroundColor = `color-mix(in srgb, ${activeColor} 12%, transparent)`;
|
|
96
99
|
}
|
|
97
100
|
});
|
|
98
101
|
|
package/src/widgets/Slider.js
CHANGED
|
@@ -50,8 +50,8 @@ export const Slider = (props) => {
|
|
|
50
50
|
stripeColor = "rgba(255,255,255,0.25)",
|
|
51
51
|
glow = false,
|
|
52
52
|
// Events
|
|
53
|
+
/** @deprecated Alias of `onPress`. */
|
|
53
54
|
onChanged,
|
|
54
|
-
/** @deprecated Use onPress instead */
|
|
55
55
|
onPress: onPressProp,
|
|
56
56
|
onChangeEnd,
|
|
57
57
|
// Rest
|
|
@@ -77,6 +77,13 @@ export const Slider = (props) => {
|
|
|
77
77
|
typeof trackSizePx === "number" ? `${trackSizePx}px` : trackSizePx;
|
|
78
78
|
let thumbSizeNum = typeof thumbSize === "number" ? thumbSize : 20;
|
|
79
79
|
|
|
80
|
+
// Positioning retries while the track still measures 0 (hidden parent, not laid
|
|
81
|
+
// out yet). Both handles are tracked so unmounting can stop them: an untracked
|
|
82
|
+
// recursive rAF outlived the widget and re-armed itself every frame, forever.
|
|
83
|
+
let thumbRaf = 0;
|
|
84
|
+
let initTimer = 0;
|
|
85
|
+
let disposed = false;
|
|
86
|
+
|
|
80
87
|
injectKeyframes(
|
|
81
88
|
"slider-stripes",
|
|
82
89
|
"0% { background-position: 0 0; } 100% { background-position: 20px 0; }",
|
|
@@ -299,6 +306,9 @@ export const Slider = (props) => {
|
|
|
299
306
|
|
|
300
307
|
function generateDefaultMarks() {
|
|
301
308
|
const stepMark = (currentMax - currentMin) / 4;
|
|
309
|
+
// With `min === max` (or non-numeric bounds) stepMark is 0/NaN, so
|
|
310
|
+
// `i += stepMark` never advances and the loop hangs the tab forever.
|
|
311
|
+
if (!(stepMark > 0)) return [currentMin];
|
|
302
312
|
const marksList = [];
|
|
303
313
|
for (let i = currentMin; i <= currentMax + 0.1; i += stepMark) {
|
|
304
314
|
marksList.push(Math.round(i));
|
|
@@ -326,10 +336,16 @@ export const Slider = (props) => {
|
|
|
326
336
|
}
|
|
327
337
|
|
|
328
338
|
function updateThumbPosition() {
|
|
329
|
-
if (!track || !thumb) return;
|
|
339
|
+
if (disposed || !track || !thumb) return;
|
|
330
340
|
const trackRect = track.getBoundingClientRect();
|
|
331
341
|
if (trackRect.width === 0 && trackRect.height === 0) {
|
|
332
|
-
|
|
342
|
+
// Not measurable yet: wait one frame for layout, keeping a single pending
|
|
343
|
+
// frame instead of stacking one retry per caller.
|
|
344
|
+
if (thumbRaf) cancelAnimationFrame(thumbRaf);
|
|
345
|
+
thumbRaf = requestAnimationFrame(() => {
|
|
346
|
+
thumbRaf = 0;
|
|
347
|
+
updateThumbPosition();
|
|
348
|
+
});
|
|
333
349
|
return;
|
|
334
350
|
}
|
|
335
351
|
if (isHorizontal) {
|
|
@@ -503,6 +519,9 @@ export const Slider = (props) => {
|
|
|
503
519
|
|
|
504
520
|
// ---------- Cleanup ----------
|
|
505
521
|
const cleanup = () => {
|
|
522
|
+
disposed = true;
|
|
523
|
+
if (thumbRaf) cancelAnimationFrame(thumbRaf);
|
|
524
|
+
if (initTimer) clearTimeout(initTimer);
|
|
506
525
|
if (resizeObserver) {
|
|
507
526
|
resizeObserver.disconnect();
|
|
508
527
|
} else {
|
|
@@ -520,7 +539,10 @@ export const Slider = (props) => {
|
|
|
520
539
|
container.onUnmount(cleanup);
|
|
521
540
|
|
|
522
541
|
// Initialize position
|
|
523
|
-
setTimeout(() =>
|
|
542
|
+
initTimer = setTimeout(() => {
|
|
543
|
+
initTimer = 0;
|
|
544
|
+
updateThumbPosition();
|
|
545
|
+
}, 0);
|
|
524
546
|
return container;
|
|
525
547
|
};
|
|
526
548
|
|
package/src/widgets/SnackBar.js
CHANGED
|
@@ -124,9 +124,18 @@ export function SnackBar(options) {
|
|
|
124
124
|
});
|
|
125
125
|
|
|
126
126
|
let timeoutId = null;
|
|
127
|
+
let rafId = null;
|
|
128
|
+
// `close()` is final: it must fire `onClose` exactly once and must win any
|
|
129
|
+
// race against the pending `show()` frame, otherwise closing a toast right
|
|
130
|
+
// after creating it would flash it back to opacity 1 for a full animation.
|
|
131
|
+
let closed = false;
|
|
127
132
|
|
|
128
133
|
const show = () => {
|
|
129
|
-
|
|
134
|
+
if (closed) return;
|
|
135
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
136
|
+
rafId = requestAnimationFrame(() => {
|
|
137
|
+
rafId = null;
|
|
138
|
+
if (closed) return;
|
|
130
139
|
snackbar.style.opacity = "1";
|
|
131
140
|
snackbar.style.transform = "translateY(0)";
|
|
132
141
|
});
|
|
@@ -134,7 +143,16 @@ export function SnackBar(options) {
|
|
|
134
143
|
};
|
|
135
144
|
|
|
136
145
|
const close = () => {
|
|
137
|
-
if (
|
|
146
|
+
if (closed) return;
|
|
147
|
+
closed = true;
|
|
148
|
+
if (timeoutId) {
|
|
149
|
+
clearTimeout(timeoutId);
|
|
150
|
+
timeoutId = null;
|
|
151
|
+
}
|
|
152
|
+
if (rafId !== null) {
|
|
153
|
+
cancelAnimationFrame(rafId);
|
|
154
|
+
rafId = null;
|
|
155
|
+
}
|
|
138
156
|
snackbar.style.opacity = "0";
|
|
139
157
|
snackbar.style.transform =
|
|
140
158
|
position === "bottom"
|
package/src/widgets/Stack.js
CHANGED
|
@@ -1,27 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file Stack.js
|
|
3
3
|
* @description Positioning container for overlaying children (relative by default,
|
|
4
|
-
* use `position: "stack"` for absolute centering).
|
|
4
|
+
* use `position: "stack"` for absolute centering). Supports a nine-point
|
|
5
|
+
* `alignment` that anchors its children inside the box.
|
|
5
6
|
*/
|
|
6
7
|
import { WidgetFactory } from "../widget-factory/index.js";
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Nine-point grid → [vertical anchor, horizontal anchor].
|
|
11
|
+
* `alignment` turns the stack into a column flex container, so `justifyContent`
|
|
12
|
+
* carries the top/center/bottom anchor and `alignItems` the left/center/right one.
|
|
13
|
+
*/
|
|
14
|
+
const ALIGNMENTS = {
|
|
15
|
+
"top-left": ["flex-start", "flex-start"],
|
|
16
|
+
"top-center": ["flex-start", "center"],
|
|
17
|
+
"top-right": ["flex-start", "flex-end"],
|
|
18
|
+
"center-left": ["center", "flex-start"],
|
|
19
|
+
center: ["center", "center"],
|
|
20
|
+
"center-right": ["center", "flex-end"],
|
|
21
|
+
"bottom-left": ["flex-end", "flex-start"],
|
|
22
|
+
"bottom-center": ["flex-end", "center"],
|
|
23
|
+
"bottom-right": ["flex-end", "flex-end"],
|
|
24
|
+
};
|
|
25
|
+
|
|
8
26
|
export const Stack = (props = {}) => {
|
|
9
27
|
const {
|
|
10
28
|
// Default layout
|
|
11
29
|
position = "relative",
|
|
12
|
-
display
|
|
30
|
+
display,
|
|
13
31
|
boxSizing = "border-box",
|
|
14
32
|
|
|
33
|
+
// Nine-point anchor for the children
|
|
34
|
+
alignment,
|
|
35
|
+
|
|
15
36
|
// Everything else
|
|
16
37
|
...rest
|
|
17
38
|
} = props;
|
|
18
39
|
|
|
40
|
+
const preset = alignment ? ALIGNMENTS[alignment] : undefined;
|
|
41
|
+
|
|
42
|
+
// The preset sits before `...rest`, so an explicit `flexDirection`,
|
|
43
|
+
// `justifyContent` or `alignItems` from the caller always overrides it;
|
|
44
|
+
// `alignment` only fills the axes nobody claimed.
|
|
19
45
|
return WidgetFactory({
|
|
20
46
|
tag: "div",
|
|
21
47
|
widgetName: "Stack",
|
|
22
48
|
position: position,
|
|
23
|
-
display: display,
|
|
49
|
+
display: display ?? (preset ? "flex" : "block"),
|
|
24
50
|
boxSizing: boxSizing,
|
|
51
|
+
...(preset
|
|
52
|
+
? {
|
|
53
|
+
flexDirection: "column",
|
|
54
|
+
justifyContent: preset[0],
|
|
55
|
+
alignItems: preset[1],
|
|
56
|
+
}
|
|
57
|
+
: null),
|
|
25
58
|
...rest,
|
|
26
59
|
});
|
|
27
60
|
};
|
package/src/widgets/Stepper.js
CHANGED
|
@@ -274,12 +274,13 @@ export const Stepper = (props) => {
|
|
|
274
274
|
overflow: "auto",
|
|
275
275
|
});
|
|
276
276
|
|
|
277
|
-
// Navigation container
|
|
278
|
-
|
|
277
|
+
// Navigation container — only built when the stepper is allowed to drive itself.
|
|
278
|
+
// `updateUI()` below skips the whole nav branch while `navContainer` is null.
|
|
279
|
+
navContainer = showNavigation ? Container({ width: "100%" }) : null;
|
|
279
280
|
|
|
280
281
|
container.appendChild(stepsWrapper);
|
|
281
282
|
container.appendChild(contentContainer);
|
|
282
|
-
container.appendChild(navContainer);
|
|
283
|
+
if (navContainer) container.appendChild(navContainer);
|
|
283
284
|
|
|
284
285
|
// Initial render
|
|
285
286
|
updateUI();
|
package/src/widgets/Switch.js
CHANGED
|
@@ -12,6 +12,7 @@ export const Switch = (props) => {
|
|
|
12
12
|
onPress: onPressProp,
|
|
13
13
|
disabled = false,
|
|
14
14
|
size = "medium",
|
|
15
|
+
activeColor = colors.success,
|
|
15
16
|
...rest
|
|
16
17
|
} = props;
|
|
17
18
|
|
|
@@ -33,9 +34,7 @@ export const Switch = (props) => {
|
|
|
33
34
|
|
|
34
35
|
const updateUI = (newValue) => {
|
|
35
36
|
if (switchRef) {
|
|
36
|
-
switchRef.style.backgroundColor = newValue
|
|
37
|
-
? colors.success
|
|
38
|
-
: colors.gray300;
|
|
37
|
+
switchRef.style.backgroundColor = newValue ? activeColor : colors.gray300;
|
|
39
38
|
}
|
|
40
39
|
if (knobRef) {
|
|
41
40
|
knobRef.style.transform = newValue
|
|
@@ -63,7 +62,7 @@ export const Switch = (props) => {
|
|
|
63
62
|
widgetName: "Switch",
|
|
64
63
|
width: sz.width,
|
|
65
64
|
height: sz.height,
|
|
66
|
-
backgroundColor: internalValue ?
|
|
65
|
+
backgroundColor: internalValue ? activeColor : colors.gray300,
|
|
67
66
|
borderRadius: sz.height / 2,
|
|
68
67
|
display: "flex",
|
|
69
68
|
alignItems: "center",
|
|
@@ -79,13 +78,17 @@ export const Switch = (props) => {
|
|
|
79
78
|
|
|
80
79
|
// Handle click
|
|
81
80
|
if (!disabled) {
|
|
82
|
-
|
|
81
|
+
const handleClick = (e) => {
|
|
83
82
|
e.stopPropagation();
|
|
84
83
|
const newValue = !internalValue;
|
|
85
84
|
internalValue = newValue;
|
|
86
85
|
updateUI(newValue);
|
|
87
86
|
if (onPress) onPress(newValue);
|
|
88
87
|
};
|
|
88
|
+
// Routed through the factory props: `assignProps` clears `onclick` on every
|
|
89
|
+
// update and only re-applies handlers present in the merged props, so a
|
|
90
|
+
// direct assignment died on the first `update()` or reactive setter.
|
|
91
|
+
switchContainer.update({ onPress: handleClick });
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
// Public methods
|
package/src/widgets/TreeView.js
CHANGED
|
@@ -104,7 +104,6 @@ export const TreeView = (props) => {
|
|
|
104
104
|
typeof borderRadius === "number" ? `${borderRadius}px` : borderRadius,
|
|
105
105
|
marginLeft: `${level * indent}px`,
|
|
106
106
|
transition: `background-color ${transitionDuration} ease`,
|
|
107
|
-
hoverBackgroundColor: hoverBgColor,
|
|
108
107
|
});
|
|
109
108
|
|
|
110
109
|
// Add hover effect
|
|
@@ -280,7 +279,9 @@ export const TreeView = (props) => {
|
|
|
280
279
|
|
|
281
280
|
// ========== PUBLIC METHODS ==========
|
|
282
281
|
|
|
283
|
-
|
|
282
|
+
// NOTE: no `selectedId = null` default. The guard below tests `!== undefined`,
|
|
283
|
+
// so a `null` default made it always true and every call wiped the selection.
|
|
284
|
+
container.updateNodes = (newNodes, selectedId) => {
|
|
284
285
|
nodes.length = 0;
|
|
285
286
|
nodes.push(...newNodes);
|
|
286
287
|
if (selectedId !== undefined) currentSelectedId = selectedId;
|