Skip to content

Commit 0d4ab0b

Browse files
authored
fix(docs): live editor issues (#59)
* fix: live editor width * fix: Form docs * chore: update diagram * chore: update
1 parent 292c0a8 commit 0d4ab0b

File tree

3 files changed

+117
-29
lines changed

3 files changed

+117
-29
lines changed

apps/docs/src/components/demo-block/demo-block.scss

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@
3232
&__editor-container {
3333
background-color: var(--ty-color-fill);
3434
border-top: solid 1px var(--ty-color-border-secondary);
35-
overflow-x: auto;
35+
// Wrap editor text instead of forcing horizontal scrolling.
36+
overflow-x: hidden;
3637
font-family: Menlo, Consolas, "Droid Sans Mono", monospace;
3738
font-size: 13px;
3839
line-height: 1.6;
3940
tab-size: 2;
4041
}
4142

4243
&__editor-wrapper {
43-
max-width: 800px;
4444
width: 100%;
4545
}
4646

@@ -50,6 +50,10 @@
5050
pre {
5151
margin: 0;
5252
pointer-events: none;
53+
// Ensure long lines wrap in the highlighted background layer.
54+
white-space: pre-wrap;
55+
word-break: break-word;
56+
overflow-wrap: anywhere;
5357
}
5458
}
5559

@@ -73,7 +77,10 @@
7377
font-size: inherit;
7478
line-height: inherit;
7579
tab-size: inherit;
76-
white-space: pre;
80+
// Keep caret + selection aligned with the highlighted background layer.
81+
white-space: pre-wrap;
82+
word-break: break-word;
83+
overflow-wrap: anywhere;
7784
box-sizing: border-box;
7885

7986
&::selection {

packages/react/src/form/ARCHITECTURE.md

Lines changed: 104 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -68,56 +68,113 @@ The `validate` function checks a value against a `Rule` supporting: `required`,
6868

6969
```mermaid
7070
graph TD
71-
subgraph Form["<Form>"]
71+
subgraph Form["<Form> Provider"]
7272
FI["FormInstance (useRef)"]
7373
FIC["FormInstanceContext.Provider"]
7474
FOC["FormOptionsContext.Provider"]
7575
end
7676
77-
subgraph FormItem1["<Form.Item name='username'>"]
78-
SUB1["subscribe(listener)"]
79-
CE1["cloneElement(child, {value, onChange, onBlur})"]
80-
ERR1["Error display with Transition"]
77+
subgraph FormItem1["Form.Item (name='username')"]
78+
CE1["cloneElement → {value, onChange, onBlur}"]
8179
end
8280
83-
subgraph FormItem2["<Form.Item name='password'>"]
84-
SUB2["subscribe(listener)"]
85-
CE2["cloneElement(child, {value, onChange, onBlur})"]
86-
ERR2["Error display with Transition"]
81+
subgraph FormItem2["Form.Item (name='password')"]
82+
CE2["cloneElement → {value, onChange, onBlur}"]
83+
end
84+
85+
subgraph Input1["Input (controlled by value prop)"]
86+
V1["value: from useState"]
87+
end
88+
89+
subgraph Input2["Input (controlled by value prop)"]
90+
V2["value: from useState"]
8791
end
8892
8993
FI --> FIC
94+
FI --> FOC
9095
FIC --> FormItem1
9196
FIC --> FormItem2
9297
FOC --> FormItem1
9398
FOC --> FormItem2
99+
100+
FormItem1 --> CE1 --> V1
101+
FormItem2 --> CE2 --> V2
102+
```
103+
104+
### Subscribe/Notify Pattern (Pub/Sub)
105+
106+
```mermaid
107+
graph LR
108+
subgraph FormInstance["FormInstance (Central Store)"]
109+
VALUES["values: { username: '', password: '' }"]
110+
ERRORS["errors: { email: ['Invalid email'] }"]
111+
RULES["rules: { username: [...], email: [...] }"]
112+
LISTENERS["listeners: [listener1, listener2, ...]"]
113+
NOTIFY["notify(name)"]
114+
end
115+
116+
subgraph FormItem_A["Form.Item(name='username')"]
117+
SUB_A["subscribe(callback)"]
118+
CALLBACK_A["callback(n) { if n==='username' setValue() }"]
119+
end
120+
121+
subgraph FormItem_B["Form.Item(name='email')"]
122+
SUB_B["subscribe(callback)"]
123+
CALLBACK_B["callback(n) { if n==='email' setValue() }"]
124+
end
125+
126+
subgraph FormItem_C["Form.Item(name='password')"]
127+
SUB_C["subscribe(callback)"]
128+
CALLBACK_C["callback(n) { if n==='password' setValue() }"]
129+
end
130+
131+
NOTIFY -->|"notify('email')"| LISTENERS
132+
LISTENERS -->|"→ listener_A"| CALLBACK_A
133+
LISTENERS -->|"→ listener_B"| CALLBACK_B
134+
LISTENERS -->|"→ listener_C"| CALLBACK_C
135+
136+
SUB_A -.->|"adds listener_A"| LISTENERS
137+
SUB_B -.->|"adds listener_B"| LISTENERS
138+
SUB_C -.->|"adds listener_C"| LISTENERS
139+
140+
style CALLBACK_A fill:#ffcccc
141+
style CALLBACK_B fill:#ccffcc
142+
style CALLBACK_C fill:#ffcccc
94143
```
95144

96-
### Data Flow: User Input
145+
### Data Flow: User Input → UI Update (Controlled)
97146

98147
```mermaid
99148
sequenceDiagram
100149
participant User
101-
participant Input as Child Input
150+
participant Input as <Input />
102151
participant Item as Form.Item
103152
participant Store as FormInstance
153+
participant Item2 as Form.Item (other)
104154
105-
Note over Item: On mount: subscribe + setFieldRules
155+
Note over Item: Mount: subscribe(listener) + setFieldRules(name, rules)
106156
107-
User->>Input: Types a character
108-
Input->>Item: onChange fires
109-
Item->>Store: setFieldValue(name, value)
110-
Store->>Store: notify(name)
111-
Store->>Item: Listener callback fires
112-
Item->>Item: setValue → re-render
113-
Item->>Input: cloneElement with new value
157+
User->>Input: Types "a"
158+
Input->>Item: onChange("a")
159+
Item->>Store: setFieldValue("field", "a")
160+
Store->>Store: values["field"] = "a"
161+
Store->>Store: notify("field")
162+
Store->>Item: listener("field") fires
163+
Store->>Item2: listener("field") fires
164+
165+
Note over Item2: n === "field" but name !== "field"<br/>→ ignore, no update
166+
167+
Item->>Item: setValue("a") → re-render
168+
Item->>Input: cloneElement injects new value="a"
169+
170+
Note over Input: Controlled: displays "a"
114171
115172
alt validateTrigger === "onChange"
116-
Item->>Store: validateField(name)
117-
Store->>Store: run rules via validate()
118-
Store->>Store: setFieldError + notify
119-
Store->>Item: Listener fires again
120-
Item->>Item: setError → show/hide error
173+
Item->>Store: validateField("field")
174+
Store->>Store: run validate() on rules
175+
Store->>Store: setFieldError + notify("field")
176+
Store->>Item: listener fires again
177+
Item->>Item: setError() → show/hide error
121178
end
122179
```
123180

@@ -133,7 +190,7 @@ sequenceDiagram
133190
User->>Form: Submit
134191
Form->>Form: e.preventDefault()
135192
Form->>Store: validateFields()
136-
Store->>Store: validateField() for each rule set
193+
Store->>Store: validateField() for each field with rules
137194
Store->>Items: notify each field name
138195
Items->>Items: Update error states
139196
@@ -161,7 +218,28 @@ sequenceDiagram
161218
Store->>Store: errors = {}
162219
Store->>Store: values = deepCopy(initValues)
163220
Store->>Items: notify("*")
164-
Items->>Items: All items re-read value and error → re-render
221+
Items->>Items: All items: name === "*" or n === "*" → true<br/>→ setValue() + setError() → re-render
222+
```
223+
224+
### Controlled Component Pattern
225+
226+
```mermaid
227+
graph TD
228+
subgraph FormItem["Form.Item"]
229+
STATE["useState<br/>value, error"]
230+
ONCHANGE["onChange(...args)<br/>form.setFieldValue()<br/>form.validateField()"]
231+
CLONE["React.cloneElement<br/>{ value, onChange, onBlur }"]
232+
end
233+
234+
subgraph Child["Child Input"]
235+
PROP["value prop<br/>(controlled)"]
236+
INTERNAL["no internal state used"]
237+
end
238+
239+
STATE -->|"on mount"| CLONE
240+
ONCHANGE -->|"on input"| CLONE
241+
CLONE -->|"props"| PROP
242+
PROP -->|"user types"| ONCHANGE
165243
```
166244

167245
### Validation Rules

packages/react/src/form/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,15 @@ Simulate an async form submission with loading state.
115115
</Column>
116116
</Layout>
117117

118+
<Demo>
118119
### Other Form Controls
119120

120121
A versatile example.
121122

122123
<DemoBlock component={OtherControlsDemo} source={OtherControlsSource} />
123124

125+
</Demo>
126+
124127
## API
125128

126129
### Form

0 commit comments

Comments
 (0)