@kortix/ui 0.14.4 → 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/README.md +8 -4
- 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/llm-provider/constants.d.ts +0 -1
- package/dist/customize/sections/llm-provider/constants.js +0 -2
- package/dist/customize/sections/llm-provider/models-tab-group.d.ts +1 -1
- package/dist/customize/sections/llm-provider/models-tab-group.js +7 -4
- package/dist/customize/sections/llm-provider/models-tab-row.d.ts +2 -18
- package/dist/customize/sections/llm-provider/models-tab-row.js +6 -30
- package/dist/customize/sections/llm-provider/models-tab.d.ts +0 -1
- package/dist/customize/sections/llm-provider/models-tab.js +1 -10
- package/dist/customize/sections/llm-provider/use-connected-providers.js +2 -2
- package/dist/customize/sections/llm-provider/utils.d.ts +1 -1
- package/dist/customize/sections/llm-provider/utils.js +7 -14
- package/dist/customize/sections/view/gateway/_shared.js +1 -2
- package/dist/customize/sections/view/gateway/gateway-routing.js +18 -20
- package/dist/customize/sections/view/sandbox-provider-coverage.d.ts +3 -18
- package/dist/customize/sections/view/sandbox-provider-coverage.js +7 -27
- package/dist/customize/settings/rail-copy-context.js +5 -3
- package/dist/customize/settings/tabs/sandbox-tab.d.ts +2 -27
- package/dist/customize/settings/tabs/sandbox-tab.js +13 -112
- package/dist/customize/settings/tabs/sandbox-template-form.js +9 -12
- package/dist/customize/shared/capability-tabs.js +2 -1
- package/dist/customize/shared/entity/entity-modal.d.ts +5 -1
- package/dist/customize/shared/entity/entity-modal.js +7 -4
- package/dist/customize/skills/remove-skill-button.d.ts +16 -0
- package/dist/customize/skills/remove-skill-button.js +42 -0
- package/dist/customize/skills/skills-page.js +4 -6
- 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/trigger-list.d.ts +0 -2
- package/dist/customize/triggers/schedule/trigger-list.js +1 -18
- package/dist/customize/triggers/schedule/trigger-tile.d.ts +1 -32
- package/dist/customize/triggers/schedule/trigger-tile.js +1 -16
- 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-change-requests.d.ts +14 -1
- package/dist/files/project/hooks/use-change-requests.js +44 -25
- package/dist/files/project/hooks/use-server-health.js +17 -15
- package/dist/files/renderers/docx/docx-viewer.js +4 -6
- package/dist/files/renderers/image-renderer.js +6 -24
- package/dist/files/renderers/pdf/pdf-renderer.d.ts +3 -1
- package/dist/files/renderers/pdf/pdf-renderer.js +2 -2
- package/dist/files/renderers/pdf/pdf-viewer.d.ts +3 -0
- package/dist/files/renderers/pdf/pdf-viewer.js +16 -7
- 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-content-renderer.d.ts +4 -1
- package/dist/files/viewer/file-content-renderer.js +2 -2
- 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 +36 -35
- package/dist/i18n/en.js +45 -44
- package/dist/index.d.ts +1 -1
- package/dist/internal/desktop/desktop-back-button.js +5 -3
- package/dist/internal/hooks/use-auto-scroll.js +5 -3
- package/dist/internal/hooks/use-notification-center.js +21 -15
- package/dist/internal/hooks/use-review-session-summary.d.ts +6 -0
- package/dist/internal/hooks/use-review-session-summary.js +11 -0
- package/dist/internal/lib/browser-error-noise.d.ts +1 -1
- package/dist/internal/lib/browser-error-noise.js +1 -1
- package/dist/internal/lib/browser-noise/rules/rejections.d.ts +10 -0
- package/dist/internal/lib/browser-noise/rules/rejections.js +27 -1
- package/dist/internal/lib/provider-branding.js +14 -3
- package/dist/internal/lib/trigger-clock.d.ts +42 -0
- package/dist/internal/lib/trigger-clock.js +34 -0
- package/dist/internal/lib/web-notifications.d.ts +6 -0
- package/dist/internal/lib/web-notifications.js +57 -7
- package/dist/internal/notifications/notification-bell.d.ts +13 -0
- package/dist/internal/notifications/notification-bell.js +1 -1
- package/dist/internal/notifications/notification-rows.js +2 -1
- package/dist/internal/outcomes/outcome-types.d.ts +5 -0
- package/dist/internal/reminders/reminder-filter.d.ts +12 -0
- package/dist/internal/reminders/reminder-filter.js +34 -0
- package/dist/internal/reminders/reminder-format.d.ts +6 -0
- package/dist/internal/reminders/reminder-format.js +20 -2
- package/dist/internal/stores/kortix-computer-store.d.ts +1 -1
- package/dist/internal/stores/session-hover-store.d.ts +20 -5
- package/dist/internal/stores/session-hover-store.js +31 -13
- package/dist/internal/stores/session-panel-memory-store.js +2 -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/count-badge.d.ts +3 -1
- package/dist/primitives/count-badge.js +3 -3
- package/dist/primitives/glyph-paths-source.js +1 -1
- package/dist/primitives/glyph-paths.generated.js +1 -1
- 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/providers/ui-provider.d.ts +57 -0
- package/dist/providers/ui-provider.js +4 -0
- package/dist/session/composer/ComposerCard.d.ts +2 -0
- package/dist/session/composer/ComposerCard.js +5 -1
- package/dist/session/composer/agent-selector.js +17 -5
- package/dist/session/composer/composer-chat-input.js +5 -3
- package/dist/session/composer/composer-logic.js +8 -7
- package/dist/session/composer/composer-toolbar.js +4 -2
- package/dist/session/composer/composer-underbar.js +3 -1
- package/dist/session/composer/composer.js +34 -5
- package/dist/session/composer/draft/composer-draft.js +4 -4
- package/dist/session/composer/menus/slash-actions.d.ts +22 -2
- package/dist/session/composer/menus/slash-actions.js +20 -0
- package/dist/session/composer/menus/slash-items.js +19 -3
- 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 +294 -0
- package/dist/session/header/reminder-parts.js +120 -0
- package/dist/session/header/session-reminders-indicator.d.ts +13 -0
- package/dist/session/header/session-reminders-indicator.js +142 -35
- package/dist/session/media/sandbox-url-detector.js +0 -7
- package/dist/session/models/model-availability.d.ts +23 -0
- package/dist/session/models/model-availability.js +20 -0
- package/dist/session/models/model-grouping.js +1 -4
- package/dist/session/models/model-selector.js +23 -14
- package/dist/session/models/use-model-connection-gate.js +4 -1
- package/dist/session/outcomes/change-request-outcomes.js +24 -3
- package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
- package/dist/session/outcomes/session-outcomes-provider.js +31 -3
- package/dist/session/overrides/provider-secret-pool-editor.js +2 -1
- package/dist/session/overrides/session-overrides-composer.d.ts +1 -1
- package/dist/session/overrides/session-overrides-composer.js +5 -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/mobile-tool-drawer.js +4 -2
- package/dist/session/panel/open-session-quick-view.js +2 -1
- package/dist/session/panel/panel-fallback.js +8 -4
- package/dist/session/panel/session-panel-provider.d.ts +1 -0
- package/dist/session/panel/session-panel-provider.js +19 -3
- package/dist/session/panel/session-reminders-panel.d.ts +4 -0
- package/dist/session/panel/session-reminders-panel.js +109 -0
- package/dist/session/panel/shared/use-panel-derivations.js +6 -4
- package/dist/session/panel/shared/use-panel-handoffs.d.ts +2 -2
- package/dist/session/panel/shared/use-panel-handoffs.js +5 -1
- package/dist/session/panel/use-session-panel-layout.js +7 -5
- package/dist/session/print/session-print-header.d.ts +0 -10
- package/dist/session/print/session-print-header.js +25 -9
- package/dist/session/status/session-surface.js +1 -1
- package/dist/session/thread/optimistic-turn.d.ts +5 -1
- package/dist/session/thread/optimistic-turn.js +8 -6
- package/dist/session/thread/session-chat.d.ts +6 -1
- package/dist/session/thread/session-chat.js +34 -12
- package/dist/session/thread/session-history.js +3 -1
- package/dist/session/thread/session-thread.d.ts +10 -1
- package/dist/session/thread/session-thread.js +2 -2
- 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/burst-step-body.js +4 -0
- 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/dist/workspace/sidebar/project-session-list.js +52 -55
- package/dist/workspace/sidebar/session-brief-hover-card.d.ts +35 -18
- package/dist/workspace/sidebar/session-brief-hover-card.js +114 -37
- package/dist/workspace/sidebar/session-status-mark.d.ts +15 -1
- package/dist/workspace/sidebar/session-status-mark.js +63 -17
- package/package.json +7 -3
- package/skills/kortix-ui/SKILL.md +1 -1
- package/dist/customize/sections/view/sandbox-provider-result.d.ts +0 -47
- package/dist/customize/sections/view/sandbox-provider-result.js +0 -79
|
@@ -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);
|
|
@@ -3,8 +3,6 @@ import type { ProjectTrigger } from '@kortix/sdk';
|
|
|
3
3
|
import { type ReactNode } from 'react';
|
|
4
4
|
/** "next Mon 09:00", "next 08:45" today, "On event" for webhooks and app events, "Paused" while paused. */
|
|
5
5
|
export declare function nextRunLabel(trigger: Pick<ProjectTrigger, 'type' | 'enabled' | 'next_fire_at' | 'next_cron_at' | 'auto_paused_at'>, t: UiTranslator, locale: string, now?: number): string;
|
|
6
|
-
/** "2d ago", "9h ago", "3w ago" in the viewer's locale, or "Never run". */
|
|
7
|
-
export declare function lastRunLabel(trigger: Pick<ProjectTrigger, 'last_fired_at' | 'event'>, t: UiTranslator, locale: string, now?: number): string;
|
|
8
6
|
export declare function TriggerList({ triggers, groups, eventNames, selectedSlug, runningSlug, onOpen, selection, projectPaused, }: {
|
|
9
7
|
triggers: ProjectTrigger[];
|
|
10
8
|
/** The trigger whose Run now is in flight: its row shows the session busy mark. */
|
|
@@ -9,6 +9,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
9
9
|
import { Checkbox } from '../../../primitives/checkbox.js';
|
|
10
10
|
import { SessionDotMatrix } from '../../../primitives/dot-matrix/session-dot-matrix.js';
|
|
11
11
|
import { useLocale, useTranslations } from '../../../i18n/index.js';
|
|
12
|
+
import { lastRunLabel } from '../../../internal/lib/trigger-clock.js';
|
|
12
13
|
import { cn } from '../../../internal/lib/utils.js';
|
|
13
14
|
import { Fragment } from 'react';
|
|
14
15
|
import { describeNextRun, describeWhen, triggerName, triggerSubtitle } from './schedule-copy.js';
|
|
@@ -35,24 +36,6 @@ export function nextRunLabel(trigger, t, locale, now = Date.now()) {
|
|
|
35
36
|
: date.toLocaleDateString(locale, { month: 'short', day: 'numeric' });
|
|
36
37
|
return t('text27a2c8b3a0d2', { value0: day ? `${day} ${time}` : time });
|
|
37
38
|
}
|
|
38
|
-
/** "2d ago", "9h ago", "3w ago" in the viewer's locale, or "Never run". */
|
|
39
|
-
export function lastRunLabel(trigger, t, locale, now = Date.now()) {
|
|
40
|
-
const iso = trigger.last_fired_at ?? trigger.event?.last_event_at ?? null;
|
|
41
|
-
const at = iso ? Date.parse(iso) : Number.NaN;
|
|
42
|
-
if (!Number.isFinite(at))
|
|
43
|
-
return t.raw('text3d40a69d3160');
|
|
44
|
-
const rtf = new Intl.RelativeTimeFormat(locale, { style: 'narrow', numeric: 'auto' });
|
|
45
|
-
const min = Math.floor(Math.max(0, now - at) / 60_000);
|
|
46
|
-
if (min < 1)
|
|
47
|
-
return rtf.format(0, 'second');
|
|
48
|
-
if (min < 60)
|
|
49
|
-
return rtf.format(-min, 'minute');
|
|
50
|
-
if (min < 24 * 60)
|
|
51
|
-
return rtf.format(-Math.floor(min / 60), 'hour');
|
|
52
|
-
if (min < 7 * 24 * 60)
|
|
53
|
-
return rtf.format(-Math.floor(min / (24 * 60)), 'day');
|
|
54
|
-
return rtf.format(-Math.floor(min / (7 * 24 * 60)), 'week');
|
|
55
|
-
}
|
|
56
39
|
export function TriggerList({ triggers, groups, eventNames, selectedSlug, runningSlug = null, onOpen, selection = null, projectPaused = false, }) {
|
|
57
40
|
const row = (trigger) => (_jsx(TriggerRow, { trigger: trigger, eventNames: eventNames, selected: !selection && trigger.slug === selectedSlug, running: trigger.slug === runningSlug, onOpen: () => onOpen(trigger), checked: selection ? selection.selected.has(trigger.slug) : null, projectPaused: projectPaused, onToggle: (range) => selection?.onToggle(trigger, range) }, trigger.slug));
|
|
58
41
|
return (
|
|
@@ -1,41 +1,10 @@
|
|
|
1
|
+
import { type ClockState } from '../../../internal/lib/trigger-clock.js';
|
|
1
2
|
import type { ProjectTrigger } from '@kortix/sdk';
|
|
2
|
-
export type ClockState = 'ok' | 'failed' | 'needs_connection' | 'pending' | 'paused' | 'never';
|
|
3
3
|
/**
|
|
4
4
|
* The health the clock shows: the badge state, with "live" split by whether
|
|
5
5
|
* it ever ran. `projectPaused` (the project-wide switch) pauses every clock.
|
|
6
6
|
*/
|
|
7
7
|
export declare function clockState(trigger: ProjectTrigger, projectPaused?: boolean, running?: boolean): ClockState;
|
|
8
|
-
/**
|
|
9
|
-
* ONE tone per state drives both the reflection and the dot, so they cannot
|
|
10
|
-
* disagree. Three colours, always full strength: green = live (running, ran,
|
|
11
|
-
* or not run yet), red = failed, yellow = paused or waiting on setup.
|
|
12
|
-
*/
|
|
13
|
-
export declare const CLOCK_TONE: {
|
|
14
|
-
readonly ok: {
|
|
15
|
-
readonly reflection: "text-kortix-green";
|
|
16
|
-
readonly dot: "bg-kortix-green";
|
|
17
|
-
};
|
|
18
|
-
readonly never: {
|
|
19
|
-
readonly reflection: "text-kortix-green";
|
|
20
|
-
readonly dot: "bg-kortix-green";
|
|
21
|
-
};
|
|
22
|
-
readonly failed: {
|
|
23
|
-
readonly reflection: "text-kortix-red";
|
|
24
|
-
readonly dot: "bg-kortix-red";
|
|
25
|
-
};
|
|
26
|
-
readonly needs_connection: {
|
|
27
|
-
readonly reflection: "text-kortix-yellow";
|
|
28
|
-
readonly dot: "bg-kortix-yellow";
|
|
29
|
-
};
|
|
30
|
-
readonly pending: {
|
|
31
|
-
readonly reflection: "text-kortix-yellow";
|
|
32
|
-
readonly dot: "bg-kortix-yellow";
|
|
33
|
-
};
|
|
34
|
-
readonly paused: {
|
|
35
|
-
readonly reflection: "text-kortix-yellow";
|
|
36
|
-
readonly dot: "bg-kortix-yellow";
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
8
|
export declare function TriggerTile({ trigger, projectPaused, running, surface, }: {
|
|
40
9
|
trigger: ProjectTrigger;
|
|
41
10
|
/** The project-wide pause switch is on. */
|
|
@@ -13,6 +13,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
13
13
|
*/
|
|
14
14
|
import { REFLECTION_MASK } from '../../../primitives/toast.js';
|
|
15
15
|
import { useTranslations } from '../../../i18n/index.js';
|
|
16
|
+
import { CLOCK_TONE } from '../../../internal/lib/trigger-clock.js';
|
|
16
17
|
import { cn } from '../../../internal/lib/utils.js';
|
|
17
18
|
import { ClockIcon } from '@phosphor-icons/react';
|
|
18
19
|
import { triggerBadgeState } from './schedule-copy.js';
|
|
@@ -34,22 +35,6 @@ export function clockState(trigger, projectPaused = false, running = false) {
|
|
|
34
35
|
return state;
|
|
35
36
|
return trigger.last_fired_at || trigger.event?.last_event_at ? 'ok' : 'never';
|
|
36
37
|
}
|
|
37
|
-
const GREEN = { reflection: 'text-kortix-green', dot: 'bg-kortix-green' };
|
|
38
|
-
const RED = { reflection: 'text-kortix-red', dot: 'bg-kortix-red' };
|
|
39
|
-
const YELLOW = { reflection: 'text-kortix-yellow', dot: 'bg-kortix-yellow' };
|
|
40
|
-
/**
|
|
41
|
-
* ONE tone per state drives both the reflection and the dot, so they cannot
|
|
42
|
-
* disagree. Three colours, always full strength: green = live (running, ran,
|
|
43
|
-
* or not run yet), red = failed, yellow = paused or waiting on setup.
|
|
44
|
-
*/
|
|
45
|
-
export const CLOCK_TONE = {
|
|
46
|
-
ok: GREEN,
|
|
47
|
-
never: GREEN,
|
|
48
|
-
failed: RED,
|
|
49
|
-
needs_connection: YELLOW,
|
|
50
|
-
pending: YELLOW,
|
|
51
|
-
paused: YELLOW,
|
|
52
|
-
};
|
|
53
38
|
const LABEL = {
|
|
54
39
|
ok: LABEL_KEY.live,
|
|
55
40
|
failed: LABEL_KEY.error,
|
|
@@ -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)
|
|
@@ -357,7 +357,7 @@ export function FileExplorerPage({ embedded = false } = {}) {
|
|
|
357
357
|
gridTemplateColumns: "repeat(auto-fill, minmax(150px, 1fr))",
|
|
358
358
|
}, children: Array.from({ length: 8 }).map((_, i) => (_jsx(Skeleton, { className: "h-[138px] rounded-lg" }, `fi${i}`))) })] })] })) : (_jsx("div", { className: "space-y-1", children: Array.from({ length: 10 }).map((_, i) => (_jsx(Skeleton, { className: "h-10 w-full rounded" }, i))) })) })), !!error && !isLoading && (_jsx(ErrorState, { title: tHardcodedUi.raw('featuresProjectFilesComponentsFileExplorerPage.line658JsxTextFailedToLoadFiles'), description: error instanceof Error
|
|
359
359
|
? error.message
|
|
360
|
-
: tHardcodedUi.raw('i18nComplete.text27c2ccd962c2'), action: _jsx(Button, { variant: "outline", size: "sm", onClick: () => refetchFiles(), children: tHardcodedUi.raw('i18nComplete.text942087cc2d41') }) })), isEmpty && (_jsx(EmptyState, { icon: FolderOpen, title: tHardcodedUi.raw('featuresProjectFilesComponentsDriveListView.line396JsxTextThisFolderIsEmpty'), description: tHardcodedUi.raw('featuresProjectFilesComponentsDriveListView.line398JsxTextNoFilesOrSubfoldersAtThisPathIn') })), !isLoading && !error && files && !isEmpty && (_jsxs(_Fragment, { children: [viewMode === 'grid' ? (_jsx(DriveGridView, { elevatedDirs: elevatedDirs, dirs: dirs, files: fileItems, onNavigateToDir: handleNavigateToDir, onOpenFile: handleOpenFile, onPreviewFile: handlePreviewFile, onDownload: handleDownload, onDownloadDir: handleDownloadDir, onRename: handleRename, onDelete: handleDelete, onHistory: handleHistory, onCopy: handleCopy, onCut: handleCut, onDropMove: handleDropMove, gitStatusMap: gitStatusMap, clipboardPath: clipboard?.path, clipboardOperation: clipboard?.operation, isDirDownloading: isDirDownloading, readOnly: true })) : (_jsx(DriveListView, { elevatedDirs: elevatedDirs, dirs: dirs, files: fileItems, sortDisabled: partial, onNavigateToDir: handleNavigateToDir, onOpenFile: handleOpenFile, onPreviewFile: handlePreviewFile, onDownload: handleDownload, onDownloadDir: handleDownloadDir, onRename: handleRename, onDelete: handleDelete, onHistory: handleHistory, onCopy: handleCopy, onCut: handleCut, onDropMove: handleDropMove, gitStatusMap: gitStatusMap, clipboardPath: clipboard?.path, clipboardOperation: clipboard?.operation, isDirDownloading: isDirDownloading, readOnly: true })), _jsx(LoadMoreRow, { listing: listing })] }))] }), _jsx(CheckpointsPanel, { open: rightPanel === 'history', onClose: () => setRightPanel(null) }), _jsx(ChangeRequestsPanel, { open: rightPanel === 'proposed-changes', onClose: () => setRightPanel(null) })] }), _jsx(ChangeRequestDetailDialog, { crId: createdCrId, onClose: () => setCreatedCrId(null) }), _jsx(ExplorerFilePreview, {}), searchEnabled && isSearchOpen && _jsx(FileSearch, {}), historyPopoverPath && (_jsx("div", { className: "bg-popover border-border animate-in slide-in-from-bottom-4 fade-in-0 fixed right-4 bottom-4 z-50 overflow-hidden rounded-md border shadow-2xl duration-200", children: _jsx(FileHistoryPopoverContent, { filePath: historyPopoverPath, onClose: () => setHistoryPopoverPath(null) }) })), _jsx(AlertDialog, { open: !!deleteTarget, onOpenChange: () => setDeleteTarget(null), children: _jsxs(AlertDialogContent, { className: "sm:max-w-md", onOpenAutoFocus: (e) => {
|
|
360
|
+
: tHardcodedUi.raw('i18nComplete.text27c2ccd962c2'), action: _jsx(Button, { variant: "outline", size: "sm", onClick: () => refetchFiles(), children: tHardcodedUi.raw('i18nComplete.text942087cc2d41') }) })), isEmpty && (_jsx(EmptyState, { icon: FolderOpen, title: tHardcodedUi.raw('featuresProjectFilesComponentsDriveListView.line396JsxTextThisFolderIsEmpty'), description: tHardcodedUi.raw('featuresProjectFilesComponentsDriveListView.line398JsxTextNoFilesOrSubfoldersAtThisPathIn') })), !isLoading && !error && files && !isEmpty && (_jsxs(_Fragment, { children: [viewMode === 'grid' ? (_jsx(DriveGridView, { elevatedDirs: elevatedDirs, dirs: dirs, files: fileItems, onNavigateToDir: handleNavigateToDir, onOpenFile: handleOpenFile, onPreviewFile: handlePreviewFile, onDownload: handleDownload, onDownloadDir: handleDownloadDir, onRename: handleRename, onDelete: handleDelete, onHistory: handleHistory, onCopy: handleCopy, onCut: handleCut, onDropMove: handleDropMove, gitStatusMap: gitStatusMap, clipboardPath: clipboard?.path, clipboardOperation: clipboard?.operation, isDirDownloading: isDirDownloading, readOnly: true })) : (_jsx(DriveListView, { elevatedDirs: elevatedDirs, dirs: dirs, files: fileItems, sortDisabled: partial, onNavigateToDir: handleNavigateToDir, onOpenFile: handleOpenFile, onPreviewFile: handlePreviewFile, onDownload: handleDownload, onDownloadDir: handleDownloadDir, onRename: handleRename, onDelete: handleDelete, onHistory: handleHistory, onCopy: handleCopy, onCut: handleCut, onDropMove: handleDropMove, gitStatusMap: gitStatusMap, clipboardPath: clipboard?.path, clipboardOperation: clipboard?.operation, isDirDownloading: isDirDownloading, readOnly: true })), _jsx(LoadMoreRow, { listing: listing })] }))] }), _jsx(CheckpointsPanel, { open: rightPanel === 'history', onClose: () => setRightPanel(null) }), _jsx(ChangeRequestsPanel, { open: rightPanel === 'proposed-changes', onClose: () => setRightPanel(null) })] }), _jsx(ChangeRequestDetailDialog, { crId: createdCrId, onClose: () => setCreatedCrId(null), onOpenChangeRequest: setCreatedCrId }), _jsx(ExplorerFilePreview, {}), searchEnabled && isSearchOpen && _jsx(FileSearch, {}), historyPopoverPath && (_jsx("div", { className: "bg-popover border-border animate-in slide-in-from-bottom-4 fade-in-0 fixed right-4 bottom-4 z-50 overflow-hidden rounded-md border shadow-2xl duration-200", children: _jsx(FileHistoryPopoverContent, { filePath: historyPopoverPath, onClose: () => setHistoryPopoverPath(null) }) })), _jsx(AlertDialog, { open: !!deleteTarget, onOpenChange: () => setDeleteTarget(null), children: _jsxs(AlertDialogContent, { className: "sm:max-w-md", onOpenAutoFocus: (e) => {
|
|
361
361
|
e.preventDefault();
|
|
362
362
|
deleteButtonRef.current?.focus();
|
|
363
363
|
}, children: [_jsxs(AlertDialogHeader, { children: [_jsxs(AlertDialogTitle, { children: [tHardcodedUi.raw('i18nComplete.texte2d0a54968ea'), ' ', deleteTarget?.type === 'directory' ? 'folder' : 'file'] }), _jsxs(AlertDialogDescription, { children: [tHardcodedUi.raw('featuresProjectFilesComponentsFileExplorerPage.line806JsxTextAreYouSureYouWantToDelete'), ' ', _jsxs("span", { className: "text-foreground font-semibold", children: [tHardcodedUi.raw('featuresProjectFilesComponentsFileExplorerPage.line807JsxTextQuot'), deleteTarget?.name, tHardcodedUi.raw('featuresProjectFilesComponentsFileExplorerPage.line807JsxTextQuot32c14d98')] }), tHardcodedUi.raw('featuresProjectFilesComponentsFileExplorerPage.line807JsxTextThisActionCannotBeUndone')] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: deleteMutation.isPending, children: tHardcodedUi.raw('i18nComplete.text19766ed6ccb2') }), _jsx(AlertDialogAction, { ref: deleteButtonRef, onClick: (e) => {
|
|
@@ -83,12 +83,7 @@ function CompactCommitRow({ commit, filePath }) {
|
|
|
83
83
|
setTimeout(() => setCopied(false), 2000);
|
|
84
84
|
}, [commit.hash]);
|
|
85
85
|
const toggle = () => setExpanded((v) => !v);
|
|
86
|
-
return (_jsxs("li", { className: cn('relative rounded-md', expanded && 'bg-muted'), children: [_jsxs("div", {
|
|
87
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
88
|
-
e.preventDefault();
|
|
89
|
-
toggle();
|
|
90
|
-
}
|
|
91
|
-
}, className: cn('group/row focus-visible:ring-ring flex w-full cursor-pointer items-start gap-3 rounded-md px-2 py-2 text-left outline-none focus-visible:ring-1', !expanded && 'hover:bg-muted'), children: [_jsx("span", { className: "border-muted-foreground bg-background relative z-10 mt-[5px] size-2.5 shrink-0 rounded-full border" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-foreground truncate text-sm font-medium", children: commit.subject }), _jsxs(InlineMeta, { className: "mt-0.5", children: [commit.author, _jsx("time", { title: formatFullDate(commit.timestamp), children: formatRelativeDate(commit.timestamp) })] })] }), _jsxs("button", { type: "button", onClick: handleCopyHash, className: "text-muted-foreground hover:text-foreground flex shrink-0 items-center gap-1 rounded-sm px-1 font-mono text-xs leading-5", title: tHardcodedUi.raw('featuresProjectFilesComponentsFileHistoryPopover.line160JsxAttrTitleCopyCheckpointId'), children: [copied ? (_jsx(SolidCheckIcon, { className: "text-kortix-green size-3" })) : (_jsx(Copy, { className: "size-3 opacity-0 group-hover/row:opacity-100" })), commit.shortHash] })] }), expanded && _jsx(CompactCommitDiff, { filePath: filePath, commitHash: commit.hash })] }));
|
|
86
|
+
return (_jsxs("li", { className: cn('relative rounded-md', expanded && 'bg-muted'), children: [_jsxs("div", { className: cn('group/row has-[button[aria-expanded]:focus-visible]:ring-ring flex w-full items-start gap-3 rounded-md has-[button[aria-expanded]:focus-visible]:ring-1', !expanded && 'hover:bg-muted'), children: [_jsxs("button", { type: "button", "aria-expanded": expanded, onClick: toggle, className: "flex min-w-0 flex-1 cursor-pointer items-start gap-3 py-2 pl-2 text-left outline-none", children: [_jsx("span", { className: "border-muted-foreground bg-background relative z-10 mt-[5px] size-2.5 shrink-0 rounded-full border" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-foreground truncate text-sm font-medium", children: commit.subject }), _jsxs(InlineMeta, { className: "mt-0.5", children: [commit.author, _jsx("time", { title: formatFullDate(commit.timestamp), children: formatRelativeDate(commit.timestamp) })] })] })] }), _jsxs("button", { type: "button", onClick: handleCopyHash, className: "text-muted-foreground hover:text-foreground my-2 mr-2 flex shrink-0 items-center gap-1 rounded-sm px-1 font-mono text-xs leading-5", title: tHardcodedUi.raw('featuresProjectFilesComponentsFileHistoryPopover.line160JsxAttrTitleCopyCheckpointId'), children: [copied ? (_jsx(SolidCheckIcon, { className: "text-kortix-green size-3" })) : (_jsx(Copy, { className: "size-3 opacity-0 group-hover/row:opacity-100" })), commit.shortHash] })] }), expanded && _jsx(CompactCommitDiff, { filePath: filePath, commitHash: commit.hash })] }));
|
|
92
87
|
}
|
|
93
88
|
export function FileHistoryPopoverContent({ filePath, onClose }) {
|
|
94
89
|
const tHardcodedUi = useTranslations('hardcodedUi');
|
|
@@ -112,7 +112,12 @@ export function FileSearch() {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
}, [closeSearch, results, selectedIndex, handleSelect, scrollItemIntoView]);
|
|
115
|
-
return (_jsx("div", { className: "absolute inset-0 z-50 bg-black/60 backdrop-blur-sm", onClick:
|
|
115
|
+
return (_jsx("div", { role: "presentation", className: "absolute inset-0 z-50 bg-black/60 backdrop-blur-sm", onClick: (e) => {
|
|
116
|
+
if (e.target === e.currentTarget)
|
|
117
|
+
closeSearch();
|
|
118
|
+
else
|
|
119
|
+
e.stopPropagation();
|
|
120
|
+
}, children: _jsx("div", { className: "mx-auto mt-4 max-w-lg px-4", children: _jsxs("div", { className: "border-border bg-card overflow-hidden rounded-2xl border shadow-2xl", children: [_jsxs("div", { className: "flex items-center gap-2 border-b px-3", children: [_jsx(Search, { className: "text-muted-foreground h-4 w-4 shrink-0" }), _jsx(Input, { type: "text", ref: inputRef, value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: handleInputKeyDown, placeholder: tHardcodedUi.raw(searchContents
|
|
116
121
|
? 'featuresProjectFilesComponentsFileSearch.searchContentsPlaceholder'
|
|
117
122
|
: 'featuresProjectFilesComponentsFileSearch.line109JsxAttrPlaceholderSearchFiles'), className: "h-10 border-0 px-0 shadow-none focus-visible:ring-0" }), _jsx("button", { onClick: closeSearch, "aria-label": tI18nHardcoded.raw('autoFeaturesProjectFilesComponentsFileSearchJsxAttrAriaLabel732c1816'), className: "hover:bg-muted rounded p-1", children: _jsx(X, { className: "text-muted-foreground h-4 w-4" }) })] }), canSearchContents && (_jsx("div", { className: "flex items-center border-b", children: _jsx(Switch, { label: tHardcodedUi.raw('featuresProjectFilesComponentsFileSearch.searchContents'), "aria-label": tHardcodedUi.raw('featuresProjectFilesComponentsFileSearch.searchContents'), checked: contentMode, onCheckedChange: (checked) => {
|
|
118
123
|
setContentMode(checked);
|
|
@@ -30,6 +30,7 @@ function BranchRow({ branch }) {
|
|
|
30
30
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
31
31
|
return (_jsxs("div", { className: "flex items-center justify-start gap-2 py-0.5", children: [_jsx(Layers, { className: "text-muted-foreground size-4 shrink-0" }), _jsxs("div", { className: "flex flex-col items-start gap-0", children: [branch.subject && (_jsx("span", { className: "text-muted-foreground/80 truncate text-xs", children: branch.subject })), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-foreground truncate font-mono text-xs", children: displayBranchName(branch.name) }), branch.is_default && (_jsx(Badge, { variant: "kortix", size: "xs", className: "shrink-0 text-[11px]", children: tI18nComplete.raw('text37a8eec1ce19') }))] })] })] }));
|
|
32
32
|
}
|
|
33
|
+
const NO_BRANCHES = [];
|
|
33
34
|
const PICKER_TRIGGER_CLASS = 'py-2 flex-1 min-w-0 rounded-sm border-0 bg-transparent px-2 hover:bg-muted/40 focus:ring-0';
|
|
34
35
|
export function OpenChangeRequestDialog({ open, onOpenChange, projectId, defaultBranch, session = null, initialHeadRef, onCreated, }) {
|
|
35
36
|
const tHardcodedUi = useTranslations('hardcodedUi');
|
|
@@ -41,7 +42,7 @@ export function OpenChangeRequestDialog({ open, onOpenChange, projectId, default
|
|
|
41
42
|
const activeSession = session ?? lastSessionRef.current;
|
|
42
43
|
const sessionMode = activeSession !== null;
|
|
43
44
|
const branchesQuery = useBranches({ enabled: open && !sessionMode, projectId });
|
|
44
|
-
const branches = branchesQuery.data?.branches ??
|
|
45
|
+
const branches = branchesQuery.data?.branches ?? NO_BRANCHES;
|
|
45
46
|
const branchMap = useMemo(() => {
|
|
46
47
|
const m = new Map();
|
|
47
48
|
for (const b of branches)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProjectBranch } from '@kortix/sdk';
|
|
2
|
+
/** A session branch is named by its session id. A person knows it by the session's title (KRTX-3020). */
|
|
3
|
+
export declare function versionTitle(branch: ProjectBranch): string;
|
|
4
|
+
/** Search reads the title, the agent, the branch name and the last commit. */
|
|
5
|
+
export declare function versionMatches(branch: ProjectBranch, query: string): boolean;
|
|
6
|
+
/** The default branch, live work, then what the person archived or deleted, each in served order. */
|
|
7
|
+
export declare function groupVersions(branches: ProjectBranch[]): {
|
|
8
|
+
primary: ProjectBranch[];
|
|
9
|
+
others: ProjectBranch[];
|
|
10
|
+
archived: ProjectBranch[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** A session branch is named by its session id. A person knows it by the session's title (KRTX-3020). */
|
|
2
|
+
export function versionTitle(branch) {
|
|
3
|
+
return branch.session?.title?.trim() || branch.name;
|
|
4
|
+
}
|
|
5
|
+
/** Search reads the title, the agent, the branch name and the last commit. */
|
|
6
|
+
export function versionMatches(branch, query) {
|
|
7
|
+
const q = query.trim().toLowerCase();
|
|
8
|
+
if (!q)
|
|
9
|
+
return true;
|
|
10
|
+
return [branch.session?.title, branch.session?.agent_name, branch.name, branch.subject].some((value) => value?.toLowerCase().includes(q));
|
|
11
|
+
}
|
|
12
|
+
/** The default branch, live work, then what the person archived or deleted, each in served order. */
|
|
13
|
+
export function groupVersions(branches) {
|
|
14
|
+
const primary = [];
|
|
15
|
+
const others = [];
|
|
16
|
+
const archived = [];
|
|
17
|
+
for (const b of branches) {
|
|
18
|
+
if (b.is_default)
|
|
19
|
+
primary.push(b);
|
|
20
|
+
else if (b.session?.archived || b.session?.deleted)
|
|
21
|
+
archived.push(b);
|
|
22
|
+
else
|
|
23
|
+
others.push(b);
|
|
24
|
+
}
|
|
25
|
+
return { primary, others, archived };
|
|
26
|
+
}
|