@parallelworks/ui 0.12.1 → 0.14.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.
Files changed (84) hide show
  1. package/dist/chunks/{BareModal-DBa84JZO.js → BareModal-BqroLbZ5.js} +1 -0
  2. package/dist/chunks/{CodePreviewEditor-hwjZof0M.js → CodePreviewEditor-67A_SKgE.js} +1 -1
  3. package/dist/chunks/{CreateModal-DLCC8t_x.js → CreateModal-DoA2WsXf.js} +28 -8
  4. package/dist/chunks/{Monaco-DCwRDrPm.js → Monaco-H56KyEdb.js} +22 -12
  5. package/dist/chunks/{PageHeader-dyoL44ue.js → PageHeader-CxxbidPp.js} +44 -10
  6. package/dist/chunks/{Provider-CfFV-vc5.js → Provider-CbFVFB7O.js} +8 -2
  7. package/dist/chunks/RequiredMark-DfLdYbYZ.js +11 -0
  8. package/dist/chunks/{StatusBadge-P6C2tv7Z.js → StatusBadge-RRUI78iS.js} +4 -4
  9. package/dist/chunks/{SwitchToggle-DcPCXkqL.js → SwitchToggle-DbW0Q__L.js} +49 -32
  10. package/dist/chunks/{Table-ByziK93x.js → Table-CutP1bRt.js} +22 -6
  11. package/dist/chunks/{Tooltip-WgbiC_nd.js → Tooltip-n9w7Tkt1.js} +28 -3
  12. package/dist/chunks/{editor-BH81U5-C.js → editor-BZ9Buwi4.js} +34 -23
  13. package/dist/chunks/lib-DyJvmbzj.js +256 -0
  14. package/dist/chunks/{list-CWVR3dfZ.js → list-CBZpAYP7.js} +35 -15
  15. package/dist/components/Breadcrumbs.d.ts +9 -0
  16. package/dist/components/CollapsiblePanel.d.ts +4 -4
  17. package/dist/components/CreateModal.d.ts +8 -8
  18. package/dist/components/Dropdown.d.ts +5 -3
  19. package/dist/components/Input.d.ts +1 -1
  20. package/dist/components/Listbox.d.ts +7 -4
  21. package/dist/components/Loader.d.ts +1 -1
  22. package/dist/components/MultiSelect.d.ts +8 -5
  23. package/dist/components/PageHeader.d.ts +4 -3
  24. package/dist/components/Pagination.d.ts +2 -2
  25. package/dist/components/Provider.d.ts +9 -3
  26. package/dist/components/RequiredMark.d.ts +1 -0
  27. package/dist/components/SettingRow.d.ts +1 -1
  28. package/dist/components/SwitchToggle.d.ts +3 -2
  29. package/dist/components/Table.d.ts +5 -3
  30. package/dist/components/Tooltip.d.ts +7 -1
  31. package/dist/components/dropdownUtils.d.ts +6 -6
  32. package/dist/editor/FormCodePanel.d.ts +3 -3
  33. package/dist/editor/Monaco.d.ts +2 -2
  34. package/dist/editor/index.js +1 -1
  35. package/dist/file-explorer/FileExplorer.d.ts +2 -2
  36. package/dist/file-explorer/helpers.d.ts +2 -2
  37. package/dist/file-explorer/index.js +46 -18
  38. package/dist/file-explorer/lib/fileExplorer.d.ts +1 -1
  39. package/dist/file-explorer/lib/types.d.ts +21 -21
  40. package/dist/form/FieldWrapper.d.ts +6 -1
  41. package/dist/form/Fields/ResourceOptionIcon.d.ts +1 -1
  42. package/dist/form/Fields/StepField.d.ts +1 -1
  43. package/dist/form/Form.d.ts +28 -27
  44. package/dist/form/SpecialTypes/DropdownWrapper.d.ts +16 -3
  45. package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +11 -11
  46. package/dist/form/SpecialTypes/FormikCustomInput.d.ts +12 -10
  47. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +1 -1
  48. package/dist/form/SpecialTypes/FormikNumericInput.d.ts +2 -2
  49. package/dist/form/Wizard/WizardContainer.d.ts +1 -1
  50. package/dist/form/Wizard/WizardStepContent.d.ts +2 -2
  51. package/dist/form/Wizard/types.d.ts +21 -14
  52. package/dist/form/Wizard/utils.d.ts +1 -1
  53. package/dist/form/fieldContext.d.ts +19 -0
  54. package/dist/form/index.d.ts +2 -1
  55. package/dist/form/index.js +191 -106
  56. package/dist/form/lib.d.ts +3 -3
  57. package/dist/form/types/fieldComponentTypes.d.ts +2 -2
  58. package/dist/form/useParsedOpts.d.ts +1 -1
  59. package/dist/form/utils/getParentValue.d.ts +3 -1
  60. package/dist/form/utils/getValueUsingPath.d.ts +1 -1
  61. package/dist/form/utils/pwResolver.d.ts +4 -4
  62. package/dist/icons.d.ts +8 -8
  63. package/dist/icons.js +4 -4
  64. package/dist/index.d.ts +4 -3
  65. package/dist/index.js +51 -21
  66. package/dist/list/ActionToolbar.d.ts +4 -4
  67. package/dist/list/HoverCard.d.ts +3 -1
  68. package/dist/list/ListPage.d.ts +3 -3
  69. package/dist/list/ListTable.d.ts +1 -1
  70. package/dist/list/RowContextMenu.d.ts +20 -20
  71. package/dist/list/index.js +2 -2
  72. package/dist/logviewer/index.js +24 -7
  73. package/dist/styles/theme.css +6 -6
  74. package/dist/styles.css +1 -1
  75. package/dist/theme/index.js +4 -3
  76. package/dist/workflow/AnnotationBanner.d.ts +2 -1
  77. package/dist/workflow/DependencyGraph.d.ts +15 -3
  78. package/dist/workflow/JobSummary.d.ts +2 -25
  79. package/dist/workflow/MatrixGroup.d.ts +3 -2
  80. package/dist/workflow/TreeView.d.ts +1 -32
  81. package/dist/workflow/index.js +235 -138
  82. package/dist/workflow/types.d.ts +48 -0
  83. package/package.json +2 -6
  84. package/dist/chunks/lib-DTgL8klR.js +0 -191
@@ -60,6 +60,7 @@ function BareModal({ open, onClose, ariaLabel, className, onPanelKeyDown, onPane
60
60
  if (!open) return null;
61
61
  return createPortal(/* @__PURE__ */ jsx("div", {
62
62
  "data-testid": "modal-backdrop",
63
+ role: "none",
63
64
  className: cx("fixed inset-0 z-[9990] flex justify-center px-4 pb-8", align === "center" ? "items-center" : "items-start pt-[14vh]"),
64
65
  style: { backgroundColor: "rgba(0, 0, 0, 0.4)" },
65
66
  onClick: preventClose ? void 0 : onClose,
@@ -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-BH81U5-C.js";
2
+ import { n as defineEditorThemes, r as getThemeName, t as setupMonacoWorkers } from "./editor-BZ9Buwi4.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,9 +1,9 @@
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 } from "./Provider-CfFV-vc5.js";
3
- import { n as TOOLTIP_ID } from "./Tooltip-WgbiC_nd.js";
4
- import { i as filterOption, l as toggleSetMember } from "./StatusBadge-P6C2tv7Z.js";
5
- import { n as modalPanelClasses, t as BareModal } from "./BareModal-DBa84JZO.js";
6
- import { S as AddMenu } from "./PageHeader-dyoL44ue.js";
2
+ import { c as useStrings, i as useNotify } from "./Provider-CbFVFB7O.js";
3
+ import { n as TOOLTIP_ID } from "./Tooltip-n9w7Tkt1.js";
4
+ import { i as filterOption, l as toggleSetMember } from "./StatusBadge-RRUI78iS.js";
5
+ import { n as modalPanelClasses, t as BareModal } from "./BareModal-BqroLbZ5.js";
6
+ import { w as AddMenu } from "./PageHeader-CxxbidPp.js";
7
7
  import cx from "classnames";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Suspense, lazy, useCallback, useEffect, useRef, useState } from "react";
@@ -30,6 +30,7 @@ function Callout({ type, className = "", children }) {
30
30
  //#region src/components/CopyToClipboard.tsx
31
31
  function CopyToClipboard({ as = "div", text, className, children, showIcon = true }) {
32
32
  const notify = useNotify();
33
+ const strings = useStrings();
33
34
  const handleCopy = async () => {
34
35
  try {
35
36
  await navigator.clipboard.writeText(text);
@@ -41,7 +42,17 @@ function CopyToClipboard({ as = "div", text, className, children, showIcon = tru
41
42
  return /* @__PURE__ */ jsxs(as, {
42
43
  className,
43
44
  onClick: handleCopy,
44
- ...as === "button" ? { type: "button" } : {},
45
+ ...as === "button" ? { type: "button" } : {
46
+ role: "button",
47
+ "aria-label": strings.common.copy,
48
+ tabIndex: 0,
49
+ onKeyDown: (e) => {
50
+ if (e.key === "Enter" || e.key === " ") {
51
+ e.preventDefault();
52
+ handleCopy();
53
+ }
54
+ }
55
+ },
45
56
  children: [showIcon && /* @__PURE__ */ jsx(ClipboardIcon, {}), children]
46
57
  });
47
58
  }
@@ -61,6 +72,7 @@ function CopyCodeBlock({ textToCopy, children, secret = false, isRevealed = fals
61
72
  };
62
73
  return /* @__PURE__ */ jsxs("div", {
63
74
  className: "group relative",
75
+ role: "none",
64
76
  onClick: handleCopy,
65
77
  children: [/* @__PURE__ */ jsx("pre", {
66
78
  className: `p-4 theme-hover border rounded-lg text-left font-mono text-sm overflow-x-auto ${secret ? "pr-24" : "pr-12"}`,
@@ -222,7 +234,13 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
222
234
  setFavorite(false);
223
235
  setNameTouched(false);
224
236
  setInteracted(false);
225
- requestAnimationFrame(() => nameRef.current?.focus());
237
+ requestAnimationFrame(() => {
238
+ const input = nameRef.current;
239
+ const dialog = input?.closest("[role=\"dialog\"]");
240
+ const active = document.activeElement;
241
+ if (dialog?.contains(active) && active !== dialog) return;
242
+ input?.focus();
243
+ });
226
244
  }
227
245
  }, [open, initialName]);
228
246
  const nameError = name.trim() ? validateName?.(name.trim()) ?? null : null;
@@ -245,6 +263,8 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
245
263
  let close = false;
246
264
  try {
247
265
  close = await onSubmit(name.trim(), description.trim(), favorite);
266
+ } catch (error) {
267
+ console.error(error);
248
268
  } finally {
249
269
  if (!close) setSubmitting(false);
250
270
  }
@@ -260,7 +280,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
260
280
  if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) handleSubmit();
261
281
  },
262
282
  onPanelMouseDown: (e) => {
263
- if (e.target instanceof Element && !e.target.closest("input, textarea, button, a, select, label")) e.preventDefault();
283
+ if (e.target instanceof Element && !e.target.closest("input, textarea, button, a, select, label, code, pre, .select-all")) e.preventDefault();
264
284
  },
265
285
  children: [/* @__PURE__ */ jsxs("div", {
266
286
  className: "flex-1 min-h-0 overflow-y-auto overscroll-contain",
@@ -1,6 +1,6 @@
1
- import { l as useWorkflowJsonResolver } from "./Provider-CfFV-vc5.js";
1
+ import { l as useWorkflowJsonResolver } from "./Provider-CbFVFB7O.js";
2
2
  import { t as useCssIsDark } from "./useCssIsDark-DHr05dG2.js";
3
- import { n as defineEditorThemes, r as getThemeName, t as setupMonacoWorkers } from "./editor-BH81U5-C.js";
3
+ import { n as defineEditorThemes, r as getThemeName, t as setupMonacoWorkers } from "./editor-BZ9Buwi4.js";
4
4
  import cx from "classnames";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { useEffect, useRef } from "react";
@@ -37,6 +37,16 @@ function ensureMonacoYamlConfigured() {
37
37
  var workflowCompletionContexts = /* @__PURE__ */ new Map();
38
38
  var registeredCompletionProviders = [];
39
39
  var workflowCompletionProvidersRegistered = false;
40
+ var isWorkflowInputs = (value) => typeof value === "object" && value !== null;
41
+ function readExecuteInputs(doc) {
42
+ if (!isWorkflowInputs(doc)) return {};
43
+ const on = doc["on"];
44
+ if (!isWorkflowInputs(on)) return {};
45
+ const execute = on["execute"];
46
+ if (!isWorkflowInputs(execute)) return {};
47
+ const inputs = execute["inputs"];
48
+ return isWorkflowInputs(inputs) ? inputs : {};
49
+ }
40
50
  var noop = () => {};
41
51
  function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop, width = "100%", height = "100%", path = "file:///default", marketplaceItems = [], workflows = [], ...options }) {
42
52
  const isDark = useCssIsDark();
@@ -51,7 +61,7 @@ function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop,
51
61
  if (!monacoRef.current) return;
52
62
  defineEditorThemes(monaco.editor);
53
63
  monaco.editor.setTheme(getThemeName(isDark, disabled));
54
- monacoRef.current.updateOptions({ readOnly });
64
+ monacoRef.current.updateOptions(readOnly === void 0 ? {} : { readOnly });
55
65
  }, [
56
66
  disabled,
57
67
  isDark,
@@ -108,7 +118,7 @@ function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop,
108
118
  automaticLayout: true,
109
119
  model,
110
120
  ...options,
111
- readOnly,
121
+ ...readOnly === void 0 ? {} : { readOnly },
112
122
  fixedOverflowWidgets: true,
113
123
  suggest: {
114
124
  preview: true,
@@ -248,7 +258,7 @@ function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop,
248
258
  let replaceSlash = false;
249
259
  const slashRefMatch = rest.match(/^([^@/]+)\/$/);
250
260
  if (slashRefMatch) {
251
- ghRepo = slashRefMatch[1];
261
+ ghRepo = slashRefMatch[1] ?? "";
252
262
  isRefTrigger = true;
253
263
  replaceSlash = true;
254
264
  } else if (rest.includes("@")) {
@@ -508,7 +518,7 @@ function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop,
508
518
  const response = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${yamlPath}`);
509
519
  if (response.ok) {
510
520
  const text = await response.text();
511
- inputs = yaml.load(text)?.on?.execute?.inputs || {};
521
+ inputs = readExecuteInputs(yaml.load(text));
512
522
  }
513
523
  } catch {}
514
524
  } else {
@@ -518,14 +528,14 @@ function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop,
518
528
  try {
519
529
  const data = await resolveJson(usesValue.startsWith("marketplace/") ? {
520
530
  kind: "marketplace",
521
- slug: usesWorkflowRef[0],
522
- version: usesWorkflowRef.length > 1 ? usesWorkflowRef[1] : "latest"
531
+ slug: usesWorkflowRef[0] ?? "",
532
+ version: usesWorkflowRef[1] ?? "latest"
523
533
  } : {
524
534
  kind: "workflow",
525
- name: usesWorkflowRef[0]
535
+ name: usesWorkflowRef[0] ?? ""
526
536
  });
527
537
  if (!data) return { suggestions: [] };
528
- inputs = data?.on?.execute?.inputs || {};
538
+ inputs = readExecuteInputs(data);
529
539
  } catch {
530
540
  return { suggestions: [] };
531
541
  }
@@ -560,7 +570,7 @@ function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop,
560
570
  let groupidx = 0;
561
571
  try {
562
572
  const basename = groupname;
563
- while (true) if (yaml.load(fullText)?.on?.execute?.inputs?.[groupname]) {
573
+ while (true) if (readExecuteInputs(yaml.load(fullText))[groupname]) {
564
574
  groupidx++;
565
575
  groupname = `${basename}_${groupidx}`;
566
576
  } else break;
@@ -680,7 +690,7 @@ function constructWithSuggestion(inputs, path) {
680
690
  const withSuggestion = {};
681
691
  Object.keys(inputs).map((k) => {
682
692
  const input = inputs[k];
683
- if (input.type === "group" && input.items) withSuggestion[k] = constructWithSuggestion(input.items, path + "." + k);
693
+ if (input?.type === "group" && input.items) withSuggestion[k] = constructWithSuggestion(input.items, path + "." + k);
684
694
  else withSuggestion[k] = "${{ inputs." + path + "." + k + " }}";
685
695
  });
686
696
  return withSuggestion;
@@ -1,6 +1,6 @@
1
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-CfFV-vc5.js";
3
- import { n as TOOLTIP_ID } from "./Tooltip-WgbiC_nd.js";
2
+ import { c as useStrings, i as useNotify, n as useLink, s as useSlots } from "./Provider-CbFVFB7O.js";
3
+ import { n as TOOLTIP_ID } from "./Tooltip-n9w7Tkt1.js";
4
4
  import cx from "classnames";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  import React, { Fragment as Fragment$1, createContext, useCallback, useContext, useEffect, useLayoutEffect, useRef, useState } from "react";
@@ -43,7 +43,8 @@ var BreadcrumbContext = createContext({
43
43
  titleActionSlot: null,
44
44
  setTitleActionSlot: () => {},
45
45
  rightActionSlot: null,
46
- setRightActionSlot: () => {}
46
+ setRightActionSlot: () => {},
47
+ claimedPath: { current: null }
47
48
  });
48
49
  var useBreadcrumb = () => useContext(BreadcrumbContext);
49
50
  function BreadcrumbProvider({ children }) {
@@ -52,6 +53,7 @@ function BreadcrumbProvider({ children }) {
52
53
  const [hidden, setHidden] = React.useState(false);
53
54
  const [titleActionSlot, setTitleActionSlot] = React.useState(null);
54
55
  const [rightActionSlot, setRightActionSlot] = React.useState(null);
56
+ const claimedPath = React.useRef(null);
55
57
  return /* @__PURE__ */ jsx(BreadcrumbContext.Provider, {
56
58
  value: {
57
59
  breadcrumbs,
@@ -63,16 +65,39 @@ function BreadcrumbProvider({ children }) {
63
65
  titleActionSlot,
64
66
  setTitleActionSlot,
65
67
  rightActionSlot,
66
- setRightActionSlot
68
+ setRightActionSlot,
69
+ claimedPath
67
70
  },
68
71
  children
69
72
  });
70
73
  }
71
74
  function useSetBreadcrumbs(getBreadcrumbs) {
72
- const { setBreadcrumbs } = useBreadcrumb();
75
+ const { setBreadcrumbs, claimedPath } = useBreadcrumb();
73
76
  useLayoutEffect(() => {
77
+ claimedPath.current = window.location.pathname;
74
78
  setBreadcrumbs(typeof getBreadcrumbs === "function" ? getBreadcrumbs() : getBreadcrumbs);
75
- }, [getBreadcrumbs, setBreadcrumbs]);
79
+ }, [
80
+ getBreadcrumbs,
81
+ setBreadcrumbs,
82
+ claimedPath
83
+ ]);
84
+ }
85
+ /**
86
+ * For layout routes that derive breadcrumbs from the URL: applies them only
87
+ * while no page under the layout has set its own for the current path.
88
+ * Without this, a layout re-running its effect (for example when the
89
+ * organization's display name loads) overwrote the page's breadcrumbs.
90
+ */
91
+ function useSetDefaultBreadcrumbs(getBreadcrumbs) {
92
+ const { setBreadcrumbs, claimedPath } = useBreadcrumb();
93
+ useLayoutEffect(() => {
94
+ if (claimedPath.current === window.location.pathname) return;
95
+ setBreadcrumbs(typeof getBreadcrumbs === "function" ? getBreadcrumbs() : getBreadcrumbs);
96
+ }, [
97
+ getBreadcrumbs,
98
+ setBreadcrumbs,
99
+ claimedPath
100
+ ]);
76
101
  }
77
102
  var EMPTY_BREADCRUMBS = [];
78
103
  /** For pages that render their own header instead of the breadcrumb strip. */
@@ -218,8 +243,11 @@ function RowContextMenu({ state, onClose, zClassName }) {
218
243
  if (!state) return null;
219
244
  const side = (pos?.left ?? state.x) > window.innerWidth * .6 ? "left" : "right";
220
245
  return createPortal(/* @__PURE__ */ jsx("div", {
246
+ role: "none",
221
247
  className: cx("fixed inset-0", zClassName),
222
- onClick: onClose,
248
+ onClick: (e) => {
249
+ if (e.target === e.currentTarget) onClose();
250
+ },
223
251
  onContextMenu: (e) => {
224
252
  e.preventDefault();
225
253
  if (ref.current?.contains(e.target)) {
@@ -248,7 +276,6 @@ function RowContextMenu({ state, onClose, zClassName }) {
248
276
  top: pos?.top ?? state.y,
249
277
  visibility: pos ? "visible" : "hidden"
250
278
  },
251
- onClick: (e) => e.stopPropagation(),
252
279
  children: /* @__PURE__ */ jsx(MenuItemList, {
253
280
  items: state.items,
254
281
  onClose,
@@ -284,9 +311,16 @@ function MenuRow({ item, onClose, side }) {
284
311
  };
285
312
  return /* @__PURE__ */ jsxs("div", {
286
313
  className: "relative",
314
+ role: "none",
287
315
  onMouseEnter: open,
288
316
  onMouseLeave: close,
289
- children: [/* @__PURE__ */ jsxs("div", {
317
+ onFocus: open,
318
+ onBlur: close,
319
+ children: [/* @__PURE__ */ jsxs("button", {
320
+ type: "button",
321
+ "aria-expanded": openSub,
322
+ "aria-haspopup": "menu",
323
+ onClick: open,
290
324
  className: cx(MENU_ITEM_CLASSES, "justify-between text-(--theme-app)"),
291
325
  children: [/* @__PURE__ */ jsxs("span", {
292
326
  className: "flex items-center gap-2.5",
@@ -577,4 +611,4 @@ function PageHeader({ breadcrumbs, title, titleAction, actions, toolbar, classNa
577
611
  });
578
612
  }
579
613
  //#endregion
580
- 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 };
614
+ export { useSetDefaultBreadcrumbs as C, useSetBreadcrumbs as S, useRowMenuActive as _, HeaderAddButton as a, useClearBreadcrumbs as b, PageHeader as c, assembleRowMenu as d, copySubmenu as f, useRowMenu as g, toolbarActionToRowAction as h, HeaderActionMenu as i, headerActionButtonClasses as l, toRowMenuItem as m, BreadcrumbsRightAction as n, HeaderEditButton as o, rowContextMenuProps as p, BreadcrumbsTitleAction as r, HeaderRowMenu as s, BreadcrumbsActionButton as t, MoreButton as u, BreadcrumbProvider as v, AddMenu as w, useHideBreadcrumbs as x, useBreadcrumb as y };
@@ -51,11 +51,14 @@ var DEFAULTS = {
51
51
  add: "Add",
52
52
  create: "Create",
53
53
  showHiddenFieldsHint: "Includes fields hidden by default because they're specific to each resource, such as name and group.",
54
- jsonHasErrors: "JSON has errors, please fix before saving"
54
+ jsonHasErrors: "JSON has errors, please fix before saving",
55
+ remove: "Remove",
56
+ sort: "Sort"
55
57
  },
56
58
  dropdown: {
57
59
  select: (type) => `Select ${type}`,
58
- noOptionsFound: "No options found"
60
+ noOptionsFound: "No options found",
61
+ showOptions: "Show options"
59
62
  },
60
63
  logviewer: {
61
64
  error: "Error:",
@@ -94,6 +97,9 @@ var DEFAULTS = {
94
97
  submitted: "Submitted",
95
98
  expandAll: "Expand all",
96
99
  collapseAll: "Collapse all",
100
+ loadingLogs: "Loading logs",
101
+ noLogFound: "No log found",
102
+ logLoadFailed: "Log could not be loaded",
97
103
  statusLabel: (status) => status,
98
104
  statusReason: () => void 0
99
105
  },
@@ -0,0 +1,11 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ //#region src/components/RequiredMark.tsx
3
+ function RequiredMark() {
4
+ return /* @__PURE__ */ jsx("span", {
5
+ "aria-hidden": "true",
6
+ className: "text-red-500 ml-0.5",
7
+ children: "*"
8
+ });
9
+ }
10
+ //#endregion
11
+ export { RequiredMark as t };
@@ -101,10 +101,10 @@ function DropdownCaret() {
101
101
  //#region src/components/StatusBadge.tsx
102
102
  var variantStyles = {
103
103
  default: "bg-(--theme-muted-panel-bg) text-(--theme-app) border-(--theme-border)",
104
- success: "bg-emerald-500/10 text-emerald-500 border-emerald-500/20",
105
- warning: "bg-amber-500/10 text-amber-500 border-amber-500/20",
106
- error: "bg-red-500/10 text-red-500 border-red-500/20",
107
- info: "bg-blue-500/10 text-blue-500 border-blue-500/20",
104
+ success: "bg-emerald-500/10 text-emerald-800 dark:text-emerald-400 border-emerald-500/20",
105
+ warning: "bg-amber-500/10 text-amber-800 dark:text-amber-400 border-amber-500/20",
106
+ error: "bg-red-500/10 text-red-800 dark:text-red-400 border-red-500/20",
107
+ info: "bg-blue-500/10 text-blue-800 dark:text-blue-400 border-blue-500/20",
108
108
  muted: "bg-(--theme-muted-panel-bg)/50 text-(--theme-muted-text-color) border-(--theme-border)"
109
109
  };
110
110
  var pulseColors = {
@@ -1,7 +1,7 @@
1
1
  import { AngleDownIcon, AngleRightIcon, CaretDownIcon } from "../icons.js";
2
- import { c as useStrings } from "./Provider-CfFV-vc5.js";
3
- import { n as TOOLTIP_ID } from "./Tooltip-WgbiC_nd.js";
4
- import { a as flattenDisplayOptions, c as isOption, i as filterOption, l as toggleSetMember, o as flattenOptions, r as DropdownCaret, s as isCategory } from "./StatusBadge-P6C2tv7Z.js";
2
+ import { c as useStrings } from "./Provider-CbFVFB7O.js";
3
+ import { a as truncationTooltipProps, n as TOOLTIP_ID } from "./Tooltip-n9w7Tkt1.js";
4
+ import { a as flattenDisplayOptions, c as isOption, i as filterOption, l as toggleSetMember, o as flattenOptions, r as DropdownCaret, s as isCategory } from "./StatusBadge-RRUI78iS.js";
5
5
  import cx from "classnames";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -12,6 +12,12 @@ import { usePopper } from "react-popper";
12
12
  import AnimateHeight from "react-animate-height";
13
13
  //#region src/components/Dropdown.tsx
14
14
  var defaultCollapsedLabel = (count) => `${count} more`;
15
+ function isResourceValue(value) {
16
+ if (typeof value !== "object" || value === null || !("name" in value)) return false;
17
+ if (typeof value.name !== "string") return false;
18
+ if ("$type" in value && value.$type === "computeResource") return true;
19
+ return "type" in value && (value.type === "computeResource" || value.type === "bucket");
20
+ }
15
21
  var checkEquals = (val, opt) => {
16
22
  if (typeof val === "object" && !Array.isArray(val)) return deepEqual(val, opt);
17
23
  return val === opt;
@@ -35,7 +41,7 @@ function getOptionFromValue(value, options) {
35
41
  value
36
42
  };
37
43
  else return found;
38
- const isResourceObject = value && typeof value === "object" && "name" in value && (value.$type === "computeResource" || value.type === "computeResource" || value.type === "bucket");
44
+ const isResourceObject = isResourceValue(value);
39
45
  const fallbackLabel = typeof value === "string" ? value : isResourceObject ? value.name : JSON.stringify(value);
40
46
  return {
41
47
  label: fallbackLabel,
@@ -89,12 +95,7 @@ function ActiveWatcher({ active, onChange }) {
89
95
  function OptionContent({ label, description, icon }) {
90
96
  return /* @__PURE__ */ jsxs("span", {
91
97
  className: cx("flex gap-1.5", description ? "items-start min-w-0" : "items-center truncate"),
92
- "data-tooltip-id": TOOLTIP_ID,
93
- onMouseEnter: (e) => {
94
- const inner = e.currentTarget.lastElementChild;
95
- if (inner && inner.scrollWidth > inner.clientWidth) e.currentTarget.setAttribute("data-tooltip-content", label);
96
- else e.currentTarget.removeAttribute("data-tooltip-content");
97
- },
98
+ ...truncationTooltipProps(label, (anchor) => anchor.lastElementChild),
98
99
  children: [icon, description ? /* @__PURE__ */ jsxs("span", {
99
100
  className: "flex flex-col min-w-0",
100
101
  children: [/* @__PURE__ */ jsx("span", {
@@ -130,8 +131,9 @@ function ToggleOption({ option, category, expanded, onToggle, ...virtualRowProps
130
131
  })
131
132
  });
132
133
  }
133
- function DropdownHelper({ wrapperClassName = "w-full", className, textBoxClassName = "w-full", options = [], onChange, onActiveChange, value, id, ariaLabel, disabled = false, placeholder = "", loading = false, allowCustomValue = false, customValueLabel = "Use", collapsedLabel = defaultCollapsedLabel, portalEl }) {
134
+ function DropdownHelper({ wrapperClassName = "w-full", className, textBoxClassName = "w-full", options = [], onChange, onActiveChange, value, id, ariaLabel, "aria-describedby": describedBy, required, disabled = false, placeholder = "", loading = false, allowCustomValue = false, customValueLabel = "Use", collapsedLabel = defaultCollapsedLabel, portalEl }) {
134
135
  const DEBOUNCE_MS = 500;
136
+ const t = useStrings().dropdown;
135
137
  const [query, setQuery] = useState("");
136
138
  const [selectedIconWidth, setSelectedIconWidth] = useState(0);
137
139
  const selectedIconRef = useCallback((node) => {
@@ -170,10 +172,12 @@ function DropdownHelper({ wrapperClassName = "w-full", className, textBoxClassNa
170
172
  phase: "beforeWrite",
171
173
  requires: ["computeStyles"],
172
174
  fn: ({ state }) => {
173
- state.styles.popper.width = `${state.rects.reference.width}px`;
175
+ const popperStyles = state.styles["popper"];
176
+ if (popperStyles) popperStyles.width = `${state.rects.reference.width}px`;
174
177
  },
175
178
  effect: ({ state }) => {
176
- state.elements.popper.style.width = `${state.elements.reference.offsetWidth}px`;
179
+ const { popper, reference } = state.elements;
180
+ if (reference instanceof HTMLElement) popper.style.width = `${reference.offsetWidth}px`;
177
181
  }
178
182
  }), []);
179
183
  const { styles, attributes } = usePopper(referenceElement, popperElement, {
@@ -251,9 +255,9 @@ function DropdownHelper({ wrapperClassName = "w-full", className, textBoxClassNa
251
255
  ]);
252
256
  const comboOptions = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(ComboboxOptions, {
253
257
  ref: setPopperElement,
254
- style: styles.popper,
258
+ style: styles["popper"],
255
259
  className: "bg-(--theme-input-bg) border-(--theme-border) text-(--theme-app) max-h-60! empty:invisible border overflow-auto rounded-md shadow-lg focus:outline-hidden sm:text-sm z-9999 data-[popper-reference-hidden=true]:invisible data-[popper-reference-hidden=true]:pointer-events-none",
256
- ...attributes.popper,
260
+ ...attributes["popper"],
257
261
  children: ({ option }) => {
258
262
  const optionLabel = typeof option === "string" ? option : option.label;
259
263
  const optionDescription = typeof option !== "string" ? option.description : void 0;
@@ -309,6 +313,8 @@ function DropdownHelper({ wrapperClassName = "w-full", className, textBoxClassNa
309
313
  /* @__PURE__ */ jsx(ComboboxInput, {
310
314
  id,
311
315
  "aria-label": ariaLabel || void 0,
316
+ "aria-describedby": describedBy,
317
+ "aria-required": required || void 0,
312
318
  placeholder: loading ? "Loading..." : placeholder,
313
319
  onBlur: onInputBlur,
314
320
  ref: setReferenceElement,
@@ -326,6 +332,7 @@ function DropdownHelper({ wrapperClassName = "w-full", className, textBoxClassNa
326
332
  }),
327
333
  /* @__PURE__ */ jsx(ComboboxButton, {
328
334
  ref: buttonRef,
335
+ "aria-label": t.showOptions,
329
336
  className: "absolute inset-y-0 right-0 flex items-center pr-3 disabled:cursor-not-allowed",
330
337
  "data-testid": "combobox-button",
331
338
  disabled,
@@ -338,7 +345,7 @@ function DropdownHelper({ wrapperClassName = "w-full", className, textBoxClassNa
338
345
  }
339
346
  //#endregion
340
347
  //#region src/components/Listbox.tsx
341
- function CustomListbox({ options = [], handleOptionSelected, type, allowSearch = false, closeOnSelect = true, className = "", invalid = false }) {
348
+ function CustomListbox({ options = [], handleOptionSelected, type, allowSearch = false, closeOnSelect = true, className = "", invalid = false, required = false, id, "aria-describedby": describedBy }) {
342
349
  const { dropdown: strings } = useStrings();
343
350
  const [filter, setFilter] = useState("");
344
351
  const [controlledOpen, setControlledOpen] = useState(false);
@@ -426,6 +433,9 @@ function CustomListbox({ options = [], handleOptionSelected, type, allowSearch =
426
433
  ref: wrapperRef,
427
434
  onChange: handleOptionSelected,
428
435
  children: [/* @__PURE__ */ jsxs(ListboxButton, {
436
+ id,
437
+ "aria-describedby": describedBy,
438
+ "aria-required": required || void 0,
429
439
  onClick: () => setControlledOpen((prev) => !prev),
430
440
  className: cx("relative w-full py-2 pl-3 text-left", invalid && "border-red-600 focus:border-red-600 focus:ring-red-500"),
431
441
  children: [/* @__PURE__ */ jsx("span", {
@@ -448,7 +458,7 @@ function CustomListbox({ options = [], handleOptionSelected, type, allowSearch =
448
458
  }
449
459
  //#endregion
450
460
  //#region src/components/MultiSelect.tsx
451
- function MultiSelectDropdown({ options, value, onChange, id, className, wrapperClassName = "w-full", textBoxClassName, disabled = false, placeholder, loading = false, searchable = true, maxTagCount = 2, compareBy }) {
461
+ function MultiSelectDropdown({ options, value, onChange, id, "aria-labelledby": labelledBy, "aria-describedby": describedBy, required, className, wrapperClassName = "w-full", textBoxClassName, disabled = false, placeholder, loading = false, searchable = true, maxTagCount = 2, compareBy }) {
452
462
  const strings = useStrings();
453
463
  const [query, setQuery] = useState("");
454
464
  const [referenceEl, setReferenceEl] = useState(null);
@@ -514,6 +524,9 @@ function MultiSelectDropdown({ options, value, onChange, id, className, wrapperC
514
524
  /* @__PURE__ */ jsx(ComboboxButton, {
515
525
  as: "div",
516
526
  id,
527
+ "aria-labelledby": labelledBy,
528
+ "aria-describedby": describedBy,
529
+ "aria-required": required || void 0,
517
530
  className: cx("theme-input flex items-center cursor-pointer rounded border text-[14px] w-full px-2 pr-8 py-1 min-h-[30px] overflow-hidden", isDisabled && "opacity-50 cursor-not-allowed", textBoxClassName, className),
518
531
  children: loading ? /* @__PURE__ */ jsx("span", {
519
532
  className: "theme-muted-text",
@@ -534,8 +547,8 @@ function MultiSelectDropdown({ options, value, onChange, id, className, wrapperC
534
547
  ref: setPopperEl,
535
548
  static: true,
536
549
  "data-testid": "msd-list",
537
- style: styles.popper,
538
- ...attributes.popper,
550
+ style: styles["popper"],
551
+ ...attributes["popper"],
539
552
  className: "theme-panel z-10 max-h-60 w-full overflow-auto rounded-md shadow-lg focus:outline-none",
540
553
  children: [searchable && /* @__PURE__ */ jsx("div", {
541
554
  className: "sticky top-0 theme-panel p-2 border-b z-10",
@@ -564,7 +577,7 @@ function MultiSelectDropdown({ options, value, onChange, id, className, wrapperC
564
577
  const option = opt;
565
578
  return /* @__PURE__ */ jsx(ComboboxOption, {
566
579
  value: option.value,
567
- disabled: option.disabled,
580
+ disabled: option.disabled ?? false,
568
581
  "data-testid": `msd-option-${String(option.value)}`,
569
582
  className: ({ focus }) => cx("relative cursor-pointer select-none py-2 pl-10 pr-4 text-sm", focus && "theme-hover", option.disabled && "cursor-not-allowed opacity-50"),
570
583
  children: ({ selected }) => /* @__PURE__ */ jsxs("div", {
@@ -577,6 +590,7 @@ function MultiSelectDropdown({ options, value, onChange, id, className, wrapperC
577
590
  type: "checkbox",
578
591
  checked: selected,
579
592
  readOnly: true,
593
+ tabIndex: -1,
580
594
  className: "h-4 w-4 cursor-pointer",
581
595
  "aria-hidden": "true"
582
596
  })
@@ -610,6 +624,7 @@ function ControlledCollapsiblePanel({ title = "", children, open, setOpen, onCli
610
624
  if (onClick) onClick();
611
625
  setOpen?.((open) => !open);
612
626
  }, [setOpen, onClick]);
627
+ const contentId = React.useId();
613
628
  const Wrapper = wrapperElement ? wrapperElement : React.Fragment;
614
629
  return React.isValidElement(title) ? /* @__PURE__ */ jsxs(Fragment, { children: [title, /* @__PURE__ */ jsx(Wrapper, { children: /* @__PURE__ */ jsx(AnimateHeight, {
615
630
  duration: 300,
@@ -619,20 +634,19 @@ function ControlledCollapsiblePanel({ title = "", children, open, setOpen, onCli
619
634
  className: cx("border border-solid rounded-2xl border-(--theme-border) bg-(--theme-panel-bg) text-(--theme-panel) mb-1 w-full", className),
620
635
  children: [/* @__PURE__ */ jsxs("div", {
621
636
  className: cx(!open && "text-(--theme-muted-text-color)", "w-full flex items-center justify-between transform ease-in transition text-sm py-3 px-2 cursor-pointer"),
622
- onClick: toggleOpen,
623
- children: [/* @__PURE__ */ jsxs("div", {
624
- className: "flex items-center w-full",
637
+ children: [/* @__PURE__ */ jsxs("button", {
638
+ type: "button",
639
+ "aria-expanded": !!open,
640
+ "aria-controls": contentId,
641
+ className: "flex items-center w-full text-left cursor-pointer",
642
+ onClick: toggleOpen,
625
643
  children: [/* @__PURE__ */ jsx(AngleRightIcon, { className: cx(open && "transform rotate-90", "px-1 ml-1 text-[1.25rem] transition ease-in") }), /* @__PURE__ */ jsx("span", {
626
644
  className: "px-2 font-bold select-none",
627
645
  children: title?.toString()
628
646
  })]
629
- }), /* @__PURE__ */ jsx("div", {
630
- onClick: (e) => {
631
- e.stopPropagation();
632
- },
633
- children: customizedButton
634
- })]
647
+ }), /* @__PURE__ */ jsx("div", { children: customizedButton })]
635
648
  }), /* @__PURE__ */ jsx(AnimateHeight, {
649
+ id: contentId,
636
650
  duration: 300,
637
651
  height: open ? "auto" : 0,
638
652
  children
@@ -675,7 +689,7 @@ function SectionHeader({ children, className = "" }) {
675
689
  }
676
690
  //#endregion
677
691
  //#region src/components/SwitchToggle.tsx
678
- function SwitchToggle({ onChange, id, value = void 0, yesLabel = "Yes", noLabel = "No", disabled = false, datatip = "", invalid = false }) {
692
+ function SwitchToggle({ onChange, id, "aria-describedby": describedBy, value = void 0, yesLabel = "Yes", noLabel = "No", disabled = false, datatip = "", invalid = false }) {
679
693
  const [enabled, setEnabled] = useState(value ?? false);
680
694
  const [isFocused, setIsFocused] = useState(false);
681
695
  const setIsEnabled = (e) => {
@@ -687,11 +701,14 @@ function SwitchToggle({ onChange, id, value = void 0, yesLabel = "Yes", noLabel
687
701
  }, [value]);
688
702
  const checked = value ?? enabled;
689
703
  return /* @__PURE__ */ jsx("div", {
690
- "data-tooltip-content": datatip || void 0,
691
- "data-tooltip-id": datatip ? TOOLTIP_ID : void 0,
704
+ ...datatip ? {
705
+ "data-tooltip-content": datatip,
706
+ "data-tooltip-id": TOOLTIP_ID
707
+ } : {},
692
708
  className: cx("w-[198px] h-[30px] overflow-hidden shadow-sm rounded-md cursor-pointer ring-(--theme-border) ring-1", invalid && "border-red-600 focus:border-red-600 focus:ring-red-500 ring-1 ring-red-500", !invalid && isFocused && "ring-1 ring-[rgba(82,168,236,.8)] drop-shadow-[0_1px_2px_rgba(82,168,236,0.8)]"),
693
709
  children: /* @__PURE__ */ jsx(Switch, {
694
710
  id,
711
+ "aria-describedby": describedBy,
695
712
  checked,
696
713
  onChange: setIsEnabled,
697
714
  className: "text-white text-sm shadow-sm rounded-md cursor-pointer",
@@ -1,3 +1,4 @@
1
+ import { c as useStrings } from "./Provider-CbFVFB7O.js";
1
2
  import { t as Loader } from "./Loader-BXoXTZGc.js";
2
3
  import cx from "classnames";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -21,14 +22,22 @@ function CompactItem({ wrap = false, children, className, colspan = 1, ...tdProp
21
22
  children
22
23
  });
23
24
  }
24
- function Header({ children, className, style, colspan = 1, onClick, caps = true }) {
25
+ function Header({ children, className, style, colspan = 1, onClick, sort, caps = true }) {
26
+ const yPadding = className?.includes("py-") ? "" : "py-3";
27
+ const xPadding = className?.includes("px-") ? "" : "px-3";
28
+ const textAlign = className?.includes("text-") ? "" : "text-left";
25
29
  return /* @__PURE__ */ jsx("th", {
26
30
  scope: "col",
27
31
  colSpan: colspan,
28
32
  style,
29
- className: cx(className, className?.includes("py-") ? "" : "py-3", className?.includes("px-") ? "" : "px-3", className?.includes("text-") ? "" : "text-left", "text-xs font-medium", caps ? "uppercase tracking-wider" : "", onClick && "cursor-pointer hover:opacity-80 transition-opacity"),
30
- onClick,
31
- children
33
+ "aria-sort": sort === "unsorted" ? "none" : sort,
34
+ className: cx(className, yPadding, xPadding, textAlign, "text-xs font-medium", caps ? "uppercase tracking-wider" : ""),
35
+ children: onClick ? /* @__PURE__ */ jsx("button", {
36
+ type: "button",
37
+ onClick,
38
+ className: "w-full cursor-pointer text-inherit [text-align:inherit] hover:opacity-80 transition-opacity",
39
+ children
40
+ }) : children
32
41
  });
33
42
  }
34
43
  var isHeaderChild = (child) => {
@@ -37,13 +46,20 @@ var isHeaderChild = (child) => {
37
46
  };
38
47
  var getHeaders = (children) => children.filter(isHeaderChild);
39
48
  function Table({ borderless = false, panel = true, className = "", wrapperClassName = "", tbodyClassName = "divide-y", theadClassName = "theme-muted-panel", children, roundedTop = false, rounded = false, roundedBottom = false, isLoading = false, tableProps }) {
49
+ const { loading } = useStrings();
40
50
  const ChildrenArr = React.Children.toArray(children);
41
51
  const Headers = getHeaders(ChildrenArr);
42
52
  return /* @__PURE__ */ jsx("div", {
53
+ "aria-busy": isLoading,
43
54
  className: cx("flex flex-col w-full", !wrapperClassName.split(" ").some((cls) => cls.startsWith("overflow-")) && "overflow-hidden", wrapperClassName),
44
- children: isLoading ? /* @__PURE__ */ jsx("div", {
55
+ children: isLoading ? /* @__PURE__ */ jsxs("div", {
56
+ role: "status",
57
+ "aria-label": loading,
45
58
  className: "flex justify-center items-center h-32",
46
- children: /* @__PURE__ */ jsx(Loader, {})
59
+ children: [/* @__PURE__ */ jsx(Loader, {}), /* @__PURE__ */ jsx("span", {
60
+ className: "sr-only",
61
+ children: loading
62
+ })]
47
63
  }) : /* @__PURE__ */ jsx("div", {
48
64
  className: cx("align-middle inline-block min-w-full overflow-x-auto", panel && "theme-panel", !borderless && "border theme-border", rounded && "rounded-2xl", roundedBottom && "rounded-b-2xl", roundedTop && "rounded-t-2xl"),
49
65
  children: /* @__PURE__ */ jsxs("table", {