UNPKG

@pmndrs/uikit-horizon

Version:

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

137 lines (136 loc) 5.69 kB
import { abortableEffect, Container, Input as InputImpl, } from '@pmndrs/uikit'; import { computed } from '@preact/signals-core'; import { theme } from '../theme.js'; const _inputSizes = { lg: { height: 48, fontSize: 14, lineHeight: '20px', }, sm: { height: 32, fontSize: 12, lineHeight: '16px', }, }; const inputSizes = _inputSizes; export class Input extends Container { input; leftIconPlaceholder; leftIcon; rightIconPlaceholder; rightIcon; constructor(inputProperties, initialClasses, config) { const hovered = config?.hovered ?? computed(() => this.hoveredList.value.length > 0); super(inputProperties, initialClasses, { ...config, defaultOverrides: { //exists to make sure the handlers are applied hover: {}, cursor: 'text', width: '100%', gap: 12, flexDirection: 'row', alignItems: 'center', fontSize: computed(() => inputSizes[this.properties.value.size ?? 'lg'].fontSize), lineHeight: computed(() => inputSizes[this.properties.value.size ?? 'lg'].lineHeight), fontWeight: 500, color: computed(() => (this.properties.value.variant ?? 'text') === 'text' ? theme.component.textInput.label.default.value : theme.component.search.label.value), paddingX: 16, height: computed(() => inputSizes[this.properties.value.size ?? 'lg'].height), borderRadius: 8, backgroundColor: computed(() => { if (this.input.hasFocus.value) { return theme.component.textInput.background.typing.value; } if (hovered.value) { return theme.component.textInput.background.hovered.value; } return theme.component.textInput.background.default.value; }), ...config?.defaultOverrides, }, }); this.addEventListener('click', () => this.input.focus()); const iconSize = computed(() => (this.properties.value.variant ?? 'text') === 'search' && (this.properties.value.size ?? 'lg') === 'lg' ? 24 : 16); this.leftIconPlaceholder = new Container(); super.add(this.leftIconPlaceholder); this.input = new InputImpl(undefined, undefined, { defaultOverrides: { flexGrow: 1, flexShrink: 0, textAlign: this.properties.signal.textAlign, minWidth: 100, focus: { color: theme.component.textInput.label.typing, }, caretColor: theme.component.textInput.cursor, placeholderStyle: { color: theme.component.semantic.text.placeholder, }, placeholder: this.properties.signal.placeholder, defaultValue: this.properties.signal.defaultValue, value: this.properties.signal.value, disabled: this.properties.signal.disabled, tabIndex: this.properties.signal.tabIndex, autocomplete: this.properties.signal.autocomplete, type: this.properties.signal.type, onValueChange: this.properties.signal.onValueChange, onFocusChange: this.properties.signal.onFocusChange, }, }); super.add(this.input); this.rightIconPlaceholder = new Container(); super.add(this.rightIconPlaceholder); const iconColor = computed(() => (this.properties.value.variant ?? 'text') === 'search' ? theme.component.search.icon.value : this.input.hasFocus ? theme.component.textInput.label.typing.value : theme.component.textInput.label.default.value); abortableEffect(() => { const LeftIcon = this.properties.value.leftIcon; if (LeftIcon == null) { return; } const leftIcon = new LeftIcon(undefined, undefined, { defaultOverrides: { width: iconSize, height: iconSize, flexShrink: 0, color: iconColor }, }); this.leftIconPlaceholder.add(leftIcon); this.leftIcon = leftIcon; return () => { leftIcon.dispose(); this.leftIcon = undefined; }; }, this.abortSignal); abortableEffect(() => { const RightIcon = this.properties.value.rightIcon; if (RightIcon == null) { return; } const rightIcon = new RightIcon(undefined, undefined, { defaultOverrides: { width: iconSize, height: iconSize, flexShrink: 0, color: iconColor }, }); this.rightIconPlaceholder.add(rightIcon); this.rightIcon = rightIcon; return () => { rightIcon.dispose(); this.rightIcon = undefined; }; }, this.abortSignal); } dispose() { this.input.dispose(); this.leftIconPlaceholder.dispose(); this.rightIconPlaceholder.dispose(); this.leftIcon?.dispose(); this.rightIcon?.dispose(); super.dispose(); } add() { throw new Error(`the Input component can not have any children`); } } //alias that is currently are workarround for uikitml because export const HorizonInput = Input;