aport-tools 4.5.2 → 4.6.0

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 (38) hide show
  1. package/package.json +13 -28
  2. package/src/cards/Card.tsx +129 -0
  3. package/src/cards/index.ts +1 -0
  4. package/src/components/Button.tsx +180 -0
  5. package/src/fonts/Text.tsx +137 -0
  6. package/{dist/fonts/index.d.ts → src/fonts/index.ts} +1 -0
  7. package/src/forms/ErrorList.tsx +47 -0
  8. package/src/forms/FORMDOC.md +87 -0
  9. package/{dist/forms/Form.d.ts → src/forms/Form.tsx} +2 -0
  10. package/src/forms/FormContext.tsx +248 -0
  11. package/src/forms/Input.tsx +174 -0
  12. package/src/forms/InputAttach.tsx +184 -0
  13. package/src/forms/InputCheck.tsx +169 -0
  14. package/src/forms/InputList.tsx +304 -0
  15. package/src/forms/Label.tsx +26 -0
  16. package/src/forms/Stepper.tsx +289 -0
  17. package/src/forms/TextArea.tsx +91 -0
  18. package/{dist/forms/index.d.ts → src/forms/index.ts} +4 -2
  19. package/src/index.ts +6 -0
  20. package/dist/cards/Card.d.ts +0 -57
  21. package/dist/cards/index.d.ts +0 -1
  22. package/dist/components/Button.d.ts +0 -52
  23. package/dist/fonts/Text.d.ts +0 -64
  24. package/dist/forms/ErrorList.d.ts +0 -6
  25. package/dist/forms/FormContext.d.ts +0 -132
  26. package/dist/forms/Input.d.ts +0 -43
  27. package/dist/forms/InputAttach.d.ts +0 -16
  28. package/dist/forms/InputCheck.d.ts +0 -19
  29. package/dist/forms/InputList.d.ts +0 -93
  30. package/dist/forms/Label.d.ts +0 -7
  31. package/dist/forms/Stepper.d.ts +0 -54
  32. package/dist/forms/TextArea.d.ts +0 -13
  33. package/dist/index.d.ts +0 -4
  34. package/dist/index.esm.js +0 -1493
  35. package/dist/index.esm.js.map +0 -1
  36. package/dist/index.js +0 -1526
  37. package/dist/index.js.map +0 -1
  38. /package/{dist/buttons/index.d.ts → src/buttons/index.ts} +0 -0
package/dist/index.esm.js DELETED
@@ -1,1493 +0,0 @@
1
- /*! aport-tools v4.5.2 | ISC */
2
- import React, { useContext, useState, createContext, useRef, useEffect, useMemo, useCallback } from 'react';
3
- import { StyleSheet, Text as Text$1, Animated, View, TouchableOpacity, Image, TextInput, Modal, Pressable, FlatList, Keyboard, Platform, Alert, ActivityIndicator } from 'react-native';
4
- import { ThemeContext } from 'aport-themes';
5
- import * as ImagePicker from 'expo-image-picker';
6
-
7
- /******************************************************************************
8
- Copyright (c) Microsoft Corporation.
9
-
10
- Permission to use, copy, modify, and/or distribute this software for any
11
- purpose with or without fee is hereby granted.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
- PERFORMANCE OF THIS SOFTWARE.
20
- ***************************************************************************** */
21
- /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
22
-
23
-
24
- var __assign = function() {
25
- __assign = Object.assign || function __assign(t) {
26
- for (var s, i = 1, n = arguments.length; i < n; i++) {
27
- s = arguments[i];
28
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
29
- }
30
- return t;
31
- };
32
- return __assign.apply(this, arguments);
33
- };
34
-
35
- function __rest(s, e) {
36
- var t = {};
37
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
38
- t[p] = s[p];
39
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
40
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
41
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
42
- t[p[i]] = s[p[i]];
43
- }
44
- return t;
45
- }
46
-
47
- function __awaiter(thisArg, _arguments, P, generator) {
48
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
49
- return new (P || (P = Promise))(function (resolve, reject) {
50
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
51
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
52
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
53
- step((generator = generator.apply(thisArg, _arguments || [])).next());
54
- });
55
- }
56
-
57
- function __generator(thisArg, body) {
58
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
59
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
60
- function verb(n) { return function (v) { return step([n, v]); }; }
61
- function step(op) {
62
- if (f) throw new TypeError("Generator is already executing.");
63
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
64
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
65
- if (y = 0, t) op = [op[0] & 2, t.value];
66
- switch (op[0]) {
67
- case 0: case 1: t = op; break;
68
- case 4: _.label++; return { value: op[1], done: false };
69
- case 5: _.label++; y = op[1]; op = [0]; continue;
70
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
71
- default:
72
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
73
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
74
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
75
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
76
- if (t[2]) _.ops.pop();
77
- _.trys.pop(); continue;
78
- }
79
- op = body.call(thisArg, _);
80
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
81
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
82
- }
83
- }
84
-
85
- function __spreadArray(to, from, pack) {
86
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
87
- if (ar || !(i in from)) {
88
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
89
- ar[i] = from[i];
90
- }
91
- }
92
- return to.concat(ar || Array.prototype.slice.call(from));
93
- }
94
-
95
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
96
- var e = new Error(message);
97
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
98
- };
99
-
100
- // src/fonts/Text.tsx
101
- /**
102
- * A dynamic Text component that supports HTML-like formatting.
103
- * Integrates with the Theme system for consistent styling.
104
- *
105
- * @param children - The content to be displayed inside the Text component.
106
- * @param size - Size of the text. Defaults to 'medium'.
107
- * @param b - If true, applies bold styling.
108
- * @param i - If true, applies italic styling.
109
- * @param type - Type of Text component. Defaults to 'text'.
110
- * @param typeFont - Type of Font component. Defaults to 'body'.
111
- * @param u - If true, applies underline styling.
112
- * @param align - Paragraph alignment. Defaults to 'left'.
113
- * @param h - Header level. Accepts 0 (none), 1, 2, or 3. Defaults to 0.
114
- * @param style - Additional styles to apply.
115
- */
116
- var Text = function Text(_a) {
117
- var _b;
118
- var children = _a.children,
119
- _c = _a.size,
120
- size = _c === void 0 ? 14 : _c,
121
- _d = _a.b,
122
- b = _d === void 0 ? false : _d,
123
- _e = _a.i,
124
- i = _e === void 0 ? false : _e,
125
- _f = _a.u,
126
- u = _f === void 0 ? false : _f,
127
- _g = _a.align,
128
- align = _g === void 0 ? 'left' : _g,
129
- _h = _a.type,
130
- type = _h === void 0 ? 'text' : _h,
131
- _j = _a.typeFont,
132
- typeFont = _j === void 0 ? 'body' : _j,
133
- _k = _a.h,
134
- h = _k === void 0 ? 0 : _k,
135
- style = _a.style;
136
- var theme = useContext(ThemeContext).theme;
137
- var colors = theme.colors,
138
- fonts = theme.fonts;
139
- // Determine font family and size based on 'typeFont'
140
- var fontSettings = fonts[typeFont] || fonts.body;
141
- var fontFamily = fontSettings.fontFamily;
142
- var fontSize = fontSettings.fontSize || size;
143
- // Calculate header size based on 'h' prop
144
- if (h === 1) fontSize = 32;else if (h === 2) fontSize = 24;else if (h === 3) fontSize = 18;
145
- // Define font weight based on bold prop
146
- var fontWeight = b ? '700' : fontSettings.fontWeight || '400';
147
- // Define font style based on italic prop
148
- var fontStyle = i ? 'italic' : 'normal';
149
- // Define text decoration based on underline prop
150
- var textDecorationLine = u ? 'underline' : 'none';
151
- // Define text alignment
152
- var textAlign = align;
153
- // Map the 'type' prop to the correct color from the theme
154
- var textColor = ((_b = colors[type]) === null || _b === void 0 ? void 0 : _b.hex) || colors.text.hex;
155
- // Combine all styles
156
- var textStyles = {
157
- fontSize: fontSize,
158
- fontWeight: fontWeight,
159
- fontFamily: fontFamily,
160
- fontStyle: fontStyle,
161
- textDecorationLine: textDecorationLine,
162
- textAlign: textAlign,
163
- color: textColor
164
- };
165
- return /*#__PURE__*/React.createElement(Text$1, {
166
- style: [textStyles, style]
167
- }, children);
168
- };
169
- StyleSheet.create({
170
- // Define any default styles if needed
171
- });
172
-
173
- var Stepper = function Stepper(_a) {
174
- var steps = _a.steps,
175
- currentStep = _a.currentStep,
176
- _b = _a.presseable,
177
- presseable = _b === void 0 ? false : _b,
178
- onPress = _a.onPress,
179
- _c = _a.stepStyle,
180
- stepStyle = _c === void 0 ? "circular" : _c,
181
- totalSteps = _a.totalSteps,
182
- _d = _a.stepType,
183
- stepType = _d === void 0 ? "number" : _d,
184
- icon = _a.icon;
185
- var progressAnim = React.useRef(new Animated.Value(0)).current;
186
- var theme = useContext(ThemeContext).theme;
187
- var colors = theme.colors;
188
- var _e = useFormContext(),
189
- formValues = _e.formValues,
190
- handleFormSubmit = _e.handleFormSubmit;
191
- var _f = useState(false),
192
- errorBack = _f[0],
193
- seterrorBack = _f[1];
194
- var handleStepPress = function handleStepPress(stepIndex) {
195
- return __awaiter(void 0, void 0, void 0, function () {
196
- var targetStep, errors;
197
- return __generator(this, function (_a) {
198
- switch (_a.label) {
199
- case 0:
200
- if (!presseable || stepIndex === currentStep) return [2 /*return*/];
201
- targetStep = stepIndex > currentStep ? currentStep + 1 : currentStep - 1;
202
- if (!(targetStep > currentStep)) return [3 /*break*/, 2];
203
- return [4 /*yield*/, handleFormSubmit(formValues)];
204
- case 1:
205
- errors = _a.sent();
206
- if (Object.keys(errors).length > 0) {
207
- console.log("Validation failed at step ".concat(currentStep, ". Cannot proceed to step ").concat(targetStep, "."));
208
- seterrorBack(true);
209
- return [2 /*return*/]; // Stop if current step has errors
210
- }
211
- _a.label = 2;
212
- case 2:
213
- // Update step
214
- seterrorBack(false);
215
- onPress === null || onPress === void 0 ? void 0 : onPress(targetStep);
216
- return [2 /*return*/];
217
- }
218
- });
219
- });
220
- };
221
- React.useEffect(function () {
222
- Animated.timing(progressAnim, {
223
- toValue: currentStep,
224
- duration: 500,
225
- useNativeDriver: false
226
- }).start();
227
- }, [currentStep]);
228
- React.useEffect(function () {
229
- if (stepType === "icon") {
230
- if (!icon) {
231
- console.error("Stepper: `icon` is required when stepType is 'icon'.");
232
- } else if (Array.isArray(icon) && icon.length !== totalSteps) {
233
- console.error("Stepper: Number of icons (".concat(icon.length, ") must match totalSteps (").concat(totalSteps, ")."));
234
- }
235
- }
236
- }, [stepType, icon, totalSteps]);
237
- var getSeparatorWidth = function getSeparatorWidth(index) {
238
- if (currentStep > index && currentStep < index + 1) {
239
- // Return the fractional percentage for odd steps
240
- return "".concat(((currentStep - index) * 100).toFixed(0), "%");
241
- }
242
- return currentStep > index ? "100%" : "0%";
243
- };
244
- var renderStepContent = function renderStepContent(index) {
245
- switch (stepType) {
246
- case "icon":
247
- if (Array.isArray(icon)) {
248
- var stepIcon = icon[index];
249
- if (typeof stepIcon === "string") {
250
- return /*#__PURE__*/React.createElement(Image, {
251
- source: {
252
- uri: stepIcon
253
- },
254
- style: {
255
- width: 24,
256
- height: 24
257
- },
258
- resizeMode: "contain"
259
- });
260
- } else {
261
- console.error("Invalid icon value for step ".concat(index, ". Expected a string URI."));
262
- return null;
263
- }
264
- }
265
- if (typeof icon === "string") {
266
- return /*#__PURE__*/React.createElement(Image, {
267
- source: {
268
- uri: icon
269
- },
270
- style: {
271
- width: 24,
272
- height: 24
273
- },
274
- resizeMode: "contain"
275
- });
276
- }
277
- console.error("Icon prop must be a string or an array of strings.");
278
- return null;
279
- case "empty":
280
- return null;
281
- case "number":
282
- default:
283
- return /*#__PURE__*/React.createElement(Text, {
284
- b: true,
285
- typeFont: "primary",
286
- style: [currentStep >= index ? {
287
- color: colors.textButton.hex
288
- } : {
289
- color: colors.text.hex
290
- }]
291
- }, index + 1);
292
- }
293
- };
294
- return /*#__PURE__*/React.createElement(View, {
295
- style: styles$9.container
296
- }, Array.from({
297
- length: totalSteps
298
- }, function (_, index) {
299
- return /*#__PURE__*/React.createElement(React.Fragment, {
300
- key: index
301
- }, /*#__PURE__*/React.createElement(TouchableOpacity, {
302
- style: [styles$9.stepContainer, presseable && {
303
- cursor: "pointer"
304
- }],
305
- disabled: !presseable,
306
- onPress: function onPress() {
307
- return handleStepPress(index);
308
- }
309
- }, /*#__PURE__*/React.createElement(View, {
310
- style: [styles$9.step, stepStyle === "square" && styles$9.squareStep, {
311
- backgroundColor: currentStep >= index ? !errorBack ? colors.primary.hex : colors.error.hex : colors.body.hex
312
- }]
313
- }, renderStepContent(index)), steps && /*#__PURE__*/React.createElement(Text, {
314
- style: styles$9.stepText
315
- }, steps[index])), index < totalSteps - 1 && (/*#__PURE__*/React.createElement(View, {
316
- style: styles$9.separatorContainer
317
- }, /*#__PURE__*/React.createElement(View, {
318
- style: styles$9.separatorBackground
319
- }), /*#__PURE__*/React.createElement(Animated.View, {
320
- style: [styles$9.separatorProgress, {
321
- width: getSeparatorWidth(index),
322
- backgroundColor: colors.primary.hex
323
- }]
324
- }))));
325
- }));
326
- };
327
- var styles$9 = StyleSheet.create({
328
- container: {
329
- flexDirection: "row",
330
- alignItems: "center",
331
- justifyContent: "space-between",
332
- marginBottom: 16
333
- },
334
- stepContainer: {
335
- alignItems: "center",
336
- flex: 1
337
- },
338
- step: {
339
- width: 30,
340
- height: 30,
341
- borderRadius: 15,
342
- // Default to circular
343
- alignItems: "center",
344
- justifyContent: "center",
345
- marginBottom: 4
346
- },
347
- squareStep: {
348
- borderRadius: 5 // Square shape
349
- },
350
- stepLabel: {
351
- color: "#ffffff",
352
- fontWeight: "bold"
353
- },
354
- stepText: {
355
- fontSize: 12,
356
- textAlign: "center",
357
- marginTop: 4
358
- },
359
- separatorContainer: {
360
- flex: 1,
361
- height: 4,
362
- marginHorizontal: 8,
363
- position: "relative"
364
- },
365
- separatorBackground: {
366
- position: "absolute",
367
- width: "100%",
368
- height: "100%",
369
- backgroundColor: "#aaaaaa",
370
- borderRadius: 2
371
- },
372
- separatorProgress: {
373
- position: "absolute",
374
- height: "100%",
375
- borderRadius: 2
376
- }
377
- });
378
-
379
- // src/forms/FormContext.tsx
380
- // Utility to use `setFormValue` globally
381
- var setFormValueGlobal = function setFormValueGlobal(name, value, firstValue) {
382
- {
383
- console.warn("setFormValueGlobal was called before the Form was rendered.");
384
- }
385
- };
386
- var FormContext = /*#__PURE__*/createContext(undefined);
387
- var useFormContext = function useFormContext() {
388
- var context = useContext(FormContext);
389
- if (!context) {
390
- throw new Error("useFormContext must be used within a Form");
391
- }
392
- return context;
393
- };
394
- var Form = function Form(_a) {
395
- var children = _a.children,
396
- onSubmit = _a.onSubmit,
397
- stepper = _a.stepper;
398
- var _b = useState({}),
399
- formValues = _b[0],
400
- setFormValues = _b[1];
401
- var _c = useState({}),
402
- errors = _c[0],
403
- setErrors = _c[1];
404
- var _d = useState({}),
405
- firstValues = _d[0],
406
- setFirstValues = _d[1]; // Track firstValues
407
- var setFormValue = function setFormValue(name, value, firstValue) {
408
- // Update formValues with the latest value
409
- setFormValues(function (prev) {
410
- var _a;
411
- return __assign(__assign({}, prev), (_a = {}, _a[name] = value, _a));
412
- });
413
- // If firstValue exists and is not empty, set it in firstValues
414
- if (firstValue !== undefined && firstValue !== null && firstValue !== "") {
415
- setFirstValues(function (prev) {
416
- var _a;
417
- return __assign(__assign({}, prev), (_a = {}, _a[name] = firstValue, _a));
418
- });
419
- }
420
- };
421
- var handleSubmit = function handleSubmit() {
422
- return __awaiter(void 0, void 0, void 0, function () {
423
- var modifiedValues, validationErrors;
424
- return __generator(this, function (_a) {
425
- switch (_a.label) {
426
- case 0:
427
- modifiedValues = Object.keys(formValues).reduce(function (result, key) {
428
- var hasFirstValue = key in firstValues;
429
- var isModified = hasFirstValue && formValues[key] !== firstValues[key];
430
- var isNewValue = !hasFirstValue;
431
- // If the field was modified or is a new value, include it in the modified values
432
- if (isModified || isNewValue) {
433
- result[key] = formValues[key];
434
- } else {
435
- // If there were no changes, use the firstValue
436
- if (hasFirstValue && firstValues[key] !== undefined) {
437
- result[key] = firstValues[key];
438
- }
439
- }
440
- return result;
441
- }, {});
442
- return [4 /*yield*/, onSubmit(modifiedValues)];
443
- case 1:
444
- validationErrors = _a.sent();
445
- // Set the validation errors in state
446
- setErrors(validationErrors);
447
- // Prevent submission if there are any errors
448
- if (Object.keys(validationErrors).length > 0) {
449
- return [2 /*return*/]; // Prevent submission
450
- }
451
- return [2 /*return*/];
452
- }
453
- });
454
- });
455
- };
456
- var handleFormSubmit = function handleFormSubmit(formValues) {
457
- return __awaiter(void 0, void 0, void 0, function () {
458
- var validationErrors;
459
- return __generator(this, function (_a) {
460
- switch (_a.label) {
461
- case 0:
462
- return [4 /*yield*/, onSubmit(formValues)];
463
- case 1:
464
- validationErrors = _a.sent();
465
- setErrors(validationErrors);
466
- return [2 /*return*/, validationErrors];
467
- }
468
- });
469
- });
470
- };
471
- return /*#__PURE__*/React.createElement(FormContext.Provider, {
472
- value: {
473
- formValues: formValues,
474
- setFormValue: setFormValue,
475
- errors: errors,
476
- setErrors: setErrors,
477
- handleSubmit: handleSubmit,
478
- handleFormSubmit: handleFormSubmit
479
- }
480
- }, stepper && (/*#__PURE__*/React.createElement(Stepper, {
481
- steps: stepper.steps,
482
- currentStep: stepper.currentStep,
483
- presseable: stepper.presseable,
484
- onPress: stepper.onPress,
485
- totalSteps: stepper.totalSteps,
486
- stepType: stepper.stepType,
487
- icon: stepper.icon,
488
- stepStyle: stepper.stepStyle
489
- })), children);
490
- };
491
-
492
- // src/forms/ErrorList.tsx
493
- var ErrorList = function ErrorList(_a) {
494
- var errors = _a.errors;
495
- var theme = useContext(ThemeContext).theme;
496
- var colors = theme.colors;
497
- return /*#__PURE__*/React.createElement(View, {
498
- style: styles$8.container
499
- }, errors.map(function (error, index) {
500
- return /*#__PURE__*/React.createElement(View, {
501
- key: index,
502
- style: styles$8.errorItem
503
- }, /*#__PURE__*/React.createElement(Text, {
504
- style: [styles$8.bullet, {
505
- color: colors.error.hex
506
- }]
507
- }, "\u2022"), /*#__PURE__*/React.createElement(Text, {
508
- style: [styles$8.errorText, {
509
- color: colors.error.hex
510
- }]
511
- }, error));
512
- }));
513
- };
514
- var styles$8 = StyleSheet.create({
515
- container: {
516
- marginTop: 4
517
- },
518
- errorItem: {
519
- flexDirection: 'row',
520
- alignItems: 'flex-start',
521
- marginBottom: 2
522
- },
523
- bullet: {
524
- marginRight: 4,
525
- fontSize: 12
526
- },
527
- errorText: {
528
- flex: 1,
529
- fontSize: 12
530
- }
531
- });
532
-
533
- // src/forms/Input.tsx
534
- /**
535
- * Input component that supports labels, error messages, and integrates with the Theme system.
536
- *
537
- * @param {InputProps} props - Props passed to the component.
538
- * @returns {JSX.Element} The rendered Input component.
539
- *
540
- * @example
541
- * <Input
542
- * name="email"
543
- * label="Email"
544
- * keyboardType="email-address"
545
- * inputType="id"
546
- * />
547
- */
548
- var Input = function Input(_a) {
549
- var name = _a.name,
550
- label = _a.label,
551
- inputType = _a.inputType,
552
- firstValue = _a.firstValue,
553
- _b = _a.editable,
554
- editable = _b === void 0 ? true : _b,
555
- style = _a.style,
556
- rest = __rest(_a, ["name", "label", "inputType", "firstValue", "editable", "style"]);
557
- var _c = useFormContext(),
558
- formValues = _c.formValues,
559
- setFormValue = _c.setFormValue,
560
- formErrors = _c.errors;
561
- var theme = useContext(ThemeContext).theme;
562
- var colors = theme.colors;
563
- var _d = useState(""),
564
- internalValue = _d[0],
565
- setInternalValue = _d[1];
566
- var isFirstRender = useRef(true); // Track the first render
567
- // Initialize the internal value when `firstValue` changes or on first render
568
- useEffect(function () {
569
- if (isFirstRender.current) {
570
- isFirstRender.current = false;
571
- if (firstValue !== undefined) {
572
- firstValue = firstValue.toString();
573
- setInternalValue(firstValue);
574
- setFormValue(name, firstValue, firstValue); // Pass firstValue here
575
- } else {
576
- setInternalValue(formValues[name] || "");
577
- }
578
- }
579
- }, [firstValue]);
580
- /**
581
- * Handles text changes in the input field, applying formatting based on the inputType.
582
- *
583
- * @param {string} text - The current text input by the user.
584
- */
585
- var handleChange = function handleChange(text) {
586
- var formattedText = text;
587
- // Apply different formatting based on inputType
588
- switch (inputType) {
589
- case "phone":
590
- // Remove all non-digit characters
591
- formattedText = text.replace(/\D/g, "");
592
- // Insert hyphens to format as xxx-xxx-xxxx
593
- if (formattedText.length > 3 && formattedText.length <= 6) {
594
- formattedText = "".concat(formattedText.slice(0, 3), "-").concat(formattedText.slice(3));
595
- } else if (formattedText.length > 6) {
596
- formattedText = "".concat(formattedText.slice(0, 3), "-").concat(formattedText.slice(3, 6), "-").concat(formattedText.slice(6, 10));
597
- }
598
- break;
599
- case "id":
600
- case "uppercase":
601
- // Convert all input to uppercase
602
- formattedText = text.toUpperCase();
603
- break;
604
- case "numeric":
605
- // Allow only numeric input
606
- formattedText = text.replace(/\D/g, "");
607
- break;
608
- }
609
- setInternalValue(formattedText);
610
- setFormValue(name, formattedText);
611
- };
612
- return /*#__PURE__*/React.createElement(View, {
613
- style: styles$7.container
614
- }, /*#__PURE__*/React.createElement(Text, {
615
- style: [styles$7.label, {
616
- color: colors.text.hex
617
- }]
618
- }, label), /*#__PURE__*/React.createElement(TextInput, __assign({
619
- style: [styles$7.input, {
620
- backgroundColor: colors.body.hex,
621
- borderColor: formErrors[name] ? colors.error.hex : "#CCC",
622
- color: colors.text.hex
623
- }, style],
624
- value: internalValue,
625
- onChangeText: handleChange,
626
- placeholder: label,
627
- editable: editable,
628
- placeholderTextColor: colors.placeHolder.hex
629
- }, rest)), formErrors[name] && formErrors[name].length > 0 && (/*#__PURE__*/React.createElement(ErrorList, {
630
- errors: formErrors[name]
631
- })));
632
- };
633
- var styles$7 = StyleSheet.create({
634
- container: {
635
- marginBottom: 16
636
- },
637
- label: {
638
- marginBottom: 4,
639
- fontSize: 14
640
- },
641
- input: {
642
- height: 40,
643
- borderWidth: 1,
644
- borderRadius: 4,
645
- paddingHorizontal: 8
646
- }
647
- });
648
-
649
- // src/forms/TextArea.tsx
650
- var TextArea = function TextArea(_a) {
651
- var name = _a.name,
652
- label = _a.label;
653
- _a.errors;
654
- var firstValue = _a.firstValue,
655
- _b = _a.editable,
656
- editable = _b === void 0 ? true : _b,
657
- style = _a.style,
658
- rest = __rest(_a, ["name", "label", "errors", "firstValue", "editable", "style"]);
659
- var _c = useFormContext(),
660
- formValues = _c.formValues,
661
- setFormValue = _c.setFormValue,
662
- formErrors = _c.errors;
663
- var theme = useContext(ThemeContext).theme;
664
- var colors = theme.colors;
665
- var _d = useState(""),
666
- internalValue = _d[0],
667
- setInternalValue = _d[1];
668
- var isFirstRender = useRef(true); // Track the first render
669
- // Initialize the internal value when `firstValue` changes or on first render
670
- useEffect(function () {
671
- if (isFirstRender.current) {
672
- isFirstRender.current = false;
673
- if (firstValue !== undefined) {
674
- setInternalValue(firstValue);
675
- setFormValue(name, firstValue, firstValue); // Pass firstValue here
676
- } else {
677
- setInternalValue(formValues[name] || "");
678
- }
679
- }
680
- }, [firstValue]);
681
- var handleChange = function handleChange(text) {
682
- setInternalValue(text);
683
- setFormValue(name, text);
684
- };
685
- return /*#__PURE__*/React.createElement(View, {
686
- style: styles$6.container
687
- }, /*#__PURE__*/React.createElement(Text, {
688
- style: [styles$6.label, {
689
- color: colors.text.hex
690
- }]
691
- }, label), /*#__PURE__*/React.createElement(TextInput, __assign({
692
- style: [styles$6.textArea, style, {
693
- backgroundColor: colors.body.hex,
694
- color: colors.text.hex,
695
- borderColor: formErrors[name] ? colors.error.hex : "#CCC"
696
- }],
697
- value: internalValue,
698
- onChangeText: handleChange,
699
- placeholder: label,
700
- placeholderTextColor: colors.placeHolder.hex,
701
- multiline: true,
702
- editable: editable,
703
- numberOfLines: 4,
704
- textAlignVertical: "top"
705
- }, rest)), formErrors[name] && formErrors[name].length > 0 && (/*#__PURE__*/React.createElement(ErrorList, {
706
- errors: formErrors[name]
707
- })));
708
- };
709
- var styles$6 = StyleSheet.create({
710
- container: {
711
- marginBottom: 16
712
- },
713
- label: {
714
- marginBottom: 4
715
- },
716
- textArea: {
717
- height: 100,
718
- borderWidth: 1,
719
- borderRadius: 4,
720
- paddingHorizontal: 8,
721
- paddingVertical: 8
722
- }
723
- });
724
-
725
- // src/forms/Label.tsx
726
- var Label = function Label(_a) {
727
- var text = _a.text,
728
- style = _a.style;
729
- var theme = useContext(ThemeContext).theme;
730
- var colors = theme.colors;
731
- return /*#__PURE__*/React.createElement(Text, {
732
- style: [styles$5.label, style, {
733
- color: colors.text.hex
734
- }]
735
- }, text);
736
- };
737
- var styles$5 = StyleSheet.create({
738
- label: {
739
- marginBottom: 4,
740
- fontWeight: '500'
741
- }
742
- });
743
-
744
- /**
745
- * InputList component - A custom dropdown list component for React Native with multi-selection support,
746
- * customizable styling, sorting, and configurable close behavior on selection or scrolling.
747
- *
748
- * @param {string} placeholder - Placeholder text for the input.
749
- * @param {object} style - Custom styles for the component.
750
- * @param {Option[]} options - Array of options to display in the dropdown.
751
- * @param {boolean} multi - Enables multi-selection mode.
752
- * @param {boolean} disabled - Disables the dropdown input.
753
- * @param {keyof Option} sortBy - Key to sort options by (e.g., 'id').
754
- * @param {boolean} separator - If true, adds a separator line between options.
755
- * @param {boolean} closeOnScroll - Closes the dropdown if the user scrolls the list.
756
- * @param {boolean} closeOnSelect - Closes the dropdown on selection in single-select mode.
757
- * @param {number} maxSelection - Maximum number of items selectable in multi-select mode.
758
- */
759
- var InputList = function InputList(_a) {
760
- var name = _a.name,
761
- _b = _a.placeholder,
762
- placeholder = _b === void 0 ? "Choose value/s" : _b,
763
- style = _a.style,
764
- options = _a.options,
765
- _c = _a.multi,
766
- multi = _c === void 0 ? false : _c,
767
- _d = _a.disabled,
768
- disabled = _d === void 0 ? false : _d,
769
- sortBy = _a.sortBy,
770
- _e = _a.firstValue,
771
- firstValue = _e === void 0 ? [] : _e,
772
- _f = _a.separator,
773
- separator = _f === void 0 ? false : _f,
774
- _g = _a.closeOnScroll,
775
- closeOnScroll = _g === void 0 ? false : _g,
776
- _h = _a.closeOnSelect,
777
- closeOnSelect = _h === void 0 ? true : _h,
778
- maxSelection = _a.maxSelection,
779
- onChange = _a.onChange;
780
- var _j = useFormContext();
781
- _j.formValues;
782
- var setFormValue = _j.setFormValue,
783
- formErrors = _j.errors;
784
- var _k = useState(false),
785
- isDropdownVisible = _k[0],
786
- setIsDropdownVisible = _k[1];
787
- // Memoize sorted options for performance
788
- var sortedOptions = useMemo(function () {
789
- return sortBy ? __spreadArray([], options, true).sort(function (a, b) {
790
- return a[sortBy] > b[sortBy] ? 1 : -1;
791
- }) : options;
792
- }, [options, sortBy]);
793
- var theme = useContext(ThemeContext).theme;
794
- var colors = theme.colors;
795
- // Initialize selected options based on firstValue
796
- // Filter initial selections from options based on `firstValue`
797
- var initialSelections = useMemo(function () {
798
- return options.filter(function (opt) {
799
- return firstValue.includes(opt.value);
800
- });
801
- }, [options, firstValue]);
802
- // State for selected options
803
- var _l = useState(multi ? initialSelections : initialSelections[0] || null),
804
- selectedOptions = _l[0],
805
- setSelectedOptions = _l[1];
806
- // Update form value when firstValue changes
807
- useEffect(function () {
808
- if (!firstValue || firstValue.length === 0) return;
809
- var matchedSelections = options.filter(function (opt) {
810
- return firstValue.includes(opt.value);
811
- });
812
- if (multi) {
813
- setSelectedOptions(matchedSelections);
814
- setFormValue(name, matchedSelections, matchedSelections);
815
- } else {
816
- var singleValue = matchedSelections[0] || null;
817
- setSelectedOptions(singleValue);
818
- setFormValue(name, singleValue, singleValue);
819
- }
820
- }, [firstValue, multi]);
821
- // Handle option selection
822
- var handleSelectOption = function handleSelectOption(option) {
823
- var updatedSelections;
824
- if (multi) {
825
- var selectedArray = Array.isArray(selectedOptions) ? selectedOptions : [];
826
- var alreadySelected = selectedArray.some(function (opt) {
827
- return opt.id === option.id;
828
- });
829
- updatedSelections = alreadySelected ? selectedArray.filter(function (opt) {
830
- return opt.id !== option.id;
831
- }) : __spreadArray(__spreadArray([], selectedArray, true), [option], false);
832
- if (!alreadySelected && maxSelection && updatedSelections.length >= maxSelection) {
833
- setIsDropdownVisible(false);
834
- }
835
- setFormValue(name, updatedSelections);
836
- } else {
837
- updatedSelections = option;
838
- setFormValue(name, option);
839
- if (closeOnSelect) setIsDropdownVisible(false);
840
- }
841
- setSelectedOptions(updatedSelections);
842
- if (onChange) onChange(updatedSelections);
843
- };
844
- var isItemDisabled = function isItemDisabled(option) {
845
- if (!multi) return false; // Disable check only applies for multi-select
846
- // Ensure selectedOptions is treated as an array
847
- var selectedArray = Array.isArray(selectedOptions) ? selectedOptions : [];
848
- return maxSelection && selectedArray.length >= maxSelection && !selectedArray.some(function (opt) {
849
- return opt.id === option.id;
850
- });
851
- };
852
- var renderSelectedText = function renderSelectedText() {
853
- if (multi) {
854
- // Ensure selectedOptions is treated as an array
855
- var selectedArray = Array.isArray(selectedOptions) ? selectedOptions : [];
856
- return selectedArray.map(function (opt) {
857
- return opt.label;
858
- }).join(', ') || placeholder;
859
- }
860
- return (selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.label) || placeholder;
861
- };
862
- var toggleDropdown = function toggleDropdown() {
863
- if (!disabled) {
864
- setIsDropdownVisible(!isDropdownVisible);
865
- if (!isDropdownVisible) Keyboard.dismiss();
866
- }
867
- };
868
- var handleCloseDropdown = useCallback(function () {
869
- if (isDropdownVisible) setIsDropdownVisible(false);
870
- }, [isDropdownVisible]);
871
- /**
872
- * Renders selected options as a comma-separated string or the placeholder if none selected.
873
- * @returns {string} - The display text for selected options or placeholder.
874
- */
875
- // Conditionally render item as disabled if max selection reached and item is unselected
876
- return /*#__PURE__*/React.createElement(View, {
877
- style: [styles$4.container, style]
878
- }, /*#__PURE__*/React.createElement(Text$1, {
879
- style: {
880
- color: colors.text.hex,
881
- marginBottom: 4
882
- }
883
- }, name), /*#__PURE__*/React.createElement(TouchableOpacity, {
884
- style: [styles$4.inputContainer, {
885
- borderColor: formErrors[name] ? colors.error.hex : "#CCC"
886
- }],
887
- onPress: toggleDropdown,
888
- disabled: disabled
889
- }, /*#__PURE__*/React.createElement(Text$1, {
890
- style: {
891
- color: colors.text.hex
892
- }
893
- }, renderSelectedText())), formErrors[name] && formErrors[name].length > 0 && (/*#__PURE__*/React.createElement(ErrorList, {
894
- errors: formErrors[name]
895
- })), /*#__PURE__*/React.createElement(Modal, {
896
- visible: isDropdownVisible,
897
- transparent: true,
898
- animationType: "fade"
899
- }, /*#__PURE__*/React.createElement(Pressable, {
900
- style: styles$4.overlay,
901
- onPress: handleCloseDropdown
902
- }), /*#__PURE__*/React.createElement(View, {
903
- style: [styles$4.dropdownContainer, {
904
- backgroundColor: colors.body.hex
905
- }]
906
- }, /*#__PURE__*/React.createElement(FlatList, {
907
- data: sortedOptions,
908
- keyExtractor: function keyExtractor(item) {
909
- return item.id.toString();
910
- },
911
- renderItem: function renderItem(_a) {
912
- var item = _a.item;
913
- var isSelected = multi ? Array.isArray(selectedOptions) && selectedOptions.some(function (opt) {
914
- return opt.id === item.id;
915
- }) : selectedOptions && 'id' in selectedOptions && selectedOptions.id === item.id;
916
- var isDisabled = isItemDisabled(item);
917
- return /*#__PURE__*/React.createElement(TouchableOpacity, {
918
- onPress: function onPress() {
919
- return handleSelectOption(item);
920
- },
921
- style: [styles$4.optionItem, isSelected ? {
922
- backgroundColor: colors.primary.hex
923
- } : {}, isDisabled ? {
924
- backgroundColor: colors.placeHolder.hex
925
- } : {}],
926
- disabled: !!isDisabled
927
- }, /*#__PURE__*/React.createElement(Text$1, {
928
- style: [isSelected ? {
929
- color: colors.body.hex
930
- } : {
931
- color: colors.text.hex
932
- }, isDisabled ? styles$4.disabledText : {}]
933
- }, item.label));
934
- },
935
- ItemSeparatorComponent: function ItemSeparatorComponent() {
936
- return separator ? /*#__PURE__*/React.createElement(View, {
937
- style: styles$4.separator
938
- }) : null;
939
- },
940
- scrollEnabled: !closeOnScroll
941
- }))));
942
- };
943
- var styles$4 = StyleSheet.create({
944
- container: {
945
- marginVertical: 10
946
- },
947
- inputContainer: {
948
- padding: 12,
949
- borderWidth: 1,
950
- borderRadius: 5
951
- },
952
- dropdownContainer: {
953
- position: 'absolute',
954
- top: '30%',
955
- // Center the dropdown vertically
956
- alignSelf: 'center',
957
- width: '90%',
958
- backgroundColor: '#fff',
959
- borderRadius: 8,
960
- elevation: 5,
961
- paddingVertical: 10
962
- },
963
- optionItem: {
964
- padding: 12
965
- },
966
- disabledText: {
967
- color: '#999'
968
- },
969
- separator: {
970
- height: 1,
971
- backgroundColor: '#ddd',
972
- marginHorizontal: 8
973
- },
974
- overlay: {
975
- flex: 1,
976
- backgroundColor: 'rgba(0,0,0,0.3)'
977
- }
978
- });
979
-
980
- // src/cards/Card.tsx
981
- /**
982
- * Card component that adapts its styles based on the current theme.
983
- * Supports dynamic styling, shadows, and press animations.
984
- *
985
- * @param children - The content to be displayed inside the Card.
986
- * @param style - Additional styles to apply to the Card.
987
- * @param onPress - Function to execute when the Card is pressed.
988
- * @param pressable - Determines if the Card is pressable. Defaults to false.
989
- * @param borderRadius - Border radius of the Card. Defaults to 12.
990
- * @param elevation - Elevation for Android shadow. Overrides default.
991
- * @param shadowProps - Custom shadow properties for iOS. Overrides defaults.
992
- */
993
- var Card = function Card(_a) {
994
- var children = _a.children,
995
- style = _a.style,
996
- onPress = _a.onPress,
997
- _b = _a.pressable,
998
- pressable = _b === void 0 ? false : _b,
999
- _c = _a.borderRadius,
1000
- borderRadius = _c === void 0 ? 12 : _c,
1001
- _d = _a.elevation,
1002
- elevation = _d === void 0 ? 4 : _d,
1003
- _e = _a.shadowProps,
1004
- shadowProps = _e === void 0 ? {} : _e;
1005
- var theme = useContext(ThemeContext).theme;
1006
- var colors = theme.colors;
1007
- // Animation state for pressable effect
1008
- // Default shadow styles (improved platform-specific handling)
1009
- var defaultShadow = Platform.select({
1010
- ios: {
1011
- shadowColor: (shadowProps === null || shadowProps === void 0 ? void 0 : shadowProps.shadowColor) || colors.text.hex,
1012
- // Defaulting to theme text color
1013
- shadowOffset: (shadowProps === null || shadowProps === void 0 ? void 0 : shadowProps.shadowOffset) || {
1014
- width: 0,
1015
- height: 2
1016
- },
1017
- shadowOpacity: (shadowProps === null || shadowProps === void 0 ? void 0 : shadowProps.shadowOpacity) || 0.1,
1018
- shadowRadius: (shadowProps === null || shadowProps === void 0 ? void 0 : shadowProps.shadowRadius) || 4
1019
- },
1020
- android: {
1021
- elevation: elevation // Only applies to Android
1022
- }
1023
- });
1024
- var cardStyles = [styles$3.container, {
1025
- borderRadius: borderRadius,
1026
- backgroundColor: colors.background.hex
1027
- }, defaultShadow,
1028
- // Dynamic shadows based on platform
1029
- style // External styles
1030
- ];
1031
- return pressable ? (/*#__PURE__*/React.createElement(TouchableOpacity, {
1032
- activeOpacity: 0.8,
1033
- onPress: onPress,
1034
- style: cardStyles
1035
- }, children)) : (/*#__PURE__*/React.createElement(View, {
1036
- style: cardStyles
1037
- }, children));
1038
- };
1039
- var styles$3 = StyleSheet.create({
1040
- container: {
1041
- padding: 16,
1042
- borderRadius: 12
1043
- // Shadows handled dynamically with platform logic
1044
- }
1045
- });
1046
-
1047
- var InputCheck = function InputCheck(_a) {
1048
- var name = _a.name,
1049
- options = _a.options,
1050
- _b = _a.multi,
1051
- multi = _b === void 0 ? false : _b,
1052
- max = _a.max,
1053
- _c = _a.rowAmount,
1054
- rowAmount = _c === void 0 ? 3 : _c,
1055
- firstValue = _a.firstValue,
1056
- _d = _a.iconPosition,
1057
- iconPosition = _d === void 0 ? "row" : _d,
1058
- _e = _a.disabled,
1059
- disabled = _e === void 0 ? false : _e;
1060
- var _f = useFormContext();
1061
- _f.formValues;
1062
- var setFormValue = _f.setFormValue,
1063
- formErrors = _f.errors;
1064
- var _g = useState([]),
1065
- selectedValues = _g[0],
1066
- setSelectedValues = _g[1];
1067
- var theme = useContext(ThemeContext).theme;
1068
- var colors = theme.colors;
1069
- var isFirstRender = useRef(true);
1070
- // Initialize selectedValues on first render if firstValue is provided
1071
- useEffect(function () {
1072
- if (isFirstRender.current && firstValue) {
1073
- var initialSelectedValues = options.filter(function (option) {
1074
- return firstValue.some(function (fv) {
1075
- return fv.value === option.value;
1076
- });
1077
- });
1078
- setSelectedValues(initialSelectedValues);
1079
- setFormValue(name, initialSelectedValues, initialSelectedValues); // Update form context
1080
- isFirstRender.current = false; // Prevent subsequent updates
1081
- }
1082
- }, [firstValue, name, options, setFormValue]);
1083
- var handleSelect = function handleSelect(id, value) {
1084
- if (disabled) return;
1085
- var updatedSelection;
1086
- if (multi) {
1087
- var alreadySelected = selectedValues.find(function (item) {
1088
- return item.id === id;
1089
- });
1090
- if (alreadySelected) {
1091
- updatedSelection = selectedValues.filter(function (item) {
1092
- return item.id !== id;
1093
- });
1094
- } else {
1095
- if (max && selectedValues.length >= max) return; // Prevent selection beyond max
1096
- updatedSelection = __spreadArray(__spreadArray([], selectedValues, true), [{
1097
- id: id,
1098
- value: value
1099
- }], false);
1100
- }
1101
- } else {
1102
- updatedSelection = [{
1103
- id: id,
1104
- value: value
1105
- }];
1106
- }
1107
- setSelectedValues(updatedSelection);
1108
- setFormValue(name, updatedSelection);
1109
- };
1110
- var renderItem = function renderItem(_a) {
1111
- var item = _a.item;
1112
- var isSelected = selectedValues.some(function (selected) {
1113
- return selected.id === item.id.toString();
1114
- });
1115
- return /*#__PURE__*/React.createElement(Card, {
1116
- pressable: true,
1117
- onPress: function onPress() {
1118
- return handleSelect(item.id.toString(), item.value);
1119
- },
1120
- style: [styles$2.card, isSelected && {
1121
- backgroundColor: colors.primary.hex
1122
- },
1123
- // Replace with colors.primary.hex if available
1124
- disabled && styles$2.cardDisabled]
1125
- }, item.icon && (/*#__PURE__*/React.createElement(Image, {
1126
- source: {
1127
- uri: item.icon
1128
- },
1129
- style: [styles$2.icon, iconPosition === "column" && styles$2.iconColumn]
1130
- })), item.label && (/*#__PURE__*/React.createElement(Text, {
1131
- style: [styles$2.label, {
1132
- color: isSelected ? colors.textButton.hex : colors.text.hex
1133
- }]
1134
- }, item.label)));
1135
- };
1136
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
1137
- style: styles$2.title
1138
- }, name), /*#__PURE__*/React.createElement(FlatList, {
1139
- data: options,
1140
- renderItem: renderItem,
1141
- keyExtractor: function keyExtractor(item) {
1142
- return item.id;
1143
- },
1144
- numColumns: rowAmount,
1145
- columnWrapperStyle: rowAmount > 1 ? styles$2.row : undefined,
1146
- scrollEnabled: false
1147
- }), formErrors[name] && formErrors[name].length > 0 && (/*#__PURE__*/React.createElement(ErrorList, {
1148
- errors: formErrors[name]
1149
- })));
1150
- };
1151
- var styles$2 = StyleSheet.create({
1152
- card: {
1153
- flex: 1,
1154
- margin: 5,
1155
- padding: 10,
1156
- borderWidth: 1,
1157
- borderColor: "#ccc",
1158
- borderRadius: 8,
1159
- alignItems: "center",
1160
- justifyContent: "center"
1161
- },
1162
- title: {
1163
- marginBottom: 4,
1164
- fontSize: 14
1165
- },
1166
- cardDisabled: {
1167
- opacity: 0.5
1168
- },
1169
- icon: {
1170
- width: 40,
1171
- height: 40,
1172
- marginBottom: 5
1173
- },
1174
- iconColumn: {
1175
- marginBottom: 10
1176
- },
1177
- label: {
1178
- fontSize: 14,
1179
- textAlign: "center"
1180
- },
1181
- row: {
1182
- justifyContent: "space-between"
1183
- }
1184
- });
1185
-
1186
- // src/components/InputAttach.tsx
1187
- var InputAttach = function InputAttach(_a) {
1188
- var name = _a.name,
1189
- _b = _a.type,
1190
- type = _b === void 0 ? ["png", "jpg", "jpeg"] : _b,
1191
- _c = _a.amount,
1192
- amount = _c === void 0 ? 1 : _c,
1193
- _d = _a.disabled,
1194
- disabled = _d === void 0 ? false : _d,
1195
- _e = _a.placeholder,
1196
- placeholder = _e === void 0 ? "Upload an image" : _e,
1197
- _f = _a.firstValue,
1198
- firstValue = _f === void 0 ? [] : _f;
1199
- var _g = useFormContext(),
1200
- setFormValue = _g.setFormValue,
1201
- formErrors = _g.errors;
1202
- var _h = useState([]),
1203
- selectedFiles = _h[0],
1204
- setSelectedFiles = _h[1];
1205
- // Ref to track initialization
1206
- var isInitialized = useRef(false);
1207
- // Sync firstValue with selectedFiles when it changes
1208
- useEffect(function () {
1209
- if (!isInitialized.current) {
1210
- setSelectedFiles(firstValue);
1211
- setFormValue(name, firstValue, firstValue); // Pass firstValue here
1212
- isInitialized.current = true;
1213
- }
1214
- }, [firstValue, name, setFormValue]);
1215
- var theme = useContext(ThemeContext).theme;
1216
- var colors = theme.colors;
1217
- var pickImage = function pickImage() {
1218
- return __awaiter(void 0, void 0, void 0, function () {
1219
- var permissionResult, result, selectedAssets, newFiles, invalidFiles, updatedFiles;
1220
- return __generator(this, function (_a) {
1221
- switch (_a.label) {
1222
- case 0:
1223
- if (disabled) return [2 /*return*/];
1224
- return [4 /*yield*/, ImagePicker.requestMediaLibraryPermissionsAsync()];
1225
- case 1:
1226
- permissionResult = _a.sent();
1227
- if (!permissionResult.granted) {
1228
- Alert.alert("Permission Required", "We need access to your photos to upload images.");
1229
- return [2 /*return*/];
1230
- }
1231
- return [4 /*yield*/, ImagePicker.launchImageLibraryAsync({
1232
- mediaTypes: ["images"],
1233
- // Updated usage
1234
- allowsEditing: true,
1235
- allowsMultipleSelection: amount > 1,
1236
- quality: 1
1237
- })];
1238
- case 2:
1239
- result = _a.sent();
1240
- if (!result.canceled) {
1241
- selectedAssets = result.assets || [result];
1242
- newFiles = selectedAssets.map(function (asset) {
1243
- return {
1244
- uri: asset.uri,
1245
- name: asset.fileName || "unknown.jpg",
1246
- type: asset.mimeType || "image/jpeg"
1247
- };
1248
- });
1249
- invalidFiles = newFiles.filter(function (file) {
1250
- return !type.some(function (ext) {
1251
- return file.name.toLowerCase().endsWith(ext);
1252
- });
1253
- });
1254
- if (invalidFiles.length > 0) {
1255
- Alert.alert("Invalid File Type", "Please upload files of type: ".concat(type.join(", ")));
1256
- return [2 /*return*/];
1257
- }
1258
- // Check max amount
1259
- if (selectedFiles.length + newFiles.length > amount) {
1260
- Alert.alert("Limit Exceeded", "You can upload up to ".concat(amount, " files."));
1261
- return [2 /*return*/];
1262
- }
1263
- updatedFiles = __spreadArray(__spreadArray([], selectedFiles, true), newFiles, true).slice(0, amount);
1264
- setSelectedFiles(updatedFiles);
1265
- setFormValue(name, updatedFiles); // Update form context
1266
- }
1267
- return [2 /*return*/];
1268
- }
1269
- });
1270
- });
1271
- };
1272
- var removeFile = function removeFile(index) {
1273
- var updatedFiles = selectedFiles.filter(function (_, i) {
1274
- return i !== index;
1275
- });
1276
- setSelectedFiles(updatedFiles);
1277
- setFormValue(name, updatedFiles); // Update form context
1278
- };
1279
- return /*#__PURE__*/React.createElement(View, {
1280
- style: styles$1.container
1281
- }, /*#__PURE__*/React.createElement(Text, {
1282
- style: [styles$1.label, {
1283
- color: colors.text.hex
1284
- }]
1285
- }, placeholder), /*#__PURE__*/React.createElement(View, {
1286
- style: styles$1.fileContainer
1287
- }, selectedFiles.map(function (file, index) {
1288
- return /*#__PURE__*/React.createElement(View, {
1289
- key: index,
1290
- style: styles$1.fileItem
1291
- }, /*#__PURE__*/React.createElement(Image, {
1292
- source: {
1293
- uri: file.uri
1294
- },
1295
- style: styles$1.imagePreview
1296
- }), /*#__PURE__*/React.createElement(TouchableOpacity, {
1297
- onPress: function onPress() {
1298
- return removeFile(index);
1299
- },
1300
- style: [styles$1.removeButton, {
1301
- backgroundColor: colors.error.hex
1302
- }]
1303
- }, /*#__PURE__*/React.createElement(Text, {
1304
- style: styles$1.removeButtonText
1305
- }, "X")));
1306
- }), selectedFiles.length < amount && (/*#__PURE__*/React.createElement(TouchableOpacity, {
1307
- onPress: pickImage,
1308
- style: [styles$1.addButton, {
1309
- backgroundColor: colors.body.hex,
1310
- borderColor: formErrors[name] && colors.error.hex
1311
- }],
1312
- disabled: disabled
1313
- }, /*#__PURE__*/React.createElement(Text, {
1314
- style: [styles$1.addButtonText, {
1315
- color: colors.placeHolder.hex
1316
- }]
1317
- }, "+")))), formErrors[name] && formErrors[name].length > 0 && (/*#__PURE__*/React.createElement(ErrorList, {
1318
- errors: formErrors[name]
1319
- })));
1320
- };
1321
- var styles$1 = StyleSheet.create({
1322
- container: {
1323
- marginVertical: 10
1324
- },
1325
- label: {
1326
- marginTop: 5
1327
- },
1328
- fileContainer: {
1329
- flexDirection: "row",
1330
- flexWrap: "wrap",
1331
- gap: 10
1332
- },
1333
- fileItem: {
1334
- position: "relative",
1335
- width: 100,
1336
- height: 100,
1337
- marginRight: 10
1338
- },
1339
- imagePreview: {
1340
- width: "100%",
1341
- height: "100%",
1342
- borderRadius: 5
1343
- },
1344
- removeButton: {
1345
- position: "absolute",
1346
- top: 0,
1347
- right: 0,
1348
- width: 20,
1349
- height: 20,
1350
- justifyContent: "center",
1351
- alignItems: "center",
1352
- borderRadius: 10
1353
- },
1354
- removeButtonText: {
1355
- color: "#fff",
1356
- fontWeight: "bold"
1357
- },
1358
- addButton: {
1359
- width: 100,
1360
- height: 100,
1361
- justifyContent: "center",
1362
- alignItems: "center",
1363
- borderRadius: 5
1364
- },
1365
- addButtonText: {
1366
- fontSize: 24
1367
- },
1368
- error: {
1369
- marginTop: 5
1370
- }
1371
- });
1372
-
1373
- // src/components/Button.tsx
1374
- /**
1375
- * Determines the styles based on the button type and whether it is disabled.
1376
- *
1377
- * @param type - The type of the button ('submit', 'button', 'cancel').
1378
- * @param disabled - Whether the button is disabled.
1379
- * @param themeColors - The theme colors.
1380
- * @returns The computed style for the button.
1381
- */
1382
- function typeStyles(type, disabled, themeColors) {
1383
- switch (type) {
1384
- case 'submit':
1385
- return {
1386
- backgroundColor: "rgba(".concat(themeColors === null || themeColors === void 0 ? void 0 : themeColors.primary.rgb.r, ", ").concat(themeColors === null || themeColors === void 0 ? void 0 : themeColors.primary.rgb.g, ", ").concat(themeColors === null || themeColors === void 0 ? void 0 : themeColors.primary.rgb.b, ", ").concat(disabled ? 0.5 : 1, ")"),
1387
- borderWidth: 2,
1388
- borderColor: themeColors === null || themeColors === void 0 ? void 0 : themeColors.primary.hex
1389
- };
1390
- case 'button':
1391
- return {
1392
- backgroundColor: themeColors === null || themeColors === void 0 ? void 0 : themeColors.primary.hex,
1393
- borderColor: themeColors === null || themeColors === void 0 ? void 0 : themeColors.secondary.hex,
1394
- opacity: disabled ? 0.5 : 1,
1395
- borderWidth: 2
1396
- };
1397
- case 'cancel':
1398
- return {
1399
- backgroundColor: themeColors === null || themeColors === void 0 ? void 0 : themeColors.background.hex,
1400
- borderWidth: 0
1401
- };
1402
- default:
1403
- return {};
1404
- }
1405
- }
1406
- /**
1407
- * Button component that adapts its styles based on the current theme.
1408
- * Supports dynamic styling, full-width option, rounded corners, and different types.
1409
- *
1410
- * @param disabled - If true, the button is disabled and not pressable.
1411
- * @param isFullWidth - If true, the button expands to full width of its container.
1412
- * @param children - Text content of the button.
1413
- * @param onPress - Function to call when the button is pressed.
1414
- * @param rounded - If true, the button has rounded corners.
1415
- * @param borderRadius - Custom border radius value. Overrides the `rounded` prop if provided.
1416
- * @param type - Specifies the button type for styling ('submit', 'button', 'cancel').
1417
- */
1418
- var Button = function Button(_a) {
1419
- var children = _a.children,
1420
- _b = _a.disabled,
1421
- disabled = _b === void 0 ? false : _b,
1422
- _c = _a.type,
1423
- type = _c === void 0 ? 'button' : _c,
1424
- _d = _a.rounded,
1425
- rounded = _d === void 0 ? true : _d,
1426
- _e = _a.borderRadius,
1427
- borderRadius = _e === void 0 ? 30 : _e,
1428
- _f = _a.isFullWidth,
1429
- isFullWidth = _f === void 0 ? false : _f,
1430
- _g = _a.loading,
1431
- loading = _g === void 0 ? false : _g,
1432
- onPress = _a.onPress;
1433
- var theme = useContext(ThemeContext).theme;
1434
- var colors = theme.colors;
1435
- var computedStyles = useMemo(function () {
1436
- return StyleSheet.flatten([styles.button, typeStyles(type, disabled, colors), rounded && {
1437
- borderRadius: borderRadius
1438
- }, isFullWidth && {
1439
- width: '100%'
1440
- }, (disabled || loading) && styles.disabled]);
1441
- }, [type, disabled, loading, rounded, borderRadius, isFullWidth, colors]);
1442
- var textColor = useMemo(function () {
1443
- return type === "cancel" ? {
1444
- color: colors.text.hex
1445
- } : {
1446
- color: colors.textButton.hex
1447
- };
1448
- }, [type, colors]);
1449
- // Safely try to access handleSubmit from the form context
1450
- var formContext = function () {
1451
- try {
1452
- return useFormContext();
1453
- } catch (_a) {
1454
- return null;
1455
- }
1456
- }();
1457
- var handlePress = function handlePress() {
1458
- if (type === 'submit' && (formContext === null || formContext === void 0 ? void 0 : formContext.handleSubmit)) {
1459
- console.log("Its submit type");
1460
- formContext.handleSubmit();
1461
- } else if (onPress) {
1462
- onPress();
1463
- }
1464
- };
1465
- return /*#__PURE__*/React.createElement(TouchableOpacity, {
1466
- style: computedStyles,
1467
- disabled: disabled || loading,
1468
- onPress: handlePress,
1469
- activeOpacity: 0.7
1470
- }, loading ? (
1471
- /*#__PURE__*/
1472
- // Show loading spinner if loading
1473
- React.createElement(ActivityIndicator, {
1474
- size: "small",
1475
- color: colors.textButton.hex
1476
- })) : (/*#__PURE__*/React.createElement(Text$1, {
1477
- style: textColor
1478
- }, Array.isArray(children) ? children.join('').toUpperCase() : children === null || children === void 0 ? void 0 : children.toUpperCase())));
1479
- };
1480
- var styles = StyleSheet.create({
1481
- button: {
1482
- justifyContent: 'center',
1483
- alignItems: 'center',
1484
- paddingVertical: 10,
1485
- paddingHorizontal: 20
1486
- },
1487
- disabled: {
1488
- opacity: 0.6
1489
- }
1490
- });
1491
-
1492
- export { Button, Card, ErrorList, Form, Input, InputAttach, InputCheck, InputList, Label, Text, TextArea, setFormValueGlobal, useFormContext };
1493
- //# sourceMappingURL=index.esm.js.map