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/image.ts

160 lines
4.2 KiB

feat(eidos): Card, Avatar ext, Image, SText, Badge, service components + dates engine fixes Sprint completo: - Card (eidos + sema): elevation/intent/interactive, eventos select+activate. - Avatar: ring, AvatarBadge, AvatarGroup separados; demo Avatar standalone. - Image: status surface (idle/loading/loaded/error) consumiendo soma ImageProvider. - SText + STextVirtualList: canvas-text engine portado de morfo-driven-soma como componentes separados para optimizar bundle (no se importa canvas si no se usa). - Badge: primitivo eidos puro. - Trans, FormatNumber, FormatDate, RelativeTime: 4 service components greppables alrededor de uix.langs y uix.format. Nav group "Utilities". Bugs fix arts/format/dates (engine-dates.ts): 1. Preset / per-axis conflict: Intl.DateTimeFormat rechaza dateStyle/timeStyle con cualquier per-axis (weekday/era/year/month/day/dayPeriod/hour/minute/ second/fractionalSecondDigits) o con timeZoneName. Engine drop-ea ambos presets por defecto cuando detecta conflict (regla estricta — un solo per-axis hace ilegales los dos presets). 2. Per-call locale override: formatDate/Time/DateTime aceptan tercer arg locale?: string. No muta engine state. Cache (getCachedDateFormat) keyea por (locale x options). resolveCallHourCycle: cuando hay locale override y pref auto, el ciclo horario se resuelve desde el locale OVERRIDE. 3. withHourCycle precedence: caller hourCycle/hour12 ahora gana sobre preferencia del engine. Antes spread mal ordenado sobrescribia 'h12' del caller con 'h23' del engine cuando locale resolvia a 24h. FormatDate component vuelve a rutear siempre por uix.format.dates (cache + hourCycle + locale reactivo), pasando locale como tercer arg. Demos service components autonomos del toolbar global: cada uno owns su demoLocale state con 7 chips (es-ES/en-US/en-GB/de-DE/fr-FR/ja-JP/ar-EG). FormatDate stage filtra dateStyle/timeStyle por mode + chip hourCycle anadido. Tests: 14/14 passing en engine-dates.test.ts (+6 nuevos: conflict handling, locale override, hourCycle precedence). Docs: arts/format/README.md (handoff 2026-05-25 con las 3 reglas), README.md por service component, project_service_components_sprint_2026-05-25.md, feedback_service_demos_own_locale.md (pattern reusable). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
import type { Morfo } from '../types';
import { v } from '../types';
/**
* Image — responsive image surface with status-driven fallback.
*
* Eidos-native primitive that consumes the existing `ImageProvider`
* (soma/layers) to track load lifecycle (idle / loading / loaded /
* error) and gate when the Fallback / Error slots are visible.
*
* Designed to be the foundation other components reach for instead of
* dropping raw `<img>` — Avatar.Image, Card images, Carousel slides,
* file thumbnails, etc. all benefit from the shared loading / error
* contract.
*
* Four parts:
* - Provider — outer `<span>` carrying status / fit / radius / placeholder
* - Img — the actual `<img>` element with src / srcset / sizes /
* loading / decoding / fetchpriority forwarded natively
* - Fallback — content rendered while the image is loading (or before
* a src is set). Optional delay before showing.
* - Error — content rendered when the image fails to load. Falls
* back automatically to Fallback when not supplied.
*
* Aspect ratio is intentionally NOT a prop here — consumers compose
* with the existing `<AspectRatio ratio>` primitive when they want to
* lock width / height. Same principle as Card / Banner: one axis, one
* primitive.
*
* 0-event surface: like Avatar, Image emits no semantic commit /
* emerge. The load lifecycle is a passive observation, not an
* evaluative act — consumers wanting a perceptual signal when an
* image lands wire it to the surrounding context (a gallery's
* `commit-select` on click, a hero's `emerge-mount` on the parent
* dialog, etc.).
*/
export const imageMorfo = {
name: 'Image',
kebab: 'image',
scope: ['eidos'],
texts: {
loading: '#?components.image.loading|Loading image',
error: '#?components.image.error|Image failed to load'
},
parts: [
{
name: 'Provider',
kebab: 'provider',
archetype: 'provider',
kind: 'public',
defaultElement: 'span',
optional: false,
states: ['idle', 'loading', 'loaded', 'error'],
data: [
{
attr: 'data-status',
values: ['idle', 'loading', 'loaded', 'error'],
value: v.stateRef('idle')
},
{
attr: 'data-fit',
values: ['cover', 'contain', 'fill', 'none', 'scale-down'],
value: v.propRef('fit'),
severity: 'optional'
},
{
attr: 'data-position',
values: ['center', 'top', 'bottom', 'start', 'end'],
value: v.propRef('position'),
severity: 'optional'
},
{
attr: 'data-radius',
values: ['none', 'sm', 'md', 'lg', 'full'],
value: v.propRef('radius'),
severity: 'optional'
},
{
attr: 'data-size',
values: ['xs', 'sm', 'md', 'lg', 'xl'],
value: v.propRef('size'),
severity: 'optional'
},
{
attr: 'data-placeholder',
values: ['skeleton', 'color', 'none'],
value: v.propRef('placeholder'),
severity: 'optional'
}
],
aria: []
},
{
name: 'Img',
kebab: 'img',
archetype: 'image',
kind: 'public',
defaultElement: 'img',
optional: false,
data: [
{
attr: 'data-status',
values: ['idle', 'loading', 'loaded', 'error'],
value: v.propRef('status')
}
],
aria: []
},
{
name: 'Fallback',
kebab: 'fallback',
archetype: 'fallback',
kind: 'public',
defaultElement: 'span',
optional: true,
data: [
{
attr: 'data-status',
values: ['idle', 'loading', 'loaded', 'error'],
value: v.propRef('status')
}
],
aria: [
{
attr: 'aria-label',
value: v.translationRef('#?components.image.loading|Loading image'),
severity: 'optional'
}
]
},
{
name: 'Error',
kebab: 'error',
archetype: 'fallback',
kind: 'public',
defaultElement: 'span',
optional: true,
data: [
{
attr: 'data-status',
values: ['idle', 'loading', 'loaded', 'error'],
value: v.propRef('status')
}
],
aria: [
{
attr: 'role',
value: v.literal('img'),
severity: 'recommended'
},
{
attr: 'aria-label',
value: v.translationRef('#?components.image.error|Image failed to load'),
severity: 'recommended'
}
]
}
]
} as const satisfies Morfo;

Powered by TurnKey Linux.