anteriority-ui 1.0.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 (199) hide show
  1. package/.github/workflows/ci.yml +31 -0
  2. package/.github/workflows/publish.yml +45 -0
  3. package/.npmrc.bak +1 -0
  4. package/.storybook/main.js +15 -0
  5. package/.storybook/preview.jsx +26 -0
  6. package/AnteriorityUI.md +2400 -0
  7. package/CLAUDE.md +91 -0
  8. package/README.md +182 -0
  9. package/assets/anteriorityUI/AnteriorityUI.logo.jpeg +0 -0
  10. package/assets/favicon/anteriorityUI.ico +0 -0
  11. package/common/api/client.js +43 -0
  12. package/common/storage/LocalStorage.js +13 -0
  13. package/common/styles/typography.css +5 -0
  14. package/common/styles/variables.css +192 -0
  15. package/common/theme/muiTheme.js +9 -0
  16. package/features/password-reset/api.js +39 -0
  17. package/features/user-profile/api.js +5 -0
  18. package/hooks/useAdminPasswordReset.js +133 -0
  19. package/index.js +57 -0
  20. package/package.json +57 -0
  21. package/pnpm-workspace.yaml +3 -0
  22. package/screens/components/AlertModal/AlertModal.jsx +259 -0
  23. package/screens/components/AlertModal/AlertModal.module.css +185 -0
  24. package/screens/components/AlertModal/AlertModal.stories.jsx +87 -0
  25. package/screens/components/Avatar/index.jsx +0 -0
  26. package/screens/components/Avatar/index.module.css +0 -0
  27. package/screens/components/Avatar/utils.js +0 -0
  28. package/screens/components/Badge/index.jsx +33 -0
  29. package/screens/components/Badge/index.module.css +18 -0
  30. package/screens/components/Badge/index.stories.jsx +40 -0
  31. package/screens/components/Barnner/index.jsx +21 -0
  32. package/screens/components/Barnner/index.module.css +33 -0
  33. package/screens/components/Barnner/index.stories.jsx +39 -0
  34. package/screens/components/Barnner/utils.js +0 -0
  35. package/screens/components/BlueLink/index.jsx +27 -0
  36. package/screens/components/BlueLink/index.module.css +11 -0
  37. package/screens/components/BlueLink/index.stories.jsx +29 -0
  38. package/screens/components/Breadcrumbs/index.jsx +62 -0
  39. package/screens/components/Breadcrumbs/index.module.css +158 -0
  40. package/screens/components/Breadcrumbs/index.stories.jsx +37 -0
  41. package/screens/components/Button/index.jsx +169 -0
  42. package/screens/components/Button/index.module.css +168 -0
  43. package/screens/components/Button/index.stories.jsx +71 -0
  44. package/screens/components/Button/utils.js +28 -0
  45. package/screens/components/CalendarComponent/CustomDatePicker.jsx +248 -0
  46. package/screens/components/CalendarComponent/CustomDatePicker.module.css +323 -0
  47. package/screens/components/CalendarComponent/CustomDatePicker.stories.jsx +45 -0
  48. package/screens/components/CalendarPicker/Constants.js +12 -0
  49. package/screens/components/CalendarPicker/index.jsx +263 -0
  50. package/screens/components/CalendarPicker/index.module.css +147 -0
  51. package/screens/components/CalendarPicker/index.stories.jsx +45 -0
  52. package/screens/components/CalendarPicker/utils.js +42 -0
  53. package/screens/components/CardV1/index.jsx +165 -0
  54. package/screens/components/CardV1/index.module.css +232 -0
  55. package/screens/components/CardV1/index.stories.jsx +62 -0
  56. package/screens/components/CardV1/utils.js +49 -0
  57. package/screens/components/ChatWindow/index.jsx +251 -0
  58. package/screens/components/ChatWindow/index.module.css +311 -0
  59. package/screens/components/ChatWindow/index.stories.jsx +62 -0
  60. package/screens/components/Checks/index.jsx +31 -0
  61. package/screens/components/Checks/index.module.css +32 -0
  62. package/screens/components/Checks/index.stories.jsx +32 -0
  63. package/screens/components/Container/index.jsx +36 -0
  64. package/screens/components/Container/index.module.css +24 -0
  65. package/screens/components/Container/index.stories.jsx +32 -0
  66. package/screens/components/CopyText/index.jsx +42 -0
  67. package/screens/components/CopyText/index.module.css +52 -0
  68. package/screens/components/CopyText/index.stories.jsx +24 -0
  69. package/screens/components/CountdownBar/constants.js +3 -0
  70. package/screens/components/CountdownBar/index.jsx +81 -0
  71. package/screens/components/CountdownBar/index.module.css +45 -0
  72. package/screens/components/CountdownBar/index.stories.jsx +43 -0
  73. package/screens/components/CountdownBar/utils.js +119 -0
  74. package/screens/components/DateTag/index.jsx +33 -0
  75. package/screens/components/DateTag/index.module.css +12 -0
  76. package/screens/components/DateTag/index.stories.jsx +29 -0
  77. package/screens/components/DesplegablePanel/constants.js +0 -0
  78. package/screens/components/DesplegablePanel/index.jsx +61 -0
  79. package/screens/components/DesplegablePanel/index.module.css +120 -0
  80. package/screens/components/DesplegablePanel/index.stories.jsx +44 -0
  81. package/screens/components/DesplegablePanel/utils.js +0 -0
  82. package/screens/components/DrawPanel/index.jsx +217 -0
  83. package/screens/components/DrawPanel/index.module.css +252 -0
  84. package/screens/components/DrawPanel/index.stories.jsx +66 -0
  85. package/screens/components/DrawPanel/utils.js +0 -0
  86. package/screens/components/Filter/index.jsx +105 -0
  87. package/screens/components/Filter/index.module.css +91 -0
  88. package/screens/components/Filter/index.stories.jsx +46 -0
  89. package/screens/components/Filter/utils.js +0 -0
  90. package/screens/components/FormControls/FormControls.module.css +86 -0
  91. package/screens/components/FormControls/index.jsx +51 -0
  92. package/screens/components/FormControls/index.stories.jsx +36 -0
  93. package/screens/components/Frame/index.jsx +54 -0
  94. package/screens/components/Frame/index.module.css +102 -0
  95. package/screens/components/Frame/index.stories.jsx +37 -0
  96. package/screens/components/Frame/utils.js +0 -0
  97. package/screens/components/GreenHighlight/index.jsx +11 -0
  98. package/screens/components/GreenHighlight/index.module.css +7 -0
  99. package/screens/components/GreenHighlight/index.stories.jsx +26 -0
  100. package/screens/components/GreenHighlight/utils.jsx +45 -0
  101. package/screens/components/HoursPicker/Constants.js +26 -0
  102. package/screens/components/HoursPicker/index.jsx +350 -0
  103. package/screens/components/HoursPicker/index.module.css +99 -0
  104. package/screens/components/HoursPicker/index.stories.jsx +44 -0
  105. package/screens/components/HoursPicker/utils.js +48 -0
  106. package/screens/components/InfoTooltip/index.jsx +59 -0
  107. package/screens/components/InfoTooltip/index.module.css +98 -0
  108. package/screens/components/InfoTooltip/index.stories.jsx +35 -0
  109. package/screens/components/Input/index.jsx +36 -0
  110. package/screens/components/Input/index.module.css +49 -0
  111. package/screens/components/Input/index.stories.jsx +37 -0
  112. package/screens/components/Input/utils.js +0 -0
  113. package/screens/components/Loading/index.jsx +76 -0
  114. package/screens/components/Loading/index.module.css +193 -0
  115. package/screens/components/Loading/index.stories.jsx +38 -0
  116. package/screens/components/Loading/utils.js +0 -0
  117. package/screens/components/MarkdownContent/index.jsx +16 -0
  118. package/screens/components/MarkdownContent/index.module.css +149 -0
  119. package/screens/components/MarkdownContent/index.stories.jsx +30 -0
  120. package/screens/components/MarkdownEditor/index.jsx +430 -0
  121. package/screens/components/MarkdownEditor/index.module.css +192 -0
  122. package/screens/components/MarkdownEditor/index.stories.jsx +50 -0
  123. package/screens/components/Material-UI/Components/InputWithIcon/index.jsx +87 -0
  124. package/screens/components/Material-UI/Components/InputWithIcon/index.stories.jsx +49 -0
  125. package/screens/components/Material-UI/Components/MenuPopover/index.jsx +117 -0
  126. package/screens/components/Material-UI/Components/MenuPopover/index.stories.jsx +36 -0
  127. package/screens/components/Material-UI/Components/MultilinePlaceholder/index.jsx +44 -0
  128. package/screens/components/Material-UI/Components/MultilinePlaceholder/index.stories.jsx +45 -0
  129. package/screens/components/Material-UI/Components/Paginador/index.jsx +79 -0
  130. package/screens/components/Material-UI/Components/Paginador/index.stories.jsx +49 -0
  131. package/screens/components/Material-UI/Components/Search/index.jsx +81 -0
  132. package/screens/components/Material-UI/Components/Search/index.stories.jsx +68 -0
  133. package/screens/components/Material-UI/Components/Selector/index.jsx +100 -0
  134. package/screens/components/Material-UI/Components/Selector/index.module.css +0 -0
  135. package/screens/components/Material-UI/Components/Selector/index.stories.jsx +52 -0
  136. package/screens/components/Material-UI/Components/Selector/utils.js +0 -0
  137. package/screens/components/Material-UI/Components/TextField/index.jsx +61 -0
  138. package/screens/components/Material-UI/Components/TextField/index.stories.jsx +53 -0
  139. package/screens/components/ModalTooltip/ModalTooltip.jsx +122 -0
  140. package/screens/components/ModalTooltip/ModalTooltip.module.css +65 -0
  141. package/screens/components/ModalTooltip/ModalTooltip.stories.jsx +39 -0
  142. package/screens/components/Notification/Error/ErrorMessage.jsx +30 -0
  143. package/screens/components/Notification/Error/ErrorMessage.module.css +57 -0
  144. package/screens/components/Notification/Error/ErrorMessage.stories.jsx +37 -0
  145. package/screens/components/PasswordResetPanel/index.jsx +325 -0
  146. package/screens/components/PasswordResetPanel/index.stories.jsx +26 -0
  147. package/screens/components/PlaceholderButton/index.jsx +169 -0
  148. package/screens/components/PlaceholderButton/index.module.css +162 -0
  149. package/screens/components/PlaceholderButton/index.stories.jsx +69 -0
  150. package/screens/components/PlaceholderButton/utils.js +42 -0
  151. package/screens/components/Profile/Avatar/index.jsx +125 -0
  152. package/screens/components/Profile/Avatar/index.module.css +86 -0
  153. package/screens/components/Profile/Avatar/index.stories.jsx +48 -0
  154. package/screens/components/Profile/Avatar/utils.js +18 -0
  155. package/screens/components/Profile/index.jsx +58 -0
  156. package/screens/components/Profile/index.module.css +0 -0
  157. package/screens/components/Profile/index.stories.jsx +38 -0
  158. package/screens/components/Profile/utils.js +0 -0
  159. package/screens/components/ScrollBar/index.jsx +62 -0
  160. package/screens/components/ScrollBar/index.module.css +78 -0
  161. package/screens/components/ScrollBar/index.stories.jsx +64 -0
  162. package/screens/components/ScrollBar/utils.js +127 -0
  163. package/screens/components/Sidebar/constants.js +16 -0
  164. package/screens/components/Sidebar/index.jsx +399 -0
  165. package/screens/components/Sidebar/index.module.css +405 -0
  166. package/screens/components/Sidebar/index.stories.jsx +86 -0
  167. package/screens/components/Sidebar/utils.js +75 -0
  168. package/screens/components/Skeleton/index.jsx +11 -0
  169. package/screens/components/Skeleton/index.module.css +26 -0
  170. package/screens/components/Skeleton/index.stories.jsx +42 -0
  171. package/screens/components/SubSidebarLayout/index.jsx +44 -0
  172. package/screens/components/SubSidebarLayout/index.module.css +80 -0
  173. package/screens/components/SubSidebarLayout/index.stories.jsx +51 -0
  174. package/screens/components/SummaryCard/index.jsx +50 -0
  175. package/screens/components/SummaryCard/index.module.css +30 -0
  176. package/screens/components/SummaryCard/index.stories.jsx +29 -0
  177. package/screens/components/Swich/constants.js +4 -0
  178. package/screens/components/Swich/index.jsx +85 -0
  179. package/screens/components/Swich/index.module.css +68 -0
  180. package/screens/components/Swich/index.stories.jsx +44 -0
  181. package/screens/components/Swich/utils.js +0 -0
  182. package/screens/components/TableA/index.jsx +156 -0
  183. package/screens/components/TableA/index.module.css +105 -0
  184. package/screens/components/TableA/index.stories.jsx +116 -0
  185. package/screens/components/TableA/utils.js +11 -0
  186. package/screens/components/TableB/index.jsx +222 -0
  187. package/screens/components/TableB/index.module.css +295 -0
  188. package/screens/components/TableB/index.stories.jsx +110 -0
  189. package/screens/components/TableB/utils.js +11 -0
  190. package/screens/components/ToggleCard/index.jsx +64 -0
  191. package/screens/components/ToggleCard/index.module.css +111 -0
  192. package/screens/components/ToggleCard/index.stories.jsx +49 -0
  193. package/screens/components/UserEditPopover/index.jsx +102 -0
  194. package/screens/components/UserEditPopover/index.module.css +97 -0
  195. package/screens/components/UserEditPopover/index.stories.jsx +49 -0
  196. package/scripts/build.mjs +129 -0
  197. package/scripts/check-case.mjs +127 -0
  198. package/scripts/verify-dist.mjs +45 -0
  199. package/vitest.config.js +36 -0
@@ -0,0 +1,66 @@
1
+ import DrawPanel from './index.jsx';
2
+
3
+ export default {
4
+ title: 'Components/DrawPanel',
5
+ component: DrawPanel,
6
+ };
7
+
8
+ export const Default = {
9
+ args: {
10
+ isOpen: true,
11
+ onClose: () => console.log('closed'),
12
+ title: 'Detalle del registro',
13
+ description: 'Revisa la información antes de continuar',
14
+ width: '420px',
15
+ children: (
16
+ <p style={{ margin: 0 }}>Contenido del panel lateral.</p>
17
+ ),
18
+ },
19
+ };
20
+
21
+ export const WithActions = {
22
+ args: {
23
+ isOpen: true,
24
+ onClose: () => console.log('closed'),
25
+ onConfirm: () => console.log('confirmed'),
26
+ title: 'Confirmar acción',
27
+ description: 'Esta acción no se puede deshacer',
28
+ descriptionPosition: 'bottom',
29
+ showActions: true,
30
+ confirmText: 'Guardar',
31
+ cancelText: 'Cancelar',
32
+ width: '400px',
33
+ children: (
34
+ <p style={{ margin: 0 }}>Formulario o resumen de la acción a confirmar.</p>
35
+ ),
36
+ },
37
+ };
38
+
39
+ export const WithCountdownSelectionProgress = {
40
+ args: {
41
+ isOpen: true,
42
+ onClose: () => console.log('closed'),
43
+ title: 'Selecciona elementos',
44
+ width: '420px',
45
+ showCountdown: true,
46
+ progressMode: 'selection',
47
+ totalItems: ['a', 'b', 'c', 'd'],
48
+ selectedItems: ['a', 'b'],
49
+ children: (
50
+ <p style={{ margin: 0 }}>2 de 4 elementos seleccionados.</p>
51
+ ),
52
+ },
53
+ };
54
+
55
+ export const TopAnchor = {
56
+ args: {
57
+ isOpen: true,
58
+ onClose: () => console.log('closed'),
59
+ title: 'Aviso',
60
+ anchor: 'top',
61
+ width: '480px',
62
+ children: (
63
+ <p style={{ margin: 0 }}>Panel anclado en la parte superior de la pantalla.</p>
64
+ ),
65
+ },
66
+ };
File without changes
@@ -0,0 +1,105 @@
1
+ import React, { useState } from 'react';
2
+ import { Filter as FilterIcon, Trash2, Search } from 'lucide-react';
3
+ import DrawPanel from '../DrawPanel/index';
4
+ import Button from '../Button/index';
5
+ import styles from './index.module.css';
6
+ import ModalTooltip from '../ModalTooltip/ModalTooltip';
7
+
8
+ const Filter = ({
9
+ children,
10
+ onClear,
11
+ onApply,
12
+ searchTerm = '',
13
+ width = '350px',
14
+ title = 'Filtros',
15
+ activeFiltersCount = 0,
16
+ badgeColor
17
+ }) => {
18
+ const [isOpen, setIsOpen] = useState(false);
19
+
20
+ const handleApply = () => {
21
+ setIsOpen(false);
22
+ if (onApply) onApply();
23
+ };
24
+
25
+ const handleClear = () => {
26
+ if (onClear) onClear();
27
+ };
28
+
29
+ return (
30
+ <div className={styles.filterWrapper}>
31
+ <div className={styles.filterBar}>
32
+ <div className={styles.actions}>
33
+ <div className={styles.filterButtonWrapper}>
34
+ <Button
35
+ onClick={() => setIsOpen(true)}
36
+ variant={Button.VARIANTS.PRIMARY}
37
+ >
38
+ <FilterIcon size={18} /> Filtrar
39
+ </Button>
40
+ {activeFiltersCount > 0 && (
41
+ <div className={styles.badgeWrapper}>
42
+ <ModalTooltip text="Filtros aplicados" position="top">
43
+ <span
44
+ className={styles.filterBadge}
45
+ style={badgeColor ? { '--filter-badge-bg': badgeColor } : undefined}
46
+ >
47
+ {activeFiltersCount}
48
+ </span>
49
+ </ModalTooltip>
50
+ </div>
51
+ )}
52
+ </div>
53
+ {onClear && (
54
+ <Button
55
+ onClick={handleClear}
56
+ variant={Button.VARIANTS.DANGER}
57
+ color={Button.COLORS.TRANSPARENT}
58
+ borderColor="var(--border-gray-low)"
59
+ >
60
+ <Trash2 size={18} /> Limpiar
61
+ </Button>
62
+ )}
63
+ </div>
64
+ {searchTerm !== undefined && searchTerm !== null && searchTerm !== '' && (
65
+ <div className={styles.searchIndicator}>
66
+ <Search size={16} />
67
+ <span>Buscar: {searchTerm}</span>
68
+ </div>
69
+ )}
70
+ </div>
71
+
72
+ <DrawPanel
73
+ isOpen={isOpen}
74
+ onClose={() => setIsOpen(false)}
75
+ title={title}
76
+ width={width}
77
+ >
78
+ <div className={styles.filterContent}>
79
+ <div className={styles.fields}>
80
+ {children}
81
+ </div>
82
+
83
+ <div className={styles.drawerActions}>
84
+ <Button
85
+ onClick={() => setIsOpen(false)}
86
+ variant={Button.VARIANTS.DANGER}
87
+ color={Button.COLORS.TRANSPARENT}
88
+ borderColor="var(--border-gray-low)"
89
+ >
90
+ Cancelar
91
+ </Button>
92
+ <Button
93
+ onClick={handleApply}
94
+ variant={Button.VARIANTS.PRIMARY}
95
+ >
96
+ Aplicar
97
+ </Button>
98
+ </div>
99
+ </div>
100
+ </DrawPanel>
101
+ </div>
102
+ );
103
+ };
104
+
105
+ export default Filter;
@@ -0,0 +1,91 @@
1
+ .filterWrapper {
2
+ display: flex;
3
+ flex-direction: column;
4
+ width: 100%;
5
+ margin-bottom: 1rem;
6
+ }
7
+
8
+ .filterBar {
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: space-between;
12
+ background-color: var(--color-background-elevated, #ffffff);
13
+ padding: 0.75rem 1.25rem;
14
+ border-radius: 8px;
15
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
16
+ width: 100%;
17
+ }
18
+
19
+ .actions {
20
+ display: flex;
21
+ align-items: center;
22
+ gap: 0.75rem;
23
+ }
24
+
25
+ .searchIndicator {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: 0.5rem;
29
+ color: var(--color-danger, #64748b);
30
+ font-size: 0.9rem;
31
+ background-color: rgba(0,0,0,0.03);
32
+ padding: 0.25rem 0.75rem;
33
+ border-radius: 16px;
34
+ }
35
+
36
+ .filterContent {
37
+ display: flex;
38
+ flex-direction: column;
39
+ height: 100%;
40
+ gap: 1.5rem;
41
+ }
42
+
43
+ .fields {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: 1.25rem;
47
+ flex: 1;
48
+ overflow-y: auto;
49
+ padding: 0.5rem 0;
50
+ }
51
+
52
+ .drawerActions {
53
+ display: flex;
54
+ justify-content: flex-end;
55
+ gap: 0.75rem;
56
+ padding-top: 1.25rem;
57
+ border-top: 1px solid var(--border-color, #e2e8f0);
58
+ margin-top: auto;
59
+ }
60
+
61
+ .filterButtonWrapper {
62
+ position: relative;
63
+ display: inline-flex;
64
+ }
65
+ .filterButtonWrapper {
66
+ position: relative;
67
+ display: inline-flex;
68
+ }
69
+
70
+ .badgeWrapper {
71
+ position: absolute;
72
+ top: -6px;
73
+ right: -6px;
74
+ z-index: 10;
75
+ display: flex;
76
+ }
77
+
78
+ .filterBadge {
79
+ background-color: var(--filter-badge-bg, #ef4444);
80
+ color: white;
81
+ border-radius: 50%;
82
+ min-width: 20px;
83
+ height: 20px;
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ font-size: 11px;
88
+ font-weight: bold;
89
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
90
+ cursor: default;
91
+ }
@@ -0,0 +1,46 @@
1
+ import Filter from './index.jsx';
2
+ import TextField from '../Material-UI/Components/TextField/index';
3
+
4
+ export default {
5
+ title: 'Components/Filter',
6
+ component: Filter,
7
+ };
8
+
9
+ export const Default = {
10
+ args: {
11
+ title: 'Filtros',
12
+ onApply: () => console.log('applied'),
13
+ onClear: () => console.log('cleared'),
14
+ children: (
15
+ <TextField label="Nombre" placeholder="Buscar por nombre" />
16
+ ),
17
+ },
18
+ };
19
+
20
+ export const WithActiveFiltersAndSearch = {
21
+ args: {
22
+ title: 'Filtros avanzados',
23
+ activeFiltersCount: 3,
24
+ searchTerm: 'reporte mensual',
25
+ onApply: () => console.log('applied'),
26
+ onClear: () => console.log('cleared'),
27
+ children: (
28
+ <>
29
+ <TextField label="Nombre" placeholder="Buscar por nombre" />
30
+ <TextField label="Estado" placeholder="Activo, inactivo..." />
31
+ </>
32
+ ),
33
+ },
34
+ };
35
+
36
+ export const WidePanel = {
37
+ args: {
38
+ title: 'Filtros',
39
+ width: '480px',
40
+ onApply: () => console.log('applied'),
41
+ onClear: () => console.log('cleared'),
42
+ children: (
43
+ <TextField label="Fecha desde" type="date" />
44
+ ),
45
+ },
46
+ };
File without changes
@@ -0,0 +1,86 @@
1
+ .card {
2
+ background: white;
3
+ border: 1px solid #e2e8f0;
4
+ border-radius: 12px;
5
+ overflow: hidden;
6
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
7
+ margin-bottom: 1.25rem;
8
+ }
9
+
10
+ .cardHeader {
11
+ display: flex;
12
+ align-items: center;
13
+ justify-content: space-between;
14
+ padding: 1rem 1.25rem;
15
+ background-color: #f8fafc;
16
+ border-bottom: 1px solid #f1f5f9;
17
+ }
18
+
19
+ .cardTitle {
20
+ display: flex;
21
+ align-items: center;
22
+ gap: 0.75rem;
23
+ color: #0f172a;
24
+ }
25
+
26
+ .cardIcon {
27
+ color: var(--form-card-icon, #0ea5e9);
28
+ }
29
+
30
+ .cardTitle h3 {
31
+ font-size: 1rem;
32
+ font-weight: 700;
33
+ margin: 0;
34
+ }
35
+
36
+ .headerActions {
37
+ display: flex;
38
+ align-items: center;
39
+ gap: 0.5rem;
40
+ }
41
+
42
+ .cardContent {
43
+ padding: 1.25rem;
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: 1rem;
47
+ }
48
+
49
+ /* Inputs */
50
+ .inputGroup {
51
+ display: flex;
52
+ flex-direction: column;
53
+ gap: 0.5rem;
54
+ }
55
+
56
+ .label {
57
+ font-size: 0.75rem;
58
+ font-weight: 700;
59
+ color: #64748b;
60
+ text-transform: uppercase;
61
+ display: flex;
62
+ align-items: center;
63
+ gap: 4px;
64
+ }
65
+
66
+ .input, .textarea {
67
+ width: 100%;
68
+ padding: 0.75rem;
69
+ border: 1px solid #cbd5e1;
70
+ border-radius: 8px;
71
+ font-size: 0.95rem;
72
+ background-color: #ffffff;
73
+ transition: all 0.2s ease;
74
+ box-sizing: border-box;
75
+ }
76
+
77
+ .input:focus, .textarea:focus {
78
+ outline: none;
79
+ border-color: #0ea5e9;
80
+ box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.1);
81
+ }
82
+
83
+ .textarea {
84
+ min-height: 100px;
85
+ resize: vertical;
86
+ }
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import styles from './FormControls.module.css';
3
+
4
+ export function FormCard({ icon: Icon, title, children, headerActions, iconColor }) {
5
+ return (
6
+ <div className={styles.card}>
7
+ <div className={styles.cardHeader}>
8
+ <div className={styles.cardTitle}>
9
+ {Icon && (
10
+ <Icon
11
+ size={20}
12
+ className={styles.cardIcon}
13
+ style={iconColor ? { '--form-card-icon': iconColor } : undefined}
14
+ />
15
+ )}
16
+ <h3>{title}</h3>
17
+ </div>
18
+ {headerActions && <div className={styles.headerActions}>{headerActions}</div>}
19
+ </div>
20
+ <div className={styles.cardContent}>
21
+ {children}
22
+ </div>
23
+ </div>
24
+ );
25
+ }
26
+
27
+ import TextField from '../Material-UI/Components/TextField/index';
28
+
29
+ export function FormInput({ label, icon: Icon, ...props }) {
30
+ return (
31
+ <div className={styles.inputGroup}>
32
+ <TextField
33
+ label={label}
34
+ {...props}
35
+ />
36
+ </div>
37
+ );
38
+ }
39
+
40
+ import MultilinePlaceholder from '../Material-UI/Components/MultilinePlaceholder/index';
41
+
42
+ export function FormTextArea({ label, icon: Icon, ...props }) {
43
+ return (
44
+ <div className={styles.inputGroup}>
45
+ <MultilinePlaceholder
46
+ label={label}
47
+ {...props}
48
+ />
49
+ </div>
50
+ );
51
+ }
@@ -0,0 +1,36 @@
1
+ import { Settings, FileText } from 'lucide-react';
2
+ import { FormCard, FormInput, FormTextArea } from './index.jsx';
3
+
4
+ export default {
5
+ title: 'Components/FormControls',
6
+ component: FormCard,
7
+ };
8
+
9
+ export const Card = {
10
+ render: () => (
11
+ <FormCard icon={Settings} title="Preferencias">
12
+ <p style={{ margin: 0 }}>Contenido de la tarjeta de formulario.</p>
13
+ </FormCard>
14
+ ),
15
+ };
16
+
17
+ export const CardWithHeaderActions = {
18
+ render: () => (
19
+ <FormCard
20
+ icon={FileText}
21
+ title="Datos del contacto"
22
+ headerActions={<button type="button">Editar</button>}
23
+ >
24
+ <FormInput label="Nombre completo" placeholder="Juan Pérez" />
25
+ </FormCard>
26
+ ),
27
+ };
28
+
29
+ export const InputAndTextArea = {
30
+ render: () => (
31
+ <FormCard icon={FileText} title="Comentarios">
32
+ <FormInput label="Asunto" placeholder="Escribe un asunto" />
33
+ <FormTextArea label="Descripción" placeholder="Cuéntanos más detalles" rows={5} />
34
+ </FormCard>
35
+ ),
36
+ };
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { createPortal } from 'react-dom';
3
+ import styles from './index.module.css';
4
+ import Loading from '../Loading/index';
5
+
6
+ function Frame({ title, icon, content, error, children, className = '', isModal = false, onClose, isLoading = false, bgColor, iconColor, descriptionBgColor }) {
7
+ const frameCardStyle = {
8
+ ...(bgColor ? { '--frame-bg': bgColor } : {}),
9
+ ...(iconColor ? { '--frame-icon': iconColor } : {}),
10
+ ...(descriptionBgColor ? { '--frame-description-bg': descriptionBgColor } : {}),
11
+ };
12
+
13
+ const frameContent = (
14
+ <div
15
+ className={`${styles.frameCard} ${className}`}
16
+ style={frameCardStyle}
17
+ onClick={(e) => e.stopPropagation()}
18
+ >
19
+ {(title || icon) && (
20
+ <div className={styles.headerContainer}>
21
+ {title && <h3 className={styles.frameTitle}>{title}</h3>}
22
+ {icon && <div className={styles.iconContainer}>{icon}</div>}
23
+ </div>
24
+ )}
25
+ {content && <p className={styles.description}>{content}</p>}
26
+ {error && <p className={styles.errorMessage}>{error}</p>}
27
+ <div className={styles.bodyContainer}>
28
+ {isLoading && (
29
+ <div className={styles.loadingOverlay}>
30
+ <Loading
31
+ size="giant"
32
+ />
33
+ </div>
34
+ )}
35
+ <div className={isLoading ? styles.hiddenContent : ''}>
36
+ {children}
37
+ </div>
38
+ </div>
39
+ </div>
40
+ );
41
+
42
+ if (isModal) {
43
+ return createPortal(
44
+ <div className={styles.modalOverlay} onClick={onClose}>
45
+ {frameContent}
46
+ </div>,
47
+ document.body
48
+ );
49
+ }
50
+
51
+ return frameContent;
52
+ }
53
+
54
+ export default Frame;
@@ -0,0 +1,102 @@
1
+ .frameCard {
2
+ background-color: var(--frame-bg, #ffffff);
3
+ width: 320px;
4
+ padding: 1.5rem 2.5rem 2.5rem 2.5rem;
5
+ border-radius: 4px;
6
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
7
+ font-family: 'Roboto', Arial, sans-serif;
8
+ display: flex;
9
+ flex-direction: column;
10
+ }
11
+
12
+ .headerContainer {
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ gap: 0.5rem;
17
+ margin: 0 0 1.25rem 0;
18
+ }
19
+
20
+ .frameTitle {
21
+ font-size: 1.1rem;
22
+ font-weight: 700;
23
+ color: #000000;
24
+ text-align: center;
25
+ margin: 0;
26
+ }
27
+
28
+ .iconContainer {
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ color: var(--frame-icon, #555); /* Neutral dark gray for icons */
33
+ }
34
+
35
+ .description {
36
+ text-align: center;
37
+ margin: 0 0 1.25rem 0;
38
+ font-size: 0.9rem;
39
+ color: #475569;
40
+ background-color: var(--frame-description-bg, #f1f5f9); /* Light grayish background */
41
+ padding: 0.75rem 1rem;
42
+ border-radius: 6px;
43
+ line-height: 1.4;
44
+ }
45
+
46
+ .errorMessage {
47
+ color: #ff0000;
48
+ font-size: 0.85rem;
49
+ text-align: center;
50
+ margin: 0 0 1rem 0;
51
+ font-weight: 700;
52
+ min-height: 1rem;
53
+ }
54
+
55
+ .modalOverlay {
56
+ position: fixed;
57
+ top: 0;
58
+ left: 0;
59
+ width: 100vw;
60
+ height: 100vh;
61
+ background: rgba(0, 0, 0, 0.45);
62
+ backdrop-filter: blur(4px);
63
+ z-index: 9999;
64
+ display: flex;
65
+ justify-content: center;
66
+ align-items: center;
67
+ animation: modalFadeIn 0.3s ease-out;
68
+ }
69
+
70
+ @keyframes modalFadeIn {
71
+ from {
72
+ opacity: 0;
73
+ }
74
+ to {
75
+ opacity: 1;
76
+ }
77
+ }
78
+
79
+ .bodyContainer {
80
+ position: relative;
81
+ width: 100%;
82
+ flex: 1;
83
+ display: flex;
84
+ flex-direction: column;
85
+ }
86
+
87
+ .loadingOverlay {
88
+ position: absolute;
89
+ top: 0;
90
+ left: 0;
91
+ right: 0;
92
+ bottom: 0;
93
+ display: flex;
94
+ justify-content: center;
95
+ align-items: center;
96
+ background-color: #ffffff;
97
+ z-index: 10;
98
+ }
99
+
100
+ .hiddenContent {
101
+ visibility: hidden;
102
+ }
@@ -0,0 +1,37 @@
1
+ import { Info } from 'lucide-react';
2
+ import Frame from './index.jsx';
3
+
4
+ export default {
5
+ title: 'Components/Frame',
6
+ component: Frame,
7
+ };
8
+
9
+ export const Default = {
10
+ args: {
11
+ title: 'Información general',
12
+ content: 'Este es un panel de contenido simple con título y descripción.',
13
+ },
14
+ };
15
+
16
+ export const WithIconAndChildren = {
17
+ args: {
18
+ title: 'Detalles',
19
+ icon: <Info size={20} />,
20
+ children: <p style={{ margin: 0 }}>Contenido personalizado dentro del marco.</p>,
21
+ },
22
+ };
23
+
24
+ export const WithError = {
25
+ args: {
26
+ title: 'Error al cargar',
27
+ error: 'No se pudo obtener la información solicitada.',
28
+ },
29
+ };
30
+
31
+ export const Loading = {
32
+ args: {
33
+ title: 'Cargando datos',
34
+ isLoading: true,
35
+ children: <p style={{ margin: 0 }}>Este contenido queda oculto mientras carga.</p>,
36
+ },
37
+ };
File without changes
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import styles from './index.module.css';
3
+
4
+ export default function GreenHighlight({ children, textColor, bgColor, style }) {
5
+ const cssVarStyle = {
6
+ ...(textColor ? { '--green-highlight-text': textColor } : {}),
7
+ ...(bgColor ? { '--green-highlight-bg': bgColor } : {}),
8
+ ...style,
9
+ };
10
+ return <strong className={styles.greenHighlight} style={cssVarStyle}>{children}</strong>;
11
+ }