react-os-shell 0.3.8 → 0.3.10
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/{Browser-NVB42ZUZ.js → Browser-LTLVDRYP.js} +3 -3
- package/dist/{Browser-NVB42ZUZ.js.map → Browser-LTLVDRYP.js.map} +1 -1
- package/dist/{Calculator-Y4IC2LXP.js → Calculator-R27HR2QS.js} +4 -4
- package/dist/{Calculator-Y4IC2LXP.js.map → Calculator-R27HR2QS.js.map} +1 -1
- package/dist/{Calendar-YEQAKHNJ.js → Calendar-7LZR4JFF.js} +3 -3
- package/dist/{Calendar-YEQAKHNJ.js.map → Calendar-7LZR4JFF.js.map} +1 -1
- package/dist/{CurrencyConverter-6QJFSYNS.js → CurrencyConverter-2HOKHG57.js} +4 -4
- package/dist/{CurrencyConverter-6QJFSYNS.js.map → CurrencyConverter-2HOKHG57.js.map} +1 -1
- package/dist/{Documents-PVQN2MSQ.js → Documents-5JVPDRMQ.js} +3 -3
- package/dist/{Documents-PVQN2MSQ.js.map → Documents-5JVPDRMQ.js.map} +1 -1
- package/dist/{Email-44JT45AP.js → Email-W6QOOSVU.js} +3 -3
- package/dist/{Email-44JT45AP.js.map → Email-W6QOOSVU.js.map} +1 -1
- package/dist/Files-L7YDPTYL.js +11 -0
- package/dist/{Files-NQMJQLDJ.js.map → Files-L7YDPTYL.js.map} +1 -1
- package/dist/{Minesweeper-X4YXGGEV.js → Minesweeper-FD5O42OI.js} +3 -3
- package/dist/{Minesweeper-X4YXGGEV.js.map → Minesweeper-FD5O42OI.js.map} +1 -1
- package/dist/{Notepad-YUSX4XVH.js → Notepad-SK6OPBVW.js} +3 -3
- package/dist/{Notepad-YUSX4XVH.js.map → Notepad-SK6OPBVW.js.map} +1 -1
- package/dist/{PomodoroTimer-JGZJRHE3.js → PomodoroTimer-JYV2DEED.js} +4 -4
- package/dist/{PomodoroTimer-JGZJRHE3.js.map → PomodoroTimer-JYV2DEED.js.map} +1 -1
- package/dist/Preview-ZMU2376L.js +8 -0
- package/dist/{Preview-2JAYBJUA.js.map → Preview-ZMU2376L.js.map} +1 -1
- package/dist/Spreadsheet-SBN532NF.js +6 -0
- package/dist/{Spreadsheet-JKLESG5X.js.map → Spreadsheet-SBN532NF.js.map} +1 -1
- package/dist/{Weather-DDA4RV4O.js → Weather-BDBAUFOF.js} +4 -4
- package/dist/{Weather-DDA4RV4O.js.map → Weather-BDBAUFOF.js.map} +1 -1
- package/dist/{WorldClock-KSJTXHYC.js → WorldClock-FIDZCNY6.js} +4 -4
- package/dist/{WorldClock-KSJTXHYC.js.map → WorldClock-FIDZCNY6.js.map} +1 -1
- package/dist/apps/index.js +19 -19
- package/dist/{chunk-7H2SYGKI.js → chunk-CNOME73V.js} +23 -13
- package/dist/chunk-CNOME73V.js.map +1 -0
- package/dist/{chunk-USRWYARC.js → chunk-F3XQURUE.js} +3 -3
- package/dist/{chunk-USRWYARC.js.map → chunk-F3XQURUE.js.map} +1 -1
- package/dist/{chunk-YUSSZEYC.js → chunk-HTXOHKRX.js} +4 -4
- package/dist/{chunk-YUSSZEYC.js.map → chunk-HTXOHKRX.js.map} +1 -1
- package/dist/{chunk-QE4CGS3U.js → chunk-WGPDZ54I.js} +4 -4
- package/dist/{chunk-QE4CGS3U.js.map → chunk-WGPDZ54I.js.map} +1 -1
- package/dist/{chunk-3AIWGZRC.js → chunk-WKET7CLC.js} +3 -3
- package/dist/{chunk-3AIWGZRC.js.map → chunk-WKET7CLC.js.map} +1 -1
- package/dist/{chunk-6H6WT7HU.js → chunk-Z3256PR3.js} +3 -3
- package/dist/{chunk-6H6WT7HU.js.map → chunk-Z3256PR3.js.map} +1 -1
- package/dist/index.d.ts +214 -2
- package/dist/index.js +670 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/Files-NQMJQLDJ.js +0 -11
- package/dist/Preview-2JAYBJUA.js +0 -8
- package/dist/Spreadsheet-JKLESG5X.js +0 -6
- package/dist/chunk-7H2SYGKI.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -6,26 +6,26 @@ export { setShellMailServer, useMailAuth } from './chunk-VBFB3ZIN.js';
|
|
|
6
6
|
import { subscribePomo, getPomoSnapshot } from './chunk-MK3HLUO4.js';
|
|
7
7
|
import { useShellPrefs } from './chunk-36VM54SC.js';
|
|
8
8
|
export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
|
|
9
|
-
import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-
|
|
9
|
+
import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-WGPDZ54I.js';
|
|
10
10
|
import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, playLogout, setSoundForType, previewSound, setAllSounds } from './chunk-D7PYW2QS.js';
|
|
11
|
-
import { setPdfPreview } from './chunk-
|
|
11
|
+
import { setPdfPreview } from './chunk-WKET7CLC.js';
|
|
12
12
|
import './chunk-KUIPWCTJ.js';
|
|
13
13
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
14
14
|
export { toast_default as toast } from './chunk-WIJ45SYD.js';
|
|
15
|
-
export { EditableGrid } from './chunk-
|
|
16
|
-
import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, ModalActions, useIsMobile, useModalActive, WINDOW_REGISTRY, isPageEntry,
|
|
17
|
-
export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-
|
|
15
|
+
export { EditableGrid } from './chunk-F3XQURUE.js';
|
|
16
|
+
import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, ModalActions, useIsMobile, useModalActive, client_default, LoadingSpinner, WINDOW_REGISTRY, isPageEntry, ThumbCard, activateModal } from './chunk-CNOME73V.js';
|
|
17
|
+
export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-CNOME73V.js';
|
|
18
18
|
import { confirm } from './chunk-PLGHQ7QW.js';
|
|
19
19
|
export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-PLGHQ7QW.js';
|
|
20
|
-
import { useAuth } from './chunk-ADJ3CERD.js';
|
|
20
|
+
import { useAuth, useShellAuth } from './chunk-ADJ3CERD.js';
|
|
21
21
|
export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ3CERD.js';
|
|
22
22
|
import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-SSA762W5.js';
|
|
23
23
|
export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-SSA762W5.js';
|
|
24
|
-
import { createContext, lazy, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement,
|
|
24
|
+
import { createContext, lazy, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, useMemo, useSyncExternalStore } from 'react';
|
|
25
25
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
26
26
|
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
|
|
27
27
|
import { createPortal } from 'react-dom';
|
|
28
|
-
import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
|
|
28
|
+
import { useQueryClient, useQuery, useMutation, useInfiniteQuery } from '@tanstack/react-query';
|
|
29
29
|
import 'react-router-dom';
|
|
30
30
|
|
|
31
31
|
// src/windowRegistry/createWindowRegistry.ts
|
|
@@ -915,7 +915,7 @@ function StatusBadge({ status }) {
|
|
|
915
915
|
}
|
|
916
916
|
|
|
917
917
|
// src/version.ts
|
|
918
|
-
var VERSION = "0.3.
|
|
918
|
+
var VERSION = "0.3.10" ;
|
|
919
919
|
var APP_VERSION = VERSION;
|
|
920
920
|
|
|
921
921
|
// src/changelog.ts
|
|
@@ -5083,6 +5083,666 @@ function SoundSettings() {
|
|
|
5083
5083
|
] }) }) })
|
|
5084
5084
|
] });
|
|
5085
5085
|
}
|
|
5086
|
+
function useTableNav(items, onSelect, onToggle, onSelectAll, onSelectRange) {
|
|
5087
|
+
const [focusIdx, setFocusIdx] = useState(-1);
|
|
5088
|
+
const itemsRef = useRef(items);
|
|
5089
|
+
const onSelectRef = useRef(onSelect);
|
|
5090
|
+
const onToggleRef = useRef(onToggle);
|
|
5091
|
+
const onSelectAllRef = useRef(onSelectAll);
|
|
5092
|
+
const onSelectRangeRef = useRef(onSelectRange);
|
|
5093
|
+
const focusRef = useRef(focusIdx);
|
|
5094
|
+
const lastToggledRef = useRef(-1);
|
|
5095
|
+
const isActive = useModalActive();
|
|
5096
|
+
const isActiveRef = useRef(isActive);
|
|
5097
|
+
itemsRef.current = items;
|
|
5098
|
+
onSelectRef.current = onSelect;
|
|
5099
|
+
onToggleRef.current = onToggle;
|
|
5100
|
+
onSelectAllRef.current = onSelectAll;
|
|
5101
|
+
onSelectRangeRef.current = onSelectRange;
|
|
5102
|
+
focusRef.current = focusIdx;
|
|
5103
|
+
isActiveRef.current = isActive;
|
|
5104
|
+
const prevLen = useRef(items.length);
|
|
5105
|
+
useEffect(() => {
|
|
5106
|
+
if (items.length !== prevLen.current) {
|
|
5107
|
+
setFocusIdx(-1);
|
|
5108
|
+
lastToggledRef.current = -1;
|
|
5109
|
+
prevLen.current = items.length;
|
|
5110
|
+
}
|
|
5111
|
+
}, [items.length]);
|
|
5112
|
+
useEffect(() => {
|
|
5113
|
+
const handler = (e) => {
|
|
5114
|
+
if (!isActiveRef.current) return;
|
|
5115
|
+
if (e.shiftKey) return;
|
|
5116
|
+
const target = e.target;
|
|
5117
|
+
const row = target?.closest?.("[data-row-idx]");
|
|
5118
|
+
if (!row) return;
|
|
5119
|
+
if (target.tagName !== "INPUT" || target.type !== "checkbox") return;
|
|
5120
|
+
const idx = parseInt(row.getAttribute("data-row-idx"), 10);
|
|
5121
|
+
if (!isNaN(idx)) {
|
|
5122
|
+
lastToggledRef.current = idx;
|
|
5123
|
+
setFocusIdx(idx);
|
|
5124
|
+
}
|
|
5125
|
+
};
|
|
5126
|
+
document.addEventListener("click", handler);
|
|
5127
|
+
return () => document.removeEventListener("click", handler);
|
|
5128
|
+
}, []);
|
|
5129
|
+
useEffect(() => {
|
|
5130
|
+
const handler = (e) => {
|
|
5131
|
+
if (!isActiveRef.current) return;
|
|
5132
|
+
const tag = e.target?.tagName;
|
|
5133
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return;
|
|
5134
|
+
if (e.target?.isContentEditable) return;
|
|
5135
|
+
if ((e.metaKey || e.ctrlKey) && e.key === "a") {
|
|
5136
|
+
e.preventDefault();
|
|
5137
|
+
onSelectAllRef.current?.();
|
|
5138
|
+
return;
|
|
5139
|
+
}
|
|
5140
|
+
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
5141
|
+
const len = itemsRef.current.length;
|
|
5142
|
+
if (len === 0) return;
|
|
5143
|
+
const isDown = e.code === "KeyJ" || e.key === "j" || e.key === "J" || e.key === "ArrowDown";
|
|
5144
|
+
const isUp = e.code === "KeyK" || e.key === "k" || e.key === "K" || e.key === "ArrowUp";
|
|
5145
|
+
if (isDown || isUp) {
|
|
5146
|
+
e.preventDefault();
|
|
5147
|
+
const prev = focusRef.current;
|
|
5148
|
+
const next = isDown ? Math.min(prev + 1, len - 1) : Math.max(prev - 1, 0);
|
|
5149
|
+
if (next !== prev) {
|
|
5150
|
+
setFocusIdx(next);
|
|
5151
|
+
scrollRowIntoView(next);
|
|
5152
|
+
if (e.shiftKey && onToggleRef.current) {
|
|
5153
|
+
onToggleRef.current(itemsRef.current[next]);
|
|
5154
|
+
lastToggledRef.current = next;
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5157
|
+
} else if (e.key === "Enter" && focusRef.current >= 0 && focusRef.current < len) {
|
|
5158
|
+
e.preventDefault();
|
|
5159
|
+
onSelectRef.current(itemsRef.current[focusRef.current]);
|
|
5160
|
+
} else if (e.key === " " && focusRef.current >= 0 && focusRef.current < len) {
|
|
5161
|
+
e.preventDefault();
|
|
5162
|
+
if (e.shiftKey && lastToggledRef.current >= 0 && onSelectRangeRef.current) {
|
|
5163
|
+
const from = Math.min(lastToggledRef.current, focusRef.current);
|
|
5164
|
+
const to = Math.max(lastToggledRef.current, focusRef.current);
|
|
5165
|
+
onSelectRangeRef.current(from, to);
|
|
5166
|
+
} else {
|
|
5167
|
+
onToggleRef.current?.(itemsRef.current[focusRef.current]);
|
|
5168
|
+
}
|
|
5169
|
+
lastToggledRef.current = focusRef.current;
|
|
5170
|
+
}
|
|
5171
|
+
};
|
|
5172
|
+
window.addEventListener("keydown", handler);
|
|
5173
|
+
return () => window.removeEventListener("keydown", handler);
|
|
5174
|
+
}, []);
|
|
5175
|
+
useEffect(() => {
|
|
5176
|
+
const handler = (e) => {
|
|
5177
|
+
if (!isActiveRef.current) return;
|
|
5178
|
+
if (!e.shiftKey) return;
|
|
5179
|
+
const target = e.target;
|
|
5180
|
+
const row = target?.closest?.("[data-row-idx]");
|
|
5181
|
+
if (!row) return;
|
|
5182
|
+
const clickedIdx = parseInt(row.getAttribute("data-row-idx"), 10);
|
|
5183
|
+
if (isNaN(clickedIdx)) return;
|
|
5184
|
+
const anchor = lastToggledRef.current;
|
|
5185
|
+
if (anchor < 0) {
|
|
5186
|
+
onToggleRef.current?.(itemsRef.current[clickedIdx]);
|
|
5187
|
+
lastToggledRef.current = clickedIdx;
|
|
5188
|
+
setFocusIdx(clickedIdx);
|
|
5189
|
+
return;
|
|
5190
|
+
}
|
|
5191
|
+
e.preventDefault();
|
|
5192
|
+
e.stopPropagation();
|
|
5193
|
+
const from = Math.min(anchor, clickedIdx);
|
|
5194
|
+
const to = Math.max(anchor, clickedIdx);
|
|
5195
|
+
if (onSelectRangeRef.current) {
|
|
5196
|
+
onSelectRangeRef.current(from, to);
|
|
5197
|
+
} else if (onToggleRef.current) {
|
|
5198
|
+
for (let i = from; i <= to; i++) {
|
|
5199
|
+
onToggleRef.current(itemsRef.current[i]);
|
|
5200
|
+
}
|
|
5201
|
+
}
|
|
5202
|
+
lastToggledRef.current = clickedIdx;
|
|
5203
|
+
setFocusIdx(clickedIdx);
|
|
5204
|
+
};
|
|
5205
|
+
document.addEventListener("click", handler, true);
|
|
5206
|
+
return () => document.removeEventListener("click", handler, true);
|
|
5207
|
+
}, []);
|
|
5208
|
+
return focusIdx;
|
|
5209
|
+
}
|
|
5210
|
+
function scrollRowIntoView(idx) {
|
|
5211
|
+
requestAnimationFrame(() => {
|
|
5212
|
+
const row = document.querySelector(`[data-row-idx="${idx}"]`);
|
|
5213
|
+
row?.scrollIntoView({ block: "nearest" });
|
|
5214
|
+
});
|
|
5215
|
+
}
|
|
5216
|
+
function pinSelectColumn(cols) {
|
|
5217
|
+
const selectIdx = cols.findIndex((c) => c.key === "_select");
|
|
5218
|
+
if (selectIdx >= 0) {
|
|
5219
|
+
const [sel] = cols.splice(selectIdx, 1);
|
|
5220
|
+
sel.hidden = false;
|
|
5221
|
+
cols.unshift(sel);
|
|
5222
|
+
}
|
|
5223
|
+
return cols;
|
|
5224
|
+
}
|
|
5225
|
+
function useColumnConfig(tableId, defaultColumns) {
|
|
5226
|
+
const [columns, setColumns] = useState(() => {
|
|
5227
|
+
const cached = localStorage.getItem(`col-config-${tableId}`);
|
|
5228
|
+
if (cached) {
|
|
5229
|
+
try {
|
|
5230
|
+
const parsed = JSON.parse(cached);
|
|
5231
|
+
const existing = new Set(parsed.map((c) => c.key));
|
|
5232
|
+
const merged = pinSelectColumn([
|
|
5233
|
+
...parsed.filter((c) => defaultColumns.some((d) => d.key === c.key)),
|
|
5234
|
+
...defaultColumns.filter((d) => !existing.has(d.key)).map((d) => ({ key: d.key, width: d.defaultWidth || 150 }))
|
|
5235
|
+
]);
|
|
5236
|
+
return merged;
|
|
5237
|
+
} catch {
|
|
5238
|
+
}
|
|
5239
|
+
}
|
|
5240
|
+
return pinSelectColumn(defaultColumns.map((d) => ({ key: d.key, width: d.defaultWidth || 150, hidden: d.defaultHidden })));
|
|
5241
|
+
});
|
|
5242
|
+
const [draggedIdx, setDraggedIdx] = useState(null);
|
|
5243
|
+
const [dropGap, setDropGap] = useState(null);
|
|
5244
|
+
const resizingRef = useRef(null);
|
|
5245
|
+
const saveTimer = useRef(null);
|
|
5246
|
+
const saveMut = useMutation({
|
|
5247
|
+
mutationFn: (cols) => client_default.patch("/auth/me/", {
|
|
5248
|
+
preferences: { [`columns_${tableId}`]: cols }
|
|
5249
|
+
})
|
|
5250
|
+
});
|
|
5251
|
+
const persistColumns = useCallback((cols) => {
|
|
5252
|
+
localStorage.setItem(`col-config-${tableId}`, JSON.stringify(cols));
|
|
5253
|
+
if (saveTimer.current) clearTimeout(saveTimer.current);
|
|
5254
|
+
saveTimer.current = setTimeout(() => saveMut.mutate(cols), 1e3);
|
|
5255
|
+
}, [tableId, saveMut]);
|
|
5256
|
+
useEffect(() => {
|
|
5257
|
+
const viewport = typeof window !== "undefined" && window.matchMedia("(max-width: 767px), (pointer: coarse)").matches ? "mobile" : "desktop";
|
|
5258
|
+
Promise.all([
|
|
5259
|
+
client_default.get("/auth/me/").catch(() => null),
|
|
5260
|
+
client_default.get(`/auth/default-columns/${tableId}/`, { params: { viewport } }).catch(() => null)
|
|
5261
|
+
]).then(([userRes, defaultRes]) => {
|
|
5262
|
+
const prefs = userRes?.data?.preferences;
|
|
5263
|
+
const userSaved = prefs?.[`columns_${tableId}`];
|
|
5264
|
+
if (userSaved && Array.isArray(userSaved)) {
|
|
5265
|
+
const existing = new Set(userSaved.map((c) => c.key));
|
|
5266
|
+
const merged = pinSelectColumn([
|
|
5267
|
+
...userSaved.filter((c) => defaultColumns.some((d) => d.key === c.key)),
|
|
5268
|
+
...defaultColumns.filter((d) => !existing.has(d.key)).map((d) => ({ key: d.key, width: d.defaultWidth || 150, hidden: d.defaultHidden }))
|
|
5269
|
+
]);
|
|
5270
|
+
setColumns(merged);
|
|
5271
|
+
localStorage.setItem(`col-config-${tableId}`, JSON.stringify(merged));
|
|
5272
|
+
} else if (Array.isArray(defaultRes?.data?.visible_columns) && defaultRes.data.visible_columns.length > 0) {
|
|
5273
|
+
const visibleSet = new Set(defaultRes.data.visible_columns);
|
|
5274
|
+
const systemCols = pinSelectColumn(defaultColumns.map((d) => ({
|
|
5275
|
+
key: d.key,
|
|
5276
|
+
width: d.defaultWidth || 150,
|
|
5277
|
+
hidden: !visibleSet.has(d.key)
|
|
5278
|
+
})));
|
|
5279
|
+
setColumns(systemCols);
|
|
5280
|
+
localStorage.setItem(`col-config-${tableId}`, JSON.stringify(systemCols));
|
|
5281
|
+
}
|
|
5282
|
+
});
|
|
5283
|
+
}, [tableId]);
|
|
5284
|
+
const visibleColumns = columns.filter((c) => !c.hidden);
|
|
5285
|
+
const onResizeStart = useCallback((idx, e) => {
|
|
5286
|
+
e.preventDefault();
|
|
5287
|
+
e.stopPropagation();
|
|
5288
|
+
const visCol = visibleColumns[idx];
|
|
5289
|
+
const realIdx = columns.findIndex((c) => c.key === visCol.key);
|
|
5290
|
+
resizingRef.current = { idx: realIdx, startX: e.clientX, startWidth: columns[realIdx].width };
|
|
5291
|
+
const onMouseMove = (ev) => {
|
|
5292
|
+
if (!resizingRef.current) return;
|
|
5293
|
+
const { idx: i, startX, startWidth } = resizingRef.current;
|
|
5294
|
+
const minW = defaultColumns.find((d) => d.key === columns[i].key)?.minWidth || 30;
|
|
5295
|
+
const newWidth = Math.max(minW, startWidth + ev.clientX - startX);
|
|
5296
|
+
setColumns((prev) => {
|
|
5297
|
+
const updated = [...prev];
|
|
5298
|
+
updated[i] = { ...updated[i], width: newWidth };
|
|
5299
|
+
return updated;
|
|
5300
|
+
});
|
|
5301
|
+
};
|
|
5302
|
+
const onMouseUp = () => {
|
|
5303
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
5304
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
5305
|
+
resizingRef.current = null;
|
|
5306
|
+
setColumns((prev) => {
|
|
5307
|
+
persistColumns(prev);
|
|
5308
|
+
return prev;
|
|
5309
|
+
});
|
|
5310
|
+
};
|
|
5311
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
5312
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
5313
|
+
}, [columns, visibleColumns, defaultColumns, persistColumns]);
|
|
5314
|
+
const onDragStart = useCallback((idx) => {
|
|
5315
|
+
setDraggedIdx(idx);
|
|
5316
|
+
}, []);
|
|
5317
|
+
const onDragOver = useCallback((visIdx, e) => {
|
|
5318
|
+
e.preventDefault();
|
|
5319
|
+
if (draggedIdx === null) return;
|
|
5320
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
5321
|
+
let gap = e.clientX < rect.left + rect.width / 2 ? visIdx : visIdx + 1;
|
|
5322
|
+
const vis = columns.filter((c) => !c.hidden);
|
|
5323
|
+
if (vis[0]?.key === "_select" && gap === 0) gap = 1;
|
|
5324
|
+
setDropGap(gap);
|
|
5325
|
+
}, [draggedIdx, columns]);
|
|
5326
|
+
const onDrop = useCallback((_visIdx, e) => {
|
|
5327
|
+
e.preventDefault();
|
|
5328
|
+
if (draggedIdx === null || dropGap === null) {
|
|
5329
|
+
setDraggedIdx(null);
|
|
5330
|
+
setDropGap(null);
|
|
5331
|
+
return;
|
|
5332
|
+
}
|
|
5333
|
+
if (dropGap === draggedIdx || dropGap === draggedIdx + 1) {
|
|
5334
|
+
setDraggedIdx(null);
|
|
5335
|
+
setDropGap(null);
|
|
5336
|
+
return;
|
|
5337
|
+
}
|
|
5338
|
+
setColumns((prev) => {
|
|
5339
|
+
const visible = prev.filter((c) => !c.hidden);
|
|
5340
|
+
const moved = visible[draggedIdx];
|
|
5341
|
+
if (!moved) return prev;
|
|
5342
|
+
const fromReal = prev.findIndex((c) => c.key === moved.key);
|
|
5343
|
+
let toReal;
|
|
5344
|
+
if (dropGap < visible.length) {
|
|
5345
|
+
toReal = prev.findIndex((c) => c.key === visible[dropGap].key);
|
|
5346
|
+
} else {
|
|
5347
|
+
toReal = prev.findIndex((c) => c.key === visible[visible.length - 1].key) + 1;
|
|
5348
|
+
}
|
|
5349
|
+
const updated = [...prev];
|
|
5350
|
+
const [item] = updated.splice(fromReal, 1);
|
|
5351
|
+
updated.splice(toReal > fromReal ? toReal - 1 : toReal, 0, item);
|
|
5352
|
+
persistColumns(updated);
|
|
5353
|
+
return updated;
|
|
5354
|
+
});
|
|
5355
|
+
setDraggedIdx(null);
|
|
5356
|
+
setDropGap(null);
|
|
5357
|
+
}, [draggedIdx, dropGap, persistColumns]);
|
|
5358
|
+
const onDragEnd = useCallback(() => {
|
|
5359
|
+
setDraggedIdx(null);
|
|
5360
|
+
setDropGap(null);
|
|
5361
|
+
}, []);
|
|
5362
|
+
const toggleColumn = useCallback((key) => {
|
|
5363
|
+
setColumns((prev) => {
|
|
5364
|
+
const updated = prev.map((c) => c.key === key ? { ...c, hidden: !c.hidden } : c);
|
|
5365
|
+
if (updated.filter((c) => !c.hidden).length === 0) return prev;
|
|
5366
|
+
persistColumns(updated);
|
|
5367
|
+
return updated;
|
|
5368
|
+
});
|
|
5369
|
+
}, [persistColumns]);
|
|
5370
|
+
const resetColumns = useCallback(() => {
|
|
5371
|
+
const defaults = defaultColumns.map((d) => ({ key: d.key, width: d.defaultWidth || 150 }));
|
|
5372
|
+
setColumns(defaults);
|
|
5373
|
+
persistColumns(defaults);
|
|
5374
|
+
}, [defaultColumns, persistColumns]);
|
|
5375
|
+
const orderedColumns = visibleColumns.map((c) => {
|
|
5376
|
+
const def = defaultColumns.find((d) => d.key === c.key);
|
|
5377
|
+
return { ...def, width: c.width };
|
|
5378
|
+
}).filter(Boolean);
|
|
5379
|
+
const allColumns = columns.map((c) => {
|
|
5380
|
+
const def = defaultColumns.find((d) => d.key === c.key);
|
|
5381
|
+
return { key: c.key, label: def?.label || c.key, hidden: !!c.hidden };
|
|
5382
|
+
});
|
|
5383
|
+
return {
|
|
5384
|
+
orderedColumns,
|
|
5385
|
+
allColumns,
|
|
5386
|
+
onResizeStart,
|
|
5387
|
+
onDragStart,
|
|
5388
|
+
onDragOver,
|
|
5389
|
+
onDrop,
|
|
5390
|
+
onDragEnd,
|
|
5391
|
+
toggleColumn,
|
|
5392
|
+
resetColumns,
|
|
5393
|
+
draggedIdx,
|
|
5394
|
+
dropGap
|
|
5395
|
+
};
|
|
5396
|
+
}
|
|
5397
|
+
function ResizableTable({
|
|
5398
|
+
tableId,
|
|
5399
|
+
columns,
|
|
5400
|
+
sort,
|
|
5401
|
+
onSort,
|
|
5402
|
+
footer,
|
|
5403
|
+
afterBody,
|
|
5404
|
+
saveDefaultPerms = ["change_numberingconfig"],
|
|
5405
|
+
children
|
|
5406
|
+
}) {
|
|
5407
|
+
const isMobile = useIsMobile();
|
|
5408
|
+
const [selectionMode, setSelectionMode] = useState(false);
|
|
5409
|
+
const effectiveColumns = useMemo(
|
|
5410
|
+
() => isMobile && !selectionMode ? columns.filter((c) => c.key !== "_select") : columns,
|
|
5411
|
+
[columns, isMobile, selectionMode]
|
|
5412
|
+
);
|
|
5413
|
+
const {
|
|
5414
|
+
orderedColumns,
|
|
5415
|
+
allColumns,
|
|
5416
|
+
onResizeStart,
|
|
5417
|
+
onDragStart,
|
|
5418
|
+
onDragOver,
|
|
5419
|
+
onDrop,
|
|
5420
|
+
onDragEnd,
|
|
5421
|
+
toggleColumn,
|
|
5422
|
+
resetColumns,
|
|
5423
|
+
draggedIdx,
|
|
5424
|
+
dropGap
|
|
5425
|
+
} = useColumnConfig(tableId, effectiveColumns);
|
|
5426
|
+
const { hasAnyPerm } = useShellAuth();
|
|
5427
|
+
const [pickerOpen, setPickerOpen] = useState(false);
|
|
5428
|
+
const [savingDefault, setSavingDefault] = useState(false);
|
|
5429
|
+
const [savedDefault, setSavedDefault] = useState(false);
|
|
5430
|
+
const pickerRef = useRef(null);
|
|
5431
|
+
const isAdmin = saveDefaultPerms.length > 0 && hasAnyPerm(saveDefaultPerms);
|
|
5432
|
+
useClickOutside(pickerRef, useCallback(() => {
|
|
5433
|
+
if (pickerOpen) setPickerOpen(false);
|
|
5434
|
+
}, [pickerOpen]));
|
|
5435
|
+
const totalWidth = orderedColumns.reduce((sum, col) => sum + col.width, 0);
|
|
5436
|
+
const colWidths = orderedColumns.map((col) => `${col.width / totalWidth * 100}%`);
|
|
5437
|
+
const saveAsDefault = async () => {
|
|
5438
|
+
setSavingDefault(true);
|
|
5439
|
+
const visibleKeys = allColumns.filter((c) => !c.hidden).map((c) => c.key);
|
|
5440
|
+
const viewport = isMobile ? "mobile" : "desktop";
|
|
5441
|
+
try {
|
|
5442
|
+
await client_default.patch(`/auth/default-columns/${tableId}/`, { visible_columns: visibleKeys }, { params: { viewport } }).catch(
|
|
5443
|
+
() => client_default.post("/auth/default-columns/", { table_id: tableId, viewport, visible_columns: visibleKeys })
|
|
5444
|
+
);
|
|
5445
|
+
setSavedDefault(true);
|
|
5446
|
+
setTimeout(() => setSavedDefault(false), 2e3);
|
|
5447
|
+
} catch {
|
|
5448
|
+
}
|
|
5449
|
+
setSavingDefault(false);
|
|
5450
|
+
};
|
|
5451
|
+
const supportsSelection = useMemo(() => columns.some((c) => c.key === "_select"), [columns]);
|
|
5452
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col flex-1 min-h-0 ${isMobile ? "-mx-4" : ""}`, children: [
|
|
5453
|
+
/* @__PURE__ */ jsxs("table", { className: "w-full divide-y divide-gray-200 shrink-0", style: { tableLayout: "fixed" }, children: [
|
|
5454
|
+
/* @__PURE__ */ jsx("colgroup", { children: orderedColumns.map((col, i) => /* @__PURE__ */ jsx("col", { style: { width: colWidths[i] } }, col.key)) }),
|
|
5455
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsx("tr", { children: orderedColumns.map((col, idx) => {
|
|
5456
|
+
const colDef = columns.find((c) => c.key === col.key);
|
|
5457
|
+
const sortField = colDef?.sortField ?? (col.key !== "_select" ? col.key : void 0);
|
|
5458
|
+
const isSorted = sort && sortField && sort.field === sortField;
|
|
5459
|
+
const isFixed = col.key === "_select";
|
|
5460
|
+
return /* @__PURE__ */ jsxs(
|
|
5461
|
+
"th",
|
|
5462
|
+
{
|
|
5463
|
+
className: `px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase select-none relative ${draggedIdx === idx ? "bg-blue-50" : ""}`,
|
|
5464
|
+
draggable: !isFixed,
|
|
5465
|
+
onDragStart: isFixed ? void 0 : () => onDragStart(idx),
|
|
5466
|
+
onDragOver: isFixed ? void 0 : (e) => onDragOver(idx, e),
|
|
5467
|
+
onDrop: isFixed ? void 0 : (e) => onDrop(idx, e),
|
|
5468
|
+
onDragEnd: isFixed ? void 0 : onDragEnd,
|
|
5469
|
+
style: isFixed ? void 0 : { cursor: "grab" },
|
|
5470
|
+
children: [
|
|
5471
|
+
/* @__PURE__ */ jsxs(
|
|
5472
|
+
"span",
|
|
5473
|
+
{
|
|
5474
|
+
className: `${isFixed ? "" : "truncate pr-3"} block ${sortField && onSort ? "cursor-pointer hover:text-gray-700" : ""}`,
|
|
5475
|
+
onClick: sortField && onSort ? (e) => {
|
|
5476
|
+
e.stopPropagation();
|
|
5477
|
+
onSort(sortField);
|
|
5478
|
+
} : void 0,
|
|
5479
|
+
children: [
|
|
5480
|
+
col.headerNode ?? col.label,
|
|
5481
|
+
isSorted && /* @__PURE__ */ jsx("span", { className: "ml-1", children: sort.direction === "asc" ? "\u25B2" : "\u25BC" })
|
|
5482
|
+
]
|
|
5483
|
+
}
|
|
5484
|
+
),
|
|
5485
|
+
!isFixed && /* @__PURE__ */ jsx(
|
|
5486
|
+
"div",
|
|
5487
|
+
{
|
|
5488
|
+
className: "absolute right-0 top-0 bottom-0 w-4 cursor-col-resize flex items-center justify-center z-10",
|
|
5489
|
+
onMouseDown: (e) => onResizeStart(idx, e),
|
|
5490
|
+
style: { marginRight: -8 },
|
|
5491
|
+
children: /* @__PURE__ */ jsx("div", { className: "w-0.5 h-full bg-gray-200 hover:bg-blue-500 transition-colors" })
|
|
5492
|
+
}
|
|
5493
|
+
),
|
|
5494
|
+
dropGap === idx && /* @__PURE__ */ jsx("div", { className: "absolute left-0 top-0 bottom-0 w-0.5 bg-blue-500 z-20 pointer-events-none" }),
|
|
5495
|
+
idx === orderedColumns.length - 1 && dropGap === orderedColumns.length && /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-0 bottom-0 w-0.5 bg-blue-500 z-20 pointer-events-none" })
|
|
5496
|
+
]
|
|
5497
|
+
},
|
|
5498
|
+
col.key
|
|
5499
|
+
);
|
|
5500
|
+
}) }) })
|
|
5501
|
+
] }),
|
|
5502
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto overflow-x-auto min-h-0", children: [
|
|
5503
|
+
/* @__PURE__ */ jsxs("table", { className: "w-full divide-y divide-gray-200", style: { tableLayout: "fixed" }, children: [
|
|
5504
|
+
/* @__PURE__ */ jsx("colgroup", { children: orderedColumns.map((col, i) => /* @__PURE__ */ jsx("col", { style: { width: colWidths[i] } }, col.key)) }),
|
|
5505
|
+
children(orderedColumns)
|
|
5506
|
+
] }),
|
|
5507
|
+
afterBody
|
|
5508
|
+
] }),
|
|
5509
|
+
footer !== void 0 && /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 px-4 py-2 text-sm text-gray-500 shrink-0 flex items-center justify-between", children: [
|
|
5510
|
+
/* @__PURE__ */ jsx("span", { children: footer }),
|
|
5511
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 relative", ref: pickerRef, children: [
|
|
5512
|
+
isMobile && supportsSelection && /* @__PURE__ */ jsx(
|
|
5513
|
+
"button",
|
|
5514
|
+
{
|
|
5515
|
+
onClick: () => setSelectionMode((s) => !s),
|
|
5516
|
+
className: `text-[11px] px-2 py-0.5 rounded ${selectionMode ? "bg-blue-600 text-white" : "text-gray-500 hover:text-gray-700 border border-gray-300"}`,
|
|
5517
|
+
title: selectionMode ? "Hide selection column" : "Show selection column",
|
|
5518
|
+
children: selectionMode ? "Done" : "Select"
|
|
5519
|
+
}
|
|
5520
|
+
),
|
|
5521
|
+
/* @__PURE__ */ jsx("button", { onClick: resetColumns, className: "text-[10px] text-gray-400 hover:text-gray-600", children: "Reset" }),
|
|
5522
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setPickerOpen(!pickerOpen), className: "text-gray-400 hover:text-gray-600", title: "Choose columns", children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "1.5", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" }) }) }),
|
|
5523
|
+
pickerOpen && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full right-0 mb-1 w-52 rounded-2xl z-50 py-1 max-h-80 overflow-y-auto", style: glassStyle(), children: [
|
|
5524
|
+
/* @__PURE__ */ jsx("p", { className: "px-3 py-1.5 text-[10px] font-semibold text-gray-400 uppercase", children: "Columns" }),
|
|
5525
|
+
allColumns.filter((col) => col.key !== "_select").map((col) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 px-3 py-1 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer", children: [
|
|
5526
|
+
/* @__PURE__ */ jsx(
|
|
5527
|
+
"input",
|
|
5528
|
+
{
|
|
5529
|
+
type: "checkbox",
|
|
5530
|
+
checked: !col.hidden,
|
|
5531
|
+
onChange: () => toggleColumn(col.key),
|
|
5532
|
+
className: "h-3.5 w-3.5 rounded border-gray-300 text-blue-600"
|
|
5533
|
+
}
|
|
5534
|
+
),
|
|
5535
|
+
col.label
|
|
5536
|
+
] }, col.key)),
|
|
5537
|
+
isAdmin && /* @__PURE__ */ jsx("div", { className: "border-t border-gray-100 mt-1 pt-1 px-3 pb-1", children: /* @__PURE__ */ jsx(
|
|
5538
|
+
"button",
|
|
5539
|
+
{
|
|
5540
|
+
onClick: saveAsDefault,
|
|
5541
|
+
disabled: savingDefault,
|
|
5542
|
+
className: `text-[10px] w-full text-center py-1 rounded ${savedDefault ? "text-green-600" : "text-gray-500 hover:text-blue-600"}`,
|
|
5543
|
+
children: savingDefault ? "..." : savedDefault ? "Saved as default" : "Save as default for all users"
|
|
5544
|
+
}
|
|
5545
|
+
) })
|
|
5546
|
+
] })
|
|
5547
|
+
] })
|
|
5548
|
+
] })
|
|
5549
|
+
] });
|
|
5550
|
+
}
|
|
5551
|
+
function ListFooter({
|
|
5552
|
+
selectedCount,
|
|
5553
|
+
loadedCount,
|
|
5554
|
+
totalCount,
|
|
5555
|
+
label,
|
|
5556
|
+
isFetchingMore,
|
|
5557
|
+
extra
|
|
5558
|
+
}) {
|
|
5559
|
+
const total = totalCount ?? loadedCount;
|
|
5560
|
+
const allLoaded = loadedCount >= total;
|
|
5561
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5562
|
+
extra,
|
|
5563
|
+
selectedCount > 0 ? `${selectedCount} selected \u2014 ` : "",
|
|
5564
|
+
allLoaded ? totalCount != null ? `All ${total.toLocaleString()} ${label} loaded` : `${total.toLocaleString()} ${label}` : `${loadedCount.toLocaleString()} of ${total.toLocaleString()} ${label}`,
|
|
5565
|
+
isFetchingMore ? " \xB7 Loading more..." : ""
|
|
5566
|
+
] });
|
|
5567
|
+
}
|
|
5568
|
+
function EntityList(props) {
|
|
5569
|
+
const {
|
|
5570
|
+
items,
|
|
5571
|
+
isLoading,
|
|
5572
|
+
emptyState,
|
|
5573
|
+
totalCount,
|
|
5574
|
+
tableId,
|
|
5575
|
+
columns,
|
|
5576
|
+
renderCell,
|
|
5577
|
+
getRowId = (item) => item.id,
|
|
5578
|
+
sort,
|
|
5579
|
+
onSort,
|
|
5580
|
+
selected,
|
|
5581
|
+
setSelected,
|
|
5582
|
+
onRowClick,
|
|
5583
|
+
onRowHover,
|
|
5584
|
+
getRowClassName,
|
|
5585
|
+
footerLabel,
|
|
5586
|
+
footerExtra,
|
|
5587
|
+
sentinelRef,
|
|
5588
|
+
isFetchingNextPage,
|
|
5589
|
+
saveDefaultPerms
|
|
5590
|
+
} = props;
|
|
5591
|
+
const toggleItem = (item) => {
|
|
5592
|
+
setSelected((prev) => {
|
|
5593
|
+
const next = new Set(prev);
|
|
5594
|
+
const id = getRowId(item);
|
|
5595
|
+
if (next.has(id)) next.delete(id);
|
|
5596
|
+
else next.add(id);
|
|
5597
|
+
return next;
|
|
5598
|
+
});
|
|
5599
|
+
};
|
|
5600
|
+
const toggleAll = () => {
|
|
5601
|
+
setSelected((prev) => prev.size === items.length ? /* @__PURE__ */ new Set() : new Set(items.map(getRowId)));
|
|
5602
|
+
};
|
|
5603
|
+
const selectRange = (from, to) => {
|
|
5604
|
+
setSelected((prev) => {
|
|
5605
|
+
const next = new Set(prev);
|
|
5606
|
+
for (let i = from; i <= to; i++) next.add(getRowId(items[i]));
|
|
5607
|
+
return next;
|
|
5608
|
+
});
|
|
5609
|
+
};
|
|
5610
|
+
const focusIdx = useTableNav(items, onRowClick, toggleItem, toggleAll, selectRange);
|
|
5611
|
+
if (isLoading) return /* @__PURE__ */ jsx(LoadingSpinner, {});
|
|
5612
|
+
if (items.length === 0) return /* @__PURE__ */ jsx(Fragment, { children: emptyState });
|
|
5613
|
+
const allSelected = items.length > 0 && selected.size === items.length;
|
|
5614
|
+
const fullColumns = [
|
|
5615
|
+
{
|
|
5616
|
+
key: "_select",
|
|
5617
|
+
label: "",
|
|
5618
|
+
defaultWidth: 52,
|
|
5619
|
+
minWidth: 52,
|
|
5620
|
+
headerNode: /* @__PURE__ */ jsx(
|
|
5621
|
+
"input",
|
|
5622
|
+
{
|
|
5623
|
+
type: "checkbox",
|
|
5624
|
+
checked: allSelected,
|
|
5625
|
+
onChange: toggleAll,
|
|
5626
|
+
className: "h-3.5 w-3.5 rounded border-gray-300 text-blue-600"
|
|
5627
|
+
}
|
|
5628
|
+
)
|
|
5629
|
+
},
|
|
5630
|
+
...columns
|
|
5631
|
+
];
|
|
5632
|
+
const footer = /* @__PURE__ */ jsx(
|
|
5633
|
+
ListFooter,
|
|
5634
|
+
{
|
|
5635
|
+
selectedCount: selected.size,
|
|
5636
|
+
loadedCount: items.length,
|
|
5637
|
+
totalCount,
|
|
5638
|
+
label: footerLabel,
|
|
5639
|
+
isFetchingMore: isFetchingNextPage,
|
|
5640
|
+
extra: footerExtra
|
|
5641
|
+
}
|
|
5642
|
+
);
|
|
5643
|
+
const afterBody = sentinelRef ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5644
|
+
/* @__PURE__ */ jsx("div", { ref: sentinelRef }),
|
|
5645
|
+
isFetchingNextPage && /* @__PURE__ */ jsx("div", { className: "text-center py-3", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: "Loading more..." }) })
|
|
5646
|
+
] }) : void 0;
|
|
5647
|
+
return /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col mb-1 bg-white rounded-lg shadow overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 flex flex-col", children: /* @__PURE__ */ jsx(
|
|
5648
|
+
ResizableTable,
|
|
5649
|
+
{
|
|
5650
|
+
tableId,
|
|
5651
|
+
columns: fullColumns,
|
|
5652
|
+
sort,
|
|
5653
|
+
onSort,
|
|
5654
|
+
footer,
|
|
5655
|
+
afterBody,
|
|
5656
|
+
saveDefaultPerms,
|
|
5657
|
+
children: (cols) => /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-gray-100", children: items.map((item, rowIdx) => {
|
|
5658
|
+
const id = getRowId(item);
|
|
5659
|
+
return /* @__PURE__ */ jsx(
|
|
5660
|
+
"tr",
|
|
5661
|
+
{
|
|
5662
|
+
"data-row-idx": rowIdx,
|
|
5663
|
+
className: `cursor-pointer ${focusIdx === rowIdx ? "bg-blue-50 ring-1 ring-inset ring-blue-300" : selected.has(id) ? "bg-blue-50 hover:bg-blue-100" : "hover:bg-gray-50"} ${getRowClassName?.(item) ?? ""}`,
|
|
5664
|
+
onClick: () => onRowClick(item),
|
|
5665
|
+
onMouseEnter: onRowHover ? () => onRowHover(item) : void 0,
|
|
5666
|
+
children: cols.map((col) => /* @__PURE__ */ jsx("td", { className: "px-4 py-3 whitespace-nowrap text-sm overflow-hidden", children: col.key === "_select" ? /* @__PURE__ */ jsx(
|
|
5667
|
+
"input",
|
|
5668
|
+
{
|
|
5669
|
+
type: "checkbox",
|
|
5670
|
+
checked: selected.has(id),
|
|
5671
|
+
onClick: (e) => {
|
|
5672
|
+
e.stopPropagation();
|
|
5673
|
+
toggleItem(item);
|
|
5674
|
+
},
|
|
5675
|
+
readOnly: true,
|
|
5676
|
+
className: "h-3.5 w-3.5 rounded border-gray-300 text-blue-600"
|
|
5677
|
+
}
|
|
5678
|
+
) : renderCell(item, col.key) }, col.key))
|
|
5679
|
+
},
|
|
5680
|
+
id
|
|
5681
|
+
);
|
|
5682
|
+
}) })
|
|
5683
|
+
}
|
|
5684
|
+
) }) });
|
|
5685
|
+
}
|
|
5686
|
+
function useInfiniteScroll({
|
|
5687
|
+
queryKey,
|
|
5688
|
+
fetchFn,
|
|
5689
|
+
extraParams = {},
|
|
5690
|
+
pageSize: _pageSize = 25
|
|
5691
|
+
}) {
|
|
5692
|
+
const sentinelRef = useRef(null);
|
|
5693
|
+
const cleanExtra = Object.fromEntries(
|
|
5694
|
+
Object.entries(extraParams).filter(([, v]) => v !== void 0)
|
|
5695
|
+
);
|
|
5696
|
+
const query = useInfiniteQuery({
|
|
5697
|
+
queryKey,
|
|
5698
|
+
queryFn: ({ pageParam = 1 }) => fetchFn({ page: String(pageParam), ...cleanExtra }),
|
|
5699
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
5700
|
+
if (lastPage.next) {
|
|
5701
|
+
return allPages.length + 1;
|
|
5702
|
+
}
|
|
5703
|
+
return void 0;
|
|
5704
|
+
},
|
|
5705
|
+
initialPageParam: 1
|
|
5706
|
+
});
|
|
5707
|
+
const { fetchNextPage, hasNextPage, isFetchingNextPage } = query;
|
|
5708
|
+
const handleObserver = useCallback(
|
|
5709
|
+
(entries) => {
|
|
5710
|
+
const [entry] = entries;
|
|
5711
|
+
if (entry.isIntersecting && hasNextPage && !isFetchingNextPage) {
|
|
5712
|
+
fetchNextPage();
|
|
5713
|
+
}
|
|
5714
|
+
},
|
|
5715
|
+
[fetchNextPage, hasNextPage, isFetchingNextPage]
|
|
5716
|
+
);
|
|
5717
|
+
useEffect(() => {
|
|
5718
|
+
const el = sentinelRef.current;
|
|
5719
|
+
if (!el) return;
|
|
5720
|
+
let scrollParent = el.parentElement;
|
|
5721
|
+
while (scrollParent) {
|
|
5722
|
+
const overflow = getComputedStyle(scrollParent).overflowY;
|
|
5723
|
+
if (overflow === "auto" || overflow === "scroll") break;
|
|
5724
|
+
scrollParent = scrollParent.parentElement;
|
|
5725
|
+
}
|
|
5726
|
+
const observer = new IntersectionObserver(handleObserver, {
|
|
5727
|
+
root: scrollParent,
|
|
5728
|
+
rootMargin: "200px",
|
|
5729
|
+
threshold: 0
|
|
5730
|
+
});
|
|
5731
|
+
observer.observe(el);
|
|
5732
|
+
return () => observer.disconnect();
|
|
5733
|
+
}, [handleObserver]);
|
|
5734
|
+
const allItems = (query.data?.pages.flatMap((page) => page?.results ?? []) ?? []).filter((x) => x != null);
|
|
5735
|
+
const totalCount = query.data?.pages[0]?.count ?? 0;
|
|
5736
|
+
return {
|
|
5737
|
+
items: allItems,
|
|
5738
|
+
totalCount,
|
|
5739
|
+
isLoading: query.isLoading,
|
|
5740
|
+
isFetchingNextPage,
|
|
5741
|
+
hasNextPage: !!hasNextPage,
|
|
5742
|
+
sentinelRef,
|
|
5743
|
+
refetch: query.refetch
|
|
5744
|
+
};
|
|
5745
|
+
}
|
|
5086
5746
|
var EntityFetcherContext = createContext(null);
|
|
5087
5747
|
function ShellEntityFetcherProvider({
|
|
5088
5748
|
value,
|
|
@@ -5129,6 +5789,6 @@ function useEditHotkey(callback) {
|
|
|
5129
5789
|
}, [callback, isActive]);
|
|
5130
5790
|
}
|
|
5131
5791
|
|
|
5132
|
-
export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BugReportConfigProvider, BugReportDetail, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Customization, Desktop, DesktopHostProvider, ENTER, GlobalSearch, Layout, MOD, MailConnectModal, NotificationBell, SHIFT, ShellEntityFetcherProvider, ShortcutHelp, StartMenu, StatusBadge, StatusBadgeProvider, VERSION, createWindowRegistry, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useDesktopHost, useEditHotkey, useNewHotkey, useShellEntityFetcher };
|
|
5792
|
+
export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BugReportConfigProvider, BugReportDetail, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Customization, Desktop, DesktopHostProvider, ENTER, EntityList, GlobalSearch, Layout, ListFooter, MOD, MailConnectModal, NotificationBell, ResizableTable, SHIFT, ShellEntityFetcherProvider, ShortcutHelp, StartMenu, StatusBadge, StatusBadgeProvider, VERSION, createWindowRegistry, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useTableNav };
|
|
5133
5793
|
//# sourceMappingURL=index.js.map
|
|
5134
5794
|
//# sourceMappingURL=index.js.map
|