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,117 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { useClassNames, useInputHandlers } from '../../../hooks';
4
+ import { Controller } from '../controller';
5
+ import { Field, InputFieldProps } from '../field';
6
+ import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
7
+
8
+ import './slider.styles.css';
9
+
10
+ type SliderProps = InputFieldProps<{
11
+ min?: number;
12
+ max?: number;
13
+ step?: number;
14
+ onlySlider?: boolean;
15
+ }>;
16
+
17
+ export const Slider = ({
18
+ name,
19
+ value,
20
+ setValue,
21
+ onBlur,
22
+ onFocus,
23
+ min,
24
+ max,
25
+ step,
26
+ onlySlider = false,
27
+ className = '',
28
+ style = {},
29
+ autoFocus = false,
30
+ readOnly = false,
31
+ disabled = false,
32
+ placeholder = '',
33
+ autoComplete = 'off',
34
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
35
+ isDirty = false,
36
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
37
+ isTouched = false,
38
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
39
+ invalid = false,
40
+ error,
41
+ ...fieldProps
42
+ }: UnControlledComponentProps<SliderProps, number>) => {
43
+ const id = useMemo(() => crypto.randomUUID(), []);
44
+ const onBlurInput = (e: React.FocusEvent<HTMLInputElement>) => {
45
+ if (onBlur) onBlur(e);
46
+
47
+ const parsedValue = parseInt(`${value}`);
48
+
49
+ if (min !== undefined && parsedValue < min) {
50
+ setValue(min);
51
+ }
52
+
53
+ if (max !== undefined && parsedValue > max) {
54
+ setValue(max);
55
+ }
56
+
57
+ setValue(parsedValue);
58
+ };
59
+
60
+ const { isFocus, handlers } = useInputHandlers({
61
+ onBlur: onBlurInput,
62
+ onChange: e => setValue(+e.target.value),
63
+ onFocus: onFocus,
64
+ });
65
+
66
+ const inputSliderClassName = useClassNames({
67
+ 'input-slider': true,
68
+ 'is-focus': isFocus,
69
+ });
70
+
71
+ return (
72
+ <Field id={id} error={error} isFocus={isFocus} {...fieldProps}>
73
+ <section className={inputSliderClassName}>
74
+ <input
75
+ id={id}
76
+ type='range'
77
+ name={name}
78
+ className={`slider ${className}`}
79
+ style={style}
80
+ value={value}
81
+ autoFocus={autoFocus}
82
+ autoComplete={autoComplete}
83
+ placeholder={placeholder}
84
+ disabled={disabled}
85
+ readOnly={readOnly}
86
+ min={min}
87
+ max={max}
88
+ step={step}
89
+ {...handlers}
90
+ />
91
+ {!onlySlider && (
92
+ <input
93
+ id={id}
94
+ type='number'
95
+ name={name}
96
+ className={`slider-number ${className}`}
97
+ style={style}
98
+ value={value}
99
+ autoComplete={autoComplete}
100
+ disabled={disabled}
101
+ readOnly={readOnly}
102
+ min={min}
103
+ max={max}
104
+ step={step}
105
+ {...handlers}
106
+ />
107
+ )}
108
+ </section>
109
+ </Field>
110
+ );
111
+ };
112
+
113
+ const SliderController = ({ rules, ...props }: ControllerGeneratorProps<SliderProps, number>) => {
114
+ return <Controller Component={Slider} defaultValue={0} inputProps={props} rules={rules} />;
115
+ };
116
+
117
+ Slider.Controller = SliderController;
@@ -0,0 +1,94 @@
1
+ @reference "polpo-tailwind-config/styles";
2
+
3
+ .input-slider {
4
+ display: grid;
5
+ grid-template-columns: 1fr 50px;
6
+ align-items: center;
7
+ gap: 10px;
8
+
9
+ .slider {
10
+ appearance: none;
11
+ -webkit-appearance: none;
12
+ -moz-appearance: none;
13
+ display: grid;
14
+ align-items: center;
15
+
16
+ &:focus {
17
+ outline: none;
18
+ }
19
+
20
+ &::-webkit-slider-thumb {
21
+ -webkit-appearance: none;
22
+ width: 20px;
23
+ height: 20px;
24
+ border-radius: 1em;
25
+ background: var(--color-primary-500);
26
+ box-shadow: 0 0 0 0 var(--color-gray-500);
27
+ margin-top: -8px;
28
+ transition: all 300ms ease;
29
+ cursor: pointer;
30
+ }
31
+
32
+ &::-webkit-slider-runnable-track {
33
+ height: 4px;
34
+ border-radius: 1em;
35
+ background: hsl(from var(--color-primary-200) h s l / 50%);
36
+ transition: all 300ms ease;
37
+ }
38
+
39
+ &:focus,
40
+ &:hover {
41
+ &::-webkit-slider-thumb {
42
+ background: var(--color-primary-500);
43
+ box-shadow: 0 0 0 6px hsl(from var(--color-primary-500) h s l / 50%);
44
+ cursor: grab;
45
+ }
46
+ }
47
+
48
+ &:active {
49
+ &::-webkit-slider-thumb {
50
+ box-shadow: 0 0 0 12px hsl(from var(--color-primary-500) h s l / 31%);
51
+ cursor: grabbing;
52
+ }
53
+ }
54
+
55
+ &:focus {
56
+ &::-webkit-slider-runnable-track {
57
+ background: var(--color-primary-300);
58
+ }
59
+ }
60
+ }
61
+
62
+ &:has(.slider-number:focus) .slider::-webkit-slider-thumb,
63
+ &:has(.slider-number:hover) .slider::-webkit-slider-thumb {
64
+ background: var(--color-primary-500);
65
+ box-shadow: 0 0 0 6px hsl(from var(--color-primary-500) h s l / 31%);
66
+ }
67
+
68
+ .slider-number {
69
+ transition: all 300ms ease;
70
+ border: 1px solid;
71
+ border-radius: 5px;
72
+ text-align: center;
73
+ @apply text-label;
74
+ appearance: none;
75
+ -webkit-appearance: none;
76
+ -moz-appearance: none;
77
+ width: 100%;
78
+ padding: 4px 8px;
79
+ font-weight: bold;
80
+ color: inherit;
81
+
82
+ &::-webkit-outer-spin-button,
83
+ &::-webkit-inner-spin-button {
84
+ -webkit-appearance: none;
85
+ margin: 0;
86
+ }
87
+ }
88
+
89
+ &.is-focus {
90
+ .slider-number {
91
+ color: var(--color-primary-500);
92
+ }
93
+ }
94
+ }
@@ -0,0 +1 @@
1
+ export * from './switch.component';
@@ -0,0 +1,166 @@
1
+ import { useMemo } from 'react';
2
+ import { IconType } from 'react-icons';
3
+
4
+ import { useClassNames, useInputHandlers } from '../../../hooks';
5
+ import { ColorTypes, SizeTypes } from '../../component.types';
6
+ import { Tooltip } from '../../tooltips';
7
+ import { Typography } from '../../typography';
8
+ import { Controller } from '../controller';
9
+ import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
10
+
11
+ import './switch.styles.css';
12
+
13
+ const DotSizeMap = {
14
+ [SizeTypes.SMALL]: 1,
15
+ [SizeTypes.REGULAR]: 1.2,
16
+ [SizeTypes.LARGE]: 1.4,
17
+ };
18
+
19
+ const WidthMap = {
20
+ [SizeTypes.SMALL]: 2,
21
+ [SizeTypes.REGULAR]: 2.5,
22
+ [SizeTypes.LARGE]: 3,
23
+ };
24
+
25
+ type SwitchProps = {
26
+ leftLabel?: string;
27
+ rightLabel?: string;
28
+ label?: string;
29
+ dotHoverSize?: number;
30
+ padding?: number;
31
+ leftIcon?: IconType;
32
+ rightIcon?: IconType;
33
+ internalLeftIcon?: IconType;
34
+ internalRightIcon?: IconType;
35
+ leftIconTooltip?: string;
36
+ rightIconTooltip?: string;
37
+ color?: `${ColorTypes}`;
38
+ size?: `${SizeTypes}`;
39
+ width?: `${SizeTypes}`;
40
+ };
41
+
42
+ export const Switch = ({
43
+ name,
44
+ value,
45
+ setValue,
46
+ onBlur,
47
+ onFocus,
48
+ className = '',
49
+ style = {},
50
+ autoFocus = false,
51
+ readOnly = false,
52
+ disabled = false,
53
+ placeholder = '',
54
+ autoComplete = 'off',
55
+ label,
56
+ leftLabel,
57
+ rightLabel,
58
+ width = SizeTypes.REGULAR,
59
+ size = SizeTypes.REGULAR,
60
+ dotHoverSize = 1.3,
61
+ padding = 0.25,
62
+ leftIcon: LeftIcon,
63
+ rightIcon: RightIcon,
64
+ internalLeftIcon: InternalLeftIcon,
65
+ internalRightIcon: InternalRightIcon,
66
+ leftIconTooltip,
67
+ rightIconTooltip,
68
+ color,
69
+ /*
70
+ * isDirty = false,
71
+ * isTouched = false,
72
+ * invalid = false,
73
+ * error,
74
+ */
75
+ }: UnControlledComponentProps<SwitchProps, boolean>) => {
76
+ const id = useMemo(() => crypto.randomUUID(), []);
77
+ const { handlers } = useInputHandlers<HTMLInputElement>({
78
+ onChange: e => setValue(e.target.checked),
79
+ onBlur: onBlur,
80
+ onFocus: onFocus,
81
+ });
82
+
83
+ const switchContainerClassName = useClassNames({
84
+ 'switch-container': true,
85
+ [className]: Boolean(className),
86
+ [`color-${color}`]: Boolean(color),
87
+ });
88
+
89
+ const switchClassName = useClassNames({
90
+ switch: true,
91
+ 'is-checked': value,
92
+ 'is-readonly': !disabled && readOnly,
93
+ });
94
+
95
+ const dotSize = DotSizeMap[size] ?? DotSizeMap[SizeTypes.REGULAR];
96
+ const _width = (WidthMap[width] ?? WidthMap[SizeTypes.REGULAR]) * dotSize;
97
+ const _padding = Math.min(padding, dotSize);
98
+
99
+ return (
100
+ <section
101
+ className={switchContainerClassName}
102
+ style={
103
+ {
104
+ ...style,
105
+ '--width': `${_width}em`,
106
+ '--dot-size': `${dotSize}em`,
107
+ '--dot-hover-size': `${dotSize * Math.min(Math.max(dotHoverSize, 1), 2)}em`,
108
+ '--padding': `${_padding}em`,
109
+ } as React.CSSProperties
110
+ }
111
+ >
112
+ {leftLabel ? (
113
+ <Typography variant='label-form' className='switch-label' htmlFor={id}>
114
+ {leftLabel}
115
+ </Typography>
116
+ ) : null}
117
+ {LeftIcon !== undefined && (
118
+ <Tooltip content={leftIconTooltip} disabled={!leftIconTooltip} offset={10}>
119
+ <LeftIcon size={`${dotSize * 0.7}em`} className='switch-icon' onClick={() => setValue(!value)} />
120
+ </Tooltip>
121
+ )}
122
+ <section className={switchClassName}>
123
+ {InternalLeftIcon !== undefined && (
124
+ <span className='switch-internal-left-icon'>
125
+ <InternalLeftIcon size={`${dotSize * 0.7}em`} />
126
+ </span>
127
+ )}
128
+ {InternalRightIcon !== undefined && (
129
+ <span className='switch-internal-right-icon'>
130
+ <InternalRightIcon size={`${dotSize * 0.7}em`} />
131
+ </span>
132
+ )}
133
+ <span className='switch-dot' />
134
+ <input
135
+ id={id}
136
+ type='checkbox'
137
+ name={name}
138
+ className={`switch-checkbox ${className}`}
139
+ style={style}
140
+ checked={value}
141
+ autoFocus={autoFocus}
142
+ autoComplete={autoComplete}
143
+ placeholder={placeholder}
144
+ disabled={disabled || readOnly}
145
+ {...handlers}
146
+ />
147
+ </section>
148
+ {RightIcon !== undefined && (
149
+ <Tooltip content={rightIconTooltip} disabled={!rightIconTooltip} offset={10}>
150
+ <RightIcon size={`${dotSize * 0.7}em`} className='switch-icon' onClick={() => setValue(!value)} />
151
+ </Tooltip>
152
+ )}
153
+ {label || rightLabel ? (
154
+ <Typography variant='label-form' className='switch-label' htmlFor={id}>
155
+ {label || rightLabel}
156
+ </Typography>
157
+ ) : null}
158
+ </section>
159
+ );
160
+ };
161
+
162
+ const SwitchController = ({ rules, ...props }: ControllerGeneratorProps<SwitchProps, boolean>) => {
163
+ return <Controller Component={Switch} defaultValue={false} inputProps={props} rules={rules} />;
164
+ };
165
+
166
+ Switch.Controller = SwitchController;
@@ -0,0 +1,165 @@
1
+ @reference "polpo-tailwind-config/styles";
2
+
3
+ .switch-container {
4
+ --width: attr(data-width);
5
+ --dot-size: attr(data-dot-size);
6
+ --dot-hover-size: attr(data-dot-hover-size);
7
+ --padding: attr(data-padding);
8
+ --color: var(--color-gray-500);
9
+ --color-dark: var(--color-gray-800);
10
+ --color-contrast: var(--color-gray-50);
11
+
12
+ display: flex;
13
+ align-items: center;
14
+ gap: 0.5em;
15
+ width: fit-content;
16
+
17
+ .switch {
18
+ width: calc(var(--width) + var(--padding) * 2);
19
+ border-radius: 100em;
20
+ background: var(--color-background-paper);
21
+ padding: var(--padding);
22
+ transition: all 300ms ease;
23
+ position: relative;
24
+
25
+ .switch-dot {
26
+ width: var(--dot-size);
27
+ height: var(--dot-size);
28
+ border-radius: 100em;
29
+ background: var(--color);
30
+ display: block;
31
+ transition: all 300ms ease;
32
+ margin-left: 0;
33
+ position: relative;
34
+ z-index: 1;
35
+ }
36
+
37
+ .switch-icon {
38
+ cursor: pointer;
39
+ display: block;
40
+ }
41
+
42
+ .switch-internal-left-icon,
43
+ .switch-internal-right-icon {
44
+ width: var(--dot-size);
45
+ height: var(--dot-size);
46
+ position: absolute;
47
+ top: var(--padding);
48
+ display: grid;
49
+ place-content: center;
50
+ color: var(--color-contrast);
51
+ transition: all 300ms ease;
52
+ }
53
+
54
+ .switch-internal-left-icon {
55
+ left: var(--padding);
56
+ }
57
+
58
+ .switch-internal-right-icon {
59
+ right: var(--padding);
60
+ }
61
+
62
+ &.is-checked {
63
+ background: var(--color);
64
+
65
+ .switch-dot {
66
+ margin-left: calc(var(--width) - var(--dot-size));
67
+ background: color-mix(in hsl, var(--color), var(--color-contrast) 75%);
68
+ }
69
+ }
70
+
71
+ &:not(.is-readonly):has(input:disabled) {
72
+ background: var(--color-background-disabled);
73
+
74
+ .switch-dot {
75
+ background: var(--color-foreground-disabled);
76
+ }
77
+
78
+ .switch-internal-left-icon,
79
+ .switch-internal-right-icon {
80
+ color: var(--color-foreground-disabled);
81
+ }
82
+
83
+ &.is-checked {
84
+ background: var(--color-dark);
85
+ }
86
+ }
87
+
88
+ .switch-checkbox {
89
+ position: absolute;
90
+ top: 0;
91
+ left: 0;
92
+ width: 100%;
93
+ height: 100%;
94
+ cursor: pointer;
95
+ opacity: 0;
96
+ z-index: 3;
97
+ }
98
+ }
99
+
100
+ .switch-label {
101
+ cursor: pointer;
102
+ user-select: none;
103
+ padding: 0 0.5em;
104
+ }
105
+
106
+ .switch:not(:has(.is-readonly, input:disabled)):hover .switch-dot,
107
+ &:has(.switch-icon:hover) .switch:not(:has(.is-readonly, input:disabled)) .switch-dot,
108
+ &:has(.switch-label:hover) .switch:not(:has(.is-readonly, input:disabled)) .switch-dot {
109
+ box-shadow: 0 0 0 calc(0.3 * var(--dot-size)) color-mix(in hsl, var(--color) 50%, var(--color-contrast));
110
+ }
111
+
112
+ .switch:not(:has(.is-readonly, input:disabled)):active .switch-dot,
113
+ &:has(.switch-icon:active) .switch:not(:has(.is-readonly, input:disabled)) .switch-dot,
114
+ &:has(.switch-label:active) .switch:not(:has(.is-readonly, input:disabled)) .switch-dot {
115
+ width: var(--dot-hover-size);
116
+ }
117
+
118
+ .switch:not(:has(.is-readonly, input:disabled)).is-checked:active .switch-dot,
119
+ &:has(.switch-icon:active) .switch:not(:has(.is-readonly, input:disabled)).is-checked .switch-dot,
120
+ &:has(.switch-label:active) .switch:not(:has(.is-readonly, input:disabled)).is-checked .switch-dot {
121
+ margin-left: calc(var(--width) - var(--dot-hover-size));
122
+ }
123
+
124
+ &.color-primary {
125
+ --color: var(--color-primary-500);
126
+ --color-dark: var(--color-primary-700);
127
+ --color-contrast: var(--color-primary-50);
128
+ }
129
+
130
+ &.color-secondary {
131
+ --color: var(--color-secondary-500);
132
+ --color-dark: var(--color-secondary-700);
133
+ --color-contrast: var(--color-secondary-50);
134
+ }
135
+
136
+ &.color-tertiary {
137
+ --color: var(--color-tertiary-500);
138
+ --color-dark: var(--color-tertiary-700);
139
+ --color-contrast: var(--color-tertiary-50);
140
+ }
141
+
142
+ &.color-active {
143
+ --color: var(--color-active-500);
144
+ --color-dark: var(--color-active-700);
145
+ --color-contrast: var(--color-active-50);
146
+ }
147
+
148
+ &.color-warning {
149
+ --color: var(--color-warning-500);
150
+ --color-dark: var(--color-warning-700);
151
+ --color-contrast: var(--color-warning-50);
152
+ }
153
+
154
+ &.color-alert {
155
+ --color: var(--color-alert-500);
156
+ --color-dark: var(--color-alert-700);
157
+ --color-contrast: var(--color-alert-50);
158
+ }
159
+
160
+ &.color-info {
161
+ --color: var(--color-info-500);
162
+ --color-dark: var(--color-info-700);
163
+ --color-contrast: var(--color-info-50);
164
+ }
165
+ }
@@ -0,0 +1 @@
1
+ export * from './textarea.component';
@@ -0,0 +1,80 @@
1
+ import React, { useMemo } from 'react';
2
+
3
+ import { useClassNames, useInputHandlers } from '../../../hooks';
4
+ import { Controller } from '../controller';
5
+ import { Field, InputFieldProps } from '../field';
6
+ import { ControllerGeneratorProps, UnControlledComponentProps } from '../form.types';
7
+
8
+ import './textarea.styles.css';
9
+
10
+ type TextareaProps = InputFieldProps<{
11
+ rows?: number;
12
+ resize?: React.CSSProperties['resize'];
13
+ leftIcon?: never;
14
+ rightIcon?: never;
15
+ }>;
16
+
17
+ export const Textarea = ({
18
+ name,
19
+ value,
20
+ setValue,
21
+ onBlur,
22
+ onFocus,
23
+ rows = 4,
24
+ resize = 'vertical',
25
+ className = '',
26
+ style = {},
27
+ autoFocus = false,
28
+ readOnly = false,
29
+ disabled = false,
30
+ placeholder = '',
31
+ autoComplete = 'off',
32
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
33
+ isDirty = false,
34
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
35
+ isTouched = false,
36
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
37
+ invalid = false,
38
+ error,
39
+ ...fieldProps
40
+ }: UnControlledComponentProps<TextareaProps, string>) => {
41
+ const id = useMemo(() => crypto.randomUUID(), []);
42
+ const { handlers, isFocus } = useInputHandlers<HTMLTextAreaElement>({
43
+ onBlur: onBlur,
44
+ onChange: e => setValue(e.target.value),
45
+ onFocus: onFocus,
46
+ });
47
+
48
+ const textareaClassName = useClassNames({
49
+ textarea: true,
50
+ [className]: Boolean(className),
51
+ });
52
+
53
+ return (
54
+ <Field id={id} error={error} isFocus={isFocus} {...fieldProps}>
55
+ <textarea
56
+ id={id}
57
+ name={name}
58
+ className={textareaClassName}
59
+ style={{
60
+ resize: resize,
61
+ ...style,
62
+ }}
63
+ value={value}
64
+ rows={rows}
65
+ {...handlers}
66
+ autoFocus={autoFocus}
67
+ autoComplete={autoComplete}
68
+ placeholder={placeholder}
69
+ disabled={disabled}
70
+ readOnly={readOnly}
71
+ />
72
+ </Field>
73
+ );
74
+ };
75
+
76
+ const TextareaController = ({ rules, ...props }: ControllerGeneratorProps<TextareaProps, string>) => {
77
+ return <Controller Component={Textarea} defaultValue='' inputProps={props} rules={rules} />;
78
+ };
79
+
80
+ Textarea.Controller = TextareaController;
@@ -0,0 +1,7 @@
1
+ @reference "polpo-tailwind-config/styles";
2
+
3
+ .textarea {
4
+ border: 0;
5
+ outline: 0;
6
+ field-sizing: content;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { DetailedHTMLProps, ImgHTMLAttributes } from 'react';
2
+
3
+ type ImageProps = DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> & {};
4
+
5
+ export const Image = ({ alt = '', loading = 'eager', ...props }: ImageProps) => {
6
+ return <img loading={loading} alt={alt} {...props} width='100%' />;
7
+ };
@@ -0,0 +1 @@
1
+ export * from './image';
@@ -0,0 +1,15 @@
1
+ export * from './accordion';
2
+ export * from './button';
3
+ export * from './cards';
4
+ export * from './cursor';
5
+ export * from './form';
6
+ export * from './image';
7
+ export * from './infinity-scroll';
8
+ export * from './line';
9
+ export * from './modals';
10
+ export * from './ripple';
11
+ export * from './smart-table';
12
+ export * from './tabs';
13
+ export * from './tag';
14
+ export * from './tooltips';
15
+ export * from './typography';
@@ -0,0 +1 @@
1
+ export * from './infinity-scroll.component';