@parallelworks/ui 0.19.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/dist/{chunks/memoryStore-CC91S5LP.js → ai/adapter/memoryStore.js} +2 -2
- package/dist/ai/adapter/mock/index.js +2 -80
- package/dist/ai/adapter/mock/mockAdapter.js +81 -0
- package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
- package/dist/ai/adapter/openai/errors.js +37 -0
- package/dist/ai/adapter/openai/index.js +5 -333
- package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
- package/dist/ai/adapter/openai/responses.js +108 -0
- package/dist/ai/adapter/openai/sse.js +112 -0
- package/dist/{chunks/types-Yy0NrerF.js → ai/adapter/types.js} +1 -1
- package/dist/ai/agent/classifier.js +12 -0
- package/dist/ai/agent/diff.js +223 -0
- package/dist/ai/agent/diffHighlight.js +101 -0
- package/dist/ai/agent/permissions.js +29 -0
- package/dist/ai/agent/toolfmt.js +383 -0
- package/dist/ai/agent/transcript.js +127 -0
- package/dist/ai/components/AllocationSelector.js +56 -0
- package/dist/ai/components/AttachmentManager.js +144 -0
- package/dist/ai/components/AttachmentUpload.js +179 -0
- package/dist/ai/components/BlockedGroupBanner.js +29 -0
- package/dist/ai/components/BranchNavigator.js +57 -0
- package/dist/ai/components/ChatEmptyState.js +171 -0
- package/dist/ai/components/ChatInput.js +265 -0
- package/dist/ai/components/ChatLayout.js +15 -0
- package/dist/ai/components/ChatMessage.js +338 -0
- package/dist/ai/components/ChatMessageList.js +301 -0
- package/dist/ai/components/ChatSidebar.js +345 -0
- package/dist/ai/components/ChatThread.js +198 -0
- package/dist/ai/components/ComposerChrome.js +50 -0
- package/dist/ai/components/ComposerFrame.js +33 -0
- package/dist/ai/components/DragOverlay.js +20 -0
- package/dist/ai/components/ModelSelector.js +343 -0
- package/dist/ai/components/ShareDialog.js +260 -0
- package/dist/ai/components/SlashMenu.js +91 -0
- package/dist/ai/components/agent/ActivityLine.js +151 -0
- package/dist/ai/components/agent/AgentMessageParts.js +721 -0
- package/dist/ai/components/agent/PermissionPicker.js +38 -0
- package/dist/ai/components/attachmentKeys.js +10 -0
- package/dist/ai/core/ChatProvider.js +848 -0
- package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
- package/dist/ai/core/chatReducer.js +223 -0
- package/dist/ai/core/config.js +45 -0
- package/dist/ai/core/events.js +4 -0
- package/dist/ai/core/exportConversation.js +42 -0
- package/dist/ai/core/greeting.js +38 -0
- package/dist/ai/core/parts.js +84 -0
- package/dist/ai/core/useDragDrop.js +36 -0
- package/dist/ai/core/useKeyboardShortcuts.js +77 -0
- package/dist/ai/core/useSSEStream.js +98 -0
- package/dist/ai/index.js +43 -6644
- package/dist/ai/strings.js +175 -0
- package/dist/ai/ui/Avatar.js +35 -0
- package/dist/ai/ui/Dropdown.js +110 -0
- package/dist/ai/ui/Markdown.js +79 -0
- package/dist/ai/ui/Notice.js +77 -0
- package/dist/ai/ui/codeBreaks.js +36 -0
- package/dist/ai/ui/prose.js +13 -0
- package/dist/ai/ui/sidebar.js +148 -0
- package/dist/ai/utils.js +23 -0
- package/dist/components/AddMenu.js +46 -0
- package/dist/components/Avatar.js +46 -0
- package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
- package/dist/components/Breadcrumbs.js +83 -0
- package/dist/components/Button.js +83 -0
- package/dist/components/Callout.js +23 -0
- package/dist/components/Card.js +31 -0
- package/dist/components/CollapsiblePanel.js +77 -0
- package/dist/{chunks/ConfirmModal-aOR4O1QE.js → components/ConfirmModal.js} +4 -9
- package/dist/components/CopyToClipboard.js +81 -0
- package/dist/{chunks/Markdown-CM-FenNE.js → components/CreateModal.js} +9 -116
- package/dist/components/DescriptionList.js +42 -0
- package/dist/components/Dropdown.js +349 -0
- package/dist/components/EmptyState.js +27 -0
- package/dist/components/Filter.js +32 -0
- package/dist/components/FilterPill.js +13 -0
- package/dist/components/IconButton.js +34 -0
- package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
- package/dist/components/Input.js +88 -0
- package/dist/components/LetterBadge.js +13 -0
- package/dist/components/Listbox.js +123 -0
- package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
- package/dist/components/Markdown.js +15 -0
- package/dist/components/MultiSelect.js +171 -0
- package/dist/components/Overview.js +39 -0
- package/dist/components/PageHeader.js +194 -0
- package/dist/components/Pagination.js +35 -0
- package/dist/{chunks/Provider-CDYurraE.js → components/Provider.js} +1 -1
- package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
- package/dist/components/SectionHeader.js +11 -0
- package/dist/components/SettingModeOption.js +30 -0
- package/dist/components/SettingRow.js +35 -0
- package/dist/components/SettingsCard.js +31 -0
- package/dist/components/SettingsGroup.js +17 -0
- package/dist/components/Sort.js +42 -0
- package/dist/components/StatusBadge.js +63 -0
- package/dist/components/SwitchToggle.js +59 -0
- package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
- package/dist/{chunks/Table-DU2MW8xz.js → components/Table.js} +3 -3
- package/dist/components/Toggle.js +20 -0
- package/dist/{chunks/Tooltip-K5HJr4_p.js → components/Tooltip.js} +2 -27
- package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
- package/dist/{chunks/focus-D_iZJTW1.js → components/focus.js} +1 -1
- package/dist/components/ghostButton.js +7 -0
- package/dist/components/inputClasses.js +4 -0
- package/dist/components/keys.js +27 -0
- package/dist/components/relativeTime.js +32 -0
- package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
- package/dist/{chunks/duration-BOv8Phl8.js → duration.js} +1 -1
- package/dist/editor/Editor.js +13 -0
- package/dist/editor/EditorField.js +53 -0
- package/dist/editor/FormCodePanel.js +173 -0
- package/dist/{chunks/Monaco-DJ8MW-Dq.js → editor/Monaco.js} +4 -2
- package/dist/editor/index.js +6 -1
- package/dist/editor/themes.js +91 -0
- package/dist/editor/workers.js +29 -0
- package/dist/editor/yaml.js +15 -0
- package/dist/file-explorer/FileExplorer.js +1402 -0
- package/dist/file-explorer/FileExplorerContext.js +370 -0
- package/dist/{chunks/CodePreviewEditor-YqQBz1YL.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
- package/dist/file-explorer/FilePreview/Inline.js +45 -0
- package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
- package/dist/file-explorer/FilePreview/Viewer.js +526 -0
- package/dist/file-explorer/FilePreview/index.js +266 -0
- package/dist/file-explorer/FilePreview/parse.js +63 -0
- package/dist/file-explorer/FilePreview/previewCache.js +98 -0
- package/dist/file-explorer/FilePreview/previewType.js +151 -0
- package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
- package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
- package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
- package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
- package/dist/file-explorer/FileRow.js +165 -0
- package/dist/file-explorer/FileRowsWindow.js +92 -0
- package/dist/file-explorer/FileTable.js +172 -0
- package/dist/file-explorer/FileTableHeaders.js +49 -0
- package/dist/file-explorer/LoadMoreRow.js +46 -0
- package/dist/file-explorer/TreeView.js +376 -0
- package/dist/file-explorer/helpers.js +537 -0
- package/dist/file-explorer/index.js +7 -5671
- package/dist/file-explorer/lib/batch.js +39 -0
- package/dist/file-explorer/lib/errors.js +9 -0
- package/dist/file-explorer/lib/paging.js +124 -0
- package/dist/file-explorer/lib/utils.js +322 -0
- package/dist/file-explorer/toasts.js +400 -0
- package/dist/file-explorer/treeRows.js +73 -0
- package/dist/file-explorer/useNearEnd.js +27 -0
- package/dist/form/FieldWrapper.js +54 -0
- package/dist/form/Fields/BooleanField.js +51 -0
- package/dist/form/Fields/CheckboxGroupField.js +72 -0
- package/dist/form/Fields/ColorField.js +33 -0
- package/dist/form/Fields/DropdownField.js +49 -0
- package/dist/form/Fields/DurationField.js +130 -0
- package/dist/form/Fields/LabelField.js +19 -0
- package/dist/form/Fields/MultiDropdownField.js +40 -0
- package/dist/form/Fields/NumberField.js +51 -0
- package/dist/form/Fields/ObjectField.js +54 -0
- package/dist/form/Fields/RadioField.js +49 -0
- package/dist/form/Fields/RangeField.js +58 -0
- package/dist/form/Fields/ResourceOptionIcon.js +21 -0
- package/dist/form/Fields/StepField.js +6 -0
- package/dist/form/Fields/StringField.js +37 -0
- package/dist/form/Fields/TextAreaField.js +31 -0
- package/dist/form/Fields/durationValidity.js +11 -0
- package/dist/form/Form.js +643 -0
- package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
- package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
- package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
- package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
- package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
- package/dist/form/Wizard/WizardContainer.js +138 -0
- package/dist/form/Wizard/WizardNavigation.js +92 -0
- package/dist/form/Wizard/WizardStepContent.js +35 -0
- package/dist/form/Wizard/WizardStepIndicator.js +108 -0
- package/dist/form/Wizard/useWizardState.js +118 -0
- package/dist/form/Wizard/utils.js +34 -0
- package/dist/form/fieldContext.js +26 -0
- package/dist/form/fieldRegistry.js +50 -0
- package/dist/form/index.js +17 -2321
- package/dist/{chunks/FieldWrapper-Cszwg-4B.js → form/lib.js} +2 -97
- package/dist/form/useParsedOpts.js +62 -0
- package/dist/form/usePrevious.js +11 -0
- package/dist/form/utils/checkShowIfObject.js +14 -0
- package/dist/form/utils/duration.js +69 -0
- package/dist/form/utils/getParentValue.js +23 -0
- package/dist/form/utils/getPlaceholder.js +9 -0
- package/dist/form/utils/getValueUsingPath.js +23 -0
- package/dist/form/utils/secondaryField.js +22 -0
- package/dist/graph/AnnotationBanner.js +141 -0
- package/dist/graph/Collapse.js +41 -0
- package/dist/graph/DependencyGraph.js +1398 -0
- package/dist/graph/JobSummary.js +104 -0
- package/dist/graph/MatrixGroup.js +107 -0
- package/dist/graph/Reveal.js +57 -0
- package/dist/graph/TreeView.js +711 -0
- package/dist/graph/index.js +1 -2519
- package/dist/graph/types.js +6 -0
- package/dist/index.js +46 -599
- package/dist/list/ActionToolbar.js +184 -0
- package/dist/list/HoverCard.js +73 -0
- package/dist/list/ListPage.js +145 -0
- package/dist/list/ListPager.js +59 -0
- package/dist/list/ListTable.js +163 -0
- package/dist/list/ListViewControls.js +372 -0
- package/dist/list/RowContextMenu.js +350 -0
- package/dist/list/UserHoverCard.js +117 -0
- package/dist/list/index.js +11 -2
- package/dist/list/listSearch.js +137 -0
- package/dist/list/listView.js +210 -0
- package/dist/list/textEntry.js +10 -0
- package/dist/{chunks/logviewer-BTKuQWzw.js → logviewer/LogViewer.js} +4 -82
- package/dist/logviewer/index.js +2 -1
- package/dist/logviewer/segments.js +80 -0
- package/package.json +1 -1
- package/dist/chunks/PageHeader-0kG_iypP.js +0 -692
- package/dist/chunks/SwitchToggle-DShNdcao.js +0 -758
- package/dist/chunks/editor-Dk1rbV75.js +0 -361
- package/dist/chunks/list-CJm875m7.js +0 -1418
- /package/dist/{chunks/MarkdownImpl-CyeTVvSt.js → components/MarkdownImpl.js} +0 -0
package/dist/ai/utils.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/ai/utils.ts
|
|
2
|
+
function formatFileSize(bytes) {
|
|
3
|
+
if (bytes === 0) return "0 B";
|
|
4
|
+
const k = 1024;
|
|
5
|
+
const sizes = [
|
|
6
|
+
"B",
|
|
7
|
+
"KB",
|
|
8
|
+
"MB",
|
|
9
|
+
"GB",
|
|
10
|
+
"TB"
|
|
11
|
+
];
|
|
12
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
13
|
+
return Number.parseFloat((bytes / k ** i).toFixed(2)) + " " + sizes[i];
|
|
14
|
+
}
|
|
15
|
+
function isMac() {
|
|
16
|
+
return navigator.platform.toUpperCase().includes("MAC");
|
|
17
|
+
}
|
|
18
|
+
/** Only org models bill to an allocation; any other model ignores it. */
|
|
19
|
+
function isOrgModel(modelId) {
|
|
20
|
+
return modelId?.startsWith("org:") ?? false;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { formatFileSize, isMac, isOrgModel };
|
|
@@ -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 };
|
|
@@ -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 };
|
|
@@ -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 };
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useStrings } from "./Provider.js";
|
|
2
|
+
import { BareModal, modalPanelClasses } from "./BareModal.js";
|
|
3
|
+
import { dangerButtonClasses, ghostButtonClasses, primaryButtonClasses } from "./ghostButton.js";
|
|
3
4
|
import cx from "classnames";
|
|
4
5
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
//#region src/components/ghostButton.ts
|
|
7
|
-
var ghostButtonClasses = "inline-flex cursor-pointer items-center gap-1.5 h-8 px-3 rounded-md text-sm text-(--theme-muted-text-color) hover:text-(--theme-app) hover:bg-(--theme-muted-panel-bg) transition-colors";
|
|
8
|
-
var primaryButtonClasses = "inline-flex cursor-pointer items-center gap-1.5 h-7 px-2.5 rounded-md text-[12.5px] font-medium bg-(--theme-element) text-(--theme-element-text) hover:opacity-90 transition-opacity";
|
|
9
|
-
/** Filled destructive button for confirming irreversible actions in ds modals. */
|
|
10
|
-
var dangerButtonClasses = "inline-flex cursor-pointer items-center gap-1.5 h-7 px-2.5 rounded-md text-[12.5px] font-medium bg-red-600 text-white hover:bg-red-700 transition-colors";
|
|
11
|
-
//#endregion
|
|
12
7
|
//#region src/components/ConfirmModal.tsx
|
|
13
8
|
function ConfirmModal({ open, onClose, title, description, children, confirmLabel, onConfirm, confirmDisabled = false, destructive = false, align = "top", cancelLabel, closeOnConfirm = true }) {
|
|
14
9
|
const strings = useStrings();
|
|
@@ -76,4 +71,4 @@ function ConfirmModal({ open, onClose, title, description, children, confirmLabe
|
|
|
76
71
|
});
|
|
77
72
|
}
|
|
78
73
|
//#endregion
|
|
79
|
-
export {
|
|
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 };
|