@squeletteapp/widget 0.1.0 → 0.3.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 +112 -0
- package/dist/app-BpPatA6a.js +42 -0
- package/dist/index-B0eQqkb_.js +7951 -0
- package/dist/types/app/app.d.ts +15 -0
- package/dist/types/banner/banner-modal.d.ts +15 -0
- package/dist/types/banner/banner.d.ts +14 -0
- package/dist/types/banner/element.d.ts +7 -0
- package/dist/types/banner/index.d.ts +19 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/utils.d.ts +2 -0
- package/dist/types/widget/__tests__/widget.test.d.ts +1 -0
- package/dist/types/widget/components/widget-shell.d.ts +8 -0
- package/dist/types/widget/constants.d.ts +9 -0
- package/dist/types/widget/core/custom-element.d.ts +142 -0
- package/dist/types/widget/core/global-api.d.ts +97 -0
- package/dist/types/widget/core/identity.d.ts +73 -0
- package/dist/types/widget/core/panel-dimensions.d.ts +36 -0
- package/dist/types/widget/core/positioning.d.ts +63 -0
- package/dist/types/widget/core/scroll-lock.d.ts +28 -0
- package/dist/types/widget/element.d.ts +90 -0
- package/dist/types/widget/events.d.ts +13 -0
- package/dist/types/widget/factories.d.ts +41 -0
- package/dist/types/widget/styles.d.ts +8 -0
- package/dist/types/widget/types.d.ts +79 -0
- package/dist/types/widget/utils.d.ts +12 -0
- package/dist/widget.es.js +14 -0
- package/dist/widget.js +168 -15
- package/package.json +32 -18
- package/dist/button-component.d.ts +0 -2
- package/dist/button-component.js +0 -158
- package/dist/index.d.ts +0 -26
- package/dist/index.js +0 -230
- package/dist/styles.css +0 -567
- package/dist/widget.d.ts +0 -42
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Squelette Widget
|
|
2
|
+
|
|
3
|
+
Embeddable feedback & roadmap widget built with Preact and delivered as a Web Component. It mounts as `<squelette-widget>` with an isolated Shadow DOM, lazy-loads the interactive app on demand, and streams feedback from `https://api.squelette.app` using your project credentials.
|
|
4
|
+
|
|
5
|
+
## CDN usage
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<script src="https://cdn.squelette.app/widget.js" async></script>
|
|
9
|
+
<script>
|
|
10
|
+
const widget = document.createElement('squelette-widget');
|
|
11
|
+
widget.setAttribute('project', 'squelette');
|
|
12
|
+
widget.setAttribute('board', 'feature-requests');
|
|
13
|
+
document.body.appendChild(widget);
|
|
14
|
+
</script>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Programmatic helper:
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<script src="https://cdn.squelette.app/widget.js" async></script>
|
|
21
|
+
<script>
|
|
22
|
+
window.SqueletteWidget?.create({
|
|
23
|
+
project: 'squelette',
|
|
24
|
+
board: 'feature-requests',
|
|
25
|
+
theme: 'auto',
|
|
26
|
+
locale: 'en',
|
|
27
|
+
label: 'Share feedback'
|
|
28
|
+
});
|
|
29
|
+
</script>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Attributes & options
|
|
33
|
+
|
|
34
|
+
| Name | Type | Default | Description |
|
|
35
|
+
| ----------- | ------------- | ------- | ----------- |
|
|
36
|
+
| `project` | string | – | **Required.** Identifies the project in the Squelette API. |
|
|
37
|
+
| `board` | string | `null` | Optional board/roadmap identifier. |
|
|
38
|
+
| `theme` | `light\|dark\|auto` | `auto` | Controls light/dark appearance. `auto` tracks system preference. |
|
|
39
|
+
| `locale` | string | `en` | Locale forwarded to the iframe (`?locale=`). |
|
|
40
|
+
| `token` | string | – | Optional bearer token used when requesting the embedded experience. |
|
|
41
|
+
| `signature` | string | – | Optional request signature for API verification. |
|
|
42
|
+
| `label` | string | `Feedback` | Launcher button label. |
|
|
43
|
+
| `open` | boolean attr | `false` | When present, forces the widget open. |
|
|
44
|
+
|
|
45
|
+
### Public methods
|
|
46
|
+
|
|
47
|
+
Every widget instance exposes an imperative API:
|
|
48
|
+
|
|
49
|
+
- `open()` / `close()` / `toggle()`
|
|
50
|
+
- `destroy()` – unmounts the application and removes the element.
|
|
51
|
+
- `on(event, handler)` – subscribe to `open`, `close`, or `submit` events. Returns an unsubscribe function.
|
|
52
|
+
|
|
53
|
+
Submit events are forwarded when the embedded iframe posts `window.parent.postMessage({ type: 'squelette:submit', payload }, '*')`.
|
|
54
|
+
|
|
55
|
+
### Theming
|
|
56
|
+
|
|
57
|
+
Hosts can override CSS custom properties directly on the element:
|
|
58
|
+
|
|
59
|
+
```css
|
|
60
|
+
squelette-widget {
|
|
61
|
+
--sq-accent: #ff6b00;
|
|
62
|
+
--sq-bg: #11131f;
|
|
63
|
+
--sq-fg: #f8fafc;
|
|
64
|
+
--sq-border: rgba(15, 23, 42, 0.24);
|
|
65
|
+
--sq-radius: 18px;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
These cascade into the Shadow DOM so host styles never leak inside.
|
|
70
|
+
|
|
71
|
+
## Development
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bun install
|
|
75
|
+
cd packages/widget
|
|
76
|
+
bun run dev # Vite dev server with auto registration
|
|
77
|
+
bun run build # tsc declarations + Vite library build
|
|
78
|
+
bun run test # Vitest (happy-dom)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The Vite build emits `dist/widget.js` (IIFE, ready for `<script>` tags) and `dist/widget.es.js` (ESM) plus type declarations under `dist/types`.
|
|
82
|
+
|
|
83
|
+
### Architecture
|
|
84
|
+
|
|
85
|
+
- `src/widget/element.tsx` – custom element class, orchestrates Shadow DOM lifecycle.
|
|
86
|
+
- `src/widget/components/widget-shell.tsx` – Preact UI for the launcher/panel/loader.
|
|
87
|
+
- `src/widget/styles.ts` – shared base styles injected via constructable stylesheets.
|
|
88
|
+
- `src/widget/utils.ts` – helpers for attribute reflection, iframe URL shaping, theming.
|
|
89
|
+
- `src/app/app.tsx` – lazy-loaded iframe renderer that animates on first paint.
|
|
90
|
+
|
|
91
|
+
## Event bridge & identity
|
|
92
|
+
|
|
93
|
+
Dispatch an identity update from the host page to enrich the embedded experience:
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
window.dispatchEvent(
|
|
97
|
+
new CustomEvent('squelette:identity', {
|
|
98
|
+
detail: {
|
|
99
|
+
userId: '123',
|
|
100
|
+
email: 'person@squelette.app',
|
|
101
|
+
name: 'Ada Lovelace'
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Inside the iframe, send `postMessage({ type: 'squelette:submit', payload })` to bubble successful submissions back to the host application.
|
|
108
|
+
|
|
109
|
+
## Security notes
|
|
110
|
+
|
|
111
|
+
- All network calls are constrained to `https://api.squelette.app` via the iframe `src` URL. No arbitrary HTML injection is allowed.
|
|
112
|
+
- The iframe runs in a restrictive sandbox (`allow-scripts`, `allow-same-origin`, `allow-forms`, and related capabilities expressly required for the widget). Host tokens can be passed via element attributes.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { s as n, t as m, A as c, y as l, u as d } from "./index-B0eQqkb_.js";
|
|
2
|
+
var p = "/Users/guillaume/projects/packages/widget/src/app/app.tsx";
|
|
3
|
+
function u({
|
|
4
|
+
src: i,
|
|
5
|
+
title: o,
|
|
6
|
+
onLoaded: s,
|
|
7
|
+
onClose: r
|
|
8
|
+
}) {
|
|
9
|
+
const t = m(c(null), "frameRef");
|
|
10
|
+
return l(() => {
|
|
11
|
+
const e = t.current;
|
|
12
|
+
if (!e) return;
|
|
13
|
+
const a = () => {
|
|
14
|
+
e.dataset.ready = "true", s == null || s();
|
|
15
|
+
};
|
|
16
|
+
return e.addEventListener("load", a), () => e.removeEventListener("load", a);
|
|
17
|
+
}, [s]), l(() => {
|
|
18
|
+
const e = (a) => {
|
|
19
|
+
console.log("WidgetFrame received message:", a.data), a.data.type === "close-feedback-widget" && (console.log("WidgetFrame closing widget as requested"), r());
|
|
20
|
+
};
|
|
21
|
+
return window.addEventListener("message", e), () => window.removeEventListener("message", e);
|
|
22
|
+
}, [r]), d("iframe", {
|
|
23
|
+
ref: t,
|
|
24
|
+
class: "sq-frame",
|
|
25
|
+
part: "frame",
|
|
26
|
+
src: i,
|
|
27
|
+
title: o,
|
|
28
|
+
loading: "eager",
|
|
29
|
+
allow: "clipboard-write; clipboard-read; fullscreen;",
|
|
30
|
+
sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
|
|
31
|
+
}, void 0, !1, {
|
|
32
|
+
fileName: p,
|
|
33
|
+
lineNumber: 55,
|
|
34
|
+
columnNumber: 5
|
|
35
|
+
}, this);
|
|
36
|
+
}
|
|
37
|
+
const g = n;
|
|
38
|
+
export {
|
|
39
|
+
u as WidgetFrame,
|
|
40
|
+
u as default,
|
|
41
|
+
g as stylesText
|
|
42
|
+
};
|