@coopdigital/react 1.30.2 → 1.31.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/dist/components/Author/Author.d.ts +3 -1
- package/dist/components/Author/Author.js +1 -1
- package/dist/components/Author/index.d.ts +2 -2
- package/dist/components/Author/index.js +2 -2
- package/dist/components/Combobox/Combobox.d.ts +1 -1
- package/dist/components/Combobox/Combobox.js +10 -5
- package/dist/components/Combobox/{combobox-utils.js → combobox-internal.js} +4 -2
- package/dist/components/DateInput/DateInput.context.js +7 -0
- package/dist/components/DateInput/DateInput.d.ts +104 -0
- package/dist/components/DateInput/DateInput.js +128 -0
- package/dist/components/DateInput/dateinput-internal.d.ts +6 -0
- package/dist/components/DateInput/dateinput-internal.js +82 -0
- package/dist/components/DateInput/dateinput-utils.d.ts +66 -0
- package/dist/components/DateInput/dateinput-utils.js +91 -0
- package/dist/components/DateInput/index.d.ts +3 -0
- package/dist/components/DateInput/index.js +6 -0
- package/dist/components/Field/Field.context.js +1 -1
- package/dist/components/Field/Field.js +1 -1
- package/dist/components/FieldMarkers/{fieldmarkers-utils.js → fieldmarkers-internal.js} +1 -1
- package/dist/components/Fieldset/Fieldset.js +1 -1
- package/dist/components/Form/Form.d.ts +7 -1
- package/dist/components/Form/Form.js +2 -1
- package/dist/components/Squircle/Squircle.d.ts +3 -1
- package/dist/components/Squircle/Squircle.js +1 -1
- package/dist/components/Squircle/index.d.ts +2 -2
- package/dist/components/Squircle/index.js +2 -2
- package/dist/components/ValidationSummary/ValidationSummary.d.ts +1 -1
- package/dist/components/ValidationSummary/ValidationSummary.js +1 -1
- package/dist/components/ValidationSummary/{validationsummary-utils.d.ts → validationsummary-internal.d.ts} +1 -1
- package/dist/components/ValidationSummary/{validationsummary-utils.js → validationsummary-internal.js} +3 -2
- package/dist/index.d.ts +6 -3
- package/dist/index.js +6 -4
- package/package.json +6 -5
- package/src/components/Author/Author.tsx +1 -1
- package/src/components/Combobox/Combobox.tsx +29 -20
- package/src/components/Combobox/combobox-internal.ts +60 -0
- package/src/components/Combobox/combobox-utils.ts +1 -41
- package/src/components/Combobox/index.ts +1 -0
- package/src/components/DateInput/DateInput.context.ts +25 -0
- package/src/components/DateInput/DateInput.tsx +252 -0
- package/src/components/DateInput/dateinput-internal.ts +176 -0
- package/src/components/DateInput/dateinput-utils.ts +194 -0
- package/src/components/DateInput/index.ts +6 -0
- package/src/components/Field/Field.context.ts +1 -1
- package/src/components/Field/Field.tsx +1 -1
- package/src/components/Fieldset/Fieldset.tsx +5 -1
- package/src/components/Form/Form.tsx +9 -1
- package/src/components/Squircle/Squircle.tsx +1 -1
- package/src/components/ValidationSummary/ValidationSummary.context.ts +1 -1
- package/src/components/ValidationSummary/ValidationSummary.tsx +1 -1
- package/src/components/ValidationSummary/{validationsummary-utils.ts → validationsummary-internal.ts} +9 -8
- package/src/index.ts +1 -0
- /package/src/components/FieldMarkers/{fieldmarkers-utils.ts → fieldmarkers-internal.ts} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StandardSizes } from "../../types/index.js";
|
|
1
2
|
import { FormHTMLAttributes, JSX, ReactNode, Ref } from "react";
|
|
2
3
|
//#region src/components/Form/Form.d.ts
|
|
3
4
|
export interface FormProps extends FormHTMLAttributes<HTMLFormElement> {
|
|
@@ -7,9 +8,14 @@ export interface FormProps extends FormHTMLAttributes<HTMLFormElement> {
|
|
|
7
8
|
className?: string;
|
|
8
9
|
/** Specify a custom React ref for this component. */
|
|
9
10
|
ref?: Ref<HTMLFormElement>;
|
|
11
|
+
/** Specify the spacing.
|
|
12
|
+
*
|
|
13
|
+
* Default: `md`
|
|
14
|
+
*/
|
|
15
|
+
spacing?: StandardSizes;
|
|
10
16
|
}
|
|
11
17
|
declare const Form: {
|
|
12
|
-
({ children, className, ref, ...props }: FormProps): JSX.Element;
|
|
18
|
+
({ children, className, ref, spacing, ...props }: FormProps): JSX.Element;
|
|
13
19
|
slot: {
|
|
14
20
|
name: string;
|
|
15
21
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region src/components/Form/Form.tsx
|
|
4
|
-
const Form = ({ children, className, ref, ...props }) => {
|
|
4
|
+
const Form = ({ children, className, ref, spacing, ...props }) => {
|
|
5
5
|
const componentProps = {
|
|
6
6
|
className: clsx("coop-form", className),
|
|
7
|
+
"data-spacing": spacing ?? void 0,
|
|
7
8
|
...props
|
|
8
9
|
};
|
|
9
10
|
return /* @__PURE__ */ jsx("form", {
|
|
@@ -22,5 +22,7 @@ declare const Squircle: {
|
|
|
22
22
|
name: string;
|
|
23
23
|
};
|
|
24
24
|
};
|
|
25
|
+
declare const SquircleSvg: ({ size, ...props }: SquircleSvgProps) => JSX.Element;
|
|
26
|
+
declare const SquircleText: ({ children, className, ...props }: HTMLAttributes<HTMLDivElement>) => JSX.Element;
|
|
25
27
|
//#endregion
|
|
26
|
-
export { Squircle, Squircle as default };
|
|
28
|
+
export { Squircle, Squircle as default, SquircleSvg, SquircleText };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Squircle, SquircleProps, SquircleSvgProps } from "./Squircle.js";
|
|
2
|
-
export { Squircle, Squircle as default, SquircleProps, SquircleSvgProps };
|
|
1
|
+
import { Squircle, SquircleProps, SquircleSvg, SquircleSvgProps, SquircleText } from "./Squircle.js";
|
|
2
|
+
export { Squircle, Squircle as default, SquircleProps, SquircleSvg, SquircleSvgProps, SquircleText };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Squircle } from "./Squircle.js";
|
|
1
|
+
import { Squircle, SquircleSvg, SquircleText } from "./Squircle.js";
|
|
2
2
|
//#region src/components/Squircle/index.ts
|
|
3
3
|
var Squircle_default = Squircle;
|
|
4
4
|
//#endregion
|
|
5
|
-
export { Squircle, Squircle_default as default };
|
|
5
|
+
export { Squircle, SquircleSvg, SquircleText, Squircle_default as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FieldError } from "./validationsummary-
|
|
1
|
+
import { FieldError } from "./validationsummary-internal.js";
|
|
2
2
|
import React, { HTMLAttributes, JSX, ReactNode, Ref, RefObject } from "react";
|
|
3
3
|
//#region src/components/ValidationSummary/ValidationSummary.d.ts
|
|
4
4
|
export interface ValidationSummaryProps extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { getSlotProp } from "../../utils/slots.js";
|
|
3
3
|
import { useSlots } from "../../hooks/useSlots.js";
|
|
4
|
-
import { getFieldElement, getFieldOrder, getForm, sanitizeFieldId, sortErrorsByFieldOrder } from "./validationsummary-
|
|
4
|
+
import { getFieldElement, getFieldOrder, getForm, sanitizeFieldId, sortErrorsByFieldOrder } from "./validationsummary-internal.js";
|
|
5
5
|
import { ValidationSummaryContext, useValidationSummary } from "./ValidationSummary.context.js";
|
|
6
6
|
import clsx from "clsx";
|
|
7
7
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/components/ValidationSummary/validationsummary-
|
|
1
|
+
//#region src/components/ValidationSummary/validationsummary-internal.ts
|
|
2
2
|
const sanitizeFieldId = (id) => id?.startsWith("#") ? id.slice(1) : id;
|
|
3
3
|
const getFieldKeys = (field, id) => [
|
|
4
4
|
...id ? [sanitizeFieldId(id)] : [],
|
|
@@ -6,11 +6,12 @@ const getFieldKeys = (field, id) => [
|
|
|
6
6
|
field
|
|
7
7
|
];
|
|
8
8
|
const VISIBLE_CONTROL = "input:not([type=\"hidden\"]), select, textarea";
|
|
9
|
+
const INVALID_CONTROL = `:is(${VISIBLE_CONTROL})[aria-invalid="true"]`;
|
|
9
10
|
const isHiddenInput = (el) => el instanceof HTMLInputElement && el.type === "hidden";
|
|
10
11
|
const getVisibleControl = (form, el) => {
|
|
11
12
|
for (let node = el.parentElement; node && node !== form; node = node.parentElement) {
|
|
12
13
|
const control = node.querySelector(VISIBLE_CONTROL);
|
|
13
|
-
if (control) return control;
|
|
14
|
+
if (control) return node.querySelector(INVALID_CONTROL) ?? control;
|
|
14
15
|
}
|
|
15
16
|
return el;
|
|
16
17
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AlertBanner, AlertBannerHeading, AlertBannerProps } from "./components/AlertBanner/AlertBanner.js";
|
|
2
2
|
import { Image, ImageProps } from "./components/Image/Image.js";
|
|
3
|
-
import { Author, AuthorImageProps, AuthorMetaProps, AuthorProps } from "./components/Author/Author.js";
|
|
3
|
+
import { Author, AuthorImage, AuthorImageProps, AuthorMeta, AuthorMetaProps, AuthorProps } from "./components/Author/Author.js";
|
|
4
4
|
import { Box, BoxProps } from "./components/Box/Box.js";
|
|
5
5
|
import "./components/Box/index.js";
|
|
6
6
|
import { Button, ButtonProps } from "./components/Button/Button.js";
|
|
@@ -12,6 +12,9 @@ import { ComboboxItem, ComboboxOption } from "./components/Combobox/combobox-uti
|
|
|
12
12
|
import { TextInput, TextInputProps } from "./components/TextInput/TextInput.js";
|
|
13
13
|
import { Combobox, ComboboxButton, ComboboxButtonProps, ComboboxControls, ComboboxControlsProps, ComboboxInput, ComboboxInputProps, ComboboxOptions, ComboboxOptionsProps, ComboboxProps, ComboboxSelectEvent } from "./components/Combobox/Combobox.js";
|
|
14
14
|
import "./components/Combobox/index.js";
|
|
15
|
+
import { DATE_ERROR_MESSAGES, DATE_PARTS, DateErrorCode, DateErrorMessage, DateInputMode, DatePart, DateParts, DateValidation, DateValidationError, DateValidationOptions, DateValidationSuccess, getAutoComplete, validateDate, validateDateParts, validateDob } from "./components/DateInput/dateinput-utils.js";
|
|
16
|
+
import { DateInput, DateInputChangeEvent, DateInputDay, DateInputMonth, DateInputPartProps, DateInputProps, DateInputYear } from "./components/DateInput/DateInput.js";
|
|
17
|
+
import "./components/DateInput/index.js";
|
|
15
18
|
import { DateType, DateTypeStr } from "./components/DatePicker/datepicker-utils.js";
|
|
16
19
|
import { DatePicker, DatePickerProps } from "./components/DatePicker/DatePicker.js";
|
|
17
20
|
import { Dialog, DialogBody, DialogHeader, DialogProps } from "./components/Dialog/Dialog.js";
|
|
@@ -33,10 +36,10 @@ import "./components/Section/index.js";
|
|
|
33
36
|
import { Select, SelectOption, SelectOptionGroup, SelectProps } from "./components/Select/Select.js";
|
|
34
37
|
import { Signpost, SignpostProps } from "./components/Signpost/Signpost.js";
|
|
35
38
|
import { SkipNav, SkipNavProps } from "./components/SkipNav/SkipNav.js";
|
|
36
|
-
import { Squircle, SquircleProps, SquircleSvgProps } from "./components/Squircle/Squircle.js";
|
|
39
|
+
import { Squircle, SquircleProps, SquircleSvg, SquircleSvgProps, SquircleText } from "./components/Squircle/Squircle.js";
|
|
37
40
|
import { Tag, TagProps } from "./components/Tag/Tag.js";
|
|
38
41
|
import { Textarea, TextareaProps } from "./components/Textarea/Textarea.js";
|
|
39
42
|
import { ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt, ValidationSummaryProps } from "./components/ValidationSummary/ValidationSummary.js";
|
|
40
43
|
import { Wrapper, WrapperProps } from "./components/Wrapper/Wrapper.js";
|
|
41
44
|
import "./components/Wrapper/index.js";
|
|
42
|
-
export { AlertBanner, AlertBannerHeading, AlertBannerProps, Author, AuthorImageProps, AuthorMetaProps, AuthorProps, Box, BoxProps, Button, ButtonProps, Card, CardBadge, CardContent, CardHeading, CardIcon, CardImage, CardLink, CardPicture, CardProps, Checkbox, CheckboxProps, Combobox, ComboboxButton, ComboboxButtonProps, ComboboxControls, ComboboxControlsProps, ComboboxInput, ComboboxInputProps, type ComboboxItem, type ComboboxOption, ComboboxOptions, ComboboxOptionsProps, ComboboxProps, ComboboxSelectEvent, DatePicker, DatePickerProps, type DateType, type DateTypeStr, Dialog, DialogBody, DialogHeader, DialogProps, Expandable, ExpandableContent, ExpandableProps, ExpandableSummary, Field, FieldError, FieldHint, FieldLabel, Fieldset, FieldsetError, FieldsetFields, FieldsetHint, FieldsetLegend, FieldsetProps, Flourish, FlourishProps, Form, FormProps, Image, ImageProps, LoadingSpinner, LoadingSpinnerProps, Logo, LogoProps, PasswordInput, PasswordInputProps, Picture, PictureProps, Pill, PillBadge, PillProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverProps, PopoverTrigger, Radio, RadioProps, RootSVG, Searchbox, SearchboxButton, SearchboxInput, SearchboxProps, Section, SectionProps, Select, SelectOption, SelectOptionGroup, SelectProps, Signpost, SignpostProps, SkipNav, SkipNavProps, Squircle, SquircleProps, SquircleSvgProps, Tag, TagProps, TextInput, TextInputProps, Textarea, TextareaProps, ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt, ValidationSummaryProps, Wrapper, WrapperProps };
|
|
45
|
+
export { AlertBanner, AlertBannerHeading, AlertBannerProps, Author, AuthorImage, AuthorImageProps, AuthorMeta, AuthorMetaProps, AuthorProps, Box, BoxProps, Button, ButtonProps, Card, CardBadge, CardContent, CardHeading, CardIcon, CardImage, CardLink, CardPicture, CardProps, Checkbox, CheckboxProps, Combobox, ComboboxButton, ComboboxButtonProps, ComboboxControls, ComboboxControlsProps, ComboboxInput, ComboboxInputProps, type ComboboxItem, type ComboboxOption, ComboboxOptions, ComboboxOptionsProps, ComboboxProps, ComboboxSelectEvent, DATE_ERROR_MESSAGES, DATE_PARTS, DateErrorCode, DateErrorMessage, DateInput, DateInputChangeEvent, DateInputDay, DateInputMode, DateInputMonth, DateInputPartProps, DateInputProps, DateInputYear, DatePart, DateParts, DatePicker, DatePickerProps, type DateType, type DateTypeStr, DateValidation, DateValidationError, DateValidationOptions, DateValidationSuccess, Dialog, DialogBody, DialogHeader, DialogProps, Expandable, ExpandableContent, ExpandableProps, ExpandableSummary, Field, FieldError, FieldHint, FieldLabel, Fieldset, FieldsetError, FieldsetFields, FieldsetHint, FieldsetLegend, FieldsetProps, Flourish, FlourishProps, Form, FormProps, Image, ImageProps, LoadingSpinner, LoadingSpinnerProps, Logo, LogoProps, PasswordInput, PasswordInputProps, Picture, PictureProps, Pill, PillBadge, PillProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverProps, PopoverTrigger, Radio, RadioProps, RootSVG, Searchbox, SearchboxButton, SearchboxInput, SearchboxProps, Section, SectionProps, Select, SelectOption, SelectOptionGroup, SelectProps, Signpost, SignpostProps, SkipNav, SkipNavProps, Squircle, SquircleProps, SquircleSvg, SquircleSvgProps, SquircleText, Tag, TagProps, TextInput, TextInputProps, Textarea, TextareaProps, ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt, ValidationSummaryProps, Wrapper, WrapperProps, getAutoComplete, validateDate, validateDateParts, validateDob };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AlertBanner, AlertBannerHeading } from "./components/AlertBanner/AlertBanner.js";
|
|
2
2
|
import { Image } from "./components/Image/Image.js";
|
|
3
|
-
import { Author } from "./components/Author/Author.js";
|
|
3
|
+
import { Author, AuthorImage, AuthorMeta } from "./components/Author/Author.js";
|
|
4
4
|
import { Box } from "./components/Box/Box.js";
|
|
5
5
|
import { LoadingSpinner } from "./components/LoadingSpinner/LoadingSpinner.js";
|
|
6
6
|
import { Button } from "./components/Button/Button.js";
|
|
@@ -9,11 +9,13 @@ import { Card, CardBadge, CardContent, CardHeading, CardIcon, CardImage, CardLin
|
|
|
9
9
|
import { Checkbox } from "./components/Checkbox/Checkbox.js";
|
|
10
10
|
import { TextInput } from "./components/TextInput/TextInput.js";
|
|
11
11
|
import { Combobox, ComboboxButton, ComboboxControls, ComboboxInput, ComboboxOptions } from "./components/Combobox/Combobox.js";
|
|
12
|
+
import { Field, FieldError, FieldHint, FieldLabel } from "./components/Field/Field.js";
|
|
13
|
+
import { DATE_ERROR_MESSAGES, DATE_PARTS, getAutoComplete, validateDate, validateDateParts, validateDob } from "./components/DateInput/dateinput-utils.js";
|
|
14
|
+
import { DateInput, DateInputDay, DateInputMonth, DateInputYear } from "./components/DateInput/DateInput.js";
|
|
12
15
|
import { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger } from "./components/Popover/Popover.js";
|
|
13
16
|
import { DatePicker } from "./components/DatePicker/DatePicker.js";
|
|
14
17
|
import { Dialog, DialogBody, DialogHeader } from "./components/Dialog/Dialog.js";
|
|
15
18
|
import { Expandable, ExpandableContent, ExpandableSummary } from "./components/Expandable/Expandable.js";
|
|
16
|
-
import { Field, FieldError, FieldHint, FieldLabel } from "./components/Field/Field.js";
|
|
17
19
|
import { Fieldset, FieldsetError, FieldsetFields, FieldsetHint, FieldsetLegend } from "./components/Fieldset/Fieldset.js";
|
|
18
20
|
import { Flourish } from "./components/Flourish/Flourish.js";
|
|
19
21
|
import { Form } from "./components/Form/Form.js";
|
|
@@ -27,9 +29,9 @@ import { Section } from "./components/Section/Section.js";
|
|
|
27
29
|
import { Select, SelectOption, SelectOptionGroup } from "./components/Select/Select.js";
|
|
28
30
|
import { Signpost } from "./components/Signpost/Signpost.js";
|
|
29
31
|
import { SkipNav } from "./components/SkipNav/SkipNav.js";
|
|
30
|
-
import { Squircle } from "./components/Squircle/Squircle.js";
|
|
32
|
+
import { Squircle, SquircleSvg, SquircleText } from "./components/Squircle/Squircle.js";
|
|
31
33
|
import { Tag } from "./components/Tag/Tag.js";
|
|
32
34
|
import { Textarea } from "./components/Textarea/Textarea.js";
|
|
33
35
|
import { ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt } from "./components/ValidationSummary/ValidationSummary.js";
|
|
34
36
|
import { Wrapper } from "./components/Wrapper/Wrapper.js";
|
|
35
|
-
export { AlertBanner, AlertBannerHeading, Author, Box, Button, Card, CardBadge, CardContent, CardHeading, CardIcon, CardImage, CardLink, CardPicture, Checkbox, Combobox, ComboboxButton, ComboboxControls, ComboboxInput, ComboboxOptions, DatePicker, Dialog, DialogBody, DialogHeader, Expandable, ExpandableContent, ExpandableSummary, Field, FieldError, FieldHint, FieldLabel, Fieldset, FieldsetError, FieldsetFields, FieldsetHint, FieldsetLegend, Flourish, Form, Image, LoadingSpinner, Logo, PasswordInput, Picture, Pill, PillBadge, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Radio, RootSVG, Searchbox, SearchboxButton, SearchboxInput, Section, Select, SelectOption, SelectOptionGroup, Signpost, SkipNav, Squircle, Tag, TextInput, Textarea, ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt, Wrapper };
|
|
37
|
+
export { AlertBanner, AlertBannerHeading, Author, AuthorImage, AuthorMeta, Box, Button, Card, CardBadge, CardContent, CardHeading, CardIcon, CardImage, CardLink, CardPicture, Checkbox, Combobox, ComboboxButton, ComboboxControls, ComboboxInput, ComboboxOptions, DATE_ERROR_MESSAGES, DATE_PARTS, DateInput, DateInputDay, DateInputMonth, DateInputYear, DatePicker, Dialog, DialogBody, DialogHeader, Expandable, ExpandableContent, ExpandableSummary, Field, FieldError, FieldHint, FieldLabel, Fieldset, FieldsetError, FieldsetFields, FieldsetHint, FieldsetLegend, Flourish, Form, Image, LoadingSpinner, Logo, PasswordInput, Picture, Pill, PillBadge, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Radio, RootSVG, Searchbox, SearchboxButton, SearchboxInput, Section, Select, SelectOption, SelectOptionGroup, Signpost, SkipNav, Squircle, SquircleSvg, SquircleText, Tag, TextInput, Textarea, ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt, Wrapper, getAutoComplete, validateDate, validateDateParts, validateDob };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coopdigital/react",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.31.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"dist",
|
|
27
27
|
"src/**/*.{tsx,ts}",
|
|
28
28
|
"!**/__{screenshots,tests}__",
|
|
29
|
-
"!**/*.{stories,test}.*"
|
|
29
|
+
"!**/*.{stories,test}.*",
|
|
30
|
+
"!**/recipes/**"
|
|
30
31
|
],
|
|
31
32
|
"keywords": [
|
|
32
33
|
"co-op",
|
|
@@ -53,8 +54,8 @@
|
|
|
53
54
|
"test:behaviour:ci": "npm run test:e2e:ci -- -g behaviour",
|
|
54
55
|
"build": "tsx scripts build",
|
|
55
56
|
"build:docs": "tsx scripts build-docs",
|
|
56
|
-
"build:docs:all": "tsx scripts build-docs --all",
|
|
57
57
|
"build:icons": "tsx scripts build-icons",
|
|
58
|
+
"build:pattern-images": "tsx scripts build-pattern-images",
|
|
58
59
|
"build:manifest": "tsx scripts build-manifest",
|
|
59
60
|
"build:storybook": "storybook build --disable-telemetry",
|
|
60
61
|
"build:storybook:test": "storybook build --test --disable-telemetry --output-dir storybook-test",
|
|
@@ -110,7 +111,7 @@
|
|
|
110
111
|
"storybook": "$storybook"
|
|
111
112
|
},
|
|
112
113
|
"dependencies": {
|
|
113
|
-
"@coopdigital/styles": "^1.
|
|
114
|
+
"@coopdigital/styles": "^1.22.0",
|
|
114
115
|
"@radix-ui/react-popover": "^1.3.1",
|
|
115
116
|
"clsx": "^2.1.1",
|
|
116
117
|
"date-fns": "^4.4.0",
|
|
@@ -119,5 +120,5 @@
|
|
|
119
120
|
"merge-refs": "^2.0.0",
|
|
120
121
|
"react-day-picker": "^10.0.2"
|
|
121
122
|
},
|
|
122
|
-
"gitHead": "
|
|
123
|
+
"gitHead": "6a649143b3381563d36754d873c1410eb307fdc4"
|
|
123
124
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client"
|
|
2
|
-
import type { ButtonHTMLAttributes, HTMLAttributes, JSX, ReactNode, Ref } from "react"
|
|
2
|
+
import type { ButtonHTMLAttributes, HTMLAttributes, JSX, MouseEvent, ReactNode, Ref } from "react"
|
|
3
3
|
|
|
4
4
|
import clsx from "clsx"
|
|
5
5
|
import {
|
|
@@ -13,16 +13,19 @@ import {
|
|
|
13
13
|
import mergeRefs from "merge-refs"
|
|
14
14
|
import { useEffect, useMemo, useRef, useState } from "react"
|
|
15
15
|
|
|
16
|
+
import type { ComboboxItem, ComboboxOption } from "@/components/Combobox/combobox-utils"
|
|
17
|
+
|
|
16
18
|
import {
|
|
17
|
-
type ComboboxItem,
|
|
18
|
-
type ComboboxOption,
|
|
19
19
|
defaultFilter,
|
|
20
20
|
defaultIsItemDisabled,
|
|
21
21
|
defaultItemToString,
|
|
22
|
+
defaultMaxResultsText,
|
|
22
23
|
isMatchingText,
|
|
23
24
|
normalizeOptions,
|
|
24
25
|
resolveOption,
|
|
25
|
-
|
|
26
|
+
type SelectionSnapshot,
|
|
27
|
+
shouldShowSelectionText,
|
|
28
|
+
} from "@/components/Combobox/combobox-internal"
|
|
26
29
|
import { ComboboxContext, useComboboxContext } from "@/components/Combobox/Combobox.context"
|
|
27
30
|
import { getFieldError, useField } from "@/components/Field/Field.context"
|
|
28
31
|
import { ChevronDownIcon } from "@/components/icons"
|
|
@@ -31,8 +34,6 @@ import { useDebounce, useFormReset, useId, useSlots } from "@/hooks"
|
|
|
31
34
|
import { StandardSizes } from "@/types"
|
|
32
35
|
import { getSlotProp } from "@/utils"
|
|
33
36
|
|
|
34
|
-
export type { ComboboxItem, ComboboxOption } from "@/components/Combobox/combobox-utils"
|
|
35
|
-
|
|
36
37
|
export interface ComboboxSelectEvent {
|
|
37
38
|
/** Whether the selection is a custom value, entered by users when `allowCustom` is set,
|
|
38
39
|
* rather than one of the options.
|
|
@@ -190,9 +191,6 @@ type ComboboxState = UseComboboxState<ComboboxItem>
|
|
|
190
191
|
const DEFAULT_MAX_RESULTS = 50
|
|
191
192
|
const ANNOUNCEMENT_DELAY = 750
|
|
192
193
|
|
|
193
|
-
const defaultMaxResultsText = (shown: number, total: number): string =>
|
|
194
|
-
`Showing ${shown} of ${total} results.`
|
|
195
|
-
|
|
196
194
|
const componentSlots = {
|
|
197
195
|
ComboboxControls: null,
|
|
198
196
|
ComboboxOptions: null,
|
|
@@ -353,24 +351,22 @@ const Combobox = ({
|
|
|
353
351
|
},
|
|
354
352
|
})
|
|
355
353
|
|
|
356
|
-
//
|
|
357
|
-
// so show the option text once it is known. Text that users are typing is
|
|
358
|
-
// left alone.
|
|
354
|
+
// Keep the input text in step with the selection
|
|
359
355
|
const selection = resolveOption(downshift.selectedItem, items)
|
|
360
356
|
const selectionText = toString(selection)
|
|
361
357
|
const selectionValue = selection?.value
|
|
362
|
-
const previousSelection = useRef({
|
|
358
|
+
const previousSelection = useRef<SelectionSnapshot>({
|
|
359
|
+
text: selectionText,
|
|
360
|
+
value: selectionValue,
|
|
361
|
+
})
|
|
363
362
|
const { inputValue, reset, setInputValue } = downshift
|
|
364
363
|
|
|
365
364
|
useEffect(() => {
|
|
366
365
|
const previous = previousSelection.current
|
|
367
|
-
|
|
366
|
+
const current = { text: selectionText, value: selectionValue }
|
|
367
|
+
previousSelection.current = current
|
|
368
368
|
|
|
369
|
-
if (
|
|
370
|
-
selectionValue === previous.value &&
|
|
371
|
-
selectionText !== previous.text &&
|
|
372
|
-
inputValue === previous.text
|
|
373
|
-
) {
|
|
369
|
+
if (shouldShowSelectionText(previous, current, inputValue)) {
|
|
374
370
|
setInputValue(selectionText)
|
|
375
371
|
}
|
|
376
372
|
}, [inputValue, selectionText, selectionValue, setInputValue])
|
|
@@ -493,9 +489,22 @@ const ComboboxOptions = ({
|
|
|
493
489
|
const message = getMessage()
|
|
494
490
|
const announcement = useDebounce(message, ANNOUNCEMENT_DELAY)
|
|
495
491
|
|
|
492
|
+
// downshift bug: a mouse leave after the menu closes is handled with the
|
|
493
|
+
// props from before a new controlled selection, so it is ignored
|
|
494
|
+
const onMouseLeave = (event: MouseEvent<HTMLUListElement>) => {
|
|
495
|
+
props.onMouseLeave?.(event)
|
|
496
|
+
if (!isOpen) Object.assign(event, { preventDownshiftDefault: true })
|
|
497
|
+
}
|
|
498
|
+
|
|
496
499
|
return (
|
|
497
500
|
<>
|
|
498
|
-
<ul
|
|
501
|
+
<ul
|
|
502
|
+
{...getMenuProps({
|
|
503
|
+
...props,
|
|
504
|
+
className: clsx("coop-combobox-options", className),
|
|
505
|
+
onMouseLeave,
|
|
506
|
+
})}
|
|
507
|
+
>
|
|
499
508
|
{isOpen &&
|
|
500
509
|
items.map((item, index) => {
|
|
501
510
|
// Keep the option fields off the element, and pass its handlers
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { matchSorter } from "match-sorter"
|
|
2
|
+
|
|
3
|
+
import type { ComboboxItem, ComboboxOption } from "./combobox-utils"
|
|
4
|
+
|
|
5
|
+
export const defaultFilter = (items: ComboboxItem[], inputValue: string): ComboboxItem[] =>
|
|
6
|
+
inputValue !== ""
|
|
7
|
+
? matchSorter(items, inputValue, {
|
|
8
|
+
keys: [(item) => [item.label ?? item.value]],
|
|
9
|
+
})
|
|
10
|
+
: items
|
|
11
|
+
|
|
12
|
+
export const defaultIsItemDisabled = (item: ComboboxItem): boolean => item.disabled ?? false
|
|
13
|
+
|
|
14
|
+
export const defaultItemToString = (item: ComboboxItem | null): string =>
|
|
15
|
+
item?.label ?? item?.value ?? ""
|
|
16
|
+
|
|
17
|
+
export const defaultMaxResultsText = (shown: number, total: number): string =>
|
|
18
|
+
`Showing ${shown} of ${total} results.`
|
|
19
|
+
|
|
20
|
+
// Convert options given as strings or objects into a list of items
|
|
21
|
+
export const normalizeOptions = (options: ComboboxOption[]): ComboboxItem[] =>
|
|
22
|
+
options
|
|
23
|
+
.filter((option) => option && typeof option !== "number")
|
|
24
|
+
.map((option) => (typeof option === "string" ? { value: option } : option))
|
|
25
|
+
|
|
26
|
+
// Created once, as localeCompare with options creates a new collator on
|
|
27
|
+
// every call, which is slow when checking a long list of options
|
|
28
|
+
const collator = new Intl.Collator(undefined, { sensitivity: "base" })
|
|
29
|
+
|
|
30
|
+
// Check whether typed text matches an option, ignoring case, accents and
|
|
31
|
+
// surrounding whitespace
|
|
32
|
+
export const isMatchingText = (optionText: string, text: string): boolean =>
|
|
33
|
+
collator.compare(optionText.trim(), text.trim()) === 0
|
|
34
|
+
|
|
35
|
+
// Find the item for an option given as a value or an object. An option that
|
|
36
|
+
// is not in the list, such as a custom value, is kept as it is.
|
|
37
|
+
export const resolveOption = (
|
|
38
|
+
option: ComboboxOption | null | undefined,
|
|
39
|
+
items: ComboboxItem[]
|
|
40
|
+
): ComboboxItem | null => {
|
|
41
|
+
if (option === null || option === undefined) return null
|
|
42
|
+
|
|
43
|
+
const item = typeof option === "string" ? { value: option } : option
|
|
44
|
+
return items.find(({ value }) => value === item.value) ?? item
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SelectionSnapshot {
|
|
48
|
+
text: string
|
|
49
|
+
value: string | undefined
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Whether the input should change to the text of the selection. Options can
|
|
53
|
+
// arrive after the selection, such as when they are fetched, so show the
|
|
54
|
+
// option text once it is known, unless users are typing.
|
|
55
|
+
export const shouldShowSelectionText = (
|
|
56
|
+
previous: SelectionSnapshot,
|
|
57
|
+
current: SelectionSnapshot,
|
|
58
|
+
inputValue: string
|
|
59
|
+
): boolean =>
|
|
60
|
+
current.value === previous.value && current.text !== previous.text && inputValue === previous.text
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HTMLAttributes } from "react"
|
|
1
|
+
import type { HTMLAttributes } from "react"
|
|
3
2
|
|
|
4
3
|
export interface ComboboxItem extends HTMLAttributes<HTMLLIElement> {
|
|
5
4
|
/** Specify the disabled state.
|
|
@@ -19,42 +18,3 @@ export interface ComboboxItem extends HTMLAttributes<HTMLLIElement> {
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
export type ComboboxOption = ComboboxItem | string
|
|
22
|
-
|
|
23
|
-
export const defaultFilter = (items: ComboboxItem[], inputValue: string): ComboboxItem[] =>
|
|
24
|
-
inputValue !== ""
|
|
25
|
-
? matchSorter(items, inputValue, {
|
|
26
|
-
keys: [(item) => [item.label ?? item.value]],
|
|
27
|
-
})
|
|
28
|
-
: items
|
|
29
|
-
|
|
30
|
-
export const defaultIsItemDisabled = (item: ComboboxItem): boolean => item.disabled ?? false
|
|
31
|
-
|
|
32
|
-
export const defaultItemToString = (item: ComboboxItem | null): string =>
|
|
33
|
-
item?.label ?? item?.value ?? ""
|
|
34
|
-
|
|
35
|
-
// Convert options given as strings or objects into a list of items
|
|
36
|
-
export const normalizeOptions = (options: ComboboxOption[]): ComboboxItem[] =>
|
|
37
|
-
options
|
|
38
|
-
.filter((option) => option && typeof option !== "number")
|
|
39
|
-
.map((option) => (typeof option === "string" ? { value: option } : option))
|
|
40
|
-
|
|
41
|
-
// Created once, as localeCompare with options creates a new collator on
|
|
42
|
-
// every call, which is slow when checking a long list of options
|
|
43
|
-
const collator = new Intl.Collator(undefined, { sensitivity: "base" })
|
|
44
|
-
|
|
45
|
-
// Check whether typed text matches an option, ignoring case, accents and
|
|
46
|
-
// surrounding whitespace
|
|
47
|
-
export const isMatchingText = (optionText: string, text: string): boolean =>
|
|
48
|
-
collator.compare(optionText.trim(), text.trim()) === 0
|
|
49
|
-
|
|
50
|
-
// Find the item for an option given as a value or an object. An option that
|
|
51
|
-
// is not in the list, such as a custom value, is kept as it is.
|
|
52
|
-
export const resolveOption = (
|
|
53
|
-
option: ComboboxOption | null | undefined,
|
|
54
|
-
items: ComboboxItem[]
|
|
55
|
-
): ComboboxItem | null => {
|
|
56
|
-
if (option === null || option === undefined) return null
|
|
57
|
-
|
|
58
|
-
const item = typeof option === "string" ? { value: option } : option
|
|
59
|
-
return items.find(({ value }) => value === item.value) ?? item
|
|
60
|
-
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
import { createContext, type RefObject, useContext } from "react"
|
|
3
|
+
|
|
4
|
+
import type { StandardSizes } from "@/types"
|
|
5
|
+
|
|
6
|
+
import type { DateInputMode, DatePart, DateParts } from "./dateinput-utils"
|
|
7
|
+
|
|
8
|
+
export interface DateInputContextValue {
|
|
9
|
+
changePart: (part: DatePart, value: string) => void
|
|
10
|
+
controlled: boolean
|
|
11
|
+
// The first rendered part attaches controlRef, which the form reset is
|
|
12
|
+
// looked up from
|
|
13
|
+
controlPart?: DatePart
|
|
14
|
+
controlRef: RefObject<HTMLInputElement | null>
|
|
15
|
+
defaultValue?: DateParts
|
|
16
|
+
id: string
|
|
17
|
+
mode?: DateInputMode
|
|
18
|
+
name?: string
|
|
19
|
+
parts: DateParts
|
|
20
|
+
size?: StandardSizes
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const DateInputContext = createContext<DateInputContextValue | null>(null)
|
|
24
|
+
|
|
25
|
+
export const useDateInput = () => useContext(DateInputContext)
|