@estiva-app/ui 0.73.0-inline-text.1 → 0.73.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/dist/InlineText.d.ts.map +1 -1
- package/dist/editor.js +17 -4
- package/dist/editor.js.map +2 -2
- package/package.json +1 -1
- package/registry.json +1 -1
- package/src/InlineText.test.tsx +21 -0
- package/src/InlineText.tsx +21 -4
package/package.json
CHANGED
package/registry.json
CHANGED
package/src/InlineText.test.tsx
CHANGED
|
@@ -168,6 +168,27 @@ describe('InlineText: a refused save, and a change from elsewhere', () => {
|
|
|
168
168
|
expect(field().textContent).toBe('Item one two')
|
|
169
169
|
})
|
|
170
170
|
|
|
171
|
+
it('Enter and the leave that follows it save once while the save is still in flight', async () => {
|
|
172
|
+
let answer: (saved: boolean) => void = () => {}
|
|
173
|
+
const onCommit = vi.fn(() => new Promise<boolean>((resolve) => (answer = resolve)))
|
|
174
|
+
draw({ onCommit, onEnter: () => field().blur() })
|
|
175
|
+
await enter()
|
|
176
|
+
await type(' two')
|
|
177
|
+
await userEvent.keyboard('{Enter}')
|
|
178
|
+
await act(async () => answer(true))
|
|
179
|
+
expect(onCommit).toHaveBeenCalledTimes(1)
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('a change from elsewhere made while you are in it, and you change nothing, is loaded when you leave', async () => {
|
|
183
|
+
const { rerender, onCommit } = draw()
|
|
184
|
+
await enter()
|
|
185
|
+
rerender({ value: 'Item three' })
|
|
186
|
+
expect(field().textContent).toBe('Item one')
|
|
187
|
+
await act(async () => field().blur())
|
|
188
|
+
expect(field().textContent).toBe('Item three')
|
|
189
|
+
expect(onCommit).not.toHaveBeenCalled()
|
|
190
|
+
})
|
|
191
|
+
|
|
171
192
|
it('a change from elsewhere is loaded while you are not in it', async () => {
|
|
172
193
|
const { rerender } = draw()
|
|
173
194
|
rerender({ value: 'Item three' })
|
package/src/InlineText.tsx
CHANGED
|
@@ -98,14 +98,22 @@ export function InlineText({ value, placeholder, label, onCommit, onText, onEnte
|
|
|
98
98
|
const [empty, setEmpty] = useState(!value)
|
|
99
99
|
// Read at key time: the editor's handlers are built once, and a prop they
|
|
100
100
|
// closed over would be the first render's.
|
|
101
|
-
const latest = useRef({ onEnter, onText, onCommit, clearable })
|
|
102
|
-
latest.current = { onEnter, onText, onCommit, clearable }
|
|
101
|
+
const latest = useRef({ onEnter, onText, onCommit, clearable, value })
|
|
102
|
+
latest.current = { onEnter, onText, onCommit, clearable, value }
|
|
103
|
+
// The text being saved right now: Enter moves on, and the leave that follows
|
|
104
|
+
// must not send the same save a second time while the first is in flight.
|
|
105
|
+
const pending = useRef<string | null>(null)
|
|
103
106
|
|
|
104
107
|
const save = useCallback(async (text: string) => {
|
|
105
108
|
const next = oneLine(text)
|
|
106
|
-
if (next === saved.current) return
|
|
109
|
+
if (next === saved.current || next === pending.current) return
|
|
107
110
|
if (!next && !latest.current.clearable) return
|
|
108
|
-
|
|
111
|
+
pending.current = next
|
|
112
|
+
try {
|
|
113
|
+
if (await latest.current.onCommit(next)) saved.current = next
|
|
114
|
+
} finally {
|
|
115
|
+
if (pending.current === next) pending.current = null
|
|
116
|
+
}
|
|
109
117
|
}, [])
|
|
110
118
|
|
|
111
119
|
const editor = useEditor({
|
|
@@ -156,6 +164,15 @@ export function InlineText({ value, placeholder, label, onCommit, onText, onEnte
|
|
|
156
164
|
setEmpty(false)
|
|
157
165
|
return
|
|
158
166
|
}
|
|
167
|
+
// Left unchanged while someone else changed it: their text comes in now,
|
|
168
|
+
// as it would have had you not been in it.
|
|
169
|
+
const { value: current } = latest.current
|
|
170
|
+
if (oneLine(e.getText()) === saved.current && current !== saved.current && pending.current === null) {
|
|
171
|
+
e.commands.setContent(doc(current), { emitUpdate: false })
|
|
172
|
+
saved.current = current
|
|
173
|
+
setEmpty(!current)
|
|
174
|
+
return
|
|
175
|
+
}
|
|
159
176
|
void save(e.getText())
|
|
160
177
|
},
|
|
161
178
|
}, [readOnly])
|