@zauru-sdk/components 6.9.0 → 6.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [6.10.0](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.9.0...@zauru-sdk/components@6.10.0) (2026-10-05)
7
+
8
+
9
+ ### Features
10
+
11
+ * menú Configuración genérico y extras de asignación fuera del SDK ([2691957](https://github.com/intuitiva/zauru-typescript-sdk/commit/2691957c9dba23226a4b8d371fee26b221e126f0))
12
+
13
+
14
+
15
+
16
+
6
17
  # [6.9.0](https://github.com/intuitiva/zauru-typescript-sdk/compare/@zauru-sdk/components@6.8.3...@zauru-sdk/components@6.9.0) (2026-10-05)
7
18
 
8
19
 
@@ -1,2 +1,2 @@
1
1
  import type { NavBarProps } from "./NavBar.types.js";
2
- export declare const NavBar: ({ title, loggedIn, items, selectedColor, version, reloadCatalogsOption, showDarkModeToggle, }: NavBarProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const NavBar: ({ title, loggedIn, items, selectedColor, version, reloadCatalogsOption, settingsOption, showDarkModeToggle, }: NavBarProps) => import("react/jsx-runtime").JSX.Element;
@@ -17,6 +17,7 @@ export type NavBarProps = {
17
17
  LinkComponent?: any;
18
18
  version?: string;
19
19
  reloadCatalogsOption?: boolean;
20
+ settingsOption?: boolean;
20
21
  showDarkModeToggle?: boolean;
21
22
  };
22
23
  export type NavBarStateProps = {
@@ -0,0 +1,12 @@
1
+ import type { ReactNode } from "react";
2
+ type Props = {
3
+ children: ReactNode;
4
+ showEmployees?: boolean;
5
+ showRoles?: boolean;
6
+ showPermissions?: boolean;
7
+ basePath?: string;
8
+ title?: string;
9
+ description?: string;
10
+ };
11
+ export declare const WebappSettingsChrome: ({ children, showEmployees, showRoles, showPermissions, basePath, title, description, }: Props) => import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -1,3 +1,4 @@
1
1
  export * from "./Tab.js";
2
2
  export * from "./RouteTabNav.js";
3
3
  export * from "./PermissionMatrix.js";
4
+ export * from "./WebappSettingsChrome.js";
@@ -4,9 +4,9 @@ import { DropDownArrowSvgIcon, LogoutDropDownSvgIcon, MenuAlt4Svg, OpcionButtonS
4
4
  import { COLORS } from "./NavBar.utils.js";
5
5
  import { Link, useNavigate, useLocation } from "@remix-run/react";
6
6
  import { useAppSelector } from "@zauru-sdk/redux";
7
- const OptionsDropDownButton = ({ color, options, name }) => {
7
+ const OptionsDropDownButton = ({ color, options, name, ariaLabel, }) => {
8
8
  const [showOptionsMenu, setShowOptionsMenu] = useState(true);
9
- return (_jsx("div", { className: "nav-item ml-auto", children: _jsx("div", { className: "flex justify-center", children: _jsxs("div", { className: "relative inline-block", children: [_jsxs("button", { onClick: () => setShowOptionsMenu(!showOptionsMenu), className: `relative flex cursor-pointer items-center p-2 text-xs text-white ${color.bg700} active:${color.bg900} border border-transparent rounded-full uppercase focus:ring-opacity-40 focus:outline-none`, children: [name ?? _jsx(OpcionButtonSvgIcon, {}), _jsx(DropDownArrowSvgIcon, {})] }), _jsx("div", { className: "absolute right-0 z-20 w-56 py-2 mt-2 overflow-hidden bg-white rounded-md shadow-xl dark:bg-gray-800", hidden: showOptionsMenu, onMouseLeave: () => setShowOptionsMenu(true), children: options.map((option, index) => (_jsx(React.Fragment, { children: option }, index))) })] }) }) }));
9
+ return (_jsx("div", { className: "nav-item ml-auto", children: _jsx("div", { className: "flex justify-center", children: _jsxs("div", { className: "relative inline-block", children: [_jsxs("button", { type: "button", "aria-label": ariaLabel ?? (typeof name === "string" ? name : "Menú"), "aria-haspopup": "menu", "aria-expanded": !showOptionsMenu, onClick: () => setShowOptionsMenu(!showOptionsMenu), className: `relative flex cursor-pointer items-center p-2 text-xs text-white ${color.bg700} active:${color.bg900} border border-transparent rounded-full uppercase focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2`, children: [name ?? _jsx(OpcionButtonSvgIcon, {}), _jsx(DropDownArrowSvgIcon, {})] }), _jsx("div", { className: "absolute right-0 z-20 w-56 py-2 mt-2 overflow-hidden bg-white rounded-md shadow-xl dark:bg-gray-800", hidden: showOptionsMenu, onMouseLeave: () => setShowOptionsMenu(true), children: options.map((option, index) => (_jsx(React.Fragment, { children: option }, index))) })] }) }) }));
10
10
  };
11
11
  const NavItem = ({ name, link, icon, selectedColor, childrens = [], reduxNotificationBadge, }) => {
12
12
  const location = useLocation();
@@ -30,7 +30,7 @@ const NavItem = ({ name, link, icon, selectedColor, childrens = [], reduxNotific
30
30
  // De lo contrario, usamos el color normal (bg700)
31
31
  className: `${isActive ? specialColor.bg900 : specialColor.bg700} container text-white w-full sm:w-auto h-10 text-sm py-1 uppercase shadow hover:shadow-lg outline-none rounded-full focus:outline-none my-auto sm:my-0 sm:mr-1 mb-1 ease-linear transition-all duration-150`, children: _jsxs(Link, { className: "px-3 flex items-center text-xs leading-snug text-white uppercase hover:opacity-75 relative", to: link, children: [_jsxs("div", { className: "mx-auto pt-2", children: [icon, _jsx("span", { children: name })] }), notificationBadge !== undefined && (_jsx("span", { className: "absolute -top-2 -right-2 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center w-5 h-5", children: notificationBadge }))] }) }) }));
32
32
  };
33
- export const NavBar = ({ title, loggedIn, items, selectedColor, version, reloadCatalogsOption, showDarkModeToggle = false, }) => {
33
+ export const NavBar = ({ title, loggedIn, items, selectedColor, version, reloadCatalogsOption, settingsOption, showDarkModeToggle = false, }) => {
34
34
  const color = COLORS[selectedColor];
35
35
  const [NavBarOpen, setNavBarOpen] = useState(false);
36
36
  const [currentVersion, setCurrentVersion] = useState(version);
@@ -56,11 +56,12 @@ export const NavBar = ({ title, loggedIn, items, selectedColor, version, reloadC
56
56
  const options = useMemo(() => {
57
57
  return (_jsxs(_Fragment, { children: [_jsx("ul", { className: "w-full lg:flex lg:items-center", children: renderNavItems(items
58
58
  .filter((item) => item.loggedIn === loggedIn)
59
- .filter((item) => item.hide !== true)) }), _jsx("ul", { className: "sm:flex sm:flex-col lg:flex-row ml-auto", children: loggedIn && (_jsx(OptionsDropDownButton, { color: color, options: [
59
+ .filter((item) => item.hide !== true)) }), _jsx("ul", { className: "sm:flex sm:flex-col lg:flex-row ml-auto", children: loggedIn && (_jsx(OptionsDropDownButton, { color: color, ariaLabel: "Men\u00FA de usuario", options: [
60
+ settingsOption && (_jsx(Link, { className: "block cursor-pointer px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 dark:hover:text-white", to: "/configuracion", children: _jsxs("div", { className: "mx-auto pt-2", children: [_jsxs("svg", { className: "h-5 w-5 mr-1", width: "24", height: "24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", viewBox: "0 0 24 24", strokeLinecap: "round", strokeLinejoin: "round", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("path", { d: "M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z" }), _jsx("path", { d: "M19.4 13a7.7 7.7 0 0 0 .06-2l2.1-1.64-2-3.46-2.55 1a7.7 7.7 0 0 0-1.73-1L14.7 2H9.3l-.58 2.9a7.7 7.7 0 0 0-1.73 1l-2.55-1-2 3.46L4.54 11a7.7 7.7 0 0 0 0 2l-2.1 1.64 2 3.46 2.55-1a7.7 7.7 0 0 0 1.73 1L9.3 22h5.4l.58-2.9a7.7 7.7 0 0 0 1.73-1l2.55 1 2-3.46Z" })] }), _jsx("span", { children: "Configuraci\u00F3n" })] }) }, "configuracion")),
60
61
  reloadCatalogsOption && (_jsx(Link, { className: `block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`, to: "/reload-catalogs", children: _jsxs("div", { className: "mx-auto pt-2", children: [_jsxs("svg", { className: `h-5 w-5 mr-1`, width: "24", height: "24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", viewBox: "0 0 24 24", strokeLinecap: "round", strokeLinejoin: "round", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M20.5 8c-1.392-3.179-4.823-5-8.522-5C7.299 3 3.453 6.552 3 11.1" }), _jsx("path", { d: "M16.489 8.4h3.97A.54.54 0 0 0 21 7.86V3.9M3.5 16c1.392 3.179 4.823 5 8.522 5 4.679 0 8.525-3.552 8.978-8.1" }), _jsx("path", { d: "M7.511 15.6h-3.97a.54.54 0 0 0-.541.54v3.96" })] }), _jsx("span", { children: "Recargar cat\u00E1logos" })] }) }, "recargar-catalogos")),
61
62
  showDarkModeToggle && (_jsx("button", { type: "button", className: "block w-full cursor-pointer text-left px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 dark:hover:text-white", onClick: () => setIsDarkMode((value) => !value), children: _jsx("div", { className: "mx-auto pt-2", children: _jsx("span", { children: isDarkMode ? "Modo claro" : "Modo oscuro" }) }) }, "dark-mode-toggle")),
62
63
  _jsx(Link, { className: `block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`, to: "/logout", children: _jsxs("div", { className: "mx-auto pt-2", children: [_jsx(LogoutDropDownSvgIcon, {}), _jsx("span", { children: "Cerrar sesi\u00F3n" })] }) }, "cerrar-sesion"),
63
64
  ] })) })] }));
64
- }, [items, loggedIn, hiddenItemsChange, showDarkModeToggle, isDarkMode]);
65
+ }, [items, loggedIn, hiddenItemsChange, reloadCatalogsOption, settingsOption, showDarkModeToggle, isDarkMode]);
65
66
  return (_jsx("nav", { className: `py-3 ${color.bg600}`, children: _jsxs("div", { className: "flex items-center justify-between ml-5 mr-5", children: [_jsxs("div", { className: "flex justify-between items-center w-full lg:w-auto", children: [_jsxs(Link, { className: "text-sm font-bold leading-relaxed inline-block mr-4 py-2 whitespace-nowrap uppercase text-white", to: "/home", children: [_jsx("div", { className: "inline-block mr-2 mb-2 align-middle", children: _jsx("img", { className: "w-auto h-7", src: "/logo.png", alt: "logo-zauru" }) }), title] }), version !== currentVersion && (_jsx("button", { className: `ml-2 px-2 py-1 text-xs text-white ${color.bg700} rounded-full hover:${color.bg900} transition-colors duration-200`, onClick: refreshPage, children: "\uD83D\uDD04 Actualizar versi\u00F3n" })), _jsx("button", { className: `rounded lg:hidden focus:outline-none focus:ring focus:${color.ring600} focus:ring-opacity-50`, "aria-label": "Toggle mobile menu", type: "button", onClick: () => setNavBarOpen(!NavBarOpen), children: _jsx(MenuAlt4Svg, { open: NavBarOpen }) })] }), _jsx("div", { className: `lg:hidden fixed top-0 left-0 z-50 w-64 h-full ${color.bg700} dark:bg-gray-900 shadow-lg transform ${NavBarOpen ? "translate-x-0" : "-translate-x-full"} transition-transform duration-300 ease-in-out overflow-y-auto`, children: _jsx("div", { className: "p-4", children: options }) }), _jsx("div", { className: "hidden lg:flex lg:items-center w-full lg:w-auto", children: options })] }) }));
66
67
  };
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { MainContainer } from "../Containers/MainContainer.js";
3
+ import { SubContainer } from "../Containers/SubContainer.js";
4
+ import { RouteTabNav } from "./RouteTabNav.js";
5
+ export const WebappSettingsChrome = ({ children, showEmployees = true, showRoles = true, showPermissions = true, basePath = "/configuracion", title = "Configuración", description = "Roles, empleados y permisos de esta aplicación.", }) => {
6
+ const base = basePath.replace(/\/$/, "");
7
+ return (_jsx(MainContainer, { children: _jsxs(SubContainer, { title: title, description: description, children: [_jsx(RouteTabNav, { ariaLabel: "Secciones de configuraci\u00F3n de accesos", selectedColor: "indigo", items: [
8
+ {
9
+ to: `${base}/empleados`,
10
+ label: "Empleados",
11
+ hide: !showEmployees,
12
+ },
13
+ {
14
+ to: `${base}/roles`,
15
+ label: "Roles",
16
+ hide: !showRoles,
17
+ },
18
+ {
19
+ to: `${base}/permisos`,
20
+ label: "Permisos",
21
+ hide: !showPermissions,
22
+ },
23
+ ] }), children] }) }));
24
+ };
@@ -1,3 +1,4 @@
1
1
  export * from "./Tab.js";
2
2
  export * from "./RouteTabNav.js";
3
3
  export * from "./PermissionMatrix.js";
4
+ export * from "./WebappSettingsChrome.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zauru-sdk/components",
3
- "version": "6.9.0",
3
+ "version": "6.10.0",
4
4
  "description": "Componentes reutilizables en las WebApps de Zauru.",
5
5
  "main": "./dist/esm/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -44,12 +44,12 @@
44
44
  "@reduxjs/toolkit": "^2.2.1",
45
45
  "@remix-run/node": "^2.8.1",
46
46
  "@remix-run/react": "^2.8.1",
47
- "@zauru-sdk/common": "^6.8.4",
48
- "@zauru-sdk/hooks": "^6.3.17",
47
+ "@zauru-sdk/common": "^6.8.5",
48
+ "@zauru-sdk/hooks": "^6.3.18",
49
49
  "@zauru-sdk/icons": "^6.1.0",
50
- "@zauru-sdk/redux": "^6.5.15",
51
- "@zauru-sdk/types": "^6.22.0",
52
- "@zauru-sdk/utils": "^6.21.0",
50
+ "@zauru-sdk/redux": "^6.5.16",
51
+ "@zauru-sdk/types": "^6.23.0",
52
+ "@zauru-sdk/utils": "^6.22.0",
53
53
  "browser-image-compression": "^2.0.2",
54
54
  "framer-motion": "^12.0.0",
55
55
  "jsonwebtoken": "^9.0.2",
@@ -62,5 +62,5 @@
62
62
  "styled-components": "^5.3.5",
63
63
  "zod": "^3.23.8"
64
64
  },
65
- "gitHead": "800600a8cdb22f1c49293fbc3a48d26aa03771c9"
65
+ "gitHead": "a3c1f2af46acb59cf9fcb78ecb18d904e33c61e5"
66
66
  }
@@ -15,7 +15,12 @@ import type {
15
15
  import { Link, useNavigate, useLocation } from "@remix-run/react";
16
16
  import { useAppSelector } from "@zauru-sdk/redux";
17
17
 
18
- const OptionsDropDownButton = ({ color, options, name }: EntityProps) => {
18
+ const OptionsDropDownButton = ({
19
+ color,
20
+ options,
21
+ name,
22
+ ariaLabel,
23
+ }: EntityProps & { ariaLabel?: string }) => {
19
24
  const [showOptionsMenu, setShowOptionsMenu] = useState(true);
20
25
 
21
26
  return (
@@ -23,8 +28,14 @@ const OptionsDropDownButton = ({ color, options, name }: EntityProps) => {
23
28
  <div className="flex justify-center">
24
29
  <div className="relative inline-block">
25
30
  <button
31
+ type="button"
32
+ aria-label={
33
+ ariaLabel ?? (typeof name === "string" ? name : "Menú")
34
+ }
35
+ aria-haspopup="menu"
36
+ aria-expanded={!showOptionsMenu}
26
37
  onClick={() => setShowOptionsMenu(!showOptionsMenu)}
27
- className={`relative flex cursor-pointer items-center p-2 text-xs text-white ${color.bg700} active:${color.bg900} border border-transparent rounded-full uppercase focus:ring-opacity-40 focus:outline-none`}
38
+ className={`relative flex cursor-pointer items-center p-2 text-xs text-white ${color.bg700} active:${color.bg900} border border-transparent rounded-full uppercase focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2`}
28
39
  >
29
40
  {name ?? <OpcionButtonSvgIcon />}
30
41
  <DropDownArrowSvgIcon />
@@ -128,6 +139,7 @@ export const NavBar = ({
128
139
  selectedColor,
129
140
  version,
130
141
  reloadCatalogsOption,
142
+ settingsOption,
131
143
  showDarkModeToggle = false,
132
144
  }: NavBarProps) => {
133
145
  const color: ColorInterface = COLORS[selectedColor];
@@ -191,7 +203,35 @@ export const NavBar = ({
191
203
  {loggedIn && (
192
204
  <OptionsDropDownButton
193
205
  color={color}
206
+ ariaLabel="Menú de usuario"
194
207
  options={[
208
+ settingsOption && (
209
+ <Link
210
+ key="configuracion"
211
+ className="block cursor-pointer px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 dark:hover:text-white"
212
+ to="/configuracion"
213
+ >
214
+ <div className="mx-auto pt-2">
215
+ <svg
216
+ className="h-5 w-5 mr-1"
217
+ width="24"
218
+ height="24"
219
+ fill="none"
220
+ stroke="currentColor"
221
+ strokeWidth="1.5"
222
+ viewBox="0 0 24 24"
223
+ strokeLinecap="round"
224
+ strokeLinejoin="round"
225
+ xmlns="http://www.w3.org/2000/svg"
226
+ aria-hidden="true"
227
+ >
228
+ <path d="M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z" />
229
+ <path d="M19.4 13a7.7 7.7 0 0 0 .06-2l2.1-1.64-2-3.46-2.55 1a7.7 7.7 0 0 0-1.73-1L14.7 2H9.3l-.58 2.9a7.7 7.7 0 0 0-1.73 1l-2.55-1-2 3.46L4.54 11a7.7 7.7 0 0 0 0 2l-2.1 1.64 2 3.46 2.55-1a7.7 7.7 0 0 0 1.73 1L9.3 22h5.4l.58-2.9a7.7 7.7 0 0 0 1.73-1l2.55 1 2-3.46Z" />
230
+ </svg>
231
+ <span>Configuración</span>
232
+ </div>
233
+ </Link>
234
+ ),
195
235
  reloadCatalogsOption && (
196
236
  <Link
197
237
  key="recargar-catalogos"
@@ -247,7 +287,7 @@ export const NavBar = ({
247
287
  </ul>
248
288
  </>
249
289
  );
250
- }, [items, loggedIn, hiddenItemsChange, showDarkModeToggle, isDarkMode]);
290
+ }, [items, loggedIn, hiddenItemsChange, reloadCatalogsOption, settingsOption, showDarkModeToggle, isDarkMode]);
251
291
 
252
292
  return (
253
293
  <nav className={`py-3 ${color.bg600}`}>
@@ -32,6 +32,7 @@ export type NavBarProps = {
32
32
  LinkComponent?: any;
33
33
  version?: string;
34
34
  reloadCatalogsOption?: boolean;
35
+ settingsOption?: boolean;
35
36
  showDarkModeToggle?: boolean;
36
37
  };
37
38
 
@@ -0,0 +1,54 @@
1
+ import type { ReactNode } from "react";
2
+ import { MainContainer } from "../Containers/MainContainer.js";
3
+ import { SubContainer } from "../Containers/SubContainer.js";
4
+ import { RouteTabNav } from "./RouteTabNav.js";
5
+
6
+ type Props = {
7
+ children: ReactNode;
8
+ showEmployees?: boolean;
9
+ showRoles?: boolean;
10
+ showPermissions?: boolean;
11
+ basePath?: string;
12
+ title?: string;
13
+ description?: string;
14
+ };
15
+
16
+ export const WebappSettingsChrome = ({
17
+ children,
18
+ showEmployees = true,
19
+ showRoles = true,
20
+ showPermissions = true,
21
+ basePath = "/configuracion",
22
+ title = "Configuración",
23
+ description = "Roles, empleados y permisos de esta aplicación.",
24
+ }: Props) => {
25
+ const base = basePath.replace(/\/$/, "");
26
+ return (
27
+ <MainContainer>
28
+ <SubContainer title={title} description={description}>
29
+ <RouteTabNav
30
+ ariaLabel="Secciones de configuración de accesos"
31
+ selectedColor="indigo"
32
+ items={[
33
+ {
34
+ to: `${base}/empleados`,
35
+ label: "Empleados",
36
+ hide: !showEmployees,
37
+ },
38
+ {
39
+ to: `${base}/roles`,
40
+ label: "Roles",
41
+ hide: !showRoles,
42
+ },
43
+ {
44
+ to: `${base}/permisos`,
45
+ label: "Permisos",
46
+ hide: !showPermissions,
47
+ },
48
+ ]}
49
+ />
50
+ {children}
51
+ </SubContainer>
52
+ </MainContainer>
53
+ );
54
+ };
package/src/Tab/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./Tab.js";
2
2
  export * from "./RouteTabNav.js";
3
3
  export * from "./PermissionMatrix.js";
4
+ export * from "./WebappSettingsChrome.js";