apprun 3.33.9 → 3.33.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/.clinerules +1 -0
  2. package/LICENSE +1 -1
  3. package/README.md +1 -1
  4. package/WHATSNEW.md +59 -0
  5. package/apprun.d.ts +6 -0
  6. package/dist/apprun-dev-tools.js +1 -1
  7. package/dist/apprun-dev-tools.js.map +1 -1
  8. package/dist/apprun-html.esm.js +21 -4
  9. package/dist/apprun-html.esm.js.map +1 -1
  10. package/dist/apprun-html.js +1 -1
  11. package/dist/apprun-html.js.LICENSE.txt +6 -0
  12. package/dist/apprun-html.js.map +1 -1
  13. package/dist/apprun-play-html.esm.js +21 -4
  14. package/dist/apprun-play-html.esm.js.map +1 -1
  15. package/dist/apprun-play.js +1 -1
  16. package/dist/apprun-play.js.map +1 -1
  17. package/dist/apprun.esm.js +1 -1
  18. package/dist/apprun.esm.js.map +1 -1
  19. package/dist/apprun.js +1 -1
  20. package/dist/apprun.js.map +1 -1
  21. package/esm/app.js +37 -9
  22. package/esm/app.js.map +1 -1
  23. package/esm/apprun-code.js.map +1 -1
  24. package/esm/apprun-dev-tools-tests.js.map +1 -1
  25. package/esm/apprun-dev-tools.js.map +1 -1
  26. package/esm/apprun-html.js.map +1 -1
  27. package/esm/apprun-play.js.map +1 -1
  28. package/esm/apprun.js +55 -3
  29. package/esm/apprun.js.map +1 -1
  30. package/esm/component.js +59 -1
  31. package/esm/component.js.map +1 -1
  32. package/esm/decorator.js +33 -0
  33. package/esm/decorator.js.map +1 -1
  34. package/esm/directive.js +31 -0
  35. package/esm/directive.js.map +1 -1
  36. package/esm/router.js +24 -0
  37. package/esm/router.js.map +1 -1
  38. package/esm/types.js +28 -0
  39. package/esm/types.js.map +1 -1
  40. package/esm/vdom-lit-html.js +19 -17
  41. package/esm/vdom-lit-html.js.map +1 -1
  42. package/esm/vdom-my.js.map +1 -1
  43. package/esm/vdom-patch.js.map +1 -1
  44. package/esm/vdom-to-html.js.map +1 -1
  45. package/esm/vdom.js +24 -0
  46. package/esm/vdom.js.map +1 -1
  47. package/esm/web-component.js +32 -0
  48. package/esm/web-component.js.map +1 -1
  49. package/index.html +2 -2
  50. package/jest.config.js +63 -0
  51. package/jest.setup.js +47 -0
  52. package/jsx-runtime.js +1 -1
  53. package/jsx-runtime.js.map +1 -1
  54. package/package.json +16 -43
  55. package/react.js +0 -15
  56. package/rollup.config.js +27 -10
  57. package/src/app.ts +61 -28
  58. package/src/apprun.ts +82 -7
  59. package/src/component.ts +57 -1
  60. package/src/decorator.ts +34 -1
  61. package/src/directive.ts +33 -1
  62. package/src/global.d.ts +22 -0
  63. package/src/router.ts +26 -1
  64. package/src/types/apprun.d.ts +56 -0
  65. package/src/types.ts +30 -1
  66. package/src/vdom-lit-html.ts +21 -19
  67. package/src/vdom.ts +25 -2
  68. package/src/web-component.ts +33 -0
  69. package/tsconfig.jest.json +27 -3
  70. package/tsconfig.json +3 -3
  71. package/webpack.config.cjs +9 -2
package/src/app.ts CHANGED
@@ -1,28 +1,59 @@
1
+ /**
2
+ * Core AppRun application class and singleton instance
3
+ *
4
+ * This file provides:
5
+ * 1. App class - The core event system implementation with pub/sub capabilities
6
+ * - on(): Subscribe to events
7
+ * - off(): Unsubscribe from events
8
+ * - run(): Publish events synchronously
9
+ * - runAsync(): Publish events asynchronously
10
+ * - query(): Alias for runAsync
11
+ *
12
+ * 2. Default app singleton - Global event bus instance
13
+ * - Created once and reused across the application
14
+ * - Stored in global scope (window/global)
15
+ * - Version tracked to prevent duplicate instances
16
+ *
17
+ * Usage:
18
+ * ```ts
19
+ * // Subscribe to events
20
+ * app.on('event-name', (state, ...args) => {
21
+ * // Handle event
22
+ * });
23
+ *
24
+ * // Publish events
25
+ * app.run('event-name', ...args);
26
+ * ```
27
+ */
28
+
1
29
  import { EventOptions} from './types'
30
+
2
31
  export class App {
3
32
 
4
- _events: Object;
33
+ _events: { [key: string]: Array<{ fn: (...args: any[]) => any, options: EventOptions }> };
5
34
 
6
- public start;
7
- public h;
8
- public createElement;
9
- public render;
10
- public Fragment;
11
- public webComponent;
12
- public safeHTML;
13
- public use_render;
14
- public use_react;
35
+ public start: any;
36
+ public h: any;
37
+ public createElement: any;
38
+ public render: any;
39
+ public Fragment: any;
40
+ public webComponent: any;
41
+ public safeHTML: any;
42
+ public use_render: any;
43
+ public use_react: any;
44
+ public route: any;
45
+ public use_prettyLink: () => void;
15
46
 
16
47
  constructor() {
17
- this._events = {};
48
+ this._events = {} as { [key: string]: Array<{ fn: (...args: any[]) => any, options: EventOptions }> };
18
49
  }
19
50
 
20
- on(name: string, fn: (...args) => void, options: EventOptions = {}): void {
51
+ on(name: string, fn: (...args: any[]) => any, options: EventOptions = {}): void {
21
52
  this._events[name] = this._events[name] || [];
22
53
  this._events[name].push({ fn, options });
23
54
  }
24
55
 
25
- off(name: string, fn: (...args) => void): void {
56
+ off(name: string, fn: (...args: any[]) => any): void {
26
57
  const subscribers = this._events[name] || [];
27
58
 
28
59
  this._events[name] = subscribers.filter((sub) => sub.fn !== fn);
@@ -32,7 +63,7 @@ export class App {
32
63
  return this._events[name];
33
64
  }
34
65
 
35
- run(name: string, ...args): number {
66
+ run(name: string, ...args: any[]): number {
36
67
  const subscribers = this.getSubscribers(name, this._events);
37
68
  console.assert(subscribers && subscribers.length > 0, 'No subscriber for event: ' + name);
38
69
  subscribers.forEach((sub) => {
@@ -48,11 +79,11 @@ export class App {
48
79
  return subscribers.length;
49
80
  }
50
81
 
51
- once(name: string, fn, options: EventOptions = {}): void {
82
+ once(name: string, fn: (...args: any[]) => any, options: EventOptions = {}): void {
52
83
  this.on(name, fn, { ...options, once: true });
53
84
  }
54
85
 
55
- private delay(name, fn, args, options): void {
86
+ private delay(name: string, fn: (...args: any[]) => any, args: any[], options: EventOptions): void {
56
87
  if (options._t) clearTimeout(options._t);
57
88
  options._t = setTimeout(() => {
58
89
  clearTimeout(options._t);
@@ -60,7 +91,7 @@ export class App {
60
91
  }, options.delay);
61
92
  }
62
93
 
63
- runAsync(name: string, ...args): Promise<any[]> {
94
+ runAsync(name: string, ...args: any[]): Promise<any[]> {
64
95
  const subscribers = this.getSubscribers(name, this._events);
65
96
  console.assert(subscribers && subscribers.length > 0, 'No subscriber for event: ' + name);
66
97
  const promises = subscribers.map(sub => {
@@ -70,11 +101,11 @@ export class App {
70
101
  return Promise.all(promises);
71
102
  }
72
103
 
73
- query(name: string, ...args): Promise<any[]> {
104
+ query(name: string, ...args: any[]): Promise<any[]> {
74
105
  return this.runAsync(name, ...args);
75
106
  }
76
107
 
77
- private getSubscribers(name: string, events) {
108
+ private getSubscribers(name: string, events: { [key: string]: Array<{ fn: (...args: any[]) => any, options: EventOptions }> }): Array<{ fn: (...args: any[]) => any, options: EventOptions }> {
78
109
  const subscribers = events[name] || [];
79
110
 
80
111
  // Update the list of subscribers by pulling out those which will run once.
@@ -94,14 +125,16 @@ export class App {
94
125
  }
95
126
 
96
127
  const AppRunVersions = 'AppRun-3';
97
- let app: App;
98
- const root = (typeof self === 'object' && self.self === self && self) ||
99
- (typeof global === 'object' && global.global === global && global)
100
- if (root['app'] && root['_AppRunVersions']) {
101
- app = root['app'];
128
+ let _app: App;
129
+ const root = (typeof window !== 'undefined' ? window :
130
+ typeof global !== 'undefined' ? global :
131
+ typeof self !== 'undefined' ? self : {}) as any;
132
+
133
+ if (root.app && root._AppRunVersions) {
134
+ _app = root.app;
102
135
  } else {
103
- app = new App();
104
- root['app'] = app;
105
- root['_AppRunVersions'] = AppRunVersions;
136
+ _app = new App();
137
+ root.app = _app;
138
+ root._AppRunVersions = AppRunVersions;
106
139
  }
107
- export default app;
140
+ export default _app;
package/src/apprun.ts CHANGED
@@ -1,3 +1,37 @@
1
+ /**
2
+ * Main AppRun framework entry point
3
+ *
4
+ * This file:
5
+ * 1. Assembles core AppRun modules into a complete framework
6
+ * 2. Exports public API and types
7
+ * 3. Initializes global app instance with:
8
+ * - Virtual DOM rendering
9
+ * - Component system
10
+ * - Router
11
+ * - Web component support
12
+ *
13
+ * Key exports:
14
+ * - app: Global event system instance
15
+ * - Component: Base component class
16
+ * - Decorators: @on, @update, @customElement
17
+ * - Router events and configuration
18
+ * - Web component registration
19
+ *
20
+ * Usage:
21
+ * ```ts
22
+ * import { app, Component } from 'apprun';
23
+ *
24
+ * // Create components
25
+ * class MyComponent extends Component {
26
+ * state = // Initial state
27
+ * view = state => // Render view
28
+ * update = {
29
+ * 'event': (state, ...args) => // Handle events
30
+ * }
31
+ * }
32
+ * ```
33
+ */
34
+
1
35
  import app, { App } from './app';
2
36
  import { createElement, render, Fragment, safeHTML } from './vdom';
3
37
  import { Component } from './component';
@@ -7,7 +41,26 @@ import webComponent, { CustomElementOptions } from './web-component';
7
41
  import { Route, route, ROUTER_EVENT, ROUTER_404_EVENT } from './router';
8
42
 
9
43
  export type StatelessComponent<T = {}> = (args: T) => string | VNode | void;
10
- export { App, app, Component, View, Action, Update, on, update, EventOptions, ActionOptions, MountOptions, Fragment, safeHTML }
44
+ type OnDecorator = {
45
+ <T = any>(options?: any): (constructor: Function) => void;
46
+ <E = string>(events?: E, options?: any): (target: any, key: string) => void;
47
+ };
48
+
49
+ export {
50
+ App,
51
+ app,
52
+ Component,
53
+ View,
54
+ Action,
55
+ Update,
56
+ on,
57
+ update,
58
+ EventOptions,
59
+ ActionOptions,
60
+ MountOptions,
61
+ Fragment,
62
+ safeHTML
63
+ }
11
64
  export { update as event };
12
65
  export { ROUTER_EVENT, ROUTER_404_EVENT };
13
66
  export { customElement, CustomElementOptions, AppStartOptions };
@@ -65,19 +118,26 @@ if (!app.start) {
65
118
  });
66
119
  }
67
120
 
121
+ type ComponentType = typeof Component & {
122
+ <T = any>(options?: any): (constructor: Function) => void;
123
+ };
124
+
68
125
  if (typeof window === 'object') {
69
- window['Component'] = Component;
126
+ window['Component'] = Component as ComponentType;
70
127
  window['_React'] = window['React'];
71
128
  window['React'] = app;
72
- window['on'] = on;
129
+ window['on'] = on as OnDecorator;
73
130
  window['customElement'] = customElement;
74
131
  window['safeHTML'] = safeHTML;
75
132
  }
76
133
 
77
- app.use_render = (render, mode = 0) =>
78
- mode === 0 ?
79
- app.render = (el, vdom) => render(vdom, el) : // react style
80
- app.render = (el, vdom) => render(el, vdom); // apprun style
134
+ app.use_render = (render, mode = 0) => {
135
+ if (mode === 0) {
136
+ app.render = (el, vdom) => render(vdom, el); // react style
137
+ } else {
138
+ app.render = (el, vdom) => render(el, vdom); // apprun style
139
+ }
140
+ };
81
141
 
82
142
  app.use_react = (React, ReactDOM) => {
83
143
  app.h = app.createElement = React.createElement;
@@ -91,4 +151,19 @@ if (!app.start) {
91
151
  }
92
152
  }
93
153
  }
154
+
155
+ app.use_prettyLink = () => {
156
+ window.onload = () => app.route(location.pathname);
157
+ window.addEventListener("popstate", () => app.route(location.pathname));
158
+ document.body.addEventListener('click', e => {
159
+ const element = e.target as HTMLElement;
160
+ const menu = (element.tagName === 'A' ? element : element.closest('a')) as HTMLAnchorElement;
161
+ if (menu &&
162
+ menu.origin === location.origin) {
163
+ e.preventDefault();
164
+ history.pushState(null, '', menu.pathname);
165
+ app.route(menu.pathname);
166
+ }
167
+ });
168
+ }
94
169
  }
package/src/component.ts CHANGED
@@ -1,3 +1,36 @@
1
+ /**
2
+ * AppRun Component System Implementation
3
+ *
4
+ * This file provides the Component class which is the foundation for:
5
+ * 1. State Management
6
+ * - Maintains component state
7
+ * - Handles state updates
8
+ * - Supports state history
9
+ *
10
+ * 2. View Rendering
11
+ * - Renders virtual DOM to real DOM
12
+ * - Handles component lifecycle (mounted, rendered, unload)
13
+ * - Supports shadow DOM and web components
14
+ *
15
+ * 3. Event Handling
16
+ * - Local and global event subscription
17
+ * - Event handler registration via decorators
18
+ * - Action to state updates
19
+ *
20
+ * Usage:
21
+ * ```ts
22
+ * class MyComponent extends Component {
23
+ * state = // Initial state
24
+ * view = state => // Return virtual DOM
25
+ * update = {
26
+ * 'event': (state, ...args) => // Return new state
27
+ * }
28
+ * }
29
+ *
30
+ * // Mount component
31
+ * new MyComponent().mount('element-id');
32
+ * ```
33
+ */
1
34
 
2
35
  import app, { App } from './app';
3
36
  import { Reflect } from './decorator'
@@ -79,7 +112,30 @@ export class Component<T = any, E = any> {
79
112
 
80
113
  public setState(state: T, options: ActionOptions & EventOptions
81
114
  = { render: true, history: false }) {
82
- if (state instanceof Promise) {
115
+
116
+ const handleAsyncIterator = async (iterator: AsyncIterator<T>) => {
117
+ try {
118
+ while (true) {
119
+ const { value, done } = await iterator.next();
120
+ if (done) break;
121
+ this.setState(value, options);
122
+ }
123
+ } catch (e) {
124
+ console.error('Error in async iterator:', e);
125
+ }
126
+ };
127
+
128
+ const result = state as any;
129
+ if (result?.[Symbol.asyncIterator]) {
130
+ // handleAsyncIterator(result[Symbol.asyncIterator]());
131
+ this.setState(handleAsyncIterator(result[Symbol.asyncIterator]()) as any, options);
132
+ return;
133
+ } else if (result?.[Symbol.iterator] && typeof result.next === "function") {
134
+ for (const value of result) {
135
+ this.setState(value, options);
136
+ }
137
+ return;
138
+ } else if (state && state instanceof Promise) {
83
139
  // Promise will not be saved or rendered
84
140
  // state will be saved and rendered when promise is resolved
85
141
  Promise.resolve(state).then(v => {
package/src/decorator.ts CHANGED
@@ -1,5 +1,39 @@
1
1
  import webComponent, { CustomElementOptions } from './web-component';
2
2
 
3
+ /**
4
+ * TypeScript Decorators for AppRun Components
5
+ *
6
+ * This file provides decorators that enable:
7
+ * 1. Event Handler Registration
8
+ * - @on(): Subscribe to events with options
9
+ * - @update(): Define state updates with metadata
10
+ *
11
+ * 2. Web Component Integration
12
+ * - @customElement(): Register as custom element with options
13
+ * - Handles shadow DOM and attribute observation
14
+ *
15
+ * 3. Metadata Management
16
+ * - Custom Reflect implementation for decorator metadata
17
+ * - Stores event handler and update metadata
18
+ * - Supports runtime reflection for dynamic behavior
19
+ *
20
+ * Usage:
21
+ * ```ts
22
+ * @customElement('my-element')
23
+ * class MyComponent extends Component {
24
+ * @on('event')
25
+ * handler(state, ...args) {
26
+ * // Handle event
27
+ * }
28
+ *
29
+ * @update('event')
30
+ * updater(state, ...args) {
31
+ * // Update state
32
+ * }
33
+ * }
34
+ * ```
35
+ */
36
+
3
37
  // tslint:disable:no-invalid-this
4
38
  export const Reflect = {
5
39
 
@@ -44,4 +78,3 @@ export function customElement(name: string, options?: CustomElementOptions) {
44
78
  return constructor;
45
79
  }
46
80
  }
47
-
package/src/directive.ts CHANGED
@@ -1,3 +1,35 @@
1
+ /**
2
+ * Component Directives Implementation
3
+ *
4
+ * This file provides built-in directives for components:
5
+ * 1. Event Binding
6
+ * - $on: Bind DOM events to component events
7
+ * - Supports event delegation and parameters
8
+ * - Handles function, string, and array event handlers
9
+ *
10
+ * 2. Two-way Data Binding
11
+ * - $bind: Sync form elements with component state
12
+ * - Handles input types: text, checkbox, radio, select
13
+ * - Automatic value type conversion
14
+ * - Support for complex property paths
15
+ *
16
+ * 3. Custom Directives
17
+ * - Extensible directive system
18
+ * - Processes virtual DOM during rendering
19
+ * - Supports custom attribute directives
20
+ *
21
+ * Usage:
22
+ * ```tsx
23
+ * // Event binding
24
+ * <button $onclick="event-name">Click</button>
25
+ * <input $oninput={e => setState(e.target.value)} />
26
+ *
27
+ * // Two-way binding
28
+ * <input $bind="state.property" />
29
+ * <select $bind="selected">...</select>
30
+ * ```
31
+ */
32
+
1
33
  import app from './app';
2
34
 
3
35
  const getStateValue = (component, name) => {
@@ -92,4 +124,4 @@ const directive = (vdom, component) => {
92
124
  }
93
125
  }
94
126
 
95
- export default directive;
127
+ export default directive;
@@ -0,0 +1,22 @@
1
+ import { App } from './app';
2
+ import { Component } from './component';
3
+
4
+ declare global {
5
+ var app: App;
6
+ var _AppRunVersions: string;
7
+ interface Window {
8
+ app: App;
9
+ _AppRunVersions: string;
10
+ Component: typeof Component & {
11
+ <T = any>(options?: any): (constructor: Function) => void;
12
+ };
13
+ _React: any;
14
+ React: App;
15
+ on: {
16
+ <T = any>(options?: any): (constructor: Function) => void;
17
+ <E = string>(events?: E, options?: any): (target: any, key: string) => void;
18
+ };
19
+ customElement: (name: string) => (constructor: Function) => void;
20
+ safeHTML: (html: string) => any[];
21
+ }
22
+ }
package/src/router.ts CHANGED
@@ -1,3 +1,28 @@
1
+ /**
2
+ * AppRun Router Implementation
3
+ *
4
+ * This file provides URL routing capabilities:
5
+ * 1. Hash-based routing (#/path)
6
+ * 2. Path-based routing (/path)
7
+ * 3. Event-based navigation
8
+ *
9
+ * Features:
10
+ * - Automatic route event firing
11
+ * - 404 handling via ROUTER_404_EVENT
12
+ * - History API integration
13
+ * - Route parameter parsing
14
+ *
15
+ * Usage:
16
+ * ```ts
17
+ * // Handle routes
18
+ * app.on('#/home', () => // Show home page);
19
+ * app.on('#/users/:id', (id) => // Show user profile);
20
+ *
21
+ * // Navigate programmatically
22
+ * app.run('route', '#/home');
23
+ * ```
24
+ */
25
+
1
26
  import app from './app';
2
27
 
3
28
  export type Route = (url: string, ...args: any[]) => any;
@@ -20,4 +45,4 @@ export const route: Route = (url: string) => {
20
45
  app.run(ROUTER_EVENT, url);
21
46
  }
22
47
  }
23
- export default route;
48
+ export default route;
@@ -0,0 +1,56 @@
1
+ declare type VNode = {
2
+ tag: string;
3
+ props?: Record<string, any>;
4
+ children?: Array<VNode | string | number>;
5
+ } | string | number;
6
+
7
+ declare type VDOM = VNode | VNode[];
8
+
9
+ declare type View<T = any> = (state: T) => VDOM | void;
10
+ declare type Action<T = any> = (state: T, ...p: any[]) => T | void | Promise<T>;
11
+ declare type ActionDef<T = any> = [Action<T>, object?];
12
+ declare type Update<T = any> = { [name: string]: Action<T> | ActionDef<T> | Array<Action<T> | ActionDef<T>> };
13
+
14
+ declare interface IApp {
15
+ start<T>(element?: Element | string | null, model?: T, view?: View<T>, update?: Update<T>, options?: AppStartOptions): Component<T>;
16
+ on(name: string, fn: (...args: any[]) => void, options?: any): void;
17
+ run(name: string, ...args: any[]): void;
18
+ createElement(tag: string | Function, props?: any, ...children: any[]): VNode;
19
+ render(element: Element, node: VNode): void;
20
+ }
21
+
22
+ declare interface Component<T = any> {
23
+ readonly state: T;
24
+ setState(state: T, options?: any): void;
25
+ mount(element?: Element | string | null, options?: any): Component<T>;
26
+ start(element?: Element | string | null, options?: any): Component<T>;
27
+ run(name: string, ...args: any[]): void;
28
+ rendered?: (state: T) => void;
29
+ view?: View<T>;
30
+ update?: Update<T>;
31
+ element?: Element;
32
+ }
33
+
34
+ declare interface CustomElementOptions {
35
+ render?: boolean;
36
+ shadow?: boolean;
37
+ history?: boolean | { prev: string; next: string };
38
+ global_event?: boolean;
39
+ route?: string;
40
+ }
41
+
42
+ declare interface AppStartOptions extends CustomElementOptions {
43
+ render?: boolean;
44
+ history?: boolean | { prev: string; next: string };
45
+ global_event?: boolean;
46
+ route?: string;
47
+ }
48
+
49
+ declare interface Route {
50
+ (url: string): void;
51
+ push(url: string, notify?: boolean): void;
52
+ }
53
+
54
+ declare const app: IApp;
55
+ declare function on<T = any>(name?: string, options?: any): (target: any, key: string) => void;
56
+ declare function Component<T = any>(options?: any): (constructor: Function) => void;
package/src/types.ts CHANGED
@@ -1,3 +1,32 @@
1
+ /**
2
+ * Core TypeScript Type Definitions
3
+ *
4
+ * This file defines the fundamental types used across AppRun:
5
+ * 1. Component Types
6
+ * - View: Function that renders state to VDOM
7
+ * - Action: Function that updates state
8
+ * - Update: Collection of actions
9
+ *
10
+ * 2. Virtual DOM Types
11
+ * - VNode: Virtual DOM node structure
12
+ * - VDOM: Union of possible VDOM types
13
+ * - Element: DOM element references
14
+ *
15
+ * 3. Configuration Types
16
+ * - EventOptions: Event handler options (once, delay, etc)
17
+ * - ActionOptions: Action behavior options (render, history, etc)
18
+ * - MountOptions: Component mounting options (global events, routing)
19
+ * - AppStartOptions: Application startup configuration
20
+ *
21
+ * Usage:
22
+ * ```ts
23
+ * class MyComponent implements Component<State> {
24
+ * view: View<State>;
25
+ * update: Update<State>;
26
+ * }
27
+ * ```
28
+ */
29
+
1
30
  import { TemplateResult } from 'lit-html';
2
31
  export type Element = HTMLElement | string;
3
32
  export type VNode = {
@@ -31,4 +60,4 @@ export type AppStartOptions<T> = {
31
60
  route?: string;
32
61
  rendered?: (state: T) => void
33
62
  mounted?: (props:any, children:any, state: T) => T
34
- };
63
+ };
@@ -1,9 +1,9 @@
1
1
  import { createElement, updateElement, Fragment } from './vdom-my';
2
2
 
3
3
 
4
- import { render, svg, html, noChange, nothing } from 'lit-html';
5
- import { directive, Directive, Part, PartInfo, PartType, EventPart } from 'lit-html/directive.js';
6
- import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
4
+ import { render, svg, html, noChange, nothing } from 'lit';
5
+ import { directive, Directive, PartInfo, ElementPart, DirectiveResult, EventPart, PartType } from 'lit/directive.js';
6
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
7
7
  import app from './apprun';
8
8
 
9
9
  function _render(element, vdom, parent?) {
@@ -26,32 +26,35 @@ export class RunDirective extends Directive {
26
26
  constructor(partInfo: PartInfo) {
27
27
  super(partInfo);
28
28
  // When necessary, validate part in constructor using `part.type`
29
- if (partInfo.type !== PartType.EVENT) {
30
- throw new Error('${run} can only be used in event handlers');
29
+ if (partInfo.type !== PartType.EVENT) { // In lit v3, use PartType.EVENT
30
+ throw new Error('run() can only be used in event handlers');
31
31
  }
32
32
  }
33
- // Optional: override update to perform any direct DOM manipulation
34
- update(part: Part, params) {
33
+ // Override update to perform any direct DOM manipulation
34
+ update(part: EventPart, props: Array<any>): DirectiveResult {
35
35
  /* Any imperative updates to DOM/parts would go here */
36
-
37
- let { element, name } = part as EventPart;
36
+ const element = part.element;
37
+ const name = part.name;
38
+ const [eventOrFn, ...args] = props;
39
+
38
40
  const getComponent = () => {
39
- let component = element['_component'];
40
- while (!component && element) {
41
- element = element.parentElement;
42
- component = element && element['_component'];
41
+ let el = element;
42
+ let component = el['_component'];
43
+ while (!component && el) {
44
+ el = el.parentElement;
45
+ component = el && el['_component'];
43
46
  }
44
47
  console.assert(!!component, 'Component not found.');
45
48
  return component;
46
49
  }
47
- const [event, ...args] = params;
48
- if (typeof event === 'string') {
50
+
51
+ if (typeof eventOrFn === 'string') {
49
52
  element[`on${name}`] = e => {
50
53
  const component = getComponent();
51
- component ? component.run(event, ...args, e) : app.run(event, ...args, e)
54
+ component ? component.run(eventOrFn, ...args, e) : app.run(eventOrFn, ...args, e)
52
55
  }
53
- } else if (typeof event === 'function') {
54
- element[`on${name}`] = e => getComponent().setState(event(getComponent().state, ...args, e));
56
+ } else if (typeof eventOrFn === 'function') {
57
+ element[`on${name}`] = e => getComponent().setState(eventOrFn(getComponent().state, ...args, e));
55
58
  }
56
59
  return this.render();
57
60
  }
@@ -62,4 +65,3 @@ export class RunDirective extends Directive {
62
65
 
63
66
  const run = directive(RunDirective) as any;
64
67
  export { createElement, Fragment, html, svg, _render as render, run };
65
-
package/src/vdom.ts CHANGED
@@ -1,5 +1,28 @@
1
+ /**
2
+ * Virtual DOM Implementation
3
+ *
4
+ * This file provides the core virtual DOM functionality:
5
+ * 1. createElement: Creates virtual DOM nodes
6
+ * 2. Fragment: Support for fragments
7
+ * 3. render: Renders virtual DOM to real DOM
8
+ * 4. safeHTML: Safely renders HTML strings
9
+ *
10
+ * The virtual DOM system:
11
+ * - Provides efficient DOM updates
12
+ * - Supports JSX compilation
13
+ * - Handles component rendering
14
+ * - Manages DOM diffing and patching
15
+ *
16
+ * Usage:
17
+ * ```ts
18
+ * // JSX gets compiled to createElement calls
19
+ * const vdom = <div id="app">Hello</div>;
20
+ *
21
+ * // Render to DOM
22
+ * render(document.body, vdom);
23
+ * ```
24
+ */
25
+
1
26
  import { createElement, updateElement, Fragment, safeHTML } from './vdom-my';
2
27
  export { createElement, Fragment, updateElement as render, safeHTML };
3
28
  export { createElement as jsx, createElement as jsxs };
4
-
5
-