tabset keyboard control

This commit is contained in:
euzu
2023-12-01 22:40:36 +01:00
parent 5d979da71b
commit e08ffefefc
5 changed files with 60 additions and 5 deletions
@@ -1,6 +1,7 @@
import './map-editor.scss';
import {KeyboardEvent, useCallback, useEffect, useMemo, useState} from "react";
import {genUuid} from "../../utils/uuid";
interface KeyValue {
key: string;
@@ -17,7 +18,7 @@ interface MapEditorProps {
export default function MapEditor(props: MapEditorProps) {
const {name, values, onChange} = props;
const uuid = useMemo(() => Date.now() + '-' + Math.floor(Math.random() * 99999), []);
const uuid = useMemo(() => genUuid(), []);
const [data, setData] = useState<KeyValue[]>(mapToList(values) || []);
useEffect(() => {
@@ -34,5 +34,9 @@
background-color: var(--tab-active-background-color);
color: var(--tab-active-color);
}
&:focus-visible {
outline: none;
}
}
}
+35 -3
View File
@@ -1,6 +1,7 @@
import React, {useCallback} from "react";
import React, {useCallback, useMemo} from "react";
import './tab-set.scss';
import {genUuid} from "../../utils/uuid";
export interface TabSetTab {
label: string;
@@ -15,15 +16,46 @@ interface TabSetProps {
export default function TabSet(props: TabSetProps) {
const {tabs, active, onTabChange} = props;
const uuid = useMemo(() => genUuid(), []);
const handleTabClick = useCallback((evt: any) => {
const key = evt.target.dataset.key;
onTabChange(key);
}, [onTabChange]);
const handleTabPress = useCallback((evt: any) => {
let key = (evt as any).key;
if (key === 'Enter' || key === ' ') {
handleTabClick(evt)
}
const rightArrow = key === 'ArrowRight';
const leftArrow = key === 'ArrowLeft';
if (rightArrow || leftArrow) {
const key = evt.target.dataset.key;
let idx = tabs?.findIndex( t => t.key === key);
if (idx >= 0) {
if (leftArrow) {
idx -= 1;
} else if (rightArrow) {
idx += 1;
}
if (idx > tabs.length-1) {
idx = 0;
} else if (idx < 0) {
idx = tabs.length-1;
}
}
let elem = document.getElementById(uuid + '-tab-' + idx)
elem?.focus();
}
}, [uuid, tabs, handleTabClick]);
return <ul className={'tab-set'}>
{tabs?.map(tab =>
<li className={'tab-set__tab' + (tab.key === active ? ' tab-set__tab-active' : '')} key={'tab_' + tab.key} data-key={tab.key} onClick={handleTabClick}>{tab.label}</li>)}
{tabs?.map((tab, idx) =>
<li tabIndex={0} className={'tab-set__tab' + (tab.key === active ? ' tab-set__tab-active' : '')}
key={'tab_' + tab.key} data-key={tab.key} id={uuid + '-tab-' + idx}
onKeyUp={handleTabPress}
onClick={handleTabClick}>{tab.label}</li>)}
</ul>
}
@@ -1,6 +1,7 @@
import './tag-select.scss';
import {useCallback, useEffect, useMemo, useState} from "react";
import {noop} from "rxjs";
import {genUuid} from "../../utils/uuid";
interface TagSelectProps {
name: string;
@@ -13,7 +14,7 @@ interface TagSelectProps {
export default function TagSelect(props: TagSelectProps) {
const {name, multi, options, defaultValues, onSelect} = props;
const [selected, setSelected] = useState<Record<number, boolean>>({});
const uuid = useMemo(() => Date.now() + '-' + Math.floor(Math.random() * 99999), []);
const uuid = useMemo(() => genUuid(), []);
useEffect(() => {
if (defaultValues && options) {
+17
View File
@@ -0,0 +1,17 @@
// yes, i know this is a fake this is not a real uuid
export const genUuid = () => {
let d = new Date().getTime();//Timestamp
// Time in microseconds since page-load or 0 if unsupported
let d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now()*1000)) || 0;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
let r = Math.random() * 16;//random number between 0 and 16
if(d > 0){//Use timestamp until depleted
r = (d + r)%16 | 0;
d = Math.floor(d/16);
} else {//Use microseconds since page-load if supported
r = (d2 + r)%16 | 0;
d2 = Math.floor(d2/16);
}
return (c === 'x' ? r : ((r & 0x3) | 0x8)).toString(16);
});
}