@wangs-ui/skills 1.0.39 → 1.0.41

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/dist/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as listSkills, n as updateSkills, r as addSkills, t as removeSkills } from "./src-95qOyh-g.js";
2
+ import { i as listSkills, n as updateSkills, r as addSkills, t as removeSkills } from "./src-Dolm1urJ.js";
3
3
  import path from "node:path";
4
4
  import { parseArgs } from "node:util";
5
5
  //#region bin.ts
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as getAgentSkillDirs, c as isSkillInstalled, d as loadAllSkills, i as listSkills, l as removeSkill, n as updateSkills, o as getInstalledSkills, r as addSkills, s as installSkill, t as removeSkills, u as getSkill } from "./src-95qOyh-g.js";
1
+ import { a as getAgentSkillDirs, c as isSkillInstalled, d as loadAllSkills, i as listSkills, l as removeSkill, n as updateSkills, o as getInstalledSkills, r as addSkills, s as installSkill, t as removeSkills, u as getSkill } from "./src-Dolm1urJ.js";
2
2
  export { addSkills, getAgentSkillDirs, getInstalledSkills, getSkill, installSkill, isSkillInstalled, listSkills, loadAllSkills, removeSkill, removeSkills, updateSkills };
@@ -1,166 +1,67 @@
1
1
  ---
2
2
  name: create-form
3
- description: Real-world patterns for building strongly-typed forms, multipart file uploads, server validation mapping, and dirty tracking with @wangs-ui/form.
3
+ description: Architecture, validation workflows, and MCP discovery protocol for building forms and input controls with @wangs-ui/react-core.
4
4
  ---
5
5
 
6
- # Skill: Real-World Form Workflows with `@wangs-ui/form`
6
+ # Skill: Form Architecture & Validation Workflows
7
7
 
8
- Use this skill when building CRUD forms, data entry dialogs, multi-field settings pages, or multipart forms in Wangs UI applications.
8
+ Use this skill when building forms, data entry panels, settings pages, or multipart forms in Wangs UI applications.
9
9
 
10
10
  ---
11
11
 
12
- ## 1. MCP Inspection Step (Before Building Fields)
12
+ ## 1. MCP Inspection Protocol (Mandatory Single Source of Truth)
13
13
 
14
- Before implementing specific input controls, query the MCP server to inspect their exact prop signatures:
14
+ Do **NOT** hardcode or guess prop names, field configurations, or validation options. Retrieve active component definitions and live implementation stories directly from MCP:
15
15
 
16
- - `get-documentation({ id: "select" })` — Check option formats (`{ label, value }` vs object).
17
- - `get-documentation({ id: "datepicker" })` — Check `selectionMode` (`single`, `range`, `multiple`) and date format props.
18
- - `get-documentation({ id: "multiselect" })` — Check chips display and filter behavior.
19
- - `get-documentation({ id: "fileupload" })` — Check accepted mime types and upload handlers.
16
+ ### Inspect Component & Form Contracts:
20
17
 
21
- ---
22
-
23
- ## 2. Recipe 1: Standard CRUD Form with Server Validation Mapping
24
-
25
- Real-world forms must handle async submission, loading state, and map backend validation errors back into `<Field>` errors:
26
-
27
- ```tsx
28
- import React, { useState } from 'react';
29
- import Card from '@wangs-ui/react-core/primitive/card';
30
- import Button from '@wangs-ui/react-core/primitive/button';
31
- import InputText from '@wangs-ui/react-core/primitive/inputtext';
32
- import Select from '@wangs-ui/react-core/primitive/select';
33
- import { Form, Field } from '@wangs-ui/react-core';
34
- import { useFormControl } from '@wangs-ui/form';
35
- import { useI18n } from '@wangs-ui/react-i18n';
36
-
37
- interface UserFormValues {
38
- fullName: string;
39
- email: string;
40
- role: string;
41
- }
42
-
43
- export default function UserForm({ onSuccess }: { onSuccess?: () => void }) {
44
- const { t } = useI18n();
45
- const formControl = useFormControl<UserFormValues>({ type: 'json' });
46
- const [isSubmitting, setIsSubmitting] = useState(false);
47
-
48
- const roleOptions = [
49
- { label: t('Administrator'), value: 'admin' },
50
- { label: t('Operator'), value: 'operator' },
51
- { label: t('Viewer'), value: 'viewer' },
52
- ];
53
-
54
- const handleSubmit = async (values: UserFormValues) => {
55
- setIsSubmitting(true);
56
- try {
57
- // Execute API call: await api.createUser(values);
58
- onSuccess?.();
59
- } catch (err: any) {
60
- // Map server validation error directly to field
61
- if (err?.fieldErrors?.email) {
62
- formControl.setError('email', {
63
- type: 'server',
64
- message: err.fieldErrors.email,
65
- });
66
- }
67
- } finally {
68
- setIsSubmitting(false);
69
- }
70
- };
71
-
72
- return (
73
- <Card className="p-6">
74
- <Form control={formControl} onSubmit={handleSubmit} className="flex flex-col gap-m">
75
- <h2 className="heading-2">{t('User Information')}</h2>
76
-
77
- {/* Text Field */}
78
- <Field<string>
79
- name="fullName"
80
- label={t('Full Name')}
81
- required
82
- rules={{ required: t('Full name is required') }}
83
- >
84
- {(field) => (
85
- <InputText {...field} placeholder={t('e.g. Jane Doe')} value={field.value || ''} />
86
- )}
87
- </Field>
88
-
89
- {/* Email Field with Regex Validation */}
90
- <Field<string>
91
- name="email"
92
- label={t('Email Address')}
93
- required
94
- rules={{
95
- required: t('Email is required'),
96
- pattern: {
97
- value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
98
- message: t('Enter a valid email address'),
99
- },
100
- }}
101
- >
102
- {(field) => (
103
- <InputText {...field} placeholder={t('name@company.com')} value={field.value || ''} />
104
- )}
105
- </Field>
106
-
107
- {/* Select Dropdown Field */}
108
- <Field<string>
109
- name="role"
110
- label={t('Access Role')}
111
- required
112
- rules={{ required: t('Role selection is required') }}
113
- >
114
- {(field) => (
115
- <Select
116
- {...field}
117
- options={roleOptions}
118
- placeholder={t('Select role')}
119
- value={field.value}
120
- onChange={(e) => field.onChange(e.value)}
121
- />
122
- )}
123
- </Field>
124
-
125
- {/* Form Actions */}
126
- <div className="flex justify-end gap-s pt-s">
127
- <Button
128
- type="button"
129
- variant="text"
130
- label={t('Reset')}
131
- onClick={() => formControl.reset()}
132
- disabled={isSubmitting}
133
- />
134
- <Button type="submit" label={t('Save User')} severity="primary" loading={isSubmitting} />
135
- </div>
136
- </Form>
137
- </Card>
138
- );
139
- }
18
+ ```json
19
+ get-documentation({ "id": "form" })
20
+ get-documentation({ "id": "field" })
21
+ get-documentation({ "id": "input" })
22
+ get-documentation({ "id": "numberinput" })
23
+ get-documentation({ "id": "select" })
24
+ get-documentation({ "id": "multiselect" })
25
+ get-documentation({ "id": "datepicker" })
26
+ get-documentation({ "id": "fileupload" })
140
27
  ```
141
28
 
142
- ---
29
+ ### Inspect Live Story Implementations:
30
+
31
+ ```json
32
+ get-documentation-for-story({ "id": "form", "storyName": "Default" })
33
+ get-documentation-for-story({ "id": "field", "storyName": "Default" })
34
+ get-documentation-for-story({ "id": "select", "storyName": "Basic" })
35
+ get-documentation-for-story({ "id": "datepicker", "storyName": "Default" })
36
+ get-documentation-for-story({ "id": "fileupload", "storyName": "Default" })
37
+ ```
143
38
 
144
- ## 3. Recipe 2: Multipart Form (File Upload + Metadata)
39
+ ### Inspect Knowledge Graph & Usages:
145
40
 
146
- For file uploads (avatar, attachment, documents), set `type: 'formdata'`:
41
+ ```json
42
+ query_graph({ "query": "useFormControl" })
43
+ query_graph({ "query": "Field" })
44
+ ```
147
45
 
148
- ```tsx
149
- import { useFormControl } from '@wangs-ui/form';
46
+ ---
150
47
 
151
- interface ProfileUploadValues {
152
- displayName: string;
153
- avatar: File | null;
154
- }
48
+ ## 2. Form Architecture & State Principles
155
49
 
156
- // Generates FormData under the hood
157
- const formControl = useFormControl<ProfileUploadValues>({ type: 'formdata' });
158
- ```
50
+ 1. **State & Control**:
51
+ - Standard REST payload forms use `useFormControl` with JSON mode.
52
+ - Multipart file upload workflows use `useFormControl` with FormData mode.
53
+ 2. **Field Composition**:
54
+ - Form inputs are wrapped with `<Field>` layout containers for unified label, tooltip, helper text, and error rendering.
55
+ - Exact props, slot rendering functions, and field binding options must be retrieved via MCP (`get-documentation({ "id": "field" })`).
56
+ 3. **Server Validation Error Mapping**:
57
+ - Backend validation responses (e.g. `422 Unprocessable Entity`) are mapped back into the form instance via `formControl.setError()`.
58
+ 4. **Submission Lifecycle**:
59
+ - In-flight network requests should manage loading state on submit actions and prevent accidental reset during mutations.
159
60
 
160
61
  ---
161
62
 
162
- ## 4. Key Implementation Rules
63
+ ## 3. Mandatory Implementation Rules
163
64
 
164
- 1. **Always Use `<Form>` & `<Field>`**: Never bind raw uncontrolled inputs.
165
- 2. **Translate All Labels & Error Messages**: Wrap text in `t('...')`.
166
- 3. **Handle Loading State**: Disable reset buttons and set `loading={isSubmitting}` on submit buttons.
65
+ 1. **Always Query MCP First**: Never guess input props or event signatures; obtain the exact types from `get-documentation`.
66
+ 2. **Strict Subpath Imports**: All components must be imported via their granular subpath (`@wangs-ui/react-core/primitive/*`, `@wangs-ui/form`).
67
+ 3. **Translate All Visible Strings**: Every field label, placeholder, helper text, and error message must be wrapped in `t('...')` from `@wangs-ui/react-i18n`.
@@ -1,178 +1,68 @@
1
1
  ---
2
2
  name: data-table
3
- description: Real-world patterns for building full CRUD DataTables with server pagination, search filters, batch actions, and confirmation modals.
3
+ description: Architecture, workflows, and MCP discovery protocol for building DataTables with sorting, pagination, filtering, selection, and export.
4
4
  ---
5
5
 
6
- # Skill: Real-World DataTable & Filter Workflows
6
+ # Skill: DataTable Architecture & Integration Workflows
7
7
 
8
- Use this skill when building administrative grids, filtered listing pages, or management dashboards with `@wangs-ui/react-core`.
8
+ Use this skill when implementing data grids, server-paginated tables, filterable listing views, or batch management interfaces with `@wangs-ui/react-core`.
9
9
 
10
10
  ---
11
11
 
12
- ## 1. MCP Inspection Step (Before Building Table)
12
+ ## 1. MCP Inspection Protocol (Mandatory Single Source of Truth)
13
13
 
14
- Query the MCP server to inspect supported features and slots:
14
+ Do **NOT** guess table prop names or hardcode table structures. Query the MCP server dynamically to inspect exact TypeScript signatures, live story implementations, and companion controls:
15
15
 
16
- - `get-documentation({ id: "datatable" })` — Check `paginator`, `lazy`, `onPage`, `onSort`, `selectionMode`, and `dataKey`.
17
- - `get-documentation({ id: "column" })` — Check `body` template, `sortable`, `frozen`, and `headerStyle`.
18
- - `get-documentation({ id: "tag" })` — Check severity colors for status pill badges (`success`, `warning`, `danger`, `info`).
16
+ ### Inspect Component Contracts:
19
17
 
20
- ---
18
+ ```json
19
+ get-documentation({ "id": "datatable" })
20
+ get-documentation({ "id": "exportbutton" })
21
+ get-documentation({ "id": "filtercontainer" })
22
+ get-documentation({ "id": "bulkactionbutton" })
23
+ ```
24
+
25
+ ### Inspect Live Story Implementations:
26
+
27
+ ```json
28
+ get-documentation-for-story({ "id": "datatable", "storyName": "Basic" })
29
+ get-documentation-for-story({ "id": "datatable", "storyName": "ServerPagination" })
30
+ get-documentation-for-story({ "id": "datatable", "storyName": "Sortable" })
31
+ get-documentation-for-story({ "id": "datatable", "storyName": "MultipleSelection" })
32
+ get-documentation-for-story({ "id": "datatable", "storyName": "CustomColumn" })
33
+ get-documentation-for-story({ "id": "exportbutton", "storyName": "WithTable" })
34
+ ```
35
+
36
+ ### Inspect Knowledge Graph & Usages:
21
37
 
22
- ## 2. Recipe: Full CRUD Data Grid with Filter Toolbar & Batch Actions
23
-
24
- ```tsx
25
- import React, { useState } from 'react';
26
- import DataTable, { Column } from '@wangs-ui/react-core/primitive/datatable';
27
- import Button from '@wangs-ui/react-core/primitive/button';
28
- import InputText from '@wangs-ui/react-core/primitive/inputtext';
29
- import Select from '@wangs-ui/react-core/primitive/select';
30
- import Tag from '@wangs-ui/react-core/primitive/tag';
31
- import Dialog from '@wangs-ui/react-core/primitive/dialog';
32
- import Card from '@wangs-ui/react-core/primitive/card';
33
- import { useI18n } from '@wangs-ui/react-i18n';
34
- import { SearchLine, DeleteBin6Line, EditLine, AddLine } from '@wangs-ui/react-icons';
35
-
36
- interface CustomerRecord {
37
- id: string;
38
- name: string;
39
- email: string;
40
- status: 'active' | 'pending' | 'suspended';
41
- createdAt: string;
42
- }
43
-
44
- export default function CustomerManagementView() {
45
- const { t } = useI18n();
46
- const [records, setRecords] = useState<CustomerRecord[]>([]);
47
- const [loading, setLoading] = useState(false);
48
- const [searchQuery, setSearchQuery] = useState('');
49
- const [selectedStatus, setSelectedStatus] = useState<string | null>(null);
50
- const [selectedRows, setSelectedRows] = useState<CustomerRecord[]>([]);
51
- const [deleteTarget, setDeleteTarget] = useState<CustomerRecord | null>(null);
52
-
53
- // Status Badge Template
54
- const statusTemplate = (row: CustomerRecord) => {
55
- const severityMap: Record<string, 'success' | 'warning' | 'danger'> = {
56
- active: 'success',
57
- pending: 'warning',
58
- suspended: 'danger',
59
- };
60
- return <Tag value={t(row.status)} severity={severityMap[row.status] || 'info'} />;
61
- };
62
-
63
- // Row Actions Template
64
- const actionsTemplate = (row: CustomerRecord) => (
65
- <div className="flex items-center gap-xs">
66
- <Button
67
- variant="text"
68
- icon={<EditLine />}
69
- aria-label={t('Edit')}
70
- onClick={() => console.log('Edit', row.id)}
71
- />
72
- <Button
73
- variant="text"
74
- severity="danger"
75
- icon={<DeleteBin6Line />}
76
- aria-label={t('Delete')}
77
- onClick={() => setDeleteTarget(row)}
78
- />
79
- </div>
80
- );
81
-
82
- return (
83
- <Card className="flex flex-col gap-m p-6">
84
- {/* 1. Filter & Search Toolbar */}
85
- <div className="flex flex-wrap items-center justify-between gap-s">
86
- <div className="flex flex-wrap items-center gap-s">
87
- <InputText
88
- value={searchQuery}
89
- onChange={(e) => setSearchQuery(e.target.value)}
90
- placeholder={t('Search customer...')}
91
- className="w-64"
92
- />
93
- <Select
94
- value={selectedStatus}
95
- options={[
96
- { label: t('All Statuses'), value: null },
97
- { label: t('Active'), value: 'active' },
98
- { label: t('Pending'), value: 'pending' },
99
- { label: t('Suspended'), value: 'suspended' },
100
- ]}
101
- onChange={(e) => setSelectedStatus(e.value)}
102
- placeholder={t('Filter status')}
103
- />
104
- </div>
105
-
106
- <Button label={t('Add Customer')} icon={<AddLine />} severity="primary" />
107
- </div>
108
-
109
- {/* 2. Batch Selection Action Bar */}
110
- {selectedRows.length > 0 && (
111
- <div className="flex items-center justify-between rounded bg-primary-50 px-4 py-2 text-primary-900">
112
- <span className="p font-medium">
113
- {t('{{count}} items selected', { count: selectedRows.length })}
114
- </span>
115
- <Button
116
- size="small"
117
- severity="danger"
118
- label={t('Delete Selected')}
119
- icon={<DeleteBin6Line />}
120
- onClick={() => console.log('Batch delete', selectedRows)}
121
- />
122
- </div>
123
- )}
124
-
125
- {/* 3. Paginated DataTable */}
126
- <DataTable
127
- value={records}
128
- loading={loading}
129
- selection={selectedRows}
130
- onSelectionChange={(e) => setSelectedRows(e.value)}
131
- dataKey="id"
132
- paginator
133
- rows={10}
134
- rowsPerPageOptions={[10, 25, 50]}
135
- emptyMessage={t('No customers found')}
136
- >
137
- <Column selectionMode="multiple" headerStyle={{ width: '3rem' }} />
138
- <Column field="name" header={t('Customer Name')} sortable />
139
- <Column field="email" header={t('Email')} sortable />
140
- <Column field="status" header={t('Status')} body={statusTemplate} sortable />
141
- <Column header={t('Actions')} body={actionsTemplate} headerStyle={{ width: '6rem' }} />
142
- </DataTable>
143
-
144
- {/* 4. Delete Confirmation Dialog */}
145
- <Dialog
146
- visible={!!deleteTarget}
147
- onHide={() => setDeleteTarget(null)}
148
- header={t('Delete Customer')}
149
- footer={
150
- <div className="flex justify-end gap-xs">
151
- <Button variant="text" label={t('Cancel')} onClick={() => setDeleteTarget(null)} />
152
- <Button
153
- severity="danger"
154
- label={t('Delete')}
155
- onClick={() => {
156
- // Execute delete API
157
- setDeleteTarget(null);
158
- }}
159
- />
160
- </div>
161
- }
162
- >
163
- <p className="p">
164
- {t('Are you sure you want to delete {{name}}?', { name: deleteTarget?.name })}
165
- </p>
166
- </Dialog>
167
- </Card>
168
- );
169
- }
38
+ ```json
39
+ query_graph({ "query": "DataTable" })
40
+ query_graph({ "query": "useDataTableFetch" })
170
41
  ```
171
42
 
172
43
  ---
173
44
 
174
- ## 3. Mandatory Best Practices
45
+ ## 2. Core Architecture & Mental Model
46
+
47
+ The Wangs UI `DataTable` is built on a modular, headless-first architecture:
48
+
49
+ 1. **Declarative Column Definitions (`TableColumn<T>[]`)**:
50
+ Columns are configured as typed array objects, not as JSX children. Check `get-documentation({ "id": "datatable" })` for column field types.
51
+ 2. **Table Instance Hook (`useDataTable`)**:
52
+ Coordinates table state (sorting, pagination, selection, column ordering, pinning, visibility).
53
+ 3. **Data Fetching Hook (`useDataTableFetch`)**:
54
+ Feeds server-side data, handles loading indicators, manages query parameters (`search`, `filter`, `sort`, `page`, `limit`), and debounces requests automatically.
55
+ 4. **Ecosystem Companions**:
56
+ - `FilterContainer` & `FilterToggleButton`: Filter popovers and faceted search.
57
+ - `ExportButton`: Client/server export to Excel, CSV, PDF, or Print.
58
+ - `BulkActionButton`: Contextual batch actions triggered when rows are selected.
59
+ - `CustomColumn`: User-controlled column ordering, visibility toggling, and pinning.
60
+
61
+ ---
62
+
63
+ ## 3. Mandatory Implementation Rules
175
64
 
176
- 1. **Always Supply `dataKey`**: Never enable row selection without `dataKey="id"`.
177
- 2. **Translate All Headers & Messages**: Pass table headers and empty state messages into `t()`.
178
- 3. **Control Batch Action Appearance**: Show batch action banner only when `selectedRows.length > 0`.
65
+ 1. **Query MCP for Current Code Patterns**: Always run `get-documentation-for-story` for `datatable` before drafting code.
66
+ 2. **Strict Subpath Imports**: Import via `@wangs-ui/react-core/primitive/datatable` and companion primitive paths.
67
+ 3. **Always Translate Visible Copy**: All column header labels, empty state messages, and action button labels must be wrapped in `t('...')` from `@wangs-ui/react-i18n`.
68
+ 4. **Stable Row Identity**: Always configure a unique key identifier for stable selection and row identity.
@@ -1,131 +1,58 @@
1
1
  ---
2
2
  name: dialog-modal
3
- description: Real-world patterns for modal forms, async confirmation workflows, and multi-step dialogs with Wangs UI Dialog and Modal components.
3
+ description: Patterns, overlay selection criteria, and MCP discovery protocol for Dialog, Modal, and DialogForm components in Wangs UI.
4
4
  ---
5
5
 
6
- # Skill: Real-World Dialog & Modal Workflows
6
+ # Skill: Dialog, Modal & Overlay Workflows
7
7
 
8
- Use this skill when building interactive modals, create/edit modal forms, destructive action confirmations, or slide-in overlay panels.
8
+ Use this skill when building interactive modals, create/edit dialog forms, destructive action confirmations, or slide-in overlay panels.
9
9
 
10
10
  ---
11
11
 
12
- ## 1. MCP Inspection Step (Before Implementing Overlays)
12
+ ## 1. MCP Inspection Protocol (Mandatory Single Source of Truth)
13
13
 
14
- Query the MCP server to check overlay configuration and animation options:
14
+ Do **NOT** guess overlay props, event names, or footer slots. Query the MCP server dynamically to inspect exact contracts and live story implementations:
15
15
 
16
- - `get-documentation({ id: "dialog" })` — Check `header`, `footer`, `visible`, `onHide`, `modal`, and `dismissableMask`.
17
- - `get-documentation({ id: "modal" })` — Check fullscreen modes, size variants, and slide-in drawer options.
18
- - `get-documentation({ id: "toast" })` — Check severity toasts (`success`, `error`, `info`, `warn`) to trigger after modal actions.
16
+ ### Inspect Overlay Contracts:
19
17
 
20
- ---
18
+ ```json
19
+ get-documentation({ "id": "dialog" })
20
+ get-documentation({ "id": "dialogform" })
21
+ get-documentation({ "id": "modal" })
22
+ get-documentation({ "id": "toast" })
23
+ ```
24
+
25
+ ### Inspect Live Story Implementations:
26
+
27
+ ```json
28
+ get-documentation-for-story({ "id": "dialog", "storyName": "Confirmation" })
29
+ get-documentation-for-story({ "id": "dialogform", "storyName": "Default" })
30
+ get-documentation-for-story({ "id": "modal", "storyName": "Default" })
31
+ ```
21
32
 
22
- ## 2. Recipe: Create/Edit Form inside a Modal Dialog
23
-
24
- This real-world recipe coordinates a modal wrapper with an embedded `@wangs-ui/form`, handles saving state, prevents accidental dismiss while saving, and resets state upon close:
25
-
26
- ```tsx
27
- import React, { useState, useEffect } from 'react';
28
- import Dialog from '@wangs-ui/react-core/primitive/dialog';
29
- import Button from '@wangs-ui/react-core/primitive/button';
30
- import InputText from '@wangs-ui/react-core/primitive/inputtext';
31
- import { Form, Field } from '@wangs-ui/react-core';
32
- import { useFormControl } from '@wangs-ui/form';
33
- import { useI18n } from '@wangs-ui/react-i18n';
34
-
35
- interface EditItemModel {
36
- title: string;
37
- code: string;
38
- }
39
-
40
- interface ItemModalProps {
41
- visible: boolean;
42
- item?: EditItemModel | null;
43
- onHide: () => void;
44
- onSaved: (item: EditItemModel) => void;
45
- }
46
-
47
- export default function ItemFormModal({ visible, item, onHide, onSaved }: ItemModalProps) {
48
- const { t } = useI18n();
49
- const formControl = useFormControl<EditItemModel>({ type: 'json' });
50
- const [saving, setSaving] = useState(false);
51
-
52
- // Sync form values when modal opens or item changes
53
- useEffect(() => {
54
- if (visible) {
55
- formControl.reset(item || { title: '', code: '' });
56
- }
57
- }, [visible, item]);
58
-
59
- const handleFormSubmit = async (values: EditItemModel) => {
60
- setSaving(true);
61
- try {
62
- // Execute API call: await api.save(values);
63
- onSaved(values);
64
- onHide();
65
- } finally {
66
- setSaving(false);
67
- }
68
- };
69
-
70
- const footerActions = (
71
- <div className="flex justify-end gap-xs">
72
- <Button type="button" variant="text" label={t('Cancel')} onClick={onHide} disabled={saving} />
73
- <Button
74
- type="submit"
75
- form="modal-item-form"
76
- label={item ? t('Save Changes') : t('Create Item')}
77
- severity="primary"
78
- loading={saving}
79
- />
80
- </div>
81
- );
82
-
83
- return (
84
- <Dialog
85
- visible={visible}
86
- onHide={() => !saving && onHide()}
87
- header={item ? t('Edit Item') : t('New Item')}
88
- footer={footerActions}
89
- style={{ width: '450px' }}
90
- modal
91
- >
92
- <Form
93
- id="modal-item-form"
94
- control={formControl}
95
- onSubmit={handleFormSubmit}
96
- className="flex flex-col gap-m pt-xs"
97
- >
98
- <Field<string>
99
- name="title"
100
- label={t('Item Title')}
101
- required
102
- rules={{ required: t('Title is required') }}
103
- >
104
- {(field) => (
105
- <InputText {...field} placeholder={t('Enter title')} value={field.value || ''} />
106
- )}
107
- </Field>
108
-
109
- <Field<string>
110
- name="code"
111
- label={t('Item Code')}
112
- required
113
- rules={{ required: t('Code is required') }}
114
- >
115
- {(field) => (
116
- <InputText {...field} placeholder={t('e.g. SKU-100')} value={field.value || ''} />
117
- )}
118
- </Field>
119
- </Form>
120
- </Dialog>
121
- );
122
- }
33
+ ### Inspect Knowledge Graph & Usages:
34
+
35
+ ```json
36
+ query_graph({ "query": "Dialog" })
37
+ query_graph({ "query": "DialogForm" })
123
38
  ```
124
39
 
125
40
  ---
126
41
 
127
- ## 3. Mandatory Best Practices
42
+ ## 2. Overlay Selection Matrix
43
+
44
+ | Component | Primary Use Case | Key Characteristics |
45
+ | :--------------- | :-------------------------------------------- | :------------------------------------------------------------------------------------ |
46
+ | **`Dialog`** | Confirmations, alerts, simple detail previews | Standard `header`, `footer`, and body layout; built-in backdrop dimming. |
47
+ | **`DialogForm`** | Create/Edit forms embedded inside a dialog | Built-in form submit/cancel action bar, dirty state tracking, and submit lifecycle. |
48
+ | **`Modal`** | Slide-in drawers, complex custom viewports | Headless overlay primitive with flexible animations, size variants, and drawer modes. |
49
+
50
+ ---
51
+
52
+ ## 3. Mandatory Implementation Rules
128
53
 
129
- 1. **Decouple Submit Button from Form Body**: Use `form="modal-item-form"` on the submit button inside `footer` so actions stay neatly aligned in the footer bar.
130
- 2. **Prevent Close During Mutation**: Guard `onHide={() => !saving && onHide()}` to prevent accidental dismissal during in-flight network requests.
131
- 3. **Always Reset on Open**: Sync initial values in an effect keyed on `visible`.
54
+ 1. **Query MCP for Current Code Patterns**: Always inspect `dialog`, `dialogform`, or `modal` stories via MCP before writing overlay code.
55
+ 2. **Strict Subpath Imports**: Import via `@wangs-ui/react-core/primitive/dialog`, `@wangs-ui/react-core/primitive/dialogform`, `@wangs-ui/react-core/primitive/modal`, or `@wangs-ui/react-core/primitive/toast`.
56
+ 3. **Prevent Dismissal During Async Mutations**: Guard the close handler so users cannot accidentally dismiss the dialog while a mutation request is in-flight.
57
+ 4. **Coordinate with Toast Notifications**: Trigger feedback toasts on successful creation, update, or deletion actions.
58
+ 5. **Translate All Overlay Copy**: All dialog titles, confirmation descriptions, and button labels must be localized using `t('...')` from `@wangs-ui/react-i18n`.