From 14cd2ff8a267a60e61e2426d9a2b5ce43c1d6da4 Mon Sep 17 00:00:00 2001 From: Abbytec Date: Mon, 8 Dec 2025 18:13:12 -0300 Subject: [PATCH 01/37] community starter pack --- .claude/parts/providers.md | 71 - .claude/parts/services.md | 55 - .claude/parts/ui-system.md | 90 -- .gitignore | 4 +- .mcp.json | 6 + .serena/memories/task_completion_checklist.md | 42 +- .serena/memories/uifederation_architecture.md | 76 ++ ARCHITECTURE.md | 2 +- CLAUDE.md | 155 +-- src/apps/public/00-adc-ui-library/README.md | 15 + src/apps/public/00-adc-ui-library/config.json | 13 + src/apps/public/00-adc-ui-library/index.ts | 8 + .../00-adc-ui-library/src/components.d.ts | 1169 +++++++++++++++++ .../adc-button-rounded/adc-button-rounded.tsx | 43 + .../atoms/adc-button/adc-button.tsx | 47 + .../atoms/adc-callout/adc-callout.tsx | 49 + .../atoms/adc-code-block/adc-code-block.tsx | 34 + .../atoms/adc-divider/adc-divider.tsx | 11 + .../adc-inline-tokens/adc-inline-tokens.tsx | 40 + .../components/atoms/adc-input/adc-input.tsx | 38 + .../atoms/adc-list-block/adc-list-block.tsx | 35 + .../atoms/adc-lp-badge/adc-lp-badge.tsx | 54 + .../components/atoms/adc-quote/adc-quote.tsx | 17 + .../adc-search-input/adc-search-input.tsx | 84 ++ .../atoms/adc-select/adc-select.tsx | 83 ++ .../atoms/adc-star-rating/adc-star-rating.tsx | 61 + .../atoms/adc-table-block/adc-table-block.tsx | 63 + .../components/atoms/adc-text/adc-text.tsx | 18 + .../adc-icon-community/adc-icon-community.css | 10 + .../adc-icon-community/adc-icon-community.tsx | 26 + .../adc-icon-learning/adc-icon-learning.css | 10 + .../adc-icon-learning/adc-icon-learning.tsx | 28 + .../adc-icon-left-arrow.css | 10 + .../adc-icon-left-arrow.tsx | 29 + .../icons/adc-icon-logout/adc-icon-logout.css | 10 + .../icons/adc-icon-logout/adc-icon-logout.tsx | 30 + .../icons/adc-icon-nitro/adc-icon-nitro.css | 10 + .../icons/adc-icon-nitro/adc-icon-nitro.tsx | 30 + .../adc-icon-opensource.css | 10 + .../adc-icon-opensource.tsx | 26 + .../icons/adc-icon-pencil/adc-icon-pencil.css | 10 + .../icons/adc-icon-pencil/adc-icon-pencil.tsx | 34 + .../icons/adc-icon-vip/adc-icon-vip.css | 10 + .../icons/adc-icon-vip/adc-icon-vip.tsx | 29 + .../adc-dropdown-menu/adc-dropdown-menu.tsx | 116 ++ .../adc-feature-card/adc-feature-card.tsx | 24 + .../adc-share-buttons/adc-share-buttons.tsx | 71 + .../adc-testimonial-card.tsx | 21 + .../adc-blocks-renderer.tsx | 149 +++ .../adc-blocks-renderer/code-highlight.css | 63 + .../adc-consent-banner/adc-consent-banner.tsx | 118 ++ .../adc-site-footer/adc-site-footer.tsx | 53 + .../adc-site-header/adc-site-header.tsx | 39 + .../src/global/accessibility.css | 108 ++ .../00-adc-ui-library/src/global/tailwind.css | 99 ++ .../00-adc-ui-library/stencil.config.ts | 26 + .../public/00-adc-ui-library/tsconfig.json | 20 + .../public/00-adc-ui-library/utils/router.ts | 101 ++ .../utils/tailwind-preset.js | 113 ++ src/apps/public/adc-layout/config.json | 22 + src/apps/public/adc-layout/i18n/en.js | 7 + src/apps/public/adc-layout/i18n/es.js | 7 + src/apps/public/adc-layout/index.html | 15 + src/apps/public/adc-layout/index.ts | 10 + src/apps/public/adc-layout/src/App.tsx | 102 ++ .../adc-layout/src/components/Shell.tsx | 95 ++ src/apps/public/adc-layout/src/main.tsx | 16 + .../public/adc-layout/src/styles/tailwind.css | 7 + src/apps/public/adc-layout/src/types.d.ts | 47 + src/apps/public/adc-layout/tsconfig.json | 14 + src/apps/public/community-home/config.json | 14 + src/apps/public/community-home/i18n/en.js | 9 + src/apps/public/community-home/i18n/es.js | 9 + src/apps/public/community-home/index.html | 15 + src/apps/public/community-home/index.ts | 10 + src/apps/public/community-home/src/App.tsx | 120 ++ src/apps/public/community-home/src/main.tsx | 16 + .../community-home/src/styles/tailwind.css | 7 + src/apps/public/community-home/src/types.d.ts | 47 + src/apps/public/community-home/tsconfig.json | 14 + .../test/00-web-ui-library-mobile/config.json | 1 - .../stencil.config.ts | 35 +- src/apps/test/00-web-ui-library/README.md | 13 + src/apps/test/00-web-ui-library/config.json | 1 - .../adc-stat-card/adc-stat-card.css | 4 + .../test/00-web-ui-library/stencil.config.ts | 35 +- src/apps/test/users-management/config.json | 3 +- src/apps/test/users-management/src/App.tsx | 2 - src/apps/test/users-management/src/main.tsx | 22 +- src/apps/test/web-config/config.json | 3 +- src/apps/test/web-config/src/App.vue | 5 +- src/apps/test/web-config/src/main.ts | 2 + src/apps/test/web-home-mobile/config.json | 3 +- src/apps/test/web-home-mobile/src/App.js | 2 - src/apps/test/web-home-mobile/src/main.js | 2 + src/apps/test/web-home/config.json | 3 +- src/apps/test/web-home/src/App.js | 3 - src/apps/test/web-home/src/main.js | 3 + src/apps/test/web-layout-mobile/config.json | 4 +- src/apps/test/web-layout-mobile/src/App.tsx | 1 - .../src/components/Shell.tsx | 1 - src/apps/test/web-layout-mobile/src/main.tsx | 19 +- .../test/web-layout-mobile/src/types.d.ts | 3 +- src/apps/test/web-layout/config.json | 4 +- src/apps/test/web-layout/src/App.tsx | 1 - .../test/web-layout/src/components/Shell.tsx | 1 - src/apps/test/web-layout/src/main.tsx | 24 +- src/apps/test/web-layout/src/types.d.ts | 3 +- src/interfaces/modules/IUIModule.d.ts | 8 +- src/kernel.ts | 204 ++- src/providers/http/express-server/README.md | 5 + src/providers/http/fastify-server/README.md | 13 + .../core/UIFederationService/README.md | 16 + .../core/UIFederationService/index.ts | 194 ++- .../strategies/rspack/base.ts | 15 +- .../strategies/standalone/stencil-strategy.ts | 187 ++- .../strategies/vite/base.ts | 4 +- .../core/UIFederationService/types.d.ts | 3 + .../utils/alias-generator.ts | 13 +- .../utils/file-operations.ts | 8 + .../utils/html-processor.ts | 4 +- temp-ui | 1 + 122 files changed, 4769 insertions(+), 528 deletions(-) delete mode 100644 .claude/parts/providers.md delete mode 100644 .claude/parts/services.md delete mode 100644 .claude/parts/ui-system.md create mode 100644 .serena/memories/uifederation_architecture.md create mode 100644 src/apps/public/00-adc-ui-library/README.md create mode 100644 src/apps/public/00-adc-ui-library/config.json create mode 100644 src/apps/public/00-adc-ui-library/index.ts create mode 100644 src/apps/public/00-adc-ui-library/src/components.d.ts create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-button-rounded/adc-button-rounded.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-button/adc-button.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-callout/adc-callout.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-code-block/adc-code-block.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-divider/adc-divider.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-inline-tokens/adc-inline-tokens.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-input/adc-input.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-list-block/adc-list-block.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-lp-badge/adc-lp-badge.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-quote/adc-quote.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-search-input/adc-search-input.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-select/adc-select.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-star-rating/adc-star-rating.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-table-block/adc-table-block.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/atoms/adc-text/adc-text.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-community/adc-icon-community.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-community/adc-icon-community.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-learning/adc-icon-learning.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-learning/adc-icon-learning.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-left-arrow/adc-icon-left-arrow.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-left-arrow/adc-icon-left-arrow.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-logout/adc-icon-logout.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-logout/adc-icon-logout.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-nitro/adc-icon-nitro.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-nitro/adc-icon-nitro.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-opensource/adc-icon-opensource.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-opensource/adc-icon-opensource.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-pencil/adc-icon-pencil.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-pencil/adc-icon-pencil.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-vip/adc-icon-vip.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-vip/adc-icon-vip.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/molecules/adc-dropdown-menu/adc-dropdown-menu.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/molecules/adc-feature-card/adc-feature-card.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/molecules/adc-share-buttons/adc-share-buttons.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/molecules/adc-testimonial-card/adc-testimonial-card.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/organisms/adc-blocks-renderer/adc-blocks-renderer.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/organisms/adc-blocks-renderer/code-highlight.css create mode 100644 src/apps/public/00-adc-ui-library/src/components/organisms/adc-consent-banner/adc-consent-banner.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/organisms/adc-site-footer/adc-site-footer.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/components/organisms/adc-site-header/adc-site-header.tsx create mode 100644 src/apps/public/00-adc-ui-library/src/global/accessibility.css create mode 100644 src/apps/public/00-adc-ui-library/src/global/tailwind.css create mode 100644 src/apps/public/00-adc-ui-library/stencil.config.ts create mode 100644 src/apps/public/00-adc-ui-library/tsconfig.json create mode 100644 src/apps/public/00-adc-ui-library/utils/router.ts create mode 100644 src/apps/public/00-adc-ui-library/utils/tailwind-preset.js create mode 100644 src/apps/public/adc-layout/config.json create mode 100644 src/apps/public/adc-layout/i18n/en.js create mode 100644 src/apps/public/adc-layout/i18n/es.js create mode 100644 src/apps/public/adc-layout/index.html create mode 100644 src/apps/public/adc-layout/index.ts create mode 100644 src/apps/public/adc-layout/src/App.tsx create mode 100644 src/apps/public/adc-layout/src/components/Shell.tsx create mode 100644 src/apps/public/adc-layout/src/main.tsx create mode 100644 src/apps/public/adc-layout/src/styles/tailwind.css create mode 100644 src/apps/public/adc-layout/src/types.d.ts create mode 100644 src/apps/public/adc-layout/tsconfig.json create mode 100644 src/apps/public/community-home/config.json create mode 100644 src/apps/public/community-home/i18n/en.js create mode 100644 src/apps/public/community-home/i18n/es.js create mode 100644 src/apps/public/community-home/index.html create mode 100644 src/apps/public/community-home/index.ts create mode 100644 src/apps/public/community-home/src/App.tsx create mode 100644 src/apps/public/community-home/src/main.tsx create mode 100644 src/apps/public/community-home/src/styles/tailwind.css create mode 100644 src/apps/public/community-home/src/types.d.ts create mode 100644 src/apps/public/community-home/tsconfig.json create mode 100644 src/apps/test/00-web-ui-library/README.md create mode 100644 src/providers/http/express-server/README.md create mode 100644 src/providers/http/fastify-server/README.md create mode 100644 src/services/core/UIFederationService/README.md create mode 120000 temp-ui diff --git a/.claude/parts/providers.md b/.claude/parts/providers.md deleted file mode 100644 index f3b788c6..00000000 --- a/.claude/parts/providers.md +++ /dev/null @@ -1,71 +0,0 @@ -# Providers Reference - -## Categorías - -### Files (`src/providers/files/`) - -- Acceso a filesystem -- Lectura/escritura de archivos - -### HTTP (`src/providers/http/`) - -- **express-server**: Servidor HTTP Express (usado en desarrollo) -- **fastify-server**: Servidor HTTP Fastify con host-based routing (usado en producción) - -### Object (`src/providers/object/`) - -- Almacenamiento de objetos -- Serialización - -## HTTP Providers - -### express-server - -Servidor Express tradicional. Usado automáticamente en modo desarrollo (`npm run dev`). - -### fastify-server - -Servidor Fastify con soporte para virtual hosts. Usado automáticamente en producción (`npm run start` y `npm run start:prodtests`). - -**Características:** - -- Host-based routing (subdominios y dominios) -- Mayor rendimiento que Express -- Prioridad automática (hosts específicos > comodines) -- SPA fallback integrado - -**Puertos:** - -- `npm run start` → puerto 80 -- `npm run start:prodtests` → puerto 3000 -- `npm run dev` → puerto 3000 (con dev servers en puertos separados) - -## Crear nuevo Provider - -```bash -npm run create:provider -``` - -## Uso en Apps - -Declarar en `config.json`: - -```json -{ - "providers": [ - { - "name": "mongo", - "global": true, - "custom": { - "uri": "mongodb://..." - } - } - ] -} -``` - -## Obtener en código - -```typescript -const storage = kernel.getProvider(STORAGE_PROVIDER); -``` diff --git a/.claude/parts/services.md b/.claude/parts/services.md deleted file mode 100644 index 728f5a6d..00000000 --- a/.claude/parts/services.md +++ /dev/null @@ -1,55 +0,0 @@ -# Services Reference - -## Core Services (Modo Kernel) - -Servicios que se cargan automáticamente con `kernelMode: true`. - -### ExecutionManagerService -- Gestión de workers para carga distribuida -- Decorador `@Distributed` para métodos pesados -- Monitoreo de CPU/memoria - -### IdentityManagerService -- Gestión de usuarios, roles y grupos -- 8 roles predefinidos: SYSTEM, Admin, Network Manager, Security Manager, Data Manager, App Manager, Config Manager, User -- Hash PBKDF2 (100k iteraciones) -- Fallback a memoria si MongoDB no disponible - -### LangManagerService -- Internacionalización (i18n) -- Archivos en `/{app}/i18n/{locale}.js` -- Interpolación `{{param}}` -- Endpoints: `/api/i18n/:namespace`, `/api/i18n?namespaces=...` - -### LogManagerService -- Logging centralizado del kernel - -### UIFederationService -- Build y servido de módulos UI -- Soporta: Stencil, React, Vue, Vite, Astro -- Module Federation con Rspack -- Namespaces para múltiples UI libraries -- Service Worker dinámico - -## Data Services - -### Ubicación: `src/services/data/` - -Servicios de acceso a datos (CRUD, etc.) - -## Crear nuevo Service - -```bash -npm run create:service -``` - -## Configuración de Service - -Archivo `config.json` en el directorio del service: - -```json -{ - "kernelMode": false, - "dependencies": [] -} -``` diff --git a/.claude/parts/ui-system.md b/.claude/parts/ui-system.md deleted file mode 100644 index 4858b4a2..00000000 --- a/.claude/parts/ui-system.md +++ /dev/null @@ -1,90 +0,0 @@ -# UI System Reference - -## UI Libraries (Stencil Web Components) - -### 00-web-ui-library - -- Componentes desktop: ``, ``, ``, `` -- Framework-agnostic (Web Components) - -### 00-web-ui-library-mobile - -- Componentes móviles - -## Uso - -```typescript -import '@ui-library/loader'; - -// JSX -Click - -// HTML -Click -``` - -## UIFederationService Config - -```json -{ - "uiModule": { - "name": "layout", - "uiNamespace": "default", - "framework": "react", - "devPort": 3014, - "serviceWorker": true, - "i18n": true, - "hosting": { - "hosts": [{ "domain": "local.com", "subdomains": ["cloud", "users", "*"] }] - } - } -} -``` - -## Hosting (Producción) - -En producción, las apps se sirven por dominio/subdominio en un solo puerto: - -```json -"hosting": { - "hosts": [{ "domain": "local.com", "subdomains": ["cloud", "users", "*"] }] -} -``` - -**Opciones:** -- `hosts`: Lista de dominios con subdominios -- `subdomains`: Lista simple (usa dominio por defecto `local.com`) -- `domains`: Dominios completos - -**Prioridad:** hosts específicos > comodines (`*`) - -## Namespaces - -- Permiten múltiples UI libraries sin colisiones -- Cada namespace tiene su import map: `/:namespace/importmap.json` -- `default` se usa cuando no se especifica - -## i18n - -Archivos en `/{app}/i18n/{locale}.js`: - -```javascript -export default { - title: "Estadísticas", - welcome: "Bienvenido, {{name}}", -}; -``` - -Cliente: - -```javascript -t("welcome", { name: "Juan" }); -setLocale("es"); -getLocale(); -``` - -## Endpoints - -- `GET /api/ui/namespaces` -- `GET /:namespace/importmap.json` -- `GET /api/i18n/:namespace?locale=es` diff --git a/.gitignore b/.gitignore index 3ccbac34..32c9f4fe 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,6 @@ npm-debug.log* .env.development apps/private -**.pyc \ No newline at end of file +**.pyc + +chroma_db_codebase \ No newline at end of file diff --git a/.mcp.json b/.mcp.json index 26ce7e1e..0f360716 100644 --- a/.mcp.json +++ b/.mcp.json @@ -7,6 +7,12 @@ "command": "/home/abby/.local/bin/serena-mcp-server", "args": ["--context", "claude-code", "--project", "/home/abby/Escritorio/proyectos/personales/ADC-platform"], "env": {} + }, + "search_code_vector": { + "type": "stdio", + "command": "/home/abby/Escritorio/scripting/ai/rag/venv/bin/python", + "args": ["/home/abby/Escritorio/scripting/ai/rag/rag_server.py"], + "env": {} } }, "enabledMcpjsonServers": [], diff --git a/.serena/memories/task_completion_checklist.md b/.serena/memories/task_completion_checklist.md index 0a6f34d9..da74003a 100644 --- a/.serena/memories/task_completion_checklist.md +++ b/.serena/memories/task_completion_checklist.md @@ -3,52 +3,30 @@ ## Before Considering a Task Complete ### 1. Run TypeScript Check - ```bash npm run typecheck ``` -This runs TypeScript compiler + ts-prune for dead code detection. - ### 2. Run Linting - ```bash npm run lint ``` - Must pass with zero warnings (`--max-warnings 0`). -### 3. Fix Linting Issues (if any) - -```bash -npm run lint:fix -``` - -### 4. Test in Development Mode - +### 3. Test in Development Mode ```bash npm run dev ``` -Verify hot reload works and no runtime errors. - -### 5. Test in Production Mode (if applicable) - -```bash -npm run start:prodtests -``` - -Verify production build works correctly. - -## Critical Documentation Rule - -From CLAUDE.md: +## Documentation Updates -> **Si durante una tarea modificas la estructura de carpetas, añades un nuevo servicio/app/provider, o cambias una decisión arquitectónica clave, DEBES actualizar el archivo `CLAUDE.md` y/o los archivos en `.claude/parts/` como parte de tus cambios.** +When modifying a module: +- Update its `README.md` if behavior changes (max 15 lines) +- `config.json` documents dependencies - update if needed -## What to Update When +When adding new modules: +- Create `README.md` in the module directory (ultra-brief) -- New app/service/provider/utility → Update relevant `.claude/parts/*.md` -- Architecture changes → Update `ARCHITECTURE.md` -- New commands → Update `CLAUDE.md` Commands table -- New concepts → Update `CLAUDE.md` Key Concepts table +Architecture changes: +- Update Serena memories for internal details +- Update `CLAUDE.md` only for fundamental concepts diff --git a/.serena/memories/uifederation_architecture.md b/.serena/memories/uifederation_architecture.md new file mode 100644 index 00000000..d9bfa9f0 --- /dev/null +++ b/.serena/memories/uifederation_architecture.md @@ -0,0 +1,76 @@ +# UIFederationService Architecture + +## Core Components + +### 1. Module Loading (kernel.ts) +- `#buildAppLoadQueue()`: Orders apps by dependencies using `uiDependencies` from config.json +- UI libraries (Stencil) are detected by `framework === "stencil" && exports` and loaded first +- Apps wait for their dependencies before being added to the queue +- **Current Issue**: Loading is sequential, not parallel + +### 2. UIFederationService (index.ts) +- Manages UI module registration, building, and serving +- Uses namespace-based organization: `Map>` +- Supports both development (Express) and production (Fastify with host-based routing) +- Key methods: + - `registerUIModule()`: Registers and builds a UI module + - `#waitForUILibraryBuild()`: Waits for Stencil UI library before building other modules + - `#regenerateLayoutConfigsForNamespace()`: Restarts host dev servers when new remotes register + +### 3. Build Strategies +- **Stencil (stencil-strategy.ts)**: Web components, outputs loader + custom-elements +- **Rspack (rspack/base.ts)**: React/Vue with Module Federation +- **Vite (vite/base.ts)**: React/Vue with import maps + +### 4. Module Federation (Rspack) +- `detectRemotes()`: Scans registered modules for remotes (non-layout, with devPort, same namespace) +- Hosts get `remotes: {...}` config pointing to remote mf-manifest.json URLs +- Remotes expose `./App` component + +## Key Concepts + +### uiDependencies +Array in config.json that declares which modules must load before this one: +```json +{ + "uiModule": { + "uiDependencies": ["home", "web-ui-library"] + } +} +``` + +### Namespace Isolation +Modules in different namespaces are isolated: +- `uiNamespace: "default"` (implicit if not set) +- `uiNamespace: "adc-platform"` (explicit) + +### Host vs Remote +- `isHost: true`: Main app that loads remotes +- `isRemote: true`: Module exposed via Module Federation + +## Auto-Init System (2025-12) + +### How it works +1. `stencil-strategy.ts` generates `init.js` + `styles.css` in output dir +2. `init.js` auto-executes `defineCustomElements(window)` on import +3. `alias-generator.ts` maps: + - `@ui-library` → `init.js` (auto-registers components) + - `@ui-library/styles` → `styles.css` (CSS base) + - `@ui-library/utils/*` → utilities from source + +### Usage in apps +```typescript +import "@ui-library"; // Auto-registers Web Components +import "@ui-library/styles"; // Loads CSS base +``` + +## Load Order +1. **Level 0**: UI Libraries (Stencil) - parallel +2. **Level 1+**: Apps by dependency level - parallel within level +3. **Last Level**: Hosts - after all remotes + +## Documentation Pattern +- Each module has its own `README.md` (max 15 lines) +- `config.json` documents dependencies +- NO centralized redundant docs +- Serena memories for architecture internals \ No newline at end of file diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 53308546..95c3f915 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -293,7 +293,7 @@ El proyecto incluye una librería de componentes UI (`00-web-ui-library`) constr ```typescript // En cualquier app React/Vue/etc: -import '@ui-library/loader'; +import "@ui-library"; // Uso en JSX/TSX: diff --git a/CLAUDE.md b/CLAUDE.md index 4bc33aab..e6be18fc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,123 +1,42 @@ -# ADC Platform - Context Map +# ADC Platform -## Project Overview +Kernel modular con carga dinámica de apps, services, providers y utilities. +Utilizar patrones KISS, DRY, SOLID y YAGNI. -Kernel modular que carga dinámicamente apps, services, providers y utilities. Soporta versionado semántico, hot reload, y múltiples lenguajes (TS/Python via IPC). - -## Structure Map +## Estructura ``` src/ -├── index.ts # Entry point -├── kernel.ts # Orquestador central (~38K líneas) -├── apps/ -│ ├── BaseApp.ts # Clase base para apps -│ ├── community/ # Apps de la comunidad -│ ├── core/ # Apps del núcleo -│ ├── private/ # Apps privadas -│ └── test/ # Apps de desarrollo/testing -│ ├── 00-web-ui-library/ # UI Components (Stencil) -│ ├── 00-web-ui-library-mobile/ -│ ├── web-layout/ # Layout principal (React) -│ ├── web-layout-mobile/ -│ ├── web-home/ # Home page -│ ├── web-home-mobile/ -│ ├── web-config/ # Configuración UI -│ ├── users-management/ # Gestión usuarios -│ ├── user-profile-file/ # Profile (file storage) -│ └── user-profile-mongo/ # Profile (MongoDB) -├── services/ -│ ├── BaseService.ts -│ ├── core/ # Servicios modo kernel -│ │ ├── ExecutionManagerService/ # Workers/distribución -│ │ ├── IdentityManagerService/ # Auth/roles -│ │ ├── LangManagerService/ # i18n -│ │ ├── LogManagerService/ # Logging -│ │ └── UIFederationService/ # Module Federation -│ └── data/ # Servicios de datos -├── providers/ -│ ├── BaseProvider.ts -│ ├── files/ # Filesystem -│ ├── http/ # HTTP servers -│ │ ├── express-server/ # Express (desarrollo) -│ │ └── fastify-server/ # Fastify + host routing (producción) -│ └── object/ # Object storage -├── utilities/ -│ ├── BaseUtility.ts -│ └── adapters/ # Adaptadores -├── utils/ # Helpers internos -│ ├── decorators/ -│ ├── ipc/ # Inter-process communication -│ ├── loaders/ # Module loaders -│ ├── logger/ -│ └── react/ -└── interfaces/ # TypeScript interfaces - ├── behaviours/ - ├── interop/ - ├── modules/ - └── utils/ +├── kernel.ts # Orquestador central +├── apps/ # Aplicaciones (cada una con README.md) +│ ├── public/ # Apps públicas (adc-platform namespace) +│ └── test/ # Apps de desarrollo (default namespace) +├── services/core/ # Servicios kernel (cada uno con README.md) +├── providers/ # Proveedores (cada uno con README.md) +└── utils/ # Helpers internos ``` ## Commands -| Command | Description | -| ------------------------- | -------------------------------------- | -| `npm run start` | Producción (sin tests) | -| `npm dev` | Dev mode (hot reload) | +| Command | Description | +| ----------------- | ------------------------------ | +| `npm run dev` | Desarrollo (hot reload) | | `npm run start:prodtests` | Simular producción + tests habilitados | -| `npm run typecheck` | TypeScript + ts-prune | -| `npm run lint` | ESLint | -| `npm run lint:fix` | ESLint autofix | +| `npm run start` | Producción (puerto 80) | +| `npm run typecheck` | TypeScript check | +| `npm run lint` | ESLint | | `npm run cleanup` | Limpiar procesos | -| `npm run create:app` | Scaffold nueva app | -| `npm run create:service` | Scaffold nuevo service | -| `npm run create:provider` | Scaffold nuevo provider | -| `npm run create:utility` | Scaffold nueva utility | - -## Workflow - Context Economy Protocol - -**ANTES de codificar cualquier módulo:** - -1. **NO leas todo el código al inicio.** Usa este mapa para orientarte. -2. **Busca documentación local primero:** - - `{module}/README.md` si existe - - `{module}/config.json` para dependencias - - `.claude/parts/*.md` para detalles específicos -3. **Solo lee el código que vas a modificar.** -4. **Para detalles de arquitectura global:** consulta `ARCHITECTURE.md` -**Referencias rápidas:** +## Key Concepts -- Services: `.claude/parts/services.md` -- Providers: `.claude/parts/providers.md` -- UI System: `.claude/parts/ui-system.md` - -## Key Concepts (Quick Reference) - -| Concepto | Descripción | -| ------------------ | ---------------------------------------------- | -| `kernelMode: true` | Service se carga con el kernel (global) | -| `config.json` | Declara dependencias de una app/service | -| `config-*.json` | Múltiples instancias de una app | +| Concepto | Descripción | +| -------- | ----------- | +| `config.json` | Dependencias y configuración del módulo | +| `uiDependencies` | Apps UI que deben cargarse antes | +| `@ui-library` | Auto-registra Web Components al importarse | +| `@ui-library/styles` | CSS base de la UI Library | +| `uiNamespace` | Aísla UI libraries (ej: `adc-platform`, `default`) | | `@Distributed` | Decorador para ejecutar en worker | -| Namespace UI | Múltiples UI libraries sin colisiones | -| Workspaces | Cada módulo es un npm package aislado | -| `hosting` | Config de dominios/subdominios para producción | - -## Production Hosting - -En producción, las apps UI se sirven mediante **virtual hosts** (dominios/subdominios). - -**Providers HTTP:** - -- `express-server`: usado en desarrollo (`npm run dev`) -- `fastify-server`: usado en producción con host-based routing - -**Puertos:** - -- `npm run start` → puerto 80 (producción real) -- `npm run start:prodtests` → puerto 3000 (tests de producción) -- `npm run dev` → puerto 3000 + dev servers en puertos separados **Configuración de hosting en `config.json`:** @@ -129,19 +48,19 @@ En producción, las apps UI se sirven mediante **virtual hosts** (dominios/subdo } } } -``` - -## Code Style -- **KISS, DRY, SOLID, YAGNI** -- Priorizar legibilidad sobre cleverness -- No documentar lo obvio -- TypeScript strict mode -- ESLint sin warnings (`--max-warnings 0`) -- Un `config.json` por módulo para dependencias +## UI Apps -## CRITICAL: Self-Maintenance Rule +```typescript +// main.tsx - Patrón de imports +import "@ui-library"; // Auto-registra Web Components +import "@ui-library/styles"; // CSS base (variables, tipografía, etc.) +import "./styles/tailwind.css"; // Extensiones locales (solo Tailwind + extensiones propias) +``` -> **Si durante una tarea modificas la estructura de carpetas, añades un nuevo servicio/app/provider, o cambias una decisión arquitectónica clave, DEBES actualizar este archivo `CLAUDE.md` y/o los archivos en `.claude/parts/` como parte de tus cambios.** +## Documentation Rules -Esta regla es **obligatoria** para mantener la economía de contexto. +- Cada módulo tiene su propio `README.md` (máx 15 líneas) +- `config.json` documenta dependencias +- NO crear documentación centralizada redundante ni documentar lo obvio +- Al modificar un módulo, actualizar SU readme si es necesario diff --git a/src/apps/public/00-adc-ui-library/README.md b/src/apps/public/00-adc-ui-library/README.md new file mode 100644 index 00000000..1f0cf971 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/README.md @@ -0,0 +1,15 @@ +# ADC UI Library + +Web Components (Stencil) para el namespace `adc-platform`. + +## Uso +```typescript +import "@ui-library"; // Auto-registra componentes +import "@ui-library/styles"; // CSS base (variables, tipografía) +``` + +## Componentes +``, ``, ``, ``, etc. + +## CSS Variables +Definidas en `src/global/tailwind.css`: `--c-primary`, `--c-accent`, `--c-text`, etc. diff --git a/src/apps/public/00-adc-ui-library/config.json b/src/apps/public/00-adc-ui-library/config.json new file mode 100644 index 00000000..3f72cc0d --- /dev/null +++ b/src/apps/public/00-adc-ui-library/config.json @@ -0,0 +1,13 @@ +{ + "uiModule": { + "name": "adc-ui-library", + "uiNamespace": "adc-platform", + "framework": "stencil", + "outputDir": "dist-ui", + "exports": { + "loader": "./loader", + "utils": "./utils", + "tailwind-preset": "./utils/tailwind-preset.js" + } + } +} diff --git a/src/apps/public/00-adc-ui-library/index.ts b/src/apps/public/00-adc-ui-library/index.ts new file mode 100644 index 00000000..86b435c1 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/index.ts @@ -0,0 +1,8 @@ +import { BaseApp } from "../../BaseApp.ts"; + +export default class AdcUILibraryApp extends BaseApp { + async run(): Promise { + this.logger.logInfo(`${this.name} - ADC UI Library disponible`); + this.logger.logOk(`${this.name} - Componentes Stencil listos para ser consumidos`); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components.d.ts b/src/apps/public/00-adc-ui-library/src/components.d.ts new file mode 100644 index 00000000..7d970eb5 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components.d.ts @@ -0,0 +1,1169 @@ +/* eslint-disable */ +/* tslint:disable */ +/** + * This is an autogenerated file created by the Stencil compiler. + * It contains typing information for all components that exist in this project. + */ +import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; +import { Block } from "./components/organisms/adc-blocks-renderer/adc-blocks-renderer"; +import { DropdownMenuItem } from "./components/molecules/adc-dropdown-menu/adc-dropdown-menu"; +import { InlineToken } from "./components/atoms/adc-inline-tokens/adc-inline-tokens"; +import { SelectOption } from "./components/atoms/adc-select/adc-select"; +export { Block } from "./components/organisms/adc-blocks-renderer/adc-blocks-renderer"; +export { DropdownMenuItem } from "./components/molecules/adc-dropdown-menu/adc-dropdown-menu"; +export { InlineToken } from "./components/atoms/adc-inline-tokens/adc-inline-tokens"; +export { SelectOption } from "./components/atoms/adc-select/adc-select"; +export namespace Components { + interface AdcBlocksRenderer { + /** + * @default [] + */ + "blocks": Block[]; + } + interface AdcButton { + "ariaLabel"?: string; + "href"?: string; + /** + * @default "button" + */ + "type": "button" | "submit" | "reset"; + } + interface AdcButtonRounded { + "ariaLabel"?: string; + "href"?: string; + /** + * @default "button" + */ + "type": "button" | "submit" | "reset"; + } + interface AdcCallout { + /** + * @default "note" + */ + "role": "note" | "status" | "alert"; + /** + * @default "info" + */ + "tone": "info" | "warning" | "success" | "error"; + } + interface AdcCodeBlock { + "ariaLabel"?: string; + /** + * @default "" + */ + "content": string; + "language"?: string; + } + interface AdcConsentBanner { + /** + * @default "/cookies" + */ + "cookiesHref": string; + /** + * @default "/privacy" + */ + "privacyHref": string; + /** + * @default false + */ + "restrictedRegion": boolean; + /** + * @default false + */ + "visible": boolean; + } + interface AdcDivider { + } + interface AdcDropdownMenu { + /** + * @default "left" + */ + "alignState": "left" | "right"; + /** + * @default [] + */ + "items": DropdownMenuItem[]; + /** + * @default true + */ + "openOnHover": boolean; + } + interface AdcFeatureCard { + /** + * @default true + */ + "staticRender": boolean; + /** + * @default "" + */ + "title": string; + } + interface AdcIconCommunity { + /** + * @default "2rem" + */ + "size": string; + } + interface AdcIconLearning { + /** + * @default "2rem" + */ + "size": string; + } + interface AdcIconLeftArrow { + /** + * @default "1rem" + */ + "size": string; + } + interface AdcIconLogout { + /** + * @default "1rem" + */ + "size": string; + } + interface AdcIconNitro { + /** + * @default "1rem" + */ + "size": string; + } + interface AdcIconOpensource { + /** + * @default "2rem" + */ + "size": string; + } + interface AdcIconPencil { + /** + * @default "1rem" + */ + "size": string; + } + interface AdcIconVip { + /** + * @default "1rem" + */ + "size": string; + } + interface AdcInlineTokens { + /** + * @default "" + */ + "fallback": string; + /** + * @default [] + */ + "tokens": InlineToken[]; + } + interface AdcInput { + /** + * @default "" + */ + "ariaLabel"?: string; + /** + * @default "off" + */ + "autocomplete"?: string; + /** + * @default "" + */ + "inputId"?: string; + /** + * @default "" + */ + "name"?: string; + /** + * @default "" + */ + "placeholder"?: string; + /** + * @default "text" + */ + "type"?: string; + /** + * @default "" + */ + "value": string; + } + interface AdcListBlock { + "ariaLabel"?: string; + /** + * @default [] + */ + "items": string[]; + /** + * @default false + */ + "ordered": boolean; + "start"?: number; + } + interface AdcLpBadge { + "as"?: "button" | "span"; + /** + * @default "" + */ + "color": string; + "slug"?: string; + /** + * @default "" + */ + "title": string; + } + interface AdcQuote { + /** + * @default true + */ + "staticRender": boolean; + } + interface AdcSearchInput { + /** + * @default "" + */ + "ariaLabel"?: string; + /** + * @default "off" + */ + "autocomplete"?: string; + /** + * @default 300 + */ + "debounce": number; + /** + * @default "" + */ + "inputId"?: string; + /** + * @default "" + */ + "name"?: string; + /** + * @default "" + */ + "placeholder": string; + /** + * @default "text" + */ + "type"?: string; + /** + * @default "" + */ + "value": string; + } + interface AdcSelect { + /** + * @default [] + */ + "options": SelectOption[]; + /** + * @default "Seleccione" + */ + "placeholder": string; + /** + * @default "" + */ + "value": string; + } + interface AdcShareButtons { + /** + * @default "" + */ + "description": string; + /** + * @default "" + */ + "title": string; + /** + * @default "" + */ + "url": string; + } + interface AdcSiteFooter { + /** + * @default "" + */ + "brandName": string; + /** + * @default "" + */ + "brandSlogan": string; + /** + * @default "" + */ + "creatorHref": string; + /** + * @default "" + */ + "creatorName": string; + } + interface AdcSiteHeader { + /** + * @default "/" + */ + "homeHref": string; + /** + * @default "" + */ + "logoAlt": string; + /** + * @default "" + */ + "logoSrc": string; + } + interface AdcStarRating { + "average"?: number | null; + /** + * @default false + */ + "canRate": boolean; + "count"?: number | null; + "myRating"?: number | null; + /** + * @default false + */ + "pending": boolean; + } + interface AdcTableBlock { + "caption"?: string; + "columnAlign"?: Array<"left" | "center" | "right">; + /** + * @default [] + */ + "header": string[]; + /** + * @default false + */ + "rowHeaders": boolean; + /** + * @default [] + */ + "rows": string[][]; + } + interface AdcTestimonialCard { + /** + * @default "" + */ + "author": string; + /** + * @default true + */ + "staticRender": boolean; + } + interface AdcText { + /** + * @default true + */ + "contain": boolean; + /** + * @default true + */ + "staticRender": boolean; + } +} +export interface AdcButtonCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcButtonElement; +} +export interface AdcButtonRoundedCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcButtonRoundedElement; +} +export interface AdcConsentBannerCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcConsentBannerElement; +} +export interface AdcDropdownMenuCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcDropdownMenuElement; +} +export interface AdcInputCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcInputElement; +} +export interface AdcLpBadgeCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcLpBadgeElement; +} +export interface AdcSearchInputCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcSearchInputElement; +} +export interface AdcSelectCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcSelectElement; +} +export interface AdcSiteFooterCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcSiteFooterElement; +} +export interface AdcStarRatingCustomEvent extends CustomEvent { + detail: T; + target: HTMLAdcStarRatingElement; +} +declare global { + interface HTMLAdcBlocksRendererElement extends Components.AdcBlocksRenderer, HTMLStencilElement { + } + var HTMLAdcBlocksRendererElement: { + prototype: HTMLAdcBlocksRendererElement; + new (): HTMLAdcBlocksRendererElement; + }; + interface HTMLAdcButtonElementEventMap { + "adcClick": MouseEvent; + } + interface HTMLAdcButtonElement extends Components.AdcButton, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcButtonElement, ev: AdcButtonCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcButtonElement, ev: AdcButtonCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcButtonElement: { + prototype: HTMLAdcButtonElement; + new (): HTMLAdcButtonElement; + }; + interface HTMLAdcButtonRoundedElementEventMap { + "adcClick": MouseEvent; + } + interface HTMLAdcButtonRoundedElement extends Components.AdcButtonRounded, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcButtonRoundedElement, ev: AdcButtonRoundedCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcButtonRoundedElement, ev: AdcButtonRoundedCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcButtonRoundedElement: { + prototype: HTMLAdcButtonRoundedElement; + new (): HTMLAdcButtonRoundedElement; + }; + interface HTMLAdcCalloutElement extends Components.AdcCallout, HTMLStencilElement { + } + var HTMLAdcCalloutElement: { + prototype: HTMLAdcCalloutElement; + new (): HTMLAdcCalloutElement; + }; + interface HTMLAdcCodeBlockElement extends Components.AdcCodeBlock, HTMLStencilElement { + } + var HTMLAdcCodeBlockElement: { + prototype: HTMLAdcCodeBlockElement; + new (): HTMLAdcCodeBlockElement; + }; + interface HTMLAdcConsentBannerElementEventMap { + "adcAcceptAll": void; + "adcAcceptAnalytics": void; + "adcDeclineAll": void; + "adcDeclineAnalytics": void; + "adcAcknowledge": void; + } + interface HTMLAdcConsentBannerElement extends Components.AdcConsentBanner, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcConsentBannerElement, ev: AdcConsentBannerCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcConsentBannerElement, ev: AdcConsentBannerCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcConsentBannerElement: { + prototype: HTMLAdcConsentBannerElement; + new (): HTMLAdcConsentBannerElement; + }; + interface HTMLAdcDividerElement extends Components.AdcDivider, HTMLStencilElement { + } + var HTMLAdcDividerElement: { + prototype: HTMLAdcDividerElement; + new (): HTMLAdcDividerElement; + }; + interface HTMLAdcDropdownMenuElementEventMap { + "adcItemClick": DropdownMenuItem; + } + interface HTMLAdcDropdownMenuElement extends Components.AdcDropdownMenu, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcDropdownMenuElement, ev: AdcDropdownMenuCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcDropdownMenuElement, ev: AdcDropdownMenuCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcDropdownMenuElement: { + prototype: HTMLAdcDropdownMenuElement; + new (): HTMLAdcDropdownMenuElement; + }; + interface HTMLAdcFeatureCardElement extends Components.AdcFeatureCard, HTMLStencilElement { + } + var HTMLAdcFeatureCardElement: { + prototype: HTMLAdcFeatureCardElement; + new (): HTMLAdcFeatureCardElement; + }; + interface HTMLAdcIconCommunityElement extends Components.AdcIconCommunity, HTMLStencilElement { + } + var HTMLAdcIconCommunityElement: { + prototype: HTMLAdcIconCommunityElement; + new (): HTMLAdcIconCommunityElement; + }; + interface HTMLAdcIconLearningElement extends Components.AdcIconLearning, HTMLStencilElement { + } + var HTMLAdcIconLearningElement: { + prototype: HTMLAdcIconLearningElement; + new (): HTMLAdcIconLearningElement; + }; + interface HTMLAdcIconLeftArrowElement extends Components.AdcIconLeftArrow, HTMLStencilElement { + } + var HTMLAdcIconLeftArrowElement: { + prototype: HTMLAdcIconLeftArrowElement; + new (): HTMLAdcIconLeftArrowElement; + }; + interface HTMLAdcIconLogoutElement extends Components.AdcIconLogout, HTMLStencilElement { + } + var HTMLAdcIconLogoutElement: { + prototype: HTMLAdcIconLogoutElement; + new (): HTMLAdcIconLogoutElement; + }; + interface HTMLAdcIconNitroElement extends Components.AdcIconNitro, HTMLStencilElement { + } + var HTMLAdcIconNitroElement: { + prototype: HTMLAdcIconNitroElement; + new (): HTMLAdcIconNitroElement; + }; + interface HTMLAdcIconOpensourceElement extends Components.AdcIconOpensource, HTMLStencilElement { + } + var HTMLAdcIconOpensourceElement: { + prototype: HTMLAdcIconOpensourceElement; + new (): HTMLAdcIconOpensourceElement; + }; + interface HTMLAdcIconPencilElement extends Components.AdcIconPencil, HTMLStencilElement { + } + var HTMLAdcIconPencilElement: { + prototype: HTMLAdcIconPencilElement; + new (): HTMLAdcIconPencilElement; + }; + interface HTMLAdcIconVipElement extends Components.AdcIconVip, HTMLStencilElement { + } + var HTMLAdcIconVipElement: { + prototype: HTMLAdcIconVipElement; + new (): HTMLAdcIconVipElement; + }; + interface HTMLAdcInlineTokensElement extends Components.AdcInlineTokens, HTMLStencilElement { + } + var HTMLAdcInlineTokensElement: { + prototype: HTMLAdcInlineTokensElement; + new (): HTMLAdcInlineTokensElement; + }; + interface HTMLAdcInputElementEventMap { + "adcInput": string; + } + interface HTMLAdcInputElement extends Components.AdcInput, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcInputElement, ev: AdcInputCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcInputElement, ev: AdcInputCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcInputElement: { + prototype: HTMLAdcInputElement; + new (): HTMLAdcInputElement; + }; + interface HTMLAdcListBlockElement extends Components.AdcListBlock, HTMLStencilElement { + } + var HTMLAdcListBlockElement: { + prototype: HTMLAdcListBlockElement; + new (): HTMLAdcListBlockElement; + }; + interface HTMLAdcLpBadgeElementEventMap { + "adcClick": void; + } + interface HTMLAdcLpBadgeElement extends Components.AdcLpBadge, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcLpBadgeElement, ev: AdcLpBadgeCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcLpBadgeElement, ev: AdcLpBadgeCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcLpBadgeElement: { + prototype: HTMLAdcLpBadgeElement; + new (): HTMLAdcLpBadgeElement; + }; + interface HTMLAdcQuoteElement extends Components.AdcQuote, HTMLStencilElement { + } + var HTMLAdcQuoteElement: { + prototype: HTMLAdcQuoteElement; + new (): HTMLAdcQuoteElement; + }; + interface HTMLAdcSearchInputElementEventMap { + "adcInput": string; + } + interface HTMLAdcSearchInputElement extends Components.AdcSearchInput, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcSearchInputElement, ev: AdcSearchInputCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcSearchInputElement, ev: AdcSearchInputCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcSearchInputElement: { + prototype: HTMLAdcSearchInputElement; + new (): HTMLAdcSearchInputElement; + }; + interface HTMLAdcSelectElementEventMap { + "adcChange": string; + } + interface HTMLAdcSelectElement extends Components.AdcSelect, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcSelectElement, ev: AdcSelectCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcSelectElement, ev: AdcSelectCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcSelectElement: { + prototype: HTMLAdcSelectElement; + new (): HTMLAdcSelectElement; + }; + interface HTMLAdcShareButtonsElement extends Components.AdcShareButtons, HTMLStencilElement { + } + var HTMLAdcShareButtonsElement: { + prototype: HTMLAdcShareButtonsElement; + new (): HTMLAdcShareButtonsElement; + }; + interface HTMLAdcSiteFooterElementEventMap { + "adcOpenPrivacyPreferences": void; + } + interface HTMLAdcSiteFooterElement extends Components.AdcSiteFooter, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcSiteFooterElement, ev: AdcSiteFooterCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcSiteFooterElement, ev: AdcSiteFooterCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcSiteFooterElement: { + prototype: HTMLAdcSiteFooterElement; + new (): HTMLAdcSiteFooterElement; + }; + interface HTMLAdcSiteHeaderElement extends Components.AdcSiteHeader, HTMLStencilElement { + } + var HTMLAdcSiteHeaderElement: { + prototype: HTMLAdcSiteHeaderElement; + new (): HTMLAdcSiteHeaderElement; + }; + interface HTMLAdcStarRatingElementEventMap { + "adcRate": number; + } + interface HTMLAdcStarRatingElement extends Components.AdcStarRating, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAdcStarRatingElement, ev: AdcStarRatingCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAdcStarRatingElement, ev: AdcStarRatingCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAdcStarRatingElement: { + prototype: HTMLAdcStarRatingElement; + new (): HTMLAdcStarRatingElement; + }; + interface HTMLAdcTableBlockElement extends Components.AdcTableBlock, HTMLStencilElement { + } + var HTMLAdcTableBlockElement: { + prototype: HTMLAdcTableBlockElement; + new (): HTMLAdcTableBlockElement; + }; + interface HTMLAdcTestimonialCardElement extends Components.AdcTestimonialCard, HTMLStencilElement { + } + var HTMLAdcTestimonialCardElement: { + prototype: HTMLAdcTestimonialCardElement; + new (): HTMLAdcTestimonialCardElement; + }; + interface HTMLAdcTextElement extends Components.AdcText, HTMLStencilElement { + } + var HTMLAdcTextElement: { + prototype: HTMLAdcTextElement; + new (): HTMLAdcTextElement; + }; + interface HTMLElementTagNameMap { + "adc-blocks-renderer": HTMLAdcBlocksRendererElement; + "adc-button": HTMLAdcButtonElement; + "adc-button-rounded": HTMLAdcButtonRoundedElement; + "adc-callout": HTMLAdcCalloutElement; + "adc-code-block": HTMLAdcCodeBlockElement; + "adc-consent-banner": HTMLAdcConsentBannerElement; + "adc-divider": HTMLAdcDividerElement; + "adc-dropdown-menu": HTMLAdcDropdownMenuElement; + "adc-feature-card": HTMLAdcFeatureCardElement; + "adc-icon-community": HTMLAdcIconCommunityElement; + "adc-icon-learning": HTMLAdcIconLearningElement; + "adc-icon-left-arrow": HTMLAdcIconLeftArrowElement; + "adc-icon-logout": HTMLAdcIconLogoutElement; + "adc-icon-nitro": HTMLAdcIconNitroElement; + "adc-icon-opensource": HTMLAdcIconOpensourceElement; + "adc-icon-pencil": HTMLAdcIconPencilElement; + "adc-icon-vip": HTMLAdcIconVipElement; + "adc-inline-tokens": HTMLAdcInlineTokensElement; + "adc-input": HTMLAdcInputElement; + "adc-list-block": HTMLAdcListBlockElement; + "adc-lp-badge": HTMLAdcLpBadgeElement; + "adc-quote": HTMLAdcQuoteElement; + "adc-search-input": HTMLAdcSearchInputElement; + "adc-select": HTMLAdcSelectElement; + "adc-share-buttons": HTMLAdcShareButtonsElement; + "adc-site-footer": HTMLAdcSiteFooterElement; + "adc-site-header": HTMLAdcSiteHeaderElement; + "adc-star-rating": HTMLAdcStarRatingElement; + "adc-table-block": HTMLAdcTableBlockElement; + "adc-testimonial-card": HTMLAdcTestimonialCardElement; + "adc-text": HTMLAdcTextElement; + } +} +declare namespace LocalJSX { + interface AdcBlocksRenderer { + /** + * @default [] + */ + "blocks"?: Block[]; + } + interface AdcButton { + "ariaLabel"?: string; + "href"?: string; + "onAdcClick"?: (event: AdcButtonCustomEvent) => void; + /** + * @default "button" + */ + "type"?: "button" | "submit" | "reset"; + } + interface AdcButtonRounded { + "ariaLabel"?: string; + "href"?: string; + "onAdcClick"?: (event: AdcButtonRoundedCustomEvent) => void; + /** + * @default "button" + */ + "type"?: "button" | "submit" | "reset"; + } + interface AdcCallout { + /** + * @default "note" + */ + "role"?: "note" | "status" | "alert"; + /** + * @default "info" + */ + "tone"?: "info" | "warning" | "success" | "error"; + } + interface AdcCodeBlock { + "ariaLabel"?: string; + /** + * @default "" + */ + "content"?: string; + "language"?: string; + } + interface AdcConsentBanner { + /** + * @default "/cookies" + */ + "cookiesHref"?: string; + "onAdcAcceptAll"?: (event: AdcConsentBannerCustomEvent) => void; + "onAdcAcceptAnalytics"?: (event: AdcConsentBannerCustomEvent) => void; + "onAdcAcknowledge"?: (event: AdcConsentBannerCustomEvent) => void; + "onAdcDeclineAll"?: (event: AdcConsentBannerCustomEvent) => void; + "onAdcDeclineAnalytics"?: (event: AdcConsentBannerCustomEvent) => void; + /** + * @default "/privacy" + */ + "privacyHref"?: string; + /** + * @default false + */ + "restrictedRegion"?: boolean; + /** + * @default false + */ + "visible"?: boolean; + } + interface AdcDivider { + } + interface AdcDropdownMenu { + /** + * @default "left" + */ + "alignState"?: "left" | "right"; + /** + * @default [] + */ + "items"?: DropdownMenuItem[]; + "onAdcItemClick"?: (event: AdcDropdownMenuCustomEvent) => void; + /** + * @default true + */ + "openOnHover"?: boolean; + } + interface AdcFeatureCard { + /** + * @default true + */ + "staticRender"?: boolean; + /** + * @default "" + */ + "title"?: string; + } + interface AdcIconCommunity { + /** + * @default "2rem" + */ + "size"?: string; + } + interface AdcIconLearning { + /** + * @default "2rem" + */ + "size"?: string; + } + interface AdcIconLeftArrow { + /** + * @default "1rem" + */ + "size"?: string; + } + interface AdcIconLogout { + /** + * @default "1rem" + */ + "size"?: string; + } + interface AdcIconNitro { + /** + * @default "1rem" + */ + "size"?: string; + } + interface AdcIconOpensource { + /** + * @default "2rem" + */ + "size"?: string; + } + interface AdcIconPencil { + /** + * @default "1rem" + */ + "size"?: string; + } + interface AdcIconVip { + /** + * @default "1rem" + */ + "size"?: string; + } + interface AdcInlineTokens { + /** + * @default "" + */ + "fallback"?: string; + /** + * @default [] + */ + "tokens"?: InlineToken[]; + } + interface AdcInput { + /** + * @default "" + */ + "ariaLabel"?: string; + /** + * @default "off" + */ + "autocomplete"?: string; + /** + * @default "" + */ + "inputId"?: string; + /** + * @default "" + */ + "name"?: string; + "onAdcInput"?: (event: AdcInputCustomEvent) => void; + /** + * @default "" + */ + "placeholder"?: string; + /** + * @default "text" + */ + "type"?: string; + /** + * @default "" + */ + "value"?: string; + } + interface AdcListBlock { + "ariaLabel"?: string; + /** + * @default [] + */ + "items"?: string[]; + /** + * @default false + */ + "ordered"?: boolean; + "start"?: number; + } + interface AdcLpBadge { + "as"?: "button" | "span"; + /** + * @default "" + */ + "color"?: string; + "onAdcClick"?: (event: AdcLpBadgeCustomEvent) => void; + "slug"?: string; + /** + * @default "" + */ + "title"?: string; + } + interface AdcQuote { + /** + * @default true + */ + "staticRender"?: boolean; + } + interface AdcSearchInput { + /** + * @default "" + */ + "ariaLabel"?: string; + /** + * @default "off" + */ + "autocomplete"?: string; + /** + * @default 300 + */ + "debounce"?: number; + /** + * @default "" + */ + "inputId"?: string; + /** + * @default "" + */ + "name"?: string; + "onAdcInput"?: (event: AdcSearchInputCustomEvent) => void; + /** + * @default "" + */ + "placeholder"?: string; + /** + * @default "text" + */ + "type"?: string; + /** + * @default "" + */ + "value"?: string; + } + interface AdcSelect { + "onAdcChange"?: (event: AdcSelectCustomEvent) => void; + /** + * @default [] + */ + "options"?: SelectOption[]; + /** + * @default "Seleccione" + */ + "placeholder"?: string; + /** + * @default "" + */ + "value"?: string; + } + interface AdcShareButtons { + /** + * @default "" + */ + "description"?: string; + /** + * @default "" + */ + "title"?: string; + /** + * @default "" + */ + "url"?: string; + } + interface AdcSiteFooter { + /** + * @default "" + */ + "brandName"?: string; + /** + * @default "" + */ + "brandSlogan"?: string; + /** + * @default "" + */ + "creatorHref"?: string; + /** + * @default "" + */ + "creatorName"?: string; + "onAdcOpenPrivacyPreferences"?: (event: AdcSiteFooterCustomEvent) => void; + } + interface AdcSiteHeader { + /** + * @default "/" + */ + "homeHref"?: string; + /** + * @default "" + */ + "logoAlt"?: string; + /** + * @default "" + */ + "logoSrc"?: string; + } + interface AdcStarRating { + "average"?: number | null; + /** + * @default false + */ + "canRate"?: boolean; + "count"?: number | null; + "myRating"?: number | null; + "onAdcRate"?: (event: AdcStarRatingCustomEvent) => void; + /** + * @default false + */ + "pending"?: boolean; + } + interface AdcTableBlock { + "caption"?: string; + "columnAlign"?: Array<"left" | "center" | "right">; + /** + * @default [] + */ + "header"?: string[]; + /** + * @default false + */ + "rowHeaders"?: boolean; + /** + * @default [] + */ + "rows"?: string[][]; + } + interface AdcTestimonialCard { + /** + * @default "" + */ + "author"?: string; + /** + * @default true + */ + "staticRender"?: boolean; + } + interface AdcText { + /** + * @default true + */ + "contain"?: boolean; + /** + * @default true + */ + "staticRender"?: boolean; + } + interface IntrinsicElements { + "adc-blocks-renderer": AdcBlocksRenderer; + "adc-button": AdcButton; + "adc-button-rounded": AdcButtonRounded; + "adc-callout": AdcCallout; + "adc-code-block": AdcCodeBlock; + "adc-consent-banner": AdcConsentBanner; + "adc-divider": AdcDivider; + "adc-dropdown-menu": AdcDropdownMenu; + "adc-feature-card": AdcFeatureCard; + "adc-icon-community": AdcIconCommunity; + "adc-icon-learning": AdcIconLearning; + "adc-icon-left-arrow": AdcIconLeftArrow; + "adc-icon-logout": AdcIconLogout; + "adc-icon-nitro": AdcIconNitro; + "adc-icon-opensource": AdcIconOpensource; + "adc-icon-pencil": AdcIconPencil; + "adc-icon-vip": AdcIconVip; + "adc-inline-tokens": AdcInlineTokens; + "adc-input": AdcInput; + "adc-list-block": AdcListBlock; + "adc-lp-badge": AdcLpBadge; + "adc-quote": AdcQuote; + "adc-search-input": AdcSearchInput; + "adc-select": AdcSelect; + "adc-share-buttons": AdcShareButtons; + "adc-site-footer": AdcSiteFooter; + "adc-site-header": AdcSiteHeader; + "adc-star-rating": AdcStarRating; + "adc-table-block": AdcTableBlock; + "adc-testimonial-card": AdcTestimonialCard; + "adc-text": AdcText; + } +} +export { LocalJSX as JSX }; +declare module "@stencil/core" { + export namespace JSX { + interface IntrinsicElements { + "adc-blocks-renderer": LocalJSX.AdcBlocksRenderer & JSXBase.HTMLAttributes; + "adc-button": LocalJSX.AdcButton & JSXBase.HTMLAttributes; + "adc-button-rounded": LocalJSX.AdcButtonRounded & JSXBase.HTMLAttributes; + "adc-callout": LocalJSX.AdcCallout & JSXBase.HTMLAttributes; + "adc-code-block": LocalJSX.AdcCodeBlock & JSXBase.HTMLAttributes; + "adc-consent-banner": LocalJSX.AdcConsentBanner & JSXBase.HTMLAttributes; + "adc-divider": LocalJSX.AdcDivider & JSXBase.HTMLAttributes; + "adc-dropdown-menu": LocalJSX.AdcDropdownMenu & JSXBase.HTMLAttributes; + "adc-feature-card": LocalJSX.AdcFeatureCard & JSXBase.HTMLAttributes; + "adc-icon-community": LocalJSX.AdcIconCommunity & JSXBase.HTMLAttributes; + "adc-icon-learning": LocalJSX.AdcIconLearning & JSXBase.HTMLAttributes; + "adc-icon-left-arrow": LocalJSX.AdcIconLeftArrow & JSXBase.HTMLAttributes; + "adc-icon-logout": LocalJSX.AdcIconLogout & JSXBase.HTMLAttributes; + "adc-icon-nitro": LocalJSX.AdcIconNitro & JSXBase.HTMLAttributes; + "adc-icon-opensource": LocalJSX.AdcIconOpensource & JSXBase.HTMLAttributes; + "adc-icon-pencil": LocalJSX.AdcIconPencil & JSXBase.HTMLAttributes; + "adc-icon-vip": LocalJSX.AdcIconVip & JSXBase.HTMLAttributes; + "adc-inline-tokens": LocalJSX.AdcInlineTokens & JSXBase.HTMLAttributes; + "adc-input": LocalJSX.AdcInput & JSXBase.HTMLAttributes; + "adc-list-block": LocalJSX.AdcListBlock & JSXBase.HTMLAttributes; + "adc-lp-badge": LocalJSX.AdcLpBadge & JSXBase.HTMLAttributes; + "adc-quote": LocalJSX.AdcQuote & JSXBase.HTMLAttributes; + "adc-search-input": LocalJSX.AdcSearchInput & JSXBase.HTMLAttributes; + "adc-select": LocalJSX.AdcSelect & JSXBase.HTMLAttributes; + "adc-share-buttons": LocalJSX.AdcShareButtons & JSXBase.HTMLAttributes; + "adc-site-footer": LocalJSX.AdcSiteFooter & JSXBase.HTMLAttributes; + "adc-site-header": LocalJSX.AdcSiteHeader & JSXBase.HTMLAttributes; + "adc-star-rating": LocalJSX.AdcStarRating & JSXBase.HTMLAttributes; + "adc-table-block": LocalJSX.AdcTableBlock & JSXBase.HTMLAttributes; + "adc-testimonial-card": LocalJSX.AdcTestimonialCard & JSXBase.HTMLAttributes; + "adc-text": LocalJSX.AdcText & JSXBase.HTMLAttributes; + } + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-button-rounded/adc-button-rounded.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-button-rounded/adc-button-rounded.tsx new file mode 100644 index 00000000..31b21d37 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-button-rounded/adc-button-rounded.tsx @@ -0,0 +1,43 @@ +import { Component, Prop, h, Event, EventEmitter } from "@stencil/core"; + +@Component({ + tag: "adc-button-rounded", + shadow: false, +}) +export class AdcButtonRounded { + @Prop() type: "button" | "submit" | "reset" = "button"; + @Prop() href?: string; + @Prop() ariaLabel?: string; + + @Event() adcClick!: EventEmitter; + + private handleClick = (event: MouseEvent) => { + this.adcClick.emit(event); + }; + + private baseClass = "rounded-full px-4 py-4 bg-button text-primary shadow-cozy font-heading cursor-pointer hover:brightness-105 inline-block text-center font-semibold min-h-[44px] min-w-[44px] touch-manipulation flex items-center justify-center"; + + render() { + const TagName = this.href ? "a" : "button"; + const attrs = this.href + ? { + href: this.href, + target: "_blank", + rel: "noopener noreferrer", + } + : { + type: this.type, + }; + + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-button/adc-button.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-button/adc-button.tsx new file mode 100644 index 00000000..e68d3ab2 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-button/adc-button.tsx @@ -0,0 +1,47 @@ +import { Component, Prop, h, Event, EventEmitter } from "@stencil/core"; + +@Component({ + tag: "adc-button", + shadow: false, +}) +export class AdcButton { + @Prop() type: "button" | "submit" | "reset" = "button"; + @Prop() href?: string; + @Prop() ariaLabel?: string; + + @Event() adcClick!: EventEmitter; + + private handleClick = (event: MouseEvent) => { + this.adcClick.emit(event); + }; + + private baseClass = "rounded-3xl px-8 py-4 bg-button text-primary shadow-cozy font-heading cursor-pointer hover:brightness-105 inline-block text-center font-semibold min-h-[44px] min-w-[44px] touch-manipulation"; + + render() { + if (this.href) { + return ( + + + + ); + } + + return ( + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-callout/adc-callout.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-callout/adc-callout.tsx new file mode 100644 index 00000000..8c62abfd --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-callout/adc-callout.tsx @@ -0,0 +1,49 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-callout", + shadow: false, +}) +export class AdcCallout { + @Prop() tone: "info" | "warning" | "success" | "error" = "info"; + @Prop() role: "note" | "status" | "alert" = "note"; + + private getToneClass(): string { + switch (this.tone) { + case "warning": + return "bg-yellow-100 bg-opacity-30 border-yellow-600 text-yellow-900"; + case "success": + return "bg-green-100 bg-opacity-30 border-green-600 text-green-900"; + case "error": + return "bg-red-100 bg-opacity-30 border-red-600 text-red-900"; + default: + return "bg-cyan-100 bg-opacity-30 border-blue-600 text-blue-900"; + } + } + + render() { + const classes = `rounded-xxl border p-3 mb-2 ml-8 xl:max-w-[80vw] ${this.getToneClass()}`; + + if (this.role === "note") { + return ( + + ); + } + + if (this.role === "status") { + return ( + + + + ); + } + + return ( + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-code-block/adc-code-block.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-code-block/adc-code-block.tsx new file mode 100644 index 00000000..fca04eb4 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-code-block/adc-code-block.tsx @@ -0,0 +1,34 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-code-block", + shadow: false, +}) +export class AdcCodeBlock { + @Prop() language?: string; + @Prop() content: string = ""; + @Prop() ariaLabel?: string; + + private escapeHtml(text: string): string { + return text.replace(/&/g, "&").replace(//g, ">"); + } + + render() { + const escapedContent = this.escapeHtml(this.content); + const codeClass = this.language + ? `block p-3 whitespace-pre break-normal language-${this.language} lang-${this.language}` + : "block p-3 whitespace-pre break-normal"; + + return ( +
+ {this.language && ( +
[{this.language}]
+ )} + +
+ ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-divider/adc-divider.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-divider/adc-divider.tsx new file mode 100644 index 00000000..b2eeaa54 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-divider/adc-divider.tsx @@ -0,0 +1,11 @@ +import { Component, h } from "@stencil/core"; + +@Component({ + tag: "adc-divider", + shadow: false, +}) +export class AdcDivider { + render() { + return
; + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-inline-tokens/adc-inline-tokens.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-inline-tokens/adc-inline-tokens.tsx new file mode 100644 index 00000000..dacefed1 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-inline-tokens/adc-inline-tokens.tsx @@ -0,0 +1,40 @@ +import { Component, Prop, h } from "@stencil/core"; + +export interface InlineToken { + type: "text" | "bold" | "italic" | "strike" | "code"; + content: string; +} + +@Component({ + tag: "adc-inline-tokens", + shadow: false, +}) +export class AdcInlineTokens { + @Prop() tokens: InlineToken[] = []; + @Prop() fallback: string = ""; + + render() { + if (!this.tokens || this.tokens.length === 0) { + return {this.fallback}; + } + + return ( + + {this.tokens.map((token, idx) => { + switch (token.type) { + case "bold": + return {token.content}; + case "italic": + return {token.content}; + case "strike": + return {token.content}; + case "code": + return {token.content}; + default: + return {token.content}; + } + })} + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-input/adc-input.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-input/adc-input.tsx new file mode 100644 index 00000000..161b6fd1 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-input/adc-input.tsx @@ -0,0 +1,38 @@ +import { Component, Prop, h, Event, EventEmitter } from "@stencil/core"; + +@Component({ + tag: "adc-input", + shadow: false, +}) +export class AdcInput { + @Prop() value: string = ""; + @Prop() placeholder?: string = ""; + @Prop() inputId?: string = ""; + @Prop() name?: string = ""; + @Prop() type?: string = "text"; + @Prop() autocomplete?: string = "off"; + @Prop() ariaLabel?: string = ""; + + @Event() adcInput!: EventEmitter; + + private handleInput = (event: Event) => { + const target = event.target as HTMLInputElement; + this.adcInput.emit(target.value); + }; + + render() { + return ( + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-list-block/adc-list-block.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-list-block/adc-list-block.tsx new file mode 100644 index 00000000..008108f4 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-list-block/adc-list-block.tsx @@ -0,0 +1,35 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-list-block", + shadow: false, +}) +export class AdcListBlock { + @Prop() ordered: boolean = false; + @Prop() items: string[] = []; + @Prop() start?: number; + @Prop() ariaLabel?: string; + + render() { + const listClass = "pl-5 my-2 list-outside mb-2 ml-16"; + const listItems = this.items.map((item, index) => ( +
  • + +
  • + )); + + if (this.ordered) { + return ( +
      + {listItems} +
    + ); + } + + return ( +
      + {listItems} +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-lp-badge/adc-lp-badge.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-lp-badge/adc-lp-badge.tsx new file mode 100644 index 00000000..f065ef2e --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-lp-badge/adc-lp-badge.tsx @@ -0,0 +1,54 @@ +import { Component, Prop, h, Event, EventEmitter } from "@stencil/core"; + +@Component({ + tag: "adc-lp-badge", + shadow: false, +}) +export class AdcLpBadge { + @Prop() title: string = ""; + @Prop() color: string = ""; + @Prop() slug?: string; + @Prop() as?: "button" | "span"; + + @Event() adcClick!: EventEmitter; + + private handleClick = () => { + this.adcClick.emit(); + }; + + private getColorClasses(): string { + const colorMap = new Map([ + ["red", "bg-red-100 text-red-700 border-red-600"], + ["orange", "bg-orange-100 text-orange-700 border-orange-600"], + ["yellow", "bg-yellow-100 text-yellow-700 border-yellow-600"], + ["green", "bg-green-100 text-green-700 border-green-600"], + ["teal", "bg-teal-100 text-teal-700 border-teal-600"], + ["blue", "bg-blue-100 text-blue-700 border-blue-600"], + ["purple", "bg-purple-100 text-purple-700 border-purple-600"], + ["pink", "bg-pink-100 text-pink-700 border-pink-600"], + ]); + return colorMap.get(this.color) ?? ""; + } + + render() { + const baseClass = `px-2 py-1 min-w-fit rounded-full border text-sm no-underline inline-block flex items-center ${this.getColorClasses()}`; + + if (this.slug) { + return ( + + {this.title} + + ); + } + + if (this.as === "button") { + return ( + + ); + } + + return {this.title}; + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-quote/adc-quote.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-quote/adc-quote.tsx new file mode 100644 index 00000000..ef7bd18c --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-quote/adc-quote.tsx @@ -0,0 +1,17 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-quote", + shadow: false, +}) +export class AdcQuote { + @Prop() staticRender: boolean = true; + + render() { + return ( +
    + +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-search-input/adc-search-input.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-search-input/adc-search-input.tsx new file mode 100644 index 00000000..c99dbebc --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-search-input/adc-search-input.tsx @@ -0,0 +1,84 @@ +import { Component, Prop, h, Event, EventEmitter, State } from "@stencil/core"; + +@Component({ + tag: "adc-search-input", + shadow: false, +}) +export class AdcSearchInput { + @Prop() value: string = ""; + @Prop() placeholder: string = ""; + @Prop() inputId?: string = ""; + @Prop() name?: string = ""; + @Prop() type?: string = "text"; + @Prop() autocomplete?: string = "off"; + @Prop() ariaLabel?: string = ""; + @Prop() debounce: number = 300; + + @State() innerValue: string = ""; + + private debounceTimer?: ReturnType; + + @Event() adcInput!: EventEmitter; + + componentWillLoad() { + this.innerValue = this.value; + } + + private handleInput = (event: Event) => { + const target = event.target as HTMLInputElement; + this.innerValue = target.value; + + if (this.debounceTimer) { + clearTimeout(this.debounceTimer); + } + + if (this.debounce > 0) { + this.debounceTimer = setTimeout(() => { + this.adcInput.emit(this.innerValue); + }, this.debounce); + } else { + this.adcInput.emit(this.innerValue); + } + }; + + disconnectedCallback() { + if (this.debounceTimer) { + clearTimeout(this.debounceTimer); + } + } + + render() { + const labelClass = "relative flex items-center w-full bg-white rounded-xxl border border-alt"; + const iconClass = "absolute left-[0.9rem] inline-flex items-center justify-center text-black/45 pointer-events-none"; + const inputClass = "flex-1 bg-transparent border-none outline-none py-[0.6rem] pr-[0.8rem] pl-[2.5rem] rounded-xxl font-text text-[0.9rem] text-text"; + + return ( + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-select/adc-select.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-select/adc-select.tsx new file mode 100644 index 00000000..256172ad --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-select/adc-select.tsx @@ -0,0 +1,83 @@ +import { Component, Prop, h, Event, EventEmitter, State } from "@stencil/core"; + +export interface SelectOption { + label: string; + value: string; +} + +@Component({ + tag: "adc-select", + shadow: false, +}) +export class AdcSelect { + @Prop() value: string = ""; + @Prop() options: SelectOption[] = []; + @Prop() placeholder: string = "Seleccione"; + + @State() isOpen: boolean = false; + + @Event() adcChange!: EventEmitter; + + private handleToggle = () => { + this.isOpen = !this.isOpen; + }; + + private handleSelect = (option: SelectOption) => { + this.adcChange.emit(option.value); + this.isOpen = false; + }; + + private handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape") { + this.isOpen = false; + } + }; + + private getSelectedLabel(): string { + const selected = this.options.find((opt) => opt.value === this.value); + return selected ? selected.label : this.placeholder; + } + + render() { + return ( +
    + + {this.isOpen && ( +
    + {this.options.map((option) => ( + + ))} +
    + )} +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-star-rating/adc-star-rating.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-star-rating/adc-star-rating.tsx new file mode 100644 index 00000000..8f9eac3a --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-star-rating/adc-star-rating.tsx @@ -0,0 +1,61 @@ +import { Component, Prop, h, Event, EventEmitter, State } from "@stencil/core"; + +@Component({ + tag: "adc-star-rating", + shadow: false, +}) +export class AdcStarRating { + @Prop() average?: number | null; + @Prop() count?: number | null; + @Prop() myRating?: number | null; + @Prop() canRate: boolean = false; + @Prop() pending: boolean = false; + + @State() mounted: boolean = false; + + @Event() adcRate!: EventEmitter; + + componentDidLoad() { + this.mounted = true; + } + + private handleClick = (rating: number) => { + if (!this.canRate || this.pending || !this.mounted) return; + this.adcRate.emit(rating); + }; + + private isDisabled(): boolean { + return !this.canRate || this.pending || !this.mounted; + } + + private getDisplayRating(): number { + return this.myRating ?? this.average ?? 0; + } + + render() { + const disabled = this.isDisabled(); + const displayRating = this.getDisplayRating(); + + return ( +
    + {[1, 2, 3, 4, 5].map((i) => ( + + ))} + + {typeof this.average === "number" ? this.average.toFixed(1) : "0.0"} ({this.count ?? 0}) + +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-table-block/adc-table-block.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-table-block/adc-table-block.tsx new file mode 100644 index 00000000..50fa2363 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-table-block/adc-table-block.tsx @@ -0,0 +1,63 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-table-block", + shadow: false, +}) +export class AdcTableBlock { + @Prop() header: string[] = []; + @Prop() rows: string[][] = []; + @Prop() columnAlign?: Array<"left" | "center" | "right">; + @Prop() caption?: string; + @Prop() rowHeaders: boolean = false; + + private getAlignClass(align?: "left" | "center" | "right"): string { + if (align === "center") return "text-center"; + if (align === "right") return "text-right"; + return "text-left"; + } + + render() { + return ( +
    + + {this.caption && ( + + )} + + + {this.header.map((h, i) => ( + + ))} + + + + {this.rows.map((row, ri) => ( + + {row.map((cell, ci) => { + if (this.rowHeaders && ci === 0) { + return ( + + ); + } + return ( + + ); + })} + + ))} + +
    {this.caption}
    + +
    + + + +
    +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/atoms/adc-text/adc-text.tsx b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-text/adc-text.tsx new file mode 100644 index 00000000..210117bb --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/atoms/adc-text/adc-text.tsx @@ -0,0 +1,18 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-text", + shadow: false, +}) +export class AdcText { + @Prop() staticRender: boolean = true; + @Prop() contain: boolean = true; + + render() { + return ( +

    + +

    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-community/adc-icon-community.css b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-community/adc-icon-community.css new file mode 100644 index 00000000..24da728d --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-community/adc-icon-community.css @@ -0,0 +1,10 @@ +:host { + display: inline-flex; + align-items: center; + justify-content: center; + color: rgb(93, 58, 47); +} + +.adc-icon { + display: block; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-community/adc-icon-community.tsx b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-community/adc-icon-community.tsx new file mode 100644 index 00000000..3a58a29e --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-community/adc-icon-community.tsx @@ -0,0 +1,26 @@ +import { Component, Prop, h, Host } from "@stencil/core"; + +@Component({ + tag: "adc-icon-community", + styleUrl: "adc-icon-community.css", + shadow: true, +}) +export class AdcIconCommunity { + @Prop() size: string = "2rem"; + + render() { + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-learning/adc-icon-learning.css b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-learning/adc-icon-learning.css new file mode 100644 index 00000000..24da728d --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-learning/adc-icon-learning.css @@ -0,0 +1,10 @@ +:host { + display: inline-flex; + align-items: center; + justify-content: center; + color: rgb(93, 58, 47); +} + +.adc-icon { + display: block; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-learning/adc-icon-learning.tsx b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-learning/adc-icon-learning.tsx new file mode 100644 index 00000000..90208ffb --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-learning/adc-icon-learning.tsx @@ -0,0 +1,28 @@ +import { Component, Prop, h, Host } from "@stencil/core"; + +@Component({ + tag: "adc-icon-learning", + styleUrl: "adc-icon-learning.css", + shadow: true, +}) +export class AdcIconLearning { + @Prop() size: string = "2rem"; + + render() { + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-left-arrow/adc-icon-left-arrow.css b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-left-arrow/adc-icon-left-arrow.css new file mode 100644 index 00000000..febfe7dc --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-left-arrow/adc-icon-left-arrow.css @@ -0,0 +1,10 @@ +:host { + display: inline-flex; + align-items: center; + justify-content: center; + color: currentColor; +} + +.adc-icon { + display: block; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-left-arrow/adc-icon-left-arrow.tsx b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-left-arrow/adc-icon-left-arrow.tsx new file mode 100644 index 00000000..36852597 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-left-arrow/adc-icon-left-arrow.tsx @@ -0,0 +1,29 @@ +import { Component, Prop, h, Host } from "@stencil/core"; + +@Component({ + tag: "adc-icon-left-arrow", + styleUrl: "adc-icon-left-arrow.css", + shadow: true, +}) +export class AdcIconLeftArrow { + @Prop() size: string = "1rem"; + + render() { + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-logout/adc-icon-logout.css b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-logout/adc-icon-logout.css new file mode 100644 index 00000000..febfe7dc --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-logout/adc-icon-logout.css @@ -0,0 +1,10 @@ +:host { + display: inline-flex; + align-items: center; + justify-content: center; + color: currentColor; +} + +.adc-icon { + display: block; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-logout/adc-icon-logout.tsx b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-logout/adc-icon-logout.tsx new file mode 100644 index 00000000..7672604d --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-logout/adc-icon-logout.tsx @@ -0,0 +1,30 @@ +import { Component, Prop, h, Host } from "@stencil/core"; + +@Component({ + tag: "adc-icon-logout", + styleUrl: "adc-icon-logout.css", + shadow: true, +}) +export class AdcIconLogout { + @Prop() size: string = "1rem"; + + render() { + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-nitro/adc-icon-nitro.css b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-nitro/adc-icon-nitro.css new file mode 100644 index 00000000..febfe7dc --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-nitro/adc-icon-nitro.css @@ -0,0 +1,10 @@ +:host { + display: inline-flex; + align-items: center; + justify-content: center; + color: currentColor; +} + +.adc-icon { + display: block; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-nitro/adc-icon-nitro.tsx b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-nitro/adc-icon-nitro.tsx new file mode 100644 index 00000000..da8eab0c --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-nitro/adc-icon-nitro.tsx @@ -0,0 +1,30 @@ +import { Component, Prop, h, Host } from "@stencil/core"; + +@Component({ + tag: "adc-icon-nitro", + styleUrl: "adc-icon-nitro.css", + shadow: true, +}) +export class AdcIconNitro { + @Prop() size: string = "1rem"; + + render() { + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-opensource/adc-icon-opensource.css b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-opensource/adc-icon-opensource.css new file mode 100644 index 00000000..24da728d --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-opensource/adc-icon-opensource.css @@ -0,0 +1,10 @@ +:host { + display: inline-flex; + align-items: center; + justify-content: center; + color: rgb(93, 58, 47); +} + +.adc-icon { + display: block; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-opensource/adc-icon-opensource.tsx b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-opensource/adc-icon-opensource.tsx new file mode 100644 index 00000000..893b59b9 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-opensource/adc-icon-opensource.tsx @@ -0,0 +1,26 @@ +import { Component, Prop, h, Host } from "@stencil/core"; + +@Component({ + tag: "adc-icon-opensource", + styleUrl: "adc-icon-opensource.css", + shadow: true, +}) +export class AdcIconOpensource { + @Prop() size: string = "2rem"; + + render() { + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-pencil/adc-icon-pencil.css b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-pencil/adc-icon-pencil.css new file mode 100644 index 00000000..febfe7dc --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-pencil/adc-icon-pencil.css @@ -0,0 +1,10 @@ +:host { + display: inline-flex; + align-items: center; + justify-content: center; + color: currentColor; +} + +.adc-icon { + display: block; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-pencil/adc-icon-pencil.tsx b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-pencil/adc-icon-pencil.tsx new file mode 100644 index 00000000..35974ec9 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-pencil/adc-icon-pencil.tsx @@ -0,0 +1,34 @@ +import { Component, Prop, h, Host } from "@stencil/core"; + +@Component({ + tag: "adc-icon-pencil", + styleUrl: "adc-icon-pencil.css", + shadow: true, +}) +export class AdcIconPencil { + @Prop() size: string = "1rem"; + + render() { + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-vip/adc-icon-vip.css b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-vip/adc-icon-vip.css new file mode 100644 index 00000000..febfe7dc --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-vip/adc-icon-vip.css @@ -0,0 +1,10 @@ +:host { + display: inline-flex; + align-items: center; + justify-content: center; + color: currentColor; +} + +.adc-icon { + display: block; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-vip/adc-icon-vip.tsx b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-vip/adc-icon-vip.tsx new file mode 100644 index 00000000..c1dab609 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/icons/adc-icon-vip/adc-icon-vip.tsx @@ -0,0 +1,29 @@ +import { Component, Prop, h, Host } from "@stencil/core"; + +@Component({ + tag: "adc-icon-vip", + styleUrl: "adc-icon-vip.css", + shadow: true, +}) +export class AdcIconVip { + @Prop() size: string = "1rem"; + + render() { + return ( + + + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/molecules/adc-dropdown-menu/adc-dropdown-menu.tsx b/src/apps/public/00-adc-ui-library/src/components/molecules/adc-dropdown-menu/adc-dropdown-menu.tsx new file mode 100644 index 00000000..bf0d4c8e --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/molecules/adc-dropdown-menu/adc-dropdown-menu.tsx @@ -0,0 +1,116 @@ +import { Component, Prop, h, Event, EventEmitter, State } from "@stencil/core"; + +export interface DropdownMenuItem { + label: string; + to?: string; + action?: string; + icon?: any; +} + +@Component({ + tag: "adc-dropdown-menu", + shadow: false, +}) +export class AdcDropdownMenu { + @Prop() items: DropdownMenuItem[] = []; + @Prop() alignState: "left" | "right" = "left"; + @Prop() openOnHover: boolean = true; + + @State() isOpen: boolean = false; + + @Event() adcItemClick!: EventEmitter; + + private hoverTimeout?: ReturnType; + + private handleToggle = () => { + this.isOpen = !this.isOpen; + }; + + private handleItemClick = (item: DropdownMenuItem) => { + this.adcItemClick.emit(item); + this.isOpen = false; + }; + + private handleMouseEnter = () => { + if (!this.openOnHover) return; + if (this.hoverTimeout) clearTimeout(this.hoverTimeout); + this.isOpen = true; + }; + + private handleMouseLeave = () => { + if (!this.openOnHover) return; + this.hoverTimeout = setTimeout(() => { + this.isOpen = false; + }, 150); + }; + + private handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape") { + this.isOpen = false; + } + }; + + disconnectedCallback() { + if (this.hoverTimeout) clearTimeout(this.hoverTimeout); + } + + render() { + const alignClass = this.alignState === "right" ? "right-0" : "left-0"; + + return ( +
    + + + {this.isOpen && ( + + )} +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/molecules/adc-feature-card/adc-feature-card.tsx b/src/apps/public/00-adc-ui-library/src/components/molecules/adc-feature-card/adc-feature-card.tsx new file mode 100644 index 00000000..ceea8b61 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/molecules/adc-feature-card/adc-feature-card.tsx @@ -0,0 +1,24 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-feature-card", + shadow: false, +}) +export class AdcFeatureCard { + @Prop() title: string = ""; + @Prop() staticRender: boolean = true; + + render() { + return ( +
    + +

    {this.title}

    + + + +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/molecules/adc-share-buttons/adc-share-buttons.tsx b/src/apps/public/00-adc-ui-library/src/components/molecules/adc-share-buttons/adc-share-buttons.tsx new file mode 100644 index 00000000..9b82a03f --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/molecules/adc-share-buttons/adc-share-buttons.tsx @@ -0,0 +1,71 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-share-buttons", + shadow: false, +}) +export class AdcShareButtons { + @Prop() title: string = ""; + @Prop() description: string = ""; + @Prop() url: string = ""; + + private getEncodedText(): string { + return encodeURIComponent(`${this.title}\n\n${this.description}\n\n${this.url}`); + } + + private getLinkedInUrl(): string { + return `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(this.url)}`; + } + + private getTwitterUrl(): string { + return `https://twitter.com/intent/tweet?text=${this.getEncodedText()}`; + } + + private getThreadsUrl(): string { + return `https://www.threads.net/intent/post?text=${this.getEncodedText()}`; + } + + render() { + return ( + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/molecules/adc-testimonial-card/adc-testimonial-card.tsx b/src/apps/public/00-adc-ui-library/src/components/molecules/adc-testimonial-card/adc-testimonial-card.tsx new file mode 100644 index 00000000..9b5ab393 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/molecules/adc-testimonial-card/adc-testimonial-card.tsx @@ -0,0 +1,21 @@ +import { Component, Prop, h } from "@stencil/core"; + +@Component({ + tag: "adc-testimonial-card", + shadow: false, +}) +export class AdcTestimonialCard { + @Prop() author: string = ""; + @Prop() staticRender: boolean = true; + + render() { + return ( +
    + + + +
    — {this.author}
    +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/organisms/adc-blocks-renderer/adc-blocks-renderer.tsx b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-blocks-renderer/adc-blocks-renderer.tsx new file mode 100644 index 00000000..5287d137 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-blocks-renderer/adc-blocks-renderer.tsx @@ -0,0 +1,149 @@ +import { Component, Prop, h } from "@stencil/core"; +import "./code-highlight.css"; + +export interface Block { + type: "heading" | "paragraph" | "list" | "code" | "callout" | "quote" | "table" | "divider"; + level?: number; + id?: string; + align?: "left" | "center" | "right"; + text?: string; + marks?: Array<"bold" | "italic" | "code">; + ordered?: boolean; + items?: string[]; + start?: number; + ariaLabel?: string; + language?: string; + content?: string; + tone?: "info" | "warning" | "success" | "error"; + role?: "note" | "status" | "alert"; + url?: string; + rel?: string[]; + header?: string[]; + rows?: string[][]; + columnAlign?: Array<"left" | "center" | "right">; + caption?: string; + rowHeaders?: boolean; +} + +@Component({ + tag: "adc-blocks-renderer", + shadow: false, +}) +export class AdcBlocksRenderer { + @Prop() blocks: Block[] = []; + + private getAlignClass(align?: "left" | "center" | "right"): string { + if (align === "center") return "text-center"; + if (align === "right") return "text-right"; + return ""; + } + + private getMarksClass(marks?: Array<"bold" | "italic" | "code">): string { + const classes: string[] = []; + if (marks?.includes("bold")) classes.push("font-bold"); + if (marks?.includes("italic")) classes.push("italic"); + return classes.join(" "); + } + + private renderBlock(block: Block, index: number) { + switch (block.type) { + case "heading": + return this.renderHeading(block, index); + case "paragraph": + return this.renderParagraph(block, index); + case "list": + return ( + + ); + case "code": + return ( + + ); + case "callout": + return ( + + + + ); + case "quote": + return ( + + + {block.url && ( + + + Fuente + + + )} + + ); + case "table": + return ( + + ); + case "divider": + return ; + default: + return null; + } + } + + private renderHeading(block: Block, index: number) { + const alignClass = this.getAlignClass(block.align); + const level = block.level || 2; + const Tag = `h${level}` as "h2" | "h3" | "h4" | "h5" | "h6"; + + return ( + + {block.text} + + ); + } + + private renderParagraph(block: Block, index: number) { + const classes = `${this.getAlignClass(block.align)} ${this.getMarksClass(block.marks)} pl-4 pr-16 whitespace-pre-line`; + + if (block.marks?.includes("code")) { + return ( + + {block.text} + + ); + } + + return ( + + + + ); + } + + render() { + return
    {this.blocks.map((block, index) => this.renderBlock(block, index))}
    ; + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/organisms/adc-blocks-renderer/code-highlight.css b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-blocks-renderer/code-highlight.css new file mode 100644 index 00000000..5d206c15 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-blocks-renderer/code-highlight.css @@ -0,0 +1,63 @@ +/* Improved contrast for light bg code blocks */ +.token.keyword { + color: #5a2ca0; /* deep purple */ + font-weight: 600; +} + +.token.function { + color: #004d85; +} + +.token.type { + color: #1666d3; + font-weight: 600; +} + +.token.comment { + color: #6a737d; /* muted gray for comments */ + font-style: italic; +} + +.token.preprocessor { + color: #6f42c1; /* purple */ + font-weight: 500; +} + +.token.operator { + color: #d73a49; /* red */ + font-weight: 600; +} + +.token.string { + color: #22863a; /* green */ +} + +/* HTML-specific tokens */ +.token.tag { + color: #1f6feb; /* blue for tag names */ + font-weight: 600; +} + +.token.attr-name { + color: #cf222e; /* red for attribute names */ +} + +.token.attr-value { + color: #116329; /* darker green for attribute values */ +} + +.token.punctuation { + color: #57606a; /* gray for <, >, =, / */ +} + +/* Ensure base code color remains readable on alt background */ +pre code { + color: #1a1a1a; + display: block; + padding-left: 20px; +} + +pre { + display: flex; + flex-direction: column; +} diff --git a/src/apps/public/00-adc-ui-library/src/components/organisms/adc-consent-banner/adc-consent-banner.tsx b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-consent-banner/adc-consent-banner.tsx new file mode 100644 index 00000000..81db94c8 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-consent-banner/adc-consent-banner.tsx @@ -0,0 +1,118 @@ +import { Component, Prop, h, Event, EventEmitter, State } from "@stencil/core"; + +@Component({ + tag: "adc-consent-banner", + shadow: false, +}) +export class AdcConsentBanner { + @Prop() visible: boolean = false; + @Prop() restrictedRegion: boolean = false; + @Prop() privacyHref: string = "/privacy"; + @Prop() cookiesHref: string = "/cookies"; + + @State() isVisible: boolean = false; + + @Event() adcAcceptAll!: EventEmitter; + @Event() adcAcceptAnalytics!: EventEmitter; + @Event() adcDeclineAll!: EventEmitter; + @Event() adcDeclineAnalytics!: EventEmitter; + @Event() adcAcknowledge!: EventEmitter; + + componentWillLoad() { + this.isVisible = this.visible; + } + + componentWillUpdate() { + this.isVisible = this.visible; + } + + private handleAcceptAll = () => { + this.adcAcceptAll.emit(); + this.isVisible = false; + }; + + private handleAcceptAnalytics = () => { + this.adcAcceptAnalytics.emit(); + this.isVisible = false; + }; + + private handleDeclineAll = () => { + this.adcDeclineAll.emit(); + this.isVisible = false; + }; + + private handleDeclineAnalytics = () => { + this.adcDeclineAnalytics.emit(); + this.isVisible = false; + }; + + private handleAcknowledge = () => { + this.adcAcknowledge.emit(); + this.isVisible = false; + }; + + render() { + if (!this.isVisible) return null; + + return ( + +
    + + + {this.restrictedRegion ? ( +
    +

    + Usamos cookies de analítica (Google Analytics 4) y medición (Microsoft Clarity) para mejorar el sitio. Podés aceptar sólo + analítica o todas. Leé nuestra{" "} + + Política de Privacidad + {" "} + y{" "} + + Política de Cookies + + . +

    +
    + + Rechazar + + + Aceptar analítica + + + Aceptar todo + +
    +
    + ) : ( +
    +

    + Usamos analítica (GA4) y medición (Clarity) para mejorar el sitio. La analítica está habilitada; podés desactivarla o + cerrar este aviso. Ver{" "} + + Privacidad + {" "} + y{" "} + + Cookies + + . +

    +
    + + Desactivar analítica + + + Entendido + +
    +
    + )} +
    +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/organisms/adc-site-footer/adc-site-footer.tsx b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-site-footer/adc-site-footer.tsx new file mode 100644 index 00000000..b69d975b --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-site-footer/adc-site-footer.tsx @@ -0,0 +1,53 @@ +import { Component, Prop, h, Event, EventEmitter } from "@stencil/core"; + +@Component({ + tag: "adc-site-footer", + shadow: false, +}) +export class AdcSiteFooter { + @Prop() brandName: string = ""; + @Prop() brandSlogan: string = ""; + @Prop() creatorName: string = ""; + @Prop() creatorHref: string = ""; + + @Event() adcOpenPrivacyPreferences!: EventEmitter; + + private getYear(): number { + return new Date().getFullYear(); + } + + private handlePrivacyClick = () => { + this.adcOpenPrivacyPreferences.emit(); + }; + + render() { + return ( + + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/components/organisms/adc-site-header/adc-site-header.tsx b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-site-header/adc-site-header.tsx new file mode 100644 index 00000000..6712525a --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/components/organisms/adc-site-header/adc-site-header.tsx @@ -0,0 +1,39 @@ +import { Component, Prop, h } from "@stencil/core"; + +export interface NavItem { + label: string; + href: string; +} + +@Component({ + tag: "adc-site-header", + shadow: false, +}) +export class AdcSiteHeader { + @Prop() logoSrc: string = ""; + @Prop() logoAlt: string = ""; + @Prop() homeHref: string = "/"; + + render() { + return ( +
    + + {this.logoSrc && ( + {this.logoAlt} + )} + + + +
    + ); + } +} diff --git a/src/apps/public/00-adc-ui-library/src/global/accessibility.css b/src/apps/public/00-adc-ui-library/src/global/accessibility.css new file mode 100644 index 00000000..d9137cca --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/global/accessibility.css @@ -0,0 +1,108 @@ +/* Mejoras de accesibilidad */ + +/* Asegurar que todos los elementos interactivos tengan un tamaño mínimo táctil */ +@media only screen and (max-width: 768px) { + button, + a, + input, + select, + textarea, + [role="button"], + [role="link"] { + min-height: 44px; + min-width: 44px; + touch-action: manipulation; + } +} + +/* Mejorar el contraste de foco para navegación por teclado */ +*:focus { + outline: 2px solid #c97e5d; + outline-offset: 2px; +} + +*:focus:not(:focus-visible) { + outline: none; +} + +*:focus-visible { + outline: 2px solid #c97e5d; + outline-offset: 2px; +} + +/* Asegurar que el texto sea legible */ +body { + line-height: 1.5; + color: #1a1a1a; +} + +/* Mejorar el espaciado entre elementos interactivos */ +.flex.gap-3 > * + * { + margin-left: 12px; +} + +/* Asegurar que los iconos decorativos no interfieran con lectores de pantalla */ +[aria-hidden="true"] { + pointer-events: none; +} + +/* Mejorar la legibilidad de enlaces */ +a { + text-decoration-skip-ink: auto; +} + +a:focus { + text-decoration: underline; +} + +/* Asegurar que los elementos con role="menuitem" tengan el tamaño adecuado */ +[role="menuitem"] { + min-height: 44px; + padding: 8px 16px; +} + +/* Mejorar la visibilidad de elementos de formulario */ +input, +select, +textarea { + border: 1px solid #c97e5d; +} + +input:focus, +select:focus, +textarea:focus { + border-color: #5d3a2f; + box-shadow: 0 0 0 2px rgba(197, 126, 93, 0.2); +} + +/* Mejorar la legibilidad en dispositivos de alto contraste */ +@media (prefers-contrast: high) { + * { + border-color: currentColor !important; + } + + button, + .button, + [role="button"] { + border: 2px solid currentColor; + } +} + +/* Reducir movimiento para usuarios que lo prefieren */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + +/* Mejorar la legibilidad del texto */ +@media (prefers-contrast: more) { + body { + color: #000; + background-color: #fff; + } +} diff --git a/src/apps/public/00-adc-ui-library/src/global/tailwind.css b/src/apps/public/00-adc-ui-library/src/global/tailwind.css new file mode 100644 index 00000000..d85a5478 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/src/global/tailwind.css @@ -0,0 +1,99 @@ +@layer base { + :root { + --c-primary: 254 240 203; + --c-accent: 201 126 93; + --c-text: 26 26 26; + --c-button: 93 58 47; + --c-alt: 242 224 196; + + --r-xxl: 16px; + --shadow: 0 8px 24px rgba(0, 0, 0, 0.08); + } + html, + body { + background-color: rgb(var(--c-primary)); + color: rgb(var(--c-text)); + margin: 0; + font-family: Inter, system-ui, sans-serif; + font-size: 12px; + } + + a { + color: inherit; + } + + * { + box-sizing: border-box; + } +} + +@layer components { + .bg-alt { + box-shadow: 0 8px 8px rgba(0, 0, 0, 0.15); + margin-bottom: 18px; + } + + /* Hint: avoid rendering below-the-fold until needed */ + .cv-auto { + content-visibility: auto; + contain-intrinsic-size: 1px 800px; /* rough placeholder to avoid layout shift */ + } + + .nav-menu li { + min-width: fit-content; + white-space: nowrap; + } + + p, + li, + .p-text { + color: var(--c-text); + font-size: 14px; + font-family: Inter, system-ui, sans-serif; + line-height: 1.6; + margin-top: 0.5rem; + margin-bottom: 0.5rem; + } + + h1 { + color: var(--c-text); + font-family: Fredoka, sans-serif; + font-size: 36px; + line-height: 1.15; + margin-top: 0.5rem; + margin-bottom: 1rem; + letter-spacing: 0.2px; + } + + h2 { + color: var(--c-text); + font-family: Fredoka, sans-serif; + font-size: 26px; + line-height: 1.2; + margin-top: 2rem; + margin-bottom: 1rem; + } + + h3, + .h3 { + color: var(--c-text); + font-family: Fredoka, sans-serif; + font-size: 20px; + line-height: 1.3; + margin-top: 1rem; + margin-bottom: 0.5rem; + } + + .breadcumb > * { + color: var(--c-text); + font-family: Fredoka, sans-serif; + font-size: 20px; + margin-bottom: 0; + margin-top: 0; + } + + .breadcumb > * + li::before { + margin-left: 8px; + content: "/ "; + } +} diff --git a/src/apps/public/00-adc-ui-library/stencil.config.ts b/src/apps/public/00-adc-ui-library/stencil.config.ts new file mode 100644 index 00000000..b2cd4d82 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/stencil.config.ts @@ -0,0 +1,26 @@ +import { Config } from '@stencil/core'; + +/** + * Stencil config para adc-ui-library + * + * Generado automáticamente por UIFederationService. + * Los componentes usan CSS puro (compatible con Shadow DOM). + */ +export const config: Config = { + namespace: 'adc-ui-library', + cacheDir: '../../../../temp/stencil-cache/adc-platform/adc-ui-library', + outputTargets: [ + { + type: 'dist', + dir: '../../../../temp/ui-builds/adc-platform/adc-ui-library', + }, + { + type: 'dist-custom-elements', + dir: '../../../../temp/ui-builds/adc-platform/adc-ui-library/custom-elements', + customElementsExportBehavior: 'auto-define-custom-elements', + externalRuntime: true, + }, + ], + sourceMap: true, + buildEs5: false, +}; diff --git a/src/apps/public/00-adc-ui-library/tsconfig.json b/src/apps/public/00-adc-ui-library/tsconfig.json new file mode 100644 index 00000000..aa150d94 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "declaration": true, + "experimentalDecorators": true, + "lib": ["dom", "es2017"], + "module": "esnext", + "moduleResolution": "bundler", + "target": "es2017", + "jsx": "react", + "jsxFactory": "h", + "jsxFragmentFactory": "Fragment", + "noUnusedLocals": true, + "noUnusedParameters": true, + "skipLibCheck": true, + "types": [] + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/src/apps/public/00-adc-ui-library/utils/router.ts b/src/apps/public/00-adc-ui-library/utils/router.ts new file mode 100644 index 00000000..d209b3f3 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/utils/router.ts @@ -0,0 +1,101 @@ +export interface RouteDefinition { + module: string; + path?: string; + subdomain?: string; +} + +export class Router { + private onRouteChange: ((path: string) => void) | null = null; + private popstateListener: (() => void) | null = null; + private baseDomain: string | null = null; + + navigate(path: string) { + if (window.location.pathname === path) { + return; + } + + window.history.pushState({}, "", path); + if (this.onRouteChange) { + this.onRouteChange(path); + } + } + + setOnRouteChange(callback: (path: string) => void) { + this.onRouteChange = callback; + + if (!this.popstateListener) { + this.popstateListener = () => { + if (this.onRouteChange) { + this.onRouteChange(window.location.pathname); + } + }; + window.addEventListener("popstate", this.popstateListener); + } + + return () => { + if (this.popstateListener) { + window.removeEventListener("popstate", this.popstateListener); + this.popstateListener = null; + } + }; + } + + getCurrentPath(): string { + return window.location.pathname; + } + + setBaseDomain(domain: string) { + this.baseDomain = domain; + } + + getSubdomain(): string | null { + const hostname = window.location.hostname; + + if (hostname === "localhost" || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) { + return null; + } + + const base = this.baseDomain || this.#inferBaseDomain(hostname); + if (!base || hostname === base) { + return null; + } + + const suffix = "." + base; + if (hostname.endsWith(suffix)) { + return hostname.slice(0, -suffix.length); + } + + return null; + } + + #inferBaseDomain(hostname: string): string { + const parts = hostname.split("."); + if (parts.length <= 2) { + return hostname; + } + return parts.slice(-2).join("."); + } + + resolveModule(routes: RouteDefinition[]): string | null { + const subdomain = this.getSubdomain(); + const path = this.getCurrentPath(); + + if (subdomain) { + const subdomainRoute = routes.find((r) => r.subdomain === subdomain); + if (subdomainRoute) { + return subdomainRoute.module; + } + } + + const pathRoute = routes.find((r) => r.path === path); + if (pathRoute) { + return pathRoute.module; + } + + const defaultRoute = routes.find((r) => r.path === "/"); + return defaultRoute?.module || null; + } +} + +export const router = new Router(); + diff --git a/src/apps/public/00-adc-ui-library/utils/tailwind-preset.js b/src/apps/public/00-adc-ui-library/utils/tailwind-preset.js new file mode 100644 index 00000000..c91b1bc4 --- /dev/null +++ b/src/apps/public/00-adc-ui-library/utils/tailwind-preset.js @@ -0,0 +1,113 @@ +/** + * Tailwind CSS Preset para ADC Platform UI Library + * + * Este preset combina los colores y utilidades de la comunidad ADC + * con los estilos corporativos de la plataforma. + * + * Los módulos que usan esta librería pueden extender este preset + * para mantener consistencia visual. + */ + +/** @type {import('tailwindcss').Config} */ +export default { + theme: { + extend: { + colors: { + // Colores dinámicos via CSS Variables (de temp-ui) + primary: "rgb(var(--c-primary) / )", + accent: "rgb(var(--c-accent) / )", + text: "rgb(var(--c-text) / )", + button: "rgb(var(--c-button) / )", + alt: "rgb(var(--c-alt) / )", + + // Colores corporativos ADC Platform (fijos) + "adc-primary": { + 50: "#eff6ff", + 100: "#dbeafe", + 200: "#bfdbfe", + 300: "#93c5fd", + 400: "#60a5fa", + 500: "#0066cc", + 600: "#0052a3", + 700: "#003d7a", + 800: "#002952", + 900: "#001429", + }, + "adc-success": { + 50: "#ecfdf5", + 100: "#d1fae5", + 200: "#a7f3d0", + 300: "#6ee7b7", + 400: "#34d399", + 500: "#10b981", + 600: "#059669", + 700: "#047857", + 800: "#065f46", + 900: "#064e3b", + }, + "adc-warning": { + 50: "#fffbeb", + 100: "#fef3c7", + 200: "#fde68a", + 300: "#fcd34d", + 400: "#fbbf24", + 500: "#f59e0b", + 600: "#d97706", + 700: "#b45309", + 800: "#92400e", + 900: "#78350f", + }, + "adc-danger": { + 50: "#fef2f2", + 100: "#fee2e2", + 200: "#fecaca", + 300: "#fca5a5", + 400: "#f87171", + 500: "#ef4444", + 600: "#dc2626", + 700: "#b91c1c", + 800: "#991b1b", + 900: "#7f1d1d", + }, + }, + fontFamily: { + heading: ["Fredoka", "sans-serif"], + text: ["Inter", "system-ui", "sans-serif"], + sans: ["system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "sans-serif"], + }, + spacing: { + "adc-sm": "0.5rem", + "adc-md": "1rem", + "adc-lg": "1.5rem", + "adc-xl": "2rem", + }, + borderRadius: { + xxl: "16px", + adc: "0.375rem", + }, + boxShadow: { + cozy: "0 8px 24px rgba(0,0,0,.08)", + }, + animation: { + "fade-in": "fadeIn 0.3s ease-in-out", + "slide-in": "slideIn 0.3s ease-out", + "bounce-soft": "bounceSoft 1s ease-in-out infinite", + }, + keyframes: { + fadeIn: { + "0%": { opacity: "0", transform: "translateY(-10px)" }, + "100%": { opacity: "1", transform: "translateY(0)" }, + }, + slideIn: { + "0%": { opacity: "0", transform: "translateX(-10px)" }, + "100%": { opacity: "1", transform: "translateX(0)" }, + }, + bounceSoft: { + "0%, 100%": { transform: "translateY(0)" }, + "50%": { transform: "translateY(-10px)" }, + }, + }, + }, + }, + plugins: [], +}; diff --git a/src/apps/public/adc-layout/config.json b/src/apps/public/adc-layout/config.json new file mode 100644 index 00000000..de834eb9 --- /dev/null +++ b/src/apps/public/adc-layout/config.json @@ -0,0 +1,22 @@ +{ + "uiModule": { + "name": "adc-layout", + "uiNamespace": "adc-platform", + "framework": "react", + "outputDir": "dist-ui", + "isHost": true, + "isRemote": false, + "uiDependencies": ["adc-ui-library", "community-home"], + "devPort": 3011, + "sharedLibs": ["react", "tailwind"], + "i18n": true, + "hosting": { + "hosts": [ + { + "domain": "adigitalcafe.com", + "subdomains": ["*"] + } + ] + } + } +} diff --git a/src/apps/public/adc-layout/i18n/en.js b/src/apps/public/adc-layout/i18n/en.js new file mode 100644 index 00000000..a3fe4729 --- /dev/null +++ b/src/apps/public/adc-layout/i18n/en.js @@ -0,0 +1,7 @@ +export default { + articles: "Articles", + paths: "Paths", + login: "Login", + logout: "Logout", + loading: "Loading...", +}; diff --git a/src/apps/public/adc-layout/i18n/es.js b/src/apps/public/adc-layout/i18n/es.js new file mode 100644 index 00000000..91552259 --- /dev/null +++ b/src/apps/public/adc-layout/i18n/es.js @@ -0,0 +1,7 @@ +export default { + articles: "Artículos", + paths: "Paths", + login: "Login", + logout: "Logout", + loading: "Cargando...", +}; diff --git a/src/apps/public/adc-layout/index.html b/src/apps/public/adc-layout/index.html new file mode 100644 index 00000000..c248c521 --- /dev/null +++ b/src/apps/public/adc-layout/index.html @@ -0,0 +1,15 @@ + + + + + + Adc layout + + + +
    + + + diff --git a/src/apps/public/adc-layout/index.ts b/src/apps/public/adc-layout/index.ts new file mode 100644 index 00000000..74f4a14f --- /dev/null +++ b/src/apps/public/adc-layout/index.ts @@ -0,0 +1,10 @@ +import { BaseApp } from "../../BaseApp.js"; + +/** + * ADC Layout - Shell principal que contiene otras apps de la comunidad + */ +export default class AdcLayoutApp extends BaseApp { + async run() { + this.logger.logOk(`${this.name} ejecutándose`); + } +} diff --git a/src/apps/public/adc-layout/src/App.tsx b/src/apps/public/adc-layout/src/App.tsx new file mode 100644 index 00000000..e63f42aa --- /dev/null +++ b/src/apps/public/adc-layout/src/App.tsx @@ -0,0 +1,102 @@ +import { createElement, useState, useEffect, useRef } from "react"; +import { Shell } from "./components/Shell.tsx"; +import { router, type RouteDefinition } from "@ui-library/utils/router"; +import { loadRemoteComponent, type Framework } from "@adc/utils/react/loadRemoteComponent"; + +interface ModuleDefinition { + framework: Framework; + importFn: () => Promise; +} + +const moduleDefinitions: Record = { + "community-home": { + framework: "react", + importFn: () => import("community-home/App" as any), + }, +}; + +const routes: RouteDefinition[] = [{ module: "community-home", path: "/" }]; + +export default function App() { + const [renderKey, setRenderKey] = useState(0); + const [currentPath, setCurrentPath] = useState(window.location.pathname); + const [moduleData, setModuleData] = useState(null); + const [loading, setLoading] = useState(true); + const loadingPathRef = useRef(null); + const isInitialized = useRef(false); + + const getNavPath = (): string => { + const subdomain = router.getSubdomain(); + if (subdomain) { + const subdomainRoute = routes.find((r) => r.subdomain === subdomain); + if (subdomainRoute?.path) { + return subdomainRoute.path; + } + } + return window.location.pathname; + }; + + useEffect(() => { + if (isInitialized.current) return; + isInitialized.current = true; + + async function loadComponent(path: string) { + if (loadingPathRef.current === path) return; + + const moduleName = router.resolveModule(routes); + + if (!moduleName || !moduleDefinitions[moduleName]) { + console.warn("[ADC Layout] Ruta no reconocida:", path); + setModuleData({ + Component: () =>
    Página no encontrada: {path}
    , + moduleName: "not-found", + timestamp: Date.now(), + }); + setLoading(false); + return; + } + + loadingPathRef.current = path; + setLoading(true); + + await new Promise((resolve) => setTimeout(resolve, 10)); + + const definition = moduleDefinitions[moduleName]; + const data = await loadRemoteComponent({ + importFn: definition.importFn, + moduleName, + framework: definition.framework, + }); + + console.log(`[ADC Layout] ✅ ${data.moduleName} @ ${path}`); + + setCurrentPath(getNavPath()); + setModuleData(data); + setRenderKey((prev) => prev + 1); + setLoading(false); + loadingPathRef.current = null; + } + + loadComponent(window.location.pathname); + router.setOnRouteChange((path: string) => { + console.log("[ADC Layout] 🔄 Route change:", path); + loadComponent(path); + }); + }, []); + + if (!moduleData || loading) { + return ( + +
    +

    Cargando...

    +
    +
    + ); + } + + return ( + + {createElement(moduleData.Component)} + + ); +} diff --git a/src/apps/public/adc-layout/src/components/Shell.tsx b/src/apps/public/adc-layout/src/components/Shell.tsx new file mode 100644 index 00000000..c0b6d42f --- /dev/null +++ b/src/apps/public/adc-layout/src/components/Shell.tsx @@ -0,0 +1,95 @@ +import React, { memo, useCallback, useState, useEffect } from "react"; + +interface ShellProps { + children: React.ReactNode; + currentPath: string; +} + +export const Shell = memo(function Shell({ children, currentPath }: ShellProps) { + const [showConsentBanner, setShowConsentBanner] = useState(false); + + useEffect(() => { + checkConsent(); + }, []); + + const checkConsent = () => { + try { + const consent = localStorage.getItem("consent"); + if (!consent) { + setShowConsentBanner(true); + } + } catch { + // Ignore localStorage errors + } + }; + + const handleOpenPrivacyPreferences = useCallback(() => { + setShowConsentBanner(true); + }, []); + + const handleConsentAcceptAll = useCallback(() => { + localStorage.setItem("consent", JSON.stringify({ analytics: true, ads: true })); + setShowConsentBanner(false); + }, []); + + const handleConsentDecline = useCallback(() => { + localStorage.setItem("consent", JSON.stringify({ analytics: false, ads: false })); + setShowConsentBanner(false); + }, []); + + return ( +
    + + + + +
    {children}
    + + + + Política de Privacidad + + + + Términos y Condiciones + + + + Política de Cookies + + + + setShowConsentBanner(false)} + > +
    + ); +}); diff --git a/src/apps/public/adc-layout/src/main.tsx b/src/apps/public/adc-layout/src/main.tsx new file mode 100644 index 00000000..d000d1ae --- /dev/null +++ b/src/apps/public/adc-layout/src/main.tsx @@ -0,0 +1,16 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import App from "./App.tsx"; +import "@ui-library"; // Auto-registra Web Components +import "@ui-library/styles"; // CSS base de la UI Library +import "./styles/tailwind.css"; // Extensiones locales + +const container = document.getElementById("root"); +if (container) { + const root = createRoot(container); + root.render( + + + + ); +} diff --git a/src/apps/public/adc-layout/src/styles/tailwind.css b/src/apps/public/adc-layout/src/styles/tailwind.css new file mode 100644 index 00000000..dc8b9daf --- /dev/null +++ b/src/apps/public/adc-layout/src/styles/tailwind.css @@ -0,0 +1,7 @@ +/** + * Tailwind CSS - Extensiones para ADC Layout + * El CSS base viene de @ui-library/styles + */ +@import "tailwindcss"; + +/* Extensiones específicas del layout (si las hay) */ diff --git a/src/apps/public/adc-layout/src/types.d.ts b/src/apps/public/adc-layout/src/types.d.ts new file mode 100644 index 00000000..666e93ea --- /dev/null +++ b/src/apps/public/adc-layout/src/types.d.ts @@ -0,0 +1,47 @@ +declare module "*.css" { + const content: string; + export default content; +} + +declare namespace JSX { + interface IntrinsicElements { + // Organisms + "adc-site-header": any; + "adc-site-footer": any; + "adc-consent-banner": any; + "adc-blocks-renderer": any; + // Molecules + "adc-dropdown-menu": any; + "adc-feature-card": any; + "adc-share-buttons": any; + "adc-testimonial-card": any; + // Atoms + "adc-button": any; + "adc-button-rounded": any; + "adc-input": any; + "adc-select": any; + "adc-callout": any; + "adc-code-block": any; + "adc-divider": any; + "adc-inline-tokens": any; + "adc-list-block": any; + "adc-lp-badge": any; + "adc-quote": any; + "adc-search-input": any; + "adc-star-rating": any; + "adc-table-block": any; + "adc-text": any; + // Icons + "adc-icon-community": any; + "adc-icon-learning": any; + "adc-icon-left-arrow": any; + "adc-icon-logout": any; + "adc-icon-nitro": any; + "adc-icon-opensource": any; + "adc-icon-pencil": any; + "adc-icon-vip": any; + } +} + +declare module "@ui-library"; +declare module "@ui-library/styles"; diff --git a/src/apps/public/adc-layout/tsconfig.json b/src/apps/public/adc-layout/tsconfig.json new file mode 100644 index 00000000..09ed37c2 --- /dev/null +++ b/src/apps/public/adc-layout/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "paths": { + "@adc/utils/*": ["./../../../utils/*"], + "@ui-library/utils/*": ["./../00-adc-ui-library/utils/*"], + "@ui-library/*": ["./../00-adc-ui-library/src/*"] + } + }, + "include": ["src/**/*", "*.ts"] +} diff --git a/src/apps/public/community-home/config.json b/src/apps/public/community-home/config.json new file mode 100644 index 00000000..1782f35c --- /dev/null +++ b/src/apps/public/community-home/config.json @@ -0,0 +1,14 @@ +{ + "uiModule": { + "name": "community-home", + "uiNamespace": "adc-platform", + "framework": "react", + "outputDir": "dist-ui", + "isHost": false, + "isRemote": true, + "uiDependencies": ["adc-ui-library"], + "devPort": 3010, + "sharedLibs": ["react", "tailwind"], + "i18n": true + } +} diff --git a/src/apps/public/community-home/i18n/en.js b/src/apps/public/community-home/i18n/en.js new file mode 100644 index 00000000..2148e2d8 --- /dev/null +++ b/src/apps/public/community-home/i18n/en.js @@ -0,0 +1,9 @@ +export default { + welcome: "Welcome to the Community", + learn: "Learn", + learnDesc: "Explore our educational resources and learning paths.", + community: "Community", + communityDesc: "Connect with other members and share experiences.", + openSource: "Open Source", + openSourceDesc: "Contribute to open source projects.", +}; diff --git a/src/apps/public/community-home/i18n/es.js b/src/apps/public/community-home/i18n/es.js new file mode 100644 index 00000000..afcc21d4 --- /dev/null +++ b/src/apps/public/community-home/i18n/es.js @@ -0,0 +1,9 @@ +export default { + welcome: "Bienvenido a la Comunidad", + learn: "Aprende", + learnDesc: "Explora nuestros recursos educativos y rutas de aprendizaje.", + community: "Comunidad", + communityDesc: "Conecta con otros miembros y comparte experiencias.", + openSource: "Open Source", + openSourceDesc: "Contribuye a proyectos de código abierto.", +}; diff --git a/src/apps/public/community-home/index.html b/src/apps/public/community-home/index.html new file mode 100644 index 00000000..b5783705 --- /dev/null +++ b/src/apps/public/community-home/index.html @@ -0,0 +1,15 @@ + + + + + + Community home + + + +
    + + + diff --git a/src/apps/public/community-home/index.ts b/src/apps/public/community-home/index.ts new file mode 100644 index 00000000..301fa233 --- /dev/null +++ b/src/apps/public/community-home/index.ts @@ -0,0 +1,10 @@ +import { BaseApp } from "../../BaseApp.js"; + +/** + * Community Home - Página principal de la comunidad ADC + */ +export default class CommunityHomeApp extends BaseApp { + async run() { + this.logger.logOk(`${this.name} ejecutándose`); + } +} diff --git a/src/apps/public/community-home/src/App.tsx b/src/apps/public/community-home/src/App.tsx new file mode 100644 index 00000000..cb7d8b20 --- /dev/null +++ b/src/apps/public/community-home/src/App.tsx @@ -0,0 +1,120 @@ +import { useEffect, useState } from "react"; + +const BRAND = { + name: "Abby's Digital Cafe", + discordVanity: "vShXpyWTTq", + description: + "Abby's Digital Cafe es una comunidad destinada a programadores y estudiantes, enfocada en aprender nuevas tecnologías y compartir código de forma libre 🧡", + slogan: "Una taza de código con tintes de amistad", +}; + +const DESCRIPTION = + "Somos una comunidad digital donde compartimos conocimiento y código abierto con buen café. El objetivo es ofrecer trabajos gratis (hablar con abbytec en Discord) siempre que podamos compartir el proceso de creación en stream, GitHub y videos, o animar a tus estudiantes a proponer modificaciones (PRs). (Para proyectos pagos, también pueden consultar precios por privado.)"; + +interface Props { + locale?: string; +} + +export default function App({ locale = "es" }: Props) { + const [mounted, setMounted] = useState(false); + + useEffect(() => { + setMounted(true); + }, []); + + if (!mounted) { + return
    Cargando...
    ; + } + + return ( +
    +
    +

    {BRAND.name}

    +

    {DESCRIPTION}

    + +

    🧡 Únete a nuestro servidor de discord 🧡

    + Trae tu taza y comparte código con nosotr@s. + + Entrar al Discord + + + {BRAND.slogan} +
    + +
    + + + + + Espacio para compartir y apoyarnos mutuamente. + + + + + + Contenido claro para crecer paso a paso. + + + + + + Proyectos libres para colaborar y aprender. + +
    + +
    +

    Durante tu sesión de código: Cozy Beats

    + Música lofi para acompañar tus sesiones de código. +
    + +
    +
    + +
    + + Buena comunidad activa para la gente que hay. Se disfruta, únanse. (desde Discord) + + + Eehh. No sé. :xd: Mentira, "Cuando no sepas que hacer o donde ir, recuerda que un café + caliente soluciona muchos dolores de cabeza, únete al café digital de Abby." + + + Gran comunidad para programar y relajarse. + +
    + +
    +

    Nuestras redes

    +
    + Discord + Twitch + YouTube + Instagram + Donaciones +
    +
    +
    + ); +} diff --git a/src/apps/public/community-home/src/main.tsx b/src/apps/public/community-home/src/main.tsx new file mode 100644 index 00000000..d000d1ae --- /dev/null +++ b/src/apps/public/community-home/src/main.tsx @@ -0,0 +1,16 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import App from "./App.tsx"; +import "@ui-library"; // Auto-registra Web Components +import "@ui-library/styles"; // CSS base de la UI Library +import "./styles/tailwind.css"; // Extensiones locales + +const container = document.getElementById("root"); +if (container) { + const root = createRoot(container); + root.render( + + + + ); +} diff --git a/src/apps/public/community-home/src/styles/tailwind.css b/src/apps/public/community-home/src/styles/tailwind.css new file mode 100644 index 00000000..c5a207ce --- /dev/null +++ b/src/apps/public/community-home/src/styles/tailwind.css @@ -0,0 +1,7 @@ +/** + * Tailwind CSS - Extensiones para Community Home + * El CSS base viene de @ui-library/styles + */ +@import "tailwindcss"; + +/* Extensiones específicas de community-home (si las hay) */ diff --git a/src/apps/public/community-home/src/types.d.ts b/src/apps/public/community-home/src/types.d.ts new file mode 100644 index 00000000..666e93ea --- /dev/null +++ b/src/apps/public/community-home/src/types.d.ts @@ -0,0 +1,47 @@ +declare module "*.css" { + const content: string; + export default content; +} + +declare namespace JSX { + interface IntrinsicElements { + // Organisms + "adc-site-header": any; + "adc-site-footer": any; + "adc-consent-banner": any; + "adc-blocks-renderer": any; + // Molecules + "adc-dropdown-menu": any; + "adc-feature-card": any; + "adc-share-buttons": any; + "adc-testimonial-card": any; + // Atoms + "adc-button": any; + "adc-button-rounded": any; + "adc-input": any; + "adc-select": any; + "adc-callout": any; + "adc-code-block": any; + "adc-divider": any; + "adc-inline-tokens": any; + "adc-list-block": any; + "adc-lp-badge": any; + "adc-quote": any; + "adc-search-input": any; + "adc-star-rating": any; + "adc-table-block": any; + "adc-text": any; + // Icons + "adc-icon-community": any; + "adc-icon-learning": any; + "adc-icon-left-arrow": any; + "adc-icon-logout": any; + "adc-icon-nitro": any; + "adc-icon-opensource": any; + "adc-icon-pencil": any; + "adc-icon-vip": any; + } +} + +declare module "@ui-library"; +declare module "@ui-library/styles"; diff --git a/src/apps/public/community-home/tsconfig.json b/src/apps/public/community-home/tsconfig.json new file mode 100644 index 00000000..09ed37c2 --- /dev/null +++ b/src/apps/public/community-home/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "paths": { + "@adc/utils/*": ["./../../../utils/*"], + "@ui-library/utils/*": ["./../00-adc-ui-library/utils/*"], + "@ui-library/*": ["./../00-adc-ui-library/src/*"] + } + }, + "include": ["src/**/*", "*.ts"] +} diff --git a/src/apps/test/00-web-ui-library-mobile/config.json b/src/apps/test/00-web-ui-library-mobile/config.json index d2d6629d..670d37ae 100644 --- a/src/apps/test/00-web-ui-library-mobile/config.json +++ b/src/apps/test/00-web-ui-library-mobile/config.json @@ -4,7 +4,6 @@ "uiNamespace": "mobile", "framework": "stencil", "outputDir": "dist-ui", - "standalone": false, "exports": { "loader": "./loader", "utils": "./utils" diff --git a/src/apps/test/00-web-ui-library-mobile/stencil.config.ts b/src/apps/test/00-web-ui-library-mobile/stencil.config.ts index 98c6b05c..57b55daf 100644 --- a/src/apps/test/00-web-ui-library-mobile/stencil.config.ts +++ b/src/apps/test/00-web-ui-library-mobile/stencil.config.ts @@ -7,23 +7,20 @@ import { Config } from '@stencil/core'; * Los componentes usan CSS puro (compatible con Shadow DOM). */ export const config: Config = { - namespace: 'web-ui-library-mobile', - cacheDir: '../../../../temp/stencil-cache/mobile/web-ui-library-mobile', - outputTargets: [ - { - type: 'dist', - dir: '../../../../temp/ui-builds/mobile/web-ui-library-mobile', - }, - { - type: 'dist-custom-elements', - dir: '../../../../temp/ui-builds/mobile/web-ui-library-mobile/custom-elements', - customElementsExportBehavior: 'auto-define-custom-elements', - externalRuntime: false, - }, - { - type: 'docs-readme', - }, - ], - sourceMap: true, - buildEs5: false, + namespace: 'web-ui-library-mobile', + cacheDir: '../../../../temp/stencil-cache/mobile/web-ui-library-mobile', + outputTargets: [ + { + type: 'dist', + dir: '../../../../temp/ui-builds/mobile/web-ui-library-mobile', + }, + { + type: 'dist-custom-elements', + dir: '../../../../temp/ui-builds/mobile/web-ui-library-mobile/custom-elements', + customElementsExportBehavior: 'auto-define-custom-elements', + externalRuntime: true, + }, + ], + sourceMap: true, + buildEs5: false, }; diff --git a/src/apps/test/00-web-ui-library/README.md b/src/apps/test/00-web-ui-library/README.md new file mode 100644 index 00000000..61d954d2 --- /dev/null +++ b/src/apps/test/00-web-ui-library/README.md @@ -0,0 +1,13 @@ +# Web UI Library + +Web Components (Stencil) para el namespace `default` (desarrollo). + +## Uso +```typescript +import "@ui-library"; // Auto-registra componentes +import "@ui-library/styles"; // CSS base +import "./styles/tailwind.css"; // Extensiones locales +``` + +## Componentes +``, ``, ``, ``, etc. diff --git a/src/apps/test/00-web-ui-library/config.json b/src/apps/test/00-web-ui-library/config.json index cc2289f4..9c0ad1c7 100644 --- a/src/apps/test/00-web-ui-library/config.json +++ b/src/apps/test/00-web-ui-library/config.json @@ -3,7 +3,6 @@ "name": "web-ui-library", "framework": "stencil", "outputDir": "dist-ui", - "standalone": false, "exports": { "loader": "./loader", "utils": "./utils", diff --git a/src/apps/test/00-web-ui-library/src/components/adc-stat-card/adc-stat-card.css b/src/apps/test/00-web-ui-library/src/components/adc-stat-card/adc-stat-card.css index a358bede..544c5435 100644 --- a/src/apps/test/00-web-ui-library/src/components/adc-stat-card/adc-stat-card.css +++ b/src/apps/test/00-web-ui-library/src/components/adc-stat-card/adc-stat-card.css @@ -27,6 +27,10 @@ color: #2563eb; } +.stat-value--secondary { + color: #805ad5; +} + .stat-value--success { color: #10b981; } diff --git a/src/apps/test/00-web-ui-library/stencil.config.ts b/src/apps/test/00-web-ui-library/stencil.config.ts index d7d4e4e9..b11e66e5 100644 --- a/src/apps/test/00-web-ui-library/stencil.config.ts +++ b/src/apps/test/00-web-ui-library/stencil.config.ts @@ -7,23 +7,20 @@ import { Config } from '@stencil/core'; * Los componentes usan CSS puro (compatible con Shadow DOM). */ export const config: Config = { - namespace: 'web-ui-library', - cacheDir: '../../../../temp/stencil-cache/default/web-ui-library', - outputTargets: [ - { - type: 'dist', - dir: '../../../../temp/ui-builds/default/web-ui-library', - }, - { - type: 'dist-custom-elements', - dir: '../../../../temp/ui-builds/default/web-ui-library/custom-elements', - customElementsExportBehavior: 'auto-define-custom-elements', - externalRuntime: false, - }, - { - type: 'docs-readme', - }, - ], - sourceMap: true, - buildEs5: false, + namespace: 'web-ui-library', + cacheDir: '../../../../temp/stencil-cache/default/web-ui-library', + outputTargets: [ + { + type: 'dist', + dir: '../../../../temp/ui-builds/default/web-ui-library', + }, + { + type: 'dist-custom-elements', + dir: '../../../../temp/ui-builds/default/web-ui-library/custom-elements', + customElementsExportBehavior: 'auto-define-custom-elements', + externalRuntime: true, + }, + ], + sourceMap: true, + buildEs5: false, }; diff --git a/src/apps/test/users-management/config.json b/src/apps/test/users-management/config.json index b2c2e4ec..0cc3af7f 100644 --- a/src/apps/test/users-management/config.json +++ b/src/apps/test/users-management/config.json @@ -4,7 +4,8 @@ "name": "users-management", "framework": "react", "outputDir": "dist-ui", - "standalone": true, + "isHost": true, + "isRemote": false, "devPort": 3001, "sharedLibs": ["react"], "hosting": { diff --git a/src/apps/test/users-management/src/App.tsx b/src/apps/test/users-management/src/App.tsx index 5e07a7c6..7adaa6bf 100644 --- a/src/apps/test/users-management/src/App.tsx +++ b/src/apps/test/users-management/src/App.tsx @@ -1,5 +1,3 @@ -import "@ui-library/loader"; - export default function App() { const handleCreateUser = () => { console.log("Crear usuario"); diff --git a/src/apps/test/users-management/src/main.tsx b/src/apps/test/users-management/src/main.tsx index 9ec176d4..32a1e315 100644 --- a/src/apps/test/users-management/src/main.tsx +++ b/src/apps/test/users-management/src/main.tsx @@ -1,13 +1,15 @@ -import React from 'react'; -import { createRoot } from 'react-dom/client'; -import App from './App.tsx'; +import React from "react"; +import { createRoot } from "react-dom/client"; +import App from "./App.tsx"; +import "@ui-library"; +import "@ui-library/styles"; -const container = document.getElementById('root'); +const container = document.getElementById("root"); if (container) { - const root = createRoot(container); - root.render( - - - - ); + const root = createRoot(container); + root.render( + + + + ); } diff --git a/src/apps/test/web-config/config.json b/src/apps/test/web-config/config.json index df733e8f..0559baf9 100644 --- a/src/apps/test/web-config/config.json +++ b/src/apps/test/web-config/config.json @@ -4,7 +4,8 @@ "framework": "vue", "outputDir": "dist-ui", "devPort": 3003, - "standalone": true, + "isHost": true, + "isRemote": false, "sharedLibs": ["vue"], "hosting": { "hosts": [ diff --git a/src/apps/test/web-config/src/App.vue b/src/apps/test/web-config/src/App.vue index c9d09066..f638d673 100644 --- a/src/apps/test/web-config/src/App.vue +++ b/src/apps/test/web-config/src/App.vue @@ -41,12 +41,12 @@ @@ -55,7 +55,6 @@