You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/morfo/components/form.ts

262 lines
6.7 KiB

import type { Morfo } from '../types';
import { v } from '../types';
export const formMorfo = {
name: 'Form',
kebab: 'form',
scope: ['soma', 'sema'],
texts: {
label: '#?components.form.label|Form',
'error-summary-title': '#?components.form.error-summary-title|{{count}} form errors need your attention',
'error-summary-single': '#?components.form.error-summary-single|1 form error needs your attention'
},
events: [
{
name: 'commit-submit',
semantic: {
family: 'commit',
verb: 'submit',
target: v.partRef('provider'),
intent: 'fulfill',
sequence: 'post'
}
},
{
// Persistence: book §6.2 — signal.risk = untilFix. A validation
// warning must stay perceptible until the user fixes the field;
// auto-clearing after 240 ms would hide the warning the moment
// the user looks away. Form provider clears it by calling
// `runtime.clearSignal(id)` when validation passes (or
// `runtime.clearTarget(formElement)` to clear all field warnings
// at once on a successful submit).
name: 'signal-warn-invalid',
semantic: {
family: 'signal',
verb: 'warn',
target: v.partRef('provider'),
intent: 'risk',
sequence: 'post',
persistence: 'untilFix'
},
// Book §9.2: signal.warn + risk ⇒ persistentTrace +
// reducedMotionFallback='text'. Focus move is also useful here
// because the provider can land focus on the first invalid
// field; the runtime focuses `target` (the form element), and
// `focusFirstInvalid()` in the provider drills further from
// there.
a11ySemantic: {
requiresPersistentTrace: true,
requiresFocusMove: true,
reducedMotionFallback: 'text'
}
},
{
name: 'commit-reset',
semantic: {
family: 'commit',
verb: 'reset',
target: v.partRef('provider'),
intent: 'neutral',
sequence: 'post'
}
}
],
parts: [
{
name: 'Provider',
kebab: 'provider',
archetype: 'provider',
kind: 'public',
defaultElement: 'form',
optional: false,
data: [
{ attr: 'data-pending', value: v.propRef('isPending'), severity: 'optional' },
{ attr: 'data-dirty', value: v.propRef('dirty'), severity: 'optional' },
{ attr: 'data-touched', value: v.propRef('touched'), severity: 'optional' },
{ attr: 'data-invalid', value: v.propRef('invalid'), severity: 'optional' },
{ attr: 'data-submitted', value: v.propRef('submitted'), severity: 'optional' }
],
aria: [
{
attr: 'aria-busy',
value: v.literal('true'),
severity: 'optional',
condition: { when: 'prop-truthy', prop: 'isPending' }
}
]
},
{
name: 'Submit',
kebab: 'submit',
archetype: 'action',
kind: 'public',
defaultElement: 'button',
role: 'button',
optional: true,
data: [{ attr: 'data-pending', severity: 'optional' }],
aria: [
{ attr: 'type', value: v.literal('submit') },
{
attr: 'aria-label',
value: v.commonRef('buttons.submit', 'Submit'),
severity: 'recommended'
},
{
// Provider stringified this as `boolToStr(isPending)` ("true"/
// "false" ALWAYS), so it models a boolean state, not presence.
// `propRef` + `ariaBoolean` lets renderProps() emit the same
// "true"/"false" the provider used to.
attr: 'aria-busy',
value: v.propRef('isPending'),
severity: 'optional',
ariaBoolean: true
}
]
},
{
name: 'Reset',
kebab: 'reset',
archetype: 'action',
kind: 'public',
defaultElement: 'button',
role: 'button',
optional: true,
data: [{ attr: 'data-dirty', severity: 'optional' }],
aria: [
{ attr: 'type', value: v.literal('button') },
{
attr: 'aria-label',
value: v.commonRef('buttons.reset', 'Reset'),
severity: 'recommended'
}
]
},
{
name: 'ErrorSummary',
kebab: 'error-summary',
archetype: 'description',
kind: 'public',
defaultElement: 'div',
role: 'alert',
optional: true,
data: [{ attr: 'data-hidden', severity: 'optional' }],
aria: [{ attr: 'aria-live', value: v.literal('polite') }]
},
{
name: 'AutoFieldsGroup',
kebab: 'auto-fields-group',
archetype: 'group',
kind: 'public',
defaultElement: 'div',
optional: true,
data: [{ attr: 'data-form-auto-fields-group', emit: 'value' }],
aria: []
},
{
name: 'AutoFieldsArray',
kebab: 'auto-fields-array',
archetype: 'group',
kind: 'public',
defaultElement: 'div',
optional: true,
data: [{ attr: 'data-form-auto-fields-array', emit: 'value' }],
aria: []
},
{
name: 'AutoFieldsArrayToolbar',
kebab: 'auto-fields-array-toolbar',
archetype: 'header',
kind: 'public',
defaultElement: 'div',
optional: true,
data: [],
aria: []
},
{
name: 'AutoFieldsArrayAdd',
kebab: 'auto-fields-array-add',
archetype: 'action',
kind: 'public',
defaultElement: 'button',
role: 'button',
optional: true,
data: [{ attr: 'data-form-auto-fields-array-add', emit: 'value' }],
aria: [{ attr: 'type', value: v.literal('button') }]
},
{
name: 'AutoFieldsItem',
kebab: 'auto-fields-item',
archetype: 'item',
kind: 'public',
defaultElement: 'div',
optional: true,
data: [{ attr: 'data-form-auto-fields-item', emit: 'value' }],
aria: []
},
{
name: 'AutoFieldsItemToolbar',
kebab: 'auto-fields-item-toolbar',
archetype: 'header',
kind: 'public',
defaultElement: 'div',
optional: true,
data: [],
aria: []
},
{
name: 'AutoFieldsArrayRemove',
kebab: 'auto-fields-array-remove',
archetype: 'action',
kind: 'public',
defaultElement: 'button',
role: 'button',
optional: true,
data: [{ attr: 'data-form-auto-fields-array-remove', emit: 'value' }],
aria: [{ attr: 'type', value: v.literal('button') }]
},
{
name: 'AutoFieldsDiscriminated',
kebab: 'auto-fields-discriminated',
archetype: 'group',
kind: 'public',
defaultElement: 'div',
optional: true,
data: [{ attr: 'data-form-auto-fields-discriminated', emit: 'value' }],
aria: []
},
{
name: 'AutoFieldsPlaceholder',
kebab: 'auto-fields-placeholder',
archetype: 'fallback',
kind: 'public',
defaultElement: 'div',
optional: true,
data: [{ attr: 'data-form-auto-fields-placeholder', emit: 'value' }],
aria: []
},
{
name: 'AutoFieldsField',
kebab: 'auto-fields-field',
archetype: 'group',
kind: 'public',
defaultElement: 'div',
optional: true,
data: [{ attr: 'data-form-auto-fields-field', emit: 'value' }],
aria: []
},
{
name: 'AutoFieldsWidget',
kebab: 'auto-fields-widget',
archetype: 'input',
kind: 'public',
defaultElement: 'input',
optional: true,
data: [
{ attr: 'data-form-auto-fields-widget', emit: 'value' },
{ attr: 'data-form-auto-fields-widget-key', emit: 'value' }
],
aria: []
}
]
} as const satisfies Morfo;

Powered by TurnKey Linux.