feat(17-02): repeater field and dependent dropdown states
- RepeaterField: rows with drag handle, index, titleFrom title, error chip, move up/down (buttons, ArrowUp/ArrowDown on the handle, native drag and drop), expand/collapse, remove (asks only for a row holding a value), add with nested defaults, maxItems counter, empty state, collapse all; every change edits form state only - 422 row paths (content.3.answer) open the row, mark it and focus the nested control; the banner no longer repeats row messages - DropdownField dependsOn: waiting, loading, not used, empty, loaded with depth indent, failed with retry; cached per sibling value, last request wins, a stale value is cleared after a sibling change and announced - FormView provides form feedback (errors and notices by row path, the polite live region, its confirm dialog) and the options cache; FormGrid provides the sibling scope for repeater rows - repeater.* and form.dependent_* phrase keys (en, pl), smoke specs, docs
This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, provide } from 'vue'
|
||||
import type { AdminRecord, ControllerParams, FormField as FormFieldSchema, RecordMeta } from '../../api/types'
|
||||
import FormField from './FormField.vue'
|
||||
import { FIELD_SCOPE } from './formContext'
|
||||
import { RELATION_MANAGER } from './registry'
|
||||
|
||||
// Two-column form grid (design screen 4): span left -> column 1, right ->
|
||||
// column 2, full (Winter's default) -> the whole row, auto and row -> the next
|
||||
// free slot. Below 600px everything is one column. Gaps are 22px x 24px.
|
||||
defineProps<{
|
||||
// The grid is the scope its fields read siblings from (a dependent dropdown,
|
||||
// D-08); a repeater row's grid passes `scopePath`, the repeater's name, so a
|
||||
// nested field's routes address it as `<repeater>.<field>`.
|
||||
const props = defineProps<{
|
||||
fields: FormFieldSchema[]
|
||||
values: AdminRecord
|
||||
errors: Record<string, string[]>
|
||||
@@ -16,9 +21,17 @@ defineProps<{
|
||||
source?: ControllerParams | null
|
||||
recordId?: number | null
|
||||
idPrefix?: string
|
||||
/** The repeater whose row this grid renders. */
|
||||
scopePath?: string
|
||||
}>()
|
||||
const emit = defineEmits<{ update: [name: string, value: unknown] }>()
|
||||
|
||||
provide(FIELD_SCOPE, {
|
||||
fields: computed(() => props.fields),
|
||||
values: computed(() => props.values),
|
||||
path: (name: string) => (props.scopePath ? `${props.scopePath}.${name}` : name),
|
||||
})
|
||||
|
||||
function spanClass(field: FormFieldSchema): string {
|
||||
// The relation manager always takes the whole row (design screen 5).
|
||||
if (field.type === RELATION_MANAGER) {
|
||||
|
||||
Reference in New Issue
Block a user