@sfperusacdev/sf-ui 0.1.23 → 0.1.25
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/dist/sf-ui.css +1 -1
- package/dist/sf-ui.js +1669 -1475
- package/dist/sf-ui.js.map +1 -1
- package/dist/sf-ui.umd.cjs +7 -7
- package/dist/sf-ui.umd.cjs.map +1 -1
- package/dist/theme/dark.css +7 -0
- package/dist/theme/sark.css +2 -0
- package/dist/theme/sf-tokens.css +10 -6
- package/dist/types/src/components/icons/AppsGridIcon.d.ts +9 -0
- package/dist/types/src/components/icons/index.d.ts +2 -0
- package/dist/types/src/components/layout/AppShell.d.ts +8 -0
- package/dist/types/src/components/table/CustomTable.d.ts +29 -3
- package/dist/types/src/components/table/CustomTable.detail.test.d.ts +1 -0
- package/dist/types/src/components/table/index.d.ts +1 -1
- package/dist/types/src/hooks/useCustomForm.d.ts +4 -20
- package/package.json +5 -4
package/dist/theme/dark.css
CHANGED
|
@@ -169,7 +169,14 @@
|
|
|
169
169
|
ese mismo valor para que el oscuro se vea EXACTAMENTE igual que antes: al
|
|
170
170
|
quitar el import las heredaría del tema base (sark) y cambiarían de color. */
|
|
171
171
|
--sf-app-shell-accent: #2e9e5b;
|
|
172
|
+
--sf-app-shell-topbar-bg: #0c2131;
|
|
173
|
+
--sf-app-shell-topbar-text: #ffffff;
|
|
172
174
|
--sf-app-shell-topbar-muted: #9fb6c4;
|
|
175
|
+
--sf-app-shell-user-chip-bg: color-mix(in srgb, var(--sf-app-shell-topbar-bg) 86%, #f5f7f9);
|
|
176
|
+
--sf-app-shell-user-chip-bg-hover: color-mix(in srgb, var(--sf-app-shell-topbar-bg) 80%, #f5f7f9);
|
|
177
|
+
--sf-app-shell-user-chip-border: color-mix(in srgb, var(--sf-app-shell-topbar-text) 18%, transparent);
|
|
178
|
+
--sf-app-shell-user-chip-border-hover: color-mix(in srgb, var(--sf-app-shell-topbar-text) 28%, transparent);
|
|
179
|
+
--sf-app-shell-user-chip-name: var(--sf-app-shell-topbar-text);
|
|
173
180
|
--sf-badge-primary-dot: #334155;
|
|
174
181
|
--sf-btn-primary-shadow-hover: none;
|
|
175
182
|
--sf-danger: #dc2626;
|
package/dist/theme/sark.css
CHANGED
|
@@ -99,6 +99,8 @@
|
|
|
99
99
|
--sf-modal-header-bg: var(--sf-primary);
|
|
100
100
|
--sf-modal-header-text: var(--sf-white);
|
|
101
101
|
--sf-app-shell-accent: var(--sf-accent);
|
|
102
|
+
--sf-app-shell-topbar-bg: #0c2131;
|
|
103
|
+
--sf-app-shell-topbar-text: #ffffff;
|
|
102
104
|
--sf-app-shell-topbar-muted: #9fb6c4;
|
|
103
105
|
--sf-modal-header-subtitle: var(--sf-app-shell-topbar-muted);
|
|
104
106
|
--sf-modal-header-icon-bg: var(--sf-app-shell-accent);
|
package/dist/theme/sf-tokens.css
CHANGED
|
@@ -158,14 +158,18 @@
|
|
|
158
158
|
--sf-page-header-border: var(--sf-border);
|
|
159
159
|
--sf-page-header-shadow: var(--sf-shadow-2);
|
|
160
160
|
|
|
161
|
+
/* AppShell topbar — fondo/texto fijos al togglear oscuro (no usar --sf-primary/--sf-white) */
|
|
162
|
+
--sf-app-shell-topbar-bg: var(--sf-primary);
|
|
163
|
+
--sf-app-shell-topbar-text: #ffffff;
|
|
164
|
+
--sf-app-shell-topbar-muted: #9fb6c4;
|
|
165
|
+
|
|
161
166
|
/* AppShell topbar user chip */
|
|
162
|
-
--sf-app-shell-user-chip-bg: color-mix(in srgb, var(--sf-
|
|
163
|
-
--sf-app-shell-user-chip-bg-hover: color-mix(in srgb, var(--sf-
|
|
164
|
-
--sf-app-shell-user-chip-border: color-mix(in srgb, var(--sf-
|
|
165
|
-
--sf-app-shell-user-chip-border-hover: color-mix(in srgb, var(--sf-
|
|
167
|
+
--sf-app-shell-user-chip-bg: color-mix(in srgb, var(--sf-app-shell-topbar-bg) 86%, var(--sf-surface-alt));
|
|
168
|
+
--sf-app-shell-user-chip-bg-hover: color-mix(in srgb, var(--sf-app-shell-topbar-bg) 80%, var(--sf-surface-alt));
|
|
169
|
+
--sf-app-shell-user-chip-border: color-mix(in srgb, var(--sf-app-shell-topbar-text) 22%, transparent);
|
|
170
|
+
--sf-app-shell-user-chip-border-hover: color-mix(in srgb, var(--sf-app-shell-topbar-text) 34%, transparent);
|
|
166
171
|
--sf-app-shell-user-chip-radius: 0.5rem;
|
|
167
|
-
--sf-app-shell-
|
|
168
|
-
--sf-app-shell-user-chip-name: var(--sf-white);
|
|
172
|
+
--sf-app-shell-user-chip-name: var(--sf-app-shell-topbar-text);
|
|
169
173
|
--sf-app-shell-user-chip-subtitle: var(--sf-app-shell-topbar-muted);
|
|
170
174
|
--sf-app-shell-user-avatar-bg: var(--sf-app-shell-accent);
|
|
171
175
|
--sf-app-shell-user-avatar-text: var(--sf-white);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type AppsGridIconProps = {
|
|
2
|
+
className?: string;
|
|
3
|
+
};
|
|
4
|
+
/**
|
|
5
|
+
* Lanzador de aplicaciones: cuadrícula de 9 puntos (3×3), el patrón que la
|
|
6
|
+
* gente reconoce como "ver todos los módulos". No usar `FiGrid` para esto:
|
|
7
|
+
* es una cuadrícula de 2×2 y se lee como "cambiar de vista", no como launcher.
|
|
8
|
+
*/
|
|
9
|
+
export declare const AppsGridIcon: ({ className }: AppsGridIconProps) => import("react").JSX.Element;
|
|
@@ -10,6 +10,11 @@ export type AppShellNavItem = {
|
|
|
10
10
|
* submenú largo sin cabeceras de sección. Se ignora en el primer item.
|
|
11
11
|
*/
|
|
12
12
|
dividerBefore?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Oculta el item sin sacarlo del árbol de navegación: útil para features
|
|
15
|
+
* detrás de bandera o permiso, donde la definición del menú es estática.
|
|
16
|
+
*/
|
|
17
|
+
hidden?: boolean;
|
|
13
18
|
};
|
|
14
19
|
export type AppShellCategory = {
|
|
15
20
|
id: string;
|
|
@@ -44,6 +49,9 @@ export type AppShellModuleLauncher = {
|
|
|
44
49
|
items: AppShellModuleLauncherItem[];
|
|
45
50
|
title?: string;
|
|
46
51
|
subtitle?: string;
|
|
52
|
+
/** Ícono del botón que abre el lanzador. Por defecto, la cuadrícula de 9 puntos. */
|
|
53
|
+
triggerIcon?: ReactNode;
|
|
54
|
+
ariaLabel?: string;
|
|
47
55
|
};
|
|
48
56
|
export type AppShellUserMenu = {
|
|
49
57
|
fullName: string;
|
|
@@ -19,7 +19,28 @@ type CustomColumn<TData> = {
|
|
|
19
19
|
enableHiding?: boolean;
|
|
20
20
|
size?: number;
|
|
21
21
|
};
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Configuración de las filas de detalle expandibles (master-detail).
|
|
24
|
+
*
|
|
25
|
+
* Se puede usar de dos maneras excluyentes:
|
|
26
|
+
* - `render`: contenido libre bajo la fila padre (tiene prioridad si se define).
|
|
27
|
+
* - `getRows` + `columns`: sub-tabla renderizada con el propio `CustomTable` en modo `embedded`.
|
|
28
|
+
*/
|
|
29
|
+
type CustomTableDetail<TData, TDetail extends Record<string, unknown> = Record<string, unknown>> = {
|
|
30
|
+
/** Render libre del detalle. Si se define, ignora `getRows`/`columns`. */
|
|
31
|
+
render?: (row: TData) => ReactNode;
|
|
32
|
+
/** Filas hijas de la fila padre; se muestran en una sub-tabla. */
|
|
33
|
+
getRows?: (row: TData) => TDetail[];
|
|
34
|
+
/** Columnas de la sub-tabla de detalle. Requerido cuando se usa `getRows`. */
|
|
35
|
+
columns?: CustomColumn<TDetail>[];
|
|
36
|
+
/** Estado inicial del detalle: booleano global o predicado por fila. Por defecto `false`. */
|
|
37
|
+
defaultExpanded?: boolean | ((row: TData) => boolean);
|
|
38
|
+
/** Deshabilita el chevron para filas sin detalle. Por defecto todas son expandibles. */
|
|
39
|
+
isExpandable?: (row: TData) => boolean;
|
|
40
|
+
/** Mensaje de la sub-tabla cuando no hay filas hijas. */
|
|
41
|
+
emptyMessage?: string;
|
|
42
|
+
};
|
|
43
|
+
type CustomTableProps<TData extends Record<string, unknown>, TDetail extends Record<string, unknown> = Record<string, unknown>> = {
|
|
23
44
|
id?: string;
|
|
24
45
|
stateStore?: AsyncStateStore;
|
|
25
46
|
data: TData[];
|
|
@@ -77,7 +98,12 @@ type CustomTableProps<TData extends Record<string, unknown>> = {
|
|
|
77
98
|
headerVariant?: TableHeaderVariant;
|
|
78
99
|
/** Oculta título, toolbar y chrome exterior — para uso dentro de ExpandableTableSection u otros contenedores. */
|
|
79
100
|
embedded?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Filas de detalle expandibles (master-detail). Agrega una columna de chevron al inicio
|
|
103
|
+
* y, al expandir, inserta una fila con el detalle debajo de la fila padre.
|
|
104
|
+
*/
|
|
105
|
+
detail?: CustomTableDetail<TData, TDetail>;
|
|
80
106
|
controller?: CustomTableController<TData>;
|
|
81
107
|
};
|
|
82
|
-
export declare function CustomTable<TData extends Record<string, unknown>>({ id, stateStore, data, columns, grouping, defaultGrouping, enableGrouping, enableSorting, enableFiltering, enablePagination, pageSize, fillParentHeight, maxBodyHeightPx, className, emptyMessage, title, subtitle, sidePanel, onGroupingChange, toolbarSlot, belowToolbarSlot, loading, loadingMessage, isFetching, error, onRetry, onRefresh, onRowClick, enableRowSelection, getRowActions, getBulkActions, bulkActionsSlot, onSelectionChange, headerVariant, embedded, controller, }: CustomTableProps<TData>): import("react").JSX.Element;
|
|
83
|
-
export type { CustomColumn, CustomTableProps, TableAggregation };
|
|
108
|
+
export declare function CustomTable<TData extends Record<string, unknown>, TDetail extends Record<string, unknown> = Record<string, unknown>>({ id, stateStore, data, columns, grouping, defaultGrouping, enableGrouping, enableSorting, enableFiltering, enablePagination, pageSize, fillParentHeight, maxBodyHeightPx, className, emptyMessage, title, subtitle, sidePanel, onGroupingChange, toolbarSlot, belowToolbarSlot, loading, loadingMessage, isFetching, error, onRetry, onRefresh, onRowClick, enableRowSelection, getRowActions, getBulkActions, bulkActionsSlot, onSelectionChange, headerVariant, embedded, detail, controller, }: CustomTableProps<TData, TDetail>): import("react").JSX.Element;
|
|
109
|
+
export type { CustomColumn, CustomTableDetail, CustomTableProps, TableAggregation };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { CustomTable } from './CustomTable';
|
|
2
|
-
export type { CustomColumn, CustomTableProps, TableHeaderVariant } from './CustomTable';
|
|
2
|
+
export type { CustomColumn, CustomTableDetail, CustomTableProps, TableHeaderVariant } from './CustomTable';
|
|
3
3
|
export { AsyncCustomTable } from './AsyncCustomTable';
|
|
4
4
|
export type { AsyncCustomTableProps } from './AsyncCustomTable';
|
|
5
5
|
export { PaginationRangeInput } from './PaginationRangeInput';
|
|
@@ -1,26 +1,10 @@
|
|
|
1
|
-
import { DefaultValues, FieldValues } from 'react-hook-form';
|
|
1
|
+
import { DefaultValues, FieldValues, UseFormReturn } from 'react-hook-form';
|
|
2
2
|
import type * as yup from "yup";
|
|
3
3
|
type UseCustomFormProps<TValues extends FieldValues> = {
|
|
4
4
|
defaultValues?: DefaultValues<TValues>;
|
|
5
5
|
};
|
|
6
|
-
|
|
7
|
-
handleSubmit:
|
|
8
|
-
watch: import('react-hook-form').UseFormWatch<yup.Asserts<TSchema>>;
|
|
9
|
-
getValues: import('react-hook-form').UseFormGetValues<yup.Asserts<TSchema>>;
|
|
10
|
-
getFieldState: import('react-hook-form').UseFormGetFieldState<yup.Asserts<TSchema>>;
|
|
11
|
-
setError: import('react-hook-form').UseFormSetError<yup.Asserts<TSchema>>;
|
|
12
|
-
clearErrors: import('react-hook-form').UseFormClearErrors<yup.Asserts<TSchema>>;
|
|
13
|
-
setValue: import('react-hook-form').UseFormSetValue<yup.Asserts<TSchema>>;
|
|
14
|
-
setValues: import('react-hook-form').UseFormSetValues<yup.Asserts<TSchema>>;
|
|
15
|
-
trigger: import('react-hook-form').UseFormTrigger<yup.Asserts<TSchema>>;
|
|
16
|
-
formState: import('react-hook-form').FormState<yup.Asserts<TSchema>>;
|
|
17
|
-
resetField: import('react-hook-form').UseFormResetField<yup.Asserts<TSchema>>;
|
|
18
|
-
reset: import('react-hook-form').UseFormReset<yup.Asserts<TSchema>>;
|
|
19
|
-
resetDefaultValues: import('react-hook-form').UseFormResetDefaultValues<yup.Asserts<TSchema>>;
|
|
20
|
-
unregister: import('react-hook-form').UseFormUnregister<yup.Asserts<TSchema>>;
|
|
21
|
-
control: import('react-hook-form').Control<yup.Asserts<TSchema>, any, yup.Asserts<TSchema>>;
|
|
22
|
-
register: import('react-hook-form').UseFormRegister<yup.Asserts<TSchema>>;
|
|
23
|
-
setFocus: import('react-hook-form').UseFormSetFocus<yup.Asserts<TSchema>>;
|
|
24
|
-
subscribe: import('react-hook-form').UseFormSubscribe<yup.Asserts<TSchema>>;
|
|
6
|
+
type UseCustomFormReturn<TValues extends FieldValues> = UseFormReturn<TValues> & {
|
|
7
|
+
handleSubmit: UseFormReturn<TValues>["handleSubmit"];
|
|
25
8
|
};
|
|
9
|
+
export declare const useCustomForm: <TSchema extends yup.ObjectSchema<FieldValues>>(schema: TSchema, props?: UseCustomFormProps<yup.Asserts<TSchema>>) => UseCustomFormReturn<yup.Asserts<TSchema>>;
|
|
26
10
|
export type { UseCustomFormProps };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sfperusacdev/sf-ui",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "SF UI
|
|
3
|
+
"version": "0.1.25",
|
|
4
|
+
"description": "SF UI \u2014 librer\u00eda de componentes React (inputs, tablas, hooks) para aplicaciones SF Per\u00fa.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/sf-ui.umd.cjs",
|
|
7
7
|
"module": "./dist/sf-ui.js",
|
|
@@ -55,7 +55,8 @@
|
|
|
55
55
|
"perf:phase5": "cross-env PERF_SCALE=1 vitest run src/performance/catalogPhases.performance.test.tsx --reporter=verbose --silent=false --testNamePattern=\"Phase 5\"",
|
|
56
56
|
"perf:phase6": "cross-env PERF_SCALE=1 vitest run src/performance/catalogPhases.performance.test.tsx --reporter=verbose --silent=false --testNamePattern=\"Phase 6\"",
|
|
57
57
|
"lint": "eslint .",
|
|
58
|
-
"dev": "npm run dev -w playground"
|
|
58
|
+
"dev": "npm run dev -w playground",
|
|
59
|
+
"postinstall": "node scripts/ensure-rolldown-binding.mjs"
|
|
59
60
|
},
|
|
60
61
|
"workspaces": [
|
|
61
62
|
"playground"
|
|
@@ -107,6 +108,7 @@
|
|
|
107
108
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
108
109
|
"eslint-plugin-react-refresh": "^0.5.2",
|
|
109
110
|
"globals": "^17.6.0",
|
|
111
|
+
"jsdom": "^26.1.0",
|
|
110
112
|
"leaflet": "^1.9.4",
|
|
111
113
|
"react": "^19.2.6",
|
|
112
114
|
"react-day-picker": "^10.0.1",
|
|
@@ -116,7 +118,6 @@
|
|
|
116
118
|
"react-leaflet": "^5.0.0",
|
|
117
119
|
"react-qr-code": "^2.2.0",
|
|
118
120
|
"recharts": "^3.9.0",
|
|
119
|
-
"jsdom": "^26.1.0",
|
|
120
121
|
"tailwindcss": "^4.3.0",
|
|
121
122
|
"typescript": "~6.0.2",
|
|
122
123
|
"typescript-eslint": "^8.59.2",
|