@teleporthq/teleport-shared 0.43.69 → 0.43.71

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 (160) hide show
  1. package/__tests__/motion-runtime/motion-engine.ts +102 -0
  2. package/__tests__/motion-runtime/scroll-video-engine.ts +28 -0
  3. package/__tests__/scroll-scene/story-lanes.ts +126 -0
  4. package/__tests__/utils/inline-script-error-guard.ts +121 -0
  5. package/dist/cjs/index.d.ts +6 -1
  6. package/dist/cjs/index.d.ts.map +1 -1
  7. package/dist/cjs/index.js +11 -1
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/motion-runtime/index.d.ts +3 -0
  10. package/dist/cjs/motion-runtime/index.d.ts.map +1 -0
  11. package/dist/cjs/motion-runtime/index.js +8 -0
  12. package/dist/cjs/motion-runtime/index.js.map +1 -0
  13. package/dist/cjs/motion-runtime/motion-engine-source.d.ts +16 -0
  14. package/dist/cjs/motion-runtime/motion-engine-source.d.ts.map +1 -0
  15. package/dist/cjs/motion-runtime/motion-engine-source.js +20 -0
  16. package/dist/cjs/motion-runtime/motion-engine-source.js.map +1 -0
  17. package/dist/cjs/motion-runtime/scroll-video-engine-source.d.ts +9 -0
  18. package/dist/cjs/motion-runtime/scroll-video-engine-source.d.ts.map +1 -0
  19. package/dist/cjs/motion-runtime/scroll-video-engine-source.js +13 -0
  20. package/dist/cjs/motion-runtime/scroll-video-engine-source.js.map +1 -0
  21. package/dist/cjs/page-transition/index.d.ts +4 -0
  22. package/dist/cjs/page-transition/index.d.ts.map +1 -0
  23. package/dist/cjs/page-transition/index.js +20 -0
  24. package/dist/cjs/page-transition/index.js.map +1 -0
  25. package/dist/cjs/page-transition/morph-source.d.ts +20 -0
  26. package/dist/cjs/page-transition/morph-source.d.ts.map +1 -0
  27. package/dist/cjs/page-transition/morph-source.js +25 -0
  28. package/dist/cjs/page-transition/morph-source.js.map +1 -0
  29. package/dist/cjs/page-transition/variants.d.ts +87 -0
  30. package/dist/cjs/page-transition/variants.d.ts.map +1 -0
  31. package/dist/cjs/page-transition/variants.js +330 -0
  32. package/dist/cjs/page-transition/variants.js.map +1 -0
  33. package/dist/cjs/page-transition/view-transition-css.d.ts +21 -0
  34. package/dist/cjs/page-transition/view-transition-css.d.ts.map +1 -0
  35. package/dist/cjs/page-transition/view-transition-css.js +188 -0
  36. package/dist/cjs/page-transition/view-transition-css.js.map +1 -0
  37. package/dist/cjs/scroll-scene/chapter-index.d.ts +15 -0
  38. package/dist/cjs/scroll-scene/chapter-index.d.ts.map +1 -0
  39. package/dist/cjs/scroll-scene/chapter-index.js +30 -0
  40. package/dist/cjs/scroll-scene/chapter-index.js.map +1 -0
  41. package/dist/cjs/scroll-scene/controller-source.d.ts +26 -0
  42. package/dist/cjs/scroll-scene/controller-source.d.ts.map +1 -0
  43. package/dist/cjs/scroll-scene/controller-source.js +34 -0
  44. package/dist/cjs/scroll-scene/controller-source.js.map +1 -0
  45. package/dist/cjs/scroll-scene/engine-source.d.ts +2 -0
  46. package/dist/cjs/scroll-scene/engine-source.d.ts.map +1 -0
  47. package/dist/cjs/scroll-scene/engine-source.js +26 -0
  48. package/dist/cjs/scroll-scene/engine-source.js.map +1 -0
  49. package/dist/cjs/scroll-scene/index.d.ts +7 -0
  50. package/dist/cjs/scroll-scene/index.d.ts.map +1 -0
  51. package/dist/cjs/scroll-scene/index.js +22 -0
  52. package/dist/cjs/scroll-scene/index.js.map +1 -0
  53. package/dist/cjs/scroll-scene/moment.d.ts +21 -0
  54. package/dist/cjs/scroll-scene/moment.d.ts.map +1 -0
  55. package/dist/cjs/scroll-scene/moment.js +50 -0
  56. package/dist/cjs/scroll-scene/moment.js.map +1 -0
  57. package/dist/cjs/scroll-scene/points.d.ts +23 -0
  58. package/dist/cjs/scroll-scene/points.d.ts.map +1 -0
  59. package/dist/cjs/scroll-scene/points.js +51 -0
  60. package/dist/cjs/scroll-scene/points.js.map +1 -0
  61. package/dist/cjs/scroll-scene/unclip.d.ts +15 -0
  62. package/dist/cjs/scroll-scene/unclip.d.ts.map +1 -0
  63. package/dist/cjs/scroll-scene/unclip.js +44 -0
  64. package/dist/cjs/scroll-scene/unclip.js.map +1 -0
  65. package/dist/cjs/state-bindings/index.d.ts +74 -0
  66. package/dist/cjs/state-bindings/index.d.ts.map +1 -0
  67. package/dist/cjs/state-bindings/index.js +193 -0
  68. package/dist/cjs/state-bindings/index.js.map +1 -0
  69. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  70. package/dist/cjs/utils/inline-script-error-guard.d.ts +29 -0
  71. package/dist/cjs/utils/inline-script-error-guard.d.ts.map +1 -0
  72. package/dist/cjs/utils/inline-script-error-guard.js +38 -0
  73. package/dist/cjs/utils/inline-script-error-guard.js.map +1 -0
  74. package/dist/esm/index.d.ts +6 -1
  75. package/dist/esm/index.d.ts.map +1 -1
  76. package/dist/esm/index.js +6 -1
  77. package/dist/esm/index.js.map +1 -1
  78. package/dist/esm/motion-runtime/index.d.ts +3 -0
  79. package/dist/esm/motion-runtime/index.d.ts.map +1 -0
  80. package/dist/esm/motion-runtime/index.js +3 -0
  81. package/dist/esm/motion-runtime/index.js.map +1 -0
  82. package/dist/esm/motion-runtime/motion-engine-source.d.ts +16 -0
  83. package/dist/esm/motion-runtime/motion-engine-source.d.ts.map +1 -0
  84. package/dist/esm/motion-runtime/motion-engine-source.js +16 -0
  85. package/dist/esm/motion-runtime/motion-engine-source.js.map +1 -0
  86. package/dist/esm/motion-runtime/scroll-video-engine-source.d.ts +9 -0
  87. package/dist/esm/motion-runtime/scroll-video-engine-source.d.ts.map +1 -0
  88. package/dist/esm/motion-runtime/scroll-video-engine-source.js +9 -0
  89. package/dist/esm/motion-runtime/scroll-video-engine-source.js.map +1 -0
  90. package/dist/esm/page-transition/index.d.ts +4 -0
  91. package/dist/esm/page-transition/index.d.ts.map +1 -0
  92. package/dist/esm/page-transition/index.js +4 -0
  93. package/dist/esm/page-transition/index.js.map +1 -0
  94. package/dist/esm/page-transition/morph-source.d.ts +20 -0
  95. package/dist/esm/page-transition/morph-source.d.ts.map +1 -0
  96. package/dist/esm/page-transition/morph-source.js +21 -0
  97. package/dist/esm/page-transition/morph-source.js.map +1 -0
  98. package/dist/esm/page-transition/variants.d.ts +87 -0
  99. package/dist/esm/page-transition/variants.d.ts.map +1 -0
  100. package/dist/esm/page-transition/variants.js +318 -0
  101. package/dist/esm/page-transition/variants.js.map +1 -0
  102. package/dist/esm/page-transition/view-transition-css.d.ts +21 -0
  103. package/dist/esm/page-transition/view-transition-css.d.ts.map +1 -0
  104. package/dist/esm/page-transition/view-transition-css.js +161 -0
  105. package/dist/esm/page-transition/view-transition-css.js.map +1 -0
  106. package/dist/esm/scroll-scene/chapter-index.d.ts +15 -0
  107. package/dist/esm/scroll-scene/chapter-index.d.ts.map +1 -0
  108. package/dist/esm/scroll-scene/chapter-index.js +26 -0
  109. package/dist/esm/scroll-scene/chapter-index.js.map +1 -0
  110. package/dist/esm/scroll-scene/controller-source.d.ts +26 -0
  111. package/dist/esm/scroll-scene/controller-source.d.ts.map +1 -0
  112. package/dist/esm/scroll-scene/controller-source.js +26 -0
  113. package/dist/esm/scroll-scene/controller-source.js.map +1 -0
  114. package/dist/esm/scroll-scene/engine-source.d.ts +2 -0
  115. package/dist/esm/scroll-scene/engine-source.d.ts.map +1 -0
  116. package/dist/esm/scroll-scene/engine-source.js +22 -0
  117. package/dist/esm/scroll-scene/engine-source.js.map +1 -0
  118. package/dist/esm/scroll-scene/index.d.ts +7 -0
  119. package/dist/esm/scroll-scene/index.d.ts.map +1 -0
  120. package/dist/esm/scroll-scene/index.js +7 -0
  121. package/dist/esm/scroll-scene/index.js.map +1 -0
  122. package/dist/esm/scroll-scene/moment.d.ts +21 -0
  123. package/dist/esm/scroll-scene/moment.d.ts.map +1 -0
  124. package/dist/esm/scroll-scene/moment.js +46 -0
  125. package/dist/esm/scroll-scene/moment.js.map +1 -0
  126. package/dist/esm/scroll-scene/points.d.ts +23 -0
  127. package/dist/esm/scroll-scene/points.d.ts.map +1 -0
  128. package/dist/esm/scroll-scene/points.js +45 -0
  129. package/dist/esm/scroll-scene/points.js.map +1 -0
  130. package/dist/esm/scroll-scene/unclip.d.ts +15 -0
  131. package/dist/esm/scroll-scene/unclip.d.ts.map +1 -0
  132. package/dist/esm/scroll-scene/unclip.js +40 -0
  133. package/dist/esm/scroll-scene/unclip.js.map +1 -0
  134. package/dist/esm/state-bindings/index.d.ts +74 -0
  135. package/dist/esm/state-bindings/index.d.ts.map +1 -0
  136. package/dist/esm/state-bindings/index.js +176 -0
  137. package/dist/esm/state-bindings/index.js.map +1 -0
  138. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  139. package/dist/esm/utils/inline-script-error-guard.d.ts +29 -0
  140. package/dist/esm/utils/inline-script-error-guard.d.ts.map +1 -0
  141. package/dist/esm/utils/inline-script-error-guard.js +34 -0
  142. package/dist/esm/utils/inline-script-error-guard.js.map +1 -0
  143. package/package.json +3 -3
  144. package/src/index.ts +10 -0
  145. package/src/motion-runtime/index.ts +2 -0
  146. package/src/motion-runtime/motion-engine-source.ts +289 -0
  147. package/src/motion-runtime/scroll-video-engine-source.ts +591 -0
  148. package/src/page-transition/index.ts +3 -0
  149. package/src/page-transition/morph-source.ts +86 -0
  150. package/src/page-transition/variants.ts +407 -0
  151. package/src/page-transition/view-transition-css.ts +237 -0
  152. package/src/scroll-scene/chapter-index.ts +25 -0
  153. package/src/scroll-scene/controller-source.ts +451 -0
  154. package/src/scroll-scene/engine-source.ts +330 -0
  155. package/src/scroll-scene/index.ts +12 -0
  156. package/src/scroll-scene/moment.ts +64 -0
  157. package/src/scroll-scene/points.ts +46 -0
  158. package/src/scroll-scene/unclip.ts +44 -0
  159. package/src/state-bindings/index.ts +207 -0
  160. package/src/utils/inline-script-error-guard.ts +51 -0
@@ -0,0 +1,207 @@
1
+ /**
2
+ * State bindings of the static HTML export: the attributes a downloaded page
3
+ * carries so that clicks open menus, switch tabs and restyle elements, and the
4
+ * small expression language they are written in. The HTML generator writes
5
+ * them (teleport-plugin-html-base-component), the one runtime file a download
6
+ * ships (`tq-state.js`, teleport-project-generator-html) reads them back.
7
+ *
8
+ * data-tq-scope="Navigation" a page root or a component instance:
9
+ * data-tq-state="menuOpen = false" its own store, with its starting values
10
+ * data-tq-if="menuOpen" shown while true; `hidden` when it starts false
11
+ * data-tq-class="active: tab === 0" the class is on while true
12
+ * data-tq-on-click="menuOpen = !menuOpen"
13
+ * data-tq-slot content a parent put into a component:
14
+ * it reads the parent's store
15
+ *
16
+ * The language has literals (numbers, 'quoted strings', true, false, null),
17
+ * state names, `!`, `+ -`, the six comparisons and `&& ||`, with JavaScript's
18
+ * meaning. Nothing is ever evaluated as JavaScript, so a page keeps working
19
+ * under a strict Content-Security-Policy.
20
+ */
21
+
22
+ export const SCOPE_ATTR = 'data-tq-scope'
23
+ export const STATE_ATTR = 'data-tq-state'
24
+ export const SLOT_ATTR = 'data-tq-slot'
25
+ export const IF_ATTR = 'data-tq-if'
26
+ export const CLASS_ATTR = 'data-tq-class'
27
+ export const CLICK_ATTR = 'data-tq-on-click'
28
+
29
+ export const RUNTIME_FILE_NAME = 'tq-state'
30
+
31
+ export type StateValue = string | number | boolean | null
32
+
33
+ export type ComparisonOperator = '===' | '!==' | '<' | '<=' | '>' | '>='
34
+ export type BinaryOperator = '||' | '&&' | ComparisonOperator | '+' | '-'
35
+
36
+ export type StateExpression =
37
+ | { kind: 'literal'; value: StateValue }
38
+ | { kind: 'state'; name: string }
39
+ | { kind: 'not'; operand: StateExpression }
40
+ | { kind: 'binary'; operator: BinaryOperator; left: StateExpression; right: StateExpression }
41
+
42
+ export interface StateAssignment {
43
+ name: string
44
+ value: StateExpression
45
+ }
46
+
47
+ export interface ClassBinding {
48
+ className: string
49
+ condition: StateExpression
50
+ }
51
+
52
+ const RESERVED_WORDS = ['true', 'false', 'null']
53
+
54
+ export const isStateName = (name: string): boolean =>
55
+ /^[A-Za-z_$][\w$]*$/.test(name) && !RESERVED_WORDS.includes(name)
56
+
57
+ export const isBindableClassName = (name: string): boolean => /^[^\s:;'"\\]+$/.test(name)
58
+
59
+ export const isStateValue = (value: unknown): value is StateValue =>
60
+ value === null ||
61
+ typeof value === 'string' ||
62
+ typeof value === 'boolean' ||
63
+ (typeof value === 'number' && Number.isFinite(value))
64
+
65
+ export const literal = (value: StateValue): StateExpression => ({ kind: 'literal', value })
66
+ export const state = (name: string): StateExpression => ({ kind: 'state', name })
67
+ export const not = (operand: StateExpression): StateExpression => ({ kind: 'not', operand })
68
+ export const binary = (
69
+ operator: BinaryOperator,
70
+ left: StateExpression,
71
+ right: StateExpression
72
+ ): StateExpression => ({ kind: 'binary', operator, left, right })
73
+
74
+ export const stateNamesOf = (expression: StateExpression, names = new Set<string>()) => {
75
+ switch (expression.kind) {
76
+ case 'state':
77
+ names.add(expression.name)
78
+ break
79
+ case 'not':
80
+ stateNamesOf(expression.operand, names)
81
+ break
82
+ case 'binary':
83
+ stateNamesOf(expression.left, names)
84
+ stateNamesOf(expression.right, names)
85
+ break
86
+ default:
87
+ break
88
+ }
89
+ return names
90
+ }
91
+
92
+ const PRECEDENCE: Record<BinaryOperator, number> = {
93
+ '||': 1,
94
+ '&&': 2,
95
+ '===': 3,
96
+ '!==': 3,
97
+ '<': 3,
98
+ '<=': 3,
99
+ '>': 3,
100
+ '>=': 3,
101
+ '+': 4,
102
+ '-': 4,
103
+ }
104
+ const UNARY_PRECEDENCE = 5
105
+ const PRIMARY_PRECEDENCE = 6
106
+
107
+ const precedenceOf = (expression: StateExpression): number => {
108
+ if (expression.kind === 'binary') {
109
+ return PRECEDENCE[expression.operator]
110
+ }
111
+ return expression.kind === 'not' ? UNARY_PRECEDENCE : PRIMARY_PRECEDENCE
112
+ }
113
+
114
+ const printOperand = (expression: StateExpression, lowestUnwrapped: number): string =>
115
+ precedenceOf(expression) < lowestUnwrapped
116
+ ? `(${printExpression(expression)})`
117
+ : printExpression(expression)
118
+
119
+ export const printValue = (value: StateValue): string => {
120
+ if (typeof value === 'string') {
121
+ return `'${value.replace(/[\\']/g, '\\$&')}'`
122
+ }
123
+ return String(value)
124
+ }
125
+
126
+ export const printExpression = (expression: StateExpression): string => {
127
+ switch (expression.kind) {
128
+ case 'literal':
129
+ return printValue(expression.value)
130
+ case 'state':
131
+ return expression.name
132
+ case 'not':
133
+ return `!${printOperand(expression.operand, UNARY_PRECEDENCE)}`
134
+ case 'binary': {
135
+ const level = PRECEDENCE[expression.operator]
136
+ const chains = expression.operator === '||' || expression.operator === '&&'
137
+ const left = printOperand(expression.left, level === 3 ? level + 1 : level)
138
+ const right = printOperand(expression.right, chains ? level : level + 1)
139
+ return `${left} ${expression.operator} ${right}`
140
+ }
141
+ default:
142
+ throw new Error(`Unknown state expression ${JSON.stringify(expression)}`)
143
+ }
144
+ }
145
+
146
+ export const printAssignments = (assignments: StateAssignment[]): string =>
147
+ assignments.map(({ name, value }) => `${name} = ${printExpression(value)}`).join('; ')
148
+
149
+ export const printClassBindings = (bindings: ClassBinding[]): string =>
150
+ bindings
151
+ .map(({ className, condition }) => `${className}: ${printExpression(condition)}`)
152
+ .join('; ')
153
+
154
+ /** The same meaning the runtime gives an expression, for the page's first paint. */
155
+ export const evaluateExpression = (
156
+ expression: StateExpression,
157
+ values: Record<string, StateValue>
158
+ ): unknown => {
159
+ switch (expression.kind) {
160
+ case 'literal':
161
+ return expression.value
162
+ case 'state':
163
+ return Object.prototype.hasOwnProperty.call(values, expression.name)
164
+ ? values[expression.name]
165
+ : undefined
166
+ case 'not':
167
+ return !evaluateExpression(expression.operand, values)
168
+ case 'binary': {
169
+ const left = evaluateExpression(expression.left, values) as any
170
+ const right = evaluateExpression(expression.right, values) as any
171
+ switch (expression.operator) {
172
+ case '||':
173
+ return left || right
174
+ case '&&':
175
+ return left && right
176
+ case '===':
177
+ return left === right
178
+ case '!==':
179
+ return left !== right
180
+ case '<':
181
+ return left < right
182
+ case '<=':
183
+ return left <= right
184
+ case '>':
185
+ return left > right
186
+ case '>=':
187
+ return left >= right
188
+ case '+':
189
+ return left + right
190
+ case '-':
191
+ return left - right
192
+ default:
193
+ throw new Error(`Unknown state operator ${expression.operator}`)
194
+ }
195
+ }
196
+ default:
197
+ throw new Error(`Unknown state expression ${JSON.stringify(expression)}`)
198
+ }
199
+ }
200
+
201
+ /**
202
+ * An attribute value as the HTML printer must receive it: it writes values
203
+ * between double quotes and escapes nothing. `&&` and `<` stay readable; an
204
+ * ampersand that could start a character reference does not.
205
+ */
206
+ export const escapeAttributeValue = (value: string): string =>
207
+ value.replace(/&(?=[A-Za-z#])/g, '&amp;').replace(/"/g, '&quot;')
@@ -0,0 +1,51 @@
1
+ import { UIDLGlobalProjectValues } from '@teleporthq/teleport-types'
2
+
3
+ /**
4
+ * Keeps an error thrown by the project's OWN inline scripts from surfacing as an
5
+ * unhandled error of the generated app.
6
+ *
7
+ * The project's custom code (Project settings → Custom code) and its inline
8
+ * script assets are pasted into the document as inline `<script>`s. When one of
9
+ * them throws — a custom accordion script calling `addEventListener` on a header
10
+ * the markup no longer has — the browser reports the error as uncaught, and the
11
+ * generated app's development server (Next.js) covers the page with its error
12
+ * overlay, on every page and again after every navigation. The app is fine; the
13
+ * script is not.
14
+ *
15
+ * An inline script reports the URL of the document it was parsed with as its
16
+ * file, both for an error thrown while it runs and for one thrown later by a
17
+ * callback it registered; the app's bundles and external scripts report their
18
+ * own URLs. The guard is the first script of the document, so its capture
19
+ * listener runs before every other `error` listener (the overlay's included):
20
+ * it stops such an error there and logs it as a warning instead. The scripts
21
+ * themselves are not wrapped or rewritten, so a top-level declaration one script
22
+ * shares with the next keeps working.
23
+ */
24
+ export const INLINE_SCRIPT_ERROR_GUARD = `(function () {
25
+ var documentUrl = String(document.URL).split('#')[0]
26
+ window.addEventListener(
27
+ 'error',
28
+ function (event) {
29
+ if (!event.error || String(event.filename || '').split('#')[0] !== documentUrl) {
30
+ return
31
+ }
32
+ event.preventDefault()
33
+ event.stopImmediatePropagation()
34
+ console.warn('A custom code script on this page failed:', event.error)
35
+ },
36
+ true
37
+ )
38
+ })()`
39
+
40
+ const SCRIPT_TAG = /<script\b/i
41
+
42
+ /**
43
+ * Whether the document runs scripts the project wrote itself — the only case the
44
+ * guard is emitted in, so a project without any comes out exactly as before.
45
+ */
46
+ export const documentRunsProjectScripts = (
47
+ globals: Pick<UIDLGlobalProjectValues, 'customCode' | 'assets'>
48
+ ): boolean =>
49
+ SCRIPT_TAG.test(globals.customCode?.head || '') ||
50
+ SCRIPT_TAG.test(globals.customCode?.body || '') ||
51
+ (globals.assets || []).some((asset) => asset.type === 'script' && 'content' in asset)