@amazon/vinyl-tsx 1.0.0
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/dist/index.cjs +354 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.js +340 -0
- package/dist/index.js.map +7 -0
- package/dist/types/current/ActiveText.d.ts +8 -0
- package/dist/types/current/ActiveText.d.ts.map +1 -0
- package/dist/types/current/ActiveText.js +19 -0
- package/dist/types/current/domUtil.d.ts +33 -0
- package/dist/types/current/domUtil.d.ts.map +1 -0
- package/dist/types/current/domUtil.js +73 -0
- package/dist/types/current/extensions/HookExtension.d.ts +2 -0
- package/dist/types/current/extensions/HookExtension.d.ts.map +1 -0
- package/dist/types/current/extensions/HookExtension.js +5 -0
- package/dist/types/current/extensions/applyClassList.d.ts +4 -0
- package/dist/types/current/extensions/applyClassList.d.ts.map +1 -0
- package/dist/types/current/extensions/applyClassList.js +40 -0
- package/dist/types/current/extensions/applyPassiveHandler.d.ts +7 -0
- package/dist/types/current/extensions/applyPassiveHandler.d.ts.map +1 -0
- package/dist/types/current/extensions/applyPassiveHandler.js +15 -0
- package/dist/types/current/extensions/applyStyles.d.ts +12 -0
- package/dist/types/current/extensions/applyStyles.d.ts.map +1 -0
- package/dist/types/current/extensions/applyStyles.js +31 -0
- package/dist/types/current/extensions/applyVisibility.d.ts +3 -0
- package/dist/types/current/extensions/applyVisibility.d.ts.map +1 -0
- package/dist/types/current/extensions/applyVisibility.js +21 -0
- package/dist/types/current/extensions/connectedObserver.d.ts +15 -0
- package/dist/types/current/extensions/connectedObserver.d.ts.map +1 -0
- package/dist/types/current/extensions/connectedObserver.js +72 -0
- package/dist/types/current/index.d.ts +12 -0
- package/dist/types/current/index.d.ts.map +1 -0
- package/dist/types/current/index.js +11 -0
- package/dist/types/current/jsx.d.ts +55 -0
- package/dist/types/current/jsx.d.ts.map +1 -0
- package/dist/types/current/jsx.js +106 -0
- package/dist/types/current/tsconfig.tsbuildinfo +1 -0
- package/dist/types/current/type.d.ts +10 -0
- package/dist/types/current/type.d.ts.map +1 -0
- package/dist/types/current/type.js +5 -0
- package/dist/types/ts3.7/ActiveText.d.ts +8 -0
- package/dist/types/ts3.7/domUtil.d.ts +33 -0
- package/dist/types/ts3.7/extensions/HookExtension.d.ts +2 -0
- package/dist/types/ts3.7/extensions/applyClassList.d.ts +4 -0
- package/dist/types/ts3.7/extensions/applyPassiveHandler.d.ts +7 -0
- package/dist/types/ts3.7/extensions/applyStyles.d.ts +12 -0
- package/dist/types/ts3.7/extensions/applyVisibility.d.ts +3 -0
- package/dist/types/ts3.7/extensions/connectedObserver.d.ts +15 -0
- package/dist/types/ts3.7/index.d.ts +12 -0
- package/dist/types/ts3.7/jsx.d.ts +55 -0
- package/dist/types/ts3.7/type.d.ts +10 -0
- package/dist/types/ts4.1/ActiveText.d.ts +8 -0
- package/dist/types/ts4.1/domUtil.d.ts +33 -0
- package/dist/types/ts4.1/extensions/HookExtension.d.ts +2 -0
- package/dist/types/ts4.1/extensions/applyClassList.d.ts +4 -0
- package/dist/types/ts4.1/extensions/applyPassiveHandler.d.ts +7 -0
- package/dist/types/ts4.1/extensions/applyStyles.d.ts +12 -0
- package/dist/types/ts4.1/extensions/applyVisibility.d.ts +3 -0
- package/dist/types/ts4.1/extensions/connectedObserver.d.ts +15 -0
- package/dist/types/ts4.1/index.d.ts +12 -0
- package/dist/types/ts4.1/jsx.d.ts +55 -0
- package/dist/types/ts4.1/type.d.ts +10 -0
- package/dist/types/ts4.7/ActiveText.d.ts +8 -0
- package/dist/types/ts4.7/domUtil.d.ts +33 -0
- package/dist/types/ts4.7/extensions/HookExtension.d.ts +2 -0
- package/dist/types/ts4.7/extensions/applyClassList.d.ts +4 -0
- package/dist/types/ts4.7/extensions/applyPassiveHandler.d.ts +7 -0
- package/dist/types/ts4.7/extensions/applyStyles.d.ts +12 -0
- package/dist/types/ts4.7/extensions/applyVisibility.d.ts +3 -0
- package/dist/types/ts4.7/extensions/connectedObserver.d.ts +15 -0
- package/dist/types/ts4.7/index.d.ts +12 -0
- package/dist/types/ts4.7/jsx.d.ts +55 -0
- package/dist/types/ts4.7/type.d.ts +10 -0
- package/docs/TSX.md +316 -0
- package/package.json +82 -0
package/docs/TSX.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# TSX UI
|
|
2
|
+
|
|
3
|
+
Amazon Vinyl TSX is a lightweight, reactive JSX runtime for creating dynamic DOM
|
|
4
|
+
elements with TypeScript support. It provides a declarative way to build user
|
|
5
|
+
interfaces with reactive data binding using vinyl-observable.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Reactive Properties**: Bind observable values to DOM properties that update
|
|
10
|
+
automatically
|
|
11
|
+
- **Hook Extensions**: Enhanced DOM manipulation through custom hooks (style,
|
|
12
|
+
visibility, classList)
|
|
13
|
+
- **Lifecycle Management**: Automatic cleanup and connection tracking for DOM
|
|
14
|
+
elements
|
|
15
|
+
- **TypeScript Support**: Full type safety with utility types for property
|
|
16
|
+
extraction
|
|
17
|
+
- **Zero Dependencies**: Lightweight runtime with no external framework
|
|
18
|
+
dependencies
|
|
19
|
+
- **Performance Optimized**: Efficient updates with passive event handlers and
|
|
20
|
+
selective rendering
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @amazon/vinyl-tsx @amazon/vinyl-util @amazon/vinyl-observable
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Basic Usage
|
|
29
|
+
|
|
30
|
+
### Setting up JSX
|
|
31
|
+
|
|
32
|
+
Configure your TypeScript compiler to use the vinyl-tsx JSX factory:
|
|
33
|
+
|
|
34
|
+
// tsconfig.json
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"compilerOptions": {
|
|
39
|
+
"jsx": "preserve",
|
|
40
|
+
"jsxFactory": "jsx",
|
|
41
|
+
"jsxFragmentFactory": "Fragment"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Creating Elements
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { jsx } from '@amazon/vinyl-tsx'
|
|
50
|
+
|
|
51
|
+
// Basic element creation
|
|
52
|
+
const button = <button>Click me</button>
|
|
53
|
+
|
|
54
|
+
// With properties
|
|
55
|
+
const input = <input type="text" placeholder="Enter text" disabled={false} />
|
|
56
|
+
|
|
57
|
+
// With children
|
|
58
|
+
const container = (
|
|
59
|
+
<div className="container">
|
|
60
|
+
<h1>Title</h1>
|
|
61
|
+
<p>Content goes here</p>
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Reactive Properties
|
|
67
|
+
|
|
68
|
+
Use vinyl-observable to create reactive properties that automatically update the
|
|
69
|
+
DOM:
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { data } from '@amazon/vinyl-observable'
|
|
73
|
+
import { jsx } from '@amazon/vinyl-tsx'
|
|
74
|
+
|
|
75
|
+
const count = data(0)
|
|
76
|
+
const isVisible = data(true)
|
|
77
|
+
|
|
78
|
+
const counter = (
|
|
79
|
+
<div>
|
|
80
|
+
<span>Count: {count}</span>
|
|
81
|
+
<button onclick={() => count.value++}>Increment</button>
|
|
82
|
+
<button visible={isVisible}>Toggle me</button>
|
|
83
|
+
</div>
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
// Updates automatically when observable changes
|
|
87
|
+
count.value = 5 // DOM updates to show "Count: 5"
|
|
88
|
+
isVisible.value = false // Button becomes hidden
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Hook Extensions
|
|
92
|
+
|
|
93
|
+
Amazon Vinyl TSX provides several built-in hook extensions for enhanced DOM
|
|
94
|
+
manipulation:
|
|
95
|
+
|
|
96
|
+
### Style Hook
|
|
97
|
+
|
|
98
|
+
Apply CSS styles with support for both static and observable values:
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
import { data } from '@amazon/vinyl-observable'
|
|
102
|
+
|
|
103
|
+
const color = data('red')
|
|
104
|
+
const fontSize = data('16px')
|
|
105
|
+
|
|
106
|
+
const styledDiv = (
|
|
107
|
+
<div
|
|
108
|
+
style={{
|
|
109
|
+
color, // Observable value
|
|
110
|
+
fontSize, // Observable value
|
|
111
|
+
backgroundColor: 'blue', // Static value
|
|
112
|
+
padding: '10px', // Static value
|
|
113
|
+
}}
|
|
114
|
+
>
|
|
115
|
+
Styled content
|
|
116
|
+
</div>
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
// Updates automatically
|
|
120
|
+
color.value = 'green' // Text color changes to green
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Visibility Hook
|
|
124
|
+
|
|
125
|
+
Control element visibility with the `visible` property:
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
const isVisible = data(true)
|
|
129
|
+
|
|
130
|
+
const conditionalElement = (
|
|
131
|
+
<div visible={isVisible}>This element can be hidden/shown</div>
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
isVisible.value = false // Sets display: none
|
|
135
|
+
isVisible.value = true // Removes display property
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### ClassList Hook
|
|
139
|
+
|
|
140
|
+
Manage CSS classes dynamically with an array of static strings and/or observable
|
|
141
|
+
values:
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
const theme = data<string | null>('dark')
|
|
145
|
+
|
|
146
|
+
const element = <div classList={['base-class', theme]}>Content</div>
|
|
147
|
+
|
|
148
|
+
// Element has classes: base-class dark
|
|
149
|
+
theme.value = 'light' // Updates to: base-class light
|
|
150
|
+
theme.value = null // Updates to: base-class
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Connection Hook
|
|
154
|
+
|
|
155
|
+
Execute code when elements are connected to or disconnected from the DOM:
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
const element = (
|
|
159
|
+
<div
|
|
160
|
+
onConnect={(el) => {
|
|
161
|
+
console.log('Element connected:', el)
|
|
162
|
+
|
|
163
|
+
// Return cleanup function (optional)
|
|
164
|
+
return () => {
|
|
165
|
+
console.log('Element disconnected:', el)
|
|
166
|
+
}
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
Content
|
|
170
|
+
</div>
|
|
171
|
+
)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Event Handlers
|
|
175
|
+
|
|
176
|
+
Amazon Vinyl TSX automatically applies passive event listeners for touch and
|
|
177
|
+
scroll events:
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
const element = (
|
|
181
|
+
<div
|
|
182
|
+
ontouchstart={(e) => console.log('Touch start')}
|
|
183
|
+
ontouchmove={(e) => console.log('Touch move')}
|
|
184
|
+
onwheel={(e) => console.log('Wheel')}
|
|
185
|
+
onmousedown={(e) => console.log('Mouse down')}
|
|
186
|
+
>
|
|
187
|
+
Interactive content
|
|
188
|
+
</div>
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Fragments
|
|
193
|
+
|
|
194
|
+
Use fragments to group elements with a wrapper `div` using `display: contents`:
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
import { Fragment } from '@amazon/vinyl-tsx'
|
|
198
|
+
|
|
199
|
+
const list = (
|
|
200
|
+
<Fragment>
|
|
201
|
+
<li>Item 1</li>
|
|
202
|
+
<li>Item 2</li>
|
|
203
|
+
<li>Item 3</li>
|
|
204
|
+
</Fragment>
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
// Or with JSX fragment syntax
|
|
208
|
+
const list2 = (
|
|
209
|
+
<>
|
|
210
|
+
<li>Item 1</li>
|
|
211
|
+
<li>Item 2</li>
|
|
212
|
+
<li>Item 3</li>
|
|
213
|
+
</>
|
|
214
|
+
)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Advanced Usage
|
|
218
|
+
|
|
219
|
+
### Custom Components
|
|
220
|
+
|
|
221
|
+
Create reusable components as functions:
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
interface ButtonProps {
|
|
225
|
+
text: string
|
|
226
|
+
onClick: () => void
|
|
227
|
+
variant?: 'primary' | 'secondary'
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function Button({ text, onClick, variant = 'primary' }: ButtonProps) {
|
|
231
|
+
return (
|
|
232
|
+
<button className={`btn btn-${variant}`} onclick={onClick}>
|
|
233
|
+
{text}
|
|
234
|
+
</button>
|
|
235
|
+
)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Usage
|
|
239
|
+
const myButton = <Button text="Click me" onClick={() => alert('Clicked!')} />
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Reactive Text Content
|
|
243
|
+
|
|
244
|
+
Text content automatically becomes reactive when using observables:
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
const message = data('Hello')
|
|
248
|
+
const count = data(0)
|
|
249
|
+
|
|
250
|
+
const dynamicContent = (
|
|
251
|
+
<div>
|
|
252
|
+
<p>{message}</p>
|
|
253
|
+
<p>Count: {count}</p>
|
|
254
|
+
</div>
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
message.value = 'Hello World!' // Text updates automatically
|
|
258
|
+
count.value = 42 // Count updates automatically
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Conditional Rendering
|
|
262
|
+
|
|
263
|
+
Unlike React, vinyl-tsx does not re-render — JSX expressions are evaluated once
|
|
264
|
+
at creation time. Use the `visible` hook to reactively show or hide content:
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
const showDetails = data(false)
|
|
268
|
+
|
|
269
|
+
const userCard = (
|
|
270
|
+
<div>
|
|
271
|
+
<h3>John</h3>
|
|
272
|
+
<div visible={showDetails}>
|
|
273
|
+
<p>Email: john@example.com</p>
|
|
274
|
+
</div>
|
|
275
|
+
<button onclick={() => (showDetails.value = !showDetails.value)}>
|
|
276
|
+
Toggle Details
|
|
277
|
+
</button>
|
|
278
|
+
</div>
|
|
279
|
+
)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Best Practices
|
|
283
|
+
|
|
284
|
+
1. **Initialize Connected Observer**: Call `initializeConnectedObserver()` once
|
|
285
|
+
in your application to enable lifecycle management:
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
import { initializeConnectedObserver } from '@amazon/vinyl-tsx'
|
|
289
|
+
|
|
290
|
+
// Call once at application startup
|
|
291
|
+
const cleanup = initializeConnectedObserver()
|
|
292
|
+
|
|
293
|
+
// Call cleanup when shutting down (optional)
|
|
294
|
+
// cleanup()
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
1. **Use Observables for Dynamic Content**: Prefer observable values for
|
|
298
|
+
properties that change over time.
|
|
299
|
+
|
|
300
|
+
2. **Leverage Hook Extensions**: Use built-in hooks like `style`, `visible`, and
|
|
301
|
+
`classList` for common DOM manipulations.
|
|
302
|
+
|
|
303
|
+
3. **Type Safety**: Take advantage of TypeScript's type checking for props and
|
|
304
|
+
children.
|
|
305
|
+
|
|
306
|
+
4. **Memory Management**: The library automatically handles cleanup for
|
|
307
|
+
observable subscriptions when elements are disconnected.
|
|
308
|
+
|
|
309
|
+
## Performance Considerations
|
|
310
|
+
|
|
311
|
+
- **Selective Updates**: Only observable properties trigger DOM updates when
|
|
312
|
+
changed
|
|
313
|
+
- **Passive Events**: Touch and scroll events use passive listeners for better
|
|
314
|
+
performance
|
|
315
|
+
- **Efficient Cleanup**: Automatic subscription cleanup prevents memory leaks
|
|
316
|
+
- **Minimal Bundle Size**: Zero runtime dependencies keep bundle size small
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@amazon/vinyl-tsx",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TSX declarative markup for creating UI",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/amazonmusic/vinyl.git"
|
|
8
|
+
},
|
|
9
|
+
"license": "UNLICENSED",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"main": "./dist/index.cjs",
|
|
12
|
+
"types": "./dist/types/ts3.7/index.d.ts",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"sideEffects": [
|
|
15
|
+
"test/**/*"
|
|
16
|
+
],
|
|
17
|
+
"files": [
|
|
18
|
+
"dist/*",
|
|
19
|
+
"docs/*"
|
|
20
|
+
],
|
|
21
|
+
"typesVersions": {
|
|
22
|
+
">=5.4": {
|
|
23
|
+
"*": [
|
|
24
|
+
"./dist/types/current/index.d.ts"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
">=4.7": {
|
|
28
|
+
"*": [
|
|
29
|
+
"./dist/types/ts4.7/index.d.ts"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
">=4.1": {
|
|
33
|
+
"*": [
|
|
34
|
+
"./dist/types/ts4.1/index.d.ts"
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
">=3.7": {
|
|
38
|
+
"*": [
|
|
39
|
+
"./dist/types/ts3.7/index.d.ts"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"exports": {
|
|
44
|
+
".": {
|
|
45
|
+
"types@>=5.4": "./dist/types/current/index.d.ts",
|
|
46
|
+
"types@>=4.7": "./dist/types/ts4.7/index.d.ts",
|
|
47
|
+
"require": "./dist/index.cjs",
|
|
48
|
+
"import": "./dist/index.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"analyzeExports": "tsx buildSrc/analyzeExports.ts",
|
|
53
|
+
"analyzeExports:write": "tsx buildSrc/analyzeExports.ts --write",
|
|
54
|
+
"clean": "rimraf --glob dist .eslintcache \"**/*.tsbuildinfo\"",
|
|
55
|
+
"indexFiles:check": "tsx buildSrc/writeIndexFiles.ts --check",
|
|
56
|
+
"indexFiles:write": "tsx buildSrc/writeIndexFiles.ts",
|
|
57
|
+
"build": "tsx buildSrc/build.ts",
|
|
58
|
+
"build:release": "tsx buildSrc/build.ts --release",
|
|
59
|
+
"prettier:check": "prettier . --ignore-path ../../.prettierignore --cache --check",
|
|
60
|
+
"prettier:write": "prettier . --ignore-path ../../.prettierignore --cache --write",
|
|
61
|
+
"eslint:check": "eslint . --cache --max-warnings=0",
|
|
62
|
+
"eslint:write": "eslint . --cache --fix",
|
|
63
|
+
"lint": "npm run indexFiles:check && npm run eslint:check && npm run prettier:check",
|
|
64
|
+
"lint:write": "npm run indexFiles:write && npm run eslint:write && npm run prettier:write",
|
|
65
|
+
"validate": "tsc --project test/unit && npm run lint && npm run test",
|
|
66
|
+
"test": "tsx --tsconfig ../../tsconfig.flat.json ../../node_modules/jasmine/bin/jasmine --config=test/unit/jasmine.config.json",
|
|
67
|
+
"test:coverage": "c8 npm run test",
|
|
68
|
+
"watch": "tsx buildSrc/build.ts --watch",
|
|
69
|
+
"watch:release": "tsx buildSrc/build.ts --watch --release"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@amazon/vinyl-build-utils": "^1.0.0",
|
|
73
|
+
"@amazon/vinyl-jasmine-wrapper": "^1.0.0"
|
|
74
|
+
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"@amazon/vinyl-observable": "^1.0.0",
|
|
77
|
+
"@amazon/vinyl-util": "^1.0.0"
|
|
78
|
+
},
|
|
79
|
+
"browserslist": [
|
|
80
|
+
"defaults, chrome 52, firefox 54, edge 15, safari 8"
|
|
81
|
+
]
|
|
82
|
+
}
|