@harborclient/sdk 0.6.4 → 0.6.7
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/FormDataEditor/index.d.ts.map +1 -1
- package/dist/components/FormDataEditor/index.js +10 -38
- package/dist/components/FormDataEditor/utils.d.ts +19 -0
- package/dist/components/FormDataEditor/utils.d.ts.map +1 -0
- package/dist/components/FormDataEditor/utils.js +28 -0
- package/dist/components/KeyValueEditor/index.d.ts.map +1 -1
- package/dist/components/KeyValueEditor/index.js +2 -3
- package/dist/components/Page/index.d.ts +46 -0
- package/dist/components/Page/index.d.ts.map +1 -0
- package/dist/components/Page/index.js +18 -0
- package/dist/components/PageSidebar/index.d.ts +45 -0
- package/dist/components/PageSidebar/index.d.ts.map +1 -0
- package/dist/components/PageSidebar/index.js +24 -0
- package/dist/components/SegmentedTabs/SegmentedTabPanel.d.ts +21 -0
- package/dist/components/SegmentedTabs/SegmentedTabPanel.d.ts.map +1 -0
- package/dist/components/SegmentedTabs/SegmentedTabPanel.js +15 -0
- package/dist/components/SegmentedTabs/SegmentedTabsContext.d.ts +24 -0
- package/dist/components/SegmentedTabs/SegmentedTabsContext.d.ts.map +1 -0
- package/dist/components/SegmentedTabs/SegmentedTabsContext.js +2 -0
- package/dist/components/SegmentedTabs/SegmentedTabsGroup.d.ts +28 -0
- package/dist/components/SegmentedTabs/SegmentedTabsGroup.d.ts.map +1 -0
- package/dist/components/SegmentedTabs/SegmentedTabsGroup.js +21 -0
- package/dist/components/SegmentedTabs/index.d.ts +5 -67
- package/dist/components/SegmentedTabs/index.d.ts.map +1 -1
- package/dist/components/SegmentedTabs/index.js +4 -33
- package/dist/components/SegmentedTabs/types.d.ts +24 -0
- package/dist/components/SegmentedTabs/types.d.ts.map +1 -0
- package/dist/components/SegmentedTabs/types.js +1 -0
- package/dist/components/SidebarLayout/index.d.ts +22 -0
- package/dist/components/SidebarLayout/index.d.ts.map +1 -0
- package/dist/components/SidebarLayout/index.js +11 -0
- package/dist/components/Table/index.d.ts +103 -0
- package/dist/components/Table/index.d.ts.map +1 -0
- package/dist/components/Table/index.js +99 -0
- package/dist/components/VariableTable/index.d.ts.map +1 -1
- package/dist/components/VariableTable/index.js +2 -2
- package/dist/components/classes.js +1 -1
- package/dist/components/index.d.ts +6 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -1
- package/package.json +1 -1
- package/dist/components/OverlayPage/index.d.ts +0 -40
- package/dist/components/OverlayPage/index.d.ts.map +0 -1
- package/dist/components/OverlayPage/index.js +0 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FormDataEditor/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAoB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FormDataEditor/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAoB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAQ/E,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,KAAK,EAAE,YAAY,EAAE,CAAC;IAEtB;;;;OAIG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAE1C;;OAEG;IACH,SAAS,EAAE,QAAQ,EAAE,CAAC;IAEtB;;OAEG;IACH,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,SAAS,EACT,aAAa,EACb,cAAc,EACf,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAwLrB"}
|
|
@@ -4,37 +4,9 @@ import { useMemo } from '@harborclient/sdk/react';
|
|
|
4
4
|
import { Button } from '../Button/index.js';
|
|
5
5
|
import { FaIcon } from '../FaIcon/index.js';
|
|
6
6
|
import { Input, Select, fieldFrame } from '../forms/index.js';
|
|
7
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader } from '../Table/index.js';
|
|
7
8
|
import { VariableInput } from '../VariableInput/index.js';
|
|
8
|
-
|
|
9
|
-
const tdClass = 'border-r border-b border-separator p-1.5 align-top last:border-r-0';
|
|
10
|
-
/**
|
|
11
|
-
* Returns a blank multipart form part with enabled set to true.
|
|
12
|
-
*/
|
|
13
|
-
function emptyFormPart() {
|
|
14
|
-
return { key: '', value: '', enabled: true, type: 'text', files: [] };
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Returns the file name portion of an absolute path.
|
|
18
|
-
*
|
|
19
|
-
* @param filePath - Absolute file path.
|
|
20
|
-
*/
|
|
21
|
-
function fileBasename(filePath) {
|
|
22
|
-
const normalized = filePath.replace(/\\/g, '/');
|
|
23
|
-
const lastSlash = normalized.lastIndexOf('/');
|
|
24
|
-
return lastSlash >= 0 ? normalized.slice(lastSlash + 1) : normalized;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Ensures at least one row exists and appends a trailing blank row when needed.
|
|
28
|
-
*
|
|
29
|
-
* @param parts - Current form parts.
|
|
30
|
-
* @returns Rows safe to render in the editor.
|
|
31
|
-
*/
|
|
32
|
-
function withTrailingRow(parts) {
|
|
33
|
-
if (parts.length === 0) {
|
|
34
|
-
return [emptyFormPart()];
|
|
35
|
-
}
|
|
36
|
-
return parts;
|
|
37
|
-
}
|
|
9
|
+
import { emptyFormPart, fileBasename, withTrailingRow } from './utils.js';
|
|
38
10
|
/**
|
|
39
11
|
* Editable table of multipart form parts with text and file field types.
|
|
40
12
|
*/
|
|
@@ -98,12 +70,12 @@ export function FormDataEditor({ parts, onChange, variables, onSelectFiles, onEd
|
|
|
98
70
|
const currentFiles = rows[index]?.files ?? [];
|
|
99
71
|
updateRow(index, { files: currentFiles.filter((file) => file !== filePath) });
|
|
100
72
|
};
|
|
101
|
-
return (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
73
|
+
return (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs("tr", { children: [_jsx(TableHead, { className: "w-6 p-0", children: _jsx("span", { className: "sr-only", children: "Enable" }) }), _jsx(TableHead, { children: "Key" }), _jsx(TableHead, { className: "w-24", children: "Type" }), _jsx(TableHead, { children: "Value" }), _jsx(TableHead, { className: "w-7 p-0" })] }) }), _jsx(TableBody, { children: rows.map((row, index) => (_jsxs("tr", { children: [_jsx(TableCell, { className: "w-6 p-1 text-center", children: _jsx(Input, { type: "checkbox", className: "app-no-drag", checked: row.enabled, onChange: (e) => updateRow(index, { enabled: e.target.checked }), "aria-label": `Enable row ${index + 1}`, title: "Enable" }) }), _jsx(TableCell, { children: _jsx(Input, { type: "text", className: "w-full", value: row.key, placeholder: "field", "aria-label": `Key, row ${index + 1}`, onChange: (e) => updateRow(index, { key: e.target.value }) }) }), _jsx(TableCell, { children: _jsxs(Select, { className: "w-full", value: row.type, "aria-label": `Type, row ${index + 1}`, onChange: (e) => {
|
|
74
|
+
const type = e.target.value;
|
|
75
|
+
updateRow(index, {
|
|
76
|
+
type,
|
|
77
|
+
value: type === 'text' ? row.value : '',
|
|
78
|
+
files: type === 'file' ? row.files : []
|
|
79
|
+
});
|
|
80
|
+
}, children: [_jsx("option", { value: "text", children: "Text" }), _jsx("option", { value: "file", children: "File" })] }) }), _jsx(TableCell, { children: row.type === 'text' ? (_jsx(VariableInput, { wrapperClassName: `${fieldFrame} w-full`, className: "app-no-drag", value: row.value, onChange: (value) => updateRow(index, { value }), variables: variables, placeholder: "value", "aria-label": `Value, row ${index + 1}`, onEditVariable: onEditVariable })) : (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Button, { type: "button", variant: "secondary", className: "self-start px-2 py-0.5 text-[14px]", onClick: () => void chooseFiles(index), children: "Choose files" }), row.files.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1", children: row.files.map((filePath) => (_jsxs("span", { className: "inline-flex max-w-full items-center gap-1 rounded-md border border-separator bg-control px-1.5 py-0.5 text-[14px] text-text", title: filePath, "aria-label": filePath, children: [_jsx("span", { className: "truncate", children: fileBasename(filePath) }), _jsx("button", { type: "button", className: "inline-flex h-4 w-4 shrink-0 cursor-pointer items-center justify-center rounded border-none bg-transparent text-muted hover:bg-selection hover:text-text app-no-drag", onClick: () => removeFile(index, filePath), title: `Remove file ${fileBasename(filePath)}`, "aria-label": `Remove file ${fileBasename(filePath)}`, children: _jsx(FaIcon, { icon: faXmark, className: "h-3 w-3" }) })] }, filePath))) }))] })) }), _jsx(TableCell, { className: "w-7 p-1 text-center", children: _jsx(Button, { type: "button", variant: "iconDanger", onClick: () => removeRow(index), title: "Remove", "aria-label": `Remove row ${index + 1}`, children: _jsx(FaIcon, { icon: faXmark, className: "h-3.5 w-3.5" }) }) })] }, index))) })] }));
|
|
109
81
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FormDataPart } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns a blank multipart form part with enabled set to true.
|
|
4
|
+
*/
|
|
5
|
+
export declare function emptyFormPart(): FormDataPart;
|
|
6
|
+
/**
|
|
7
|
+
* Returns the file name portion of an absolute path.
|
|
8
|
+
*
|
|
9
|
+
* @param filePath - Absolute file path.
|
|
10
|
+
*/
|
|
11
|
+
export declare function fileBasename(filePath: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Ensures at least one row exists and appends a trailing blank row when needed.
|
|
14
|
+
*
|
|
15
|
+
* @param parts - Current form parts.
|
|
16
|
+
* @returns Rows safe to render in the editor.
|
|
17
|
+
*/
|
|
18
|
+
export declare function withTrailingRow(parts: FormDataPart[]): FormDataPart[];
|
|
19
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/FormDataEditor/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,IAAI,YAAY,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAKrE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a blank multipart form part with enabled set to true.
|
|
3
|
+
*/
|
|
4
|
+
export function emptyFormPart() {
|
|
5
|
+
return { key: '', value: '', enabled: true, type: 'text', files: [] };
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Returns the file name portion of an absolute path.
|
|
9
|
+
*
|
|
10
|
+
* @param filePath - Absolute file path.
|
|
11
|
+
*/
|
|
12
|
+
export function fileBasename(filePath) {
|
|
13
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
14
|
+
const lastSlash = normalized.lastIndexOf('/');
|
|
15
|
+
return lastSlash >= 0 ? normalized.slice(lastSlash + 1) : normalized;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Ensures at least one row exists and appends a trailing blank row when needed.
|
|
19
|
+
*
|
|
20
|
+
* @param parts - Current form parts.
|
|
21
|
+
* @returns Rows safe to render in the editor.
|
|
22
|
+
*/
|
|
23
|
+
export function withTrailingRow(parts) {
|
|
24
|
+
if (parts.length === 0) {
|
|
25
|
+
return [emptyFormPart()];
|
|
26
|
+
}
|
|
27
|
+
return parts;
|
|
28
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/KeyValueEditor/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/KeyValueEditor/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAOzD,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,IAAI,EAAE,QAAQ,EAAE,CAAC;IAEjB;;;;OAIG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IAErC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,SAAS,EAAE,QAAQ,EAAE,CAAC;IAEtB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,QAAQ,EACR,cAAsB,EACtB,gBAA0B,EAC1B,SAAS,EACT,cAAc,EACf,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CA4FrB"}
|
|
@@ -3,9 +3,8 @@ import { faXmark } from '@fortawesome/free-solid-svg-icons';
|
|
|
3
3
|
import { Button } from '../Button/index.js';
|
|
4
4
|
import { FaIcon } from '../FaIcon/index.js';
|
|
5
5
|
import { Input, fieldFrame } from '../forms/index.js';
|
|
6
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader } from '../Table/index.js';
|
|
6
7
|
import { VariableInput } from '../VariableInput/index.js';
|
|
7
|
-
const thClass = 'border-r border-b border-separator p-3 text-left text-[14px] font-medium uppercase tracking-wide text-muted last:border-r-0';
|
|
8
|
-
const tdClass = 'border-r border-b border-separator p-3 last:border-r-0';
|
|
9
8
|
/**
|
|
10
9
|
* Editable table of key-value rows with enable toggles for headers and params.
|
|
11
10
|
*/
|
|
@@ -36,5 +35,5 @@ export function KeyValueEditor({ rows, onChange, placeholderKey = 'Key', placeho
|
|
|
36
35
|
}
|
|
37
36
|
onChange(rows.filter((_, i) => i !== index));
|
|
38
37
|
};
|
|
39
|
-
return (
|
|
38
|
+
return (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs("tr", { children: [_jsx(TableHead, { className: "w-6 p-0", children: _jsx("span", { className: "sr-only", children: "Enable" }) }), _jsx(TableHead, { children: "Key" }), _jsx(TableHead, { children: "Value" }), _jsx(TableHead, { className: "w-7 p-0" })] }) }), _jsx(TableBody, { children: rows.map((row, index) => (_jsxs("tr", { children: [_jsx(TableCell, { className: "w-6 p-1 text-center", children: _jsx(Input, { type: "checkbox", className: "app-no-drag", checked: row.enabled, onChange: (e) => updateRow(index, { enabled: e.target.checked }), "aria-label": `Enable row ${index + 1}`, title: "Enable" }) }), _jsx(TableCell, { children: _jsx(Input, { type: "text", className: "w-full", value: row.key, placeholder: placeholderKey, "aria-label": `Key, row ${index + 1}`, onChange: (e) => updateRow(index, { key: e.target.value }) }) }), _jsx(TableCell, { children: _jsx(VariableInput, { wrapperClassName: `${fieldFrame} w-full`, className: "app-no-drag", value: row.value, onChange: (value) => updateRow(index, { value }), variables: variables, placeholder: placeholderValue, "aria-label": `Value, row ${index + 1}`, onEditVariable: onEditVariable }) }), _jsx(TableCell, { className: "w-7 p-1 text-center", children: _jsx(Button, { type: "button", variant: "iconDanger", onClick: () => removeRow(index), title: "Remove", "aria-label": `Remove row ${index + 1}`, children: _jsx(FaIcon, { icon: faXmark, className: "h-3.5 w-3.5" }) }) })] }, index))) })] }));
|
|
40
39
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
2
|
+
import type { JSX, ReactNode } from 'react';
|
|
3
|
+
interface Props {
|
|
4
|
+
/**
|
|
5
|
+
* Page heading rendered in the header row.
|
|
6
|
+
*/
|
|
7
|
+
title: string;
|
|
8
|
+
/**
|
|
9
|
+
* Optional muted summary shown below the title.
|
|
10
|
+
*/
|
|
11
|
+
description?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Optional decorative icon shown before the title.
|
|
14
|
+
*/
|
|
15
|
+
icon?: IconDefinition;
|
|
16
|
+
/**
|
|
17
|
+
* Action controls aligned to the right side of the header row, such as close
|
|
18
|
+
* or back buttons.
|
|
19
|
+
*/
|
|
20
|
+
actions?: ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Optional trailing action row below the body, such as Save/Cancel footers.
|
|
23
|
+
*/
|
|
24
|
+
footer?: ReactNode;
|
|
25
|
+
/**
|
|
26
|
+
* When true, omits the scroll container and padding so the page can render
|
|
27
|
+
* inside a parent that already scrolls (for example {@link SidebarLayout}).
|
|
28
|
+
*/
|
|
29
|
+
embedded?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Additional Tailwind classes merged onto the outer wrapper.
|
|
32
|
+
*/
|
|
33
|
+
className?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Main page body content below the header.
|
|
36
|
+
*/
|
|
37
|
+
children?: ReactNode;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Full-area page shell with a {@link PageHeader}, scrollable body, and optional
|
|
41
|
+
* footer. Use the default mode for self-contained overlay pages; set
|
|
42
|
+
* `embedded` when the parent already provides scroll and padding.
|
|
43
|
+
*/
|
|
44
|
+
export declare function Page({ title, description, icon, actions, footer, embedded, className, children }: Props): JSX.Element;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Page/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,UAAU,KAAK;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,EACnB,KAAK,EACL,WAAW,EACX,IAAI,EACJ,OAAO,EACP,MAAM,EACN,QAAgB,EAChB,SAAS,EACT,QAAQ,EACT,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CA+BrB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { PageHeader } from '../PageHeader/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Full-area page shell with a {@link PageHeader}, scrollable body, and optional
|
|
5
|
+
* footer. Use the default mode for self-contained overlay pages; set
|
|
6
|
+
* `embedded` when the parent already provides scroll and padding.
|
|
7
|
+
*/
|
|
8
|
+
export function Page({ title, description, icon, actions, footer, embedded = false, className, children }) {
|
|
9
|
+
const header = (_jsx(PageHeader, { title: title, description: description, icon: icon, children: actions }));
|
|
10
|
+
if (embedded) {
|
|
11
|
+
const outer = className ?? undefined;
|
|
12
|
+
return (_jsxs("div", { className: outer, children: [header, children, footer] }));
|
|
13
|
+
}
|
|
14
|
+
const outer = className
|
|
15
|
+
? `flex min-h-0 flex-1 flex-col overflow-y-auto p-6 ${className}`
|
|
16
|
+
: 'flex min-h-0 flex-1 flex-col overflow-y-auto p-6';
|
|
17
|
+
return (_jsx("div", { className: outer, children: _jsxs("div", { className: "mx-auto w-full", children: [header, children, footer] }) }));
|
|
18
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
2
|
+
import type { JSX } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* One entry in a {@link PageSidebar} navigation list.
|
|
5
|
+
*/
|
|
6
|
+
export interface PageSidebarItem<T extends string = string> {
|
|
7
|
+
/**
|
|
8
|
+
* Stable section identifier passed to `onSelect` when the row is activated.
|
|
9
|
+
*/
|
|
10
|
+
value: T;
|
|
11
|
+
/**
|
|
12
|
+
* Visible label for the navigation row.
|
|
13
|
+
*/
|
|
14
|
+
label: string;
|
|
15
|
+
/**
|
|
16
|
+
* Optional decorative icon shown before the label.
|
|
17
|
+
*/
|
|
18
|
+
icon?: IconDefinition;
|
|
19
|
+
}
|
|
20
|
+
interface Props<T extends string> {
|
|
21
|
+
/**
|
|
22
|
+
* Navigation entries to render in the sidebar.
|
|
23
|
+
*/
|
|
24
|
+
items: PageSidebarItem<T>[];
|
|
25
|
+
/**
|
|
26
|
+
* Currently selected section value.
|
|
27
|
+
*/
|
|
28
|
+
selected: T;
|
|
29
|
+
/**
|
|
30
|
+
* Called when the user selects a different section.
|
|
31
|
+
*
|
|
32
|
+
* @param value - Newly selected section value.
|
|
33
|
+
*/
|
|
34
|
+
onSelect: (value: T) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Accessible name for the sidebar `nav` element.
|
|
37
|
+
*/
|
|
38
|
+
ariaLabel: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Narrow sidebar navigation for multi-section pages such as settings overlays.
|
|
42
|
+
*/
|
|
43
|
+
export declare function PageSidebar<T extends string>({ items, selected, onSelect, ariaLabel }: Props<T>): JSX.Element;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/PageSidebar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAGjC;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACxD;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAED,UAAU,KAAK,CAAC,CAAC,SAAS,MAAM;IAC9B;;OAEG;IACH,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAE5B;;OAEG;IACH,QAAQ,EAAE,CAAC,CAAC;IAEZ;;;;OAIG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAE7B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,EAC5C,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAS,EACV,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,CAiCxB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { FaIcon } from '../FaIcon/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Tailwind classes for a sidebar navigation row.
|
|
5
|
+
*
|
|
6
|
+
* @param active - Whether this row is the current selection.
|
|
7
|
+
*/
|
|
8
|
+
function sidebarRow(active) {
|
|
9
|
+
return active
|
|
10
|
+
? 'group flex items-center gap-1 rounded-md bg-selection px-1.5 py-0.5 app-no-drag'
|
|
11
|
+
: 'group flex items-center gap-1 rounded-md px-1.5 py-0.5 hover:bg-selection/60 app-no-drag';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Narrow sidebar navigation for multi-section pages such as settings overlays.
|
|
15
|
+
*/
|
|
16
|
+
export function PageSidebar({ items, selected, onSelect, ariaLabel }) {
|
|
17
|
+
return (_jsx("nav", { className: "flex w-[180px] shrink-0 flex-col gap-0.5 border-r border-separator bg-sidebar px-2 py-3", "aria-label": ariaLabel, children: items.map((item) => {
|
|
18
|
+
const active = selected === item.value;
|
|
19
|
+
const rowClass = item.icon
|
|
20
|
+
? `${sidebarRow(active)} w-full gap-2 border-none text-left text-[14px] app-no-drag`
|
|
21
|
+
: `${sidebarRow(active)} w-full border-none text-left text-[14px] app-no-drag`;
|
|
22
|
+
return (_jsxs("button", { type: "button", className: rowClass, "aria-current": active ? 'page' : undefined, onClick: () => onSelect(item.value), children: [item.icon ? (_jsx(FaIcon, { icon: item.icon, className: `h-3.5 w-3.5 shrink-0 ${active ? 'text-text' : 'text-muted'}`, "aria-hidden": true })) : null, _jsx("span", { className: "min-w-0 truncate", children: item.label })] }, item.value));
|
|
23
|
+
}) }));
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from 'react';
|
|
2
|
+
interface Props<T extends string> {
|
|
3
|
+
/**
|
|
4
|
+
* Tab value that controls visibility of this panel.
|
|
5
|
+
*/
|
|
6
|
+
value: T;
|
|
7
|
+
/**
|
|
8
|
+
* Panel content shown when this tab is selected.
|
|
9
|
+
*/
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Additional CSS classes for the panel container.
|
|
13
|
+
*/
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Renders a WAI-ARIA tab panel linked to the matching tab in the parent group.
|
|
18
|
+
*/
|
|
19
|
+
export declare function SegmentedTabPanel<T extends string>({ value, children, className }: Props<T>): JSX.Element | null;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=SegmentedTabPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedTabPanel.d.ts","sourceRoot":"","sources":["../../../src/components/SegmentedTabs/SegmentedTabPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,UAAU,KAAK,CAAC,CAAC,SAAS,MAAM;IAC9B;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,EAClD,KAAK,EACL,QAAQ,EACR,SAAS,EACV,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAkB/B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { useContext } from '@harborclient/sdk/react';
|
|
3
|
+
import { SegmentedTabsContext } from './SegmentedTabsContext.js';
|
|
4
|
+
/**
|
|
5
|
+
* Renders a WAI-ARIA tab panel linked to the matching tab in the parent group.
|
|
6
|
+
*/
|
|
7
|
+
export function SegmentedTabPanel({ value, children, className }) {
|
|
8
|
+
const context = useContext(SegmentedTabsContext);
|
|
9
|
+
if (!context) {
|
|
10
|
+
throw new Error('SegmentedTabPanel must be used within SegmentedTabsGroup');
|
|
11
|
+
}
|
|
12
|
+
if (context.value !== value)
|
|
13
|
+
return null;
|
|
14
|
+
return (_jsx("div", { role: "tabpanel", id: context.getPanelId(value), "aria-labelledby": context.getTabId(value), className: className, children: children }));
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface SegmentedTabsContextValue {
|
|
2
|
+
/**
|
|
3
|
+
* Currently selected tab value.
|
|
4
|
+
*/
|
|
5
|
+
value: string;
|
|
6
|
+
/**
|
|
7
|
+
* Selects a tab by value.
|
|
8
|
+
*/
|
|
9
|
+
onChange: (value: string) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Accessible name for the tab list.
|
|
12
|
+
*/
|
|
13
|
+
ariaLabel: string;
|
|
14
|
+
/**
|
|
15
|
+
* Stable DOM id for a tab control.
|
|
16
|
+
*/
|
|
17
|
+
getTabId: (value: string) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Stable DOM id for a tab panel linked to a tab.
|
|
20
|
+
*/
|
|
21
|
+
getPanelId: (value: string) => string;
|
|
22
|
+
}
|
|
23
|
+
export declare const SegmentedTabsContext: import("react").Context<SegmentedTabsContextValue | null>;
|
|
24
|
+
//# sourceMappingURL=SegmentedTabsContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedTabsContext.d.ts","sourceRoot":"","sources":["../../../src/components/SegmentedTabs/SegmentedTabsContext.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAEpC;;OAEG;IACH,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC;AAED,eAAO,MAAM,oBAAoB,2DAAwD,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from 'react';
|
|
2
|
+
interface Props<T extends string> {
|
|
3
|
+
/**
|
|
4
|
+
* Currently selected tab value.
|
|
5
|
+
*/
|
|
6
|
+
value: T;
|
|
7
|
+
/**
|
|
8
|
+
* Called when the user selects a different tab.
|
|
9
|
+
*
|
|
10
|
+
* @param value - Newly selected tab value.
|
|
11
|
+
*/
|
|
12
|
+
onChange: (value: T) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Accessible name for the tab list.
|
|
15
|
+
*/
|
|
16
|
+
ariaLabel: string;
|
|
17
|
+
/**
|
|
18
|
+
* Tab list and linked tab panels.
|
|
19
|
+
*/
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Provides tab selection state and stable ids for `SegmentedTabs` and
|
|
24
|
+
* `SegmentedTabPanel` children.
|
|
25
|
+
*/
|
|
26
|
+
export declare function SegmentedTabsGroup<T extends string>({ value, onChange, ariaLabel, children }: Props<T>): JSX.Element;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=SegmentedTabsGroup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedTabsGroup.d.ts","sourceRoot":"","sources":["../../../src/components/SegmentedTabs/SegmentedTabsGroup.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,UAAU,KAAK,CAAC,CAAC,SAAS,MAAM;IAC9B;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC;IAET;;;;OAIG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAE7B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EAAE,EACnD,KAAK,EACL,QAAQ,EACR,SAAS,EACT,QAAQ,EACT,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,CAmBxB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createElement, useId, useMemo } from '@harborclient/sdk/react';
|
|
2
|
+
import { SegmentedTabsContext } from './SegmentedTabsContext.js';
|
|
3
|
+
/**
|
|
4
|
+
* Provides tab selection state and stable ids for `SegmentedTabs` and
|
|
5
|
+
* `SegmentedTabPanel` children.
|
|
6
|
+
*/
|
|
7
|
+
export function SegmentedTabsGroup({ value, onChange, ariaLabel, children }) {
|
|
8
|
+
const baseId = useId();
|
|
9
|
+
/**
|
|
10
|
+
* Memoizes context so tab ids stay stable across renders while value updates
|
|
11
|
+
* propagate to list and panel children.
|
|
12
|
+
*/
|
|
13
|
+
const contextValue = useMemo(() => ({
|
|
14
|
+
value,
|
|
15
|
+
onChange: (nextValue) => onChange(nextValue),
|
|
16
|
+
ariaLabel,
|
|
17
|
+
getTabId: (tabValue) => `${baseId}-tab-${tabValue}`,
|
|
18
|
+
getPanelId: (tabValue) => `${baseId}-panel-${tabValue}`
|
|
19
|
+
}), [value, onChange, ariaLabel, baseId]);
|
|
20
|
+
return createElement(SegmentedTabsContext.Provider, { value: contextValue }, children);
|
|
21
|
+
}
|
|
@@ -1,69 +1,8 @@
|
|
|
1
|
-
import type { JSX
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
value: T;
|
|
7
|
-
/**
|
|
8
|
-
* Tab label or custom content.
|
|
9
|
-
*/
|
|
10
|
-
label: ReactNode;
|
|
11
|
-
/**
|
|
12
|
-
* When true, the tab is not rendered.
|
|
13
|
-
*/
|
|
14
|
-
hidden?: boolean;
|
|
15
|
-
/**
|
|
16
|
-
* When true, the tab button is disabled.
|
|
17
|
-
*/
|
|
18
|
-
disabled?: boolean;
|
|
19
|
-
/**
|
|
20
|
-
* When true, renders a small dot indicating the tab has values set.
|
|
21
|
-
*/
|
|
22
|
-
indicator?: boolean;
|
|
23
|
-
}
|
|
24
|
-
interface GroupProps<T extends string> {
|
|
25
|
-
/**
|
|
26
|
-
* Currently selected tab value.
|
|
27
|
-
*/
|
|
28
|
-
value: T;
|
|
29
|
-
/**
|
|
30
|
-
* Called when the user selects a different tab.
|
|
31
|
-
*
|
|
32
|
-
* @param value - Newly selected tab value.
|
|
33
|
-
*/
|
|
34
|
-
onChange: (value: T) => void;
|
|
35
|
-
/**
|
|
36
|
-
* Accessible name for the tab list.
|
|
37
|
-
*/
|
|
38
|
-
ariaLabel: string;
|
|
39
|
-
/**
|
|
40
|
-
* Tab list and linked tab panels.
|
|
41
|
-
*/
|
|
42
|
-
children: ReactNode;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Provides tab selection state and stable ids for `SegmentedTabs` and
|
|
46
|
-
* `SegmentedTabPanel` children.
|
|
47
|
-
*/
|
|
48
|
-
export declare function SegmentedTabsGroup<T extends string>({ value, onChange, ariaLabel, children }: GroupProps<T>): JSX.Element;
|
|
49
|
-
interface PanelProps<T extends string> {
|
|
50
|
-
/**
|
|
51
|
-
* Tab value that controls visibility of this panel.
|
|
52
|
-
*/
|
|
53
|
-
value: T;
|
|
54
|
-
/**
|
|
55
|
-
* Panel content shown when this tab is selected.
|
|
56
|
-
*/
|
|
57
|
-
children: ReactNode;
|
|
58
|
-
/**
|
|
59
|
-
* Additional CSS classes for the panel container.
|
|
60
|
-
*/
|
|
61
|
-
className?: string;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Renders a WAI-ARIA tab panel linked to the matching tab in the parent group.
|
|
65
|
-
*/
|
|
66
|
-
export declare function SegmentedTabPanel<T extends string>({ value, children, className }: PanelProps<T>): JSX.Element | null;
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
import type { TabItem } from './types.js';
|
|
3
|
+
export { SegmentedTabsGroup } from './SegmentedTabsGroup.js';
|
|
4
|
+
export { SegmentedTabPanel } from './SegmentedTabPanel.js';
|
|
5
|
+
export type { TabItem } from './types.js';
|
|
67
6
|
interface Props<T extends string> {
|
|
68
7
|
/**
|
|
69
8
|
* Tab definitions to render.
|
|
@@ -103,5 +42,4 @@ interface Props<T extends string> {
|
|
|
103
42
|
* macOS-style segmented tab control with WAI-ARIA tabs or radiogroup semantics.
|
|
104
43
|
*/
|
|
105
44
|
export declare function SegmentedTabs<T extends string>({ tabs, value: valueProp, onChange: onChangeProp, fullWidth, className, pattern, ariaLabel: ariaLabelProp }: Props<T>): JSX.Element;
|
|
106
|
-
export {};
|
|
107
45
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SegmentedTabs/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SegmentedTabs/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAiB,MAAM,OAAO,CAAC;AAIhD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,UAAU,KAAK,CAAC,CAAC,SAAS,MAAM;IAC9B;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,CAAC;IAEV;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAE9B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAEhC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,EAC9C,IAAI,EACJ,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,YAAY,EACtB,SAAiB,EACjB,SAAS,EACT,OAAgB,EAChB,SAAS,EAAE,aAAa,EACzB,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,CA+GxB"}
|
|
@@ -1,39 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useCallback, useContext, useId, useMemo, useRef } from '@harborclient/sdk/react';
|
|
3
3
|
import { resolveTabListKeyAction } from '../utils.js';
|
|
4
4
|
import { segment, segmentGroup } from '../classes.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* `SegmentedTabPanel` children.
|
|
9
|
-
*/
|
|
10
|
-
export function SegmentedTabsGroup({ value, onChange, ariaLabel, children }) {
|
|
11
|
-
const baseId = useId();
|
|
12
|
-
/**
|
|
13
|
-
* Memoizes context so tab ids stay stable across renders while value updates
|
|
14
|
-
* propagate to list and panel children.
|
|
15
|
-
*/
|
|
16
|
-
const contextValue = useMemo(() => ({
|
|
17
|
-
value,
|
|
18
|
-
onChange: (nextValue) => onChange(nextValue),
|
|
19
|
-
ariaLabel,
|
|
20
|
-
getTabId: (tabValue) => `${baseId}-tab-${tabValue}`,
|
|
21
|
-
getPanelId: (tabValue) => `${baseId}-panel-${tabValue}`
|
|
22
|
-
}), [value, onChange, ariaLabel, baseId]);
|
|
23
|
-
return createElement(SegmentedTabsContext.Provider, { value: contextValue }, children);
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Renders a WAI-ARIA tab panel linked to the matching tab in the parent group.
|
|
27
|
-
*/
|
|
28
|
-
export function SegmentedTabPanel({ value, children, className }) {
|
|
29
|
-
const context = useContext(SegmentedTabsContext);
|
|
30
|
-
if (!context) {
|
|
31
|
-
throw new Error('SegmentedTabPanel must be used within SegmentedTabsGroup');
|
|
32
|
-
}
|
|
33
|
-
if (context.value !== value)
|
|
34
|
-
return null;
|
|
35
|
-
return (_jsx("div", { role: "tabpanel", id: context.getPanelId(value), "aria-labelledby": context.getTabId(value), className: className, children: children }));
|
|
36
|
-
}
|
|
5
|
+
import { SegmentedTabsContext } from './SegmentedTabsContext.js';
|
|
6
|
+
export { SegmentedTabsGroup } from './SegmentedTabsGroup.js';
|
|
7
|
+
export { SegmentedTabPanel } from './SegmentedTabPanel.js';
|
|
37
8
|
/**
|
|
38
9
|
* macOS-style segmented tab control with WAI-ARIA tabs or radiogroup semantics.
|
|
39
10
|
*/
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface TabItem<T extends string> {
|
|
3
|
+
/**
|
|
4
|
+
* Unique tab identifier.
|
|
5
|
+
*/
|
|
6
|
+
value: T;
|
|
7
|
+
/**
|
|
8
|
+
* Tab label or custom content.
|
|
9
|
+
*/
|
|
10
|
+
label: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* When true, the tab is not rendered.
|
|
13
|
+
*/
|
|
14
|
+
hidden?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* When true, the tab button is disabled.
|
|
17
|
+
*/
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* When true, renders a small dot indicating the tab has values set.
|
|
21
|
+
*/
|
|
22
|
+
indicator?: boolean;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/SegmentedTabs/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,MAAM;IACvC;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
/**
|
|
4
|
+
* Sidebar navigation rendered in the left column.
|
|
5
|
+
*/
|
|
6
|
+
sidebar: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Scrollable main content rendered in the right column.
|
|
9
|
+
*/
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Additional Tailwind classes merged onto the outer flex column wrapper.
|
|
13
|
+
*/
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Two-pane layout shell: a fixed sidebar column and a scrollable content area
|
|
18
|
+
* with standard page padding.
|
|
19
|
+
*/
|
|
20
|
+
export declare function SidebarLayout({ sidebar, children, className }: Props): JSX.Element;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarLayout/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5C,UAAU,KAAK;IACb;;OAEG;IACH,OAAO,EAAE,SAAS,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAalF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Two-pane layout shell: a fixed sidebar column and a scrollable content area
|
|
4
|
+
* with standard page padding.
|
|
5
|
+
*/
|
|
6
|
+
export function SidebarLayout({ sidebar, children, className }) {
|
|
7
|
+
const outer = className
|
|
8
|
+
? `flex min-h-0 flex-1 flex-col ${className}`
|
|
9
|
+
: 'flex min-h-0 flex-1 flex-col';
|
|
10
|
+
return (_jsx("div", { className: outer, children: _jsxs("div", { className: "flex min-h-0 flex-1", children: [sidebar, _jsx("div", { className: "flex-1 overflow-y-auto p-6", children: children })] }) }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { HTMLAttributes, JSX, ReactNode, TdHTMLAttributes, ThHTMLAttributes } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Layout preset for {@link Table} and its subcomponents.
|
|
4
|
+
*/
|
|
5
|
+
export type TableVariant = 'bordered' | 'loose';
|
|
6
|
+
/**
|
|
7
|
+
* Default header cell classes for bordered editor tables.
|
|
8
|
+
*/
|
|
9
|
+
export declare const tableHeadClass = "border-r border-b border-separator p-3 text-left text-[14px] font-medium uppercase tracking-wide text-muted last:border-r-0";
|
|
10
|
+
/**
|
|
11
|
+
* Default body cell classes for bordered editor tables.
|
|
12
|
+
*/
|
|
13
|
+
export declare const tableCellClass = "border-r border-b border-separator p-3 last:border-r-0";
|
|
14
|
+
/**
|
|
15
|
+
* Header cell classes for loose tables with separate cell spacing.
|
|
16
|
+
*/
|
|
17
|
+
export declare const tableHeadClassLoose = "pb-1 text-left text-[14px] font-medium uppercase tracking-wide text-muted";
|
|
18
|
+
/**
|
|
19
|
+
* Body cell classes for loose tables with separate cell spacing.
|
|
20
|
+
*/
|
|
21
|
+
export declare const tableCellClassLoose = "";
|
|
22
|
+
interface TableProps {
|
|
23
|
+
/**
|
|
24
|
+
* Table header and body sections.
|
|
25
|
+
*/
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* Layout preset for the table shell and cell styling.
|
|
29
|
+
*/
|
|
30
|
+
variant?: TableVariant;
|
|
31
|
+
/**
|
|
32
|
+
* Additional Tailwind classes merged onto the outer wrapper or table element.
|
|
33
|
+
*/
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Table shell for editable row layouts.
|
|
38
|
+
*
|
|
39
|
+
* @param children - {@link TableHeader} and {@link TableBody} sections.
|
|
40
|
+
* @param variant - Bordered collapsed layout or loose separate-cell spacing.
|
|
41
|
+
* @param className - Extra classes on the wrapper (bordered) or table element (loose).
|
|
42
|
+
*/
|
|
43
|
+
export declare function Table({ children, variant, className }: TableProps): JSX.Element;
|
|
44
|
+
interface TableSectionProps extends HTMLAttributes<HTMLTableSectionElement> {
|
|
45
|
+
/**
|
|
46
|
+
* Header or body row content.
|
|
47
|
+
*/
|
|
48
|
+
children: ReactNode;
|
|
49
|
+
/**
|
|
50
|
+
* Additional Tailwind classes merged onto the section element.
|
|
51
|
+
*/
|
|
52
|
+
className?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Table header section wrapper.
|
|
56
|
+
*
|
|
57
|
+
* @param children - Header row elements, typically native `tr` nodes.
|
|
58
|
+
* @param className - Extra classes appended after any section preset.
|
|
59
|
+
*/
|
|
60
|
+
export declare function TableHeader({ children, className, ...rest }: TableSectionProps): JSX.Element;
|
|
61
|
+
/**
|
|
62
|
+
* Table body section wrapper.
|
|
63
|
+
*
|
|
64
|
+
* @param children - Body row elements, typically native `tr` nodes.
|
|
65
|
+
* @param className - Extra classes appended after the layout preset.
|
|
66
|
+
*/
|
|
67
|
+
export declare function TableBody({ children, className, ...rest }: TableSectionProps): JSX.Element;
|
|
68
|
+
interface TableHeadProps extends ThHTMLAttributes<HTMLTableCellElement> {
|
|
69
|
+
/**
|
|
70
|
+
* Header cell content.
|
|
71
|
+
*/
|
|
72
|
+
children?: ReactNode;
|
|
73
|
+
/**
|
|
74
|
+
* Additional Tailwind classes merged after the header cell preset.
|
|
75
|
+
*/
|
|
76
|
+
className?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Header cell with table styling for the active variant.
|
|
80
|
+
*
|
|
81
|
+
* @param children - Header label content.
|
|
82
|
+
* @param className - Extra classes appended after the layout preset.
|
|
83
|
+
*/
|
|
84
|
+
export declare function TableHead({ children, className, scope, ...rest }: TableHeadProps): JSX.Element;
|
|
85
|
+
interface TableCellProps extends TdHTMLAttributes<HTMLTableCellElement> {
|
|
86
|
+
/**
|
|
87
|
+
* Body cell content.
|
|
88
|
+
*/
|
|
89
|
+
children?: ReactNode;
|
|
90
|
+
/**
|
|
91
|
+
* Additional Tailwind classes merged after the body cell preset.
|
|
92
|
+
*/
|
|
93
|
+
className?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Body cell with table styling for the active variant.
|
|
97
|
+
*
|
|
98
|
+
* @param children - Cell content.
|
|
99
|
+
* @param className - Extra classes appended after the layout preset.
|
|
100
|
+
*/
|
|
101
|
+
export declare function TableCell({ children, className, ...rest }: TableCellProps): JSX.Element;
|
|
102
|
+
export {};
|
|
103
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Table/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAEhG;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,cAAc,gIACoG,CAAC;AAEhI;;GAEG;AACH,eAAO,MAAM,cAAc,2DAA2D,CAAC;AAEvF;;GAEG;AACH,eAAO,MAAM,mBAAmB,8EAC6C,CAAC;AAE9E;;GAEG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAuBtC,UAAU,UAAU;IAClB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,EAAE,QAAQ,EAAE,OAAoB,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,GAAG,CAAC,OAAO,CAwB5F;AAED,UAAU,iBAAkB,SAAQ,cAAc,CAAC,uBAAuB,CAAC;IACzE;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAM5F;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAU1F;AAED,UAAU,cAAe,SAAQ,gBAAgB,CAAC,oBAAoB,CAAC;IACrE;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,SAAS,EACT,KAAa,EACb,GAAG,IAAI,EACR,EAAE,cAAc,GAAG,GAAG,CAAC,OAAO,CAU9B;AAED,UAAU,cAAe,SAAQ,gBAAgB,CAAC,oBAAoB,CAAC;IACrE;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,cAAc,GAAG,GAAG,CAAC,OAAO,CAUvF"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { createContext, createElement, useContext } from '@harborclient/sdk/react';
|
|
3
|
+
/**
|
|
4
|
+
* Default header cell classes for bordered editor tables.
|
|
5
|
+
*/
|
|
6
|
+
export const tableHeadClass = 'border-r border-b border-separator p-3 text-left text-[14px] font-medium uppercase tracking-wide text-muted last:border-r-0';
|
|
7
|
+
/**
|
|
8
|
+
* Default body cell classes for bordered editor tables.
|
|
9
|
+
*/
|
|
10
|
+
export const tableCellClass = 'border-r border-b border-separator p-3 last:border-r-0';
|
|
11
|
+
/**
|
|
12
|
+
* Header cell classes for loose tables with separate cell spacing.
|
|
13
|
+
*/
|
|
14
|
+
export const tableHeadClassLoose = 'pb-1 text-left text-[14px] font-medium uppercase tracking-wide text-muted';
|
|
15
|
+
/**
|
|
16
|
+
* Body cell classes for loose tables with separate cell spacing.
|
|
17
|
+
*/
|
|
18
|
+
export const tableCellClassLoose = '';
|
|
19
|
+
const TableVariantContext = createContext('bordered');
|
|
20
|
+
/**
|
|
21
|
+
* Returns preset classes merged with optional overrides.
|
|
22
|
+
*
|
|
23
|
+
* @param base - Variant preset classes.
|
|
24
|
+
* @param className - Additional classes appended after the preset.
|
|
25
|
+
*/
|
|
26
|
+
function mergeClasses(base, className) {
|
|
27
|
+
if (base && className) {
|
|
28
|
+
return `${base} ${className}`;
|
|
29
|
+
}
|
|
30
|
+
if (base) {
|
|
31
|
+
return base;
|
|
32
|
+
}
|
|
33
|
+
if (className) {
|
|
34
|
+
return className;
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Table shell for editable row layouts.
|
|
40
|
+
*
|
|
41
|
+
* @param children - {@link TableHeader} and {@link TableBody} sections.
|
|
42
|
+
* @param variant - Bordered collapsed layout or loose separate-cell spacing.
|
|
43
|
+
* @param className - Extra classes on the wrapper (bordered) or table element (loose).
|
|
44
|
+
*/
|
|
45
|
+
export function Table({ children, variant = 'bordered', className }) {
|
|
46
|
+
if (variant === 'loose') {
|
|
47
|
+
const tableBase = 'w-full border-separate border-spacing-x-1.5 border-spacing-y-1.5';
|
|
48
|
+
const tableClasses = className ? `${tableBase} ${className}` : tableBase;
|
|
49
|
+
return createElement(TableVariantContext.Provider, { value: variant }, createElement('table', { className: tableClasses }, children));
|
|
50
|
+
}
|
|
51
|
+
const wrapperBase = 'overflow-hidden rounded-md border border-separator';
|
|
52
|
+
const wrapperClasses = className ? `${wrapperBase} ${className}` : wrapperBase;
|
|
53
|
+
return createElement(TableVariantContext.Provider, { value: variant }, createElement('div', { className: wrapperClasses }, createElement('table', { className: 'w-full border-collapse' }, children)));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Table header section wrapper.
|
|
57
|
+
*
|
|
58
|
+
* @param children - Header row elements, typically native `tr` nodes.
|
|
59
|
+
* @param className - Extra classes appended after any section preset.
|
|
60
|
+
*/
|
|
61
|
+
export function TableHeader({ children, className, ...rest }) {
|
|
62
|
+
return (_jsx("thead", { className: className, ...rest, children: children }));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Table body section wrapper.
|
|
66
|
+
*
|
|
67
|
+
* @param children - Body row elements, typically native `tr` nodes.
|
|
68
|
+
* @param className - Extra classes appended after the layout preset.
|
|
69
|
+
*/
|
|
70
|
+
export function TableBody({ children, className, ...rest }) {
|
|
71
|
+
const variant = useContext(TableVariantContext);
|
|
72
|
+
const base = variant === 'bordered' ? '[&_tr:last-child_td]:border-b-0' : '';
|
|
73
|
+
const classes = mergeClasses(base, className);
|
|
74
|
+
return (_jsx("tbody", { className: classes, ...rest, children: children }));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Header cell with table styling for the active variant.
|
|
78
|
+
*
|
|
79
|
+
* @param children - Header label content.
|
|
80
|
+
* @param className - Extra classes appended after the layout preset.
|
|
81
|
+
*/
|
|
82
|
+
export function TableHead({ children, className, scope = 'col', ...rest }) {
|
|
83
|
+
const variant = useContext(TableVariantContext);
|
|
84
|
+
const base = variant === 'loose' ? tableHeadClassLoose : tableHeadClass;
|
|
85
|
+
const classes = mergeClasses(base, className);
|
|
86
|
+
return (_jsx("th", { scope: scope, className: classes, ...rest, children: children }));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Body cell with table styling for the active variant.
|
|
90
|
+
*
|
|
91
|
+
* @param children - Cell content.
|
|
92
|
+
* @param className - Extra classes appended after the layout preset.
|
|
93
|
+
*/
|
|
94
|
+
export function TableCell({ children, className, ...rest }) {
|
|
95
|
+
const variant = useContext(TableVariantContext);
|
|
96
|
+
const base = variant === 'loose' ? tableCellClassLoose : tableCellClass;
|
|
97
|
+
const classes = mergeClasses(base, className);
|
|
98
|
+
return (_jsx("td", { className: classes, ...rest, children: children }));
|
|
99
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/VariableTable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/VariableTable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAY/C,UAAU,KAAK;IACb;;OAEG;IACH,SAAS,EAAE,QAAQ,EAAE,CAAC;IAEtB;;OAEG;IACH,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IAE1C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAmHtF"}
|
|
@@ -3,11 +3,11 @@ import { Button } from '../Button/index.js';
|
|
|
3
3
|
import { FaIcon } from '../FaIcon/index.js';
|
|
4
4
|
import { faPlus, faXmark } from '@fortawesome/free-solid-svg-icons';
|
|
5
5
|
import { Input } from '../forms/index.js';
|
|
6
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader } from '../Table/index.js';
|
|
6
7
|
/**
|
|
7
8
|
* Returns a blank variable row for new table entries.
|
|
8
9
|
*/
|
|
9
10
|
const emptyVariable = () => ({ key: '', value: '', defaultValue: '', share: false });
|
|
10
|
-
const thClass = 'pb-1 text-left text-[14px] font-medium uppercase tracking-wide text-muted';
|
|
11
11
|
/**
|
|
12
12
|
* Editable table for key/value/default/share variable rows.
|
|
13
13
|
*/
|
|
@@ -39,5 +39,5 @@ export function VariableTable({ variables, onChange, description }) {
|
|
|
39
39
|
}
|
|
40
40
|
onChange(variables.filter((_, i) => i !== index));
|
|
41
41
|
};
|
|
42
|
-
return (_jsxs("div", { children: [description && _jsx("p", { className: "mb-3 text-[14px] text-muted", children: description }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsxs(
|
|
42
|
+
return (_jsxs("div", { children: [description && _jsx("p", { className: "mb-3 text-[14px] text-muted", children: description }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsxs(Table, { variant: "loose", children: [_jsx(TableHeader, { children: _jsxs("tr", { children: [_jsx(TableHead, { children: "Key" }), _jsx(TableHead, { children: "Value" }), _jsx(TableHead, { children: "Default" }), _jsx(TableHead, { className: "w-14 text-center", children: "Share" }), _jsx(TableHead, { className: "w-7 p-0 text-center" })] }) }), _jsx(TableBody, { children: variables.map((variable, index) => (_jsxs("tr", { children: [_jsx(TableCell, { children: _jsx(Input, { type: "text", className: "w-full", value: variable.key, placeholder: "variable", "aria-label": `Key, row ${index + 1}`, onChange: (e) => updateVariable(index, { key: e.target.value }) }) }), _jsx(TableCell, { children: _jsx(Input, { type: "text", className: "w-full", value: variable.value, placeholder: "value", "aria-label": `Value, row ${index + 1}`, onChange: (e) => updateVariable(index, { value: e.target.value }) }) }), _jsx(TableCell, { children: _jsx(Input, { type: "text", className: "w-full", value: variable.defaultValue, placeholder: "default", "aria-label": `Default, row ${index + 1}`, onChange: (e) => updateVariable(index, { defaultValue: e.target.value }) }) }), _jsx(TableCell, { className: "w-14 text-center", children: _jsx(Input, { type: "checkbox", checked: variable.share, onChange: (e) => updateVariable(index, { share: e.target.checked }), "aria-label": `Include value in export, row ${index + 1}`, title: "Include value in export" }) }), _jsx(TableCell, { className: "w-7 p-0 text-center", children: _jsx(Button, { type: "button", variant: "iconDanger", onClick: () => removeVariable(index), title: "Remove", "aria-label": `Remove row ${index + 1}`, children: _jsx(FaIcon, { icon: faXmark, className: "h-3.5 w-3.5" }) }) })] }, index))) })] }), _jsxs(Button, { type: "button", variant: "toolbar", className: "inline-flex items-center gap-1 self-start", onClick: addVariable, children: [_jsx(FaIcon, { icon: faPlus, className: "h-3 w-3" }), "Add variable"] })] })] }));
|
|
43
43
|
}
|
|
@@ -9,6 +9,6 @@ export const segmentGroup = 'inline-flex p-3 border-b border-separator w-full sh
|
|
|
9
9
|
*/
|
|
10
10
|
export function segment(active) {
|
|
11
11
|
return active
|
|
12
|
-
? 'cursor-pointer rounded-[2.5px] border-none bg-
|
|
12
|
+
? 'cursor-pointer rounded-[2.5px] border-none bg-field px-3 py-1 text-[15px] text-text shadow-sm app-no-drag'
|
|
13
13
|
: 'cursor-pointer rounded-[2.5px] border-none bg-transparent px-3 py-1 text-[15px] text-muted hover:text-text app-no-drag';
|
|
14
14
|
}
|
|
@@ -25,8 +25,11 @@ export { MethodSelect } from './MethodSelect/index.js';
|
|
|
25
25
|
export { Modal, ModalFooter, ModalFormLayout } from './Modal/index.js';
|
|
26
26
|
export { ModalHeader } from './Modal/ModalHeader.js';
|
|
27
27
|
export { OverlayCloseButton } from './OverlayCloseButton/index.js';
|
|
28
|
-
export {
|
|
28
|
+
export { Page } from './Page/index.js';
|
|
29
29
|
export { PageHeader } from './PageHeader/index.js';
|
|
30
|
+
export { PageSidebar } from './PageSidebar/index.js';
|
|
31
|
+
export type { PageSidebarItem } from './PageSidebar/index.js';
|
|
32
|
+
export { SidebarLayout } from './SidebarLayout/index.js';
|
|
30
33
|
export { PanelCloseButton } from './PanelCloseButton/index.js';
|
|
31
34
|
export { Resizable, ResizeHandle, useResizable } from './Resizable/index.js';
|
|
32
35
|
export type { UseResizableOptions, UseResizableResult } from './Resizable/useResizable.js';
|
|
@@ -40,6 +43,8 @@ export type { TabItem } from './SegmentedTabs/index.js';
|
|
|
40
43
|
export { Spinner } from './Spinner/index.js';
|
|
41
44
|
export { StatusMessage } from './StatusMessage/index.js';
|
|
42
45
|
export { TabCloseButton } from './TabCloseButton/index.js';
|
|
46
|
+
export { Table, TableBody, TableCell, TableHead, TableHeader, tableCellClass, tableCellClassLoose, tableHeadClass, tableHeadClassLoose } from './Table/index.js';
|
|
47
|
+
export type { TableVariant } from './Table/index.js';
|
|
43
48
|
export { VariableInput } from './VariableInput/index.js';
|
|
44
49
|
export type { Props as VariableInputProps } from './VariableInput/index.js';
|
|
45
50
|
export { VariableTable } from './VariableTable/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,YAAY,EAAE,KAAK,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,YAAY,EAAE,KAAK,IAAI,eAAe,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EAAE,KAAK,IAAI,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EACL,KAAK,EACL,MAAM,EACN,QAAQ,EACR,KAAK,EACL,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EAAE,KAAK,IAAI,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
|
package/dist/components/index.js
CHANGED
|
@@ -18,8 +18,10 @@ export { MethodSelect } from './MethodSelect/index.js';
|
|
|
18
18
|
export { Modal, ModalFooter, ModalFormLayout } from './Modal/index.js';
|
|
19
19
|
export { ModalHeader } from './Modal/ModalHeader.js';
|
|
20
20
|
export { OverlayCloseButton } from './OverlayCloseButton/index.js';
|
|
21
|
-
export {
|
|
21
|
+
export { Page } from './Page/index.js';
|
|
22
22
|
export { PageHeader } from './PageHeader/index.js';
|
|
23
|
+
export { PageSidebar } from './PageSidebar/index.js';
|
|
24
|
+
export { SidebarLayout } from './SidebarLayout/index.js';
|
|
23
25
|
export { PanelCloseButton } from './PanelCloseButton/index.js';
|
|
24
26
|
export { Resizable, ResizeHandle, useResizable } from './Resizable/index.js';
|
|
25
27
|
export { DEFAULT_HEIGHT, MIN_HEIGHT, footerPanelClassName, footerPanelCloseButtonClassName, getFooterPanelMaxSize } from './Resizable/footerPanelUtils.js';
|
|
@@ -30,6 +32,7 @@ export { SegmentedTabs, SegmentedTabsGroup, SegmentedTabPanel } from './Segmente
|
|
|
30
32
|
export { Spinner } from './Spinner/index.js';
|
|
31
33
|
export { StatusMessage } from './StatusMessage/index.js';
|
|
32
34
|
export { TabCloseButton } from './TabCloseButton/index.js';
|
|
35
|
+
export { Table, TableBody, TableCell, TableHead, TableHeader, tableCellClass, tableCellClassLoose, tableHeadClass, tableHeadClassLoose } from './Table/index.js';
|
|
33
36
|
export { VariableInput } from './VariableInput/index.js';
|
|
34
37
|
export { VariableTable } from './VariableTable/index.js';
|
|
35
38
|
export { cleanVariables, resolveTabListKeyAction } from './utils.js';
|
package/package.json
CHANGED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { JSX, ReactNode } from 'react';
|
|
2
|
-
interface Props {
|
|
3
|
-
/**
|
|
4
|
-
* Page title shown in the overlay header.
|
|
5
|
-
*/
|
|
6
|
-
title: ReactNode;
|
|
7
|
-
/**
|
|
8
|
-
* Called when the user closes the overlay.
|
|
9
|
-
*/
|
|
10
|
-
onClose: () => void;
|
|
11
|
-
/**
|
|
12
|
-
* Scrollable page body content.
|
|
13
|
-
*/
|
|
14
|
-
children: ReactNode;
|
|
15
|
-
/**
|
|
16
|
-
* Optional footer actions such as Save/Cancel rows.
|
|
17
|
-
*/
|
|
18
|
-
footer?: ReactNode;
|
|
19
|
-
/**
|
|
20
|
-
* Accessible name for the header close button.
|
|
21
|
-
*/
|
|
22
|
-
closeLabel?: string;
|
|
23
|
-
/**
|
|
24
|
-
* Additional Tailwind classes merged onto the outer scroll container.
|
|
25
|
-
*/
|
|
26
|
-
className?: string;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Full-page scrollable overlay shell shared by environment, collection, and plugin views.
|
|
30
|
-
*
|
|
31
|
-
* @param title - Header title text or element.
|
|
32
|
-
* @param onClose - Close handler for the header button.
|
|
33
|
-
* @param children - Main page content.
|
|
34
|
-
* @param footer - Optional trailing action row below the body.
|
|
35
|
-
* @param closeLabel - Accessible close button label.
|
|
36
|
-
* @param className - Extra classes on the outer container.
|
|
37
|
-
*/
|
|
38
|
-
export declare function OverlayPage({ title, onClose, children, footer, closeLabel, className }: Props): JSX.Element;
|
|
39
|
-
export {};
|
|
40
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/OverlayPage/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,UAAU,KAAK;IACb;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,SAAS,EACV,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAiBrB"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
-
import { OverlayCloseButton } from '../OverlayCloseButton/index.js';
|
|
3
|
-
/**
|
|
4
|
-
* Full-page scrollable overlay shell shared by environment, collection, and plugin views.
|
|
5
|
-
*
|
|
6
|
-
* @param title - Header title text or element.
|
|
7
|
-
* @param onClose - Close handler for the header button.
|
|
8
|
-
* @param children - Main page content.
|
|
9
|
-
* @param footer - Optional trailing action row below the body.
|
|
10
|
-
* @param closeLabel - Accessible close button label.
|
|
11
|
-
* @param className - Extra classes on the outer container.
|
|
12
|
-
*/
|
|
13
|
-
export function OverlayPage({ title, onClose, children, footer, closeLabel, className }) {
|
|
14
|
-
const outer = className
|
|
15
|
-
? `flex min-h-0 flex-1 flex-col overflow-y-auto p-6 ${className}`
|
|
16
|
-
: 'flex min-h-0 flex-1 flex-col overflow-y-auto p-6';
|
|
17
|
-
return (_jsx("div", { className: outer, children: _jsxs("div", { className: "mx-auto w-full", children: [_jsxs("div", { className: "mb-6 flex items-center justify-between gap-4", children: [_jsx("h1", { className: "m-0 text-[15px] font-semibold text-text", children: title }), _jsx(OverlayCloseButton, { label: closeLabel, onClose: onClose })] }), children, footer] }) }));
|
|
18
|
-
}
|