@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
package/dist/ai/ai.css
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/* Chat-specific styles: markdown rendering (streamdown output) and the
|
|
2
|
+
* streaming/thinking animations. */
|
|
3
|
+
|
|
4
|
+
/* Answers are read at length, so their ink sits further from the page than
|
|
5
|
+
* the theme's UI text: pulled toward black on a light scheme and toward white
|
|
6
|
+
* on a dark one, from whatever ink the theme (or an org palette) supplies. */
|
|
7
|
+
.chat-ink {
|
|
8
|
+
--chat-ink: light-dark(
|
|
9
|
+
color-mix(in oklab, var(--theme-panel, #000) 60%, black),
|
|
10
|
+
color-mix(in oklab, var(--theme-panel, #fff) 75%, white)
|
|
11
|
+
);
|
|
12
|
+
color: var(--chat-ink);
|
|
13
|
+
--tw-prose-body: var(--chat-ink);
|
|
14
|
+
--tw-prose-headings: var(--chat-ink);
|
|
15
|
+
--tw-prose-bold: var(--chat-ink);
|
|
16
|
+
--tw-prose-code: var(--chat-ink);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Links */
|
|
20
|
+
.markdown a {
|
|
21
|
+
color: var(--theme-link, #428bca);
|
|
22
|
+
text-decoration: none;
|
|
23
|
+
}
|
|
24
|
+
.markdown a:hover {
|
|
25
|
+
text-decoration: underline;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Lists hang their markers in the gutter so a wrapped line lines up with the
|
|
29
|
+
* text above it, not with the number. Streamdown sets them inside. */
|
|
30
|
+
.markdown ol,
|
|
31
|
+
.markdown ul {
|
|
32
|
+
list-style-position: outside;
|
|
33
|
+
padding-left: 1.625em;
|
|
34
|
+
}
|
|
35
|
+
.markdown li {
|
|
36
|
+
padding-left: 0.25em;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Horizontal rules */
|
|
40
|
+
.markdown hr {
|
|
41
|
+
display: block;
|
|
42
|
+
height: 0;
|
|
43
|
+
border: 0;
|
|
44
|
+
border-top: 1px solid var(--theme-border, #e5e7eb);
|
|
45
|
+
margin: 1.5em 0;
|
|
46
|
+
padding: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Inline code — code blocks are styled by Streamdown. A tint of the ink and
|
|
50
|
+
* no border: a hard outline turns every identifier into a keycap. */
|
|
51
|
+
.markdown code {
|
|
52
|
+
/* rem, not em: a table cell or list already sized down would size it twice. */
|
|
53
|
+
font-size: 0.875rem;
|
|
54
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
55
|
+
padding: 0.125em 0.375em;
|
|
56
|
+
background-color: color-mix(in oklab, var(--theme-panel, #000) 8%, transparent);
|
|
57
|
+
border-radius: 0.25rem;
|
|
58
|
+
/* Identifiers carry a colour of their own so they read as code at a glance
|
|
59
|
+
* without the weight the plugin gives them: the theme's link blue, which
|
|
60
|
+
* every palette already keeps legible on its surfaces. */
|
|
61
|
+
color: var(--theme-link, #2f6fa8);
|
|
62
|
+
font-weight: 400;
|
|
63
|
+
}
|
|
64
|
+
/* Reset inline code styles when inside a pre (code block) */
|
|
65
|
+
.markdown pre code {
|
|
66
|
+
padding: 0;
|
|
67
|
+
background-color: transparent;
|
|
68
|
+
border: none;
|
|
69
|
+
border-radius: 0;
|
|
70
|
+
font-size: inherit;
|
|
71
|
+
color: inherit;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* KaTeX overrides */
|
|
75
|
+
.katex-display {
|
|
76
|
+
margin: 1em 0;
|
|
77
|
+
overflow-x: auto;
|
|
78
|
+
overflow-y: hidden;
|
|
79
|
+
}
|
|
80
|
+
.katex {
|
|
81
|
+
font-size: 1.1em;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Subscript and superscript */
|
|
85
|
+
.markdown sub,
|
|
86
|
+
.markdown sup {
|
|
87
|
+
font-size: 75%;
|
|
88
|
+
line-height: 0;
|
|
89
|
+
position: relative;
|
|
90
|
+
vertical-align: baseline;
|
|
91
|
+
}
|
|
92
|
+
.markdown sup {
|
|
93
|
+
top: -0.5em;
|
|
94
|
+
}
|
|
95
|
+
.markdown sub {
|
|
96
|
+
bottom: -0.25em;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Images */
|
|
100
|
+
.markdown img {
|
|
101
|
+
border: 0;
|
|
102
|
+
max-width: 100%;
|
|
103
|
+
height: auto;
|
|
104
|
+
vertical-align: middle;
|
|
105
|
+
border-radius: 0.5rem;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Streamdown tables: the body's own type,
|
|
109
|
+
* hairlines at a tenth of the ink, a header on a five-percent tint, and the
|
|
110
|
+
* copy/download controls only while the pointer is over the table. */
|
|
111
|
+
.markdown [data-streamdown="table-wrapper"] {
|
|
112
|
+
--table-line: color-mix(in oklab, var(--theme-panel, #000) 10%, transparent);
|
|
113
|
+
position: relative;
|
|
114
|
+
display: block;
|
|
115
|
+
background: transparent;
|
|
116
|
+
border: none;
|
|
117
|
+
padding: 0;
|
|
118
|
+
margin: 0.75rem 0;
|
|
119
|
+
}
|
|
120
|
+
.markdown [data-streamdown="table-wrapper"] > div:first-child {
|
|
121
|
+
position: absolute;
|
|
122
|
+
top: 0.375rem;
|
|
123
|
+
right: 0.375rem;
|
|
124
|
+
z-index: 1;
|
|
125
|
+
gap: 0.125rem;
|
|
126
|
+
padding: 0.125rem;
|
|
127
|
+
border-radius: 0.375rem;
|
|
128
|
+
background: var(--theme-panel-bg, #fff);
|
|
129
|
+
border: 1px solid var(--table-line);
|
|
130
|
+
opacity: 0;
|
|
131
|
+
transition: opacity 150ms ease-out;
|
|
132
|
+
}
|
|
133
|
+
.markdown [data-streamdown="table-wrapper"]:hover > div:first-child,
|
|
134
|
+
.markdown [data-streamdown="table-wrapper"]:focus-within > div:first-child {
|
|
135
|
+
opacity: 1;
|
|
136
|
+
}
|
|
137
|
+
.markdown [data-streamdown="table-wrapper"] > div:last-child {
|
|
138
|
+
padding: 0;
|
|
139
|
+
border: 1px solid var(--table-line);
|
|
140
|
+
border-radius: 0.5rem;
|
|
141
|
+
background: transparent;
|
|
142
|
+
}
|
|
143
|
+
.markdown [data-streamdown="table-wrapper"] table {
|
|
144
|
+
margin: 0;
|
|
145
|
+
font-size: 1rem;
|
|
146
|
+
line-height: 1.5;
|
|
147
|
+
}
|
|
148
|
+
.markdown [data-streamdown="table"] th {
|
|
149
|
+
padding: 0.4375rem 0.75rem;
|
|
150
|
+
font-size: 1rem;
|
|
151
|
+
font-weight: 500;
|
|
152
|
+
color: inherit;
|
|
153
|
+
background: color-mix(in oklab, var(--theme-panel, #000) 5%, transparent);
|
|
154
|
+
border-bottom: 1px solid var(--table-line);
|
|
155
|
+
}
|
|
156
|
+
.markdown [data-streamdown="table"] td {
|
|
157
|
+
padding: 0.4375rem 0.75rem;
|
|
158
|
+
/* Streamdown sizes cells down with its own class; the table is body type. */
|
|
159
|
+
font-size: 1rem;
|
|
160
|
+
line-height: 1.5;
|
|
161
|
+
vertical-align: top;
|
|
162
|
+
color: inherit;
|
|
163
|
+
/* A prose column keeps enough room to read; a wide table scrolls instead. */
|
|
164
|
+
min-width: 9rem;
|
|
165
|
+
}
|
|
166
|
+
.markdown [data-streamdown="table"] tbody tr {
|
|
167
|
+
border-bottom: 1px solid var(--table-line);
|
|
168
|
+
}
|
|
169
|
+
.markdown [data-streamdown="table"] tbody tr:last-child {
|
|
170
|
+
border-bottom: 0;
|
|
171
|
+
}
|
|
172
|
+
@media (prefers-reduced-motion: reduce) {
|
|
173
|
+
.markdown [data-streamdown="table-wrapper"] > div:first-child {
|
|
174
|
+
transition: none;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* Streamdown code blocks — tighten spacing, remove inner double-border */
|
|
179
|
+
.markdown [data-streamdown="code-block"] {
|
|
180
|
+
padding: 0.375rem 0.5rem 0;
|
|
181
|
+
margin: 0.5em 0;
|
|
182
|
+
gap: 0;
|
|
183
|
+
}
|
|
184
|
+
.markdown [data-streamdown="code-block-header"] {
|
|
185
|
+
padding: 0.25rem 0.25rem;
|
|
186
|
+
}
|
|
187
|
+
.markdown [data-streamdown="code-block-body"] {
|
|
188
|
+
border: none;
|
|
189
|
+
border-radius: 0 0 0.5rem 0.5rem;
|
|
190
|
+
padding: 0;
|
|
191
|
+
}
|
|
192
|
+
/* Remove prose pre margin and code block body inner pre margin */
|
|
193
|
+
.markdown [data-streamdown="code-block-body"] pre {
|
|
194
|
+
margin: 0;
|
|
195
|
+
padding: 0.75rem 1rem;
|
|
196
|
+
overflow-x: auto;
|
|
197
|
+
/* Code reads looser than prose; Streamdown's text-sm line is too tight. */
|
|
198
|
+
line-height: 1.6;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* Shiki dual-theme color overrides (standard Shiki approach).
|
|
202
|
+
Streamdown uses Tailwind dark: arbitrary-value classes for theme switching,
|
|
203
|
+
but Tailwind v4's source scanner can misparse them from minified JS —
|
|
204
|
+
generating broken selectors that apply dark bg unconditionally while
|
|
205
|
+
missing the text color classes entirely. Override both light and dark
|
|
206
|
+
explicitly to ensure correct colors in all modes.
|
|
207
|
+
See: https://shiki.style/guide/dual-themes#class-based-dark-mode */
|
|
208
|
+
|
|
209
|
+
/* Light mode: use the primary Shiki theme (--sdm-bg/--sdm-c) */
|
|
210
|
+
.markdown [data-streamdown="code-block-body"] pre {
|
|
211
|
+
background-color: var(--sdm-bg, inherit) !important;
|
|
212
|
+
color: var(--sdm-fg, inherit);
|
|
213
|
+
}
|
|
214
|
+
.markdown [data-streamdown="code-block-body"] pre code > span > span {
|
|
215
|
+
color: var(--sdm-c, inherit);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* Dark mode: switch to --shiki-dark variants */
|
|
219
|
+
.dark .markdown [data-streamdown="code-block-body"] pre {
|
|
220
|
+
background-color: var(--shiki-dark-bg, var(--sdm-bg, inherit)) !important;
|
|
221
|
+
color: var(--shiki-dark, var(--sdm-fg, inherit));
|
|
222
|
+
}
|
|
223
|
+
.dark .markdown [data-streamdown="code-block-body"] pre code > span > span {
|
|
224
|
+
color: var(--shiki-dark, inherit);
|
|
225
|
+
font-style: var(--shiki-dark-font-style, inherit);
|
|
226
|
+
font-weight: var(--shiki-dark-font-weight, inherit);
|
|
227
|
+
text-decoration: var(--shiki-dark-text-decoration, inherit);
|
|
228
|
+
}
|
|
229
|
+
.dark .markdown [data-streamdown="code-block-body"] pre code > span > span[style*="--sdm-tbg"] {
|
|
230
|
+
background-color: var(--shiki-dark-bg, var(--sdm-tbg));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/* Remove prose backtick pseudo-elements on inline code */
|
|
234
|
+
.markdown code::before,
|
|
235
|
+
.markdown code::after {
|
|
236
|
+
content: none !important;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* Task lists (checkboxes) */
|
|
240
|
+
.markdown input[type="checkbox"] {
|
|
241
|
+
margin-right: 0.5em;
|
|
242
|
+
vertical-align: middle;
|
|
243
|
+
}
|
|
244
|
+
.markdown li:has(> input[type="checkbox"]) {
|
|
245
|
+
list-style: none;
|
|
246
|
+
margin-left: -1.5em;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* Touch device: always show chat actions */
|
|
250
|
+
@media (hover: none) {
|
|
251
|
+
.chat-actions,
|
|
252
|
+
.chat-meta {
|
|
253
|
+
opacity: 1 !important;
|
|
254
|
+
pointer-events: auto !important;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Long finished replies clamp with a bottom fade; mask keeps the fade
|
|
259
|
+
* background-agnostic across themes. */
|
|
260
|
+
.chat-message-clamp {
|
|
261
|
+
max-height: 600px;
|
|
262
|
+
overflow: hidden;
|
|
263
|
+
mask-image: linear-gradient(to bottom, black calc(100% - 96px), transparent);
|
|
264
|
+
-webkit-mask-image: linear-gradient(to bottom, black calc(100% - 96px), transparent);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Theme-aware input styling (matches the host app's .theme-input; defined
|
|
268
|
+
* here too so the edit textarea is styled in standalone use) */
|
|
269
|
+
.theme-input {
|
|
270
|
+
background-color: var(--theme-input-bg, #f9fafb);
|
|
271
|
+
border-color: var(--theme-border, #d1d5db);
|
|
272
|
+
color: var(--theme-app, #374151);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.theme-input:focus {
|
|
276
|
+
border-color: var(--theme-element, #3b82f6);
|
|
277
|
+
outline: none;
|
|
278
|
+
box-shadow: 0 0 0 1px var(--theme-element, #3b82f6);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@keyframes shimmer {
|
|
282
|
+
0% {
|
|
283
|
+
background-position: 200% 0;
|
|
284
|
+
}
|
|
285
|
+
100% {
|
|
286
|
+
background-position: -200% 0;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@utility animate-shimmer {
|
|
291
|
+
animation: shimmer 1.75s linear infinite;
|
|
292
|
+
background-size: 200% 100%;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@utility text-shimmer {
|
|
296
|
+
background-image: linear-gradient(
|
|
297
|
+
90deg,
|
|
298
|
+
var(--theme-muted-text-color, #6a7282) 0%,
|
|
299
|
+
var(--theme-app, #d1d5db) 20%,
|
|
300
|
+
var(--theme-muted-text-color, #6a7282) 40%
|
|
301
|
+
);
|
|
302
|
+
-webkit-background-clip: text;
|
|
303
|
+
background-clip: text;
|
|
304
|
+
color: transparent;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/* Entrance animation for chat messages (CSS replacement for a JS motion lib).
|
|
308
|
+
* Only `from` is defined so elements settle at their natural styles (queued
|
|
309
|
+
* messages render at reduced opacity). */
|
|
310
|
+
@keyframes chat-fade-in-up {
|
|
311
|
+
from {
|
|
312
|
+
opacity: 0;
|
|
313
|
+
transform: translateY(8px);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
@utility animate-chat-enter {
|
|
318
|
+
animation: chat-fade-in-up 0.25s ease-out;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
@media (prefers-reduced-motion: reduce) {
|
|
322
|
+
.animate-chat-enter {
|
|
323
|
+
animation: none;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useChat } from "../core/ChatProvider.js";
|
|
2
|
+
import Dropdown from "../ui/Dropdown.js";
|
|
3
|
+
import { isOrgModel } from "../utils.js";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import useSWR from "swr";
|
|
7
|
+
//#region src/ai/components/AllocationSelector.tsx
|
|
8
|
+
function AllocationSelector({ variant = "default" } = {}) {
|
|
9
|
+
const bare = variant === "bare";
|
|
10
|
+
const { adapter, selectedProvider, selectedAllocation, setSelectedAllocation } = useChat();
|
|
11
|
+
const isOrgProvider = isOrgModel(selectedProvider);
|
|
12
|
+
const allocationsAdapter = adapter.allocations;
|
|
13
|
+
const { data: allocations } = useSWR(isOrgProvider && allocationsAdapter ? ["ai-chat-allocations"] : null, () => allocationsAdapter.list());
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (isOrgProvider && allocations?.length && !selectedAllocation) setSelectedAllocation(allocations[0].name);
|
|
16
|
+
}, [
|
|
17
|
+
isOrgProvider,
|
|
18
|
+
allocations,
|
|
19
|
+
selectedAllocation,
|
|
20
|
+
setSelectedAllocation
|
|
21
|
+
]);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!isOrgProvider && selectedAllocation) setSelectedAllocation(null);
|
|
24
|
+
}, [
|
|
25
|
+
isOrgProvider,
|
|
26
|
+
selectedAllocation,
|
|
27
|
+
setSelectedAllocation
|
|
28
|
+
]);
|
|
29
|
+
if (!isOrgProvider || !allocations?.length) return null;
|
|
30
|
+
const options = allocations.map((alloc) => ({
|
|
31
|
+
label: alloc.name,
|
|
32
|
+
value: alloc.name
|
|
33
|
+
}));
|
|
34
|
+
const selected = allocations.find((a) => a.name === selectedAllocation);
|
|
35
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
36
|
+
className: "flex items-center gap-2",
|
|
37
|
+
children: [/* @__PURE__ */ jsx(Dropdown, {
|
|
38
|
+
options,
|
|
39
|
+
value: selectedAllocation ?? "",
|
|
40
|
+
onChange: (v) => setSelectedAllocation(v || null),
|
|
41
|
+
variant,
|
|
42
|
+
textBoxClassName: bare ? "rounded-md px-1.5 py-0.5 text-[11px] hover:theme-muted-panel" : "h-8 rounded-lg border theme-border text-xs px-2",
|
|
43
|
+
placeholder: "Select allocation"
|
|
44
|
+
}), selected && /* @__PURE__ */ jsxs("span", {
|
|
45
|
+
className: "text-[10px] theme-muted-text whitespace-nowrap",
|
|
46
|
+
children: [
|
|
47
|
+
"$",
|
|
48
|
+
(selected.used ?? 0).toFixed(2),
|
|
49
|
+
" / $",
|
|
50
|
+
selected.total.toFixed(2)
|
|
51
|
+
]
|
|
52
|
+
})]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { AllocationSelector as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function AttachmentManager(): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { DownloadFileIcon, FileIcon, TrashIcon } from "../../icons.js";
|
|
2
|
+
import { useChatConfig } from "../core/config.js";
|
|
3
|
+
import { useChat } from "../core/ChatProvider.js";
|
|
4
|
+
import { formatFileSize } from "../utils.js";
|
|
5
|
+
import { attachmentsPageKey } from "./attachmentKeys.js";
|
|
6
|
+
import cx from "classnames";
|
|
7
|
+
import { useCallback, useMemo, useState } from "react";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { DateTime } from "luxon";
|
|
10
|
+
import useSWRInfinite from "swr/infinite";
|
|
11
|
+
//#region src/ai/components/AttachmentManager.tsx
|
|
12
|
+
function triggerDownload(url, filename) {
|
|
13
|
+
const a = document.createElement("a");
|
|
14
|
+
a.href = url;
|
|
15
|
+
a.download = filename;
|
|
16
|
+
document.body.appendChild(a);
|
|
17
|
+
a.click();
|
|
18
|
+
document.body.removeChild(a);
|
|
19
|
+
}
|
|
20
|
+
function AttachmentManager() {
|
|
21
|
+
const { adapter, notify } = useChat();
|
|
22
|
+
const t = useChatConfig().strings.attachmentManager;
|
|
23
|
+
const attachmentsAdapter = adapter.attachments;
|
|
24
|
+
const [deleting, setDeleting] = useState(null);
|
|
25
|
+
const [thumbnails, setThumbnails] = useState({});
|
|
26
|
+
const markThumbnail = useCallback((attachmentId, state) => {
|
|
27
|
+
setThumbnails((previous) => previous[attachmentId] === state ? previous : {
|
|
28
|
+
...previous,
|
|
29
|
+
[attachmentId]: state
|
|
30
|
+
});
|
|
31
|
+
}, []);
|
|
32
|
+
const { data: pages, size, setSize, isLoading, isValidating, mutate } = useSWRInfinite(attachmentsAdapter ? attachmentsPageKey : () => null, ([, cursor]) => attachmentsAdapter.list({
|
|
33
|
+
limit: 24,
|
|
34
|
+
cursor
|
|
35
|
+
}));
|
|
36
|
+
const attachments = useMemo(() => pages?.flatMap((page) => page?.attachments ?? []) ?? [], [pages]);
|
|
37
|
+
const handleDelete = useCallback(async (attachmentId) => {
|
|
38
|
+
if (!attachmentsAdapter) return;
|
|
39
|
+
setDeleting(attachmentId);
|
|
40
|
+
try {
|
|
41
|
+
await attachmentsAdapter.remove(attachmentId);
|
|
42
|
+
await mutate();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
notify.error(error instanceof Error ? error.message : String(error));
|
|
45
|
+
} finally {
|
|
46
|
+
setDeleting(null);
|
|
47
|
+
}
|
|
48
|
+
}, [
|
|
49
|
+
attachmentsAdapter,
|
|
50
|
+
mutate,
|
|
51
|
+
notify
|
|
52
|
+
]);
|
|
53
|
+
if (!attachmentsAdapter) return null;
|
|
54
|
+
const hasMore = pages?.[pages.length - 1]?.hasMore ?? false;
|
|
55
|
+
return /* @__PURE__ */ jsx("div", {
|
|
56
|
+
className: "flex h-full bg-(--theme-app-bg)",
|
|
57
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
58
|
+
className: "flex-1 flex flex-col min-w-0",
|
|
59
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
60
|
+
className: "flex-1 overflow-y-auto p-8",
|
|
61
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
62
|
+
className: "max-w-4xl mx-auto",
|
|
63
|
+
children: [/* @__PURE__ */ jsx("h1", {
|
|
64
|
+
className: "text-2xl font-semibold mb-6 text-(--theme-panel)",
|
|
65
|
+
children: t.title
|
|
66
|
+
}), isLoading && attachments.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
67
|
+
className: "flex items-center justify-center py-12",
|
|
68
|
+
children: /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-2 border-current border-t-transparent theme-muted-text" })
|
|
69
|
+
}) : attachments.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
70
|
+
className: "text-center theme-muted-text py-12 text-sm",
|
|
71
|
+
children: t.empty
|
|
72
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
73
|
+
className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4",
|
|
74
|
+
children: attachments.map((att) => {
|
|
75
|
+
const downloadUrl = attachmentsAdapter.downloadUrl(att.id);
|
|
76
|
+
const isDeleting = deleting === att.id;
|
|
77
|
+
const thumbnail = thumbnails[att.id];
|
|
78
|
+
const showThumbnail = att.contentType?.startsWith("image/") && thumbnail !== "broken";
|
|
79
|
+
const openProps = attachmentsAdapter.onOpen ? {
|
|
80
|
+
onClick: () => attachmentsAdapter.onOpen?.(att),
|
|
81
|
+
role: "button",
|
|
82
|
+
style: { cursor: "pointer" }
|
|
83
|
+
} : {};
|
|
84
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
85
|
+
className: cx("rounded-lg border theme-border overflow-hidden", isDeleting && "opacity-50 pointer-events-none"),
|
|
86
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
87
|
+
className: "relative aspect-square bg-(--theme-muted-panel-bg) flex items-center justify-center",
|
|
88
|
+
...openProps,
|
|
89
|
+
children: [/* @__PURE__ */ jsx(FileIcon, { className: "w-8 h-8 theme-muted-text" }), showThumbnail && /* @__PURE__ */ jsx("img", {
|
|
90
|
+
src: downloadUrl,
|
|
91
|
+
alt: att.filename || "Image",
|
|
92
|
+
className: cx("absolute inset-0 w-full h-full object-cover", thumbnail !== "loaded" && "opacity-0"),
|
|
93
|
+
loading: "lazy",
|
|
94
|
+
onLoad: () => markThumbnail(att.id, "loaded"),
|
|
95
|
+
onError: () => markThumbnail(att.id, "broken")
|
|
96
|
+
})]
|
|
97
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
98
|
+
className: "p-3 text-xs bg-(--theme-panel-bg) flex items-center justify-between gap-1",
|
|
99
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
100
|
+
className: "min-w-0 flex-1",
|
|
101
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
102
|
+
className: "truncate font-medium text-(--theme-panel)",
|
|
103
|
+
children: att.filename || "File"
|
|
104
|
+
}), /* @__PURE__ */ jsxs("p", {
|
|
105
|
+
className: "truncate theme-muted-text",
|
|
106
|
+
children: [att.size ? formatFileSize(att.size) : "", att.uploadedAt && /* @__PURE__ */ jsxs(Fragment$1, { children: [att.size ? " · " : "", DateTime.fromISO(att.uploadedAt).toRelative()] })]
|
|
107
|
+
})]
|
|
108
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
109
|
+
className: "flex items-center gap-0.5 flex-shrink-0",
|
|
110
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
111
|
+
type: "button",
|
|
112
|
+
onClick: () => triggerDownload(downloadUrl, att.filename || "File"),
|
|
113
|
+
className: "p-1.5 rounded-lg hover:theme-hover theme-muted-text transition-colors",
|
|
114
|
+
title: t.download,
|
|
115
|
+
children: /* @__PURE__ */ jsx(DownloadFileIcon, { className: "w-4 h-4" })
|
|
116
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
117
|
+
type: "button",
|
|
118
|
+
onClick: () => handleDelete(att.id),
|
|
119
|
+
disabled: isDeleting,
|
|
120
|
+
className: "p-1.5 rounded-lg hover:bg-red-500/15 theme-muted-text hover:text-red-600 transition-colors",
|
|
121
|
+
title: t.delete,
|
|
122
|
+
children: /* @__PURE__ */ jsx(TrashIcon, { className: "w-4 h-4" })
|
|
123
|
+
})]
|
|
124
|
+
})]
|
|
125
|
+
})]
|
|
126
|
+
}, att.id);
|
|
127
|
+
})
|
|
128
|
+
}), hasMore && /* @__PURE__ */ jsx("div", {
|
|
129
|
+
className: "flex justify-center mt-8",
|
|
130
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
131
|
+
type: "button",
|
|
132
|
+
onClick: () => setSize(size + 1),
|
|
133
|
+
disabled: isValidating,
|
|
134
|
+
className: "px-6 py-3 text-sm rounded-lg theme-muted-panel hover:theme-hover transition-colors disabled:opacity-50",
|
|
135
|
+
children: isValidating ? t.loading : t.loadMore
|
|
136
|
+
})
|
|
137
|
+
})] })]
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
export { AttachmentManager as default };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface AttachmentUploadHandle {
|
|
2
|
+
addFiles: (files: FileList | File[]) => void;
|
|
3
|
+
}
|
|
4
|
+
export interface Attachment {
|
|
5
|
+
id?: string;
|
|
6
|
+
file?: File;
|
|
7
|
+
filename: string;
|
|
8
|
+
mimeType: string;
|
|
9
|
+
size: number;
|
|
10
|
+
uploading?: boolean;
|
|
11
|
+
uploaded?: boolean;
|
|
12
|
+
error?: string;
|
|
13
|
+
url?: string;
|
|
14
|
+
}
|
|
15
|
+
interface AttachmentUploadProps {
|
|
16
|
+
conversationId?: string | undefined;
|
|
17
|
+
attachments: Attachment[];
|
|
18
|
+
onAttachmentsChange: (attachments: Attachment[]) => void;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
maxFiles?: number;
|
|
21
|
+
maxFileSize?: number;
|
|
22
|
+
}
|
|
23
|
+
declare const AttachmentUpload: import("react").ForwardRefExoticComponent<AttachmentUploadProps & import("react").RefAttributes<AttachmentUploadHandle>>;
|
|
24
|
+
export default AttachmentUpload;
|