@cratis/scene.react 4.14.0 → 4.16.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 (79) hide show
  1. package/core/ScreenplayCoreComponents.tsx +24 -3
  2. package/dist/cjs/SceneElementView.js +1 -0
  3. package/dist/cjs/SceneElementView.js.map +1 -1
  4. package/dist/cjs/core/ScreenplayCoreComponents.js +25 -5
  5. package/dist/cjs/core/ScreenplayCoreComponents.js.map +1 -1
  6. package/dist/cjs/index.js +11 -0
  7. package/dist/cjs/index.js.map +1 -1
  8. package/dist/cjs/navigation/createHashSceneHistory.js +43 -0
  9. package/dist/cjs/navigation/createHashSceneHistory.js.map +1 -0
  10. package/dist/cjs/packages/PackageHostConfiguration.js +18 -2
  11. package/dist/cjs/packages/PackageHostConfiguration.js.map +1 -1
  12. package/dist/cjs/packages/isNetworkAsset.js +18 -0
  13. package/dist/cjs/packages/isNetworkAsset.js.map +1 -0
  14. package/dist/cjs/renderer/RenderBindingScopeContext.js +15 -5
  15. package/dist/cjs/renderer/RenderBindingScopeContext.js.map +1 -1
  16. package/dist/cjs/renderer/useBoundQuery.js +50 -0
  17. package/dist/cjs/renderer/useBoundQuery.js.map +1 -0
  18. package/dist/cjs/renderer/useValueOutput.js +31 -0
  19. package/dist/cjs/renderer/useValueOutput.js.map +1 -0
  20. package/dist/cjs/renderer/valueOutputProperty.js +28 -0
  21. package/dist/cjs/renderer/valueOutputProperty.js.map +1 -0
  22. package/dist/esm/SceneElementView.js +1 -0
  23. package/dist/esm/SceneElementView.js.map +1 -1
  24. package/dist/esm/core/ScreenplayCoreComponents.d.ts.map +1 -1
  25. package/dist/esm/core/ScreenplayCoreComponents.js +25 -5
  26. package/dist/esm/core/ScreenplayCoreComponents.js.map +1 -1
  27. package/dist/esm/index.js +5 -0
  28. package/dist/esm/index.js.map +1 -1
  29. package/dist/esm/navigation/createHashSceneHistory.d.ts +4 -0
  30. package/dist/esm/navigation/createHashSceneHistory.d.ts.map +1 -0
  31. package/dist/esm/navigation/createHashSceneHistory.js +41 -0
  32. package/dist/esm/navigation/createHashSceneHistory.js.map +1 -0
  33. package/dist/esm/navigation/index.d.ts +1 -0
  34. package/dist/esm/navigation/index.d.ts.map +1 -1
  35. package/dist/esm/navigation/index.js +1 -0
  36. package/dist/esm/navigation/index.js.map +1 -1
  37. package/dist/esm/packages/PackageHostConfiguration.d.ts +2 -0
  38. package/dist/esm/packages/PackageHostConfiguration.d.ts.map +1 -1
  39. package/dist/esm/packages/PackageHostConfiguration.js +19 -3
  40. package/dist/esm/packages/PackageHostConfiguration.js.map +1 -1
  41. package/dist/esm/packages/index.d.ts +1 -0
  42. package/dist/esm/packages/index.d.ts.map +1 -1
  43. package/dist/esm/packages/index.js +1 -0
  44. package/dist/esm/packages/index.js.map +1 -1
  45. package/dist/esm/packages/isNetworkAsset.d.ts +2 -0
  46. package/dist/esm/packages/isNetworkAsset.d.ts.map +1 -0
  47. package/dist/esm/packages/isNetworkAsset.js +16 -0
  48. package/dist/esm/packages/isNetworkAsset.js.map +1 -0
  49. package/dist/esm/renderer/RenderBindingScopeContext.d.ts.map +1 -1
  50. package/dist/esm/renderer/RenderBindingScopeContext.js +17 -7
  51. package/dist/esm/renderer/RenderBindingScopeContext.js.map +1 -1
  52. package/dist/esm/renderer/index.d.ts +3 -0
  53. package/dist/esm/renderer/index.d.ts.map +1 -1
  54. package/dist/esm/renderer/index.js +3 -0
  55. package/dist/esm/renderer/index.js.map +1 -1
  56. package/dist/esm/renderer/useBoundQuery.d.ts +3 -0
  57. package/dist/esm/renderer/useBoundQuery.d.ts.map +1 -0
  58. package/dist/esm/renderer/useBoundQuery.js +48 -0
  59. package/dist/esm/renderer/useBoundQuery.js.map +1 -0
  60. package/dist/esm/renderer/useValueOutput.d.ts +4 -0
  61. package/dist/esm/renderer/useValueOutput.d.ts.map +1 -0
  62. package/dist/esm/renderer/useValueOutput.js +28 -0
  63. package/dist/esm/renderer/useValueOutput.js.map +1 -0
  64. package/dist/esm/renderer/valueOutputProperty.d.ts +3 -0
  65. package/dist/esm/renderer/valueOutputProperty.d.ts.map +1 -0
  66. package/dist/esm/renderer/valueOutputProperty.js +26 -0
  67. package/dist/esm/renderer/valueOutputProperty.js.map +1 -0
  68. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  69. package/navigation/createHashSceneHistory.ts +42 -0
  70. package/navigation/index.ts +1 -0
  71. package/package.json +5 -5
  72. package/packages/PackageHostConfiguration.ts +26 -3
  73. package/packages/index.ts +1 -0
  74. package/packages/isNetworkAsset.ts +15 -0
  75. package/renderer/RenderBindingScopeContext.tsx +12 -8
  76. package/renderer/index.ts +3 -0
  77. package/renderer/useBoundQuery.ts +50 -0
  78. package/renderer/useValueOutput.ts +28 -0
  79. package/renderer/valueOutputProperty.ts +25 -0
@@ -1,16 +1,22 @@
1
- import { jsx, Fragment } from 'react/jsx-runtime';
1
+ import { jsx } from 'react/jsx-runtime';
2
2
  import { useContext, createContext, useRef, useMemo, useCallback } from 'react';
3
- import { resolveBindingExpression } from '@cratis/scene.engine';
3
+ import { nestBindingScope, resolveBindingExpression } from '@cratis/scene.engine';
4
4
  import { BindingNullBehavior } from '@cratis/scene.model';
5
5
  import { BindingOutputProvider, useBindingOutputScope } from './BindingOutputContext.js';
6
6
 
7
7
  const Context = /*#__PURE__*/ createContext(undefined);
8
8
  /**
9
9
  * Provides the inherited reactive binding scope for a rendered Scene tree.
10
+ *
11
+ * The outermost provider owns the component output scope. A provider rendered inside another - a nested
12
+ * template or region - nests its own data context, query results and component outputs over the inherited
13
+ * scope with `nestBindingScope`, so a detail region bound to the selected row reads that row while still
14
+ * seeing the screen's queries and every component's outputs.
10
15
  */ function RenderBindingScopeProvider(props) {
11
16
  const current = useContext(Context);
12
- if (current) return /*#__PURE__*/ jsx(Fragment, {
13
- children: props.children
17
+ if (current) return /*#__PURE__*/ jsx(RenderBindingScopeInner, {
18
+ ...props,
19
+ parent: current.scope
14
20
  });
15
21
  return /*#__PURE__*/ jsx(BindingOutputProvider, {
16
22
  onOutputsChanged: props.onComponentOutputsChanged,
@@ -19,20 +25,24 @@ const Context = /*#__PURE__*/ createContext(undefined);
19
25
  })
20
26
  });
21
27
  }
22
- function RenderBindingScopeInner({ children, dataContext, queryResults, componentOutputs, resolveBinding }) {
28
+ function RenderBindingScopeInner({ children, dataContext, queryResults, componentOutputs, resolveBinding, parent }) {
23
29
  const outputs = useBindingOutputScope();
24
30
  const previousValues = useRef(new Map());
25
- const scope = useMemo(()=>({
31
+ const scope = useMemo(()=>{
32
+ const own = {
26
33
  dataContext,
27
34
  queryResults,
28
35
  componentOutputs: {
29
36
  ...componentOutputs ?? {},
30
37
  ...outputs
31
38
  }
32
- }), [
39
+ };
40
+ return parent ? nestBindingScope(parent, own) : own;
41
+ }, [
33
42
  componentOutputs,
34
43
  dataContext,
35
44
  outputs,
45
+ parent,
36
46
  queryResults
37
47
  ]);
38
48
  const resolver = useCallback((binding)=>{
@@ -1 +1 @@
1
- {"version":3,"file":"RenderBindingScopeContext.js","sources":["../../../renderer/RenderBindingScopeContext.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ReactNode, createContext, useCallback, useContext, useMemo, useRef } from 'react';\nimport { BindingResolver, BindingScope, resolveBindingExpression } from '@cratis/scene.engine';\nimport { BindingExpression, BindingNullBehavior } from '@cratis/scene.model';\nimport { BindingOutputProvider, useBindingOutputScope } from './BindingOutputContext';\n\ninterface RenderBindingScopeValue {\n resolveBinding: BindingResolver;\n scope: BindingScope;\n}\n\nconst Context = createContext<RenderBindingScopeValue | undefined>(undefined);\n\nexport interface RenderBindingScopeProviderProps {\n children: ReactNode;\n dataContext?: unknown;\n queryResults?: Record<string, unknown>;\n componentOutputs?: Record<string, Record<string, unknown>>;\n resolveBinding?: BindingResolver;\n onComponentOutputsChanged?: (outputs: Record<string, Record<string, unknown>>) => void;\n}\n\n/**\n * Provides the inherited reactive binding scope for a rendered Scene tree.\n */\nexport function RenderBindingScopeProvider(props: RenderBindingScopeProviderProps) {\n const current = useContext(Context);\n if (current) return <>{props.children}</>;\n\n return (\n <BindingOutputProvider onOutputsChanged={props.onComponentOutputsChanged}>\n <RenderBindingScopeInner {...props} />\n </BindingOutputProvider>\n );\n}\n\nfunction RenderBindingScopeInner({ children, dataContext, queryResults, componentOutputs, resolveBinding }: RenderBindingScopeProviderProps) {\n const outputs = useBindingOutputScope();\n const previousValues = useRef(new Map<string, unknown>());\n const scope = useMemo<BindingScope>(() => ({\n dataContext,\n queryResults,\n componentOutputs: { ...(componentOutputs ?? {}), ...outputs },\n }), [componentOutputs, dataContext, outputs, queryResults]);\n\n const resolver = useCallback<BindingResolver>((binding: BindingExpression) => {\n if (!binding.kind && resolveBinding) return resolveBinding(binding);\n\n const key = JSON.stringify(binding);\n const value = resolveBindingExpression(binding, scope);\n if (binding.nullBehavior === BindingNullBehavior.Preserve && value === undefined) {\n return previousValues.current.get(key);\n }\n\n if (value !== undefined) previousValues.current.set(key, value);\n return value;\n }, [resolveBinding, scope]);\n\n const value = useMemo<RenderBindingScopeValue>(() => ({ resolveBinding: resolver, scope }), [resolver, scope]);\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport function useRenderBindingResolver(): BindingResolver {\n const context = useContext(Context);\n if (!context) throw new Error('No Scene render binding scope is available.');\n return context.resolveBinding;\n}\n\nexport function useRenderBindingScope(): BindingScope {\n return useContext(Context)?.scope ?? {};\n}\n"],"names":["Context","createContext","undefined","RenderBindingScopeProvider","props","current","useContext","_jsx","_Fragment","children","BindingOutputProvider","onOutputsChanged","onComponentOutputsChanged","RenderBindingScopeInner","dataContext","queryResults","componentOutputs","resolveBinding","outputs","useBindingOutputScope","previousValues","useRef","Map","scope","useMemo","resolver","useCallback","binding","kind","key","JSON","stringify","value","resolveBindingExpression","nullBehavior","BindingNullBehavior","Preserve","get","set","Provider","useRenderBindingResolver","context","Error","useRenderBindingScope"],"mappings":";;;;;;AAaA,MAAMA,wBAAUC,aAAAA,CAAmDC,SAAAA,CAAAA;AAWnE;;IAGO,SAASC,0BAAAA,CAA2BC,KAAsC,EAAA;AAC7E,IAAA,MAAMC,UAAUC,UAAAA,CAAWN,OAAAA,CAAAA;AAC3B,IAAA,IAAIK,SAAS,qBAAOE,GAAA,CAAAC,QAAA,EAAA;AAAGJ,QAAAA,QAAAA,EAAAA,KAAAA,CAAMK;;AAE7B,IAAA,qBACIF,GAAA,CAACG,qBAAAA,EAAAA;AAAsBC,QAAAA,gBAAAA,EAAkBP,MAAMQ,yBAAyB;AACpE,QAAA,QAAA,gBAAAL,GAAA,CAACM,uBAAAA,EAAAA;AAAyB,YAAA,GAAGT;;;AAGzC;AAEA,SAASS,uBAAAA,CAAwB,EAAEJ,QAAQ,EAAEK,WAAW,EAAEC,YAAY,EAAEC,gBAAgB,EAAEC,cAAc,EAAmC,EAAA;AACvI,IAAA,MAAMC,OAAAA,GAAUC,qBAAAA,EAAAA;IAChB,MAAMC,cAAAA,GAAiBC,OAAO,IAAIC,GAAAA,EAAAA,CAAAA;IAClC,MAAMC,KAAAA,GAAQC,OAAAA,CAAsB,KAAO;AACvCV,YAAAA,WAAAA;AACAC,YAAAA,YAAAA;YACAC,gBAAAA,EAAkB;gBAAE,GAAIA,gBAAAA,IAAoB,EAAE;AAAG,gBAAA,GAAGE;AAAQ;AAChE,SAAA,CAAA,EAAI;AAACF,QAAAA,gBAAAA;AAAkBF,QAAAA,WAAAA;AAAaI,QAAAA,OAAAA;AAASH,QAAAA;AAAa,KAAA,CAAA;IAE1D,MAAMU,QAAAA,GAAWC,YAA6B,CAACC,OAAAA,GAAAA;AAC3C,QAAA,IAAI,CAACA,OAAAA,CAAQC,IAAI,IAAIX,cAAAA,EAAgB,OAAOA,cAAAA,CAAeU,OAAAA,CAAAA;QAE3D,MAAME,GAAAA,GAAMC,IAAAA,CAAKC,SAAS,CAACJ,OAAAA,CAAAA;QAC3B,MAAMK,KAAAA,GAAQC,yBAAyBN,OAAAA,EAASJ,KAAAA,CAAAA;AAChD,QAAA,IAAII,QAAQO,YAAY,KAAKC,oBAAoBC,QAAQ,IAAIJ,UAAU9B,SAAAA,EAAW;AAC9E,YAAA,OAAOkB,cAAAA,CAAef,OAAO,CAACgC,GAAG,CAACR,GAAAA,CAAAA;AACtC,QAAA;AAEA,QAAA,IAAIG,UAAU9B,SAAAA,EAAWkB,cAAAA,CAAef,OAAO,CAACiC,GAAG,CAACT,GAAAA,EAAKG,KAAAA,CAAAA;QACzD,OAAOA,KAAAA;IACX,CAAA,EAAG;AAACf,QAAAA,cAAAA;AAAgBM,QAAAA;AAAM,KAAA,CAAA;IAE1B,MAAMS,KAAAA,GAAQR,OAAAA,CAAiC,KAAO;YAAEP,cAAAA,EAAgBQ,QAAAA;AAAUF,YAAAA;AAAM,SAAA,CAAA,EAAI;AAACE,QAAAA,QAAAA;AAAUF,QAAAA;AAAM,KAAA,CAAA;IAC7G,qBAAOhB,GAAA,CAACP,QAAQuC,QAAQ,EAAA;QAACP,KAAAA,EAAOA,KAAAA;AAAQvB,QAAAA,QAAAA,EAAAA;;AAC5C;AAEO,SAAS+B,wBAAAA,GAAAA;AACZ,IAAA,MAAMC,UAAUnC,UAAAA,CAAWN,OAAAA,CAAAA;AAC3B,IAAA,IAAI,CAACyC,OAAAA,EAAS,MAAM,IAAIC,KAAAA,CAAM,6CAAA,CAAA;AAC9B,IAAA,OAAOD,QAAQxB,cAAc;AACjC;AAEO,SAAS0B,qBAAAA,GAAAA;IACZ,OAAOrC,UAAAA,CAAWN,OAAAA,CAAAA,EAAUuB,KAAAA,IAAS,EAAC;AAC1C;;"}
1
+ {"version":3,"file":"RenderBindingScopeContext.js","sources":["../../../renderer/RenderBindingScopeContext.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ReactNode, createContext, useCallback, useContext, useMemo, useRef } from 'react';\nimport { BindingResolver, BindingScope, nestBindingScope, resolveBindingExpression } from '@cratis/scene.engine';\nimport { BindingExpression, BindingNullBehavior } from '@cratis/scene.model';\nimport { BindingOutputProvider, useBindingOutputScope } from './BindingOutputContext';\n\ninterface RenderBindingScopeValue {\n resolveBinding: BindingResolver;\n scope: BindingScope;\n}\n\nconst Context = createContext<RenderBindingScopeValue | undefined>(undefined);\n\nexport interface RenderBindingScopeProviderProps {\n children: ReactNode;\n dataContext?: unknown;\n queryResults?: Record<string, unknown>;\n componentOutputs?: Record<string, Record<string, unknown>>;\n resolveBinding?: BindingResolver;\n onComponentOutputsChanged?: (outputs: Record<string, Record<string, unknown>>) => void;\n}\n\n/**\n * Provides the inherited reactive binding scope for a rendered Scene tree.\n *\n * The outermost provider owns the component output scope. A provider rendered inside another - a nested\n * template or region - nests its own data context, query results and component outputs over the inherited\n * scope with `nestBindingScope`, so a detail region bound to the selected row reads that row while still\n * seeing the screen's queries and every component's outputs.\n */\nexport function RenderBindingScopeProvider(props: RenderBindingScopeProviderProps) {\n const current = useContext(Context);\n if (current) return <RenderBindingScopeInner {...props} parent={current.scope} />;\n\n return (\n <BindingOutputProvider onOutputsChanged={props.onComponentOutputsChanged}>\n <RenderBindingScopeInner {...props} />\n </BindingOutputProvider>\n );\n}\n\nfunction RenderBindingScopeInner({ children, dataContext, queryResults, componentOutputs, resolveBinding, parent }: RenderBindingScopeProviderProps & { parent?: BindingScope }) {\n const outputs = useBindingOutputScope();\n const previousValues = useRef(new Map<string, unknown>());\n const scope = useMemo<BindingScope>(() => {\n const own = { dataContext, queryResults, componentOutputs: { ...(componentOutputs ?? {}), ...outputs } };\n return parent ? nestBindingScope(parent, own) : own;\n }, [componentOutputs, dataContext, outputs, parent, queryResults]);\n\n const resolver = useCallback<BindingResolver>((binding: BindingExpression) => {\n if (!binding.kind && resolveBinding) return resolveBinding(binding);\n\n const key = JSON.stringify(binding);\n const value = resolveBindingExpression(binding, scope);\n if (binding.nullBehavior === BindingNullBehavior.Preserve && value === undefined) {\n return previousValues.current.get(key);\n }\n\n if (value !== undefined) previousValues.current.set(key, value);\n return value;\n }, [resolveBinding, scope]);\n\n const value = useMemo<RenderBindingScopeValue>(() => ({ resolveBinding: resolver, scope }), [resolver, scope]);\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport function useRenderBindingResolver(): BindingResolver {\n const context = useContext(Context);\n if (!context) throw new Error('No Scene render binding scope is available.');\n return context.resolveBinding;\n}\n\nexport function useRenderBindingScope(): BindingScope {\n return useContext(Context)?.scope ?? {};\n}\n"],"names":["Context","createContext","undefined","RenderBindingScopeProvider","props","current","useContext","_jsx","RenderBindingScopeInner","parent","scope","BindingOutputProvider","onOutputsChanged","onComponentOutputsChanged","children","dataContext","queryResults","componentOutputs","resolveBinding","outputs","useBindingOutputScope","previousValues","useRef","Map","useMemo","own","nestBindingScope","resolver","useCallback","binding","kind","key","JSON","stringify","value","resolveBindingExpression","nullBehavior","BindingNullBehavior","Preserve","get","set","Provider","useRenderBindingResolver","context","Error","useRenderBindingScope"],"mappings":"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"}
@@ -3,6 +3,9 @@ export * from './BindingOutputContext';
3
3
  export * from './ComponentRegistry';
4
4
  export * from './RenderBindingScopeContext';
5
5
  export * from './UnresolvedComponent';
6
+ export * from './useBoundQuery';
7
+ export * from './useValueOutput';
8
+ export * from './valueOutputProperty';
6
9
  export * from './createReactRenderer';
7
10
  export * from './InteractiveComponent';
8
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../renderer/index.ts"],"names":[],"mappings":"AAGA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../renderer/index.ts"],"names":[],"mappings":"AAGA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC"}
@@ -3,6 +3,9 @@ export * from './BindingOutputContext';
3
3
  export * from './ComponentRegistry';
4
4
  export * from './RenderBindingScopeContext';
5
5
  export * from './UnresolvedComponent';
6
+ export * from './useBoundQuery';
7
+ export * from './useValueOutput';
8
+ export * from './valueOutputProperty';
6
9
  export * from './createReactRenderer';
7
10
  export * from './InteractiveComponent';
8
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../renderer/index.ts"],"names":[],"mappings":"AAGA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../renderer/index.ts"],"names":[],"mappings":"AAGA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { QueryPerformer } from './AbortableQueryRunner';
2
+ export declare function useBoundQuery(query: string, argumentsValue: unknown, perform: QueryPerformer): Record<string, unknown>;
3
+ //# sourceMappingURL=useBoundQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBoundQuery.d.ts","sourceRoot":"","sources":["../../../renderer/useBoundQuery.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAWxD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiCtH"}
@@ -0,0 +1,48 @@
1
+ import { useMemo, useState, useRef, useEffect } from 'react';
2
+ import { QueryBindingState } from '@cratis/scene.engine';
3
+
4
+ // Copyright (c) Cratis. All rights reserved.
5
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
6
+ /**
7
+ * Runs a bound query whenever its arguments change and returns the accepted query results.
8
+ *
9
+ * Each change of arguments rebinds the query: the previous run is aborted and, should its answer still
10
+ * arrive, discarded by `QueryBindingState` - a slow result for a previous selection never replaces the
11
+ * current one. Arguments of `undefined` mean the binding is cleared, as when a selection is cleared, so the
12
+ * result is removed, and so is it when the current run fails - a failed rebind must not leave the previous
13
+ * selection's data on screen. The results are keyed by `query`, ready to pass as a scope's `queryResults`.
14
+ */ function useBoundQuery(query, argumentsValue, perform) {
15
+ const state = useMemo(()=>new QueryBindingState(), []);
16
+ const [results, setResults] = useState({});
17
+ const key = argumentsValue === undefined ? undefined : JSON.stringify(argumentsValue);
18
+ const latestArguments = useRef(argumentsValue);
19
+ latestArguments.current = argumentsValue;
20
+ // The arguments are compared by value through `key`; the effect reads them from `latestArguments`.
21
+ useEffect(()=>{
22
+ const argumentsForRun = latestArguments.current;
23
+ if (argumentsForRun === undefined) {
24
+ state.clear(query);
25
+ setResults(state.queryResults);
26
+ return undefined;
27
+ }
28
+ const controller = new AbortController();
29
+ const ticket = state.begin(query);
30
+ perform(query, argumentsForRun, controller.signal).then((result)=>{
31
+ if (state.complete(ticket, result)) setResults(state.queryResults);
32
+ }, ()=>{
33
+ if (controller.signal.aborted || !state.complete(ticket, undefined)) return;
34
+ state.clear(query);
35
+ setResults(state.queryResults);
36
+ });
37
+ return ()=>controller.abort();
38
+ }, [
39
+ key,
40
+ perform,
41
+ query,
42
+ state
43
+ ]);
44
+ return results;
45
+ }
46
+
47
+ export { useBoundQuery };
48
+ //# sourceMappingURL=useBoundQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBoundQuery.js","sources":["../../../renderer/useBoundQuery.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { QueryBindingState } from '@cratis/scene.engine';\nimport { QueryPerformer } from './AbortableQueryRunner';\n\n/**\n * Runs a bound query whenever its arguments change and returns the accepted query results.\n *\n * Each change of arguments rebinds the query: the previous run is aborted and, should its answer still\n * arrive, discarded by `QueryBindingState` - a slow result for a previous selection never replaces the\n * current one. Arguments of `undefined` mean the binding is cleared, as when a selection is cleared, so the\n * result is removed, and so is it when the current run fails - a failed rebind must not leave the previous\n * selection's data on screen. The results are keyed by `query`, ready to pass as a scope's `queryResults`.\n */\nexport function useBoundQuery(query: string, argumentsValue: unknown, perform: QueryPerformer): Record<string, unknown> {\n const state = useMemo(() => new QueryBindingState(), []);\n const [results, setResults] = useState<Record<string, unknown>>({});\n const key = argumentsValue === undefined ? undefined : JSON.stringify(argumentsValue);\n const latestArguments = useRef(argumentsValue);\n latestArguments.current = argumentsValue;\n\n // The arguments are compared by value through `key`; the effect reads them from `latestArguments`.\n useEffect(() => {\n const argumentsForRun = latestArguments.current;\n if (argumentsForRun === undefined) {\n state.clear(query);\n setResults(state.queryResults);\n return undefined;\n }\n\n const controller = new AbortController();\n const ticket = state.begin(query);\n perform(query, argumentsForRun, controller.signal).then(\n result => {\n if (state.complete(ticket, result)) setResults(state.queryResults);\n },\n () => {\n if (controller.signal.aborted || !state.complete(ticket, undefined)) return;\n state.clear(query);\n setResults(state.queryResults);\n },\n );\n\n return () => controller.abort();\n }, [key, perform, query, state]);\n\n return results;\n}\n"],"names":["useBoundQuery","query","argumentsValue","perform","state","useMemo","QueryBindingState","results","setResults","useState","key","undefined","JSON","stringify","latestArguments","useRef","current","useEffect","argumentsForRun","clear","queryResults","controller","AbortController","ticket","begin","signal","then","result","complete","aborted","abort"],"mappings":";;;AAAA;AACA;AAMA;;;;;;;;AAQC,IACM,SAASA,aAAAA,CAAcC,KAAa,EAAEC,cAAuB,EAAEC,OAAuB,EAAA;AACzF,IAAA,MAAMC,KAAAA,GAAQC,OAAAA,CAAQ,IAAM,IAAIC,qBAAqB,EAAE,CAAA;AACvD,IAAA,MAAM,CAACC,OAAAA,EAASC,UAAAA,CAAW,GAAGC,SAAkC,EAAC,CAAA;AACjE,IAAA,MAAMC,MAAMR,cAAAA,KAAmBS,SAAAA,GAAYA,SAAAA,GAAYC,IAAAA,CAAKC,SAAS,CAACX,cAAAA,CAAAA;AACtE,IAAA,MAAMY,kBAAkBC,MAAAA,CAAOb,cAAAA,CAAAA;AAC/BY,IAAAA,eAAAA,CAAgBE,OAAO,GAAGd,cAAAA;;IAG1Be,SAAAA,CAAU,IAAA;QACN,MAAMC,eAAAA,GAAkBJ,gBAAgBE,OAAO;AAC/C,QAAA,IAAIE,oBAAoBP,SAAAA,EAAW;AAC/BP,YAAAA,KAAAA,CAAMe,KAAK,CAAClB,KAAAA,CAAAA;AACZO,YAAAA,UAAAA,CAAWJ,MAAMgB,YAAY,CAAA;YAC7B,OAAOT,SAAAA;AACX,QAAA;AAEA,QAAA,MAAMU,aAAa,IAAIC,eAAAA,EAAAA;QACvB,MAAMC,MAAAA,GAASnB,KAAAA,CAAMoB,KAAK,CAACvB,KAAAA,CAAAA;AAC3BE,QAAAA,OAAAA,CAAQF,OAAOiB,eAAAA,EAAiBG,UAAAA,CAAWI,MAAM,CAAA,CAAEC,IAAI,CACnDC,CAAAA,MAAAA,GAAAA;AACI,YAAA,IAAIvB,MAAMwB,QAAQ,CAACL,QAAQI,MAAAA,CAAAA,EAASnB,UAAAA,CAAWJ,MAAMgB,YAAY,CAAA;QACrE,CAAA,EACA,IAAA;YACI,IAAIC,UAAAA,CAAWI,MAAM,CAACI,OAAO,IAAI,CAACzB,KAAAA,CAAMwB,QAAQ,CAACL,MAAAA,EAAQZ,SAAAA,CAAAA,EAAY;AACrEP,YAAAA,KAAAA,CAAMe,KAAK,CAAClB,KAAAA,CAAAA;AACZO,YAAAA,UAAAA,CAAWJ,MAAMgB,YAAY,CAAA;AACjC,QAAA,CAAA,CAAA;QAGJ,OAAO,IAAMC,WAAWS,KAAK,EAAA;IACjC,CAAA,EAAG;AAACpB,QAAAA,GAAAA;AAAKP,QAAAA,OAAAA;AAASF,QAAAA,KAAAA;AAAOG,QAAAA;AAAM,KAAA,CAAA;IAE/B,OAAOG,OAAAA;AACX;;"}
@@ -0,0 +1,4 @@
1
+ import { ComponentBindingOutputs } from './BindingOutputContext';
2
+ export declare const valueOutputName = "value";
3
+ export declare function useValueOutput(bindingOutputs: ComponentBindingOutputs | undefined, value: unknown): void;
4
+ //# sourceMappingURL=useValueOutput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useValueOutput.d.ts","sourceRoot":"","sources":["../../../renderer/useValueOutput.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,eAAO,MAAM,eAAe,UAAU,CAAC;AAUvC,wBAAgB,cAAc,CAAC,cAAc,EAAE,uBAAuB,GAAG,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAUxG"}
@@ -0,0 +1,28 @@
1
+ import { useRef, useEffect } from 'react';
2
+
3
+ // Copyright (c) Cratis. All rights reserved.
4
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5
+ /** The output property an input widget publishes its current value under. */ const valueOutputName = 'value';
6
+ /**
7
+ * Publishes an input widget's current value as its `value` output: once when it mounts, with the initial
8
+ * value, and again on every change. Other elements bind to it with a `componentProperty` binding, and a
9
+ * command action maps it as `component.<id>.value`. The renderer clears the output when the widget unmounts.
10
+ *
11
+ * Values are published as JSON-compatible data so both engines read the same thing: a `Date` is published
12
+ * as its ISO 8601 string, and `undefined` as `null`.
13
+ */ function useValueOutput(bindingOutputs, value) {
14
+ const published = value instanceof Date ? value.toISOString() : value ?? null;
15
+ const key = JSON.stringify(published);
16
+ const latest = useRef(published);
17
+ latest.current = published;
18
+ // Published by value through `key`: a new array or object with the same content is not a change.
19
+ useEffect(()=>{
20
+ bindingOutputs?.setOutput(valueOutputName, latest.current);
21
+ }, [
22
+ bindingOutputs,
23
+ key
24
+ ]);
25
+ }
26
+
27
+ export { useValueOutput, valueOutputName };
28
+ //# sourceMappingURL=useValueOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useValueOutput.js","sources":["../../../renderer/useValueOutput.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useRef } from 'react';\nimport { ComponentBindingOutputs } from './BindingOutputContext';\n\n/** The output property an input widget publishes its current value under. */\nexport const valueOutputName = 'value';\n\n/**\n * Publishes an input widget's current value as its `value` output: once when it mounts, with the initial\n * value, and again on every change. Other elements bind to it with a `componentProperty` binding, and a\n * command action maps it as `component.<id>.value`. The renderer clears the output when the widget unmounts.\n *\n * Values are published as JSON-compatible data so both engines read the same thing: a `Date` is published\n * as its ISO 8601 string, and `undefined` as `null`.\n */\nexport function useValueOutput(bindingOutputs: ComponentBindingOutputs | undefined, value: unknown): void {\n const published = value instanceof Date ? value.toISOString() : value ?? null;\n const key = JSON.stringify(published);\n const latest = useRef(published);\n latest.current = published;\n\n // Published by value through `key`: a new array or object with the same content is not a change.\n useEffect(() => {\n bindingOutputs?.setOutput(valueOutputName, latest.current);\n }, [bindingOutputs, key]);\n}\n"],"names":["valueOutputName","useValueOutput","bindingOutputs","value","published","Date","toISOString","key","JSON","stringify","latest","useRef","current","useEffect","setOutput"],"mappings":";;AAAA;AACA;AAKA,8EACO,MAAMA,eAAAA,GAAkB;AAE/B;;;;;;;AAOC,IACM,SAASC,cAAAA,CAAeC,cAAmD,EAAEC,KAAc,EAAA;AAC9F,IAAA,MAAMC,YAAYD,KAAAA,YAAiBE,IAAAA,GAAOF,KAAAA,CAAMG,WAAW,KAAKH,KAAAA,IAAS,IAAA;IACzE,MAAMI,GAAAA,GAAMC,IAAAA,CAAKC,SAAS,CAACL,SAAAA,CAAAA;AAC3B,IAAA,MAAMM,SAASC,MAAAA,CAAOP,SAAAA,CAAAA;AACtBM,IAAAA,MAAAA,CAAOE,OAAO,GAAGR,SAAAA;;IAGjBS,SAAAA,CAAU,IAAA;QACNX,cAAAA,EAAgBY,SAAAA,CAAUd,eAAAA,EAAiBU,MAAAA,CAAOE,OAAO,CAAA;IAC7D,CAAA,EAAG;AAACV,QAAAA,cAAAA;AAAgBK,QAAAA;AAAI,KAAA,CAAA;AAC5B;;"}
@@ -0,0 +1,3 @@
1
+ import { PropertyDescriptor, PropertyValueType } from '@cratis/scene.model';
2
+ export declare function valueOutputProperty(valueType: PropertyValueType, description?: string): PropertyDescriptor;
3
+ //# sourceMappingURL=valueOutputProperty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valueOutputProperty.d.ts","sourceRoot":"","sources":["../../../renderer/valueOutputProperty.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAUzF,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,iBAAiB,EAAE,WAAW,SAA+D,GAAG,kBAAkB,CAWhK"}
@@ -0,0 +1,26 @@
1
+ import { BindingMode } from '@cratis/scene.model';
2
+ import { valueOutputName } from './useValueOutput.js';
3
+
4
+ // Copyright (c) Cratis. All rights reserved.
5
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
6
+ /**
7
+ * The descriptor entry an input widget declares for the value it publishes with `useValueOutput`, so a
8
+ * designer can offer it as a binding source - for a detail component, a query argument or a command input.
9
+ *
10
+ * @param valueType The type of value the widget publishes.
11
+ * @param description What the value is, when the default sentence does not say enough.
12
+ */ function valueOutputProperty(valueType, description = 'What the user has entered, published as the input changes.') {
13
+ return {
14
+ path: valueOutputName,
15
+ label: 'Value',
16
+ group: 'Outputs',
17
+ valueType,
18
+ readOnly: true,
19
+ output: true,
20
+ bindingMode: BindingMode.OneWay,
21
+ description
22
+ };
23
+ }
24
+
25
+ export { valueOutputProperty };
26
+ //# sourceMappingURL=valueOutputProperty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valueOutputProperty.js","sources":["../../../renderer/valueOutputProperty.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { BindingMode, PropertyDescriptor, PropertyValueType } from '@cratis/scene.model';\nimport { valueOutputName } from './useValueOutput';\n\n/**\n * The descriptor entry an input widget declares for the value it publishes with `useValueOutput`, so a\n * designer can offer it as a binding source - for a detail component, a query argument or a command input.\n *\n * @param valueType The type of value the widget publishes.\n * @param description What the value is, when the default sentence does not say enough.\n */\nexport function valueOutputProperty(valueType: PropertyValueType, description = 'What the user has entered, published as the input changes.'): PropertyDescriptor {\n return {\n path: valueOutputName,\n label: 'Value',\n group: 'Outputs',\n valueType,\n readOnly: true,\n output: true,\n bindingMode: BindingMode.OneWay,\n description,\n };\n}\n"],"names":["valueOutputProperty","valueType","description","path","valueOutputName","label","group","readOnly","output","bindingMode","BindingMode","OneWay"],"mappings":";;;AAAA;AACA;AAKA;;;;;;AAMC,IACM,SAASA,mBAAAA,CAAoBC,SAA4B,EAAEC,cAAc,4DAA4D,EAAA;IACxI,OAAO;QACHC,IAAAA,EAAMC,eAAAA;QACNC,KAAAA,EAAO,OAAA;QACPC,KAAAA,EAAO,SAAA;AACPL,QAAAA,SAAAA;QACAM,QAAAA,EAAU,IAAA;QACVC,MAAAA,EAAQ,IAAA;AACRC,QAAAA,WAAAA,EAAaC,YAAYC,MAAM;AAC/BT,QAAAA;AACJ,KAAA;AACJ;;"}