@parallelworks/ui 0.19.0 → 0.20.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 +1 -1
- package/dist/{chunks/memoryStore-CC91S5LP.js → ai/adapter/memoryStore.js} +2 -2
- package/dist/ai/adapter/mock/index.js +2 -80
- package/dist/ai/adapter/mock/mockAdapter.js +81 -0
- package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
- package/dist/ai/adapter/openai/errors.js +37 -0
- package/dist/ai/adapter/openai/index.js +5 -333
- package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
- package/dist/ai/adapter/openai/responses.js +108 -0
- package/dist/ai/adapter/openai/sse.js +112 -0
- package/dist/{chunks/types-Yy0NrerF.js → ai/adapter/types.js} +1 -1
- package/dist/ai/agent/classifier.js +12 -0
- package/dist/ai/agent/diff.js +223 -0
- package/dist/ai/agent/diffHighlight.js +101 -0
- package/dist/ai/agent/permissions.js +29 -0
- package/dist/ai/agent/toolfmt.js +383 -0
- package/dist/ai/agent/transcript.js +127 -0
- package/dist/ai/components/AllocationSelector.js +56 -0
- package/dist/ai/components/AttachmentManager.js +147 -0
- package/dist/ai/components/AttachmentUpload.js +179 -0
- package/dist/ai/components/BlockedGroupBanner.js +29 -0
- package/dist/ai/components/BranchNavigator.js +57 -0
- package/dist/ai/components/ChatEmptyState.js +171 -0
- package/dist/ai/components/ChatInput.js +265 -0
- package/dist/ai/components/ChatLayout.js +15 -0
- package/dist/ai/components/ChatMessage.js +341 -0
- package/dist/ai/components/ChatMessageList.js +301 -0
- package/dist/ai/components/ChatSidebar.js +345 -0
- package/dist/ai/components/ChatThread.js +198 -0
- package/dist/ai/components/ComposerChrome.js +50 -0
- package/dist/ai/components/ComposerFrame.js +33 -0
- package/dist/ai/components/DragOverlay.js +20 -0
- package/dist/ai/components/ModelSelector.js +343 -0
- package/dist/ai/components/ShareDialog.js +260 -0
- package/dist/ai/components/SlashMenu.js +91 -0
- package/dist/ai/components/agent/ActivityLine.js +151 -0
- package/dist/ai/components/agent/AgentMessageParts.js +721 -0
- package/dist/ai/components/agent/PermissionPicker.js +38 -0
- package/dist/ai/components/attachmentKeys.js +10 -0
- package/dist/ai/core/ChatProvider.js +848 -0
- package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
- package/dist/ai/core/chatReducer.js +223 -0
- package/dist/ai/core/config.js +46 -0
- package/dist/ai/core/events.js +4 -0
- package/dist/ai/core/exportConversation.js +42 -0
- package/dist/ai/core/greeting.js +38 -0
- package/dist/ai/core/parts.js +84 -0
- package/dist/ai/core/useDragDrop.js +36 -0
- package/dist/ai/core/useKeyboardShortcuts.js +77 -0
- package/dist/ai/core/useSSEStream.js +98 -0
- package/dist/ai/index.js +43 -6644
- package/dist/ai/strings.js +175 -0
- package/dist/ai/ui/Avatar.js +35 -0
- package/dist/ai/ui/Dropdown.js +110 -0
- package/dist/ai/ui/Markdown.js +79 -0
- package/dist/ai/ui/Notice.js +77 -0
- package/dist/ai/ui/codeBreaks.js +36 -0
- package/dist/ai/ui/prose.js +13 -0
- package/dist/ai/ui/sidebar.js +148 -0
- package/dist/ai/utils.js +23 -0
- package/dist/assets/editor.worker-DfmPPyOL.js +60 -0
- package/dist/assets/json.worker-Dqgjpq9F.js +92 -0
- package/dist/assets/yaml.worker-DLx0whrM.js +1441 -0
- package/dist/components/AddMenu.js +46 -0
- package/dist/components/Avatar.js +46 -0
- package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
- package/dist/components/Breadcrumbs.js +83 -0
- package/dist/components/Button.js +83 -0
- package/dist/components/Callout.js +23 -0
- package/dist/components/Card.js +31 -0
- package/dist/components/CollapsiblePanel.js +77 -0
- package/dist/{chunks/ConfirmModal-aOR4O1QE.js → components/ConfirmModal.js} +4 -9
- package/dist/components/CopyToClipboard.js +81 -0
- package/dist/{chunks/Markdown-CM-FenNE.js → components/CreateModal.js} +9 -116
- package/dist/components/DescriptionList.js +42 -0
- package/dist/components/Dropdown.js +349 -0
- package/dist/components/EmptyState.js +27 -0
- package/dist/components/Filter.js +32 -0
- package/dist/components/FilterPill.js +13 -0
- package/dist/components/IconButton.js +34 -0
- package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
- package/dist/components/Input.js +88 -0
- package/dist/components/LetterBadge.js +13 -0
- package/dist/components/Listbox.js +123 -0
- package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
- package/dist/components/Markdown.js +15 -0
- package/dist/components/MultiSelect.js +171 -0
- package/dist/components/Overview.js +39 -0
- package/dist/components/PageHeader.js +194 -0
- package/dist/components/Pagination.js +35 -0
- package/dist/{chunks/Provider-CDYurraE.js → components/Provider.js} +13 -5
- package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
- package/dist/components/SectionHeader.js +11 -0
- package/dist/components/SettingModeOption.js +30 -0
- package/dist/components/SettingRow.js +35 -0
- package/dist/components/SettingsCard.js +31 -0
- package/dist/components/SettingsGroup.js +17 -0
- package/dist/components/Sort.js +42 -0
- package/dist/components/StatusBadge.js +63 -0
- package/dist/components/SwitchToggle.js +59 -0
- package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
- package/dist/{chunks/Table-DU2MW8xz.js → components/Table.js} +3 -3
- package/dist/components/Toggle.js +20 -0
- package/dist/{chunks/Tooltip-K5HJr4_p.js → components/Tooltip.js} +2 -27
- package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
- package/dist/{chunks/focus-D_iZJTW1.js → components/focus.js} +1 -1
- package/dist/components/ghostButton.js +7 -0
- package/dist/components/inputClasses.js +4 -0
- package/dist/components/keys.js +27 -0
- package/dist/components/relativeTime.js +32 -0
- package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
- package/dist/{chunks/duration-BOv8Phl8.js → duration.js} +1 -1
- package/dist/editor/Editor.js +13 -0
- package/dist/editor/EditorField.js +53 -0
- package/dist/editor/FormCodePanel.js +173 -0
- package/dist/{chunks/Monaco-DJ8MW-Dq.js → editor/Monaco.js} +5 -26
- package/dist/editor/index.js +6 -1
- package/dist/editor/themes.js +91 -0
- package/dist/editor/workers.d.ts +5 -0
- package/dist/editor/workers.js +35 -0
- package/dist/editor/yaml.d.ts +9 -1
- package/dist/editor/yaml.js +15 -0
- package/dist/editor/yaml.worker.d.ts +1 -0
- package/dist/editor/yamlLanguage.d.ts +6 -0
- package/dist/editor/yamlLanguage.js +312 -0
- package/dist/file-explorer/FileExplorer.js +1405 -0
- package/dist/file-explorer/FileExplorerContext.js +370 -0
- package/dist/{chunks/CodePreviewEditor-YqQBz1YL.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
- package/dist/file-explorer/FilePreview/Inline.js +45 -0
- package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
- package/dist/file-explorer/FilePreview/Viewer.js +526 -0
- package/dist/file-explorer/FilePreview/index.js +266 -0
- package/dist/file-explorer/FilePreview/parse.js +63 -0
- package/dist/file-explorer/FilePreview/previewCache.js +98 -0
- package/dist/file-explorer/FilePreview/previewType.js +151 -0
- package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
- package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
- package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
- package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
- package/dist/file-explorer/FileRow.js +165 -0
- package/dist/file-explorer/FileRowsWindow.js +92 -0
- package/dist/file-explorer/FileTable.js +172 -0
- package/dist/file-explorer/FileTableHeaders.js +49 -0
- package/dist/file-explorer/LoadMoreRow.js +46 -0
- package/dist/file-explorer/TreeView.js +376 -0
- package/dist/file-explorer/helpers.js +537 -0
- package/dist/file-explorer/index.js +7 -5671
- package/dist/file-explorer/lib/batch.js +39 -0
- package/dist/file-explorer/lib/errors.js +9 -0
- package/dist/file-explorer/lib/paging.js +124 -0
- package/dist/file-explorer/lib/utils.js +322 -0
- package/dist/file-explorer/toasts.js +400 -0
- package/dist/file-explorer/treeRows.js +73 -0
- package/dist/file-explorer/useNearEnd.js +27 -0
- package/dist/form/FieldWrapper.js +54 -0
- package/dist/form/Fields/BooleanField.js +51 -0
- package/dist/form/Fields/CheckboxGroupField.js +72 -0
- package/dist/form/Fields/ColorField.js +33 -0
- package/dist/form/Fields/DropdownField.js +49 -0
- package/dist/form/Fields/DurationField.js +130 -0
- package/dist/form/Fields/LabelField.js +19 -0
- package/dist/form/Fields/MultiDropdownField.js +40 -0
- package/dist/form/Fields/NumberField.js +51 -0
- package/dist/form/Fields/ObjectField.js +54 -0
- package/dist/form/Fields/RadioField.js +49 -0
- package/dist/form/Fields/RangeField.js +58 -0
- package/dist/form/Fields/ResourceOptionIcon.js +21 -0
- package/dist/form/Fields/StepField.js +6 -0
- package/dist/form/Fields/StringField.js +37 -0
- package/dist/form/Fields/TextAreaField.js +31 -0
- package/dist/form/Fields/durationValidity.js +11 -0
- package/dist/form/Form.js +643 -0
- package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
- package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
- package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
- package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
- package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
- package/dist/form/Wizard/WizardContainer.js +138 -0
- package/dist/form/Wizard/WizardNavigation.js +92 -0
- package/dist/form/Wizard/WizardStepContent.js +35 -0
- package/dist/form/Wizard/WizardStepIndicator.js +108 -0
- package/dist/form/Wizard/useWizardState.js +118 -0
- package/dist/form/Wizard/utils.js +34 -0
- package/dist/form/fieldContext.js +26 -0
- package/dist/form/fieldRegistry.js +50 -0
- package/dist/form/index.js +17 -2321
- package/dist/{chunks/FieldWrapper-Cszwg-4B.js → form/lib.js} +2 -97
- package/dist/form/useParsedOpts.js +62 -0
- package/dist/form/usePrevious.js +11 -0
- package/dist/form/utils/checkShowIfObject.js +14 -0
- package/dist/form/utils/duration.js +69 -0
- package/dist/form/utils/getParentValue.js +23 -0
- package/dist/form/utils/getPlaceholder.js +9 -0
- package/dist/form/utils/getValueUsingPath.js +23 -0
- package/dist/form/utils/secondaryField.js +22 -0
- package/dist/graph/AnnotationBanner.js +141 -0
- package/dist/graph/Collapse.js +41 -0
- package/dist/graph/DependencyGraph.js +1398 -0
- package/dist/graph/JobSummary.js +104 -0
- package/dist/graph/MatrixGroup.js +107 -0
- package/dist/graph/Reveal.js +57 -0
- package/dist/graph/TreeView.js +711 -0
- package/dist/graph/index.js +1 -2519
- package/dist/graph/types.js +6 -0
- package/dist/icons.d.ts +4 -4
- package/dist/icons.js +5 -5
- package/dist/index.js +46 -599
- package/dist/list/ActionToolbar.js +184 -0
- package/dist/list/HoverCard.js +73 -0
- package/dist/list/ListPage.js +145 -0
- package/dist/list/ListPager.js +59 -0
- package/dist/list/ListTable.js +163 -0
- package/dist/list/ListViewControls.js +372 -0
- package/dist/list/RowContextMenu.js +351 -0
- package/dist/list/UserHoverCard.js +117 -0
- package/dist/list/index.js +11 -2
- package/dist/list/listSearch.js +137 -0
- package/dist/list/listView.js +210 -0
- package/dist/list/textEntry.js +10 -0
- package/dist/{chunks/logviewer-BTKuQWzw.js → logviewer/LogViewer.js} +4 -82
- package/dist/logviewer/index.js +2 -1
- package/dist/logviewer/segments.js +80 -0
- package/dist/safeUrl.d.ts +6 -0
- package/dist/safeUrl.js +22 -0
- package/package.json +7 -9
- package/dist/assets/editor.worker-BmHUIVG4.js +0 -14807
- package/dist/assets/json.worker-D8bJ92nw.js +0 -22207
- package/dist/assets/yaml.worker-C4gyGAko.js +0 -50201
- package/dist/chunks/PageHeader-0kG_iypP.js +0 -692
- package/dist/chunks/SwitchToggle-DShNdcao.js +0 -758
- package/dist/chunks/editor-Dk1rbV75.js +0 -361
- package/dist/chunks/list-CJm875m7.js +0 -1418
- /package/dist/{chunks/MarkdownImpl-CyeTVvSt.js → components/MarkdownImpl.js} +0 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { usePersistedState, useStrings } from "../components/Provider.js";
|
|
2
|
+
import { actionsColumnWidth } from "./ListTable.js";
|
|
3
|
+
import { useCallback, useMemo } from "react";
|
|
4
|
+
//#region src/list/listView.tsx
|
|
5
|
+
var PRIORITY_SHOW_CLASS = {
|
|
6
|
+
low: "hidden @[52rem]:table-cell",
|
|
7
|
+
medium: "hidden @[36rem]:table-cell"
|
|
8
|
+
};
|
|
9
|
+
function columnResponsiveClass(col) {
|
|
10
|
+
return col.priority ? PRIORITY_SHOW_CLASS[col.priority] : "";
|
|
11
|
+
}
|
|
12
|
+
var DEFAULT_ORDER = "__default";
|
|
13
|
+
var FAVORITE_ORDER = "__favorite";
|
|
14
|
+
/** Persisted grouping + column-visibility + field-filter state for a list page,
|
|
15
|
+
* driving the shared Display/Filter menus. */
|
|
16
|
+
function useListView({ storageKey, sharedFiltersKey, columns, groupBys = [], defaultGroupBy, orderBys = [], defaultOrderBy, facets = [], actions = [], actionCount, defaultShowColumnHeaders = false, defaultShowActions = true, isFavorite, isOn, createdAt }) {
|
|
17
|
+
const t = useStrings().list;
|
|
18
|
+
const tiebreak = orderBys[0]?.compare;
|
|
19
|
+
const effectiveOrderBys = useMemo(() => {
|
|
20
|
+
if (!isFavorite) return orderBys;
|
|
21
|
+
const favoriteRank = (row) => isFavorite(row) ? 0 : 1;
|
|
22
|
+
const onRank = (row) => isOn?.(row) ? 0 : 1;
|
|
23
|
+
const createdMs = (row) => {
|
|
24
|
+
const v = createdAt?.(row);
|
|
25
|
+
return v === null || v === void 0 || Number.isNaN(v) ? 0 : v;
|
|
26
|
+
};
|
|
27
|
+
const newestFirst = (a, b) => createdMs(b) - createdMs(a);
|
|
28
|
+
return [...[{
|
|
29
|
+
value: DEFAULT_ORDER,
|
|
30
|
+
label: t.orderDefault,
|
|
31
|
+
compare: (a, b) => onRank(a) - onRank(b) || favoriteRank(a) - favoriteRank(b) || newestFirst(a, b) || (tiebreak?.(a, b) ?? 0)
|
|
32
|
+
}, {
|
|
33
|
+
value: FAVORITE_ORDER,
|
|
34
|
+
label: t.orderFavorites,
|
|
35
|
+
compare: (a, b) => favoriteRank(a) - favoriteRank(b) || (tiebreak?.(a, b) ?? 0)
|
|
36
|
+
}], ...orderBys];
|
|
37
|
+
}, [
|
|
38
|
+
orderBys,
|
|
39
|
+
isFavorite,
|
|
40
|
+
isOn,
|
|
41
|
+
createdAt,
|
|
42
|
+
tiebreak,
|
|
43
|
+
t
|
|
44
|
+
]);
|
|
45
|
+
const defaultGroupByValue = defaultGroupBy ?? groupBys[0]?.value ?? "";
|
|
46
|
+
const defaultOrderByValue = isFavorite ? DEFAULT_ORDER : defaultOrderBy ?? orderBys[0]?.value ?? "";
|
|
47
|
+
const defaultHiddenKeys = useMemo(() => columns.filter((c) => c.defaultHidden && !c.alwaysVisible).map((c) => c.key), [columns]);
|
|
48
|
+
const defaultPinnedKeys = useMemo(() => actions.filter((a) => a.defaultPinned).map((a) => a.key), [actions]);
|
|
49
|
+
const [hiddenKeys, setHiddenKeys] = usePersistedState(`${storageKey}:hiddenColumns`, defaultHiddenKeys);
|
|
50
|
+
const [pinnedKeys, setPinnedKeys] = usePersistedState(`${storageKey}:pinnedActions`, defaultPinnedKeys);
|
|
51
|
+
const [groupBy, setGroupBy] = usePersistedState(`${storageKey}:groupBy`, defaultGroupByValue);
|
|
52
|
+
const [showColumnHeaders, setShowColumnHeaders] = usePersistedState(`${storageKey}:showColumnHeaders`, defaultShowColumnHeaders);
|
|
53
|
+
const [showActions, setShowActions] = usePersistedState(`${storageKey}:showActions`, defaultShowActions);
|
|
54
|
+
const [alwaysShowActions, setAlwaysShowActions] = usePersistedState(`${storageKey}:alwaysShowActions`, false);
|
|
55
|
+
const [orderBy, setOrderBy] = usePersistedState(`${storageKey}:orderBy`, defaultOrderByValue);
|
|
56
|
+
const [orderDir, setOrderDir] = usePersistedState(`${storageKey}:orderDir`, "asc");
|
|
57
|
+
const [localFilters, setLocalFilters] = usePersistedState(`${storageKey}:filters`, {});
|
|
58
|
+
const [sharedFilters, setSharedFilters] = usePersistedState(`${sharedFiltersKey ?? storageKey}:sharedFilters`, {});
|
|
59
|
+
const sharedKeys = useMemo(() => new Set(facets.filter((f) => f.shared).map((f) => f.key)), [facets]);
|
|
60
|
+
const filters = useMemo(() => {
|
|
61
|
+
if (sharedKeys.size === 0) return localFilters;
|
|
62
|
+
const merged = {};
|
|
63
|
+
for (const [key, values] of Object.entries(localFilters)) if (!sharedKeys.has(key)) merged[key] = values;
|
|
64
|
+
for (const key of sharedKeys) {
|
|
65
|
+
const values = sharedFilters[key];
|
|
66
|
+
if (values?.length) merged[key] = values;
|
|
67
|
+
}
|
|
68
|
+
return merged;
|
|
69
|
+
}, [
|
|
70
|
+
localFilters,
|
|
71
|
+
sharedFilters,
|
|
72
|
+
sharedKeys
|
|
73
|
+
]);
|
|
74
|
+
const pinnedCount = actionCount ?? pinnedKeys.filter((key) => actions.some((action) => action.key === key)).length;
|
|
75
|
+
const effectiveShowActions = showActions || alwaysShowActions;
|
|
76
|
+
const actionsWidth = effectiveShowActions ? actionsColumnWidth(pinnedCount) : 0;
|
|
77
|
+
const isVisible = useCallback((key) => {
|
|
78
|
+
const col = columns.find((c) => c.key === key);
|
|
79
|
+
return Boolean(col?.alwaysVisible) || !hiddenKeys.includes(key);
|
|
80
|
+
}, [columns, hiddenKeys]);
|
|
81
|
+
const visibleColumns = useMemo(() => columns.filter((c) => !c.inline && (c.alwaysVisible || !hiddenKeys.includes(c.key))), [columns, hiddenKeys]);
|
|
82
|
+
const columnClasses = useMemo(() => visibleColumns.map(columnResponsiveClass), [visibleColumns]);
|
|
83
|
+
const toggleColumn = useCallback((key) => setHiddenKeys((prev) => prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]), [setHiddenKeys]);
|
|
84
|
+
const setFacetValues = useCallback((key, values) => {
|
|
85
|
+
const update = (prev) => {
|
|
86
|
+
const next = { ...prev };
|
|
87
|
+
if (values.length) next[key] = values;
|
|
88
|
+
else delete next[key];
|
|
89
|
+
return next;
|
|
90
|
+
};
|
|
91
|
+
if (sharedKeys.has(key)) setSharedFilters(update);
|
|
92
|
+
else setLocalFilters(update);
|
|
93
|
+
}, [
|
|
94
|
+
setLocalFilters,
|
|
95
|
+
setSharedFilters,
|
|
96
|
+
sharedKeys
|
|
97
|
+
]);
|
|
98
|
+
const clearFilters = useCallback(() => {
|
|
99
|
+
setLocalFilters({});
|
|
100
|
+
if (sharedKeys.size > 0) setSharedFilters((prev) => {
|
|
101
|
+
const next = { ...prev };
|
|
102
|
+
for (const key of sharedKeys) delete next[key];
|
|
103
|
+
return next;
|
|
104
|
+
});
|
|
105
|
+
}, [
|
|
106
|
+
setLocalFilters,
|
|
107
|
+
setSharedFilters,
|
|
108
|
+
sharedKeys
|
|
109
|
+
]);
|
|
110
|
+
const isPinned = useCallback((key) => pinnedKeys.includes(key), [pinnedKeys]);
|
|
111
|
+
const togglePinned = useCallback((key) => setPinnedKeys((prev) => prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]), [setPinnedKeys]);
|
|
112
|
+
const toggleColumnHeaders = useCallback(() => setShowColumnHeaders((prev) => !prev), [setShowColumnHeaders]);
|
|
113
|
+
const toggleShowActions = useCallback(() => {
|
|
114
|
+
if (effectiveShowActions) {
|
|
115
|
+
setShowActions(false);
|
|
116
|
+
setAlwaysShowActions(false);
|
|
117
|
+
} else setShowActions(true);
|
|
118
|
+
}, [
|
|
119
|
+
effectiveShowActions,
|
|
120
|
+
setShowActions,
|
|
121
|
+
setAlwaysShowActions
|
|
122
|
+
]);
|
|
123
|
+
const toggleAlwaysShowActions = useCallback(() => {
|
|
124
|
+
const next = !alwaysShowActions;
|
|
125
|
+
setAlwaysShowActions(next);
|
|
126
|
+
if (next) setShowActions(true);
|
|
127
|
+
}, [
|
|
128
|
+
alwaysShowActions,
|
|
129
|
+
setAlwaysShowActions,
|
|
130
|
+
setShowActions
|
|
131
|
+
]);
|
|
132
|
+
const toggleOrderDir = useCallback(() => setOrderDir((d) => d === "asc" ? "desc" : "asc"), [setOrderDir]);
|
|
133
|
+
const applyOrder = useCallback((rows) => {
|
|
134
|
+
const opt = effectiveOrderBys.find((o) => o.value === orderBy);
|
|
135
|
+
if (!opt) return rows;
|
|
136
|
+
const sign = orderDir === "asc" ? 1 : -1;
|
|
137
|
+
return [...rows].sort((a, b) => opt.compare(a, b) * sign);
|
|
138
|
+
}, [
|
|
139
|
+
effectiveOrderBys,
|
|
140
|
+
orderBy,
|
|
141
|
+
orderDir
|
|
142
|
+
]);
|
|
143
|
+
const sameKeys = (a, b) => a.length === b.length && a.every((k) => b.includes(k));
|
|
144
|
+
const isDisplayDefault = groupBy === defaultGroupByValue && orderBy === defaultOrderByValue && orderDir === "asc" && showColumnHeaders === defaultShowColumnHeaders && showActions === defaultShowActions && alwaysShowActions === false && sameKeys(hiddenKeys, defaultHiddenKeys) && sameKeys(pinnedKeys, defaultPinnedKeys);
|
|
145
|
+
const resetDisplay = useCallback(() => {
|
|
146
|
+
setGroupBy(defaultGroupByValue);
|
|
147
|
+
setOrderBy(defaultOrderByValue);
|
|
148
|
+
setOrderDir("asc");
|
|
149
|
+
setShowColumnHeaders(defaultShowColumnHeaders);
|
|
150
|
+
setShowActions(defaultShowActions);
|
|
151
|
+
setAlwaysShowActions(false);
|
|
152
|
+
setHiddenKeys(defaultHiddenKeys);
|
|
153
|
+
setPinnedKeys(defaultPinnedKeys);
|
|
154
|
+
}, [
|
|
155
|
+
setGroupBy,
|
|
156
|
+
setOrderBy,
|
|
157
|
+
setOrderDir,
|
|
158
|
+
defaultOrderByValue,
|
|
159
|
+
setShowColumnHeaders,
|
|
160
|
+
setShowActions,
|
|
161
|
+
setAlwaysShowActions,
|
|
162
|
+
setHiddenKeys,
|
|
163
|
+
setPinnedKeys,
|
|
164
|
+
defaultGroupByValue,
|
|
165
|
+
defaultHiddenKeys,
|
|
166
|
+
defaultPinnedKeys,
|
|
167
|
+
defaultShowColumnHeaders,
|
|
168
|
+
defaultShowActions
|
|
169
|
+
]);
|
|
170
|
+
return {
|
|
171
|
+
columns,
|
|
172
|
+
visibleColumns,
|
|
173
|
+
columnClasses,
|
|
174
|
+
isVisible,
|
|
175
|
+
pinnedCount,
|
|
176
|
+
actionsWidth,
|
|
177
|
+
toggleColumn,
|
|
178
|
+
groupBys,
|
|
179
|
+
groupBy,
|
|
180
|
+
setGroupBy,
|
|
181
|
+
orderBys: effectiveOrderBys,
|
|
182
|
+
orderBy,
|
|
183
|
+
setOrderBy,
|
|
184
|
+
orderDir,
|
|
185
|
+
toggleOrderDir,
|
|
186
|
+
applyOrder,
|
|
187
|
+
facets,
|
|
188
|
+
filters,
|
|
189
|
+
setFacetValues,
|
|
190
|
+
clearFilters,
|
|
191
|
+
activeFilterCount: useMemo(() => Object.values(filters).filter((v) => v && v.length > 0).length, [filters]),
|
|
192
|
+
applyFilters: useCallback((rows) => rows.filter((row) => facets.every((f) => {
|
|
193
|
+
const selected = filters[f.key];
|
|
194
|
+
return !selected || selected.length === 0 ? true : f.matches(row, selected);
|
|
195
|
+
})), [facets, filters]),
|
|
196
|
+
actions,
|
|
197
|
+
isPinned,
|
|
198
|
+
togglePinned,
|
|
199
|
+
showColumnHeaders,
|
|
200
|
+
toggleColumnHeaders,
|
|
201
|
+
showActions: effectiveShowActions,
|
|
202
|
+
toggleShowActions,
|
|
203
|
+
alwaysShowActions,
|
|
204
|
+
toggleAlwaysShowActions,
|
|
205
|
+
isDisplayDefault,
|
|
206
|
+
resetDisplay
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
210
|
+
export { DEFAULT_ORDER, FAVORITE_ORDER, useListView };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/list/textEntry.ts
|
|
2
|
+
/** Guards list-page shortcuts from firing inside inputs, terminals, editors, and dialogs. */
|
|
3
|
+
function isTextEntryContext(target) {
|
|
4
|
+
const el = target;
|
|
5
|
+
if (!el) return false;
|
|
6
|
+
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable) return true;
|
|
7
|
+
return Boolean(el.closest?.(".xterm, .monaco-editor, .cm-editor, [role=\"dialog\"]"));
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { isTextEntryContext };
|
|
@@ -1,89 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useNotify, useOptionalWorkflowEngine, useStrings } from "../components/Provider.js";
|
|
2
2
|
import { ArrowDownIcon, ArrowUpIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ClockIcon, CopyIcon, DownloadIcon, ExpandIcon, ShrinkIcon, XIcon } from "../icons.js";
|
|
3
|
-
import {
|
|
3
|
+
import { TooltipInfo } from "../components/Tooltip.js";
|
|
4
|
+
import { highlightSegments, parseAnsiSegments, plainSegments } from "./segments.js";
|
|
4
5
|
import cx from "classnames";
|
|
5
6
|
import { Fragment, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
6
7
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
import { DateTime } from "luxon";
|
|
8
|
-
import Anser from "anser";
|
|
9
|
-
//#region src/logviewer/segments.ts
|
|
10
|
-
function segmentClassName(chunk) {
|
|
11
|
-
const classes = [];
|
|
12
|
-
if (chunk.fg) classes.push(`${chunk.fg}-fg`);
|
|
13
|
-
if (chunk.bg) classes.push(`${chunk.bg}-bg`);
|
|
14
|
-
for (const decoration of chunk.decorations) classes.push(`ansi-${decoration}`);
|
|
15
|
-
return classes.join(" ");
|
|
16
|
-
}
|
|
17
|
-
function parseAnsiSegments(line) {
|
|
18
|
-
return Anser.ansiToJson(line, {
|
|
19
|
-
use_classes: true,
|
|
20
|
-
remove_empty: true
|
|
21
|
-
}).map((chunk) => ({
|
|
22
|
-
content: chunk.content,
|
|
23
|
-
className: segmentClassName(chunk)
|
|
24
|
-
}));
|
|
25
|
-
}
|
|
26
|
-
function plainSegments(text) {
|
|
27
|
-
return [{
|
|
28
|
-
content: text,
|
|
29
|
-
className: ""
|
|
30
|
-
}];
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Matches are located on the concatenated line text so a term straddling an
|
|
34
|
-
* ANSI colour boundary still highlights, then sliced back onto the segments it
|
|
35
|
-
* covers.
|
|
36
|
-
*/
|
|
37
|
-
function highlightSegments(segments, searchTerm) {
|
|
38
|
-
if (!searchTerm) return segments;
|
|
39
|
-
const haystack = segments.map((segment) => segment.content).join("").toLowerCase();
|
|
40
|
-
const needle = searchTerm.toLowerCase();
|
|
41
|
-
if (!haystack.includes(needle)) return segments;
|
|
42
|
-
const matchStarts = [];
|
|
43
|
-
let found = haystack.indexOf(needle);
|
|
44
|
-
while (found !== -1) {
|
|
45
|
-
matchStarts.push(found);
|
|
46
|
-
found = haystack.indexOf(needle, found + needle.length);
|
|
47
|
-
}
|
|
48
|
-
const result = [];
|
|
49
|
-
let matchIndex = 0;
|
|
50
|
-
let offset = 0;
|
|
51
|
-
for (const segment of segments) {
|
|
52
|
-
const segmentEnd = offset + segment.content.length;
|
|
53
|
-
let cursor = offset;
|
|
54
|
-
while (cursor < segmentEnd) {
|
|
55
|
-
let matchStart = matchStarts[matchIndex];
|
|
56
|
-
while (matchStart !== void 0 && matchStart + needle.length <= cursor) {
|
|
57
|
-
matchIndex++;
|
|
58
|
-
matchStart = matchStarts[matchIndex];
|
|
59
|
-
}
|
|
60
|
-
if (matchStart === void 0 || matchStart >= segmentEnd) {
|
|
61
|
-
result.push({
|
|
62
|
-
...segment,
|
|
63
|
-
content: segment.content.slice(cursor - offset)
|
|
64
|
-
});
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
if (matchStart > cursor) {
|
|
68
|
-
result.push({
|
|
69
|
-
...segment,
|
|
70
|
-
content: segment.content.slice(cursor - offset, matchStart - offset)
|
|
71
|
-
});
|
|
72
|
-
cursor = matchStart;
|
|
73
|
-
}
|
|
74
|
-
const matchEnd = Math.min(matchStart + needle.length, segmentEnd);
|
|
75
|
-
result.push({
|
|
76
|
-
...segment,
|
|
77
|
-
content: segment.content.slice(cursor - offset, matchEnd - offset),
|
|
78
|
-
highlighted: true
|
|
79
|
-
});
|
|
80
|
-
cursor = matchEnd;
|
|
81
|
-
}
|
|
82
|
-
offset = segmentEnd;
|
|
83
|
-
}
|
|
84
|
-
return result;
|
|
85
|
-
}
|
|
86
|
-
//#endregion
|
|
87
9
|
//#region src/logviewer/LogViewer.tsx
|
|
88
10
|
function LogSegments({ segments }) {
|
|
89
11
|
return segments.map((segment, i) => segment.highlighted ? /* @__PURE__ */ jsx("mark", {
|
|
@@ -825,4 +747,4 @@ function LogViewer({ log, height = "unset", width, roundedBottom = false, lineNu
|
|
|
825
747
|
});
|
|
826
748
|
}
|
|
827
749
|
//#endregion
|
|
828
|
-
export {
|
|
750
|
+
export { LogViewer };
|
package/dist/logviewer/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { highlightSegments, parseAnsiSegments, plainSegments } from "./segments.js";
|
|
2
|
+
import { LogViewer } from "./LogViewer.js";
|
|
2
3
|
export { LogViewer, highlightSegments, parseAnsiSegments, plainSegments };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import Anser from "anser";
|
|
2
|
+
//#region src/logviewer/segments.ts
|
|
3
|
+
function segmentClassName(chunk) {
|
|
4
|
+
const classes = [];
|
|
5
|
+
if (chunk.fg) classes.push(`${chunk.fg}-fg`);
|
|
6
|
+
if (chunk.bg) classes.push(`${chunk.bg}-bg`);
|
|
7
|
+
for (const decoration of chunk.decorations) classes.push(`ansi-${decoration}`);
|
|
8
|
+
return classes.join(" ");
|
|
9
|
+
}
|
|
10
|
+
function parseAnsiSegments(line) {
|
|
11
|
+
return Anser.ansiToJson(line, {
|
|
12
|
+
use_classes: true,
|
|
13
|
+
remove_empty: true
|
|
14
|
+
}).map((chunk) => ({
|
|
15
|
+
content: chunk.content,
|
|
16
|
+
className: segmentClassName(chunk)
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
function plainSegments(text) {
|
|
20
|
+
return [{
|
|
21
|
+
content: text,
|
|
22
|
+
className: ""
|
|
23
|
+
}];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Matches are located on the concatenated line text so a term straddling an
|
|
27
|
+
* ANSI colour boundary still highlights, then sliced back onto the segments it
|
|
28
|
+
* covers.
|
|
29
|
+
*/
|
|
30
|
+
function highlightSegments(segments, searchTerm) {
|
|
31
|
+
if (!searchTerm) return segments;
|
|
32
|
+
const haystack = segments.map((segment) => segment.content).join("").toLowerCase();
|
|
33
|
+
const needle = searchTerm.toLowerCase();
|
|
34
|
+
if (!haystack.includes(needle)) return segments;
|
|
35
|
+
const matchStarts = [];
|
|
36
|
+
let found = haystack.indexOf(needle);
|
|
37
|
+
while (found !== -1) {
|
|
38
|
+
matchStarts.push(found);
|
|
39
|
+
found = haystack.indexOf(needle, found + needle.length);
|
|
40
|
+
}
|
|
41
|
+
const result = [];
|
|
42
|
+
let matchIndex = 0;
|
|
43
|
+
let offset = 0;
|
|
44
|
+
for (const segment of segments) {
|
|
45
|
+
const segmentEnd = offset + segment.content.length;
|
|
46
|
+
let cursor = offset;
|
|
47
|
+
while (cursor < segmentEnd) {
|
|
48
|
+
let matchStart = matchStarts[matchIndex];
|
|
49
|
+
while (matchStart !== void 0 && matchStart + needle.length <= cursor) {
|
|
50
|
+
matchIndex++;
|
|
51
|
+
matchStart = matchStarts[matchIndex];
|
|
52
|
+
}
|
|
53
|
+
if (matchStart === void 0 || matchStart >= segmentEnd) {
|
|
54
|
+
result.push({
|
|
55
|
+
...segment,
|
|
56
|
+
content: segment.content.slice(cursor - offset)
|
|
57
|
+
});
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
if (matchStart > cursor) {
|
|
61
|
+
result.push({
|
|
62
|
+
...segment,
|
|
63
|
+
content: segment.content.slice(cursor - offset, matchStart - offset)
|
|
64
|
+
});
|
|
65
|
+
cursor = matchStart;
|
|
66
|
+
}
|
|
67
|
+
const matchEnd = Math.min(matchStart + needle.length, segmentEnd);
|
|
68
|
+
result.push({
|
|
69
|
+
...segment,
|
|
70
|
+
content: segment.content.slice(cursor - offset, matchEnd - offset),
|
|
71
|
+
highlighted: true
|
|
72
|
+
});
|
|
73
|
+
cursor = matchEnd;
|
|
74
|
+
}
|
|
75
|
+
offset = segmentEnd;
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { highlightSegments, parseAnsiSegments, plainSegments };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns url when following it cannot run script in the app's origin: a
|
|
3
|
+
* relative path or an http, https or blob URL. Hosts and servers supply these
|
|
4
|
+
* URLs, so a javascript: URL from either would otherwise run when clicked.
|
|
5
|
+
*/
|
|
6
|
+
export declare function safeUrl(url: string | null | undefined): string | undefined;
|
package/dist/safeUrl.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/safeUrl.ts
|
|
2
|
+
var SAFE_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
3
|
+
"http:",
|
|
4
|
+
"https:",
|
|
5
|
+
"blob:"
|
|
6
|
+
]);
|
|
7
|
+
/**
|
|
8
|
+
* Returns url when following it cannot run script in the app's origin: a
|
|
9
|
+
* relative path or an http, https or blob URL. Hosts and servers supply these
|
|
10
|
+
* URLs, so a javascript: URL from either would otherwise run when clicked.
|
|
11
|
+
*/
|
|
12
|
+
function safeUrl(url) {
|
|
13
|
+
if (!url) return;
|
|
14
|
+
try {
|
|
15
|
+
const { protocol } = new URL(url, "https://relative.invalid");
|
|
16
|
+
return SAFE_PROTOCOLS.has(protocol) ? url : void 0;
|
|
17
|
+
} catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { safeUrl };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parallelworks/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "React UI components: a theme contract, icons, primitives, lists, forms, a job graph, a code editor, a log viewer, a file explorer and an AI chat, each on its own subpath",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -76,8 +76,7 @@
|
|
|
76
76
|
],
|
|
77
77
|
"peerDependencies": {
|
|
78
78
|
"formik": "^2.4.9",
|
|
79
|
-
"monaco-editor": "^0.
|
|
80
|
-
"monaco-yaml": "^5.5.1",
|
|
79
|
+
"monaco-editor": "^0.57.0",
|
|
81
80
|
"react": "^19.0.0",
|
|
82
81
|
"react-dom": "^19.0.0"
|
|
83
82
|
},
|
|
@@ -123,23 +122,22 @@
|
|
|
123
122
|
"@vitejs/plugin-react": "^6.0.2",
|
|
124
123
|
"formik": "^2.4.9",
|
|
125
124
|
"jsdom": "^26.1.0",
|
|
126
|
-
"monaco-editor": "^0.
|
|
127
|
-
"
|
|
125
|
+
"monaco-editor": "^0.57.0",
|
|
126
|
+
"path-browserify": "^1.0.1",
|
|
128
127
|
"publint": "^0.3.14",
|
|
129
128
|
"react": "19.3.0",
|
|
130
129
|
"react-dom": "19.3.0",
|
|
131
130
|
"storybook": "10.5.8",
|
|
132
131
|
"tailwindcss": "^4.3.0",
|
|
133
132
|
"typescript": "^7.0.0",
|
|
133
|
+
"url": "^0.11.4",
|
|
134
134
|
"vite": "^8.0.16",
|
|
135
|
-
"vitest": "^4.1.8"
|
|
135
|
+
"vitest": "^4.1.8",
|
|
136
|
+
"yaml-language-server": "^1.24.0"
|
|
136
137
|
},
|
|
137
138
|
"peerDependenciesMeta": {
|
|
138
139
|
"monaco-editor": {
|
|
139
140
|
"optional": true
|
|
140
|
-
},
|
|
141
|
-
"monaco-yaml": {
|
|
142
|
-
"optional": true
|
|
143
141
|
}
|
|
144
142
|
},
|
|
145
143
|
"scripts": {
|