zidane-ui 9.1.4 → 9.1.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/adapters/server-extensions-host.js +1 -1
- package/dist/adapters/server-host.js +2 -1
- package/dist/adapters/server-machines-host.js +1 -1
- package/dist/adapters/server-session-host.js +87 -13
- package/dist/adapters/server-settings-host.js +1 -1
- package/dist/appearance/AppearanceProvider.js +2 -2
- package/dist/appearance/headless/index.js +1 -1
- package/dist/approvals/headless/index.js +2 -2
- package/dist/chat/HostTranscript.d.ts +5 -1
- package/dist/chat/HostTranscript.js +16 -4
- package/dist/chat/RunEstimateChip.d.ts +5 -3
- package/dist/chat/RunEstimateChip.js +33 -3
- package/dist/chat/Transcript.js +1 -1
- package/dist/chat/composer/ConversationBadges.js +16 -10
- package/dist/chat/composer/composer-bus.d.ts +2 -2
- package/dist/chat/composer/composer-bus.js +2 -2
- package/dist/chat/composer/use-composer-stores.js +1 -1
- package/dist/chat/composer/use-run-meter.js +1 -1
- package/dist/chat/headless/composer/conversation-badges.d.ts +8 -3
- package/dist/chat/headless/composer/conversation-badges.js +26 -11
- package/dist/chat/headless/composer/index.js +2 -2
- package/dist/chat/headless/composer/labels-chrome.d.ts +3 -1
- package/dist/chat/headless/composer/labels-chrome.js +3 -1
- package/dist/chat/headless/index.d.ts +6 -3
- package/dist/chat/headless/index.js +16 -13
- package/dist/chat/headless/labels.d.ts +54 -1
- package/dist/chat/headless/labels.js +62 -2
- package/dist/chat/headless/secrets.d.ts +32 -0
- package/dist/chat/headless/secrets.js +43 -0
- package/dist/chat/headless/session-list.d.ts +45 -0
- package/dist/chat/headless/sidebar/estimates.js +13 -1
- package/dist/chat/headless/sidebar/history.d.ts +71 -0
- package/dist/chat/headless/sidebar/history.js +174 -0
- package/dist/chat/headless/sidebar/index.d.ts +3 -2
- package/dist/chat/headless/sidebar/index.js +2 -1
- package/dist/chat/headless/sidebar/labels.d.ts +50 -0
- package/dist/chat/headless/sidebar/labels.js +1 -0
- package/dist/chat/headless/sidebar/query.d.ts +2 -2
- package/dist/chat/headless/sidebar/query.js +6 -3
- package/dist/chat/headless/sidebar/types.d.ts +7 -1
- package/dist/chat/headless/sidebar/view.js +2 -0
- package/dist/chat/headless/transcript/auth-failure.d.ts +67 -0
- package/dist/chat/headless/transcript/auth-failure.js +87 -0
- package/dist/chat/headless/transcript/index.d.ts +2 -1
- package/dist/chat/headless/transcript/index.js +2 -1
- package/dist/chat/headless/transcript/nesting.d.ts +3 -3
- package/dist/chat/headless/transcript/nesting.js +12 -4
- package/dist/chat/index.d.ts +4 -2
- package/dist/chat/index.js +3 -1
- package/dist/chat/interactions/InboxPanel.d.ts +6 -2
- package/dist/chat/interactions/InboxPanel.js +82 -44
- package/dist/chat/interactions/PlanCard.d.ts +2 -2
- package/dist/chat/interactions/PlanCard.js +1 -1
- package/dist/chat/interactions/QuestionField.d.ts +8 -3
- package/dist/chat/interactions/QuestionField.js +89 -8
- package/dist/chat/interactions/QuestionForm.d.ts +3 -1
- package/dist/chat/interactions/QuestionForm.js +48 -10
- package/dist/chat/interactions/SecretInput.d.ts +32 -0
- package/dist/chat/interactions/SecretInput.js +72 -0
- package/dist/chat/interactions/card-ui.d.ts +5 -3
- package/dist/chat/interactions/card-ui.js +5 -3
- package/dist/chat/interactions/index.d.ts +2 -1
- package/dist/chat/interactions/index.js +2 -1
- package/dist/chat/sidebar/SessionSidebar.js +2 -0
- package/dist/chat/sidebar/SidebarFilterMenu.d.ts +7 -2
- package/dist/chat/sidebar/SidebarFilterMenu.js +26 -2
- package/dist/chat/sidebar/SidebarSessionRow.d.ts +3 -1
- package/dist/chat/sidebar/SidebarSessionRow.js +8 -3
- package/dist/chat/sidebar/sidebar-live.js +8 -4
- package/dist/chat/transcript/AuthFailureCard.d.ts +34 -0
- package/dist/chat/transcript/AuthFailureCard.js +358 -0
- package/dist/chat/transcript/InteractionToolBody.js +12 -2
- package/dist/chat/transcript/actions.d.ts +24 -1
- package/dist/chat/transcript/index.d.ts +3 -2
- package/dist/chat/transcript/index.js +2 -1
- package/dist/chat/transcript/notices.d.ts +2 -1
- package/dist/chat/transcript/notices.js +13 -1
- package/dist/chat/transcript/script-input.d.ts +1 -1
- package/dist/chat/transcript/shell-block.js +1 -1
- package/dist/components/HowItWorks.d.ts +8 -1
- package/dist/components/HowItWorks.js +2 -2
- package/dist/components/RowActionsMenu.d.ts +6 -1
- package/dist/components/RowActionsMenu.js +4 -0
- package/dist/core.css +24 -0
- package/dist/dist/{index-WlE93Q6d.d.ts → index-DqCio7Nd.d.ts} +36 -3
- package/dist/dist/index-f-XWIoYo.d.ts +1 -0
- package/dist/dist/index.d.ts +6 -0
- package/dist/dist/sandbox-B4OW6oNx.d.ts +2 -0
- package/dist/dist/timeout-B5pO5I5a.d.ts +30 -0
- package/dist/extensions/ExtensionSettingsPage.js +1 -1
- package/dist/extensions/ExtensionSettingsSidebar.js +1 -1
- package/dist/extensions/headless/fixture-host.js +1 -1
- package/dist/extensions/headless/index.js +4 -4
- package/dist/extensions/hooks.js +1 -1
- package/dist/files/DiffsTab.js +1 -1
- package/dist/files/EditorColumn.js +1 -1
- package/dist/files/MediaDiff.js +1 -1
- package/dist/files/SearchPanel.js +121 -53
- package/dist/files/headless/name-match.js +29 -14
- package/dist/files/useEntryActions.js +1 -1
- package/dist/files/useOpenFiles.js +1 -1
- package/dist/git/WherePicker.js +2 -2
- package/dist/git/headless/environment.d.ts +6 -1
- package/dist/git/headless/environment.js +5 -2
- package/dist/git/headless/labels.d.ts +2 -0
- package/dist/git/headless/labels.js +2 -0
- package/dist/git/index.d.ts +2 -1
- package/dist/git/index.js +2 -1
- package/dist/git/useStartFromPanel.d.ts +22 -0
- package/dist/git/useStartFromPanel.js +91 -0
- package/dist/keybindings/KeyCommands.js +1 -1
- package/dist/keybindings/KeybindingsProvider.js +1 -1
- package/dist/keybindings/headless/catalog.d.ts +1 -1
- package/dist/keybindings/headless/catalog.js +14 -2
- package/dist/keybindings/headless/index.js +2 -2
- package/dist/keybindings/headless/key-scope.d.ts +4 -2
- package/dist/keybindings/headless/key-scope.js +17 -2
- package/dist/keybindings/headless/overrides.js +1 -1
- package/dist/machines/HostSyncPanel.js +1 -1
- package/dist/machines/SyncOutcomeBadge.js +1 -1
- package/dist/machines/headless/index.js +1 -1
- package/dist/onboarding/demos/features.d.ts +9 -1
- package/dist/onboarding/demos/features.js +107 -2
- package/dist/onboarding/demos/how-it-works.d.ts +5 -1
- package/dist/onboarding/demos/how-it-works.js +120 -2
- package/dist/onboarding/demos/index.js +1 -1
- package/dist/onboarding/headless/labels.d.ts +17 -0
- package/dist/onboarding/headless/labels.js +17 -0
- package/dist/onboarding/index.js +4 -4
- package/dist/onboarding/marks.d.ts +1 -2
- package/dist/onboarding/marks.js +4 -12
- package/dist/onboarding/steps/ConnectorsStep.js +1 -1
- package/dist/onboarding/steps/ReadyStep.js +1 -1
- package/dist/onboarding/steps/SkillsStep.js +1 -1
- package/dist/onboarding/steps/connect/ProviderPanel.js +1 -1
- package/dist/onboarding/tutorials.d.ts +3 -1
- package/dist/onboarding/tutorials.js +2 -1
- package/dist/palette/app-sources.js +1 -1
- package/dist/palette/headless/app-sources.js +10 -0
- package/dist/palette/headless/labels.js +2 -0
- package/dist/session/ArtifactsPanel.js +1 -1
- package/dist/session/PanelAttention.d.ts +14 -6
- package/dist/session/PanelAttention.js +35 -24
- package/dist/session/PlanTracker.d.ts +54 -0
- package/dist/session/PlanTracker.js +413 -0
- package/dist/session/ProjectHome.d.ts +15 -2
- package/dist/session/ProjectHome.js +158 -85
- package/dist/session/RemindersPanel.d.ts +25 -0
- package/dist/session/RemindersPanel.js +526 -0
- package/dist/session/SecretsPanel.d.ts +19 -0
- package/dist/session/SecretsPanel.js +241 -0
- package/dist/session/SessionProvider.d.ts +26 -5
- package/dist/session/SessionProvider.js +51 -6
- package/dist/session/StepStatusIcon.d.ts +24 -0
- package/dist/session/StepStatusIcon.js +50 -0
- package/dist/session/TodoList.d.ts +4 -3
- package/dist/session/TodoList.js +6 -5
- package/dist/session/headless/fixture-host.d.ts +32 -22
- package/dist/session/headless/fixture-host.js +86 -51
- package/dist/session/headless/fixture-plans.d.ts +57 -0
- package/dist/session/headless/fixture-plans.js +141 -0
- package/dist/session/headless/fixture-schedules.d.ts +49 -0
- package/dist/session/headless/fixture-schedules.js +133 -0
- package/dist/session/headless/home-layout.d.ts +10 -2
- package/dist/session/headless/home-layout.js +7 -2
- package/dist/session/headless/host.d.ts +85 -13
- package/dist/session/headless/index.d.ts +5 -3
- package/dist/session/headless/index.js +5 -3
- package/dist/session/headless/labels.d.ts +95 -12
- package/dist/session/headless/labels.js +67 -18
- package/dist/session/headless/plans.d.ts +53 -0
- package/dist/session/headless/plans.js +78 -0
- package/dist/session/headless/reminder-labels.d.ts +63 -0
- package/dist/session/headless/reminder-labels.js +84 -0
- package/dist/session/headless/schedules.d.ts +93 -0
- package/dist/session/headless/schedules.js +190 -0
- package/dist/session/headless/secrets.d.ts +28 -0
- package/dist/session/headless/secrets.js +48 -0
- package/dist/session/index.d.ts +7 -5
- package/dist/session/index.js +6 -4
- package/dist/session/testing/contract.d.ts +18 -5
- package/dist/session/testing/contract.js +351 -43
- package/dist/session/testing/index.d.ts +4 -2
- package/dist/session/testing/index.js +4 -2
- package/dist/settings/headless/catalog.js +17 -1
- package/dist/settings/headless/index.d.ts +2 -2
- package/dist/settings/headless/index.js +3 -3
- package/dist/settings/headless/labels.d.ts +0 -2
- package/dist/settings/headless/labels.js +0 -2
- package/dist/settings/headless/layout.js +7 -1
- package/dist/settings/headless/providers.d.ts +17 -1
- package/dist/settings/headless/providers.js +19 -1
- package/dist/settings/headless/search.d.ts +1 -1
- package/dist/settings/rows.d.ts +1 -1
- package/dist/settings/rows.js +2 -2
- package/dist/settings/sections/appearance/AppearanceSection.js +2 -2
- package/dist/settings/sections/claude-import/ClaudeImportDialog.js +1 -1
- package/dist/settings/sections/editor/EditorSection.js +1 -1
- package/dist/settings/sections/environments/EnvironmentsSection.js +1 -1
- package/dist/settings/sections/extensions/ChangeOriginDialog.js +1 -1
- package/dist/settings/sections/extensions/CreateExtensionDialog.js +1 -1
- package/dist/settings/sections/extensions/ExtensionsSection.js +1 -1
- package/dist/settings/sections/host-catalog/HostCatalogSection.js +1 -1
- package/dist/settings/sections/instructions/InstructionsSection.js +1 -1
- package/dist/settings/sections/keybindings/labels.d.ts +2 -0
- package/dist/settings/sections/keybindings/labels.js +2 -0
- package/dist/settings/sections/keybindings/rows.js +8 -0
- package/dist/settings/sections/mcp/McpSection.js +1 -1
- package/dist/settings/sections/mcp/McpServerRow.js +1 -1
- package/dist/settings/sections/models/ModelRows.js +2 -2
- package/dist/settings/sections/providers/ProvidersSection.js +209 -201
- package/dist/settings/sections/providers/ServerProvidersSection.js +1 -1
- package/dist/settings/sections/shared/catalog.js +1 -1
- package/dist/settings/sections/skills/SkillList.js +1 -1
- package/dist/settings/sections/skills/SkillsSection.js +2 -2
- package/dist/styles.css +59 -1
- package/dist/terminal/HostTerminalSurface.js +2 -2
- package/dist/workspace/PanelContentView.d.ts +22 -4
- package/dist/workspace/PanelContentView.js +112 -16
- package/dist/workspace/PanelGlyph.d.ts +21 -0
- package/dist/workspace/PanelGlyph.js +33 -0
- package/dist/workspace/PanelHome.js +5 -3
- package/dist/workspace/PanelStrip.js +11 -4
- package/dist/workspace/PanelToolbar.d.ts +32 -0
- package/dist/workspace/PanelToolbar.js +194 -0
- package/dist/workspace/WorkspaceProvider.d.ts +3 -1
- package/dist/workspace/WorkspaceProvider.js +6 -2
- package/dist/workspace/extension-tabs.js +5 -2
- package/dist/workspace/headless/host.d.ts +4 -0
- package/dist/workspace/headless/index.d.ts +3 -1
- package/dist/workspace/headless/index.js +4 -2
- package/dist/workspace/headless/labels.d.ts +10 -0
- package/dist/workspace/headless/labels.js +11 -1
- package/dist/workspace/headless/pages.d.ts +15 -0
- package/dist/workspace/headless/pages.js +49 -0
- package/dist/workspace/headless/tab-mark.d.ts +14 -0
- package/dist/workspace/headless/tab-mark.js +27 -0
- package/dist/workspace/headless/view.d.ts +7 -1
- package/dist/workspace/index.d.ts +3 -2
- package/dist/workspace/index.js +3 -2
- package/dist/workspace/testing/index.js +6 -0
- package/dist/workspace/workspace-key-commands.js +3 -3
- package/package.json +2 -2
- package/src/styles/motion.css +13 -0
- package/src/styles/onboarding.css +0 -1
- package/src/styles/primitives.css +10 -0
- package/src/styles/workspace.css +17 -0
- package/dist/session/TodosPanel.d.ts +0 -19
- package/dist/session/TodosPanel.js +0 -251
- package/dist/session/headless/todos.d.ts +0 -22
- package/dist/session/headless/todos.js +0 -38
|
@@ -5,6 +5,8 @@ import { RowActionsMenu } from "../components/RowActionsMenu.js";
|
|
|
5
5
|
import { CountBadge, TabPill } from "../components/TabPill.js";
|
|
6
6
|
import { useWorkspaceLabels } from "./useWorkspaceLabels.js";
|
|
7
7
|
import { useWorkspaceActions, useWorkspaceContent } from "./WorkspaceProvider.js";
|
|
8
|
+
import { panelTabMark } from "./headless/tab-mark.js";
|
|
9
|
+
import { PanelGlyph } from "./PanelGlyph.js";
|
|
8
10
|
import { caretX, insertBefore } from "./headless/strip-drop.js";
|
|
9
11
|
import { startDrag } from "./dnd/engine.js";
|
|
10
12
|
import { useDropTarget } from "./dnd/hooks.js";
|
|
@@ -120,6 +122,10 @@ function PanelStrip({ tabs, activeId, groupId, scopeKey, closedTabs, label, cont
|
|
|
120
122
|
const addItems = useMemo(() => closedTabs.map((t) => ({
|
|
121
123
|
id: t.id,
|
|
122
124
|
label: t.label,
|
|
125
|
+
icon: /* @__PURE__ */ jsx(PanelGlyph, {
|
|
126
|
+
tab: t,
|
|
127
|
+
fallback: "i-ph-app-window"
|
|
128
|
+
}),
|
|
123
129
|
onSelect: () => onPick(t.id)
|
|
124
130
|
})), [closedTabs, onPick]);
|
|
125
131
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -157,7 +163,8 @@ function PanelStrip({ tabs, activeId, groupId, scopeKey, closedTabs, label, cont
|
|
|
157
163
|
text: panelBadgeText(entry.content.badge),
|
|
158
164
|
tone: "neutral"
|
|
159
165
|
} : null;
|
|
160
|
-
const
|
|
166
|
+
const mark = panelTabMark(tab);
|
|
167
|
+
const icon = mark?.kind === "icon" ? mark.gui : void 0;
|
|
161
168
|
return /* @__PURE__ */ jsx(motion.div, {
|
|
162
169
|
layout: "position",
|
|
163
170
|
"data-tab-id": tab.id,
|
|
@@ -194,9 +201,9 @@ function PanelStrip({ tabs, activeId, groupId, scopeKey, closedTabs, label, cont
|
|
|
194
201
|
role: "status",
|
|
195
202
|
"aria-label": labels.panelTabInUse,
|
|
196
203
|
className: "zg-arc shrink-0"
|
|
197
|
-
}) :
|
|
198
|
-
|
|
199
|
-
"
|
|
204
|
+
}) : /* @__PURE__ */ jsx(PanelGlyph, {
|
|
205
|
+
tab,
|
|
206
|
+
className: "text-zg-body shrink-0"
|
|
200
207
|
}),
|
|
201
208
|
trailing: badge && /* @__PURE__ */ jsx(CountBadge, {
|
|
202
209
|
text: badge.text,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CSSProperties } from "react";
|
|
2
|
+
import { PanelControl, PanelSearch, PanelView } from "zidane/chat/pure";
|
|
3
|
+
//#region src/workspace/PanelToolbar.d.ts
|
|
4
|
+
/** How long typing rests before the search reloads the panel. */
|
|
5
|
+
declare const PANEL_SEARCH_DEBOUNCE_MS = 300;
|
|
6
|
+
/** Props for {@link PanelToolbar}. */
|
|
7
|
+
interface PanelToolbarProps {
|
|
8
|
+
/** The panel's controls. */
|
|
9
|
+
controls: readonly PanelControl[];
|
|
10
|
+
/** The panel's search field. Absent: none. */
|
|
11
|
+
search?: PanelSearch;
|
|
12
|
+
/** What the user picked, by control id: shown over the content's own values. */
|
|
13
|
+
view?: PanelView;
|
|
14
|
+
/** The text in the search field. */
|
|
15
|
+
searchText?: string;
|
|
16
|
+
/** A control changed: one option, or the options of a `multi` control. */
|
|
17
|
+
onControl: (id: string, value: string | readonly string[]) => void;
|
|
18
|
+
/** The search text changed (after typing rests). Absent: no search field. */
|
|
19
|
+
onSearch?: (text: string) => void;
|
|
20
|
+
/** Extra classes on the root. */
|
|
21
|
+
className?: string;
|
|
22
|
+
/** Inline styles on the root. */
|
|
23
|
+
style?: CSSProperties;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Renders a panel's controls, search field and filter menus.
|
|
27
|
+
*
|
|
28
|
+
* @param props - The {@link PanelToolbarProps}.
|
|
29
|
+
*/
|
|
30
|
+
declare function PanelToolbar({ controls, search, view, searchText, onControl, onSearch, className, style }: PanelToolbarProps): import("react").JSX.Element | null;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { PANEL_SEARCH_DEBOUNCE_MS, PanelToolbar, PanelToolbarProps };
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { Menu, MenuRow, MenuSeparator } from "../components/Menu.js";
|
|
2
|
+
import { Popover } from "../components/floating/Popover.js";
|
|
3
|
+
import { useWorkspaceLabels } from "./useWorkspaceLabels.js";
|
|
4
|
+
import { PanelControls } from "./PanelItems.js";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
//#region src/workspace/PanelToolbar.tsx
|
|
8
|
+
/** How long typing rests before the search reloads the panel. */
|
|
9
|
+
const PANEL_SEARCH_DEBOUNCE_MS = 300;
|
|
10
|
+
/** What a menu control shows: its picked options, and the option that means no filter (`select`). */
|
|
11
|
+
function pickedOf(control, view) {
|
|
12
|
+
const own = view?.[control.id];
|
|
13
|
+
if (control.kind === "multi") {
|
|
14
|
+
const picked = Array.isArray(own) ? own : typeof own === "string" ? [own] : control.values ?? [];
|
|
15
|
+
return {
|
|
16
|
+
picked,
|
|
17
|
+
active: picked.length > 0
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const value = typeof own === "string" && control.options.some((o) => o.id === own) ? own : control.value;
|
|
21
|
+
return {
|
|
22
|
+
picked: [value],
|
|
23
|
+
active: value !== (control.neutral ?? control.options[0]?.id)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Renders a panel's controls, search field and filter menus.
|
|
28
|
+
*
|
|
29
|
+
* @param props - The {@link PanelToolbarProps}.
|
|
30
|
+
*/
|
|
31
|
+
function PanelToolbar({ controls, search, view, searchText = "", onControl, onSearch, className = "", style }) {
|
|
32
|
+
const labels = useWorkspaceLabels();
|
|
33
|
+
const segmented = controls.filter((c) => (c.kind ?? "segmented") === "segmented");
|
|
34
|
+
const menus = controls.filter((c) => c.kind === "select" || c.kind === "multi");
|
|
35
|
+
const searching = search !== void 0 && onSearch !== void 0;
|
|
36
|
+
const filtering = menus.some((c) => pickedOf(c, view).active);
|
|
37
|
+
if (segmented.length === 0 && menus.length === 0 && !searching) return null;
|
|
38
|
+
const clear = () => {
|
|
39
|
+
for (const c of menus) {
|
|
40
|
+
if (!pickedOf(c, view).active) continue;
|
|
41
|
+
onControl(c.id, c.kind === "multi" ? [] : c.neutral ?? c.options[0].id);
|
|
42
|
+
}
|
|
43
|
+
if (searchText) onSearch?.("");
|
|
44
|
+
};
|
|
45
|
+
const controlsOf = segmented.map((c) => withPicked(c, view));
|
|
46
|
+
if (!searching && menus.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
47
|
+
className,
|
|
48
|
+
style,
|
|
49
|
+
children: /* @__PURE__ */ jsx(PanelControls, {
|
|
50
|
+
controls: controlsOf,
|
|
51
|
+
onChange: onControl
|
|
52
|
+
})
|
|
53
|
+
});
|
|
54
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
55
|
+
className: `flex flex-wrap items-center gap-1.5 ${className}`,
|
|
56
|
+
style,
|
|
57
|
+
children: [
|
|
58
|
+
segmented.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
59
|
+
className: "shrink-0",
|
|
60
|
+
children: /* @__PURE__ */ jsx(PanelControls, {
|
|
61
|
+
controls: controlsOf,
|
|
62
|
+
onChange: onControl
|
|
63
|
+
})
|
|
64
|
+
}),
|
|
65
|
+
searching && /* @__PURE__ */ jsx(SearchField, {
|
|
66
|
+
text: searchText,
|
|
67
|
+
placeholder: search.placeholder,
|
|
68
|
+
onSearch
|
|
69
|
+
}),
|
|
70
|
+
menus.map((c) => /* @__PURE__ */ jsx(FilterMenu, {
|
|
71
|
+
control: c,
|
|
72
|
+
view,
|
|
73
|
+
onChange: onControl
|
|
74
|
+
}, c.id)),
|
|
75
|
+
(filtering || searchText !== "") && /* @__PURE__ */ jsx("button", {
|
|
76
|
+
type: "button",
|
|
77
|
+
onClick: clear,
|
|
78
|
+
className: "h-6 px-1.5 bg-transparent border-0 rounded-zg-sm text-zg-meta text-[var(--zg-text-muted)] cursor-pointer whitespace-nowrap hover:text-[var(--zg-text)]",
|
|
79
|
+
children: labels.panelFiltersClear
|
|
80
|
+
})
|
|
81
|
+
]
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/** A segmented control showing the user's pick before the content for it lands. */
|
|
85
|
+
function withPicked(control, view) {
|
|
86
|
+
const own = view?.[control.id];
|
|
87
|
+
return typeof own === "string" && control.options.some((o) => o.id === own) ? {
|
|
88
|
+
...control,
|
|
89
|
+
value: own
|
|
90
|
+
} : control;
|
|
91
|
+
}
|
|
92
|
+
/** The search field: it reloads once typing rests; Esc clears it. */
|
|
93
|
+
function SearchField({ text, placeholder, onSearch }) {
|
|
94
|
+
const labels = useWorkspaceLabels();
|
|
95
|
+
const [draft, setDraft] = useState(text);
|
|
96
|
+
const sent = useRef(text);
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (text !== sent.current) {
|
|
99
|
+
sent.current = text;
|
|
100
|
+
setDraft(text);
|
|
101
|
+
}
|
|
102
|
+
}, [text]);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (draft === sent.current) return void 0;
|
|
105
|
+
const timer = setTimeout(() => {
|
|
106
|
+
sent.current = draft;
|
|
107
|
+
onSearch(draft);
|
|
108
|
+
}, 300);
|
|
109
|
+
return () => clearTimeout(timer);
|
|
110
|
+
}, [draft, onSearch]);
|
|
111
|
+
const name = placeholder ?? labels.panelSearch;
|
|
112
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
113
|
+
className: "zg-well h-7 flex-1 min-w-[8rem] flex items-center gap-1.5 px-2 text-zg-ui",
|
|
114
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
115
|
+
"aria-hidden": true,
|
|
116
|
+
className: "i-ph-magnifying-glass shrink-0 text-[var(--zg-text-muted)]"
|
|
117
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
118
|
+
type: "search",
|
|
119
|
+
value: draft,
|
|
120
|
+
onChange: (e) => setDraft(e.target.value),
|
|
121
|
+
onKeyDown: (e) => {
|
|
122
|
+
if (e.key !== "Escape" || draft === "") return;
|
|
123
|
+
e.stopPropagation();
|
|
124
|
+
sent.current = "";
|
|
125
|
+
setDraft("");
|
|
126
|
+
onSearch("");
|
|
127
|
+
},
|
|
128
|
+
placeholder: name,
|
|
129
|
+
"aria-label": name,
|
|
130
|
+
className: "flex-1 min-w-0 bg-transparent border-0 outline-none text-[var(--zg-text)] placeholder:text-[var(--zg-text-subtle)]"
|
|
131
|
+
})]
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/** A `select` or `multi` control: a button saying what is picked, opening its options. */
|
|
135
|
+
function FilterMenu({ control, view, onChange }) {
|
|
136
|
+
const labels = useWorkspaceLabels();
|
|
137
|
+
const multi = control.kind === "multi";
|
|
138
|
+
const { picked, active } = pickedOf(control, view);
|
|
139
|
+
const names = active ? control.options.filter((o) => picked.includes(o.id)).map((o) => o.label) : [];
|
|
140
|
+
const summary = labels.panelFilterSummary(control.label, names);
|
|
141
|
+
return /* @__PURE__ */ jsx(Popover, {
|
|
142
|
+
ariaLabel: control.label,
|
|
143
|
+
role: "menu",
|
|
144
|
+
side: "bottom",
|
|
145
|
+
align: "start",
|
|
146
|
+
width: 240,
|
|
147
|
+
trigger: (props) => /* @__PURE__ */ jsxs("button", {
|
|
148
|
+
type: "button",
|
|
149
|
+
...props,
|
|
150
|
+
title: summary,
|
|
151
|
+
"data-active": active ? "" : void 0,
|
|
152
|
+
className: `zg-press-subtle inline-flex items-center gap-1 h-6 max-w-[14rem] px-2 rounded-full text-zg-meta cursor-pointer ${active ? "zg-raised border-0 text-[var(--zg-text)]" : "bg-transparent border-0 text-[var(--zg-text-muted)] hover:text-[var(--zg-text)] hover:before:bg-[var(--zg-row-hover)]"}`,
|
|
153
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
154
|
+
className: "truncate",
|
|
155
|
+
children: summary
|
|
156
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
157
|
+
"aria-hidden": true,
|
|
158
|
+
className: "i-ph-caret-down shrink-0 text-zg-badge"
|
|
159
|
+
})]
|
|
160
|
+
}),
|
|
161
|
+
children: (close) => /* @__PURE__ */ jsxs(Menu, {
|
|
162
|
+
"aria-label": control.label,
|
|
163
|
+
className: "max-h-80 overflow-y-auto",
|
|
164
|
+
children: [control.options.map((o) => {
|
|
165
|
+
const checked = picked.includes(o.id);
|
|
166
|
+
return /* @__PURE__ */ jsx(MenuRow, {
|
|
167
|
+
size: "sm",
|
|
168
|
+
role: multi ? "menuitemcheckbox" : "menuitemradio",
|
|
169
|
+
"aria-checked": checked,
|
|
170
|
+
checked,
|
|
171
|
+
...o.icon?.gui ? { icon: /* @__PURE__ */ jsx("span", {
|
|
172
|
+
"aria-hidden": true,
|
|
173
|
+
className: o.icon.gui
|
|
174
|
+
}) } : {},
|
|
175
|
+
title: o.label,
|
|
176
|
+
onClick: () => {
|
|
177
|
+
if (multi) {
|
|
178
|
+
onChange(control.id, checked ? picked.filter((id) => id !== o.id) : [...picked, o.id]);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (!checked) onChange(control.id, o.id);
|
|
182
|
+
close();
|
|
183
|
+
}
|
|
184
|
+
}, o.id);
|
|
185
|
+
}), multi && picked.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MenuSeparator, {}), /* @__PURE__ */ jsx(MenuRow, {
|
|
186
|
+
size: "sm",
|
|
187
|
+
title: labels.panelFilterClear,
|
|
188
|
+
onClick: () => onChange(control.id, [])
|
|
189
|
+
})] })]
|
|
190
|
+
})
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
export { PANEL_SEARCH_DEBOUNCE_MS, PanelToolbar };
|
|
@@ -134,6 +134,8 @@ declare function useWorkspaceActions(): WorkspaceActions;
|
|
|
134
134
|
declare function useOptionalWorkspaceActions(): WorkspaceActions | null;
|
|
135
135
|
/** The catalog, strips and open state. Re-renders on navigation, not on content loads. */
|
|
136
136
|
declare function useWorkspaceView(): WorkspaceView;
|
|
137
|
+
/** {@link useWorkspaceView}, or `null` outside a `WorkspaceProvider`. */
|
|
138
|
+
declare function useOptionalWorkspaceView(): WorkspaceView | null;
|
|
137
139
|
/** The one-shot requests to tab bodies. */
|
|
138
140
|
declare function useWorkspaceRequests(): WorkspaceRequests;
|
|
139
141
|
/** Extension content and badges. Re-renders on every content load and badge change. */
|
|
@@ -152,4 +154,4 @@ declare function useWorkspace(): WorkspaceApi;
|
|
|
152
154
|
*/
|
|
153
155
|
declare function useExtensionPanels(panels: WorkspacePanels | undefined, cwd: string | null): readonly WorkspacePanelSummary[];
|
|
154
156
|
//#endregion
|
|
155
|
-
export { WorkspaceActions, WorkspaceApi, WorkspaceContent, WorkspaceContentTarget, WorkspaceHostProvider, WorkspaceHostProviderProps, WorkspaceProvider, WorkspaceProviderProps, WorkspaceRequests, WorkspaceView, useExtensionPanels, useOptionalWorkspaceActions, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceRequests, useWorkspaceView };
|
|
157
|
+
export { WorkspaceActions, WorkspaceApi, WorkspaceContent, WorkspaceContentTarget, WorkspaceHostProvider, WorkspaceHostProviderProps, WorkspaceProvider, WorkspaceProviderProps, WorkspaceRequests, WorkspaceView, useExtensionPanels, useOptionalWorkspaceActions, useOptionalWorkspaceView, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceRequests, useWorkspaceView };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LabelsProvider } from "../labels.js";
|
|
2
|
-
import { EMPTY_CONTENT_ENTRY, bindingKey, createPanelContents } from "./headless/contents.js";
|
|
3
2
|
import { activeTabOf } from "./headless/panel-tree.js";
|
|
4
3
|
import { EMPTY_WORKSPACE_LAYOUT, createMemoryLayouts } from "./headless/layouts.js";
|
|
4
|
+
import { EMPTY_CONTENT_ENTRY, bindingKey, createPanelContents } from "./headless/contents.js";
|
|
5
5
|
import { groupViews, sameAttention, viewOf } from "./headless/view.js";
|
|
6
6
|
import { createWorkspaceOps } from "./headless/ops.js";
|
|
7
7
|
import { useWorkspaceLabels } from "./useWorkspaceLabels.js";
|
|
@@ -339,6 +339,10 @@ function useOptionalWorkspaceActions() {
|
|
|
339
339
|
function useWorkspaceView() {
|
|
340
340
|
return required(useContext(ViewContext), "useWorkspaceView");
|
|
341
341
|
}
|
|
342
|
+
/** {@link useWorkspaceView}, or `null` outside a `WorkspaceProvider`. */
|
|
343
|
+
function useOptionalWorkspaceView() {
|
|
344
|
+
return useContext(ViewContext);
|
|
345
|
+
}
|
|
342
346
|
/** The one-shot requests to tab bodies. */
|
|
343
347
|
function useWorkspaceRequests() {
|
|
344
348
|
return required(useContext(RequestsContext), "useWorkspaceRequests");
|
|
@@ -409,4 +413,4 @@ function useExtensionPanels(panels, cwd) {
|
|
|
409
413
|
return known ?? lastCatalog;
|
|
410
414
|
}
|
|
411
415
|
//#endregion
|
|
412
|
-
export { WorkspaceHostProvider, WorkspaceProvider, useExtensionPanels, useOptionalWorkspaceActions, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceRequests, useWorkspaceView };
|
|
416
|
+
export { WorkspaceHostProvider, WorkspaceProvider, useExtensionPanels, useOptionalWorkspaceActions, useOptionalWorkspaceView, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceRequests, useWorkspaceView };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { extensionsErrorOf } from "../extensions/headless/host.js";
|
|
1
2
|
import { useExtensionsLabels } from "../extensions/useExtensionsLabels.js";
|
|
2
3
|
import { ExtensionComponent } from "../extensions/ExtensionComponent.js";
|
|
3
4
|
import { useExtensionEffectRouter, useExtensionItems, useExtensionsHost } from "../extensions/ExtensionsProvider.js";
|
|
4
|
-
import { extensionsErrorOf } from "../extensions/headless/host.js";
|
|
5
5
|
import { ExtensionWebview } from "../extensions/ExtensionWebview.js";
|
|
6
6
|
import { PanelContentView } from "./PanelContentView.js";
|
|
7
7
|
import { useWorkspaceView } from "./WorkspaceProvider.js";
|
|
@@ -38,13 +38,16 @@ function useWithExtensionTabs(tabs) {
|
|
|
38
38
|
return useMemo(() => {
|
|
39
39
|
const listed = new Set(tabs.map((t) => t.id));
|
|
40
40
|
const added = [];
|
|
41
|
-
for (const { item } of panels) {
|
|
41
|
+
for (const { item, extension } of panels) {
|
|
42
42
|
if (!item.surfaces.includes("side") || listed.has(item.id)) continue;
|
|
43
43
|
listed.add(item.id);
|
|
44
44
|
added.push({
|
|
45
45
|
id: item.id,
|
|
46
46
|
label: item.label,
|
|
47
47
|
...item.icon ? { icon: item.icon } : {},
|
|
48
|
+
owner: extension,
|
|
49
|
+
...item.ownerName ? { ownerName: item.ownerName } : {},
|
|
50
|
+
...item.ownerIcon ? { ownerIcon: item.ownerIcon } : {},
|
|
48
51
|
builtin: true,
|
|
49
52
|
extension: "panel"
|
|
50
53
|
});
|
|
@@ -42,6 +42,10 @@ interface WorkspacePanelSummary {
|
|
|
42
42
|
label: string;
|
|
43
43
|
/** The extension that registered it. */
|
|
44
44
|
owner: string;
|
|
45
|
+
/** That extension's display name. */
|
|
46
|
+
ownerName?: string;
|
|
47
|
+
/** That extension's own icon: the tab draws its mark when the panel has no `icon`. */
|
|
48
|
+
ownerIcon?: PanelIcon;
|
|
45
49
|
/** The tab icon. */
|
|
46
50
|
icon?: PanelIcon;
|
|
47
51
|
/** Where its side tab shows: with a session, on a folder alone, or both. */
|
|
@@ -6,9 +6,11 @@ import { PanelContentEntry, PanelGroupView, PanelSplitView, PanelViewNode, TabAt
|
|
|
6
6
|
import { DEFAULT_WORKSPACE_LABELS, WorkspaceLabels } from "./labels.js";
|
|
7
7
|
import { WorkspaceOps, WorkspaceOpsOptions, WorkspaceOpsView, createWorkspaceOps } from "./ops.js";
|
|
8
8
|
import { CHAT_MIN, CHAT_MIN_SHARE, LayoutResolved, LayoutWants, OVERLAY_CHAT_PEEK, chatFloor, maxColumnWidth, panelDragResult, resolveLayout, splitPanelWidth } from "./resolve.js";
|
|
9
|
+
import { PanelTabMarkSource, panelTabMark } from "./tab-mark.js";
|
|
9
10
|
import { EMPTY_CONTENT_ENTRY, PanelContentCache, PanelContents, bindingInFolder, bindingKey, createPanelContents } from "./contents.js";
|
|
11
|
+
import { PANEL_PAGED_ITEMS, appendPanelPage } from "./pages.js";
|
|
10
12
|
import { EMPTY_LAYOUT, LAYOUT_STORAGE_KEY, LayoutMemory, LayoutMemoryOptions, LayoutPatch, LayoutScope, SessionLayout, createLayoutMemory, layoutProjectKey, layoutScopeKey, parseLayout } from "./layout-memory.js";
|
|
11
13
|
import { OpenTarget, OpenTargetApi, OpenTargetDeps, OpenTargetEvent, createOpenTarget } from "./open-target.js";
|
|
12
14
|
import { setPendingReveal, takePendingReveal } from "./reveal-at.js";
|
|
13
15
|
import { PanelFocusEntry, PanelFocusStore, createPanelFocusStore } from "./panel-focus.js";
|
|
14
|
-
export { CHAT_MIN, CHAT_MIN_SHARE, DEFAULT_WORKSPACE_LABELS, type DropZone, EMPTY_CONTENT_ENTRY, EMPTY_LAYOUT, EMPTY_WORKSPACE_LAYOUT, LAYOUT_STORAGE_KEY, LayoutMemory, LayoutMemoryOptions, LayoutPatch, LayoutResolved, LayoutScope, LayoutStorage, LayoutStoreOptions, LayoutWants, MemoryLayouts, OVERLAY_CHAT_PEEK, OpenTarget, OpenTargetApi, OpenTargetDeps, OpenTargetEvent, type PanelContent, PanelContentCache, PanelContentEntry, PanelContents, PanelFocusEntry, PanelFocusStore, type PanelGroup, PanelGroupView, type PanelLoadContextInput, type PanelNode, type PanelSplit, PanelSplitView, PanelTree, PanelViewNode, SessionLayout, type SplitDir, type SplitSide, StorageLayoutsOptions, TabAttention, TabDrop, WORKSPACE_STORAGE_KEY, WorkspaceHost, WorkspaceHostError, WorkspaceLabels, WorkspaceLayout, WorkspaceLayouts, WorkspaceOps, WorkspaceOpsOptions, WorkspaceOpsView, WorkspacePanelActionResult, WorkspacePanelChange, WorkspacePanelSummary, WorkspacePanels, WorkspaceScope, WorkspaceTab, activeTabOf, bindingInFolder, bindingKey, chatFloor, closeTab, createLayoutMemory, createMemoryLayouts, createOpenTarget, createPanelContents, createPanelFocusStore, createStorageLayouts, createWorkspaceOps, dropTab, findGroup, focusTab, focusedGroup, groupIdsOf, groupViews, groupsOf, layoutProjectKey, layoutScopeKey, maxColumnWidth, moveTabBy, panelDragResult, panelTreeOf, parseLayout, parsePanelTree, parseTree, parseWorkspaceLayout, pickTab, pinTab, resizeSplit, resolveLayout, sameAttention, sameWorkspaceLayout, setPendingReveal, splitPanelWidth, splitTab, splitView, takePendingReveal, treeTabs, viewOf };
|
|
16
|
+
export { CHAT_MIN, CHAT_MIN_SHARE, DEFAULT_WORKSPACE_LABELS, type DropZone, EMPTY_CONTENT_ENTRY, EMPTY_LAYOUT, EMPTY_WORKSPACE_LAYOUT, LAYOUT_STORAGE_KEY, LayoutMemory, LayoutMemoryOptions, LayoutPatch, LayoutResolved, LayoutScope, LayoutStorage, LayoutStoreOptions, LayoutWants, MemoryLayouts, OVERLAY_CHAT_PEEK, OpenTarget, OpenTargetApi, OpenTargetDeps, OpenTargetEvent, PANEL_PAGED_ITEMS, type PanelContent, PanelContentCache, PanelContentEntry, PanelContents, PanelFocusEntry, PanelFocusStore, type PanelGroup, PanelGroupView, type PanelLoadContextInput, type PanelNode, type PanelSplit, PanelSplitView, PanelTabMarkSource, PanelTree, PanelViewNode, SessionLayout, type SplitDir, type SplitSide, StorageLayoutsOptions, TabAttention, TabDrop, WORKSPACE_STORAGE_KEY, WorkspaceHost, WorkspaceHostError, WorkspaceLabels, WorkspaceLayout, WorkspaceLayouts, WorkspaceOps, WorkspaceOpsOptions, WorkspaceOpsView, WorkspacePanelActionResult, WorkspacePanelChange, WorkspacePanelSummary, WorkspacePanels, WorkspaceScope, WorkspaceTab, activeTabOf, appendPanelPage, bindingInFolder, bindingKey, chatFloor, closeTab, createLayoutMemory, createMemoryLayouts, createOpenTarget, createPanelContents, createPanelFocusStore, createStorageLayouts, createWorkspaceOps, dropTab, findGroup, focusTab, focusedGroup, groupIdsOf, groupViews, groupsOf, layoutProjectKey, layoutScopeKey, maxColumnWidth, moveTabBy, panelDragResult, panelTabMark, panelTreeOf, parseLayout, parsePanelTree, parseTree, parseWorkspaceLayout, pickTab, pinTab, resizeSplit, resolveLayout, sameAttention, sameWorkspaceLayout, setPendingReveal, splitPanelWidth, splitTab, splitView, takePendingReveal, treeTabs, viewOf };
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { EMPTY_CONTENT_ENTRY, bindingInFolder, bindingKey, createPanelContents } from "./contents.js";
|
|
2
1
|
import { findGroup, groupsOf, parseTree, treeTabs } from "./tree.js";
|
|
3
2
|
import { activeTabOf, closeTab, dropTab, focusTab, focusedGroup, moveTabBy, panelTreeOf, parsePanelTree, pickTab, pinTab, resizeSplit, splitTab } from "./panel-tree.js";
|
|
4
3
|
import { EMPTY_WORKSPACE_LAYOUT, WORKSPACE_STORAGE_KEY, createMemoryLayouts, createStorageLayouts, parseWorkspaceLayout, sameWorkspaceLayout } from "./layouts.js";
|
|
4
|
+
import { EMPTY_CONTENT_ENTRY, bindingInFolder, bindingKey, createPanelContents } from "./contents.js";
|
|
5
5
|
import { groupIdsOf, groupViews, sameAttention, splitView, viewOf } from "./view.js";
|
|
6
6
|
import { createWorkspaceOps } from "./ops.js";
|
|
7
7
|
import { DEFAULT_WORKSPACE_LABELS } from "./labels.js";
|
|
8
|
+
import { panelTabMark } from "./tab-mark.js";
|
|
9
|
+
import { PANEL_PAGED_ITEMS, appendPanelPage } from "./pages.js";
|
|
8
10
|
import { CHAT_MIN, CHAT_MIN_SHARE, OVERLAY_CHAT_PEEK, chatFloor, maxColumnWidth, panelDragResult, resolveLayout, splitPanelWidth } from "./resolve.js";
|
|
9
11
|
import { EMPTY_LAYOUT, LAYOUT_STORAGE_KEY, createLayoutMemory, layoutProjectKey, layoutScopeKey, parseLayout } from "./layout-memory.js";
|
|
10
12
|
import { setPendingReveal, takePendingReveal } from "./reveal-at.js";
|
|
11
13
|
import { createOpenTarget } from "./open-target.js";
|
|
12
14
|
import { createPanelFocusStore } from "./panel-focus.js";
|
|
13
|
-
export { CHAT_MIN, CHAT_MIN_SHARE, DEFAULT_WORKSPACE_LABELS, EMPTY_CONTENT_ENTRY, EMPTY_LAYOUT, EMPTY_WORKSPACE_LAYOUT, LAYOUT_STORAGE_KEY, OVERLAY_CHAT_PEEK, WORKSPACE_STORAGE_KEY, activeTabOf, bindingInFolder, bindingKey, chatFloor, closeTab, createLayoutMemory, createMemoryLayouts, createOpenTarget, createPanelContents, createPanelFocusStore, createStorageLayouts, createWorkspaceOps, dropTab, findGroup, focusTab, focusedGroup, groupIdsOf, groupViews, groupsOf, layoutProjectKey, layoutScopeKey, maxColumnWidth, moveTabBy, panelDragResult, panelTreeOf, parseLayout, parsePanelTree, parseTree, parseWorkspaceLayout, pickTab, pinTab, resizeSplit, resolveLayout, sameAttention, sameWorkspaceLayout, setPendingReveal, splitPanelWidth, splitTab, splitView, takePendingReveal, treeTabs, viewOf };
|
|
15
|
+
export { CHAT_MIN, CHAT_MIN_SHARE, DEFAULT_WORKSPACE_LABELS, EMPTY_CONTENT_ENTRY, EMPTY_LAYOUT, EMPTY_WORKSPACE_LAYOUT, LAYOUT_STORAGE_KEY, OVERLAY_CHAT_PEEK, PANEL_PAGED_ITEMS, WORKSPACE_STORAGE_KEY, activeTabOf, appendPanelPage, bindingInFolder, bindingKey, chatFloor, closeTab, createLayoutMemory, createMemoryLayouts, createOpenTarget, createPanelContents, createPanelFocusStore, createStorageLayouts, createWorkspaceOps, dropTab, findGroup, focusTab, focusedGroup, groupIdsOf, groupViews, groupsOf, layoutProjectKey, layoutScopeKey, maxColumnWidth, moveTabBy, panelDragResult, panelTabMark, panelTreeOf, parseLayout, parsePanelTree, parseTree, parseWorkspaceLayout, pickTab, pinTab, resizeSplit, resolveLayout, sameAttention, sameWorkspaceLayout, setPendingReveal, splitPanelWidth, splitTab, splitView, takePendingReveal, treeTabs, viewOf };
|
|
@@ -31,6 +31,16 @@ declare const DEFAULT_WORKSPACE_LABELS: {
|
|
|
31
31
|
panelRowExpand: string;
|
|
32
32
|
panelRowCollapse: string;
|
|
33
33
|
panelRowShowMore: string;
|
|
34
|
+
panelSearch: string;
|
|
35
|
+
panelSearchClear: string;
|
|
36
|
+
panelFiltersClear: string;
|
|
37
|
+
/** In a filter's menu: drop its picks. */
|
|
38
|
+
panelFilterClear: string;
|
|
39
|
+
/** A filter's button: its label, and what is picked (none: its label alone). */
|
|
40
|
+
panelFilterSummary: (label: string, picked: readonly string[]) => string;
|
|
41
|
+
panelLoadMore: string;
|
|
42
|
+
panelLoadingMore: string;
|
|
43
|
+
panelRowActions: (row: string) => string;
|
|
34
44
|
};
|
|
35
45
|
/** The shape of the workspace label dictionary. Some values are functions that build a string. */
|
|
36
46
|
type WorkspaceLabels = typeof DEFAULT_WORKSPACE_LABELS;
|
|
@@ -37,7 +37,17 @@ const DEFAULT_WORKSPACE_LABELS = {
|
|
|
37
37
|
},
|
|
38
38
|
panelRowExpand: "Expand",
|
|
39
39
|
panelRowCollapse: "Collapse",
|
|
40
|
-
panelRowShowMore: "Show more"
|
|
40
|
+
panelRowShowMore: "Show more",
|
|
41
|
+
panelSearch: "Search",
|
|
42
|
+
panelSearchClear: "Clear search",
|
|
43
|
+
panelFiltersClear: "Clear filters",
|
|
44
|
+
/** In a filter's menu: drop its picks. */
|
|
45
|
+
panelFilterClear: "Clear",
|
|
46
|
+
/** A filter's button: its label, and what is picked (none: its label alone). */
|
|
47
|
+
panelFilterSummary: (label, picked) => picked.length === 0 ? label : picked.length === 1 ? `${label}: ${picked[0]}` : `${label}: ${picked.length}`,
|
|
48
|
+
panelLoadMore: "Show more",
|
|
49
|
+
panelLoadingMore: "Loading…",
|
|
50
|
+
panelRowActions: (row) => `Actions for ${row}`
|
|
41
51
|
};
|
|
42
52
|
//#endregion
|
|
43
53
|
export { DEFAULT_WORKSPACE_LABELS };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PanelContent } from "zidane/chat/pure";
|
|
2
|
+
//#region src/workspace/headless/pages.d.ts
|
|
3
|
+
/** Rows kept across every page of one panel, at most: past it, Show more goes away. */
|
|
4
|
+
declare const PANEL_PAGED_ITEMS = 1000;
|
|
5
|
+
/**
|
|
6
|
+
* `base` with `page` after it: its rows join the sections of the same id (a row already shown, by id, is not
|
|
7
|
+
* repeated), its other sections follow, and its `more` replaces `base`'s. The header (title, controls, search)
|
|
8
|
+
* stays `base`'s. Past {@link PANEL_PAGED_ITEMS} rows, the rest is dropped and there is no more.
|
|
9
|
+
*
|
|
10
|
+
* @param base - The content shown.
|
|
11
|
+
* @param page - The next page.
|
|
12
|
+
*/
|
|
13
|
+
declare function appendPanelPage(base: PanelContent, page: PanelContent): PanelContent;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { PANEL_PAGED_ITEMS, appendPanelPage };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//#region src/workspace/headless/pages.ts
|
|
2
|
+
/** Rows kept across every page of one panel, at most: past it, Show more goes away. */
|
|
3
|
+
const PANEL_PAGED_ITEMS = 1e3;
|
|
4
|
+
const keyOf = (item) => item.kind === "row" && item.id ? item.id : null;
|
|
5
|
+
/**
|
|
6
|
+
* `base` with `page` after it: its rows join the sections of the same id (a row already shown, by id, is not
|
|
7
|
+
* repeated), its other sections follow, and its `more` replaces `base`'s. The header (title, controls, search)
|
|
8
|
+
* stays `base`'s. Past {@link PANEL_PAGED_ITEMS} rows, the rest is dropped and there is no more.
|
|
9
|
+
*
|
|
10
|
+
* @param base - The content shown.
|
|
11
|
+
* @param page - The next page.
|
|
12
|
+
*/
|
|
13
|
+
function appendPanelPage(base, page) {
|
|
14
|
+
const seen = new Set(base.sections.flatMap((s) => s.items.map(keyOf).filter((k) => k !== null)));
|
|
15
|
+
let budget = PANEL_PAGED_ITEMS - base.sections.reduce((n, s) => n + s.items.length, 0);
|
|
16
|
+
const fresh = (items) => {
|
|
17
|
+
const out = [];
|
|
18
|
+
for (const item of items) {
|
|
19
|
+
const key = keyOf(item);
|
|
20
|
+
if (key !== null && seen.has(key)) continue;
|
|
21
|
+
if (budget <= 0) break;
|
|
22
|
+
if (key !== null) seen.add(key);
|
|
23
|
+
out.push(item);
|
|
24
|
+
budget--;
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
};
|
|
28
|
+
const byId = new Map(page.sections.map((s) => [s.id, s]));
|
|
29
|
+
const sections = base.sections.map((s) => {
|
|
30
|
+
const more = byId.get(s.id);
|
|
31
|
+
return more ? {
|
|
32
|
+
...s,
|
|
33
|
+
items: [...s.items, ...fresh(more.items)]
|
|
34
|
+
} : s;
|
|
35
|
+
});
|
|
36
|
+
const known = new Set(base.sections.map((s) => s.id));
|
|
37
|
+
for (const s of page.sections) if (!known.has(s.id)) sections.push({
|
|
38
|
+
...s,
|
|
39
|
+
items: fresh(s.items)
|
|
40
|
+
});
|
|
41
|
+
const { more: _more, ...rest } = base;
|
|
42
|
+
return {
|
|
43
|
+
...rest,
|
|
44
|
+
sections,
|
|
45
|
+
...page.more && budget > 0 ? { more: page.more } : {}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { PANEL_PAGED_ITEMS, appendPanelPage };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { WorkspaceTab } from "./view.js";
|
|
2
|
+
import { ExtensionMark } from "zidane/chat/pure";
|
|
3
|
+
//#region src/workspace/headless/tab-mark.d.ts
|
|
4
|
+
/** What {@link panelTabMark} reads of a tab. */
|
|
5
|
+
type PanelTabMarkSource = Pick<WorkspaceTab, 'icon' | 'owner' | 'ownerName' | 'ownerIcon'>;
|
|
6
|
+
/**
|
|
7
|
+
* The mark a panel's tab draws: `icon.gui` as an icon, else its extension's mark. `undefined`: a tab with
|
|
8
|
+
* neither (an app's tab without an icon).
|
|
9
|
+
*
|
|
10
|
+
* @param tab - The tab.
|
|
11
|
+
*/
|
|
12
|
+
declare function panelTabMark(tab: PanelTabMarkSource): ExtensionMark | undefined;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { PanelTabMarkSource, panelTabMark };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { extensionMark } from "zidane/chat/pure";
|
|
2
|
+
//#region src/workspace/headless/tab-mark.ts
|
|
3
|
+
/**
|
|
4
|
+
* What a panel's tab draws: its own icon, else the mark of the extension that added it, the one the rest of
|
|
5
|
+
* the app draws for that extension (`extensionMark`: its icon, else its logo, else its first letter).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* The mark a panel's tab draws: `icon.gui` as an icon, else its extension's mark. `undefined`: a tab with
|
|
9
|
+
* neither (an app's tab without an icon).
|
|
10
|
+
*
|
|
11
|
+
* @param tab - The tab.
|
|
12
|
+
*/
|
|
13
|
+
function panelTabMark(tab) {
|
|
14
|
+
const own = tab.icon?.gui?.trim();
|
|
15
|
+
if (own) return {
|
|
16
|
+
kind: "icon",
|
|
17
|
+
gui: own
|
|
18
|
+
};
|
|
19
|
+
if (!tab.owner) return void 0;
|
|
20
|
+
return extensionMark({
|
|
21
|
+
id: tab.owner,
|
|
22
|
+
...tab.ownerName ? { name: tab.ownerName } : {},
|
|
23
|
+
...tab.ownerIcon ? { icon: tab.ownerIcon } : {}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { panelTabMark };
|
|
@@ -12,8 +12,14 @@ interface WorkspaceTab {
|
|
|
12
12
|
id: string;
|
|
13
13
|
/** The pill's label. */
|
|
14
14
|
label: string;
|
|
15
|
-
/** The pill's icon (`gui`: an icon class). */
|
|
15
|
+
/** The pill's icon (`gui`: an icon class). Absent on an extension's panel: its extension's mark ({@link panelTabMark}). */
|
|
16
16
|
icon?: PanelIcon;
|
|
17
|
+
/** The extension that added it (its id): the tab draws the extension's mark when it has no `icon.gui`. */
|
|
18
|
+
owner?: string;
|
|
19
|
+
/** That extension's display name. */
|
|
20
|
+
ownerName?: string;
|
|
21
|
+
/** That extension's own icon. */
|
|
22
|
+
ownerIcon?: PanelIcon;
|
|
17
23
|
/** The app renders it; `false`: an extension panel. */
|
|
18
24
|
builtin: boolean;
|
|
19
25
|
/**
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { WorkspaceActions, WorkspaceApi, WorkspaceContent, WorkspaceContentTarget, WorkspaceHostProvider, WorkspaceHostProviderProps, WorkspaceProvider, WorkspaceProviderProps, WorkspaceRequests, WorkspaceView, useExtensionPanels, useOptionalWorkspaceActions, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceRequests, useWorkspaceView } from "./WorkspaceProvider.js";
|
|
1
|
+
import { WorkspaceActions, WorkspaceApi, WorkspaceContent, WorkspaceContentTarget, WorkspaceHostProvider, WorkspaceHostProviderProps, WorkspaceProvider, WorkspaceProviderProps, WorkspaceRequests, WorkspaceView, useExtensionPanels, useOptionalWorkspaceActions, useOptionalWorkspaceView, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceRequests, useWorkspaceView } from "./WorkspaceProvider.js";
|
|
2
2
|
import { PanelContentView, PanelContentViewProps, PanelOpenEvent, PanelSessionRowProps, PanelSessionRowProvider, PanelSessionRowProviderProps, detailsPreview } from "./PanelContentView.js";
|
|
3
3
|
import { BudgetColumn, LayoutBudget, LayoutBudgetProvider, LayoutBudgetProviderProps, useLayoutBudget, useLayoutBudgetOptional } from "./LayoutBudget.js";
|
|
4
4
|
import { PanelCorner, PanelCornerProps, panelCornerWidth } from "./PanelCorner.js";
|
|
5
|
+
import { PanelGlyph, PanelGlyphProps } from "./PanelGlyph.js";
|
|
5
6
|
import { StripControls } from "./PanelStrip.js";
|
|
6
7
|
import { WorkspaceTabRegistry } from "./TabParking.js";
|
|
7
8
|
import { SidePanel, SidePanelProps } from "./SidePanel.js";
|
|
@@ -11,4 +12,4 @@ import { useScopeLayout } from "./useScopeLayout.js";
|
|
|
11
12
|
import { TAB_REGION_PROPS, TabScope, TabTarget, focusedTabScope, hoveredTabScope, keepFocusIn, panelTabScope, registerTabScope, steppedIndex, tabTarget, trackTabRegions, useTabScope } from "./tab-scopes.js";
|
|
12
13
|
import { usePanelGroupHandlers } from "./panel-group-keys.js";
|
|
13
14
|
import { WorkspaceKeyCommandsOptions, useWorkspaceKeyCommands } from "./workspace-key-commands.js";
|
|
14
|
-
export { BudgetColumn, LayoutBudget, LayoutBudgetProvider, LayoutBudgetProviderProps, PanelContentView, PanelContentViewProps, PanelCorner, PanelCornerProps, PanelOpenEvent, PanelSessionRowProps, PanelSessionRowProvider, PanelSessionRowProviderProps, PanelVisibilityContext, SidePanel, SidePanelProps, type StripControls, TAB_REGION_PROPS, TabScope, TabTarget, WorkspaceActions, WorkspaceApi, WorkspaceContent, WorkspaceContentTarget, WorkspaceHostProvider, WorkspaceHostProviderProps, WorkspaceKeyCommandsOptions, WorkspaceProvider, WorkspaceProviderProps, WorkspaceRequests, type WorkspaceTabRegistry, WorkspaceView, detailsPreview, focusedTabScope, hoveredTabScope, keepFocusIn, panelCornerWidth, panelTabScope, registerTabScope, steppedIndex, tabTarget, touchRecent, trackTabRegions, useExtensionPanels, useLayoutBudget, useLayoutBudgetOptional, useOptionalWorkspaceActions, usePanelGroupHandlers, usePanelVisible, useScopeLayout, useTabScope, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceKeyCommands, useWorkspaceLabels, useWorkspaceRequests, useWorkspaceView };
|
|
15
|
+
export { BudgetColumn, LayoutBudget, LayoutBudgetProvider, LayoutBudgetProviderProps, PanelContentView, PanelContentViewProps, PanelCorner, PanelCornerProps, PanelGlyph, PanelGlyphProps, PanelOpenEvent, PanelSessionRowProps, PanelSessionRowProvider, PanelSessionRowProviderProps, PanelVisibilityContext, SidePanel, SidePanelProps, type StripControls, TAB_REGION_PROPS, TabScope, TabTarget, WorkspaceActions, WorkspaceApi, WorkspaceContent, WorkspaceContentTarget, WorkspaceHostProvider, WorkspaceHostProviderProps, WorkspaceKeyCommandsOptions, WorkspaceProvider, WorkspaceProviderProps, WorkspaceRequests, type WorkspaceTabRegistry, WorkspaceView, detailsPreview, focusedTabScope, hoveredTabScope, keepFocusIn, panelCornerWidth, panelTabScope, registerTabScope, steppedIndex, tabTarget, touchRecent, trackTabRegions, useExtensionPanels, useLayoutBudget, useLayoutBudgetOptional, useOptionalWorkspaceActions, useOptionalWorkspaceView, usePanelGroupHandlers, usePanelVisible, useScopeLayout, useTabScope, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceKeyCommands, useWorkspaceLabels, useWorkspaceRequests, useWorkspaceView };
|
package/dist/workspace/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { useWorkspaceLabels } from "./useWorkspaceLabels.js";
|
|
2
2
|
import { PanelContentView, PanelSessionRowProvider, detailsPreview } from "./PanelContentView.js";
|
|
3
|
-
import { WorkspaceHostProvider, WorkspaceProvider, useExtensionPanels, useOptionalWorkspaceActions, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceRequests, useWorkspaceView } from "./WorkspaceProvider.js";
|
|
3
|
+
import { WorkspaceHostProvider, WorkspaceProvider, useExtensionPanels, useOptionalWorkspaceActions, useOptionalWorkspaceView, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceRequests, useWorkspaceView } from "./WorkspaceProvider.js";
|
|
4
4
|
import { TAB_REGION_PROPS, focusedTabScope, hoveredTabScope, keepFocusIn, panelTabScope, registerTabScope, steppedIndex, tabTarget, trackTabRegions, useTabScope } from "./tab-scopes.js";
|
|
5
5
|
import { PanelVisibilityContext, touchRecent, usePanelVisible } from "./panel-visibility.js";
|
|
6
|
+
import { PanelGlyph } from "./PanelGlyph.js";
|
|
6
7
|
import { LayoutBudgetProvider, useLayoutBudget, useLayoutBudgetOptional } from "./LayoutBudget.js";
|
|
7
8
|
import { PanelCorner, panelCornerWidth } from "./PanelCorner.js";
|
|
8
9
|
import { SidePanel } from "./SidePanel.js";
|
|
9
10
|
import { useScopeLayout } from "./useScopeLayout.js";
|
|
10
11
|
import { usePanelGroupHandlers } from "./panel-group-keys.js";
|
|
11
12
|
import { useWorkspaceKeyCommands } from "./workspace-key-commands.js";
|
|
12
|
-
export { LayoutBudgetProvider, PanelContentView, PanelCorner, PanelSessionRowProvider, PanelVisibilityContext, SidePanel, TAB_REGION_PROPS, WorkspaceHostProvider, WorkspaceProvider, detailsPreview, focusedTabScope, hoveredTabScope, keepFocusIn, panelCornerWidth, panelTabScope, registerTabScope, steppedIndex, tabTarget, touchRecent, trackTabRegions, useExtensionPanels, useLayoutBudget, useLayoutBudgetOptional, useOptionalWorkspaceActions, usePanelGroupHandlers, usePanelVisible, useScopeLayout, useTabScope, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceKeyCommands, useWorkspaceLabels, useWorkspaceRequests, useWorkspaceView };
|
|
13
|
+
export { LayoutBudgetProvider, PanelContentView, PanelCorner, PanelGlyph, PanelSessionRowProvider, PanelVisibilityContext, SidePanel, TAB_REGION_PROPS, WorkspaceHostProvider, WorkspaceProvider, detailsPreview, focusedTabScope, hoveredTabScope, keepFocusIn, panelCornerWidth, panelTabScope, registerTabScope, steppedIndex, tabTarget, touchRecent, trackTabRegions, useExtensionPanels, useLayoutBudget, useLayoutBudgetOptional, useOptionalWorkspaceActions, useOptionalWorkspaceView, usePanelGroupHandlers, usePanelVisible, useScopeLayout, useTabScope, useWorkspace, useWorkspaceActions, useWorkspaceContent, useWorkspaceHost, useWorkspaceKeyCommands, useWorkspaceLabels, useWorkspaceRequests, useWorkspaceView };
|
|
@@ -108,6 +108,12 @@ const DEMO_WORKSPACE_TABS = [
|
|
|
108
108
|
label: "Terminal",
|
|
109
109
|
icon: { gui: "i-ph-terminal-window" },
|
|
110
110
|
builtin: true
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "inbox",
|
|
114
|
+
label: "Inbox",
|
|
115
|
+
icon: { gui: "i-ph-tray" },
|
|
116
|
+
builtin: true
|
|
111
117
|
}
|
|
112
118
|
];
|
|
113
119
|
/** A demo layout: open, Files and Todos in one group, Diffs split off to the right. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useWorkspaceActions, useWorkspaceView } from "./WorkspaceProvider.js";
|
|
2
2
|
import { focusedTabScope, keepFocusIn, panelTabScope, tabTarget, trackTabRegions } from "./tab-scopes.js";
|
|
3
3
|
import { useCallback, useEffect, useMemo } from "react";
|
|
4
|
-
import {
|
|
4
|
+
import { INBOX_PANEL_ID } from "zidane/chat/pure";
|
|
5
5
|
//#region src/workspace/workspace-key-commands.ts
|
|
6
6
|
/**
|
|
7
7
|
* The side panel's key commands: show or hide the panel (`openArtifacts`),
|
|
@@ -69,8 +69,8 @@ function useWorkspaceKeyCommands(options) {
|
|
|
69
69
|
return useMemo(() => ({
|
|
70
70
|
...toggle ? { openArtifacts: () => actions.toggle() } : {},
|
|
71
71
|
...session ? { openTodos: () => {
|
|
72
|
-
if (activeId ===
|
|
73
|
-
else actions.pick(
|
|
72
|
+
if (activeId === INBOX_PANEL_ID) actions.close();
|
|
73
|
+
else actions.pick(INBOX_PANEL_ID);
|
|
74
74
|
} } : {},
|
|
75
75
|
...scope ? {
|
|
76
76
|
panelNext: () => actions.cycle(1),
|