Comparing version 3.0.9 to 3.1.0
@@ -45,2 +45,3 @@ /// <reference types="node" /> | ||
disableFocus: () => void; | ||
focus: (id: string) => void; | ||
focusNext: () => void; | ||
@@ -47,0 +48,0 @@ focusPrevious: () => void; |
@@ -117,2 +117,11 @@ "use strict"; | ||
}; | ||
this.focus = (id) => { | ||
this.setState(previousState => { | ||
const hasFocusableId = previousState.focusables.some(focusable => (focusable === null || focusable === void 0 ? void 0 : focusable.id) === id); | ||
if (!hasFocusableId) { | ||
return previousState; | ||
} | ||
return { activeFocusId: id }; | ||
}); | ||
}; | ||
this.focusNext = () => { | ||
@@ -254,3 +263,4 @@ this.setState(previousState => { | ||
focusNext: this.focusNext, | ||
focusPrevious: this.focusPrevious | ||
focusPrevious: this.focusPrevious, | ||
focus: this.focus | ||
} }, this.state.error ? (react_1.default.createElement(ErrorOverview_1.default, { error: this.state.error })) : (this.props.children))))))); | ||
@@ -257,0 +267,0 @@ } |
@@ -14,4 +14,5 @@ /// <reference types="react" /> | ||
readonly focusPrevious: () => void; | ||
readonly focus: (id: string) => void; | ||
} | ||
declare const FocusContext: import("react").Context<Props>; | ||
export default FocusContext; |
@@ -13,3 +13,4 @@ "use strict"; | ||
focusNext: () => { }, | ||
focusPrevious: () => { } | ||
focusPrevious: () => { }, | ||
focus: () => { } | ||
}); | ||
@@ -16,0 +17,0 @@ FocusContext.displayName = 'InternalFocusContext'; |
@@ -23,2 +23,7 @@ import { Props } from '../components/FocusContext'; | ||
focusPrevious: Props['focusPrevious']; | ||
/** | ||
* Switch focus to the element with provided `id`. | ||
* If there's no element with that `id`, focus will be given to the first focusable component. | ||
*/ | ||
focus: Props['focus']; | ||
} | ||
@@ -25,0 +30,0 @@ /** |
@@ -18,3 +18,4 @@ "use strict"; | ||
focusNext: focusContext.focusNext, | ||
focusPrevious: focusContext.focusPrevious | ||
focusPrevious: focusContext.focusPrevious, | ||
focus: focusContext.focus | ||
}; | ||
@@ -21,0 +22,0 @@ }; |
@@ -10,2 +10,6 @@ interface Input { | ||
autoFocus?: boolean; | ||
/** | ||
* Assign an ID to this component, so it can be programmatically focused with `focus(id)`. | ||
*/ | ||
id?: string; | ||
} | ||
@@ -17,2 +21,6 @@ interface Output { | ||
isFocused: boolean; | ||
/** | ||
* Allows focusing a specific element with the provided `id`. | ||
*/ | ||
focus: (id: string) => void; | ||
} | ||
@@ -27,3 +35,3 @@ /** | ||
*/ | ||
declare const useFocus: ({ isActive, autoFocus }?: Input) => Output; | ||
declare const useFocus: ({ isActive, autoFocus, id: customId }?: Input) => Output; | ||
export default useFocus; |
@@ -17,6 +17,8 @@ "use strict"; | ||
*/ | ||
const useFocus = ({ isActive = true, autoFocus = false } = {}) => { | ||
const useFocus = ({ isActive = true, autoFocus = false, id: customId } = {}) => { | ||
const { isRawModeSupported, setRawMode } = use_stdin_1.default(); | ||
const { activeId, add, remove, activate, deactivate } = react_1.useContext(FocusContext_1.default); | ||
const id = react_1.useMemo(() => Math.random().toString().slice(2, 7), []); | ||
const { activeId, add, remove, activate, deactivate, focus } = react_1.useContext(FocusContext_1.default); | ||
const id = react_1.useMemo(() => { | ||
return customId !== null && customId !== void 0 ? customId : Math.random().toString().slice(2, 7); | ||
}, [customId]); | ||
react_1.useEffect(() => { | ||
@@ -46,3 +48,4 @@ add(id, { autoFocus }); | ||
return { | ||
isFocused: Boolean(id) && activeId === id | ||
isFocused: Boolean(id) && activeId === id, | ||
focus | ||
}; | ||
@@ -49,0 +52,0 @@ }; |
{ | ||
"name": "ink", | ||
"version": "3.0.9", | ||
"version": "3.1.0", | ||
"description": "React for CLI", | ||
@@ -20,4 +20,3 @@ "license": "MIT", | ||
"prepare": "npm run build", | ||
"test": "tsc --noEmit && xo && FORCE_COLOR=true ava", | ||
"cast": "svg-term --command='node media/demo.js' --out=media/demo.svg --from=100 --window --width=50 --height=8 --term=iterm2 --profile=Snazzy" | ||
"test": "tsc --noEmit && xo && FORCE_COLOR=true ava" | ||
}, | ||
@@ -99,3 +98,2 @@ "files": [ | ||
"strip-ansi": "^6.0.0", | ||
"svg-term-cli": "^2.1.1", | ||
"ts-node": "7.0.0", | ||
@@ -155,2 +153,3 @@ "typescript": "^3.8.3", | ||
"react/prop-types": "off", | ||
"react/default-props-match-prop-types": "off", | ||
"unicorn/prevent-abbreviations": "off", | ||
@@ -157,0 +156,0 @@ "react/require-default-props": "warn", |
@@ -356,3 +356,3 @@ <h1 align="center"> | ||
<Text>This is a box with margin</Text> | ||
</Box>; | ||
</Box> | ||
); | ||
@@ -1446,2 +1446,9 @@ | ||
##### id | ||
Type: `string`\ | ||
Required: `false` | ||
Set a component's focus ID, which can be used to programmatically focus the component. This is useful for large interfaces with many focusable elements, to avoid having to cycle through all of them. | ||
```jsx | ||
@@ -1459,3 +1466,3 @@ import {render, useFocus, Text} from 'ink'; | ||
See example in [examples/use-focus](examples/use-focus/use-focus.js). | ||
See example in [examples/use-focus](examples/use-focus/use-focus.js) and [examples/use-focus-with-id](examples/use-focus/use-focus-with-id.js). | ||
@@ -1549,2 +1556,28 @@ ### useFocusManager() | ||
#### focus(id) | ||
##### id | ||
Type: `string` | ||
Switch focus to the component with the given [`id`](#id). | ||
If there's no component with that ID, focus will be given to the next focusable component. | ||
```js | ||
import {useFocusManager, useInput} from 'ink'; | ||
const Example = () => { | ||
const {focus} = useFocusManager(); | ||
useInput(input => { | ||
if (input === 's') { | ||
// Focus the component with focus ID 'someId' | ||
focus('someId'); | ||
} | ||
}); | ||
return … | ||
}; | ||
``` | ||
## API | ||
@@ -1551,0 +1584,0 @@ |
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
231921
35
3104
1811