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
TypeScript
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]};