agent-facets 0.2.2 → 0.3.3

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 (59) hide show
  1. package/bin/facet +181 -0
  2. package/bin/package.json +3 -0
  3. package/package.json +17 -37
  4. package/postinstall.mjs +210 -0
  5. package/.package.json.bak +0 -44
  6. package/.turbo/turbo-build.log +0 -3
  7. package/CHANGELOG.md +0 -85
  8. package/bunfig.toml +0 -2
  9. package/dist/facet +0 -0
  10. package/src/__tests__/cli.test.ts +0 -195
  11. package/src/__tests__/create-build.test.ts +0 -227
  12. package/src/__tests__/edit-integration.test.ts +0 -171
  13. package/src/__tests__/resolve-dir.test.ts +0 -95
  14. package/src/commands/build.ts +0 -58
  15. package/src/commands/create/index.ts +0 -76
  16. package/src/commands/create/types.ts +0 -9
  17. package/src/commands/create/wizard.tsx +0 -75
  18. package/src/commands/create-scaffold.ts +0 -184
  19. package/src/commands/edit/index.ts +0 -144
  20. package/src/commands/edit/wizard.tsx +0 -74
  21. package/src/commands/resolve-dir.ts +0 -98
  22. package/src/commands.ts +0 -40
  23. package/src/help.ts +0 -43
  24. package/src/index.ts +0 -10
  25. package/src/run.ts +0 -82
  26. package/src/suggest.ts +0 -35
  27. package/src/tui/components/asset-description.tsx +0 -17
  28. package/src/tui/components/asset-field-picker.tsx +0 -78
  29. package/src/tui/components/asset-inline-input.tsx +0 -91
  30. package/src/tui/components/asset-item.tsx +0 -44
  31. package/src/tui/components/asset-section.tsx +0 -191
  32. package/src/tui/components/button.tsx +0 -92
  33. package/src/tui/components/editable-field.tsx +0 -172
  34. package/src/tui/components/exit-toast.tsx +0 -20
  35. package/src/tui/components/reconciliation-item.tsx +0 -129
  36. package/src/tui/components/stage-row.tsx +0 -45
  37. package/src/tui/components/version-selector.tsx +0 -79
  38. package/src/tui/context/focus-mode-context.ts +0 -36
  39. package/src/tui/context/focus-order-context.ts +0 -68
  40. package/src/tui/context/form-state-context.ts +0 -260
  41. package/src/tui/editor.ts +0 -40
  42. package/src/tui/gradient.ts +0 -1
  43. package/src/tui/hooks/use-exit-keys.ts +0 -75
  44. package/src/tui/hooks/use-navigation-keys.ts +0 -34
  45. package/src/tui/layouts/wizard-layout.tsx +0 -41
  46. package/src/tui/theme.ts +0 -1
  47. package/src/tui/views/build/build-view.tsx +0 -152
  48. package/src/tui/views/create/confirm-view.tsx +0 -74
  49. package/src/tui/views/create/create-view.tsx +0 -158
  50. package/src/tui/views/create/wizard.tsx +0 -97
  51. package/src/tui/views/edit/edit-confirm-view.tsx +0 -93
  52. package/src/tui/views/edit/edit-types.ts +0 -34
  53. package/src/tui/views/edit/edit-view.tsx +0 -140
  54. package/src/tui/views/edit/manifest-to-form.ts +0 -38
  55. package/src/tui/views/edit/reconciliation-view.tsx +0 -170
  56. package/src/tui/views/edit/use-edit-session.ts +0 -125
  57. package/src/tui/views/edit/wizard.tsx +0 -129
  58. package/src/version.ts +0 -3
  59. package/tsconfig.json +0 -4
@@ -1,191 +0,0 @@
1
- import { Box, Text } from 'ink'
2
- import { useState } from 'react'
3
- import { useFocusMode } from '../context/focus-mode-context.ts'
4
- import { useFocusOrder } from '../context/focus-order-context.ts'
5
- import type { AssetSectionKey } from '../context/form-state-context.ts'
6
- import { useFormState } from '../context/form-state-context.ts'
7
- import { AssetDescription, truncateDescription } from './asset-description.tsx'
8
- import type { AssetField } from './asset-field-picker.tsx'
9
- import { AssetFieldPicker } from './asset-field-picker.tsx'
10
- import { AssetInlineInput } from './asset-inline-input.tsx'
11
- import { AssetItem } from './asset-item.tsx'
12
- import { Button } from './button.tsx'
13
-
14
- export function AssetSection({
15
- section,
16
- label,
17
- defaultName,
18
- dimmed,
19
- validate,
20
- onEditDescription,
21
- }: {
22
- section: AssetSectionKey
23
- label: string
24
- defaultName?: string
25
- dimmed?: boolean
26
- validate?: (value: string) => string | undefined
27
- onEditDescription?: (section: AssetSectionKey, name: string) => void
28
- }) {
29
- const { form, addAsset, removeAsset, renameAsset, setAssetAdding, setAssetEditing } = useFormState()
30
- const { items, descriptions, editing, adding } = form.assets[section]
31
- const { setMode } = useFocusMode()
32
- const { focusedId, focus } = useFocusOrder()
33
- const [inputValue, setInputValue] = useState('')
34
- const [error, setError] = useState('')
35
- const [selectedItem, setSelectedItem] = useState<string | null>(null)
36
-
37
- const startAdding = () => {
38
- setAssetAdding(section, true)
39
- setInputValue('')
40
- setError('')
41
- setMode('field-revision')
42
- }
43
-
44
- const startEditing = (name: string) => {
45
- setAssetEditing(section, name)
46
- setInputValue(name)
47
- setError('')
48
- setMode('field-revision')
49
- }
50
-
51
- const closeInput = (focusTarget?: string | false) => {
52
- setAssetAdding(section, false)
53
- setAssetEditing(section, undefined)
54
- setInputValue('')
55
- setError('')
56
- if (focusTarget !== false) {
57
- setMode('form-navigation')
58
- focus(focusTarget ?? `add-${section}`)
59
- }
60
- }
61
-
62
- const handleFieldChoice = (name: string, field: AssetField) => {
63
- setSelectedItem(null)
64
- if (field === 'name') {
65
- startEditing(name)
66
- } else {
67
- onEditDescription?.(section, name)
68
- }
69
- }
70
-
71
- const handleRemove = (name: string) => {
72
- const index = items.indexOf(name)
73
- removeAsset(section, name)
74
-
75
- if (index < items.length - 1) {
76
- focus(`item-${section}-${index}`)
77
- } else if (index > 0) {
78
- focus(`item-${section}-${index - 1}`)
79
- } else {
80
- focus(`add-${section}`)
81
- }
82
- }
83
-
84
- return (
85
- <Box flexDirection="column" gap={0}>
86
- <Box gap={1}>
87
- <Text bold dimColor={dimmed}>
88
- {label}
89
- </Text>
90
- {items.length === 0 && !adding && <Text dimColor>(none)</Text>}
91
- </Box>
92
-
93
- {items.map((item, i) => {
94
- const itemId = `item-${section}-${i}`
95
- const isFocusedItem = focusedId === itemId
96
- const description = descriptions[item] ?? `A ${item} ${section}`
97
-
98
- // Field picker (entered via ↓ during name editing)
99
- if (selectedItem === item) {
100
- return (
101
- <AssetFieldPicker
102
- key={itemId}
103
- name={item}
104
- description={truncateDescription(description)}
105
- initialField="description"
106
- onChoose={(field) => handleFieldChoice(item, field)}
107
- onCancel={() => {
108
- setSelectedItem(null)
109
- setMode('form-navigation')
110
- focus(itemId)
111
- }}
112
- />
113
- )
114
- }
115
-
116
- // Inline name editing
117
- if (editing === item) {
118
- return (
119
- <Box key={itemId} flexDirection="column">
120
- <AssetInlineInput
121
- id={itemId}
122
- value={inputValue}
123
- placeholder={item}
124
- error={error}
125
- isFocused={isFocusedItem}
126
- onChange={setInputValue}
127
- validate={validate}
128
- onError={setError}
129
- onSubmit={(newName) => {
130
- renameAsset(section, item, newName)
131
- closeInput(itemId)
132
- }}
133
- onCancel={() => closeInput(itemId)}
134
- onDownArrow={() => {
135
- closeInput(false)
136
- setSelectedItem(item)
137
- }}
138
- />
139
- <AssetDescription description={description} />
140
- </Box>
141
- )
142
- }
143
-
144
- // Normal display (level 1)
145
- return (
146
- <Box key={itemId} flexDirection="column">
147
- <AssetItem
148
- id={itemId}
149
- name={item}
150
- isFocused={isFocusedItem}
151
- onEdit={() => startEditing(item)}
152
- onRemove={() => handleRemove(item)}
153
- />
154
- <AssetDescription description={description} />
155
- </Box>
156
- )
157
- })}
158
-
159
- {adding ? (
160
- <AssetInlineInput
161
- id={`add-${section}`}
162
- value={inputValue}
163
- placeholder={defaultName}
164
- error={error}
165
- isFocused={focusedId === `add-${section}`}
166
- onChange={setInputValue}
167
- validate={validate}
168
- onError={setError}
169
- onSubmit={(name) => {
170
- addAsset(section, name)
171
- closeInput()
172
- }}
173
- onCancel={closeInput}
174
- />
175
- ) : (
176
- <Box marginLeft={2}>
177
- <Button
178
- id={`add-${section}`}
179
- label="+ Add"
180
- hint={
181
- <Text dimColor>
182
- <Text>Enter</Text> to add
183
- </Text>
184
- }
185
- onPress={startAdding}
186
- />
187
- </Box>
188
- )}
189
- </Box>
190
- )
191
- }
@@ -1,92 +0,0 @@
1
- import { Box, Text, useInput } from 'ink'
2
- import Gradient from 'ink-gradient'
3
- import type { ReactNode } from 'react'
4
- import { useEffect, useState } from 'react'
5
- import { useFocusOrder } from '../context/focus-order-context.ts'
6
- import { GRADIENT_STOPS, getAnimatedGradient } from '../gradient.ts'
7
- import { THEME } from '../theme.ts'
8
-
9
- const ANIMATION_INTERVAL_MS = 75
10
-
11
- export function Button({
12
- id,
13
- label,
14
- hint,
15
- onPress,
16
- disabled,
17
- color,
18
- gradient: showGradient,
19
- animateGradient,
20
- }: {
21
- id: string
22
- label: string
23
- hint?: ReactNode
24
- onPress: () => void
25
- disabled?: boolean
26
- color?: string
27
- autoFocus?: boolean
28
- gradient?: boolean
29
- animateGradient?: boolean
30
- }) {
31
- const { focusedId } = useFocusOrder()
32
- const isFocused = focusedId === id && !disabled
33
- const [offset, setOffset] = useState(0)
34
-
35
- useEffect(() => {
36
- if (!animateGradient) return
37
- const interval = setInterval(() => {
38
- setOffset((prev) => (prev + 1) % GRADIENT_STOPS.length)
39
- }, ANIMATION_INTERVAL_MS)
40
- return () => clearInterval(interval)
41
- }, [animateGradient])
42
-
43
- useInput(
44
- (_input, key) => {
45
- if (key.return) {
46
- onPress()
47
- }
48
- },
49
- { isActive: isFocused },
50
- )
51
-
52
- const prefix = isFocused ? '▸ ' : ' '
53
-
54
- const focusHint = isFocused && hint ? <Text> {hint}</Text> : null
55
-
56
- if (disabled) {
57
- return (
58
- <Box gap={0}>
59
- <Text color="gray" dimColor>
60
- {prefix}
61
- {label}
62
- </Text>
63
- </Box>
64
- )
65
- }
66
-
67
- if (showGradient) {
68
- const colors = animateGradient ? getAnimatedGradient(offset) : [...THEME.gradient]
69
-
70
- return (
71
- <Box gap={0}>
72
- <Gradient colors={colors}>
73
- <Text bold>
74
- {prefix}
75
- {label}
76
- </Text>
77
- </Gradient>
78
- {focusHint}
79
- </Box>
80
- )
81
- }
82
-
83
- return (
84
- <Box gap={0}>
85
- <Text color={isFocused ? (color ?? THEME.primary) : undefined} bold={isFocused}>
86
- {prefix}
87
- {label}
88
- </Text>
89
- {focusHint}
90
- </Box>
91
- )
92
- }
@@ -1,172 +0,0 @@
1
- import { Box, Text, useInput } from 'ink'
2
- import TextInput from 'ink-text-input'
3
- import { useCallback, useEffect, useState } from 'react'
4
- import { useFocusMode } from '../context/focus-mode-context.ts'
5
- import { useFocusOrder } from '../context/focus-order-context.ts'
6
- import type { RequiredFieldKey } from '../context/form-state-context.ts'
7
- import { useFormState } from '../context/form-state-context.ts'
8
- import { THEME } from '../theme.ts'
9
-
10
- export function EditableField({
11
- field,
12
- label,
13
- placeholder,
14
- hint,
15
- defaultValue,
16
- dimmed,
17
- validate,
18
- onConfirm,
19
- }: {
20
- field: RequiredFieldKey
21
- label: string
22
- placeholder?: string
23
- hint?: string
24
- defaultValue?: string
25
- dimmed?: boolean
26
- validate?: (value: string) => string | undefined
27
- onConfirm?: () => void
28
- }) {
29
- const id = `field-${field}`
30
- const { focusedId } = useFocusOrder()
31
- const { mode, setMode } = useFocusMode()
32
- const { form, setFieldValue, setFieldStatus } = useFormState()
33
- const { value, status } = form.fields[field]
34
- const isFocused = focusedId === id
35
- const editing = status === 'editing'
36
- const [error, setError] = useState('')
37
- const [didAutofill, setDidAutofill] = useState(false)
38
- const [previousValue, setPreviousValue] = useState<string | undefined>(undefined)
39
-
40
- const startEditing = useCallback(() => {
41
- setPreviousValue(value || undefined)
42
- setFieldStatus(field, 'editing')
43
- // Revising an existing value: Escape reverts without triggering exit modal
44
- // Initial entry: Escape passes through to the exit hook
45
- setMode(value ? 'field-revision' : 'field-initial-entry')
46
- }, [field, value, setFieldStatus, setMode])
47
-
48
- const stopEditing = useCallback(() => {
49
- setPreviousValue(undefined)
50
- setFieldStatus(field, value ? 'confirmed' : 'empty')
51
- setMode('form-navigation')
52
- }, [field, value, setFieldStatus, setMode])
53
-
54
- const cancelEditing = useCallback(() => {
55
- if (previousValue) {
56
- setFieldValue(field, previousValue)
57
- setPreviousValue(undefined)
58
- setFieldStatus(field, 'confirmed')
59
- setMode('form-navigation')
60
- setError('')
61
- }
62
- }, [previousValue, field, setFieldValue, setFieldStatus, setMode])
63
-
64
- // Handle Enter to edit, or 'c' to clear and edit
65
- useInput(
66
- (input, key) => {
67
- if (!editing) {
68
- if (key.return) {
69
- startEditing()
70
- }
71
- if (input === 'c' && value) {
72
- setFieldValue(field, '')
73
- startEditing()
74
- }
75
- }
76
- },
77
- { isActive: isFocused && !editing && mode === 'form-navigation' },
78
- )
79
-
80
- // Handle Enter to confirm / Escape to revert (if previously had value)
81
- useInput(
82
- (_input, key) => {
83
- if (key.return) {
84
- if (validate) {
85
- const err = validate(value)
86
- if (err) {
87
- setError(err)
88
- return
89
- }
90
- }
91
- if (!value) {
92
- setError(`${label} is required`)
93
- return
94
- }
95
- setError('')
96
- stopEditing()
97
- onConfirm?.()
98
- }
99
- if (key.escape && previousValue) {
100
- cancelEditing()
101
- }
102
- },
103
- { isActive: isFocused && editing },
104
- )
105
-
106
- // Auto-start editing when focused on an empty required field
107
- useEffect(() => {
108
- if (isFocused && !value && !editing && mode === 'form-navigation') {
109
- startEditing()
110
- }
111
- }, [isFocused, value, editing, mode, startEditing])
112
-
113
- // Autofill defaultValue when editing starts on an empty field
114
- useEffect(() => {
115
- if (editing && !value && defaultValue && !didAutofill) {
116
- setFieldValue(field, defaultValue)
117
- setDidAutofill(true)
118
- }
119
- }, [editing, value, defaultValue, didAutofill, field, setFieldValue])
120
-
121
- const isEditing = editing && isFocused
122
-
123
- return (
124
- <Box flexDirection="column" gap={0}>
125
- <Box gap={1}>
126
- <Text color={isFocused ? THEME.primary : undefined} bold={isFocused} dimColor={dimmed && !isFocused}>
127
- {label}:
128
- </Text>
129
- {isEditing && error ? (
130
- <Text color={THEME.warning}>{error}</Text>
131
- ) : isEditing ? (
132
- <>
133
- {hint && <Text color={THEME.hint}>({hint})</Text>}
134
- {previousValue && (
135
- <Text color={THEME.hint}>
136
- <Text color={THEME.keyword}>Escape</Text> to revert to{' '}
137
- <Text color={THEME.keyword}>"{previousValue}"</Text>
138
- </Text>
139
- )}
140
- </>
141
- ) : !isEditing && value ? (
142
- <Text color={dimmed && !isFocused ? undefined : THEME.success} dimColor={dimmed && !isFocused}>
143
-
144
- </Text>
145
- ) : !isEditing ? (
146
- <Text dimColor>(not set)</Text>
147
- ) : null}
148
- </Box>
149
- <Box marginLeft={2}>
150
- {isEditing ? (
151
- <Box gap={1}>
152
- <Text color={THEME.tertiary}>{'> '}</Text>
153
- <TextInput value={value} onChange={(v) => setFieldValue(field, v)} placeholder={placeholder} focus />
154
- <Text color={THEME.hint}>
155
- · <Text color={THEME.keyword}>Enter</Text> to save
156
- </Text>
157
- </Box>
158
- ) : (
159
- <Box gap={1}>
160
- <Text dimColor={dimmed && !isFocused}>{value || ' '}</Text>
161
- {isFocused && value && (
162
- <Text color={THEME.hint}>
163
- · <Text color={THEME.keyword}>Enter</Text> to edit · <Text color={THEME.keyword}>c</Text> to clear and
164
- edit
165
- </Text>
166
- )}
167
- </Box>
168
- )}
169
- </Box>
170
- </Box>
171
- )
172
- }
@@ -1,20 +0,0 @@
1
- import { Box, Text } from 'ink'
2
- import { useFocusMode } from '../context/focus-mode-context.ts'
3
- import { THEME } from '../theme.ts'
4
-
5
- export function ExitFooter() {
6
- const { mode, exitSecondsLeft } = useFocusMode()
7
- const visible = mode === 'exit-modal' && exitSecondsLeft > 0
8
-
9
- return (
10
- <Box marginTop={1}>
11
- {visible ? (
12
- <Text color={THEME.warning} bold>
13
- Press Escape again to exit ({exitSecondsLeft}s) — any other key to cancel
14
- </Text>
15
- ) : (
16
- <Text> </Text>
17
- )}
18
- </Box>
19
- )
20
- }
@@ -1,129 +0,0 @@
1
- import { Box, Text, useInput } from 'ink'
2
- import Gradient from 'ink-gradient'
3
- import { useEffect, useState } from 'react'
4
- import { useFocusOrder } from '../context/focus-order-context.ts'
5
- import { GRADIENT_STOPS, getAnimatedGradient } from '../gradient.ts'
6
- import { THEME } from '../theme.ts'
7
-
8
- const ANIMATION_INTERVAL_MS = 75
9
-
10
- export interface ReconciliationOption {
11
- label: string
12
- }
13
-
14
- export function ReconciliationItemRow({
15
- id,
16
- description,
17
- detail,
18
- options,
19
- selectedIndex,
20
- onSelect,
21
- }: {
22
- id: string
23
- /** Primary text for this item (e.g., file path or asset name) */
24
- description: string
25
- /** Optional secondary detail line below the description */
26
- detail?: string
27
- /** The two action options */
28
- options: [ReconciliationOption, ReconciliationOption]
29
- /** Index of currently selected option, or null if unresolved */
30
- selectedIndex: number | null
31
- /** Called when the user locks in an option */
32
- onSelect: (index: number) => void
33
- }) {
34
- const { focusedId } = useFocusOrder()
35
- const isFocused = focusedId === id
36
-
37
- // Which option is highlighted (cursor position)
38
- const [highlightedIndex, setHighlightedIndex] = useState(selectedIndex ?? 0)
39
- const [offset, setOffset] = useState(0)
40
-
41
- // Animate gradient when focused
42
- useEffect(() => {
43
- if (!isFocused) return
44
- const interval = setInterval(() => {
45
- setOffset((prev) => (prev + 1) % GRADIENT_STOPS.length)
46
- }, ANIMATION_INTERVAL_MS)
47
- return () => clearInterval(interval)
48
- }, [isFocused])
49
-
50
- useInput(
51
- (_input, key) => {
52
- if (key.leftArrow) setHighlightedIndex(0)
53
- if (key.rightArrow) setHighlightedIndex(1)
54
- if (key.return) onSelect(highlightedIndex)
55
- },
56
- { isActive: isFocused },
57
- )
58
-
59
- const animatedColors = getAnimatedGradient(offset)
60
-
61
- return (
62
- <Box flexDirection="column">
63
- <Box gap={2}>
64
- <Box gap={1}>
65
- {isFocused ? (
66
- <Text color={THEME.primary} bold>
67
-
68
- </Text>
69
- ) : (
70
- <Text> </Text>
71
- )}
72
- <Text color={isFocused ? THEME.primary : undefined}>{description}</Text>
73
- </Box>
74
-
75
- <Box gap={2}>
76
- {options.map((opt, i) => {
77
- const isSelected = selectedIndex === i
78
- const isHighlighted = isFocused && highlightedIndex === i
79
- const isOther = selectedIndex !== null && !isSelected
80
-
81
- if (isHighlighted) {
82
- return (
83
- <Box key={opt.label} gap={1}>
84
- {isSelected && <Text color={THEME.success}>✓</Text>}
85
- <Gradient colors={animatedColors}>
86
- <Text bold>{opt.label}</Text>
87
- </Gradient>
88
- </Box>
89
- )
90
- }
91
-
92
- if (isSelected && !isFocused) {
93
- return (
94
- <Box key={opt.label} gap={1}>
95
- <Text color={THEME.success}>✓</Text>
96
- <Gradient colors={[...THEME.gradient]}>
97
- <Text bold>{opt.label}</Text>
98
- </Gradient>
99
- </Box>
100
- )
101
- }
102
-
103
- if (isOther) {
104
- return (
105
- <Text key={opt.label} dimColor>
106
- {opt.label}
107
- </Text>
108
- )
109
- }
110
-
111
- // Unresolved, unfocused
112
- return (
113
- <Box key={opt.label} gap={1}>
114
- {isSelected && <Text color={THEME.success}>✓</Text>}
115
- <Text>{opt.label}</Text>
116
- </Box>
117
- )
118
- })}
119
- </Box>
120
- </Box>
121
-
122
- {detail && (
123
- <Box marginLeft={2}>
124
- <Text dimColor>{detail}</Text>
125
- </Box>
126
- )}
127
- </Box>
128
- )
129
- }
@@ -1,45 +0,0 @@
1
- import { Box, Text } from 'ink'
2
- import Spinner from 'ink-spinner'
3
- import type { ReactNode } from 'react'
4
- import { THEME } from '../theme.ts'
5
-
6
- export type StageStatus = 'pending' | 'running' | 'done' | 'failed'
7
-
8
- export interface Stage {
9
- label: string
10
- status: StageStatus
11
- detail?: string
12
- errors?: string[]
13
- }
14
-
15
- const ICONS: Record<StageStatus, ReactNode> = {
16
- pending: <Text color={THEME.hint}>○</Text>,
17
- running: (
18
- <Text color={THEME.secondary}>
19
- <Spinner type="dots" />
20
- </Text>
21
- ),
22
- done: <Text color={THEME.success}>●</Text>,
23
- failed: <Text color={THEME.warning}>✕</Text>,
24
- }
25
-
26
- export function StageRow({ stage }: { stage: Stage }) {
27
- return (
28
- <Box flexDirection="column">
29
- <Box gap={1}>
30
- {ICONS[stage.status]}
31
- <Text dimColor={stage.status === 'pending'}>{stage.label}</Text>
32
- {stage.detail && <Text color={THEME.hint}> — {stage.detail}</Text>}
33
- </Box>
34
- {stage.errors && stage.errors.length > 0 && (
35
- <Box flexDirection="column" marginLeft={3}>
36
- {stage.errors.map((e) => (
37
- <Text key={e} color={THEME.warning}>
38
- {e}
39
- </Text>
40
- ))}
41
- </Box>
42
- )}
43
- </Box>
44
- )
45
- }