tungsten 0.4.14 → 0.5.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 (159) hide show
  1. package/dist/.build-complete +1 -1
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/Components.d.ts +1 -0
  4. package/dist/Components.d.ts.map +1 -1
  5. package/dist/Components.js +2 -0
  6. package/dist/ContentNode.d.ts +8 -2
  7. package/dist/ContentNode.d.ts.map +1 -1
  8. package/dist/ContentNode.js +4 -1
  9. package/dist/Framework.js +4 -4
  10. package/dist/FrameworkConfig.d.ts +0 -2
  11. package/dist/FrameworkConfig.d.ts.map +1 -1
  12. package/dist/FunctionComponentStandIn.d.ts +1 -1
  13. package/dist/FunctionComponentStandIn.d.ts.map +1 -1
  14. package/dist/FunctionComponentStandIn.js +1 -0
  15. package/dist/Instance/Instance.js +2 -2
  16. package/dist/RenderingNode.d.ts +2 -2
  17. package/dist/RenderingNode.d.ts.map +1 -1
  18. package/dist/Script.d.ts +1 -1
  19. package/dist/Script.d.ts.map +1 -1
  20. package/dist/Servers/DevServer.d.ts.map +1 -1
  21. package/dist/Servers/DevServer.js +10 -0
  22. package/dist/Servers/loadEnvsDev.js +10 -10
  23. package/dist/Servers/routing.d.ts.map +1 -1
  24. package/dist/Servers/routing.js +8 -9
  25. package/dist/Store/makeStore.d.ts +4 -4
  26. package/dist/Store/makeStore.d.ts.map +1 -1
  27. package/dist/Store/makeStore.js +23 -57
  28. package/dist/babelPlugins/BabelTransformDocInit.d.ts +9 -0
  29. package/dist/babelPlugins/BabelTransformDocInit.d.ts.map +1 -0
  30. package/dist/babelPlugins/BabelTransformDocInit.js +201 -0
  31. package/dist/babelPlugins/BabelTransformPackageImports.d.ts.map +1 -1
  32. package/dist/babelPlugins/BabelTransformPackageImports.js +1 -10
  33. package/dist/bin/index.d.ts.map +1 -1
  34. package/dist/bin/index.js +82 -75
  35. package/dist/browserStorage.d.ts +56 -18
  36. package/dist/browserStorage.d.ts.map +1 -1
  37. package/dist/browserStorage.js +172 -102
  38. package/dist/build/bundle.d.ts +1 -1
  39. package/dist/build/bundle.d.ts.map +1 -1
  40. package/dist/build/bundle.js +45 -40
  41. package/dist/build/compileJavascript.d.ts.map +1 -1
  42. package/dist/build/compileJavascript.js +0 -1
  43. package/dist/build/makeBabelUserDevConfig.d.ts.map +1 -1
  44. package/dist/build/makeBabelUserDevConfig.js +5 -1
  45. package/dist/build/makeBabelUserProdConfig.d.ts.map +1 -1
  46. package/dist/build/makeBabelUserProdConfig.js +5 -1
  47. package/dist/cliOutput.d.ts +5 -0
  48. package/dist/cliOutput.d.ts.map +1 -1
  49. package/dist/cliOutput.js +22 -0
  50. package/dist/components/Link.d.ts +1 -1
  51. package/dist/components/Link.d.ts.map +1 -1
  52. package/dist/components/NativeHtml.d.ts +10 -0
  53. package/dist/components/NativeHtml.d.ts.map +1 -0
  54. package/dist/components/NativeHtml.js +12 -0
  55. package/dist/components/PopMessages.d.ts +1 -1
  56. package/dist/components/PopMessages.d.ts.map +1 -1
  57. package/dist/components/Protected.d.ts +10 -0
  58. package/dist/components/Protected.d.ts.map +1 -0
  59. package/dist/components/Protected.js +12 -0
  60. package/dist/components/Stylesheet.d.ts +1 -1
  61. package/dist/components/Stylesheet.d.ts.map +1 -1
  62. package/dist/components/bindable/BindableCheckbox.d.ts +1 -1
  63. package/dist/components/bindable/BindableCheckbox.d.ts.map +1 -1
  64. package/dist/components/bindable/BindableInput.d.ts +1 -1
  65. package/dist/components/bindable/BindableInput.d.ts.map +1 -1
  66. package/dist/components/bindable/BindableInputNonString.d.ts +1 -1
  67. package/dist/components/bindable/BindableInputNonString.d.ts.map +1 -1
  68. package/dist/components/bindable/BindableInputString.d.ts +1 -1
  69. package/dist/components/bindable/BindableInputString.d.ts.map +1 -1
  70. package/dist/components/bindable/BindableInputTyped.d.ts +1 -1
  71. package/dist/components/bindable/BindableInputTyped.d.ts.map +1 -1
  72. package/dist/components/bindable/BindableInputTypedLegacy.d.ts +1 -1
  73. package/dist/components/bindable/BindableInputTypedLegacy.d.ts.map +1 -1
  74. package/dist/components/bindable/BindableRadio.d.ts +1 -1
  75. package/dist/components/bindable/BindableRadio.d.ts.map +1 -1
  76. package/dist/components/bindable/BindableSelect.d.ts +1 -1
  77. package/dist/components/bindable/BindableSelect.d.ts.map +1 -1
  78. package/dist/components/bindable/BindableTextarea.d.ts +1 -1
  79. package/dist/components/bindable/BindableTextarea.d.ts.map +1 -1
  80. package/dist/components/library/RichTextEditor/RichTextEditor.d.ts +1 -1
  81. package/dist/components/library/RichTextEditor/RichTextEditor.d.ts.map +1 -1
  82. package/dist/components/library/RichTextEditor/contentTree.d.ts.map +1 -1
  83. package/dist/components/library/RichTextEditor/contentTree.js +2 -1
  84. package/dist/components/library/__StatefulMessage/StatefulMessage.d.ts +1 -1
  85. package/dist/components/library/__StatefulMessage/StatefulMessage.d.ts.map +1 -1
  86. package/dist/defaultConfig.d.ts.map +1 -1
  87. package/dist/defaultConfig.js +0 -1
  88. package/dist/devBanner.d.ts +4 -0
  89. package/dist/devBanner.d.ts.map +1 -0
  90. package/dist/devBanner.js +50 -0
  91. package/dist/docInit.d.ts +16 -0
  92. package/dist/docInit.d.ts.map +1 -0
  93. package/dist/docInit.js +54 -0
  94. package/dist/env/getEnvSchemas.d.ts +1 -1
  95. package/dist/env/getEnvSchemas.d.ts.map +1 -1
  96. package/dist/env/getEnvSchemas.js +21 -22
  97. package/dist/env/registerEnvSchemas.d.ts +13 -0
  98. package/dist/env/registerEnvSchemas.d.ts.map +1 -0
  99. package/dist/env/registerEnvSchemas.js +23 -0
  100. package/dist/frameworkConfigSchema.d.ts +0 -2
  101. package/dist/frameworkConfigSchema.d.ts.map +1 -1
  102. package/dist/frameworkConfigSchema.js +0 -1
  103. package/dist/hydrate/hydrate.d.ts.map +1 -1
  104. package/dist/hydrate/hydrate.js +11 -2
  105. package/dist/hydrate/renderHydrationMismatchBanner.d.ts +1 -0
  106. package/dist/hydrate/renderHydrationMismatchBanner.d.ts.map +1 -1
  107. package/dist/hydrate/renderHydrationMismatchBanner.js +11 -63
  108. package/dist/indexInner.d.ts +5 -1
  109. package/dist/indexInner.d.ts.map +1 -1
  110. package/dist/indexInner.js +5 -1
  111. package/dist/jsxRuntime.d.ts +1 -1
  112. package/dist/jsxRuntime.d.ts.map +1 -1
  113. package/dist/jsxRuntime.js +9 -7
  114. package/dist/jsxRuntimeSignals.d.ts +8 -4
  115. package/dist/jsxRuntimeSignals.d.ts.map +1 -1
  116. package/dist/jsxRuntimeSignals.js +8 -6
  117. package/dist/nbsp.d.ts +2 -2
  118. package/dist/nbsp.d.ts.map +1 -1
  119. package/dist/rawHtml/filterContentNode.d.ts.map +1 -1
  120. package/dist/rawHtml/filterContentNode.js +3 -1
  121. package/dist/render/HeadData.d.ts +1 -0
  122. package/dist/render/HeadData.d.ts.map +1 -1
  123. package/dist/render/contentNodeToHtml.d.ts.map +1 -1
  124. package/dist/render/contentNodeToHtml.js +2 -1
  125. package/dist/render/contentToHtml.d.ts.map +1 -1
  126. package/dist/render/contentToHtml.js +3 -1
  127. package/dist/render/contentTreeToRenderingTree.d.ts.map +1 -1
  128. package/dist/render/contentTreeToRenderingTree.js +5 -1
  129. package/dist/render/processHead.d.ts.map +1 -1
  130. package/dist/render/processHead.js +10 -0
  131. package/dist/render/readDocInitScript.d.ts +3 -0
  132. package/dist/render/readDocInitScript.d.ts.map +1 -0
  133. package/dist/render/readDocInitScript.js +15 -0
  134. package/dist/render/rootToHtmlDev.d.ts.map +1 -1
  135. package/dist/routing/Group.d.ts +1 -1
  136. package/dist/routing/Group.d.ts.map +1 -1
  137. package/dist/routing/MatchedRoute.d.ts +1 -1
  138. package/dist/routing/MatchedRoute.d.ts.map +1 -1
  139. package/dist/settings.d.ts +3 -0
  140. package/dist/settings.d.ts.map +1 -1
  141. package/dist/settings.js +4 -0
  142. package/dist/style/styleContentSxy.d.ts.map +1 -1
  143. package/dist/style/styleContentSxy.js +6 -1
  144. package/dist/testing/installTestDocInit.d.ts +2 -0
  145. package/dist/testing/installTestDocInit.d.ts.map +1 -0
  146. package/dist/testing/installTestDocInit.js +6 -0
  147. package/dist/throwError.d.ts.map +1 -1
  148. package/dist/throwError.js +4 -1
  149. package/dist/update/integrateUpdateVdom.d.ts.map +1 -1
  150. package/dist/update/integrateUpdateVdom.js +39 -3
  151. package/package.json +2 -1
  152. package/readme.md +2 -135
  153. package/types/assets.d.ts +21 -0
  154. package/types/index.d.ts +24 -29
  155. package/types/jsx/html.d.ts +0 -1
  156. package/types/jsx/html.global.d.ts +0 -1
  157. package/types/jsx/html.values.d.ts +0 -1
  158. package/types/jsx/jsx.d.ts +8 -8
  159. package/vendor/manifest.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"styleContentSxy.d.ts","sourceRoot":"","sources":["../../src/style/styleContentSxy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EACH,KAAK,WAAW,EACnB,MAAM,mBAAmB,CAAA;AAc1B,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,eAIrE"}
1
+ {"version":3,"file":"styleContentSxy.d.ts","sourceRoot":"","sources":["../../src/style/styleContentSxy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EACH,KAAK,WAAW,EAEnB,MAAM,mBAAmB,CAAA;AAc1B,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,eAIrE"}
@@ -1,5 +1,5 @@
1
1
  import { count } from 'sxy-lib/objects.js';
2
- import { ContentNodeElementIsHtml, ContentNodeElementIsComponent } from '../ContentNode.js';
2
+ import { ContentNodeElementIsHtml, ContentNodeElementIsComponent, ContentNodeIsFragment } from '../ContentNode.js';
3
3
  import { warn } from '../output.js';
4
4
  import { TungstenError } from '../TungstenError.js';
5
5
  import { componentBumpClass } from '../componentClassName.js';
@@ -44,6 +44,11 @@ function processItem(element, styles, usage) {
44
44
  }
45
45
  return;
46
46
  }
47
+ // a fragment gets no class of its own; its children are styled as if they sat in its place
48
+ if (ContentNodeIsFragment(element)) {
49
+ processItem(element[$props].children, styles, usage);
50
+ return;
51
+ }
47
52
  debug('Element must be an element. Type: ', typeof element);
48
53
  // element is a ContentNodeElement
49
54
  let tagName;
@@ -0,0 +1,2 @@
1
+ export declare function installTestDocInit(): void;
2
+ //# sourceMappingURL=installTestDocInit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installTestDocInit.d.ts","sourceRoot":"","sources":["../../src/testing/installTestDocInit.ts"],"names":[],"mappings":"AAGA,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC"}
@@ -0,0 +1,6 @@
1
+ // DocInit is compiled away by BabelTransformDocInit in an app build. Tests run tsc output, where
2
+ // the global is the throwing stand-in docInit.ts installs. This makes the same split the compiled
3
+ // form does: run the function where a document exists, else hand back the server value.
4
+ export function installTestDocInit() {
5
+ globalThis.DocInit = (fn, serverValue) => typeof document !== 'undefined' ? fn() : serverValue; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion -- the void overload has no server value
6
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"throwError.d.ts","sourceRoot":"","sources":["../src/throwError.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAEnE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAErE"}
1
+ {"version":3,"file":"throwError.d.ts","sourceRoot":"","sources":["../src/throwError.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAKnE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAErE"}
@@ -1,7 +1,10 @@
1
1
  import { TungstenError } from './TungstenError.js';
2
2
  import { packageNameCapitalized } from './settings.js';
3
3
  export function throwError(location, message) {
4
- throw new TungstenError(errorMessage(location, message));
4
+ const error = new TungstenError(errorMessage(location, message));
5
+ // V8 only (Chrome, Node): start the stack at the caller, not here. Elsewhere the frame stays.
6
+ Error.captureStackTrace?.(error, throwError); // eslint-disable-line @typescript-eslint/no-unnecessary-condition -- absent outside V8
7
+ throw error;
5
8
  }
6
9
  export function errorMessage(location, message) {
7
10
  return `${packageNameCapitalized} ${location} error: ${message}`;
@@ -1 +1 @@
1
- {"version":3,"file":"integrateUpdateVdom.d.ts","sourceRoot":"","sources":["../../src/update/integrateUpdateVdom.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"integrateUpdateVdom.d.ts","sourceRoot":"","sources":["../../src/update/integrateUpdateVdom.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { IsHTMLElement } from '../DomNodes.js';
2
2
  import { DomRegion } from '../DomRegion.js';
3
3
  import { DomPointer } from '../DomPointer.js';
4
- import { ContentNodeComponentIsClassComponent, ContentNodeIsNonRendered, ContentNodeIsLiteral, ContentNodeIsHtml, ContentNodeIsComponent, ContentNodeIsArray, ContentNodeIsElement, ContentNodeElementHasValidKey } from '../ContentNode.js';
4
+ import { ContentNodeComponentIsClassComponent, ContentNodeIsNonRendered, ContentNodeIsLiteral, ContentNodeIsHtml, ContentNodeIsComponent, ContentNodeIsArray, ContentNodeIsFragment, ContentNodeIsElement, ContentNodeElementHasValidKey } from '../ContentNode.js';
5
5
  import { StringIsHtmlEvent, htmlEvents } from '../htmlEvents.js';
6
6
  import { out, warn } from '../appOutput.js';
7
7
  import { getStyledContentFromFunctionComponent } from '../getStyledContentFromFunctionComponent.js';
@@ -207,6 +207,17 @@ export async function applyUpdate({
207
207
  debug('DD delete node because current node is non rendered');
208
208
  deleteNodeIfRendered(oldNode);
209
209
  return makeRenderedContentNodeNonRendered();
210
+ } else if (ContentNodeIsFragment(newNode)) {
211
+ // a fragment is its children to the reconciler; the rendered side never holds one
212
+ return applyUpdate({
213
+ tungstenElement,
214
+ instance,
215
+ newNode: newNode[$props].children,
216
+ oldNode,
217
+ domRegion,
218
+ domPointer,
219
+ parentNode
220
+ });
210
221
  } else if (ContentNodeIsArray(newNode)) {
211
222
  //newNode
212
223
  debug('*** Content node is array');
@@ -417,7 +428,8 @@ export async function applyUpdate({
417
428
  if (WideRenderedContentNodeIsHtml(oldNode)) {
418
429
  debug('node types', newNode[$type].toLocaleLowerCase(), oldNode[$type].toLocaleLowerCase(), newNode[$type].toLocaleLowerCase() === oldNode[$type].toLocaleLowerCase());
419
430
  }
420
- if (WideRenderedContentNodeIsHtml(oldNode) && newNode[$type].toLocaleLowerCase() === oldNode[$type].toLocaleLowerCase()) {
431
+ if (WideRenderedContentNodeIsHtml(oldNode) && newNode[$type].toLocaleLowerCase() === oldNode[$type].toLocaleLowerCase() && oldNode[$key] === newNode[$key] // a changed, gained or lost key is a new element
432
+ ) {
421
433
  return updateHtmlElement(tungstenElement, instance, newNode, oldNode, domPointer);
422
434
  } else {
423
435
  //console.log('deleting node and creating html', newNode[$type], oldNode)
@@ -429,7 +441,12 @@ export async function applyUpdate({
429
441
  }
430
442
  } else if (ContentNodeIsComponent(newNode)) {
431
443
  //console.log('Comp A', WideRenderedContentNodeIsComponent(oldNode))
432
- if (WideRenderedContentNodeIsComponent(oldNode) && newNode[$type] === oldNode[$type] && (oldNode[$key] !== undefined && newNode[$key] !== undefined || oldNode[$key] === newNode[$key])) {
444
+ if (WideRenderedContentNodeIsComponent(oldNode) && newNode[$type] === oldNode[$type] &&
445
+ // this code survived for years without issue
446
+ // but probably the simple equality check below is right
447
+ // (oldNode[$key] !== undefined && newNode[$key] !== undefined)
448
+ // || oldNode[$key] === newNode[$key]
449
+ oldNode[$key] === newNode[$key]) {
433
450
  //console.log('updating tu el', newNode, oldNode[$key], newNode[$key])
434
451
  // update
435
452
  return updateComponent({
@@ -639,6 +656,14 @@ async function createNode({
639
656
  if (ContentNodeIsNonRendered(newNode)) {
640
657
  debug('node is NonRendered');
641
658
  return makeRenderedContentNodeNonRendered();
659
+ } else if (ContentNodeIsFragment(newNode)) {
660
+ return createNode({
661
+ tungstenElement,
662
+ instance,
663
+ newNode: newNode[$props].children,
664
+ domPointer,
665
+ parentNode
666
+ });
642
667
  } else if (ContentNodeIsArray(newNode)) {
643
668
  debug('node is array');
644
669
  const renderedNodes = [];
@@ -1293,6 +1318,17 @@ async function updateClassComponent({
1293
1318
  // not fire: the component did not update.
1294
1319
  //console.log('old props', element.props)
1295
1320
  //console.log('new props', newNode[$props])
1321
+ // an opaque class (static __opaque) renders once and then owns its dom: its parent never
1322
+ // re-renders it, and its region is measured live because hand-added nodes change its length
1323
+ if (element.constructor.__opaque === true) {
1324
+ // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion -- the static declared on TungstenBaseComponent
1325
+ markRendered(element);
1326
+ const length = element.__domRegion?.length();
1327
+ if (length !== undefined) {
1328
+ domPointer.increment(length);
1329
+ return oldNode;
1330
+ }
1331
+ }
1296
1332
  if (propsAreEqual(element.props, newNode[$props], renderedAt(element))) {
1297
1333
  if (tracing()) trace('SKIP', element.constructor.name, '(props unchanged since tick', renderedAt(element), ')');
1298
1334
  // the dom is current for these props, so the baseline moves with it -- otherwise a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tungsten",
3
- "version": "0.4.14",
3
+ "version": "0.5.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -38,6 +38,7 @@
38
38
  "@babel/preset-react": "^7.28.5",
39
39
  "@babel/preset-typescript": "^7.29.7",
40
40
  "@babel/types": "^7.29.0",
41
+ "@jridgewell/trace-mapping": "^0.3.31",
41
42
  "@rollup/plugin-babel": "^6.1.0",
42
43
  "@rollup/plugin-commonjs": "^28.0.9",
43
44
  "@rollup/plugin-json": "^6.1.0",
package/readme.md CHANGED
@@ -2,139 +2,6 @@
2
2
 
3
3
  [Docs](https://robertsandiford.co.uk/tungsten)
4
4
 
5
- ## Component testing
5
+ ## Agents
6
6
 
7
- Test-specific APIs are available from `tungsten/testing` and are not exported
8
- from Tungsten's main entry point. A test project supplies its own DOM
9
- implementation, such as happy-dom or jsdom:
10
-
11
- ```tsx
12
- import { Window } from 'happy-dom'
13
- import { createTestApp } from 'tungsten/testing'
14
-
15
- describe('RootComponent', () => {
16
- it('responds to a button click', async () => {
17
- const window = new Window()
18
- const testApp = await createTestApp(RootComponent, {
19
- document: window.document as unknown as Document,
20
- props: { initialName: 'Robert' },
21
- location: '/',
22
- })
23
-
24
- try {
25
- const button = testApp.container.querySelector('button')
26
- expect(button).not.toBeNull()
27
-
28
- button!.dispatchEvent(new window.Event('click') as unknown as Event)
29
- await testApp.resolved()
30
-
31
- expect(testApp.container.textContent).toContain('Robert')
32
- } finally {
33
- await testApp.unmount()
34
- }
35
- })
36
- })
37
- ```
38
-
39
- The casts are only needed when a DOM package publishes types which are not
40
- structurally compatible with the TypeScript DOM library version used by the
41
- test project.
42
-
43
- `createTestApp()` completes the initial client render before returning.
44
- `resolved()` subsequently waits for Tungsten updates, DOM reconciliation,
45
- lifecycle-triggered updates, and promises returned by registered event
46
- handlers. It does not wait for unrelated timers, network requests, or promises
47
- which the application has not returned to Tungsten.
48
-
49
- An automatically created container is appended to the supplied document body
50
- and removed by `unmount()`. A caller-supplied container must be empty; it is
51
- emptied but retained during unmount.
52
-
53
- Registered stores are created independently for each test application. Use
54
- `testStore()` to initialize one before the root component starts:
55
-
56
- ```ts
57
- import { createTestApp, testStore } from 'tungsten/testing'
58
-
59
- const testApp = await createTestApp(RootComponent, {
60
- document,
61
- stores: [testStore(userStore, store => {
62
- store.user.set(mockUser)
63
- })],
64
- })
65
- ```
66
-
67
- Tests containing Tungsten JSX must be compiled through `tungsten compile` so
68
- they use Tungsten's JSX runtime and application transforms.
69
-
70
- ## Preparing code for tests
71
-
72
- Run a one-shot development compilation without starting a server:
73
-
74
- ```sh
75
- tungsten compile
76
- ```
77
-
78
- By default this compiles JavaScript (including JSX and Tungsten's Babel
79
- transforms), stylesheets, client support files, assets, and public files into
80
- `.tungsten/dev`.
81
- Each selected target's existing generated output is cleaned before the initial
82
- compilation, including when watch mode is used. Pass `--no-clean` to preserve
83
- existing output.
84
-
85
- Use `--output` to select an independent output root. The layout below that root
86
- is the same as `.tungsten/dev`, including `code`, `.client`, `.static`,
87
- `.assets`, `.public`, `.componentCss`, and `.packages`:
88
-
89
- ```sh
90
- tungsten compile --output .tungsten/test
91
- tungsten compile --output .tungsten/test --watch
92
- ```
93
-
94
- Cleaning and generated package-cache data are scoped to the selected output.
95
- Limit the work with one or more options:
96
-
97
- ```sh
98
- tungsten compile --js
99
- tungsten compile --css
100
- tungsten compile --client
101
- tungsten compile --assets
102
- tungsten compile --public
103
- tungsten compile --js --css
104
- ```
105
-
106
- `--all` explicitly selects all five targets.
107
-
108
- Add `--watch` to keep the JavaScript, stylesheet, asset, and/or public-file
109
- compiler running after the initial pass. Client support files are still
110
- generated once:
111
-
112
- ```sh
113
- tungsten compile --watch
114
- tungsten compile --js --watch
115
- ```
116
-
117
- For process orchestration, `--ready-file <file>` writes a small JSON file only
118
- after the initial compilation succeeds. A failed JavaScript watch cycle removes
119
- the file, and a later successful cycle recreates it. `--quiet` suppresses
120
- per-file transformation messages while retaining errors and cycle status:
121
-
122
- ```sh
123
- tungsten compile --watch --output .tungsten/test \
124
- --ready-file .tungsten/test.ready --quiet
125
- ```
126
-
127
- ## Preserving package imports in selected files
128
-
129
- Use `skipPackageCompilation` in `tungsten.config.js` for files that should be
130
- transformed and emitted without Tungsten traversing or copying their package
131
- dependencies. Bare package imports in matching files are left unchanged:
132
-
133
- ```js
134
- export default {
135
- skipPackageCompilation: '**/*.domTest.js'
136
- }
137
- ```
138
-
139
- The option accepts one glob or an array of globs. Patterns match the actual
140
- JavaScript files received by Tungsten; extensions are not translated.
7
+ If you are an agent, read [AGENTS.md](AGENTS.md)
@@ -0,0 +1,21 @@
1
+ //// Importing a stylesheet gives the url of the compiled file, inserted at build. A string so the
2
+ //// value is a valid ContentNode and can be passed as children: `<Stylesheet>{globalStyles}</Stylesheet>`
3
+ //// No import or export in this file: as a script these are ambient declarations, where in a
4
+ //// module they would be augmentations, which cannot add exports
5
+
6
+ declare module '*.css' {
7
+ const href: string
8
+ export default href
9
+ }
10
+ declare module '*.sass' {
11
+ const href: string
12
+ export default href
13
+ }
14
+ declare module '*.scss' {
15
+ const href: string
16
+ export default href
17
+ }
18
+ declare module '*.less' {
19
+ const href: string
20
+ export default href
21
+ }
package/types/index.d.ts CHANGED
@@ -1,6 +1,15 @@
1
1
 
2
2
  /* eslint-disable no-var */
3
3
 
4
+ // the stylesheet module declarations live in a script file: this one is a module, and a
5
+ // `declare module '*.css'` here would augment the app's own '*.css' declaration, which cannot add exports.
6
+ // A reference, as an import of a script file is refused
7
+ // eslint-disable-next-line @typescript-eslint/triple-slash-reference
8
+ /// <reference path="./assets.d.ts" />
9
+ // Disposable and Symbol.dispose appear in the shipped types (component using(), browser storage), and in
10
+ // TS 6 that lib comes only with ESNext - so bring it in here rather than require it of every app's lib list
11
+ /// <reference lib="esnext.disposable" />
12
+
4
13
  import { CssNames } from 'tungsten/CssNames.js'
5
14
 
6
15
  //export type { JSX } from './jsx/jsx.d.js'
@@ -12,12 +21,27 @@ declare global {
12
21
  var Scss: (style: TemplateStringsArray) => CssNames
13
22
  var ReactZoneScss: (style: TemplateStringsArray) => CssNames
14
23
  //var Less: (style: TemplateStringsArray) => CssNames
24
+
25
+ //// Rewritten at build by BabelTransformDocInit: fn is inlined into the document head and runs
26
+ //// there before <body>; the call becomes a read of its result (the server gets serverValue).
27
+ //// fn must be self-contained - only globals like document and localStorage exist in the head.
28
+ var DocInit: {
29
+ <T>(fn: () => T, serverValue: NoInfer<T>): T
30
+ (fn: () => void): void
31
+ }
15
32
  }
16
33
 
34
+ //// Apps fill these by declaration merging in their env module: `interface TungstenPrivateEnv extends PrivateEnv {}`.
35
+ //// Empty here on purpose: a base that extended the core env types would collide with an app whose schema
36
+ //// makes a core field required (TS2320). Tungsten's own reads of the core fields come from src/env/Interfaces.ts
37
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
17
38
  declare global {
39
+ interface TungstenPrivateEnv {}
40
+ interface TungstenPublicEnv {}
18
41
  var tungstenPrivateEnv: TungstenPrivateEnv
19
42
  var tungstenPublicEnv: TungstenPublicEnv
20
43
  }
44
+ /* eslint-enable @typescript-eslint/no-empty-object-type */
21
45
 
22
46
  //// In dev, cjsHelpers.ts installs a partial `process` on the browser global so that converted
23
47
  //// CommonJS packages can read process.env.NODE_ENV. It flags itself with __tungstenCjsShim so
@@ -36,33 +60,4 @@ declare global {
36
60
  // var __T_CurrentElement: TElement // eslint-disable-line no-var
37
61
  // }
38
62
 
39
- //// Allow importing css files (treated as exporting the url of the final stylesheet file
40
- //// as a string, which is actually magically inserted by compilation)
41
- //// A string is used so that the value is a valid ContentNode and can be passed as children,
42
- //// e.g. `<Stylesheet>{globalStyles}</Stylesheet>`
43
- //// For some reason these declarions are recognised, but TS complains unless the project folder
44
- //// contains an additional `declare module '*.sass'` entry
45
-
46
- // declare module '*.css'
47
- // declare module '*.sass'
48
- // declare module '*.scss'
49
- // declare module '*.less'
50
-
51
- declare module '*.css' {
52
- const href: string
53
- export default href
54
- }
55
- declare module '*.sass' {
56
- const href: string
57
- export default href
58
- }
59
- declare module '*.scss' {
60
- const href: string
61
- export default href
62
- }
63
- declare module '*.less' {
64
- const href: string
65
- export default href
66
- }
67
-
68
63
  export {}
@@ -967,7 +967,6 @@ export interface LiHTMLAttributes<T, BO extends object> extends HTMLAttributes<T
967
967
  export interface LinkHTMLAttributes<T> extends HTMLAttributes<T> {
968
968
  as?: string | undefined;
969
969
  crossOrigin?: 'anonymous' | 'use-credentials' | '' | undefined;
970
- fetchpriority?: 'high' | 'low' | 'auto';
971
970
  href?: string | undefined;
972
971
  hrefLang?: string | undefined;
973
972
  integrity?: string | undefined;
@@ -15,7 +15,6 @@ interface WheelEvent extends Event { }
15
15
  interface EventTarget { }
16
16
  interface Document { }
17
17
  interface DataTransfer { }
18
- interface StyleMedia { }
19
18
 
20
19
  interface Element { }
21
20
  interface DocumentFragment { }
@@ -7,7 +7,6 @@ export type Booleanish = boolean | 'true' | 'false'
7
7
  // ----------------------------------------------------------------------
8
8
 
9
9
  export interface AbstractView {
10
- styleMedia: StyleMedia;
11
10
  document: Document;
12
11
  }
13
12
 
@@ -1,5 +1,5 @@
1
1
 
2
- import type { ContentNode, ContentNodeComponent } from 'tungsten/ContentNode.js'
2
+ import type { ContentNode, ContentNodeElement, ContentNodeType } from 'tungsten/ContentNode.js'
3
3
  import { TungstenBaseComponent } from 'tungsten/Components.jsx'
4
4
  import type { FunctionComponent } from 'tungsten/FunctionComponent.js'
5
5
  import type { TungstenRef } from 'tungsten/createRef.js'
@@ -324,16 +324,16 @@ export interface TungstenIntrinsicElements {
324
324
  view: SVGProps<SVGViewElement>;
325
325
  }
326
326
 
327
- type IntrinsicElement = TungstenIntrinsicElements[keyof TungstenIntrinsicElements]
328
-
329
- type TungstenElementType = string | JSXElementConstructor<any>;
330
- export type TungstenElement = IntrinsicElement | ContentNodeComponent
331
- export interface TungstenElementAttributesProperty { props: {}; } // eslint-disable-line @typescript-eslint/ban-types
332
- export interface TungstenElementChildrenAttribute { children: {}; } // eslint-disable-line @typescript-eslint/ban-types
327
+ export type TungstenElement = ContentNodeElement
328
+ export interface TungstenElementAttributesProperty { props: {}; } // eslint-disable-line @typescript-eslint/no-empty-object-type
329
+ export interface TungstenElementChildrenAttribute { children: {}; } // eslint-disable-line @typescript-eslint/no-empty-object-type
333
330
 
334
331
  declare global {
335
332
  namespace JSX {
336
- export type Element = ContentNode // ContentNode allows an array. Use Core because Element is exclusive of an array of Elements
333
+ export type Element = ContentNodeElement // every JSX expression is an element node - a fragment included
334
+ // what may stand as a tag. Declared (TS 5.1+) so a component's return type is checked against
335
+ // ContentNode through its own signature, not against Element
336
+ export type ElementType = ContentNodeType
337
337
  export interface ElementAttributesProperty extends TungstenElementAttributesProperty {}
338
338
  export interface ElementChildrenAttribute extends TungstenElementChildrenAttribute {}
339
339
  export type ElementClass = TungstenBaseComponent<any, any> | FunctionComponent<any, any>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "lockfile": {
3
- "size": 246952,
4
- "mtimeMs": 1788803027627.8281
3
+ "size": 247038,
4
+ "mtimeMs": 1789221974883.9106
5
5
  },
6
6
  "specifiers": {
7
7
  "@babel/core": "babel-core",