This commit is contained in:
2026-03-26 11:10:56 +01:00
parent 390fe3857d
commit cbde05fd21
7 changed files with 270 additions and 5 deletions

View File

@@ -20,6 +20,7 @@
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"daisyui": "^5.5.19", "daisyui": "^5.5.19",
"tailwindcss": "^4.2.1", "tailwindcss": "^4.2.1",
"terser": "^5.46.1",
"vite": "^8.0.0", "vite": "^8.0.0",
}, },
}, },
@@ -147,6 +148,8 @@
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
@@ -247,6 +250,8 @@
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
@@ -255,7 +260,7 @@
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
"concurrently": ["concurrently@9.2.1", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.8.3", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng=="], "concurrently": ["concurrently@9.2.1", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.8.3", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng=="],
@@ -389,8 +394,12 @@
"shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="], "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
@@ -405,6 +414,8 @@
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
"terser": ["terser@5.46.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ=="],
"tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="],
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
@@ -445,6 +456,8 @@
"csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],
"svgo/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
"@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], "@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
"@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], "@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],

View File

@@ -11,7 +11,8 @@
"start": "concurrently \"bun dev\" \"bun dev:srv\"", "start": "concurrently \"bun dev\" \"bun dev:srv\"",
"build": "vite build", "build": "vite build",
"build:server": "bun build ./server/index.js --target bun --outdir ./dist-server", "build:server": "bun build ./server/index.js --target bun --outdir ./dist-server",
"preview": "vite preview" "preview": "vite preview",
"build:aggrid": "vite build --config src/aggrid/vite.config.js"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.2.1", "@tailwindcss/vite": "^4.2.1",
@@ -29,6 +30,7 @@
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"daisyui": "^5.5.19", "daisyui": "^5.5.19",
"tailwindcss": "^4.2.1", "tailwindcss": "^4.2.1",
"terser": "^5.46.1",
"vite": "^8.0.0" "vite": "^8.0.0"
} }
} }

View File

@@ -95,6 +95,7 @@ export const App = () => {
const menuItems = [ const menuItems = [
{ label: "Inicio", onclick: () => $.go("/") }, { label: "Inicio", onclick: () => $.go("/") },
{ label: "Mi Perfil", onclick: () => $.go("/profile/42") }, { label: "Mi Perfil", onclick: () => $.go("/profile/42") },
{ label: "Tareas TODO", onclick: () => $.go("/todo") }, // <-- Nueva opción
{ label: "Ajustes", onclick: () => Toast("Ajustes no disponibles", "alert-error") }, { label: "Ajustes", onclick: () => Toast("Ajustes no disponibles", "alert-error") },
]; ];
@@ -132,6 +133,7 @@ export const App = () => {
$.router([ $.router([
{ path: "/", component: Home }, { path: "/", component: Home },
{ path: "/profile/:id", component: Profile }, { path: "/profile/:id", component: Profile },
{ path: "/todo", component: TodoPage },
{ {
path: "*", path: "*",
component: () => component: () =>
@@ -145,3 +147,87 @@ export const App = () => {
Footer({ class: "footer footer-center p-4 bg-base-300 text-base-content text-xs" }, [P("© 2026 - Built with SigPro Engine")]), Footer({ class: "footer footer-center p-4 bg-base-300 text-base-content text-xs" }, [P("© 2026 - Built with SigPro Engine")]),
]); ]);
}; };
const TodoPage = () => {
const newTask = $("");
// Persistencia automática en localStorage gracias a tu Core
const tasks = $([], "sigpro-todo-list");
const addTask = () => {
const val = newTask().trim();
if (!val) return Toast("Escribe algo...", "alert-warning");
tasks([...tasks(), { id: crypto.randomUUID(), text: val, done: false }]);
newTask(""); // Limpia el input
};
const removeTask = (id) => {
tasks(tasks().filter((t) => t.id !== id));
};
const toggleTask = (id) => {
tasks(tasks().map((t) => (t.id === id ? { ...t, done: !t.done } : t)));
};
// Señal computada para el contador
const pendingCount = $(() => tasks().filter((t) => !t.done).length);
const misDatos = $([{ id: 1 }]);
return Div({ class: "max-w-md mx-auto space-y-6" }, [
Div(Json(misDatos())),
H1({ class: "text-3xl font-black italic" }, "TODO LIST"),
// Input Group
Div({ class: "join w-full" }, [
Input({
class: "join-item w-full",
placeholder: "Nueva tarea...",
$value: newTask,
onkeydown: (e) => e.key === "Enter" && addTask(),
}),
Button({ class: "btn-primary join-item", onclick: addTask }, "Añadir"),
]),
// Stats
Div({ class: "flex justify-between items-center opacity-70 text-sm" }, [
Span(() => `Total: ${tasks().length}`),
Span({ class: "badge badge-secondary" }, () => `${pendingCount()} pendientes`),
]),
// Lista Reactiva (Aquí evaluamos tu append con sweep)
Ul({ class: "menu bg-base-200 rounded-box w-full p-2" }, () =>
tasks().length === 0
? Li({ class: "p-4 text-center opacity-50" }, "No hay tareas pendientes")
: tasks().map((task) =>
Li({ class: "flex flex-row items-center gap-2 p-2 border-b border-base-300 last:border-0" }, [
CheckBox({
class: "checkbox-sm",
$value: () => task.done,
onclick: () => toggleTask(task.id),
}),
Span(
{
class: `flex-1 ${task.done ? "line-through opacity-40" : ""}`,
onclick: () => toggleTask(task.id),
},
task.text,
),
Button(
{
class: "btn-ghost btn-xs text-error",
onclick: () => removeTask(task.id),
},
"✕",
),
]),
),
),
Button(
{
class: "btn-link btn-xs text-error p-0",
onclick: () => tasks([]),
},
"Limpiar todo",
),
]);
};

68
src/aggrid/aggrid-lib.js Normal file
View File

@@ -0,0 +1,68 @@
import {
createGrid,
ModuleRegistry,
ValidationModule,
ColumnAutoSizeModule,
CellStyleModule,
QuickFilterModule,
RowSelectionModule,
TextEditorModule,
ClientSideRowModelModule,
themeQuartz,
iconSetQuartzLight,
} from "ag-grid-community";
import {
MultiFilterModule,
CellSelectionModule,
PivotModule,
MasterDetailModule,
SideBarModule,
ColumnsToolPanelModule,
ColumnMenuModule,
StatusBarModule,
ExcelExportModule,
ClipboardModule,
} from "ag-grid-enterprise";
// Registro único de módulos
ModuleRegistry.registerModules([
ValidationModule,
ColumnAutoSizeModule,
CellStyleModule,
QuickFilterModule,
RowSelectionModule,
TextEditorModule,
ClientSideRowModelModule,
MultiFilterModule,
CellSelectionModule,
PivotModule,
MasterDetailModule,
SideBarModule,
ColumnsToolPanelModule,
ColumnMenuModule,
StatusBarModule,
ExcelExportModule,
ClipboardModule,
]);
// Helper de tema exportado
export const getAgTheme = (isDark) =>
themeQuartz.withPart(iconSetQuartzLight).withParams({
browserColorScheme: isDark ? "dark" : "light",
backgroundColor: isDark ? "#121212" : "#FDFDFD",
foregroundColor: isDark ? "#E0E0E0" : "#181D1F",
accentColor: isDark ? "#4FAAFF" : "#004B9C",
headerBackgroundColor: isDark ? "#2A2A2A" : "#EEB111",
headerTextColor: isDark ? "#4FAAFF" : "#004B9C",
borderRadius: 4,
columnBorder: false,
headerFontSize: 14,
headerFontWeight: 600,
listItemHeight: 20,
iconSize: 14,
spacing: 3,
wrapperBorderRadius: 4,
});
export { createGrid };

1
src/aggrid/aggrid.js Normal file

File diff suppressed because one or more lines are too long

31
src/aggrid/vite.config.js Normal file
View File

@@ -0,0 +1,31 @@
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
import { resolve } from "path";
import path from "node:path";
const __dirname = path.resolve();
export default defineConfig({
plugins: [tailwindcss()],
build: {
// Usamos la configuración de librería para generar el bundle limpio
lib: {
entry: resolve(__dirname, "./src/aggrid/aggrid-lib.js"),
name: "AgGridBundle",
fileName: "aggrid",
formats: ["es"],
},
outDir: "./dist",
minify: "terser", // Máxima compresión
rollupOptions: {
// Si quieres que ag-grid NO se incluya y sea externo, añádelo aquí.
// Pero como quieres un "Bundle", lo dejamos vacío para que empaquete todo.
external: ["sigpro"],
output: {
globals: {
sigpro: "$",
},
},
},
},
});

View File

@@ -114,6 +114,17 @@ export const UI = ($, defaultLang = "es") => {
return container; return container;
}; };
/** JSON */
ui.Json = (data, space = 2) => {
return Span({ class: "font-mono whitespace-pre-wrap" }, () => {
try {
return JSON.stringify(val(data), null, space);
} catch (e) {
return "[Error: Circular or Invalid JSON]";
}
});
};
/** REQ */ /** REQ */
ui.Request = (url, payload = null, options = {}) => { ui.Request = (url, payload = null, options = {}) => {
const data = $(null), const data = $(null),
@@ -185,7 +196,6 @@ export const UI = ($, defaultLang = "es") => {
/** BUTTON */ /** BUTTON */
ui.Button = (props, children) => { ui.Button = (props, children) => {
const { badge, badgeClass, tooltip, icon, $loading, ...rest } = props; const { badge, badgeClass, tooltip, icon, $loading, ...rest } = props;
const btn = $.html( const btn = $.html(
"button", "button",
{ {
@@ -199,7 +209,6 @@ export const UI = ($, defaultLang = "es") => {
children, children,
], ],
); );
let out = btn; let out = btn;
if (badge) { if (badge) {
out = $.html("div", { class: "indicator" }, [ out = $.html("div", { class: "indicator" }, [
@@ -207,7 +216,6 @@ export const UI = ($, defaultLang = "es") => {
out, out,
]); ]);
} }
return tooltip ? $.html("div", { class: "tooltip", "data-tip": tooltip }, out) : out; return tooltip ? $.html("div", { class: "tooltip", "data-tip": tooltip }, out) : out;
}; };
@@ -746,6 +754,62 @@ export const UI = ($, defaultLang = "es") => {
); );
}; };
/** GRID */
ui.Grid = (props) => {
const { data, options, class: className } = props;
let gridApi = null;
const container = $.html("div", {
style: "height: 100%; width: 100%;",
class: className,
});
const observer = new MutationObserver(() => {
if (gridApi) gridApi.setGridOption("theme", getTheme(isDark()));
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-theme"],
});
container._cleanups.add(() => observer.disconnect());
const stopGrid = $.effect(() => {
const dark = isDark();
const agTheme = getTheme(dark);
const rowData = val(data) || [];
if (!gridApi) {
gridApi = createGrid(container, {
...(val(options) || {}),
theme: agTheme,
rowData: rowData,
});
} else {
gridApi.setGridOption("theme", agTheme);
}
});
container._cleanups.add(stopGrid);
const stopData = $.effect(() => {
const rowData = val(data);
if (gridApi && Array.isArray(rowData)) {
gridApi.setGridOption("rowData", rowData);
}
});
container._cleanups.add(stopData);
container._cleanups.add(() => {
if (gridApi) {
gridApi.destroy();
gridApi = null;
}
});
return container;
};
/** DROPDOWN */ /** DROPDOWN */
ui.Dropdown = (props, children) => { ui.Dropdown = (props, children) => {
const { label, icon, ...rest } = props; const { label, icon, ...rest } = props;