@saleor/macaw-ui 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/index.js.map +3 -3
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +3 -3
- package/dist/types/ActionBar/ActionBar.d.ts +1 -0
- package/dist/types/ActionBar/context.d.ts +6 -3
- package/dist/types/Autocomplete/Autocomplete.d.ts +23 -0
- package/dist/types/Autocomplete/Autocomplete.stories.d.ts +5 -0
- package/dist/types/Autocomplete/fixtures.d.ts +4 -0
- package/dist/types/Autocomplete/index.d.ts +1 -0
- package/dist/types/Autocomplete/styles.d.ts +2 -0
- package/dist/types/Chip/Chip.d.ts +8 -0
- package/dist/types/Chip/ChipAdornment.d.ts +6 -0
- package/dist/types/Chip/ChipMovable.d.ts +5 -0
- package/dist/types/Chip/ChipRemovable.d.ts +6 -0
- package/dist/types/Chip/ChipSwatch.d.ts +7 -0
- package/dist/types/Chip/index.d.ts +5 -0
- package/dist/types/Chip/private/ColorSwatch.d.ts +6 -0
- package/dist/types/Chip/styles.d.ts +2 -0
- package/dist/types/CircleIndicator/index.d.ts +1 -1
- package/dist/types/Filter/FilterField/AutocompleteFilterField.d.ts +6 -0
- package/dist/types/Filter/FilterField/MultipleValueAutocompleteFilterField.d.ts +6 -0
- package/dist/types/Filter/stories/Filter.stories.d.ts +5 -0
- package/dist/types/Filter/stories/FilterInteractive.stories.d.ts +4 -0
- package/dist/types/Filter/stories/labels.d.ts +8 -0
- package/dist/types/Filter/styles.d.ts +1 -1
- package/dist/types/Filter/types.d.ts +8 -2
- package/dist/types/Filter/utils.d.ts +4 -1
- package/dist/types/IconButton/IconButton.d.ts +2 -0
- package/dist/types/IconButton/partials.d.ts +1 -1
- package/dist/types/IconButton/styles.d.ts +1 -1
- package/dist/types/MultipleValueAutocomplete/MultipleValueAutocomplete.d.ts +26 -0
- package/dist/types/MultipleValueAutocomplete/MultipleValueAutocomplete.stories.d.ts +6 -0
- package/dist/types/MultipleValueAutocomplete/fixtures.d.ts +4 -0
- package/dist/types/MultipleValueAutocomplete/index.d.ts +1 -0
- package/dist/types/MultipleValueAutocomplete/styles.d.ts +2 -0
- package/dist/types/MultipleValueAutocomplete/useMultipleValueAutocomplete.d.ts +32 -0
- package/dist/types/Savebar/Savebar.d.ts +1 -0
- package/dist/types/Sidebar/MenuItem.d.ts +9 -3
- package/dist/types/Sidebar/types.d.ts +8 -0
- package/dist/types/Sidebar/utils.d.ts +12 -0
- package/dist/types/SidebarDrawer/MenuItemBtn.d.ts +2 -1
- package/dist/types/SwitchSelector/SwitchSelector.d.ts +2 -0
- package/dist/types/SwitchSelector/SwitchSelector.stories.d.ts +4 -0
- package/dist/types/SwitchSelector/SwitchSelectorButton.d.ts +8 -0
- package/dist/types/SwitchSelector/index.d.ts +2 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/theme/ThemeProvider.d.ts +4 -0
- package/dist/types/theme/types.d.ts +1 -0
- package/dist/types/tools/useTextWidth.d.ts +2 -0
- package/dist/types/utils/guideStyles.d.ts +1 -1
- package/dist/types/utils/mergeRefs.d.ts +2 -0
- package/dist/types/utils/useMockAutocomplete.d.ts +10 -0
- package/package.json +11 -13
- package/src/ActionBar/ActionBar.tsx +8 -11
- package/src/ActionBar/context.tsx +15 -6
- package/src/ActionBar/styles.ts +1 -1
- package/src/Autocomplete/Autocomplete.stories.tsx +43 -0
- package/src/Autocomplete/Autocomplete.tsx +187 -0
- package/src/Autocomplete/fixtures.ts +122 -0
- package/src/Autocomplete/index.ts +1 -0
- package/src/Autocomplete/styles.ts +19 -0
- package/src/Backlink/Backlink.tsx +3 -1
- package/src/Chip/Chip.tsx +52 -0
- package/src/Chip/ChipAdornment.tsx +53 -0
- package/src/Chip/ChipMovable.tsx +40 -0
- package/src/Chip/ChipRemovable.tsx +29 -0
- package/src/Chip/ChipSwatch.tsx +42 -0
- package/src/Chip/index.ts +5 -0
- package/src/Chip/private/ColorSwatch.tsx +21 -0
- package/src/Chip/styles.ts +46 -0
- package/src/CircleIndicator/CircleIndicator.stories.tsx +6 -6
- package/src/CircleIndicator/index.ts +1 -1
- package/src/Filter/Filter.tsx +88 -44
- package/src/Filter/FilterBar.tsx +15 -9
- package/src/Filter/FilterContent.tsx +8 -1
- package/src/Filter/FilterField/AutocompleteFilterField.tsx +61 -0
- package/src/Filter/FilterField/MultipleSelectFilterField.tsx +9 -3
- package/src/Filter/FilterField/MultipleValueAutocompleteFilterField.tsx +60 -0
- package/src/Filter/context.tsx +1 -1
- package/src/Filter/{Filter.stories.tsx → stories/Filter.stories.tsx} +47 -13
- package/src/Filter/stories/FilterInteractive.stories.tsx +97 -0
- package/src/Filter/stories/labels.ts +8 -0
- package/src/Filter/styles.ts +37 -6
- package/src/Filter/types.ts +8 -1
- package/src/Filter/utils.ts +71 -5
- package/src/IconButton/IconButton.tsx +17 -2
- package/src/IconButton/partials.ts +1 -1
- package/src/IconButton/styles.ts +38 -16
- package/src/MultipleValueAutocomplete/MultipleValueAutocomplete.stories.tsx +76 -0
- package/src/MultipleValueAutocomplete/MultipleValueAutocomplete.tsx +185 -0
- package/src/MultipleValueAutocomplete/fixtures.ts +122 -0
- package/src/MultipleValueAutocomplete/index.ts +1 -0
- package/src/MultipleValueAutocomplete/styles.ts +39 -0
- package/src/MultipleValueAutocomplete/useMultipleValueAutocomplete.ts +172 -0
- package/src/Savebar/Savebar.tsx +3 -4
- package/src/Sidebar/MenuItem.tsx +35 -14
- package/src/Sidebar/Sidebar.tsx +27 -11
- package/src/Sidebar/types.ts +9 -0
- package/src/Sidebar/utils.ts +23 -0
- package/src/SidebarDrawer/MenuItemBtn.tsx +12 -6
- package/src/SidebarDrawer/SidebarDrawer.tsx +8 -2
- package/src/SwitchSelector/SwitchSelector.stories.tsx +63 -0
- package/src/SwitchSelector/SwitchSelector.tsx +19 -0
- package/src/SwitchSelector/SwitchSelectorButton.tsx +59 -0
- package/src/SwitchSelector/index.ts +2 -0
- package/src/index.tsx +4 -1
- package/src/theme/ThemeProvider.tsx +6 -0
- package/src/theme/createSaleorTheme/createSaleorTheme.tsx +2 -1
- package/src/theme/createSaleorTheme/overrides/controls.ts +4 -1
- package/src/theme/createSaleorTheme/overrides/inputs.ts +1 -1
- package/src/theme/themes.ts +1 -1
- package/src/theme/types.ts +1 -0
- package/src/tools/useTextWidth.ts +20 -0
- package/src/utils/guideStyles.ts +5 -0
- package/src/utils/mergeRefs.ts +14 -0
- package/src/utils/useMockAutocomplete.ts +37 -0
package/src/Sidebar/Sidebar.tsx
CHANGED
|
@@ -23,7 +23,9 @@ const useStyles = makeStyles(
|
|
|
23
23
|
paddingBottom: theme.spacing(3),
|
|
24
24
|
},
|
|
25
25
|
logo: {
|
|
26
|
+
display: "block",
|
|
26
27
|
margin: `36px 0 ${theme.spacing(3)} ${theme.spacing(2.5)}`,
|
|
28
|
+
color: "inherit",
|
|
27
29
|
},
|
|
28
30
|
root: {
|
|
29
31
|
transition: "width 0.5s ease",
|
|
@@ -50,6 +52,8 @@ export const Sidebar: React.FC<SidebarProps> = ({
|
|
|
50
52
|
menuItems,
|
|
51
53
|
toolbar,
|
|
52
54
|
onMenuItemClick,
|
|
55
|
+
logoHref,
|
|
56
|
+
linkComponent,
|
|
53
57
|
}) => {
|
|
54
58
|
const classes = useStyles({});
|
|
55
59
|
const { value: isShrunkStr, setValue: setShrink } = useLocalStorage(
|
|
@@ -59,6 +63,8 @@ export const Sidebar: React.FC<SidebarProps> = ({
|
|
|
59
63
|
const isShrunk = isShrunkStr === "true";
|
|
60
64
|
const { themeType } = useTheme();
|
|
61
65
|
|
|
66
|
+
const Link = linkComponent ?? "a";
|
|
67
|
+
|
|
62
68
|
return (
|
|
63
69
|
<div
|
|
64
70
|
className={clsx(classes.root, {
|
|
@@ -66,18 +72,28 @@ export const Sidebar: React.FC<SidebarProps> = ({
|
|
|
66
72
|
})}
|
|
67
73
|
>
|
|
68
74
|
<div className={classes.float}>
|
|
69
|
-
<
|
|
75
|
+
<Link href={logoHref} className={classes.logo}>
|
|
70
76
|
{themeType === "dark" ? <LogoDark /> : <Logo />}
|
|
71
|
-
</
|
|
72
|
-
{menuItems.map((menuItem) =>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
</Link>
|
|
78
|
+
{menuItems.map((menuItem) =>
|
|
79
|
+
linkComponent ? (
|
|
80
|
+
<MenuItem
|
|
81
|
+
activeId={activeId}
|
|
82
|
+
isMenuShrunk={isShrunk}
|
|
83
|
+
menuItem={menuItem}
|
|
84
|
+
key={menuItem.ariaLabel}
|
|
85
|
+
linkComponent={linkComponent}
|
|
86
|
+
/>
|
|
87
|
+
) : (
|
|
88
|
+
<MenuItem
|
|
89
|
+
activeId={activeId}
|
|
90
|
+
isMenuShrunk={isShrunk}
|
|
91
|
+
menuItem={menuItem}
|
|
92
|
+
onClick={onMenuItemClick}
|
|
93
|
+
key={menuItem.ariaLabel}
|
|
94
|
+
/>
|
|
95
|
+
)
|
|
96
|
+
)}
|
|
81
97
|
{toolbar && <div className={classes.toolbarContainer}>{toolbar}</div>}
|
|
82
98
|
<ExpandButton
|
|
83
99
|
className={classes.expandButton}
|
package/src/Sidebar/types.ts
CHANGED
|
@@ -8,11 +8,20 @@ export interface SidebarMenuItem {
|
|
|
8
8
|
iconSrc?: string;
|
|
9
9
|
url?: string;
|
|
10
10
|
external?: boolean;
|
|
11
|
+
onClick?: () => void;
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
export type CustomLinkComponent = React.ForwardRefExoticComponent<{
|
|
15
|
+
href?: string;
|
|
16
|
+
onClick?: (...params: any) => void;
|
|
17
|
+
className?: string;
|
|
18
|
+
}>;
|
|
19
|
+
|
|
13
20
|
export interface BaseSidebarProps {
|
|
14
21
|
className?: string;
|
|
15
22
|
menuItems: SidebarMenuItem[];
|
|
16
23
|
toolbar?: React.ReactNode;
|
|
17
24
|
onMenuItemClick: (menuItem: SidebarMenuItem) => void;
|
|
25
|
+
linkComponent?: CustomLinkComponent;
|
|
26
|
+
logoHref?: string;
|
|
18
27
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CustomLinkComponent, SidebarMenuItem } from "./types";
|
|
2
|
+
|
|
3
|
+
export const getLinkProps = (menuItem: SidebarMenuItem) => {
|
|
4
|
+
if (menuItem.external) {
|
|
5
|
+
return { href: menuItem.url, target: "_blank" };
|
|
6
|
+
}
|
|
7
|
+
if (menuItem.url) {
|
|
8
|
+
return {
|
|
9
|
+
href: menuItem.url,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
return {};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const getLinkComponent = (
|
|
16
|
+
menuItem: SidebarMenuItem,
|
|
17
|
+
customComponent?: CustomLinkComponent
|
|
18
|
+
) => {
|
|
19
|
+
if (menuItem.external) {
|
|
20
|
+
return "a";
|
|
21
|
+
}
|
|
22
|
+
return customComponent ?? "button";
|
|
23
|
+
};
|
|
@@ -2,22 +2,24 @@ import Typography from "@material-ui/core/Typography";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import SVG from "react-inlinesvg";
|
|
4
4
|
|
|
5
|
-
import { SidebarMenuItem } from "../Sidebar/types";
|
|
5
|
+
import { CustomLinkComponent, SidebarMenuItem } from "../Sidebar/types";
|
|
6
|
+
import { getLinkComponent, getLinkProps } from "../Sidebar/utils";
|
|
6
7
|
import useStyles from "./styles";
|
|
7
8
|
|
|
8
9
|
export interface MenuItemBtnProps {
|
|
9
10
|
menuItem: SidebarMenuItem;
|
|
10
11
|
onClick: (menuItem: SidebarMenuItem) => void;
|
|
12
|
+
linkComponent?: CustomLinkComponent;
|
|
11
13
|
}
|
|
14
|
+
|
|
12
15
|
export const MenuItemBtn: React.FC<MenuItemBtnProps> = ({
|
|
13
16
|
menuItem,
|
|
14
17
|
onClick,
|
|
18
|
+
linkComponent,
|
|
15
19
|
}) => {
|
|
16
20
|
const classes = useStyles();
|
|
17
|
-
const linkProps = menuItem
|
|
18
|
-
|
|
19
|
-
: {};
|
|
20
|
-
const Component = menuItem.external ? "a" : "button";
|
|
21
|
+
const linkProps = getLinkProps(menuItem);
|
|
22
|
+
const Component = getLinkComponent(menuItem, linkComponent);
|
|
21
23
|
|
|
22
24
|
return (
|
|
23
25
|
<Component
|
|
@@ -30,7 +32,11 @@ export const MenuItemBtn: React.FC<MenuItemBtnProps> = ({
|
|
|
30
32
|
{menuItem.iconSrc && (
|
|
31
33
|
<SVG className={classes.icon} src={menuItem.iconSrc} />
|
|
32
34
|
)}
|
|
33
|
-
<Typography
|
|
35
|
+
<Typography
|
|
36
|
+
component="span"
|
|
37
|
+
aria-label={menuItem.ariaLabel}
|
|
38
|
+
className={classes.label}
|
|
39
|
+
>
|
|
34
40
|
{menuItem.label}
|
|
35
41
|
</Typography>
|
|
36
42
|
</Component>
|
|
@@ -19,6 +19,8 @@ export type SideBarDrawerProps = BaseSidebarProps;
|
|
|
19
19
|
export const SidebarDrawer: React.FC<SideBarDrawerProps> = ({
|
|
20
20
|
menuItems,
|
|
21
21
|
onMenuItemClick,
|
|
22
|
+
linkComponent,
|
|
23
|
+
logoHref,
|
|
22
24
|
}) => {
|
|
23
25
|
const [isOpened, setOpened] = React.useState(false);
|
|
24
26
|
const classes = useStyles({});
|
|
@@ -43,6 +45,8 @@ export const SidebarDrawer: React.FC<SideBarDrawerProps> = ({
|
|
|
43
45
|
});
|
|
44
46
|
};
|
|
45
47
|
|
|
48
|
+
const Link = linkComponent ?? "a";
|
|
49
|
+
|
|
46
50
|
return (
|
|
47
51
|
<>
|
|
48
52
|
<SquareButton onClick={() => setOpened(true)}>
|
|
@@ -67,9 +71,9 @@ export const SidebarDrawer: React.FC<SideBarDrawerProps> = ({
|
|
|
67
71
|
})}
|
|
68
72
|
>
|
|
69
73
|
<div className={classes.content}>
|
|
70
|
-
<
|
|
74
|
+
<Link href={logoHref} className={classes.logo}>
|
|
71
75
|
{themeType === "dark" ? <LogoDark /> : <Logo />}
|
|
72
|
-
</
|
|
76
|
+
</Link>
|
|
73
77
|
{menuItems.map((menuItem) => (
|
|
74
78
|
<MenuItemBtn
|
|
75
79
|
menuItem={menuItem}
|
|
@@ -78,6 +82,7 @@ export const SidebarDrawer: React.FC<SideBarDrawerProps> = ({
|
|
|
78
82
|
? () => handleMenuItemWithChildrenClick(menuItem)
|
|
79
83
|
: handleMenuItemClick
|
|
80
84
|
}
|
|
85
|
+
linkComponent={linkComponent}
|
|
81
86
|
key={menuItem.ariaLabel}
|
|
82
87
|
/>
|
|
83
88
|
))}
|
|
@@ -104,6 +109,7 @@ export const SidebarDrawer: React.FC<SideBarDrawerProps> = ({
|
|
|
104
109
|
menuItem={subMenuItem}
|
|
105
110
|
onClick={handleMenuItemClick}
|
|
106
111
|
key={subMenuItem.ariaLabel}
|
|
112
|
+
linkComponent={linkComponent}
|
|
107
113
|
/>
|
|
108
114
|
);
|
|
109
115
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Typography } from "@material-ui/core";
|
|
2
|
+
import { Meta, Story } from "@storybook/react";
|
|
3
|
+
import React, { useState } from "react";
|
|
4
|
+
|
|
5
|
+
import { SwitchSelector } from "./SwitchSelector";
|
|
6
|
+
import { SwitchSelectorButton } from "./SwitchSelectorButton";
|
|
7
|
+
import useGuideStyles from "../utils/guideStyles";
|
|
8
|
+
|
|
9
|
+
type SwitchSelectorButtonOptions = {
|
|
10
|
+
label: string | React.ReactNode;
|
|
11
|
+
value: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const INITIAL_TAB = "op2";
|
|
15
|
+
|
|
16
|
+
const OPTIONS: SwitchSelectorButtonOptions[] = [
|
|
17
|
+
{ label: "Option 1", value: "op1" },
|
|
18
|
+
{ label: "Option 2", value: "op2" },
|
|
19
|
+
{ label: "Option 3", value: "op3" },
|
|
20
|
+
{ label: "Option 4", value: "op4" },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const DefaultStory: React.FC = () => {
|
|
24
|
+
const guideClasses = useGuideStyles();
|
|
25
|
+
const [active, setActive] = useState(INITIAL_TAB);
|
|
26
|
+
|
|
27
|
+
const currentTab = OPTIONS.find((option) => option.value === active);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div>
|
|
31
|
+
<Typography className={guideClasses.headline} variant="h1">
|
|
32
|
+
Switch Selector
|
|
33
|
+
</Typography>
|
|
34
|
+
<Typography className={guideClasses.paragraph} component="p">
|
|
35
|
+
Switch Selector has the functionality of a radio button group. It is
|
|
36
|
+
used to change an active tab to toggle context.
|
|
37
|
+
</Typography>
|
|
38
|
+
<div>
|
|
39
|
+
<SwitchSelector>
|
|
40
|
+
{OPTIONS.map(({ label, value }) => (
|
|
41
|
+
<SwitchSelectorButton
|
|
42
|
+
value={value}
|
|
43
|
+
onClick={() => setActive(value)}
|
|
44
|
+
activeTab={active}
|
|
45
|
+
>
|
|
46
|
+
{label}
|
|
47
|
+
</SwitchSelectorButton>
|
|
48
|
+
))}
|
|
49
|
+
</SwitchSelector>
|
|
50
|
+
|
|
51
|
+
<div style={{ marginTop: "2em" }}>
|
|
52
|
+
<Typography>{`You have selected ${currentTab?.label}`}</Typography>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const Default: Story = () => <DefaultStory />;
|
|
60
|
+
|
|
61
|
+
export default {
|
|
62
|
+
title: "Switch selector",
|
|
63
|
+
} as Meta;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { makeStyles } from "..";
|
|
3
|
+
|
|
4
|
+
const useStyles = makeStyles((theme) => ({
|
|
5
|
+
switchSelector: {
|
|
6
|
+
border: `1px solid ${theme.palette.saleor.main[5]}`,
|
|
7
|
+
padding: "6px",
|
|
8
|
+
borderRadius: 4,
|
|
9
|
+
width: "fit-content",
|
|
10
|
+
},
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
export const SwitchSelector: React.FC<{}> = ({ children }) => {
|
|
14
|
+
const classes = useStyles();
|
|
15
|
+
|
|
16
|
+
return <div className={classes.switchSelector}>{children}</div>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
SwitchSelector.displayName = "SwitchSelector";
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Button, makeStyles } from "..";
|
|
4
|
+
|
|
5
|
+
interface SwitchSelectorButtonProps {
|
|
6
|
+
value: string;
|
|
7
|
+
activeTab?: string;
|
|
8
|
+
onClick: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const useSwitchSelectorButtonStyles = makeStyles((theme) => ({
|
|
12
|
+
root: {
|
|
13
|
+
color: "#77738C",
|
|
14
|
+
background: "none",
|
|
15
|
+
borderColor: "transparent",
|
|
16
|
+
cursor: "pointer",
|
|
17
|
+
|
|
18
|
+
"&:not(:first-child)": {
|
|
19
|
+
marginLeft: theme.spacing(1),
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"&:hover": {
|
|
23
|
+
backgroundColor: theme.palette.common.white,
|
|
24
|
+
color: theme.palette.saleor.active[1],
|
|
25
|
+
border: `1px solid ${theme.palette.saleor.active[1]}`,
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
"&:active": {
|
|
29
|
+
backgroundColor: theme.palette.saleor.active[5],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
buttonSelected: {
|
|
33
|
+
color: theme.palette.common.white,
|
|
34
|
+
backgroundColor: theme.palette.saleor.active[1],
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
export const SwitchSelectorButton: React.FC<SwitchSelectorButtonProps> = ({
|
|
39
|
+
onClick,
|
|
40
|
+
value,
|
|
41
|
+
children,
|
|
42
|
+
activeTab,
|
|
43
|
+
}) => {
|
|
44
|
+
const classes = useSwitchSelectorButtonStyles();
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Button
|
|
48
|
+
key={value}
|
|
49
|
+
onClick={onClick}
|
|
50
|
+
className={clsx(classes.root, {
|
|
51
|
+
[classes.buttonSelected]: value === activeTab,
|
|
52
|
+
})}
|
|
53
|
+
>
|
|
54
|
+
{children}
|
|
55
|
+
</Button>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
SwitchSelectorButton.displayName = "SwitchSelectorButton";
|
package/src/index.tsx
CHANGED
|
@@ -32,4 +32,7 @@ export * from "./OffsettedList";
|
|
|
32
32
|
export * from "./List";
|
|
33
33
|
export * from "./NavigationCard";
|
|
34
34
|
export * from "./Pill";
|
|
35
|
-
export * from "./CircleIndicator"
|
|
35
|
+
export * from "./CircleIndicator";
|
|
36
|
+
export * from "./SwitchSelector";
|
|
37
|
+
export * from "./Autocomplete";
|
|
38
|
+
export * from "./MultipleValueAutocomplete";
|
|
@@ -30,12 +30,17 @@ export interface ThemeProviderProps {
|
|
|
30
30
|
* Saleor's Dashboard. Use with caution.
|
|
31
31
|
*/
|
|
32
32
|
overrides?: Partial<Theme>;
|
|
33
|
+
/**
|
|
34
|
+
* Enables server side rendering.
|
|
35
|
+
*/
|
|
36
|
+
ssr?: boolean;
|
|
33
37
|
}
|
|
34
38
|
export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
35
39
|
children,
|
|
36
40
|
defaultTheme = "light",
|
|
37
41
|
palettes = {},
|
|
38
42
|
overrides = {},
|
|
43
|
+
ssr = false,
|
|
39
44
|
}) => {
|
|
40
45
|
const { value: themeTypeName, setValue: setThemeType } = useLocalStorage(
|
|
41
46
|
localStorageKeys.theme,
|
|
@@ -66,6 +71,7 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
66
71
|
<ThemeContext.Provider
|
|
67
72
|
value={{
|
|
68
73
|
themeType,
|
|
74
|
+
ssr,
|
|
69
75
|
sendThemeToExtension,
|
|
70
76
|
setTheme: setThemeType,
|
|
71
77
|
}}
|
|
@@ -149,6 +149,7 @@ export const createTheme = (colors: SaleorThemeColors): SaleorTheme =>
|
|
|
149
149
|
backgroundColor: colors.main[1],
|
|
150
150
|
},
|
|
151
151
|
backgroundColor: colors.main[1],
|
|
152
|
+
outline: 0,
|
|
152
153
|
},
|
|
153
154
|
},
|
|
154
155
|
},
|
|
@@ -162,7 +163,6 @@ export const createTheme = (colors: SaleorThemeColors): SaleorTheme =>
|
|
|
162
163
|
"&$selected, &$selected:focus, &$selected:hover": {
|
|
163
164
|
backgroundColor: [colors.active[5], "!important"] as any,
|
|
164
165
|
color: colors.active[1],
|
|
165
|
-
fontWeight: 700,
|
|
166
166
|
},
|
|
167
167
|
"&:hover": {
|
|
168
168
|
backgroundColor: [colors.active[5], "!important"] as any,
|
|
@@ -170,6 +170,7 @@ export const createTheme = (colors: SaleorThemeColors): SaleorTheme =>
|
|
|
170
170
|
"@media(min-width: 600px)": {
|
|
171
171
|
minHeight: 48,
|
|
172
172
|
},
|
|
173
|
+
cursor: "pointer",
|
|
173
174
|
},
|
|
174
175
|
},
|
|
175
176
|
MuiSelect: {
|
|
@@ -137,7 +137,8 @@ export const controlOverrides = (
|
|
|
137
137
|
},
|
|
138
138
|
},
|
|
139
139
|
height: 48,
|
|
140
|
-
|
|
140
|
+
padding: "12px 16px",
|
|
141
|
+
width: 80,
|
|
141
142
|
},
|
|
142
143
|
switchBase: {
|
|
143
144
|
"&$checked": {
|
|
@@ -157,6 +158,8 @@ export const controlOverrides = (
|
|
|
157
158
|
thumb: {
|
|
158
159
|
boxShadow: "none",
|
|
159
160
|
height: 14,
|
|
161
|
+
left: 4,
|
|
162
|
+
position: "relative",
|
|
160
163
|
width: 14,
|
|
161
164
|
},
|
|
162
165
|
track: {
|
|
@@ -171,7 +171,7 @@ export const inputOverrides = (
|
|
|
171
171
|
backgroundColor: colors.background.paper,
|
|
172
172
|
transition: "box-shadow 200ms",
|
|
173
173
|
top: 0,
|
|
174
|
-
fontWeight:
|
|
174
|
+
fontWeight: 400,
|
|
175
175
|
},
|
|
176
176
|
notchedOutline: {
|
|
177
177
|
// It's so much easier to put it here with important tag rather than
|
package/src/theme/themes.ts
CHANGED
package/src/theme/types.ts
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
export function useTextWidth(
|
|
4
|
+
font: string
|
|
5
|
+
): [number, Dispatch<SetStateAction<string>>] {
|
|
6
|
+
const [text, setText] = useState("");
|
|
7
|
+
const [width, setWidth] = useState(0);
|
|
8
|
+
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const canvas = document.createElement("canvas");
|
|
11
|
+
const context = canvas.getContext("2d")!;
|
|
12
|
+
context.font = font;
|
|
13
|
+
const { width: newWidth } = context.measureText(text);
|
|
14
|
+
canvas.remove();
|
|
15
|
+
|
|
16
|
+
setWidth(newWidth + 8);
|
|
17
|
+
}, [text, font]);
|
|
18
|
+
|
|
19
|
+
return [width, setText];
|
|
20
|
+
}
|
package/src/utils/guideStyles.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Ref } from "react";
|
|
2
|
+
|
|
3
|
+
export function mergeRefs<T>(...refs: Ref<T>[]) {
|
|
4
|
+
return (node: T) => {
|
|
5
|
+
for (const ref of refs) {
|
|
6
|
+
if (typeof ref === "function") {
|
|
7
|
+
ref(node);
|
|
8
|
+
} else {
|
|
9
|
+
// ref.current is typed as readonly
|
|
10
|
+
(ref as any).current = node;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { score } from "fuzzaldrin";
|
|
2
|
+
import { sortBy } from "lodash";
|
|
3
|
+
import { useEffect, useMemo, useState } from "react";
|
|
4
|
+
|
|
5
|
+
const pageSize = 10;
|
|
6
|
+
|
|
7
|
+
export function useMockAutocomplete(
|
|
8
|
+
choices: Array<Record<"label" | "value", string>>
|
|
9
|
+
) {
|
|
10
|
+
const [query, setQuery] = useState("");
|
|
11
|
+
const [slice, setSlice] = useState(pageSize);
|
|
12
|
+
const results = useMemo(
|
|
13
|
+
() =>
|
|
14
|
+
sortBy(
|
|
15
|
+
choices.map((choice) => ({
|
|
16
|
+
...choice,
|
|
17
|
+
score: -score(choice.label, query),
|
|
18
|
+
})),
|
|
19
|
+
"score"
|
|
20
|
+
).slice(0, slice),
|
|
21
|
+
[query]
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
setSlice(pageSize);
|
|
26
|
+
}, [query]);
|
|
27
|
+
|
|
28
|
+
const search = (query: string) => setTimeout(() => setQuery(query), 300);
|
|
29
|
+
|
|
30
|
+
const more = () => setSlice((s) => s + pageSize);
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
search,
|
|
34
|
+
results,
|
|
35
|
+
more,
|
|
36
|
+
};
|
|
37
|
+
}
|