@harborclient/sdk 1.1.13 → 1.1.15
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/components/Badge/index.d.ts +1 -1
- package/dist/components/Badge/index.d.ts.map +1 -1
- package/dist/components/Badge/index.js +2 -0
- package/dist/components/Breadcrumb/CrumbSegment.d.ts +19 -0
- package/dist/components/Breadcrumb/CrumbSegment.d.ts.map +1 -0
- package/dist/components/Breadcrumb/CrumbSegment.js +19 -0
- package/dist/components/Breadcrumb/EditableSegment.d.ts +46 -0
- package/dist/components/Breadcrumb/EditableSegment.d.ts.map +1 -0
- package/dist/components/Breadcrumb/EditableSegment.js +14 -0
- package/dist/components/Breadcrumb/SegmentShell.d.ts +32 -0
- package/dist/components/Breadcrumb/SegmentShell.d.ts.map +1 -0
- package/dist/components/Breadcrumb/SegmentShell.js +35 -0
- package/dist/components/Breadcrumb/index.d.ts +2 -18
- package/dist/components/Breadcrumb/index.d.ts.map +1 -1
- package/dist/components/Breadcrumb/index.js +2 -61
- package/dist/components/Breadcrumb/types.d.ts +18 -0
- package/dist/components/Breadcrumb/types.d.ts.map +1 -0
- package/dist/components/Breadcrumb/types.js +1 -0
- package/dist/components/CatalogCard/index.d.ts +51 -0
- package/dist/components/CatalogCard/index.d.ts.map +1 -0
- package/dist/components/CatalogCard/index.js +23 -0
- package/dist/components/CatalogReadmeMarkdown/index.d.ts +13 -0
- package/dist/components/CatalogReadmeMarkdown/index.d.ts.map +1 -0
- package/dist/components/CatalogReadmeMarkdown/index.js +53 -0
- package/dist/components/FormGroup/index.d.ts +6 -1
- package/dist/components/FormGroup/index.d.ts.map +1 -1
- package/dist/components/FormGroup/index.js +21 -10
- package/dist/components/FormSection/index.d.ts +37 -0
- package/dist/components/FormSection/index.d.ts.map +1 -0
- package/dist/components/FormSection/index.js +9 -0
- package/dist/components/ProgressBar/index.d.ts +20 -0
- package/dist/components/ProgressBar/index.d.ts.map +1 -0
- package/dist/components/ProgressBar/index.js +10 -0
- package/dist/components/ProgressBar/progressBar.logic.d.ts +9 -0
- package/dist/components/ProgressBar/progressBar.logic.d.ts.map +1 -0
- package/dist/components/ProgressBar/progressBar.logic.js +13 -0
- package/dist/components/PromptModal/index.d.ts +82 -0
- package/dist/components/PromptModal/index.d.ts.map +1 -0
- package/dist/components/PromptModal/index.js +22 -0
- package/dist/components/PromptModal/promptModal.logic.d.ts +8 -0
- package/dist/components/PromptModal/promptModal.logic.d.ts.map +1 -0
- package/dist/components/PromptModal/promptModal.logic.js +9 -0
- package/dist/components/ScreenshotCarousel/ScreenshotLightbox.d.ts +29 -0
- package/dist/components/ScreenshotCarousel/ScreenshotLightbox.d.ts.map +1 -0
- package/dist/components/ScreenshotCarousel/ScreenshotLightbox.js +66 -0
- package/dist/components/ScreenshotCarousel/index.d.ts +35 -0
- package/dist/components/ScreenshotCarousel/index.d.ts.map +1 -0
- package/dist/components/ScreenshotCarousel/index.js +89 -0
- package/dist/components/ScreenshotCarousel/variants.d.ts +17 -0
- package/dist/components/ScreenshotCarousel/variants.d.ts.map +1 -0
- package/dist/components/ScreenshotCarousel/variants.js +22 -0
- package/dist/components/SelectionActionToolbar/index.d.ts +41 -0
- package/dist/components/SelectionActionToolbar/index.d.ts.map +1 -0
- package/dist/components/SelectionActionToolbar/index.js +13 -0
- package/dist/components/SettingIdLabel/index.d.ts +16 -0
- package/dist/components/SettingIdLabel/index.d.ts.map +1 -0
- package/dist/components/SettingIdLabel/index.js +7 -0
- package/dist/components/SettingSectionHeading/index.d.ts +33 -0
- package/dist/components/SettingSectionHeading/index.d.ts.map +1 -0
- package/dist/components/SettingSectionHeading/index.js +10 -0
- package/dist/components/SidebarItem/SidebarDocumentItem.d.ts +79 -0
- package/dist/components/SidebarItem/SidebarDocumentItem.d.ts.map +1 -0
- package/dist/components/SidebarItem/SidebarDocumentItem.js +26 -0
- package/dist/components/SidebarItem/SidebarRequestItem.d.ts +0 -76
- package/dist/components/SidebarItem/SidebarRequestItem.d.ts.map +1 -1
- package/dist/components/SidebarItem/SidebarRequestItem.js +0 -21
- package/dist/components/SidebarItem/SidebarTree.d.ts +0 -21
- package/dist/components/SidebarItem/SidebarTree.d.ts.map +1 -1
- package/dist/components/SidebarItem/SidebarTree.js +0 -9
- package/dist/components/SidebarItem/SidebarTreeGroup.d.ts +24 -0
- package/dist/components/SidebarItem/SidebarTreeGroup.d.ts.map +1 -0
- package/dist/components/SidebarItem/SidebarTreeGroup.js +11 -0
- package/dist/components/SidebarItem/index.d.ts +5 -3
- package/dist/components/SidebarItem/index.d.ts.map +1 -1
- package/dist/components/SidebarItem/index.js +5 -3
- package/dist/components/SidebarItem/sidebarItemClasses.d.ts +8 -0
- package/dist/components/SidebarItem/sidebarItemClasses.d.ts.map +1 -1
- package/dist/components/SidebarItem/sidebarItemClasses.js +18 -8
- package/dist/components/SidebarSection/SectionItem.d.ts +40 -0
- package/dist/components/SidebarSection/SectionItem.d.ts.map +1 -0
- package/dist/components/SidebarSection/SectionItem.js +19 -0
- package/dist/components/SidebarSection/SidebarSection.d.ts +2 -38
- package/dist/components/SidebarSection/SidebarSection.d.ts.map +1 -1
- package/dist/components/SidebarSection/SidebarSection.js +2 -19
- package/dist/components/StatusDot/index.d.ts +42 -0
- package/dist/components/StatusDot/index.d.ts.map +1 -0
- package/dist/components/StatusDot/index.js +42 -0
- package/dist/components/ThemeVariantPickerModal/index.d.ts +71 -0
- package/dist/components/ThemeVariantPickerModal/index.d.ts.map +1 -0
- package/dist/components/ThemeVariantPickerModal/index.js +37 -0
- package/dist/components/VisibilityMenu/MenuCheckboxItem.d.ts +14 -0
- package/dist/components/VisibilityMenu/MenuCheckboxItem.d.ts.map +1 -0
- package/dist/components/VisibilityMenu/MenuCheckboxItem.js +14 -0
- package/dist/components/VisibilityMenu/index.d.ts.map +1 -1
- package/dist/components/VisibilityMenu/index.js +2 -11
- package/dist/components/index.d.ts +24 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +15 -1
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FormSection/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,WAAW,EAAE,SAAS,CAAC;IAEvB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,WAAW,EACX,QAAQ,EACR,IAAY,EACZ,SAAS,EACT,cAAc,EACd,OAAO,EACR,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAoBrB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { cn } from '../utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Shared settings section shell: title, description, and editor content.
|
|
5
|
+
* Used across collection, folder, environment, and globals settings views.
|
|
6
|
+
*/
|
|
7
|
+
export function FormSection({ title, description, children, fill = false, className, titleClassName, titleId }) {
|
|
8
|
+
return (_jsxs("div", { className: cn('mb-6 flex flex-col gap-1', fill && 'min-h-0 flex-1', className), children: [_jsx("span", { id: titleId, className: cn(titleClassName ?? 'text-[18px] text-muted', fill && 'shrink-0'), children: title }), _jsx("p", { className: cn('hc-form-group-description m-0 mb-2 text-[14px] text-muted', fill && 'shrink-0'), children: description }), children] }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef, JSX } from 'react';
|
|
2
|
+
export interface Props extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
|
|
3
|
+
/**
|
|
4
|
+
* Current progress count (for example completed items).
|
|
5
|
+
*/
|
|
6
|
+
value: number;
|
|
7
|
+
/**
|
|
8
|
+
* Maximum progress count (for example total items).
|
|
9
|
+
*/
|
|
10
|
+
max: number;
|
|
11
|
+
/**
|
|
12
|
+
* Accessible name announced for the progress bar.
|
|
13
|
+
*/
|
|
14
|
+
label: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Determinate horizontal progress bar with accent fill and width transition.
|
|
18
|
+
*/
|
|
19
|
+
export declare function ProgressBar({ value, max, label, className, ...props }: Props): JSX.Element;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ProgressBar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAI3D,MAAM,WAAW,KAAM,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC9E;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAmB1F"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { cn } from '../utils.js';
|
|
3
|
+
import { progressFillPercent } from './progressBar.logic.js';
|
|
4
|
+
/**
|
|
5
|
+
* Determinate horizontal progress bar with accent fill and width transition.
|
|
6
|
+
*/
|
|
7
|
+
export function ProgressBar({ value, max, label, className, ...props }) {
|
|
8
|
+
const fillPercent = progressFillPercent(value, max);
|
|
9
|
+
return (_jsx("div", { ...props, role: "progressbar", "aria-valuemin": 0, "aria-valuemax": max, "aria-valuenow": value, "aria-label": label, className: cn('hc-progress-bar h-2 overflow-hidden rounded-full bg-separator', className), children: _jsx("div", { className: "hc-progress-bar-fill h-full rounded-full bg-accent transition-[width] duration-200 motion-reduce:transition-none", style: { width: `${fillPercent}%` } }) }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes the fill width percentage for a determinate progress bar.
|
|
3
|
+
*
|
|
4
|
+
* @param value - Current progress count.
|
|
5
|
+
* @param max - Total count; zero yields 0% to avoid division by zero.
|
|
6
|
+
* @returns Rounded percentage between 0 and 100.
|
|
7
|
+
*/
|
|
8
|
+
export declare function progressFillPercent(value: number, max: number): number;
|
|
9
|
+
//# sourceMappingURL=progressBar.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progressBar.logic.d.ts","sourceRoot":"","sources":["../../../src/components/ProgressBar/progressBar.logic.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKtE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes the fill width percentage for a determinate progress bar.
|
|
3
|
+
*
|
|
4
|
+
* @param value - Current progress count.
|
|
5
|
+
* @param max - Total count; zero yields 0% to avoid division by zero.
|
|
6
|
+
* @returns Rounded percentage between 0 and 100.
|
|
7
|
+
*/
|
|
8
|
+
export function progressFillPercent(value, max) {
|
|
9
|
+
if (max === 0) {
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
return Math.round((value / max) * 100);
|
|
13
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from 'react';
|
|
2
|
+
import type { FormGroupLabelTone } from '../FormGroup/index.js';
|
|
3
|
+
export interface Props {
|
|
4
|
+
/**
|
|
5
|
+
* Dialog heading rendered in the modal header row.
|
|
6
|
+
*/
|
|
7
|
+
title: ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* Id of the element that labels the dialog (typically the heading).
|
|
10
|
+
*/
|
|
11
|
+
labelledBy: string;
|
|
12
|
+
/**
|
|
13
|
+
* Visible field label, or screen-reader-only text when `srOnlyLabel` is set.
|
|
14
|
+
*/
|
|
15
|
+
label: ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Hides the field label visually while keeping it available to screen readers.
|
|
18
|
+
*/
|
|
19
|
+
srOnlyLabel?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Label color style for the field. Defaults to muted helper tone.
|
|
22
|
+
*/
|
|
23
|
+
labelTone?: FormGroupLabelTone;
|
|
24
|
+
/**
|
|
25
|
+
* Current input value controlled by the parent.
|
|
26
|
+
*/
|
|
27
|
+
value: string;
|
|
28
|
+
/**
|
|
29
|
+
* Called when the user edits the input value.
|
|
30
|
+
*/
|
|
31
|
+
onChange: (value: string) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Called when the user submits via Enter or the primary button.
|
|
34
|
+
*/
|
|
35
|
+
onSubmit: () => void;
|
|
36
|
+
/**
|
|
37
|
+
* Called when the modal should close.
|
|
38
|
+
*/
|
|
39
|
+
onClose: () => void;
|
|
40
|
+
/**
|
|
41
|
+
* Primary action button label. Defaults to "Save".
|
|
42
|
+
*/
|
|
43
|
+
submitLabel?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Optional placeholder shown when the input is empty.
|
|
46
|
+
*/
|
|
47
|
+
placeholder?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Optional muted helper text rendered below the field label.
|
|
50
|
+
*/
|
|
51
|
+
description?: ReactNode;
|
|
52
|
+
/**
|
|
53
|
+
* Inline validation or submit error rendered below the input.
|
|
54
|
+
*/
|
|
55
|
+
error?: ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* When true, disables the input and primary button while work is in flight.
|
|
58
|
+
*/
|
|
59
|
+
busy?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Custom gate for enabling submit and Enter-to-submit. Defaults to non-empty trimmed value.
|
|
62
|
+
*/
|
|
63
|
+
canSubmit?: (value: string) => boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Optional width class for the dialog panel (passed to {@link Modal}).
|
|
66
|
+
*/
|
|
67
|
+
className?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Explicit id for the text input; used to associate the label via `htmlFor`.
|
|
70
|
+
*/
|
|
71
|
+
inputId?: string;
|
|
72
|
+
/**
|
|
73
|
+
* When true, focuses the input when the modal opens. Defaults to true.
|
|
74
|
+
*/
|
|
75
|
+
autoFocus?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Single-field prompt modal with autofocus input, Enter-to-submit, inline error,
|
|
79
|
+
* and a primary action gated on a trimmed non-empty value (or custom `canSubmit`).
|
|
80
|
+
*/
|
|
81
|
+
export declare function PromptModal({ title, labelledBy, label, srOnlyLabel, labelTone, value, onChange, onSubmit, onClose, submitLabel, placeholder, description, error, busy, canSubmit, className, inputId, autoFocus }: Props): JSX.Element;
|
|
82
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/PromptModal/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAMhE,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAE/B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAEvC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,UAAU,EACV,KAAK,EACL,WAAmB,EACnB,SAAmB,EACnB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,WAAoB,EACpB,WAAW,EACX,WAAW,EACX,KAAK,EACL,IAAY,EACZ,SAAuC,EACvC,SAAS,EACT,OAAO,EACP,SAAgB,EACjB,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAyCrB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { Button } from '../Button/index.js';
|
|
3
|
+
import { FormGroup } from '../FormGroup/index.js';
|
|
4
|
+
import { Modal, ModalFooter } from '../Modal/index.js';
|
|
5
|
+
import { Input } from '../forms/index.js';
|
|
6
|
+
import { defaultCanSubmitPromptValue } from './promptModal.logic.js';
|
|
7
|
+
/**
|
|
8
|
+
* Single-field prompt modal with autofocus input, Enter-to-submit, inline error,
|
|
9
|
+
* and a primary action gated on a trimmed non-empty value (or custom `canSubmit`).
|
|
10
|
+
*/
|
|
11
|
+
export function PromptModal({ title, labelledBy, label, srOnlyLabel = false, labelTone = 'muted', value, onChange, onSubmit, onClose, submitLabel = 'Save', placeholder, description, error, busy = false, canSubmit = defaultCanSubmitPromptValue, className, inputId, autoFocus = true }) {
|
|
12
|
+
const submitEnabled = !busy && canSubmit(value);
|
|
13
|
+
/**
|
|
14
|
+
* Submits the prompt when Enter is pressed and submission is allowed.
|
|
15
|
+
*/
|
|
16
|
+
const handleKeyDown = (event) => {
|
|
17
|
+
if (event.key === 'Enter' && submitEnabled) {
|
|
18
|
+
onSubmit();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
return (_jsxs(Modal, { onClose: onClose, className: className, labelledBy: labelledBy, title: title, children: [_jsx(FormGroup, { label: label, labelTone: labelTone, srOnly: srOnlyLabel, htmlFor: inputId, description: description, error: error, className: "border-none! p-0!", children: _jsx(Input, { className: "w-full", type: "text", autoFocus: autoFocus, placeholder: placeholder, value: value, disabled: busy, onChange: (event) => onChange(event.target.value), onKeyDown: handleKeyDown }) }), _jsx(ModalFooter, { spaced: true, children: _jsx(Button, { disabled: !submitEnabled, onClick: onSubmit, children: submitLabel }) })] }));
|
|
22
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns whether a prompt modal value is non-empty after trimming whitespace.
|
|
3
|
+
*
|
|
4
|
+
* @param value - Draft text from the single-field input.
|
|
5
|
+
* @returns True when the trimmed value has at least one character.
|
|
6
|
+
*/
|
|
7
|
+
export declare function defaultCanSubmitPromptValue(value: string): boolean;
|
|
8
|
+
//# sourceMappingURL=promptModal.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promptModal.logic.d.ts","sourceRoot":"","sources":["../../../src/components/PromptModal/promptModal.logic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAElE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns whether a prompt modal value is non-empty after trimming whitespace.
|
|
3
|
+
*
|
|
4
|
+
* @param value - Draft text from the single-field input.
|
|
5
|
+
* @returns True when the trimmed value has at least one character.
|
|
6
|
+
*/
|
|
7
|
+
export function defaultCanSubmitPromptValue(value) {
|
|
8
|
+
return value.trim().length > 0;
|
|
9
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
/**
|
|
4
|
+
* Resolved screenshot URLs or data URLs shown in the lightbox.
|
|
5
|
+
*/
|
|
6
|
+
images: string[];
|
|
7
|
+
/**
|
|
8
|
+
* Active slide index shared with the carousel preview.
|
|
9
|
+
*/
|
|
10
|
+
index: number;
|
|
11
|
+
/**
|
|
12
|
+
* Updates the active slide when the user navigates inside the lightbox.
|
|
13
|
+
*/
|
|
14
|
+
onIndexChange: (index: number) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Closes the lightbox overlay.
|
|
17
|
+
*/
|
|
18
|
+
onClose: () => void;
|
|
19
|
+
/**
|
|
20
|
+
* Accessible name for the lightbox dialog.
|
|
21
|
+
*/
|
|
22
|
+
label?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Full-size screenshot preview dialog opened from a screenshot carousel.
|
|
26
|
+
*/
|
|
27
|
+
export declare function ScreenshotLightbox({ images, index, onIndexChange, onClose, label }: Props): JSX.Element;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=ScreenshotLightbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScreenshotLightbox.d.ts","sourceRoot":"","sources":["../../../src/components/ScreenshotCarousel/ScreenshotLightbox.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAiB,MAAM,OAAO,CAAC;AAKhD,UAAU,KAAK;IACb;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEvC;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,KAAK,EACL,aAAa,EACb,OAAO,EACP,KAA4B,EAC7B,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAqGrB"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { faAngleLeft, faAngleRight } from '@fortawesome/free-solid-svg-icons';
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
import { FaIcon } from '../FaIcon/index.js';
|
|
5
|
+
import { Modal } from '../Modal/index.js';
|
|
6
|
+
/** Shared prev/next control styling for carousel and lightbox navigation. */
|
|
7
|
+
const NAV_BUTTON_CLASS = 'flex h-8 w-8 items-center justify-center rounded-md border border-separator bg-panel/90 text-text shadow-sm hover:bg-selection focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent motion-reduce:transition-none';
|
|
8
|
+
/**
|
|
9
|
+
* Full-size screenshot preview dialog opened from a screenshot carousel.
|
|
10
|
+
*/
|
|
11
|
+
export function ScreenshotLightbox({ images, index, onIndexChange, onClose, label = 'Screenshot preview' }) {
|
|
12
|
+
const imageCount = images.length;
|
|
13
|
+
const currentIndex = Math.min(index, imageCount - 1);
|
|
14
|
+
const hasMultiple = imageCount > 1;
|
|
15
|
+
const currentImage = images[currentIndex];
|
|
16
|
+
/**
|
|
17
|
+
* Closes the lightbox on Escape without dismissing a parent dialog beneath it.
|
|
18
|
+
*/
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
/**
|
|
21
|
+
* Handles Escape in the capture phase so nested modals stay open.
|
|
22
|
+
*
|
|
23
|
+
* @param event - Document keydown event.
|
|
24
|
+
*/
|
|
25
|
+
const handleKeyDown = (event) => {
|
|
26
|
+
if (event.key === 'Escape') {
|
|
27
|
+
event.stopImmediatePropagation();
|
|
28
|
+
onClose();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
document.addEventListener('keydown', handleKeyDown, true);
|
|
32
|
+
return () => document.removeEventListener('keydown', handleKeyDown, true);
|
|
33
|
+
}, [onClose]);
|
|
34
|
+
/**
|
|
35
|
+
* Moves to the previous screenshot, wrapping to the last slide.
|
|
36
|
+
*/
|
|
37
|
+
const showPrevious = () => {
|
|
38
|
+
onIndexChange(currentIndex === 0 ? imageCount - 1 : currentIndex - 1);
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Moves to the next screenshot, wrapping to the first slide.
|
|
42
|
+
*/
|
|
43
|
+
const showNext = () => {
|
|
44
|
+
onIndexChange(currentIndex === imageCount - 1 ? 0 : currentIndex + 1);
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Handles keyboard navigation within the lightbox dialog.
|
|
48
|
+
*
|
|
49
|
+
* @param event - Keyboard event on the lightbox container.
|
|
50
|
+
*/
|
|
51
|
+
const handleKeyDown = (event) => {
|
|
52
|
+
if (!hasMultiple) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (event.key === 'ArrowLeft') {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
showPrevious();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (event.key === 'ArrowRight') {
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
showNext();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
return (_jsx(Modal, { label: label, onClose: onClose, disableEscape: true, overlayClassName: "z-[60]", className: "relative flex max-h-[90vh] w-[min(92vw,72rem)] items-center justify-center p-2", children: _jsxs("div", { className: "relative flex w-full items-center justify-center", onKeyDown: handleKeyDown, children: [_jsx("img", { src: currentImage, alt: "", className: "max-h-[85vh] max-w-full object-contain" }), hasMultiple ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: `absolute top-1/2 left-2 -translate-y-1/2 ${NAV_BUTTON_CLASS}`, "aria-label": "Previous screenshot", onClick: showPrevious, children: _jsx(FaIcon, { icon: faAngleLeft, className: "h-3.5 w-3.5" }) }), _jsx("button", { type: "button", className: `absolute top-1/2 right-2 -translate-y-1/2 ${NAV_BUTTON_CLASS}`, "aria-label": "Next screenshot", onClick: showNext, children: _jsx(FaIcon, { icon: faAngleRight, className: "h-3.5 w-3.5" }) }), _jsx("p", { className: "sr-only", role: "status", "aria-live": "polite", children: `Screenshot ${currentIndex + 1} of ${imageCount}` })] })) : null] }) }));
|
|
66
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
import { type ScreenshotCarouselVariant } from './variants.js';
|
|
3
|
+
interface Props {
|
|
4
|
+
/**
|
|
5
|
+
* Resolved screenshot URLs or data URLs to display.
|
|
6
|
+
*/
|
|
7
|
+
images: string[];
|
|
8
|
+
/**
|
|
9
|
+
* Visual context for card grid, detail modal, or page tab spacing.
|
|
10
|
+
*/
|
|
11
|
+
variant: ScreenshotCarouselVariant;
|
|
12
|
+
/**
|
|
13
|
+
* Accessible name for the carousel group.
|
|
14
|
+
*/
|
|
15
|
+
ariaLabel?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Accessible name for the full-size lightbox dialog.
|
|
18
|
+
*/
|
|
19
|
+
lightboxLabel?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Optional wrapper class names.
|
|
22
|
+
*/
|
|
23
|
+
className?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Stops pointer and keyboard events from bubbling to a parent activator.
|
|
26
|
+
* Used by marketplace cards that open a modal on click.
|
|
27
|
+
*/
|
|
28
|
+
stopPropagation?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Accessible left/right screenshot carousel for marketplace previews.
|
|
32
|
+
*/
|
|
33
|
+
export declare function ScreenshotCarousel({ images, variant, ariaLabel, lightboxLabel, className, stopPropagation }: Props): JSX.Element | null;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ScreenshotCarousel/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAA6B,MAAM,OAAO,CAAC;AAI5D,OAAO,EACL,KAAK,yBAAyB,EAG/B,MAAM,eAAe,CAAC;AAEvB,UAAU,KAAK;IACb;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,yBAAyB,CAAC;IAEnC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,OAAO,EACP,SAAyB,EACzB,aAAoC,EACpC,SAAS,EACT,eAAuB,EACxB,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAmK5B"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { faAngleLeft, faAngleRight } from '@fortawesome/free-solid-svg-icons';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { FaIcon } from '../FaIcon/index.js';
|
|
5
|
+
import { ScreenshotLightbox } from './ScreenshotLightbox.js';
|
|
6
|
+
import { screenshotCarouselImageFrameClassName, screenshotCarouselLightboxEnabled } from './variants.js';
|
|
7
|
+
/**
|
|
8
|
+
* Accessible left/right screenshot carousel for marketplace previews.
|
|
9
|
+
*/
|
|
10
|
+
export function ScreenshotCarousel({ images, variant, ariaLabel = 'Screenshots', lightboxLabel = 'Screenshot preview', className, stopPropagation = false }) {
|
|
11
|
+
const [index, setIndex] = useState(0);
|
|
12
|
+
const [lightboxOpen, setLightboxOpen] = useState(false);
|
|
13
|
+
const imageCount = images.length;
|
|
14
|
+
const currentIndex = imageCount === 0 ? 0 : Math.min(index, imageCount - 1);
|
|
15
|
+
if (imageCount === 0) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const hasMultiple = imageCount > 1;
|
|
19
|
+
const currentImage = images[currentIndex];
|
|
20
|
+
const lightboxEnabled = screenshotCarouselLightboxEnabled(variant);
|
|
21
|
+
/**
|
|
22
|
+
* Moves to the previous screenshot, wrapping to the last slide.
|
|
23
|
+
*/
|
|
24
|
+
const showPrevious = () => {
|
|
25
|
+
setIndex(currentIndex === 0 ? imageCount - 1 : currentIndex - 1);
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Moves to the next screenshot, wrapping to the first slide.
|
|
29
|
+
*/
|
|
30
|
+
const showNext = () => {
|
|
31
|
+
setIndex(currentIndex === imageCount - 1 ? 0 : currentIndex + 1);
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Handles keyboard navigation within the carousel group.
|
|
35
|
+
*
|
|
36
|
+
* @param event - Keyboard event on the carousel container.
|
|
37
|
+
*/
|
|
38
|
+
const handleKeyDown = (event) => {
|
|
39
|
+
if (!hasMultiple) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (event.key === 'ArrowLeft') {
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
showPrevious();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (event.key === 'ArrowRight') {
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
showNext();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Prevents carousel controls from activating a parent card click handler.
|
|
54
|
+
*
|
|
55
|
+
* @param event - Pointer event from a carousel control.
|
|
56
|
+
*/
|
|
57
|
+
const handleControlPointerEvent = (event) => {
|
|
58
|
+
if (stopPropagation) {
|
|
59
|
+
event.stopPropagation();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Prevents carousel keyboard activation from opening a parent card.
|
|
64
|
+
*
|
|
65
|
+
* @param event - Keyboard event from a carousel control.
|
|
66
|
+
*/
|
|
67
|
+
const handleControlKeyDown = (event) => {
|
|
68
|
+
if (stopPropagation) {
|
|
69
|
+
event.stopPropagation();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Opens the full-size screenshot lightbox for modal and tab detail views.
|
|
74
|
+
*/
|
|
75
|
+
const handleOpenLightbox = () => {
|
|
76
|
+
setLightboxOpen(true);
|
|
77
|
+
};
|
|
78
|
+
const frameClassName = screenshotCarouselImageFrameClassName(variant);
|
|
79
|
+
const previewLabel = hasMultiple
|
|
80
|
+
? `View screenshot ${currentIndex + 1} of ${imageCount} in full size`
|
|
81
|
+
: 'View screenshot in full size';
|
|
82
|
+
return (_jsxs("div", { className: className ?? 'relative', role: "group", "aria-roledescription": "carousel", "aria-label": ariaLabel, tabIndex: hasMultiple ? 0 : undefined, onKeyDown: handleKeyDown, children: [lightboxEnabled ? (_jsx("button", { type: "button", className: "mb-4 block w-full cursor-zoom-in border-none bg-transparent p-0 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent", "aria-label": previewLabel, onClick: handleOpenLightbox, children: _jsx("img", { src: currentImage, alt: "", "aria-hidden": true, className: frameClassName }) })) : (_jsx("img", { src: currentImage, alt: "", "aria-hidden": true, className: frameClassName })), lightboxEnabled && lightboxOpen ? (_jsx(ScreenshotLightbox, { images: images, index: currentIndex, onIndexChange: setIndex, onClose: () => setLightboxOpen(false), label: lightboxLabel })) : null, hasMultiple ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "bg-panel/90 absolute top-1/2 left-2 flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-md border border-separator text-text shadow-sm hover:bg-selection focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent motion-reduce:transition-none", "aria-label": "Previous screenshot", onClick: (event) => {
|
|
83
|
+
handleControlPointerEvent(event);
|
|
84
|
+
showPrevious();
|
|
85
|
+
}, onKeyDown: handleControlKeyDown, children: _jsx(FaIcon, { icon: faAngleLeft, className: "h-3.5 w-3.5" }) }), _jsx("button", { type: "button", className: "bg-panel/90 absolute top-1/2 right-2 flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-md border border-separator text-text shadow-sm hover:bg-selection focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent motion-reduce:transition-none", "aria-label": "Next screenshot", onClick: (event) => {
|
|
86
|
+
handleControlPointerEvent(event);
|
|
87
|
+
showNext();
|
|
88
|
+
}, onKeyDown: handleControlKeyDown, children: _jsx(FaIcon, { icon: faAngleRight, className: "h-3.5 w-3.5" }) }), _jsx("p", { className: "sr-only", role: "status", "aria-live": "polite", children: `Screenshot ${currentIndex + 1} of ${imageCount}` }), _jsx("div", { className: "pointer-events-none absolute bottom-2 left-1/2 flex -translate-x-1/2 gap-1.5", "aria-hidden": true, children: images.map((image, dotIndex) => (_jsx("span", { className: `h-2 w-2 rounded-full ${dotIndex === currentIndex ? 'bg-text' : 'bg-text/40'}` }, `${image}-${dotIndex}`))) })] })) : null] }));
|
|
89
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screenshot carousel layout variant.
|
|
3
|
+
*/
|
|
4
|
+
export type ScreenshotCarouselVariant = 'card' | 'modal' | 'tab';
|
|
5
|
+
/**
|
|
6
|
+
* Returns the image frame classes for card, modal, and tab variants.
|
|
7
|
+
*
|
|
8
|
+
* @param variant - Card grid, detail modal, or page tab layout.
|
|
9
|
+
*/
|
|
10
|
+
export declare function screenshotCarouselImageFrameClassName(variant: ScreenshotCarouselVariant): string;
|
|
11
|
+
/**
|
|
12
|
+
* Returns whether the carousel should open a full-size lightbox on click.
|
|
13
|
+
*
|
|
14
|
+
* @param variant - Card grid, detail modal, or page tab layout.
|
|
15
|
+
*/
|
|
16
|
+
export declare function screenshotCarouselLightboxEnabled(variant: ScreenshotCarouselVariant): boolean;
|
|
17
|
+
//# sourceMappingURL=variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variants.d.ts","sourceRoot":"","sources":["../../../src/components/ScreenshotCarousel/variants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAEjE;;;;GAIG;AACH,wBAAgB,qCAAqC,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,CAQhG;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAE7F"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the image frame classes for card, modal, and tab variants.
|
|
3
|
+
*
|
|
4
|
+
* @param variant - Card grid, detail modal, or page tab layout.
|
|
5
|
+
*/
|
|
6
|
+
export function screenshotCarouselImageFrameClassName(variant) {
|
|
7
|
+
if (variant === 'card') {
|
|
8
|
+
return 'aspect-video w-full object-cover object-top border-b border-separator';
|
|
9
|
+
}
|
|
10
|
+
if (variant === 'tab') {
|
|
11
|
+
return 'max-h-[min(18rem,35vh)] w-full rounded-md border border-separator object-contain object-top';
|
|
12
|
+
}
|
|
13
|
+
return 'aspect-video w-full object-cover object-top rounded-md border border-separator';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Returns whether the carousel should open a full-size lightbox on click.
|
|
17
|
+
*
|
|
18
|
+
* @param variant - Card grid, detail modal, or page tab layout.
|
|
19
|
+
*/
|
|
20
|
+
export function screenshotCarouselLightboxEnabled(variant) {
|
|
21
|
+
return variant === 'modal' || variant === 'tab';
|
|
22
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
2
|
+
import type { JSX } from 'react';
|
|
3
|
+
export interface Props {
|
|
4
|
+
/**
|
|
5
|
+
* Fixed viewport coordinates for the floating toolbar button.
|
|
6
|
+
*/
|
|
7
|
+
coords: {
|
|
8
|
+
top: number;
|
|
9
|
+
left: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Accessible name announced for the action button.
|
|
13
|
+
*/
|
|
14
|
+
label: string;
|
|
15
|
+
/**
|
|
16
|
+
* Visible button label, for example "Copy to chat".
|
|
17
|
+
*/
|
|
18
|
+
text: string;
|
|
19
|
+
/**
|
|
20
|
+
* Invoked when the user activates the selection action.
|
|
21
|
+
*/
|
|
22
|
+
onSelect: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Optional leading icon rendered before the visible label.
|
|
25
|
+
*/
|
|
26
|
+
icon?: IconDefinition;
|
|
27
|
+
/**
|
|
28
|
+
* Optional muted shortcut hint shown after the label.
|
|
29
|
+
*/
|
|
30
|
+
shortcutHint?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Additional classes merged onto the toolbar button.
|
|
33
|
+
*/
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Floating selection action button portaled to document.body so fixed positioning
|
|
38
|
+
* is not clipped by overflow-hidden editor or terminal containers.
|
|
39
|
+
*/
|
|
40
|
+
export declare function SelectionActionToolbar({ coords, label, text, onSelect, icon, shortcutHint, className }: Props): JSX.Element;
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SelectionActionToolbar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAKjC,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAEtC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;IAEtB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,YAAY,EACZ,SAAS,EACV,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAoBrB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { FaIcon } from '../FaIcon/index.js';
|
|
3
|
+
import { portalToBody } from '../portalToBody.js';
|
|
4
|
+
import { cn } from '../utils.js';
|
|
5
|
+
/**
|
|
6
|
+
* Floating selection action button portaled to document.body so fixed positioning
|
|
7
|
+
* is not clipped by overflow-hidden editor or terminal containers.
|
|
8
|
+
*/
|
|
9
|
+
export function SelectionActionToolbar({ coords, label, text, onSelect, icon, shortcutHint, className }) {
|
|
10
|
+
return portalToBody(_jsxs("button", { type: "button", className: cn('hc-code-editor-selection-action app-no-drag pointer-events-auto fixed z-[70] inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-separator bg-control px-2 py-1 text-[14px] text-text shadow-sm hover:bg-surface focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-accent', className), style: { top: coords.top, left: coords.left }, "aria-label": label, onMouseDown: (event) => {
|
|
11
|
+
event.preventDefault();
|
|
12
|
+
}, onClick: onSelect, children: [icon ? _jsx(FaIcon, { icon: icon, className: "h-3.5 w-3.5" }) : null, _jsx("span", { children: text }), shortcutHint ? _jsx("span", { className: "text-[14px] text-muted", children: shortcutHint }) : null] }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from 'react';
|
|
2
|
+
export interface Props {
|
|
3
|
+
/**
|
|
4
|
+
* Visible setting label text.
|
|
5
|
+
*/
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Stable setting id shown on hover and keyboard focus.
|
|
9
|
+
*/
|
|
10
|
+
settingId: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Setting label with a VS Code-style id affordance revealed on hover and focus.
|
|
14
|
+
*/
|
|
15
|
+
export declare function SettingIdLabel({ children, settingId }: Props): JSX.Element;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SettingIdLabel/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAa1E"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Setting label with a VS Code-style id affordance revealed on hover and focus.
|
|
4
|
+
*/
|
|
5
|
+
export function SettingIdLabel({ children, settingId }) {
|
|
6
|
+
return (_jsxs("span", { className: "group/setting-label inline-flex items-baseline gap-2", children: [_jsx("span", { children: children }), _jsx("span", { className: "pointer-events-none font-mono text-[14px] text-muted opacity-0 transition-opacity select-none group-focus-within/setting-label:opacity-100 group-hover/setting-label:opacity-100", title: settingId, "aria-label": `Setting id: ${settingId}`, children: settingId })] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from 'react';
|
|
2
|
+
export interface Props {
|
|
3
|
+
/**
|
|
4
|
+
* Stable setting id shown on hover and keyboard focus beside the title.
|
|
5
|
+
*/
|
|
6
|
+
settingId: string;
|
|
7
|
+
/**
|
|
8
|
+
* Visible section title text.
|
|
9
|
+
*/
|
|
10
|
+
title: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Optional muted helper copy rendered below the title.
|
|
13
|
+
*/
|
|
14
|
+
description?: ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* Extra classes on the outer wrapper.
|
|
17
|
+
*/
|
|
18
|
+
className?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Overrides the default title span classes.
|
|
21
|
+
*/
|
|
22
|
+
titleClassName?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Overrides the default description paragraph classes.
|
|
25
|
+
*/
|
|
26
|
+
descriptionClassName?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Settings section heading that pairs a titled label with an optional description
|
|
30
|
+
* and a hover-revealed setting id badge.
|
|
31
|
+
*/
|
|
32
|
+
export declare function SettingSectionHeading({ settingId, title, description, className, titleClassName, descriptionClassName }: Props): JSX.Element;
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SettingSectionHeading/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAI5C,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,KAAK,EACL,WAAW,EACX,SAAS,EACT,cAAc,EACd,oBAAoB,EACrB,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAWrB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { SettingIdLabel } from '../SettingIdLabel/index.js';
|
|
3
|
+
import { cn } from '../utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Settings section heading that pairs a titled label with an optional description
|
|
6
|
+
* and a hover-revealed setting id badge.
|
|
7
|
+
*/
|
|
8
|
+
export function SettingSectionHeading({ settingId, title, description, className, titleClassName, descriptionClassName }) {
|
|
9
|
+
return (_jsxs("div", { className: className, children: [_jsx("span", { className: cn('text-[18px] font-medium text-text', titleClassName), children: _jsx(SettingIdLabel, { settingId: settingId, children: title }) }), description != null && description !== '' ? (_jsx("p", { className: cn('m-0 mb-4 text-muted', descriptionClassName), children: description })) : null] }));
|
|
10
|
+
}
|