(react) add Select component

Finally our powerful Select component is available to make great forms!
This commit is contained in:
Nathan Vasse
2023-05-05 16:04:50 +02:00
committed by NathanVss
parent 270484c0e7
commit 2ff5fc5d29
21 changed files with 2441 additions and 158 deletions

View File

@@ -0,0 +1,5 @@
---
"@openfun/cunningham-react": minor
---
add Select component

View File

@@ -0,0 +1,5 @@
---
"@openfun/cunningham-react": patch
---
add forwardRef to Button

View File

@@ -0,0 +1,5 @@
---
"@openfun/cunningham-react": patch
---
create a generic LabelledBox

View File

@@ -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": "*",

View 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);
}
}
}
}

File diff suppressed because it is too large Load Diff

View 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"/>

View 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} />
);
};

View 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>
);
};

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 266 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 364 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 268 KiB

View 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",
});

View File

@@ -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;

View File

@@ -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}}};

View File

@@ -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,
},
},
};

View File

@@ -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';

View File

@@ -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";

View File

@@ -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"
}
} }
} }
} }

View File

@@ -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"
}
} }
} }
} }

View File

@@ -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==