@shellui/sdk 0.0.3 → 0.0.4
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 +3 -2
- package/dist/actions/closeDrawer.d.ts +6 -0
- package/dist/actions/closeDrawer.d.ts.map +1 -0
- package/dist/actions/closeDrawer.js +19 -0
- package/dist/actions/dialog.d.ts +9 -0
- package/dist/actions/dialog.d.ts.map +1 -0
- package/dist/actions/dialog.js +51 -0
- package/dist/actions/openDrawer.d.ts +8 -0
- package/dist/actions/openDrawer.d.ts.map +1 -0
- package/dist/actions/openDrawer.js +27 -0
- package/dist/actions/openModal.d.ts +7 -0
- package/dist/actions/openModal.d.ts.map +1 -0
- package/dist/actions/openModal.js +22 -0
- package/dist/actions/toast.d.ts +9 -0
- package/dist/actions/toast.d.ts.map +1 -0
- package/dist/actions/toast.js +47 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +198 -0
- package/dist/logger/logger.d.ts +7 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.js +175 -0
- package/dist/types.d.ts +131 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/utils/callbackRegistry.d.ts +29 -0
- package/dist/utils/callbackRegistry.d.ts.map +1 -0
- package/dist/utils/callbackRegistry.js +124 -0
- package/dist/utils/frameRegistry.d.ts +12 -0
- package/dist/utils/frameRegistry.d.ts.map +1 -0
- package/dist/utils/frameRegistry.js +59 -0
- package/dist/utils/messageListenerRegistry.d.ts +25 -0
- package/dist/utils/messageListenerRegistry.d.ts.map +1 -0
- package/dist/utils/messageListenerRegistry.js +197 -0
- package/dist/utils/setupKeyListener.d.ts +7 -0
- package/dist/utils/setupKeyListener.d.ts.map +1 -0
- package/dist/utils/setupKeyListener.js +29 -0
- package/dist/utils/setupUrlMonitoring.d.ts +12 -0
- package/dist/utils/setupUrlMonitoring.d.ts.map +1 -0
- package/dist/utils/setupUrlMonitoring.js +57 -0
- package/dist/utils/uuid.d.ts +10 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +18 -0
- package/package.json +22 -11
- package/src/index.d.ts +0 -55
- package/src/index.js +0 -118
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Listener Registry
|
|
3
|
+
* Manages message listeners for ShellUI message types
|
|
4
|
+
*/
|
|
5
|
+
import { getLogger } from '../logger/logger.js';
|
|
6
|
+
const logger = getLogger('shellsdk');
|
|
7
|
+
export class MessageListenerRegistry {
|
|
8
|
+
constructor(frameRegistry = null) {
|
|
9
|
+
this.listeners = new Map();
|
|
10
|
+
this.messageHandler = null;
|
|
11
|
+
this.isListening = false;
|
|
12
|
+
this.frameRegistry = frameRegistry;
|
|
13
|
+
}
|
|
14
|
+
setupGlobalListener() {
|
|
15
|
+
if (typeof window === 'undefined' || this.isListening) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
this.messageHandler = (event) => {
|
|
19
|
+
if (!event.data || typeof event.data !== 'object' || !event.data.type) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const messageType = event.data.type;
|
|
23
|
+
if (!messageType.startsWith('SHELLUI_')) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const fromUuid = this.frameRegistry?.getUuidByIframe(event.source);
|
|
27
|
+
const typeListeners = this.listeners.get(messageType) ?? [];
|
|
28
|
+
typeListeners.forEach((listener) => {
|
|
29
|
+
try {
|
|
30
|
+
if (window.parent === window ||
|
|
31
|
+
(event.data.to && (event.data.to.length === 0 || event.data.to.includes('*'))) ||
|
|
32
|
+
messageType === 'SHELLUI_URL_CHANGED' ||
|
|
33
|
+
messageType === 'SHELLUI_INITIALIZED') {
|
|
34
|
+
listener({
|
|
35
|
+
...event.data,
|
|
36
|
+
from: [fromUuid, ...(event.data.from || [])].filter(Boolean),
|
|
37
|
+
}, event);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger.error(`Error in message listener for ${messageType}:`, {
|
|
42
|
+
error,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
logger.debug('Message received:', event.data);
|
|
47
|
+
if (messageType === 'SHELLUI_URL_CHANGED' || messageType === 'SHELLUI_INITIALIZED') {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (fromUuid) {
|
|
51
|
+
this.sendMessageToParent({
|
|
52
|
+
type: messageType,
|
|
53
|
+
payload: event.data.payload,
|
|
54
|
+
from: [fromUuid, ...(event.data.from || [])],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const fromParent = event.source === window.parent;
|
|
58
|
+
if (fromParent) {
|
|
59
|
+
this.sendMessage({
|
|
60
|
+
type: messageType,
|
|
61
|
+
payload: event.data.payload,
|
|
62
|
+
to: [...(event.data.to || [])],
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
window.addEventListener('message', this.messageHandler);
|
|
67
|
+
this.isListening = true;
|
|
68
|
+
logger.debug('Global message listener set up');
|
|
69
|
+
}
|
|
70
|
+
teardownGlobalListener() {
|
|
71
|
+
if (!this.isListening || !this.messageHandler) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
window.removeEventListener('message', this.messageHandler);
|
|
75
|
+
this.isListening = false;
|
|
76
|
+
this.messageHandler = null;
|
|
77
|
+
logger.debug('Global message listener torn down');
|
|
78
|
+
}
|
|
79
|
+
addMessageListener(messageType, listener) {
|
|
80
|
+
if (typeof messageType !== 'string' || !messageType.startsWith('SHELLUI_')) {
|
|
81
|
+
throw new Error('messageType must be a string starting with "SHELLUI_"');
|
|
82
|
+
}
|
|
83
|
+
if (typeof listener !== 'function') {
|
|
84
|
+
throw new Error('listener must be a function');
|
|
85
|
+
}
|
|
86
|
+
if (!this.listeners.has(messageType)) {
|
|
87
|
+
this.listeners.set(messageType, new Set());
|
|
88
|
+
}
|
|
89
|
+
const typeListeners = this.listeners.get(messageType);
|
|
90
|
+
typeListeners?.add(listener);
|
|
91
|
+
logger.debug(`Added listener for message type: ${messageType}`);
|
|
92
|
+
return () => {
|
|
93
|
+
this.removeMessageListener(messageType, listener);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
removeMessageListener(messageType, listener) {
|
|
97
|
+
if (typeof messageType !== 'string' || !messageType.startsWith('SHELLUI_')) {
|
|
98
|
+
throw new Error('messageType must be a string starting with "SHELLUI_"');
|
|
99
|
+
}
|
|
100
|
+
const typeListeners = this.listeners.get(messageType);
|
|
101
|
+
if (!typeListeners) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const removed = typeListeners.delete(listener);
|
|
105
|
+
if (typeListeners.size === 0) {
|
|
106
|
+
this.listeners.delete(messageType);
|
|
107
|
+
}
|
|
108
|
+
if (removed) {
|
|
109
|
+
logger.debug(`Removed listener for message type: ${messageType}`);
|
|
110
|
+
}
|
|
111
|
+
return removed;
|
|
112
|
+
}
|
|
113
|
+
getListenerCount(messageType) {
|
|
114
|
+
const typeListeners = this.listeners.get(messageType);
|
|
115
|
+
return typeListeners ? typeListeners.size : 0;
|
|
116
|
+
}
|
|
117
|
+
removeAllListeners(messageType) {
|
|
118
|
+
if (typeof messageType !== 'string' || !messageType.startsWith('SHELLUI_')) {
|
|
119
|
+
throw new Error('messageType must be a string starting with "SHELLUI_"');
|
|
120
|
+
}
|
|
121
|
+
const typeListeners = this.listeners.get(messageType);
|
|
122
|
+
if (!typeListeners) {
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
const count = typeListeners.size;
|
|
126
|
+
this.listeners.delete(messageType);
|
|
127
|
+
logger.debug(`Removed all ${count} listeners for message type: ${messageType}`);
|
|
128
|
+
return count;
|
|
129
|
+
}
|
|
130
|
+
removeAllListenersForAllTypes() {
|
|
131
|
+
const totalCount = Array.from(this.listeners.values()).reduce((sum, set) => sum + set.size, 0);
|
|
132
|
+
this.listeners.clear();
|
|
133
|
+
logger.debug(`Removed all ${totalCount} listeners for all message types`);
|
|
134
|
+
}
|
|
135
|
+
sendMessage(message) {
|
|
136
|
+
if (typeof window === 'undefined') {
|
|
137
|
+
logger.warn('Cannot send message: window is undefined');
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
if (!this.frameRegistry) {
|
|
141
|
+
logger.warn('Cannot send message: frameRegistry not available');
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
if (typeof message.type !== 'string' || !message.type.startsWith('SHELLUI_')) {
|
|
145
|
+
throw new Error('messageType must be a string starting with "SHELLUI_"');
|
|
146
|
+
}
|
|
147
|
+
const sendToAll = message.to?.includes('*');
|
|
148
|
+
const allIframes = this.frameRegistry.getAllIframes();
|
|
149
|
+
if (allIframes.length === 0) {
|
|
150
|
+
logger.debug(`No iframes registered, message ${message.type} not sent`);
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
let sentCount = 0;
|
|
154
|
+
for (const [uuid, iframe] of allIframes) {
|
|
155
|
+
if (sendToAll || message.to?.includes(uuid)) {
|
|
156
|
+
try {
|
|
157
|
+
if (iframe?.contentWindow) {
|
|
158
|
+
iframe.contentWindow.postMessage({
|
|
159
|
+
type: message.type,
|
|
160
|
+
payload: message.payload,
|
|
161
|
+
to: (message.to || []).filter((t) => t !== uuid),
|
|
162
|
+
}, '*');
|
|
163
|
+
sentCount++;
|
|
164
|
+
logger.debug(`Sent message ${message.type} to iframe ${uuid}`);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
logger.warn(`Iframe ${uuid} has no contentWindow, skipping`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
logger.error(`Error sending message to iframe ${uuid}:`, { error });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
logger.debug(`Sent message ${message.type} to ${sentCount} iframe(s)`);
|
|
176
|
+
return sentCount;
|
|
177
|
+
}
|
|
178
|
+
propagateMessage(message) {
|
|
179
|
+
return this.sendMessage({
|
|
180
|
+
type: message.type,
|
|
181
|
+
payload: message.payload,
|
|
182
|
+
to: ['*'],
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
sendMessageToParent(message) {
|
|
186
|
+
if (typeof window === 'undefined') {
|
|
187
|
+
logger.warn('Cannot send message to parent: window is undefined');
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
if (window.parent !== window) {
|
|
191
|
+
window.parent.postMessage(message, '*');
|
|
192
|
+
logger.debug(`Sent message ${message.type} to parent window`);
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sets up a listener for the Escape key to close modal
|
|
3
|
+
* If in an iframe, sends a message to the parent
|
|
4
|
+
* @returns Cleanup function to remove the event listener
|
|
5
|
+
*/
|
|
6
|
+
export declare function setupKeyListener(): () => void;
|
|
7
|
+
//# sourceMappingURL=setupKeyListener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setupKeyListener.d.ts","sourceRoot":"","sources":["../../src/utils/setupKeyListener.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,IAAI,CA8B7C"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getLogger } from '../logger/logger.js';
|
|
2
|
+
const logger = getLogger('shellsdk');
|
|
3
|
+
/**
|
|
4
|
+
* Sets up a listener for the Escape key to close modal
|
|
5
|
+
* If in an iframe, sends a message to the parent
|
|
6
|
+
* @returns Cleanup function to remove the event listener
|
|
7
|
+
*/
|
|
8
|
+
export function setupKeyListener() {
|
|
9
|
+
if (typeof window === 'undefined') {
|
|
10
|
+
return () => { };
|
|
11
|
+
}
|
|
12
|
+
const handleEscape = (event) => {
|
|
13
|
+
if (event.key === 'Escape' || event.keyCode === 27) {
|
|
14
|
+
logger.info(`${event.key} (${event.keyCode}) pressed ${window.parent !== window ? 'inside iframe' : 'at top level'}`, {
|
|
15
|
+
key: event.key,
|
|
16
|
+
keyCode: event.keyCode,
|
|
17
|
+
code: event.code,
|
|
18
|
+
});
|
|
19
|
+
if (window.parent !== window) {
|
|
20
|
+
window.parent.postMessage({ type: 'SHELLUI_CLOSE_MODAL', payload: {} }, '*');
|
|
21
|
+
window.parent.postMessage({ type: 'SHELLUI_CLOSE_DRAWER', payload: {} }, '*');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
window.addEventListener('keydown', handleEscape);
|
|
26
|
+
return () => {
|
|
27
|
+
window.removeEventListener('keydown', handleEscape);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ShellSDKLike {
|
|
2
|
+
currentPath: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Handles URL changes and notifies parent if the path has changed
|
|
6
|
+
*/
|
|
7
|
+
export declare function handleUrlChange(sdk: ShellSDKLike): void;
|
|
8
|
+
/**
|
|
9
|
+
* Sets up listeners for various URL change events
|
|
10
|
+
*/
|
|
11
|
+
export declare function setupUrlMonitoring(sdk: ShellSDKLike): void;
|
|
12
|
+
//# sourceMappingURL=setupUrlMonitoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setupUrlMonitoring.d.ts","sourceRoot":"","sources":["../../src/utils/setupUrlMonitoring.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CA0BvD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CA2B1D"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { getLogger } from '../logger/logger.js';
|
|
2
|
+
import { shellui } from '../index.js';
|
|
3
|
+
const logger = getLogger('shellsdk');
|
|
4
|
+
/**
|
|
5
|
+
* Handles URL changes and notifies parent if the path has changed
|
|
6
|
+
*/
|
|
7
|
+
export function handleUrlChange(sdk) {
|
|
8
|
+
if (typeof window === 'undefined') {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const newPath = window.location.pathname + window.location.search + window.location.hash;
|
|
12
|
+
if (newPath !== sdk.currentPath) {
|
|
13
|
+
sdk.currentPath = newPath;
|
|
14
|
+
if (typeof window === 'undefined') {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const message = {
|
|
18
|
+
pathname: window.location.pathname,
|
|
19
|
+
search: window.location.search,
|
|
20
|
+
hash: window.location.hash,
|
|
21
|
+
fullPath: window.location.pathname + window.location.search + window.location.hash,
|
|
22
|
+
};
|
|
23
|
+
if (window.parent !== window) {
|
|
24
|
+
shellui.sendMessageToParent({
|
|
25
|
+
type: 'SHELLUI_URL_CHANGED',
|
|
26
|
+
payload: message,
|
|
27
|
+
});
|
|
28
|
+
logger.debug('Sent SHELLUI_URL_CHANGED message to parent', message);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Sets up listeners for various URL change events
|
|
34
|
+
*/
|
|
35
|
+
export function setupUrlMonitoring(sdk) {
|
|
36
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
window.addEventListener('popstate', () => handleUrlChange(sdk));
|
|
40
|
+
window.addEventListener('hashchange', () => handleUrlChange(sdk));
|
|
41
|
+
const originalPushState = window.history.pushState;
|
|
42
|
+
const originalReplaceState = window.history.replaceState;
|
|
43
|
+
window.history.pushState = function (...args) {
|
|
44
|
+
originalPushState.apply(this, args);
|
|
45
|
+
handleUrlChange(sdk);
|
|
46
|
+
};
|
|
47
|
+
window.history.replaceState = function (...args) {
|
|
48
|
+
originalReplaceState.apply(this, args);
|
|
49
|
+
handleUrlChange(sdk);
|
|
50
|
+
};
|
|
51
|
+
document.addEventListener('click', (e) => {
|
|
52
|
+
const link = e.target?.closest('a');
|
|
53
|
+
if (link && link.href && new URL(link.href).origin === window.location.origin) {
|
|
54
|
+
setTimeout(() => handleUrlChange(sdk), 0);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUID Utility
|
|
3
|
+
* Generates UUID v4 identifiers
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generates a UUID v4
|
|
7
|
+
* Uses crypto.randomUUID() if available, otherwise falls back to a manual implementation
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateUuid(): string;
|
|
10
|
+
//# sourceMappingURL=uuid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAUrC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUID Utility
|
|
3
|
+
* Generates UUID v4 identifiers
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generates a UUID v4
|
|
7
|
+
* Uses crypto.randomUUID() if available, otherwise falls back to a manual implementation
|
|
8
|
+
*/
|
|
9
|
+
export function generateUuid() {
|
|
10
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
11
|
+
return crypto.randomUUID();
|
|
12
|
+
}
|
|
13
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
14
|
+
const r = (Math.random() * 16) | 0;
|
|
15
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
16
|
+
return v.toString(16);
|
|
17
|
+
});
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shellui/sdk",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "ShellUI SDK - JavaScript SDK for ShellUI integration",
|
|
5
|
-
"main": "
|
|
6
|
-
"types": "
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"description": "ShellUI SDK - TypeScript/JavaScript SDK for ShellUI integration",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
8
14
|
"files": [
|
|
9
|
-
"
|
|
15
|
+
"dist",
|
|
10
16
|
"README.md",
|
|
11
17
|
"package.json"
|
|
12
18
|
],
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "echo 'SDK build complete'",
|
|
15
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
-
},
|
|
17
19
|
"keywords": [
|
|
18
20
|
"shellui",
|
|
19
21
|
"sdk",
|
|
@@ -22,8 +24,17 @@
|
|
|
22
24
|
],
|
|
23
25
|
"author": "ShellUI",
|
|
24
26
|
"license": "MIT",
|
|
25
|
-
"dependencies": {
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"roarr": "^7.21.2"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"typescript": "^5.0.0"
|
|
32
|
+
},
|
|
26
33
|
"publishConfig": {
|
|
27
34
|
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"test": "echo \"No tests specified for @shellui/sdk\""
|
|
28
39
|
}
|
|
29
|
-
}
|
|
40
|
+
}
|
package/src/index.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ShellUI SDK Type Definitions
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export interface ShellUIUrlPayload {
|
|
6
|
-
pathname: string;
|
|
7
|
-
search: string;
|
|
8
|
-
hash: string;
|
|
9
|
-
fullPath: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface ShellUIMessage {
|
|
13
|
-
type: 'SHELLUI_URL_CHANGED';
|
|
14
|
-
payload: ShellUIUrlPayload;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class ShellUISDK {
|
|
18
|
-
private initialized: boolean;
|
|
19
|
-
private currentPath: string;
|
|
20
|
-
private version: string;
|
|
21
|
-
|
|
22
|
-
constructor();
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Initialize the SDK and start monitoring URL changes
|
|
26
|
-
*/
|
|
27
|
-
init(): this;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Sets up listeners for various URL change events
|
|
31
|
-
*/
|
|
32
|
-
setupUrlMonitoring(): void;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Internal handler for URL changes
|
|
36
|
-
*/
|
|
37
|
-
handleUrlChange(): void;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Sends a message to the parent frame with the current path information
|
|
41
|
-
*/
|
|
42
|
-
notifyParent(): void;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Returns the current version of the SDK
|
|
46
|
-
*/
|
|
47
|
-
getVersion(): string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export const init: () => ShellUISDK;
|
|
51
|
-
export const getVersion: () => string;
|
|
52
|
-
export const shellui: ShellUISDK;
|
|
53
|
-
|
|
54
|
-
declare const sdk: ShellUISDK;
|
|
55
|
-
export default sdk;
|
package/src/index.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ShellUI SDK
|
|
3
|
-
* Handles communication between the iframe content and the ShellUI parent frame.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
class ShellUISDK {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.initialized = false;
|
|
9
|
-
// Don't access window in constructor - it may not exist during SSR
|
|
10
|
-
this.currentPath = typeof window !== 'undefined'
|
|
11
|
-
? window.location.pathname + window.location.search + window.location.hash
|
|
12
|
-
: '';
|
|
13
|
-
this.version = '0.0.1';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Initialize the SDK and start monitoring URL changes
|
|
18
|
-
*/
|
|
19
|
-
init() {
|
|
20
|
-
if (this.initialized) return this;
|
|
21
|
-
|
|
22
|
-
// Monitor URL changes
|
|
23
|
-
this.setupUrlMonitoring();
|
|
24
|
-
|
|
25
|
-
// Initial sync
|
|
26
|
-
this.notifyParent();
|
|
27
|
-
|
|
28
|
-
this.initialized = true;
|
|
29
|
-
console.log('ShellUI SDK initialized');
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Sets up listeners for various URL change events
|
|
35
|
-
*/
|
|
36
|
-
setupUrlMonitoring() {
|
|
37
|
-
// Guard against SSR - window and document may not exist
|
|
38
|
-
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Listen for popstate (back/forward buttons)
|
|
43
|
-
window.addEventListener('popstate', () => this.handleUrlChange());
|
|
44
|
-
|
|
45
|
-
// Listen for hashchange
|
|
46
|
-
window.addEventListener('hashchange', () => this.handleUrlChange());
|
|
47
|
-
|
|
48
|
-
// Intercept pushState and replaceState
|
|
49
|
-
const originalPushState = window.history.pushState;
|
|
50
|
-
const originalReplaceState = window.history.replaceState;
|
|
51
|
-
|
|
52
|
-
const self = this;
|
|
53
|
-
window.history.pushState = function(...args) {
|
|
54
|
-
originalPushState.apply(this, args);
|
|
55
|
-
self.handleUrlChange();
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
window.history.replaceState = function(...args) {
|
|
59
|
-
originalReplaceState.apply(this, args);
|
|
60
|
-
self.handleUrlChange();
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// Monitor clicks on same-origin links to catch re-renders or local routing
|
|
64
|
-
document.addEventListener('click', (e) => {
|
|
65
|
-
const link = e.target.closest('a');
|
|
66
|
-
if (link && link.href && new URL(link.href).origin === window.location.origin) {
|
|
67
|
-
// Wait a bit for the framework to handle the route
|
|
68
|
-
setTimeout(() => this.handleUrlChange(), 0);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
handleUrlChange() {
|
|
74
|
-
if (typeof window === 'undefined') {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const newPath = window.location.pathname + window.location.search + window.location.hash;
|
|
78
|
-
if (newPath !== this.currentPath) {
|
|
79
|
-
this.currentPath = newPath;
|
|
80
|
-
this.notifyParent();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Sends a message to the parent frame with the current path information
|
|
86
|
-
*/
|
|
87
|
-
notifyParent() {
|
|
88
|
-
if (typeof window === 'undefined') {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const message = {
|
|
92
|
-
type: 'SHELLUI_URL_CHANGED',
|
|
93
|
-
payload: {
|
|
94
|
-
pathname: window.location.pathname,
|
|
95
|
-
search: window.location.search,
|
|
96
|
-
hash: window.location.hash,
|
|
97
|
-
fullPath: window.location.pathname + window.location.search + window.location.hash
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
// Send to parent frame
|
|
102
|
-
if (window.parent !== window) {
|
|
103
|
-
window.parent.postMessage(message, '*');
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
getVersion() {
|
|
108
|
-
return this.version;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const sdk = new ShellUISDK();
|
|
113
|
-
|
|
114
|
-
export const init = () => sdk.init();
|
|
115
|
-
export const getVersion = () => sdk.getVersion();
|
|
116
|
-
export const shellui = sdk;
|
|
117
|
-
|
|
118
|
-
export default sdk;
|