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,140 +0,0 @@
1
- import { Box, Text } from 'ink'
2
- import { useCallback, useEffect } from 'react'
3
- import { DEFAULT_VERSION, isValidKebabCase } from '../../../commands/create-scaffold.ts'
4
- import { AssetSection } from '../../components/asset-section.tsx'
5
- import { Button } from '../../components/button.tsx'
6
- import { EditableField } from '../../components/editable-field.tsx'
7
- import { useFocusOrder } from '../../context/focus-order-context.ts'
8
- import type { AssetSectionKey } from '../../context/form-state-context.ts'
9
- import { useFormState } from '../../context/form-state-context.ts'
10
- import { THEME } from '../../theme.ts'
11
-
12
- const ASSET_TYPES: AssetSectionKey[] = ['skill', 'command', 'agent']
13
- const ASSET_LABELS: Record<AssetSectionKey, string> = {
14
- skill: 'Skills',
15
- command: 'Commands',
16
- agent: 'Agents',
17
- }
18
-
19
- function computeFocusIds(form: ReturnType<typeof useFormState>['form']): string[] {
20
- const ids: string[] = ['field-name', 'field-description', 'field-version']
21
-
22
- for (const type of ASSET_TYPES) {
23
- const section = form.assets[type]
24
-
25
- for (let i = 0; i < section.items.length; i++) {
26
- ids.push(`item-${type}-${i}`)
27
- }
28
-
29
- ids.push(`add-${type}`)
30
- }
31
-
32
- ids.push('edit-confirm-btn')
33
- return ids
34
- }
35
-
36
- export function EditView({
37
- onSubmit,
38
- onEditDescription,
39
- }: {
40
- onSubmit: () => void
41
- onEditDescription?: (section: AssetSectionKey, name: string) => void
42
- }) {
43
- const { form } = useFormState()
44
- const { setFocusIds, focus, focusedId } = useFocusOrder()
45
-
46
- const validateKebab = useCallback((v: string) => {
47
- if (!v) return undefined
48
- if (!isValidKebabCase(v)) return 'Must be kebab-case (e.g., my-facet)'
49
- return undefined
50
- }, [])
51
-
52
- useEffect(() => {
53
- const ids = computeFocusIds(form)
54
- setFocusIds(ids)
55
-
56
- if (focusedId && !ids.includes(focusedId)) {
57
- focus(ids[0] ?? '')
58
- }
59
- }, [form, setFocusIds, focus, focusedId])
60
-
61
- const totalAssets = form.assets.skill.items.length + form.assets.agent.items.length + form.assets.command.items.length
62
- const canConfirm = totalAssets > 0
63
-
64
- useEffect(() => {
65
- if (!focusedId) {
66
- focus('field-name')
67
- }
68
- }, [focusedId, focus])
69
-
70
- return (
71
- <Box flexDirection="column" padding={1} gap={1}>
72
- <Text bold color={THEME.brand}>
73
- Edit facet
74
- </Text>
75
-
76
- <Box flexDirection="column">
77
- <EditableField
78
- field="name"
79
- label="Name"
80
- placeholder="my-facet"
81
- hint="kebab-case"
82
- validate={validateKebab}
83
- onConfirm={() => focus('field-description')}
84
- />
85
-
86
- <EditableField
87
- field="description"
88
- label="Description"
89
- placeholder="A brief description"
90
- onConfirm={() => focus('field-version')}
91
- />
92
-
93
- <EditableField
94
- field="version"
95
- label="Version"
96
- hint="SemVer N.N.N"
97
- validate={(v) => (/^\d+\.\d+\.\d+$/.test(v) ? undefined : `Must be SemVer (e.g., ${DEFAULT_VERSION})`)}
98
- onConfirm={() => focus(`add-${ASSET_TYPES[0]}`)}
99
- />
100
- </Box>
101
-
102
- {ASSET_TYPES.map((type) => (
103
- <Box key={type} marginTop={0}>
104
- <AssetSection
105
- section={type}
106
- label={ASSET_LABELS[type]}
107
- onEditDescription={onEditDescription}
108
- validate={(v) => {
109
- if (!isValidKebabCase(v)) return 'Must be kebab-case'
110
- const editing = form.assets[type].editing
111
- if (form.assets[type].items.some((item) => item === v && item !== editing)) return `"${v}" already exists`
112
- return undefined
113
- }}
114
- />
115
- </Box>
116
- ))}
117
-
118
- <Box marginTop={1}>
119
- <Button
120
- id="edit-confirm-btn"
121
- label="[ Review & Confirm ]"
122
- disabled={!canConfirm}
123
- gradient={canConfirm}
124
- animateGradient={canConfirm && focusedId === 'edit-confirm-btn'}
125
- onPress={onSubmit}
126
- />
127
- </Box>
128
-
129
- {!canConfirm && (
130
- <Box marginLeft={2}>
131
- <Text dimColor>Add at least one skill, agent, or command</Text>
132
- </Box>
133
- )}
134
-
135
- <Box>
136
- <Text dimColor>↑ ↓ navigate · Enter edit · Esc Esc exit (no changes)</Text>
137
- </Box>
138
- </Box>
139
- )
140
- }
@@ -1,38 +0,0 @@
1
- import type { FacetManifest } from '@agent-facets/core'
2
- import type { AssetSectionKey, FormState } from '../../context/form-state-context.ts'
3
-
4
- /** Maps manifest asset keys to form section keys. */
5
- const MANIFEST_TO_FORM: Record<string, AssetSectionKey> = {
6
- skills: 'skill',
7
- agents: 'agent',
8
- commands: 'command',
9
- }
10
-
11
- /** Builds initial form state from an existing manifest. */
12
- export function manifestToFormState(manifest: FacetManifest): FormState {
13
- const assets: FormState['assets'] = {
14
- skill: { items: [], descriptions: {}, editing: undefined, adding: false },
15
- agent: { items: [], descriptions: {}, editing: undefined, adding: false },
16
- command: { items: [], descriptions: {}, editing: undefined, adding: false },
17
- }
18
-
19
- for (const [manifestKey, formKey] of Object.entries(MANIFEST_TO_FORM)) {
20
- const section = manifest[manifestKey as keyof FacetManifest]
21
- if (section && typeof section === 'object' && !Array.isArray(section)) {
22
- const entries = section as Record<string, { description?: string }>
23
- for (const [name, descriptor] of Object.entries(entries)) {
24
- assets[formKey].items.push(name)
25
- assets[formKey].descriptions[name] = descriptor.description ?? `A ${name} ${formKey}`
26
- }
27
- }
28
- }
29
-
30
- return {
31
- fields: {
32
- name: { value: manifest.name, status: 'confirmed' },
33
- description: { value: manifest.description ?? '', status: 'confirmed' },
34
- version: { value: manifest.version, status: 'confirmed' },
35
- },
36
- assets,
37
- }
38
- }
@@ -1,170 +0,0 @@
1
- import { Box, Text } from 'ink'
2
- import { useCallback, useEffect, useMemo } from 'react'
3
- import { Button } from '../../components/button.tsx'
4
- import { ReconciliationItemRow } from '../../components/reconciliation-item.tsx'
5
- import { useFocusOrder } from '../../context/focus-order-context.ts'
6
- import { THEME } from '../../theme.ts'
7
- import type { ReconciliationItem, ReconciliationResolution } from './edit-types.ts'
8
-
9
- /** Maps a reconciliation item to a unique key. */
10
- function itemKey(item: ReconciliationItem): string {
11
- return `${item.kind}:${item.type}:${item.name}`
12
- }
13
-
14
- /** Returns the two action options for a reconciliation item kind. */
15
- function optionsForKind(kind: ReconciliationItem['kind']): [{ label: string }, { label: string }] {
16
- switch (kind) {
17
- case 'addition':
18
- return [{ label: 'Add to manifest' }, { label: 'Ignore for now' }]
19
- case 'missing':
20
- return [{ label: 'Scaffold template' }, { label: 'Remove from manifest' }]
21
- case 'front-matter':
22
- return [{ label: 'Strip front matter' }, { label: 'Remove from manifest' }]
23
- }
24
- }
25
-
26
- /** Converts a selected option index to a resolution for the given item kind. */
27
- function indexToResolution(kind: ReconciliationItem['kind'], index: number): ReconciliationResolution {
28
- switch (kind) {
29
- case 'addition':
30
- return index === 0 ? { action: 'add-to-manifest' } : { action: 'ignore' }
31
- case 'missing':
32
- return index === 0 ? { action: 'scaffold-template' } : { action: 'remove-from-manifest' }
33
- case 'front-matter':
34
- return index === 0 ? { action: 'strip-front-matter' } : { action: 'remove-from-manifest' }
35
- }
36
- }
37
-
38
- /** Returns the selected option index for a resolution, or null. */
39
- function resolutionToIndex(
40
- kind: ReconciliationItem['kind'],
41
- resolution: ReconciliationResolution | undefined,
42
- ): number | null {
43
- if (!resolution) return null
44
- switch (kind) {
45
- case 'addition':
46
- return resolution.action === 'add-to-manifest' ? 0 : resolution.action === 'ignore' ? 1 : null
47
- case 'missing':
48
- return resolution.action === 'scaffold-template' ? 0 : resolution.action === 'remove-from-manifest' ? 1 : null
49
- case 'front-matter':
50
- return resolution.action === 'strip-front-matter' ? 0 : resolution.action === 'remove-from-manifest' ? 1 : null
51
- }
52
- }
53
-
54
- export function ReconciliationView({
55
- items,
56
- resolutions,
57
- onResolve,
58
- onContinue,
59
- }: {
60
- items: ReconciliationItem[]
61
- resolutions: Map<string, ReconciliationResolution>
62
- onResolve: (key: string, resolution: ReconciliationResolution) => void
63
- onContinue: () => void
64
- }) {
65
- const { setFocusIds, focusedId, focus } = useFocusOrder()
66
-
67
- const allResolved = items.every((item) => resolutions.has(itemKey(item)))
68
-
69
- // Group items by kind
70
- const additions = items.filter((i) => i.kind === 'addition')
71
- const missing = items.filter((i) => i.kind === 'missing')
72
- const frontMatter = items.filter((i) => i.kind === 'front-matter')
73
-
74
- // Build focus order: all items then continue button
75
- const focusIds = useMemo(() => {
76
- const ids = items.map((item) => `recon-${itemKey(item)}`)
77
- ids.push('recon-continue')
78
- return ids
79
- }, [items])
80
-
81
- useEffect(() => {
82
- setFocusIds(focusIds)
83
- if (!focusedId) {
84
- focus(focusIds[0] ?? '')
85
- }
86
- }, [focusIds, setFocusIds, focusedId, focus])
87
-
88
- const handleSelect = useCallback(
89
- (item: ReconciliationItem, optionIndex: number) => {
90
- const key = itemKey(item)
91
- const resolution = indexToResolution(item.kind, optionIndex)
92
- onResolve(key, resolution)
93
-
94
- // Auto-advance to next unresolved item
95
- const currentIdx = items.findIndex((i) => itemKey(i) === key)
96
- for (let i = currentIdx + 1; i < items.length; i++) {
97
- const nextItem = items[i]
98
- if (!nextItem) continue
99
- const nextKey = itemKey(nextItem)
100
- if (!resolutions.has(nextKey)) {
101
- focus(`recon-${nextKey}`)
102
- return
103
- }
104
- }
105
- // All resolved — focus continue button
106
- focus('recon-continue')
107
- },
108
- [items, resolutions, onResolve, focus],
109
- )
110
-
111
- const renderGroup = (label: string, groupItems: ReconciliationItem[]) => {
112
- if (groupItems.length === 0) return null
113
- return (
114
- <Box flexDirection="column" key={label}>
115
- <Box marginBottom={0}>
116
- <Text bold color={THEME.warning}>
117
- {label}
118
- </Text>
119
- </Box>
120
- {groupItems.map((item) => {
121
- const key = itemKey(item)
122
- const description =
123
- item.kind === 'missing'
124
- ? `${item.name} (${item.type}) — ${item.expectedPath}`
125
- : 'path' in item
126
- ? item.path
127
- : ''
128
-
129
- return (
130
- <ReconciliationItemRow
131
- key={key}
132
- id={`recon-${key}`}
133
- description={description}
134
- options={optionsForKind(item.kind)}
135
- selectedIndex={resolutionToIndex(item.kind, resolutions.get(key))}
136
- onSelect={(index) => handleSelect(item, index)}
137
- />
138
- )
139
- })}
140
- </Box>
141
- )
142
- }
143
-
144
- return (
145
- <Box flexDirection="column" padding={1} gap={1}>
146
- <Text bold color={THEME.brand}>
147
- Reconciliation — {items.length} item{items.length !== 1 ? 's' : ''} to resolve
148
- </Text>
149
-
150
- {renderGroup('New files on disk:', additions)}
151
- {renderGroup('Missing from disk:', missing)}
152
- {renderGroup('Front matter detected:', frontMatter)}
153
-
154
- <Box marginTop={1}>
155
- <Button
156
- id="recon-continue"
157
- label="[ Continue to edit ]"
158
- disabled={!allResolved}
159
- gradient={allResolved}
160
- animateGradient={allResolved && focusedId === 'recon-continue'}
161
- onPress={onContinue}
162
- />
163
- </Box>
164
-
165
- <Box>
166
- <Text dimColor>↑ ↓ navigate · ← → switch option · Enter select · Esc Esc exit</Text>
167
- </Box>
168
- </Box>
169
- )
170
- }
@@ -1,125 +0,0 @@
1
- import type { FacetManifest } from '@agent-facets/core'
2
- import { useCallback, useState } from 'react'
3
- import type { AssetSectionKey, FormState } from '../../context/form-state-context.ts'
4
- import type { EditContext, EditOperation, EditResult, ReconciliationResolution } from './edit-types.ts'
5
-
6
- /** Maps form section keys to manifest asset keys. */
7
- const FORM_TO_MANIFEST: Record<AssetSectionKey, 'skills' | 'agents' | 'commands'> = {
8
- skill: 'skills',
9
- agent: 'agents',
10
- command: 'commands',
11
- }
12
-
13
- /** Builds a manifest from form state, preserving non-asset fields from the original. */
14
- function buildManifest(original: FacetManifest, form: FormState): FacetManifest {
15
- const manifest: FacetManifest = {
16
- ...original,
17
- name: form.fields.name.value,
18
- version: form.fields.version.value,
19
- }
20
-
21
- if (form.fields.description.value) {
22
- manifest.description = form.fields.description.value
23
- }
24
-
25
- for (const [formKey, manifestKey] of Object.entries(FORM_TO_MANIFEST) as [
26
- AssetSectionKey,
27
- 'skills' | 'agents' | 'commands',
28
- ][]) {
29
- const items = form.assets[formKey].items
30
- if (items.length > 0) {
31
- const section: Record<string, { description: string }> = {}
32
- for (const name of items) {
33
- section[name] = { description: form.assets[formKey].descriptions[name] ?? '' }
34
- }
35
- manifest[manifestKey] = section
36
- } else {
37
- delete manifest[manifestKey]
38
- }
39
- }
40
-
41
- return manifest
42
- }
43
-
44
- /** Builds the list of file operations from resolutions + form changes. */
45
- function buildOperations(
46
- context: EditContext,
47
- form: FormState,
48
- resolutions: Map<string, ReconciliationResolution>,
49
- ): EditOperation[] {
50
- const operations: EditOperation[] = [{ op: 'write-manifest' }]
51
-
52
- // Operations from reconciliation resolutions
53
- for (const [key, resolution] of resolutions) {
54
- const parts = key.split(':')
55
- const kind = parts[0]
56
- const assetType = parts[1] as 'skills' | 'agents' | 'commands'
57
- const name = parts[2]
58
- if (!kind || !assetType || !name) continue
59
-
60
- if (resolution.action === 'scaffold-template') {
61
- operations.push({ op: 'scaffold', type: assetType, name })
62
- } else if (resolution.action === 'remove-from-manifest' && kind === 'front-matter') {
63
- operations.push({ op: 'delete-file', type: assetType, name })
64
- } else if (resolution.action === 'strip-front-matter') {
65
- const item = context.reconciliationItems.find(
66
- (i) => i.kind === 'front-matter' && i.type === assetType && i.name === name,
67
- )
68
- if (item && 'path' in item) {
69
- operations.push({ op: 'strip-front-matter', type: assetType, name, path: item.path })
70
- }
71
- }
72
- }
73
-
74
- // New assets added during editing (not from reconciliation)
75
- for (const [formKey, manifestKey] of Object.entries(FORM_TO_MANIFEST) as [
76
- AssetSectionKey,
77
- 'skills' | 'agents' | 'commands',
78
- ][]) {
79
- const originalSection = context.manifest[manifestKey]
80
- const originalNames =
81
- originalSection && typeof originalSection === 'object' && !Array.isArray(originalSection)
82
- ? Object.keys(originalSection)
83
- : []
84
-
85
- for (const name of form.assets[formKey].items) {
86
- const isFromReconciliation = resolutions.has(`addition:${manifestKey}:${name}`)
87
- if (!originalNames.includes(name) && !isFromReconciliation) {
88
- operations.push({ op: 'scaffold', type: manifestKey, name })
89
- }
90
- }
91
-
92
- // Removed assets
93
- for (const name of originalNames) {
94
- if (!form.assets[formKey].items.includes(name)) {
95
- operations.push({ op: 'delete-file', type: manifestKey, name })
96
- }
97
- }
98
- }
99
-
100
- return operations
101
- }
102
-
103
- export function useEditSession(context: EditContext) {
104
- const [resolutions, setResolutions] = useState<Map<string, ReconciliationResolution>>(new Map())
105
-
106
- const resolve = useCallback((key: string, resolution: ReconciliationResolution) => {
107
- setResolutions((prev) => {
108
- const next = new Map(prev)
109
- next.set(key, resolution)
110
- return next
111
- })
112
- }, [])
113
-
114
- /** Builds the final edit result from current form state and resolutions. */
115
- const buildResult = useCallback(
116
- (form: FormState): EditResult => {
117
- const manifest = buildManifest(context.manifest, form)
118
- const operations = buildOperations(context, form, resolutions)
119
- return { outcome: 'applied', manifest, operations }
120
- },
121
- [context, resolutions],
122
- )
123
-
124
- return { resolutions, resolve, buildResult }
125
- }
@@ -1,129 +0,0 @@
1
- import { useApp } from 'ink'
2
- import { useCallback, useEffect, useMemo, useState } from 'react'
3
- import { FocusModeProvider, useFocusMode } from '../../context/focus-mode-context.ts'
4
- import { FocusOrderProvider, useFocusOrder } from '../../context/focus-order-context.ts'
5
- import type { AssetSectionKey, FormState } from '../../context/form-state-context.ts'
6
- import { FormStateProvider, useFormState } from '../../context/form-state-context.ts'
7
- import { useExitKeys } from '../../hooks/use-exit-keys.ts'
8
- import { useNavigationKeys } from '../../hooks/use-navigation-keys.ts'
9
- import { EditConfirmView } from './edit-confirm-view.tsx'
10
- import type { EditContext, EditResult, ReconciliationResolution } from './edit-types.ts'
11
- import { EditView } from './edit-view.tsx'
12
- import { manifestToFormState } from './manifest-to-form.ts'
13
- import { ReconciliationView } from './reconciliation-view.tsx'
14
- import { useEditSession } from './use-edit-session.ts'
15
-
16
- type EditPhase = 'reconciliation' | 'editing' | 'confirmation'
17
-
18
- export interface EditWizardSnapshot {
19
- phase: EditPhase
20
- formState?: FormState
21
- focusedId?: string | null
22
- resolutions: Map<string, ReconciliationResolution>
23
- selectedItem?: {
24
- section: AssetSectionKey
25
- name: string
26
- field: 'name' | 'description'
27
- }
28
- }
29
-
30
- export interface EditWizardProps {
31
- context: EditContext
32
- snapshot?: EditWizardSnapshot
33
- onComplete: (result: EditResult) => void
34
- onSnapshot?: (snapshot: EditWizardSnapshot) => void
35
- onRequestEditor?: (section: AssetSectionKey, name: string, description: string) => void
36
- }
37
-
38
- function EditWizardInner({ context, snapshot, onComplete, onSnapshot, onRequestEditor }: EditWizardProps) {
39
- const { exit } = useApp()
40
- const { setMode } = useFocusMode()
41
- const { form } = useFormState()
42
- const { focusedId, focus } = useFocusOrder()
43
- const hasReconciliation = context.reconciliationItems.length > 0
44
-
45
- const initialPhase = snapshot?.phase ?? (hasReconciliation ? 'reconciliation' : 'editing')
46
- const [phase, setPhase] = useState<EditPhase>(initialPhase)
47
- const { resolutions, resolve, buildResult } = useEditSession(context)
48
-
49
- // Report snapshot to parent for editor round-trips
50
- useEffect(() => {
51
- onSnapshot?.({ phase, formState: form, focusedId, resolutions })
52
- }, [phase, form, focusedId, resolutions, onSnapshot])
53
-
54
- const cancel = useCallback(() => {
55
- onComplete({ outcome: 'cancelled' })
56
- exit()
57
- }, [onComplete, exit])
58
-
59
- useExitKeys(cancel)
60
- useNavigationKeys()
61
-
62
- const handleEditDescription = useCallback(
63
- (section: AssetSectionKey, name: string) => {
64
- const description = form.assets[section].descriptions[name] ?? ''
65
- onRequestEditor?.(section, name, description)
66
- },
67
- [form, onRequestEditor],
68
- )
69
-
70
- const handleConfirm = useCallback(() => {
71
- onComplete(buildResult(form))
72
- exit()
73
- }, [form, buildResult, onComplete, exit])
74
-
75
- if (phase === 'reconciliation') {
76
- return (
77
- <ReconciliationView
78
- items={context.reconciliationItems}
79
- resolutions={resolutions}
80
- onResolve={resolve}
81
- onContinue={() => setPhase('editing')}
82
- />
83
- )
84
- }
85
-
86
- if (phase === 'editing') {
87
- return (
88
- <EditView
89
- onSubmit={() => {
90
- setPhase('confirmation')
91
- setMode('form-confirmation')
92
- }}
93
- onEditDescription={handleEditDescription}
94
- />
95
- )
96
- }
97
-
98
- if (phase === 'confirmation') {
99
- return (
100
- <EditConfirmView
101
- onConfirm={handleConfirm}
102
- onBack={() => {
103
- setPhase('editing')
104
- setMode('form-navigation')
105
- focus('edit-confirm-btn')
106
- }}
107
- />
108
- )
109
- }
110
-
111
- return null
112
- }
113
-
114
- export function EditWizard(props: EditWizardProps) {
115
- const initialFormState = useMemo(
116
- () => props.snapshot?.formState ?? manifestToFormState(props.context.manifest),
117
- [props.snapshot?.formState, props.context.manifest],
118
- )
119
-
120
- return (
121
- <FocusModeProvider>
122
- <FocusOrderProvider initialFocusId={props.snapshot?.focusedId}>
123
- <FormStateProvider initialState={initialFormState}>
124
- <EditWizardInner {...props} />
125
- </FormStateProvider>
126
- </FocusOrderProvider>
127
- </FocusModeProvider>
128
- )
129
- }
package/src/version.ts DELETED
@@ -1,3 +0,0 @@
1
- import pkg from '../package.json'
2
-
3
- export const version: string = pkg.version
package/tsconfig.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "include": ["src"]
4
- }