diff --git a/panel/src/helpers/field.test.js b/panel/src/helpers/field.test.ts similarity index 87% rename from panel/src/helpers/field.test.js rename to panel/src/helpers/field.test.ts index af823b9edc..3f098a5d2c 100644 --- a/panel/src/helpers/field.test.js +++ b/panel/src/helpers/field.test.ts @@ -2,6 +2,8 @@ import { describe, expect, it } from "vitest"; import { form } from "./field"; describe.concurrent("$helper.field.form()", () => { + // TODO: Remove once window.panel is globally typed + // @ts-expect-error - window.panel is not typed yet // mock the app with the component setup window.panel = { app: { diff --git a/panel/src/helpers/field.js b/panel/src/helpers/field.ts similarity index 53% rename from panel/src/helpers/field.js rename to panel/src/helpers/field.ts index b70b55c895..5344df205c 100644 --- a/panel/src/helpers/field.js +++ b/panel/src/helpers/field.ts @@ -1,20 +1,24 @@ -import { clone } from "./object.js"; +import { clone } from "./object"; + +type Field = Record; /** * Loads the default value for a field definition * @unstable * - * @param {Object} field - * @returns {mixed} + * @example + * defaultValue({ type: "text", default: "Hello" }) // => "Hello" + * defaultValue({ type: "text" }) // => null */ -export function defaultValue(field) { +export function defaultValue(field: Field): unknown { if (field.default !== undefined) { return clone(field.default); } - const component = - window.panel.app.$options.components[`k-${field.type}-field`]; - + // TODO: Remove once window.panel is globally typed + // @ts-expect-error - window.panel has no type yet + const options = window.panel.app.$options; + const component = options.components[`k-${field.type}-field`]; const valueProp = component?.options.props?.value; // if the field has no value prop, @@ -41,11 +45,12 @@ export function defaultValue(field) { * Creates form values for provided fields * @unstable * - * @param {Object} fields - * @returns {Object} + * @example + * form({ title: { type: "text", default: "Hello" }, age: { type: "number" } }) + * // => { title: "Hello" } */ -export function form(fields) { - const form = {}; +export function form(fields: Record): Record { + const form: Record = {}; for (const fieldName in fields) { const defaultVal = defaultValue(fields[fieldName]); @@ -63,11 +68,17 @@ export function form(fields) { * and the current form values. Also works for sections. * @unstable * - * @param {Object} field - The form field object - * @param {Object} values - The current form values object - * @returns {boolean} - Whether the field is visible or not + * @example + * isVisible({ type: "text", when: { status: "draft" } }, { status: "draft" }) // => true + * isVisible({ type: "text", when: { status: "draft" } }, { status: "published" }) // => false + * + * @param field - The form field object + * @param values - The current form values object */ -export function isVisible(field, values) { +export function isVisible( + field: Field, + values: Record +): boolean { if (field.type === "hidden" || field.hidden === true) { return false; } @@ -76,9 +87,11 @@ export function isVisible(field, values) { return true; } - for (const key in field.when) { + const when = field.when as Record; + + for (const key in when) { const value = values[key.toLowerCase()]; - const condition = field.when[key]; + const condition = when[key]; // if condition is checking for empty field if ( @@ -100,13 +113,12 @@ export function isVisible(field, values) { * Adds proper endpoint and section definitions * to subfields for a form field. * @unstable - * - * @param {object} field - * @param {object} fields - * @returns {object} */ -export function subfields(field, fields) { - let subfields = {}; +export function subfields( + field: Field, + fields: Record +): Record { + const subfields: Record = {}; for (const name in fields) { const subfield = fields[name]; @@ -114,10 +126,16 @@ export function subfields(field, fields) { subfield.section = field.name; if (field.endpoints) { + const endpoints = field.endpoints as { + field: string; + section: string; + model: string; + }; + subfield.endpoints = { - field: field.endpoints.field + "+" + name, - section: field.endpoints.section, - model: field.endpoints.model + field: endpoints.field + "+" + name, + section: endpoints.section, + model: endpoints.model }; } diff --git a/panel/src/helpers/index.js b/panel/src/helpers/index.js index ae123d3f17..ed9e1ea077 100644 --- a/panel/src/helpers/index.js +++ b/panel/src/helpers/index.js @@ -3,7 +3,7 @@ import clipboard from "./clipboard.js"; import color from "./color.js"; import debounce from "./debounce"; import embed from "./embed"; -import field from "./field.js"; +import field from "./field"; import file from "./file.js"; import focus from "./focus.js"; import isComponent from "./isComponent";