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

@cmsgov/design-system-core

Package Overview
Dependencies
Maintainers
1
Versions
81
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cmsgov/design-system-core - npm Package Compare versions

Comparing version 1.0.0-rc.2 to 1.0.0

dist/components/SkipNav/SkipNav.css

13

dist/components/ChoiceList/Choice.js

@@ -38,2 +38,3 @@ 'use strict';

var Choice = function Choice(props) {
/* eslint-disable prefer-const */
var children = props.children,

@@ -44,2 +45,3 @@ className = props.className,

inputProps = _objectWithoutProperties(props, ['children', 'className', 'id', 'inversed']);
/* eslint-enable prefer-const */

@@ -78,5 +80,4 @@ var inputClasses = (0, _classnames2.default)('ds-c-choice', { 'ds-c-choice--inverse': inversed });

/**
* Setting this prop will render a read-only field and require an `onChange`
* event handler if you'd want to check its checked stated. Use `defaultChecked`
* if you want the field to be mutable.
* **Note**: Setting this prop will render a read-only field. If the field should be
* mutable, use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`
*/

@@ -89,4 +90,4 @@ checked: _propTypes2.default.bool,

/**
* Sets the initial checked state and allows the user to check/uncheck the
* field without also requiring an `onChange` event handler.
* Sets the initial checked state. Use this for an uncontrolled component;
* otherwise, use the `checked` property.
*/

@@ -104,3 +105,3 @@ defaultChecked: _propTypes2.default.bool,

/**
* The `input` `name` attribute
* The `input` field's `name` attribute
*/

@@ -107,0 +108,0 @@ name: _propTypes2.default.string.isRequired,

@@ -51,10 +51,9 @@ 'use strict';

/**
* A `ChoiceList` component can be used to render a `select` menu, radio
* A `ChoiceList` component can be used to render a select menu, radio
* button group, or checkbox group.
*
* You can manually pass in the `type` prop, but the real power of this component
* is unleashed when you let it determine the type of fields for you. It takes
* into account accessibility and usability best practices, so you can pass in
* an array of choices and let it determine what type of field would be best for
* the user.
* By default the component determines the type of field for you, taking
* into account accessibility and usability best practices. So, you can pass in
* an array of `choices` and let it determine what type of field would be best for
* the user, or alternatively you can manually pass in the `type` prop.
*/

@@ -241,3 +240,3 @@ var ChoiceList = exports.ChoiceList = function (_React$PureComponent) {

/**
* Hint text
* Additional hint text to display
*/

@@ -250,3 +249,3 @@ hint: _propTypes2.default.node,

/**
* The label for the entire list of choices
* Label for the field
*/

@@ -263,2 +262,5 @@ label: _propTypes2.default.node.isRequired,

multiple: _propTypes2.default.bool,
/**
* The field's `name` attribute
*/
name: _propTypes2.default.string.isRequired,

@@ -265,0 +267,0 @@ onBlur: _propTypes2.default.func,

@@ -37,2 +37,3 @@ 'use strict';

var Select = function Select(props) {
/* eslint-disable prefer-const */
var children = props.children,

@@ -43,2 +44,3 @@ className = props.className,

selectProps = _objectWithoutProperties(props, ['children', 'className', 'id', 'inversed']);
/* eslint-enable prefer-const */

@@ -69,4 +71,4 @@ var classes = (0, _classnames2.default)('ds-c-field ds-c-field--select', { 'ds-c-field--inverse': inversed }, className);

/**
* Sets the initial `selected` state and allows the user to select a different
* option without also requiring an `onChange` event handler.
* Sets the initial selected state. Use this for an uncontrolled component;
* otherwise, use the `selected` property.
*/

@@ -85,4 +87,5 @@ defaultValue: _propTypes2.default.string,

/**
* Setting this prop to `true` will result in an error message due to
* accessibility concerns. See the usability guidelines for more info.
* Setting this prop will result in a PropTypes error message due to
* accessibility concerns. Use checkboxes instead if you need to support multiple
* selections. See the Guidance tab for more info.
*/

@@ -96,2 +99,5 @@ multiple: function multiple(props, propName, componentName) {

},
/**
* The `select` field's `name` attribute
*/
name: _propTypes2.default.string.isRequired,

@@ -101,5 +107,4 @@ onBlur: _propTypes2.default.func,

/**
* Setting this prop will render a read-only field and require an `onChange`
* event handler if you'd want to change its `selected` stated. Use
* `defaultValue` if you want the field to be mutable.
* **Note**: Setting this prop will render a read-only field. If the field should be
* mutable, use `defaultValue`. Otherwise, set either `onChange` or `readOnly`
*/

@@ -106,0 +111,0 @@ value: _propTypes2.default.string

@@ -113,3 +113,3 @@ 'use strict';

/**
* Hint text
* Additional hint text to display
*/

@@ -116,0 +116,0 @@ hint: _propTypes2.default.node,

@@ -91,2 +91,14 @@ 'use strict';

var _SkipNav = require('./SkipNav/SkipNav');
Object.keys(_SkipNav).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _SkipNav[key];
}
});
});
var _Tab = require('./Tabs/Tab');

@@ -162,2 +174,14 @@

});
});
var _VerticalNavItemLabel = require('./VerticalNav/VerticalNavItemLabel');
Object.keys(_VerticalNavItemLabel).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _VerticalNavItemLabel[key];
}
});
});

@@ -89,4 +89,4 @@ 'use strict';

/**
* You can optionally set the `href` attribute used for the tab. This can be
* useful if you want to use relative links rather than a URL hash (the default)
* Sets the `href` attribute used for the tab. This can be useful if you want
* to use relative links rather than a URL hash (the default).
*/

@@ -101,3 +101,3 @@ href: _propTypes2.default.string,

/**
* The `id` of the associated `TabPanel`. Used for the `aria-controls` attribute
* The `id` of the associated `TabPanel`. Used for the `aria-controls` attribute.
*/

@@ -104,0 +104,0 @@ panelId: _propTypes2.default.string.isRequired,

@@ -22,2 +22,6 @@ 'use strict';

/**
* A `TabPanel` is a presentational component which accepts a tab's content as
* its `children`.
*/
function TabPanel(props) {

@@ -75,3 +79,3 @@ var classes = (0, _classnames2.default)('ds-c-tabs__panel', props.className);

/**
* The `id` of the associated `Tab`. Used for the `aria-labelledby` attribute
* The `id` of the associated `Tab`. Used for the `aria-labelledby` attribute.
*/

@@ -78,0 +82,0 @@ tabId: _propTypes2.default.string

@@ -76,4 +76,4 @@ 'use strict';

/**
* A container component that manages the state of your tabs for you. For most
* cases, you'll want to use this component rather than the presentational
* `Tabs` is a container component that manages the state of your tabs for you.
* In most cases, you'll want to use this component rather than the presentational
* components (`Tab`, `TabPanel`) on their own.

@@ -207,4 +207,4 @@ */

/**
* Default selected `TabPanel`'s `id`. If this isn't set, the first `TabPanel`
* will be selected.
* Sets the initial selected `TabPanel` state. If this isn't set, the first
* `TabPanel` will be selected.
*/

@@ -211,0 +211,0 @@ defaultSelectedId: _propTypes2.default.string,

@@ -39,5 +39,4 @@ 'use strict';

/**
The `TextField` component affords a user to type text into a form.
By default it renders a field for capturing a single line of text,
but can be configured to support multiline text.
* A `TextField` component renders an input field as well as supporting UI
* elements like a label, error message, and hint text.
*/

@@ -108,8 +107,8 @@ var TextField = exports.TextField = function (_React$PureComponent) {

/**
* Additional classes to be added to the root element
* Additional classes to be added to the root `div` element
*/
className: _propTypes2.default.string,
/**
* Default value of the text field, if any. Use this for an uncontrolled
* component; otherwise, use the `value` property
* Sets the initial value. Use this for an uncontrolled component; otherwise,
* use the `value` property.
*/

@@ -124,3 +123,3 @@ defaultValue: _propTypes2.default.string,

/**
* Hint text
* Additional hint text to display
*/

@@ -133,7 +132,7 @@ hint: _propTypes2.default.node,

/**
* The label for the entire list of choices
* Label for the input
*/
label: _propTypes2.default.node.isRequired,
/**
* Additional classes to be added to the `FormLabel`
* Additional classes to be added to the label
*/

@@ -149,4 +148,4 @@ labelClassName: _propTypes2.default.string,

/**
* Optionally specify the number of visible text lines for the control. Only
* applicable if this is a multiline field
* Optionally specify the number of visible text lines for the field. Only
* applicable if this is a multiline field.
*/

@@ -159,4 +158,4 @@ rows: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]),

/**
* Current value of the text field. Use this for a controlled component where
* you are maintaining its current state; otherwise, use the `defaultValue` property
* **Note**: Setting this prop will render a read-only field. If the field should be
* mutable, use `defaultValue`. Otherwise, set `onChange` or `disabled`.
*/

@@ -163,0 +162,0 @@ value: _propTypes2.default.string

@@ -37,3 +37,3 @@ 'use strict';

/**
* The `VerticalNav` React component accepts list items as a JSON object and
* A `VerticalNav` component accepts list items as a JSON object and
* includes additional functionality like collapsible nested menus.

@@ -40,0 +40,0 @@ */

@@ -22,2 +22,6 @@ 'use strict';

var _VerticalNavItemLabel = require('./VerticalNavItemLabel');
var _VerticalNavItemLabel2 = _interopRequireDefault(_VerticalNavItemLabel);
var _classnames = require('classnames');

@@ -47,10 +51,6 @@

_this.handleLinkClick = _this.handleLinkClick.bind(_this);
_this.handleToggleClick = _this.handleToggleClick.bind(_this);
_this.handleLabelClick = _this.handleLabelClick.bind(_this);
_this.id = _this.props.id || (0, _lodash2.default)('VerticalNavItem_');
_this.subnavId = _this.id + '__subnav';
_this.state = {
collapsed: _this.props.defaultCollapsed
};
_this.state = { collapsed: _this.props.defaultCollapsed };
return _this;

@@ -66,5 +66,28 @@ }

}
/**
* Called when VerticalNavItemLabel is clicked. Since the "label" could be
* a link, subnav toggle button, or plain text, we use this method to
* determine what action to take and which event to actually fire.
* @param {Object} SyntheticEvent
*/
}, {
key: 'handleLinkClick',
value: function handleLinkClick(evt) {
key: 'handleLabelClick',
value: function handleLabelClick(evt) {
if (this.hasSubnav()) {
return this.handleToggleClick();
}
return this.handleClick(evt);
}
/**
* Note: This event handler will only get called when the VerticalNavItemLabel
* is a link or plain text
*/
}, {
key: 'handleClick',
value: function handleClick(evt) {
if (this.props.onClick) {

@@ -82,3 +105,3 @@ this.props.onClick(evt, this.id, this.props.url);

value: function hasSubnav() {
return this.props.items && this.props.items.length;
return Boolean(this.props.items && this.props.items.length > 0);
}

@@ -88,2 +111,3 @@

* Check if this item is selected or if it is a parent of a selected item
* @return {Boolean}
*/

@@ -99,2 +123,4 @@

}
return false;
}

@@ -105,2 +131,3 @@

* @param {Array} children - The nested items
* @return {Boolean}
*/

@@ -122,18 +149,15 @@

}, {
key: 'renderSubnavToggle',
value: function renderSubnavToggle() {
if (this.hasSubnav()) {
var label = this.state.collapsed ? this.props.ariaCollapsedStateButtonLabel : this.props.ariaExpandedStateButtonLabel;
key: 'subnavItems',
value: function subnavItems() {
if (this.props.url) {
// Since the VerticalNavItemLabel will just toggle the subnav, we
// add a link to the top of the subnav for this item. Otherwise there
// wouldn't be a way to actually visit its URL
var item = Object.assign({}, this.props);
delete item.items;
return _react2.default.createElement(
'button',
{
'aria-controls': this.subnavId,
'aria-expanded': !this.state.collapsed,
className: 'ds-c-vertical-nav__subnav-toggle',
onClick: this.handleToggleClick
},
label
);
return [item].concat(this.props.items);
}
return this.props.items;
}

@@ -148,3 +172,3 @@ }, {

id: this.subnavId,
items: this.props.items,
items: this.subnavItems(),
nested: true

@@ -158,11 +182,2 @@ });

var classes = (0, _classnames2.default)('ds-c-vertical-nav__item', this.props.className);
var LinkComponent = this.props.url ? 'a' : 'div';
var linkProps = {
className: (0, _classnames2.default)('ds-c-vertical-nav__link', {
'ds-c-vertical-nav__link--current': this.isSelected(),
'ds-c-vertical-nav__link--parent': this.hasSubnav()
}),
href: this.props.url ? this.props.url : undefined,
onClick: this.props.onClick ? this.handleLinkClick : undefined
};

@@ -172,8 +187,13 @@ return _react2.default.createElement(

{ className: classes },
_react2.default.createElement(
LinkComponent,
linkProps,
this.props.label
),
this.renderSubnavToggle(),
_react2.default.createElement(_VerticalNavItemLabel2.default, {
ariaCollapsedStateButtonLabel: this.props.ariaCollapsedStateButtonLabel,
ariaExpandedStateButtonLabel: this.props.ariaExpandedStateButtonLabel,
collapsed: this.state.collapsed,
label: this.props.label,
hasSubnav: this.hasSubnav(),
onClick: this.handleLabelClick,
selected: this.isSelected(),
subnavId: this.subnavId,
url: this.props.url
}),
this.renderSubnav()

@@ -188,2 +208,5 @@ );

VerticalNavItem.defaultProps = {
// Unfortunately, we're defining these default ARIA pros here and in
// VerticalNavItemLabel. We define them here so they show in the docs.
// TODO(sawyer): Update react-docgen so we don't have to do this
ariaCollapsedStateButtonLabel: 'Expand sub-navigation',

@@ -214,3 +237,3 @@ ariaExpandedStateButtonLabel: 'Collapse sub-navigation',

/**
* Called when the item is clicked, with the following arguments:
* Called when the link is clicked, with the following arguments:
* [`SyntheticEvent`](https://facebook.github.io/react/docs/events.html),

@@ -217,0 +240,0 @@ * `id`, `url`.

{
"name": "@cmsgov/design-system-core",
"version": "1.0.0-rc.2",
"version": "1.0.0",
"publishConfig": {

@@ -12,3 +12,3 @@ "access": "public"

"dependencies": {
"@cmsgov/design-system-support": "^1.0.0-rc.2",
"@cmsgov/design-system-support": "^1.0.0",
"classnames": "^2.2.5",

@@ -15,0 +15,0 @@ "lodash.uniqueid": "^4.0.1",

@@ -5,4 +5,5 @@ This package contains the following design system assets:

- Utility classes
- Core Sass/CSS components
- Core React components
- Sass/CSS and React components
- Sass mixins and variables
- Fonts and images

@@ -29,3 +30,3 @@ ## Installation

[Please view the documentation site for additional information.](https://cmsgov.github.io/design-system/)
[Please view the documentation site for additional information.](https://design.cms.gov/)

@@ -49,4 +50,6 @@ ## Examples

```
├── dist Transpiled CSS and fonts
└── src Sass and JSX
├── dist Compiled CSS and JS
├── fonts
├── images
└── src Non-compiled Sass and JSX
├── base Base HTML styles

@@ -56,6 +59,4 @@ ├── components Sass and React components

│   └── etc...
├── fonts
├── generics Far reaching selectors
├── images
└── utilities Functional CSS classes to apply individual traits
```

@@ -8,11 +8,10 @@ /* eslint-disable react/display-name */

<div>
<Button>React button</Button>
<Button>Button</Button>
<Button
className='ds-u-margin-left--1'
href='http://example.com'
target='_blank'
href='javascript:void(0);'
variation='primary'
>
React anchor button
Anchor button
</Button>

@@ -19,0 +18,0 @@ </div>

@@ -35,3 +35,3 @@ import PropTypes from 'prop-types';

let attrs = {
const attrs = {
className: this.classNames(),

@@ -38,0 +38,0 @@ ...props

@@ -14,2 +14,3 @@ import PropTypes from 'prop-types';

export const Choice = function(props) {
/* eslint-disable prefer-const */
let { // Using let rather than const since we sometimes rewrite id

@@ -22,2 +23,3 @@ children,

} = props;
/* eslint-enable prefer-const */

@@ -55,5 +57,4 @@ const inputClasses = classNames(

/**
* Setting this prop will render a read-only field and require an `onChange`
* event handler if you'd want to check its checked stated. Use `defaultChecked`
* if you want the field to be mutable.
* **Note**: Setting this prop will render a read-only field. If the field should be
* mutable, use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`
*/

@@ -66,4 +67,4 @@ checked: PropTypes.bool,

/**
* Sets the initial checked state and allows the user to check/uncheck the
* field without also requiring an `onChange` event handler.
* Sets the initial checked state. Use this for an uncontrolled component;
* otherwise, use the `checked` property.
*/

@@ -81,3 +82,3 @@ defaultChecked: PropTypes.bool,

/**
* The `input` `name` attribute
* The `input` field's `name` attribute
*/

@@ -84,0 +85,0 @@ name: PropTypes.string.isRequired,

@@ -6,5 +6,5 @@ /* eslint-disable react/display-name */

function generateChoices(length) {
let choices = [];
const choices = [];
for (var i = 0; i < length; i++) {
for (let i = 0; i < length; i++) {
choices.push({

@@ -20,4 +20,4 @@ label: `Choice ${i + 1}`,

export default function() {
let choices = generateChoices(4);
let options = generateChoices(8);
const choices = generateChoices(4);
const options = generateChoices(8);

@@ -49,15 +49,4 @@ choices[1].defaultChecked = true;

/>
<div className='ds-base--inverse ds-u-margin-top--4 ds-u-padding--1'>
<ChoiceList
choices={options}
hint='Example hint text'
inversed
label='Select example'
labelClassName='ds-u-margin-top--0'
name='select_choices_field_inverse'
/>
</div>
</div>
);
}

@@ -10,10 +10,9 @@ import Choice from './Choice';

/**
* A `ChoiceList` component can be used to render a `select` menu, radio
* A `ChoiceList` component can be used to render a select menu, radio
* button group, or checkbox group.
*
* You can manually pass in the `type` prop, but the real power of this component
* is unleashed when you let it determine the type of fields for you. It takes
* into account accessibility and usability best practices, so you can pass in
* an array of choices and let it determine what type of field would be best for
* the user.
* By default the component determines the type of field for you, taking
* into account accessibility and usability best practices. So, you can pass in
* an array of `choices` and let it determine what type of field would be best for
* the user, or alternatively you can manually pass in the `type` prop.
*/

@@ -28,3 +27,3 @@ export class ChoiceList extends React.PureComponent {

const ChoiceComponent = type === 'select' ? 'option' : Choice;
let selectProps = {};
const selectProps = {};

@@ -181,3 +180,3 @@ const choices = this.props.choices.map(choice => {

/**
* Hint text
* Additional hint text to display
*/

@@ -190,3 +189,3 @@ hint: PropTypes.node,

/**
* The label for the entire list of choices
* Label for the field
*/

@@ -203,2 +202,5 @@ label: PropTypes.node.isRequired,

multiple: PropTypes.bool,
/**
* The field's `name` attribute
*/
name: PropTypes.string.isRequired,

@@ -205,0 +207,0 @@ onBlur: PropTypes.func,

@@ -6,5 +6,5 @@ import ChoiceList from './ChoiceList';

function generateChoices(length) {
let choices = [];
const choices = [];
for (var i = 0; i < length; i++) {
for (let i = 0; i < length; i++) {
choices.push({

@@ -91,3 +91,3 @@ label: `Choice ${i + 1}`,

it('passes checked prop', () => {
let choices = generateChoices(4);
const choices = generateChoices(4);
choices[1].checked = true;

@@ -101,3 +101,3 @@ const data = shallowRender({ choices });

it('passes defaultChecked prop', () => {
let choices = generateChoices(4);
const choices = generateChoices(4);
choices[1].defaultChecked = true;

@@ -111,3 +111,3 @@ const data = shallowRender({ choices });

it('passes disabled prop', () => {
let choices = generateChoices(4);
const choices = generateChoices(4);
choices[1].disabled = true;

@@ -114,0 +114,0 @@ const data = shallowRender({ choices });

@@ -13,3 +13,4 @@ import PropTypes from 'prop-types';

export const Select = function(props) {
let {
/* eslint-disable prefer-const */
let { // Using let rather than const since we sometimes rewrite id
children,

@@ -21,2 +22,3 @@ className,

} = props;
/* eslint-enable prefer-const */

@@ -51,4 +53,4 @@ const classes = classNames(

/**
* Sets the initial `selected` state and allows the user to select a different
* option without also requiring an `onChange` event handler.
* Sets the initial selected state. Use this for an uncontrolled component;
* otherwise, use the `selected` property.
*/

@@ -67,4 +69,5 @@ defaultValue: PropTypes.string,

/**
* Setting this prop to `true` will result in an error message due to
* accessibility concerns. See the usability guidelines for more info.
* Setting this prop will result in a PropTypes error message due to
* accessibility concerns. Use checkboxes instead if you need to support multiple
* selections. See the Guidance tab for more info.
*/

@@ -81,2 +84,5 @@ multiple: function(props, propName, componentName) {

},
/**
* The `select` field's `name` attribute
*/
name: PropTypes.string.isRequired,

@@ -86,5 +92,4 @@ onBlur: PropTypes.func,

/**
* Setting this prop will render a read-only field and require an `onChange`
* event handler if you'd want to change its `selected` stated. Use
* `defaultValue` if you want the field to be mutable.
* **Note**: Setting this prop will render a read-only field. If the field should be
* mutable, use `defaultValue`. Otherwise, set either `onChange` or `readOnly`
*/

@@ -91,0 +96,0 @@ value: PropTypes.string

@@ -10,5 +10,5 @@ import React from 'react';

function generateOptions(count) {
let options = [];
const options = [];
for (var i = 1; i < count + 1; i++) {
for (let i = 1; i < count + 1; i++) {
options.push(<option key={i} value={String(i)}>{i}</option>);

@@ -15,0 +15,0 @@ }

@@ -68,3 +68,3 @@ import PropTypes from 'prop-types';

/**
* Hint text
* Additional hint text to display
*/

@@ -71,0 +71,0 @@ hint: PropTypes.node,

@@ -10,2 +10,3 @@ 'use strict';

export * from './FormLabel/FormLabel';
export * from './SkipNav/SkipNav';
export * from './Tabs/Tab';

@@ -17,1 +18,2 @@ export * from './Tabs/Tabs';

export * from './VerticalNav/VerticalNavItem';
export * from './VerticalNav/VerticalNavItemLabel';

@@ -57,4 +57,4 @@ import PropTypes from 'prop-types';

/**
* You can optionally set the `href` attribute used for the tab. This can be
* useful if you want to use relative links rather than a URL hash (the default)
* Sets the `href` attribute used for the tab. This can be useful if you want
* to use relative links rather than a URL hash (the default).
*/

@@ -69,3 +69,3 @@ href: PropTypes.string,

/**
* The `id` of the associated `TabPanel`. Used for the `aria-controls` attribute
* The `id` of the associated `TabPanel`. Used for the `aria-controls` attribute.
*/

@@ -72,0 +72,0 @@ panelId: PropTypes.string.isRequired,

@@ -5,2 +5,6 @@ import PropTypes from 'prop-types';

/**
* A `TabPanel` is a presentational component which accepts a tab's content as
* its `children`.
*/
export function TabPanel(props) {

@@ -58,3 +62,3 @@ const classes = classnames('ds-c-tabs__panel', props.className);

/**
* The `id` of the associated `Tab`. Used for the `aria-labelledby` attribute
* The `id` of the associated `Tab`. Used for the `aria-labelledby` attribute.
*/

@@ -61,0 +65,0 @@ tabId: PropTypes.string

@@ -45,4 +45,4 @@ import PropTypes from 'prop-types';

/**
* A container component that manages the state of your tabs for you. For most
* cases, you'll want to use this component rather than the presentational
* `Tabs` is a container component that manages the state of your tabs for you.
* In most cases, you'll want to use this component rather than the presentational
* components (`Tab`, `TabPanel`) on their own.

@@ -151,4 +151,4 @@ */

/**
* Default selected `TabPanel`'s `id`. If this isn't set, the first `TabPanel`
* will be selected.
* Sets the initial selected `TabPanel` state. If this isn't set, the first
* `TabPanel` will be selected.
*/

@@ -155,0 +155,0 @@ defaultSelectedId: PropTypes.string,

@@ -32,19 +32,4 @@ /* eslint-disable react/display-name */

/>
<div className='ds-base--inverse ds-u-margin-top--3 ds-u-padding--2'>
<TextField
inversed
label='Single line'
labelClassName='ds-u-margin-top--0'
name='inversed_single_example'
/>
<TextField
label='Disabled field'
disabled
inversed
name='inversed_disabled_example'
/>
</div>
</div>
);
}

@@ -8,5 +8,4 @@ import FormLabel from '../FormLabel/FormLabel';

/**
The `TextField` component affords a user to type text into a form.
By default it renders a field for capturing a single line of text,
but can be configured to support multiline text.
* A `TextField` component renders an input field as well as supporting UI
* elements like a label, error message, and hint text.
*/

@@ -71,8 +70,8 @@ export class TextField extends React.PureComponent {

/**
* Additional classes to be added to the root element
* Additional classes to be added to the root `div` element
*/
className: PropTypes.string,
/**
* Default value of the text field, if any. Use this for an uncontrolled
* component; otherwise, use the `value` property
* Sets the initial value. Use this for an uncontrolled component; otherwise,
* use the `value` property.
*/

@@ -87,3 +86,3 @@ defaultValue: PropTypes.string,

/**
* Hint text
* Additional hint text to display
*/

@@ -96,7 +95,7 @@ hint: PropTypes.node,

/**
* The label for the entire list of choices
* Label for the input
*/
label: PropTypes.node.isRequired,
/**
* Additional classes to be added to the `FormLabel`
* Additional classes to be added to the label
*/

@@ -112,4 +111,4 @@ labelClassName: PropTypes.string,

/**
* Optionally specify the number of visible text lines for the control. Only
* applicable if this is a multiline field
* Optionally specify the number of visible text lines for the field. Only
* applicable if this is a multiline field.
*/

@@ -125,4 +124,4 @@ rows: PropTypes.oneOfType([

/**
* Current value of the text field. Use this for a controlled component where
* you are maintaining its current state; otherwise, use the `defaultValue` property
* **Note**: Setting this prop will render a read-only field. If the field should be
* mutable, use `defaultValue`. Otherwise, set `onChange` or `disabled`.
*/

@@ -129,0 +128,0 @@ value: PropTypes.string

@@ -12,3 +12,3 @@ /* eslint-disable react/display-name */

label: 'Home',
url: 'http://example.com'
url: 'javascript:void(0);'
},

@@ -21,3 +21,3 @@ {

label: 'Team',
url: 'http://example.com#team'
url: 'javascript:void(0);'
},

@@ -27,3 +27,3 @@ {

label: 'Company',
url: 'http://example.com#company'
url: 'javascript:void(0);'
}

@@ -34,3 +34,3 @@ ]

label: 'Contact',
url: 'http://example.com#contact'
url: 'javascript:void(0);'
}

@@ -37,0 +37,0 @@ ]}

@@ -7,3 +7,3 @@ import PropTypes from 'prop-types';

/**
* The `VerticalNav` React component accepts list items as a JSON object and
* A `VerticalNav` component accepts list items as a JSON object and
* includes additional functionality like collapsible nested menus.

@@ -10,0 +10,0 @@ */

@@ -116,14 +116,14 @@ import {mount, shallow} from 'enzyme';

expect(
parentWrapper.find('.ds-c-vertical-nav__link').first()
.hasClass('ds-c-vertical-nav__link--current')
parentWrapper.find('.ds-c-vertical-nav__label').first()
.hasClass('ds-c-vertical-nav__label--current')
).toBe(true);
expect(
childWrapper.find('.ds-c-vertical-nav__link').first()
.hasClass('ds-c-vertical-nav__link--current')
childWrapper.find('.ds-c-vertical-nav__label').first()
.hasClass('ds-c-vertical-nav__label--current')
).toBe(true);
expect(
grandchild1Wrapper.find('.ds-c-vertical-nav__link').first()
.hasClass('ds-c-vertical-nav__link--current')
grandchild1Wrapper.find('.ds-c-vertical-nav__label').first()
.hasClass('ds-c-vertical-nav__label--current')
).toBe(true);

@@ -133,11 +133,11 @@

expect(
grandchild2Wrapper.find('.ds-c-vertical-nav__link').first()
.hasClass('ds-c-vertical-nav__link--current')
grandchild2Wrapper.find('.ds-c-vertical-nav__label').first()
.hasClass('ds-c-vertical-nav__label--current')
).toBe(false);
expect(
fooWrapper.find('.ds-c-vertical-nav__link').first()
.hasClass('ds-c-vertical-nav__link--current')
fooWrapper.find('.ds-c-vertical-nav__label').first()
.hasClass('ds-c-vertical-nav__label--current')
).toBe(false);
});
});
import PropTypes from 'prop-types';
import React from 'react';
import VerticalNav from './VerticalNav';
import VerticalNavItemLabel from './VerticalNavItemLabel';
import classNames from 'classnames';

@@ -10,10 +11,6 @@ import uniqueId from 'lodash.uniqueid';

super(props);
this.handleLinkClick = this.handleLinkClick.bind(this);
this.handleToggleClick = this.handleToggleClick.bind(this);
this.handleLabelClick = this.handleLabelClick.bind(this);
this.id = this.props.id || uniqueId('VerticalNavItem_');
this.subnavId = `${this.id}__subnav`;
this.state = {
collapsed: this.props.defaultCollapsed
};
this.state = { collapsed: this.props.defaultCollapsed };
}

@@ -27,3 +24,21 @@

handleLinkClick(evt) {
/**
* Called when VerticalNavItemLabel is clicked. Since the "label" could be
* a link, subnav toggle button, or plain text, we use this method to
* determine what action to take and which event to actually fire.
* @param {Object} SyntheticEvent
*/
handleLabelClick(evt) {
if (this.hasSubnav()) {
return this.handleToggleClick();
}
return this.handleClick(evt);
}
/**
* Note: This event handler will only get called when the VerticalNavItemLabel
* is a link or plain text
*/
handleClick(evt) {
if (this.props.onClick) {

@@ -43,3 +58,3 @@ this.props.onClick(

hasSubnav() {
return this.props.items && this.props.items.length;
return Boolean(this.props.items && this.props.items.length > 0);
}

@@ -49,2 +64,3 @@

* Check if this item is selected or if it is a parent of a selected item
* @return {Boolean}
*/

@@ -57,2 +73,4 @@ isSelected() {

}
return false;
}

@@ -63,2 +81,3 @@

* @param {Array} children - The nested items
* @return {Boolean}
*/

@@ -78,19 +97,14 @@ childIsSelected(children) {

renderSubnavToggle() {
if (this.hasSubnav()) {
const label = this.state.collapsed
? this.props.ariaCollapsedStateButtonLabel
: this.props.ariaExpandedStateButtonLabel;
subnavItems() {
if (this.props.url) {
// Since the VerticalNavItemLabel will just toggle the subnav, we
// add a link to the top of the subnav for this item. Otherwise there
// wouldn't be a way to actually visit its URL
const item = Object.assign({}, this.props);
delete item.items;
return (
<button
aria-controls={this.subnavId}
aria-expanded={!this.state.collapsed}
className='ds-c-vertical-nav__subnav-toggle'
onClick={this.handleToggleClick}
>
{label}
</button>
);
return [item].concat(this.props.items);
}
return this.props.items;
}

@@ -105,3 +119,3 @@

id={this.subnavId}
items={this.props.items}
items={this.subnavItems()}
nested

@@ -115,21 +129,16 @@ />

const classes = classNames('ds-c-vertical-nav__item', this.props.className);
const LinkComponent = this.props.url ? 'a' : 'div';
const linkProps = {
className: classNames(
'ds-c-vertical-nav__link',
{
'ds-c-vertical-nav__link--current': this.isSelected(),
'ds-c-vertical-nav__link--parent': this.hasSubnav()
}
),
href: this.props.url ? this.props.url : undefined,
onClick: this.props.onClick ? this.handleLinkClick : undefined
};
return (
<li className={classes}>
<LinkComponent {...linkProps}>
{this.props.label}
</LinkComponent>
{this.renderSubnavToggle()}
<VerticalNavItemLabel
ariaCollapsedStateButtonLabel={this.props.ariaCollapsedStateButtonLabel}
ariaExpandedStateButtonLabel={this.props.ariaExpandedStateButtonLabel}
collapsed={this.state.collapsed}
label={this.props.label}
hasSubnav={this.hasSubnav()}
onClick={this.handleLabelClick}
selected={this.isSelected()}
subnavId={this.subnavId}
url={this.props.url}
/>
{this.renderSubnav()}

@@ -142,2 +151,5 @@ </li>

VerticalNavItem.defaultProps = {
// Unfortunately, we're defining these default ARIA pros here and in
// VerticalNavItemLabel. We define them here so they show in the docs.
// TODO(sawyer): Update react-docgen so we don't have to do this
ariaCollapsedStateButtonLabel: 'Expand sub-navigation',

@@ -168,3 +180,3 @@ ariaExpandedStateButtonLabel: 'Collapse sub-navigation',

/**
* Called when the item is clicked, with the following arguments:
* Called when the link is clicked, with the following arguments:
* [`SyntheticEvent`](https://facebook.github.io/react/docs/events.html),

@@ -171,0 +183,0 @@ * `id`, `url`.

@@ -23,40 +23,12 @@ import React from 'react';

expect(wrapper.hasClass('ds-c-vertical-nav__item')).toBe(true);
expect(wrapper.text()).toBe(data.props.label);
});
it('is not a link', () => {
it('renders VerticalNavItemLabel', () => {
const data = shallowRender();
const wrapper = data.wrapper;
const link = wrapper.find('.ds-c-vertical-nav__link').first();
const label = data.wrapper.find('VerticalNavItemLabel').first();
expect(link.is('div')).toBe(true);
expect(link.prop('href')).toBeUndefined();
expect(link.hasClass('ds-c-vertical-nav__link--current')).toBe(false);
expect(label.prop('collapsed')).toBe(data.wrapper.state('collapsed'));
expect(label.prop('label')).toBe(data.props.label);
});
it('is a link', () => {
const data = shallowRender({ url: '/bar' });
const wrapper = data.wrapper;
const link = wrapper.find('.ds-c-vertical-nav__link').first();
expect(link.is('a')).toBe(true);
expect(link.prop('href')).toBe(data.props.url);
});
it('accepts a node as a label', () => {
const wrapper = shallowRender({
label: <strong>Foo</strong>
}).wrapper;
const link = wrapper.find('.ds-c-vertical-nav__link').first();
expect(link.html()).toMatch(/<strong>/);
});
it('is selected', () => {
const data = shallowRender({ selected: true });
const link = data.wrapper.find('.ds-c-vertical-nav__link').first();
expect(link.hasClass('ds-c-vertical-nav__link--current')).toBe(true);
});
it('has additional class names', () => {

@@ -69,16 +41,2 @@ const data = shallowRender({ className: 'bar' });

it('calls onClick', () => {
const data = shallowRender({
id: 'bar',
onClick: jest.fn(),
url: '/bar'
});
const link = data.wrapper.find('.ds-c-vertical-nav__link').first();
link.simulate('click');
expect(data.props.onClick.mock.calls.length).toBe(1);
expect(data.props.onClick.mock.calls[0][1]).toBe(data.props.id);
expect(data.props.onClick.mock.calls[0][2]).toBe(data.props.url);
});
it('calls onSubnavToggle', () => {

@@ -90,2 +48,3 @@ const data = shallowRender({

// Collapsed state changes, triggering the event!
data.wrapper.setState({ collapsed: true });

@@ -101,3 +60,41 @@

describe('with nested menu', () => {
describe('without subnav', () => {
it('is not selected', () => {
const data = shallowRender();
expect(data.wrapper.find('VerticalNavItemLabel').prop('selected'))
.toBe(false);
});
it('is selected', () => {
const data = shallowRender({ selected: true });
expect(data.wrapper.find('VerticalNavItemLabel').prop('selected'))
.toBe(true);
});
it('has no subnav', () => {
const data = shallowRender();
const label = data.wrapper.find('VerticalNavItemLabel').first();
expect(label.prop('hasSubnav')).toBe(false);
expect(data.wrapper.find('VerticalNav').length).toBe(0);
});
it('calls onClick', () => {
const data = shallowRender({
id: 'bar',
onClick: jest.fn(),
url: '/bar'
});
data.wrapper.find('VerticalNavItemLabel').first().simulate('click');
expect(data.props.onClick.mock.calls.length).toBe(1);
expect(data.props.onClick.mock.calls[0][1]).toBe(data.props.id);
expect(data.props.onClick.mock.calls[0][2]).toBe(data.props.url);
});
});
describe('with subnav', () => {
let props;

@@ -118,23 +115,31 @@

it('renders subnavs', () => {
it('has subnav', () => {
const data = shallowRender(props);
const label = data.wrapper.find('VerticalNavItemLabel').first();
const subnav = data.wrapper.find('VerticalNav').first();
expect(data.wrapper.render().find('ul').length)
.toBe(2);
expect(data.wrapper.find('VerticalNav').first().prop('collapsed'))
expect(label.prop('hasSubnav')).toBe(true);
expect(data.wrapper.render().find('ul').length).toBe(2);
expect(subnav.prop('collapsed')).toBe(false);
expect(subnav.prop('id')).not.toBeUndefined();
expect(subnav.prop('nested')).toBe(true);
});
it('is not selected', () => {
const data = shallowRender(props);
expect(data.wrapper.find('VerticalNavItemLabel').prop('selected'))
.toBe(false);
expect(data.wrapper.find('VerticalNav').first().prop('id'))
.not.toBeUndefined();
});
it('renders toggle button', () => {
it('is selected', () => {
props._selectedId = 'selected-child';
props.items[0].id = 'selected-child';
const data = shallowRender(props);
const button = data.wrapper.find('.ds-c-vertical-nav__subnav-toggle');
const subnavId = data.wrapper.find('VerticalNav').prop('id');
expect(button.prop('aria-controls')).toBe(subnavId);
expect(button.prop('aria-expanded')).toBe(true);
expect(data.wrapper.find('VerticalNavItemLabel').prop('selected'))
.toBe(true);
});
it('is collapsed', () => {
it('has collapsed subnav', () => {
props.defaultCollapsed = true;

@@ -148,23 +153,59 @@ const data = shallowRender(props);

it('toggles collapsed state', () => {
props.ariaExpandedStateButtonLabel = 'Collapse me';
props.ariaCollapsedStateButtonLabel = 'Expand me';
props.onClick = jest.fn();
const data = shallowRender(props);
let button = data.wrapper.find('.ds-c-vertical-nav__subnav-toggle');
const label = data.wrapper.find('VerticalNavItemLabel').first();
expect(data.wrapper.find('VerticalNav').first().prop('collapsed'))
.toBe(false);
expect(button.text())
.toBe(data.props.ariaExpandedStateButtonLabel);
button.simulate('click');
// Get updated render...
label.simulate('click');
data.wrapper.update();
button = data.wrapper.find('.ds-c-vertical-nav__subnav-toggle');
expect(data.wrapper.find('VerticalNav').first().prop('collapsed'))
.toBe(true);
expect(button.text())
.toBe(data.props.ariaCollapsedStateButtonLabel);
});
it('does not add top-level link to top of subnav', () => {
const data = shallowRender(props);
const subnav = data.wrapper.find('VerticalNav').first().shallow();
const firstSubnavItem = subnav.find('VerticalNavItem').first();
expect(firstSubnavItem.prop('label')).toBe(data.props.items[0].label);
});
describe('with url', () => {
beforeEach(() => {
props.url = '/foo';
});
it('adds top-level link to top of subnav', () => {
props.id = 'foo';
const data = shallowRender(props);
const subnav = data.wrapper.find('VerticalNav').first().shallow();
const firstSubnavItem = subnav.find('VerticalNavItem').first();
expect(firstSubnavItem.prop('id'))
.toBe(data.props.id);
expect(firstSubnavItem.prop('items'))
.toBeUndefined();
expect(firstSubnavItem.prop('label'))
.toBe(data.props.label);
expect(firstSubnavItem.prop('url'))
.toBe(data.props.url);
});
it('calls onSubnavToggle rather than onClick', () => {
props.onClick = jest.fn();
props.onSubnavToggle = jest.fn();
const data = shallowRender(props);
const label = data.wrapper.find('VerticalNavItemLabel').first();
label.simulate('click');
expect(data.props.onClick.mock.calls.length).toBe(0);
expect(data.props.onSubnavToggle.mock.calls.length).toBe(1);
});
});
});
});
'use strict';
export * from './components';
export * from './components'; // eslint-disable-line import/export

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

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

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

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

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