mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
feat: CB-1236 federated authentication
This commit is contained in:
@@ -18,6 +18,9 @@ export const BASE_CONTAINERS_STYLES = composes(
|
||||
ColoredContainer {
|
||||
composes: theme-background-secondary theme-text-on-secondary from global;
|
||||
}
|
||||
GroupSubTitle {
|
||||
composes: theme-text-text-hint-on-light from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
Container, ColoredContainer, Group {
|
||||
@@ -137,6 +140,12 @@ export const BASE_CONTAINERS_STYLES = composes(
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
GroupSubTitle {
|
||||
composes: theme-typography--caption from global;
|
||||
display: block;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
GroupClose {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { filterLayoutFakeProps } from './filterLayoutFakeProps';
|
||||
import type { ILayoutSizeProps } from './ILayoutSizeProps';
|
||||
|
||||
export const GroupSubTitle: React.FC<ILayoutSizeProps & React.HTMLAttributes<HTMLHeadingElement>> = function GroupSubTitle(props) {
|
||||
const divProps = filterLayoutFakeProps(props);
|
||||
return <span {...divProps} />;
|
||||
};
|
||||
@@ -107,6 +107,7 @@ export * from './Containers/Container';
|
||||
export * from './Containers/Group';
|
||||
export * from './Containers/GroupClose';
|
||||
export * from './Containers/GroupItem';
|
||||
export * from './Containers/GroupSubTitle';
|
||||
export * from './Containers/GroupTitle';
|
||||
export * from './Containers/ColoredContainer';
|
||||
export * from './Containers/IContainerProps';
|
||||
|
||||
@@ -20,6 +20,7 @@ interface FocusOptions {
|
||||
|
||||
interface IState {
|
||||
focus: boolean;
|
||||
focusFirstChild: () => void;
|
||||
}
|
||||
|
||||
export function useFocus<T extends HTMLElement>({
|
||||
@@ -28,24 +29,45 @@ export function useFocus<T extends HTMLElement>({
|
||||
onBlur,
|
||||
}: FocusOptions): [React.RefObject<T>, IState] {
|
||||
const handlersRef = useObjectRef({ onFocus, onBlur });
|
||||
const reference = useRef<T>(null);
|
||||
// TODO: seems can be inconsistent when element changes
|
||||
const state = useObservableRef<IState>(
|
||||
() => ({ focus: false }),
|
||||
() => ({
|
||||
focus: false,
|
||||
focusFirstChild() {
|
||||
if (reference.current !== null && focusFirstChild) {
|
||||
const firstFocusable = reference.current
|
||||
.querySelectorAll<T>(`
|
||||
button:not([disabled=disabled]),
|
||||
[href],
|
||||
input:not([disabled=disabled],[readonly=readonly]),
|
||||
select:not([disabled=disabled],[readonly=readonly]),
|
||||
textarea:not([disabled=disabled],[readonly=readonly]),
|
||||
[tabndex]:not([tabndex="-1"])`);
|
||||
|
||||
let tabIndex = -1;
|
||||
let lastElement: T | undefined;
|
||||
|
||||
firstFocusable.forEach(element => {
|
||||
if (element.tabIndex > tabIndex) {
|
||||
lastElement = element;
|
||||
tabIndex = element.tabIndex;
|
||||
}
|
||||
});
|
||||
|
||||
if (lastElement) {
|
||||
lastElement.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
{ focus: observable.ref },
|
||||
false,
|
||||
'useFocus'
|
||||
);
|
||||
const reference = useRef<T>(null);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (reference.current !== null && focusFirstChild) {
|
||||
const firstFocusable = reference.current
|
||||
.querySelector<T>('button, [href], input, select, textarea, [tabndex]:not([tabndex="-1"])');
|
||||
|
||||
if (firstFocusable) {
|
||||
firstFocusable.focus();
|
||||
}
|
||||
}
|
||||
state.focusFirstChild();
|
||||
}, [focusFirstChild]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user