@instructure/ui-selectable
Advanced tools
Comparing version 10.4.2-snapshot-11 to 10.4.2-snapshot-13
@@ -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. |
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
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
207104
+ Added@instructure/console@10.4.2-snapshot-13(transitive)
+ Added@instructure/shared-types@10.4.2-snapshot-13(transitive)
+ Added@instructure/ui-decorator@10.4.2-snapshot-13(transitive)
+ Added@instructure/ui-dom-utils@10.4.2-snapshot-13(transitive)
+ Added@instructure/ui-react-utils@10.4.2-snapshot-13(transitive)
+ Added@instructure/ui-testable@10.4.2-snapshot-13(transitive)
+ Added@instructure/ui-utils@10.4.2-snapshot-13(transitive)
- Removed@instructure/console@10.4.2-snapshot-11(transitive)
- Removed@instructure/shared-types@10.4.2-snapshot-11(transitive)
- Removed@instructure/ui-decorator@10.4.2-snapshot-11(transitive)
- Removed@instructure/ui-dom-utils@10.4.2-snapshot-11(transitive)
- Removed@instructure/ui-react-utils@10.4.2-snapshot-11(transitive)
- Removed@instructure/ui-testable@10.4.2-snapshot-11(transitive)
- Removed@instructure/ui-utils@10.4.2-snapshot-11(transitive)