@famgia/omnify-typescript 0.0.67 → 0.0.68

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 (43) hide show
  1. package/ai-guides/react-form-guide.md +259 -0
  2. package/ai-guides/typescript-guide.md +53 -0
  3. package/dist/{chunk-4L77AHAC.js → chunk-6I4O23X6.js} +521 -66
  4. package/dist/chunk-6I4O23X6.js.map +1 -0
  5. package/dist/index.cjs +761 -65
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +138 -2
  8. package/dist/index.d.ts +138 -2
  9. package/dist/index.js +227 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/plugin.cjs +624 -75
  12. package/dist/plugin.cjs.map +1 -1
  13. package/dist/plugin.d.cts +6 -0
  14. package/dist/plugin.d.ts +6 -0
  15. package/dist/plugin.js +96 -11
  16. package/dist/plugin.js.map +1 -1
  17. package/package.json +4 -3
  18. package/scripts/postinstall.js +29 -40
  19. package/stubs/JapaneseAddressField.tsx.stub +289 -0
  20. package/stubs/JapaneseBankField.tsx.stub +212 -0
  21. package/stubs/JapaneseNameField.tsx.stub +194 -0
  22. package/stubs/ai-guides/checklists/react.md.stub +108 -0
  23. package/stubs/ai-guides/cursor/react-design.mdc.stub +289 -0
  24. package/stubs/ai-guides/cursor/react-form.mdc.stub +277 -0
  25. package/stubs/ai-guides/cursor/react-services.mdc.stub +304 -0
  26. package/stubs/ai-guides/cursor/react.mdc.stub +305 -0
  27. package/stubs/ai-guides/react/README.md.stub +221 -0
  28. package/stubs/ai-guides/react/antd-guide.md.stub +294 -0
  29. package/stubs/ai-guides/react/checklist.md.stub +108 -0
  30. package/stubs/ai-guides/react/datetime-guide.md.stub +137 -0
  31. package/stubs/ai-guides/react/design-philosophy.md.stub +363 -0
  32. package/stubs/ai-guides/react/i18n-guide.md.stub +211 -0
  33. package/stubs/ai-guides/react/laravel-integration.md.stub +181 -0
  34. package/stubs/ai-guides/react/service-pattern.md.stub +180 -0
  35. package/stubs/ai-guides/react/tanstack-query.md.stub +339 -0
  36. package/stubs/ai-guides/react/types-guide.md.stub +524 -0
  37. package/stubs/components-index.ts.stub +13 -0
  38. package/stubs/form-validation.ts.stub +106 -0
  39. package/stubs/rules/index.ts.stub +48 -0
  40. package/stubs/rules/kana.ts.stub +291 -0
  41. package/stubs/use-form-mutation.ts.stub +117 -0
  42. package/stubs/zod-i18n.ts.stub +32 -0
  43. package/dist/chunk-4L77AHAC.js.map +0 -1
@@ -0,0 +1,259 @@
1
+ # Omnify React Form Guide
2
+
3
+ This guide explains how to build forms using Omnify generated schemas with **Ant Design** and **TanStack Query**.
4
+
5
+ ## Quick Start
6
+
7
+ ```tsx
8
+ import { Form } from 'antd';
9
+ import { useFormMutation } from '@/omnify/hooks';
10
+ import { type CustomerCreate } from '@/omnify/schemas';
11
+ import { CustomerForm } from '@/features/customers';
12
+ import { api } from '@/lib/api';
13
+
14
+ function CreateCustomerPage() {
15
+ const [form] = Form.useForm<CustomerCreate>();
16
+
17
+ const mutation = useFormMutation<CustomerCreate>({
18
+ form,
19
+ mutationFn: (data) => api.post('/customers', data),
20
+ invalidateKeys: [['customers']],
21
+ successMessage: '顧客を登録しました',
22
+ onSuccess: () => form.resetFields(),
23
+ });
24
+
25
+ return (
26
+ <CustomerForm
27
+ form={form}
28
+ onSubmit={mutation.mutate}
29
+ loading={mutation.isPending}
30
+ />
31
+ );
32
+ }
33
+ ```
34
+
35
+ ## useFormMutation Hook
36
+
37
+ Location: `resources/ts/omnify/hooks/use-form-mutation.ts`
38
+
39
+ ### Usage with Types
40
+
41
+ ```tsx
42
+ import { useFormMutation } from '@/omnify/hooks';
43
+ import { type CustomerCreate } from '@/omnify/schemas';
44
+
45
+ // With type parameter for type safety
46
+ const mutation = useFormMutation<CustomerCreate>({
47
+ form,
48
+ mutationFn: (data) => api.post('/customers', data),
49
+ invalidateKeys: [['customers']],
50
+ successMessage: '保存しました',
51
+ onSuccess: () => form.resetFields(),
52
+ });
53
+ ```
54
+
55
+ ### Options
56
+
57
+ | Option | Type | Description |
58
+ |--------|------|-------------|
59
+ | `form` | `FormInstance<T>` | Ant Design form instance (required) |
60
+ | `mutationFn` | `(data: T) => Promise` | API call function (required) |
61
+ | `invalidateKeys` | `string[][]` | Query keys to invalidate on success |
62
+ | `successMessage` | `string` | Toast message on success |
63
+ | `onSuccess` | `(data) => void` | Callback after success |
64
+ | `onError` | `(error) => void` | Callback after error |
65
+
66
+ ### Laravel Error Handling
67
+
68
+ The hook automatically handles Laravel validation errors (422):
69
+
70
+ ```json
71
+ {
72
+ "message": "The given data was invalid.",
73
+ "errors": {
74
+ "email": ["The email has already been taken."]
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## Japanese Form Components
80
+
81
+ Omnify provides specialized components for Japanese data input.
82
+
83
+ ### JapaneseNameField
84
+
85
+ ```tsx
86
+ import { JapaneseNameField } from '@/omnify/components';
87
+
88
+ <JapaneseNameField
89
+ schemas={customerSchemas}
90
+ i18n={customerI18n}
91
+ prefix="name" // name_lastname, name_firstname, etc.
92
+ required // Show required asterisk
93
+ showKana={true} // Show kana fields (default)
94
+ />
95
+ ```
96
+
97
+ **Fields:** `{prefix}_lastname`, `{prefix}_firstname`, `{prefix}_kana_lastname`, `{prefix}_kana_firstname`
98
+
99
+ ### JapaneseAddressField
100
+
101
+ ```tsx
102
+ import { JapaneseAddressField } from '@/omnify/components';
103
+
104
+ <JapaneseAddressField
105
+ form={form}
106
+ schemas={customerSchemas}
107
+ i18n={customerI18n}
108
+ prefix="address"
109
+ enablePostalLookup={true} // Postal code → address lookup
110
+ />
111
+ ```
112
+
113
+ **Fields:** `{prefix}_postal_code`, `{prefix}_prefecture`, `{prefix}_address1`, `{prefix}_address2`, `{prefix}_address3`
114
+
115
+ **Options:**
116
+ - `enablePostalLookup` - Enable postal code search
117
+ - `autoSearch` - Auto-search when 7 digits entered
118
+ - `usePrefectureId` - Use numeric ID instead of string enum
119
+
120
+ ### JapaneseBankField
121
+
122
+ ```tsx
123
+ import { JapaneseBankField } from '@/omnify/components';
124
+
125
+ <JapaneseBankField
126
+ schemas={customerSchemas}
127
+ i18n={customerI18n}
128
+ prefix="bank"
129
+ />
130
+ ```
131
+
132
+ **Fields:** `{prefix}_bank_code`, `{prefix}_branch_code`, `{prefix}_account_type`, `{prefix}_account_number`, `{prefix}_account_holder`
133
+
134
+ Account type options auto-loaded from `BankAccountType` enum with i18n.
135
+
136
+ ## Complete Form Example
137
+
138
+ ```tsx
139
+ import { Form, Input, Button, Card, Space, Divider } from 'antd';
140
+ import type { FormInstance } from 'antd';
141
+ import { zodRule, setZodLocale } from '@/omnify/lib';
142
+ import { JapaneseNameField, JapaneseAddressField, JapaneseBankField } from '@/omnify/components';
143
+ import {
144
+ type Customer, type CustomerCreate,
145
+ customerSchemas, customerI18n,
146
+ getCustomerFieldLabel, getCustomerFieldPlaceholder,
147
+ } from '@/omnify/schemas';
148
+
149
+ const LOCALE = 'ja';
150
+
151
+ interface CustomerFormProps {
152
+ form: FormInstance<CustomerCreate>;
153
+ initialValues?: Partial<Customer>;
154
+ onSubmit: (values: CustomerCreate) => void;
155
+ loading?: boolean;
156
+ isEdit?: boolean;
157
+ }
158
+
159
+ export function CustomerForm({ form, initialValues, onSubmit, loading, isEdit }: CustomerFormProps) {
160
+ setZodLocale(LOCALE);
161
+
162
+ const label = (key: string) => getCustomerFieldLabel(key, LOCALE);
163
+ const placeholder = (key: string) => getCustomerFieldPlaceholder(key, LOCALE);
164
+ const rule = (key: keyof typeof customerSchemas) => zodRule(customerSchemas[key], label(key));
165
+
166
+ return (
167
+ <Card>
168
+ <Form form={form} layout="horizontal" labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}
169
+ initialValues={initialValues} onFinish={onSubmit} style={{ maxWidth: 800 }}>
170
+
171
+ <Divider orientation="left">氏名</Divider>
172
+ <JapaneseNameField schemas={customerSchemas} i18n={customerI18n} prefix="name" required />
173
+
174
+ <Divider orientation="left">連絡先</Divider>
175
+ <Form.Item name="phone" label={label('phone')} rules={[rule('phone')]}>
176
+ <Input placeholder={placeholder('phone')} />
177
+ </Form.Item>
178
+ <Form.Item name="email" label={label('email')} rules={[rule('email')]}>
179
+ <Input type="email" placeholder={placeholder('email')} />
180
+ </Form.Item>
181
+
182
+ <Divider orientation="left">住所</Divider>
183
+ <JapaneseAddressField form={form} schemas={customerSchemas} i18n={customerI18n}
184
+ prefix="address" enablePostalLookup={true} />
185
+
186
+ <Divider orientation="left">銀行口座</Divider>
187
+ <JapaneseBankField schemas={customerSchemas} i18n={customerI18n} prefix="bank" />
188
+
189
+ <Form.Item wrapperCol={{ offset: 6, span: 18 }}>
190
+ <Space>
191
+ <Button type="primary" htmlType="submit" loading={loading}>
192
+ {isEdit ? '更新' : '登録'}
193
+ </Button>
194
+ </Space>
195
+ </Form.Item>
196
+ </Form>
197
+ </Card>
198
+ );
199
+ }
200
+ ```
201
+
202
+ ## Zod Validation with i18n
203
+
204
+ ```tsx
205
+ import { zodRule, setZodLocale } from '@/omnify/lib';
206
+
207
+ // Set locale once at component level
208
+ setZodLocale('ja');
209
+
210
+ // Use zodRule for field validation
211
+ <Form.Item name="email" label={label('email')} rules={[zodRule(customerSchemas.email, label('email'))]}>
212
+ <Input />
213
+ </Form.Item>
214
+ ```
215
+
216
+ ## Kana Validation Rules
217
+
218
+ ```tsx
219
+ import { kanaString, KATAKANA_PATTERN } from '@/omnify/lib/rules';
220
+
221
+ // Full-width katakana (default)
222
+ const kanaSchema = kanaString();
223
+
224
+ // Custom options
225
+ const kanaSchema = kanaString({
226
+ fullWidthKatakana: true,
227
+ hiragana: true,
228
+ allowNumbers: true,
229
+ });
230
+ ```
231
+
232
+ ## File Structure
233
+
234
+ ```
235
+ resources/ts/omnify/
236
+ ├── components/
237
+ │ ├── JapaneseNameField.tsx
238
+ │ ├── JapaneseAddressField.tsx
239
+ │ └── JapaneseBankField.tsx
240
+ ├── enum/
241
+ │ └── plugin/
242
+ │ ├── Prefecture.ts
243
+ │ └── BankAccountType.ts
244
+ ├── hooks/
245
+ │ └── use-form-mutation.ts
246
+ ├── lib/
247
+ │ ├── form-validation.ts
248
+ │ ├── zod-i18n.ts
249
+ │ └── rules/kana.ts
250
+ └── schemas/
251
+ ```
252
+
253
+ ## Tips
254
+
255
+ 1. **Use type generics** - `useFormMutation<CustomerCreate>` for type safety
256
+ 2. **Use `setZodLocale`** - Call once for localized validation messages
257
+ 3. **Use Japanese* components** - Built-in i18n, validation, postal lookup
258
+ 4. **Set `invalidateKeys`** - Auto-refresh lists after mutations
259
+ 5. **Don't pass `form` to Name/Bank components** - Only Address needs it for postal lookup
@@ -145,6 +145,59 @@ export function isPostStatus(value: unknown): value is PostStatus {
145
145
  }
146
146
  ```
147
147
 
148
+ ## Display Names and Placeholders
149
+
150
+ Omnify generates multi-locale display names and placeholders for form inputs.
151
+
152
+ ```typescript
153
+ import {
154
+ UserDisplayName,
155
+ UserPropertyDisplayNames,
156
+ UserPropertyPlaceholders,
157
+ getUserDisplayName,
158
+ getUserPropertyDisplayName,
159
+ getUserPropertyPlaceholder,
160
+ } from './types/models/User';
161
+
162
+ // Get model display name
163
+ getUserDisplayName('ja'); // "ユーザー"
164
+ getUserDisplayName('en'); // "User"
165
+
166
+ // Get property display name
167
+ getUserPropertyDisplayName('email', 'ja'); // "メールアドレス"
168
+ getUserPropertyDisplayName('email', 'en'); // "Email"
169
+
170
+ // Get property placeholder
171
+ getUserPropertyPlaceholder('email', 'ja'); // "メールアドレスを入力"
172
+ getUserPropertyPlaceholder('email', 'en'); // "Enter your email"
173
+ ```
174
+
175
+ ### Using Placeholders in Forms
176
+
177
+ ```tsx
178
+ import { Form, Input } from 'antd';
179
+ import {
180
+ getUserRules,
181
+ getUserPropertyDisplayName,
182
+ getUserPropertyPlaceholder,
183
+ } from './types/models/User';
184
+
185
+ function UserForm({ locale = 'ja' }) {
186
+ const rules = getUserRules(locale);
187
+ return (
188
+ <Form>
189
+ <Form.Item
190
+ name="email"
191
+ label={getUserPropertyDisplayName('email', locale)}
192
+ rules={rules.email}
193
+ >
194
+ <Input placeholder={getUserPropertyPlaceholder('email', locale)} />
195
+ </Form.Item>
196
+ </Form>
197
+ );
198
+ }
199
+ ```
200
+
148
201
  ## Validation Rules (Ant Design)
149
202
 
150
203
  Omnify generates Ant Design compatible validation rules in `rules/` directory.