@achasoft/dsh-advanced-sidebar 0.1.0
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/LICENSE +21 -0
- package/README.md +205 -0
- package/cordis.patch.yml +158 -0
- package/lib/client.js +24890 -0
- package/lib/client.js.map +1 -0
- package/lib/host.js +3156 -0
- package/lib/index.js +20 -0
- package/lib/remote.js +1994 -0
- package/lib/typert.host.js +2000 -0
- package/package.json +136 -0
- package/types/client/ActionMenu.d.ts +36 -0
- package/types/client/Glyphs.d.ts +49 -0
- package/types/client/PanelHost.d.ts +24 -0
- package/types/client/Seats.d.ts +16 -0
- package/types/client/SettingsCard.d.ts +22 -0
- package/types/client/contract.d.ts +358 -0
- package/types/client/controller.d.ts +224 -0
- package/types/client/cx.d.ts +16 -0
- package/types/client/index.d.ts +39 -0
- package/types/client/locales.d.ts +474 -0
- package/types/client/panels/ChangesPanel.d.ts +22 -0
- package/types/client/panels/FilesPanel.d.ts +16 -0
- package/types/client/panels/PreviewPanel.d.ts +27 -0
- package/types/client/panels/TasksPanel.d.ts +28 -0
- package/types/client/panels/TerminalPanel.d.ts +40 -0
- package/types/client/panels/shared.d.ts +65 -0
- package/types/client/target.d.ts +23 -0
- package/types/client/terminal-screen.d.ts +95 -0
- package/types/client/ui/Alert.d.ts +30 -0
- package/types/client/ui/Badge.d.ts +24 -0
- package/types/client/ui/Button.d.ts +28 -0
- package/types/client/ui/Calendar.d.ts +65 -0
- package/types/client/ui/DatePicker.d.ts +41 -0
- package/types/client/ui/Dialog.d.ts +61 -0
- package/types/client/ui/DropdownMenu.d.ts +98 -0
- package/types/client/ui/Input.d.ts +25 -0
- package/types/client/ui/Layer.d.ts +56 -0
- package/types/client/ui/Select.d.ts +49 -0
- package/types/client/ui/Separator.d.ts +15 -0
- package/types/client/ui/Tabs.d.ts +49 -0
- package/types/client/ui/Toggle.d.ts +57 -0
- package/types/client/ui/Tooltip.d.ts +22 -0
- package/types/client/ui/anchor.d.ts +92 -0
- package/types/client/ui/index.d.ts +42 -0
- package/types/client/use-capability.d.ts +27 -0
- package/types/host/deletion.d.ts +57 -0
- package/types/host/files.d.ts +43 -0
- package/types/host/git.d.ts +198 -0
- package/types/host/index.d.ts +210 -0
- package/types/host/open-in.d.ts +93 -0
- package/types/host/paths.d.ts +55 -0
- package/types/host/porcelain.d.ts +51 -0
- package/types/host/preview.d.ts +185 -0
- package/types/host/run.d.ts +72 -0
- package/types/host/tasks.d.ts +80 -0
- package/types/host/terminals.d.ts +86 -0
- package/types/host/types.d.ts +877 -0
- package/types/index.d.ts +17 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolving what the menu acts on.
|
|
3
|
+
*
|
|
4
|
+
* Both menu seats answer the same question — which session, and which directory — from different
|
|
5
|
+
* starting points: the sidebar foot is root-scoped and must find the current session itself, while
|
|
6
|
+
* the session header is handed one. The resolution rule is shared so the two seats can never
|
|
7
|
+
* disagree about the target of an identical menu.
|
|
8
|
+
* @module @achasoft/dsh-advanced-sidebar/client/target
|
|
9
|
+
*/
|
|
10
|
+
import type { SessionListState, WorkspaceListState } from '@deepseek-ai/dsh-client-runtime/client';
|
|
11
|
+
import type { OperationTarget } from './controller.ts';
|
|
12
|
+
/**
|
|
13
|
+
* Build the operation target for one session.
|
|
14
|
+
*
|
|
15
|
+
* The directory is the session's own cwd first, and its Workspace's path only as a fallback: a
|
|
16
|
+
* session started inside a subdirectory works there, and reading git or opening a terminal at the
|
|
17
|
+
* Workspace root would silently act on a different tree than the model does.
|
|
18
|
+
* @param sessions - the session list snapshot.
|
|
19
|
+
* @param workspaces - the workspace list snapshot.
|
|
20
|
+
* @param sessionId - the session to describe; absent yields no target.
|
|
21
|
+
* @returns the target, or undefined when no session is selected or the id is not listed.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveTarget(sessions: SessionListState, workspaces: WorkspaceListState, sessionId: string | undefined): OperationTarget | undefined;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A one-line-at-a-time terminal screen: enough of the control vocabulary that a shell prompt, an
|
|
3
|
+
* interactive line edit, and a progress line all read correctly.
|
|
4
|
+
*
|
|
5
|
+
* This is deliberately not a full terminal emulator — there is no scroll region, no alternate
|
|
6
|
+
* screen, and no vertical cursor addressing, so a full-screen editor run in the panel will not
|
|
7
|
+
* render. What IS modelled is everything that decides what the current line SAYS, because an
|
|
8
|
+
* interactive shell redraws its prompt constantly and a screen that drops those sequences turns
|
|
9
|
+
* every keystroke into overwritten gibberish:
|
|
10
|
+
*
|
|
11
|
+
* - CR / BS move within the line.
|
|
12
|
+
* - `CUF` / `CUB` / `CHA` / `HPA` move the column, which is how `zle` and `readline` reposition
|
|
13
|
+
* themselves after re-emitting a prompt.
|
|
14
|
+
* - `EL` erases part of the line, `ECH` blanks characters in place, and `DCH` / `ICH` delete and
|
|
15
|
+
* insert them — the four a shell uses to edit text you already typed.
|
|
16
|
+
* - `ED` with parameter 2 clears the screen, which is what `clear` sends.
|
|
17
|
+
*
|
|
18
|
+
* Colour, mode switches, bracketed paste, and window titles are discarded: they change presentation,
|
|
19
|
+
* not text. Vertical movement is discarded too, and that is the honest boundary of this model.
|
|
20
|
+
*
|
|
21
|
+
* Feeding is incremental: the panel writes each polled delta, so cost is proportional to new output
|
|
22
|
+
* rather than to the whole retained scrollback.
|
|
23
|
+
* @module @achasoft/dsh-advanced-sidebar/client/terminal-screen
|
|
24
|
+
*/
|
|
25
|
+
/** A mutable text screen fed by {@link TerminalScreen.write}. */
|
|
26
|
+
export declare class TerminalScreen {
|
|
27
|
+
private readonly maxLines;
|
|
28
|
+
private lines;
|
|
29
|
+
private column;
|
|
30
|
+
/** Bumped on every mutation so React can re-render from a primitive rather than an array identity. */
|
|
31
|
+
private generation;
|
|
32
|
+
/**
|
|
33
|
+
* @param maxLines - how many lines to retain; the head is dropped past it.
|
|
34
|
+
*/
|
|
35
|
+
constructor(maxLines: number);
|
|
36
|
+
/**
|
|
37
|
+
* The current screen.
|
|
38
|
+
* @returns the retained lines, oldest first.
|
|
39
|
+
*/
|
|
40
|
+
snapshot(): readonly string[];
|
|
41
|
+
/**
|
|
42
|
+
* A value that changes whenever the screen does.
|
|
43
|
+
* @returns the mutation counter.
|
|
44
|
+
*/
|
|
45
|
+
revision(): number;
|
|
46
|
+
/** Discard everything and start from one empty line. */
|
|
47
|
+
clear(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Feed one chunk of terminal output.
|
|
50
|
+
* @param text - the delta, exactly as the terminal produced it.
|
|
51
|
+
*/
|
|
52
|
+
write(text: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Consume one escape sequence, applying the ones that change the text or the column.
|
|
55
|
+
* @param text - the chunk being written.
|
|
56
|
+
* @param start - index of the ESC byte.
|
|
57
|
+
* @returns the index just past the sequence.
|
|
58
|
+
*/
|
|
59
|
+
private escape;
|
|
60
|
+
/**
|
|
61
|
+
* Apply one CSI sequence.
|
|
62
|
+
* @param final - the sequence's final byte.
|
|
63
|
+
* @param parameters - the parameter bytes before it.
|
|
64
|
+
*/
|
|
65
|
+
private csi;
|
|
66
|
+
/** The line the cursor sits on, padded out to the cursor when it sits past the end. */
|
|
67
|
+
private padded;
|
|
68
|
+
/**
|
|
69
|
+
* Apply the erase-in-line sequence.
|
|
70
|
+
* @param mode - 0 erases to the end, 1 to the cursor, 2 the whole line.
|
|
71
|
+
*/
|
|
72
|
+
private eraseInLine;
|
|
73
|
+
/**
|
|
74
|
+
* Blank characters in place, leaving the cursor where it was.
|
|
75
|
+
* @param count - how many characters to blank.
|
|
76
|
+
*/
|
|
77
|
+
private eraseCharacters;
|
|
78
|
+
/**
|
|
79
|
+
* Delete characters at the cursor, shifting the rest of the line left.
|
|
80
|
+
* @param count - how many characters to delete.
|
|
81
|
+
*/
|
|
82
|
+
private deleteCharacters;
|
|
83
|
+
/**
|
|
84
|
+
* Insert blanks at the cursor, shifting the rest of the line right.
|
|
85
|
+
* @param count - how many blanks to insert.
|
|
86
|
+
*/
|
|
87
|
+
private insertBlanks;
|
|
88
|
+
/** Start a new line, dropping the head once the retention bound is reached. */
|
|
89
|
+
private newline;
|
|
90
|
+
/**
|
|
91
|
+
* Write printable text at the cursor, overwriting what it covers.
|
|
92
|
+
* @param text - printable characters only.
|
|
93
|
+
*/
|
|
94
|
+
private put;
|
|
95
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's alert: an inline message with a tone, used for every panel-level failure and for the
|
|
3
|
+
* one toast this plugin raises.
|
|
4
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Alert
|
|
5
|
+
*/
|
|
6
|
+
import type { ReactNode } from 'react';
|
|
7
|
+
/** Message tone. */
|
|
8
|
+
export type AlertTone = 'default' | 'success' | 'warning' | 'destructive';
|
|
9
|
+
/** Everything an alert renders from. */
|
|
10
|
+
export interface AlertProps {
|
|
11
|
+
/** Tone; defaults to `default`. */
|
|
12
|
+
tone?: AlertTone | undefined;
|
|
13
|
+
/** A heading above the message. */
|
|
14
|
+
title?: string | undefined;
|
|
15
|
+
/** Leading glyph; a destructive or warning alert defaults to the warning triangle. */
|
|
16
|
+
icon?: ReactNode | undefined;
|
|
17
|
+
/** The message. */
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
/** Rendered at the end of the row: a dismiss control, a retry. */
|
|
20
|
+
action?: ReactNode | undefined;
|
|
21
|
+
/** Additional classes. */
|
|
22
|
+
className?: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* An alert.
|
|
26
|
+
* @param props - the tone, the optional heading, the message, and an optional action.
|
|
27
|
+
* @returns the alert element.
|
|
28
|
+
* @see {@link AlertProps}
|
|
29
|
+
*/
|
|
30
|
+
export declare function Alert(props: AlertProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's badge — the tag used for a branch name, a file status letter, a port, or a capability
|
|
3
|
+
* verdict.
|
|
4
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Badge
|
|
5
|
+
*/
|
|
6
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
7
|
+
/** Badge tone. The three state tones carry meaning; the first three are neutral. */
|
|
8
|
+
export type BadgeVariant = 'default' | 'secondary' | 'outline' | 'success' | 'warning' | 'destructive';
|
|
9
|
+
/** Everything a span takes, plus the tone. */
|
|
10
|
+
export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
|
|
11
|
+
/** Tone; defaults to `secondary`. */
|
|
12
|
+
variant?: BadgeVariant | undefined;
|
|
13
|
+
/** Render the text monospaced and allow it to clip, for a path or a command. */
|
|
14
|
+
code?: boolean | undefined;
|
|
15
|
+
/** Rendered before the text. */
|
|
16
|
+
icon?: ReactNode | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A badge.
|
|
20
|
+
* @param props - the tone, the optional monospace form, an optional icon, and span attributes.
|
|
21
|
+
* @returns the badge element.
|
|
22
|
+
* @see {@link BadgeProps}
|
|
23
|
+
*/
|
|
24
|
+
export declare function Badge(props: BadgeProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's button, in shadcn's variant/size vocabulary.
|
|
3
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Button
|
|
4
|
+
*/
|
|
5
|
+
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
6
|
+
/** Visual weight, in shadcn's names. */
|
|
7
|
+
export type ButtonVariant = 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive';
|
|
8
|
+
/** Control height; `icon` is the square form for a glyph with no label. */
|
|
9
|
+
export type ButtonSize = 'sm' | 'md' | 'lg' | 'icon' | 'icon-lg';
|
|
10
|
+
/** Everything a native button takes, plus the two style axes. */
|
|
11
|
+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
12
|
+
/** Visual weight; defaults to `ghost`, the toolbar form used most here. */
|
|
13
|
+
variant?: ButtonVariant | undefined;
|
|
14
|
+
/** Control height; defaults to `md`. */
|
|
15
|
+
size?: ButtonSize | undefined;
|
|
16
|
+
/** Rendered before the label. */
|
|
17
|
+
icon?: ReactNode | undefined;
|
|
18
|
+
/** Marks a toggle button as pressed, which also sets `aria-pressed`. */
|
|
19
|
+
active?: boolean | undefined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A button.
|
|
23
|
+
* @param props - the two style axes, an optional leading icon, and every native button attribute.
|
|
24
|
+
* @param ref - forwarded to the button element, so a caller can anchor a layer to it.
|
|
25
|
+
* @returns the button element.
|
|
26
|
+
* @see {@link ButtonProps}
|
|
27
|
+
*/
|
|
28
|
+
export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's month grid.
|
|
3
|
+
*
|
|
4
|
+
* Dates are handled as local calendar days, never as instants: a task started at 23:30 belongs to
|
|
5
|
+
* the day the operator saw on the clock, and comparing `Date` values directly would put it on the
|
|
6
|
+
* next one for anybody east of UTC. {@link dayKey} is the comparison used everywhere.
|
|
7
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Calendar
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* One local calendar day, as `YYYY-MM-DD`.
|
|
11
|
+
*
|
|
12
|
+
* `toISOString` is deliberately not used: it converts to UTC first, which shifts the day for most
|
|
13
|
+
* of the world.
|
|
14
|
+
* @param date - any instant.
|
|
15
|
+
* @returns the local day it falls on.
|
|
16
|
+
*/
|
|
17
|
+
export declare function dayKey(date: Date): string;
|
|
18
|
+
/**
|
|
19
|
+
* Midnight at the start of one local day.
|
|
20
|
+
* @param date - any instant.
|
|
21
|
+
* @returns a new Date at 00:00 local time on the same day.
|
|
22
|
+
*/
|
|
23
|
+
export declare function startOfDay(date: Date): Date;
|
|
24
|
+
/**
|
|
25
|
+
* The days one month grid shows, including the leading and trailing days of its neighbours.
|
|
26
|
+
* @param month - any instant inside the month.
|
|
27
|
+
* @param weekStart - 0 for Sunday, 1 for Monday.
|
|
28
|
+
* @returns 42 consecutive local days.
|
|
29
|
+
*/
|
|
30
|
+
export declare function monthGrid(month: Date, weekStart: number): Date[];
|
|
31
|
+
/** Everything the grid renders from. */
|
|
32
|
+
export interface CalendarProps {
|
|
33
|
+
/** The selected day; absent selects nothing. */
|
|
34
|
+
value: Date | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* A day was chosen.
|
|
37
|
+
* @param next - midnight at the start of the chosen local day.
|
|
38
|
+
*/
|
|
39
|
+
onValueChange: (next: Date) => void;
|
|
40
|
+
/** Earliest selectable day; earlier days are disabled. */
|
|
41
|
+
min?: Date | undefined;
|
|
42
|
+
/** Latest selectable day; later days are disabled. */
|
|
43
|
+
max?: Date | undefined;
|
|
44
|
+
/** BCP 47 tag for the month and weekday names; absent uses the browser's. */
|
|
45
|
+
locale?: string | undefined;
|
|
46
|
+
/** 0 for Sunday, 1 for Monday; defaults to Monday. */
|
|
47
|
+
weekStart?: number | undefined;
|
|
48
|
+
/** The clear control's text; absent hides it. */
|
|
49
|
+
clearLabel?: string | undefined;
|
|
50
|
+
/** Clear the selection. */
|
|
51
|
+
onClear?: (() => void) | undefined;
|
|
52
|
+
/** The today control's text. */
|
|
53
|
+
todayLabel: string;
|
|
54
|
+
/** Accessible name of the previous-month control. */
|
|
55
|
+
previousLabel: string;
|
|
56
|
+
/** Accessible name of the next-month control. */
|
|
57
|
+
nextLabel: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A month grid.
|
|
61
|
+
* @param props - the selection, the bounds, and the control labels.
|
|
62
|
+
* @returns the calendar element.
|
|
63
|
+
* @see {@link CalendarProps}
|
|
64
|
+
*/
|
|
65
|
+
export declare function Calendar(props: CalendarProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's date picker: a trigger showing the chosen day, and the month grid in a floating layer.
|
|
3
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/DatePicker
|
|
4
|
+
*/
|
|
5
|
+
/** Everything the picker renders from. */
|
|
6
|
+
export interface DatePickerProps {
|
|
7
|
+
/** The chosen day; absent shows the placeholder. */
|
|
8
|
+
value: Date | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* A different day was chosen, or the selection was cleared.
|
|
11
|
+
* @param next - midnight at the start of the chosen local day, or undefined when cleared.
|
|
12
|
+
*/
|
|
13
|
+
onValueChange: (next: Date | undefined) => void;
|
|
14
|
+
/** Shown while nothing is chosen. */
|
|
15
|
+
placeholder: string;
|
|
16
|
+
/** The clear control's text inside the grid. */
|
|
17
|
+
clearLabel: string;
|
|
18
|
+
/** The today control's text inside the grid. */
|
|
19
|
+
todayLabel: string;
|
|
20
|
+
/** Accessible name of the previous-month control. */
|
|
21
|
+
previousLabel: string;
|
|
22
|
+
/** Accessible name of the next-month control. */
|
|
23
|
+
nextLabel: string;
|
|
24
|
+
/** Latest selectable day. */
|
|
25
|
+
max?: Date | undefined;
|
|
26
|
+
/** BCP 47 tag for the month and weekday names. */
|
|
27
|
+
locale?: string | undefined;
|
|
28
|
+
/** Accessible name of the trigger. */
|
|
29
|
+
'aria-label'?: string | undefined;
|
|
30
|
+
/** Refuses the press and dims the trigger. */
|
|
31
|
+
disabled?: boolean | undefined;
|
|
32
|
+
/** Additional classes on the trigger. */
|
|
33
|
+
className?: string | undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A date picker.
|
|
37
|
+
* @param props - the selection, the labels, and the bounds.
|
|
38
|
+
* @returns the trigger and, while open, the month grid.
|
|
39
|
+
* @see {@link DatePickerProps}
|
|
40
|
+
*/
|
|
41
|
+
export declare function DatePicker(props: DatePickerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's modal: a scrimmed, centred card, and the confirmation form of it.
|
|
3
|
+
*
|
|
4
|
+
* Unlike the dock this plugin opens beside the conversation, a dialog IS modal: it takes focus,
|
|
5
|
+
* traps it, and blocks the page behind its scrim. That is the whole difference between asking a
|
|
6
|
+
* question and offering a panel, and it is why Delete uses this and the panels do not.
|
|
7
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Dialog
|
|
8
|
+
*/
|
|
9
|
+
import type { ReactNode } from 'react';
|
|
10
|
+
/** Everything a dialog renders from. */
|
|
11
|
+
export interface DialogProps {
|
|
12
|
+
/** Whether the dialog is showing. */
|
|
13
|
+
open: boolean;
|
|
14
|
+
/** Asked to close, from the scrim, Escape, or a cancel control. */
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
/** The heading. */
|
|
17
|
+
title: string;
|
|
18
|
+
/** The body text; a caller with richer content passes `children` instead. */
|
|
19
|
+
description?: ReactNode | undefined;
|
|
20
|
+
/** Body content below the description. */
|
|
21
|
+
children?: ReactNode | undefined;
|
|
22
|
+
/** The action row. */
|
|
23
|
+
footer?: ReactNode | undefined;
|
|
24
|
+
/** Refuses the scrim and Escape while an action is in flight. */
|
|
25
|
+
busy?: boolean | undefined;
|
|
26
|
+
/** Additional classes on the card. */
|
|
27
|
+
className?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A modal dialog.
|
|
31
|
+
* @param props - the open state, the heading, the body, and the action row.
|
|
32
|
+
* @returns the portal, or null while closed.
|
|
33
|
+
* @see {@link DialogProps}
|
|
34
|
+
*/
|
|
35
|
+
export declare function Dialog(props: DialogProps): import("react").ReactPortal | null;
|
|
36
|
+
/**
|
|
37
|
+
* A confirmation dialog: a question, a cancel, and one action that commits it.
|
|
38
|
+
* @param props.open - whether the dialog is showing.
|
|
39
|
+
* @param props.onClose - dismiss without acting.
|
|
40
|
+
* @param props.onConfirm - commit the action.
|
|
41
|
+
* @param props.title - the question.
|
|
42
|
+
* @param props.description - what committing will do.
|
|
43
|
+
* @param props.confirmLabel - the committing control's text.
|
|
44
|
+
* @param props.cancelLabel - the dismissing control's text.
|
|
45
|
+
* @param props.destructive - draw the committing control as destructive.
|
|
46
|
+
* @param props.busy - the action is in flight; both controls refuse.
|
|
47
|
+
* @param props.children - extra body content between the description and the action row.
|
|
48
|
+
* @returns the dialog.
|
|
49
|
+
*/
|
|
50
|
+
export declare function AlertDialog(props: {
|
|
51
|
+
open: boolean;
|
|
52
|
+
onClose: () => void;
|
|
53
|
+
onConfirm: () => void;
|
|
54
|
+
title: string;
|
|
55
|
+
description?: ReactNode | undefined;
|
|
56
|
+
confirmLabel: string;
|
|
57
|
+
cancelLabel: string;
|
|
58
|
+
destructive?: boolean | undefined;
|
|
59
|
+
busy?: boolean | undefined;
|
|
60
|
+
children?: ReactNode | undefined;
|
|
61
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's dropdown menu, with submenus that stay on screen.
|
|
3
|
+
*
|
|
4
|
+
* The harness's `Menu` primitive pins a submenu at `left: calc(100% + 10px)` with no collision
|
|
5
|
+
* handling, so a menu anchored near the right edge of the window — the session header's, always —
|
|
6
|
+
* pushed its `Open in` submenu off the viewport entirely. Every surface here is placed through
|
|
7
|
+
* {@link placeLayer}, which flips a submenu to the left of its row when the right side cannot hold
|
|
8
|
+
* it and shifts it vertically to stay inside the window.
|
|
9
|
+
*
|
|
10
|
+
* Keyboard handling follows the WAI-ARIA menu pattern: arrows move, Home/End jump, Right opens a
|
|
11
|
+
* submenu, Left closes it, Escape closes the deepest surface, and focus returns to the row that
|
|
12
|
+
* opened it — and to the trigger when the whole menu closes.
|
|
13
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/DropdownMenu
|
|
14
|
+
*/
|
|
15
|
+
import type { ReactNode, RefObject } from 'react';
|
|
16
|
+
import type { Align, Side } from './anchor.ts';
|
|
17
|
+
/** A selectable row. */
|
|
18
|
+
export interface MenuItemNode {
|
|
19
|
+
kind: 'item';
|
|
20
|
+
/** Reported to `onSelect`; unique within the whole tree. */
|
|
21
|
+
id: string;
|
|
22
|
+
/** The row's text. */
|
|
23
|
+
label: ReactNode;
|
|
24
|
+
/** Why the row cannot be used, shown beside the label rather than replacing it. */
|
|
25
|
+
note?: string | undefined;
|
|
26
|
+
/** Leading glyph. */
|
|
27
|
+
icon?: ReactNode | undefined;
|
|
28
|
+
/** Unusable rows stay visible: an absent row cannot be told from a mistyped configuration. */
|
|
29
|
+
disabled?: boolean | undefined;
|
|
30
|
+
/** Destructive rows take the error colour and its hover fill. */
|
|
31
|
+
danger?: boolean | undefined;
|
|
32
|
+
/** Draws a trailing check. */
|
|
33
|
+
checked?: boolean | undefined;
|
|
34
|
+
}
|
|
35
|
+
/** A row that opens a nested surface. */
|
|
36
|
+
export interface MenuSubNode {
|
|
37
|
+
kind: 'sub';
|
|
38
|
+
/** Identifies the row; never reported to `onSelect`, which fires only for leaves. */
|
|
39
|
+
id: string;
|
|
40
|
+
/** The row's text. */
|
|
41
|
+
label: ReactNode;
|
|
42
|
+
/** Leading glyph. */
|
|
43
|
+
icon?: ReactNode | undefined;
|
|
44
|
+
/** A disabled parent cannot be opened. */
|
|
45
|
+
disabled?: boolean | undefined;
|
|
46
|
+
/** The nested rows. */
|
|
47
|
+
items: readonly MenuNode[];
|
|
48
|
+
}
|
|
49
|
+
/** A hairline between groups. */
|
|
50
|
+
export interface MenuSeparatorNode {
|
|
51
|
+
kind: 'separator';
|
|
52
|
+
/** React key. */
|
|
53
|
+
id: string;
|
|
54
|
+
}
|
|
55
|
+
/** A non-interactive heading above a group. */
|
|
56
|
+
export interface MenuLabelNode {
|
|
57
|
+
kind: 'label';
|
|
58
|
+
/** React key. */
|
|
59
|
+
id: string;
|
|
60
|
+
/** The heading. */
|
|
61
|
+
text: string;
|
|
62
|
+
}
|
|
63
|
+
/** One entry of a menu surface. */
|
|
64
|
+
export type MenuNode = MenuItemNode | MenuSubNode | MenuSeparatorNode | MenuLabelNode;
|
|
65
|
+
/** Everything the menu renders from. */
|
|
66
|
+
export interface DropdownMenuProps {
|
|
67
|
+
/** Whether the menu is showing; the caller owns it, because the trigger does the toggling. */
|
|
68
|
+
open: boolean;
|
|
69
|
+
/** Asked to close, from a selection, Escape, or a pointer outside the tree. */
|
|
70
|
+
onClose: () => void;
|
|
71
|
+
/** The trigger the root surface is placed against, and focus returns to. */
|
|
72
|
+
anchorRef: RefObject<HTMLElement | null>;
|
|
73
|
+
/** The rows. */
|
|
74
|
+
items: readonly MenuNode[];
|
|
75
|
+
/**
|
|
76
|
+
* A leaf was chosen.
|
|
77
|
+
* @param id - the leaf's id.
|
|
78
|
+
*/
|
|
79
|
+
onSelect: (id: string) => void;
|
|
80
|
+
/** Preferred edge of the trigger; flipped when the surface does not fit there. */
|
|
81
|
+
side?: Side | undefined;
|
|
82
|
+
/** Preferred alignment along that edge. */
|
|
83
|
+
align?: Align | undefined;
|
|
84
|
+
/** Accessible name of the root surface. */
|
|
85
|
+
label?: string | undefined;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A dropdown menu anchored to a caller-owned trigger.
|
|
89
|
+
*
|
|
90
|
+
* The trigger is rendered by the caller rather than by this component: each seat needs its own
|
|
91
|
+
* geometry and its own accessible name, and a wrapper element around a flex-centred icon button is
|
|
92
|
+
* not laid out where the button is — which is what put the harness menu's list against the wrong
|
|
93
|
+
* edge in the collapsed rail.
|
|
94
|
+
* @param props - the open state, the trigger, the rows, and the selection callback.
|
|
95
|
+
* @returns the menu surface, or null while closed.
|
|
96
|
+
* @see {@link DropdownMenuProps}
|
|
97
|
+
*/
|
|
98
|
+
export declare function DropdownMenu(props: DropdownMenuProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's text controls: a single-line input and a textarea, both in shadcn's bordered form.
|
|
3
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Input
|
|
4
|
+
*/
|
|
5
|
+
import type { InputHTMLAttributes, TextareaHTMLAttributes } from 'react';
|
|
6
|
+
/** Every native input attribute, plus the two shapes this package needs. */
|
|
7
|
+
export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
8
|
+
/** Render the value monospaced, for a path, a command, or a URL. */
|
|
9
|
+
code?: boolean | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A single-line input.
|
|
13
|
+
* @param props - the optional monospace form and every native input attribute.
|
|
14
|
+
* @param ref - forwarded to the input element.
|
|
15
|
+
* @returns the input element.
|
|
16
|
+
* @see {@link InputProps}
|
|
17
|
+
*/
|
|
18
|
+
export declare const Input: import("react").ForwardRefExoticComponent<InputProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
19
|
+
/**
|
|
20
|
+
* A multi-line input.
|
|
21
|
+
* @param props - every native textarea attribute.
|
|
22
|
+
* @param ref - forwarded to the textarea element.
|
|
23
|
+
* @returns the textarea element.
|
|
24
|
+
*/
|
|
25
|
+
export declare const Textarea: import("react").ForwardRefExoticComponent<TextareaHTMLAttributes<HTMLTextAreaElement> & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The portal every floating surface in the kit is drawn in: menus, submenus, select lists, the date
|
|
3
|
+
* picker, and tooltips.
|
|
4
|
+
*
|
|
5
|
+
* Floating surfaces go to `document.body` rather than staying beside their trigger. The dock, the
|
|
6
|
+
* session header, and the settings card all sit inside overflow-clipping containers, and a list
|
|
7
|
+
* rendered in place is cropped by the first of them.
|
|
8
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Layer
|
|
9
|
+
*/
|
|
10
|
+
import type { CSSProperties, MutableRefObject, ReactNode, RefObject } from 'react';
|
|
11
|
+
import { type PlacementRequest } from './anchor.ts';
|
|
12
|
+
/** Everything a floating surface needs to place itself. */
|
|
13
|
+
export interface LayerProps {
|
|
14
|
+
/** Whether the surface is rendered at all. */
|
|
15
|
+
open: boolean;
|
|
16
|
+
/** The element the surface is positioned against. */
|
|
17
|
+
anchorRef: RefObject<HTMLElement | null>;
|
|
18
|
+
/** Overrides of the default placement request. */
|
|
19
|
+
placement?: Partial<PlacementRequest> | undefined;
|
|
20
|
+
/** ARIA role of the surface itself. */
|
|
21
|
+
role?: string | undefined;
|
|
22
|
+
/** Marks every surface of one menu tree, so an outside-click test can recognise its own. */
|
|
23
|
+
treeId?: string | undefined;
|
|
24
|
+
/** Additional classes on the surface. */
|
|
25
|
+
className?: string | undefined;
|
|
26
|
+
/** Additional inline style, merged after the computed position. */
|
|
27
|
+
style?: CSSProperties | undefined;
|
|
28
|
+
/** The surface's contents. */
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
/** Ref to the surface element, for callers that manage focus inside it. */
|
|
31
|
+
contentRef?: MutableRefObject<HTMLDivElement | null> | undefined;
|
|
32
|
+
/** Makes the surface itself focusable, so a menu can take focus without focusing a row. */
|
|
33
|
+
tabIndex?: number | undefined;
|
|
34
|
+
/** Accessible name of the surface. */
|
|
35
|
+
'aria-label'?: string | undefined;
|
|
36
|
+
/** Called with the surface's own key events, before they reach the document. */
|
|
37
|
+
onKeyDown?: ((event: React.KeyboardEvent<HTMLDivElement>) => void) | undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A positioned floating surface.
|
|
41
|
+
* @param props - the open flag, the anchor, the placement, and the contents.
|
|
42
|
+
* @returns the portal, or null while closed.
|
|
43
|
+
* @see {@link LayerProps}
|
|
44
|
+
*/
|
|
45
|
+
export declare function Layer(props: LayerProps): import("react").ReactPortal | null;
|
|
46
|
+
/**
|
|
47
|
+
* Whether one event target sits inside the trigger or any surface of one layer tree.
|
|
48
|
+
*
|
|
49
|
+
* A portal is outside its trigger's DOM subtree, and a submenu is outside its parent list's, so an
|
|
50
|
+
* outside-click test that only walks the trigger would dismiss the menu on its own rows.
|
|
51
|
+
* @param target - the event target.
|
|
52
|
+
* @param treeId - the tree marker every surface of one menu carries.
|
|
53
|
+
* @param anchor - the trigger element.
|
|
54
|
+
* @returns true when the target belongs to the tree.
|
|
55
|
+
*/
|
|
56
|
+
export declare function insideLayerTree(target: EventTarget | null, treeId: string, anchor: Element | null): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's select: a trigger showing the current option and a floating list of the rest.
|
|
3
|
+
*
|
|
4
|
+
* A native `<select>` cannot be drawn in this vocabulary — its popup is the operating system's, and
|
|
5
|
+
* on the platforms this Web Client runs on it ignores every colour the app resolves. The list here
|
|
6
|
+
* is the same {@link Layer} the menu uses, so it flips and clamps like everything else.
|
|
7
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Select
|
|
8
|
+
*/
|
|
9
|
+
import type { ReactNode } from 'react';
|
|
10
|
+
/** One option. */
|
|
11
|
+
export interface SelectOption<T extends string> {
|
|
12
|
+
/** The stored value. */
|
|
13
|
+
value: T;
|
|
14
|
+
/** The rendered text. */
|
|
15
|
+
label: ReactNode;
|
|
16
|
+
/** Shown beside the label, for the reason an option is unusable. */
|
|
17
|
+
note?: string | undefined;
|
|
18
|
+
/** Refuses selection. */
|
|
19
|
+
disabled?: boolean | undefined;
|
|
20
|
+
}
|
|
21
|
+
/** Everything the select renders from. */
|
|
22
|
+
export interface SelectProps<T extends string> {
|
|
23
|
+
/** The selected value; absent shows the placeholder. */
|
|
24
|
+
value: T | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* A different option was chosen.
|
|
27
|
+
* @param next - the chosen value.
|
|
28
|
+
*/
|
|
29
|
+
onValueChange: (next: T) => void;
|
|
30
|
+
/** The options, in the order they are offered. */
|
|
31
|
+
options: readonly SelectOption<T>[];
|
|
32
|
+
/** Shown while nothing is selected. */
|
|
33
|
+
placeholder?: string | undefined;
|
|
34
|
+
/** Refuses the press and dims the trigger. */
|
|
35
|
+
disabled?: boolean | undefined;
|
|
36
|
+
/** Accessible name. */
|
|
37
|
+
'aria-label'?: string | undefined;
|
|
38
|
+
/** The trigger's id, for a `<label for>`. */
|
|
39
|
+
id?: string | undefined;
|
|
40
|
+
/** Additional classes on the trigger. */
|
|
41
|
+
className?: string | undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A select.
|
|
45
|
+
* @param props - the value, the options, and the change callback.
|
|
46
|
+
* @returns the trigger and, while open, its list.
|
|
47
|
+
* @see {@link SelectProps}
|
|
48
|
+
*/
|
|
49
|
+
export declare function Select<T extends string>(props: SelectProps<T>): import("react").JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's separator: a hairline between groups, in either orientation.
|
|
3
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Separator
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* A hairline.
|
|
7
|
+
* @param props.orientation - `horizontal` (default) draws a rule across the flow; `vertical` draws
|
|
8
|
+
* one between two controls in a row.
|
|
9
|
+
* @param props.className - additional classes.
|
|
10
|
+
* @returns the separator element.
|
|
11
|
+
*/
|
|
12
|
+
export declare function Separator({ orientation, className }: {
|
|
13
|
+
orientation?: 'horizontal' | 'vertical' | undefined;
|
|
14
|
+
className?: string | undefined;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kit's tab strip: shadcn's segmented control, with an optional per-tab close.
|
|
3
|
+
*
|
|
4
|
+
* The strip scrolls horizontally rather than wrapping. The panels it heads are full-height, so a
|
|
5
|
+
* second row of tabs would take height from the thing being tabbed.
|
|
6
|
+
* @module @achasoft/dsh-advanced-sidebar/client/ui/Tabs
|
|
7
|
+
*/
|
|
8
|
+
import type { ReactNode } from 'react';
|
|
9
|
+
/** One tab. */
|
|
10
|
+
export interface TabDescriptor {
|
|
11
|
+
/** Identifies the tab; reported to both callbacks. */
|
|
12
|
+
id: string;
|
|
13
|
+
/** The tab's text. */
|
|
14
|
+
label: ReactNode;
|
|
15
|
+
/** Native tooltip, for a label the strip clips. */
|
|
16
|
+
title?: string | undefined;
|
|
17
|
+
/** Leading glyph, for a state marker. */
|
|
18
|
+
icon?: ReactNode | undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Everything the strip renders from. */
|
|
21
|
+
export interface TabsProps {
|
|
22
|
+
/** The tabs, in display order. */
|
|
23
|
+
tabs: readonly TabDescriptor[];
|
|
24
|
+
/** Which tab is showing. */
|
|
25
|
+
value: string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* A different tab was chosen.
|
|
28
|
+
* @param id - the chosen tab.
|
|
29
|
+
*/
|
|
30
|
+
onValueChange: (id: string) => void;
|
|
31
|
+
/**
|
|
32
|
+
* A tab's close control was used; absent leaves the tabs uncloseable.
|
|
33
|
+
* @param id - the tab to close.
|
|
34
|
+
*/
|
|
35
|
+
onClose?: ((id: string) => void) | undefined;
|
|
36
|
+
/** Accessible name of the strip. */
|
|
37
|
+
'aria-label'?: string | undefined;
|
|
38
|
+
/** Rendered after the tabs, inside the strip: the add button, a count, a toolbar. */
|
|
39
|
+
children?: ReactNode | undefined;
|
|
40
|
+
/** Additional classes. */
|
|
41
|
+
className?: string | undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A tab strip.
|
|
45
|
+
* @param props - the tabs, the selection, and the callbacks.
|
|
46
|
+
* @returns the strip.
|
|
47
|
+
* @see {@link TabsProps}
|
|
48
|
+
*/
|
|
49
|
+
export declare function Tabs(props: TabsProps): import("react").JSX.Element;
|