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

@tds/core-button-group

Package Overview
Dependencies
Maintainers
9
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tds/core-button-group - npm Package Compare versions

Comparing version 2.0.10 to 2.1.0

77

ButtonGroup.jsx

@@ -12,3 +12,2 @@ import React from 'react'

import safeRest from '../../shared/utils/safeRest'
import { warn } from '../../shared/utils/warn'

@@ -24,40 +23,37 @@ const StyledButtonGroup = styled(Box)({

*/
const ButtonGroup = ({ name, onChange, onFocus, onBlur, value, label, children, ...rest }) => {
const passedButtons = React.Children.map(children, child =>
React.cloneElement(child, {
name,
onChange,
onFocus,
onBlur,
checked: value === child.props.value,
const ButtonGroup = React.forwardRef(
({ name, onChange, onFocus, onBlur, value, label, children, readOnly, ...rest }, ref) => {
const passedButtons = React.Children.map(children, child =>
React.cloneElement(child, {
name,
onChange,
onFocus,
onBlur,
checked: typeof value !== 'undefined' ? value === child.props.value : undefined,
readOnly,
})
)
const buttonValues = []
Object.keys(passedButtons).forEach(key => {
buttonValues.push(passedButtons[key].props.value)
})
)
const buttonValues = []
Object.keys(passedButtons).forEach(key => {
buttonValues.push(passedButtons[key].props.value)
})
return (
<fieldset {...safeRest(rest)} name={name} ref={ref}>
<legend>
<Text bold size="medium">
{label}
</Text>
</legend>
if (buttonValues.indexOf(value) === -1) {
warn(
'ButtonGroup',
`Selected value "${value}" of ButtonGroup named "${name}" does not match the value of any button in the group. A button must be selected by default. Available button values are: ${buttonValues}`
<StyledButtonGroup between={3} inline>
{passedButtons}
</StyledButtonGroup>
</fieldset>
)
}
)
ButtonGroup.displayName = 'ButtonGroup'
return (
<fieldset {...safeRest(rest)} name={name}>
<legend>
<Text bold size="medium">
{label}
</Text>
</legend>
<StyledButtonGroup between={3} inline>
{passedButtons}
</StyledButtonGroup>
</fieldset>
)
}
ButtonGroup.propTypes = {

@@ -71,3 +67,3 @@ /**

*/
value: PropTypes.string.isRequired,
value: PropTypes.string,
/**

@@ -82,3 +78,3 @@ * A label to be displayed above the ButtonGroup.

*/
onChange: PropTypes.func.isRequired,
onChange: PropTypes.func,
/**

@@ -97,5 +93,11 @@ * A callback function to be invoked when a button receives focus. Passed into all buttons.

/**
* @ignore
*
* A callback function to be invoked when a button loses focus. Passed into all buttons.
*/
readOnly: PropTypes.bool,
/**
* A group of ButtonGroup.Item components.
*/
children: componentWithName('ButtonGroupItem').isRequired,
children: componentWithName('ButtonGroup.Item', true).isRequired,
}

@@ -106,2 +108,5 @@

onBlur: undefined,
onChange: undefined,
value: undefined,
readOnly: undefined,
}

@@ -108,0 +113,0 @@

@@ -7,3 +7,2 @@ ### Minimal usage

- A single `ButtonGroup.Item` within `ButtonGroup` must be selected by default
- Use `ButtonGroup` when one selection needs to be made from multiple options

@@ -19,13 +18,25 @@ - Use when there can only be exactly one choice from multiple options

### Controlled ButtonGroup
If it is required that the state of the `ButtonGroup` be controlled by the application or other external methods, `value` and `onChange` props must be passed to the `ButtonGroup`.
If the `ButtonGroup` should not be changed by user input, a `readOnly` prop must be provided.
If none of the `ButtonGroup.Item` should be pre-selected then the `ButtonGroup` value must be `null`.
```js
initialState = {
choice: '64gb',
choice: null,
}
const onChange = (event) => {
setState({choice: event.target.value})
const onChange = event => {
setState({ choice: event.target.value })
}
<ButtonGroup name="storageSize" onChange={onChange} value={state.choice} label="Please select a storage size">
;<ButtonGroup
name="storageSize"
onChange={onChange}
value={state.choice}
label="Please select a storage size"
>
<ButtonGroup.Item value="64gb">64 GB</ButtonGroup.Item>

@@ -37,2 +48,19 @@ <ButtonGroup.Item value="128gb">128 GB</ButtonGroup.Item>

### Uncontrolled ButtonGroup
If it is not neccessary to control `ButtonGroup` state. You can create a `ButtonGroup` without a `value` prop, in this case the `ButtonGroup` will act as a collection HTML `input` with the type of `radio`. Its value can be accessed by referencing the element via a `ref`.
#### Default values
Due to the nature of uncontrolled components, you cannot set an initial `checked` property on the component. If you need to set a default state for your uncontrolled `ButtonGroup`, you can use the `defaultChecked` property on the default `ButtonGroup.Item` as described [in the react documentation](https://reactjs.org/docs/uncontrolled-components.html#default-values).
```js
<ButtonGroup name="tv" label="Choose your TV">
<ButtonGroup.Item defaultChecked value="Optik TV">
Optik TV
</ButtonGroup.Item>
<ButtonGroup.Item value="Pik TV">Pik TV</ButtonGroup.Item>
</ButtonGroup>
```
### Using A11yContent

@@ -47,12 +75,22 @@

const onChange = (event) => {
setState({choice: event.target.value})
const onChange = event => {
setState({ choice: event.target.value })
}
<ButtonGroup name="purposeOfVisit" onChange={onChange} value={state.choice} label="What was the purpose of your visit?">
<ButtonGroup.Item value="buy">Buy<A11yContent> mobile phones</A11yContent></ButtonGroup.Item>
<ButtonGroup.Item value="inquiry">Inquiry <A11yContent> about mobile phones</A11yContent></ButtonGroup.Item>
<ButtonGroup.Item value="tradeIn">Trade-In <A11yContent> mobile phones</A11yContent></ButtonGroup.Item>
;<ButtonGroup
name="purposeOfVisit"
onChange={onChange}
value={state.choice}
label="What was the purpose of your visit?"
>
<ButtonGroup.Item value="buy">
Buy<A11yContent> mobile phones</A11yContent>
</ButtonGroup.Item>
<ButtonGroup.Item value="inquiry">
Inquiry <A11yContent> about mobile phones</A11yContent>
</ButtonGroup.Item>
<ButtonGroup.Item value="tradeIn">
Trade-In <A11yContent> mobile phones</A11yContent>
</ButtonGroup.Item>
</ButtonGroup>
```

@@ -70,29 +70,39 @@ import React from 'react'

const ButtonGroupItem = ({
name,
value,
checked,
onChange,
onFocus,
onBlur,
children,
...rest
}) => {
const itemId = generateId(name).postfix(value)
return (
<StyledButtonGroupItem {...safeRest(rest)}>
<StyledInput
id={itemId}
name={name}
value={value}
type="radio"
checked={checked}
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
/>
<StyledLabel htmlFor={itemId}>{children}</StyledLabel>
</StyledButtonGroupItem>
)
}
const ButtonGroupItem = React.forwardRef(
(
{
name,
value,
checked,
onChange,
onFocus,
onBlur,
children,
defaultChecked,
readOnly,
...rest
},
ref
) => {
const itemId = generateId(name).postfix(value)
return (
<StyledButtonGroupItem {...safeRest(rest)}>
<StyledInput
id={itemId}
name={name}
value={value}
type="radio"
checked={checked}
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
defaultChecked={defaultChecked}
readOnly={readOnly}
ref={ref}
/>
<StyledLabel htmlFor={itemId}>{children}</StyledLabel>
</StyledButtonGroupItem>
)
}
)

@@ -135,2 +145,16 @@ ButtonGroupItem.propTypes = {

/**
*@ignore
*
* React defaultChecked
* https://reactjs.org/docs/uncontrolled-components.html#default-values
*/
defaultChecked: PropTypes.bool,
/**
*@ignore
*
* HTML readOnly
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly
*/
readOnly: PropTypes.bool,
/**
* The button's label. It can include the `A11yContent` component or strings.

@@ -148,2 +172,4 @@ */

onBlur: undefined,
defaultChecked: undefined,
readOnly: undefined,
}

@@ -150,0 +176,0 @@

@@ -6,2 +6,14 @@ # Change Log

# [2.1.0](https://github.com/telusdigital/tds-core/compare/@tds/core-button-group@2.0.10...@tds/core-button-group@2.1.0) (2019-08-12)
### Features
* **core-button-group:** allow ButtonGroup to be uncontrolled ([63e26c2](https://github.com/telusdigital/tds-core/commit/63e26c2))
* **core-button-group:** allow unselected by default ([ddb99b8](https://github.com/telusdigital/tds-core/commit/ddb99b8))
## [2.0.10](https://github.com/telusdigital/tds-core/compare/@tds/core-button-group@2.0.9...@tds/core-button-group@2.0.10) (2019-08-09)

@@ -8,0 +20,0 @@

@@ -169,4 +169,3 @@ 'use strict';

});
var ButtonGroupItem = function ButtonGroupItem(_ref) {
var ButtonGroupItem = React.forwardRef(function (_ref, ref) {
var name = _ref.name,

@@ -179,3 +178,5 @@ value = _ref.value,

children = _ref.children,
rest = objectWithoutProperties(_ref, ["name", "value", "checked", "onChange", "onFocus", "onBlur", "children"]);
defaultChecked = _ref.defaultChecked,
readOnly = _ref.readOnly,
rest = objectWithoutProperties(_ref, ["name", "value", "checked", "onChange", "onFocus", "onBlur", "children", "defaultChecked", "readOnly"]);

@@ -191,8 +192,10 @@ var itemId = generateId(name).postfix(value);

onFocus: onFocus,
onBlur: onBlur
onBlur: onBlur,
defaultChecked: defaultChecked,
readOnly: readOnly,
ref: ref
}), React.createElement(StyledLabel, {
htmlFor: itemId
}, children));
};
});
ButtonGroupItem.propTypes = {

@@ -240,2 +243,18 @@ /**

/**
*@ignore
*
* React defaultChecked
* https://reactjs.org/docs/uncontrolled-components.html#default-values
*/
defaultChecked: PropTypes.bool,
/**
*@ignore
*
* HTML readOnly
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly
*/
readOnly: PropTypes.bool,
/**
* The button's label. It can include the `A11yContent` component or strings.

@@ -250,15 +269,8 @@ */

onFocus: undefined,
onBlur: undefined
onBlur: undefined,
defaultChecked: undefined,
readOnly: undefined
};
ButtonGroupItem.displayName = 'ButtonGroup.Item';
/* eslint-disable import/prefer-default-export */
var warn = function warn(componentName, message) {
if (process.env.NODE_ENV === 'production') {
return;
}
console.warn("[TDS] ".concat(componentName, ": ").concat(message)); // eslint-disable-line no-console
};
var StyledButtonGroup = styled(Box)({

@@ -273,3 +285,3 @@ flexFlow: 'row wrap',

var ButtonGroup = function ButtonGroup(_ref) {
var ButtonGroup = React.forwardRef(function (_ref, ref) {
var name = _ref.name,

@@ -282,3 +294,4 @@ onChange = _ref.onChange,

children = _ref.children,
rest = objectWithoutProperties(_ref, ["name", "onChange", "onFocus", "onBlur", "value", "label", "children"]);
readOnly = _ref.readOnly,
rest = objectWithoutProperties(_ref, ["name", "onChange", "onFocus", "onBlur", "value", "label", "children", "readOnly"]);

@@ -291,3 +304,4 @@ var passedButtons = React.Children.map(children, function (child) {

onBlur: onBlur,
checked: value === child.props.value
checked: typeof value !== 'undefined' ? value === child.props.value : undefined,
readOnly: readOnly
});

@@ -299,9 +313,5 @@ });

});
if (buttonValues.indexOf(value) === -1) {
warn('ButtonGroup', "Selected value \"".concat(value, "\" of ButtonGroup named \"").concat(name, "\" does not match the value of any button in the group. A button must be selected by default. Available button values are: ").concat(buttonValues));
}
return React.createElement("fieldset", _extends_1({}, safeRest(rest), {
name: name
name: name,
ref: ref
}), React.createElement("legend", null, React.createElement(Text, {

@@ -314,4 +324,4 @@ bold: true,

}, passedButtons));
};
});
ButtonGroup.displayName = 'ButtonGroup';
ButtonGroup.propTypes = {

@@ -326,3 +336,3 @@ /**

*/
value: PropTypes.string.isRequired,
value: PropTypes.string,

@@ -339,3 +349,3 @@ /**

*/
onChange: PropTypes.func.isRequired,
onChange: PropTypes.func,

@@ -357,9 +367,19 @@ /**

/**
* @ignore
*
* A callback function to be invoked when a button loses focus. Passed into all buttons.
*/
readOnly: PropTypes.bool,
/**
* A group of ButtonGroup.Item components.
*/
children: utilPropTypes.componentWithName('ButtonGroupItem').isRequired
children: utilPropTypes.componentWithName('ButtonGroup.Item', true).isRequired
};
ButtonGroup.defaultProps = {
onFocus: undefined,
onBlur: undefined
onBlur: undefined,
onChange: undefined,
value: undefined,
readOnly: undefined
};

@@ -366,0 +386,0 @@ ButtonGroup.Item = ButtonGroupItem;

@@ -165,4 +165,3 @@ import React from 'react';

});
var ButtonGroupItem = function ButtonGroupItem(_ref) {
var ButtonGroupItem = React.forwardRef(function (_ref, ref) {
var name = _ref.name,

@@ -175,3 +174,5 @@ value = _ref.value,

children = _ref.children,
rest = objectWithoutProperties(_ref, ["name", "value", "checked", "onChange", "onFocus", "onBlur", "children"]);
defaultChecked = _ref.defaultChecked,
readOnly = _ref.readOnly,
rest = objectWithoutProperties(_ref, ["name", "value", "checked", "onChange", "onFocus", "onBlur", "children", "defaultChecked", "readOnly"]);

@@ -187,8 +188,10 @@ var itemId = generateId(name).postfix(value);

onFocus: onFocus,
onBlur: onBlur
onBlur: onBlur,
defaultChecked: defaultChecked,
readOnly: readOnly,
ref: ref
}), React.createElement(StyledLabel, {
htmlFor: itemId
}, children));
};
});
ButtonGroupItem.propTypes = {

@@ -236,2 +239,18 @@ /**

/**
*@ignore
*
* React defaultChecked
* https://reactjs.org/docs/uncontrolled-components.html#default-values
*/
defaultChecked: PropTypes.bool,
/**
*@ignore
*
* HTML readOnly
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly
*/
readOnly: PropTypes.bool,
/**
* The button's label. It can include the `A11yContent` component or strings.

@@ -246,15 +265,8 @@ */

onFocus: undefined,
onBlur: undefined
onBlur: undefined,
defaultChecked: undefined,
readOnly: undefined
};
ButtonGroupItem.displayName = 'ButtonGroup.Item';
/* eslint-disable import/prefer-default-export */
var warn = function warn(componentName, message) {
if (process.env.NODE_ENV === 'production') {
return;
}
console.warn("[TDS] ".concat(componentName, ": ").concat(message)); // eslint-disable-line no-console
};
var StyledButtonGroup = styled(Box)({

@@ -269,3 +281,3 @@ flexFlow: 'row wrap',

var ButtonGroup = function ButtonGroup(_ref) {
var ButtonGroup = React.forwardRef(function (_ref, ref) {
var name = _ref.name,

@@ -278,3 +290,4 @@ onChange = _ref.onChange,

children = _ref.children,
rest = objectWithoutProperties(_ref, ["name", "onChange", "onFocus", "onBlur", "value", "label", "children"]);
readOnly = _ref.readOnly,
rest = objectWithoutProperties(_ref, ["name", "onChange", "onFocus", "onBlur", "value", "label", "children", "readOnly"]);

@@ -287,3 +300,4 @@ var passedButtons = React.Children.map(children, function (child) {

onBlur: onBlur,
checked: value === child.props.value
checked: typeof value !== 'undefined' ? value === child.props.value : undefined,
readOnly: readOnly
});

@@ -295,9 +309,5 @@ });

});
if (buttonValues.indexOf(value) === -1) {
warn('ButtonGroup', "Selected value \"".concat(value, "\" of ButtonGroup named \"").concat(name, "\" does not match the value of any button in the group. A button must be selected by default. Available button values are: ").concat(buttonValues));
}
return React.createElement("fieldset", _extends_1({}, safeRest(rest), {
name: name
name: name,
ref: ref
}), React.createElement("legend", null, React.createElement(Text, {

@@ -310,4 +320,4 @@ bold: true,

}, passedButtons));
};
});
ButtonGroup.displayName = 'ButtonGroup';
ButtonGroup.propTypes = {

@@ -322,3 +332,3 @@ /**

*/
value: PropTypes.string.isRequired,
value: PropTypes.string,

@@ -335,3 +345,3 @@ /**

*/
onChange: PropTypes.func.isRequired,
onChange: PropTypes.func,

@@ -353,9 +363,19 @@ /**

/**
* @ignore
*
* A callback function to be invoked when a button loses focus. Passed into all buttons.
*/
readOnly: PropTypes.bool,
/**
* A group of ButtonGroup.Item components.
*/
children: componentWithName('ButtonGroupItem').isRequired
children: componentWithName('ButtonGroup.Item', true).isRequired
};
ButtonGroup.defaultProps = {
onFocus: undefined,
onBlur: undefined
onBlur: undefined,
onChange: undefined,
value: undefined,
readOnly: undefined
};

@@ -362,0 +382,0 @@ ButtonGroup.Item = ButtonGroupItem;

{
"name": "@tds/core-button-group",
"version": "2.0.10",
"version": "2.1.0",
"description": "An input component utilizing buttons that act as radios.",

@@ -42,3 +42,3 @@ "main": "index.cjs.js",

},
"gitHead": "56cee5f41176b371248ff7d0325ecfa998c04aa4"
"gitHead": "99d776ba7523acbddc66f60227355bc275773b4c"
}
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