@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.
Files changed (118) hide show
  1. package/README.md +20 -0
  2. package/dist/cjs/index.js +2 -2
  3. package/dist/cjs/index.js.map +3 -3
  4. package/dist/esm/index.js +2 -2
  5. package/dist/esm/index.js.map +3 -3
  6. package/dist/types/ActionBar/ActionBar.d.ts +1 -0
  7. package/dist/types/ActionBar/context.d.ts +6 -3
  8. package/dist/types/Autocomplete/Autocomplete.d.ts +23 -0
  9. package/dist/types/Autocomplete/Autocomplete.stories.d.ts +5 -0
  10. package/dist/types/Autocomplete/fixtures.d.ts +4 -0
  11. package/dist/types/Autocomplete/index.d.ts +1 -0
  12. package/dist/types/Autocomplete/styles.d.ts +2 -0
  13. package/dist/types/Chip/Chip.d.ts +8 -0
  14. package/dist/types/Chip/ChipAdornment.d.ts +6 -0
  15. package/dist/types/Chip/ChipMovable.d.ts +5 -0
  16. package/dist/types/Chip/ChipRemovable.d.ts +6 -0
  17. package/dist/types/Chip/ChipSwatch.d.ts +7 -0
  18. package/dist/types/Chip/index.d.ts +5 -0
  19. package/dist/types/Chip/private/ColorSwatch.d.ts +6 -0
  20. package/dist/types/Chip/styles.d.ts +2 -0
  21. package/dist/types/CircleIndicator/index.d.ts +1 -1
  22. package/dist/types/Filter/FilterField/AutocompleteFilterField.d.ts +6 -0
  23. package/dist/types/Filter/FilterField/MultipleValueAutocompleteFilterField.d.ts +6 -0
  24. package/dist/types/Filter/stories/Filter.stories.d.ts +5 -0
  25. package/dist/types/Filter/stories/FilterInteractive.stories.d.ts +4 -0
  26. package/dist/types/Filter/stories/labels.d.ts +8 -0
  27. package/dist/types/Filter/styles.d.ts +1 -1
  28. package/dist/types/Filter/types.d.ts +8 -2
  29. package/dist/types/Filter/utils.d.ts +4 -1
  30. package/dist/types/IconButton/IconButton.d.ts +2 -0
  31. package/dist/types/IconButton/partials.d.ts +1 -1
  32. package/dist/types/IconButton/styles.d.ts +1 -1
  33. package/dist/types/MultipleValueAutocomplete/MultipleValueAutocomplete.d.ts +26 -0
  34. package/dist/types/MultipleValueAutocomplete/MultipleValueAutocomplete.stories.d.ts +6 -0
  35. package/dist/types/MultipleValueAutocomplete/fixtures.d.ts +4 -0
  36. package/dist/types/MultipleValueAutocomplete/index.d.ts +1 -0
  37. package/dist/types/MultipleValueAutocomplete/styles.d.ts +2 -0
  38. package/dist/types/MultipleValueAutocomplete/useMultipleValueAutocomplete.d.ts +32 -0
  39. package/dist/types/Savebar/Savebar.d.ts +1 -0
  40. package/dist/types/Sidebar/MenuItem.d.ts +9 -3
  41. package/dist/types/Sidebar/types.d.ts +8 -0
  42. package/dist/types/Sidebar/utils.d.ts +12 -0
  43. package/dist/types/SidebarDrawer/MenuItemBtn.d.ts +2 -1
  44. package/dist/types/SwitchSelector/SwitchSelector.d.ts +2 -0
  45. package/dist/types/SwitchSelector/SwitchSelector.stories.d.ts +4 -0
  46. package/dist/types/SwitchSelector/SwitchSelectorButton.d.ts +8 -0
  47. package/dist/types/SwitchSelector/index.d.ts +2 -0
  48. package/dist/types/index.d.ts +3 -0
  49. package/dist/types/theme/ThemeProvider.d.ts +4 -0
  50. package/dist/types/theme/types.d.ts +1 -0
  51. package/dist/types/tools/useTextWidth.d.ts +2 -0
  52. package/dist/types/utils/guideStyles.d.ts +1 -1
  53. package/dist/types/utils/mergeRefs.d.ts +2 -0
  54. package/dist/types/utils/useMockAutocomplete.d.ts +10 -0
  55. package/package.json +11 -13
  56. package/src/ActionBar/ActionBar.tsx +8 -11
  57. package/src/ActionBar/context.tsx +15 -6
  58. package/src/ActionBar/styles.ts +1 -1
  59. package/src/Autocomplete/Autocomplete.stories.tsx +43 -0
  60. package/src/Autocomplete/Autocomplete.tsx +187 -0
  61. package/src/Autocomplete/fixtures.ts +122 -0
  62. package/src/Autocomplete/index.ts +1 -0
  63. package/src/Autocomplete/styles.ts +19 -0
  64. package/src/Backlink/Backlink.tsx +3 -1
  65. package/src/Chip/Chip.tsx +52 -0
  66. package/src/Chip/ChipAdornment.tsx +53 -0
  67. package/src/Chip/ChipMovable.tsx +40 -0
  68. package/src/Chip/ChipRemovable.tsx +29 -0
  69. package/src/Chip/ChipSwatch.tsx +42 -0
  70. package/src/Chip/index.ts +5 -0
  71. package/src/Chip/private/ColorSwatch.tsx +21 -0
  72. package/src/Chip/styles.ts +46 -0
  73. package/src/CircleIndicator/CircleIndicator.stories.tsx +6 -6
  74. package/src/CircleIndicator/index.ts +1 -1
  75. package/src/Filter/Filter.tsx +88 -44
  76. package/src/Filter/FilterBar.tsx +15 -9
  77. package/src/Filter/FilterContent.tsx +8 -1
  78. package/src/Filter/FilterField/AutocompleteFilterField.tsx +61 -0
  79. package/src/Filter/FilterField/MultipleSelectFilterField.tsx +9 -3
  80. package/src/Filter/FilterField/MultipleValueAutocompleteFilterField.tsx +60 -0
  81. package/src/Filter/context.tsx +1 -1
  82. package/src/Filter/{Filter.stories.tsx → stories/Filter.stories.tsx} +47 -13
  83. package/src/Filter/stories/FilterInteractive.stories.tsx +97 -0
  84. package/src/Filter/stories/labels.ts +8 -0
  85. package/src/Filter/styles.ts +37 -6
  86. package/src/Filter/types.ts +8 -1
  87. package/src/Filter/utils.ts +71 -5
  88. package/src/IconButton/IconButton.tsx +17 -2
  89. package/src/IconButton/partials.ts +1 -1
  90. package/src/IconButton/styles.ts +38 -16
  91. package/src/MultipleValueAutocomplete/MultipleValueAutocomplete.stories.tsx +76 -0
  92. package/src/MultipleValueAutocomplete/MultipleValueAutocomplete.tsx +185 -0
  93. package/src/MultipleValueAutocomplete/fixtures.ts +122 -0
  94. package/src/MultipleValueAutocomplete/index.ts +1 -0
  95. package/src/MultipleValueAutocomplete/styles.ts +39 -0
  96. package/src/MultipleValueAutocomplete/useMultipleValueAutocomplete.ts +172 -0
  97. package/src/Savebar/Savebar.tsx +3 -4
  98. package/src/Sidebar/MenuItem.tsx +35 -14
  99. package/src/Sidebar/Sidebar.tsx +27 -11
  100. package/src/Sidebar/types.ts +9 -0
  101. package/src/Sidebar/utils.ts +23 -0
  102. package/src/SidebarDrawer/MenuItemBtn.tsx +12 -6
  103. package/src/SidebarDrawer/SidebarDrawer.tsx +8 -2
  104. package/src/SwitchSelector/SwitchSelector.stories.tsx +63 -0
  105. package/src/SwitchSelector/SwitchSelector.tsx +19 -0
  106. package/src/SwitchSelector/SwitchSelectorButton.tsx +59 -0
  107. package/src/SwitchSelector/index.ts +2 -0
  108. package/src/index.tsx +4 -1
  109. package/src/theme/ThemeProvider.tsx +6 -0
  110. package/src/theme/createSaleorTheme/createSaleorTheme.tsx +2 -1
  111. package/src/theme/createSaleorTheme/overrides/controls.ts +4 -1
  112. package/src/theme/createSaleorTheme/overrides/inputs.ts +1 -1
  113. package/src/theme/themes.ts +1 -1
  114. package/src/theme/types.ts +1 -0
  115. package/src/tools/useTextWidth.ts +20 -0
  116. package/src/utils/guideStyles.ts +5 -0
  117. package/src/utils/mergeRefs.ts +14 -0
  118. package/src/utils/useMockAutocomplete.ts +37 -0
@@ -6,6 +6,7 @@ import clsx from "clsx";
6
6
  import React from "react";
7
7
 
8
8
  import { ConfirmButtonTransitionState } from "../ConfirmButton";
9
+ import { useTheme } from "../theme";
9
10
  import { useWindowScroll } from "../tools";
10
11
  import { useActionBar } from "./context";
11
12
  import useStyles from "./styles";
@@ -13,6 +14,7 @@ import useStyles from "./styles";
13
14
  export interface ActionBarProps {
14
15
  disabled: boolean;
15
16
  state: ConfirmButtonTransitionState;
17
+ className?: string;
16
18
  children: React.ReactNode[] | React.ReactNode;
17
19
  }
18
20
 
@@ -20,34 +22,29 @@ export const ActionBar: React.FC<ActionBarProps> = ({
20
22
  disabled,
21
23
  children,
22
24
  state,
25
+ className,
23
26
  ...rest
24
27
  }) => {
28
+ const { ssr } = useTheme();
25
29
  const classes = useStyles();
26
30
 
27
- const { anchor, docked, setDocked } = useActionBar();
31
+ const { anchor } = useActionBar();
28
32
  const scrollPosition = useWindowScroll();
29
33
 
30
- React.useEffect(() => {
31
- if (!disabled && state !== "loading") {
32
- setDocked(false);
33
- }
34
- }, [disabled, state, setDocked]);
35
- React.useEffect(() => () => setDocked(true), [setDocked]);
36
-
37
34
  const scrolledToBottom =
38
35
  scrollPosition.y + window.innerHeight >= document.body.scrollHeight;
39
36
 
40
- if (!anchor.current) {
37
+ if (!anchor.current && !ssr) {
41
38
  return null;
42
39
  }
43
40
 
44
41
  return (
45
42
  <Portal container={anchor.current}>
46
- <div className={classes.root} {...rest}>
43
+ <div className={clsx(classes.root, className)} {...rest}>
47
44
  <Container maxWidth="lg">
48
45
  <Card
49
46
  className={clsx(classes.paper, {
50
- [classes.shadow]: !(docked || scrolledToBottom),
47
+ [classes.shadow]: !scrolledToBottom,
51
48
  })}
52
49
  >
53
50
  <CardContent className={classes.content}>{children}</CardContent>
@@ -1,9 +1,13 @@
1
1
  import React from "react";
2
2
 
3
+ // Imitate object returned from useRef
4
+ type AnchorFunction = {
5
+ (el: HTMLDivElement): void;
6
+ current: HTMLDivElement | null;
7
+ };
8
+
3
9
  export interface ActionBarContextType {
4
- anchor: React.RefObject<HTMLDivElement>;
5
- docked: boolean;
6
- setDocked: (docked: boolean) => void;
10
+ anchor: AnchorFunction;
7
11
  }
8
12
 
9
13
  export const ActionBarContext = React.createContext<
@@ -21,11 +25,16 @@ export const useActionBar = () => {
21
25
  };
22
26
 
23
27
  export const ActionBarProvider: React.FC = ({ children }) => {
24
- const [docked, setDocked] = React.useState(true);
25
- const anchor = React.useRef<HTMLDivElement | null>(null);
28
+ const [anchorState, setAnchor] = React.useState<HTMLDivElement | null>(null);
29
+
30
+ const anchor = React.useMemo(() => {
31
+ const fn = setAnchor as AnchorFunction;
32
+ fn.current = anchorState;
33
+ return fn;
34
+ }, [anchorState]);
26
35
 
27
36
  return (
28
- <ActionBarContext.Provider value={{ anchor, docked, setDocked }}>
37
+ <ActionBarContext.Provider value={{ anchor }}>
29
38
  {children}
30
39
  </ActionBarContext.Provider>
31
40
  );
@@ -25,7 +25,7 @@ const useStyles = makeStyles(
25
25
  boxShadow: "0 -24px 20px -20px rgba(0, 0, 0, 0.15)",
26
26
  },
27
27
  }),
28
- { name: "Savebar" }
28
+ { name: "ActionBar" }
29
29
  );
30
30
 
31
31
  export default useStyles;
@@ -0,0 +1,43 @@
1
+ import { MenuItem } from "@material-ui/core";
2
+ import { Meta, Story } from "@storybook/react";
3
+ import React from "react";
4
+
5
+ import { Decorator, GuideDecorator } from "../utils/Decorator";
6
+ import { useMockAutocomplete } from "../utils/useMockAutocomplete";
7
+ import { Autocomplete } from "./Autocomplete";
8
+ import { choices } from "./fixtures";
9
+
10
+ export const Default: Story = () => {
11
+ const { results, search } = useMockAutocomplete(choices);
12
+
13
+ return (
14
+ <Autocomplete
15
+ choices={results}
16
+ fullWidth
17
+ label="Employee of the month"
18
+ onInputChange={search}
19
+ >
20
+ {({ highlightedIndex, getItemProps }) =>
21
+ results.map((choice, choiceIndex) => (
22
+ <MenuItem
23
+ selected={highlightedIndex === choiceIndex}
24
+ {...getItemProps({ item: choice, index: choiceIndex })}
25
+ >
26
+ {choice.label}
27
+ </MenuItem>
28
+ ))
29
+ }
30
+ </Autocomplete>
31
+ );
32
+ };
33
+
34
+ export const Loading: Story = () => (
35
+ <Autocomplete fullWidth choices={[]} label="Employee of the month" loading>
36
+ {() => null}
37
+ </Autocomplete>
38
+ );
39
+
40
+ export default {
41
+ decorators: [Decorator, GuideDecorator],
42
+ title: "Autocomplete / Single choice",
43
+ } as Meta;
@@ -0,0 +1,187 @@
1
+ import { CircularProgress } from "@material-ui/core";
2
+ import Grow from "@material-ui/core/Grow";
3
+ import Paper from "@material-ui/core/Paper";
4
+ import Popper, { PopperPlacementType } from "@material-ui/core/Popper";
5
+ import TextField, { StandardTextFieldProps } from "@material-ui/core/TextField";
6
+ import clsx from "clsx";
7
+ import { useCombobox, UseComboboxGetItemPropsOptions } from "downshift";
8
+ import React from "react";
9
+
10
+ import { SyntheticChangeEvent } from "../../types/utils";
11
+ import { Choice } from "../Filter";
12
+ import { ChevronIcon } from "../icons";
13
+ import { isScrolledToBottom, useElementScroll } from "../tools";
14
+ import { mergeRefs } from "../utils/mergeRefs";
15
+ import useStyles from "./styles";
16
+
17
+ export interface AutocompleteProps extends StandardTextFieldProps {
18
+ children: (data: {
19
+ getItemProps: (opts: UseComboboxGetItemPropsOptions<Choice>) => any;
20
+ highlightedIndex: number;
21
+ inputValue: string;
22
+ }) => React.ReactNode | React.ReactNodeArray;
23
+ className?: string;
24
+ styles?: React.CSSProperties;
25
+ choices: Choice[];
26
+ label?: string;
27
+ loading?: boolean;
28
+ popperPlacement?: PopperPlacementType;
29
+ onChange?: (event: SyntheticChangeEvent) => void;
30
+ onInputChange?: (value: string) => void;
31
+ onScrollToBottom?: () => void;
32
+ }
33
+
34
+ export const Autocomplete: React.FC<AutocompleteProps> = ({
35
+ choices,
36
+ children,
37
+ loading,
38
+ name,
39
+ InputProps,
40
+ popperPlacement = "bottom-start",
41
+ onChange,
42
+ onInputChange,
43
+ onScrollToBottom,
44
+ ...rest
45
+ }) => {
46
+ const classes = useStyles();
47
+ const anchor = React.useRef<HTMLDivElement>();
48
+ const input = React.useRef<HTMLInputElement>();
49
+
50
+ const {
51
+ closeMenu,
52
+ isOpen,
53
+ getToggleButtonProps,
54
+ getLabelProps,
55
+ getMenuProps,
56
+ getInputProps,
57
+ getComboboxProps,
58
+ highlightedIndex,
59
+ getItemProps,
60
+ openMenu,
61
+ inputValue,
62
+ setInputValue,
63
+ } = useCombobox({
64
+ circularNavigation: false,
65
+ defaultHighlightedIndex: 0,
66
+ items: choices,
67
+ onInputValueChange: ({ inputValue }) => {
68
+ if (onInputChange) {
69
+ onInputChange(inputValue ?? "");
70
+ }
71
+ },
72
+ onSelectedItemChange: ({ selectedItem }) => {
73
+ closeMenu();
74
+ if (onChange) {
75
+ onChange({
76
+ target: {
77
+ name: name ?? "",
78
+ value: selectedItem?.value ?? "",
79
+ },
80
+ });
81
+ }
82
+ },
83
+ itemToString: (choice) => choice?.label ?? "",
84
+ onIsOpenChange: ({ selectedItem, inputValue, isOpen }) => {
85
+ if (!isOpen && selectedItem && selectedItem?.label !== inputValue) {
86
+ setInputValue(selectedItem!.label);
87
+ }
88
+ },
89
+ });
90
+
91
+ const { anchor: dropdownRef, position, setAnchor } = useElementScroll();
92
+
93
+ React.useEffect(() => {
94
+ if (
95
+ isOpen &&
96
+ onScrollToBottom &&
97
+ dropdownRef &&
98
+ isScrolledToBottom(dropdownRef, position!, 5)
99
+ ) {
100
+ onScrollToBottom();
101
+ }
102
+ }, [position?.y, dropdownRef]);
103
+
104
+ const labelProps = getLabelProps();
105
+ const { ref: comboboxDownshiftRef, ...comboboxProps } = getComboboxProps();
106
+ const { ref: downshiftRef, ...inputProps } = getInputProps({
107
+ onFocus: () => {
108
+ if (!isOpen) {
109
+ input.current?.select();
110
+ openMenu();
111
+ }
112
+ },
113
+ });
114
+ const menuProps = getMenuProps();
115
+
116
+ React.useEffect(() => {
117
+ if (
118
+ isOpen &&
119
+ onScrollToBottom &&
120
+ dropdownRef &&
121
+ isScrolledToBottom(dropdownRef, position!, 5)
122
+ ) {
123
+ onScrollToBottom();
124
+ }
125
+ }, [position?.y, dropdownRef]);
126
+
127
+ return (
128
+ <>
129
+ <TextField
130
+ {...rest}
131
+ {...comboboxProps}
132
+ name={name}
133
+ InputLabelProps={labelProps}
134
+ ref={mergeRefs(comboboxDownshiftRef, anchor)}
135
+ InputProps={{
136
+ ...InputProps,
137
+ ...inputProps,
138
+ endAdornment: (
139
+ <>
140
+ {loading && (
141
+ <div className={classes.loader}>
142
+ <CircularProgress size={24} />
143
+ </div>
144
+ )}
145
+ <ChevronIcon
146
+ {...getToggleButtonProps()}
147
+ type="button"
148
+ aria-label="toggle menu"
149
+ />
150
+ </>
151
+ ),
152
+ }}
153
+ inputProps={{ ref: mergeRefs(downshiftRef, input) }}
154
+ />
155
+ <Popper
156
+ className={clsx(classes.popper, menuProps.className)}
157
+ open={isOpen}
158
+ anchorEl={input.current}
159
+ transition
160
+ placement={popperPlacement}
161
+ >
162
+ {({ TransitionProps, placement }) => (
163
+ <Grow
164
+ {...TransitionProps}
165
+ style={{
166
+ transformOrigin:
167
+ placement === "bottom" ? "left top" : "left bottom",
168
+ }}
169
+ >
170
+ <Paper
171
+ className={classes.dropdown}
172
+ elevation={8}
173
+ style={{ width: anchor.current?.clientWidth }}
174
+ ref={mergeRefs(setAnchor, menuProps.ref)}
175
+ >
176
+ {children({
177
+ highlightedIndex,
178
+ getItemProps,
179
+ inputValue,
180
+ })}
181
+ </Paper>
182
+ </Grow>
183
+ )}
184
+ </Popper>
185
+ </>
186
+ );
187
+ };
@@ -0,0 +1,122 @@
1
+ export const choices = [
2
+ {
3
+ label: "Hazel, Direct Integration Producer",
4
+ value: "hazel, direct integration producer",
5
+ },
6
+ {
7
+ label: "Audra, District Functionality Facilitator",
8
+ value: "audra, district functionality facilitator",
9
+ },
10
+ {
11
+ label: "Emilie, Product Integration Assistant",
12
+ value: "emilie, product integration assistant",
13
+ },
14
+ {
15
+ label: "Kyla, Central Interactions Director",
16
+ value: "kyla, central interactions director",
17
+ },
18
+ {
19
+ label: "Vida, Senior Usability Producer",
20
+ value: "vida, senior usability producer",
21
+ },
22
+ {
23
+ label: "Lonie, Chief Infrastructure Director",
24
+ value: "lonie, chief infrastructure director",
25
+ },
26
+ {
27
+ label: "Zola, Lead Operations Producer",
28
+ value: "zola, lead operations producer",
29
+ },
30
+ {
31
+ label: "Angel, District Operations Orchestrator",
32
+ value: "angel, district operations orchestrator",
33
+ },
34
+ {
35
+ label: "Glenda, Lead Accountability Technician",
36
+ value: "glenda, lead accountability technician",
37
+ },
38
+ {
39
+ label: "Kayley, National Web Facilitator",
40
+ value: "kayley, national web facilitator",
41
+ },
42
+ {
43
+ label: "Kali, National Configuration Planner",
44
+ value: "kali, national configuration planner",
45
+ },
46
+ {
47
+ label: "Lilian, Internal Branding Planner",
48
+ value: "lilian, internal branding planner",
49
+ },
50
+ {
51
+ label: "Lamar, Dynamic Integration Executive",
52
+ value: "lamar, dynamic integration executive",
53
+ },
54
+ {
55
+ label: "Leonel, Central Brand Strategist",
56
+ value: "leonel, central brand strategist",
57
+ },
58
+ {
59
+ label: "Broderick, Chief Division Liaison",
60
+ value: "broderick, chief division liaison",
61
+ },
62
+ {
63
+ label: "Kavon, Future Marketing Representative",
64
+ value: "kavon, future marketing representative",
65
+ },
66
+ {
67
+ label: "Sydnee, Corporate Marketing Liaison",
68
+ value: "sydnee, corporate marketing liaison",
69
+ },
70
+ {
71
+ label: "Jett, Future Data Specialist",
72
+ value: "jett, future data specialist",
73
+ },
74
+ {
75
+ label: "Theresia, International Tactics Assistant",
76
+ value: "theresia, international tactics assistant",
77
+ },
78
+ {
79
+ label: "Cesar, Direct Mobility Director",
80
+ value: "cesar, direct mobility director",
81
+ },
82
+ {
83
+ label: "Madonna, Investor Assurance Executive",
84
+ value: "madonna, investor assurance executive",
85
+ },
86
+ {
87
+ label: "Ima, Internal Research Facilitator",
88
+ value: "ima, internal research facilitator",
89
+ },
90
+ {
91
+ label: "Joanne, Investor Identity Coordinator",
92
+ value: "joanne, investor identity coordinator",
93
+ },
94
+ {
95
+ label: "Gavin, Future Web Assistant",
96
+ value: "gavin, future web assistant",
97
+ },
98
+ {
99
+ label: "Maverick, Internal Optimization Assistant",
100
+ value: "maverick, internal optimization assistant",
101
+ },
102
+ {
103
+ label: "Hudson, Regional Branding Representative",
104
+ value: "hudson, regional branding representative",
105
+ },
106
+ {
107
+ label: "Brooklyn, Human Paradigm Producer",
108
+ value: "brooklyn, human paradigm producer",
109
+ },
110
+ {
111
+ label: "Gussie, Future Configuration Supervisor",
112
+ value: "gussie, future configuration supervisor",
113
+ },
114
+ {
115
+ label: "Michel, Corporate Tactics Orchestrator",
116
+ value: "michel, corporate tactics orchestrator",
117
+ },
118
+ {
119
+ label: "Maxime, Customer Mobility Analyst",
120
+ value: "maxime, customer mobility analyst",
121
+ },
122
+ ];
@@ -0,0 +1 @@
1
+ export * from "./Autocomplete";
@@ -0,0 +1,19 @@
1
+ import { makeStyles } from "../theme";
2
+
3
+ const useStyles = makeStyles(
4
+ (theme) => ({
5
+ dropdown: {
6
+ maxHeight: 220,
7
+ overflow: "scroll",
8
+ },
9
+ loader: {
10
+ marginRight: theme.spacing(1),
11
+ },
12
+ popper: {
13
+ marginTop: theme.spacing(1),
14
+ },
15
+ }),
16
+ { name: "Autocomplete" }
17
+ );
18
+
19
+ export default useStyles;
@@ -4,6 +4,7 @@ import React from "react";
4
4
 
5
5
  import { ArrowRightIcon } from "../icons";
6
6
  import { LayoutButton, LayoutButtonProps } from "../LayoutButton";
7
+ import { useTheme } from "../theme";
7
8
  import { useBacklink } from "./context";
8
9
  import useStyles from "./styles";
9
10
 
@@ -19,10 +20,11 @@ export const Backlink: React.FC<AppHeaderProps> = ({
19
20
  onClick,
20
21
  ...props
21
22
  }) => {
23
+ const { ssr } = useTheme();
22
24
  const classes = useStyles();
23
25
  const anchor = useBacklink();
24
26
 
25
- if (!anchor.current) {
27
+ if (!anchor.current && !ssr) {
26
28
  return null;
27
29
  }
28
30
 
@@ -0,0 +1,52 @@
1
+ import clsx from "clsx";
2
+ import React from "react";
3
+
4
+ import useStyles from "./styles";
5
+
6
+ export interface ChipProps
7
+ extends React.DetailedHTMLProps<
8
+ React.HTMLAttributes<HTMLDivElement>,
9
+ HTMLDivElement
10
+ > {
11
+ startAdornment?: React.ReactElement;
12
+ startAdornmentClassName?: string;
13
+ endAdornment?: React.ReactElement;
14
+ endAdornmnetClassName?: string;
15
+ }
16
+
17
+ export const Chip = React.forwardRef<HTMLDivElement, ChipProps>(
18
+ (
19
+ {
20
+ startAdornment,
21
+ startAdornmentClassName,
22
+ endAdornment,
23
+ endAdornmnetClassName,
24
+ className,
25
+ children,
26
+ ...props
27
+ }: ChipProps,
28
+ ref
29
+ ) => {
30
+ const classes = useStyles();
31
+
32
+ return (
33
+ <div className={clsx(classes.chip, className)} ref={ref} {...props}>
34
+ {startAdornment && (
35
+ <span
36
+ className={clsx(classes.startAdornment, startAdornmentClassName)}
37
+ >
38
+ {startAdornment}
39
+ </span>
40
+ )}
41
+ <span>{children}</span>
42
+ {endAdornment && (
43
+ <span className={clsx(classes.endAdornment, endAdornmnetClassName)}>
44
+ {endAdornment}
45
+ </span>
46
+ )}
47
+ </div>
48
+ );
49
+ }
50
+ );
51
+
52
+ Chip.displayName = "Chip";
@@ -0,0 +1,53 @@
1
+ import clsx from "clsx";
2
+ import React from "react";
3
+
4
+ import { makeStyles } from "../theme";
5
+
6
+ const useStyles = makeStyles(
7
+ (theme) => ({
8
+ adornment: {
9
+ color: theme.palette.primary.contrastText,
10
+ opacity: 0.6,
11
+ cursor: "pointer",
12
+ display: "flex",
13
+ alignItems: "center",
14
+ transition: theme.transitions.create("opacity", {
15
+ duration: theme.transitions.duration.short,
16
+ easing: theme.transitions.easing.easeOut,
17
+ }),
18
+ lineHeight: 0,
19
+ "&:hover": {
20
+ opacity: 1,
21
+ },
22
+ },
23
+ defaultCursor: {
24
+ cursor: "inherit",
25
+ },
26
+ }),
27
+ { name: "ChipAdornment" }
28
+ );
29
+
30
+ export interface ChipAdornmentProps {
31
+ className?: string;
32
+ inheirtCursor?: boolean;
33
+ }
34
+
35
+ export const ChipAdornment: React.FC<ChipAdornmentProps> = ({
36
+ className,
37
+ inheirtCursor,
38
+ children,
39
+ }) => {
40
+ const classes = useStyles();
41
+
42
+ return (
43
+ <span
44
+ className={clsx(
45
+ classes.adornment,
46
+ inheirtCursor && classes.defaultCursor,
47
+ className
48
+ )}
49
+ >
50
+ {children}
51
+ </span>
52
+ );
53
+ };
@@ -0,0 +1,40 @@
1
+ import clsx from "clsx";
2
+ import React from "react";
3
+
4
+ import { DragIcon } from "../icons";
5
+ import { makeStyles } from "../theme";
6
+ import { Chip, ChipProps } from "./Chip";
7
+ import { ChipAdornment } from "./ChipAdornment";
8
+
9
+ export interface ChipMovableProps extends ChipProps {}
10
+
11
+ const useStyles = makeStyles(
12
+ () => ({
13
+ root: {
14
+ cursor: "move",
15
+ },
16
+ }),
17
+ { name: "ChipMovable" }
18
+ );
19
+
20
+ export const ChipMovable = React.forwardRef<HTMLDivElement, ChipMovableProps>(
21
+ ({ startAdornment, className, ...props }, ref) => {
22
+ const classes = useStyles();
23
+
24
+ return (
25
+ <Chip
26
+ className={clsx(classes.root, className)}
27
+ startAdornment={
28
+ <ChipAdornment inheirtCursor>
29
+ <DragIcon aria-hidden="true" />
30
+ {startAdornment}
31
+ </ChipAdornment>
32
+ }
33
+ {...props}
34
+ ref={ref}
35
+ />
36
+ );
37
+ }
38
+ );
39
+
40
+ ChipMovable.displayName = "ChipMovable";
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+
3
+ import { CloseIcon } from "../icons";
4
+ import { Chip, ChipProps } from "./Chip";
5
+ import { ChipAdornment } from "./ChipAdornment";
6
+
7
+ export interface ChipRemovableProps extends ChipProps {
8
+ onRemove: () => void;
9
+ }
10
+
11
+ export const ChipRemovable = React.forwardRef<
12
+ HTMLDivElement,
13
+ ChipRemovableProps
14
+ >(({ endAdornment, onRemove, ...props }, ref) => {
15
+ return (
16
+ <Chip
17
+ endAdornment={
18
+ <ChipAdornment>
19
+ <CloseIcon role="button" onClick={() => onRemove()} />
20
+ {endAdornment}
21
+ </ChipAdornment>
22
+ }
23
+ {...props}
24
+ ref={ref}
25
+ />
26
+ );
27
+ });
28
+
29
+ ChipRemovable.displayName = "ChipRemovable";