fix issues with tabs
This commit is contained in:
parent
b27abe928d
commit
addc6bfb11
14 changed files with 210 additions and 137 deletions
|
@ -31,24 +31,28 @@ const Root: ParentComponent<{ commands: CommandType[] }> = (props) => {
|
|||
},
|
||||
|
||||
execute<T extends any[] = any[]>(command: CommandType<T>, event: Event): boolean | undefined {
|
||||
const contexts = contextualArguments.get(command);
|
||||
const args = ((): T => {
|
||||
|
||||
if (contexts === undefined) {
|
||||
return;
|
||||
}
|
||||
const contexts = contextualArguments.get(command);
|
||||
|
||||
const element = event.composedPath().find(el => contexts.has(el));
|
||||
if (contexts === undefined) {
|
||||
return [] as any;
|
||||
}
|
||||
|
||||
if (element === undefined) {
|
||||
return;
|
||||
}
|
||||
const element = event.composedPath().find(el => contexts.has(el));
|
||||
|
||||
if (element === undefined) {
|
||||
return [] as any;
|
||||
}
|
||||
|
||||
const args = contexts.get(element)! as Accessor<T>;
|
||||
return args();
|
||||
})();
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const args = contexts.get(element)! as Accessor<T>;
|
||||
|
||||
command(...args());
|
||||
command(...args);
|
||||
|
||||
return false;
|
||||
},
|
||||
|
@ -159,17 +163,6 @@ export const createCommand = <TArgs extends any[] = []>(label: string, command:
|
|||
});
|
||||
};
|
||||
|
||||
export const commandArguments = <T extends any[] = any[]>(element: Element, commandAndArgs: Accessor<[CommandType<T>, T]>) => {
|
||||
const ctx = useContext(CommandContext);
|
||||
const args = createMemo(() => commandAndArgs()[1]);
|
||||
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.addContextualArguments(commandAndArgs()[0], element, args);
|
||||
}
|
||||
|
||||
export const noop = Object.defineProperties(createCommand('noop', () => { }), {
|
||||
withLabel: {
|
||||
value(label: string) {
|
||||
|
@ -180,12 +173,4 @@ export const noop = Object.defineProperties(createCommand('noop', () => { }), {
|
|||
},
|
||||
}) as CommandType & { withLabel(label: string): CommandType };
|
||||
|
||||
declare module "solid-js" {
|
||||
namespace JSX {
|
||||
interface Directives {
|
||||
commandArguments<T extends any[] = any[]>(): [CommandType<T>, T];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { Context } from './contextMenu';
|
|
@ -4,6 +4,8 @@ import { createStore } from "solid-js/store";
|
|||
import { isServer } from "solid-js/web";
|
||||
import * as json from './parser/json';
|
||||
|
||||
const ROOT = '__root__';
|
||||
|
||||
interface FileEntity {
|
||||
key: string;
|
||||
handle: FileSystemDirectoryHandle;
|
||||
|
@ -25,7 +27,9 @@ interface InternalFilesContextType {
|
|||
|
||||
interface FilesContextType {
|
||||
readonly files: Accessor<FileEntity[]>,
|
||||
readonly root: Accessor<FileSystemDirectoryHandle | undefined>,
|
||||
|
||||
open(directory: FileSystemDirectoryHandle): void;
|
||||
get(key: string): Accessor<FileSystemDirectoryHandle | undefined>
|
||||
set(key: string, handle: FileSystemDirectoryHandle): Promise<void>;
|
||||
remove(key: string): Promise<void>;
|
||||
|
@ -42,10 +46,16 @@ const clientContext = (): InternalFilesContextType => {
|
|||
|
||||
return {
|
||||
onChange(hook: (key: string, handle: FileSystemDirectoryHandle) => any) {
|
||||
const callHook = (key: string, handle: FileSystemDirectoryHandle) => setTimeout(() => hook(key, handle), 1);
|
||||
const callHook = (key: string, handle: FileSystemDirectoryHandle) => {
|
||||
if (!key || key === ROOT) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => hook(key, handle), 1);
|
||||
};
|
||||
|
||||
db.files.hook('creating', (_: string, { key, handle }: FileEntity) => { callHook(key, handle); });
|
||||
db.files.hook('deleting', (_: string, { key, handle }: FileEntity) => callHook(key, handle));
|
||||
db.files.hook('deleting', (_: string, { key, handle }: FileEntity = { key: undefined!, handle: undefined! }) => callHook(key, handle));
|
||||
db.files.hook('updating', (_1: Object, _2: string, { key, handle }: FileEntity) => callHook(key, handle));
|
||||
},
|
||||
|
||||
|
@ -59,13 +69,13 @@ const clientContext = (): InternalFilesContextType => {
|
|||
return (await db.files.delete(key));
|
||||
},
|
||||
async keys() {
|
||||
return (await db.files.toArray()).map(f => f.key);
|
||||
return (await db.files.where('key').notEqual(ROOT).toArray()).map(f => f.key);
|
||||
},
|
||||
async entries() {
|
||||
return await db.files.toArray();
|
||||
return await db.files.where('key').notEqual(ROOT).toArray();
|
||||
},
|
||||
async list() {
|
||||
const files = await db.files.toArray();
|
||||
const files = await db.files.where('key').notEqual(ROOT).toArray();
|
||||
|
||||
return files.map(f => f.handle)
|
||||
},
|
||||
|
@ -99,27 +109,35 @@ const serverContext = (): InternalFilesContextType => ({
|
|||
export const FilesProvider: ParentComponent = (props) => {
|
||||
const internal = isServer ? serverContext() : clientContext();
|
||||
|
||||
const [state, setState] = createStore<{ files: FileEntity[] }>({ files: [] });
|
||||
const [state, setState] = createStore<{ openedFiles: FileEntity[], root: FileSystemDirectoryHandle | undefined }>({ openedFiles: [], root: undefined });
|
||||
|
||||
const updateFilesInState = async () => {
|
||||
const entities = await internal.entries();
|
||||
|
||||
setState('files', entities);
|
||||
};
|
||||
|
||||
internal.onChange((key: string, handle: FileSystemDirectoryHandle) => {
|
||||
updateFilesInState();
|
||||
internal.onChange(async () => {
|
||||
setState('openedFiles', await internal.entries());
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
updateFilesInState();
|
||||
(async () => {
|
||||
const [root, files] = await Promise.all([
|
||||
internal.get(ROOT),
|
||||
internal.entries(),
|
||||
]);
|
||||
|
||||
setState('root', root);
|
||||
setState('openedFiles', files);
|
||||
})();
|
||||
});
|
||||
|
||||
const context: FilesContextType = {
|
||||
files: createMemo(() => state.files),
|
||||
files: createMemo(() => state.openedFiles),
|
||||
root: createMemo(() => state.root),
|
||||
|
||||
open(directory: FileSystemDirectoryHandle) {
|
||||
setState('root', directory);
|
||||
internal.set(ROOT, directory);
|
||||
},
|
||||
|
||||
get(key: string): Accessor<FileSystemDirectoryHandle | undefined> {
|
||||
return createMemo(() => state.files.find(entity => entity.key === key)?.handle);
|
||||
return createMemo(() => state.openedFiles.find(entity => entity.key === key)?.handle);
|
||||
},
|
||||
|
||||
async set(key: string, handle: FileSystemDirectoryHandle) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Accessor, Component, For, JSX, Match, ParentComponent, Setter, Show, Switch, children, createContext, createEffect, createMemo, createSignal, createUniqueId, mergeProps, onCleanup, onMount, useContext } from "solid-js";
|
||||
import { Portal } from "solid-js/web";
|
||||
import { createStore } from "solid-js/store";
|
||||
import { CommandType, Command } from "../command";
|
||||
import { CommandType, Command, useCommands } from "../command";
|
||||
import css from "./index.module.css";
|
||||
|
||||
export interface MenuContextType {
|
||||
|
@ -35,7 +35,7 @@ const MenuContext = createContext<MenuContextType>();
|
|||
|
||||
export const MenuProvider: ParentComponent<{ commands?: CommandType[] }> = (props) => {
|
||||
const [ref, setRef] = createSignal<Node | undefined>();
|
||||
const [store, setStore] = createStore<{ items: Record<string, Item | ItemWithChildren> }>({ items: {} });
|
||||
const [store, setStore] = createStore<{ items: Map<string, Item | ItemWithChildren> }>({ items: new Map });
|
||||
|
||||
const ctx = {
|
||||
ref,
|
||||
|
@ -43,19 +43,19 @@ export const MenuProvider: ParentComponent<{ commands?: CommandType[] }> = (prop
|
|||
addItems(items: (Item | ItemWithChildren)[]) {
|
||||
return setStore('items', values => {
|
||||
for (const item of items) {
|
||||
values[item.id] = item;
|
||||
values.set(item.id, item);
|
||||
}
|
||||
|
||||
return values;
|
||||
return new Map(values.entries());
|
||||
})
|
||||
},
|
||||
items() {
|
||||
return Object.values(store.items);
|
||||
return store.items.values();
|
||||
},
|
||||
commands() {
|
||||
return Object.values(store.items)
|
||||
.map(item => item.kind === 'node' ? item.children.filter(c => c.kind === 'leaf').map(c => c.command) : item.command)
|
||||
.flat()
|
||||
return store.items.values()
|
||||
.flatMap(item => item.kind === 'node' ? item.children.filter(c => c.kind === 'leaf').map(c => c.command) : [item.command])
|
||||
.toArray()
|
||||
.concat(props.commands ?? []);
|
||||
},
|
||||
};
|
||||
|
@ -100,11 +100,12 @@ const Separator: Component = (props) => {
|
|||
}
|
||||
|
||||
const Root: ParentComponent<{}> = (props) => {
|
||||
const menu = useMenu();
|
||||
const menuContext = useMenu();
|
||||
const commandContext = useCommands();
|
||||
const [current, setCurrent] = createSignal<HTMLElement>();
|
||||
const items = children(() => props.children).toArray() as unknown as (Item | ItemWithChildren)[];
|
||||
|
||||
menu.addItems(items)
|
||||
menuContext.addItems(items)
|
||||
|
||||
const close = () => {
|
||||
const el = current();
|
||||
|
@ -118,10 +119,10 @@ const Root: ParentComponent<{}> = (props) => {
|
|||
|
||||
const onExecute = (command?: CommandType) => {
|
||||
return command
|
||||
? async () => {
|
||||
await command?.();
|
||||
|
||||
? (e: Event) => {
|
||||
close();
|
||||
|
||||
return commandContext?.execute(command, e);
|
||||
}
|
||||
: () => { }
|
||||
};
|
||||
|
@ -132,7 +133,7 @@ const Root: ParentComponent<{}> = (props) => {
|
|||
</button>
|
||||
};
|
||||
|
||||
return <Portal mount={menu.ref()}>
|
||||
return <Portal mount={menuContext.ref()}>
|
||||
<For each={items}>{
|
||||
item => <Switch>
|
||||
<Match when={item.kind === 'node' ? item as ItemWithChildren : undefined}>{
|
||||
|
@ -349,4 +350,4 @@ declare module "solid-js" {
|
|||
anchor?: string | undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue