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,405 @@
1
+ /* Sidebar base styling */
2
+ .sidebar {
3
+ height: 100vh;
4
+ max-height: 100vh;
5
+ background: var(--sidebar-bg);
6
+ backdrop-filter: var(--sidebar-blur);
7
+ -webkit-backdrop-filter: var(--sidebar-blur);
8
+ border-radius: 0;
9
+ border: none;
10
+ border-right: var(--sidebar-border-right);
11
+ color: var(--sidebar-text);
12
+ padding: 24px 16px;
13
+ width: 280px;
14
+ min-width: 280px;
15
+ align-self: stretch;
16
+ display: flex;
17
+ flex-direction: column;
18
+ gap: 16px;
19
+ box-sizing: border-box;
20
+ position: relative;
21
+ transition: width 0.3s ease, min-width 0.3s ease, padding 0.3s ease;
22
+ }
23
+
24
+ /* Collapsed state styling */
25
+ .sidebar.collapsed {
26
+ width: 68px;
27
+ min-width: 68px;
28
+ padding: 20px 8px;
29
+ }
30
+
31
+ .sidebar.collapsed .sidebarHeader {
32
+ justify-content: center;
33
+ padding: 0;
34
+ }
35
+
36
+ .sidebar.collapsed .sidebarItemBtn {
37
+ padding: 10px 0 !important;
38
+ justify-content: center !important;
39
+ }
40
+
41
+ .sidebar.collapsed .btnLayout {
42
+ justify-content: center !important;
43
+ }
44
+
45
+ .sidebar.collapsed .leftPart {
46
+ justify-content: center !important;
47
+ flex: none !important;
48
+ gap: 0 !important;
49
+ }
50
+
51
+ /* Header section */
52
+ .sidebarHeader {
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: space-between;
56
+ padding: 0 4px;
57
+ min-height: 40px;
58
+ gap: 8px;
59
+ }
60
+
61
+ .headerContent {
62
+ flex: 1;
63
+ min-width: 0;
64
+ overflow: hidden;
65
+ }
66
+
67
+ .toggleBtn {
68
+ flex-shrink: 0;
69
+ width: 28px !important;
70
+ height: 28px !important;
71
+ min-width: 0 !important;
72
+ padding: 0 !important;
73
+ background-color: #ffffff !important;
74
+ border: 1px solid #cbd5e1 !important;
75
+ color: #475569 !important;
76
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08) !important;
77
+ z-index: 5;
78
+ border-radius: 50% !important;
79
+ display: flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ cursor: pointer;
83
+ transition: background-color 0.2s, color 0.2s;
84
+ }
85
+
86
+ .toggleBtn:hover {
87
+ background-color: var(--sidebar-avatar-bg, #0d52f8) !important;
88
+ color: #ffffff !important;
89
+ border-color: var(--sidebar-avatar-bg, #0d52f8) !important;
90
+ }
91
+
92
+ /* Search wrapper */
93
+ .searchWrapper {
94
+ margin-top: 4px;
95
+ }
96
+
97
+ /* Navigation container */
98
+ .navContainer {
99
+ display: flex;
100
+ flex-direction: column;
101
+ gap: 20px;
102
+ flex: 1;
103
+ overflow-y: auto;
104
+ padding-right: 4px;
105
+ scrollbar-width: none;
106
+ -ms-overflow-style: none;
107
+ }
108
+
109
+ .navContainer::-webkit-scrollbar {
110
+ display: none;
111
+ }
112
+
113
+ .navContainer::-webkit-scrollbar-thumb:hover {
114
+ background: #94a3b8;
115
+ }
116
+
117
+ /* Menu groups */
118
+ .menuGroup {
119
+ display: flex;
120
+ flex-direction: column;
121
+ gap: 8px;
122
+ }
123
+
124
+ .groupTitle {
125
+ font-size: 0.72rem;
126
+ font-weight: 700;
127
+ color: #94a3b8;
128
+ letter-spacing: 0.06em;
129
+ display: block;
130
+ padding-left: 8px;
131
+ text-transform: uppercase;
132
+ }
133
+
134
+ .buttonList {
135
+ display: flex;
136
+ flex-direction: column;
137
+ gap: 6px;
138
+ }
139
+
140
+ /* Sidebar list items */
141
+ .sidebarItemBtn {
142
+ width: 100% !important;
143
+ justify-content: flex-start !important;
144
+ align-items: center !important;
145
+ text-align: left !important;
146
+ padding: 10px 12px !important;
147
+ border-radius: 8px !important;
148
+ border: none !important;
149
+ box-shadow: none !important;
150
+ color: var(--sidebar-text-muted) !important;
151
+ background-color: transparent !important;
152
+ text-transform: none !important;
153
+ display: flex !important;
154
+ transition: background-color 0.2s, color 0.2s !important;
155
+ }
156
+
157
+ .btnLayout {
158
+ display: flex !important;
159
+ align-items: center !important;
160
+ justify-content: space-between !important;
161
+ width: 100% !important;
162
+ gap: 12px;
163
+ }
164
+
165
+ .leftPart {
166
+ display: flex !important;
167
+ align-items: center !important;
168
+ gap: 12px;
169
+ flex: 1;
170
+ min-width: 0;
171
+ }
172
+
173
+ .icon {
174
+ font-size: 20px !important;
175
+ color: var(--sidebar-text-muted);
176
+ flex-shrink: 0;
177
+ display: inline-flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ }
181
+
182
+ .label {
183
+ font-size: 0.88rem;
184
+ font-weight: 500;
185
+ color: inherit;
186
+ white-space: nowrap;
187
+ overflow: hidden;
188
+ text-overflow: ellipsis;
189
+ }
190
+
191
+ /* Badge styles */
192
+ .badge {
193
+ font-size: 0.65rem;
194
+ font-weight: 800;
195
+ padding: 2px 6px;
196
+ border-radius: 4px;
197
+ flex-shrink: 0;
198
+ text-transform: uppercase;
199
+ }
200
+
201
+ .badgePost { background: var(--sidebar-badge-post-bg, #dcfce7); color: var(--sidebar-badge-post-color, #15803d); }
202
+ .badgeGet { background: var(--sidebar-badge-get-bg, #e0f2fe); color: var(--sidebar-badge-get-color, #0369a1); }
203
+ .badgePut { background: var(--sidebar-badge-put-bg, #fef3c7); color: var(--sidebar-badge-put-color, #b45309); }
204
+ .badgeDelete { background: var(--sidebar-badge-delete-bg, #fee2e2); color: var(--sidebar-badge-delete-color, #b91c1c); }
205
+ .badgeInfo { background: var(--sidebar-badge-info-bg, #f1f5f9); color: var(--sidebar-badge-info-color, #475569); }
206
+
207
+ .sidebarItemBtn:hover {
208
+ background-color: var(--sidebar-hover-bg) !important;
209
+ color: var(--sidebar-text-active) !important;
210
+ }
211
+
212
+ .dragHandle {
213
+ display: inline-flex;
214
+ align-items: center;
215
+ color: var(--sidebar-text-muted);
216
+ opacity: 0.5;
217
+ flex-shrink: 0;
218
+ cursor: grab;
219
+ }
220
+
221
+ .sidebarItemBtn:hover .dragHandle {
222
+ opacity: 0.9;
223
+ }
224
+
225
+ .pinnedIcon {
226
+ color: var(--sidebar-pinned-icon, #f59e0b);
227
+ flex-shrink: 0;
228
+ }
229
+
230
+ .dragging {
231
+ opacity: 0.5 !important;
232
+ }
233
+
234
+ .dragOver {
235
+ box-shadow: inset 0 2px 0 0 #0d52f8 !important;
236
+ }
237
+
238
+ .sidebarItemBtn:hover .icon {
239
+ color: var(--sidebar-text-active) !important;
240
+ }
241
+
242
+ /* Active navigation item styling */
243
+ .activeBtn {
244
+ background-color: var(--sidebar-hover-bg) !important;
245
+ color: var(--sidebar-text-active) !important;
246
+ font-weight: 600 !important;
247
+ }
248
+
249
+ .activeBtn .icon {
250
+ color: var(--sidebar-text-active) !important;
251
+ }
252
+
253
+ /* Footer section: groups the optional footerContent slot and the user footer together
254
+ so both stay bottom-aligned and share a single top divider. */
255
+ .footerGroup {
256
+ margin-top: auto;
257
+ border-top: 1px solid var(--sidebar-border);
258
+ padding-top: 12px;
259
+ display: flex;
260
+ flex-direction: column;
261
+ gap: 12px;
262
+ }
263
+
264
+ /* User footer: avatar + email, opens the user menu (Ajustes, Cómo usar, Cerrar sesión, etc.) */
265
+ .userFooter {
266
+ position: relative;
267
+ }
268
+
269
+ .userFooterButton {
270
+ display: flex;
271
+ align-items: center;
272
+ gap: 10px;
273
+ width: 100%;
274
+ padding: 6px;
275
+ border: none;
276
+ background: transparent;
277
+ border-radius: 8px;
278
+ cursor: pointer;
279
+ text-align: left;
280
+ transition: background-color 0.2s;
281
+ }
282
+
283
+ .userFooterButton:hover {
284
+ background-color: var(--sidebar-hover-bg);
285
+ }
286
+
287
+ .avatar {
288
+ flex-shrink: 0;
289
+ width: 32px;
290
+ height: 32px;
291
+ border-radius: 50%;
292
+ display: flex;
293
+ align-items: center;
294
+ justify-content: center;
295
+ background: var(--sidebar-avatar-bg, #0d52f8);
296
+ color: #ffffff;
297
+ font-weight: 700;
298
+ font-size: 0.85rem;
299
+ text-transform: uppercase;
300
+ }
301
+
302
+ .userEmail {
303
+ font-size: 0.82rem;
304
+ color: var(--sidebar-text);
305
+ white-space: nowrap;
306
+ overflow: hidden;
307
+ text-overflow: ellipsis;
308
+ }
309
+
310
+ /* Rendered through a portal into document.body (see Index.jsx) so it always
311
+ paints above the rest of the app, regardless of the sidebar's stacking
312
+ context; position is computed from the trigger button's bounding rect. */
313
+ .userMenu {
314
+ position: fixed;
315
+ background: #ffffff;
316
+ border: 1px solid #e2e8f0;
317
+ border-radius: 10px;
318
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12);
319
+ padding: 6px;
320
+ display: flex;
321
+ flex-direction: column;
322
+ gap: 2px;
323
+ z-index: 2000;
324
+ }
325
+
326
+ .userMenuEmail {
327
+ padding: 8px 10px;
328
+ font-size: 0.78rem;
329
+ color: #64748b;
330
+ border-bottom: 1px solid #e2e8f0;
331
+ margin-bottom: 4px;
332
+ word-break: break-all;
333
+ }
334
+
335
+ .userMenuItem {
336
+ display: flex;
337
+ align-items: center;
338
+ gap: 8px;
339
+ width: 100%;
340
+ padding: 8px 10px;
341
+ border: none;
342
+ background: transparent;
343
+ border-radius: 6px;
344
+ font-size: 0.85rem;
345
+ font-family: inherit;
346
+ color: #334155;
347
+ cursor: pointer;
348
+ text-align: left;
349
+ }
350
+
351
+ .userMenuItem:hover {
352
+ background-color: #f1f5f9;
353
+ }
354
+
355
+ .userMenuItemDanger {
356
+ color: #dc2626;
357
+ }
358
+
359
+ .userMenuItemDanger:hover {
360
+ background-color: #fef2f2;
361
+ }
362
+
363
+ /* Right-click context menu for sidebar items (Editar / Eliminar).
364
+ Also rendered through a portal into document.body — see Index.jsx. */
365
+ .contextMenu {
366
+ position: fixed;
367
+ background: #ffffff;
368
+ border: 1px solid #e2e8f0;
369
+ border-radius: 10px;
370
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12);
371
+ padding: 6px;
372
+ display: flex;
373
+ flex-direction: column;
374
+ gap: 2px;
375
+ z-index: 2000;
376
+ min-width: 150px;
377
+ }
378
+
379
+ .contextMenuItem {
380
+ display: flex;
381
+ align-items: center;
382
+ gap: 8px;
383
+ width: 100%;
384
+ padding: 8px 10px;
385
+ border: none;
386
+ background: transparent;
387
+ border-radius: 6px;
388
+ font-size: 0.85rem;
389
+ font-family: inherit;
390
+ color: #334155;
391
+ cursor: pointer;
392
+ text-align: left;
393
+ }
394
+
395
+ .contextMenuItem:hover {
396
+ background-color: #f1f5f9;
397
+ }
398
+
399
+ .contextMenuItemDanger {
400
+ color: #dc2626;
401
+ }
402
+
403
+ .contextMenuItemDanger:hover {
404
+ background-color: #fef2f2;
405
+ }
@@ -0,0 +1,86 @@
1
+ import { useState } from 'react';
2
+ import { Home, FileText, Settings, Users, LogOut, User } from 'lucide-react';
3
+ import ProSidebar from './index';
4
+
5
+ export default {
6
+ title: 'Components/Sidebar',
7
+ component: ProSidebar,
8
+ };
9
+
10
+ const groups = [
11
+ {
12
+ title: 'General',
13
+ items: [
14
+ { id: 'home', label: 'Inicio', icon: Home },
15
+ { id: 'docs', label: 'Documentos', icon: FileText, badge: 'GET', badgeType: 'get' },
16
+ { id: 'team', label: 'Equipo', icon: Users, isOwner: true, isShared: true },
17
+ ],
18
+ },
19
+ {
20
+ title: 'Configuración',
21
+ items: [
22
+ { id: 'settings', label: 'Ajustes', icon: Settings, pinned: true },
23
+ ],
24
+ },
25
+ ];
26
+
27
+ const userMenuItems = [
28
+ { id: 'profile', label: 'Mi perfil', icon: User, onClick: () => console.log('profile clicked') },
29
+ { id: 'logout', label: 'Cerrar sesión', icon: LogOut, variant: 'danger', onClick: () => console.log('logout clicked') },
30
+ ];
31
+
32
+ const SidebarWithState = (args) => {
33
+ const [activeId, setActiveId] = useState(args.activeId ?? groups[0].items[0].id);
34
+ return (
35
+ <div style={{ height: 600 }}>
36
+ <ProSidebar
37
+ {...args}
38
+ activeId={activeId}
39
+ onSelect={(item) => setActiveId(item.id)}
40
+ />
41
+ </div>
42
+ );
43
+ };
44
+
45
+ export const Default = {
46
+ render: (args) => <SidebarWithState {...args} />,
47
+ args: {
48
+ groups,
49
+ user: { email: 'jane.doe@example.com' },
50
+ userMenuItems,
51
+ },
52
+ };
53
+
54
+ export const WithItemActions = {
55
+ render: (args) => <SidebarWithState {...args} />,
56
+ args: {
57
+ groups,
58
+ user: { email: 'jane.doe@example.com' },
59
+ userMenuItems,
60
+ onItemEdit: (item) => console.log('edit', item),
61
+ onItemDelete: (item) => console.log('delete', item),
62
+ onItemPin: (item) => console.log('pin', item),
63
+ onItemCollaborators: (item) => console.log('collaborators', item),
64
+ onReorderItems: (orderedIds) => console.log('reordered', orderedIds),
65
+ },
66
+ };
67
+
68
+ export const Loading = {
69
+ render: (args) => <SidebarWithState {...args} />,
70
+ args: {
71
+ groups: [],
72
+ loading: true,
73
+ skeletonItems: 8,
74
+ user: { email: 'jane.doe@example.com' },
75
+ },
76
+ };
77
+
78
+ export const NotCollapsible = {
79
+ render: (args) => <SidebarWithState {...args} />,
80
+ args: {
81
+ groups,
82
+ collapsible: false,
83
+ user: { email: 'jane.doe@example.com' },
84
+ userMenuItems,
85
+ },
86
+ };
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Filtra los grupos de menú y sus elementos basándose en un término de búsqueda.
3
+ */
4
+ export function filterMenuGroups(groups, query) {
5
+ if (!groups || !Array.isArray(groups)) return [];
6
+ if (!query) return groups;
7
+
8
+ const lowercaseQuery = query.toLowerCase();
9
+
10
+ return groups
11
+ .map((group) => {
12
+ const filteredItems = (group.items || []).filter((item) => {
13
+ const matchesLabel = item.label?.toLowerCase().includes(lowercaseQuery);
14
+ // También buscamos en subItems si existieran
15
+ const matchesSubItems = item.subItems?.some(sub =>
16
+ sub.label?.toLowerCase().includes(lowercaseQuery)
17
+ );
18
+ return matchesLabel || matchesSubItems;
19
+ });
20
+
21
+ return {
22
+ ...group,
23
+ items: filteredItems,
24
+ };
25
+ })
26
+ .filter((group) => group.items.length > 0);
27
+ }
28
+
29
+ /**
30
+ * Determina si un evento de teclado corresponde al atajo Ctrl/Cmd+B para
31
+ * colapsar o expandir el sidebar.
32
+ */
33
+ export function isSidebarToggleShortcut(event) {
34
+ return (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'b';
35
+ }
36
+
37
+ /**
38
+ * Invierte el estado de colapso del sidebar y lo persiste en localStorage.
39
+ * Usado tanto por el botón de toggle como por el atajo de teclado.
40
+ */
41
+ export function toggleSidebarCollapsed(prevCollapsed) {
42
+ const next = !prevCollapsed;
43
+ localStorage.setItem('sidebar_collapsed', String(next));
44
+ return next;
45
+ }
46
+
47
+ /**
48
+ * Retorna la inicial (mayúscula) de un texto, usada para generar avatares.
49
+ */
50
+ export function getInitial(value) {
51
+ if (!value) return '?';
52
+ const trimmed = String(value).trim();
53
+ return trimmed ? trimmed.charAt(0).toUpperCase() : '?';
54
+ }
55
+
56
+ /**
57
+ * Retorna la clase CSS correspondiente al tipo de badge de la opción del menú.
58
+ */
59
+ export function getBadgeClass(styles, badgeType) {
60
+ if (!styles || !badgeType) return '';
61
+
62
+ switch (badgeType) {
63
+ case 'post':
64
+ return styles.badgePost;
65
+ case 'get':
66
+ return styles.badgeGet;
67
+ case 'put':
68
+ return styles.badgePut;
69
+ case 'delete':
70
+ return styles.badgeDelete;
71
+ case 'info':
72
+ default:
73
+ return styles.badgeInfo;
74
+ }
75
+ }
@@ -0,0 +1,11 @@
1
+ import styles from './index.module.css';
2
+
3
+ const Skeleton = ({ width = '100%', height = '1em', radius = '6px', circle = false, className = '', style = {} }) => (
4
+ <span
5
+ className={`${styles.skeleton} ${className}`}
6
+ style={{ width, height, borderRadius: circle ? '50%' : radius, ...style }}
7
+ />
8
+ );
9
+
10
+ export default Skeleton;
11
+ export { Skeleton };
@@ -0,0 +1,26 @@
1
+ .skeleton {
2
+ position: relative;
3
+ display: inline-block;
4
+ overflow: hidden;
5
+ background: rgba(128, 128, 128, 0.18);
6
+ }
7
+
8
+ .skeleton::after {
9
+ content: '';
10
+ position: absolute;
11
+ inset: 0;
12
+ transform: translateX(-100%);
13
+ background: linear-gradient(
14
+ 90deg,
15
+ rgba(255, 255, 255, 0) 0%,
16
+ rgba(255, 255, 255, 0.35) 50%,
17
+ rgba(255, 255, 255, 0) 100%
18
+ );
19
+ animation: skeletonSweep 1.6s ease-in-out infinite;
20
+ }
21
+
22
+ @keyframes skeletonSweep {
23
+ 100% {
24
+ transform: translateX(100%);
25
+ }
26
+ }
@@ -0,0 +1,42 @@
1
+ import Skeleton from './index';
2
+
3
+ export default {
4
+ title: 'Components/Skeleton',
5
+ component: Skeleton,
6
+ };
7
+
8
+ export const TextLine = {
9
+ args: {
10
+ width: '200px',
11
+ height: '1em',
12
+ },
13
+ };
14
+
15
+ export const Circle = {
16
+ args: {
17
+ circle: true,
18
+ width: 40,
19
+ height: 40,
20
+ },
21
+ };
22
+
23
+ export const Block = {
24
+ args: {
25
+ width: '100%',
26
+ height: '120px',
27
+ radius: '12px',
28
+ },
29
+ };
30
+
31
+ export const ListPreview = {
32
+ render: () => (
33
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 12, width: 260 }}>
34
+ {Array.from({ length: 4 }).map((_, idx) => (
35
+ <div key={idx} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
36
+ <Skeleton circle width={28} height={28} />
37
+ <Skeleton width={`${60 + (idx % 3) * 15}%`} height="12px" />
38
+ </div>
39
+ ))}
40
+ </div>
41
+ ),
42
+ };
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import styles from './index.module.css';
3
+
4
+ import Button from '../Button';
5
+
6
+ export default function SubSidebarLayout({
7
+ menuItems = [],
8
+ activeItemId,
9
+ onItemClick,
10
+ children,
11
+ bgColor
12
+ }) {
13
+ return (
14
+ <div className={styles.layoutWrapper}>
15
+ <aside
16
+ className={styles.subSidebar}
17
+ style={{
18
+ ...(bgColor ? { '--subsidebarlayout-bg': bgColor } : {}),
19
+ }}
20
+ >
21
+ <div className={styles.menuList}>
22
+ {menuItems.map(item => {
23
+ const isActive = activeItemId === item.id;
24
+ return (
25
+ <Button
26
+ key={item.id}
27
+ variant={Button.VARIANTS.TAB}
28
+ size={Button.SIZES.LARGE}
29
+ active={isActive}
30
+ onClick={() => onItemClick(item.id, item)}
31
+ >
32
+ {item.icon && <span className={styles.iconWrapper}>{item.icon}</span>}
33
+ <span className={styles.label}>{item.label}</span>
34
+ </Button>
35
+ )
36
+ })}
37
+ </div>
38
+ </aside>
39
+ <div className={styles.contentArea}>
40
+ {children}
41
+ </div>
42
+ </div>
43
+ );
44
+ }