diff --git a/src/app/schema/renderHtml.tsx b/src/app/schema/renderHtml.tsx index 11a67a53..b4cbe6d7 100644 --- a/src/app/schema/renderHtml.tsx +++ b/src/app/schema/renderHtml.tsx @@ -1,4 +1,4 @@ -import type { BooleanHookParams, EnumOption, Hook, INode, NodeChildren, NumberHookParams, StringHookParams, ValidationOption } from '@mcschema/core' +import type { BooleanHookParams, EnumOption, Hook, INode, ListHookParams, NodeChildren, NumberHookParams, StringHookParams, ValidationOption } from '@mcschema/core' import { DataModel, ListNode, MapNode, ModelPath, ObjectNode, Path, relativePath, StringNode } from '@mcschema/core' import { Identifier, ItemStack } from 'deepslate/core' import type { ComponentChildren, JSX } from 'preact' @@ -94,10 +94,7 @@ const renderHtml: RenderHook = { return [prefix, <>{inject}{suffix}, body] }, - list({ children, config }, path, value, lang, version, states, ctx) { - const { expand, collapse, isToggled } = useToggles() - const [maxShown, setMaxShown] = useState(50) - + list({ children, config, node }, path, value, lang, version, states, ctx) { const context = path.getContext().join('.') if (fixedLists.includes(context)) { const prefix = <> @@ -117,87 +114,8 @@ const renderHtml: RenderHook = { const node = DataModel.wrapLists(children.default()) path.model.set(path, [{ node, id: hexId() }, ...value]) } - const onAddBottom = () => { - if (!Array.isArray(value)) value = [] - const node = DataModel.wrapLists(children.default()) - path.model.set(path, [...value, { node, id: hexId() }]) - } const suffix = - const body = <> - {(value && Array.isArray(value)) && value.map(({ node: cValue, id: cId }, index) => { - if (index === maxShown) { - return
- - - -
- } - if (index > maxShown) { - return null - } - const pathWithContext = (config?.context) ? new ModelPath(path.getModel(), new Path(path.getArray(), [config.context])) : path - const cPath = pathWithContext.push(index).contextPush('entry') - const canToggle = children.type(cPath) === 'object' - const toggle = isToggled(cId) - - let label: undefined | string | JSX.Element - if (itemPreviewFields.includes(cPath.getContext().join('.'))) { - if (isObject(cValue) && typeof cValue.type === 'string' && cValue.type.replace(/^minecraft:/, '') === 'item' && typeof cValue.name === 'string') { - let itemStack: ItemStack | undefined - try { - itemStack = new ItemStack(Identifier.parse(cValue.name), 1) - } catch (e) {} - if (itemStack !== undefined) { - label = - } - } - } - - if (canToggle && (toggle === false || (toggle === undefined && value.length > 20))) { - return
- - - - -
- } - - const onRemove = () => cPath.set(undefined) - const onMoveUp = () => { - const v = [...path.get()]; - [v[index - 1], v[index]] = [v[index], v[index - 1]] - path.model.set(path, v) - } - const onMoveDown = () => { - const v = [...path.get()]; - [v[index + 1], v[index]] = [v[index], v[index + 1]] - path.model.set(path, v) - } - const actions: MenuAction[] = [ - { - icon: 'duplicate', - label: 'duplicate', - onSelect: () => { - const v = [...path.get()] - v.splice(index, 0, { id: hexId(), node: deepClone(cValue) }) - path.model.set(path, v) - }, - }, - ] - return - {canToggle && } - - {value.length > 1 &&
- - -
} -
- })} - {(value && value.length > 0 && value.length <= maxShown) &&
- -
} - - return [null, suffix, body] + return [null, suffix, ] }, map({ children, keys, config }, path, value, lang, version, states, ctx) { @@ -386,6 +304,90 @@ function useToggles() { return { expand, collapse, isToggled } } +function ListBody({ path, value, lang, config, children, version, states, ctx }: NodeProps) { + const { expand, collapse, isToggled } = useToggles() + const [maxShown, setMaxShown] = useState(50) + const onAddBottom = () => { + if (!Array.isArray(value)) value = [] + const node = DataModel.wrapLists(children.default()) + path.model.set(path, [...value, { node, id: hexId() }]) + } + return <> + {(value && Array.isArray(value)) && value.map(({ node: cValue, id: cId }, index) => { + if (index === maxShown) { + return
+ + + +
+ } + if (index > maxShown) { + return null + } + const pathWithContext = (config?.context) ? new ModelPath(path.getModel(), new Path(path.getArray(), [config.context])) : path + const cPath = pathWithContext.push(index).contextPush('entry') + const canToggle = children.type(cPath) === 'object' + const toggle = isToggled(cId) + + let label: undefined | string | JSX.Element + if (itemPreviewFields.includes(cPath.getContext().join('.'))) { + if (isObject(cValue) && typeof cValue.type === 'string' && cValue.type.replace(/^minecraft:/, '') === 'item' && typeof cValue.name === 'string') { + let itemStack: ItemStack | undefined + try { + itemStack = new ItemStack(Identifier.parse(cValue.name), 1) + } catch (e) {} + if (itemStack !== undefined) { + label = + } + } + } + + if (canToggle && (toggle === false || (toggle === undefined && value.length > 20))) { + return
+ + + + +
+ } + + const onRemove = () => cPath.set(undefined) + const onMoveUp = () => { + const v = [...path.get()]; + [v[index - 1], v[index]] = [v[index], v[index - 1]] + path.model.set(path, v) + } + const onMoveDown = () => { + const v = [...path.get()]; + [v[index + 1], v[index]] = [v[index], v[index + 1]] + path.model.set(path, v) + } + const actions: MenuAction[] = [ + { + icon: 'duplicate', + label: 'duplicate', + onSelect: () => { + const v = [...path.get()] + v.splice(index, 0, { id: hexId(), node: deepClone(cValue) }) + path.model.set(path, v) + }, + }, + ] + return + {canToggle && } + + {value.length > 1 &&
+ + +
} +
+ })} + {(value && value.length > 0 && value.length <= maxShown) &&
+ +
} + +} + function BooleanSuffix({ path, node, value, lang }: NodeProps) { const set = (target: boolean) => { path.model.set(path, node.optional() && value === target ? undefined : target)