Skip to content

Commit 95f4363

Browse files
committed
Improve input fields in mcdoc renderer
1 parent c3d0f13 commit 95f4363

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

src/app/components/generator/McdocRenderer.tsx

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { SimplifiedEnum, SimplifiedMcdocType, SimplifiedMcdocTypeNoUnion, S
99
import { getValues } from '@spyglassmc/mcdoc/lib/runtime/completer/index.js'
1010
import { Identifier, ItemStack } from 'deepslate'
1111
import { marked } from 'marked'
12-
import { useCallback, useMemo, useState } from 'preact/hooks'
12+
import { useCallback, useEffect, useMemo, useState } from 'preact/hooks'
1313
import config from '../../Config.js'
1414
import { useLocale } from '../../contexts/Locale.jsx'
1515
import { useFocus } from '../../hooks/useFocus.js'
@@ -137,7 +137,12 @@ const SPECIAL_UNSET = '__unset__'
137137
function StringHead({ type, optional, excludeStrings, node, ctx }: Props<StringType>) {
138138
const { locale } = useLocale()
139139

140-
const value = (JsonStringNode.is(node) ? node.value : undefined)?.replaceAll('\n', '\\n')
140+
const nodeValue = (JsonStringNode.is(node) ? node.value : undefined)?.replaceAll('\n', '\\n')
141+
const [value, setValue] = useState(nodeValue)
142+
143+
useEffect(() => {
144+
setValue(nodeValue)
145+
}, [nodeValue])
141146

142147
const idAttribute = type.attributes?.find(a => a.name === 'id')?.value
143148
const idRegistry = idAttribute?.kind === 'literal' && idAttribute.value.kind === 'string'
@@ -152,7 +157,7 @@ function StringHead({ type, optional, excludeStrings, node, ctx }: Props<StringT
152157

153158
const onChangeValue = useCallback((newValue: string) => {
154159
newValue = newValue.replaceAll('\\n', '\n')
155-
if (value === newValue) {
160+
if (nodeValue === newValue) {
156161
return
157162
}
158163
ctx.makeEdit((range) => {
@@ -167,7 +172,11 @@ function StringHead({ type, optional, excludeStrings, node, ctx }: Props<StringT
167172
type: 'json:string',
168173
}
169174
})
170-
}, [optional, node, ctx, isSelect])
175+
}, [optional, node, ctx, nodeValue, isSelect])
176+
177+
const onCommitValue = useCallback(() => {
178+
onChangeValue(value ?? '')
179+
}, [value, onChangeValue])
171180

172181
const completions = useMemo(() => {
173182
return getValues(type, { ...ctx, offset: node?.range.start ?? 0 })
@@ -201,7 +210,7 @@ function StringHead({ type, optional, excludeStrings, node, ctx }: Props<StringT
201210
{completions.length > 0 && <datalist id={datalistId}>
202211
{completions.map(c => <option>{c.value}</option>)}
203212
</datalist>}
204-
<input class={colorKind === 'hex_rgb' ? 'short-input' : idRegistry ? 'long-input' : ''} value={value ?? ''} onInput={(e) => onChangeValue((e.target as HTMLInputElement).value)} list={completions.length > 0 ? datalistId : undefined} />
213+
<input class={colorKind === 'hex_rgb' ? 'short-input' : idRegistry ? 'long-input' : ''} value={value ?? ''} onInput={(e) => setValue((e.target as HTMLInputElement).value)} onBlur={onCommitValue} onSubmit={onCommitValue} onKeyDown={(e) => {if (e.key === 'Enter') onCommitValue()}} list={completions.length > 0 ? datalistId : undefined} />
205214
{value && gen && <a href={`/${gen.url}/?preset=${value?.replace(/^minecraft:/, '')}`} class="tooltipped tip-se" aria-label={locale('follow_reference')}>
206215
{Octicon.link_external}
207216
</a>}
@@ -263,8 +272,12 @@ function EnumHead({ type, optional, excludeStrings, node, ctx }: Props<Simplifie
263272
function NumericHead({ type, node, ctx }: Props<NumericType>) {
264273
const { locale } = useLocale()
265274

266-
const value = node && JsonNumberNode.is(node) ? Number(node.value.value) : undefined
267-
const isFloat = type.kind === 'float' || type.kind === 'double'
275+
const nodeValue = node && JsonNumberNode.is(node) ? Number(node.value.value) : undefined
276+
const [value, setValue] = useState(nodeValue?.toString())
277+
278+
useEffect(() => {
279+
setValue(nodeValue?.toString())
280+
}, [nodeValue])
268281

269282
const onChangeValue = useCallback((value: string | bigint | number) => {
270283
const number = typeof value === 'string'
@@ -277,9 +290,9 @@ function NumericHead({ type, node, ctx }: Props<NumericType>) {
277290
if (number === undefined) {
278291
return undefined
279292
}
280-
const newValue: core.FloatNode | core.LongNode = isFloat
281-
? { type: 'float', range, value: Number(number) }
282-
: { type: 'long', range, value: BigInt(number) }
293+
const newValue: core.FloatNode | core.LongNode = typeof number === 'bigint' || Number.isInteger(number)
294+
? { type: 'long', range, value: BigInt(number) }
295+
: { type: 'float', range, value: Number(number) }
283296
const newNode: JsonNumberNode = {
284297
type: 'json:number',
285298
range,
@@ -289,7 +302,11 @@ function NumericHead({ type, node, ctx }: Props<NumericType>) {
289302
newValue.parent = newNode
290303
return newNode
291304
})
292-
}, [isFloat, node, ctx])
305+
}, [node, ctx])
306+
307+
const onCommitValue = useCallback(() => {
308+
onChangeValue(value ?? '')
309+
}, [value, onChangeValue])
293310

294311
const color = type.attributes?.find(a => a.name === 'color')?.value
295312
const colorKind = color?.kind === 'literal' && color.value.kind === 'string' ? color.value.value : undefined
@@ -309,9 +326,9 @@ function NumericHead({ type, node, ctx }: Props<NumericType>) {
309326
}, [type, onChangeValue])
310327

311328
return <>
312-
<input class="short-input" type="number" value={value} onInput={(e) => onChangeValue((e.target as HTMLInputElement).value)} />
329+
<input class="short-input" type="number" value={value} onInput={(e) => setValue((e.target as HTMLInputElement).value)} onBlur={onCommitValue} onSubmit={onCommitValue} onKeyDown={(e) => {if (e.key === 'Enter') onCommitValue()}} />
313330
{colorKind && <>
314-
<input class="short-input" type="color" value={'#' + (value?.toString(16).padStart(6, '0') ?? '000000')} onChange={(e) => onChangeColor((e.target as HTMLInputElement).value)} />
331+
<input class="short-input" type="color" value={'#' + (nodeValue?.toString(16).padStart(6, '0') ?? '000000')} onChange={(e) => onChangeColor((e.target as HTMLInputElement).value)} />
315332
<button class="tooltipped tip-se" aria-label={locale('generate_new_color')} onClick={onRandomColor}>{Octicon.sync}</button>
316333
</>}
317334
{random && <>

0 commit comments

Comments
 (0)