@pingux/astro 1.33.1-alpha.0 → 1.33.1-alpha.1

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.
@@ -20,7 +20,7 @@ var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/e
20
20
 
21
21
  var _react = _interopRequireWildcard(require("react"));
22
22
 
23
- var _themeUi = require("theme-ui");
23
+ var _CheckboxBase = _interopRequireDefault(require("./CheckboxBase"));
24
24
 
25
25
  var _react2 = require("@emotion/react");
26
26
 
@@ -35,12 +35,8 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
35
35
  * **Note: Requires a label. It's recommended to use `CheckboxField` for a complete solution.**
36
36
  */
37
37
  var Checkbox = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
38
- return (0, _react2.jsx)(_themeUi.Checkbox, (0, _extends2["default"])({
39
- ref: ref,
40
- __css: {
41
- top: 0,
42
- left: 0
43
- }
38
+ return (0, _react2.jsx)(_CheckboxBase["default"], (0, _extends2["default"])({
39
+ ref: ref
44
40
  }, props));
45
41
  });
46
42
  Checkbox.displayName = 'Checkbox';
@@ -32,5 +32,7 @@ test('default checkbox', function () {
32
32
  var input = _react2.screen.getByRole('checkbox');
33
33
 
34
34
  expect(input).toBeInstanceOf(HTMLInputElement);
35
- expect(input).toBeInTheDocument();
35
+ expect(input).toBeInTheDocument(); // Should be visually hidden
36
+
37
+ expect(input).not.toBeVisible();
36
38
  });
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
4
+
5
+ var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor");
6
+
7
+ var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
8
+
9
+ var _typeof = require("@babel/runtime-corejs3/helpers/typeof");
10
+
11
+ var _WeakMap = require("@babel/runtime-corejs3/core-js-stable/weak-map");
12
+
13
+ _Object$defineProperty(exports, "__esModule", {
14
+ value: true
15
+ });
16
+
17
+ exports["default"] = void 0;
18
+
19
+ var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));
20
+
21
+ var _react = _interopRequireWildcard(require("react"));
22
+
23
+ var _themeUi = require("theme-ui");
24
+
25
+ var _visuallyHidden = require("@react-aria/visually-hidden");
26
+
27
+ var _Box = _interopRequireDefault(require("../Box"));
28
+
29
+ var _react2 = require("@emotion/react");
30
+
31
+ function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
32
+
33
+ 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; }
34
+
35
+ /**
36
+ * Checkbox component from Theme UI, renders a visually hidden input + svg icons for the
37
+ * checked and unchecked states.
38
+ */
39
+ var DefaultCheckbox = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
40
+ return (0, _react2.jsx)(_themeUi.Checkbox, (0, _extends2["default"])({
41
+ ref: ref,
42
+ __css: {
43
+ top: 0,
44
+ left: 0
45
+ }
46
+ }, props));
47
+ });
48
+
49
+ var IndeterminateCheckboxIcon = function IndeterminateCheckboxIcon(props) {
50
+ return (0, _react2.jsx)("svg", (0, _extends2["default"])({
51
+ width: "24",
52
+ height: "24",
53
+ viewBox: "0 0 24 24",
54
+ fill: "none",
55
+ xmlns: "http://www.w3.org/2000/svg"
56
+ }, props), (0, _react2.jsx)("rect", {
57
+ x: "3.5",
58
+ y: "3.5",
59
+ width: "17",
60
+ height: "17",
61
+ rx: "1.5",
62
+ fill: "#4462ED",
63
+ stroke: "#4462ED"
64
+ }), (0, _react2.jsx)("rect", {
65
+ x: "6.5",
66
+ y: "11",
67
+ width: "11",
68
+ height: "2",
69
+ fill: "white"
70
+ }));
71
+ };
72
+ /**
73
+ * Renders a visually hidden default checkbox since the Theme UI checkbox does not support
74
+ * indeterminism. This allows us to have the necessary ARIA attributes and visual presentation.
75
+ */
76
+
77
+
78
+ var IndeterminateCheckbox = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
79
+ /* eslint-disable no-param-reassign */
80
+ if (ref !== null && ref !== void 0 && ref.current) ref.current.indeterminate = true;
81
+ return (0, _react2.jsx)(_react["default"].Fragment, null, (0, _react2.jsx)(_visuallyHidden.VisuallyHidden, null, (0, _react2.jsx)(DefaultCheckbox, (0, _extends2["default"])({
82
+ ref: ref
83
+ }, props))), (0, _react2.jsx)(_Box["default"], (0, _extends2["default"])({
84
+ as: IndeterminateCheckboxIcon,
85
+ mr: 2
86
+ }, props)));
87
+ });
88
+ var CheckboxBase = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
89
+ /* eslint-disable react/prop-types */
90
+ return props.isIndeterminate ? (0, _react2.jsx)(IndeterminateCheckbox, (0, _extends2["default"])({
91
+ ref: ref
92
+ }, props)) : (0, _react2.jsx)(DefaultCheckbox, (0, _extends2["default"])({
93
+ ref: ref
94
+ }, props));
95
+ });
96
+ var _default = CheckboxBase;
97
+ exports["default"] = _default;
@@ -73,6 +73,7 @@ var CheckboxField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
73
73
  hasAutoFocus = props.hasAutoFocus,
74
74
  helperText = props.helperText,
75
75
  isDefaultSelected = props.isDefaultSelected,
76
+ isIndeterminate = props.isIndeterminate,
76
77
  status = props.status;
77
78
 
78
79
  var checkboxProps = _objectSpread(_objectSpread({
@@ -89,11 +90,21 @@ var CheckboxField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
89
90
  (0, _react.useImperativeHandle)(ref, function () {
90
91
  return checkboxRef.current;
91
92
  });
93
+ (0, _react.useEffect)(function () {
94
+ if (checkboxRef.current && isIndeterminate) {
95
+ checkboxRef.current.indeterminate = true;
96
+ } else if (checkboxRef.current && !isIndeterminate) {
97
+ checkboxRef.current.indeterminate = false;
98
+ }
99
+ }, [isIndeterminate]);
92
100
 
93
101
  var _useCheckbox = (0, _checkbox.useCheckbox)(checkboxProps, state, checkboxRef),
94
102
  inputProps = _useCheckbox.inputProps;
95
103
 
96
104
  var _useField = (0, _hooks.useField)(_objectSpread(_objectSpread({}, props), {}, {
105
+ statusClasses: {
106
+ isIndeterminate: isIndeterminate
107
+ },
97
108
  controlProps: _objectSpread(_objectSpread({}, controlProps), inputProps)
98
109
  })),
99
110
  fieldContainerProps = _useField.fieldContainerProps,
@@ -131,8 +142,8 @@ CheckboxField.propTypes = _objectSpread({
131
142
  isDisabled: _propTypes["default"].bool,
132
143
 
133
144
  /**
134
- * Indeterminism is presentational only. The indeterminate visual representation remains
135
- * regardless of user interaction.
145
+ * Indeterminism is presentational only. The indeterminate visual representation remains until
146
+ * this prop is set to false regardless of user interaction.
136
147
  */
137
148
  isIndeterminate: _propTypes["default"].bool,
138
149
 
@@ -2,6 +2,10 @@
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
4
4
 
5
+ var _typeof = require("@babel/runtime-corejs3/helpers/typeof");
6
+
7
+ var _WeakMap = require("@babel/runtime-corejs3/core-js-stable/weak-map");
8
+
5
9
  var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
6
10
 
7
11
  var _Object$defineProperties = require("@babel/runtime-corejs3/core-js-stable/object/define-properties");
@@ -22,13 +26,19 @@ _Object$defineProperty(exports, "__esModule", {
22
26
  value: true
23
27
  });
24
28
 
25
- exports["default"] = exports.Required = exports.HelperText = exports.DefaultSelected = exports.Default = exports.Controlled = void 0;
29
+ exports["default"] = exports.Required = exports.Indeterminate = exports.HelperText = exports.DefaultSelected = exports.Default = exports.Controlled = void 0;
30
+
31
+ var _every = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/every"));
32
+
33
+ var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map"));
26
34
 
27
35
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray"));
28
36
 
37
+ var _values = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/values"));
38
+
29
39
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
30
40
 
31
- var _react = _interopRequireDefault(require("react"));
41
+ var _react = _interopRequireWildcard(require("react"));
32
42
 
33
43
  var _ariaAttributes = require("../../utils/devUtils/props/ariaAttributes");
34
44
 
@@ -40,8 +50,14 @@ var _Text = _interopRequireDefault(require("../Text"));
40
50
 
41
51
  var _statuses = _interopRequireDefault(require("../../utils/devUtils/constants/statuses"));
42
52
 
53
+ var _Box = _interopRequireDefault(require("../Box"));
54
+
43
55
  var _react2 = require("@emotion/react");
44
56
 
57
+ function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
58
+
59
+ 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; }
60
+
45
61
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
46
62
 
47
63
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context, _context2; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(source), !0)).call(_context, function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context2 = ownKeys(Object(source))).call(_context2, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
@@ -69,7 +85,7 @@ var _default = {
69
85
  status: {
70
86
  control: {
71
87
  type: 'select',
72
- options: _statuses["default"]
88
+ options: (0, _values["default"])(_statuses["default"])
73
89
  },
74
90
  defaultValue: _statuses["default"].DEFAULT
75
91
  },
@@ -156,4 +172,98 @@ var HelperText = function HelperText() {
156
172
  });
157
173
  };
158
174
 
159
- exports.HelperText = HelperText;
175
+ exports.HelperText = HelperText;
176
+
177
+ var Indeterminate = function Indeterminate() {
178
+ // Whether the parent checkbox is indeterminate (default is true for our example)
179
+ var _useState = (0, _react.useState)(true),
180
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
181
+ isIndeterminate = _useState2[0],
182
+ setIsIndeterminate = _useState2[1]; // Whether the parent checkbox should be checked, this is set independently from indeterminism
183
+
184
+
185
+ var _useState3 = (0, _react.useState)(false),
186
+ _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
187
+ isCompleted = _useState4[0],
188
+ setIsCompleted = _useState4[1]; // The state of the sub-checkboxes
189
+
190
+
191
+ var _useState5 = (0, _react.useState)([{
192
+ label: 'Apple Chunks',
193
+ isSelected: true
194
+ }, {
195
+ label: 'Blueberries',
196
+ isSelected: false
197
+ }, {
198
+ label: 'Grapes',
199
+ isSelected: false
200
+ }, {
201
+ label: 'Strawberry Slices',
202
+ isSelected: true
203
+ }]),
204
+ _useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
205
+ subCheckboxes = _useState6[0],
206
+ setSubCheckboxes = _useState6[1]; // Determine which checkbox needs its state updated
207
+
208
+
209
+ var handleSubCheckboxChange = function handleSubCheckboxChange(isSelected, changedIndex) {
210
+ var changeAll = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
211
+ var newSubCheckboxes = (0, _map["default"])(subCheckboxes).call(subCheckboxes, function (checkbox, index) {
212
+ if (changeAll || index === changedIndex) return _objectSpread(_objectSpread({}, checkbox), {}, {
213
+ isSelected: isSelected
214
+ });
215
+ return checkbox;
216
+ });
217
+ setSubCheckboxes(newSubCheckboxes);
218
+ }; // Update all sub-checkbox states when the parent checkbox is pressed
219
+
220
+
221
+ var handleParentCheckboxChange = function handleParentCheckboxChange(isSelected) {
222
+ handleSubCheckboxChange(isSelected, null, true);
223
+ };
224
+
225
+ (0, _react.useEffect)(function () {
226
+ // Determine if all sub-checkboxes are selected / unselected or if there is a mix
227
+ // and update the parent checkbox
228
+ if ((0, _every["default"])(subCheckboxes).call(subCheckboxes, function (item) {
229
+ return item.isSelected;
230
+ })) {
231
+ setIsIndeterminate(false);
232
+ setIsCompleted(true);
233
+ } else if ((0, _every["default"])(subCheckboxes).call(subCheckboxes, function (item) {
234
+ return !item.isSelected;
235
+ })) {
236
+ setIsIndeterminate(false);
237
+ setIsCompleted(false);
238
+ } else {
239
+ setIsIndeterminate(true);
240
+ setIsCompleted(false);
241
+ }
242
+ }, [isIndeterminate, subCheckboxes]);
243
+ return (0, _react2.jsx)(_react["default"].Fragment, null, (0, _react2.jsx)(_CheckboxField["default"], {
244
+ label: "Fruit Salad Recipe",
245
+ isIndeterminate: isIndeterminate,
246
+ isSelected: isCompleted,
247
+ onChange: handleParentCheckboxChange
248
+ }), (0, _react2.jsx)(_Box["default"], {
249
+ ml: "lg"
250
+ }, (0, _map["default"])(subCheckboxes).call(subCheckboxes, function (checkbox, index) {
251
+ return (0, _react2.jsx)(_CheckboxField["default"], {
252
+ key: checkbox.label,
253
+ label: checkbox.label,
254
+ isSelected: checkbox.isSelected,
255
+ onChange: function onChange(isSelected) {
256
+ return handleSubCheckboxChange(isSelected, index);
257
+ }
258
+ });
259
+ })));
260
+ };
261
+
262
+ exports.Indeterminate = Indeterminate;
263
+ Indeterminate.parameters = {
264
+ docs: {
265
+ description: {
266
+ story: 'When a `CheckboxField` is indeterminate, it\'s necessary to control the state in order to determine how it should function when pressed. Here is an example of how to do that.'
267
+ }
268
+ }
269
+ };
@@ -23,7 +23,12 @@ var defaultProps = {
23
23
 
24
24
  var getComponent = function getComponent() {
25
25
  var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
26
- return (0, _testWrapper.render)((0, _react2.jsx)(_CheckboxField["default"], (0, _extends2["default"])({}, defaultProps, props)));
26
+
27
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
28
+ _ref$renderFn = _ref.renderFn,
29
+ renderFn = _ref$renderFn === void 0 ? _testWrapper.render : _ref$renderFn;
30
+
31
+ return renderFn((0, _react2.jsx)(_CheckboxField["default"], (0, _extends2["default"])({}, defaultProps, props)));
27
32
  }; // Need to be added to each test file to test accessibility using axe.
28
33
 
29
34
 
@@ -113,4 +118,37 @@ test('read only checkbox', function () {
113
118
  var input = _testWrapper.screen.getByRole('checkbox');
114
119
 
115
120
  expect(input).toHaveAttribute('readonly');
121
+ });
122
+ test('indeterminate checkbox', function () {
123
+ var _getComponent = getComponent({
124
+ isIndeterminate: true
125
+ }),
126
+ rerender = _getComponent.rerender;
127
+
128
+ var input = _testWrapper.screen.getByRole('checkbox');
129
+
130
+ var label = _testWrapper.screen.getByText(testLabel);
131
+ /* eslint-disable jest-dom/prefer-checked */
132
+
133
+
134
+ expect(input).toHaveAttribute('aria-checked', 'mixed');
135
+ expect(label).toHaveClass('is-indeterminate'); // Ensure it cannot be changed via user interaction
136
+
137
+ _userEvent["default"].click(input);
138
+
139
+ expect(input).toHaveAttribute('aria-checked', 'mixed'); // An indeterminite checkbox can still have the checked attribute
140
+
141
+ expect(input).toBeChecked(); // Ensure it works normally when toggled off again
142
+
143
+ getComponent({}, {
144
+ renderFn: rerender
145
+ }); // Reset the variable since the DOM has changed
146
+
147
+ input = _testWrapper.screen.getByRole('checkbox');
148
+ expect(input).not.toHaveAttribute('aria-checked', 'mixed');
149
+ expect(label).not.toHaveClass('is-indeterminate'); // Ensure it can be changed via user interaction, should be unchecked now
150
+
151
+ _userEvent["default"].click(input);
152
+
153
+ expect(input).not.toBeChecked();
116
154
  });
@@ -52,7 +52,7 @@ var _hooks = require("../../hooks");
52
52
 
53
53
  var _constants = require("../../components/Label/constants");
54
54
 
55
- var _excluded = ["autocomplete", "autoComplete", "autoCorrect", "children", "className", "containerProps", "controlProps", "defaultText", "defaultValue", "direction", "disabledKeys", "hasAutoFocus", "hasNoStatusIndicator", "helperText", "hintText", "id", "isDefaultSelected", "isDisabled", "isReadOnly", "isRequired", "isSelected", "label", "labelMode", "labelProps", "maxLength", "name", "onBlur", "onChange", "onClear", "onFocus", "onFocusChange", "onLoadMore", "onOpenChange", "onSelectionChange", "placeholder", "role", "selectedKey", "spellCheck", "status", "statusClasses", "type", "value"];
55
+ var _excluded = ["autocomplete", "autoComplete", "autoCorrect", "children", "className", "containerProps", "controlProps", "defaultText", "defaultValue", "direction", "disabledKeys", "hasAutoFocus", "hasNoStatusIndicator", "helperText", "hintText", "id", "isDefaultSelected", "isDisabled", "isIndeterminate", "isReadOnly", "isRequired", "isSelected", "label", "labelMode", "labelProps", "maxLength", "name", "onBlur", "onChange", "onClear", "onFocus", "onFocusChange", "onLoadMore", "onOpenChange", "onSelectionChange", "placeholder", "role", "selectedKey", "spellCheck", "status", "statusClasses", "type", "value"];
56
56
 
57
57
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
58
58
 
@@ -85,6 +85,7 @@ var useField = function useField() {
85
85
  id = props.id,
86
86
  isDefaultSelected = props.isDefaultSelected,
87
87
  isDisabled = props.isDisabled,
88
+ isIndeterminate = props.isIndeterminate,
88
89
  isReadOnly = props.isReadOnly,
89
90
  isRequired = props.isRequired,
90
91
  isSelected = props.isSelected,
@@ -210,6 +211,7 @@ var useField = function useField() {
210
211
  disabled: isDisabled,
211
212
  id: id,
212
213
  isFocused: hasFocusWithin,
214
+ isIndeterminate: isIndeterminate,
213
215
  maxLength: maxLength,
214
216
  name: name,
215
217
  onChange: fieldOnChange,
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
2
2
  import React, { forwardRef } from 'react';
3
- import { Checkbox as ThemeUICheckbox } from 'theme-ui';
3
+ import CheckboxBase from './CheckboxBase';
4
4
  /**
5
5
  * Basic checkbox input.
6
6
  * Built on top of the [Checkbox from Theme-UI](https://theme-ui.com/components/checkbox/).
@@ -10,12 +10,8 @@ import { Checkbox as ThemeUICheckbox } from 'theme-ui';
10
10
 
11
11
  import { jsx as ___EmotionJSX } from "@emotion/react";
12
12
  var Checkbox = /*#__PURE__*/forwardRef(function (props, ref) {
13
- return ___EmotionJSX(ThemeUICheckbox, _extends({
14
- ref: ref,
15
- __css: {
16
- top: 0,
17
- left: 0
18
- }
13
+ return ___EmotionJSX(CheckboxBase, _extends({
14
+ ref: ref
19
15
  }, props));
20
16
  });
21
17
  Checkbox.displayName = 'Checkbox';
@@ -22,5 +22,7 @@ test('default checkbox', function () {
22
22
  getComponent();
23
23
  var input = screen.getByRole('checkbox');
24
24
  expect(input).toBeInstanceOf(HTMLInputElement);
25
- expect(input).toBeInTheDocument();
25
+ expect(input).toBeInTheDocument(); // Should be visually hidden
26
+
27
+ expect(input).not.toBeVisible();
26
28
  });
@@ -0,0 +1,69 @@
1
+ import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
2
+ import React, { forwardRef } from 'react';
3
+ import { Checkbox as ThemeUICheckbox } from 'theme-ui';
4
+ import { VisuallyHidden } from '@react-aria/visually-hidden';
5
+ import Box from '../Box';
6
+ /**
7
+ * Checkbox component from Theme UI, renders a visually hidden input + svg icons for the
8
+ * checked and unchecked states.
9
+ */
10
+
11
+ import { jsx as ___EmotionJSX } from "@emotion/react";
12
+ var DefaultCheckbox = /*#__PURE__*/forwardRef(function (props, ref) {
13
+ return ___EmotionJSX(ThemeUICheckbox, _extends({
14
+ ref: ref,
15
+ __css: {
16
+ top: 0,
17
+ left: 0
18
+ }
19
+ }, props));
20
+ });
21
+
22
+ var IndeterminateCheckboxIcon = function IndeterminateCheckboxIcon(props) {
23
+ return ___EmotionJSX("svg", _extends({
24
+ width: "24",
25
+ height: "24",
26
+ viewBox: "0 0 24 24",
27
+ fill: "none",
28
+ xmlns: "http://www.w3.org/2000/svg"
29
+ }, props), ___EmotionJSX("rect", {
30
+ x: "3.5",
31
+ y: "3.5",
32
+ width: "17",
33
+ height: "17",
34
+ rx: "1.5",
35
+ fill: "#4462ED",
36
+ stroke: "#4462ED"
37
+ }), ___EmotionJSX("rect", {
38
+ x: "6.5",
39
+ y: "11",
40
+ width: "11",
41
+ height: "2",
42
+ fill: "white"
43
+ }));
44
+ };
45
+ /**
46
+ * Renders a visually hidden default checkbox since the Theme UI checkbox does not support
47
+ * indeterminism. This allows us to have the necessary ARIA attributes and visual presentation.
48
+ */
49
+
50
+
51
+ var IndeterminateCheckbox = /*#__PURE__*/forwardRef(function (props, ref) {
52
+ /* eslint-disable no-param-reassign */
53
+ if (ref !== null && ref !== void 0 && ref.current) ref.current.indeterminate = true;
54
+ return ___EmotionJSX(React.Fragment, null, ___EmotionJSX(VisuallyHidden, null, ___EmotionJSX(DefaultCheckbox, _extends({
55
+ ref: ref
56
+ }, props))), ___EmotionJSX(Box, _extends({
57
+ as: IndeterminateCheckboxIcon,
58
+ mr: 2
59
+ }, props)));
60
+ });
61
+ var CheckboxBase = /*#__PURE__*/forwardRef(function (props, ref) {
62
+ /* eslint-disable react/prop-types */
63
+ return props.isIndeterminate ? ___EmotionJSX(IndeterminateCheckbox, _extends({
64
+ ref: ref
65
+ }, props)) : ___EmotionJSX(DefaultCheckbox, _extends({
66
+ ref: ref
67
+ }, props));
68
+ });
69
+ export default CheckboxBase;
@@ -14,7 +14,7 @@ function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (
14
14
 
15
15
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context, _context2; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(source), !0)).call(_context, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context2 = ownKeys(Object(source))).call(_context2, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
16
16
 
17
- import React, { forwardRef, useRef, useImperativeHandle } from 'react';
17
+ import React, { forwardRef, useRef, useImperativeHandle, useEffect } from 'react';
18
18
  import { useCheckbox } from '@react-aria/checkbox';
19
19
  import { useToggleState } from '@react-stately/toggle';
20
20
  import PropTypes from 'prop-types';
@@ -37,6 +37,7 @@ var CheckboxField = /*#__PURE__*/forwardRef(function (props, ref) {
37
37
  hasAutoFocus = props.hasAutoFocus,
38
38
  helperText = props.helperText,
39
39
  isDefaultSelected = props.isDefaultSelected,
40
+ isIndeterminate = props.isIndeterminate,
40
41
  status = props.status;
41
42
 
42
43
  var checkboxProps = _objectSpread(_objectSpread({
@@ -53,11 +54,21 @@ var CheckboxField = /*#__PURE__*/forwardRef(function (props, ref) {
53
54
  useImperativeHandle(ref, function () {
54
55
  return checkboxRef.current;
55
56
  });
57
+ useEffect(function () {
58
+ if (checkboxRef.current && isIndeterminate) {
59
+ checkboxRef.current.indeterminate = true;
60
+ } else if (checkboxRef.current && !isIndeterminate) {
61
+ checkboxRef.current.indeterminate = false;
62
+ }
63
+ }, [isIndeterminate]);
56
64
 
57
65
  var _useCheckbox = useCheckbox(checkboxProps, state, checkboxRef),
58
66
  inputProps = _useCheckbox.inputProps;
59
67
 
60
68
  var _useField = useField(_objectSpread(_objectSpread({}, props), {}, {
69
+ statusClasses: {
70
+ isIndeterminate: isIndeterminate
71
+ },
61
72
  controlProps: _objectSpread(_objectSpread({}, controlProps), inputProps)
62
73
  })),
63
74
  fieldContainerProps = _useField.fieldContainerProps,
@@ -95,8 +106,8 @@ CheckboxField.propTypes = _objectSpread({
95
106
  isDisabled: PropTypes.bool,
96
107
 
97
108
  /**
98
- * Indeterminism is presentational only. The indeterminate visual representation remains
99
- * regardless of user interaction.
109
+ * Indeterminism is presentational only. The indeterminate visual representation remains until
110
+ * this prop is set to false regardless of user interaction.
100
111
  */
101
112
  isIndeterminate: PropTypes.bool,
102
113
 
@@ -6,19 +6,23 @@ import _Object$getOwnPropertyDescriptor from "@babel/runtime-corejs3/core-js-sta
6
6
  import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
7
7
  import _Object$getOwnPropertySymbols from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols";
8
8
  import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys";
9
+ import _everyInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/every";
10
+ import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
9
11
  import _slicedToArray from "@babel/runtime-corejs3/helpers/esm/slicedToArray";
12
+ import _Object$values from "@babel/runtime-corejs3/core-js-stable/object/values";
10
13
  import _defineProperty from "@babel/runtime-corejs3/helpers/esm/defineProperty";
11
14
 
12
15
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
13
16
 
14
17
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context, _context2; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(source), !0)).call(_context, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context2 = ownKeys(Object(source))).call(_context2, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
15
18
 
16
- import React from 'react';
19
+ import React, { useEffect, useState } from 'react';
17
20
  import { ariaAttributeBaseArgTypes } from '../../utils/devUtils/props/ariaAttributes';
18
21
  import CheckboxField from './CheckboxField';
19
22
  import Link from '../Link';
20
23
  import Text from '../Text';
21
24
  import statuses from '../../utils/devUtils/constants/statuses';
25
+ import Box from '../Box';
22
26
  import { jsx as ___EmotionJSX } from "@emotion/react";
23
27
  export default {
24
28
  title: 'Form/CheckboxField',
@@ -43,7 +47,7 @@ export default {
43
47
  status: {
44
48
  control: {
45
49
  type: 'select',
46
- options: statuses
50
+ options: _Object$values(statuses)
47
51
  },
48
52
  defaultValue: statuses.DEFAULT
49
53
  },
@@ -114,4 +118,97 @@ export var HelperText = function HelperText() {
114
118
  helperText: "Here is some helpful text...",
115
119
  label: "Click me"
116
120
  });
121
+ };
122
+ export var Indeterminate = function Indeterminate() {
123
+ // Whether the parent checkbox is indeterminate (default is true for our example)
124
+ var _useState = useState(true),
125
+ _useState2 = _slicedToArray(_useState, 2),
126
+ isIndeterminate = _useState2[0],
127
+ setIsIndeterminate = _useState2[1]; // Whether the parent checkbox should be checked, this is set independently from indeterminism
128
+
129
+
130
+ var _useState3 = useState(false),
131
+ _useState4 = _slicedToArray(_useState3, 2),
132
+ isCompleted = _useState4[0],
133
+ setIsCompleted = _useState4[1]; // The state of the sub-checkboxes
134
+
135
+
136
+ var _useState5 = useState([{
137
+ label: 'Apple Chunks',
138
+ isSelected: true
139
+ }, {
140
+ label: 'Blueberries',
141
+ isSelected: false
142
+ }, {
143
+ label: 'Grapes',
144
+ isSelected: false
145
+ }, {
146
+ label: 'Strawberry Slices',
147
+ isSelected: true
148
+ }]),
149
+ _useState6 = _slicedToArray(_useState5, 2),
150
+ subCheckboxes = _useState6[0],
151
+ setSubCheckboxes = _useState6[1]; // Determine which checkbox needs its state updated
152
+
153
+
154
+ var handleSubCheckboxChange = function handleSubCheckboxChange(isSelected, changedIndex) {
155
+ var changeAll = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
156
+
157
+ var newSubCheckboxes = _mapInstanceProperty(subCheckboxes).call(subCheckboxes, function (checkbox, index) {
158
+ if (changeAll || index === changedIndex) return _objectSpread(_objectSpread({}, checkbox), {}, {
159
+ isSelected: isSelected
160
+ });
161
+ return checkbox;
162
+ });
163
+
164
+ setSubCheckboxes(newSubCheckboxes);
165
+ }; // Update all sub-checkbox states when the parent checkbox is pressed
166
+
167
+
168
+ var handleParentCheckboxChange = function handleParentCheckboxChange(isSelected) {
169
+ handleSubCheckboxChange(isSelected, null, true);
170
+ };
171
+
172
+ useEffect(function () {
173
+ // Determine if all sub-checkboxes are selected / unselected or if there is a mix
174
+ // and update the parent checkbox
175
+ if (_everyInstanceProperty(subCheckboxes).call(subCheckboxes, function (item) {
176
+ return item.isSelected;
177
+ })) {
178
+ setIsIndeterminate(false);
179
+ setIsCompleted(true);
180
+ } else if (_everyInstanceProperty(subCheckboxes).call(subCheckboxes, function (item) {
181
+ return !item.isSelected;
182
+ })) {
183
+ setIsIndeterminate(false);
184
+ setIsCompleted(false);
185
+ } else {
186
+ setIsIndeterminate(true);
187
+ setIsCompleted(false);
188
+ }
189
+ }, [isIndeterminate, subCheckboxes]);
190
+ return ___EmotionJSX(React.Fragment, null, ___EmotionJSX(CheckboxField, {
191
+ label: "Fruit Salad Recipe",
192
+ isIndeterminate: isIndeterminate,
193
+ isSelected: isCompleted,
194
+ onChange: handleParentCheckboxChange
195
+ }), ___EmotionJSX(Box, {
196
+ ml: "lg"
197
+ }, _mapInstanceProperty(subCheckboxes).call(subCheckboxes, function (checkbox, index) {
198
+ return ___EmotionJSX(CheckboxField, {
199
+ key: checkbox.label,
200
+ label: checkbox.label,
201
+ isSelected: checkbox.isSelected,
202
+ onChange: function onChange(isSelected) {
203
+ return handleSubCheckboxChange(isSelected, index);
204
+ }
205
+ });
206
+ })));
207
+ };
208
+ Indeterminate.parameters = {
209
+ docs: {
210
+ description: {
211
+ story: 'When a `CheckboxField` is indeterminate, it\'s necessary to control the state in order to determine how it should function when pressed. Here is an example of how to do that.'
212
+ }
213
+ }
117
214
  };
@@ -12,7 +12,12 @@ var defaultProps = {
12
12
 
13
13
  var getComponent = function getComponent() {
14
14
  var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
15
- return render(___EmotionJSX(CheckboxField, _extends({}, defaultProps, props)));
15
+
16
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
17
+ _ref$renderFn = _ref.renderFn,
18
+ renderFn = _ref$renderFn === void 0 ? render : _ref$renderFn;
19
+
20
+ return renderFn(___EmotionJSX(CheckboxField, _extends({}, defaultProps, props)));
16
21
  }; // Need to be added to each test file to test accessibility using axe.
17
22
 
18
23
 
@@ -81,4 +86,33 @@ test('read only checkbox', function () {
81
86
  });
82
87
  var input = screen.getByRole('checkbox');
83
88
  expect(input).toHaveAttribute('readonly');
89
+ });
90
+ test('indeterminate checkbox', function () {
91
+ var _getComponent = getComponent({
92
+ isIndeterminate: true
93
+ }),
94
+ rerender = _getComponent.rerender;
95
+
96
+ var input = screen.getByRole('checkbox');
97
+ var label = screen.getByText(testLabel);
98
+ /* eslint-disable jest-dom/prefer-checked */
99
+
100
+ expect(input).toHaveAttribute('aria-checked', 'mixed');
101
+ expect(label).toHaveClass('is-indeterminate'); // Ensure it cannot be changed via user interaction
102
+
103
+ userEvent.click(input);
104
+ expect(input).toHaveAttribute('aria-checked', 'mixed'); // An indeterminite checkbox can still have the checked attribute
105
+
106
+ expect(input).toBeChecked(); // Ensure it works normally when toggled off again
107
+
108
+ getComponent({}, {
109
+ renderFn: rerender
110
+ }); // Reset the variable since the DOM has changed
111
+
112
+ input = screen.getByRole('checkbox');
113
+ expect(input).not.toHaveAttribute('aria-checked', 'mixed');
114
+ expect(label).not.toHaveClass('is-indeterminate'); // Ensure it can be changed via user interaction, should be unchecked now
115
+
116
+ userEvent.click(input);
117
+ expect(input).not.toBeChecked();
84
118
  });
@@ -9,7 +9,7 @@ import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys";
9
9
  import _defineProperty from "@babel/runtime-corejs3/helpers/esm/defineProperty";
10
10
  import _slicedToArray from "@babel/runtime-corejs3/helpers/esm/slicedToArray";
11
11
  import _objectWithoutProperties from "@babel/runtime-corejs3/helpers/esm/objectWithoutProperties";
12
- var _excluded = ["autocomplete", "autoComplete", "autoCorrect", "children", "className", "containerProps", "controlProps", "defaultText", "defaultValue", "direction", "disabledKeys", "hasAutoFocus", "hasNoStatusIndicator", "helperText", "hintText", "id", "isDefaultSelected", "isDisabled", "isReadOnly", "isRequired", "isSelected", "label", "labelMode", "labelProps", "maxLength", "name", "onBlur", "onChange", "onClear", "onFocus", "onFocusChange", "onLoadMore", "onOpenChange", "onSelectionChange", "placeholder", "role", "selectedKey", "spellCheck", "status", "statusClasses", "type", "value"];
12
+ var _excluded = ["autocomplete", "autoComplete", "autoCorrect", "children", "className", "containerProps", "controlProps", "defaultText", "defaultValue", "direction", "disabledKeys", "hasAutoFocus", "hasNoStatusIndicator", "helperText", "hintText", "id", "isDefaultSelected", "isDisabled", "isIndeterminate", "isReadOnly", "isRequired", "isSelected", "label", "labelMode", "labelProps", "maxLength", "name", "onBlur", "onChange", "onClear", "onFocus", "onFocusChange", "onLoadMore", "onOpenChange", "onSelectionChange", "placeholder", "role", "selectedKey", "spellCheck", "status", "statusClasses", "type", "value"];
13
13
 
14
14
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
15
15
 
@@ -55,6 +55,7 @@ var useField = function useField() {
55
55
  id = props.id,
56
56
  isDefaultSelected = props.isDefaultSelected,
57
57
  isDisabled = props.isDisabled,
58
+ isIndeterminate = props.isIndeterminate,
58
59
  isReadOnly = props.isReadOnly,
59
60
  isRequired = props.isRequired,
60
61
  isSelected = props.isSelected,
@@ -181,6 +182,7 @@ var useField = function useField() {
181
182
  disabled: isDisabled,
182
183
  id: id,
183
184
  isFocused: hasFocusWithin,
185
+ isIndeterminate: isIndeterminate,
184
186
  maxLength: maxLength,
185
187
  name: name,
186
188
  onChange: fieldOnChange,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pingux/astro",
3
- "version": "1.33.1-alpha.0",
3
+ "version": "1.33.1-alpha.1",
4
4
  "description": "PingUX themeable React component library",
5
5
  "repository": {
6
6
  "type": "git",