@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.
Files changed (73) hide show
  1. package/dist/index.cjs +354 -0
  2. package/dist/index.cjs.map +7 -0
  3. package/dist/index.js +340 -0
  4. package/dist/index.js.map +7 -0
  5. package/dist/types/current/ActiveText.d.ts +8 -0
  6. package/dist/types/current/ActiveText.d.ts.map +1 -0
  7. package/dist/types/current/ActiveText.js +19 -0
  8. package/dist/types/current/domUtil.d.ts +33 -0
  9. package/dist/types/current/domUtil.d.ts.map +1 -0
  10. package/dist/types/current/domUtil.js +73 -0
  11. package/dist/types/current/extensions/HookExtension.d.ts +2 -0
  12. package/dist/types/current/extensions/HookExtension.d.ts.map +1 -0
  13. package/dist/types/current/extensions/HookExtension.js +5 -0
  14. package/dist/types/current/extensions/applyClassList.d.ts +4 -0
  15. package/dist/types/current/extensions/applyClassList.d.ts.map +1 -0
  16. package/dist/types/current/extensions/applyClassList.js +40 -0
  17. package/dist/types/current/extensions/applyPassiveHandler.d.ts +7 -0
  18. package/dist/types/current/extensions/applyPassiveHandler.d.ts.map +1 -0
  19. package/dist/types/current/extensions/applyPassiveHandler.js +15 -0
  20. package/dist/types/current/extensions/applyStyles.d.ts +12 -0
  21. package/dist/types/current/extensions/applyStyles.d.ts.map +1 -0
  22. package/dist/types/current/extensions/applyStyles.js +31 -0
  23. package/dist/types/current/extensions/applyVisibility.d.ts +3 -0
  24. package/dist/types/current/extensions/applyVisibility.d.ts.map +1 -0
  25. package/dist/types/current/extensions/applyVisibility.js +21 -0
  26. package/dist/types/current/extensions/connectedObserver.d.ts +15 -0
  27. package/dist/types/current/extensions/connectedObserver.d.ts.map +1 -0
  28. package/dist/types/current/extensions/connectedObserver.js +72 -0
  29. package/dist/types/current/index.d.ts +12 -0
  30. package/dist/types/current/index.d.ts.map +1 -0
  31. package/dist/types/current/index.js +11 -0
  32. package/dist/types/current/jsx.d.ts +55 -0
  33. package/dist/types/current/jsx.d.ts.map +1 -0
  34. package/dist/types/current/jsx.js +106 -0
  35. package/dist/types/current/tsconfig.tsbuildinfo +1 -0
  36. package/dist/types/current/type.d.ts +10 -0
  37. package/dist/types/current/type.d.ts.map +1 -0
  38. package/dist/types/current/type.js +5 -0
  39. package/dist/types/ts3.7/ActiveText.d.ts +8 -0
  40. package/dist/types/ts3.7/domUtil.d.ts +33 -0
  41. package/dist/types/ts3.7/extensions/HookExtension.d.ts +2 -0
  42. package/dist/types/ts3.7/extensions/applyClassList.d.ts +4 -0
  43. package/dist/types/ts3.7/extensions/applyPassiveHandler.d.ts +7 -0
  44. package/dist/types/ts3.7/extensions/applyStyles.d.ts +12 -0
  45. package/dist/types/ts3.7/extensions/applyVisibility.d.ts +3 -0
  46. package/dist/types/ts3.7/extensions/connectedObserver.d.ts +15 -0
  47. package/dist/types/ts3.7/index.d.ts +12 -0
  48. package/dist/types/ts3.7/jsx.d.ts +55 -0
  49. package/dist/types/ts3.7/type.d.ts +10 -0
  50. package/dist/types/ts4.1/ActiveText.d.ts +8 -0
  51. package/dist/types/ts4.1/domUtil.d.ts +33 -0
  52. package/dist/types/ts4.1/extensions/HookExtension.d.ts +2 -0
  53. package/dist/types/ts4.1/extensions/applyClassList.d.ts +4 -0
  54. package/dist/types/ts4.1/extensions/applyPassiveHandler.d.ts +7 -0
  55. package/dist/types/ts4.1/extensions/applyStyles.d.ts +12 -0
  56. package/dist/types/ts4.1/extensions/applyVisibility.d.ts +3 -0
  57. package/dist/types/ts4.1/extensions/connectedObserver.d.ts +15 -0
  58. package/dist/types/ts4.1/index.d.ts +12 -0
  59. package/dist/types/ts4.1/jsx.d.ts +55 -0
  60. package/dist/types/ts4.1/type.d.ts +10 -0
  61. package/dist/types/ts4.7/ActiveText.d.ts +8 -0
  62. package/dist/types/ts4.7/domUtil.d.ts +33 -0
  63. package/dist/types/ts4.7/extensions/HookExtension.d.ts +2 -0
  64. package/dist/types/ts4.7/extensions/applyClassList.d.ts +4 -0
  65. package/dist/types/ts4.7/extensions/applyPassiveHandler.d.ts +7 -0
  66. package/dist/types/ts4.7/extensions/applyStyles.d.ts +12 -0
  67. package/dist/types/ts4.7/extensions/applyVisibility.d.ts +3 -0
  68. package/dist/types/ts4.7/extensions/connectedObserver.d.ts +15 -0
  69. package/dist/types/ts4.7/index.d.ts +12 -0
  70. package/dist/types/ts4.7/jsx.d.ts +55 -0
  71. package/dist/types/ts4.7/type.d.ts +10 -0
  72. package/docs/TSX.md +316 -0
  73. 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
+ }