import type { Morfo } from '../types'; import { v } from '../types'; export const yearGridMorfo = { name: 'YearGrid', kebab: 'year-grid', scope: ['soma', 'sema'], expression: "family-default", apg: 'https://www.w3.org/WAI/ARIA/apg/patterns/grid/', texts: { label: '#?components.year-grid.label|Year grid', prevPage: '#?common.year-grid.prev-page|Previous years', nextPage: '#?common.year-grid.next-page|Next years' }, events: [ { name: 'commit-set', semantic: { family: 'commit', verb: 'set', target: v.partRef('cell'), intent: 'affirm', sequence: 'post' } }, { // Paginate to the previous/next range of years. Per book cap. 27 §5, // `shift.navigate` covers "Page A → page B" — the user moves to a // different stretch of the time axis. `step` variant for a discrete step. name: 'shift-navigate-step', semantic: { family: 'shift', verb: 'navigate', target: v.partRef('provider'), sequence: 'post' } } ], parts: [ { name: 'Provider', kebab: 'provider', archetype: 'provider', kind: 'public', defaultElement: 'div', role: 'application', optional: false, data: [ { attr: 'data-readonly', severity: 'optional' }, { attr: 'data-disabled', severity: 'optional' } ], aria: [ { attr: 'aria-label', value: v.propRef('ariaLabel'), severity: 'recommended' }, // Provider emitted `boolToStr(disabled)` (always "true"/"false"), so // `propRef` + `ariaBoolean` lets renderProps() emit the same string. { attr: 'aria-disabled', value: v.propRef('disabled'), severity: 'optional', ariaBoolean: true } ], keyboard: [ { key: 'ArrowRight', action: 'next-year' }, { key: 'ArrowLeft', action: 'prev-year' }, { key: 'ArrowDown', action: 'next-row' }, { key: 'ArrowUp', action: 'prev-row' }, { key: 'PageUp', action: 'prev-page' }, { key: 'PageDown', action: 'next-page' }, { key: 'Home', action: 'first-year' }, { key: 'End', action: 'last-year' }, { key: 'Enter', action: 'select' }, { key: ' ', action: 'select' } ] }, { name: 'Header', kebab: 'header', archetype: 'header', kind: 'public', defaultElement: 'div', optional: true, data: [], aria: [] }, { name: 'Heading', kebab: 'heading', archetype: 'header', kind: 'public', defaultElement: 'div', optional: true, data: [], aria: [] }, { name: 'PrevButton', kebab: 'prev-button', archetype: 'trigger', kind: 'public', defaultElement: 'button', role: 'button', optional: true, data: [{ attr: 'data-disabled', severity: 'optional' }], aria: [ { attr: 'type', value: v.literal('button') }, { attr: 'aria-label', value: v.commonRef('year-grid.prev-page', 'Previous years'), severity: 'recommended' }, // Provider emitted `boolToStr(disabled)` (always "true"/"false"), so // `propRef` + `ariaBoolean` lets renderProps() emit the same string. { attr: 'aria-disabled', value: v.propRef('disabled'), severity: 'optional', ariaBoolean: true } ] }, { name: 'NextButton', kebab: 'next-button', archetype: 'trigger', kind: 'public', defaultElement: 'button', role: 'button', optional: true, data: [{ attr: 'data-disabled', severity: 'optional' }], aria: [ { attr: 'type', value: v.literal('button') }, { attr: 'aria-label', value: v.commonRef('year-grid.next-page', 'Next years'), severity: 'recommended' }, // Provider emitted `boolToStr(disabled)` (always "true"/"false"), so // `propRef` + `ariaBoolean` lets renderProps() emit the same string. { attr: 'aria-disabled', value: v.propRef('disabled'), severity: 'optional', ariaBoolean: true } ] }, { name: 'Grid', kebab: 'grid', kind: 'public', defaultElement: 'div', role: 'grid', optional: false, data: [], aria: [ { attr: 'aria-labelledby', value: v.partRef('heading'), condition: { when: 'part-present', part: 'heading' }, severity: 'recommended' }, // Provider emitted `boolToStr(...)` (always "true"/"false") for both; // `propRef` + `ariaBoolean` lets renderProps() emit the same string. { attr: 'aria-readonly', value: v.propRef('readonly'), severity: 'optional', ariaBoolean: true }, { attr: 'aria-disabled', value: v.propRef('disabled'), severity: 'optional', ariaBoolean: true } ] }, { name: 'Cell', kebab: 'cell', archetype: 'item', kind: 'public', defaultElement: 'button', role: 'gridcell', optional: false, data: [ { attr: 'data-value' }, { attr: 'data-selected', severity: 'optional' }, { attr: 'data-current', severity: 'optional' }, { attr: 'data-disabled', severity: 'optional' }, { attr: 'data-focused', severity: 'optional' } ], aria: [ // Provider emitted `boolToStr(...)` (always "true"/"false") for both; // `propRef` + `ariaBoolean` lets renderProps() emit the same string. { attr: 'aria-selected', value: v.propRef('selected'), severity: 'optional', ariaBoolean: true }, { attr: 'aria-disabled', value: v.propRef('disabled'), severity: 'optional', ariaBoolean: true } ] } ] } as const satisfies Morfo;