diff --git a/src/plugin/fieldViews/FieldView.ts b/src/plugin/fieldViews/FieldView.ts index 99cd53b9..bfde6327 100644 --- a/src/plugin/fieldViews/FieldView.ts +++ b/src/plugin/fieldViews/FieldView.ts @@ -28,7 +28,7 @@ export enum FieldContentType { /** * Represents a prosemirror-element view of a Prosemirror Node. */ -export abstract class FieldView { +export abstract class FieldView { public static fieldType: string; public static fieldContentType: FieldContentType; // The HTML element this fieldView renders content into. @@ -53,7 +53,7 @@ export abstract class FieldView { /** * Programmatically update this fieldView with the given value. */ - public abstract update(value: NodeValue): void; + public abstract update(value: FieldValue): void; /** * Destroy this fieldView, cleaning up any resources it has instantiated. diff --git a/src/plugin/fieldViews/RepeaterFieldView.ts b/src/plugin/fieldViews/RepeaterFieldView.ts index adb1df6e..87c779eb 100644 --- a/src/plugin/fieldViews/RepeaterFieldView.ts +++ b/src/plugin/fieldViews/RepeaterFieldView.ts @@ -35,7 +35,7 @@ export interface RepeaterFieldDescription< /** * A FieldView representing a node that contains user-defined child nodes. */ -export class RepeaterFieldView extends FieldView { +export class RepeaterFieldView extends FieldView { public static fieldType = repeaterFieldType; public static fieldContentType = FieldContentType.REPEATER; public static defaultValue = []; @@ -48,7 +48,8 @@ export class RepeaterFieldView extends FieldView { // The outer editor instance. Updated from within this class when nodes are added or removed. private outerView: EditorView, private fieldName: string, - public minChildren: number + public minChildren: number, + private getChildNodeFromData: (data: ChildValue) => Node ) { super(); } @@ -93,9 +94,10 @@ export class RepeaterFieldView extends FieldView { /** * Add a new child from this repeater at the given index. + * You can pre-populate this with * If list is empty, you will need to pass -1. */ - public addChildAfter(index: number) { + public addChildAfter(index: number, childValue?: ChildValue) { if (index < -1 || index > this.node.childCount - 1) { console.error( `Cannot add at index ${index}: index out of range. Minimum -1, Maximum ${ @@ -108,9 +110,14 @@ export class RepeaterFieldView extends FieldView { const repeaterChildNodeName = getRepeaterChildNameFromParent( this.node.type.name ); + const maybeNode = childValue + ? this.getChildNodeFromData(childValue) + : undefined; + const newNode = this.node.type.schema.nodes[ repeaterChildNodeName - ].createAndFill({ [RepeaterFieldMapIDKey]: getRepeaterID() }); + ].createAndFill({ [RepeaterFieldMapIDKey]: getRepeaterID() }, maybeNode); + if (!newNode) { console.warn( `[prosemirror-elements]: Could not create new repeater node of type ${this.fieldName}: createAndFill did not return a node` @@ -137,8 +144,8 @@ export class RepeaterFieldView extends FieldView { this.outerView.dispatch(tr); } - public addChildAtEnd() { - this.addChildAfter(this.node.childCount - 1); + public addChildAtEnd(childValue?: ChildValue) { + this.addChildAfter(this.node.childCount - 1, childValue); } /** diff --git a/src/plugin/helpers/fieldView.ts b/src/plugin/helpers/fieldView.ts index 1e2a9bf3..9b13820d 100644 --- a/src/plugin/helpers/fieldView.ts +++ b/src/plugin/helpers/fieldView.ts @@ -13,6 +13,7 @@ import { TextFieldView } from "../fieldViews/TextFieldView"; import type { FieldDescription, FieldDescriptions } from "../types/Element"; import type { ExternalElementData } from "./element"; import type { KeysWithValsOfType, Optional } from "./types"; +import { createNodesForFieldValues } from "../nodeSpec"; export const fieldTypeToViewMap = { [TextFieldView.fieldType]: TextFieldView, @@ -97,12 +98,12 @@ type Options = { export const getElementFieldViewFromType = ( fieldName: string, - field: FieldDescription, + fieldDescription: FieldDescription, { node, view, getPos, offset, innerDecos }: Options ) => { - switch (field.type) { + switch (fieldDescription.type) { case "text": - return new TextFieldView(node, view, getPos, offset, innerDecos, field); + return new TextFieldView(node, view, getPos, offset, innerDecos, fieldDescription); case "nestedElement": return new NestedElementFieldView( node, @@ -110,8 +111,8 @@ export const getElementFieldViewFromType = ( getPos, offset, innerDecos, - field, - field.allowedPlugins + fieldDescription, + fieldDescription.allowedPlugins ); case "richText": return new RichTextFieldView( @@ -120,7 +121,7 @@ export const getElementFieldViewFromType = ( getPos, offset, innerDecos, - field + fieldDescription ); case "checkbox": return new CheckboxFieldView( @@ -128,7 +129,7 @@ export const getElementFieldViewFromType = ( view, getPos, offset, - field.defaultValue ?? CheckboxFieldView.defaultValue + fieldDescription.defaultValue ?? CheckboxFieldView.defaultValue ); case "custom": return new CustomFieldView(node, view, getPos, offset); @@ -138,17 +139,25 @@ export const getElementFieldViewFromType = ( view, getPos, offset, - field.defaultValue ?? DropdownFieldView.defaultValue, - field.options + fieldDescription.defaultValue ?? DropdownFieldView.defaultValue, + fieldDescription.options ); case "repeater": + const a = (childValue: unknown) => createNodesForFieldValues( + node.type.schema, // got + fieldDescription, // need (parent has) + childValue, // got + nodeName, // ? not sure what 'node' means here + getNodeFromElementData, // will need (parent doesn't appear to have) + ); return new RepeaterFieldView( node, offset, getPos, view, fieldName, - field.minChildren + fieldDescription.minChildren, + a ); } };