UNPKG

be-enhanced

Version:

be-enhanced provides a base class that enables casting spells, or enhancing server-rendered DOM elements based on cross-cutting custom attributes

485 lines (368 loc) 15.6 kB
import { IMountObserver } from '../../mount-observer/types'; import { Scope} from '../lib/types'; import { WrapperConfig } from '../XV/types'; import {CSSQuery, XForm} from '../types'; export interface IEventConfig<MCProps = any, MCActions = MCProps, TAction = Action>{ on?: string, of?: 'tbd' | EventTarget, doInit?: boolean, options?: AddEventListenerOptions, abort?: { origMethName: string & keyof MCActions, //destMethName: string & keyof MCActions, of: 'tbd' | EventTarget, on: string, }, composedPathMatches?: string, } //Is anything using this anymore? export type ActionOnEventConfigs<MCProps = any, MCActions = MCProps, TAction = Action> = Partial<{[key in keyof MCActions]: IEventConfig<MCProps, MCActions, TAction>}> export interface IPropagator extends EventTarget{ get(key: string): any; set(key: string, val: any): void; /** * Delta Keys */ dk: Set<string>; /** * Mature keys */ mk: Set<string>; /** * timeout handles - key is name of prop * used for simple debouncing of echo notifications in XtalElement */ eth: Map<string, string | number | NodeJS.Timeout> | undefined; /** * timeout handles - key is name of prop * used for simple debouncing of toggle echo notifications in XtalElement */ tth: Map<string, string | number | NodeJS.Timeout> | undefined; } export interface IResolvableService extends EventTarget{ resolved: boolean; resolve(): Promise<void>; } export interface IInstanceResolvableService<T extends object = object> extends IResolvableService{ instanceResolve(instance: T): Promise<void>; } export interface IMix extends IResolvableService{ ext: {new(): HTMLElement} } export interface IPropRegistrar extends IResolvableService{ propInfos: {[key: string]: PropInfo}, allPropNames: string[], getAttrNames(ext: any): Promise<string[]>, getPropsFromAction(action: string | Action): Set<string>, nonDryProps: Set<string>, } // export interface IDefine extends IResolvableService{ // custElClass: {new(): HTMLElement}; // resolveInstanceSvcs(args: CEArgs, instance: any): Promise<void>; // } export interface IPropSvc extends IResolvableService{ createPropBag(instance: Element): void; } export interface IHookup extends IInstanceResolvableService{ } export interface IAttrChgCB{ instance: HTMLElement, // name: string, // oldVal: string, // newVal: string, newAttrs: {[key: string]: {oldVal: string | null, newVal: string | null}}, filteredAttrs: {[key: string]: string} } export interface IConnectedCB{ instance: HTMLElement, } export interface IPropChg{ key: string, oldVal: any, newVal: any, } export interface IDisconnectedCB { instance: HTMLElement } export interface INewPropagator { instance: HTMLElement, propagator: IPropagator, } // export interface CEArgs<TProps = any, TActions = TProps, TPropInfo = PropInfo, TAction extends Action<TProps> = Action<TProps>> extends DefineArgs<TProps, TActions, TPropInfo, TAction>{ // definer?: IDefine, // servers?: CEServiceClasses // services?: CEServices, // asides?: any // } export interface DynamicTransform { scope?: Scope, noCache?: boolean, } export interface IPE { do(instance: EventTarget, originMethodName: string, vals: [any, ActionOnEventConfigs] ): Promise<void>, } export interface IPET extends IPE{ re(instance: EventTarget, originMethodName: string, vals: [any, ActionOnEventConfigs, DynamicTransform] ): Promise<void>, } export interface DefineArgs<MixinCompositeProps = any, MixinCompositeActions = MixinCompositeProps, TPropInfo = PropInfo, TAction extends Action = Action<MixinCompositeProps>>{ superclass?: {new(): HTMLElement} | string, mixins?: any[], mainTemplate?: HTMLTemplateElement; /** use this only for defaults that can't be JSON serialized in config */ complexPropDefaults?: Partial<MixinCompositeProps>; /** Config should be 100% JSON serializable, or a JSON import, or an id of an be-exportable script tag */ config: WCConfig<MixinCompositeProps, MixinCompositeActions, TPropInfo, TAction> | (() => Promise<{default: WCConfig<MixinCompositeProps, MixinCompositeActions, TPropInfo, TAction>}>) | string; // /** // * Side effects tied to actions, mostly used to load enhancement dependencies tied to // * enhancements // */ // asides?: Partial<{[key in keyof MixinCompositeActions & string]: (instance: EventTarget, methodName: string, key: string) => Promise<void> }> } export interface WCConfig<TProps = any, TActions = TProps, TPropInfo = PropInfo, TAction = Action>{ tagName?: string; isEnh?: boolean; propDefaults?: Partial<{[key in keyof TProps]: TProps[key]}>; propInfo?: Partial<{[key in keyof TProps]: TPropInfo}>; wrappers?: Partial<{[key in keyof TProps]: WrapperConfig<TProps>}>; derivedProps?: (keyof TProps & string)[]; // actions?: // Partial<{[key in keyof MCActions & string]: TAction | keyof MCProps}> actions?: Actions<TProps, TActions>; propChangeMethod?: keyof TActions; style?: Partial<CSSStyleDeclaration>; /** * Used for providing hints to server side processing what css queries should be observed if using HTMLRewriter. */ keyQueries?: string[]; formAss?: boolean; compacts?: Compacts<TProps>; } export type PropLookup<TProps = any, TActions = any> = Partial<{[key in keyof TProps]: PropInfo<TProps, TActions>}>; export type IshPropLookup<TProps = any, TActions = any> = Partial<{[key in keyof TProps]: IshPropInfo<TProps, TActions>}>; export interface IshConfig<TProps = any, TActions = TProps, ETProps = TProps>{ propDefaults?: Partial<{[key in keyof TProps]: TProps[key]}>; propInfo?: Partial<{[key in keyof TProps]: PropInfo}>; wrappers?: Partial<{[key in keyof TProps]: WrapperConfig<TProps>}>; actions?: Actions<TProps, TActions>; /** * inferred actions */ infractions?: Infractions<TProps>, compacts?: Compacts<TProps, TActions>; hitch?: Hitches<TProps, TActions>; handlers?: Handlers<ETProps, TActions>; positractions?: Positractions<TProps, TActions>; isSleepless?: boolean; xform?: XForm<TProps, TActions>; inScopeXForms?: {[key: CSSQuery]: XForm<TProps, TActions>}; ishListCountProp?: keyof TProps & string; defaultIshList?: any[]; } export interface OConfig<TProps = any, TActions = TProps, ETProps = TProps> extends IshConfig<TProps, TActions, ETProps>{ mainTemplate?: string | HTMLTemplateElement; } export type Positractions<TProps = any, TActions = TProps> = | Array<Positraction<TProps, TActions>>; export interface Positraction<TProps = any, TActions = TProps> extends LogicOp<TProps> { do: Function | (keyof TActions & string), ifKeyIn?: Array<keyof TProps & string>, ifAllOf?: Array<keyof TProps & string>, //ifNoneOf: Array<keyof TProps & string>, pass?: Array<(keyof TProps & string) | number | boolean | '$0' | '$0+' | `\`${string}\``>, assignTo?: Array<null | (keyof TProps & string)> } export type Compacts<TProps = any, TActions = TProps> = //| Partial<{[key in `${keyof TProps & string}_to_${keyof TProps & string}` & string]: Operation<TProps> }> | Partial<{[key in `negate_${keyof TProps & string}_to_${keyof TProps & string}`]: number}> | Partial<{[key in `pass_length_of_${keyof TProps & string}_to_${keyof TProps & string}`]: number}> | Partial<{[key in `echo_${keyof TProps & string}_to_${keyof TProps & string}`]: number}> | Partial<{[key in `echo_${keyof TProps & string}_to_${keyof TProps & string}_after`]: keyof TProps}> | Partial<{[key in `when_${keyof TProps & string}_changes_call_${keyof TActions & string}`]: number}> | Partial<{[key in `when_${keyof TProps & string}_changes_toggle_${keyof TProps & string}`]: number}> | Partial<{[key in `when_${keyof TProps & string}_changes_inc_${keyof TProps & string}_by`]: number}> | Partial<{[key in `when_${keyof TProps & string}_changes_dispatch`]: string}> //TODO ; export type Hitches<TProps = any, TActions = TProps> = | Partial<{[key in `when_${keyof TProps & string}_emits_${keyof TProps & string}_inc_${keyof TProps & string}_by`]: number}> ; export type Handlers<ETProps = any, TActions = ETProps> = | Partial<{[key in `${keyof ETProps & string}_to_${keyof TActions & string}_on` & string]: string }>; export type ListOfLogicalExpressions<MCProps = any> = (keyof MCProps | LogicOp<MCProps>)[]; export type LogicOpProp<MCProps = any> = |LogicOp<MCProps> | (keyof MCProps & string)[]; export interface LogicOp<Props = any>{ /** * Supported by trans-render */ ifAllOf?: Keysh<Props>, ifKeyIn?: Keysh<Props>, ifNoneOf?: Keysh<Props>, ifEquals?: Array<Key<Props>>, ifAtLeastOneOf?: Keysh<Props>, ifNotAllOf?: Keysh<Props>, debug?: boolean, delay?: number, do?: (x: Props) => (Promise<Partial<Props>> | Partial<Props>) } export interface SetLogicOps<Props = any>{ a?: boolean, ifAllOf?: Set<Key<Props>>, ifKeyIn?: Set<Key<Props>>, ifNoneOf?: Set<Key<Props>>, ifEquals?: Set<Key<Props>>, ifAtLeastOneOf?: Set<Key<Props>>, ifNotAllOf?: Set<Key<Props>>, debug?: boolean, delay?: number, do?: (x: Props) => (Promise<Partial<Props>> | Partial<Props>), } export interface Action<MCProps = any, MCActions = MCProps> extends LogicOp<MCProps>{ target?: keyof MCProps; debug?: boolean; secondArg?: any; //setFree?: (keyof MCProps & string)[], } export interface IActionProcessor{ doActions(self: IActionProcessor, actions: {[methodName: string]: Action}, target: any, proxy?: any): void; postHoc(self: this, action: Action, target: any, returnVal: any, proxy?: any): void; } type PropInfoTypes = "String" | "Number" | "Boolean" | "Object" | "RegExp"; export interface IshPropInfo<TProps = any, TActions = any>{ type?: PropInfoTypes; dry?: boolean; ro?: boolean; propName?: string; /** * Allow for discarding what is passed in favor of a modified value such as a formatted value * or filtered list */ adjuster?: |keyof TActions & string |((nv: any) => any) } export interface PropInfo<TProps=any, TActions=any> extends IshPropInfo<TProps, TActions>{ parse?: boolean; def?: any; attrName?: string; /** * form associated read only property * https://web.dev/articles/more-capable-form-controls#:~:text=Form-associated%20custom%20elements%20aim%20to%20bridge%20the%20gap,associated%20with%20the%20form%2C%20like%20a%20browser-provided%20control. * examples: form, validity, validityMessage, willValidate */ farop?: boolean; /** * form associated read only method * examples: checkValidity, reportValidity */ farom?: 'checkValidity' | 'reportValidity'; /** * form associated write method */ fawm?: 'setValidity' | 'setFormValue' /** * internals pass through property * examples: role, ariaRole */ ip?: boolean; } export type ConstString = string; export type NameOfProp = string; export type StringOrProp = ConstString | [NameOfProp, PropInfo]; export type Parts = Array<StringOrProp>; export interface PropChangeInfo<TPropInfo = PropInfo> { key: string, ov: any, nv: any, prop: TPropInfo, pcm: PropChangeMethod | undefined; } //are these still really used? export type PropChangeMoment = 'v' | '-a' | '+a' | '+qr' | '+qm'; export type PropChangeMethod = (self: EventTarget, pci: PropChangeInfo, moment: PropChangeMoment) => boolean; export type Actions<TProps = any, TActions = TProps> = Partial<{[key in keyof TActions & string]: LogicOp<TProps>}> //& Partial<{[key in `do_${keyof TActions & string}_on`]: Key<TActions> | Array<Key<TActions>> }> ; export type Checks<TProps = any, TActions = TProps> = Partial<{[key in keyof TActions & string]: SetLogicOps<TProps>}> export type roundaboutOptions<TProps = any, TActions = TProps, ETProps = TProps> = { vm?: TProps & TActions & RoundaboutReady, //for enhanced elements, pass in the container, referenced via $0. container?: EventTarget, propagate?: keyof TProps & string | Array<keyof TProps & string>, actions?: Actions<TProps,TActions>, compacts?: Compacts<TProps, TActions>, //onsets?: Onsets<TProps, TActions>, handlers?: Handlers<ETProps, TActions>, hitch?: Hitches<TProps, TActions>, positractions?: Positractions<TProps>, mountObservers?: Set<IMountObserver> } export type PropsToPartialProps<TProps = any> = | ((self: TProps, a: any, b: any) => Promise<Partial<TProps>>) | ((self: TProps) => Partial<TProps>); export type Infractions<TProps = any> = //| PropsToPartialProps<TProps> | Array<PropsToPartialProps<TProps>> export type Busses = {[key: string]: Set<string>}; export type Routers = {[key: string]: Array<{ on: string, do: string, full: string, }>} export type Key<T = any> = keyof T & string; export type Keysh<T = any> = Key<T> | Array<Key<T>>; export interface RoundaboutReady{ /** * Allow for assigning to read only props via the "backdoor" * Bypasses getters / setters, sets directly to (private) memory slots * Doesn't do any notification * Allows for nested property setting */ covertAssignment(obj: any): Promise<void>; /** * fires event with name matching the name of the property when the value changes (but not via covertAssignment) * when property is set via public interface, not (immediately) via an action method's return object */ readonly propagator : EventTarget | undefined; /** * * https://github.com/whatwg/dom/issues/1296 */ //readonly disconnectedSignal: AbortSignal RAController: AbortController; /** * During this time, queues/buses continue to perform "bookkeeping" * but doesn't process the queue until sleep property becomes falsy. * If truthy, can call await awake() before processing should resume * [TODO] */ readonly sleep?: number, awake(): Promise<void>; nudge(): void; rock(): void; } export interface BaseProps{ proppedUp: boolean, sleep?: number; } export interface ICompact{ compacts: Compacts, } interface CompactStatement { srcKey: string, destKey: string, op: 'toggle' | 'negate' | 'call' | 'pass_length' | 'echo' | 'inc' | 'dispatch', rhsIsDynamic: boolean } interface HitchStatement { leftKey: string, middleKey: string, rightKey: string, lOp: 'when' lmOp: 'emits', mrOp: 'inc', rOp: 'by' } export type CommandMethod<T extends EventTarget = EventTarget> = (self: T, evt: Event) => Partial<T> | Promise<Partial<T>> export type HookupConfig<T extends EventTarget = EventTarget> = {[key: string]: CommandMethod | [string, CommandMethod]};