From 6287d0f24e262e9af6128d25ae384819d406df89 Mon Sep 17 00:00:00 2001 From: Bela Bohlender Date: Tue, 10 Sep 2024 16:51:40 +0200 Subject: [PATCH] feat #34: added blur function and html element to input internals --- examples/uikit/src/App.tsx | 24 ++++++++++++++++++++---- packages/react/src/input.tsx | 11 +++++++++-- packages/uikit/src/components/input.ts | 11 ++++++++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/examples/uikit/src/App.tsx b/examples/uikit/src/App.tsx index e11f0d03..a3220487 100644 --- a/examples/uikit/src/App.tsx +++ b/examples/uikit/src/App.tsx @@ -1,4 +1,4 @@ -import { ComponentRef, StrictMode, Suspense, useEffect, useMemo, useRef, useState } from 'react' +import { StrictMode, Suspense, useEffect, useMemo, useRef, useState } from 'react' import { Canvas, useThree } from '@react-three/fiber' import { Box, OrbitControls, OrthographicCamera, RenderTexture } from '@react-three/drei' import { signal } from '@preact/signals-core' @@ -18,6 +18,7 @@ import { ImageProperties, Video, useMeasureText, + InputInternals, } from '@react-three/uikit' import { Texture } from 'three' import { Skeleton } from '../../../packages/kits/default/src/skeleton.js' @@ -30,10 +31,25 @@ export default function App() { const x = useMemo(() => signal('red'), []) const t = useMemo(() => signal('X X\nX X'), []) const ref = useRef>(null) - const inputRef = useRef>(null) + const [input, setInput] = useState(null) const videoRef = useRef() const [videoel, setVideoEl] = useState() + useEffect(() => { + const x = input?.element.peek() + if (x == null) { + return + } + const keydown = (e: Event) => { + if ('key' in e && e.key != 'Enter') { + return + } + x.blur() + } + x.addEventListener('keydown', keydown) + return () => x.removeEventListener('keydown', keydown) + }, [input]) + useEffect(() => setVideoEl(videoRef.current), []) return ( @@ -242,7 +258,7 @@ export default function App() { inputRef.current?.focus()} + onClick={() => input?.focus()} positionType="absolute" positionBottom="100%" positionRight="100%" @@ -251,7 +267,7 @@ export default function App() { backgroundColor="red" > console.log('focus change', focus)} backgroundColor="white" width="100%" diff --git a/packages/react/src/input.tsx b/packages/react/src/input.tsx index 67dc0bf1..78d93bf0 100644 --- a/packages/react/src/input.tsx +++ b/packages/react/src/input.tsx @@ -19,6 +19,8 @@ import { useFontFamilies } from './font.js' export type InputInternals = ComponentInternals & { current: ReadonlySignal focus: () => void + blur: () => void + element: ReadonlySignal } & PointerEventsProperties export type InputProperties = BaseInputProperties & @@ -63,8 +65,13 @@ export const Input: (props: InputProperties & RefAttributes) => internals, internals.interactionPanel, useMemo( - () => ({ focus: internals.focus, current: internals.valueSignal }), - [internals.focus, internals.valueSignal], + () => ({ + focus: internals.focus, + blur: internals.blur, + current: internals.valueSignal, + element: internals.element, + }), + [internals.focus, internals.blur, internals.valueSignal, internals.element], ), ) diff --git a/packages/uikit/src/components/input.ts b/packages/uikit/src/components/input.ts index 5adc7604..9ee21d9e 100644 --- a/packages/uikit/src/components/input.ts +++ b/packages/uikit/src/components/input.ts @@ -274,6 +274,14 @@ export function createInput( } selectionRange.value = [inputElement.selectionStart ?? 0, inputElement.selectionEnd ?? 0] } + const blur = () => { + const inputElement = element.peek() + if (inputElement == null) { + return + } + inputElement.blur() + selectionRange.value = undefined + } setupUpdateHasFocus(element, hasFocusSignal, initializers, (hasFocus: boolean) => { properties.peek()?.onFocusChange?.(hasFocus) style.peek()?.onFocusChange?.(hasFocus) @@ -284,7 +292,8 @@ export function createInput( isClipped, mergedProperties, valueSignal, - focus: () => focus(), + focus, + blur, root: parentContext.root, element, node: nodeSignal,