@shellui/sdk 0.0.2 → 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.
Files changed (46) hide show
  1. package/README.md +3 -2
  2. package/dist/actions/closeDrawer.d.ts +6 -0
  3. package/dist/actions/closeDrawer.d.ts.map +1 -0
  4. package/dist/actions/closeDrawer.js +19 -0
  5. package/dist/actions/dialog.d.ts +9 -0
  6. package/dist/actions/dialog.d.ts.map +1 -0
  7. package/dist/actions/dialog.js +51 -0
  8. package/dist/actions/openDrawer.d.ts +8 -0
  9. package/dist/actions/openDrawer.d.ts.map +1 -0
  10. package/dist/actions/openDrawer.js +27 -0
  11. package/dist/actions/openModal.d.ts +7 -0
  12. package/dist/actions/openModal.d.ts.map +1 -0
  13. package/dist/actions/openModal.js +22 -0
  14. package/dist/actions/toast.d.ts +9 -0
  15. package/dist/actions/toast.d.ts.map +1 -0
  16. package/dist/actions/toast.js +47 -0
  17. package/dist/index.d.ts +58 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +198 -0
  20. package/dist/logger/logger.d.ts +7 -0
  21. package/dist/logger/logger.d.ts.map +1 -0
  22. package/dist/logger/logger.js +175 -0
  23. package/dist/types.d.ts +131 -0
  24. package/dist/types.d.ts.map +1 -0
  25. package/dist/types.js +4 -0
  26. package/dist/utils/callbackRegistry.d.ts +29 -0
  27. package/dist/utils/callbackRegistry.d.ts.map +1 -0
  28. package/dist/utils/callbackRegistry.js +124 -0
  29. package/dist/utils/frameRegistry.d.ts +12 -0
  30. package/dist/utils/frameRegistry.d.ts.map +1 -0
  31. package/dist/utils/frameRegistry.js +59 -0
  32. package/dist/utils/messageListenerRegistry.d.ts +25 -0
  33. package/dist/utils/messageListenerRegistry.d.ts.map +1 -0
  34. package/dist/utils/messageListenerRegistry.js +197 -0
  35. package/dist/utils/setupKeyListener.d.ts +7 -0
  36. package/dist/utils/setupKeyListener.d.ts.map +1 -0
  37. package/dist/utils/setupKeyListener.js +29 -0
  38. package/dist/utils/setupUrlMonitoring.d.ts +12 -0
  39. package/dist/utils/setupUrlMonitoring.d.ts.map +1 -0
  40. package/dist/utils/setupUrlMonitoring.js +57 -0
  41. package/dist/utils/uuid.d.ts +10 -0
  42. package/dist/utils/uuid.d.ts.map +1 -0
  43. package/dist/utils/uuid.js +18 -0
  44. package/package.json +22 -11
  45. package/src/index.d.ts +0 -55
  46. package/src/index.js +0 -104
@@ -0,0 +1,175 @@
1
+ /* eslint-disable no-console */
2
+ /**
3
+ * Logger utility with namespace support
4
+ * Reads logging configuration from localStorage settings
5
+ */
6
+ import { Roarr as roarrLogger, ROARR } from 'roarr';
7
+ const STORAGE_KEY = 'shellui:settings';
8
+ const DEFAULT_NAMESPACES = {
9
+ shellsdk: false,
10
+ shellcore: false,
11
+ };
12
+ function getSettings() {
13
+ if (typeof window === 'undefined') {
14
+ return {
15
+ developerFeatures: { enabled: false },
16
+ logging: { namespaces: DEFAULT_NAMESPACES },
17
+ };
18
+ }
19
+ try {
20
+ const stored = localStorage.getItem(STORAGE_KEY);
21
+ if (stored) {
22
+ const parsed = JSON.parse(stored);
23
+ return {
24
+ developerFeatures: parsed.developerFeatures ?? { enabled: false },
25
+ logging: {
26
+ namespaces: parsed.logging?.namespaces ?? DEFAULT_NAMESPACES,
27
+ },
28
+ };
29
+ }
30
+ }
31
+ catch {
32
+ // Silently fail - use defaults
33
+ }
34
+ return {
35
+ developerFeatures: { enabled: false },
36
+ logging: { namespaces: DEFAULT_NAMESPACES },
37
+ };
38
+ }
39
+ function isNamespaceEnabled(namespace) {
40
+ const settings = getSettings();
41
+ if (!settings.developerFeatures?.enabled) {
42
+ return false;
43
+ }
44
+ return settings.logging?.namespaces?.[namespace] === true;
45
+ }
46
+ const NAMESPACE_COLORS = {
47
+ shellsdk: {
48
+ bg: '#3b82f6',
49
+ text: '#ffffff',
50
+ name: 'ShellSDK',
51
+ },
52
+ shellcore: {
53
+ bg: '#10b981',
54
+ text: '#ffffff',
55
+ name: 'ShellCore',
56
+ },
57
+ };
58
+ function getNamespaceStyles(namespace) {
59
+ const colors = NAMESPACE_COLORS[namespace] ?? {
60
+ bg: '#6b7280',
61
+ text: '#ffffff',
62
+ name: namespace,
63
+ };
64
+ return {
65
+ background: colors.bg,
66
+ color: colors.text,
67
+ padding: '2px 8px',
68
+ borderRadius: '4px',
69
+ fontWeight: '600',
70
+ fontSize: '11px',
71
+ textTransform: 'uppercase',
72
+ letterSpacing: '0.5px',
73
+ };
74
+ }
75
+ function formatStyles(styles) {
76
+ return Object.entries(styles)
77
+ .map(([key, value]) => `${key.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${value}`)
78
+ .join('; ');
79
+ }
80
+ let writerInitialized = false;
81
+ function setupRoarrWriter() {
82
+ if (typeof window === 'undefined') {
83
+ return;
84
+ }
85
+ if (writerInitialized) {
86
+ return;
87
+ }
88
+ ROARR.write = (message) => {
89
+ try {
90
+ const logData = JSON.parse(message);
91
+ const namespace = logData.context?.namespace;
92
+ if (namespace && !isNamespaceEnabled(namespace)) {
93
+ return;
94
+ }
95
+ const logLevel = logData.context?.logLevel ?? logData.logLevel ?? 0;
96
+ const logMethod = logLevel >= 50 ? 'error' : logLevel >= 40 ? 'warn' : 'log';
97
+ const messageText = String(logData.context?.message ?? '');
98
+ const contextWithoutNamespace = { ...logData.context };
99
+ delete contextWithoutNamespace.namespace;
100
+ delete contextWithoutNamespace.logLevel;
101
+ delete contextWithoutNamespace.message;
102
+ const hasAdditionalContext = Object.keys(contextWithoutNamespace).length > 0;
103
+ if (namespace) {
104
+ const styles = getNamespaceStyles(namespace);
105
+ const namespaceBadge = `[${NAMESPACE_COLORS[namespace]?.name ?? namespace}]`;
106
+ const styleString = formatStyles(styles);
107
+ if (hasAdditionalContext) {
108
+ console[logMethod](`%c${namespaceBadge}%c ${messageText}`, styleString, '', contextWithoutNamespace);
109
+ }
110
+ else {
111
+ console[logMethod](`%c${namespaceBadge}%c ${messageText}`, styleString, '');
112
+ }
113
+ }
114
+ else {
115
+ if (hasAdditionalContext) {
116
+ console[logMethod](messageText, contextWithoutNamespace);
117
+ }
118
+ else {
119
+ console[logMethod](messageText);
120
+ }
121
+ }
122
+ }
123
+ catch {
124
+ console.log(message);
125
+ }
126
+ };
127
+ writerInitialized = true;
128
+ }
129
+ setupRoarrWriter();
130
+ export function getLogger(namespace) {
131
+ const logger = roarrLogger.child({ namespace });
132
+ return {
133
+ log: (message, context = {}) => {
134
+ if (isNamespaceEnabled(namespace)) {
135
+ logger({ ...context, message });
136
+ }
137
+ },
138
+ info: (message, context = {}) => {
139
+ if (isNamespaceEnabled(namespace)) {
140
+ logger({
141
+ ...context,
142
+ message,
143
+ logLevel: 30,
144
+ });
145
+ }
146
+ },
147
+ warn: (message, context = {}) => {
148
+ if (isNamespaceEnabled(namespace)) {
149
+ logger({
150
+ ...context,
151
+ message,
152
+ logLevel: 40,
153
+ });
154
+ }
155
+ },
156
+ error: (message, context = {}) => {
157
+ if (isNamespaceEnabled(namespace)) {
158
+ logger({
159
+ ...context,
160
+ message,
161
+ logLevel: 50,
162
+ });
163
+ }
164
+ },
165
+ debug: (message, context = {}) => {
166
+ if (isNamespaceEnabled(namespace)) {
167
+ logger({
168
+ ...context,
169
+ message,
170
+ logLevel: 20,
171
+ });
172
+ }
173
+ },
174
+ };
175
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * ShellUI SDK Type Definitions
3
+ */
4
+ export interface ShellUIUrlPayload {
5
+ pathname: string;
6
+ search: string;
7
+ hash: string;
8
+ fullPath: string;
9
+ }
10
+ export interface ToastOptions {
11
+ id?: string;
12
+ title?: string;
13
+ description?: string;
14
+ type?: 'default' | 'success' | 'error' | 'warning' | 'info' | 'loading';
15
+ duration?: number;
16
+ position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
17
+ action?: {
18
+ label: string;
19
+ onClick: () => void;
20
+ };
21
+ cancel?: {
22
+ label: string;
23
+ onClick: () => void;
24
+ };
25
+ }
26
+ export type DialogMode = 'ok' | 'okCancel' | 'delete' | 'confirm' | 'onlyCancel';
27
+ export type AlertDialogSize = 'default' | 'sm';
28
+ export type DialogPosition = 'center' | 'bottom-left';
29
+ export interface DialogOptions {
30
+ id?: string;
31
+ title: string;
32
+ description?: string;
33
+ mode?: DialogMode;
34
+ okLabel?: string;
35
+ cancelLabel?: string;
36
+ size?: AlertDialogSize;
37
+ position?: DialogPosition;
38
+ secondaryButton?: {
39
+ label: string;
40
+ onClick: () => void;
41
+ };
42
+ icon?: string;
43
+ onOk?: () => void;
44
+ onCancel?: () => void;
45
+ }
46
+ /** Navigation item exposed to sub-apps (root-level nav config) */
47
+ export interface SettingsNavigationItem {
48
+ path: string;
49
+ url: string;
50
+ label?: string;
51
+ }
52
+ export interface Settings {
53
+ developerFeatures: {
54
+ enabled: boolean;
55
+ };
56
+ /** User toggle for sending error reports (only relevant when app has reporting configured). */
57
+ errorReporting: {
58
+ enabled: boolean;
59
+ };
60
+ logging: {
61
+ namespaces: {
62
+ shellsdk: boolean;
63
+ shellcore: boolean;
64
+ };
65
+ };
66
+ appearance: {
67
+ theme: 'light' | 'dark' | 'system';
68
+ themeName: string;
69
+ };
70
+ language: {
71
+ code: 'en' | 'fr';
72
+ };
73
+ region: {
74
+ timezone: string;
75
+ };
76
+ /**
77
+ * Cookie consent: hosts the user has accepted. Only enable a feature when its cookie host is in acceptedHosts.
78
+ * consentedCookieHosts = list of hosts that were in config when user last gave consent; if config has a host
79
+ * not in this list, re-prompt and pre-fill with acceptedHosts so existing approvals are kept.
80
+ */
81
+ cookieConsent?: {
82
+ /** Hosts the user has accepted (e.g. ["sentry.io", ".example.com"]). */
83
+ acceptedHosts: string[];
84
+ /** Hosts that were in config when user last consented; used to detect new cookies and re-collect consent. */
85
+ consentedCookieHosts: string[];
86
+ };
87
+ /** Service worker settings (caching, offline) */
88
+ serviceWorker?: {
89
+ /** Whether the service worker is enabled */
90
+ enabled: boolean;
91
+ };
92
+ /** Override layout at runtime: 'sidebar' | 'fullscreen' | 'windows'. When set, overrides config.layout (e.g. from Develop settings). */
93
+ layout?: 'sidebar' | 'fullscreen' | 'windows';
94
+ /** Root-level navigation items (injected by shell when sending settings to sub-apps) */
95
+ navigation?: {
96
+ items: SettingsNavigationItem[];
97
+ };
98
+ }
99
+ export type DrawerPosition = 'top' | 'bottom' | 'left' | 'right';
100
+ /** Size as CSS length: e.g. "400px", "80vh", "50vw" */
101
+ export interface OpenDrawerOptions {
102
+ url?: string;
103
+ position?: DrawerPosition;
104
+ /** CSS length for drawer size: height for top/bottom (e.g. "80vh", "400px"), width for left/right (e.g. "50vw", "320px") */
105
+ size?: string;
106
+ }
107
+ export type ShellUIMessageType = 'SHELLUI_URL_CHANGED' | 'SHELLUI_OPEN_MODAL' | 'SHELLUI_CLOSE_MODAL' | 'SHELLUI_OPEN_DRAWER' | 'SHELLUI_CLOSE_DRAWER' | 'SHELLUI_NAVIGATE' | 'SHELLUI_SETTINGS_UPDATED' | 'SHELLUI_SETTINGS' | 'SHELLUI_SETTINGS_REQUESTED' | 'SHELLUI_TOAST' | 'SHELLUI_TOAST_UPDATE' | 'SHELLUI_TOAST_ACTION' | 'SHELLUI_TOAST_CANCEL' | 'SHELLUI_TOAST_CLEAR' | 'SHELLUI_DIALOG' | 'SHELLUI_DIALOG_UPDATE' | 'SHELLUI_DIALOG_OK' | 'SHELLUI_DIALOG_CANCEL' | 'SHELLUI_DIALOG_SECONDARY' | 'SHELLUI_INITIALIZED' | 'SHELLUI_REFRESH_PAGE';
108
+ export interface ShellUIMessage {
109
+ type: ShellUIMessageType | string;
110
+ payload: ShellUIUrlPayload | Record<string, never> | {
111
+ url?: string | null;
112
+ } | {
113
+ url: string;
114
+ } | {
115
+ url?: string;
116
+ position?: DrawerPosition;
117
+ size?: string;
118
+ } | ToastOptions | DialogOptions | {
119
+ [key: string]: unknown;
120
+ };
121
+ from?: string[];
122
+ to?: string[];
123
+ }
124
+ export interface LoggerInstance {
125
+ log: (message: string, context?: Record<string, unknown>) => void;
126
+ info: (message: string, context?: Record<string, unknown>) => void;
127
+ warn: (message: string, context?: Record<string, unknown>) => void;
128
+ error: (message: string, context?: Record<string, unknown>) => void;
129
+ debug: (message: string, context?: Record<string, unknown>) => void;
130
+ }
131
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ /**
2
+ * ShellUI SDK Type Definitions
3
+ */
4
+ export {};
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Callback Registry
3
+ * Manages callbacks for toast actions and cancel buttons
4
+ * Since postMessage can only send serializable content, callbacks are stored
5
+ * in the SDK and triggered by ID
6
+ */
7
+ interface CallbackEntry {
8
+ action?: () => void;
9
+ cancel?: () => void;
10
+ secondary?: () => void;
11
+ createdAt: Date;
12
+ }
13
+ export declare class CallbackRegistry {
14
+ private callbacks;
15
+ register(id: string, { action, cancel, secondary, }?: {
16
+ action?: () => void;
17
+ cancel?: () => void;
18
+ secondary?: () => void;
19
+ }): void;
20
+ triggerAction(id: string): boolean;
21
+ triggerCancel(id: string): boolean;
22
+ triggerSecondary(id: string): boolean;
23
+ clear(id: string): boolean;
24
+ get(id: string): CallbackEntry | undefined;
25
+ getAllIds(): string[];
26
+ clearAll(): void;
27
+ }
28
+ export {};
29
+ //# sourceMappingURL=callbackRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callbackRegistry.d.ts","sourceRoot":"","sources":["../../src/utils/callbackRegistry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAoC;IAErD,QAAQ,CACN,EAAE,EAAE,MAAM,EACV,EACE,MAAM,EACN,MAAM,EACN,SAAS,GACV,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;KAAO,GAC3E,IAAI;IAoBP,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAwBlC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAwBlC,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAwBrC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAiB1B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI1C,SAAS,IAAI,MAAM,EAAE;IAIrB,QAAQ,IAAI,IAAI;CAKjB"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Callback Registry
3
+ * Manages callbacks for toast actions and cancel buttons
4
+ * Since postMessage can only send serializable content, callbacks are stored
5
+ * in the SDK and triggered by ID
6
+ */
7
+ import { getLogger } from '../logger/logger.js';
8
+ const logger = getLogger('shellsdk');
9
+ export class CallbackRegistry {
10
+ constructor() {
11
+ this.callbacks = new Map();
12
+ }
13
+ register(id, { action, cancel, secondary, } = {}) {
14
+ if (!id) {
15
+ logger.warn('Cannot register callback without ID');
16
+ return;
17
+ }
18
+ this.callbacks.set(id, {
19
+ action,
20
+ cancel,
21
+ secondary,
22
+ createdAt: new Date(),
23
+ });
24
+ logger.debug(`Registered callbacks for ID ${id}`, {
25
+ hasAction: !!action,
26
+ hasCancel: !!cancel,
27
+ hasSecondary: !!secondary,
28
+ });
29
+ }
30
+ triggerAction(id) {
31
+ const callbacks = this.callbacks.get(id);
32
+ if (!callbacks) {
33
+ logger.warn(`No callbacks found for ID ${id}`);
34
+ return false;
35
+ }
36
+ if (callbacks.action && typeof callbacks.action === 'function') {
37
+ try {
38
+ callbacks.action();
39
+ logger.debug(`Triggered action callback for ID ${id}`);
40
+ return true;
41
+ }
42
+ catch (error) {
43
+ logger.error(`Error triggering action callback for ID ${id}:`, {
44
+ error,
45
+ });
46
+ return false;
47
+ }
48
+ }
49
+ logger.warn(`No action callback found for ID ${id}`);
50
+ return false;
51
+ }
52
+ triggerCancel(id) {
53
+ const callbacks = this.callbacks.get(id);
54
+ if (!callbacks) {
55
+ logger.warn(`No callbacks found for ID ${id}`);
56
+ return false;
57
+ }
58
+ if (callbacks.cancel && typeof callbacks.cancel === 'function') {
59
+ try {
60
+ callbacks.cancel();
61
+ logger.debug(`Triggered cancel callback for ID ${id}`);
62
+ return true;
63
+ }
64
+ catch (error) {
65
+ logger.error(`Error triggering cancel callback for ID ${id}:`, {
66
+ error,
67
+ });
68
+ return false;
69
+ }
70
+ }
71
+ logger.warn(`No cancel callback found for ID ${id}`);
72
+ return false;
73
+ }
74
+ triggerSecondary(id) {
75
+ const callbacks = this.callbacks.get(id);
76
+ if (!callbacks) {
77
+ logger.warn(`No callbacks found for ID ${id}`);
78
+ return false;
79
+ }
80
+ if (callbacks.secondary && typeof callbacks.secondary === 'function') {
81
+ try {
82
+ callbacks.secondary();
83
+ logger.debug(`Triggered secondary callback for ID ${id}`);
84
+ return true;
85
+ }
86
+ catch (error) {
87
+ logger.error(`Error triggering secondary callback for ID ${id}:`, {
88
+ error,
89
+ });
90
+ return false;
91
+ }
92
+ }
93
+ logger.warn(`No secondary callback found for ID ${id}`);
94
+ return false;
95
+ }
96
+ clear(id) {
97
+ const existed = this.callbacks.has(id);
98
+ if (existed) {
99
+ const callbacks = this.callbacks.get(id);
100
+ this.callbacks.delete(id);
101
+ if (callbacks) {
102
+ logger.debug(`Cleared callbacks for ID ${id}`, {
103
+ createdAt: callbacks.createdAt,
104
+ age: Date.now() - callbacks.createdAt.getTime(),
105
+ });
106
+ }
107
+ }
108
+ else {
109
+ logger.warn(`No callbacks found to clear for ID ${id}`);
110
+ }
111
+ return existed;
112
+ }
113
+ get(id) {
114
+ return this.callbacks.get(id);
115
+ }
116
+ getAllIds() {
117
+ return Array.from(this.callbacks.keys());
118
+ }
119
+ clearAll() {
120
+ const count = this.callbacks.size;
121
+ this.callbacks.clear();
122
+ logger.debug(`Cleared all callbacks (${count} total)`);
123
+ }
124
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Frame Registry
3
+ * Manages iframe references with UUID tracking
4
+ */
5
+ export declare class FrameRegistry {
6
+ private iframes;
7
+ getUuidByIframe(windowRef: Window | null | undefined): string | undefined;
8
+ addIframe(iframe: HTMLIFrameElement): string;
9
+ removeIframe(identifier: string | HTMLIFrameElement): boolean;
10
+ getAllIframes(): Array<[string, HTMLIFrameElement]>;
11
+ }
12
+ //# sourceMappingURL=frameRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameRegistry.d.ts","sourceRoot":"","sources":["../../src/utils/frameRegistry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAwC;IAEvD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;IAczE,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;IAW5C,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,GAAG,OAAO;IAwB7D,aAAa,IAAI,KAAK,CAAC,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAGpD"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Frame Registry
3
+ * Manages iframe references with UUID tracking
4
+ */
5
+ import { getLogger } from '../logger/logger.js';
6
+ import { generateUuid } from './uuid.js';
7
+ const logger = getLogger('shellsdk');
8
+ export class FrameRegistry {
9
+ constructor() {
10
+ this.iframes = new Map();
11
+ }
12
+ getUuidByIframe(windowRef) {
13
+ if (!windowRef) {
14
+ return undefined;
15
+ }
16
+ for (const [uuid, iframe] of this.iframes.entries()) {
17
+ if (iframe?.contentWindow === windowRef) {
18
+ return uuid;
19
+ }
20
+ }
21
+ return undefined;
22
+ }
23
+ addIframe(iframe) {
24
+ if (!iframe || !(iframe instanceof HTMLIFrameElement)) {
25
+ throw new Error('addIframe requires a valid HTMLIFrameElement');
26
+ }
27
+ const uuid = generateUuid();
28
+ this.iframes.set(uuid, iframe);
29
+ logger.debug(`Added iframe with UUID: ${uuid}`);
30
+ return uuid;
31
+ }
32
+ removeIframe(identifier) {
33
+ if (typeof identifier === 'string') {
34
+ const removed = this.iframes.delete(identifier);
35
+ if (removed) {
36
+ logger.debug(`Removed iframe with UUID: ${identifier}`);
37
+ }
38
+ else {
39
+ logger.warn(`Iframe with UUID not found: ${identifier}`);
40
+ }
41
+ return removed;
42
+ }
43
+ if (identifier instanceof HTMLIFrameElement) {
44
+ for (const [uuid, iframe] of this.iframes.entries()) {
45
+ if (iframe === identifier) {
46
+ this.iframes.delete(uuid);
47
+ logger.debug(`Removed iframe with UUID: ${uuid}`);
48
+ return true;
49
+ }
50
+ }
51
+ logger.warn('Iframe element not found in registry');
52
+ return false;
53
+ }
54
+ throw new Error('removeIframe requires a UUID string or HTMLIFrameElement');
55
+ }
56
+ getAllIframes() {
57
+ return Array.from(this.iframes.entries());
58
+ }
59
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Message Listener Registry
3
+ * Manages message listeners for ShellUI message types
4
+ */
5
+ import type { ShellUIMessage } from '../types.js';
6
+ import type { FrameRegistry } from './frameRegistry.js';
7
+ export type MessageListener = (messageData: ShellUIMessage, originalEvent: MessageEvent) => void;
8
+ export declare class MessageListenerRegistry {
9
+ private listeners;
10
+ private messageHandler;
11
+ private isListening;
12
+ private frameRegistry;
13
+ constructor(frameRegistry?: FrameRegistry | null);
14
+ setupGlobalListener(): void;
15
+ teardownGlobalListener(): void;
16
+ addMessageListener(messageType: string, listener: MessageListener): () => void;
17
+ removeMessageListener(messageType: string, listener: MessageListener): boolean;
18
+ getListenerCount(messageType: string): number;
19
+ removeAllListeners(messageType: string): number;
20
+ removeAllListenersForAllTypes(): void;
21
+ sendMessage(message: ShellUIMessage): number;
22
+ propagateMessage(message: ShellUIMessage): number;
23
+ sendMessageToParent(message: ShellUIMessage): boolean;
24
+ }
25
+ //# sourceMappingURL=messageListenerRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messageListenerRegistry.d.ts","sourceRoot":"","sources":["../../src/utils/messageListenerRegistry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC;AAEjG,qBAAa,uBAAuB;IAClC,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,cAAc,CAAgD;IACtE,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAuB;gBAEhC,aAAa,GAAE,aAAa,GAAG,IAAW;IAItD,mBAAmB,IAAI,IAAI;IAwE3B,sBAAsB,IAAI,IAAI;IAW9B,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,MAAM,IAAI;IAuB9E,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO;IAuB9E,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAK7C,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAgB/C,6BAA6B,IAAI,IAAI;IAMrC,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM;IAoD5C,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM;IAQjD,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;CAatD"}