@framv/image 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/dist/cdn.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import "./element.js";
2
+ export { FramvImageElement } from "./element.js";
3
+ //# sourceMappingURL=cdn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdn.d.ts","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
package/dist/cdn.js ADDED
@@ -0,0 +1,3 @@
1
+ import "./element.js";
2
+ export { FramvImageElement } from "./element.js";
3
+ //# sourceMappingURL=cdn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdn.js","sourceRoot":"","sources":["../src/cdn.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `<framv-image>` — renders HTML/SVG content to a static image.
3
+ *
4
+ * Attributes:
5
+ * width — output width in pixels (default: 800)
6
+ * height — output height in pixels (default: 600)
7
+ * format — png, jpg, webp, svg (default: png)
8
+ * quality — export quality 0–1 (default: 0.95, jpg/webp only)
9
+ *
10
+ * @example
11
+ * ```html
12
+ * <framv-image width="800" height="600" format="png">
13
+ * <div>Your content here</div>
14
+ * </framv-image>
15
+ * ```
16
+ */
17
+ export declare class FramvImageElement extends HTMLElement {
18
+ static observedAttributes: string[];
19
+ private _stage;
20
+ private _exportBtn;
21
+ private _shadow;
22
+ private _exporting;
23
+ constructor();
24
+ get width(): number;
25
+ get height(): number;
26
+ get format(): string;
27
+ get quality(): number;
28
+ connectedCallback(): void;
29
+ attributeChangedCallback(name: string): void;
30
+ private _adaptSize;
31
+ private _export;
32
+ }
33
+ //# sourceMappingURL=element.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AA8CA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,MAAM,CAAC,kBAAkB,WAAc;IAEvC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,UAAU,CAAS;;IAO3B,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,MAAM,IAAI,MAAM,CAEnB;IACD,IAAI,MAAM,IAAI,MAAM,CAEnB;IACD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,iBAAiB,IAAI,IAAI;IAyBzB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ5C,OAAO,CAAC,UAAU;YASJ,OAAO;CAqCtB"}
@@ -0,0 +1,160 @@
1
+ import { exportElement } from "@framv/core";
2
+ const STYLES = `
3
+ :host {
4
+ display: block;
5
+ position: relative;
6
+ background: #f5f5f5;
7
+ border-radius: 8px;
8
+ overflow: hidden;
9
+ font-family: system-ui, sans-serif;
10
+ }
11
+ .framv-image-stage {
12
+ position: relative;
13
+ width: var(--framv-iw, 800px);
14
+ height: var(--framv-ih, 600px);
15
+ transform-origin: top left;
16
+ overflow: hidden;
17
+ }
18
+ .framv-image-toolbar {
19
+ display: flex; align-items: center; justify-content: center; gap: 8px;
20
+ padding: 8px 12px;
21
+ background: rgba(0,0,0,0.7);
22
+ color: #fff; font: 12px system-ui;
23
+ position: absolute; bottom: 0; left: 0; right: 0;
24
+ opacity: 0; transition: opacity 0.2s;
25
+ z-index: 10;
26
+ }
27
+ :host(:hover) .framv-image-toolbar { opacity: 1; }
28
+ .framv-image-toolbar button {
29
+ background: none; border: 1px solid rgba(255,255,255,0.2);
30
+ color: inherit; cursor: pointer;
31
+ padding: 4px 10px; font: inherit; border-radius: 4px;
32
+ }
33
+ .framv-image-toolbar button:hover { background: rgba(255,255,255,0.15); }
34
+ .framv-image-toolbar .btn-export {
35
+ border-color: #ff79c6; color: #ff79c6;
36
+ }
37
+ .framv-image-badge {
38
+ position: absolute; top: 8px; right: 8px;
39
+ background: rgba(0,0,0,0.6); color: #fff;
40
+ padding: 2px 8px; border-radius: 4px;
41
+ font: 11px system-ui; letter-spacing: 0.5px;
42
+ text-transform: uppercase; z-index: 5;
43
+ }
44
+ `;
45
+ /**
46
+ * `<framv-image>` — renders HTML/SVG content to a static image.
47
+ *
48
+ * Attributes:
49
+ * width — output width in pixels (default: 800)
50
+ * height — output height in pixels (default: 600)
51
+ * format — png, jpg, webp, svg (default: png)
52
+ * quality — export quality 0–1 (default: 0.95, jpg/webp only)
53
+ *
54
+ * @example
55
+ * ```html
56
+ * <framv-image width="800" height="600" format="png">
57
+ * <div>Your content here</div>
58
+ * </framv-image>
59
+ * ```
60
+ */
61
+ export class FramvImageElement extends HTMLElement {
62
+ static observedAttributes = ["format"];
63
+ _stage;
64
+ _exportBtn;
65
+ _shadow;
66
+ _exporting = false;
67
+ constructor() {
68
+ super();
69
+ this._shadow = this.attachShadow({ mode: "open" });
70
+ }
71
+ get width() {
72
+ return parseInt(this.getAttribute("width") ?? "800");
73
+ }
74
+ get height() {
75
+ return parseInt(this.getAttribute("height") ?? "600");
76
+ }
77
+ get format() {
78
+ return this.getAttribute("format") ?? "png";
79
+ }
80
+ get quality() {
81
+ return parseFloat(this.getAttribute("quality") ?? "0.95");
82
+ }
83
+ connectedCallback() {
84
+ const w = this.width;
85
+ const h = this.height;
86
+ this._shadow.innerHTML = `
87
+ <style>${STYLES}</style>
88
+ <div class="framv-image-badge">framv image · ${this.format.toUpperCase()} · ${w}x${h}</div>
89
+ <div class="framv-image-stage" style="--framv-iw:${w}px;--framv-ih:${h}px">
90
+ <slot></slot>
91
+ </div>
92
+ <div class="framv-image-toolbar">
93
+ <span style="opacity:0.6;font-size:11px">${w}x${h}</span>
94
+ <button class="btn-export">⬇ Export ${this.format.toUpperCase()}</button>
95
+ </div>
96
+ `;
97
+ this._stage = this._shadow.querySelector(".framv-image-stage");
98
+ this._exportBtn = this._shadow.querySelector(".btn-export");
99
+ this._adaptSize();
100
+ this._exportBtn.addEventListener("click", () => this._export());
101
+ new ResizeObserver(() => this._adaptSize()).observe(this);
102
+ }
103
+ attributeChangedCallback(name) {
104
+ if (name === "format" && this._stage) {
105
+ const badge = this._shadow.querySelector(".framv-image-badge");
106
+ if (badge)
107
+ badge.textContent = `framv image · ${this.format.toUpperCase()} · ${this.width}x${this.height}`;
108
+ this._exportBtn.textContent = `⬇ Export ${this.format.toUpperCase()}`;
109
+ }
110
+ }
111
+ _adaptSize() {
112
+ const w = this.width;
113
+ const h = this.height;
114
+ const containerW = this.clientWidth || w;
115
+ const scale = Math.min(containerW / w, 1);
116
+ this._stage.style.transform = `scale(${scale})`;
117
+ this.style.minHeight = `${h * scale}px`;
118
+ }
119
+ async _export() {
120
+ if (this._exporting)
121
+ return;
122
+ this._exporting = true;
123
+ const container = document.createElement("div");
124
+ container.style.width = `${this.width}px`;
125
+ container.style.height = `${this.height}px`;
126
+ container.style.position = "relative";
127
+ container.style.overflow = "hidden";
128
+ Array.from(this.children).forEach((child) => container.appendChild(child.cloneNode(true)));
129
+ try {
130
+ const blob = await exportElement({
131
+ element: container,
132
+ settings: {
133
+ format: this.format,
134
+ width: this.width,
135
+ height: this.height,
136
+ quality: this.quality,
137
+ time: 0,
138
+ },
139
+ });
140
+ const url = URL.createObjectURL(blob);
141
+ const a = document.createElement("a");
142
+ a.href = url;
143
+ a.download = `framv-image.${this.format}`;
144
+ this._shadow.appendChild(a);
145
+ a.click();
146
+ a.remove();
147
+ URL.revokeObjectURL(url);
148
+ }
149
+ catch (err) {
150
+ console.error("Export failed:", err);
151
+ }
152
+ finally {
153
+ this._exporting = false;
154
+ }
155
+ }
156
+ }
157
+ if (!customElements.get("framv-image")) {
158
+ customElements.define("framv-image", FramvImageElement);
159
+ }
160
+ //# sourceMappingURL=element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { FramvImageElement } from "./element.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { FramvImageElement } from "./element.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@framv/image",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "Image export component for framv — render HTML/SVG to PNG, JPG, WebP, SVG as a declarative custom element",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -b && npm run bundle",
21
+ "prepublishOnly": "npm run build",
22
+ "bundle": "esbuild src/index.ts --bundle --format=esm --external:@framv/core --outfile=dist/bundle.esm.js && esbuild src/cdn.ts --bundle --format=iife --global-name=FramvImage --outfile=dist/bundle.iife.js"
23
+ },
24
+ "dependencies": {
25
+ "@framv/core": "*"
26
+ },
27
+ "devDependencies": {
28
+ "esbuild": "^0.27.2",
29
+ "typescript": "^5.9.3"
30
+ },
31
+ "author": "Mens Reversa",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/mensreversa/framv.git",
36
+ "directory": "packages/image"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/mensreversa/framv/issues"
40
+ }
41
+ }