@kortix/ui 0.14.5 → 0.14.6
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/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-grant-pages.js +5 -6
- package/dist/customize/agents/agent-page.js +2 -1
- 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/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/connector-advanced-tools.js +4 -6
- 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/view/gateway/gateway-routing.js +15 -18
- package/dist/customize/settings/rail-copy-context.js +5 -3
- package/dist/customize/settings/tabs/sandbox-template-form.js +9 -12
- 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/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/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-preview-modal.js +1 -1
- package/dist/files/viewer/use-file-content-state.js +1 -1
- package/dist/i18n/en.d.ts +10 -0
- package/dist/i18n/en.js +10 -0
- package/dist/internal/desktop/desktop-back-button.js +5 -3
- package/dist/internal/hooks/use-auto-scroll.js +5 -3
- package/dist/internal/notifications/notification-rows.js +2 -1
- package/dist/internal/outcomes/outcome-types.d.ts +5 -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/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/composer-chat-input.js +5 -3
- package/dist/session/composer/composer-logic.js +8 -7
- package/dist/session/composer/draft/composer-draft.js +4 -4
- package/dist/session/composer/pasted-text.js +3 -2
- package/dist/session/composer/stores/queued-draft-store.js +3 -2
- package/dist/session/header/reminder-parts.d.ts +11 -2
- package/dist/session/header/reminder-parts.js +9 -4
- 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-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/thread/session-chat.js +12 -9
- package/dist/session/thread/session-history.js +3 -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/session-terminal-panel.js +3 -5
- package/dist/theme/theme.js +2 -1
- package/dist/workspace/projects/modal/github-import-pickers.js +7 -6
- package/dist/workspace/review/review-center.js +13 -10
- package/dist/workspace/session-workspace.js +5 -9
- 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-mcp-nav.js +6 -2
- package/dist/workspace/sidebar/modal/rename-session-modal.js +8 -3
- package/package.json +3 -3
|
@@ -287,26 +287,23 @@ export function GatewayRouting({ projectId, canWrite, projectDefaultPending, })
|
|
|
287
287
|
const [advancedOpen, setAdvancedOpen] = useState(false);
|
|
288
288
|
const [resetOpen, setResetOpen] = useState(false);
|
|
289
289
|
const [availability, setAvailability] = useState({});
|
|
290
|
-
const hydratedPolicySignature =
|
|
290
|
+
const [hydratedPolicySignature, setHydratedPolicySignature] = useState(null);
|
|
291
291
|
const previewRequestId = useRef(0);
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
setAdvancedOpen((current) => current || hasAdvancedRoutingConfig(routing.data.project));
|
|
305
|
-
}, [routing.data]);
|
|
292
|
+
// Effective routing also changes when the header's project default changes.
|
|
293
|
+
// Keep an in-progress fallback draft intact unless the persisted project
|
|
294
|
+
// policy itself changed (save, reset, or an external editor update).
|
|
295
|
+
const persistedProject = routing.data?.project;
|
|
296
|
+
const persistedSignature = persistedProject ? editablePolicySignature(persistedProject) : null;
|
|
297
|
+
if (persistedProject && persistedSignature !== hydratedPolicySignature) {
|
|
298
|
+
setHydratedPolicySignature(persistedSignature);
|
|
299
|
+
setDraft(clonePolicy(persistedProject));
|
|
300
|
+
setFallbackMode(fallbackModeForPolicy(persistedProject.defaultFallback));
|
|
301
|
+
setAdvancedOpen((current) => current || hasAdvancedRoutingConfig(persistedProject));
|
|
302
|
+
}
|
|
303
|
+
const previewRoute = routing.preview.mutateAsync;
|
|
306
304
|
// Debounced availability preview: whenever the draft's referenced models
|
|
307
305
|
// change, ask the gateway which of them currently have a connected
|
|
308
306
|
// provider so the chain editor can flag a dead fallback before save.
|
|
309
|
-
// biome-ignore lint/correctness/useExhaustiveDependencies: routing.preview's mutateAsync is a stable handle from useGatewayRoutingPolicy and shouldn't retrigger this debounce.
|
|
310
307
|
useEffect(() => {
|
|
311
308
|
if (!draft || !routing.data) {
|
|
312
309
|
setAvailability({});
|
|
@@ -325,7 +322,7 @@ export function GatewayRouting({ projectId, canWrite, projectDefaultPending, })
|
|
|
325
322
|
const timer = setTimeout(() => {
|
|
326
323
|
Promise.all(targets.map(async (model) => {
|
|
327
324
|
try {
|
|
328
|
-
const result = await
|
|
325
|
+
const result = await previewRoute({
|
|
329
326
|
requestedModel: model,
|
|
330
327
|
imageInput: false,
|
|
331
328
|
});
|
|
@@ -345,7 +342,7 @@ export function GatewayRouting({ projectId, canWrite, projectDefaultPending, })
|
|
|
345
342
|
});
|
|
346
343
|
}, 400);
|
|
347
344
|
return () => clearTimeout(timer);
|
|
348
|
-
}, [draft, routing.data, modelDefaults.projectDefault]);
|
|
345
|
+
}, [draft, routing.data, modelDefaults.projectDefault, previewRoute]);
|
|
349
346
|
const models = useMemo(() => {
|
|
350
347
|
const byWire = new Map();
|
|
351
348
|
for (const model of catalogModels) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useContext } from 'react';
|
|
3
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
4
4
|
import { railGroups } from './rail.js';
|
|
5
5
|
export const DEFAULT_SETTINGS_RAIL_CHROME_COPY = {
|
|
6
6
|
settings: 'Settings',
|
|
@@ -14,13 +14,15 @@ const DEFAULT_VALUE = {
|
|
|
14
14
|
};
|
|
15
15
|
const SettingsRailCopyContext = createContext(DEFAULT_VALUE);
|
|
16
16
|
export function SettingsRailCopyProvider({ groups, chrome, children, }) {
|
|
17
|
-
|
|
17
|
+
const value = useMemo(() => ({ groups, chrome }), [groups, chrome]);
|
|
18
|
+
return (_jsx(SettingsRailCopyContext.Provider, { value: value, children: children }));
|
|
18
19
|
}
|
|
19
20
|
export function useSettingsRailChromeCopy() {
|
|
20
21
|
return useContext(SettingsRailCopyContext).chrome;
|
|
21
22
|
}
|
|
22
23
|
export function useSettingsRailItem(tab) {
|
|
23
|
-
|
|
24
|
+
const { groups } = useContext(SettingsRailCopyContext);
|
|
25
|
+
for (const group of groups) {
|
|
24
26
|
const item = group.items.find((candidate) => candidate.tab === tab);
|
|
25
27
|
if (item)
|
|
26
28
|
return item;
|
|
@@ -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;
|
|
@@ -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,
|
|
@@ -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, }) {
|
|
@@ -84,7 +84,7 @@ function ListRow({ node, onClick, onDoubleClick, onDownload, onRename, onDelete,
|
|
|
84
84
|
(isCut || isCopied || selected) && 'ring-ring bg-ring/15 ring-1 ring-inset', isDragging && 'opacity-30', isDragOver && 'bg-primary/8'), children: [_jsx(TableCell, { children: _jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [selectMode ? _jsx(SelectionCheck, { selected: selected, className: "shrink-0" }) : null, isDir ? (_jsx(Folder, { className: "text-muted-foreground size-4 shrink-0" })) : (getFileIcon(node.name, {
|
|
85
85
|
className: 'size-4 shrink-0 text-muted-foreground',
|
|
86
86
|
variant: 'monochrome',
|
|
87
|
-
})), isRenaming ? (_jsx("input", { ref: renameInputRef, type: "text", value: renameName, onChange: (e) => setRenameName(e.target.value), onKeyDown: (e) => {
|
|
87
|
+
})), isRenaming ? (_jsx("input", { ref: renameInputRef, type: "text", "aria-label": tHardcodedUi.raw('i18nComplete.text3064d79a295c'), value: renameName, onChange: (e) => setRenameName(e.target.value), onKeyDown: (e) => {
|
|
88
88
|
if (e.key === 'Enter') {
|
|
89
89
|
if (e.nativeEvent.isComposing)
|
|
90
90
|
return;
|
|
@@ -92,7 +92,7 @@ function ListRow({ node, onClick, onDoubleClick, onDownload, onRename, onDelete,
|
|
|
92
92
|
}
|
|
93
93
|
if (e.key === 'Escape')
|
|
94
94
|
setIsRenaming(false);
|
|
95
|
-
}, onBlur: confirmRename, onClick: (e) => e.stopPropagation(), className: "border-border min-w-0 flex-1 border-b bg-transparent py-0.5 text-sm outline-none" })) : (_jsx("span", { className: cn('truncate text-sm font-medium', node.ignored && 'opacity-50', node.name.startsWith('.') && 'text-muted-foreground'), children: node.name })), uploading ? (_jsx("span", { role: "status", "aria-label": tDrives('uploadingFile', { name: node.name }), className: "shrink-0", children: _jsx(Loading, { variant: "spokes", className: "size-3.5" }) })) : null] }) }), _jsx(TableCell, { children: isDir ? (_jsx(ChalkBadge, { label: tHardcodedUi.raw('i18nComplete.text74ccd4330384') })) : ext ? (_jsx(ChalkBadge, { label: ext })) : (_jsx("span", { className: "text-muted-foreground text-sm", children: "\u2014" })) }), _jsx(TableCell, { children: !isRenaming && (_jsx("div", { className: "flex justify-end", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { onClick: (e) => e.stopPropagation(), variant: "ghost", size: "icon-xs", className: "shrink-0 opacity-0 group-hover:opacity-100", children: _jsx(MoreVertical, { className: "text-muted-foreground size-3.5" }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "w-48", children: isDir ? (_jsx(FolderDriveMenuItems, { Item: DropdownMenuItem, Separator: DropdownMenuSeparator, ...folderMenuProps })) : (_jsx(FileDriveMenuItems, { Item: DropdownMenuItem, Separator: DropdownMenuSeparator, ...fileMenuProps })) })] }) })) })] }) }), _jsx(ContextMenuContent, { className: "w-48", children: selection?.selectionMenu(node, ContextMenuItem, ContextMenuSeparator) ?? (_jsxs(_Fragment, { children: [_jsx(SelectMenuItem, { selection: selection, node: node, Item: ContextMenuItem, Separator: ContextMenuSeparator }), isDir ? (_jsx(FolderDriveMenuItems, { Item: ContextMenuItem, Separator: ContextMenuSeparator, ...folderMenuProps })) : (_jsx(FileDriveMenuItems, { Item: ContextMenuItem, Separator: ContextMenuSeparator, ...fileMenuProps }))] })) })] }));
|
|
95
|
+
}, onBlur: confirmRename, onClick: (e) => e.stopPropagation(), className: "border-border min-w-0 flex-1 border-b bg-transparent py-0.5 text-sm outline-none" })) : (_jsx("span", { className: cn('truncate text-sm font-medium', node.ignored && 'opacity-50', node.name.startsWith('.') && 'text-muted-foreground'), children: node.name })), uploading ? (_jsx("span", { role: "status", "aria-label": tDrives('uploadingFile', { name: node.name }), className: "shrink-0", children: _jsx(Loading, { variant: "spokes", className: "size-3.5" }) })) : null] }) }), _jsx(TableCell, { children: isDir ? (_jsx(ChalkBadge, { label: tHardcodedUi.raw('i18nComplete.text74ccd4330384') })) : ext ? (_jsx(ChalkBadge, { label: ext })) : (_jsx("span", { className: "text-muted-foreground text-sm", children: "\u2014" })) }), _jsx(TableCell, { children: !isRenaming && (_jsx("div", { className: "flex justify-end", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { onClick: (e) => e.stopPropagation(), "aria-label": tHardcodedUi.raw('i18nComplete.textf8d46c2570e7'), variant: "ghost", size: "icon-xs", className: "shrink-0 opacity-0 group-hover:opacity-100", children: _jsx(MoreVertical, { className: "text-muted-foreground size-3.5" }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "w-48", children: isDir ? (_jsx(FolderDriveMenuItems, { Item: DropdownMenuItem, Separator: DropdownMenuSeparator, ...folderMenuProps })) : (_jsx(FileDriveMenuItems, { Item: DropdownMenuItem, Separator: DropdownMenuSeparator, ...fileMenuProps })) })] }) })) })] }) }), _jsx(ContextMenuContent, { className: "w-48", children: selection?.selectionMenu(node, ContextMenuItem, ContextMenuSeparator) ?? (_jsxs(_Fragment, { children: [_jsx(SelectMenuItem, { selection: selection, node: node, Item: ContextMenuItem, Separator: ContextMenuSeparator }), isDir ? (_jsx(FolderDriveMenuItems, { Item: ContextMenuItem, Separator: ContextMenuSeparator, ...folderMenuProps })) : (_jsx(FileDriveMenuItems, { Item: ContextMenuItem, Separator: ContextMenuSeparator, ...fileMenuProps }))] })) })] }));
|
|
96
96
|
}
|
|
97
97
|
function ElevatedDirRow({ node, onNavigate }) {
|
|
98
98
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
@@ -119,10 +119,10 @@ export function DriveListView({ elevatedDirs, dirs, files, onNavigateToDir, onOp
|
|
|
119
119
|
setSortBy(field);
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
|
-
const
|
|
122
|
+
const renderSortIcon = (field) => {
|
|
123
123
|
if (sortDisabled || sortBy !== field)
|
|
124
124
|
return null;
|
|
125
125
|
return sortOrder === 'asc' ? (_jsx(ArrowUp, { className: "ml-1 size-3" })) : (_jsx(ArrowDown, { className: "ml-1 size-3" }));
|
|
126
126
|
};
|
|
127
|
-
return (_jsx("div", { className: "space-y-7 p-5", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { className: "hover:bg-transparent", children: [_jsx(TableHead, { children: _jsxs(Button, { onClick: () => handleHeaderClick('name'), disabled: sortDisabled, variant: "transparent", className: "text-muted-foreground hover:text-foreground m-0 h-fit w-fit p-0 font-normal has-[>svg]:p-0", children: [tI18nComplete.raw('textdcd1d5223f73'),
|
|
127
|
+
return (_jsx("div", { className: "space-y-7 p-5", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { className: "hover:bg-transparent", children: [_jsx(TableHead, { children: _jsxs(Button, { onClick: () => handleHeaderClick('name'), disabled: sortDisabled, variant: "transparent", className: "text-muted-foreground hover:text-foreground m-0 h-fit w-fit p-0 font-normal has-[>svg]:p-0", children: [tI18nComplete.raw('textdcd1d5223f73'), renderSortIcon('name')] }) }), _jsx(TableHead, { children: _jsxs(Button, { onClick: () => handleHeaderClick('type'), disabled: sortDisabled, variant: "transparent", className: "text-muted-foreground hover:text-foreground m-0 h-fit w-fit p-0 font-normal has-[>svg]:p-0", children: [tI18nComplete.raw('textbaaddf70fb5d'), renderSortIcon('type')] }) }), _jsx(TableHead, { className: "w-[52px]", children: _jsx("span", { className: "sr-only", children: tI18nComplete.raw('textff8059dc6752') }) })] }) }), _jsxs(TableBody, { children: [elevatedDirs.map((node) => (_jsx(ElevatedDirRow, { node: node, onNavigate: () => onNavigateToDir(node) }, node.path))), dirs.map((node) => (_jsx(ListRow, { node: node, onClick: () => onNavigateToDir(node), 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.map((node) => (_jsx(ListRow, { node: node, onClick: () => onPreviewFile(node), onDoubleClick: () => onOpenFile(node), 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)))] })] }) }));
|
|
128
128
|
}
|
|
@@ -12,7 +12,7 @@ function BreadcrumbSegments({ segments, onSegmentClick, onHomeClick, fileMode, f
|
|
|
12
12
|
// When rootPath is set, only show segments at or below it
|
|
13
13
|
const rootSegmentCount = useMemo(() => (rootPath ? rootPath.split('/').filter(Boolean).length : 0), [rootPath]);
|
|
14
14
|
const visibleSegments = useMemo(() => (rootPath ? segments.slice(rootSegmentCount) : segments), [rootPath, segments, rootSegmentCount]);
|
|
15
|
-
return (_jsxs("nav", { className: "flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto", onDoubleClick: onDoubleClick, title: onDoubleClick ? tI18nComplete.raw('text5efd0bed7735') : undefined, children: [_jsx("button", { onClick: onHomeClick, className: cn('flex shrink-0 cursor-pointer items-center gap-1 rounded-lg px-2 py-1 transition-colors', 'hover:bg-muted', visibleSegments.length === 0
|
|
15
|
+
return (_jsxs("nav", { className: "flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto", onDoubleClick: onDoubleClick, title: onDoubleClick ? tI18nComplete.raw('text5efd0bed7735') : undefined, children: [_jsx("button", { onClick: onHomeClick, "aria-label": tI18nComplete.raw('text3a78695388b3'), className: cn('flex shrink-0 cursor-pointer items-center gap-1 rounded-lg px-2 py-1 transition-colors', 'hover:bg-muted', visibleSegments.length === 0
|
|
16
16
|
? 'text-foreground bg-muted/50 font-medium'
|
|
17
17
|
: 'text-muted-foreground'), children: _jsx(FolderRoot, { className: "h-3.5 w-3.5" }) }), visibleSegments.map((segment, visibleIndex) => {
|
|
18
18
|
// Skip 'workspace' when not sandboxed (rootPath null)
|