@harborclient/sdk 1.6.2 → 1.6.4
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/CHANGELOG.md +10 -0
- package/dist/components/Button/index.d.ts +4 -0
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +22 -8
- package/dist/components/CodeEditor/index.d.ts +6 -3
- package/dist/components/CodeEditor/index.d.ts.map +1 -1
- package/dist/components/CodeEditor/index.js +10 -3
- package/dist/components/RowActionsMenu/index.d.ts +7 -1
- package/dist/components/RowActionsMenu/index.d.ts.map +1 -1
- package/dist/components/RowActionsMenu/index.js +3 -2
- package/dist/components/Sidebar/index.d.ts +10 -2
- package/dist/components/Sidebar/index.d.ts.map +1 -1
- package/dist/components/Sidebar/index.js +2 -2
- package/dist/components/SidebarItem/SidebarEnvironmentItem.d.ts +5 -1
- package/dist/components/SidebarItem/SidebarEnvironmentItem.d.ts.map +1 -1
- package/dist/components/SidebarItem/SidebarEnvironmentItem.js +6 -6
- package/dist/components/SidebarItem/SidebarItem.d.ts +10 -1
- package/dist/components/SidebarItem/SidebarItem.d.ts.map +1 -1
- package/dist/components/SidebarItem/SidebarItem.js +3 -3
- package/dist/components/SidebarItem/SidebarListbox.d.ts +3 -1
- package/dist/components/SidebarItem/SidebarListbox.d.ts.map +1 -1
- package/dist/components/SidebarItem/SidebarListbox.js +49 -2
- package/dist/components/SidebarItem/SidebarTree.d.ts +2 -0
- package/dist/components/SidebarItem/SidebarTree.d.ts.map +1 -1
- package/dist/components/SidebarItem/SidebarTree.js +48 -1
- package/dist/components/SidebarItem/SortableSidebarItem.d.ts +15 -5
- package/dist/components/SidebarItem/SortableSidebarItem.d.ts.map +1 -1
- package/dist/components/SidebarItem/SortableSidebarItem.js +8 -7
- package/dist/components/SidebarItem/index.d.ts +1 -0
- package/dist/components/SidebarItem/index.d.ts.map +1 -1
- package/dist/components/SidebarItem/index.js +1 -0
- package/dist/components/SidebarItem/sidebarCompositeNavigation.d.ts +100 -0
- package/dist/components/SidebarItem/sidebarCompositeNavigation.d.ts.map +1 -0
- package/dist/components/SidebarItem/sidebarCompositeNavigation.js +246 -0
- package/dist/components/SidebarItem/sidebarListOption.d.ts +4 -0
- package/dist/components/SidebarItem/sidebarListOption.d.ts.map +1 -1
- package/dist/components/SidebarItem/sidebarListOption.js +11 -0
- package/dist/components/SidebarRail/SidebarRailItem.d.ts +1 -1
- package/dist/components/SidebarRail/SidebarRailItem.d.ts.map +1 -1
- package/dist/components/SidebarRail/SidebarRailItem.js +2 -1
- package/dist/components/SidebarRail/focusSidebarRailPanel.d.ts +31 -0
- package/dist/components/SidebarRail/focusSidebarRailPanel.d.ts.map +1 -0
- package/dist/components/SidebarRail/focusSidebarRailPanel.js +73 -0
- package/dist/components/SidebarRail/index.d.ts +21 -5
- package/dist/components/SidebarRail/index.d.ts.map +1 -1
- package/dist/components/SidebarRail/index.js +62 -7
- package/dist/components/SidebarSection/SectionItem.d.ts.map +1 -1
- package/dist/components/SidebarSection/SectionItem.js +3 -1
- package/dist/components/SidebarSection/index.d.ts.map +1 -1
- package/dist/components/SidebarSection/index.js +1 -1
- package/dist/components/index.d.ts +3 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -1
- package/dist/styles.css +16 -0
- package/dist/ui/codeEditorSettings.d.ts +1 -1
- package/dist/ui/codeEditorSettings.js +2 -2
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SortableSidebarItem.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarItem/SortableSidebarItem.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAItF,UAAU,KAAK;IACb;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,EAAE,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IAElB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAE5D;;OAEG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACnD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CACzD;AAED
|
|
1
|
+
{"version":3,"file":"SortableSidebarItem.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarItem/SortableSidebarItem.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAItF,UAAU,KAAK;IACb;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,EAAE,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IAElB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExC;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAE5D;;OAEG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACnD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CACzD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,EAAE,EACF,EAAE,EAAE,SAAiB,EACrB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,IAAI,EACJ,eAAe,EAAE,YAAY,EAC7B,YAAY,EAAE,SAAS,EACvB,eAAe,EAAE,YAAY,EAC7B,eAAe,EAAE,YAAY,EAC7B,YAAY,EAAE,SAAS,EACvB,cAAc,EAAE,WAAW,EAC3B,eAAe,EAAE,YAAY,EAC7B,QAAQ,EACR,OAAO,EACP,aAAa,EACb,SAAS,EACV,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CA2ErB"}
|
|
@@ -6,12 +6,13 @@ import { FaIcon } from '../FaIcon/index.js';
|
|
|
6
6
|
import { SIDEBAR_DRAG_HANDLE_CLASS } from './sidebarItemClasses.js';
|
|
7
7
|
/**
|
|
8
8
|
* Wraps a sidebar row with dnd-kit sortable drag behavior. Reordering is activated
|
|
9
|
-
* from a dedicated trailing grip handle
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* non-sortable sections such as Runs
|
|
9
|
+
* from a dedicated trailing grip handle (mouse / programmatic focus). The handle is
|
|
10
|
+
* removed from Tab order so listbox/tree composites keep a single Tab stop per row;
|
|
11
|
+
* keyboard users reorder via Move up/down in the row actions menu. Keeping the handle
|
|
12
|
+
* after the label keeps leading content flush with non-sortable sections such as Runs
|
|
13
|
+
* and History.
|
|
13
14
|
*/
|
|
14
|
-
export function SortableSidebarItem({ id, as: Container = 'div', className, dragHandleLabel, children, trailing, disabled = false, onRowContextMenu, role, 'aria-selected': ariaSelected, 'aria-label': ariaLabel, 'aria-expanded': ariaExpanded, 'aria-controls': ariaControls, 'aria-level': ariaLevel, 'aria-setsize': ariaSetSize, 'aria-posinset': ariaPosInSet, tabIndex, onClick, onDoubleClick, onKeyDown }) {
|
|
15
|
+
export function SortableSidebarItem({ id, as: Container = 'div', className, dragHandleLabel, children, trailing, subtree, disabled = false, dataAttributes, onRowContextMenu, role, 'aria-selected': ariaSelected, 'aria-label': ariaLabel, 'aria-expanded': ariaExpanded, 'aria-controls': ariaControls, 'aria-level': ariaLevel, 'aria-setsize': ariaSetSize, 'aria-posinset': ariaPosInSet, tabIndex, onClick, onDoubleClick, onKeyDown }) {
|
|
15
16
|
const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({ id, disabled });
|
|
16
17
|
const isInteractiveRow = role === 'option' || role === 'treeitem';
|
|
17
18
|
const interactiveProps = isInteractiveRow
|
|
@@ -31,12 +32,12 @@ export function SortableSidebarItem({ id, as: Container = 'div', className, drag
|
|
|
31
32
|
}
|
|
32
33
|
: {};
|
|
33
34
|
if (disabled) {
|
|
34
|
-
return (_jsxs(Container, { className: className, onContextMenu: onRowContextMenu, ...interactiveProps, children: [children, trailing] }));
|
|
35
|
+
return (_jsxs(Container, { className: className, onContextMenu: onRowContextMenu, ...dataAttributes, ...interactiveProps, children: [children, trailing, subtree] }));
|
|
35
36
|
}
|
|
36
37
|
const style = {
|
|
37
38
|
transform: CSS.Transform.toString(transform),
|
|
38
39
|
transition: isDragging ? transition : undefined,
|
|
39
40
|
opacity: isDragging ? 0.45 : undefined
|
|
40
41
|
};
|
|
41
|
-
return (_jsxs(Container, { ref: setNodeRef, style: style, className: className, onContextMenu: onRowContextMenu, ...interactiveProps, children: [children, _jsx("button", { type: "button", ref: setActivatorNodeRef, className: SIDEBAR_DRAG_HANDLE_CLASS, "aria-label": dragHandleLabel, ...attributes, ...listeners, children: _jsx(FaIcon, { icon: faGripVertical, className: "h-2.5 w-2.5", "aria-hidden": true }) }), trailing] }));
|
|
42
|
+
return (_jsxs(Container, { ref: setNodeRef, style: style, className: className, onContextMenu: onRowContextMenu, ...dataAttributes, ...interactiveProps, children: [children, _jsx("button", { type: "button", ref: setActivatorNodeRef, className: SIDEBAR_DRAG_HANDLE_CLASS, "aria-label": dragHandleLabel, ...attributes, ...listeners, tabIndex: -1, children: _jsx(FaIcon, { icon: faGripVertical, className: "h-2.5 w-2.5", "aria-hidden": true }) }), trailing, subtree] }));
|
|
42
43
|
}
|
|
@@ -4,6 +4,7 @@ export { SidebarList } from './SidebarList.js';
|
|
|
4
4
|
export { SidebarTree } from './SidebarTree.js';
|
|
5
5
|
export { SidebarTreeGroup } from './SidebarTreeGroup.js';
|
|
6
6
|
export { handleSidebarOptionKeyDown } from './sidebarListOption.js';
|
|
7
|
+
export { focusSidebarCompositeItem, handleSidebarCompositeContainerKeyDown, handleSidebarCompositeFocusIn, isSidebarRowActionsMenuKey, openSidebarRowActionsMenu, querySidebarCompositeItems, resolveSidebarCompositeFocusIndex, setSidebarCompositeRovingTabIndex } from './sidebarCompositeNavigation.js';
|
|
7
8
|
export { SortableSidebarItem } from './SortableSidebarItem.js';
|
|
8
9
|
export { stopSortableDragPointerDown } from './stopSortableDragPointerDown.js';
|
|
9
10
|
export { SidebarMarkerDot } from './SidebarMarkerDot.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarItem/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,4BAA4B,EAC5B,0BAA0B,EAC1B,0BAA0B,EAC1B,kCAAkC,EACnC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarItem/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EACL,yBAAyB,EACzB,sCAAsC,EACtC,6BAA6B,EAC7B,0BAA0B,EAC1B,yBAAyB,EACzB,0BAA0B,EAC1B,iCAAiC,EACjC,iCAAiC,EAClC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EACL,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,4BAA4B,EAC5B,0BAA0B,EAC1B,0BAA0B,EAC1B,kCAAkC,EACnC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -4,6 +4,7 @@ export { SidebarList } from './SidebarList.js';
|
|
|
4
4
|
export { SidebarTree } from './SidebarTree.js';
|
|
5
5
|
export { SidebarTreeGroup } from './SidebarTreeGroup.js';
|
|
6
6
|
export { handleSidebarOptionKeyDown } from './sidebarListOption.js';
|
|
7
|
+
export { focusSidebarCompositeItem, handleSidebarCompositeContainerKeyDown, handleSidebarCompositeFocusIn, isSidebarRowActionsMenuKey, openSidebarRowActionsMenu, querySidebarCompositeItems, resolveSidebarCompositeFocusIndex, setSidebarCompositeRovingTabIndex } from './sidebarCompositeNavigation.js';
|
|
7
8
|
export { SortableSidebarItem } from './SortableSidebarItem.js';
|
|
8
9
|
export { stopSortableDragPointerDown } from './stopSortableDragPointerDown.js';
|
|
9
10
|
export { SidebarMarkerDot } from './SidebarMarkerDot.js';
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { FocusEvent, KeyboardEvent as ReactKeyboardEvent } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Role used by flat sidebar item lists.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SIDEBAR_LISTBOX_ITEM_ROLE = "option";
|
|
6
|
+
/**
|
|
7
|
+
* Role used by nested sidebar item trees.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SIDEBAR_TREE_ITEM_ROLE = "treeitem";
|
|
10
|
+
/**
|
|
11
|
+
* Collects composite items under a listbox or tree root in DOM order.
|
|
12
|
+
*
|
|
13
|
+
* @param root - Listbox or tree element.
|
|
14
|
+
* @param role - Item role to collect (`option` or `treeitem`).
|
|
15
|
+
* @returns Focusable item elements in document order.
|
|
16
|
+
*/
|
|
17
|
+
export declare function querySidebarCompositeItems(root: ParentNode, role: typeof SIDEBAR_LISTBOX_ITEM_ROLE | typeof SIDEBAR_TREE_ITEM_ROLE): HTMLElement[];
|
|
18
|
+
/**
|
|
19
|
+
* Updates roving tabindex so exactly one composite item is a Tab stop.
|
|
20
|
+
*
|
|
21
|
+
* @param items - Composite items in order.
|
|
22
|
+
* @param focusIndex - Index that should receive `tabIndex={0}`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function setSidebarCompositeRovingTabIndex(items: readonly HTMLElement[], focusIndex: number): void;
|
|
25
|
+
/**
|
|
26
|
+
* Resolves the index of the focused item, falling back to the current Tab stop.
|
|
27
|
+
*
|
|
28
|
+
* @param items - Composite items in order.
|
|
29
|
+
* @param activeElement - Document active element, if any.
|
|
30
|
+
* @returns Index into `items`, or `-1` when empty.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveSidebarCompositeFocusIndex(items: readonly HTMLElement[], activeElement: Element | null): number;
|
|
33
|
+
/**
|
|
34
|
+
* Focuses a composite item and makes it the sole Tab stop.
|
|
35
|
+
*
|
|
36
|
+
* @param items - Composite items in order.
|
|
37
|
+
* @param index - Target index.
|
|
38
|
+
*/
|
|
39
|
+
export declare function focusSidebarCompositeItem(items: readonly HTMLElement[], index: number): void;
|
|
40
|
+
/**
|
|
41
|
+
* Finds the expand/collapse control inside a treeitem, if present.
|
|
42
|
+
*
|
|
43
|
+
* @param item - Treeitem element.
|
|
44
|
+
* @returns Chevron button, or null when the item is a leaf.
|
|
45
|
+
*/
|
|
46
|
+
export declare function findSidebarTreeExpandButton(item: HTMLElement): HTMLButtonElement | null;
|
|
47
|
+
/**
|
|
48
|
+
* Whether the key event should open the focused row's actions menu.
|
|
49
|
+
*
|
|
50
|
+
* @param event - Keyboard event from a composite item or container.
|
|
51
|
+
* @returns True for Shift+F10 or the ContextMenu key.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isSidebarRowActionsMenuKey(event: Pick<KeyboardEvent | ReactKeyboardEvent, 'key' | 'shiftKey'>): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Opens the row actions menu trigger inside a sidebar row, if present.
|
|
56
|
+
*
|
|
57
|
+
* @param row - Focused option or treeitem element.
|
|
58
|
+
* @returns True when a trigger was found and activated.
|
|
59
|
+
*/
|
|
60
|
+
export declare function openSidebarRowActionsMenu(row: HTMLElement): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Handles ArrowLeft / ArrowRight expand/collapse for a focused treeitem.
|
|
63
|
+
*
|
|
64
|
+
* @param event - Keydown event.
|
|
65
|
+
* @param item - Focused treeitem.
|
|
66
|
+
* @param items - All visible treeitems under the tree.
|
|
67
|
+
* @param focusIndex - Index of `item` in `items`.
|
|
68
|
+
* @returns True when the key was handled.
|
|
69
|
+
*/
|
|
70
|
+
export declare function handleSidebarTreeHorizontalKey(event: KeyboardEvent | ReactKeyboardEvent, item: HTMLElement, items: readonly HTMLElement[], focusIndex: number): boolean;
|
|
71
|
+
type CompositeRole = typeof SIDEBAR_LISTBOX_ITEM_ROLE | typeof SIDEBAR_TREE_ITEM_ROLE;
|
|
72
|
+
/**
|
|
73
|
+
* Handles vertical arrow / Home / End navigation inside a sidebar composite.
|
|
74
|
+
*
|
|
75
|
+
* @param event - Keydown from the composite container or an item.
|
|
76
|
+
* @param root - Listbox or tree element.
|
|
77
|
+
* @param role - Item role under `root`.
|
|
78
|
+
* @returns True when focus moved.
|
|
79
|
+
*/
|
|
80
|
+
export declare function handleSidebarCompositeVerticalKey(event: KeyboardEvent | ReactKeyboardEvent, root: HTMLElement, role: CompositeRole): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Container keydown handler for {@link SidebarListbox} / {@link SidebarTree}.
|
|
83
|
+
*
|
|
84
|
+
* Moves focus among items with arrows, opens row actions with Shift+F10 /
|
|
85
|
+
* ContextMenu, and leaves Enter/Space activation to the focused item.
|
|
86
|
+
*
|
|
87
|
+
* @param event - React keydown from the composite root.
|
|
88
|
+
* @param role - Item role managed by this composite.
|
|
89
|
+
*/
|
|
90
|
+
export declare function handleSidebarCompositeContainerKeyDown(event: ReactKeyboardEvent<HTMLElement>, role: CompositeRole): void;
|
|
91
|
+
/**
|
|
92
|
+
* Keeps roving tabindex aligned when focus moves inside the composite via pointer
|
|
93
|
+
* or programmatic focus.
|
|
94
|
+
*
|
|
95
|
+
* @param event - Focusin from the composite root.
|
|
96
|
+
* @param role - Item role managed by this composite.
|
|
97
|
+
*/
|
|
98
|
+
export declare function handleSidebarCompositeFocusIn(event: FocusEvent<HTMLElement>, role: CompositeRole): void;
|
|
99
|
+
export {};
|
|
100
|
+
//# sourceMappingURL=sidebarCompositeNavigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebarCompositeNavigation.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarItem/sidebarCompositeNavigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,IAAI,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAG7E;;GAEG;AACH,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,sBAAsB,aAAa,CAAC;AAEjD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,OAAO,yBAAyB,GAAG,OAAO,sBAAsB,GACrE,WAAW,EAAE,CASf;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,UAAU,EAAE,MAAM,GACjB,IAAI,CAIN;AAED;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,aAAa,EAAE,OAAO,GAAG,IAAI,GAC5B,MAAM,CAkBR;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAW5F;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,WAAW,GAAG,iBAAiB,GAAG,IAAI,CAIvF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,IAAI,CAAC,aAAa,GAAG,kBAAkB,EAAE,KAAK,GAAG,UAAU,CAAC,GAClE,OAAO,CAMT;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAWnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,aAAa,GAAG,kBAAkB,EACzC,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,UAAU,EAAE,MAAM,GACjB,OAAO,CAsDT;AAED,KAAK,aAAa,GAAG,OAAO,yBAAyB,GAAG,OAAO,sBAAsB,CAAC;AAEtF;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,aAAa,GAAG,kBAAkB,EACzC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CA2BT;AAED;;;;;;;;GAQG;AACH,wBAAgB,sCAAsC,CACpD,KAAK,EAAE,kBAAkB,CAAC,WAAW,CAAC,EACtC,IAAI,EAAE,aAAa,GAClB,IAAI,CAuBN;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,EAC9B,IAAI,EAAE,aAAa,GAClB,IAAI,CAaN"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { resolveTabListKeyAction } from '../utils.js';
|
|
2
|
+
/**
|
|
3
|
+
* Role used by flat sidebar item lists.
|
|
4
|
+
*/
|
|
5
|
+
export const SIDEBAR_LISTBOX_ITEM_ROLE = 'option';
|
|
6
|
+
/**
|
|
7
|
+
* Role used by nested sidebar item trees.
|
|
8
|
+
*/
|
|
9
|
+
export const SIDEBAR_TREE_ITEM_ROLE = 'treeitem';
|
|
10
|
+
/**
|
|
11
|
+
* Collects composite items under a listbox or tree root in DOM order.
|
|
12
|
+
*
|
|
13
|
+
* @param root - Listbox or tree element.
|
|
14
|
+
* @param role - Item role to collect (`option` or `treeitem`).
|
|
15
|
+
* @returns Focusable item elements in document order.
|
|
16
|
+
*/
|
|
17
|
+
export function querySidebarCompositeItems(root, role) {
|
|
18
|
+
return Array.from(root.querySelectorAll(`[role="${role}"]`)).filter((element) => {
|
|
19
|
+
// Nested listboxes/trees can appear in plugin hosts; keep items local to this root.
|
|
20
|
+
const owner = role === SIDEBAR_LISTBOX_ITEM_ROLE
|
|
21
|
+
? element.closest('[role="listbox"]')
|
|
22
|
+
: element.closest('[role="tree"]');
|
|
23
|
+
return owner === root || (owner == null && root.contains(element));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Updates roving tabindex so exactly one composite item is a Tab stop.
|
|
28
|
+
*
|
|
29
|
+
* @param items - Composite items in order.
|
|
30
|
+
* @param focusIndex - Index that should receive `tabIndex={0}`.
|
|
31
|
+
*/
|
|
32
|
+
export function setSidebarCompositeRovingTabIndex(items, focusIndex) {
|
|
33
|
+
items.forEach((item, index) => {
|
|
34
|
+
item.tabIndex = index === focusIndex ? 0 : -1;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the index of the focused item, falling back to the current Tab stop.
|
|
39
|
+
*
|
|
40
|
+
* @param items - Composite items in order.
|
|
41
|
+
* @param activeElement - Document active element, if any.
|
|
42
|
+
* @returns Index into `items`, or `-1` when empty.
|
|
43
|
+
*/
|
|
44
|
+
export function resolveSidebarCompositeFocusIndex(items, activeElement) {
|
|
45
|
+
if (items.length === 0) {
|
|
46
|
+
return -1;
|
|
47
|
+
}
|
|
48
|
+
const focusedIndex = items.findIndex((item) => item === activeElement || item.contains(activeElement));
|
|
49
|
+
if (focusedIndex >= 0) {
|
|
50
|
+
return focusedIndex;
|
|
51
|
+
}
|
|
52
|
+
const tabStopIndex = items.findIndex((item) => item.tabIndex === 0);
|
|
53
|
+
if (tabStopIndex >= 0) {
|
|
54
|
+
return tabStopIndex;
|
|
55
|
+
}
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Focuses a composite item and makes it the sole Tab stop.
|
|
60
|
+
*
|
|
61
|
+
* @param items - Composite items in order.
|
|
62
|
+
* @param index - Target index.
|
|
63
|
+
*/
|
|
64
|
+
export function focusSidebarCompositeItem(items, index) {
|
|
65
|
+
const target = items[index];
|
|
66
|
+
if (target == null) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
setSidebarCompositeRovingTabIndex(items, index);
|
|
70
|
+
target.focus();
|
|
71
|
+
if (typeof target.scrollIntoView === 'function') {
|
|
72
|
+
target.scrollIntoView({ block: 'nearest' });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Finds the expand/collapse control inside a treeitem, if present.
|
|
77
|
+
*
|
|
78
|
+
* @param item - Treeitem element.
|
|
79
|
+
* @returns Chevron button, or null when the item is a leaf.
|
|
80
|
+
*/
|
|
81
|
+
export function findSidebarTreeExpandButton(item) {
|
|
82
|
+
return item.querySelector('button[aria-expanded], button[aria-label^="Expand"], button[aria-label^="Collapse"]');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Whether the key event should open the focused row's actions menu.
|
|
86
|
+
*
|
|
87
|
+
* @param event - Keyboard event from a composite item or container.
|
|
88
|
+
* @returns True for Shift+F10 or the ContextMenu key.
|
|
89
|
+
*/
|
|
90
|
+
export function isSidebarRowActionsMenuKey(event) {
|
|
91
|
+
if (event.key === 'ContextMenu') {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
return event.key === 'F10' && event.shiftKey;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Opens the row actions menu trigger inside a sidebar row, if present.
|
|
98
|
+
*
|
|
99
|
+
* @param row - Focused option or treeitem element.
|
|
100
|
+
* @returns True when a trigger was found and activated.
|
|
101
|
+
*/
|
|
102
|
+
export function openSidebarRowActionsMenu(row) {
|
|
103
|
+
const trigger = row.querySelector('.hc-row-actions-menu-trigger') ??
|
|
104
|
+
row.querySelector('[data-sidebar-actions] button');
|
|
105
|
+
if (trigger == null || trigger.disabled) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
trigger.click();
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Handles ArrowLeft / ArrowRight expand/collapse for a focused treeitem.
|
|
113
|
+
*
|
|
114
|
+
* @param event - Keydown event.
|
|
115
|
+
* @param item - Focused treeitem.
|
|
116
|
+
* @param items - All visible treeitems under the tree.
|
|
117
|
+
* @param focusIndex - Index of `item` in `items`.
|
|
118
|
+
* @returns True when the key was handled.
|
|
119
|
+
*/
|
|
120
|
+
export function handleSidebarTreeHorizontalKey(event, item, items, focusIndex) {
|
|
121
|
+
const expanded = item.getAttribute('aria-expanded');
|
|
122
|
+
if (event.key === 'ArrowRight') {
|
|
123
|
+
if (expanded === 'false') {
|
|
124
|
+
const expandButton = findSidebarTreeExpandButton(item);
|
|
125
|
+
if (expandButton != null) {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
expandButton.click();
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (expanded === 'true') {
|
|
132
|
+
const next = items[focusIndex + 1];
|
|
133
|
+
if (next != null) {
|
|
134
|
+
event.preventDefault();
|
|
135
|
+
focusSidebarCompositeItem(items, focusIndex + 1);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (event.key === 'ArrowLeft') {
|
|
142
|
+
if (expanded === 'true') {
|
|
143
|
+
const collapseButton = findSidebarTreeExpandButton(item);
|
|
144
|
+
if (collapseButton != null) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
collapseButton.click();
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const level = Number(item.getAttribute('aria-level') ?? '1');
|
|
151
|
+
for (let index = focusIndex - 1; index >= 0; index -= 1) {
|
|
152
|
+
const candidate = items[index];
|
|
153
|
+
if (candidate == null) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const candidateLevel = Number(candidate.getAttribute('aria-level') ?? '1');
|
|
157
|
+
if (candidateLevel < level) {
|
|
158
|
+
event.preventDefault();
|
|
159
|
+
focusSidebarCompositeItem(items, index);
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Handles vertical arrow / Home / End navigation inside a sidebar composite.
|
|
169
|
+
*
|
|
170
|
+
* @param event - Keydown from the composite container or an item.
|
|
171
|
+
* @param root - Listbox or tree element.
|
|
172
|
+
* @param role - Item role under `root`.
|
|
173
|
+
* @returns True when focus moved.
|
|
174
|
+
*/
|
|
175
|
+
export function handleSidebarCompositeVerticalKey(event, root, role) {
|
|
176
|
+
const key = event.key;
|
|
177
|
+
// Listbox and tree both navigate vertically with Up/Down/Home/End.
|
|
178
|
+
if (key !== 'ArrowUp' && key !== 'ArrowDown' && key !== 'Home' && key !== 'End') {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const items = querySidebarCompositeItems(root, role);
|
|
182
|
+
if (items.length === 0) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
const currentIndex = resolveSidebarCompositeFocusIndex(items, document.activeElement);
|
|
186
|
+
if (currentIndex < 0) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
// Map Home/End/Up/Down through the shared tablist helper (Left/Right also map there,
|
|
190
|
+
// but listbox never reaches this with those keys).
|
|
191
|
+
const nextIndex = resolveTabListKeyAction(key, currentIndex, items.length);
|
|
192
|
+
if (nextIndex == null || nextIndex === currentIndex) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
event.preventDefault();
|
|
196
|
+
focusSidebarCompositeItem(items, nextIndex);
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Container keydown handler for {@link SidebarListbox} / {@link SidebarTree}.
|
|
201
|
+
*
|
|
202
|
+
* Moves focus among items with arrows, opens row actions with Shift+F10 /
|
|
203
|
+
* ContextMenu, and leaves Enter/Space activation to the focused item.
|
|
204
|
+
*
|
|
205
|
+
* @param event - React keydown from the composite root.
|
|
206
|
+
* @param role - Item role managed by this composite.
|
|
207
|
+
*/
|
|
208
|
+
export function handleSidebarCompositeContainerKeyDown(event, role) {
|
|
209
|
+
if (event.defaultPrevented) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const root = event.currentTarget;
|
|
213
|
+
const items = querySidebarCompositeItems(root, role);
|
|
214
|
+
const focusIndex = resolveSidebarCompositeFocusIndex(items, document.activeElement);
|
|
215
|
+
const focusedItem = focusIndex >= 0 ? items[focusIndex] : null;
|
|
216
|
+
if (focusedItem != null && isSidebarRowActionsMenuKey(event)) {
|
|
217
|
+
event.preventDefault();
|
|
218
|
+
openSidebarRowActionsMenu(focusedItem);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (role === SIDEBAR_TREE_ITEM_ROLE && focusedItem != null) {
|
|
222
|
+
if (handleSidebarTreeHorizontalKey(event, focusedItem, items, focusIndex)) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
handleSidebarCompositeVerticalKey(event, root, role);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Keeps roving tabindex aligned when focus moves inside the composite via pointer
|
|
230
|
+
* or programmatic focus.
|
|
231
|
+
*
|
|
232
|
+
* @param event - Focusin from the composite root.
|
|
233
|
+
* @param role - Item role managed by this composite.
|
|
234
|
+
*/
|
|
235
|
+
export function handleSidebarCompositeFocusIn(event, role) {
|
|
236
|
+
const root = event.currentTarget;
|
|
237
|
+
const items = querySidebarCompositeItems(root, role);
|
|
238
|
+
if (items.length === 0) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const focusIndex = resolveSidebarCompositeFocusIndex(items, event.target);
|
|
242
|
+
if (focusIndex < 0) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
setSidebarCompositeRovingTabIndex(items, focusIndex);
|
|
246
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { KeyboardEvent } from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* Activates a listbox option on Enter or Space, matching native button behavior.
|
|
4
|
+
* Opens the row actions menu on Shift+F10 / ContextMenu when a trigger is present.
|
|
5
|
+
*
|
|
6
|
+
* @param event - Keydown from the option or treeitem.
|
|
7
|
+
* @param onActivate - Called for Enter / Space activation.
|
|
4
8
|
*/
|
|
5
9
|
export declare function handleSidebarOptionKeyDown(event: KeyboardEvent<HTMLElement>, onActivate?: (event: KeyboardEvent<HTMLElement>) => void): void;
|
|
6
10
|
//# sourceMappingURL=sidebarListOption.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebarListOption.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarItem/sidebarListOption.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"sidebarListOption.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarItem/sidebarListOption.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAM3C;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,EACjC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,GACvD,IAAI,CAcN"}
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
import { isSidebarRowActionsMenuKey, openSidebarRowActionsMenu } from './sidebarCompositeNavigation.js';
|
|
1
2
|
/**
|
|
2
3
|
* Activates a listbox option on Enter or Space, matching native button behavior.
|
|
4
|
+
* Opens the row actions menu on Shift+F10 / ContextMenu when a trigger is present.
|
|
5
|
+
*
|
|
6
|
+
* @param event - Keydown from the option or treeitem.
|
|
7
|
+
* @param onActivate - Called for Enter / Space activation.
|
|
3
8
|
*/
|
|
4
9
|
export function handleSidebarOptionKeyDown(event, onActivate) {
|
|
10
|
+
if (isSidebarRowActionsMenuKey(event)) {
|
|
11
|
+
if (openSidebarRowActionsMenu(event.currentTarget)) {
|
|
12
|
+
event.preventDefault();
|
|
13
|
+
}
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
5
16
|
if (event.key !== 'Enter' && event.key !== ' ') {
|
|
6
17
|
return;
|
|
7
18
|
}
|
|
@@ -52,7 +52,7 @@ interface Props {
|
|
|
52
52
|
*/
|
|
53
53
|
onSelect: () => void;
|
|
54
54
|
/**
|
|
55
|
-
* Keyboard handler for tablist arrow-key navigation.
|
|
55
|
+
* Keyboard handler for tablist arrow-key navigation and panel entry.
|
|
56
56
|
*/
|
|
57
57
|
onKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void;
|
|
58
58
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidebarRailItem.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarRail/SidebarRailItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SidebarRailItem.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarRail/SidebarRailItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAWrD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,cAAc,CAAC;IAErB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CACrC;AAED,UAAU,KAAK;IACb;;OAEG;IACH,IAAI,EAAE,mBAAmB,CAAC;IAE1B;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAE7D;;OAEG;IACH,SAAS,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC;CACpC;AA0ED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,SAAS,EACV,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAqDrB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
2
|
import { FaIcon } from '../FaIcon/index.js';
|
|
3
3
|
import { cn } from '../utils.js';
|
|
4
|
+
import { sidebarRailTabId } from './focusSidebarRailPanel.js';
|
|
4
5
|
/**
|
|
5
6
|
* Shared focus-visible outline for rail tabs (matches TabBar / segment chrome).
|
|
6
7
|
*/
|
|
@@ -75,5 +76,5 @@ export function SidebarRailItem({ item, active, expanded, tabIndex, panelId, onS
|
|
|
75
76
|
* left with a color-only cue and is not announced twice via aria-label.
|
|
76
77
|
*/
|
|
77
78
|
const ariaLabel = expanded ? undefined : accessibleName;
|
|
78
|
-
return (_jsx("div", { className: railItemSectionClasses(active), children: _jsxs("button", { type: "button", role: "tab", ref: buttonRef, className: railItemButtonClasses(active, expanded), title: item.label, tabIndex: tabIndex, "aria-label": ariaLabel, "aria-selected": active, "aria-controls": panelId, onClick: onSelect, onKeyDown: onKeyDown, children: [_jsxs("span", { className: "relative inline-flex shrink-0 items-center justify-center", children: [_jsx(FaIcon, { icon: item.icon, className: "hc-sidebar-rail-item-icon h-[22.5px]! w-[22.5px]!", "aria-hidden": true }), item.badge ? (_jsx("span", { className: cn('hc-sidebar-rail-item-badge absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full', railItemBadgeBackgroundClass(item.badgeVariant)), "aria-hidden": true })) : null] }), expanded ? (_jsx("span", { className: "hc-sidebar-rail-item-label min-w-0 truncate text-left", children: item.label })) : null, expanded && item.badge === true ? (_jsxs("span", { className: "sr-only", children: [", ", badgeStatusLabel] })) : null] }) }));
|
|
79
|
+
return (_jsx("div", { className: railItemSectionClasses(active), children: _jsxs("button", { type: "button", role: "tab", id: sidebarRailTabId(item.id), ref: buttonRef, className: railItemButtonClasses(active, expanded), title: item.label, tabIndex: tabIndex, "aria-label": ariaLabel, "aria-selected": active, "aria-controls": panelId, onClick: onSelect, onKeyDown: onKeyDown, children: [_jsxs("span", { className: "relative inline-flex shrink-0 items-center justify-center", children: [_jsx(FaIcon, { icon: item.icon, className: "hc-sidebar-rail-item-icon h-[22.5px]! w-[22.5px]!", "aria-hidden": true }), item.badge ? (_jsx("span", { className: cn('hc-sidebar-rail-item-badge absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full', railItemBadgeBackgroundClass(item.badgeVariant)), "aria-hidden": true })) : null] }), expanded ? (_jsx("span", { className: "hc-sidebar-rail-item-label min-w-0 truncate text-left", children: item.label })) : null, expanded && item.badge === true ? (_jsxs("span", { className: "sr-only", children: [", ", badgeStatusLabel] })) : null] }) }));
|
|
79
80
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the stable DOM id for a sidebar rail tab button.
|
|
3
|
+
*
|
|
4
|
+
* Used for `id` on the tab and `aria-labelledby` on the associated tabpanel.
|
|
5
|
+
*
|
|
6
|
+
* @param itemId - Rail item id from {@link SidebarRailItemData.id}.
|
|
7
|
+
* @returns Stable element id string.
|
|
8
|
+
*/
|
|
9
|
+
export declare function sidebarRailTabId(itemId: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Moves focus to the first visible focusable element inside a rail tab panel.
|
|
12
|
+
*
|
|
13
|
+
* Falls back to focusing the panel itself (making it programmatically focusable)
|
|
14
|
+
* when the panel has no interactive descendants yet — for example empty states
|
|
15
|
+
* or content still mounting after a mode change.
|
|
16
|
+
*
|
|
17
|
+
* @param panel - Tab panel element, or null when missing from the DOM.
|
|
18
|
+
* @returns True when focus moved into the panel or onto a descendant.
|
|
19
|
+
*/
|
|
20
|
+
export declare function focusSidebarRailPanel(panel: HTMLElement | null): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Returns focus from a rail tab panel to the tab that labels it.
|
|
23
|
+
*
|
|
24
|
+
* Skips CodeMirror editors so Arrow keys keep editing text. Used when the
|
|
25
|
+
* directional key opposite the panel-entry key is pressed inside the panel.
|
|
26
|
+
*
|
|
27
|
+
* @param panel - Tab panel that currently contains focus.
|
|
28
|
+
* @returns True when focus moved back to the owning tab.
|
|
29
|
+
*/
|
|
30
|
+
export declare function focusSidebarRailTabFromPanel(panel: HTMLElement): boolean;
|
|
31
|
+
//# sourceMappingURL=focusSidebarRailPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focusSidebarRailPanel.d.ts","sourceRoot":"","sources":["../../../src/components/SidebarRail/focusSidebarRailPanel.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CA+BxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAsBxE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { getFocusableElements } from '../useDialogFocus.js';
|
|
2
|
+
/**
|
|
3
|
+
* Builds the stable DOM id for a sidebar rail tab button.
|
|
4
|
+
*
|
|
5
|
+
* Used for `id` on the tab and `aria-labelledby` on the associated tabpanel.
|
|
6
|
+
*
|
|
7
|
+
* @param itemId - Rail item id from {@link SidebarRailItemData.id}.
|
|
8
|
+
* @returns Stable element id string.
|
|
9
|
+
*/
|
|
10
|
+
export function sidebarRailTabId(itemId) {
|
|
11
|
+
return `hc-sidebar-rail-tab-${itemId}`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Moves focus to the first visible focusable element inside a rail tab panel.
|
|
15
|
+
*
|
|
16
|
+
* Falls back to focusing the panel itself (making it programmatically focusable)
|
|
17
|
+
* when the panel has no interactive descendants yet — for example empty states
|
|
18
|
+
* or content still mounting after a mode change.
|
|
19
|
+
*
|
|
20
|
+
* @param panel - Tab panel element, or null when missing from the DOM.
|
|
21
|
+
* @returns True when focus moved into the panel or onto a descendant.
|
|
22
|
+
*/
|
|
23
|
+
export function focusSidebarRailPanel(panel) {
|
|
24
|
+
if (panel == null) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
let firstFocusable = getFocusableElements(panel)[0];
|
|
28
|
+
if (firstFocusable == null) {
|
|
29
|
+
const selector = 'button:not([disabled]), a[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
30
|
+
firstFocusable =
|
|
31
|
+
Array.from(panel.querySelectorAll(selector)).find((element) => !element.closest('[aria-hidden="true"]')) ?? undefined;
|
|
32
|
+
}
|
|
33
|
+
if (firstFocusable != null && typeof firstFocusable.focus === 'function') {
|
|
34
|
+
firstFocusable.focus();
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (typeof panel.focus !== 'function') {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (!panel.hasAttribute('tabindex')) {
|
|
41
|
+
panel.tabIndex = -1;
|
|
42
|
+
}
|
|
43
|
+
panel.focus();
|
|
44
|
+
return document.activeElement === panel;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Returns focus from a rail tab panel to the tab that labels it.
|
|
48
|
+
*
|
|
49
|
+
* Skips CodeMirror editors so Arrow keys keep editing text. Used when the
|
|
50
|
+
* directional key opposite the panel-entry key is pressed inside the panel.
|
|
51
|
+
*
|
|
52
|
+
* @param panel - Tab panel that currently contains focus.
|
|
53
|
+
* @returns True when focus moved back to the owning tab.
|
|
54
|
+
*/
|
|
55
|
+
export function focusSidebarRailTabFromPanel(panel) {
|
|
56
|
+
const active = document.activeElement;
|
|
57
|
+
if (!(active instanceof HTMLElement) || !panel.contains(active)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (active.closest('.cm-editor') != null) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const labelledBy = panel.getAttribute('aria-labelledby');
|
|
64
|
+
if (labelledBy == null || labelledBy === '') {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
const tab = document.getElementById(labelledBy);
|
|
68
|
+
if (!(tab instanceof HTMLElement) || typeof tab.focus !== 'function') {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
tab.focus();
|
|
72
|
+
return document.activeElement === tab;
|
|
73
|
+
}
|