@umituz/react-native-ai-generation-content 1.17.144 → 1.17.146

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 (29) hide show
  1. package/package.json +1 -1
  2. package/src/features/photo-restoration/presentation/components/PhotoRestoreResultView.tsx +1 -1
  3. package/src/features/replace-background/index.ts +5 -50
  4. package/src/features/replace-background/presentation/components/index.ts +0 -12
  5. package/src/features/replace-background/presentation/hooks/index.ts +0 -3
  6. package/src/infrastructure/utils/index.ts +1 -0
  7. package/src/infrastructure/utils/result-validator.util.ts +0 -214
  8. package/src/infrastructure/utils/url-extractor.util.ts +209 -0
  9. package/src/presentation/hooks/flow-state.utils.ts +101 -0
  10. package/src/presentation/hooks/useGenerationFlow.ts +47 -178
  11. package/src/presentation/types/flow-config.types.ts +5 -99
  12. package/src/presentation/types/flow-default-configs.ts +106 -0
  13. package/src/features/replace-background/domain/entities/background.types.ts +0 -77
  14. package/src/features/replace-background/domain/entities/component.types.ts +0 -87
  15. package/src/features/replace-background/domain/entities/config.types.ts +0 -41
  16. package/src/features/replace-background/domain/entities/index.ts +0 -30
  17. package/src/features/replace-background/infrastructure/constants/index.ts +0 -5
  18. package/src/features/replace-background/infrastructure/constants/prompts.constants.ts +0 -15
  19. package/src/features/replace-background/infrastructure/index.ts +0 -5
  20. package/src/features/replace-background/presentation/components/BackgroundFeature.tsx +0 -143
  21. package/src/features/replace-background/presentation/components/ComparisonSlider.tsx +0 -187
  22. package/src/features/replace-background/presentation/components/ErrorDisplay.tsx +0 -60
  23. package/src/features/replace-background/presentation/components/FeatureHeader.tsx +0 -80
  24. package/src/features/replace-background/presentation/components/GenerateButton.tsx +0 -85
  25. package/src/features/replace-background/presentation/components/ImagePicker.tsx +0 -136
  26. package/src/features/replace-background/presentation/components/ModeSelector.tsx +0 -78
  27. package/src/features/replace-background/presentation/components/PromptInput.tsx +0 -142
  28. package/src/features/replace-background/presentation/components/ResultDisplay.tsx +0 -122
  29. package/src/features/replace-background/presentation/hooks/useBackgroundFeature.ts +0 -119
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.17.144",
3
+ "version": "1.17.146",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -10,7 +10,7 @@ import {
10
10
  useAppDesignTokens,
11
11
  } from "@umituz/react-native-design-system";
12
12
  import { AIGenerationResult } from "../../../../presentation/components/display/AIGenerationResult";
13
- import { ComparisonSlider } from "../../../replace-background/presentation/components/ComparisonSlider";
13
+ import { ComparisonSlider } from "../../../upscaling/presentation/components/ComparisonSlider";
14
14
  import type { PhotoRestoreTranslations } from "../../domain/types";
15
15
 
16
16
  export interface PhotoRestoreResultViewProps {
@@ -1,31 +1,9 @@
1
1
  /**
2
2
  * Replace Background Feature
3
- * AI-powered background replacement and removal feature for React Native
3
+ * AI-powered background replacement feature for React Native
4
4
  */
5
5
 
6
- // Domain Types - Legacy
7
- export type {
8
- BackgroundProcessRequest,
9
- BackgroundProcessResult,
10
- BackgroundFeatureState,
11
- SamplePrompt,
12
- StudioMode,
13
- StudioModeConfig,
14
- ComparisonState,
15
- ImagePickerProps,
16
- PromptInputProps,
17
- GenerateButtonProps,
18
- ResultDisplayProps,
19
- ErrorDisplayProps,
20
- FeatureHeaderProps,
21
- ModeSelectorProps,
22
- ComparisonSliderProps,
23
- ProcessRequestParams,
24
- BackgroundFeatureConfig,
25
- UseBackgroundFeatureConfig,
26
- } from "./domain/entities";
27
-
28
- // Domain Types - Provider-Agnostic
6
+ // Domain Types
29
7
  export type {
30
8
  ReplaceBackgroundMode,
31
9
  ReplaceBackgroundOptions,
@@ -37,36 +15,13 @@ export type {
37
15
  ReplaceBackgroundResultExtractor,
38
16
  } from "./domain/types";
39
17
 
40
- // Constants
41
- export { DEFAULT_SAMPLE_PROMPTS } from "./infrastructure/constants";
42
-
43
18
  // Presentation Components
44
- export {
45
- BackgroundFeature,
46
- ReplaceBackgroundFeature,
47
- ImagePicker,
48
- PromptInput,
49
- GenerateButton,
50
- ResultDisplay,
51
- ErrorDisplay,
52
- FeatureHeader,
53
- ComparisonSlider,
54
- ModeSelector,
55
- } from "./presentation/components";
56
-
57
- export type {
58
- BackgroundFeatureProps,
59
- ReplaceBackgroundFeatureProps,
60
- } from "./presentation/components";
19
+ export { ReplaceBackgroundFeature } from "./presentation/components";
20
+ export type { ReplaceBackgroundFeatureProps } from "./presentation/components";
61
21
 
62
22
  // Presentation Hooks
63
- export {
64
- useBackgroundFeature,
65
- useReplaceBackgroundFeature,
66
- } from "./presentation/hooks";
67
-
23
+ export { useReplaceBackgroundFeature } from "./presentation/hooks";
68
24
  export type {
69
- UseBackgroundFeatureReturn,
70
25
  UseReplaceBackgroundFeatureProps,
71
26
  UseReplaceBackgroundFeatureReturn,
72
27
  } from "./presentation/hooks";
@@ -2,17 +2,5 @@
2
2
  * Presentation Components Export
3
3
  */
4
4
 
5
- export { BackgroundFeature } from "./BackgroundFeature";
6
- export type { BackgroundFeatureProps } from "./BackgroundFeature";
7
-
8
5
  export { ReplaceBackgroundFeature } from "./ReplaceBackgroundFeature";
9
6
  export type { ReplaceBackgroundFeatureProps } from "./ReplaceBackgroundFeature";
10
-
11
- export { ImagePicker } from "./ImagePicker";
12
- export { PromptInput } from "./PromptInput";
13
- export { GenerateButton } from "./GenerateButton";
14
- export { ResultDisplay } from "./ResultDisplay";
15
- export { ErrorDisplay } from "./ErrorDisplay";
16
- export { FeatureHeader } from "./FeatureHeader";
17
- export { ComparisonSlider } from "./ComparisonSlider";
18
- export { ModeSelector } from "./ModeSelector";
@@ -2,9 +2,6 @@
2
2
  * Presentation Hooks Export
3
3
  */
4
4
 
5
- export { useBackgroundFeature } from "./useBackgroundFeature";
6
- export type { UseBackgroundFeatureReturn } from "./useBackgroundFeature";
7
-
8
5
  export { useReplaceBackgroundFeature } from "./useReplaceBackgroundFeature";
9
6
  export type {
10
7
  UseReplaceBackgroundFeatureProps,
@@ -7,6 +7,7 @@ export * from "./polling-interval.util";
7
7
  export * from "./progress-calculator.util";
8
8
  export * from "./status-checker.util";
9
9
  export * from "./result-validator.util";
10
+ export * from "./url-extractor.util";
10
11
  export * from "./photo-generation";
11
12
  export * from "./feature-utils";
12
13
  export * from "./video-helpers";
@@ -13,9 +13,7 @@ export interface ResultValidation {
13
13
  }
14
14
 
15
15
  export interface ValidateResultOptions {
16
- /** Custom output field names to check */
17
16
  outputFields?: string[];
18
- /** Whether empty results are allowed */
19
17
  allowEmpty?: boolean;
20
18
  }
21
19
 
@@ -44,7 +42,6 @@ export function validateResult(
44
42
  const { outputFields = DEFAULT_OUTPUT_FIELDS, allowEmpty = false } =
45
43
  options ?? {};
46
44
 
47
- // Handle null/undefined
48
45
  if (result === null || result === undefined) {
49
46
  return {
50
47
  isValid: allowEmpty,
@@ -54,7 +51,6 @@ export function validateResult(
54
51
  };
55
52
  }
56
53
 
57
- // Handle non-object results
58
54
  if (typeof result !== "object") {
59
55
  return {
60
56
  isValid: true,
@@ -65,7 +61,6 @@ export function validateResult(
65
61
 
66
62
  const resultObj = result as Record<string, unknown>;
67
63
 
68
- // Check for error fields
69
64
  const errorValue = resultObj.error || resultObj.detail;
70
65
  const errorString = errorValue ? String(errorValue).toLowerCase() : "";
71
66
 
@@ -74,15 +69,12 @@ export function validateResult(
74
69
  errorString.includes("500") ||
75
70
  errorString === "internal server error";
76
71
 
77
- // Check for empty object
78
72
  const isEmpty = Object.keys(resultObj).length === 0;
79
73
 
80
- // Check for output in expected fields
81
74
  const hasOutput = outputFields.some((field) => {
82
75
  const value = resultObj[field];
83
76
  if (!value) return false;
84
77
 
85
- // Handle nested output structures
86
78
  if (typeof value === "object" && value !== null) {
87
79
  const nested = value as Record<string, unknown>;
88
80
  return !!(
@@ -96,7 +88,6 @@ export function validateResult(
96
88
  return true;
97
89
  });
98
90
 
99
- // Determine if result has error
100
91
  const hasError =
101
92
  hasInternalServerError || (isEmpty && !hasOutput && !allowEmpty);
102
93
 
@@ -113,213 +104,8 @@ export function validateResult(
113
104
  isValid: validation.isValid,
114
105
  hasOutput: validation.hasOutput,
115
106
  hasError: validation.hasError,
116
- checkedFields: outputFields.join(", "),
117
107
  });
118
108
  }
119
109
 
120
110
  return validation;
121
111
  }
122
-
123
- /**
124
- * Extract output URL from result
125
- * Supports various AI provider response formats
126
- */
127
- export function extractOutputUrl(
128
- result: unknown,
129
- urlFields?: string[],
130
- ): string | undefined {
131
- if (!result || typeof result !== "object") {
132
- return undefined;
133
- }
134
-
135
- const fields = urlFields ?? [
136
- "url",
137
- "image_url",
138
- "video_url",
139
- "output_url",
140
- "result_url",
141
- ];
142
-
143
- const resultObj = result as Record<string, unknown>;
144
-
145
- // Check top-level fields
146
- for (const field of fields) {
147
- const value = resultObj[field];
148
- if (typeof value === "string" && value.length > 0) {
149
- return value;
150
- }
151
- }
152
-
153
- // Check nested data/output objects
154
- const nested =
155
- (resultObj.data as Record<string, unknown>) ||
156
- (resultObj.output as Record<string, unknown>) ||
157
- (resultObj.result as Record<string, unknown>);
158
-
159
- if (nested && typeof nested === "object") {
160
- for (const field of fields) {
161
- const value = nested[field];
162
- if (typeof value === "string" && value.length > 0) {
163
- return value;
164
- }
165
- }
166
-
167
- // Check for nested image/video objects
168
- const media =
169
- (nested.image as Record<string, unknown>) ||
170
- (nested.video as Record<string, unknown>);
171
- if (media && typeof media === "object" && typeof media.url === "string") {
172
- return media.url;
173
- }
174
- }
175
-
176
- return undefined;
177
- }
178
-
179
- /**
180
- * Extract multiple output URLs from result
181
- */
182
- export function extractOutputUrls(
183
- result: unknown,
184
- urlFields?: string[],
185
- ): string[] {
186
- if (!result || typeof result !== "object") {
187
- return [];
188
- }
189
-
190
- const urls: string[] = [];
191
- const resultObj = result as Record<string, unknown>;
192
-
193
- // Check for arrays
194
- const arrayFields = ["images", "videos", "outputs", "results", "urls"];
195
- for (const field of arrayFields) {
196
- const arr = resultObj[field];
197
- if (Array.isArray(arr)) {
198
- for (const item of arr) {
199
- const url = extractOutputUrl(item, urlFields);
200
- if (url) {
201
- urls.push(url);
202
- }
203
- }
204
- }
205
- }
206
-
207
- // Check nested data/output
208
- const nested = resultObj.data || resultObj.output;
209
- if (nested && typeof nested === "object") {
210
- for (const field of arrayFields) {
211
- const arr = (nested as Record<string, unknown>)[field];
212
- if (Array.isArray(arr)) {
213
- for (const item of arr) {
214
- const url = extractOutputUrl(item, urlFields);
215
- if (url) {
216
- urls.push(url);
217
- }
218
- }
219
- }
220
- }
221
- }
222
-
223
- // If no array found, try single URL
224
- if (urls.length === 0) {
225
- const singleUrl = extractOutputUrl(result, urlFields);
226
- if (singleUrl) {
227
- urls.push(singleUrl);
228
- }
229
- }
230
-
231
- return urls;
232
- }
233
-
234
- /**
235
- * Extract video URL from AI generation result
236
- */
237
- export function extractVideoUrl(result: unknown): string | undefined {
238
- return extractOutputUrl(result, [
239
- "video_url",
240
- "videoUrl",
241
- "video",
242
- "url",
243
- ]);
244
- }
245
-
246
- /**
247
- * Extract thumbnail URL from AI generation result
248
- */
249
- export function extractThumbnailUrl(result: unknown): string | undefined {
250
- if (!result || typeof result !== "object") {
251
- return undefined;
252
- }
253
-
254
- const resultObj = result as Record<string, unknown>;
255
-
256
- // Check direct fields
257
- const fields = ["thumbnail_url", "thumbnailUrl", "thumbnail", "poster"];
258
- for (const field of fields) {
259
- const value = resultObj[field];
260
- if (typeof value === "string" && value.length > 0) {
261
- return value;
262
- }
263
- if (value && typeof value === "object") {
264
- const nested = value as Record<string, unknown>;
265
- if (typeof nested.url === "string") {
266
- return nested.url;
267
- }
268
- }
269
- }
270
-
271
- return undefined;
272
- }
273
-
274
- /**
275
- * Extract audio URL from AI generation result
276
- */
277
- export function extractAudioUrl(result: unknown): string | undefined {
278
- return extractOutputUrl(result, [
279
- "audio_url",
280
- "audioUrl",
281
- "audio",
282
- "url",
283
- ]);
284
- }
285
-
286
- /**
287
- * Extract image URLs from AI generation result
288
- */
289
- export function extractImageUrls(result: unknown): string[] {
290
- if (!result || typeof result !== "object") {
291
- return [];
292
- }
293
-
294
- const urls: string[] = [];
295
- const resultObj = result as Record<string, unknown>;
296
-
297
- // Check images array
298
- if (Array.isArray(resultObj.images)) {
299
- for (const img of resultObj.images) {
300
- if (typeof img === "string" && img.length > 0) {
301
- urls.push(img);
302
- } else if (img && typeof img === "object") {
303
- const imgObj = img as Record<string, unknown>;
304
- if (typeof imgObj.url === "string") {
305
- urls.push(imgObj.url);
306
- }
307
- }
308
- }
309
- }
310
-
311
- // Check single image
312
- if (urls.length === 0) {
313
- const singleUrl = extractOutputUrl(result, [
314
- "image_url",
315
- "imageUrl",
316
- "image",
317
- "url",
318
- ]);
319
- if (singleUrl) {
320
- urls.push(singleUrl);
321
- }
322
- }
323
-
324
- return urls;
325
- }
@@ -0,0 +1,209 @@
1
+ /**
2
+ * URL Extractor Utility
3
+ * Extracts output URLs from AI generation results
4
+ * Supports various provider response formats
5
+ */
6
+
7
+ /**
8
+ * Extract output URL from result
9
+ * Supports various AI provider response formats
10
+ */
11
+ export function extractOutputUrl(
12
+ result: unknown,
13
+ urlFields?: string[],
14
+ ): string | undefined {
15
+ if (!result || typeof result !== "object") {
16
+ return undefined;
17
+ }
18
+
19
+ const fields = urlFields ?? [
20
+ "url",
21
+ "image_url",
22
+ "video_url",
23
+ "output_url",
24
+ "result_url",
25
+ ];
26
+
27
+ const resultObj = result as Record<string, unknown>;
28
+
29
+ // Check top-level fields
30
+ for (const field of fields) {
31
+ const value = resultObj[field];
32
+ if (typeof value === "string" && value.length > 0) {
33
+ return value;
34
+ }
35
+ }
36
+
37
+ // Check nested data/output objects
38
+ const nested =
39
+ (resultObj.data as Record<string, unknown>) ||
40
+ (resultObj.output as Record<string, unknown>) ||
41
+ (resultObj.result as Record<string, unknown>);
42
+
43
+ if (nested && typeof nested === "object") {
44
+ for (const field of fields) {
45
+ const value = nested[field];
46
+ if (typeof value === "string" && value.length > 0) {
47
+ return value;
48
+ }
49
+ }
50
+
51
+ // Check for nested image/video objects
52
+ const media =
53
+ (nested.image as Record<string, unknown>) ||
54
+ (nested.video as Record<string, unknown>);
55
+ if (media && typeof media === "object" && typeof media.url === "string") {
56
+ return media.url;
57
+ }
58
+ }
59
+
60
+ return undefined;
61
+ }
62
+
63
+ /**
64
+ * Extract multiple output URLs from result
65
+ */
66
+ export function extractOutputUrls(
67
+ result: unknown,
68
+ urlFields?: string[],
69
+ ): string[] {
70
+ if (!result || typeof result !== "object") {
71
+ return [];
72
+ }
73
+
74
+ const urls: string[] = [];
75
+ const resultObj = result as Record<string, unknown>;
76
+
77
+ // Check for arrays
78
+ const arrayFields = ["images", "videos", "outputs", "results", "urls"];
79
+ for (const field of arrayFields) {
80
+ const arr = resultObj[field];
81
+ if (Array.isArray(arr)) {
82
+ for (const item of arr) {
83
+ const url = extractOutputUrl(item, urlFields);
84
+ if (url) {
85
+ urls.push(url);
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ // Check nested data/output
92
+ const nested = resultObj.data || resultObj.output;
93
+ if (nested && typeof nested === "object") {
94
+ for (const field of arrayFields) {
95
+ const arr = (nested as Record<string, unknown>)[field];
96
+ if (Array.isArray(arr)) {
97
+ for (const item of arr) {
98
+ const url = extractOutputUrl(item, urlFields);
99
+ if (url) {
100
+ urls.push(url);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ // If no array found, try single URL
108
+ if (urls.length === 0) {
109
+ const singleUrl = extractOutputUrl(result, urlFields);
110
+ if (singleUrl) {
111
+ urls.push(singleUrl);
112
+ }
113
+ }
114
+
115
+ return urls;
116
+ }
117
+
118
+ /**
119
+ * Extract video URL from AI generation result
120
+ */
121
+ export function extractVideoUrl(result: unknown): string | undefined {
122
+ return extractOutputUrl(result, [
123
+ "video_url",
124
+ "videoUrl",
125
+ "video",
126
+ "url",
127
+ ]);
128
+ }
129
+
130
+ /**
131
+ * Extract thumbnail URL from AI generation result
132
+ */
133
+ export function extractThumbnailUrl(result: unknown): string | undefined {
134
+ if (!result || typeof result !== "object") {
135
+ return undefined;
136
+ }
137
+
138
+ const resultObj = result as Record<string, unknown>;
139
+
140
+ // Check direct fields
141
+ const fields = ["thumbnail_url", "thumbnailUrl", "thumbnail", "poster"];
142
+ for (const field of fields) {
143
+ const value = resultObj[field];
144
+ if (typeof value === "string" && value.length > 0) {
145
+ return value;
146
+ }
147
+ if (value && typeof value === "object") {
148
+ const nested = value as Record<string, unknown>;
149
+ if (typeof nested.url === "string") {
150
+ return nested.url;
151
+ }
152
+ }
153
+ }
154
+
155
+ return undefined;
156
+ }
157
+
158
+ /**
159
+ * Extract audio URL from AI generation result
160
+ */
161
+ export function extractAudioUrl(result: unknown): string | undefined {
162
+ return extractOutputUrl(result, [
163
+ "audio_url",
164
+ "audioUrl",
165
+ "audio",
166
+ "url",
167
+ ]);
168
+ }
169
+
170
+ /**
171
+ * Extract image URLs from AI generation result
172
+ */
173
+ export function extractImageUrls(result: unknown): string[] {
174
+ if (!result || typeof result !== "object") {
175
+ return [];
176
+ }
177
+
178
+ const urls: string[] = [];
179
+ const resultObj = result as Record<string, unknown>;
180
+
181
+ // Check images array
182
+ if (Array.isArray(resultObj.images)) {
183
+ for (const img of resultObj.images) {
184
+ if (typeof img === "string" && img.length > 0) {
185
+ urls.push(img);
186
+ } else if (img && typeof img === "object") {
187
+ const imgObj = img as Record<string, unknown>;
188
+ if (typeof imgObj.url === "string") {
189
+ urls.push(imgObj.url);
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ // Check single image
196
+ if (urls.length === 0) {
197
+ const singleUrl = extractOutputUrl(result, [
198
+ "image_url",
199
+ "imageUrl",
200
+ "image",
201
+ "url",
202
+ ]);
203
+ if (singleUrl) {
204
+ urls.push(singleUrl);
205
+ }
206
+ }
207
+
208
+ return urls;
209
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Flow State Utilities
3
+ * State initialization and update helpers for generation flow
4
+ *
5
+ * @package @umituz/react-native-ai-generation-content
6
+ */
7
+
8
+ import type {
9
+ GenerationFlowConfig,
10
+ GenerationFlowState,
11
+ PhotoStepData,
12
+ PhotoStepConfig,
13
+ } from "../types/flow-config.types";
14
+
15
+ /**
16
+ * Create initial flow state from config
17
+ */
18
+ export function createInitialFlowState(
19
+ config: GenerationFlowConfig,
20
+ ): GenerationFlowState {
21
+ return {
22
+ currentStepIndex: 0,
23
+ photoSteps: config.photoSteps.map((step) => ({
24
+ id: step.id,
25
+ imageUri: null,
26
+ previewUrl: undefined,
27
+ name: undefined,
28
+ isValid: undefined,
29
+ validationStatus: "pending" as const,
30
+ })),
31
+ textInput: config.textInputStep
32
+ ? {
33
+ id: config.textInputStep.id,
34
+ text: "",
35
+ isValid: false,
36
+ }
37
+ : undefined,
38
+ isComplete: false,
39
+ isProcessing: false,
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Update photo step in state
45
+ */
46
+ export function updatePhotoStep(
47
+ state: GenerationFlowState,
48
+ stepIndex: number,
49
+ updates: Partial<PhotoStepData>,
50
+ ): GenerationFlowState {
51
+ const newPhotoSteps = [...state.photoSteps];
52
+ newPhotoSteps[stepIndex] = {
53
+ ...newPhotoSteps[stepIndex],
54
+ ...updates,
55
+ };
56
+
57
+ return {
58
+ ...state,
59
+ photoSteps: newPhotoSteps,
60
+ };
61
+ }
62
+
63
+ /**
64
+ * Check if current step is valid
65
+ */
66
+ export function isStepValid(
67
+ stepData: PhotoStepData | null,
68
+ stepConfig: PhotoStepConfig | null,
69
+ ): boolean {
70
+ if (!stepData || !stepConfig) {
71
+ return false;
72
+ }
73
+
74
+ // Check photo
75
+ if (!stepData.imageUri) {
76
+ return false;
77
+ }
78
+
79
+ // Check name if required
80
+ if (stepConfig.requireNameInput && !stepData.name) {
81
+ return false;
82
+ }
83
+
84
+ // Check validation if enabled
85
+ if (stepConfig.enableValidation && !stepData.isValid) {
86
+ return false;
87
+ }
88
+
89
+ return true;
90
+ }
91
+
92
+ /**
93
+ * Check if text input is valid
94
+ */
95
+ export function isTextInputValid(
96
+ text: string,
97
+ minLength: number,
98
+ maxLength: number,
99
+ ): boolean {
100
+ return text.length >= minLength && text.length <= maxLength;
101
+ }