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,299 @@
1
+ /**
2
+ * @file random.js
3
+ * Faker-style random data generators for prototyping and testing.
4
+ *
5
+ * All generators are grouped under the `random` namespace object.
6
+ * Functions that accept no arguments choose sensible defaults so you can
7
+ * call them without configuration for quick mocks.
8
+ *
9
+ * Important: the `firstNames` and `lastNames` arrays are intentionally
10
+ * Spanish-language sample data — they are runtime content, not developer
11
+ * comments, and are left unchanged.
12
+ *
13
+ * @module tools/random
14
+ */
15
+
16
+ // ========== BASE DATA ==========
17
+ // Sample name pools used by firstName / lastName / fullName / email generators.
18
+ const firstNames = [
19
+ "Ana",
20
+ "Juan",
21
+ "María",
22
+ "Carlos",
23
+ "Laura",
24
+ "Pedro",
25
+ "Sofía",
26
+ "Luis",
27
+ "Elena",
28
+ "Miguel",
29
+ "Carmen",
30
+ "José",
31
+ "Isabel",
32
+ "Francisco",
33
+ "Marta",
34
+ "David",
35
+ "Lucía",
36
+ "Javier",
37
+ "Paula",
38
+ "Daniel",
39
+ ];
40
+
41
+ const lastNames = [
42
+ "García",
43
+ "Pérez",
44
+ "López",
45
+ "Martínez",
46
+ "Sánchez",
47
+ "Rodríguez",
48
+ "Fernández",
49
+ "González",
50
+ "Díaz",
51
+ "Moreno",
52
+ "Jiménez",
53
+ "Ruiz",
54
+ "Hernández",
55
+ "Álvarez",
56
+ "Romero",
57
+ "Navarro",
58
+ "Torres",
59
+ "Domínguez",
60
+ ];
61
+
62
+ const domains = [
63
+ "gmail.com",
64
+ "yahoo.com",
65
+ "hotmail.com",
66
+ "outlook.com",
67
+ "icloud.com",
68
+ "protonmail.com",
69
+ "example.com",
70
+ "mail.com",
71
+ ];
72
+
73
+ // Helper to pad numbers with leading zeros
74
+ const pad = (num, length = 2) => String(num).padStart(length, "0");
75
+
76
+ export const random = {
77
+ // ========== NUMBERS ==========
78
+ /**
79
+ * Generate a random number between min and max (inclusive)
80
+ * @param {number} min - Minimum value (default: 0)
81
+ * @param {number} max - Maximum value (default: 100)
82
+ * @returns {number}
83
+ */
84
+ number: (min = 0, max = 100) =>
85
+ Math.floor(Math.random() * (max - min + 1)) + min,
86
+
87
+ // ========== STRINGS ==========
88
+ /**
89
+ * Generate a random string of specified length
90
+ * @param {number} length - Length of the string (default: 8)
91
+ * @returns {string}
92
+ */
93
+ string: (length = 8) =>
94
+ Math.random()
95
+ .toString(36)
96
+ .substring(2, 2 + length),
97
+
98
+ // ========== NAMES ==========
99
+ /**
100
+ * Random first name
101
+ * @returns {string}
102
+ */
103
+ firstName: () => firstNames[Math.floor(Math.random() * firstNames.length)],
104
+
105
+ /**
106
+ * Random last name
107
+ * @returns {string}
108
+ */
109
+ lastName: () => lastNames[Math.floor(Math.random() * lastNames.length)],
110
+
111
+ /**
112
+ * Random full name
113
+ * @returns {string} Example: "Juan Pérez"
114
+ */
115
+ fullName: () => `${random.firstName()} ${random.lastName()}`,
116
+
117
+ /**
118
+ * Generate random email from name
119
+ * @param {string} name - Optional name (if not provided, generates one)
120
+ * @returns {string} Example: "juan.perez123@gmail.com"
121
+ */
122
+ email: (name = null) => {
123
+ const fullName = name || random.fullName();
124
+
125
+ let base = fullName
126
+ .toLowerCase()
127
+ .normalize("NFD")
128
+ .replace(/[\u0300-\u036f]/g, "")
129
+ .replace(/[^a-z]/g, ".");
130
+
131
+ base = base.replace(/\.+/g, ".");
132
+
133
+ const code = random.number(100, 999);
134
+ const domain = domains[Math.floor(Math.random() * domains.length)];
135
+
136
+ return `${base}${code}@${domain}`;
137
+ },
138
+
139
+ // ========== DATES & TIMES ==========
140
+ /**
141
+ * Generate a random date between two dates
142
+ * @param {Date|string} start - Start date (default: 1 year ago)
143
+ * @param {Date|string} end - End date (default: today)
144
+ * @returns {Date}
145
+ */
146
+ date: (start = null, end = null) => {
147
+ const startDate = start ? new Date(start) : new Date();
148
+ startDate.setFullYear(startDate.getFullYear() - 1);
149
+
150
+ const endDate = end ? new Date(end) : new Date();
151
+
152
+ const startTime = startDate.getTime();
153
+ const endTime = endDate.getTime();
154
+ const randomTime = startTime + Math.random() * (endTime - startTime);
155
+
156
+ return new Date(randomTime);
157
+ },
158
+
159
+ /**
160
+ * Generate a random date as ISO string
161
+ * @param {Date|string} start - Start date (default: 1 year ago)
162
+ * @param {Date|string} end - End date (default: today)
163
+ * @returns {string} ISO format: "2024-01-15"
164
+ */
165
+ dateString: (start = null, end = null) => {
166
+ const date = random.date(start, end);
167
+ return date.toISOString().split("T")[0];
168
+ },
169
+
170
+ /**
171
+ * Generate a random time (HH:MM:SS)
172
+ * @returns {string} Example: "14:32:18"
173
+ */
174
+ time: () => {
175
+ const hours = random.number(0, 23);
176
+ const minutes = random.number(0, 59);
177
+ const seconds = random.number(0, 59);
178
+ return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
179
+ },
180
+
181
+ /**
182
+ * Generate a random time with AM/PM format
183
+ * @returns {string} Example: "02:32:18 PM"
184
+ */
185
+ timeAmPm: () => {
186
+ let hours = random.number(0, 23);
187
+ const minutes = random.number(0, 59);
188
+ const seconds = random.number(0, 59);
189
+ const ampm = hours >= 12 ? "PM" : "AM";
190
+ hours = hours % 12 || 12;
191
+ return `${pad(hours)}:${pad(minutes)}:${pad(seconds)} ${ampm}`;
192
+ },
193
+
194
+ /**
195
+ * Generate a random datetime (ISO string)
196
+ * @returns {string} Example: "2024-01-15T14:32:18.123Z"
197
+ */
198
+ datetime: () => {
199
+ const date = random.date();
200
+ return date.toISOString();
201
+ },
202
+
203
+ /**
204
+ * Generate a random timestamp (Unix timestamp in milliseconds)
205
+ * @returns {number}
206
+ */
207
+ timestamp: () => random.date().getTime(),
208
+
209
+ /**
210
+ * Generate a random day of week
211
+ * @returns {string} Monday, Tuesday, etc.
212
+ */
213
+ dayOfWeek: () => {
214
+ const days = [
215
+ "Monday",
216
+ "Tuesday",
217
+ "Wednesday",
218
+ "Thursday",
219
+ "Friday",
220
+ "Saturday",
221
+ "Sunday",
222
+ ];
223
+ return random.choice(days);
224
+ },
225
+
226
+ /**
227
+ * Generate a random month
228
+ * @returns {string} January, February, etc.
229
+ */
230
+ month: () => {
231
+ const months = [
232
+ "January",
233
+ "February",
234
+ "March",
235
+ "April",
236
+ "May",
237
+ "June",
238
+ "July",
239
+ "August",
240
+ "September",
241
+ "October",
242
+ "November",
243
+ "December",
244
+ ];
245
+ return random.choice(months);
246
+ },
247
+
248
+ // ========== OTHER UTILITIES ==========
249
+ /**
250
+ * Random age between 18 and 65
251
+ * @returns {number}
252
+ */
253
+ age: () => random.number(18, 65),
254
+
255
+ /**
256
+ * Random boolean (true/false)
257
+ * @returns {boolean}
258
+ */
259
+ boolean: () => Math.random() > 0.5,
260
+
261
+ /**
262
+ * Pick a random element from an array
263
+ * @param {Array} array - The array to pick from
264
+ * @returns {*}
265
+ */
266
+ choice: (array) => array[Math.floor(Math.random() * array.length)],
267
+
268
+ /**
269
+ * Generate a random ID (8-10 characters)
270
+ * @returns {string}
271
+ */
272
+ id: () => Math.random().toString(36).substring(2, 10),
273
+
274
+ /**
275
+ * Generate a random hex color
276
+ * @returns {string} Example: "#3a7bd5"
277
+ */
278
+ hexColor: () => {
279
+ return (
280
+ "#" +
281
+ Math.floor(Math.random() * 16777215)
282
+ .toString(16)
283
+ .padStart(6, "0")
284
+ );
285
+ },
286
+
287
+ /**
288
+ * Generate a random RGB color
289
+ * @returns {string} Example: "rgb(58, 123, 213)"
290
+ */
291
+ rgbColor: () => {
292
+ const r = random.number(0, 255);
293
+ const g = random.number(0, 255);
294
+ const b = random.number(0, 255);
295
+ return `rgb(${r}, ${g}, ${b})`;
296
+ },
297
+ };
298
+
299
+ export default random;
@@ -0,0 +1,70 @@
1
+ // src/tools/ref.js
2
+ //
3
+ // Usage:
4
+ // const display = ref();
5
+ // Text({ ref: display });
6
+ // display.update({ text: 'Goodbye' });
7
+
8
+ /**
9
+ * Creates a ref function that can be attached to a widget via its `ref` prop.
10
+ *
11
+ * When the framework assigns a widget instance to the ref, the ref function:
12
+ * 1. Stores the widget instance internally.
13
+ * 2. Copies all of the widget's methods directly onto the ref function so they
14
+ * can be called as `display.someMethod()` without going through `.get()`.
15
+ * 3. Exposes non-function properties via `Object.defineProperty` getters/setters
16
+ * so reads and writes are forwarded to the live widget.
17
+ *
18
+ * @returns {Function} A ref function with an additional `.update(props)` method.
19
+ *
20
+ * @example
21
+ * const display = ref();
22
+ * Text({ ref: display }); // framework assigns the widget
23
+ * display.update({ text: 'Hello' }); // directly updates the widget prop
24
+ */
25
+ export const ref = () => {
26
+ let _widget = null;
27
+
28
+ /**
29
+ * Called by the framework with the widget instance when the widget is mounted.
30
+ * Also callable manually to point the ref at a different widget.
31
+ *
32
+ * @param {Object|null} widget - The widget instance to bind.
33
+ * @returns {Object|null} The same widget, for convenience.
34
+ */
35
+ const refFn = (widget) => {
36
+ _widget = widget;
37
+
38
+ // Mirror all methods and properties from the widget onto the ref function
39
+ // so callers can use `display.method()` directly
40
+ if (widget) {
41
+ Object.keys(widget).forEach((key) => {
42
+ if (typeof widget[key] === "function") {
43
+ refFn[key] = widget[key].bind(widget);
44
+ } else {
45
+ Object.defineProperty(refFn, key, {
46
+ get: () => widget[key],
47
+ set: (v) => {
48
+ widget[key] = v;
49
+ },
50
+ configurable: true,
51
+ });
52
+ }
53
+ });
54
+ }
55
+ return widget;
56
+ };
57
+
58
+ /**
59
+ * Calls the bound widget's `update` method with the given props, if the widget
60
+ * is mounted and supports updates.
61
+ *
62
+ * @param {Object} props - Props to pass to `widget.update(props)`.
63
+ * @returns {void}
64
+ */
65
+ refFn.update = (props) => {
66
+ if (_widget && _widget.update) _widget.update(props);
67
+ };
68
+
69
+ return refFn;
70
+ };
@@ -0,0 +1,4 @@
1
+ // RGBA.js - Así of simple
2
+ const rgba = (r, g, b, a = 1) => `rgba(${r}, ${g}, ${b}, ${a})`;
3
+
4
+ export default rgba;
@@ -0,0 +1,23 @@
1
+ // Shadow.js - Minimal box-shadow helper
2
+
3
+ /**
4
+ * Generate a CSS box-shadow string from individual components.
5
+ *
6
+ * Keeps callers from having to manually concatenate pixel values and color strings.
7
+ * Every parameter maps 1-to-1 to the CSS `box-shadow` shorthand property.
8
+ *
9
+ * @param {number} x - Horizontal offset in pixels (positive = right, negative = left)
10
+ * @param {number} y - Vertical offset in pixels (positive = down, negative = up)
11
+ * @param {number} blur - Blur radius in pixels (0 = sharp edge)
12
+ * @param {number} spread - Spread radius in pixels (positive = larger shadow, negative = smaller)
13
+ * @param {string} color - Shadow color (any valid CSS color value, e.g. "rgba(0,0,0,0.3)")
14
+ * @returns {string} CSS box-shadow value
15
+ *
16
+ * @example
17
+ * shadow(0, 4, 8, 0, "rgba(0,0,0,0.2)")
18
+ * // "0px 4px 8px 0px rgba(0,0,0,0.2)"
19
+ */
20
+ const shadow = (x, y, blur, spread, color) =>
21
+ `${x}px ${y}px ${blur}px ${spread}px ${color}`;
22
+
23
+ export default shadow;
@@ -0,0 +1,85 @@
1
+ // tools/string.js
2
+ export const startsWith = (str, prefix) => str.startsWith(prefix);
3
+ export const endsWith = (str, suffix) => str.endsWith(suffix);
4
+ export const includes = (str, substr) => str.includes(substr);
5
+ export const split = (str, separator) => str.split(separator);
6
+ export const join = (arr, separator) => arr.join(separator);
7
+ export const trim = (str) => str.trim();
8
+
9
+ /**
10
+ * Capitalize first letter of a string
11
+ * @param {string} str - Input string
12
+ * @returns {string} Capitalized string
13
+ * @example capitalize('hello') // "Hello"
14
+ */
15
+ export const capitalize = (str) => {
16
+ if (!str) return "";
17
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
18
+ };
19
+
20
+ /**
21
+ * Capitalize each word in a string
22
+ * @param {string} str - Input string
23
+ * @returns {string} String with each word capitalized
24
+ * @example capitalizeWords('hello world') // "Hello World"
25
+ */
26
+ export const capitalizeWords = (str) => {
27
+ if (!str) return "";
28
+ return str
29
+ .split(" ")
30
+ .map((word) => capitalize(word))
31
+ .join(" ");
32
+ };
33
+
34
+ /**
35
+ * Convert string to lowercase
36
+ * @param {string} str - Input string
37
+ * @returns {string} Lowercase string
38
+ */
39
+ export const lowerCase = (str) => {
40
+ if (!str) return "";
41
+ return str.toLowerCase();
42
+ };
43
+
44
+ /**
45
+ * Convert string to uppercase
46
+ * @param {string} str - Input string
47
+ * @returns {string} Uppercase string
48
+ */
49
+ export const upperCase = (str) => {
50
+ if (!str) return "";
51
+ return str.toUpperCase();
52
+ };
53
+
54
+ /**
55
+ * Reverse a string
56
+ * @param {string} str - Input string
57
+ * @returns {string} Reversed string
58
+ * @example reverse('hello') // "olleh"
59
+ */
60
+ export const reverseString = (str) => {
61
+ if (!str) return "";
62
+ return str.split("").reverse().join("");
63
+ };
64
+
65
+ /**
66
+ * Truncate string to max length
67
+ * @param {string} str - Input string
68
+ * @param {number} length - Max length
69
+ * @param {string} suffix - Suffix to add (default: '...')
70
+ * @returns {string} Truncated string
71
+ */
72
+ export const truncate = (str, length = 50, suffix = "...") => {
73
+ if (!str) return "";
74
+ if (str.length <= length) return str;
75
+ return str.slice(0, length) + suffix;
76
+ };
77
+
78
+ export default {
79
+ capitalize,
80
+ capitalizeWords,
81
+ lowerCase,
82
+ upperCase,
83
+ reverseString,
84
+ truncate,
85
+ };