diff --git a/src/index.ts b/src/index.ts index d752d93..5ebc47f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,13 @@ -import { NavigationView, contentView, asFactory} from "tabris"; +import { NavigationView, contentView } from "tabris"; import type { Page, Action, SearchAction, CompositeAddChildEvent, + Widget, + Constructor, } from "tabris"; -import { createProxies } from "./utils/proxy"; +import { factory } from "./utils/proxy"; let navigation: NavigationView; @@ -18,7 +20,6 @@ contentView.on( } ); -export default addView; export * from "./modal"; export * from "./navigation"; export * from "./preference"; @@ -31,6 +32,7 @@ export function addView(...widgets: (Page | Action | SearchAction)[]) { */ abstract class VoirRender { abstract renderAction(): Action[]; + abstract render(): Page; constructor() { @@ -45,10 +47,15 @@ abstract class VoirRender { } } +export interface Render { + renderAction(): (Action | SearchAction)[]; + render(): Widget; +} + +//@ts-ignore export const Voir = Object.freeze({ Render: VoirRender, - factory(Class: VoirRender) { - //@ts-ignore - return createProxies(Class) as VoirRender; + factory(Class: Constructor) { + return factory(Class); } -}) \ No newline at end of file +}) diff --git a/src/modal/animation.ts b/src/modal/animation.ts index 9ff8516..6564893 100644 --- a/src/modal/animation.ts +++ b/src/modal/animation.ts @@ -34,11 +34,12 @@ export function animateHidden( ); } -export async function animate( +export function animate( element: Widget, delay: number, duration: number ) { - await animateShow(element, delay, 300); - await animateHidden(element, duration, duration); + return Promise.resolve(animateShow(element, delay, 300)).then(()=> { + return Promise.resolve(animateHidden(element, duration, duration)); + }) } diff --git a/src/modal/toast.ts b/src/modal/toast.ts index f81227d..bdeec95 100644 --- a/src/modal/toast.ts +++ b/src/modal/toast.ts @@ -8,51 +8,84 @@ import { import AnimationTime from "./animation-time"; import { animate } from "./animation"; +let stackToast: ({element: Composite, promise: ()=> Promise})[] = []; + export default class Toast extends AnimationTime { show: (time: number) => any; + readonly _message = TextView({ + textColor: "white", + left: 0, + right: 0, + }); + + readonly _modal = Composite({ + background: "black", + padding: 10, + cornerRadius: 10, + bottom: 30, + opacity: 0 + }).append(this._message); + constructor(message: string, duration: number) { super(); + const font = "12px"; + const size = sizeMeasurement.measureTextsSync([ - { text: message, font: "12px" }, + { text: message, font }, ]); const isMax: boolean = size[0].width > contentView.bounds.width - 20; const props: Properties = {}; if (isMax) { - props.left = 20; - props.right = 20; + this._modal.left = 20; + this._modal.right = 20; } else { - props.centerX = true; + this._modal.centerX = true; } - - const textview = TextView({ - text: message, - font: "12px", - textColor: "white", - left: 0, - right: 0, - }); - - const modal = Composite({ - background: "black", - padding: 10, - cornerRadius: 10, - bottom: 30, - opacity: 0, - ...props, - }).append(textview); + + this._message.text = message; + this._message.font = font; Object.defineProperty(this, "show", { configurable: false, - value: async () => { - contentView.append(modal); - await animate(modal, 0, duration); - modal.dispose(); + value: () => { + if (stackToast.length === 1) { + flush(); + } + if (stackToast.length > 0) { + stackToast.push({ + element: this._modal, + promise: () => new Promise((resolve)=> { + resolve(appendToast(this._modal)) + }) + }) + } else { + const ani = appendToast(this._modal); + stackToast.push({ + promise: ()=> ani, + element: this._modal + }); + } }, }); + + const flush = () => { + if (stackToast.length === 0) return; + const { promise, element } = stackToast.at(0); + promise().then(() => { + stackToast.shift(); + element.dispose(); + flush(); + }).catch(console.log); + } + + function appendToast(modal: Composite) { + contentView.append(modal); + return animate(modal, 0, duration); + } } static makeText(msg: string, duration: number = Toast.SHORT) { diff --git a/src/navigation/CoordinatePage.ts b/src/navigation/CoordinatePage.ts index 55e7780..96f8072 100644 --- a/src/navigation/CoordinatePage.ts +++ b/src/navigation/CoordinatePage.ts @@ -1,17 +1,23 @@ import { type EventObject, type AnyWidget, + type WidgetCollection, NavigationView, drawer, Page, Action, Properties as PropertiesTabris, SearchAction, - CompositeAddChildEvent + CompositeAddChildEvent, + Widget, + NativeObject, + Properties, + Listeners } from "tabris"; import { createProxies } from "../utils/proxy"; import { createInstance } from "../utils/helpers"; -import { type IMenuItemOption, type MenuItemOf, setMenuDrawer, setContentDrawer } from "./menu"; +import { customEvent } from "../utils/custom-events"; +import { type MenuItemOption, type MenuItemOf, setMenuDrawer, setContentDrawer, MenuItem, MenuAction } from "./menu"; type FirstExecAction = { actions: Array | null; @@ -31,118 +37,107 @@ const ctxPages = new Map(); /** * @description * utilizar en JSX - * encapsula la logica del menu de acciones del AppBar + * encapsula la lógica del menu de acciones del AppBar * cuando se añade un Page con Action o SearchAction - * estas acciones desapareceran si la no es visible + * estas acciones desaparecerán si la no es visible * haciendo que la nueva pagina no tenga los menus anteriores */ export class CoordinatePageComponent extends NavigationView { - private _onActionSelect!: any; - private _onDrawerItemSelected!: any; private _dataMenuDrawer!: any; private _contentDrawer!: any; - - set contentDrawer(view: AnyWidget) { - this._contentDrawer = view; - } - - get contentDrawer() { - return this._contentDrawer; - } + onActionSelected?: any; + onDrawerItemSelected?: any; + + static readonly events = ['actionSelected', 'drawerItemSelected']; - set onActionSelect(event: (itemAction: Action) => void) { - this._onActionSelect = event; + set contentDrawer(view: Widget) { + this._contentDrawer = view; } - get onActionSelect() { - return this._onActionSelect; + get contentDrawer() { + return this._contentDrawer; } - set menuDrawer(menu: ()=> IMenuItemOption[]) { - this._dataMenuDrawer = menu(); + set menuDrawer(menu: WidgetCollection) { + this._dataMenuDrawer = menu.toArray(); } - get menuDrawer(): IMenuItemOption[] { + get menuDrawer(): WidgetCollection { return this._dataMenuDrawer; } - set onDrawerItemSelected(event: (item: MenuItemOf) => void) { - this._onDrawerItemSelected = event; + constructor(props: any) { + super(props); } - get onDrawerItemSelected() { - return this._onDrawerItemSelected; - } - - private _render() { - if (this.menuDrawer?.length > 0) setMenuDrawer(this.menuDrawer, this.onDrawerItemSelected); - if (this._contentDrawer) setContentDrawer(this._contentDrawer); - } + private readonly _renderWidgetInDrawer = (() => { + let isAdd = false; + return () => { + if (isAdd) return; + isAdd = true; + const handler = () => { + setMenuDrawer(this.menuDrawer); + setContentDrawer(this.contentDrawer); + this.menuDrawer.forEach(item => { + customEvent.listener(this, item.parent()); + }); + } + if (this.drawerActionVisible) handler(); + } + })(); - constructor(props: PropertiesTabris) { - super(props); - - if (props.drawerActionVisible) { - this._render(); + on(type: string, listener: (event: EventObject) => any, context?: object): this; + on(listeners: { [event: string]: (event: EventObject) => void; }): this; + on(type: any, listener?: any, context?: any): this { + if (typeof type === 'string' && CoordinatePageComponent.events.includes(type)) { + customEvent.addListener(this, type, listener); } - - /** - * @INFO - * ARREGLAR UN ERROR QUE SE GENERA CUANDO addView - * SE LLAMA VARIAS VECES AL AÑADIR ELEMENTOS - * EJEMPLO: addView() addView() - * ESTO PROVOCA NO OBTENER CORRECTAMENTE EL Action y SearchAction - */ - this.on( - "addChild", - ({ child }: CompositeAddChildEvent) => { - if (child instanceof Action && this._onActionSelect && !child.data.voirInitalizedEvent) { - child.onSelect(({ target }: EventObject) => this._onActionSelect(target)); + return super.on(type, listener, context); + } + + protected _addChild(child: Widget): void { + customEvent.listener(this, child); + if (child instanceof Page) { + ctxPages.set(child, { + hidden: false, + actions: null, + isDisposed: false, + }); + + child.on("appear", () => { + this._renderWidgetInDrawer(); + const info = ctxPages.get(child); + if (typeof info === "object" && info.hidden) { + if (info.actions !== null) + this.append(info.actions); + info.hidden = false; } - - if (child instanceof Page) { - ctxPages.set(child, { - hidden: false, - actions: null, - isDisposed: false, - }); - - child.on("appear", () => { - const info = ctxPages.get(child); - if (typeof info === "object" && info.hidden) { - if (info.actions !== null) - this.append(info.actions); - info.hidden = false; - } - - if (ctxPages.size === 1) { - setChangeEnabledDrawer(true); - } - }); - - child.on("disappear", () => { - const info = ctxPages.get(child); - - setChangeEnabledDrawer(false); - - if (!info.hidden) { - info.hidden = true; - info.actions?.forEach((action) => action.detach()); - } - - if (info.isDisposed) ctxPages.delete(child); - }); - - child.on("dispose", () => { - ctxPages.get(child).isDisposed = true; - }); + if (ctxPages.size === 1) { + setChangeEnabledDrawer(true); } - } - ); + }); + + child.on("disappear", () => { + const info = ctxPages.get(child); + setChangeEnabledDrawer(false); + if (!info.hidden) { + info.hidden = true; + info.actions?.forEach((action) => action.detach()); + } + + if (info.isDisposed) ctxPages.delete(child); + }); - function setChangeEnabledDrawer(enable: boolean) { - if (props?.drawerActionVisible) drawer.enabled = enable; + child.on("dispose", () => { + ctxPages.get(child).isDisposed = true; + }); } + + const setChangeEnabledDrawer = (enable: boolean) => { + if (this?.drawerActionVisible) drawer.enabled = enable; + } + + return super._addChild(child); } append(...widgets: TypeWidget) { @@ -160,7 +155,7 @@ function fillExecAction(widgets: TypeWidget) { const actions = widgets.filter( (widget: TypeChild) => { if (widget instanceof Action || widget instanceof SearchAction) { - return widget.data.voirInitalizedEvent = true; + return widget.data.voirInitializedEvent = true; } return false; } @@ -188,20 +183,27 @@ function resolveParameter($widgets: TypeWidget) { return fillExecAction(widgets); } -function ProxyCoordinatePage( - props: PropertiesTabris -): CoordinatePageComponent { - return createInstance( - props, - CoordinatePageComponent - ); -} +customEvent(CoordinatePageComponent, { + instanceOf: [{ + element: Action, + listeners: ['select'], + invoke: ['actionSelected'] + }, { + element: SearchAction, + listeners: ['select'], + invoke: ['actionSelected'] + }, { + element: MenuAction, + listeners: ['tap'], + invoke: ['drawerItemSelected'] + }], + nameEvents: ['actionSelected', 'drawerItemSelected'] +}) /** * @description * encapsula en un proxy cuando se ejecute como funcion o instancia */ -export const CoordinatePage = createProxies( - ProxyCoordinatePage, - resolveParameter +export const CoordinatePage = createProxies( + CoordinatePageComponent ); \ No newline at end of file diff --git a/src/navigation/menu.ts b/src/navigation/menu.ts index 6806bc6..e302e03 100644 --- a/src/navigation/menu.ts +++ b/src/navigation/menu.ts @@ -1,6 +1,6 @@ import { type Widget, - type WidgetCollection, + WidgetCollection, drawer, Constraint, TextView, @@ -10,20 +10,20 @@ import { ScrollView, } from "tabris"; -type MenuItemOf = MenuItem; +export type MenuItemOf = MenuItem; -type MenuOption = { - [key: string]: IMenuItemOption; +export type MenuOption = { + [key: string]: MenuItemOption; }; -export interface IMenuItemOption { +export interface MenuItemOption { id: string; text: string; image?: string; } -class MenuItem extends Composite { - constructor(id: string) { +export class MenuAction extends Composite { + constructor(id?: string) { super({ id, top: Constraint.prev, @@ -35,37 +35,61 @@ class MenuItem extends Composite { } } +export class MenuItem extends Row { + constructor(props: any) { + super({ + layoutData: "stretch", + alignment: "centerY", + }); + this.id = props.id; + this._setElements(props.image, props.text); + } + + _setElements(img: any, text: string) { + const refImage = 'voir-img-ref-' + this.id; + const refText = 'voir-text-ref-' + this.id; + + if (img) this.append(ImageView({ + image: img, + width: 24, + left: 28, + id: refImage + })) + + const separatorLeft = !img ? 28 + 24 + 12 : 12; + + this.append(TextView({ + text: text, + font: "20px sans-serif", + left: separatorLeft, + id: refText + })) + } + + text: string + image: any +} + /** * @version 0.4 - * no posee hijos y su padre es DrawerMenu */ -export const DrawerMenuItem = (props: IMenuItemOption) => { - return ()=> props; -} +export const DrawerMenuItem = MenuItem; /** * @version 0.4 * contenedor para DrawerMenuItem */ -export const DrawerMenu = ({children}: {children: ReturnType[]}) => { - return ()=> { - const props: IMenuItemOption[] = []; - for (const child of children) { - if (typeof child === 'function') props.push(child()); - } - return props; - }; +export const DrawerMenu = ({ children }: { children: Widget[] }) => { + return new WidgetCollection(children); } -export type { MenuItemOf }; - /** * @deprecated * emite un warning desde la version 0.4 */ export const menuDrawer = ( - menus: IMenuItemOption[], - eventSelectMenu: (menu: MenuItem) => void + menus: MenuItemOption[] | WidgetCollection, + eventSelectMenu: (menu: MenuAction) => void ) => { console.warn('deprecated function [menuDrawer] use setMenuDrawer'); setMenuDrawer(menus, eventSelectMenu); @@ -73,7 +97,7 @@ export const menuDrawer = ( function getScrollLayoutDrawer() { const scrollLayout = drawer.find('#scrollableLayoutMenuDrawer'); - + const layoutMenu = (scrollLayout.length !== 0 ? scrollLayout.only() as ScrollView : ScrollView({ id: "scrollableLayoutMenuDrawer", top: Constraint.prev, @@ -83,7 +107,7 @@ function getScrollLayoutDrawer() { })); if (scrollLayout.length === 0) drawer.append(layoutMenu); - + return layoutMenu; } @@ -91,37 +115,22 @@ function getScrollLayoutDrawer() { * @version 0.4 */ export function setMenuDrawer( - menus: IMenuItemOption[], - eventSelectMenu: (menu: MenuItem) => void + menus: MenuItemOption[] | WidgetCollection, + eventSelectMenu?: (menu: MenuAction) => void ) { - const scrollLayout = getScrollLayoutDrawer().append( - menus.map((data: IMenuItemOption) => { - const row = Row({ - layoutData: "stretch", - alignment: "centerY", - }); - if (!!data.image) - row.append( - ImageView({ - image: data.image, - width: 24, - left: 28, - }) - ); - - const separatorLeft = !data.image ? 28 + 24 + 12 : 12; - - row.append( - TextView({ - text: data.text, - font: "20px sans-serif", - left: separatorLeft, + getScrollLayoutDrawer().append( + menus.map(data => { + const isObject = data instanceof MenuItem; + const id = data.id; + if (isObject) data.id = ''; + return new MenuAction(id).append( + isObject ? data : new MenuItem({ + image: data.image, + text: data.text }) - ); - - return new MenuItem(data.id).append(row).onTap(function () { - eventSelectMenu(this as MenuItem); - setTimeout(() => drawer.close(), 100); + ).onTap(function () { + if (typeof eventSelectMenu === 'function') eventSelectMenu(this); + const id = setTimeout(() => (drawer.close(), clearTimeout(id)), 100); }); }) ); @@ -134,12 +143,12 @@ export function setContentDrawer(view: Widget) { const scrollLayout = getScrollLayoutDrawer(); const findContent: WidgetCollection = drawer.find('#voirContentDrawer'); const content = findContent.length === 0 ? Composite({ - top: [Constraint.prev, 15], - left: 0, - right: 0, - id: 'voirContentDrawer', - padding: 8 - }).append(view) + top: [Constraint.prev, 15], + left: 0, + right: 0, + id: 'voirContentDrawer', + padding: 8 + }).append(view) : findContent.only().append(view); if (findContent.length === 0) scrollLayout.append(content); - } \ No newline at end of file +} \ No newline at end of file diff --git a/src/preference/CheckBoxPreference.ts b/src/preference/CheckBoxPreference.ts index 35ed9f6..cdbd78b 100644 --- a/src/preference/CheckBoxPreference.ts +++ b/src/preference/CheckBoxPreference.ts @@ -2,10 +2,6 @@ import { CheckBox, Properties } from "tabris"; import { createProxies } from "../utils/proxy"; import { Checked } from "./AbstractCheked"; -function ProxyCheckBoxPreference(props: Properties = {}) { - return new CheckBoxPreferenceComponent(props); -} - export class CheckBoxPreferenceComponent extends Checked { constructor(props: Properties) { super(props); @@ -16,4 +12,4 @@ export class CheckBoxPreferenceComponent extends Checked { } } -export const CheckBoxPreference = createProxies(ProxyCheckBoxPreference); +export const CheckBoxPreference = createProxies(CheckBoxPreferenceComponent); diff --git a/src/preference/ListPreference.ts b/src/preference/ListPreference.ts index 884f099..4fb7d43 100644 --- a/src/preference/ListPreference.ts +++ b/src/preference/ListPreference.ts @@ -16,10 +16,6 @@ export interface IEntry { checked?: boolean; } -function ProxyListPreference(props: Properties = {}) { - return new ListPreferenceComponent(props); -} - export class ListPreferenceComponent extends Checked { entries: IEntry[]; textButtonAccept: string; @@ -44,7 +40,7 @@ export class ListPreferenceComponent extends Checked { if (this.entries && this.entries.length > 0) { modal.addView( ...this.entries.map((entry, index) => { - const radiobtn = RadioButton({ + const radio = RadioButton({ text: entry.text, checked: entry.checked ?? @@ -64,10 +60,10 @@ export class ListPreferenceComponent extends Checked { }); if (entry.id) { - radiobtn.id = entry.id; + radio.id = entry.id; } - return radiobtn; + return radio; }) ); } @@ -84,7 +80,7 @@ export class ListPreferenceComponent extends Checked { } } -export const ListPreference = createProxies(ProxyListPreference); +export const ListPreference = createProxies(ListPreferenceComponent); defineProperty(ListPreferenceComponent.prototype, "entries", { type: "any", diff --git a/src/preference/PreferenceScreen.ts b/src/preference/PreferenceScreen.ts index ab754e4..4c80ab3 100644 --- a/src/preference/PreferenceScreen.ts +++ b/src/preference/PreferenceScreen.ts @@ -4,19 +4,12 @@ import { createInstance } from "../utils/helpers"; export class PreferenceScreenComponent extends Page { constructor(props?: Properties) { - super(props); + super({ + ...props, + layoutData: "stretch" + }); } } -function preferenceScreen(props: Properties) { - return createInstance( - { - layoutData: "stretch", - ...props, - }, - PreferenceScreenComponent - ); -} -export const PreferenceScreen = - createProxies(preferenceScreen); +export const PreferenceScreen = createProxies(PreferenceScreenComponent); diff --git a/src/preference/SwitchPreference.ts b/src/preference/SwitchPreference.ts index 2001047..9e4ac21 100644 --- a/src/preference/SwitchPreference.ts +++ b/src/preference/SwitchPreference.ts @@ -2,12 +2,6 @@ import { Switch, Properties } from "tabris"; import { createProxies } from "../utils/proxy"; import { Checked } from "./AbstractCheked"; -function ProxySwitchPreference( - props: Properties = {} -) { - return new SwitchPreferenceComponent(props); -} - export class SwitchPreferenceComponent extends Checked { onChange: any; @@ -20,4 +14,4 @@ export class SwitchPreferenceComponent extends Checked { } } -export const SwitchPreference = createProxies(ProxySwitchPreference); +export const SwitchPreference = createProxies(SwitchPreferenceComponent); diff --git a/src/preference/TextPreference.ts b/src/preference/TextPreference.ts index fc66e5e..95da81f 100644 --- a/src/preference/TextPreference.ts +++ b/src/preference/TextPreference.ts @@ -2,10 +2,6 @@ import { TextView, Properties } from "tabris"; import ItemPreference from "./AbstractItemPreference"; import { createProxies } from "../utils/proxy"; -function ProxyTextPreference(props: Properties) { - return new TextPreferenceComponent(props); -} - export class TextPreferenceComponent extends ItemPreference { constructor(props: Properties) { super(props) @@ -13,4 +9,4 @@ export class TextPreferenceComponent extends ItemPreference { } -export const TextPreference = createProxies(ProxyTextPreference); +export const TextPreference = createProxies(TextPreferenceComponent); diff --git a/src/utils/custom-events.js b/src/utils/custom-events.js new file mode 100644 index 0000000..4bde94f --- /dev/null +++ b/src/utils/custom-events.js @@ -0,0 +1,46 @@ +import { Listeners } from "tabris"; + +const events = new Map(); + +function getConstructor(ctx) { + return ctx instanceof Object && ctx.constructor ? ctx.constructor : ctx; +} + +function getEventManager(ctx) { + return events.get(getConstructor(ctx)); +} + +customEvent.addListener = (ctx, name, handler) => { + const { store } = getEventManager(ctx); + if (!store.has(ctx)) { + store.set(ctx, {event: {}, listeners: new WeakMap()}); + } + store.get(ctx).event[name] = handler; +} + +customEvent.listener = (ctx, ctx2) => { + const { instanceOf, store } = getEventManager(ctx); + for (let { listeners: nameEvents, element, invoke } of instanceOf) { + if (!(ctx2 instanceof element)) continue; + const realHandler = store.get(ctx); + //console.log(realHandler, ctx); + if (realHandler.listeners.has(ctx2)) continue; + realHandler.listeners.set(ctx2, nameEvents.map(nameEvent => { + const event = new Listeners(ctx2, nameEvent); + event.addListener((evt) => { + for (let typeInvoke of invoke) { + realHandler.event[typeInvoke](evt.target, evt); + } + }); + return event; + })) + } +} + +export function customEvent(construct, defEvent) { + if (events.has(construct)) return; + events.set(construct, { + ...defEvent, + store: new WeakMap() + }); +} \ No newline at end of file diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index c755f7b..127df2d 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,14 +1,13 @@ -import type { CallbackInstance } from "./proxy"; -import type { Composite } from "tabris"; +import type { Composite, Constructor } from "tabris"; export function createInstance( props: any, - $Class: CallbackInstance + $Class: Constructor ): ClassType { const children = props.children; delete props.children; - + const instance = new $Class(props); if (children) instance.append(children); diff --git a/src/utils/proxy.ts b/src/utils/proxy.ts index ac1a8fe..a387b2e 100644 --- a/src/utils/proxy.ts +++ b/src/utils/proxy.ts @@ -1,56 +1,9 @@ -import { PreferenceParams } from "../preference/AbstractItemPreference"; -import { CoordinatePageComponent } from "../navigation"; -import { - IEntry, - ListPreferenceComponent, - PreferenceScreenComponent, -} from "../preference"; -import type { - AnyWidget, - ApplyAttributes, - CheckBox, - Composite, - JSXAttributes, - PropertyChangedEvent, - RadioButton, - RadioButtonSelectEvent, - Switch, -} from "tabris"; +import { Constructor } from "tabris"; -type CallbackAppend = (widgets: any[]) => any; +type Callback = Constructor | (() => T); +type Handler = (new ()=> T) & (()=> T) -type OptionalAtrributes = { - [K in keyof T]?: T[K]; -}; - -type Attributes = View extends - | PreferenceScreenComponent - | CoordinatePageComponent - ? JSXAttributes & { - children?: AnyWidget[]; - } - : OptionalAtrributes & { - onSelect?: ( - event: View extends RadioButton - ? RadioButtonSelectEvent - : PropertyChangedEvent< - RadioButton | Switch | CheckBox, - boolean - > - ) => any; - } & (View extends ListPreferenceComponent ? { entries: IEntry[] } : {}); - -export type CallbackInstance = new ( - props: Attributes -) => View; -export type Callable = ( - props?: Attributes -) => View; -export type Callback = - | CallbackInstance - | Callable; - -export function createProxies(component: Callback) { +export function createProxies(component: Constructor) { const ProxiesCallback = new Proxy( component, { @@ -66,26 +19,17 @@ export function createProxies(component: Callback) { return ProxiesCallback; } -type Args = C extends Composite ? Attributes[] : any[]; -interface Constructor extends Function { - new(...args: Args): T; - (...iargs: Args): T; -} - -export function factory< - T extends Function, ->(fac: T) { - type Caller = Constructor; - const handler: ProxyHandler> = { +export function factory(fac: Callback): Handler { + const handler: ProxyHandler = { get(target, p, receiver) { return Reflect.get(target, p, receiver); }, apply(target, thisArg, argArray) { if (typeof target.name === 'string' && typeof target.constructor === 'function') { - return Reflect.construct(target, thisArg); + return Reflect.construct(target, argArray); } - return Reflect.apply(null, target, thisArg); + return Reflect.apply(null, target, argArray); } } - return new Proxy(fac as unknown as Caller, handler); + return new Proxy(fac, handler) as unknown as Handler; } \ No newline at end of file