Pure React Command Bar (#828)

This commit is contained in:
Steve Faulkner
2021-05-28 15:20:59 -05:00
committed by GitHub
parent 18ce8749ed
commit b875407d49
24 changed files with 93 additions and 211 deletions

View File

@@ -3,100 +3,71 @@
* If the component signals a change through the callback passed in the properties, it must render the React component when appropriate
* and update any knockout observables passed from the parent.
*/
import { CommandBar, ICommandBarItemProps } from "@fluentui/react";
import * as ko from "knockout";
import { CommandBar as FluentCommandBar, ICommandBarItemProps } from "@fluentui/react";
import * as React from "react";
import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
import create, { UseStore } from "zustand";
import { StyleConstants } from "../../../Common/Constants";
import * as ViewModels from "../../../Contracts/ViewModels";
import { userContext } from "../../../UserContext";
import { useObservable } from "../../../hooks/useObservable";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import Explorer from "../../Explorer";
import * as CommandBarComponentButtonFactory from "./CommandBarComponentButtonFactory";
import * as CommandBarUtil from "./CommandBarUtil";
export class CommandBarComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<number>;
public container: Explorer;
private tabsButtons: CommandButtonComponentProps[];
private isNotebookTabActive: ko.Computed<boolean>;
constructor(container: Explorer) {
this.container = container;
this.tabsButtons = [];
this.isNotebookTabActive = ko.computed(
() => container.tabsManager.activeTab()?.tabKind === ViewModels.CollectionTabKind.NotebookV2
);
// These are the parameters watched by the react binding that will trigger a renderComponent() if one of the ko mutates
const toWatch = [
container.isDatabaseNodeOrNoneSelected,
container.isDatabaseNodeSelected,
container.isNoneSelected,
container.isResourceTokenCollectionNodeSelected,
container.isHostedDataExplorerEnabled,
container.isSynapseLinkUpdating,
userContext?.databaseAccount,
this.isNotebookTabActive,
container.isServerlessEnabled,
];
ko.computed(() => ko.toJSON(toWatch)).subscribe(() => this.triggerRender());
this.parameters = ko.observable(Date.now());
}
public onUpdateTabsButtons(buttons: CommandButtonComponentProps[]): void {
this.tabsButtons = buttons;
this.triggerRender();
}
public renderComponent(): JSX.Element {
const backgroundColor = StyleConstants.BaseLight;
const staticButtons = CommandBarComponentButtonFactory.createStaticCommandBarButtons(this.container);
const contextButtons = (this.tabsButtons || []).concat(
CommandBarComponentButtonFactory.createContextCommandBarButtons(this.container)
);
const controlButtons = CommandBarComponentButtonFactory.createControlCommandBarButtons(this.container);
const uiFabricStaticButtons = CommandBarUtil.convertButton(staticButtons, backgroundColor);
if (this.tabsButtons && this.tabsButtons.length > 0) {
uiFabricStaticButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
}
const uiFabricTabsButtons: ICommandBarItemProps[] = CommandBarUtil.convertButton(contextButtons, backgroundColor);
if (uiFabricTabsButtons.length > 0) {
uiFabricStaticButtons.push(CommandBarUtil.createDivider("commandBarDivider"));
}
const uiFabricControlButtons = CommandBarUtil.convertButton(controlButtons, backgroundColor);
uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
if (this.isNotebookTabActive()) {
uiFabricControlButtons.unshift(
CommandBarUtil.createMemoryTracker("memoryTracker", this.container.memoryUsageInfo)
);
}
return (
<React.Fragment>
<div className="commandBarContainer">
<CommandBar
ariaLabel="Use left and right arrow keys to navigate between commands"
items={uiFabricStaticButtons.concat(uiFabricTabsButtons)}
farItems={uiFabricControlButtons}
styles={{
root: { backgroundColor: backgroundColor },
}}
overflowButtonProps={{ ariaLabel: "More commands" }}
/>
</div>
</React.Fragment>
);
}
private triggerRender() {
window.requestAnimationFrame(() => this.parameters(Date.now()));
}
interface Props {
container: Explorer;
}
export interface CommandBarStore {
contextButtons: CommandButtonComponentProps[];
setContextButtons: (contextButtons: CommandButtonComponentProps[]) => void;
}
export const useCommandBar: UseStore<CommandBarStore> = create((set) => ({
contextButtons: [],
setContextButtons: (contextButtons: CommandButtonComponentProps[]) => set((state) => ({ ...state, contextButtons })),
}));
export const CommandBar: React.FC<Props> = ({ container }: Props) => {
useObservable(container.selectedNode);
const buttons = useCommandBar((state) => state.contextButtons);
const backgroundColor = StyleConstants.BaseLight;
const staticButtons = CommandBarComponentButtonFactory.createStaticCommandBarButtons(container);
const contextButtons = (buttons || []).concat(
CommandBarComponentButtonFactory.createContextCommandBarButtons(container)
);
const controlButtons = CommandBarComponentButtonFactory.createControlCommandBarButtons(container);
const uiFabricStaticButtons = CommandBarUtil.convertButton(staticButtons, backgroundColor);
if (buttons && buttons.length > 0) {
uiFabricStaticButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
}
const uiFabricTabsButtons: ICommandBarItemProps[] = CommandBarUtil.convertButton(contextButtons, backgroundColor);
if (uiFabricTabsButtons.length > 0) {
uiFabricStaticButtons.push(CommandBarUtil.createDivider("commandBarDivider"));
}
const uiFabricControlButtons = CommandBarUtil.convertButton(controlButtons, backgroundColor);
uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
if (container.tabsManager.activeTab()?.tabKind === ViewModels.CollectionTabKind.NotebookV2) {
uiFabricControlButtons.unshift(CommandBarUtil.createMemoryTracker("memoryTracker", container.memoryUsageInfo));
}
return (
<div className="commandBarContainer">
<FluentCommandBar
ariaLabel="Use left and right arrow keys to navigate between commands"
items={uiFabricStaticButtons.concat(uiFabricTabsButtons)}
farItems={uiFabricControlButtons}
styles={{
root: { backgroundColor: backgroundColor },
}}
overflowButtonProps={{ ariaLabel: "More commands" }}
/>
</div>
);
};