@pixpilot/chrome-lifecycle 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -18
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -42,45 +42,45 @@ Tracks whether side panels are visible or hidden across different windows.
|
|
|
42
42
|
|
|
43
43
|
#### Setup
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
This feature requires initialization in both your background script and side panel script.
|
|
46
|
+
|
|
47
|
+
**1. Background script (service worker):**
|
|
48
|
+
|
|
49
|
+
Call `initSidePanelStateManager()` at the top of your background script, before any other side panel functions. All other functions (`getSidePanelStateForWindow`, `isWindowSidePanelVisible`, `onSidePanelStateChange`) will throw an error if called before initialization.
|
|
46
50
|
|
|
47
51
|
```typescript
|
|
52
|
+
// background.ts
|
|
48
53
|
import { initSidePanelStateManager } from '@pixpilot/chrome-lifecycle';
|
|
49
54
|
|
|
50
|
-
//
|
|
55
|
+
// ⚠️ Critical Setup
|
|
56
|
+
// Must be called first, before any other side panel functions
|
|
51
57
|
initSidePanelStateManager();
|
|
58
|
+
|
|
59
|
+
// Now you can use other functions
|
|
52
60
|
```
|
|
53
61
|
|
|
54
|
-
**Side panel script (frontend):**
|
|
62
|
+
**2. Side panel script (frontend):**
|
|
63
|
+
|
|
64
|
+
Call `initializeSidePanelStateTracker()` when your side panel loads. This sets up visibility tracking and a heartbeat to keep the connection alive.
|
|
55
65
|
|
|
56
66
|
```typescript
|
|
67
|
+
// sidepanel.ts
|
|
57
68
|
import { initializeSidePanelStateTracker } from '@pixpilot/chrome-lifecycle';
|
|
58
69
|
|
|
59
|
-
// Initialize when side panel loads
|
|
60
70
|
const cleanup = initializeSidePanelStateTracker();
|
|
71
|
+
|
|
72
|
+
// Optional: call cleanup() when done to remove listeners and disconnect
|
|
61
73
|
```
|
|
62
74
|
|
|
63
75
|
#### Functions
|
|
64
76
|
|
|
65
77
|
##### `initSidePanelStateManager()`
|
|
66
78
|
|
|
67
|
-
Initializes the backend state manager. Must be called once
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import { initSidePanelStateManager } from '@pixpilot/chrome-lifecycle';
|
|
71
|
-
|
|
72
|
-
initSidePanelStateManager();
|
|
73
|
-
```
|
|
79
|
+
Initializes the backend state manager. **Must be called once at the top of your background script before using any other side panel functions.** Subsequent calls log a warning and are ignored.
|
|
74
80
|
|
|
75
81
|
##### `initializeSidePanelStateTracker()`
|
|
76
82
|
|
|
77
|
-
Initializes the frontend tracker in your side panel. Sets up visibility
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
import { initializeSidePanelStateTracker } from '@pixpilot/chrome-lifecycle';
|
|
81
|
-
|
|
82
|
-
const cleanup = initializeSidePanelStateTracker();
|
|
83
|
-
```
|
|
83
|
+
Initializes the frontend tracker in your side panel. Sets up visibility change detection and a heartbeat (every 15 seconds) to maintain the connection.
|
|
84
84
|
|
|
85
85
|
**Returns:** Cleanup function to remove listeners and disconnect
|
|
86
86
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=new Map;let t=!1;function n(){t||(t=!0,chrome.windows.onRemoved.addListener(t=>{let n=e.get(t);n&&(n.forEach(e=>{e()}),e.delete(t))}))}function r(t,r){n();let i=e.get(t);return i||(i=new Set,e.set(t,i)),i.add(r),()=>{let n=e.get(t);n&&(n.delete(r),n.size===0&&e.delete(t))}}const i=15e3;let a=!1;function o(){a&&console.warn(`Side panel state tracker already initialized`),a=!0;let e,t,n;return chrome.windows.getCurrent(r=>{if(r.id==null){console.error(`[side-panel-state-tracker] Could not get window ID`);return}e=chrome.runtime.connect({name:chrome.runtime.id});let i=r.id;function a(t){try{e.postMessage({...t,windowId:i,type:`side-panel-state-tracker`,timestamp:Date.now()})}catch(e){console.error(`[side-panel-state-tracker] Failed to send message:`,e)}}t=setInterval(()=>{try{e.postMessage({type:`side-panel-heartbeat`,windowId:i,timestamp:Date.now()})}catch(e){console.error(`[side-panel-state-tracker] Heartbeat failed:`,e),t&&clearInterval(t)}},15e3),n=()=>{a({state:document.hidden?`hidden`:`visible`,reason:`visibility-change`})},document.addEventListener(`visibilitychange`,n),e.onDisconnect.addListener(()=>{console.warn(`[side-panel-state-tracker] Background connection lost`),t&&clearInterval(t)}),e.onMessage.addListener(e=>{e.type===`close-side-panel`&&(t&&clearInterval(t),window.close())}),a({state:document.hidden?`hidden`:`visible`,reason:`document-load`})}),()=>{t&&clearInterval(t),n&&document.removeEventListener(`visibilitychange`,n),e&&e.disconnect(),a=!1}}const s=new Map,c=new Set;let l=!1;function u(){
|
|
1
|
+
const e=new Map;let t=!1;function n(){t||(t=!0,chrome.windows.onRemoved.addListener(t=>{let n=e.get(t);n&&(n.forEach(e=>{e()}),e.delete(t))}))}function r(t,r){n();let i=e.get(t);return i||(i=new Set,e.set(t,i)),i.add(r),()=>{let n=e.get(t);n&&(n.delete(r),n.size===0&&e.delete(t))}}const i=15e3;let a=!1;function o(){a&&console.warn(`Side panel state tracker already initialized`),a=!0;let e,t,n;return chrome.windows.getCurrent(r=>{if(r.id==null){console.error(`[side-panel-state-tracker] Could not get window ID`);return}e=chrome.runtime.connect({name:chrome.runtime.id});let i=r.id;function a(t){try{e.postMessage({...t,windowId:i,type:`side-panel-state-tracker`,timestamp:Date.now()})}catch(e){console.error(`[side-panel-state-tracker] Failed to send message:`,e)}}t=setInterval(()=>{try{e.postMessage({type:`side-panel-heartbeat`,windowId:i,timestamp:Date.now()})}catch(e){console.error(`[side-panel-state-tracker] Heartbeat failed:`,e),t&&clearInterval(t)}},15e3),n=()=>{a({state:document.hidden?`hidden`:`visible`,reason:`visibility-change`})},document.addEventListener(`visibilitychange`,n),e.onDisconnect.addListener(()=>{console.warn(`[side-panel-state-tracker] Background connection lost`),t&&clearInterval(t)}),e.onMessage.addListener(e=>{e.type===`close-side-panel`&&(t&&clearInterval(t),window.close())}),a({state:document.hidden?`hidden`:`visible`,reason:`document-load`})}),()=>{t&&clearInterval(t),n&&document.removeEventListener(`visibilitychange`,n),e&&e.disconnect(),a=!1}}const s=new Map,c=new Set;let l=!1;function u(){l||console.error(`Side panel state manager is not initialized.`,`Call initSidePanelStateManager() at the top of your background script before using any other functions.`)}function d(){l||(l=!0,chrome.action.onClicked.addListener(e=>{let t=s.get(e.windowId);t&&t.state===`visible`?t.port&&(s.delete(e.windowId),t.port.postMessage({type:`close-side-panel`})):chrome.sidePanel.open({windowId:e.windowId}).catch(console.error)}),chrome.runtime.onConnect.addListener(e=>{e.name===chrome.runtime.id&&(e.onMessage.addListener(t=>{t.type===`side-panel-state-tracker`&&t.state&&p({port:e,state:t.state,reason:t.reason??`unknown`,windowId:t.windowId,type:t.type})}),e.onDisconnect.addListener(e=>{Array.from(s.entries()).forEach(([t,n])=>{n.port&&n.port===e&&p({port:void 0,state:`hidden`,reason:`port-disconnected`,windowId:t,type:`side-panel-state-tracker`})})}))}))}function f(e){if(e.type!==`side-panel-state-tracker`)return;let t={state:e.state,reason:e.reason,windowId:e.windowId};c.forEach(e=>{try{e(t)}catch(e){console.error(`Error in side panel state listener:`,e)}})}function p(e){let{windowId:t,state:n}=e;if(n===`hidden`){s.delete(t),f(e);return}s.set(t,e),f(e)}function m(e){return u(),s.get(e)?.state}function h(e){return u(),m(e)===`visible`}function g(e){return u(),c.add(e),()=>{c.delete(e)}}exports.getSidePanelStateForWindow=m,exports.initSidePanelStateManager=d,exports.initializeSidePanelStateTracker=o,exports.isWindowSidePanelVisible=h,exports.onSidePanelStateChange=g,exports.onWindowClose=r;
|
package/dist/index.d.cts
CHANGED
|
@@ -38,7 +38,6 @@ type SidePanelStateChangeData = Omit<SidePanelStateData, 'timestamp' | 'type'>;
|
|
|
38
38
|
interface SidePanelClientMessage {
|
|
39
39
|
type: 'close-side-panel';
|
|
40
40
|
}
|
|
41
|
-
type SidePanelTabTypes = 'insights' | 'history' | 'settings';
|
|
42
41
|
//#endregion
|
|
43
42
|
//#region src/sidepanel-state-manager.d.ts
|
|
44
43
|
type SidePanelStateListener = (data: SidePanelStateChangeData) => void;
|
|
@@ -61,4 +60,4 @@ declare function isWindowSidePanelVisible(windowId: number): boolean;
|
|
|
61
60
|
*/
|
|
62
61
|
declare function onSidePanelStateChange(listener: SidePanelStateListener): () => void;
|
|
63
62
|
//#endregion
|
|
64
|
-
export { SidePanelClientMessage, SidePanelState, SidePanelStateChangeData, SidePanelStateData,
|
|
63
|
+
export { SidePanelClientMessage, SidePanelState, SidePanelStateChangeData, SidePanelStateData, getSidePanelStateForWindow, initSidePanelStateManager, initializeSidePanelStateTracker, isWindowSidePanelVisible, onSidePanelStateChange, onWindowClose };
|
package/dist/index.d.ts
CHANGED
|
@@ -38,7 +38,6 @@ type SidePanelStateChangeData = Omit<SidePanelStateData, 'timestamp' | 'type'>;
|
|
|
38
38
|
interface SidePanelClientMessage {
|
|
39
39
|
type: 'close-side-panel';
|
|
40
40
|
}
|
|
41
|
-
type SidePanelTabTypes = 'insights' | 'history' | 'settings';
|
|
42
41
|
//#endregion
|
|
43
42
|
//#region src/sidepanel-state-manager.d.ts
|
|
44
43
|
type SidePanelStateListener = (data: SidePanelStateChangeData) => void;
|
|
@@ -61,4 +60,4 @@ declare function isWindowSidePanelVisible(windowId: number): boolean;
|
|
|
61
60
|
*/
|
|
62
61
|
declare function onSidePanelStateChange(listener: SidePanelStateListener): () => void;
|
|
63
62
|
//#endregion
|
|
64
|
-
export { SidePanelClientMessage, SidePanelState, SidePanelStateChangeData, SidePanelStateData,
|
|
63
|
+
export { SidePanelClientMessage, SidePanelState, SidePanelStateChangeData, SidePanelStateData, getSidePanelStateForWindow, initSidePanelStateManager, initializeSidePanelStateTracker, isWindowSidePanelVisible, onSidePanelStateChange, onWindowClose };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=new Map;let t=!1;function n(){t||(t=!0,chrome.windows.onRemoved.addListener(t=>{let n=e.get(t);n&&(n.forEach(e=>{e()}),e.delete(t))}))}function r(t,r){n();let i=e.get(t);return i||(i=new Set,e.set(t,i)),i.add(r),()=>{let n=e.get(t);n&&(n.delete(r),n.size===0&&e.delete(t))}}let i=!1;function a(){i&&console.warn(`Side panel state tracker already initialized`),i=!0;let e,t,n;return chrome.windows.getCurrent(r=>{if(r.id==null){console.error(`[side-panel-state-tracker] Could not get window ID`);return}e=chrome.runtime.connect({name:chrome.runtime.id});let i=r.id;function a(t){try{e.postMessage({...t,windowId:i,type:`side-panel-state-tracker`,timestamp:Date.now()})}catch(e){console.error(`[side-panel-state-tracker] Failed to send message:`,e)}}t=setInterval(()=>{try{e.postMessage({type:`side-panel-heartbeat`,windowId:i,timestamp:Date.now()})}catch(e){console.error(`[side-panel-state-tracker] Heartbeat failed:`,e),t&&clearInterval(t)}},15e3),n=()=>{a({state:document.hidden?`hidden`:`visible`,reason:`visibility-change`})},document.addEventListener(`visibilitychange`,n),e.onDisconnect.addListener(()=>{console.warn(`[side-panel-state-tracker] Background connection lost`),t&&clearInterval(t)}),e.onMessage.addListener(e=>{e.type===`close-side-panel`&&(t&&clearInterval(t),window.close())}),a({state:document.hidden?`hidden`:`visible`,reason:`document-load`})}),()=>{t&&clearInterval(t),n&&document.removeEventListener(`visibilitychange`,n),e&&e.disconnect(),i=!1}}const o=new Map,s=new Set;let c=!1;function l(){
|
|
1
|
+
const e=new Map;let t=!1;function n(){t||(t=!0,chrome.windows.onRemoved.addListener(t=>{let n=e.get(t);n&&(n.forEach(e=>{e()}),e.delete(t))}))}function r(t,r){n();let i=e.get(t);return i||(i=new Set,e.set(t,i)),i.add(r),()=>{let n=e.get(t);n&&(n.delete(r),n.size===0&&e.delete(t))}}let i=!1;function a(){i&&console.warn(`Side panel state tracker already initialized`),i=!0;let e,t,n;return chrome.windows.getCurrent(r=>{if(r.id==null){console.error(`[side-panel-state-tracker] Could not get window ID`);return}e=chrome.runtime.connect({name:chrome.runtime.id});let i=r.id;function a(t){try{e.postMessage({...t,windowId:i,type:`side-panel-state-tracker`,timestamp:Date.now()})}catch(e){console.error(`[side-panel-state-tracker] Failed to send message:`,e)}}t=setInterval(()=>{try{e.postMessage({type:`side-panel-heartbeat`,windowId:i,timestamp:Date.now()})}catch(e){console.error(`[side-panel-state-tracker] Heartbeat failed:`,e),t&&clearInterval(t)}},15e3),n=()=>{a({state:document.hidden?`hidden`:`visible`,reason:`visibility-change`})},document.addEventListener(`visibilitychange`,n),e.onDisconnect.addListener(()=>{console.warn(`[side-panel-state-tracker] Background connection lost`),t&&clearInterval(t)}),e.onMessage.addListener(e=>{e.type===`close-side-panel`&&(t&&clearInterval(t),window.close())}),a({state:document.hidden?`hidden`:`visible`,reason:`document-load`})}),()=>{t&&clearInterval(t),n&&document.removeEventListener(`visibilitychange`,n),e&&e.disconnect(),i=!1}}const o=new Map,s=new Set;let c=!1;function l(){c||console.error(`Side panel state manager is not initialized.`,`Call initSidePanelStateManager() at the top of your background script before using any other functions.`)}function u(){c||(c=!0,chrome.action.onClicked.addListener(e=>{let t=o.get(e.windowId);t&&t.state===`visible`?t.port&&(o.delete(e.windowId),t.port.postMessage({type:`close-side-panel`})):chrome.sidePanel.open({windowId:e.windowId}).catch(console.error)}),chrome.runtime.onConnect.addListener(e=>{e.name===chrome.runtime.id&&(e.onMessage.addListener(t=>{t.type===`side-panel-state-tracker`&&t.state&&f({port:e,state:t.state,reason:t.reason??`unknown`,windowId:t.windowId,type:t.type})}),e.onDisconnect.addListener(e=>{Array.from(o.entries()).forEach(([t,n])=>{n.port&&n.port===e&&f({port:void 0,state:`hidden`,reason:`port-disconnected`,windowId:t,type:`side-panel-state-tracker`})})}))}))}function d(e){if(e.type!==`side-panel-state-tracker`)return;let t={state:e.state,reason:e.reason,windowId:e.windowId};s.forEach(e=>{try{e(t)}catch(e){console.error(`Error in side panel state listener:`,e)}})}function f(e){let{windowId:t,state:n}=e;if(n===`hidden`){o.delete(t),d(e);return}o.set(t,e),d(e)}function p(e){return l(),o.get(e)?.state}function m(e){return l(),p(e)===`visible`}function h(e){return l(),s.add(e),()=>{s.delete(e)}}export{p as getSidePanelStateForWindow,u as initSidePanelStateManager,a as initializeSidePanelStateTracker,m as isWindowSidePanelVisible,h as onSidePanelStateChange,r as onWindowClose};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixpilot/chrome-lifecycle",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"description": "Lifecycle management utilities for Chrome extensions.",
|
|
6
6
|
"author": "m.doaie <m.doaie@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"tsdown": "^0.15.9",
|
|
31
31
|
"typescript": "^5.9.3",
|
|
32
32
|
"@internal/eslint-config": "0.3.0",
|
|
33
|
-
"@internal/prettier-config": "0.1.0",
|
|
34
|
-
"@internal/tsconfig": "0.1.0",
|
|
35
33
|
"@internal/tsdown-config": "0.1.0",
|
|
36
|
-
"@internal/
|
|
34
|
+
"@internal/prettier-config": "0.1.0",
|
|
35
|
+
"@internal/vitest-config": "0.1.0",
|
|
36
|
+
"@internal/tsconfig": "0.1.0"
|
|
37
37
|
},
|
|
38
38
|
"prettier": "@internal/prettier-config",
|
|
39
39
|
"scripts": {
|