mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-14 03:42:30 +02:00
tabset keyboard control
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user