@parallelworks/ui 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -6
- package/dist/ai/adapter/memoryStore.d.ts +8 -0
- package/dist/ai/adapter/memoryStore.js +152 -0
- package/dist/ai/adapter/mock/index.d.ts +2 -0
- package/dist/ai/adapter/mock/index.js +3 -0
- package/dist/ai/adapter/mock/mockAdapter.d.ts +4 -0
- package/dist/ai/adapter/mock/mockAdapter.js +81 -0
- package/dist/ai/adapter/openai/createOpenAIStream.d.ts +9 -0
- package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
- package/dist/ai/adapter/openai/errors.d.ts +3 -0
- package/dist/ai/adapter/openai/errors.js +37 -0
- package/dist/ai/adapter/openai/index.d.ts +6 -0
- package/dist/ai/adapter/openai/index.js +6 -0
- package/dist/ai/adapter/openai/openaiAdapter.d.ts +9 -0
- package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
- package/dist/ai/adapter/openai/responses.d.ts +4 -0
- package/dist/ai/adapter/openai/responses.js +108 -0
- package/dist/ai/adapter/openai/sse.d.ts +24 -0
- package/dist/ai/adapter/openai/sse.js +112 -0
- package/dist/ai/adapter/openai/wire.d.ts +40 -0
- package/dist/ai/adapter/types.d.ts +131 -0
- package/dist/ai/adapter/types.js +11 -0
- package/dist/ai/agent/classifier.d.ts +2 -0
- package/dist/ai/agent/classifier.js +12 -0
- package/dist/ai/agent/diff.d.ts +35 -0
- package/dist/ai/agent/diff.js +223 -0
- package/dist/ai/agent/diffHighlight.d.ts +6 -0
- package/dist/ai/agent/diffHighlight.js +101 -0
- package/dist/ai/agent/index.d.ts +6 -0
- package/dist/ai/agent/permissions.d.ts +11 -0
- package/dist/ai/agent/permissions.js +29 -0
- package/dist/ai/agent/toolfmt.d.ts +18 -0
- package/dist/ai/agent/toolfmt.js +383 -0
- package/dist/ai/agent/transcript.d.ts +38 -0
- package/dist/ai/agent/transcript.js +127 -0
- package/dist/ai/ai.css +325 -0
- package/dist/ai/components/AllocationSelector.d.ts +4 -0
- package/dist/ai/components/AllocationSelector.js +56 -0
- package/dist/ai/components/AttachmentManager.d.ts +1 -0
- package/dist/ai/components/AttachmentManager.js +144 -0
- package/dist/ai/components/AttachmentUpload.d.ts +24 -0
- package/dist/ai/components/AttachmentUpload.js +179 -0
- package/dist/ai/components/BlockedGroupBanner.d.ts +1 -0
- package/dist/ai/components/BlockedGroupBanner.js +29 -0
- package/dist/ai/components/BranchNavigator.d.ts +8 -0
- package/dist/ai/components/BranchNavigator.js +57 -0
- package/dist/ai/components/ChatEmptyState.d.ts +3 -0
- package/dist/ai/components/ChatEmptyState.js +171 -0
- package/dist/ai/components/ChatInput.d.ts +45 -0
- package/dist/ai/components/ChatInput.js +265 -0
- package/dist/ai/components/ChatLayout.d.ts +5 -0
- package/dist/ai/components/ChatLayout.js +15 -0
- package/dist/ai/components/ChatMessage.d.ts +24 -0
- package/dist/ai/components/ChatMessage.js +338 -0
- package/dist/ai/components/ChatMessageList.d.ts +35 -0
- package/dist/ai/components/ChatMessageList.js +301 -0
- package/dist/ai/components/ChatSidebar.d.ts +5 -0
- package/dist/ai/components/ChatSidebar.js +345 -0
- package/dist/ai/components/ChatThread.d.ts +3 -0
- package/dist/ai/components/ChatThread.js +198 -0
- package/dist/ai/components/ComposerChrome.d.ts +18 -0
- package/dist/ai/components/ComposerChrome.js +50 -0
- package/dist/ai/components/ComposerFrame.d.ts +16 -0
- package/dist/ai/components/ComposerFrame.js +33 -0
- package/dist/ai/components/DragOverlay.d.ts +5 -0
- package/dist/ai/components/DragOverlay.js +20 -0
- package/dist/ai/components/ModelSelector.d.ts +6 -0
- package/dist/ai/components/ModelSelector.js +343 -0
- package/dist/ai/components/ShareDialog.d.ts +11 -0
- package/dist/ai/components/ShareDialog.js +260 -0
- package/dist/ai/components/SlashMenu.d.ts +28 -0
- package/dist/ai/components/SlashMenu.js +91 -0
- package/dist/ai/components/agent/ActivityLine.d.ts +21 -0
- package/dist/ai/components/agent/ActivityLine.js +151 -0
- package/dist/ai/components/agent/AgentMessageParts.d.ts +54 -0
- package/dist/ai/components/agent/AgentMessageParts.js +721 -0
- package/dist/ai/components/agent/PermissionPicker.d.ts +11 -0
- package/dist/ai/components/agent/PermissionPicker.js +38 -0
- package/dist/ai/components/attachmentKeys.d.ts +4 -0
- package/dist/ai/components/attachmentKeys.js +10 -0
- package/dist/ai/core/ChatProvider.d.ts +66 -0
- package/dist/ai/core/ChatProvider.js +848 -0
- package/dist/ai/core/KeyboardShortcutsProvider.d.ts +5 -0
- package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
- package/dist/ai/core/chatReducer.d.ts +114 -0
- package/dist/ai/core/chatReducer.js +223 -0
- package/dist/ai/core/config.d.ts +47 -0
- package/dist/ai/core/config.js +45 -0
- package/dist/ai/core/events.d.ts +1 -0
- package/dist/ai/core/events.js +4 -0
- package/dist/ai/core/exportConversation.d.ts +4 -0
- package/dist/ai/core/exportConversation.js +42 -0
- package/dist/ai/core/greeting.d.ts +3 -0
- package/dist/ai/core/greeting.js +38 -0
- package/dist/ai/core/parts.d.ts +11 -0
- package/dist/ai/core/parts.js +84 -0
- package/dist/ai/core/useDragDrop.d.ts +14 -0
- package/dist/ai/core/useDragDrop.js +36 -0
- package/dist/ai/core/useKeyboardShortcuts.d.ts +12 -0
- package/dist/ai/core/useKeyboardShortcuts.js +77 -0
- package/dist/ai/core/useSSEStream.d.ts +34 -0
- package/dist/ai/core/useSSEStream.js +98 -0
- package/dist/ai/index.d.ts +40 -0
- package/dist/ai/index.js +44 -0
- package/dist/ai/strings.d.ts +167 -0
- package/dist/ai/strings.js +175 -0
- package/dist/ai/types.d.ts +236 -0
- package/dist/ai/ui/Avatar.d.ts +8 -0
- package/dist/ai/ui/Avatar.js +35 -0
- package/dist/ai/ui/Dropdown.d.ts +31 -0
- package/dist/ai/ui/Dropdown.js +110 -0
- package/dist/ai/ui/Markdown.d.ts +8 -0
- package/dist/ai/ui/Markdown.js +79 -0
- package/dist/ai/ui/Notice.d.ts +21 -0
- package/dist/ai/ui/Notice.js +77 -0
- package/dist/ai/ui/buttons.d.ts +1 -0
- package/dist/ai/ui/codeBreaks.d.ts +16 -0
- package/dist/ai/ui/codeBreaks.js +36 -0
- package/dist/ai/ui/prose.d.ts +1 -0
- package/dist/ai/ui/prose.js +13 -0
- package/dist/ai/ui/sidebar.d.ts +81 -0
- package/dist/ai/ui/sidebar.js +148 -0
- package/dist/ai/utils.d.ts +4 -0
- package/dist/ai/utils.js +23 -0
- package/dist/assets/{editor.worker-CuBRIwi-.js → editor.worker-BmHUIVG4.js} +194 -163
- package/dist/assets/{json.worker-8ytS02vz.js → json.worker-D8bJ92nw.js} +384 -338
- package/dist/assets/{yaml.worker-DJC-VUcv.js → yaml.worker-C4gyGAko.js} +15657 -13823
- package/dist/components/AddMenu.js +46 -0
- package/dist/components/Avatar.d.ts +1 -1
- package/dist/components/Avatar.js +46 -0
- package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
- package/dist/components/Breadcrumbs.d.ts +1 -1
- package/dist/components/Breadcrumbs.js +83 -0
- package/dist/components/Button.js +83 -0
- package/dist/components/Callout.js +23 -0
- package/dist/components/Card.js +31 -0
- package/dist/components/CollapsiblePanel.js +77 -0
- package/dist/components/ConfirmModal.js +74 -0
- package/dist/components/CopyToClipboard.js +81 -0
- package/dist/{chunks/CreateModal-BY6DLmur.js → components/CreateModal.js} +10 -189
- package/dist/components/DescriptionList.js +42 -0
- package/dist/components/Dropdown.d.ts +1 -1
- package/dist/components/Dropdown.js +349 -0
- package/dist/components/EmptyState.d.ts +1 -1
- package/dist/components/EmptyState.js +27 -0
- package/dist/components/Filter.js +32 -0
- package/dist/components/FilterPill.js +13 -0
- package/dist/components/IconButton.js +34 -0
- package/dist/components/Indicator.d.ts +2 -2
- package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
- package/dist/components/Input.d.ts +1 -1
- package/dist/components/Input.js +88 -0
- package/dist/components/LetterBadge.d.ts +1 -1
- package/dist/components/LetterBadge.js +13 -0
- package/dist/components/Listbox.js +123 -0
- package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
- package/dist/components/Markdown.js +15 -0
- package/dist/components/MarkdownImpl.d.ts +1 -1
- package/dist/components/MultiSelect.js +171 -0
- package/dist/components/Overview.js +39 -0
- package/dist/components/PageHeader.js +194 -0
- package/dist/components/Pagination.js +35 -0
- package/dist/components/Provider.d.ts +16 -65
- package/dist/{chunks/Provider-Ghua9PkN.js → components/Provider.js} +54 -20
- package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
- package/dist/components/SectionHeader.js +11 -0
- package/dist/components/SettingModeOption.js +30 -0
- package/dist/components/SettingRow.d.ts +1 -1
- package/dist/components/SettingRow.js +35 -0
- package/dist/components/SettingsCard.js +31 -0
- package/dist/components/SettingsGroup.d.ts +1 -1
- package/dist/components/SettingsGroup.js +17 -0
- package/dist/components/Sort.js +42 -0
- package/dist/components/StatusBadge.js +63 -0
- package/dist/components/SwitchToggle.js +59 -0
- package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
- package/dist/{chunks/Table-4OHjdKdO.js → components/Table.js} +7 -5
- package/dist/components/Toggle.js +20 -0
- package/dist/{chunks/Tooltip-Crxo_eU_.js → components/Tooltip.js} +6 -4
- package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
- package/dist/components/focus.d.ts +2 -0
- package/dist/components/focus.js +7 -0
- package/dist/components/ghostButton.js +7 -0
- package/dist/components/inputClasses.js +4 -0
- package/dist/components/keys.d.ts +12 -0
- package/dist/components/keys.js +27 -0
- package/dist/components/relativeTime.js +32 -0
- package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
- package/dist/duration.d.ts +3 -0
- package/dist/duration.js +17 -0
- package/dist/editor/Editor.js +13 -0
- package/dist/editor/EditorField.js +53 -0
- package/dist/editor/FormCodePanel.js +173 -0
- package/dist/editor/Monaco.d.ts +1 -20
- package/dist/editor/Monaco.js +112 -0
- package/dist/editor/index.d.ts +2 -1
- package/dist/editor/index.js +7 -2
- package/dist/editor/themes.js +91 -0
- package/dist/editor/workers.js +29 -0
- package/dist/editor/yaml.d.ts +5 -0
- package/dist/editor/yaml.js +15 -0
- package/dist/engine.d.ts +98 -0
- package/dist/file-explorer/FileExplorer.d.ts +11 -2
- package/dist/file-explorer/FileExplorer.js +1402 -0
- package/dist/file-explorer/FileExplorerContext.d.ts +1 -1
- package/dist/file-explorer/FileExplorerContext.js +370 -0
- package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +1 -1
- package/dist/{chunks/CodePreviewEditor-4lx3kE-w.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
- package/dist/file-explorer/FilePreview/Inline.js +45 -0
- package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
- package/dist/file-explorer/FilePreview/Viewer.js +526 -0
- package/dist/file-explorer/FilePreview/index.js +266 -0
- package/dist/file-explorer/FilePreview/parse.js +63 -0
- package/dist/file-explorer/FilePreview/previewCache.js +98 -0
- package/dist/file-explorer/FilePreview/previewType.d.ts +1 -1
- package/dist/file-explorer/FilePreview/previewType.js +151 -0
- package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
- package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
- package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
- package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
- package/dist/file-explorer/FileRow.d.ts +1 -1
- package/dist/file-explorer/FileRow.js +165 -0
- package/dist/file-explorer/FileRowsWindow.js +92 -0
- package/dist/file-explorer/FileTable.js +172 -0
- package/dist/file-explorer/FileTableHeaders.js +49 -0
- package/dist/file-explorer/LoadMoreRow.js +46 -0
- package/dist/file-explorer/TreeView.js +376 -0
- package/dist/file-explorer/helpers.d.ts +4 -4
- package/dist/file-explorer/helpers.js +537 -0
- package/dist/file-explorer/index.d.ts +3 -3
- package/dist/file-explorer/index.js +7 -5705
- package/dist/file-explorer/lib/batch.js +39 -0
- package/dist/file-explorer/lib/errors.js +9 -0
- package/dist/file-explorer/lib/paging.js +124 -0
- package/dist/file-explorer/lib/types.d.ts +6 -1
- package/dist/file-explorer/lib/utils.d.ts +1 -3
- package/dist/file-explorer/lib/utils.js +322 -0
- package/dist/file-explorer/toasts.js +400 -0
- package/dist/file-explorer/treeRows.js +73 -0
- package/dist/file-explorer/useNearEnd.d.ts +1 -1
- package/dist/file-explorer/useNearEnd.js +27 -0
- package/dist/form/FieldWrapper.d.ts +2 -2
- package/dist/form/FieldWrapper.js +54 -0
- package/dist/form/Fields/BooleanField.js +51 -0
- package/dist/form/Fields/CheckboxGroupField.js +72 -0
- package/dist/form/Fields/ColorField.js +33 -0
- package/dist/form/Fields/DropdownField.js +49 -0
- package/dist/form/Fields/DurationField.js +130 -0
- package/dist/form/Fields/LabelField.js +19 -0
- package/dist/form/Fields/MultiDropdownField.js +40 -0
- package/dist/form/Fields/NumberField.js +51 -0
- package/dist/form/Fields/ObjectField.js +54 -0
- package/dist/form/Fields/RadioField.js +49 -0
- package/dist/form/Fields/RangeField.js +58 -0
- package/dist/form/Fields/ResourceOptionIcon.d.ts +1 -1
- package/dist/form/Fields/ResourceOptionIcon.js +21 -0
- package/dist/form/Fields/StepField.js +6 -0
- package/dist/form/Fields/StringField.js +37 -0
- package/dist/form/Fields/TextAreaField.js +31 -0
- package/dist/form/Fields/durationValidity.js +11 -0
- package/dist/form/Form.d.ts +4 -21
- package/dist/form/Form.js +643 -0
- package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
- package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
- package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
- package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
- package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
- package/dist/form/Wizard/WizardContainer.js +138 -0
- package/dist/form/Wizard/WizardNavigation.js +92 -0
- package/dist/form/Wizard/WizardStepContent.js +35 -0
- package/dist/form/Wizard/WizardStepIndicator.js +108 -0
- package/dist/form/Wizard/useWizardState.js +118 -0
- package/dist/form/Wizard/utils.js +34 -0
- package/dist/form/fieldContext.js +26 -0
- package/dist/form/fieldRegistry.js +50 -0
- package/dist/form/index.d.ts +11 -12
- package/dist/form/index.js +18 -2445
- package/dist/form/lib.d.ts +6 -1
- package/dist/{chunks/FieldWrapper-Bef01EWO.js → form/lib.js} +5 -104
- package/dist/form/types/fieldComponentTypes.d.ts +3 -2
- package/dist/form/types/fieldTypes.d.ts +6 -20
- package/dist/form/useParsedOpts.d.ts +1 -1
- package/dist/form/useParsedOpts.js +62 -0
- package/dist/form/usePrevious.js +11 -0
- package/dist/form/utils/checkShowIfObject.js +14 -0
- package/dist/form/utils/{slurmDuration.d.ts → duration.d.ts} +2 -2
- package/dist/form/utils/duration.js +69 -0
- package/dist/form/utils/getParentValue.js +23 -0
- package/dist/form/utils/getPlaceholder.js +9 -0
- package/dist/form/utils/getValueUsingPath.js +23 -0
- package/dist/form/utils/secondaryField.js +22 -0
- package/dist/graph/AnnotationBanner.js +141 -0
- package/dist/graph/Collapse.js +41 -0
- package/dist/{workflow/index.js → graph/DependencyGraph.js} +76 -1163
- package/dist/graph/JobSummary.js +104 -0
- package/dist/{workflow → graph}/MatrixGroup.d.ts +2 -2
- package/dist/graph/MatrixGroup.js +107 -0
- package/dist/graph/Reveal.js +57 -0
- package/dist/graph/TreeView.js +711 -0
- package/dist/{workflow → graph}/index.d.ts +1 -1
- package/dist/graph/index.js +2 -0
- package/dist/{workflow → graph}/types.d.ts +3 -3
- package/dist/graph/types.js +6 -0
- package/dist/icons.d.ts +20 -21
- package/dist/index.d.ts +38 -40
- package/dist/index.js +47 -599
- package/dist/list/ActionToolbar.js +184 -0
- package/dist/list/HoverCard.js +73 -0
- package/dist/list/ListPage.js +145 -0
- package/dist/list/ListPager.js +59 -0
- package/dist/list/ListTable.d.ts +1 -1
- package/dist/list/ListTable.js +163 -0
- package/dist/list/ListViewControls.d.ts +2 -2
- package/dist/list/ListViewControls.js +372 -0
- package/dist/list/RowContextMenu.js +350 -0
- package/dist/list/UserHoverCard.js +117 -0
- package/dist/list/index.d.ts +9 -9
- package/dist/list/index.js +11 -2
- package/dist/list/listSearch.js +137 -0
- package/dist/list/listView.js +210 -0
- package/dist/list/textEntry.js +10 -0
- package/dist/logviewer/LogViewer.d.ts +1 -1
- package/dist/logviewer/LogViewer.js +750 -0
- package/dist/logviewer/index.d.ts +1 -0
- package/dist/logviewer/index.js +3 -742
- package/dist/logviewer/segments.d.ts +9 -0
- package/dist/logviewer/segments.js +80 -0
- package/dist/styles/fonts.css +4 -4
- package/dist/styles/theme.css +6 -4
- package/dist/styles.css +1 -1
- package/dist/theme/index.js +2 -2
- package/package.json +38 -14
- package/LICENSE +0 -202
- package/dist/chunks/Monaco-C1POOdVv.js +0 -1046
- package/dist/chunks/PageHeader-l49p1nM9.js +0 -690
- package/dist/chunks/SwitchToggle-CHPP8uZQ.js +0 -755
- package/dist/chunks/editor-9_uVtUyy.js +0 -347
- package/dist/chunks/list-qrojZZNv.js +0 -1411
- package/dist/editor/usesGitlab.d.ts +0 -97
- package/dist/form/Fields/BucketReadOnlyField.d.ts +0 -7
- package/dist/form/types/workflow-schema.d.ts +0 -1145
- package/dist/form/utils/pwResolver.d.ts +0 -18
- package/dist/{chunks/MarkdownImpl-Bq4QhrtA.js → components/MarkdownImpl.js} +1 -1
- /package/dist/{workflow → graph}/AnnotationBanner.d.ts +0 -0
- /package/dist/{workflow → graph}/Collapse.d.ts +0 -0
- /package/dist/{workflow → graph}/DependencyGraph.d.ts +0 -0
- /package/dist/{workflow → graph}/JobSummary.d.ts +0 -0
- /package/dist/{workflow → graph}/Reveal.d.ts +0 -0
- /package/dist/{workflow → graph}/TreeView.d.ts +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useLink } from "./Provider.js";
|
|
2
|
+
import { TOOLTIP_ID } from "./Tooltip.js";
|
|
3
|
+
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
|
|
4
|
+
import cx from "classnames";
|
|
5
|
+
import { Fragment } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/AddMenu.tsx
|
|
8
|
+
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";
|
|
9
|
+
function itemButtonProps(item) {
|
|
10
|
+
if (!item.disabled) return { onClick: item.onSelect };
|
|
11
|
+
return {
|
|
12
|
+
"aria-disabled": true,
|
|
13
|
+
...item.hint ? {
|
|
14
|
+
"aria-label": `${item.label}. ${item.hint}`,
|
|
15
|
+
"data-tooltip-id": TOOLTIP_ID,
|
|
16
|
+
"data-tooltip-content": item.hint
|
|
17
|
+
} : {}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function AddMenu({ items, label, buttonClassName, zClassName = "z-50", children }) {
|
|
21
|
+
const Link = useLink();
|
|
22
|
+
return /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuButton, {
|
|
23
|
+
"aria-label": label,
|
|
24
|
+
title: label,
|
|
25
|
+
className: buttonClassName,
|
|
26
|
+
children
|
|
27
|
+
}), /* @__PURE__ */ jsx(MenuItems, {
|
|
28
|
+
anchor: "bottom start",
|
|
29
|
+
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),
|
|
30
|
+
children: items.map((item) => /* @__PURE__ */ jsxs(Fragment, { children: [item.separatorAbove && /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-(--theme-border)" }), /* @__PURE__ */ jsx(MenuItem, {
|
|
31
|
+
disabled: item.disabled ?? false,
|
|
32
|
+
children: item.to && !item.disabled ? /* @__PURE__ */ jsxs(Link, {
|
|
33
|
+
to: item.to,
|
|
34
|
+
className: addMenuItemClasses,
|
|
35
|
+
children: [item.icon, item.label]
|
|
36
|
+
}) : /* @__PURE__ */ jsxs("button", {
|
|
37
|
+
type: "button",
|
|
38
|
+
...itemButtonProps(item),
|
|
39
|
+
className: cx(addMenuItemClasses, item.disabled && "opacity-50 cursor-not-allowed"),
|
|
40
|
+
children: [item.icon, item.label]
|
|
41
|
+
})
|
|
42
|
+
})] }, item.label))
|
|
43
|
+
})] });
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { AddMenu };
|
|
@@ -10,4 +10,4 @@ export interface AvatarProps {
|
|
|
10
10
|
}
|
|
11
11
|
/** Up to two initials: the first and last word of a name split on spaces and dots. */
|
|
12
12
|
export declare function avatarInitials(name: string | undefined): string;
|
|
13
|
-
export declare function Avatar({ src, name, size, status, className
|
|
13
|
+
export declare function Avatar({ src, name, size, status, className }: AvatarProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useStrings } from "./Provider.js";
|
|
2
|
+
import cx from "classnames";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/Avatar.tsx
|
|
6
|
+
var SIZE_CLASSES = {
|
|
7
|
+
sm: "w-6 h-6 text-xs",
|
|
8
|
+
md: "w-8 h-8 text-sm",
|
|
9
|
+
lg: "w-10 h-10 text-base",
|
|
10
|
+
xl: "w-12 h-12 text-lg",
|
|
11
|
+
"2xl": "w-16 h-16 text-xl"
|
|
12
|
+
};
|
|
13
|
+
var STATUS_CLASSES = {
|
|
14
|
+
online: "bg-green-500",
|
|
15
|
+
offline: "bg-(--theme-muted-text-color)",
|
|
16
|
+
busy: "bg-red-500",
|
|
17
|
+
away: "bg-yellow-500"
|
|
18
|
+
};
|
|
19
|
+
/** Up to two initials: the first and last word of a name split on spaces and dots. */
|
|
20
|
+
function avatarInitials(name) {
|
|
21
|
+
const parts = (name ?? "").split(/[\s.]+/).filter(Boolean);
|
|
22
|
+
if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
23
|
+
return parts[0]?.[0]?.toUpperCase() || "?";
|
|
24
|
+
}
|
|
25
|
+
function Avatar({ src, name, size = "md", status, className }) {
|
|
26
|
+
const strings = useStrings();
|
|
27
|
+
const [erroredUrl, setErroredUrl] = useState(null);
|
|
28
|
+
const showImage = !!src && erroredUrl !== src;
|
|
29
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
30
|
+
className: cx("relative inline-flex", className),
|
|
31
|
+
children: [showImage ? /* @__PURE__ */ jsx("img", {
|
|
32
|
+
src,
|
|
33
|
+
alt: name || strings.common.userAvatar,
|
|
34
|
+
onError: () => setErroredUrl(src),
|
|
35
|
+
className: cx("rounded-full object-cover", SIZE_CLASSES[size])
|
|
36
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
37
|
+
className: cx("rounded-full flex items-center justify-center font-medium", "bg-gradient-to-br from-[var(--gradient-start,var(--theme-element))] to-[var(--gradient-mid,var(--theme-link))] text-white", SIZE_CLASSES[size]),
|
|
38
|
+
children: avatarInitials(name)
|
|
39
|
+
}), status && /* @__PURE__ */ jsx("span", {
|
|
40
|
+
"data-testid": "online-indicator",
|
|
41
|
+
className: cx("absolute bottom-0 right-0 block rounded-full ring-2 ring-(--theme-app-bg)", STATUS_CLASSES[status], size === "sm" ? "w-1.5 h-1.5" : "w-2.5 h-2.5")
|
|
42
|
+
})]
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { Avatar, avatarInitials };
|
|
@@ -20,7 +20,7 @@ interface BreadcrumbContextType {
|
|
|
20
20
|
claimedPath: React.MutableRefObject<string | null>;
|
|
21
21
|
}
|
|
22
22
|
export declare const useBreadcrumb: () => BreadcrumbContextType;
|
|
23
|
-
export declare function BreadcrumbProvider({ children
|
|
23
|
+
export declare function BreadcrumbProvider({ children }: {
|
|
24
24
|
children: React.ReactNode;
|
|
25
25
|
}): React.JSX.Element;
|
|
26
26
|
export declare function useSetBreadcrumbs(getBreadcrumbs: (() => IBreadcrumbItem[]) | IBreadcrumbItem[]): void;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { createContext, useContext, useEffect, useLayoutEffect } from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/Breadcrumbs.tsx
|
|
4
|
+
var BreadcrumbContext = createContext({
|
|
5
|
+
breadcrumbs: [],
|
|
6
|
+
setBreadcrumbs: () => {},
|
|
7
|
+
rightsideBreadcrumb: null,
|
|
8
|
+
setRightsideBreadcrumb: () => {},
|
|
9
|
+
hidden: false,
|
|
10
|
+
setHidden: () => {},
|
|
11
|
+
titleActionSlot: null,
|
|
12
|
+
setTitleActionSlot: () => {},
|
|
13
|
+
rightActionSlot: null,
|
|
14
|
+
setRightActionSlot: () => {},
|
|
15
|
+
claimedPath: { current: null }
|
|
16
|
+
});
|
|
17
|
+
var useBreadcrumb = () => useContext(BreadcrumbContext);
|
|
18
|
+
function BreadcrumbProvider({ children }) {
|
|
19
|
+
const [breadcrumbs, setBreadcrumbs] = React.useState([]);
|
|
20
|
+
const [rightsideBreadcrumb, setRightsideBreadcrumb] = React.useState(null);
|
|
21
|
+
const [hidden, setHidden] = React.useState(false);
|
|
22
|
+
const [titleActionSlot, setTitleActionSlot] = React.useState(null);
|
|
23
|
+
const [rightActionSlot, setRightActionSlot] = React.useState(null);
|
|
24
|
+
const claimedPath = React.useRef(null);
|
|
25
|
+
return /* @__PURE__ */ jsx(BreadcrumbContext.Provider, {
|
|
26
|
+
value: {
|
|
27
|
+
breadcrumbs,
|
|
28
|
+
setBreadcrumbs,
|
|
29
|
+
rightsideBreadcrumb,
|
|
30
|
+
setRightsideBreadcrumb,
|
|
31
|
+
hidden,
|
|
32
|
+
setHidden,
|
|
33
|
+
titleActionSlot,
|
|
34
|
+
setTitleActionSlot,
|
|
35
|
+
rightActionSlot,
|
|
36
|
+
setRightActionSlot,
|
|
37
|
+
claimedPath
|
|
38
|
+
},
|
|
39
|
+
children
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function useSetBreadcrumbs(getBreadcrumbs) {
|
|
43
|
+
const { setBreadcrumbs, claimedPath } = useBreadcrumb();
|
|
44
|
+
useLayoutEffect(() => {
|
|
45
|
+
claimedPath.current = window.location.pathname;
|
|
46
|
+
setBreadcrumbs(typeof getBreadcrumbs === "function" ? getBreadcrumbs() : getBreadcrumbs);
|
|
47
|
+
}, [
|
|
48
|
+
getBreadcrumbs,
|
|
49
|
+
setBreadcrumbs,
|
|
50
|
+
claimedPath
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* For layout routes that derive breadcrumbs from the URL: applies them only
|
|
55
|
+
* while no page under the layout has set its own for the current path.
|
|
56
|
+
* Without this, a layout re-running its effect (for example when the
|
|
57
|
+
* organization's display name loads) overwrote the page's breadcrumbs.
|
|
58
|
+
*/
|
|
59
|
+
function useSetDefaultBreadcrumbs(getBreadcrumbs) {
|
|
60
|
+
const { setBreadcrumbs, claimedPath } = useBreadcrumb();
|
|
61
|
+
useLayoutEffect(() => {
|
|
62
|
+
if (claimedPath.current === window.location.pathname) return;
|
|
63
|
+
setBreadcrumbs(typeof getBreadcrumbs === "function" ? getBreadcrumbs() : getBreadcrumbs);
|
|
64
|
+
}, [
|
|
65
|
+
getBreadcrumbs,
|
|
66
|
+
setBreadcrumbs,
|
|
67
|
+
claimedPath
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
var EMPTY_BREADCRUMBS = [];
|
|
71
|
+
/** For pages that render their own header instead of the breadcrumb strip. */
|
|
72
|
+
function useClearBreadcrumbs() {
|
|
73
|
+
useSetBreadcrumbs(EMPTY_BREADCRUMBS);
|
|
74
|
+
}
|
|
75
|
+
function useHideBreadcrumbs(hidden) {
|
|
76
|
+
const { setHidden } = useBreadcrumb();
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
setHidden(hidden);
|
|
79
|
+
return () => setHidden(false);
|
|
80
|
+
}, [hidden, setHidden]);
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { BreadcrumbProvider, useBreadcrumb, useClearBreadcrumbs, useHideBreadcrumbs, useSetBreadcrumbs, useSetDefaultBreadcrumbs };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { useLink } from "./Provider.js";
|
|
2
|
+
import { AngleRightIcon, LoaderIcon } from "../icons.js";
|
|
3
|
+
import cx from "classnames";
|
|
4
|
+
import { forwardRef } from "react";
|
|
5
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/Button.tsx
|
|
7
|
+
var Button = forwardRef(({ children, variant = "primary", size = "default", loading, icon, iconPosition = "right", fullWidth = true, className = "", disabled, ...props }, ref) => {
|
|
8
|
+
const baseClasses = "inline-flex items-center justify-center gap-2 font-semibold rounded-lg transition-all duration-200 cursor-pointer border-none mt-2 disabled:opacity-50 disabled:cursor-not-allowed";
|
|
9
|
+
const variantClasses = {
|
|
10
|
+
primary: "bg-gradient-to-br from-[var(--gradient-start,var(--theme-element))] to-[var(--gradient-mid,var(--theme-link))] text-white shadow-[0_4px_14px_0_rgba(59,130,246,0.3)] hover:enabled:-translate-y-0.5 hover:enabled:shadow-[0_6px_20px_0_rgba(59,130,246,0.4)] active:enabled:translate-y-0",
|
|
11
|
+
secondary: "bg-[var(--theme-muted-panel-bg)] text-[var(--theme-app)] border border-[var(--theme-border)] hover:enabled:bg-[var(--theme-border)]",
|
|
12
|
+
outline: "bg-transparent text-[var(--theme-app)] border border-[var(--theme-border)] hover:enabled:bg-[var(--theme-muted-panel-bg)] hover:enabled:border-[var(--theme-muted-text-color)]",
|
|
13
|
+
ghost: "bg-transparent text-[var(--theme-muted-text-color)] hover:enabled:text-[var(--theme-app)] hover:enabled:bg-[var(--theme-muted-panel-bg)]"
|
|
14
|
+
};
|
|
15
|
+
const sizeClasses = {
|
|
16
|
+
sm: "py-2 px-4 text-[0.8125rem]",
|
|
17
|
+
default: "py-3 px-5 text-sm",
|
|
18
|
+
lg: "py-4 px-6 text-base"
|
|
19
|
+
};
|
|
20
|
+
const widthClass = fullWidth ? "w-full" : "w-auto";
|
|
21
|
+
return /* @__PURE__ */ jsx("button", {
|
|
22
|
+
ref,
|
|
23
|
+
type: "button",
|
|
24
|
+
disabled: disabled || loading,
|
|
25
|
+
className: cx(baseClasses, variantClasses[variant], sizeClasses[size], widthClass, className),
|
|
26
|
+
...props,
|
|
27
|
+
children: loading ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(LoaderIcon, { className: "size-[18px]" }), children] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
28
|
+
icon && iconPosition === "left" && /* @__PURE__ */ jsx("span", {
|
|
29
|
+
className: "flex items-center",
|
|
30
|
+
children: icon
|
|
31
|
+
}),
|
|
32
|
+
children,
|
|
33
|
+
icon && iconPosition === "right" && /* @__PURE__ */ jsx("span", {
|
|
34
|
+
className: "flex items-center",
|
|
35
|
+
children: icon
|
|
36
|
+
})
|
|
37
|
+
] })
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
Button.displayName = "Button";
|
|
41
|
+
function MethodButton({ icon, label, description, href, loading, disabled, className = "", ...props }) {
|
|
42
|
+
const Link = useLink();
|
|
43
|
+
const baseClasses = "flex items-center w-full p-4 bg-[var(--theme-muted-panel-bg)] border border-[var(--theme-border)] rounded-xl text-[var(--theme-app)] text-[0.9375rem] font-medium cursor-pointer transition-all duration-200 no-underline mb-3 last:mb-0 hover:bg-[var(--theme-border)] hover:border-[var(--theme-muted-text-color)] hover:-translate-y-0.5 active:translate-y-0";
|
|
44
|
+
const disabledClasses = "disabled:opacity-60 disabled:cursor-not-allowed disabled:hover:bg-[var(--ds-muted)] disabled:hover:border-[var(--ds-border)] disabled:hover:translate-y-0";
|
|
45
|
+
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
46
|
+
icon && /* @__PURE__ */ jsx("span", {
|
|
47
|
+
className: "size-10 rounded-lg bg-gradient-to-br from-[var(--gradient-start,var(--theme-element))] to-[var(--gradient-mid,var(--theme-link))] flex items-center justify-center shrink-0 mr-4 [&_svg]:size-5 [&_svg]:text-white",
|
|
48
|
+
children: icon
|
|
49
|
+
}),
|
|
50
|
+
/* @__PURE__ */ jsxs("span", {
|
|
51
|
+
className: "flex-1 text-left",
|
|
52
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
53
|
+
className: "block font-semibold text-[var(--theme-app)]",
|
|
54
|
+
children: label
|
|
55
|
+
}), description && /* @__PURE__ */ jsx("span", {
|
|
56
|
+
className: "block text-[0.8125rem] text-[var(--theme-muted-text-color)] font-normal mt-0.5",
|
|
57
|
+
children: description
|
|
58
|
+
})]
|
|
59
|
+
}),
|
|
60
|
+
loading ? /* @__PURE__ */ jsx(LoaderIcon, { className: "size-5 text-[var(--theme-muted-text-color)] shrink-0 ml-2" }) : /* @__PURE__ */ jsx(AngleRightIcon, { className: "size-5 text-[var(--theme-muted-text-color)] shrink-0 ml-2 transition-all duration-200 group-hover:translate-x-[3px] group-hover:text-[var(--theme-app)]" })
|
|
61
|
+
] });
|
|
62
|
+
if (href) {
|
|
63
|
+
if (href.startsWith("/api/") || href.startsWith("http")) return /* @__PURE__ */ jsx("a", {
|
|
64
|
+
href,
|
|
65
|
+
className: cx("group", baseClasses, className),
|
|
66
|
+
children: content
|
|
67
|
+
});
|
|
68
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
69
|
+
to: href,
|
|
70
|
+
className: cx("group", baseClasses, className),
|
|
71
|
+
children: content
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return /* @__PURE__ */ jsx("button", {
|
|
75
|
+
type: "button",
|
|
76
|
+
className: cx("group", baseClasses, disabledClasses, className),
|
|
77
|
+
disabled: disabled || loading,
|
|
78
|
+
...props,
|
|
79
|
+
children: content
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { Button, MethodButton };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AlertIcon, InfoIcon } from "../icons.js";
|
|
2
|
+
import cx from "classnames";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/Callout.tsx
|
|
5
|
+
function CalloutIcon({ type }) {
|
|
6
|
+
if (type === "warning" || type === "error") return /* @__PURE__ */ jsx(AlertIcon, { className: "h-6 w-6 mr-4 text-lg" });
|
|
7
|
+
else return /* @__PURE__ */ jsx(InfoIcon, { className: "h-6 w-6 mr-4 text-lg" });
|
|
8
|
+
}
|
|
9
|
+
function Callout({ type, className = "", children }) {
|
|
10
|
+
return /* @__PURE__ */ jsx("div", {
|
|
11
|
+
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"),
|
|
12
|
+
role: "alert",
|
|
13
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
14
|
+
className: "flex",
|
|
15
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
16
|
+
className: "py-1",
|
|
17
|
+
children: /* @__PURE__ */ jsx(CalloutIcon, { type })
|
|
18
|
+
}), /* @__PURE__ */ jsx("div", { children })]
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { Callout as default };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/Card.tsx
|
|
4
|
+
function Card({ children, className = "", wide, compact, interactive, authShadow }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("div", {
|
|
6
|
+
className: cx("w-full bg-[var(--theme-card-bg)] backdrop-blur-xl border border-[var(--theme-border)] rounded-2xl", authShadow ? "shadow-[var(--theme-auth-shadow)]" : "shadow-[var(--theme-shadow)]", wide && "max-w-[560px] p-8", compact && "max-w-[400px] p-6", !wide && !compact && "max-w-[520px] p-10", interactive && "ds-card-interactive cursor-pointer", className),
|
|
7
|
+
children
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
function CardHeader({ badge, title, description, className = "", align = "center" }) {
|
|
11
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
12
|
+
className: cx(align === "center" ? "text-center" : "text-left", "mb-6", className),
|
|
13
|
+
children: [
|
|
14
|
+
badge && /* @__PURE__ */ jsx("div", {
|
|
15
|
+
className: "inline-flex items-center gap-1.5 py-1.5 px-3 text-xs font-medium bg-[var(--theme-muted-panel-bg)] border border-[var(--theme-border)] rounded-full text-[var(--theme-muted-text-color)] mb-4 transition-colors duration-200",
|
|
16
|
+
children: badge
|
|
17
|
+
}),
|
|
18
|
+
/* @__PURE__ */ jsx("h1", {
|
|
19
|
+
className: "text-2xl font-bold tracking-tight text-[var(--theme-app)]",
|
|
20
|
+
style: { letterSpacing: "-0.025em" },
|
|
21
|
+
children: title
|
|
22
|
+
}),
|
|
23
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
24
|
+
className: "text-[var(--theme-muted-text-color)] text-sm leading-relaxed mt-2",
|
|
25
|
+
children: description
|
|
26
|
+
})
|
|
27
|
+
]
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { Card, CardHeader };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { AngleRightIcon } from "../icons.js";
|
|
2
|
+
import cx from "classnames";
|
|
3
|
+
import React, { useCallback } from "react";
|
|
4
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import AnimateHeight from "react-animate-height";
|
|
6
|
+
//#region src/components/CollapsiblePanel.tsx
|
|
7
|
+
var noop = () => {};
|
|
8
|
+
function ControlledCollapsiblePanel({ title = "", children, open, setOpen, onClick = noop, wrapperElement, customizedButton = null, titleAction, className }) {
|
|
9
|
+
const toggleOpen = useCallback(() => {
|
|
10
|
+
if (onClick) onClick();
|
|
11
|
+
setOpen?.((open) => !open);
|
|
12
|
+
}, [setOpen, onClick]);
|
|
13
|
+
const contentId = React.useId();
|
|
14
|
+
const Wrapper = wrapperElement ? wrapperElement : React.Fragment;
|
|
15
|
+
return React.isValidElement(title) ? /* @__PURE__ */ jsxs(Fragment$1, { children: [title, /* @__PURE__ */ jsx(Wrapper, { children: /* @__PURE__ */ jsx(AnimateHeight, {
|
|
16
|
+
duration: 300,
|
|
17
|
+
height: open ? "auto" : 0,
|
|
18
|
+
children
|
|
19
|
+
}) })] }) : /* @__PURE__ */ jsxs("div", {
|
|
20
|
+
className: cx("border border-solid rounded-2xl border-(--theme-border) bg-(--theme-panel-bg) text-(--theme-panel) mb-1 w-full", className),
|
|
21
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
22
|
+
className: cx(!open && "text-(--theme-muted-text-color)", "w-full flex items-center transform ease-in transition text-sm py-3 px-2 cursor-pointer"),
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsxs("button", {
|
|
25
|
+
type: "button",
|
|
26
|
+
"aria-expanded": !!open,
|
|
27
|
+
"aria-controls": contentId,
|
|
28
|
+
className: cx("flex items-center text-left cursor-pointer", !titleAction && "w-full"),
|
|
29
|
+
onClick: toggleOpen,
|
|
30
|
+
children: [/* @__PURE__ */ jsx(AngleRightIcon, { className: cx(open && "transform rotate-90", "px-1 ml-1 text-[1.25rem] transition ease-in") }), /* @__PURE__ */ jsx("span", {
|
|
31
|
+
className: "px-2 font-bold select-none",
|
|
32
|
+
children: title?.toString()
|
|
33
|
+
})]
|
|
34
|
+
}),
|
|
35
|
+
titleAction,
|
|
36
|
+
/* @__PURE__ */ jsx("div", {
|
|
37
|
+
className: "ml-auto",
|
|
38
|
+
children: customizedButton
|
|
39
|
+
})
|
|
40
|
+
]
|
|
41
|
+
}), /* @__PURE__ */ jsx(AnimateHeight, {
|
|
42
|
+
id: contentId,
|
|
43
|
+
duration: 300,
|
|
44
|
+
height: open ? "auto" : 0,
|
|
45
|
+
children
|
|
46
|
+
})]
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function UncontrolledCollapsiblePanel({ title, children, onClick, wrapperElement, initialState = true, className, customizedButton = null }) {
|
|
50
|
+
const [open, setOpen] = React.useState(initialState);
|
|
51
|
+
const passTitle = typeof title === "function" ? title(open, setOpen) : title;
|
|
52
|
+
return /* @__PURE__ */ jsx(ControlledCollapsiblePanel, {
|
|
53
|
+
title: passTitle,
|
|
54
|
+
open,
|
|
55
|
+
setOpen,
|
|
56
|
+
onClick,
|
|
57
|
+
wrapperElement,
|
|
58
|
+
className,
|
|
59
|
+
customizedButton,
|
|
60
|
+
children
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function MaybeCollapsible({ className, initialState, children, title, customizedButton, collapsible }) {
|
|
64
|
+
if (collapsible) return /* @__PURE__ */ jsx(UncontrolledCollapsiblePanel, {
|
|
65
|
+
className,
|
|
66
|
+
initialState,
|
|
67
|
+
title,
|
|
68
|
+
customizedButton,
|
|
69
|
+
children
|
|
70
|
+
});
|
|
71
|
+
return /* @__PURE__ */ jsx("div", {
|
|
72
|
+
className,
|
|
73
|
+
children
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { ControlledCollapsiblePanel, MaybeCollapsible, UncontrolledCollapsiblePanel };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { useStrings } from "./Provider.js";
|
|
2
|
+
import { BareModal, modalPanelClasses } from "./BareModal.js";
|
|
3
|
+
import { dangerButtonClasses, ghostButtonClasses, primaryButtonClasses } from "./ghostButton.js";
|
|
4
|
+
import cx from "classnames";
|
|
5
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/ConfirmModal.tsx
|
|
8
|
+
function ConfirmModal({ open, onClose, title, description, children, confirmLabel, onConfirm, confirmDisabled = false, destructive = false, align = "top", cancelLabel, closeOnConfirm = true }) {
|
|
9
|
+
const strings = useStrings();
|
|
10
|
+
const [pending, setPending] = useState(false);
|
|
11
|
+
const firedRef = useRef(false);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (open) firedRef.current = false;
|
|
14
|
+
}, [open]);
|
|
15
|
+
const onCloseRef = useRef(onClose);
|
|
16
|
+
onCloseRef.current = onClose;
|
|
17
|
+
const runConfirm = useCallback(async () => {
|
|
18
|
+
if (firedRef.current) return;
|
|
19
|
+
firedRef.current = true;
|
|
20
|
+
setPending(true);
|
|
21
|
+
try {
|
|
22
|
+
await onConfirm();
|
|
23
|
+
if (closeOnConfirm) onCloseRef.current();
|
|
24
|
+
else firedRef.current = false;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
firedRef.current = false;
|
|
27
|
+
throw error;
|
|
28
|
+
} finally {
|
|
29
|
+
setPending(false);
|
|
30
|
+
}
|
|
31
|
+
}, [onConfirm, closeOnConfirm]);
|
|
32
|
+
return /* @__PURE__ */ jsxs(BareModal, {
|
|
33
|
+
open,
|
|
34
|
+
onClose,
|
|
35
|
+
ariaLabel: title,
|
|
36
|
+
align,
|
|
37
|
+
preventClose: pending,
|
|
38
|
+
className: cx(modalPanelClasses, "w-[480px] max-w-full"),
|
|
39
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
40
|
+
className: "px-5 pt-5",
|
|
41
|
+
children: [
|
|
42
|
+
/* @__PURE__ */ jsx("h2", {
|
|
43
|
+
className: "text-lg font-semibold text-(--theme-app)",
|
|
44
|
+
children: title
|
|
45
|
+
}),
|
|
46
|
+
description !== null && description !== void 0 && /* @__PURE__ */ jsx("p", {
|
|
47
|
+
className: "mt-1.5 text-sm text-(--theme-muted-text-color)",
|
|
48
|
+
children: description
|
|
49
|
+
}),
|
|
50
|
+
children !== null && children !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
51
|
+
className: "mt-4",
|
|
52
|
+
children
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
56
|
+
className: "mt-5 flex items-center justify-end gap-2 border-t border-(--theme-border) px-5 py-3",
|
|
57
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
58
|
+
type: "button",
|
|
59
|
+
onClick: onClose,
|
|
60
|
+
disabled: pending,
|
|
61
|
+
className: cx(ghostButtonClasses, pending && "cursor-wait"),
|
|
62
|
+
children: cancelLabel ?? strings.modal.cancel
|
|
63
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
64
|
+
type: "button",
|
|
65
|
+
onClick: runConfirm,
|
|
66
|
+
disabled: confirmDisabled || pending,
|
|
67
|
+
className: cx(destructive ? dangerButtonClasses : primaryButtonClasses, "disabled:cursor-not-allowed disabled:opacity-50", pending && "cursor-wait"),
|
|
68
|
+
children: confirmLabel
|
|
69
|
+
})]
|
|
70
|
+
})]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { ConfirmModal };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { useNotify, useStrings } from "./Provider.js";
|
|
2
|
+
import { CheckIcon, ClipboardIcon, CopyIcon, HiddenFalseIcon, HiddenTrueIcon } from "../icons.js";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/CopyToClipboard.tsx
|
|
6
|
+
function CopyToClipboard({ as = "div", text, className, children, showIcon = true }) {
|
|
7
|
+
const notify = useNotify();
|
|
8
|
+
const strings = useStrings();
|
|
9
|
+
const handleCopy = async () => {
|
|
10
|
+
try {
|
|
11
|
+
await navigator.clipboard.writeText(text);
|
|
12
|
+
notify.info("Copied to clipboard");
|
|
13
|
+
} catch {
|
|
14
|
+
notify.error("Failed to copy to clipboard");
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
return /* @__PURE__ */ jsxs(as, {
|
|
18
|
+
className,
|
|
19
|
+
onClick: handleCopy,
|
|
20
|
+
...as === "button" ? { type: "button" } : {
|
|
21
|
+
role: "button",
|
|
22
|
+
"aria-label": strings.common.copy,
|
|
23
|
+
tabIndex: 0,
|
|
24
|
+
onKeyDown: (e) => {
|
|
25
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
handleCopy();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
children: [showIcon && /* @__PURE__ */ jsx(ClipboardIcon, {}), children]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function CopyCodeBlock({ textToCopy, children, secret = false, isRevealed = false, onRevealToggle }) {
|
|
35
|
+
const notify = useNotify();
|
|
36
|
+
const [copied, setCopied] = useState(false);
|
|
37
|
+
const handleCopy = async () => {
|
|
38
|
+
if (copied) return;
|
|
39
|
+
try {
|
|
40
|
+
await navigator.clipboard.writeText(textToCopy);
|
|
41
|
+
setCopied(true);
|
|
42
|
+
notify.info("Copied to clipboard");
|
|
43
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
44
|
+
} catch {
|
|
45
|
+
notify.error("Failed to copy to clipboard");
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
49
|
+
className: "group relative",
|
|
50
|
+
role: "none",
|
|
51
|
+
onClick: handleCopy,
|
|
52
|
+
children: [/* @__PURE__ */ jsx("pre", {
|
|
53
|
+
className: `p-4 theme-hover border rounded-lg text-left font-mono text-sm overflow-x-auto ${secret ? "pr-24" : "pr-12"}`,
|
|
54
|
+
children
|
|
55
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
56
|
+
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",
|
|
57
|
+
children: [secret && /* @__PURE__ */ jsx("button", {
|
|
58
|
+
type: "button",
|
|
59
|
+
onClick: (e) => {
|
|
60
|
+
e.stopPropagation();
|
|
61
|
+
onRevealToggle?.();
|
|
62
|
+
},
|
|
63
|
+
className: "p-2 rounded-md opacity-0 group-hover:opacity-100 transition-all duration-150",
|
|
64
|
+
"aria-label": isRevealed ? "Hide secret" : "Reveal secret",
|
|
65
|
+
title: isRevealed ? "Hide secret" : "Reveal secret",
|
|
66
|
+
children: isRevealed ? /* @__PURE__ */ jsx(HiddenFalseIcon, {}) : /* @__PURE__ */ jsx(HiddenTrueIcon, {})
|
|
67
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
68
|
+
type: "button",
|
|
69
|
+
onClick: (e) => {
|
|
70
|
+
e.stopPropagation();
|
|
71
|
+
handleCopy();
|
|
72
|
+
},
|
|
73
|
+
className: "p-2 rounded-md opacity-0 group-hover:opacity-100 transition-all duration-150",
|
|
74
|
+
"aria-label": copied ? "Copied" : "Copy to clipboard",
|
|
75
|
+
children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-green-400" }) : /* @__PURE__ */ jsx(CopyIcon, {})
|
|
76
|
+
})]
|
|
77
|
+
})]
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { CopyCodeBlock, CopyToClipboard as default };
|