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,247 @@
1
+ /**
2
+ * @file Button.js
3
+ * @description Button with size presets, variants, icons and gradient support.
4
+ */
5
+ import { WidgetFactory } from "../widget-factory/index.js";import { colors } from "../utils/themes.js";
6
+ import { Text } from "./Text.js";
7
+ import { Icon } from "./Icon.js";
8
+
9
+ // ============================================================
10
+ // CONFIGURATION
11
+ // ============================================================
12
+
13
+ const SIZE_PRESETS = {
14
+ small: { padding: [6, 12], fontSize: 12, gap: 6, iconSize: 16 },
15
+ medium: { padding: [10, 20], fontSize: 14, gap: 8, iconSize: 20 },
16
+ large: { padding: [14, 28], fontSize: 16, gap: 10, iconSize: 24 },
17
+ };
18
+
19
+ const SHADOW_LEVELS = {
20
+ 0: "none",
21
+ 1: "0 1px 3px rgba(0,0,0,0.12)",
22
+ 2: "0 3px 6px rgba(0,0,0,0.16)",
23
+ 3: "0 6px 12px rgba(0,0,0,0.2)",
24
+ 4: "0 10px 20px rgba(0,0,0,0.25)",
25
+ 5: "0 15px 30px rgba(0,0,0,0.3)",
26
+ };
27
+
28
+ // ============================================================
29
+ // HELPERS
30
+ // ============================================================
31
+
32
+ function normalizeSpacing(value, defaultPair) {
33
+ if (value === undefined) return defaultPair;
34
+ if (typeof value === "number") return [value, value * 2];
35
+ if (Array.isArray(value) && value.length === 2) return value;
36
+ return value;
37
+ }
38
+
39
+ function computeBackground(variant, disabled, bgColor, gradient) {
40
+ if (disabled) return colors.gray100;
41
+ if (variant === "filled") return gradient || bgColor || colors.primary;
42
+ return "transparent";
43
+ }
44
+
45
+ function computeTextColor(variant, disabled, color, bgColor) {
46
+ if (disabled) return colors.textDisabled;
47
+ if (variant === "filled") return color || "#fff";
48
+ return color || bgColor || colors.primary;
49
+ }
50
+
51
+ function computeBorder(variant, disabled, color, bgColor) {
52
+ if (disabled) return `1px solid ${colors.gray300}`;
53
+ if (variant === "outlined") {
54
+ const borderColor = color || bgColor || colors.primary;
55
+ return `2px solid ${borderColor}`;
56
+ }
57
+ if (variant === "text") return "none";
58
+ return `1px solid ${colors.border}`;
59
+ }
60
+
61
+ function createIcon(name, size, color) {
62
+ if (!name) return null;
63
+ return Icon({ name, size, color, display: "inline-flex" });
64
+ }
65
+
66
+ function resolveIconNames(props) {
67
+ const { icon, iconPosition, iconTop, iconLeft, iconRight, iconBottom } =
68
+ props;
69
+ return {
70
+ top: iconTop || (icon && iconPosition === "top" ? icon : null),
71
+ left: iconLeft || (icon && iconPosition === "left" ? icon : null),
72
+ right: iconRight || (icon && iconPosition === "right" ? icon : null),
73
+ bottom: iconBottom || (icon && iconPosition === "bottom" ? icon : null),
74
+ };
75
+ }
76
+
77
+ function buildIconElements(iconNames, size, color) {
78
+ return {
79
+ top: createIcon(iconNames.top, size, color),
80
+ left: createIcon(iconNames.left, size, color),
81
+ right: createIcon(iconNames.right, size, color),
82
+ bottom: createIcon(iconNames.bottom, size, color),
83
+ };
84
+ }
85
+
86
+ function buildButtonChildren(text, textColor, fontSize, gap, iconElements) {
87
+ const children = [];
88
+
89
+ if (iconElements.top) children.push(iconElements.top);
90
+
91
+ const middleRow = [];
92
+ if (iconElements.left) middleRow.push(iconElements.left);
93
+ if (text) {
94
+ middleRow.push(
95
+ Text({ text, color: textColor, size: fontSize, weight: "bold" }),
96
+ );
97
+ }
98
+ if (iconElements.right) middleRow.push(iconElements.right);
99
+
100
+ if (middleRow.length > 0) {
101
+ children.push(
102
+ WidgetFactory({
103
+ tag: "div",
104
+ display: "flex",
105
+ flexDirection: "row",
106
+ alignItems: "center",
107
+ justifyContent: "center",
108
+ gap,
109
+ child: middleRow,
110
+ }),
111
+ );
112
+ }
113
+
114
+ if (iconElements.bottom) children.push(iconElements.bottom);
115
+
116
+ if (children.length === 0 && iconElements.left) {
117
+ children.push(iconElements.left);
118
+ }
119
+
120
+ return children;
121
+ }
122
+
123
+ function applySpacingToProps(buttonProps, padding, margin) {
124
+ const normalizedPadding = normalizeSpacing(
125
+ padding,
126
+ SIZE_PRESETS.medium.padding,
127
+ );
128
+ const normalizedMargin = normalizeSpacing(margin, undefined);
129
+
130
+ if (Array.isArray(normalizedPadding)) {
131
+ buttonProps.paddingTop = normalizedPadding[0];
132
+ buttonProps.paddingBottom = normalizedPadding[0];
133
+ buttonProps.paddingLeft = normalizedPadding[1];
134
+ buttonProps.paddingRight = normalizedPadding[1];
135
+ } else if (normalizedPadding !== undefined) {
136
+ buttonProps.padding = normalizedPadding;
137
+ }
138
+
139
+ if (Array.isArray(normalizedMargin)) {
140
+ buttonProps.marginTop = normalizedMargin[0];
141
+ buttonProps.marginBottom = normalizedMargin[0];
142
+ buttonProps.marginLeft = normalizedMargin[1];
143
+ buttonProps.marginRight = normalizedMargin[1];
144
+ } else if (normalizedMargin !== undefined) {
145
+ buttonProps.margin = normalizedMargin;
146
+ }
147
+ }
148
+
149
+ // ============================================================
150
+ // MAIN COMPONENT
151
+ // ============================================================
152
+
153
+ export const Button = (props) => {
154
+ const {
155
+ text,
156
+ iconLeft,
157
+ iconRight,
158
+ iconTop,
159
+ iconBottom,
160
+ icon,
161
+ gradient,
162
+ padding,
163
+ margin,
164
+ onPress,
165
+ iconPosition = "left",
166
+ variant = "filled",
167
+ size = "medium",
168
+ borderRadius = 24,
169
+ elevation = 2,
170
+ disabled = false,
171
+ fullWidth = false,
172
+ bgColor = colors.surface,
173
+ color = colors.text,
174
+ ...rest
175
+ } = props;
176
+
177
+ const sizePreset = SIZE_PRESETS[size] || SIZE_PRESETS.medium;
178
+ const shadow = SHADOW_LEVELS[elevation] || SHADOW_LEVELS[0];
179
+
180
+ const background = computeBackground(variant, disabled, bgColor, gradient);
181
+ const textColor = computeTextColor(variant, disabled, color, bgColor);
182
+ const border = computeBorder(variant, disabled, color, bgColor);
183
+
184
+ const iconNames = resolveIconNames({
185
+ icon,
186
+ iconPosition,
187
+ iconTop,
188
+ iconLeft,
189
+ iconRight,
190
+ iconBottom,
191
+ });
192
+
193
+ const iconElements = buildIconElements(
194
+ iconNames,
195
+ sizePreset.iconSize,
196
+ textColor,
197
+ );
198
+
199
+ const children = buildButtonChildren(
200
+ text,
201
+ textColor,
202
+ sizePreset.fontSize,
203
+ sizePreset.gap,
204
+ iconElements,
205
+ );
206
+
207
+ const hasTopOrBottomIcon = !!(iconElements.top || iconElements.bottom);
208
+ const flexDirection = hasTopOrBottomIcon ? "column" : "row";
209
+
210
+ const buttonProps = {
211
+ tag: "button",
212
+ widgetName: "Button",
213
+ display: "inline-flex",
214
+ flexDirection,
215
+ alignItems: "center",
216
+ justifyContent: "center",
217
+ gap: sizePreset.gap,
218
+ borderRadius,
219
+ width: fullWidth ? "100%" : "auto",
220
+ backgroundColor: background,
221
+ border,
222
+ color: textColor,
223
+ boxShadow: shadow,
224
+ cursor: disabled ? "not-allowed" : "pointer",
225
+ opacity: disabled ? 0.6 : 1,
226
+ transition: "all 0.2s ease",
227
+ boxSizing: fullWidth ? "border-box" : undefined,
228
+ flexShrink: fullWidth ? undefined : 0,
229
+ onclick: disabled ? null : onPress,
230
+ child: children.length === 1 ? children[0] : children,
231
+ ...rest,
232
+ };
233
+
234
+ applySpacingToProps(buttonProps, padding, margin);
235
+
236
+ if (gradient) {
237
+ buttonProps.background = gradient;
238
+ delete buttonProps.backgroundColor;
239
+ }
240
+
241
+ const button = WidgetFactory(buttonProps);
242
+ button.setAttribute("type", "button");
243
+
244
+ return button;
245
+ };
246
+
247
+ export default Button;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @file Card.js
3
+ * @description Elevated surface card with optional border, padding and radius.
4
+ */
5
+ import { WidgetFactory } from "../widget-factory/index.js";
6
+ import { colors } from "../utils/themes.js";
7
+ import { border } from "../tools/index.js";
8
+
9
+ export const Card = (props = {}) => {
10
+ const {
11
+ elevation = 2,
12
+ padding = 16,
13
+ borderRadius = 12,
14
+ bgColor = colors.surface,
15
+ borderColor = colors.border,
16
+ borderWidth = 1,
17
+ borderStyle = "solid",
18
+ showBorder = true,
19
+ ...rest
20
+ } = props;
21
+
22
+ return WidgetFactory({
23
+ widgetName: "Card",
24
+ backgroundColor: bgColor,
25
+ borderRadius: borderRadius,
26
+ padding: padding,
27
+ elevation: elevation,
28
+ border: showBorder ? border(borderWidth, borderStyle, borderColor) : "none",
29
+ ...rest,
30
+ });
31
+ };
32
+
33
+ export default Card;
@@ -0,0 +1,301 @@
1
+ /**
2
+ * @file Carousel.js
3
+ * @description Swipeable carousel of slides with navigation controls.
4
+ */
5
+ import { WidgetFactory } from "../widget-factory/index.js";
6
+ import { Icon } from "./Icon.js";
7
+ import { colors } from "../utils/themes.js";
8
+
9
+ export const Carousel = (props) => {
10
+ const {
11
+ items = [],
12
+ autoPlay = false,
13
+ interval = 3000,
14
+ showArrows = true,
15
+ showDots = true,
16
+ infinite = true,
17
+ height = 300,
18
+ width = "100%",
19
+ borderRadius = 12,
20
+ onIndexChange,
21
+ onPress,
22
+
23
+ // Dot customization
24
+ dotColor = colors.gray300,
25
+ dotActiveColor = colors.primary,
26
+ dotSize = 8,
27
+ dotActiveSize = 20,
28
+
29
+ // Button customization
30
+ buttonBgColor = colors.surface,
31
+ buttonIconColor = colors.secondary,
32
+ buttonSize = 36,
33
+ buttonIconSize = 24,
34
+ buttonTop = "46%",
35
+
36
+ ...rest
37
+ } = props;
38
+
39
+ if (!items.length) return null;
40
+
41
+ let currentIndex = 0;
42
+ let autoPlayInterval = null;
43
+ let isTransitioning = false;
44
+ let trackRef = null;
45
+ let dotsContainerRef = null;
46
+
47
+ const updatePosition = (animate = true) => {
48
+ if (!trackRef) return;
49
+ trackRef.style.transition = animate ? "transform 0.3s ease-in-out" : "none";
50
+ trackRef.style.transform = `translateX(-${currentIndex * (100 / items.length)}%)`;
51
+ };
52
+
53
+ const updateDots = () => {
54
+ if (!dotsContainerRef) return;
55
+ const dots = dotsContainerRef.children;
56
+ for (let i = 0; i < dots.length; i++) {
57
+ const dot = dots[i];
58
+ if (i === currentIndex) {
59
+ dot.style.backgroundColor = dotActiveColor;
60
+ dot.style.width =
61
+ typeof dotActiveSize === "number"
62
+ ? `${dotActiveSize}px`
63
+ : dotActiveSize;
64
+ } else {
65
+ dot.style.backgroundColor = dotColor;
66
+ dot.style.width =
67
+ typeof dotSize === "number" ? `${dotSize}px` : dotSize;
68
+ }
69
+ }
70
+ };
71
+
72
+ const next = () => {
73
+ if (isTransitioning) return;
74
+ isTransitioning = true;
75
+
76
+ let newIndex = currentIndex + 1;
77
+ if (newIndex >= items.length) {
78
+ if (infinite) newIndex = 0;
79
+ else {
80
+ isTransitioning = false;
81
+ return;
82
+ }
83
+ }
84
+
85
+ currentIndex = newIndex;
86
+ updatePosition(true);
87
+ updateDots();
88
+
89
+ setTimeout(() => {
90
+ isTransitioning = false;
91
+ }, 350);
92
+ const cb = onIndexChange || onPress;
93
+ if (cb) cb(currentIndex);
94
+ };
95
+
96
+ const prev = () => {
97
+ if (isTransitioning) return;
98
+ isTransitioning = true;
99
+
100
+ let newIndex = currentIndex - 1;
101
+ if (newIndex < 0) {
102
+ if (infinite) newIndex = items.length - 1;
103
+ else {
104
+ isTransitioning = false;
105
+ return;
106
+ }
107
+ }
108
+
109
+ currentIndex = newIndex;
110
+ updatePosition(true);
111
+ updateDots();
112
+
113
+ setTimeout(() => {
114
+ isTransitioning = false;
115
+ }, 350);
116
+ const cb = onIndexChange || onPress;
117
+ if (cb) cb(currentIndex);
118
+ };
119
+
120
+ const goTo = (index) => {
121
+ if (isTransitioning) return;
122
+ if (index < 0 || index >= items.length) return;
123
+ isTransitioning = true;
124
+ currentIndex = index;
125
+ updatePosition(true);
126
+ updateDots();
127
+ setTimeout(() => {
128
+ isTransitioning = false;
129
+ }, 350);
130
+ const cb = onIndexChange || onPress;
131
+ if (cb) cb(currentIndex);
132
+ };
133
+
134
+ const startAutoPlay = () => {
135
+ if (!autoPlay || items.length <= 1) return;
136
+ if (autoPlayInterval) clearInterval(autoPlayInterval);
137
+ autoPlayInterval = setInterval(next, interval);
138
+ };
139
+
140
+ const stopAutoPlay = () => {
141
+ if (autoPlayInterval) {
142
+ clearInterval(autoPlayInterval);
143
+ autoPlayInterval = null;
144
+ }
145
+ };
146
+
147
+ const createArrow = (position, iconName, onClick) => {
148
+ const isLeft = position === "left";
149
+ return WidgetFactory({
150
+ position: "absolute",
151
+ left: isLeft ? "10px" : "auto",
152
+ right: isLeft ? "auto" : "10px",
153
+ top: buttonTop,
154
+ cursor: "pointer",
155
+ backgroundColor: buttonBgColor,
156
+ borderRadius: "50%",
157
+ width: typeof buttonSize === "number" ? `${buttonSize}px` : buttonSize,
158
+ height: typeof buttonSize === "number" ? `${buttonSize}px` : buttonSize,
159
+ display: "flex",
160
+ alignItems: "center",
161
+ justifyContent: "center",
162
+ zIndex: 10,
163
+ child: Icon({
164
+ name: iconName,
165
+ size: buttonIconSize,
166
+ color: buttonIconColor,
167
+ }),
168
+ onclick: onClick,
169
+ });
170
+ };
171
+
172
+ // Main container
173
+ const container = WidgetFactory({
174
+ widgetName: "Carousel",
175
+ position: "relative",
176
+ width: typeof width === "number" ? `${width}px` : width,
177
+ height: typeof height === "number" ? `${height}px` : height,
178
+ overflow: "hidden",
179
+ borderRadius:
180
+ typeof borderRadius === "number" ? `${borderRadius}px` : borderRadius,
181
+ ...rest,
182
+ });
183
+
184
+ // Track container
185
+ const track = WidgetFactory({
186
+ display: "flex",
187
+ transition: "transform 0.3s ease-in-out",
188
+ height: "100%",
189
+ width: `${items.length * 100}%`,
190
+ });
191
+ trackRef = track;
192
+
193
+ // Createste slides
194
+ items.forEach((item) => {
195
+ const slide = WidgetFactory({
196
+ width: `${100 / items.length}%`,
197
+ height: "100%",
198
+ flexShrink: 0,
199
+ display: "flex",
200
+ justifyContent: "center",
201
+ alignItems: "center",
202
+ overflow: "hidden",
203
+ });
204
+
205
+ if (item instanceof HTMLElement) {
206
+ slide.appendChild(item);
207
+ } else if (typeof item === "string") {
208
+ const img = document.createElement("img");
209
+ img.src = item;
210
+ img.style.width = "100%";
211
+ img.style.height = "100%";
212
+ img.style.objectFit = "cover";
213
+ img.onerror = () => {
214
+ console.error("Image not loaded:", item);
215
+ };
216
+ slide.appendChild(img);
217
+ } else if (item && typeof item === "object" && item.src) {
218
+ const img = document.createElement("img");
219
+ img.src = item.src;
220
+ img.alt = item.alt || "";
221
+ img.style.width = "100%";
222
+ img.style.height = "100%";
223
+ img.style.objectFit = "cover";
224
+ slide.appendChild(img);
225
+ }
226
+
227
+ track.appendChild(slide);
228
+ });
229
+
230
+ container.appendChild(track);
231
+
232
+ // Navigation arrows
233
+ if (showArrows && items.length > 1) {
234
+ const prevArrow = createArrow("left", "chevron_left", prev);
235
+ const nextArrow = createArrow("right", "chevron_right", next);
236
+ container.appendChild(prevArrow);
237
+ container.appendChild(nextArrow);
238
+ }
239
+
240
+ // Dots indicators
241
+ if (showDots && items.length > 1) {
242
+ const dotsContainer = WidgetFactory({
243
+ position: "absolute",
244
+ bottom: "15px",
245
+ left: "50%",
246
+ transform: "translateX(-50%)",
247
+ display: "flex",
248
+ gap: "8px",
249
+ zIndex: 10,
250
+ });
251
+ dotsContainerRef = dotsContainer;
252
+
253
+ items.forEach((_, index) => {
254
+ const dot = WidgetFactory({
255
+ width:
256
+ index === currentIndex
257
+ ? typeof dotActiveSize === "number"
258
+ ? `${dotActiveSize}px`
259
+ : dotActiveSize
260
+ : typeof dotSize === "number"
261
+ ? `${dotSize}px`
262
+ : dotSize,
263
+ height: typeof dotSize === "number" ? `${dotSize}px` : dotSize,
264
+ borderRadius: "4px",
265
+ backgroundColor: index === currentIndex ? dotActiveColor : dotColor,
266
+ cursor: "pointer",
267
+ transition: "all 0.2s",
268
+ onclick: () => goTo(index),
269
+ });
270
+ dotsContainer.appendChild(dot);
271
+ });
272
+
273
+ container.appendChild(dotsContainer);
274
+ }
275
+
276
+ // Initialize position
277
+ updatePosition(false);
278
+ updateDots();
279
+
280
+ // Autoplay setup
281
+ if (autoPlay) {
282
+ startAutoPlay();
283
+ container.addEventListener("mouseenter", stopAutoPlay);
284
+ container.addEventListener("mouseleave", startAutoPlay);
285
+ }
286
+
287
+ // Public methods
288
+ container.next = next;
289
+ container.prev = prev;
290
+ container.goTo = goTo;
291
+ container.getCurrentIndex = () => currentIndex;
292
+
293
+ // Cleanup
294
+ container.onUnmount(() => {
295
+ stopAutoPlay();
296
+ });
297
+
298
+ return container;
299
+ };
300
+
301
+ export default Carousel;