@ttoss/ui 3.1.2 → 3.1.4
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/dist/esm/index.js +78 -20
- package/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +78 -20
- package/package.json +2 -2
- package/src/components/Select.tsx +101 -30
package/dist/esm/index.js
CHANGED
|
@@ -261,43 +261,75 @@ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-run
|
|
|
261
261
|
var Select = /*#__PURE__*/React4.forwardRef(({
|
|
262
262
|
arrow,
|
|
263
263
|
sx,
|
|
264
|
+
leadingIcon,
|
|
265
|
+
trailingIcon,
|
|
264
266
|
...props
|
|
265
267
|
}, ref) => {
|
|
268
|
+
const hasError = props["aria-invalid"] === "true";
|
|
269
|
+
const refEl = React4.useRef({});
|
|
270
|
+
React4.useImperativeHandle(ref, () => {
|
|
271
|
+
return refEl.current;
|
|
272
|
+
});
|
|
273
|
+
React4.useEffect(() => {
|
|
274
|
+
const parentEl = refEl.current?.parentElement;
|
|
275
|
+
if (parentEl) {
|
|
276
|
+
parentEl.style.position = "relative";
|
|
277
|
+
}
|
|
278
|
+
}, []);
|
|
266
279
|
return /* @__PURE__ */jsx7(SelectUi, {
|
|
267
280
|
arrow: /* @__PURE__ */jsxs6(Fragment2, {
|
|
268
|
-
children: [
|
|
281
|
+
children: [leadingIcon && /* @__PURE__ */jsx7(Text, {
|
|
269
282
|
sx: {
|
|
270
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
271
|
-
marginLeft: ({
|
|
272
|
-
space
|
|
273
|
-
}) => {
|
|
274
|
-
return space?.["2xl"] ? "-2xl" : "-28px";
|
|
275
|
-
},
|
|
276
283
|
alignSelf: "center",
|
|
277
284
|
pointerEvents: "none",
|
|
278
285
|
lineHeight: 0,
|
|
279
|
-
fontSize: "base"
|
|
286
|
+
fontSize: "base",
|
|
287
|
+
position: "absolute",
|
|
288
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
289
|
+
left: ({
|
|
290
|
+
space
|
|
291
|
+
}) => {
|
|
292
|
+
const leftSpaceValue = space?.["xl"] || "16px";
|
|
293
|
+
return leftSpaceValue;
|
|
294
|
+
}
|
|
280
295
|
},
|
|
281
296
|
children: /* @__PURE__ */jsx7(Icon5, {
|
|
282
|
-
icon:
|
|
297
|
+
icon: leadingIcon
|
|
283
298
|
})
|
|
284
|
-
}),
|
|
285
|
-
className: "error-icon",
|
|
299
|
+
}), /* @__PURE__ */jsxs6(Flex, {
|
|
286
300
|
sx: {
|
|
301
|
+
gap: "lg",
|
|
302
|
+
position: "absolute",
|
|
287
303
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
288
|
-
|
|
304
|
+
right: ({
|
|
289
305
|
space
|
|
290
306
|
}) => {
|
|
291
|
-
|
|
307
|
+
const xlSpace = space?.["xl"] || "16px";
|
|
308
|
+
return xlSpace;
|
|
292
309
|
},
|
|
293
310
|
alignSelf: "center",
|
|
294
|
-
pointerEvents: "none"
|
|
295
|
-
lineHeight: 0,
|
|
296
|
-
fontSize: "base"
|
|
311
|
+
pointerEvents: "none"
|
|
297
312
|
},
|
|
298
|
-
children: /* @__PURE__ */jsx7(
|
|
299
|
-
|
|
300
|
-
|
|
313
|
+
children: [(trailingIcon || hasError) && /* @__PURE__ */jsx7(Text, {
|
|
314
|
+
className: hasError ? "error-icon" : "",
|
|
315
|
+
sx: {
|
|
316
|
+
alignSelf: "center",
|
|
317
|
+
pointerEvents: "none",
|
|
318
|
+
lineHeight: 0,
|
|
319
|
+
fontSize: "base"
|
|
320
|
+
},
|
|
321
|
+
children: /* @__PURE__ */jsx7(Icon5, {
|
|
322
|
+
icon: hasError ? "warning-alt" : trailingIcon
|
|
323
|
+
})
|
|
324
|
+
}), arrow ?? /* @__PURE__ */jsx7(Text, {
|
|
325
|
+
sx: {
|
|
326
|
+
lineHeight: 0,
|
|
327
|
+
fontSize: "base"
|
|
328
|
+
},
|
|
329
|
+
children: /* @__PURE__ */jsx7(Icon5, {
|
|
330
|
+
icon: "picker-down"
|
|
331
|
+
})
|
|
332
|
+
})]
|
|
301
333
|
})]
|
|
302
334
|
}),
|
|
303
335
|
sx: {
|
|
@@ -305,9 +337,35 @@ var Select = /*#__PURE__*/React4.forwardRef(({
|
|
|
305
337
|
width: "100%",
|
|
306
338
|
paddingY: "lg",
|
|
307
339
|
paddingX: "xl",
|
|
340
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
341
|
+
paddingLeft: ({
|
|
342
|
+
space,
|
|
343
|
+
fontSizes
|
|
344
|
+
}) => {
|
|
345
|
+
const xlSpace = space?.["xl"] || "16px";
|
|
346
|
+
const iconSize = fontSizes?.["base"] || "16px";
|
|
347
|
+
const lgSpace = space?.["lg"] || "16px";
|
|
348
|
+
if (leadingIcon) {
|
|
349
|
+
return `calc(${xlSpace} + ${iconSize} + ${lgSpace})`;
|
|
350
|
+
}
|
|
351
|
+
return xlSpace;
|
|
352
|
+
},
|
|
353
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
354
|
+
paddingRight: ({
|
|
355
|
+
space,
|
|
356
|
+
fontSizes
|
|
357
|
+
}) => {
|
|
358
|
+
const xlSpace = space?.["xl"] || "16px";
|
|
359
|
+
const iconSize = fontSizes?.["base"] || "16px";
|
|
360
|
+
const lgSpace = space?.["lg"] || "16px";
|
|
361
|
+
if (trailingIcon || hasError) {
|
|
362
|
+
return `calc(${lgSpace} + ${iconSize} + ${lgSpace} + ${iconSize} + ${xlSpace})`;
|
|
363
|
+
}
|
|
364
|
+
return `calc(${lgSpace} + ${iconSize} + ${xlSpace})`;
|
|
365
|
+
},
|
|
308
366
|
...sx
|
|
309
367
|
},
|
|
310
|
-
ref,
|
|
368
|
+
ref: refEl,
|
|
311
369
|
...props
|
|
312
370
|
});
|
|
313
371
|
});
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as theme_ui from 'theme-ui';
|
|
2
|
-
import { Theme, BadgeProps as BadgeProps$1, ButtonProps as ButtonProps$1, InputProps as InputProps$1, LabelProps as LabelProps$1, LinkProps as LinkProps$1, SelectProps, IconButtonProps, TextareaProps as TextareaProps$1, TextProps, FlexProps } from 'theme-ui';
|
|
3
|
-
export { BaseStyles, Box, BoxProps, Card, CardProps, Checkbox, CheckboxProps, ContainerProps, Divider, DividerProps, Flex, FlexProps, Global, Grid, GridProps, Heading, HeadingProps, IconButtonProps, Image, ImageProps, Progress as LinearProgress, ProgressProps as LinearProgressProps, Paragraph, ParagraphProps, Radio, RadioProps,
|
|
2
|
+
import { Theme, BadgeProps as BadgeProps$1, ButtonProps as ButtonProps$1, InputProps as InputProps$1, LabelProps as LabelProps$1, LinkProps as LinkProps$1, SelectProps as SelectProps$1, IconButtonProps, TextareaProps as TextareaProps$1, TextProps, FlexProps } from 'theme-ui';
|
|
3
|
+
export { BaseStyles, Box, BoxProps, Card, CardProps, Checkbox, CheckboxProps, ContainerProps, Divider, DividerProps, Flex, FlexProps, Global, Grid, GridProps, Heading, HeadingProps, IconButtonProps, Image, ImageProps, Progress as LinearProgress, ProgressProps as LinearProgressProps, Paragraph, ParagraphProps, Radio, RadioProps, Slider, SliderProps, Spinner, SpinnerProps, SxProp, Text, TextProps, Theme } from 'theme-ui';
|
|
4
4
|
export { useBreakpointIndex, useResponsiveValue } from '@theme-ui/match-media';
|
|
5
5
|
export { Keyframes, keyframes } from '@emotion/react';
|
|
6
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
@@ -50,6 +50,10 @@ type LinkProps = LinkProps$1 & {
|
|
|
50
50
|
};
|
|
51
51
|
declare const Link: React.ForwardRefExoticComponent<Omit<LinkProps, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
|
|
52
52
|
|
|
53
|
+
type SelectProps = SelectProps$1 & {
|
|
54
|
+
leadingIcon?: IconType;
|
|
55
|
+
trailingIcon?: IconType;
|
|
56
|
+
};
|
|
53
57
|
declare const Select: React.ForwardRefExoticComponent<Omit<SelectProps, "ref"> & React.RefAttributes<HTMLSelectElement>>;
|
|
54
58
|
|
|
55
59
|
declare const IconButton: React.ForwardRefExoticComponent<Omit<IconButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -100,4 +104,4 @@ type ActionButtonProps = Omit<ButtonProps, 'rightIcon' | 'leftIcon' | 'variant'>
|
|
|
100
104
|
};
|
|
101
105
|
declare const ActionButton: ({ icon, variant, sx, ...props }: ActionButtonProps) => react_jsx_runtime.JSX.Element;
|
|
102
106
|
|
|
103
|
-
export { ActionButton, ActionButtonProps, Badge, BadgeProps, Button, ButtonProps, CloseButton, CloseButtonProps, Container, HelpText, HelpTextProps, IconButton, InfiniteLinearProgress, Input, InputNumber, InputNumberProps, InputPassword, InputPasswordProps, InputProps, Label, LabelProps, Link, LinkProps, Select, Stack, StackProps, Textarea, TextareaProps, ThemeProvider, ThemeProviderProps, useTheme };
|
|
107
|
+
export { ActionButton, ActionButtonProps, Badge, BadgeProps, Button, ButtonProps, CloseButton, CloseButtonProps, Container, HelpText, HelpTextProps, IconButton, InfiniteLinearProgress, Input, InputNumber, InputNumberProps, InputPassword, InputPasswordProps, InputProps, Label, LabelProps, Link, LinkProps, Select, SelectProps, Stack, StackProps, Textarea, TextareaProps, ThemeProvider, ThemeProviderProps, useTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as theme_ui from 'theme-ui';
|
|
2
|
-
import { Theme, BadgeProps as BadgeProps$1, ButtonProps as ButtonProps$1, InputProps as InputProps$1, LabelProps as LabelProps$1, LinkProps as LinkProps$1, SelectProps, IconButtonProps, TextareaProps as TextareaProps$1, TextProps, FlexProps } from 'theme-ui';
|
|
3
|
-
export { BaseStyles, Box, BoxProps, Card, CardProps, Checkbox, CheckboxProps, ContainerProps, Divider, DividerProps, Flex, FlexProps, Global, Grid, GridProps, Heading, HeadingProps, IconButtonProps, Image, ImageProps, Progress as LinearProgress, ProgressProps as LinearProgressProps, Paragraph, ParagraphProps, Radio, RadioProps,
|
|
2
|
+
import { Theme, BadgeProps as BadgeProps$1, ButtonProps as ButtonProps$1, InputProps as InputProps$1, LabelProps as LabelProps$1, LinkProps as LinkProps$1, SelectProps as SelectProps$1, IconButtonProps, TextareaProps as TextareaProps$1, TextProps, FlexProps } from 'theme-ui';
|
|
3
|
+
export { BaseStyles, Box, BoxProps, Card, CardProps, Checkbox, CheckboxProps, ContainerProps, Divider, DividerProps, Flex, FlexProps, Global, Grid, GridProps, Heading, HeadingProps, IconButtonProps, Image, ImageProps, Progress as LinearProgress, ProgressProps as LinearProgressProps, Paragraph, ParagraphProps, Radio, RadioProps, Slider, SliderProps, Spinner, SpinnerProps, SxProp, Text, TextProps, Theme } from 'theme-ui';
|
|
4
4
|
export { useBreakpointIndex, useResponsiveValue } from '@theme-ui/match-media';
|
|
5
5
|
export { Keyframes, keyframes } from '@emotion/react';
|
|
6
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
@@ -50,6 +50,10 @@ type LinkProps = LinkProps$1 & {
|
|
|
50
50
|
};
|
|
51
51
|
declare const Link: React.ForwardRefExoticComponent<Omit<LinkProps, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
|
|
52
52
|
|
|
53
|
+
type SelectProps = SelectProps$1 & {
|
|
54
|
+
leadingIcon?: IconType;
|
|
55
|
+
trailingIcon?: IconType;
|
|
56
|
+
};
|
|
53
57
|
declare const Select: React.ForwardRefExoticComponent<Omit<SelectProps, "ref"> & React.RefAttributes<HTMLSelectElement>>;
|
|
54
58
|
|
|
55
59
|
declare const IconButton: React.ForwardRefExoticComponent<Omit<IconButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -100,4 +104,4 @@ type ActionButtonProps = Omit<ButtonProps, 'rightIcon' | 'leftIcon' | 'variant'>
|
|
|
100
104
|
};
|
|
101
105
|
declare const ActionButton: ({ icon, variant, sx, ...props }: ActionButtonProps) => react_jsx_runtime.JSX.Element;
|
|
102
106
|
|
|
103
|
-
export { ActionButton, ActionButtonProps, Badge, BadgeProps, Button, ButtonProps, CloseButton, CloseButtonProps, Container, HelpText, HelpTextProps, IconButton, InfiniteLinearProgress, Input, InputNumber, InputNumberProps, InputPassword, InputPasswordProps, InputProps, Label, LabelProps, Link, LinkProps, Select, Stack, StackProps, Textarea, TextareaProps, ThemeProvider, ThemeProviderProps, useTheme };
|
|
107
|
+
export { ActionButton, ActionButtonProps, Badge, BadgeProps, Button, ButtonProps, CloseButton, CloseButtonProps, Container, HelpText, HelpTextProps, IconButton, InfiniteLinearProgress, Input, InputNumber, InputNumberProps, InputPassword, InputPasswordProps, InputProps, Label, LabelProps, Link, LinkProps, Select, SelectProps, Stack, StackProps, Textarea, TextareaProps, ThemeProvider, ThemeProviderProps, useTheme };
|
package/dist/index.js
CHANGED
|
@@ -337,43 +337,75 @@ var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
|
337
337
|
var Select = React4.forwardRef(({
|
|
338
338
|
arrow,
|
|
339
339
|
sx,
|
|
340
|
+
leadingIcon,
|
|
341
|
+
trailingIcon,
|
|
340
342
|
...props
|
|
341
343
|
}, ref) => {
|
|
344
|
+
const hasError = props["aria-invalid"] === "true";
|
|
345
|
+
const refEl = React4.useRef({});
|
|
346
|
+
React4.useImperativeHandle(ref, () => {
|
|
347
|
+
return refEl.current;
|
|
348
|
+
});
|
|
349
|
+
React4.useEffect(() => {
|
|
350
|
+
const parentEl = refEl.current?.parentElement;
|
|
351
|
+
if (parentEl) {
|
|
352
|
+
parentEl.style.position = "relative";
|
|
353
|
+
}
|
|
354
|
+
}, []);
|
|
342
355
|
return /* @__PURE__ */(0, import_jsx_runtime7.jsx)(import_theme_ui17.Select, {
|
|
343
356
|
arrow: /* @__PURE__ */(0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, {
|
|
344
|
-
children: [
|
|
357
|
+
children: [leadingIcon && /* @__PURE__ */(0, import_jsx_runtime7.jsx)(import_theme_ui16.Text, {
|
|
345
358
|
sx: {
|
|
346
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
347
|
-
marginLeft: ({
|
|
348
|
-
space
|
|
349
|
-
}) => {
|
|
350
|
-
return space?.["2xl"] ? "-2xl" : "-28px";
|
|
351
|
-
},
|
|
352
359
|
alignSelf: "center",
|
|
353
360
|
pointerEvents: "none",
|
|
354
361
|
lineHeight: 0,
|
|
355
|
-
fontSize: "base"
|
|
362
|
+
fontSize: "base",
|
|
363
|
+
position: "absolute",
|
|
364
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
365
|
+
left: ({
|
|
366
|
+
space
|
|
367
|
+
}) => {
|
|
368
|
+
const leftSpaceValue = space?.["xl"] || "16px";
|
|
369
|
+
return leftSpaceValue;
|
|
370
|
+
}
|
|
356
371
|
},
|
|
357
372
|
children: /* @__PURE__ */(0, import_jsx_runtime7.jsx)(import_react_icons5.Icon, {
|
|
358
|
-
icon:
|
|
373
|
+
icon: leadingIcon
|
|
359
374
|
})
|
|
360
|
-
}),
|
|
361
|
-
className: "error-icon",
|
|
375
|
+
}), /* @__PURE__ */(0, import_jsx_runtime7.jsxs)(import_theme_ui8.Flex, {
|
|
362
376
|
sx: {
|
|
377
|
+
gap: "lg",
|
|
378
|
+
position: "absolute",
|
|
363
379
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
364
|
-
|
|
380
|
+
right: ({
|
|
365
381
|
space
|
|
366
382
|
}) => {
|
|
367
|
-
|
|
383
|
+
const xlSpace = space?.["xl"] || "16px";
|
|
384
|
+
return xlSpace;
|
|
368
385
|
},
|
|
369
386
|
alignSelf: "center",
|
|
370
|
-
pointerEvents: "none"
|
|
371
|
-
lineHeight: 0,
|
|
372
|
-
fontSize: "base"
|
|
387
|
+
pointerEvents: "none"
|
|
373
388
|
},
|
|
374
|
-
children: /* @__PURE__ */(0, import_jsx_runtime7.jsx)(
|
|
375
|
-
|
|
376
|
-
|
|
389
|
+
children: [(trailingIcon || hasError) && /* @__PURE__ */(0, import_jsx_runtime7.jsx)(import_theme_ui16.Text, {
|
|
390
|
+
className: hasError ? "error-icon" : "",
|
|
391
|
+
sx: {
|
|
392
|
+
alignSelf: "center",
|
|
393
|
+
pointerEvents: "none",
|
|
394
|
+
lineHeight: 0,
|
|
395
|
+
fontSize: "base"
|
|
396
|
+
},
|
|
397
|
+
children: /* @__PURE__ */(0, import_jsx_runtime7.jsx)(import_react_icons5.Icon, {
|
|
398
|
+
icon: hasError ? "warning-alt" : trailingIcon
|
|
399
|
+
})
|
|
400
|
+
}), arrow ?? /* @__PURE__ */(0, import_jsx_runtime7.jsx)(import_theme_ui16.Text, {
|
|
401
|
+
sx: {
|
|
402
|
+
lineHeight: 0,
|
|
403
|
+
fontSize: "base"
|
|
404
|
+
},
|
|
405
|
+
children: /* @__PURE__ */(0, import_jsx_runtime7.jsx)(import_react_icons5.Icon, {
|
|
406
|
+
icon: "picker-down"
|
|
407
|
+
})
|
|
408
|
+
})]
|
|
377
409
|
})]
|
|
378
410
|
}),
|
|
379
411
|
sx: {
|
|
@@ -381,9 +413,35 @@ var Select = React4.forwardRef(({
|
|
|
381
413
|
width: "100%",
|
|
382
414
|
paddingY: "lg",
|
|
383
415
|
paddingX: "xl",
|
|
416
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
417
|
+
paddingLeft: ({
|
|
418
|
+
space,
|
|
419
|
+
fontSizes
|
|
420
|
+
}) => {
|
|
421
|
+
const xlSpace = space?.["xl"] || "16px";
|
|
422
|
+
const iconSize = fontSizes?.["base"] || "16px";
|
|
423
|
+
const lgSpace = space?.["lg"] || "16px";
|
|
424
|
+
if (leadingIcon) {
|
|
425
|
+
return `calc(${xlSpace} + ${iconSize} + ${lgSpace})`;
|
|
426
|
+
}
|
|
427
|
+
return xlSpace;
|
|
428
|
+
},
|
|
429
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
430
|
+
paddingRight: ({
|
|
431
|
+
space,
|
|
432
|
+
fontSizes
|
|
433
|
+
}) => {
|
|
434
|
+
const xlSpace = space?.["xl"] || "16px";
|
|
435
|
+
const iconSize = fontSizes?.["base"] || "16px";
|
|
436
|
+
const lgSpace = space?.["lg"] || "16px";
|
|
437
|
+
if (trailingIcon || hasError) {
|
|
438
|
+
return `calc(${lgSpace} + ${iconSize} + ${lgSpace} + ${iconSize} + ${xlSpace})`;
|
|
439
|
+
}
|
|
440
|
+
return `calc(${lgSpace} + ${iconSize} + ${xlSpace})`;
|
|
441
|
+
},
|
|
384
442
|
...sx
|
|
385
443
|
},
|
|
386
|
-
ref,
|
|
444
|
+
ref: refEl,
|
|
387
445
|
...props
|
|
388
446
|
});
|
|
389
447
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/ui",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.4",
|
|
4
4
|
"description": "Primitive layout, typographic, and other components for styling applications.",
|
|
5
5
|
"author": "ttoss",
|
|
6
6
|
"contributors": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@theme-ui/match-media": "^0.16.0",
|
|
24
24
|
"theme-ui": "^0.16.0",
|
|
25
|
-
"@ttoss/theme": "^1.6.
|
|
25
|
+
"@ttoss/theme": "^1.6.3"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@emotion/react": "^11",
|
|
@@ -1,53 +1,100 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { Flex, Text } from '..';
|
|
3
|
+
import { Icon, IconType } from '@ttoss/react-icons';
|
|
4
|
+
import {
|
|
5
|
+
type SelectProps as SelectPropsUi,
|
|
6
|
+
Select as SelectUi,
|
|
7
|
+
} from 'theme-ui';
|
|
5
8
|
|
|
6
|
-
export
|
|
9
|
+
export type SelectProps = SelectPropsUi & {
|
|
10
|
+
leadingIcon?: IconType;
|
|
11
|
+
trailingIcon?: IconType;
|
|
12
|
+
};
|
|
7
13
|
|
|
8
14
|
export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|
9
|
-
({ arrow, sx, ...props }, ref) => {
|
|
15
|
+
({ arrow, sx, leadingIcon, trailingIcon, ...props }, ref) => {
|
|
16
|
+
const hasError = props['aria-invalid'] === 'true';
|
|
17
|
+
|
|
18
|
+
const refEl = React.useRef<HTMLSelectElement>({} as HTMLSelectElement);
|
|
19
|
+
|
|
20
|
+
React.useImperativeHandle(ref, () => {
|
|
21
|
+
return refEl.current;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
React.useEffect(() => {
|
|
25
|
+
const parentEl = refEl.current?.parentElement;
|
|
26
|
+
|
|
27
|
+
if (parentEl) {
|
|
28
|
+
parentEl.style.position = 'relative';
|
|
29
|
+
}
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
10
32
|
return (
|
|
11
33
|
<SelectUi
|
|
12
34
|
// https://theme-ui.com/components/select#custom-arrow-icon
|
|
13
35
|
arrow={
|
|
14
36
|
<>
|
|
15
|
-
{
|
|
37
|
+
{leadingIcon && (
|
|
16
38
|
<Text
|
|
17
39
|
sx={{
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
-
marginLeft: ({ space }: any) => {
|
|
20
|
-
return space?.['2xl'] ? '-2xl' : '-28px';
|
|
21
|
-
},
|
|
22
40
|
alignSelf: 'center',
|
|
23
41
|
pointerEvents: 'none',
|
|
24
42
|
lineHeight: 0,
|
|
25
43
|
fontSize: 'base',
|
|
26
|
-
|
|
27
|
-
>
|
|
28
|
-
<Icon icon="picker-down" />
|
|
29
|
-
</Text>
|
|
30
|
-
)}
|
|
31
|
-
|
|
32
|
-
{props['aria-invalid'] === 'true' && (
|
|
33
|
-
<Text
|
|
34
|
-
className="error-icon"
|
|
35
|
-
sx={{
|
|
44
|
+
position: 'absolute',
|
|
36
45
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
left: ({ space }: any) => {
|
|
47
|
+
const leftSpaceValue = space?.['xl'] || '16px';
|
|
48
|
+
|
|
49
|
+
return leftSpaceValue;
|
|
41
50
|
},
|
|
42
|
-
alignSelf: 'center',
|
|
43
|
-
pointerEvents: 'none',
|
|
44
|
-
lineHeight: 0,
|
|
45
|
-
fontSize: 'base',
|
|
46
51
|
}}
|
|
47
52
|
>
|
|
48
|
-
<Icon icon=
|
|
53
|
+
<Icon icon={leadingIcon} />
|
|
49
54
|
</Text>
|
|
50
55
|
)}
|
|
56
|
+
|
|
57
|
+
<Flex
|
|
58
|
+
sx={{
|
|
59
|
+
gap: 'lg',
|
|
60
|
+
position: 'absolute',
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
+
right: ({ space }: any) => {
|
|
63
|
+
const xlSpace = space?.['xl'] || '16px';
|
|
64
|
+
|
|
65
|
+
return xlSpace;
|
|
66
|
+
},
|
|
67
|
+
alignSelf: 'center',
|
|
68
|
+
pointerEvents: 'none',
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
{(trailingIcon || hasError) && (
|
|
72
|
+
<Text
|
|
73
|
+
className={hasError ? 'error-icon' : ''}
|
|
74
|
+
sx={{
|
|
75
|
+
alignSelf: 'center',
|
|
76
|
+
pointerEvents: 'none',
|
|
77
|
+
lineHeight: 0,
|
|
78
|
+
fontSize: 'base',
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
<Icon
|
|
82
|
+
icon={hasError ? 'warning-alt' : (trailingIcon as IconType)}
|
|
83
|
+
/>
|
|
84
|
+
</Text>
|
|
85
|
+
)}
|
|
86
|
+
|
|
87
|
+
{arrow ?? (
|
|
88
|
+
<Text
|
|
89
|
+
sx={{
|
|
90
|
+
lineHeight: 0,
|
|
91
|
+
fontSize: 'base',
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
<Icon icon="picker-down" />
|
|
95
|
+
</Text>
|
|
96
|
+
)}
|
|
97
|
+
</Flex>
|
|
51
98
|
</>
|
|
52
99
|
}
|
|
53
100
|
sx={{
|
|
@@ -55,9 +102,33 @@ export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|
|
55
102
|
width: '100%',
|
|
56
103
|
paddingY: 'lg',
|
|
57
104
|
paddingX: 'xl',
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
+
paddingLeft: ({ space, fontSizes }: any) => {
|
|
107
|
+
const xlSpace = space?.['xl'] || '16px';
|
|
108
|
+
const iconSize = fontSizes?.['base'] || '16px';
|
|
109
|
+
const lgSpace = space?.['lg'] || '16px';
|
|
110
|
+
|
|
111
|
+
if (leadingIcon) {
|
|
112
|
+
return `calc(${xlSpace} + ${iconSize} + ${lgSpace})`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return xlSpace;
|
|
116
|
+
},
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
|
+
paddingRight: ({ space, fontSizes }: any) => {
|
|
119
|
+
const xlSpace = space?.['xl'] || '16px';
|
|
120
|
+
const iconSize = fontSizes?.['base'] || '16px';
|
|
121
|
+
const lgSpace = space?.['lg'] || '16px';
|
|
122
|
+
|
|
123
|
+
if (trailingIcon || hasError) {
|
|
124
|
+
return `calc(${lgSpace} + ${iconSize} + ${lgSpace} + ${iconSize} + ${xlSpace})`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return `calc(${lgSpace} + ${iconSize} + ${xlSpace})`;
|
|
128
|
+
},
|
|
58
129
|
...sx,
|
|
59
130
|
}}
|
|
60
|
-
ref={
|
|
131
|
+
ref={refEl}
|
|
61
132
|
{...props}
|
|
62
133
|
/>
|
|
63
134
|
);
|