@pmndrs/uikit-horizon
Version:
Horizon kit for @pmndrs/uikit based on the Reality Labs Design System (RLDS)
117 lines (116 loc) • 5.02 kB
JavaScript
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`);
}
}