@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 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"]}
@@ -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 };
@@ -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,4 @@
1
+ import React from 'react';
2
+ import { CheckboxGroupState } from 'react-stately';
3
+
4
+ export const CheckboxGroupStateContext = React.createContext<CheckboxGroupState | null>(null);
@@ -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
+ });
@@ -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
@@ -0,0 +1,2 @@
1
+ export * from './checkbox.tsx';
2
+ export * from './checkbox-group.tsx';