@bento/checkbox 0.1.2
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/LICENSE +9 -0
- package/README.mdx +118 -0
- package/dist/index.cjs +121 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +79 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +114 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
- package/src/checkbox-group-state.tsx +4 -0
- package/src/checkbox-group.tsx +98 -0
- package/src/checkbox.tsx +139 -0
- package/src/index.tsx +2 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 GoDaddy Operating Company, LLC.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.mdx
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Meta, ArgTypes, Story, Controls, Source } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as Stories from './checkbox.stories.tsx';
|
|
3
|
+
import CheckboxControlledExample from './examples/checkbox-controlled.tsx?raw';
|
|
4
|
+
import CheckboxExample from './examples/checkbox.tsx?raw';
|
|
5
|
+
import CheckboxGroupExample from './examples/checkbox-group.tsx?raw';
|
|
6
|
+
import CheckboxGroupControlledExample from './examples/checkbox-group-controlled.tsx?raw';
|
|
7
|
+
import CheckboxGroupIndeterminateExample from './examples/checkbox-group-indeterminate.tsx?raw';
|
|
8
|
+
|
|
9
|
+
<Meta of={Stories} name="Overview" />
|
|
10
|
+
|
|
11
|
+
# Checkbox
|
|
12
|
+
|
|
13
|
+
The `@bento/checkbox` package provides accessible and customizable checkbox inputs. It exports the **CheckboxGroup** and **Checkbox** primitives, enabling you to build individual or groups of checkboxes with consistent keyboard navigation, focus management, and ARIA support. React Aria is used to ensure that the checkboxes are accessible to all users.
|
|
14
|
+
|
|
15
|
+
The `CheckboxGroup` allows a user to select multiple items from a list of `Checkbox` components.
|
|
16
|
+
|
|
17
|
+
The `Checkbox` is a single checkbox option that can be selected by the user.
|
|
18
|
+
|
|
19
|
+
# Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install --save @bento/checkbox
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Props
|
|
26
|
+
|
|
27
|
+
The following properties are available to be used on the `CheckboxGroup` and `Checkbox` primitives:
|
|
28
|
+
|
|
29
|
+
### Checkbox
|
|
30
|
+
|
|
31
|
+
<ArgTypes of={Stories.CheckboxProps} />
|
|
32
|
+
|
|
33
|
+
### CheckboxGroup
|
|
34
|
+
|
|
35
|
+
<ArgTypes of={Stories.CheckboxGroupProps} />
|
|
36
|
+
|
|
37
|
+
## Data Attributes, Slot Map and Props
|
|
38
|
+
|
|
39
|
+
### Data Attributes
|
|
40
|
+
|
|
41
|
+
The following data attributes can be used to style and customize the `CheckboxGroup` and `Checkbox` primitives.
|
|
42
|
+
|
|
43
|
+
#### `CheckboxGroup` Data Attributes
|
|
44
|
+
|
|
45
|
+
| Attribute | Description |
|
|
46
|
+
| --------------- | ------------------------------- |
|
|
47
|
+
| `data-disabled` | Indicates the checkbox group is disabled |
|
|
48
|
+
| `data-read-only` | Indicates the checkbox group is readonly |
|
|
49
|
+
| `data-required` | Indicates the checkbox group is required |
|
|
50
|
+
| `data-invalid` | Indicates the checkbox group is invalid |
|
|
51
|
+
|
|
52
|
+
#### `Checkbox` Data Attributes
|
|
53
|
+
|
|
54
|
+
| Attribute | Description |
|
|
55
|
+
| --------------- | ------------------------------- |
|
|
56
|
+
| `data-disabled` | Indicates the checkbox is disabled |
|
|
57
|
+
| `data-read-only` | Indicates the checkbox is readonly |
|
|
58
|
+
| `data-required` | Indicates the checkbox is required |
|
|
59
|
+
| `data-invalid` | Indicates the checkbox is invalid |
|
|
60
|
+
| `data-indeterminate` | Indicates the checkbox is in an indeterminate state |
|
|
61
|
+
| `data-pressed` | Indicates the checkbox is being pressed |
|
|
62
|
+
| `data-hovered` | Indicates the checkbox is hovered |
|
|
63
|
+
| `data-focused` | Indicates the checkbox has focus |
|
|
64
|
+
| `data-focus-visible` | Indicates focus should be visible |
|
|
65
|
+
| `data-selected` | Indicates the checkbox is selected |
|
|
66
|
+
|
|
67
|
+
### Slot Map
|
|
68
|
+
|
|
69
|
+
The `CheckboxGroup` and `Checkbox` primitives are built off of the `Control` and `ControlGroup` primitives, which provide a consisten set of slot values, as shown below.
|
|
70
|
+
|
|
71
|
+
#### `CheckboxGroup` Slot Map
|
|
72
|
+
|
|
73
|
+
| Slot Name | Description |
|
|
74
|
+
| ------------------- | ---------------------------- |
|
|
75
|
+
| `group.label` | Label for checkbox group |
|
|
76
|
+
| `group.description` | Description for checkbox group|
|
|
77
|
+
| `group.error` | Error message for checkbox group|
|
|
78
|
+
|
|
79
|
+
#### `Checkbox` Slot Map
|
|
80
|
+
|
|
81
|
+
| Slot Name | Description |
|
|
82
|
+
| --------------- | -------------- |
|
|
83
|
+
| `control.icon-checked` | Icon for checked checkbox |
|
|
84
|
+
| `control.icon-unchecked` | Icon for unchecked checkbox |
|
|
85
|
+
| `control.icon-indeterminate` | Icon for indeterminate checkbox |
|
|
86
|
+
| `control.label` | Text for checkbox |
|
|
87
|
+
|
|
88
|
+
## Examples
|
|
89
|
+
|
|
90
|
+
### Default Checkbox - Uncontrolled
|
|
91
|
+
|
|
92
|
+
The `Checkbox` primitive is uncontrolled by default, meaning it manages its own state internally. You can also use it in a controlled manner by providing the `checked` and `onChange` props.
|
|
93
|
+
|
|
94
|
+
<Source language="tsx" code={CheckboxExample} />
|
|
95
|
+
|
|
96
|
+
### Controlled Checkbox
|
|
97
|
+
|
|
98
|
+
The `Checkbox` can also be used in a controlled manner, where you manage its state externally with the `checked` and `onChange` props.
|
|
99
|
+
|
|
100
|
+
<Source language="tsx" code={CheckboxControlledExample} />
|
|
101
|
+
|
|
102
|
+
### Checkbox Group
|
|
103
|
+
|
|
104
|
+
The `CheckboxGroup` allows a user to select multiple items from a list of `Checkbox` components.
|
|
105
|
+
|
|
106
|
+
<Source language="tsx" code={CheckboxGroupExample} />
|
|
107
|
+
|
|
108
|
+
### Controlled Checkbox Group
|
|
109
|
+
|
|
110
|
+
The `CheckboxGroup` can also be used in a controlled manner, where you manage the state of the checkboxes externally with the `value` and `onChange` props.
|
|
111
|
+
|
|
112
|
+
<Source language="tsx" code={CheckboxGroupControlledExample} />
|
|
113
|
+
|
|
114
|
+
### Checkbox Group with Indeterminate State
|
|
115
|
+
|
|
116
|
+
The `CheckboxGroup` can also support an indeterminate state, which is useful when some but not all checkboxes are selected. The complex state management shown here is an example of how to handle indeterminate states in a checkbox group in a common way.
|
|
117
|
+
|
|
118
|
+
<Source language="tsx" code={CheckboxGroupIndeterminateExample} />
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React2 = require('react');
|
|
4
|
+
var control = require('@bento/control');
|
|
5
|
+
var icon = require('@bento/icon');
|
|
6
|
+
var slots = require('@bento/slots');
|
|
7
|
+
var useProps = require('@bento/use-props');
|
|
8
|
+
var reactAria = require('react-aria');
|
|
9
|
+
var utils = require('@react-aria/utils');
|
|
10
|
+
var reactStately = require('react-stately');
|
|
11
|
+
var useDataAttributes = require('@bento/use-data-attributes');
|
|
12
|
+
|
|
13
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
|
|
15
|
+
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
16
|
+
|
|
17
|
+
// src/checkbox.tsx
|
|
18
|
+
var CheckboxGroupStateContext = React2__default.default.createContext(null);
|
|
19
|
+
|
|
20
|
+
// src/checkbox.tsx
|
|
21
|
+
var Checkbox = slots.withSlots("BentoCheckbox", function Checkbox2(args) {
|
|
22
|
+
const { props, apply } = useProps.useProps(args);
|
|
23
|
+
const {
|
|
24
|
+
isRequired = false,
|
|
25
|
+
isIndeterminate = false,
|
|
26
|
+
isDisabled: isDisabledProp = false,
|
|
27
|
+
isSelected: isSelectedProp = false,
|
|
28
|
+
isReadOnly: isReadOnlyProp = false
|
|
29
|
+
} = props;
|
|
30
|
+
const groupState = React2.useContext(CheckboxGroupStateContext);
|
|
31
|
+
const ref = React2.useRef(null);
|
|
32
|
+
const inputRef = utils.useObjectRef(React2.useMemo(() => utils.mergeRefs(ref, props.inputRef), [ref, props.inputRef]));
|
|
33
|
+
let { labelProps, inputProps, isSelected, isReadOnly, isDisabled, isPressed, isInvalid } = groupState ? reactAria.useCheckboxGroupItem(
|
|
34
|
+
{
|
|
35
|
+
...props,
|
|
36
|
+
// Value is optional for standalone checkboxes, but required for CheckboxGroup items;
|
|
37
|
+
// it's passed explicitly here to avoid typescript error (requires ignore)(recommendation from React Aria).
|
|
38
|
+
value: props.value
|
|
39
|
+
},
|
|
40
|
+
groupState,
|
|
41
|
+
inputRef
|
|
42
|
+
) : reactAria.useCheckbox(
|
|
43
|
+
{
|
|
44
|
+
...props
|
|
45
|
+
},
|
|
46
|
+
reactStately.useToggleState(props),
|
|
47
|
+
inputRef
|
|
48
|
+
);
|
|
49
|
+
const interactionDisabled = isDisabledProp || isDisabled || isReadOnly || isReadOnlyProp;
|
|
50
|
+
const { hoverProps, isHovered } = reactAria.useHover({
|
|
51
|
+
...props,
|
|
52
|
+
isDisabled: interactionDisabled
|
|
53
|
+
});
|
|
54
|
+
const { isFocused, isFocusVisible, focusProps } = reactAria.useFocusRing();
|
|
55
|
+
return /* @__PURE__ */ React2__default.default.createElement(
|
|
56
|
+
control.Control,
|
|
57
|
+
{
|
|
58
|
+
slot: "control",
|
|
59
|
+
labelProps: utils.mergeProps(labelProps, hoverProps),
|
|
60
|
+
inputProps: utils.mergeProps(inputProps, focusProps),
|
|
61
|
+
label: props.children,
|
|
62
|
+
inputRef,
|
|
63
|
+
"aria-checked": isIndeterminate ? "mixed" : void 0,
|
|
64
|
+
...apply(props, ["isReadOnly", "isSelected", "isIndeterminate", "isDisabled", "value", "autoFocus"]),
|
|
65
|
+
...useDataAttributes.useDataAttributes({
|
|
66
|
+
selected: isSelected || isSelectedProp,
|
|
67
|
+
pressed: isPressed,
|
|
68
|
+
hovered: isHovered,
|
|
69
|
+
focused: isFocused,
|
|
70
|
+
focusVisible: isFocusVisible,
|
|
71
|
+
disabled: interactionDisabled,
|
|
72
|
+
readOnly: isReadOnly || isReadOnlyProp,
|
|
73
|
+
invalid: isInvalid,
|
|
74
|
+
required: isRequired,
|
|
75
|
+
indeterminate: isIndeterminate
|
|
76
|
+
})
|
|
77
|
+
},
|
|
78
|
+
isIndeterminate ? /* @__PURE__ */ React2__default.default.createElement(icon.Icon, { slot: "icon-indeterminate", icon: "checkboxIndeterminate" }, /* @__PURE__ */ React2__default.default.createElement("svg", { viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React2__default.default.createElement("rect", { x: "6", y: "11", width: "12", height: "2", fill: "currentColor" }))) : isSelected ? /* @__PURE__ */ React2__default.default.createElement(icon.Icon, { slot: "icon-checked", icon: "checkboxChecked" }, /* @__PURE__ */ React2__default.default.createElement("svg", { viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React2__default.default.createElement("path", { d: "M9,16.2L4.8,12l-1.4,1.4L9,19L21,7l-1.4-1.4L9,16.2z", fill: "currentColor" }))) : /* @__PURE__ */ React2__default.default.createElement(icon.Icon, { slot: "icon-unchecked", icon: "checkboxUnchecked" }, /* @__PURE__ */ React2__default.default.createElement("svg", { width: 24, height: 24, "aria-hidden": "true" }, /* @__PURE__ */ React2__default.default.createElement("rect", { x: 4, y: 4, width: 16, height: 16, rx: 3, fill: "none", stroke: "gray", strokeWidth: 2 })))
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
var CheckboxGroup = slots.withSlots("BentoCheckboxGroup", function CheckboxGroup2(args) {
|
|
82
|
+
const { errorMessage, ...restArgs } = args;
|
|
83
|
+
const { props, apply } = useProps.useProps(restArgs);
|
|
84
|
+
const state = reactStately.useCheckboxGroupState(props);
|
|
85
|
+
const { children } = props;
|
|
86
|
+
const { groupProps, labelProps, descriptionProps, errorMessageProps, ...validationResult } = reactAria.useCheckboxGroup(
|
|
87
|
+
props,
|
|
88
|
+
state
|
|
89
|
+
);
|
|
90
|
+
const displayedErrorMessage = React2.useMemo(
|
|
91
|
+
function getErrorMessage() {
|
|
92
|
+
return typeof errorMessage === "function" ? errorMessage(validationResult) : errorMessage || validationResult.validationErrors.join(", ");
|
|
93
|
+
},
|
|
94
|
+
[errorMessage, validationResult]
|
|
95
|
+
);
|
|
96
|
+
return /* @__PURE__ */ React2__default.default.createElement(
|
|
97
|
+
control.ControlGroup,
|
|
98
|
+
{
|
|
99
|
+
slot: "group",
|
|
100
|
+
labelProps,
|
|
101
|
+
descriptionProps,
|
|
102
|
+
errorMessage: displayedErrorMessage,
|
|
103
|
+
errorMessageProps,
|
|
104
|
+
...groupProps,
|
|
105
|
+
...apply(props, ["isInvalid", "isDisabled", "isReadOnly", "isRequired", "validationBehavior"]),
|
|
106
|
+
...useDataAttributes.useDataAttributes({
|
|
107
|
+
orientation: props.orientation || "vertical",
|
|
108
|
+
invalid: state.isInvalid,
|
|
109
|
+
disabled: state.isDisabled,
|
|
110
|
+
readonly: state.isReadOnly,
|
|
111
|
+
required: state.isRequired
|
|
112
|
+
})
|
|
113
|
+
},
|
|
114
|
+
/* @__PURE__ */ React2__default.default.createElement(CheckboxGroupStateContext.Provider, { value: state }, children)
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
exports.Checkbox = Checkbox;
|
|
119
|
+
exports.CheckboxGroup = CheckboxGroup;
|
|
120
|
+
//# sourceMappingURL=index.cjs.map
|
|
121
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/checkbox-group-state.tsx","../src/checkbox.tsx","../src/checkbox-group.tsx"],"names":["React","withSlots","Checkbox","useProps","useContext","useRef","useObjectRef","useMemo","mergeRefs","useCheckboxGroupItem","useCheckbox","useToggleState","useHover","useFocusRing","Control","mergeProps","useDataAttributes","Icon","CheckboxGroup","useCheckboxGroupState","useCheckboxGroup","ControlGroup"],"mappings":"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","file":"index.cjs","sourcesContent":["import React from 'react';\nimport { CheckboxGroupState } from 'react-stately';\n\nexport const CheckboxGroupStateContext = React.createContext<CheckboxGroupState | null>(null);\n","import React, { useContext, useRef, useMemo } from 'react';\nimport { Control, ControlProps } from '@bento/control';\nimport { Icon } from '@bento/icon';\nimport { withSlots } from '@bento/slots';\nimport { useProps } from '@bento/use-props';\nimport { useFocusRing, useHover, type AriaCheckboxProps, useCheckboxGroupItem, useCheckbox } from 'react-aria';\nimport { mergeProps, mergeRefs, useObjectRef } from '@react-aria/utils';\nimport { useToggleState } from 'react-stately';\nimport { useDataAttributes } from '@bento/use-data-attributes';\nimport { CheckboxGroupStateContext } from './checkbox-group-state';\n\nexport interface CheckboxProps extends AriaCheckboxProps, Partial<Omit<ControlProps, keyof AriaCheckboxProps>> {\n /** The value of the checkbox, used when submitting an HTML form. */\n value?: string;\n\n /** The name of the checkbox. */\n name?: string;\n\n /** A ref for the HTML input element. */\n inputRef?: React.Ref<HTMLInputElement>;\n\n /** The label for the checkbox. Accepts any renderable node. */\n children?: React.ReactNode;\n\n /** Whether the checkbox is required or not. */\n isRequired?: boolean;\n\n /** Whether the input can be selected but not changed by the user. */\n isReadOnly?: boolean;\n\n /**\n * Whether the checkbox is disabled or not. Shows that a selection exists,\n * but is not available in that circumstance.\n */\n isDisabled?: boolean;\n\n /** Whether the element should receive focus on render. */\n autoFocus?: boolean;\n\n /** Whether the checkbox is in an indeterminate state. */\n isIndeterminate?: boolean;\n\n /** Whether the checkbox is in a selected state. */\n isSelected?: boolean;\n}\n\n/**\n * The `Checkbox` is a single checkbox option that can be selected by the user.\n *\n * @component\n * @param args - The props {@link CheckboxProps} passed to the Checkbox component.\n *\n * @public\n */\nexport const Checkbox = withSlots('BentoCheckbox', function Checkbox(args: CheckboxProps) {\n const { props, apply } = useProps(args);\n const {\n isRequired = false,\n isIndeterminate = false,\n isDisabled: isDisabledProp = false,\n isSelected: isSelectedProp = false,\n isReadOnly: isReadOnlyProp = false\n } = props;\n\n const groupState = useContext(CheckboxGroupStateContext);\n\n const ref = useRef<HTMLInputElement>(null);\n const inputRef = useObjectRef(useMemo(() => mergeRefs(ref, props.inputRef), [ref, props.inputRef]));\n\n let { labelProps, inputProps, isSelected, isReadOnly, isDisabled, isPressed, isInvalid } = groupState\n ? useCheckboxGroupItem(\n {\n ...props,\n // Value is optional for standalone checkboxes, but required for CheckboxGroup items;\n // it's passed explicitly here to avoid typescript error (requires ignore)(recommendation from React Aria).\n value: (props as Required<Pick<typeof props, 'value'>>).value\n },\n groupState,\n inputRef\n )\n : useCheckbox(\n {\n ...props\n },\n useToggleState(props),\n inputRef\n );\n\n const interactionDisabled = isDisabledProp || isDisabled || isReadOnly || isReadOnlyProp;\n const { hoverProps, isHovered } = useHover({\n ...props,\n isDisabled: interactionDisabled\n });\n const { isFocused, isFocusVisible, focusProps } = useFocusRing();\n\n return (\n <Control\n slot=\"control\"\n labelProps={mergeProps(labelProps, hoverProps)}\n inputProps={mergeProps(inputProps, focusProps)}\n label={props.children}\n inputRef={inputRef}\n aria-checked={isIndeterminate ? 'mixed' : undefined}\n {...apply(props, ['isReadOnly', 'isSelected', 'isIndeterminate', 'isDisabled', 'value', 'autoFocus'])}\n {...useDataAttributes({\n selected: isSelected || isSelectedProp,\n pressed: isPressed,\n hovered: isHovered,\n focused: isFocused,\n focusVisible: isFocusVisible,\n disabled: interactionDisabled,\n readOnly: isReadOnly || isReadOnlyProp,\n invalid: isInvalid,\n required: isRequired,\n indeterminate: isIndeterminate\n })}\n >\n {isIndeterminate ? (\n <Icon slot=\"icon-indeterminate\" icon=\"checkboxIndeterminate\">\n <svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"6\" y=\"11\" width=\"12\" height=\"2\" fill=\"currentColor\" />\n </svg>\n </Icon>\n ) : isSelected ? (\n <Icon slot=\"icon-checked\" icon=\"checkboxChecked\">\n <svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9,16.2L4.8,12l-1.4,1.4L9,19L21,7l-1.4-1.4L9,16.2z\" fill=\"currentColor\" />\n </svg>\n </Icon>\n ) : (\n <Icon slot=\"icon-unchecked\" icon=\"checkboxUnchecked\">\n <svg width={24} height={24} aria-hidden=\"true\">\n <rect x={4} y={4} width={16} height={16} rx={3} fill=\"none\" stroke=\"gray\" strokeWidth={2} />\n </svg>\n </Icon>\n )}\n </Control>\n );\n});\n","import React, { useMemo } from 'react';\nimport { useProps } from '@bento/use-props';\nimport { ControlGroup, ControlGroupProps } from '@bento/control';\nimport { useDataAttributes } from '@bento/use-data-attributes';\nimport { type ValidationResult } from '@react-types/shared';\nimport { AriaCheckboxGroupProps, useCheckboxGroup } from 'react-aria';\nimport { useCheckboxGroupState } from 'react-stately';\nimport { withSlots } from '@bento/slots';\nimport { CheckboxGroupStateContext } from './checkbox-group-state';\n\nexport interface CheckboxGroupProps\n extends AriaCheckboxGroupProps,\n Partial<Omit<ControlGroupProps, keyof AriaCheckboxGroupProps>> {\n /** The current value of the checkbox group (controlled). */\n value?: string[];\n\n /** The default value of the checkbox group (uncontrolled). */\n defaultValue?: string[];\n\n /** Whether the input is disabled. */\n isDisabled?: boolean;\n\n /** Whether the input can be selected but not changed by the user. */\n isReadOnly?: boolean;\n\n /** Whether user input is required on the input before form submission. */\n isRequired?: boolean;\n\n /** Whether the input value is invalid. */\n isInvalid?: boolean;\n\n /** The name of the input element, used when submitting an HTML form. */\n name?: string;\n\n /**\n * The <form> element to associate the input with.\n * The value of this attribute must be the id of a <form> in the same document.\n */\n form?: string;\n\n /** Description for the checkbox group. */\n description?: string;\n\n /** Checkbox children. */\n children?: React.ReactNode;\n\n /** Error message for the checkbox group. */\n errorMessage?: React.ReactNode | ((val: ValidationResult) => React.ReactNode);\n}\n\n/**\n * The `CheckboxGroup` allows a user to select items from a list of `Checkbox` components.\n *\n * @component\n * @param {CheckboxGroupProps} args - The props passed to the CheckboxGroup component.\n *\n * @public\n */\nexport const CheckboxGroup = withSlots('BentoCheckboxGroup', function CheckboxGroup(args: CheckboxGroupProps) {\n const { errorMessage, ...restArgs } = args;\n const { props, apply } = useProps(restArgs);\n const state = useCheckboxGroupState(props);\n const { children } = props;\n const { groupProps, labelProps, descriptionProps, errorMessageProps, ...validationResult } = useCheckboxGroup(\n props,\n state\n );\n\n const displayedErrorMessage = useMemo(\n function getErrorMessage() {\n return typeof errorMessage === 'function'\n ? errorMessage(validationResult)\n : errorMessage || validationResult.validationErrors.join(', ');\n },\n [errorMessage, validationResult]\n );\n\n return (\n <ControlGroup\n slot=\"group\"\n labelProps={labelProps}\n descriptionProps={descriptionProps}\n errorMessage={displayedErrorMessage}\n errorMessageProps={errorMessageProps}\n {...groupProps}\n {...apply(props, ['isInvalid', 'isDisabled', 'isReadOnly', 'isRequired', 'validationBehavior'])}\n {...useDataAttributes({\n orientation: props.orientation || 'vertical',\n invalid: state.isInvalid,\n disabled: state.isDisabled,\n readonly: state.isReadOnly,\n required: state.isRequired\n })}\n >\n <CheckboxGroupStateContext.Provider value={state}>{children}</CheckboxGroupStateContext.Provider>\n </ControlGroup>\n );\n});\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as _bento_slots from '@bento/slots';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ControlProps, ControlGroupProps } from '@bento/control';
|
|
4
|
+
import { AriaCheckboxProps, AriaCheckboxGroupProps } from 'react-aria';
|
|
5
|
+
import { ValidationResult } from '@react-types/shared';
|
|
6
|
+
|
|
7
|
+
interface CheckboxProps extends AriaCheckboxProps, Partial<Omit<ControlProps, keyof AriaCheckboxProps>> {
|
|
8
|
+
/** The value of the checkbox, used when submitting an HTML form. */
|
|
9
|
+
value?: string;
|
|
10
|
+
/** The name of the checkbox. */
|
|
11
|
+
name?: string;
|
|
12
|
+
/** A ref for the HTML input element. */
|
|
13
|
+
inputRef?: React.Ref<HTMLInputElement>;
|
|
14
|
+
/** The label for the checkbox. Accepts any renderable node. */
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
/** Whether the checkbox is required or not. */
|
|
17
|
+
isRequired?: boolean;
|
|
18
|
+
/** Whether the input can be selected but not changed by the user. */
|
|
19
|
+
isReadOnly?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the checkbox is disabled or not. Shows that a selection exists,
|
|
22
|
+
* but is not available in that circumstance.
|
|
23
|
+
*/
|
|
24
|
+
isDisabled?: boolean;
|
|
25
|
+
/** Whether the element should receive focus on render. */
|
|
26
|
+
autoFocus?: boolean;
|
|
27
|
+
/** Whether the checkbox is in an indeterminate state. */
|
|
28
|
+
isIndeterminate?: boolean;
|
|
29
|
+
/** Whether the checkbox is in a selected state. */
|
|
30
|
+
isSelected?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The `Checkbox` is a single checkbox option that can be selected by the user.
|
|
34
|
+
*
|
|
35
|
+
* @component
|
|
36
|
+
* @param args - The props {@link CheckboxProps} passed to the Checkbox component.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
declare const Checkbox: React.NamedExoticComponent<CheckboxProps & _bento_slots.Slots>;
|
|
41
|
+
|
|
42
|
+
interface CheckboxGroupProps extends AriaCheckboxGroupProps, Partial<Omit<ControlGroupProps, keyof AriaCheckboxGroupProps>> {
|
|
43
|
+
/** The current value of the checkbox group (controlled). */
|
|
44
|
+
value?: string[];
|
|
45
|
+
/** The default value of the checkbox group (uncontrolled). */
|
|
46
|
+
defaultValue?: string[];
|
|
47
|
+
/** Whether the input is disabled. */
|
|
48
|
+
isDisabled?: boolean;
|
|
49
|
+
/** Whether the input can be selected but not changed by the user. */
|
|
50
|
+
isReadOnly?: boolean;
|
|
51
|
+
/** Whether user input is required on the input before form submission. */
|
|
52
|
+
isRequired?: boolean;
|
|
53
|
+
/** Whether the input value is invalid. */
|
|
54
|
+
isInvalid?: boolean;
|
|
55
|
+
/** The name of the input element, used when submitting an HTML form. */
|
|
56
|
+
name?: string;
|
|
57
|
+
/**
|
|
58
|
+
* The <form> element to associate the input with.
|
|
59
|
+
* The value of this attribute must be the id of a <form> in the same document.
|
|
60
|
+
*/
|
|
61
|
+
form?: string;
|
|
62
|
+
/** Description for the checkbox group. */
|
|
63
|
+
description?: string;
|
|
64
|
+
/** Checkbox children. */
|
|
65
|
+
children?: React.ReactNode;
|
|
66
|
+
/** Error message for the checkbox group. */
|
|
67
|
+
errorMessage?: React.ReactNode | ((val: ValidationResult) => React.ReactNode);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The `CheckboxGroup` allows a user to select items from a list of `Checkbox` components.
|
|
71
|
+
*
|
|
72
|
+
* @component
|
|
73
|
+
* @param {CheckboxGroupProps} args - The props passed to the CheckboxGroup component.
|
|
74
|
+
*
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
declare const CheckboxGroup: React.NamedExoticComponent<CheckboxGroupProps & _bento_slots.Slots>;
|
|
78
|
+
|
|
79
|
+
export { Checkbox, CheckboxGroup, type CheckboxGroupProps, type CheckboxProps };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as _bento_slots from '@bento/slots';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ControlProps, ControlGroupProps } from '@bento/control';
|
|
4
|
+
import { AriaCheckboxProps, AriaCheckboxGroupProps } from 'react-aria';
|
|
5
|
+
import { ValidationResult } from '@react-types/shared';
|
|
6
|
+
|
|
7
|
+
interface CheckboxProps extends AriaCheckboxProps, Partial<Omit<ControlProps, keyof AriaCheckboxProps>> {
|
|
8
|
+
/** The value of the checkbox, used when submitting an HTML form. */
|
|
9
|
+
value?: string;
|
|
10
|
+
/** The name of the checkbox. */
|
|
11
|
+
name?: string;
|
|
12
|
+
/** A ref for the HTML input element. */
|
|
13
|
+
inputRef?: React.Ref<HTMLInputElement>;
|
|
14
|
+
/** The label for the checkbox. Accepts any renderable node. */
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
/** Whether the checkbox is required or not. */
|
|
17
|
+
isRequired?: boolean;
|
|
18
|
+
/** Whether the input can be selected but not changed by the user. */
|
|
19
|
+
isReadOnly?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the checkbox is disabled or not. Shows that a selection exists,
|
|
22
|
+
* but is not available in that circumstance.
|
|
23
|
+
*/
|
|
24
|
+
isDisabled?: boolean;
|
|
25
|
+
/** Whether the element should receive focus on render. */
|
|
26
|
+
autoFocus?: boolean;
|
|
27
|
+
/** Whether the checkbox is in an indeterminate state. */
|
|
28
|
+
isIndeterminate?: boolean;
|
|
29
|
+
/** Whether the checkbox is in a selected state. */
|
|
30
|
+
isSelected?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The `Checkbox` is a single checkbox option that can be selected by the user.
|
|
34
|
+
*
|
|
35
|
+
* @component
|
|
36
|
+
* @param args - The props {@link CheckboxProps} passed to the Checkbox component.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
declare const Checkbox: React.NamedExoticComponent<CheckboxProps & _bento_slots.Slots>;
|
|
41
|
+
|
|
42
|
+
interface CheckboxGroupProps extends AriaCheckboxGroupProps, Partial<Omit<ControlGroupProps, keyof AriaCheckboxGroupProps>> {
|
|
43
|
+
/** The current value of the checkbox group (controlled). */
|
|
44
|
+
value?: string[];
|
|
45
|
+
/** The default value of the checkbox group (uncontrolled). */
|
|
46
|
+
defaultValue?: string[];
|
|
47
|
+
/** Whether the input is disabled. */
|
|
48
|
+
isDisabled?: boolean;
|
|
49
|
+
/** Whether the input can be selected but not changed by the user. */
|
|
50
|
+
isReadOnly?: boolean;
|
|
51
|
+
/** Whether user input is required on the input before form submission. */
|
|
52
|
+
isRequired?: boolean;
|
|
53
|
+
/** Whether the input value is invalid. */
|
|
54
|
+
isInvalid?: boolean;
|
|
55
|
+
/** The name of the input element, used when submitting an HTML form. */
|
|
56
|
+
name?: string;
|
|
57
|
+
/**
|
|
58
|
+
* The <form> element to associate the input with.
|
|
59
|
+
* The value of this attribute must be the id of a <form> in the same document.
|
|
60
|
+
*/
|
|
61
|
+
form?: string;
|
|
62
|
+
/** Description for the checkbox group. */
|
|
63
|
+
description?: string;
|
|
64
|
+
/** Checkbox children. */
|
|
65
|
+
children?: React.ReactNode;
|
|
66
|
+
/** Error message for the checkbox group. */
|
|
67
|
+
errorMessage?: React.ReactNode | ((val: ValidationResult) => React.ReactNode);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The `CheckboxGroup` allows a user to select items from a list of `Checkbox` components.
|
|
71
|
+
*
|
|
72
|
+
* @component
|
|
73
|
+
* @param {CheckboxGroupProps} args - The props passed to the CheckboxGroup component.
|
|
74
|
+
*
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
declare const CheckboxGroup: React.NamedExoticComponent<CheckboxGroupProps & _bento_slots.Slots>;
|
|
78
|
+
|
|
79
|
+
export { Checkbox, CheckboxGroup, type CheckboxGroupProps, type CheckboxProps };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React2, { useContext, useRef, useMemo } from 'react';
|
|
2
|
+
import { Control, ControlGroup } from '@bento/control';
|
|
3
|
+
import { Icon } from '@bento/icon';
|
|
4
|
+
import { withSlots } from '@bento/slots';
|
|
5
|
+
import { useProps } from '@bento/use-props';
|
|
6
|
+
import { useCheckboxGroupItem, useCheckbox, useHover, useFocusRing, useCheckboxGroup } from 'react-aria';
|
|
7
|
+
import { useObjectRef, mergeRefs, mergeProps } from '@react-aria/utils';
|
|
8
|
+
import { useToggleState, useCheckboxGroupState } from 'react-stately';
|
|
9
|
+
import { useDataAttributes } from '@bento/use-data-attributes';
|
|
10
|
+
|
|
11
|
+
// src/checkbox.tsx
|
|
12
|
+
var CheckboxGroupStateContext = React2.createContext(null);
|
|
13
|
+
|
|
14
|
+
// src/checkbox.tsx
|
|
15
|
+
var Checkbox = withSlots("BentoCheckbox", function Checkbox2(args) {
|
|
16
|
+
const { props, apply } = useProps(args);
|
|
17
|
+
const {
|
|
18
|
+
isRequired = false,
|
|
19
|
+
isIndeterminate = false,
|
|
20
|
+
isDisabled: isDisabledProp = false,
|
|
21
|
+
isSelected: isSelectedProp = false,
|
|
22
|
+
isReadOnly: isReadOnlyProp = false
|
|
23
|
+
} = props;
|
|
24
|
+
const groupState = useContext(CheckboxGroupStateContext);
|
|
25
|
+
const ref = useRef(null);
|
|
26
|
+
const inputRef = useObjectRef(useMemo(() => mergeRefs(ref, props.inputRef), [ref, props.inputRef]));
|
|
27
|
+
let { labelProps, inputProps, isSelected, isReadOnly, isDisabled, isPressed, isInvalid } = groupState ? useCheckboxGroupItem(
|
|
28
|
+
{
|
|
29
|
+
...props,
|
|
30
|
+
// Value is optional for standalone checkboxes, but required for CheckboxGroup items;
|
|
31
|
+
// it's passed explicitly here to avoid typescript error (requires ignore)(recommendation from React Aria).
|
|
32
|
+
value: props.value
|
|
33
|
+
},
|
|
34
|
+
groupState,
|
|
35
|
+
inputRef
|
|
36
|
+
) : useCheckbox(
|
|
37
|
+
{
|
|
38
|
+
...props
|
|
39
|
+
},
|
|
40
|
+
useToggleState(props),
|
|
41
|
+
inputRef
|
|
42
|
+
);
|
|
43
|
+
const interactionDisabled = isDisabledProp || isDisabled || isReadOnly || isReadOnlyProp;
|
|
44
|
+
const { hoverProps, isHovered } = useHover({
|
|
45
|
+
...props,
|
|
46
|
+
isDisabled: interactionDisabled
|
|
47
|
+
});
|
|
48
|
+
const { isFocused, isFocusVisible, focusProps } = useFocusRing();
|
|
49
|
+
return /* @__PURE__ */ React2.createElement(
|
|
50
|
+
Control,
|
|
51
|
+
{
|
|
52
|
+
slot: "control",
|
|
53
|
+
labelProps: mergeProps(labelProps, hoverProps),
|
|
54
|
+
inputProps: mergeProps(inputProps, focusProps),
|
|
55
|
+
label: props.children,
|
|
56
|
+
inputRef,
|
|
57
|
+
"aria-checked": isIndeterminate ? "mixed" : void 0,
|
|
58
|
+
...apply(props, ["isReadOnly", "isSelected", "isIndeterminate", "isDisabled", "value", "autoFocus"]),
|
|
59
|
+
...useDataAttributes({
|
|
60
|
+
selected: isSelected || isSelectedProp,
|
|
61
|
+
pressed: isPressed,
|
|
62
|
+
hovered: isHovered,
|
|
63
|
+
focused: isFocused,
|
|
64
|
+
focusVisible: isFocusVisible,
|
|
65
|
+
disabled: interactionDisabled,
|
|
66
|
+
readOnly: isReadOnly || isReadOnlyProp,
|
|
67
|
+
invalid: isInvalid,
|
|
68
|
+
required: isRequired,
|
|
69
|
+
indeterminate: isIndeterminate
|
|
70
|
+
})
|
|
71
|
+
},
|
|
72
|
+
isIndeterminate ? /* @__PURE__ */ React2.createElement(Icon, { slot: "icon-indeterminate", icon: "checkboxIndeterminate" }, /* @__PURE__ */ React2.createElement("svg", { viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React2.createElement("rect", { x: "6", y: "11", width: "12", height: "2", fill: "currentColor" }))) : isSelected ? /* @__PURE__ */ React2.createElement(Icon, { slot: "icon-checked", icon: "checkboxChecked" }, /* @__PURE__ */ React2.createElement("svg", { viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React2.createElement("path", { d: "M9,16.2L4.8,12l-1.4,1.4L9,19L21,7l-1.4-1.4L9,16.2z", fill: "currentColor" }))) : /* @__PURE__ */ React2.createElement(Icon, { slot: "icon-unchecked", icon: "checkboxUnchecked" }, /* @__PURE__ */ React2.createElement("svg", { width: 24, height: 24, "aria-hidden": "true" }, /* @__PURE__ */ React2.createElement("rect", { x: 4, y: 4, width: 16, height: 16, rx: 3, fill: "none", stroke: "gray", strokeWidth: 2 })))
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
var CheckboxGroup = withSlots("BentoCheckboxGroup", function CheckboxGroup2(args) {
|
|
76
|
+
const { errorMessage, ...restArgs } = args;
|
|
77
|
+
const { props, apply } = useProps(restArgs);
|
|
78
|
+
const state = useCheckboxGroupState(props);
|
|
79
|
+
const { children } = props;
|
|
80
|
+
const { groupProps, labelProps, descriptionProps, errorMessageProps, ...validationResult } = useCheckboxGroup(
|
|
81
|
+
props,
|
|
82
|
+
state
|
|
83
|
+
);
|
|
84
|
+
const displayedErrorMessage = useMemo(
|
|
85
|
+
function getErrorMessage() {
|
|
86
|
+
return typeof errorMessage === "function" ? errorMessage(validationResult) : errorMessage || validationResult.validationErrors.join(", ");
|
|
87
|
+
},
|
|
88
|
+
[errorMessage, validationResult]
|
|
89
|
+
);
|
|
90
|
+
return /* @__PURE__ */ React2.createElement(
|
|
91
|
+
ControlGroup,
|
|
92
|
+
{
|
|
93
|
+
slot: "group",
|
|
94
|
+
labelProps,
|
|
95
|
+
descriptionProps,
|
|
96
|
+
errorMessage: displayedErrorMessage,
|
|
97
|
+
errorMessageProps,
|
|
98
|
+
...groupProps,
|
|
99
|
+
...apply(props, ["isInvalid", "isDisabled", "isReadOnly", "isRequired", "validationBehavior"]),
|
|
100
|
+
...useDataAttributes({
|
|
101
|
+
orientation: props.orientation || "vertical",
|
|
102
|
+
invalid: state.isInvalid,
|
|
103
|
+
disabled: state.isDisabled,
|
|
104
|
+
readonly: state.isReadOnly,
|
|
105
|
+
required: state.isRequired
|
|
106
|
+
})
|
|
107
|
+
},
|
|
108
|
+
/* @__PURE__ */ React2.createElement(CheckboxGroupStateContext.Provider, { value: state }, children)
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export { Checkbox, CheckboxGroup };
|
|
113
|
+
//# sourceMappingURL=index.js.map
|
|
114
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/checkbox-group-state.tsx","../src/checkbox.tsx","../src/checkbox-group.tsx"],"names":["React","Checkbox","withSlots","CheckboxGroup","useProps","useMemo","useDataAttributes"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react';\nimport { CheckboxGroupState } from 'react-stately';\n\nexport const CheckboxGroupStateContext = React.createContext<CheckboxGroupState | null>(null);\n","import React, { useContext, useRef, useMemo } from 'react';\nimport { Control, ControlProps } from '@bento/control';\nimport { Icon } from '@bento/icon';\nimport { withSlots } from '@bento/slots';\nimport { useProps } from '@bento/use-props';\nimport { useFocusRing, useHover, type AriaCheckboxProps, useCheckboxGroupItem, useCheckbox } from 'react-aria';\nimport { mergeProps, mergeRefs, useObjectRef } from '@react-aria/utils';\nimport { useToggleState } from 'react-stately';\nimport { useDataAttributes } from '@bento/use-data-attributes';\nimport { CheckboxGroupStateContext } from './checkbox-group-state';\n\nexport interface CheckboxProps extends AriaCheckboxProps, Partial<Omit<ControlProps, keyof AriaCheckboxProps>> {\n /** The value of the checkbox, used when submitting an HTML form. */\n value?: string;\n\n /** The name of the checkbox. */\n name?: string;\n\n /** A ref for the HTML input element. */\n inputRef?: React.Ref<HTMLInputElement>;\n\n /** The label for the checkbox. Accepts any renderable node. */\n children?: React.ReactNode;\n\n /** Whether the checkbox is required or not. */\n isRequired?: boolean;\n\n /** Whether the input can be selected but not changed by the user. */\n isReadOnly?: boolean;\n\n /**\n * Whether the checkbox is disabled or not. Shows that a selection exists,\n * but is not available in that circumstance.\n */\n isDisabled?: boolean;\n\n /** Whether the element should receive focus on render. */\n autoFocus?: boolean;\n\n /** Whether the checkbox is in an indeterminate state. */\n isIndeterminate?: boolean;\n\n /** Whether the checkbox is in a selected state. */\n isSelected?: boolean;\n}\n\n/**\n * The `Checkbox` is a single checkbox option that can be selected by the user.\n *\n * @component\n * @param args - The props {@link CheckboxProps} passed to the Checkbox component.\n *\n * @public\n */\nexport const Checkbox = withSlots('BentoCheckbox', function Checkbox(args: CheckboxProps) {\n const { props, apply } = useProps(args);\n const {\n isRequired = false,\n isIndeterminate = false,\n isDisabled: isDisabledProp = false,\n isSelected: isSelectedProp = false,\n isReadOnly: isReadOnlyProp = false\n } = props;\n\n const groupState = useContext(CheckboxGroupStateContext);\n\n const ref = useRef<HTMLInputElement>(null);\n const inputRef = useObjectRef(useMemo(() => mergeRefs(ref, props.inputRef), [ref, props.inputRef]));\n\n let { labelProps, inputProps, isSelected, isReadOnly, isDisabled, isPressed, isInvalid } = groupState\n ? useCheckboxGroupItem(\n {\n ...props,\n // Value is optional for standalone checkboxes, but required for CheckboxGroup items;\n // it's passed explicitly here to avoid typescript error (requires ignore)(recommendation from React Aria).\n value: (props as Required<Pick<typeof props, 'value'>>).value\n },\n groupState,\n inputRef\n )\n : useCheckbox(\n {\n ...props\n },\n useToggleState(props),\n inputRef\n );\n\n const interactionDisabled = isDisabledProp || isDisabled || isReadOnly || isReadOnlyProp;\n const { hoverProps, isHovered } = useHover({\n ...props,\n isDisabled: interactionDisabled\n });\n const { isFocused, isFocusVisible, focusProps } = useFocusRing();\n\n return (\n <Control\n slot=\"control\"\n labelProps={mergeProps(labelProps, hoverProps)}\n inputProps={mergeProps(inputProps, focusProps)}\n label={props.children}\n inputRef={inputRef}\n aria-checked={isIndeterminate ? 'mixed' : undefined}\n {...apply(props, ['isReadOnly', 'isSelected', 'isIndeterminate', 'isDisabled', 'value', 'autoFocus'])}\n {...useDataAttributes({\n selected: isSelected || isSelectedProp,\n pressed: isPressed,\n hovered: isHovered,\n focused: isFocused,\n focusVisible: isFocusVisible,\n disabled: interactionDisabled,\n readOnly: isReadOnly || isReadOnlyProp,\n invalid: isInvalid,\n required: isRequired,\n indeterminate: isIndeterminate\n })}\n >\n {isIndeterminate ? (\n <Icon slot=\"icon-indeterminate\" icon=\"checkboxIndeterminate\">\n <svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"6\" y=\"11\" width=\"12\" height=\"2\" fill=\"currentColor\" />\n </svg>\n </Icon>\n ) : isSelected ? (\n <Icon slot=\"icon-checked\" icon=\"checkboxChecked\">\n <svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9,16.2L4.8,12l-1.4,1.4L9,19L21,7l-1.4-1.4L9,16.2z\" fill=\"currentColor\" />\n </svg>\n </Icon>\n ) : (\n <Icon slot=\"icon-unchecked\" icon=\"checkboxUnchecked\">\n <svg width={24} height={24} aria-hidden=\"true\">\n <rect x={4} y={4} width={16} height={16} rx={3} fill=\"none\" stroke=\"gray\" strokeWidth={2} />\n </svg>\n </Icon>\n )}\n </Control>\n );\n});\n","import React, { useMemo } from 'react';\nimport { useProps } from '@bento/use-props';\nimport { ControlGroup, ControlGroupProps } from '@bento/control';\nimport { useDataAttributes } from '@bento/use-data-attributes';\nimport { type ValidationResult } from '@react-types/shared';\nimport { AriaCheckboxGroupProps, useCheckboxGroup } from 'react-aria';\nimport { useCheckboxGroupState } from 'react-stately';\nimport { withSlots } from '@bento/slots';\nimport { CheckboxGroupStateContext } from './checkbox-group-state';\n\nexport interface CheckboxGroupProps\n extends AriaCheckboxGroupProps,\n Partial<Omit<ControlGroupProps, keyof AriaCheckboxGroupProps>> {\n /** The current value of the checkbox group (controlled). */\n value?: string[];\n\n /** The default value of the checkbox group (uncontrolled). */\n defaultValue?: string[];\n\n /** Whether the input is disabled. */\n isDisabled?: boolean;\n\n /** Whether the input can be selected but not changed by the user. */\n isReadOnly?: boolean;\n\n /** Whether user input is required on the input before form submission. */\n isRequired?: boolean;\n\n /** Whether the input value is invalid. */\n isInvalid?: boolean;\n\n /** The name of the input element, used when submitting an HTML form. */\n name?: string;\n\n /**\n * The <form> element to associate the input with.\n * The value of this attribute must be the id of a <form> in the same document.\n */\n form?: string;\n\n /** Description for the checkbox group. */\n description?: string;\n\n /** Checkbox children. */\n children?: React.ReactNode;\n\n /** Error message for the checkbox group. */\n errorMessage?: React.ReactNode | ((val: ValidationResult) => React.ReactNode);\n}\n\n/**\n * The `CheckboxGroup` allows a user to select items from a list of `Checkbox` components.\n *\n * @component\n * @param {CheckboxGroupProps} args - The props passed to the CheckboxGroup component.\n *\n * @public\n */\nexport const CheckboxGroup = withSlots('BentoCheckboxGroup', function CheckboxGroup(args: CheckboxGroupProps) {\n const { errorMessage, ...restArgs } = args;\n const { props, apply } = useProps(restArgs);\n const state = useCheckboxGroupState(props);\n const { children } = props;\n const { groupProps, labelProps, descriptionProps, errorMessageProps, ...validationResult } = useCheckboxGroup(\n props,\n state\n );\n\n const displayedErrorMessage = useMemo(\n function getErrorMessage() {\n return typeof errorMessage === 'function'\n ? errorMessage(validationResult)\n : errorMessage || validationResult.validationErrors.join(', ');\n },\n [errorMessage, validationResult]\n );\n\n return (\n <ControlGroup\n slot=\"group\"\n labelProps={labelProps}\n descriptionProps={descriptionProps}\n errorMessage={displayedErrorMessage}\n errorMessageProps={errorMessageProps}\n {...groupProps}\n {...apply(props, ['isInvalid', 'isDisabled', 'isReadOnly', 'isRequired', 'validationBehavior'])}\n {...useDataAttributes({\n orientation: props.orientation || 'vertical',\n invalid: state.isInvalid,\n disabled: state.isDisabled,\n readonly: state.isReadOnly,\n required: state.isRequired\n })}\n >\n <CheckboxGroupStateContext.Provider value={state}>{children}</CheckboxGroupStateContext.Provider>\n </ControlGroup>\n );\n});\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bento/checkbox",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Checkbox component",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsup-node",
|
|
10
|
+
"lint": "biome lint && tsc",
|
|
11
|
+
"posttest": "npm run lint",
|
|
12
|
+
"pretest": "npm run build",
|
|
13
|
+
"test": "vitest --run",
|
|
14
|
+
"test:watch": "vitest"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/godaddy/bento.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"accessibility",
|
|
22
|
+
"aria",
|
|
23
|
+
"bento",
|
|
24
|
+
"checkbox",
|
|
25
|
+
"component",
|
|
26
|
+
"interactive",
|
|
27
|
+
"library",
|
|
28
|
+
"react"
|
|
29
|
+
],
|
|
30
|
+
"author": "GoDaddy Operating Company, LLC",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/godaddy/bento/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/godaddy/bento#readme",
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"src",
|
|
39
|
+
"package.json"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@bento/control": "^0.1.1",
|
|
43
|
+
"@bento/icon": "^0.1.1",
|
|
44
|
+
"@bento/slots": "^0.1.2",
|
|
45
|
+
"@bento/use-data-attributes": "^0.1.0",
|
|
46
|
+
"@bento/use-props": "^0.1.0",
|
|
47
|
+
"@react-aria/utils": "^3.30.0",
|
|
48
|
+
"react-aria": "^3.44.0",
|
|
49
|
+
"react-stately": "^3.42.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"react": "18.x || 19.x",
|
|
53
|
+
"react-dom": "18.x || 19.x"
|
|
54
|
+
},
|
|
55
|
+
"exports": {
|
|
56
|
+
".": {
|
|
57
|
+
"import": {
|
|
58
|
+
"types": "./dist/index.d.ts",
|
|
59
|
+
"default": "./dist/index.js"
|
|
60
|
+
},
|
|
61
|
+
"require": {
|
|
62
|
+
"types": "./dist/index.d.cts",
|
|
63
|
+
"default": "./dist/index.cjs"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"./package.json": "./package.json"
|
|
67
|
+
},
|
|
68
|
+
"publishConfig": {
|
|
69
|
+
"access": "public",
|
|
70
|
+
"registry": "https://registry.npmjs.org/"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { useProps } from '@bento/use-props';
|
|
3
|
+
import { ControlGroup, ControlGroupProps } from '@bento/control';
|
|
4
|
+
import { useDataAttributes } from '@bento/use-data-attributes';
|
|
5
|
+
import { type ValidationResult } from '@react-types/shared';
|
|
6
|
+
import { AriaCheckboxGroupProps, useCheckboxGroup } from 'react-aria';
|
|
7
|
+
import { useCheckboxGroupState } from 'react-stately';
|
|
8
|
+
import { withSlots } from '@bento/slots';
|
|
9
|
+
import { CheckboxGroupStateContext } from './checkbox-group-state';
|
|
10
|
+
|
|
11
|
+
export interface CheckboxGroupProps
|
|
12
|
+
extends AriaCheckboxGroupProps,
|
|
13
|
+
Partial<Omit<ControlGroupProps, keyof AriaCheckboxGroupProps>> {
|
|
14
|
+
/** The current value of the checkbox group (controlled). */
|
|
15
|
+
value?: string[];
|
|
16
|
+
|
|
17
|
+
/** The default value of the checkbox group (uncontrolled). */
|
|
18
|
+
defaultValue?: string[];
|
|
19
|
+
|
|
20
|
+
/** Whether the input is disabled. */
|
|
21
|
+
isDisabled?: boolean;
|
|
22
|
+
|
|
23
|
+
/** Whether the input can be selected but not changed by the user. */
|
|
24
|
+
isReadOnly?: boolean;
|
|
25
|
+
|
|
26
|
+
/** Whether user input is required on the input before form submission. */
|
|
27
|
+
isRequired?: boolean;
|
|
28
|
+
|
|
29
|
+
/** Whether the input value is invalid. */
|
|
30
|
+
isInvalid?: boolean;
|
|
31
|
+
|
|
32
|
+
/** The name of the input element, used when submitting an HTML form. */
|
|
33
|
+
name?: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The <form> element to associate the input with.
|
|
37
|
+
* The value of this attribute must be the id of a <form> in the same document.
|
|
38
|
+
*/
|
|
39
|
+
form?: string;
|
|
40
|
+
|
|
41
|
+
/** Description for the checkbox group. */
|
|
42
|
+
description?: string;
|
|
43
|
+
|
|
44
|
+
/** Checkbox children. */
|
|
45
|
+
children?: React.ReactNode;
|
|
46
|
+
|
|
47
|
+
/** Error message for the checkbox group. */
|
|
48
|
+
errorMessage?: React.ReactNode | ((val: ValidationResult) => React.ReactNode);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The `CheckboxGroup` allows a user to select items from a list of `Checkbox` components.
|
|
53
|
+
*
|
|
54
|
+
* @component
|
|
55
|
+
* @param {CheckboxGroupProps} args - The props passed to the CheckboxGroup component.
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
export const CheckboxGroup = withSlots('BentoCheckboxGroup', function CheckboxGroup(args: CheckboxGroupProps) {
|
|
60
|
+
const { errorMessage, ...restArgs } = args;
|
|
61
|
+
const { props, apply } = useProps(restArgs);
|
|
62
|
+
const state = useCheckboxGroupState(props);
|
|
63
|
+
const { children } = props;
|
|
64
|
+
const { groupProps, labelProps, descriptionProps, errorMessageProps, ...validationResult } = useCheckboxGroup(
|
|
65
|
+
props,
|
|
66
|
+
state
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const displayedErrorMessage = useMemo(
|
|
70
|
+
function getErrorMessage() {
|
|
71
|
+
return typeof errorMessage === 'function'
|
|
72
|
+
? errorMessage(validationResult)
|
|
73
|
+
: errorMessage || validationResult.validationErrors.join(', ');
|
|
74
|
+
},
|
|
75
|
+
[errorMessage, validationResult]
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<ControlGroup
|
|
80
|
+
slot="group"
|
|
81
|
+
labelProps={labelProps}
|
|
82
|
+
descriptionProps={descriptionProps}
|
|
83
|
+
errorMessage={displayedErrorMessage}
|
|
84
|
+
errorMessageProps={errorMessageProps}
|
|
85
|
+
{...groupProps}
|
|
86
|
+
{...apply(props, ['isInvalid', 'isDisabled', 'isReadOnly', 'isRequired', 'validationBehavior'])}
|
|
87
|
+
{...useDataAttributes({
|
|
88
|
+
orientation: props.orientation || 'vertical',
|
|
89
|
+
invalid: state.isInvalid,
|
|
90
|
+
disabled: state.isDisabled,
|
|
91
|
+
readonly: state.isReadOnly,
|
|
92
|
+
required: state.isRequired
|
|
93
|
+
})}
|
|
94
|
+
>
|
|
95
|
+
<CheckboxGroupStateContext.Provider value={state}>{children}</CheckboxGroupStateContext.Provider>
|
|
96
|
+
</ControlGroup>
|
|
97
|
+
);
|
|
98
|
+
});
|
package/src/checkbox.tsx
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React, { useContext, useRef, useMemo } from 'react';
|
|
2
|
+
import { Control, ControlProps } from '@bento/control';
|
|
3
|
+
import { Icon } from '@bento/icon';
|
|
4
|
+
import { withSlots } from '@bento/slots';
|
|
5
|
+
import { useProps } from '@bento/use-props';
|
|
6
|
+
import { useFocusRing, useHover, type AriaCheckboxProps, useCheckboxGroupItem, useCheckbox } from 'react-aria';
|
|
7
|
+
import { mergeProps, mergeRefs, useObjectRef } from '@react-aria/utils';
|
|
8
|
+
import { useToggleState } from 'react-stately';
|
|
9
|
+
import { useDataAttributes } from '@bento/use-data-attributes';
|
|
10
|
+
import { CheckboxGroupStateContext } from './checkbox-group-state';
|
|
11
|
+
|
|
12
|
+
export interface CheckboxProps extends AriaCheckboxProps, Partial<Omit<ControlProps, keyof AriaCheckboxProps>> {
|
|
13
|
+
/** The value of the checkbox, used when submitting an HTML form. */
|
|
14
|
+
value?: string;
|
|
15
|
+
|
|
16
|
+
/** The name of the checkbox. */
|
|
17
|
+
name?: string;
|
|
18
|
+
|
|
19
|
+
/** A ref for the HTML input element. */
|
|
20
|
+
inputRef?: React.Ref<HTMLInputElement>;
|
|
21
|
+
|
|
22
|
+
/** The label for the checkbox. Accepts any renderable node. */
|
|
23
|
+
children?: React.ReactNode;
|
|
24
|
+
|
|
25
|
+
/** Whether the checkbox is required or not. */
|
|
26
|
+
isRequired?: boolean;
|
|
27
|
+
|
|
28
|
+
/** Whether the input can be selected but not changed by the user. */
|
|
29
|
+
isReadOnly?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Whether the checkbox is disabled or not. Shows that a selection exists,
|
|
33
|
+
* but is not available in that circumstance.
|
|
34
|
+
*/
|
|
35
|
+
isDisabled?: boolean;
|
|
36
|
+
|
|
37
|
+
/** Whether the element should receive focus on render. */
|
|
38
|
+
autoFocus?: boolean;
|
|
39
|
+
|
|
40
|
+
/** Whether the checkbox is in an indeterminate state. */
|
|
41
|
+
isIndeterminate?: boolean;
|
|
42
|
+
|
|
43
|
+
/** Whether the checkbox is in a selected state. */
|
|
44
|
+
isSelected?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The `Checkbox` is a single checkbox option that can be selected by the user.
|
|
49
|
+
*
|
|
50
|
+
* @component
|
|
51
|
+
* @param args - The props {@link CheckboxProps} passed to the Checkbox component.
|
|
52
|
+
*
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
export const Checkbox = withSlots('BentoCheckbox', function Checkbox(args: CheckboxProps) {
|
|
56
|
+
const { props, apply } = useProps(args);
|
|
57
|
+
const {
|
|
58
|
+
isRequired = false,
|
|
59
|
+
isIndeterminate = false,
|
|
60
|
+
isDisabled: isDisabledProp = false,
|
|
61
|
+
isSelected: isSelectedProp = false,
|
|
62
|
+
isReadOnly: isReadOnlyProp = false
|
|
63
|
+
} = props;
|
|
64
|
+
|
|
65
|
+
const groupState = useContext(CheckboxGroupStateContext);
|
|
66
|
+
|
|
67
|
+
const ref = useRef<HTMLInputElement>(null);
|
|
68
|
+
const inputRef = useObjectRef(useMemo(() => mergeRefs(ref, props.inputRef), [ref, props.inputRef]));
|
|
69
|
+
|
|
70
|
+
let { labelProps, inputProps, isSelected, isReadOnly, isDisabled, isPressed, isInvalid } = groupState
|
|
71
|
+
? useCheckboxGroupItem(
|
|
72
|
+
{
|
|
73
|
+
...props,
|
|
74
|
+
// Value is optional for standalone checkboxes, but required for CheckboxGroup items;
|
|
75
|
+
// it's passed explicitly here to avoid typescript error (requires ignore)(recommendation from React Aria).
|
|
76
|
+
value: (props as Required<Pick<typeof props, 'value'>>).value
|
|
77
|
+
},
|
|
78
|
+
groupState,
|
|
79
|
+
inputRef
|
|
80
|
+
)
|
|
81
|
+
: useCheckbox(
|
|
82
|
+
{
|
|
83
|
+
...props
|
|
84
|
+
},
|
|
85
|
+
useToggleState(props),
|
|
86
|
+
inputRef
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const interactionDisabled = isDisabledProp || isDisabled || isReadOnly || isReadOnlyProp;
|
|
90
|
+
const { hoverProps, isHovered } = useHover({
|
|
91
|
+
...props,
|
|
92
|
+
isDisabled: interactionDisabled
|
|
93
|
+
});
|
|
94
|
+
const { isFocused, isFocusVisible, focusProps } = useFocusRing();
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<Control
|
|
98
|
+
slot="control"
|
|
99
|
+
labelProps={mergeProps(labelProps, hoverProps)}
|
|
100
|
+
inputProps={mergeProps(inputProps, focusProps)}
|
|
101
|
+
label={props.children}
|
|
102
|
+
inputRef={inputRef}
|
|
103
|
+
aria-checked={isIndeterminate ? 'mixed' : undefined}
|
|
104
|
+
{...apply(props, ['isReadOnly', 'isSelected', 'isIndeterminate', 'isDisabled', 'value', 'autoFocus'])}
|
|
105
|
+
{...useDataAttributes({
|
|
106
|
+
selected: isSelected || isSelectedProp,
|
|
107
|
+
pressed: isPressed,
|
|
108
|
+
hovered: isHovered,
|
|
109
|
+
focused: isFocused,
|
|
110
|
+
focusVisible: isFocusVisible,
|
|
111
|
+
disabled: interactionDisabled,
|
|
112
|
+
readOnly: isReadOnly || isReadOnlyProp,
|
|
113
|
+
invalid: isInvalid,
|
|
114
|
+
required: isRequired,
|
|
115
|
+
indeterminate: isIndeterminate
|
|
116
|
+
})}
|
|
117
|
+
>
|
|
118
|
+
{isIndeterminate ? (
|
|
119
|
+
<Icon slot="icon-indeterminate" icon="checkboxIndeterminate">
|
|
120
|
+
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
121
|
+
<rect x="6" y="11" width="12" height="2" fill="currentColor" />
|
|
122
|
+
</svg>
|
|
123
|
+
</Icon>
|
|
124
|
+
) : isSelected ? (
|
|
125
|
+
<Icon slot="icon-checked" icon="checkboxChecked">
|
|
126
|
+
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
127
|
+
<path d="M9,16.2L4.8,12l-1.4,1.4L9,19L21,7l-1.4-1.4L9,16.2z" fill="currentColor" />
|
|
128
|
+
</svg>
|
|
129
|
+
</Icon>
|
|
130
|
+
) : (
|
|
131
|
+
<Icon slot="icon-unchecked" icon="checkboxUnchecked">
|
|
132
|
+
<svg width={24} height={24} aria-hidden="true">
|
|
133
|
+
<rect x={4} y={4} width={16} height={16} rx={3} fill="none" stroke="gray" strokeWidth={2} />
|
|
134
|
+
</svg>
|
|
135
|
+
</Icon>
|
|
136
|
+
)}
|
|
137
|
+
</Control>
|
|
138
|
+
);
|
|
139
|
+
});
|
package/src/index.tsx
ADDED