x4js 2.2.74 → 2.3.2
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.
- package/bin/x4js.mjs +3 -0
- package/cli/build-options.mjs +68 -0
- package/cli/build.mjs +33 -0
- package/cli/config.mjs +165 -0
- package/cli/copy-plugin.mjs +115 -0
- package/cli/create.mjs +159 -0
- package/cli/dev-client.js +41 -0
- package/cli/dev.mjs +190 -0
- package/cli/less-plugin.mjs +47 -0
- package/cli/log.mjs +41 -0
- package/cli/main.mjs +74 -0
- package/cli/templates-source.mjs +61 -0
- package/cli/templates.mjs +13 -0
- package/package.json +10 -1
- package/readme.npm.md +248 -0
- package/src/components/themes.scss +44 -44
- package/src/x4.scss +4 -4
package/readme.npm.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# x4js
|
|
2
|
+
|
|
3
|
+
**A TypeScript framework for building applications, not markup.**
|
|
4
|
+
|
|
5
|
+
x4js is designed for rich web and desktop applications: business software, industrial interfaces, dashboards, data-heavy tools and desktop-like applications.
|
|
6
|
+
|
|
7
|
+
It uses persistent TypeScript objects associated with the real DOM. No virtual DOM, no reconciliation layer, and no application architecture imposed by JSX.
|
|
8
|
+
|
|
9
|
+
**TypeScript objects. JSX when it helps. Real DOM.**
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install x4js
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
Create a project:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx x4build create demo --type=html
|
|
23
|
+
cd demo
|
|
24
|
+
npm install
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Run it in development mode with HMR:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx x4build --watch --hmr --serve
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## More than 50 UI components
|
|
34
|
+
|
|
35
|
+
x4 includes a complete UI toolkit for building real applications.
|
|
36
|
+
|
|
37
|
+
Among the available components:
|
|
38
|
+
|
|
39
|
+
`Button`, `Input`, `TextEdit`, `TextArea`, `Checkbox`, `Radio`, `Switch`, `Select`, `Combobox`, `Slider`, `ColorPicker`, `Form`, `Dialog`, `Popup`, `Menu`, `Tabs`, `Gridview`, `Treeview`, `PropertyGrid`, `Spreadsheet`, `Calendar`, `Gauge`, `Progress`, `FileDrop`, `MonacoEditor`, layouts and more.
|
|
40
|
+
|
|
41
|
+
The framework also provides:
|
|
42
|
+
|
|
43
|
+
* drag & drop
|
|
44
|
+
* SVG primitives and builder
|
|
45
|
+
* routing
|
|
46
|
+
* PDF generation
|
|
47
|
+
* internationalization
|
|
48
|
+
* data stores and views
|
|
49
|
+
* application-wide events
|
|
50
|
+
* persistence helpers
|
|
51
|
+
* CSS infrastructure and theming
|
|
52
|
+
|
|
53
|
+
## Easy to extend
|
|
54
|
+
|
|
55
|
+
x4 components are ordinary TypeScript classes.
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { Component, ComponentProps } from 'x4js'
|
|
59
|
+
|
|
60
|
+
interface StatusBadgeProps extends ComponentProps {
|
|
61
|
+
text: string
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class StatusBadge extends Component<StatusBadgeProps> {
|
|
65
|
+
constructor(props: StatusBadgeProps) {
|
|
66
|
+
super(props)
|
|
67
|
+
|
|
68
|
+
this.setContent(props.text)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Your own components use the same DOM, lifecycle and event model as the components provided by x4.
|
|
74
|
+
|
|
75
|
+
Because x4 works with the real browser DOM, third-party UI libraries can also be integrated where they make sense. There is no separate plugin architecture to satisfy.
|
|
76
|
+
|
|
77
|
+
## Real DOM
|
|
78
|
+
|
|
79
|
+
A `Component` is a persistent TypeScript object associated with an actual DOM element.
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const button = new Button({
|
|
83
|
+
label: 'Restart'
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
button.on('click', () => restartMachine())
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The object remains alive for the lifetime of the component. You can keep references, call methods and listen to events directly.
|
|
90
|
+
|
|
91
|
+
There is no virtual tree to rebuild or reconcile.
|
|
92
|
+
|
|
93
|
+
## JSX is optional
|
|
94
|
+
|
|
95
|
+
x4 supports JSX, but JSX is syntax — not the application architecture.
|
|
96
|
+
|
|
97
|
+
Object API:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
this.setContent([
|
|
101
|
+
new Label({
|
|
102
|
+
text: 'Temperature'
|
|
103
|
+
}),
|
|
104
|
+
|
|
105
|
+
new Gauge({
|
|
106
|
+
min: 0,
|
|
107
|
+
max: 100
|
|
108
|
+
})
|
|
109
|
+
])
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
JSX:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
this.setContent(
|
|
116
|
+
<VBox>
|
|
117
|
+
<Label text="Temperature" />
|
|
118
|
+
<Gauge min={0} max={100} />
|
|
119
|
+
</VBox>
|
|
120
|
+
)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Both create the same x4 Components and the same real DOM.
|
|
124
|
+
|
|
125
|
+
Use whichever makes the code clearer.
|
|
126
|
+
|
|
127
|
+
## Data-heavy applications
|
|
128
|
+
|
|
129
|
+
x4 treats grids, trees, forms and structured data as first-class application concerns.
|
|
130
|
+
|
|
131
|
+
`DataStore`, `DataView` and `Gridview` are designed to work together for tabular data:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
const store = new DataStore({
|
|
135
|
+
model,
|
|
136
|
+
data
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const grid = new Gridview({
|
|
140
|
+
store,
|
|
141
|
+
columns: [
|
|
142
|
+
{ id: 'name', title: 'Name', width: 200 },
|
|
143
|
+
{ id: 'age', title: 'Age', width: 80 }
|
|
144
|
+
]
|
|
145
|
+
})
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Changes to the data are reflected by the components using it.
|
|
149
|
+
|
|
150
|
+
## Routing
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
const router = new Router(true)
|
|
154
|
+
|
|
155
|
+
router.get('/home', () => showHome())
|
|
156
|
+
router.get('/device/:id', p => showDevice(p.id))
|
|
157
|
+
|
|
158
|
+
router.init()
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Internationalization
|
|
162
|
+
|
|
163
|
+
Internationalization support is built in.
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
createLanguage('de', 'en')
|
|
167
|
+
addTranslation('de', translations)
|
|
168
|
+
|
|
169
|
+
selectLanguage('de')
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
x4 includes French and English translations by default and allows applications to add their own languages.
|
|
173
|
+
|
|
174
|
+
## SVG and PDF
|
|
175
|
+
|
|
176
|
+
SVG is part of the framework surface through `SvgComponent` and `SvgBuilder`.
|
|
177
|
+
|
|
178
|
+
PDF documents can be generated programmatically with `X4PDFBuilder`:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
const pdf = new X4PDFBuilder()
|
|
182
|
+
|
|
183
|
+
pdf.page(595, 842, page => {
|
|
184
|
+
// draw page
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
const data = pdf.build()
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## CSS and themes
|
|
191
|
+
|
|
192
|
+
x4 includes the CSS foundation used by its components.
|
|
193
|
+
|
|
194
|
+
Applications can use the default styling, adapt it to their product, or provide their own CSS. Components expose their real DOM and CSS classes, so standard browser styling techniques remain available.
|
|
195
|
+
|
|
196
|
+
No CSS-in-JS runtime is required.
|
|
197
|
+
|
|
198
|
+
## HMR and development workflow
|
|
199
|
+
|
|
200
|
+
The standard x4 build workflow supports watch mode, development serving and HMR:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
x4build --watch --hmr --serve
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Edit the application, save, see the result.
|
|
207
|
+
|
|
208
|
+
## Ship only what you use
|
|
209
|
+
|
|
210
|
+
The `x4js` npm package ships its TypeScript sources directly.
|
|
211
|
+
|
|
212
|
+
Your application and x4 therefore participate in the same module graph, allowing the bundler to tree-shake unused code.
|
|
213
|
+
|
|
214
|
+
Import a small part of x4 and the rest of the component library does not need to become part of your application bundle.
|
|
215
|
+
|
|
216
|
+
## Web and desktop
|
|
217
|
+
|
|
218
|
+
x4 targets both browser and desktop applications.
|
|
219
|
+
|
|
220
|
+
The same component model can be used in the browser or inside a desktop wrapper such as Electron, Tauri or NW.js.
|
|
221
|
+
|
|
222
|
+
## AI-friendly documentation
|
|
223
|
+
|
|
224
|
+
x4 provides a generated `aicontext.md` containing the actual TypeScript API signatures.
|
|
225
|
+
|
|
226
|
+
AI coding agents can also inspect the framework sources directly because they are distributed with the npm package:
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
node_modules/x4js/src/
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The goal is not to make x4 an “AI framework”.
|
|
233
|
+
|
|
234
|
+
The goal is simpler: an explicit architecture and an API that are readable by humans and predictable for machines.
|
|
235
|
+
|
|
236
|
+
## Philosophy
|
|
237
|
+
|
|
238
|
+
x4 deliberately keeps its conceptual model small.
|
|
239
|
+
|
|
240
|
+
Use TypeScript when TypeScript is enough.
|
|
241
|
+
Use the browser when the browser is enough.
|
|
242
|
+
Add an abstraction only when it solves a real problem.
|
|
243
|
+
|
|
244
|
+
**Use the simplest tool that fits.**
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
MIT License
|
|
@@ -14,77 +14,77 @@
|
|
|
14
14
|
* that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
|
15
15
|
**/
|
|
16
16
|
|
|
17
|
+
@use "sass:color";
|
|
17
18
|
|
|
18
19
|
$color--base: #569cd6;
|
|
19
20
|
$color--interval: 8.4%;
|
|
20
21
|
|
|
21
22
|
:root {
|
|
22
23
|
--color-primary-a0: #ffffff;
|
|
23
|
-
--color-primary-a5:
|
|
24
|
-
--color-primary-a10:
|
|
25
|
-
--color-primary-a20: #{
|
|
26
|
-
--color-primary-a30: #{
|
|
27
|
-
--color-primary-a40: #{
|
|
24
|
+
--color-primary-a5: #{color.adjust($color--base, $lightness: 35%)};
|
|
25
|
+
--color-primary-a10: #{color.adjust($color--base, $lightness: $color--interval * 4)};
|
|
26
|
+
--color-primary-a20: #{color.adjust($color--base, $lightness: $color--interval * 3)};
|
|
27
|
+
--color-primary-a30: #{color.adjust($color--base, $lightness: $color--interval * 2)};
|
|
28
|
+
--color-primary-a40: #{color.adjust($color--base, $lightness: $color--interval)};
|
|
28
29
|
--color-primary-a50: #{$color--base};
|
|
29
|
-
--color-primary-a55: #{
|
|
30
|
-
--color-primary-a60: #{
|
|
31
|
-
--color-primary-a70: #{
|
|
32
|
-
--color-primary-a80: #{
|
|
33
|
-
--color-primary-a90: #{
|
|
30
|
+
--color-primary-a55: #{color.adjust($color--base, $lightness: -5%)};
|
|
31
|
+
--color-primary-a60: #{color.adjust($color--base, $lightness: -$color--interval)};
|
|
32
|
+
--color-primary-a70: #{color.adjust($color--base, $lightness: -$color--interval * 2)};
|
|
33
|
+
--color-primary-a80: #{color.adjust($color--base, $lightness: -$color--interval * 3)};
|
|
34
|
+
--color-primary-a90: #{color.adjust($color--base, $lightness: -$color--interval * 4)};
|
|
34
35
|
--color-primary-a100: #000000;
|
|
35
36
|
|
|
36
|
-
--color-danger-a30: #{
|
|
37
|
+
--color-danger-a30: #{color.adjust(#c01010, $lightness: 30%)};
|
|
37
38
|
--color-danger-a50: #c01010;
|
|
38
|
-
--color-danger-a60: #{
|
|
39
|
+
--color-danger-a60: #{color.adjust(#c01010, $lightness: -10%)};
|
|
39
40
|
|
|
40
41
|
--color-warning-a50: #b67b0d;
|
|
41
42
|
|
|
42
43
|
--color-success-a50: #10c01f;
|
|
43
|
-
--color-success-a60: #{
|
|
44
|
+
--color-success-a60: #{color.adjust(#10c01f, $lightness: -10%)};
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
:root {
|
|
47
48
|
// Backgrounds
|
|
48
|
-
--background-primary: var(--color-primary-a0);
|
|
49
|
-
--background-secondary: var(--color-primary-a10);
|
|
50
|
-
--background-ternary: #f4f4f4;
|
|
49
|
+
--background-primary: var(--color-primary-a0);
|
|
50
|
+
--background-secondary: var(--color-primary-a10);
|
|
51
|
+
--background-ternary: #f4f4f4;
|
|
51
52
|
|
|
52
53
|
// Texts
|
|
53
|
-
--text-primary: var(--color-primary-a100);
|
|
54
|
-
--text-secondary: #999;
|
|
55
|
-
--text-ternary: #666;
|
|
54
|
+
--text-primary: var(--color-primary-a100);
|
|
55
|
+
--text-secondary: #999;
|
|
56
|
+
--text-ternary: #666;
|
|
56
57
|
|
|
57
|
-
//
|
|
58
|
+
// Disabled
|
|
58
59
|
--disabled-background: #ccc;
|
|
59
60
|
--disabled-color: white;
|
|
60
61
|
--disabled-color-dark: #aaa;
|
|
61
62
|
|
|
62
|
-
//
|
|
63
|
-
--accent-background: var(--color-primary-a60);
|
|
64
|
-
--accent-background-hover: var(--color-primary-a55);
|
|
63
|
+
// Accents
|
|
64
|
+
--accent-background: var(--color-primary-a60);
|
|
65
|
+
--accent-background-hover: var(--color-primary-a55);
|
|
65
66
|
--accent-background-focus: var(--color-primary-a70);
|
|
66
|
-
--accent-background-active: var(--color-primary-a80);
|
|
67
|
+
--accent-background-active: var(--color-primary-a80);
|
|
67
68
|
|
|
68
|
-
--accent-color: var(--color-primary-a0);
|
|
69
|
-
--accent-color-hover: var(--color-primary-a0);
|
|
69
|
+
--accent-color: var(--color-primary-a0);
|
|
70
|
+
--accent-color-hover: var(--color-primary-a0);
|
|
70
71
|
--accent-color-focus: var(--color-primary-a0);
|
|
71
|
-
--accent-color-active: var(--color-primary-a0);
|
|
72
|
+
--accent-color-active: var(--color-primary-a0);
|
|
72
73
|
|
|
73
74
|
// Borders
|
|
74
|
-
--border: #e1e1e1;
|
|
75
|
-
--border-light: #eaeaea;
|
|
76
|
-
--border-hover: #c2c2c2;
|
|
77
|
-
--border-focus: var(
|
|
78
|
-
|
|
79
|
-
--alert-background: var(
|
|
80
|
-
--alert-background-active: var(
|
|
81
|
-
--alert-color: var(
|
|
82
|
-
|
|
83
|
-
--warning-background: var(
|
|
84
|
-
--warning-color: var(
|
|
85
|
-
|
|
86
|
-
--success-background: var(
|
|
87
|
-
--success-background-active: var(
|
|
88
|
-
--success-color: var(
|
|
89
|
-
}
|
|
90
|
-
|
|
75
|
+
--border: #e1e1e1;
|
|
76
|
+
--border-light: #eaeaea;
|
|
77
|
+
--border-hover: #c2c2c2;
|
|
78
|
+
--border-focus: var(--accent-background);
|
|
79
|
+
|
|
80
|
+
--alert-background: var(--color-danger-a50);
|
|
81
|
+
--alert-background-active: var(--color-danger-a60);
|
|
82
|
+
--alert-color: var(--color-primary-a0);
|
|
83
|
+
|
|
84
|
+
--warning-background: var(--color-warning-a50);
|
|
85
|
+
--warning-color: var(--color-primary-a0);
|
|
86
|
+
|
|
87
|
+
--success-background: var(--color-success-a50);
|
|
88
|
+
--success-background-active: var(--color-success-a60);
|
|
89
|
+
--success-color: var(--color-primary-a0);
|
|
90
|
+
}
|
package/src/x4.scss
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
|
15
15
|
**/
|
|
16
16
|
|
|
17
|
-
@
|
|
18
|
-
@
|
|
19
|
-
@
|
|
20
|
-
@
|
|
17
|
+
@use "./components/normalize";
|
|
18
|
+
@use "./components/colors";
|
|
19
|
+
@use "./components/themes";
|
|
20
|
+
@use "./components/base";
|