@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
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useStrings } from "./Provider.js";
|
|
2
|
+
import cx from "classnames";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/Pagination.tsx
|
|
5
|
+
function Pagination({ endingNumber, endingTime, nextCallback, prevCallback, roundedBottom, startingNumber, startingTime, nextDisabled, prevDisabled, name, useTimeRange = false }) {
|
|
6
|
+
const t = useStrings().list;
|
|
7
|
+
return /* @__PURE__ */ jsxs("nav", {
|
|
8
|
+
className: cx(roundedBottom && "rounded-b-2xl", "theme-muted-panel flex items-center justify-between border-t theme-border px-4 py-1 sm:px-6"),
|
|
9
|
+
"aria-label": "Pagination",
|
|
10
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
11
|
+
className: cx("hidden", (startingNumber !== void 0 && startingNumber !== null && endingNumber !== void 0 && endingNumber !== null || startingTime && endingTime) && "sm:block"),
|
|
12
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
13
|
+
className: "text-sm whitespace-nowrap",
|
|
14
|
+
children: useTimeRange && startingTime && endingTime ? t.paginationShowingTimeRange(name ?? "", startingTime, endingTime) : t.paginationShowing(name ?? "", startingNumber ?? "", endingNumber ?? "")
|
|
15
|
+
})
|
|
16
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
17
|
+
className: "flex flex-1 justify-between sm:justify-end gap-x-2",
|
|
18
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
19
|
+
type: "button",
|
|
20
|
+
disabled: prevDisabled,
|
|
21
|
+
onClick: prevCallback,
|
|
22
|
+
className: cx("link text-sm", prevDisabled && "disabled"),
|
|
23
|
+
children: t.paginationPrevious
|
|
24
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
25
|
+
type: "button",
|
|
26
|
+
disabled: nextDisabled,
|
|
27
|
+
onClick: nextCallback,
|
|
28
|
+
className: cx("link text-sm", nextDisabled && "disabled"),
|
|
29
|
+
children: t.paginationNext
|
|
30
|
+
})]
|
|
31
|
+
})]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { Pagination };
|
|
@@ -548,4 +548,4 @@ function UIProvider({ notify, strings, navigation, data, slots, engine, children
|
|
|
548
548
|
});
|
|
549
549
|
}
|
|
550
550
|
//#endregion
|
|
551
|
-
export {
|
|
551
|
+
export { UIProvider, useLink, useNavigation, useNotify, useOptionalWorkflowEngine, usePersistedState, useProvisionCorsRules, useRunFile, useSlots, useStrings, useWorkflowEngine, useWorkflowEngineLoader };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/SectionHeader.tsx
|
|
4
|
+
function SectionHeader({ children, className = "", size = "md" }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("div", {
|
|
6
|
+
className: cx("w-full font-semibold", size === "sm" ? "mb-2 text-sm theme-text" : "text-lg", className),
|
|
7
|
+
children
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { SectionHeader as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/SettingModeOption.tsx
|
|
4
|
+
/** A labeled + described radio option row, used inside a SettingsCard to pick
|
|
5
|
+
* between modes (e.g. default vs custom). Stacked rows share the card's
|
|
6
|
+
* dividers via `isFirst`. */
|
|
7
|
+
function SettingModeOption({ name, checked, onSelect, label, description, isFirst, disabled }) {
|
|
8
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
9
|
+
className: cx("flex items-start gap-3 px-5 py-4", disabled ? "cursor-default opacity-60" : "cursor-pointer", !isFirst && "border-t theme-border"),
|
|
10
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
11
|
+
type: "radio",
|
|
12
|
+
name,
|
|
13
|
+
checked,
|
|
14
|
+
onChange: onSelect,
|
|
15
|
+
disabled,
|
|
16
|
+
className: "mt-0.5 w-4 h-4 theme-input shrink-0"
|
|
17
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
18
|
+
className: "min-w-0",
|
|
19
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
20
|
+
className: "font-semibold theme-text leading-tight",
|
|
21
|
+
children: label
|
|
22
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
23
|
+
className: "theme-muted-text text-xs leading-snug mt-0.5",
|
|
24
|
+
children: description
|
|
25
|
+
})]
|
|
26
|
+
})]
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { SettingModeOption };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/SettingRow.tsx
|
|
4
|
+
function SettingRow({ label, htmlFor, helpText, children, isFirst, fill, onClick }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
6
|
+
role: "none",
|
|
7
|
+
onClick,
|
|
8
|
+
className: cx("px-5 py-5 grid grid-cols-1 gap-x-8 gap-y-2", fill ? "md:grid-cols-[200px_1fr]" : "md:grid-cols-[1fr_auto]", !isFirst && "border-t theme-border", onClick && "cursor-pointer select-none hover:theme-hover transition-colors"),
|
|
9
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
10
|
+
className: "flex flex-col gap-y-1",
|
|
11
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
12
|
+
htmlFor,
|
|
13
|
+
className: "font-semibold theme-text leading-tight",
|
|
14
|
+
children: label
|
|
15
|
+
}), helpText && /* @__PURE__ */ jsx("div", {
|
|
16
|
+
className: "theme-muted-text text-xs leading-snug",
|
|
17
|
+
children: helpText
|
|
18
|
+
})]
|
|
19
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
20
|
+
className: cx("min-w-0", !fill && "flex items-center justify-end"),
|
|
21
|
+
children
|
|
22
|
+
})]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function SettingSection({ title, isFirst }) {
|
|
26
|
+
return /* @__PURE__ */ jsx("div", {
|
|
27
|
+
className: cx("px-5 py-3 theme-muted-panel", !isFirst && "border-t theme-border"),
|
|
28
|
+
children: /* @__PURE__ */ jsx("h2", {
|
|
29
|
+
className: "font-semibold text-sm uppercase tracking-wider theme-muted-text",
|
|
30
|
+
children: title
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { SettingRow, SettingSection };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/SettingsCard.tsx
|
|
4
|
+
/**
|
|
5
|
+
* A settings card: an optional sentence-case section label sits above a
|
|
6
|
+
* bordered panel of rows. The label carries the breathing-room rhythm between
|
|
7
|
+
* cards; the rows inside provide their own dividers via SettingRow's `isFirst`.
|
|
8
|
+
*/
|
|
9
|
+
function SettingsCard({ title, description, action, actionAlign = "adjacent", overflowVisible, children, className }) {
|
|
10
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
11
|
+
className: cx("mt-10 first:mt-0", className),
|
|
12
|
+
children: [(title || action) && /* @__PURE__ */ jsxs("div", {
|
|
13
|
+
className: "mb-3 px-0.5",
|
|
14
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
15
|
+
className: cx("flex items-center gap-1.5", actionAlign === "right" && "justify-between"),
|
|
16
|
+
children: [title && /* @__PURE__ */ jsx("h2", {
|
|
17
|
+
className: "text-[15px] font-semibold theme-text leading-none",
|
|
18
|
+
children: title
|
|
19
|
+
}), action]
|
|
20
|
+
}), description && /* @__PURE__ */ jsx("p", {
|
|
21
|
+
className: "text-xs theme-muted-text mt-1.5 leading-snug",
|
|
22
|
+
children: description
|
|
23
|
+
})]
|
|
24
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
25
|
+
className: cx("panel", overflowVisible ? "overflow-visible" : "overflow-hidden"),
|
|
26
|
+
children
|
|
27
|
+
})]
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { SettingsCard as default };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/SettingsGroup.tsx
|
|
4
|
+
function SettingsGroup({ title, children, className }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
6
|
+
className: cx("mt-8 first:mt-0", className),
|
|
7
|
+
children: [title && /* @__PURE__ */ jsx("h2", {
|
|
8
|
+
className: "text-[11px] font-semibold uppercase tracking-wider theme-muted-text mb-2 px-1",
|
|
9
|
+
children: title
|
|
10
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
11
|
+
className: "panel divide-y divide-(--theme-border)",
|
|
12
|
+
children
|
|
13
|
+
})]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { SettingsGroup as default };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useStrings } from "./Provider.js";
|
|
2
|
+
import { SortDownIcon, SortUnsortedIcon, SortUpIcon } from "../icons.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/Sort.tsx
|
|
5
|
+
var SortIcon = ({ currentlySorted, currentDirection, name }) => {
|
|
6
|
+
const style = { transform: "translateY(2px)" };
|
|
7
|
+
if (currentlySorted === name) {
|
|
8
|
+
if (currentDirection === "ascending") return /* @__PURE__ */ jsx(SortDownIcon, { style });
|
|
9
|
+
else if (currentDirection === "descending") return /* @__PURE__ */ jsx(SortUpIcon, { style });
|
|
10
|
+
} else return /* @__PURE__ */ jsx(SortUnsortedIcon, { style });
|
|
11
|
+
return null;
|
|
12
|
+
};
|
|
13
|
+
function Sort({ currentlySorted, name, setCurrentDirection, setCurrentlySorted, currentDirection }) {
|
|
14
|
+
const t = useStrings().common;
|
|
15
|
+
const sort = (sorted, direction) => {
|
|
16
|
+
if (sorted === name) {
|
|
17
|
+
if (direction === "ascending") setCurrentDirection("descending");
|
|
18
|
+
else if (direction === "descending") {
|
|
19
|
+
setCurrentDirection("unsorted");
|
|
20
|
+
setCurrentlySorted("");
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
setCurrentDirection("ascending");
|
|
24
|
+
setCurrentlySorted(name);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
return /* @__PURE__ */ jsx("div", {
|
|
28
|
+
className: "inline",
|
|
29
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
30
|
+
type: "button",
|
|
31
|
+
"aria-label": t.sort,
|
|
32
|
+
onClick: () => sort(currentlySorted, currentDirection),
|
|
33
|
+
children: /* @__PURE__ */ jsx(SortIcon, {
|
|
34
|
+
currentDirection,
|
|
35
|
+
currentlySorted,
|
|
36
|
+
name
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { Sort as default };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/StatusBadge.tsx
|
|
4
|
+
var variantStyles = {
|
|
5
|
+
default: "bg-(--theme-muted-panel-bg) text-(--theme-app) border-(--theme-border)",
|
|
6
|
+
success: "bg-emerald-500/10 text-emerald-800 dark:text-emerald-400 border-emerald-500/20",
|
|
7
|
+
warning: "bg-amber-500/10 text-amber-800 dark:text-amber-400 border-amber-500/20",
|
|
8
|
+
error: "bg-red-500/10 text-red-800 dark:text-red-400 border-red-500/20",
|
|
9
|
+
info: "bg-blue-500/10 text-blue-800 dark:text-blue-400 border-blue-500/20",
|
|
10
|
+
muted: "bg-(--theme-muted-panel-bg)/50 text-(--theme-muted-text-color) border-(--theme-border)"
|
|
11
|
+
};
|
|
12
|
+
var pulseColors = {
|
|
13
|
+
default: "bg-(--theme-app)",
|
|
14
|
+
success: "bg-emerald-500",
|
|
15
|
+
warning: "bg-amber-500",
|
|
16
|
+
error: "bg-red-500",
|
|
17
|
+
info: "bg-blue-500",
|
|
18
|
+
muted: "bg-(--theme-muted-text-color)"
|
|
19
|
+
};
|
|
20
|
+
var textColors = {
|
|
21
|
+
default: "text-(--theme-app)",
|
|
22
|
+
success: "text-emerald-600 dark:text-emerald-400",
|
|
23
|
+
warning: "text-amber-600 dark:text-amber-400",
|
|
24
|
+
error: "text-red-600 dark:text-red-400",
|
|
25
|
+
info: "text-blue-600 dark:text-blue-400",
|
|
26
|
+
muted: "text-(--theme-muted-text-color)"
|
|
27
|
+
};
|
|
28
|
+
/** A line of text in a variant's colour, for a status that stands beside a
|
|
29
|
+
* dot rather than inside a badge. */
|
|
30
|
+
function statusTextClass(variant) {
|
|
31
|
+
return textColors[variant];
|
|
32
|
+
}
|
|
33
|
+
function StatusBadge({ children, variant = "default", pulse = false, dot = false, size = "sm", className }) {
|
|
34
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
35
|
+
className: cx("inline-flex items-center gap-1.5 rounded-full border font-medium", size === "sm" && "px-2 py-0.5 text-[10px]", size === "md" && "px-2.5 py-1 text-xs", variantStyles[variant], className),
|
|
36
|
+
children: [
|
|
37
|
+
pulse && /* @__PURE__ */ jsxs("span", {
|
|
38
|
+
className: "relative flex h-2 w-2",
|
|
39
|
+
children: [/* @__PURE__ */ jsx("span", { className: cx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", { className: cx("relative inline-flex h-2 w-2 rounded-full", pulseColors[variant]) })]
|
|
40
|
+
}),
|
|
41
|
+
dot && !pulse && /* @__PURE__ */ jsx("span", { className: cx("inline-flex h-1.5 w-1.5 rounded-full", pulseColors[variant]) }),
|
|
42
|
+
children
|
|
43
|
+
]
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function StatusDot({ variant = "default", pulse = false, size = 8, className }) {
|
|
47
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
48
|
+
className: cx("relative inline-flex", className),
|
|
49
|
+
style: {
|
|
50
|
+
width: size,
|
|
51
|
+
height: size
|
|
52
|
+
},
|
|
53
|
+
children: [pulse && /* @__PURE__ */ jsx("span", { className: cx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", {
|
|
54
|
+
className: cx("relative inline-flex rounded-full", pulseColors[variant]),
|
|
55
|
+
style: {
|
|
56
|
+
width: size,
|
|
57
|
+
height: size
|
|
58
|
+
}
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { StatusBadge, StatusDot, statusTextClass };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { TOOLTIP_ID } from "./Tooltip.js";
|
|
2
|
+
import { Switch } from "@headlessui/react";
|
|
3
|
+
import cx from "classnames";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/SwitchToggle.tsx
|
|
7
|
+
function SwitchToggle({ onChange, id, "aria-describedby": describedBy, value = void 0, yesLabel = "Yes", noLabel = "No", disabled = false, datatip = "", invalid = false }) {
|
|
8
|
+
const [enabled, setEnabled] = useState(value ?? false);
|
|
9
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
10
|
+
const setIsEnabled = (e) => {
|
|
11
|
+
setEnabled(e);
|
|
12
|
+
onChange(e);
|
|
13
|
+
};
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (value !== void 0) setEnabled(value);
|
|
16
|
+
}, [value]);
|
|
17
|
+
const checked = value ?? enabled;
|
|
18
|
+
return /* @__PURE__ */ jsx("div", {
|
|
19
|
+
...datatip ? {
|
|
20
|
+
"data-tooltip-content": datatip,
|
|
21
|
+
"data-tooltip-id": TOOLTIP_ID
|
|
22
|
+
} : {},
|
|
23
|
+
className: cx("w-[198px] h-[30px] overflow-hidden shadow-sm rounded-md cursor-pointer ring-(--theme-border) ring-1", invalid && "border-red-600 focus:border-red-600 focus:ring-red-500 ring-1 ring-red-500", !invalid && isFocused && "ring-1 ring-[rgba(82,168,236,.8)] drop-shadow-[0_1px_2px_rgba(82,168,236,0.8)]"),
|
|
24
|
+
children: /* @__PURE__ */ jsx(Switch, {
|
|
25
|
+
id,
|
|
26
|
+
"aria-describedby": describedBy,
|
|
27
|
+
checked,
|
|
28
|
+
onChange: setIsEnabled,
|
|
29
|
+
className: "text-white text-sm shadow-sm rounded-md cursor-pointer",
|
|
30
|
+
onClick: (e) => e.stopPropagation(),
|
|
31
|
+
onFocus: () => setIsFocused(true),
|
|
32
|
+
onBlur: () => setIsFocused(false),
|
|
33
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
34
|
+
className: cx(checked ? "translate-x-0" : "-translate-x-[100px]", "relative transform flex flex-row ease-in-out duration-500", disabled && "cursor-not-allowed opacity-50"),
|
|
35
|
+
children: [
|
|
36
|
+
/* @__PURE__ */ jsx("div", {
|
|
37
|
+
className: "inline text-center capitalize px-2 py-1 w-[99px] border-0",
|
|
38
|
+
style: {
|
|
39
|
+
background: `linear-gradient(
|
|
40
|
+
to bottom,
|
|
41
|
+
var(--theme-element, #04c) 0%,
|
|
42
|
+
var(--theme-element, #08c) 100%
|
|
43
|
+
)`,
|
|
44
|
+
color: "var(--theme-element-text, #ffffff)"
|
|
45
|
+
},
|
|
46
|
+
children: yesLabel
|
|
47
|
+
}),
|
|
48
|
+
/* @__PURE__ */ jsx("div", { className: "inline px-2 py-1 h-8 w-[99px] bg-linear-to-b from-white to-[#e6e6e6]" }),
|
|
49
|
+
/* @__PURE__ */ jsx("div", {
|
|
50
|
+
className: "inline text-center capitalize px-2 py-1 w-[99px] bg-linear-to-b from-[#e6e6e6] to-white bg-[#04c] text-black",
|
|
51
|
+
children: noLabel
|
|
52
|
+
})
|
|
53
|
+
]
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { SwitchToggle as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { useStrings } from "./Provider.js";
|
|
2
|
+
import Loader from "./Loader.js";
|
|
3
3
|
import cx from "classnames";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -106,4 +106,4 @@ Table.Item = Item;
|
|
|
106
106
|
CompactTable.Header = Header;
|
|
107
107
|
CompactTable.Item = CompactItem;
|
|
108
108
|
//#endregion
|
|
109
|
-
export {
|
|
109
|
+
export { CompactTable, Table };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/Toggle.tsx
|
|
4
|
+
function Toggle({ checked, onChange, disabled, label }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
6
|
+
role: "none",
|
|
7
|
+
onClick: (e) => e.stopPropagation(),
|
|
8
|
+
className: cx("relative inline-flex items-center", disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer"),
|
|
9
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
10
|
+
type: "checkbox",
|
|
11
|
+
className: "peer sr-only",
|
|
12
|
+
checked,
|
|
13
|
+
onChange: (e) => onChange(e.target.checked),
|
|
14
|
+
disabled,
|
|
15
|
+
"aria-label": label
|
|
16
|
+
}), /* @__PURE__ */ jsx("div", { className: "h-6 w-11 rounded-full bg-(--theme-muted-panel-bg) transition-colors peer-checked:bg-(--theme-element) peer-focus-visible:ring-2 peer-focus-visible:ring-[color-mix(in_srgb,var(--theme-element)_25%,transparent)] after:absolute after:start-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:bg-white after:shadow-sm after:transition-transform after:content-[\"\"] motion-reduce:after:transition-none peer-checked:after:translate-x-5" })]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { Toggle };
|
|
@@ -1,33 +1,8 @@
|
|
|
1
1
|
import { TooltipIcon } from "../icons.js";
|
|
2
|
+
import { keyedByContent } from "./keys.js";
|
|
2
3
|
import { Fragment } from "react";
|
|
3
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
5
|
import { Tooltip } from "react-tooltip";
|
|
5
|
-
//#region src/components/keys.ts
|
|
6
|
-
/** Pairs each item with a React key from its content, suffixing repeats so keys stay unique. */
|
|
7
|
-
function keyedByContent(items, toKey) {
|
|
8
|
-
const seen = /* @__PURE__ */ new Map();
|
|
9
|
-
return items.map((item) => {
|
|
10
|
-
const base = toKey(item);
|
|
11
|
-
const count = (seen.get(base) ?? 0) + 1;
|
|
12
|
-
seen.set(base, count);
|
|
13
|
-
return {
|
|
14
|
-
key: count === 1 ? base : `${base}#${count}`,
|
|
15
|
-
item
|
|
16
|
-
};
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
/** Keys for a list whose position is its identity, such as placeholder rows or a fixed grid. */
|
|
20
|
-
function positionKeys(count, prefix = "position") {
|
|
21
|
-
return Array.from({ length: count }, (_, position) => `${prefix}-${position}`);
|
|
22
|
-
}
|
|
23
|
-
/** Pairs each item of a list that never reorders with a key from its position. */
|
|
24
|
-
function withPositionKeys(items, prefix = "position") {
|
|
25
|
-
return items.map((item, position) => ({
|
|
26
|
-
key: `${prefix}-${position}`,
|
|
27
|
-
item
|
|
28
|
-
}));
|
|
29
|
-
}
|
|
30
|
-
//#endregion
|
|
31
6
|
//#region src/components/Tooltip.tsx
|
|
32
7
|
var TOOLTIP_ID = "global-tooltip";
|
|
33
8
|
/** Anchor props that reveal `content` only while the text is ellipsized; `measure` picks the clipped descendant when it isn't the anchor. */
|
|
@@ -120,4 +95,4 @@ function TooltipInfo({ text, className = "", children, place = "top", tabIndex }
|
|
|
120
95
|
});
|
|
121
96
|
}
|
|
122
97
|
//#endregion
|
|
123
|
-
export {
|
|
98
|
+
export { GlobalTooltip, TOOLTIP_ID, TooltipInfo, formatTooltipContent, truncationTooltipProps };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CaretDownIcon } from "../icons.js";
|
|
2
|
-
import
|
|
3
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
3
|
//#region src/components/dropdownUtils.tsx
|
|
5
4
|
function isCategory(option) {
|
|
6
5
|
return typeof option === "object" && option !== null && option !== void 0 && "options" in option;
|
|
@@ -98,64 +97,4 @@ function DropdownCaret() {
|
|
|
98
97
|
return /* @__PURE__ */ jsx(CaretDownIcon, { className: "text-neutral-400 absolute top-1/2 -translate-y-1/2 right-0 mr-3 inset-y-0 flex items-center rounded-r-md focus:outline-hidden" });
|
|
99
98
|
}
|
|
100
99
|
//#endregion
|
|
101
|
-
|
|
102
|
-
var variantStyles = {
|
|
103
|
-
default: "bg-(--theme-muted-panel-bg) text-(--theme-app) border-(--theme-border)",
|
|
104
|
-
success: "bg-emerald-500/10 text-emerald-800 dark:text-emerald-400 border-emerald-500/20",
|
|
105
|
-
warning: "bg-amber-500/10 text-amber-800 dark:text-amber-400 border-amber-500/20",
|
|
106
|
-
error: "bg-red-500/10 text-red-800 dark:text-red-400 border-red-500/20",
|
|
107
|
-
info: "bg-blue-500/10 text-blue-800 dark:text-blue-400 border-blue-500/20",
|
|
108
|
-
muted: "bg-(--theme-muted-panel-bg)/50 text-(--theme-muted-text-color) border-(--theme-border)"
|
|
109
|
-
};
|
|
110
|
-
var pulseColors = {
|
|
111
|
-
default: "bg-(--theme-app)",
|
|
112
|
-
success: "bg-emerald-500",
|
|
113
|
-
warning: "bg-amber-500",
|
|
114
|
-
error: "bg-red-500",
|
|
115
|
-
info: "bg-blue-500",
|
|
116
|
-
muted: "bg-(--theme-muted-text-color)"
|
|
117
|
-
};
|
|
118
|
-
var textColors = {
|
|
119
|
-
default: "text-(--theme-app)",
|
|
120
|
-
success: "text-emerald-600 dark:text-emerald-400",
|
|
121
|
-
warning: "text-amber-600 dark:text-amber-400",
|
|
122
|
-
error: "text-red-600 dark:text-red-400",
|
|
123
|
-
info: "text-blue-600 dark:text-blue-400",
|
|
124
|
-
muted: "text-(--theme-muted-text-color)"
|
|
125
|
-
};
|
|
126
|
-
/** A line of text in a variant's colour, for a status that stands beside a
|
|
127
|
-
* dot rather than inside a badge. */
|
|
128
|
-
function statusTextClass(variant) {
|
|
129
|
-
return textColors[variant];
|
|
130
|
-
}
|
|
131
|
-
function StatusBadge({ children, variant = "default", pulse = false, dot = false, size = "sm", className }) {
|
|
132
|
-
return /* @__PURE__ */ jsxs("span", {
|
|
133
|
-
className: cx("inline-flex items-center gap-1.5 rounded-full border font-medium", size === "sm" && "px-2 py-0.5 text-[10px]", size === "md" && "px-2.5 py-1 text-xs", variantStyles[variant], className),
|
|
134
|
-
children: [
|
|
135
|
-
pulse && /* @__PURE__ */ jsxs("span", {
|
|
136
|
-
className: "relative flex h-2 w-2",
|
|
137
|
-
children: [/* @__PURE__ */ jsx("span", { className: cx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", { className: cx("relative inline-flex h-2 w-2 rounded-full", pulseColors[variant]) })]
|
|
138
|
-
}),
|
|
139
|
-
dot && !pulse && /* @__PURE__ */ jsx("span", { className: cx("inline-flex h-1.5 w-1.5 rounded-full", pulseColors[variant]) }),
|
|
140
|
-
children
|
|
141
|
-
]
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
function StatusDot({ variant = "default", pulse = false, size = 8, className }) {
|
|
145
|
-
return /* @__PURE__ */ jsxs("span", {
|
|
146
|
-
className: cx("relative inline-flex", className),
|
|
147
|
-
style: {
|
|
148
|
-
width: size,
|
|
149
|
-
height: size
|
|
150
|
-
},
|
|
151
|
-
children: [pulse && /* @__PURE__ */ jsx("span", { className: cx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", {
|
|
152
|
-
className: cx("relative inline-flex rounded-full", pulseColors[variant]),
|
|
153
|
-
style: {
|
|
154
|
-
width: size,
|
|
155
|
-
height: size
|
|
156
|
-
}
|
|
157
|
-
})]
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
//#endregion
|
|
161
|
-
export { filterOption as a, isCategory as c, DropdownCaret as i, isOption as l, StatusDot as n, flattenDisplayOptions as o, statusTextClass as r, flattenOptions as s, StatusBadge as t, toggleSetMember as u };
|
|
100
|
+
export { DropdownCaret, filterOption, flattenDisplayOptions, flattenOptions, isCategory, isOption, toggleSetMember };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/components/ghostButton.ts
|
|
2
|
+
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";
|
|
3
|
+
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";
|
|
4
|
+
/** Filled destructive button for confirming irreversible actions in ds modals. */
|
|
5
|
+
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";
|
|
6
|
+
//#endregion
|
|
7
|
+
export { dangerButtonClasses, ghostButtonClasses, primaryButtonClasses };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/components/keys.ts
|
|
2
|
+
/** Pairs each item with a React key from its content, suffixing repeats so keys stay unique. */
|
|
3
|
+
function keyedByContent(items, toKey) {
|
|
4
|
+
const seen = /* @__PURE__ */ new Map();
|
|
5
|
+
return items.map((item) => {
|
|
6
|
+
const base = toKey(item);
|
|
7
|
+
const count = (seen.get(base) ?? 0) + 1;
|
|
8
|
+
seen.set(base, count);
|
|
9
|
+
return {
|
|
10
|
+
key: count === 1 ? base : `${base}#${count}`,
|
|
11
|
+
item
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
/** Keys for a list whose position is its identity, such as placeholder rows or a fixed grid. */
|
|
16
|
+
function positionKeys(count, prefix = "position") {
|
|
17
|
+
return Array.from({ length: count }, (_, position) => `${prefix}-${position}`);
|
|
18
|
+
}
|
|
19
|
+
/** Pairs each item of a list that never reorders with a key from its position. */
|
|
20
|
+
function withPositionKeys(items, prefix = "position") {
|
|
21
|
+
return items.map((item, position) => ({
|
|
22
|
+
key: `${prefix}-${position}`,
|
|
23
|
+
item
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { keyedByContent, positionKeys, withPositionKeys };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useStrings } from "./Provider.js";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { DateTime } from "luxon";
|
|
4
|
+
//#region src/components/relativeTime.ts
|
|
5
|
+
var TICK_MS = 3e4;
|
|
6
|
+
function compactRelativeMinutes(minutes, t) {
|
|
7
|
+
if (!Number.isFinite(minutes) || minutes < 1) return t.now;
|
|
8
|
+
if (minutes < 60) return t.minutes(minutes);
|
|
9
|
+
const hours = Math.floor(minutes / 60);
|
|
10
|
+
if (hours < 24) return t.hours(hours);
|
|
11
|
+
const days = Math.floor(hours / 24);
|
|
12
|
+
if (days < 365) return t.days(days);
|
|
13
|
+
return t.years(Math.floor(days / 365));
|
|
14
|
+
}
|
|
15
|
+
/** A clock that re-reads itself, so "5m" ages while the page sits open, with
|
|
16
|
+
* the abbreviated form a row has room for. */
|
|
17
|
+
function useRelativeTime() {
|
|
18
|
+
const t = useStrings().time;
|
|
19
|
+
const [now, setNow] = useState(() => DateTime.now());
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const id = setInterval(() => setNow(DateTime.now()), TICK_MS);
|
|
22
|
+
return () => clearInterval(id);
|
|
23
|
+
}, []);
|
|
24
|
+
const compactMinutes = (minutes) => compactRelativeMinutes(minutes, t);
|
|
25
|
+
return {
|
|
26
|
+
now,
|
|
27
|
+
compactMinutes,
|
|
28
|
+
compact: (iso) => iso ? compactMinutes(Math.floor(now.diff(DateTime.fromISO(iso)).as("minutes"))) : ""
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { compactRelativeMinutes, useRelativeTime };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Loader from "../components/Loader.js";
|
|
2
|
+
import { Suspense, lazy } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/editor/Editor.tsx
|
|
5
|
+
var MonacoEditor = lazy(() => import("./Monaco.js"));
|
|
6
|
+
function Editor({ ...props }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(Suspense, {
|
|
8
|
+
fallback: /* @__PURE__ */ jsx(Loader, { text: "Loading editor..." }),
|
|
9
|
+
children: /* @__PURE__ */ jsx(MonacoEditor, { ...props })
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { Editor as default };
|