@mrshmllw/smores-react 16.3.1 → 16.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.
@@ -1,24 +1,28 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef, } from 'react';
3
3
  import styled, { css } from 'styled-components';
4
- import { IconContainer as CommonIconContainer } from '../sharedStyles/shared.styles';
5
4
  import { Box } from '../Box';
6
5
  import { Icon as IconComponent } from '../Icon';
7
6
  import { Loader } from '../Loader';
8
7
  import { focusOutlineStyle } from '../utils/focusOutline';
9
8
  export const Button = forwardRef((props, ref) => {
10
9
  const { children, id, className = '', disabled = false, handleClick, loading = false, primary = false, secondary = false, tertiary = false, fallbackStyle = false, textBtn = false, smallButton = false, icon, iconComponent, trailingIcon = false, forcedWidth = '', form, type, ...otherProps } = props;
11
- const iconToRender = iconComponent ? (_jsx(CommonIconContainer, { $size: smallButton ? 16 : 24, children: iconComponent })) : icon ? (_jsx(IconContainer, { $trailingIcon: trailingIcon, render: icon, size: smallButton ? 16 : 24,
12
- // Tertiary dims by colour rather than opacity when disabled
13
- color: tertiary && disabled ? 'color.icon.nonEssential' : 'color.icon.base' })) : null;
14
- return (_jsxs(Container, { forwardedAs: "button", id: id, className: className, disabled: disabled || loading, onClick: handleClick, $loading: loading, $primary: primary, $secondary: secondary, $tertiary: tertiary, $fallbackStyle: fallbackStyle, $textBtn: textBtn, $smallButton: smallButton, $trailingIcon: trailingIcon, $forcedWidth: forcedWidth, ...(form ? { form } : {}), type: type, ...otherProps, ref: ref, children: [loading && (_jsx(LoaderContainer, { children: _jsx(Loader, { color: "color.icon.base", height: "16" }) })), _jsxs(ContentContainer, { $hasIcon: !!iconToRender, $loading: loading, children: [!trailingIcon && iconToRender ? iconToRender : null, _jsx(ChildrenContainer, { className: "childrenContainer", children: children }), trailingIcon && iconToRender && textBtn ? iconToRender : null] })] }));
10
+ // Primary is the default type, so an untyped button gets Primary's hover and pressed states too
11
+ const isPrimary = primary || !(secondary || tertiary || fallbackStyle || textBtn);
12
+ // Icon-only buttons drop the gap so the icon stays centred
13
+ // React renders nothing for null, undefined, booleans and empty strings
14
+ const hasLabel = children != null && typeof children !== 'boolean' && children !== '';
15
+ const iconToRender = iconComponent ? (_jsx(CustomIconContainer, { children: iconComponent })) : icon ? (_jsx(IconComponent, { render: icon, size: iconSize,
16
+ // Matches the label, which tertiary dims by colour rather than opacity when disabled
17
+ color: tertiary && disabled ? 'color.icon.nonEssential' : 'color.icon.contrast' })) : null;
18
+ return (_jsxs(Container, { forwardedAs: "button", id: id, className: className, disabled: disabled || loading, onClick: handleClick, $loading: loading, $primary: isPrimary, $secondary: secondary, $tertiary: tertiary, $fallbackStyle: fallbackStyle, $textBtn: textBtn, $smallButton: smallButton, $trailingIcon: trailingIcon, $forcedWidth: forcedWidth, ...(form ? { form } : {}), type: type, ...otherProps, ref: ref, children: [loading && (_jsx(LoaderContainer, { children: _jsx(Loader, { color: "color.icon.base", height: "16" }) })), _jsxs(ContentContainer, { $loading: loading, $hasLabel: hasLabel, children: [!trailingIcon && iconToRender ? iconToRender : null, _jsx(ChildrenContainer, { className: "childrenContainer", children: children }), trailingIcon && iconToRender ? iconToRender : null] })] }));
15
19
  });
16
20
  Button.displayName = 'Button';
17
21
  const Container = styled(Box)(({ disabled, $loading, $primary, $secondary, $tertiary, $forcedWidth, $fallbackStyle, $textBtn, $smallButton, }) => css `
18
22
  position: relative;
19
23
  background-color: ${({ theme }) => theme.color.interactive.primary.base};
20
24
  box-shadow: none;
21
- color: ${({ theme }) => theme.color.text.base};
25
+ color: ${({ theme }) => theme.color.text.contrast};
22
26
  padding: 0 20px;
23
27
  outline: none;
24
28
  border-radius: 10000px;
@@ -63,7 +67,7 @@ const Container = styled(Box)(({ disabled, $loading, $primary, $secondary, $tert
63
67
  }
64
68
  &:active {
65
69
  background-color: ${({ theme }) => !(disabled || $loading) &&
66
- theme.color.interactive.neutral.subtle.pressed};
70
+ theme.color.interactive.neutral.subtle.selected};
67
71
  }
68
72
 
69
73
  ${disabled &&
@@ -85,16 +89,11 @@ const Container = styled(Box)(({ disabled, $loading, $primary, $secondary, $tert
85
89
  `}
86
90
  ${$smallButton &&
87
91
  css `
88
- padding: 0 10px;
92
+ padding: 0 12px;
89
93
  min-width: 54px;
90
- font-size: 14px;
91
94
 
92
95
  .childrenContainer {
93
- padding: 9px 0;
94
- }
95
-
96
- span {
97
- margin: 0 5px 0 0;
96
+ padding: 8px 0;
98
97
  }
99
98
  `}
100
99
  ${$textBtn &&
@@ -111,6 +110,15 @@ const Container = styled(Box)(({ disabled, $loading, $primary, $secondary, $tert
111
110
  background-color: transparent;
112
111
  color: ${({ theme }) => theme.color.text.subtle};
113
112
  }
113
+
114
+ ${$smallButton &&
115
+ css `
116
+ font-size: 14px;
117
+
118
+ .childrenContainer {
119
+ padding: 9px 0;
120
+ }
121
+ `}
114
122
  `}
115
123
  `);
116
124
  const LoaderContainer = styled.div `
@@ -126,14 +134,28 @@ const LoaderContainer = styled.div `
126
134
  const ContentContainer = styled.div `
127
135
  display: flex;
128
136
  align-items: center;
129
- justify-content: ${({ $hasIcon }) => ($hasIcon ? 'space-evenly' : 'center')};
137
+ justify-content: center;
138
+ gap: ${({ $hasLabel }) => ($hasLabel ? '4px' : '0')};
130
139
  opacity: ${({ $loading }) => ($loading ? '0' : '1')};
131
140
  `;
132
- const IconContainer = styled(IconComponent)(({ $trailingIcon }) => css `
133
- margin: ${$trailingIcon ? '0 0 0 10px' : '0 10px 0 0'};
134
- `);
141
+ const iconSize = 20;
142
+ // Figma icons use Font Awesome's square bounding box, in which the glyph's em height
143
+ // takes up 80% of the box, so custom (Font Awesome) icons are drawn at that size
144
+ const CustomIconContainer = styled.span `
145
+ display: inline-flex;
146
+ flex-shrink: 0;
147
+ align-items: center;
148
+ justify-content: center;
149
+ width: ${iconSize}px;
150
+ height: ${iconSize}px;
151
+
152
+ svg {
153
+ width: 100%;
154
+ height: 80%;
155
+ overflow: visible;
156
+ }
157
+ `;
135
158
  const ChildrenContainer = styled.div `
136
159
  padding: 16px 0;
137
- flex-grow: 1;
138
160
  `;
139
161
  //# sourceMappingURL=Button.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n ButtonHTMLAttributes,\n FC,\n FormEvent,\n ReactNode,\n forwardRef,\n} from 'react'\nimport styled, { css } from 'styled-components'\nimport { IconContainer as CommonIconContainer } from '../sharedStyles/shared.styles'\n\nimport { TransientProps } from '../utils/utilTypes'\nimport { Box } from '../Box'\nimport { Icon as IconComponent, Icons } from '../Icon'\n\nimport { Loader } from '../Loader'\nimport { focusOutlineStyle } from '../utils/focusOutline'\nimport { MarginProps } from '../utils/space'\n\ntype Props = {\n children: ReactNode\n id?: string\n className?: string\n disabled?: boolean\n handleClick?: (e: FormEvent<HTMLButtonElement>) => void\n loading?: boolean\n primary?: boolean\n secondary?: boolean\n /** Low-emphasis, text-only action, e.g. \"Skip\" or \"Cancel\" */\n tertiary?: boolean\n fallbackStyle?: boolean\n /** Legacy underlined text style. Prefer `tertiary` for new low-emphasis actions */\n textBtn?: boolean\n smallButton?: boolean\n icon?: Icons\n iconComponent?: ReactNode\n trailingIcon?: boolean\n forcedWidth?: string\n form?: string\n}\n\nexport type ButtonProps = Props &\n MarginProps &\n Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'color'>\n\nexport const Button: FC<ButtonProps> = forwardRef<\n HTMLButtonElement,\n ButtonProps\n>((props, ref) => {\n const {\n children,\n id,\n className = '',\n disabled = false,\n handleClick,\n loading = false,\n primary = false,\n secondary = false,\n tertiary = false,\n fallbackStyle = false,\n textBtn = false,\n smallButton = false,\n icon,\n iconComponent,\n trailingIcon = false,\n forcedWidth = '',\n form,\n type,\n ...otherProps\n } = props\n\n const iconToRender = iconComponent ? (\n <CommonIconContainer $size={smallButton ? 16 : 24}>\n {iconComponent}\n </CommonIconContainer>\n ) : icon ? (\n <IconContainer\n $trailingIcon={trailingIcon}\n render={icon}\n size={smallButton ? 16 : 24}\n // Tertiary dims by colour rather than opacity when disabled\n color={\n tertiary && disabled ? 'color.icon.nonEssential' : 'color.icon.base'\n }\n />\n ) : null\n\n return (\n <Container\n forwardedAs=\"button\"\n id={id}\n className={className}\n disabled={disabled || loading}\n onClick={handleClick}\n $loading={loading}\n $primary={primary}\n $secondary={secondary}\n $tertiary={tertiary}\n $fallbackStyle={fallbackStyle}\n $textBtn={textBtn}\n $smallButton={smallButton}\n $trailingIcon={trailingIcon}\n $forcedWidth={forcedWidth}\n {...(form ? { form } : {})}\n type={type}\n {...otherProps}\n ref={ref}\n >\n {loading && (\n <LoaderContainer>\n <Loader color=\"color.icon.base\" height=\"16\" />\n </LoaderContainer>\n )}\n <ContentContainer $hasIcon={!!iconToRender} $loading={loading}>\n {!trailingIcon && iconToRender ? iconToRender : null}\n <ChildrenContainer className=\"childrenContainer\">\n {children}\n </ChildrenContainer>\n {trailingIcon && iconToRender && textBtn ? iconToRender : null}\n </ContentContainer>\n </Container>\n )\n})\n\nButton.displayName = 'Button'\n\ntype IButton = TransientProps<\n Required<\n Pick<\n ButtonProps,\n | 'primary'\n | 'secondary'\n | 'tertiary'\n | 'forcedWidth'\n | 'fallbackStyle'\n | 'textBtn'\n | 'trailingIcon'\n | 'smallButton'\n >\n >\n> & {\n $loading: NonNullable<ButtonProps['loading']>\n disabled: boolean\n}\n\nconst Container = styled(Box)<IButton>(\n ({\n disabled,\n $loading,\n $primary,\n $secondary,\n $tertiary,\n $forcedWidth,\n $fallbackStyle,\n $textBtn,\n $smallButton,\n }) => css`\n position: relative;\n background-color: ${({ theme }) => theme.color.interactive.primary.base};\n box-shadow: none;\n color: ${({ theme }) => theme.color.text.base};\n padding: 0 20px;\n outline: none;\n border-radius: 10000px;\n font-weight: ${({ theme }) => theme.fontWeight[500]};\n cursor: ${disabled || $loading ? 'not-allowed' : 'pointer'};\n line-height: 100%;\n font-size: 16px;\n opacity: ${disabled ? '0.5' : '1'};\n width: ${$forcedWidth ? $forcedWidth : 'auto'};\n\n ${focusOutlineStyle}\n\n ${\n $primary &&\n css`\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) && theme.color.interactive.primary.hover};\n }\n &:active {\n background-color: ${({ theme }) =>\n theme.color.interactive.primary.selected};\n }\n `\n }\n\n ${\n $secondary &&\n css`\n background-color: ${({ theme }) =>\n theme.color.interactive.secondary.base};\n\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) && theme.color.interactive.secondary.hover};\n }\n &:active {\n background-color: ${({ theme }) =>\n theme.color.interactive.secondary.selected};\n }\n `\n }\n ${\n $tertiary &&\n css`\n background-color: transparent;\n opacity: 1;\n\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) &&\n theme.color.interactive.neutral.subtle.hover};\n }\n &:active {\n background-color: ${({ theme }) =>\n !(disabled || $loading) &&\n theme.color.interactive.neutral.subtle.pressed};\n }\n\n ${\n disabled &&\n css`\n color: ${({ theme }) => theme.color.text.nonEssential};\n `\n }\n `\n }\n ${\n $fallbackStyle &&\n css`\n background-color: ${({ theme }) => theme.color.interactive.neutral.subtle.base};\n\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) &&\n theme.color.interactive.neutral.subtle.hover};\n }\n &:active {\n background-color: ${({ theme }) =>\n theme.color.interactive.neutral.subtle.selected};\n }\n `\n }\n ${\n $smallButton &&\n css`\n padding: 0 10px;\n min-width: 54px;\n font-size: 14px;\n\n .childrenContainer {\n padding: 9px 0;\n }\n\n span {\n margin: 0 5px 0 0;\n }\n `\n }\n ${\n $textBtn &&\n css`\n background-color: transparent;\n padding: 0;\n border-radius: 0;\n text-decoration: underline;\n\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) && theme.color.interactive.primary.hover};\n }\n &:active {\n background-color: transparent;\n color: ${({ theme }) => theme.color.text.subtle};\n }\n `\n }\n `,\n)\n\nconst LoaderContainer = styled.div`\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n`\n\nconst ContentContainer = styled.div<{ $loading: boolean; $hasIcon?: boolean }>`\n display: flex;\n align-items: center;\n justify-content: ${({ $hasIcon }) => ($hasIcon ? 'space-evenly' : 'center')};\n opacity: ${({ $loading }) => ($loading ? '0' : '1')};\n`\n\nconst IconContainer = styled(IconComponent)<\n TransientProps<Pick<ButtonProps, 'trailingIcon'>>\n>(\n ({ $trailingIcon }) => css`\n margin: ${$trailingIcon ? '0 0 0 10px' : '0 10px 0 0'};\n `,\n)\n\nconst ChildrenContainer = styled.div`\n padding: 16px 0;\n flex-grow: 1;\n`\n"]}
1
+ {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n ButtonHTMLAttributes,\n FC,\n FormEvent,\n ReactNode,\n forwardRef,\n} from 'react'\nimport styled, { css } from 'styled-components'\n\nimport { TransientProps } from '../utils/utilTypes'\nimport { Box } from '../Box'\nimport { Icon as IconComponent, Icons } from '../Icon'\n\nimport { Loader } from '../Loader'\nimport { focusOutlineStyle } from '../utils/focusOutline'\nimport { MarginProps } from '../utils/space'\n\ntype Props = {\n children: ReactNode\n id?: string\n className?: string\n disabled?: boolean\n handleClick?: (e: FormEvent<HTMLButtonElement>) => void\n loading?: boolean\n primary?: boolean\n secondary?: boolean\n /** Low-emphasis, text-only action, e.g. \"Skip\" or \"Cancel\" */\n tertiary?: boolean\n fallbackStyle?: boolean\n /** Legacy underlined text style. Prefer `tertiary` for new low-emphasis actions */\n textBtn?: boolean\n smallButton?: boolean\n icon?: Icons\n iconComponent?: ReactNode\n trailingIcon?: boolean\n forcedWidth?: string\n form?: string\n}\n\nexport type ButtonProps = Props &\n MarginProps &\n Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'color'>\n\nexport const Button: FC<ButtonProps> = forwardRef<\n HTMLButtonElement,\n ButtonProps\n>((props, ref) => {\n const {\n children,\n id,\n className = '',\n disabled = false,\n handleClick,\n loading = false,\n primary = false,\n secondary = false,\n tertiary = false,\n fallbackStyle = false,\n textBtn = false,\n smallButton = false,\n icon,\n iconComponent,\n trailingIcon = false,\n forcedWidth = '',\n form,\n type,\n ...otherProps\n } = props\n\n // Primary is the default type, so an untyped button gets Primary's hover and pressed states too\n const isPrimary =\n primary || !(secondary || tertiary || fallbackStyle || textBtn)\n\n // Icon-only buttons drop the gap so the icon stays centred\n // React renders nothing for null, undefined, booleans and empty strings\n const hasLabel =\n children != null && typeof children !== 'boolean' && children !== ''\n\n const iconToRender = iconComponent ? (\n <CustomIconContainer>{iconComponent}</CustomIconContainer>\n ) : icon ? (\n <IconComponent\n render={icon}\n size={iconSize}\n // Matches the label, which tertiary dims by colour rather than opacity when disabled\n color={\n tertiary && disabled ? 'color.icon.nonEssential' : 'color.icon.contrast'\n }\n />\n ) : null\n\n return (\n <Container\n forwardedAs=\"button\"\n id={id}\n className={className}\n disabled={disabled || loading}\n onClick={handleClick}\n $loading={loading}\n $primary={isPrimary}\n $secondary={secondary}\n $tertiary={tertiary}\n $fallbackStyle={fallbackStyle}\n $textBtn={textBtn}\n $smallButton={smallButton}\n $trailingIcon={trailingIcon}\n $forcedWidth={forcedWidth}\n {...(form ? { form } : {})}\n type={type}\n {...otherProps}\n ref={ref}\n >\n {loading && (\n <LoaderContainer>\n <Loader color=\"color.icon.base\" height=\"16\" />\n </LoaderContainer>\n )}\n <ContentContainer $loading={loading} $hasLabel={hasLabel}>\n {!trailingIcon && iconToRender ? iconToRender : null}\n <ChildrenContainer className=\"childrenContainer\">\n {children}\n </ChildrenContainer>\n {trailingIcon && iconToRender ? iconToRender : null}\n </ContentContainer>\n </Container>\n )\n})\n\nButton.displayName = 'Button'\n\ntype IButton = TransientProps<\n Required<\n Pick<\n ButtonProps,\n | 'primary'\n | 'secondary'\n | 'tertiary'\n | 'forcedWidth'\n | 'fallbackStyle'\n | 'textBtn'\n | 'trailingIcon'\n | 'smallButton'\n >\n >\n> & {\n $loading: NonNullable<ButtonProps['loading']>\n disabled: boolean\n}\n\nconst Container = styled(Box)<IButton>(\n ({\n disabled,\n $loading,\n $primary,\n $secondary,\n $tertiary,\n $forcedWidth,\n $fallbackStyle,\n $textBtn,\n $smallButton,\n }) => css`\n position: relative;\n background-color: ${({ theme }) => theme.color.interactive.primary.base};\n box-shadow: none;\n color: ${({ theme }) => theme.color.text.contrast};\n padding: 0 20px;\n outline: none;\n border-radius: 10000px;\n font-weight: ${({ theme }) => theme.fontWeight[500]};\n cursor: ${disabled || $loading ? 'not-allowed' : 'pointer'};\n line-height: 100%;\n font-size: 16px;\n opacity: ${disabled ? '0.5' : '1'};\n width: ${$forcedWidth ? $forcedWidth : 'auto'};\n\n ${focusOutlineStyle}\n\n ${\n $primary &&\n css`\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) && theme.color.interactive.primary.hover};\n }\n &:active {\n background-color: ${({ theme }) =>\n theme.color.interactive.primary.selected};\n }\n `\n }\n\n ${\n $secondary &&\n css`\n background-color: ${({ theme }) =>\n theme.color.interactive.secondary.base};\n\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) && theme.color.interactive.secondary.hover};\n }\n &:active {\n background-color: ${({ theme }) =>\n theme.color.interactive.secondary.selected};\n }\n `\n }\n ${\n $tertiary &&\n css`\n background-color: transparent;\n opacity: 1;\n\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) &&\n theme.color.interactive.neutral.subtle.hover};\n }\n &:active {\n background-color: ${({ theme }) =>\n !(disabled || $loading) &&\n theme.color.interactive.neutral.subtle.selected};\n }\n\n ${\n disabled &&\n css`\n color: ${({ theme }) => theme.color.text.nonEssential};\n `\n }\n `\n }\n ${\n $fallbackStyle &&\n css`\n background-color: ${({ theme }) => theme.color.interactive.neutral.subtle.base};\n\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) &&\n theme.color.interactive.neutral.subtle.hover};\n }\n &:active {\n background-color: ${({ theme }) =>\n theme.color.interactive.neutral.subtle.selected};\n }\n `\n }\n ${\n $smallButton &&\n css`\n padding: 0 12px;\n min-width: 54px;\n\n .childrenContainer {\n padding: 8px 0;\n }\n `\n }\n ${\n $textBtn &&\n css`\n background-color: transparent;\n padding: 0;\n border-radius: 0;\n text-decoration: underline;\n\n &:hover {\n background-color: ${({ theme }) =>\n !(disabled || $loading) && theme.color.interactive.primary.hover};\n }\n &:active {\n background-color: transparent;\n color: ${({ theme }) => theme.color.text.subtle};\n }\n\n ${\n $smallButton &&\n css`\n font-size: 14px;\n\n .childrenContainer {\n padding: 9px 0;\n }\n `\n }\n `\n }\n `,\n)\n\nconst LoaderContainer = styled.div`\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n`\n\nconst ContentContainer = styled.div<{ $loading: boolean; $hasLabel: boolean }>`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: ${({ $hasLabel }) => ($hasLabel ? '4px' : '0')};\n opacity: ${({ $loading }) => ($loading ? '0' : '1')};\n`\n\nconst iconSize = 20\n\n// Figma icons use Font Awesome's square bounding box, in which the glyph's em height\n// takes up 80% of the box, so custom (Font Awesome) icons are drawn at that size\nconst CustomIconContainer = styled.span`\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: ${iconSize}px;\n height: ${iconSize}px;\n\n svg {\n width: 100%;\n height: 80%;\n overflow: visible;\n }\n`\n\nconst ChildrenContainer = styled.div`\n padding: 16px 0;\n`\n"]}
@@ -18,7 +18,11 @@ export interface Props extends CommonFieldProps {
18
18
  frontIcon?: Icons;
19
19
  iconComponent?: ReactNode;
20
20
  fallbackStyle?: boolean;
21
- onSelect: (element: string) => void;
21
+ /** Accessible name, for when there is no visible `label` */
22
+ 'aria-label'?: string;
23
+ /** Lets the browser autofill the field, e.g. `honorific-prefix` */
24
+ autoComplete?: string;
25
+ onSelect?: (element: string) => void;
22
26
  onBlur?: (e: FocusEvent<HTMLSelectElement>) => void;
23
27
  }
24
28
  type TruncateProps = {
@@ -4,18 +4,21 @@ import styled, { css, useTheme } from 'styled-components';
4
4
  import { Box } from '../Box';
5
5
  import { Field } from '../fields/Field';
6
6
  import { InputLeadingIconContainer, StyledFrontIcon, } from '../fields/components/CommonInput';
7
+ import { fieldDisabledStyle, fieldFocusAttrs, fieldFocusRing, } from '../fields/components/fieldStyles';
7
8
  import { useUniqueId } from '../utils/id';
8
9
  import { useControllableState } from '../utils/useControlledState';
9
10
  import { IconContainer } from '../sharedStyles/shared.styles';
10
- import { faChevronDown } from '@awesome.me/kit-46ca99185c/icons/classic/regular';
11
+ import { faChevronDown } from '@awesome.me/kit-46ca99185c/icons/classic/solid';
11
12
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
12
- export const Dropdown = forwardRef(function Dropdown({ id: idProp, placeholder, showDefaultOption = false, customDefaultOption, name, value: valueProp, defaultValue, disabled = false, list, onSelect, error = false, onInputChange, onBlur, frontIcon, iconComponent, fallbackStyle, ...fieldProps }, ref) {
13
+ export const Dropdown = forwardRef(function Dropdown({ id: idProp, placeholder, showDefaultOption = false, customDefaultOption, name, value: valueProp, defaultValue, disabled = false, list, onSelect, error = false, onInputChange, onBlur, frontIcon, iconComponent, fallbackStyle, required, 'aria-label': ariaLabel, autoComplete, ...fieldProps }, ref) {
13
14
  const theme = useTheme();
14
15
  const [value, setValue] = useControllableState({
15
16
  initialState: defaultValue,
16
17
  stateProp: valueProp,
17
18
  });
18
19
  const id = useUniqueId(idProp);
20
+ const assistiveTextId = `${id}-assistive-text`;
21
+ const errorMsgId = `${id}-error`;
19
22
  const hasOptGroups = list.findIndex((item) => !!item.optionGroupLabel) !== -1;
20
23
  const dropdownItemsGroups = useMemo(() => {
21
24
  const itemsPerGroupLabel = new Map();
@@ -33,64 +36,70 @@ export const Dropdown = forwardRef(function Dropdown({ id: idProp, placeholder,
33
36
  }
34
37
  return customDefaultOption ?? 'Select an option';
35
38
  };
36
- const iconToRender = iconComponent ? (_jsx(InputLeadingIconContainer, { $size: 16, $iconColor: theme.color.text.base, children: iconComponent })) : frontIcon ? (_jsx(StyledFrontIcon, { $disabled: disabled, render: frontIcon, color: "sesame" })) : null;
37
- return (_jsx(Field, { ...fieldProps, htmlFor: id, error: error, children: _jsxs(Box, { flex: true, alignItems: "center", style: { position: 'relative' }, children: [iconToRender, _jsxs(StyledSelect, { id: id, disabled: disabled || list.length < 1, onChange: (event) => {
39
+ // Only reference messages that the field actually renders.
40
+ const describedBy = [
41
+ fieldProps.assistiveText &&
42
+ (!fieldProps.renderAsTitle || fieldProps.label) &&
43
+ assistiveTextId,
44
+ error && fieldProps.errorMsg && errorMsgId,
45
+ ]
46
+ .filter(Boolean)
47
+ .join(' ') || undefined;
48
+ const iconToRender = iconComponent ? (_jsx(InputLeadingIconContainer, { $size: 16, $iconColor: theme.color.text.base, children: iconComponent })) : frontIcon ? (_jsx(StyledFrontIcon, { render: frontIcon, color: "color.icon.subtle" })) : null;
49
+ return (_jsx(Field, { ...fieldProps, htmlFor: id, error: error, required: required, assistiveTextId: assistiveTextId, errorMsgId: errorMsgId, children: _jsxs(Box, { flex: true, alignItems: "center", style: { position: 'relative' }, children: [iconToRender, _jsxs(StyledSelect, { id: id, disabled: disabled || list.length < 1, onChange: (event) => {
38
50
  const value = event.currentTarget.value;
39
51
  onSelect?.(value);
40
52
  onInputChange?.(event);
41
53
  setValue(value);
42
- }, $error: error, ref: ref, onBlur: onBlur, name: name, $frontIcon: frontIcon, $fallbackStyle: fallbackStyle, value: value ?? '', children: [hasOptGroups ? (_jsx("optgroup", { label: defaultOptionLabel(), children: _jsx("option", { value: "", hidden: !showDefaultOption, disabled: true, children: defaultOptionLabel() }) })) : (_jsx("option", { value: "", hidden: !showDefaultOption, disabled: true, children: defaultOptionLabel() })), dropdownItemsGroups.map((groupItems, i) => hasOptGroups ? (_jsx("optgroup", { label: groupItems[0].optionGroupLabel ?? 'Other', children: groupItems.map((el, j) => (_jsx("option", { value: el.value, children: el.label }, `${i}-${j}`))) }, i)) : (groupItems.map((el, j) => (_jsx("option", { value: el.value, children: el.label }, j)))))] }), _jsx(Caret, { children: _jsx(IconContainer, { $size: 20, children: _jsx(FontAwesomeIcon, { icon: faChevronDown, color: theme.color.illustration.neutral[400] }) }) })] }) }));
54
+ }, $error: error, ref: ref, onBlur: onBlur, name: name, autoComplete: autoComplete, "aria-label": ariaLabel, "aria-invalid": error || undefined, "aria-required": required || undefined, "aria-describedby": describedBy, $frontIcon: !!iconToRender, $fallbackStyle: fallbackStyle, value: value ?? '', children: [_jsx("option", { value: "", hidden: !showDefaultOption, disabled: true, children: defaultOptionLabel() }), dropdownItemsGroups.map((groupItems, i) => hasOptGroups ? (_jsx("optgroup", { label: groupItems[0].optionGroupLabel ?? 'Other', children: groupItems.map((el, j) => (_jsx("option", { value: el.value, children: el.label }, `${i}-${j}`))) }, i)) : (groupItems.map((el, j) => (_jsx("option", { value: el.value, children: el.label }, j)))))] }), _jsx(Caret, { children: _jsx(IconContainer, { $size: 16, children: _jsx(FontAwesomeIcon, { icon: faChevronDown, color: theme.color.icon.subtle }) }) })] }) }));
43
55
  });
44
- const resetSelect = css `
45
- border: none;
46
- border-radius: 0;
47
- font-size: 16px;
48
- appearance: none; /* remove default arrow */
49
- outline: none;
50
- `;
51
- const StyledSelect = styled.select `
52
- ${resetSelect}
53
- width: 100%;
54
- height: 32px;
55
- color: ${({ value, theme }) => value === '' ? theme.color.text.subtle : theme.color.text.base};
56
- cursor: pointer;
57
- background-color: ${({ $fallbackStyle, theme }) => $fallbackStyle
58
- ? theme.color.surface.base[300]
59
- : theme.color.background['000']};
60
-
61
- border-radius: 12px;
62
- padding: 18px 14px;
63
- border: 2px solid
64
- ${({ $error, theme }) => $error ? theme.color.feedback.negative[200] : theme.color.border.subtle};
65
- height: auto;
56
+ // Figma's 32px chevron slot sits 12px from the edge, 16px from the text
57
+ const CHEVRON_INSET = 20;
58
+ const StyledSelect = styled.select.attrs(fieldFocusAttrs)(({ theme, $error, $frontIcon, $fallbackStyle, value }) => {
59
+ const borderColor = (color) => $error ? theme.color.feedback.negative[200] : color;
60
+ return css `
61
+ appearance: none;
62
+ width: 100%;
63
+ height: 48px;
64
+ margin: 0;
65
+ padding: 12px 60px 12px ${$frontIcon ? '42px' : '12px'};
66
+ border: 2px solid ${borderColor(theme.color.border.subtle)};
67
+ border-radius: 12px;
68
+ background-color: ${$fallbackStyle
69
+ ? theme.color.surface.base[300]
70
+ : theme.color.background['000']};
71
+ color: ${value === '' ? theme.color.text.subtle : theme.color.text.base};
72
+ font-family: inherit;
73
+ font-size: 16px;
74
+ line-height: 20px;
75
+ text-overflow: ellipsis;
76
+ cursor: pointer;
77
+ outline: none;
66
78
 
67
- ${({ $frontIcon }) => $frontIcon &&
68
- $frontIcon != '' &&
69
- `
70
- padding-left: 42px;
71
- `}
79
+ option,
80
+ optgroup {
81
+ color: ${theme.color.text.base};
82
+ }
72
83
 
73
- &:disabled {
74
- cursor: not-allowed;
75
- opacity: 0.5;
76
- }
84
+ // Hover mustn't override the focus border while the pointer is over a
85
+ // focused field.
86
+ &:hover:not(:disabled):not(:focus) {
87
+ border-color: ${borderColor(theme.color.border.base)};
88
+ }
77
89
 
78
- ${({ $error }) => !$error &&
79
- css `
80
- :not(:disabled) {
81
- &:hover,
82
- &:focus,
83
- &:focus-visible,
84
- &:checked {
85
- border-color: ${({ theme }) => theme.color.icon.nonEssential};
90
+ &:focus {
91
+ border-color: ${borderColor(theme.color.border.contrast)};
86
92
  }
87
- `}
88
- `;
93
+
94
+ ${fieldFocusRing}
95
+ ${fieldDisabledStyle}
96
+ `;
97
+ });
89
98
  const Caret = styled.div `
90
99
  position: absolute;
91
100
  z-index: 1;
92
- right: 15px;
101
+ right: ${CHEVRON_INSET}px;
102
+ display: flex;
93
103
  pointer-events: none;
94
- color: ${({ theme }) => theme.color.icon.nonEssential};
95
104
  `;
96
105
  //# sourceMappingURL=Dropdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.js","sourceRoot":"","sources":["../../src/Dropdown/Dropdown.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n FocusEvent,\n FormEvent,\n ForwardedRef,\n forwardRef,\n ReactNode,\n useMemo,\n} from 'react'\nimport styled, { css, useTheme } from 'styled-components'\n\nimport { Box } from '../Box'\nimport { Icons } from '../Icon'\n\nimport { Field } from '../fields/Field'\nimport { CommonFieldProps } from '../fields/commonFieldTypes'\nimport {\n InputLeadingIconContainer,\n StyledFrontIcon,\n} from '../fields/components/CommonInput'\nimport { useUniqueId } from '../utils/id'\nimport { useControllableState } from '../utils/useControlledState'\nimport { IconContainer } from '../sharedStyles/shared.styles'\nimport { faChevronDown } from '@awesome.me/kit-46ca99185c/icons/classic/regular'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\n\nexport type DropdownItem = {\n optionGroupLabel?: string\n label: string\n value: string\n}\n\nexport interface Props extends CommonFieldProps {\n placeholder?: string\n showDefaultOption?: boolean\n customDefaultOption?: string\n name?: string\n value?: string | null\n defaultValue?: string\n disabled?: boolean\n list: DropdownItem[]\n frontIcon?: Icons\n iconComponent?: ReactNode\n fallbackStyle?: boolean\n onSelect: (element: string) => void\n onBlur?: (e: FocusEvent<HTMLSelectElement>) => void\n}\n\ntype TruncateProps =\n | {\n onSelect: (e: string) => void\n onInputChange?: (e: FormEvent<HTMLSelectElement>) => void\n }\n | {\n onSelect?: (e: string) => void\n onInputChange: (e: FormEvent<HTMLSelectElement>) => void\n }\n\nexport type DropdownProps = Props & TruncateProps\n\nexport const Dropdown = forwardRef(function Dropdown(\n {\n id: idProp,\n placeholder,\n showDefaultOption = false,\n customDefaultOption,\n name,\n value: valueProp,\n defaultValue,\n disabled = false,\n list,\n onSelect,\n error = false,\n onInputChange,\n onBlur,\n frontIcon,\n iconComponent,\n fallbackStyle,\n ...fieldProps\n }: DropdownProps,\n ref: ForwardedRef<HTMLSelectElement>,\n) {\n const theme = useTheme()\n const [value, setValue] = useControllableState({\n initialState: defaultValue,\n stateProp: valueProp,\n })\n const id = useUniqueId(idProp)\n const hasOptGroups = list.findIndex((item) => !!item.optionGroupLabel) !== -1\n\n const dropdownItemsGroups = useMemo(() => {\n const itemsPerGroupLabel = new Map<string, DropdownItem[]>()\n\n list.forEach((item) => {\n const key = item.optionGroupLabel ?? ''\n const group = itemsPerGroupLabel.get(key) ?? []\n\n group.push(item)\n itemsPerGroupLabel.set(key, group)\n })\n\n return Array.from(itemsPerGroupLabel.values())\n }, [list])\n\n const defaultOptionLabel = () => {\n if (!showDefaultOption) {\n return placeholder\n }\n return customDefaultOption ?? 'Select an option'\n }\n\n const iconToRender = iconComponent ? (\n <InputLeadingIconContainer $size={16} $iconColor={theme.color.text.base}>\n {iconComponent}\n </InputLeadingIconContainer>\n ) : frontIcon ? (\n <StyledFrontIcon $disabled={disabled} render={frontIcon} color=\"sesame\" />\n ) : null\n\n return (\n <Field {...fieldProps} htmlFor={id} error={error}>\n <Box flex alignItems=\"center\" style={{ position: 'relative' }}>\n {iconToRender}\n <StyledSelect\n id={id}\n disabled={disabled || list.length < 1}\n onChange={(event) => {\n const value = event.currentTarget.value\n\n onSelect?.(value)\n onInputChange?.(event)\n setValue(value)\n }}\n $error={error}\n ref={ref}\n onBlur={onBlur}\n name={name}\n $frontIcon={frontIcon}\n $fallbackStyle={fallbackStyle}\n value={value ?? ''}\n >\n {hasOptGroups ? (\n <optgroup label={defaultOptionLabel()}>\n <option value=\"\" hidden={!showDefaultOption} disabled>\n {defaultOptionLabel()}\n </option>\n </optgroup>\n ) : (\n <option value=\"\" hidden={!showDefaultOption} disabled>\n {defaultOptionLabel()}\n </option>\n )}\n\n {dropdownItemsGroups.map((groupItems, i) =>\n hasOptGroups ? (\n <optgroup\n key={i}\n label={groupItems[0].optionGroupLabel ?? 'Other'}\n >\n {groupItems.map((el, j) => (\n <option key={`${i}-${j}`} value={el.value}>\n {el.label}\n </option>\n ))}\n </optgroup>\n ) : (\n groupItems.map((el, j) => (\n <option key={j} value={el.value}>\n {el.label}\n </option>\n ))\n ),\n )}\n </StyledSelect>\n <Caret>\n <IconContainer $size={20}>\n <FontAwesomeIcon\n icon={faChevronDown}\n color={theme.color.illustration.neutral[400]}\n />\n </IconContainer>\n </Caret>\n </Box>\n </Field>\n )\n})\n\nconst resetSelect = css`\n border: none;\n border-radius: 0;\n font-size: 16px;\n appearance: none; /* remove default arrow */\n outline: none;\n`\n\ninterface SSelect {\n $error: boolean\n $frontIcon?: string\n $fallbackStyle?: boolean\n value?: string | null\n}\n\nconst StyledSelect = styled.select<SSelect>`\n ${resetSelect}\n width: 100%;\n height: 32px;\n color: ${({ value, theme }) =>\n value === '' ? theme.color.text.subtle : theme.color.text.base};\n cursor: pointer;\n background-color: ${({ $fallbackStyle, theme }) =>\n $fallbackStyle\n ? theme.color.surface.base[300]\n : theme.color.background['000']};\n\n border-radius: 12px;\n padding: 18px 14px;\n border: 2px solid\n ${({ $error, theme }) =>\n $error ? theme.color.feedback.negative[200] : theme.color.border.subtle};\n height: auto;\n\n ${({ $frontIcon }) =>\n $frontIcon &&\n $frontIcon != '' &&\n `\n padding-left: 42px;\n `}\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n ${({ $error }) =>\n !$error &&\n css`\n :not(:disabled) {\n &:hover,\n &:focus,\n &:focus-visible,\n &:checked {\n border-color: ${({ theme }) => theme.color.icon.nonEssential};\n }\n `}\n`\n\nconst Caret = styled.div`\n position: absolute;\n z-index: 1;\n right: 15px;\n pointer-events: none;\n color: ${({ theme }) => theme.color.icon.nonEssential};\n`\n"]}
1
+ {"version":3,"file":"Dropdown.js","sourceRoot":"","sources":["../../src/Dropdown/Dropdown.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n FocusEvent,\n FormEvent,\n ForwardedRef,\n forwardRef,\n ReactNode,\n useMemo,\n} from 'react'\nimport styled, { css, useTheme } from 'styled-components'\n\nimport { Box } from '../Box'\nimport { Icons } from '../Icon'\n\nimport { Field } from '../fields/Field'\nimport { CommonFieldProps } from '../fields/commonFieldTypes'\nimport {\n InputLeadingIconContainer,\n StyledFrontIcon,\n} from '../fields/components/CommonInput'\nimport {\n fieldDisabledStyle,\n fieldFocusAttrs,\n fieldFocusRing,\n} from '../fields/components/fieldStyles'\nimport { useUniqueId } from '../utils/id'\nimport { useControllableState } from '../utils/useControlledState'\nimport { IconContainer } from '../sharedStyles/shared.styles'\nimport { faChevronDown } from '@awesome.me/kit-46ca99185c/icons/classic/solid'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\n\nexport type DropdownItem = {\n optionGroupLabel?: string\n label: string\n value: string\n}\n\nexport interface Props extends CommonFieldProps {\n placeholder?: string\n showDefaultOption?: boolean\n customDefaultOption?: string\n name?: string\n value?: string | null\n defaultValue?: string\n disabled?: boolean\n list: DropdownItem[]\n frontIcon?: Icons\n iconComponent?: ReactNode\n fallbackStyle?: boolean\n /** Accessible name, for when there is no visible `label` */\n 'aria-label'?: string\n /** Lets the browser autofill the field, e.g. `honorific-prefix` */\n autoComplete?: string\n onSelect?: (element: string) => void\n onBlur?: (e: FocusEvent<HTMLSelectElement>) => void\n}\n\ntype TruncateProps =\n | {\n onSelect: (e: string) => void\n onInputChange?: (e: FormEvent<HTMLSelectElement>) => void\n }\n | {\n onSelect?: (e: string) => void\n onInputChange: (e: FormEvent<HTMLSelectElement>) => void\n }\n\nexport type DropdownProps = Props & TruncateProps\n\nexport const Dropdown = forwardRef(function Dropdown(\n {\n id: idProp,\n placeholder,\n showDefaultOption = false,\n customDefaultOption,\n name,\n value: valueProp,\n defaultValue,\n disabled = false,\n list,\n onSelect,\n error = false,\n onInputChange,\n onBlur,\n frontIcon,\n iconComponent,\n fallbackStyle,\n required,\n 'aria-label': ariaLabel,\n autoComplete,\n ...fieldProps\n }: DropdownProps,\n ref: ForwardedRef<HTMLSelectElement>,\n) {\n const theme = useTheme()\n const [value, setValue] = useControllableState({\n initialState: defaultValue,\n stateProp: valueProp,\n })\n const id = useUniqueId(idProp)\n const assistiveTextId = `${id}-assistive-text`\n const errorMsgId = `${id}-error`\n const hasOptGroups = list.findIndex((item) => !!item.optionGroupLabel) !== -1\n\n const dropdownItemsGroups = useMemo(() => {\n const itemsPerGroupLabel = new Map<string, DropdownItem[]>()\n\n list.forEach((item) => {\n const key = item.optionGroupLabel ?? ''\n const group = itemsPerGroupLabel.get(key) ?? []\n\n group.push(item)\n itemsPerGroupLabel.set(key, group)\n })\n\n return Array.from(itemsPerGroupLabel.values())\n }, [list])\n\n const defaultOptionLabel = () => {\n if (!showDefaultOption) {\n return placeholder\n }\n return customDefaultOption ?? 'Select an option'\n }\n\n // Only reference messages that the field actually renders.\n const describedBy =\n [\n fieldProps.assistiveText &&\n (!fieldProps.renderAsTitle || fieldProps.label) &&\n assistiveTextId,\n error && fieldProps.errorMsg && errorMsgId,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n\n const iconToRender = iconComponent ? (\n <InputLeadingIconContainer $size={16} $iconColor={theme.color.text.base}>\n {iconComponent}\n </InputLeadingIconContainer>\n ) : frontIcon ? (\n <StyledFrontIcon render={frontIcon} color=\"color.icon.subtle\" />\n ) : null\n\n return (\n <Field\n {...fieldProps}\n htmlFor={id}\n error={error}\n required={required}\n assistiveTextId={assistiveTextId}\n errorMsgId={errorMsgId}\n >\n <Box flex alignItems=\"center\" style={{ position: 'relative' }}>\n {iconToRender}\n <StyledSelect\n id={id}\n disabled={disabled || list.length < 1}\n onChange={(event) => {\n const value = event.currentTarget.value\n\n onSelect?.(value)\n onInputChange?.(event)\n setValue(value)\n }}\n $error={error}\n ref={ref}\n onBlur={onBlur}\n name={name}\n autoComplete={autoComplete}\n aria-label={ariaLabel}\n aria-invalid={error || undefined}\n aria-required={required || undefined}\n aria-describedby={describedBy}\n $frontIcon={!!iconToRender}\n $fallbackStyle={fallbackStyle}\n value={value ?? ''}\n >\n <option value=\"\" hidden={!showDefaultOption} disabled>\n {defaultOptionLabel()}\n </option>\n\n {dropdownItemsGroups.map((groupItems, i) =>\n hasOptGroups ? (\n <optgroup\n key={i}\n label={groupItems[0].optionGroupLabel ?? 'Other'}\n >\n {groupItems.map((el, j) => (\n <option key={`${i}-${j}`} value={el.value}>\n {el.label}\n </option>\n ))}\n </optgroup>\n ) : (\n groupItems.map((el, j) => (\n <option key={j} value={el.value}>\n {el.label}\n </option>\n ))\n ),\n )}\n </StyledSelect>\n <Caret>\n <IconContainer $size={16}>\n <FontAwesomeIcon\n icon={faChevronDown}\n color={theme.color.icon.subtle}\n />\n </IconContainer>\n </Caret>\n </Box>\n </Field>\n )\n})\n\ninterface SSelect {\n $error: boolean\n $frontIcon: boolean\n $fallbackStyle?: boolean\n value?: string | null\n}\n\n// Figma's 32px chevron slot sits 12px from the edge, 16px from the text\nconst CHEVRON_INSET = 20\n\nconst StyledSelect = styled.select.attrs(fieldFocusAttrs)<SSelect>(\n ({ theme, $error, $frontIcon, $fallbackStyle, value }) => {\n const borderColor = (color: string) =>\n $error ? theme.color.feedback.negative[200] : color\n\n return css`\n appearance: none;\n width: 100%;\n height: 48px;\n margin: 0;\n padding: 12px 60px 12px ${$frontIcon ? '42px' : '12px'};\n border: 2px solid ${borderColor(theme.color.border.subtle)};\n border-radius: 12px;\n background-color: ${\n $fallbackStyle\n ? theme.color.surface.base[300]\n : theme.color.background['000']\n };\n color: ${value === '' ? theme.color.text.subtle : theme.color.text.base};\n font-family: inherit;\n font-size: 16px;\n line-height: 20px;\n text-overflow: ellipsis;\n cursor: pointer;\n outline: none;\n\n option,\n optgroup {\n color: ${theme.color.text.base};\n }\n\n // Hover mustn't override the focus border while the pointer is over a\n // focused field.\n &:hover:not(:disabled):not(:focus) {\n border-color: ${borderColor(theme.color.border.base)};\n }\n\n &:focus {\n border-color: ${borderColor(theme.color.border.contrast)};\n }\n\n ${fieldFocusRing}\n ${fieldDisabledStyle}\n `\n },\n)\n\nconst Caret = styled.div`\n position: absolute;\n z-index: 1;\n right: ${CHEVRON_INSET}px;\n display: flex;\n pointer-events: none;\n`\n"]}
package/dist/Link/Link.js CHANGED
@@ -1,15 +1,23 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { darken } from 'polished';
3
3
  import styled, { css } from 'styled-components';
4
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
5
+ import { faArrowUpRightFromSquare } from '@awesome.me/kit-46ca99185c/icons/classic/regular';
4
6
  import { Icon } from '../Icon';
5
7
  import { theme as oldTheme } from '../theme';
6
8
  import { focusOutline } from '../utils/focusOutline';
7
9
  import { IconContainer } from '../sharedStyles/shared.styles';
8
- export const Link = ({ className, href, onClick, openInNewTab, download, children, typo = 'regular', highlight = false, iconToRender: legacyIcon = openInNewTab ? 'new-window' : undefined, iconComponent, isTrailingIcon = true, }) => {
10
+ const ICON_SPACING = '4px';
11
+ export const Link = ({ className, href, onClick, openInNewTab, download, children, typo = 'regular', highlight = false, iconToRender: legacyIcon, iconComponent = !legacyIcon && openInNewTab ? (_jsx(FontAwesomeIcon, { icon: faArrowUpRightFromSquare })) : undefined, isTrailingIcon = true, }) => {
12
+ // Icon-only links keep the icon flush
13
+ const iconSpacing = children ? ICON_SPACING : '0';
9
14
  const iconToRender = iconComponent ? (_jsx(IconContainer, { $size: typo === 'regular' ? 16 : 12, style: {
10
- paddingRight: isTrailingIcon ? '0' : '4px',
11
- paddingLeft: isTrailingIcon ? '8px' : '0',
12
- }, children: iconComponent })) : legacyIcon ? (_jsx(Icon, { mt: { custom: '3px' }, size: typo === 'regular' ? 14 : 12, render: legacyIcon, color: highlight ? 'color.surface.brand.400' : 'color.surface.base.900' })) : null;
15
+ alignSelf: 'center',
16
+ marginRight: isTrailingIcon ? '0' : iconSpacing,
17
+ marginLeft: isTrailingIcon ? iconSpacing : '0',
18
+ }, children: iconComponent })) : legacyIcon ? (_jsx(Icon, { mt: { custom: '3px' }, ...(isTrailingIcon
19
+ ? { ml: { custom: iconSpacing } }
20
+ : { mr: { custom: iconSpacing } }), size: typo === 'regular' ? 14 : 12, render: legacyIcon, color: highlight ? 'color.interactive.primary.base' : 'color.text.base' })) : null;
13
21
  return (_jsxs(LinkWrapper, { href: href, className: className, onClick: onClick, download: download, $typo: typo, $highlight: highlight, ...(openInNewTab && {
14
22
  rel: 'noopener noreferrer',
15
23
  target: '_blank',
@@ -1 +1 @@
1
- {"version":3,"file":"Link.js","sourceRoot":"","sources":["../../src/Link/Link.tsx"],"names":[],"mappings":"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","sourcesContent":["import { darken } from 'polished'\nimport { FC, MouseEventHandler, ReactNode } from 'react'\nimport styled, { css } from 'styled-components'\n\nimport { Icon, Icons } from '../Icon'\nimport { theme as oldTheme } from '../theme'\nimport { focusOutline } from '../utils/focusOutline'\nimport { IconContainer } from '../sharedStyles/shared.styles'\n\ntype LinkTypo = 'regular' | 'small'\n\nexport type LinkProps = {\n className?: string\n href: string\n onClick?: MouseEventHandler\n openInNewTab?: boolean\n children?: ReactNode\n download?: boolean\n typo?: LinkTypo\n highlight?: boolean\n iconToRender?: Icons\n iconComponent?: ReactNode\n isTrailingIcon?: boolean\n}\n\nexport const Link: FC<LinkProps> = ({\n className,\n href,\n onClick,\n openInNewTab,\n download,\n children,\n typo = 'regular',\n highlight = false,\n iconToRender: legacyIcon = openInNewTab ? 'new-window' : undefined,\n iconComponent,\n isTrailingIcon = true,\n}) => {\n const iconToRender = iconComponent ? (\n <IconContainer\n $size={typo === 'regular' ? 16 : 12}\n style={{\n paddingRight: isTrailingIcon ? '0' : '4px',\n paddingLeft: isTrailingIcon ? '8px' : '0',\n }}\n >\n {iconComponent}\n </IconContainer>\n ) : legacyIcon ? (\n <Icon\n mt={{ custom: '3px' }}\n size={typo === 'regular' ? 14 : 12}\n render={legacyIcon}\n color={highlight ? 'color.surface.brand.400' : 'color.surface.base.900'}\n />\n ) : null\n\n return (\n <LinkWrapper\n href={href}\n className={className}\n onClick={onClick}\n download={download}\n $typo={typo}\n $highlight={highlight}\n {...(openInNewTab && {\n rel: 'noopener noreferrer',\n target: '_blank',\n })}\n >\n {!isTrailingIcon && iconToRender}\n {children}\n {isTrailingIcon && iconToRender}\n </LinkWrapper>\n )\n}\n\nconst LinkWrapper = styled.a<{ $typo: LinkTypo; $highlight: boolean }>(\n ({ $typo, $highlight, theme }) => css`\n ${focusOutline()}\n display: inline-flex;\n flex-direction: row;\n\n ${\n $typo === 'regular' &&\n css`\n font-size: 16px;\n line-height: 20px;\n `\n }\n\n ${\n $typo === 'small' &&\n css`\n font-size: 14px;\n line-height: 20px;\n `\n }\n\n font-weight: ${oldTheme.font.weight.medium};\n text-decoration: underline;\n color: ${\n $highlight ? theme.color.interactive.primary.base : theme.color.text.base\n };\n\n background: none;\n cursor: pointer;\n\n &:hover {\n color: ${theme.color.text.subtle};\n\n path {\n fill: ${theme.color.icon.subtle};\n }\n }\n\n &:active {\n color: ${theme.color.text.base};\n\n path {\n fill: ${theme.color.icon.subtle};\n }\n }\n `,\n)\n\n/**\n * Internal utility to override styling in other components (see Text)\n * @internal\n */\nexport const linkStyleOverride = ({ color }: { color: string }) => css`\n & ${LinkWrapper} {\n color: ${color};\n\n path {\n fill: ${color};\n }\n\n &:hover {\n color: ${darken(0.1, color)};\n\n path {\n fill: ${darken(0.1, color)};\n }\n }\n }\n`\n"]}
1
+ {"version":3,"file":"Link.js","sourceRoot":"","sources":["../../src/Link/Link.tsx"],"names":[],"mappings":"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","sourcesContent":["import { darken } from 'polished'\nimport { FC, MouseEventHandler, ReactNode } from 'react'\nimport styled, { css } from 'styled-components'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport { faArrowUpRightFromSquare } from '@awesome.me/kit-46ca99185c/icons/classic/regular'\n\nimport { Icon, Icons } from '../Icon'\nimport { theme as oldTheme } from '../theme'\nimport { focusOutline } from '../utils/focusOutline'\nimport { IconContainer } from '../sharedStyles/shared.styles'\n\ntype LinkTypo = 'regular' | 'small'\n\nconst ICON_SPACING = '4px'\n\nexport type LinkProps = {\n className?: string\n href: string\n onClick?: MouseEventHandler\n openInNewTab?: boolean\n children?: ReactNode\n download?: boolean\n typo?: LinkTypo\n highlight?: boolean\n iconToRender?: Icons\n iconComponent?: ReactNode\n isTrailingIcon?: boolean\n}\n\nexport const Link: FC<LinkProps> = ({\n className,\n href,\n onClick,\n openInNewTab,\n download,\n children,\n typo = 'regular',\n highlight = false,\n iconToRender: legacyIcon,\n iconComponent = !legacyIcon && openInNewTab ? (\n <FontAwesomeIcon icon={faArrowUpRightFromSquare} />\n ) : undefined,\n isTrailingIcon = true,\n}) => {\n // Icon-only links keep the icon flush\n const iconSpacing = children ? ICON_SPACING : '0'\n\n const iconToRender = iconComponent ? (\n <IconContainer\n $size={typo === 'regular' ? 16 : 12}\n style={{\n alignSelf: 'center',\n marginRight: isTrailingIcon ? '0' : iconSpacing,\n marginLeft: isTrailingIcon ? iconSpacing : '0',\n }}\n >\n {iconComponent}\n </IconContainer>\n ) : legacyIcon ? (\n <Icon\n mt={{ custom: '3px' }}\n {...(isTrailingIcon\n ? { ml: { custom: iconSpacing } }\n : { mr: { custom: iconSpacing } })}\n size={typo === 'regular' ? 14 : 12}\n render={legacyIcon}\n color={highlight ? 'color.interactive.primary.base' : 'color.text.base'}\n />\n ) : null\n\n return (\n <LinkWrapper\n href={href}\n className={className}\n onClick={onClick}\n download={download}\n $typo={typo}\n $highlight={highlight}\n {...(openInNewTab && {\n rel: 'noopener noreferrer',\n target: '_blank',\n })}\n >\n {!isTrailingIcon && iconToRender}\n {children}\n {isTrailingIcon && iconToRender}\n </LinkWrapper>\n )\n}\n\nconst LinkWrapper = styled.a<{ $typo: LinkTypo; $highlight: boolean }>(\n ({ $typo, $highlight, theme }) => css`\n ${focusOutline()}\n display: inline-flex;\n flex-direction: row;\n\n ${\n $typo === 'regular' &&\n css`\n font-size: 16px;\n line-height: 20px;\n `\n }\n\n ${\n $typo === 'small' &&\n css`\n font-size: 14px;\n line-height: 20px;\n `\n }\n\n font-weight: ${oldTheme.font.weight.medium};\n text-decoration: underline;\n color: ${\n $highlight ? theme.color.interactive.primary.base : theme.color.text.base\n };\n\n background: none;\n cursor: pointer;\n\n &:hover {\n color: ${theme.color.text.subtle};\n\n path {\n fill: ${theme.color.icon.subtle};\n }\n }\n\n &:active {\n color: ${theme.color.text.base};\n\n path {\n fill: ${theme.color.icon.subtle};\n }\n }\n `,\n)\n\n/**\n * Internal utility to override styling in other components (see Text)\n * @internal\n */\nexport const linkStyleOverride = ({ color }: { color: string }) => css`\n & ${LinkWrapper} {\n color: ${color};\n\n path {\n fill: ${color};\n }\n\n &:hover {\n color: ${darken(0.1, color)};\n\n path {\n fill: ${darken(0.1, color)};\n }\n }\n }\n`\n"]}
@@ -3,5 +3,7 @@ import { CommonFieldProps } from '../commonFieldTypes';
3
3
  export interface FieldProps extends CommonFieldProps {
4
4
  htmlFor?: string;
5
5
  children: ReactNode;
6
+ assistiveTextId?: string;
7
+ errorMsgId?: string;
6
8
  }
7
9
  export declare const Field: ({ children, ...fieldProps }: FieldProps) => import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"Field.js","sourceRoot":"","sources":["../../../src/fields/Field/Field.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAO3D,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAc,EAAE,EAAE;IAC/D,OAAO,CACL,KAAC,aAAa,IAAC,SAAS,EAAC,OAAO,KAAK,UAAU,YAC5C,QAAQ,GACK,CACjB,CAAA;AACH,CAAC,CAAA","sourcesContent":["import { ReactNode } from 'react'\n\nimport { CommonFieldProps } from '../commonFieldTypes'\nimport { InternalField } from '../components/InternalField'\n\nexport interface FieldProps extends CommonFieldProps {\n htmlFor?: string\n children: ReactNode\n}\n\nexport const Field = ({ children, ...fieldProps }: FieldProps) => {\n return (\n <InternalField fieldType=\"field\" {...fieldProps}>\n {children}\n </InternalField>\n )\n}\n"]}
1
+ {"version":3,"file":"Field.js","sourceRoot":"","sources":["../../../src/fields/Field/Field.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAS3D,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAc,EAAE,EAAE;IAC/D,OAAO,CACL,KAAC,aAAa,IAAC,SAAS,EAAC,OAAO,KAAK,UAAU,YAC5C,QAAQ,GACK,CACjB,CAAA;AACH,CAAC,CAAA","sourcesContent":["import { ReactNode } from 'react'\n\nimport { CommonFieldProps } from '../commonFieldTypes'\nimport { InternalField } from '../components/InternalField'\n\nexport interface FieldProps extends CommonFieldProps {\n htmlFor?: string\n children: ReactNode\n assistiveTextId?: string\n errorMsgId?: string\n}\n\nexport const Field = ({ children, ...fieldProps }: FieldProps) => {\n return (\n <InternalField fieldType=\"field\" {...fieldProps}>\n {children}\n </InternalField>\n )\n}\n"]}
@@ -5,6 +5,10 @@ interface InternalFieldProps extends CommonFieldProps {
5
5
  className?: string;
6
6
  htmlFor?: string;
7
7
  fieldType: 'field' | 'fieldset';
8
+ /** id for the assistive text, so a control can reference it with `aria-describedby` */
9
+ assistiveTextId?: string;
10
+ /** id for the error message, so a control can reference it with `aria-describedby` */
11
+ errorMsgId?: string;
8
12
  }
9
- export declare const InternalField: ({ children, fieldType, renderAsTitle, htmlFor, className, label, assistiveText, error, errorMsg, required, completed, ...marginProps }: InternalFieldProps) => import("react").JSX.Element;
13
+ export declare const InternalField: ({ children, fieldType, renderAsTitle, htmlFor, className, label, assistiveText, error, errorMsg, required, completed, assistiveTextId, errorMsgId, ...marginProps }: InternalFieldProps) => import("react").JSX.Element;
10
14
  export {};
@@ -3,12 +3,17 @@ import styled, { css } from 'styled-components';
3
3
  import { Box } from '../../Box';
4
4
  import { Icon } from '../../Icon';
5
5
  import { Text } from '../../Text';
6
- export const InternalField = ({ children, fieldType, renderAsTitle, htmlFor, className, label, assistiveText, error, errorMsg, required, completed, ...marginProps }) => {
6
+ import { markPointerFocus } from './fieldStyles';
7
+ export const InternalField = ({ children, fieldType, renderAsTitle, htmlFor, className, label, assistiveText, error, errorMsg, required, completed, assistiveTextId, errorMsgId, ...marginProps }) => {
7
8
  const labelTag = fieldType === 'field' ? 'label' : 'legend';
9
+ // Clicking a label focuses its field, which shouldn't show the focus ring.
10
+ const handleLabelPointerDown = htmlFor
11
+ ? () => markPointerFocus(document.getElementById(htmlFor))
12
+ : undefined;
8
13
  const textColor = error ? 'color.feedback.negative.200' : 'color.text.subtle';
9
- return (_jsxs(Container, { forwardedAs: fieldType === 'field' ? 'div' : 'fieldset', className: className, ...marginProps, children: [label && (_jsx(_Fragment, { children: renderAsTitle ? (_jsxs(Box, { mb: "space.200", children: [_jsx(Text, { tag: labelTag, typo: "heading-small", htmlFor: htmlFor, children: label }), assistiveText && (_jsx(Text, { tag: "p", color: "sesame", mt: "space.050", children: assistiveText }))] })) : (_jsxs(Text, { tag: labelTag, typo: "label", color: textColor, htmlFor: htmlFor, mb: "space.050", children: [label, required && (_jsx(Text, { tag: "span", typo: "body-small", color: "color.feedback.negative.200", children: "*" }))] })) })), _jsx(Box, { children: children }), fieldType === 'field' && assistiveText && !renderAsTitle && (_jsx(Text, { tag: labelTag, typo: "caption", color: textColor, mt: "space.050", children: assistiveText })), error &&
14
+ return (_jsxs(Container, { forwardedAs: fieldType === 'field' ? 'div' : 'fieldset', className: className, ...marginProps, children: [label && (_jsx(_Fragment, { children: renderAsTitle ? (_jsxs(Box, { mb: "space.200", children: [_jsx(Text, { tag: labelTag, typo: "heading-small", htmlFor: htmlFor, onPointerDown: handleLabelPointerDown, children: label }), assistiveText && (_jsx(Text, { tag: "p", color: "color.text.subtle", mt: "space.050", id: assistiveTextId, children: assistiveText }))] })) : (_jsxs(Text, { tag: labelTag, typo: "label", color: textColor, htmlFor: htmlFor, onPointerDown: handleLabelPointerDown, mb: "space.050", children: [label, required && (_jsx(Text, { tag: "span", typo: "body-small", color: "color.feedback.negative.200", children: "*" }))] })) })), _jsx(Box, { children: children }), fieldType === 'field' && assistiveText && !renderAsTitle && (_jsx(Text, { tag: labelTag, typo: "caption", color: textColor, mt: "space.050", id: assistiveTextId, children: assistiveText })), error &&
10
15
  errorMsg &&
11
- (typeof errorMsg === 'string' ? (_jsxs(Box, { flex: true, alignItems: "center", mt: "space.100", gap: "space.050", children: [_jsx(Icon, { render: "warning", size: 16, color: "color.feedback.negative.200" }), _jsx(Text, { tag: "span", typo: "caption", color: "color.feedback.negative.200", children: errorMsg })] })) : (_jsx(Box, { mt: "space.100", children: errorMsg }))), completed !== undefined && (_jsx(AnimationWrapper, { $displayStatus: completed, $isError: !!(error && errorMsg), children: _jsxs(StatusWrapper, { mt: 'space.100', children: [_jsx(Icon, { render: "included", size: 16, color: "color.feedback.positive.200" }), _jsx(Text, { typo: "caption", color: "color.feedback.positive.200", children: "Complete" })] }) }))] }));
16
+ (typeof errorMsg === 'string' ? (_jsxs(Box, { flex: true, alignItems: "center", mt: "space.100", gap: "space.050", id: errorMsgId, children: [_jsx(Icon, { render: "warning", size: 16, color: "color.feedback.negative.200" }), _jsx(Text, { tag: "span", typo: "caption", color: "color.feedback.negative.200", children: errorMsg })] })) : (_jsx(Box, { mt: "space.100", id: errorMsgId, children: errorMsg }))), completed !== undefined && (_jsx(AnimationWrapper, { $displayStatus: completed, $isError: !!(error && errorMsg), children: _jsxs(StatusWrapper, { mt: 'space.100', children: [_jsx(Icon, { render: "included", size: 16, color: "color.feedback.positive.200" }), _jsx(Text, { typo: "caption", color: "color.feedback.positive.200", children: "Complete" })] }) }))] }));
12
17
  };
13
18
  const AnimationWrapper = styled(Box) `
14
19
  width: 0;
@@ -1 +1 @@
1
- {"version":3,"file":"InternalField.js","sourceRoot":"","sources":["../../../src/fields/components/InternalField.tsx"],"names":[],"mappings":"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","sourcesContent":["import { ReactNode } from 'react'\nimport styled, { css } from 'styled-components'\n\nimport { Box } from '../../Box'\nimport { Icon } from '../../Icon'\nimport { Text } from '../../Text'\nimport { CommonFieldProps } from '../commonFieldTypes'\n\ninterface InternalFieldProps extends CommonFieldProps {\n children: ReactNode\n className?: string\n htmlFor?: string\n fieldType: 'field' | 'fieldset'\n}\n\nexport const InternalField = ({\n children,\n fieldType,\n renderAsTitle,\n htmlFor,\n className,\n label,\n assistiveText,\n error,\n errorMsg,\n required,\n completed,\n ...marginProps\n}: InternalFieldProps) => {\n const labelTag = fieldType === 'field' ? 'label' : 'legend'\n\n const textColor = error ? 'color.feedback.negative.200' : 'color.text.subtle'\n return (\n <Container\n forwardedAs={fieldType === 'field' ? 'div' : 'fieldset'}\n className={className}\n {...marginProps}\n >\n {label && (\n <>\n {renderAsTitle ? (\n <Box mb=\"space.200\">\n <Text tag={labelTag} typo=\"heading-small\" htmlFor={htmlFor}>\n {label}\n </Text>\n\n {assistiveText && (\n <Text tag=\"p\" color=\"sesame\" mt=\"space.050\">\n {assistiveText}\n </Text>\n )}\n </Box>\n ) : (\n <Text\n tag={labelTag}\n typo=\"label\"\n color={textColor}\n htmlFor={htmlFor}\n mb=\"space.050\"\n >\n {label}\n {required && (\n <Text\n tag=\"span\"\n typo=\"body-small\"\n color=\"color.feedback.negative.200\"\n >\n *\n </Text>\n )}\n </Text>\n )}\n </>\n )}\n\n <Box>{children}</Box>\n {fieldType === 'field' && assistiveText && !renderAsTitle && (\n <Text tag={labelTag} typo=\"caption\" color={textColor} mt=\"space.050\">\n {assistiveText}\n </Text>\n )}\n\n {error &&\n errorMsg &&\n (typeof errorMsg === 'string' ? (\n <Box flex alignItems=\"center\" mt=\"space.100\" gap=\"space.050\">\n <Icon\n render=\"warning\"\n size={16}\n color=\"color.feedback.negative.200\"\n />\n <Text tag=\"span\" typo=\"caption\" color=\"color.feedback.negative.200\">\n {errorMsg}\n </Text>\n </Box>\n ) : (\n <Box mt=\"space.100\">{errorMsg}</Box>\n ))}\n\n {/* When completed is false, whitespace is rendered */}\n {completed !== undefined && (\n <AnimationWrapper\n $displayStatus={completed}\n $isError={!!(error && errorMsg)}\n >\n <StatusWrapper mt={'space.100'}>\n <Icon\n render=\"included\"\n size={16}\n color=\"color.feedback.positive.200\"\n />\n <Text typo=\"caption\" color=\"color.feedback.positive.200\">\n Complete\n </Text>\n </StatusWrapper>\n </AnimationWrapper>\n )}\n </Container>\n )\n}\n\nconst AnimationWrapper = styled(Box)<{\n $displayStatus: boolean\n $isError: boolean\n}>`\n width: 0;\n overflow: hidden;\n\n ${({ $displayStatus }) =>\n $displayStatus &&\n css`\n transition: width 0.6s ease-in;\n width: 100%;\n `}\n\n /* This enables animation to appear when previous state is error */\n ${({ $isError }) =>\n $isError &&\n css`\n height: 0;\n `}\n`\n\nconst StatusWrapper = styled(Box)`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.space['050']};\n`\n\nconst Container = styled(Box)`\n display: flex;\n flex-direction: column;\n position: relative;\n width: 100%;\n\n // In case, the element is a 'fieldset', we remove the border\n border: 0;\n`\n"]}
1
+ {"version":3,"file":"InternalField.js","sourceRoot":"","sources":["../../../src/fields/components/InternalField.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAahD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,aAAa,EACb,OAAO,EACP,SAAS,EACT,KAAK,EACL,aAAa,EACb,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,eAAe,EACf,UAAU,EACV,GAAG,WAAW,EACK,EAAE,EAAE;IACvB,MAAM,QAAQ,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAA;IAC3D,2EAA2E;IAC3E,MAAM,sBAAsB,GAAG,OAAO;QACpC,CAAC,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC1D,CAAC,CAAC,SAAS,CAAA;IAEb,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,mBAAmB,CAAA;IAC7E,OAAO,CACL,MAAC,SAAS,IACR,WAAW,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,EACvD,SAAS,EAAE,SAAS,KAChB,WAAW,aAEd,KAAK,IAAI,CACR,4BACG,aAAa,CAAC,CAAC,CAAC,CACf,MAAC,GAAG,IAAC,EAAE,EAAC,WAAW,aACjB,KAAC,IAAI,IACH,GAAG,EAAE,QAAQ,EACb,IAAI,EAAC,eAAe,EACpB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,sBAAsB,YAEpC,KAAK,GACD,EAEN,aAAa,IAAI,CAChB,KAAC,IAAI,IACH,GAAG,EAAC,GAAG,EACP,KAAK,EAAC,mBAAmB,EACzB,EAAE,EAAC,WAAW,EACd,EAAE,EAAE,eAAe,YAElB,aAAa,GACT,CACR,IACG,CACP,CAAC,CAAC,CAAC,CACF,MAAC,IAAI,IACH,GAAG,EAAE,QAAQ,EACb,IAAI,EAAC,OAAO,EACZ,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,sBAAsB,EACrC,EAAE,EAAC,WAAW,aAEb,KAAK,EACL,QAAQ,IAAI,CACX,KAAC,IAAI,IACH,GAAG,EAAC,MAAM,EACV,IAAI,EAAC,YAAY,EACjB,KAAK,EAAC,6BAA6B,kBAG9B,CACR,IACI,CACR,GACA,CACJ,EAED,KAAC,GAAG,cAAE,QAAQ,GAAO,EACpB,SAAS,KAAK,OAAO,IAAI,aAAa,IAAI,CAAC,aAAa,IAAI,CAC3D,KAAC,IAAI,IACH,GAAG,EAAE,QAAQ,EACb,IAAI,EAAC,SAAS,EACd,KAAK,EAAE,SAAS,EAChB,EAAE,EAAC,WAAW,EACd,EAAE,EAAE,eAAe,YAElB,aAAa,GACT,CACR,EAEA,KAAK;gBACJ,QAAQ;gBACR,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAC9B,MAAC,GAAG,IACF,IAAI,QACJ,UAAU,EAAC,QAAQ,EACnB,EAAE,EAAC,WAAW,EACd,GAAG,EAAC,WAAW,EACf,EAAE,EAAE,UAAU,aAEd,KAAC,IAAI,IACH,MAAM,EAAC,SAAS,EAChB,IAAI,EAAE,EAAE,EACR,KAAK,EAAC,6BAA6B,GACnC,EACF,KAAC,IAAI,IAAC,GAAG,EAAC,MAAM,EAAC,IAAI,EAAC,SAAS,EAAC,KAAK,EAAC,6BAA6B,YAChE,QAAQ,GACJ,IACH,CACP,CAAC,CAAC,CAAC,CACF,KAAC,GAAG,IAAC,EAAE,EAAC,WAAW,EAAC,EAAE,EAAE,UAAU,YAC/B,QAAQ,GACL,CACP,CAAC,EAGH,SAAS,KAAK,SAAS,IAAI,CAC1B,KAAC,gBAAgB,IACf,cAAc,EAAE,SAAS,EACzB,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,QAAQ,CAAC,YAE/B,MAAC,aAAa,IAAC,EAAE,EAAE,WAAW,aAC5B,KAAC,IAAI,IACH,MAAM,EAAC,UAAU,EACjB,IAAI,EAAE,EAAE,EACR,KAAK,EAAC,6BAA6B,GACnC,EACF,KAAC,IAAI,IAAC,IAAI,EAAC,SAAS,EAAC,KAAK,EAAC,6BAA6B,yBAEjD,IACO,GACC,CACpB,IACS,CACb,CAAA;AACH,CAAC,CAAA;AAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,CAGlC;;;;IAIE,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CACvB,cAAc;IACd,GAAG,CAAA;;;KAGF;;;IAGD,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CACjB,QAAQ;IACR,GAAG,CAAA;;KAEF;CACJ,CAAA;AAED,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;;;SAGxB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;CACzC,CAAA;AAED,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;;;;;;;;CAQ5B,CAAA","sourcesContent":["import { ReactNode } from 'react'\nimport styled, { css } from 'styled-components'\n\nimport { Box } from '../../Box'\nimport { Icon } from '../../Icon'\nimport { Text } from '../../Text'\nimport { CommonFieldProps } from '../commonFieldTypes'\nimport { markPointerFocus } from './fieldStyles'\n\ninterface InternalFieldProps extends CommonFieldProps {\n children: ReactNode\n className?: string\n htmlFor?: string\n fieldType: 'field' | 'fieldset'\n /** id for the assistive text, so a control can reference it with `aria-describedby` */\n assistiveTextId?: string\n /** id for the error message, so a control can reference it with `aria-describedby` */\n errorMsgId?: string\n}\n\nexport const InternalField = ({\n children,\n fieldType,\n renderAsTitle,\n htmlFor,\n className,\n label,\n assistiveText,\n error,\n errorMsg,\n required,\n completed,\n assistiveTextId,\n errorMsgId,\n ...marginProps\n}: InternalFieldProps) => {\n const labelTag = fieldType === 'field' ? 'label' : 'legend'\n // Clicking a label focuses its field, which shouldn't show the focus ring.\n const handleLabelPointerDown = htmlFor\n ? () => markPointerFocus(document.getElementById(htmlFor))\n : undefined\n\n const textColor = error ? 'color.feedback.negative.200' : 'color.text.subtle'\n return (\n <Container\n forwardedAs={fieldType === 'field' ? 'div' : 'fieldset'}\n className={className}\n {...marginProps}\n >\n {label && (\n <>\n {renderAsTitle ? (\n <Box mb=\"space.200\">\n <Text\n tag={labelTag}\n typo=\"heading-small\"\n htmlFor={htmlFor}\n onPointerDown={handleLabelPointerDown}\n >\n {label}\n </Text>\n\n {assistiveText && (\n <Text\n tag=\"p\"\n color=\"color.text.subtle\"\n mt=\"space.050\"\n id={assistiveTextId}\n >\n {assistiveText}\n </Text>\n )}\n </Box>\n ) : (\n <Text\n tag={labelTag}\n typo=\"label\"\n color={textColor}\n htmlFor={htmlFor}\n onPointerDown={handleLabelPointerDown}\n mb=\"space.050\"\n >\n {label}\n {required && (\n <Text\n tag=\"span\"\n typo=\"body-small\"\n color=\"color.feedback.negative.200\"\n >\n *\n </Text>\n )}\n </Text>\n )}\n </>\n )}\n\n <Box>{children}</Box>\n {fieldType === 'field' && assistiveText && !renderAsTitle && (\n <Text\n tag={labelTag}\n typo=\"caption\"\n color={textColor}\n mt=\"space.050\"\n id={assistiveTextId}\n >\n {assistiveText}\n </Text>\n )}\n\n {error &&\n errorMsg &&\n (typeof errorMsg === 'string' ? (\n <Box\n flex\n alignItems=\"center\"\n mt=\"space.100\"\n gap=\"space.050\"\n id={errorMsgId}\n >\n <Icon\n render=\"warning\"\n size={16}\n color=\"color.feedback.negative.200\"\n />\n <Text tag=\"span\" typo=\"caption\" color=\"color.feedback.negative.200\">\n {errorMsg}\n </Text>\n </Box>\n ) : (\n <Box mt=\"space.100\" id={errorMsgId}>\n {errorMsg}\n </Box>\n ))}\n\n {/* When completed is false, whitespace is rendered */}\n {completed !== undefined && (\n <AnimationWrapper\n $displayStatus={completed}\n $isError={!!(error && errorMsg)}\n >\n <StatusWrapper mt={'space.100'}>\n <Icon\n render=\"included\"\n size={16}\n color=\"color.feedback.positive.200\"\n />\n <Text typo=\"caption\" color=\"color.feedback.positive.200\">\n Complete\n </Text>\n </StatusWrapper>\n </AnimationWrapper>\n )}\n </Container>\n )\n}\n\nconst AnimationWrapper = styled(Box)<{\n $displayStatus: boolean\n $isError: boolean\n}>`\n width: 0;\n overflow: hidden;\n\n ${({ $displayStatus }) =>\n $displayStatus &&\n css`\n transition: width 0.6s ease-in;\n width: 100%;\n `}\n\n /* This enables animation to appear when previous state is error */\n ${({ $isError }) =>\n $isError &&\n css`\n height: 0;\n `}\n`\n\nconst StatusWrapper = styled(Box)`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.space['050']};\n`\n\nconst Container = styled(Box)`\n display: flex;\n flex-direction: column;\n position: relative;\n width: 100%;\n\n // In case, the element is a 'fieldset', we remove the border\n border: 0;\n`\n"]}
@@ -0,0 +1,17 @@
1
+ import { FocusEvent, FocusEventHandler, PointerEvent, PointerEventHandler } from 'react';
2
+ /**
3
+ * Browsers treat text fields as `:focus-visible` even when they are clicked,
4
+ * so fields flag focus that comes from a pointer and only show the focus ring
5
+ * for keyboard focus.
6
+ */
7
+ export declare const markPointerFocus: (element: HTMLElement | null) => void;
8
+ /** Pass to styled-components `.attrs`. Callers' own handlers still run. */
9
+ export declare const fieldFocusAttrs: <T extends HTMLElement>({ onPointerDown, onBlurCapture, }: {
10
+ onPointerDown?: PointerEventHandler<T>;
11
+ onBlurCapture?: FocusEventHandler<T>;
12
+ }) => {
13
+ onPointerDown: (event: PointerEvent<T>) => void;
14
+ onBlurCapture: (event: FocusEvent<T>) => void;
15
+ };
16
+ export declare const fieldFocusRing: import("styled-components").RuleSet<object>;
17
+ export declare const fieldDisabledStyle: import("styled-components").RuleSet<object>;
@@ -0,0 +1,39 @@
1
+ import { css } from 'styled-components';
2
+ /**
3
+ * Browsers treat text fields as `:focus-visible` even when they are clicked,
4
+ * so fields flag focus that comes from a pointer and only show the focus ring
5
+ * for keyboard focus.
6
+ */
7
+ export const markPointerFocus = (element) => {
8
+ if (element)
9
+ element.dataset.pointerFocus = '';
10
+ };
11
+ /** Pass to styled-components `.attrs`. Callers' own handlers still run. */
12
+ export const fieldFocusAttrs = ({ onPointerDown, onBlurCapture, }) => ({
13
+ onPointerDown: (event) => {
14
+ markPointerFocus(event.currentTarget);
15
+ onPointerDown?.(event);
16
+ },
17
+ onBlurCapture: (event) => {
18
+ delete event.currentTarget.dataset.pointerFocus;
19
+ onBlurCapture?.(event);
20
+ },
21
+ });
22
+ export const fieldFocusRing = css `
23
+ &:focus-visible:not([data-pointer-focus]) {
24
+ outline: 2px solid ${({ theme }) => theme.color.focus.onLight};
25
+ outline-offset: 2px;
26
+ }
27
+ `;
28
+ export const fieldDisabledStyle = css `
29
+ &:disabled {
30
+ border-color: ${({ theme }) => theme.color.feedback.inactive[100]};
31
+ background-color: ${({ theme }) => theme.color.feedback.inactive[50]};
32
+ color: ${({ theme }) => theme.color.text.subtle};
33
+ cursor: not-allowed;
34
+ /* Safari fades disabled fields on top of these colours */
35
+ opacity: 1;
36
+ -webkit-text-fill-color: currentColor;
37
+ }
38
+ `;
39
+ //# sourceMappingURL=fieldStyles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldStyles.js","sourceRoot":"","sources":["../../../src/fields/components/fieldStyles.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAA2B,EAAE,EAAE;IAC9D,IAAI,OAAO;QAAE,OAAO,CAAC,OAAO,CAAC,YAAY,GAAG,EAAE,CAAA;AAChD,CAAC,CAAA;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,eAAe,GAAG,CAAwB,EACrD,aAAa,EACb,aAAa,GAId,EAAE,EAAE,CAAC,CAAC;IACL,aAAa,EAAE,CAAC,KAAsB,EAAE,EAAE;QACxC,gBAAgB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;QACrC,aAAa,EAAE,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IACD,aAAa,EAAE,CAAC,KAAoB,EAAE,EAAE;QACtC,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,CAAA;QAC/C,aAAa,EAAE,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;CACF,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAA;;yBAER,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO;;;CAGhE,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAA;;oBAEjB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;wBAC7C,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;aAC3D,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM;;;;;;CAMlD,CAAA","sourcesContent":["import {\n FocusEvent,\n FocusEventHandler,\n PointerEvent,\n PointerEventHandler,\n} from 'react'\nimport { css } from 'styled-components'\n\n/**\n * Browsers treat text fields as `:focus-visible` even when they are clicked,\n * so fields flag focus that comes from a pointer and only show the focus ring\n * for keyboard focus.\n */\nexport const markPointerFocus = (element: HTMLElement | null) => {\n if (element) element.dataset.pointerFocus = ''\n}\n\n/** Pass to styled-components `.attrs`. Callers' own handlers still run. */\nexport const fieldFocusAttrs = <T extends HTMLElement>({\n onPointerDown,\n onBlurCapture,\n}: {\n onPointerDown?: PointerEventHandler<T>\n onBlurCapture?: FocusEventHandler<T>\n}) => ({\n onPointerDown: (event: PointerEvent<T>) => {\n markPointerFocus(event.currentTarget)\n onPointerDown?.(event)\n },\n onBlurCapture: (event: FocusEvent<T>) => {\n delete event.currentTarget.dataset.pointerFocus\n onBlurCapture?.(event)\n },\n})\n\nexport const fieldFocusRing = css`\n &:focus-visible:not([data-pointer-focus]) {\n outline: 2px solid ${({ theme }) => theme.color.focus.onLight};\n outline-offset: 2px;\n }\n`\n\nexport const fieldDisabledStyle = css`\n &:disabled {\n border-color: ${({ theme }) => theme.color.feedback.inactive[100]};\n background-color: ${({ theme }) => theme.color.feedback.inactive[50]};\n color: ${({ theme }) => theme.color.text.subtle};\n cursor: not-allowed;\n /* Safari fades disabled fields on top of these colours */\n opacity: 1;\n -webkit-text-fill-color: currentColor;\n }\n`\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrshmllw/smores-react",
3
- "version": "16.3.1",
3
+ "version": "16.5.0",
4
4
  "description": "Collection of React components used by Marshmallow Technology",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",