@stackcraftmx/calcita 0.57.0 → 0.59.1

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.
@@ -0,0 +1,312 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { useId, useState, useRef, useEffect } from "react";
4
+ import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
5
+ import Box from "@mui/material/Box";
6
+ import FormHelperText from "@mui/material/FormHelperText";
7
+ import IconButton from "@mui/material/IconButton";
8
+ import Paper from "@mui/material/Paper";
9
+ import Table from "@mui/material/Table";
10
+ import TableBody from "@mui/material/TableBody";
11
+ import TableCell from "@mui/material/TableCell";
12
+ import TableContainer from "@mui/material/TableContainer";
13
+ import TableHead from "@mui/material/TableHead";
14
+ import TableRow from "@mui/material/TableRow";
15
+ import Tooltip from "@mui/material/Tooltip";
16
+ import DragIndicatorRoundedIcon from "@mui/icons-material/DragIndicatorRounded";
17
+ import KeyboardArrowDownRoundedIcon from "@mui/icons-material/KeyboardArrowDownRounded";
18
+ import KeyboardArrowUpRoundedIcon from "@mui/icons-material/KeyboardArrowUpRounded";
19
+ import { moveRow } from "./sortableRows.js";
20
+ import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
21
+ import { warnUnknownProps } from "../toolkit/unknownProps.js";
22
+ import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
23
+ const THEME_NAME = "CalcitaSortableTable";
24
+ const SortableRoot = piecePart(THEME_NAME, "Root", Box);
25
+ const SortableContainer = piecePart(THEME_NAME, "Container", TableContainer);
26
+ const SortableTableElement = piecePart(THEME_NAME, "Table", Table);
27
+ const SortableHead = piecePart(THEME_NAME, "Head", TableHead);
28
+ const SortableHeaderRow = piecePart(THEME_NAME, "HeaderRow", TableRow);
29
+ const SortableHeaderCell = piecePart(THEME_NAME, "HeaderCell", TableCell);
30
+ const SortableBody = piecePart(THEME_NAME, "Body", TableBody);
31
+ const SortableRow = piecePart(THEME_NAME, "Row", TableRow);
32
+ const SortableHandleCell = piecePart(THEME_NAME, "HandleCell", TableCell);
33
+ const SortableHandle = piecePart(THEME_NAME, "Handle", Box);
34
+ const SortablePositionCell = piecePart(THEME_NAME, "PositionCell", TableCell);
35
+ const SortableCell = piecePart(THEME_NAME, "Cell", TableCell);
36
+ const SortableMoveCell = piecePart(THEME_NAME, "MoveCell", TableCell);
37
+ const SortableMoveButton = piecePart(THEME_NAME, "MoveButton", IconButton);
38
+ const SortableEmpty = piecePart(THEME_NAME, "Empty", TableCell);
39
+ const SortableHelperText = piecePart(THEME_NAME, "HelperText", FormHelperText);
40
+ const SortableAnnouncer = piecePart(THEME_NAME, "Announcer", Box);
41
+ const HANDLE_COLUMN_WIDTH_PIXELS = 48;
42
+ const POSITION_COLUMN_WIDTH_PIXELS = 88;
43
+ const HOUSE_COLUMN_PADDING_X = 1.5;
44
+ const MOVE_COLUMN_WIDTH_PIXELS = 88;
45
+ const MOVE_BUTTONS = Object.freeze([
46
+ { direction: "up", step: -1, Icon: KeyboardArrowUpRoundedIcon, labelKey: "moveUp", hintKey: "moveUpHint" },
47
+ { direction: "down", step: 1, Icon: KeyboardArrowDownRoundedIcon, labelKey: "moveDown", hintKey: "moveDownHint" }
48
+ ]);
49
+ const DEFAULT_COLUMN_MIN_WIDTH_PIXELS = 96;
50
+ const VISUALLY_HIDDEN_SX = { position: "absolute", width: "1px", height: "1px", padding: 0, margin: "-1px", overflow: "hidden", clip: "rect(0 0 0 0)", whiteSpace: "nowrap", border: 0 };
51
+ const JUSTIFY_BY_ALIGN = Object.freeze({ left: "flex-start", center: "center", right: "flex-end" });
52
+ function trackOf(column) {
53
+ if (column.width) {
54
+ return `${column.width}px`;
55
+ }
56
+ return `minmax(${column.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH_PIXELS}px, ${column.flex ?? 1}fr)`;
57
+ }
58
+ function isPromiseLike(value) {
59
+ return typeof value?.then === "function";
60
+ }
61
+ function SortableTableContent(props) {
62
+ const {
63
+ rows,
64
+ columns,
65
+ onReorder,
66
+ ariaLabel,
67
+ getRowId = (row) => row.id,
68
+ getRowLabel,
69
+ showPosition = true,
70
+ moveButtons = true,
71
+ disabled = false,
72
+ error,
73
+ helperText,
74
+ sx,
75
+ texts,
76
+ ...unknownProps
77
+ } = usePieceProps(props, THEME_NAME);
78
+ warnUnknownProps(THEME_NAME, unknownProps);
79
+ const { t } = useToolkitTranslation("sortableTable", texts);
80
+ const helperId = useId();
81
+ const listId = useId();
82
+ const [pending, setPending] = useState(null);
83
+ const [notice, setNotice] = useState("");
84
+ const handlePropsByRow = useRef(/* @__PURE__ */ new Map());
85
+ const shownRows = pending && pending.basedOn === rows ? pending.rows : rows;
86
+ const isSaving = Boolean(pending && pending.basedOn === rows && pending.saving);
87
+ const canDrag = !disabled && !isSaving;
88
+ const total = shownRows.length;
89
+ const labelOf = (row) => String(getRowLabel ? getRowLabel(row) : row[columns[0]?.field] ?? getRowId(row));
90
+ const rowOfDraggable = (draggableId) => shownRows.find((row) => String(getRowId(row)) === draggableId);
91
+ const titleOf = (draggableId) => {
92
+ const row = rowOfDraggable(draggableId);
93
+ return row ? labelOf(row) : draggableId;
94
+ };
95
+ const handlePropsOf = (rowId, dragHandleProps) => {
96
+ if (dragHandleProps) {
97
+ handlePropsByRow.current.set(rowId, dragHandleProps);
98
+ return dragHandleProps;
99
+ }
100
+ return handlePropsByRow.current.get(rowId) ?? { tabIndex: 0, role: "button" };
101
+ };
102
+ const moveButtonsByRow = useRef(/* @__PURE__ */ new Map());
103
+ const focusAfterMove = useRef(null);
104
+ const rememberMoveButton = (rowId, direction) => (element) => {
105
+ const buttons = moveButtonsByRow.current.get(rowId) ?? {};
106
+ buttons[direction] = element;
107
+ moveButtonsByRow.current.set(rowId, buttons);
108
+ };
109
+ const keepFocusOnMoveButton = (rowId, expectedIndex) => {
110
+ const buttons = moveButtonsByRow.current.get(rowId);
111
+ const focused = MOVE_BUTTONS.find(({ direction }) => buttons?.[direction] && buttons[direction] === document.activeElement);
112
+ focusAfterMove.current = focused ? { rowId, direction: focused.direction, expectedIndex } : null;
113
+ };
114
+ useEffect(() => {
115
+ const wanted = focusAfterMove.current;
116
+ if (!wanted) {
117
+ return;
118
+ }
119
+ const index = shownRows.findIndex((row) => String(getRowId(row)) === wanted.rowId);
120
+ if (index !== -1 && index !== wanted.expectedIndex) {
121
+ return;
122
+ }
123
+ focusAfterMove.current = null;
124
+ const buttons = moveButtonsByRow.current.get(wanted.rowId);
125
+ const pressed = MOVE_BUTTONS.find(({ direction }) => direction === wanted.direction);
126
+ const reachedEdge = index + pressed.step < 0 || index + pressed.step >= shownRows.length;
127
+ const opposite = MOVE_BUTTONS.find(({ direction }) => direction !== wanted.direction);
128
+ buttons?.[reachedEdge ? opposite.direction : pressed.direction]?.focus();
129
+ });
130
+ const reorder = (row, fromIndex, toIndex) => {
131
+ const movedRows = moveRow(shownRows, fromIndex, toIndex);
132
+ const outcome = onReorder({ rows: movedRows, rowId: getRowId(row), fromIndex, toIndex });
133
+ if (!isPromiseLike(outcome)) {
134
+ return;
135
+ }
136
+ const attempt = { rows: movedRows, basedOn: rows, saving: true };
137
+ setPending(attempt);
138
+ outcome.then(
139
+ () => setPending((current) => current === attempt ? { ...attempt, saving: false } : current),
140
+ () => {
141
+ keepFocusOnMoveButton(String(getRowId(row)), fromIndex);
142
+ setPending((current) => current === attempt ? null : current);
143
+ setNotice(t("reverted", { title: labelOf(row), position: fromIndex + 1 }));
144
+ }
145
+ );
146
+ };
147
+ const moveWithButton = (row, index, step) => {
148
+ const toIndex = index + step;
149
+ if (!canDrag || toIndex < 0 || toIndex >= total) {
150
+ return;
151
+ }
152
+ keepFocusOnMoveButton(String(getRowId(row)), toIndex);
153
+ setNotice(t("moved", { title: labelOf(row), fromPosition: index + 1, position: toIndex + 1, total }));
154
+ reorder(row, index, toIndex);
155
+ };
156
+ const announceStart = (start, provided) => {
157
+ focusAfterMove.current = null;
158
+ setNotice("");
159
+ provided.announce(t("lifted", { title: titleOf(start.draggableId), position: start.source.index + 1, total }));
160
+ };
161
+ const announceUpdate = (update, provided) => {
162
+ const { draggableId, source, destination } = update;
163
+ if (!destination) {
164
+ return;
165
+ }
166
+ const key = destination.index === source.index ? "movingBack" : "moving";
167
+ provided.announce(t(key, {
168
+ title: titleOf(draggableId),
169
+ fromPosition: source.index + 1,
170
+ position: destination.index + 1,
171
+ total
172
+ }));
173
+ };
174
+ const finishMove = (result, provided) => {
175
+ const { draggableId, source, destination } = result;
176
+ const row = rowOfDraggable(draggableId);
177
+ if (!row || !destination || destination.index === source.index) {
178
+ provided.announce(t("cancelled", { title: titleOf(draggableId), position: source.index + 1 }));
179
+ return;
180
+ }
181
+ provided.announce(t("dropped", {
182
+ title: labelOf(row),
183
+ fromPosition: source.index + 1,
184
+ position: destination.index + 1,
185
+ total
186
+ }));
187
+ reorder(row, source.index, destination.index);
188
+ };
189
+ const gridTemplateColumns = [
190
+ `${HANDLE_COLUMN_WIDTH_PIXELS}px`,
191
+ ...showPosition ? [`${POSITION_COLUMN_WIDTH_PIXELS}px`] : [],
192
+ ...columns.map(trackOf),
193
+ ...moveButtons ? [`${MOVE_COLUMN_WIDTH_PIXELS}px`] : []
194
+ ].join(" ");
195
+ const minimumWidth = HANDLE_COLUMN_WIDTH_PIXELS + (showPosition ? POSITION_COLUMN_WIDTH_PIXELS : 0) + (moveButtons ? MOVE_COLUMN_WIDTH_PIXELS : 0) + columns.reduce((sum, column) => sum + (column.width ?? column.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH_PIXELS), 0);
196
+ const rowSx = { display: "grid", gridTemplateColumns };
197
+ const cellSx = (align = "left") => ({ display: "flex", alignItems: "center", minWidth: 0, justifyContent: JUSTIFY_BY_ALIGN[align], textAlign: align, overflowWrap: "break-word" });
198
+ const houseCellSx = (align) => ({ ...cellSx(align), px: HOUSE_COLUMN_PADDING_X });
199
+ const bottomText = error || helperText;
200
+ return /* @__PURE__ */ jsxs(SortableRoot, { sx, children: [
201
+ /* @__PURE__ */ jsx(SortableContainer, { component: Paper, variant: "outlined", ownSx: { overflowX: "auto", position: "relative" }, children: /* @__PURE__ */ jsxs(
202
+ SortableTableElement,
203
+ {
204
+ component: "div",
205
+ "aria-label": ariaLabel,
206
+ "aria-busy": isSaving || void 0,
207
+ "aria-describedby": bottomText ? helperId : void 0,
208
+ ownSx: { display: "block", minWidth: minimumWidth },
209
+ children: [
210
+ /* @__PURE__ */ jsx(SortableHead, { component: "div", ownSx: { display: "block" }, children: /* @__PURE__ */ jsxs(SortableHeaderRow, { component: "div", ownSx: rowSx, children: [
211
+ /* @__PURE__ */ jsx(SortableHeaderCell, { component: "div", role: "columnheader", ownSx: houseCellSx("center"), children: /* @__PURE__ */ jsx(Box, { component: "span", sx: VISUALLY_HIDDEN_SX, children: t("handleHeader") }) }),
212
+ showPosition && /* @__PURE__ */ jsx(SortableHeaderCell, { component: "div", role: "columnheader", ownSx: houseCellSx("right"), children: t("position") }),
213
+ columns.map((column) => /* @__PURE__ */ jsx(SortableHeaderCell, { component: "div", role: "columnheader", ownSx: cellSx(column.align), children: column.headerName }, column.field)),
214
+ moveButtons && /* @__PURE__ */ jsx(SortableHeaderCell, { component: "div", role: "columnheader", ownSx: houseCellSx("center"), children: /* @__PURE__ */ jsx(Box, { component: "span", sx: VISUALLY_HIDDEN_SX, children: t("moveHeader") }) })
215
+ ] }) }),
216
+ /* @__PURE__ */ jsx(
217
+ DragDropContext,
218
+ {
219
+ onDragStart: announceStart,
220
+ onDragUpdate: announceUpdate,
221
+ onDragEnd: finishMove,
222
+ dragHandleUsageInstructions: t("instructions"),
223
+ children: /* @__PURE__ */ jsx(Droppable, { droppableId: listId, children: (droppableProvided) => /* @__PURE__ */ jsxs(
224
+ SortableBody,
225
+ {
226
+ component: "div",
227
+ ref: droppableProvided.innerRef,
228
+ ...droppableProvided.droppableProps,
229
+ ownSx: { display: "block", "& > .MuiTableRow-root:last-of-type > .MuiTableCell-root": { borderBottom: 0 } },
230
+ children: [
231
+ shownRows.map((row, index) => {
232
+ const rowId = String(getRowId(row));
233
+ const label = labelOf(row);
234
+ return /* @__PURE__ */ jsx(Draggable, { draggableId: rowId, index, isDragDisabled: !canDrag, children: (draggableProvided, draggableSnapshot) => /* @__PURE__ */ jsxs(
235
+ SortableRow,
236
+ {
237
+ component: "div",
238
+ ref: draggableProvided.innerRef,
239
+ ...draggableProvided.draggableProps,
240
+ ownSx: {
241
+ ...rowSx,
242
+ // el que flota lleva fondo y sombra: sin eso se transparenta sobre los demás
243
+ ...draggableSnapshot.isDragging && { bgcolor: "background.paper", boxShadow: 8, borderRadius: 1 }
244
+ },
245
+ children: [
246
+ /* @__PURE__ */ jsx(SortableHandleCell, { component: "div", role: "cell", ownSx: houseCellSx("center"), children: /* @__PURE__ */ jsx(
247
+ SortableHandle,
248
+ {
249
+ component: "span",
250
+ ...handlePropsOf(rowId, draggableProvided.dragHandleProps),
251
+ "aria-label": t("handle", { title: label, position: index + 1 }),
252
+ "aria-disabled": !canDrag || void 0,
253
+ ownSx: {
254
+ display: "inline-flex",
255
+ p: 0.5,
256
+ borderRadius: 1,
257
+ color: canDrag ? "text.secondary" : "text.disabled",
258
+ cursor: canDrag ? draggableSnapshot.isDragging ? "grabbing" : "grab" : "default",
259
+ "&:focus-visible": { outline: 2, outlineColor: "primary.main", outlineOffset: 1 }
260
+ },
261
+ children: /* @__PURE__ */ jsx(DragIndicatorRoundedIcon, { fontSize: "small" })
262
+ }
263
+ ) }),
264
+ showPosition && /* @__PURE__ */ jsx(
265
+ SortablePositionCell,
266
+ {
267
+ component: "div",
268
+ role: "cell",
269
+ ownSx: { ...houseCellSx("right"), fontVariantNumeric: "tabular-nums", color: "text.secondary" },
270
+ children: index + 1
271
+ }
272
+ ),
273
+ columns.map((column) => /* @__PURE__ */ jsx(SortableCell, { component: "div", role: "cell", ownSx: cellSx(column.align), children: column.renderCell ? column.renderCell(row, { index, position: index + 1 }) : row[column.field] ?? t("noValue") }, column.field)),
274
+ moveButtons && /* @__PURE__ */ jsx(SortableMoveCell, { component: "div", role: "cell", ownSx: { ...houseCellSx("center"), gap: 0.5 }, children: MOVE_BUTTONS.map(({ direction, step, Icon, labelKey, hintKey }) => (
275
+ // el span deja que el globo salga también con el botón apagado (regla de MUI)
276
+ /* @__PURE__ */ jsx(Tooltip, { title: t(hintKey), children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
277
+ SortableMoveButton,
278
+ {
279
+ size: "small",
280
+ ref: rememberMoveButton(rowId, direction),
281
+ "aria-label": t(labelKey, { title: label }),
282
+ disabled: disabled || index + step < 0 || index + step >= total,
283
+ "aria-disabled": isSaving || void 0,
284
+ onClick: () => moveWithButton(row, index, step),
285
+ ownSx: isSaving ? { color: "text.disabled" } : void 0,
286
+ children: /* @__PURE__ */ jsx(Icon, { fontSize: "small" })
287
+ }
288
+ ) }) }, direction)
289
+ )) })
290
+ ]
291
+ }
292
+ ) }, rowId);
293
+ }),
294
+ droppableProvided.placeholder,
295
+ total === 0 && /* @__PURE__ */ jsx(TableRow, { component: "div", sx: rowSx, children: /* @__PURE__ */ jsx(SortableEmpty, { component: "div", role: "cell", ownSx: { gridColumn: "1 / -1", color: "text.secondary", textAlign: "center", py: 3 }, children: t("empty") }) })
296
+ ]
297
+ }
298
+ ) })
299
+ }
300
+ )
301
+ ]
302
+ }
303
+ ) }),
304
+ bottomText && /* @__PURE__ */ jsx(SortableHelperText, { id: helperId, error: Boolean(error), children: bottomText }),
305
+ /* @__PURE__ */ jsx(SortableAnnouncer, { role: "status", "aria-live": "polite", ownSx: VISUALLY_HIDDEN_SX, children: notice })
306
+ ] });
307
+ }
308
+ const SortableTable = withPieceSlots(SortableTableContent, THEME_NAME);
309
+ export {
310
+ SortableTable as default
311
+ };
312
+ //# sourceMappingURL=SortableTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SortableTable.js","sources":["../../src/sortable/SortableTable.jsx"],"sourcesContent":["// Una tabla chica donde el orden de los renglones es el dato (@stackcraftmx/calcita/sortable): qué se hace primero, en qué\n// orden pasa la ruta. Los renglones se arrastran con el ratón, con el dedo o con el teclado (espacio para levantar, flechas\n// para mover, espacio para soltar), y la columna «Orden» se renumera 1..n. Con @hello-pangea/dnd por dentro, la misma del\n// tablero kanban.\n//\n// <SortableTable rows={stops} columns={[{field: 'name', headerName: 'Sucursal', flex: 1}]} ariaLabel=\"Ruta de reparto\"\n// onReorder={({rows}) => setStops(rows)} />\n//\n// Dos formas de guardar, según lo que regrese onReorder:\n// - nada (en un formulario: se guarda al final con su botón): la pantalla pone los renglones nuevos (rows) y la tabla los\n// enseña. FormSortableField lo hace con formik y marca el formulario como cambiado;\n// - una promesa (se guarda al soltar): la tabla enseña el orden nuevo al instante y, si la promesa truena (el servidor dijo\n// que no), el renglón regresa a donde estaba y el lector de pantalla lo anuncia; mientras se guarda no se arrastra otro.\n// Al cumplirse, la pantalla pone los renglones nuevos o los vuelve a pedir.\n//\n// Para lo que no va en una tabla de servidor: la tabla de MUI X gratis no ordena renglones arrastrando (es de su versión de\n// paga), así que esta lista va completa en el navegador, sin páginas.\n//\n// OJO trampa: un renglón que se arrastra flota (position fixed) y en una tabla de HTML pierde el ancho de sus columnas. Aquí\n// la tabla de MUI se pinta con divisiones (role table, row y cell) y cada renglón es una cuadrícula con las mismas columnas:\n// el que flota conserva su ancho. El estilo del tema del proyecto para MuiTableCell se le aplica igual.\n//\n// Mover sin arrastrar: cada renglón trae «Subir» y «Bajar» en la última columna (moveButtons, por omisión sí). La regla de\n// accesibilidad lo pide (WCAG 2.5.7: lo que se arrastra también se hace con un clic, para quien no puede sostener y mover el\n// ratón o el dedo). Cada clic mueve el renglón un lugar y guarda igual que soltarlo. Para mover desde otra parte (un menú\n// «Mandar al final»): moveRow de sortableRows.js.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSortableTable con defaultProps y\n// styleOverrides de sus partes: root, container, table, head, headerRow, headerCell, body, row, handleCell, handle, positionCell,\n// cell, moveCell, moveButton, empty, helperText, announcer.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useId, useRef, useState} from 'react';\nimport {DragDropContext, Draggable, Droppable} from '@hello-pangea/dnd';\nimport Box from '@mui/material/Box';\nimport FormHelperText from '@mui/material/FormHelperText';\nimport IconButton from '@mui/material/IconButton';\nimport Paper from '@mui/material/Paper';\nimport Table from '@mui/material/Table';\nimport TableBody from '@mui/material/TableBody';\nimport TableCell from '@mui/material/TableCell';\nimport TableContainer from '@mui/material/TableContainer';\nimport TableHead from '@mui/material/TableHead';\nimport TableRow from '@mui/material/TableRow';\nimport Tooltip from '@mui/material/Tooltip';\nimport DragIndicatorRoundedIcon from '@mui/icons-material/DragIndicatorRounded';\nimport KeyboardArrowDownRoundedIcon from '@mui/icons-material/KeyboardArrowDownRounded';\nimport KeyboardArrowUpRoundedIcon from '@mui/icons-material/KeyboardArrowUpRounded';\n\nimport {moveRow} from '@/sortable/sortableRows.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\n\nconst THEME_NAME = 'CalcitaSortableTable';\nconst SortableRoot = piecePart(THEME_NAME, 'Root', Box);\nconst SortableContainer = piecePart(THEME_NAME, 'Container', TableContainer);\nconst SortableTableElement = piecePart(THEME_NAME, 'Table', Table);\nconst SortableHead = piecePart(THEME_NAME, 'Head', TableHead);\nconst SortableHeaderRow = piecePart(THEME_NAME, 'HeaderRow', TableRow);\nconst SortableHeaderCell = piecePart(THEME_NAME, 'HeaderCell', TableCell);\nconst SortableBody = piecePart(THEME_NAME, 'Body', TableBody);\nconst SortableRow = piecePart(THEME_NAME, 'Row', TableRow);\nconst SortableHandleCell = piecePart(THEME_NAME, 'HandleCell', TableCell);\nconst SortableHandle = piecePart(THEME_NAME, 'Handle', Box);\nconst SortablePositionCell = piecePart(THEME_NAME, 'PositionCell', TableCell);\nconst SortableCell = piecePart(THEME_NAME, 'Cell', TableCell);\nconst SortableMoveCell = piecePart(THEME_NAME, 'MoveCell', TableCell);\nconst SortableMoveButton = piecePart(THEME_NAME, 'MoveButton', IconButton);\nconst SortableEmpty = piecePart(THEME_NAME, 'Empty', TableCell);\nconst SortableHelperText = piecePart(THEME_NAME, 'HelperText', FormHelperText);\nconst SortableAnnouncer = piecePart(THEME_NAME, 'Announcer', Box);\n\n// las columnas de la casa, con menos relleno a los lados que las demás: la del asa (el ícono y su foco) y la del orden\n// (OJO: con 72 px y el relleno de siempre, «Orden» se partía en «Orde / n»; con 88 caben «Orden», «Order» o «Prioridad»)\nconst HANDLE_COLUMN_WIDTH_PIXELS = 48;\nconst POSITION_COLUMN_WIDTH_PIXELS = 88;\nconst HOUSE_COLUMN_PADDING_X = 1.5;\n// la columna de «Subir» y «Bajar»: dos botones chicos (30 px cada uno), su separación y el relleno de la casa\nconst MOVE_COLUMN_WIDTH_PIXELS = 88;\n// los dos botones de cada renglón para mover sin arrastrar: cuántos lugares se mueve con cada uno, su ícono y sus textos\nconst MOVE_BUTTONS = Object.freeze([\n {direction: 'up', step: -1, Icon: KeyboardArrowUpRoundedIcon, labelKey: 'moveUp', hintKey: 'moveUpHint'},\n {direction: 'down', step: 1, Icon: KeyboardArrowDownRoundedIcon, labelKey: 'moveDown', hintKey: 'moveDownHint'},\n]);\n// lo mínimo de una columna sin ancho fijo: abajo de eso la tabla se desliza de lado (en el teléfono)\nconst DEFAULT_COLUMN_MIN_WIDTH_PIXELS = 96;\n// lo que se ve, solo para el lector de pantalla\nconst VISUALLY_HIDDEN_SX = {position: 'absolute', width: '1px', height: '1px', padding: 0, margin: '-1px', overflow: 'hidden', clip: 'rect(0 0 0 0)', whiteSpace: 'nowrap', border: 0};\nconst JUSTIFY_BY_ALIGN = Object.freeze({left: 'flex-start', center: 'center', right: 'flex-end'});\n\n/**\n * Una columna de la tabla. Row: el renglón de la pantalla (llega tal cual a renderCell).\n *\n * @template Row\n * @typedef {object} SortableTableColumn\n * @property {string} field la llave del renglón que se pinta (y la del encabezado)\n * @property {string} headerName el encabezado, ya traducido\n * @property {number} [width] ancho fijo en px\n * @property {number} [flex] cuánto del espacio libre toma, como en la tabla de servidor (por omisión 1)\n * @property {number} [minWidth] el mínimo en px de una columna sin ancho fijo (por omisión 96)\n * @property {'left'|'center'|'right'} [align] los números a la derecha\n * @property {(row: Row, place: {index: number, position: number}) => import('react').ReactNode} [renderCell] lo de la celda a la\n * medida; position es la que ve la persona (desde 1)\n */\n\n/** La pista de la cuadrícula de una columna: el ancho fijo, o lo que le toque del espacio libre sin bajar de su mínimo. */\nfunction trackOf(column) {\n if (column.width) {\n return `${column.width}px`;\n }\n return `minmax(${column.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH_PIXELS}px, ${column.flex ?? 1}fr)`;\n}\n\n/** Una función que regresa una promesa: se guarda al soltar. */\nfunction isPromiseLike(value) {\n return typeof value?.then === 'function';\n}\n\n/**\n * Los renglones conservan el tipo que usa la pantalla (Row): onReorder los regresa del mismo tipo, ya en su orden nuevo.\n *\n * @template {object} Row\n * @param {object} props\n * @param {Row[]} props.rows en su orden\n * @param {SortableTableColumn<Row>[]} props.columns\n * @param {(change: {rows: Row[], rowId: string|number, fromIndex: number, toIndex: number}) => Promise<unknown>|void} props.onReorder\n * al soltar un renglón en otro lugar: rows ya en el orden nuevo; fromIndex y toIndex desde 0. Si regresa una promesa, el\n * orden nuevo se enseña mientras se cumple y regresa si truena\n * @param {string} props.ariaLabel qué es la tabla, ya traducido\n * @param {(row: Row) => string|number} [props.getRowId] por omisión row.id\n * @param {(row: Row) => string} [props.getRowLabel] el nombre del renglón que oye el lector de pantalla («Polanco»); por omisión\n * lo de la primera columna\n * @param {boolean} [props.showPosition] la columna «Orden» con 1..n (por omisión sí)\n * @param {boolean} [props.moveButtons] «Subir» y «Bajar» en cada renglón, para mover sin arrastrar (por omisión sí: lo pide la\n * regla de accesibilidad WCAG 2.5.7); false los quita\n * @param {boolean} [props.disabled] nada se arrastra ni se mueve (mientras se envía el formulario, o de solo lectura)\n * @param {import('react').ReactNode} [props.error] el error de la lista (en rojo, abajo de la tabla)\n * @param {import('react').ReactNode} [props.helperText] una ayuda abajo de la tabla (el error gana)\n * @param {import('@mui/material').SxProps<import('@mui/material').Theme>} [props.sx] lo de afuera de la tabla\n * @param {object} [props.texts] los textos que cambian, con la forma de `sortableTable` en los textos del paquete\n */\nfunction SortableTableContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaSortableTable.defaultProps) y encima lo que llega aquí\n const {\n rows, columns, onReorder, ariaLabel, getRowId = (row) => row.id, getRowLabel, showPosition = true, moveButtons = true,\n disabled = false, error, helperText, sx, texts, ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('sortableTable', texts);\n const helperId = useId();\n const listId = useId();\n // un orden que se está guardando (o ya se guardó y la pantalla todavía no da los renglones nuevos); vale mientras rows\n // sea el mismo arreglo sobre el que se movió\n const [pending, setPending] = useState(null);\n // lo último que se anunció fuera del arrastre (el renglón que regresó)\n const [notice, setNotice] = useState('');\n // el asa que la librería le dio a cada renglón la última vez que se podía arrastrar (ver la trampa en el asa)\n const handlePropsByRow = useRef(new Map());\n const shownRows = pending && pending.basedOn === rows ? pending.rows : rows;\n const isSaving = Boolean(pending && pending.basedOn === rows && pending.saving);\n const canDrag = !disabled && !isSaving;\n const total = shownRows.length;\n\n const labelOf = (row) => String(getRowLabel ? getRowLabel(row) : (row[columns[0]?.field] ?? getRowId(row)));\n const rowOfDraggable = (draggableId) => shownRows.find((row) => String(getRowId(row)) === draggableId);\n const titleOf = (draggableId) => {\n const row = rowOfDraggable(draggableId);\n return row ? labelOf(row) : draggableId;\n };\n\n // OJO trampa pagada: sin poder arrastrar (mientras se guarda) la librería no da el asa. Sin ella, quien soltó con el\n // teclado se quedaba sin foco, y la librería (que busca el asa para devolverle el foco al soltar) avisaba en la consola\n // que no la encontraba. Mientras tanto se queda con la que tuvo la última vez: con el renglón apagado no arranca otro\n // arrastre (la librería lo revisa en su registro, no en el asa). Sin una de antes (apagada desde el principio), solo\n // recibe el foco.\n const handlePropsOf = (rowId, dragHandleProps) => {\n if (dragHandleProps) {\n handlePropsByRow.current.set(rowId, dragHandleProps);\n return dragHandleProps;\n }\n return handlePropsByRow.current.get(rowId) ?? {tabIndex: 0, role: 'button'};\n };\n\n // los botones «Subir» y «Bajar» ya pintados de cada renglón (para regresarles el foco) y a cuál se le regresa\n const moveButtonsByRow = useRef(new Map());\n const focusAfterMove = useRef(null);\n const rememberMoveButton = (rowId, direction) => (element) => {\n const buttons = moveButtonsByRow.current.get(rowId) ?? {};\n buttons[direction] = element;\n moveButtonsByRow.current.set(rowId, buttons);\n };\n\n // OJO trampa pagada: al cambiar el orden, React a veces saca la división del renglón movido y la vuelve a meter en su lugar\n // nuevo (medido en Chrome: al bajar sí, al subir no), y el navegador le quita el foco a lo que se saca: quien movía con el\n // teclado se quedaba sin foco y tenía que volver a buscar el renglón. Si el foco estaba en un botón del renglón, se le\n // regresa cuando el renglón se pinta en expectedIndex (al botón de enfrente si ya llegó a la orilla y se apagó). Con el\n // ratón en Safari el botón no se lleva el foco: ahí no se toca.\n const keepFocusOnMoveButton = (rowId, expectedIndex) => {\n const buttons = moveButtonsByRow.current.get(rowId);\n const focused = MOVE_BUTTONS.find(({direction}) => buttons?.[direction] && buttons[direction] === document.activeElement);\n focusAfterMove.current = focused ? {rowId, direction: focused.direction, expectedIndex} : null;\n };\n useEffect(() => {\n const wanted = focusAfterMove.current;\n if (!wanted) {\n return;\n }\n const index = shownRows.findIndex((row) => String(getRowId(row)) === wanted.rowId);\n // todavía no se pinta en su lugar nuevo: la pantalla no ha dado los renglones\n if (index !== -1 && index !== wanted.expectedIndex) {\n return;\n }\n focusAfterMove.current = null;\n const buttons = moveButtonsByRow.current.get(wanted.rowId);\n const pressed = MOVE_BUTTONS.find(({direction}) => direction === wanted.direction);\n const reachedEdge = index + pressed.step < 0 || index + pressed.step >= shownRows.length;\n const opposite = MOVE_BUTTONS.find(({direction}) => direction !== wanted.direction);\n buttons?.[reachedEdge ? opposite.direction : pressed.direction]?.focus();\n });\n\n const reorder = (row, fromIndex, toIndex) => {\n const movedRows = moveRow(shownRows, fromIndex, toIndex);\n const outcome = onReorder({rows: movedRows, rowId: getRowId(row), fromIndex, toIndex});\n // sin promesa: la pantalla ya puso sus renglones (un formulario); nada que esperar\n if (!isPromiseLike(outcome)) {\n return;\n }\n const attempt = {rows: movedRows, basedOn: rows, saving: true};\n setPending(attempt);\n outcome.then(\n () => setPending((current) => (current === attempt ? {...attempt, saving: false} : current)),\n () => {\n // el servidor dijo que no: se enseñan otra vez los renglones de la pantalla (el orden de antes), y si el foco\n // estaba en «Subir» o «Bajar» de ese renglón, lo sigue a su lugar de antes\n keepFocusOnMoveButton(String(getRowId(row)), fromIndex);\n setPending((current) => (current === attempt ? null : current));\n setNotice(t('reverted', {title: labelOf(row), position: fromIndex + 1}));\n },\n );\n };\n\n // un lugar arriba o abajo con su botón: guarda igual que soltarlo; mientras se guarda, el botón conserva el foco pero no\n // mueve (y en la orilla está apagado)\n const moveWithButton = (row, index, step) => {\n const toIndex = index + step;\n if (!canDrag || toIndex < 0 || toIndex >= total) {\n return;\n }\n keepFocusOnMoveButton(String(getRowId(row)), toIndex);\n setNotice(t('moved', {title: labelOf(row), fromPosition: index + 1, position: toIndex + 1, total}));\n reorder(row, index, toIndex);\n };\n\n // lo que oye quien usa lector de pantalla (posiciones desde 1, como se cuentan). Cada aviso de una movida dice qué\n // renglón, de qué lugar salió y a cuál va (guía de accesibilidad de arrastrar de Atlassian); position siempre es el\n // lugar nuevo, así los textos propios de un proyecto que solo usan {{position}} siguen diciendo lo correcto\n const announceStart = (start, provided) => {\n // se empezó a arrastrar: ya no se espera regresarle el foco a un botón\n focusAfterMove.current = null;\n setNotice('');\n provided.announce(t('lifted', {title: titleOf(start.draggableId), position: start.source.index + 1, total}));\n };\n const announceUpdate = (update, provided) => {\n const {draggableId, source, destination} = update;\n if (!destination) {\n return;\n }\n // al regresar a su lugar de origen no se dice «de la 2 a la 2»\n const key = destination.index === source.index ? 'movingBack' : 'moving';\n provided.announce(t(key, {\n title: titleOf(draggableId), fromPosition: source.index + 1, position: destination.index + 1, total,\n }));\n };\n const finishMove = (result, provided) => {\n const {draggableId, source, destination} = result;\n const row = rowOfDraggable(draggableId);\n // se soltó fuera de la tabla o en el mismo lugar: nada que mover\n if (!row || !destination || destination.index === source.index) {\n provided.announce(t('cancelled', {title: titleOf(draggableId), position: source.index + 1}));\n return;\n }\n provided.announce(t('dropped', {\n title: labelOf(row), fromPosition: source.index + 1, position: destination.index + 1, total,\n }));\n reorder(row, source.index, destination.index);\n };\n\n // todas las filas con las mismas columnas: la del asa, la del orden, las de la pantalla y la de «Subir» y «Bajar»\n const gridTemplateColumns = [\n `${HANDLE_COLUMN_WIDTH_PIXELS}px`, ...(showPosition ? [`${POSITION_COLUMN_WIDTH_PIXELS}px`] : []), ...columns.map(trackOf),\n ...(moveButtons ? [`${MOVE_COLUMN_WIDTH_PIXELS}px`] : []),\n ].join(' ');\n // abajo de esto la tabla se desliza de lado en vez de apretar las columnas\n const minimumWidth = HANDLE_COLUMN_WIDTH_PIXELS + (showPosition ? POSITION_COLUMN_WIDTH_PIXELS : 0) + (moveButtons ? MOVE_COLUMN_WIDTH_PIXELS : 0)\n + columns.reduce((sum, column) => sum + (column.width ?? column.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH_PIXELS), 0);\n const rowSx = {display: 'grid', gridTemplateColumns};\n // una palabra solo se parte si no cabe ni sola en su renglón (un correo largo); un encabezado de dos palabras baja entero\n const cellSx = (align = 'left') => ({display: 'flex', alignItems: 'center', minWidth: 0, justifyContent: JUSTIFY_BY_ALIGN[align], textAlign: align, overflowWrap: 'break-word'});\n const houseCellSx = (align) => ({...cellSx(align), px: HOUSE_COLUMN_PADDING_X});\n const bottomText = error || helperText;\n\n return (\n <SortableRoot sx={sx}>\n {/* OJO trampa pagada: los encabezados escondidos (solo para el lector de pantalla) van con position absolute y se\n acomodan contra el primer papá con posición. Sin la de esta caja, el de la última columna («Subir o bajar») quedaba\n fuera de lo que se desliza y ensanchaba la página en el teléfono (715 px en una pantalla de 390). */}\n <SortableContainer component={Paper} variant=\"outlined\" ownSx={{overflowX: 'auto', position: 'relative'}}>\n <SortableTableElement component=\"div\" aria-label={ariaLabel} aria-busy={isSaving || undefined}\n aria-describedby={bottomText ? helperId : undefined} ownSx={{display: 'block', minWidth: minimumWidth}}>\n <SortableHead component=\"div\" ownSx={{display: 'block'}}>\n <SortableHeaderRow component=\"div\" ownSx={rowSx}>\n <SortableHeaderCell component=\"div\" role=\"columnheader\" ownSx={houseCellSx('center')}>\n <Box component=\"span\" sx={VISUALLY_HIDDEN_SX}>{t('handleHeader')}</Box>\n </SortableHeaderCell>\n {showPosition && (\n <SortableHeaderCell component=\"div\" role=\"columnheader\" ownSx={houseCellSx('right')}>{t('position')}</SortableHeaderCell>\n )}\n {columns.map((column) => (\n <SortableHeaderCell key={column.field} component=\"div\" role=\"columnheader\" ownSx={cellSx(column.align)}>\n {column.headerName}\n </SortableHeaderCell>\n ))}\n {moveButtons && (\n <SortableHeaderCell component=\"div\" role=\"columnheader\" ownSx={houseCellSx('center')}>\n <Box component=\"span\" sx={VISUALLY_HIDDEN_SX}>{t('moveHeader')}</Box>\n </SortableHeaderCell>\n )}\n </SortableHeaderRow>\n </SortableHead>\n <DragDropContext onDragStart={announceStart} onDragUpdate={announceUpdate} onDragEnd={finishMove}\n dragHandleUsageInstructions={t('instructions')}>\n <Droppable droppableId={listId}>\n {(droppableProvided) => (\n <SortableBody component=\"div\" ref={droppableProvided.innerRef} {...droppableProvided.droppableProps}\n ownSx={{display: 'block', '& > .MuiTableRow-root:last-of-type > .MuiTableCell-root': {borderBottom: 0}}}>\n {shownRows.map((row, index) => {\n const rowId = String(getRowId(row));\n const label = labelOf(row);\n return (\n <Draggable key={rowId} draggableId={rowId} index={index} isDragDisabled={!canDrag}>\n {(draggableProvided, draggableSnapshot) => (\n <SortableRow component=\"div\" ref={draggableProvided.innerRef} {...draggableProvided.draggableProps}\n ownSx={{\n ...rowSx,\n // el que flota lleva fondo y sombra: sin eso se transparenta sobre los demás\n ...(draggableSnapshot.isDragging && {bgcolor: 'background.paper', boxShadow: 8, borderRadius: 1}),\n }}>\n <SortableHandleCell component=\"div\" role=\"cell\" ownSx={houseCellSx('center')}>\n <SortableHandle component=\"span\" {...handlePropsOf(rowId, draggableProvided.dragHandleProps)}\n aria-label={t('handle', {title: label, position: index + 1})}\n aria-disabled={!canDrag || undefined}\n ownSx={{\n display: 'inline-flex', p: 0.5, borderRadius: 1,\n color: canDrag ? 'text.secondary' : 'text.disabled',\n cursor: canDrag ? (draggableSnapshot.isDragging ? 'grabbing' : 'grab') : 'default',\n '&:focus-visible': {outline: 2, outlineColor: 'primary.main', outlineOffset: 1},\n }}>\n <DragIndicatorRoundedIcon fontSize=\"small\" />\n </SortableHandle>\n </SortableHandleCell>\n {showPosition && (\n <SortablePositionCell component=\"div\" role=\"cell\"\n ownSx={{...houseCellSx('right'), fontVariantNumeric: 'tabular-nums', color: 'text.secondary'}}>\n {index + 1}\n </SortablePositionCell>\n )}\n {columns.map((column) => (\n <SortableCell key={column.field} component=\"div\" role=\"cell\" ownSx={cellSx(column.align)}>\n {column.renderCell ? column.renderCell(row, {index, position: index + 1}) : (row[column.field] ?? t('noValue'))}\n </SortableCell>\n ))}\n {moveButtons && (\n <SortableMoveCell component=\"div\" role=\"cell\" ownSx={{...houseCellSx('center'), gap: 0.5}}>\n {MOVE_BUTTONS.map(({direction, step, Icon, labelKey, hintKey}) => (\n // el span deja que el globo salga también con el botón apagado (regla de MUI)\n <Tooltip key={direction} title={t(hintKey)}>\n <span>\n <SortableMoveButton size=\"small\" ref={rememberMoveButton(rowId, direction)}\n aria-label={t(labelKey, {title: label})}\n // el primero no sube y el último no baja; mientras se guarda\n // se queda prendido para no perder el foco, pero no mueve\n disabled={disabled || index + step < 0 || index + step >= total}\n aria-disabled={isSaving || undefined}\n onClick={() => moveWithButton(row, index, step)}\n ownSx={isSaving ? {color: 'text.disabled'} : undefined}>\n <Icon fontSize=\"small\" />\n </SortableMoveButton>\n </span>\n </Tooltip>\n ))}\n </SortableMoveCell>\n )}\n </SortableRow>\n )}\n </Draggable>\n );\n })}\n {droppableProvided.placeholder}\n {total === 0 && (\n <TableRow component=\"div\" sx={rowSx}>\n <SortableEmpty component=\"div\" role=\"cell\" ownSx={{gridColumn: '1 / -1', color: 'text.secondary', textAlign: 'center', py: 3}}>\n {t('empty')}\n </SortableEmpty>\n </TableRow>\n )}\n </SortableBody>\n )}\n </Droppable>\n </DragDropContext>\n </SortableTableElement>\n </SortableContainer>\n {bottomText && <SortableHelperText id={helperId} error={Boolean(error)}>{bottomText}</SortableHelperText>}\n <SortableAnnouncer role=\"status\" aria-live=\"polite\" ownSx={VISUALLY_HIDDEN_SX}>{notice}</SortableAnnouncer>\n </SortableRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\n// OJO: con su tipo propio, el genérico (Row: el renglón de la pantalla) que la envoltura borraría; slots y slotProps van en su\n// documentación\n/** @type {typeof SortableTableContent} */\nconst SortableTable = withPieceSlots(SortableTableContent, THEME_NAME);\nexport default SortableTable;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ function moveRow(rows, fromIndex, toIndex) {
2
+ const next = [...rows];
3
+ const isInside = (index) => Number.isInteger(index) && index >= 0 && index < rows.length;
4
+ if (!isInside(fromIndex) || !isInside(toIndex) || fromIndex === toIndex) {
5
+ return next;
6
+ }
7
+ const [moved] = next.splice(fromIndex, 1);
8
+ next.splice(toIndex, 0, moved);
9
+ return next;
10
+ }
11
+ export {
12
+ moveRow
13
+ };
14
+ //# sourceMappingURL=sortableRows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sortableRows.js","sources":["../../src/sortable/sortableRows.js"],"sourcesContent":["// Mover un renglón de lugar en una lista donde el orden es el dato (qué se hace primero, en qué orden pasa la ruta). Sin\n// React ni MUI: lo usa SortableTable al soltar y con sus botones «Subir» y «Bajar», y la pantalla que quiera mover desde otra\n// parte (un menú «Mandar al final»).\n//\n// Las posiciones van desde 0, como las del arreglo; lo que ve una persona («posición 3») es la de aquí más uno.\n//\n// Funciones puras, sin React: function (regla de la casa).\n\n/**\n * La lista con un renglón movido a otro lugar. No toca la lista que recibe: regresa una nueva.\n *\n * Una posición fuera de la lista (o la misma) regresa una copia igual: nada que mover.\n *\n * @template T\n * @param {ReadonlyArray<T>} rows en su orden de hoy\n * @param {number} fromIndex dónde está el renglón (desde 0)\n * @param {number} toIndex dónde queda (desde 0, contado en la lista ya sin él, como lo da el arrastre)\n * @returns {T[]}\n */\nexport function moveRow(rows, fromIndex, toIndex) {\n const next = [...rows];\n const isInside = (index) => Number.isInteger(index) && index >= 0 && index < rows.length;\n // guard clause: posiciones que no existen o el mismo lugar\n if (!isInside(fromIndex) || !isInside(toIndex) || fromIndex === toIndex) {\n return next;\n }\n const [moved] = next.splice(fromIndex, 1);\n next.splice(toIndex, 0, moved);\n return next;\n}\n"],"names":[],"mappings":"AAmBO,SAAS,QAAQ,MAAM,WAAW,SAAS;AAC9C,QAAM,OAAO,CAAC,GAAG,IAAI;AACrB,QAAM,WAAW,CAAC,UAAU,OAAO,UAAU,KAAK,KAAK,SAAS,KAAK,QAAQ,KAAK;AAElF,MAAI,CAAC,SAAS,SAAS,KAAK,CAAC,SAAS,OAAO,KAAK,cAAc,SAAS;AACrE,WAAO;AAAA,EACX;AACA,QAAM,CAAC,KAAK,IAAI,KAAK,OAAO,WAAW,CAAC;AACxC,OAAK,OAAO,SAAS,GAAG,KAAK;AAC7B,SAAO;AACX;"}
@@ -0,0 +1,9 @@
1
+ import { default as default2 } from "./sortable/FormSortableField.js";
2
+ import { default as default3 } from "./sortable/SortableTable.js";
3
+ import { moveRow } from "./sortable/sortableRows.js";
4
+ export {
5
+ default2 as FormSortableField,
6
+ default3 as SortableTable,
7
+ moveRow
8
+ };
9
+ //# sourceMappingURL=sortable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sortable.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -1,19 +1,19 @@
1
1
  /** Los tipos de la casa: su ícono y su color (de la paleta del tema, claro y oscuro). */
2
2
  export declare const DEFAULT_FILE_TYPES: Readonly<{
3
3
  xlsx: Readonly<{
4
- Icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material/SvgIcon").SvgIconTypeMap<{}, "svg">> & {
4
+ Icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
5
5
  muiName: string;
6
6
  };
7
7
  color: "success.main";
8
8
  }>;
9
9
  csv: Readonly<{
10
- Icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material/SvgIcon").SvgIconTypeMap<{}, "svg">> & {
10
+ Icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
11
11
  muiName: string;
12
12
  };
13
13
  color: "info.main";
14
14
  }>;
15
15
  pdf: Readonly<{
16
- Icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material/SvgIcon").SvgIconTypeMap<{}, "svg">> & {
16
+ Icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
17
17
  muiName: string;
18
18
  };
19
19
  color: "error.main";
@@ -21,7 +21,7 @@ export declare const DEFAULT_FILE_TYPES: Readonly<{
21
21
  }>;
22
22
  /** Un tipo que nadie declaró: el ícono de archivo y el gris del texto. */
23
23
  export declare const UNKNOWN_FILE_TYPE: Readonly<{
24
- Icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material/SvgIcon").SvgIconTypeMap<{}, "svg">> & {
24
+ Icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
25
25
  muiName: string;
26
26
  };
27
27
  color: "text.secondary";
@@ -2,7 +2,7 @@ declare const SubmitButton: (props: {
2
2
  children: import('react').ReactNode;
3
3
  disabled?: boolean;
4
4
  isPending?: boolean;
5
- } & Omit<import("@mui/material/Button").ButtonProps<"button", {}>, "children" | "type"> & {
5
+ } & Omit<import("@mui/material").ButtonProps<"button", {}>, "children" | "type"> & {
6
6
  slots?: Record<string, import('react').ElementType>;
7
7
  slotProps?: Record<string, object | ((partProps: object) => object)>;
8
8
  }) => import("react").JSX.Element;
@@ -961,6 +961,26 @@ declare const _default: Readonly<{
961
961
  emptyFiltered: string;
962
962
  empty: string;
963
963
  };
964
+ sortableTable: {
965
+ instructions: string;
966
+ handleHeader: string;
967
+ handle: string;
968
+ moveHeader: string;
969
+ moveUp: string;
970
+ moveDown: string;
971
+ moveUpHint: string;
972
+ moveDownHint: string;
973
+ moved: string;
974
+ position: string;
975
+ lifted: string;
976
+ moving: string;
977
+ movingBack: string;
978
+ dropped: string;
979
+ cancelled: string;
980
+ reverted: string;
981
+ empty: string;
982
+ noValue: string;
983
+ };
964
984
  inbox: {
965
985
  labels: string;
966
986
  select: string;
@@ -961,6 +961,26 @@ declare const _default: Readonly<{
961
961
  emptyFiltered: string;
962
962
  empty: string;
963
963
  };
964
+ sortableTable: {
965
+ instructions: string;
966
+ handleHeader: string;
967
+ handle: string;
968
+ moveHeader: string;
969
+ moveUp: string;
970
+ moveDown: string;
971
+ moveUpHint: string;
972
+ moveDownHint: string;
973
+ moved: string;
974
+ position: string;
975
+ lifted: string;
976
+ moving: string;
977
+ movingBack: string;
978
+ dropped: string;
979
+ cancelled: string;
980
+ reverted: string;
981
+ empty: string;
982
+ noValue: string;
983
+ };
964
984
  inbox: {
965
985
  labels: string;
966
986
  select: string;
@@ -0,0 +1,15 @@
1
+ import SortableTable from './SortableTable.js';
2
+ /**
3
+ * @template {object} Row
4
+ * @param {{name: string, onReorder?: (change: {rows: Row[], rowId: string|number, fromIndex: number, toIndex: number}) => void} & Omit<Parameters<typeof SortableTable<Row>>[0], 'rows'|'onReorder'|'error'>} props
5
+ * las de SortableTable (columns, ariaLabel, getRowId…) sin rows ni error; su onReorder corre después del cambio del campo
6
+ */
7
+ export default function FormSortableField<Row extends object>({ name, onReorder, disabled, ...tableProps }: {
8
+ name: string;
9
+ onReorder?: (change: {
10
+ rows: Row[];
11
+ rowId: string | number;
12
+ fromIndex: number;
13
+ toIndex: number;
14
+ }) => void;
15
+ } & Omit<Parameters<typeof SortableTable<Row>>[0], 'rows' | 'onReorder' | 'error'>): import("react").JSX.Element;
@@ -0,0 +1,80 @@
1
+ export type SortableTableColumn<Row> = {
2
+ /**
3
+ * la llave del renglón que se pinta (y la del encabezado)
4
+ */
5
+ field: string;
6
+ /**
7
+ * el encabezado, ya traducido
8
+ */
9
+ headerName: string;
10
+ /**
11
+ * ancho fijo en px
12
+ */
13
+ width?: number;
14
+ /**
15
+ * cuánto del espacio libre toma, como en la tabla de servidor (por omisión 1)
16
+ */
17
+ flex?: number;
18
+ /**
19
+ * el mínimo en px de una columna sin ancho fijo (por omisión 96)
20
+ */
21
+ minWidth?: number;
22
+ /**
23
+ * los números a la derecha
24
+ */
25
+ align?: 'left' | 'center' | 'right';
26
+ /**
27
+ * lo de la celda a la
28
+ * medida; position es la que ve la persona (desde 1)
29
+ */
30
+ renderCell?: (row: Row, place: {
31
+ index: number;
32
+ position: number;
33
+ }) => import('react').ReactNode;
34
+ };
35
+ /**
36
+ * Los renglones conservan el tipo que usa la pantalla (Row): onReorder los regresa del mismo tipo, ya en su orden nuevo.
37
+ *
38
+ * @template {object} Row
39
+ * @param {object} props
40
+ * @param {Row[]} props.rows en su orden
41
+ * @param {SortableTableColumn<Row>[]} props.columns
42
+ * @param {(change: {rows: Row[], rowId: string|number, fromIndex: number, toIndex: number}) => Promise<unknown>|void} props.onReorder
43
+ * al soltar un renglón en otro lugar: rows ya en el orden nuevo; fromIndex y toIndex desde 0. Si regresa una promesa, el
44
+ * orden nuevo se enseña mientras se cumple y regresa si truena
45
+ * @param {string} props.ariaLabel qué es la tabla, ya traducido
46
+ * @param {(row: Row) => string|number} [props.getRowId] por omisión row.id
47
+ * @param {(row: Row) => string} [props.getRowLabel] el nombre del renglón que oye el lector de pantalla («Polanco»); por omisión
48
+ * lo de la primera columna
49
+ * @param {boolean} [props.showPosition] la columna «Orden» con 1..n (por omisión sí)
50
+ * @param {boolean} [props.moveButtons] «Subir» y «Bajar» en cada renglón, para mover sin arrastrar (por omisión sí: lo pide la
51
+ * regla de accesibilidad WCAG 2.5.7); false los quita
52
+ * @param {boolean} [props.disabled] nada se arrastra ni se mueve (mientras se envía el formulario, o de solo lectura)
53
+ * @param {import('react').ReactNode} [props.error] el error de la lista (en rojo, abajo de la tabla)
54
+ * @param {import('react').ReactNode} [props.helperText] una ayuda abajo de la tabla (el error gana)
55
+ * @param {import('@mui/material').SxProps<import('@mui/material').Theme>} [props.sx] lo de afuera de la tabla
56
+ * @param {object} [props.texts] los textos que cambian, con la forma de `sortableTable` en los textos del paquete
57
+ */
58
+ declare function SortableTableContent<Row extends object>(props: {
59
+ rows: Row[];
60
+ columns: SortableTableColumn<Row>[];
61
+ onReorder: (change: {
62
+ rows: Row[];
63
+ rowId: string | number;
64
+ fromIndex: number;
65
+ toIndex: number;
66
+ }) => Promise<unknown> | void;
67
+ ariaLabel: string;
68
+ getRowId?: (row: Row) => string | number;
69
+ getRowLabel?: (row: Row) => string;
70
+ showPosition?: boolean;
71
+ moveButtons?: boolean;
72
+ disabled?: boolean;
73
+ error?: import('react').ReactNode;
74
+ helperText?: import('react').ReactNode;
75
+ sx?: import('@mui/material').SxProps<import('@mui/material').Theme>;
76
+ texts?: object;
77
+ }): import("react").JSX.Element;
78
+ /** @type {typeof SortableTableContent} */
79
+ declare const SortableTable: typeof SortableTableContent;
80
+ export default SortableTable;