UNPKG

@pmndrs/uikit-horizon

Version:

Horizon kit for @pmndrs/uikit based on the Reality Labs Design System (RLDS)

117 lines (116 loc) 5.02 kB
import { Image, Container, abortableEffect, } from '@pmndrs/uikit'; import { theme } from '../theme.js'; import { computed } from '@preact/signals-core'; const _avatarSizes = { xl: { attributionActiveMargin: 4, attributionActiveWidth: 24, attributionSrcWidth: 44, borderWidth: 3, height: 120 }, lg: { attributionActiveMargin: 2, attributionActiveWidth: 16, attributionSrcWidth: 32, borderWidth: 3, height: 72 }, md: { attributionActiveMargin: 0, attributionActiveWidth: 12, attributionSrcWidth: 16, borderWidth: 2, height: 44 }, sm: { borderWidth: 2, height: 24 }, xs: { borderWidth: 2, height: 16 }, }; const avatarSizes = _avatarSizes; export class Avatar extends Container { focusRing; image; activeBadge; attributionImage; constructor(inputProperties, initialClasses, config) { const height = computed(() => avatarSizes[this.properties.value.size ?? 'md'].height); super(inputProperties, initialClasses, { ...config, defaultOverrides: { positionType: 'relative', width: height, height, flexShrink: 0, '*': { important: { borderColor: computed(() => this.properties.value.selected === true ? theme.component.avatar.focusRing.selected.value : undefined), }, active: { borderColor: theme.component.avatar.focusRing.pressed, }, hover: { borderColor: theme.component.avatar.focusRing.hovered, }, borderColor: theme.component.avatar.focusRing.default, }, ...config?.defaultOverrides, }, }); //focus ring const focusRingBorderWidth = computed(() => avatarSizes[this.properties.value.size ?? 'md'].borderWidth); super.add((this.focusRing = new Container(undefined, undefined, { defaultOverrides: { borderWidth: focusRingBorderWidth, positionType: 'absolute', borderRadius: 1000, inset: computed(() => -2 - focusRingBorderWidth.value), }, }))); //avatar image super.add((this.image = new Image(undefined, undefined, { defaultOverrides: { width: '100%', height: '100%', aspectRatio: 1, borderRadius: 1000, borderColor: 'initial', src: this.properties.signal.src, }, }))); //active attribution const attributionActiveWidth = computed(() => avatarSizes[this.properties.value.size ?? 'md'].attributionActiveWidth); const cattributionActiveMargin = computed(() => avatarSizes[this.properties.value.size ?? 'md'].attributionActiveMargin); super.add((this.activeBadge = new Container(undefined, undefined, { defaultOverrides: { display: computed(() => (this.properties.value.attributionActive ?? false) && this.properties.value.attributionSrc == null ? 'flex' : 'none'), zIndex: 1, width: attributionActiveWidth, height: attributionActiveWidth, flexShrink: 0, backgroundColor: theme.component.avatar.badge.active, positionType: 'absolute', borderColor: 'initial', borderRadius: 1000, positionBottom: cattributionActiveMargin, positionRight: cattributionActiveMargin, }, }))); //src attribution abortableEffect(() => { const src = this.properties.value.attributionSrc; if (src == null) { return; } const attributionSrcWidth = computed(() => avatarSizes[this.properties.value.size ?? 'md'].attributionSrcWidth); const attributionImage = new Image(undefined, undefined, { defaultOverrides: { src, positionType: 'absolute', positionBottom: cattributionActiveMargin, positionRight: cattributionActiveMargin, flexShrink: 0, width: attributionSrcWidth, height: attributionSrcWidth, aspectRatio: 1, }, }); super.add(attributionImage); this.attributionImage = attributionImage; return () => attributionImage.dispose(); }, this.abortSignal); } dispose() { this.attributionImage?.dispose(); this.activeBadge.dispose(); this.image.dispose(); this.focusRing.dispose(); super.dispose(); } add() { throw new Error(`the Avatar component can not have any children`); } }