@drawmotive/textgraph 0.1.0-alpha.1 → 0.2.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 (78) hide show
  1. package/README.md +47 -6
  2. package/docs/api-v1.md +2 -1
  3. package/docs/react.md +52 -0
  4. package/docs/releases.md +22 -15
  5. package/generated/wasm/DrawMotive.TextGraph.Bridge.runtimeconfig.json +1 -1
  6. package/generated/wasm/DrawMotive.TextGraph.Bridge.wasm +0 -0
  7. package/generated/wasm/Graphics.Core.wasm +0 -0
  8. package/generated/wasm/Grpc.Core.Api.wasm +0 -0
  9. package/generated/wasm/HarfBuzzSharp.wasm +0 -0
  10. package/generated/wasm/Math.Core.wasm +0 -0
  11. package/generated/wasm/Microsoft.AspNetCore.Components.Web.wasm +0 -0
  12. package/generated/wasm/Microsoft.Extensions.DependencyInjection.Abstractions.wasm +0 -0
  13. package/generated/wasm/Microsoft.Extensions.DependencyInjection.wasm +0 -0
  14. package/generated/wasm/Microsoft.Extensions.Logging.Abstractions.wasm +0 -0
  15. package/generated/wasm/Microsoft.Extensions.Logging.wasm +0 -0
  16. package/generated/wasm/Microsoft.Extensions.Options.wasm +0 -0
  17. package/generated/wasm/Microsoft.Extensions.Primitives.wasm +0 -0
  18. package/generated/wasm/Polly.Core.wasm +0 -0
  19. package/generated/wasm/RBush.wasm +0 -0
  20. package/generated/wasm/SkiaSharp.HarfBuzz.wasm +0 -0
  21. package/generated/wasm/SkiaSharp.wasm +0 -0
  22. package/generated/wasm/System.Collections.Concurrent.wasm +0 -0
  23. package/generated/wasm/System.Collections.Immutable.wasm +0 -0
  24. package/generated/wasm/System.Collections.NonGeneric.wasm +0 -0
  25. package/generated/wasm/System.Collections.Specialized.wasm +0 -0
  26. package/generated/wasm/System.Collections.wasm +0 -0
  27. package/generated/wasm/System.ComponentModel.Annotations.wasm +0 -0
  28. package/generated/wasm/System.ComponentModel.Primitives.wasm +0 -0
  29. package/generated/wasm/System.ComponentModel.TypeConverter.wasm +0 -0
  30. package/generated/wasm/System.ComponentModel.wasm +0 -0
  31. package/generated/wasm/System.Console.wasm +0 -0
  32. package/generated/wasm/System.Diagnostics.StackTrace.wasm +0 -0
  33. package/generated/wasm/System.Diagnostics.Tracing.wasm +0 -0
  34. package/generated/wasm/System.IO.Compression.Brotli.wasm +0 -0
  35. package/generated/wasm/System.IO.Compression.wasm +0 -0
  36. package/generated/wasm/System.IO.Pipelines.wasm +0 -0
  37. package/generated/wasm/System.Linq.Expressions.wasm +0 -0
  38. package/generated/wasm/System.Linq.wasm +0 -0
  39. package/generated/wasm/System.Memory.wasm +0 -0
  40. package/generated/wasm/System.Net.Http.wasm +0 -0
  41. package/generated/wasm/System.Net.Primitives.wasm +0 -0
  42. package/generated/wasm/System.Numerics.Vectors.wasm +0 -0
  43. package/generated/wasm/System.ObjectModel.wasm +0 -0
  44. package/generated/wasm/System.Private.CoreLib.wasm +0 -0
  45. package/generated/wasm/System.Private.Uri.wasm +0 -0
  46. package/generated/wasm/System.Reflection.Emit.ILGeneration.wasm +0 -0
  47. package/generated/wasm/System.Reflection.Emit.wasm +0 -0
  48. package/generated/wasm/System.Reflection.Primitives.wasm +0 -0
  49. package/generated/wasm/System.Runtime.InteropServices.JavaScript.wasm +0 -0
  50. package/generated/wasm/System.Runtime.InteropServices.wasm +0 -0
  51. package/generated/wasm/System.Runtime.Intrinsics.wasm +0 -0
  52. package/generated/wasm/System.Runtime.Loader.wasm +0 -0
  53. package/generated/wasm/System.Runtime.Numerics.wasm +0 -0
  54. package/generated/wasm/System.Runtime.Serialization.Primitives.wasm +0 -0
  55. package/generated/wasm/System.Runtime.wasm +0 -0
  56. package/generated/wasm/System.Security.Cryptography.wasm +0 -0
  57. package/generated/wasm/System.Text.Encoding.Extensions.wasm +0 -0
  58. package/generated/wasm/System.Text.Encodings.Web.wasm +0 -0
  59. package/generated/wasm/System.Text.Json.wasm +0 -0
  60. package/generated/wasm/System.Text.RegularExpressions.wasm +0 -0
  61. package/generated/wasm/System.Threading.Channels.wasm +0 -0
  62. package/generated/wasm/System.Threading.Thread.wasm +0 -0
  63. package/generated/wasm/System.Threading.ThreadPool.wasm +0 -0
  64. package/generated/wasm/System.Threading.wasm +0 -0
  65. package/generated/wasm/System.wasm +0 -0
  66. package/generated/wasm/dotnet.boot.js +63 -63
  67. package/generated/wasm/dotnet.js +1 -1
  68. package/generated/wasm/dotnet.native.js +745 -22
  69. package/generated/wasm/dotnet.native.wasm +0 -0
  70. package/generated/wasm/dotnet.runtime.js +1 -1
  71. package/generated/wasm/netstandard.wasm +0 -0
  72. package/generated/wasm-manifest.js +77 -77
  73. package/generated/wasm-manifest.json +77 -77
  74. package/package.json +39 -7
  75. package/scripts/copy-assets.mjs +49 -0
  76. package/src/react/index.d.ts +19 -0
  77. package/src/react/index.js +56 -0
  78. package/src/react/runtime.js +37 -0
@@ -0,0 +1,19 @@
1
+ import type { ImgHTMLAttributes, ReactElement, ReactNode } from 'react';
2
+ import type { TextGraphInitializeOptions, TextGraphRenderPngOptions } from '../index.js';
3
+
4
+ /** Keep options stable (module constant or useMemo); replacing them replaces the runtime. */
5
+ export interface TextGraphProviderProps {
6
+ options?: TextGraphInitializeOptions;
7
+ children?: ReactNode;
8
+ }
9
+
10
+ /** The component owns its image source and cancellation; other image attributes pass through. */
11
+ export interface TextGraphProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'srcSet' | 'children' | 'loading'> {
12
+ source: string;
13
+ alt?: string;
14
+ renderOptions?: Omit<TextGraphRenderPngOptions, 'encoding' | 'signal'>;
15
+ loading?: ReactNode;
16
+ }
17
+
18
+ export declare function TextGraphProvider(props: TextGraphProviderProps): ReactElement;
19
+ export declare function TextGraph(props: TextGraphProps): ReactElement;
@@ -0,0 +1,56 @@
1
+ 'use client';
2
+
3
+ import { createContext, createElement, useContext, useEffect, useMemo, useState } from 'react';
4
+ import { createRuntimeResource } from './runtime.js';
5
+
6
+ const RuntimeContext = createContext(null);
7
+ const defaultOptions = Object.freeze({});
8
+
9
+ /** Shares a lazy browser runtime across diagrams and owns its eventual disposal. */
10
+ export function TextGraphProvider({ options = defaultOptions, children }) {
11
+ const resource = useMemo(() => createRuntimeResource(options), [options]);
12
+ useEffect(() => resource.retain(), [resource]);
13
+ return createElement(RuntimeContext.Provider, { value: resource }, children);
14
+ }
15
+
16
+ /** Renders DSL as an image; only the latest committed input may publish a result. */
17
+ export function TextGraph({ source, alt = 'TextGraph diagram', renderOptions = defaultOptions,
18
+ loading = 'Rendering diagram…', ...imageProps }) {
19
+ const shared = useContext(RuntimeContext);
20
+ const resource = useMemo(() => shared ?? createRuntimeResource(defaultOptions), [shared]);
21
+ const { scale, padding, maxWidth } = renderOptions;
22
+ const request = useMemo(() => ({ source, scale, padding, maxWidth, resource }),
23
+ [source, scale, padding, maxWidth, resource]);
24
+ const [state, setState] = useState(null);
25
+
26
+ useEffect(() => {
27
+ const release = resource.retain();
28
+ const controller = new AbortController();
29
+ void (async () => {
30
+ try {
31
+ const runtime = await resource.get();
32
+ if (controller.signal.aborted) return;
33
+ const result = await runtime.renderPng(source, { scale, padding, maxWidth, encoding: 'base64', signal: controller.signal });
34
+ if (!controller.signal.aborted) setState({ request, result });
35
+ } catch (error) {
36
+ if (!controller.signal.aborted) {
37
+ // Host loaders may reject arbitrary values, including null. Keep the
38
+ // failure branch explicit so reporting an error cannot break React render.
39
+ setState({ request, error: error instanceof Error ? error : new Error(String(error ?? 'Could not render diagram')) });
40
+ }
41
+ }
42
+ })();
43
+ return () => { controller.abort(); release(); };
44
+ }, [request]);
45
+
46
+ // State is keyed by the whole request so old images disappear immediately,
47
+ // even before passive effects clean up the previous asynchronous render.
48
+ if (state?.request !== request) return createElement('span', { role: 'status' }, loading);
49
+ if (state.error || !state.result.success) {
50
+ const message = state.error?.message ?? state.result.diagnostics.map(item => item.message).join('\n');
51
+ return createElement('span', { role: 'alert' }, message || 'Could not render diagram');
52
+ }
53
+ const result = state.result;
54
+ return createElement('img', { width: result.width, height: result.height, ...imageProps,
55
+ src: `data:image/png;base64,${result.png}`, alt });
56
+ }
@@ -0,0 +1,37 @@
1
+ import { initializeTextGraph } from '../platform/browser.js';
2
+
3
+ /** A provider owns one lazy runtime; retaining it has no I/O during React render. */
4
+ export function createRuntimeResource(options) {
5
+ let users = 0;
6
+ let pending;
7
+ return {
8
+ retain() {
9
+ users++;
10
+ let released = false;
11
+ return () => {
12
+ if (released) return;
13
+ released = true;
14
+ users--;
15
+ // StrictMode replays effects synchronously. Defer final release so that
16
+ // replay reuses the same .NET module graph instead of starting another.
17
+ queueMicrotask(() => {
18
+ if (users !== 0 || !pending) return;
19
+ const retiring = pending;
20
+ pending = undefined;
21
+ // Startup may finish after unmount. Dispose that instance as well;
22
+ // there is no mounted view to receive startup or cleanup errors.
23
+ void retiring.then(runtime => runtime.dispose()).catch(() => undefined);
24
+ });
25
+ };
26
+ },
27
+ get() {
28
+ if (!pending) {
29
+ const attempt = initializeTextGraph(options);
30
+ pending = attempt;
31
+ // A later input change may retry a failed startup.
32
+ void attempt.catch(() => { if (pending === attempt) pending = undefined; });
33
+ }
34
+ return pending;
35
+ },
36
+ };
37
+ }