@simplybusiness/mobius 5.3.1 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/cjs/components/Checkbox/Checkbox.js +16 -22
- package/dist/cjs/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/cjs/components/Checkbox/CheckboxGroup.js +29 -11
- package/dist/cjs/components/Checkbox/CheckboxGroup.js.map +1 -1
- package/dist/cjs/components/Combobox/Combobox.js +129 -0
- package/dist/cjs/components/Combobox/Combobox.js.map +1 -0
- package/dist/cjs/components/Combobox/fixtures.js +244 -0
- package/dist/cjs/components/Combobox/fixtures.js.map +1 -0
- package/dist/cjs/components/Combobox/index.js +21 -0
- package/dist/cjs/components/Combobox/index.js.map +1 -0
- package/dist/cjs/components/Combobox/types.js +6 -0
- package/dist/cjs/components/Combobox/types.js.map +1 -0
- package/dist/cjs/components/index.js +1 -0
- package/dist/cjs/components/index.js.map +1 -1
- package/dist/cjs/hooks/index.js +1 -0
- package/dist/cjs/hooks/index.js.map +1 -1
- package/dist/cjs/hooks/useRenderCount/index.js +20 -0
- package/dist/cjs/hooks/useRenderCount/index.js.map +1 -0
- package/dist/cjs/hooks/useRenderCount/useRenderCount.js +20 -0
- package/dist/cjs/hooks/useRenderCount/useRenderCount.js.map +1 -0
- package/dist/cjs/hooks/useTextField/useTextField.js +1 -0
- package/dist/cjs/hooks/useTextField/useTextField.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/components/Checkbox/Checkbox.js +17 -23
- package/dist/esm/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/esm/components/Checkbox/CheckboxGroup.js +29 -11
- package/dist/esm/components/Checkbox/CheckboxGroup.js.map +1 -1
- package/dist/esm/components/Checkbox/types.js.map +1 -1
- package/dist/esm/components/Combobox/Combobox.js +114 -0
- package/dist/esm/components/Combobox/Combobox.js.map +1 -0
- package/dist/esm/components/Combobox/fixtures.js +226 -0
- package/dist/esm/components/Combobox/fixtures.js.map +1 -0
- package/dist/esm/components/Combobox/index.js +4 -0
- package/dist/esm/components/Combobox/index.js.map +1 -0
- package/dist/esm/components/Combobox/types.js +3 -0
- package/dist/esm/components/Combobox/types.js.map +1 -0
- package/dist/esm/components/index.js +1 -0
- package/dist/esm/components/index.js.map +1 -1
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/index.js.map +1 -1
- package/dist/esm/hooks/useRenderCount/index.js +3 -0
- package/dist/esm/hooks/useRenderCount/index.js.map +1 -0
- package/dist/esm/hooks/useRenderCount/useRenderCount.js +10 -0
- package/dist/esm/hooks/useRenderCount/useRenderCount.js.map +1 -0
- package/dist/esm/hooks/useTextField/types.js.map +1 -1
- package/dist/esm/hooks/useTextField/useTextField.js +1 -0
- package/dist/esm/hooks/useTextField/useTextField.js.map +1 -1
- package/dist/types/components/Checkbox/CheckboxGroup.stories.d.ts +1 -0
- package/dist/types/components/Checkbox/types.d.ts +10 -6
- package/dist/types/components/Combobox/Combobox.d.ts +3 -0
- package/dist/types/components/Combobox/Combobox.stories.d.ts +7 -0
- package/dist/types/components/Combobox/Combobox.test.d.ts +1 -0
- package/dist/types/components/Combobox/fixtures.d.ts +5 -0
- package/dist/types/components/Combobox/index.d.ts +2 -0
- package/dist/types/components/Combobox/types.d.ts +16 -0
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/hooks/index.d.ts +1 -0
- package/dist/types/hooks/useRenderCount/index.d.ts +1 -0
- package/dist/types/hooks/useRenderCount/useRenderCount.d.ts +1 -0
- package/dist/types/hooks/useRenderCount/useRenderCount.test.d.ts +1 -0
- package/dist/types/hooks/useTextField/types.d.ts +3 -2
- package/package.json +17 -17
- package/src/components/Checkbox/Checkbox.tsx +18 -28
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +15 -0
- package/src/components/Checkbox/CheckboxGroup.test.tsx +107 -1
- package/src/components/Checkbox/CheckboxGroup.tsx +45 -15
- package/src/components/Checkbox/types.ts +13 -6
- package/src/components/Combobox/Combobox.css +30 -0
- package/src/components/Combobox/Combobox.stories.tsx +26 -0
- package/src/components/Combobox/Combobox.test.tsx +578 -0
- package/src/components/Combobox/Combobox.tsx +154 -0
- package/src/components/Combobox/fixtures.tsx +93 -0
- package/src/components/Combobox/index.tsx +2 -0
- package/src/components/Combobox/types.tsx +20 -0
- package/src/components/index.tsx +1 -0
- package/src/hooks/index.tsx +1 -0
- package/src/hooks/useRenderCount/index.ts +1 -0
- package/src/hooks/useRenderCount/useRenderCount.test.ts +26 -0
- package/src/hooks/useRenderCount/useRenderCount.ts +9 -0
- package/src/hooks/useTextField/types.tsx +7 -1
- package/src/hooks/useTextField/useTextField.test.tsx +1 -0
- package/src/hooks/useTextField/useTextField.tsx +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { forwardRef, useRef, useState,
|
|
3
|
+
import { forwardRef, useRef, useId, useState, useEffect } from "react";
|
|
4
4
|
import classNames from "classnames/dedupe";
|
|
5
5
|
import { squareTick, square } from "@simplybusiness/icons";
|
|
6
6
|
import { ErrorMessage } from "../ErrorMessage";
|
|
@@ -9,18 +9,27 @@ import { useValidationClasses } from "../../hooks";
|
|
|
9
9
|
import { Icon } from "../Icon";
|
|
10
10
|
import { Stack } from "../Stack";
|
|
11
11
|
export const Checkbox = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
12
|
-
const { id, label, isDisabled, isRequired, validationState, isInvalid, onChange, className, errorMessage, defaultSelected = false, isReadOnly, name, value, ["aria-describedby"]: ariaDescribedBy, ...rest } = props;
|
|
13
|
-
const [
|
|
12
|
+
const { id, label, isDisabled, isRequired, validationState, isInvalid, onChange, className, errorMessage, selected, defaultSelected = false, isReadOnly, isLastItem, name, value, ["aria-describedby"]: ariaDescribedBy, ...rest } = props;
|
|
13
|
+
const [checked, setChecked] = useState(defaultSelected);
|
|
14
14
|
const fallbackRef = useRef(null);
|
|
15
15
|
const refObj = ref || fallbackRef;
|
|
16
16
|
const inputId = useId();
|
|
17
|
+
const isControlled = typeof selected === "boolean";
|
|
18
|
+
useEffect(()=>{
|
|
19
|
+
if (isControlled) {
|
|
20
|
+
setChecked(selected);
|
|
21
|
+
}
|
|
22
|
+
}, [
|
|
23
|
+
selected,
|
|
24
|
+
isControlled
|
|
25
|
+
]);
|
|
17
26
|
const validationClasses = useValidationClasses({
|
|
18
27
|
validationState,
|
|
19
28
|
isInvalid
|
|
20
29
|
});
|
|
21
30
|
const sharedClasses = classNames({
|
|
22
31
|
"--is-disabled": isDisabled,
|
|
23
|
-
"--is-selected":
|
|
32
|
+
"--is-selected": checked,
|
|
24
33
|
"--is-required": typeof isRequired === "boolean" && isRequired,
|
|
25
34
|
"--is-optional": typeof isRequired === "boolean" && !isRequired
|
|
26
35
|
}, validationClasses);
|
|
@@ -36,23 +45,10 @@ export const Checkbox = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
36
45
|
ariaDescribedBy
|
|
37
46
|
]);
|
|
38
47
|
const labelId = useId();
|
|
39
|
-
const toggleState = ()=>{
|
|
40
|
-
setSelected(!selected);
|
|
41
|
-
};
|
|
42
|
-
const handleClick = (event)=>{
|
|
43
|
-
const isMouseEvent = event.clientX;
|
|
44
|
-
if (isMouseEvent) {
|
|
45
|
-
toggleState();
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
48
|
const handleChange = (event)=>{
|
|
49
|
+
setChecked(!checked);
|
|
49
50
|
if (onChange) {
|
|
50
|
-
onChange(event);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
const handleKeyDown = (event)=>{
|
|
54
|
-
if (event.code === "Space") {
|
|
55
|
-
toggleState();
|
|
51
|
+
onChange(event, isLastItem);
|
|
56
52
|
}
|
|
57
53
|
};
|
|
58
54
|
return /*#__PURE__*/ _jsxs(Stack, {
|
|
@@ -71,11 +67,9 @@ export const Checkbox = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
71
67
|
disabled: isDisabled,
|
|
72
68
|
ref: refObj,
|
|
73
69
|
className: inputClasses,
|
|
74
|
-
onClick: handleClick,
|
|
75
70
|
onChange: handleChange,
|
|
76
|
-
onKeyDown: handleKeyDown,
|
|
77
71
|
type: "checkbox",
|
|
78
|
-
|
|
72
|
+
checked: checked,
|
|
79
73
|
required: isRequired,
|
|
80
74
|
id: id || inputId,
|
|
81
75
|
name: name,
|
|
@@ -83,7 +77,7 @@ export const Checkbox = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
83
77
|
...rest
|
|
84
78
|
}),
|
|
85
79
|
/*#__PURE__*/ _jsx(Icon, {
|
|
86
|
-
icon:
|
|
80
|
+
icon: checked ? squareTick : square,
|
|
87
81
|
size: "md",
|
|
88
82
|
className: iconClasses
|
|
89
83
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ChangeEvent,\n forwardRef,\n useRef,\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n ChangeEvent,\n forwardRef,\n useRef,\n useId,\n useState,\n useEffect,\n} from \"react\";\nimport classNames from \"classnames/dedupe\";\nimport { squareTick, square } from \"@simplybusiness/icons\";\nimport { ErrorMessage } from \"../ErrorMessage\";\nimport { ForwardedRefComponent } from \"../../types/components\";\nimport { CheckboxElementType, CheckboxProps, CheckboxRef } from \"./types\";\nimport { spaceDelimitedList } from \"../../utils/spaceDelimitedList\";\nimport { useValidationClasses } from \"../../hooks\";\nimport { Icon } from \"../Icon\";\nimport { Stack } from \"../Stack\";\n\nexport const Checkbox: ForwardedRefComponent<\n CheckboxProps,\n CheckboxElementType\n> = forwardRef((props: CheckboxProps, ref: CheckboxRef) => {\n const {\n id,\n label,\n isDisabled,\n isRequired,\n validationState,\n isInvalid,\n onChange,\n className,\n errorMessage,\n selected,\n defaultSelected = false,\n isReadOnly,\n isLastItem,\n name,\n value,\n [\"aria-describedby\"]: ariaDescribedBy,\n ...rest\n } = props;\n const [checked, setChecked] = useState<boolean>(defaultSelected);\n const fallbackRef = useRef<HTMLInputElement>(null);\n const refObj = ref || fallbackRef;\n const inputId = useId();\n\n const isControlled = typeof selected === \"boolean\";\n useEffect(() => {\n if (isControlled) {\n setChecked(selected);\n }\n }, [selected, isControlled]);\n\n const validationClasses = useValidationClasses({\n validationState,\n isInvalid,\n });\n const sharedClasses = classNames(\n {\n \"--is-disabled\": isDisabled,\n \"--is-selected\": checked,\n \"--is-required\": typeof isRequired === \"boolean\" && isRequired,\n \"--is-optional\": typeof isRequired === \"boolean\" && !isRequired,\n },\n validationClasses,\n );\n // Append an additional wrapper class name to differenitate from input\n const wrapperClasses = classNames(\n \"mobius\",\n \"mobius-checkbox\",\n sharedClasses,\n className,\n );\n const labelClasses = classNames(\"mobius-checkbox__label\", sharedClasses);\n const inputClasses = classNames(\"mobius-checkbox__input\", sharedClasses);\n const iconClasses = classNames(\"mobius-checkbox__icon\", sharedClasses);\n const errorMessageId = useId();\n const shouldErrorMessageShow = errorMessage ? errorMessageId : undefined;\n const describedBy = spaceDelimitedList([\n shouldErrorMessageShow,\n ariaDescribedBy,\n ]);\n const labelId = useId();\n\n const handleChange = (event: ChangeEvent<CheckboxElementType>) => {\n setChecked(!checked);\n if (onChange) {\n onChange(event, isLastItem);\n }\n };\n\n return (\n <Stack gap=\"xs\" className={wrapperClasses}>\n <label className={labelClasses}>\n <input\n aria-describedby={describedBy}\n aria-errormessage={shouldErrorMessageShow}\n aria-invalid={isInvalid}\n aria-labelledby={labelId}\n readOnly={isReadOnly}\n disabled={isDisabled}\n ref={refObj}\n className={inputClasses}\n onChange={handleChange}\n type=\"checkbox\"\n checked={checked}\n required={isRequired}\n id={id || inputId}\n name={name}\n value={value}\n {...rest}\n />\n <Icon\n icon={checked ? squareTick : square}\n size=\"md\"\n className={iconClasses}\n />\n <span id={labelId} className=\"mobius-checkbox__visible-label\">\n {label}\n </span>\n </label>\n <ErrorMessage id={errorMessageId} errorMessage={errorMessage} />\n </Stack>\n );\n});\n"],"names":["forwardRef","useRef","useId","useState","useEffect","classNames","squareTick","square","ErrorMessage","spaceDelimitedList","useValidationClasses","Icon","Stack","Checkbox","props","ref","id","label","isDisabled","isRequired","validationState","isInvalid","onChange","className","errorMessage","selected","defaultSelected","isReadOnly","isLastItem","name","value","ariaDescribedBy","rest","checked","setChecked","fallbackRef","refObj","inputId","isControlled","validationClasses","sharedClasses","wrapperClasses","labelClasses","inputClasses","iconClasses","errorMessageId","shouldErrorMessageShow","undefined","describedBy","labelId","handleChange","event","gap","input","aria-describedby","aria-errormessage","aria-invalid","aria-labelledby","readOnly","disabled","type","required","icon","size","span"],"mappings":"AAAA;;AAEA,SAEEA,UAAU,EACVC,MAAM,EACNC,KAAK,EACLC,QAAQ,EACRC,SAAS,QACJ,QAAQ;AACf,OAAOC,gBAAgB,oBAAoB;AAC3C,SAASC,UAAU,EAAEC,MAAM,QAAQ,wBAAwB;AAC3D,SAASC,YAAY,QAAQ,kBAAkB;AAG/C,SAASC,kBAAkB,QAAQ,iCAAiC;AACpE,SAASC,oBAAoB,QAAQ,cAAc;AACnD,SAASC,IAAI,QAAQ,UAAU;AAC/B,SAASC,KAAK,QAAQ,WAAW;AAEjC,OAAO,MAAMC,yBAGTb,WAAW,CAACc,OAAsBC;IACpC,MAAM,EACJC,EAAE,EACFC,KAAK,EACLC,UAAU,EACVC,UAAU,EACVC,eAAe,EACfC,SAAS,EACTC,QAAQ,EACRC,SAAS,EACTC,YAAY,EACZC,QAAQ,EACRC,kBAAkB,KAAK,EACvBC,UAAU,EACVC,UAAU,EACVC,IAAI,EACJC,KAAK,EACL,CAAC,mBAAmB,EAAEC,eAAe,EACrC,GAAGC,MACJ,GAAGlB;IACJ,MAAM,CAACmB,SAASC,WAAW,GAAG/B,SAAkBuB;IAChD,MAAMS,cAAclC,OAAyB;IAC7C,MAAMmC,SAASrB,OAAOoB;IACtB,MAAME,UAAUnC;IAEhB,MAAMoC,eAAe,OAAOb,aAAa;IACzCrB,UAAU;QACR,IAAIkC,cAAc;YAChBJ,WAAWT;QACb;IACF,GAAG;QAACA;QAAUa;KAAa;IAE3B,MAAMC,oBAAoB7B,qBAAqB;QAC7CU;QACAC;IACF;IACA,MAAMmB,gBAAgBnC,WACpB;QACE,iBAAiBa;QACjB,iBAAiBe;QACjB,iBAAiB,OAAOd,eAAe,aAAaA;QACpD,iBAAiB,OAAOA,eAAe,aAAa,CAACA;IACvD,GACAoB;IAEF,sEAAsE;IACtE,MAAME,iBAAiBpC,WACrB,UACA,mBACAmC,eACAjB;IAEF,MAAMmB,eAAerC,WAAW,0BAA0BmC;IAC1D,MAAMG,eAAetC,WAAW,0BAA0BmC;IAC1D,MAAMI,cAAcvC,WAAW,yBAAyBmC;IACxD,MAAMK,iBAAiB3C;IACvB,MAAM4C,yBAAyBtB,eAAeqB,iBAAiBE;IAC/D,MAAMC,cAAcvC,mBAAmB;QACrCqC;QACAf;KACD;IACD,MAAMkB,UAAU/C;IAEhB,MAAMgD,eAAe,CAACC;QACpBjB,WAAW,CAACD;QACZ,IAAIX,UAAU;YACZA,SAAS6B,OAAOvB;QAClB;IACF;IAEA,qBACE,MAAChB;QAAMwC,KAAI;QAAK7B,WAAWkB;;0BACzB,MAACxB;gBAAMM,WAAWmB;;kCAChB,KAACW;wBACCC,oBAAkBN;wBAClBO,qBAAmBT;wBACnBU,gBAAcnC;wBACdoC,mBAAiBR;wBACjBS,UAAU/B;wBACVgC,UAAUzC;wBACVH,KAAKqB;wBACLb,WAAWoB;wBACXrB,UAAU4B;wBACVU,MAAK;wBACL3B,SAASA;wBACT4B,UAAU1C;wBACVH,IAAIA,MAAMqB;wBACVR,MAAMA;wBACNC,OAAOA;wBACN,GAAGE,IAAI;;kCAEV,KAACrB;wBACCmD,MAAM7B,UAAU3B,aAAaC;wBAC7BwD,MAAK;wBACLxC,WAAWqB;;kCAEb,KAACoB;wBAAKhD,IAAIiC;wBAAS1B,WAAU;kCAC1BN;;;;0BAGL,KAACT;gBAAaQ,IAAI6B;gBAAgBrB,cAAcA;;;;AAGtD,GAAG"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Children, forwardRef, cloneElement, isValidElement, useId, useState, useEffect } from "react";
|
|
4
3
|
import classNames from "classnames/dedupe";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { Children, cloneElement, forwardRef, isValidElement, useEffect, useId, useState } from "react";
|
|
5
|
+
import { useRenderCount, useValidationClasses } from "../../hooks";
|
|
7
6
|
import { spaceDelimitedList } from "../../utils/spaceDelimitedList";
|
|
8
|
-
import {
|
|
7
|
+
import { ErrorMessage } from "../ErrorMessage";
|
|
8
|
+
import { Label } from "../Label";
|
|
9
|
+
import { Checkbox } from "./Checkbox";
|
|
9
10
|
export const CheckboxGroup = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
10
|
-
const { label, isDisabled = false, isRequired, validationState, isInvalid, orientation = "vertical", onChange, className, errorMessage, children, defaultValue = [], isReadOnly, itemsPerRow, ...rest } = props;
|
|
11
|
+
const { label, isDisabled = false, isRequired, validationState, isInvalid, orientation = "vertical", onChange, className, errorMessage, children, defaultValue = [], isReadOnly, itemsPerRow, lastItemDisables = false, ...rest } = props;
|
|
11
12
|
const [selected, setSelected] = useState(defaultValue);
|
|
12
13
|
const checkboxGroupClasses = classNames("mobius", "mobius-checkbox-group", className, {
|
|
13
14
|
"--is-horizontal": orientation === "horizontal",
|
|
@@ -29,11 +30,17 @@ export const CheckboxGroup = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
29
30
|
props["aria-describedby"]
|
|
30
31
|
]);
|
|
31
32
|
const labelId = useId();
|
|
32
|
-
const handleChange = (event)=>{
|
|
33
|
+
const handleChange = (event, isLastItem = false)=>{
|
|
33
34
|
const { target: { value, checked } } = event;
|
|
34
35
|
if (!checked) {
|
|
35
36
|
setSelected(selected.filter((item)=>item !== value));
|
|
36
37
|
}
|
|
38
|
+
if (checked && lastItemDisables && isLastItem) {
|
|
39
|
+
setSelected([
|
|
40
|
+
value
|
|
41
|
+
]);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
37
44
|
if (checked) {
|
|
38
45
|
setSelected([
|
|
39
46
|
...selected,
|
|
@@ -41,14 +48,21 @@ export const CheckboxGroup = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
41
48
|
]);
|
|
42
49
|
}
|
|
43
50
|
};
|
|
51
|
+
// HACK: This is a workaround to ensure that the onChange event is not
|
|
52
|
+
// fired on the initial render.
|
|
53
|
+
const renderCount = useRenderCount();
|
|
44
54
|
useEffect(()=>{
|
|
45
|
-
if (onChange) {
|
|
55
|
+
if (onChange && renderCount > 1) {
|
|
46
56
|
onChange(selected);
|
|
47
57
|
}
|
|
48
58
|
}, [
|
|
49
59
|
selected,
|
|
50
|
-
onChange
|
|
60
|
+
onChange,
|
|
61
|
+
renderCount
|
|
51
62
|
]);
|
|
63
|
+
const childrenArray = Children.toArray(children);
|
|
64
|
+
const lastCheckbox = childrenArray.filter((child)=>/*#__PURE__*/ isValidElement(child) && child.type === Checkbox).pop();
|
|
65
|
+
const lastCheckboxIsChecked = lastCheckbox && selected.includes(lastCheckbox.props.value);
|
|
52
66
|
return /*#__PURE__*/ _jsxs("div", {
|
|
53
67
|
...rest,
|
|
54
68
|
"aria-labelledby": props["aria-labelledby"] || labelId,
|
|
@@ -67,14 +81,18 @@ export const CheckboxGroup = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
67
81
|
}),
|
|
68
82
|
/*#__PURE__*/ _jsx("div", {
|
|
69
83
|
className: "mobius-checkbox-group__wrapper",
|
|
70
|
-
children:
|
|
84
|
+
children: childrenArray.map((child)=>{
|
|
71
85
|
if (/*#__PURE__*/ isValidElement(child)) {
|
|
86
|
+
// lastItemDisables support
|
|
87
|
+
const isLastItem = child === lastCheckbox;
|
|
88
|
+
const isChildDisabled = isDisabled || lastItemDisables && lastCheckboxIsChecked && !isLastItem;
|
|
72
89
|
return /*#__PURE__*/ cloneElement(child, {
|
|
73
|
-
isDisabled,
|
|
90
|
+
isDisabled: isChildDisabled,
|
|
74
91
|
isRequired,
|
|
75
92
|
isReadOnly,
|
|
76
93
|
isInvalid,
|
|
77
|
-
|
|
94
|
+
isLastItem,
|
|
95
|
+
selected: selected.includes(child.props.value),
|
|
78
96
|
onChange: handleChange,
|
|
79
97
|
"aria-describedby": describedBy
|
|
80
98
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Checkbox/CheckboxGroup.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Checkbox/CheckboxGroup.tsx"],"sourcesContent":["\"use client\";\n\nimport classNames from \"classnames/dedupe\";\nimport {\n type ChangeEvent,\n type ReactElement,\n Children,\n cloneElement,\n forwardRef,\n isValidElement,\n useEffect,\n useId,\n useState,\n} from \"react\";\nimport { useRenderCount, useValidationClasses } from \"../../hooks\";\nimport { ForwardedRefComponent } from \"../../types/components\";\nimport { spaceDelimitedList } from \"../../utils/spaceDelimitedList\";\nimport { ErrorMessage } from \"../ErrorMessage\";\nimport { Label } from \"../Label\";\nimport { Checkbox } from \"./Checkbox\";\nimport {\n CheckboxElementType,\n CheckboxGroupElementType,\n CheckboxGroupProps,\n CheckboxGroupRef,\n} from \"./types\";\n\nexport const CheckboxGroup: ForwardedRefComponent<\n CheckboxGroupProps,\n CheckboxGroupElementType\n> = forwardRef((props: CheckboxGroupProps, ref: CheckboxGroupRef) => {\n const {\n label,\n isDisabled = false,\n isRequired,\n validationState,\n isInvalid,\n orientation = \"vertical\",\n onChange,\n className,\n errorMessage,\n children,\n defaultValue = [],\n isReadOnly,\n itemsPerRow,\n lastItemDisables = false,\n ...rest\n } = props;\n const [selected, setSelected] = useState<string[]>(defaultValue);\n const checkboxGroupClasses = classNames(\n \"mobius\",\n \"mobius-checkbox-group\",\n className,\n {\n \"--is-horizontal\": orientation === \"horizontal\",\n \"--is-vertical\": orientation === \"vertical\",\n \"--is-required\": typeof isRequired === \"boolean\" && isRequired,\n \"--is-optional\": typeof isRequired === \"boolean\" && !isRequired,\n },\n );\n const validationClasses = useValidationClasses({\n validationState,\n isInvalid,\n });\n const labelClasses = classNames(\n {\n \"--is-disabled\": isDisabled,\n },\n validationClasses,\n );\n const errorMessageId = useId();\n const shouldErrorMessageShow = errorMessage ? errorMessageId : undefined;\n const describedBy = spaceDelimitedList([\n shouldErrorMessageShow,\n props[\"aria-describedby\"],\n ]);\n const labelId = useId();\n\n const handleChange = (\n event: ChangeEvent<CheckboxElementType>,\n isLastItem = false,\n ) => {\n const {\n target: { value, checked },\n } = event;\n\n if (!checked) {\n setSelected(selected.filter(item => item !== value));\n }\n\n if (checked && lastItemDisables && isLastItem) {\n setSelected([value]);\n return;\n }\n\n if (checked) {\n setSelected([...selected, value]);\n }\n };\n\n // HACK: This is a workaround to ensure that the onChange event is not\n // fired on the initial render.\n const renderCount = useRenderCount();\n useEffect(() => {\n if (onChange && renderCount > 1) {\n onChange(selected);\n }\n }, [selected, onChange, renderCount]);\n\n const childrenArray = Children.toArray(children);\n const lastCheckbox = childrenArray\n .filter(\n child =>\n isValidElement(child) && (child as ReactElement).type === Checkbox,\n )\n .pop() as ReactElement<CheckboxElementType> | undefined;\n const lastCheckboxIsChecked =\n lastCheckbox && selected.includes(lastCheckbox.props.value);\n\n return (\n <div\n {...rest}\n aria-labelledby={props[\"aria-labelledby\"] || labelId}\n ref={ref}\n className={checkboxGroupClasses}\n role=\"group\"\n style={\n {\n \"--checkbox-items-per-row\": itemsPerRow || Children.count(children),\n } as React.CSSProperties\n }\n >\n {label && (\n <Label elementType=\"span\" id={labelId} className={labelClasses}>\n {label}\n </Label>\n )}\n <div className=\"mobius-checkbox-group__wrapper\">\n {childrenArray.map(child => {\n if (isValidElement(child)) {\n // lastItemDisables support\n const isLastItem = child === lastCheckbox;\n const isChildDisabled =\n isDisabled ||\n (lastItemDisables && lastCheckboxIsChecked && !isLastItem);\n\n return cloneElement(child as ReactElement, {\n isDisabled: isChildDisabled,\n isRequired,\n isReadOnly,\n isInvalid,\n isLastItem,\n selected: selected.includes(child.props.value),\n onChange: handleChange,\n \"aria-describedby\": describedBy,\n });\n }\n\n return child;\n })}\n </div>\n {errorMessage && (\n <ErrorMessage id={errorMessageId} errorMessage={errorMessage} />\n )}\n </div>\n );\n});\n"],"names":["classNames","Children","cloneElement","forwardRef","isValidElement","useEffect","useId","useState","useRenderCount","useValidationClasses","spaceDelimitedList","ErrorMessage","Label","Checkbox","CheckboxGroup","props","ref","label","isDisabled","isRequired","validationState","isInvalid","orientation","onChange","className","errorMessage","children","defaultValue","isReadOnly","itemsPerRow","lastItemDisables","rest","selected","setSelected","checkboxGroupClasses","validationClasses","labelClasses","errorMessageId","shouldErrorMessageShow","undefined","describedBy","labelId","handleChange","event","isLastItem","target","value","checked","filter","item","renderCount","childrenArray","toArray","lastCheckbox","child","type","pop","lastCheckboxIsChecked","includes","div","aria-labelledby","role","style","count","elementType","id","map","isChildDisabled"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Checkbox/types.ts"],"sourcesContent":["import { ChangeEvent, ReactNode, Ref, RefAttributes } from \"react\";\nimport { DOMProps } from \"../../types/dom\";\nimport { Validation } from \"../../types\";\n\nexport type CheckboxElementType = HTMLInputElement;\nexport type CheckboxRef = Ref<CheckboxElementType>;\n\nexport interface CheckboxProps\n extends DOMProps,\n Validation,\n RefAttributes<CheckboxElementType> {\n className?: string;\n // The content to display as the label.\n label?: ReactNode;\n errorMessage?: string;\n /** The name of the input */\n name?: string;\n /** The current value (controlled). */\n value?: string;\n // Whether the input is disabled.\n isDisabled?: boolean;\n onChange?: (event: ChangeEvent<CheckboxElementType
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Checkbox/types.ts"],"sourcesContent":["import { ChangeEvent, ReactNode, Ref, RefAttributes } from \"react\";\nimport { DOMProps } from \"../../types/dom\";\nimport { Validation } from \"../../types\";\n\nexport type CheckboxElementType = HTMLInputElement;\nexport type CheckboxRef = Ref<CheckboxElementType>;\n\nexport interface CheckboxProps\n extends DOMProps,\n Validation,\n RefAttributes<CheckboxElementType> {\n className?: string;\n // The content to display as the label.\n label?: ReactNode;\n errorMessage?: string;\n /** The name of the input */\n name?: string;\n /** The current value (controlled). */\n value?: string;\n // Whether the input is disabled.\n isDisabled?: boolean;\n onChange?: (\n event: ChangeEvent<CheckboxElementType>,\n isLastItem?: boolean,\n ) => void;\n // The default value (uncontrolled).\n defaultSelected?: boolean;\n // Whether the input can be selected but not changed by the user.\n isReadOnly?: boolean;\n // Whether user input is required on the input before form submission.\n isRequired?: boolean;\n // Identifies the element that provides an error message for the object.\n \"aria-errormessage\"?: string;\n /**\n * Identifies the element (or elements) that describes the object.\n */\n \"aria-describedby\"?: string;\n /**\n * Whether the checkbox is the last item of a group.\n */\n isLastItem?: boolean;\n /**\n * **Internal:** Do not use\n */\n groupDisabled?: boolean;\n /**\n * Whether the checkbox is selected.\n */\n selected?: boolean;\n}\n\nexport type CheckboxGroupElementType = HTMLDivElement;\ninterface CheckboxGroupPropsInternal\n extends DOMProps,\n Validation,\n RefAttributes<CheckboxGroupElementType> {\n children: ReactNode;\n className?: string;\n orientation?: \"horizontal\" | \"vertical\";\n // Defines number of items to be displayed on a single row when used with orientation=\"horizontal\". Defaults to number of items in the group.\n itemsPerRow?: number;\n errorMessage?: string;\n onChange?: (values: string[]) => void;\n // Defines a string value that labels the current element.\n // \"aria-label\"?: string;\n // Identifies the element (or elements) that labels the current element.\n \"aria-labelledby\"?: string;\n // Identifies the element that provides an error message for the object.\n // \"aria-errormessage\"?: string;\n // Identifies the element (or elements) that describes the object.\n \"aria-describedby\"?: string;\n // Whether user input is required on the input before form submission.\n isRequired?: boolean;\n // Whether the input is disabled.\n isDisabled?: boolean;\n // Whether the input can be selected but not changed by the user.\n isReadOnly?: boolean;\n // The default value (uncontrolled).\n defaultValue?: string[];\n // The content to display as the label.\n label?: ReactNode;\n /**\n * The value of the radio button, used when submitting an HTML form.\n * See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio#Value).\n */\n value?: string;\n /**\n * This determines if the last item in the group should disable the other items when selected.\n */\n lastItemDisables?: boolean;\n}\n\ninterface HorizontalCheckboxGroupProps extends CheckboxGroupPropsInternal {\n orientation?: \"horizontal\";\n itemsPerRow: number;\n}\n\ninterface VerticalCheckboxGroupProps extends CheckboxGroupPropsInternal {\n orientation?: \"vertical\";\n itemsPerRow?: never;\n}\n\nexport type CheckboxGroupProps =\n | HorizontalCheckboxGroupProps\n | VerticalCheckboxGroupProps;\n\nexport type CheckboxGroupRef = Ref<CheckboxGroupElementType>;\n"],"names":[],"mappings":"AA0GA,WAA6D"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useId, useRef, useState, useEffect } from "react";
|
|
3
|
+
import classNames from "classnames/dedupe";
|
|
4
|
+
import { TextField } from "../TextField";
|
|
5
|
+
const getOptionValue = (option)=>typeof option === "string" ? option : option.value;
|
|
6
|
+
const getOptionLabel = (option)=>typeof option === "string" ? option : option.label;
|
|
7
|
+
export const Combobox = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
8
|
+
const { defaultValue, options, onSelected } = props;
|
|
9
|
+
const fallbackRef = useRef();
|
|
10
|
+
const [inputValue, setInputValue] = useState(defaultValue || "");
|
|
11
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
12
|
+
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
|
13
|
+
const [filteredOptions, setFilteredOptions] = useState([]);
|
|
14
|
+
const inputRef = ref || fallbackRef;
|
|
15
|
+
const listboxId = useId();
|
|
16
|
+
useEffect(()=>{
|
|
17
|
+
const fetchOptions = async ()=>{
|
|
18
|
+
if (typeof options === "function") {
|
|
19
|
+
const result = await options(inputValue);
|
|
20
|
+
setFilteredOptions(result);
|
|
21
|
+
} else {
|
|
22
|
+
setFilteredOptions(options.filter((option)=>getOptionLabel(option).toLowerCase().includes(inputValue.toLowerCase())));
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
fetchOptions();
|
|
26
|
+
}, [
|
|
27
|
+
inputValue,
|
|
28
|
+
options
|
|
29
|
+
]);
|
|
30
|
+
const handleFocus = ()=>{
|
|
31
|
+
setIsOpen(true);
|
|
32
|
+
};
|
|
33
|
+
const handleBlur = ()=>{
|
|
34
|
+
setIsOpen(false);
|
|
35
|
+
};
|
|
36
|
+
const handleInputChange = (e)=>{
|
|
37
|
+
const newValue = e.target.value;
|
|
38
|
+
setInputValue(newValue);
|
|
39
|
+
setIsOpen(true);
|
|
40
|
+
setHighlightedIndex(-1);
|
|
41
|
+
};
|
|
42
|
+
const handleOptionSelect = (option)=>{
|
|
43
|
+
const value = getOptionValue(option);
|
|
44
|
+
setIsOpen(false);
|
|
45
|
+
setInputValue(value);
|
|
46
|
+
onSelected === null || onSelected === void 0 ? void 0 : onSelected(value);
|
|
47
|
+
};
|
|
48
|
+
const handleKeyDown = (e)=>{
|
|
49
|
+
switch(e.key){
|
|
50
|
+
case "ArrowDown":
|
|
51
|
+
e.preventDefault();
|
|
52
|
+
setIsOpen(true);
|
|
53
|
+
setHighlightedIndex((prev)=>prev < filteredOptions.length - 1 ? prev + 1 : 0);
|
|
54
|
+
break;
|
|
55
|
+
case "ArrowUp":
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
setIsOpen(true);
|
|
58
|
+
setHighlightedIndex((prev)=>prev > 0 ? prev - 1 : filteredOptions.length - 1);
|
|
59
|
+
break;
|
|
60
|
+
case "Enter":
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
if (isOpen && highlightedIndex >= 0) {
|
|
63
|
+
handleOptionSelect(filteredOptions[highlightedIndex]);
|
|
64
|
+
} else if (isOpen && highlightedIndex === -1 && filteredOptions.length > 0) {
|
|
65
|
+
handleOptionSelect(filteredOptions[0]);
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
case "Escape":
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
setIsOpen(false);
|
|
71
|
+
setHighlightedIndex(-1);
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
77
|
+
className: "mobius mobius-combobox",
|
|
78
|
+
children: [
|
|
79
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
80
|
+
className: "mobius-combobox__input",
|
|
81
|
+
role: "combobox",
|
|
82
|
+
value: inputValue,
|
|
83
|
+
onFocus: handleFocus,
|
|
84
|
+
onBlur: handleBlur,
|
|
85
|
+
onKeyDown: handleKeyDown,
|
|
86
|
+
onChange: handleInputChange,
|
|
87
|
+
"aria-autocomplete": "list",
|
|
88
|
+
"aria-haspopup": "listbox",
|
|
89
|
+
"aria-controls": listboxId,
|
|
90
|
+
"aria-expanded": isOpen,
|
|
91
|
+
"aria-activedescendant": highlightedIndex === -1 ? undefined : `${listboxId}-option-${highlightedIndex}`,
|
|
92
|
+
// @ts-expect-error I have no idea how ref typing works
|
|
93
|
+
ref: inputRef
|
|
94
|
+
}),
|
|
95
|
+
isOpen && /*#__PURE__*/ _jsx("ul", {
|
|
96
|
+
role: "listbox",
|
|
97
|
+
id: listboxId,
|
|
98
|
+
className: "mobius-combobox__list",
|
|
99
|
+
children: filteredOptions.map((option, index)=>/*#__PURE__*/ _jsx("li", {
|
|
100
|
+
role: "option",
|
|
101
|
+
id: `${listboxId}-option-${index}`,
|
|
102
|
+
"aria-selected": highlightedIndex === index,
|
|
103
|
+
onMouseDown: ()=>handleOptionSelect(option),
|
|
104
|
+
className: classNames("mobius-combobox__option", {
|
|
105
|
+
"mobius-combobox__option--is-highlighted": highlightedIndex === index
|
|
106
|
+
}),
|
|
107
|
+
children: getOptionLabel(option)
|
|
108
|
+
}, getOptionValue(option)))
|
|
109
|
+
})
|
|
110
|
+
]
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=Combobox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { forwardRef, useId, useRef, useState, useEffect } from \"react\";\nimport classNames from \"classnames/dedupe\";\nimport { TextField } from \"../TextField\";\nimport type {\n ComboboxProps,\n ComboboxElementType,\n ComboboxRef,\n ComboboxOption,\n} from \"./types\";\nimport type { ForwardedRefComponent } from \"../../types\";\n\nconst getOptionValue = (option: ComboboxOption) =>\n typeof option === \"string\" ? option : option.value;\n\nconst getOptionLabel = (option: ComboboxOption) =>\n typeof option === \"string\" ? option : option.label;\n\nexport const Combobox: ForwardedRefComponent<\n ComboboxProps,\n ComboboxElementType\n> = forwardRef((props: ComboboxProps, ref: ComboboxRef) => {\n const { defaultValue, options, onSelected } = props;\n\n const fallbackRef = useRef();\n const [inputValue, setInputValue] = useState(defaultValue || \"\");\n const [isOpen, setIsOpen] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const [filteredOptions, setFilteredOptions] = useState<ComboboxOption[]>([]);\n const inputRef = ref || fallbackRef;\n const listboxId = useId();\n\n useEffect(() => {\n const fetchOptions = async () => {\n if (typeof options === \"function\") {\n const result = await options(inputValue);\n setFilteredOptions(result);\n } else {\n setFilteredOptions(\n options.filter(option =>\n getOptionLabel(option)\n .toLowerCase()\n .includes(inputValue.toLowerCase()),\n ),\n );\n }\n };\n\n fetchOptions();\n }, [inputValue, options]);\n\n const handleFocus = () => {\n setIsOpen(true);\n };\n\n const handleBlur = () => {\n setIsOpen(false);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setIsOpen(true);\n setHighlightedIndex(-1);\n };\n\n const handleOptionSelect = (option: ComboboxOption) => {\n const value = getOptionValue(option);\n setIsOpen(false);\n setInputValue(value);\n onSelected?.(value);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n setIsOpen(true);\n setHighlightedIndex(prev =>\n prev < filteredOptions.length - 1 ? prev + 1 : 0,\n );\n break;\n case \"ArrowUp\":\n e.preventDefault();\n setIsOpen(true);\n setHighlightedIndex(prev =>\n prev > 0 ? prev - 1 : filteredOptions.length - 1,\n );\n break;\n case \"Enter\":\n e.preventDefault();\n if (isOpen && highlightedIndex >= 0) {\n handleOptionSelect(filteredOptions[highlightedIndex]);\n } else if (\n isOpen &&\n highlightedIndex === -1 &&\n filteredOptions.length > 0\n ) {\n handleOptionSelect(filteredOptions[0]);\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setIsOpen(false);\n setHighlightedIndex(-1);\n break;\n default:\n // Do nothing\n }\n };\n\n return (\n <div className=\"mobius mobius-combobox\">\n <TextField\n className=\"mobius-combobox__input\"\n role=\"combobox\"\n value={inputValue}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n onChange={handleInputChange}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-expanded={isOpen}\n aria-activedescendant={\n highlightedIndex === -1\n ? undefined\n : `${listboxId}-option-${highlightedIndex}`\n }\n // @ts-expect-error I have no idea how ref typing works\n ref={inputRef}\n />\n {isOpen && (\n <ul role=\"listbox\" id={listboxId} className=\"mobius-combobox__list\">\n {filteredOptions.map((option, index) => (\n <li\n role=\"option\"\n key={getOptionValue(option)}\n id={`${listboxId}-option-${index}`}\n aria-selected={highlightedIndex === index}\n onMouseDown={() => handleOptionSelect(option)}\n className={classNames(\"mobius-combobox__option\", {\n \"mobius-combobox__option--is-highlighted\":\n highlightedIndex === index,\n })}\n >\n {getOptionLabel(option)}\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n});\n"],"names":["forwardRef","useId","useRef","useState","useEffect","classNames","TextField","getOptionValue","option","value","getOptionLabel","label","Combobox","props","ref","defaultValue","options","onSelected","fallbackRef","inputValue","setInputValue","isOpen","setIsOpen","highlightedIndex","setHighlightedIndex","filteredOptions","setFilteredOptions","inputRef","listboxId","fetchOptions","result","filter","toLowerCase","includes","handleFocus","handleBlur","handleInputChange","e","newValue","target","handleOptionSelect","handleKeyDown","key","preventDefault","prev","length","div","className","role","onFocus","onBlur","onKeyDown","onChange","aria-autocomplete","aria-haspopup","aria-controls","aria-expanded","aria-activedescendant","undefined","ul","id","map","index","li","aria-selected","onMouseDown"],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
export const FRUITS = [
|
|
2
|
+
"Apple",
|
|
3
|
+
"Apricot",
|
|
4
|
+
"Avocado",
|
|
5
|
+
"Banana",
|
|
6
|
+
"Blackberry",
|
|
7
|
+
"Blueberry",
|
|
8
|
+
"Cantaloupe",
|
|
9
|
+
"Cherry",
|
|
10
|
+
"Clementine",
|
|
11
|
+
"Coconut",
|
|
12
|
+
"Cranberry",
|
|
13
|
+
"Date",
|
|
14
|
+
"Dragonfruit",
|
|
15
|
+
"Durian",
|
|
16
|
+
"Elderberry",
|
|
17
|
+
"Fig",
|
|
18
|
+
"Grape",
|
|
19
|
+
"Grapefruit",
|
|
20
|
+
"Guava",
|
|
21
|
+
"Honeydew",
|
|
22
|
+
"Jackfruit",
|
|
23
|
+
"Kiwi",
|
|
24
|
+
"Kumquat",
|
|
25
|
+
"Lemon",
|
|
26
|
+
"Lime",
|
|
27
|
+
"Lychee",
|
|
28
|
+
"Mango",
|
|
29
|
+
"Mulberry",
|
|
30
|
+
"Nectarine",
|
|
31
|
+
"Orange",
|
|
32
|
+
"Papaya",
|
|
33
|
+
"Passionfruit",
|
|
34
|
+
"Peach",
|
|
35
|
+
"Pear",
|
|
36
|
+
"Persimmon",
|
|
37
|
+
"Pineapple",
|
|
38
|
+
"Plum",
|
|
39
|
+
"Pomegranate",
|
|
40
|
+
"Raspberry",
|
|
41
|
+
"Redcurrant",
|
|
42
|
+
"Starfruit",
|
|
43
|
+
"Strawberry",
|
|
44
|
+
"Tangerine",
|
|
45
|
+
"Watermelon"
|
|
46
|
+
];
|
|
47
|
+
export const FRUITS_OBJECTS = [
|
|
48
|
+
{
|
|
49
|
+
label: "Apple",
|
|
50
|
+
value: "apple"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
label: "Apricot",
|
|
54
|
+
value: "apricot"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
label: "Avocado",
|
|
58
|
+
value: "avocado"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: "Banana",
|
|
62
|
+
value: "banana"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: "Blackberry",
|
|
66
|
+
value: "blackberry"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
label: "Blueberry",
|
|
70
|
+
value: "blueberry"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
label: "Cantaloupe",
|
|
74
|
+
value: "cantaloupe"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: "Cherry",
|
|
78
|
+
value: "cherry"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
label: "Clementine",
|
|
82
|
+
value: "clementine"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
label: "Coconut",
|
|
86
|
+
value: "coconut"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
label: "Cranberry",
|
|
90
|
+
value: "cranberry"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
label: "Date",
|
|
94
|
+
value: "date"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
label: "Dragonfruit",
|
|
98
|
+
value: "dragonfruit"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
label: "Durian",
|
|
102
|
+
value: "durian"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
label: "Elderberry",
|
|
106
|
+
value: "elderberry"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
label: "Fig",
|
|
110
|
+
value: "fig"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
label: "Grape",
|
|
114
|
+
value: "grape"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
label: "Grapefruit",
|
|
118
|
+
value: "grapefruit"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
label: "Guava",
|
|
122
|
+
value: "guava"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
label: "Honeydew",
|
|
126
|
+
value: "honeydew"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
label: "Jackfruit",
|
|
130
|
+
value: "jackfruit"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
label: "Kiwi",
|
|
134
|
+
value: "kiwi"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
label: "Kumquat",
|
|
138
|
+
value: "kumquat"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
label: "Lemon",
|
|
142
|
+
value: "lemon"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
label: "Lime",
|
|
146
|
+
value: "lime"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
label: "Lychee",
|
|
150
|
+
value: "lychee"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
label: "Mango",
|
|
154
|
+
value: "mango"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
label: "Mulberry",
|
|
158
|
+
value: "mulberry"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
label: "Nectarine",
|
|
162
|
+
value: "nectarine"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
label: "Orange",
|
|
166
|
+
value: "orange"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
label: "Papaya",
|
|
170
|
+
value: "papaya"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
label: "Passionfruit",
|
|
174
|
+
value: "passionfruit"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
label: "Peach",
|
|
178
|
+
value: "peach"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
label: "Pear",
|
|
182
|
+
value: "pear"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
label: "Persimmon",
|
|
186
|
+
value: "persimmon"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
label: "Pineapple",
|
|
190
|
+
value: "pineapple"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
label: "Plum",
|
|
194
|
+
value: "plum"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
label: "Pomegranate",
|
|
198
|
+
value: "pomegranate"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
label: "Raspberry",
|
|
202
|
+
value: "raspberry"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
label: "Redcurrant",
|
|
206
|
+
value: "redcurrant"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
label: "Starfruit",
|
|
210
|
+
value: "starfruit"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
label: "Strawberry",
|
|
214
|
+
value: "strawberry"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
label: "Tangerine",
|
|
218
|
+
value: "tangerine"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
label: "Watermelon",
|
|
222
|
+
value: "watermelon"
|
|
223
|
+
}
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
//# sourceMappingURL=fixtures.js.map
|