@weave-apps/sdk 0.1.17 → 0.1.19

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.
@@ -1,274 +0,0 @@
1
- /**
2
- * Sidekick API Client
3
- *
4
- * Client-side API for iframe apps to interact with the Sidekick backend
5
- * through a secure proxy in the sidebar.
6
- *
7
- * Apps can call AI services and manage their own app data.
8
- */
9
- /**
10
- * API operation types
11
- */
12
- var APIOperation;
13
- (function (APIOperation) {
14
- // AI Service
15
- APIOperation["AI_CHAT"] = "AI_CHAT";
16
- // App Data Service
17
- APIOperation["APP_DATA_GET_ALL"] = "APP_DATA_GET_ALL";
18
- APIOperation["APP_DATA_CREATE"] = "APP_DATA_CREATE";
19
- APIOperation["APP_DATA_GET"] = "APP_DATA_GET";
20
- APIOperation["APP_DATA_UPDATE"] = "APP_DATA_UPDATE";
21
- APIOperation["APP_DATA_DELETE"] = "APP_DATA_DELETE";
22
- })(APIOperation || (APIOperation = {}));
23
- /**
24
- * Sidekick API Client
25
- * Provides methods for iframe apps to interact with Sidekick backend
26
- */
27
- export class SidekickAPIClient {
28
- constructor() {
29
- this.pendingRequests = new Map();
30
- this.messageListener = null;
31
- this.requestCounter = 0;
32
- this.timeout = 180000; // 3 minute timeout for API calls (AI can take time on large forms)
33
- this.appId = null; // App ID set by the app
34
- // ============================================================================
35
- // AI Service
36
- // ============================================================================
37
- /**
38
- * Send a chat message to the AI service
39
- *
40
- * Note: App ID is automatically injected by the APIBridge.
41
- * You only need to provide the prompt and optional context.
42
- *
43
- * @example
44
- * ```javascript
45
- * const response = await sidekickAPI.ai.chat({
46
- * prompt: 'What is the capital of France?',
47
- * context: 'User is learning geography'
48
- * });
49
- * ```
50
- */
51
- this.ai = {
52
- chat: async (request) => {
53
- return this.sendRequest(APIOperation.AI_CHAT, request);
54
- }
55
- };
56
- // ============================================================================
57
- // App Data Service
58
- // ============================================================================
59
- /**
60
- * App Data operations - CRUD for app-specific data storage
61
- */
62
- this.appData = {
63
- /**
64
- * Get all app data for the current company (paginated)
65
- *
66
- * Returns a paginated response with data and metadata.
67
- * Default limit is 25 items. For apps with large datasets (500-5000+ rows),
68
- * use pagination to avoid performance issues.
69
- *
70
- * @example
71
- * ```javascript
72
- * // Get first page (default: 25 items)
73
- * const response = await sidekickAPI.appData.getAll();
74
- *
75
- * // Access the array of items
76
- * const items = response.data;
77
- * items.forEach(item => {
78
- * });
79
- * ```
80
- */
81
- getAll: async () => {
82
- return this.sendRequest(APIOperation.APP_DATA_GET_ALL, {});
83
- },
84
- /**
85
- * Create new app data
86
- *
87
- * Note: App ID is automatically injected by the APIBridge.
88
- *
89
- * @example
90
- * ```javascript
91
- * const newData = await sidekickAPI.appData.create({
92
- * dataKey: 'user-preferences',
93
- * data: { theme: 'dark', language: 'en' }
94
- * });
95
- * ```
96
- */
97
- create: async (request) => {
98
- return this.sendRequest(APIOperation.APP_DATA_CREATE, request);
99
- },
100
- /**
101
- * Get specific app data by ID
102
- *
103
- * @example
104
- * ```javascript
105
- * const data = await sidekickAPI.appData.get('data-id-123');
106
- * ```
107
- */
108
- get: async (appDataId) => {
109
- return this.sendRequest(APIOperation.APP_DATA_GET, { appDataId });
110
- },
111
- /**
112
- * Update existing app data
113
- *
114
- * @example
115
- * ```javascript
116
- * const updated = await sidekickAPI.appData.update('data-id-123', {
117
- * data: { theme: 'light' }
118
- * });
119
- * ```
120
- */
121
- update: async (appDataId, request) => {
122
- return this.sendRequest(APIOperation.APP_DATA_UPDATE, {
123
- appDataId,
124
- ...request
125
- });
126
- },
127
- /**
128
- * Delete app data
129
- *
130
- * @example
131
- * ```javascript
132
- * await sidekickAPI.appData.delete('data-id-123');
133
- * ```
134
- */
135
- delete: async (appDataId) => {
136
- return this.sendRequest(APIOperation.APP_DATA_DELETE, { appDataId });
137
- }
138
- };
139
- /**
140
- * Utility functions for common operations
141
- *
142
- * Note: These utilities are loaded from the sidebar-loader at runtime.
143
- * They are available through the window object and don't need to be bundled with apps.
144
- */
145
- this.utils = {
146
- /**
147
- * Convert HTML to Markdown
148
- *
149
- * @example
150
- * ```javascript
151
- * const markdown = sidekickAPI.utils.htmlToMarkdown('<h1>Hello</h1>');
152
- * console.log(markdown); // # Hello
153
- * ```
154
- */
155
- htmlToMarkdown: (html) => {
156
- // Access the utility from window object (loaded by sidebar-loader)
157
- if (typeof window !== 'undefined' && window.__sidekickUtils?.htmlToMarkdown) {
158
- return window.__sidekickUtils.htmlToMarkdown(html);
159
- }
160
- throw new Error('htmlToMarkdown utility not available. Ensure sidebar-loader is loaded.');
161
- },
162
- /**
163
- * Convert Markdown to HTML (sanitized)
164
- *
165
- * @example
166
- * ```javascript
167
- * const html = sidekickAPI.utils.markdownToHtml('# Hello');
168
- * console.log(html); // <h1>Hello</h1>
169
- * ```
170
- */
171
- markdownToHtml: (markdown) => {
172
- // Access the utility from window object (loaded by sidebar-loader)
173
- if (typeof window !== 'undefined' && window.__sidekickUtils?.markdownToHtml) {
174
- return window.__sidekickUtils.markdownToHtml(markdown);
175
- }
176
- throw new Error('markdownToHtml utility not available. Ensure sidebar-loader is loaded.');
177
- }
178
- };
179
- this.initialize();
180
- }
181
- /**
182
- * Set the app ID for this client
183
- * Called automatically by SidekickBaseApp
184
- */
185
- setAppId(appId) {
186
- this.appId = appId;
187
- }
188
- /**
189
- * Initialize the API client and start listening for responses
190
- */
191
- initialize() {
192
- this.messageListener = (event) => {
193
- this.handleResponse(event);
194
- };
195
- window.addEventListener('message', this.messageListener);
196
- }
197
- /**
198
- * Cleanup
199
- */
200
- destroy() {
201
- if (this.messageListener) {
202
- window.removeEventListener('message', this.messageListener);
203
- this.messageListener = null;
204
- }
205
- this.pendingRequests.clear();
206
- }
207
- /**
208
- * Handle response from sidebar
209
- */
210
- handleResponse(event) {
211
- const data = event.data;
212
- if (data?.type !== 'SIDEKICK_API_RESPONSE') {
213
- return;
214
- }
215
- const response = data;
216
- const pending = this.pendingRequests.get(response.id);
217
- if (!pending) {
218
- return;
219
- }
220
- this.pendingRequests.delete(response.id);
221
- if (response.success) {
222
- pending.resolve(response.data);
223
- }
224
- else {
225
- pending.reject(new Error(response.error || 'Unknown error'));
226
- }
227
- }
228
- /**
229
- * Send request to sidebar
230
- */
231
- sendRequest(operation, payload) {
232
- return new Promise((resolve, reject) => {
233
- const id = `api-request-${++this.requestCounter}`;
234
- const request = {
235
- type: 'SIDEKICK_API_REQUEST',
236
- id,
237
- operation,
238
- payload,
239
- appId: this.appId || undefined, // Include app ID if set
240
- };
241
- // Store pending request
242
- this.pendingRequests.set(id, { resolve, reject });
243
- // Set timeout
244
- const timeoutId = setTimeout(() => {
245
- this.pendingRequests.delete(id);
246
- reject(new Error(`Request timeout: ${operation}`));
247
- }, this.timeout);
248
- // Clear timeout on resolve/reject
249
- const originalResolve = resolve;
250
- const originalReject = reject;
251
- this.pendingRequests.set(id, {
252
- resolve: (value) => {
253
- clearTimeout(timeoutId);
254
- originalResolve(value);
255
- },
256
- reject: (error) => {
257
- clearTimeout(timeoutId);
258
- originalReject(error);
259
- },
260
- });
261
- // Send to current window (sidebar APIBridge will intercept)
262
- // Apps run in the sidebar's window, not in a separate iframe
263
- window.postMessage(request, '*');
264
- APIOperation;
265
- });
266
- }
267
- }
268
- // Create singleton instance
269
- const sidekickAPI = new SidekickAPIClient();
270
- // Export for global usage
271
- if (typeof window !== 'undefined') {
272
- window.sidekickAPI = sidekickAPI;
273
- }
274
- export default sidekickAPI;
@@ -1,177 +0,0 @@
1
- /**
2
- * Sidekick Base App
3
- *
4
- * Base class for all Sidekick apps. Provides common functionality and lifecycle methods.
5
- * Third-party developers should extend this class instead of HTMLElement directly.
6
- *
7
- * @example
8
- * ```typescript
9
- * // Define your settings and state types
10
- * interface MyAppSettings {
11
- * apiKey: string;
12
- * endpoint: string;
13
- * autoSave?: boolean;
14
- * }
15
- *
16
- * interface MyAppState {
17
- * count: number;
18
- * isLoading: boolean;
19
- * data: any[];
20
- * }
21
- *
22
- * class MyApp extends SidekickBaseApp<MyAppSettings, MyAppState> {
23
- * constructor() {
24
- * super({
25
- * id: 'my-app',
26
- * name: 'My App',
27
- * version: '1.0.0',
28
- * category: 'utility',
29
- * description: 'My custom app',
30
- * author: 'Your Name',
31
- * tags: ['custom']
32
- * });
33
- *
34
- * // Settings are now type-safe!
35
- * const apiKey = this.appSettings?.apiKey; // ✅ TypeScript knows this exists
36
- *
37
- * // Initialize state with proper typing
38
- * this.state = {
39
- * count: 0,
40
- * isLoading: false,
41
- * data: []
42
- * };
43
- * }
44
- *
45
- * render() {
46
- * return `<div>My App Content</div>`;
47
- * }
48
- *
49
- * setupEventListeners() {
50
- * // setState is also type-safe
51
- * this.setState({ count: this.state.count + 1 }); // ✅ Type-safe
52
- * }
53
- * }
54
- *
55
- * customElements.define('my-app', MyApp);
56
- * ```
57
- */
58
- /**
59
- * App metadata configuration
60
- */
61
- export interface SidekickAppInfo {
62
- /** Unique identifier for the app (kebab-case recommended) */
63
- id: string;
64
- /** Display name of the app */
65
- name: string;
66
- /** Semantic version (x.y.z) */
67
- version: string;
68
- /** Primary category for the app */
69
- category: string;
70
- /** Detailed description of the app */
71
- description: string;
72
- /** Author or organization name */
73
- author: string;
74
- /** Additional tags for search and categorization */
75
- tags?: string[];
76
- }
77
- /**
78
- * Base class for Sidekick apps
79
- * @template TSettings - Type for app settings, defaults to an empty object
80
- * @template TState - Type for app state, defaults to an empty object
81
- */
82
- export declare abstract class SidekickBaseApp<TSettings = Record<string, any>, TState = Record<string, any>> extends HTMLElement {
83
- /** App metadata */
84
- protected appInfo: SidekickAppInfo;
85
- /** App settings (override in subclass) **/
86
- protected appSettings?: TSettings;
87
- /** App-specific state (override in subclass) */
88
- protected state: TState;
89
- /** Shadow root for style isolation */
90
- private _shadowRoot;
91
- /** App-specific API client instance (prevents app ID conflicts) */
92
- protected sidekickAPI: any;
93
- /**
94
- * Creates a new Sidekick app
95
- * @param appInfo - App metadata configuration
96
- */
97
- constructor(appInfo: SidekickAppInfo);
98
- /**
99
- * Get shadow root (override native property)
100
- */
101
- get shadowRoot(): ShadowRoot;
102
- /**
103
- * Background service - optional override in subclass
104
- * Called immediately after app instantiation, before DOM attachment
105
- * Use this for background tasks like URL monitoring, event listening, etc.
106
- */
107
- protected onBackgroundService?(): void;
108
- /**
109
- * URL change handler - optional override in subclass
110
- * Called when the page URL changes (SPA navigation)
111
- * @param url - The new URL
112
- */
113
- protected onUrlChange?(url: string): void;
114
- /**
115
- * Render method - must be implemented by subclass
116
- * Should return HTML string or directly manipulate shadowRoot
117
- */
118
- protected render(): void;
119
- /**
120
- * Setup event listeners - optional override in subclass
121
- */
122
- protected setupEventListeners(): void;
123
- /**
124
- * Initialize background service
125
- * Called by BackgroundAppManager after instantiation
126
- */
127
- initializeBackgroundService(): void;
128
- /**
129
- * Handle URL change
130
- * Called by BackgroundAppManager when URL changes
131
- */
132
- handleUrlChange(url: string): void;
133
- /**
134
- * Lifecycle: Called when element is added to DOM
135
- * This happens when user opens the app in the drawer
136
- */
137
- connectedCallback(): void;
138
- /**
139
- * Lifecycle: Called when element is removed from DOM
140
- */
141
- disconnectedCallback(): void;
142
- /**
143
- * Cleanup method - optional override in subclass
144
- * Called when app is disconnected from DOM
145
- */
146
- protected cleanup(): void;
147
- /**
148
- * Get app configuration (for Sidekick Platform)
149
- */
150
- getAppInfo(): SidekickAppInfo;
151
- /**
152
- * Get current app state (for Sidekick Platform)
153
- */
154
- getAppState(): Record<string, any>;
155
- /**
156
- * Set app configuration (for Sidekick Platform)
157
- * Override this method to handle configuration updates
158
- */
159
- setAppConfig(_config: Record<string, any>): void;
160
- /**
161
- * Helper: Update app state
162
- */
163
- protected setState(updates: Partial<TState>): void;
164
- /**
165
- * Helper: Render HTML into shadow root
166
- */
167
- protected renderHTML(html: string): void;
168
- /**
169
- * Helper: Query element in shadow root
170
- */
171
- protected query<T extends Element = Element>(selector: string): T | null;
172
- /**
173
- * Helper: Query all elements in shadow root
174
- */
175
- protected queryAll<T extends Element = Element>(selector: string): NodeListOf<T>;
176
- }
177
- //# sourceMappingURL=SidekickBaseApp.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SidekickBaseApp.d.ts","sourceRoot":"","sources":["../src/SidekickBaseApp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;GAIG;AACH,8BAAsB,eAAe,CACnC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAC5B,SAAQ,WAAW;IACnB,mBAAmB;IACnB,SAAS,CAAC,OAAO,EAAE,eAAe,CAAC;IAEnC,2CAA2C;IAC3C,SAAS,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;IAElC,gDAAgD;IAChD,SAAS,CAAC,KAAK,EAAE,MAAM,CAAgB;IAEvC,sCAAsC;IACtC,OAAO,CAAC,WAAW,CAAa;IAEhC,mEAAmE;IACnE,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC;IAE3B;;;OAGG;gBACS,OAAO,EAAE,eAAe;IAyCpC;;OAEG;IACH,IAAI,UAAU,IAAI,UAAU,CAE3B;IAED;;;;OAIG;IACH,SAAS,CAAC,mBAAmB,CAAC,IAAI,IAAI;IAEtC;;;;OAIG;IACH,SAAS,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAEzC;;;OAGG;IACH,SAAS,CAAC,MAAM,IAAI,IAAI;IAIxB;;OAEG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI;IAIrC;;;OAGG;IACI,2BAA2B,IAAI,IAAI;IAO1C;;;OAGG;IACI,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMzC;;;OAGG;IACH,iBAAiB,IAAI,IAAI;IAoBzB;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAI5B;;;OAGG;IACH,SAAS,CAAC,OAAO,IAAI,IAAI;IAIzB;;OAEG;IACI,UAAU,IAAI,eAAe;IAIpC;;OAEG;IACI,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAOzC;;;OAGG;IACI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAIvD;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI;IAIlD;;OAEG;IACH,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQxC;;OAEG;IACH,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAIxE;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC;CAGjF"}
@@ -1,228 +0,0 @@
1
- /**
2
- * Sidekick Base App
3
- *
4
- * Base class for all Sidekick apps. Provides common functionality and lifecycle methods.
5
- * Third-party developers should extend this class instead of HTMLElement directly.
6
- *
7
- * @example
8
- * ```typescript
9
- * // Define your settings and state types
10
- * interface MyAppSettings {
11
- * apiKey: string;
12
- * endpoint: string;
13
- * autoSave?: boolean;
14
- * }
15
- *
16
- * interface MyAppState {
17
- * count: number;
18
- * isLoading: boolean;
19
- * data: any[];
20
- * }
21
- *
22
- * class MyApp extends SidekickBaseApp<MyAppSettings, MyAppState> {
23
- * constructor() {
24
- * super({
25
- * id: 'my-app',
26
- * name: 'My App',
27
- * version: '1.0.0',
28
- * category: 'utility',
29
- * description: 'My custom app',
30
- * author: 'Your Name',
31
- * tags: ['custom']
32
- * });
33
- *
34
- * // Settings are now type-safe!
35
- * const apiKey = this.appSettings?.apiKey; // ✅ TypeScript knows this exists
36
- *
37
- * // Initialize state with proper typing
38
- * this.state = {
39
- * count: 0,
40
- * isLoading: false,
41
- * data: []
42
- * };
43
- * }
44
- *
45
- * render() {
46
- * return `<div>My App Content</div>`;
47
- * }
48
- *
49
- * setupEventListeners() {
50
- * // setState is also type-safe
51
- * this.setState({ count: this.state.count + 1 }); // ✅ Type-safe
52
- * }
53
- * }
54
- *
55
- * customElements.define('my-app', MyApp);
56
- * ```
57
- */
58
- /**
59
- * Base class for Sidekick apps
60
- * @template TSettings - Type for app settings, defaults to an empty object
61
- * @template TState - Type for app state, defaults to an empty object
62
- */
63
- export class SidekickBaseApp extends HTMLElement {
64
- /**
65
- * Creates a new Sidekick app
66
- * @param appInfo - App metadata configuration
67
- */
68
- constructor(appInfo) {
69
- super();
70
- /** App-specific state (override in subclass) */
71
- this.state = {};
72
- // Validate required fields
73
- if (!appInfo.id || !appInfo.name || !appInfo.version) {
74
- throw new Error('SidekickBaseApp: id, name, and version are required');
75
- }
76
- this.appInfo = appInfo;
77
- // Create shadow DOM for style isolation and store reference
78
- this._shadowRoot = this.attachShadow({ mode: 'open' });
79
- // Read UUID and settings from global registry (set by BackgroundAppManager before element creation)
80
- // This allows the constructor to access both UUID and settings immediately
81
- const registry = window.__sidekickAppRegistry;
82
- const tagName = this.tagName.toLowerCase();
83
- const registryData = registry?.[tagName];
84
- // Set app settings if available in registry
85
- if (registryData?.settings) {
86
- this.appSettings = registryData.settings;
87
- }
88
- // Set app UUID on the global API client so it's included in all requests
89
- // This allows background services to make API calls without the app being open
90
- if (window.sidekickAPI) {
91
- const appUuid = registryData?.uuid;
92
- if (appUuid) {
93
- // Create a new API client instance for THIS app
94
- this.sidekickAPI = new window.SidekickAPIClient();
95
- this.sidekickAPI.setAppId(appUuid);
96
- }
97
- else {
98
- console.warn('⚠️ App UUID not found in registry - API calls may fail. App:', appInfo.id);
99
- // Fallback to global API client (will have wrong app ID, but better than nothing)
100
- this.sidekickAPI = window.sidekickAPI;
101
- }
102
- }
103
- }
104
- /**
105
- * Get shadow root (override native property)
106
- */
107
- get shadowRoot() {
108
- return this._shadowRoot;
109
- }
110
- /**
111
- * Render method - must be implemented by subclass
112
- * Should return HTML string or directly manipulate shadowRoot
113
- */
114
- render() {
115
- // Default implementation - subclasses should override
116
- }
117
- /**
118
- * Setup event listeners - optional override in subclass
119
- */
120
- setupEventListeners() {
121
- // Default implementation - subclasses can override
122
- }
123
- /**
124
- * Initialize background service
125
- * Called by BackgroundAppManager after instantiation
126
- */
127
- initializeBackgroundService() {
128
- if (this.onBackgroundService) {
129
- this.onBackgroundService();
130
- }
131
- }
132
- /**
133
- * Handle URL change
134
- * Called by BackgroundAppManager when URL changes
135
- */
136
- handleUrlChange(url) {
137
- if (this.onUrlChange) {
138
- this.onUrlChange(url);
139
- }
140
- }
141
- /**
142
- * Lifecycle: Called when element is added to DOM
143
- * This happens when user opens the app in the drawer
144
- */
145
- connectedCallback() {
146
- // Render the app UI
147
- this.render();
148
- // Setup event listeners for UI
149
- this.setupEventListeners();
150
- // Notify Sidekick Platform that app UI is ready
151
- this.dispatchEvent(new CustomEvent('sidekick-app-ready', {
152
- detail: {
153
- appInfo: this.appInfo,
154
- timestamp: new Date().toISOString()
155
- },
156
- bubbles: true,
157
- composed: true
158
- }));
159
- }
160
- /**
161
- * Lifecycle: Called when element is removed from DOM
162
- */
163
- disconnectedCallback() {
164
- this.cleanup();
165
- }
166
- /**
167
- * Cleanup method - optional override in subclass
168
- * Called when app is disconnected from DOM
169
- */
170
- cleanup() {
171
- // Default implementation - subclasses can override
172
- }
173
- /**
174
- * Get app configuration (for Sidekick Platform)
175
- */
176
- getAppInfo() {
177
- return this.appInfo;
178
- }
179
- /**
180
- * Get current app state (for Sidekick Platform)
181
- */
182
- getAppState() {
183
- return {
184
- ...this.state,
185
- lastUpdated: new Date().toISOString()
186
- };
187
- }
188
- /**
189
- * Set app configuration (for Sidekick Platform)
190
- * Override this method to handle configuration updates
191
- */
192
- setAppConfig(_config) {
193
- // Default implementation - subclasses can override
194
- }
195
- /**
196
- * Helper: Update app state
197
- */
198
- setState(updates) {
199
- this.state = { ...this.state, ...updates };
200
- }
201
- /**
202
- * Helper: Render HTML into shadow root
203
- */
204
- renderHTML(html) {
205
- if (this._shadowRoot) {
206
- this._shadowRoot.innerHTML = html;
207
- }
208
- else {
209
- console.error('❌ No shadow root available!');
210
- }
211
- }
212
- /**
213
- * Helper: Query element in shadow root
214
- */
215
- query(selector) {
216
- return this._shadowRoot?.querySelector(selector) || null;
217
- }
218
- /**
219
- * Helper: Query all elements in shadow root
220
- */
221
- queryAll(selector) {
222
- return this._shadowRoot?.querySelectorAll(selector) || [];
223
- }
224
- }
225
- // Export for global usage
226
- if (typeof window !== 'undefined') {
227
- window.SidekickBaseApp = SidekickBaseApp;
228
- }