@ms-cloudpack/overlay 0.19.56 → 0.19.57

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.
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Handles hot module replacement (HMR) updates for packages.
3
+ *
4
+ * This function is called when the development server notifies the client that a package
5
+ * has been updated. It performs the following steps:
6
+ *
7
+ * 1. **Check which modules are loaded**: Uses Performance API to determine which entry points
8
+ * from the package are actually loaded on the current page.
9
+ *
10
+ * 2. **Re-import updated modules**: Dynamically imports the new versions of loaded modules
11
+ * using their updated bundle URLs (with new hash).
12
+ *
13
+ * 3. **Trigger React Refresh**: If React Refresh is available, triggers component updates
14
+ * while preserving component state. Falls back to full page reload otherwise.
15
+ *
16
+ * The process ensures:
17
+ * - Only relevant modules are updated (skip modules not loaded on current page)
18
+ * - React component state is preserved when possible
19
+ * - Graceful fallback to full reload if React Refresh fails
20
+ *
21
+ * @param data - The package update payload containing package name, version, and entry points
22
+ *
23
+ * @example
24
+ * // This is typically called by the WebSocket message handler:
25
+ * socket.on('package-update', (data) => {
26
+ * await handlePackageUpdate(data);
27
+ * });
28
+ */
29
+ export declare const handlePackageUpdate: (data: unknown) => Promise<void>;
30
+ //# sourceMappingURL=handlePackageUpdate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlePackageUpdate.d.ts","sourceRoot":"","sources":["../src/handlePackageUpdate.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,mBAAmB,GAAU,MAAM,OAAO,KAAG,OAAO,CAAC,IAAI,CAmFrE,CAAC"}
@@ -0,0 +1,106 @@
1
+ import { removeHashFromUrl } from '@ms-cloudpack/path-string-parsing';
2
+ /**
3
+ * Handles hot module replacement (HMR) updates for packages.
4
+ *
5
+ * This function is called when the development server notifies the client that a package
6
+ * has been updated. It performs the following steps:
7
+ *
8
+ * 1. **Check which modules are loaded**: Uses Performance API to determine which entry points
9
+ * from the package are actually loaded on the current page.
10
+ *
11
+ * 2. **Re-import updated modules**: Dynamically imports the new versions of loaded modules
12
+ * using their updated bundle URLs (with new hash).
13
+ *
14
+ * 3. **Trigger React Refresh**: If React Refresh is available, triggers component updates
15
+ * while preserving component state. Falls back to full page reload otherwise.
16
+ *
17
+ * The process ensures:
18
+ * - Only relevant modules are updated (skip modules not loaded on current page)
19
+ * - React component state is preserved when possible
20
+ * - Graceful fallback to full reload if React Refresh fails
21
+ *
22
+ * @param data - The package update payload containing package name, version, and entry points
23
+ *
24
+ * @example
25
+ * // This is typically called by the WebSocket message handler:
26
+ * socket.on('package-update', (data) => {
27
+ * await handlePackageUpdate(data);
28
+ * });
29
+ */
30
+ export const handlePackageUpdate = async (data) => {
31
+ const { packageName, entryPoints, version } = data;
32
+ try {
33
+ console.log(`[Cloudpack HMR] Package updated: ${packageName}@${version}`);
34
+ // Get all loaded resources for checking
35
+ const normalizedResources = performance.getEntriesByType('resource').map((r) => removeHashFromUrl(r.name));
36
+ // Process each entry point
37
+ let loadedCount = 0;
38
+ for (const { importPath, bundleUrl } of entryPoints) {
39
+ // Check if this module was actually loaded using Performance API
40
+ // bundleUrl already has the new hash: http://localhost:5500/pkg@1.0.0/h-abc123-1234567890/v1.2/bundled/lib/file.js
41
+ // We normalize both URLs by removing the hash to compare them
42
+ const normalizedBundleUrl = removeHashFromUrl(bundleUrl);
43
+ const wasLoaded = normalizedResources.some((r) => r === normalizedBundleUrl);
44
+ if (!wasLoaded) {
45
+ console.log(`[Cloudpack HMR] Skipping ${importPath} - not loaded on this page`);
46
+ continue;
47
+ }
48
+ console.log(`[Cloudpack HMR] Loading ${importPath} from ${bundleUrl}`);
49
+ // Dynamic import - use webpackIgnore to bypass bundler's import analysis
50
+ // This ensures we use the browser's native import() for runtime URL
51
+ await import(/* webpackIgnore: true */ bundleUrl);
52
+ loadedCount++;
53
+ }
54
+ if (loadedCount === 0) {
55
+ console.log(`[Cloudpack HMR] No entry points from ${packageName} were loaded on this page`);
56
+ return;
57
+ }
58
+ // ===== Trigger React Refresh =====
59
+ //
60
+ // React Refresh is a hot reloading feature that updates React components without losing state.
61
+ // It allows developers to see component changes instantly while preserving:
62
+ // - Component state (useState, useReducer)
63
+ // - Form inputs
64
+ // - Scroll position
65
+ // - Any other runtime state
66
+ //
67
+ // How it works:
68
+ // 1. When modules are re-imported above, React Refresh automatically detects changed components
69
+ // 2. Components are registered via $RefreshReg$ calls (injected by the bundler during build)
70
+ // 3. Calling performReactRefresh() re-renders the registered components with new code
71
+ // 4. React's reconciliation preserves state by matching component types and positions
72
+ //
73
+ // The $RefreshRuntime$ global is initialized in registerReactRefresh.ts
74
+ if (window.$RefreshRuntime$?.performReactRefresh) {
75
+ // Perform the actual refresh - this will update all components that were re-registered
76
+ // during the dynamic import above, while preserving their state
77
+ const refreshResult = window.$RefreshRuntime$.performReactRefresh();
78
+ if (refreshResult === null) {
79
+ // Refresh returned null - this indicates no components were registered
80
+ // This shouldn't happen if we successfully imported modules, so we fall back to full reload
81
+ console.warn(`[Cloudpack HMR] React Refresh returned null despite registrations, reloading page`);
82
+ window.location.reload();
83
+ }
84
+ else {
85
+ // React components successfully updated with state preservation
86
+ // refreshResult contains metadata about what was updated
87
+ console.log(`[Cloudpack HMR] ✓ Updated ${packageName}@${version}`, refreshResult);
88
+ }
89
+ }
90
+ else {
91
+ // React Refresh runtime is not available
92
+ // This happens when:
93
+ // - React Refresh wasn't initialized (registerReactRefresh.ts not called)
94
+ // - The app doesn't use React
95
+ // - React Refresh was disabled
96
+ // Fall back to full page reload to show the changes
97
+ console.warn(`[Cloudpack HMR] React Refresh runtime not found, reloading page`);
98
+ window.location.reload();
99
+ }
100
+ }
101
+ catch (error) {
102
+ console.error(`[Cloudpack HMR] ✗ Failed to update ${packageName}:`, error);
103
+ window.location.reload();
104
+ }
105
+ };
106
+ //# sourceMappingURL=handlePackageUpdate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlePackageUpdate.js","sourceRoot":"","sources":["../src/handlePackageUpdate.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PackageUpdatePayload } from '@ms-cloudpack/api-server/browser';\nimport { removeHashFromUrl } from '@ms-cloudpack/path-string-parsing';\n\n/**\n * Handles hot module replacement (HMR) updates for packages.\n *\n * This function is called when the development server notifies the client that a package\n * has been updated. It performs the following steps:\n *\n * 1. **Check which modules are loaded**: Uses Performance API to determine which entry points\n * from the package are actually loaded on the current page.\n *\n * 2. **Re-import updated modules**: Dynamically imports the new versions of loaded modules\n * using their updated bundle URLs (with new hash).\n *\n * 3. **Trigger React Refresh**: If React Refresh is available, triggers component updates\n * while preserving component state. Falls back to full page reload otherwise.\n *\n * The process ensures:\n * - Only relevant modules are updated (skip modules not loaded on current page)\n * - React component state is preserved when possible\n * - Graceful fallback to full reload if React Refresh fails\n *\n * @param data - The package update payload containing package name, version, and entry points\n *\n * @example\n * // This is typically called by the WebSocket message handler:\n * socket.on('package-update', (data) => {\n * await handlePackageUpdate(data);\n * });\n */\nexport const handlePackageUpdate = async (data: unknown): Promise<void> => {\n const { packageName, entryPoints, version } = data as PackageUpdatePayload;\n\n try {\n console.log(`[Cloudpack HMR] Package updated: ${packageName}@${version}`);\n\n // Get all loaded resources for checking\n const normalizedResources = (performance.getEntriesByType('resource') as PerformanceResourceTiming[]).map((r) =>\n removeHashFromUrl(r.name),\n );\n\n // Process each entry point\n let loadedCount = 0;\n for (const { importPath, bundleUrl } of entryPoints) {\n // Check if this module was actually loaded using Performance API\n // bundleUrl already has the new hash: http://localhost:5500/pkg@1.0.0/h-abc123-1234567890/v1.2/bundled/lib/file.js\n // We normalize both URLs by removing the hash to compare them\n const normalizedBundleUrl = removeHashFromUrl(bundleUrl);\n const wasLoaded = normalizedResources.some((r) => r === normalizedBundleUrl);\n\n if (!wasLoaded) {\n console.log(`[Cloudpack HMR] Skipping ${importPath} - not loaded on this page`);\n continue;\n }\n\n console.log(`[Cloudpack HMR] Loading ${importPath} from ${bundleUrl}`);\n\n // Dynamic import - use webpackIgnore to bypass bundler's import analysis\n // This ensures we use the browser's native import() for runtime URL\n await import(/* webpackIgnore: true */ bundleUrl);\n loadedCount++;\n }\n\n if (loadedCount === 0) {\n console.log(`[Cloudpack HMR] No entry points from ${packageName} were loaded on this page`);\n return;\n }\n\n // ===== Trigger React Refresh =====\n //\n // React Refresh is a hot reloading feature that updates React components without losing state.\n // It allows developers to see component changes instantly while preserving:\n // - Component state (useState, useReducer)\n // - Form inputs\n // - Scroll position\n // - Any other runtime state\n //\n // How it works:\n // 1. When modules are re-imported above, React Refresh automatically detects changed components\n // 2. Components are registered via $RefreshReg$ calls (injected by the bundler during build)\n // 3. Calling performReactRefresh() re-renders the registered components with new code\n // 4. React's reconciliation preserves state by matching component types and positions\n //\n // The $RefreshRuntime$ global is initialized in registerReactRefresh.ts\n if (window.$RefreshRuntime$?.performReactRefresh) {\n // Perform the actual refresh - this will update all components that were re-registered\n // during the dynamic import above, while preserving their state\n const refreshResult = window.$RefreshRuntime$.performReactRefresh();\n\n if (refreshResult === null) {\n // Refresh returned null - this indicates no components were registered\n // This shouldn't happen if we successfully imported modules, so we fall back to full reload\n console.warn(`[Cloudpack HMR] React Refresh returned null despite registrations, reloading page`);\n window.location.reload();\n } else {\n // React components successfully updated with state preservation\n // refreshResult contains metadata about what was updated\n console.log(`[Cloudpack HMR] ✓ Updated ${packageName}@${version}`, refreshResult);\n }\n } else {\n // React Refresh runtime is not available\n // This happens when:\n // - React Refresh wasn't initialized (registerReactRefresh.ts not called)\n // - The app doesn't use React\n // - React Refresh was disabled\n // Fall back to full page reload to show the changes\n console.warn(`[Cloudpack HMR] React Refresh runtime not found, reloading page`);\n window.location.reload();\n }\n } catch (error) {\n console.error(`[Cloudpack HMR] ✗ Failed to update ${packageName}:`, error);\n window.location.reload();\n }\n};\n"]}
package/lib/index.js CHANGED
@@ -4,7 +4,8 @@ import { CloudpackProvider } from './components/CloudpackProvider/CloudpackProvi
4
4
  import { Overlay } from './components/Overlay/Overlay.js';
5
5
  import { ThemeProvider } from './components/ThemeProvider/ThemeProvider.js';
6
6
  import { elementIds } from './constants.js';
7
- import { createCloudpackClient, reloadCountSource } from '@ms-cloudpack/api-server/browser';
7
+ import { createCloudpackClient, reloadCountSource, packageUpdateSource } from '@ms-cloudpack/api-server/browser';
8
+ import { handlePackageUpdate } from './handlePackageUpdate.js';
8
9
  async function start() {
9
10
  if (!window.__cloudpack) {
10
11
  throw new Error('Cloudpack not found on window');
@@ -13,7 +14,7 @@ async function start() {
13
14
  if (!pageSessionContext) {
14
15
  throw new Error('Session context not found on window.__cloudpack');
15
16
  }
16
- const { apiUrl, currentSequence, sessionId, showOverlay } = pageSessionContext;
17
+ const { apiUrl, currentSequence, sessionId, showOverlay, features } = pageSessionContext;
17
18
  // injectScripts shouldn't inject the overlay if it's disabled, but check here too
18
19
  if (showOverlay === 'never') {
19
20
  return;
@@ -38,6 +39,12 @@ async function start() {
38
39
  });
39
40
  },
40
41
  });
42
+ // Subscribe to HMR package updates
43
+ if (features?.hmr) {
44
+ const { registerReactRefresh } = await import('./registerReactRefresh.js');
45
+ registerReactRefresh();
46
+ client.onDataChanged.subscribe(packageUpdateSource, { onData: (data) => void handlePackageUpdate(data) });
47
+ }
41
48
  client.onDataChanged.subscribe(reloadCountSource, {
42
49
  onData: (data) => {
43
50
  if (Number(data) > currentSequence) {
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qDAAqD,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAE5F,KAAK,UAAU,KAAK;IAClB,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;IAElD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,kBAAkB,CAAC;IAE/E,kFAAkF;IAClF,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC;QACzC,GAAG,EAAE,MAAM;QACX,MAAM,EAAE,GAAG,EAAE;YACX,MAAM,CAAC,YAAY;iBAChB,KAAK,EAAE;iBACP,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE;gBACrB,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;oBAC/B,OAAO,CAAC,GAAG,CAAC,wCAAwC,EAAE,SAAS,CAAC,CAAC;gBACnE,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;oBAChG,iGAAiG;oBACjG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC3B,CAAC;YACH,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACb,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;QACP,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,iBAAiB,EAAE;QAChD,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACf,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,EAAE,CAAC;gBACnC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC;IAE7B,MAAM,CACJ,KAAC,aAAa,cACZ,KAAC,iBAAiB,IAAC,MAAM,EAAE,MAAM,YAC/B,KAAC,OAAO,KAAG,GACO,GACN,EAChB,OAAO,CACR,CAAC;IAEF,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,KAAK,KAAK,EAAE,CAAC","sourcesContent":["import { render } from 'preact';\nimport { CloudpackProvider } from './components/CloudpackProvider/CloudpackProvider.js';\nimport { Overlay } from './components/Overlay/Overlay.js';\nimport { ThemeProvider } from './components/ThemeProvider/ThemeProvider.js';\nimport { elementIds } from './constants.js';\nimport { createCloudpackClient, reloadCountSource } from '@ms-cloudpack/api-server/browser';\n\nasync function start(): Promise<void> {\n if (!window.__cloudpack) {\n throw new Error('Cloudpack not found on window');\n }\n\n const { pageSessionContext } = window.__cloudpack;\n\n if (!pageSessionContext) {\n throw new Error('Session context not found on window.__cloudpack');\n }\n\n const { apiUrl, currentSequence, sessionId, showOverlay } = pageSessionContext;\n\n // injectScripts shouldn't inject the overlay if it's disabled, but check here too\n if (showOverlay === 'never') {\n return;\n }\n\n const client = await createCloudpackClient({\n url: apiUrl,\n onOpen: () => {\n client.getSessionId\n .query()\n .then((newSessionId) => {\n if (sessionId === newSessionId) {\n console.log('[Cloudpack] socket opened, session Id:', sessionId);\n } else {\n console.warn('[Cloudpack] session ID mismatch, expected:', sessionId, 'but got:', newSessionId);\n // One possible reason for this is that the config has changed and the page needs to be reloaded.\n window.location.reload();\n }\n })\n .catch((err) => {\n console.error('[Cloudpack] Error getting session Id:', err);\n });\n },\n });\n\n client.onDataChanged.subscribe(reloadCountSource, {\n onData: (data) => {\n if (Number(data) > currentSequence) {\n window.location.reload();\n }\n },\n });\n\n const rootDiv = document.createElement('div');\n rootDiv.id = elementIds.root;\n\n render(\n <ThemeProvider>\n <CloudpackProvider client={client}>\n <Overlay />\n </CloudpackProvider>\n </ThemeProvider>,\n rootDiv,\n );\n\n document.body.appendChild(rootDiv);\n}\n\nvoid start();\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import { render } from 'preact';\nimport { CloudpackProvider } from './components/CloudpackProvider/CloudpackProvider.js';\nimport { Overlay } from './components/Overlay/Overlay.js';\nimport { ThemeProvider } from './components/ThemeProvider/ThemeProvider.js';\nimport { elementIds } from './constants.js';\nimport { createCloudpackClient, reloadCountSource, packageUpdateSource } from '@ms-cloudpack/api-server/browser';\nimport { handlePackageUpdate } from './handlePackageUpdate.js';\n\nasync function start(): Promise<void> {\n if (!window.__cloudpack) {\n throw new Error('Cloudpack not found on window');\n }\n\n const { pageSessionContext } = window.__cloudpack;\n\n if (!pageSessionContext) {\n throw new Error('Session context not found on window.__cloudpack');\n }\n\n const { apiUrl, currentSequence, sessionId, showOverlay, features } = pageSessionContext;\n\n // injectScripts shouldn't inject the overlay if it's disabled, but check here too\n if (showOverlay === 'never') {\n return;\n }\n\n const client = await createCloudpackClient({\n url: apiUrl,\n onOpen: () => {\n client.getSessionId\n .query()\n .then((newSessionId) => {\n if (sessionId === newSessionId) {\n console.log('[Cloudpack] socket opened, session Id:', sessionId);\n } else {\n console.warn('[Cloudpack] session ID mismatch, expected:', sessionId, 'but got:', newSessionId);\n // One possible reason for this is that the config has changed and the page needs to be reloaded.\n window.location.reload();\n }\n })\n .catch((err) => {\n console.error('[Cloudpack] Error getting session Id:', err);\n });\n },\n });\n\n // Subscribe to HMR package updates\n if (features?.hmr) {\n const { registerReactRefresh } = await import('./registerReactRefresh.js');\n registerReactRefresh();\n client.onDataChanged.subscribe(packageUpdateSource, { onData: (data) => void handlePackageUpdate(data) });\n }\n client.onDataChanged.subscribe(reloadCountSource, {\n onData: (data) => {\n if (Number(data) > currentSequence) {\n window.location.reload();\n }\n },\n });\n\n const rootDiv = document.createElement('div');\n rootDiv.id = elementIds.root;\n\n render(\n <ThemeProvider>\n <CloudpackProvider client={client}>\n <Overlay />\n </CloudpackProvider>\n </ThemeProvider>,\n rootDiv,\n );\n\n document.body.appendChild(rootDiv);\n}\n\nvoid start();\n"]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Initializes the React Refresh runtime for hot module replacement (HMR).
3
+ *
4
+ * React Refresh enables fast refresh of React components without losing their state.
5
+ * This function sets up the necessary global hooks and functions that the bundler-transformed
6
+ * code will use to register components and trigger updates.
7
+ *
8
+ * This should be called once during application initialization, before any React components are loaded.
9
+ *
10
+ * @example
11
+ * // In your app entry point:
12
+ * import { registerReactRefresh } from '@ms-cloudpack/overlay';
13
+ * registerReactRefresh();
14
+ */
15
+ export declare const registerReactRefresh: () => void;
16
+ //# sourceMappingURL=registerReactRefresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerReactRefresh.d.ts","sourceRoot":"","sources":["../src/registerReactRefresh.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,QAAO,IAkEvC,CAAC"}
@@ -0,0 +1,79 @@
1
+ import RefreshRuntime from 'react-refresh';
2
+ /**
3
+ * Initializes the React Refresh runtime for hot module replacement (HMR).
4
+ *
5
+ * React Refresh enables fast refresh of React components without losing their state.
6
+ * This function sets up the necessary global hooks and functions that the bundler-transformed
7
+ * code will use to register components and trigger updates.
8
+ *
9
+ * This should be called once during application initialization, before any React components are loaded.
10
+ *
11
+ * @example
12
+ * // In your app entry point:
13
+ * import { registerReactRefresh } from '@ms-cloudpack/overlay';
14
+ * registerReactRefresh();
15
+ */
16
+ export const registerReactRefresh = () => {
17
+ // Initialize React Refresh by injecting into React's internals
18
+ // This hooks into React's reconciler to enable hot reloading capabilities
19
+ // It modifies the global React DevTools hook to track component updates
20
+ RefreshRuntime.injectIntoGlobalHook(window);
21
+ // Set up the component registration function
22
+ // This function is called by bundler-injected code for every React component/hook
23
+ //
24
+ // Example of what the bundler transforms:
25
+ // Original code:
26
+ // export const MyComponent = () => <div>Hello</div>
27
+ //
28
+ // Transformed code:
29
+ // export const MyComponent = () => <div>Hello</div>
30
+ // $RefreshReg$(MyComponent, 'MyComponent');
31
+ //
32
+ // The registration allows React Refresh to:
33
+ // - Track which components exist in the module
34
+ // - Match old and new versions of components during updates
35
+ // - Determine if a full reload is needed (e.g., if hooks changed)
36
+ window.$RefreshReg$ = (type, id) => {
37
+ // TODO: Make this fully qualified with id including package name to avoid collisions
38
+ // Currently, if two packages export a component with the same name, they could collide
39
+ // Example collision: '@pkg-a/MyComponent' and '@pkg-b/MyComponent' both register as 'MyComponent'
40
+ RefreshRuntime.register(type, id);
41
+ };
42
+ // Set up the signature function for tracking hook changes
43
+ // This is used to detect when hooks in a component have changed
44
+ //
45
+ // Example of what the bundler transforms:
46
+ // Original code:
47
+ // const MyComponent = () => {
48
+ // const [count, setCount] = useState(0);
49
+ // return <div>{count}</div>
50
+ // }
51
+ //
52
+ // Transformed code:
53
+ // var _s = $RefreshSig$();
54
+ // const MyComponent = () => {
55
+ // _s(); // Signature call to track hooks
56
+ // const [count, setCount] = useState(0);
57
+ // return <div>{count}</div>
58
+ // }
59
+ // _s(MyComponent, "useState{count}");
60
+ //
61
+ // If hook signatures change (e.g., adding/removing useState), React Refresh will:
62
+ // - Detect the change via the signature mismatch
63
+ // - Force a full remount of the component (state will be lost)
64
+ // - Warn the developer about the limitation
65
+ window.$RefreshSig$ = () => {
66
+ return RefreshRuntime.createSignatureFunctionForTransform();
67
+ };
68
+ // Store the runtime globally for manual refresh triggering
69
+ // This is used by handlePackageUpdate.ts to call performReactRefresh()
70
+ // after new modules are imported
71
+ //
72
+ // The runtime provides:
73
+ // - performReactRefresh(): Triggers the actual component updates
74
+ // - register(): Called by $RefreshReg$ to track components
75
+ // - createSignatureFunctionForTransform(): Called by $RefreshSig$ to track hooks
76
+ window.$RefreshRuntime$ = RefreshRuntime;
77
+ console.log('[React Refresh] Runtime initialized');
78
+ };
79
+ //# sourceMappingURL=registerReactRefresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerReactRefresh.js","sourceRoot":"","sources":["../src/registerReactRefresh.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,eAAe,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAS,EAAE;IAC7C,+DAA+D;IAC/D,0EAA0E;IAC1E,wEAAwE;IACxE,cAAc,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE5C,6CAA6C;IAC7C,kFAAkF;IAClF,EAAE;IACF,0CAA0C;IAC1C,iBAAiB;IACjB,sDAAsD;IACtD,EAAE;IACF,oBAAoB;IACpB,sDAAsD;IACtD,8CAA8C;IAC9C,EAAE;IACF,4CAA4C;IAC5C,+CAA+C;IAC/C,4DAA4D;IAC5D,kEAAkE;IAClE,MAAM,CAAC,YAAY,GAAG,CAAC,IAAa,EAAE,EAAU,EAAE,EAAE;QAClD,qFAAqF;QACrF,uFAAuF;QACvF,kGAAkG;QAClG,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC;IAEF,0DAA0D;IAC1D,gEAAgE;IAChE,EAAE;IACF,0CAA0C;IAC1C,iBAAiB;IACjB,gCAAgC;IAChC,6CAA6C;IAC7C,gCAAgC;IAChC,MAAM;IACN,EAAE;IACF,oBAAoB;IACpB,6BAA6B;IAC7B,gCAAgC;IAChC,8CAA8C;IAC9C,6CAA6C;IAC7C,gCAAgC;IAChC,MAAM;IACN,wCAAwC;IACxC,EAAE;IACF,kFAAkF;IAClF,iDAAiD;IACjD,+DAA+D;IAC/D,4CAA4C;IAC5C,MAAM,CAAC,YAAY,GAAG,GAAG,EAAE;QACzB,OAAO,cAAc,CAAC,mCAAmC,EAAE,CAAC;IAC9D,CAAC,CAAC;IAEF,2DAA2D;IAC3D,uEAAuE;IACvE,iCAAiC;IACjC,EAAE;IACF,wBAAwB;IACxB,iEAAiE;IACjE,2DAA2D;IAC3D,iFAAiF;IACjF,MAAM,CAAC,gBAAgB,GAAG,cAAc,CAAC;IAEzC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;AACrD,CAAC,CAAC","sourcesContent":["import RefreshRuntime from 'react-refresh';\n\n/**\n * Initializes the React Refresh runtime for hot module replacement (HMR).\n *\n * React Refresh enables fast refresh of React components without losing their state.\n * This function sets up the necessary global hooks and functions that the bundler-transformed\n * code will use to register components and trigger updates.\n *\n * This should be called once during application initialization, before any React components are loaded.\n *\n * @example\n * // In your app entry point:\n * import { registerReactRefresh } from '@ms-cloudpack/overlay';\n * registerReactRefresh();\n */\nexport const registerReactRefresh = (): void => {\n // Initialize React Refresh by injecting into React's internals\n // This hooks into React's reconciler to enable hot reloading capabilities\n // It modifies the global React DevTools hook to track component updates\n RefreshRuntime.injectIntoGlobalHook(window);\n\n // Set up the component registration function\n // This function is called by bundler-injected code for every React component/hook\n //\n // Example of what the bundler transforms:\n // Original code:\n // export const MyComponent = () => <div>Hello</div>\n //\n // Transformed code:\n // export const MyComponent = () => <div>Hello</div>\n // $RefreshReg$(MyComponent, 'MyComponent');\n //\n // The registration allows React Refresh to:\n // - Track which components exist in the module\n // - Match old and new versions of components during updates\n // - Determine if a full reload is needed (e.g., if hooks changed)\n window.$RefreshReg$ = (type: unknown, id: string) => {\n // TODO: Make this fully qualified with id including package name to avoid collisions\n // Currently, if two packages export a component with the same name, they could collide\n // Example collision: '@pkg-a/MyComponent' and '@pkg-b/MyComponent' both register as 'MyComponent'\n RefreshRuntime.register(type, id);\n };\n\n // Set up the signature function for tracking hook changes\n // This is used to detect when hooks in a component have changed\n //\n // Example of what the bundler transforms:\n // Original code:\n // const MyComponent = () => {\n // const [count, setCount] = useState(0);\n // return <div>{count}</div>\n // }\n //\n // Transformed code:\n // var _s = $RefreshSig$();\n // const MyComponent = () => {\n // _s(); // Signature call to track hooks\n // const [count, setCount] = useState(0);\n // return <div>{count}</div>\n // }\n // _s(MyComponent, \"useState{count}\");\n //\n // If hook signatures change (e.g., adding/removing useState), React Refresh will:\n // - Detect the change via the signature mismatch\n // - Force a full remount of the component (state will be lost)\n // - Warn the developer about the limitation\n window.$RefreshSig$ = () => {\n return RefreshRuntime.createSignatureFunctionForTransform();\n };\n\n // Store the runtime globally for manual refresh triggering\n // This is used by handlePackageUpdate.ts to call performReactRefresh()\n // after new modules are imported\n //\n // The runtime provides:\n // - performReactRefresh(): Triggers the actual component updates\n // - register(): Called by $RefreshReg$ to track components\n // - createSignatureFunctionForTransform(): Called by $RefreshSig$ to track hooks\n window.$RefreshRuntime$ = RefreshRuntime;\n\n console.log('[React Refresh] Runtime initialized');\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ms-cloudpack/overlay",
3
- "version": "0.19.56",
3
+ "version": "0.19.57",
4
4
  "description": "The Cloudpack overlay UX",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,16 +29,18 @@
29
29
  "prepack": "cp .npmignore dist/.npmignore"
30
30
  },
31
31
  "devDependencies": {
32
- "@ms-cloudpack/api-server": "^0.65.14",
33
- "@ms-cloudpack/common-types": "^0.33.1",
34
- "@ms-cloudpack/common-types-browser": "^0.6.4",
32
+ "@ms-cloudpack/api-server": "^0.66.0",
33
+ "@ms-cloudpack/common-types": "^0.33.2",
34
+ "@ms-cloudpack/common-types-browser": "^0.6.5",
35
35
  "@ms-cloudpack/eslint-plugin-internal": "^0.0.1",
36
- "@ms-cloudpack/path-string-parsing": "^1.2.7",
36
+ "@ms-cloudpack/path-string-parsing": "^1.3.0",
37
37
  "@ms-cloudpack/scripts": "^0.0.1",
38
+ "@types/react-refresh": "^0.14.0",
38
39
  "classnames": "^2.5.1",
39
40
  "preact": "^10.26.8",
40
41
  "react": "npm:@preact/compat@^18.0.0",
41
- "react-focus-on": "^3.10.0"
42
+ "react-focus-on": "^3.10.0",
43
+ "react-refresh": "patch:react-refresh@npm%3A0.18.0#~/.yarn/patches/react-refresh-npm-0.18.0-5576c3f4a3.patch"
42
44
  },
43
45
  "files": [
44
46
  "lib/**/!(*.test.*)",