feat(field): Field.Input adopts commit-submit on Enter — the text-input family doctrine (A-3.1)

Adoption, not design (audit ficha field F-2, refined against password-field):
the family doctrine is WRITTEN in the password-field morfo — per-keystroke
typing is plain data flow; Enter is the terminal gesture. textarea already
had commit-submit; the base Field.Input did not — the text-input pair was
asymmetric, and the machine flagged the shell as interactive-with-0-events
(A-3.1), converging with the clean-room audit finding "field infra-declarado".

- morfo: scope gains sema; expression family-default (the base shell speaks
  with the family voice — the concrete fields carry the packs); apg textbox
  (the password/textarea cite); commit-submit event (commit.submit, neutral,
  post, target input) + Enter in the Input keyboard contract.
- soma FieldInputProvider: onkeydown — plain Enter (no modifiers), gated on
  disabled/readonly, triggers commit-submit through the runtime.

Verified live in the field demo: Enter stamps data-event="commit-submit" /
family=commit / intent=neutral / phase=active on the input and the demo trace
logs the event. Machine: field -> PASS (A-3.1 + A-1.4 cleared). Field suite
3/3, vocab exit 0, type baseline 57.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
menubar-v4-safe
dev 3 months ago
parent 82e9aba946
commit 33f346ed50

@ -4,12 +4,38 @@ import { v } from '../types';
export const fieldMorfo = {
name: 'Field',
kebab: 'field',
scope: ['soma', 'eidos'],
scope: ['soma', 'sema', 'eidos'],
// The base shell stays on the family voice: the concrete fields carry the
// packs; Field.Input's Enter submit speaks with the commit family's base
// signature (adoption of the written family doctrine — see the event note).
expression: 'family-default',
// Field.Input is the single-line text input — same pattern the password /
// textarea siblings cite.
apg: 'https://www.w3.org/WAI/ARIA/apg/patterns/textbox/',
texts: {
label: '#?components.field.label|Field',
'required-indicator': '#?components.field.required-indicator|*',
'optional-indicator': '#?components.field.optional-indicator|(optional)'
},
events: [
// User pressed Enter on the plain-text Field.Input. ADOPTION of the
// family doctrine written (with incident) in password-field's morfo:
// per-keystroke typing is NOT a commit — `commit` is for terminal
// actions, and Enter-to-submit IS the text-input pattern (aligned with
// password / textarea / editable / number-field / search / combobox).
// This closed the text-input pair's asymmetry (audit ficha field F-2:
// textarea had `commit-submit`, the base Input did not).
{
name: 'commit-submit',
semantic: {
family: 'commit',
verb: 'submit',
target: v.partRef('input'),
intent: 'neutral',
sequence: 'post'
}
}
],
parts: [
{
name: 'Provider',
@ -125,7 +151,8 @@ export const fieldMorfo = {
severity: 'optional',
condition: { when: 'prop-truthy', prop: 'required' }
}
]
],
keyboard: [{ key: 'Enter', action: 'submit' }]
},
{
name: 'HelperText',

@ -356,6 +356,17 @@ export class FieldInputProvider {
this.opts.onValueChange.current(value);
};
/**
* Enter → `commit-submit` (the morfo keyboard contract). Adoption of the
* text-input family doctrine (password-field precedent): typing is plain
* data flow; Enter is the terminal gesture.
*/
readonly onkeydown = (e: SomaEvent<KeyboardEvent, HTMLInputElement>) => {
if (this.provider.isDisabled || this.provider.isReadonly) return;
if (e.key !== 'Enter' || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) return;
void this.provider.runtime.trigger('commit-submit');
};
readonly props = $derived.by(() =>
this.runtimePart.assert({
// Morfo-declared attrs (type, data-state, aria-labelledby, aria-invalid,
@ -371,7 +382,8 @@ export class FieldInputProvider {
// Morfo declares aria-describedby from the helper-text part; soma joins
// the helper + error ids, so it overrides with the richer value.
'aria-describedby': this.describedBy,
oninput: this.oninput
oninput: this.oninput,
onkeydown: this.onkeydown
} as const)
);
}

Loading…
Cancel
Save

Powered by TurnKey Linux.