create-react-scaffold-cli 1.0.6 → 1.1.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.
Files changed (196) hide show
  1. package/bin/index.js +15 -5
  2. package/package.json +21 -7
  3. package/scripts/createProject.js +8 -2
  4. package/templates/{base → base-js}/src/shared/utils/parser.js +1 -1
  5. package/templates/base-ts/.husky/pre-commit +1 -0
  6. package/templates/base-ts/.husky/pre-push +0 -0
  7. package/templates/base-ts/.prettierrc +8 -0
  8. package/templates/base-ts/.vscode/extensions.json +8 -0
  9. package/templates/base-ts/.vscode/settings.json +16 -0
  10. package/templates/base-ts/README.md +165 -0
  11. package/templates/base-ts/docs/DOCS.md +7 -0
  12. package/templates/base-ts/eslint.config.js +56 -0
  13. package/templates/base-ts/index.html +16 -0
  14. package/templates/base-ts/jsconfig.json +7 -0
  15. package/templates/base-ts/package.json +69 -0
  16. package/templates/base-ts/postcss.config.mjs +7 -0
  17. package/templates/base-ts/public/icons/react.svg +1 -0
  18. package/templates/base-ts/src/app/APP.md +74 -0
  19. package/templates/base-ts/src/app/App.tsx +15 -0
  20. package/templates/base-ts/src/app/Router.tsx +48 -0
  21. package/templates/base-ts/src/app/index.css +37 -0
  22. package/templates/base-ts/src/app/main.tsx +13 -0
  23. package/templates/base-ts/src/app/middlewares/AuthMiddleware.tsx +6 -0
  24. package/templates/base-ts/src/app/middlewares/index.ts +1 -0
  25. package/templates/base-ts/src/app/providers/QueryProvider.tsx +75 -0
  26. package/templates/base-ts/src/app/providers/index.ts +1 -0
  27. package/templates/base-ts/src/app/routes.registry.ts +9 -0
  28. package/templates/base-ts/src/features/FEATURES.md +102 -0
  29. package/templates/base-ts/src/features/sample/components/index.ts +0 -0
  30. package/templates/base-ts/src/features/sample/constants/index.ts +3 -0
  31. package/templates/base-ts/src/features/sample/constants/sample.assets.ts +8 -0
  32. package/templates/base-ts/src/features/sample/constants/sample.navigations.ts +5 -0
  33. package/templates/base-ts/src/features/sample/constants/sample.queryKeys.ts +3 -0
  34. package/templates/base-ts/src/features/sample/hooks/index.ts +0 -0
  35. package/templates/base-ts/src/features/sample/index.ts +1 -0
  36. package/templates/base-ts/src/features/sample/pages/SamplePage.tsx +7 -0
  37. package/templates/base-ts/src/features/sample/pages/index.ts +1 -0
  38. package/templates/base-ts/src/features/sample/sample.routes.ts +13 -0
  39. package/templates/base-ts/src/features/welcome/components/CodeLine.tsx +59 -0
  40. package/templates/base-ts/src/features/welcome/components/Divider.tsx +11 -0
  41. package/templates/base-ts/src/features/welcome/components/Footer.tsx +78 -0
  42. package/templates/base-ts/src/features/welcome/components/Hero.tsx +131 -0
  43. package/templates/base-ts/src/features/welcome/components/IconLink.tsx +24 -0
  44. package/templates/base-ts/src/features/welcome/components/QuickStartPanel.tsx +63 -0
  45. package/templates/base-ts/src/features/welcome/components/RingSoft.tsx +21 -0
  46. package/templates/base-ts/src/features/welcome/components/StorySections.tsx +63 -0
  47. package/templates/base-ts/src/features/welcome/components/WhatYouGet.tsx +49 -0
  48. package/templates/base-ts/src/features/welcome/components/index.ts +5 -0
  49. package/templates/base-ts/src/features/welcome/constants/index.ts +2 -0
  50. package/templates/base-ts/src/features/welcome/constants/welcome.constants.ts +21 -0
  51. package/templates/base-ts/src/features/welcome/constants/welcome.navigations.ts +3 -0
  52. package/templates/base-ts/src/features/welcome/index.ts +1 -0
  53. package/templates/base-ts/src/features/welcome/pages/WelcomePage.tsx +28 -0
  54. package/templates/base-ts/src/features/welcome/pages/index.ts +1 -0
  55. package/templates/base-ts/src/features/welcome/welcome.routes.ts +13 -0
  56. package/templates/base-ts/src/shared/SHARED.md +104 -0
  57. package/templates/base-ts/src/shared/constants/app.constants.ts +11 -0
  58. package/templates/base-ts/src/shared/constants/assets.constants.ts +5 -0
  59. package/templates/base-ts/src/shared/constants/index.ts +2 -0
  60. package/templates/base-ts/src/shared/contexts/index.ts +0 -0
  61. package/templates/base-ts/src/shared/hooks/index.ts +3 -0
  62. package/templates/base-ts/src/shared/hooks/useBooleanState.ts +19 -0
  63. package/templates/base-ts/src/shared/hooks/useDebounce.ts +17 -0
  64. package/templates/base-ts/src/shared/hooks/useToggleState.ts +11 -0
  65. package/templates/base-ts/src/shared/layouts/index.ts +0 -0
  66. package/templates/base-ts/src/shared/libs/axios.ts +6 -0
  67. package/templates/base-ts/src/shared/libs/cn.ts +6 -0
  68. package/templates/base-ts/src/shared/libs/index.ts +2 -0
  69. package/templates/base-ts/src/shared/theme/index.ts +1 -0
  70. package/templates/base-ts/src/shared/theme/theme.ts +2149 -0
  71. package/templates/base-ts/src/shared/types/navigation.ts +9 -0
  72. package/templates/base-ts/src/shared/types/ui.ts +5 -0
  73. package/templates/base-ts/src/shared/ui/Box.tsx +153 -0
  74. package/templates/base-ts/src/shared/ui/Button.tsx +124 -0
  75. package/templates/base-ts/src/shared/ui/Checkbox.tsx +87 -0
  76. package/templates/base-ts/src/shared/ui/DropdownMenu.tsx +134 -0
  77. package/templates/base-ts/src/shared/ui/Flex.tsx +96 -0
  78. package/templates/base-ts/src/shared/ui/FlexItem.tsx +67 -0
  79. package/templates/base-ts/src/shared/ui/FormField.tsx +139 -0
  80. package/templates/base-ts/src/shared/ui/Grid.tsx +96 -0
  81. package/templates/base-ts/src/shared/ui/GridItem.tsx +67 -0
  82. package/templates/base-ts/src/shared/ui/Modal.tsx +42 -0
  83. package/templates/base-ts/src/shared/ui/Scrollable.tsx +48 -0
  84. package/templates/base-ts/src/shared/ui/Select.tsx +212 -0
  85. package/templates/base-ts/src/shared/ui/Sheet.tsx +126 -0
  86. package/templates/base-ts/src/shared/ui/Text.tsx +99 -0
  87. package/templates/base-ts/src/shared/ui/Toaster.tsx +31 -0
  88. package/templates/base-ts/src/shared/ui/index.ts +20 -0
  89. package/templates/base-ts/src/shared/utils/getClassName.ts +8 -0
  90. package/templates/base-ts/src/shared/utils/index.ts +4 -0
  91. package/templates/base-ts/src/shared/utils/localStorage.ts +18 -0
  92. package/templates/base-ts/src/shared/utils/memo.ts +9 -0
  93. package/templates/base-ts/src/shared/utils/motion.ts +0 -0
  94. package/templates/base-ts/src/shared/utils/parser.ts +41 -0
  95. package/templates/base-ts/src/shared/utils/regix.ts +3 -0
  96. package/templates/base-ts/src/shared/utils/tryCatch.ts +16 -0
  97. package/templates/base-ts/src/vite-env.d.ts +1 -0
  98. package/templates/base-ts/tsconfig.json +33 -0
  99. package/templates/base-ts/tsconfig.node.json +11 -0
  100. package/templates/base-ts/tsconfig.tsbuildinfo +1 -0
  101. package/templates/base-ts/vercel.json +3 -0
  102. package/templates/base-ts/vite.config.d.ts +2 -0
  103. package/templates/base-ts/vite.config.ts +18 -0
  104. /package/templates/{base → base-js}/.husky/pre-commit +0 -0
  105. /package/templates/{base → base-js}/.husky/pre-push +0 -0
  106. /package/templates/{base → base-js}/.prettierrc +0 -0
  107. /package/templates/{base → base-js}/.vscode/extensions.json +0 -0
  108. /package/templates/{base → base-js}/.vscode/settings.json +0 -0
  109. /package/templates/{base → base-js}/README.md +0 -0
  110. /package/templates/{base → base-js}/docs/DOCS.md +0 -0
  111. /package/templates/{base → base-js}/eslint.config.js +0 -0
  112. /package/templates/{base → base-js}/index.html +0 -0
  113. /package/templates/{base → base-js}/jsconfig.json +0 -0
  114. /package/templates/{base → base-js}/package.json +0 -0
  115. /package/templates/{base → base-js}/postcss.config.mjs +0 -0
  116. /package/templates/{base → base-js}/public/icons/react.svg +0 -0
  117. /package/templates/{base → base-js}/src/app/APP.md +0 -0
  118. /package/templates/{base → base-js}/src/app/App.jsx +0 -0
  119. /package/templates/{base → base-js}/src/app/Router.jsx +0 -0
  120. /package/templates/{base → base-js}/src/app/index.css +0 -0
  121. /package/templates/{base → base-js}/src/app/main.jsx +0 -0
  122. /package/templates/{base → base-js}/src/app/middlewares/AuthMiddleware.jsx +0 -0
  123. /package/templates/{base → base-js}/src/app/middlewares/index.js +0 -0
  124. /package/templates/{base → base-js}/src/app/providers/QueryProvider.jsx +0 -0
  125. /package/templates/{base → base-js}/src/app/providers/index.js +0 -0
  126. /package/templates/{base → base-js}/src/app/routes.registry.js +0 -0
  127. /package/templates/{base → base-js}/src/features/FEATURES.md +0 -0
  128. /package/templates/{base → base-js}/src/features/sample/components/index.js +0 -0
  129. /package/templates/{base → base-js}/src/features/sample/constants/index.js +0 -0
  130. /package/templates/{base → base-js}/src/features/sample/constants/sample.assets.js +0 -0
  131. /package/templates/{base → base-js}/src/features/sample/constants/sample.constants.js +0 -0
  132. /package/templates/{base → base-js}/src/features/sample/constants/sample.navigations.js +0 -0
  133. /package/templates/{base → base-js}/src/features/sample/constants/sample.queryKeys.js +0 -0
  134. /package/templates/{base → base-js}/src/features/sample/hooks/index.js +0 -0
  135. /package/templates/{base → base-js}/src/features/sample/index.js +0 -0
  136. /package/templates/{base → base-js}/src/features/sample/pages/SamplePage.jsx +0 -0
  137. /package/templates/{base → base-js}/src/features/sample/pages/index.js +0 -0
  138. /package/templates/{base → base-js}/src/features/sample/sample.context.js +0 -0
  139. /package/templates/{base → base-js}/src/features/sample/sample.routes.js +0 -0
  140. /package/templates/{base → base-js}/src/features/welcome/components/CodeLine.jsx +0 -0
  141. /package/templates/{base → base-js}/src/features/welcome/components/Divider.jsx +0 -0
  142. /package/templates/{base → base-js}/src/features/welcome/components/Footer.jsx +0 -0
  143. /package/templates/{base → base-js}/src/features/welcome/components/Hero.jsx +0 -0
  144. /package/templates/{base → base-js}/src/features/welcome/components/IconLink.jsx +0 -0
  145. /package/templates/{base → base-js}/src/features/welcome/components/QuickStartPanel.jsx +0 -0
  146. /package/templates/{base → base-js}/src/features/welcome/components/RingSoft.jsx +0 -0
  147. /package/templates/{base → base-js}/src/features/welcome/components/StorySections.jsx +0 -0
  148. /package/templates/{base → base-js}/src/features/welcome/components/WhatYouGet.jsx +0 -0
  149. /package/templates/{base → base-js}/src/features/welcome/components/index.js +0 -0
  150. /package/templates/{base → base-js}/src/features/welcome/constants/index.js +0 -0
  151. /package/templates/{base → base-js}/src/features/welcome/constants/welcome.constants.js +0 -0
  152. /package/templates/{base → base-js}/src/features/welcome/constants/welcome.navigations.js +0 -0
  153. /package/templates/{base → base-js}/src/features/welcome/index.js +0 -0
  154. /package/templates/{base → base-js}/src/features/welcome/pages/WelcomePage.jsx +0 -0
  155. /package/templates/{base → base-js}/src/features/welcome/pages/index.js +0 -0
  156. /package/templates/{base → base-js}/src/features/welcome/welcome.routes.js +0 -0
  157. /package/templates/{base → base-js}/src/shared/SHARED.md +0 -0
  158. /package/templates/{base → base-js}/src/shared/constants/app.constants.js +0 -0
  159. /package/templates/{base → base-js}/src/shared/constants/assets.constants.js +0 -0
  160. /package/templates/{base → base-js}/src/shared/constants/index.js +0 -0
  161. /package/templates/{base → base-js}/src/shared/contexts/index.js +0 -0
  162. /package/templates/{base → base-js}/src/shared/hooks/index.js +0 -0
  163. /package/templates/{base → base-js}/src/shared/hooks/useBooleanState.js +0 -0
  164. /package/templates/{base → base-js}/src/shared/hooks/useDebounce.js +0 -0
  165. /package/templates/{base → base-js}/src/shared/hooks/useToggleState.js +0 -0
  166. /package/templates/{base → base-js}/src/shared/layouts/index.js +0 -0
  167. /package/templates/{base → base-js}/src/shared/libs/axios.js +0 -0
  168. /package/templates/{base → base-js}/src/shared/libs/cn.js +0 -0
  169. /package/templates/{base → base-js}/src/shared/libs/index.js +0 -0
  170. /package/templates/{base → base-js}/src/shared/theme/index.js +0 -0
  171. /package/templates/{base → base-js}/src/shared/theme/theme.js +0 -0
  172. /package/templates/{base → base-js}/src/shared/ui/Box.jsx +0 -0
  173. /package/templates/{base → base-js}/src/shared/ui/Button.jsx +0 -0
  174. /package/templates/{base → base-js}/src/shared/ui/Checkbox.jsx +0 -0
  175. /package/templates/{base → base-js}/src/shared/ui/DropdownMenu.jsx +0 -0
  176. /package/templates/{base → base-js}/src/shared/ui/Flex.jsx +0 -0
  177. /package/templates/{base → base-js}/src/shared/ui/FlexItem.jsx +0 -0
  178. /package/templates/{base → base-js}/src/shared/ui/FormField.jsx +0 -0
  179. /package/templates/{base → base-js}/src/shared/ui/Grid.jsx +0 -0
  180. /package/templates/{base → base-js}/src/shared/ui/GridItem.jsx +0 -0
  181. /package/templates/{base → base-js}/src/shared/ui/Modal.jsx +0 -0
  182. /package/templates/{base → base-js}/src/shared/ui/Scrollable.jsx +0 -0
  183. /package/templates/{base → base-js}/src/shared/ui/Select.jsx +0 -0
  184. /package/templates/{base → base-js}/src/shared/ui/Sheet.jsx +0 -0
  185. /package/templates/{base → base-js}/src/shared/ui/Text.jsx +0 -0
  186. /package/templates/{base → base-js}/src/shared/ui/Toaster.jsx +0 -0
  187. /package/templates/{base → base-js}/src/shared/ui/index.js +0 -0
  188. /package/templates/{base → base-js}/src/shared/utils/getClassName.js +0 -0
  189. /package/templates/{base → base-js}/src/shared/utils/index.js +0 -0
  190. /package/templates/{base → base-js}/src/shared/utils/localStorage.js +0 -0
  191. /package/templates/{base → base-js}/src/shared/utils/memo.js +0 -0
  192. /package/templates/{base → base-js}/src/shared/utils/motion.js +0 -0
  193. /package/templates/{base → base-js}/src/shared/utils/regix.js +0 -0
  194. /package/templates/{base → base-js}/src/shared/utils/tryCatch.js +0 -0
  195. /package/templates/{base → base-js}/vercel.json +0 -0
  196. /package/templates/{base → base-js}/vite.config.js +0 -0
@@ -0,0 +1,139 @@
1
+ import { ReactNode, useId } from 'react';
2
+ import {
3
+ fontSizeLookup,
4
+ fontSizeMdLookup,
5
+ fontSizeLgLookup,
6
+ fontWeightLookup,
7
+ fontWeightMdLookup,
8
+ fontWeightLgLookup,
9
+ gapLookup,
10
+ gapMdLookup,
11
+ gapLgLookup,
12
+ gapXlLookup,
13
+ fontSizeXlLookup,
14
+ fontWeightXlLookup,
15
+ fontSize2xlLookup,
16
+ fontWeight2xlLookup,
17
+ colorLookup,
18
+ } from '../theme';
19
+ import { Text } from './Text';
20
+ import { getClassName, memo } from '../utils';
21
+ import { cn } from '../libs';
22
+ import { Responsive } from '../types/ui';
23
+
24
+ export type Gap = keyof typeof gapLookup;
25
+ export type Size = keyof typeof fontSizeLookup;
26
+ export type Weight = keyof typeof fontWeightLookup;
27
+ export type Color = keyof typeof colorLookup;
28
+
29
+ export interface FormFieldProps {
30
+ label?: string;
31
+ labelFontSize?: Size | Responsive<Size>;
32
+ labelFontWeight?: Weight | Responsive<Weight>;
33
+ labelColor?: Color;
34
+ labelClass?: string;
35
+ gap?: Gap | Responsive<Gap>;
36
+ error?: string;
37
+ errorFontSize?: Size | Responsive<Size>;
38
+ errorFontWeight?: Weight | Responsive<Weight>;
39
+ errorColor?: Color | Responsive<Color>;
40
+ className?: string; // Type mismatch in original JSDoc vs Usage?
41
+ // Original JSDoc said className overrides? No, just passed.
42
+ // Actually JSDoc said className property but destructured className...
43
+ hide?: boolean | Responsive<boolean>;
44
+ hideLabel?: boolean | Responsive<boolean>;
45
+ children: ReactNode | ((id: string) => ReactNode);
46
+ }
47
+
48
+ const Component = ({
49
+ label,
50
+ labelFontSize,
51
+ labelFontWeight,
52
+ labelColor,
53
+ labelClass,
54
+ gap = 2,
55
+ hide,
56
+ hideLabel,
57
+ error,
58
+ errorFontSize = 'xs',
59
+ errorFontWeight = 'medium',
60
+ errorColor = 'danger',
61
+ className,
62
+ children,
63
+ }: FormFieldProps) => {
64
+ const id = useId();
65
+ const markup = typeof children === 'function' ? children(id) : children;
66
+
67
+ const g = gap as any;
68
+ const h = hide as any;
69
+ const hl = hideLabel as any;
70
+ const lfs = labelFontSize as any;
71
+ const lfw = labelFontWeight as any;
72
+
73
+ return (
74
+ <div
75
+ className={cn(
76
+ 'flex flex-col w-full',
77
+ typeof gap !== 'object' && getClassName(gap, gapLookup),
78
+ getClassName(g?.base, gapLookup),
79
+ getClassName(g?.md, gapMdLookup),
80
+ getClassName(g?.lg, gapLgLookup),
81
+ getClassName(g?.xl, gapXlLookup),
82
+ typeof hide !== 'object' && hide === true ? 'hidden' : hide === false && 'block',
83
+ h?.base === true ? 'hidden' : h?.base === false && 'block',
84
+ h?.md === true ? 'md:hidden' : h?.md === false && 'md:block',
85
+ h?.lg === true ? 'lg:hidden' : h?.lg === false && 'lg:block',
86
+ typeof className === 'string' && className
87
+ )}
88
+ >
89
+ {label && (
90
+ <div>
91
+ <label
92
+ htmlFor={id}
93
+ className={cn(
94
+ 'font-inter',
95
+ typeof hideLabel !== 'object' && hideLabel === true
96
+ ? 'hidden'
97
+ : hideLabel === false && 'block',
98
+ hl?.base === true ? 'hidden' : hl?.base === false && 'block',
99
+ hl?.md === true ? 'md:hidden' : hl?.md === false && 'md:block',
100
+ hl?.lg === true ? 'lg:hidden' : hl?.lg === false && 'lg:block',
101
+ typeof labelFontSize !== 'object' && getClassName(labelFontSize, fontSizeLookup),
102
+ getClassName(lfs?.base, fontSizeLookup),
103
+ getClassName(lfs?.md, fontSizeMdLookup),
104
+ getClassName(lfs?.lg, fontSizeLgLookup),
105
+ getClassName(lfs?.xl, fontSizeXlLookup),
106
+ getClassName(lfs?.['2xl'], fontSize2xlLookup),
107
+ typeof labelFontWeight !== 'object' &&
108
+ getClassName(labelFontWeight, fontWeightLookup),
109
+ getClassName(lfw?.base, fontWeightLookup),
110
+ getClassName(lfw?.md, fontWeightMdLookup),
111
+ getClassName(lfw?.lg, fontWeightLgLookup),
112
+ getClassName(lfw?.xl, fontWeightXlLookup),
113
+ getClassName(lfw?.['2xl'], fontWeight2xlLookup),
114
+ getClassName(labelColor, colorLookup),
115
+ labelClass
116
+ )}
117
+ >
118
+ {label}
119
+ </label>
120
+ </div>
121
+ )}
122
+ <div className="-mt-1!">{markup}</div>
123
+ {error && (
124
+ <div>
125
+ <Text
126
+ size={errorFontSize}
127
+ weight={errorFontWeight}
128
+ color={errorColor}
129
+ className="font-inter"
130
+ >
131
+ {error}
132
+ </Text>
133
+ </div>
134
+ )}
135
+ </div>
136
+ );
137
+ };
138
+
139
+ export const FormField = memo(Component);
@@ -0,0 +1,96 @@
1
+ import { getClassName, memo } from '../utils';
2
+ import { ComponentPropsWithRef, forwardRef, Ref } from 'react';
3
+ import {
4
+ gapLookup,
5
+ gapMdLookup,
6
+ gapLgLookup,
7
+ columnsLookup,
8
+ columnsMdLookup,
9
+ columnsLgLookup,
10
+ justifyLookup,
11
+ justifyMdLookup,
12
+ justifyLgLookup,
13
+ alignLookup,
14
+ alignMdLookup,
15
+ alignLgLookup,
16
+ widthLookup,
17
+ widthLgLookup,
18
+ widthMdLookup,
19
+ columnsSmLookup,
20
+ gapXlLookup,
21
+ columnsXlLookup,
22
+ justifyXlLookup,
23
+ alignXlLookup,
24
+ widthXlLookup,
25
+ columns2XlLookup,
26
+ } from '../theme';
27
+ import { cn } from '../libs';
28
+ import { Responsive } from '../types/ui';
29
+
30
+ export type Gap = keyof typeof gapLookup;
31
+ export type Columns = keyof typeof columnsLookup;
32
+ export type Justify = keyof typeof justifyLookup;
33
+ export type Align = keyof typeof alignLookup;
34
+ export type Width = keyof typeof widthLookup;
35
+
36
+ export interface GridProps extends ComponentPropsWithRef<'div'> {
37
+ grow?: boolean | Responsive<boolean>;
38
+ gap?: Gap | Responsive<Gap>;
39
+ columns?: Columns | Responsive<Columns>;
40
+ justify?: Justify | Responsive<Justify>;
41
+ align?: Align | Responsive<Align>;
42
+ width?: Width | Responsive<Width>;
43
+ }
44
+
45
+ const Component = ({ grow, gap, columns, justify, align, className, width, ...rest }: GridProps, ref: Ref<HTMLDivElement>) => {
46
+ const g = grow as any;
47
+ const gp = gap as any;
48
+ const c = columns as any;
49
+ const j = justify as any;
50
+ const a = align as any;
51
+ const w = width as any;
52
+
53
+ return (
54
+ <div
55
+ ref={ref}
56
+ className={cn(
57
+ 'grid',
58
+ typeof grow !== 'object' && grow === true ? 'h-full' : grow === false && 'h-auto',
59
+ g?.base === true ? 'h-full' : g?.base === false && 'h-auto',
60
+ g?.md === true ? 'md:h-full' : g?.md === false && 'md:h-auto',
61
+ g?.lg === true ? 'lg:h-full' : g?.lg === false && 'lg:h-auto',
62
+ typeof gap !== 'object' && getClassName(gap, gapLookup),
63
+ getClassName(gp?.base, gapLookup),
64
+ getClassName(gp?.md, gapMdLookup),
65
+ getClassName(gp?.lg, gapLgLookup),
66
+ getClassName(gp?.xl, gapXlLookup),
67
+ typeof columns !== 'object' && getClassName(columns, columnsLookup),
68
+ getClassName(c?.base, columnsLookup),
69
+ getClassName(c?.md, columnsMdLookup),
70
+ getClassName(c?.sm, columnsSmLookup),
71
+ getClassName(c?.lg, columnsLgLookup),
72
+ getClassName(c?.xl, columnsXlLookup),
73
+ getClassName(c?.['2xl'], columns2XlLookup),
74
+ typeof justify !== 'object' && getClassName(justify, justifyLookup),
75
+ getClassName(j?.base, justifyLookup),
76
+ getClassName(j?.md, justifyMdLookup),
77
+ getClassName(j?.lg, justifyLgLookup),
78
+ getClassName(j?.xl, justifyXlLookup),
79
+ typeof align !== 'object' && getClassName(align, alignLookup),
80
+ getClassName(a?.base, alignLookup),
81
+ getClassName(a?.md, alignMdLookup),
82
+ getClassName(a?.lg, alignLgLookup),
83
+ getClassName(a?.xl, alignXlLookup),
84
+ typeof width !== 'object' && getClassName(width, widthLookup),
85
+ getClassName(w?.base, widthLookup),
86
+ getClassName(w?.md, widthMdLookup),
87
+ getClassName(w?.lg, widthLgLookup),
88
+ getClassName(w?.xl, widthXlLookup),
89
+ className
90
+ )}
91
+ {...rest}
92
+ />
93
+ );
94
+ };
95
+
96
+ export const Grid = memo(forwardRef(Component));
@@ -0,0 +1,67 @@
1
+ import {
2
+ spanLookup,
3
+ spanMdLookup,
4
+ spanLgLookup,
5
+ alignSelfLookup,
6
+ alignSelfMdLookup,
7
+ alignSelfLgLookup,
8
+ widthLookup,
9
+ widthMdLookup,
10
+ widthLgLookup,
11
+ spanXlLookup,
12
+ alignSelfXlLookup,
13
+ widthXlLookup,
14
+ } from '../theme';
15
+ import { getClassName, memo } from '../utils';
16
+ import { cn } from '../libs';
17
+ import { ComponentPropsWithRef, forwardRef, Ref } from 'react';
18
+ import { Responsive } from '../types/ui';
19
+
20
+ export type Span = keyof typeof spanLookup;
21
+ export type AlignSelf = keyof typeof alignSelfLookup;
22
+ export type Width = keyof typeof widthLookup;
23
+
24
+ export interface GridItemProps extends ComponentPropsWithRef<'div'> {
25
+ hide?: boolean | Responsive<boolean>;
26
+ span?: Span | Responsive<Span>;
27
+ alignSelf?: AlignSelf | Responsive<AlignSelf>;
28
+ width?: Width | Responsive<Width>;
29
+ }
30
+
31
+ const Component = ({ hide, span, alignSelf, width, className, ...rest }: GridItemProps, ref: Ref<HTMLDivElement>) => {
32
+ const h = hide as any;
33
+ const s = span as any;
34
+ const as = alignSelf as any;
35
+ const w = width as any;
36
+
37
+ return (
38
+ <div
39
+ ref={ref}
40
+ className={cn(
41
+ typeof hide !== 'object' && hide === true ? 'hidden' : hide === false && 'block',
42
+ h?.base === true ? 'hidden' : h?.base === false && 'block',
43
+ h?.md === true ? 'md:hidden' : h?.md === false && 'md:block',
44
+ h?.lg === true ? 'lg:hidden' : h?.lg === false && 'lg:block',
45
+ typeof span !== 'object' && getClassName(span, spanLookup),
46
+ getClassName(s?.base, spanLookup),
47
+ getClassName(s?.md, spanMdLookup),
48
+ getClassName(s?.lg, spanLgLookup),
49
+ getClassName(s?.xl, spanXlLookup),
50
+ typeof alignSelf !== 'object' && getClassName(alignSelf, alignSelfLookup),
51
+ getClassName(as?.base, alignSelfLookup),
52
+ getClassName(as?.md, alignSelfMdLookup),
53
+ getClassName(as?.lg, alignSelfLgLookup),
54
+ getClassName(as?.xl, alignSelfXlLookup),
55
+ typeof width !== 'object' && getClassName(width, widthLookup),
56
+ getClassName(w?.base, widthLookup),
57
+ getClassName(w?.md, widthMdLookup),
58
+ getClassName(w?.lg, widthLgLookup),
59
+ getClassName(w?.xl, widthXlLookup),
60
+ className
61
+ )}
62
+ {...rest}
63
+ />
64
+ );
65
+ };
66
+
67
+ export const GridItem = memo(forwardRef(Component));
@@ -0,0 +1,42 @@
1
+ import { ReactNode, useCallback } from 'react';
2
+ import * as Dialog from '@radix-ui/react-dialog';
3
+ import { Scrollable } from './Scrollable';
4
+ import { cn } from '../libs';
5
+ import { memo } from '../utils';
6
+
7
+ export interface ModalProps {
8
+ isOpen: boolean;
9
+ onClose: () => void;
10
+ className?: string;
11
+ children?: ReactNode;
12
+ }
13
+
14
+ const Component = ({ isOpen, onClose, className, children }: ModalProps) => {
15
+ const onOpenChange = useCallback(
16
+ (open: boolean) => {
17
+ if (open) return;
18
+ onClose();
19
+ },
20
+ [onClose]
21
+ );
22
+
23
+ return (
24
+ <Dialog.Root open={isOpen} onOpenChange={onOpenChange}>
25
+ <Dialog.Portal>
26
+ <Dialog.Overlay className="fixed inset-0 z-50 bg-black/20 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" />
27
+ <Dialog.Content
28
+ aria-describedby={undefined}
29
+ className={cn(
30
+ 'fixed left-[50%] top-[50%] z-50 p-5 grid translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-2xl bg-white font-inter overflow-hidden',
31
+ className
32
+ )}
33
+ >
34
+ <Dialog.Title className="sr-only"></Dialog.Title>
35
+ <Scrollable indicatorClassName="!w-1">{children}</Scrollable>
36
+ </Dialog.Content>
37
+ </Dialog.Portal>
38
+ </Dialog.Root>
39
+ );
40
+ };
41
+
42
+ export const Modal = memo(Component);
@@ -0,0 +1,48 @@
1
+ import * as ScrollArea from '@radix-ui/react-scroll-area';
2
+ import { cn } from '../libs';
3
+ import { CSSProperties, memo, MouseEventHandler, ReactNode } from 'react';
4
+
5
+ export interface ScrollableProps {
6
+ orientation?: 'horizontal' | 'vertical';
7
+ className?: string;
8
+ children?: ReactNode;
9
+ style?: CSSProperties;
10
+ onClick?: MouseEventHandler<HTMLDivElement>;
11
+ indicatorClassName?: string;
12
+ viewPortClassName?: string;
13
+ }
14
+
15
+ const Component = ({
16
+ orientation = 'vertical',
17
+ className,
18
+ children,
19
+ style,
20
+ onClick,
21
+ indicatorClassName,
22
+ viewPortClassName,
23
+ }: ScrollableProps) => {
24
+ return (
25
+ <ScrollArea.Root
26
+ className={cn('size-full overflow-hidden', className)}
27
+ style={style}
28
+ onClick={onClick}
29
+ >
30
+ <ScrollArea.Viewport className={cn('size-full overflow-hidden', viewPortClassName)}>
31
+ {children}
32
+ </ScrollArea.Viewport>
33
+
34
+ <ScrollArea.Scrollbar
35
+ orientation={orientation}
36
+ className={cn(
37
+ orientation === 'vertical' ? 'w-1 lg:w-1.5 2xl:w-2' : 'h-1 lg:h-1.5 flex flex-col',
38
+ indicatorClassName
39
+ )}
40
+ >
41
+ <ScrollArea.Thumb className="relative flex-1 rounded bg-gray-400/50 hover:bg-gray-800/50 transition-colors" />
42
+ </ScrollArea.Scrollbar>
43
+ <ScrollArea.Corner />
44
+ </ScrollArea.Root>
45
+ );
46
+ };
47
+
48
+ export const Scrollable = memo(Component);
@@ -0,0 +1,212 @@
1
+ import { ComponentPropsWithoutRef, ElementRef, forwardRef, ReactElement, ReactNode, useCallback, useMemo } from 'react';
2
+ import * as SelectPrimitive from '@radix-ui/react-select';
3
+ import { FaChevronDown, FaChevronUp, FaCheck } from 'react-icons/fa6';
4
+ import { cn } from '../libs';
5
+
6
+ const SelectRoot = SelectPrimitive.Root;
7
+
8
+ const SelectValue = SelectPrimitive.Value;
9
+
10
+ const SelectTrigger = forwardRef<
11
+ ElementRef<typeof SelectPrimitive.Trigger>,
12
+ ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
13
+ >(({ className, children, ...props }, ref) => (
14
+ <SelectPrimitive.Trigger
15
+ ref={ref}
16
+ className={cn(
17
+ 'flex w-full items-center justify-between whitespace-nowrap rounded-10rd border bg-transparent px-3 py-2.5 font-inter text-sm placeholder:!text-custom-grey-900 placeholder:!opacity-30 disabled:cursor-not-allowed disabled:bg-neutral-50 [&>span]:line-clamp-1',
18
+ className
19
+ )}
20
+ {...props}
21
+ >
22
+ {children}
23
+ <SelectPrimitive.Icon asChild>
24
+ <FaChevronDown size={12} className="text-neutral-300" />
25
+ </SelectPrimitive.Icon>
26
+ </SelectPrimitive.Trigger>
27
+ ));
28
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
29
+
30
+ const SelectScrollUpButton = forwardRef<
31
+ ElementRef<typeof SelectPrimitive.ScrollUpButton>,
32
+ ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
33
+ >(({ className, ...props }, ref) => (
34
+ <SelectPrimitive.ScrollUpButton
35
+ ref={ref}
36
+ className={cn('flex cursor-default items-center justify-center py-1', className)}
37
+ {...props}
38
+ >
39
+ <FaChevronUp className="h-4 w-4" />
40
+ </SelectPrimitive.ScrollUpButton>
41
+ ));
42
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
43
+
44
+ const SelectScrollDownButton = forwardRef<
45
+ ElementRef<typeof SelectPrimitive.ScrollDownButton>,
46
+ ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
47
+ >(({ className, ...props }, ref) => (
48
+ <SelectPrimitive.ScrollDownButton
49
+ ref={ref}
50
+ className={cn('flex cursor-default items-center justify-center py-1', className)}
51
+ {...props}
52
+ />
53
+ ));
54
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
55
+
56
+ const SelectContent = forwardRef<
57
+ ElementRef<typeof SelectPrimitive.Content>,
58
+ ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
59
+ >(({ className, children, position = 'popper', ...props }, ref) => (
60
+ <SelectPrimitive.Portal>
61
+ <SelectPrimitive.Content
62
+ ref={ref}
63
+ className={cn(
64
+ 'relative z-[100] max-h-80 min-w-[8rem] font-inter overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 w-[var(--radix-select-trigger-width)]',
65
+ position === 'popper' &&
66
+ 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
67
+ className
68
+ )}
69
+ position={position}
70
+ {...props}
71
+ >
72
+ <SelectScrollUpButton className="text-secondary" />
73
+ <SelectPrimitive.Viewport
74
+ className={cn(
75
+ 'p-1',
76
+ position === 'popper' &&
77
+ 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] font-inter'
78
+ )}
79
+ >
80
+ {children}
81
+ </SelectPrimitive.Viewport>
82
+ <SelectScrollDownButton className="text-secondary" />
83
+ </SelectPrimitive.Content>
84
+ </SelectPrimitive.Portal>
85
+ ));
86
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
87
+
88
+ const SelectLabel = forwardRef<
89
+ ElementRef<typeof SelectPrimitive.Label>,
90
+ ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
91
+ >(({ className, ...props }, ref) => (
92
+ <SelectPrimitive.Label
93
+ ref={ref}
94
+ className={cn('px-2 py-1.5 text-13fs font-semibold font-inter', className)}
95
+ {...props}
96
+ />
97
+ ));
98
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
99
+
100
+ const SelectItem = forwardRef<
101
+ ElementRef<typeof SelectPrimitive.Item>,
102
+ ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
103
+ >(({ className, children, ...props }, ref) => (
104
+ <SelectPrimitive.Item
105
+ ref={ref}
106
+ className={cn(
107
+ 'relative flex w-full cursor-pointer select-none items-center hover:bg-neutral-100 rounded-sm py-1.5 pl-2 pr-8 text-sm focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 outline-none',
108
+ className
109
+ )}
110
+ {...props}
111
+ >
112
+ <span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
113
+ <SelectPrimitive.ItemIndicator>
114
+ <FaCheck className="h-4 w-4 text-secondary" />
115
+ </SelectPrimitive.ItemIndicator>
116
+ </span>
117
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
118
+ </SelectPrimitive.Item>
119
+ ));
120
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
121
+
122
+ const SelectSeparator = forwardRef<
123
+ ElementRef<typeof SelectPrimitive.Separator>,
124
+ ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
125
+ >(({ className, ...props }, ref) => (
126
+ <SelectPrimitive.Separator
127
+ ref={ref}
128
+ className={cn('-mx-1 my-1 h-px bg-muted', className)}
129
+ {...props}
130
+ />
131
+ ));
132
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
133
+
134
+ export interface SelectProps<T> {
135
+ placeholder?: string;
136
+ values: T[];
137
+ value: T | undefined;
138
+ getValueId?: (value: T) => string;
139
+ getValueLabel?: (value: T) => ReactNode;
140
+ onChange: (value: T) => void;
141
+ fullWidth?: boolean;
142
+ disabled?: boolean;
143
+ contentClass?: string;
144
+ customOption?: ReactNode;
145
+ }
146
+
147
+ const Component = <T,>({
148
+ placeholder = 'Seleccionar...',
149
+ value,
150
+ values,
151
+ getValueId = (val: any) => val.id,
152
+ getValueLabel = (val: any) => val.name,
153
+ onChange,
154
+ fullWidth,
155
+ customOption,
156
+ disabled,
157
+ contentClass,
158
+ }: SelectProps<T>) => {
159
+ let id: string | undefined;
160
+ if (value) {
161
+ id = getValueId(value);
162
+ }
163
+
164
+ const valuesLookup = useMemo(
165
+ () =>
166
+ values.reduce((acc, val) => {
167
+ const id = getValueId(val);
168
+ acc[id] = val;
169
+ return acc;
170
+ }, {} as Record<string, T>),
171
+ [getValueId, values]
172
+ );
173
+
174
+ const onValueChange = useCallback(
175
+ (id: string) => {
176
+ const selectedValue = valuesLookup[id];
177
+ onChange(selectedValue);
178
+ },
179
+ [onChange, valuesLookup]
180
+ );
181
+
182
+ return (
183
+ <SelectRoot value={id} onValueChange={onValueChange} disabled={disabled}>
184
+ <SelectTrigger
185
+ className={cn(
186
+ 'outline-none bg-white',
187
+ fullWidth ? 'w-full' : 'w-64',
188
+ 'data-placeholder:text-black/25'
189
+ )}
190
+ >
191
+ <SelectValue placeholder={placeholder} />
192
+ </SelectTrigger>
193
+ <SelectContent className={contentClass}>
194
+ {values.map((val, key) => {
195
+ const itemId = getValueId(val);
196
+ const label = getValueLabel(val);
197
+
198
+ return (
199
+ <SelectItem key={key} value={itemId}>
200
+ {label}
201
+ </SelectItem>
202
+ );
203
+ })}
204
+ {customOption}
205
+ </SelectContent>
206
+ </SelectRoot>
207
+ );
208
+ };
209
+
210
+ import { memo } from '../utils';
211
+
212
+ export const Select = memo(Component) as <T>(props: SelectProps<T>) => ReactElement;