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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zidane-ui",
|
|
3
|
-
"version": "9.1.
|
|
3
|
+
"version": "9.1.6",
|
|
4
4
|
"description": "Zidane design system and chat kit: tokens, surface primitives, theme engine, React components, the chat layer (sessions, transcript, composer) and ChatHost adapters.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -536,7 +536,7 @@
|
|
|
536
536
|
"react": "^19.3.0",
|
|
537
537
|
"react-dom": "^19.3.0",
|
|
538
538
|
"unocss": ">=66.0.0",
|
|
539
|
-
"zidane": "^9.1.
|
|
539
|
+
"zidane": "^9.1.6",
|
|
540
540
|
"vitest": ">=3"
|
|
541
541
|
},
|
|
542
542
|
"peerDependenciesMeta": {
|
package/src/styles/motion.css
CHANGED
|
@@ -611,6 +611,19 @@ html[data-motion='reduced'] :is(.animate-spin, .zg-spin-ring, .zg-sendstop-ring)
|
|
|
611
611
|
animation: zg-sendstop-rotate 800ms linear infinite;
|
|
612
612
|
}
|
|
613
613
|
|
|
614
|
+
/* --- Step status icon (`StepStatusIcon`) ----------------------------------
|
|
615
|
+
* A `.zg-swap` whose layers centre their glyph (the spin ring is a fixed
|
|
616
|
+
* 12px box, the others are 1em glyphs). The layer that lands after a change
|
|
617
|
+
* pops in on `snap`, its opacity on the swap's `fade`; the pop sits on the
|
|
618
|
+
* layer so the ring inside keeps its own rotation. */
|
|
619
|
+
.zg-step-icon-layer {
|
|
620
|
+
display: grid;
|
|
621
|
+
place-items: center;
|
|
622
|
+
}
|
|
623
|
+
.zg-step-icon-layer[data-landed] {
|
|
624
|
+
animation: zg-pop var(--zg-motion-snap) both;
|
|
625
|
+
}
|
|
626
|
+
|
|
614
627
|
@keyframes zg-sendstop-rotate {
|
|
615
628
|
to {
|
|
616
629
|
transform: rotate(360deg);
|
|
@@ -281,7 +281,6 @@ html[data-motion='off'] .zg-onboarding-step {
|
|
|
281
281
|
.zg-demo-fade-y {
|
|
282
282
|
mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
|
|
283
283
|
}
|
|
284
|
-
|
|
285
284
|
/* Two states of one scene in the same cell: the before state, then the
|
|
286
285
|
after state (the rest state). */
|
|
287
286
|
.zg-demo-stack {
|
|
@@ -346,6 +346,16 @@
|
|
|
346
346
|
var(--zg-shadow-well),
|
|
347
347
|
0 0 0 3px color-mix(in oklab, var(--zg-ring) 18%, transparent);
|
|
348
348
|
}
|
|
349
|
+
/* A well whose value is wrong: the danger edge, focused or not. */
|
|
350
|
+
.zg-well[aria-invalid='true'] {
|
|
351
|
+
border-color: color-mix(in oklab, var(--zg-danger) 70%, transparent);
|
|
352
|
+
}
|
|
353
|
+
.zg-well[aria-invalid='true']:focus,
|
|
354
|
+
.zg-well[aria-invalid='true']:focus-within {
|
|
355
|
+
box-shadow:
|
|
356
|
+
var(--zg-shadow-well),
|
|
357
|
+
0 0 0 3px color-mix(in oklab, var(--zg-danger) 18%, transparent);
|
|
358
|
+
}
|
|
349
359
|
/* A file dragged over a well that takes it (focused or not). */
|
|
350
360
|
.zg-well[data-drop] {
|
|
351
361
|
border-color: var(--zg-accent);
|
package/src/styles/workspace.css
CHANGED
|
@@ -63,6 +63,23 @@
|
|
|
63
63
|
padding-right: calc(0.5rem + var(--zg-strip-end-inset));
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/* A panel row's buttons (`PanelRowItem.actions`): shown while the row is hovered or holds focus, or one runs.
|
|
67
|
+
Their place is kept, so the row never shifts. */
|
|
68
|
+
.zg-row-actions {
|
|
69
|
+
opacity: 0;
|
|
70
|
+
transition: opacity var(--zg-motion-hover);
|
|
71
|
+
}
|
|
72
|
+
.group:hover .zg-row-actions,
|
|
73
|
+
.group:focus-within .zg-row-actions,
|
|
74
|
+
.zg-row-actions[data-busy] {
|
|
75
|
+
opacity: 1;
|
|
76
|
+
}
|
|
77
|
+
@media (hover: none) {
|
|
78
|
+
.zg-row-actions {
|
|
79
|
+
opacity: 1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
66
83
|
/* The corner (`PanelCorner`): pop out and full screen fade in left of the toggle while the panel shows. */
|
|
67
84
|
.zg-panel-corner-extra {
|
|
68
85
|
transition: opacity var(--zg-motion-fade);
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { CSSProperties } from "react";
|
|
2
|
-
//#region src/session/TodosPanel.d.ts
|
|
3
|
-
/** Props for {@link TodosPanel}. */
|
|
4
|
-
interface TodosPanelProps {
|
|
5
|
-
/** The session whose list the panel shows. */
|
|
6
|
-
sessionId: string;
|
|
7
|
-
/** Extra classes on the root element. */
|
|
8
|
-
className?: string;
|
|
9
|
-
/** Inline styles on the root element. */
|
|
10
|
-
style?: CSSProperties;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* A session's todo list with its edits, retry, add box, tally and "Clear all".
|
|
14
|
-
*
|
|
15
|
-
* @param props - The {@link TodosPanelProps}.
|
|
16
|
-
*/
|
|
17
|
-
declare function TodosPanel({ sessionId, className, style }: TodosPanelProps): import("react").JSX.Element;
|
|
18
|
-
//#endregion
|
|
19
|
-
export { TodosPanel, TodosPanelProps };
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import { IconButton } from "../components/IconButton.js";
|
|
2
|
-
import { buttonClass } from "../components/button.js";
|
|
3
|
-
import { MetaChip } from "../components/Form.js";
|
|
4
|
-
import { PanelEmpty } from "../components/PanelEmpty.js";
|
|
5
|
-
import { useSessionHost, useSessionTodos } from "./SessionProvider.js";
|
|
6
|
-
import { useSessionLabels } from "./useSessionLabels.js";
|
|
7
|
-
import { TODO_ROW_CLASS, TodoTally, isDoneTodo, todoGlyphTone } from "./TodoList.js";
|
|
8
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
10
|
-
import { TODO_STATUS_GLYPHS, addTodo, buildTodoRetryMessage, clearTodos, cycleTodoStatus, editTodo, removeTodo } from "zidane/chat/pure";
|
|
11
|
-
//#region src/session/TodosPanel.tsx
|
|
12
|
-
/**
|
|
13
|
-
* The Todos panel: a session's live list, editable at parity with the TUI's
|
|
14
|
-
* modal. Shows the live list when non-empty, else the archive (the last
|
|
15
|
-
* list, read-only).
|
|
16
|
-
*
|
|
17
|
-
* Every edit goes through the shared todo transforms (`zidane/chat/pure`)
|
|
18
|
-
* and commits through the host's `todos.set`, which lands on the session the
|
|
19
|
-
* model reads; the panel follows the host's snapshot, so no shadow list
|
|
20
|
-
* lives here. Only "which row is mid-edit" and the add box are local.
|
|
21
|
-
*
|
|
22
|
-
* Gestures: click the glyph to cycle the status, click the text to edit in
|
|
23
|
-
* place (Enter saves, Esc cancels, blur saves), retry asks the agent to redo
|
|
24
|
-
* the row, remove drops it, the box at the bottom adds, "Clear all" empties
|
|
25
|
-
* after an inline confirm. Without `todos.set` the panel is read-only;
|
|
26
|
-
* without `todos.retry` there is no retry.
|
|
27
|
-
*/
|
|
28
|
-
const INPUT_CLS = "zg-well flex-1 min-w-0 font-mono text-zg-label px-2.5 py-1 placeholder:text-[var(--zg-text-subtle)]";
|
|
29
|
-
const GHOST_BTN = buttonClass({
|
|
30
|
-
variant: "ghost",
|
|
31
|
-
size: "xs"
|
|
32
|
-
});
|
|
33
|
-
/**
|
|
34
|
-
* A session's todo list with its edits, retry, add box, tally and "Clear all".
|
|
35
|
-
*
|
|
36
|
-
* @param props - The {@link TodosPanelProps}.
|
|
37
|
-
*/
|
|
38
|
-
function TodosPanel({ sessionId, className, style }) {
|
|
39
|
-
const labels = useSessionLabels();
|
|
40
|
-
const host = useSessionHost().todos;
|
|
41
|
-
const snap = useSessionTodos(sessionId);
|
|
42
|
-
const refresh = host?.refresh;
|
|
43
|
-
const set = host?.set;
|
|
44
|
-
const retryRun = host?.retry;
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
refresh?.(sessionId);
|
|
47
|
-
}, [sessionId, refresh]);
|
|
48
|
-
const list = snap ? snap.todos.length > 0 ? snap.todos : snap.archive : [];
|
|
49
|
-
const isArchive = Boolean(snap && snap.todos.length === 0 && snap.archive.length > 0);
|
|
50
|
-
const total = list.length;
|
|
51
|
-
const done = snap ? snap.tally.completed + snap.tally.cancelled : 0;
|
|
52
|
-
const editable = Boolean(set);
|
|
53
|
-
const [editingId, setEditingId] = useState(null);
|
|
54
|
-
const [draft, setDraft] = useState("");
|
|
55
|
-
const [adding, setAdding] = useState("");
|
|
56
|
-
const [error, setError] = useState(null);
|
|
57
|
-
const [confirmClear, setConfirmClear] = useState(false);
|
|
58
|
-
const editRef = useRef(null);
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
if (editingId) {
|
|
61
|
-
editRef.current?.focus();
|
|
62
|
-
editRef.current?.select();
|
|
63
|
-
}
|
|
64
|
-
}, [editingId]);
|
|
65
|
-
const base = snap?.todos ?? [];
|
|
66
|
-
const saveFailed = labels.todosSaveFailed;
|
|
67
|
-
const commit = useCallback((next) => {
|
|
68
|
-
if (!set) return;
|
|
69
|
-
setError(null);
|
|
70
|
-
set(sessionId, next).then((applied) => {
|
|
71
|
-
if (!applied) setError(saveFailed);
|
|
72
|
-
}, (err) => setError(err instanceof Error ? err.message : String(err)));
|
|
73
|
-
}, [
|
|
74
|
-
sessionId,
|
|
75
|
-
set,
|
|
76
|
-
saveFailed
|
|
77
|
-
]);
|
|
78
|
-
const startEdit = (todo) => {
|
|
79
|
-
if (isArchive || !editable) return;
|
|
80
|
-
setEditingId(todo.id);
|
|
81
|
-
setDraft(todo.content);
|
|
82
|
-
};
|
|
83
|
-
const saveEdit = () => {
|
|
84
|
-
if (!editingId) return;
|
|
85
|
-
const trimmed = draft.trim();
|
|
86
|
-
if (trimmed.length > 0) commit(editTodo(base, editingId, trimmed));
|
|
87
|
-
setEditingId(null);
|
|
88
|
-
};
|
|
89
|
-
const submitAdd = () => {
|
|
90
|
-
const trimmed = adding.trim();
|
|
91
|
-
if (trimmed.length === 0) return;
|
|
92
|
-
commit(addTodo(base, trimmed));
|
|
93
|
-
setAdding("");
|
|
94
|
-
};
|
|
95
|
-
/** Steer the run with the shared retry text: mid-run it steers, idle it starts a run. */
|
|
96
|
-
const retry = (todo) => {
|
|
97
|
-
if (!retryRun) return;
|
|
98
|
-
setError(null);
|
|
99
|
-
retryRun(sessionId, buildTodoRetryMessage(todo)).catch((err) => setError(err.message));
|
|
100
|
-
};
|
|
101
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
102
|
-
className: ["flex-1 min-h-0 flex flex-col", className].filter(Boolean).join(" "),
|
|
103
|
-
style,
|
|
104
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
105
|
-
className: "flex-1 min-h-0 overflow-y-auto",
|
|
106
|
-
children: list.length === 0 ? /* @__PURE__ */ jsx(PanelEmpty, {
|
|
107
|
-
icon: "i-ph-list-checks",
|
|
108
|
-
title: labels.todosEmpty,
|
|
109
|
-
hint: labels.todosEmptyHint
|
|
110
|
-
}) : /* @__PURE__ */ jsxs("div", {
|
|
111
|
-
className: "flex flex-col gap-2 p-3",
|
|
112
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
113
|
-
className: "zg-meta flex items-center gap-1 px-2",
|
|
114
|
-
"data-testid": "todo-progress",
|
|
115
|
-
children: [isArchive && /* @__PURE__ */ jsx("span", {
|
|
116
|
-
className: "mr-1",
|
|
117
|
-
children: labels.todosLastList
|
|
118
|
-
}), /* @__PURE__ */ jsx(MetaChip, { children: labels.todosProgress(done, total) })]
|
|
119
|
-
}), /* @__PURE__ */ jsx("ul", {
|
|
120
|
-
className: "flex flex-col gap-px m-0 p-0 list-none",
|
|
121
|
-
children: list.map((todo) => {
|
|
122
|
-
const dim = isDoneTodo(todo.status);
|
|
123
|
-
const glyphTone = todoGlyphTone(todo.status);
|
|
124
|
-
const rowEditable = editable && !isArchive;
|
|
125
|
-
return /* @__PURE__ */ jsxs("li", {
|
|
126
|
-
"data-status": todo.status,
|
|
127
|
-
className: `group ${TODO_ROW_CLASS} hover:bg-[var(--zg-row-hover)]`,
|
|
128
|
-
children: [
|
|
129
|
-
/* @__PURE__ */ jsx("button", {
|
|
130
|
-
type: "button",
|
|
131
|
-
"aria-label": labels.todoChangeStatus(todo.status),
|
|
132
|
-
title: rowEditable ? labels.todoChangeStatusHint(todo.status) : labels.todoStatus(todo.status),
|
|
133
|
-
disabled: !rowEditable,
|
|
134
|
-
onClick: () => commit(cycleTodoStatus(base, todo.id)),
|
|
135
|
-
className: `text-zg-ui leading-6 w-4 shrink-0 bg-transparent border-0 p-0 cursor-pointer disabled:cursor-default ${glyphTone}`,
|
|
136
|
-
children: TODO_STATUS_GLYPHS[todo.status]
|
|
137
|
-
}),
|
|
138
|
-
editingId === todo.id ? /* @__PURE__ */ jsx("input", {
|
|
139
|
-
ref: editRef,
|
|
140
|
-
type: "text",
|
|
141
|
-
value: draft,
|
|
142
|
-
spellCheck: false,
|
|
143
|
-
"aria-label": labels.todoEdit,
|
|
144
|
-
onChange: (e) => setDraft(e.target.value),
|
|
145
|
-
onBlur: saveEdit,
|
|
146
|
-
onKeyDown: (e) => {
|
|
147
|
-
if (e.key === "Enter") saveEdit();
|
|
148
|
-
if (e.key === "Escape") setEditingId(null);
|
|
149
|
-
},
|
|
150
|
-
className: INPUT_CLS
|
|
151
|
-
}) : /* @__PURE__ */ jsx("button", {
|
|
152
|
-
type: "button",
|
|
153
|
-
disabled: !rowEditable,
|
|
154
|
-
onClick: () => startEdit(todo),
|
|
155
|
-
title: rowEditable ? labels.todoEdit : void 0,
|
|
156
|
-
className: `flex-1 min-w-0 text-left text-zg-ui leading-6 bg-transparent border-0 p-0 cursor-text disabled:cursor-default truncate ${dim ? "text-[var(--zg-text-muted)] line-through" : "text-[var(--zg-text)]"}`,
|
|
157
|
-
children: todo.content
|
|
158
|
-
}),
|
|
159
|
-
rowEditable && /* @__PURE__ */ jsxs(Fragment, { children: [retryRun && /* @__PURE__ */ jsx(IconButton, {
|
|
160
|
-
size: "xs",
|
|
161
|
-
icon: "i-ph-arrow-clockwise",
|
|
162
|
-
label: labels.todoRetry,
|
|
163
|
-
title: labels.todoRetryHint,
|
|
164
|
-
onClick: () => retry(todo),
|
|
165
|
-
className: "opacity-0 group-hover:opacity-100 focus-visible:opacity-100"
|
|
166
|
-
}), /* @__PURE__ */ jsx(IconButton, {
|
|
167
|
-
size: "xs",
|
|
168
|
-
icon: "i-ph-x",
|
|
169
|
-
label: labels.todoRemove,
|
|
170
|
-
title: labels.todoRemoveHint,
|
|
171
|
-
tone: "danger",
|
|
172
|
-
onClick: () => commit(removeTodo(base, todo.id)),
|
|
173
|
-
className: "opacity-0 group-hover:opacity-100 focus-visible:opacity-100"
|
|
174
|
-
})] })
|
|
175
|
-
]
|
|
176
|
-
}, todo.id);
|
|
177
|
-
})
|
|
178
|
-
})]
|
|
179
|
-
})
|
|
180
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
181
|
-
className: "shrink-0 px-3 pt-1 pb-3 flex flex-col gap-2",
|
|
182
|
-
children: [
|
|
183
|
-
error && /* @__PURE__ */ jsx("div", {
|
|
184
|
-
className: "text-zg-meta text-[var(--zg-warn)]",
|
|
185
|
-
role: "alert",
|
|
186
|
-
children: error
|
|
187
|
-
}),
|
|
188
|
-
editable && /* @__PURE__ */ jsxs("div", {
|
|
189
|
-
className: "flex items-center gap-2",
|
|
190
|
-
children: [/* @__PURE__ */ jsx("input", {
|
|
191
|
-
type: "text",
|
|
192
|
-
placeholder: labels.todoAddPlaceholder,
|
|
193
|
-
"aria-label": labels.todoAddLabel,
|
|
194
|
-
value: adding,
|
|
195
|
-
spellCheck: false,
|
|
196
|
-
onChange: (e) => setAdding(e.target.value),
|
|
197
|
-
onKeyDown: (e) => {
|
|
198
|
-
if (e.key === "Enter") submitAdd();
|
|
199
|
-
},
|
|
200
|
-
className: INPUT_CLS
|
|
201
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
202
|
-
type: "button",
|
|
203
|
-
className: GHOST_BTN,
|
|
204
|
-
disabled: adding.trim().length === 0,
|
|
205
|
-
onClick: submitAdd,
|
|
206
|
-
children: labels.todoAdd
|
|
207
|
-
})]
|
|
208
|
-
}),
|
|
209
|
-
/* @__PURE__ */ jsxs("div", {
|
|
210
|
-
className: "flex items-center justify-between gap-3 min-h-6",
|
|
211
|
-
children: [snap && /* @__PURE__ */ jsx(TodoTally, {
|
|
212
|
-
tally: snap.tally,
|
|
213
|
-
className: "ml-2"
|
|
214
|
-
}), !editable ? null : confirmClear ? /* @__PURE__ */ jsxs("span", {
|
|
215
|
-
className: "flex items-center gap-1.5 text-zg-meta",
|
|
216
|
-
children: [
|
|
217
|
-
/* @__PURE__ */ jsx("span", {
|
|
218
|
-
className: "text-[var(--zg-text-muted)]",
|
|
219
|
-
children: labels.todosClearConfirm(base.length)
|
|
220
|
-
}),
|
|
221
|
-
/* @__PURE__ */ jsx("button", {
|
|
222
|
-
type: "button",
|
|
223
|
-
className: `${GHOST_BTN} text-[var(--zg-error)]`,
|
|
224
|
-
onClick: () => {
|
|
225
|
-
commit(clearTodos());
|
|
226
|
-
setConfirmClear(false);
|
|
227
|
-
},
|
|
228
|
-
children: labels.todosClearYes
|
|
229
|
-
}),
|
|
230
|
-
/* @__PURE__ */ jsx("button", {
|
|
231
|
-
type: "button",
|
|
232
|
-
className: GHOST_BTN,
|
|
233
|
-
onClick: () => setConfirmClear(false),
|
|
234
|
-
children: labels.todosClearCancel
|
|
235
|
-
})
|
|
236
|
-
]
|
|
237
|
-
}) : /* @__PURE__ */ jsx("button", {
|
|
238
|
-
type: "button",
|
|
239
|
-
className: GHOST_BTN,
|
|
240
|
-
disabled: base.length === 0,
|
|
241
|
-
onClick: () => setConfirmClear(true),
|
|
242
|
-
title: labels.todosClearHint,
|
|
243
|
-
children: labels.todosClear
|
|
244
|
-
})]
|
|
245
|
-
})
|
|
246
|
-
]
|
|
247
|
-
})]
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
//#endregion
|
|
251
|
-
export { TodosPanel };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Readable } from "../../chat/headless/store.js";
|
|
2
|
-
import { TodosSnapshot } from "./host.js";
|
|
3
|
-
//#region src/session/headless/todos.d.ts
|
|
4
|
-
/** The todo snapshots of every session a host has seen. */
|
|
5
|
-
interface TodosState {
|
|
6
|
-
/** The session's snapshot store (`null` until known). */
|
|
7
|
-
snapshot(sessionId: string): Readable<TodosSnapshot | null>;
|
|
8
|
-
/** Reads the session from the backend: one request per session at a time, never rejects. */
|
|
9
|
-
refresh(sessionId: string): Promise<void>;
|
|
10
|
-
/** A snapshot the backend pushed. */
|
|
11
|
-
push(sessionId: string, snapshot: TodosSnapshot): void;
|
|
12
|
-
/** Forgets a deleted session. */
|
|
13
|
-
forget(sessionId: string): void;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Creates a {@link TodosState}.
|
|
17
|
-
*
|
|
18
|
-
* @param read - Reads one session's snapshot from the backend (`null`: no list yet).
|
|
19
|
-
*/
|
|
20
|
-
declare function createTodosState(read: (sessionId: string) => Promise<TodosSnapshot | null>): TodosState;
|
|
21
|
-
//#endregion
|
|
22
|
-
export { TodosState, createTodosState };
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { createKeyedState } from "./keyed.js";
|
|
2
|
-
//#region src/session/headless/todos.ts
|
|
3
|
-
/**
|
|
4
|
-
* Creates a {@link TodosState}.
|
|
5
|
-
*
|
|
6
|
-
* @param read - Reads one session's snapshot from the backend (`null`: no list yet).
|
|
7
|
-
*/
|
|
8
|
-
function createTodosState(read) {
|
|
9
|
-
const state = createKeyedState(null);
|
|
10
|
-
const pushes = /* @__PURE__ */ new Map();
|
|
11
|
-
const inflight = /* @__PURE__ */ new Map();
|
|
12
|
-
return {
|
|
13
|
-
snapshot: (sessionId) => state.readable(sessionId),
|
|
14
|
-
refresh(sessionId) {
|
|
15
|
-
const running = inflight.get(sessionId);
|
|
16
|
-
if (running) return running;
|
|
17
|
-
const seenPushes = pushes.get(sessionId) ?? 0;
|
|
18
|
-
const p = read(sessionId).then((snap) => {
|
|
19
|
-
if (!snap || (pushes.get(sessionId) ?? 0) !== seenPushes) return;
|
|
20
|
-
state.set(sessionId, snap);
|
|
21
|
-
}).catch(() => void 0).finally(() => {
|
|
22
|
-
inflight.delete(sessionId);
|
|
23
|
-
});
|
|
24
|
-
inflight.set(sessionId, p);
|
|
25
|
-
return p;
|
|
26
|
-
},
|
|
27
|
-
push(sessionId, snapshot) {
|
|
28
|
-
pushes.set(sessionId, (pushes.get(sessionId) ?? 0) + 1);
|
|
29
|
-
state.set(sessionId, snapshot);
|
|
30
|
-
},
|
|
31
|
-
forget(sessionId) {
|
|
32
|
-
pushes.delete(sessionId);
|
|
33
|
-
state.delete(sessionId);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
|
-
export { createTodosState };
|