@sudobility/devops-components-rn 1.0.0 → 1.0.1

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 (63) hide show
  1. package/dist/AlertDialog.d.ts.map +1 -1
  2. package/dist/ApiPlayground.d.ts.map +1 -1
  3. package/dist/ApiReference.d.ts.map +1 -1
  4. package/dist/AuditLog.d.ts +26 -4
  5. package/dist/AuditLog.d.ts.map +1 -1
  6. package/dist/BodyMetrics.d.ts.map +1 -1
  7. package/dist/BuildLog.d.ts +16 -5
  8. package/dist/BuildLog.d.ts.map +1 -1
  9. package/dist/ChangelogDisplay.d.ts.map +1 -1
  10. package/dist/CodePlayground.d.ts.map +1 -1
  11. package/dist/ConflictResolver.d.ts.map +1 -1
  12. package/dist/DealPipeline.d.ts.map +1 -1
  13. package/dist/DeploymentStatus.d.ts +11 -4
  14. package/dist/DeploymentStatus.d.ts.map +1 -1
  15. package/dist/DriverLog.d.ts.map +1 -1
  16. package/dist/MemoryUsage.d.ts.map +1 -1
  17. package/dist/MetricsGrid.d.ts +12 -19
  18. package/dist/MetricsGrid.d.ts.map +1 -1
  19. package/dist/PipelineView.d.ts +21 -5
  20. package/dist/PipelineView.d.ts.map +1 -1
  21. package/dist/RegressionTest.d.ts.map +1 -1
  22. package/dist/SystemStatusIndicator.d.ts +9 -8
  23. package/dist/SystemStatusIndicator.d.ts.map +1 -1
  24. package/dist/TestResult.d.ts.map +1 -1
  25. package/dist/TestRunner.d.ts.map +1 -1
  26. package/dist/WebhookLogger.d.ts.map +1 -1
  27. package/dist/WorkflowBuilder.d.ts.map +1 -1
  28. package/dist/WorkflowTemplate.d.ts.map +1 -1
  29. package/dist/XmlParser.d.ts.map +1 -1
  30. package/dist/{index.cjs.js → index.cjs} +634 -614
  31. package/dist/index.cjs.map +1 -0
  32. package/dist/index.d.ts +6 -27
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/{index.esm.js → index.mjs} +637 -617
  35. package/dist/index.mjs.map +1 -0
  36. package/package.json +8 -15
  37. package/src/AlertDialog.tsx +21 -16
  38. package/src/ApiPlayground.tsx +7 -3
  39. package/src/ApiReference.tsx +6 -2
  40. package/src/AuditLog.tsx +244 -21
  41. package/src/BodyMetrics.tsx +6 -2
  42. package/src/BuildLog.tsx +132 -26
  43. package/src/ChangelogDisplay.tsx +6 -2
  44. package/src/CodePlayground.tsx +7 -3
  45. package/src/ConflictResolver.tsx +7 -3
  46. package/src/DealPipeline.tsx +6 -2
  47. package/src/DeploymentStatus.tsx +159 -25
  48. package/src/DriverLog.tsx +4 -2
  49. package/src/MemoryUsage.tsx +6 -2
  50. package/src/MetricsGrid.tsx +99 -94
  51. package/src/PipelineView.tsx +225 -26
  52. package/src/RegressionTest.tsx +6 -2
  53. package/src/SystemStatusIndicator.tsx +70 -47
  54. package/src/TestResult.tsx +6 -2
  55. package/src/TestRunner.tsx +7 -3
  56. package/src/WebhookLogger.tsx +6 -2
  57. package/src/WorkflowBuilder.tsx +7 -3
  58. package/src/WorkflowTemplate.tsx +7 -3
  59. package/src/XmlParser.tsx +4 -2
  60. package/src/index.ts +41 -30
  61. package/src/nativewind.d.ts +3 -0
  62. package/dist/index.cjs.js.map +0 -1
  63. package/dist/index.esm.js.map +0 -1
@@ -1,32 +1,166 @@
1
1
  import React from 'react';
2
- import { Text, Pressable, type ViewProps } from 'react-native';
3
- import { cn } from '@sudobility/components-rn';
2
+ import { View, Text, Pressable } from 'react-native';
3
+ import { cn, Card } from '@sudobility/components-rn';
4
4
 
5
- export interface DeploymentStatusProps extends ViewProps {
6
- disabled?: boolean;
5
+ export type DeploymentState =
6
+ | 'pending'
7
+ | 'building'
8
+ | 'deploying'
9
+ | 'success'
10
+ | 'failed'
11
+ | 'cancelled';
12
+
13
+ export interface DeploymentStatusProps {
14
+ state: DeploymentState;
15
+ environment: string;
16
+ version: string;
17
+ timestamp: Date;
18
+ commitHash?: string;
19
+ commitMessage?: string;
20
+ duration?: number;
7
21
  onPress?: () => void;
8
- children?: React.ReactNode;
22
+ className?: string;
9
23
  }
10
24
 
25
+ const stateConfig: Record<
26
+ DeploymentState,
27
+ {
28
+ color: string;
29
+ bgColor: string;
30
+ darkBgColor: string;
31
+ label: string;
32
+ icon: string;
33
+ }
34
+ > = {
35
+ pending: {
36
+ color: 'text-gray-600 dark:text-gray-400',
37
+ bgColor: 'bg-gray-100',
38
+ darkBgColor: 'dark:bg-gray-800',
39
+ label: 'Pending',
40
+ icon: '⏳',
41
+ },
42
+ building: {
43
+ color: 'text-blue-600 dark:text-blue-400',
44
+ bgColor: 'bg-blue-100',
45
+ darkBgColor: 'dark:bg-blue-900',
46
+ label: 'Building',
47
+ icon: '🔨',
48
+ },
49
+ deploying: {
50
+ color: 'text-purple-600 dark:text-purple-400',
51
+ bgColor: 'bg-purple-100',
52
+ darkBgColor: 'dark:bg-purple-900',
53
+ label: 'Deploying',
54
+ icon: '🚀',
55
+ },
56
+ success: {
57
+ color: 'text-green-600 dark:text-green-400',
58
+ bgColor: 'bg-green-100',
59
+ darkBgColor: 'dark:bg-green-900',
60
+ label: 'Success',
61
+ icon: '✓',
62
+ },
63
+ failed: {
64
+ color: 'text-red-600 dark:text-red-400',
65
+ bgColor: 'bg-red-100',
66
+ darkBgColor: 'dark:bg-red-900',
67
+ label: 'Failed',
68
+ icon: '✗',
69
+ },
70
+ cancelled: {
71
+ color: 'text-orange-600 dark:text-orange-400',
72
+ bgColor: 'bg-orange-100',
73
+ darkBgColor: 'dark:bg-orange-900',
74
+ label: 'Cancelled',
75
+ icon: '⊘',
76
+ },
77
+ };
78
+
79
+ const formatDuration = (seconds: number): string => {
80
+ if (seconds < 60) return `${seconds}s`;
81
+ const minutes = Math.floor(seconds / 60);
82
+ const remainingSeconds = seconds % 60;
83
+ if (minutes < 60) return `${minutes}m ${remainingSeconds}s`;
84
+ const hours = Math.floor(minutes / 60);
85
+ const remainingMinutes = minutes % 60;
86
+ return `${hours}h ${remainingMinutes}m`;
87
+ };
88
+
11
89
  export const DeploymentStatus: React.FC<DeploymentStatusProps> = ({
12
- className,
13
- children,
14
- disabled = false,
90
+ state,
91
+ environment,
92
+ version,
93
+ timestamp,
94
+ commitHash,
95
+ commitMessage,
96
+ duration,
15
97
  onPress,
16
- ...props
17
- }) => (
18
- <Pressable
19
- onPress={disabled ? undefined : onPress}
20
- disabled={disabled}
21
- accessibilityRole="button"
22
- accessibilityLabel="Deployment Status"
23
- className={cn(
24
- 'p-4 rounded-lg border bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700',
25
- disabled && 'opacity-50',
26
- className
27
- )}
28
- {...props}
29
- >
30
- {children || <Text className="text-gray-900 dark:text-white">DeploymentStatus Component</Text>}
31
- </Pressable>
32
- );
98
+ className,
99
+ }) => {
100
+ const config = stateConfig[state];
101
+
102
+ const content = (
103
+ <Card className={cn('p-4', className)}>
104
+ <View className='flex-row items-start justify-between'>
105
+ <View className='flex-1'>
106
+ <View className='flex-row items-center'>
107
+ <View
108
+ className={cn(
109
+ 'px-2 py-1 rounded-md mr-2',
110
+ config.bgColor,
111
+ config.darkBgColor
112
+ )}
113
+ >
114
+ <Text className={cn('text-xs font-medium', config.color)}>
115
+ {config.icon} {config.label}
116
+ </Text>
117
+ </View>
118
+ <View className='bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-md'>
119
+ <Text className='text-xs font-medium text-gray-700 dark:text-gray-300'>
120
+ {environment}
121
+ </Text>
122
+ </View>
123
+ </View>
124
+ <Text className='mt-2 text-base font-semibold text-gray-900 dark:text-gray-100'>
125
+ {version}
126
+ </Text>
127
+ {commitHash && (
128
+ <Text className='mt-1 text-sm font-mono text-gray-600 dark:text-gray-400'>
129
+ {commitHash.substring(0, 7)}
130
+ </Text>
131
+ )}
132
+ {commitMessage && (
133
+ <Text
134
+ className='mt-1 text-sm text-gray-600 dark:text-gray-400'
135
+ numberOfLines={2}
136
+ >
137
+ {commitMessage}
138
+ </Text>
139
+ )}
140
+ </View>
141
+ </View>
142
+ <View className='flex-row items-center justify-between mt-3 pt-3 border-t border-gray-200 dark:border-gray-700'>
143
+ <Text className='text-xs text-gray-500 dark:text-gray-500'>
144
+ {timestamp.toLocaleString()}
145
+ </Text>
146
+ {duration !== undefined && (
147
+ <Text className='text-xs text-gray-500 dark:text-gray-500'>
148
+ Duration: {formatDuration(duration)}
149
+ </Text>
150
+ )}
151
+ </View>
152
+ </Card>
153
+ );
154
+
155
+ if (onPress) {
156
+ return (
157
+ <Pressable onPress={onPress} accessibilityRole='button'>
158
+ {content}
159
+ </Pressable>
160
+ );
161
+ }
162
+
163
+ return content;
164
+ };
165
+
166
+ export default DeploymentStatus;
package/src/DriverLog.tsx CHANGED
@@ -19,9 +19,11 @@ export const DriverLog: React.FC<DriverLogProps> = ({
19
19
  disabled && 'opacity-50',
20
20
  className
21
21
  )}
22
- accessibilityLabel="Driver Log"
22
+ accessibilityLabel='Driver Log'
23
23
  {...props}
24
24
  >
25
- {children || <Text className="text-gray-900 dark:text-white">DriverLog Component</Text>}
25
+ {children || (
26
+ <Text className='text-gray-900 dark:text-white'>DriverLog Component</Text>
27
+ )}
26
28
  </View>
27
29
  );
@@ -19,9 +19,13 @@ export const MemoryUsage: React.FC<MemoryUsageProps> = ({
19
19
  disabled && 'opacity-50',
20
20
  className
21
21
  )}
22
- accessibilityLabel="Memory Usage"
22
+ accessibilityLabel='Memory Usage'
23
23
  {...props}
24
24
  >
25
- {children || <Text className="text-gray-900 dark:text-white">MemoryUsage Component</Text>}
25
+ {children || (
26
+ <Text className='text-gray-900 dark:text-white'>
27
+ MemoryUsage Component
28
+ </Text>
29
+ )}
26
30
  </View>
27
31
  );
@@ -1,115 +1,120 @@
1
1
  import React from 'react';
2
- import { View, Text, FlatList, type ViewProps } from 'react-native';
3
- import { cn } from '@sudobility/components-rn';
2
+ import { View, Text, Pressable } from 'react-native';
3
+ import { cn, Card } from '@sudobility/components-rn';
4
4
 
5
- type MetricColor = 'blue' | 'green' | 'purple' | 'orange' | 'pink' | 'gray';
6
-
7
- export interface MetricItem {
8
- value: string | number;
5
+ export interface Metric {
6
+ id: string;
9
7
  label: string;
10
- color?: MetricColor;
8
+ value: number | string;
9
+ unit?: string;
10
+ change?: number;
11
+ changeLabel?: string;
11
12
  icon?: React.ReactNode;
12
- trend?: {
13
- direction: 'up' | 'down';
14
- value: string;
15
- };
16
13
  }
17
14
 
18
- export interface MetricsGridProps extends ViewProps {
19
- title?: string;
20
- description?: string;
21
- metrics: MetricItem[];
22
- columns?: 2 | 3 | 4;
15
+ export interface MetricsGridProps {
16
+ metrics: Metric[];
17
+ columns?: 1 | 2 | 3 | 4;
18
+ onMetricPress?: (metric: Metric) => void;
19
+ className?: string;
23
20
  }
24
21
 
25
- const colorClasses: Record<MetricColor, string> = {
26
- blue: 'text-blue-600 dark:text-blue-400',
27
- green: 'text-green-600 dark:text-green-400',
28
- purple: 'text-purple-600 dark:text-purple-400',
29
- orange: 'text-orange-600 dark:text-orange-400',
30
- pink: 'text-pink-600 dark:text-pink-400',
31
- gray: 'text-gray-600 dark:text-gray-400',
22
+ const formatChange = (change: number): string => {
23
+ const sign = change >= 0 ? '+' : '';
24
+ return sign + change.toFixed(1) + '%';
32
25
  };
33
26
 
34
- interface MetricCardProps {
35
- metric: MetricItem;
36
- }
37
-
38
- const MetricCard: React.FC<MetricCardProps> = ({ metric }) => {
39
- const colorClass = metric.color ? colorClasses[metric.color] : colorClasses.blue;
40
-
41
- return (
42
- <View className="bg-white dark:bg-gray-800 rounded-xl p-6 border border-gray-200 dark:border-gray-700 items-center mb-4 mx-2">
43
- {metric.icon && (
44
- <View className={cn('mb-4', colorClass)}>{metric.icon}</View>
45
- )}
46
-
47
- <View className="gap-2 items-center">
48
- <Text className={cn('text-3xl font-bold', colorClass)}>
49
- {metric.value}
50
- </Text>
51
-
52
- <Text className="text-gray-600 dark:text-gray-400 font-medium">
53
- {metric.label}
54
- </Text>
55
-
56
- {metric.trend && (
57
- <Text
58
- className={cn(
59
- 'text-sm font-semibold',
60
- metric.trend.direction === 'up'
61
- ? 'text-green-600 dark:text-green-400'
62
- : 'text-red-600 dark:text-red-400'
63
- )}
64
- >
65
- {metric.trend.direction === 'up' ? '↑' : '↓'} {metric.trend.value}
66
- </Text>
67
- )}
68
- </View>
69
- </View>
70
- );
71
- };
72
-
73
- /**
74
- * MetricsGrid component for React Native
75
- * Grid display of metric cards
76
- */
77
27
  export const MetricsGrid: React.FC<MetricsGridProps> = ({
78
- title,
79
- description,
80
28
  metrics,
81
29
  columns = 2,
30
+ onMetricPress,
82
31
  className,
83
- ...props
84
32
  }) => {
33
+ const columnWidthClass = {
34
+ 1: 'w-full',
35
+ 2: 'w-1/2',
36
+ 3: 'w-1/3',
37
+ 4: 'w-1/4',
38
+ }[columns];
39
+
85
40
  return (
86
- <View className={cn('py-8 px-4', className)} {...props}>
87
- {(title || description) && (
88
- <View className="items-center mb-8">
89
- {title && (
90
- <Text className="text-2xl font-bold text-gray-900 dark:text-white mb-4 text-center">
91
- {title}
92
- </Text>
93
- )}
94
- {description && (
95
- <Text className="text-lg text-gray-600 dark:text-gray-300 text-center max-w-lg">
96
- {description}
97
- </Text>
98
- )}
99
- </View>
100
- )}
41
+ <View className={cn('flex-row flex-wrap -m-1', className)}>
42
+ {metrics.map(metric => {
43
+ const content = (
44
+ <Card className='p-4 m-1 flex-1'>
45
+ <View className='flex-row items-start justify-between'>
46
+ <View className='flex-1'>
47
+ <Text className='text-sm text-gray-600 dark:text-gray-400 mb-1'>
48
+ {metric.label}
49
+ </Text>
50
+ <View className='flex-row items-baseline'>
51
+ <Text className='text-2xl font-bold text-gray-900 dark:text-gray-100'>
52
+ {metric.value}
53
+ </Text>
54
+ {metric.unit && (
55
+ <Text className='text-sm text-gray-500 dark:text-gray-500 ml-1'>
56
+ {metric.unit}
57
+ </Text>
58
+ )}
59
+ </View>
60
+ {metric.change !== undefined && (
61
+ <View className='flex-row items-center mt-2'>
62
+ <View
63
+ className={cn(
64
+ 'px-1.5 py-0.5 rounded',
65
+ metric.change >= 0
66
+ ? 'bg-green-100 dark:bg-green-900'
67
+ : 'bg-red-100 dark:bg-red-900'
68
+ )}
69
+ >
70
+ <Text
71
+ className={cn(
72
+ 'text-xs font-medium',
73
+ metric.change >= 0
74
+ ? 'text-green-700 dark:text-green-300'
75
+ : 'text-red-700 dark:text-red-300'
76
+ )}
77
+ >
78
+ {formatChange(metric.change)}
79
+ </Text>
80
+ </View>
81
+ {metric.changeLabel && (
82
+ <Text className='text-xs text-gray-500 dark:text-gray-500 ml-2'>
83
+ {metric.changeLabel}
84
+ </Text>
85
+ )}
86
+ </View>
87
+ )}
88
+ </View>
89
+ {metric.icon && <View className='ml-2'>{metric.icon}</View>}
90
+ </View>
91
+ </Card>
92
+ );
93
+
94
+ if (onMetricPress) {
95
+ return (
96
+ <View key={metric.id} className={columnWidthClass}>
97
+ <Pressable
98
+ onPress={() => onMetricPress(metric)}
99
+ accessibilityRole='button'
100
+ accessibilityLabel={
101
+ metric.label + ': ' + metric.value + (metric.unit || '')
102
+ }
103
+ >
104
+ {content}
105
+ </Pressable>
106
+ </View>
107
+ );
108
+ }
101
109
 
102
- <FlatList
103
- data={metrics}
104
- keyExtractor={(_, index) => index.toString()}
105
- numColumns={columns > 2 ? 2 : columns}
106
- renderItem={({ item }) => (
107
- <View className="flex-1">
108
- <MetricCard metric={item} />
110
+ return (
111
+ <View key={metric.id} className={columnWidthClass}>
112
+ {content}
109
113
  </View>
110
- )}
111
- scrollEnabled={false}
112
- />
114
+ );
115
+ })}
113
116
  </View>
114
117
  );
115
118
  };
119
+
120
+ export default MetricsGrid;