@parallelworks/ui 0.5.1 → 0.5.2
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/chunks/{CodePreviewEditor-KwzSyk3-.js → CodePreviewEditor-Uij_Npp4.js} +1 -1
- package/dist/chunks/{CreateModal-CXSi9ELO.js → CreateModal-DEvWkdFl.js} +4 -29
- package/dist/chunks/{Monaco-FlGHL7zR.js → Monaco-H1M5hQbJ.js} +2 -2
- package/dist/chunks/PageHeader-CSo3LVId.js +571 -0
- package/dist/chunks/{Provider-wC9G01Ou.js → Provider-BIL5347a.js} +1 -0
- package/dist/chunks/{SwitchToggle-CkYT1isd.js → SwitchToggle-DiBXEP12.js} +1 -1
- package/dist/chunks/{editor-DbDUZn8w.js → editor-4ZuZruLz.js} +2 -2
- package/dist/chunks/{list-CGbR-ueU.js → list-CgzqVlao.js} +314 -8
- package/dist/components/PageHeader.d.ts +1 -1
- package/dist/components/Provider.d.ts +1 -0
- package/dist/components/Table.d.ts +1 -1
- package/dist/editor/index.js +1 -1
- package/dist/file-explorer/FileExplorer.d.ts +1 -3
- package/dist/file-explorer/helpers.d.ts +1 -3
- package/dist/file-explorer/index.js +15 -23
- package/dist/form/index.js +2 -2
- package/dist/index.js +6 -231
- package/dist/list/ActionToolbar.d.ts +38 -0
- package/dist/list/ListPage.d.ts +63 -0
- package/dist/list/RowContextMenu.d.ts +1 -1
- package/dist/list/index.d.ts +2 -0
- package/dist/list/index.js +3 -3
- package/dist/logviewer/index.js +1 -1
- package/dist/styles/theme.css +1 -0
- package/dist/styles.css +1 -1
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.js +3 -0
- package/dist/workflow/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/RowContextMenu-D3G3DPQk.js +0 -319
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as useCssIsDark } from "./useCssIsDark-DHr05dG2.js";
|
|
2
|
-
import { n as defineEditorThemes, r as getThemeName, t as setupMonacoWorkers } from "./editor-
|
|
2
|
+
import { n as defineEditorThemes, r as getThemeName, t as setupMonacoWorkers } from "./editor-4ZuZruLz.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
import { useEffect, useRef } from "react";
|
|
5
5
|
import * as monaco from "monaco-editor";
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { AlertIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ClipboardIcon, CopyIcon, FavoriteIcon, FavoriteOutlineIcon, HiddenFalseIcon, HiddenTrueIcon, InfoIcon, TooltipIcon } from "../icons.js";
|
|
2
|
-
import { c as useStrings, i as useNotify
|
|
2
|
+
import { c as useStrings, i as useNotify } from "./Provider-BIL5347a.js";
|
|
3
3
|
import { n as TOOLTIP_ID } from "./Tooltip-WgbiC_nd.js";
|
|
4
4
|
import { n as modalPanelClasses, t as BareModal } from "./BareModal-DBa84JZO.js";
|
|
5
|
+
import { S as AddMenu } from "./PageHeader-CSo3LVId.js";
|
|
5
6
|
import cx from "classnames";
|
|
6
7
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
-
import {
|
|
8
|
+
import { Suspense, lazy, useCallback, useEffect, useRef, useState } from "react";
|
|
8
9
|
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions, Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
|
|
9
10
|
//#region src/components/Callout.tsx
|
|
10
11
|
function CalloutIcon({ type }) {
|
|
@@ -171,32 +172,6 @@ function ConfirmModal({ open, onClose, title, description, children, confirmLabe
|
|
|
171
172
|
});
|
|
172
173
|
}
|
|
173
174
|
//#endregion
|
|
174
|
-
//#region src/components/AddMenu.tsx
|
|
175
|
-
var addMenuItemClasses = "flex w-full items-center gap-2 px-3 py-1.5 text-[13px] text-(--theme-app) data-[focus]:bg-(--theme-muted-panel-bg) cursor-pointer";
|
|
176
|
-
function AddMenu({ items, label, buttonClassName, zClassName = "z-50", children }) {
|
|
177
|
-
const Link = useLink();
|
|
178
|
-
return /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuButton, {
|
|
179
|
-
"aria-label": label,
|
|
180
|
-
title: label,
|
|
181
|
-
className: buttonClassName,
|
|
182
|
-
children
|
|
183
|
-
}), /* @__PURE__ */ jsx(MenuItems, {
|
|
184
|
-
anchor: "bottom start",
|
|
185
|
-
className: cx("mt-1 min-w-52 rounded-lg border border-(--theme-border) bg-(--theme-app-bg) py-1 shadow-lg focus:outline-none", zClassName),
|
|
186
|
-
children: items.map((item) => /* @__PURE__ */ jsxs(Fragment$1, { children: [item.separatorAbove && /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-(--theme-border)" }), /* @__PURE__ */ jsx(MenuItem, { children: item.to && !item.disabled ? /* @__PURE__ */ jsxs(Link, {
|
|
187
|
-
to: item.to,
|
|
188
|
-
className: addMenuItemClasses,
|
|
189
|
-
children: [item.icon, item.label]
|
|
190
|
-
}) : /* @__PURE__ */ jsxs("button", {
|
|
191
|
-
type: "button",
|
|
192
|
-
onClick: item.onSelect,
|
|
193
|
-
disabled: item.disabled,
|
|
194
|
-
className: cx(addMenuItemClasses, item.disabled && "opacity-50 cursor-not-allowed"),
|
|
195
|
-
children: [item.icon, item.label]
|
|
196
|
-
}) })] }, item.label))
|
|
197
|
-
})] });
|
|
198
|
-
}
|
|
199
|
-
//#endregion
|
|
200
175
|
//#region src/components/CreateModal.tsx
|
|
201
176
|
/** Small info icon that surfaces field help via the global tooltip. */
|
|
202
177
|
function FieldHelp({ tooltip }) {
|
|
@@ -592,4 +567,4 @@ function CreateModalSelect({ label, icon, value, options, onChange, disabled = f
|
|
|
592
567
|
})] }) });
|
|
593
568
|
}
|
|
594
569
|
//#endregion
|
|
595
|
-
export { CreateModalSwitch as a,
|
|
570
|
+
export { CreateModalSwitch as a, dangerButtonClasses as c, Markdown as d, CopyCodeBlock as f, CreateModalSelect as i, ghostButtonClasses as l, Callout as m, CreateModalAutocompleteField as n, CreateModalTextarea as o, CopyToClipboard as p, CreateModalField as r, ConfirmModal as s, CreateModal as t, primaryButtonClasses as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { l as useWorkflowJsonResolver } from "./Provider-
|
|
1
|
+
import { l as useWorkflowJsonResolver } from "./Provider-BIL5347a.js";
|
|
2
2
|
import { t as useCssIsDark } from "./useCssIsDark-DHr05dG2.js";
|
|
3
|
-
import { n as defineEditorThemes, r as getThemeName, t as setupMonacoWorkers } from "./editor-
|
|
3
|
+
import { n as defineEditorThemes, r as getThemeName, t as setupMonacoWorkers } from "./editor-4ZuZruLz.js";
|
|
4
4
|
import cx from "classnames";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
import { useEffect, useRef } from "react";
|
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
import { AddIcon, CheckIcon, ChevronRightIcon, ClipboardIcon, CopyIcon, EditIcon, IdCardIcon, KeyIcon, LinkIcon, MailIcon, MoreIcon, UserIcon } from "../icons.js";
|
|
2
|
+
import { c as useStrings, i as useNotify, n as useLink, s as useSlots } from "./Provider-BIL5347a.js";
|
|
3
|
+
import { n as TOOLTIP_ID } from "./Tooltip-WgbiC_nd.js";
|
|
4
|
+
import cx from "classnames";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import React, { Fragment as Fragment$1, createContext, useCallback, useContext, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
7
|
+
import { createPortal } from "react-dom";
|
|
8
|
+
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
|
|
9
|
+
//#region src/components/AddMenu.tsx
|
|
10
|
+
var addMenuItemClasses = "flex w-full items-center gap-2 px-3 py-1.5 text-[13px] text-(--theme-app) data-[focus]:bg-(--theme-muted-panel-bg) cursor-pointer";
|
|
11
|
+
function AddMenu({ items, label, buttonClassName, zClassName = "z-50", children }) {
|
|
12
|
+
const Link = useLink();
|
|
13
|
+
return /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuButton, {
|
|
14
|
+
"aria-label": label,
|
|
15
|
+
title: label,
|
|
16
|
+
className: buttonClassName,
|
|
17
|
+
children
|
|
18
|
+
}), /* @__PURE__ */ jsx(MenuItems, {
|
|
19
|
+
anchor: "bottom start",
|
|
20
|
+
className: cx("mt-1 min-w-52 rounded-lg border border-(--theme-border) bg-(--theme-app-bg) py-1 shadow-lg focus:outline-none", zClassName),
|
|
21
|
+
children: items.map((item) => /* @__PURE__ */ jsxs(Fragment$1, { children: [item.separatorAbove && /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-(--theme-border)" }), /* @__PURE__ */ jsx(MenuItem, { children: item.to && !item.disabled ? /* @__PURE__ */ jsxs(Link, {
|
|
22
|
+
to: item.to,
|
|
23
|
+
className: addMenuItemClasses,
|
|
24
|
+
children: [item.icon, item.label]
|
|
25
|
+
}) : /* @__PURE__ */ jsxs("button", {
|
|
26
|
+
type: "button",
|
|
27
|
+
onClick: item.onSelect,
|
|
28
|
+
disabled: item.disabled,
|
|
29
|
+
className: cx(addMenuItemClasses, item.disabled && "opacity-50 cursor-not-allowed"),
|
|
30
|
+
children: [item.icon, item.label]
|
|
31
|
+
}) })] }, item.label))
|
|
32
|
+
})] });
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/components/Breadcrumbs.tsx
|
|
36
|
+
var BreadcrumbContext = createContext({
|
|
37
|
+
breadcrumbs: [],
|
|
38
|
+
setBreadcrumbs: () => {},
|
|
39
|
+
rightsideBreadcrumb: null,
|
|
40
|
+
setRightsideBreadcrumb: () => {},
|
|
41
|
+
hidden: false,
|
|
42
|
+
setHidden: () => {},
|
|
43
|
+
titleActionSlot: null,
|
|
44
|
+
setTitleActionSlot: () => {},
|
|
45
|
+
rightActionSlot: null,
|
|
46
|
+
setRightActionSlot: () => {}
|
|
47
|
+
});
|
|
48
|
+
var useBreadcrumb = () => useContext(BreadcrumbContext);
|
|
49
|
+
function BreadcrumbProvider({ children }) {
|
|
50
|
+
const [breadcrumbs, setBreadcrumbs] = React.useState([]);
|
|
51
|
+
const [rightsideBreadcrumb, setRightsideBreadcrumb] = React.useState(null);
|
|
52
|
+
const [hidden, setHidden] = React.useState(false);
|
|
53
|
+
const [titleActionSlot, setTitleActionSlot] = React.useState(null);
|
|
54
|
+
const [rightActionSlot, setRightActionSlot] = React.useState(null);
|
|
55
|
+
return /* @__PURE__ */ jsx(BreadcrumbContext.Provider, {
|
|
56
|
+
value: {
|
|
57
|
+
breadcrumbs,
|
|
58
|
+
setBreadcrumbs,
|
|
59
|
+
rightsideBreadcrumb,
|
|
60
|
+
setRightsideBreadcrumb,
|
|
61
|
+
hidden,
|
|
62
|
+
setHidden,
|
|
63
|
+
titleActionSlot,
|
|
64
|
+
setTitleActionSlot,
|
|
65
|
+
rightActionSlot,
|
|
66
|
+
setRightActionSlot
|
|
67
|
+
},
|
|
68
|
+
children
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function useSetBreadcrumbs(getBreadcrumbs) {
|
|
72
|
+
const { setBreadcrumbs } = useBreadcrumb();
|
|
73
|
+
useLayoutEffect(() => {
|
|
74
|
+
setBreadcrumbs(typeof getBreadcrumbs === "function" ? getBreadcrumbs() : getBreadcrumbs);
|
|
75
|
+
}, [getBreadcrumbs, setBreadcrumbs]);
|
|
76
|
+
}
|
|
77
|
+
var EMPTY_BREADCRUMBS = [];
|
|
78
|
+
/** For pages that render their own header instead of the breadcrumb strip. */
|
|
79
|
+
function useClearBreadcrumbs() {
|
|
80
|
+
useSetBreadcrumbs(EMPTY_BREADCRUMBS);
|
|
81
|
+
}
|
|
82
|
+
function useHideBreadcrumbs(hidden) {
|
|
83
|
+
const { setHidden } = useBreadcrumb();
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
setHidden(hidden);
|
|
86
|
+
return () => setHidden(false);
|
|
87
|
+
}, [hidden, setHidden]);
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/list/RowContextMenu.tsx
|
|
91
|
+
/** Converts a single row action to a menu item: a `to` makes it a link, otherwise an action. */
|
|
92
|
+
function toRowMenuItem(action) {
|
|
93
|
+
if (action.to) return {
|
|
94
|
+
kind: "link",
|
|
95
|
+
label: action.label,
|
|
96
|
+
icon: action.icon,
|
|
97
|
+
to: action.to,
|
|
98
|
+
destructive: action.destructive
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
kind: "action",
|
|
102
|
+
label: action.label,
|
|
103
|
+
icon: action.icon,
|
|
104
|
+
onSelect: action.onSelect ?? (() => {}),
|
|
105
|
+
disabled: action.disabled,
|
|
106
|
+
destructive: action.destructive
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Bridges a toolbar action (icon component, `onClick`/`href`) onto the shared
|
|
110
|
+
* `RowAction` shape. Typed structurally so any toolbar action shape matching
|
|
111
|
+
* these fields is assignable. */
|
|
112
|
+
function toolbarActionToRowAction(action) {
|
|
113
|
+
const Icon = action.icon;
|
|
114
|
+
return {
|
|
115
|
+
key: action.key,
|
|
116
|
+
label: action.label,
|
|
117
|
+
icon: /* @__PURE__ */ jsx(Icon, {}),
|
|
118
|
+
onSelect: action.onClick,
|
|
119
|
+
to: action.href,
|
|
120
|
+
disabled: action.disabled,
|
|
121
|
+
destructive: action.key === "delete" || action.key === "destroy"
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/** Assembles a row's context menu in the shared order: leading link(s) → middle
|
|
125
|
+
* actions → extra items → Copy submenu → trailing (destructive) actions last. */
|
|
126
|
+
function assembleRowMenu({ lead = [], actions, exclude, order, trailing = ["delete"], extra = [], copy }) {
|
|
127
|
+
const trailingSet = new Set(trailing);
|
|
128
|
+
const excludeSet = new Set(exclude);
|
|
129
|
+
let middle = actions.filter((a) => !trailingSet.has(a.key) && !excludeSet.has(a.key));
|
|
130
|
+
if (order) {
|
|
131
|
+
const byKey = new Map(middle.map((a) => [a.key, a]));
|
|
132
|
+
middle = order.map((key) => byKey.get(key)).filter((a) => a !== void 0);
|
|
133
|
+
}
|
|
134
|
+
const trailingItems = trailing.map((key) => actions.find((a) => a.key === key)).filter((a) => a !== void 0);
|
|
135
|
+
return [
|
|
136
|
+
...lead,
|
|
137
|
+
...middle.map(toRowMenuItem),
|
|
138
|
+
...extra,
|
|
139
|
+
...copy ? [copy] : [],
|
|
140
|
+
...trailingItems.map(toRowMenuItem)
|
|
141
|
+
];
|
|
142
|
+
}
|
|
143
|
+
function useRowMenu() {
|
|
144
|
+
const [menu, setMenu] = useState(null);
|
|
145
|
+
const onCloseRef = useRef(void 0);
|
|
146
|
+
return {
|
|
147
|
+
openMenu: useCallback((x, y, items, onClose) => {
|
|
148
|
+
if (items.length > 0) {
|
|
149
|
+
onCloseRef.current?.();
|
|
150
|
+
onCloseRef.current = onClose;
|
|
151
|
+
setMenu({
|
|
152
|
+
x,
|
|
153
|
+
y,
|
|
154
|
+
items
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}, []),
|
|
158
|
+
contextMenu: /* @__PURE__ */ jsx(RowContextMenu, {
|
|
159
|
+
state: menu,
|
|
160
|
+
onClose: useCallback(() => {
|
|
161
|
+
onCloseRef.current?.();
|
|
162
|
+
onCloseRef.current = void 0;
|
|
163
|
+
setMenu(null);
|
|
164
|
+
}, [])
|
|
165
|
+
})
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/** The full-screen menu overlay drops CSS :hover on the triggering row; wrap openMenu here to substitute a JS-driven `active` highlight. */
|
|
169
|
+
function useRowMenuActive(openMenu) {
|
|
170
|
+
const [active, setActive] = useState(false);
|
|
171
|
+
return {
|
|
172
|
+
active,
|
|
173
|
+
openMenu: useCallback((x, y, items) => {
|
|
174
|
+
setActive(true);
|
|
175
|
+
openMenu(x, y, items, () => setActive(false));
|
|
176
|
+
}, [openMenu])
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function rowContextMenuProps(openMenu, items) {
|
|
180
|
+
return { onContextMenu: (e) => {
|
|
181
|
+
e.preventDefault();
|
|
182
|
+
if (items.length > 0) e.stopPropagation();
|
|
183
|
+
openMenu(e.clientX, e.clientY, items);
|
|
184
|
+
} };
|
|
185
|
+
}
|
|
186
|
+
function RowContextMenu({ state, onClose }) {
|
|
187
|
+
const ref = useRef(null);
|
|
188
|
+
const [pos, setPos] = useState(null);
|
|
189
|
+
useLayoutEffect(() => {
|
|
190
|
+
if (!state || !ref.current) {
|
|
191
|
+
setPos(null);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const { width, height } = ref.current.getBoundingClientRect();
|
|
195
|
+
const pad = 8;
|
|
196
|
+
const top = height > window.innerHeight - pad - state.y && state.y - height - pad >= 0 ? state.y - height : Math.min(state.y, window.innerHeight - height - pad);
|
|
197
|
+
setPos({
|
|
198
|
+
left: Math.max(pad, Math.min(state.x, window.innerWidth - width - pad)),
|
|
199
|
+
top: Math.max(pad, top)
|
|
200
|
+
});
|
|
201
|
+
}, [state]);
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
if (!state) return;
|
|
204
|
+
const close = () => onClose();
|
|
205
|
+
const onKey = (e) => {
|
|
206
|
+
if (e.key === "Escape") onClose();
|
|
207
|
+
};
|
|
208
|
+
window.addEventListener("scroll", close, true);
|
|
209
|
+
window.addEventListener("resize", close);
|
|
210
|
+
window.addEventListener("keydown", onKey);
|
|
211
|
+
return () => {
|
|
212
|
+
window.removeEventListener("scroll", close, true);
|
|
213
|
+
window.removeEventListener("resize", close);
|
|
214
|
+
window.removeEventListener("keydown", onKey);
|
|
215
|
+
};
|
|
216
|
+
}, [state, onClose]);
|
|
217
|
+
if (!state) return null;
|
|
218
|
+
const side = (pos?.left ?? state.x) > window.innerWidth * .6 ? "left" : "right";
|
|
219
|
+
return createPortal(/* @__PURE__ */ jsx("div", {
|
|
220
|
+
className: "fixed inset-0 z-50",
|
|
221
|
+
onClick: onClose,
|
|
222
|
+
onContextMenu: (e) => {
|
|
223
|
+
e.preventDefault();
|
|
224
|
+
if (ref.current?.contains(e.target)) {
|
|
225
|
+
onClose();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const { clientX, clientY } = e;
|
|
229
|
+
const overlay = e.currentTarget;
|
|
230
|
+
overlay.style.pointerEvents = "none";
|
|
231
|
+
const under = document.elementFromPoint(clientX, clientY);
|
|
232
|
+
overlay.style.pointerEvents = "";
|
|
233
|
+
onClose();
|
|
234
|
+
under?.dispatchEvent(new MouseEvent("contextmenu", {
|
|
235
|
+
bubbles: true,
|
|
236
|
+
cancelable: true,
|
|
237
|
+
clientX,
|
|
238
|
+
clientY
|
|
239
|
+
}));
|
|
240
|
+
},
|
|
241
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
242
|
+
ref,
|
|
243
|
+
role: "menu",
|
|
244
|
+
className: "absolute min-w-44 rounded-lg border border-(--theme-border) bg-(--theme-panel-bg) py-1 shadow-lg backdrop-blur-xl",
|
|
245
|
+
style: {
|
|
246
|
+
left: pos?.left ?? state.x,
|
|
247
|
+
top: pos?.top ?? state.y,
|
|
248
|
+
visibility: pos ? "visible" : "hidden"
|
|
249
|
+
},
|
|
250
|
+
onClick: (e) => e.stopPropagation(),
|
|
251
|
+
children: /* @__PURE__ */ jsx(MenuItemList, {
|
|
252
|
+
items: state.items,
|
|
253
|
+
onClose,
|
|
254
|
+
side
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
}), document.body);
|
|
258
|
+
}
|
|
259
|
+
var MENU_ITEM_CLASSES = "flex w-full items-center gap-2.5 px-3 py-1.5 text-left text-[13px] hover:bg-(--theme-muted-panel-bg) transition-colors cursor-pointer [&>svg]:h-4 [&>svg]:w-4 [&>svg]:shrink-0";
|
|
260
|
+
function MenuItemList({ items, onClose, side }) {
|
|
261
|
+
return items.map((item, i) => item.kind === "divider" ? /* @__PURE__ */ jsx("div", {
|
|
262
|
+
"aria-hidden": "true",
|
|
263
|
+
className: "my-1 h-px bg-(--theme-border)"
|
|
264
|
+
}, `divider-${i}`) : /* @__PURE__ */ jsx(MenuRow, {
|
|
265
|
+
item,
|
|
266
|
+
onClose,
|
|
267
|
+
side
|
|
268
|
+
}, `${item.label}-${i}`));
|
|
269
|
+
}
|
|
270
|
+
function MenuRow({ item, onClose, side }) {
|
|
271
|
+
const Link = useLink();
|
|
272
|
+
const notify = useNotify();
|
|
273
|
+
const { list: t } = useStrings();
|
|
274
|
+
const [openSub, setOpenSub] = useState(false);
|
|
275
|
+
const closeTimer = useRef(void 0);
|
|
276
|
+
if (item.kind === "submenu") {
|
|
277
|
+
const open = () => {
|
|
278
|
+
clearTimeout(closeTimer.current);
|
|
279
|
+
setOpenSub(true);
|
|
280
|
+
};
|
|
281
|
+
const close = () => {
|
|
282
|
+
closeTimer.current = setTimeout(() => setOpenSub(false), 160);
|
|
283
|
+
};
|
|
284
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
285
|
+
className: "relative",
|
|
286
|
+
onMouseEnter: open,
|
|
287
|
+
onMouseLeave: close,
|
|
288
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
289
|
+
className: cx(MENU_ITEM_CLASSES, "justify-between text-(--theme-app)"),
|
|
290
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
291
|
+
className: "flex items-center gap-2.5",
|
|
292
|
+
children: [item.icon, item.label]
|
|
293
|
+
}), /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 shrink-0 opacity-60" })]
|
|
294
|
+
}), openSub && /* @__PURE__ */ jsx("div", {
|
|
295
|
+
className: cx("absolute -top-1 z-10 min-w-44 rounded-lg border border-(--theme-border) bg-(--theme-panel-bg) py-1 shadow-lg", side === "left" ? "right-full" : "left-full"),
|
|
296
|
+
children: /* @__PURE__ */ jsx(MenuItemList, {
|
|
297
|
+
items: item.items,
|
|
298
|
+
onClose,
|
|
299
|
+
side
|
|
300
|
+
})
|
|
301
|
+
})]
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
if (item.kind === "link") return /* @__PURE__ */ jsxs(Link, {
|
|
305
|
+
to: item.to,
|
|
306
|
+
onClick: onClose,
|
|
307
|
+
className: cx(MENU_ITEM_CLASSES, item.destructive ? "text-red-500" : "text-(--theme-app)"),
|
|
308
|
+
children: [item.icon, item.label]
|
|
309
|
+
});
|
|
310
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
311
|
+
type: "button",
|
|
312
|
+
disabled: item.disabled,
|
|
313
|
+
onClick: () => {
|
|
314
|
+
if (item.copy) {
|
|
315
|
+
const { text, label } = item.copy;
|
|
316
|
+
navigator.clipboard?.writeText(text).then(() => notify.success(t.copied(label)), () => notify.error(t.couldntCopy(label)));
|
|
317
|
+
}
|
|
318
|
+
item.onSelect?.();
|
|
319
|
+
onClose();
|
|
320
|
+
},
|
|
321
|
+
className: cx(MENU_ITEM_CLASSES, item.destructive ? "text-red-500" : "text-(--theme-app)", item.disabled && "opacity-40 cursor-not-allowed hover:bg-transparent"),
|
|
322
|
+
children: [
|
|
323
|
+
item.icon,
|
|
324
|
+
item.label,
|
|
325
|
+
item.selected && /* @__PURE__ */ jsx(CheckIcon, { className: "ml-auto opacity-80" })
|
|
326
|
+
]
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
/** Builds the Copy submenu entries for whichever fields a row has, in stable
|
|
330
|
+
* order. The menu itself performs the copy and notifies; `t` is an optional
|
|
331
|
+
* host translator for the field labels (falls back to the provider defaults'
|
|
332
|
+
* English). */
|
|
333
|
+
function copySubmenu({ name, nameLabel, email, username, uid, id, url, extra, t }) {
|
|
334
|
+
const items = [
|
|
335
|
+
{
|
|
336
|
+
label: nameLabel ?? (t ? t("rowContextMenu.labelName") : "name"),
|
|
337
|
+
value: name,
|
|
338
|
+
icon: /* @__PURE__ */ jsx(CopyIcon, {})
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
label: t ? t("rowContextMenu.labelEmail") : "email",
|
|
342
|
+
value: email,
|
|
343
|
+
icon: /* @__PURE__ */ jsx(MailIcon, {})
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
label: t ? t("rowContextMenu.labelUsername") : "username",
|
|
347
|
+
value: username,
|
|
348
|
+
icon: /* @__PURE__ */ jsx(UserIcon, {})
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
label: t ? t("rowContextMenu.labelUid") : "UID",
|
|
352
|
+
value: uid === null || uid === void 0 ? null : String(uid),
|
|
353
|
+
icon: /* @__PURE__ */ jsx(KeyIcon, {})
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
label: t ? t("rowContextMenu.labelId") : "ID",
|
|
357
|
+
value: id,
|
|
358
|
+
icon: /* @__PURE__ */ jsx(IdCardIcon, {})
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
label: t ? t("rowContextMenu.labelUrl") : "URL",
|
|
362
|
+
value: url,
|
|
363
|
+
icon: /* @__PURE__ */ jsx(LinkIcon, {})
|
|
364
|
+
},
|
|
365
|
+
...(extra ?? []).map((e) => ({
|
|
366
|
+
label: e.label,
|
|
367
|
+
value: e.value,
|
|
368
|
+
icon: e.icon ?? /* @__PURE__ */ jsx(CopyIcon, {})
|
|
369
|
+
}))
|
|
370
|
+
].filter((f) => f.value).map((f) => ({
|
|
371
|
+
kind: "action",
|
|
372
|
+
label: t ? t("rowContextMenu.copy", { label: f.label }) : `Copy ${f.label}`,
|
|
373
|
+
icon: f.icon,
|
|
374
|
+
copy: {
|
|
375
|
+
text: f.value,
|
|
376
|
+
label: f.label
|
|
377
|
+
}
|
|
378
|
+
}));
|
|
379
|
+
return {
|
|
380
|
+
kind: "submenu",
|
|
381
|
+
label: t ? t("common.copy") : "Copy",
|
|
382
|
+
icon: /* @__PURE__ */ jsx(ClipboardIcon, {}),
|
|
383
|
+
items
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
/** Stays visible while active (menu open) so it doesn't vanish behind the overlay. */
|
|
387
|
+
function MoreButton({ onOpen, active, className }) {
|
|
388
|
+
const { list: t } = useStrings();
|
|
389
|
+
return /* @__PURE__ */ jsx("button", {
|
|
390
|
+
type: "button",
|
|
391
|
+
"aria-label": t.moreActions,
|
|
392
|
+
onClick: (e) => {
|
|
393
|
+
e.stopPropagation();
|
|
394
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
395
|
+
onOpen(r.right, r.bottom);
|
|
396
|
+
},
|
|
397
|
+
className: cx("rounded p-1 cursor-pointer text-(--theme-muted-text-color) transition-colors hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app) focus-visible:opacity-100", active ? "opacity-100" : "opacity-0 group-hover:opacity-100", className),
|
|
398
|
+
children: /* @__PURE__ */ jsx(MoreIcon, { className: "h-4 w-4" })
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
//#endregion
|
|
402
|
+
//#region src/components/PageHeader.tsx
|
|
403
|
+
var headerActionButtonClasses = "flex items-center justify-center w-6 h-6 rounded-md shrink-0 cursor-pointer text-(--theme-muted-text-color) hover:text-(--theme-app) hover:bg-(--theme-muted-panel-bg) transition-colors";
|
|
404
|
+
var headerAddButtonClasses = "inline-flex h-[26px] shrink-0 items-center gap-1.5 rounded-md border border-(--theme-border) px-2 text-xs font-medium cursor-pointer text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app) transition-colors";
|
|
405
|
+
/** With menu, the plus opens a chooser; otherwise navigates to or calls the
|
|
406
|
+
* single action. `word` is the visible verb; `label` stays the full action for
|
|
407
|
+
* the tooltip and screen readers. */
|
|
408
|
+
function HeaderAddButton({ to, onClick, label, word = "add", menu }) {
|
|
409
|
+
const { common } = useStrings();
|
|
410
|
+
const Link = useLink();
|
|
411
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(AddIcon, { className: "w-3 h-3" }), /* @__PURE__ */ jsx("span", { children: word === "create" ? common.create : common.add })] });
|
|
412
|
+
if (menu) return /* @__PURE__ */ jsx(AddMenu, {
|
|
413
|
+
items: menu,
|
|
414
|
+
label,
|
|
415
|
+
buttonClassName: headerAddButtonClasses,
|
|
416
|
+
children: content
|
|
417
|
+
});
|
|
418
|
+
if (to) return /* @__PURE__ */ jsx(Link, {
|
|
419
|
+
to,
|
|
420
|
+
"aria-label": label,
|
|
421
|
+
title: label,
|
|
422
|
+
className: headerAddButtonClasses,
|
|
423
|
+
children: content
|
|
424
|
+
});
|
|
425
|
+
return /* @__PURE__ */ jsx("button", {
|
|
426
|
+
type: "button",
|
|
427
|
+
onClick,
|
|
428
|
+
"aria-label": label,
|
|
429
|
+
title: label,
|
|
430
|
+
className: headerAddButtonClasses,
|
|
431
|
+
children: content
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
function HeaderActionMenu({ items, label = "Actions" }) {
|
|
435
|
+
if (items.length === 0) return null;
|
|
436
|
+
return /* @__PURE__ */ jsx(AddMenu, {
|
|
437
|
+
items,
|
|
438
|
+
label,
|
|
439
|
+
buttonClassName: headerActionButtonClasses,
|
|
440
|
+
children: /* @__PURE__ */ jsx(MoreIcon, { className: "w-3.5 h-3.5" })
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
/** The header "…" trigger for a RowMenuItem menu — same rendering (submenus,
|
|
444
|
+
* destructive styling) as the list pages' right-click context menus. */
|
|
445
|
+
function HeaderRowMenu({ items, label = "Actions" }) {
|
|
446
|
+
const { openMenu, contextMenu } = useRowMenu();
|
|
447
|
+
if (items.length === 0) return null;
|
|
448
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
|
|
449
|
+
type: "button",
|
|
450
|
+
"aria-label": label,
|
|
451
|
+
title: label,
|
|
452
|
+
className: headerActionButtonClasses,
|
|
453
|
+
onClick: (e) => {
|
|
454
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
455
|
+
openMenu(r.left, r.bottom + 4, items);
|
|
456
|
+
},
|
|
457
|
+
children: /* @__PURE__ */ jsx(MoreIcon, { className: "w-3.5 h-3.5" })
|
|
458
|
+
}), contextMenu] });
|
|
459
|
+
}
|
|
460
|
+
function HeaderEditButton({ to, onClick, label = "Edit", disabled, tooltip }) {
|
|
461
|
+
const Link = useLink();
|
|
462
|
+
const tooltipProps = tooltip ? {
|
|
463
|
+
"data-tooltip-id": TOOLTIP_ID,
|
|
464
|
+
"data-tooltip-content": tooltip
|
|
465
|
+
} : {};
|
|
466
|
+
if (to && !disabled) return /* @__PURE__ */ jsx(Link, {
|
|
467
|
+
to,
|
|
468
|
+
"aria-label": label,
|
|
469
|
+
...tooltip ? {} : { title: label },
|
|
470
|
+
className: headerActionButtonClasses,
|
|
471
|
+
...tooltipProps,
|
|
472
|
+
children: /* @__PURE__ */ jsx(EditIcon, { className: "w-3 h-3" })
|
|
473
|
+
});
|
|
474
|
+
return /* @__PURE__ */ jsx("button", {
|
|
475
|
+
type: "button",
|
|
476
|
+
onClick,
|
|
477
|
+
disabled,
|
|
478
|
+
"aria-label": label,
|
|
479
|
+
title: tooltip ? void 0 : label,
|
|
480
|
+
className: cx(headerActionButtonClasses, disabled && "opacity-50 cursor-not-allowed hover:bg-transparent"),
|
|
481
|
+
...tooltipProps,
|
|
482
|
+
children: /* @__PURE__ */ jsx(EditIcon, { className: "w-3 h-3" })
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
/** Renders nothing when the modern breadcrumb strip isn't mounted (classic chrome or self-headered pages). */
|
|
486
|
+
function BreadcrumbsTitleAction({ children }) {
|
|
487
|
+
const { titleActionSlot } = useBreadcrumb();
|
|
488
|
+
if (!titleActionSlot) return null;
|
|
489
|
+
return createPortal(children, titleActionSlot);
|
|
490
|
+
}
|
|
491
|
+
function BreadcrumbsRightAction({ children }) {
|
|
492
|
+
const { rightActionSlot } = useBreadcrumb();
|
|
493
|
+
if (!rightActionSlot) return null;
|
|
494
|
+
return createPortal(children, rightActionSlot);
|
|
495
|
+
}
|
|
496
|
+
var breadcrumbsActionClasses = "flex items-center gap-1 link text-xs whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed";
|
|
497
|
+
function BreadcrumbsActionButton({ icon: Icon, label, to, onClick, disabled, tooltip }) {
|
|
498
|
+
const Link = useLink();
|
|
499
|
+
const tip = tooltip ? {
|
|
500
|
+
"data-tooltip-id": TOOLTIP_ID,
|
|
501
|
+
"data-tooltip-content": tooltip
|
|
502
|
+
} : {};
|
|
503
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Icon, { className: "w-3 h-3" }), label] });
|
|
504
|
+
if (to && !disabled) return /* @__PURE__ */ jsx(Link, {
|
|
505
|
+
to,
|
|
506
|
+
className: breadcrumbsActionClasses,
|
|
507
|
+
...tip,
|
|
508
|
+
children: content
|
|
509
|
+
});
|
|
510
|
+
return /* @__PURE__ */ jsx("button", {
|
|
511
|
+
type: "button",
|
|
512
|
+
onClick,
|
|
513
|
+
disabled,
|
|
514
|
+
className: breadcrumbsActionClasses,
|
|
515
|
+
...tip,
|
|
516
|
+
children: content
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
function PageHeader({ breadcrumbs, title, titleAction, actions, toolbar, className, sticky = true, stickyTopClassName = "top-0" }) {
|
|
520
|
+
const { setHidden } = useBreadcrumb();
|
|
521
|
+
const Link = useLink();
|
|
522
|
+
const { breadcrumbPin } = useSlots();
|
|
523
|
+
useLayoutEffect(() => {
|
|
524
|
+
setHidden(true);
|
|
525
|
+
return () => setHidden(false);
|
|
526
|
+
}, [setHidden]);
|
|
527
|
+
const crumbs = [...breadcrumbs ?? []];
|
|
528
|
+
const lastLabel = crumbs[crumbs.length - 1]?.label;
|
|
529
|
+
if (title !== null && title !== void 0 && title !== lastLabel) crumbs.push({ label: title });
|
|
530
|
+
const crumbRow = crumbs.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
531
|
+
className: "flex items-center gap-1.5 min-w-0",
|
|
532
|
+
children: [
|
|
533
|
+
/* @__PURE__ */ jsx("nav", {
|
|
534
|
+
"aria-label": "Breadcrumb",
|
|
535
|
+
className: "flex items-center gap-2 min-w-0 text-[13px]",
|
|
536
|
+
children: crumbs.map((crumb, idx) => {
|
|
537
|
+
if (idx === crumbs.length - 1) return /* @__PURE__ */ jsx("h1", {
|
|
538
|
+
className: "m-0 text-[13px] font-medium leading-none text-(--theme-app) truncate",
|
|
539
|
+
children: crumb.label
|
|
540
|
+
}, `${crumb.label}-${idx}`);
|
|
541
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [crumb.href ? /* @__PURE__ */ jsx(Link, {
|
|
542
|
+
to: crumb.href,
|
|
543
|
+
className: "text-(--theme-muted-text-color) hover:text-(--theme-app) transition-colors cursor-pointer whitespace-nowrap",
|
|
544
|
+
children: crumb.label
|
|
545
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
546
|
+
className: "text-(--theme-muted-text-color) whitespace-nowrap",
|
|
547
|
+
children: crumb.label
|
|
548
|
+
}), /* @__PURE__ */ jsx(ChevronRightIcon, { className: "w-3 h-3 opacity-60 shrink-0 text-(--theme-muted-text-color)" })] }, `${crumb.label}-${idx}`);
|
|
549
|
+
})
|
|
550
|
+
}),
|
|
551
|
+
titleAction,
|
|
552
|
+
breadcrumbPin?.({ crumbs })
|
|
553
|
+
]
|
|
554
|
+
});
|
|
555
|
+
const actionCluster = actions && /* @__PURE__ */ jsx("div", {
|
|
556
|
+
className: "flex items-center gap-1.5 shrink-0",
|
|
557
|
+
children: actions
|
|
558
|
+
});
|
|
559
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
560
|
+
className: cx(sticky && cx("sticky z-20", stickyTopClassName), "w-full bg-(--theme-app-bg)", className),
|
|
561
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
562
|
+
className: cx("flex items-center justify-between gap-6 px-4 h-11", crumbRow && "border-b border-(--theme-border)"),
|
|
563
|
+
children: [crumbRow || /* @__PURE__ */ jsx("div", {}), actionCluster]
|
|
564
|
+
}), toolbar && /* @__PURE__ */ jsx("div", {
|
|
565
|
+
className: "px-4",
|
|
566
|
+
children: toolbar
|
|
567
|
+
})]
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
//#endregion
|
|
571
|
+
export { AddMenu as S, BreadcrumbProvider as _, HeaderAddButton as a, useHideBreadcrumbs as b, PageHeader as c, copySubmenu as d, rowContextMenuProps as f, useRowMenuActive as g, useRowMenu as h, HeaderActionMenu as i, MoreButton as l, toolbarActionToRowAction as m, BreadcrumbsRightAction as n, HeaderEditButton as o, toRowMenuItem as p, BreadcrumbsTitleAction as r, HeaderRowMenu as s, BreadcrumbsActionButton as t, assembleRowMenu as u, useBreadcrumb as v, useSetBreadcrumbs as x, useClearBreadcrumbs as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AngleDownIcon, AngleRightIcon, CaretDownIcon } from "../icons.js";
|
|
2
|
-
import { c as useStrings } from "./Provider-
|
|
2
|
+
import { c as useStrings } from "./Provider-BIL5347a.js";
|
|
3
3
|
import { n as TOOLTIP_ID } from "./Tooltip-WgbiC_nd.js";
|
|
4
4
|
import cx from "classnames";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CheckIcon, CopyIcon, EyeIcon, EyeOffIcon } from "../icons.js";
|
|
2
|
-
import { c as useStrings, i as useNotify } from "./Provider-
|
|
2
|
+
import { c as useStrings, i as useNotify } from "./Provider-BIL5347a.js";
|
|
3
3
|
import { t as Loader } from "./Loader-BXoXTZGc.js";
|
|
4
4
|
import { t as SwitchToggleSmall } from "./SwitchToggleSmall-FcsaYSTs.js";
|
|
5
5
|
import { c as FieldWrapper, n as flattenGroups, r as impureSetValueFromPath } from "./lib-DTgL8klR.js";
|
|
@@ -9,7 +9,7 @@ import { Suspense, lazy, useMemo, useRef, useState } from "react";
|
|
|
9
9
|
import { convertToDynamicForm, parseStringsOfObj, parseStringsOfObjReady } from "@parallelworks/workflow-parser";
|
|
10
10
|
import { useField, useFormikContext } from "formik";
|
|
11
11
|
//#region src/editor/Editor.tsx
|
|
12
|
-
var MonacoEditor = lazy(() => import("./Monaco-
|
|
12
|
+
var MonacoEditor = lazy(() => import("./Monaco-H1M5hQbJ.js"));
|
|
13
13
|
function Editor({ ...props }) {
|
|
14
14
|
return /* @__PURE__ */ jsx(Suspense, {
|
|
15
15
|
fallback: /* @__PURE__ */ jsx(Loader, { text: "Loading editor..." }),
|