Files
outline/app/actions/index.ts
忽如寄 9f400af73b refactor: ♻️ refactor isHosted && type clean up (#3290)
* refactor: ♻️ refactor isHosted && type clean up

Change-Id: I4dfbad8a07607432801de78920ce42bf81e46498

* refactor: ♻️ code clean up

Change-Id: I8f487a33d332a2acaff84397a97371b56ace28a1

* feat: 💄 lint

Change-Id: I776b1a5e249bdb542f8e6da7cb2277821cf91094

* feat:  ci type

Change-Id: I486dde7bf60321238e9a394c40ad8cdb8bfc54c8

* feat: some code sugession

Change-Id: I4761d057344b95a98e99068d312a42292977875b
2022-03-27 15:18:37 -07:00

109 lines
2.8 KiB
TypeScript

import { flattenDeep } from "lodash";
import * as React from "react";
import { Optional } from "utility-types";
import { v4 as uuidv4 } from "uuid";
import {
Action,
ActionContext,
CommandBarAction,
MenuItemButton,
MenuItemWithChildren,
} from "~/types";
export function createAction(definition: Optional<Action, "id">): Action {
return {
...definition,
id: uuidv4(),
};
}
export function actionToMenuItem(
action: Action,
context: ActionContext
): MenuItemButton | MenuItemWithChildren {
function resolve<T>(value: any): T {
if (typeof value === "function") {
return value(context);
}
return value;
}
const resolvedIcon = resolve<React.ReactElement<any>>(action.icon);
const resolvedChildren = resolve<Action[]>(action.children);
const visible = action.visible ? action.visible(context) : true;
const title = resolve<string>(action.name);
const icon =
resolvedIcon && action.iconInContextMenu !== false
? React.cloneElement(resolvedIcon, {
color: "currentColor",
})
: undefined;
if (resolvedChildren) {
const items = resolvedChildren
.map((a) => actionToMenuItem(a, context))
.filter(Boolean)
.filter((a) => a.visible);
return {
type: "submenu",
title,
icon,
items,
visible: visible && items.length > 0,
};
}
return {
type: "button",
title,
icon,
visible,
onClick: () => action.perform && action.perform(context),
selected: action.selected ? action.selected(context) : undefined,
};
}
export function actionToKBar(
action: Action,
context: ActionContext
): CommandBarAction[] {
function resolve<T>(value: any): T {
if (typeof value === "function") {
return value(context);
}
return value;
}
if (typeof action.visible === "function" && !action.visible(context)) {
return [];
}
const resolvedIcon = resolve<React.ReactElement<any>>(action.icon);
const resolvedChildren = resolve<Action[]>(action.children);
const resolvedSection = resolve<string>(action.section);
const resolvedName = resolve<string>(action.name);
const resolvedPlaceholder = resolve<string>(action.placeholder);
const children = resolvedChildren
? flattenDeep(resolvedChildren.map((a) => actionToKBar(a, context))).filter(
(a) => !!a
)
: [];
return [
{
id: action.id,
name: resolvedName,
section: resolvedSection,
placeholder: resolvedPlaceholder,
keywords: action.keywords ?? "",
shortcut: action.shortcut || [],
icon: resolvedIcon,
perform: action.perform ? () => action?.perform?.(context) : undefined,
},
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
].concat(children.map((child) => ({ ...child, parent: action.id })));
}