import type { ComponentCtrl, Props, VNode } from './core'; // === exports ======================================================= export { opt, props, req, widget }; export type { ComponentCtrl, PropDef, PropsDef }; // === types ========================================================= type ComponentFunc

= (p: P) => () => VNode; type PropDefReq = { required: true }; type PropDefOpt = { required: false; defaultValue: never }; type PropDefVal = { required: false; defaultValue: T }; type PropDef = PropDefReq | PropDefOpt | PropDefVal; type PropsDef = Record>; type Prettify = T; //{ [K in keyof T]: T[K] }; type PropsType = Prettify< { [K in keyof T as T[K] extends PropDefReq ? K : never]: T[K] extends PropDefReq ? U : never; } & { [K in keyof T as T[K] extends PropDefOpt ? K : never]?: T[K] extends PropDefOpt ? U : never; } & { [K in keyof T as T[K] extends PropDefVal ? K : never]?: T[K] extends PropDefVal ? U : never; } >; type DefaultsType = { [K in keyof T as T[K] extends PropDefVal ? K : never]: T[K] extends PropDefVal ? U : never; }; // TODO!!!!!!! interface PropsConfig

{ validateProps?: (nextProps: P, oldProps: P) => null | Error; defaults: D; } // === constants ===================================================== const symbolProps = Symbol('props'); // === local data ==================================================== const reqDef = Object.freeze({ required: true }); const optDef = Object.freeze({ required: false }); // === exported functions ============================================ function req(): PropDefReq { return reqDef; } function opt(): PropDefOpt; function opt(defaultValue?: T): PropDefVal; function opt(defaultValue?: any): any { return arguments.length > 0 ? { required: false, defaultValue } : optDef; } function props( propsDef: T ): PropsConfig, DefaultsType> { const defaults: any = {}; for (const key of Object.keys(propsDef)) { if (hasOwn(propsDef[key], 'defaultValue')) { defaults[key] = (propsDef[key] as any).defaultValue; } } return { defaults }; } function widget(name: string, main: ComponentFunc<{}>): ComponentFunc<{}>; function widget( name: string ):

>( propsConfig: PropsConfig ) => (fn: (props: Prettify

) => () => VNode) => ComponentFunc

; function widget(name: string, arg2?: any): any { if (arguments.length > 1) { const ret = arg2.bind(null); Object.defineProperty(ret, 'name', { value: name }); return ret; } return

>( propsConfig: PropsConfig ) => { const defaults = propsConfig.defaults || {}; // TODO!!!! return (fn: Function) => { return (props: Props) => { (props.constructor as any).__defaults = defaults; for (const key of Object.keys(defaults)) { if (props[key] === undefined) { props[key] = defaults[key]; } } return fn(props); }; }; }; } // === utilities ===================================================== function hasOwn(subj: any, propName: string) { return subj != null && Object.prototype.hasOwnProperty.call(subj, propName); }