@lightningjs/solid-primitives
Advanced tools
Comparing version 0.4.8 to 0.5.0
@@ -17,3 +17,3 @@ /* | ||
*/ | ||
import { ElementNode } from "@lightningjs/solid"; | ||
import { View, ElementNode } from "@lightningjs/solid"; | ||
import { handleNavigation } from "./navigation.js"; | ||
@@ -28,4 +28,4 @@ export function Column(props) { | ||
}; | ||
return <node onUp={up} onDown={down} onFocus={props.onFocus || (elm => { | ||
if (!elm || elm.selected === null) | ||
return <View onUp={up} onDown={down} onFocus={props.onFocus || ((elm) => { | ||
if (!elm || elm.selected === undefined) | ||
return; | ||
@@ -40,4 +40,4 @@ let child = elm.children[elm.selected]; | ||
child.setFocus(); | ||
})} selected={props.selected || 0} style={props.style || defaultStyle} {...props}>{props.children}</node>; | ||
})} selected={props.selected || 0} style={props.style || defaultStyle} {...props}>{props.children}</View>; | ||
} | ||
//# sourceMappingURL=Column.jsx.map |
@@ -29,3 +29,3 @@ /* | ||
if (!wrap) { | ||
this.selected = null; | ||
this.selected = undefined; | ||
break; | ||
@@ -42,3 +42,3 @@ } | ||
if (!wrap) { | ||
this.selected = null; | ||
this.selected = undefined; | ||
break; | ||
@@ -50,3 +50,3 @@ } | ||
} | ||
if (this.selected === null) { | ||
if (this.selected === undefined) { | ||
this.selected = lastSelected; | ||
@@ -59,3 +59,3 @@ return false; | ||
this.onSelectedChanged.call(this, this, active, this.selected, lastSelected); | ||
if (this.plinko && lastSelected !== null) { | ||
if (this.plinko && lastSelected !== undefined) { | ||
// Set the next item to have the same selected index | ||
@@ -62,0 +62,0 @@ // so we move up / down directly |
@@ -18,3 +18,3 @@ /* | ||
import { handleNavigation } from "./navigation.js"; | ||
import { ElementNode } from '@lightningjs/solid'; | ||
import { View, ElementNode } from '@lightningjs/solid'; | ||
export function Row(props) { | ||
@@ -27,4 +27,4 @@ const left = handleNavigation('left'); | ||
}; | ||
return <node onLeft={left} onRight={right} selected={props.selected || 0} onFocus={props.onFocus || (elm => { | ||
if (!elm || elm.selected === null) | ||
return <View onLeft={left} onRight={right} selected={props.selected || 0} onFocus={props.onFocus || ((elm) => { | ||
if (!elm || elm.selected === undefined) | ||
return; | ||
@@ -39,4 +39,4 @@ let child = elm.children[elm.selected]; | ||
child.setFocus(); | ||
})} style={props.style || defaultStyle} {...props}>{props.children}</node>; | ||
})} style={props.style || defaultStyle} {...props}>{props.children}</View>; | ||
} | ||
//# sourceMappingURL=Row.jsx.map |
@@ -0,9 +1,10 @@ | ||
import { type Accessor } from 'solid-js'; | ||
import { ElementNode } from '@lightningjs/solid'; | ||
export interface DefaultKeyMap { | ||
Left: string; | ||
Right: string; | ||
Up: string; | ||
Down: string; | ||
Enter: string; | ||
Last: string; | ||
Left: string | string[]; | ||
Right: string | string[]; | ||
Up: string | string[]; | ||
Down: string | string[]; | ||
Enter: string | string[]; | ||
Last: string | string[]; | ||
} | ||
@@ -26,6 +27,6 @@ export interface KeyMap extends DefaultKeyMap { | ||
interface IntrinsicCommonProps extends KeyMapEventHandlers { | ||
onFocus?: (currentFocusedElm: ElementNode | null, prevFocusedElm: ElementNode | null) => void; | ||
onBlur?: (currentFocusedElm: ElementNode | null, prevFocusedElm: ElementNode | null) => void; | ||
onFocus?: (currentFocusedElm: ElementNode | undefined, prevFocusedElm: ElementNode | undefined) => void; | ||
onBlur?: (currentFocusedElm: ElementNode | undefined, prevFocusedElm: ElementNode | undefined) => void; | ||
onKeyPress?: (this: ElementNode, e: KeyboardEvent, mappedKeyEvent: string | undefined, currentFocusedElm: ElementNode) => KeyHandlerReturn; | ||
onSelectedChanged?: (container: ElementNode, activeElm: ElementNode, selectedIndex: number | null, lastSelectedIndex: number | null) => void; | ||
onSelectedChanged?: (container: ElementNode, activeElm: ElementNode, selectedIndex: number | undefined, lastSelectedIndex: number | undefined) => void; | ||
skipFocus?: boolean; | ||
@@ -45,4 +46,4 @@ wrap?: boolean; | ||
} | ||
declare const focusPath: import("solid-js").Accessor<ElementNode[]>; | ||
declare const focusPath: Accessor<ElementNode[]>; | ||
export { focusPath }; | ||
export declare const useFocusManager: (userKeyMap?: Partial<KeyMap>) => import("solid-js").Accessor<ElementNode[]>; | ||
export declare const useFocusManager: (userKeyMap?: Partial<KeyMap>) => Accessor<ElementNode[]>; |
@@ -17,23 +17,42 @@ /* | ||
*/ | ||
import { createEffect, on, createSignal, untrack } from 'solid-js'; | ||
import { createEffect, on, createSignal, untrack, } from 'solid-js'; | ||
import { useKeyDownEvent } from '@solid-primitives/keyboard'; | ||
import { activeElement, ElementNode } from '@lightningjs/solid'; | ||
import { isFunc } from './utils.js'; | ||
let keyMap = { | ||
Left: 'ArrowLeft', | ||
Right: 'ArrowRight', | ||
Up: 'ArrowUp', | ||
Down: 'ArrowDown', | ||
import { isFunc, isArray } from './utils.js'; | ||
const keyMapEntries = { | ||
ArrowLeft: 'Left', | ||
ArrowRight: 'Right', | ||
ArrowUp: 'Up', | ||
ArrowDown: 'Down', | ||
Enter: 'Enter', | ||
Last: 'l', | ||
l: 'Last', | ||
' ': 'Space', | ||
Backspace: 'Back', | ||
Escape: 'Escape', | ||
37: 'Left', | ||
39: 'Right', | ||
38: 'Up', | ||
40: 'Down', | ||
13: 'Enter', | ||
32: 'Space', | ||
8: 'Back', | ||
27: 'Escape', | ||
}; | ||
const [focusPath, setFocusPath] = createSignal([]); | ||
export { focusPath }; | ||
export const useFocusManager = (userKeyMap = {}) => { | ||
export const useFocusManager = (userKeyMap) => { | ||
const keypressEvent = useKeyDownEvent(); | ||
keyMap = { | ||
...keyMap, | ||
...userKeyMap, | ||
}; | ||
const keyMapEntries = Object.entries(keyMap); | ||
if (userKeyMap) { | ||
// Flatten the userKeyMap to a hash | ||
for (const [key, value] of Object.entries(userKeyMap)) { | ||
if (isArray(value)) { | ||
value.forEach((v) => { | ||
keyMapEntries[key] = v; | ||
}); | ||
} | ||
else { | ||
keyMapEntries[key] = value; | ||
} | ||
} | ||
} | ||
createEffect(on(activeElement, (currentFocusedElm, prevFocusedElm, prevFocusPath = []) => { | ||
@@ -47,7 +66,7 @@ const newFocusedElms = []; | ||
isFunc(current.onFocus) && | ||
current.onFocus.call(current, currentFocusedElm, prevFocusedElm ?? null); | ||
current.onFocus.call(current, currentFocusedElm, prevFocusedElm); | ||
newFocusedElms.push(current); | ||
} | ||
fp.push(current); | ||
current = current.parent ?? null; | ||
current = current.parent; | ||
} | ||
@@ -58,3 +77,3 @@ prevFocusPath.forEach((elm) => { | ||
isFunc(elm.onBlur) && | ||
elm.onBlur.call(elm, currentFocusedElm, prevFocusedElm ?? null); | ||
elm.onBlur.call(elm, currentFocusedElm, prevFocusedElm); | ||
} | ||
@@ -69,10 +88,6 @@ }); | ||
// Search keyMap for the value of the pressed key | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const foundKeyEntry = keyMapEntries.find(([key, value]) => { | ||
return value === e.key; | ||
}); | ||
const mappedKeyEvent = keyMapEntries[e.key]; | ||
untrack(() => { | ||
const fp = focusPath(); | ||
for (const elm of fp) { | ||
const mappedKeyEvent = foundKeyEntry ? foundKeyEntry[0] : undefined; | ||
if (mappedKeyEvent) { | ||
@@ -79,0 +94,0 @@ const onKeyHandler = elm[`on${mappedKeyEvent}`]; |
{ | ||
"name": "@lightningjs/solid-primitives", | ||
"version": "0.4.8", | ||
"version": "0.5.0", | ||
"description": "Lightning Primitives for Solid Lightning", | ||
@@ -41,15 +41,15 @@ "type": "module", | ||
"devDependencies": { | ||
"@lightningjs/renderer": "^0.4.1", | ||
"@lightningjs/solid": "^0.7.2", | ||
"@typescript-eslint/eslint-plugin": "^6.3.0", | ||
"@typescript-eslint/parser": "^6.3.0", | ||
"eslint": "^8.46.0", | ||
"eslint-config-prettier": "^9.0.0", | ||
"husky": "^8.0.3", | ||
"lint-staged": "^13.2.3", | ||
"prettier": "^3.0.1", | ||
"solid-js": "^1.8.1", | ||
"typescript": "^5.1.6", | ||
"vite": "^4.4.9", | ||
"vite-tsconfig-paths": "^4.2.0" | ||
"@lightningjs/renderer": "^0.7.0", | ||
"@lightningjs/solid": "^0.12.0", | ||
"@typescript-eslint/eslint-plugin": "^6.20.0", | ||
"@typescript-eslint/parser": "^6.20.0", | ||
"eslint": "^8.56.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"husky": "^9.0.7", | ||
"lint-staged": "^15.2.0", | ||
"prettier": "^3.2.4", | ||
"solid-js": "^1.8.12", | ||
"typescript": "^5.3.3", | ||
"vite": "^5.0.12", | ||
"vite-tsconfig-paths": "^4.3.1" | ||
}, | ||
@@ -64,4 +64,4 @@ "lint-staged": { | ||
"dependencies": { | ||
"@solid-primitives/keyboard": "^1.2.5", | ||
"@solid-primitives/scheduled": "^1.4.1" | ||
"@solid-primitives/keyboard": "^1.2.6", | ||
"@solid-primitives/scheduled": "^1.4.2" | ||
}, | ||
@@ -68,0 +68,0 @@ "peerDependencies": { |
@@ -71,4 +71,4 @@ /* | ||
function getElmName(elm: ElementNode) { | ||
return elm.id || elm.name; | ||
function getElmName(elm: ElementNode): string { | ||
return (elm.id as string) || elm.name; | ||
} | ||
@@ -75,0 +75,0 @@ |
@@ -35,3 +35,3 @@ /* | ||
if (!wrap) { | ||
this.selected = null; | ||
this.selected = undefined; | ||
break; | ||
@@ -47,3 +47,3 @@ } | ||
if (!wrap) { | ||
this.selected = null; | ||
this.selected = undefined; | ||
break; | ||
@@ -56,3 +56,3 @@ } | ||
if (this.selected === null) { | ||
if (this.selected === undefined) { | ||
this.selected = lastSelected; | ||
@@ -72,3 +72,3 @@ return false; | ||
if (this.plinko && lastSelected !== null) { | ||
if (this.plinko && lastSelected !== undefined) { | ||
// Set the next item to have the same selected index | ||
@@ -75,0 +75,0 @@ // so we move up / down directly |
@@ -18,14 +18,20 @@ /* | ||
import { createEffect, on, createSignal, untrack } from 'solid-js'; | ||
import { | ||
createEffect, | ||
on, | ||
createSignal, | ||
untrack, | ||
type Accessor, | ||
} from 'solid-js'; | ||
import { useKeyDownEvent } from '@solid-primitives/keyboard'; | ||
import { activeElement, ElementNode } from '@lightningjs/solid'; | ||
import { isFunc } from './utils.js'; | ||
import { isFunc, isArray } from './utils.js'; | ||
export interface DefaultKeyMap { | ||
Left: string; | ||
Right: string; | ||
Up: string; | ||
Down: string; | ||
Enter: string; | ||
Last: string; | ||
Left: string | string[]; | ||
Right: string | string[]; | ||
Up: string | string[]; | ||
Down: string | string[]; | ||
Enter: string | string[]; | ||
Last: string | string[]; | ||
} | ||
@@ -57,8 +63,8 @@ | ||
onFocus?: ( | ||
currentFocusedElm: ElementNode | null, | ||
prevFocusedElm: ElementNode | null, | ||
currentFocusedElm: ElementNode | undefined, | ||
prevFocusedElm: ElementNode | undefined, | ||
) => void; | ||
onBlur?: ( | ||
currentFocusedElm: ElementNode | null, | ||
prevFocusedElm: ElementNode | null, | ||
currentFocusedElm: ElementNode | undefined, | ||
prevFocusedElm: ElementNode | undefined, | ||
) => void; | ||
@@ -74,4 +80,4 @@ onKeyPress?: ( | ||
activeElm: ElementNode, | ||
selectedIndex: number | null, | ||
lastSelectedIndex: number | null, | ||
selectedIndex: number | undefined, | ||
lastSelectedIndex: number | undefined, | ||
) => void; | ||
@@ -98,30 +104,48 @@ skipFocus?: boolean; | ||
let keyMap: Partial<KeyMap> = { | ||
Left: 'ArrowLeft', | ||
Right: 'ArrowRight', | ||
Up: 'ArrowUp', | ||
Down: 'ArrowDown', | ||
const keyMapEntries: Record<string | number, string> = { | ||
ArrowLeft: 'Left', | ||
ArrowRight: 'Right', | ||
ArrowUp: 'Up', | ||
ArrowDown: 'Down', | ||
Enter: 'Enter', | ||
Last: 'l', | ||
} satisfies DefaultKeyMap; | ||
l: 'Last', | ||
' ': 'Space', | ||
Backspace: 'Back', | ||
Escape: 'Escape', | ||
37: 'Left', | ||
39: 'Right', | ||
38: 'Up', | ||
40: 'Down', | ||
13: 'Enter', | ||
32: 'Space', | ||
8: 'Back', | ||
27: 'Escape', | ||
}; | ||
const [focusPath, setFocusPath] = createSignal<ElementNode[]>([]); | ||
export { focusPath }; | ||
export const useFocusManager = (userKeyMap: Partial<KeyMap> = {}) => { | ||
export const useFocusManager = (userKeyMap?: Partial<KeyMap>) => { | ||
const keypressEvent = useKeyDownEvent(); | ||
keyMap = { | ||
...keyMap, | ||
...userKeyMap, | ||
}; | ||
const keyMapEntries = Object.entries(keyMap); | ||
if (userKeyMap) { | ||
// Flatten the userKeyMap to a hash | ||
for (const [key, value] of Object.entries(userKeyMap)) { | ||
if (isArray(value)) { | ||
value.forEach((v) => { | ||
keyMapEntries[key] = v; | ||
}); | ||
} else { | ||
keyMapEntries[key] = value; | ||
} | ||
} | ||
} | ||
createEffect( | ||
on( | ||
activeElement, | ||
activeElement as Accessor<ElementNode>, | ||
( | ||
currentFocusedElm: ElementNode | null, | ||
prevFocusedElm: ElementNode | null | undefined, | ||
currentFocusedElm: ElementNode, | ||
prevFocusedElm: ElementNode | undefined, | ||
prevFocusPath: ElementNode[] = [], | ||
) => { | ||
const newFocusedElms = []; | ||
let current: ElementNode | null = currentFocusedElm; | ||
let current = currentFocusedElm; | ||
@@ -133,7 +157,3 @@ const fp: ElementNode[] = []; | ||
isFunc(current.onFocus) && | ||
current.onFocus.call( | ||
current, | ||
currentFocusedElm, | ||
prevFocusedElm ?? null, | ||
); | ||
current.onFocus.call(current, currentFocusedElm, prevFocusedElm); | ||
@@ -143,3 +163,3 @@ newFocusedElms.push(current); | ||
fp.push(current); | ||
current = current.parent ?? null; | ||
current = current.parent!; | ||
} | ||
@@ -151,3 +171,3 @@ | ||
isFunc(elm.onBlur) && | ||
elm.onBlur.call(elm, currentFocusedElm, prevFocusedElm ?? null); | ||
elm.onBlur.call(elm, currentFocusedElm, prevFocusedElm); | ||
} | ||
@@ -168,10 +188,6 @@ }); | ||
// Search keyMap for the value of the pressed key | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const foundKeyEntry = keyMapEntries.find(([key, value]) => { | ||
return value === e.key; | ||
}); | ||
const mappedKeyEvent = keyMapEntries[e.key]; | ||
untrack(() => { | ||
const fp = focusPath(); | ||
for (const elm of fp) { | ||
const mappedKeyEvent = foundKeyEntry ? foundKeyEntry[0] : undefined; | ||
if (mappedKeyEvent) { | ||
@@ -178,0 +194,0 @@ const onKeyHandler = |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
430650
175
6614
1