@hai3/react 0.2.0-alpha.0
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.
- package/CLAUDE.md +227 -0
- package/commands/hai3-duplicate-screenset.md +58 -0
- package/commands/hai3-new-component.md +76 -0
- package/commands/hai3-new-screen.md +81 -0
- package/commands/hai3-new-screenset.md +85 -0
- package/dist/index.cjs +27587 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +345 -0
- package/dist/index.d.ts +345 -0
- package/dist/index.js +27558 -0
- package/dist/index.js.map +1 -0
- package/dist/types.cjs +19 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +247 -0
- package/dist/types.d.ts +247 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/llms.txt +60 -0
- package/package.json +59 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# @hai3/react
|
|
2
|
+
|
|
3
|
+
React bindings and hooks for HAI3 applications. Provides the React integration layer.
|
|
4
|
+
|
|
5
|
+
## React Layer
|
|
6
|
+
|
|
7
|
+
This package is part of the **React Layer (L3)** - it depends only on @hai3/framework (not directly on SDK packages) and provides React-specific components and hooks.
|
|
8
|
+
|
|
9
|
+
## Core Concepts
|
|
10
|
+
|
|
11
|
+
### HAI3Provider
|
|
12
|
+
|
|
13
|
+
Wrap your app with HAI3Provider to enable all hooks:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { HAI3Provider } from '@hai3/react';
|
|
17
|
+
|
|
18
|
+
function App() {
|
|
19
|
+
return (
|
|
20
|
+
<HAI3Provider>
|
|
21
|
+
<YourApp />
|
|
22
|
+
</HAI3Provider>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// With configuration
|
|
27
|
+
<HAI3Provider config={{ devMode: true }}>
|
|
28
|
+
<YourApp />
|
|
29
|
+
</HAI3Provider>
|
|
30
|
+
|
|
31
|
+
// With pre-built app
|
|
32
|
+
const app = createHAI3().use(screensets()).build();
|
|
33
|
+
<HAI3Provider app={app}>
|
|
34
|
+
<YourApp />
|
|
35
|
+
</HAI3Provider>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Available Hooks
|
|
39
|
+
|
|
40
|
+
#### useHAI3
|
|
41
|
+
|
|
42
|
+
Access the HAI3 app instance:
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { useHAI3 } from '@hai3/react';
|
|
46
|
+
|
|
47
|
+
function MyComponent() {
|
|
48
|
+
const app = useHAI3();
|
|
49
|
+
const screensets = app.screensetRegistry.getAll();
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### useAppDispatch / useAppSelector
|
|
54
|
+
|
|
55
|
+
Type-safe Redux hooks:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { useAppDispatch, useAppSelector } from '@hai3/react';
|
|
59
|
+
import { selectActiveScreen } from '@hai3/react';
|
|
60
|
+
|
|
61
|
+
function MyComponent() {
|
|
62
|
+
const dispatch = useAppDispatch();
|
|
63
|
+
const activeScreen = useAppSelector(selectActiveScreen);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### useTranslation
|
|
68
|
+
|
|
69
|
+
Access translation utilities:
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { useTranslation } from '@hai3/react';
|
|
73
|
+
|
|
74
|
+
function MyComponent() {
|
|
75
|
+
const { t, language, setLanguage, isRTL } = useTranslation();
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div dir={isRTL ? 'rtl' : 'ltr'}>
|
|
79
|
+
<h1>{t('common:title')}</h1>
|
|
80
|
+
<p>{t('common:welcome', { name: 'John' })}</p>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### useScreenTranslations
|
|
87
|
+
|
|
88
|
+
Load screen-level translations:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { useScreenTranslations } from '@hai3/react';
|
|
92
|
+
|
|
93
|
+
const translations = {
|
|
94
|
+
en: () => import('./i18n/en.json'),
|
|
95
|
+
es: () => import('./i18n/es.json'),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
function HomeScreen() {
|
|
99
|
+
const { isLoaded, error } = useScreenTranslations('demo', 'home', translations);
|
|
100
|
+
|
|
101
|
+
if (!isLoaded) return <Loading />;
|
|
102
|
+
if (error) return <Error error={error} />;
|
|
103
|
+
|
|
104
|
+
return <div>...</div>;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### useNavigation
|
|
109
|
+
|
|
110
|
+
Navigate between screens:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { useNavigation } from '@hai3/react';
|
|
114
|
+
|
|
115
|
+
function MyComponent() {
|
|
116
|
+
const { navigateToScreen, navigateToScreenset, currentScreen } = useNavigation();
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<button onClick={() => navigateToScreen('demo', 'home')}>
|
|
120
|
+
Go to Home
|
|
121
|
+
</button>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### useTheme
|
|
127
|
+
|
|
128
|
+
Access theme utilities:
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import { useTheme } from '@hai3/react';
|
|
132
|
+
|
|
133
|
+
function ThemeToggle() {
|
|
134
|
+
const { currentTheme, themes, setTheme } = useTheme();
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<select value={currentTheme} onChange={(e) => setTheme(e.target.value)}>
|
|
138
|
+
{themes.map((theme) => (
|
|
139
|
+
<option key={theme.id} value={theme.id}>{theme.name}</option>
|
|
140
|
+
))}
|
|
141
|
+
</select>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Components
|
|
147
|
+
|
|
148
|
+
#### TextLoader
|
|
149
|
+
|
|
150
|
+
Prevents flash of untranslated content:
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import { TextLoader } from '@hai3/react';
|
|
154
|
+
|
|
155
|
+
function Screen() {
|
|
156
|
+
return (
|
|
157
|
+
<TextLoader fallback={<Loading />}>
|
|
158
|
+
<h1>{t('screen.demo.home:title')}</h1>
|
|
159
|
+
</TextLoader>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### AppRouter
|
|
165
|
+
|
|
166
|
+
Renders screens with lazy loading:
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
import { AppRouter } from '@hai3/react';
|
|
170
|
+
|
|
171
|
+
function App() {
|
|
172
|
+
return (
|
|
173
|
+
<HAI3Provider>
|
|
174
|
+
<Layout>
|
|
175
|
+
<AppRouter
|
|
176
|
+
fallback={<Loading />}
|
|
177
|
+
errorFallback={(error) => <Error error={error} />}
|
|
178
|
+
/>
|
|
179
|
+
</Layout>
|
|
180
|
+
</HAI3Provider>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Key Rules
|
|
186
|
+
|
|
187
|
+
1. **Wrap with HAI3Provider** - Required for all hooks to work
|
|
188
|
+
2. **Use hooks for state access** - Don't import selectors directly from @hai3/layout
|
|
189
|
+
3. **Lazy load translations** - Use `useScreenTranslations` for screen-level i18n
|
|
190
|
+
4. **Use TextLoader** - Wrap translated content to prevent FOUC
|
|
191
|
+
5. **NO Layout components here** - Layout is in @hai3/uikit or user code
|
|
192
|
+
|
|
193
|
+
## Re-exports
|
|
194
|
+
|
|
195
|
+
For convenience, this package re-exports everything from @hai3/framework:
|
|
196
|
+
|
|
197
|
+
- All SDK primitives (eventBus, createStore, etc.)
|
|
198
|
+
- All plugins (screensets, themes, layout, etc.)
|
|
199
|
+
- All registries and factory functions
|
|
200
|
+
- All selectors from @hai3/layout
|
|
201
|
+
- All types
|
|
202
|
+
|
|
203
|
+
This allows users to import everything from `@hai3/react` without needing `@hai3/framework` directly.
|
|
204
|
+
|
|
205
|
+
## Exports
|
|
206
|
+
|
|
207
|
+
### Components
|
|
208
|
+
- `HAI3Provider` - Main context provider
|
|
209
|
+
- `AppRouter` - Screen router
|
|
210
|
+
- `TextLoader` - Translation loading wrapper
|
|
211
|
+
|
|
212
|
+
### Hooks
|
|
213
|
+
- `useHAI3` - Access app instance
|
|
214
|
+
- `useAppDispatch` - Typed dispatch
|
|
215
|
+
- `useAppSelector` - Typed selector
|
|
216
|
+
- `useTranslation` - Translation utilities
|
|
217
|
+
- `useScreenTranslations` - Screen translation loading
|
|
218
|
+
- `useNavigation` - Navigation utilities
|
|
219
|
+
- `useTheme` - Theme utilities
|
|
220
|
+
|
|
221
|
+
### Context
|
|
222
|
+
- `HAI3Context` - React context (for advanced use)
|
|
223
|
+
|
|
224
|
+
### Types
|
|
225
|
+
- `HAI3ProviderProps`, `AppRouterProps`, `TextLoaderProps`
|
|
226
|
+
- `UseTranslationReturn`, `UseNavigationReturn`, `UseThemeReturn`
|
|
227
|
+
- All types from @hai3/framework
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:duplicate-screenset - Duplicate Screenset
|
|
3
|
+
|
|
4
|
+
## AI WORKFLOW (REQUIRED)
|
|
5
|
+
1) Read .ai/targets/SCREENSETS.md before starting.
|
|
6
|
+
2) Gather requirements from user.
|
|
7
|
+
3) Follow steps below.
|
|
8
|
+
|
|
9
|
+
REQUIRED: Copy folder and update ids.ts only (2 steps, 96% reduction).
|
|
10
|
+
REQUIRED: Pass arch:check with zero errors.
|
|
11
|
+
REQUIRED: Test via Chrome DevTools MCP (never skip).
|
|
12
|
+
|
|
13
|
+
## GATHER REQUIREMENTS
|
|
14
|
+
Ask user for:
|
|
15
|
+
- SOURCE screenset name (existing screenset to copy).
|
|
16
|
+
- TARGET screenset name (camelCase, single word preferred).
|
|
17
|
+
- TARGET category: Drafts | Mockups | Production.
|
|
18
|
+
|
|
19
|
+
## STEP 1: Copy Screenset via CLI
|
|
20
|
+
```bash
|
|
21
|
+
hai3 screenset copy SOURCE TARGET --category={category}
|
|
22
|
+
```
|
|
23
|
+
The CLI automatically:
|
|
24
|
+
- Copies all files (screens, slices, actions, events, effects, API, icons, i18n).
|
|
25
|
+
- Updates ids.ts with TARGET_SCREENSET_ID and all SCREEN_IDs.
|
|
26
|
+
- Everything auto-updates via template literals:
|
|
27
|
+
- Event enums: ${TARGET_SCREENSET_ID}/${DOMAIN_ID}/eventName.
|
|
28
|
+
- Icon IDs: ${TARGET_SCREENSET_ID}:iconName.
|
|
29
|
+
- API domain: ${TARGET_SCREENSET_ID}:serviceName.
|
|
30
|
+
- Redux state key.
|
|
31
|
+
- Screenset auto-discovered (no manual registration).
|
|
32
|
+
|
|
33
|
+
## STEP 2: Validate
|
|
34
|
+
```bash
|
|
35
|
+
npm run type-check
|
|
36
|
+
npm run arch:check
|
|
37
|
+
npm run lint
|
|
38
|
+
grep -rn "OLD_SCREENSET_ID" src/screensets/TARGET/ # Must return 0 matches
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## STEP 3: Test via Chrome DevTools MCP
|
|
42
|
+
STOP: If MCP connection is broken, fix it first. NEVER skip testing.
|
|
43
|
+
- npm run dev.
|
|
44
|
+
- Verify TARGET in screenset selector.
|
|
45
|
+
- Click TARGET screenset in dev panel.
|
|
46
|
+
- Verify URL changes to target screenset.
|
|
47
|
+
- Check 0 console errors.
|
|
48
|
+
- Test all primary features.
|
|
49
|
+
- Verify auto-discovery worked (screenset appears without manual registration).
|
|
50
|
+
|
|
51
|
+
## CHECKLIST
|
|
52
|
+
- [ ] Gather requirements (source, target name, category).
|
|
53
|
+
- [ ] Run `hai3 screenset copy SOURCE TARGET --category={category}`.
|
|
54
|
+
- [ ] Run type-check (MUST pass).
|
|
55
|
+
- [ ] Run arch:check (MUST pass).
|
|
56
|
+
- [ ] Run lint (MUST pass).
|
|
57
|
+
- [ ] Verify zero occurrences of old screenset ID.
|
|
58
|
+
- [ ] Test via Chrome DevTools MCP (NEVER skip).
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:new-component - Add New UI Component
|
|
3
|
+
|
|
4
|
+
## AI WORKFLOW (REQUIRED)
|
|
5
|
+
1) Check if @hai3/uikit has equivalent component first.
|
|
6
|
+
2) Gather requirements from user.
|
|
7
|
+
3) Determine type: screenset composite (default) | screenset base (rare).
|
|
8
|
+
4) Create OpenSpec proposal for approval.
|
|
9
|
+
5) After approval, apply implementation.
|
|
10
|
+
|
|
11
|
+
## CHECK GLOBAL UIKIT FIRST
|
|
12
|
+
- REQUIRED: Before creating screenset component, verify @hai3/uikit lacks equivalent.
|
|
13
|
+
- REQUIRED: Import from @hai3/uikit if component exists there.
|
|
14
|
+
|
|
15
|
+
## GATHER REQUIREMENTS
|
|
16
|
+
Ask user for:
|
|
17
|
+
- Component name (e.g., "DataTable", "ColorPicker").
|
|
18
|
+
- Component type: screenset composite (default) | screenset base (rare).
|
|
19
|
+
- Component description and props.
|
|
20
|
+
- If screenset base: justification why composite is insufficient.
|
|
21
|
+
|
|
22
|
+
## IF SCREENSET COMPONENT
|
|
23
|
+
|
|
24
|
+
### STEP 0: Determine Subfolder
|
|
25
|
+
- uikit/composite/: Screenset-specific composites (theme tokens only).
|
|
26
|
+
- uikit/base/: Rare primitives needing inline styles (needs strong justification).
|
|
27
|
+
|
|
28
|
+
### STEP 1: Create OpenSpec Proposal
|
|
29
|
+
Create openspec/changes/add-{screenset}-{component}/ with:
|
|
30
|
+
|
|
31
|
+
#### proposal.md
|
|
32
|
+
- Summary: Add new screenset-specific component to {screenset}.
|
|
33
|
+
- Details: Screenset, component name, placement (base/composite), description, props.
|
|
34
|
+
- Justification (if base/): Why global uikit insufficient, why composite insufficient.
|
|
35
|
+
- Implementation: HAI3 patterns (no Redux, no business logic).
|
|
36
|
+
|
|
37
|
+
#### tasks.md
|
|
38
|
+
- Create component file in uikit/{base|composite}/.
|
|
39
|
+
- Implement props interface.
|
|
40
|
+
- Add theme token styling (or inline for base/).
|
|
41
|
+
- Export from local index if needed.
|
|
42
|
+
- Validate: npm run arch:check.
|
|
43
|
+
- Test in UI.
|
|
44
|
+
|
|
45
|
+
### STEP 2: Wait for Approval
|
|
46
|
+
Tell user: "Review proposal at openspec/changes/add-{screenset}-{component}/."
|
|
47
|
+
Tell user: "Run /openspec:apply add-{screenset}-{component} to implement."
|
|
48
|
+
|
|
49
|
+
### STEP 3: Apply Implementation (after approval)
|
|
50
|
+
When user runs /openspec:apply:
|
|
51
|
+
|
|
52
|
+
#### 3.1 Create Component
|
|
53
|
+
File: src/screensets/{screenset}/uikit/{base|composite}/{ComponentName}.tsx
|
|
54
|
+
- composite/: Use theme tokens only (no inline styles).
|
|
55
|
+
- base/: May use inline styles (rare, needs justification).
|
|
56
|
+
- Must be reusable within the screenset.
|
|
57
|
+
- NO @hai3/uicore imports (except types).
|
|
58
|
+
- NO Redux or state management.
|
|
59
|
+
- Accept value/onChange pattern for state.
|
|
60
|
+
|
|
61
|
+
#### 3.2 Export
|
|
62
|
+
Export from local index if needed.
|
|
63
|
+
|
|
64
|
+
#### 3.3 Validation
|
|
65
|
+
Run: npm run arch:check && npm run dev
|
|
66
|
+
Test component in UI.
|
|
67
|
+
|
|
68
|
+
#### 3.4 Mark Tasks Complete
|
|
69
|
+
Update tasks.md to mark all completed tasks.
|
|
70
|
+
|
|
71
|
+
## RULES
|
|
72
|
+
- REQUIRED: Check @hai3/uikit first; screenset uikit only if missing.
|
|
73
|
+
- REQUIRED: Screenset base components need strong justification.
|
|
74
|
+
- FORBIDDEN: Redux, business logic, side effects in components.
|
|
75
|
+
- FORBIDDEN: Inline styles outside uikit/base/.
|
|
76
|
+
- REQUIRED: Accept value/onChange pattern for state.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:new-screen - Add New Screen
|
|
3
|
+
|
|
4
|
+
## PREREQUISITES (CRITICAL - STOP IF FAILED)
|
|
5
|
+
FORBIDDEN: Proceeding without proposal.
|
|
6
|
+
FORBIDDEN: Creating screen manually without OpenSpec workflow.
|
|
7
|
+
|
|
8
|
+
## AI WORKFLOW (REQUIRED)
|
|
9
|
+
1) Read .ai/targets/SCREENSETS.md and .ai/targets/EVENTS.md before starting.
|
|
10
|
+
2) Gather requirements from user (including UI sections).
|
|
11
|
+
3) Create OpenSpec proposal via `.claude/commands/openspec-proposal.md` (REQUIRED).
|
|
12
|
+
4) After approval, implement via `.claude/commands/openspec-apply.md` (REQUIRED).
|
|
13
|
+
|
|
14
|
+
## GATHER REQUIREMENTS
|
|
15
|
+
Ask user for:
|
|
16
|
+
- Screenset path (e.g., src/screensets/chat).
|
|
17
|
+
- Screen name (camelCase).
|
|
18
|
+
- UI sections (e.g., "header, form, data table").
|
|
19
|
+
- Add to menu? (Y/N)
|
|
20
|
+
|
|
21
|
+
## STEP 1: Create OpenSpec Proposal (REQUIRED)
|
|
22
|
+
Execute openspec:proposal command (see `.claude/commands/openspec-proposal.md`).
|
|
23
|
+
Proposal name: `add-{screenset}-{screen}`
|
|
24
|
+
|
|
25
|
+
### proposal.md content
|
|
26
|
+
```
|
|
27
|
+
# Proposal: Add {ScreenName} Screen
|
|
28
|
+
|
|
29
|
+
## Summary
|
|
30
|
+
Add new screen "{screenName}" to {screenset} screenset.
|
|
31
|
+
|
|
32
|
+
## Details
|
|
33
|
+
- Screenset: {screenset}
|
|
34
|
+
- Screen name: {screenName}
|
|
35
|
+
- Add to menu: {Y/N}
|
|
36
|
+
|
|
37
|
+
## Component Plan
|
|
38
|
+
- REQUIRED: Use @hai3/uikit components first; local uikit only if missing.
|
|
39
|
+
- uikit/base/: rare primitives (inline styles allowed, needs justification)
|
|
40
|
+
- uikit/composite/: screenset composites (theme tokens only)
|
|
41
|
+
- screens/{screen}/components/: screen-specific components
|
|
42
|
+
|
|
43
|
+
## Data Flow
|
|
44
|
+
- Uses existing screenset events/slices per EVENTS.md
|
|
45
|
+
- Screen dispatches actions, never direct slice updates
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### tasks.md minimum required tasks
|
|
49
|
+
NOTE: Proposal may include additional tasks, but MUST include these:
|
|
50
|
+
```
|
|
51
|
+
- [ ] Add screen ID to ids.ts
|
|
52
|
+
- [ ] Create components per Component Plan (BEFORE screen file)
|
|
53
|
+
- [ ] Create screen (orchestrates components, follows EVENTS.md data flow)
|
|
54
|
+
- [ ] Add i18n files for all languages
|
|
55
|
+
- [ ] Add to menu (if requested)
|
|
56
|
+
- [ ] Validate: `npm run type-check && npm run lint`
|
|
57
|
+
- [ ] Test via Chrome DevTools MCP
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## STEP 2: Wait for Approval
|
|
61
|
+
Tell user: "Review proposal at `openspec/changes/add-{screenset}-{screen}/`."
|
|
62
|
+
Tell user: "Execute openspec:apply command to implement."
|
|
63
|
+
|
|
64
|
+
## STEP 3: Implementation (via openspec:apply)
|
|
65
|
+
BEFORE executing openspec:apply, verify tasks.md contains all minimum required tasks above.
|
|
66
|
+
Execute openspec:apply command (see `.claude/commands/openspec-apply.md`).
|
|
67
|
+
Follow tasks.md strictly:
|
|
68
|
+
1) Add screen ID to ids.ts.
|
|
69
|
+
2) Create components BEFORE screen file per Component Plan.
|
|
70
|
+
3) Create screen following data flow rules from .ai/targets/EVENTS.md:
|
|
71
|
+
- Use actions to trigger state changes
|
|
72
|
+
- FORBIDDEN: Direct slice dispatch from screen
|
|
73
|
+
4) Add i18n with useScreenTranslations(). Export default.
|
|
74
|
+
5) Add to menu if requested.
|
|
75
|
+
6) Validate: `npm run type-check && npm run lint`.
|
|
76
|
+
7) Test via Chrome DevTools MCP (REQUIRED):
|
|
77
|
+
- Navigate to new screen
|
|
78
|
+
- Verify screen renders without console errors
|
|
79
|
+
- Test UI interactions and data flow
|
|
80
|
+
- Verify translations load correctly
|
|
81
|
+
- STOP if MCP connection fails
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<!-- @standalone -->
|
|
2
|
+
# hai3:new-screenset - Create New Screenset
|
|
3
|
+
|
|
4
|
+
## PREREQUISITES (CRITICAL - STOP IF FAILED)
|
|
5
|
+
Run `hai3 --version`.
|
|
6
|
+
STOP: If fails, tell user to install.
|
|
7
|
+
FORBIDDEN: Proceeding without CLI tools.
|
|
8
|
+
FORBIDDEN: Creating screenset manually or by copying peers.
|
|
9
|
+
|
|
10
|
+
## AI WORKFLOW (REQUIRED)
|
|
11
|
+
1) Check prerequisites above.
|
|
12
|
+
2) Read .ai/targets/SCREENSETS.md and .ai/targets/EVENTS.md before starting.
|
|
13
|
+
3) Gather requirements from user (including UI sections).
|
|
14
|
+
4) Create OpenSpec proposal via `.claude/commands/openspec-proposal.md` (REQUIRED).
|
|
15
|
+
5) After approval, implement via `.claude/commands/openspec-apply.md` (REQUIRED).
|
|
16
|
+
|
|
17
|
+
## GATHER REQUIREMENTS
|
|
18
|
+
Ask user for:
|
|
19
|
+
- Screenset name (camelCase).
|
|
20
|
+
- Category: Drafts | Mockups | Production.
|
|
21
|
+
- Initial screens.
|
|
22
|
+
- UI sections per screen (e.g., "stats cards, charts, activity feed").
|
|
23
|
+
|
|
24
|
+
## STEP 1: Create OpenSpec Proposal (REQUIRED)
|
|
25
|
+
Execute openspec:proposal command (see `.claude/commands/openspec-proposal.md`).
|
|
26
|
+
Proposal name: `add-{screenset-name}`
|
|
27
|
+
|
|
28
|
+
### proposal.md content
|
|
29
|
+
```
|
|
30
|
+
# Proposal: Add {ScreensetName} Screenset
|
|
31
|
+
|
|
32
|
+
## Summary
|
|
33
|
+
Add new {category} screenset "{screensetName}" with {screens} screen(s).
|
|
34
|
+
|
|
35
|
+
## Details
|
|
36
|
+
- Name: {screensetName}
|
|
37
|
+
- Category: {category}
|
|
38
|
+
- Initial screens: {screens}
|
|
39
|
+
|
|
40
|
+
## Component Plan
|
|
41
|
+
- REQUIRED: Use @hai3/uikit components first; local uikit only if missing.
|
|
42
|
+
- uikit/base/: rare primitives (inline styles allowed, needs justification)
|
|
43
|
+
- uikit/composite/: screenset composites (theme tokens only)
|
|
44
|
+
- components/: multi-screen components
|
|
45
|
+
- screens/{screen}/components/: screen-specific components
|
|
46
|
+
|
|
47
|
+
## Data Flow
|
|
48
|
+
- Events: {domain events per EVENTS.md}
|
|
49
|
+
- State: slices/, events/, effects/, actions/
|
|
50
|
+
- API: api/{Name}ApiService.ts with mocks
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### tasks.md minimum required tasks
|
|
54
|
+
NOTE: Proposal may include additional tasks, but MUST include these:
|
|
55
|
+
```
|
|
56
|
+
- [ ] Create screenset: `hai3 screenset create {name} --category={category}`
|
|
57
|
+
- [ ] Create components per Component Plan (BEFORE screen file)
|
|
58
|
+
- [ ] Implement data flow per EVENTS.md (actions emit events, effects update slices)
|
|
59
|
+
- [ ] Add API service with mocks
|
|
60
|
+
- [ ] Validate: `npm run type-check && npm run arch:check && npm run lint`
|
|
61
|
+
- [ ] Test via Chrome DevTools MCP
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## STEP 2: Wait for Approval
|
|
65
|
+
Tell user: "Review proposal at `openspec/changes/add-{screenset-name}/`."
|
|
66
|
+
Tell user: "Execute openspec:apply command to implement."
|
|
67
|
+
|
|
68
|
+
## STEP 3: Implementation (via openspec:apply)
|
|
69
|
+
BEFORE executing openspec:apply, verify tasks.md contains all minimum required tasks above.
|
|
70
|
+
Execute openspec:apply command (see `.claude/commands/openspec-apply.md`).
|
|
71
|
+
Follow tasks.md strictly:
|
|
72
|
+
1) Create screenset via `hai3 screenset create` (REQUIRED).
|
|
73
|
+
2) Create components BEFORE screen file per Component Plan.
|
|
74
|
+
3) Implement data flow per .ai/targets/EVENTS.md:
|
|
75
|
+
- Actions emit events via eventBus.emit()
|
|
76
|
+
- Effects subscribe and update slices
|
|
77
|
+
- FORBIDDEN: Direct slice dispatch from components
|
|
78
|
+
4) Add API service with mocks.
|
|
79
|
+
5) Validate: `npm run type-check && npm run arch:check && npm run lint`.
|
|
80
|
+
6) Test via Chrome DevTools MCP (REQUIRED):
|
|
81
|
+
- Navigate to new screenset
|
|
82
|
+
- Verify screen renders without console errors
|
|
83
|
+
- Test user interactions trigger correct events
|
|
84
|
+
- Verify state updates via Redux DevTools
|
|
85
|
+
- STOP if MCP connection fails
|