Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@instructure/ui-selectable

Package Overview
Dependencies
Maintainers
0
Versions
1498
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@instructure/ui-selectable - npm Package Compare versions

Comparing version 10.4.2-snapshot-11 to 10.4.2-snapshot-13

2

CHANGELOG.md

@@ -6,3 +6,3 @@ # Change Log

## [10.4.2-snapshot-11](https://github.com/instructure/instructure-ui/compare/v10.4.1...v10.4.2-snapshot-11) (2024-11-06)
## [10.4.2-snapshot-13](https://github.com/instructure/instructure-ui/compare/v10.4.1...v10.4.2-snapshot-13) (2024-11-07)

@@ -9,0 +9,0 @@ **Note:** Version bump only for package @instructure/ui-selectable

{
"name": "@instructure/ui-selectable",
"version": "10.4.2-snapshot-11",
"version": "10.4.2-snapshot-13",
"description": "A UI component library made by Instructure Inc.",

@@ -26,13 +26,13 @@ "author": "Instructure, Inc. Engineering and Product Design",

"devDependencies": {
"@instructure/ui-babel-preset": "10.4.2-snapshot-11",
"@instructure/ui-test-utils": "10.4.2-snapshot-11"
"@instructure/ui-babel-preset": "10.4.2-snapshot-13",
"@instructure/ui-test-utils": "10.4.2-snapshot-13"
},
"dependencies": {
"@babel/runtime": "^7.25.6",
"@instructure/console": "10.4.2-snapshot-11",
"@instructure/shared-types": "10.4.2-snapshot-11",
"@instructure/ui-dom-utils": "10.4.2-snapshot-11",
"@instructure/ui-react-utils": "10.4.2-snapshot-11",
"@instructure/ui-testable": "10.4.2-snapshot-11",
"@instructure/ui-utils": "10.4.2-snapshot-11",
"@instructure/console": "10.4.2-snapshot-13",
"@instructure/shared-types": "10.4.2-snapshot-13",
"@instructure/ui-dom-utils": "10.4.2-snapshot-13",
"@instructure/ui-react-utils": "10.4.2-snapshot-13",
"@instructure/ui-testable": "10.4.2-snapshot-13",
"@instructure/ui-utils": "10.4.2-snapshot-13",
"keycode": "^2",

@@ -39,0 +39,0 @@ "prop-types": "^15.8.1"

@@ -7,143 +7,374 @@ ---

```javascript
---
type: example
---
- ```javascript
class CustomSelect extends React.Component {
state = {
isShowingOptions: false,
highlightedOptionId: this.props.options[0].id,
selectedOptionId: this.props.options[0].id,
inputValue: this.props.options[0].label,
filteredOptions: this.props.options
}
class CustomSelect extends React.Component {
state = {
isShowingOptions: false,
highlightedOptionId: this.props.options[0].id,
selectedOptionId: this.props.options[0].id,
inputValue: this.props.options[0].label,
filteredOptions: this.props.options
}
filterOptions = (value) => {
return this.props.options.filter((option) =>
option.label.toLowerCase().startsWith(value.toLowerCase())
)
}
filterOptions = (value) => {
return this.props.options.filter(option => (
option.label.toLowerCase().startsWith(value.toLowerCase())
))
}
matchValue() {
const { filteredOptions, inputValue, selectedOptionId } = this.state
if (filteredOptions.length === 1) {
if (
filteredOptions[0].label.toLowerCase() === inputValue.toLowerCase()
) {
return {
inputValue: filteredOptions[0].label,
selectedOptionId: filteredOptions[0].id
}
}
}
const index = this.getOptionIndex(
null,
selectedOptionId,
this.props.options
)
return { inputValue: this.props.options[index].label }
}
matchValue () {
const { filteredOptions, inputValue, selectedOptionId } = this.state
if (filteredOptions.length === 1) {
if (filteredOptions[0].label.toLowerCase() === inputValue.toLowerCase()) {
return {
inputValue: filteredOptions[0].label,
selectedOptionId: filteredOptions[0].id
getInputStyles() {
return {
display: 'block',
width: '250px',
padding: '5px'
}
}
getListStyles() {
const { isShowingOptions } = this.state
return {
background: 'white',
listStyle: 'none',
padding: 0,
margin: 0,
border: isShowingOptions && 'solid 1px lightgray'
}
}
getOptionStyles(option) {
const { selectedOptionId, highlightedOptionId } = this.state
const selected = selectedOptionId === option.id
const highlighted = highlightedOptionId === option.id
let background = 'transparent'
if (selected) {
background = 'lightgray'
} else if (highlighted) {
background = '#eeeeee'
}
return {
background,
padding: '0 10px'
}
}
getOptionIndex(direction, id, from) {
const { filteredOptions, highlightedOptionId } = this.state
const options = from ? from : filteredOptions
let index
for (let i = 0; i <= options.length - 1; i++) {
if (typeof id === 'undefined') {
if (highlightedOptionId === options[i].id) {
index = i + direction
if (index < 0) {
index = 0
} else if (index >= options.length - 1) {
index = options.length - 1
}
break
}
} else {
if (id === options[i].id) {
index = i
break
}
}
}
return index
}
const index = this.getOptionIndex(null, selectedOptionId, this.props.options)
return { inputValue: this.props.options[index].label }
}
getInputStyles () {
return {
display: 'block',
width: '250px',
padding: '5px'
getHandlers() {
return this.props.isDisabled
? {}
: {
onRequestShowOptions: (e) =>
this.setState((state) => ({
isShowingOptions: true,
highlightedOptionId: state.filteredOptions[0].id
})),
onRequestHideOptions: (e) => {
const index = this.getOptionIndex(
null,
this.state.selectedOptionId,
this.props.options
)
this.setState((state) => ({
isShowingOptions: false,
inputValue: this.props.options[index].label,
filteredOptions: this.props.options,
highlightedOptionId: null
}))
},
onRequestHighlightOption: (e, { id, direction }) => {
let index = this.getOptionIndex(direction, id)
this.setState((state) => ({
highlightedOptionId: state.filteredOptions[index]
? state.filteredOptions[index].id
: null,
inputValue:
direction && state.filteredOptions[index]
? state.filteredOptions[index].label
: state.inputValue
}))
},
onRequestSelectOption: (e, { id }) => {
const index = this.getOptionIndex(null, id)
this.setState((state) => ({
selectedOptionId: id,
inputValue: state.filteredOptions[index].label,
filteredOptions: this.props.options,
isShowingOptions: false,
highlightedOptionId: null
}))
}
}
}
}
getListStyles () {
const { isShowingOptions } = this.state
return {
background: 'white',
listStyle: 'none',
padding: 0,
margin: 0,
border: isShowingOptions && 'solid 1px lightgray'
render() {
const {
isShowingOptions,
inputValue,
highlightedOptionId,
selectedOptionId,
filteredOptions
} = this.state
return (
<Selectable
isShowingOptions={isShowingOptions}
highlightedOptionId={highlightedOptionId}
selectedOptionId={selectedOptionId ? selectedOptionId : null}
{...this.getHandlers()}
>
{({
getRootProps,
getLabelProps,
getInputProps,
getTriggerProps,
getListProps,
getOptionProps
}) => (
<span
style={{ display: 'inline-block' }}
{...getRootProps({ ref: (el) => (this.rootRef = el) })}
>
<label {...getLabelProps()}>Selectable Example</label>
<input
style={this.getInputStyles()}
{...getInputProps()}
{...getTriggerProps({
type: 'text',
value: inputValue,
onChange: (e) => {
const newOptions = this.filterOptions(e.target.value)
this.setState({
inputValue: e.target.value,
filteredOptions: newOptions,
isShowingOptions: true,
highlightedOptionId: newOptions[0]
? newOptions[0].id
: null
})
},
onBlur: (e) =>
this.setState({
filteredOptions: this.props.options,
highlightedOptionId: null,
isShowingOptions: false,
...this.matchValue()
})
})}
/>
<ul style={this.getListStyles()} {...getListProps()}>
{isShowingOptions &&
filteredOptions.map((option) => (
<li
key={option.id}
style={this.getOptionStyles(option)}
{...getOptionProps({ id: option.id })}
>
{option.label}
</li>
))}
</ul>
</span>
)}
</Selectable>
)
}
}
getOptionStyles (option) {
const { selectedOptionId, highlightedOptionId } = this.state
const selected = selectedOptionId === option.id
const highlighted = highlightedOptionId === option.id
let background = 'transparent'
if (selected) {
background = 'lightgray'
} else if (highlighted) {
background = '#eeeeee'
render(
<View>
<CustomSelect
options={[
{ id: 'opt0', value: '0', label: 'Alabama' },
{ id: 'opt1', value: '1', label: 'Alaska' },
{ id: 'opt2', value: '2', label: 'American Samoa' },
{ id: 'opt3', value: '3', label: 'Arizona' },
{ id: 'opt4', value: '4', label: 'Arkansas' },
{ id: 'opt5', value: '5', label: 'California' },
{ id: 'opt6', value: '6', label: 'Colorado' },
{ id: 'opt7', value: '7', label: 'Connecticut' },
{ id: 'opt8', value: '8', label: 'Delaware' },
{ id: 'opt9', value: '9', label: 'District Of Columbia' },
{ id: 'opt10', value: '10', label: 'Federated States Of Micronesia' },
{ id: 'opt11', value: '11', label: 'Florida' },
{ id: 'opt12', value: '12', label: 'Georgia' },
{ id: 'opt13', value: '13', label: 'Guam' },
{ id: 'opt14', value: '14', label: 'Hawaii' },
{ id: 'opt15', value: '15', label: 'Idaho' },
{ id: 'opt16', value: '16', label: 'Illinois' }
]}
/>
</View>
)
```
- ```js
const CustomSelect = ({ options, isDisabled }) => {
const [isShowingOptions, setIsShowingOptions] = useState(false)
const [highlightedOptionId, setHighlightedOptionId] = useState(
options[0].id
)
const [selectedOptionId, setSelectedOptionId] = useState(options[0].id)
const [inputValue, setInputValue] = useState(options[0].label)
const [filteredOptions, setFilteredOptions] = useState(options)
const rootRef = useRef(null)
const filterOptions = (value) => {
return options.filter((option) =>
option.label.toLowerCase().startsWith(value.toLowerCase())
)
}
return {
background,
padding: '0 10px'
const matchValue = () => {
if (filteredOptions.length === 1) {
if (
filteredOptions[0].label.toLowerCase() === inputValue.toLowerCase()
) {
setInputValue(filteredOptions[0].label)
setsSelectedOptionId(filteredOptions[0].id)
return
}
}
const index = getOptionIndex(null, selectedOptionId, options)
setInputValue(options[index].label)
}
}
getOptionIndex (direction, id, from) {
const { filteredOptions, highlightedOptionId } = this.state
const options = from ? from : filteredOptions
let index
const getInputStyles = () => {
return {
display: 'block',
width: '250px',
padding: '5px'
}
}
for (let i = 0; i <= options.length - 1; i++) {
if (typeof id === 'undefined') {
if (highlightedOptionId === options[i].id) {
index = i + direction
if (index < 0) {
index = 0
} else if (index >= options.length - 1) {
index = options.length - 1
const getListStyles = () => {
return {
background: 'white',
listStyle: 'none',
padding: 0,
margin: 0,
border: isShowingOptions && 'solid 1px lightgray'
}
}
const getOptionStyles = (option) => {
const selected = selectedOptionId === option.id
const highlighted = highlightedOptionId === option.id
let background = 'transparent'
if (selected) {
background = 'lightgray'
} else if (highlighted) {
background = '#eeeeee'
}
return {
background,
padding: '0 10px'
}
}
const getOptionIndex = (direction, id, from) => {
const options = from ? from : filteredOptions
let index
for (let i = 0; i <= options.length - 1; i++) {
if (typeof id === 'undefined') {
if (highlightedOptionId === options[i].id) {
index = i + direction
if (index < 0) {
index = 0
} else if (index >= options.length - 1) {
index = options.length - 1
}
break
}
break
} else {
if (id === options[i].id) {
index = i
break
}
}
} else {
if (id === options[i].id) {
index = i
break
}
}
return index
}
return index
}
getHandlers () {
return this.props.isDisabled ? {} : {
onRequestShowOptions: (e) => this.setState(state => ({
isShowingOptions: true,
highlightedOptionId: state.filteredOptions[0].id
})),
onRequestHideOptions: (e) => {
const index = this.getOptionIndex(null, this.state.selectedOptionId, this.props.options)
this.setState(state => ({
isShowingOptions: false,
inputValue: this.props.options[index].label,
filteredOptions: this.props.options,
highlightedOptionId: null,
}))
},
onRequestHighlightOption: (e, { id, direction }) => {
let index = this.getOptionIndex(direction, id)
this.setState(state => ({
highlightedOptionId: state.filteredOptions[index] ? state.filteredOptions[index].id : null,
inputValue: direction && state.filteredOptions[index]
? state.filteredOptions[index].label
: state.inputValue
}))
},
onRequestSelectOption: (e, { id }) => {
const index = this.getOptionIndex(null, id)
this.setState(state => ({
selectedOptionId: id,
inputValue: state.filteredOptions[index].label,
filteredOptions: this.props.options,
isShowingOptions: false,
highlightedOptionId: null,
}))
}
const getHandlers = () => {
return isDisabled
? {}
: {
onRequestShowOptions: (e) => {
setIsShowingOptions(true)
setHighlightedOptionId(filteredOptions[0].id)
},
onRequestHideOptions: (e) => {
const index = getOptionIndex(null, selectedOptionId, options)
setIsShowingOptions(false)
setInputValue(options[index].label)
setFilteredOptions(options)
setHighlightedOptionId(null)
},
onRequestHighlightOption: (e, { id, direction }) => {
let index = getOptionIndex(direction, id)
setHighlightedOptionId(
filteredOptions[index] ? filteredOptions[index].id : null
)
setInputValue(
direction && filteredOptions[index]
? filteredOptions[index].label
: inputValue
)
},
onRequestSelectOption: (e, { id }) => {
const index = getOptionIndex(null, id)
setSelectedOptionId(id)
setInputValue(filteredOptions[index].label)
setFilteredOptions(options)
setIsShowingOptions(false)
setHighlightedOptionId(null)
}
}
}
}
render () {
const {
isShowingOptions,
inputValue,
highlightedOptionId,
selectedOptionId,
filteredOptions
} = this.state
return (

@@ -154,3 +385,3 @@ <Selectable

selectedOptionId={selectedOptionId ? selectedOptionId : null}
{...this.getHandlers()}
{...getHandlers()}
>

@@ -166,8 +397,8 @@ {({

<span
style={{display: 'inline-block'}}
{...getRootProps({ref: (el) => this.rootRef = el})}
style={{ display: 'inline-block' }}
{...getRootProps({ ref: rootRef })}
>
<label {...getLabelProps()}>Selectable Example</label>
<input
style={this.getInputStyles()}
style={getInputStyles()}
{...getInputProps()}

@@ -178,31 +409,29 @@ {...getTriggerProps({

onChange: (e) => {
const newOptions = this.filterOptions(e.target.value)
this.setState({
inputValue: e.target.value,
filteredOptions: newOptions,
isShowingOptions: true,
highlightedOptionId: newOptions[0] ? newOptions[0].id : null
})
const newOptions = filterOptions(e.target.value)
setInputValue(e.target.valu)
setFilteredOptions(newOptions)
setIsShowingOptions(true)
setHighlightedOptionId(
newOptions[0] ? newOptions[0].id : null
)
},
onBlur: (e) => this.setState({
filteredOptions: this.props.options,
highlightedOptionId: null,
isShowingOptions: false,
...this.matchValue()
})
})
} />
<ul
style={this.getListStyles()}
{...getListProps()}
>
{isShowingOptions && filteredOptions.map((option) => (
<li
key={option.id}
style={this.getOptionStyles(option)}
{...getOptionProps({ id: option.id })}
>
{option.label}
</li>
))}
onBlur: (e) => {
setFilteredOptions(options)
setHighlightedOptionId(null)
setIsShowingOptions(false)
matchValue()
}
})}
/>
<ul style={getListStyles()} {...getListProps()}>
{isShowingOptions &&
filteredOptions.map((option) => (
<li
key={option.id}
style={getOptionStyles(option)}
{...getOptionProps({ id: option.id })}
>
{option.label}
</li>
))}
</ul>

@@ -214,30 +443,29 @@ </span>

}
}
render(
<View>
<CustomSelect
options={[
{ id: 'opt0', value: '0', label: 'Alabama' },
{ id: 'opt1', value: '1', label: 'Alaska' },
{ id: 'opt2', value: '2', label: 'American Samoa' },
{ id: 'opt3', value: '3', label: 'Arizona' },
{ id: 'opt4', value: '4', label: 'Arkansas' },
{ id: 'opt5', value: '5', label: 'California' },
{ id: 'opt6', value: '6', label: 'Colorado' },
{ id: 'opt7', value: '7', label: 'Connecticut' },
{ id: 'opt8', value: '8', label: 'Delaware' },
{ id: 'opt9', value: '9', label: 'District Of Columbia' },
{ id: 'opt10', value: '10', label: 'Federated States Of Micronesia' },
{ id: 'opt11', value: '11', label: 'Florida' },
{ id: 'opt12', value: '12', label: 'Georgia' },
{ id: 'opt13', value: '13', label: 'Guam' },
{ id: 'opt14', value: '14', label: 'Hawaii' },
{ id: 'opt15', value: '15', label: 'Idaho' },
{ id: 'opt16', value: '16', label: 'Illinois' }
]}
/>
</View>
)
```
render(
<View>
<CustomSelect
options={[
{ id: 'opt0', value: '0', label: 'Alabama' },
{ id: 'opt1', value: '1', label: 'Alaska' },
{ id: 'opt2', value: '2', label: 'American Samoa' },
{ id: 'opt3', value: '3', label: 'Arizona' },
{ id: 'opt4', value: '4', label: 'Arkansas' },
{ id: 'opt5', value: '5', label: 'California' },
{ id: 'opt6', value: '6', label: 'Colorado' },
{ id: 'opt7', value: '7', label: 'Connecticut' },
{ id: 'opt8', value: '8', label: 'Delaware' },
{ id: 'opt9', value: '9', label: 'District Of Columbia' },
{ id: 'opt10', value: '10', label: 'Federated States Of Micronesia' },
{ id: 'opt11', value: '11', label: 'Florida' },
{ id: 'opt12', value: '12', label: 'Georgia' },
{ id: 'opt13', value: '13', label: 'Guam' },
{ id: 'opt14', value: '14', label: 'Hawaii' },
{ id: 'opt15', value: '15', label: 'Idaho' },
{ id: 'opt16', value: '16', label: 'Illinois' }
]}
/>
</View>
)
```

@@ -244,0 +472,0 @@ Selectable has very few opinions about how a combobox component should be composed. It mostly aims to ensure all the proper WAI-ARIA roles and attributes are set on the right elements at the right times. Selectable uses a combination of controllable props and prop getters to set these attributes and provide accessible behavior.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc