hypercrm 1.0.4 → 1.0.6

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/assets/widget.js CHANGED
@@ -53,8 +53,8 @@
53
53
  const styles = `
54
54
  .hypercrm-widget-container {
55
55
  position: fixed;
56
- bottom: 24px;
57
- right: 24px;
56
+ bottom: calc(24px + var(--hypercrm-offset-bottom, 0px));
57
+ right: calc(24px + var(--hypercrm-offset-side, 0px));
58
58
  z-index: 2147483000;
59
59
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
60
60
  color: var(--hypercrm-text-primary, #111827);
@@ -78,13 +78,15 @@
78
78
  --hypercrm-radius-lg: 20px;
79
79
  --hypercrm-radius-md: 16px;
80
80
  --hypercrm-radius-sm: 12px;
81
+ --hypercrm-offset-bottom: 0px;
82
+ --hypercrm-offset-side: 0px;
81
83
  color-scheme: light;
82
84
  -webkit-font-smoothing: antialiased;
83
85
  }
84
86
 
85
87
  .hypercrm-widget-container.hypercrm-position-left {
86
88
  right: auto;
87
- left: 24px;
89
+ left: calc(24px + var(--hypercrm-offset-side, 0px));
88
90
  }
89
91
 
90
92
  .hypercrm-widget-container.hypercrm-position-left .hypercrm-widget-panel {
@@ -1291,12 +1293,12 @@
1291
1293
 
1292
1294
  @media (max-width: 640px) {
1293
1295
  .hypercrm-widget-container {
1294
- bottom: 16px;
1295
- right: 16px;
1296
+ bottom: calc(16px + var(--hypercrm-offset-bottom, 0px));
1297
+ right: calc(16px + var(--hypercrm-offset-side, 0px));
1296
1298
  }
1297
1299
 
1298
1300
  .hypercrm-widget-container.hypercrm-position-left {
1299
- left: 16px;
1301
+ left: calc(16px + var(--hypercrm-offset-side, 0px));
1300
1302
  right: auto;
1301
1303
  }
1302
1304
 
@@ -1331,6 +1333,7 @@
1331
1333
  this.theme = { ...DEFAULT_THEME, ...(this.options.theme || {}) };
1332
1334
  this.colorModePreference = this.options.colorMode || 'light';
1333
1335
  this.position = this.normalizePosition(this.options.position);
1336
+ this.offset = this.normalizeOffsets(this.options.offset);
1334
1337
  this.mediaColorQuery = null;
1335
1338
  this.systemColorListener = null;
1336
1339
  this.systemColorListenerAttached = false;
@@ -1401,6 +1404,22 @@
1401
1404
  return value === 'left' ? 'left' : 'right';
1402
1405
  }
1403
1406
 
1407
+ normalizeOffsetValue(value) {
1408
+ if (value === null || value === undefined || value === '') return 0;
1409
+ const num = Number(value);
1410
+ return Number.isFinite(num) ? num : 0;
1411
+ }
1412
+
1413
+ normalizeOffsets(value) {
1414
+ if (!value || typeof value !== 'object') {
1415
+ return { bottom: 0, side: 0 };
1416
+ }
1417
+ return {
1418
+ bottom: this.normalizeOffsetValue(value.bottom),
1419
+ side: this.normalizeOffsetValue(value.side),
1420
+ };
1421
+ }
1422
+
1404
1423
  applyPosition() {
1405
1424
  if (!this.container) return;
1406
1425
  const position = this.normalizePosition(this.position || this.options.position);
@@ -1414,6 +1433,19 @@
1414
1433
  this.applyPosition();
1415
1434
  }
1416
1435
 
1436
+ applyOffsets() {
1437
+ if (!this.container) return;
1438
+ const offset = this.offset || { bottom: 0, side: 0 };
1439
+ this.container.style.setProperty('--hypercrm-offset-bottom', `${offset.bottom}px`);
1440
+ this.container.style.setProperty('--hypercrm-offset-side', `${offset.side}px`);
1441
+ }
1442
+
1443
+ setOffset(offset) {
1444
+ this.offset = this.normalizeOffsets(offset);
1445
+ this.options.offset = this.offset;
1446
+ this.applyOffsets();
1447
+ }
1448
+
1417
1449
  absUrl(url) {
1418
1450
  if (!url) return url;
1419
1451
  if (/^https?:/i.test(url)) return url;
@@ -1618,6 +1650,7 @@
1618
1650
  document.body.appendChild(container);
1619
1651
  this.container = container;
1620
1652
  this.applyPosition();
1653
+ this.applyOffsets();
1621
1654
 
1622
1655
  // Lightbox overlay
1623
1656
  const lightbox = document.createElement('div');
@@ -2371,6 +2404,10 @@
2371
2404
  if (!this.options.position && this.orgInfo?.widget?.position) {
2372
2405
  this.setPosition(this.orgInfo.widget.position);
2373
2406
  }
2407
+ const orgOffset = this.orgInfo?.widget?.offset;
2408
+ if (!this.options.offset && orgOffset) {
2409
+ this.setOffset(orgOffset);
2410
+ }
2374
2411
  const iconUrl = this.orgInfo?.widget?.iconUrl;
2375
2412
  this.orgIconUrl = iconUrl ? this.absUrl(iconUrl) : null;
2376
2413
  this.updateHeaderIcons();
@@ -2954,6 +2991,9 @@
2954
2991
  setPosition(position) {
2955
2992
  if (activeWidget) activeWidget.setPosition(position);
2956
2993
  },
2994
+ setOffset(offset) {
2995
+ if (activeWidget) activeWidget.setOffset(offset);
2996
+ },
2957
2997
  open() {
2958
2998
  if (activeWidget) activeWidget.openWidget();
2959
2999
  },
package/dist/index.d.ts CHANGED
@@ -6,6 +6,10 @@ export interface WidgetOptions {
6
6
  theme?: Record<string, string>;
7
7
  colorMode?: 'light' | 'dark' | 'auto';
8
8
  position?: 'left' | 'right';
9
+ offset?: {
10
+ bottom?: number;
11
+ side?: number;
12
+ };
9
13
  autoOpen?: boolean;
10
14
  debug?: boolean;
11
15
  scriptUrl?: string;
@@ -15,12 +19,20 @@ export declare const destroyWidget: () => void;
15
19
  export declare const setWidgetTheme: (theme: Record<string, string>) => Promise<void>;
16
20
  export declare const setWidgetColorMode: (mode: "light" | "dark" | "auto") => Promise<void>;
17
21
  export declare const setWidgetPosition: (position: "left" | "right") => Promise<void>;
22
+ export declare const setWidgetOffset: (offset: {
23
+ bottom?: number;
24
+ side?: number;
25
+ }) => Promise<void>;
18
26
  declare const _default: {
19
27
  init: (options?: WidgetOptions) => Promise<any>;
20
28
  destroy: () => void;
21
29
  setTheme: (theme: Record<string, string>) => Promise<void>;
22
30
  setColorMode: (mode: "light" | "dark" | "auto") => Promise<void>;
23
31
  setPosition: (position: "left" | "right") => Promise<void>;
32
+ setOffset: (offset: {
33
+ bottom?: number;
34
+ side?: number;
35
+ }) => Promise<void>;
24
36
  };
25
37
  export default _default;
26
38
  declare global {
@@ -31,6 +43,10 @@ declare global {
31
43
  setTheme: (theme?: Record<string, string>) => void;
32
44
  setColorMode: (mode: 'light' | 'dark' | 'auto') => void;
33
45
  setPosition: (position: 'left' | 'right') => void;
46
+ setOffset: (offset: {
47
+ bottom?: number;
48
+ side?: number;
49
+ }) => void;
34
50
  open: () => void;
35
51
  close: () => void;
36
52
  toggle: () => void;
package/dist/index.js CHANGED
@@ -95,10 +95,15 @@ export const setWidgetPosition = async (position) => {
95
95
  await ensureScriptLoaded();
96
96
  window.HyperCRMWidget.setPosition(position);
97
97
  };
98
+ export const setWidgetOffset = async (offset) => {
99
+ await ensureScriptLoaded();
100
+ window.HyperCRMWidget.setOffset(offset || {});
101
+ };
98
102
  export default {
99
103
  init: initWidget,
100
104
  destroy: destroyWidget,
101
105
  setTheme: setWidgetTheme,
102
106
  setColorMode: setWidgetColorMode,
103
107
  setPosition: setWidgetPosition,
108
+ setOffset: setWidgetOffset,
104
109
  };
package/dist/react.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { useEffect, useRef } from 'react';
2
- import { initWidget, destroyWidget, setWidgetTheme, setWidgetColorMode, setWidgetPosition, } from './index';
2
+ import { initWidget, destroyWidget, setWidgetTheme, setWidgetColorMode, setWidgetPosition, setWidgetOffset, } from './index';
3
3
  export const useHyperCRMWidget = (options = {}) => {
4
- const { apiUrl, apiKey, orgId, mount, theme, colorMode, position, autoOpen, debug, scriptUrl, } = options;
4
+ const { apiUrl, apiKey, orgId, mount, theme, colorMode, position, offset, autoOpen, debug, scriptUrl, } = options;
5
5
  const readyRef = useRef(false);
6
- const latestRef = useRef({ theme, colorMode, position });
6
+ const latestRef = useRef({ theme, colorMode, position, offset });
7
7
  useEffect(() => {
8
- latestRef.current = { theme, colorMode, position };
9
- }, [theme, colorMode, position]);
8
+ latestRef.current = { theme, colorMode, position, offset };
9
+ }, [theme, colorMode, position, offset]);
10
10
  useEffect(() => {
11
11
  let cancelled = false;
12
12
  readyRef.current = false;
@@ -18,6 +18,7 @@ export const useHyperCRMWidget = (options = {}) => {
18
18
  theme: latestRef.current.theme,
19
19
  colorMode: latestRef.current.colorMode,
20
20
  position: latestRef.current.position,
21
+ offset: latestRef.current.offset,
21
22
  autoOpen,
22
23
  debug,
23
24
  scriptUrl,
@@ -32,6 +33,8 @@ export const useHyperCRMWidget = (options = {}) => {
32
33
  setWidgetColorMode(latest.colorMode);
33
34
  if (latest.position)
34
35
  setWidgetPosition(latest.position);
36
+ if (latest.offset)
37
+ setWidgetOffset(latest.offset);
35
38
  })
36
39
  .catch((err) => {
37
40
  if (debug)
@@ -58,6 +61,11 @@ export const useHyperCRMWidget = (options = {}) => {
58
61
  return;
59
62
  setWidgetPosition(position);
60
63
  }, [position]);
64
+ useEffect(() => {
65
+ if (!readyRef.current || !offset)
66
+ return;
67
+ setWidgetOffset(offset);
68
+ }, [offset]);
61
69
  };
62
70
  export const HyperCRMWidget = (props) => {
63
71
  useHyperCRMWidget(props);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercrm",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "HyperCRM widget loader with optional React component.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",