@cshah18/sdk 4.8.0 → 4.9.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.
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Input validation helpers for SDK configuration and widget options
3
+ */
4
+ /**
5
+ * Validate product ID format and constraints
6
+ *
7
+ * @param {string} productId - The product ID to validate
8
+ * @returns {boolean} True if product ID is valid, false otherwise
9
+ *
10
+ * @description
11
+ * Validates that a product ID meets the following criteria:
12
+ * - Must be a non-empty string
13
+ * - Maximum length of 200 characters
14
+ * - Cannot be only whitespace
15
+ *
16
+ * @example
17
+ * validateProductId("prod_123"); // ✅ true
18
+ * validateProductId(""); // ❌ false (empty)
19
+ * validateProductId("x".repeat(201)); // ❌ false (too long)
20
+ */
21
+ export declare function validateProductId(productId: string): boolean;
22
+ /**
23
+ * Validate CSS color format
24
+ *
25
+ * @param {string} color - The color value to validate
26
+ * @returns {boolean} True if color is valid CSS format, false otherwise
27
+ *
28
+ * @description
29
+ * Validates that a color value is valid CSS format. Supports:
30
+ * - **Hex Colors**: #RGB, #RRGGBB, #RRGGBBAA
31
+ * - **RGB/RGBA**: rgb(255, 0, 0), rgba(255, 0, 0, 0.5)
32
+ * - **HSL/HSLA**: hsl(0, 100%, 50%), hsla(0, 100%, 50%, 0.5)
33
+ * - **Named Colors**: transparent, inherit, initial, unset
34
+ *
35
+ * @example
36
+ * validateColor("#4f46e5"); // ✅ true (hex)
37
+ * validateColor("#4f46e5cc"); // ✅ true (hex with alpha)
38
+ * validateColor("rgb(0, 0, 0)"); // ✅ true (rgb)
39
+ * validateColor("notacolor"); // ❌ false (invalid)
40
+ */
41
+ export declare function validateColor(color: string): boolean;
42
+ /**
43
+ * Validate CSS border radius format
44
+ *
45
+ * @param {string} borderRadius - The border radius value to validate
46
+ * @returns {boolean} True if border radius is valid CSS format, false otherwise
47
+ *
48
+ * @description
49
+ * Validates that a border radius value is valid CSS format.
50
+ * Supports common CSS units: px, rem, em, %, ch, ex, vw, vh, vmin, vmax
51
+ *
52
+ * @example
53
+ * validateBorderRadius("8px"); // ✅ true
54
+ * validateBorderRadius("0.5rem"); // ✅ true
55
+ * validateBorderRadius("8"); // ✅ true (assumes pixels)
56
+ * validateBorderRadius("notsize"); // ❌ false
57
+ */
58
+ export declare function validateBorderRadius(borderRadius: string): boolean;
59
+ /**
60
+ * Validate CSS font family format
61
+ *
62
+ * @param {string} fontFamily - The font family value to validate
63
+ * @returns {boolean} True if font family is valid, false otherwise
64
+ *
65
+ * @description
66
+ * Validates that a font family value is suitable for use.
67
+ * - Must not be empty or whitespace-only
68
+ * - Maximum length of 500 characters
69
+ * - Can be single font or comma-separated list
70
+ *
71
+ * @example
72
+ * validateFontFamily("Inter, sans-serif"); // ✅ true
73
+ * validateFontFamily("'Courier New', monospace"); // ✅ true
74
+ * validateFontFamily(""); // ❌ false (empty)
75
+ */
76
+ export declare function validateFontFamily(fontFamily: string): boolean;
77
+ /**
78
+ * Validate animation speed value
79
+ *
80
+ * @param {string} speed - The animation speed to validate
81
+ * @returns {boolean} True if speed is a valid animation speed value, false otherwise
82
+ *
83
+ * @description
84
+ * Validates that the animation speed is one of the predefined values.
85
+ * Valid values: "none", "fast", "normal", "slow"
86
+ *
87
+ * @example
88
+ * validateAnimationSpeed("normal"); // ✅ true
89
+ * validateAnimationSpeed("slow"); // ✅ true
90
+ * validateAnimationSpeed("fast"); // ✅ true (case-insensitive)
91
+ * validateAnimationSpeed("SLOW"); // ✅ true
92
+ * validateAnimationSpeed("instant"); // ❌ false (invalid value)
93
+ */
94
+ export declare function validateAnimationSpeed(speed: string): boolean;
95
+ /**
96
+ * Validate animation style value
97
+ *
98
+ * @param {string} style - The animation style to validate
99
+ * @returns {boolean} True if style is a valid animation style value, false otherwise
100
+ *
101
+ * @description
102
+ * Validates that the animation style is one of the predefined values.
103
+ * Valid values: "none", "subtle", "smooth", "bouncy"
104
+ * - *none*: No animation
105
+ * - *subtle*: Fade only (no movement)
106
+ * - *smooth*: Fade + slide animation
107
+ * - *bouncy*: Spring-like bounce effect
108
+ *
109
+ * @example
110
+ * validateAnimationStyle("subtle"); // ✅ true
111
+ * validateAnimationStyle("SMOOTH"); // ✅ true (case-insensitive)
112
+ * validateAnimationStyle("bouncy"); // ✅ true
113
+ * validateAnimationStyle("custom"); // ❌ false (invalid)
114
+ */
115
+ export declare function validateAnimationStyle(style: string): boolean;
116
+ /**
117
+ * Validate widget container (selector or element)
118
+ *
119
+ * @param {string | HTMLElement} container - CSS selector string or HTMLElement
120
+ * @returns {boolean} True if container is valid, false otherwise
121
+ *
122
+ * @description
123
+ * Validates that a container is either a valid CSS selector string or
124
+ * an actual HTMLElement instance for widget rendering.
125
+ *
126
+ * @example
127
+ * validateContainer("#my-widget"); // ✅ true (valid selector)
128
+ * validateContainer(document.getElementById("target")); // ✅ true (element)
129
+ * validateContainer(""); // ❌ false (empty selector)
130
+ * validateContainer(" "); // ❌ false (whitespace)
131
+ */
132
+ export declare function validateContainer(container: string | HTMLElement): boolean;
133
+ /**
134
+ * Validate merchant authentication key
135
+ *
136
+ * @param {string} merchantKey - The merchant key to validate
137
+ * @returns {boolean} True if merchant key is valid, false otherwise
138
+ *
139
+ * @description
140
+ * Validates that a merchant key is properly formatted for authentication.
141
+ * - Must be a non-empty string
142
+ * - Maximum length of 500 characters
143
+ * - Cannot be whitespace-only
144
+ *
145
+ * @example
146
+ * validateMerchantKey("pk_live_abc123xyz"); // ✅ true
147
+ * validateMerchantKey(""); // ❌ false (empty)
148
+ * validateMerchantKey(" "); // ❌ false (whitespace)
149
+ */
150
+ export declare function validateMerchantKey(merchantKey: string): boolean;
151
+ /**
152
+ * Validate session authentication token
153
+ *
154
+ * @param {string | Function} token - Session token string or function
155
+ * @returns {boolean} True if token is valid, false otherwise
156
+ *
157
+ * @description
158
+ * Validates that a session token is either:
159
+ * - A non-empty string token, OR
160
+ * - A function that returns a string or Promise<string> for async token retrieval
161
+ *
162
+ * This allows both static tokens and dynamic token providers.
163
+ *
164
+ * @example
165
+ * validateSessionToken("token_abc123"); // ✅ true
166
+ * validateSessionToken(() => "dynamic_token"); // ✅ true
167
+ * validateSessionToken(async () => await fetchToken()); // ✅ true
168
+ * validateSessionToken(""); // ❌ false (empty string)
169
+ * validateSessionToken({} as any); // ❌ false (not function)
170
+ */
171
+ export declare function validateSessionToken(token: string | (() => string | Promise<string>)): boolean;
@@ -1,13 +1,12 @@
1
- import { CoBuy } from "./core/cobuy";
2
1
  import type { CoBuySDK } from "./core/types";
3
2
  export type { CoBuySDK };
4
3
  export * from "./core/types";
5
4
  export type { AuthStrategy } from "./core/auth-strategy";
6
5
  export { PublicKeyAuth, TokenAuth } from "./core/auth-strategy";
7
- declare const instance: CoBuy;
8
6
  declare global {
9
7
  interface Window {
10
8
  CoBuy?: CoBuySDK;
11
9
  }
12
10
  }
11
+ declare const instance: CoBuySDK;
13
12
  export default instance;
@@ -17,10 +17,10 @@ export interface ApiGroupData extends ProductPrimaryGroupData {
17
17
  */
18
18
  export declare class GroupListModal {
19
19
  private overlayEl;
20
- private logger;
20
+ private readonly logger;
21
21
  private groups;
22
22
  private liveCount;
23
- private apiClient;
23
+ private readonly apiClient;
24
24
  private isLoading;
25
25
  private startButton;
26
26
  private countdownIntervals;
@@ -46,7 +46,7 @@ export declare class GroupListModal {
46
46
  /** Unsubscribe from socket events */
47
47
  private unsubscribeFromSocketEvents;
48
48
  /** Handle group member joined socket event and update groups list */
49
- private onGroupMemberJoined;
49
+ private readonly onGroupMemberJoined;
50
50
  /** Update the rendered group card with new data */
51
51
  private updateGroupCard;
52
52
  open(productId?: string, sessionId?: string, joinedGroupId?: string): Promise<void>;
@@ -2,7 +2,6 @@ import { ApiClient } from "../../core/api-client";
2
2
  import { OfflineRedemption } from "../../core/types";
3
3
  import { AnalyticsClient } from "../../core/analytics";
4
4
  import { SocketManager } from "../../core/socket";
5
- import "./styles/styles.css";
6
5
  export interface LobbyModalData {
7
6
  productId: string;
8
7
  groupId?: string;
@@ -36,19 +35,20 @@ export interface LobbyModalCallbacks {
36
35
  * LobbyModal - Renders and manages the group buying lobby modal
37
36
  */
38
37
  export declare class LobbyModal {
39
- private logger;
40
- private analyticsClient;
41
- private socketManager;
42
- private apiClient;
38
+ private readonly logger;
39
+ private readonly analyticsClient;
40
+ private readonly socketManager;
41
+ private readonly apiClient;
43
42
  private modalElement;
44
43
  private data;
45
- private callbacks;
44
+ private readonly callbacks;
46
45
  private timerInterval;
47
46
  private activityInterval;
48
47
  private activityCards;
49
48
  private socketListenerRegistered;
50
49
  private currentGroupId;
51
50
  private shareOverlay;
51
+ private keyboardHandler;
52
52
  constructor(data: LobbyModalData, callbacks: LobbyModalCallbacks, apiClient: ApiClient | null, analyticsClient: AnalyticsClient | null, socketManager?: SocketManager | null, debug?: boolean);
53
53
  /**
54
54
  * Derive lock state from data so UI reflects completion
@@ -120,6 +120,12 @@ export declare class LobbyModal {
120
120
  * Inject styles for offline redemption section
121
121
  */
122
122
  private injectOfflineRedemptionStyles;
123
+ /**
124
+ * Inject lobby styles into the document head
125
+ * This is called once when the first lobby modal is created
126
+ */
127
+ private static stylesInjected;
128
+ private injectLobbyStyles;
123
129
  /**
124
130
  * Trigger the same checkout flow as clicking "Continue to Checkout" on the widget
125
131
  */
@@ -240,6 +246,18 @@ export declare class LobbyModal {
240
246
  * Open/render the modal
241
247
  */
242
248
  open(groupId?: string): void;
249
+ /**
250
+ * Set up keyboard accessibility features: ESC to close and Tab focus trap
251
+ */
252
+ private setupKeyboardAccessibility;
253
+ /**
254
+ * Get all focusable elements within the modal
255
+ */
256
+ private getFocusableElements;
257
+ /**
258
+ * Clean up keyboard event listeners
259
+ */
260
+ private removeKeyboardAccessibility;
243
261
  /**
244
262
  * Close the modal
245
263
  */
@@ -286,7 +304,7 @@ export declare class LobbyModal {
286
304
  /**
287
305
  * Handle socket group update events
288
306
  */
289
- private handleSocketGroupUpdate;
307
+ private readonly handleSocketGroupUpdate;
290
308
  /**
291
309
  * Create activity item from socket event data
292
310
  */
@@ -5,8 +5,8 @@
5
5
  import { OfflineRedemption } from "../../core/types";
6
6
  export declare class OfflineRedemptionModal {
7
7
  private modalElement;
8
- private offlineRedemption;
9
- private onClose?;
8
+ private readonly offlineRedemption;
9
+ private readonly onClose?;
10
10
  constructor(offlineRedemption: OfflineRedemption, onClose?: () => void);
11
11
  /**
12
12
  * Open the modal
@@ -1,19 +1,137 @@
1
1
  import { CoBuyThemeOptions } from "../../core/types";
2
2
  /**
3
- * Merge global theme with optional widget-specific overrides
4
- * Priority: widgetTheme > globalTheme > defaults
3
+ * Merge global theme with widget-specific theme overrides
4
+ *
5
+ * Combines multiple theme objects with priority: widgetTheme > globalTheme > defaults.
6
+ * Validates all color and style values, falling back to defaults if invalid.
7
+ *
8
+ * @param {CoBuyThemeOptions} [globalTheme={}] - Global theme to apply to all widgets
9
+ * @param {string} [globalTheme.primaryColor] - Primary brand color (validated as CSS color)
10
+ * @param {string} [globalTheme.secondaryColor] - Secondary brand color
11
+ * @param {string} [globalTheme.textColor] - Text color for widget
12
+ * @param {string} [globalTheme.borderRadius] - Border radius for widget elements (CSS size value)
13
+ * @param {string} [globalTheme.fontFamily] - Font family for widget text
14
+ * @param {"none" | "fast" | "normal" | "slow"} [globalTheme.animationSpeed] - Animation speed
15
+ * @param {"none" | "subtle" | "smooth" | "bouncy"} [globalTheme.animationStyle] - Animation style
16
+ *
17
+ * @param {CoBuyThemeOptions} [widgetTheme={}] - Widget-specific theme overrides (takes priority over global)
18
+ * @param {string} [widgetTheme.primaryColor] - Override primary color
19
+ * @param {string} [widgetTheme.secondaryColor] - Override secondary color
20
+ * @param {string} [widgetTheme.textColor] - Override text color
21
+ * @param {string} [widgetTheme.borderRadius] - Override border radius
22
+ * @param {string} [widgetTheme.fontFamily] - Override font family
23
+ * @param {"none" | "fast" | "normal" | "slow"} [widgetTheme.animationSpeed] - Override animation speed
24
+ * @param {"none" | "subtle" | "smooth" | "bouncy"} [widgetTheme.animationStyle] - Override animation style
25
+ *
26
+ * @returns {Required<CoBuyThemeOptions>} Merged theme with all properties defined
27
+ *
28
+ * @description
29
+ * All theme values are validated:
30
+ * - Colors are checked against valid CSS color formats
31
+ * - Border radius is validated as a CSS size value
32
+ * - Font family is validated as a non-empty string
33
+ * - Animation speeds and styles are checked against allowed values
34
+ * - Invalid values are logged and replaced with defaults
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // Merge global and widget themes
39
+ * const theme = mergeTheme(
40
+ * {
41
+ * primaryColor: '#4f46e5',
42
+ * fontFamily: 'Inter, sans-serif'
43
+ * },
44
+ * {
45
+ * primaryColor: '#ff0000' // Override primary color for this widget
46
+ * }
47
+ * );
48
+ * // Result: theme.primaryColor === '#ff0000'
49
+ *
50
+ * // With invalid color (falls back to default)
51
+ * const theme2 = mergeTheme(
52
+ * { primaryColor: 'notacolor' },
53
+ * {}
54
+ * );
55
+ * // Result: theme2.primaryColor === '#4f46e5' (default value)
56
+ * ```
5
57
  */
6
58
  export declare function mergeTheme(globalTheme?: CoBuyThemeOptions, widgetTheme?: CoBuyThemeOptions): Required<CoBuyThemeOptions>;
7
59
  /**
8
- * Apply theme to widget container using scoped CSS custom properties
9
- * This approach ensures:
10
- * 1. Styles are isolated to this widget instance
11
- * 2. No conflicts with merchant's global styles
12
- * 3. Easy runtime theme updates
13
- * 4. Browser handles invalid values gracefully
60
+ * Apply theme to widget container using CSS custom properties
61
+ *
62
+ * Sets scoped CSS variables on the container element to apply theme colors,
63
+ * sizing, fonts, and animations. This approach isolates styles to the widget
64
+ * instance and prevents conflicts with merchant's global styles.
65
+ *
66
+ * @param {HTMLElement} container - The DOM element to apply theme to
67
+ * @param {Required<CoBuyThemeOptions>} theme - The theme configuration to apply
68
+ * @param {string} theme.primaryColor - Primary brand color (applied to --cobuy-primary-color)
69
+ * @param {string} theme.secondaryColor - Secondary color (applied to --cobuy-secondary-color)
70
+ * @param {string} theme.textColor - Text color (applied to --cobuy-text-color)
71
+ * @param {string} theme.borderRadius - Border radius (applied to --cobuy-border-radius)
72
+ * @param {string} theme.fontFamily - Font family (applied to --cobuy-font-family)
73
+ * @param {AnimationSpeed} theme.animationSpeed - Animation speed for transitions
74
+ * @param {AnimationStyle} theme.animationStyle - Animation style/easing
75
+ *
76
+ * @returns {void}
77
+ *
78
+ * @description
79
+ * Sets the following CSS custom properties on the container:
80
+ * - `--cobuy-primary-color`: Primary brand color
81
+ * - `--cobuy-secondary-color`: Secondary color
82
+ * - `--cobuy-text-color`: Text color
83
+ * - `--cobuy-border-radius`: Border radius value
84
+ * - `--cobuy-font-family`: Font family stack
85
+ * - `--cobuy-animation-duration`: Duration in milliseconds
86
+ * - `--cobuy-animation-easing`: CSS easing function
87
+ * - `--cobuy-animation-transform`: CSS transform for animations
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const container = document.getElementById('cobuy-widget');
92
+ * const theme = {
93
+ * primaryColor: '#4f46e5',
94
+ * secondaryColor: '#6366f1',
95
+ * textColor: '#111827',
96
+ * borderRadius: '8px',
97
+ * fontFamily: 'Inter, sans-serif',
98
+ * animationSpeed: 'normal',
99
+ * animationStyle: 'smooth'
100
+ * };
101
+ *
102
+ * applyTheme(container, theme);
103
+ * // Now all widget styles use the applied theme colors and animations
104
+ * ```
14
105
  */
15
106
  export declare function applyTheme(container: HTMLElement, theme: Required<CoBuyThemeOptions>): void;
16
107
  /**
17
- * Get the default theme (useful for testing and documentation)
108
+ * Get the default theme configuration
109
+ *
110
+ * Returns a copy of the default theme used when no custom theme is provided.
111
+ * Useful for documentation, testing, or as a baseline for customization.
112
+ *
113
+ * @returns {Required<CoBuyThemeOptions>} Default theme with all properties defined
114
+ *
115
+ * @description
116
+ * Default values:
117
+ * - Primary Color: #4f46e5 (Indigo-600)
118
+ * - Secondary Color: #6366f1 (Indigo-500)
119
+ * - Text Color: #111827 (Gray-900)
120
+ * - Border Radius: 8px
121
+ * - Font Family: Inter, system-ui, -apple-system, sans-serif
122
+ * - Animation Speed: normal (300ms)
123
+ * - Animation Style: subtle (fade only)
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * const defaults = getDefaultTheme();
128
+ * console.log(defaults.primaryColor); // #4f46e5
129
+ *
130
+ * // Use default as base and customize
131
+ * const customTheme = {
132
+ * ...getDefaultTheme(),
133
+ * primaryColor: '#ff0000'
134
+ * };
135
+ * ```
18
136
  */
19
137
  export declare function getDefaultTheme(): Required<CoBuyThemeOptions>;
@@ -5,17 +5,16 @@ import { AnalyticsClient } from "../../core/analytics";
5
5
  * WidgetRoot handles rendering of the CoBuy widget into a DOM container
6
6
  */
7
7
  export declare class WidgetRoot {
8
- private logger;
9
- private apiClient;
10
- private analyticsClient;
11
- private config;
12
- private events?;
8
+ private readonly logger;
9
+ private readonly apiClient;
10
+ private readonly analyticsClient;
11
+ private readonly config;
12
+ private readonly events?;
13
13
  private state;
14
14
  private retryCount;
15
- private readonly MAX_RETRIES;
16
15
  private currentProductId;
17
16
  private currentContainer;
18
- private debouncedCTAClick;
17
+ private readonly debouncedCTAClick;
19
18
  private currentGroupData;
20
19
  private groupFulfilled;
21
20
  private frozenReward;
@@ -31,13 +30,25 @@ export declare class WidgetRoot {
31
30
  private groupExpiryRefreshTriggered;
32
31
  private offlineRedemption;
33
32
  private offlineRedemptionModal;
33
+ private isRendering;
34
+ private renderPromise;
35
+ private liveRegionAnnouncer;
36
+ private lastRenderedProductId;
37
+ private lastRenderedContainer;
38
+ private renderDebounceTimer;
39
+ private pendingRenderOptions;
40
+ private readonly RENDER_DEBOUNCE_MS;
41
+ /**
42
+ * Get max retries from config (configurable via performance options)
43
+ */
44
+ private get MAX_RETRIES();
34
45
  constructor(config: InternalConfig, apiClient: ApiClient | null, analyticsClient?: AnalyticsClient | null);
35
46
  /** Subscribe once to backend socket events routed through the host page */
36
47
  private subscribeToSocketEvents;
37
48
  /** Handle backend fulfillment notifications */
38
- private handleGroupFulfilledEvent;
49
+ private readonly handleGroupFulfilledEvent;
39
50
  /** Handle realtime group creation/join events by refreshing group UI */
40
- private handleGroupUpdatedEvent;
51
+ private readonly handleGroupUpdatedEvent;
41
52
  /** Fetch latest group data and re-render containers */
42
53
  private refreshGroupDataFromRealtime;
43
54
  /** Update widget and any external containers after realtime refresh */
@@ -59,10 +70,45 @@ export declare class WidgetRoot {
59
70
  private getGroupListModal;
60
71
  /**
61
72
  * Render the widget into the specified container
73
+ *
74
+ * Asynchronous method that renders the collaborative buying widget.
75
+ * Automatically fetches product data, groups, and set up event listeners.
76
+ * Includes request deduplication to prevent redundant API calls from rapid re-renders
77
+ * (e.g., React component re-rendering).
78
+ *
79
+ * @param {RenderWidgetOptions} options - Widget rendering options
80
+ * @returns {Promise<void>} Rejects if rendering fails
81
+ *
82
+ * @throws {CoBuyRenderError} If container not found or rendering fails
83
+ * @throws {CoBuyValidationError} If productId validation fails
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * try {
88
+ * const widget = new WidgetRoot(config, apiClient, analyticsClient);
89
+ * await widget.render({
90
+ * productId: 'prod_123',
91
+ * container: '#widget-container'
92
+ * });
93
+ * } catch (error) {
94
+ * if (error instanceof CoBuyRenderError) {
95
+ * console.error('Widget render failed:', error.message);
96
+ * }
97
+ * }
98
+ * ```
62
99
  */
63
100
  render(options: RenderWidgetOptions): Promise<void>;
101
+ /**
102
+ * Queued render that handles concurrent render protection
103
+ */
104
+ private doQueuedRender;
105
+ private doRender;
64
106
  /**
65
107
  * Fetch reward data with automatic retry on failure
108
+ *
109
+ * @param productId The product ID to fetch reward for
110
+ * @returns Promise with reward data on success, null on failure
111
+ * @internal State updates (LOADED/ERROR) are handled by the caller
66
112
  */
67
113
  private fetchRewardWithRetry;
68
114
  /**
@@ -97,6 +143,14 @@ export declare class WidgetRoot {
97
143
  * Handle retry button click - reset retry count and re-fetch
98
144
  */
99
145
  private handleRetry;
146
+ /**
147
+ * Get or create a live region announcer for screen reader announcements
148
+ */
149
+ private getOrCreateLiveRegion;
150
+ /**
151
+ * Announce a message to screen readers via live region
152
+ */
153
+ private announceToScreenReaders;
100
154
  private createWidget;
101
155
  /**
102
156
  * Inject base layout styles for responsive widget rendering
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cshah18/sdk",
3
- "version": "4.8.0",
3
+ "version": "4.9.0",
4
4
  "description": "CoBuy Embedded SDK for browser JavaScript integration",
5
5
  "type": "module",
6
6
  "main": "dist/cobuy-sdk.umd.js",
@@ -11,6 +11,7 @@
11
11
  ],
12
12
  "scripts": {
13
13
  "build": "rollup -c",
14
+ "build:analyze": "ANALYZE=true rollup -c && echo '📊 Bundle analysis: open dist/stats.html'",
14
15
  "build:watch": "rollup -c -w",
15
16
  "lint": "eslint \"src/**/*.{ts,tsx}\"",
16
17
  "lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
@@ -29,6 +30,7 @@
29
30
  "author": "CoBuy",
30
31
  "license": "MIT",
31
32
  "dependencies": {
33
+ "@fingerprintjs/botd": "^2.0.0",
32
34
  "socket.io-client": "^4.7.5"
33
35
  },
34
36
  "devDependencies": {
@@ -46,6 +48,7 @@
46
48
  "prettier": "^3.7.4",
47
49
  "rollup": "^4.9.4",
48
50
  "rollup-plugin-postcss": "^4.0.2",
51
+ "rollup-plugin-visualizer": "^5.12.0",
49
52
  "tslib": "^2.6.2",
50
53
  "typescript": "^5.3.3"
51
54
  }