@kortix/ui 0.14.5 → 0.14.7
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/_vendor/kortix-shared.js +489 -381
- package/dist/access/access/access-dialog.js +8 -5
- package/dist/access/access/copy-row.js +2 -2
- package/dist/access/sharing-picker.js +2 -1
- package/dist/browser/app-in-browser.js +5 -3
- package/dist/browser/browser-panel.js +6 -6
- package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
- package/dist/browser/sandbox-browser-chrome.js +4 -3
- package/dist/customize/agents/agent-access.d.ts +20 -0
- package/dist/customize/agents/agent-access.js +17 -0
- package/dist/customize/agents/agent-authority-card.js +1 -2
- package/dist/customize/agents/agent-detail-aside.js +15 -14
- package/dist/customize/agents/agent-drives-section.js +5 -6
- package/dist/customize/agents/agent-grant-pages.js +73 -76
- package/dist/customize/agents/agent-nav.prototype.d.ts +35 -0
- package/dist/customize/agents/agent-nav.prototype.js +95 -0
- package/dist/customize/agents/agent-page.js +59 -23
- package/dist/customize/agents/agent-people-section.js +18 -17
- package/dist/customize/agents/agent-triggers-section.js +6 -5
- package/dist/customize/agents/agents-page.js +18 -1
- package/dist/customize/connectors/add-mcp/add-mcp-server.js +4 -2
- package/dist/customize/connectors/catalog/catalog-entry.d.ts +14 -0
- package/dist/customize/connectors/catalog/catalog-entry.js +18 -1
- package/dist/customize/connectors/catalog/connector-browse.d.ts +28 -0
- package/dist/customize/connectors/catalog/connector-browse.js +18 -5
- package/dist/customize/connectors/connector-routes.d.ts +3 -1
- package/dist/customize/connectors/connector-routes.js +18 -0
- package/dist/customize/connectors/connectors-page.js +23 -4
- package/dist/customize/connectors/detail/app-page.js +19 -5
- package/dist/customize/connectors/detail/connector-advanced-tools.js +4 -6
- package/dist/customize/connectors/detail/connector-modal.d.ts +10 -13
- package/dist/customize/connectors/detail/connector-modal.js +18 -101
- package/dist/customize/connectors/detail/connector-notice.js +6 -2
- package/dist/customize/connectors/detail/connector-page.d.ts +30 -0
- package/dist/customize/connectors/detail/connector-page.js +26 -13
- package/dist/customize/providers/provider-accordion.js +2 -1
- package/dist/customize/providers/provider-connect.js +2 -1
- package/dist/customize/sections/component/telegram-channel-row.js +1 -1
- package/dist/customize/sections/connector-connection-modal.js +11 -9
- package/dist/customize/sections/connectors-view.js +11 -13
- package/dist/customize/sections/llm-provider/custom-provider-form.js +24 -7
- package/dist/customize/sections/llm-provider/custom-provider-panel.js +44 -8
- package/dist/customize/sections/llm-provider/types.d.ts +3 -0
- package/dist/customize/sections/llm-provider/utils.js +2 -2
- package/dist/customize/sections/view/agent-editor-access-fields.d.ts +9 -16
- package/dist/customize/sections/view/agent-editor-access-fields.js +30 -30
- package/dist/customize/sections/view/agent-editor-basics-fields.js +3 -10
- package/dist/customize/sections/view/agent-editor-primitives.d.ts +28 -10
- package/dist/customize/sections/view/agent-editor-primitives.js +32 -19
- package/dist/customize/sections/view/agent-editor.js +3 -3
- package/dist/customize/sections/view/gateway/gateway-routing.js +18 -21
- package/dist/customize/sections/view/grant-mode-field.d.ts +2 -5
- package/dist/customize/sections/view/grant-mode-field.js +10 -18
- package/dist/customize/sections/view/permission-editor.js +11 -8
- package/dist/customize/sections/view/secrets-view.js +2 -1
- package/dist/customize/settings/rail-copy-context.js +5 -3
- package/dist/customize/settings/tabs/general-tab.d.ts +9 -2
- package/dist/customize/settings/tabs/general-tab.js +33 -11
- package/dist/customize/settings/tabs/sandbox-template-form.js +9 -12
- package/dist/customize/settings/tabs/transfer-workspace-dialog.d.ts +4 -0
- package/dist/customize/settings/tabs/transfer-workspace-dialog.js +82 -0
- package/dist/customize/shared/capability-tabs.js +2 -1
- package/dist/customize/skills/skills-page.js +3 -5
- package/dist/customize/triggers/schedule/event-trigger-copy.js +3 -2
- package/dist/customize/triggers/schedule/schedule-builder.js +7 -4
- package/dist/customize/triggers/schedule/trigger-composer.js +5 -2
- package/dist/customize/triggers/schedule/when-event.js +1 -1
- package/dist/diff/diff-view.js +9 -10
- package/dist/files/editor/code-editor.js +2 -3
- package/dist/files/project/api/runtime-files.js +3 -2
- package/dist/files/project/components/change-request-detail-dialog.d.ts +3 -1
- package/dist/files/project/components/change-request-detail-dialog.js +3 -5
- package/dist/files/project/components/change-request-status-badge.d.ts +12 -0
- package/dist/files/project/components/change-request-status-badge.js +27 -0
- package/dist/files/project/components/change-requests-panel.js +1 -1
- package/dist/files/project/components/drive-explorer.js +2 -1
- package/dist/files/project/components/drive-grid-view.js +11 -7
- package/dist/files/project/components/drive-list-view.js +4 -4
- package/dist/files/project/components/file-breadcrumbs.js +1 -1
- package/dist/files/project/components/file-explorer-page.js +1 -1
- package/dist/files/project/components/file-history-popover.js +1 -6
- package/dist/files/project/components/file-search.js +6 -1
- package/dist/files/project/components/open-change-request-dialog.js +2 -1
- package/dist/files/project/components/version-selector-logic.d.ts +11 -0
- package/dist/files/project/components/version-selector-logic.js +26 -0
- package/dist/files/project/components/version-selector.js +11 -20
- package/dist/files/project/file-source.js +18 -1
- package/dist/files/project/hooks/use-file-content.js +2 -0
- package/dist/files/project/hooks/use-server-health.js +17 -15
- package/dist/files/renderers/docx/docx-viewer.js +0 -5
- package/dist/files/renderers/image-renderer.js +6 -24
- package/dist/files/renderers/pdf/pdf-viewer.js +1 -1
- package/dist/files/renderers/presentation/FullScreenPresentationViewer.js +2 -11
- package/dist/files/renderers/show-content-renderer.js +1 -1
- package/dist/files/renderers/sqlite-renderer.js +8 -3
- package/dist/files/renderers/xlsx/xlsx-viewer.js +15 -16
- package/dist/files/tree/components/file-tree-item.js +1 -1
- package/dist/files/viewer/file-header.js +1 -1
- package/dist/files/viewer/file-preview-modal.d.ts +1 -1
- package/dist/files/viewer/file-preview-modal.js +13 -3
- package/dist/files/viewer/file-source.d.ts +3 -1
- package/dist/files/viewer/use-file-content-state.js +27 -8
- package/dist/files/viewer/viewer-actions.js +2 -2
- package/dist/i18n/en.d.ts +355 -12
- package/dist/i18n/en.js +360 -17
- package/dist/internal/desktop/desktop-back-button.js +5 -3
- package/dist/internal/files/types.d.ts +2 -0
- package/dist/internal/goals/goal-meta.d.ts +30 -0
- package/dist/internal/goals/goal-meta.js +55 -0
- package/dist/internal/hooks/use-auto-scroll.js +5 -3
- package/dist/internal/lib/query-client-singleton.d.ts +9 -3
- package/dist/internal/lib/query-client-singleton.js +18 -12
- package/dist/internal/notifications/notification-rows.js +2 -1
- package/dist/internal/outcomes/outcome-types.d.ts +5 -0
- package/dist/internal/share/session-shares-modal.js +3 -7
- package/dist/internal/stores/kortix-computer-store.js +14 -2
- package/dist/internal/stores/session-hover-store.d.ts +32 -0
- package/dist/internal/stores/session-hover-store.js +38 -0
- package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
- package/dist/internal/stores/sidebar-nav-store.js +3 -1
- package/dist/lib/routes.d.ts +2 -0
- package/dist/lib/routes.js +1 -0
- package/dist/markdown/code/inline-code.js +8 -0
- package/dist/markdown/code/output-paths-context.d.ts +18 -0
- package/dist/markdown/code/output-paths-context.js +35 -0
- package/dist/markdown/genui/components/charts.js +6 -5
- package/dist/primitives/map.js +2 -1
- package/dist/primitives/preview-image.js +4 -2
- package/dist/primitives/settings-section-header.d.ts +1 -1
- package/dist/primitives/textarea.js +1 -1
- package/dist/primitives/typed-title.js +12 -14
- package/dist/primitives/typing-animation.js +4 -2
- package/dist/session/composer/agent-selector.js +6 -1
- package/dist/session/composer/attachment-tile.d.ts +0 -2
- package/dist/session/composer/attachment-tile.js +0 -8
- package/dist/session/composer/clipboard-files.d.ts +2 -1
- package/dist/session/composer/composer-chat-input.js +5 -3
- package/dist/session/composer/composer-draft-recovery.d.ts +1 -2
- package/dist/session/composer/composer-draft-recovery.js +0 -13
- package/dist/session/composer/composer-logic.js +8 -7
- package/dist/session/composer/context-ring.d.ts +1 -1
- package/dist/session/composer/context-ring.js +2 -2
- package/dist/session/composer/context-usage.d.ts +3 -6
- package/dist/session/composer/context-usage.js +3 -6
- package/dist/session/composer/draft/composer-draft.js +4 -4
- package/dist/session/composer/inbox-row-claims.d.ts +2 -2
- package/dist/session/composer/inbox-row-claims.js +1 -1
- package/dist/session/composer/pasted-text.js +3 -2
- package/dist/session/composer/queue-projection.d.ts +3 -2
- package/dist/session/composer/queued-prompt-edit.d.ts +1 -1
- package/dist/session/composer/reasoning-effort-selector.d.ts +2 -1
- package/dist/session/composer/session-composer-readiness.d.ts +7 -22
- package/dist/session/composer/session-composer-readiness.js +12 -40
- package/dist/session/composer/stores/queued-draft-store.js +3 -2
- package/dist/session/composer/token-progress.d.ts +1 -1
- package/dist/session/composer/token-progress.js +2 -2
- package/dist/session/header/reminder-parts.d.ts +11 -2
- package/dist/session/header/reminder-parts.js +9 -4
- package/dist/session/header/session-goal-indicator.d.ts +1 -0
- package/dist/session/header/session-goal-indicator.js +41 -0
- package/dist/session/header/session-site-header.js +2 -1
- package/dist/session/media/sandbox-url-detector.js +0 -7
- package/dist/session/outcomes/change-request-outcomes.js +24 -3
- package/dist/session/overrides/provider-secret-pool-editor.js +2 -1
- package/dist/session/panel/advanced/advanced-panel.js +3 -7
- package/dist/session/panel/easy/app-preview.js +12 -2
- package/dist/session/panel/easy/easy-panel-logic.d.ts +1 -1
- package/dist/session/panel/easy/easy-panel-logic.js +1 -1
- package/dist/session/panel/easy/outputs-card.js +2 -1
- package/dist/session/panel/easy/panel-card.js +5 -3
- package/dist/session/panel/easy/preview-load.d.ts +14 -0
- package/dist/session/panel/easy/preview-load.js +15 -0
- package/dist/session/panel/easy/step-detail-body.js +2 -7
- package/dist/session/panel/session-action-panel-column.js +11 -1
- package/dist/session/panel/session-audit-shared.d.ts +0 -4
- package/dist/session/panel/session-audit-shared.js +1 -1
- package/dist/session/panel/session-changes-shared.d.ts +2 -1
- package/dist/session/panel/session-panel-provider.js +6 -2
- package/dist/session/panel/shared/use-panel-derivations.js +6 -4
- package/dist/session/panel/use-session-panel-layout.js +7 -5
- package/dist/session/print/session-print-header.js +9 -8
- package/dist/session/prompts/session-permission-prompt.js +6 -3
- package/dist/session/status/provisioning-failure.d.ts +2 -1
- package/dist/session/status/session-error-banner.js +8 -6
- package/dist/session/status/session-starting-loader.d.ts +24 -31
- package/dist/session/status/session-starting-loader.js +32 -81
- package/dist/session/thread/chat-minimap-items.d.ts +4 -4
- package/dist/session/thread/first-prompt-handover.d.ts +3 -2
- package/dist/session/thread/message-parsing.d.ts +3 -3
- package/dist/session/thread/session-chat.js +15 -19
- package/dist/session/thread/session-history-scroll.d.ts +2 -1
- package/dist/session/thread/session-history.js +3 -1
- package/dist/session/thread/session-thread.js +1 -1
- package/dist/session/thread/transcript.js +13 -7
- package/dist/session/tool/shared/file-list.js +19 -2
- package/dist/session/tool/shared/infrastructure-contexts.d.ts +7 -0
- package/dist/session/tool/shared/infrastructure-contexts.js +7 -0
- package/dist/session/tool/shared/infrastructure-output.js +9 -5
- package/dist/session/tool/shared/infrastructure-row-header.js +9 -1
- package/dist/session/tool/shared/infrastructure-rows.js +7 -5
- package/dist/session/tool/tools/bash-tool.js +10 -6
- package/dist/session/tool/tools/web-search-tool.js +25 -3
- package/dist/session/turn/recovered-failures.d.ts +8 -0
- package/dist/session/turn/recovered-failures.js +32 -0
- package/dist/session/turn/streaming-cadence.js +5 -8
- package/dist/styles.css +1 -1
- package/dist/terminal/pty-connection.d.ts +5 -4
- package/dist/terminal/session-terminal-panel.js +3 -5
- package/dist/theme/theme.js +2 -1
- package/dist/workspace/index.d.ts +1 -0
- package/dist/workspace/index.js +1 -0
- package/dist/workspace/projects/modal/github-import-pickers.js +7 -6
- package/dist/workspace/review/review-center.js +13 -10
- package/dist/workspace/saved-session-skeleton-shape.d.ts +4 -3
- package/dist/workspace/saved-session-skeleton.d.ts +5 -1
- package/dist/workspace/saved-session-skeleton.js +5 -4
- package/dist/workspace/session-workspace.js +9 -14
- package/dist/workspace/sessions/deleted-session-row.js +5 -2
- package/dist/workspace/sidebar/footer/project-computer-nav.js +6 -4
- package/dist/workspace/sidebar/footer/project-goals-nav.d.ts +6 -0
- package/dist/workspace/sidebar/footer/project-goals-nav.js +26 -0
- package/dist/workspace/sidebar/footer/project-mcp-nav.js +6 -2
- package/dist/workspace/sidebar/modal/rename-session-modal.js +8 -3
- package/dist/workspace/sidebar/modal/session-embed-section.d.ts +25 -0
- package/dist/workspace/sidebar/modal/session-embed-section.js +71 -0
- package/dist/workspace/sidebar/modal/share-session-modal.js +2 -2
- package/dist/workspace/sidebar/nav-row-meta.js +14 -2
- package/dist/workspace/sidebar/project-nav-items.js +3 -0
- package/dist/workspace/sidebar/project-session-list.js +12 -3
- package/dist/workspace/sidebar/session-brief-hover-card.js +5 -8
- package/package.json +4 -4
- package/skills/kortix-ui/references/modules.md +2 -0
- package/dist/session/status/use-readiness-settling.d.ts +0 -18
- package/dist/session/status/use-readiness-settling.js +0 -43
- package/dist/workspace/sidebar/modal/session-public-link-section.d.ts +0 -13
- package/dist/workspace/sidebar/modal/session-public-link-section.js +0 -66
|
@@ -11,7 +11,7 @@ import { useTranslations } from '../../../i18n/index.js';
|
|
|
11
11
|
*/
|
|
12
12
|
import { ShippingContainerIcon as Container, FileCodeIcon as FileCode, PackageIcon as Package, } from '@phosphor-icons/react';
|
|
13
13
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
14
|
-
import {
|
|
14
|
+
import { useMemo, useState } from 'react';
|
|
15
15
|
import { Button } from '../../../primitives/button.js';
|
|
16
16
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../../primitives/dialog.js';
|
|
17
17
|
import { Input } from '../../../primitives/input.js';
|
|
@@ -39,7 +39,7 @@ export function SandboxTemplateForm({ projectId, open, onOpenChange, template, }
|
|
|
39
39
|
const isEdit = !!template;
|
|
40
40
|
const queryClient = useQueryClient();
|
|
41
41
|
const [name, setName] = useState('');
|
|
42
|
-
const [
|
|
42
|
+
const [typedSlug, setSlug] = useState('');
|
|
43
43
|
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false);
|
|
44
44
|
const [mode, setMode] = useState('image');
|
|
45
45
|
const [image, setImage] = useState('');
|
|
@@ -49,10 +49,10 @@ export function SandboxTemplateForm({ projectId, open, onOpenChange, template, }
|
|
|
49
49
|
const [memoryGb, setMemoryGb] = useState('4');
|
|
50
50
|
const [diskGb, setDiskGb] = useState('20');
|
|
51
51
|
// Reset / hydrate when opening
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (template) {
|
|
52
|
+
const [hydratedFor, setHydratedFor] = useState(null);
|
|
53
|
+
if (!hydratedFor || hydratedFor[0] !== open || hydratedFor[1] !== template) {
|
|
54
|
+
setHydratedFor([open, template]);
|
|
55
|
+
if (open && template) {
|
|
56
56
|
setName(template.name);
|
|
57
57
|
setSlug(template.slug);
|
|
58
58
|
setSlugManuallyEdited(true);
|
|
@@ -71,7 +71,7 @@ export function SandboxTemplateForm({ projectId, open, onOpenChange, template, }
|
|
|
71
71
|
setMemoryGb(String(template.memory_gb));
|
|
72
72
|
setDiskGb(String(template.disk_gb));
|
|
73
73
|
}
|
|
74
|
-
else {
|
|
74
|
+
else if (open) {
|
|
75
75
|
setName('');
|
|
76
76
|
setSlug('');
|
|
77
77
|
setSlugManuallyEdited(false);
|
|
@@ -83,12 +83,9 @@ export function SandboxTemplateForm({ projectId, open, onOpenChange, template, }
|
|
|
83
83
|
setMemoryGb('6');
|
|
84
84
|
setDiskGb('20');
|
|
85
85
|
}
|
|
86
|
-
}
|
|
86
|
+
}
|
|
87
87
|
// Auto-slug from name when the user hasn't typed a slug manually yet.
|
|
88
|
-
|
|
89
|
-
if (!slugManuallyEdited)
|
|
90
|
-
setSlug(slugify(name));
|
|
91
|
-
}, [name, slugManuallyEdited]);
|
|
88
|
+
const slug = slugManuallyEdited ? typedSlug : slugify(name);
|
|
92
89
|
const slugError = useMemo(() => {
|
|
93
90
|
if (!slug)
|
|
94
91
|
return null;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Transfer-workspace entry point — the settings row and its dialog.
|
|
5
|
+
*
|
|
6
|
+
* The API (POST /v1/projects/:id/transfer) refuses a caller who holds the
|
|
7
|
+
* destructive tier on the project but no rights on the TARGET organization,
|
|
8
|
+
* and answers with the target's project cap when the move would exceed its
|
|
9
|
+
* plan — so this dialog only has to pick a target and say plainly what
|
|
10
|
+
* moves: sessions, files, settings and member grants follow the project;
|
|
11
|
+
* the usage ledger stays with the organization that consumed it.
|
|
12
|
+
*
|
|
13
|
+
* The project may land in an organization the mover cannot see afterwards
|
|
14
|
+
* (they are not a member there) — the same outcome the Delete flow produces,
|
|
15
|
+
* so success leaves the project the same way: forget the remembered landing
|
|
16
|
+
* target, close the settings overlay, replace into the landing door.
|
|
17
|
+
*/
|
|
18
|
+
import { useMemo, useState } from 'react';
|
|
19
|
+
import { Button } from '../../../primitives/button.js';
|
|
20
|
+
import { ConfirmDialog } from '../../../primitives/confirm-dialog.js';
|
|
21
|
+
import { SettingsRow } from '../../../primitives/settings-row.js';
|
|
22
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../../primitives/select.js';
|
|
23
|
+
import { errorToast, successToast } from '../../../primitives/toast.js';
|
|
24
|
+
import { useSettingsPanelStore } from '../../../internal/stores/settings-panel-store.js';
|
|
25
|
+
import { useUiRouter, useUiViewerId } from '../../../providers/ui-provider.js';
|
|
26
|
+
import { useAccountsList } from '../../../internal/hooks/account/use-accounts-list.js';
|
|
27
|
+
import { PROJECT_LANDING_PATH } from '../../../internal/lib/onboarding/landing-destination.js';
|
|
28
|
+
import { forgetLastProjectId } from '../../../internal/lib/onboarding/last-project-cookie.js';
|
|
29
|
+
import { transferProject } from '@kortix/sdk';
|
|
30
|
+
import { qk } from '@kortix/sdk/react';
|
|
31
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
32
|
+
import { useTranslations } from '../../../i18n/index.js';
|
|
33
|
+
export function TransferWorkspaceEntry({ projectId, currentAccountId, }) {
|
|
34
|
+
const t = useTranslations('settings.workspace');
|
|
35
|
+
const [open, setOpen] = useState(false);
|
|
36
|
+
return (_jsxs(_Fragment, { children: [_jsx(SettingsRow, { label: t('transferWorkspace'), description: t('transferDescription'), children: _jsx(Button, { variant: "ghost", size: "sm", className: "text-destructive hover:bg-destructive/10 hover:text-destructive", onClick: () => setOpen(true), children: t('transferWorkspace') }) }), _jsx(TransferWorkspaceDialog, { projectId: projectId, currentAccountId: currentAccountId, open: open, onOpenChange: setOpen })] }));
|
|
37
|
+
}
|
|
38
|
+
function TransferWorkspaceDialog({ projectId, currentAccountId, open, onOpenChange, }) {
|
|
39
|
+
const t = useTranslations('settings.workspace');
|
|
40
|
+
const queryClient = useQueryClient();
|
|
41
|
+
const router = useUiRouter();
|
|
42
|
+
const viewerId = useUiViewerId();
|
|
43
|
+
const [targetId, setTargetId] = useState('');
|
|
44
|
+
// Same freshness contract as every other account-list reader: fetch only
|
|
45
|
+
// while the dialog is open.
|
|
46
|
+
const accountsQuery = useAccountsList({ enabled: open });
|
|
47
|
+
// The target cannot be the account the project already lives in — the API
|
|
48
|
+
// refuses that anyway — and a stale `currentAccountId` (project query still
|
|
49
|
+
// in flight) is harmless: the API re-checks.
|
|
50
|
+
const targetOptions = useMemo(() => (accountsQuery.data ?? []).filter((account) => account.account_id !== currentAccountId), [accountsQuery.data, currentAccountId]);
|
|
51
|
+
const transferMutation = useMutation({
|
|
52
|
+
mutationFn: () => transferProject(projectId, targetId),
|
|
53
|
+
onSuccess: () => {
|
|
54
|
+
successToast(t('transferSuccess'));
|
|
55
|
+
// Same leave-the-project flow as Delete: the moved project must stop
|
|
56
|
+
// being the remembered landing target, the global overlay must close
|
|
57
|
+
// before the navigation lands, and Back must not return to a project
|
|
58
|
+
// the viewer may no longer see.
|
|
59
|
+
forgetLastProjectId(viewerId, projectId);
|
|
60
|
+
useSettingsPanelStore.getState().close();
|
|
61
|
+
// qk.projects.scope(): lists across every account plus the accountless
|
|
62
|
+
// slot — the project just changed accounts, so every list form is
|
|
63
|
+
// stale at once. The moved project's own caches are unreachable after
|
|
64
|
+
// the replace below (the old id's entries gcTime out).
|
|
65
|
+
queryClient.invalidateQueries({ queryKey: qk.projects.scope() });
|
|
66
|
+
onOpenChange(false);
|
|
67
|
+
router.replace(PROJECT_LANDING_PATH);
|
|
68
|
+
},
|
|
69
|
+
onError: (error) => errorToast(error.message || t('transferFailed')),
|
|
70
|
+
});
|
|
71
|
+
const targetName = targetOptions.find((account) => account.account_id === targetId)?.name;
|
|
72
|
+
const changeOpen = (next) => {
|
|
73
|
+
if (transferMutation.isPending)
|
|
74
|
+
return;
|
|
75
|
+
if (!next) {
|
|
76
|
+
setTargetId('');
|
|
77
|
+
transferMutation.reset();
|
|
78
|
+
}
|
|
79
|
+
onOpenChange(next);
|
|
80
|
+
};
|
|
81
|
+
return (_jsx(ConfirmDialog, { open: open, onOpenChange: changeOpen, title: t('transferTitle'), description: _jsxs("div", { className: "space-y-4", children: [_jsx("p", { children: t('transferDialog') }), accountsQuery.isLoading ? (_jsx("p", { children: t('transferLoadingTargets') })) : accountsQuery.isError ? (_jsx(Button, { variant: "outline", onClick: () => accountsQuery.refetch(), children: t('retry') })) : targetOptions.length === 0 ? (_jsx("p", { children: t('transferNoTargets') })) : (_jsxs(Select, { value: targetId, onValueChange: setTargetId, children: [_jsx(SelectTrigger, { className: "w-full", "aria-label": t('transferTargetLabel'), children: _jsx(SelectValue, { placeholder: t('transferTargetPlaceholder') }) }), _jsx(SelectContent, { children: targetOptions.map((account) => (_jsx(SelectItem, { value: account.account_id, children: account.name }, account.account_id))) })] }))] }), cancelLabel: t('keepWorkspace'), confirmLabel: targetName ? t('transferMoveTo', { name: targetName }) : t('transferMove'), confirmVariant: "destructive", confirmDisabled: !targetName || accountsQuery.isError, isPending: transferMutation.isPending, onConfirm: () => transferMutation.mutate() }));
|
|
82
|
+
}
|
|
@@ -126,7 +126,8 @@ export function CapabilityTabs({ projectId }) {
|
|
|
126
126
|
// once the project turns its flag on. `capabilityAccess()` applies the flags
|
|
127
127
|
// and the leaves; before it settles the bar is invisible and both are left out.
|
|
128
128
|
const access = useCapabilityAccess(projectId);
|
|
129
|
-
const
|
|
129
|
+
const allowedTabs = new Set(access.tabs);
|
|
130
|
+
const tabs = allTabs.filter((tab) => access.settled ? allowedTabs.has(tab.key) : !FLAG_GATED_TABS.includes(tab.key));
|
|
130
131
|
const leading = tabs.filter((tab) => !TRAILING_TABS.includes(tab.key));
|
|
131
132
|
const primary = leading.filter((tab) => PRIMARY_TABS.includes(tab.key));
|
|
132
133
|
const library = leading.filter((tab) => !PRIMARY_TABS.includes(tab.key));
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { NewEntityMenu } from '../shared/new-entity-menu.js';
|
|
4
4
|
import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { useMemo, useRef, useState } from 'react';
|
|
6
6
|
import { Button } from '../../primitives/button.js';
|
|
7
7
|
import { InputGroupSearch, InputGroupSearchClear, InputGroupSearchIcon, InputGroupSearchInput, } from '../../primitives/input-group.js';
|
|
8
8
|
import { Tabs, TabsList, TabsTrigger } from '../../primitives/tabs.js';
|
|
@@ -85,10 +85,8 @@ export function SkillsPage({ projectId }) {
|
|
|
85
85
|
});
|
|
86
86
|
// The one honest auto-close: the config came back and this skill is not in
|
|
87
87
|
// it, so it really was deleted or renamed.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
setSelectedPath(null);
|
|
91
|
-
}, [detail.isMissing]);
|
|
88
|
+
if (detail.isMissing)
|
|
89
|
+
setSelectedPath(null);
|
|
92
90
|
// `null` = render the grid. Otherwise which "nothing to show" copy applies:
|
|
93
91
|
// genuinely zero skills vs. skills exist but this filter/search hid all of
|
|
94
92
|
// them. Telling the user "No skills yet" in the second case is false and
|
|
@@ -411,10 +411,11 @@ export function newConnectorSlug(app, taken) {
|
|
|
411
411
|
.toLowerCase()
|
|
412
412
|
.replace(/[^a-z0-9_-]+/g, '-')
|
|
413
413
|
.replace(/^-+|-+$/g, '') || 'app';
|
|
414
|
-
|
|
414
|
+
const takenSet = new Set(taken);
|
|
415
|
+
if (!takenSet.has(slug))
|
|
415
416
|
return slug;
|
|
416
417
|
for (let n = 2;; n++)
|
|
417
|
-
if (!
|
|
418
|
+
if (!takenSet.has(`${slug}-${n}`))
|
|
418
419
|
return `${slug}-${n}`;
|
|
419
420
|
}
|
|
420
421
|
/* ─── Delivery ──────────────────────────────────────────────────────────── */
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { CalendarDotsIcon as CalendarClock, CaretDownIcon as ChevronDown } from '@phosphor-icons/react';
|
|
4
4
|
import { useTranslations } from '../../../i18n/index.js';
|
|
5
|
-
import { useCallback,
|
|
5
|
+
import { useCallback, useState } from 'react';
|
|
6
6
|
import { Button } from '../../../primitives/button.js';
|
|
7
7
|
import { Input } from '../../../primitives/input.js';
|
|
8
8
|
import { Label } from '../../../primitives/label.js';
|
|
@@ -195,13 +195,15 @@ export function ScheduleBuilder({ value, onChange, disabled, allowOnce, runAt, o
|
|
|
195
195
|
const onceMode = Boolean(allowOnce && onRunAtChange && runAt != null);
|
|
196
196
|
const isCustom = cronToState(rawCron) === null;
|
|
197
197
|
const hasPastRunAt = Boolean(runAt && new Date(runAt).getTime() <= Date.now());
|
|
198
|
-
|
|
198
|
+
const [syncedValue, setSyncedValue] = useState(value);
|
|
199
|
+
if (value !== syncedValue) {
|
|
200
|
+
setSyncedValue(value);
|
|
199
201
|
const parsed = cronToState(value);
|
|
200
202
|
if (parsed)
|
|
201
203
|
setState(parsed);
|
|
202
204
|
setRawCron(value);
|
|
203
205
|
setShowCron((visible) => visible || !parsed);
|
|
204
|
-
}
|
|
206
|
+
}
|
|
205
207
|
const update = useCallback((partial) => {
|
|
206
208
|
const next = { ...state, ...partial };
|
|
207
209
|
setState(next);
|
|
@@ -256,6 +258,7 @@ export function ScheduleBuilder({ value, onChange, disabled, allowOnce, runAt, o
|
|
|
256
258
|
const canOnce = Boolean(allowOnce && onRunAtChange);
|
|
257
259
|
const cadences = localizeUiCatalog(CADENCES, tI18nComplete, APP_REGISTRY_TRANSLATION_KEYS);
|
|
258
260
|
const weekdayButtons = localizeUiCatalog(WEEKDAY_BUTTONS, tI18nComplete, APP_REGISTRY_TRANSLATION_KEYS);
|
|
261
|
+
const selectedWeekdays = new Set(state.weekdays);
|
|
259
262
|
const intervalUnit = (value) => state.frequency === 'minutes' ? 'minutes' : `hour${value === 1 ? '' : 's'}`;
|
|
260
263
|
return (_jsxs("div", { className: cn('space-y-3', disabled && 'pointer-events-none opacity-60 select-none'), children: [_jsxs("div", { className: "flex flex-wrap items-end gap-3", children: [_jsx(ScheduleField, { label: tI18nComplete.raw('textb6b7a0065808'), className: "w-full sm:w-44", children: _jsxs(Select, { value: onceMode ? 'once' : cadence, onValueChange: (next) => next === 'once' ? selectOnce() : selectCadence(next), disabled: disabled, children: [_jsx(SelectTrigger, { className: "h-9 w-full", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [cadences.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value))), canOnce ? (_jsx(SelectItem, { value: "once", children: tI18nComplete.raw('textd88f6d8372f4') })) : null] })] }) }), onceMode ? (_jsx(ScheduleField, { label: tI18nComplete.raw('text4b4c31294fb5'), className: "w-full sm:w-auto", children: _jsx(Input, { type: "datetime-local", value: runAt ? isoToLocalInput(runAt) : '', min: isoToLocalInput(new Date().toISOString()), onChange: (event) => onRunAtChange?.(localInputToIso(event.target.value)), onBlur: () => {
|
|
261
264
|
if (hasPastRunAt)
|
|
@@ -265,7 +268,7 @@ export function ScheduleBuilder({ value, onChange, disabled, allowOnce, runAt, o
|
|
|
265
268
|
: [1, 2, 3, 4, 6, 8, 12]).map((value) => (_jsxs(SelectItem, { value: String(value), children: [value, " ", intervalUnit(value)] }, value))) })] }) })), state.frequency === 'monthly' && (_jsx(ScheduleField, { label: tTrigger('dayOfMonth'), className: "w-28", children: _jsxs(Select, { value: String(state.monthDay), onValueChange: (value) => update({ monthDay: Number(value) }), disabled: disabled, children: [_jsx(SelectTrigger, { className: "h-9 w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: Array.from({ length: 31 }, (_, index) => index + 1).map((value) => (_jsx(SelectItem, { value: String(value), children: value }, value))) })] }) })), state.frequency !== 'minutes' && (_jsx(ScheduleField, { label: state.frequency === 'hourly'
|
|
266
269
|
? tI18nComplete.raw('text5f2ed72dfcbc')
|
|
267
270
|
: tI18nComplete.raw('text33b93476cf59'), children: _jsxs("div", { className: "flex items-center gap-1.5", children: [state.frequency !== 'hourly' && (_jsxs(_Fragment, { children: [_jsxs(Select, { value: String(state.hour), onValueChange: (value) => update({ hour: Number(value) }), disabled: disabled, children: [_jsx(SelectTrigger, { className: "h-9 w-18 tabular-nums", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: HOURS.map((value) => (_jsx(SelectItem, { value: String(value), children: pad2(value) }, value))) })] }), _jsx("span", { className: "text-muted-foreground", children: ":" })] })), _jsxs(Select, { value: String(state.minute), onValueChange: (value) => update({ minute: Number(value) }), disabled: disabled, children: [_jsx(SelectTrigger, { className: "h-9 w-18 tabular-nums", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: MINUTE_OPTIONS.map((value) => (_jsx(SelectItem, { value: String(value), children: state.frequency === 'hourly' ? `:${pad2(value)}` : pad2(value) }, value))) })] })] }) })), trailing] }))] }), !onceMode && cadence === 'weekly' && (_jsx("div", { className: "flex flex-wrap gap-1.5", "aria-label": tI18nComplete.raw('text2069f4549744'), children: weekdayButtons.map(({ value, label }) => {
|
|
268
|
-
const selected =
|
|
271
|
+
const selected = selectedWeekdays.has(value);
|
|
269
272
|
return (_jsx(Button, { type: "button", variant: selected ? 'secondary' : 'outline', size: "sm", "aria-pressed": selected, onClick: () => toggleWeekday(value), disabled: disabled, className: "min-w-10 transition-transform active:scale-[0.96]", children: label }, value));
|
|
270
273
|
}) })), onceMode && runAt && hasPastRunAt ? (_jsx(SchedulePreview, { text: describeRunAt(runAt, tI18nComplete), error: true })) : null, !onceMode && isCustom ? (_jsx(SchedulePreview, { text: tI18nComplete.raw('text7afd348d0d4b') })) : null, !onceMode && (_jsxs("div", { className: "space-y-2", children: [_jsxs(Button, { type: "button", variant: "text", size: "xs", onClick: () => setShowCron((visible) => !visible), disabled: disabled, className: "text-muted-foreground hover:text-foreground -ml-1 transition-transform active:scale-[0.96]", children: [_jsx(ChevronDown, { className: cn('size-3 transition-transform duration-(--duration-normal)', showCron && 'rotate-180') }), showCron
|
|
271
274
|
? tI18nComplete.raw('text6c848b936d1d')
|
|
@@ -138,7 +138,11 @@ function ComposerForm({ projectId, onOpenChange, onCreated, initialAgent = null,
|
|
|
138
138
|
reveal(errorRef.current);
|
|
139
139
|
}, [error]);
|
|
140
140
|
const create = useMutation({
|
|
141
|
-
|
|
141
|
+
onMutate: () => onBusyChange(true),
|
|
142
|
+
onSettled: () => {
|
|
143
|
+
setFrozenApp(null);
|
|
144
|
+
onBusyChange(false);
|
|
145
|
+
},
|
|
142
146
|
mutationFn: async () => {
|
|
143
147
|
const trimmedName = name.trim();
|
|
144
148
|
const slug = slugify(draft.customId.trim() || trimmedName);
|
|
@@ -251,7 +255,6 @@ function ComposerForm({ projectId, onOpenChange, onCreated, initialAgent = null,
|
|
|
251
255
|
setError(message);
|
|
252
256
|
},
|
|
253
257
|
});
|
|
254
|
-
useEffect(() => onBusyChange(create.isPending), [create.isPending, onBusyChange]);
|
|
255
258
|
const submit = () => {
|
|
256
259
|
setError(null);
|
|
257
260
|
setTaken(null);
|
|
@@ -143,7 +143,7 @@ function Connection({ projectId, app, draft, patch, setDraft, canConnect, }) {
|
|
|
143
143
|
*/
|
|
144
144
|
function EventSettings({ fields, draft, errors, onChange, }) {
|
|
145
145
|
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
146
|
-
const [open, setOpen] = useState(fields.some((f) => f.required && f.kind !== 'boolean'));
|
|
146
|
+
const [open, setOpen] = useState(() => fields.some((f) => f.required && f.kind !== 'boolean'));
|
|
147
147
|
const hasProblem = Object.keys(errors).length > 0;
|
|
148
148
|
return (_jsxs(Disclosure, { className: "group", open: open || hasProblem, onOpenChange: setOpen, children: [_jsx(FoldTrigger, { children: tI18nComplete.raw('text6abe3b60f184') }), _jsx(DisclosureContent, { children: _jsxs("div", { className: "space-y-3 pt-3", children: [_jsx("p", { className: "text-muted-foreground text-xs leading-relaxed text-pretty", children: tI18nComplete.raw('text9f2c75e76be9') }), _jsx(EventConfigForm, { fields: fields, draft: draft, errors: errors, onChange: onChange })] }) })] }));
|
|
149
149
|
}
|
package/dist/diff/diff-view.js
CHANGED
|
@@ -24,19 +24,18 @@ export function splitablePatch(patch) {
|
|
|
24
24
|
export function DiffView(props) {
|
|
25
25
|
const isDark = useIsDark();
|
|
26
26
|
const themeType = isDark ? 'dark' : 'light';
|
|
27
|
+
const patchInput = 'patch' in props ? props.patch : null;
|
|
28
|
+
const beforeName = 'before' in props ? props.before.name : '';
|
|
29
|
+
const beforeContents = 'before' in props ? props.before.contents : '';
|
|
30
|
+
const afterName = 'after' in props ? props.after.name : '';
|
|
31
|
+
const afterContents = 'after' in props ? props.after.contents : '';
|
|
27
32
|
const patch = useMemo(() => {
|
|
28
33
|
// `createTwoFilesPatch` writes no `new file mode` / `deleted file mode`
|
|
29
34
|
// line, so only the patch path can be one-sided.
|
|
30
|
-
if (
|
|
31
|
-
return splitablePatch(
|
|
32
|
-
return createTwoFilesPatch(
|
|
33
|
-
}, [
|
|
34
|
-
'patch' in props ? props.patch : null,
|
|
35
|
-
'before' in props ? props.before.name : null,
|
|
36
|
-
'before' in props ? props.before.contents : null,
|
|
37
|
-
'after' in props ? props.after.name : null,
|
|
38
|
-
'after' in props ? props.after.contents : null,
|
|
39
|
-
]);
|
|
35
|
+
if (patchInput !== null)
|
|
36
|
+
return splitablePatch(patchInput);
|
|
37
|
+
return createTwoFilesPatch(beforeName, afterName, beforeContents, afterContents, '', '');
|
|
38
|
+
}, [patchInput, beforeName, beforeContents, afterName, afterContents]);
|
|
40
39
|
const options = useMemo(() => ({
|
|
41
40
|
theme: { dark: SHIKI_THEME_DARK, light: SHIKI_THEME_LIGHT },
|
|
42
41
|
themeType,
|
|
@@ -477,8 +477,7 @@ export function CodeEditor({ content, originalContent, hasUnsavedChanges: extern
|
|
|
477
477
|
}
|
|
478
478
|
return exts;
|
|
479
479
|
}, [langExtension, diagExt]);
|
|
480
|
-
const
|
|
481
|
-
const tHardcodedUi = useTranslations('hardcodedUi');
|
|
480
|
+
const renderSaveButton = () => {
|
|
482
481
|
if (readOnly || !onSave)
|
|
483
482
|
return null;
|
|
484
483
|
switch (saveState) {
|
|
@@ -494,7 +493,7 @@ export function CodeEditor({ content, originalContent, hasUnsavedChanges: extern
|
|
|
494
493
|
};
|
|
495
494
|
return (_jsxs("div", { className: cn('flex max-w-full flex-col', readOnly
|
|
496
495
|
? 'min-h-full' // For read-only, fill at least one viewport so the editor background doesn't end at the last line
|
|
497
|
-
: 'h-full max-h-full overflow-hidden', className), style: readOnly ? undefined : { contain: 'strict' }, children: [!readOnly && showHeader && (_jsxs("div", { className: "bg-muted/30 flex max-w-full min-w-0 shrink-0 items-center justify-between border-b px-3 py-1.5", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [
|
|
496
|
+
: 'h-full max-h-full overflow-hidden', className), style: readOnly ? undefined : { contain: 'strict' }, children: [!readOnly && showHeader && (_jsxs("div", { className: "bg-muted/30 flex max-w-full min-w-0 shrink-0 items-center justify-between border-b px-3 py-1.5", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [renderSaveButton(), hasChanges && (_jsx(TooltipProvider, { delayDuration: 300, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "sm", onClick: handleDiscard, className: "text-muted-foreground hover:text-destructive h-7 w-7 p-0", children: _jsx(RotateCcw, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { side: "bottom", children: tHardcodedUi.raw('componentsFileEditorsCodeEditor.line719JsxTextDiscardChanges') })] }) })), hasChanges && (_jsxs("div", { className: "flex items-center gap-1.5 rounded-md bg-amber-50 px-2 py-1 text-xs text-amber-600 dark:bg-amber-900/20 dark:text-amber-500", children: [_jsxs("span", { className: "relative flex h-2 w-2", children: [_jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-amber-400 opacity-75" }), _jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-amber-500" })] }), _jsx("span", { className: "font-semibold", children: tHardcodedUi.raw('i18nComplete.text6250d5725dda') })] }))] }), _jsx(Badge, { variant: "outline", className: "font-mono text-xs", children: language })] })), _jsx("div", { ref: editorContainerRef, className: cn('bg-background w-full max-w-full', editorClassName, readOnly
|
|
498
497
|
? 'min-h-full flex-1 overflow-visible' // Stretch to fill parent so short files still fill the viewport
|
|
499
498
|
: 'max-h-full min-h-0 flex-1 overflow-hidden'), style: readOnly ? undefined : { contain: 'strict' }, children: mounted && (_jsx(CodeMirror, { ref: editorRef, onCreateEditor: setEditorView, value: localContent, onChange: handleChange, theme: theme, extensions: extensions, basicSetup: {
|
|
500
499
|
lineNumbers: showLineNumbers,
|
|
@@ -194,12 +194,13 @@ export async function readFile(projectId, ref, filePath) {
|
|
|
194
194
|
// text, and the JSON content read is byte-safe for it.
|
|
195
195
|
if (hasExtension && getLanguageFromExt(name) !== 'plaintext') {
|
|
196
196
|
const result = await readProjectFile(projectId, relativePath, ref);
|
|
197
|
-
return { type: 'text', content: result.content };
|
|
197
|
+
return { type: 'text', content: result.content, revision: result.revision };
|
|
198
198
|
}
|
|
199
199
|
// Unknown or missing extension: the bytes decide, text or binary.
|
|
200
200
|
const bytes = await readRawBytes(projectId, relativePath, ref);
|
|
201
201
|
if (isTextBytes(bytes)) {
|
|
202
|
-
|
|
202
|
+
const result = await readProjectFile(projectId, relativePath, ref);
|
|
203
|
+
return { type: 'text', content: result.content, revision: result.revision, mimeType: 'text/plain; charset=utf-8' };
|
|
203
204
|
}
|
|
204
205
|
return { type: 'binary', content: '', mimeType: 'application/octet-stream' };
|
|
205
206
|
}
|
|
@@ -8,6 +8,8 @@ export declare const diffRendererViewportClass: typeof diffViewportClass;
|
|
|
8
8
|
interface ChangeRequestDetailDialogProps {
|
|
9
9
|
crId: string | null;
|
|
10
10
|
onClose: () => void;
|
|
11
|
+
/** Opens another change request in this dialog: a superseded one's replacement. */
|
|
12
|
+
onOpenChangeRequest?: (crId: string) => void;
|
|
11
13
|
}
|
|
12
|
-
export declare function ChangeRequestDetailDialog({ crId, onClose }: ChangeRequestDetailDialogProps): import("react").JSX.Element;
|
|
14
|
+
export declare function ChangeRequestDetailDialog({ crId, onClose, onOpenChangeRequest }: ChangeRequestDetailDialogProps): import("react").JSX.Element;
|
|
13
15
|
export {};
|
|
@@ -17,7 +17,6 @@ import { useTranslations } from '../../../i18n/index.js';
|
|
|
17
17
|
* has actually gone wrong and the reader has to act on them.
|
|
18
18
|
*/
|
|
19
19
|
import { UnifiedMarkdown } from '../../../markdown/index.js';
|
|
20
|
-
import { Badge } from '../../../primitives/badge.js';
|
|
21
20
|
import { Button } from '../../../primitives/button.js';
|
|
22
21
|
import { InfoBanner } from '../../../primitives/info-banner.js';
|
|
23
22
|
import Loading from '../../../primitives/loading.js';
|
|
@@ -27,14 +26,13 @@ import { errorToast, successToast } from '../../../primitives/toast.js';
|
|
|
27
26
|
import { ChangeList, ChangeSummary, DiffLayoutToggle, ExpandAllButton, diffViewportClass, entryFromCommitFile, fileCount, proposedChangeTimeline, splitUnifiedPatch, useChangeExpansion, } from '../../../changes/index.js';
|
|
28
27
|
import { EmptyState } from '../../../primitives/empty-state.js';
|
|
29
28
|
import { manifestFilename, useProjectManifestVersion, } from '../../../internal/lib/manifest-version.js';
|
|
30
|
-
import { translateUiCatalogText } from '../../../i18n/ui-catalog/localize-ui-catalog.js';
|
|
31
|
-
import { REMAINING_UI_TRANSLATION_KEYS } from '../../../i18n/ui-catalog/remaining-ui-translation-keys.generated.js';
|
|
32
29
|
import { useProjectCans } from '../../../internal/lib/use-project-can.js';
|
|
33
30
|
import { REVIEW_CONTROL_ACTIONS, changeRequestControlsFrom } from '@kortix/sdk';
|
|
34
31
|
import { ArrowCounterClockwiseIcon, CheckIcon, FileDashedIcon, SparkleIcon, WarningIcon, } from '@phosphor-icons/react';
|
|
35
32
|
import { formatDistanceToNowStrict } from 'date-fns';
|
|
36
33
|
import { useMemo, useState } from 'react';
|
|
37
34
|
import { useProjectContext } from '../context.js';
|
|
35
|
+
import { ChangeRequestStatusBadge } from './change-request-status-badge.js';
|
|
38
36
|
import { useChangeRequestRecovery } from '../hooks/use-change-request-recovery.js';
|
|
39
37
|
import { useChangeRequest, useChangeRequestDiff, useChangeRequestMergePreview, useCloseChangeRequest, useMergeChangeRequest, useReopenChangeRequest, } from '../hooks/use-change-requests.js';
|
|
40
38
|
/**
|
|
@@ -44,7 +42,7 @@ import { useChangeRequest, useChangeRequestDiff, useChangeRequestMergePreview, u
|
|
|
44
42
|
*/
|
|
45
43
|
export const diffRendererViewportClass = diffViewportClass;
|
|
46
44
|
const relative = (iso) => formatDistanceToNowStrict(new Date(iso), { addSuffix: true });
|
|
47
|
-
export function ChangeRequestDetailDialog({ crId, onClose }) {
|
|
45
|
+
export function ChangeRequestDetailDialog({ crId, onClose, onOpenChangeRequest }) {
|
|
48
46
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
49
47
|
const open = crId !== null;
|
|
50
48
|
const detailQuery = useChangeRequest(crId);
|
|
@@ -149,7 +147,7 @@ export function ChangeRequestDetailDialog({ crId, onClose }) {
|
|
|
149
147
|
const blocked = recoveryBlocker !== null;
|
|
150
148
|
// An open change offers Dismiss and the apply; a closed one offers Reopen.
|
|
151
149
|
const hasDecision = cr?.status === 'open' ? controls.canClose || controls.canMerge : controls.canClose;
|
|
152
|
-
return (_jsx(Modal, { open: open, onOpenChange: (v) => !v && onClose(), children: _jsxs(ModalContent, { className: "flex h-[94dvh] max-h-[94dvh] min-h-0 w-full flex-col gap-0 space-y-0 overflow-hidden p-0 lg:h-[90vh] lg:max-h-[90vh] lg:min-h-[90vh] lg:max-w-5xl", children: [_jsx(ModalHeader, { className: "flex shrink-0 flex-col space-y-0 border-b px-5 py-4 pr-14", children: !cr ? (_jsxs("div", { className: "space-y-2", children: [_jsx(ModalTitle, { className: "sr-only", children: tI18nComplete.raw('text28b00af7cb71') }), _jsx(Skeleton, { className: "h-5 w-2/3" }), _jsx(Skeleton, { className: "h-3 w-1/3" })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex min-w-0 items-start gap-2.5", children: [_jsx(ModalTitle, { className: "text-foreground min-w-0 flex-1 text-base leading-snug font-medium text-balance", children: cr.title || tI18nComplete.raw('text63cb7c2ea609') }),
|
|
150
|
+
return (_jsx(Modal, { open: open, onOpenChange: (v) => !v && onClose(), children: _jsxs(ModalContent, { className: "flex h-[94dvh] max-h-[94dvh] min-h-0 w-full flex-col gap-0 space-y-0 overflow-hidden p-0 lg:h-[90vh] lg:max-h-[90vh] lg:min-h-[90vh] lg:max-w-5xl", children: [_jsx(ModalHeader, { className: "flex shrink-0 flex-col space-y-0 border-b px-5 py-4 pr-14", children: !cr ? (_jsxs("div", { className: "space-y-2", children: [_jsx(ModalTitle, { className: "sr-only", children: tI18nComplete.raw('text28b00af7cb71') }), _jsx(Skeleton, { className: "h-5 w-2/3" }), _jsx(Skeleton, { className: "h-3 w-1/3" })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex min-w-0 items-start gap-2.5", children: [_jsx(ModalTitle, { className: "text-foreground min-w-0 flex-1 text-base leading-snug font-medium text-balance", children: cr.title || tI18nComplete.raw('text63cb7c2ea609') }), _jsx(ChangeRequestStatusBadge, { cr: cr, onOpenChangeRequest: onOpenChangeRequest })] }), _jsxs("p", { className: "text-muted-foreground mt-1 flex min-w-0 flex-wrap items-center gap-x-1.5 text-xs", children: [_jsxs("span", { className: "tabular-nums", children: ["#", cr.number] }), _jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: tI18nComplete.raw('text3b9453dad42b') }), _jsx("span", { children: proposedChangeTimeline(cr, relative, tI18nComplete) }), cr.base_ref !== defaultBranch && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: tI18nComplete.raw('text3b9453dad42b') }), _jsxs("span", { className: "truncate", children: [tI18nComplete.raw('text6b847a0ed0b2'), " ", cr.base_ref] })] }))] })] })) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain", children: _jsxs("div", { className: "space-y-4 px-5 py-4", children: [manifestIssues !== null && (_jsx(InfoBanner, { tone: "destructive", icon: WarningIcon, title: tI18nComplete('text8e5d6f03865c', { value0: manifestFile }), children: manifestIssues.length > 0 ? (_jsx("ul", { className: "mt-1 space-y-1", children: dedupeIssues(manifestIssues).map(({ key, issue }) => (_jsxs("li", { children: [_jsx("code", { className: "text-foreground font-mono text-xs break-all", children: issue.path }), ' ', issue.message, issue.line
|
|
153
151
|
? tI18nComplete('texta6b97728ff89', { value0: issue.line })
|
|
154
152
|
: ''] }, key))) })) : (_jsx("span", { children: tI18nComplete.raw('textcc85fb556a48') })) })), manifestIssues === null && conflictPaths !== null && conflictPaths.length > 0 && (_jsx(InfoBanner, { tone: "warning", icon: WarningIcon, title: tI18nComplete('text57bbed2817ff', {
|
|
155
153
|
value0: fileCount(conflictPaths.length),
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChangeRequest } from '@kortix/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* The word for what happened to a finished change request. An open one shows
|
|
4
|
+
* nothing: its state is the two buttons at the bottom of the dialog.
|
|
5
|
+
*
|
|
6
|
+
* A request an agent replaced (closed, with a later request on the same
|
|
7
|
+
* branch) names its replacement, and opens it when the host can (KRTX-3031).
|
|
8
|
+
*/
|
|
9
|
+
export declare function ChangeRequestStatusBadge({ cr, onOpenChangeRequest, }: {
|
|
10
|
+
cr: ChangeRequest;
|
|
11
|
+
onOpenChangeRequest?: (crId: string) => void;
|
|
12
|
+
}): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslations } from '../../../i18n/index.js';
|
|
4
|
+
import { translateUiCatalogText } from '../../../i18n/ui-catalog/localize-ui-catalog.js';
|
|
5
|
+
import { REMAINING_UI_TRANSLATION_KEYS } from '../../../i18n/ui-catalog/remaining-ui-translation-keys.generated.js';
|
|
6
|
+
import { Badge } from '../../../primitives/badge.js';
|
|
7
|
+
/**
|
|
8
|
+
* The word for what happened to a finished change request. An open one shows
|
|
9
|
+
* nothing: its state is the two buttons at the bottom of the dialog.
|
|
10
|
+
*
|
|
11
|
+
* A request an agent replaced (closed, with a later request on the same
|
|
12
|
+
* branch) names its replacement, and opens it when the host can (KRTX-3031).
|
|
13
|
+
*/
|
|
14
|
+
export function ChangeRequestStatusBadge({ cr, onOpenChangeRequest, }) {
|
|
15
|
+
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
16
|
+
if (cr.status === 'open')
|
|
17
|
+
return null;
|
|
18
|
+
const replacement = cr.status === 'closed' ? (cr.superseded_by ?? null) : null;
|
|
19
|
+
if (replacement) {
|
|
20
|
+
const label = tI18nComplete('textddcd87c21894', { number: replacement.number });
|
|
21
|
+
if (!onOpenChangeRequest) {
|
|
22
|
+
return (_jsx(Badge, { variant: "secondary", size: "sm", className: "mt-0.5 shrink-0", children: label }));
|
|
23
|
+
}
|
|
24
|
+
return (_jsx(Badge, { asChild: true, variant: "secondary", size: "sm", className: "mt-0.5 shrink-0 cursor-pointer hover:underline", children: _jsx("button", { type: "button", onClick: () => onOpenChangeRequest(replacement.cr_id), children: label }) }));
|
|
25
|
+
}
|
|
26
|
+
return (_jsx(Badge, { variant: cr.status === 'merged' ? 'badgeSuccess' : 'secondary', size: "sm", className: "mt-0.5 shrink-0", children: translateUiCatalogText(cr.status === 'merged' ? 'Applied' : 'Dismissed', tI18nComplete, REMAINING_UI_TRANSLATION_KEYS) }));
|
|
27
|
+
}
|
|
@@ -90,5 +90,5 @@ export function ChangeRequestsPanel({ open = false, onClose }) {
|
|
|
90
90
|
? tSidebar('loadingMore')
|
|
91
91
|
: isFetchNextPageError
|
|
92
92
|
? tSidebar('retry')
|
|
93
|
-
: tSidebar('loadMore') }) }))] }))] }), _jsx(ChangeRequestDetailDialog, { crId: selectedCrId, onClose: () => setSelectedCrId(null) }), _jsx(OpenChangeRequestDialog, { open: openDialogShown, onOpenChange: setOpenDialogShown, projectId: ctx?.projectId ?? '', defaultBranch: defaultBranch, initialHeadRef: initialHeadForDialog, onCreated: (crId) => setSelectedCrId(crId) })] }));
|
|
93
|
+
: tSidebar('loadMore') }) }))] }))] }), _jsx(ChangeRequestDetailDialog, { crId: selectedCrId, onClose: () => setSelectedCrId(null), onOpenChangeRequest: setSelectedCrId }), _jsx(OpenChangeRequestDialog, { open: openDialogShown, onOpenChange: setOpenDialogShown, projectId: ctx?.projectId ?? '', defaultBranch: defaultBranch, initialHeadRef: initialHeadForDialog, onCreated: (crId) => setSelectedCrId(crId) })] }));
|
|
94
94
|
}
|
|
@@ -490,7 +490,8 @@ export function DriveExplorer({ embedded = false, shareContext, leading, trailin
|
|
|
490
490
|
const { accepted, rejected } = partitionUploadBatch(tree.map((t) => t.file));
|
|
491
491
|
for (const { reason } of rejected)
|
|
492
492
|
errorToast(reason);
|
|
493
|
-
const
|
|
493
|
+
const acceptedSet = new Set(accepted);
|
|
494
|
+
const items = tree.filter((t) => acceptedSet.has(t.file));
|
|
494
495
|
if (items.length === 0)
|
|
495
496
|
return;
|
|
496
497
|
const root = base === '/' ? '' : base.replace(/\/+$/, '');
|
|
@@ -17,15 +17,19 @@ import { SelectionCheck, SelectMenuItem } from './drive-selection-ui.js';
|
|
|
17
17
|
import { FileThumbnail } from './file-thumbnail.js';
|
|
18
18
|
import { Download } from '../../../internal/icons/download.js';
|
|
19
19
|
import { ownClicks } from './own-clicks.js';
|
|
20
|
-
|
|
20
|
+
/** Copy, cut, copy path, rename and delete: the same on a folder and a file. */
|
|
21
|
+
function DriveMenuSharedItems({ Item, Separator, node, onCopy, onCut, onRename, onDelete, startRenaming, copyPathLabel, }) {
|
|
21
22
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
22
23
|
const hasEditActions = Boolean(onRename || onDelete);
|
|
23
|
-
return (_jsxs(_Fragment, { children: [
|
|
24
|
+
return (_jsxs(_Fragment, { children: [onCopy && (_jsxs(Item, { onClick: () => onCopy(node), children: [_jsx(ClipboardCopy, {}), tI18nComplete.raw('texte21f935f11d7')] })), onCut && (_jsxs(Item, { onClick: () => onCut(node), children: [_jsx(Scissors, {}), tI18nComplete.raw('text1f45f02561f4')] })), _jsxs(Item, { onClick: () => navigator.clipboard.writeText(node.path), children: [_jsx(Copy, {}), copyPathLabel] }), hasEditActions && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), onRename && (_jsxs(Item, { onClick: () => setTimeout(startRenaming, 100), children: [_jsx(PencilSimpleIcon, {}), tI18nComplete.raw('text3064d79a295c')] })), onDelete && (_jsxs(Item, { onClick: () => onDelete(node), children: [_jsx(TrashIcon, {}), tI18nComplete.raw('textc3812fc4acb8')] }))] }))] }));
|
|
25
|
+
}
|
|
26
|
+
export function FolderDriveMenuItems({ Item, Separator, node, onClick, onDownload, onCopy, onCut, onRename, onDelete, startRenaming, isDownloadingItem, openFolderLabel, copyPathLabel, }) {
|
|
27
|
+
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
28
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Item, { onClick: onClick, children: [_jsx(ArrowUpRight, {}), openFolderLabel] }), onDownload && (_jsxs(Item, { onClick: () => onDownload(node), disabled: isDownloadingItem, children: [_jsx(Download, {}), isDownloadingItem ? 'Zipping...' : tI18nComplete.raw('textdda839b13617')] })), _jsx(Separator, {}), _jsx(DriveMenuSharedItems, { Item: Item, Separator: Separator, node: node, onCopy: onCopy, onCut: onCut, onRename: onRename, onDelete: onDelete, startRenaming: startRenaming, copyPathLabel: copyPathLabel })] }));
|
|
24
29
|
}
|
|
25
30
|
export function FileDriveMenuItems({ Item, Separator, node, onClick, onDownload, onHistory, onCopy, onCut, onRename, onDelete, startRenaming, checkpointHistoryLabel, copyPathLabel, }) {
|
|
26
31
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
27
|
-
|
|
28
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Item, { onClick: onClick, children: [_jsx(Eye, {}), tI18nComplete.raw('text324b134f57c7')] }), onDownload && (_jsxs(Item, { onClick: () => onDownload(node), children: [_jsx(Download, {}), tI18nComplete.raw('textd6eafe823591')] })), onHistory && (_jsxs(Item, { onClick: () => onHistory(node), children: [_jsx(History, {}), checkpointHistoryLabel] })), _jsx(Separator, {}), onCopy && (_jsxs(Item, { onClick: () => onCopy(node), children: [_jsx(ClipboardCopy, {}), tI18nComplete.raw('texte21f935f11d7')] })), onCut && (_jsxs(Item, { onClick: () => onCut(node), children: [_jsx(Scissors, {}), tI18nComplete.raw('text1f45f02561f4')] })), _jsxs(Item, { onClick: () => navigator.clipboard.writeText(node.path), children: [_jsx(Copy, {}), copyPathLabel] }), hasEditActions && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), onRename && (_jsxs(Item, { onClick: () => setTimeout(startRenaming, 100), children: [_jsx(PencilSimpleIcon, {}), tI18nComplete.raw('text3064d79a295c')] })), onDelete && (_jsxs(Item, { onClick: () => onDelete(node), children: [_jsx(TrashIcon, {}), tI18nComplete.raw('textc3812fc4acb8')] }))] }))] }));
|
|
32
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Item, { onClick: onClick, children: [_jsx(Eye, {}), tI18nComplete.raw('text324b134f57c7')] }), onDownload && (_jsxs(Item, { onClick: () => onDownload(node), children: [_jsx(Download, {}), tI18nComplete.raw('textd6eafe823591')] })), onHistory && (_jsxs(Item, { onClick: () => onHistory(node), children: [_jsx(History, {}), checkpointHistoryLabel] })), _jsx(Separator, {}), _jsx(DriveMenuSharedItems, { Item: Item, Separator: Separator, node: node, onCopy: onCopy, onCut: onCut, onRename: onRename, onDelete: onDelete, startRenaming: startRenaming, copyPathLabel: copyPathLabel })] }));
|
|
29
33
|
}
|
|
30
34
|
function selectFolderRenameInput(el) {
|
|
31
35
|
el.focus();
|
|
@@ -62,7 +66,7 @@ const FolderCard = memo(function FolderCard({ node, onClick, onDownload, onRenam
|
|
|
62
66
|
// Transparent at rest, so the marked border takes no space when it appears.
|
|
63
67
|
'h-[120px] border border-transparent',
|
|
64
68
|
// Copied, cut or selected: the focus border plus its soft 15% ring.
|
|
65
|
-
(isCut || isCopied || selected) && 'border-ring ring-ring/15 ring-2', isDragOver && 'ring-primary ring-2') }), selectMode ? _jsx(SelectionCheck, { selected: selected, className: "absolute top-2 left-2" }) : null, !isRenaming && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { onClick: (e) => e.stopPropagation(), variant: "secondary", size: "icon-sm", className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100", children: _jsx(MoreVertical, { weight: "bold", className: "size-3.5" }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "w-48", children: _jsx(FolderDriveMenuItems, { Item: DropdownMenuItem, Separator: DropdownMenuSeparator, ...folderMenuProps }) })] })), _jsx("div", { className: "flex min-w-0 items-center px-0.5", children: isRenaming ? (_jsx("input", { ref: renameInputRef, type: "text", value: renameName, onChange: (e) => setRenameName(e.target.value), onKeyDown: (e) => {
|
|
69
|
+
(isCut || isCopied || selected) && 'border-ring ring-ring/15 ring-2', isDragOver && 'ring-primary ring-2') }), selectMode ? _jsx(SelectionCheck, { selected: selected, className: "absolute top-2 left-2" }) : null, !isRenaming && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { onClick: (e) => e.stopPropagation(), "aria-label": tHardcodedUi.raw('i18nComplete.textf8d46c2570e7'), variant: "secondary", size: "icon-sm", className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100", children: _jsx(MoreVertical, { weight: "bold", className: "size-3.5" }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "w-48", children: _jsx(FolderDriveMenuItems, { Item: DropdownMenuItem, Separator: DropdownMenuSeparator, ...folderMenuProps }) })] })), _jsx("div", { className: "flex min-w-0 items-center px-0.5", children: isRenaming ? (_jsx("input", { ref: renameInputRef, type: "text", "aria-label": tHardcodedUi.raw('i18nComplete.text3064d79a295c'), value: renameName, onChange: (e) => setRenameName(e.target.value), onKeyDown: (e) => {
|
|
66
70
|
if (e.nativeEvent.isComposing)
|
|
67
71
|
return;
|
|
68
72
|
if (e.key === 'Enter')
|
|
@@ -96,7 +100,7 @@ const FileCard = memo(function FileCard({ node, onClick, onDoubleClick, onDownlo
|
|
|
96
100
|
};
|
|
97
101
|
return (_jsxs(ContextMenu, { children: [_jsx(ContextMenuTrigger, { asChild: true, children: _jsxs("div", { draggable: !isRenaming, onDragStart: handleDragStart, onDragEnd: handleDragEnd, onClick: isRenaming ? undefined : onItemClick, "data-drive-item": node.path, onDoubleClick: isRenaming || !onDoubleClick ? undefined : ownClicks(() => onDoubleClick(node)), className: cn('group relative flex cursor-pointer flex-col gap-2 select-none', isCut && 'opacity-60', isDragging && 'opacity-30'), children: [_jsx(FileThumbnail, { filePath: node.path, fileName: node.name, onOpen: open, className: cn('border-border h-[120px] rounded-lg border',
|
|
98
102
|
// Copied, cut or selected: the focus border plus its soft 15% ring.
|
|
99
|
-
(isCut || isCopied || selected) && 'border-ring ring-ring/15 ring-2') }), selectMode && !uploading ? (_jsx(SelectionCheck, { selected: selected, className: "absolute top-2 left-2 z-10" })) : null, uploading ? (_jsx("span", { role: "status", "aria-label": tDrives('uploadingFile', { name: node.name }), className: "bg-popover border-border absolute top-2 left-2 z-10 flex size-7 items-center justify-center rounded-md border shadow-xs", children: _jsx(Loading, { variant: "spokes", className: "size-4" }) })) : null, !isRenaming && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { onClick: (e) => e.stopPropagation(), variant: "secondary", size: "icon-sm", className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100", children: _jsx(MoreVertical, { weight: "bold", className: "size-3.5" }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "w-48", children: _jsx(FileDriveMenuItems, { Item: DropdownMenuItem, Separator: DropdownMenuSeparator, ...fileMenuProps }) })] })), _jsx("div", { className: "flex min-w-0 items-center px-0.5", children: isRenaming ? (_jsx("input", { ref: renameInputRef, type: "text", value: renameName, onChange: (e) => setRenameName(e.target.value), onKeyDown: (e) => {
|
|
103
|
+
(isCut || isCopied || selected) && 'border-ring ring-ring/15 ring-2') }), selectMode && !uploading ? (_jsx(SelectionCheck, { selected: selected, className: "absolute top-2 left-2 z-10" })) : null, uploading ? (_jsx("span", { role: "status", "aria-label": tDrives('uploadingFile', { name: node.name }), className: "bg-popover border-border absolute top-2 left-2 z-10 flex size-7 items-center justify-center rounded-md border shadow-xs", children: _jsx(Loading, { variant: "spokes", className: "size-4" }) })) : null, !isRenaming && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { onClick: (e) => e.stopPropagation(), "aria-label": tHardcodedUi.raw('i18nComplete.textf8d46c2570e7'), variant: "secondary", size: "icon-sm", className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100", children: _jsx(MoreVertical, { weight: "bold", className: "size-3.5" }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "w-48", children: _jsx(FileDriveMenuItems, { Item: DropdownMenuItem, Separator: DropdownMenuSeparator, ...fileMenuProps }) })] })), _jsx("div", { className: "flex min-w-0 items-center px-0.5", children: isRenaming ? (_jsx("input", { ref: renameInputRef, type: "text", "aria-label": tHardcodedUi.raw('i18nComplete.text3064d79a295c'), value: renameName, onChange: (e) => setRenameName(e.target.value), onKeyDown: (e) => {
|
|
100
104
|
if (e.nativeEvent.isComposing)
|
|
101
105
|
return;
|
|
102
106
|
if (e.key === 'Enter')
|
|
@@ -125,7 +129,7 @@ export function DriveGridView({ elevatedDirs, dirs, files, onNavigateToDir, onOp
|
|
|
125
129
|
const description = meta
|
|
126
130
|
? tI18nComplete.raw(node.name === '.kortix' ? 'text85231c543c71' : 'text96ef9c0ac0c9')
|
|
127
131
|
: undefined;
|
|
128
|
-
return (_jsxs("
|
|
132
|
+
return (_jsxs("button", { type: "button", onClick: () => onNavigateToDir(node), title: description, className: "group relative flex w-full min-w-0 cursor-pointer flex-col gap-2 text-left select-none", children: [_jsx(DriveFolderThumbnail, { path: node.path, className: "h-[120px]" }), _jsx("span", { className: "text-foreground truncate px-0.5 text-sm font-medium", children: node.name })] }, node.path));
|
|
129
133
|
}) })] })), dirs.length > 0 && (_jsxs("section", { className: "space-y-2", children: [_jsx(SectionHeader, { label: tI18nComplete.raw('textc4d6bb200f4c'), count: dirs.length }), _jsx("div", { className: "grid gap-x-4 gap-y-5", style: { gridTemplateColumns: "repeat(auto-fill, minmax(168px, 1fr))" }, children: dirs.map((node) => (_jsx(FolderCard, { node: node, onClick: onNavigateToDir, onDownload: onDownloadDir, isDownloadingItem: isDirDownloading(node.path), onRename: isFixed?.(node.path) ? undefined : onRename, onDelete: isFixed?.(node.path) ? undefined : onDelete, onCopy: onCopy, onCut: isFixed?.(node.path) ? undefined : onCut, onDropMove: onDropMove, onDropUpload: onDropUpload, isCut: clipboardOperation === 'cut' && clipboardPath === node.path, isCopied: clipboardOperation === 'copy' && clipboardPath === node.path }, node.path))) })] })), files.length > 0 && (_jsxs("section", { className: "space-y-2", children: [_jsx(SectionHeader, { label: tI18nComplete.raw('textabc7e9892806'), count: files.length }), _jsx("div", { className: "grid gap-x-4 gap-y-5", style: { gridTemplateColumns: "repeat(auto-fill, minmax(168px, 1fr))" }, children: files.map((node) => (_jsx(FileCard, { node: node, onClick: onPreviewFile, onDoubleClick: onOpenFile, onDownload: onDownload, onRename: onRename, onDelete: onDelete, onHistory: onHistory, onCopy: onCopy, onCut: onCut, gitStatus: gitStatusMap.get(node.path), isCut: clipboardOperation === 'cut' && clipboardPath === node.path, isCopied: clipboardOperation === 'copy' && clipboardPath === node.path, uploading: uploadingPaths?.has(node.path) }, node.path))) })] }))] }));
|
|
130
134
|
}
|
|
131
135
|
function SectionHeader({ label, count, icon, }) {
|