@primer/components 32.0.1-rc.44e3df9b → 32.1.0-rc.6f5d2b00
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/browser.esm.js +7 -1
- package/dist/browser.esm.js.map +1 -1
- package/dist/browser.umd.js +7 -1
- package/dist/browser.umd.js.map +1 -1
- package/docs/content/Checkbox.md +118 -0
- package/docs/src/@primer/gatsby-theme-doctocat/nav.yml +2 -0
- package/lib/Checkbox.d.ts +29 -0
- package/lib/Checkbox.js +64 -0
- package/lib/Overlay.d.ts +5 -3
- package/lib/__tests__/Checkbox.test.d.ts +2 -0
- package/lib/__tests__/Checkbox.test.js +189 -0
- package/lib/__tests__/Overlay.types.test.d.ts +3 -0
- package/lib/__tests__/Overlay.types.test.js +38 -0
- package/lib/__tests__/SelectPanel.types.test.d.ts +3 -0
- package/lib/__tests__/SelectPanel.types.test.js +44 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +8 -0
- package/lib/stories/Checkbox.stories.js +227 -0
- package/lib-esm/Checkbox.d.ts +29 -0
- package/lib-esm/Checkbox.js +44 -0
- package/lib-esm/Overlay.d.ts +5 -3
- package/lib-esm/__tests__/Checkbox.test.d.ts +2 -0
- package/lib-esm/__tests__/Checkbox.test.js +169 -0
- package/lib-esm/__tests__/Overlay.types.test.d.ts +3 -0
- package/lib-esm/__tests__/Overlay.types.test.js +29 -0
- package/lib-esm/__tests__/SelectPanel.types.test.d.ts +3 -0
- package/lib-esm/__tests__/SelectPanel.types.test.js +29 -0
- package/lib-esm/index.d.ts +2 -0
- package/lib-esm/index.js +1 -0
- package/lib-esm/stories/Checkbox.stories.js +197 -0
- package/package.json +1 -1
- package/src/Checkbox.tsx +75 -0
- package/src/Overlay.tsx +7 -4
- package/src/__tests__/Checkbox.test.tsx +155 -0
- package/src/__tests__/Overlay.types.test.tsx +15 -0
- package/src/__tests__/SelectPanel.types.test.tsx +31 -0
- package/src/__tests__/__snapshots__/Checkbox.test.tsx.snap +16 -0
- package/src/index.ts +3 -0
- package/src/stories/Checkbox.stories.tsx +164 -0
- package/stats.html +1 -1
@@ -0,0 +1,227 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
4
|
+
value: true
|
5
|
+
});
|
6
|
+
exports.Indeterminate = exports.Uncontrolled = exports.Default = exports.default = void 0;
|
7
|
+
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
9
|
+
|
10
|
+
var _styledComponents = _interopRequireDefault(require("styled-components"));
|
11
|
+
|
12
|
+
var _2 = require("..");
|
13
|
+
|
14
|
+
var _addonActions = require("@storybook/addon-actions");
|
15
|
+
|
16
|
+
var _constants = require("../constants");
|
17
|
+
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
19
|
+
|
20
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
21
|
+
|
22
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
23
|
+
|
24
|
+
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
25
|
+
|
26
|
+
var _default = {
|
27
|
+
title: 'Forms/Checkbox',
|
28
|
+
component: _2.Checkbox,
|
29
|
+
decorators: [Story => {
|
30
|
+
return /*#__PURE__*/_react.default.createElement(_2.ThemeProvider, null, /*#__PURE__*/_react.default.createElement(_2.BaseStyles, null, /*#__PURE__*/_react.default.createElement(_2.Box, {
|
31
|
+
paddingTop: 5
|
32
|
+
}, Story())));
|
33
|
+
}],
|
34
|
+
argTypes: {
|
35
|
+
sx: {
|
36
|
+
table: {
|
37
|
+
disable: true
|
38
|
+
}
|
39
|
+
},
|
40
|
+
disabled: {
|
41
|
+
name: 'Disabled',
|
42
|
+
defaultValue: false,
|
43
|
+
control: {
|
44
|
+
type: 'boolean'
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
};
|
49
|
+
exports.default = _default;
|
50
|
+
|
51
|
+
const StyledLabel = _styledComponents.default.label.withConfig({
|
52
|
+
displayName: "Checkboxstories__StyledLabel",
|
53
|
+
componentId: "sdupvr-0"
|
54
|
+
})(["user-select:none;font-weight:600;font-size:14px;line-height:18px;margin-left:16px;", ""], _constants.COMMON);
|
55
|
+
|
56
|
+
const StyledSubLabel = (0, _styledComponents.default)(_2.Text).withConfig({
|
57
|
+
displayName: "Checkboxstories__StyledSubLabel",
|
58
|
+
componentId: "sdupvr-1"
|
59
|
+
})(["color:", ";font-size:13px;", ""], (0, _constants.get)('colors.fg.muted'), _constants.COMMON);
|
60
|
+
|
61
|
+
const Default = args => {
|
62
|
+
const [isChecked, setChecked] = (0, _react.useState)(false);
|
63
|
+
|
64
|
+
const handleChange = event => {
|
65
|
+
setChecked(event.target.checked);
|
66
|
+
(0, _addonActions.action)('Change event triggered');
|
67
|
+
};
|
68
|
+
|
69
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_2.Box, {
|
70
|
+
as: "form",
|
71
|
+
sx: {
|
72
|
+
p: 3,
|
73
|
+
display: 'flex',
|
74
|
+
alignItems: 'flex-start'
|
75
|
+
}
|
76
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Checkbox, _extends({
|
77
|
+
id: "controlled-checkbox",
|
78
|
+
onChange: handleChange,
|
79
|
+
checked: isChecked
|
80
|
+
}, args)), /*#__PURE__*/_react.default.createElement(StyledLabel, {
|
81
|
+
htmlFor: "controlled-checkbox"
|
82
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Text, {
|
83
|
+
sx: {
|
84
|
+
display: 'block'
|
85
|
+
}
|
86
|
+
}, "Default checkbox"), /*#__PURE__*/_react.default.createElement(StyledSubLabel, null, "controlled"))), /*#__PURE__*/_react.default.createElement(_2.Box, {
|
87
|
+
as: "form",
|
88
|
+
sx: {
|
89
|
+
p: 3,
|
90
|
+
display: 'flex',
|
91
|
+
alignItems: 'flex-start'
|
92
|
+
}
|
93
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Checkbox, _extends({
|
94
|
+
id: "always-checked-checkbox",
|
95
|
+
checked: true
|
96
|
+
}, args)), /*#__PURE__*/_react.default.createElement(StyledLabel, {
|
97
|
+
htmlFor: "always-checked-checkbox"
|
98
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Text, {
|
99
|
+
sx: {
|
100
|
+
display: 'block'
|
101
|
+
}
|
102
|
+
}, "Always checked"), /*#__PURE__*/_react.default.createElement(StyledSubLabel, null, "checked=\"true\""))), /*#__PURE__*/_react.default.createElement(_2.Box, {
|
103
|
+
as: "form",
|
104
|
+
sx: {
|
105
|
+
p: 3,
|
106
|
+
display: 'flex',
|
107
|
+
alignItems: 'flex-start'
|
108
|
+
}
|
109
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Checkbox, _extends({
|
110
|
+
id: "always-unchecked-checkbox",
|
111
|
+
checked: false
|
112
|
+
}, args)), /*#__PURE__*/_react.default.createElement(StyledLabel, {
|
113
|
+
htmlFor: "always-unchecked-checkbox"
|
114
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Text, {
|
115
|
+
sx: {
|
116
|
+
display: 'block'
|
117
|
+
}
|
118
|
+
}, "Always unchecked"), /*#__PURE__*/_react.default.createElement(StyledSubLabel, null, "checked=\"false\""))), /*#__PURE__*/_react.default.createElement(_2.Box, {
|
119
|
+
as: "form",
|
120
|
+
sx: {
|
121
|
+
p: 3,
|
122
|
+
display: 'flex',
|
123
|
+
alignItems: 'flex-start'
|
124
|
+
}
|
125
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Checkbox, {
|
126
|
+
id: "disabled-checkbox",
|
127
|
+
disabled: true,
|
128
|
+
checked: false
|
129
|
+
}), /*#__PURE__*/_react.default.createElement(StyledLabel, {
|
130
|
+
htmlFor: "disabled-checkbox"
|
131
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Text, {
|
132
|
+
sx: {
|
133
|
+
display: 'block'
|
134
|
+
}
|
135
|
+
}, "Inactive"), /*#__PURE__*/_react.default.createElement(StyledSubLabel, null, "disabled=\"true\""))));
|
136
|
+
};
|
137
|
+
|
138
|
+
exports.Default = Default;
|
139
|
+
|
140
|
+
const Uncontrolled = args => {
|
141
|
+
const checkboxRef = (0, _react.useRef)(null);
|
142
|
+
(0, _react.useLayoutEffect)(() => {
|
143
|
+
if (checkboxRef.current) {
|
144
|
+
checkboxRef.current.checked = true;
|
145
|
+
}
|
146
|
+
}, []);
|
147
|
+
return /*#__PURE__*/_react.default.createElement(_2.Box, {
|
148
|
+
as: "form",
|
149
|
+
sx: {
|
150
|
+
p: 3,
|
151
|
+
display: 'flex',
|
152
|
+
alignItems: 'flex-start'
|
153
|
+
}
|
154
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Checkbox, _extends({
|
155
|
+
id: "uncontrolled-checkbox",
|
156
|
+
ref: checkboxRef
|
157
|
+
}, args)), /*#__PURE__*/_react.default.createElement(StyledLabel, {
|
158
|
+
htmlFor: "uncontrolled-checkbox"
|
159
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Text, {
|
160
|
+
sx: {
|
161
|
+
display: 'block'
|
162
|
+
}
|
163
|
+
}, "Uncontrolled checkbox"), /*#__PURE__*/_react.default.createElement(StyledSubLabel, null, "Checked by default")));
|
164
|
+
};
|
165
|
+
|
166
|
+
exports.Uncontrolled = Uncontrolled;
|
167
|
+
Uncontrolled.displayName = "Uncontrolled";
|
168
|
+
|
169
|
+
const Indeterminate = args => {
|
170
|
+
const [checkboxes, setCheckboxes] = (0, _react.useState)([false, false, false, false]);
|
171
|
+
|
172
|
+
const handleChange = (_, index) => {
|
173
|
+
const newCheckboxes = [...checkboxes];
|
174
|
+
newCheckboxes[index] = !checkboxes[index];
|
175
|
+
setCheckboxes(newCheckboxes);
|
176
|
+
};
|
177
|
+
|
178
|
+
const handleIndeterminateChange = () => {
|
179
|
+
if (checkboxes.every(checkbox => checkbox)) {
|
180
|
+
return setCheckboxes(checkboxes.map(() => false));
|
181
|
+
}
|
182
|
+
|
183
|
+
const newCheckboxes = checkboxes.map(() => true);
|
184
|
+
setCheckboxes(newCheckboxes);
|
185
|
+
};
|
186
|
+
|
187
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_2.Box, {
|
188
|
+
as: "form",
|
189
|
+
sx: {
|
190
|
+
p: 3,
|
191
|
+
display: 'flex',
|
192
|
+
alignItems: 'flex-start'
|
193
|
+
}
|
194
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Checkbox, {
|
195
|
+
id: "indeterminate-checkbox",
|
196
|
+
checked: checkboxes.every(Boolean),
|
197
|
+
onChange: handleIndeterminateChange,
|
198
|
+
indeterminate: !checkboxes.every(Boolean)
|
199
|
+
}), /*#__PURE__*/_react.default.createElement(StyledLabel, {
|
200
|
+
htmlFor: "controlled-checkbox"
|
201
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Text, {
|
202
|
+
sx: {
|
203
|
+
display: 'block'
|
204
|
+
}
|
205
|
+
}, "Default checkbox"), /*#__PURE__*/_react.default.createElement(StyledSubLabel, null, "controlled"))), checkboxes.map((field, index) => /*#__PURE__*/_react.default.createElement(_2.Box, {
|
206
|
+
key: `sub-checkbox-${index}`,
|
207
|
+
as: "form",
|
208
|
+
sx: {
|
209
|
+
p: 1,
|
210
|
+
pl: 7,
|
211
|
+
display: 'flex',
|
212
|
+
alignItems: 'flex-start'
|
213
|
+
}
|
214
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Checkbox, _extends({
|
215
|
+
id: `sub-checkbox-${index}`,
|
216
|
+
checked: checkboxes[index],
|
217
|
+
onChange: event => handleChange(event, index)
|
218
|
+
}, args)), /*#__PURE__*/_react.default.createElement(StyledLabel, {
|
219
|
+
htmlFor: `sub-checkbox-${index}`
|
220
|
+
}, /*#__PURE__*/_react.default.createElement(_2.Text, {
|
221
|
+
sx: {
|
222
|
+
display: 'block'
|
223
|
+
}
|
224
|
+
}, "Checkbox ", index + 1)))));
|
225
|
+
};
|
226
|
+
|
227
|
+
exports.Indeterminate = Indeterminate;
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import React, { InputHTMLAttributes } from 'react';
|
2
|
+
import { SxProp } from './sx';
|
3
|
+
export declare type CheckboxProps = {
|
4
|
+
/**
|
5
|
+
* Apply indeterminate visual appearance to the checkbox
|
6
|
+
*/
|
7
|
+
indeterminate?: boolean;
|
8
|
+
/**
|
9
|
+
* Apply inactive visual appearance to the checkbox
|
10
|
+
*/
|
11
|
+
disabled?: boolean;
|
12
|
+
/**
|
13
|
+
* Forward a ref to the underlying input element
|
14
|
+
*/
|
15
|
+
ref?: React.RefObject<HTMLInputElement>;
|
16
|
+
/**
|
17
|
+
* Indicates whether the checkbox must be checked
|
18
|
+
*/
|
19
|
+
required?: boolean;
|
20
|
+
/**
|
21
|
+
* Indicates whether the checkbox validation state
|
22
|
+
*/
|
23
|
+
validationStatus?: 'error' | 'success';
|
24
|
+
} & InputHTMLAttributes<HTMLInputElement> & SxProp;
|
25
|
+
/**
|
26
|
+
* An accessible, native checkbox component
|
27
|
+
*/
|
28
|
+
declare const Checkbox: React.ForwardRefExoticComponent<Pick<CheckboxProps, "sx" | keyof React.InputHTMLAttributes<HTMLInputElement> | "indeterminate" | "validationStatus"> & React.RefAttributes<HTMLInputElement>>;
|
29
|
+
export default Checkbox;
|
@@ -0,0 +1,44 @@
|
|
1
|
+
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
|
+
|
3
|
+
import styled from 'styled-components';
|
4
|
+
import { useProvidedRefOrCreate } from './hooks';
|
5
|
+
import React, { useLayoutEffect } from 'react';
|
6
|
+
import sx from './sx';
|
7
|
+
const StyledCheckbox = styled.input.withConfig({
|
8
|
+
displayName: "Checkbox__StyledCheckbox",
|
9
|
+
componentId: "i51804-0"
|
10
|
+
})(["cursor:pointer;", " ", ""], props => props.disabled && `cursor: not-allowed;`, sx);
|
11
|
+
/**
|
12
|
+
* An accessible, native checkbox component
|
13
|
+
*/
|
14
|
+
|
15
|
+
const Checkbox = /*#__PURE__*/React.forwardRef(({
|
16
|
+
checked,
|
17
|
+
indeterminate,
|
18
|
+
disabled,
|
19
|
+
sx: sxProp,
|
20
|
+
required,
|
21
|
+
validationStatus,
|
22
|
+
...rest
|
23
|
+
}, ref) => {
|
24
|
+
const checkboxRef = useProvidedRefOrCreate(ref);
|
25
|
+
useLayoutEffect(() => {
|
26
|
+
if (checkboxRef.current) {
|
27
|
+
checkboxRef.current.indeterminate = indeterminate || false;
|
28
|
+
}
|
29
|
+
}, [indeterminate, checked, checkboxRef]);
|
30
|
+
return /*#__PURE__*/React.createElement(StyledCheckbox, _extends({
|
31
|
+
type: "checkbox",
|
32
|
+
disabled: disabled,
|
33
|
+
"aria-disabled": disabled ? 'true' : 'false',
|
34
|
+
ref: ref || checkboxRef,
|
35
|
+
checked: indeterminate ? false : checked,
|
36
|
+
"aria-checked": indeterminate ? 'mixed' : checked ? 'true' : 'false',
|
37
|
+
sx: sxProp,
|
38
|
+
required: required,
|
39
|
+
"aria-required": required ? 'true' : 'false',
|
40
|
+
"aria-invalid": validationStatus === 'error' ? 'true' : 'false'
|
41
|
+
}, rest));
|
42
|
+
});
|
43
|
+
Checkbox.displayName = 'Checkbox';
|
44
|
+
export default Checkbox;
|
package/lib-esm/Overlay.d.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { ComponentPropsWithRef } from 'react';
|
2
2
|
import { AriaRole, Merge } from './utils/types';
|
3
3
|
import { TouchOrMouseEvent } from './hooks';
|
4
4
|
import { SxProp } from './sx';
|
5
5
|
import { AnchorSide } from './behaviors/anchoredPosition';
|
6
|
+
import { ForwardRefComponent as PolymorphicForwardRefComponent } from '@radix-ui/react-polymorphic';
|
6
7
|
declare type StyledOverlayProps = {
|
7
8
|
width?: keyof typeof widthMap;
|
8
9
|
height?: keyof typeof heightMap;
|
@@ -42,7 +43,7 @@ declare type BaseOverlayProps = {
|
|
42
43
|
role?: AriaRole;
|
43
44
|
children?: React.ReactNode;
|
44
45
|
};
|
45
|
-
|
46
|
+
declare type OwnOverlayProps = Merge<StyledOverlayProps, BaseOverlayProps>;
|
46
47
|
/**
|
47
48
|
* An `Overlay` is a flexible floating surface, used to display transient content such as menus,
|
48
49
|
* selection options, dialogs, and more. Overlays use shadows to express elevation. The `Overlay`
|
@@ -60,5 +61,6 @@ export declare type OverlayProps = Merge<StyledOverlayProps, BaseOverlayProps>;
|
|
60
61
|
* @param left Optional. Horizontal position of the overlay, relative to its closest positioned ancestor (often its `Portal`).
|
61
62
|
* @param portalContainerName Optional. The name of the portal container to render the Overlay into.
|
62
63
|
*/
|
63
|
-
declare const Overlay:
|
64
|
+
declare const Overlay: PolymorphicForwardRefComponent<"div", OwnOverlayProps>;
|
65
|
+
export declare type OverlayProps = ComponentPropsWithRef<typeof Overlay>;
|
64
66
|
export default Overlay;
|
@@ -0,0 +1,169 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { Checkbox } from '..';
|
3
|
+
import { behavesAsComponent, checkExports } from '../utils/testing';
|
4
|
+
import { render, cleanup } from '@testing-library/react';
|
5
|
+
import { toHaveNoViolations } from 'jest-axe';
|
6
|
+
import 'babel-polyfill';
|
7
|
+
import '@testing-library/jest-dom';
|
8
|
+
import userEvent from '@testing-library/user-event';
|
9
|
+
expect.extend(toHaveNoViolations);
|
10
|
+
describe('Checkbox', () => {
|
11
|
+
beforeEach(() => {
|
12
|
+
jest.resetAllMocks();
|
13
|
+
cleanup();
|
14
|
+
});
|
15
|
+
behavesAsComponent({
|
16
|
+
Component: Checkbox
|
17
|
+
});
|
18
|
+
checkExports('Checkbox', {
|
19
|
+
default: Checkbox
|
20
|
+
});
|
21
|
+
it('renders a valid checkbox input', () => {
|
22
|
+
const {
|
23
|
+
getByRole
|
24
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, null));
|
25
|
+
const checkbox = getByRole('checkbox');
|
26
|
+
expect(checkbox).toBeDefined();
|
27
|
+
});
|
28
|
+
it('renders an unchecked checkbox by default', () => {
|
29
|
+
const {
|
30
|
+
getByRole
|
31
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, null));
|
32
|
+
const checkbox = getByRole('checkbox');
|
33
|
+
expect(checkbox.checked).toEqual(false);
|
34
|
+
});
|
35
|
+
it('renders an active checkbox when checked attribute is passed', () => {
|
36
|
+
const handleChange = jest.fn();
|
37
|
+
const {
|
38
|
+
getByRole
|
39
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, {
|
40
|
+
checked: true,
|
41
|
+
onChange: handleChange
|
42
|
+
}));
|
43
|
+
const checkbox = getByRole('checkbox');
|
44
|
+
expect(checkbox.checked).toEqual(true);
|
45
|
+
});
|
46
|
+
it('accepts a change handler that can alter the checkbox state', () => {
|
47
|
+
const handleChange = jest.fn();
|
48
|
+
const {
|
49
|
+
getByRole
|
50
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, {
|
51
|
+
onChange: handleChange
|
52
|
+
}));
|
53
|
+
const checkbox = getByRole('checkbox');
|
54
|
+
expect(checkbox.checked).toEqual(false);
|
55
|
+
userEvent.click(checkbox);
|
56
|
+
expect(handleChange).toHaveBeenCalled();
|
57
|
+
expect(checkbox.checked).toEqual(true);
|
58
|
+
userEvent.click(checkbox);
|
59
|
+
expect(handleChange).toHaveBeenCalled();
|
60
|
+
expect(checkbox.checked).toEqual(false);
|
61
|
+
});
|
62
|
+
it('renders an indeterminate prop correctly', () => {
|
63
|
+
const handleChange = jest.fn();
|
64
|
+
const {
|
65
|
+
getByRole
|
66
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, {
|
67
|
+
indeterminate: true,
|
68
|
+
checked: true,
|
69
|
+
onChange: handleChange
|
70
|
+
}));
|
71
|
+
const checkbox = getByRole('checkbox');
|
72
|
+
expect(checkbox.indeterminate).toEqual(true);
|
73
|
+
expect(checkbox.checked).toEqual(false);
|
74
|
+
});
|
75
|
+
it('renders an inactive checkbox state correctly', () => {
|
76
|
+
const handleChange = jest.fn();
|
77
|
+
const {
|
78
|
+
getByRole,
|
79
|
+
rerender
|
80
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, {
|
81
|
+
disabled: true,
|
82
|
+
onChange: handleChange
|
83
|
+
}));
|
84
|
+
const checkbox = getByRole('checkbox');
|
85
|
+
expect(checkbox.disabled).toEqual(true);
|
86
|
+
expect(checkbox.checked).toEqual(false);
|
87
|
+
expect(checkbox).toHaveAttribute('aria-disabled', 'true');
|
88
|
+
userEvent.click(checkbox);
|
89
|
+
expect(checkbox.disabled).toEqual(true);
|
90
|
+
expect(checkbox.checked).toEqual(false);
|
91
|
+
expect(checkbox).toHaveAttribute('aria-disabled', 'true'); // remove disabled attribute and retest
|
92
|
+
|
93
|
+
rerender( /*#__PURE__*/React.createElement(Checkbox, {
|
94
|
+
onChange: handleChange
|
95
|
+
}));
|
96
|
+
expect(checkbox).toHaveAttribute('aria-disabled', 'false');
|
97
|
+
});
|
98
|
+
it('renders an uncontrolled component correctly', () => {
|
99
|
+
const {
|
100
|
+
getByRole
|
101
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, {
|
102
|
+
defaultChecked: true
|
103
|
+
}));
|
104
|
+
const checkbox = getByRole('checkbox');
|
105
|
+
expect(checkbox.checked).toEqual(true);
|
106
|
+
userEvent.click(checkbox);
|
107
|
+
expect(checkbox.checked).toEqual(false);
|
108
|
+
});
|
109
|
+
it('renders an aria-checked attribute correctly', () => {
|
110
|
+
const handleChange = jest.fn();
|
111
|
+
const {
|
112
|
+
getByRole,
|
113
|
+
rerender
|
114
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, {
|
115
|
+
checked: false,
|
116
|
+
onChange: handleChange
|
117
|
+
}));
|
118
|
+
const checkbox = getByRole('checkbox');
|
119
|
+
expect(checkbox).toHaveAttribute('aria-checked', 'false');
|
120
|
+
rerender( /*#__PURE__*/React.createElement(Checkbox, {
|
121
|
+
checked: true,
|
122
|
+
onChange: handleChange
|
123
|
+
}));
|
124
|
+
expect(checkbox).toHaveAttribute('aria-checked', 'true');
|
125
|
+
rerender( /*#__PURE__*/React.createElement(Checkbox, {
|
126
|
+
indeterminate: true,
|
127
|
+
checked: true,
|
128
|
+
onChange: handleChange
|
129
|
+
}));
|
130
|
+
expect(checkbox).toHaveAttribute('aria-checked', 'mixed');
|
131
|
+
});
|
132
|
+
it('renders an invalid aria state when validation prop indicates an error', () => {
|
133
|
+
const handleChange = jest.fn();
|
134
|
+
const {
|
135
|
+
getByRole,
|
136
|
+
rerender
|
137
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, {
|
138
|
+
onChange: handleChange
|
139
|
+
}));
|
140
|
+
const checkbox = getByRole('checkbox');
|
141
|
+
expect(checkbox).toHaveAttribute('aria-invalid', 'false');
|
142
|
+
rerender( /*#__PURE__*/React.createElement(Checkbox, {
|
143
|
+
onChange: handleChange,
|
144
|
+
validationStatus: "success"
|
145
|
+
}));
|
146
|
+
expect(checkbox).toHaveAttribute('aria-invalid', 'false');
|
147
|
+
rerender( /*#__PURE__*/React.createElement(Checkbox, {
|
148
|
+
onChange: handleChange,
|
149
|
+
validationStatus: "error"
|
150
|
+
}));
|
151
|
+
expect(checkbox).toHaveAttribute('aria-invalid', 'true');
|
152
|
+
});
|
153
|
+
it('renders an aria state indicating the field is required', () => {
|
154
|
+
const handleChange = jest.fn();
|
155
|
+
const {
|
156
|
+
getByRole,
|
157
|
+
rerender
|
158
|
+
} = render( /*#__PURE__*/React.createElement(Checkbox, {
|
159
|
+
onChange: handleChange
|
160
|
+
}));
|
161
|
+
const checkbox = getByRole('checkbox');
|
162
|
+
expect(checkbox).toHaveAttribute('aria-required', 'false');
|
163
|
+
rerender( /*#__PURE__*/React.createElement(Checkbox, {
|
164
|
+
onChange: handleChange,
|
165
|
+
required: true
|
166
|
+
}));
|
167
|
+
expect(checkbox).toHaveAttribute('aria-required', 'true');
|
168
|
+
});
|
169
|
+
});
|
@@ -1,3 +1,6 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
export declare function shouldAcceptCallWithNoProps(ref: React.RefObject<HTMLElement>): JSX.Element;
|
3
|
+
export declare function shouldAcceptCallWithDOMProps(ref: React.RefObject<HTMLElement>): JSX.Element;
|
4
|
+
export declare function shouldNotAcceptCallWithDOMPropsThatDontMatchElement(ref: React.RefObject<HTMLElement>): JSX.Element;
|
5
|
+
export declare function shouldAcceptCallWithAsAndDOMProps(ref: React.RefObject<HTMLElement>): JSX.Element;
|
3
6
|
export declare function shouldNotAcceptSystemProps(ref: React.RefObject<HTMLElement>): JSX.Element;
|
@@ -8,6 +8,35 @@ export function shouldAcceptCallWithNoProps(ref) {
|
|
8
8
|
});
|
9
9
|
}
|
10
10
|
shouldAcceptCallWithNoProps.displayName = "shouldAcceptCallWithNoProps";
|
11
|
+
export function shouldAcceptCallWithDOMProps(ref) {
|
12
|
+
return /*#__PURE__*/React.createElement(Overlay, {
|
13
|
+
returnFocusRef: ref,
|
14
|
+
onClickOutside: () => null,
|
15
|
+
onEscape: () => null,
|
16
|
+
onMouseDown: () => null
|
17
|
+
});
|
18
|
+
}
|
19
|
+
shouldAcceptCallWithDOMProps.displayName = "shouldAcceptCallWithDOMProps";
|
20
|
+
export function shouldNotAcceptCallWithDOMPropsThatDontMatchElement(ref) {
|
21
|
+
// @ts-expect-error href should not be allowed on a <div>
|
22
|
+
return /*#__PURE__*/React.createElement(Overlay, {
|
23
|
+
returnFocusRef: ref,
|
24
|
+
onClickOutside: () => null,
|
25
|
+
onEscape: () => null,
|
26
|
+
href: "//primer.style/"
|
27
|
+
});
|
28
|
+
}
|
29
|
+
shouldNotAcceptCallWithDOMPropsThatDontMatchElement.displayName = "shouldNotAcceptCallWithDOMPropsThatDontMatchElement";
|
30
|
+
export function shouldAcceptCallWithAsAndDOMProps(ref) {
|
31
|
+
return /*#__PURE__*/React.createElement(Overlay, {
|
32
|
+
as: "a",
|
33
|
+
returnFocusRef: ref,
|
34
|
+
onClickOutside: () => null,
|
35
|
+
onEscape: () => null,
|
36
|
+
href: "//primer.style/"
|
37
|
+
});
|
38
|
+
}
|
39
|
+
shouldAcceptCallWithAsAndDOMProps.displayName = "shouldAcceptCallWithAsAndDOMProps";
|
11
40
|
export function shouldNotAcceptSystemProps(ref) {
|
12
41
|
return /*#__PURE__*/React.createElement(Overlay, {
|
13
42
|
returnFocusRef: ref,
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { SelectPanel } from '../SelectPanel';
|
3
|
+
export function shouldAcceptCallWithNoProps() {
|
4
|
+
return /*#__PURE__*/React.createElement(SelectPanel, {
|
5
|
+
placeholderText: "",
|
6
|
+
open: false,
|
7
|
+
onOpenChange: () => null,
|
8
|
+
items: [],
|
9
|
+
selected: [],
|
10
|
+
onSelectedChange: () => null,
|
11
|
+
onFilterChange: () => null
|
12
|
+
});
|
13
|
+
}
|
14
|
+
shouldAcceptCallWithNoProps.displayName = "shouldAcceptCallWithNoProps";
|
15
|
+
export function shouldAcceptDOMPropsOnOverlay() {
|
16
|
+
return /*#__PURE__*/React.createElement(SelectPanel, {
|
17
|
+
placeholderText: "",
|
18
|
+
open: false,
|
19
|
+
onOpenChange: () => null,
|
20
|
+
items: [],
|
21
|
+
selected: [],
|
22
|
+
onSelectedChange: () => null,
|
23
|
+
onFilterChange: () => null,
|
24
|
+
overlayProps: {
|
25
|
+
onMouseDown: () => null
|
26
|
+
}
|
27
|
+
});
|
28
|
+
}
|
29
|
+
shouldAcceptDOMPropsOnOverlay.displayName = "shouldAcceptDOMPropsOnOverlay";
|
package/lib-esm/index.d.ts
CHANGED
@@ -115,4 +115,6 @@ export { default as Truncate } from './Truncate';
|
|
115
115
|
export type { TruncateProps } from './Truncate';
|
116
116
|
export { default as UnderlineNav } from './UnderlineNav';
|
117
117
|
export type { UnderlineNavProps, UnderlineNavLinkProps } from './UnderlineNav';
|
118
|
+
export { default as Checkbox } from './Checkbox';
|
119
|
+
export type { CheckboxProps } from './Checkbox';
|
118
120
|
export { SSRProvider, useSSRSafeId } from './utils/ssr';
|
package/lib-esm/index.js
CHANGED
@@ -70,4 +70,5 @@ export { default as Token, IssueLabelToken, AvatarToken } from './Token';
|
|
70
70
|
export { default as Tooltip } from './Tooltip';
|
71
71
|
export { default as Truncate } from './Truncate';
|
72
72
|
export { default as UnderlineNav } from './UnderlineNav';
|
73
|
+
export { default as Checkbox } from './Checkbox';
|
73
74
|
export { SSRProvider, useSSRSafeId } from './utils/ssr';
|