@basic-ui/material 1.0.0-alpha.15 → 1.0.0-alpha.18

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/build/cjs/index.js +296 -52
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/Alert/Alert.d.ts +1 -1
  4. package/build/esm/AppBar/AppBarButton.d.ts +1 -1
  5. package/build/esm/BottomSheet/BottomSheet.d.ts +1 -1
  6. package/build/esm/BottomSheet/BottomSheetSurface.d.ts +1 -1
  7. package/build/esm/Button/BaseButton.d.ts +1 -1
  8. package/build/esm/Button/BaseButton.js +1 -0
  9. package/build/esm/Button/BaseButton.js.map +1 -1
  10. package/build/esm/Button/Button.d.ts +1 -1
  11. package/build/esm/Button/ButtonGroup.d.ts +1 -1
  12. package/build/esm/Button/FilledButton.d.ts +1 -1
  13. package/build/esm/Button/OutlinedButton.d.ts +1 -1
  14. package/build/esm/Button/TransparentButton.d.ts +1 -1
  15. package/build/esm/CheckBox/CheckBox.d.ts +1 -1
  16. package/build/esm/Chip/ButtonChip.d.ts +1 -1
  17. package/build/esm/Chip/ChipBase.d.ts +1 -1
  18. package/build/esm/Chip/ChoiceChip.d.ts +1 -1
  19. package/build/esm/Combobox/Combobox.d.ts +7 -7
  20. package/build/esm/Combobox/Combobox.js +4 -3
  21. package/build/esm/Combobox/Combobox.js.map +1 -1
  22. package/build/esm/Dialog/Dialog.d.ts +1 -1
  23. package/build/esm/Dialog/DialogBackdrop.d.ts +1 -1
  24. package/build/esm/Dialog/DialogSurface.d.ts +1 -1
  25. package/build/esm/Dialog/Scrim.d.ts +1 -1
  26. package/build/esm/Divider/Divider.d.ts +1 -1
  27. package/build/esm/Link/Link.d.ts +1 -1
  28. package/build/esm/Link/Link.js +12 -0
  29. package/build/esm/Link/Link.js.map +1 -1
  30. package/build/esm/ListItem/ListItem.d.ts +3 -1
  31. package/build/esm/ListItem/ListItem.js +46 -43
  32. package/build/esm/ListItem/ListItem.js.map +1 -1
  33. package/build/esm/Menu/Menu.d.ts +4 -4
  34. package/build/esm/NavRail/NavRailItem.d.ts +3 -3
  35. package/build/esm/Paper/Paper.d.ts +1 -1
  36. package/build/esm/RadioButton/RadioGroup.d.ts +1 -1
  37. package/build/esm/Ripple/useRippleSurface.d.ts +1 -0
  38. package/build/esm/Ripple/useRippleSurface.js +17 -16
  39. package/build/esm/Ripple/useRippleSurface.js.map +1 -1
  40. package/build/esm/Select/Select.d.ts +1 -1
  41. package/build/esm/Select/Select.js +4 -0
  42. package/build/esm/Select/Select.js.map +1 -1
  43. package/build/esm/Select/SelectIcon.d.ts +1 -1
  44. package/build/esm/SelectItem/SelectItem.d.ts +5 -2
  45. package/build/esm/SelectItem/SelectItem.js +17 -4
  46. package/build/esm/SelectItem/SelectItem.js.map +1 -1
  47. package/build/esm/SelectionControl/SelectionControlText.d.ts +1 -1
  48. package/build/esm/Skeleton/Skeleton.d.ts +1 -1
  49. package/build/esm/Slider/Slider.d.ts +17 -0
  50. package/build/esm/Slider/Slider.js +224 -0
  51. package/build/esm/Slider/Slider.js.map +1 -0
  52. package/build/esm/Slider/index.d.ts +1 -0
  53. package/build/esm/Slider/index.js +2 -0
  54. package/build/esm/Slider/index.js.map +1 -0
  55. package/build/esm/Snackbar/Snackbar.d.ts +1 -1
  56. package/build/esm/Switch/Switch.d.ts +1 -1
  57. package/build/esm/Tab/Tab.d.ts +1 -1
  58. package/build/esm/Tab/TabList.d.ts +1 -1
  59. package/build/esm/Tab/TabPanel.d.ts +1 -1
  60. package/build/esm/TabIndicator/TabIndicator.d.ts +1 -1
  61. package/build/esm/Table/TableHead.d.ts +1 -1
  62. package/build/esm/Table/TableRow.d.ts +1 -1
  63. package/build/esm/TextField/FilledContainer.d.ts +1 -1
  64. package/build/esm/TextField/HelperText.d.ts +1 -1
  65. package/build/esm/TextField/Input.d.ts +1 -1
  66. package/build/esm/TextField/OutlinedContainer.d.ts +1 -1
  67. package/build/esm/TextField/OutlinedContainer.js +13 -5
  68. package/build/esm/TextField/OutlinedContainer.js.map +1 -1
  69. package/build/esm/TextField/TextField.d.ts +1 -1
  70. package/build/esm/ThemeExplorer/BorderSlider.d.ts +7 -0
  71. package/build/esm/ThemeExplorer/BorderSlider.js +78 -0
  72. package/build/esm/ThemeExplorer/BorderSlider.js.map +1 -0
  73. package/build/esm/ThemeExplorer/ColorSchemePicker.d.ts +10 -0
  74. package/build/esm/ThemeExplorer/ColorSchemePicker.js +54 -0
  75. package/build/esm/ThemeExplorer/ColorSchemePicker.js.map +1 -0
  76. package/build/esm/ThemeExplorer/FontAutoComplete.d.ts +9 -0
  77. package/build/esm/ThemeExplorer/FontAutoComplete.js +128 -0
  78. package/build/esm/ThemeExplorer/FontAutoComplete.js.map +1 -0
  79. package/build/esm/ThemeExplorer/ThemeBuilder.d.ts +2 -0
  80. package/build/esm/ThemeExplorer/ThemeBuilder.js +231 -93
  81. package/build/esm/ThemeExplorer/ThemeBuilder.js.map +1 -1
  82. package/build/esm/ThemeExplorer/components.js +4 -4
  83. package/build/esm/ThemeExplorer/components.js.map +1 -1
  84. package/build/esm/ThemeExplorer/googleFonts.d.ts +1 -0
  85. package/build/esm/ThemeExplorer/googleFonts.js +7 -0
  86. package/build/esm/ThemeExplorer/googleFonts.js.map +1 -0
  87. package/build/esm/ThemeExplorer/updateGoogleFonts.js +70 -0
  88. package/build/esm/ThemeExplorer/updateGoogleFonts.js.map +1 -0
  89. package/build/esm/ThemeExplorer/useDeferredColor.js +3 -4
  90. package/build/esm/ThemeExplorer/useDeferredColor.js.map +1 -1
  91. package/build/esm/Tooltip/Tooltip.d.ts +1 -1
  92. package/build/esm/index.d.ts +1 -0
  93. package/build/esm/index.js +1 -0
  94. package/build/esm/index.js.map +1 -1
  95. package/build/tsconfig-build.tsbuildinfo +1 -1
  96. package/package.json +6 -6
  97. package/src/Button/BaseButton.tsx +1 -0
  98. package/src/Combobox/Combobox.tsx +5 -2
  99. package/src/Link/Link.tsx +12 -0
  100. package/src/ListItem/ListItem.tsx +48 -42
  101. package/src/Ripple/useRippleSurface.ts +8 -2
  102. package/src/Select/PaymentMethodSelect.story.tsx +17 -24
  103. package/src/Select/Select.tsx +6 -0
  104. package/src/SelectItem/SelectItem.tsx +13 -3
  105. package/src/Slider/Slider.story.tsx +36 -0
  106. package/src/Slider/Slider.tsx +275 -0
  107. package/src/Slider/index.ts +1 -0
  108. package/src/TextField/OutlinedContainer.tsx +8 -3
  109. package/src/ThemeExplorer/BorderSlider.tsx +73 -0
  110. package/src/ThemeExplorer/ColorSchemePicker.tsx +55 -0
  111. package/src/ThemeExplorer/FontAutoComplete.tsx +139 -0
  112. package/src/ThemeExplorer/ThemeBuilder.story.tsx +2 -1
  113. package/src/ThemeExplorer/ThemeBuilder.tsx +218 -82
  114. package/src/ThemeExplorer/components.tsx +4 -4
  115. package/src/ThemeExplorer/googleFonts.ts +1436 -0
  116. package/src/ThemeExplorer/updateGoogleFonts.js +33 -0
  117. package/src/ThemeExplorer/useDeferredColor.tsx +3 -6
  118. package/src/index.ts +1 -0
@@ -0,0 +1,275 @@
1
+ import {
2
+ SliderHandle as SliderHandleCore,
3
+ SliderInput as SliderInputCore,
4
+ SliderMarker as SliderMarkerCore,
5
+ SliderTrack as SliderTrackCore,
6
+ SliderRange as SliderRangeCore,
7
+ } from '@basic-ui/core';
8
+ import type {
9
+ SliderProps as SliderPropsCore,
10
+ SliderHandleProps as SliderHandlePropsCore,
11
+ SliderInputProps as SliderInputPropsCore,
12
+ SliderMarkerProps as SliderMarkerPropsCore,
13
+ SliderTrackProps as SliderTrackPropsCore,
14
+ SliderRangeProps as SliderRangePropsCore,
15
+ } from '@basic-ui/core';
16
+ export type { SliderHandleAlignment } from '@basic-ui/core';
17
+ import type { HTMLAttributes } from 'react';
18
+ import { forwardRef } from 'react';
19
+ import { rem } from 'polished';
20
+
21
+ import type { BoxProps } from '../Box';
22
+ import { Box } from '../Box';
23
+ import type { RippleBoxProps } from '../Ripple';
24
+ import { RippleBox } from '../Ripple';
25
+
26
+ /////////////////////////////////////////////////////
27
+ // SliderInput
28
+
29
+ export type SliderInputProps = Omit<
30
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>,
31
+ | 'onChange'
32
+ | 'onMouseDown'
33
+ | 'onMouseMove'
34
+ | 'onMouseUp'
35
+ | 'onPointerDown'
36
+ | 'onPointerUp'
37
+ | 'onTouchEnd'
38
+ | 'onTouchMove'
39
+ | 'onTouchStart'
40
+ > &
41
+ SliderInputPropsCore;
42
+
43
+ export const SliderInput = forwardRef<HTMLDivElement, SliderInputProps>(
44
+ ({ as = 'div', __css, ...props }, ref) => (
45
+ <SliderInputCore
46
+ as={Box}
47
+ innerAs={as as any}
48
+ ref={ref}
49
+ {...props}
50
+ __css={{
51
+ maxWidth: '100%',
52
+ cursor: 'pointer',
53
+ '&[data-orientation="horizontal"]': { height: rem(4) },
54
+ '&[data-orientation="vertical"]': {
55
+ width: rem(4),
56
+ height: '250px',
57
+ maxHeight: '100%',
58
+ },
59
+ '&[data-disabled]': { opacity: 0.5, pointerEvents: 'none' },
60
+ ...__css,
61
+ }}
62
+ />
63
+ )
64
+ );
65
+
66
+ /////////////////////////////////////////////////////
67
+ // SliderHandle
68
+
69
+ export type SliderHandleProps = SliderHandlePropsCore &
70
+ RippleBoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>;
71
+
72
+ export const SliderHandle = forwardRef<HTMLDivElement, SliderHandleProps>(
73
+ ({ as = 'div', __css, children, ...props }, ref) => (
74
+ <SliderHandleCore
75
+ as={RippleBox}
76
+ innerAs={as as any}
77
+ ref={ref}
78
+ rippleColor="currentColor"
79
+ hoverOpacity={0.12}
80
+ focusOpacity={0.24}
81
+ pressedOpacity={0.24}
82
+ mouseFocus
83
+ center
84
+ __css={{
85
+ position: 'relative',
86
+ width: rem(40),
87
+ height: rem(40),
88
+ color: 'primary',
89
+ borderRadius: 'full',
90
+ zIndex: 1,
91
+ transformOrigin: 'center',
92
+ userSelect: 'none',
93
+ '&[aria-orientation="horizontal"]': {
94
+ top: '50%',
95
+ transform: 'translateY(-50%)',
96
+ },
97
+ '&[aria-orientation="horizontal"]:focus': {
98
+ transform: 'translateY(-50%)',
99
+ },
100
+ '&[aria-orientation="vertical"]': {
101
+ left: '50%',
102
+ transform: 'translateX(-50%)',
103
+ },
104
+ ':focus': {
105
+ outline: 'none',
106
+ },
107
+ ...__css,
108
+ }}
109
+ {...props}
110
+ >
111
+ <Box
112
+ __css={{
113
+ bg: 'currentColor',
114
+ width: '50%',
115
+ height: '50%',
116
+ borderRadius: 'full',
117
+ pointerEvents: 'none',
118
+ position: 'absolute',
119
+ top: '50%',
120
+ left: '50%',
121
+ transform: 'translate(-50%, -50%)',
122
+ boxShadow: 1,
123
+ }}
124
+ />
125
+ {children}
126
+ </SliderHandleCore>
127
+ )
128
+ );
129
+
130
+ /////////////////////////////////////////////////////
131
+ // SliderMarker
132
+
133
+ export type SliderMarkerProps = SliderMarkerPropsCore &
134
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>;
135
+
136
+ export const SliderMarker = forwardRef<HTMLDivElement, SliderMarkerProps>(
137
+ ({ as = 'div', __css, ...props }, ref) => (
138
+ <SliderMarkerCore
139
+ as={Box}
140
+ innerAs={as as any}
141
+ ref={ref}
142
+ {...props}
143
+ __css={{
144
+ transformOrigin: 'center',
145
+ borderRadius: 'full',
146
+ width: '2px',
147
+ height: '2px',
148
+ '&[data-orientation="horizontal"]': {
149
+ top: '50%',
150
+ transform: 'translate(-50%, -50%)',
151
+ },
152
+ '&[data-orientation="vertical"]': {
153
+ left: '50%',
154
+ transform: 'translate(-50%, -50%)',
155
+ },
156
+ opacity: 0.38,
157
+ bg: 'on.surface-variant',
158
+ '&[data-state="at-value"],&[data-state="under-value"]': {
159
+ bg: 'on.primary',
160
+ },
161
+ ...__css,
162
+ }}
163
+ />
164
+ )
165
+ );
166
+
167
+ /////////////////////////////////////////////////////
168
+ // SliderTrack
169
+
170
+ export type SliderTrackProps = SliderTrackPropsCore &
171
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>;
172
+
173
+ export const SliderTrack = forwardRef<HTMLDivElement, SliderTrackProps>(
174
+ ({ as = 'div', __css, ...props }, ref) => (
175
+ <SliderTrackCore
176
+ as={Box}
177
+ innerAs={as as any}
178
+ ref={ref}
179
+ {...props}
180
+ __css={{
181
+ position: 'relative',
182
+ borderRadius: 'full',
183
+ bg: 'surface-variant',
184
+ '&[data-orientation="horizontal"]': {
185
+ width: '100%',
186
+ height: 'inherit',
187
+ },
188
+ '&[data-orientation="vertical"]': {
189
+ width: 'inherit',
190
+ height: '100%',
191
+ },
192
+ '&::before': {
193
+ content: '""',
194
+ position: 'absolute',
195
+ },
196
+ '&[data-orientation="horizontal"]::before': {
197
+ width: '100%',
198
+ height: '1.5rem',
199
+ top: 'calc(-0.5rem - 1px)',
200
+ left: '0',
201
+ },
202
+ '&[data-orientation="vertical"]::before': {
203
+ width: '1.5rem',
204
+ height: '100%',
205
+ top: '0',
206
+ left: 'calc(-0.5rem - 1px)',
207
+ },
208
+ ...__css,
209
+ }}
210
+ />
211
+ )
212
+ );
213
+
214
+ /////////////////////////////////////////////////////
215
+ // SliderRange
216
+
217
+ export type SliderRangeProps = SliderRangePropsCore &
218
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>;
219
+
220
+ export const SliderRange = forwardRef<HTMLDivElement, SliderRangeProps>(
221
+ ({ as = 'div', __css, ...props }, ref) => (
222
+ <SliderRangeCore
223
+ as={Box}
224
+ innerAs={as as any}
225
+ ref={ref}
226
+ __css={{
227
+ borderRadius: 'inherit',
228
+ bg: 'primary',
229
+ left: '0',
230
+ bottom: '0',
231
+ top: '50%',
232
+ '&[data-orientation="horizontal"]': {
233
+ height: '100%',
234
+ },
235
+ '&[data-orientation="vertical"]': {
236
+ width: '100%',
237
+ },
238
+ transform: 'translateY(-50%)',
239
+ ...__css,
240
+ }}
241
+ {...props}
242
+ />
243
+ )
244
+ );
245
+
246
+ export type SliderProps = SliderPropsCore &
247
+ Omit<
248
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>,
249
+ | 'onChange'
250
+ | 'onMouseDown'
251
+ | 'onMouseMove'
252
+ | 'onMouseUp'
253
+ | 'onPointerDown'
254
+ | 'onPointerUp'
255
+ | 'onTouchEnd'
256
+ | 'onTouchMove'
257
+ | 'onTouchStart'
258
+ >;
259
+
260
+ export const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(
261
+ props,
262
+ forwardedRef
263
+ ) {
264
+ const { children, ...otherProps } = props;
265
+
266
+ return (
267
+ <SliderInput {...otherProps} ref={forwardedRef} data-reach-slider="">
268
+ <SliderTrack>
269
+ <SliderRange />
270
+ <SliderHandle />
271
+ {children}
272
+ </SliderTrack>
273
+ </SliderInput>
274
+ );
275
+ });
@@ -0,0 +1 @@
1
+ export * from './Slider';
@@ -58,12 +58,17 @@ export const OutlinedContainer = forwardRef<
58
58
 
59
59
  if (element) {
60
60
  setLabelWidth(element.offsetWidth);
61
- (document as any)?.fonts?.ready?.then(() => {
61
+ function handleFontsLoaded() {
62
62
  // set the label width again once the fonts have been loaded
63
63
  requestAnimationFrame(() => {
64
- setLabelWidth(element.offsetWidth);
64
+ if (element) setLabelWidth(element.offsetWidth);
65
65
  });
66
- });
66
+ }
67
+ document.fonts?.addEventListener?.('loadingdone', handleFontsLoaded);
68
+ document.fonts?.ready?.then(handleFontsLoaded);
69
+
70
+ return () =>
71
+ document.fonts?.removeEventListener?.('loadingdone', handleFontsLoaded);
67
72
  }
68
73
  }, [label]);
69
74
 
@@ -0,0 +1,73 @@
1
+ import type { ButtonHTMLAttributes, FC } from 'react';
2
+ import { startTransition, useEffect, useRef, useState } from 'react';
3
+
4
+ import type { BoxProps } from '../Box';
5
+ import { Box } from '../Box';
6
+ import { Link as BaseLink } from '../Link';
7
+ import { Slider, SliderMarker } from '../Slider';
8
+ import { Text } from '../Text';
9
+
10
+ const Link: FC<
11
+ BoxProps<HTMLButtonElement, ButtonHTMLAttributes<HTMLButtonElement>>
12
+ > = BaseLink as any;
13
+
14
+ export function BorderSlider(props: {
15
+ label: string;
16
+ defaultValue: number;
17
+ onChange: (value: number) => void;
18
+ onReset: () => void;
19
+ resetDisabled: boolean;
20
+ }) {
21
+ const [value, setValue] = useState(props.defaultValue);
22
+
23
+ const resetting = useRef(false);
24
+ useEffect(() => {
25
+ if (resetting.current) {
26
+ setValue(props.defaultValue);
27
+ resetting.current = false;
28
+ }
29
+ }, [props.defaultValue]);
30
+
31
+ return (
32
+ <Box width="100%" display="flex" flexDirection="column">
33
+ <Text display="flex" justifyContent="space-between" width="100%" pb={2}>
34
+ <span>
35
+ {props.label}{' '}
36
+ <Link
37
+ as="button"
38
+ disabled={props.resetDisabled ? true : undefined}
39
+ onClick={() => {
40
+ resetting.current = true;
41
+ props.onReset();
42
+ }}
43
+ >
44
+ Reset
45
+ </Link>
46
+ </span>
47
+ <span>{value}px</span>
48
+ </Text>
49
+ <Slider
50
+ value={value}
51
+ onChange={(e, v) => {
52
+ setValue(v);
53
+ startTransition(() => {
54
+ props.onChange(v);
55
+ });
56
+ }}
57
+ min={0}
58
+ max={64}
59
+ step={2}
60
+ >
61
+ <SliderMarker value={2} />
62
+ <SliderMarker value={4} />
63
+ <SliderMarker value={8} />
64
+ <SliderMarker value={12} />
65
+ <SliderMarker value={16} />
66
+ <SliderMarker value={24} />
67
+ <SliderMarker value={32} />
68
+ <SliderMarker value={40} />
69
+ <SliderMarker value={48} />
70
+ </Slider>
71
+ </Box>
72
+ );
73
+ }
@@ -0,0 +1,55 @@
1
+ import type { Color } from '@basic-ui/color-picker';
2
+ import { startTransition, useEffect, useRef, useState } from 'react';
3
+
4
+ import { Box } from '../Box';
5
+ import { Button } from '../Button';
6
+ import { TextFieldColorPicker } from './TextFieldColorPicker';
7
+
8
+ interface ColorSchemePickerProps {
9
+ label: string;
10
+ initialValue: Color;
11
+ onChange: (c: Color) => void;
12
+ onReset: () => void;
13
+ resetDisabled: boolean;
14
+ }
15
+
16
+ export function ColorSchemePicker(props: ColorSchemePickerProps) {
17
+ const { label, initialValue, onChange, onReset, resetDisabled } = props;
18
+ const [value, setValue] = useState(initialValue);
19
+
20
+ const remountKey = useRef(0);
21
+ const resetting = useRef(false);
22
+ useEffect(() => {
23
+ if (resetting.current) {
24
+ remountKey.current++;
25
+ resetting.current = false;
26
+ setValue(props.initialValue);
27
+ }
28
+ }, [props.initialValue]);
29
+
30
+ return (
31
+ <Box display="flex" minWidth="300px" flex="1" alignItems="center">
32
+ <TextFieldColorPicker
33
+ key={remountKey.current}
34
+ label={label}
35
+ value={value}
36
+ onChange={(c) => {
37
+ setValue(c);
38
+ startTransition(() => {
39
+ onChange(c);
40
+ });
41
+ }}
42
+ />
43
+ <Button
44
+ variant="text"
45
+ disabled={resetDisabled}
46
+ onClick={() => {
47
+ resetting.current = true;
48
+ onReset();
49
+ }}
50
+ >
51
+ Reset
52
+ </Button>
53
+ </Box>
54
+ );
55
+ }
@@ -0,0 +1,139 @@
1
+ import {
2
+ useState,
3
+ useMemo,
4
+ useEffect,
5
+ useRef,
6
+ useDeferredValue,
7
+ memo,
8
+ } from 'react';
9
+
10
+ import { Box } from '../Box';
11
+ import { Button } from '../Button';
12
+ import {
13
+ Combobox,
14
+ ComboboxOption,
15
+ ComboboxList,
16
+ ComboboxPopover,
17
+ ComboboxInput,
18
+ ComboboxButton,
19
+ } from '../Combobox';
20
+ import { Text } from '../Text';
21
+ import { googleFonts } from './googleFonts';
22
+
23
+ export interface FontAutoCompleteProps {
24
+ label?: string;
25
+ initialValue?: string;
26
+ onSelect?: (font: string) => void;
27
+ onReset: () => void;
28
+ resetDisabled: boolean;
29
+ }
30
+
31
+ function useFontMatch(searchTerm: string) {
32
+ return useMemo(() => {
33
+ const term = searchTerm.trim().toLowerCase();
34
+ return term === ''
35
+ ? googleFonts
36
+ : googleFonts.filter((font) => font.toLowerCase().indexOf(term) !== -1);
37
+ }, [searchTerm]);
38
+ }
39
+
40
+ export function parseMainFont(fontStr: string): string | undefined {
41
+ const fonts = fontStr.split(/, */).map((f) => f.replace(/"([^"]+)"/, '$1'));
42
+ return fonts.length > 0 ? fonts[0] : undefined;
43
+ }
44
+
45
+ export function FontAutoComplete({
46
+ initialValue = '',
47
+ onSelect,
48
+ label,
49
+ onReset,
50
+ resetDisabled,
51
+ }: FontAutoCompleteProps) {
52
+ const [term, setTerm] = useState<undefined | string>(undefined);
53
+ const filterTerm = useDeferredValue(term);
54
+ const [selected, setSelected] = useState(initialValue);
55
+
56
+ const resetting = useRef(false);
57
+ useEffect(() => {
58
+ if (resetting.current) {
59
+ setSelected(initialValue);
60
+ setTerm(undefined);
61
+ resetting.current = false;
62
+ }
63
+ }, [initialValue]);
64
+
65
+ const results = useFontMatch(filterTerm || '');
66
+ return (
67
+ <Box display="flex" minWidth="300px" flex="1" alignItems="center">
68
+ <Combobox
69
+ onSelect={(text) => {
70
+ setSelected(text);
71
+ setTerm(text);
72
+ onSelect?.(text);
73
+ }}
74
+ selectOnBlur
75
+ width="100%"
76
+ >
77
+ <Box position="relative" width="100%">
78
+ <ComboboxInput
79
+ onChange={(e) => {
80
+ setTerm(e.target.value);
81
+ }}
82
+ value={term === undefined ? selected : term}
83
+ label={label}
84
+ />
85
+ <Box
86
+ height={56}
87
+ width={56}
88
+ position="absolute"
89
+ justifyContent="center"
90
+ alignItems="center"
91
+ display="flex"
92
+ top={0}
93
+ right={0}
94
+ bottom={0}
95
+ >
96
+ <ComboboxButton />
97
+ </Box>
98
+ </Box>
99
+ <SearchResults results={results} />
100
+ </Combobox>
101
+ <Button
102
+ variant="text"
103
+ onClick={() => {
104
+ resetting.current = true;
105
+ onReset();
106
+ }}
107
+ disabled={resetDisabled}
108
+ >
109
+ Reset
110
+ </Button>
111
+ </Box>
112
+ );
113
+ }
114
+
115
+ const SearchResults = memo(function SearchResults(props: {
116
+ results: string[];
117
+ }) {
118
+ if (!props.results) {
119
+ return null;
120
+ }
121
+
122
+ return (
123
+ <ComboboxPopover zIndex={100}>
124
+ <ComboboxList persistSelection={true}>
125
+ <Text variant="label-medium" opacity={0.6} px={3} py={2}>
126
+ Sorted by popularity
127
+ </Text>
128
+ {props.results.map((result) => (
129
+ <ComboboxOption
130
+ key={result}
131
+ id={result}
132
+ text={result}
133
+ value={result}
134
+ />
135
+ ))}
136
+ </ComboboxList>
137
+ </ComboboxPopover>
138
+ );
139
+ });
@@ -1,7 +1,8 @@
1
+ import { theme } from '../theme/theme';
1
2
  import { ThemeBuilder } from './ThemeBuilder';
2
3
 
3
4
  export default {
4
5
  title: 'components/ThemeExplorer',
5
6
  };
6
7
 
7
- export const Builder = () => <ThemeBuilder />;
8
+ export const Builder = () => <ThemeBuilder baseTheme={theme} />;