11import React from 'react' ;
2+ import deepmerge from 'deepmerge' ;
23import styled from 'styled-components' ;
34import css from '@styled-system/css' ;
45import { Input } from '../Input' ;
56import { Element } from '../Element' ;
67
7- // caret icon
8- const svg = color =>
9- `"data:image/svg+xml,%3Csvg width='8' height='24' viewBox='0 0 8 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.00006 17L1 13L7 13L4.00006 17Z' fill='%23${
10- ( color || '' ) . split ( '#' ) [ 1 ]
11- } '/%3E%3Cpath d='M3.99994 7L7 11H1L3.99994 7Z' fill='%23${
12- ( color || '' ) . split ( '#' ) [ 1 ]
13- } '/%3E%3C/svg%3E%0A"`;
8+ const variantStyles = {
9+ default : {
10+ // inherits from input
11+ } ,
12+ link : {
13+ border : 'none' ,
14+ backgroundColor : 'transparent' ,
15+ } ,
16+ } ;
1417
15- const SelectComponent = styled ( Input ) . attrs ( { as : 'select' } ) (
16- css ( {
17- appearance : 'none' ,
18- color : 'input.placeholderForeground' ,
19- transition : 'all ease' ,
20- transitionDuration : theme => theme . speeds [ 2 ] ,
18+ const variantCarets = {
19+ default : fill => `
20+ <svg width="8" height="24" viewBox="0 0 8 24" fill="none" xmlns="http://www.w3.org/2000/svg">
21+ <path d="M4 7L7 11H1L4 7Z" fill="${ fill } " />
22+ <path d="M4 17L1 13L7 13L4 17Z" fill="${ fill } " />
23+ </svg>
24+ ` ,
25+ link : fill => `
26+ <svg width="8" height="24" viewBox="0 0 8 24" fill="none" xmlns="http://www.w3.org/2000/svg">
27+ <path d="M4 15L1 11L7 11L4 15Z" fill="${ fill } " />
28+ </svg>
29+ ` ,
30+ } ;
31+ // <path d="M4 14L1 10H7L4 14Z" fill="${fill}" />
2132
22- paddingRight : 5 , // select has a caret icon on the right
33+ const getSVG = ( variant , color ) => {
34+ const fill = '#' + ( color || '' ) . split ( '#' ) [ 1 ] ;
2335
24- backgroundImage : theme =>
25- theme && `url(${ svg ( theme . colors . input . placeholderForeground ) } )` ,
26- backgroundPosition : 'calc(100% - 8px) center' ,
27- backgroundRepeat : 'no-repeat' ,
36+ // caret icon
37+ const svgString = variantCarets [ variant ] ( fill ) ;
38+
39+ const header = 'data:image/svg+xml,' ;
40+ const encoded = encodeURIComponent ( svgString )
41+ . replace ( / ' / g, '%27' )
42+ . replace ( / " / g, '%22' ) ;
43+ return header + encoded ;
44+ } ;
45+
46+ const SelectComponent = styled ( Input ) . attrs ( { as : 'select' } ) < {
47+ variant ?: string ;
48+ } > ( ( { variant = 'default' } ) =>
49+ css (
50+ deepmerge ( variantStyles [ variant ] , {
51+ appearance : 'none' ,
52+ color : 'input.placeholderForeground' ,
53+ transition : 'all ease' ,
54+ transitionDuration : theme => theme . speeds [ 2 ] ,
55+
56+ paddingRight : 5 , // select has a caret icon on the right
2857
29- ':hover, :focus' : {
30- color : 'input.foreground' ,
3158 backgroundImage : theme =>
32- theme && `url(${ svg ( theme . colors . input . foreground ) } )` ,
33- } ,
34- } )
59+ theme &&
60+ `url(${ getSVG ( variant , theme . colors . input . placeholderForeground ) } )` ,
61+ backgroundPosition : 'calc(100% - 8px) center' ,
62+ backgroundRepeat : 'no-repeat' ,
63+
64+ ':hover, :focus' : {
65+ color : 'input.foreground' ,
66+ backgroundImage : theme =>
67+ theme && `url(${ getSVG ( variant , theme . colors . input . foreground ) } )` ,
68+ } ,
69+ } )
70+ )
3571) ;
3672
37- const SelectWithIcon = styled ( Element ) (
73+ const SelectWithIcon = styled ( Element ) < {
74+ variant ?: string ;
75+ } > ( ( { variant = 'default' } ) =>
3876 css ( {
3977 position : 'relative' ,
4078 color : 'input.placeholderForeground' ,
@@ -57,7 +95,8 @@ const SelectWithIcon = styled(Element)(
5795 color : 'input.foreground' ,
5896 select : {
5997 color : 'input.foreground' ,
60- backgroundImage : theme => `url(${ svg ( theme . colors . input . foreground ) } )` ,
98+ backgroundImage : theme =>
99+ `url(${ getSVG ( variant , theme . colors . input . foreground ) } )` ,
61100 } ,
62101 } ,
63102 } )
@@ -71,25 +110,31 @@ interface ISelectProps {
71110 onChange ?: any ;
72111 value ?: string | number ;
73112 defaultValue ?: string | number ;
113+ variant ?: string ;
74114}
75115
76116export const Select = ( {
77117 icon = null ,
78118 placeholder = null ,
79119 ...props
80120} : ISelectProps ) => {
81- const PrefixIcon = icon || React . Fragment ;
82- const SelectContainer = icon ? SelectWithIcon : React . Fragment ;
121+ const PrefixIcon = icon ;
83122
84- return (
85- < >
86- < SelectContainer >
123+ if ( icon )
124+ return (
125+ < SelectWithIcon variant = { props . variant } >
87126 < PrefixIcon />
88127 < SelectComponent { ...props } >
89128 { placeholder ? < option value = "" > { placeholder } </ option > : null }
90129 { props . children }
91130 </ SelectComponent >
92- </ SelectContainer >
93- </ >
131+ </ SelectWithIcon >
132+ ) ;
133+
134+ return (
135+ < SelectComponent { ...props } >
136+ { placeholder ? < option value = "" > { placeholder } </ option > : null }
137+ { props . children }
138+ </ SelectComponent >
94139 ) ;
95140} ;
0 commit comments