chromatic-lattice/src/features/feature.ts

96 lines
3.5 KiB
TypeScript
Raw Normal View History

2022-03-04 03:39:48 +00:00
import Decimal from "util/bignum";
import { DoNotCache } from "util/computed";
import { CSSProperties, DefineComponent, isRef } from "vue";
2022-01-14 04:25:47 +00:00
export const Component = Symbol("Component");
export const GatherProps = Symbol("GatherProps");
2022-01-14 04:25:47 +00:00
export type JSXFunction = (() => JSX.Element) & { [DoNotCache]: true };
export type CoercableComponent = string | DefineComponent | JSXFunction;
2022-01-25 04:23:30 +00:00
export type StyleValue = string | CSSProperties | Array<string | CSSProperties>;
2022-01-14 04:25:47 +00:00
// TODO if importing .vue components in .tsx can become type safe,
// this type can probably be safely removed
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type GenericComponent = DefineComponent<any, any, any>;
export type Replace<T, S> = S & Omit<T, keyof S>;
export type OptionsFunc<T, S = T, R = Record<string, unknown>> = () => T & ThisType<S> & Partial<R>;
2022-01-14 04:25:47 +00:00
let id = 0;
// Get a unique ID to allow a feature to be found for creating branches
// and any other uses requiring unique identifiers for each feature
// IDs are gauranteed unique, but should not be saved as they are not
// guaranteed to be persistent through updates and such
export function getUniqueID(prefix = "feature-"): string {
return prefix + id++;
}
export enum Visibility {
Visible,
Hidden,
None
}
export function jsx(func: () => JSX.Element | ""): JSXFunction {
(func as Partial<JSXFunction>)[DoNotCache] = true;
return func as JSXFunction;
}
2022-01-14 04:25:47 +00:00
export function showIf(condition: boolean, otherwise = Visibility.None): Visibility {
return condition ? Visibility.Visible : otherwise;
}
export function setDefault<T, K extends keyof T>(
object: T,
key: K,
value: T[K]
): asserts object is Exclude<T, K> & Required<Pick<T, K>> {
if (object[key] === undefined && value != undefined) {
object[key] = value;
}
}
export function findFeatures(obj: Record<string, unknown>, ...types: symbol[]): unknown[] {
2022-01-14 04:25:47 +00:00
const objects: unknown[] = [];
const handleObject = (obj: Record<string, unknown>) => {
Object.keys(obj).forEach(key => {
const value = obj[key];
if (value && typeof value === "object") {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (types.includes((value as Record<string, any>).type)) {
objects.push(value);
} else if (!(value instanceof Decimal) && !isRef(value)) {
handleObject(value as Record<string, unknown>);
}
}
});
};
handleObject(obj);
return objects;
}
export function excludeFeatures(obj: Record<string, unknown>, ...types: symbol[]): unknown[] {
const objects: unknown[] = [];
const handleObject = (obj: Record<string, unknown>) => {
Object.keys(obj).forEach(key => {
const value = obj[key];
if (value && typeof value === "object") {
if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
typeof (value as Record<string, any>).type == "symbol" &&
// eslint-disable-next-line @typescript-eslint/no-explicit-any
!types.includes((value as Record<string, any>).type)
) {
2022-01-14 04:25:47 +00:00
objects.push(value);
} else if (!(value instanceof Decimal) && !isRef(value)) {
2022-01-14 04:25:47 +00:00
handleObject(value as Record<string, unknown>);
}
}
});
};
handleObject(obj);
return objects;
}