@workday/canvas-kit-preview-react 7.0.0-alpha.95-next.21 → 7.0.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/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +1 -0
- package/dist/commonjs/pill/index.d.ts +3 -0
- package/dist/commonjs/pill/index.d.ts.map +1 -0
- package/dist/commonjs/pill/index.js +14 -0
- package/dist/commonjs/pill/lib/Pill.d.ts +58 -0
- package/dist/commonjs/pill/lib/Pill.d.ts.map +1 -0
- package/dist/commonjs/pill/lib/Pill.js +164 -0
- package/dist/commonjs/pill/lib/PillAvatar.d.ts +11 -0
- package/dist/commonjs/pill/lib/PillAvatar.d.ts.map +1 -0
- package/dist/commonjs/pill/lib/PillAvatar.js +29 -0
- package/dist/commonjs/pill/lib/PillCount.d.ts +5 -0
- package/dist/commonjs/pill/lib/PillCount.d.ts.map +1 -0
- package/dist/commonjs/pill/lib/PillCount.js +45 -0
- package/dist/commonjs/pill/lib/PillIcon.d.ts +17 -0
- package/dist/commonjs/pill/lib/PillIcon.d.ts.map +1 -0
- package/dist/commonjs/pill/lib/PillIcon.js +40 -0
- package/dist/commonjs/pill/lib/PillIconButton.d.ts +17 -0
- package/dist/commonjs/pill/lib/PillIconButton.d.ts.map +1 -0
- package/dist/commonjs/pill/lib/PillIconButton.js +88 -0
- package/dist/commonjs/pill/lib/PillLabel.d.ts +13 -0
- package/dist/commonjs/pill/lib/PillLabel.d.ts.map +1 -0
- package/dist/commonjs/pill/lib/PillLabel.js +47 -0
- package/dist/commonjs/pill/lib/usePillModel.d.ts +58 -0
- package/dist/commonjs/pill/lib/usePillModel.d.ts.map +1 -0
- package/dist/commonjs/pill/lib/usePillModel.js +31 -0
- package/dist/commonjs/select/index.d.ts +1 -1
- package/dist/commonjs/select/index.d.ts.map +1 -1
- package/dist/commonjs/select/lib/SelectBase.d.ts +20 -1
- package/dist/commonjs/select/lib/SelectBase.d.ts.map +1 -1
- package/dist/commonjs/select/lib/SelectBase.js +6 -4
- package/dist/es6/index.d.ts +1 -0
- package/dist/es6/index.d.ts.map +1 -1
- package/dist/es6/index.js +1 -0
- package/dist/es6/pill/index.d.ts +3 -0
- package/dist/es6/pill/index.d.ts.map +1 -0
- package/dist/es6/pill/index.js +2 -0
- package/dist/es6/pill/lib/Pill.d.ts +58 -0
- package/dist/es6/pill/lib/Pill.d.ts.map +1 -0
- package/dist/es6/pill/lib/Pill.js +158 -0
- package/dist/es6/pill/lib/PillAvatar.d.ts +12 -0
- package/dist/es6/pill/lib/PillAvatar.d.ts.map +1 -0
- package/dist/es6/pill/lib/PillAvatar.js +23 -0
- package/dist/es6/pill/lib/PillCount.d.ts +5 -0
- package/dist/es6/pill/lib/PillCount.d.ts.map +1 -0
- package/dist/es6/pill/lib/PillCount.js +39 -0
- package/dist/es6/pill/lib/PillIcon.d.ts +18 -0
- package/dist/es6/pill/lib/PillIcon.d.ts.map +1 -0
- package/dist/es6/pill/lib/PillIcon.js +34 -0
- package/dist/es6/pill/lib/PillIconButton.d.ts +18 -0
- package/dist/es6/pill/lib/PillIconButton.d.ts.map +1 -0
- package/dist/es6/pill/lib/PillIconButton.js +82 -0
- package/dist/es6/pill/lib/PillLabel.d.ts +14 -0
- package/dist/es6/pill/lib/PillLabel.d.ts.map +1 -0
- package/dist/es6/pill/lib/PillLabel.js +41 -0
- package/dist/es6/pill/lib/usePillModel.d.ts +58 -0
- package/dist/es6/pill/lib/usePillModel.d.ts.map +1 -0
- package/dist/es6/pill/lib/usePillModel.js +28 -0
- package/dist/es6/select/index.d.ts +1 -1
- package/dist/es6/select/index.d.ts.map +1 -1
- package/dist/es6/select/lib/SelectBase.d.ts +20 -1
- package/dist/es6/select/lib/SelectBase.d.ts.map +1 -1
- package/dist/es6/select/lib/SelectBase.js +6 -4
- package/index.ts +1 -0
- package/package.json +4 -4
- package/pill/LICENSE +52 -0
- package/pill/README.md +5 -0
- package/pill/index.ts +2 -0
- package/pill/lib/Pill.tsx +218 -0
- package/pill/lib/PillAvatar.tsx +26 -0
- package/pill/lib/PillCount.tsx +39 -0
- package/pill/lib/PillIcon.tsx +32 -0
- package/pill/lib/PillIconButton.tsx +96 -0
- package/pill/lib/PillLabel.tsx +35 -0
- package/pill/lib/usePillModel.tsx +21 -0
- package/pill/package.json +5 -0
- package/select/index.ts +6 -1
- package/select/lib/SelectBase.tsx +27 -3
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {CSSObject} from '@emotion/react';
|
|
3
|
+
|
|
4
|
+
import {BaseButton} from '@workday/canvas-kit-react/button';
|
|
5
|
+
import {
|
|
6
|
+
createContainer,
|
|
7
|
+
focusRing,
|
|
8
|
+
mouseFocusBehavior,
|
|
9
|
+
styled,
|
|
10
|
+
StyledType,
|
|
11
|
+
} from '@workday/canvas-kit-react/common';
|
|
12
|
+
import {BoxProps, boxStyleFn, HStack, Stack} from '@workday/canvas-kit-react/layout';
|
|
13
|
+
import {borderRadius, colors, space, type} from '@workday/canvas-kit-react/tokens';
|
|
14
|
+
|
|
15
|
+
import {usePillModel} from './usePillModel';
|
|
16
|
+
|
|
17
|
+
import {PillIcon} from './PillIcon';
|
|
18
|
+
import {PillIconButton} from './PillIconButton';
|
|
19
|
+
import {PillCount} from './PillCount';
|
|
20
|
+
import {PillAvatar} from './PillAvatar';
|
|
21
|
+
import {PillLabel} from './PillLabel';
|
|
22
|
+
|
|
23
|
+
export interface PillProps extends BoxProps {
|
|
24
|
+
/**
|
|
25
|
+
* Defines what kind of pill to render stylistically and its interaction states
|
|
26
|
+
* @default 'default'
|
|
27
|
+
*/
|
|
28
|
+
variant?: 'default' | 'readOnly' | 'removable';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const getButtonPillColors = () => {
|
|
32
|
+
return {
|
|
33
|
+
default: {
|
|
34
|
+
background: colors.soap300,
|
|
35
|
+
icon: colors.licorice200,
|
|
36
|
+
label: colors.blackPepper400,
|
|
37
|
+
border: colors.licorice200,
|
|
38
|
+
},
|
|
39
|
+
hover: {
|
|
40
|
+
icon: colors.licorice500,
|
|
41
|
+
background: colors.soap400,
|
|
42
|
+
border: colors.licorice400,
|
|
43
|
+
},
|
|
44
|
+
active: {
|
|
45
|
+
icon: colors.licorice500,
|
|
46
|
+
background: colors.soap500,
|
|
47
|
+
border: colors.licorice500,
|
|
48
|
+
},
|
|
49
|
+
focus: {
|
|
50
|
+
icon: colors.licorice500,
|
|
51
|
+
background: colors.soap300,
|
|
52
|
+
border: colors.blueberry400,
|
|
53
|
+
focusRing: focusRing({
|
|
54
|
+
width: 0,
|
|
55
|
+
inset: 'inner',
|
|
56
|
+
innerColor: colors.blueberry400,
|
|
57
|
+
outerColor: colors.blueberry400,
|
|
58
|
+
separation: 1,
|
|
59
|
+
}),
|
|
60
|
+
},
|
|
61
|
+
disabled: {
|
|
62
|
+
icon: colors.licorice100,
|
|
63
|
+
label: colors.licorice100,
|
|
64
|
+
background: colors.soap100,
|
|
65
|
+
border: colors.licorice100,
|
|
66
|
+
opacity: '1',
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const getRemovablePillColors = (disabled?: boolean) => {
|
|
72
|
+
return {
|
|
73
|
+
default: {
|
|
74
|
+
background: disabled ? colors.soap100 : colors.soap300,
|
|
75
|
+
icon: disabled ? colors.licorice100 : colors.licorice200,
|
|
76
|
+
label: disabled ? colors.licorice100 : colors.blackPepper400,
|
|
77
|
+
border: disabled ? colors.licorice100 : colors.licorice200,
|
|
78
|
+
},
|
|
79
|
+
hover: {
|
|
80
|
+
icon: disabled ? colors.licorice100 : colors.licorice500,
|
|
81
|
+
background: disabled ? colors.soap100 : colors.soap300,
|
|
82
|
+
border: disabled ? colors.licorice100 : colors.licorice200,
|
|
83
|
+
label: disabled ? colors.licorice100 : colors.blackPepper400,
|
|
84
|
+
},
|
|
85
|
+
active: {
|
|
86
|
+
icon: disabled ? colors.licorice100 : colors.licorice500,
|
|
87
|
+
background: disabled ? colors.soap100 : colors.soap500,
|
|
88
|
+
border: disabled ? colors.licorice100 : colors.licorice500,
|
|
89
|
+
label: disabled ? colors.licorice100 : colors.blackPepper400,
|
|
90
|
+
},
|
|
91
|
+
focus: {
|
|
92
|
+
icon: colors.licorice200,
|
|
93
|
+
background: colors.soap300,
|
|
94
|
+
label: colors.blackPepper400,
|
|
95
|
+
focusRing: focusRing({
|
|
96
|
+
width: 0,
|
|
97
|
+
innerColor: 'transparent',
|
|
98
|
+
outerColor: 'transparent',
|
|
99
|
+
}),
|
|
100
|
+
},
|
|
101
|
+
disabled: {},
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const pillBaseStyles: CSSObject = {
|
|
106
|
+
display: 'inline-flex',
|
|
107
|
+
alignItems: 'center',
|
|
108
|
+
borderRadius: borderRadius.m,
|
|
109
|
+
flexShrink: 0,
|
|
110
|
+
...type.levels.subtext.large,
|
|
111
|
+
color: colors.blackPepper400,
|
|
112
|
+
boxShadow: 'none',
|
|
113
|
+
outline: 'none',
|
|
114
|
+
fontWeight: type.properties.fontWeights.medium,
|
|
115
|
+
WebkitFontSmoothing: 'antialiased',
|
|
116
|
+
MozOsxFontSmoothing: 'grayscale',
|
|
117
|
+
width: 'fit-content',
|
|
118
|
+
padding: `2px ${space.xxs}`,
|
|
119
|
+
height: space.m,
|
|
120
|
+
position: 'relative',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const StyledBasePill = styled(BaseButton.as('button'))<StyledType & PillProps>(
|
|
124
|
+
{
|
|
125
|
+
...pillBaseStyles,
|
|
126
|
+
'&:focus': {
|
|
127
|
+
borderColor: colors.blueberry400,
|
|
128
|
+
'span[data-count="ck-pill-count"]': {
|
|
129
|
+
borderTop: `1px solid ${colors.blueberry400}`,
|
|
130
|
+
borderBottom: `1px solid ${colors.blueberry400}`,
|
|
131
|
+
borderRight: `1px solid ${colors.blueberry400}`,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
'&:active, &:active:hover, &:active:focus': {
|
|
135
|
+
'span[data-count="ck-pill-count"]': {
|
|
136
|
+
backgroundColor: colors.soap600,
|
|
137
|
+
border: 'none',
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
...mouseFocusBehavior({
|
|
142
|
+
'&:focus': {
|
|
143
|
+
'span[data-count="ck-pill-count"]': {
|
|
144
|
+
border: 'none',
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
}),
|
|
148
|
+
},
|
|
149
|
+
boxStyleFn
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const StyledNonInteractivePill = styled(StyledBasePill)({
|
|
153
|
+
cursor: 'default',
|
|
154
|
+
overflow: 'revert', // override BaseButton overflow styles so the click target exists outside the pill for removable
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
export const Pill = createContainer('button')({
|
|
158
|
+
modelHook: usePillModel,
|
|
159
|
+
subComponents: {
|
|
160
|
+
Icon: PillIcon,
|
|
161
|
+
Avatar: PillAvatar,
|
|
162
|
+
Count: PillCount,
|
|
163
|
+
Label: PillLabel,
|
|
164
|
+
IconButton: PillIconButton,
|
|
165
|
+
},
|
|
166
|
+
})<PillProps>(({variant = 'default', maxWidth, ...elemProps}, Element, model) => {
|
|
167
|
+
return (
|
|
168
|
+
<>
|
|
169
|
+
{variant === 'readOnly' && (
|
|
170
|
+
<StyledNonInteractivePill
|
|
171
|
+
maxWidth={model.state.maxWidth}
|
|
172
|
+
as={Element !== 'button' ? Element : 'span'}
|
|
173
|
+
border={`1px solid ${colors.licorice200}`}
|
|
174
|
+
{...elemProps}
|
|
175
|
+
>
|
|
176
|
+
<PillLabel>{elemProps.children}</PillLabel>
|
|
177
|
+
</StyledNonInteractivePill>
|
|
178
|
+
)}
|
|
179
|
+
{variant === 'default' && (
|
|
180
|
+
<StyledBasePill
|
|
181
|
+
colors={getButtonPillColors()}
|
|
182
|
+
as={Element}
|
|
183
|
+
{...elemProps}
|
|
184
|
+
disabled={model.state.disabled}
|
|
185
|
+
>
|
|
186
|
+
<HStack spacing="xxxs" display="inline-flex" alignItems="center">
|
|
187
|
+
{React.Children.map(elemProps.children, (child, index) => {
|
|
188
|
+
if (typeof child === 'string') {
|
|
189
|
+
return <PillLabel key={index}>{child}</PillLabel>;
|
|
190
|
+
}
|
|
191
|
+
return (
|
|
192
|
+
<Stack.Item key={index} display="inline-flex">
|
|
193
|
+
{child}
|
|
194
|
+
</Stack.Item>
|
|
195
|
+
);
|
|
196
|
+
})}
|
|
197
|
+
</HStack>
|
|
198
|
+
</StyledBasePill>
|
|
199
|
+
)}
|
|
200
|
+
{variant === 'removable' && (
|
|
201
|
+
<StyledNonInteractivePill
|
|
202
|
+
colors={getRemovablePillColors(model.state.disabled)}
|
|
203
|
+
as={Element !== 'button' ? Element : 'span'}
|
|
204
|
+
{...elemProps}
|
|
205
|
+
>
|
|
206
|
+
<HStack spacing="xxxs" display="inline-flex" alignItems="center" justifyContent="center">
|
|
207
|
+
{React.Children.map(elemProps.children, (child, index) => {
|
|
208
|
+
if (typeof child === 'string') {
|
|
209
|
+
return <PillLabel key={index}>{child}</PillLabel>;
|
|
210
|
+
}
|
|
211
|
+
return <Stack.Item key={index}>{child}</Stack.Item>;
|
|
212
|
+
})}
|
|
213
|
+
</HStack>
|
|
214
|
+
</StyledNonInteractivePill>
|
|
215
|
+
)}
|
|
216
|
+
</>
|
|
217
|
+
);
|
|
218
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {createSubcomponent} from '@workday/canvas-kit-react/common';
|
|
4
|
+
import {Avatar, AvatarProps} from '@workday/canvas-kit-react/avatar';
|
|
5
|
+
import {usePillModel} from './usePillModel';
|
|
6
|
+
|
|
7
|
+
export interface PillAvatarProps extends AvatarProps {}
|
|
8
|
+
|
|
9
|
+
// When the component is created, it needs to be a button element to match AvatarProps.
|
|
10
|
+
// Once Avatar becomes a `createComponent` we can default the element type to a `div`
|
|
11
|
+
// and the types should be properly extracted
|
|
12
|
+
export const PillAvatar = createSubcomponent('button')({
|
|
13
|
+
modelHook: usePillModel,
|
|
14
|
+
})<PillAvatarProps>((elemProps, Element, model) => {
|
|
15
|
+
return (
|
|
16
|
+
<Avatar
|
|
17
|
+
style={{opacity: model.state.disabled ? '.7' : '1'}}
|
|
18
|
+
as="div"
|
|
19
|
+
size={18}
|
|
20
|
+
{...elemProps}
|
|
21
|
+
disabled={model.state.disabled}
|
|
22
|
+
>
|
|
23
|
+
{elemProps.children}
|
|
24
|
+
</Avatar>
|
|
25
|
+
);
|
|
26
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {createComponent, styled, StyledType} from '@workday/canvas-kit-react/common';
|
|
4
|
+
import {Flex, FlexProps} from '@workday/canvas-kit-react/layout';
|
|
5
|
+
import {borderRadius, colors, space} from '@workday/canvas-kit-react/tokens';
|
|
6
|
+
|
|
7
|
+
export interface PillCountProps extends FlexProps {}
|
|
8
|
+
|
|
9
|
+
const StyledCountContainer = styled(Flex.as('span'))<StyledType>({
|
|
10
|
+
borderTopLeftRadius: borderRadius.zero,
|
|
11
|
+
borderTopRightRadius: borderRadius.m,
|
|
12
|
+
borderBottomLeftRadius: borderRadius.zero,
|
|
13
|
+
borderBottomRightRadius: borderRadius.m,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const PillCount = createComponent('span')({
|
|
17
|
+
displayName: 'Pill.Avatar',
|
|
18
|
+
Component: ({children, ...elemProps}: PillCountProps, ref, Element) => {
|
|
19
|
+
return (
|
|
20
|
+
<StyledCountContainer
|
|
21
|
+
display="inline-flex"
|
|
22
|
+
alignItems="center"
|
|
23
|
+
justifyContent="center"
|
|
24
|
+
as={Element}
|
|
25
|
+
height={22}
|
|
26
|
+
minWidth={22}
|
|
27
|
+
padding={`0 ${space.xxxs}`}
|
|
28
|
+
marginInlineEnd={`-${space.xxs}`} // Remove padding from HStack on the right side
|
|
29
|
+
marginInlineStart={`${space.xxxs}`}
|
|
30
|
+
backgroundColor={colors.soap500}
|
|
31
|
+
data-count="ck-pill-count"
|
|
32
|
+
ref={ref}
|
|
33
|
+
{...elemProps}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</StyledCountContainer>
|
|
37
|
+
);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {createSubcomponent} from '@workday/canvas-kit-react/common';
|
|
4
|
+
|
|
5
|
+
import {SystemIcon, SystemIconProps} from '@workday/canvas-kit-react/icon';
|
|
6
|
+
import {usePillModel} from './usePillModel';
|
|
7
|
+
import {plusIcon} from '@workday/canvas-system-icons-web';
|
|
8
|
+
import {CanvasSystemIcon} from '@workday/design-assets-types';
|
|
9
|
+
import {space} from '@workday/canvas-kit-react/tokens';
|
|
10
|
+
|
|
11
|
+
export interface PillIconProps extends Omit<SystemIconProps, 'icon'> {
|
|
12
|
+
/**
|
|
13
|
+
* The system icon rendered by the component
|
|
14
|
+
* @default `plusIcon`
|
|
15
|
+
*/
|
|
16
|
+
icon?: CanvasSystemIcon;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const PillIcon = createSubcomponent('span')({
|
|
20
|
+
modelHook: usePillModel,
|
|
21
|
+
})<PillIconProps>(({size, icon, ...elemProps}, Element) => {
|
|
22
|
+
return (
|
|
23
|
+
<SystemIcon
|
|
24
|
+
marginInlineStart={`-${space.xxxs}`} // remove padding on the left from HStack
|
|
25
|
+
display="flex"
|
|
26
|
+
as={Element}
|
|
27
|
+
size={20}
|
|
28
|
+
icon={icon || plusIcon}
|
|
29
|
+
{...elemProps}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {focusRing, styled, StyledType, createSubcomponent} from '@workday/canvas-kit-react/common';
|
|
4
|
+
|
|
5
|
+
import {SystemIcon, SystemIconProps} from '@workday/canvas-kit-react/icon';
|
|
6
|
+
import {usePillModel} from './usePillModel';
|
|
7
|
+
import {xSmallIcon} from '@workday/canvas-system-icons-web';
|
|
8
|
+
import {CanvasSystemIcon} from '@workday/design-assets-types';
|
|
9
|
+
import {borderRadius, colors, space} from '@workday/canvas-kit-react/tokens';
|
|
10
|
+
import {BaseButton} from '@workday/canvas-kit-react/button';
|
|
11
|
+
|
|
12
|
+
export interface PillIconButtonProps extends Omit<SystemIconProps, 'icon'> {
|
|
13
|
+
/**
|
|
14
|
+
* The system icon rendered by the button
|
|
15
|
+
* @default `xSmallIcon`
|
|
16
|
+
*/
|
|
17
|
+
icon?: CanvasSystemIcon;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getIconColors = () => {
|
|
21
|
+
return {
|
|
22
|
+
default: {
|
|
23
|
+
icon: colors.licorice200,
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
hover: {
|
|
27
|
+
icon: colors.licorice500,
|
|
28
|
+
},
|
|
29
|
+
active: {
|
|
30
|
+
icon: colors.licorice500,
|
|
31
|
+
},
|
|
32
|
+
focus: {
|
|
33
|
+
icon: colors.licorice500,
|
|
34
|
+
|
|
35
|
+
focusRing: focusRing({
|
|
36
|
+
width: 0,
|
|
37
|
+
innerColor: 'transparent',
|
|
38
|
+
outerColor: 'transparent',
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
disabled: {
|
|
42
|
+
icon: colors.licorice100,
|
|
43
|
+
opacity: '1',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const StyledFocusTarget = styled('span')<StyledType & PillIconButtonProps>({
|
|
49
|
+
height: 20,
|
|
50
|
+
position: 'absolute',
|
|
51
|
+
right: '5px',
|
|
52
|
+
left: space.xxxs,
|
|
53
|
+
margin: 0,
|
|
54
|
+
borderRadius: borderRadius.m,
|
|
55
|
+
'&:focus': {
|
|
56
|
+
outline: 'none',
|
|
57
|
+
...focusRing({
|
|
58
|
+
outerColor: colors.blueberry400,
|
|
59
|
+
innerColor: 'transparent',
|
|
60
|
+
separation: 0,
|
|
61
|
+
width: 2,
|
|
62
|
+
inset: 'inner',
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const StyledIconButton = styled(BaseButton)<StyledType & PillIconButtonProps>({
|
|
68
|
+
marginInlineEnd: '-14px !important', // visually pull in the pill to the right size
|
|
69
|
+
paddingInlineEnd: space.xxxs, // add 4px padding outside the pill for click target
|
|
70
|
+
marginInlineStart: `-${space.xxs} !important`, // visually create space between label and the button
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const PillIconButton = createSubcomponent('button')({
|
|
74
|
+
modelHook: usePillModel,
|
|
75
|
+
})<PillIconButtonProps>(
|
|
76
|
+
({size, icon = xSmallIcon, maxWidth, children, ...elemProps}, Element, model) => {
|
|
77
|
+
return (
|
|
78
|
+
<StyledIconButton
|
|
79
|
+
borderRadius="s"
|
|
80
|
+
height={space.l}
|
|
81
|
+
width={space.l}
|
|
82
|
+
padding="zero"
|
|
83
|
+
disabled={model.state.disabled}
|
|
84
|
+
colors={getIconColors()}
|
|
85
|
+
tabIndex={-1}
|
|
86
|
+
as={Element}
|
|
87
|
+
position="relative"
|
|
88
|
+
{...elemProps}
|
|
89
|
+
>
|
|
90
|
+
{/* We made the clickable element in this case the button larger, and have the span be the visible focus area */}
|
|
91
|
+
<StyledFocusTarget aria-hidden="true" tabIndex={model.state.disabled ? -1 : 0} />
|
|
92
|
+
<SystemIcon icon={icon} size={24} />
|
|
93
|
+
</StyledIconButton>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {createSubcomponent, styled, StyledType} from '@workday/canvas-kit-react/common';
|
|
4
|
+
import {Box, BoxProps} from '@workday/canvas-kit-react/layout';
|
|
5
|
+
import {OverflowTooltip, OverflowTooltipProps} from '@workday/canvas-kit-react/tooltip';
|
|
6
|
+
|
|
7
|
+
import {usePillModel} from './usePillModel';
|
|
8
|
+
import {colors} from '@workday/canvas-kit-react/tokens';
|
|
9
|
+
|
|
10
|
+
export interface PillLabelProps extends BoxProps {
|
|
11
|
+
tooltipProps?: Omit<OverflowTooltipProps, 'children'>;
|
|
12
|
+
}
|
|
13
|
+
const StyledLabelContainer = styled(Box.as('span'))<StyledType>({
|
|
14
|
+
whiteSpace: 'nowrap',
|
|
15
|
+
overflow: 'hidden',
|
|
16
|
+
textOverflow: 'ellipsis',
|
|
17
|
+
display: 'block',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const PillLabel = createSubcomponent('span')({
|
|
21
|
+
modelHook: usePillModel,
|
|
22
|
+
})<PillLabelProps>(({tooltipProps, ...elemProps}, Element, model) => {
|
|
23
|
+
return (
|
|
24
|
+
<OverflowTooltip {...tooltipProps}>
|
|
25
|
+
<StyledLabelContainer
|
|
26
|
+
color={model.state.disabled ? colors.licorice100 : 'inherit'}
|
|
27
|
+
maxWidth={model.state.maxWidth}
|
|
28
|
+
as={Element}
|
|
29
|
+
{...elemProps}
|
|
30
|
+
>
|
|
31
|
+
{elemProps.children}
|
|
32
|
+
</StyledLabelContainer>
|
|
33
|
+
</OverflowTooltip>
|
|
34
|
+
);
|
|
35
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {createModelHook} from '@workday/canvas-kit-react/common';
|
|
2
|
+
|
|
3
|
+
export const usePillModel = createModelHook({
|
|
4
|
+
defaultConfig: {
|
|
5
|
+
/**
|
|
6
|
+
* Determines the max width of the pill. If the pill text is longer than the max width,
|
|
7
|
+
* text will be truncated and a tooltip will show the rest of the content when hovered over
|
|
8
|
+
*/
|
|
9
|
+
maxWidth: 200 as string | number,
|
|
10
|
+
/**
|
|
11
|
+
* Use to disable a pill.
|
|
12
|
+
*/
|
|
13
|
+
disabled: false,
|
|
14
|
+
},
|
|
15
|
+
})(config => {
|
|
16
|
+
const state = {
|
|
17
|
+
...config,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return {state, events: {}};
|
|
21
|
+
});
|
package/select/index.ts
CHANGED
|
@@ -4,4 +4,9 @@ export default Select;
|
|
|
4
4
|
export {Select};
|
|
5
5
|
export * from './lib/Select';
|
|
6
6
|
|
|
7
|
-
export {
|
|
7
|
+
export {
|
|
8
|
+
Option,
|
|
9
|
+
RenderableOption,
|
|
10
|
+
RenderOptionFunction,
|
|
11
|
+
RenderSelectedFunction,
|
|
12
|
+
} from './lib/SelectBase';
|
|
@@ -49,6 +49,10 @@ export interface NormalizedOption extends Option {
|
|
|
49
49
|
label: string;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
export interface RenderSelectedFunction {
|
|
53
|
+
(option: NormalizedOption): React.ReactNode;
|
|
54
|
+
}
|
|
55
|
+
|
|
52
56
|
export interface RenderableOption extends NormalizedOption {
|
|
53
57
|
focused: boolean;
|
|
54
58
|
selected: boolean;
|
|
@@ -86,6 +90,22 @@ export interface CoreSelectBaseProps
|
|
|
86
90
|
* @default defaultRenderOption
|
|
87
91
|
*/
|
|
88
92
|
renderOption?: RenderOptionFunction;
|
|
93
|
+
/**
|
|
94
|
+
* The function called to render the selected option.
|
|
95
|
+
*
|
|
96
|
+
* The `option` argument passed to the function is an object which contains the following:
|
|
97
|
+
*
|
|
98
|
+
* * `data: object` (data object carried over from the corresponding option originally passed into the component)
|
|
99
|
+
* * `disabled: boolean`
|
|
100
|
+
* * `id: string`
|
|
101
|
+
* * `label: string`
|
|
102
|
+
* * `value: string`
|
|
103
|
+
*
|
|
104
|
+
* If you omit the `renderSelected` prop, each option will be rendered using a `defaultRenderSelected` function provided by the component.
|
|
105
|
+
*
|
|
106
|
+
* @default defaultRenderSelected
|
|
107
|
+
*/
|
|
108
|
+
renderSelected?: RenderSelectedFunction;
|
|
89
109
|
/**
|
|
90
110
|
* The value of the Select.
|
|
91
111
|
*/
|
|
@@ -261,7 +281,11 @@ const SelectWrapper = styled('div')<Pick<SelectBaseProps, 'grow' | 'disabled'>>(
|
|
|
261
281
|
);
|
|
262
282
|
|
|
263
283
|
const defaultRenderOption: RenderOptionFunction = option => {
|
|
264
|
-
return <div>{option
|
|
284
|
+
return <div>{defaultRenderSelected(option)}</div>;
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const defaultRenderSelected: RenderSelectedFunction = option => {
|
|
288
|
+
return option.label;
|
|
265
289
|
};
|
|
266
290
|
|
|
267
291
|
const SelectBase = ({
|
|
@@ -284,6 +308,7 @@ const SelectBase = ({
|
|
|
284
308
|
onOptionSelection,
|
|
285
309
|
options,
|
|
286
310
|
renderOption = defaultRenderOption,
|
|
311
|
+
renderSelected = defaultRenderSelected,
|
|
287
312
|
required,
|
|
288
313
|
shouldMenuAutoFlip = true,
|
|
289
314
|
shouldMenuAutoFocus = true,
|
|
@@ -393,7 +418,6 @@ const SelectBase = ({
|
|
|
393
418
|
// Do a bit of error-checking in case options weren't provided
|
|
394
419
|
const hasOptions = options.length > 0;
|
|
395
420
|
const selectedOption = hasOptions ? options[getCorrectedIndexByValue(options, value)] : null;
|
|
396
|
-
const selectedOptionLabel = selectedOption ? selectedOption.label : '';
|
|
397
421
|
const selectedOptionValue = selectedOption ? selectedOption.value : '';
|
|
398
422
|
|
|
399
423
|
return (
|
|
@@ -419,7 +443,7 @@ const SelectBase = ({
|
|
|
419
443
|
value={selectedOptionValue}
|
|
420
444
|
{...elemProps}
|
|
421
445
|
>
|
|
422
|
-
{
|
|
446
|
+
{!!selectedOption && renderSelected(selectedOption)}
|
|
423
447
|
</SelectButton>
|
|
424
448
|
<SelectInput onChange={onChange} ref={inputRef} type="text" value={selectedOptionValue} />
|
|
425
449
|
{hasOptions && menuVisibility !== 'closed' && (
|