flet-box 0.0.0-stage โ†’ 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +190 -2
  3. package/bin/cli.js +394 -0
  4. package/bin/commands/buildAndroid.js +200 -0
  5. package/bin/commands/buildIOS.js +237 -0
  6. package/bin/commands/create.js +406 -0
  7. package/bin/commands/createBundle.js +375 -0
  8. package/bin/commands/createComponent.js +115 -0
  9. package/bin/commands/createScreen.js +161 -0
  10. package/bin/commands/killServer.js +107 -0
  11. package/bin/commands/package.js +131 -0
  12. package/bin/commands/release.js +189 -0
  13. package/bin/commands/runBundle.js +62 -0
  14. package/bin/commands/runCloudflare.js +89 -0
  15. package/bin/commands/runNative.js +109 -0
  16. package/bin/commands/runServer.js +390 -0
  17. package/bin/ota/loader.js +361 -0
  18. package/bin/utils/bundleConfig.js +178 -0
  19. package/bin/utils/capacitor.js +137 -0
  20. package/bin/utils/colors.js +215 -0
  21. package/bin/utils/helpers.js +80 -0
  22. package/bin/utils/spinner.js +96 -0
  23. package/bin/utils/templates.js +1824 -0
  24. package/bin/utils/version.js +108 -0
  25. package/package.json +58 -4
  26. package/src/animations/AnimatedBox.js +607 -0
  27. package/src/animations/AnimatedText.js +105 -0
  28. package/src/animations/MatrixRain.js +220 -0
  29. package/src/animations/ParallaxBox.js +369 -0
  30. package/src/animations/animate.js +332 -0
  31. package/src/animations/index.js +25 -0
  32. package/src/app.js +41 -0
  33. package/src/assets/icon-1024-maskable.png +0 -0
  34. package/src/assets/icon-192-maskable.png +0 -0
  35. package/src/assets/icon-192.png +0 -0
  36. package/src/assets/icon-512-maskable.png +0 -0
  37. package/src/assets/icon-512.png +0 -0
  38. package/src/assets/logo.png +0 -0
  39. package/src/core/App.js +44 -0
  40. package/src/core/hmr-client.js +142 -0
  41. package/src/core/index.js +34 -0
  42. package/src/core/pwa.js +100 -0
  43. package/src/core/runApp.js +430 -0
  44. package/src/create-index.sh +237 -0
  45. package/src/fonts/MaterialIcons-Regular.woff2 +0 -0
  46. package/src/fonts/icons.css +23 -0
  47. package/src/index.d.ts +1930 -0
  48. package/src/index.js +288 -0
  49. package/src/navigations/AdaptiveScaffold.js +149 -0
  50. package/src/navigations/AppBar.js +331 -0
  51. package/src/navigations/BottomNavigation.js +298 -0
  52. package/src/navigations/CollapsibleSideBar.js +139 -0
  53. package/src/navigations/Drawer.js +333 -0
  54. package/src/navigations/DrawerItem.js +260 -0
  55. package/src/navigations/Router.js +475 -0
  56. package/src/navigations/Scaffold.js +537 -0
  57. package/src/navigations/Tabs.js +384 -0
  58. package/src/navigations/index.js +57 -0
  59. package/src/services/RamStore.js +213 -0
  60. package/src/services/Session.js +310 -0
  61. package/src/services/Storage.js +309 -0
  62. package/src/services/http.js +350 -0
  63. package/src/services/index.js +57 -0
  64. package/src/tools/animation.js +42 -0
  65. package/src/tools/array.js +95 -0
  66. package/src/tools/border.js +28 -0
  67. package/src/tools/clipboard.js +104 -0
  68. package/src/tools/color.js +329 -0
  69. package/src/tools/createList.js +215 -0
  70. package/src/tools/delay.js +55 -0
  71. package/src/tools/device.js +138 -0
  72. package/src/tools/dict.js +297 -0
  73. package/src/tools/dimensions.js +118 -0
  74. package/src/tools/filter.js +41 -0
  75. package/src/tools/flex.js +26 -0
  76. package/src/tools/gradient.js +34 -0
  77. package/src/tools/grid.js +57 -0
  78. package/src/tools/index.js +38 -0
  79. package/src/tools/mapList.js +107 -0
  80. package/src/tools/margin.js +93 -0
  81. package/src/tools/memo.js +60 -0
  82. package/src/tools/os.js +104 -0
  83. package/src/tools/padding.js +93 -0
  84. package/src/tools/print.js +69 -0
  85. package/src/tools/random.js +299 -0
  86. package/src/tools/ref.js +70 -0
  87. package/src/tools/rgba.js +4 -0
  88. package/src/tools/shadow.js +23 -0
  89. package/src/tools/string.js +85 -0
  90. package/src/tools/time.js +674 -0
  91. package/src/tools/transform.js +68 -0
  92. package/src/tools/transition.js +48 -0
  93. package/src/tools/useState.js +268 -0
  94. package/src/tools/uuid.js +42 -0
  95. package/src/utils/TextInputValidator.js +256 -0
  96. package/src/utils/composeUpdate.js +65 -0
  97. package/src/utils/getWidgetProps.js +35 -0
  98. package/src/utils/index.js +76 -0
  99. package/src/utils/markdownParser.js +368 -0
  100. package/src/utils/mediaTime.js +79 -0
  101. package/src/utils/navigation.js +263 -0
  102. package/src/utils/scriptInjector.js +73 -0
  103. package/src/utils/stackPosition.js +31 -0
  104. package/src/utils/stopWebRefresh.js +77 -0
  105. package/src/utils/styleInjector.js +38 -0
  106. package/src/utils/syntaxHighlight.js +339 -0
  107. package/src/utils/themes.js +347 -0
  108. package/src/utils/units.js +87 -0
  109. package/src/utils/visualEffects.js +169 -0
  110. package/src/widget-factory/addChildren.js +114 -0
  111. package/src/widget-factory/assignProps.js +256 -0
  112. package/src/widget-factory/createWidget.js +28 -0
  113. package/src/widget-factory/effects.js +132 -0
  114. package/src/widget-factory/index.js +7 -0
  115. package/src/widget-factory/lifecycle.js +210 -0
  116. package/src/widget-factory/makeParentable.js +89 -0
  117. package/src/widget-factory/pixTool.js +40 -0
  118. package/src/widget-factory/processProps.js +122 -0
  119. package/src/widget-factory/reactivity.js +98 -0
  120. package/src/widget-factory/remTool.js +34 -0
  121. package/src/widget-factory/stackPosition.js +87 -0
  122. package/src/widget-factory/stringTool.js +26 -0
  123. package/src/widget-factory/tools.js +249 -0
  124. package/src/widget-factory/translateProps.js +1049 -0
  125. package/src/widget-factory/warnings.js +284 -0
  126. package/src/widget-factory/widgetFactory.js +200 -0
  127. package/src/widgets/Accordion.js +562 -0
  128. package/src/widgets/AdMob.js +315 -0
  129. package/src/widgets/AdSense.js +268 -0
  130. package/src/widgets/AlertDialog.js +162 -0
  131. package/src/widgets/Audio.js +311 -0
  132. package/src/widgets/Avatar.js +210 -0
  133. package/src/widgets/Badge.js +189 -0
  134. package/src/widgets/BottomSheet.js +287 -0
  135. package/src/widgets/Button.js +247 -0
  136. package/src/widgets/Card.js +33 -0
  137. package/src/widgets/Carousel.js +301 -0
  138. package/src/widgets/Chart.js +632 -0
  139. package/src/widgets/Checkbox.js +106 -0
  140. package/src/widgets/Chip.js +153 -0
  141. package/src/widgets/CircularBar.js +352 -0
  142. package/src/widgets/CircularChart.js +549 -0
  143. package/src/widgets/CodeViewer.js +236 -0
  144. package/src/widgets/Column.js +29 -0
  145. package/src/widgets/Container.js +31 -0
  146. package/src/widgets/DataTable.js +257 -0
  147. package/src/widgets/Divider.js +93 -0
  148. package/src/widgets/DraggBox.js +115 -0
  149. package/src/widgets/Dropdown.js +505 -0
  150. package/src/widgets/DroppBox.js +180 -0
  151. package/src/widgets/FloatingActionButton.js +91 -0
  152. package/src/widgets/GridView.js +20 -0
  153. package/src/widgets/Icon.js +33 -0
  154. package/src/widgets/Image.js +15 -0
  155. package/src/widgets/Input.js +565 -0
  156. package/src/widgets/Inspector.js +254 -0
  157. package/src/widgets/InstallButton.js +110 -0
  158. package/src/widgets/ListTile.js +224 -0
  159. package/src/widgets/ListView.js +503 -0
  160. package/src/widgets/Markdown.js +1236 -0
  161. package/src/widgets/Modal.js +496 -0
  162. package/src/widgets/Pagination.js +195 -0
  163. package/src/widgets/ProgressBar.js +178 -0
  164. package/src/widgets/QRCode.js +467 -0
  165. package/src/widgets/Radio.js +132 -0
  166. package/src/widgets/Rating.js +261 -0
  167. package/src/widgets/Row.js +29 -0
  168. package/src/widgets/Skeleton.js +243 -0
  169. package/src/widgets/Slider.js +527 -0
  170. package/src/widgets/SnackBar.js +227 -0
  171. package/src/widgets/Stack.js +29 -0
  172. package/src/widgets/Stepper.js +296 -0
  173. package/src/widgets/Switch.js +102 -0
  174. package/src/widgets/Text.js +98 -0
  175. package/src/widgets/Tooltip.js +267 -0
  176. package/src/widgets/TreeView.js +370 -0
  177. package/src/widgets/Video.js +92 -0
  178. package/src/widgets/index.js +52 -0
@@ -0,0 +1,98 @@
1
+ // core/reactivity.js
2
+ import { REACTIVE_PROPS } from "./translateProps.js";
3
+
4
+ /**
5
+ * Tags where `width` and `height` are native IDL attributes with their own
6
+ * semantics (intrinsic size, aspect-ratio, etc.). Overriding them with a custom
7
+ * `defineProperty` accessor would break that native behaviour, so these props
8
+ * are NOT shadowed on these tags.
9
+ *
10
+ * @type {Set<string>}
11
+ */
12
+ const REPLACED_ELEMENT_TAGS = new Set([
13
+ "img",
14
+ "canvas",
15
+ "video",
16
+ "iframe",
17
+ "embed",
18
+ "object",
19
+ "source",
20
+ ]);
21
+
22
+ /**
23
+ * Props that must NEVER be shadowed with a custom accessor because the browser
24
+ * maintains live, user-controlled state for them. For example, shadowing `value`
25
+ * on an `<input>` would disconnect `widget.value` from what the user is actually
26
+ * typing.
27
+ *
28
+ * @type {Set<string>}
29
+ */
30
+ const NEVER_SHADOW = new Set(["value"]);
31
+
32
+ /**
33
+ * Installs reactive property accessors on a widget for every prop in
34
+ * `REACTIVE_PROPS`, excluding those guarded by `NEVER_SHADOW` and those that
35
+ * conflict with native IDL attributes on replaced elements.
36
+ *
37
+ * Each accessor follows this contract:
38
+ * - **getter** โ€“ returns the prop's current value from `_originalProps`.
39
+ * - **setter** โ€“ writes the new value to `_originalProps` and calls `updateFn`
40
+ * with a partial change object `{ [prop]: newValue }` only when the value
41
+ * actually changed (strict equality check prevents redundant updates).
42
+ *
43
+ * Additionally, for `<input>`, `<textarea>`, and `<select>` elements, syncs the
44
+ * DOM's own `value` back into `_originalProps` on every `input` and `change`
45
+ * event so that the stored props always reflect the live field content.
46
+ *
47
+ * @param {HTMLElement} widget - The widget to make reactive.
48
+ * @param {function(Object): void} updateFn - Callback invoked with the changed
49
+ * partial props whenever a reactive prop is set. Typically calls
50
+ * `widget.update(changedProps)`.
51
+ * @returns {HTMLElement} The same widget (for chaining).
52
+ */
53
+ export const makeReactive = (widget, updateFn) => {
54
+ const tag = widget.tagName ? widget.tagName.toLowerCase() : "";
55
+
56
+ REACTIVE_PROPS.forEach((prop) => {
57
+ if (NEVER_SHADOW.has(prop)) return;
58
+
59
+ if (
60
+ (prop === "width" || prop === "height") &&
61
+ REPLACED_ELEMENT_TAGS.has(tag)
62
+ ) {
63
+ return;
64
+ }
65
+
66
+ Object.defineProperty(widget, prop, {
67
+ get() {
68
+ return widget._originalProps ? widget._originalProps[prop] : undefined;
69
+ },
70
+ set(newValue) {
71
+ if (!widget._originalProps) return;
72
+ const current = widget._originalProps[prop];
73
+ if (current === newValue) return;
74
+
75
+ widget._originalProps[prop] = newValue;
76
+ updateFn({ [prop]: newValue });
77
+ },
78
+ enumerable: true,
79
+ configurable: true,
80
+ });
81
+ });
82
+
83
+ // For form elements, keep _originalProps in sync with the live DOM value so
84
+ // that getProps() always returns what the user has typed.
85
+ if (tag === "input" || tag === "textarea" || tag === "select") {
86
+ const syncValueFromDOM = () => {
87
+ if (widget._originalProps) {
88
+ widget._originalProps.value = widget.value;
89
+ }
90
+ };
91
+ widget.addEventListener("input", syncValueFromDOM);
92
+ widget.addEventListener("change", syncValueFromDOM);
93
+ }
94
+
95
+ return widget;
96
+ };
97
+
98
+ export default { makeReactive, REACTIVE_PROPS };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * REM TOOL - Only converts numbers to REM
3
+ */
4
+
5
+ /**
6
+ * Converts a number to REM
7
+ * @param {number} value - Number to convert
8
+ * @param {number} baseFontSize - Base root font size (default: 16)
9
+ * @returns {string} - Value in REM
10
+ */
11
+ export const toREM = (value, baseFontSize = 16) => {
12
+ if (typeof value !== "number") return value;
13
+ return `${value / baseFontSize}rem`;
14
+ };
15
+
16
+ /**
17
+ * Applies REM to a styles object
18
+ * @param {Object} styles - Styles with numbers
19
+ * @param {number} baseFontSize - Base root font size (default: 16)
20
+ * @returns {Object} - Styles with REM
21
+ */
22
+ export const applyREM = (styles, baseFontSize = 16) => {
23
+ const result = {};
24
+
25
+ for (const [key, value] of Object.entries(styles)) {
26
+ if (typeof value === "number") {
27
+ result[key] = toREM(value, baseFontSize);
28
+ } else {
29
+ result[key] = value;
30
+ }
31
+ }
32
+
33
+ return result;
34
+ };
@@ -0,0 +1,87 @@
1
+ // core/stackPosition.js
2
+ import { toREM } from "./remTool.js";
3
+
4
+ /**
5
+ * Applies positioning for Stack layout
6
+ * @param {HTMLElement} widget - The widget to position
7
+ * @param {Object} props - Widget props
8
+ * @returns {HTMLElement} The widget with position applied
9
+ *
10
+ * @example
11
+ * stackPosition(element, { position: 'stack', top: 10, left: 20 })
12
+ * // โ†’ element.style.position = 'absolute'
13
+ * // โ†’ element.style.top = '0.625rem'
14
+ * // โ†’ element.style.left = '1.25rem'
15
+ */
16
+ export const stackPosition = (widget, props) => {
17
+ // Numeric offsets follow the framework-wide rule: numbers are pixels on a
18
+ // 16px base, emitted as rem so they scale with the root font size.
19
+ const offset = (value) => (typeof value === "number" ? toREM(value) : value);
20
+
21
+ // Only apply if position is 'stack'
22
+ if (props.position !== "stack") {
23
+ return widget;
24
+ }
25
+
26
+ // Absolute positioning
27
+ widget.style.position = "absolute";
28
+
29
+ // Process each position prop
30
+ for (const [key, value] of Object.entries(props)) {
31
+ if (key === "position") continue;
32
+
33
+ switch (key) {
34
+ case "top":
35
+ widget.style.top = offset(value);
36
+ break;
37
+ case "right":
38
+ widget.style.right = offset(value);
39
+ break;
40
+ case "bottom":
41
+ widget.style.bottom = offset(value);
42
+ break;
43
+ case "left":
44
+ widget.style.left = offset(value);
45
+ break;
46
+ case "start":
47
+ widget.style.left = offset(value);
48
+ break;
49
+ case "end":
50
+ widget.style.right = offset(value);
51
+ break;
52
+ case "centerX":
53
+ widget.style.left = "50%";
54
+ widget.style.transform = "translateX(-50%)";
55
+ break;
56
+ case "centerY":
57
+ widget.style.top = "50%";
58
+ widget.style.transform = "translateY(-50%)";
59
+ break;
60
+ case "center":
61
+ widget.style.top = "50%";
62
+ widget.style.left = "50%";
63
+ widget.style.transform = "translate(-50%, -50%)";
64
+ break;
65
+ case "fullWidth":
66
+ widget.style.width = "100%";
67
+ widget.style.left = "0";
68
+ widget.style.right = "0";
69
+ break;
70
+ case "fullHeight":
71
+ widget.style.height = "100%";
72
+ widget.style.top = "0";
73
+ widget.style.bottom = "0";
74
+ break;
75
+ case "full":
76
+ widget.style.width = "100%";
77
+ widget.style.height = "100%";
78
+ widget.style.top = "0";
79
+ widget.style.left = "0";
80
+ break;
81
+ }
82
+ }
83
+
84
+ return widget;
85
+ };
86
+
87
+ export default stackPosition;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * STRING TOOL - Only keeps props that are strings
3
+ */
4
+
5
+ /**
6
+ * Filters and keeps only string values
7
+ * @param {Object} styles - Styles object
8
+ * @returns {Object} - Only string props
9
+ *
10
+ * @example
11
+ * keepStrings({ padding: 16, color: 'red', display: 'flex', zIndex: 10 })
12
+ * // โ†’ { color: 'red', display: 'flex' }
13
+ */
14
+ export const keepStrings = (styles) => {
15
+ const result = {};
16
+
17
+ for (const [key, value] of Object.entries(styles)) {
18
+ if (typeof value === "string") {
19
+ result[key] = value;
20
+ }
21
+ }
22
+
23
+ return result;
24
+ };
25
+
26
+ export default keepStrings;
@@ -0,0 +1,249 @@
1
+ // ============================================================
2
+ // ๐Ÿ“‹ READ: Get styles
3
+ // ============================================================
4
+
5
+ /**
6
+ * Reads one or all inline styles from a DOM element.
7
+ *
8
+ * @param {HTMLElement|null} el - The target element.
9
+ * @param {string} [prop] - CSS property name. When provided, returns only that
10
+ * property's value (or `null` when absent). When omitted, returns an object
11
+ * containing every non-empty inline style.
12
+ * @returns {string|Object|null} The property value, a styles object, or `null`
13
+ * when `el` is falsy or the property is not set.
14
+ */
15
+ export function getStyles(el, prop) {
16
+ if (!el) return null;
17
+ if (prop) return el.style[prop] || null;
18
+
19
+ const styles = {};
20
+ for (let i = 0; i < el.style.length; i++) {
21
+ const p = el.style[i];
22
+ const v = el.style[p];
23
+ if (v !== "") styles[p] = v;
24
+ }
25
+ return styles;
26
+ }
27
+
28
+ // ============================================================
29
+ // โž• CREATE / UPDATE: Assign styles
30
+ // ============================================================
31
+
32
+ /**
33
+ * Converts a raw prop value to a CSS-ready string or number.
34
+ *
35
+ * Conversion rules:
36
+ * - **Array** โ†’ space-separated string (e.g. `[12, 24]` โ†’ `"12px 24px"`).
37
+ * - **Number** on a unitless prop (flex, zIndex, opacity, etc.) โ†’ returned
38
+ * as-is without a suffix.
39
+ * - **Number** on any other prop โ†’ suffixed with `"px"`.
40
+ * - **String** โ†’ returned unchanged.
41
+ * - `undefined` / `null` โ†’ returned as `null` (caller should skip assignment).
42
+ *
43
+ * @param {string} key - The CSS property name (camelCase).
44
+ * @param {*} value - The raw value to convert.
45
+ * @returns {string|number|null} The CSS-ready value, or `null` to skip.
46
+ */
47
+ const toCSSValue = (key, value) => {
48
+ if (value === undefined || value === null) return null;
49
+
50
+ // Array โ†’ "12px 24px"
51
+ if (Array.isArray(value)) {
52
+ return value.map((v) => (typeof v === "number" ? `${v}px` : v)).join(" ");
53
+ }
54
+
55
+ // Number โ†’ apply unit or no unit
56
+ if (typeof value === "number") {
57
+ // Props that must NOT receive a unit suffix
58
+ const noUnitProps = new Set([
59
+ "flex",
60
+ "flexGrow",
61
+ "flexShrink",
62
+ "order",
63
+ "zIndex",
64
+ "opacity",
65
+ "fontWeight",
66
+ "lineHeight",
67
+ "scale",
68
+ "rotate",
69
+ "rotateX",
70
+ "rotateY",
71
+ "rotateZ",
72
+ ]);
73
+
74
+ if (noUnitProps.has(key)) {
75
+ return value; // No unit
76
+ }
77
+ return `${value}px`; // Add px
78
+ }
79
+
80
+ // String โ†’ keep as is
81
+ return value;
82
+ };
83
+
84
+ /**
85
+ * Applies one or more styles to a DOM element.
86
+ *
87
+ * Supports two call signatures:
88
+ * 1. `setStyles(el, propName, value)` โ€“ sets a single CSS property.
89
+ * 2. `setStyles(el, stylesObject)` โ€“ applies every key/value pair in the object.
90
+ *
91
+ * Values are converted via `toCSSValue` before assignment. Invalid CSS
92
+ * assignments (e.g. read-only properties) are silently ignored.
93
+ *
94
+ * @param {HTMLElement} el - The target element.
95
+ * @param {string|Object} prop - CSS property name (camelCase) or an object of
96
+ * propertyโ€“value pairs.
97
+ * @param {*} [value] - The value to assign. Required when `prop` is a string.
98
+ * @returns {HTMLElement} The element (for chaining).
99
+ */
100
+ export function setStyles(el, prop, value) {
101
+ // Validateste element
102
+ if (!el || !el.style) return el;
103
+
104
+ // Case 1: string (prop + value)
105
+ if (typeof prop === "string") {
106
+ const cssValue = toCSSValue(prop, value);
107
+ if (cssValue !== null) {
108
+ try {
109
+ el.style[prop] = cssValue;
110
+ } catch (e) {
111
+ // Silently ignore errors
112
+ }
113
+ }
114
+ return el;
115
+ }
116
+
117
+ // Case 2: styles object
118
+ if (typeof prop === "object" && prop !== null) {
119
+ for (const [key, val] of Object.entries(prop)) {
120
+ const cssValue = toCSSValue(key, val);
121
+ if (cssValue !== null) {
122
+ try {
123
+ el.style[key] = cssValue;
124
+ } catch (e) {
125
+ // Silently ignore errors
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ return el;
132
+ }
133
+
134
+ // ============================================================
135
+ // ๐Ÿ”„ TOGGLE: Toggle styles
136
+ // ============================================================
137
+
138
+ /**
139
+ * Toggles a CSS property between two values.
140
+ *
141
+ * If the property currently equals `val1` it is set to `val2`, and vice versa.
142
+ * Useful for toggling visibility, themes, or active states without external
143
+ * boolean tracking.
144
+ *
145
+ * @param {HTMLElement} el - The target element.
146
+ * @param {string} prop - CSS property name (camelCase).
147
+ * @param {*} val1 - First value (the one to switch away from when current).
148
+ * @param {*} val2 - Second value (the one to switch away from when current).
149
+ * @returns {HTMLElement} The element (for chaining).
150
+ */
151
+ export function updateStyle(el, prop, val1, val2) {
152
+ if (!el || !prop) return el;
153
+
154
+ const current = el.style[prop] || "";
155
+ const newValue = current === val1 ? val2 : val1;
156
+ const cssValue = toCSSValue(prop, newValue);
157
+
158
+ if (cssValue !== null) {
159
+ try {
160
+ el.style[prop] = cssValue;
161
+ } catch (e) {
162
+ // Silently ignore errors
163
+ }
164
+ }
165
+
166
+ return el;
167
+ }
168
+
169
+ // ============================================================
170
+ // ๐Ÿ—‘๏ธ DELETE: Remove styles
171
+ // ============================================================
172
+
173
+ /**
174
+ * Removes one or more inline styles from a DOM element by setting them to an
175
+ * empty string (which causes the browser to fall back to inherited / default
176
+ * values).
177
+ *
178
+ * - `string` โ†’ removes that single property.
179
+ * - `Array<string>` โ†’ removes every listed property.
180
+ * - `undefined` โ†’ removes ALL currently set inline styles.
181
+ *
182
+ * @param {HTMLElement} el - The target element.
183
+ * @param {string|string[]|undefined} [prop] - Property or properties to remove.
184
+ * Omit to remove all inline styles.
185
+ * @returns {HTMLElement} The element (for chaining).
186
+ */
187
+ export function removeStyles(el, prop) {
188
+ if (!el) return el;
189
+
190
+ if (typeof prop === "string") {
191
+ try {
192
+ el.style[prop] = "";
193
+ } catch (e) {}
194
+ } else if (Array.isArray(prop)) {
195
+ prop.forEach((p) => {
196
+ try {
197
+ el.style[p] = "";
198
+ } catch (e) {}
199
+ });
200
+ } else if (prop === undefined) {
201
+ const styles = getStyles(el);
202
+ Object.keys(styles).forEach((p) => {
203
+ try {
204
+ el.style[p] = "";
205
+ } catch (e) {}
206
+ });
207
+ }
208
+ return el;
209
+ }
210
+
211
+ // ============================================================
212
+ // ๐Ÿ” UTILITY: Check styles
213
+ // ============================================================
214
+
215
+ /**
216
+ * Checks whether a specific inline style is set on an element.
217
+ *
218
+ * @param {HTMLElement|null} el - The target element.
219
+ * @param {string} prop - CSS property name (camelCase).
220
+ * @returns {boolean} `true` if the property has a non-empty inline value.
221
+ */
222
+ export function hasStyle(el, prop) {
223
+ if (!el || !prop) return false;
224
+ return el.style[prop] !== "";
225
+ }
226
+
227
+ /**
228
+ * Logs all inline styles of an element to the console in a readable format.
229
+ * Useful for debugging style issues during development.
230
+ *
231
+ * @param {HTMLElement|null} el - The target element.
232
+ * @param {string} [label="Styles"] - Label prefix shown in the console output.
233
+ * @returns {Object|null} The styles object (same as `getStyles(el)`), or `null`
234
+ * when `el` is falsy.
235
+ */
236
+ export function logStyles(el, label = "Styles") {
237
+ if (!el) {
238
+ console.warn("โš ๏ธ Invalid element");
239
+ return null;
240
+ }
241
+ const styles = getStyles(el);
242
+ console.log(`๐Ÿ“‹ ${label}:`);
243
+ if (Object.keys(styles).length === 0) {
244
+ console.log(" (No inline styles)");
245
+ } else {
246
+ Object.entries(styles).forEach(([p, v]) => console.log(` ${p}: ${v}`));
247
+ }
248
+ return styles;
249
+ }