@parallelworks/ui 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -6
- package/dist/ai/adapter/memoryStore.d.ts +8 -0
- package/dist/ai/adapter/mock/index.d.ts +2 -0
- package/dist/ai/adapter/mock/index.js +81 -0
- package/dist/ai/adapter/mock/mockAdapter.d.ts +4 -0
- package/dist/ai/adapter/openai/createOpenAIStream.d.ts +9 -0
- package/dist/ai/adapter/openai/errors.d.ts +3 -0
- package/dist/ai/adapter/openai/index.d.ts +6 -0
- package/dist/ai/adapter/openai/index.js +334 -0
- package/dist/ai/adapter/openai/openaiAdapter.d.ts +9 -0
- package/dist/ai/adapter/openai/responses.d.ts +4 -0
- package/dist/ai/adapter/openai/sse.d.ts +24 -0
- package/dist/ai/adapter/openai/wire.d.ts +40 -0
- package/dist/ai/adapter/types.d.ts +131 -0
- package/dist/ai/agent/classifier.d.ts +2 -0
- package/dist/ai/agent/diff.d.ts +35 -0
- package/dist/ai/agent/diffHighlight.d.ts +6 -0
- package/dist/ai/agent/index.d.ts +6 -0
- package/dist/ai/agent/permissions.d.ts +11 -0
- package/dist/ai/agent/toolfmt.d.ts +18 -0
- package/dist/ai/agent/transcript.d.ts +38 -0
- package/dist/ai/ai.css +325 -0
- package/dist/ai/components/AllocationSelector.d.ts +4 -0
- package/dist/ai/components/AttachmentManager.d.ts +1 -0
- package/dist/ai/components/AttachmentUpload.d.ts +24 -0
- package/dist/ai/components/BlockedGroupBanner.d.ts +1 -0
- package/dist/ai/components/BranchNavigator.d.ts +8 -0
- package/dist/ai/components/ChatEmptyState.d.ts +3 -0
- package/dist/ai/components/ChatInput.d.ts +45 -0
- package/dist/ai/components/ChatLayout.d.ts +5 -0
- package/dist/ai/components/ChatMessage.d.ts +24 -0
- package/dist/ai/components/ChatMessageList.d.ts +35 -0
- package/dist/ai/components/ChatSidebar.d.ts +5 -0
- package/dist/ai/components/ChatThread.d.ts +3 -0
- package/dist/ai/components/ComposerChrome.d.ts +18 -0
- package/dist/ai/components/ComposerFrame.d.ts +16 -0
- package/dist/ai/components/DragOverlay.d.ts +5 -0
- package/dist/ai/components/ModelSelector.d.ts +6 -0
- package/dist/ai/components/ShareDialog.d.ts +11 -0
- package/dist/ai/components/SlashMenu.d.ts +28 -0
- package/dist/ai/components/agent/ActivityLine.d.ts +21 -0
- package/dist/ai/components/agent/AgentMessageParts.d.ts +54 -0
- package/dist/ai/components/agent/PermissionPicker.d.ts +11 -0
- package/dist/ai/components/attachmentKeys.d.ts +4 -0
- package/dist/ai/core/ChatProvider.d.ts +66 -0
- package/dist/ai/core/KeyboardShortcutsProvider.d.ts +5 -0
- package/dist/ai/core/chatReducer.d.ts +114 -0
- package/dist/ai/core/config.d.ts +47 -0
- package/dist/ai/core/events.d.ts +1 -0
- package/dist/ai/core/exportConversation.d.ts +4 -0
- package/dist/ai/core/greeting.d.ts +3 -0
- package/dist/ai/core/parts.d.ts +11 -0
- package/dist/ai/core/useDragDrop.d.ts +14 -0
- package/dist/ai/core/useKeyboardShortcuts.d.ts +12 -0
- package/dist/ai/core/useSSEStream.d.ts +34 -0
- package/dist/ai/index.d.ts +40 -0
- package/dist/ai/index.js +6645 -0
- package/dist/ai/strings.d.ts +167 -0
- package/dist/ai/types.d.ts +236 -0
- package/dist/ai/ui/Avatar.d.ts +8 -0
- package/dist/ai/ui/Dropdown.d.ts +31 -0
- package/dist/ai/ui/Markdown.d.ts +8 -0
- package/dist/ai/ui/Notice.d.ts +21 -0
- package/dist/ai/ui/buttons.d.ts +1 -0
- package/dist/ai/ui/codeBreaks.d.ts +16 -0
- package/dist/ai/ui/prose.d.ts +1 -0
- package/dist/ai/ui/sidebar.d.ts +81 -0
- package/dist/ai/utils.d.ts +4 -0
- package/dist/assets/{editor.worker-CuBRIwi-.js → editor.worker-BmHUIVG4.js} +194 -163
- package/dist/assets/{json.worker-8ytS02vz.js → json.worker-D8bJ92nw.js} +384 -338
- package/dist/assets/{yaml.worker-DJC-VUcv.js → yaml.worker-C4gyGAko.js} +15657 -13823
- package/dist/chunks/{CodePreviewEditor-4lx3kE-w.js → CodePreviewEditor-YqQBz1YL.js} +1 -1
- package/dist/chunks/ConfirmModal-aOR4O1QE.js +79 -0
- package/dist/chunks/{FieldWrapper-Bef01EWO.js → FieldWrapper-Cszwg-4B.js} +3 -7
- package/dist/chunks/{CreateModal-BY6DLmur.js → Markdown-CM-FenNE.js} +19 -91
- package/dist/chunks/Monaco-DJ8MW-Dq.js +110 -0
- package/dist/chunks/{PageHeader-l49p1nM9.js → PageHeader-0kG_iypP.js} +67 -65
- package/dist/chunks/{Provider-Ghua9PkN.js → Provider-CDYurraE.js} +54 -20
- package/dist/chunks/{SwitchToggle-CHPP8uZQ.js → SwitchToggle-DShNdcao.js} +135 -132
- package/dist/chunks/{Table-4OHjdKdO.js → Table-DU2MW8xz.js} +5 -3
- package/dist/chunks/{Tooltip-Crxo_eU_.js → Tooltip-K5HJr4_p.js} +31 -4
- package/dist/chunks/duration-BOv8Phl8.js +17 -0
- package/dist/chunks/{editor-9_uVtUyy.js → editor-Dk1rbV75.js} +32 -18
- package/dist/chunks/focus-D_iZJTW1.js +7 -0
- package/dist/chunks/{list-qrojZZNv.js → list-CJm875m7.js} +377 -370
- package/dist/chunks/logviewer-BTKuQWzw.js +828 -0
- package/dist/chunks/memoryStore-CC91S5LP.js +152 -0
- package/dist/chunks/types-Yy0NrerF.js +11 -0
- package/dist/components/Avatar.d.ts +1 -1
- package/dist/components/Breadcrumbs.d.ts +1 -1
- package/dist/components/Dropdown.d.ts +1 -1
- package/dist/components/EmptyState.d.ts +1 -1
- package/dist/components/Indicator.d.ts +2 -2
- package/dist/components/Input.d.ts +1 -1
- package/dist/components/LetterBadge.d.ts +1 -1
- package/dist/components/MarkdownImpl.d.ts +1 -1
- package/dist/components/Provider.d.ts +16 -65
- package/dist/components/SettingRow.d.ts +1 -1
- package/dist/components/SettingsGroup.d.ts +1 -1
- package/dist/components/focus.d.ts +2 -0
- package/dist/components/keys.d.ts +12 -0
- package/dist/duration.d.ts +3 -0
- package/dist/editor/Monaco.d.ts +1 -20
- package/dist/editor/index.d.ts +2 -1
- package/dist/editor/index.js +2 -2
- package/dist/editor/yaml.d.ts +5 -0
- package/dist/engine.d.ts +98 -0
- package/dist/file-explorer/FileExplorer.d.ts +11 -2
- package/dist/file-explorer/FileExplorerContext.d.ts +1 -1
- package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +1 -1
- package/dist/file-explorer/FilePreview/previewType.d.ts +1 -1
- package/dist/file-explorer/FileRow.d.ts +1 -1
- package/dist/file-explorer/helpers.d.ts +4 -4
- package/dist/file-explorer/index.d.ts +3 -3
- package/dist/file-explorer/index.js +613 -647
- package/dist/file-explorer/lib/types.d.ts +6 -1
- package/dist/file-explorer/lib/utils.d.ts +1 -3
- package/dist/file-explorer/useNearEnd.d.ts +1 -1
- package/dist/form/FieldWrapper.d.ts +2 -2
- package/dist/form/Fields/ResourceOptionIcon.d.ts +1 -1
- package/dist/form/Form.d.ts +4 -21
- package/dist/form/index.d.ts +11 -12
- package/dist/form/index.js +1488 -1611
- package/dist/form/lib.d.ts +6 -1
- package/dist/form/types/fieldComponentTypes.d.ts +3 -2
- package/dist/form/types/fieldTypes.d.ts +6 -20
- package/dist/form/useParsedOpts.d.ts +1 -1
- package/dist/form/utils/{slurmDuration.d.ts → duration.d.ts} +2 -2
- package/dist/{workflow → graph}/MatrixGroup.d.ts +2 -2
- package/dist/{workflow → graph}/index.d.ts +1 -1
- package/dist/{workflow → graph}/index.js +215 -180
- package/dist/{workflow → graph}/types.d.ts +3 -3
- package/dist/icons.d.ts +20 -21
- package/dist/index.d.ts +38 -40
- package/dist/index.js +347 -346
- package/dist/list/ListTable.d.ts +1 -1
- package/dist/list/ListViewControls.d.ts +2 -2
- package/dist/list/index.d.ts +9 -9
- package/dist/list/index.js +2 -2
- package/dist/logviewer/LogViewer.d.ts +1 -1
- package/dist/logviewer/index.d.ts +1 -0
- package/dist/logviewer/index.js +2 -742
- package/dist/logviewer/segments.d.ts +9 -0
- package/dist/styles/fonts.css +4 -4
- package/dist/styles/theme.css +6 -4
- package/dist/styles.css +1 -1
- package/dist/theme/index.js +2 -2
- package/package.json +38 -14
- package/LICENSE +0 -202
- package/dist/chunks/Monaco-C1POOdVv.js +0 -1046
- package/dist/editor/usesGitlab.d.ts +0 -97
- package/dist/form/Fields/BucketReadOnlyField.d.ts +0 -7
- package/dist/form/types/workflow-schema.d.ts +0 -1145
- package/dist/form/utils/pwResolver.d.ts +0 -18
- package/dist/chunks/{MarkdownImpl-Bq4QhrtA.js → MarkdownImpl-CyeTVvSt.js} +1 -1
- /package/dist/{workflow → graph}/AnnotationBanner.d.ts +0 -0
- /package/dist/{workflow → graph}/Collapse.d.ts +0 -0
- /package/dist/{workflow → graph}/DependencyGraph.d.ts +0 -0
- /package/dist/{workflow → graph}/JobSummary.d.ts +0 -0
- /package/dist/{workflow → graph}/Reveal.d.ts +0 -0
- /package/dist/{workflow → graph}/TreeView.d.ts +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { T as Avatar, _ as useRowMenuActive, c as PageHeader, f as rowContextMenuProps, u as MoreButton } from "./PageHeader-l49p1nM9.js";
|
|
1
|
+
import { n as useLink, o as usePersistedState, r as useNavigation, u as useStrings } from "./Provider-CDYurraE.js";
|
|
3
2
|
import { CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, DisplayIcon, ErrorIcon, FilterIcon, MenuIcon, SearchIcon, XIcon } from "../icons.js";
|
|
4
|
-
import { n as TOOLTIP_ID, r as TooltipInfo } from "./Tooltip-
|
|
5
|
-
import {
|
|
3
|
+
import { n as TOOLTIP_ID, r as TooltipInfo, s as positionKeys } from "./Tooltip-K5HJr4_p.js";
|
|
4
|
+
import { _ as useRowMenuActive, c as PageHeader, f as rowContextMenuProps, u as MoreButton, w as Avatar } from "./PageHeader-0kG_iypP.js";
|
|
5
|
+
import { n as Table } from "./Table-DU2MW8xz.js";
|
|
6
|
+
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
|
|
6
7
|
import cx from "classnames";
|
|
7
8
|
import { Children, Fragment, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
8
9
|
import { useLocalStorage } from "usehooks-ts";
|
|
9
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
11
|
import { createPortal } from "react-dom";
|
|
11
|
-
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
|
|
12
12
|
//#region src/list/ActionToolbar.tsx
|
|
13
13
|
var OverflowMenuContext = createContext(false);
|
|
14
14
|
/** Omits data-tooltip-content when absent — react-tooltip treats an explicit undefined as an empty tooltip anchor. */
|
|
@@ -185,6 +185,74 @@ function ActionToolbar({ groups, right = [], sticky = false }) {
|
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
187
|
//#endregion
|
|
188
|
+
//#region src/list/HoverCard.tsx
|
|
189
|
+
function useHoverCard() {
|
|
190
|
+
const triggerRef = useRef(null);
|
|
191
|
+
const [coords, setCoords] = useState(null);
|
|
192
|
+
const openTimer = useRef(void 0);
|
|
193
|
+
const closeTimer = useRef(void 0);
|
|
194
|
+
useEffect(() => () => {
|
|
195
|
+
clearTimeout(openTimer.current);
|
|
196
|
+
clearTimeout(closeTimer.current);
|
|
197
|
+
}, []);
|
|
198
|
+
const scheduleOpen = () => {
|
|
199
|
+
clearTimeout(closeTimer.current);
|
|
200
|
+
openTimer.current = setTimeout(() => {
|
|
201
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
202
|
+
if (rect) setCoords({
|
|
203
|
+
x: rect.left,
|
|
204
|
+
y: rect.bottom
|
|
205
|
+
});
|
|
206
|
+
}, 350);
|
|
207
|
+
};
|
|
208
|
+
const scheduleClose = () => {
|
|
209
|
+
clearTimeout(openTimer.current);
|
|
210
|
+
closeTimer.current = setTimeout(() => setCoords(null), 150);
|
|
211
|
+
};
|
|
212
|
+
const keepOpen = () => clearTimeout(closeTimer.current);
|
|
213
|
+
return {
|
|
214
|
+
triggerRef,
|
|
215
|
+
coords,
|
|
216
|
+
scheduleOpen,
|
|
217
|
+
scheduleClose,
|
|
218
|
+
keepOpen
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function HoverCardSurface({ x, y, widthClassName, padded = true, relayoutKey, onKeepOpen, onLeave, children }) {
|
|
222
|
+
const ref = useRef(null);
|
|
223
|
+
const [pos, setPos] = useState(null);
|
|
224
|
+
useLayoutEffect(() => {
|
|
225
|
+
if (!ref.current) return;
|
|
226
|
+
const { width, height } = ref.current.getBoundingClientRect();
|
|
227
|
+
const pad = 8;
|
|
228
|
+
const left = Math.max(pad, Math.min(x, window.innerWidth - width - pad));
|
|
229
|
+
const top = y + 8 + height + pad > window.innerHeight ? Math.max(pad, y - 8 - height) : y + 8;
|
|
230
|
+
setPos({
|
|
231
|
+
left,
|
|
232
|
+
top
|
|
233
|
+
});
|
|
234
|
+
}, [
|
|
235
|
+
x,
|
|
236
|
+
y,
|
|
237
|
+
relayoutKey
|
|
238
|
+
]);
|
|
239
|
+
return createPortal(/* @__PURE__ */ jsx("div", {
|
|
240
|
+
ref,
|
|
241
|
+
role: "none",
|
|
242
|
+
onMouseEnter: onKeepOpen,
|
|
243
|
+
onMouseLeave: onLeave,
|
|
244
|
+
onFocus: onKeepOpen,
|
|
245
|
+
onBlur: onLeave,
|
|
246
|
+
className: cx("fixed z-[9999] overflow-hidden rounded-xl border border-(--theme-border) bg-(--theme-panel-bg) shadow-xl backdrop-blur-xl", padded && "p-3", widthClassName),
|
|
247
|
+
style: {
|
|
248
|
+
left: pos?.left ?? x,
|
|
249
|
+
top: pos?.top ?? y + 8,
|
|
250
|
+
visibility: pos ? "visible" : "hidden"
|
|
251
|
+
},
|
|
252
|
+
children
|
|
253
|
+
}), document.querySelector(".ds-root") ?? document.body);
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
188
256
|
//#region src/list/ListTable.tsx
|
|
189
257
|
var NAME_TEXT = "font-medium text-[13px] leading-tight text-(--theme-app) truncate";
|
|
190
258
|
var SUBTITLE_TEXT = "text-xs leading-tight text-(--theme-muted-text-color) truncate";
|
|
@@ -274,7 +342,7 @@ function ListSkeleton({ rows = 6 }) {
|
|
|
274
342
|
role: "status",
|
|
275
343
|
"aria-label": loading,
|
|
276
344
|
className: "divide-y border-b border-(--theme-border) divide-(--theme-border)",
|
|
277
|
-
children: [
|
|
345
|
+
children: [positionKeys(rows, "skeleton").map((key) => /* @__PURE__ */ jsxs("div", {
|
|
278
346
|
"aria-hidden": "true",
|
|
279
347
|
className: "flex items-center gap-3 px-4 py-2.5 animate-pulse",
|
|
280
348
|
children: [
|
|
@@ -285,7 +353,7 @@ function ListSkeleton({ rows = 6 }) {
|
|
|
285
353
|
}),
|
|
286
354
|
/* @__PURE__ */ jsx("div", { className: "ml-auto h-3 w-20 rounded bg-(--theme-muted-panel-bg)" })
|
|
287
355
|
]
|
|
288
|
-
},
|
|
356
|
+
}, key)), /* @__PURE__ */ jsx("span", {
|
|
289
357
|
className: "sr-only",
|
|
290
358
|
children: loading
|
|
291
359
|
})]
|
|
@@ -381,8 +449,9 @@ function ListRowActionsProvider({ view, children }) {
|
|
|
381
449
|
});
|
|
382
450
|
}
|
|
383
451
|
function ListPage({ section = "main", shellPadded, embedded = false, breadcrumbs, title, titleAction, actions, toolbar, view, children }) {
|
|
452
|
+
const cancelShellPadding = shellPadded ?? SECTION_SHELL_PADDED[section];
|
|
384
453
|
return /* @__PURE__ */ jsxs("div", {
|
|
385
|
-
className: cx("flex h-full min-h-0 flex-col",
|
|
454
|
+
className: cx("flex h-full min-h-0 flex-col", cancelShellPadding && "-m-4"),
|
|
386
455
|
children: [embedded ? toolbar && /* @__PURE__ */ jsx("div", {
|
|
387
456
|
className: "px-4 py-1.5",
|
|
388
457
|
children: toolbar
|
|
@@ -475,252 +544,46 @@ function useListNavigate() {
|
|
|
475
544
|
return useNavigation().goTo;
|
|
476
545
|
}
|
|
477
546
|
//#endregion
|
|
478
|
-
//#region src/list/
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return
|
|
547
|
+
//#region src/list/textEntry.ts
|
|
548
|
+
/** Guards list-page shortcuts from firing inside inputs, terminals, editors, and dialogs. */
|
|
549
|
+
function isTextEntryContext(target) {
|
|
550
|
+
const el = target;
|
|
551
|
+
if (!el) return false;
|
|
552
|
+
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable) return true;
|
|
553
|
+
return Boolean(el.closest?.(".xterm, .monaco-editor, .cm-editor, [role=\"dialog\"]"));
|
|
485
554
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
*
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
555
|
+
//#endregion
|
|
556
|
+
//#region src/list/ListViewControls.tsx
|
|
557
|
+
/** Shared chrome for the toolbar control buttons (Filter, Display, Search) so
|
|
558
|
+
* they read as a consistent button cluster — matched by ListSearchControl. */
|
|
559
|
+
var listControlButtonClasses = "relative flex h-7 w-7 items-center justify-center rounded-md border border-(--theme-border) text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app) transition-colors";
|
|
560
|
+
var FLYOUT = "min-w-44 rounded-lg border border-(--theme-border) bg-(--theme-app-bg) py-1 shadow-lg";
|
|
561
|
+
/** Toggle pill shared by the Display menu's column + pinned-action pickers. */
|
|
562
|
+
function pillClass(on) {
|
|
563
|
+
return cx("whitespace-nowrap rounded-full border px-2.5 py-1 text-[12px] transition-colors", on ? "border-transparent bg-(--theme-muted-panel-bg) text-(--theme-app)" : "border-(--theme-border) text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app)");
|
|
564
|
+
}
|
|
565
|
+
var SECTION_LABEL = "mb-2 text-[11px] font-medium uppercase tracking-wide text-(--theme-muted-text-color)";
|
|
566
|
+
/** Portals into .ds-root so the panel escapes the toolbar's overflow clipping. */
|
|
567
|
+
function AnchoredPopover({ icon, label, active, shortcut, panelClassName, children }) {
|
|
568
|
+
const btnRef = useRef(null);
|
|
569
|
+
const panelRef = useRef(null);
|
|
570
|
+
const [pos, setPos] = useState(null);
|
|
571
|
+
const close = useCallback(() => setPos(null), []);
|
|
572
|
+
const open = useCallback(() => {
|
|
573
|
+
const r = btnRef.current?.getBoundingClientRect();
|
|
574
|
+
if (r) setPos({
|
|
575
|
+
right: Math.max(8, Math.round(window.innerWidth - r.right)),
|
|
576
|
+
top: Math.round(r.bottom) + 4
|
|
577
|
+
});
|
|
578
|
+
}, []);
|
|
579
|
+
useEffect(() => {
|
|
580
|
+
if (!pos) return;
|
|
581
|
+
const onKey = (e) => {
|
|
582
|
+
if (e.key === "Escape") close();
|
|
500
583
|
};
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
label: t.orderDefault,
|
|
505
|
-
compare: (a, b) => onRank(a) - onRank(b) || favoriteRank(a) - favoriteRank(b) || newestFirst(a, b) || (tiebreak?.(a, b) ?? 0)
|
|
506
|
-
}, {
|
|
507
|
-
value: FAVORITE_ORDER,
|
|
508
|
-
label: t.orderFavorites,
|
|
509
|
-
compare: (a, b) => favoriteRank(a) - favoriteRank(b) || (tiebreak?.(a, b) ?? 0)
|
|
510
|
-
}], ...orderBys];
|
|
511
|
-
}, [
|
|
512
|
-
orderBys,
|
|
513
|
-
isFavorite,
|
|
514
|
-
isOn,
|
|
515
|
-
createdAt,
|
|
516
|
-
tiebreak,
|
|
517
|
-
t
|
|
518
|
-
]);
|
|
519
|
-
const defaultGroupByValue = defaultGroupBy ?? groupBys[0]?.value ?? "";
|
|
520
|
-
const defaultOrderByValue = isFavorite ? DEFAULT_ORDER : defaultOrderBy ?? orderBys[0]?.value ?? "";
|
|
521
|
-
const defaultHiddenKeys = useMemo(() => columns.filter((c) => c.defaultHidden && !c.alwaysVisible).map((c) => c.key), [columns]);
|
|
522
|
-
const defaultPinnedKeys = useMemo(() => actions.filter((a) => a.defaultPinned).map((a) => a.key), [actions]);
|
|
523
|
-
const [hiddenKeys, setHiddenKeys] = usePersistedState(`${storageKey}:hiddenColumns`, defaultHiddenKeys);
|
|
524
|
-
const [pinnedKeys, setPinnedKeys] = usePersistedState(`${storageKey}:pinnedActions`, defaultPinnedKeys);
|
|
525
|
-
const [groupBy, setGroupBy] = usePersistedState(`${storageKey}:groupBy`, defaultGroupByValue);
|
|
526
|
-
const [showColumnHeaders, setShowColumnHeaders] = usePersistedState(`${storageKey}:showColumnHeaders`, defaultShowColumnHeaders);
|
|
527
|
-
const [showActions, setShowActions] = usePersistedState(`${storageKey}:showActions`, defaultShowActions);
|
|
528
|
-
const [alwaysShowActions, setAlwaysShowActions] = usePersistedState(`${storageKey}:alwaysShowActions`, false);
|
|
529
|
-
const [orderBy, setOrderBy] = usePersistedState(`${storageKey}:orderBy`, defaultOrderByValue);
|
|
530
|
-
const [orderDir, setOrderDir] = usePersistedState(`${storageKey}:orderDir`, "asc");
|
|
531
|
-
const [localFilters, setLocalFilters] = usePersistedState(`${storageKey}:filters`, {});
|
|
532
|
-
const [sharedFilters, setSharedFilters] = usePersistedState(`${sharedFiltersKey ?? storageKey}:sharedFilters`, {});
|
|
533
|
-
const sharedKeys = useMemo(() => new Set(facets.filter((f) => f.shared).map((f) => f.key)), [facets]);
|
|
534
|
-
const filters = useMemo(() => {
|
|
535
|
-
if (sharedKeys.size === 0) return localFilters;
|
|
536
|
-
const merged = {};
|
|
537
|
-
for (const [key, values] of Object.entries(localFilters)) if (!sharedKeys.has(key)) merged[key] = values;
|
|
538
|
-
for (const key of sharedKeys) {
|
|
539
|
-
const values = sharedFilters[key];
|
|
540
|
-
if (values?.length) merged[key] = values;
|
|
541
|
-
}
|
|
542
|
-
return merged;
|
|
543
|
-
}, [
|
|
544
|
-
localFilters,
|
|
545
|
-
sharedFilters,
|
|
546
|
-
sharedKeys
|
|
547
|
-
]);
|
|
548
|
-
const pinnedCount = actionCount ?? pinnedKeys.filter((key) => actions.some((action) => action.key === key)).length;
|
|
549
|
-
const effectiveShowActions = showActions || alwaysShowActions;
|
|
550
|
-
const actionsWidth = effectiveShowActions ? actionsColumnWidth(pinnedCount) : 0;
|
|
551
|
-
const isVisible = useCallback((key) => {
|
|
552
|
-
const col = columns.find((c) => c.key === key);
|
|
553
|
-
return Boolean(col?.alwaysVisible) || !hiddenKeys.includes(key);
|
|
554
|
-
}, [columns, hiddenKeys]);
|
|
555
|
-
const visibleColumns = useMemo(() => columns.filter((c) => !c.inline && (c.alwaysVisible || !hiddenKeys.includes(c.key))), [columns, hiddenKeys]);
|
|
556
|
-
const columnClasses = useMemo(() => visibleColumns.map(columnResponsiveClass), [visibleColumns]);
|
|
557
|
-
const toggleColumn = useCallback((key) => setHiddenKeys((prev) => prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]), [setHiddenKeys]);
|
|
558
|
-
const setFacetValues = useCallback((key, values) => {
|
|
559
|
-
const update = (prev) => {
|
|
560
|
-
const next = { ...prev };
|
|
561
|
-
if (values.length) next[key] = values;
|
|
562
|
-
else delete next[key];
|
|
563
|
-
return next;
|
|
564
|
-
};
|
|
565
|
-
if (sharedKeys.has(key)) setSharedFilters(update);
|
|
566
|
-
else setLocalFilters(update);
|
|
567
|
-
}, [
|
|
568
|
-
setLocalFilters,
|
|
569
|
-
setSharedFilters,
|
|
570
|
-
sharedKeys
|
|
571
|
-
]);
|
|
572
|
-
const clearFilters = useCallback(() => {
|
|
573
|
-
setLocalFilters({});
|
|
574
|
-
if (sharedKeys.size > 0) setSharedFilters((prev) => {
|
|
575
|
-
const next = { ...prev };
|
|
576
|
-
for (const key of sharedKeys) delete next[key];
|
|
577
|
-
return next;
|
|
578
|
-
});
|
|
579
|
-
}, [
|
|
580
|
-
setLocalFilters,
|
|
581
|
-
setSharedFilters,
|
|
582
|
-
sharedKeys
|
|
583
|
-
]);
|
|
584
|
-
const isPinned = useCallback((key) => pinnedKeys.includes(key), [pinnedKeys]);
|
|
585
|
-
const togglePinned = useCallback((key) => setPinnedKeys((prev) => prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]), [setPinnedKeys]);
|
|
586
|
-
const toggleColumnHeaders = useCallback(() => setShowColumnHeaders((prev) => !prev), [setShowColumnHeaders]);
|
|
587
|
-
const toggleShowActions = useCallback(() => {
|
|
588
|
-
if (effectiveShowActions) {
|
|
589
|
-
setShowActions(false);
|
|
590
|
-
setAlwaysShowActions(false);
|
|
591
|
-
} else setShowActions(true);
|
|
592
|
-
}, [
|
|
593
|
-
effectiveShowActions,
|
|
594
|
-
setShowActions,
|
|
595
|
-
setAlwaysShowActions
|
|
596
|
-
]);
|
|
597
|
-
const toggleAlwaysShowActions = useCallback(() => {
|
|
598
|
-
const next = !alwaysShowActions;
|
|
599
|
-
setAlwaysShowActions(next);
|
|
600
|
-
if (next) setShowActions(true);
|
|
601
|
-
}, [
|
|
602
|
-
alwaysShowActions,
|
|
603
|
-
setAlwaysShowActions,
|
|
604
|
-
setShowActions
|
|
605
|
-
]);
|
|
606
|
-
const toggleOrderDir = useCallback(() => setOrderDir((d) => d === "asc" ? "desc" : "asc"), [setOrderDir]);
|
|
607
|
-
const applyOrder = useCallback((rows) => {
|
|
608
|
-
const opt = effectiveOrderBys.find((o) => o.value === orderBy);
|
|
609
|
-
if (!opt) return rows;
|
|
610
|
-
const sign = orderDir === "asc" ? 1 : -1;
|
|
611
|
-
return [...rows].sort((a, b) => opt.compare(a, b) * sign);
|
|
612
|
-
}, [
|
|
613
|
-
effectiveOrderBys,
|
|
614
|
-
orderBy,
|
|
615
|
-
orderDir
|
|
616
|
-
]);
|
|
617
|
-
const sameKeys = (a, b) => a.length === b.length && a.every((k) => b.includes(k));
|
|
618
|
-
const isDisplayDefault = groupBy === defaultGroupByValue && orderBy === defaultOrderByValue && orderDir === "asc" && showColumnHeaders === defaultShowColumnHeaders && showActions === defaultShowActions && alwaysShowActions === false && sameKeys(hiddenKeys, defaultHiddenKeys) && sameKeys(pinnedKeys, defaultPinnedKeys);
|
|
619
|
-
const resetDisplay = useCallback(() => {
|
|
620
|
-
setGroupBy(defaultGroupByValue);
|
|
621
|
-
setOrderBy(defaultOrderByValue);
|
|
622
|
-
setOrderDir("asc");
|
|
623
|
-
setShowColumnHeaders(defaultShowColumnHeaders);
|
|
624
|
-
setShowActions(defaultShowActions);
|
|
625
|
-
setAlwaysShowActions(false);
|
|
626
|
-
setHiddenKeys(defaultHiddenKeys);
|
|
627
|
-
setPinnedKeys(defaultPinnedKeys);
|
|
628
|
-
}, [
|
|
629
|
-
setGroupBy,
|
|
630
|
-
setOrderBy,
|
|
631
|
-
setOrderDir,
|
|
632
|
-
defaultOrderByValue,
|
|
633
|
-
setShowColumnHeaders,
|
|
634
|
-
setShowActions,
|
|
635
|
-
setAlwaysShowActions,
|
|
636
|
-
setHiddenKeys,
|
|
637
|
-
setPinnedKeys,
|
|
638
|
-
defaultGroupByValue,
|
|
639
|
-
defaultHiddenKeys,
|
|
640
|
-
defaultPinnedKeys,
|
|
641
|
-
defaultShowColumnHeaders,
|
|
642
|
-
defaultShowActions
|
|
643
|
-
]);
|
|
644
|
-
return {
|
|
645
|
-
columns,
|
|
646
|
-
visibleColumns,
|
|
647
|
-
columnClasses,
|
|
648
|
-
isVisible,
|
|
649
|
-
pinnedCount,
|
|
650
|
-
actionsWidth,
|
|
651
|
-
toggleColumn,
|
|
652
|
-
groupBys,
|
|
653
|
-
groupBy,
|
|
654
|
-
setGroupBy,
|
|
655
|
-
orderBys: effectiveOrderBys,
|
|
656
|
-
orderBy,
|
|
657
|
-
setOrderBy,
|
|
658
|
-
orderDir,
|
|
659
|
-
toggleOrderDir,
|
|
660
|
-
applyOrder,
|
|
661
|
-
facets,
|
|
662
|
-
filters,
|
|
663
|
-
setFacetValues,
|
|
664
|
-
clearFilters,
|
|
665
|
-
activeFilterCount: useMemo(() => Object.values(filters).filter((v) => v && v.length > 0).length, [filters]),
|
|
666
|
-
applyFilters: useCallback((rows) => rows.filter((row) => facets.every((f) => {
|
|
667
|
-
const selected = filters[f.key];
|
|
668
|
-
return !selected || selected.length === 0 ? true : f.matches(row, selected);
|
|
669
|
-
})), [facets, filters]),
|
|
670
|
-
actions,
|
|
671
|
-
isPinned,
|
|
672
|
-
togglePinned,
|
|
673
|
-
showColumnHeaders,
|
|
674
|
-
toggleColumnHeaders,
|
|
675
|
-
showActions: effectiveShowActions,
|
|
676
|
-
toggleShowActions,
|
|
677
|
-
alwaysShowActions,
|
|
678
|
-
toggleAlwaysShowActions,
|
|
679
|
-
isDisplayDefault,
|
|
680
|
-
resetDisplay
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
//#endregion
|
|
684
|
-
//#region src/list/textEntry.ts
|
|
685
|
-
/** Guards list-page shortcuts from firing inside inputs, terminals, editors, and dialogs. */
|
|
686
|
-
function isTextEntryContext(target) {
|
|
687
|
-
const el = target;
|
|
688
|
-
if (!el) return false;
|
|
689
|
-
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable) return true;
|
|
690
|
-
return Boolean(el.closest?.(".xterm, .monaco-editor, .cm-editor, [role=\"dialog\"]"));
|
|
691
|
-
}
|
|
692
|
-
//#endregion
|
|
693
|
-
//#region src/list/ListViewControls.tsx
|
|
694
|
-
/** Shared chrome for the toolbar control buttons (Filter, Display, Search) so
|
|
695
|
-
* they read as a consistent button cluster — matched by ListSearchControl. */
|
|
696
|
-
var listControlButtonClasses = "relative flex h-7 w-7 items-center justify-center rounded-md border border-(--theme-border) text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app) transition-colors";
|
|
697
|
-
var FLYOUT = "min-w-44 rounded-lg border border-(--theme-border) bg-(--theme-app-bg) py-1 shadow-lg";
|
|
698
|
-
/** Toggle pill shared by the Display menu's column + pinned-action pickers. */
|
|
699
|
-
function pillClass(on) {
|
|
700
|
-
return cx("whitespace-nowrap rounded-full border px-2.5 py-1 text-[12px] transition-colors", on ? "border-transparent bg-(--theme-muted-panel-bg) text-(--theme-app)" : "border-(--theme-border) text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app)");
|
|
701
|
-
}
|
|
702
|
-
var SECTION_LABEL = "mb-2 text-[11px] font-medium uppercase tracking-wide text-(--theme-muted-text-color)";
|
|
703
|
-
/** Portals into .ds-root so the panel escapes the toolbar's overflow clipping. */
|
|
704
|
-
function AnchoredPopover({ icon, label, active, shortcut, panelClassName, children }) {
|
|
705
|
-
const btnRef = useRef(null);
|
|
706
|
-
const panelRef = useRef(null);
|
|
707
|
-
const [pos, setPos] = useState(null);
|
|
708
|
-
const close = useCallback(() => setPos(null), []);
|
|
709
|
-
const open = useCallback(() => {
|
|
710
|
-
const r = btnRef.current?.getBoundingClientRect();
|
|
711
|
-
if (r) setPos({
|
|
712
|
-
right: Math.max(8, Math.round(window.innerWidth - r.right)),
|
|
713
|
-
top: Math.round(r.bottom) + 4
|
|
714
|
-
});
|
|
715
|
-
}, []);
|
|
716
|
-
useEffect(() => {
|
|
717
|
-
if (!pos) return;
|
|
718
|
-
const onKey = (e) => {
|
|
719
|
-
if (e.key === "Escape") close();
|
|
720
|
-
};
|
|
721
|
-
const onScroll = (e) => {
|
|
722
|
-
if (e.target instanceof Node && panelRef.current?.contains(e.target)) return;
|
|
723
|
-
close();
|
|
584
|
+
const onScroll = (e) => {
|
|
585
|
+
if (e.target instanceof Node && panelRef.current?.contains(e.target)) return;
|
|
586
|
+
close();
|
|
724
587
|
};
|
|
725
588
|
window.addEventListener("keydown", onKey);
|
|
726
589
|
window.addEventListener("scroll", onScroll, true);
|
|
@@ -915,14 +778,16 @@ function useCloseOnOutsideClick(open, close) {
|
|
|
915
778
|
function GroupingDropdown({ view }) {
|
|
916
779
|
const t = useStrings().list;
|
|
917
780
|
const [open, setOpen] = useState(false);
|
|
781
|
+
const ref = useCloseOnOutsideClick(open, useCallback(() => setOpen(false), []));
|
|
782
|
+
const current = view.groupBys.find((g) => g.value === view.groupBy);
|
|
918
783
|
return /* @__PURE__ */ jsxs("div", {
|
|
919
|
-
ref
|
|
784
|
+
ref,
|
|
920
785
|
className: "relative",
|
|
921
786
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
922
787
|
type: "button",
|
|
923
788
|
onClick: () => setOpen((o) => !o),
|
|
924
789
|
className: "flex items-center gap-1.5 rounded-md border border-(--theme-border) px-2 py-1 text-[12px] text-(--theme-app) hover:bg-(--theme-muted-panel-bg)",
|
|
925
|
-
children: [
|
|
790
|
+
children: [current?.label ?? t.none, /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-2.5 w-2.5 opacity-60" })]
|
|
926
791
|
}), open && /* @__PURE__ */ jsx("div", {
|
|
927
792
|
className: cx("absolute right-0 top-full z-20 mt-1", FLYOUT),
|
|
928
793
|
children: view.groupBys.map((g) => /* @__PURE__ */ jsxs("button", {
|
|
@@ -940,14 +805,16 @@ function GroupingDropdown({ view }) {
|
|
|
940
805
|
function OrderingDropdown({ view }) {
|
|
941
806
|
const t = useStrings().list;
|
|
942
807
|
const [open, setOpen] = useState(false);
|
|
808
|
+
const ref = useCloseOnOutsideClick(open, useCallback(() => setOpen(false), []));
|
|
809
|
+
const current = view.orderBys.find((o) => o.value === view.orderBy);
|
|
943
810
|
return /* @__PURE__ */ jsxs("div", {
|
|
944
|
-
ref
|
|
811
|
+
ref,
|
|
945
812
|
className: "relative",
|
|
946
813
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
947
814
|
type: "button",
|
|
948
815
|
onClick: () => setOpen((o) => !o),
|
|
949
816
|
className: "flex items-center gap-1.5 rounded-md border border-(--theme-border) px-2 py-1 text-[12px] text-(--theme-app) hover:bg-(--theme-muted-panel-bg)",
|
|
950
|
-
children: [
|
|
817
|
+
children: [current?.label ?? t.none, /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-2.5 w-2.5 opacity-60" })]
|
|
951
818
|
}), open && /* @__PURE__ */ jsx("div", {
|
|
952
819
|
className: cx("absolute right-0 top-full z-20 mt-1", FLYOUT),
|
|
953
820
|
children: view.orderBys.map((o) => /* @__PURE__ */ jsxs("button", {
|
|
@@ -1049,6 +916,59 @@ function FilterFacetRow({ view, facet, open, onEnter, onLeave }) {
|
|
|
1049
916
|
});
|
|
1050
917
|
}
|
|
1051
918
|
//#endregion
|
|
919
|
+
//#region src/list/ListPager.tsx
|
|
920
|
+
/** Page sizes offered by the pager's per-page select; first entry is the default. */
|
|
921
|
+
var LIST_PAGE_SIZES = [
|
|
922
|
+
50,
|
|
923
|
+
100,
|
|
924
|
+
200
|
|
925
|
+
];
|
|
926
|
+
/** Footer pager bar for paginated new-nav lists: "{start}–{end} of {total}" with prev/next. Renders nothing for a single page. */
|
|
927
|
+
function ListPager({ page, pageSize, total, onPageChange, pageSizes = LIST_PAGE_SIZES, onPageSizeChange, hasNext }) {
|
|
928
|
+
const t = useStrings().list;
|
|
929
|
+
const pageCount = Math.max(1, Math.ceil(total / pageSize));
|
|
930
|
+
const start = page * pageSize + 1;
|
|
931
|
+
const end = Math.min(total, (page + 1) * pageSize);
|
|
932
|
+
const smallest = Math.min(...pageSizes);
|
|
933
|
+
const showSizeSelect = !!onPageSizeChange && (total > smallest || pageSize > smallest);
|
|
934
|
+
if (pageCount <= 1 && !showSizeSelect) return null;
|
|
935
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
936
|
+
className: "flex items-center justify-between px-2.5 h-10 shrink-0 border-t theme-border",
|
|
937
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
938
|
+
className: "flex items-center gap-3 text-xs text-(--theme-muted-text-color)",
|
|
939
|
+
children: [/* @__PURE__ */ jsx("span", { children: t.pager(start, end, total) }), showSizeSelect && /* @__PURE__ */ jsxs("label", {
|
|
940
|
+
className: "flex items-center gap-1",
|
|
941
|
+
children: [t.perPage, /* @__PURE__ */ jsx("select", {
|
|
942
|
+
value: pageSize,
|
|
943
|
+
onChange: (e) => onPageSizeChange(Number(e.target.value)),
|
|
944
|
+
className: "theme-input rounded px-1.5 py-0.5 text-xs",
|
|
945
|
+
children: pageSizes.map((size) => /* @__PURE__ */ jsx("option", {
|
|
946
|
+
value: size,
|
|
947
|
+
children: size
|
|
948
|
+
}, size))
|
|
949
|
+
})]
|
|
950
|
+
})]
|
|
951
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
952
|
+
className: "flex items-center gap-1",
|
|
953
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
954
|
+
type: "button",
|
|
955
|
+
"aria-label": t.paginationPrevious,
|
|
956
|
+
disabled: page === 0,
|
|
957
|
+
onClick: () => onPageChange(page - 1),
|
|
958
|
+
className: cx(listControlButtonClasses, "disabled:opacity-40 disabled:pointer-events-none"),
|
|
959
|
+
children: /* @__PURE__ */ jsx(ChevronLeftIcon, { className: "w-3.5 h-3.5" })
|
|
960
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
961
|
+
type: "button",
|
|
962
|
+
"aria-label": t.paginationNext,
|
|
963
|
+
disabled: hasNext === void 0 ? page >= pageCount - 1 : !hasNext,
|
|
964
|
+
onClick: () => onPageChange(page + 1),
|
|
965
|
+
className: cx(listControlButtonClasses, "disabled:opacity-40 disabled:pointer-events-none"),
|
|
966
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "w-3.5 h-3.5" })
|
|
967
|
+
})]
|
|
968
|
+
})]
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
//#endregion
|
|
1052
972
|
//#region src/list/listSearch.tsx
|
|
1053
973
|
var NO_TERMS = [];
|
|
1054
974
|
/** Pass `enabled: false` to suspend the global ⌘F/`/` hijack (e.g. when search isn't shown and browser Find should stay active). */
|
|
@@ -1178,123 +1098,210 @@ function ListCount({ total, matches, filterActive, noun, nounPlural }) {
|
|
|
1178
1098
|
});
|
|
1179
1099
|
}
|
|
1180
1100
|
//#endregion
|
|
1181
|
-
//#region src/list/
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
];
|
|
1188
|
-
/** Footer pager bar for paginated new-nav lists: "{start}–{end} of {total}" with prev/next. Renders nothing for a single page. */
|
|
1189
|
-
function ListPager({ page, pageSize, total, onPageChange, pageSizes = LIST_PAGE_SIZES, onPageSizeChange, hasNext }) {
|
|
1190
|
-
const t = useStrings().list;
|
|
1191
|
-
const pageCount = Math.max(1, Math.ceil(total / pageSize));
|
|
1192
|
-
const start = page * pageSize + 1;
|
|
1193
|
-
const end = Math.min(total, (page + 1) * pageSize);
|
|
1194
|
-
const smallest = Math.min(...pageSizes);
|
|
1195
|
-
const showSizeSelect = !!onPageSizeChange && (total > smallest || pageSize > smallest);
|
|
1196
|
-
if (pageCount <= 1 && !showSizeSelect) return null;
|
|
1197
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1198
|
-
className: "flex items-center justify-between px-2.5 h-10 shrink-0 border-t theme-border",
|
|
1199
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
1200
|
-
className: "flex items-center gap-3 text-xs text-(--theme-muted-text-color)",
|
|
1201
|
-
children: [/* @__PURE__ */ jsx("span", { children: t.pager(start, end, total) }), showSizeSelect && /* @__PURE__ */ jsxs("label", {
|
|
1202
|
-
className: "flex items-center gap-1",
|
|
1203
|
-
children: [t.perPage, /* @__PURE__ */ jsx("select", {
|
|
1204
|
-
value: pageSize,
|
|
1205
|
-
onChange: (e) => onPageSizeChange(Number(e.target.value)),
|
|
1206
|
-
className: "theme-input rounded px-1.5 py-0.5 text-xs",
|
|
1207
|
-
children: pageSizes.map((size) => /* @__PURE__ */ jsx("option", {
|
|
1208
|
-
value: size,
|
|
1209
|
-
children: size
|
|
1210
|
-
}, size))
|
|
1211
|
-
})]
|
|
1212
|
-
})]
|
|
1213
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
1214
|
-
className: "flex items-center gap-1",
|
|
1215
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
1216
|
-
type: "button",
|
|
1217
|
-
"aria-label": t.paginationPrevious,
|
|
1218
|
-
disabled: page === 0,
|
|
1219
|
-
onClick: () => onPageChange(page - 1),
|
|
1220
|
-
className: cx(listControlButtonClasses, "disabled:opacity-40 disabled:pointer-events-none"),
|
|
1221
|
-
children: /* @__PURE__ */ jsx(ChevronLeftIcon, { className: "w-3.5 h-3.5" })
|
|
1222
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
1223
|
-
type: "button",
|
|
1224
|
-
"aria-label": t.paginationNext,
|
|
1225
|
-
disabled: hasNext === void 0 ? page >= pageCount - 1 : !hasNext,
|
|
1226
|
-
onClick: () => onPageChange(page + 1),
|
|
1227
|
-
className: cx(listControlButtonClasses, "disabled:opacity-40 disabled:pointer-events-none"),
|
|
1228
|
-
children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "w-3.5 h-3.5" })
|
|
1229
|
-
})]
|
|
1230
|
-
})]
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
//#endregion
|
|
1234
|
-
//#region src/list/HoverCard.tsx
|
|
1235
|
-
function useHoverCard() {
|
|
1236
|
-
const triggerRef = useRef(null);
|
|
1237
|
-
const [coords, setCoords] = useState(null);
|
|
1238
|
-
const openTimer = useRef(void 0);
|
|
1239
|
-
const closeTimer = useRef(void 0);
|
|
1240
|
-
useEffect(() => () => {
|
|
1241
|
-
clearTimeout(openTimer.current);
|
|
1242
|
-
clearTimeout(closeTimer.current);
|
|
1243
|
-
}, []);
|
|
1244
|
-
const scheduleOpen = () => {
|
|
1245
|
-
clearTimeout(closeTimer.current);
|
|
1246
|
-
openTimer.current = setTimeout(() => {
|
|
1247
|
-
const rect = triggerRef.current?.getBoundingClientRect();
|
|
1248
|
-
if (rect) setCoords({
|
|
1249
|
-
x: rect.left,
|
|
1250
|
-
y: rect.bottom
|
|
1251
|
-
});
|
|
1252
|
-
}, 350);
|
|
1253
|
-
};
|
|
1254
|
-
const scheduleClose = () => {
|
|
1255
|
-
clearTimeout(openTimer.current);
|
|
1256
|
-
closeTimer.current = setTimeout(() => setCoords(null), 150);
|
|
1257
|
-
};
|
|
1258
|
-
const keepOpen = () => clearTimeout(closeTimer.current);
|
|
1259
|
-
return {
|
|
1260
|
-
triggerRef,
|
|
1261
|
-
coords,
|
|
1262
|
-
scheduleOpen,
|
|
1263
|
-
scheduleClose,
|
|
1264
|
-
keepOpen
|
|
1265
|
-
};
|
|
1101
|
+
//#region src/list/listView.tsx
|
|
1102
|
+
var PRIORITY_SHOW_CLASS = {
|
|
1103
|
+
low: "hidden @[52rem]:table-cell",
|
|
1104
|
+
medium: "hidden @[36rem]:table-cell"
|
|
1105
|
+
};
|
|
1106
|
+
function columnResponsiveClass(col) {
|
|
1107
|
+
return col.priority ? PRIORITY_SHOW_CLASS[col.priority] : "";
|
|
1266
1108
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1109
|
+
var DEFAULT_ORDER = "__default";
|
|
1110
|
+
var FAVORITE_ORDER = "__favorite";
|
|
1111
|
+
/** Persisted grouping + column-visibility + field-filter state for a list page,
|
|
1112
|
+
* driving the shared Display/Filter menus. */
|
|
1113
|
+
function useListView({ storageKey, sharedFiltersKey, columns, groupBys = [], defaultGroupBy, orderBys = [], defaultOrderBy, facets = [], actions = [], actionCount, defaultShowColumnHeaders = false, defaultShowActions = true, isFavorite, isOn, createdAt }) {
|
|
1114
|
+
const t = useStrings().list;
|
|
1115
|
+
const tiebreak = orderBys[0]?.compare;
|
|
1116
|
+
const effectiveOrderBys = useMemo(() => {
|
|
1117
|
+
if (!isFavorite) return orderBys;
|
|
1118
|
+
const favoriteRank = (row) => isFavorite(row) ? 0 : 1;
|
|
1119
|
+
const onRank = (row) => isOn?.(row) ? 0 : 1;
|
|
1120
|
+
const createdMs = (row) => {
|
|
1121
|
+
const v = createdAt?.(row);
|
|
1122
|
+
return v === null || v === void 0 || Number.isNaN(v) ? 0 : v;
|
|
1123
|
+
};
|
|
1124
|
+
const newestFirst = (a, b) => createdMs(b) - createdMs(a);
|
|
1125
|
+
return [...[{
|
|
1126
|
+
value: DEFAULT_ORDER,
|
|
1127
|
+
label: t.orderDefault,
|
|
1128
|
+
compare: (a, b) => onRank(a) - onRank(b) || favoriteRank(a) - favoriteRank(b) || newestFirst(a, b) || (tiebreak?.(a, b) ?? 0)
|
|
1129
|
+
}, {
|
|
1130
|
+
value: FAVORITE_ORDER,
|
|
1131
|
+
label: t.orderFavorites,
|
|
1132
|
+
compare: (a, b) => favoriteRank(a) - favoriteRank(b) || (tiebreak?.(a, b) ?? 0)
|
|
1133
|
+
}], ...orderBys];
|
|
1134
|
+
}, [
|
|
1135
|
+
orderBys,
|
|
1136
|
+
isFavorite,
|
|
1137
|
+
isOn,
|
|
1138
|
+
createdAt,
|
|
1139
|
+
tiebreak,
|
|
1140
|
+
t
|
|
1141
|
+
]);
|
|
1142
|
+
const defaultGroupByValue = defaultGroupBy ?? groupBys[0]?.value ?? "";
|
|
1143
|
+
const defaultOrderByValue = isFavorite ? DEFAULT_ORDER : defaultOrderBy ?? orderBys[0]?.value ?? "";
|
|
1144
|
+
const defaultHiddenKeys = useMemo(() => columns.filter((c) => c.defaultHidden && !c.alwaysVisible).map((c) => c.key), [columns]);
|
|
1145
|
+
const defaultPinnedKeys = useMemo(() => actions.filter((a) => a.defaultPinned).map((a) => a.key), [actions]);
|
|
1146
|
+
const [hiddenKeys, setHiddenKeys] = usePersistedState(`${storageKey}:hiddenColumns`, defaultHiddenKeys);
|
|
1147
|
+
const [pinnedKeys, setPinnedKeys] = usePersistedState(`${storageKey}:pinnedActions`, defaultPinnedKeys);
|
|
1148
|
+
const [groupBy, setGroupBy] = usePersistedState(`${storageKey}:groupBy`, defaultGroupByValue);
|
|
1149
|
+
const [showColumnHeaders, setShowColumnHeaders] = usePersistedState(`${storageKey}:showColumnHeaders`, defaultShowColumnHeaders);
|
|
1150
|
+
const [showActions, setShowActions] = usePersistedState(`${storageKey}:showActions`, defaultShowActions);
|
|
1151
|
+
const [alwaysShowActions, setAlwaysShowActions] = usePersistedState(`${storageKey}:alwaysShowActions`, false);
|
|
1152
|
+
const [orderBy, setOrderBy] = usePersistedState(`${storageKey}:orderBy`, defaultOrderByValue);
|
|
1153
|
+
const [orderDir, setOrderDir] = usePersistedState(`${storageKey}:orderDir`, "asc");
|
|
1154
|
+
const [localFilters, setLocalFilters] = usePersistedState(`${storageKey}:filters`, {});
|
|
1155
|
+
const [sharedFilters, setSharedFilters] = usePersistedState(`${sharedFiltersKey ?? storageKey}:sharedFilters`, {});
|
|
1156
|
+
const sharedKeys = useMemo(() => new Set(facets.filter((f) => f.shared).map((f) => f.key)), [facets]);
|
|
1157
|
+
const filters = useMemo(() => {
|
|
1158
|
+
if (sharedKeys.size === 0) return localFilters;
|
|
1159
|
+
const merged = {};
|
|
1160
|
+
for (const [key, values] of Object.entries(localFilters)) if (!sharedKeys.has(key)) merged[key] = values;
|
|
1161
|
+
for (const key of sharedKeys) {
|
|
1162
|
+
const values = sharedFilters[key];
|
|
1163
|
+
if (values?.length) merged[key] = values;
|
|
1164
|
+
}
|
|
1165
|
+
return merged;
|
|
1166
|
+
}, [
|
|
1167
|
+
localFilters,
|
|
1168
|
+
sharedFilters,
|
|
1169
|
+
sharedKeys
|
|
1170
|
+
]);
|
|
1171
|
+
const pinnedCount = actionCount ?? pinnedKeys.filter((key) => actions.some((action) => action.key === key)).length;
|
|
1172
|
+
const effectiveShowActions = showActions || alwaysShowActions;
|
|
1173
|
+
const actionsWidth = effectiveShowActions ? actionsColumnWidth(pinnedCount) : 0;
|
|
1174
|
+
const isVisible = useCallback((key) => {
|
|
1175
|
+
const col = columns.find((c) => c.key === key);
|
|
1176
|
+
return Boolean(col?.alwaysVisible) || !hiddenKeys.includes(key);
|
|
1177
|
+
}, [columns, hiddenKeys]);
|
|
1178
|
+
const visibleColumns = useMemo(() => columns.filter((c) => !c.inline && (c.alwaysVisible || !hiddenKeys.includes(c.key))), [columns, hiddenKeys]);
|
|
1179
|
+
const columnClasses = useMemo(() => visibleColumns.map(columnResponsiveClass), [visibleColumns]);
|
|
1180
|
+
const toggleColumn = useCallback((key) => setHiddenKeys((prev) => prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]), [setHiddenKeys]);
|
|
1181
|
+
const setFacetValues = useCallback((key, values) => {
|
|
1182
|
+
const update = (prev) => {
|
|
1183
|
+
const next = { ...prev };
|
|
1184
|
+
if (values.length) next[key] = values;
|
|
1185
|
+
else delete next[key];
|
|
1186
|
+
return next;
|
|
1187
|
+
};
|
|
1188
|
+
if (sharedKeys.has(key)) setSharedFilters(update);
|
|
1189
|
+
else setLocalFilters(update);
|
|
1190
|
+
}, [
|
|
1191
|
+
setLocalFilters,
|
|
1192
|
+
setSharedFilters,
|
|
1193
|
+
sharedKeys
|
|
1194
|
+
]);
|
|
1195
|
+
const clearFilters = useCallback(() => {
|
|
1196
|
+
setLocalFilters({});
|
|
1197
|
+
if (sharedKeys.size > 0) setSharedFilters((prev) => {
|
|
1198
|
+
const next = { ...prev };
|
|
1199
|
+
for (const key of sharedKeys) delete next[key];
|
|
1200
|
+
return next;
|
|
1277
1201
|
});
|
|
1278
1202
|
}, [
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1203
|
+
setLocalFilters,
|
|
1204
|
+
setSharedFilters,
|
|
1205
|
+
sharedKeys
|
|
1282
1206
|
]);
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1207
|
+
const isPinned = useCallback((key) => pinnedKeys.includes(key), [pinnedKeys]);
|
|
1208
|
+
const togglePinned = useCallback((key) => setPinnedKeys((prev) => prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]), [setPinnedKeys]);
|
|
1209
|
+
const toggleColumnHeaders = useCallback(() => setShowColumnHeaders((prev) => !prev), [setShowColumnHeaders]);
|
|
1210
|
+
const toggleShowActions = useCallback(() => {
|
|
1211
|
+
if (effectiveShowActions) {
|
|
1212
|
+
setShowActions(false);
|
|
1213
|
+
setAlwaysShowActions(false);
|
|
1214
|
+
} else setShowActions(true);
|
|
1215
|
+
}, [
|
|
1216
|
+
effectiveShowActions,
|
|
1217
|
+
setShowActions,
|
|
1218
|
+
setAlwaysShowActions
|
|
1219
|
+
]);
|
|
1220
|
+
const toggleAlwaysShowActions = useCallback(() => {
|
|
1221
|
+
const next = !alwaysShowActions;
|
|
1222
|
+
setAlwaysShowActions(next);
|
|
1223
|
+
if (next) setShowActions(true);
|
|
1224
|
+
}, [
|
|
1225
|
+
alwaysShowActions,
|
|
1226
|
+
setAlwaysShowActions,
|
|
1227
|
+
setShowActions
|
|
1228
|
+
]);
|
|
1229
|
+
const toggleOrderDir = useCallback(() => setOrderDir((d) => d === "asc" ? "desc" : "asc"), [setOrderDir]);
|
|
1230
|
+
const applyOrder = useCallback((rows) => {
|
|
1231
|
+
const opt = effectiveOrderBys.find((o) => o.value === orderBy);
|
|
1232
|
+
if (!opt) return rows;
|
|
1233
|
+
const sign = orderDir === "asc" ? 1 : -1;
|
|
1234
|
+
return [...rows].sort((a, b) => opt.compare(a, b) * sign);
|
|
1235
|
+
}, [
|
|
1236
|
+
effectiveOrderBys,
|
|
1237
|
+
orderBy,
|
|
1238
|
+
orderDir
|
|
1239
|
+
]);
|
|
1240
|
+
const sameKeys = (a, b) => a.length === b.length && a.every((k) => b.includes(k));
|
|
1241
|
+
const isDisplayDefault = groupBy === defaultGroupByValue && orderBy === defaultOrderByValue && orderDir === "asc" && showColumnHeaders === defaultShowColumnHeaders && showActions === defaultShowActions && alwaysShowActions === false && sameKeys(hiddenKeys, defaultHiddenKeys) && sameKeys(pinnedKeys, defaultPinnedKeys);
|
|
1242
|
+
const resetDisplay = useCallback(() => {
|
|
1243
|
+
setGroupBy(defaultGroupByValue);
|
|
1244
|
+
setOrderBy(defaultOrderByValue);
|
|
1245
|
+
setOrderDir("asc");
|
|
1246
|
+
setShowColumnHeaders(defaultShowColumnHeaders);
|
|
1247
|
+
setShowActions(defaultShowActions);
|
|
1248
|
+
setAlwaysShowActions(false);
|
|
1249
|
+
setHiddenKeys(defaultHiddenKeys);
|
|
1250
|
+
setPinnedKeys(defaultPinnedKeys);
|
|
1251
|
+
}, [
|
|
1252
|
+
setGroupBy,
|
|
1253
|
+
setOrderBy,
|
|
1254
|
+
setOrderDir,
|
|
1255
|
+
defaultOrderByValue,
|
|
1256
|
+
setShowColumnHeaders,
|
|
1257
|
+
setShowActions,
|
|
1258
|
+
setAlwaysShowActions,
|
|
1259
|
+
setHiddenKeys,
|
|
1260
|
+
setPinnedKeys,
|
|
1261
|
+
defaultGroupByValue,
|
|
1262
|
+
defaultHiddenKeys,
|
|
1263
|
+
defaultPinnedKeys,
|
|
1264
|
+
defaultShowColumnHeaders,
|
|
1265
|
+
defaultShowActions
|
|
1266
|
+
]);
|
|
1267
|
+
return {
|
|
1268
|
+
columns,
|
|
1269
|
+
visibleColumns,
|
|
1270
|
+
columnClasses,
|
|
1271
|
+
isVisible,
|
|
1272
|
+
pinnedCount,
|
|
1273
|
+
actionsWidth,
|
|
1274
|
+
toggleColumn,
|
|
1275
|
+
groupBys,
|
|
1276
|
+
groupBy,
|
|
1277
|
+
setGroupBy,
|
|
1278
|
+
orderBys: effectiveOrderBys,
|
|
1279
|
+
orderBy,
|
|
1280
|
+
setOrderBy,
|
|
1281
|
+
orderDir,
|
|
1282
|
+
toggleOrderDir,
|
|
1283
|
+
applyOrder,
|
|
1284
|
+
facets,
|
|
1285
|
+
filters,
|
|
1286
|
+
setFacetValues,
|
|
1287
|
+
clearFilters,
|
|
1288
|
+
activeFilterCount: useMemo(() => Object.values(filters).filter((v) => v && v.length > 0).length, [filters]),
|
|
1289
|
+
applyFilters: useCallback((rows) => rows.filter((row) => facets.every((f) => {
|
|
1290
|
+
const selected = filters[f.key];
|
|
1291
|
+
return !selected || selected.length === 0 ? true : f.matches(row, selected);
|
|
1292
|
+
})), [facets, filters]),
|
|
1293
|
+
actions,
|
|
1294
|
+
isPinned,
|
|
1295
|
+
togglePinned,
|
|
1296
|
+
showColumnHeaders,
|
|
1297
|
+
toggleColumnHeaders,
|
|
1298
|
+
showActions: effectiveShowActions,
|
|
1299
|
+
toggleShowActions,
|
|
1300
|
+
alwaysShowActions,
|
|
1301
|
+
toggleAlwaysShowActions,
|
|
1302
|
+
isDisplayDefault,
|
|
1303
|
+
resetDisplay
|
|
1304
|
+
};
|
|
1298
1305
|
}
|
|
1299
1306
|
//#endregion
|
|
1300
1307
|
//#region src/list/UserHoverCard.tsx
|
|
@@ -1408,4 +1415,4 @@ function HoverCardRow({ icon, children, title, align = "center", truncate = fals
|
|
|
1408
1415
|
});
|
|
1409
1416
|
}
|
|
1410
1417
|
//#endregion
|
|
1411
|
-
export {
|
|
1418
|
+
export { listTableProps as A, ListError as C, RowSelectCheckbox as D, NameCell as E, stickyTabsClasses as F, stickyTabsUnderHeaderClasses as I, stickyToolbarClasses as L, useHoverCard as M, ActionToolbar as N, actionsColumnWidth as O, ToolbarButton as P, ListActionsHeader as S, NAME_MIN_WIDTH_PX as T, ListPage as _, FAVORITE_ORDER as a, useListNavigate as b, ListSearchControl as c, ListPager as d, ListDisplayMenu as f, ListColumns as g, isTextEntryContext as h, DEFAULT_ORDER as i, HoverCardSurface as j, listTableFixedProps as k, useListSearch as l, listControlButtonClasses as m, HoverCardTrigger as n, useListView as o, ListFilterMenu as p, UserHoverCard as r, ListCount as s, HoverCardRow as t, LIST_PAGE_SIZES as u, ListRow as v, ListSkeleton as w, GroupRow as x, ListRowActionsProvider as y };
|