budibase/packages/standard-components/src/forms/Field.svelte

110 lines
2.9 KiB
Svelte

<script>
import Placeholder from "../Placeholder.svelte"
import FieldGroupFallback from "./FieldGroupFallback.svelte"
import { getContext, onDestroy } from "svelte"
export let label
export let field
export let fieldState
export let fieldApi
export let fieldSchema
export let defaultValue
export let type
export let disabled = false
export let validation
// Get contexts
const formContext = getContext("form")
const formStepContext = getContext("form-step")
const fieldGroupContext = getContext("field-group")
const { styleable } = getContext("sdk")
const component = getContext("component")
// Register field with form
const formApi = formContext?.formApi
const labelPosition = fieldGroupContext?.labelPosition || "above"
const formField = formApi?.registerField(
field,
defaultValue,
disabled,
validation,
formStepContext || 1
)
// Update form properties in parent component on every store change
const unsubscribe = formField?.subscribe(value => {
fieldState = value?.fieldState
fieldApi = value?.fieldApi
fieldSchema = value?.fieldSchema
})
onDestroy(() => unsubscribe && unsubscribe())
// Keep validation rules up to date
$: updateValidation(validation)
const updateValidation = validation => {
fieldApi?.updateValidation(validation)
}
// Extract label position from field group context
$: labelPositionClass =
labelPosition === "above" ? "" : `spectrum-FieldLabel--${labelPosition}`
</script>
<FieldGroupFallback>
<div class="spectrum-Form-item" use:styleable={$component.styles}>
<label
class:hidden={!label}
for={fieldState?.fieldId}
class={`spectrum-FieldLabel spectrum-FieldLabel--sizeM spectrum-Form-itemLabel ${labelPositionClass}`}
>
{label || ""}
</label>
<div class="spectrum-Form-itemField">
{#if !formContext}
<Placeholder text="Form components need to be wrapped in a form" />
{:else if !fieldState}
<Placeholder
text="Add the Field setting to start using your component"
/>
{:else if fieldSchema?.type && fieldSchema?.type !== type}
<Placeholder
text="This Field setting is the wrong data type for this component"
/>
{:else}
<slot />
{#if fieldState.error}
<div class="error">{fieldState.error}</div>
{/if}
{/if}
</div>
</div>
</FieldGroupFallback>
<style>
label {
white-space: nowrap;
}
label.hidden {
padding: 0;
}
.spectrum-Form-itemField {
position: relative;
width: 100%;
}
.error {
color: var(
--spectrum-semantic-negative-color-default,
var(--spectrum-global-color-red-500)
);
font-size: var(--spectrum-global-dimension-font-size-75);
margin-top: var(--spectrum-global-dimension-size-75);
}
.spectrum-FieldLabel--right,
.spectrum-FieldLabel--left {
padding-right: var(--spectrum-global-dimension-size-200);
}
</style>