polpo 0.1.13 → 0.1.16

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.
Files changed (204) hide show
  1. package/.turbo/cache/eslint/.cache_16wwsjl +1 -0
  2. package/.turbo/cache/eslint/.cache_rpznjo +1 -0
  3. package/.turbo/turbo-build$colon$code.log +49 -0
  4. package/.turbo/turbo-build$colon$css.log +2 -0
  5. package/.turbo/turbo-build.log +43 -0
  6. package/.turbo/turbo-lint.log +2 -0
  7. package/dist/components.cjs +1 -3655
  8. package/dist/components.css +2 -2173
  9. package/dist/components.js +1 -3576
  10. package/dist/helpers.cjs +1 -311
  11. package/dist/helpers.d.cts +4 -1
  12. package/dist/helpers.d.ts +4 -1
  13. package/dist/helpers.js +1 -276
  14. package/dist/hooks.cjs +1 -1065
  15. package/dist/hooks.js +1 -998
  16. package/dist/layouts.cjs +1 -146
  17. package/dist/layouts.css +2 -5
  18. package/dist/layouts.js +1 -119
  19. package/dist/types.cjs +1 -19
  20. package/dist/types.js +0 -1
  21. package/eslint.config.js +4 -0
  22. package/package.json +16 -11
  23. package/postcss.config.js +3 -0
  24. package/src/components/accordion/accordion-item.tsx +123 -0
  25. package/src/components/accordion/accordion.component.tsx +80 -0
  26. package/src/components/accordion/accordion.styles.css +41 -0
  27. package/src/components/accordion/index.ts +2 -0
  28. package/src/components/button/button.component.tsx +50 -0
  29. package/src/components/button/button.styles.css +317 -0
  30. package/src/components/button/index.ts +1 -0
  31. package/src/components/cards/flip-card/flip-card.component.tsx +66 -0
  32. package/src/components/cards/flip-card/flip-card.styles.css +50 -0
  33. package/src/components/cards/flip-card/index.ts +1 -0
  34. package/src/components/cards/hover-card/hover-card.component.tsx +76 -0
  35. package/src/components/cards/hover-card/hover-card.styles.css +13 -0
  36. package/src/components/cards/hover-card/index.ts +1 -0
  37. package/src/components/cards/index.ts +3 -0
  38. package/src/components/cards/slide-card/index.ts +1 -0
  39. package/src/components/cards/slide-card/slide-card.component.tsx +27 -0
  40. package/src/components/component.types.ts +31 -0
  41. package/src/components/cursor/cursor.component.tsx +49 -0
  42. package/src/components/cursor/cursor.styles.css +73 -0
  43. package/src/components/cursor/index.ts +1 -0
  44. package/src/components/form/checkbox/checkbox.component.tsx +95 -0
  45. package/src/components/form/checkbox/checkbox.styles.css +162 -0
  46. package/src/components/form/checkbox/index.ts +1 -0
  47. package/src/components/form/controller/controller.component.tsx +42 -0
  48. package/src/components/form/controller/index.ts +1 -0
  49. package/src/components/form/date-picker/date-picker.component.tsx +66 -0
  50. package/src/components/form/date-picker/index.ts +1 -0
  51. package/src/components/form/field/field.component.tsx +84 -0
  52. package/src/components/form/field/field.styles.css +98 -0
  53. package/src/components/form/field/field.types.ts +34 -0
  54. package/src/components/form/field/index.ts +2 -0
  55. package/src/components/form/form.types.ts +37 -0
  56. package/src/components/form/index.ts +14 -0
  57. package/src/components/form/input/index.ts +1 -0
  58. package/src/components/form/input/input.component.tsx +75 -0
  59. package/src/components/form/input-color/index.ts +1 -0
  60. package/src/components/form/input-color/input-color.component.tsx +170 -0
  61. package/src/components/form/input-color/input-color.styles.css +92 -0
  62. package/src/components/form/input-file/index.ts +1 -0
  63. package/src/components/form/input-file/input-file.component.tsx +221 -0
  64. package/src/components/form/input-file/input-file.styles.css +143 -0
  65. package/src/components/form/input-number/index.ts +1 -0
  66. package/src/components/form/input-number/input-number.component.tsx +144 -0
  67. package/src/components/form/input-password/index.ts +1 -0
  68. package/src/components/form/input-password/input-password.component.tsx +77 -0
  69. package/src/components/form/radio/index.ts +1 -0
  70. package/src/components/form/radio/radio.component.tsx +92 -0
  71. package/src/components/form/radio/radio.styles.css +117 -0
  72. package/src/components/form/select/index.ts +1 -0
  73. package/src/components/form/select/option.tsx +101 -0
  74. package/src/components/form/select/options.tsx +165 -0
  75. package/src/components/form/select/select.component.tsx +317 -0
  76. package/src/components/form/select/select.styles.css +115 -0
  77. package/src/components/form/select/select.types.ts +97 -0
  78. package/src/components/form/slider/index.ts +1 -0
  79. package/src/components/form/slider/slider.component.tsx +117 -0
  80. package/src/components/form/slider/slider.styles.css +94 -0
  81. package/src/components/form/switch/index.ts +1 -0
  82. package/src/components/form/switch/switch.component.tsx +166 -0
  83. package/src/components/form/switch/switch.styles.css +165 -0
  84. package/src/components/form/textarea/index.ts +1 -0
  85. package/src/components/form/textarea/textarea.component.tsx +80 -0
  86. package/src/components/form/textarea/textarea.styles.css +7 -0
  87. package/src/components/image/image.tsx +7 -0
  88. package/src/components/image/index.ts +1 -0
  89. package/src/components/index.ts +15 -0
  90. package/src/components/infinity-scroll/index.ts +1 -0
  91. package/src/components/infinity-scroll/infinity-scroll.component.tsx +51 -0
  92. package/src/components/infinity-scroll/infinity-scroll.styles.css +25 -0
  93. package/src/components/line/index.ts +1 -0
  94. package/src/components/line/line.component.tsx +77 -0
  95. package/src/components/line/line.styles.css +61 -0
  96. package/src/components/modals/action-modal/action-modal.component.tsx +150 -0
  97. package/src/components/modals/action-modal/action-modal.styles.css +115 -0
  98. package/src/components/modals/action-modal/index.ts +1 -0
  99. package/src/components/modals/aside-modal/aside-modal.component.tsx +63 -0
  100. package/src/components/modals/aside-modal/aside-modal.styles.css +86 -0
  101. package/src/components/modals/aside-modal/index.ts +1 -0
  102. package/src/components/modals/confirmation-modal/confirmation-modal.component.tsx +43 -0
  103. package/src/components/modals/confirmation-modal/confirmation-modal.styles.css +17 -0
  104. package/src/components/modals/confirmation-modal/index.ts +1 -0
  105. package/src/components/modals/index.ts +6 -0
  106. package/src/components/modals/menu/index.ts +1 -0
  107. package/src/components/modals/menu/menu.component.tsx +194 -0
  108. package/src/components/modals/menu/menu.styles.css +101 -0
  109. package/src/components/modals/modal/index.ts +2 -0
  110. package/src/components/modals/modal/modal.backdrop.tsx +67 -0
  111. package/src/components/modals/modal/modal.component.tsx +104 -0
  112. package/src/components/modals/modal/modal.styles.css +70 -0
  113. package/src/components/modals/portal/index.ts +1 -0
  114. package/src/components/modals/portal/portal.component.tsx +19 -0
  115. package/src/components/ripple/index.ts +1 -0
  116. package/src/components/ripple/ripple.component.tsx +70 -0
  117. package/src/components/ripple/ripple.styles.css +33 -0
  118. package/src/components/smart-table/index.ts +2 -0
  119. package/src/components/smart-table/smart-table.column.tsx +62 -0
  120. package/src/components/smart-table/smart-table.component.tsx +116 -0
  121. package/src/components/smart-table/smart-table.helpers.tsx +58 -0
  122. package/src/components/smart-table/smart-table.hooks.ts +27 -0
  123. package/src/components/smart-table/smart-table.row.tsx +28 -0
  124. package/src/components/smart-table/smart-table.styles.css +102 -0
  125. package/src/components/smart-table/smart-table.types.ts +42 -0
  126. package/src/components/tabs/index.ts +1 -0
  127. package/src/components/tabs/tabs-list.tsx +120 -0
  128. package/src/components/tabs/tabs.styles.css +164 -0
  129. package/src/components/tabs/tabs.tsx +119 -0
  130. package/src/components/tag/index.ts +1 -0
  131. package/src/components/tag/tag.component.tsx +34 -0
  132. package/src/components/tag/tag.styles.css +50 -0
  133. package/src/components/tooltips/click-to-copy/click-to-copy.component.tsx +41 -0
  134. package/src/components/tooltips/click-to-copy/index.ts +1 -0
  135. package/src/components/tooltips/index.ts +2 -0
  136. package/src/components/tooltips/tooltip/index.ts +1 -0
  137. package/src/components/tooltips/tooltip/tooltip.component.tsx +64 -0
  138. package/src/components/tooltips/tooltip/tooltip.styles.css +91 -0
  139. package/src/components/typography/index.ts +1 -0
  140. package/src/components/typography/typography.component.tsx +81 -0
  141. package/src/components/typography/typography.constants.ts +53 -0
  142. package/src/components/typography/typography.styles.css +122 -0
  143. package/src/helpers/cn.ts +6 -0
  144. package/src/helpers/format-bytes.ts +11 -0
  145. package/src/helpers/format-dates.ts +47 -0
  146. package/src/helpers/get-modal-position-relative-to-screen.ts +86 -0
  147. package/src/helpers/get-modal-position.ts +211 -0
  148. package/src/helpers/index.ts +6 -0
  149. package/src/helpers/text/index.ts +1 -0
  150. package/src/helpers/text/to-capitalize.ts +17 -0
  151. package/src/hooks/index.ts +30 -0
  152. package/src/hooks/use-async.ts +88 -0
  153. package/src/hooks/use-classnames.ts +13 -0
  154. package/src/hooks/use-click-outside.ts +32 -0
  155. package/src/hooks/use-constant.ts +3 -0
  156. package/src/hooks/use-cookie.ts +124 -0
  157. package/src/hooks/use-debounce-state.ts +13 -0
  158. package/src/hooks/use-debounce.ts +15 -0
  159. package/src/hooks/use-dimensions.ts +19 -0
  160. package/src/hooks/use-dom-container.ts +35 -0
  161. package/src/hooks/use-event-listener.ts +71 -0
  162. package/src/hooks/use-file-reader.ts +69 -0
  163. package/src/hooks/use-geolocation.ts +63 -0
  164. package/src/hooks/use-hover.ts +17 -0
  165. package/src/hooks/use-in-view.ts +18 -0
  166. package/src/hooks/use-input-handlers.ts +52 -0
  167. package/src/hooks/use-intersection-observer.ts +19 -0
  168. package/src/hooks/use-media-query.ts +25 -0
  169. package/src/hooks/use-modal-in-container.ts +85 -0
  170. package/src/hooks/use-modal-transition.ts +64 -0
  171. package/src/hooks/use-modal.ts +21 -0
  172. package/src/hooks/use-mouse-position.ts +64 -0
  173. package/src/hooks/use-online-status.ts +12 -0
  174. package/src/hooks/use-render-count.ts +11 -0
  175. package/src/hooks/use-resize-observer.ts +18 -0
  176. package/src/hooks/use-safe-dispatch.ts +22 -0
  177. package/src/hooks/use-scroll.ts +31 -0
  178. package/src/hooks/use-state-history.ts +22 -0
  179. package/src/hooks/use-toggle-values.ts +14 -0
  180. package/src/hooks/use-toggle.ts +11 -0
  181. package/src/hooks/use-viewport.ts +38 -0
  182. package/src/index.ts +5 -0
  183. package/src/layouts/flex/flex.component.tsx +75 -0
  184. package/src/layouts/flex/index.ts +1 -0
  185. package/src/layouts/grid/grid.component.tsx +89 -0
  186. package/src/layouts/grid/grid.styles.css +5 -0
  187. package/src/layouts/grid/index.ts +1 -0
  188. package/src/layouts/index.ts +2 -0
  189. package/src/types/generics.ts +68 -0
  190. package/src/types/index.ts +1 -0
  191. package/tsconfig.json +10 -0
  192. package/tsup.config.cjs +36 -0
  193. package/dist/components.cjs.map +0 -1
  194. package/dist/components.css.map +0 -1
  195. package/dist/components.js.map +0 -1
  196. package/dist/helpers.cjs.map +0 -1
  197. package/dist/helpers.js.map +0 -1
  198. package/dist/hooks.cjs.map +0 -1
  199. package/dist/hooks.js.map +0 -1
  200. package/dist/layouts.cjs.map +0 -1
  201. package/dist/layouts.css.map +0 -1
  202. package/dist/layouts.js.map +0 -1
  203. package/dist/types.cjs.map +0 -1
  204. package/dist/types.js.map +0 -1
@@ -0,0 +1,51 @@
1
+ import { useEffect } from 'react';
2
+
3
+ import { useDebounce, useInView } from '../../hooks';
4
+
5
+ import './infinity-scroll.styles.css';
6
+
7
+ interface InfinityScrollProps extends React.HTMLAttributes<HTMLDivElement> {
8
+ isLoading: boolean;
9
+ hasNextPage: boolean;
10
+ loadMore: () => void;
11
+ customLoadMoreElement?: (ref: React.RefObject<HTMLElement | null>) => React.ReactNode;
12
+ emptyMessage?: string;
13
+ children?: React.ReactNode;
14
+ }
15
+
16
+ export const InfinityScroll = ({
17
+ isLoading: isLoadingProp = false,
18
+ hasNextPage = false,
19
+ loadMore,
20
+ customLoadMoreElement,
21
+ emptyMessage,
22
+ children,
23
+ }: InfinityScrollProps) => {
24
+ const { ref, inView } = useInView();
25
+ const isLoading = useDebounce(isLoadingProp, 100);
26
+
27
+ useEffect(() => {
28
+ if (hasNextPage && inView && !isLoading) {
29
+ loadMore();
30
+ }
31
+ }, [hasNextPage, isLoading, loadMore, inView]);
32
+
33
+ const childrenExists = Array.isArray(children) ? children.length > 0 : Boolean(children);
34
+
35
+ return (
36
+ <>
37
+ {children}
38
+ <section className='infinity-scroll'>
39
+ {Boolean(emptyMessage) && !childrenExists && !isLoading && <p className='empty-message'>{emptyMessage}</p>}
40
+ {(hasNextPage || isLoading) &&
41
+ (customLoadMoreElement ? (
42
+ customLoadMoreElement(ref)
43
+ ) : (
44
+ <section ref={ref} className='loading'>
45
+ {isLoading && <span className='loading--icon'>:D</span>}
46
+ </section>
47
+ ))}
48
+ </section>
49
+ </>
50
+ );
51
+ };
@@ -0,0 +1,25 @@
1
+ @reference "polpo-tailwind-config/styles";
2
+
3
+ .infinity-scroll {
4
+ display: grid;
5
+ place-content: start center;
6
+ place-items: start center;
7
+
8
+ .loading {
9
+ width: 100%;
10
+ height: 30px;
11
+ display: grid;
12
+ place-content: center;
13
+
14
+ .loading--icon {
15
+ animation: spin 0.5s linear infinite;
16
+ font-size: 20px;
17
+ }
18
+ }
19
+
20
+ .empty-message {
21
+ font-size: 0.8em;
22
+ text-align: center;
23
+ color: #a6a6a6;
24
+ }
25
+ }
@@ -0,0 +1 @@
1
+ export * from './line.component';
@@ -0,0 +1,77 @@
1
+ import { useClassNames } from '../../hooks';
2
+
3
+ import './line.styles.css';
4
+
5
+ export enum LineOrientation {
6
+ VERTICAL = 'vertical',
7
+ HORIZONTAL = 'horizontal',
8
+ }
9
+
10
+ export enum LineStyle {
11
+ SOLID = 'solid',
12
+ DOTTED = 'dotted',
13
+ DASHED = 'dashed',
14
+ }
15
+
16
+ type LineCommonProps = {
17
+ orientation?: `${LineOrientation}`;
18
+ className?: string;
19
+ style?: React.CSSProperties;
20
+ color?: string;
21
+ };
22
+
23
+ type LineSolidProps = LineCommonProps & {
24
+ lineStyle?: `${LineStyle.SOLID}`;
25
+ spacing?: never;
26
+ dashedSize?: never;
27
+ size?: number;
28
+ };
29
+
30
+ type LineDottedProps = LineCommonProps & {
31
+ lineStyle: `${LineStyle.DOTTED}`;
32
+ spacing?: number;
33
+ size?: number;
34
+ dashedSize?: never;
35
+ };
36
+
37
+ type LineDashedProps = LineCommonProps & {
38
+ lineStyle: `${LineStyle.DASHED}`;
39
+ spacing?: number;
40
+ dashedSize?: number;
41
+ size?: number;
42
+ };
43
+
44
+ type LineProps = LineSolidProps | LineDottedProps | LineDashedProps;
45
+
46
+ export const Line = ({
47
+ orientation = LineOrientation.HORIZONTAL,
48
+ className = '',
49
+ style = {},
50
+ color = 'currentColor',
51
+ size = 1,
52
+ lineStyle = LineStyle.SOLID,
53
+ dashedSize = 1,
54
+ spacing = 1,
55
+ }: LineProps) => {
56
+ const classNames = useClassNames({
57
+ 'custom-line': true,
58
+ [orientation]: true,
59
+ [className]: !!className,
60
+ [lineStyle]: true,
61
+ });
62
+
63
+ return (
64
+ <span
65
+ className={classNames}
66
+ style={
67
+ {
68
+ ...style,
69
+ '--color': color,
70
+ '--size': `${size}px`,
71
+ '--spacing': `${spacing}px`,
72
+ '--dashSize': `${dashedSize}px`,
73
+ } as React.CSSProperties
74
+ }
75
+ />
76
+ );
77
+ };
@@ -0,0 +1,61 @@
1
+ @reference "polpo-tailwind-config/styles";
2
+
3
+ .custom-line {
4
+ --color: attr(data-color, 'currentColor');
5
+ --size: attr(data-size, 1px);
6
+ --spacing: attr(data-spacing, 1px);
7
+ --dashSize: attr(data-dash-size, 1px);
8
+
9
+ &.horizontal,
10
+ &.vertical {
11
+ background: var(--color);
12
+ display: inline-block;
13
+ border-radius: 100px;
14
+ }
15
+
16
+ &.horizontal {
17
+ width: 100%;
18
+ height: var(--size);
19
+
20
+ &.dotted {
21
+ background: radial-gradient(
22
+ calc(var(--size) / 2) calc(var(--size) / 2),
23
+ var(--color) 100%,
24
+ transparent
25
+ ) 0 0 / calc(var(--spacing) + var(--size)) 100%;
26
+ }
27
+
28
+ &.dashed {
29
+ background: repeating-linear-gradient(
30
+ 90deg,
31
+ var(--color),
32
+ var(--color) var(--dashSize),
33
+ transparent var(--dashSize),
34
+ transparent calc(var(--spacing) + var(--dashSize))
35
+ );
36
+ }
37
+ }
38
+
39
+ &.vertical {
40
+ height: 100%;
41
+ width: var(--size);
42
+
43
+ &.dotted {
44
+ background: radial-gradient(
45
+ calc(var(--size) / 2) calc(var(--size) / 2),
46
+ var(--color) 100%,
47
+ transparent
48
+ ) 0 0 / 100% calc(var(--spacing) + var(--size));
49
+ }
50
+
51
+ &.dashed {
52
+ background: repeating-linear-gradient(
53
+ 0deg,
54
+ var(--color),
55
+ var(--color) var(--dashSize),
56
+ transparent var(--dashSize),
57
+ transparent calc(var(--spacing) + var(--dashSize))
58
+ );
59
+ }
60
+ }
61
+ }
@@ -0,0 +1,150 @@
1
+ import { createContext, useCallback, useContext, useRef, useState } from 'react';
2
+ import { IconType } from 'react-icons';
3
+ import { ImCross } from 'react-icons/im';
4
+
5
+ import { PositionContainer } from '../../../helpers';
6
+ import { useClassNames } from '../../../hooks';
7
+ import { Button, ButtonProps } from '../../button';
8
+ import { Typography } from '../../typography';
9
+ import { Modal, ModalProps } from '../modal';
10
+
11
+ import './action-modal.styles.css';
12
+
13
+ type ActionModalContextType = {
14
+ onClose: () => void;
15
+ isActionInProgress: boolean;
16
+ setIsActionInProgress: (isActionInProgress: boolean) => void;
17
+ };
18
+
19
+ const ActionModalContext = createContext<ActionModalContextType | null>(null);
20
+
21
+ const useActionModalContext = () => {
22
+ const context = useContext(ActionModalContext);
23
+
24
+ if (!context) {
25
+ throw new Error('useActionModalContext must be used within a ActionModal');
26
+ }
27
+
28
+ return context;
29
+ };
30
+
31
+ export type ActionModalProps = Omit<
32
+ ModalProps,
33
+ 'id' | 'animation' | 'closeAnimationClassName' | 'position' | 'rootStyle' | 'className' | 'style'
34
+ > & {
35
+ actionRequired?: boolean;
36
+ icon?: IconType;
37
+ noCloseButton?: boolean;
38
+ lineOnTop?: boolean;
39
+ backCard?: boolean;
40
+ noPadding?: boolean;
41
+ className?: string;
42
+ style?: React.CSSProperties;
43
+ };
44
+
45
+ export const ActionModal = ({
46
+ children,
47
+ isOpen,
48
+ onClose,
49
+ actionRequired,
50
+ icon: Icon,
51
+ noCloseButton,
52
+ lineOnTop = false,
53
+ backCard = false,
54
+ noPadding = false,
55
+ className = '',
56
+ style = {},
57
+ ...modalProps
58
+ }: ActionModalProps) => {
59
+ const [isActionInProgress, setIsActionInProgress] = useState(false);
60
+ const ref = useRef<HTMLElement>(null);
61
+
62
+ const remainAction = useCallback(() => {
63
+ ref.current?.classList.add('shake-animation');
64
+ setTimeout(() => {
65
+ ref.current?.classList.remove('shake-animation');
66
+ }, 500);
67
+ }, []);
68
+
69
+ const actionModalClassName = useClassNames({
70
+ 'action-modal-content': true,
71
+ 'back-card': backCard,
72
+ 'line-on-top': lineOnTop,
73
+ 'no-padding': noPadding,
74
+ });
75
+
76
+ return (
77
+ <ActionModalContext.Provider value={{ onClose, isActionInProgress, setIsActionInProgress }}>
78
+ <Modal
79
+ className='action-modal'
80
+ id='action-modal'
81
+ animation='bounce'
82
+ opacity={0.8}
83
+ isOpen={isOpen}
84
+ onClose={onClose}
85
+ {...modalProps}
86
+ backdropOnClick={actionRequired ? remainAction : onClose}
87
+ position={PositionContainer.CENTER}
88
+ >
89
+ <section ref={ref} className='modal-content'>
90
+ <section className={actionModalClassName}>
91
+ {!noCloseButton && !actionRequired && (
92
+ <section className='close-modal-button' onClick={() => onClose()}>
93
+ <ImCross />
94
+ </section>
95
+ )}
96
+ {Icon ? (
97
+ <Typography variant='header4' className='action-modal-icon'>
98
+ <Icon />
99
+ </Typography>
100
+ ) : null}
101
+ <section className='action-modal-body'>
102
+ <section className={`action-modal-content ${className}`} style={style}>
103
+ {children}
104
+ </section>
105
+ </section>
106
+ </section>
107
+ </section>
108
+ </Modal>
109
+ </ActionModalContext.Provider>
110
+ );
111
+ };
112
+
113
+ type ActionButtonProps = Omit<ButtonProps, 'onClick'> & {
114
+ onClick: (() => Promise<void>) | (() => void);
115
+ };
116
+
117
+ const ActionButton = ({ onClick, children, isLoading: manualIsLoading, ...buttonProps }: ActionButtonProps) => {
118
+ const { onClose, isActionInProgress, setIsActionInProgress } = useActionModalContext();
119
+ const [isLoading, setIsLoading] = useState(false);
120
+
121
+ const handleAction = useCallback(() => {
122
+ setIsLoading(true);
123
+ setIsActionInProgress(true);
124
+ const result = onClick();
125
+
126
+ if (result instanceof Promise) {
127
+ result.then(() => {
128
+ onClose();
129
+ setIsLoading(false);
130
+ setIsActionInProgress(false);
131
+ });
132
+ } else {
133
+ onClose();
134
+ setIsLoading(false);
135
+ setIsActionInProgress(false);
136
+ }
137
+ }, [onClick, onClose, setIsActionInProgress]);
138
+
139
+ if (!isLoading && isActionInProgress) {
140
+ return null;
141
+ }
142
+
143
+ return (
144
+ <Button {...buttonProps} onClick={handleAction} isLoading={manualIsLoading || isLoading}>
145
+ {children}
146
+ </Button>
147
+ );
148
+ };
149
+
150
+ ActionModal.ActionButton = ActionButton;
@@ -0,0 +1,115 @@
1
+ @reference "polpo-tailwind-config/styles";
2
+
3
+ .action-modal {
4
+ background: transparent;
5
+
6
+ .modal-content {
7
+ &.shake-animation {
8
+ animation: headShake 600ms linear;
9
+ }
10
+ }
11
+ }
12
+
13
+ .action-modal-content {
14
+ position: relative;
15
+
16
+ .action-modal-body {
17
+ box-shadow: 0 0 10px -5px;
18
+ border-radius: 10px;
19
+ overflow: hidden;
20
+ display: grid;
21
+ }
22
+
23
+ .action-modal-content {
24
+ background: var(--color-background);
25
+ padding: 3em 4em 2em;
26
+ display: grid;
27
+ gap: 1em;
28
+ }
29
+
30
+ &.no-padding .action-modal-content {
31
+ padding: 2em 0 0;
32
+ }
33
+
34
+ &:has(.action-modal-icon) .action-modal-content {
35
+ padding-top: 4em;
36
+ }
37
+
38
+ &.back-card {
39
+ &::before {
40
+ content: '';
41
+ position: absolute;
42
+ width: 90%;
43
+ height: 100%;
44
+ top: 8px;
45
+ left: 50%;
46
+ transform: translate(-50%);
47
+ z-index: -1;
48
+ background: var(--color-primary-500);
49
+ border-radius: 10px;
50
+ display: block;
51
+ transition: top 300ms cubic-bezier(0.81, -0.52, 0.42, 2.5);
52
+ }
53
+ }
54
+
55
+ .action-modal-icon {
56
+ position: absolute;
57
+ top: 0;
58
+ left: 50%;
59
+ transform: translate(-50%, -50%);
60
+ background: var(--color-primary-500);
61
+ color: var(--color-primary-50);
62
+ padding: 0;
63
+ border-radius: 50%;
64
+ width: 2em;
65
+ height: 2em;
66
+ display: grid;
67
+ place-content: center;
68
+ transition: box-shadow 300ms cubic-bezier(0.81, -0.52, 0.42, 2.5);
69
+ z-index: 1;
70
+ box-shadow:
71
+ 0 0 0 0 hsl(from var(--color-primary-500) h s l / 53%),
72
+ 0 0 0 0 hsl(from var(--color-primary-500) h s l / 40%),
73
+ 0 0 0 0 hsl(from var(--color-primary-500) h s l / 27%),
74
+ 0 0 0 0 hsl(from var(--color-primary-500) h s l / 14%);
75
+ }
76
+
77
+ .close-modal-button {
78
+ width: 1em;
79
+ height: 1em;
80
+ border-radius: 50%;
81
+ cursor: pointer;
82
+ background: var(--color-background);
83
+ position: absolute;
84
+ top: 10px;
85
+ right: 5px;
86
+ @apply text-label;
87
+ opacity: 0;
88
+ transition: opacity 300ms ease;
89
+ z-index: 1;
90
+ }
91
+
92
+ &.line-on-top {
93
+ .action-modal-content {
94
+ border-top: 5px solid var(--color-primary-500);
95
+ }
96
+ }
97
+
98
+ &:hover {
99
+ .action-modal-icon {
100
+ box-shadow:
101
+ 0 0 0 7px hsl(from var(--color-primary-500) h s l / 53%),
102
+ 0 0 0 14px hsl(from var(--color-primary-500) h s l / 40%),
103
+ 0 0 0 21px hsl(from var(--color-primary-500) h s l / 27%),
104
+ 0 0 0 28px hsl(from var(--color-primary-500) h s l / 14%);
105
+ }
106
+
107
+ .close-modal-button {
108
+ opacity: 1;
109
+ }
110
+
111
+ &::before {
112
+ top: 15px;
113
+ }
114
+ }
115
+ }
@@ -0,0 +1 @@
1
+ export * from './action-modal.component';
@@ -0,0 +1,63 @@
1
+ import { CSSProperties, useMemo } from 'react';
2
+ import { ImCross } from 'react-icons/im';
3
+
4
+ import { PositionContainer } from '../../../helpers';
5
+ import { Modal, ModalProps } from '../modal';
6
+
7
+ import './aside-modal.styles.css';
8
+
9
+ type AsideModalProps = Omit<
10
+ ModalProps,
11
+ 'id' | 'animation' | 'closeAnimationClassName' | 'position' | 'rootStyle' | 'className' | 'style'
12
+ > & {
13
+ position?:
14
+ | `${PositionContainer.TOP}`
15
+ | `${PositionContainer.LEFT}`
16
+ | `${PositionContainer.RIGHT}`
17
+ | `${PositionContainer.BOTTOM}`;
18
+ size?: number | `${number}px` | `${number}em`;
19
+ className?: string;
20
+ style?: React.CSSProperties;
21
+ };
22
+
23
+ export const AsideModal = ({
24
+ children,
25
+ isOpen,
26
+ onClose,
27
+ position = PositionContainer.LEFT,
28
+ size,
29
+ className = '',
30
+ ...modalProps
31
+ }: AsideModalProps) => {
32
+ const modalRootStyles = useMemo<CSSProperties>(() => {
33
+ const computedSize = {
34
+ [PositionContainer.TOP]: { height: size, width: '100%' },
35
+ [PositionContainer.LEFT]: { height: '100%', width: size },
36
+ [PositionContainer.RIGHT]: { height: '100%', width: size },
37
+ [PositionContainer.BOTTOM]: { height: size, width: '100%' },
38
+ };
39
+
40
+ return computedSize[position];
41
+ }, [position, size]);
42
+
43
+ return (
44
+ <Modal
45
+ id='aside'
46
+ isOpen={isOpen}
47
+ onClose={onClose}
48
+ opacity={0.6}
49
+ windowOffset={0}
50
+ animation='none'
51
+ className={`aside-modal ${className} ${position}`}
52
+ rootStyle={modalRootStyles}
53
+ backdropOnClick={onClose}
54
+ position={position}
55
+ {...modalProps}
56
+ >
57
+ <span className='close-modal-button' onClick={onClose}>
58
+ <ImCross />
59
+ </span>
60
+ <section className='aside-modal-content'>{children}</section>
61
+ </Modal>
62
+ );
63
+ };
@@ -0,0 +1,86 @@
1
+ @reference "polpo-tailwind-config/styles";
2
+
3
+ .aside-modal {
4
+ color: var(--color-foreground);
5
+ overflow: auto;
6
+ height: 100%;
7
+
8
+ .aside-modal-content {
9
+ padding: 2em;
10
+ }
11
+
12
+ .close-modal-button {
13
+ border-radius: 50%;
14
+ cursor: pointer;
15
+ display: grid;
16
+ place-content: center;
17
+ background: var(--color-background);
18
+ border: 4px solid var(--color-primary-500);
19
+ position: absolute;
20
+ padding: 0.5em;
21
+ }
22
+
23
+ &.left {
24
+ border-right: 4px solid var(--color-primary-500);
25
+ animation: slideIn-left 300ms ease;
26
+
27
+ &.modal-close {
28
+ animation: slideOut-left 300ms ease;
29
+ transform: translateX(-100%);
30
+ }
31
+
32
+ .close-modal-button {
33
+ top: 2em;
34
+ left: 100%;
35
+ transform: translate(calc(-50% + 2px));
36
+ }
37
+ }
38
+
39
+ &.right {
40
+ border-left: 4px solid var(--color-primary-500);
41
+ animation: slideIn-right 300ms ease;
42
+
43
+ &.modal-close {
44
+ animation: slideOut-right 300ms ease;
45
+ transform: translateX(100%);
46
+ }
47
+
48
+ .close-modal-button {
49
+ top: 2em;
50
+ right: 100%;
51
+ transform: translate(calc(50% - 2px));
52
+ }
53
+ }
54
+
55
+ &.top {
56
+ border-bottom: 4px solid var(--color-primary-500);
57
+ animation: slideIn-top 300ms ease;
58
+
59
+ &.modal-close {
60
+ animation: slideOut-top 300ms ease;
61
+ transform: translateY(-100%);
62
+ }
63
+
64
+ .close-modal-button {
65
+ bottom: 0;
66
+ right: 2em;
67
+ transform: translate(0, calc(50% - 2px));
68
+ }
69
+ }
70
+
71
+ &.bottom {
72
+ border-top: 4px solid var(--color-primary-500);
73
+ animation: slideIn-bottom 300ms ease;
74
+
75
+ &.modal-close {
76
+ animation: slideOut-bottom 300ms ease;
77
+ transform: translateY(100%);
78
+ }
79
+
80
+ .close-modal-button {
81
+ top: 0;
82
+ right: 2em;
83
+ transform: translate(0, calc(-50% + 2px));
84
+ }
85
+ }
86
+ }
@@ -0,0 +1 @@
1
+ export * from './aside-modal.component';
@@ -0,0 +1,43 @@
1
+ import { Typography } from '../../typography';
2
+ import { ActionModal, ActionModalProps } from '../action-modal';
3
+
4
+ import './confirmation-modal.styles.css';
5
+
6
+ type ConfirmationModalProps = ActionModalProps & {
7
+ title: string;
8
+ onAccept: (() => Promise<void>) | (() => void);
9
+ onReject?: (() => Promise<void>) | (() => void);
10
+ acceptText: string;
11
+ rejectText: string;
12
+ isLoading?: boolean;
13
+ };
14
+
15
+ export const ConfirmationModal = ({
16
+ title,
17
+ onAccept,
18
+ onReject = () => null,
19
+ acceptText,
20
+ rejectText,
21
+ children,
22
+ isLoading,
23
+ ...actionModalProps
24
+ }: ConfirmationModalProps) => {
25
+ return (
26
+ <ActionModal {...actionModalProps} backCard>
27
+ <section className='confirmation-modal'>
28
+ <Typography variant='header4'>{title}</Typography>
29
+ <section>{children}</section>
30
+ <section className='confirmation-modal-actions'>
31
+ {!isLoading && (
32
+ <ActionModal.ActionButton variant='flat' onClick={onReject}>
33
+ {rejectText}
34
+ </ActionModal.ActionButton>
35
+ )}
36
+ <ActionModal.ActionButton isLoading={isLoading} onClick={onAccept}>
37
+ {acceptText}
38
+ </ActionModal.ActionButton>
39
+ </section>
40
+ </section>
41
+ </ActionModal>
42
+ );
43
+ };
@@ -0,0 +1,17 @@
1
+ @reference "polpo-tailwind-config/styles";
2
+
3
+ .confirmation-modal {
4
+ display: grid;
5
+ max-width: 450px;
6
+ gap: 1em;
7
+ place-content: center;
8
+ justify-items: center;
9
+ text-align: center;
10
+
11
+ .confirmation-modal-actions {
12
+ display: grid;
13
+ grid-auto-flow: column;
14
+ justify-content: center;
15
+ gap: 1em;
16
+ }
17
+ }