polpo 0.1.1 → 0.1.2
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/.storybook/theme.ts +2 -2
- package/.turbo/turbo-lint.log +1 -1
- package/README.md +2 -5
- package/dist/chunk-CFYQBHH5.js +3 -0
- package/dist/chunk-CFYQBHH5.js.map +1 -0
- package/dist/chunk-MAWW6AA7.js +3 -0
- package/dist/chunk-MAWW6AA7.js.map +1 -0
- package/dist/get-modal-position-drle0OjP.d.cts +49 -0
- package/dist/get-modal-position-drle0OjP.d.ts +49 -0
- package/dist/helpers.cjs +1 -1
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +9 -2
- package/dist/helpers.d.ts +9 -2
- package/dist/helpers.js +1 -1
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +59 -21
- package/dist/hooks.d.ts +59 -21
- package/dist/hooks.js +1 -1
- package/dist/ui.cjs +601 -389
- package/dist/ui.cjs.map +1 -1
- package/dist/ui.d.cts +97 -77
- package/dist/ui.d.ts +97 -77
- package/dist/ui.js +585 -373
- package/dist/ui.js.map +1 -1
- package/dist/use-modal-in-container-DiNW1PE_.d.cts +34 -0
- package/dist/use-modal-in-container-neGo-kMk.d.ts +34 -0
- package/package.json +2 -2
- package/src/components/buttons/button/button.stories.tsx +4 -4
- package/src/components/buttons/button/button.style.ts +10 -5
- package/src/components/buttons/button/button.tsx +7 -19
- package/src/components/cards/flip-card/flip-card.tsx +1 -1
- package/src/components/cursor/cursor.stories.tsx +35 -0
- package/src/components/cursor/cursor.style.ts +73 -0
- package/src/components/cursor/cursor.tsx +49 -0
- package/src/components/cursor/index.ts +1 -0
- package/src/components/form/checkbox/checkbox.stories.tsx +51 -0
- package/src/components/form/checkbox/checkbox.style.ts +73 -37
- package/src/components/form/checkbox/checkbox.tsx +38 -4
- package/src/components/form/field/field.stories.tsx +5 -1
- package/src/components/form/field/field.style.ts +12 -0
- package/src/components/form/field/field.tsx +3 -1
- package/src/components/form/field/field.types.ts +6 -0
- package/src/components/form/input-color/input-color.style.ts +5 -4
- package/src/components/form/input-color/input-color.tsx +41 -44
- package/src/components/form/radio/radio.stories.tsx +29 -5
- package/src/components/form/radio/radio.style.ts +45 -24
- package/src/components/form/radio/radio.tsx +22 -3
- package/src/components/form/select/options.tsx +119 -67
- package/src/components/form/select/select.stories.tsx +103 -42
- package/src/components/form/select/select.style.ts +10 -92
- package/src/components/form/select/select.tsx +19 -42
- package/src/components/form/select/select.types.ts +4 -21
- package/src/components/form/slider/slider.style.ts +2 -0
- package/src/components/icon/icons/social.tsx +17 -1
- package/src/components/index.ts +1 -0
- package/src/components/infinity-scroll/infinity-scroll.tsx +1 -1
- package/src/components/line/line.stories.tsx +3 -4
- package/src/components/modals/action-modal/action-modal.stories.tsx +58 -39
- package/src/components/modals/action-modal/action-modal.style.ts +13 -25
- package/src/components/modals/action-modal/action-modal.tsx +68 -70
- package/src/components/modals/aside-modal/aside-modal.stories.tsx +11 -15
- package/src/components/modals/aside-modal/aside-modal.style.ts +17 -37
- package/src/components/modals/aside-modal/aside-modal.tsx +41 -43
- package/src/components/modals/confirmation-modal/confirmation-modal.stories.tsx +21 -9
- package/src/components/modals/index.ts +2 -0
- package/src/components/modals/menu/index.ts +1 -0
- package/src/components/modals/menu/menu.stories.tsx +69 -0
- package/src/components/modals/menu/menu.style.ts +62 -0
- package/src/components/modals/menu/menu.tsx +142 -0
- package/src/components/modals/modal/backdrop.tsx +70 -0
- package/src/components/modals/modal/index.ts +1 -0
- package/src/components/modals/modal/modal.stories.tsx +325 -0
- package/src/components/modals/modal/modal.style.ts +62 -2
- package/src/components/modals/modal/modal.tsx +82 -123
- package/src/components/modals/portal/index.ts +1 -0
- package/src/components/modals/portal/portal.tsx +18 -0
- package/src/components/tabs/tabs-list.tsx +13 -10
- package/src/components/tabs/tabs.style.ts +48 -43
- package/src/components/tag/tag.stories.tsx +11 -12
- package/src/components/tag/tag.style.ts +9 -4
- package/src/components/tag/tag.tsx +2 -12
- package/src/components/tooltips/tooltip/tooltip.stories.tsx +5 -2
- package/src/components/tooltips/tooltip/tooltip.style.ts +37 -6
- package/src/components/tooltips/tooltip/tooltip.tsx +33 -19
- package/src/components/typography/typography.stories.tsx +3 -1
- package/src/components/typography/typography.tsx +21 -0
- package/src/contexts/theme-context/theme.animations.ts +91 -2
- package/src/contexts/theme-context/theme.defaults.ts +1 -1
- package/src/core/http-client.ts +49 -47
- package/src/core/variants/color.ts +3 -30
- package/src/core/variants/radius.ts +12 -41
- package/src/core/variants/size.ts +8 -33
- package/src/helpers/get-modal-position-relative-to-screen.ts +86 -0
- package/src/helpers/get-modal-position.ts +173 -28
- package/src/helpers/index.ts +1 -0
- package/src/hooks/index.ts +9 -3
- package/src/hooks/use-click-outside.ts +32 -0
- package/src/hooks/use-cookie.ts +124 -0
- package/src/hooks/use-dimensions.ts +11 -14
- package/src/hooks/use-dom-container.ts +32 -0
- package/src/hooks/use-event-listener.ts +4 -4
- package/src/hooks/use-geolocation.ts +63 -0
- package/src/hooks/use-in-view.ts +9 -11
- package/src/hooks/use-intersection-observer.ts +19 -0
- package/src/hooks/use-modal-in-container.ts +60 -52
- package/src/hooks/use-modal-transition.ts +54 -0
- package/src/hooks/use-modal.ts +21 -0
- package/src/hooks/use-mouse-position.ts +55 -7
- package/src/hooks/use-resize-observer.ts +18 -0
- package/src/stories/GettingStarted.mdx +2 -6
- package/svg/Name=npm, Category=social.svg +3 -0
- package/dist/chunk-M4KRSYE7.js +0 -3
- package/dist/chunk-M4KRSYE7.js.map +0 -1
- package/dist/chunk-U5XSMSKZ.js +0 -3
- package/dist/chunk-U5XSMSKZ.js.map +0 -1
- package/dist/get-modal-position-DPftPoU2.d.cts +0 -28
- package/dist/get-modal-position-DPftPoU2.d.ts +0 -28
- package/src/components/form/select/select-option.tsx +0 -84
- package/src/hooks/use-observer.ts +0 -18
- package/src/hooks/use-on-click-outside-ref.ts +0 -17
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
+
import { DefaultTheme, useTheme } from 'styled-components';
|
|
2
3
|
|
|
4
|
+
import { ColorVariants } from '../../../core/variants';
|
|
3
5
|
import { Icon, IconNameT } from '../../icon';
|
|
4
6
|
import { Typography } from '../../typography';
|
|
5
7
|
import { Controller } from '../controller';
|
|
6
8
|
import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
|
|
7
9
|
|
|
8
|
-
import { CheckboxContainerStyle, CheckboxStyle } from './checkbox.style';
|
|
10
|
+
import { CheckboxContainerStyle, CheckboxFillStyle, CheckboxStyle } from './checkbox.style';
|
|
9
11
|
|
|
10
12
|
import { useInputHandlers } from '@polpo/hooks';
|
|
11
13
|
|
|
14
|
+
type CheckboxColor = {
|
|
15
|
+
color: string;
|
|
16
|
+
colorIcon: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const getCheckboxColor = (theme: DefaultTheme, color: `${ColorVariants}`): CheckboxColor => {
|
|
20
|
+
const checkboxColors: Record<ColorVariants, CheckboxColor> = {
|
|
21
|
+
[ColorVariants.Primary]: { color: theme.colors.primary.main, colorIcon: theme.colors.primary.contrast },
|
|
22
|
+
[ColorVariants.Secondary]: { color: theme.colors.secondary.main, colorIcon: theme.colors.secondary.contrast },
|
|
23
|
+
[ColorVariants.Tertiary]: { color: theme.colors.tertiary.main, colorIcon: theme.colors.tertiary.contrast },
|
|
24
|
+
[ColorVariants.Info]: { color: theme.colors.info.main, colorIcon: theme.colors.info.contrast },
|
|
25
|
+
[ColorVariants.Active]: { color: theme.colors.active.main, colorIcon: theme.colors.active.contrast },
|
|
26
|
+
[ColorVariants.Warning]: { color: theme.colors.warning.main, colorIcon: theme.colors.warning.contrast },
|
|
27
|
+
[ColorVariants.Alert]: { color: theme.colors.alert.main, colorIcon: theme.colors.alert.contrast },
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return checkboxColors[color] ?? checkboxColors[ColorVariants.Primary];
|
|
31
|
+
};
|
|
32
|
+
|
|
12
33
|
type CheckboxProps = {
|
|
13
|
-
label?:
|
|
34
|
+
label?: React.ReactNode;
|
|
14
35
|
placeholder?: never;
|
|
15
36
|
icon?: IconNameT;
|
|
37
|
+
color?: `${ColorVariants}`;
|
|
16
38
|
};
|
|
17
39
|
|
|
18
40
|
export const Checkbox = ({
|
|
@@ -29,6 +51,7 @@ export const Checkbox = ({
|
|
|
29
51
|
autoComplete = 'off',
|
|
30
52
|
icon = 'checkmark',
|
|
31
53
|
label,
|
|
54
|
+
color = ColorVariants.Primary,
|
|
32
55
|
/*
|
|
33
56
|
* isDirty = false,
|
|
34
57
|
* isTouched = false,
|
|
@@ -36,6 +59,7 @@ export const Checkbox = ({
|
|
|
36
59
|
* error,
|
|
37
60
|
*/
|
|
38
61
|
}: UnControlledComponentProps<CheckboxProps, boolean>) => {
|
|
62
|
+
const theme = useTheme();
|
|
39
63
|
const id = useMemo(() => crypto.randomUUID(), []);
|
|
40
64
|
const { handlers } = useInputHandlers<HTMLInputElement>({
|
|
41
65
|
onChange: e => setValue(e.target.checked),
|
|
@@ -43,10 +67,20 @@ export const Checkbox = ({
|
|
|
43
67
|
onFocus: onFocus,
|
|
44
68
|
});
|
|
45
69
|
|
|
70
|
+
const checkboxColor = getCheckboxColor(theme, color);
|
|
71
|
+
|
|
46
72
|
return (
|
|
47
|
-
<CheckboxContainerStyle
|
|
73
|
+
<CheckboxContainerStyle
|
|
74
|
+
$color={checkboxColor.color}
|
|
75
|
+
$colorIcon={checkboxColor.colorIcon}
|
|
76
|
+
className={className}
|
|
77
|
+
style={style}
|
|
78
|
+
onClick={e => e.stopPropagation()}
|
|
79
|
+
>
|
|
48
80
|
<CheckboxStyle className={value ? 'is-checked' : ''}>
|
|
49
|
-
<
|
|
81
|
+
<CheckboxFillStyle>
|
|
82
|
+
<Icon name={icon} className='checkbox-icon' />
|
|
83
|
+
</CheckboxFillStyle>
|
|
50
84
|
<input
|
|
51
85
|
id={id}
|
|
52
86
|
type='checkbox'
|
|
@@ -3,6 +3,8 @@ import { ContainerDecorator } from '../form.stories.types';
|
|
|
3
3
|
|
|
4
4
|
import { Field } from './field';
|
|
5
5
|
|
|
6
|
+
import { FieldOrientation, FieldVariant } from '@polpo/ui';
|
|
7
|
+
|
|
6
8
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
7
9
|
|
|
8
10
|
export const FieldSharedArgTypes: Meta<typeof Field>['argTypes'] = {
|
|
@@ -10,7 +12,8 @@ export const FieldSharedArgTypes: Meta<typeof Field>['argTypes'] = {
|
|
|
10
12
|
rightIcon: { options: [undefined, ...IconNames.toSorted()] },
|
|
11
13
|
leftIcon: { options: [undefined, ...IconNames.toSorted()] },
|
|
12
14
|
errorIcon: { options: [undefined, ...IconNames.toSorted()] },
|
|
13
|
-
|
|
15
|
+
fieldOrientation: { control: 'inline-radio', options: Object.values(FieldOrientation) },
|
|
16
|
+
variant: { control: 'select', options: [undefined, ...Object.values(FieldVariant)] },
|
|
14
17
|
};
|
|
15
18
|
|
|
16
19
|
export const FieldSharedArgs: StoryObj<typeof Field>['args'] = {
|
|
@@ -37,6 +40,7 @@ const meta: Meta<typeof Field> = {
|
|
|
37
40
|
...FieldSharedArgs,
|
|
38
41
|
leftIcon: 'facebook',
|
|
39
42
|
rightIcon: 'airplane',
|
|
43
|
+
fieldOrientation: 'vertical',
|
|
40
44
|
},
|
|
41
45
|
decorators: [ContainerDecorator],
|
|
42
46
|
};
|
|
@@ -2,7 +2,9 @@ import styled from 'styled-components';
|
|
|
2
2
|
|
|
3
3
|
export const FieldStyle = styled.section`
|
|
4
4
|
display: grid;
|
|
5
|
+
grid-auto-columns: auto;
|
|
5
6
|
gap: 0.5em;
|
|
7
|
+
transition: all 200ms ease;
|
|
6
8
|
|
|
7
9
|
.field-content {
|
|
8
10
|
display: grid;
|
|
@@ -76,4 +78,14 @@ export const FieldStyle = styled.section`
|
|
|
76
78
|
padding: 0 1em;
|
|
77
79
|
}
|
|
78
80
|
}
|
|
81
|
+
|
|
82
|
+
&.variant-inline {
|
|
83
|
+
grid-auto-flow: column;
|
|
84
|
+
padding: 0.5em 0;
|
|
85
|
+
align-items: center;
|
|
86
|
+
|
|
87
|
+
.field-label {
|
|
88
|
+
width: auto;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
79
91
|
`;
|
|
@@ -4,7 +4,7 @@ import { Icon, IconNameT } from '../../icon';
|
|
|
4
4
|
import { Typography } from '../../typography';
|
|
5
5
|
|
|
6
6
|
import { FieldStyle } from './field.style';
|
|
7
|
-
import { FieldProps, FieldVariant } from './field.types';
|
|
7
|
+
import { FieldOrientation, FieldProps, FieldVariant } from './field.types';
|
|
8
8
|
|
|
9
9
|
import { useClassNames } from '@polpo/hooks';
|
|
10
10
|
|
|
@@ -27,6 +27,7 @@ const FieldComponent = (
|
|
|
27
27
|
error,
|
|
28
28
|
onClickLeftIcon,
|
|
29
29
|
onClickRightIcon,
|
|
30
|
+
fieldOrientation = FieldOrientation.VERTICAL,
|
|
30
31
|
children,
|
|
31
32
|
isFocus = false,
|
|
32
33
|
variant,
|
|
@@ -39,6 +40,7 @@ const FieldComponent = (
|
|
|
39
40
|
'variant-content-border': variant === FieldVariant.CONTENT_BORDER,
|
|
40
41
|
'variant-content-line': variant === FieldVariant.CONTENT_LINE,
|
|
41
42
|
'variant-full-border': variant === FieldVariant.FULL_BORDER,
|
|
43
|
+
'variant-inline': fieldOrientation === FieldOrientation.HORIZONTAL,
|
|
42
44
|
});
|
|
43
45
|
|
|
44
46
|
const handleClick = (callback?: () => void) => (e: React.MouseEvent) => {
|
|
@@ -8,6 +8,11 @@ export enum FieldVariant {
|
|
|
8
8
|
CONTENT_LINE = 'line',
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export enum FieldOrientation {
|
|
12
|
+
HORIZONTAL = 'horizontal',
|
|
13
|
+
VERTICAL = 'vertical',
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
type FieldSharedProps = {
|
|
12
17
|
rightIcon?: IconNameT;
|
|
13
18
|
leftIcon?: IconNameT;
|
|
@@ -23,6 +28,7 @@ export type FieldProps = FieldSharedProps & {
|
|
|
23
28
|
id: string;
|
|
24
29
|
error?: string;
|
|
25
30
|
isFocus?: boolean;
|
|
31
|
+
fieldOrientation?: `${FieldOrientation}`;
|
|
26
32
|
};
|
|
27
33
|
|
|
28
34
|
export type InputFieldProps<T> = T & FieldSharedProps;
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import styled from 'styled-components';
|
|
2
2
|
|
|
3
|
+
import { Modal } from '../../modals';
|
|
4
|
+
|
|
3
5
|
export const InputColorStyle = styled.section`
|
|
4
6
|
display: grid;
|
|
5
7
|
grid-auto-flow: column;
|
|
6
8
|
align-items: center;
|
|
7
9
|
justify-content: start;
|
|
10
|
+
gap: 0.5em;
|
|
8
11
|
|
|
9
12
|
.input-color-value {
|
|
10
13
|
margin-left: 10px;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
.color-input {
|
|
14
|
-
padding:
|
|
17
|
+
padding-right: 1em;
|
|
15
18
|
border-radius: inherit;
|
|
16
19
|
width: 100%;
|
|
17
20
|
font-size: ${props => props.theme.constants.typography.label.fontSize};
|
|
@@ -41,9 +44,7 @@ export const InputColorBoxStyle = styled.section`
|
|
|
41
44
|
}
|
|
42
45
|
`;
|
|
43
46
|
|
|
44
|
-
export const InputColorSelectorStyle = styled
|
|
45
|
-
position: fixed;
|
|
46
|
-
z-index: 1;
|
|
47
|
+
export const InputColorSelectorStyle = styled(Modal)`
|
|
47
48
|
display: grid;
|
|
48
49
|
gap: 10px;
|
|
49
50
|
background: ${props => props.theme.colors.background.main};
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import Color from 'color';
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { HexAlphaColorPicker, HexColorInput } from 'react-colorful';
|
|
4
4
|
import useEyeDropper from 'use-eye-dropper';
|
|
5
5
|
|
|
6
6
|
import { Icon } from '../../icon';
|
|
7
|
-
import { Modal } from '../../modals';
|
|
8
7
|
import { Controller } from '../controller';
|
|
9
8
|
import { Field, InputFieldProps } from '../field';
|
|
10
9
|
import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
|
|
11
10
|
|
|
12
11
|
import { InputColorBoxStyle, InputColorSelectorStyle, InputColorStyle } from './input-color.style';
|
|
13
12
|
|
|
14
|
-
import { useInputHandlers
|
|
13
|
+
import { useInputHandlers } from '@polpo/hooks';
|
|
15
14
|
|
|
16
15
|
type ColorProps = InputFieldProps<{
|
|
17
16
|
showValueText?: boolean;
|
|
@@ -43,6 +42,8 @@ export const InputColor = ({
|
|
|
43
42
|
const { open, isSupported } = useEyeDropper();
|
|
44
43
|
const [inputValue, setInputValue] = useState<string>(value);
|
|
45
44
|
const id = useMemo(() => crypto.randomUUID(), []);
|
|
45
|
+
const containerRef = useRef<HTMLElement>(null);
|
|
46
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
46
47
|
const { handlers, isFocus } = useInputHandlers({
|
|
47
48
|
onChange: e => setInputValue(e.target.value),
|
|
48
49
|
onBlur: e => {
|
|
@@ -54,10 +55,6 @@ export const InputColor = ({
|
|
|
54
55
|
onFocus && onFocus(e);
|
|
55
56
|
},
|
|
56
57
|
});
|
|
57
|
-
const { modalRef, isVisible, setIsVisible, modalStyle, containerRef } = useModalInContainer({
|
|
58
|
-
position: 'bottom',
|
|
59
|
-
distancePercentage: 0,
|
|
60
|
-
});
|
|
61
58
|
|
|
62
59
|
const borderColor = useMemo(() => {
|
|
63
60
|
const color = Color(value === '' ? '#000000' : value);
|
|
@@ -88,13 +85,7 @@ export const InputColor = ({
|
|
|
88
85
|
|
|
89
86
|
return (
|
|
90
87
|
<Field id={id} error={error} isFocus={isFocus} {...fieldProps}>
|
|
91
|
-
<InputColorStyle
|
|
92
|
-
onClick={e => {
|
|
93
|
-
e.stopPropagation();
|
|
94
|
-
setIsVisible(true);
|
|
95
|
-
}}
|
|
96
|
-
ref={containerRef}
|
|
97
|
-
>
|
|
88
|
+
<InputColorStyle onClick={() => setIsOpen(true)} ref={containerRef}>
|
|
98
89
|
<InputColorBoxStyle
|
|
99
90
|
className={className}
|
|
100
91
|
style={{
|
|
@@ -103,36 +94,7 @@ export const InputColor = ({
|
|
|
103
94
|
color: value,
|
|
104
95
|
...style,
|
|
105
96
|
}}
|
|
106
|
-
|
|
107
|
-
<Modal id='input-color' isOpen={isVisible}>
|
|
108
|
-
<InputColorSelectorStyle ref={modalRef} style={modalStyle}>
|
|
109
|
-
<HexAlphaColorPicker id={id} color={value} onChange={setValue} />
|
|
110
|
-
<section className='color-input-container'>
|
|
111
|
-
{isSupported() ? (
|
|
112
|
-
<Icon
|
|
113
|
-
name='dropper'
|
|
114
|
-
onClick={() => {
|
|
115
|
-
void openEyeDropper();
|
|
116
|
-
}}
|
|
117
|
-
/>
|
|
118
|
-
) : (
|
|
119
|
-
<span />
|
|
120
|
-
)}
|
|
121
|
-
<HexColorInput
|
|
122
|
-
className='color-input'
|
|
123
|
-
id={id}
|
|
124
|
-
name={name}
|
|
125
|
-
color={value}
|
|
126
|
-
placeholder='Type a color'
|
|
127
|
-
prefixed
|
|
128
|
-
alpha
|
|
129
|
-
onChange={setValue}
|
|
130
|
-
/>
|
|
131
|
-
<span />
|
|
132
|
-
</section>
|
|
133
|
-
</InputColorSelectorStyle>
|
|
134
|
-
</Modal>
|
|
135
|
-
</InputColorBoxStyle>
|
|
97
|
+
/>
|
|
136
98
|
{showValueText ? (
|
|
137
99
|
<input
|
|
138
100
|
id={id}
|
|
@@ -148,6 +110,41 @@ export const InputColor = ({
|
|
|
148
110
|
/>
|
|
149
111
|
) : null}
|
|
150
112
|
</InputColorStyle>
|
|
113
|
+
|
|
114
|
+
<InputColorSelectorStyle
|
|
115
|
+
id='input-color'
|
|
116
|
+
isOpen={isOpen}
|
|
117
|
+
onClose={() => setIsOpen(false)}
|
|
118
|
+
position='bottom right'
|
|
119
|
+
offset={5}
|
|
120
|
+
backdrop='transparent'
|
|
121
|
+
containerRef={containerRef}
|
|
122
|
+
>
|
|
123
|
+
<HexAlphaColorPicker id={id} color={value} onChange={setValue} />
|
|
124
|
+
<section className='color-input-container'>
|
|
125
|
+
{isSupported() ? (
|
|
126
|
+
<Icon
|
|
127
|
+
name='dropper'
|
|
128
|
+
onClick={() => {
|
|
129
|
+
void openEyeDropper();
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
132
|
+
) : (
|
|
133
|
+
<span />
|
|
134
|
+
)}
|
|
135
|
+
<HexColorInput
|
|
136
|
+
className='color-input'
|
|
137
|
+
id={id}
|
|
138
|
+
name={name}
|
|
139
|
+
color={value}
|
|
140
|
+
placeholder='Type a color'
|
|
141
|
+
prefixed
|
|
142
|
+
alpha
|
|
143
|
+
onChange={setValue}
|
|
144
|
+
/>
|
|
145
|
+
<span />
|
|
146
|
+
</section>
|
|
147
|
+
</InputColorSelectorStyle>
|
|
151
148
|
</Field>
|
|
152
149
|
);
|
|
153
150
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ColorVariants } from '../../../core/variants';
|
|
4
|
+
import { Grid, SectionLayout } from '../../../layouts';
|
|
4
5
|
import { UnControlledComponentArgTypes } from '../form.stories.types';
|
|
5
6
|
|
|
6
7
|
import { Radio } from './radio';
|
|
@@ -15,6 +16,7 @@ const meta: Meta<typeof Radio> = {
|
|
|
15
16
|
label: { control: 'text' },
|
|
16
17
|
radioValue: { control: false },
|
|
17
18
|
placeholder: { table: { disable: true } },
|
|
19
|
+
color: { control: { type: 'inline-radio', options: Object.values(ColorVariants) } },
|
|
18
20
|
},
|
|
19
21
|
args: {
|
|
20
22
|
label: 'Option A',
|
|
@@ -26,10 +28,10 @@ const meta: Meta<typeof Radio> = {
|
|
|
26
28
|
return (
|
|
27
29
|
<Grid gap='0.4em'>
|
|
28
30
|
<Radio {...args} name='radio' value={value} radioValue='A' setValue={setValue} />
|
|
29
|
-
<Radio name='radio' value={value} label='Option B' radioValue='B' setValue={setValue} />
|
|
30
|
-
<Radio name='radio' value={value} label='Option C' radioValue='C' setValue={setValue} />
|
|
31
|
-
<Radio name='radio' value={value} label='Option D' radioValue='D' setValue={setValue} />
|
|
32
|
-
<Radio name='radio' value={value} label='Option E' radioValue='E' setValue={setValue} />
|
|
31
|
+
<Radio {...args} name='radio' value={value} label='Option B' radioValue='B' setValue={setValue} />
|
|
32
|
+
<Radio {...args} name='radio' value={value} label='Option C' radioValue='C' setValue={setValue} />
|
|
33
|
+
<Radio {...args} name='radio' value={value} label='Option D' radioValue='D' setValue={setValue} />
|
|
34
|
+
<Radio {...args} name='radio' value={value} label='Option E' radioValue='E' setValue={setValue} />
|
|
33
35
|
</Grid>
|
|
34
36
|
);
|
|
35
37
|
},
|
|
@@ -41,3 +43,25 @@ type Story = StoryObj<typeof Radio>;
|
|
|
41
43
|
export const Default: Story = {
|
|
42
44
|
args: {},
|
|
43
45
|
};
|
|
46
|
+
|
|
47
|
+
export const Colors: Story = {
|
|
48
|
+
args: {},
|
|
49
|
+
argTypes: {
|
|
50
|
+
color: { control: false },
|
|
51
|
+
},
|
|
52
|
+
render: args => {
|
|
53
|
+
const [value, setValue] = useState('Primary');
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<SectionLayout>
|
|
57
|
+
<Radio {...args} color='primary' value={value} setValue={setValue} radioValue='Primary' label='Primary' />
|
|
58
|
+
<Radio {...args} color='secondary' value={value} setValue={setValue} radioValue='Secondary' label='Secondary' />
|
|
59
|
+
<Radio {...args} color='tertiary' value={value} setValue={setValue} radioValue='Tertiary' label='Tertiary' />
|
|
60
|
+
<Radio {...args} color='info' value={value} setValue={setValue} radioValue='Info' label='Info' />
|
|
61
|
+
<Radio {...args} color='active' value={value} setValue={setValue} radioValue='Active' label='Active' />
|
|
62
|
+
<Radio {...args} color='warning' value={value} setValue={setValue} radioValue='Warning' label='Warning' />
|
|
63
|
+
<Radio {...args} color='alert' value={value} setValue={setValue} radioValue='Alert' label='Alert' />
|
|
64
|
+
</SectionLayout>
|
|
65
|
+
);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
@@ -1,33 +1,24 @@
|
|
|
1
1
|
import styled from 'styled-components';
|
|
2
2
|
|
|
3
|
+
export const RadioFillStyle = styled.section`
|
|
4
|
+
transition: all 200ms ease-out;
|
|
5
|
+
border-radius: inherit;
|
|
6
|
+
margin: auto;
|
|
7
|
+
width: 0;
|
|
8
|
+
height: 0;
|
|
9
|
+
`;
|
|
10
|
+
|
|
3
11
|
export const RadioStyle = styled.section`
|
|
4
12
|
border-radius: 50%;
|
|
5
|
-
background: ${props => props.theme.colors.
|
|
6
|
-
color: ${props => props.theme.colors.gray6};
|
|
7
|
-
border: 2px solid;
|
|
13
|
+
background: ${props => props.theme.colors.background.paper};
|
|
8
14
|
transition: all 300ms ease;
|
|
15
|
+
width: 1.4em;
|
|
16
|
+
height: 1.4em;
|
|
17
|
+
outline: 2px solid;
|
|
18
|
+
display: flex;
|
|
9
19
|
position: relative;
|
|
10
20
|
padding: 2px;
|
|
11
21
|
|
|
12
|
-
.radio-dot {
|
|
13
|
-
width: 1em;
|
|
14
|
-
height: 1em;
|
|
15
|
-
border-radius: 50%;
|
|
16
|
-
display: block;
|
|
17
|
-
opacity: 0;
|
|
18
|
-
transition: opacity 300ms ease;
|
|
19
|
-
background: ${props => props.theme.colors.primary.main};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
&.is-checked {
|
|
23
|
-
background: ${props => props.theme.colors.primary.contrast};
|
|
24
|
-
color: ${props => props.theme.colors.primary.main};
|
|
25
|
-
|
|
26
|
-
.radio-dot {
|
|
27
|
-
opacity: 1;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
22
|
.radio-input {
|
|
32
23
|
position: absolute;
|
|
33
24
|
top: 0;
|
|
@@ -40,7 +31,11 @@ export const RadioStyle = styled.section`
|
|
|
40
31
|
}
|
|
41
32
|
`;
|
|
42
33
|
|
|
43
|
-
|
|
34
|
+
type RadioContainerStyleProps = {
|
|
35
|
+
$color: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const RadioContainerStyle = styled.section<RadioContainerStyleProps>`
|
|
44
39
|
display: flex;
|
|
45
40
|
align-items: center;
|
|
46
41
|
gap: 1em;
|
|
@@ -51,8 +46,34 @@ export const RadioContainerStyle = styled.section`
|
|
|
51
46
|
user-select: none;
|
|
52
47
|
}
|
|
53
48
|
|
|
49
|
+
${RadioStyle} {
|
|
50
|
+
color: ${props => props.$color};
|
|
51
|
+
|
|
52
|
+
&.is-checked {
|
|
53
|
+
${RadioFillStyle} {
|
|
54
|
+
width: 100%;
|
|
55
|
+
height: 100%;
|
|
56
|
+
background: ${props => props.$color};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
${RadioStyle}:hover,
|
|
55
62
|
&:has(.radio-label:hover) ${RadioStyle} {
|
|
56
|
-
box-shadow: 0 0 0 0.4em ${props => props
|
|
63
|
+
box-shadow: 0 0 0 0.4em ${props => props.$color}88;
|
|
64
|
+
|
|
65
|
+
${RadioFillStyle} {
|
|
66
|
+
width: 20%;
|
|
67
|
+
height: 20%;
|
|
68
|
+
background: ${props => props.$color}88;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&:is(.is-checked) {
|
|
72
|
+
${RadioFillStyle} {
|
|
73
|
+
width: 80%;
|
|
74
|
+
height: 80%;
|
|
75
|
+
background: ${props => props.$color};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
57
78
|
}
|
|
58
79
|
`;
|
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
+
import { DefaultTheme, useTheme } from 'styled-components';
|
|
2
3
|
|
|
4
|
+
import { ColorVariants } from '../../../core/variants';
|
|
3
5
|
import { Typography } from '../../typography';
|
|
4
6
|
import { Controller } from '../controller';
|
|
5
7
|
import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
|
|
6
8
|
|
|
7
|
-
import { RadioContainerStyle, RadioStyle } from './radio.style';
|
|
9
|
+
import { RadioContainerStyle, RadioFillStyle, RadioStyle } from './radio.style';
|
|
8
10
|
|
|
9
11
|
import { useInputHandlers } from '@polpo/hooks';
|
|
10
12
|
|
|
13
|
+
const getRadioColor = (theme: DefaultTheme, color: `${ColorVariants}`): string => {
|
|
14
|
+
const radioColors: Record<ColorVariants, string> = {
|
|
15
|
+
[ColorVariants.Primary]: theme.colors.primary.main,
|
|
16
|
+
[ColorVariants.Secondary]: theme.colors.secondary.main,
|
|
17
|
+
[ColorVariants.Tertiary]: theme.colors.tertiary.main,
|
|
18
|
+
[ColorVariants.Info]: theme.colors.info.main,
|
|
19
|
+
[ColorVariants.Active]: theme.colors.active.main,
|
|
20
|
+
[ColorVariants.Warning]: theme.colors.warning.main,
|
|
21
|
+
[ColorVariants.Alert]: theme.colors.alert.main,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return radioColors[color] ?? radioColors[ColorVariants.Primary];
|
|
25
|
+
};
|
|
26
|
+
|
|
11
27
|
type RadioProps = {
|
|
12
28
|
label?: string;
|
|
13
29
|
radioValue: string;
|
|
14
30
|
placeholder?: never;
|
|
31
|
+
color?: `${ColorVariants}`;
|
|
15
32
|
};
|
|
16
33
|
|
|
17
34
|
export const Radio = ({
|
|
@@ -28,6 +45,7 @@ export const Radio = ({
|
|
|
28
45
|
autoComplete = 'off',
|
|
29
46
|
radioValue,
|
|
30
47
|
label,
|
|
48
|
+
color = ColorVariants.Primary,
|
|
31
49
|
/*
|
|
32
50
|
* isDirty = false,
|
|
33
51
|
* isTouched = false,
|
|
@@ -35,6 +53,7 @@ export const Radio = ({
|
|
|
35
53
|
* error,
|
|
36
54
|
*/
|
|
37
55
|
}: UnControlledComponentProps<RadioProps, string>) => {
|
|
56
|
+
const theme = useTheme();
|
|
38
57
|
const id = useMemo(() => crypto.randomUUID(), []);
|
|
39
58
|
const { handlers } = useInputHandlers({
|
|
40
59
|
onChange: e => setValue(e.target.value),
|
|
@@ -43,9 +62,9 @@ export const Radio = ({
|
|
|
43
62
|
});
|
|
44
63
|
|
|
45
64
|
return (
|
|
46
|
-
<RadioContainerStyle className={className} style={style}>
|
|
65
|
+
<RadioContainerStyle $color={getRadioColor(theme, color)} className={className} style={style}>
|
|
47
66
|
<RadioStyle className={radioValue === value ? 'is-checked' : ''}>
|
|
48
|
-
<
|
|
67
|
+
<RadioFillStyle />
|
|
49
68
|
<input
|
|
50
69
|
id={id}
|
|
51
70
|
type='radio'
|