@protobase/ui 0.45.15 → 0.45.16
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/data-grid/column-resize.js +17 -0
- package/dist/data-grid/data-grid.js +8 -2
- package/dist/data-grid/grid-header.js +28 -18
- package/dist/data-grid/messages.js +2 -0
- package/dist/data-grid/resize-handle.js +21 -0
- package/dist/data-grid/use-column-resize.js +51 -0
- package/dist/package.js +1 -1
- package/dist/shell/assets/app-BBAu6BH3.js +9 -0
- package/dist/shell/assets/{index-BAnTId9-.js → index-B50he88Q.js} +2 -2
- package/dist/shell/assets/index-DVdwieyN.css +2 -0
- package/dist/shell/assets/{records-map-Dnm8MrTC.js → records-map-BuXJau3Q.js} +2 -2
- package/dist/shell/assets/{shared-protobase-ui-1yTMromK.js → shared-protobase-ui-BRL2lCxo.js} +2 -2
- package/dist/shell/index.html +4 -4
- package/dist/shell/protobase.shell.json +1 -1
- package/dist/shell/protobase.sw.js +2 -2
- package/dist/shell-source-maps/assets/app-BBAu6BH3.js.map +1 -0
- package/dist/shell-source-maps/assets/{index-BAnTId9-.js.map → index-B50he88Q.js.map} +1 -1
- package/dist/shell-source-maps/assets/{records-map-Dnm8MrTC.js.map → records-map-BuXJau3Q.js.map} +1 -1
- package/dist/shell-source-maps/assets/{shared-protobase-ui-1yTMromK.js.map → shared-protobase-ui-BRL2lCxo.js.map} +1 -1
- package/package.json +4 -4
- package/dist/shell/assets/app-BMBAT2xo.js +0 -9
- package/dist/shell/assets/index-DE9AVN7c.css +0 -2
- package/dist/shell-source-maps/assets/app-BMBAT2xo.js.map +0 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The width a column dragged `delta` pixels from `start` takes, never below `minColumnWidth`, or below `start` for a
|
|
3
|
+
* column the app made narrower than that, such as one of check marks.
|
|
4
|
+
*/
|
|
5
|
+
const resizedWidth = (start, delta) => Math.max(Math.min(64, start), Math.round(start + delta));
|
|
6
|
+
/**
|
|
7
|
+
* `specs` with the widths a resize set them to: those columns take that width whole, even below the minimum width the
|
|
8
|
+
* app gave them, as `resizedWidth` keeps them usable.
|
|
9
|
+
*/
|
|
10
|
+
const withResizedWidths = (specs, widths) => specs.map((spec) => spec.id in widths ? {
|
|
11
|
+
...spec,
|
|
12
|
+
fixed: true,
|
|
13
|
+
width: widths[spec.id],
|
|
14
|
+
minWidth: void 0
|
|
15
|
+
} : spec);
|
|
16
|
+
//#endregion
|
|
17
|
+
export { resizedWidth, withResizedWidths };
|
|
@@ -10,6 +10,8 @@ import { useHorizontalScroll } from "./use-horizontal-scroll.js";
|
|
|
10
10
|
import { usePinnedColumns } from "./use-pinned-columns.js";
|
|
11
11
|
import { defaultPins } from "./default-pins.js";
|
|
12
12
|
import { useFittedColumns } from "./use-fitted-columns.js";
|
|
13
|
+
import { withResizedWidths } from "./column-resize.js";
|
|
14
|
+
import { useColumnResize } from "./use-column-resize.js";
|
|
13
15
|
import { GridHeader } from "./grid-header.js";
|
|
14
16
|
import { DataRow, SkeletonRow } from "./grid-row.js";
|
|
15
17
|
import { usePagedRows } from "./use-paged-rows.js";
|
|
@@ -94,7 +96,10 @@ const DataGrid = ({ columns: given, source, naturalSort, initialScrollIndex = 0,
|
|
|
94
96
|
firstIndex,
|
|
95
97
|
lastIndex
|
|
96
98
|
]);
|
|
97
|
-
const
|
|
99
|
+
const headerRef = useRef(null);
|
|
100
|
+
const resize = useColumnResize(headerRef);
|
|
101
|
+
const fitted = useFittedColumns(columns, data);
|
|
102
|
+
const sized = useMemo(() => withResizedWidths(fitted, resize.widths), [fitted, resize.widths]);
|
|
98
103
|
const table = useTable({
|
|
99
104
|
features,
|
|
100
105
|
columns: tableColumns,
|
|
@@ -117,7 +122,6 @@ const DataGrid = ({ columns: given, source, naturalSort, initialScrollIndex = 0,
|
|
|
117
122
|
const trailing = rowActions && rowActions.length > 0 ? 40 : 0;
|
|
118
123
|
const minScale = narrow ? 1 : desktopMinScale;
|
|
119
124
|
const horizontal = useHorizontalScroll();
|
|
120
|
-
const headerRef = useRef(null);
|
|
121
125
|
const onBodyScroll = () => {
|
|
122
126
|
horizontal.onScroll();
|
|
123
127
|
if (headerRef.current && horizontal.ref.current) headerRef.current.scrollLeft = horizontal.ref.current.scrollLeft;
|
|
@@ -169,6 +173,8 @@ const DataGrid = ({ columns: given, source, naturalSort, initialScrollIndex = 0,
|
|
|
169
173
|
lastPinned,
|
|
170
174
|
scrolled: horizontal.scrolled,
|
|
171
175
|
onTogglePin: togglePin,
|
|
176
|
+
resize,
|
|
177
|
+
widths: resize.widths,
|
|
172
178
|
selectable,
|
|
173
179
|
selectedCount,
|
|
174
180
|
onClearSelection: () => setRowSelection({})
|
|
@@ -4,6 +4,7 @@ import { text } from "./messages.js";
|
|
|
4
4
|
import { gridTemplate } from "./grid-template.js";
|
|
5
5
|
import { isRightAligned } from "./column-spec.js";
|
|
6
6
|
import { HeaderMenu, unsortableText } from "./header-menu.js";
|
|
7
|
+
import { ResizeHandle } from "./resize-handle.js";
|
|
7
8
|
import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
|
|
8
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
10
|
//#region src/data-grid/grid-header.tsx
|
|
@@ -19,7 +20,7 @@ const HeaderLabel = ({ spec }) => /* @__PURE__ */ jsxs(Fragment, { children: [/*
|
|
|
19
20
|
className: "rounded bg-primary px-1 text-[10px] font-semibold uppercase leading-4 text-primary-foreground",
|
|
20
21
|
children: text("new")
|
|
21
22
|
})] });
|
|
22
|
-
const GridHeader = ({ cells, specs, gutter, selectedCount, selectable, trailing, minScale, pins = {}, lastPinned, scrolled, onTogglePin, onClearSelection }) => /* @__PURE__ */ jsxs("div", {
|
|
23
|
+
const GridHeader = ({ cells, specs, gutter, selectedCount, selectable, trailing, minScale, pins = {}, lastPinned, scrolled, onTogglePin, resize, widths = {}, onClearSelection }) => /* @__PURE__ */ jsxs("div", {
|
|
23
24
|
className: "grid h-8 shrink-0 items-center border-b bg-surface text-body font-medium text-muted-foreground",
|
|
24
25
|
style: { gridTemplateColumns: gridTemplate(specs, gutter, trailing, minScale) },
|
|
25
26
|
role: "row",
|
|
@@ -44,25 +45,34 @@ const GridHeader = ({ cells, specs, gutter, selectedCount, selectable, trailing,
|
|
|
44
45
|
return /* @__PURE__ */ jsxs("div", {
|
|
45
46
|
"data-col-id": spec.id,
|
|
46
47
|
style: pinned ? { left: pins[spec.id] } : void 0,
|
|
47
|
-
className: cn("group/cell flex h-full min-w-0 items-center", pinned
|
|
48
|
-
children: [
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
48
|
+
className: cn("group/cell flex h-full min-w-0 items-center", pinned ? "sticky z-10 bg-inherit" : "relative", pinned && scrolled && spec.id === lastPinned && "shadow-[1px_0_0_var(--border),4px_0_6px_-2px_rgb(0_0_0/0.12)]", spec.highlight && "bg-primary-soft text-primary-text"),
|
|
49
|
+
children: [
|
|
50
|
+
spec.sortable ? /* @__PURE__ */ jsxs("button", {
|
|
51
|
+
type: "button",
|
|
52
|
+
onClick: onSort,
|
|
53
|
+
className: cn("group/head flex h-full min-w-0 flex-1 items-center gap-1 pl-3 pr-1 text-left", isRightAligned(spec.kind) && "justify-end", "hover:text-foreground", sorted && "text-foreground"),
|
|
54
|
+
children: [/* @__PURE__ */ jsx(HeaderLabel, { spec }), /* @__PURE__ */ jsx(SortIcon, { sorted })]
|
|
55
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
56
|
+
title: unsortableText(),
|
|
57
|
+
className: cn("flex h-full min-w-0 flex-1 items-center gap-1 pl-3 pr-1 text-left", isRightAligned(spec.kind) && "justify-end"),
|
|
58
|
+
children: /* @__PURE__ */ jsx(HeaderLabel, { spec })
|
|
59
|
+
}),
|
|
60
|
+
/* @__PURE__ */ jsx("div", {
|
|
61
|
+
className: "pr-1.5",
|
|
62
|
+
children: /* @__PURE__ */ jsx(HeaderMenu, {
|
|
63
|
+
header: spec.header,
|
|
64
|
+
pinned,
|
|
65
|
+
sortable: Boolean(spec.sortable),
|
|
66
|
+
onTogglePin: () => onTogglePin(spec.id)
|
|
67
|
+
})
|
|
68
|
+
}),
|
|
69
|
+
resize && /* @__PURE__ */ jsx(ResizeHandle, {
|
|
70
|
+
id: spec.id,
|
|
60
71
|
header: spec.header,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
onTogglePin: () => onTogglePin(spec.id)
|
|
72
|
+
width: widths[spec.id],
|
|
73
|
+
resize
|
|
64
74
|
})
|
|
65
|
-
|
|
75
|
+
]
|
|
66
76
|
}, spec.id);
|
|
67
77
|
}),
|
|
68
78
|
trailing ? /* @__PURE__ */ jsx("div", { className: "sticky right-0 z-10 h-full bg-inherit" }) : null
|
|
@@ -6,6 +6,7 @@ const text = defineMessages({
|
|
|
6
6
|
columnMenu: (header) => `${header} column menu`,
|
|
7
7
|
unpin: "Unpin",
|
|
8
8
|
pinToLeft: "Pin to left",
|
|
9
|
+
resizeColumn: (header) => `Resize ${header} column`,
|
|
9
10
|
selected: (count) => `${count} selected`,
|
|
10
11
|
no: "No",
|
|
11
12
|
shownIn: (zone) => `Shown in ${zone}`,
|
|
@@ -28,6 +29,7 @@ const text = defineMessages({
|
|
|
28
29
|
columnMenu: (header) => `Kolommenu ${header}`,
|
|
29
30
|
unpin: "Losmaken",
|
|
30
31
|
pinToLeft: "Links vastzetten",
|
|
32
|
+
resizeColumn: (header) => `Breedte kolom ${header}`,
|
|
31
33
|
selected: (count) => `${count} geselecteerd`,
|
|
32
34
|
no: "Nee",
|
|
33
35
|
shownIn: (zone) => `Getoond in ${zone}`,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { text } from "./messages.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/data-grid/resize-handle.tsx
|
|
4
|
+
/**
|
|
5
|
+
* The right edge of a header cell, dragged to make its column wider or narrower. It sits beside the sort button rather
|
|
6
|
+
* than in it, so a drag never sorts.
|
|
7
|
+
*/
|
|
8
|
+
const ResizeHandle = ({ id, header, width, resize }) => /* @__PURE__ */ jsx("div", {
|
|
9
|
+
role: "separator",
|
|
10
|
+
"aria-orientation": "vertical",
|
|
11
|
+
"aria-label": text("resizeColumn", header),
|
|
12
|
+
"aria-valuemin": 64,
|
|
13
|
+
"aria-valuenow": width,
|
|
14
|
+
tabIndex: 0,
|
|
15
|
+
onPointerDown: (event) => resize.onPointerDown(id, event),
|
|
16
|
+
onKeyDown: (event) => resize.onKeyDown(id, event),
|
|
17
|
+
className: "group/resize absolute inset-y-0 right-0 z-10 flex w-2 cursor-col-resize touch-none justify-end outline-none",
|
|
18
|
+
children: /* @__PURE__ */ jsx("div", { className: "h-full w-0.5 bg-transparent group-hover/resize:bg-primary group-focus-visible/resize:bg-primary group-active/resize:bg-primary" })
|
|
19
|
+
});
|
|
20
|
+
//#endregion
|
|
21
|
+
export { ResizeHandle };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { resizedWidth } from "./column-resize.js";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
//#region src/data-grid/use-column-resize.ts
|
|
4
|
+
/** The widths every header cell has now, by column id, so that resizing one column leaves the others as they are. */
|
|
5
|
+
const measuredWidths = (header) => Object.fromEntries([...header.querySelectorAll("[data-col-id]")].map((cell) => [cell.dataset.colId, cell.offsetWidth]));
|
|
6
|
+
/**
|
|
7
|
+
* Column widths the user sets by dragging a header cell's edge, or with the arrow keys on it, by column id. They live
|
|
8
|
+
* as long as the grid does: a reload or another page shows the app's widths again.
|
|
9
|
+
*/
|
|
10
|
+
const useColumnResize = (header) => {
|
|
11
|
+
const [widths, setWidths] = useState({});
|
|
12
|
+
const startWidths = () => ({
|
|
13
|
+
...header.current ? measuredWidths(header.current) : {},
|
|
14
|
+
...widths
|
|
15
|
+
});
|
|
16
|
+
const onPointerDown = (id, event) => {
|
|
17
|
+
if (event.button !== 0) return;
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
const start = startWidths();
|
|
20
|
+
const startX = event.clientX;
|
|
21
|
+
const onMove = (move) => setWidths({
|
|
22
|
+
...start,
|
|
23
|
+
[id]: resizedWidth(start[id] ?? 0, move.clientX - startX)
|
|
24
|
+
});
|
|
25
|
+
const onEnd = () => {
|
|
26
|
+
window.removeEventListener("pointermove", onMove);
|
|
27
|
+
window.removeEventListener("pointerup", onEnd);
|
|
28
|
+
window.removeEventListener("pointercancel", onEnd);
|
|
29
|
+
};
|
|
30
|
+
window.addEventListener("pointermove", onMove);
|
|
31
|
+
window.addEventListener("pointerup", onEnd);
|
|
32
|
+
window.addEventListener("pointercancel", onEnd);
|
|
33
|
+
};
|
|
34
|
+
const onKeyDown = (id, event) => {
|
|
35
|
+
const delta = event.key === "ArrowRight" ? 16 : event.key === "ArrowLeft" ? -16 : 0;
|
|
36
|
+
if (delta === 0) return;
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
const start = startWidths();
|
|
39
|
+
setWidths({
|
|
40
|
+
...start,
|
|
41
|
+
[id]: resizedWidth(start[id] ?? 0, delta)
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
widths,
|
|
46
|
+
onPointerDown,
|
|
47
|
+
onKeyDown
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { useColumnResize };
|
package/dist/package.js
CHANGED