@makeswift/runtime 0.29.0-canary.21 → 0.29.0-canary.23

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/cjs/api/graphql-api-client.js +1 -1
  2. package/dist/cjs/api/rest-api-client.js +1 -1
  3. package/dist/cjs/api-handler/handlers/manifest.js +1 -1
  4. package/dist/cjs/api-handler/handlers/merge-translated-data.js +2 -12
  5. package/dist/cjs/api-handler/handlers/merge-translated-data.js.map +1 -1
  6. package/dist/cjs/api-handler/handlers/revalidate.js +2 -12
  7. package/dist/cjs/api-handler/handlers/revalidate.js.map +1 -1
  8. package/dist/cjs/api-handler/handlers/table-record.js +2 -12
  9. package/dist/cjs/api-handler/handlers/table-record.js.map +1 -1
  10. package/dist/cjs/next/components/tests/controls/page-control-prop-rendering.js +3 -18
  11. package/dist/cjs/next/components/tests/controls/page-control-prop-rendering.js.map +1 -1
  12. package/dist/cjs/next/document.js +2 -1
  13. package/dist/cjs/next/document.js.map +1 -1
  14. package/dist/cjs/next/root-style-registry.js +11 -2
  15. package/dist/cjs/next/root-style-registry.js.map +1 -1
  16. package/dist/cjs/runtimes/react/css-runtime/components/styles-context-provider.js +2 -0
  17. package/dist/cjs/runtimes/react/css-runtime/components/styles-context-provider.js.map +1 -1
  18. package/dist/cjs/runtimes/react/css-runtime/constants.js +3 -0
  19. package/dist/cjs/runtimes/react/css-runtime/constants.js.map +1 -1
  20. package/dist/cjs/runtimes/react/css-runtime/hooks/use-base-styles.js +2 -2
  21. package/dist/cjs/runtimes/react/css-runtime/hooks/use-base-styles.js.map +1 -1
  22. package/dist/cjs/runtimes/react/css-runtime/hooks/use-controlled-styles.js +4 -3
  23. package/dist/cjs/runtimes/react/css-runtime/hooks/use-controlled-styles.js.map +1 -1
  24. package/dist/cjs/runtimes/react/css-runtime/hooks/use-css-reset.js +4 -7
  25. package/dist/cjs/runtimes/react/css-runtime/hooks/use-css-reset.js.map +1 -1
  26. package/dist/cjs/runtimes/react/css-runtime/hooks/use-legacy-controlled-style.js +2 -2
  27. package/dist/cjs/runtimes/react/css-runtime/hooks/use-legacy-controlled-style.js.map +1 -1
  28. package/dist/cjs/runtimes/react/css-runtime/hooks/use-style.js +4 -3
  29. package/dist/cjs/runtimes/react/css-runtime/hooks/use-style.js.map +1 -1
  30. package/dist/cjs/runtimes/react/css-runtime/serialize-css.js +24 -7
  31. package/dist/cjs/runtimes/react/css-runtime/serialize-css.js.map +1 -1
  32. package/dist/cjs/runtimes/react/css-runtime/stylesheet-engine.js +9 -3
  33. package/dist/cjs/runtimes/react/css-runtime/stylesheet-engine.js.map +1 -1
  34. package/dist/cjs/runtimes/react/hooks/use-async-effect.js +4 -3
  35. package/dist/cjs/runtimes/react/hooks/use-async-effect.js.map +1 -1
  36. package/dist/cjs/runtimes/react/hooks/use-server-element-refresh.js +10 -20
  37. package/dist/cjs/runtimes/react/hooks/use-server-element-refresh.js.map +1 -1
  38. package/dist/cjs/runtimes/react/root-style-registry.js +5 -1
  39. package/dist/cjs/runtimes/react/root-style-registry.js.map +1 -1
  40. package/dist/cjs/runtimes/react/server/components/editable-server-element.js +18 -14
  41. package/dist/cjs/runtimes/react/server/components/editable-server-element.js.map +1 -1
  42. package/dist/cjs/runtimes/react/server/components/element-data.js +1 -0
  43. package/dist/cjs/runtimes/react/server/components/element-data.js.map +1 -1
  44. package/dist/cjs/runtimes/react/server/components/server-elements-cache.js +75 -25
  45. package/dist/cjs/runtimes/react/server/components/server-elements-cache.js.map +1 -1
  46. package/dist/cjs/state/actions/internal/read-write-action-types.js +1 -1
  47. package/dist/cjs/state/actions/internal/read-write-action-types.js.map +1 -1
  48. package/dist/cjs/state/actions/internal/read-write-actions.js +4 -4
  49. package/dist/cjs/state/actions/internal/read-write-actions.js.map +1 -1
  50. package/dist/cjs/state/modules/read-write/resolved-value-overrides.js +32 -14
  51. package/dist/cjs/state/modules/read-write/resolved-value-overrides.js.map +1 -1
  52. package/dist/cjs/state/read-write-state.js +5 -0
  53. package/dist/cjs/state/read-write-state.js.map +1 -1
  54. package/dist/cjs/testing/window.js +50 -0
  55. package/dist/cjs/testing/window.js.map +1 -0
  56. package/dist/cjs/utils/{isErrorWithMessage.js → error-message.js} +12 -5
  57. package/dist/cjs/utils/error-message.js.map +1 -0
  58. package/dist/esm/api/graphql-api-client.js +1 -1
  59. package/dist/esm/api/rest-api-client.js +1 -1
  60. package/dist/esm/api-handler/handlers/manifest.js +1 -1
  61. package/dist/esm/api-handler/handlers/merge-translated-data.js +1 -1
  62. package/dist/esm/api-handler/handlers/merge-translated-data.js.map +1 -1
  63. package/dist/esm/api-handler/handlers/revalidate.js +1 -1
  64. package/dist/esm/api-handler/handlers/revalidate.js.map +1 -1
  65. package/dist/esm/api-handler/handlers/table-record.js +1 -1
  66. package/dist/esm/api-handler/handlers/table-record.js.map +1 -1
  67. package/dist/esm/next/components/tests/controls/page-control-prop-rendering.js +3 -18
  68. package/dist/esm/next/components/tests/controls/page-control-prop-rendering.js.map +1 -1
  69. package/dist/esm/next/document.js +2 -1
  70. package/dist/esm/next/document.js.map +1 -1
  71. package/dist/esm/next/root-style-registry.js +11 -2
  72. package/dist/esm/next/root-style-registry.js.map +1 -1
  73. package/dist/esm/runtimes/react/css-runtime/components/styles-context-provider.js +2 -0
  74. package/dist/esm/runtimes/react/css-runtime/components/styles-context-provider.js.map +1 -1
  75. package/dist/esm/runtimes/react/css-runtime/constants.js +2 -0
  76. package/dist/esm/runtimes/react/css-runtime/constants.js.map +1 -1
  77. package/dist/esm/runtimes/react/css-runtime/hooks/use-base-styles.js +2 -2
  78. package/dist/esm/runtimes/react/css-runtime/hooks/use-base-styles.js.map +1 -1
  79. package/dist/esm/runtimes/react/css-runtime/hooks/use-controlled-styles.js +4 -3
  80. package/dist/esm/runtimes/react/css-runtime/hooks/use-controlled-styles.js.map +1 -1
  81. package/dist/esm/runtimes/react/css-runtime/hooks/use-css-reset.js +4 -7
  82. package/dist/esm/runtimes/react/css-runtime/hooks/use-css-reset.js.map +1 -1
  83. package/dist/esm/runtimes/react/css-runtime/hooks/use-legacy-controlled-style.js +2 -2
  84. package/dist/esm/runtimes/react/css-runtime/hooks/use-legacy-controlled-style.js.map +1 -1
  85. package/dist/esm/runtimes/react/css-runtime/hooks/use-style.js +4 -3
  86. package/dist/esm/runtimes/react/css-runtime/hooks/use-style.js.map +1 -1
  87. package/dist/esm/runtimes/react/css-runtime/serialize-css.js +34 -8
  88. package/dist/esm/runtimes/react/css-runtime/serialize-css.js.map +1 -1
  89. package/dist/esm/runtimes/react/css-runtime/stylesheet-engine.js +9 -3
  90. package/dist/esm/runtimes/react/css-runtime/stylesheet-engine.js.map +1 -1
  91. package/dist/esm/runtimes/react/hooks/use-async-effect.js +4 -3
  92. package/dist/esm/runtimes/react/hooks/use-async-effect.js.map +1 -1
  93. package/dist/esm/runtimes/react/hooks/use-server-element-refresh.js +11 -21
  94. package/dist/esm/runtimes/react/hooks/use-server-element-refresh.js.map +1 -1
  95. package/dist/esm/runtimes/react/root-style-registry.js +7 -2
  96. package/dist/esm/runtimes/react/root-style-registry.js.map +1 -1
  97. package/dist/esm/runtimes/react/server/components/editable-server-element.js +19 -15
  98. package/dist/esm/runtimes/react/server/components/editable-server-element.js.map +1 -1
  99. package/dist/esm/runtimes/react/server/components/element-data.js +1 -0
  100. package/dist/esm/runtimes/react/server/components/element-data.js.map +1 -1
  101. package/dist/esm/runtimes/react/server/components/server-elements-cache.js +83 -26
  102. package/dist/esm/runtimes/react/server/components/server-elements-cache.js.map +1 -1
  103. package/dist/esm/state/actions/internal/read-write-action-types.js +1 -1
  104. package/dist/esm/state/actions/internal/read-write-action-types.js.map +1 -1
  105. package/dist/esm/state/actions/internal/read-write-actions.js +3 -3
  106. package/dist/esm/state/actions/internal/read-write-actions.js.map +1 -1
  107. package/dist/esm/state/modules/read-write/resolved-value-overrides.js +31 -14
  108. package/dist/esm/state/modules/read-write/resolved-value-overrides.js.map +1 -1
  109. package/dist/esm/state/read-write-state.js +4 -0
  110. package/dist/esm/state/read-write-state.js.map +1 -1
  111. package/dist/esm/testing/window.js +26 -0
  112. package/dist/esm/testing/window.js.map +1 -0
  113. package/dist/esm/utils/error-message.js +9 -0
  114. package/dist/esm/utils/error-message.js.map +1 -0
  115. package/dist/types/next/components/tests/controls/page-control-prop-rendering.d.ts.map +1 -1
  116. package/dist/types/next/root-style-registry.d.ts +1 -1
  117. package/dist/types/next/root-style-registry.d.ts.map +1 -1
  118. package/dist/types/runtimes/react/css-runtime/__tests__/runtime-integration/utils.d.ts +2 -1
  119. package/dist/types/runtimes/react/css-runtime/__tests__/runtime-integration/utils.d.ts.map +1 -1
  120. package/dist/types/runtimes/react/css-runtime/components/styles-context-provider.d.ts +2 -1
  121. package/dist/types/runtimes/react/css-runtime/components/styles-context-provider.d.ts.map +1 -1
  122. package/dist/types/runtimes/react/css-runtime/constants.d.ts +1 -0
  123. package/dist/types/runtimes/react/css-runtime/constants.d.ts.map +1 -1
  124. package/dist/types/runtimes/react/css-runtime/hooks/use-controlled-styles.d.ts.map +1 -1
  125. package/dist/types/runtimes/react/css-runtime/hooks/use-style.d.ts.map +1 -1
  126. package/dist/types/runtimes/react/css-runtime/serialize-css.d.ts +7 -3
  127. package/dist/types/runtimes/react/css-runtime/serialize-css.d.ts.map +1 -1
  128. package/dist/types/runtimes/react/css-runtime/stylesheet-engine.d.ts +3 -1
  129. package/dist/types/runtimes/react/css-runtime/stylesheet-engine.d.ts.map +1 -1
  130. package/dist/types/runtimes/react/hooks/use-async-effect.d.ts.map +1 -1
  131. package/dist/types/runtimes/react/hooks/use-server-element-refresh.d.ts +3 -4
  132. package/dist/types/runtimes/react/hooks/use-server-element-refresh.d.ts.map +1 -1
  133. package/dist/types/runtimes/react/root-style-registry.d.ts +12 -2
  134. package/dist/types/runtimes/react/root-style-registry.d.ts.map +1 -1
  135. package/dist/types/runtimes/react/server/components/editable-server-element.d.ts.map +1 -1
  136. package/dist/types/runtimes/react/server/components/element-data.d.ts.map +1 -1
  137. package/dist/types/runtimes/react/server/components/server-elements-cache.d.ts +2 -2
  138. package/dist/types/runtimes/react/server/components/server-elements-cache.d.ts.map +1 -1
  139. package/dist/types/state/actions/index.d.ts +1 -1
  140. package/dist/types/state/actions/internal/action-types.d.ts +1 -1
  141. package/dist/types/state/actions/internal/read-write-action-types.d.ts +1 -1
  142. package/dist/types/state/actions/internal/read-write-actions.d.ts +6 -5
  143. package/dist/types/state/actions/internal/read-write-actions.d.ts.map +1 -1
  144. package/dist/types/state/modules/read-write/resolved-value-overrides.d.ts +9 -3
  145. package/dist/types/state/modules/read-write/resolved-value-overrides.d.ts.map +1 -1
  146. package/dist/types/state/read-write-state.d.ts +1 -0
  147. package/dist/types/state/read-write-state.d.ts.map +1 -1
  148. package/dist/types/testing/window.d.ts +9 -0
  149. package/dist/types/testing/window.d.ts.map +1 -0
  150. package/dist/types/utils/__tests__/error-message.test.d.ts +2 -0
  151. package/dist/types/utils/__tests__/error-message.test.d.ts.map +1 -0
  152. package/dist/types/utils/error-message.d.ts +7 -0
  153. package/dist/types/utils/error-message.d.ts.map +1 -0
  154. package/package.json +3 -3
  155. package/dist/cjs/utils/isErrorWithMessage.js.map +0 -1
  156. package/dist/esm/utils/isErrorWithMessage.js +0 -7
  157. package/dist/esm/utils/isErrorWithMessage.js.map +0 -1
  158. package/dist/types/utils/isErrorWithMessage.d.ts +0 -6
  159. package/dist/types/utils/isErrorWithMessage.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-async-effect.ts"],"sourcesContent":["import { type DependencyList, useEffect } from 'react'\n\nexport function useAsyncEffect(effect: () => Promise<void | (() => void)>, deps: DependencyList) {\n useEffect(() => {\n let cancelled = false\n let cleanup: void | (() => void) | null = null\n\n const runAsyncEffect = async () => {\n try {\n cleanup = await effect()\n\n if (cancelled) {\n cleanup?.()\n cleanup = null\n }\n } catch (error) {\n console.error('Async effect error:', { error, deps })\n }\n }\n\n runAsyncEffect()\n\n return () => {\n cancelled = true\n try {\n cleanup?.()\n } catch (error) {\n console.error('Async effect cleanup error:', { error, deps })\n }\n }\n }, deps)\n}\n"],"mappings":"AAAA,SAA8B,iBAAiB;AAExC,SAAS,eAAe,QAA4C,MAAsB;AAC/F,YAAU,MAAM;AACd,QAAI,YAAY;AAChB,QAAI,UAAsC;AAE1C,UAAM,iBAAiB,YAAY;AACjC,UAAI;AACF,kBAAU,MAAM,OAAO;AAEvB,YAAI,WAAW;AACb,oBAAU;AACV,oBAAU;AAAA,QACZ;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,uBAAuB,EAAE,OAAO,KAAK,CAAC;AAAA,MACtD;AAAA,IACF;AAEA,mBAAe;AAEf,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI;AACF,kBAAU;AAAA,MACZ,SAAS,OAAO;AACd,gBAAQ,MAAM,+BAA+B,EAAE,OAAO,KAAK,CAAC;AAAA,MAC9D;AAAA,IACF;AAAA,EACF,GAAG,IAAI;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-async-effect.ts"],"sourcesContent":["import { type DependencyList, useEffect } from 'react'\n\nimport { errorMessage } from '../../../utils/error-message'\n\nexport function useAsyncEffect(effect: () => Promise<void | (() => void)>, deps: DependencyList) {\n useEffect(() => {\n let cancelled = false\n let cleanup: void | (() => void) | null = null\n\n const runAsyncEffect = async () => {\n try {\n cleanup = await effect()\n\n if (cancelled) {\n cleanup?.()\n cleanup = null\n }\n } catch (error) {\n console.error(`Async effect error: ${errorMessage(error)}`, { error, deps })\n }\n }\n\n void runAsyncEffect()\n\n return () => {\n cancelled = true\n try {\n cleanup?.()\n } catch (error) {\n console.error(`Async effect cleanup error: ${errorMessage(error)}`, { error, deps })\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps)\n}\n"],"mappings":"AAAA,SAA8B,iBAAiB;AAE/C,SAAS,oBAAoB;AAEtB,SAAS,eAAe,QAA4C,MAAsB;AAC/F,YAAU,MAAM;AACd,QAAI,YAAY;AAChB,QAAI,UAAsC;AAE1C,UAAM,iBAAiB,YAAY;AACjC,UAAI;AACF,kBAAU,MAAM,OAAO;AAEvB,YAAI,WAAW;AACb,oBAAU;AACV,oBAAU;AAAA,QACZ;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,uBAAuB,aAAa,KAAK,CAAC,IAAI,EAAE,OAAO,KAAK,CAAC;AAAA,MAC7E;AAAA,IACF;AAEA,SAAK,eAAe;AAEpB,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI;AACF,kBAAU;AAAA,MACZ,SAAS,OAAO;AACd,gBAAQ,MAAM,+BAA+B,aAAa,KAAK,CAAC,IAAI,EAAE,OAAO,KAAK,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,EAEF,GAAG,IAAI;AACT;","names":[]}
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useRef } from "react";
1
+ import { useCallback } from "react";
2
2
  import { useFrameworkContext } from "../components/hooks/use-framework-context";
3
3
  import { useServerElementsCache } from "../server/components/server-elements-cache";
4
4
  import { useDocumentKey, useDocumentLocale } from "./use-document-context";
@@ -6,36 +6,31 @@ import { useApiResourcesClient } from "./use-api-resources-client";
6
6
  const useServerElementRefresh = ({
7
7
  elementKey
8
8
  }) => {
9
- const requestIdRef = useRef(0);
10
- const lastAppliedRequestId = useRef(0);
11
9
  const { renderRSCElement } = useFrameworkContext();
12
- const { updateElement } = useServerElementsCache();
10
+ const { beginRefresh } = useServerElementsCache();
13
11
  const documentKey = useDocumentKey();
14
12
  const documentLocale = useDocumentLocale();
15
13
  const apiResourcesClient = useApiResourcesClient();
16
- useEffect(() => {
17
- return () => {
18
- lastAppliedRequestId.current = ++requestIdRef.current;
19
- };
20
- }, []);
21
14
  return useCallback(
22
- async (elementData) => {
15
+ async (elementData, onCommitted) => {
23
16
  if (!documentKey)
24
- return false;
17
+ return;
25
18
  if (elementData.key !== elementKey) {
26
19
  console.error(
27
20
  `Cannot refresh server element: mismatching element key '${elementData.key}' != '${elementKey}'`
28
21
  );
29
- return false;
22
+ return;
30
23
  }
31
24
  if (!renderRSCElement) {
32
25
  console.error(
33
26
  `Cannot refresh server element '${elementKey}' of type '${elementData.type}': \`renderRSCElement\` callback is null`
34
27
  );
35
- return false;
28
+ return;
36
29
  }
37
30
  try {
38
- const requestId = ++requestIdRef.current;
31
+ const commit = beginRefresh(elementKey, onCommitted);
32
+ if (commit == null)
33
+ return;
39
34
  const reactNode = await renderRSCElement({
40
35
  elementData,
41
36
  cacheData: apiResourcesClient.cacheData,
@@ -44,20 +39,15 @@ const useServerElementRefresh = ({
44
39
  locale: documentLocale ?? void 0
45
40
  }
46
41
  });
47
- if (requestId > lastAppliedRequestId.current) {
48
- updateElement(elementKey, reactNode);
49
- lastAppliedRequestId.current = requestId;
50
- return true;
51
- }
42
+ commit(reactNode);
52
43
  } catch (error) {
53
44
  console.error(
54
45
  `Failed to refresh server element '${elementKey}' of type '${elementData.type}'`,
55
46
  error
56
47
  );
57
48
  }
58
- return false;
59
49
  },
60
- [renderRSCElement, documentKey, documentLocale, elementKey, apiResourcesClient, updateElement]
50
+ [renderRSCElement, documentKey, documentLocale, elementKey, apiResourcesClient, beginRefresh]
61
51
  );
62
52
  };
63
53
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-server-element-refresh.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\n\nimport { type ElementData } from '../../../state/read-only-state'\n\nimport { useFrameworkContext } from '../components/hooks/use-framework-context'\nimport { useServerElementsCache } from '../server/components/server-elements-cache'\n\nimport { useDocumentKey, useDocumentLocale } from './use-document-context'\nimport { useApiResourcesClient } from './use-api-resources-client'\n\n/**\n * Returns a element-scoped callback that renders the provided element data on\n * the server and stores the result in the server element cache under the\n * provided element key.\n *\n * The callback returns true only if the element render succeeds and is committed\n * to the cache. Returns false when rendering is unavailable, fails, or produces a\n * stale/out-of-order result.\n */\nexport const useServerElementRefresh = ({\n elementKey,\n}: {\n elementKey: string\n}): ((elementData: ElementData) => Promise<boolean>) => {\n const requestIdRef = useRef(0)\n const lastAppliedRequestId = useRef(0)\n\n const { renderRSCElement } = useFrameworkContext()\n const { updateElement } = useServerElementsCache()\n\n const documentKey = useDocumentKey()\n const documentLocale = useDocumentLocale()\n const apiResourcesClient = useApiResourcesClient()\n\n useEffect(() => {\n // Invalidate all in-flight requests on unmount so they cannot update the cache\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n lastAppliedRequestId.current = ++requestIdRef.current\n }\n }, [])\n\n return useCallback(\n async (elementData: ElementData): Promise<boolean> => {\n if (!documentKey) return false\n if (elementData.key !== elementKey) {\n console.error(\n `Cannot refresh server element: mismatching element key '${elementData.key}' != '${elementKey}'`,\n )\n return false\n }\n\n if (!renderRSCElement) {\n console.error(\n `Cannot refresh server element '${elementKey}' of type '${elementData.type}': \\`renderRSCElement\\` callback is null`,\n )\n return false\n }\n\n try {\n // Assign each server refresh a sequential ID so we can track response\n // arrival and ignore out-of-order results\n const requestId = ++requestIdRef.current\n const reactNode = await renderRSCElement({\n elementData,\n cacheData: apiResourcesClient.cacheData,\n documentContext: {\n key: documentKey,\n locale: documentLocale ?? undefined,\n },\n })\n\n if (requestId > lastAppliedRequestId.current) {\n updateElement(elementKey, reactNode)\n lastAppliedRequestId.current = requestId\n return true\n }\n } catch (error) {\n console.error(\n `Failed to refresh server element '${elementKey}' of type '${elementData.type}'`,\n error,\n )\n }\n\n return false\n },\n [renderRSCElement, documentKey, documentLocale, elementKey, apiResourcesClient, updateElement],\n )\n}\n"],"mappings":"AAAA,SAAS,aAAa,WAAW,cAAc;AAI/C,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AAEvC,SAAS,gBAAgB,yBAAyB;AAClD,SAAS,6BAA6B;AAW/B,MAAM,0BAA0B,CAAC;AAAA,EACtC;AACF,MAEwD;AACtD,QAAM,eAAe,OAAO,CAAC;AAC7B,QAAM,uBAAuB,OAAO,CAAC;AAErC,QAAM,EAAE,iBAAiB,IAAI,oBAAoB;AACjD,QAAM,EAAE,cAAc,IAAI,uBAAuB;AAEjD,QAAM,cAAc,eAAe;AACnC,QAAM,iBAAiB,kBAAkB;AACzC,QAAM,qBAAqB,sBAAsB;AAEjD,YAAU,MAAM;AAEd,WAAO,MAAM;AAEX,2BAAqB,UAAU,EAAE,aAAa;AAAA,IAChD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL,OAAO,gBAA+C;AACpD,UAAI,CAAC;AAAa,eAAO;AACzB,UAAI,YAAY,QAAQ,YAAY;AAClC,gBAAQ;AAAA,UACN,2DAA2D,YAAY,GAAG,SAAS,UAAU;AAAA,QAC/F;AACA,eAAO;AAAA,MACT;AAEA,UAAI,CAAC,kBAAkB;AACrB,gBAAQ;AAAA,UACN,kCAAkC,UAAU,cAAc,YAAY,IAAI;AAAA,QAC5E;AACA,eAAO;AAAA,MACT;AAEA,UAAI;AAGF,cAAM,YAAY,EAAE,aAAa;AACjC,cAAM,YAAY,MAAM,iBAAiB;AAAA,UACvC;AAAA,UACA,WAAW,mBAAmB;AAAA,UAC9B,iBAAiB;AAAA,YACf,KAAK;AAAA,YACL,QAAQ,kBAAkB;AAAA,UAC5B;AAAA,QACF,CAAC;AAED,YAAI,YAAY,qBAAqB,SAAS;AAC5C,wBAAc,YAAY,SAAS;AACnC,+BAAqB,UAAU;AAC/B,iBAAO;AAAA,QACT;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ;AAAA,UACN,qCAAqC,UAAU,cAAc,YAAY,IAAI;AAAA,UAC7E;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,kBAAkB,aAAa,gBAAgB,YAAY,oBAAoB,aAAa;AAAA,EAC/F;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-server-element-refresh.tsx"],"sourcesContent":["import { useCallback } from 'react'\n\nimport { type ElementData } from '../../../state/read-only-state'\n\nimport { useFrameworkContext } from '../components/hooks/use-framework-context'\nimport { useServerElementsCache } from '../server/components/server-elements-cache'\n\nimport { useDocumentKey, useDocumentLocale } from './use-document-context'\nimport { useApiResourcesClient } from './use-api-resources-client'\n\n/**\n * Returns a element-scoped callback that renders the provided element data on\n * the server and stores the result in the server element cache under the\n * provided element key.\n *\n * Calls the `onCommitted` callback once after a successfully rendered node is\n * committed to the current React tree.\n */\nexport const useServerElementRefresh = ({\n elementKey,\n}: {\n elementKey: string\n}): ((elementData: ElementData, onCommitted?: () => void) => Promise<void>) => {\n const { renderRSCElement } = useFrameworkContext()\n const { beginRefresh } = useServerElementsCache()\n\n const documentKey = useDocumentKey()\n const documentLocale = useDocumentLocale()\n const apiResourcesClient = useApiResourcesClient()\n\n return useCallback(\n async (elementData: ElementData, onCommitted?: () => void): Promise<void> => {\n if (!documentKey) return\n if (elementData.key !== elementKey) {\n console.error(\n `Cannot refresh server element: mismatching element key '${elementData.key}' != '${elementKey}'`,\n )\n return\n }\n\n if (!renderRSCElement) {\n console.error(\n `Cannot refresh server element '${elementKey}' of type '${elementData.type}': \\`renderRSCElement\\` callback is null`,\n )\n return\n }\n\n try {\n const commit = beginRefresh(elementKey, onCommitted)\n if (commit == null) return\n\n const reactNode = await renderRSCElement({\n elementData,\n cacheData: apiResourcesClient.cacheData,\n documentContext: {\n key: documentKey,\n locale: documentLocale ?? undefined,\n },\n })\n\n commit(reactNode)\n } catch (error) {\n console.error(\n `Failed to refresh server element '${elementKey}' of type '${elementData.type}'`,\n error,\n )\n }\n },\n [renderRSCElement, documentKey, documentLocale, elementKey, apiResourcesClient, beginRefresh],\n )\n}\n"],"mappings":"AAAA,SAAS,mBAAmB;AAI5B,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AAEvC,SAAS,gBAAgB,yBAAyB;AAClD,SAAS,6BAA6B;AAU/B,MAAM,0BAA0B,CAAC;AAAA,EACtC;AACF,MAE+E;AAC7E,QAAM,EAAE,iBAAiB,IAAI,oBAAoB;AACjD,QAAM,EAAE,aAAa,IAAI,uBAAuB;AAEhD,QAAM,cAAc,eAAe;AACnC,QAAM,iBAAiB,kBAAkB;AACzC,QAAM,qBAAqB,sBAAsB;AAEjD,SAAO;AAAA,IACL,OAAO,aAA0B,gBAA4C;AAC3E,UAAI,CAAC;AAAa;AAClB,UAAI,YAAY,QAAQ,YAAY;AAClC,gBAAQ;AAAA,UACN,2DAA2D,YAAY,GAAG,SAAS,UAAU;AAAA,QAC/F;AACA;AAAA,MACF;AAEA,UAAI,CAAC,kBAAkB;AACrB,gBAAQ;AAAA,UACN,kCAAkC,UAAU,cAAc,YAAY,IAAI;AAAA,QAC5E;AACA;AAAA,MACF;AAEA,UAAI;AACF,cAAM,SAAS,aAAa,YAAY,WAAW;AACnD,YAAI,UAAU;AAAM;AAEpB,cAAM,YAAY,MAAM,iBAAiB;AAAA,UACvC;AAAA,UACA,WAAW,mBAAmB;AAAA,UAC9B,iBAAiB;AAAA,YACf,KAAK;AAAA,YACL,QAAQ,kBAAkB;AAAA,UAC5B;AAAA,QACF,CAAC;AAED,eAAO,SAAS;AAAA,MAClB,SAAS,OAAO;AACd,gBAAQ;AAAA,UACN,qCAAqC,UAAU,cAAc,YAAY,IAAI;AAAA,UAC7E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,kBAAkB,aAAa,gBAAgB,YAAY,oBAAoB,YAAY;AAAA,EAC9F;AACF;","names":[]}
@@ -6,7 +6,8 @@ import { useDynamicBrowserStyleUpdates } from "./css-runtime/hooks/use-dynamic-b
6
6
  import {
7
7
  DEFAULT_CSS_CLASS_NAME_PREFIX,
8
8
  DEFAULT_SHOULD_RENDER_STYLE_ELEMENTS,
9
- DEFAULT_CSS_RESET_ENABLED
9
+ DEFAULT_CSS_RESET_ENABLED,
10
+ DEFAULT_CSS_FORCE_IMPORTANT
10
11
  } from "./css-runtime/constants";
11
12
  import { createMakeswiftStylesRegistry } from "./css-runtime/utils";
12
13
  function RootStyleRegistry({
@@ -14,6 +15,7 @@ function RootStyleRegistry({
14
15
  stylesRegistry,
15
16
  classNamePrefix = DEFAULT_CSS_CLASS_NAME_PREFIX,
16
17
  enableCssReset = DEFAULT_CSS_RESET_ENABLED,
18
+ forceImportant = DEFAULT_CSS_FORCE_IMPORTANT,
17
19
  shouldRenderStyleElements = DEFAULT_SHOULD_RENDER_STYLE_ELEMENTS
18
20
  }) {
19
21
  useDynamicBrowserStyleUpdates(stylesRegistry);
@@ -22,6 +24,7 @@ function RootStyleRegistry({
22
24
  {
23
25
  classNamePrefix,
24
26
  enableCssReset,
27
+ forceImportant,
25
28
  stylesRegistry,
26
29
  shouldRenderStyleElements,
27
30
  children
@@ -31,7 +34,8 @@ function RootStyleRegistry({
31
34
  function DefaultRootStyleRegistry({
32
35
  children,
33
36
  classNamePrefix,
34
- enableCssReset
37
+ enableCssReset,
38
+ forceImportant
35
39
  }) {
36
40
  const [stylesRegistry] = useState(createMakeswiftStylesRegistry);
37
41
  return /* @__PURE__ */ jsx(
@@ -40,6 +44,7 @@ function DefaultRootStyleRegistry({
40
44
  stylesRegistry,
41
45
  classNamePrefix,
42
46
  enableCssReset,
47
+ forceImportant,
43
48
  children
44
49
  }
45
50
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/runtimes/react/root-style-registry.tsx"],"sourcesContent":["'use client'\n\nimport { useState, type PropsWithChildren } from 'react'\nimport { StylesContextProvider } from './css-runtime/components/styles-context-provider'\nimport { StylesRegistry } from './css-runtime/styles-registry'\nimport { useDynamicBrowserStyleUpdates } from './css-runtime/hooks/use-dynamic-browser-style-updates'\nimport {\n DEFAULT_CSS_CLASS_NAME_PREFIX,\n DEFAULT_SHOULD_RENDER_STYLE_ELEMENTS,\n DEFAULT_CSS_RESET_ENABLED,\n} from './css-runtime/constants'\nimport { createMakeswiftStylesRegistry } from './css-runtime/utils'\n\nexport type RootStyleProps = {\n /**\n * The prefix used for generated class names.\n * If not provided, a default prefix will be used.\n */\n classNamePrefix?: string\n /**\n * Toggle the built-in CSS reset.\n * Set to `false` when using `@layer`-based CSS frameworks like Tailwind.\n */\n enableCssReset?: boolean\n}\n\nexport function RootStyleRegistry({\n children,\n stylesRegistry,\n classNamePrefix = DEFAULT_CSS_CLASS_NAME_PREFIX,\n enableCssReset = DEFAULT_CSS_RESET_ENABLED,\n shouldRenderStyleElements = DEFAULT_SHOULD_RENDER_STYLE_ELEMENTS,\n}: PropsWithChildren<{\n stylesRegistry: StylesRegistry\n classNamePrefix?: string\n enableCssReset?: boolean\n shouldRenderStyleElements?: boolean\n}>) {\n useDynamicBrowserStyleUpdates(stylesRegistry)\n\n return (\n <StylesContextProvider\n classNamePrefix={classNamePrefix}\n enableCssReset={enableCssReset}\n stylesRegistry={stylesRegistry}\n shouldRenderStyleElements={shouldRenderStyleElements}\n >\n {children}\n </StylesContextProvider>\n )\n}\n\nexport function DefaultRootStyleRegistry({\n children,\n classNamePrefix,\n enableCssReset,\n}: PropsWithChildren<RootStyleProps>) {\n const [stylesRegistry] = useState(createMakeswiftStylesRegistry)\n return (\n <RootStyleRegistry\n stylesRegistry={stylesRegistry}\n classNamePrefix={classNamePrefix}\n enableCssReset={enableCssReset}\n >\n {children}\n </RootStyleRegistry>\n )\n}\n"],"mappings":";AAyCI;AAvCJ,SAAS,gBAAwC;AACjD,SAAS,6BAA6B;AAEtC,SAAS,qCAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qCAAqC;AAevC,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,4BAA4B;AAC9B,GAKI;AACF,gCAA8B,cAAc;AAE5C,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AACF,GAAsC;AACpC,QAAM,CAAC,cAAc,IAAI,SAAS,6BAA6B;AAC/D,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../src/runtimes/react/root-style-registry.tsx"],"sourcesContent":["'use client'\n\nimport { useState, type PropsWithChildren } from 'react'\nimport { StylesContextProvider } from './css-runtime/components/styles-context-provider'\nimport { StylesRegistry } from './css-runtime/styles-registry'\nimport { useDynamicBrowserStyleUpdates } from './css-runtime/hooks/use-dynamic-browser-style-updates'\nimport {\n DEFAULT_CSS_CLASS_NAME_PREFIX,\n DEFAULT_SHOULD_RENDER_STYLE_ELEMENTS,\n DEFAULT_CSS_RESET_ENABLED,\n DEFAULT_CSS_FORCE_IMPORTANT,\n} from './css-runtime/constants'\nimport { createMakeswiftStylesRegistry } from './css-runtime/utils'\n\n/**\n * Style configuration must remain unchanged while the document is mounted.\n * Changing it during development may require a full page reload.\n */\nexport type RootStyleProps = {\n /**\n * The prefix used for generated class names.\n * If not provided, a default prefix will be used.\n */\n classNamePrefix?: string\n /**\n * Toggle the built-in CSS reset.\n * Set to `false` when using `@layer`-based CSS frameworks like Tailwind.\n */\n enableCssReset?: boolean\n /**\n * Append `!important` to Makeswift-generated style rule declarations to\n * increase their priority relative to external styles.\n */\n forceImportant?: boolean\n}\n\nexport function RootStyleRegistry({\n children,\n stylesRegistry,\n classNamePrefix = DEFAULT_CSS_CLASS_NAME_PREFIX,\n enableCssReset = DEFAULT_CSS_RESET_ENABLED,\n forceImportant = DEFAULT_CSS_FORCE_IMPORTANT,\n shouldRenderStyleElements = DEFAULT_SHOULD_RENDER_STYLE_ELEMENTS,\n}: PropsWithChildren<{\n stylesRegistry: StylesRegistry\n classNamePrefix?: string\n enableCssReset?: boolean\n forceImportant?: boolean\n shouldRenderStyleElements?: boolean\n}>) {\n useDynamicBrowserStyleUpdates(stylesRegistry)\n\n return (\n <StylesContextProvider\n classNamePrefix={classNamePrefix}\n enableCssReset={enableCssReset}\n forceImportant={forceImportant}\n stylesRegistry={stylesRegistry}\n shouldRenderStyleElements={shouldRenderStyleElements}\n >\n {children}\n </StylesContextProvider>\n )\n}\n\nexport function DefaultRootStyleRegistry({\n children,\n classNamePrefix,\n enableCssReset,\n forceImportant,\n}: PropsWithChildren<RootStyleProps>) {\n const [stylesRegistry] = useState(createMakeswiftStylesRegistry)\n return (\n <RootStyleRegistry\n stylesRegistry={stylesRegistry}\n classNamePrefix={classNamePrefix}\n enableCssReset={enableCssReset}\n forceImportant={forceImportant}\n >\n {children}\n </RootStyleRegistry>\n )\n}\n"],"mappings":";AAqDI;AAnDJ,SAAS,gBAAwC;AACjD,SAAS,6BAA6B;AAEtC,SAAS,qCAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qCAAqC;AAwBvC,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,4BAA4B;AAC9B,GAMI;AACF,gCAA8B,cAAc;AAE5C,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsC;AACpC,QAAM,CAAC,cAAc,IAAI,SAAS,6BAA6B;AAC/D,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -1,9 +1,11 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, startTransition, useCallback } from "react";
4
+ import { getResolvedValueOverridesGeneration } from "../../../../state/read-write-state";
5
+ import { isReadWriteState } from "../../../../state/unified-state";
4
6
  import {
5
7
  setResolvedValueOverride,
6
- clearResolvedValueOverride
8
+ clearStaleResolvedValueOverrides
7
9
  } from "../../../../state/actions/internal/read-write-actions";
8
10
  import { useServerElementRefresh } from "../../hooks/use-server-element-refresh";
9
11
  import { useElementData } from "../../hooks/use-element-data";
@@ -11,6 +13,7 @@ import { useControlDefs } from "../../hooks/use-control-defs";
11
13
  import { useResolvedProps } from "../../hooks/use-resolved-props";
12
14
  import { useControlInstances } from "../../components/control-instances-context";
13
15
  import { useDispatch } from "../../hooks/use-dispatch";
16
+ import { useStore } from "../../hooks/use-store";
14
17
  import { useDocumentKey } from "../../hooks/use-document-context";
15
18
  import { getProp } from "../../../../utils/prop-by-path";
16
19
  import { setUnion, setDifference } from "../../../../utils/set";
@@ -32,6 +35,7 @@ const EditableServerElementWrapper = ({
32
35
  children
33
36
  }) => {
34
37
  const elementKey = initialElementData.key;
38
+ const store = useStore();
35
39
  const dispatch = useDispatch();
36
40
  const documentKey = useDocumentKey();
37
41
  const [_legacyDefs, definitions] = useControlDefs({ elementType: initialElementData.type });
@@ -50,17 +54,18 @@ const EditableServerElementWrapper = ({
50
54
  );
51
55
  const serverRefresh = useServerElementRefresh({ elementKey });
52
56
  const applyServerRefresh = useCallback(
53
- (elementData2, leafInstances, documentKey2) => startTransition(async () => {
54
- const applied = await serverRefresh(elementData2);
55
- if (!applied)
56
- return;
57
- startTransition(() => {
58
- leafInstances.forEach(
59
- (c) => dispatch(clearResolvedValueOverride({ documentKey: documentKey2, instanceKey: c.instanceKey }))
60
- );
57
+ (elementData2, documentKey2) => startTransition(async () => {
58
+ const state = store.getState();
59
+ const generation = isReadWriteState(state) ? getResolvedValueOverridesGeneration(state) : null;
60
+ await serverRefresh(elementData2, () => {
61
+ if (generation == null)
62
+ return;
63
+ startTransition(() => {
64
+ dispatch(clearStaleResolvedValueOverrides({ documentKey: documentKey2, elementKey, generation }));
65
+ });
61
66
  });
62
67
  }),
63
- [serverRefresh, dispatch]
68
+ [serverRefresh, dispatch, store, elementKey]
64
69
  );
65
70
  const applyResolvedValueOverrides = useCallback(
66
71
  (instances, props, documentKey2) => instances.forEach(
@@ -78,21 +83,21 @@ const EditableServerElementWrapper = ({
78
83
  if (documentKey == null)
79
84
  return;
80
85
  if (children == null) {
81
- const { leafInstances, leafProps } = getLeafPropsAndInstances(resolvedProps, controlInstances);
82
- applyServerRefresh(elementData, leafInstances, documentKey);
86
+ const { leafProps } = getLeafPropsAndInstances(resolvedProps, controlInstances);
87
+ applyServerRefresh(elementData, documentKey);
83
88
  prevPropsRef.current = resolvedProps;
84
89
  prevLeafPropsRef.current = leafProps;
85
90
  return;
86
91
  }
87
92
  if (resolvedProps !== prevPropsRef.current) {
88
- const { needsRefresh, leafInstances, leafProps, reactNodeInstances } = needsServerRefresh({
93
+ const { needsRefresh, leafProps, reactNodeInstances } = needsServerRefresh({
89
94
  resolvedProps,
90
95
  controlInstances,
91
96
  prevProps: prevPropsRef.current,
92
97
  prevLeafProps: prevLeafPropsRef.current
93
98
  });
94
99
  if (needsRefresh) {
95
- applyServerRefresh(elementData, leafInstances, documentKey);
100
+ applyServerRefresh(elementData, documentKey);
96
101
  } else {
97
102
  applyResolvedValueOverrides(reactNodeInstances, resolvedProps, documentKey);
98
103
  }
@@ -135,7 +140,6 @@ const needsServerRefresh = ({
135
140
  const needsRefresh = setDifference(updatedLeafProps, reactNodePropKeys).size > 0 || newlyAddedLeafProps.size > 0;
136
141
  return {
137
142
  needsRefresh,
138
- leafInstances,
139
143
  leafProps,
140
144
  reactNodeInstances
141
145
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/runtimes/react/server/components/editable-server-element.tsx"],"sourcesContent":["'use client'\n\nimport { type PropsWithChildren, useEffect, useRef, startTransition, useCallback } from 'react'\n\nimport { ControlInstance } from '@makeswift/controls'\n\nimport { type ElementData } from '../../../../state/read-only-state'\nimport {\n setResolvedValueOverride,\n clearResolvedValueOverride,\n} from '../../../../state/actions/internal/read-write-actions'\n\nimport { useServerElementRefresh } from '../../hooks/use-server-element-refresh'\nimport { useElementData } from '../../hooks/use-element-data'\nimport { useControlDefs } from '../../hooks/use-control-defs'\nimport { useResolvedProps } from '../../hooks/use-resolved-props'\nimport { useControlInstances } from '../../components/control-instances-context'\nimport { useDispatch } from '../../hooks/use-dispatch'\nimport { useDocumentKey } from '../../hooks/use-document-context'\n\nimport { getProp } from '../../../../utils/prop-by-path'\nimport { setUnion, setDifference } from '../../../../utils/set'\nimport { useControlledStyles } from '../../css-runtime/hooks/use-controlled-styles'\n\nexport const EditableServerElement = ({\n initialElementData,\n children,\n}: PropsWithChildren<{ initialElementData: ElementData }>) => {\n const elementKey = initialElementData.key\n const elementData = useElementData({ elementKey })\n if (elementData == null) {\n // Element has been deleted\n return null\n }\n\n return (\n <EditableServerElementWrapper {...{ initialElementData, elementData }}>\n {children}\n </EditableServerElementWrapper>\n )\n}\n\n/**\n * Reflects edits to `elementData.props` in the server-rendered `children`.\n * Changes limited to existing `ReactNode` props are applied through client-side\n * overrides. Style prop changes are handled by the stylesheet engine during\n * prop resolution. All other prop changes trigger a server refresh.\n */\nconst EditableServerElementWrapper = ({\n initialElementData,\n elementData,\n children,\n}: PropsWithChildren<{ initialElementData: ElementData; elementData: ElementData }>) => {\n const elementKey = initialElementData.key\n const dispatch = useDispatch()\n const documentKey = useDocumentKey()\n\n const [_legacyDefs, definitions] = useControlDefs({ elementType: initialElementData.type })\n const { getStylesheet, styleElements } = useControlledStyles({ namespace: elementKey })\n\n const controlInstances = useControlInstances(elementKey)\n const resolvedProps = useResolvedProps({\n elementKey,\n propDefs: definitions,\n propData: elementData.props,\n controlInstances,\n getStylesheet,\n })\n\n const prevPropsRef = useRef(resolvedProps)\n const prevLeafPropsRef = useRef(\n getLeafPropsAndInstances(resolvedProps, controlInstances).leafProps,\n )\n\n const serverRefresh = useServerElementRefresh({ elementKey })\n const applyServerRefresh = useCallback(\n (elementData: ElementData, leafInstances: ControlInstance[], documentKey: string) =>\n startTransition(async () => {\n const applied = await serverRefresh(elementData)\n if (!applied) return\n\n // need a nested `startTransition` here, see\n // https://react.dev/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition\n startTransition(() => {\n // reset instance overrides, if any\n leafInstances.forEach(c =>\n dispatch(clearResolvedValueOverride({ documentKey, instanceKey: c.instanceKey })),\n )\n })\n }),\n [serverRefresh, dispatch],\n )\n\n const applyResolvedValueOverrides = useCallback(\n (instances: ControlInstance[], props: Record<string, unknown>, documentKey: string) =>\n instances.forEach(c =>\n dispatch(\n setResolvedValueOverride({\n documentKey,\n instanceKey: c.instanceKey,\n value: getProp(props, c.propPath),\n }),\n ),\n ),\n [dispatch],\n )\n\n useEffect(() => {\n if (documentKey == null) return\n\n if (children == null) {\n // If we don't have a server-rendered node (i.e. user just dropped the element to the page),\n // trigger a server re-render\n const { leafInstances, leafProps } = getLeafPropsAndInstances(resolvedProps, controlInstances)\n\n applyServerRefresh(elementData, leafInstances, documentKey)\n\n prevPropsRef.current = resolvedProps\n prevLeafPropsRef.current = leafProps\n return\n }\n\n if (resolvedProps !== prevPropsRef.current) {\n // If there was a change in resolved value, check if any of the changed props necessitate\n // a server refresh.\n //\n // Note that style props have stable class names and updating a style prop will not result\n // in a change to the resolved value, which is what we want. Dynamic style updates are handled\n // through a subscription mechanism that listens for changes to controlled style data in the\n // styles registry.\n const { needsRefresh, leafInstances, leafProps, reactNodeInstances } = needsServerRefresh({\n resolvedProps,\n controlInstances,\n prevProps: prevPropsRef.current,\n prevLeafProps: prevLeafPropsRef.current,\n })\n\n if (needsRefresh) {\n applyServerRefresh(elementData, leafInstances, documentKey)\n } else {\n applyResolvedValueOverrides(reactNodeInstances, resolvedProps, documentKey)\n }\n\n prevPropsRef.current = resolvedProps\n prevLeafPropsRef.current = leafProps\n }\n }, [\n children,\n resolvedProps,\n documentKey,\n elementData,\n controlInstances,\n applyServerRefresh,\n applyResolvedValueOverrides,\n ])\n\n return (\n <>\n {children}\n {styleElements}\n </>\n )\n}\n\n/**\n * Determines whether resolved prop changes require a server refresh and returns\n * the control-instance state needed to apply the update.\n */\nconst needsServerRefresh = ({\n resolvedProps,\n controlInstances,\n prevProps,\n prevLeafProps,\n}: {\n resolvedProps: Record<string, unknown>\n controlInstances: Record<string, ControlInstance> | null\n prevProps: Record<string, unknown>\n prevLeafProps: Set<string>\n}): {\n needsRefresh: boolean\n leafInstances: ControlInstance[]\n leafProps: Set<string>\n reactNodeInstances: ControlInstance[]\n} => {\n const { leafInstances, leafProps } = getLeafPropsAndInstances(resolvedProps, controlInstances)\n\n const combinedLeafProps = setUnion(leafProps, prevLeafProps).values()\n const updatedLeafProps = new Set(\n [...combinedLeafProps].filter(\n propName => getProp(resolvedProps, propName) !== getProp(prevProps, propName),\n ),\n )\n\n const updatedLeafInstances = leafInstances.filter(instance =>\n updatedLeafProps.has(instance.propPath),\n )\n\n const reactNodeInstances = updatedLeafInstances.filter(c => c.resolvesToRenderableNode())\n\n const reactNodePropKeys = new Set(reactNodeInstances.map(c => c.propPath))\n const newlyAddedLeafProps = setDifference(leafProps, prevLeafProps)\n\n // A server refresh is needed if some of the updated props are not `ReactNode` props, or we\n // have newly observed props (typically `List` items). Even when newly observed props are\n // `ReactNode` props, we have to first render them on the server to get them in the element\n // tree before they can be updated client-side.\n const needsRefresh =\n setDifference(updatedLeafProps, reactNodePropKeys).size > 0 || newlyAddedLeafProps.size > 0\n\n return {\n needsRefresh,\n leafInstances,\n leafProps,\n reactNodeInstances,\n }\n}\n\n/**\n * Returns terminal prop paths with the corresponding control instances.\n */\nconst getLeafPropsAndInstances = (\n props: Record<string, unknown>,\n controlInstances: Record<string, ControlInstance> | null,\n): {\n leafProps: Set<string>\n leafInstances: ControlInstance[]\n} => {\n const topLevelInstances = Object.keys(props)\n .map(prop => controlInstances?.[prop])\n .filter(inst => inst != null)\n\n const leafInstances = getLeafInstances(topLevelInstances)\n const leafProps = new Set(leafInstances.map(c => c.propPath))\n return { leafProps, leafInstances }\n}\n\n/**\n * Flattens a control instance tree to its leaf (terminal) instances.\n */\nconst getLeafInstances = (instances: ControlInstance[]): ControlInstance[] =>\n instances.flatMap(instance =>\n instance.isCompositeProp() ? getLeafInstances(instance.children()) : [instance],\n )\n"],"mappings":";AAoCI,SAyHA,UAzHA,KAyHA,YAzHA;AAlCJ,SAAiC,WAAW,QAAQ,iBAAiB,mBAAmB;AAKxF;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,+BAA+B;AACxC,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC,SAAS,2BAA2B;AACpC,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAE/B,SAAS,eAAe;AACxB,SAAS,UAAU,qBAAqB;AACxC,SAAS,2BAA2B;AAE7B,MAAM,wBAAwB,CAAC;AAAA,EACpC;AAAA,EACA;AACF,MAA8D;AAC5D,QAAM,aAAa,mBAAmB;AACtC,QAAM,cAAc,eAAe,EAAE,WAAW,CAAC;AACjD,MAAI,eAAe,MAAM;AAEvB,WAAO;AAAA,EACT;AAEA,SACE,oBAAC,gCAA8B,GAAG,EAAE,oBAAoB,YAAY,GACjE,UACH;AAEJ;AAQA,MAAM,+BAA+B,CAAC;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AACF,MAAwF;AACtF,QAAM,aAAa,mBAAmB;AACtC,QAAM,WAAW,YAAY;AAC7B,QAAM,cAAc,eAAe;AAEnC,QAAM,CAAC,aAAa,WAAW,IAAI,eAAe,EAAE,aAAa,mBAAmB,KAAK,CAAC;AAC1F,QAAM,EAAE,eAAe,cAAc,IAAI,oBAAoB,EAAE,WAAW,WAAW,CAAC;AAEtF,QAAM,mBAAmB,oBAAoB,UAAU;AACvD,QAAM,gBAAgB,iBAAiB;AAAA,IACrC;AAAA,IACA,UAAU;AAAA,IACV,UAAU,YAAY;AAAA,IACtB;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,eAAe,OAAO,aAAa;AACzC,QAAM,mBAAmB;AAAA,IACvB,yBAAyB,eAAe,gBAAgB,EAAE;AAAA,EAC5D;AAEA,QAAM,gBAAgB,wBAAwB,EAAE,WAAW,CAAC;AAC5D,QAAM,qBAAqB;AAAA,IACzB,CAACA,cAA0B,eAAkCC,iBAC3D,gBAAgB,YAAY;AAC1B,YAAM,UAAU,MAAM,cAAcD,YAAW;AAC/C,UAAI,CAAC;AAAS;AAId,sBAAgB,MAAM;AAEpB,sBAAc;AAAA,UAAQ,OACpB,SAAS,2BAA2B,EAAE,aAAAC,cAAa,aAAa,EAAE,YAAY,CAAC,CAAC;AAAA,QAClF;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,IACH,CAAC,eAAe,QAAQ;AAAA,EAC1B;AAEA,QAAM,8BAA8B;AAAA,IAClC,CAAC,WAA8B,OAAgCA,iBAC7D,UAAU;AAAA,MAAQ,OAChB;AAAA,QACE,yBAAyB;AAAA,UACvB,aAAAA;AAAA,UACA,aAAa,EAAE;AAAA,UACf,OAAO,QAAQ,OAAO,EAAE,QAAQ;AAAA,QAClC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACF,CAAC,QAAQ;AAAA,EACX;AAEA,YAAU,MAAM;AACd,QAAI,eAAe;AAAM;AAEzB,QAAI,YAAY,MAAM;AAGpB,YAAM,EAAE,eAAe,UAAU,IAAI,yBAAyB,eAAe,gBAAgB;AAE7F,yBAAmB,aAAa,eAAe,WAAW;AAE1D,mBAAa,UAAU;AACvB,uBAAiB,UAAU;AAC3B;AAAA,IACF;AAEA,QAAI,kBAAkB,aAAa,SAAS;AAQ1C,YAAM,EAAE,cAAc,eAAe,WAAW,mBAAmB,IAAI,mBAAmB;AAAA,QACxF;AAAA,QACA;AAAA,QACA,WAAW,aAAa;AAAA,QACxB,eAAe,iBAAiB;AAAA,MAClC,CAAC;AAED,UAAI,cAAc;AAChB,2BAAmB,aAAa,eAAe,WAAW;AAAA,MAC5D,OAAO;AACL,oCAA4B,oBAAoB,eAAe,WAAW;AAAA,MAC5E;AAEA,mBAAa,UAAU;AACvB,uBAAiB,UAAU;AAAA,IAC7B;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE,iCACG;AAAA;AAAA,IACA;AAAA,KACH;AAEJ;AAMA,MAAM,qBAAqB,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAUK;AACH,QAAM,EAAE,eAAe,UAAU,IAAI,yBAAyB,eAAe,gBAAgB;AAE7F,QAAM,oBAAoB,SAAS,WAAW,aAAa,EAAE,OAAO;AACpE,QAAM,mBAAmB,IAAI;AAAA,IAC3B,CAAC,GAAG,iBAAiB,EAAE;AAAA,MACrB,cAAY,QAAQ,eAAe,QAAQ,MAAM,QAAQ,WAAW,QAAQ;AAAA,IAC9E;AAAA,EACF;AAEA,QAAM,uBAAuB,cAAc;AAAA,IAAO,cAChD,iBAAiB,IAAI,SAAS,QAAQ;AAAA,EACxC;AAEA,QAAM,qBAAqB,qBAAqB,OAAO,OAAK,EAAE,yBAAyB,CAAC;AAExF,QAAM,oBAAoB,IAAI,IAAI,mBAAmB,IAAI,OAAK,EAAE,QAAQ,CAAC;AACzE,QAAM,sBAAsB,cAAc,WAAW,aAAa;AAMlE,QAAM,eACJ,cAAc,kBAAkB,iBAAiB,EAAE,OAAO,KAAK,oBAAoB,OAAO;AAE5F,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKA,MAAM,2BAA2B,CAC/B,OACA,qBAIG;AACH,QAAM,oBAAoB,OAAO,KAAK,KAAK,EACxC,IAAI,UAAQ,mBAAmB,IAAI,CAAC,EACpC,OAAO,UAAQ,QAAQ,IAAI;AAE9B,QAAM,gBAAgB,iBAAiB,iBAAiB;AACxD,QAAM,YAAY,IAAI,IAAI,cAAc,IAAI,OAAK,EAAE,QAAQ,CAAC;AAC5D,SAAO,EAAE,WAAW,cAAc;AACpC;AAKA,MAAM,mBAAmB,CAAC,cACxB,UAAU;AAAA,EAAQ,cAChB,SAAS,gBAAgB,IAAI,iBAAiB,SAAS,SAAS,CAAC,IAAI,CAAC,QAAQ;AAChF;","names":["elementData","documentKey"]}
1
+ {"version":3,"sources":["../../../../../../src/runtimes/react/server/components/editable-server-element.tsx"],"sourcesContent":["'use client'\n\nimport { type PropsWithChildren, useEffect, useRef, startTransition, useCallback } from 'react'\n\nimport { ControlInstance } from '@makeswift/controls'\n\nimport { type ElementData } from '../../../../state/read-only-state'\nimport { getResolvedValueOverridesGeneration } from '../../../../state/read-write-state'\nimport { isReadWriteState } from '../../../../state/unified-state'\nimport {\n setResolvedValueOverride,\n clearStaleResolvedValueOverrides,\n} from '../../../../state/actions/internal/read-write-actions'\n\nimport { useServerElementRefresh } from '../../hooks/use-server-element-refresh'\nimport { useElementData } from '../../hooks/use-element-data'\nimport { useControlDefs } from '../../hooks/use-control-defs'\nimport { useResolvedProps } from '../../hooks/use-resolved-props'\nimport { useControlInstances } from '../../components/control-instances-context'\nimport { useDispatch } from '../../hooks/use-dispatch'\nimport { useStore } from '../../hooks/use-store'\nimport { useDocumentKey } from '../../hooks/use-document-context'\n\nimport { getProp } from '../../../../utils/prop-by-path'\nimport { setUnion, setDifference } from '../../../../utils/set'\nimport { useControlledStyles } from '../../css-runtime/hooks/use-controlled-styles'\n\nexport const EditableServerElement = ({\n initialElementData,\n children,\n}: PropsWithChildren<{ initialElementData: ElementData }>) => {\n const elementKey = initialElementData.key\n const elementData = useElementData({ elementKey })\n if (elementData == null) {\n // Element has been deleted\n return null\n }\n\n return (\n <EditableServerElementWrapper {...{ initialElementData, elementData }}>\n {children}\n </EditableServerElementWrapper>\n )\n}\n\n/**\n * Reflects edits to `elementData.props` in the server-rendered `children`.\n * Changes limited to existing `ReactNode` props are applied through client-side\n * overrides. Style prop changes are handled by the stylesheet engine during\n * prop resolution. All other prop changes trigger a server refresh.\n */\nconst EditableServerElementWrapper = ({\n initialElementData,\n elementData,\n children,\n}: PropsWithChildren<{ initialElementData: ElementData; elementData: ElementData }>) => {\n const elementKey = initialElementData.key\n const store = useStore()\n const dispatch = useDispatch()\n const documentKey = useDocumentKey()\n\n const [_legacyDefs, definitions] = useControlDefs({ elementType: initialElementData.type })\n const { getStylesheet, styleElements } = useControlledStyles({ namespace: elementKey })\n\n const controlInstances = useControlInstances(elementKey)\n const resolvedProps = useResolvedProps({\n elementKey,\n propDefs: definitions,\n propData: elementData.props,\n controlInstances,\n getStylesheet,\n })\n\n const prevPropsRef = useRef(resolvedProps)\n const prevLeafPropsRef = useRef(\n getLeafPropsAndInstances(resolvedProps, controlInstances).leafProps,\n )\n\n const serverRefresh = useServerElementRefresh({ elementKey })\n const applyServerRefresh = useCallback(\n (elementData: ElementData, documentKey: string) =>\n startTransition(async () => {\n const state = store.getState()\n // Capture the overrides generation prior to initiating server refresh so that we\n // only clear the overrides that haven't been updated while the refresh is in flight\n const generation = isReadWriteState(state)\n ? getResolvedValueOverridesGeneration(state)\n : null\n\n await serverRefresh(elementData, () => {\n if (generation == null) return\n // need a nested `startTransition` here, see\n // https://react.dev/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition\n startTransition(() => {\n dispatch(clearStaleResolvedValueOverrides({ documentKey, elementKey, generation }))\n })\n })\n }),\n [serverRefresh, dispatch, store, elementKey],\n )\n\n const applyResolvedValueOverrides = useCallback(\n (instances: ControlInstance[], props: Record<string, unknown>, documentKey: string) =>\n instances.forEach(c =>\n dispatch(\n setResolvedValueOverride({\n documentKey,\n instanceKey: c.instanceKey,\n value: getProp(props, c.propPath),\n }),\n ),\n ),\n [dispatch],\n )\n\n useEffect(() => {\n if (documentKey == null) return\n\n if (children == null) {\n // If we don't have a server-rendered node (i.e. user just dropped the element to the page),\n // trigger a server re-render\n const { leafProps } = getLeafPropsAndInstances(resolvedProps, controlInstances)\n\n applyServerRefresh(elementData, documentKey)\n\n prevPropsRef.current = resolvedProps\n prevLeafPropsRef.current = leafProps\n return\n }\n\n if (resolvedProps !== prevPropsRef.current) {\n // If there was a change in resolved value, check if any of the changed props necessitate\n // a server refresh.\n //\n // Note that style props have stable class names and updating a style prop will not result\n // in a change to the resolved value, which is what we want. Dynamic style updates are handled\n // through a subscription mechanism that listens for changes to controlled style data in the\n // styles registry.\n const { needsRefresh, leafProps, reactNodeInstances } = needsServerRefresh({\n resolvedProps,\n controlInstances,\n prevProps: prevPropsRef.current,\n prevLeafProps: prevLeafPropsRef.current,\n })\n\n if (needsRefresh) {\n applyServerRefresh(elementData, documentKey)\n } else {\n applyResolvedValueOverrides(reactNodeInstances, resolvedProps, documentKey)\n }\n\n prevPropsRef.current = resolvedProps\n prevLeafPropsRef.current = leafProps\n }\n }, [\n children,\n resolvedProps,\n documentKey,\n elementData,\n controlInstances,\n applyServerRefresh,\n applyResolvedValueOverrides,\n ])\n\n return (\n <>\n {children}\n {styleElements}\n </>\n )\n}\n\n/**\n * Determines whether resolved prop changes require a server refresh and returns\n * the control-instance state needed to apply the update.\n */\nconst needsServerRefresh = ({\n resolvedProps,\n controlInstances,\n prevProps,\n prevLeafProps,\n}: {\n resolvedProps: Record<string, unknown>\n controlInstances: Record<string, ControlInstance> | null\n prevProps: Record<string, unknown>\n prevLeafProps: Set<string>\n}): {\n needsRefresh: boolean\n leafProps: Set<string>\n reactNodeInstances: ControlInstance[]\n} => {\n const { leafInstances, leafProps } = getLeafPropsAndInstances(resolvedProps, controlInstances)\n\n const combinedLeafProps = setUnion(leafProps, prevLeafProps).values()\n const updatedLeafProps = new Set(\n [...combinedLeafProps].filter(\n propName => getProp(resolvedProps, propName) !== getProp(prevProps, propName),\n ),\n )\n\n const updatedLeafInstances = leafInstances.filter(instance =>\n updatedLeafProps.has(instance.propPath),\n )\n\n const reactNodeInstances = updatedLeafInstances.filter(c => c.resolvesToRenderableNode())\n\n const reactNodePropKeys = new Set(reactNodeInstances.map(c => c.propPath))\n const newlyAddedLeafProps = setDifference(leafProps, prevLeafProps)\n\n // A server refresh is needed if some of the updated props are not `ReactNode` props, or we\n // have newly observed props (typically `List` items). Even when newly observed props are\n // `ReactNode` props, we have to first render them on the server to get them in the element\n // tree before they can be updated client-side.\n const needsRefresh =\n setDifference(updatedLeafProps, reactNodePropKeys).size > 0 || newlyAddedLeafProps.size > 0\n\n return {\n needsRefresh,\n leafProps,\n reactNodeInstances,\n }\n}\n\n/**\n * Returns terminal prop paths with the corresponding control instances.\n */\nconst getLeafPropsAndInstances = (\n props: Record<string, unknown>,\n controlInstances: Record<string, ControlInstance> | null,\n): {\n leafProps: Set<string>\n leafInstances: ControlInstance[]\n} => {\n const topLevelInstances = Object.keys(props)\n .map(prop => controlInstances?.[prop])\n .filter(inst => inst != null)\n\n const leafInstances = getLeafInstances(topLevelInstances)\n const leafProps = new Set(leafInstances.map(c => c.propPath))\n return { leafProps, leafInstances }\n}\n\n/**\n * Flattens a control instance tree to its leaf (terminal) instances.\n */\nconst getLeafInstances = (instances: ControlInstance[]): ControlInstance[] =>\n instances.flatMap(instance =>\n instance.isCompositeProp() ? getLeafInstances(instance.children()) : [instance],\n )\n"],"mappings":"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","names":["elementData","documentKey"]}
@@ -40,6 +40,7 @@ async function ServerElementData({
40
40
  const stylesheet = new StylesheetEngine({
41
41
  breakpointsData: getBreakpoints(state),
42
42
  classNamePrefix: context.rootStyleProps?.classNamePrefix,
43
+ forceImportant: context.rootStyleProps?.forceImportant,
43
44
  documentKey,
44
45
  elementKey: elementData.key,
45
46
  propPathComponents: [],
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/runtimes/react/server/components/element-data.tsx"],"sourcesContent":["import { type ReactNode } from 'react'\n\nimport { partitionRecord } from '../../../../utils/partition'\n\nimport {\n type State,\n type ElementData,\n getReactComponent,\n getBreakpoints,\n getComponentPropControllerDescriptors,\n} from '../../../../state/read-only-state'\n\nimport { FallbackComponent } from '../../../../components/shared/FallbackComponent'\nimport { isLegacyDescriptor } from '../../../../prop-controllers/descriptors'\n\nimport { type ServerRenderContext, getStore } from '../render-context'\nimport { resolveProps } from '../resolve-props'\nimport { StylesheetEngine } from '../../css-runtime/stylesheet-engine'\nimport { type ControlledStyleData } from '../../css-runtime/types'\nimport { RSCEmittedStyle } from '../../css-runtime/components/rsc-emitted-style'\n\nexport async function ServerElementData({\n documentKey,\n context,\n elementData,\n injectedProps,\n}: {\n documentKey: string\n context: ServerRenderContext\n elementData: ElementData\n injectedProps: Record<string, unknown>\n}): Promise<ReactNode> {\n const state = getStore(context).getState()\n\n const Component = getReactComponent(state, elementData.type)\n if (Component == null) {\n return (\n <FallbackComponent\n text=\"Component not found\"\n details={`Unknown component '${elementData.type}'`}\n />\n )\n }\n\n const [legacyDescriptors, definitions] = getControlDefs(state, elementData)\n const legacyKeys = Object.keys(legacyDescriptors)\n if (legacyKeys.length > 0) {\n console.warn(`Unexpected legacy control data in server element '${elementData.key}`, {\n elementData,\n legacyKeys,\n })\n }\n\n const classStyleData = new Map<string, ControlledStyleData>()\n const stylesheet = new StylesheetEngine({\n breakpointsData: getBreakpoints(state),\n classNamePrefix: context.rootStyleProps?.classNamePrefix,\n documentKey,\n elementKey: elementData.key,\n propPathComponents: [],\n onDefineStyle: styleData => {\n const { onBoxModelChange, ...serializableStyleData } = styleData\n classStyleData.set(styleData.className, serializableStyleData)\n },\n })\n\n const props = {\n ...(await resolveProps(context, elementData, documentKey, definitions, stylesheet)),\n ...injectedProps,\n }\n\n const styleElements = Array.from(classStyleData, ([className, styleData]) => (\n <RSCEmittedStyle key={className} namespace={elementData.key} serializableData={styleData} />\n ))\n\n return (\n <>\n {/* Make the component the first child so that `findDOMNode` resolves to its first\n rendered DOM node (if any) rather than the component's `<style>` element */}\n <Component key={elementData.key} {...props} />\n {styleElements}\n </>\n )\n}\n\nconst getControlDefs = (state: State, elementData: ElementData) => {\n const descriptors = getComponentPropControllerDescriptors(state, elementData.type) ?? {}\n return partitionRecord(descriptors, isLegacyDescriptor)\n}\n"],"mappings":"AAqCM,SAuCF,UAvCE,KAuCF,YAvCE;AAnCN,SAAS,uBAAuB;AAEhC;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AAEnC,SAAmC,gBAAgB;AACnD,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AAEjC,SAAS,uBAAuB;AAEhC,eAAsB,kBAAkB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKuB;AACrB,QAAM,QAAQ,SAAS,OAAO,EAAE,SAAS;AAEzC,QAAM,YAAY,kBAAkB,OAAO,YAAY,IAAI;AAC3D,MAAI,aAAa,MAAM;AACrB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,sBAAsB,YAAY,IAAI;AAAA;AAAA,IACjD;AAAA,EAEJ;AAEA,QAAM,CAAC,mBAAmB,WAAW,IAAI,eAAe,OAAO,WAAW;AAC1E,QAAM,aAAa,OAAO,KAAK,iBAAiB;AAChD,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,KAAK,qDAAqD,YAAY,GAAG,IAAI;AAAA,MACnF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,oBAAI,IAAiC;AAC5D,QAAM,aAAa,IAAI,iBAAiB;AAAA,IACtC,iBAAiB,eAAe,KAAK;AAAA,IACrC,iBAAiB,QAAQ,gBAAgB;AAAA,IACzC;AAAA,IACA,YAAY,YAAY;AAAA,IACxB,oBAAoB,CAAC;AAAA,IACrB,eAAe,eAAa;AAC1B,YAAM,EAAE,kBAAkB,GAAG,sBAAsB,IAAI;AACvD,qBAAe,IAAI,UAAU,WAAW,qBAAqB;AAAA,IAC/D;AAAA,EACF,CAAC;AAED,QAAM,QAAQ;AAAA,IACZ,GAAI,MAAM,aAAa,SAAS,aAAa,aAAa,aAAa,UAAU;AAAA,IACjF,GAAG;AAAA,EACL;AAEA,QAAM,gBAAgB,MAAM,KAAK,gBAAgB,CAAC,CAAC,WAAW,SAAS,MACrE,oBAAC,mBAAgC,WAAW,YAAY,KAAK,kBAAkB,aAAzD,SAAoE,CAC3F;AAED,SACE,iCAGE;AAAA,wBAAC,aAAiC,GAAG,SAArB,YAAY,GAAgB;AAAA,IAC3C;AAAA,KACH;AAEJ;AAEA,MAAM,iBAAiB,CAAC,OAAc,gBAA6B;AACjE,QAAM,cAAc,sCAAsC,OAAO,YAAY,IAAI,KAAK,CAAC;AACvF,SAAO,gBAAgB,aAAa,kBAAkB;AACxD;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/runtimes/react/server/components/element-data.tsx"],"sourcesContent":["import { type ReactNode } from 'react'\n\nimport { partitionRecord } from '../../../../utils/partition'\n\nimport {\n type State,\n type ElementData,\n getReactComponent,\n getBreakpoints,\n getComponentPropControllerDescriptors,\n} from '../../../../state/read-only-state'\n\nimport { FallbackComponent } from '../../../../components/shared/FallbackComponent'\nimport { isLegacyDescriptor } from '../../../../prop-controllers/descriptors'\n\nimport { type ServerRenderContext, getStore } from '../render-context'\nimport { resolveProps } from '../resolve-props'\nimport { StylesheetEngine } from '../../css-runtime/stylesheet-engine'\nimport { type ControlledStyleData } from '../../css-runtime/types'\nimport { RSCEmittedStyle } from '../../css-runtime/components/rsc-emitted-style'\n\nexport async function ServerElementData({\n documentKey,\n context,\n elementData,\n injectedProps,\n}: {\n documentKey: string\n context: ServerRenderContext\n elementData: ElementData\n injectedProps: Record<string, unknown>\n}): Promise<ReactNode> {\n const state = getStore(context).getState()\n\n const Component = getReactComponent(state, elementData.type)\n if (Component == null) {\n return (\n <FallbackComponent\n text=\"Component not found\"\n details={`Unknown component '${elementData.type}'`}\n />\n )\n }\n\n const [legacyDescriptors, definitions] = getControlDefs(state, elementData)\n const legacyKeys = Object.keys(legacyDescriptors)\n if (legacyKeys.length > 0) {\n console.warn(`Unexpected legacy control data in server element '${elementData.key}`, {\n elementData,\n legacyKeys,\n })\n }\n\n const classStyleData = new Map<string, ControlledStyleData>()\n const stylesheet = new StylesheetEngine({\n breakpointsData: getBreakpoints(state),\n classNamePrefix: context.rootStyleProps?.classNamePrefix,\n forceImportant: context.rootStyleProps?.forceImportant,\n documentKey,\n elementKey: elementData.key,\n propPathComponents: [],\n onDefineStyle: styleData => {\n const { onBoxModelChange, ...serializableStyleData } = styleData\n classStyleData.set(styleData.className, serializableStyleData)\n },\n })\n\n const props = {\n ...(await resolveProps(context, elementData, documentKey, definitions, stylesheet)),\n ...injectedProps,\n }\n\n const styleElements = Array.from(classStyleData, ([className, styleData]) => (\n <RSCEmittedStyle key={className} namespace={elementData.key} serializableData={styleData} />\n ))\n\n return (\n <>\n {/* Make the component the first child so that `findDOMNode` resolves to its first\n rendered DOM node (if any) rather than the component's `<style>` element */}\n <Component key={elementData.key} {...props} />\n {styleElements}\n </>\n )\n}\n\nconst getControlDefs = (state: State, elementData: ElementData) => {\n const descriptors = getComponentPropControllerDescriptors(state, elementData.type) ?? {}\n return partitionRecord(descriptors, isLegacyDescriptor)\n}\n"],"mappings":"AAqCM,SAwCF,UAxCE,KAwCF,YAxCE;AAnCN,SAAS,uBAAuB;AAEhC;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AAEnC,SAAmC,gBAAgB;AACnD,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AAEjC,SAAS,uBAAuB;AAEhC,eAAsB,kBAAkB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKuB;AACrB,QAAM,QAAQ,SAAS,OAAO,EAAE,SAAS;AAEzC,QAAM,YAAY,kBAAkB,OAAO,YAAY,IAAI;AAC3D,MAAI,aAAa,MAAM;AACrB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,sBAAsB,YAAY,IAAI;AAAA;AAAA,IACjD;AAAA,EAEJ;AAEA,QAAM,CAAC,mBAAmB,WAAW,IAAI,eAAe,OAAO,WAAW;AAC1E,QAAM,aAAa,OAAO,KAAK,iBAAiB;AAChD,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,KAAK,qDAAqD,YAAY,GAAG,IAAI;AAAA,MACnF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,oBAAI,IAAiC;AAC5D,QAAM,aAAa,IAAI,iBAAiB;AAAA,IACtC,iBAAiB,eAAe,KAAK;AAAA,IACrC,iBAAiB,QAAQ,gBAAgB;AAAA,IACzC,gBAAgB,QAAQ,gBAAgB;AAAA,IACxC;AAAA,IACA,YAAY,YAAY;AAAA,IACxB,oBAAoB,CAAC;AAAA,IACrB,eAAe,eAAa;AAC1B,YAAM,EAAE,kBAAkB,GAAG,sBAAsB,IAAI;AACvD,qBAAe,IAAI,UAAU,WAAW,qBAAqB;AAAA,IAC/D;AAAA,EACF,CAAC;AAED,QAAM,QAAQ;AAAA,IACZ,GAAI,MAAM,aAAa,SAAS,aAAa,aAAa,aAAa,UAAU;AAAA,IACjF,GAAG;AAAA,EACL;AAEA,QAAM,gBAAgB,MAAM,KAAK,gBAAgB,CAAC,CAAC,WAAW,SAAS,MACrE,oBAAC,mBAAgC,WAAW,YAAY,KAAK,kBAAkB,aAAzD,SAAoE,CAC3F;AAED,SACE,iCAGE;AAAA,wBAAC,aAAiC,GAAG,SAArB,YAAY,GAAgB;AAAA,IAC3C;AAAA,KACH;AAEJ;AAEA,MAAM,iBAAiB,CAAC,OAAc,gBAA6B;AACjE,QAAM,cAAc,sCAAsC,OAAO,YAAY,IAAI,KAAK,CAAC;AACvF,SAAO,gBAAgB,aAAa,kBAAkB;AACxD;","names":[]}
@@ -1,41 +1,98 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
- import { createContext, useCallback, useContext, useState, useMemo } from "react";
3
+ import {
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useMemo,
9
+ useState
10
+ } from "react";
11
+ import { useIsomorphicLayoutEffect } from "../../../../components/hooks/useIsomorphicLayoutEffect";
12
+ const createCacheState = (initialElements) => ({
13
+ initialElements,
14
+ elements: new Map(Array.from(initialElements, ([key, node]) => [key, { node }])),
15
+ refreshScope: {
16
+ active: false,
17
+ requestsByElement: /* @__PURE__ */ new Map()
18
+ }
19
+ });
4
20
  const Context = createContext({
5
21
  getElement: () => null,
6
- updateElement: () => {
7
- },
8
- removeElement: () => {
9
- }
22
+ beginRefresh: () => null
10
23
  });
11
24
  const ServerElementsCache = ({
12
25
  children,
13
26
  value
14
27
  }) => {
15
- const [nodes, setNodes] = useState(value);
16
- const [previousValue, setPreviousValue] = useState(value);
17
- if (value !== previousValue) {
18
- setPreviousValue(value);
19
- setNodes(value);
28
+ const [state, setState] = useState(() => createCacheState(value));
29
+ if (state.initialElements !== value) {
30
+ setState(createCacheState(value));
20
31
  }
21
- const getElement = useCallback((elementKey) => nodes.get(elementKey), [nodes]);
22
- const updateElement = useCallback(
23
- (elementKey, node) => setNodes((prev) => new Map(prev).set(elementKey, node)),
24
- []
25
- );
26
- const removeElement = useCallback(
27
- (elementKey) => setNodes((prev) => {
28
- const next = new Map(prev);
29
- next.delete(elementKey);
30
- return next;
31
- }),
32
- []
32
+ const { elements, refreshScope } = state;
33
+ useIsomorphicLayoutEffect(() => {
34
+ refreshScope.active = true;
35
+ return () => {
36
+ refreshScope.active = false;
37
+ };
38
+ }, [refreshScope]);
39
+ const getElement = useCallback(
40
+ // Always wrap the node in `<RefreshCommitObserver>` so adding a commit callback
41
+ // during refresh doesn't change the tree shape and remount the refreshed node
42
+ (elementKey) => {
43
+ const entry = elements.get(elementKey);
44
+ if (entry == null)
45
+ return null;
46
+ return /* @__PURE__ */ jsx(RefreshCommitObserver, { onCommitted: entry.onCommitted, children: entry.node });
47
+ },
48
+ [elements]
33
49
  );
34
- const cache = useMemo(
35
- () => ({ getElement, updateElement, removeElement }),
36
- [getElement, updateElement, removeElement]
50
+ const beginRefresh = useCallback(
51
+ (elementKey, onCommitted) => {
52
+ const { requestsByElement } = refreshScope;
53
+ const elementRequests = requestsByElement.get(elementKey) ?? {
54
+ lastIssued: 0,
55
+ lastAccepted: 0,
56
+ lastCommitted: 0
57
+ };
58
+ requestsByElement.set(elementKey, elementRequests);
59
+ const requestId = ++elementRequests.lastIssued;
60
+ return (node) => {
61
+ if (!refreshScope.active || requestId <= elementRequests.lastAccepted)
62
+ return;
63
+ elementRequests.lastAccepted = requestId;
64
+ const notifyCommitted = () => {
65
+ if (requestId <= elementRequests.lastCommitted)
66
+ return;
67
+ elementRequests.lastCommitted = requestId;
68
+ const callback = onCommitted;
69
+ onCommitted = void 0;
70
+ callback?.();
71
+ };
72
+ setState((prev) => {
73
+ if (prev.refreshScope !== refreshScope)
74
+ return prev;
75
+ return {
76
+ ...prev,
77
+ elements: new Map(prev.elements).set(elementKey, {
78
+ node,
79
+ onCommitted: notifyCommitted
80
+ })
81
+ };
82
+ });
83
+ };
84
+ },
85
+ [refreshScope]
37
86
  );
38
- return /* @__PURE__ */ jsx(Context.Provider, { value: cache, children });
87
+ const result = useMemo(() => ({ getElement, beginRefresh }), [getElement, beginRefresh]);
88
+ return /* @__PURE__ */ jsx(Context.Provider, { value: result, children });
89
+ };
90
+ const RefreshCommitObserver = ({
91
+ children,
92
+ onCommitted
93
+ }) => {
94
+ useEffect(() => onCommitted?.(), [onCommitted]);
95
+ return children;
39
96
  };
40
97
  const ServerElementsProvider = ({
41
98
  children,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/runtimes/react/server/components/server-elements-cache.tsx"],"sourcesContent":["'use client'\n\nimport { createContext, ReactNode, useCallback, useContext, useState, useMemo } from 'react'\n\nimport { type ElementsMap } from '../collect-server-elements'\n\ntype ContextValue = {\n getElement: (elementKey: string) => ReactNode\n updateElement: (elementKey: string, node: ReactNode) => void\n removeElement: (elementKey: string) => void\n}\n\nconst Context = createContext<ContextValue>({\n getElement: () => null,\n updateElement: () => {},\n removeElement: () => {},\n})\n\n/**\n * Client-side \"cache\" of server-rendered elements; this is one of the key pieces in our RSC\n * implementation, with React doing the majority of the heavy lifting: when `ReactNode`s are\n * passed as props across a 'use client' boundary, React's flight serializer automatically\n * renders and encodes them in the RSC stream and then reconstructs them on the client. All\n * we need to do on the client is to make these React elements available for lookup/\n * manipulation when editing in the builder.\n */\nexport const ServerElementsCache = ({\n children,\n value,\n}: {\n children: ReactNode\n value: ElementsMap\n}) => {\n // An RSC re-render does not inherently remount client components; React can reconcile\n // the new server tree with the existing client tree, so we need to handle the `value`\n // prop updates\n const [nodes, setNodes] = useState(value)\n const [previousValue, setPreviousValue] = useState(value)\n\n // this is okay to do on render, see https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes\n if (value !== previousValue) {\n setPreviousValue(value)\n setNodes(value)\n }\n\n const getElement = useCallback((elementKey: string): ReactNode => nodes.get(elementKey), [nodes])\n\n const updateElement = useCallback(\n (elementKey: string, node: ReactNode) => setNodes(prev => new Map(prev).set(elementKey, node)),\n [],\n )\n\n const removeElement = useCallback(\n (elementKey: string) =>\n setNodes(prev => {\n const next = new Map(prev)\n next.delete(elementKey)\n return next\n }),\n [],\n )\n\n const cache = useMemo(\n () => ({ getElement, updateElement, removeElement }),\n [getElement, updateElement, removeElement],\n )\n\n return <Context.Provider value={cache}>{children}</Context.Provider>\n}\n\nexport const ServerElementsProvider = ({\n children,\n elements,\n}: {\n children: ReactNode\n elements: ElementsMap\n}) => <ServerElementsCache value={elements}>{children}</ServerElementsCache>\n\nexport const useServerElementsCache = () => useContext(Context)\n"],"mappings":";AAmES;AAjET,SAAS,eAA0B,aAAa,YAAY,UAAU,eAAe;AAUrF,MAAM,UAAU,cAA4B;AAAA,EAC1C,YAAY,MAAM;AAAA,EAClB,eAAe,MAAM;AAAA,EAAC;AAAA,EACtB,eAAe,MAAM;AAAA,EAAC;AACxB,CAAC;AAUM,MAAM,sBAAsB,CAAC;AAAA,EAClC;AAAA,EACA;AACF,MAGM;AAIJ,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AACxC,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AAGxD,MAAI,UAAU,eAAe;AAC3B,qBAAiB,KAAK;AACtB,aAAS,KAAK;AAAA,EAChB;AAEA,QAAM,aAAa,YAAY,CAAC,eAAkC,MAAM,IAAI,UAAU,GAAG,CAAC,KAAK,CAAC;AAEhG,QAAM,gBAAgB;AAAA,IACpB,CAAC,YAAoB,SAAoB,SAAS,UAAQ,IAAI,IAAI,IAAI,EAAE,IAAI,YAAY,IAAI,CAAC;AAAA,IAC7F,CAAC;AAAA,EACH;AAEA,QAAM,gBAAgB;AAAA,IACpB,CAAC,eACC,SAAS,UAAQ;AACf,YAAM,OAAO,IAAI,IAAI,IAAI;AACzB,WAAK,OAAO,UAAU;AACtB,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,QAAM,QAAQ;AAAA,IACZ,OAAO,EAAE,YAAY,eAAe,cAAc;AAAA,IAClD,CAAC,YAAY,eAAe,aAAa;AAAA,EAC3C;AAEA,SAAO,oBAAC,QAAQ,UAAR,EAAiB,OAAO,OAAQ,UAAS;AACnD;AAEO,MAAM,yBAAyB,CAAC;AAAA,EACrC;AAAA,EACA;AACF,MAGM,oBAAC,uBAAoB,OAAO,UAAW,UAAS;AAE/C,MAAM,yBAAyB,MAAM,WAAW,OAAO;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/runtimes/react/server/components/server-elements-cache.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react'\n\nimport { useIsomorphicLayoutEffect } from '../../../../components/hooks/useIsomorphicLayoutEffect'\n\nimport { type ElementsMap } from '../collect-server-elements'\n\ntype CommitRefresh = (node: ReactNode) => void\n\ntype ElementRequests = {\n lastIssued: number\n lastAccepted: number\n lastCommitted: number\n}\n\ntype ContextValue = {\n getElement: (elementKey: string) => ReactNode\n beginRefresh: (elementKey: string, onCommitted?: () => void) => CommitRefresh | null\n}\n\ntype CacheEntry = {\n node: ReactNode\n onCommitted?: () => void\n}\n\ntype CacheState = {\n initialElements: ElementsMap\n elements: Map<string, CacheEntry>\n refreshScope: {\n active: boolean\n requestsByElement: Map<string, ElementRequests>\n }\n}\n\nconst createCacheState = (initialElements: ElementsMap): CacheState => ({\n initialElements,\n elements: new Map(Array.from(initialElements, ([key, node]) => [key, { node }] as const)),\n refreshScope: {\n active: false,\n requestsByElement: new Map(),\n },\n})\n\nconst Context = createContext<ContextValue>({\n getElement: () => null,\n beginRefresh: () => null,\n})\n\n/**\n * Client-side \"cache\" of server-rendered elements; this is one of the key pieces in our RSC\n * implementation, with React doing the majority of the heavy lifting: when `ReactNode`s are\n * passed as props across a 'use client' boundary, React's flight serializer automatically\n * renders and encodes them in the RSC stream and then reconstructs them on the client. All\n * we need to do on the client is to make these React elements available for lookup/\n * manipulation when editing in the builder.\n */\nexport const ServerElementsCache = ({\n children,\n value,\n}: {\n children: ReactNode\n value: ElementsMap\n}) => {\n const [state, setState] = useState<CacheState>(() => createCacheState(value))\n // A new elements map resets the state\n if (state.initialElements !== value) {\n setState(createCacheState(value))\n }\n\n const { elements, refreshScope } = state\n\n // Run during React commit, before paint\n useIsomorphicLayoutEffect(() => {\n // Activate current scope on mount / whenever we reset the state\n refreshScope.active = true\n return () => {\n // Stop accepting refresh requests associated with the old scope\n refreshScope.active = false\n }\n }, [refreshScope])\n\n const getElement = useCallback(\n // Always wrap the node in `<RefreshCommitObserver>` so adding a commit callback\n // during refresh doesn't change the tree shape and remount the refreshed node\n (elementKey: string): ReactNode => {\n const entry = elements.get(elementKey)\n if (entry == null) return null\n\n return (\n <RefreshCommitObserver onCommitted={entry.onCommitted}>{entry.node}</RefreshCommitObserver>\n )\n },\n [elements],\n )\n\n const beginRefresh = useCallback(\n (elementKey: string, onCommitted?: () => void) => {\n const { requestsByElement } = refreshScope\n\n const elementRequests = requestsByElement.get(elementKey) ?? {\n lastIssued: 0,\n lastAccepted: 0,\n lastCommitted: 0,\n }\n\n requestsByElement.set(elementKey, elementRequests)\n\n const requestId = ++elementRequests.lastIssued\n\n return (node: ReactNode): void => {\n // Ignore stale updates\n if (!refreshScope.active || requestId <= elementRequests.lastAccepted) return\n\n elementRequests.lastAccepted = requestId\n const notifyCommitted = () => {\n if (requestId <= elementRequests.lastCommitted) return\n\n elementRequests.lastCommitted = requestId\n // Don't retain the external callback and its captured values after notification\n const callback = onCommitted\n onCommitted = undefined\n callback?.()\n }\n\n setState(prev => {\n // Ignore updates that come in between element map replacement and scope deactivation\n if (prev.refreshScope !== refreshScope) return prev\n\n return {\n ...prev,\n elements: new Map(prev.elements).set(elementKey, {\n node,\n onCommitted: notifyCommitted,\n }),\n }\n })\n }\n },\n [refreshScope],\n )\n\n const result = useMemo(() => ({ getElement, beginRefresh }), [getElement, beginRefresh])\n\n return <Context.Provider value={result}>{children}</Context.Provider>\n}\n\nconst RefreshCommitObserver = ({\n children,\n onCommitted,\n}: {\n children: ReactNode\n onCommitted?: () => void\n}) => {\n // Notify the caller that the updated element node has been committed to\n // the current React tree\n useEffect(() => onCommitted?.(), [onCommitted])\n return children\n}\n\nexport const ServerElementsProvider = ({\n children,\n elements,\n}: {\n children: ReactNode\n elements: ElementsMap\n}) => <ServerElementsCache value={elements}>{children}</ServerElementsCache>\n\nexport const useServerElementsCache = () => useContext(Context)\n"],"mappings":";AAkGQ;AAhGR;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,iCAAiC;AA+B1C,MAAM,mBAAmB,CAAC,qBAA8C;AAAA,EACtE;AAAA,EACA,UAAU,IAAI,IAAI,MAAM,KAAK,iBAAiB,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAU,CAAC;AAAA,EACxF,cAAc;AAAA,IACZ,QAAQ;AAAA,IACR,mBAAmB,oBAAI,IAAI;AAAA,EAC7B;AACF;AAEA,MAAM,UAAU,cAA4B;AAAA,EAC1C,YAAY,MAAM;AAAA,EAClB,cAAc,MAAM;AACtB,CAAC;AAUM,MAAM,sBAAsB,CAAC;AAAA,EAClC;AAAA,EACA;AACF,MAGM;AACJ,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAqB,MAAM,iBAAiB,KAAK,CAAC;AAE5E,MAAI,MAAM,oBAAoB,OAAO;AACnC,aAAS,iBAAiB,KAAK,CAAC;AAAA,EAClC;AAEA,QAAM,EAAE,UAAU,aAAa,IAAI;AAGnC,4BAA0B,MAAM;AAE9B,iBAAa,SAAS;AACtB,WAAO,MAAM;AAEX,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,aAAa;AAAA;AAAA;AAAA,IAGjB,CAAC,eAAkC;AACjC,YAAM,QAAQ,SAAS,IAAI,UAAU;AACrC,UAAI,SAAS;AAAM,eAAO;AAE1B,aACE,oBAAC,yBAAsB,aAAa,MAAM,aAAc,gBAAM,MAAK;AAAA,IAEvE;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,eAAe;AAAA,IACnB,CAAC,YAAoB,gBAA6B;AAChD,YAAM,EAAE,kBAAkB,IAAI;AAE9B,YAAM,kBAAkB,kBAAkB,IAAI,UAAU,KAAK;AAAA,QAC3D,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,eAAe;AAAA,MACjB;AAEA,wBAAkB,IAAI,YAAY,eAAe;AAEjD,YAAM,YAAY,EAAE,gBAAgB;AAEpC,aAAO,CAAC,SAA0B;AAEhC,YAAI,CAAC,aAAa,UAAU,aAAa,gBAAgB;AAAc;AAEvE,wBAAgB,eAAe;AAC/B,cAAM,kBAAkB,MAAM;AAC5B,cAAI,aAAa,gBAAgB;AAAe;AAEhD,0BAAgB,gBAAgB;AAEhC,gBAAM,WAAW;AACjB,wBAAc;AACd,qBAAW;AAAA,QACb;AAEA,iBAAS,UAAQ;AAEf,cAAI,KAAK,iBAAiB;AAAc,mBAAO;AAE/C,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,UAAU,IAAI,IAAI,KAAK,QAAQ,EAAE,IAAI,YAAY;AAAA,cAC/C;AAAA,cACA,aAAa;AAAA,YACf,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,SAAS,QAAQ,OAAO,EAAE,YAAY,aAAa,IAAI,CAAC,YAAY,YAAY,CAAC;AAEvF,SAAO,oBAAC,QAAQ,UAAR,EAAiB,OAAO,QAAS,UAAS;AACpD;AAEA,MAAM,wBAAwB,CAAC;AAAA,EAC7B;AAAA,EACA;AACF,MAGM;AAGJ,YAAU,MAAM,cAAc,GAAG,CAAC,WAAW,CAAC;AAC9C,SAAO;AACT;AAEO,MAAM,yBAAyB,CAAC;AAAA,EACrC;AAAA,EACA;AACF,MAGM,oBAAC,uBAAoB,OAAO,UAAW,UAAS;AAE/C,MAAM,yBAAyB,MAAM,WAAW,OAAO;","names":[]}
@@ -10,7 +10,7 @@ const ReadWriteActionTypes = {
10
10
  REGISTER_MEASURABLE: "REGISTER_MEASURABLE",
11
11
  UNREGISTER_MEASURABLE: "UNREGISTER_MEASURABLE",
12
12
  SET_RESOLVED_VALUE_OVERRIDE: "SET_RESOLVED_VALUE_OVERRIDE",
13
- CLEAR_RESOLVED_VALUE_OVERRIDE: "CLEAR_RESOLVED_VALUE_OVERRIDE",
13
+ CLEAR_STALE_RESOLVED_VALUE_OVERRIDES: "CLEAR_STALE_RESOLVED_VALUE_OVERRIDES",
14
14
  UPDATE_API_CLIENT_CACHE: "UPDATE_API_CLIENT_CACHE",
15
15
  CLEAR_API_CLIENT_CACHE: "CLEAR_API_CLIENT_CACHE"
16
16
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/state/actions/internal/read-write-action-types.ts"],"sourcesContent":["export const ReadWriteActionTypes = {\n FLUSH_ACTION_BUFFER: 'FLUSH_ACTION_BUFFER',\n\n CHANGE_ELEMENT_TREE: 'CHANGE_ELEMENT_TREE',\n\n REGISTER_COMPONENT_HANDLE: 'REGISTER_COMPONENT_HANDLE',\n UNREGISTER_COMPONENT_HANDLE: 'UNREGISTER_COMPONENT_HANDLE',\n\n REGISTER_PROP_CONTROLLERS: 'REGISTER_PROP_CONTROLLERS',\n UNREGISTER_PROP_CONTROLLERS: 'UNREGISTER_PROP_CONTROLLERS',\n REGISTER_PROP_CONTROLLERS_HANDLE: 'REGISTER_PROP_CONTROLLERS_HANDLE',\n UNREGISTER_PROP_CONTROLLERS_HANDLE: 'UNREGISTER_PROP_CONTROLLERS_HANDLE',\n\n REGISTER_MEASURABLE: 'REGISTER_MEASURABLE',\n UNREGISTER_MEASURABLE: 'UNREGISTER_MEASURABLE',\n\n SET_RESOLVED_VALUE_OVERRIDE: 'SET_RESOLVED_VALUE_OVERRIDE',\n CLEAR_RESOLVED_VALUE_OVERRIDE: 'CLEAR_RESOLVED_VALUE_OVERRIDE',\n\n UPDATE_API_CLIENT_CACHE: 'UPDATE_API_CLIENT_CACHE',\n CLEAR_API_CLIENT_CACHE: 'CLEAR_API_CLIENT_CACHE',\n} as const\n"],"mappings":"AAAO,MAAM,uBAAuB;AAAA,EAClC,qBAAqB;AAAA,EAErB,qBAAqB;AAAA,EAErB,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAE7B,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAC7B,kCAAkC;AAAA,EAClC,oCAAoC;AAAA,EAEpC,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EAEvB,6BAA6B;AAAA,EAC7B,+BAA+B;AAAA,EAE/B,yBAAyB;AAAA,EACzB,wBAAwB;AAC1B;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/state/actions/internal/read-write-action-types.ts"],"sourcesContent":["export const ReadWriteActionTypes = {\n FLUSH_ACTION_BUFFER: 'FLUSH_ACTION_BUFFER',\n\n CHANGE_ELEMENT_TREE: 'CHANGE_ELEMENT_TREE',\n\n REGISTER_COMPONENT_HANDLE: 'REGISTER_COMPONENT_HANDLE',\n UNREGISTER_COMPONENT_HANDLE: 'UNREGISTER_COMPONENT_HANDLE',\n\n REGISTER_PROP_CONTROLLERS: 'REGISTER_PROP_CONTROLLERS',\n UNREGISTER_PROP_CONTROLLERS: 'UNREGISTER_PROP_CONTROLLERS',\n REGISTER_PROP_CONTROLLERS_HANDLE: 'REGISTER_PROP_CONTROLLERS_HANDLE',\n UNREGISTER_PROP_CONTROLLERS_HANDLE: 'UNREGISTER_PROP_CONTROLLERS_HANDLE',\n\n REGISTER_MEASURABLE: 'REGISTER_MEASURABLE',\n UNREGISTER_MEASURABLE: 'UNREGISTER_MEASURABLE',\n\n SET_RESOLVED_VALUE_OVERRIDE: 'SET_RESOLVED_VALUE_OVERRIDE',\n CLEAR_STALE_RESOLVED_VALUE_OVERRIDES: 'CLEAR_STALE_RESOLVED_VALUE_OVERRIDES',\n\n UPDATE_API_CLIENT_CACHE: 'UPDATE_API_CLIENT_CACHE',\n CLEAR_API_CLIENT_CACHE: 'CLEAR_API_CLIENT_CACHE',\n} as const\n"],"mappings":"AAAO,MAAM,uBAAuB;AAAA,EAClC,qBAAqB;AAAA,EAErB,qBAAqB;AAAA,EAErB,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAE7B,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAC7B,kCAAkC;AAAA,EAClC,oCAAoC;AAAA,EAEpC,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EAEvB,6BAA6B;AAAA,EAC7B,sCAAsC;AAAA,EAEtC,yBAAyB;AAAA,EACzB,wBAAwB;AAC1B;","names":[]}
@@ -78,9 +78,9 @@ function setResolvedValueOverride(payload) {
78
78
  payload
79
79
  };
80
80
  }
81
- function clearResolvedValueOverride(payload) {
81
+ function clearStaleResolvedValueOverrides(payload) {
82
82
  return {
83
- type: ReadWriteActionTypes.CLEAR_RESOLVED_VALUE_OVERRIDE,
83
+ type: ReadWriteActionTypes.CLEAR_STALE_RESOLVED_VALUE_OVERRIDES,
84
84
  payload
85
85
  };
86
86
  }
@@ -126,7 +126,7 @@ function createPropControllers({
126
126
  export {
127
127
  changeElementTree,
128
128
  clearAPIClientCache,
129
- clearResolvedValueOverride,
129
+ clearStaleResolvedValueOverrides,
130
130
  createPropControllers,
131
131
  flushActionBuffer,
132
132
  registerComponentHandle,