@parallelworks/ui 0.1.0 → 0.3.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 (146) hide show
  1. package/dist/assets/editor.worker-CuBRIwi-.js +14776 -0
  2. package/dist/assets/json.worker-8ytS02vz.js +22161 -0
  3. package/dist/assets/yaml.worker-DJC-VUcv.js +48367 -0
  4. package/dist/chunks/CodePreviewEditor-CSPRILMp.js +61 -0
  5. package/dist/chunks/Indicator-hBSIxOPK.js +39 -0
  6. package/dist/chunks/Loader-DQiZ75fa.js +25 -0
  7. package/dist/chunks/Markdown-C5Re2ezs.js +101 -0
  8. package/dist/chunks/MarkdownImpl-Bq4QhrtA.js +33 -0
  9. package/dist/chunks/Modal-sOUEwebV.js +121 -0
  10. package/dist/chunks/Monaco-CC4ak1JG.js +717 -0
  11. package/dist/chunks/Provider-DvVvScTQ.js +391 -0
  12. package/dist/chunks/StatusBadge-DXp4zkSd.js +46 -0
  13. package/dist/chunks/SwitchToggle-2uRw8ZeJ.js +725 -0
  14. package/dist/chunks/SwitchToggleSmall-FcsaYSTs.js +14 -0
  15. package/dist/chunks/Table-C5z6qWjM.js +91 -0
  16. package/dist/chunks/Tooltip-WgbiC_nd.js +71 -0
  17. package/dist/chunks/editor-D55tumuZ.js +372 -0
  18. package/dist/chunks/lib-DTgL8klR.js +191 -0
  19. package/dist/chunks/list-7PyDF1tz.js +465 -0
  20. package/dist/components/CollapsiblePanel.d.ts +27 -0
  21. package/dist/components/CopyToClipboard.d.ts +17 -0
  22. package/dist/components/Dropdown.d.ts +24 -0
  23. package/dist/components/Indicator.d.ts +4 -0
  24. package/dist/components/Listbox.d.ts +18 -0
  25. package/dist/components/Markdown.d.ts +7 -0
  26. package/dist/components/MarkdownImpl.d.ts +2 -0
  27. package/dist/components/MultiSelect.d.ts +19 -0
  28. package/dist/components/Overview.d.ts +12 -0
  29. package/dist/components/Provider.d.ts +438 -0
  30. package/dist/components/SectionHeader.d.ts +6 -0
  31. package/dist/components/SwitchToggle.d.ts +12 -0
  32. package/dist/components/SwitchToggleSmall.d.ts +6 -0
  33. package/dist/components/dropdownUtils.d.ts +18 -0
  34. package/dist/editor/Editor.d.ts +2 -0
  35. package/dist/editor/EditorField.d.ts +11 -0
  36. package/dist/editor/FormCodePanel.d.ts +8 -0
  37. package/dist/editor/Monaco.d.ts +31 -0
  38. package/dist/editor/index.d.ts +7 -0
  39. package/dist/editor/index.js +2 -0
  40. package/dist/editor/themes.d.ts +4 -0
  41. package/dist/editor/useCssIsDark.d.ts +6 -0
  42. package/dist/editor/workers.d.ts +6 -0
  43. package/dist/file-explorer/FileExplorer.d.ts +23 -0
  44. package/dist/file-explorer/FileExplorerContext.d.ts +17 -0
  45. package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +6 -0
  46. package/dist/file-explorer/FilePreview/Inline.d.ts +13 -0
  47. package/dist/file-explorer/FilePreview/StreamedBadge.d.ts +1 -0
  48. package/dist/file-explorer/FilePreview/Viewer.d.ts +15 -0
  49. package/dist/file-explorer/FilePreview/index.d.ts +15 -0
  50. package/dist/file-explorer/FilePreview/parse.d.ts +24 -0
  51. package/dist/file-explorer/FilePreview/previewCache.d.ts +26 -0
  52. package/dist/file-explorer/FilePreview/previewType.d.ts +21 -0
  53. package/dist/file-explorer/FilePreview/readCappedBytes.d.ts +37 -0
  54. package/dist/file-explorer/FilePreview/useObjectBlobUrl.d.ts +16 -0
  55. package/dist/file-explorer/FilePreview/useObjectText.d.ts +23 -0
  56. package/dist/file-explorer/FilePreview/usePresignedUrl.d.ts +12 -0
  57. package/dist/file-explorer/FileRow.d.ts +35 -0
  58. package/dist/file-explorer/FileRowsWindow.d.ts +43 -0
  59. package/dist/file-explorer/FileTable.d.ts +26 -0
  60. package/dist/file-explorer/FileTableHeaders.d.ts +13 -0
  61. package/dist/file-explorer/LoadMoreRow.d.ts +15 -0
  62. package/dist/file-explorer/TreeView.d.ts +28 -0
  63. package/dist/file-explorer/helpers.d.ts +47 -0
  64. package/dist/file-explorer/index.d.ts +10 -0
  65. package/dist/file-explorer/index.js +5646 -0
  66. package/dist/file-explorer/lib/batch.d.ts +3 -0
  67. package/dist/file-explorer/lib/errors.d.ts +3 -0
  68. package/dist/file-explorer/lib/fileExplorer.d.ts +32 -0
  69. package/dist/file-explorer/lib/paging.d.ts +93 -0
  70. package/dist/file-explorer/lib/types.d.ts +92 -0
  71. package/dist/file-explorer/lib/utils.d.ts +37 -0
  72. package/dist/file-explorer/toasts.d.ts +9 -0
  73. package/dist/file-explorer/treeRows.d.ts +35 -0
  74. package/dist/file-explorer/useNearEnd.d.ts +7 -0
  75. package/dist/form/FieldWrapper.d.ts +10 -0
  76. package/dist/form/Fields/BooleanField.d.ts +12 -0
  77. package/dist/form/Fields/BucketReadOnlyField.d.ts +7 -0
  78. package/dist/form/Fields/CheckboxGroupField.d.ts +18 -0
  79. package/dist/form/Fields/ColorField.d.ts +8 -0
  80. package/dist/form/Fields/DropdownField.d.ts +24 -0
  81. package/dist/form/Fields/DurationField.d.ts +13 -0
  82. package/dist/form/Fields/LabelField.d.ts +9 -0
  83. package/dist/form/Fields/MultiDropdownField.d.ts +18 -0
  84. package/dist/form/Fields/NumberField.d.ts +13 -0
  85. package/dist/form/Fields/ObjectField.d.ts +8 -0
  86. package/dist/form/Fields/RadioField.d.ts +9 -0
  87. package/dist/form/Fields/RangeField.d.ts +11 -0
  88. package/dist/form/Fields/ResourceOptionIcon.d.ts +11 -0
  89. package/dist/form/Fields/StepField.d.ts +3 -0
  90. package/dist/form/Fields/StringField.d.ts +17 -0
  91. package/dist/form/Fields/TextAreaField.d.ts +8 -0
  92. package/dist/form/Fields/durationValidity.d.ts +2 -0
  93. package/dist/form/Form.d.ts +105 -0
  94. package/dist/form/SpecialTypes/DropdownWrapper.d.ts +14 -0
  95. package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +53 -0
  96. package/dist/form/SpecialTypes/FormikCustomInput.d.ts +17 -0
  97. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +13 -0
  98. package/dist/form/SpecialTypes/FormikNumericInput.d.ts +9 -0
  99. package/dist/form/SpecialTypes/index.d.ts +3 -0
  100. package/dist/form/Wizard/WizardContainer.d.ts +5 -0
  101. package/dist/form/Wizard/WizardNavigation.d.ts +2 -0
  102. package/dist/form/Wizard/WizardStepContent.d.ts +8 -0
  103. package/dist/form/Wizard/WizardStepIndicator.d.ts +2 -0
  104. package/dist/form/Wizard/types.d.ts +171 -0
  105. package/dist/form/Wizard/useWizardState.d.ts +28 -0
  106. package/dist/form/Wizard/utils.d.ts +2 -0
  107. package/dist/form/fieldRegistry.d.ts +7 -0
  108. package/dist/form/index.d.ts +16 -0
  109. package/dist/form/index.js +2319 -0
  110. package/dist/form/lib.d.ts +15 -0
  111. package/dist/form/types/fieldComponentTypes.d.ts +32 -0
  112. package/dist/form/types/fieldTypes.d.ts +80 -0
  113. package/dist/form/types/workflow-schema.d.ts +1107 -0
  114. package/dist/form/useParsedOpts.d.ts +5 -0
  115. package/dist/form/usePrevious.d.ts +1 -0
  116. package/dist/form/utils/checkShowIfObject.d.ts +1 -0
  117. package/dist/form/utils/getParentValue.d.ts +1 -0
  118. package/dist/form/utils/getPlaceholder.d.ts +2 -0
  119. package/dist/form/utils/getValueUsingPath.d.ts +1 -0
  120. package/dist/form/utils/pwResolver.d.ts +18 -0
  121. package/dist/form/utils/secondaryField.d.ts +8 -0
  122. package/dist/form/utils/slurmDuration.d.ts +15 -0
  123. package/dist/icons.d.ts +1 -1
  124. package/dist/icons.js +2 -2
  125. package/dist/index.d.ts +17 -0
  126. package/dist/index.js +42 -350
  127. package/dist/list/ListTable.d.ts +63 -0
  128. package/dist/list/RowContextMenu.d.ts +113 -0
  129. package/dist/list/index.d.ts +2 -0
  130. package/dist/list/index.js +2 -0
  131. package/dist/logviewer/LogViewer.d.ts +18 -0
  132. package/dist/logviewer/index.d.ts +1 -0
  133. package/dist/logviewer/index.js +534 -0
  134. package/dist/logviewer/logviewer.css +70 -0
  135. package/dist/styles/theme.css +30 -0
  136. package/dist/styles.css +1 -1
  137. package/dist/workflow/AnnotationBanner.d.ts +5 -0
  138. package/dist/workflow/Collapse.d.ts +6 -0
  139. package/dist/workflow/DependencyGraph.d.ts +15 -0
  140. package/dist/workflow/JobSummary.d.ts +38 -0
  141. package/dist/workflow/MatrixGroup.d.ts +41 -0
  142. package/dist/workflow/Reveal.d.ts +7 -0
  143. package/dist/workflow/TreeView.d.ts +42 -0
  144. package/dist/workflow/index.d.ts +1 -0
  145. package/dist/workflow/index.js +2331 -0
  146. package/package.json +71 -6
@@ -0,0 +1,61 @@
1
+ import { i as getThemeName, n as setupMonacoWorkers, r as defineEditorThemes, t as useCssIsDark } from "./editor-D55tumuZ.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useRef } from "react";
4
+ import * as monaco from "monaco-editor";
5
+ //#region src/file-explorer/FilePreview/CodePreviewEditor.tsx
6
+ var OPTIONS = {
7
+ readOnly: true,
8
+ domReadOnly: true,
9
+ automaticLayout: true,
10
+ minimap: { enabled: false },
11
+ scrollBeyondLastLine: false,
12
+ renderLineHighlight: "none",
13
+ overviewRulerLanes: 0,
14
+ hideCursorInOverviewRuler: true,
15
+ lineNumbers: "on",
16
+ wordWrap: "off",
17
+ fontSize: 12,
18
+ scrollbar: { alwaysConsumeMouseWheel: false }
19
+ };
20
+ setupMonacoWorkers();
21
+ function CodePreviewEditor({ value, language }) {
22
+ const isDark = useCssIsDark();
23
+ const editorRef = useRef(null);
24
+ useEffect(() => {
25
+ return () => {
26
+ editorRef.current?.getModel()?.dispose();
27
+ editorRef.current?.dispose();
28
+ editorRef.current = null;
29
+ };
30
+ }, []);
31
+ useEffect(() => {
32
+ const model = editorRef.current?.getModel();
33
+ if (model && model.getValue() !== value) model.setValue(value);
34
+ }, [value]);
35
+ useEffect(() => {
36
+ const model = editorRef.current?.getModel();
37
+ if (model) monaco.editor.setModelLanguage(model, language);
38
+ }, [language]);
39
+ useEffect(() => {
40
+ if (editorRef.current) {
41
+ defineEditorThemes(monaco.editor);
42
+ monaco.editor.setTheme(getThemeName(isDark));
43
+ }
44
+ }, [isDark]);
45
+ return /* @__PURE__ */ jsx("div", {
46
+ className: "h-full w-full",
47
+ ref: (container) => {
48
+ if (container && !editorRef.current) {
49
+ defineEditorThemes(monaco.editor);
50
+ const model = monaco.editor.createModel(value, language);
51
+ editorRef.current = monaco.editor.create(container, {
52
+ ...OPTIONS,
53
+ model
54
+ });
55
+ monaco.editor.setTheme(getThemeName(isDark));
56
+ }
57
+ }
58
+ });
59
+ }
60
+ //#endregion
61
+ export { CodePreviewEditor as default };
@@ -0,0 +1,39 @@
1
+ import { CancelIcon, FailIcon, NotRunningIcon, RunningIcon, SkipIcon, SuccessIcon } from "../icons.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/Indicator.tsx
4
+ function Indicator({ status }) {
5
+ return /* @__PURE__ */ jsx("div", {
6
+ className: "h-2 flex items-center text-(--theme-panel-bg)",
7
+ children: status === "started" || status === "running" ? /* @__PURE__ */ jsx(RunningIcon, {
8
+ className: "rounded-full text-[#FFCF00] animate-spin",
9
+ "data-testid": "running-indicator"
10
+ }) : status === "completed" ? /* @__PURE__ */ jsx(SuccessIcon, {
11
+ className: "text-[#6FBF5A]",
12
+ style: { transform: "scale(1.25)" },
13
+ "data-testid": "completed-indicator"
14
+ }) : status === "failed" || status === "error" ? /* @__PURE__ */ jsx(FailIcon, {
15
+ className: "text-red-500",
16
+ style: { transform: "scale(1.25)" },
17
+ "data-testid": "failed-indicator"
18
+ }) : status === "skipped" || status === "skipped-failed" ? /* @__PURE__ */ jsx(SkipIcon, {
19
+ className: "text-gray-400",
20
+ style: { transform: "scale(1.25)" },
21
+ "data-testid": "skipped-indicator"
22
+ }) : status === "canceled" ? /* @__PURE__ */ jsx(CancelIcon, {
23
+ className: "text-[#3B82F6]",
24
+ style: { transform: "scale(1.5)" },
25
+ "data-testid": "canceled-indicator"
26
+ }) : status === "faulted" ? /* @__PURE__ */ jsx(RunningIcon, {
27
+ className: "rounded-full text-[#EF4444] animate-spin",
28
+ "data-testid": "faulted-indicator"
29
+ }) : status === "canceling" ? /* @__PURE__ */ jsx(RunningIcon, {
30
+ className: "rounded-full text-[#3B82F6] animate-spin",
31
+ "data-testid": "canceling-indicator"
32
+ }) : /* @__PURE__ */ jsx(NotRunningIcon, {
33
+ className: "rounded-full text-[#AAAAAA]",
34
+ "data-testid": "not-running-indicator"
35
+ })
36
+ });
37
+ }
38
+ //#endregion
39
+ export { Indicator as t };
@@ -0,0 +1,25 @@
1
+ import { LoaderIcon } from "../icons.js";
2
+ import cx from "classnames";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/components/Loader.tsx
5
+ function Loader({ size = 48, text, textSize = 12, full = true, color = "", loaderStyle = {} }) {
6
+ const loaderColor = color || "text-(--theme-element,#3b82f6)";
7
+ const fontSize = typeof size === "number" ? `${size}px` : size;
8
+ return /* @__PURE__ */ jsxs("div", {
9
+ className: cx(full && "w-full", "flex flex-col flex-wrap justify-center items-center gap-y-1"),
10
+ children: [/* @__PURE__ */ jsx("div", {
11
+ className: cx("w-full flex justify-center items-center", loaderColor),
12
+ style: loaderStyle,
13
+ children: /* @__PURE__ */ jsx(LoaderIcon, {
14
+ className: "animate-spin",
15
+ style: { fontSize }
16
+ })
17
+ }), text && /* @__PURE__ */ jsx("div", {
18
+ className: "text-center italic",
19
+ style: { fontSize: `${textSize}px` },
20
+ children: text
21
+ })]
22
+ });
23
+ }
24
+ //#endregion
25
+ export { Loader as t };
@@ -0,0 +1,101 @@
1
+ import { AlertIcon, CheckIcon, ClipboardIcon, CopyIcon, HiddenFalseIcon, HiddenTrueIcon, InfoIcon } from "../icons.js";
2
+ import { i as useNotify } from "./Provider-DvVvScTQ.js";
3
+ import cx from "classnames";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Suspense, lazy, useState } from "react";
6
+ //#region src/components/Callout.tsx
7
+ function CalloutIcon({ type }) {
8
+ if (type === "warning" || type === "error") return /* @__PURE__ */ jsx(AlertIcon, { className: "h-6 w-6 mr-4 text-lg" });
9
+ else return /* @__PURE__ */ jsx(InfoIcon, { className: "h-6 w-6 mr-4 text-lg" });
10
+ }
11
+ function Callout({ type, className = "", children }) {
12
+ return /* @__PURE__ */ jsx("div", {
13
+ className: cx(className, type === "warning" && "bg-orange-100 border-orange-500 text-orange-700", type === "error" && "bg-red-100 border-red-500 text-red-700", type === "info" && "bg-blue-100 border-blue-500 text-blue-700", "border-t-4 rounded-b px-4 py-3 shadow-md my-4"),
14
+ role: "alert",
15
+ children: /* @__PURE__ */ jsxs("div", {
16
+ className: "flex",
17
+ children: [/* @__PURE__ */ jsx("div", {
18
+ className: "py-1",
19
+ children: /* @__PURE__ */ jsx(CalloutIcon, { type })
20
+ }), /* @__PURE__ */ jsx("div", { children })]
21
+ })
22
+ });
23
+ }
24
+ //#endregion
25
+ //#region src/components/CopyToClipboard.tsx
26
+ function CopyToClipboard({ as = "div", text, className, children, showIcon = true }) {
27
+ const notify = useNotify();
28
+ const handleCopy = async () => {
29
+ try {
30
+ await navigator.clipboard.writeText(text);
31
+ notify.info("Copied to clipboard");
32
+ } catch {
33
+ notify.error("Failed to copy to clipboard");
34
+ }
35
+ };
36
+ return /* @__PURE__ */ jsxs(as, {
37
+ className,
38
+ onClick: handleCopy,
39
+ ...as === "button" ? { type: "button" } : {},
40
+ children: [showIcon && /* @__PURE__ */ jsx(ClipboardIcon, {}), children]
41
+ });
42
+ }
43
+ function CopyCodeBlock({ textToCopy, children, secret = false, isRevealed = false, onRevealToggle }) {
44
+ const notify = useNotify();
45
+ const [copied, setCopied] = useState(false);
46
+ const handleCopy = async () => {
47
+ if (copied) return;
48
+ try {
49
+ await navigator.clipboard.writeText(textToCopy);
50
+ setCopied(true);
51
+ notify.info("Copied to clipboard");
52
+ setTimeout(() => setCopied(false), 2e3);
53
+ } catch {
54
+ notify.error("Failed to copy to clipboard");
55
+ }
56
+ };
57
+ return /* @__PURE__ */ jsxs("div", {
58
+ className: "group relative",
59
+ onClick: handleCopy,
60
+ children: [/* @__PURE__ */ jsx("pre", {
61
+ className: `p-4 theme-hover border rounded-lg text-left font-mono text-sm overflow-x-auto ${secret ? "pr-24" : "pr-12"}`,
62
+ children
63
+ }), /* @__PURE__ */ jsxs("div", {
64
+ className: "absolute top-0 right-0 bottom-0 flex items-center gap-1 pl-8 pr-2 bg-gradient-to-l from-[var(--color-panel)] from-70% to-transparent rounded-r-lg",
65
+ children: [secret && /* @__PURE__ */ jsx("button", {
66
+ type: "button",
67
+ onClick: (e) => {
68
+ e.stopPropagation();
69
+ onRevealToggle?.();
70
+ },
71
+ className: "p-2 rounded-md opacity-0 group-hover:opacity-100 transition-all duration-150",
72
+ "aria-label": isRevealed ? "Hide secret" : "Reveal secret",
73
+ title: isRevealed ? "Hide secret" : "Reveal secret",
74
+ children: isRevealed ? /* @__PURE__ */ jsx(HiddenFalseIcon, {}) : /* @__PURE__ */ jsx(HiddenTrueIcon, {})
75
+ }), /* @__PURE__ */ jsx("button", {
76
+ type: "button",
77
+ onClick: (e) => {
78
+ e.stopPropagation();
79
+ handleCopy();
80
+ },
81
+ className: "p-2 rounded-md opacity-0 group-hover:opacity-100 transition-all duration-150",
82
+ "aria-label": copied ? "Copied" : "Copy to clipboard",
83
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-green-400" }) : /* @__PURE__ */ jsx(CopyIcon, {})
84
+ })]
85
+ })]
86
+ });
87
+ }
88
+ //#endregion
89
+ //#region src/components/Markdown.tsx
90
+ var MarkdownImpl = lazy(() => import("./MarkdownImpl-Bq4QhrtA.js"));
91
+ function Markdown(props) {
92
+ return /* @__PURE__ */ jsx(Suspense, {
93
+ fallback: /* @__PURE__ */ jsx("div", {
94
+ className: "markdown whitespace-pre-wrap text-start w-full",
95
+ children: props.children
96
+ }),
97
+ children: /* @__PURE__ */ jsx(MarkdownImpl, { ...props })
98
+ });
99
+ }
100
+ //#endregion
101
+ export { Callout as i, CopyCodeBlock as n, CopyToClipboard as r, Markdown as t };
@@ -0,0 +1,33 @@
1
+ import cx from "classnames";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Streamdown } from "streamdown";
4
+ import { code } from "@streamdown/code";
5
+ import { math } from "@streamdown/math";
6
+ //#region src/components/MarkdownImpl.tsx
7
+ var plugins = {
8
+ code,
9
+ math
10
+ };
11
+ var shikiTheme = ["github-light", "github-dark"];
12
+ function Markdown({ children, isStreaming, controls }) {
13
+ return /* @__PURE__ */ jsx("div", {
14
+ className: "markdown whitespace-normal text-start w-full",
15
+ children: /* @__PURE__ */ jsx(Streamdown, {
16
+ mode: isStreaming ? "streaming" : "static",
17
+ isAnimating: isStreaming ?? false,
18
+ ...isStreaming ? { caret: "block" } : {},
19
+ ...controls ? { controls } : {},
20
+ plugins,
21
+ shikiTheme,
22
+ components: { a: ({ node, ...props }) => /* @__PURE__ */ jsx("a", {
23
+ ...props,
24
+ className: cx("link wrap-break-word", props.className),
25
+ target: "_blank",
26
+ rel: "noopener noreferrer"
27
+ }) },
28
+ children: children || ""
29
+ })
30
+ });
31
+ }
32
+ //#endregion
33
+ export { Markdown as default };
@@ -0,0 +1,121 @@
1
+ import cx from "classnames";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useId, useRef, useState } from "react";
4
+ import { createPortal } from "react-dom";
5
+ //#region src/components/Modal.tsx
6
+ var FOCUSABLE = "a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])";
7
+ var noop = () => {};
8
+ var actionClasses = {
9
+ destructive: "bg-red-600 text-white hover:bg-red-700",
10
+ warning: "bg-yellow-500 text-white hover:bg-yellow-700",
11
+ info: "bg-(--theme-element,#06354f) text-(--theme-element-text,#ffffff) hover:opacity-90"
12
+ };
13
+ function Modal({ isOpen, close, cancelAction = noop, children, title = "", text = "", actionLabel = "", cancelLabel = "Cancel", action, closeAfterAction = true, type = "destructive", className = "", showButtons = true, disableAction = false, loading = false, padding = true, fitWidth = false, dimScreen = true, ignoreOutsideClickClose = false }) {
14
+ const [pending, setPending] = useState(false);
15
+ const actionFiredRef = useRef(false);
16
+ const panelRef = useRef(null);
17
+ const titleId = useId();
18
+ const inFlight = loading || pending;
19
+ const inFlightRef = useRef(inFlight);
20
+ inFlightRef.current = inFlight;
21
+ useEffect(() => {
22
+ if (isOpen) actionFiredRef.current = false;
23
+ }, [isOpen]);
24
+ useEffect(() => {
25
+ if (!isOpen) return;
26
+ const previouslyFocused = document.activeElement;
27
+ const previousOverflow = document.body.style.overflow;
28
+ document.body.style.overflow = "hidden";
29
+ panelRef.current?.focus();
30
+ return () => {
31
+ document.body.style.overflow = previousOverflow;
32
+ previouslyFocused?.focus?.();
33
+ };
34
+ }, [isOpen]);
35
+ const trapFocus = useCallback((e) => {
36
+ if (e.key !== "Tab" || !panelRef.current) return;
37
+ const focusable = panelRef.current.querySelectorAll(FOCUSABLE);
38
+ if (focusable.length === 0) {
39
+ e.preventDefault();
40
+ return;
41
+ }
42
+ const first = focusable[0];
43
+ const last = focusable[focusable.length - 1];
44
+ if (e.shiftKey && document.activeElement === first) {
45
+ e.preventDefault();
46
+ last.focus();
47
+ } else if (!e.shiftKey && document.activeElement === last) {
48
+ e.preventDefault();
49
+ first.focus();
50
+ }
51
+ }, []);
52
+ const closeRef = useRef(close);
53
+ closeRef.current = close;
54
+ useEffect(() => {
55
+ if (!isOpen) return;
56
+ const onKey = (e) => {
57
+ if (e.key === "Escape" && !inFlightRef.current) closeRef.current();
58
+ };
59
+ window.addEventListener("keydown", onKey);
60
+ return () => window.removeEventListener("keydown", onKey);
61
+ }, [isOpen]);
62
+ const runAction = useCallback(async () => {
63
+ if (actionFiredRef.current) return;
64
+ actionFiredRef.current = true;
65
+ setPending(true);
66
+ try {
67
+ await action?.();
68
+ if (closeAfterAction) closeRef.current();
69
+ else actionFiredRef.current = false;
70
+ } finally {
71
+ setPending(false);
72
+ }
73
+ }, [action, closeAfterAction]);
74
+ if (!isOpen) return null;
75
+ return createPortal(/* @__PURE__ */ jsxs("div", {
76
+ className: "fixed z-250 inset-0 flex w-screen items-center justify-center p-4",
77
+ role: "dialog",
78
+ "aria-modal": "true",
79
+ ...title ? { "aria-labelledby": titleId } : {},
80
+ onKeyDown: trapFocus,
81
+ children: [/* @__PURE__ */ jsx("div", {
82
+ className: cx("fixed inset-0", dimScreen && "bg-gray-500/75"),
83
+ onClick: inFlight || ignoreOutsideClickClose ? void 0 : close
84
+ }), /* @__PURE__ */ jsxs("div", {
85
+ ref: panelRef,
86
+ tabIndex: -1,
87
+ className: cx(className, "relative inline-block align-bottom rounded-lg text-left shadow-xl z-50 sm:my-8 sm:align-middle max-h-full overflow-y-auto", "bg-(--theme-panel-bg,#ffffff) text-(--theme-panel,#000000)", padding && "px-4 pt-5 pb-4 sm:p-6", fitWidth ? "sm:w-min-[32rem]" : "sm:max-w-lg sm:w-full"),
88
+ children: [/* @__PURE__ */ jsxs("div", { children: [title && /* @__PURE__ */ jsx("h3", {
89
+ id: titleId,
90
+ className: "text-center text-xl leading-6 font-semibold",
91
+ children: title
92
+ }), /* @__PURE__ */ jsxs("div", {
93
+ className: cx(title.length !== 0 && "mt-2"),
94
+ children: [text && /* @__PURE__ */ jsx("p", {
95
+ className: "text-sm text-center",
96
+ children: text
97
+ }), children]
98
+ })] }), showButtons && /* @__PURE__ */ jsxs("div", {
99
+ className: "mt-5 sm:mt-6 grid grid-cols-2 gap-3 grid-flow-row-dense",
100
+ children: [/* @__PURE__ */ jsx("button", {
101
+ type: "button",
102
+ className: cx("self-center cursor-pointer px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap flex items-center justify-center", "border border-(--theme-border,#d1d5db) hover:bg-(--theme-hover,#f3f4f6)", inFlight && "cursor-wait"),
103
+ onClick: () => {
104
+ cancelAction();
105
+ close();
106
+ },
107
+ disabled: inFlight,
108
+ children: cancelLabel
109
+ }), /* @__PURE__ */ jsx("button", {
110
+ type: "button",
111
+ className: cx("self-center cursor-pointer px-3 py-1.5 rounded-md text-xs font-medium whitespace-nowrap flex items-center justify-center", "disabled:opacity-50 disabled:cursor-not-allowed", actionClasses[type], loading && "cursor-wait"),
112
+ onClick: runAction,
113
+ disabled: disableAction || inFlight,
114
+ children: actionLabel
115
+ })]
116
+ })]
117
+ })]
118
+ }), document.body);
119
+ }
120
+ //#endregion
121
+ export { Modal as t };