@umituz/react-native-ai-generation-content 1.72.10 → 1.72.12

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/domains/creations/presentation/components/CreationCard.utils.ts +2 -3
  3. package/src/domains/creations/presentation/components/CreationsFilterBar.tsx +41 -5
  4. package/src/domains/creations/presentation/hooks/filterHelpers.ts +5 -17
  5. package/src/domains/image-to-video/presentation/hooks/useFormState.ts +30 -58
  6. package/src/domains/image-to-video/presentation/hooks/useGeneration.ts +41 -71
  7. package/src/domains/text-to-image/presentation/hooks/useFormState.ts +34 -81
  8. package/src/exports/presentation.ts +5 -5
  9. package/src/index.ts +3 -0
  10. package/src/presentation/components/GenerationProgressContent.tsx +5 -2
  11. package/src/presentation/components/PendingJobCard.tsx +9 -2
  12. package/src/presentation/components/README.md +6 -5
  13. package/src/presentation/components/index.ts +0 -4
  14. package/src/shared/components/common/ProgressBar.tsx +99 -0
  15. package/src/shared/components/common/index.ts +5 -0
  16. package/src/shared/components/index.ts +5 -0
  17. package/src/shared/hooks/factories/createFormStateHook.ts +119 -0
  18. package/src/shared/hooks/factories/createGenerationHook.ts +253 -0
  19. package/src/shared/hooks/factories/index.ts +21 -0
  20. package/src/shared/hooks/index.ts +5 -0
  21. package/src/shared/index.ts +14 -0
  22. package/src/shared/utils/date/index.ts +11 -0
  23. package/src/shared/utils/date/normalization.ts +60 -0
  24. package/src/shared/utils/filters/createFilterButtons.ts +60 -0
  25. package/src/shared/utils/filters/index.ts +11 -0
  26. package/src/shared/utils/index.ts +6 -0
  27. package/src/domains/creations/presentation/components/filter-bar-utils.ts +0 -96
  28. package/src/presentation/components/GenerationProgressBar.tsx +0 -78
  29. package/src/presentation/components/PendingJobProgressBar.tsx +0 -56
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.72.10",
3
+ "version": "1.72.12",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import { useMemo } from "react";
6
+ import { normalizeToDate } from "../../../../shared/utils/date";
6
7
 
7
8
  /**
8
9
  * Format creation date for display
@@ -12,9 +13,7 @@ export function useCreationDateFormatter(
12
13
  formatDate?: (date: Date) => string
13
14
  ): string {
14
15
  return useMemo(() => {
15
- const date = createdAt instanceof Date
16
- ? createdAt
17
- : new Date(createdAt);
16
+ const date = normalizeToDate(createdAt);
18
17
 
19
18
  if (formatDate) {
20
19
  return formatDate(date);
@@ -10,7 +10,8 @@ import {
10
10
  AtomicText,
11
11
  AtomicIcon,
12
12
  } from "@umituz/react-native-design-system";
13
- import type { CreationsFilterBarProps } from "./CreationsFilterBar.types";
13
+ import { createFilterButtons } from "../../../../shared/utils/filters";
14
+ import type { CreationsFilterBarProps, MediaFilterLabels, StatusFilterLabels, FilterButton } from "./CreationsFilterBar.types";
14
15
 
15
16
  export function CreationsFilterBar({
16
17
  filters,
@@ -133,7 +134,42 @@ export function CreationsFilterBar({
133
134
  }
134
135
 
135
136
  export type { FilterButton, CreationsFilterBarProps } from "./CreationsFilterBar.types";
136
- export {
137
- createMediaFilterButtons,
138
- createStatusFilterButtons,
139
- } from "./filter-bar-utils";
137
+
138
+ /**
139
+ * Helper to create media filter buttons
140
+ * Uses shared generic filter factory
141
+ */
142
+ export function createMediaFilterButtons(
143
+ activeFilter: string,
144
+ onSelect: (filter: string) => void,
145
+ labels: MediaFilterLabels
146
+ ): FilterButton[] {
147
+ const items = [
148
+ { id: "all" as const, label: labels.all, icon: "grid" },
149
+ { id: "image" as const, label: labels.images, icon: "image" },
150
+ { id: "video" as const, label: labels.videos, icon: "film" },
151
+ { id: "voice" as const, label: labels.voice, icon: "mic" },
152
+ ];
153
+
154
+ return createFilterButtons(items, activeFilter, onSelect);
155
+ }
156
+
157
+ /**
158
+ * Helper to create status filter buttons
159
+ * Uses shared generic filter factory
160
+ */
161
+ export function createStatusFilterButtons(
162
+ activeFilter: string,
163
+ onSelect: (filter: string) => void,
164
+ labels: StatusFilterLabels
165
+ ): FilterButton[] {
166
+ const items = [
167
+ { id: "all" as const, label: labels.all, icon: "options" },
168
+ { id: "completed" as const, label: labels.completed, icon: "checkmark-circle" },
169
+ { id: "processing" as const, label: labels.processing, icon: "refresh" },
170
+ { id: "pending" as const, label: labels.pending, icon: "time" },
171
+ { id: "failed" as const, label: labels.failed, icon: "close-circle" },
172
+ ];
173
+
174
+ return createFilterButtons(items, activeFilter, onSelect);
175
+ }
@@ -7,6 +7,7 @@ import type { CreationFilter } from "../../domain/types";
7
7
  import { isTypeInCategory } from "../../domain/types";
8
8
  import type { CreationCategory, CreationTypeId } from "../../domain/types";
9
9
  import type { FilterableCreation } from "./advancedFilter.types";
10
+ import { normalizeDateToTimestamp, compareDates } from "../../../../shared/utils/date";
10
11
 
11
12
  export function filterByType<T extends FilterableCreation>(
12
13
  creations: T[],
@@ -55,16 +56,14 @@ export function filterByDateRange<T extends FilterableCreation>(
55
56
 
56
57
  if (startDate) {
57
58
  result = result.filter((c) => {
58
- const createdAt =
59
- c.createdAt instanceof Date ? c.createdAt.getTime() : c.createdAt || 0;
59
+ const createdAt = normalizeDateToTimestamp(c.createdAt);
60
60
  return createdAt >= startDate;
61
61
  });
62
62
  }
63
63
 
64
64
  if (endDate) {
65
65
  result = result.filter((c) => {
66
- const createdAt =
67
- c.createdAt instanceof Date ? c.createdAt.getTime() : c.createdAt || 0;
66
+ const createdAt = normalizeDateToTimestamp(c.createdAt);
68
67
  return createdAt <= endDate;
69
68
  });
70
69
  }
@@ -85,13 +84,9 @@ export function sortCreations<T extends FilterableCreation>(
85
84
 
86
85
  switch (sortField) {
87
86
  case "createdAt":
88
- aVal = a.createdAt;
89
- bVal = b.createdAt;
90
- break;
87
+ return compareDates(a.createdAt, b.createdAt, sortOrder);
91
88
  case "updatedAt":
92
- aVal = a.updatedAt;
93
- bVal = b.updatedAt;
94
- break;
89
+ return compareDates(a.updatedAt, b.updatedAt, sortOrder);
95
90
  case "type":
96
91
  aVal = a.type;
97
92
  bVal = b.type;
@@ -104,9 +99,6 @@ export function sortCreations<T extends FilterableCreation>(
104
99
  return 0;
105
100
  }
106
101
 
107
- if (aVal instanceof Date) aVal = aVal.getTime();
108
- if (bVal instanceof Date) bVal = bVal.getTime();
109
-
110
102
  if (aVal === undefined && bVal === undefined) return 0;
111
103
  if (aVal === undefined) return 1;
112
104
  if (bVal === undefined) return -1;
@@ -117,10 +109,6 @@ export function sortCreations<T extends FilterableCreation>(
117
109
  : aVal.localeCompare(bVal);
118
110
  }
119
111
 
120
- if (typeof aVal === "number" && typeof bVal === "number") {
121
- return sortOrder === "desc" ? bVal - aVal : aVal - bVal;
122
- }
123
-
124
112
  return 0;
125
113
  });
126
114
  }
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * Form State Hook for Image-to-Video
3
3
  * Manages form state with actions
4
+ * Now powered by generic form state factory
4
5
  */
5
6
 
6
- import { useState, useCallback, useMemo } from "react";
7
+ import { useCallback, useMemo } from "react";
8
+ import { createFormStateHook } from "../../../../shared/hooks/factories";
7
9
  import type {
8
10
  ImageToVideoFormState,
9
11
  ImageToVideoFormActions,
10
12
  ImageToVideoFormDefaults,
11
- AnimationStyleId,
12
- VideoDuration,
13
13
  } from "../../domain/types";
14
14
 
15
15
  export interface UseFormStateOptions {
@@ -18,78 +18,50 @@ export interface UseFormStateOptions {
18
18
 
19
19
  export interface UseFormStateReturn {
20
20
  state: ImageToVideoFormState;
21
- actions: ImageToVideoFormActions;
21
+ actions: ImageToVideoFormActions & {
22
+ addImages: (images: string[]) => void;
23
+ removeImage: (index: number) => void;
24
+ };
22
25
  }
23
26
 
24
- function createInitialState(defaults: ImageToVideoFormDefaults): ImageToVideoFormState {
25
- return {
27
+ // Create the form state hook using the factory
28
+ const useImageToVideoFormStateInternal = createFormStateHook<
29
+ ImageToVideoFormState,
30
+ ImageToVideoFormDefaults
31
+ >({
32
+ createInitialState: (defaults) => ({
26
33
  selectedImages: [],
27
34
  animationStyle: defaults.animationStyle ?? "none",
28
35
  duration: defaults.duration ?? 3,
29
36
  motionPrompt: "",
30
- };
31
- }
37
+ }),
38
+ });
32
39
 
40
+ /**
41
+ * Image-to-Video form state hook
42
+ * Manages form fields with additional image array helpers
43
+ */
33
44
  export function useFormState(options: UseFormStateOptions): UseFormStateReturn {
34
- const { defaults } = options;
35
-
36
- const [state, setState] = useState<ImageToVideoFormState>(() =>
37
- createInitialState(defaults)
38
- );
39
-
40
- const setSelectedImages = useCallback((images: string[]) => {
41
- setState((prev) => ({ ...prev, selectedImages: images }));
42
- }, []);
45
+ const { state, actions: baseActions } = useImageToVideoFormStateInternal(options);
43
46
 
47
+ // Add custom array helpers
44
48
  const addImages = useCallback((images: string[]) => {
45
- setState((prev) => ({
46
- ...prev,
47
- selectedImages: [...prev.selectedImages, ...images],
48
- }));
49
- }, []);
49
+ baseActions.setSelectedImages([...state.selectedImages, ...images]);
50
+ }, [state.selectedImages, baseActions]);
50
51
 
51
52
  const removeImage = useCallback((index: number) => {
52
- setState((prev) => ({
53
- ...prev,
54
- selectedImages: prev.selectedImages.filter((_, i) => i !== index),
55
- }));
56
- }, []);
57
-
58
- const setAnimationStyle = useCallback((style: AnimationStyleId) => {
59
- setState((prev) => ({ ...prev, animationStyle: style }));
60
- }, []);
61
-
62
- const setDuration = useCallback((duration: VideoDuration) => {
63
- setState((prev) => ({ ...prev, duration }));
64
- }, []);
65
-
66
- const setMotionPrompt = useCallback((prompt: string) => {
67
- setState((prev) => ({ ...prev, motionPrompt: prompt }));
68
- }, []);
53
+ baseActions.setSelectedImages(
54
+ state.selectedImages.filter((_, i) => i !== index)
55
+ );
56
+ }, [state.selectedImages, baseActions]);
69
57
 
70
- const reset = useCallback(() => {
71
- setState(createInitialState(defaults));
72
- }, [defaults]);
73
-
74
- const actions = useMemo<ImageToVideoFormActions>(
58
+ const actions = useMemo(
75
59
  () => ({
76
- setSelectedImages,
60
+ ...baseActions,
77
61
  addImages,
78
62
  removeImage,
79
- setAnimationStyle,
80
- setDuration,
81
- setMotionPrompt,
82
- reset,
83
63
  }),
84
- [
85
- setSelectedImages,
86
- addImages,
87
- removeImage,
88
- setAnimationStyle,
89
- setDuration,
90
- setMotionPrompt,
91
- reset,
92
- ]
64
+ [baseActions, addImages, removeImage]
93
65
  );
94
66
 
95
67
  return { state, actions };
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * Generation Hook for Image-to-Video
3
3
  * Manages generation state and execution with abort support
4
+ * Now powered by generic generation hook factory
4
5
  */
5
6
 
6
- import { useState, useCallback, useMemo, useRef, useEffect } from "react";
7
+ import { useMemo } from "react";
8
+ import { createGenerationHook } from "../../../../shared/hooks/factories";
7
9
  import type {
8
10
  ImageToVideoFormState,
9
11
  ImageToVideoGenerationState,
@@ -23,85 +25,53 @@ export interface UseGenerationReturn {
23
25
  isReady: boolean;
24
26
  }
25
27
 
26
- const INITIAL_GENERATION_STATE: ImageToVideoGenerationState = {
27
- isGenerating: false,
28
- progress: 0,
29
- error: null,
30
- };
28
+ // Create the generation hook using the factory
29
+ const useImageToVideoGenerationInternal = createGenerationHook<
30
+ ImageToVideoFormState,
31
+ void
32
+ >({
33
+ execute: async (_request) => {
34
+ // This will be called via callbacks
35
+ // The actual execution happens in the callbacks layer
36
+ },
37
+ validate: (request) => {
38
+ if (request.selectedImages.length === 0) {
39
+ return "No images selected";
40
+ }
41
+ return null;
42
+ },
43
+ transformError: (error) => {
44
+ return error instanceof Error ? error.message : String(error);
45
+ },
46
+ });
31
47
 
48
+ /**
49
+ * Image-to-Video generation hook
50
+ * Manages generation state with validation and error handling
51
+ */
32
52
  export function useGeneration(options: UseGenerationOptions): UseGenerationReturn {
33
53
  const { formState, callbacks } = options;
34
54
 
35
- const [generationState, setGenerationState] = useState<ImageToVideoGenerationState>(
36
- INITIAL_GENERATION_STATE
37
- );
38
-
39
- const abortControllerRef = useRef<AbortController | null>(null);
40
- const isMountedRef = useRef(true);
41
-
42
- // Cleanup on unmount
43
- useEffect(() => {
44
- isMountedRef.current = true;
45
- return () => {
46
- isMountedRef.current = false;
47
- abortControllerRef.current?.abort();
48
- };
49
- }, []);
50
-
51
- // Stabilize callbacks to prevent unnecessary re-renders
52
- const onErrorRef = useRef(callbacks.onError);
53
- const onGenerateRef = useRef(callbacks.onGenerate);
54
-
55
- useEffect(() => {
56
- onErrorRef.current = callbacks.onError;
57
- onGenerateRef.current = callbacks.onGenerate;
58
- }, [callbacks.onError, callbacks.onGenerate]);
59
-
60
- const setProgress = useCallback((progress: number) => {
61
- if (!isMountedRef.current) return;
62
- setGenerationState((prev) => ({ ...prev, progress }));
63
- }, []);
64
-
65
- const setError = useCallback((error: string | null) => {
66
- if (!isMountedRef.current) return;
67
- setGenerationState((prev) => ({ ...prev, error, isGenerating: false }));
68
- }, []);
69
-
70
- const handleGenerate = useCallback(async () => {
71
- if (formState.selectedImages.length === 0) {
72
- onErrorRef.current?.("No images selected");
73
- return;
74
- }
75
-
76
- // Create new AbortController for this generation
77
- abortControllerRef.current = new AbortController();
78
-
79
- setGenerationState({
80
- isGenerating: true,
81
- progress: 0,
82
- error: null,
83
- });
55
+ const {
56
+ generationState,
57
+ handleGenerate: baseHandleGenerate,
58
+ setProgress,
59
+ setError,
60
+ } = useImageToVideoGenerationInternal({
61
+ onError: callbacks.onError,
62
+ });
84
63
 
64
+ const handleGenerate = async () => {
65
+ await baseHandleGenerate(formState);
66
+ // Execute the actual generation via callbacks
85
67
  try {
86
- await onGenerateRef.current(formState);
87
-
88
- if (!isMountedRef.current || abortControllerRef.current.signal.aborted) return;
89
-
90
- setGenerationState((prev) => ({ ...prev, isGenerating: false, progress: 100 }));
68
+ await callbacks.onGenerate(formState);
91
69
  } catch (error) {
92
- if (!isMountedRef.current || abortControllerRef.current.signal.aborted) return;
93
-
94
70
  const errorMessage = error instanceof Error ? error.message : String(error);
95
- setGenerationState({
96
- isGenerating: false,
97
- progress: 0,
98
- error: errorMessage,
99
- });
100
- onErrorRef.current?.(errorMessage);
101
- } finally {
102
- abortControllerRef.current = null;
71
+ setError(errorMessage);
72
+ callbacks.onError?.(errorMessage);
103
73
  }
104
- }, [formState]);
74
+ };
105
75
 
106
76
  const isReady = useMemo(
107
77
  () => formState.selectedImages.length > 0 && !generationState.isGenerating,
@@ -1,14 +1,11 @@
1
1
  /**
2
2
  * Text-to-Image Form State Hook
3
3
  * Manages form state for text-to-image generation
4
+ * Now powered by generic form state factory
4
5
  */
5
6
 
6
- import { useState, useCallback, useMemo } from "react";
7
+ import { createFormStateHook } from "../../../../shared/hooks/factories";
7
8
  import type {
8
- AspectRatio,
9
- ImageSize,
10
- NumImages,
11
- OutputFormat,
12
9
  TextToImageFormState,
13
10
  TextToImageFormActions,
14
11
  TextToImageFormDefaults,
@@ -23,95 +20,51 @@ export interface UseFormStateReturn {
23
20
  actions: TextToImageFormActions;
24
21
  }
25
22
 
26
- function validateDefaults(defaults: TextToImageFormDefaults): asserts defaults is Required<TextToImageFormDefaults> {
27
- if (!defaults.aspectRatio) {
23
+ function validateDefaults(state: TextToImageFormState): void {
24
+ if (!state.aspectRatio) {
28
25
  throw new Error("useFormState: defaults.aspectRatio is required");
29
26
  }
30
- if (!defaults.size) {
27
+ if (!state.size) {
31
28
  throw new Error("useFormState: defaults.size is required");
32
29
  }
33
- if (!defaults.numImages) {
30
+ if (!state.numImages) {
34
31
  throw new Error("useFormState: defaults.numImages is required");
35
32
  }
36
- if (defaults.guidanceScale === undefined) {
33
+ if (state.guidanceScale === undefined) {
37
34
  throw new Error("useFormState: defaults.guidanceScale is required");
38
35
  }
39
- if (!defaults.outputFormat) {
36
+ if (!state.outputFormat) {
40
37
  throw new Error("useFormState: defaults.outputFormat is required");
41
38
  }
42
- if (!defaults.selectedStyle) {
39
+ if (!state.selectedStyle) {
43
40
  throw new Error("useFormState: defaults.selectedStyle is required");
44
41
  }
45
42
  }
46
43
 
47
- export function useFormState(options: UseFormStateOptions): UseFormStateReturn {
48
- const defaults = useMemo(() => {
49
- validateDefaults(options.defaults);
50
- return options.defaults;
51
- }, [options.defaults]);
52
-
53
- const [prompt, setPrompt] = useState("");
54
- const [aspectRatio, setAspectRatio] = useState<AspectRatio>(defaults.aspectRatio);
55
- const [size, setSize] = useState<ImageSize>(defaults.size);
56
- const [numImages, setNumImages] = useState<NumImages>(defaults.numImages);
57
- const [negativePrompt, setNegativePrompt] = useState("");
58
- const [guidanceScale, setGuidanceScale] = useState(defaults.guidanceScale);
59
- const [selectedModel, setSelectedModel] = useState<string | null>(null);
60
- const [outputFormat, setOutputFormat] = useState<OutputFormat>(defaults.outputFormat);
61
- const [selectedStyle, setSelectedStyle] = useState(defaults.selectedStyle);
62
-
63
- const reset = useCallback(() => {
64
- setPrompt("");
65
- setAspectRatio(defaults.aspectRatio);
66
- setSize(defaults.size);
67
- setNumImages(defaults.numImages);
68
- setNegativePrompt("");
69
- setGuidanceScale(defaults.guidanceScale);
70
- setSelectedModel(null);
71
- setOutputFormat(defaults.outputFormat);
72
- setSelectedStyle(defaults.selectedStyle);
73
- }, [defaults]);
74
-
75
- const state: TextToImageFormState = useMemo(
76
- () => ({
77
- prompt,
78
- aspectRatio,
79
- size,
80
- numImages,
81
- negativePrompt,
82
- guidanceScale,
83
- selectedModel,
84
- outputFormat,
85
- selectedStyle,
86
- }),
87
- [
88
- prompt,
89
- aspectRatio,
90
- size,
91
- numImages,
92
- negativePrompt,
93
- guidanceScale,
94
- selectedModel,
95
- outputFormat,
96
- selectedStyle,
97
- ]
98
- );
99
-
100
- const actions: TextToImageFormActions = useMemo(
101
- () => ({
102
- setPrompt,
103
- setAspectRatio,
104
- setSize,
105
- setNumImages,
106
- setNegativePrompt,
107
- setGuidanceScale,
108
- setSelectedModel,
109
- setOutputFormat,
110
- setSelectedStyle,
111
- reset,
112
- }),
113
- [reset]
114
- );
44
+ // Create the form state hook using the factory
45
+ const useTextToImageFormStateInternal = createFormStateHook<
46
+ TextToImageFormState,
47
+ TextToImageFormDefaults,
48
+ TextToImageFormActions
49
+ >({
50
+ createInitialState: (defaults) => ({
51
+ prompt: "",
52
+ aspectRatio: defaults.aspectRatio!,
53
+ size: defaults.size!,
54
+ numImages: defaults.numImages!,
55
+ negativePrompt: "",
56
+ guidanceScale: defaults.guidanceScale!,
57
+ selectedModel: null,
58
+ outputFormat: defaults.outputFormat!,
59
+ selectedStyle: defaults.selectedStyle!,
60
+ }),
61
+ validate: validateDefaults,
62
+ });
115
63
 
116
- return { state, actions };
64
+ /**
65
+ * Text-to-Image form state hook
66
+ * Manages all form fields for text-to-image generation
67
+ */
68
+ export function useFormState(options: UseFormStateOptions): UseFormStateReturn {
69
+ return useTextToImageFormStateInternal(options);
117
70
  }
@@ -28,20 +28,20 @@ export type {
28
28
 
29
29
  // Components
30
30
  export {
31
- GenerationProgressContent, GenerationProgressBar, PendingJobCard,
32
- PendingJobProgressBar, PendingJobCardActions, GenerationResultContent, ResultHeader,
31
+ GenerationProgressContent, PendingJobCard,
32
+ PendingJobCardActions, GenerationResultContent, ResultHeader,
33
33
  ResultImageCard, ResultStoryCard, ResultActions, DEFAULT_RESULT_CONFIG, PhotoStep,
34
34
  DualImagePicker, PromptInput, AIGenerationHero, ExamplePrompts, ModerationSummary,
35
35
  GenerateButton, ResultDisplay, AIGenerationResult, ErrorDisplay, FeatureHeader,
36
36
  AIGenScreenHeader, CreditBadge, PhotoUploadCard, SettingsSheet, StyleSelector,
37
37
  AspectRatioSelector, DurationSelector, GridSelector, StylePresetsGrid, AIGenerationForm,
38
- AIGenerationConfig, ModelSelector,
38
+ AIGenerationConfig, ModelSelector,
39
39
  createAspectRatioOptions, createDurationOptions, createStyleOptions, createStyleOptionsFromConfig,
40
40
  ASPECT_RATIO_IDS, COMMON_DURATIONS,
41
41
  } from "../presentation/components";
42
42
  export type {
43
- GenerationProgressContentProps, GenerationProgressBarProps, PendingJobCardProps, StatusLabels,
44
- PendingJobProgressBarProps, PendingJobCardActionsProps, GenerationResultData, GenerationResultContentProps,
43
+ GenerationProgressContentProps, PendingJobCardProps, StatusLabels,
44
+ PendingJobCardActionsProps, GenerationResultData, GenerationResultContentProps,
45
45
  ResultHeaderProps, ResultImageCardProps, ResultStoryCardProps, ResultActionsProps, ResultConfig,
46
46
  ResultHeaderConfig, ResultImageConfig, ResultStoryConfig, ResultActionsConfig, ResultLayoutConfig,
47
47
  ResultActionButton, PhotoStepProps, DualImagePickerProps, PromptInputProps, AIGenerationHeroProps,
package/src/index.ts CHANGED
@@ -8,6 +8,9 @@ export * from "./exports/infrastructure";
8
8
  export * from "./exports/presentation";
9
9
  export * from "./exports/features";
10
10
 
11
+ // Shared Utilities and Components
12
+ export * from "./shared";
13
+
11
14
  // Creations Domain
12
15
  export * from "./domains/creations";
13
16
 
@@ -11,7 +11,7 @@ import { ProgressCloseButton } from "./ProgressCloseButton";
11
11
  import { ProgressHeader } from "./ProgressHeader";
12
12
  import { ProgressHint } from "./ProgressHint";
13
13
  import { ProgressDismissButton } from "./ProgressDismissButton";
14
- import { GenerationProgressBar } from "./GenerationProgressBar";
14
+ import { ProgressBar } from "../../shared/components/common";
15
15
  import { generationProgressContentStyles } from "./GenerationProgressContent.styles";
16
16
  import type { GenerationProgressContentProps } from "./GenerationProgressContent.types";
17
17
 
@@ -56,11 +56,14 @@ export const GenerationProgressContent: React.FC<
56
56
  textColor={textColor}
57
57
  />
58
58
 
59
- <GenerationProgressBar
59
+ <ProgressBar
60
60
  progress={progress}
61
+ showPercentage={true}
61
62
  textColor={tokens.colors.primary}
62
63
  progressColor={progressColor}
63
64
  backgroundColor={progressBackgroundColor}
65
+ height={8}
66
+ marginBottom={16}
64
67
  />
65
68
 
66
69
  <ProgressHint
@@ -7,7 +7,7 @@ import React from "react";
7
7
  import { View, StyleSheet } from "react-native";
8
8
  import { AtomicText, AtomicSpinner, useAppDesignTokens } from "@umituz/react-native-design-system";
9
9
  import type { BackgroundJob } from "../../domains/background/domain/entities/job.types";
10
- import { PendingJobProgressBar } from "./PendingJobProgressBar";
10
+ import { ProgressBar } from "../../shared/components/common";
11
11
  import { PendingJobCardActions } from "./PendingJobCardActions";
12
12
 
13
13
  export interface StatusLabels {
@@ -110,7 +110,14 @@ export function PendingJobCard<TInput = unknown, TResult = unknown>({
110
110
  <AtomicText style={styles.statusText}>
111
111
  {statusText}
112
112
  </AtomicText>
113
- {!isFailed && <PendingJobProgressBar progress={job.progress} />}
113
+ {!isFailed && (
114
+ <ProgressBar
115
+ progress={job.progress}
116
+ showPercentage={false}
117
+ height={4}
118
+ marginBottom={0}
119
+ />
120
+ )}
114
121
  </View>
115
122
  {renderActions ? (
116
123
  renderActions(job)
@@ -50,17 +50,18 @@ import { GenerationProgressContent } from '@umituz/react-native-ai-generation-co
50
50
  />
51
51
  ```
52
52
 
53
- ### GenerationProgressBar
53
+ ### ProgressBar
54
54
 
55
- Progress bar component:
55
+ Progress bar component (from shared utilities):
56
56
 
57
57
  ```tsx
58
- import { GenerationProgressBar } from '@umituz/react-native-ai-generation-content';
58
+ import { ProgressBar } from '@umituz/react-native-ai-generation-content';
59
59
 
60
- <GenerationProgressBar
60
+ <ProgressBar
61
61
  progress={progress}
62
+ showPercentage={true}
62
63
  height={8}
63
- color="#4CAF50"
64
+ progressColor="#4CAF50"
64
65
  />
65
66
  ```
66
67