airx 0.4.0 → 0.7.1

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 (150) hide show
  1. package/README.md +247 -63
  2. package/output/app/app.d.ts +41 -0
  3. package/output/app/app.d.ts.map +1 -0
  4. package/output/app/app.js +51 -0
  5. package/output/app/app.js.map +1 -0
  6. package/output/app/index.d.ts +2 -0
  7. package/output/app/index.d.ts.map +1 -0
  8. package/output/app/index.js +2 -0
  9. package/output/app/index.js.map +1 -0
  10. package/output/element/element.d.ts +108 -0
  11. package/output/element/element.d.ts.map +1 -0
  12. package/output/element/element.js +106 -0
  13. package/output/element/element.js.map +1 -0
  14. package/output/element/index.d.ts +2 -0
  15. package/output/element/index.d.ts.map +1 -0
  16. package/output/element/index.js +2 -0
  17. package/output/element/index.js.map +1 -0
  18. package/output/index.d.ts +40 -0
  19. package/output/index.d.ts.map +1 -0
  20. package/output/index.js +36 -0
  21. package/output/index.js.map +1 -0
  22. package/output/jsx-dev-runtime.d.ts +4 -0
  23. package/output/jsx-dev-runtime.d.ts.map +1 -0
  24. package/output/jsx-dev-runtime.js +9 -0
  25. package/output/jsx-dev-runtime.js.map +1 -0
  26. package/output/jsx-runtime.d.ts +23 -0
  27. package/output/jsx-runtime.d.ts.map +1 -0
  28. package/output/jsx-runtime.js +24 -0
  29. package/output/jsx-runtime.js.map +1 -0
  30. package/output/logger/index.d.ts +2 -0
  31. package/output/logger/index.d.ts.map +1 -0
  32. package/output/logger/index.js +2 -0
  33. package/output/logger/index.js.map +1 -0
  34. package/output/{esm → logger}/logger.d.ts +1 -0
  35. package/output/logger/logger.d.ts.map +1 -0
  36. package/output/logger/logger.js +17 -0
  37. package/output/logger/logger.js.map +1 -0
  38. package/output/{esm/render/common/index.d.ts → render/basic/common.d.ts} +4 -3
  39. package/output/render/basic/common.d.ts.map +1 -0
  40. package/output/render/basic/common.js +436 -0
  41. package/output/render/basic/common.js.map +1 -0
  42. package/output/render/basic/hooks/hooks.d.ts +61 -0
  43. package/output/render/basic/hooks/hooks.d.ts.map +1 -0
  44. package/output/render/basic/hooks/hooks.js +72 -0
  45. package/output/render/basic/hooks/hooks.js.map +1 -0
  46. package/output/render/basic/hooks/index.d.ts +2 -0
  47. package/output/render/basic/hooks/index.d.ts.map +1 -0
  48. package/output/render/basic/hooks/index.js +2 -0
  49. package/output/render/basic/hooks/index.js.map +1 -0
  50. package/output/render/basic/index.d.ts +2 -0
  51. package/output/render/basic/index.d.ts.map +1 -0
  52. package/output/render/basic/index.js +2 -0
  53. package/output/render/basic/index.js.map +1 -0
  54. package/output/{umd/render/common/plugins → render/basic/plugins/context}/context.d.ts +2 -1
  55. package/output/render/basic/plugins/context/context.d.ts.map +1 -0
  56. package/output/render/basic/plugins/context/context.js +12 -0
  57. package/output/render/basic/plugins/context/context.js.map +1 -0
  58. package/output/render/basic/plugins/context/index.d.ts +2 -0
  59. package/output/render/basic/plugins/context/index.d.ts.map +1 -0
  60. package/output/render/basic/plugins/context/index.js +2 -0
  61. package/output/render/basic/plugins/context/index.js.map +1 -0
  62. package/output/render/basic/plugins/index.d.ts +3 -0
  63. package/output/render/basic/plugins/index.d.ts.map +1 -0
  64. package/output/render/basic/plugins/index.js +2 -0
  65. package/output/render/basic/plugins/index.js.map +1 -0
  66. package/output/{umd/render/common/plugins/internal → render/basic/plugins/internal/basic}/basic.d.ts +4 -3
  67. package/output/render/basic/plugins/internal/basic/basic.d.ts.map +1 -0
  68. package/output/render/basic/plugins/internal/basic/basic.js +158 -0
  69. package/output/render/basic/plugins/internal/basic/basic.js.map +1 -0
  70. package/output/render/basic/plugins/internal/basic/index.d.ts +2 -0
  71. package/output/render/basic/plugins/internal/basic/index.d.ts.map +1 -0
  72. package/output/render/basic/plugins/internal/basic/index.js +2 -0
  73. package/output/render/basic/plugins/internal/basic/index.js.map +1 -0
  74. package/output/render/basic/plugins/internal/inject/index.d.ts +2 -0
  75. package/output/render/basic/plugins/internal/inject/index.d.ts.map +1 -0
  76. package/output/render/basic/plugins/internal/inject/index.js +2 -0
  77. package/output/render/basic/plugins/internal/inject/index.js.map +1 -0
  78. package/output/{umd/render/common/plugins/internal → render/basic/plugins/internal/inject}/inject.d.ts +3 -2
  79. package/output/render/basic/plugins/internal/inject/inject.d.ts.map +1 -0
  80. package/output/render/basic/plugins/internal/inject/inject.js +25 -0
  81. package/output/render/basic/plugins/internal/inject/inject.js.map +1 -0
  82. package/output/{umd/render/common/plugins/index.d.ts → render/basic/plugins/plugin.d.ts} +3 -3
  83. package/output/render/basic/plugins/plugin.d.ts.map +1 -0
  84. package/output/render/basic/plugins/plugin.js +2 -0
  85. package/output/render/basic/plugins/plugin.js.map +1 -0
  86. package/output/{esm/render → render/browser}/browser.d.ts +4 -3
  87. package/output/render/browser/browser.d.ts.map +1 -0
  88. package/output/render/browser/browser.js +218 -0
  89. package/output/render/browser/browser.js.map +1 -0
  90. package/output/render/browser/index.d.ts +2 -0
  91. package/output/render/browser/index.d.ts.map +1 -0
  92. package/output/render/browser/index.js +2 -0
  93. package/output/render/browser/index.js.map +1 -0
  94. package/output/render/index.d.ts +5 -0
  95. package/output/render/index.d.ts.map +1 -0
  96. package/output/render/index.js +5 -0
  97. package/output/render/index.js.map +1 -0
  98. package/output/render/server/index.d.ts +2 -0
  99. package/output/render/server/index.d.ts.map +1 -0
  100. package/output/render/server/index.js +2 -0
  101. package/output/render/server/index.js.map +1 -0
  102. package/output/{umd/render → render/server}/server.d.ts +3 -2
  103. package/output/render/server/server.d.ts.map +1 -0
  104. package/output/render/server/server.js +314 -0
  105. package/output/render/server/server.js.map +1 -0
  106. package/output/signal/index.d.ts +4 -0
  107. package/output/signal/index.d.ts.map +1 -0
  108. package/output/signal/index.js +2 -0
  109. package/output/signal/index.js.map +1 -0
  110. package/output/{esm/signal/index.d.ts → signal/signal.d.ts} +1 -1
  111. package/output/signal/signal.d.ts.map +1 -0
  112. package/output/signal/signal.js +46 -0
  113. package/output/signal/signal.js.map +1 -0
  114. package/output/symbol/index.d.ts +2 -0
  115. package/output/symbol/index.d.ts.map +1 -0
  116. package/output/symbol/index.js +2 -0
  117. package/output/symbol/index.js.map +1 -0
  118. package/output/types/index.d.ts +2 -0
  119. package/output/types/index.d.ts.map +1 -0
  120. package/output/types/index.js +2 -0
  121. package/output/types/index.js.map +1 -0
  122. package/output/{esm → types}/types.d.ts +3 -1
  123. package/output/types/types.d.ts.map +1 -0
  124. package/output/types/types.js +2 -0
  125. package/output/types/types.js.map +1 -0
  126. package/package.json +42 -15
  127. package/output/esm/element.d.ts +0 -48
  128. package/output/esm/index.d.ts +0 -14
  129. package/output/esm/index.js +0 -1289
  130. package/output/esm/index.js.map +0 -1
  131. package/output/esm/render/common/hooks.d.ts +0 -10
  132. package/output/esm/render/common/plugins/context.d.ts +0 -5
  133. package/output/esm/render/common/plugins/index.d.ts +0 -19
  134. package/output/esm/render/common/plugins/internal/basic.d.ts +0 -10
  135. package/output/esm/render/common/plugins/internal/inject.d.ts +0 -6
  136. package/output/esm/render/index.d.ts +0 -4
  137. package/output/esm/render/server.d.ts +0 -5
  138. package/output/esm/symbol.d.ts +0 -2
  139. package/output/umd/element.d.ts +0 -48
  140. package/output/umd/index.d.ts +0 -14
  141. package/output/umd/index.js +0 -1304
  142. package/output/umd/index.js.map +0 -1
  143. package/output/umd/logger.d.ts +0 -3
  144. package/output/umd/render/browser.d.ts +0 -7
  145. package/output/umd/render/common/hooks.d.ts +0 -10
  146. package/output/umd/render/common/index.d.ts +0 -64
  147. package/output/umd/render/index.d.ts +0 -4
  148. package/output/umd/signal/index.d.ts +0 -6
  149. package/output/umd/symbol.d.ts +0 -2
  150. package/output/umd/types.d.ts +0 -1173
package/README.md CHANGED
@@ -1,118 +1,302 @@
1
- # airx
1
+ # Airx ☁️
2
2
 
3
- [![npm](https://img.shields.io/npm/v/airx.svg)](https://www.npmjs.com/package/airx) [![build status](https://github.com/airxjs/airx/actions/workflows/check.yml/badge.svg?branch=main)](https://github.com/airxjs/airx/actions/workflows/check.yml)
3
+ [![npm](https://img.shields.io/npm/v/airx.svg)](https://www.npmjs.com/package/airx)
4
+ [![build status](https://github.com/airxjs/airx/actions/workflows/check.yml/badge.svg?branch=main)](https://github.com/airxjs/airx/actions/workflows/check.yml)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
6
+ [![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
4
7
 
5
- ☁️ Airx is a lightweight JSX web application framework.
8
+ > A lightweight, Signal-driven JSX web application framework
6
9
 
7
- [中文文档](https://github.com/airxjs/airx/blob/main/README_CN.md)
8
- |
9
- [English Document](https://github.com/airxjs/airx/blob/main/README.md)
10
+ [中文文档](./README_CN.md) • [English Documentation](./README.md)
10
11
 
11
- Airx is a frontend development framework based on `JSX` and `Signal`, aimed at providing a simple and direct solution for building web applications.
12
+ Airx is a modern frontend framework built on **JSX** and **Signal** primitives, designed to provide a simple, performant, and intuitive solution for building reactive web applications.
12
13
 
13
- ## Features
14
+ ## Features
14
15
 
15
- - Seamlessly integrates with [Signal](https://github.com/tc39/proposal-signals) and its ecosystem!
16
- - Developed entirely using TypeScript, TypeScript-friendly
17
- - Defines components using JSX functional syntax
18
- - No hooks like React 😊
19
- - Minimal API for easy learning
16
+ - 🔄 **Signal-driven reactivity**: Seamlessly integrates with [TC39 Signal proposal](https://github.com/tc39/proposal-signals)
17
+ - 📝 **TypeScript-first**: Developed entirely in TypeScript with excellent type safety
18
+ - **Functional components**: Define components using clean JSX functional syntax
19
+ - 🚫 **No hooks complexity**: Simple and straightforward API without React-style hooks
20
+ - 🪶 **Lightweight**: Minimal bundle size with zero dependencies
21
+ - 🔌 **Extensible**: Plugin system for advanced functionality
22
+ - 🌐 **Universal**: Works in both browser and server environments
20
23
 
21
- ## Getting Started
24
+ ## 🚀 Quick Start
22
25
 
23
- To begin using Airx, follow these steps:
26
+ ### Installation
24
27
 
25
- 1. Install Airx using npm or yarn:
26
-
27
- ```shell
28
+ ```bash
28
29
  npm install airx
30
+ # or
31
+ yarn add airx
32
+ # or
33
+ pnpm add airx
29
34
  ```
30
35
 
31
- 2. Import necessary functions and components into your project:
36
+ ### Basic Usage
32
37
 
33
- ```javascript
38
+ ```tsx
34
39
  import * as airx from 'airx'
35
40
 
36
- // All values based on Signal automatically trigger updates
37
- const state = new Signal.State(1)
38
- const computed = new Signal.Computed(() => state.get() + 100)
41
+ // Create reactive state using Signal
42
+ const count = new Signal.State(0)
43
+ const doubleCount = new Signal.Computed(() => count.get() * 2)
39
44
 
40
- function App() {
41
- const innerState = new Signal.State(1)
45
+ function Counter() {
46
+ const localState = new Signal.State(0)
42
47
 
43
- const handleClick = () => {
44
- state.set(state.get() + 1)
45
- innerState.set(innerState.get() + 1)
48
+ const increment = () => {
49
+ count.set(count.get() + 1)
50
+ localState.set(localState.get() + 1)
46
51
  }
47
52
 
48
- // Return a rendering function
53
+ // Return a render function
49
54
  return () => (
50
- <button onClick={handleClick}>
51
- {state.get()}
52
- {computed.get()}
53
- {innerState.get()}
54
- </button>
55
+ <div>
56
+ <h1>Counter App</h1>
57
+ <p>Global count: {count.get()}</p>
58
+ <p>Double count: {doubleCount.get()}</p>
59
+ <p>Local count: {localState.get()}</p>
60
+ <button onClick={increment}>
61
+ Click me!
62
+ </button>
63
+ </div>
55
64
  )
56
65
  }
57
66
 
58
- const app = airx.createApp(<App />);
59
- app.mount(document.getElementById('app'));
67
+ // Create and mount the app
68
+ const app = airx.createApp(<Counter />)
69
+ app.mount(document.getElementById('app'))
70
+ ```
71
+
72
+ ## 📖 Core Concepts
73
+
74
+ ### Components
75
+
76
+ Components in Airx are simple functions that return a render function:
77
+
78
+ ```tsx
79
+ function MyComponent() {
80
+ const state = new Signal.State('Hello')
81
+
82
+ return () => (
83
+ <div>{state.get()} World!</div>
84
+ )
85
+ }
86
+ ```
87
+
88
+ ### State Management
89
+
90
+ Airx leverages the Signal primitive for reactive state management:
91
+
92
+ ```tsx
93
+ // State
94
+ const count = new Signal.State(0)
95
+
96
+ // Computed values
97
+ const isEven = new Signal.Computed(() => count.get() % 2 === 0)
98
+
99
+ // Effects
100
+ const effect = new Signal.Effect(() => {
101
+ console.log('Count changed:', count.get())
102
+ })
103
+ ```
104
+
105
+ ### Context & Dependency Injection
106
+
107
+ ```tsx
108
+ const ThemeContext = Symbol('theme')
109
+
110
+ function App() {
111
+ // Provide values down the component tree
112
+ airx.provide(ThemeContext, 'dark')
113
+
114
+ return () => <Child />
115
+ }
116
+
117
+ function Child() {
118
+ // Inject values from parent components
119
+ const theme = airx.inject(ThemeContext)
120
+
121
+ return () => (
122
+ <div className={`theme-${theme}`}>
123
+ Current theme: {theme}
124
+ </div>
125
+ )
126
+ }
60
127
  ```
61
128
 
62
- ## API
129
+ ### Lifecycle Hooks
130
+
131
+ ```tsx
132
+ function Component() {
133
+ airx.onMounted(() => {
134
+ console.log('Component mounted')
135
+
136
+ // Return cleanup function
137
+ return () => {
138
+ console.log('Component unmounted')
139
+ }
140
+ })
141
+
142
+ airx.onUnmounted(() => {
143
+ console.log('Component will unmount')
144
+ })
145
+
146
+ return () => <div>My Component</div>
147
+ }
63
148
 
64
- We have only a few APIs because we pursue a minimal core design. In the future, we will also open up a plugin system.
149
+ ## 📚 API Reference
65
150
 
66
- ### createApp
151
+ Airx follows a minimal API design philosophy. Here are the core APIs:
67
152
 
68
- Create an application instance.
153
+ ### `createApp(element)`
69
154
 
70
- ### provide
155
+ Creates an application instance.
71
156
 
72
- ```ts
73
- function provide: <T = unknown>(key: unknown, value: T): ProvideUpdater<T>
157
+ ```tsx
158
+ const app = airx.createApp(<App />)
159
+ app.mount(document.getElementById('root'))
74
160
  ```
75
161
 
76
- Inject a value downwards through the `context`, must be called synchronously directly or indirectly within a component.
162
+ ### `provide<T>(key, value): ProvideUpdater<T>`
77
163
 
78
- ### inject
164
+ Provides a value down the component tree through context. Must be called synchronously within a component.
79
165
 
80
- ```ts
81
- function inject<T = unknown>(key: unknown): T | undefined
166
+ ```tsx
167
+ function Parent() {
168
+ airx.provide('theme', 'dark')
169
+ return () => <Child />
170
+ }
82
171
  ```
83
172
 
84
- Look up a specified value upwards through the `context`, must be called synchronously directly or indirectly within a component.
173
+ ### `inject<T>(key): T | undefined`
85
174
 
86
- ### onMounted
175
+ Retrieves a provided value from the component tree. Must be called synchronously within a component.
87
176
 
88
- ```ts
177
+ ```tsx
178
+ function Child() {
179
+ const theme = airx.inject('theme')
180
+ return () => <div>Theme: {theme}</div>
181
+ }
182
+ ```
183
+
184
+ ### `onMounted(listener): void`
185
+
186
+ Registers a callback for when the component is mounted to the DOM.
187
+
188
+ ```tsx
89
189
  type MountedListener = () => (() => void) | void
90
- function onMounted(listener: MountedListener): void
190
+
191
+ airx.onMounted(() => {
192
+ console.log('Mounted!')
193
+ return () => console.log('Cleanup')
194
+ })
91
195
  ```
92
196
 
93
- Register a callback for when the DOM is mounted, must be called synchronously directly or indirectly within a component.
197
+ ### `onUnmounted(listener): void`
94
198
 
95
- ### onUnmounted
199
+ Registers a callback for when the component is unmounted from the DOM.
96
200
 
97
- ```ts
201
+ ```tsx
98
202
  type UnmountedListener = () => void
99
- function onUnmounted(listener: UnmountedListener): void
203
+
204
+ airx.onUnmounted(() => {
205
+ console.log('Unmounted!')
206
+ })
207
+ ```
208
+
209
+ ### `createElement(type, props, ...children)`
210
+
211
+ Creates virtual DOM elements (usually handled by JSX transpiler).
212
+
213
+ ### `Fragment`
214
+
215
+ A component for grouping multiple elements without adding extra DOM nodes.
216
+
217
+ ```tsx
218
+ function App() {
219
+ return () => (
220
+ <airx.Fragment>
221
+ <div>First</div>
222
+ <div>Second</div>
223
+ </airx.Fragment>
224
+ )
225
+ }
100
226
  ```
101
227
 
102
- Register a callback for when the DOM is unmounted, must be called synchronously directly or indirectly within a component.
228
+ ## 🔧 Development
229
+
230
+ ### Building from Source
231
+
232
+ ```bash
233
+ # Clone the repository
234
+ git clone https://github.com/airxjs/airx.git
235
+ cd airx
236
+
237
+ # Install dependencies
238
+ npm install
239
+
240
+ # Build the project
241
+ npm run build
242
+
243
+ # Run tests
244
+ npm test
245
+
246
+ # Run tests with UI
247
+ npm run test:ui
248
+
249
+ # Run tests with coverage
250
+ npm run test:coverage
251
+ ```
252
+
253
+ ### Project Structure
254
+
255
+ ```text
256
+ source/
257
+ ├── app/ # Application creation and management
258
+ ├── element/ # Virtual DOM and JSX handling
259
+ ├── logger/ # Internal logging utilities
260
+ ├── render/ # Rendering engine
261
+ │ ├── basic/ # Core rendering logic
262
+ │ ├── browser/ # Browser-specific rendering
263
+ │ └── server/ # Server-side rendering
264
+ ├── signal/ # Signal integration
265
+ ├── symbol/ # Internal symbols
266
+ └── types/ # TypeScript type definitions
267
+ ```
268
+
269
+ ## 🤝 Contributing
270
+
271
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
272
+
273
+ ### Development Workflow
274
+
275
+ 1. Fork the repository
276
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
277
+ 3. Make your changes
278
+ 4. Add tests for your changes
279
+ 5. Ensure all tests pass (`npm test`)
280
+ 6. Commit your changes (`git commit -m 'Add amazing feature'`)
281
+ 7. Push to the branch (`git push origin feature/amazing-feature`)
282
+ 8. Open a Pull Request
103
283
 
104
- ## License
284
+ ## 📄 License
105
285
 
106
- This project uses the MIT License. For detailed information, please refer to the [LICENSE](LICENSE) file.
286
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
107
287
 
108
- ## Contribution
288
+ ## 🙏 Acknowledgments
109
289
 
110
- Contributions are welcome! If you have any ideas, suggestions, or bug reports, please open an issue or submit a pull request.
290
+ - Thanks to all contributors and supporters of the Airx project
291
+ - Inspired by the [TC39 Signal proposal](https://github.com/tc39/proposal-signals)
292
+ - Built with ❤️ by the Airx community
111
293
 
112
- ## Acknowledgements
294
+ ## 📞 Support
113
295
 
114
- We want to thank all contributors and supporters of the Airx project.
296
+ - 📖 [Documentation](https://github.com/airxjs/airx)
297
+ - 🐛 [Issue Tracker](https://github.com/airxjs/airx/issues)
298
+ - 💬 [Discussions](https://github.com/airxjs/airx/discussions)
115
299
 
116
300
  ---
117
301
 
118
- For more information, please refer to the [official documentation](https://github.com/airxjs/airx)
302
+ Made with ☁️ by the Airx team
@@ -0,0 +1,41 @@
1
+ import { Plugin } from '../render/index.js';
2
+ import { AirxComponent, AirxElement } from '../element/index.js';
3
+ /**
4
+ * Airx 应用实例。
5
+ *
6
+ * @example
7
+ * import { createApp } from 'airx'
8
+ * import { App } from './App.js'
9
+ *
10
+ * createApp(App).mount(document.getElementById('root')!)
11
+ */
12
+ export interface AirxApp {
13
+ mount: (container: HTMLElement) => AirxApp;
14
+ /** @deprecated WIP */
15
+ plugin: (...plugins: Plugin[]) => AirxApp;
16
+ /** @deprecated WIP */
17
+ renderToHTML: () => Promise<string>;
18
+ }
19
+ /**
20
+ * 创建一个 Airx 应用。
21
+ *
22
+ * 支持直接传入组件函数,也支持传入已经创建好的元素。
23
+ *
24
+ * @param element 根组件或根元素。
25
+ * @returns 可继续链式调用的应用实例。
26
+ *
27
+ * @example
28
+ * import { createApp } from 'airx'
29
+ * import { App } from './App.js'
30
+ *
31
+ * createApp(App).mount(document.getElementById('root')!)
32
+ *
33
+ * @example
34
+ * import { createApp, createElement } from 'airx'
35
+ * import { App } from './App.js'
36
+ *
37
+ * const appElement = createElement(App, { title: 'Airx' })
38
+ * createApp(appElement).mount(document.getElementById('root')!)
39
+ */
40
+ export declare function createApp(element: AirxElement<any> | AirxComponent): AirxApp;
41
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../source/app/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,MAAM,EAAiB,MAAM,oBAAoB,CAAA;AACvF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAiB,MAAM,qBAAqB,CAAA;AAE/E;;;;;;;;GAQG;AACH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,CAAC,SAAS,EAAE,WAAW,KAAK,OAAO,CAAA;IAE1C,sBAAsB;IACtB,MAAM,EAAE,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,CAAA;IACzC,sBAAsB;IACtB,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACpC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,aAAa,GAAG,OAAO,CA+B5E"}
@@ -0,0 +1,51 @@
1
+ import { browserRender, serverRender, PluginContext } from '../render/index.js';
2
+ import { createElement } from '../element/index.js';
3
+ /**
4
+ * 创建一个 Airx 应用。
5
+ *
6
+ * 支持直接传入组件函数,也支持传入已经创建好的元素。
7
+ *
8
+ * @param element 根组件或根元素。
9
+ * @returns 可继续链式调用的应用实例。
10
+ *
11
+ * @example
12
+ * import { createApp } from 'airx'
13
+ * import { App } from './App.js'
14
+ *
15
+ * createApp(App).mount(document.getElementById('root')!)
16
+ *
17
+ * @example
18
+ * import { createApp, createElement } from 'airx'
19
+ * import { App } from './App.js'
20
+ *
21
+ * const appElement = createElement(App, { title: 'Airx' })
22
+ * createApp(appElement).mount(document.getElementById('root')!)
23
+ */
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ export function createApp(element) {
26
+ const appContext = new PluginContext();
27
+ const ensureAsElement = (element) => {
28
+ if (typeof element === 'function') {
29
+ return createElement(element, {});
30
+ }
31
+ return element;
32
+ };
33
+ const app = {
34
+ plugin: (...plugins) => {
35
+ appContext.registerPlugin(...plugins);
36
+ return app;
37
+ },
38
+ mount: (container) => {
39
+ container.innerHTML = ''; // 先清空再说
40
+ browserRender(appContext, ensureAsElement(element), container);
41
+ return app;
42
+ },
43
+ renderToHTML: () => {
44
+ return new Promise(resolve => {
45
+ serverRender(appContext, ensureAsElement(element), resolve);
46
+ });
47
+ }
48
+ };
49
+ return app;
50
+ }
51
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../source/app/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAU,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvF,OAAO,EAA8B,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAoB/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,8DAA8D;AAC9D,MAAM,UAAU,SAAS,CAAC,OAAyC;IACjE,MAAM,UAAU,GAAG,IAAI,aAAa,EAAE,CAAA;IAEtC,MAAM,eAAe,GAAG,CAAC,OAAoC,EAAe,EAAE;QAC5E,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAClC,OAAO,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;QACnC,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC,CAAA;IAED,MAAM,GAAG,GAAY;QACnB,MAAM,EAAE,CAAC,GAAG,OAAiB,EAAE,EAAE;YAC/B,UAAU,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,CAAA;YACrC,OAAO,GAAG,CAAA;QACZ,CAAC;QAED,KAAK,EAAE,CAAC,SAAsB,EAAE,EAAE;YAChC,SAAS,CAAC,SAAS,GAAG,EAAE,CAAA,CAAC,QAAQ;YACjC,aAAa,CAAC,UAAU,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,CAAA;YAC9D,OAAO,GAAG,CAAA;QACZ,CAAC;QAED,YAAY,EAAE,GAAoB,EAAE;YAClC,OAAO,IAAI,OAAO,CAAS,OAAO,CAAC,EAAE;gBACnC,YAAY,CAAC,UAAU,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAA;YAC7D,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;IAED,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './app.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/app/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './app.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/app/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
@@ -0,0 +1,108 @@
1
+ import * as symbol from '../symbol/index.js';
2
+ type AirxElementType<P> = string | AirxComponent<P>;
3
+ export type Props = {
4
+ [propKey: string]: unknown;
5
+ };
6
+ /**
7
+ * Airx 虚拟节点结构。
8
+ *
9
+ * - type: 标签名或组件函数
10
+ * - props: 组件参数或标签属性
11
+ * - props.children: 子节点列表
12
+ *
13
+ * @example
14
+ * import { createElement, type AirxElement } from 'airx'
15
+ *
16
+ * const node: AirxElement = createElement('div', { id: 'app' }, 'hello')
17
+ */
18
+ export interface AirxElement<P = any> {
19
+ type: AirxElementType<P>;
20
+ props: Props & P;
21
+ [symbol.airxElementSymbol]: true;
22
+ }
23
+ /**
24
+ * 组件可返回的子节点类型。
25
+ */
26
+ export type AirxChildren = null | string | number | boolean | undefined | AirxElement | Array<AirxChildren> | AirxComponentRender;
27
+ /**
28
+ * 组件渲染函数类型。
29
+ *
30
+ * 组件函数返回值本身是一个 "render 函数",该函数最终返回子节点。
31
+ */
32
+ export type AirxComponentRender = () => AirxChildren;
33
+ export type AirxComponent<P = unknown> = ReactiveComponent<P>;
34
+ export type ReactiveComponent<P = unknown> = (props: P) => AirxComponentRender;
35
+ /**
36
+ * 创建 Airx 虚拟节点。
37
+ *
38
+ * 可用于手写节点,也会被 JSX 转换后调用。
39
+ *
40
+ * @param type 标签名或组件函数。
41
+ * @param props 属性对象。
42
+ * @param children 可变子节点参数。
43
+ * @returns 标准化后的 AirxElement。
44
+ *
45
+ * @example
46
+ * import { createElement } from 'airx'
47
+ *
48
+ * const view = createElement('div', { class: 'box' }, 'hello')
49
+ *
50
+ * @example
51
+ * import { createElement } from 'airx'
52
+ *
53
+ * function Title(props: { text: string }) {
54
+ * return () => createElement('h1', null as never, props.text)
55
+ * }
56
+ *
57
+ * const node = createElement(Title, { text: 'Airx' })
58
+ */
59
+ export declare function createElement<P = any>(type: AirxElementType<P>, props: {
60
+ [key: string]: unknown;
61
+ } & P, ...children: AirxChildren[]): AirxElement<P>;
62
+ /**
63
+ * 判断一个值是否是合法的 AirxElement。
64
+ */
65
+ export declare function isValidElement(element: unknown): element is AirxElement;
66
+ /**
67
+ * JSX Fragment 对应的运行时实现。
68
+ *
69
+ * @example
70
+ * function Card() {
71
+ * return () => (
72
+ * <>
73
+ * <h3>Title</h3>
74
+ * <p>Content</p>
75
+ * </>
76
+ * )
77
+ * }
78
+ */
79
+ export declare function Fragment(props: {
80
+ children: AirxElement;
81
+ }): () => AirxElement<any>;
82
+ export type AirxComponentUnmountedListener = () => void;
83
+ export type AirxComponentMountedListener = () => (() => void) | void;
84
+ export interface AirxComponentLifecycle {
85
+ onMounted: (listener: AirxComponentMountedListener) => void;
86
+ onUnmounted: (listener: AirxComponentUnmountedListener) => void;
87
+ }
88
+ type ProvideUpdater<T = unknown> = (newValue: T | ((old: T) => T)) => void;
89
+ export type AirxComponentContext = AirxComponentLifecycle & {
90
+ provide: <T = unknown>(key: unknown, value: T) => ProvideUpdater<T>;
91
+ inject: <T = unknown>(key: unknown) => T | undefined;
92
+ };
93
+ /**
94
+ * 为组件提供类型友好的包装。
95
+ *
96
+ * 主要用于在不使用 JSX 的场景下显式声明组件签名。
97
+ *
98
+ * @example
99
+ * import { component, createElement } from 'airx'
100
+ *
101
+ * const Hello = component<{ name: string }>((props) => {
102
+ * return () => createElement('h1', null as never, `Hello ${props.name}`)
103
+ * })
104
+ */
105
+ export declare function component<P = unknown>(comp: AirxComponent<P>): AirxComponent<P>;
106
+ export declare function createErrorRender(error: unknown): AirxComponentRender;
107
+ export {};
108
+ //# sourceMappingURL=element.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../../source/element/element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAG5C,KAAK,eAAe,CAAC,CAAC,IAAI,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;AAEnD,MAAM,MAAM,KAAK,GAAG;IAAE,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAA;AAElD;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG;IAClC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAA;IACxB,KAAK,EAAE,KAAK,GAAG,CAAC,CAAA;IAChB,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAA;CACjC;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB,IAAI,GACJ,MAAM,GACN,MAAM,GACN,OAAO,GACP,SAAS,GACT,WAAW,GACX,KAAK,CAAC,YAAY,CAAC,GACnB,mBAAmB,CAAA;AAEvB;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,YAAY,CAAA;AACpD,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAA;AAC7D,MAAM,MAAM,iBAAiB,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,mBAAmB,CAAA;AAE9E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EACnC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,EACxB,KAAK,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAAG,CAAC,EACrC,GAAG,QAAQ,EAAE,YAAY,EAAE,GAC1B,WAAW,CAAC,CAAC,CAAC,CAiBhB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,WAAW,CAIvE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,0BAExD;AAED,MAAM,MAAM,8BAA8B,GAAG,MAAM,IAAI,CAAA;AACvD,MAAM,MAAM,4BAA4B,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;AAEpE,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,CAAC,QAAQ,EAAE,4BAA4B,KAAK,IAAI,CAAA;IAC3D,WAAW,EAAE,CAAC,QAAQ,EAAE,8BAA8B,KAAK,IAAI,CAAA;CAChE;AAED,KAAK,cAAc,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAA;AAE1E,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,GAAG;IAC1D,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,CAAA;IACnE,MAAM,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,CAAC,GAAG,SAAS,CAAA;CACrD,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAE/E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAwBrE"}