@beeport/widget 0.1.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.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # @beeport/widget
2
+
3
+ BeePort feedback widget — npm package for programmatic installation.
4
+
5
+ Injects the same CDN-hosted widget as the `<script>` tag installation, but lets you control initialisation from your application code.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @beeport/widget
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### Named imports (recommended — tree-shakeable)
16
+
17
+ ```typescript
18
+ import { init, destroy, open, close } from '@beeport/widget';
19
+
20
+ // Initialise the widget
21
+ init({ project: 'prj_abc123' });
22
+
23
+ // Programmatically open/close the feedback panel
24
+ open();
25
+ close();
26
+
27
+ // Remove all widget elements and reset (allows re-init)
28
+ destroy();
29
+ ```
30
+
31
+ ### Namespace import
32
+
33
+ ```typescript
34
+ import BeeportWidget from '@beeport/widget';
35
+
36
+ BeeportWidget.init({ project: 'prj_abc123' });
37
+ BeeportWidget.open();
38
+ BeeportWidget.close();
39
+ BeeportWidget.destroy();
40
+ ```
41
+
42
+ ### CommonJS
43
+
44
+ ```javascript
45
+ const { init, destroy, open, close } = require('@beeport/widget');
46
+ init({ project: 'prj_abc123' });
47
+ ```
48
+
49
+ ## API
50
+
51
+ ### `init(config)`
52
+
53
+ Loads and initialises the BeePort widget by injecting the CDN script tag into `document.body`.
54
+
55
+ Idempotent — calling `init()` multiple times is safe; subsequent calls are no-ops.
56
+
57
+ **Throws** `Error` if called outside a browser environment (SSR guard).
58
+
59
+ ```typescript
60
+ init({
61
+ project: 'prj_abc123', // Required. Your project key.
62
+ theme: 'auto', // Optional. 'light' | 'dark' | 'auto'. Default: browser default.
63
+ position: 'bottom-right', // Optional. 'bottom-right' | 'bottom-left'. Default: 'bottom-right'.
64
+ accent: '#f3c744', // Optional. CSS colour string. Default: BeePort gold.
65
+ text: 'Feedback', // Optional. Button label. Default: 'Feedback'.
66
+ });
67
+ ```
68
+
69
+ ### `destroy()`
70
+
71
+ Removes all widget DOM elements (script tag, trigger button, iframe card, mobile sheet) and resets the loaded flag so `init()` can be called again.
72
+
73
+ Safe to call before `init()` or in non-browser environments (no-op).
74
+
75
+ ### `open()`
76
+
77
+ Programmatically opens the feedback panel by dispatching a `beeport:open` custom event on `window`.
78
+
79
+ Safe to call in non-browser environments (no-op).
80
+
81
+ ### `close()`
82
+
83
+ Programmatically closes the feedback panel by dispatching a `beeport:close` custom event on `window`.
84
+
85
+ Safe to call in non-browser environments (no-op).
86
+
87
+ ## TypeScript
88
+
89
+ Full TypeScript types are included. The `BeePortConfig` interface is exported for use in your own code:
90
+
91
+ ```typescript
92
+ import { init, type BeePortConfig } from '@beeport/widget';
93
+
94
+ const config: BeePortConfig = {
95
+ project: 'prj_abc123',
96
+ theme: 'dark',
97
+ };
98
+
99
+ init(config);
100
+ ```
101
+
102
+ ## Framework examples
103
+
104
+ ### React
105
+
106
+ ```tsx
107
+ import { useEffect } from 'react';
108
+ import { init, destroy } from '@beeport/widget';
109
+
110
+ export function FeedbackWidget() {
111
+ useEffect(() => {
112
+ init({ project: 'prj_abc123', theme: 'auto' });
113
+ return () => destroy();
114
+ }, []);
115
+
116
+ return null;
117
+ }
118
+ ```
119
+
120
+ ### Vue
121
+
122
+ ```typescript
123
+ import { onMounted, onUnmounted } from 'vue';
124
+ import { init, destroy } from '@beeport/widget';
125
+
126
+ export function useFeedbackWidget(project: string) {
127
+ onMounted(() => init({ project }));
128
+ onUnmounted(() => destroy());
129
+ }
130
+ ```
131
+
132
+ ## SSR
133
+
134
+ The package is SSR-safe. No `window` or `document` access occurs at import time — all browser APIs are only accessed inside function bodies. `init()` throws a descriptive error if called server-side; all other functions are silent no-ops.
135
+
136
+ ## Output formats
137
+
138
+ - **ESM** (`dist/index.js`) — for bundlers and modern environments
139
+ - **CJS** (`dist/index.cjs`) — for Node.js and legacy bundlers
140
+ - **Types** (`dist/index.d.ts`) — TypeScript declarations
141
+
142
+ `sideEffects: false` is set in `package.json` for reliable tree-shaking.
143
+
144
+ ## Script tag alternative
145
+
146
+ If you don't use a bundler, load the widget directly from the CDN:
147
+
148
+ ```html
149
+ <script
150
+ src="https://cdn.beeport.ai/widget.js"
151
+ data-project="prj_abc123"
152
+ data-theme="auto"
153
+ ></script>
154
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ close: () => close,
24
+ default: () => index_default,
25
+ destroy: () => destroy,
26
+ init: () => init,
27
+ open: () => open
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+ var CDN_URL = "https://cdn.beeport.ai/widget.js";
31
+ var SCRIPT_ATTR = "data-beeport-script";
32
+ function init(config) {
33
+ if (typeof window === "undefined") {
34
+ throw new Error("BeePort widget requires a browser environment");
35
+ }
36
+ if (window.__beeport_loaded) return;
37
+ const script = document.createElement("script");
38
+ script.src = CDN_URL;
39
+ script.setAttribute(SCRIPT_ATTR, "true");
40
+ script.setAttribute("data-project", config.project);
41
+ if (config.theme !== void 0) {
42
+ script.setAttribute("data-theme", config.theme);
43
+ }
44
+ if (config.position !== void 0) {
45
+ script.setAttribute("data-position", config.position);
46
+ }
47
+ if (config.accent !== void 0) {
48
+ script.setAttribute("data-accent", config.accent);
49
+ }
50
+ if (config.text !== void 0) {
51
+ script.setAttribute("data-text", config.text);
52
+ }
53
+ document.body.appendChild(script);
54
+ window.__beeport_loaded = true;
55
+ }
56
+ function destroy() {
57
+ if (typeof window === "undefined") return;
58
+ window.dispatchEvent(new CustomEvent("beeport:destroy"));
59
+ document.body.querySelectorAll(`script[${SCRIPT_ATTR}]`).forEach((el) => el.remove());
60
+ document.body.querySelectorAll("[data-beeport-trigger]").forEach((el) => el.remove());
61
+ document.body.querySelectorAll("[data-beeport-card]").forEach((el) => el.remove());
62
+ document.body.querySelectorAll("[data-beeport-sheet]").forEach((el) => el.remove());
63
+ delete window.__beeport_loaded;
64
+ }
65
+ function open() {
66
+ if (typeof window === "undefined") return;
67
+ window.dispatchEvent(new CustomEvent("beeport:open"));
68
+ }
69
+ function close() {
70
+ if (typeof window === "undefined") return;
71
+ window.dispatchEvent(new CustomEvent("beeport:close"));
72
+ }
73
+ var BeeportWidget = { init, destroy, open, close };
74
+ var index_default = BeeportWidget;
75
+ // Annotate the CommonJS export names for ESM import in node:
76
+ 0 && (module.exports = {
77
+ close,
78
+ destroy,
79
+ init,
80
+ open
81
+ });
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @beeport/widget
3
+ *
4
+ * npm package wrapper around the CDN-served BeePort widget.
5
+ *
6
+ * Usage:
7
+ * import { init } from '@beeport/widget';
8
+ * init({ project: 'prj_abc123' });
9
+ *
10
+ * SSR-safe: no window/document access at module import time.
11
+ * All browser APIs are only accessed inside function bodies.
12
+ */
13
+ interface BeePortConfig {
14
+ /** Project API key (required). */
15
+ project: string;
16
+ /** Colour theme forwarded to the widget iframe. */
17
+ theme?: "light" | "dark" | "auto";
18
+ /** Position of the floating button. */
19
+ position?: "bottom-right" | "bottom-left";
20
+ /** Custom accent colour (any CSS colour string). */
21
+ accent?: string;
22
+ /** Custom button label text. */
23
+ text?: string;
24
+ }
25
+ /**
26
+ * Load and initialise the BeePort widget by injecting the CDN script tag.
27
+ *
28
+ * Idempotent — calling init() multiple times is safe; the second call is a
29
+ * no-op if the widget is already loaded.
30
+ *
31
+ * @throws Error if called in a non-browser environment (SSR guard).
32
+ */
33
+ declare function init(config: BeePortConfig): void;
34
+ /**
35
+ * Remove all widget DOM elements and reset the loaded flag.
36
+ *
37
+ * After calling destroy(), init() can be called again to re-initialise.
38
+ * Safe to call before init() or in non-browser environments (no-op).
39
+ */
40
+ declare function destroy(): void;
41
+ /**
42
+ * Programmatically open the feedback widget.
43
+ *
44
+ * Dispatches a `beeport:open` custom event on window. The loaded widget
45
+ * listens for this event and opens the iframe panel.
46
+ *
47
+ * Safe to call in non-browser environments (no-op).
48
+ */
49
+ declare function open(): void;
50
+ /**
51
+ * Programmatically close the feedback widget.
52
+ *
53
+ * Dispatches a `beeport:close` custom event on window. The loaded widget
54
+ * listens for this event and closes the iframe panel.
55
+ *
56
+ * Safe to call in non-browser environments (no-op).
57
+ */
58
+ declare function close(): void;
59
+ /**
60
+ * BeeportWidget namespace — use this for the BeeportWidget.init() call pattern.
61
+ *
62
+ * All methods are identical to the named exports and are tree-shakeable when
63
+ * destructured (e.g. `const { init } = BeeportWidget`).
64
+ */
65
+ declare const BeeportWidget: {
66
+ readonly init: typeof init;
67
+ readonly destroy: typeof destroy;
68
+ readonly open: typeof open;
69
+ readonly close: typeof close;
70
+ };
71
+
72
+ export { type BeePortConfig, close, BeeportWidget as default, destroy, init, open };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @beeport/widget
3
+ *
4
+ * npm package wrapper around the CDN-served BeePort widget.
5
+ *
6
+ * Usage:
7
+ * import { init } from '@beeport/widget';
8
+ * init({ project: 'prj_abc123' });
9
+ *
10
+ * SSR-safe: no window/document access at module import time.
11
+ * All browser APIs are only accessed inside function bodies.
12
+ */
13
+ interface BeePortConfig {
14
+ /** Project API key (required). */
15
+ project: string;
16
+ /** Colour theme forwarded to the widget iframe. */
17
+ theme?: "light" | "dark" | "auto";
18
+ /** Position of the floating button. */
19
+ position?: "bottom-right" | "bottom-left";
20
+ /** Custom accent colour (any CSS colour string). */
21
+ accent?: string;
22
+ /** Custom button label text. */
23
+ text?: string;
24
+ }
25
+ /**
26
+ * Load and initialise the BeePort widget by injecting the CDN script tag.
27
+ *
28
+ * Idempotent — calling init() multiple times is safe; the second call is a
29
+ * no-op if the widget is already loaded.
30
+ *
31
+ * @throws Error if called in a non-browser environment (SSR guard).
32
+ */
33
+ declare function init(config: BeePortConfig): void;
34
+ /**
35
+ * Remove all widget DOM elements and reset the loaded flag.
36
+ *
37
+ * After calling destroy(), init() can be called again to re-initialise.
38
+ * Safe to call before init() or in non-browser environments (no-op).
39
+ */
40
+ declare function destroy(): void;
41
+ /**
42
+ * Programmatically open the feedback widget.
43
+ *
44
+ * Dispatches a `beeport:open` custom event on window. The loaded widget
45
+ * listens for this event and opens the iframe panel.
46
+ *
47
+ * Safe to call in non-browser environments (no-op).
48
+ */
49
+ declare function open(): void;
50
+ /**
51
+ * Programmatically close the feedback widget.
52
+ *
53
+ * Dispatches a `beeport:close` custom event on window. The loaded widget
54
+ * listens for this event and closes the iframe panel.
55
+ *
56
+ * Safe to call in non-browser environments (no-op).
57
+ */
58
+ declare function close(): void;
59
+ /**
60
+ * BeeportWidget namespace — use this for the BeeportWidget.init() call pattern.
61
+ *
62
+ * All methods are identical to the named exports and are tree-shakeable when
63
+ * destructured (e.g. `const { init } = BeeportWidget`).
64
+ */
65
+ declare const BeeportWidget: {
66
+ readonly init: typeof init;
67
+ readonly destroy: typeof destroy;
68
+ readonly open: typeof open;
69
+ readonly close: typeof close;
70
+ };
71
+
72
+ export { type BeePortConfig, close, BeeportWidget as default, destroy, init, open };
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ // src/index.ts
2
+ var CDN_URL = "https://cdn.beeport.ai/widget.js";
3
+ var SCRIPT_ATTR = "data-beeport-script";
4
+ function init(config) {
5
+ if (typeof window === "undefined") {
6
+ throw new Error("BeePort widget requires a browser environment");
7
+ }
8
+ if (window.__beeport_loaded) return;
9
+ const script = document.createElement("script");
10
+ script.src = CDN_URL;
11
+ script.setAttribute(SCRIPT_ATTR, "true");
12
+ script.setAttribute("data-project", config.project);
13
+ if (config.theme !== void 0) {
14
+ script.setAttribute("data-theme", config.theme);
15
+ }
16
+ if (config.position !== void 0) {
17
+ script.setAttribute("data-position", config.position);
18
+ }
19
+ if (config.accent !== void 0) {
20
+ script.setAttribute("data-accent", config.accent);
21
+ }
22
+ if (config.text !== void 0) {
23
+ script.setAttribute("data-text", config.text);
24
+ }
25
+ document.body.appendChild(script);
26
+ window.__beeport_loaded = true;
27
+ }
28
+ function destroy() {
29
+ if (typeof window === "undefined") return;
30
+ window.dispatchEvent(new CustomEvent("beeport:destroy"));
31
+ document.body.querySelectorAll(`script[${SCRIPT_ATTR}]`).forEach((el) => el.remove());
32
+ document.body.querySelectorAll("[data-beeport-trigger]").forEach((el) => el.remove());
33
+ document.body.querySelectorAll("[data-beeport-card]").forEach((el) => el.remove());
34
+ document.body.querySelectorAll("[data-beeport-sheet]").forEach((el) => el.remove());
35
+ delete window.__beeport_loaded;
36
+ }
37
+ function open() {
38
+ if (typeof window === "undefined") return;
39
+ window.dispatchEvent(new CustomEvent("beeport:open"));
40
+ }
41
+ function close() {
42
+ if (typeof window === "undefined") return;
43
+ window.dispatchEvent(new CustomEvent("beeport:close"));
44
+ }
45
+ var BeeportWidget = { init, destroy, open, close };
46
+ var index_default = BeeportWidget;
47
+ export {
48
+ close,
49
+ index_default as default,
50
+ destroy,
51
+ init,
52
+ open
53
+ };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@beeport/widget",
3
+ "version": "0.1.0",
4
+ "description": "BeePort feedback widget — npm package wrapper around CDN widget.js",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "sideEffects": false,
24
+ "scripts": {
25
+ "test": "vitest run",
26
+ "test:watch": "vitest",
27
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
28
+ "prepack": "npm run build"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^22.0.0",
32
+ "jsdom": "^26.0.0",
33
+ "tsup": "^8.0.0",
34
+ "typescript": "^5.7.0",
35
+ "vitest": "^3.0.0"
36
+ },
37
+ "keywords": [
38
+ "beeport",
39
+ "feedback",
40
+ "widget"
41
+ ],
42
+ "license": "UNLICENSED"
43
+ }