Properly type field

This commit is contained in:
Adria Navarro 2025-03-10 10:42:58 +01:00
parent 1bdcb0986d
commit 5808b33ef9
4 changed files with 52 additions and 17 deletions

View File

@ -1,37 +1,39 @@
<script lang="ts">
import { getContext, onDestroy } from "svelte"
import { writable } from "svelte/store"
import { Readable, writable } from "svelte/store"
import { Icon } from "@budibase/bbui"
import { memo } from "@budibase/frontend-core"
import Placeholder from "../Placeholder.svelte"
import InnerForm from "./InnerForm.svelte"
import type { FieldApi } from "."
import type { FieldApi, FieldState } from "."
import { FieldSchema, FieldType } from "@budibase/types"
import { FormField } from "@/index"
export let label: string | undefined = undefined
export let field: string | undefined = undefined
export let fieldState: any
export let fieldApi: FieldApi
export let fieldSchema: any
export let fieldState: FieldState | undefined
export let fieldApi: FieldApi | undefined
export let fieldSchema: FieldSchema | undefined
export let defaultValue: string | undefined = undefined
export let type: any
export let type: FieldType
export let disabled = false
export let readonly = false
export let validation: any
export let validation: () => string | undefined
export let span = 6
export let helpText: string | undefined = undefined
// Get contexts
const formContext: any = getContext("form")
const formContext = getContext("form")
const formStepContext: any = getContext("form-step")
const fieldGroupContext: any = getContext("field-group")
const { styleable, builderStore, Provider } = getContext("sdk")
const component: any = getContext("component")
const component = getContext("component")
// Register field with form
const formApi = formContext?.formApi
const labelPos = fieldGroupContext?.labelPosition || "above"
let formField: any
let formField: Readable<FormField> | undefined
let touched = false
let labelNode: any
@ -66,11 +68,17 @@
$: $component.editing && labelNode?.focus()
// Update form properties in parent component on every store change
$: unsubscribe = formField?.subscribe((value: any) => {
fieldState = value?.fieldState
fieldApi = value?.fieldApi
fieldSchema = value?.fieldSchema
})
$: unsubscribe = formField?.subscribe(
(value?: {
fieldState: FieldState
fieldApi: FieldApi
fieldSchema: FieldSchema
}) => {
fieldState = value?.fieldState
fieldApi = value?.fieldApi
fieldSchema = value?.fieldSchema
}
)
// Determine label class from position
$: labelClass = labelPos === "above" ? "" : `spectrum-FieldLabel--${labelPos}`

View File

@ -25,9 +25,10 @@ export interface FieldApi {
deregister(): void
}
export interface FieldState<T> {
export interface FieldState<T = any> {
value: T
fieldId: string
disabled: boolean
readonly: boolean
error?: string
}

View File

@ -1,7 +1,8 @@
import { Component, Context, SDK } from "."
import { Component, Context, FormContext, SDK } from "."
declare module "svelte" {
export function getContext(key: "sdk"): SDK
export function getContext(key: "component"): Component
export function getContext(key: "context"): Context
export function getContext(key: "form"): FormContext
}

View File

@ -27,6 +27,8 @@ import {
Snippet,
UIComponentError,
CustomComponent,
FieldType,
FieldSchema,
} from "@budibase/types"
// Provide svelte and svelte/internal as globals for custom components
@ -39,6 +41,7 @@ window.svelte = svelte
// Initialise spectrum icons
// eslint-disable-next-line local-rules/no-budibase-imports
import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js"
import { FieldApi, FieldState } from "./components/app"
loadSpectrumIcons()
// Extend global window scope
@ -95,12 +98,34 @@ export interface SDK {
export type Component = Readable<{
id: string
name: string
styles: any
editing: boolean
errorState: boolean
}>
export type Context = Readable<Record<string, any>>
export interface FormContext {
formApi?: {
registerField: (
field: string,
type: FieldType,
defaultValue: string | undefined,
disabled: boolean,
readonly: boolean,
validation: () => string | undefined,
formStep: number
) => Readable<FormField>
}
}
export interface FormField {
fieldState: FieldState
fieldApi: FieldApi
fieldSchema: FieldSchema
}
let app: ClientApp
const loadBudibase = async () => {