@stackcraftmx/calcita 0.56.0 → 0.58.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/README.md +83 -4
- package/dist/DataTable/ServerTableFilterDrawer.js +3 -1
- package/dist/DataTable/ServerTableFilterDrawer.js.map +1 -1
- package/dist/locales/en.js +15 -0
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +15 -0
- package/dist/locales/es.js.map +1 -1
- package/dist/sortable/FormSortableField.js +27 -0
- package/dist/sortable/FormSortableField.js.map +1 -0
- package/dist/sortable/SortableTable.js +230 -0
- package/dist/sortable/SortableTable.js.map +1 -0
- package/dist/sortable/sortableRows.js +14 -0
- package/dist/sortable/sortableRows.js.map +1 -0
- package/dist/sortable.js +9 -0
- package/dist/sortable.js.map +1 -0
- package/dist/theme/components/minimalComponents.js +15 -0
- package/dist/theme/components/minimalComponents.js.map +1 -1
- package/dist/theme/glassSurface.js +10 -12
- package/dist/theme/glassSurface.js.map +1 -1
- package/dist/theme/themePieces.js +10 -4
- package/dist/theme/themePieces.js.map +1 -1
- package/dist/types/DataTable/ServerTableFilterDrawer.d.ts +2 -0
- package/dist/types/downloads/fileTypes.d.ts +4 -4
- package/dist/types/forms/SubmitButton.d.ts +1 -1
- package/dist/types/locales/en.d.ts +15 -0
- package/dist/types/locales/es.d.ts +15 -0
- package/dist/types/sortable/FormSortableField.d.ts +15 -0
- package/dist/types/sortable/SortableTable.d.ts +77 -0
- package/dist/types/sortable/sortableRows.d.ts +12 -0
- package/dist/types/sortable.d.ts +3 -0
- package/dist/types/ui/filters/FilterDrawer.d.ts +1 -0
- package/dist/types/ui/filters/filterDrawerFields.d.ts +77 -2
- package/dist/ui/filters/FilterDrawer.js +118 -53
- package/dist/ui/filters/FilterDrawer.js.map +1 -1
- package/dist/ui/filters/filterDrawerFields.js +65 -14
- package/dist/ui/filters/filterDrawerFields.js.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -5,8 +5,8 @@ transparente famoso por doblar la luz, y eso es lo que define al vidrio líquido
|
|
|
5
5
|
|
|
6
6
|
Arranca un proyecto sin copiar y volver a probar lo de siempre: el marco de la app con menú y permisos, tabla de servidor,
|
|
7
7
|
diálogos de confirmación, avisos, descargas, formularios, formatos de número y fecha, errores RFC 9457, reportes en Excel,
|
|
8
|
-
la cuenta completa, mapa, calendario, tablero kanban, bandeja tipo correo y el tema con
|
|
9
|
-
componente por componente según la guía de Apple.
|
|
8
|
+
la cuenta completa, mapa, calendario, tablero kanban, listas que se ordenan arrastrando, bandeja tipo correo y el tema con
|
|
9
|
+
vidrio líquido, interpretado componente por componente según la guía de Apple.
|
|
10
10
|
|
|
11
11
|
JavaScript con sus tipos generados: se usa igual desde un proyecto en TypeScript. Sirve para un proyecto nuevo y también
|
|
12
12
|
para meterlo por pedazos en un sistema que ya existe (ver «En un sistema que ya existe»).
|
|
@@ -244,6 +244,7 @@ Cada puerta pide solo sus librerías; un proyecto instala lo que usa.
|
|
|
244
244
|
| `@stackcraftmx/calcita/maps` | `MapView`: mapa con marcadores del color del tema, el elegido con su globo, se acomoda solo; en oscuro, mosaicos oscuros | `leaflet`, `react-leaflet` 5 |
|
|
245
245
|
| `@stackcraftmx/calcita/calendar` | `EventCalendar`: mes, semana, día y lista, con la barra del framework; arrastrar cambia la cita y regresa si el servidor dice que no. `EventDetails`: el detalle de una cita (lugar, liga de la reunión, invitados con su respuesta, recordatorio, notas) | `@fullcalendar/react`, `core`, `daygrid`, `timegrid`, `list`, `interaction` 6.1 |
|
|
246
246
|
| `@stackcraftmx/calcita/kanban` | `KanbanBoard`: columnas con tope (y que se encogen, como un congelador) y tarjetas de producto (etiquetas, responsables, fecha, pendientes, terminar) que se arrastran con el ratón, el dedo o el teclado; `moveCard` para ver la movida al instante | `@hello-pangea/dnd` 18 |
|
|
247
|
+
| `@stackcraftmx/calcita/sortable` | `SortableTable`: una tabla chica cuyos renglones se arrastran (ratón, dedo o teclado) para ordenarlos, con su columna «Orden»; guarda al soltar (y regresa el renglón si el servidor dice que no) o en un formulario con `FormSortableField`; `moveRow` para mover sin arrastrar | `@hello-pangea/dnd` 18 |
|
|
247
248
|
|
|
248
249
|
## El tema
|
|
249
250
|
|
|
@@ -307,6 +308,36 @@ números, de fechas, monto con operador o uno propio); lo que se cambia adentro
|
|
|
307
308
|
por filtro (`filterDrawerDefaultsOf`, `filterDrawerKindsOf`, `filterDrawerChipsOf`). Un monto viaja como `gte:500`
|
|
308
309
|
(`comparisonOf` lo separa en el backend o en la pantalla).
|
|
309
310
|
|
|
311
|
+
Las fechas del cajón usan el calendario del navegador, así el cajón no obliga a instalar MUI X. Una app que ya trae
|
|
312
|
+
`/date-pickers` pone el suyo para que el cajón y sus formularios se vean igual: `slots={{dateInput: DateInput}}` en un
|
|
313
|
+
cajón (desde la tabla, `drawerProps`), o una vez en el tema para todas las listas. Un rango de fechas se acota con
|
|
314
|
+
`minDate`, `maxDate`, `disablePast` y `disableFuture`: el calendario no deja escoger fuera y cada extremo acota al otro. Si
|
|
315
|
+
alguien teclea una fecha fuera de los topes o un rango al revés, su campo lo dice y «Buscar» no busca; nada se borra solo.
|
|
316
|
+
Un `custom` con `keys` es un rango propio en un solo campo: guarda en sus dos llaves, cuenta como un filtro, da sus dos chips
|
|
317
|
+
y, con `isBackwards`, tampoco deja buscar al revés. Su `render` recibe todo el borrador (`values`, `setValue`), sus `keys` y
|
|
318
|
+
lo que esté mal en cada una (`errors`), ya dicho. En un cajón angosto, `stackPairsBelow` pone cada par uno arriba del otro.
|
|
319
|
+
|
|
320
|
+
```jsx
|
|
321
|
+
import {DateInput, TimeInput} from '@stackcraftmx/calcita/date-pickers';
|
|
322
|
+
|
|
323
|
+
const FIELDS = [
|
|
324
|
+
{name: 'paid', label: 'Fecha de pago', kind: FILTER_FIELD_KIND.dateRange, minDate: '2026-01-01', disableFuture: true},
|
|
325
|
+
{
|
|
326
|
+
name: 'hours', label: 'Hora de compra', kind: FILTER_FIELD_KIND.custom, keys: {from: 'hour_from', to: 'hour_to'},
|
|
327
|
+
isBackwards: (from, to) => to < from,
|
|
328
|
+
render: ({values, setValue, keys: [fromKey, toKey], errors}) => (
|
|
329
|
+
<>
|
|
330
|
+
<TimeInput label="Desde" value={values[fromKey]} onChange={(time) => setValue(fromKey, time)} />
|
|
331
|
+
<TimeInput label="Hasta" value={values[toKey]} onChange={(time) => setValue(toKey, time)} error={errors[toKey]} />
|
|
332
|
+
</>
|
|
333
|
+
),
|
|
334
|
+
},
|
|
335
|
+
];
|
|
336
|
+
|
|
337
|
+
<ServerTableFilterDrawer fields={FIELDS} width={460} stackPairsBelow={420} drawerProps={{slots: {dateInput: DateInput}}} />
|
|
338
|
+
// o para todas las listas: createTheme({components: {CalcitaFilterDrawer: {defaultProps: {slots: {dateInput: DateInput}}}}})
|
|
339
|
+
```
|
|
340
|
+
|
|
310
341
|
```jsx
|
|
311
342
|
<BarActions label="Buscar en pedidos" order={1}>
|
|
312
343
|
<IconButton aria-label="Buscar" onClick={openSearch}><SearchRoundedIcon /></IconButton>
|
|
@@ -336,6 +367,16 @@ se pueden escribir en `colorSchemes`.
|
|
|
336
367
|
createToolkitTheme({glass: true, fields: {radius: 8, light: {fill: '#FFFFFF', hoverFill: '#FFFFFF', border: '#C4CDD5'}}});
|
|
337
368
|
```
|
|
338
369
|
|
|
370
|
+
Para cambiar el relleno solo en ciertos campos (los bloqueados, o todos en oscuro con el color de la marca), el tema del
|
|
371
|
+
proyecto pone la variable `--calcita-field-fill` (y `--calcita-field-hover-fill`, `--calcita-field-edge`,
|
|
372
|
+
`--calcita-field-hover-edge`) en el campo o en algo que lo contenga: todos los campos de Calcita la leen, los de
|
|
373
|
+
`FormSection` y los sueltos (un cajón de filtros, una ventana). Ponerle un `backgroundColor` al campo no siempre gana, porque
|
|
374
|
+
las reglas de Calcita llevan selectores largos; con la variable manda la definición más cercana.
|
|
375
|
+
|
|
376
|
+
```js
|
|
377
|
+
MuiOutlinedInput: {styleOverrides: {root: ({theme}) => theme.applyStyles('dark', {'--calcita-field-fill': '#1E3A5F', '--calcita-field-hover-fill': '#1E3A5F'})}}
|
|
378
|
+
```
|
|
379
|
+
|
|
339
380
|
El minimalista separa las superficies por su tono con los grises de Apple. Para pintarlo con los colores de la marca:
|
|
340
381
|
`minimalTones`, por modo, con el fondo de la página (`default`), las tarjetas (`paper`), el relleno de campos, grupos y
|
|
341
382
|
botones sin color (`fill`) y lo que flota, como la barra del teléfono (`floating`). Lo que no se pase se queda con el gris
|
|
@@ -368,7 +409,8 @@ createTheme({components: {CalcitaRecordCard: {defaultProps: {slotProps: {root: {
|
|
|
368
409
|
```
|
|
369
410
|
|
|
370
411
|
`className`, `style` y `sx` de `slotProps` se suman a los de Calcita; una pieza dentro de otra igual no toma los `slots` de la
|
|
371
|
-
de afuera.
|
|
412
|
+
de afuera. Una parte propia no recibe el estilo de Calcita ni, si la parte es un `Stack`, su acomodo (`spacing`,
|
|
413
|
+
`direction`): eso lo pone ella; lo que la pantalla le dé en `slotProps` sí le llega. `TextInput` es la excepción: su `slotProps` es el del `TextField` de MUI (`input`, `htmlInput`…). Una pieza propia
|
|
372
414
|
del proyecto se arma con lo mismo: `piecePart`, `usePieceProps` y `withPieceSlots`.
|
|
373
415
|
|
|
374
416
|
El `sx` de la pantalla se **combina regla por regla** con el de la pieza, no la reemplaza: en la tabla,
|
|
@@ -429,7 +471,7 @@ Para hacer lo mismo en un componente propio: `sx={[{p: 2}, ...sxListOf(sx)]}` (u
|
|
|
429
471
|
| `CalcitaFileInput` | `root`, `button`, `fileChip`, `empty` |
|
|
430
472
|
| `CalcitaFileUploadInput` | `root`, `fileName`, `status`, `button`, `helper` |
|
|
431
473
|
| `CalcitaFilterChips` | `root`, `header`, `clearButton` |
|
|
432
|
-
| `CalcitaFilterDrawer` | `header`, `body`, `footer` |
|
|
474
|
+
| `CalcitaFilterDrawer` | `header`, `body`, `footer`, `dateInput` |
|
|
433
475
|
| `CalcitaFontSizeToggle` | `button` |
|
|
434
476
|
| `CalcitaFormProblemAlert` | `root` |
|
|
435
477
|
| `CalcitaFormRow` | `root`, `label`, `control` |
|
|
@@ -495,6 +537,7 @@ Para hacer lo mismo en un componente propio: `sx={[{p: 2}, ...sxListOf(sx)]}` (u
|
|
|
495
537
|
| `CalcitaSignInForm` | `footer` |
|
|
496
538
|
| `CalcitaSignInScreen` | `alert` |
|
|
497
539
|
| `CalcitaSortableFilterHeader` | `title`, `root`, `sortButton`, `sortIndicator`, `clearButton` |
|
|
540
|
+
| `CalcitaSortableTable` | `root`, `container`, `table`, `head`, `headerRow`, `headerCell`, `body`, `row`, `handleCell`, `handle`, `positionCell`, `cell`, `empty`, `helperText`, `announcer` |
|
|
498
541
|
| `CalcitaStackedCell` | `root`, `line`, `label`, `valueRow`, `primary`, `secondary`, `note` |
|
|
499
542
|
| `CalcitaStatusChip` | `root`, `dot`, `label`, `chip` |
|
|
500
543
|
| `CalcitaSubmenuActionsMenu` | `badge` |
|
|
@@ -682,6 +725,42 @@ const columns = [
|
|
|
682
725
|
para decidirlo desde la pantalla.
|
|
683
726
|
- `gridSx` se combina con los estilos de la tabla regla por regla; `gridProps` pasa lo demás al DataGrid.
|
|
684
727
|
|
|
728
|
+
## Listas que se ordenan (`/sortable`)
|
|
729
|
+
|
|
730
|
+
Para una lista chica donde el orden de los renglones es el dato (qué se surte primero, en qué orden pasa la ruta, qué se
|
|
731
|
+
hace antes): `SortableTable` es una tabla cuyos renglones se arrastran con el ratón, el dedo o el teclado (espacio, flechas,
|
|
732
|
+
espacio), con la columna «Orden» 1..n que se renumera sola. Pide `@hello-pangea/dnd`, la misma del tablero kanban. La tabla
|
|
733
|
+
de servidor no sirve para esto: en MUI X, ordenar renglones arrastrando es de su versión de paga; esta lista va completa en
|
|
734
|
+
el navegador.
|
|
735
|
+
|
|
736
|
+
```jsx
|
|
737
|
+
import {FormSortableField, SortableTable, moveRow} from '@stackcraftmx/calcita/sortable';
|
|
738
|
+
|
|
739
|
+
// guardar al soltar: si la promesa truena (el servidor dijo que no), el renglón regresa solo a su lugar
|
|
740
|
+
<SortableTable rows={orders} ariaLabel="Orden de surtido" getRowLabel={(order) => order.folio}
|
|
741
|
+
columns={[{field: 'folio', headerName: 'Pedido', width: 120}, {field: 'customer', headerName: 'Cliente', flex: 1}]}
|
|
742
|
+
onReorder={async ({rows}) => {
|
|
743
|
+
await api.put('/packing', rows.map((order, index) => ({order_id: order.id, priority: index + 1})));
|
|
744
|
+
setOrders(rows);
|
|
745
|
+
}} />
|
|
746
|
+
|
|
747
|
+
// en un formulario de formik: el valor del campo es la lista en su orden; al soltar, el formulario queda cambiado
|
|
748
|
+
<FormSortableField name="stops" ariaLabel="Ruta de reparto" columns={columns} />
|
|
749
|
+
// al guardar: values.stops.map((stop, index) => ({branch_id: stop.id, stop: index + 1}))
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
- `onReorder` recibe los renglones ya en su orden nuevo (`rows`), el id del que se movió y de dónde a dónde (desde 0). Si no
|
|
753
|
+
regresa nada, la pantalla pone los renglones nuevos. Si regresa una promesa, la tabla enseña el orden nuevo al instante,
|
|
754
|
+
no deja mover otro mientras se guarda y, si truena, lo regresa a su lugar y el lector de pantalla lo anuncia.
|
|
755
|
+
- El error de la lista (una regla de yup sobre el arreglo, o el 422 del servidor con `applyServerProblem`) sale abajo de la
|
|
756
|
+
tabla. Con react-hook-form: `SortableTable` dentro de un `Controller` (`rows={field.value}`,
|
|
757
|
+
`onReorder={({rows}) => field.onChange(rows)}`).
|
|
758
|
+
- Las columnas: `width` fijo, o `flex` y `minWidth` para repartirse el espacio libre; abajo de su mínimo, la tabla se desliza
|
|
759
|
+
de lado (en el teléfono). `renderCell(row, {position})` para una celda a la medida. Los renglones conservan su tipo en
|
|
760
|
+
TypeScript.
|
|
761
|
+
- `moveRow(rows, desde, hasta)` mueve sin arrastrar (un botón «Subir» de la pantalla). `showPosition={false}` quita la
|
|
762
|
+
columna «Orden»; `disabled` la deja de solo lectura; `texts` y el tema (`CalcitaSortableTable`) cambian lo demás.
|
|
763
|
+
|
|
685
764
|
## Eventos y textos de cada componente
|
|
686
765
|
|
|
687
766
|
Cada componente de la casa avisa hacia afuera todo lo que pasa adentro (`onSelect`, `onChange`, `onViewChange`,
|
|
@@ -12,7 +12,7 @@ import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.j
|
|
|
12
12
|
const THEME_NAME = "CalcitaServerTableFilterDrawer";
|
|
13
13
|
const ServerTableFilterDrawerButton = piecePart(THEME_NAME, "Button", Button);
|
|
14
14
|
function ServerTableFilterDrawerContent(props) {
|
|
15
|
-
const { fields, anchor, width, title, buttonLabel, onApply, children, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
15
|
+
const { fields, anchor, width, title, buttonLabel, onApply, stackPairsBelow, drawerProps, children, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
16
16
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
17
17
|
const { t } = useToolkitTranslation("common", texts);
|
|
18
18
|
const { filters, setFilters } = useTableFilter();
|
|
@@ -33,6 +33,7 @@ function ServerTableFilterDrawerContent(props) {
|
|
|
33
33
|
/* @__PURE__ */ jsx(
|
|
34
34
|
FilterDrawer,
|
|
35
35
|
{
|
|
36
|
+
...drawerProps,
|
|
36
37
|
open: isOpen,
|
|
37
38
|
onClose: () => setIsOpen(false),
|
|
38
39
|
fields,
|
|
@@ -40,6 +41,7 @@ function ServerTableFilterDrawerContent(props) {
|
|
|
40
41
|
anchor,
|
|
41
42
|
width,
|
|
42
43
|
title,
|
|
44
|
+
stackPairsBelow,
|
|
43
45
|
texts,
|
|
44
46
|
onApply: (values) => {
|
|
45
47
|
setFilters(values);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerTableFilterDrawer.js","sources":["../../src/DataTable/ServerTableFilterDrawer.jsx"],"sourcesContent":["// El botón «Filtros» de ServerTable con su cajón de búsqueda (FilterDrawer): se pone en toolbarExtra y lee y cambia los\n// filtros de SU tabla (los de la dirección, los mismos de los chips). El botón dice cuántos filtros del cajón hay puestos.\n//\n// const FILTER_FIELDS = [{name: 'total', label: 'Total', kind: FILTER_FIELD_KIND.comparison, prefix: '$'}, …];\n// <ServerTable … filterDefaults={{...MIS_DEFAULTS, ...filterDrawerDefaultsOf(FILTER_FIELDS)}}\n// filterKinds={{...MIS_KINDS, ...filterDrawerKindsOf(FILTER_FIELDS)}}\n// chipConfig={buildChipConfig(filterDrawerChipsOf(FILTER_FIELDS, {t, formatDate}))}\n// toolbarExtra={<ServerTableFilterDrawer fields={FILTER_FIELDS} />} />\n//\n// filterDefaults: la tabla solo guarda en la dirección lo que declara ahí. filterKinds: las listas se leen como lista. Los\n// chips dicen cada filtro en palabras y cada uno se quita con su ×.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaServerTableFilterDrawer con defaultProps, styleOverrides de\n// sus partes (button) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Button from '@mui/material/Button';\nimport TuneRoundedIcon from '@mui/icons-material/TuneRounded';\n\nimport {useTableFilter} from '@/DataTable/filterContext.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport FilterDrawer from '@/ui/filters/FilterDrawer.jsx';\nimport {activeDrawerFilterCountOf} from '@/ui/filters/filterDrawerFields.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaServerTableFilterDrawer)\nconst THEME_NAME = 'CalcitaServerTableFilterDrawer';\nconst ServerTableFilterDrawerButton = piecePart(THEME_NAME, 'Button', Button);\n\n/**\n * @param {object} props\n * @param {object[]} props.fields los campos del cajón (filterDrawerFields.js)\n * @param {'left'|'right'} [props.anchor] de qué lado sale; por omisión la derecha\n * @param {number} [props.width] su ancho en escritorio\n * @param {string} [props.title] ya traducido; por omisión «Filtros»\n * @param {string} [props.buttonLabel] ya traducido; por omisión «Filtros» (con los puestos, «Filtros (3)»)\n * @param {(values: Record<string, unknown>) => void} [props.onApply] aviso de lo que se buscó (la tabla ya se filtró)\n * @param {import('react').ReactNode} [props.children] algo más abajo de los campos del cajón\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction ServerTableFilterDrawerContent(props) {\n const {fields, anchor, width, title, buttonLabel, onApply, children, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const {filters, setFilters} = useTableFilter();\n const [isOpen, setIsOpen] = useState(false);\n const activeCount = activeDrawerFilterCountOf(fields, filters);\n\n return (\n <>\n <ServerTableFilterDrawerButton size=\"small\" variant={activeCount > 0 ? 'contained' : 'outlined'} startIcon={<TuneRoundedIcon />}\n aria-haspopup=\"dialog\" onClick={() => setIsOpen(true)}>\n {activeCount > 0 ? t('filterDrawer.openWithCount', {count: activeCount}) : (buttonLabel ?? t('filterDrawer.open'))}\n </ServerTableFilterDrawerButton>\n <FilterDrawer open={isOpen} onClose={() => setIsOpen(false)} fields={fields} values={filters} anchor={anchor} width={width}
|
|
1
|
+
{"version":3,"file":"ServerTableFilterDrawer.js","sources":["../../src/DataTable/ServerTableFilterDrawer.jsx"],"sourcesContent":["// El botón «Filtros» de ServerTable con su cajón de búsqueda (FilterDrawer): se pone en toolbarExtra y lee y cambia los\n// filtros de SU tabla (los de la dirección, los mismos de los chips). El botón dice cuántos filtros del cajón hay puestos.\n//\n// const FILTER_FIELDS = [{name: 'total', label: 'Total', kind: FILTER_FIELD_KIND.comparison, prefix: '$'}, …];\n// <ServerTable … filterDefaults={{...MIS_DEFAULTS, ...filterDrawerDefaultsOf(FILTER_FIELDS)}}\n// filterKinds={{...MIS_KINDS, ...filterDrawerKindsOf(FILTER_FIELDS)}}\n// chipConfig={buildChipConfig(filterDrawerChipsOf(FILTER_FIELDS, {t, formatDate}))}\n// toolbarExtra={<ServerTableFilterDrawer fields={FILTER_FIELDS} />} />\n//\n// filterDefaults: la tabla solo guarda en la dirección lo que declara ahí. filterKinds: las listas se leen como lista. Los\n// chips dicen cada filtro en palabras y cada uno se quita con su ×.\n//\n// Lo demás del cajón (su calendario propio, sus partes) va en drawerProps: <ServerTableFilterDrawer fields={…}\n// drawerProps={{slots: {dateInput: DateInput}}} />. Los slots de aquí son del botón.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaServerTableFilterDrawer con defaultProps, styleOverrides de\n// sus partes (button) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Button from '@mui/material/Button';\nimport TuneRoundedIcon from '@mui/icons-material/TuneRounded';\n\nimport {useTableFilter} from '@/DataTable/filterContext.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport FilterDrawer from '@/ui/filters/FilterDrawer.jsx';\nimport {activeDrawerFilterCountOf} from '@/ui/filters/filterDrawerFields.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaServerTableFilterDrawer)\nconst THEME_NAME = 'CalcitaServerTableFilterDrawer';\nconst ServerTableFilterDrawerButton = piecePart(THEME_NAME, 'Button', Button);\n\n/**\n * @param {object} props\n * @param {object[]} props.fields los campos del cajón (filterDrawerFields.js)\n * @param {'left'|'right'} [props.anchor] de qué lado sale; por omisión la derecha\n * @param {number} [props.width] su ancho en escritorio\n * @param {string} [props.title] ya traducido; por omisión «Filtros»\n * @param {string} [props.buttonLabel] ya traducido; por omisión «Filtros» (con los puestos, «Filtros (3)»)\n * @param {(values: Record<string, unknown>) => void} [props.onApply] aviso de lo que se buscó (la tabla ya se filtró)\n * @param {number} [props.stackPairsBelow] en px: si el cajón mide menos, cada par («desde» y «hasta») va uno arriba del otro\n * @param {object} [props.drawerProps] lo demás de FilterDrawer: slots (dateInput, body…), slotProps, applyLabel, closeOnApply\n * @param {import('react').ReactNode} [props.children] algo más abajo de los campos del cajón\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction ServerTableFilterDrawerContent(props) {\n const {fields, anchor, width, title, buttonLabel, onApply, stackPairsBelow, drawerProps, children, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const {filters, setFilters} = useTableFilter();\n const [isOpen, setIsOpen] = useState(false);\n const activeCount = activeDrawerFilterCountOf(fields, filters);\n\n return (\n <>\n <ServerTableFilterDrawerButton size=\"small\" variant={activeCount > 0 ? 'contained' : 'outlined'} startIcon={<TuneRoundedIcon />}\n aria-haspopup=\"dialog\" onClick={() => setIsOpen(true)}>\n {activeCount > 0 ? t('filterDrawer.openWithCount', {count: activeCount}) : (buttonLabel ?? t('filterDrawer.open'))}\n </ServerTableFilterDrawerButton>\n <FilterDrawer {...drawerProps} open={isOpen} onClose={() => setIsOpen(false)} fields={fields} values={filters} anchor={anchor} width={width}\n title={title} stackPairsBelow={stackPairsBelow} texts={texts}\n onApply={(values) => {\n setFilters(values);\n onApply?.(values);\n }}>\n {children}\n </FilterDrawer>\n </>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst ServerTableFilterDrawer = withPieceSlots(ServerTableFilterDrawerContent, THEME_NAME);\nexport default ServerTableFilterDrawer;\n"],"names":[],"mappings":";;;;;;;;;;;AA+BA,MAAM,aAAa;AACnB,MAAM,gCAAgC,UAAU,YAAY,UAAU,MAAM;AAe5E,SAAS,+BAA+B,OAAO;AAC3C,QAAM,EAAC,QAAQ,QAAQ,OAAO,OAAO,aAAa,SAAS,iBAAiB,aAAa,UAAU,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAC5J,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,EAAC,SAAS,WAAA,IAAc,eAAA;AAC9B,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,cAAc,0BAA0B,QAAQ,OAAO;AAE7D,SACI,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAA8B,MAAK;AAAA,QAAQ,SAAS,cAAc,IAAI,cAAc;AAAA,QAAY,+BAAY,iBAAA,EAAgB;AAAA,QACrH,iBAAc;AAAA,QAAS,SAAS,MAAM,UAAU,IAAI;AAAA,QACvD,UAAA,cAAc,IAAI,EAAE,8BAA8B,EAAC,OAAO,YAAA,CAAY,IAAK,eAAe,EAAE,mBAAmB;AAAA,MAAA;AAAA,IAAA;AAAA,IAEpH;AAAA,MAAC;AAAA,MAAA;AAAA,QAAc,GAAG;AAAA,QAAa,MAAM;AAAA,QAAQ,SAAS,MAAM,UAAU,KAAK;AAAA,QAAG;AAAA,QAAgB,QAAQ;AAAA,QAAS;AAAA,QAAgB;AAAA,QACjH;AAAA,QAAc;AAAA,QAAkC;AAAA,QAChD,SAAS,CAAC,WAAW;AACjB,qBAAW,MAAM;AACjB,oBAAU,MAAM;AAAA,QACpB;AAAA,QACT;AAAA,MAAA;AAAA,IAAA;AAAA,EACL,GACJ;AAER;AAGA,MAAM,0BAA0B,eAAe,gCAAgC,UAAU;"}
|
package/dist/locales/en.js
CHANGED
|
@@ -214,6 +214,8 @@ const en = Object.freeze({
|
|
|
214
214
|
"lte": "At most"
|
|
215
215
|
},
|
|
216
216
|
"rangeBackwards": "It must be equal to or greater than «From».",
|
|
217
|
+
"dateBeforeMin": "It cannot be before {{date}}.",
|
|
218
|
+
"dateAfterMax": "It cannot be after {{date}}.",
|
|
217
219
|
"chipFrom": "{{label}} from",
|
|
218
220
|
"chipTo": "{{label}} to"
|
|
219
221
|
},
|
|
@@ -955,6 +957,19 @@ const en = Object.freeze({
|
|
|
955
957
|
"emptyFiltered": "No card here matches the search.",
|
|
956
958
|
"empty": "No cards. Drag one here."
|
|
957
959
|
},
|
|
960
|
+
"sortableTable": {
|
|
961
|
+
"instructions": "To move a row with the keyboard: space to lift it, up and down arrows to move it and space to drop it. Escape leaves it where it was.",
|
|
962
|
+
"handleHeader": "Move",
|
|
963
|
+
"handle": "Move “{{title}}”, position {{position}}",
|
|
964
|
+
"position": "Order",
|
|
965
|
+
"lifted": "You lifted “{{title}}”, position {{position}} of {{total}}.",
|
|
966
|
+
"moving": "Going to position {{position}} of {{total}}.",
|
|
967
|
+
"dropped": "You dropped “{{title}}” in position {{position}} of {{total}}.",
|
|
968
|
+
"cancelled": "“{{title}}” stayed in position {{position}}.",
|
|
969
|
+
"reverted": "“{{title}}” could not be moved: it went back to position {{position}}.",
|
|
970
|
+
"empty": "No rows.",
|
|
971
|
+
"noValue": "—"
|
|
972
|
+
},
|
|
958
973
|
"inbox": {
|
|
959
974
|
"labels": "Labels",
|
|
960
975
|
"select": "Select “{{subject}}”",
|