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.
- package/.github/workflows/ci.yml +31 -0
- package/.github/workflows/publish.yml +45 -0
- package/.npmrc.bak +1 -0
- package/.storybook/main.js +15 -0
- package/.storybook/preview.jsx +26 -0
- package/AnteriorityUI.md +2400 -0
- package/CLAUDE.md +91 -0
- package/README.md +182 -0
- package/assets/anteriorityUI/AnteriorityUI.logo.jpeg +0 -0
- package/assets/favicon/anteriorityUI.ico +0 -0
- package/common/api/client.js +43 -0
- package/common/storage/LocalStorage.js +13 -0
- package/common/styles/typography.css +5 -0
- package/common/styles/variables.css +192 -0
- package/common/theme/muiTheme.js +9 -0
- package/features/password-reset/api.js +39 -0
- package/features/user-profile/api.js +5 -0
- package/hooks/useAdminPasswordReset.js +133 -0
- package/index.js +57 -0
- package/package.json +57 -0
- package/pnpm-workspace.yaml +3 -0
- package/screens/components/AlertModal/AlertModal.jsx +259 -0
- package/screens/components/AlertModal/AlertModal.module.css +185 -0
- package/screens/components/AlertModal/AlertModal.stories.jsx +87 -0
- package/screens/components/Avatar/index.jsx +0 -0
- package/screens/components/Avatar/index.module.css +0 -0
- package/screens/components/Avatar/utils.js +0 -0
- package/screens/components/Badge/index.jsx +33 -0
- package/screens/components/Badge/index.module.css +18 -0
- package/screens/components/Badge/index.stories.jsx +40 -0
- package/screens/components/Barnner/index.jsx +21 -0
- package/screens/components/Barnner/index.module.css +33 -0
- package/screens/components/Barnner/index.stories.jsx +39 -0
- package/screens/components/Barnner/utils.js +0 -0
- package/screens/components/BlueLink/index.jsx +27 -0
- package/screens/components/BlueLink/index.module.css +11 -0
- package/screens/components/BlueLink/index.stories.jsx +29 -0
- package/screens/components/Breadcrumbs/index.jsx +62 -0
- package/screens/components/Breadcrumbs/index.module.css +158 -0
- package/screens/components/Breadcrumbs/index.stories.jsx +37 -0
- package/screens/components/Button/index.jsx +169 -0
- package/screens/components/Button/index.module.css +168 -0
- package/screens/components/Button/index.stories.jsx +71 -0
- package/screens/components/Button/utils.js +28 -0
- package/screens/components/CalendarComponent/CustomDatePicker.jsx +248 -0
- package/screens/components/CalendarComponent/CustomDatePicker.module.css +323 -0
- package/screens/components/CalendarComponent/CustomDatePicker.stories.jsx +45 -0
- package/screens/components/CalendarPicker/Constants.js +12 -0
- package/screens/components/CalendarPicker/index.jsx +263 -0
- package/screens/components/CalendarPicker/index.module.css +147 -0
- package/screens/components/CalendarPicker/index.stories.jsx +45 -0
- package/screens/components/CalendarPicker/utils.js +42 -0
- package/screens/components/CardV1/index.jsx +165 -0
- package/screens/components/CardV1/index.module.css +232 -0
- package/screens/components/CardV1/index.stories.jsx +62 -0
- package/screens/components/CardV1/utils.js +49 -0
- package/screens/components/ChatWindow/index.jsx +251 -0
- package/screens/components/ChatWindow/index.module.css +311 -0
- package/screens/components/ChatWindow/index.stories.jsx +62 -0
- package/screens/components/Checks/index.jsx +31 -0
- package/screens/components/Checks/index.module.css +32 -0
- package/screens/components/Checks/index.stories.jsx +32 -0
- package/screens/components/Container/index.jsx +36 -0
- package/screens/components/Container/index.module.css +24 -0
- package/screens/components/Container/index.stories.jsx +32 -0
- package/screens/components/CopyText/index.jsx +42 -0
- package/screens/components/CopyText/index.module.css +52 -0
- package/screens/components/CopyText/index.stories.jsx +24 -0
- package/screens/components/CountdownBar/constants.js +3 -0
- package/screens/components/CountdownBar/index.jsx +81 -0
- package/screens/components/CountdownBar/index.module.css +45 -0
- package/screens/components/CountdownBar/index.stories.jsx +43 -0
- package/screens/components/CountdownBar/utils.js +119 -0
- package/screens/components/DateTag/index.jsx +33 -0
- package/screens/components/DateTag/index.module.css +12 -0
- package/screens/components/DateTag/index.stories.jsx +29 -0
- package/screens/components/DesplegablePanel/constants.js +0 -0
- package/screens/components/DesplegablePanel/index.jsx +61 -0
- package/screens/components/DesplegablePanel/index.module.css +120 -0
- package/screens/components/DesplegablePanel/index.stories.jsx +44 -0
- package/screens/components/DesplegablePanel/utils.js +0 -0
- package/screens/components/DrawPanel/index.jsx +217 -0
- package/screens/components/DrawPanel/index.module.css +252 -0
- package/screens/components/DrawPanel/index.stories.jsx +66 -0
- package/screens/components/DrawPanel/utils.js +0 -0
- package/screens/components/Filter/index.jsx +105 -0
- package/screens/components/Filter/index.module.css +91 -0
- package/screens/components/Filter/index.stories.jsx +46 -0
- package/screens/components/Filter/utils.js +0 -0
- package/screens/components/FormControls/FormControls.module.css +86 -0
- package/screens/components/FormControls/index.jsx +51 -0
- package/screens/components/FormControls/index.stories.jsx +36 -0
- package/screens/components/Frame/index.jsx +54 -0
- package/screens/components/Frame/index.module.css +102 -0
- package/screens/components/Frame/index.stories.jsx +37 -0
- package/screens/components/Frame/utils.js +0 -0
- package/screens/components/GreenHighlight/index.jsx +11 -0
- package/screens/components/GreenHighlight/index.module.css +7 -0
- package/screens/components/GreenHighlight/index.stories.jsx +26 -0
- package/screens/components/GreenHighlight/utils.jsx +45 -0
- package/screens/components/HoursPicker/Constants.js +26 -0
- package/screens/components/HoursPicker/index.jsx +350 -0
- package/screens/components/HoursPicker/index.module.css +99 -0
- package/screens/components/HoursPicker/index.stories.jsx +44 -0
- package/screens/components/HoursPicker/utils.js +48 -0
- package/screens/components/InfoTooltip/index.jsx +59 -0
- package/screens/components/InfoTooltip/index.module.css +98 -0
- package/screens/components/InfoTooltip/index.stories.jsx +35 -0
- package/screens/components/Input/index.jsx +36 -0
- package/screens/components/Input/index.module.css +49 -0
- package/screens/components/Input/index.stories.jsx +37 -0
- package/screens/components/Input/utils.js +0 -0
- package/screens/components/Loading/index.jsx +76 -0
- package/screens/components/Loading/index.module.css +193 -0
- package/screens/components/Loading/index.stories.jsx +38 -0
- package/screens/components/Loading/utils.js +0 -0
- package/screens/components/MarkdownContent/index.jsx +16 -0
- package/screens/components/MarkdownContent/index.module.css +149 -0
- package/screens/components/MarkdownContent/index.stories.jsx +30 -0
- package/screens/components/MarkdownEditor/index.jsx +430 -0
- package/screens/components/MarkdownEditor/index.module.css +192 -0
- package/screens/components/MarkdownEditor/index.stories.jsx +50 -0
- package/screens/components/Material-UI/Components/InputWithIcon/index.jsx +87 -0
- package/screens/components/Material-UI/Components/InputWithIcon/index.stories.jsx +49 -0
- package/screens/components/Material-UI/Components/MenuPopover/index.jsx +117 -0
- package/screens/components/Material-UI/Components/MenuPopover/index.stories.jsx +36 -0
- package/screens/components/Material-UI/Components/MultilinePlaceholder/index.jsx +44 -0
- package/screens/components/Material-UI/Components/MultilinePlaceholder/index.stories.jsx +45 -0
- package/screens/components/Material-UI/Components/Paginador/index.jsx +79 -0
- package/screens/components/Material-UI/Components/Paginador/index.stories.jsx +49 -0
- package/screens/components/Material-UI/Components/Search/index.jsx +81 -0
- package/screens/components/Material-UI/Components/Search/index.stories.jsx +68 -0
- package/screens/components/Material-UI/Components/Selector/index.jsx +100 -0
- package/screens/components/Material-UI/Components/Selector/index.module.css +0 -0
- package/screens/components/Material-UI/Components/Selector/index.stories.jsx +52 -0
- package/screens/components/Material-UI/Components/Selector/utils.js +0 -0
- package/screens/components/Material-UI/Components/TextField/index.jsx +61 -0
- package/screens/components/Material-UI/Components/TextField/index.stories.jsx +53 -0
- package/screens/components/ModalTooltip/ModalTooltip.jsx +122 -0
- package/screens/components/ModalTooltip/ModalTooltip.module.css +65 -0
- package/screens/components/ModalTooltip/ModalTooltip.stories.jsx +39 -0
- package/screens/components/Notification/Error/ErrorMessage.jsx +30 -0
- package/screens/components/Notification/Error/ErrorMessage.module.css +57 -0
- package/screens/components/Notification/Error/ErrorMessage.stories.jsx +37 -0
- package/screens/components/PasswordResetPanel/index.jsx +325 -0
- package/screens/components/PasswordResetPanel/index.stories.jsx +26 -0
- package/screens/components/PlaceholderButton/index.jsx +169 -0
- package/screens/components/PlaceholderButton/index.module.css +162 -0
- package/screens/components/PlaceholderButton/index.stories.jsx +69 -0
- package/screens/components/PlaceholderButton/utils.js +42 -0
- package/screens/components/Profile/Avatar/index.jsx +125 -0
- package/screens/components/Profile/Avatar/index.module.css +86 -0
- package/screens/components/Profile/Avatar/index.stories.jsx +48 -0
- package/screens/components/Profile/Avatar/utils.js +18 -0
- package/screens/components/Profile/index.jsx +58 -0
- package/screens/components/Profile/index.module.css +0 -0
- package/screens/components/Profile/index.stories.jsx +38 -0
- package/screens/components/Profile/utils.js +0 -0
- package/screens/components/ScrollBar/index.jsx +62 -0
- package/screens/components/ScrollBar/index.module.css +78 -0
- package/screens/components/ScrollBar/index.stories.jsx +64 -0
- package/screens/components/ScrollBar/utils.js +127 -0
- package/screens/components/Sidebar/constants.js +16 -0
- package/screens/components/Sidebar/index.jsx +399 -0
- package/screens/components/Sidebar/index.module.css +405 -0
- package/screens/components/Sidebar/index.stories.jsx +86 -0
- package/screens/components/Sidebar/utils.js +75 -0
- package/screens/components/Skeleton/index.jsx +11 -0
- package/screens/components/Skeleton/index.module.css +26 -0
- package/screens/components/Skeleton/index.stories.jsx +42 -0
- package/screens/components/SubSidebarLayout/index.jsx +44 -0
- package/screens/components/SubSidebarLayout/index.module.css +80 -0
- package/screens/components/SubSidebarLayout/index.stories.jsx +51 -0
- package/screens/components/SummaryCard/index.jsx +50 -0
- package/screens/components/SummaryCard/index.module.css +30 -0
- package/screens/components/SummaryCard/index.stories.jsx +29 -0
- package/screens/components/Swich/constants.js +4 -0
- package/screens/components/Swich/index.jsx +85 -0
- package/screens/components/Swich/index.module.css +68 -0
- package/screens/components/Swich/index.stories.jsx +44 -0
- package/screens/components/Swich/utils.js +0 -0
- package/screens/components/TableA/index.jsx +156 -0
- package/screens/components/TableA/index.module.css +105 -0
- package/screens/components/TableA/index.stories.jsx +116 -0
- package/screens/components/TableA/utils.js +11 -0
- package/screens/components/TableB/index.jsx +222 -0
- package/screens/components/TableB/index.module.css +295 -0
- package/screens/components/TableB/index.stories.jsx +110 -0
- package/screens/components/TableB/utils.js +11 -0
- package/screens/components/ToggleCard/index.jsx +64 -0
- package/screens/components/ToggleCard/index.module.css +111 -0
- package/screens/components/ToggleCard/index.stories.jsx +49 -0
- package/screens/components/UserEditPopover/index.jsx +102 -0
- package/screens/components/UserEditPopover/index.module.css +97 -0
- package/screens/components/UserEditPopover/index.stories.jsx +49 -0
- package/scripts/build.mjs +129 -0
- package/scripts/check-case.mjs +127 -0
- package/scripts/verify-dist.mjs +45 -0
- package/vitest.config.js +36 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Guía para trabajar en este repo. Para documentación orientada a consumidores de la librería, ver [README.md](README.md) (instalación, setup, estructura) y [AnteriorityUI.md](AnteriorityUI.md) (props y ejemplos de uso de cada uno de los 50 componentes, en un único documento).
|
|
4
|
+
|
|
5
|
+
## Qué es este proyecto
|
|
6
|
+
|
|
7
|
+
`anteriority-ui` es una librería interna de componentes React, extraída originalmente del proyecto `vet-system-WEB` (en `C:\Users\Usuario\ProjectoUniversidad\vet-system-WEB`), con el objetivo de reutilizarla en otros proyectos. Los componentes viven en `screens/components/` y están construidos sobre MUI + CSS Modules + lucide-react.
|
|
8
|
+
|
|
9
|
+
## Estructura
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
index.js → barrel: re-exporta los ~50 componentes por nombre (import { Button } from 'anteriority-ui')
|
|
13
|
+
screens/components/ → ~50 componentes de UI, uno por carpeta (index.jsx + .module.css + .stories.jsx, siempre en minúscula)
|
|
14
|
+
common/
|
|
15
|
+
styles/ → variables.css (design tokens en :root) y typography.css (fuente global + import de Google Fonts)
|
|
16
|
+
theme/muiTheme.js → theme de MUI compartido (fontFamily: var(--font-sans))
|
|
17
|
+
api/client.js → cliente HTTP genérico (fetch wrapper), sin lógica de negocio ni endpoints hardcodeados
|
|
18
|
+
storage/LocalStorage.js → utilidades de sessionStorage/localStorage (getUserId/setUserId)
|
|
19
|
+
features/
|
|
20
|
+
password-reset/api.js → funciones de API específicas del flujo de reseteo de contraseña
|
|
21
|
+
user-profile/api.js → función de API para actualizar nombre de usuario
|
|
22
|
+
hooks/useAdminPasswordReset.js → hook que consume features/password-reset/api.js
|
|
23
|
+
.storybook/ → config de Storybook (main.js, preview.jsx)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Regla de separación:** `screens/components/*` es UI pura y reutilizable. `features/*` y `hooks/*` son lógica de negocio (llamadas a API con endpoints concretos) — solo dos componentes dependen de ellos (`PasswordResetPanel`, `UserEditPopover`), y ambos siguen funcionando/renderizando sin crashear aunque no haya backend real detrás (las llamadas fallan silenciosamente, atrapadas en try/catch).
|
|
27
|
+
|
|
28
|
+
## Origen y por qué existen `common/api`, `features/`, `hooks/`
|
|
29
|
+
|
|
30
|
+
Al extraer componentes de `vet-system-WEB`, algunos (`Button`, `Sidebar`, `PasswordResetPanel`, `UserEditPopover`, etc.) importaban cosas fuera del árbol de componentes: `ModalTooltip`, `AlertModal`, `Notification/Error/ErrorMessage` (ya copiados dentro de `screens/components/`), y lógica real de negocio (`services/api`, `hooks/useAdminPasswordReset`, `context/LocalStorage`). Para esta última parte, en vez de copiar el cliente API completo de vet-system-WEB (771 líneas acopladas a axios/config/dummyDB/tokens de esa app específica), se reimplementó un cliente HTTP genérico (`common/api/client.js`) y solo las funciones puntuales que los dos componentes necesitan (`features/password-reset`, `features/user-profile`), para que la librería no dependa del backend de ningún proyecto en particular.
|
|
31
|
+
|
|
32
|
+
Un consumidor de la librería que quiera usar `PasswordResetPanel` o `UserEditPopover` con datos reales debe llamar `configureApiClient({ baseURL, getAuthToken })` (ver README.md) antes de que se disparen las llamadas.
|
|
33
|
+
|
|
34
|
+
## Convención: props de color
|
|
35
|
+
|
|
36
|
+
La mayoría de los componentes con color propio (fondo, texto, ícono, borde) exponen props opcionales de color (`bgColor`, `textColor`, `iconColor`, `borderColor`, `accentColor`, o nombres específicos del rol cuando ninguno de esos encaja). Reglas al tocar o agregar componentes:
|
|
37
|
+
|
|
38
|
+
- **Todo prop de color es opcional y su default debe reproducir exactamente el color hardcodeado que existía antes** — es un cambio aditivo, nunca un rediseño.
|
|
39
|
+
- **Mecanismo:** si el color vive en el CSS module, se convierte a `var(--token-local, <valor-original>)` y el componente aplica `style={{ '--token-local': prop }}` solo cuando la prop viene definida (merge con cualquier `style` que el componente ya reciba). Esto funciona incluso para gradientes, `:hover` y contenido en portales (las CSS custom properties heredan).
|
|
40
|
+
- Si el color ya estaba inline en JSX (`style`, `sx`, `color=` de MUI), se reemplaza el literal por la prop con ese mismo valor como default de parámetro.
|
|
41
|
+
- **Los componentes con sistema `variant`/`type` (Barnner, DesplegablePanel, Notification/Error, TableB) mantienen su variant tal cual** — las props de color nuevas son un override opcional por encima de la paleta que resolvería el variant.
|
|
42
|
+
- Nombres reutilizados a propósito para consistencia entre componentes: `bgColor`, `textColor`, `iconColor`, `borderColor`, `accentColor`.
|
|
43
|
+
|
|
44
|
+
## Tipografía y theme
|
|
45
|
+
|
|
46
|
+
La fuente global es **Plus Jakarta Sans** (Google Fonts), no Roboto (default de MUI) ni el serif por default del navegador. Esto requiere DOS piezas trabajando juntas:
|
|
47
|
+
- `common/styles/typography.css` → importa la fuente y define `body { font-family: var(--font-sans) }` (arregla elementos HTML planos, ej. un `<h3>` sin clase).
|
|
48
|
+
- `common/theme/muiTheme.js` → `ThemeProvider` de MUI con `typography.fontFamily: 'var(--font-sans)'` (arregla componentes MUI, que si no, ignoran el `body` y usan su propio theme default).
|
|
49
|
+
|
|
50
|
+
Si se agrega un componente nuevo con texto visible, verificar que se vea con la fuente correcta en Storybook (`.storybook/preview.jsx` ya envuelve todas las stories en ambos).
|
|
51
|
+
|
|
52
|
+
## Comandos
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pnpm storybook # levanta Storybook en http://localhost:6006
|
|
56
|
+
pnpm build-storybook # build estático de Storybook
|
|
57
|
+
pnpm build # check-case + compila a dist/ + verify-dist — correr antes de confiar en un release
|
|
58
|
+
pnpm check-case # solo el audit de mayúsculas/minúsculas en imports (rápido, sin compilar)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Barrel (`index.js`) — indexación de componentes
|
|
62
|
+
|
|
63
|
+
`index.js` en la raíz re-exporta cada componente por nombre (`export { default as Button } from './screens/components/Button/index.js'`, etc.) para que un consumidor pueda hacer `import { Button, Sidebar } from 'anteriority-ui'` sin conocer el subpath de cada uno. Es un archivo **mantenido a mano**, no generado — al agregar un componente nuevo en `screens/components/`, agregarlo también acá. Reglas:
|
|
64
|
+
- Alias siempre = nombre de la carpeta (no el nombre interno de la variable/función, que a veces difiere — ej. `Sidebar/index.jsx` exporta internamente `ProSidebar`, pero el barrel lo expone como `Sidebar`).
|
|
65
|
+
- Solo se re-exporta el `default` de cada componente, nunca `export *` — varios componentes tienen sus propios `VARIANTS`/`SIZES`/`COLORS` locales (ver [Convención: props de color](#convención-props-de-color) y el patrón `variant`/`type`) que colisionarían entre sí como named exports al tope del barrel. Quien necesite esos named exports sigue importando el subpath directo del componente.
|
|
66
|
+
- `screens/components/Avatar/` (el stub vacío) queda **fuera** del barrel a propósito — ver [Componentes sin implementar](#componentes-sin-implementar). El avatar real (`Profile/Avatar`) está en el barrel como `ProfileAvatar`.
|
|
67
|
+
- `FormControls` no tiene default export (exporta `FormCard`, `FormInput`, `FormTextArea` con nombre propio) — se re-exportan tal cual, sin alias de carpeta.
|
|
68
|
+
|
|
69
|
+
## Build y publicación (versionado real, npm público)
|
|
70
|
+
|
|
71
|
+
El paquete se publica en el registro público de npm como `anteriority-ui`, no vía `git+https://...` apuntando a `main` (ese instalaba el HEAD del branch sin versión ni changelog — ver [.github/workflows/publish.yml](.github/workflows/publish.yml)). Se eligió npm público en vez de GitHub Packages a propósito: GitHub Packages exige autenticación hasta para instalar (incluso en repos públicos), y la prioridad acá era que instalar fuera tan simple como `pnpm add mui` — sin `.npmrc` ni token del lado del consumidor. El costo es que el código queda visible públicamente en npm (el repo de GitHub puede seguir siendo privado).
|
|
72
|
+
|
|
73
|
+
- `scripts/build.mjs` transpila JSX → JS con esbuild (`jsx: 'automatic'`) y copia CSS Modules/otros assets, preservando la misma estructura de carpetas que el código fuente para que los subpath imports documentados en README.md sigan resolviendo igual. También genera `dist/package.json` (subset de campos del `package.json` raíz — ver el script para la lista exacta) porque `publishConfig.directory: "dist"` en el `package.json` raíz le dice a `pnpm publish` que empaquete desde ahí, no desde la raíz del repo.
|
|
74
|
+
- **Todos los imports relativos internos deben ser sin extensión** (`from '../Loading/index'`, no `'../Loading/index.jsx'`). Un import con extensión `.jsx` explícita funciona en el código fuente (Vite/Storybook resuelve contra el archivo `.jsx` real), pero rompe en `dist/` una vez compilado, porque esbuild transpila `.jsx` → `.js` sin reescribir el string del import — queda apuntando a un archivo que ya no existe. `scripts/verify-dist.mjs` (bundlea `dist/index.js` completo con esbuild, con los peer deps como `external`) es lo único que detecta esto; `pnpm build-storybook` NO alcanza porque corre contra el código fuente, no contra el paquete compilado.
|
|
75
|
+
- `scripts/check-case.mjs` audita que cada import relativo matchee el nombre real en disco con mayúsculas/minúsculas exactas (había 22 componentes con entry file `Index.jsx` en vez de `index.jsx` — rompía deploys en Linux por ser case-sensitive, invisible en Windows/Mac). Corre como parte de `pnpm build` y en CI ([.github/workflows/ci.yml](.github/workflows/ci.yml)).
|
|
76
|
+
- **Gotcha real ya vivido:** un rename de archivo solo-de-casing (`Index.jsx` → `index.jsx`) en Windows puede quedar sin aplicar físicamente en disco después de un `git checkout`/merge, aunque el índice de git ya diga `index.jsx` — NTFS es case-insensitive y git a veces no reescribe el archivo físico si solo cambia el casing. Si `pnpm check-case` falla después de un pull que "debería" traer un fix de casing ya mergeado, sospechar de esto antes de asumir que el fix nunca se aplicó.
|
|
77
|
+
- El workflow de publish se dispara con push de un tag `vX.Y.Z` y valida que coincida con la versión de `package.json` antes de publicar — ver la sección "Versionado y releases" en README.md para el flujo (`pnpm version patch/minor/major` + `git push --tags`).
|
|
78
|
+
- Si se agrega un componente/carpeta nueva bajo `screens/`, `common/`, `features/` o `hooks/`, no hace falta tocar nada del build — `scripts/build.mjs` recorre esos cuatro directorios dinámicamente. Sí hay que agregarlo a mano al barrel `index.js` (ver arriba).
|
|
79
|
+
- `react`, `react-dom`, `@mui/material`, `@emotion/*` ya son `peerDependencies` (no van empaquetados) — eso ya estaba bien resuelto antes de este cambio; lo que faltaba era el build + versionado, no las peer deps.
|
|
80
|
+
|
|
81
|
+
## ⚠️ Gotcha de pnpm workspace
|
|
82
|
+
|
|
83
|
+
`C:\Users\Usuario` (la carpeta home del usuario) es raíz de OTRO proyecto suyo no relacionado (`proyecto-hp-backend`, con su propio `package.json`/`pnpm-workspace.yaml`/`.git`). Como está dos niveles arriba de este repo, pnpm puede tratarlo como raíz del workspace y mezclar instalaciones ahí en vez de aislarlas acá. Por eso este repo tiene su propio `pnpm-workspace.yaml` (con `packages: []`) — **no lo borres** — sirve para que pnpm pare la búsqueda hacia arriba y trate `AnteriorityUI` como su propia raíz. Si algo similar vuelve a romperse (paquetes no encontrados en runtime pese a estar en `package.json`), sospechar primero de esto antes de reinstalar todo.
|
|
84
|
+
|
|
85
|
+
## Storybook
|
|
86
|
+
|
|
87
|
+
Cada componente en `screens/components/` tiene un `.stories.jsx` (formato CSF3) al lado de su implementación. Al agregar un componente nuevo, agregarle también su story con variantes reales (no placeholders) — son la referencia que se usa para escribir/actualizar la sección correspondiente en AnteriorityUI.md.
|
|
88
|
+
|
|
89
|
+
## Componentes sin implementar
|
|
90
|
+
|
|
91
|
+
`screens/components/Avatar/` (`index.jsx`, `utils.js`, `index.module.css`) son archivos vacíos (0 bytes) — un stub sin terminar, no lo usa nada del código. El avatar real y usado es `screens/components/Profile/Avatar/`. No confundir los dos ni documentar el stub hasta que tenga contenido real.
|
package/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/favicon/anteriorityUI.ico" alt="anteriority-ui" width="480" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# anteriority-ui
|
|
6
|
+
|
|
7
|
+
Librería interna de componentes React (UI) para reutilizar entre proyectos. Construida sobre [MUI](https://mui.com/), [lucide-react](https://lucide.dev/) y CSS Modules, con [Storybook](https://storybook.js.org/) para navegar y probar cada componente de forma aislada.
|
|
8
|
+
|
|
9
|
+
## Instalación
|
|
10
|
+
|
|
11
|
+
Publicada en el registro público de npm — se instala igual que cualquier otra dependencia, sin tokens ni configuración extra:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add anteriority-ui
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Cada versión se genera a partir de un tag `vX.Y.Z` (semver real, no el HEAD de `main`) — ver [Versionado y releases](#versionado-y-releases).
|
|
18
|
+
|
|
19
|
+
### Peer dependencies
|
|
20
|
+
|
|
21
|
+
Estas dependencias las provee el proyecto que consume la librería (no van empaquetadas, para evitar duplicar React/MUI):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pnpm add react react-dom @mui/material @emotion/react @emotion/styled
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Setup en el proyecto consumidor
|
|
28
|
+
|
|
29
|
+
1. Importar los estilos base (design tokens + tipografía) una sola vez, en el punto de entrada de la app:
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
import 'anteriority-ui/common/styles/variables.css';
|
|
33
|
+
import 'anteriority-ui/common/styles/typography.css';
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. Envolver la app en el `ThemeProvider` de MUI con el theme de la librería, para que los componentes basados en MUI (Button, TextField, Selector, etc.) usen la misma tipografía y no el Roboto por default de MUI:
|
|
37
|
+
|
|
38
|
+
```jsx
|
|
39
|
+
import { ThemeProvider } from '@mui/material/styles';
|
|
40
|
+
import muiTheme from 'anteriority-ui/common/theme/muiTheme';
|
|
41
|
+
|
|
42
|
+
function App() {
|
|
43
|
+
return (
|
|
44
|
+
<ThemeProvider theme={muiTheme}>
|
|
45
|
+
{/* resto de la app */}
|
|
46
|
+
</ThemeProvider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
3. (Opcional) Si vas a usar `hooks/useAdminPasswordReset` o cualquier función de `features/*/api.js`, configurá el cliente HTTP genérico una vez al arrancar la app:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
import { configureApiClient } from 'anteriority-ui/common/api/client';
|
|
55
|
+
|
|
56
|
+
configureApiClient({
|
|
57
|
+
baseURL: 'https://api.tu-proyecto.com',
|
|
58
|
+
getAuthToken: () => localStorage.getItem('token'),
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Importar componentes
|
|
63
|
+
|
|
64
|
+
Todos los componentes están indexados en el entry point principal — no hace falta conocer el subpath de cada uno:
|
|
65
|
+
|
|
66
|
+
```jsx
|
|
67
|
+
import { Button, Sidebar, TableB } from 'anteriority-ui';
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Alternativa, importando el subpath directo de cada componente (útil para acceder a exports nombrados extra que no pasan por el barrel, ej. `Button.VARIANTS`):
|
|
71
|
+
|
|
72
|
+
```jsx
|
|
73
|
+
import Button, { VARIANTS } from 'anteriority-ui/screens/components/Button';
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Estructura del proyecto
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
screens/components/ → componentes de UI (uno por carpeta, ver docs abajo)
|
|
80
|
+
common/
|
|
81
|
+
styles/ → variables.css (design tokens) y typography.css (fuente global)
|
|
82
|
+
theme/ → muiTheme.js, el theme de MUI compartido
|
|
83
|
+
api/ → cliente HTTP genérico (client.js), sin lógica de negocio
|
|
84
|
+
storage/ → utilidades de localStorage/sessionStorage (LocalStorage.js)
|
|
85
|
+
features/
|
|
86
|
+
password-reset/ → lógica de API para el flujo de reseteo de contraseña
|
|
87
|
+
user-profile/ → lógica de API para edición de perfil de usuario
|
|
88
|
+
hooks/ → hooks reutilizables (useAdminPasswordReset)
|
|
89
|
+
.storybook/ → configuración de Storybook
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Cada componente en `screens/components/` es independiente entre sí salvo por composición explícita (por ejemplo, `Button` usa `ModalTooltip`, `TableB` usa `Barnner`). Ningún componente de UI importa nada de `features/` directamente salvo los que ya tienen lógica de negocio propia (`PasswordResetPanel`, `UserEditPopover`).
|
|
93
|
+
|
|
94
|
+
## Versionado y releases
|
|
95
|
+
|
|
96
|
+
La librería se compila (JSX → JS, se preserva la estructura de carpetas) antes de publicarse — ver [scripts/build.mjs](scripts/build.mjs). El build corre solo en CI, no hace falta ejecutarlo a mano salvo para probarlo localmente con `pnpm run build`.
|
|
97
|
+
|
|
98
|
+
**Setup único, antes del primer release:** generar un [access token de npm](https://www.npmjs.com/) de tipo *Automation* (desde la cuenta/organización de npm que va a ser dueña del paquete) y cargarlo como secret `NPM_TOKEN` en Settings → Secrets and variables → Actions de este repo. Sin esto el workflow de publish falla.
|
|
99
|
+
|
|
100
|
+
Para publicar una nueva versión (ej. después de un fix en un componente):
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pnpm version patch # o minor / major — bumpea package.json, commitea y crea el tag vX.Y.Z
|
|
104
|
+
git push && git push --tags
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
El push del tag dispara [.github/workflows/publish.yml](.github/workflows/publish.yml), que compila y publica a npm con el secret `NPM_TOKEN`. El workflow falla si el tag no coincide con la versión del `package.json`, como chequeo de seguridad.
|
|
108
|
+
|
|
109
|
+
Los proyectos consumidores controlan cuándo actualizar corriendo `pnpm update anteriority-ui` (respetando el rango semver que hayan fijado), en vez de recibir cambios de golpe con cada push a `main`.
|
|
110
|
+
|
|
111
|
+
## Ver los componentes en Storybook
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pnpm storybook
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Abre `http://localhost:6006` con los ~50 componentes navegables, cada uno con varias variantes de ejemplo.
|
|
118
|
+
|
|
119
|
+
## Convención de colores
|
|
120
|
+
|
|
121
|
+
La mayoría de los componentes con color propio (fondo, texto, ícono, borde) exponen props opcionales para sobreescribirlo — por ejemplo `bgColor`, `textColor`, `iconColor`, `borderColor`, `accentColor`. Si no se pasa la prop, el componente se ve exactamente igual que antes (el valor por default reproduce el color original). Ver [AnteriorityUI.md](AnteriorityUI.md) para la lista exacta de props de color que acepta cada componente.
|
|
122
|
+
|
|
123
|
+
Componentes que ya tenían un sistema de `variant`/`type` con paletas predefinidas (`Barnner`, `DesplegablePanel`, `Notification/Error`, `TableB`) lo conservan tal cual — las props de color nuevas son un override opcional por encima del `variant` elegido.
|
|
124
|
+
|
|
125
|
+
## Componentes
|
|
126
|
+
|
|
127
|
+
Documentación completa de props y ejemplos de uso de los 50 componentes en **[AnteriorityUI.md](AnteriorityUI.md)**.
|
|
128
|
+
|
|
129
|
+
| Componente | Descripción |
|
|
130
|
+
|---|---|
|
|
131
|
+
| [AlertModal](AnteriorityUI.md#alertmodal) | Modal de confirmación/alerta, con soporte de input embebido |
|
|
132
|
+
| [Badge](AnteriorityUI.md#badge) | Etiqueta de estado con ícono, label y valor |
|
|
133
|
+
| [Barnner](AnteriorityUI.md#barnner) | Banner de aviso con variantes de color |
|
|
134
|
+
| [BlueLink](AnteriorityUI.md#bluelink) | Link de navegación con tooltip |
|
|
135
|
+
| [Breadcrumbs](AnteriorityUI.md#breadcrumbs) | Migas de pan de navegación |
|
|
136
|
+
| [Button](AnteriorityUI.md#button) | Botón (envoltorio de MUI Button) con variantes, loading, tooltip |
|
|
137
|
+
| [CalendarComponent](AnteriorityUI.md#calendarcomponent) | Selector de fecha standalone (date picker) |
|
|
138
|
+
| [CalendarPicker](AnteriorityUI.md#calendarpicker) | Selector de fecha integrado a un `TextField` |
|
|
139
|
+
| [CardV1](AnteriorityUI.md#cardv1) | Tarjeta con badges, acción e indicadores de estado |
|
|
140
|
+
| [ChatWindow](AnteriorityUI.md#chatwindow) | Ventana de chat completa (mensajes, input, avatar) |
|
|
141
|
+
| [Checks](AnteriorityUI.md#checks) | Checkbox de permisos/ítem seleccionable |
|
|
142
|
+
| [Container](AnteriorityUI.md#container) | Contenedor con paginación integrada |
|
|
143
|
+
| [CopyText](AnteriorityUI.md#copytext) | Texto con botón de copiar al portapapeles |
|
|
144
|
+
| [CountdownBar](AnteriorityUI.md#countdownbar) | Barra de progreso con cuenta regresiva |
|
|
145
|
+
| [DateTag](AnteriorityUI.md#datetag) | Etiqueta de fecha formateada |
|
|
146
|
+
| [DesplegablePanel](AnteriorityUI.md#desplegablepanel) | Panel colapsable con ícono temático |
|
|
147
|
+
| [DrawPanel](AnteriorityUI.md#drawpanel) | Panel lateral deslizable (drawer) |
|
|
148
|
+
| [Filter](AnteriorityUI.md#filter) | Panel de filtros con contador de activos |
|
|
149
|
+
| [FormControls](AnteriorityUI.md#formcontrols) | Controles de formulario (Card, Input, TextArea) |
|
|
150
|
+
| [Frame](AnteriorityUI.md#frame) | Marco/tarjeta base reutilizable, soporta modal |
|
|
151
|
+
| [GreenHighlight](AnteriorityUI.md#greenhighlight) | Resaltado de texto/valor destacado |
|
|
152
|
+
| [HoursPicker](AnteriorityUI.md#hourspicker) | Selector de horario |
|
|
153
|
+
| [InfoTooltip](AnteriorityUI.md#infotooltip) | Ícono de información con tooltip |
|
|
154
|
+
| [Input](AnteriorityUI.md#input) | Input de texto (envoltorio de MUI TextField) |
|
|
155
|
+
| [Loading](AnteriorityUI.md#loading) | Indicadores de carga (spinner, barras, rebote) |
|
|
156
|
+
| [MarkdownContent](AnteriorityUI.md#markdowncontent) | Render de contenido Markdown |
|
|
157
|
+
| [MarkdownEditor](AnteriorityUI.md#markdowneditor) | Editor de Markdown con vista previa |
|
|
158
|
+
| [Material-UI/Components/InputWithIcon](AnteriorityUI.md#inputwithicon) | Input con ícono embebido |
|
|
159
|
+
| [Material-UI/Components/MenuPopover](AnteriorityUI.md#menupopover) | Menú contextual (popover) |
|
|
160
|
+
| [Material-UI/Components/MultilinePlaceholder](AnteriorityUI.md#multilineplaceholder) | Textarea con placeholder multilinea |
|
|
161
|
+
| [Material-UI/Components/Paginador](AnteriorityUI.md#paginador) | Paginación (envoltorio de MUI Pagination) |
|
|
162
|
+
| [Material-UI/Components/Search](AnteriorityUI.md#search) | Buscador con autocompletado |
|
|
163
|
+
| [Material-UI/Components/Selector](AnteriorityUI.md#selector) | Select (envoltorio de MUI Select) |
|
|
164
|
+
| [Material-UI/Components/TextField](AnteriorityUI.md#textfield) | TextField base compartido por otros componentes |
|
|
165
|
+
| [ModalTooltip](AnteriorityUI.md#modaltooltip) | Tooltip flotante (portal) |
|
|
166
|
+
| [Notification/Error/ErrorMessage](AnteriorityUI.md#errormessage) | Mensaje de error/éxito inline |
|
|
167
|
+
| [PasswordResetPanel](AnteriorityUI.md#passwordresetpanel) | Panel de flujo de reseteo de contraseña (usa `features/password-reset`) |
|
|
168
|
+
| [PlaceholderButton](AnteriorityUI.md#placeholderbutton) | Botón que se convierte en input al hacer click |
|
|
169
|
+
| [Profile](AnteriorityUI.md#profile) | Header de perfil de usuario |
|
|
170
|
+
| [Profile/Avatar](AnteriorityUI.md#avatar-profileavatar) | Avatar con estado (online/offline) |
|
|
171
|
+
| [ScrollBar](AnteriorityUI.md#scrollbar) | Contenedor con scrollbar estilizada |
|
|
172
|
+
| [Sidebar](AnteriorityUI.md#sidebar) | Barra lateral de navegación completa |
|
|
173
|
+
| [Skeleton](AnteriorityUI.md#skeleton) | Placeholders de carga (shimmer) |
|
|
174
|
+
| [SubSidebarLayout](AnteriorityUI.md#subsidebarlayout) | Layout de sub-sidebar con menú |
|
|
175
|
+
| [SummaryCard](AnteriorityUI.md#summarycard) | Tarjeta de resumen con degradado |
|
|
176
|
+
| [Swich](AnteriorityUI.md#swich) | Interruptor (switch) on/off |
|
|
177
|
+
| [TableA](AnteriorityUI.md#tablea) | Tabla simple con columnas configurables |
|
|
178
|
+
| [TableB](AnteriorityUI.md#tableb) | Tabla con filas expandibles y badges |
|
|
179
|
+
| [ToggleCard](AnteriorityUI.md#togglecard) | Tarjeta colapsable con acción |
|
|
180
|
+
| [UserEditPopover](AnteriorityUI.md#usereditpopover) | Popover de edición de nombre de usuario (usa `features/user-profile`) |
|
|
181
|
+
|
|
182
|
+
> `screens/components/Avatar/` existe pero está sin implementar (archivos vacíos) — no se documenta hasta que tenga contenido.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
let baseURL = '';
|
|
2
|
+
let getAuthToken = () => null;
|
|
3
|
+
|
|
4
|
+
// Debe llamarse una vez al iniciar la app consumidora de la librería.
|
|
5
|
+
export function configureApiClient({ baseURL: base, getAuthToken: tokenGetter } = {}) {
|
|
6
|
+
if (base !== undefined) baseURL = base;
|
|
7
|
+
if (tokenGetter) getAuthToken = tokenGetter;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function request(path, { method = 'GET', body, headers = {}, auth = true } = {}) {
|
|
11
|
+
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
|
12
|
+
const url = `${baseURL}${cleanPath}`;
|
|
13
|
+
|
|
14
|
+
const opts = { method, headers: { ...headers } };
|
|
15
|
+
|
|
16
|
+
if (auth) {
|
|
17
|
+
const token = getAuthToken();
|
|
18
|
+
if (token) opts.headers['Authorization'] = `Bearer ${token}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (body !== undefined && !['GET', 'HEAD'].includes(method.toUpperCase())) {
|
|
22
|
+
opts.headers['Content-Type'] = opts.headers['Content-Type'] || 'application/json';
|
|
23
|
+
opts.body = typeof body === 'string' ? body : JSON.stringify(body);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const res = await fetch(url, opts);
|
|
27
|
+
|
|
28
|
+
if (res.status === 204) return null;
|
|
29
|
+
|
|
30
|
+
const contentType = (res.headers.get('content-type') || '').toLowerCase();
|
|
31
|
+
const data = contentType.includes('application/json')
|
|
32
|
+
? await res.json().catch(() => null)
|
|
33
|
+
: await res.text();
|
|
34
|
+
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
const err = new Error((data && (data.error || data.message)) || res.statusText || `Request failed (${res.status})`);
|
|
37
|
+
err.status = res.status;
|
|
38
|
+
err.body = data;
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
// Guarda el id del usuario logueado
|
|
3
|
+
export function setUserId(id) {
|
|
4
|
+
if (!id) return;
|
|
5
|
+
localStorage.setItem('user_id', id);
|
|
6
|
+
sessionStorage.setItem('user_id', id);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Obtiene el id del usuario logueado
|
|
10
|
+
export function getUserId() {
|
|
11
|
+
// Prioriza sessionStorage para evitar IDs viejos de otra sesión/pestaña.
|
|
12
|
+
return sessionStorage.getItem('user_id') || localStorage.getItem('user_id') || null;
|
|
13
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
/*fondo sistema*/
|
|
3
|
+
--bg-soft: rgba(216, 239, 220, 0);
|
|
4
|
+
--bg-modal-big: rgb(188, 219, 188);
|
|
5
|
+
--bg-marron-gueso: #E3DAC9;
|
|
6
|
+
/*colores de botones*/
|
|
7
|
+
--button-blue: linear-gradient(135deg, #0284c7, #0369a1);
|
|
8
|
+
--button-hover-blue: #0369a1;
|
|
9
|
+
--button-green: #0f766e;
|
|
10
|
+
--button-hover-green: rgb(0, 167, 39);
|
|
11
|
+
--cancel-button: red;
|
|
12
|
+
--button-hover-red: rgb(203, 3, 3);
|
|
13
|
+
/*letras*/
|
|
14
|
+
--letter: #103529;
|
|
15
|
+
--letter-white: #ffffff;
|
|
16
|
+
/*interfaz CitasDoctor*/
|
|
17
|
+
--ink: #0f172a;
|
|
18
|
+
--line: #008412;
|
|
19
|
+
--brand-dark: #115e59;
|
|
20
|
+
--danger-bg: #fdfdfd;
|
|
21
|
+
--danger-text: #991b1b;
|
|
22
|
+
|
|
23
|
+
/*diseño*/
|
|
24
|
+
--blur: blur(18px);
|
|
25
|
+
--shadow: 2px 1px 6px rgb(0, 0, 0);
|
|
26
|
+
|
|
27
|
+
--color-secondary: rgb(2, 169, 18);
|
|
28
|
+
--color-secondary-dark: #027800;
|
|
29
|
+
--color-primary: rgb(23, 23, 255);
|
|
30
|
+
--color-primary-dark: #032585;
|
|
31
|
+
--color-danger: #ea1f1f;
|
|
32
|
+
--color-danger-dark: #dc2626;
|
|
33
|
+
--color-danger-bg: #fee2e2;
|
|
34
|
+
--color-text: #1e293b;
|
|
35
|
+
--color-text-muted: #64748b;
|
|
36
|
+
--color-text-muted2: #b3b7bd;
|
|
37
|
+
--color-border: #e2e8f0;
|
|
38
|
+
--productCardConsulta: #088d4f;
|
|
39
|
+
--color-card-bg: #ffffff;
|
|
40
|
+
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
41
|
+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
42
|
+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
43
|
+
--radius-sm: 0.375rem;
|
|
44
|
+
--radius-md: 0.5rem;
|
|
45
|
+
--radius-lg: 0.75rem;
|
|
46
|
+
--font-sans: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
|
|
47
|
+
--transition: all 0.2s ease;
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
/* Glassmorphism Green-White Gradient */
|
|
51
|
+
--bg-glass-gradient-green: linear-gradient(135deg, rgb(101, 255, 49), rgba(85, 255, 0, 0.45));
|
|
52
|
+
--bg-glass-gradient-ross: linear-gradient(135deg, rgba(207, 173, 2, 0.25), rgba(255, 255, 255, 0.45));
|
|
53
|
+
--bg-glass-gradient-logo: linear-gradient(135deg, rgba(34, 197, 94, 0.15), rgba(255, 255, 255, 0.5), rgba(14, 165, 233, 0.15));
|
|
54
|
+
|
|
55
|
+
--logo-yellow-soft: #60aaff31;
|
|
56
|
+
--logo-yellow-border: rgba(254, 240, 138, 0.5);
|
|
57
|
+
|
|
58
|
+
--glass-blur-panel: blur(12px);
|
|
59
|
+
--glass-border: 1px solid rgba(255, 255, 255, 0.4);
|
|
60
|
+
|
|
61
|
+
/* Pink-Green Glassmorphism */
|
|
62
|
+
--gr-pink-green: linear-gradient(135deg, #f47fe9 0%, #017A51 100%);
|
|
63
|
+
--glass-blur-pink-green: blur(10px);
|
|
64
|
+
|
|
65
|
+
/* Sidebar Glassmorphism */
|
|
66
|
+
--sidebar-bg: linear-gradient(135deg, rgba(34, 197, 94, 0.5), rgba(255, 255, 255, 0.4), rgba(14, 165, 233, 0.5));
|
|
67
|
+
--sidebar-blur: blur(24px);
|
|
68
|
+
--sidebar-border-right: 1px solid rgba(14, 165, 233, 0.3);
|
|
69
|
+
--sidebar-text: #0f172a;
|
|
70
|
+
--sidebar-text-muted: #475569;
|
|
71
|
+
--sidebar-text-active: #0ea5e9;
|
|
72
|
+
--sidebar-hover-bg: rgba(14, 165, 233, 0.08);
|
|
73
|
+
--sidebar-border: rgba(14, 165, 233, 0.15);
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
/*AlertModal*/
|
|
77
|
+
--modal-overlay-bg: rgba(15, 23, 42, 0.65);
|
|
78
|
+
--modal-bg: #ffffff70;
|
|
79
|
+
--modal-border: 1px solid rgba(226, 232, 240, 0.8);
|
|
80
|
+
--modal-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.02);
|
|
81
|
+
--modal-title-color: #0f172a;
|
|
82
|
+
--modal-text-color: #faebeb;
|
|
83
|
+
--primary-color: #2563eb;
|
|
84
|
+
--primary-hover: #000000;
|
|
85
|
+
--secondary-color: #f1f5f9;
|
|
86
|
+
--secondary-hover: #e2e8f0;
|
|
87
|
+
--border-radius-md: 0.5rem;
|
|
88
|
+
--border-radius-lg: 0.75rem;
|
|
89
|
+
--transition: all 0.2s ease;
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
/*AgreeProduct*/
|
|
93
|
+
--input-border: #e2e8f0;
|
|
94
|
+
--input-focus: #2a4d97;
|
|
95
|
+
--bg-dropdown: #ffffff;
|
|
96
|
+
--text-muted: #64748b00;
|
|
97
|
+
--item-hover: #f8fafc;
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
/*CreatedCita*/
|
|
101
|
+
--bg-page: #f8fafc;
|
|
102
|
+
--bg-inputs: #ffffff;
|
|
103
|
+
--text-primary: #0f172a;
|
|
104
|
+
--text-secondary: #475569;
|
|
105
|
+
--text-muted: #64748b;
|
|
106
|
+
--border-light: #e2e8f0;
|
|
107
|
+
--border-focus: #0ea5e9;
|
|
108
|
+
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
109
|
+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
110
|
+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
111
|
+
--radius-sm: 0.375rem;
|
|
112
|
+
--radius-md: 0.5rem;
|
|
113
|
+
--radius-lg: 0.75rem;
|
|
114
|
+
--transition: all 0.2s ease;
|
|
115
|
+
--font-sans: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
116
|
+
|
|
117
|
+
/*Facturas*/
|
|
118
|
+
--bg-facturas: #1e293b;
|
|
119
|
+
--bg-main: #0f172a;
|
|
120
|
+
--bg-hover: rgb(0, 80, 47);
|
|
121
|
+
--text-main: #f1f5f9;
|
|
122
|
+
--text-muted: #ffffff;
|
|
123
|
+
--accent-green: #10b981;
|
|
124
|
+
--accent-blue: #0c3d9f;
|
|
125
|
+
--border-color: #ffffff;
|
|
126
|
+
|
|
127
|
+
/*colores*/
|
|
128
|
+
--color-black: #000000;
|
|
129
|
+
--color-white: #ffffff;
|
|
130
|
+
|
|
131
|
+
/*inputs*/
|
|
132
|
+
--inputs-bordes: #309ff9;
|
|
133
|
+
--inputs-px: 2px;
|
|
134
|
+
|
|
135
|
+
/*Buttons color */
|
|
136
|
+
--btn-login: #34cc06;
|
|
137
|
+
--btn-login-hover: #259e04;
|
|
138
|
+
--btn-blue: rgb(1, 1, 225);
|
|
139
|
+
|
|
140
|
+
/* Switch Colors */
|
|
141
|
+
--SW-green: rgb(0, 125, 0);
|
|
142
|
+
--SW-blue: rgb(1, 1, 225);
|
|
143
|
+
--SW-red: rgb(197, 0, 0);
|
|
144
|
+
--SW-white: white;
|
|
145
|
+
--SW-disable-default: rgb(100, 100, 100);
|
|
146
|
+
--SW-thumb-color: white;
|
|
147
|
+
--SW-thumb-color: black;
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
/*Bordes*/
|
|
151
|
+
--border-gray-low: #9b9b9b;
|
|
152
|
+
--border-gray-hight: #575757;
|
|
153
|
+
--border-white: #f3f4f6;
|
|
154
|
+
--border-black: #000000;
|
|
155
|
+
|
|
156
|
+
/* Gradients */
|
|
157
|
+
--gr-login: linear-gradient(135deg, #0041f2, #1341e0);
|
|
158
|
+
--gr-login-hover: linear-gradient(135deg, #0039d1, #1039c2);
|
|
159
|
+
--gr-create: linear-gradient(135deg, #0041f2, #0039d1);
|
|
160
|
+
--gr-create-hover: linear-gradient(135deg, #0039d1, #1039c2);
|
|
161
|
+
--gr-danger: linear-gradient(135deg, #d10000, #c20000);
|
|
162
|
+
--gr-danger-hover: linear-gradient(135deg, #c20000, #a30000);
|
|
163
|
+
--gr-cancel: linear-gradient(135deg, #d10000, #c20000);
|
|
164
|
+
--gr-cancel-hover: linear-gradient(135deg, #c20000, #a30000);
|
|
165
|
+
--gr-spinner-green-blue: linear-gradient(135deg, #027800, #0284c7);
|
|
166
|
+
--gr-spinner-green-blue-hover: linear-gradient(135deg, #0039d1, #1039c2);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.glass-panel-green {
|
|
170
|
+
background: var(--bg-glass-gradient-green) !important;
|
|
171
|
+
backdrop-filter: var(--glass-blur-panel) !important;
|
|
172
|
+
-webkit-backdrop-filter: var(--glass-blur-panel) !important;
|
|
173
|
+
border: var(--glass-border) !important;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.sidebar-glass {
|
|
177
|
+
background: var(--sidebar-bg) !important;
|
|
178
|
+
backdrop-filter: var(--sidebar-blur) !important;
|
|
179
|
+
-webkit-backdrop-filter: var(--sidebar-blur) !important;
|
|
180
|
+
border-right: var(--sidebar-border-right) !important;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.glass-pink-green {
|
|
184
|
+
background: var(--gr-pink-green) !important;
|
|
185
|
+
backdrop-filter: var(--glass-blur-pink-green) !important;
|
|
186
|
+
-webkit-backdrop-filter: var(--glass-blur-pink-green) !important;
|
|
187
|
+
border: 1px solid rgba(255, 255, 255, 0.2) !important;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.glass-pink-green * {
|
|
191
|
+
color: #ffffff !important;
|
|
192
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { request } from '../../common/api/client';
|
|
2
|
+
|
|
3
|
+
export async function requestPasswordReset(email) {
|
|
4
|
+
return request('/users/request-password-reset', {
|
|
5
|
+
method: 'POST',
|
|
6
|
+
body: { email: String(email).trim() },
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function getResetStatus(email) {
|
|
11
|
+
return request(`/users/reset-status/${encodeURIComponent(email)}`, {
|
|
12
|
+
method: 'GET',
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function getPendingResets() {
|
|
17
|
+
return request('/users/pending-resets', {
|
|
18
|
+
method: 'GET',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function assignNewPassword(email, new_password) {
|
|
23
|
+
return request('/users/assign-new-password', {
|
|
24
|
+
method: 'POST',
|
|
25
|
+
body: {
|
|
26
|
+
email: String(email).trim(),
|
|
27
|
+
new_password: String(new_password).trim(),
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const api = {
|
|
33
|
+
requestPasswordReset,
|
|
34
|
+
getResetStatus,
|
|
35
|
+
getPendingResets,
|
|
36
|
+
assignNewPassword,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default api;
|