import type { Morfo } from '../types'; import { v } from '../types'; /** * ImageAdjustments — a reusable set of image-filter sliders. * * Declarative DNA only: the parts (a group of adjustment rows + a reset). The * adjustment definitions, ranges and the value→CSS-`filter` math live in soma * (logic), and eidos composes a `` per row. The component emits a live * CSS `filter` string + the per-adjustment values, so ANY surface can apply it * (the ImagePicker preview, an avatar editor, a words image, the cropper…). * * Reuses the framework's `Slider` (one per `Item`); never reinvents a slider. */ export const imageAdjustmentsMorfo = { name: 'ImageAdjustments', kebab: 'image-adjustments', scope: ['soma', 'sema', 'eidos'], expression: 'pack', apg: 'https://www.w3.org/WAI/ARIA/apg/patterns/slider/', texts: { label: '#?components.image-adjustments.label|Image adjustments', reset: '#?components.image-adjustments.reset|Reset' }, events: [ { // Reset every adjustment back to its neutral default. name: 'commit-reset', semantic: { family: 'commit', verb: 'reset', target: v.partRef('provider'), intent: 'neutral', sequence: 'post' } } ], parts: [ { name: 'Provider', kebab: 'provider', archetype: 'group', kind: 'public', defaultElement: 'div', role: 'group', optional: false, data: [{ attr: 'data-disabled', value: v.propRef('disabled'), severity: 'optional' }], aria: [ { attr: 'aria-label', value: v.propRef('ariaLabel'), severity: 'recommended' } ] }, { // One adjustment row (repeatable). `data-adjustment` names which // adjustment it drives (brightness / contrast / …) so eidos can style a // row per-adjustment (e.g. a rainbow track for `hue`). It's a string // value, so it MUST declare `values` + `value` — a bare propRef without // `values` would emit empty-string presence instead of the key. name: 'Item', kebab: 'item', archetype: 'group', kind: 'public', defaultElement: 'div', optional: true, data: [ { attr: 'data-adjustment', values: [ 'brightness', 'contrast', 'saturation', 'temperature', 'hue', 'blur', 'grayscale', 'sepia' ], value: v.propRef('adjustment'), severity: 'optional' } ], aria: [] }, { name: 'ItemLabel', kebab: 'item-label', archetype: 'label', kind: 'public', defaultElement: 'span', optional: true, data: [], aria: [] }, { // Value read-out for an adjustment. A plain `` (not ``): // the composed Slider's thumb already exposes `aria-valuenow`, so a // live region here would double-announce on every step. name: 'ItemValue', kebab: 'item-value', archetype: 'description', kind: 'public', defaultElement: 'span', optional: true, data: [], aria: [] }, { name: 'Reset', kebab: 'reset', archetype: 'action', kind: 'public', defaultElement: 'button', role: 'button', optional: true, data: [], aria: [{ attr: 'type', value: v.literal('button') }] } ] } as const satisfies Morfo;