✨(react) add Select component
Finally our powerful Select component is available to make great forms!
This commit is contained in:
5
.changeset/good-coins-divide.md
Normal file
5
.changeset/good-coins-divide.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@openfun/cunningham-react": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
add Select component
|
||||||
5
.changeset/lazy-crews-press.md
Normal file
5
.changeset/lazy-crews-press.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@openfun/cunningham-react": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
add forwardRef to Button
|
||||||
5
.changeset/moody-glasses-fly.md
Normal file
5
.changeset/moody-glasses-fly.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@openfun/cunningham-react": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
create a generic LabelledBox
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
"@openfun/cunningham-tokens": "*",
|
"@openfun/cunningham-tokens": "*",
|
||||||
"@tanstack/react-table": "8.8.4",
|
"@tanstack/react-table": "8.8.4",
|
||||||
"classnames": "2.3.2",
|
"classnames": "2.3.2",
|
||||||
|
"downshift": "7.6.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0"
|
"react-dom": "18.2.0"
|
||||||
},
|
},
|
||||||
@@ -51,9 +52,9 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.21.3",
|
"@babel/core": "7.21.3",
|
||||||
"@babel/preset-typescript": "7.21.4",
|
|
||||||
"@babel/plugin-proposal-decorators": "7.21.0",
|
"@babel/plugin-proposal-decorators": "7.21.0",
|
||||||
"@babel/plugin-proposal-export-default-from": "7.18.10",
|
"@babel/plugin-proposal-export-default-from": "7.18.10",
|
||||||
|
"@babel/preset-typescript": "7.21.4",
|
||||||
"@faker-js/faker": "7.6.0",
|
"@faker-js/faker": "7.6.0",
|
||||||
"@openfun/cunningham-tokens": "*",
|
"@openfun/cunningham-tokens": "*",
|
||||||
"@openfun/typescript-configs": "*",
|
"@openfun/typescript-configs": "*",
|
||||||
|
|||||||
183
packages/react/src/components/Forms/Select/index.scss
Normal file
183
packages/react/src/components/Forms/Select/index.scss
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
.c__select {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&__wrapper {
|
||||||
|
border-radius: var(--c--components--forms-select--border-radius);
|
||||||
|
border-width: var(--c--components--forms-select--border-width);
|
||||||
|
border-color: var(--c--components--forms-select--border-color);
|
||||||
|
border-style: var(--c--components--forms-select--border-style);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: border var(--c--theme--transitions--duration) var(--c--theme--transitions--ease-out);
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
gap: 1rem;
|
||||||
|
color: var(--c--components--forms-select--color);
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: var(--c--components--forms-select--height);
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: var(--c--components--forms-select--background-color);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
label {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-radius: var(--c--components--forms-select--border-radius--hover);
|
||||||
|
border-color: var(--c--components--forms-select--border-color--hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-within {
|
||||||
|
border-radius: var(--c--components--forms-select--border-radius--focus);
|
||||||
|
border-color: var(--c--components--forms-select--border-color--focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__inner {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
user-select: none;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: var(--c--components--forms-select--font-size);
|
||||||
|
|
||||||
|
input {
|
||||||
|
outline: 0;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
color: var(--c--components--forms-select--color);
|
||||||
|
font-size: var(--c--components--forms-select--font-size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__actions {
|
||||||
|
position: relative;
|
||||||
|
top: -14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
transition: all var(--c--theme--transitions--duration) var(--c--theme--transitions--ease-out);
|
||||||
|
&.opened {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__clear {
|
||||||
|
color: var(--c--theme--colors--greyscale-500);
|
||||||
|
}
|
||||||
|
&__separator {
|
||||||
|
background-color: var(--c--theme--colors--greyscale-400);
|
||||||
|
height: 24px;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
&__open {
|
||||||
|
color: var(--c--theme--colors--greyscale-900);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__menu {
|
||||||
|
position: absolute;
|
||||||
|
overflow: auto;
|
||||||
|
width: calc(100% - 4px);
|
||||||
|
max-height: 10rem;
|
||||||
|
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
background-color: var(--c--components--forms-select--menu-background-color);
|
||||||
|
transform: translate(2px, 0);
|
||||||
|
display: none;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&--opened {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
padding: 0.75rem;
|
||||||
|
font-size: var(--c--components--forms-select--item-font-size);
|
||||||
|
color: var(--c--components--forms-select--item-color);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&--highlight {
|
||||||
|
background-color: var(--c--components--forms-select--item-background-color--hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--selected {
|
||||||
|
background-color: var(--c--components--forms-select--item-background-color--selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Modifiers */
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
|
||||||
|
.c__select__wrapper {
|
||||||
|
color: var(--c--theme--colors--greyscale-600);
|
||||||
|
border-color: var(--c--theme--colors--greyscale-200);
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
|
label {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
color: var(--c--theme--colors--greyscale-600);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.c__input__inner {
|
||||||
|
.c__input, label {
|
||||||
|
color: var(--c--theme--colors--greyscale-600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--c--theme--colors--greyscale-200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
|
||||||
|
.c__select__wrapper {
|
||||||
|
border-color: var(--c--theme--colors--danger-600);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.c__select__wrapper--disabled) {
|
||||||
|
.c__select__wrapper:hover {
|
||||||
|
border-color: var(--c--theme--colors--danger-200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
|
||||||
|
.c__select__wrapper {
|
||||||
|
border-color: var(--c--theme--colors--success-600);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.c__select__wrapper--disabled) {
|
||||||
|
.c__select__wrapper:hover {
|
||||||
|
border-color: var(--c--theme--colors--success-400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1032
packages/react/src/components/Forms/Select/index.spec.tsx
Normal file
1032
packages/react/src/components/Forms/Select/index.spec.tsx
Normal file
File diff suppressed because it is too large
Load Diff
134
packages/react/src/components/Forms/Select/index.stories.mdx
Normal file
134
packages/react/src/components/Forms/Select/index.stories.mdx
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import { Canvas, Meta, Story, Source, ArgsTable } from '@storybook/addon-docs';
|
||||||
|
import { Select } from "./index";
|
||||||
|
|
||||||
|
<Meta title="Components/Forms/Select/Doc" component={Select}/>
|
||||||
|
|
||||||
|
export const Template = (args) => <Input {...args} />;
|
||||||
|
|
||||||
|
# Select
|
||||||
|
|
||||||
|
Cunningham provides a versatile Select component that you can use in your forms. This component follows the [ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-autocomplete-list/)
|
||||||
|
using [Downshift](https://www.downshift-js.com/), so that mean there is no `select` wrapped inside it.
|
||||||
|
|
||||||
|
> For now it is only available for mono selection, multiple selection will be available soon.
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story id="components-forms-select-mono--uncontrolled"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The available options must be given via the `options` props. It is an array of objects with the following shape:
|
||||||
|
|
||||||
|
<Source
|
||||||
|
language='ts'
|
||||||
|
dark
|
||||||
|
format={false}
|
||||||
|
code={`{
|
||||||
|
label: string
|
||||||
|
value?: string
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
As you can see the `value` is optional, if not provided, the `label` will be used as the value.
|
||||||
|
|
||||||
|
## Searchable
|
||||||
|
|
||||||
|
You can enable the text live filtering simply by using the `searchable` props.
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="components-forms-select-mono--searchable-uncontrolled"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## States
|
||||||
|
|
||||||
|
You can use the following props to change the state of the Select component by using the `state` props.
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="components-forms-select-mono--success"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="components-forms-select-mono--error"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Disabled
|
||||||
|
|
||||||
|
As a regular select, you can disable it by using the `disabled` props.
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="components-forms-select-mono--disabled"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Texts
|
||||||
|
|
||||||
|
As the component uses [Field](?path=/story/components-forms-field-doc--page), you can use the `text` props to provide a description of the checkbox.
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="components-forms-select-mono--with-text"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Width
|
||||||
|
|
||||||
|
By default, the select has a default width, like all inputs. But you can force it to take the full width of its container by using the `fullWidth` props.
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="components-forms-select-mono--full-width"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Controlled / Non Controlled
|
||||||
|
|
||||||
|
Like a native select, you can use the Select component in a controlled or non controlled way. You can see the example below
|
||||||
|
using the component in a controlled way.
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="components-forms-select-mono--controlled"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
The props of this component are as close as possible to the native select component. You can see the list of props below.
|
||||||
|
|
||||||
|
<ArgsTable of={Select} />
|
||||||
|
|
||||||
|
## Design tokens
|
||||||
|
|
||||||
|
Here are the custom design tokens defined by the select.
|
||||||
|
|
||||||
|
| Token | Description |
|
||||||
|
|--------------- |----------------------------- |
|
||||||
|
| background-color | Background color of the select |
|
||||||
|
| border-color | Border color of the select |
|
||||||
|
| border-color--hover | Border color of the select on mouse hover |
|
||||||
|
| border-color--focus | Border color of the select when focus |
|
||||||
|
| border-radius | Border radius of the select |
|
||||||
|
| border-radius--hover | Border radius of the select on mouse hover |
|
||||||
|
| border-radius--focus | Border radius of the select when focused |
|
||||||
|
| color | Value color |
|
||||||
|
| font-size | Value font size |
|
||||||
|
| height | Height of the combo box |
|
||||||
|
| item-background-color--hover | Background color of the item on mouse hover |
|
||||||
|
| item-background-color--selected | Background color of the selected item |
|
||||||
|
| item-color | Color of the item |
|
||||||
|
| item-font-size | Font size of the item |
|
||||||
|
| menu-background-color | Background color of the menu |
|
||||||
|
|
||||||
|
See also [Field](?path=/story/components-forms-field-doc--page)
|
||||||
|
|
||||||
|
## Form Example
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story id="components-forms-select-mono--form-example"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
<img src="components/Forms/Select/resources/dd_1.svg"/>
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
<img src="components/Forms/Select/resources/dd_2.svg"/>
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
<img src="components/Forms/Select/resources/dd_3.svg"/>
|
||||||
352
packages/react/src/components/Forms/Select/index.tsx
Normal file
352
packages/react/src/components/Forms/Select/index.tsx
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
import React, {
|
||||||
|
HTMLAttributes,
|
||||||
|
PropsWithChildren,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
import {
|
||||||
|
useCombobox,
|
||||||
|
useSelect,
|
||||||
|
UseSelectReturnValue,
|
||||||
|
UseSelectStateChange,
|
||||||
|
} from "downshift";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { useCunningham } from ":/components/Provider";
|
||||||
|
import { Field, FieldProps } from ":/components/Forms/Field";
|
||||||
|
import { LabelledBox } from ":/components/Forms/LabelledBox";
|
||||||
|
import { Button } from ":/components/Button";
|
||||||
|
|
||||||
|
interface Option {
|
||||||
|
value?: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = PropsWithChildren &
|
||||||
|
FieldProps & {
|
||||||
|
label: string;
|
||||||
|
options: Option[];
|
||||||
|
searchable?: boolean;
|
||||||
|
name?: string;
|
||||||
|
defaultValue?: string | number;
|
||||||
|
value?: string | number;
|
||||||
|
onChange?: (event: {
|
||||||
|
target: { value: string | number | undefined };
|
||||||
|
}) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getOptionsFilter(inputValue?: string) {
|
||||||
|
return (option: Option) => {
|
||||||
|
return (
|
||||||
|
!inputValue ||
|
||||||
|
option.label.toLowerCase().includes(inputValue.toLowerCase()) ||
|
||||||
|
option.value?.toLowerCase().includes(inputValue.toLowerCase())
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionToString = (option: Option | null) => {
|
||||||
|
return option ? option.label : "";
|
||||||
|
};
|
||||||
|
|
||||||
|
const optionToValue = (option: Option) => {
|
||||||
|
return option.value ?? option.label;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SubProps extends Props {
|
||||||
|
defaultSelectedItem?: Option;
|
||||||
|
downshiftProps: {
|
||||||
|
initialSelectedItem?: Option;
|
||||||
|
onSelectedItemChange?: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SelectAuxProps extends SubProps {
|
||||||
|
options: Option[];
|
||||||
|
labelAsPlaceholder: boolean;
|
||||||
|
downshiftReturn: {
|
||||||
|
isOpen: boolean;
|
||||||
|
wrapperProps?: HTMLAttributes<HTMLDivElement>;
|
||||||
|
selectedItem?: Option | null;
|
||||||
|
getLabelProps: any;
|
||||||
|
toggleButtonProps: any;
|
||||||
|
getMenuProps: any;
|
||||||
|
getItemProps: any;
|
||||||
|
highlightedIndex: number;
|
||||||
|
selectItem: UseSelectReturnValue<Option>["selectItem"];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component is used by searchable and non-searchable select components.
|
||||||
|
* It contains the common logic between the two.
|
||||||
|
*/
|
||||||
|
const SelectAux = ({
|
||||||
|
children,
|
||||||
|
state = "default",
|
||||||
|
text,
|
||||||
|
rightText,
|
||||||
|
fullWidth,
|
||||||
|
options,
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
labelAsPlaceholder,
|
||||||
|
downshiftProps,
|
||||||
|
downshiftReturn,
|
||||||
|
value,
|
||||||
|
disabled,
|
||||||
|
}: SelectAuxProps) => {
|
||||||
|
const { t } = useCunningham();
|
||||||
|
const labelProps = downshiftReturn.getLabelProps();
|
||||||
|
|
||||||
|
// When component is controlled, this useEffect will update the local selected item.
|
||||||
|
useEffect(() => {
|
||||||
|
if (downshiftProps.initialSelectedItem !== undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const optionToSelect = options.find(
|
||||||
|
(option) => optionToValue(option) === value
|
||||||
|
);
|
||||||
|
downshiftReturn.selectItem(optionToSelect ?? null);
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Field
|
||||||
|
state={state}
|
||||||
|
text={text}
|
||||||
|
rightText={rightText}
|
||||||
|
fullWidth={fullWidth}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={classNames("c__select", "c__select--" + state, {
|
||||||
|
"c__select--disabled": disabled,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{/* We disabled linting for this specific line because we consider that the onClick props is only used for */}
|
||||||
|
{/* mouse users, so this do not engender any issue for accessibility. */}
|
||||||
|
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
|
||||||
|
<div
|
||||||
|
className={classNames("c__select__wrapper", {
|
||||||
|
"c__select__wrapper--focus": downshiftReturn.isOpen && !disabled,
|
||||||
|
})}
|
||||||
|
{...downshiftReturn.wrapperProps}
|
||||||
|
>
|
||||||
|
{downshiftReturn.selectedItem && (
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name={name}
|
||||||
|
value={optionToValue(downshiftReturn.selectedItem)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<LabelledBox
|
||||||
|
label={label}
|
||||||
|
labelAsPlaceholder={labelAsPlaceholder}
|
||||||
|
htmlFor={labelProps.htmlFor}
|
||||||
|
labelId={labelProps.id}
|
||||||
|
>
|
||||||
|
<div className="c__select__inner">
|
||||||
|
<div className="c__select__inner__value">{children}</div>
|
||||||
|
<div className="c__select__inner__actions">
|
||||||
|
{!disabled && downshiftReturn.selectedItem && (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
color="tertiary"
|
||||||
|
size="small"
|
||||||
|
aria-label={t(
|
||||||
|
"components.forms.select.clear_button_aria_label"
|
||||||
|
)}
|
||||||
|
className="c__select__inner__actions__clear"
|
||||||
|
onClick={(e) => {
|
||||||
|
downshiftReturn.selectItem(null);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
icon={<span className="material-icons">close</span>}
|
||||||
|
/>
|
||||||
|
<div className="c__select__inner__actions__separator" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color="tertiary"
|
||||||
|
size="small"
|
||||||
|
className="c__select__inner__actions__open"
|
||||||
|
icon={
|
||||||
|
<span
|
||||||
|
className={classNames("material-icons", {
|
||||||
|
opened: downshiftReturn.isOpen,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
arrow_drop_down
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
disabled={disabled}
|
||||||
|
{...downshiftReturn.toggleButtonProps}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LabelledBox>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={classNames("c__select__menu", {
|
||||||
|
"c__select__menu--opened": downshiftReturn.isOpen,
|
||||||
|
})}
|
||||||
|
{...downshiftReturn.getMenuProps()}
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
{downshiftReturn.isOpen &&
|
||||||
|
options.map((item, index) => (
|
||||||
|
<li
|
||||||
|
className={classNames("c__select__menu__item", {
|
||||||
|
"c__select__menu__item--highlight":
|
||||||
|
downshiftReturn.highlightedIndex === index,
|
||||||
|
"c__select__menu__item--selected":
|
||||||
|
downshiftReturn.selectedItem === item,
|
||||||
|
})}
|
||||||
|
key={`${item.value}${index}`}
|
||||||
|
{...downshiftReturn.getItemProps({ item, index })}
|
||||||
|
>
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Field>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SelectSimple = (props: SubProps) => {
|
||||||
|
const downshiftReturn = useSelect({
|
||||||
|
...props.downshiftProps,
|
||||||
|
items: props.options,
|
||||||
|
itemToString: optionToString,
|
||||||
|
});
|
||||||
|
const [labelAsPlaceholder, setLabelAsPlaceholder] = useState(
|
||||||
|
!downshiftReturn.selectedItem
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLabelAsPlaceholder(!downshiftReturn.selectedItem);
|
||||||
|
}, [downshiftReturn.selectedItem]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SelectAux
|
||||||
|
{...props}
|
||||||
|
downshiftReturn={{
|
||||||
|
...downshiftReturn,
|
||||||
|
wrapperProps: downshiftReturn.getToggleButtonProps({
|
||||||
|
disabled: props.disabled,
|
||||||
|
}),
|
||||||
|
toggleButtonProps: {},
|
||||||
|
}}
|
||||||
|
labelAsPlaceholder={labelAsPlaceholder}
|
||||||
|
>
|
||||||
|
{downshiftReturn.selectedItem && (
|
||||||
|
<span>{optionToString(downshiftReturn.selectedItem)}</span>
|
||||||
|
)}
|
||||||
|
</SelectAux>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SelectSearchable = (props: SubProps) => {
|
||||||
|
const { t } = useCunningham();
|
||||||
|
const [optionsToDisplay, setOptionsToDisplay] = useState(props.options);
|
||||||
|
const [hasInputFocused, setHasInputFocused] = useState(false);
|
||||||
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
const downshiftReturn = useCombobox({
|
||||||
|
...props.downshiftProps,
|
||||||
|
items: optionsToDisplay,
|
||||||
|
itemToString: optionToString,
|
||||||
|
onInputValueChange: (e) => {
|
||||||
|
setOptionsToDisplay(props.options.filter(getOptionsFilter(e.inputValue)));
|
||||||
|
if (!e.inputValue) {
|
||||||
|
downshiftReturn.selectItem(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [labelAsPlaceholder, setLabelAsPlaceholder] = useState(
|
||||||
|
!downshiftReturn.selectedItem
|
||||||
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
if (hasInputFocused || downshiftReturn.inputValue) {
|
||||||
|
setLabelAsPlaceholder(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLabelAsPlaceholder(!downshiftReturn.selectedItem);
|
||||||
|
}, [
|
||||||
|
downshiftReturn.selectedItem,
|
||||||
|
hasInputFocused,
|
||||||
|
downshiftReturn.inputValue,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const inputProps = downshiftReturn.getInputProps({
|
||||||
|
ref: inputRef,
|
||||||
|
disabled: props.disabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SelectAux
|
||||||
|
{...props}
|
||||||
|
downshiftReturn={{
|
||||||
|
...downshiftReturn,
|
||||||
|
wrapperProps: {
|
||||||
|
onClick: () => {
|
||||||
|
inputRef.current?.focus();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
toggleButtonProps: downshiftReturn.getToggleButtonProps({
|
||||||
|
disabled: props.disabled,
|
||||||
|
"aria-label": t("components.forms.select.toggle_button_aria_label"),
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
labelAsPlaceholder={labelAsPlaceholder}
|
||||||
|
options={optionsToDisplay}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="w-full p-1.5"
|
||||||
|
{...inputProps}
|
||||||
|
onFocus={(e) => {
|
||||||
|
inputProps.onFocus(e);
|
||||||
|
setHasInputFocused(true);
|
||||||
|
}}
|
||||||
|
onBlur={(e) => {
|
||||||
|
inputProps.onBlur(e);
|
||||||
|
setHasInputFocused(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SelectAux>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Select = (props: Props) => {
|
||||||
|
if (props.defaultValue && props.value) {
|
||||||
|
throw new Error(
|
||||||
|
"You cannot use both defaultValue and value props on Select component"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultSelectedItem = props.defaultValue
|
||||||
|
? props.options.find(
|
||||||
|
(option) => optionToValue(option) === props.defaultValue
|
||||||
|
)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const commonDownshiftProps: SubProps["downshiftProps"] = {
|
||||||
|
initialSelectedItem: defaultSelectedItem,
|
||||||
|
onSelectedItemChange: (e: UseSelectStateChange<Option>) => {
|
||||||
|
props.onChange?.({
|
||||||
|
target: {
|
||||||
|
value: e.selectedItem ? optionToValue(e.selectedItem) : undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return props.searchable ? (
|
||||||
|
<SelectSearchable {...props} downshiftProps={commonDownshiftProps} />
|
||||||
|
) : (
|
||||||
|
<SelectSimple {...props} downshiftProps={commonDownshiftProps} />
|
||||||
|
);
|
||||||
|
};
|
||||||
258
packages/react/src/components/Forms/Select/mono.stories.tsx
Normal file
258
packages/react/src/components/Forms/Select/mono.stories.tsx
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
import { ComponentMeta, ComponentStory } from "@storybook/react";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { faker } from "@faker-js/faker";
|
||||||
|
import { Select } from ":/components/Forms/Select";
|
||||||
|
import { Button } from ":/components/Button";
|
||||||
|
import { CunninghamProvider } from ":/components/Provider";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Components/Forms/Select/Mono",
|
||||||
|
component: Select,
|
||||||
|
} as ComponentMeta<typeof Select>;
|
||||||
|
|
||||||
|
const Template: ComponentStory<typeof Select> = (args) => (
|
||||||
|
<div style={{ paddingBottom: "200px" }}>
|
||||||
|
<CunninghamProvider>
|
||||||
|
<Select {...args} />
|
||||||
|
</CunninghamProvider>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const CITIES = Array.from({ length: 10 }).map(() => faker.address.city());
|
||||||
|
const OPTIONS = CITIES.map((city) => ({
|
||||||
|
label: city,
|
||||||
|
value: city.toLowerCase(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const Uncontrolled = Template.bind({});
|
||||||
|
Uncontrolled.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
defaultValue: OPTIONS[4].value,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Disabled = Template.bind({});
|
||||||
|
Disabled.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
defaultValue: OPTIONS[4].value,
|
||||||
|
disabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WithText = Template.bind({});
|
||||||
|
WithText.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
defaultValue: OPTIONS[4].value,
|
||||||
|
text: "This is a text, you can display anything you want here like warnings, information or errors.",
|
||||||
|
};
|
||||||
|
export const Controlled = () => {
|
||||||
|
const [value, setValue] = useState(OPTIONS[8].value);
|
||||||
|
return (
|
||||||
|
<CunninghamProvider>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
Value: <span>{value}</span>
|
||||||
|
</div>
|
||||||
|
<Select
|
||||||
|
label="Select a city"
|
||||||
|
options={OPTIONS}
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => setValue(e.target.value as string)}
|
||||||
|
/>
|
||||||
|
<Button onClick={() => setValue("")}>Reset</Button>
|
||||||
|
</div>
|
||||||
|
</CunninghamProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Overflow = Template.bind({});
|
||||||
|
Overflow.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: "1",
|
||||||
|
label: "Very long long long long long long long city name",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: "1",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SearchableEmpty = Template.bind({});
|
||||||
|
SearchableEmpty.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
searchable: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SearchableUncontrolled = Template.bind({});
|
||||||
|
SearchableUncontrolled.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
defaultValue: OPTIONS[4].value,
|
||||||
|
searchable: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SearchableDisabled = Template.bind({});
|
||||||
|
SearchableDisabled.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
defaultValue: OPTIONS[4].value,
|
||||||
|
searchable: true,
|
||||||
|
disabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SearchableControlled = () => {
|
||||||
|
const [value, setValue] = useState(OPTIONS[8].value);
|
||||||
|
return (
|
||||||
|
<CunninghamProvider>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
Value: <span>{value}</span>
|
||||||
|
</div>
|
||||||
|
<Select
|
||||||
|
label="Select a city"
|
||||||
|
options={OPTIONS}
|
||||||
|
searchable={true}
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => setValue(e.target.value as string)}
|
||||||
|
/>
|
||||||
|
<Button onClick={() => setValue("")}>Reset</Button>
|
||||||
|
</div>
|
||||||
|
</CunninghamProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FullWidth = Template.bind({});
|
||||||
|
FullWidth.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
fullWidth: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Success = Template.bind({});
|
||||||
|
Success.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
state: "success",
|
||||||
|
text: "Well done",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Error = Template.bind({});
|
||||||
|
Error.args = {
|
||||||
|
label: "Select a city",
|
||||||
|
options: OPTIONS,
|
||||||
|
state: "error",
|
||||||
|
text: "Something went wrong",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FormExample = () => {
|
||||||
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const data = new FormData(e.target as any);
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(data.getAll("city"));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CunninghamProvider>
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="mb-s">
|
||||||
|
<Select
|
||||||
|
label="Your city"
|
||||||
|
name="city"
|
||||||
|
options={OPTIONS}
|
||||||
|
defaultValue={OPTIONS[2].value}
|
||||||
|
text="The city you were born in"
|
||||||
|
state="success"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-s">
|
||||||
|
<Select
|
||||||
|
label="Your gender"
|
||||||
|
name="gender"
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: "Male",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Female",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Other",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-s">
|
||||||
|
<Select
|
||||||
|
label="Your department"
|
||||||
|
name="department"
|
||||||
|
searchable={true}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: "Legal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tech",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "AI",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Accounting",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-s">
|
||||||
|
<Select
|
||||||
|
label="Your grade"
|
||||||
|
text="Any error you want"
|
||||||
|
name="grade"
|
||||||
|
searchable={true}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: "Level 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Level 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Level 3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Emperor",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
state="error"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-s">
|
||||||
|
<Select
|
||||||
|
label="Your plan"
|
||||||
|
text="This field is disabled"
|
||||||
|
name="grade"
|
||||||
|
disabled={true}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: "Bronze",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Silver",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Gold",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Platinum",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
defaultValue="Platinum"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button>Submit</Button>
|
||||||
|
</form>
|
||||||
|
</CunninghamProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
127
packages/react/src/components/Forms/Select/resources/dd_1.svg
Normal file
127
packages/react/src/components/Forms/Select/resources/dd_1.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 266 KiB |
128
packages/react/src/components/Forms/Select/resources/dd_2.svg
Normal file
128
packages/react/src/components/Forms/Select/resources/dd_2.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 364 KiB |
135
packages/react/src/components/Forms/Select/resources/dd_3.svg
Normal file
135
packages/react/src/components/Forms/Select/resources/dd_3.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 268 KiB |
21
packages/react/src/components/Forms/Select/tokens.ts
Normal file
21
packages/react/src/components/Forms/Select/tokens.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { DefaultTokens } from "@openfun/cunningham-tokens";
|
||||||
|
|
||||||
|
export const tokens = (defaults: DefaultTokens) => ({
|
||||||
|
"border-color": defaults.theme.colors["greyscale-300"],
|
||||||
|
"border-color--focus": defaults.theme.colors["primary-600"],
|
||||||
|
"border-color--hover": defaults.theme.colors["greyscale-500"],
|
||||||
|
"border-radius": "8px",
|
||||||
|
"border-radius--focus": "2px",
|
||||||
|
"border-radius--hover": "2px",
|
||||||
|
"border-style": "solid",
|
||||||
|
"border-width": "2px",
|
||||||
|
color: defaults.theme.colors["greyscale-800"],
|
||||||
|
"font-size": defaults.theme.font.sizes.l,
|
||||||
|
height: "3.5rem",
|
||||||
|
"item-background-color--hover": defaults.theme.colors["greyscale-200"],
|
||||||
|
"item-background-color--selected": defaults.theme.colors["primary-100"],
|
||||||
|
"item-color": defaults.theme.colors["greyscale-800"],
|
||||||
|
"item-font-size": defaults.theme.font.sizes.l,
|
||||||
|
"background-color": "white",
|
||||||
|
"menu-background-color": "white",
|
||||||
|
});
|
||||||
@@ -96,6 +96,23 @@
|
|||||||
--c--theme--transitions--ease-out: cubic-bezier(0.33, 1, 0.68, 1);
|
--c--theme--transitions--ease-out: cubic-bezier(0.33, 1, 0.68, 1);
|
||||||
--c--theme--transitions--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
--c--theme--transitions--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
||||||
--c--theme--transitions--duration: 250ms;
|
--c--theme--transitions--duration: 250ms;
|
||||||
|
--c--components--forms-select--border-color: #E7E8EA;
|
||||||
|
--c--components--forms-select--border-color--focus: #0556BF;
|
||||||
|
--c--components--forms-select--border-color--hover: #9EA3AA;
|
||||||
|
--c--components--forms-select--border-radius: 8px;
|
||||||
|
--c--components--forms-select--border-radius--focus: 2px;
|
||||||
|
--c--components--forms-select--border-radius--hover: 2px;
|
||||||
|
--c--components--forms-select--border-style: solid;
|
||||||
|
--c--components--forms-select--border-width: 2px;
|
||||||
|
--c--components--forms-select--color: #303C4B;
|
||||||
|
--c--components--forms-select--font-size: 1rem;
|
||||||
|
--c--components--forms-select--height: 3.5rem;
|
||||||
|
--c--components--forms-select--item-background-color--hover: #F3F4F4;
|
||||||
|
--c--components--forms-select--item-background-color--selected: #EBF2FC;
|
||||||
|
--c--components--forms-select--item-color: #303C4B;
|
||||||
|
--c--components--forms-select--item-font-size: 1rem;
|
||||||
|
--c--components--forms-select--background-color: white;
|
||||||
|
--c--components--forms-select--menu-background-color: white;
|
||||||
--c--components--forms-radio--border-color: #E7E8EA;
|
--c--components--forms-radio--border-color: #E7E8EA;
|
||||||
--c--components--forms-radio--accent-color: #419A14;
|
--c--components--forms-radio--accent-color: #419A14;
|
||||||
--c--components--forms-input--font-weight: 400;
|
--c--components--forms-input--font-weight: 400;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export const tokens = {"theme":{"colors":{"primary-text":"#FFFFFF","primary-100":"#EBF2FC","primary-200":"#8CB5EA","primary-300":"#5894E1","primary-400":"#377FDB","primary-500":"#055FD2","primary-600":"#0556BF","primary-700":"#044395","primary-800":"#033474","primary-900":"#022858","secondary-text":"#555F6B","secondary-100":"#F2F7FC","secondary-200":"#EBF3FA","secondary-300":"#E2EEF8","secondary-400":"#DDEAF7","secondary-500":"#D4E5F5","secondary-600":"#C1D0DF","secondary-700":"#97A3AE","secondary-800":"#757E87","secondary-900":"#596067","greyscale-000":"#FFFFFF","greyscale-100":"#FAFAFB","greyscale-200":"#F3F4F4","greyscale-300":"#E7E8EA","greyscale-400":"#C2C6CA","greyscale-500":"#9EA3AA","greyscale-600":"#79818A","greyscale-700":"#555F6B","greyscale-800":"#303C4B","greyscale-900":"#0C1A2B","success-text":"#FFFFFF","success-100":"#EFFCD3","success-200":"#DBFAA9","success-300":"#BEF27C","success-400":"#A0E659","success-500":"#76D628","success-600":"#5AB81D","success-700":"#419A14","success-800":"#2C7C0C","success-900":"#1D6607","info-text":"#FFFFFF","info-100":"#EBF2FC","info-200":"#8CB5EA","info-300":"#5894E1","info-400":"#377FDB","info-500":"#055FD2","info-600":"#0556BF","info-700":"#044395","info-800":"#033474","info-900":"#022858","warning-text":"#FFFFFF","warning-100":"#FFF8CD","warning-200":"#FFEF9B","warning-300":"#FFE469","warning-400":"#FFDA43","warning-500":"#FFC805","warning-600":"#DBA603","warning-700":"#B78702","warning-800":"#936901","warning-900":"#7A5400","danger-text":"#FFFFFF","danger-100":"#F4B0B0","danger-200":"#EE8A8A","danger-300":"#E65454","danger-400":"#E13333","danger-500":"#DA0000","danger-600":"#C60000","danger-700":"#9B0000","danger-800":"#780000","danger-900":"#5C0000"},"font":{"sizes":{"h1":"1.75rem","h2":"1.375rem","h3":"1.125rem","h4":"0.8125rem","h5":"0.625rem","h6":"0.5rem","l":"1rem","m":"0.8125rem","s":"0.6875rem"},"weights":{"thin":100,"regular":300,"medium":400,"bold":500,"extrabold":700,"black":900},"families":{"base":"Roboto","accent":"Roboto"}},"spacings":{"xl":"4rem","l":"3rem","b":"1.625rem","s":"1rem","t":"0.5rem","st":"0.25rem"},"transitions":{"ease-in":"cubic-bezier(0.32, 0, 0.67, 0)","ease-out":"cubic-bezier(0.33, 1, 0.68, 1)","ease-in-out":"cubic-bezier(0.65, 0, 0.35, 1)","duration":"250ms"}},"components":{"forms-radio":{"border-color":"#E7E8EA","accent-color":"#419A14"},"forms-input":{"font-weight":400,"font-size":"1rem","border-radius":"8px","border-radius--hover":"2px","border-radius--focus":"2px","border-width":"2px","border-color":"#E7E8EA","border-color--hover":"#9EA3AA","border-color--focus":"#0556BF","border-style":"solid","color":"#303C4B"},"forms-field":{"width":"292px","font-size":"0.6875rem","color":"#79818A"},"forms-checkbox":{"font-size":"0.8125rem","font-weight":400,"color":"#0C1A2B","border-color":"#E7E8EA","border-radius":"2px","accent-color":"#419A14","size":"1.5rem"},"button":{"border-radius":"8px","border-radius--active":"2px","medium-height":"48px","small-height":"32px","medium-font-size":"1rem","small-font-size":"0.8125rem","font-weight":400}}};
|
export const tokens = {"theme":{"colors":{"primary-text":"#FFFFFF","primary-100":"#EBF2FC","primary-200":"#8CB5EA","primary-300":"#5894E1","primary-400":"#377FDB","primary-500":"#055FD2","primary-600":"#0556BF","primary-700":"#044395","primary-800":"#033474","primary-900":"#022858","secondary-text":"#555F6B","secondary-100":"#F2F7FC","secondary-200":"#EBF3FA","secondary-300":"#E2EEF8","secondary-400":"#DDEAF7","secondary-500":"#D4E5F5","secondary-600":"#C1D0DF","secondary-700":"#97A3AE","secondary-800":"#757E87","secondary-900":"#596067","greyscale-000":"#FFFFFF","greyscale-100":"#FAFAFB","greyscale-200":"#F3F4F4","greyscale-300":"#E7E8EA","greyscale-400":"#C2C6CA","greyscale-500":"#9EA3AA","greyscale-600":"#79818A","greyscale-700":"#555F6B","greyscale-800":"#303C4B","greyscale-900":"#0C1A2B","success-text":"#FFFFFF","success-100":"#EFFCD3","success-200":"#DBFAA9","success-300":"#BEF27C","success-400":"#A0E659","success-500":"#76D628","success-600":"#5AB81D","success-700":"#419A14","success-800":"#2C7C0C","success-900":"#1D6607","info-text":"#FFFFFF","info-100":"#EBF2FC","info-200":"#8CB5EA","info-300":"#5894E1","info-400":"#377FDB","info-500":"#055FD2","info-600":"#0556BF","info-700":"#044395","info-800":"#033474","info-900":"#022858","warning-text":"#FFFFFF","warning-100":"#FFF8CD","warning-200":"#FFEF9B","warning-300":"#FFE469","warning-400":"#FFDA43","warning-500":"#FFC805","warning-600":"#DBA603","warning-700":"#B78702","warning-800":"#936901","warning-900":"#7A5400","danger-text":"#FFFFFF","danger-100":"#F4B0B0","danger-200":"#EE8A8A","danger-300":"#E65454","danger-400":"#E13333","danger-500":"#DA0000","danger-600":"#C60000","danger-700":"#9B0000","danger-800":"#780000","danger-900":"#5C0000"},"font":{"sizes":{"h1":"1.75rem","h2":"1.375rem","h3":"1.125rem","h4":"0.8125rem","h5":"0.625rem","h6":"0.5rem","l":"1rem","m":"0.8125rem","s":"0.6875rem"},"weights":{"thin":100,"regular":300,"medium":400,"bold":500,"extrabold":700,"black":900},"families":{"base":"Roboto","accent":"Roboto"}},"spacings":{"xl":"4rem","l":"3rem","b":"1.625rem","s":"1rem","t":"0.5rem","st":"0.25rem"},"transitions":{"ease-in":"cubic-bezier(0.32, 0, 0.67, 0)","ease-out":"cubic-bezier(0.33, 1, 0.68, 1)","ease-in-out":"cubic-bezier(0.65, 0, 0.35, 1)","duration":"250ms"}},"components":{"forms-select":{"border-color":"#E7E8EA","border-color--focus":"#0556BF","border-color--hover":"#9EA3AA","border-radius":"8px","border-radius--focus":"2px","border-radius--hover":"2px","border-style":"solid","border-width":"2px","color":"#303C4B","font-size":"1rem","height":"3.5rem","item-background-color--hover":"#F3F4F4","item-background-color--selected":"#EBF2FC","item-color":"#303C4B","item-font-size":"1rem","background-color":"white","menu-background-color":"white"},"forms-radio":{"border-color":"#E7E8EA","accent-color":"#419A14"},"forms-input":{"font-weight":400,"font-size":"1rem","border-radius":"8px","border-radius--hover":"2px","border-radius--focus":"2px","border-width":"2px","border-color":"#E7E8EA","border-color--hover":"#9EA3AA","border-color--focus":"#0556BF","border-style":"solid","color":"#303C4B"},"forms-field":{"width":"292px","font-size":"0.6875rem","color":"#79818A"},"forms-checkbox":{"font-size":"0.8125rem","font-weight":400,"color":"#0C1A2B","border-color":"#E7E8EA","border-radius":"2px","accent-color":"#419A14","size":"1.5rem"},"button":{"border-radius":"8px","border-radius--active":"2px","medium-height":"48px","small-height":"32px","medium-font-size":"1rem","small-font-size":"0.8125rem","font-weight":400}}};
|
||||||
|
|||||||
@@ -1,151 +1 @@
|
|||||||
export const tokens = {
|
export const tokens = {"theme":{"colors":{"primary-text":"#FFFFFF","primary-100":"#EBF2FC","primary-200":"#8CB5EA","primary-300":"#5894E1","primary-400":"#377FDB","primary-500":"#055FD2","primary-600":"#0556BF","primary-700":"#044395","primary-800":"#033474","primary-900":"#022858","secondary-text":"#555F6B","secondary-100":"#F2F7FC","secondary-200":"#EBF3FA","secondary-300":"#E2EEF8","secondary-400":"#DDEAF7","secondary-500":"#D4E5F5","secondary-600":"#C1D0DF","secondary-700":"#97A3AE","secondary-800":"#757E87","secondary-900":"#596067","greyscale-000":"#FFFFFF","greyscale-100":"#FAFAFB","greyscale-200":"#F3F4F4","greyscale-300":"#E7E8EA","greyscale-400":"#C2C6CA","greyscale-500":"#9EA3AA","greyscale-600":"#79818A","greyscale-700":"#555F6B","greyscale-800":"#303C4B","greyscale-900":"#0C1A2B","success-text":"#FFFFFF","success-100":"#EFFCD3","success-200":"#DBFAA9","success-300":"#BEF27C","success-400":"#A0E659","success-500":"#76D628","success-600":"#5AB81D","success-700":"#419A14","success-800":"#2C7C0C","success-900":"#1D6607","info-text":"#FFFFFF","info-100":"#EBF2FC","info-200":"#8CB5EA","info-300":"#5894E1","info-400":"#377FDB","info-500":"#055FD2","info-600":"#0556BF","info-700":"#044395","info-800":"#033474","info-900":"#022858","warning-text":"#FFFFFF","warning-100":"#FFF8CD","warning-200":"#FFEF9B","warning-300":"#FFE469","warning-400":"#FFDA43","warning-500":"#FFC805","warning-600":"#DBA603","warning-700":"#B78702","warning-800":"#936901","warning-900":"#7A5400","danger-text":"#FFFFFF","danger-100":"#F4B0B0","danger-200":"#EE8A8A","danger-300":"#E65454","danger-400":"#E13333","danger-500":"#DA0000","danger-600":"#C60000","danger-700":"#9B0000","danger-800":"#780000","danger-900":"#5C0000"},"font":{"sizes":{"h1":"1.75rem","h2":"1.375rem","h3":"1.125rem","h4":"0.8125rem","h5":"0.625rem","h6":"0.5rem","l":"1rem","m":"0.8125rem","s":"0.6875rem"},"weights":{"thin":100,"regular":300,"medium":400,"bold":500,"extrabold":700,"black":900},"families":{"base":"Roboto","accent":"Roboto"}},"spacings":{"xl":"4rem","l":"3rem","b":"1.625rem","s":"1rem","t":"0.5rem","st":"0.25rem"},"transitions":{"ease-in":"cubic-bezier(0.32, 0, 0.67, 0)","ease-out":"cubic-bezier(0.33, 1, 0.68, 1)","ease-in-out":"cubic-bezier(0.65, 0, 0.35, 1)","duration":"250ms"}},"components":{"forms-select":{"border-color":"#E7E8EA","border-color--focus":"#0556BF","border-color--hover":"#9EA3AA","border-radius":"8px","border-radius--focus":"2px","border-radius--hover":"2px","border-style":"solid","border-width":"2px","color":"#303C4B","font-size":"1rem","height":"3.5rem","item-background-color--hover":"#F3F4F4","item-background-color--selected":"#EBF2FC","item-color":"#303C4B","item-font-size":"1rem","background-color":"white","menu-background-color":"white"},"forms-radio":{"border-color":"#E7E8EA","accent-color":"#419A14"},"forms-input":{"font-weight":400,"font-size":"1rem","border-radius":"8px","border-radius--hover":"2px","border-radius--focus":"2px","border-width":"2px","border-color":"#E7E8EA","border-color--hover":"#9EA3AA","border-color--focus":"#0556BF","border-style":"solid","color":"#303C4B"},"forms-field":{"width":"292px","font-size":"0.6875rem","color":"#79818A"},"forms-checkbox":{"font-size":"0.8125rem","font-weight":400,"color":"#0C1A2B","border-color":"#E7E8EA","border-radius":"2px","accent-color":"#419A14","size":"1.5rem"},"button":{"border-radius":"8px","border-radius--active":"2px","medium-height":"48px","small-height":"32px","medium-font-size":"1rem","small-font-size":"0.8125rem","font-weight":400}}};
|
||||||
theme: {
|
|
||||||
colors: {
|
|
||||||
"primary-text": "#FFFFFF",
|
|
||||||
"primary-100": "#EBF2FC",
|
|
||||||
"primary-200": "#8CB5EA",
|
|
||||||
"primary-300": "#5894E1",
|
|
||||||
"primary-400": "#377FDB",
|
|
||||||
"primary-500": "#055FD2",
|
|
||||||
"primary-600": "#0556BF",
|
|
||||||
"primary-700": "#044395",
|
|
||||||
"primary-800": "#033474",
|
|
||||||
"primary-900": "#022858",
|
|
||||||
"secondary-text": "#555F6B",
|
|
||||||
"secondary-100": "#F2F7FC",
|
|
||||||
"secondary-200": "#EBF3FA",
|
|
||||||
"secondary-300": "#E2EEF8",
|
|
||||||
"secondary-400": "#DDEAF7",
|
|
||||||
"secondary-500": "#D4E5F5",
|
|
||||||
"secondary-600": "#C1D0DF",
|
|
||||||
"secondary-700": "#97A3AE",
|
|
||||||
"secondary-800": "#757E87",
|
|
||||||
"secondary-900": "#596067",
|
|
||||||
"greyscale-000": "#FFFFFF",
|
|
||||||
"greyscale-100": "#FAFAFB",
|
|
||||||
"greyscale-200": "#F3F4F4",
|
|
||||||
"greyscale-300": "#E7E8EA",
|
|
||||||
"greyscale-400": "#C2C6CA",
|
|
||||||
"greyscale-500": "#9EA3AA",
|
|
||||||
"greyscale-600": "#79818A",
|
|
||||||
"greyscale-700": "#555F6B",
|
|
||||||
"greyscale-800": "#303C4B",
|
|
||||||
"greyscale-900": "#0C1A2B",
|
|
||||||
"success-text": "#FFFFFF",
|
|
||||||
"success-100": "#EFFCD3",
|
|
||||||
"success-200": "#DBFAA9",
|
|
||||||
"success-300": "#BEF27C",
|
|
||||||
"success-400": "#A0E659",
|
|
||||||
"success-500": "#76D628",
|
|
||||||
"success-600": "#5AB81D",
|
|
||||||
"success-700": "#419A14",
|
|
||||||
"success-800": "#2C7C0C",
|
|
||||||
"success-900": "#1D6607",
|
|
||||||
"info-text": "#FFFFFF",
|
|
||||||
"info-100": "#EBF2FC",
|
|
||||||
"info-200": "#8CB5EA",
|
|
||||||
"info-300": "#5894E1",
|
|
||||||
"info-400": "#377FDB",
|
|
||||||
"info-500": "#055FD2",
|
|
||||||
"info-600": "#0556BF",
|
|
||||||
"info-700": "#044395",
|
|
||||||
"info-800": "#033474",
|
|
||||||
"info-900": "#022858",
|
|
||||||
"warning-text": "#FFFFFF",
|
|
||||||
"warning-100": "#FFF8CD",
|
|
||||||
"warning-200": "#FFEF9B",
|
|
||||||
"warning-300": "#FFE469",
|
|
||||||
"warning-400": "#FFDA43",
|
|
||||||
"warning-500": "#FFC805",
|
|
||||||
"warning-600": "#DBA603",
|
|
||||||
"warning-700": "#B78702",
|
|
||||||
"warning-800": "#936901",
|
|
||||||
"warning-900": "#7A5400",
|
|
||||||
"danger-text": "#FFFFFF",
|
|
||||||
"danger-100": "#F4B0B0",
|
|
||||||
"danger-200": "#EE8A8A",
|
|
||||||
"danger-300": "#E65454",
|
|
||||||
"danger-400": "#E13333",
|
|
||||||
"danger-500": "#DA0000",
|
|
||||||
"danger-600": "#C60000",
|
|
||||||
"danger-700": "#9B0000",
|
|
||||||
"danger-800": "#780000",
|
|
||||||
"danger-900": "#5C0000",
|
|
||||||
},
|
|
||||||
font: {
|
|
||||||
sizes: {
|
|
||||||
h1: "1.75rem",
|
|
||||||
h2: "1.375rem",
|
|
||||||
h3: "1.125rem",
|
|
||||||
h4: "0.8125rem",
|
|
||||||
h5: "0.625rem",
|
|
||||||
h6: "0.5rem",
|
|
||||||
l: "1rem",
|
|
||||||
m: "0.8125rem",
|
|
||||||
s: "0.6875rem",
|
|
||||||
},
|
|
||||||
weights: {
|
|
||||||
thin: 100,
|
|
||||||
regular: 300,
|
|
||||||
medium: 400,
|
|
||||||
bold: 500,
|
|
||||||
extrabold: 700,
|
|
||||||
black: 900,
|
|
||||||
},
|
|
||||||
families: { base: "Roboto", accent: "Roboto" },
|
|
||||||
},
|
|
||||||
spacings: {
|
|
||||||
xl: "4rem",
|
|
||||||
l: "3rem",
|
|
||||||
b: "1.625rem",
|
|
||||||
s: "1rem",
|
|
||||||
t: "0.5rem",
|
|
||||||
st: "0.25rem",
|
|
||||||
},
|
|
||||||
transitions: {
|
|
||||||
"ease-in": "cubic-bezier(0.32, 0, 0.67, 0)",
|
|
||||||
"ease-out": "cubic-bezier(0.33, 1, 0.68, 1)",
|
|
||||||
"ease-in-out": "cubic-bezier(0.65, 0, 0.35, 1)",
|
|
||||||
duration: "250ms",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
"forms-radio": { "border-color": "#E7E8EA", "accent-color": "#419A14" },
|
|
||||||
"forms-input": {
|
|
||||||
"font-weight": 400,
|
|
||||||
"font-size": "1rem",
|
|
||||||
"border-radius": "8px",
|
|
||||||
"border-radius--hover": "2px",
|
|
||||||
"border-radius--focus": "2px",
|
|
||||||
"border-width": "2px",
|
|
||||||
"border-color": "#E7E8EA",
|
|
||||||
"border-color--hover": "#9EA3AA",
|
|
||||||
"border-color--focus": "#0556BF",
|
|
||||||
"border-style": "solid",
|
|
||||||
color: "#303C4B",
|
|
||||||
},
|
|
||||||
"forms-field": {
|
|
||||||
width: "292px",
|
|
||||||
"font-size": "0.6875rem",
|
|
||||||
color: "#79818A",
|
|
||||||
},
|
|
||||||
"forms-checkbox": {
|
|
||||||
"font-size": "0.8125rem",
|
|
||||||
"font-weight": 400,
|
|
||||||
color: "#0C1A2B",
|
|
||||||
"border-color": "#E7E8EA",
|
|
||||||
"border-radius": "2px",
|
|
||||||
"accent-color": "#419A14",
|
|
||||||
size: "1.5rem",
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
"border-radius": "8px",
|
|
||||||
"border-radius--active": "2px",
|
|
||||||
"medium-height": "48px",
|
|
||||||
"small-height": "32px",
|
|
||||||
"medium-font-size": "1rem",
|
|
||||||
"small-font-size": "0.8125rem",
|
|
||||||
"font-weight": 400,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
@import './components/Forms/Radio';
|
@import './components/Forms/Radio';
|
||||||
@import './components/Forms/Input';
|
@import './components/Forms/Input';
|
||||||
@import './components/Forms/LabelledBox';
|
@import './components/Forms/LabelledBox';
|
||||||
|
@import './components/Forms/Select';
|
||||||
@import './components/Loader';
|
@import './components/Loader';
|
||||||
@import './components/Pagination';
|
@import './components/Pagination';
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export * from "./components/DataGrid/SimpleDataGrid";
|
|||||||
export * from "./components/DataGrid/DataList";
|
export * from "./components/DataGrid/DataList";
|
||||||
export * from "./components/Forms/Field";
|
export * from "./components/Forms/Field";
|
||||||
export * from "./components/Forms/Input";
|
export * from "./components/Forms/Input";
|
||||||
|
export * from "./components/Forms/Select";
|
||||||
export * from "./components/Loader";
|
export * from "./components/Loader";
|
||||||
export * from "./components/Pagination";
|
export * from "./components/Pagination";
|
||||||
export * from "./components/Provider";
|
export * from "./components/Provider";
|
||||||
|
|||||||
@@ -17,6 +17,12 @@
|
|||||||
},
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"test": "This is a test: {name}"
|
"test": "This is a test: {name}"
|
||||||
|
},
|
||||||
|
"forms": {
|
||||||
|
"select": {
|
||||||
|
"toggle_button_aria_label": "Toggle dropdown",
|
||||||
|
"clear_button_aria_label": "Clear selection"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,12 @@
|
|||||||
},
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"test": "Ceci est un test : {name}"
|
"test": "Ceci est un test : {name}"
|
||||||
|
},
|
||||||
|
"forms": {
|
||||||
|
"select": {
|
||||||
|
"toggle_button_aria_label": "Ouvrir le menu",
|
||||||
|
"clear_button_aria_label": "Effacer la sélection"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
yarn.lock
22
yarn.lock
@@ -1330,7 +1330,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.11"
|
regenerator-runtime "^0.13.11"
|
||||||
|
|
||||||
"@babel/runtime@^7.9.2":
|
"@babel/runtime@^7.14.8", "@babel/runtime@^7.9.2":
|
||||||
version "7.21.0"
|
version "7.21.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
|
||||||
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
|
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
|
||||||
@@ -6165,6 +6165,11 @@ compression@^1.7.4:
|
|||||||
safe-buffer "5.1.2"
|
safe-buffer "5.1.2"
|
||||||
vary "~1.1.2"
|
vary "~1.1.2"
|
||||||
|
|
||||||
|
compute-scroll-into-view@^2.0.4:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-2.0.4.tgz#2b444b2b9e4724819d2531efacb7ac094155fdf6"
|
||||||
|
integrity sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g==
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
@@ -6875,6 +6880,17 @@ dotenv@^8.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
|
||||||
integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==
|
integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==
|
||||||
|
|
||||||
|
downshift@^7.6.0:
|
||||||
|
version "7.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/downshift/-/downshift-7.6.0.tgz#de04fb2962bd6c4ea94589c797c91f34aa9816f3"
|
||||||
|
integrity sha512-VSoTVynTAsabou/hbZ6HJHUVhtBiVOjQoBsCPcQq5eAROIGP+9XKMp9asAKQ3cEcUP4oe0fFdD2pziUjhFY33Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.14.8"
|
||||||
|
compute-scroll-into-view "^2.0.4"
|
||||||
|
prop-types "^15.7.2"
|
||||||
|
react-is "^17.0.2"
|
||||||
|
tslib "^2.3.0"
|
||||||
|
|
||||||
duplexify@^3.4.2, duplexify@^3.6.0:
|
duplexify@^3.4.2, duplexify@^3.6.0:
|
||||||
version "3.7.1"
|
version "3.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
|
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
|
||||||
@@ -12264,7 +12280,7 @@ react-inspector@^5.1.0:
|
|||||||
is-dom "^1.0.0"
|
is-dom "^1.0.0"
|
||||||
prop-types "^15.0.0"
|
prop-types "^15.0.0"
|
||||||
|
|
||||||
react-is@17.0.2, react-is@^17.0.1:
|
react-is@17.0.2, react-is@^17.0.1, react-is@^17.0.2:
|
||||||
version "17.0.2"
|
version "17.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||||
@@ -13982,7 +13998,7 @@ tslib@^1.8.1, tslib@^1.9.3:
|
|||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||||
|
|
||||||
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.4.0, tslib@^2.5.0:
|
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.5.0:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
|
||||||
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
|
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
|
||||||
|
|||||||
Reference in New Issue
Block a user